diff -urN imap-2001a.RELEASE-CANDIDATE.2.orig/Makefile imap-2001a.RELEASE-CANDIDATE.2/Makefile --- imap-2001a.RELEASE-CANDIDATE.2.orig/Makefile Fri Oct 19 18:53:15 2001 +++ imap-2001a.RELEASE-CANDIDATE.2/Makefile Thu Nov 1 14:04:56 2001 @@ -128,7 +128,9 @@ # mbox if file "mbox" exists on the home directory, automatically moves mail # from the spool directory to "mbox" and uses "mbox" as INBOX. -EXTRADRIVERS=mbox +#EXTRADRIVERS=mbox +# We set it to nothing to override the default in src/osdep/unix/Makefile +EXTRADRIVERS= # Plaintext password type. Defines how plaintext password authentication is @@ -211,8 +213,33 @@ # years. The Orthodox and Gregorian calendars diverge by 1 day for # gradually-increasing intervals, starting at 2800-2900, and becoming # permanent at 48,300. +# +# -DMBXHOMEDIR="/var/spool/mbx" +# If /var/spool/mbx/user/INBOX exists, mail is delivered there +# (allows you to have both users with MBX mailboxes and folders on the +# mail server, while others use MBOX format and have folders in their +# homedirs (MBX doesn't work over NFS)) +# +# -DHOMEMAILDIR="Mail" +# Will look for folders in /home/user/Mail instead of /home/user +# +# -DBLOCKFSWANDERING +# Will prevent fileops with '/' or '..', or anything else that would +# let a user wander around your server's filesystem +# (like select /etc/passwd). +# If used in conjunction with DHOMEMAILDIR, it will prevent a cracker +# to browse through a user's homedir if they somehow steal their mail +# password (they'd be confined to the mail directory) +# +# -DFORCENODOTFILES +# Useful if the above isn't set as it won't show dot files and dirs +# when browse all folders is selected from the imap client +# +# -DVERBOSELOG +# Improved syslog which gives lots of performance stats on each imap +# connection -EXTRACFLAGS= +EXTRACFLAGS=-DMBXHOMEDIR="/var/spool/mbx" -DFORCENODOTFILES -DVERBOSELOG -DBLOCKFSWANDERING -DHOMEMAILDIR="Mail" # Extra linker flags (additional/alternative libraries, etc.) @@ -222,13 +249,15 @@ # Big heartfelt sigh of utter disgust -SSLDIR=/usr/local/ssl +# On a FSSTND unix system, openssl is split in different dirs, config in +# /etc, includes in /usr/include/openssl, libs in /usr/lib, etc... -- Marc +SSLDIR=/etc/ssl GSSDIR=/usr/local # Special make flags (e.g. to override make environment variables) -EXTRASPECIALS= +EXTRASPECIALS=SSLINCLUDE=/usr/include/openssl SPECIALS=SSLDIR=$(SSLDIR) GSSDIR=$(GSSDIR) diff -urN imap-2001a.RELEASE-CANDIDATE.2.orig/src/imapd/imapd.c imap-2001a.RELEASE-CANDIDATE.2/src/imapd/imapd.c --- imap-2001a.RELEASE-CANDIDATE.2.orig/src/imapd/imapd.c Fri Sep 28 17:52:18 2001 +++ imap-2001a.RELEASE-CANDIDATE.2/src/imapd/imapd.c Thu Nov 1 15:03:58 2001 @@ -49,6 +49,11 @@ #define MAXCLIENTLIT 10000 /* maximum non-APPEND client literal size */ #define TMPLEN 8192 /* size of temporary buffers */ +#ifdef VERBOSELOG +#include +#include +#include +#endif /* Server states */ @@ -173,7 +178,7 @@ /* Global storage */ -char *version = "2001.313"; /* version number of this server */ +char *version = "2001.313-VA-mm1"; /* version number of this server */ time_t alerttime = 0; /* time of last alert */ time_t sysalerttime = 0; /* time of last system alert */ time_t useralerttime = 0; /* time of last user alert */ @@ -209,6 +214,11 @@ char *lastsel = NIL; /* last selected mailbox name */ SIZEDTEXT lastst = {NIL,0}; /* last sizedtext */ +#ifdef VERBOSELOG +time_t *timer; /* timer */ +time_t starttime; /* record start time of process */ +double uutime,sstime; /* user and system time */ +#endif /* Response texts which appear in multiple places */ @@ -242,6 +252,9 @@ char *s,*t,*u,*v,tmp[MAILTMPLEN]; struct stat sbuf; time_t autologouttime = 0; +#ifdef VERBOSELOG + struct rusage sysinfo; +#endif #include "linkage.c" rfc822_date (tmp); /* get date/time at startup */ /* initialize server */ @@ -273,6 +286,9 @@ default: fatal ("Unknown state from myusername_full()"); } +#ifdef VERBOSELOG + starttime = time(timer); +#endif PSOUT ("] "); if (user) { /* preauthenticated as someone? */ PSOUT ("Pre-authenticated user "); @@ -1203,6 +1219,34 @@ } syslog (LOG_INFO,"Logout user=%.80s host=%.80s",user ? user : "???", tcp_clienthost ()); +#ifdef VERBOSELOG + /* This is for additional logging information so that we can do analysis */ + getrusage(RUSAGE_SELF,&sysinfo); + + uutime = (double) sysinfo.ru_utime.tv_sec + + sysinfo.ru_utime.tv_usec / 1000000.0; + sstime = (double) sysinfo.ru_stime.tv_sec + + sysinfo.ru_stime.tv_usec / 1000000.0; + + syslog (LOG_INFO,"u %s from %s start %d et %d ut %.3f st %.3f mss %ld iss %ld minf %ld majf %ld sw %ld bi %ld bo %ld mi %ld mo %ld nsig %ld vcs %ld ics %ld", user ? user : "???", + tcp_clienthost (), + starttime, + time(timer) - starttime, + uutime, + sstime, + sysinfo.ru_maxrss, + sysinfo.ru_idrss, + sysinfo.ru_minflt, + sysinfo.ru_majflt, + sysinfo.ru_nswap, + sysinfo.ru_inblock, + sysinfo.ru_oublock, + sysinfo.ru_msgrcv, + sysinfo.ru_msgsnd, + sysinfo.ru_nsignals, + sysinfo.ru_nvcsw, + sysinfo.ru_nivcsw); +#endif return 0; /* all done */ } @@ -1444,12 +1488,43 @@ void clkint (void) { +#ifdef VERBOSELOG + struct rusage sysinfo; +#endif alarm (0); /* disable all interrupts */ server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); if (!quell_events) PSOUT ("* BYE Autologout; idle for too long\015\012"); syslog (LOG_INFO,"Autologout user=%.80s host=%.80s",user ? user : "???", tcp_clienthost ()); +#ifdef VERBOSELOG + /* This is for additional logging information so that we can do analysis */ + getrusage(RUSAGE_SELF,&sysinfo); + + uutime = (double) sysinfo.ru_utime.tv_sec + + sysinfo.ru_utime.tv_usec / 1000000.0; + sstime = (double) sysinfo.ru_stime.tv_sec + + sysinfo.ru_stime.tv_usec / 1000000.0; + + syslog (LOG_INFO,"u %s from %s start %d et %d ut %.3f st %.3f mss %ld iss %ld minf %ld majf %ld sw %ld bi %ld bo %ld mi %ld mo %ld nsig %ld vcs %ld ics %ld", user ? user : "???", + tcp_clienthost (), + starttime, + time(timer) - starttime, + uutime, + sstime, + sysinfo.ru_maxrss, + sysinfo.ru_idrss, + sysinfo.ru_minflt, + sysinfo.ru_majflt, + sysinfo.ru_nswap, + sysinfo.ru_inblock, + sysinfo.ru_oublock, + sysinfo.ru_msgrcv, + sysinfo.ru_msgsnd, + sysinfo.ru_nsignals, + sysinfo.ru_nvcsw, + sysinfo.ru_nivcsw); +#endif PFLUSH (); /* make sure output blatted */ if (critical) state = LOGOUT; /* must defer if in critical code */ else { /* try to close stream gracefully */ diff -urN imap-2001a.RELEASE-CANDIDATE.2.orig/src/osdep/unix/dummy.c imap-2001a.RELEASE-CANDIDATE.2/src/osdep/unix/dummy.c --- imap-2001a.RELEASE-CANDIDATE.2.orig/src/osdep/unix/dummy.c Fri Sep 28 17:57:21 2001 +++ imap-2001a.RELEASE-CANDIDATE.2/src/osdep/unix/dummy.c Wed Oct 31 16:07:48 2001 @@ -240,11 +240,15 @@ dummy_listed (stream,'/',dir,LATT_NOSELECT,contents); /* scan directory, ignore . and .. */ if (!dir || dir[strlen (dir) - 1] == '/') while (d = readdir (dp)) +#if FORCENODOTFILES + if (d->d_name[0] != '.') { +#else if (((d->d_name[0] != '.') || (((int) mail_parameters (NIL,GET_HIDEDOTFILES,NIL)) ? NIL : (d->d_name[1] && (((d->d_name[1] != '.') || d->d_name[2]) && strcmp (d->d_name+1,MXINDEXNAME+2))))) && (strlen (d->d_name) <= NETMAXMBX)) { +#endif /* see if name is useful */ if (dir) sprintf (tmp,"%s%s",dir,d->d_name); else strcpy (tmp,d->d_name); diff -urN imap-2001a.RELEASE-CANDIDATE.2.orig/src/osdep/unix/env_unix.c imap-2001a.RELEASE-CANDIDATE.2/src/osdep/unix/env_unix.c --- imap-2001a.RELEASE-CANDIDATE.2.orig/src/osdep/unix/env_unix.c Wed Oct 17 20:35:20 2001 +++ imap-2001a.RELEASE-CANDIDATE.2/src/osdep/unix/env_unix.c Thu Nov 1 15:27:15 2001 @@ -628,6 +628,7 @@ { extern MAILSTREAM CREATEPROTO; extern MAILSTREAM EMPTYPROTO; + extern MAILSTREAM mbxproto; struct passwd *pw; struct stat sbuf; char tmp[MAILTMPLEN]; @@ -673,7 +674,29 @@ sysInbox = cpystr (tmp); /* make system INBOX */ anonymous = T; /* flag as anonymous */ } - myHomeDir = cpystr (home); /* set home directory */ +#ifdef MBXHOMEDIR + /* If that specific user has an INBOX in the MBX location, we look for */ + /* all our files there */ + sprintf (tmp,"%s/%s/INBOX",MBXHOMEDIR,myUserName); + if (access (tmp, R_OK | W_OK) == 0) { + sprintf (tmp,"%s/%s/",MBXHOMEDIR,myUserName); + myHomeDir = cpystr (tmp); + + /* Our default is to create new mailboxes in unix mailbox format, but */ + /* we change this to MBX if the user has MBX mailboxes in MBXHOMEDIR */ + createProto = &mbxproto; + } + else { +#endif +#ifdef HOMEMAILDIR + sprintf (tmp,"%s/%s",home,HOMEMAILDIR); + myHomeDir = cpystr (tmp); +#else + myHomeDir = cpystr (home); /* set home directory */ +#endif +#ifdef MBXHOMEDIR + } +#endif } if (allowuserconfig) { /* allow user config files */ @@ -833,12 +856,37 @@ char *mailboxfile (char *dst,char *name) { + char tmp[MAILTMPLEN]; struct passwd *pw; char *dir = mymailboxdir (); *dst = '\0'; /* default to empty string */ /* check invalid name */ if (!name || !*name || (*name == '{') || (strlen (name) > NETMAXMBX)) return NIL; + +#ifdef BLOCKFSWANDERING +/* + * As far as I can tell, all file accesses go through this, so blocking unwanted + * paths here should be enough. Let me know if I'm wrong + * -- Marc 2001/11/01 + */ + + /* Preventing names that start with # is bad because clients like netscape + * will do 18 different queries based on those names, and they will all + * fail one per one. You are responsible for making sure that #ftp or + * #public doesn't lead to anything you don't want people to see + */ + + /* netscape will also try to select "~" which is ok, let's not deny that */ + /* ~/foo is cool too, as well as /var/spool/mail/foo */ + if ((name[0] == '/' && strstr(name, MAILSPOOL) != name) || (name[0] == '~' && name[1] != 0 && name[1] != '/') || (strstr(name, "..") != NULL)) + { + sprintf (tmp,"Security: mailboxfile() blocked access to %s by %s", name, myUserName); + syslog (LOG_ERR, "%s", tmp); + MM_LOG (tmp,ERROR); + return NIL; + } +#endif /* check for INBOX */ if (((name[0] == 'I') || (name[0] == 'i')) && ((name[1] == 'N') || (name[1] == 'n')) &&