PREAUTH ?

Ken Murchison ken at oceana.com
Tue Sep 28 14:16:14 EDT 2004


Christiaan den Besten wrote:
>> Cyrus doesn't support running imapd from the command line.  All 
>> process are spawned from the master process.
>>
>> What type of application requires you to run imapd from the command 
>> line? I *might* be able to add a command line switch which allows you 
>> to do this if its of general use.
> 
> 
> We have aprox 300 users who have shell access on the same machine as 
> where the cyrus process runs. It would be -very- nice if they wouldn't 
> have to enter their username/password whenever they run Pine.
> 
> Pine supports pre-start commands: "ssh-command=/usr/sbin/imapd" is what 
> we now use with uw-imapd. They can then access their mail folder without 
> having to authenticate themselves.

Attached is a quick proof-of-concept patch against the current CVS 
(2.2.x) which allows the services to be run outside of master and 
implements PREAUTH for imapd and allows EXTERNAL to be used for pop3d 
and nntpd.  In order for the services to be run from the command line, 
they MUST be setuid 'cyrus'.

If people find this useful (I still think this is questionable), I can 
clean it up and commit it to CVS.  I don't know whether the methods I'm 
using to detect that the process is running outside of master and that 
the client is connected on stdio are foolproof, but they were quick to 
implement without too much thought (and didn't require a new command 
line option).

-- 
Kenneth Murchison     Oceana Matrix Ltd.
Software Engineer     21 Princeton Place
716-662-8973 x26      Orchard Park, NY 14127
--PGP Public Key--    http://www.oceana.com/~ken/ksm.pgp
-------------- next part --------------
? myconfig
? nobody.patch
? preauth.patch
? doc/internal/master-state-machine.png
? imtest/imtest.c.unix_socket
? sieve/foo.bc
? sieve/foo.s
? sieve/ken.bc
? sieve/ken.script
? sieve/test.bc
? sieve/test.msg
? sieve/test.script
Index: imap/imapd.c
===================================================================
RCS file: /afs/andrew/system/cvs/src/cyrus/imap/imapd.c,v
retrieving revision 1.485
diff -u -r1.485 imapd.c
--- imap/imapd.c	16 Sep 2004 17:58:53 -0000	1.485
+++ imap/imapd.c	28 Sep 2004 18:06:51 -0000
@@ -60,6 +60,7 @@
 #include <sys/wait.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <pwd.h>
 
 #include <sasl/sasl.h>
 
@@ -511,6 +512,35 @@
     imapd_exists = -1;
 }
 
+static void imapd_preauth()
+{
+    uid_t uid = getuid();
+    struct passwd *pw = getpwuid(uid);
+    int r;
+
+    imapd_userid = xstrdup(pw->pw_name);
+    imapd_authstate = auth_newstate(imapd_userid);
+    imapd_userisadmin = global_authisa(imapd_authstate, IMAPOPT_ADMINS);
+
+    syslog(LOG_NOTICE, "login: %s %s preauthenticated",
+	   imapd_clienthost, imapd_userid);
+
+    /* Create telemetry log */
+    imapd_logfd = telemetry_log(imapd_userid, imapd_in, imapd_out, 0);
+
+    /* Set namespace */
+    if ((r = mboxname_init_namespace(&imapd_namespace,
+				     imapd_userisadmin || imapd_userisproxyadmin)) != 0) {
+	syslog(LOG_ERR, error_message(r));
+	fatal(error_message(r), EC_CONFIG);
+    }
+
+    /* Translate any separators in userid */
+    mboxname_hiersep_tointernal(&imapd_namespace, imapd_userid,
+				config_virtdomains ?
+				strcspn(imapd_userid, "@") : 0);
+}
+
 /*
  * run once when process is forked;
  * MUST NOT exit directly; must return with non-zero error code
@@ -644,6 +674,11 @@
 	    }
 	}
     }
+    else if (errno == ENOTSOCK) {
+	/* connected via stdio, preauth as real uid */
+
+	imapd_preauth();
+    }
 
     /* create the SASL connection */
     if (sasl_server_new("imap", config_servername, 
@@ -812,9 +847,16 @@
     char *p, shut[1024];
     const char *err;
 
-    prot_printf(imapd_out,
-		"* OK %s Cyrus IMAP4 %s server ready\r\n", config_servername,
-		CYRUS_VERSION);
+    if (imapd_userid) {
+	prot_printf(imapd_out,
+		    "* PREAUTH %s Cyrus IMAP4 %s server logged in as %s\r\n",
+		    config_servername, CYRUS_VERSION, imapd_userid);
+    }
+    else {
+	prot_printf(imapd_out,
+		    "* OK %s Cyrus IMAP4 %s server ready\r\n",
+		    config_servername, CYRUS_VERSION);
+    }
 
     ret = snprintf(motdfilename, sizeof(motdfilename), "%s/msg/motd",
 		   config_dir);
Index: imap/nntpd.c
===================================================================
RCS file: /afs/andrew/system/cvs/src/cyrus/imap/nntpd.c,v
retrieving revision 1.36
diff -u -r1.36 nntpd.c
--- imap/nntpd.c	9 Sep 2004 16:21:26 -0000	1.36
+++ imap/nntpd.c	28 Sep 2004 18:06:51 -0000
@@ -70,6 +70,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <ctype.h>
+#include <pwd.h>
 
 #include <sasl/sasl.h>
 #include <sasl/saslutil.h>
@@ -624,6 +625,14 @@
 	    nntp_haveaddr = 1;
 	}
     }
+    else if (errno == ENOTSOCK) {
+	/* connected via stdio, allow external auth as real uid */
+	uid_t uid = getuid();
+	struct passwd *pw = getpwuid(uid);
+
+	saslprops.ssf = 2;
+	saslprops.authid = xstrdup(pw->pw_name);
+    }
 
     /* other params should be filled in */
     if (sasl_server_new("nntp", config_servername, NULL, NULL, NULL,
@@ -633,6 +642,9 @@
     /* will always return something valid */
     secprops = mysasl_secprops(SASL_SEC_NOPLAINTEXT);
     sasl_setprop(nntp_saslconn, SASL_SEC_PROPS, secprops);
+    sasl_setprop(nntp_saslconn, SASL_SSF_EXTERNAL, &saslprops.ssf);
+    if (saslprops.authid)
+	sasl_setprop(nntp_saslconn, SASL_AUTH_EXTERNAL, saslprops.authid);
     
     if(iptostring((struct sockaddr *)&nntp_localaddr, salen,
 		  localip, 60) == 0) {
Index: imap/pop3d.c
===================================================================
RCS file: /afs/andrew/system/cvs/src/cyrus/imap/pop3d.c,v
retrieving revision 1.163
diff -u -r1.163 pop3d.c
--- imap/pop3d.c	9 Sep 2004 16:21:26 -0000	1.163
+++ imap/pop3d.c	28 Sep 2004 18:06:51 -0000
@@ -62,6 +62,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <ctype.h>
+#include <pwd.h>
 #include "prot.h"
 
 #include <sasl/sasl.h>
@@ -379,6 +380,14 @@
 	    popd_haveaddr = 1;
 	}
     }
+    else if (errno == ENOTSOCK) {
+	/* connected via stdio, allow external auth as real uid */
+	uid_t uid = getuid();
+	struct passwd *pw = getpwuid(uid);
+
+	saslprops.ssf = 2;
+	saslprops.authid = xstrdup(pw->pw_name);
+    }
 
     /* other params should be filled in */
     if (sasl_server_new("pop", config_servername, NULL, NULL, NULL,
@@ -388,6 +397,9 @@
     /* will always return something valid */
     secprops = mysasl_secprops(SASL_SEC_NOPLAINTEXT);
     sasl_setprop(popd_saslconn, SASL_SEC_PROPS, secprops);
+    sasl_setprop(popd_saslconn, SASL_SSF_EXTERNAL, &saslprops.ssf);
+    if (saslprops.authid)
+	sasl_setprop(popd_saslconn, SASL_AUTH_EXTERNAL, saslprops.authid);
     
     if(iptostring((struct sockaddr *)&popd_localaddr,
 		  salen, localip, 60) == 0) {
Index: master/service.c
===================================================================
RCS file: /afs/andrew/system/cvs/src/cyrus/master/service.c,v
retrieving revision 1.52
diff -u -r1.52 service.c
--- master/service.c	13 Sep 2004 22:13:04 -0000	1.52
+++ master/service.c	28 Sep 2004 18:06:52 -0000
@@ -338,6 +338,18 @@
     opterr = 1; /* enable error reporting */
     optind = 1; /* reset the option index for parsing by the service */
 
+    if (fstat(LISTEN_FD, &sbuf) == -1 && errno == EBADF) {
+	/* not spawned from master, run as a standalone process */
+
+	cyrus_init(alt_config, argv[0], 0);
+
+	if (service_init(newargc, newargv, envp) != 0) return 1;
+	service_main(newargc, newargv, envp);
+	service_abort(0);
+
+	return 0;
+    }
+
     p = getenv("CYRUS_VERBOSE");
     if (p) verbose = atoi(p) + 1;
 


More information about the Info-cyrus mailing list