From: Wilfried Göesgens Date: Sun, 21 Jun 2009 21:14:56 +0000 (+0000) Subject: * add support for reading the UID via getsockopt from unix domain socket conneciotns... X-Git-Tag: v7.86~1021 X-Git-Url: https://code.citadel.org/?p=citadel.git;a=commitdiff_plain;h=9d04a04a45ac67c1747e784de135afb977b03dd2 * add support for reading the UID via getsockopt from unix domain socket conneciotns in begin_session() * use the UID like bzed suggested in debian Bug#528760 when sending mails via LMTP * add configure options to detect ucread; borowed from http://git.musicpd.org/cgit/master/mpd.git/plain/m4/ucred.m4; thanks to Max Kellermann to point me there. a further good read is http://www.wsinnovations.com/softeng/articles/uds.html ; it indicates that this might not be portable to *bsd / Solaris; configure should protect us from problems here though. --- diff --git a/citadel/bootstrap b/citadel/bootstrap index 61a7e8088..d14671ffd 100755 --- a/citadel/bootstrap +++ b/citadel/bootstrap @@ -9,7 +9,7 @@ rm -f .libs modules *.so *.lo *.la 2>/dev/null echo ... running aclocal ... -aclocal +aclocal -I m4 echo ... running autoconf ... autoconf diff --git a/citadel/citserver.c b/citadel/citserver.c index 063c229f8..3530e848a 100644 --- a/citadel/citserver.c +++ b/citadel/citserver.c @@ -966,6 +966,7 @@ void begin_session(struct CitContext *con) generate_nonce(con); safestrncpy(con->cs_host, config.c_fqdn, sizeof con->cs_host); safestrncpy(con->cs_addr, "", sizeof con->cs_addr); + con->cs_UDSclientUID = -1; con->cs_host[sizeof con->cs_host - 1] = 0; len = sizeof sin; if (!CC->is_local_socket) { @@ -978,6 +979,34 @@ void begin_session(struct CitContext *con) } else { strcpy(con->cs_host, ""); +#ifdef HAVE_STRUCT_UCRED + { + /* as http://www.wsinnovations.com/softeng/articles/uds.html told us... */ + struct ucred credentials; + int ucred_length = sizeof(struct ucred); + + /*fill in the user data structure */ + if(getsockopt(con->client_socket, SOL_SOCKET, SO_PEERCRED, &credentials, &ucred_length)) { + CtdlLogPrintf(CTDL_NOTICE, "could obtain credentials from unix domain socket"); + + } + else { + /* the process ID of the process on the other side of the socket */ + /* credentials.pid; */ + + /* the effective UID of the process on the other side of the socket */ + con->cs_UDSclientUID = credentials.uid; + + /* the effective primary GID of the process on the other side of the socket */ + /* credentials.gid; */ + + /* To get supplemental groups, we will have to look them up in our account + database, after a reverse lookup on the UID to get the account name. + We can take this opportunity to check to see if this is a legit account. + */ + } + } +#endif } con->cs_flags = 0; con->upload_type = UPL_FILE; diff --git a/citadel/configure.ac b/citadel/configure.ac index bde22474d..9fd195b0f 100644 --- a/citadel/configure.ac +++ b/citadel/configure.ac @@ -4,6 +4,8 @@ AC_PREREQ(2.52) AC_INIT([Citadel], [7.60], [http://www.citadel.org/]) AC_REVISION([$Revision: 5108 $]) AC_CONFIG_SRCDIR([citserver.c]) +AC_CONFIG_HEADER(sysdep.h) +AC_CONFIG_MACRO_DIR([m4]) AC_PREFIX_DEFAULT(/usr/local/citadel) if test "$prefix" = NONE; then AC_DEFINE_UNQUOTED(CTDLDIR, "$ac_default_prefix", [define this to the Citadel home directory]) @@ -975,6 +977,11 @@ AC_CACHE_CHECK([under the bed], ac_cv_under_the_bed, [ esac ]) + +STRUCT_UCRED + + + dnl Done! Now write the Makefile and sysdep.h AC_SUBST(AUTH) AC_SUBST(RESOLV) @@ -984,7 +991,6 @@ AC_SUBST(DATABASE) AC_SUBST(SERVER_LDFLAGS) AC_SUBST(SERVER_LIBS) AC_SUBST(SETUP_LIBS) -AC_CONFIG_HEADER(sysdep.h) ./mk_module_init.sh AC_CONFIG_FILES([Makefile]) AC_OUTPUT(database_cleanup.sh) diff --git a/citadel/m4/ucread.m4 b/citadel/m4/ucread.m4 new file mode 100644 index 000000000..09ac70fcd --- /dev/null +++ b/citadel/m4/ucread.m4 @@ -0,0 +1,33 @@ +# Check if "struct ucred" is available. If not, try harder with +# _GNU_SOURCE. +# +# heavily inspired by: http://git.musicpd.org/cgit/master/mpd.git/tree/m4/ucred.m4 +# Author: Max Kellermann + +AC_DEFUN([STRUCT_UCRED],[ + AC_MSG_CHECKING([for struct ucred]) + AC_CACHE_VAL(mpd_cv_have_struct_ucred, [ + AC_TRY_COMPILE([#include ], + [struct ucred cred;], + mpd_cv_have_struct_ucred=yes, + mpd_cv_have_struct_ucred=no) + if test x$mpd_cv_have_struct_ucred = xno; then + # glibc 2.8 forces _GNU_SOURCE on us + AC_TRY_COMPILE( + [#define _GNU_SOURCE + #include ], + [struct ucred cred;], + mpd_cv_have_struct_ucred=yes, + mpd_cv_have_struct_ucred=no) + if test x$mpd_cv_have_struct_ucred = xyes; then + # :( + MPD_CFLAGS="$MPD_CFLAGS -D_GNU_SOURCE" + fi + fi + ]) + + AC_MSG_RESULT($mpd_cv_have_struct_ucred) + if test x$mpd_cv_have_struct_ucred = xyes; then + AC_DEFINE(HAVE_STRUCT_UCRED, 1, [Define if struct ucred is present from sys/socket.h]) + fi +]) \ No newline at end of file diff --git a/citadel/modules/smtp/serv_smtp.c b/citadel/modules/smtp/serv_smtp.c index a5d64f0a5..896944de6 100644 --- a/citadel/modules/smtp/serv_smtp.c +++ b/citadel/modules/smtp/serv_smtp.c @@ -659,15 +659,27 @@ void smtp_data(void) { datestring(nowstamp, sizeof nowstamp, time(NULL), DATESTRING_RFC822); body = malloc(4096); - if (body != NULL) snprintf(body, 4096, - "Received: from %s (%s [%s])\n" - " by %s; %s\n", - SMTP->helo_node, - CC->cs_host, - CC->cs_addr, - config.c_fqdn, - nowstamp); - + if (body != NULL) { + if (SMTP->is_lmtp && (CC->cs_UDSclientUID != -1)) { + snprintf(body, 4096, + "Received: from %s (Citadel from userid %ld)\n" + " by %s; %s\n", + SMTP->helo_node, + CC->cs_UDSclientUID, + config.c_fqdn, + nowstamp); + } + else { + snprintf(body, 4096, + "Received: from %s (%s [%s])\n" + " by %s; %s\n", + SMTP->helo_node, + CC->cs_host, + CC->cs_addr, + config.c_fqdn, + nowstamp); + } + } body = CtdlReadMessageBody(".", config.c_maxmsglen, body, 1, 0); if (body == NULL) { cprintf("550 Unable to save message: internal error.\r\n"); diff --git a/citadel/server.h b/citadel/server.h index d78f61907..a926a3c14 100644 --- a/citadel/server.h +++ b/citadel/server.h @@ -91,6 +91,7 @@ struct CitContext { int cs_clientdev; /* client developer ID */ int cs_clienttyp; /* client type code */ int cs_clientver; /* client version number */ + uid_t cs_UDSclientUID; /* the uid of the client when talking via UDS */ char cs_clientname[32]; /* name of client software */ char cs_host[64]; /* host logged in from */ char cs_addr[64]; /* address logged in from */ diff --git a/citadel/sysdep.c b/citadel/sysdep.c index bf39a3177..90b5e4517 100644 --- a/citadel/sysdep.c +++ b/citadel/sysdep.c @@ -375,6 +375,9 @@ int ig_uds_server(char *sockpath, int queue_len, char **errormessage) int s; int i; int actual_queue_len; +#ifdef HAVE_STRUCT_UCRED + int passcred = 1; +#endif actual_queue_len = queue_len; if (actual_queue_len < 5) actual_queue_len = 5; @@ -431,6 +434,10 @@ int ig_uds_server(char *sockpath, int queue_len, char **errormessage) return(-1); } +#ifdef HAVE_STRUCT_UCRED + setsockopt(s, SOL_SOCKET, SO_PASSCRED, &passcred, sizeof(passcred)); +#endif + chmod(sockpath, S_ISGID|S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH); return(s); }