I had a request to add DRAC support to Cyrus IMAPd in Debian, so I applied the already excelent patches in contrib/drac_auth.patch and cleaned them up a little bit (and made the default to be DRAC disabled).
Here it is, patch against stock 2.1.4. They look clean and well-done enough to be made part of standard Cyrus IMHO, to be enabled by anyone who wants to compile DRAC support in. -- "One disk to rule them all, One disk to find them. One disk to bring them all and in the darkness grind them. In the Land of Redmond where the shadows lie." -- The Silicon Valley Tarot Henrique Holschuh
diff -ru cyrus-imapd-2.1.4.orig/acconfig.h cyrus-imapd-2.1.4/acconfig.h --- cyrus-imapd-2.1.4.orig/acconfig.h Mon Apr 15 16:35:49 2002 +++ cyrus-imapd-2.1.4/acconfig.h Sun May 19 15:29:20 2002 @@ -101,6 +101,9 @@ /* do we have SASL support for APOP? */ #undef HAVE_APOP +/* the Dynamic Relay Authorization Control package */ +#undef DRAC_AUTH + /* do we have OpenSSL? */ #undef HAVE_SSL diff -ru cyrus-imapd-2.1.4.orig/configure.in cyrus-imapd-2.1.4/configure.in --- cyrus-imapd-2.1.4.orig/configure.in Mon Apr 15 16:35:48 2002 +++ cyrus-imapd-2.1.4/configure.in Sun May 19 15:29:20 2002 @@ -865,6 +865,19 @@ SNMP_SUBDIRS="" AC_SUBST(SNMP_SUBDIRS) +dnl +dnl Test for DRAC +dnl +DRACLIBS= +AC_ARG_WITH(drac, [ --with-drac=DIR use DRAC library in <DIR> [no] ], + if test -d "$withval"; then + LDFLAGS="$LDFLAGS -L${withval}" + AC_CHECK_LIB(drac, dracauth, + AC_DEFINE(DRAC_AUTH) + DRACLIBS="-ldrac") + fi) +AC_SUBST(DRACLIBS) + CMU_SOCKETS CMU_LIBWRAP CMU_UCDSNMP Only in cyrus-imapd-2.1.4: configure.in.orig diff -ru cyrus-imapd-2.1.4.orig/imap/Makefile.in cyrus-imapd-2.1.4/imap/Makefile.in --- cyrus-imapd-2.1.4.orig/imap/Makefile.in Thu Apr 18 14:35:26 2002 +++ cyrus-imapd-2.1.4/imap/Makefile.in Sun May 19 15:29:20 2002 @@ -67,6 +67,7 @@ SIEVE_LIBS = @SIEVE_LIBS@ IMAP_COM_ERR_LIBS = @IMAP_COM_ERR_LIBS@ LIB_WRAP = @LIB_WRAP@ +DRAC_LIBS = @DRACLIBS@ LIBS = $(IMAP_LIBS) $(IMAP_COM_ERR_LIBS) DEPLIBS = ../acap/libacap.a ../lib/libcyrus.a @DEPLIBS@ @@ -201,15 +202,15 @@ imapd: xversion $(IMAPDOBJS) libimap.a $(DEPLIBS) $(SERVICE) $(CC) $(LDFLAGS) -o imapd \ - $(SERVICE) $(IMAPDOBJS) libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) + $(SERVICE) $(IMAPDOBJS) libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) $(DRAC_LIBS) imapd.pure: $(IMAPDOBJS) libimap.a $(DEPLIBS) $(SERVICE) $(PURIFY) $(PUREOPT) $(CC) $(LDFLAGS) -o imapd.pure \ - $(SERVICE) $(IMAPDOBJS) libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) + $(SERVICE) $(IMAPDOBJS) libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) $(DRAC_LIBS) imapd.quant: $(IMAPDOBJS) libimap.a $(DEPLIBS) $(SERVICE) $(QUANTIFY) $(QUANTOPT) $(CC) $(LDFLAGS) -o imapd.quant \ - $(SERVICE) $(IMAPDOBJS) libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) + $(SERVICE) $(IMAPDOBJS) libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) $(DRAC_LIBS) proxyd: $(PROXYDOBJS) libimap.a $(DEPLIBS) $(SERVICE) $(CC) $(LDFLAGS) -o proxyd \ @@ -235,7 +236,7 @@ pop3d: pop3d.o tls.o libimap.a $(DEPLIBS) $(SERVICE) $(CC) $(LDFLAGS) -o pop3d pop3d.o tls.o $(SERVICE) \ - libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) + libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) $(DRAC_LIBS) pop3proxyd: pop3proxyd.o tls.o libimap.a $(DEPLIBS) $(SERVICE) $(CC) $(LDFLAGS) -o pop3proxyd pop3proxyd.o tls.o $(SERVICE) \ diff -ru cyrus-imapd-2.1.4.orig/imap/imapd.c cyrus-imapd-2.1.4/imap/imapd.c --- cyrus-imapd-2.1.4.orig/imap/imapd.c Thu Apr 25 15:15:14 2002 +++ cyrus-imapd-2.1.4/imap/imapd.c Sun May 19 15:29:20 2002 @@ -120,6 +120,18 @@ static SSL *tls_conn = NULL; #endif /* HAVE_SSL */ +#ifdef DRAC_AUTH +static struct { + int interval; /* dracd "ping" interval; 0 = disabled */ + unsigned long clientaddr; + struct prot_waitevent *event; +} drac; + +extern int dracconn(char *server, char **errmsg); +extern int dracsend(unsigned long userip, char **errmsg); +extern int dracdisc(char **errmsg); +#endif /* DRAC_AUTH */ + /* current sub-user state */ static struct mailbox mboxstruct; static struct mailbox *imapd_mailbox; @@ -529,6 +541,23 @@ /* setup for sending IMAP IDLE notifications */ idle_enabled(); +#ifdef DRAC_AUTH + /* setup for sending DRAC "pings" */ + drac.event = NULL; + drac.interval = config_getint("dracinterval", 0); + if (drac.interval < 0) drac.interval = 0; + if (drac.interval) { + char *err; + + if (dracconn((char*) config_getstring("drachost", "localhost"), &err) != 0) { + /* disable DRAC */ + drac.interval = 0; + syslog(LOG_ERR, "dracconn: %s", err); + syslog(LOG_ERR, "DRAC notifications disabled"); + } + } +#endif /* DRAC_AUTH */ + /* create connection to the SNMP listener, if available. */ snmp_connect(); /* ignore return code */ snmp_set_str(SERVER_NAME_VERSION,CYRUS_VERSION); @@ -611,6 +640,12 @@ imapd_haveaddr = 1; } } + +#ifdef DRAC_AUTH + drac.clientaddr = imapd_remoteaddr.sin_addr.s_addr; + } else { + drac.clientaddr = 0; +#endif /* DRAC_AUTH */ } /* create the SASL connection */ @@ -653,6 +688,11 @@ prot_flush(imapd_out); snmp_increment(ACTIVE_CONNECTIONS, -1); +#ifdef DRAC_AUTH + if (drac.event) prot_removewaitevent(imapd_in, drac.event); + drac.event = NULL; +#endif /* DRAC_AUTH */ + /* cleanup */ imapd_reset(); @@ -731,6 +771,10 @@ snmp_increment(ACTIVE_CONNECTIONS, -1); } +#ifdef DRAC_AUTH + if (drac.interval) (void) dracdisc((char **)NULL); +#endif /* DRAC_AUTH */ + exit(code); } @@ -753,6 +797,35 @@ } +#ifdef DRAC_AUTH +/* + * Ping dracd every 'drac.interval' minutes + * to let it know that we are still connected + */ +struct prot_waitevent *drac_ping(struct protstream *s, + struct prot_waitevent *ev, void *rock) +{ + char *err; + static int nfailure = 0; + + if (dracsend(drac.clientaddr, &err) != 0) { + syslog(LOG_ERR, "dracsend: %s", err); + if (++nfailure >= 3) { + /* can't contact dracd for 3 consecutive tries - disable DRAC */ + prot_removewaitevent(s, ev); + drac.event = NULL; + syslog(LOG_ERR, "DRAC notifications disabled"); + return NULL; + } + } + else + nfailure = 0; + + ev->mark = time(NULL) + (drac.interval * 60); + return ev; +} +#endif /* DRAC_AUTH */ + /* * Top-level command loop parsing */ @@ -1774,6 +1847,11 @@ prot_printf(imapd_out, "%s OK %s\r\n", tag, reply); +#ifdef DRAC_AUTH + if (drac.interval && drac.clientaddr) + drac.event = prot_addwaitevent(imapd_in, 0 /* now */, drac_ping, NULL); +#endif /* DRAC_AUTH */ + /* Create telemetry log */ imapd_logfd = telemetry_log(imapd_userid, imapd_in, imapd_out); @@ -1928,6 +2006,11 @@ prot_setsasl(imapd_in, imapd_saslconn); prot_setsasl(imapd_out, imapd_saslconn); + +#ifdef DRAC_AUTH + if (drac.interval && drac.clientaddr) + drac.event = prot_addwaitevent(imapd_in, 0 /* now */, drac_ping, NULL); +#endif /* DRAC_AUTH */ /* Create telemetry log */ imapd_logfd = telemetry_log(imapd_userid, imapd_in, imapd_out); Only in cyrus-imapd-2.1.4/imap: imapd.c.orig diff -ru cyrus-imapd-2.1.4.orig/imap/pop3d.c cyrus-imapd-2.1.4/imap/pop3d.c --- cyrus-imapd-2.1.4.orig/imap/pop3d.c Wed Apr 10 15:02:42 2002 +++ cyrus-imapd-2.1.4/imap/pop3d.c Sun May 19 15:29:20 2002 @@ -101,6 +101,10 @@ extern int errno; +#ifdef DRAC_AUTH +static int drac_enabled; +extern int dracauth(char *server, unsigned long userip, char **errmsg); +#endif /* DRAC_AUTH */ #ifdef HAVE_SSL @@ -428,6 +432,10 @@ prot_settimeout(popd_in, timeout*60); prot_setflushonread(popd_in, popd_out); +#ifdef DRAC_AUTH + drac_enabled = (config_getint("dracinterval", 0) > 0); +#endif /* DRAC_AUTH */ + if (kflag) kpop(); /* we were connected on pop3s port so we should do @@ -1404,6 +1412,20 @@ } popd_mailbox = &mboxstruct; proc_register("pop3d", popd_clienthost, popd_userid, popd_mailbox->name); + +#ifdef DRAC_AUTH + if (drac_enabled) { + char *err; + + if (dracauth((char*) config_getstring("drachost", "localhost"), + popd_remoteaddr.sin_addr.s_addr, &err) != 0) { + /* disable DRAC */ + drac_enabled = 0; + syslog(LOG_ERR, "dracauth: %s", err); + syslog(LOG_ERR, "DRAC notifications disabled"); + } + } +#endif /* DRAC_AUTH */ /* Create telemetry log */ telemetry_log(popd_userid, popd_in, popd_out); Only in cyrus-imapd-2.1.4/imap: pop3d.c.orig diff -ru cyrus-imapd-2.1.4.orig/imap/version.c cyrus-imapd-2.1.4/imap/version.c --- cyrus-imapd-2.1.4.orig/imap/version.c Thu Mar 21 18:10:04 2002 +++ cyrus-imapd-2.1.4/imap/version.c Sun May 19 15:29:20 2002 @@ -130,6 +130,10 @@ snprintf(env_buf + strlen(env_buf), MAXIDVALUELEN - strlen(env_buf), "; %s", SIEVE_VERSION); #endif +#ifdef DRAC_AUTH + snprintf(env_buf + strlen(env_buf), MAXIDVALUELEN - strlen(env_buf), + "; DRAC"); +#endif #ifdef HAVE_LIBWRAP snprintf(env_buf + strlen(env_buf), MAXIDVALUELEN - strlen(env_buf), "; TCP Wrappers"); diff -ru cyrus-imapd-2.1.4.orig/man/imapd.conf.5 cyrus-imapd-2.1.4/man/imapd.conf.5 --- cyrus-imapd-2.1.4.orig/man/imapd.conf.5 Thu Mar 21 18:10:05 2002 +++ cyrus-imapd-2.1.4/man/imapd.conf.5 Sun May 19 15:30:23 2002 @@ -318,8 +318,14 @@ Unix domain socket that idled listens on. .IP "\fBnotifysocket:\fR /var/imap/socket/notify" 5 Unix domain socket that the new mail notification daemon listens on. +.IP "\fBdracinterval:\fR 0" 5 +If nonzero, enables the use of DRAC (Dynamic Relay Authorization Control) +by the pop3d and imapd daemons. Also sets the interval (in minutes) between +re-authorization requests made by imapd. +.IP "\fBdrachost:\fR localhost" 5 +Hostname of the RPC dracd server. .SH SEE ALSO .PP \fBimapd(8)\fR, \fBpop3d(8)\fR, \fBlmtpd(8)\fR, \fBtimsieved(8)\fR, \fBidled(8)\fR, \fBnotifyd(8)\fR, \fBdeliver(8)\fR, \fBmaster(8)\fR, -\fBciphers(1)\fR +\fBrpc.dracd(1m)\fR, \fBciphers(1)\fR