* add support for reading the UID via getsockopt from unix domain socket conneciotns...
authorWilfried Göesgens <willi@citadel.org>
Sun, 21 Jun 2009 21:14:56 +0000 (21:14 +0000)
committerWilfried Göesgens <willi@citadel.org>
Sun, 21 Jun 2009 21:14:56 +0000 (21:14 +0000)
* 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.

citadel/bootstrap
citadel/citserver.c
citadel/configure.ac
citadel/m4/ucread.m4 [new file with mode: 0644]
citadel/modules/smtp/serv_smtp.c
citadel/server.h
citadel/sysdep.c

index 61a7e80888d19f369e7d128d83ee4a542e4fba95..d14671ffd93db598810cb94819ad41e962235d15 100755 (executable)
@@ -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
index 063c229f8ef40f55554e201cdf6ee860e53e4a2c..3530e848ab6b10722ada2f734c5845f3256530d6 100644 (file)
@@ -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;
index bde22474dac957eb432dbbfb8e53a377b6e00dd8..9fd195b0f8cafd8c5997c99a455b841b6a4d07e8 100644 (file)
@@ -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 (file)
index 0000000..09ac70f
--- /dev/null
@@ -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 <max@duempel.org>
+
+AC_DEFUN([STRUCT_UCRED],[
+       AC_MSG_CHECKING([for struct ucred])
+       AC_CACHE_VAL(mpd_cv_have_struct_ucred, [
+               AC_TRY_COMPILE([#include <sys/socket.h>],
+                       [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 <sys/socket.h>],
+                               [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
index a5d64f0a5e22463150deee7536fdadb6acb87315..896944de61399f87ffa106e0ac4ee042ca76436e 100644 (file)
@@ -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");
index d78f61907837fedc9c3ad611f66261698ea266c6..a926a3c14c05c18b9f8a3a0435a044956ead4933 100644 (file)
@@ -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 */
index bf39a3177224725e3fdb4ca1c39f1cdf073d58cf..90b5e4517f2ce34860b8e9fd57994238627b894e 100644 (file)
@@ -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);
 }