diff -b -B --unified smtpd-2.0-orig/CREDITS smtpd-2.0/CREDITS --- smtpd-2.0-orig/CREDITS Wed Oct 6 02:35:02 1999 +++ smtpd-2.0/CREDITS Thu Oct 7 15:25:05 1999 @@ -120,3 +120,16 @@ sending message body - could make smtpd exit and leave an incomplete spool file sitting in the spool dir. +Who: Simon J. Gerraty +What: Contributed new -q logging format and fixes for spaces within + quoted local-part so smtpd doesn't smack X400 messages. + +Who: Henning P. Schmiedehausen +What: Contributed -l option to allow for smtpd to be restricted to + answering on only one address on a box with many addresses. + +Who: D. R. Tzeck +What: Fixed show_usage(), added even more logging, made smtp_port + and identification in syslog configurable in the Makefile, + added -F option to keep smtpd from forking. + Only in smtpd-2.0-orig: CVS diff -b -B --unified smtpd-2.0-orig/Makefile smtpd-2.0/Makefile --- smtpd-2.0-orig/Makefile Wed Oct 6 02:35:03 1999 +++ smtpd-2.0/Makefile Thu Oct 7 15:13:45 1999 @@ -12,15 +12,16 @@ # This must take arguments of the form: # "mailprog -f fromaddr toaddr toaddr ..." # to deliver mail. -MAIL_AGENT = /usr/sbin/sendmail +#MAIL_AGENT = /usr/sbin/sendmail #MAIL_AGENT = /usr/lib/sendmail +MAIL_AGENT = /var/qmail/bin/qmail-inject # What user and group should smtpfwdd and smtpd run as? # This MUST NOT be root, and must be a user that is "trusted" by # sendmail or whatever you are using as MAIL_AGENT above so that the user # may use the "-f" flag to specify the sender of a mail message. -SMTP_USER = uucp -SMTP_GROUP = uucp +SMTP_USER = smtpd +SMTP_GROUP = smtpd # smtpd and smtpfwdd generate lots of syslogs, by design. # @@ -41,7 +42,8 @@ # in SMTP_USER above. # # The chroot directory -SPOOLDIR = /usr/spool/smtpd +#SPOOLDIR = /usr/spool/smtpd +SPOOLDIR = /var/spool/smtpd # Where to store messages, relative to SPOOLDIR above. SPOOLSUBDIR = . #Use below instead of above if you don't want smtpd to chroot. This @@ -53,12 +55,12 @@ # How frequently (in seconds) should smtpfwdd wake up to check the # spool directory for new mail? -POLL_TIME = 10 +POLL_TIME = 5 # What is the maximum number of children smtpfwdd should spawn at one time # when delivering messages before waiting for some to complete? This ensures # the arrival of hundreds of mail messages doesn't run you out of processes. -MAXCHILDREN = 10 +MAXCHILDREN = 5 # Should smtpfwdd check the exit code of sendmail? smtpfwdd checks any # non-zero exit status from sendmail to see if it indicates that @@ -79,13 +81,13 @@ # name ends in the string "sendmail". If your "sendmail" isn't really # sendmail, you may not need or want this. If so, change the SENDMAIL_OITRUE # below to 0. -SENDMAIL_OITRUE = 1 +SENDMAIL_OITRUE = 0 # Sendmail can handle addresses quoted in <> on the command line. Some # MTA's (like qmail) can't. set STRIP_QUOTES to 1 if you want smtpfwdd # to peel off the <> from mail addresses on the command line when # invoking the mta -STRIP_QUOTES = 0 +STRIP_QUOTES = 1 # How many arguments can your execv() call take at once? This can be a # conservative estimate. It determines the maximum number of @@ -114,8 +116,8 @@ # It's understandable that they aren't everyone's cup of tea. Set # VANILLA_MESSAGES below to 1 and smtp will use plain old politically # correct Sendmail/RFC 821 style status messages. -# VANILLA_MESSAGES = 1 # Boring.... -VANILLA_MESSAGES = 0 +VANILLA_MESSAGES = 1 # Boring.... +#VANILLA_MESSAGES = 0 # smtpd checks and clobbers and potentially "evil" characters in hostnames, # and mail addresses recieved on FROM: and RCPT: lines. This clobbers things @@ -206,8 +208,8 @@ # build with CHECK_ADDRESS set to 1. You will get an error about # juniper_firewall.h not existing if you forget this. # -JUNIPER_SUPPORT=1 -#JUNIPER_SUPPORT=0 +#JUNIPER_SUPPORT=1 +JUNIPER_SUPPORT=0 # Use regexp's in patterns? If you have a POSIX and friends, # and you trust the regex lib enough for use, you can set USE_REGEX to @@ -260,8 +262,8 @@ # seconds) on an ident request. if CHECK_IDENT is 0, no ident # requests will be made by smtpd even if it sees a rule that would # normally make it perform one. -# CHECK_IDENT = 0 -CHECK_IDENT = 10 +CHECK_IDENT = 0 +#CHECK_IDENT = 10 # If you use the address checks to block incoming mail from certain # spam sites, you can set NOTO_DELAY and DENY_DELAY below to specify @@ -287,6 +289,15 @@ # CHECK_ADDRESS_DENY_ON_FAILURE = 1 CHECK_ADDRESS_DENY_ON_FAILURE = 0 +# The well known Port for smtp is 25 so we will listen on port 25. +# You don't have to change this unless you are doing something +# very special. +LISTENPORT = 25 + +# The identifier smtpd should use when logging to syslog. +# In general you should use the name of the process which is +# "smtpd" +SMTPDSYSLOGSTR = smtpd # Options to pass to indent when tidying up the code. INDENT_ARGS = -di0 -br -bad -bap -nbc -cdb -ce -i2 -lp -npro -npcs -psl @@ -314,7 +325,8 @@ -DNOTO_DELAY=$(NOTO_DELAY) -DDENY_DELAY=$(DENY_DELAY) \ -DSET_LOCALE=$(SET_LOCALE) -DLOCALIZATION=\"$(LOCALIZATION)\" \ -DJUNIPER_SUPPORT=$(JUNIPER_SUPPORT) -DNS_MATCH=$(NS_MATCH) \ - -DUSE_REGEX=$(USE_REGEX) + -DUSE_REGEX=$(USE_REGEX) -DSMTPDSYSLOGSTR=\"$(SMTPDSYSLOGSTR)\" \ + -DLISTENPORT=$(LISTENPORT) ## CC of choice. #CC = cc @@ -346,24 +358,29 @@ all: smtpd smtpfwdd -smtpd: smtpd.o address_check.o - $(CC) -o smtpd smtpd.o address_check.o $(LD_LIBS) +smtpd: smtpd.o address_check.o accumlog.o + $(CC) -o smtpd smtpd.o address_check.o accumlog.o $(LD_LIBS) -smtpfwdd: smtpfwdd.o - $(CC) -o smtpfwdd smtpfwdd.o $(LD_LIBS) +smtpfwdd: smtpfwdd.o accumlog.o + $(CC) -o smtpfwdd smtpfwdd.o accumlog.o $(LD_LIBS) smtpd.o: smtpd.c smtpd.h smtp.h smtpfwdd.o: smtpfwdd.c smtp.h +accumlog.o: accumlog.c + indent: indent $(INDENT_ARGS) smtpd.c indent $(INDENT_ARGS) smtpfwdd.c indent $(INDENT_ARGS) address_check.c + indent $(INDENT_ARGS) accumlog.c install: smtpd smtpfwdd install -m 500 smtpd $(INSTALL_PREFIX)$(INSTALL_BIN)smtpd install -m 500 smtpfwdd $(INSTALL_PREFIX)$(INSTALL_BIN)smtpfwdd + install -m 500 smtpd.8 $(INSTALL_PREFIX)$(INSTALL_MAN)/man8/smtpd.8 + install -m 500 smtpfwdd.8 $(INSTALL_PREFIX)$(INSTALL_MAN)/man8/smtpfwdd.8 clean: /bin/rm -f *.o Only in smtpd-2.0-orig: Makefile.default Only in smtpd-2.0-orig: Makefile.minimal Only in smtpd-2.0-orig: Makefile.nochecks Only in smtpd-2.0: RCS Only in smtpd-2.0: accumlog.c diff -b -B --unified smtpd-2.0-orig/antirelay_check_rules_example smtpd-2.0/antirelay_check_rules_example --- smtpd-2.0-orig/antirelay_check_rules_example Wed Oct 6 02:35:03 1999 +++ smtpd-2.0/antirelay_check_rules_example Wed Oct 6 02:34:43 1999 @@ -9,6 +9,11 @@ # for any connection on a trusted interface. #allow:TRUSTED:ALL:ALL +# Don't allow people to %hack relay off of me. +noto:ALL:ALL:*%*@*:551 Sorry %H (%I), I don't allow unauthorized relaying. You can't use me to send mail from %F to %T. +noto:ALL:ALL:*!*@*:551 Sorry %H (%I), I don't allow unauthorized relaying. You can't use me to send mail from %F to %T. +noto:ALL:ALL:*@*@*:551 Sorry %H (%I), I don't allow unauthorized relaying. You can't use me to send mail from %F to %T. + # If we have NS_MATCH=1 compiled in, we can do it this way, by allowing # the relay mail outbound from hosts that have dns.my.domain as one of # their nameservers. this might be useful if we sit in front of a diff -b -B --unified smtpd-2.0-orig/antispam_check_rules.example smtpd-2.0/antispam_check_rules.example --- smtpd-2.0-orig/antispam_check_rules.example Wed Oct 6 02:35:03 1999 +++ smtpd-2.0/antispam_check_rules.example Wed Oct 6 02:34:43 1999 @@ -27,6 +27,10 @@ # otherwise, we'd do it like this: allow:*mydomain.com *otherdomain.com:ALL +# don't allow people to use %hack to relay off of me. +noto:ALL:ALL:*%*@*:551 Sorry %H (%I), I don't allow unauthorized relaying. You can't use me to send mail from %F to %T. +noto:ALL:ALL:*!*@*:551 Sorry %H (%I), I don't allow unauthorized relaying. You can't use me to send mail from %F to %T. +noto:ALL:ALL:*@*@*:551 Sorry %H (%I), I don't allow unauthorized relaying. You can't use me to send mail from %F to %T. # First, the exceptions. # "I'll have your spam dear, I love it!" @@ -38,6 +42,18 @@ allow:ALL:ALL:ALL@hormel.mydomain.com spamboy@otherdomain.com +# Block any connections from host in the MAPS rbl at rbl.maps.vix.com +# Beware that this can throw the baby out with the bathwater. +noto:RBL.rbl.maps.vix.com:ALL:ALL:550 Mail refused from host %I in MAPS RBL, see http%C//maps.vix.com/rbl/ + +# Block any connections from a host or connecting address who uses a +# nameserver for which the address is in the MAPS rbl at rbl.maps.vix.com. +# Note that this can *really* throw the baby out with the bathwater, +# be sure you understand the implications before using the two below. +noto:NS=RBL.rbl.maps.vix.com:ALL:ALL:550 Mail refused due to nameserver for %H(%I) in MAPS RBL, see http%C//maps.vix.com/rbl/ +noto:ALL:NS=RBL.rbl.maps.vix.com:ALL:550 Mail refused due to nameserver for %F in MAPS RBL, see http%C//maps.vix.com/rbl/ + + # block anyone who uses a major SPAM provider as a nameserver or MX. either # on a connection from one of their hosts, a connection from a host they act # as a nameserver for, or a connection with a FROM: address that uses @@ -86,8 +102,85 @@ noto:NS=206.85.231.0/24:ALL:ALL noto:ALL:NS=206.85.231.0/24:ALL #tnlb.com - "the national letter bureau" and "mako marketing" - yeesh.. -noto:NS=206.101.40.5:ALL:ALL -noto:ALL:NS=206.101.40.5:ALL +noto:206.101.40.0/24 206.101.58.0/24 208.230.127.0/24:ALL:ALL +noto:NS=206.101.40.0/24 NS=206.101.58.0/24 NS=208.230.127.0/24:ALL:ALL +noto:ALL:NS=206.101.40.0/24 NS=206.101.58.0/24 NS=208.230.127.0/24:ALL +#c-flash.net - yaash +noto:205.199.166.0/24:ALL:ALL +noto:NS=205.199.166.0/24:ALL:ALL +noto:ALL:NS=205.199.166.0/24:ALL +#directsend.com - Former Nancynet customer, now yaash +noto:206.84.21.0/24 207.201.213.0/24:ALL:ALL +noto:NS=206.84.21.0/24 NS=207.201.213.0/24:ALL:ALL +noto:ALL:NS=206.84.21.0/24 NS=207.201.213.0/24:ALL +noto:206.84.21.0/24:ALL:ALL +noto:NS=206.84.21.0/24:ALL:ALL +noto:ALL:NS=206.84.21.0/24:ALL +#we-deliver.net - yaash +noto:206.62.151.0/24:ALL:ALL +noto:NS=206.62.151.0/24:ALL:ALL +noto:ALL:NS=206.62.151.0/24:ALL +#savoynet.com - yaash +noto:204.157.255.0/24:ALL:ALL +noto:NS=204.157.255.0/24:ALL:ALL +noto:ALL:NS=204.157.255.0/24:ALL +#taizen.com - "grandbikes.com" and other spammers. No response to complaints. +noto:208.219.218.0/24:ALL:ALL +noto:NS=208.219.218.0/24:ALL:ALL +noto:ALL:NS=208.219.218.0/24:ALL +#edgetone.com and cyberserverscentral.com +noto:208.223.114.0/24 208.223.112.0/24 204.178.73.192/25:ALL:ALL +noto:NS=208.223.114.0/24 NS=208.223.112.0/24 NS=204.178.73.192/25:ALL:ALL +noto:ALL:NS=208.223.114.0/24 NS=208.223.112.0/24 NS=204.178.73.192/25:ALL +#icsinc.net and money-group.net +noto:151.201.64.0/24:ALL:ALL +noto:NS=151.201.64.0/24:ALL:ALL +noto:ALL:NS=151.201.64.0/24:ALL +#gil.net and firstgear.com +noto:207.100.79.0/24:ALL:ALL +noto:NS=207.100.79.0/24:ALL:ALL +noto:ALL:NS=207.100.79.0/24:ALL +#ultramax.net and friends +noto:207.201.213.0/24:ALL:ALL +noto:NS=207.201.213.0/24:ALL:ALL +noto:ALL:NS=207.201.213.0/24:ALL +#t-1net.com +noto:208.21.213.0/24:ALL:ALL +noto:NS=208.21.213.0/24:ALL:ALL +noto:ALL:NS=208.21.213.0/24:ALL +#ezmoney.com and pals +noto:204.212.245.0/24:ALL:ALL +noto:NS=204.212.245.0/24:ALL:ALL +noto:ALL:NS=204.212.245.0/24:ALL +#mail-response, hitrus, etc. +noto:209.136.134.0/24:ALL:ALL +noto:NS=209.136.134.0/24:ALL:ALL +noto:ALL:NS=209.136.134.0/24:ALL +#nevwest - the next generation, via ACSI. +noto:209.12.111.0/23:ALL:ALL +noto:NS=209.12.111.0/23:ALL:ALL +noto:ALL:NS=209.12.111.0/23:ALL +#gtwinc, gmds.com - spamhaus +noto:207.201.213.0/24 206.98.109.0/24:ALL:ALL +noto:NS=207.201.213.0/24 NS=206.98.109.0/24:ALL:ALL +noto:ALL:NS=207.201.213.0/24 NS=206.98.109.0/24:ALL +#goplay.com, mpx.com - many, many spams +noto:199.74.206.0/24:ALL:ALL +noto:NS=199.74.206.0/24:ALL:ALL +noto:ALL:NS=199.74.206.0/24:ALL +#silkspin.com spamhaus +noto:151.196.90.0/24 151.196.69.0/24:ALL:ALL +noto:NS=151.196.90.0/24 NS=151.196.69.0/24:ALL:ALL +noto:ALL:NS=151.196.90.0/24 NS=151.196.69.0/24:ALL +#uplinkpro.com +noto:206.30.95.0/24:ALL:ALL +noto:NS=206.30.95.0/24:ALL:ALL +noto:ALL:NS=206.30.95.0/24:ALL +#excite.com mailexcite.com +noto:198.3.102.0/24 198.3.98.0/24:ALL:ALL +noto:NS=198.3.102.0/24 NS=198.3.98.0/24:ALL:ALL +noto:ALL:NS=198.3.102.0/24 NS=198.3.98.0/24:ALL + # dump things with a bogus rhs to a FROM: addresses. usually spammers Common subdirectories: smtpd-2.0-orig/contrib and smtpd-2.0/contrib diff -b -B --unified smtpd-2.0-orig/smtp.h smtpd-2.0/smtp.h --- smtpd-2.0-orig/smtp.h Wed Oct 6 02:35:03 1999 +++ smtpd-2.0/smtp.h Wed Oct 6 02:34:43 1999 @@ -1,7 +1,7 @@ /* * Obtuse smtp store/forward daemon include file * - * $Id: smtpd-2.0-drt-0.1.patch 750 2005-08-13 20:28:39Z md $ + * $Id: smtpd-2.0-drt-0.1.patch 750 2005-08-13 20:28:39Z md $ * * Copyright (c) 1996, 1997 Obtuse Systems Corporation. All rights * reserved. @@ -86,3 +86,5 @@ long location; /* start of RCPT line in spoolfile */ struct smtp_victim * next; }; + +extern int accumlog(int level, const char *fmt, ...); Only in smtpd-2.0: smtpd.8 diff -b -B --unified smtpd-2.0-orig/smtpd.c smtpd-2.0/smtpd.c --- smtpd-2.0-orig/smtpd.c Wed Oct 6 02:35:03 1999 +++ smtpd-2.0/smtpd.c Thu Oct 7 15:38:40 1999 @@ -2,7 +2,8 @@ * smtpd, Obtuse SMTP daemon, storing agent. does simple collection of * mail messages, for later forwarding by smtpfwdd. * - * $Id: smtpd-2.0-drt-0.1.patch 750 2005-08-13 20:28:39Z md $ + * oldrcsId: smtpd.c,v 1.8 1999/05/25 16:40:55 millert Exp + * $Id: smtpd-2.0-drt-0.1.patch 750 2005-08-13 20:28:39Z md $ * * Copyright (c) 1996, 1997 Obtuse Systems Corporation. All rights * reserved. @@ -36,11 +37,16 @@ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * $Log: smtpd.c,v $ + * Revision 1.1 1999/10/07 12:58:49 drt + * Initial revision + * + * */ char *obtuse_copyright = "Copyright 1996 - Obtuse Systems Corporation - All rights reserved."; -char *obtuse_rcsid = "$Id: smtpd-2.0-drt-0.1.patch 750 2005-08-13 20:28:39Z md $"; +char *obtuse_rcsid = "$Id: smtpd-2.0-drt-0.1.patch 750 2005-08-13 20:28:39Z md $"; #include #include @@ -58,7 +64,9 @@ #include #include #ifdef IRIX_BROKEN_INCLUDES -/* IRIX 5.3 defines EX_OK (see sysexits.h) as something very strange in unistd.h :-) */ +/* + IRIX 5.3 defines EX_OK (see sysexits.h) as something very strange in unistd.h :-) + */ #ifdef EX_OK #undef EX_OK #endif @@ -92,8 +100,11 @@ #include "smtp.h" #include "smtpd.h" #ifdef BROKEN_SUN_INCLUDES -/* SunOS 5.5 doesn't seem to want to prototype this anywhere - Sigh */ +/* + SunOS 5.5 doesn't seem to want to prototype this anywhere - Sigh + */ extern int gethostname(char *name, int len); + #endif #ifndef READ_TIMEOUT @@ -116,6 +127,15 @@ #define SPOOLSUBDIR "." #endif +#ifndef LISTENPORT +#define LISTENPORT 25 +#endif + +#ifndef SMTPDSYSLOGSTR +#define SMTPDSYSLOGSTR "smtpd" +#endif + + #ifndef LOG_FACILITY #define LOG_FACILITY LOG_MAIL #endif @@ -138,10 +158,14 @@ char *current_from_mailpath = NULL; char *client_claimed_name = "UNKNOWN"; char *spoolfile = NULL; -char *spooldir = SPOOLSUBDIR; /* this is relative to our chroot. */ +char *spooldir = SPOOLSUBDIR; /* + + this is relative to our chroot. + */ int read_timeout = READ_TIMEOUT; -int maxsize = 0; +long maxsize = 0; int outfd, replyfd; + #ifdef SUNOS_GETOPT extern char *optarg; extern int optind; @@ -154,6 +180,20 @@ int Paranoid_Smtp = PARANOID_SMTP; int Paranoid_Dns = PARANOID_DNS; int exiting = 0; +int VerboseSyslog = 1; + +#ifndef SMTPD_PID_DIR +#if defined(OpenBSD) || defined(FreeBSD) || defined(NetBSD) +#define SMTPD_PID_DIR "/var/run" +#else +#define SMTPD_PID_DIR SPOOLDIR +#endif +#endif + +#ifndef SMTPD_PID_FILENAME +#define SMTPD_PID_FILENAME "smtpd.pid" +#endif + /* * Generate the usual cryptic usage statement @@ -167,15 +207,37 @@ fprintf(stderr, "this version of smtpd was compiled without command line option support\n"); #else fprintf(stderr, "usage: smtpd [-c chrootdir] [-d spooldir] [-u user] [-g group]\n"); - fprintf(stderr, " [-m maxsize] [-H] [-P] [-D]\n"); -#endif /* NO_LINE_OPTIONS */ + fprintf(stderr, " [-s maxsize] [-p port] [-l ip] [-i pidfile] [-m myname]Sample\n"); + fprintf(stderr, " [-q] [-H] [-L] [-P] [-D] [-F]\n"); + fprintf(stderr, "\n\t -c \t chroot to \n"); + fprintf(stderr, "\t -d \t use spooldir \n"); + fprintf(stderr, "\t -u \t switch to \n"); + fprintf(stderr, "\t -g \t switch to \n"); + fprintf(stderr, "\t -s \t don't accept messages bigger than \n"); + fprintf(stderr, "\t -p \t bind to \n"); + fprintf(stderr, "\t -l \t bind to \n"); + fprintf(stderr, "\t -i \t write PID to \n"); + fprintf(stderr, "\t -m \t set local hostname to \n"); + fprintf(stderr, "\t -q \t don't brabble too much to syslog\n"); + fprintf(stderr, "\t -H \t disable hostchecks\n"); + fprintf(stderr, "\t -L \t don't reopen syslog when forking\n"); + fprintf(stderr, "\t -P \t be paranoid\n"); + fprintf(stderr, "\t -D \t run in daemon mode instead of inetd mode\n"); + fprintf(stderr, "\t -F \t don't fork into background (implies -D)\n"); +#endif /* + NO_LINE_OPTIONS + */ } #if CHECK_ADDRESS -char * make_check_fail_reply(char *user, char *host, char *hostIP, +char * +make_check_fail_reply(char *user, char *host, char *hostIP, char *from, char *to, char *msg) { - static char replybuf[512]; /* static buffer that returns reply */ + static char replybuf[512]; /* + + static buffer that returns reply + */ char *c; int i = 0; int bogus = 0; @@ -191,24 +253,30 @@ } c = msg; if (!isdigit(*c)) { - /* do some very rudimentary checking. beyond this hope they + /* + do some very rudimentary checking. beyond this hope they * know what they're doing */ - syslog(LOG_ERR, "Reply message doesn't start with numeric code" ); + syslog(LOG_ERR, "Reply message doesn't start with numeric code"); bogus = 1; } - - while (*c != '\0' && !bogus && i<512) { + while (*c != '\0' && !bogus && i < 512) { if (*c != '%') { - replybuf[i]=*c; + replybuf[i] = *c; c++; i++; - } - else { + } else { char *add; int len; + c++; switch (*c) { + case '%': + add = "%"; + break; + case 'C': + add = ":"; + break; case 'F': add = from; break; @@ -234,22 +302,21 @@ if (len > 128) { syslog(LOG_NOTICE, "Very long (%d bytes) value obtained for %%%c in reply message", len, *c); } - if (len+i >= 512) { + if (len + i >= 512) { syslog(LOG_ERR, "reply message too long - truncating at 512 bytes"); } - strncpy(replybuf+i, add, 511 - i); - replybuf[511]='\0'; + strncpy(replybuf + i, add, 511 - i); + replybuf[511] = '\0'; i = strlen(replybuf); c++; } } if (!bogus) { - replybuf[(i<512)?i:511] = '\0'; - return(replybuf); - } - else { + replybuf[(i < 512) ? i : 511] = '\0'; + return (replybuf); + } else { msg = "550 Recipient not allowed"; - return(msg); + return (msg); } } #endif @@ -392,11 +459,13 @@ flush_smtp_mbuf(struct smtp_mbuf *buf, int fd, int len) { int foo = 0; - static int deaththroes=0; + static int deaththroes = 0; if (deaththroes) { - return; /* We've already had a write barf. Don't try again */ + return; /* + We've already had a write barf. Don't try again + */ } if (len <= buf->offset) { while (foo < len) { @@ -405,7 +474,7 @@ i = write(fd, (buf->data) + foo, len); if (i < 0) { syslog(LOG_INFO, "write failed: (%m)"); - deaththroes=1; + deaththroes = 1; smtp_exit(EX_OSERR); } foo += i; @@ -421,7 +490,7 @@ } } } else { - syslog(LOG_CRIT, "You can't write %d bytes from a buffer with only %d in it!", len, buf->offset); + syslog(LOG_CRIT, "You can't write %d bytes from a buffer with only %d in it!", len, (int) buf->offset); } } @@ -509,7 +578,7 @@ * let's hope there is enough to syslog :-) */ syslog(LOG_CRIT, "malloc said no to a %d byte buffer!", - (mbuf->size + len + 1024)); + (int) (mbuf->size + len + 1024)); return (0); } } @@ -545,7 +613,7 @@ * let's hope there is enough to syslog :-) */ syslog(LOG_ERR, "malloc said no to a %d byte buffer!", - (mbuf->size + len + 1024)); + (int) (mbuf->size + len + 1024)); errno = ENOMEM; return (-1); } @@ -553,6 +621,8 @@ /* * buffer is now big enough */ + + fflush(NULL); signal(SIGALRM, read_alarm_timeout); alarm(read_timeout); howmany = read(fd, mbuf->tail, len); @@ -614,12 +684,13 @@ */ #if USE_MKSTEMP - /* If someone does manage to misconfigure us so people have + /* + If someone does manage to misconfigure us so people have * access to the spool dir they probably have worse things to * worry about than the race condition but.. Oh well, keeps gcc * from complaining. */ - spoolfile= (char *) malloc(strlen(spooldir)+13); + spoolfile = (char *) malloc(strlen(spooldir) + 13); if (spoolfile == NULL) { syslog(LOG_CRIT, "Couldn't make a unique filename for spooling!"); smtp_exit(EX_CONFIG); @@ -628,28 +699,34 @@ strncat(spoolfile, "/smtpdXXXXXX", 12); if ((fd = mkstemp(spoolfile)) < 0) { syslog(LOG_CRIT, "Couldn't create spool file %s!", spoolfile); + free(spoolfile); + spoolfile = NULL; smtp_exit(EX_CONFIG); } -#else /* USE_MKSTEMP */ - /* gcc will bitch about this. There's nothing wrong with it where +#else /* + USE_MKSTEMP + */ + /* + gcc will bitch about this. There's nothing wrong with it where * we are using it (not in /tmp). There shouldn't be a race condition * since nothing other than smtpd should be using this spool dir, or * have access to it if it is permitted correctly. */ { char *cp; - cp=tempnam(spooldir, "smtpd"); + + cp = tempnam(spooldir, "smtpd"); if (cp == NULL) { syslog(LOG_CRIT, "Couldn't make a unique filename for spooling!"); smtp_exit(EX_CONFIG); } + spoolfile = (char *) malloc((strlen(spooldir) + strlen(cp) + 1) * sizeof(char)); - spoolfile=(char *) malloc((strlen(spooldir)+strlen(cp)+1) * sizeof(char)); if (spoolfile == NULL) { syslog(LOG_CRIT, "Malloc failed"); smtp_exit(EX_TEMPFAIL); } - spoolfile[0]='\0'; + spoolfile[0] = '\0'; /* * some versions of tempnam() with a spooldir give you a "/" in @@ -660,7 +737,9 @@ */ if (strncmp(cp, spooldir, strlen(spooldir)) != 0) { - /* looks like we don't have the spool directory on the front */ + /* + looks like we don't have the spool directory on the front + */ strcpy(spoolfile, spooldir); } strcat(spoolfile, cp); @@ -670,7 +749,9 @@ syslog(LOG_CRIT, "Couldn't create spool file %s!", spoolfile); smtp_exit(EX_CONFIG); } -#endif /* USE_MKSTEMP */ +#endif /* + USE_MKSTEMP + */ #ifdef USE_LOCKF if (lockf(fd, F_LOCK, 0) != 0) { @@ -773,31 +854,34 @@ * we're leaving the client hanging. attempt to tell them we're * going away */ - if (exiting++<1) { + if (exiting++ < 1) { writereply(reply_buf, 421, 0, m421msg, NULL); } - /* * if we have an open spool file that's unclosed, blast it out of * existence */ - if (exiting++<2) { + if (exiting++ < 2) { if (spoolfile != NULL) { smtp_nuke_spoolfile(outfd); } } } else { - if (exiting++<1) { + if (exiting++ < 1) { if (spoolfile != NULL) { smtp_close_spoolfile(outfd); exiting++; } } } - if (exiting++<3) { + if (exiting++ < 3) { flush_smtp_mbuf(reply_buf, replyfd, reply_buf->offset); } - + if (!VerboseSyslog) { + accumlog(LOG_INFO, 0); /* + flush? + */ + } exit(val); } @@ -957,7 +1041,12 @@ *dst++ = '^'; *dst++ = '='; } - if (isalnum(ch) || strchr(" -,:=.@_!<>()[]/+%", ch) != NULL) { + /* + * RFC822 allows both ' and " in local-part. + * " is infact _required_ if local-part contains spaces as is + * common in x400 (yuk). + */ + if (isalnum(ch) || strchr(" -,:=.@_!<>()[]/+%'\"", ch) != NULL) { if (firstone && (ch == '-')) { arg_attempt = 1; *dst++ = '^'; @@ -1036,22 +1125,6 @@ /* - * does string s look like a source routed mail address? - */ - -int -is_src_route(const unsigned char *s) -{ - while (*s != '\0') { - if ( (*s == '%') || (*s == '!') ) - return 1; - s++; - } - return 0; -} - - -/* * is smtp command "cmd" legal in state "state" */ int @@ -1063,7 +1136,7 @@ return (!(test_state(OK_HELO, state))); #if EHLO_KLUDGE case EHLO: - return(test_state(OK_EHLO, state)); + return (test_state(OK_EHLO, state)); #endif case MAIL: if (test_state(OK_HELO, state) && (!test_state(OK_MAIL, state))) @@ -1305,7 +1378,8 @@ verb[4] = '\0'; buf = inbuf + 4; - /* The basic vanilla SMTP commands, minimum as specified in RFC 821; + /* + The basic vanilla SMTP commands, minimum as specified in RFC 821; * HELO, MAIL, RCPT, DATA, RSET, NOOP, QUIT. Added minimal VRFY * after rumors (never substantiated) that some mail agents might * try it thanks to RFC 1123. We don't bother checking address @@ -1375,8 +1449,19 @@ /* * log the connection */ + if (VerboseSyslog) { syslog(LOG_INFO, "SMTP HELO from %s(%s) as \"%s\"", - peerinfo.peer_clean_reverse_name, peerinfo.peer_ok_addr, client_claimed_name); + peerinfo.peer_clean_reverse_name, + peerinfo.peer_ok_addr, client_claimed_name); + } else { + accumlog(LOG_INFO, 0); /* + flush anything left + */ + accumlog(LOG_INFO, "relay=%s/%s", + peerinfo.peer_clean_reverse_name, peerinfo.peer_ok_addr); + if (strcasecmp(peerinfo.peer_clean_reverse_name, client_claimed_name)) + accumlog(LOG_INFO, " as \"%s\"", client_claimed_name); + } state_change(state, HELO, SUCCESS); } else if (strcasecmp(verb, "MAIL") == 0) { if (!cmd_ok(MAIL, state)) { @@ -1407,15 +1492,27 @@ } buf += 5; SPANBLANK(buf); + /* + * if local-part contains ", then spaces are allowed + */ cp = NULL; - cp = strchr(buf, ' '); + if (buf[0] == '"' || buf[1] == '"') + cp = strrchr(buf, '"'); /* + REVISIT: find last " + */ + if (cp == NULL) + cp = buf + 1; + cp = strchr(cp + 1, ' '); if (cp != NULL) { - /* stuff on the end */ + /* + stuff on the end + */ *cp = '\0'; cp++; SPANBLANK(cp); if (*cp != '\0') { - /* We could deal with ESMTP SIZE here. If so it's either + /* + We could deal with ESMTP SIZE here. If so it's either * OK or bogus, in which we have to return 555. * * Without ESMTP. this is crud on the end, and we give 501 @@ -1433,7 +1530,6 @@ syslog(LOG_ERR, "Malloc failed, abandoning session."); smtp_exit(EX_OSERR); } - if (strcmp(buf, current_from_mailpath) != 0) { syslog(LOG_ALERT, "Suspicious characters in FROM: address from host %s(%s), cleaned to %s", peerinfo.peer_clean_reverse_name, peerinfo.peer_ok_addr, current_from_mailpath); @@ -1453,8 +1549,12 @@ /* * log the connection */ - syslog(LOG_INFO, "mail from %s", - current_from_mailpath); + if (VerboseSyslog) { + syslog(LOG_INFO, "mail from %s", current_from_mailpath); + } else { + accumlog(LOG_INFO, " from=%s", current_from_mailpath); + } + /* * put our output in the outbuf */ @@ -1468,7 +1568,7 @@ } } else if (strcasecmp(verb, "RCPT") == 0) { char *victim; - int badrcpt=0; + int badrcpt = 0; if (!cmd_ok(RCPT, state)) { writereply(replybuf, 554, 0, m554nofrom, NULL); @@ -1498,10 +1598,21 @@ } buf += 3; SPANBLANK(buf); + /* + * if local-part contains ", then spaces are allowed + */ cp = NULL; - cp = strchr(buf, ' '); + if (buf[0] == '"' || buf[1] == '"') + cp = strrchr(buf, '"'); /* + REVISIT: find last " + */ + if (cp == NULL) + cp = buf; + cp = strchr(cp + 1, ' '); if (cp != NULL) { - /* stuff on the end */ + /* + stuff on the end + */ *cp = '\0'; cp++; SPANBLANK(cp); @@ -1536,8 +1647,10 @@ { char *deathmsg = NULL; + if (NoHostChecks) { - /* It's just possible that someone will be trying to do this + /* + It's just possible that someone will be trying to do this * without having the DNS lookup checks on. Sigh.. * As a minimum for the lookups we need to know who we are * and who is at the other end. meaning we must have @@ -1565,8 +1679,8 @@ exit(EX_CONFIG); } } - - /* We may have a username passed down in the environment from + /* + We may have a username passed down in the environment from * our caller if they did an ident. Juniperd in particular may * pass a JUNIPER_IDENT, which will have been cleaned by * the cleanitup() routine, and will be "UNKNOWN" if no value @@ -1582,8 +1696,8 @@ } peerinfo.peer_dirty_ident = peerinfo.peer_clean_ident; } - - /* otherwise, allow our invoker to pass us in an ident value in the + /* + otherwise, allow our invoker to pass us in an ident value in the * environment as SMTPD_IDENT. (for people who do this with the tcp * wrapper.)We must however, clean the string. */ @@ -1593,8 +1707,7 @@ if (peerinfo.peer_dirty_ident != NULL) { if (strcmp(peerinfo.peer_dirty_ident, "UNKNOWN") == 0) { peerinfo.peer_dirty_ident = NULL; - } - else { + } else { peerinfo.peer_clean_ident = strdup(cleanitup(peerinfo.peer_dirty_ident)); if (peerinfo.peer_clean_ident == NULL) { @@ -1604,19 +1717,32 @@ } } } - switch (smtpd_addr_check( CHECK_FILE, + switch (smtpd_addr_check(CHECK_FILE, &peerinfo, current_from_mailpath, victim, - &deathmsg) ) { + &deathmsg)) { case 1: - /* we matched an "allow" rule - continue */ + /* + we matched an "allow" rule - continue + */ break; case 0: - /* we matched a "deny" rule. syslog and send back failure message */ - syslog(LOG_INFO, "Forbidden FROM or RCPT for host %s(%s) - Abandoning session", peerinfo.peer_clean_reverse_name, peerinfo.peer_ok_addr); + /* + we matched a "deny" rule. syslog and send back failure message + */ + if (VerboseSyslog) { + syslog(LOG_INFO, "Forbidden FROM or RCPT for host %s(%s) - Abandoning session", + peerinfo.peer_clean_reverse_name, peerinfo.peer_ok_addr); + } else { + accumlog(LOG_INFO, " forbidden FROM or RCPT"); + accumlog(LOG_INFO, 0); /* + flush it + */ + } { char *c; + c = make_check_fail_reply(peerinfo.peer_clean_ident, peerinfo.peer_clean_reverse_name, peerinfo.peer_ok_addr, @@ -1628,12 +1754,17 @@ } } smtp_exit(EX_PROTOCOL); - break;; /* notreached */ + break;; /* + notreached + */ case -1: - /* we matched a "noto" rule. send message, and set state */ + /* + we matched a "noto" rule. send message, and set state + */ { char *c; + c = make_check_fail_reply(peerinfo.peer_clean_ident, peerinfo.peer_clean_reverse_name, peerinfo.peer_ok_addr, @@ -1645,7 +1776,12 @@ } } badrcpt = 1; + + if (VerboseSyslog) { syslog(LOG_INFO, "Discarded bad recipient %s", victim); + } else { + accumlog(LOG_INFO, " discarded bad recipient=%s", victim); + } state_change(state, RCPT, ERROR); break; @@ -1654,7 +1790,9 @@ abort(); } } -#endif /* CHECK_ADDRESS */ +#endif /* + CHECK_ADDRESS + */ if (!badrcpt) { writereply(replybuf, 250, 0, "recipient ", @@ -1666,7 +1804,11 @@ /* * log the recipient. */ + if (VerboseSyslog) { syslog(LOG_INFO, "Recipient %s", victim); + } else { + accumlog(LOG_INFO, " to=%s", victim); + } if (write_smtp_mbuf(outbuf, "RCPT ", strlen("RCPT ")) && write_smtp_mbuf(outbuf, victim, strlen(victim)) && write_smtp_mbuf(outbuf, "\n", 1)) { @@ -1677,9 +1819,15 @@ } free(victim); } else if (strcasecmp(verb, "NOOP") == 0) { + syslog(LOG_NOTICE, + "NOOP command from %s(%s), name %s", + peerinfo.peer_clean_reverse_name, peerinfo.peer_ok_addr, client_claimed_name); writereply(replybuf, 250, 0, m250msg, NULL); state_change(state, NOOP, SUCCESS); } else if (strcasecmp(verb, "VRFY") == 0) { + syslog(LOG_NOTICE, + "VRFY command from %s(%s), name %s", + peerinfo.peer_clean_reverse_name, peerinfo.peer_ok_addr, client_claimed_name); writereply(replybuf, 252, 0, m252msg, NULL); state_change(state, NOOP, SUCCESS); } else if (strcasecmp(verb, "DEBU") == 0) { @@ -1739,7 +1887,7 @@ /* * initial message size */ - max = (*size ? *size : INT_MAX); + max = (*size ? *size : LONG_MAX); /* @@ -1749,12 +1897,12 @@ * the program will probably die and the bug will (hopefully) get fixed). */ - buf = alloc_smtp_mbuf(64); + buf = alloc_smtp_mbuf(1024); if (buf == NULL) { syslog(LOG_DEBUG, "Couldn't allocate input buffer for data command"); return (5); } - outbuf = alloc_smtp_mbuf(64); + outbuf = alloc_smtp_mbuf(1024); if (outbuf == NULL) { syslog(LOG_DEBUG, "Couldn't allocate output buffer for data command"); return (5); @@ -1768,11 +1916,20 @@ snarfed = read_smtp_mbuf(buf, in, 1024); if (snarfed < 0) { + if (VerboseSyslog) { syslog(LOG_INFO, "read error receiving message body: %m"); + } else { + accumlog(LOG_INFO, " read error receiving message body: %s", + strerror(errno)); + } return (2); } if (snarfed == 0) { + if (VerboseSyslog) { syslog(LOG_INFO, "EOF while receiving message body"); + } else { + accumlog(LOG_INFO, " EOF while receiving message body"); + } return (2); } if (outbuf->size < buf->size) { @@ -1809,34 +1966,31 @@ */ if (!body) { if (buf->data[linestart] == LF || - (buf->data[linestart] == '\r' && buf->data[linestart+1] == LF)) - { + (buf->data[linestart] == '\r' && buf->data[linestart + 1] == LF)) { body = 1; - } else - { + } else { char *p; - int off=0; + int off = 0; int unprintable = 0; - for (p=buf->data+linestart; *p != LF; p++) - { - /* add isalpha(), to allow for non + + for (p = buf->data + linestart; *p != LF; p++) { + /* + add isalpha(), to allow for non * conventional locales. where * isalpha != isprint. */ if (!isalpha(*p) && !isprint(*p) && - !isspace(*p)) - { - syslog(LOG_DEBUG, "Unprintable character value=%d in message header at offset %d", (int)*p, off); - *p='?'; + !isspace(*p)) { + syslog(LOG_DEBUG, "Unprintable character value=%d in message header at offset %d", (int) *p, off); + *p = '?'; unprintable++; } off++; } - if (unprintable) - { - buf->data[lineend]='\0'; - syslog(LOG_ALERT, "%d unprintable characters in \"%.255s\"", unprintable, buf->data+linestart); - buf->data[lineend]=LF; + if (unprintable) { + buf->data[lineend] = '\0'; + syslog(LOG_ALERT, "%d unprintable characters in \"%.255s\"", unprintable, buf->data + linestart); + buf->data[lineend] = LF; if (Paranoid_Smtp) { syslog(LOG_CRIT, "Abandoning session from %s(%s) due to unprintable message header", peerinfo.peer_clean_reverse_name, peerinfo.peer_ok_addr); @@ -1844,8 +1998,8 @@ } } if (lineend - linestart > 255) { - syslog(LOG_ALERT, "unusually long header (trucated) [%d bytes] = \"%.255s\"...", lineend-linestart, buf->data+linestart); - buf->data[linestart+255]=LF; + syslog(LOG_ALERT, "unusually long header (trucated) [%d bytes] = \"%.255s\"...", lineend - linestart, buf->data + linestart); + buf->data[linestart + 255] = LF; lineend = linestart + 255; } } @@ -1945,24 +2100,40 @@ * The brains of this operation */ -void +int main(int argc, char **argv) { int opt; - char *optstring = "xc:d:u:s:g:m:HPDL"; + long smtp_port = LISTENPORT; + char *optstring = "l:p:q:d:u:s:g:m:i:c:HPDLF"; int i, k; - smtp_state_set last_state_s, current_state_s; /* The real state vector. */ - smtp_state last_state, current_state; /* Pointers to the state vector. */ + smtp_state_set last_state_s, current_state_s; /* + + The real state vector. + */ + smtp_state last_state, current_state; /* + + Pointers to the state vector. + */ char *chrootdir = SPOOLDIR; char *username = SMTP_USER; char *groupname = SMTP_GROUP; struct passwd *user = NULL; struct group *group = NULL; - struct sigaction new_sa, old_sa; + struct sigaction new_sa; int daemon_mode = 0; - int listen_fd = -1; /* make gcc be quiet */ - int child_no_openlog = 0; /* don't openlog() in children - use inherited + int dont_fork = 0; + int listen_fd = -1; /* + + make gcc be quiet + */ + int pid_fd = -1; + char *pid_fname = NULL; + struct in_addr listen_addr; + int child_no_openlog = 0; /* + + don't openlog() in children - use inherited * parent fd */ @@ -1971,12 +2143,15 @@ peerinfo.peer_clean_reverse_name = "UNKNOWN"; peerinfo.peer_ok_addr = ""; - umask (077); + umask(077); - openlog("smtpd", LOG_PID | LOG_NDELAY, LOG_FACILITY); + openlog(SMTPDSYSLOGSTR, LOG_PID | LOG_NDELAY, LOG_FACILITY); + listen_addr.s_addr = INADDR_ANY; #if SET_LOCALE - /* try to set our localization to the one specified */ + /* + try to set our localization to the one specified + */ (void) setlocale(LC_CTYPE, LOCALIZATION); #endif @@ -1990,10 +2165,48 @@ #ifdef GETOPT_EOF while ((opt = getopt(argc, argv, optstring)) != EOF) { #else - while ((opt = getopt(argc, argv, optstring)) > 0) { + while ((opt = getopt(argc, argv, optstring)) != -1) { #endif switch (opt) { + case 'p': + { + char *foo; + + smtp_port = strtol(optarg, &foo, 10); + syslog(LOG_DEBUG, "I am requested to listen on port %d", smtp_port); + if (*foo != '\0') { + /* + this doesn't smell like a number. Bail + */ + syslog(LOG_ERR, "Invalid port argument for the \"-p\" option"); + show_usage(); + exit(EX_USAGE); + } + } + break; + case 'l': + listen_addr.s_addr = inet_addr(optarg); + syslog(LOG_DEBUG, "I am requested to listen on interface \"%s\"", optarg); + if (listen_addr.s_addr == htonl(INADDR_NONE)) { + syslog(LOG_ERR, "Invalid ip address given for the \"-l\" option"); + show_usage(); + exit(EX_USAGE); + } + break; + case 'i': + syslog(LOG_DEBUG, "I am requested to write PID to \"%s\"", optarg); + if (optarg[0] != '/') { + syslog(LOG_ERR, "The \"-i\" option requires an absolute pathname argument\n"); + show_usage(); + exit(EX_USAGE); + } + pid_fname = optarg; + break; + case 'q': + VerboseSyslog = 0; + break; case 'c': + syslog(LOG_DEBUG, "I am requested to chroot to \"%s\"", optarg); if (optarg[0] != '/') { syslog(LOG_ERR, "The \"-c\" option requires an absolute pathname argument\n"); show_usage(); @@ -2002,12 +2215,20 @@ chrootdir = optarg; break; case 'D': + syslog(LOG_DEBUG, "I am requested to start as daemon"); + daemon_mode = 1; + break; + case 'F': + syslog(LOG_DEBUG, "I am requested to daemonize and not to fork into background"); daemon_mode = 1; + dont_fork = 1; break; case 'L': + syslog(LOG_DEBUG, "I am requested to keep my children from reopening syslog"); child_no_openlog = 1; break; case 'm': + syslog(LOG_DEBUG, "I am requested to set my hostname to \"%s\"", optarg); peerinfo.my_clean_reverse_name = optarg; break; case 'H': @@ -2020,8 +2241,9 @@ syslog(LOG_INFO, "smtpd running in Paranoid mode"); break; case 'd': + syslog(LOG_DEBUG, "I am requested to use spooldir \"%s\"", optarg); if (optarg[0] != '/') { - syslog(LOG_ERR, "%s, The \"-d\" option requires an absolute pathname argument\n", optarg); + syslog(LOG_ERR, "%s, The \"-d\" option requires an absolute pathname argument", optarg); show_usage(); exit(EX_USAGE); } @@ -2032,6 +2254,8 @@ long userid; char *foo; + syslog(LOG_DEBUG, "I am requested to use uid \"%s\"", optarg); + userid = strtol(optarg, &foo, 10); if (*foo == '\0') { /* @@ -2040,7 +2264,7 @@ */ user = getpwuid((uid_t) userid); if (user == NULL) { - syslog(LOG_ERR, "Invalid uid argument for the \"-u\" option, no user found for uid %s\n", optarg); + syslog(LOG_ERR, "Invalid uid argument for the \"-u\" option, no user found for uid %s", optarg); show_usage(); exit(EX_USAGE); } @@ -2052,7 +2276,7 @@ */ user = getpwnam(optarg); if (user == NULL) { - syslog(LOG_ERR, "Invalid username argument for the \"-u\" option, no user found for name %s\n", optarg); + syslog(LOG_ERR, "Invalid username argument for the \"-u\" option, no user found for name %s", optarg); show_usage(); exit(EX_USAGE); } @@ -2065,6 +2289,8 @@ long grpid; char *foo; + syslog(LOG_DEBUG, "I am requested to use gid \"%s\"", optarg); + grpid = strtol(optarg, &foo, 10); if (*foo == '\0') { /* @@ -2073,7 +2299,7 @@ */ group = getgrgid((gid_t) grpid); if (group == NULL) { - syslog(LOG_ERR, "Invalid gid argument for the \"-g\" option, no group found for gid %s\n", optarg); + syslog(LOG_ERR, "Invalid gid argument for the \"-g\" option, no group found for gid %s", optarg); show_usage(); exit(EX_USAGE); } @@ -2085,7 +2311,7 @@ */ group = getgrnam(optarg); if (group == NULL) { - syslog(LOG_ERR, "Invalid groupname argument for the \"-g\" option, no group found for name %s\n", optarg); + syslog(LOG_ERR, "Invalid groupname argument for the \"-g\" option, no group found for name %s", optarg); show_usage(); exit(EX_USAGE); } @@ -2097,27 +2323,31 @@ { char *foo; + syslog(LOG_DEBUG, "I am requested to accept only messages smaller than \"%s\"", optarg); + maxsize = strtol(optarg, &foo, 10); if (*foo != '\0') { - syslog(LOG_ERR, "The \"-s\" option requires a size argument\n"); + syslog(LOG_ERR, "The \"-s\" option requires a size argument"); show_usage(); exit(EX_USAGE); } if (maxsize <= 0) { - syslog(LOG_ERR, "\"-s\" argument must be positive!\n"); + syslog(LOG_ERR, "\"-s\" argument must be positive!"); show_usage(); exit(EX_USAGE); } } break; default: - syslog(LOG_ERR, "Unknown option \"-%c\"\n", opt); + syslog(LOG_ERR, "Unknown option \"-%c\"", opt); show_usage(); exit(EX_USAGE); break; } } -#endif /* NO_COMMANDLINE_OPTIONS */ +#endif /* + NO_COMMANDLINE_OPTIONS + */ /* * OK, got my options, now change uid/gid @@ -2137,8 +2367,8 @@ */ user = getpwuid((uid_t) userid); if (user == NULL) { - syslog(LOG_ERR, "Eeek! I was compiled to run as uid %s, but no user found for uid %s\n", username, username); - syslog(LOG_ERR, "Please recompile me to use a valid user, or specify one with the \"-u\" option.\n"); + syslog(LOG_ERR, "Eeek! I was compiled to run as uid %s, but no user found for uid %s", username, username); + syslog(LOG_ERR, "Please recompile me to use a valid user, or specify one with the \"-u\" option."); exit(EX_CONFIG); } username = user->pw_name; @@ -2149,8 +2379,8 @@ */ user = getpwnam(username); if (user == NULL) { - syslog(LOG_ERR, "Eeek! I was compiled to run as user \"%s\", but no user found for username \"%s\"\n", username, username); - syslog(LOG_ERR, "Please recompile me to use a valid user, or specify one with the \"-u\" option.\n"); + syslog(LOG_ERR, "Eeek! I was compiled to run as user \"%s\", but no user found for username \"%s\"", username, username); + syslog(LOG_ERR, "Please recompile me to use a valid user, or specify one with the \"-u\" option."); exit(EX_CONFIG); } username = user->pw_name; @@ -2171,8 +2401,8 @@ */ group = getgrgid((gid_t) grpid); if (group == NULL) { - syslog(LOG_ERR, "Eeek! I was compiled to run as gid %s, but no group found for gid %s\n", groupname, groupname); - syslog(LOG_ERR, "Please recompile me to use a valid group, or specify one with the \"-g\" option.\n"); + syslog(LOG_ERR, "Eeek! I was compiled to run as gid %s, but no group found for gid %s", groupname, groupname); + syslog(LOG_ERR, "Please recompile me to use a valid group, or specify one with the \"-g\" option."); exit(EX_CONFIG); } groupname = group->gr_name; @@ -2183,8 +2413,8 @@ */ group = getgrnam(groupname); if (group == NULL) { - syslog(LOG_ERR, "Eeek! I was compiled to run as group \"%s\", but no group found for groupname \"%s\"\n", groupname, groupname); - syslog(LOG_ERR, "Please recompile me to use a valid group, or specify one with the \"-g\" option.\n"); + syslog(LOG_ERR, "Eeek! I was compiled to run as group \"%s\", but no group found for groupname \"%s\"", groupname, groupname); + syslog(LOG_ERR, "Please recompile me to use a valid group, or specify one with the \"-g\" option."); exit(EX_CONFIG); } groupname = group->gr_name; @@ -2194,24 +2424,24 @@ * If we're here, we have a valid user and group to run as */ if (group == NULL || user == NULL) { - syslog(LOG_CRIT, "Didn't find a user or group, (Shouldn't happen)\n"); + syslog(LOG_CRIT, "Didn't find a user or group, (Shouldn't happen)"); abort(); } if (user->pw_uid == 0) { syslog(LOG_CRIT, "Sorry, I don't want to run as root! It's a bad idea!"); - syslog(LOG_CRIT, "Please recompile me to use a valid user, or specify one with the \"-u\" option.\n"); + syslog(LOG_CRIT, "Please recompile me to use a valid user, or specify one with the \"-u\" option."); exit(EX_CONFIG); } if (group->gr_gid == 0) { syslog(LOG_CRIT, "Sorry, I don't want to run as group 0. It's a bad idea!"); - syslog(LOG_CRIT, "Please recompile me to use a valid group, or specify one with the \"-g\" option.\n"); + syslog(LOG_CRIT, "Please recompile me to use a valid group, or specify one with the \"-g\" option."); exit(EX_CONFIG); } - if ( daemon_mode ) { + if (daemon_mode) { struct sockaddr_in sa; - listen_fd = socket(AF_INET,SOCK_STREAM,0); - if ( listen_fd < 0 ) { + listen_fd = socket(AF_INET, SOCK_STREAM, 0); + if (listen_fd < 0) { syslog(LOG_ERR, "Can't get a listen socket for daemon mode (%m)"); exit(EX_OSERR); } @@ -2215,21 +2445,22 @@ syslog(LOG_ERR, "Can't get a listen socket for daemon mode (%m)"); exit(EX_OSERR); } - memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; - sa.sin_port = htons(25); - sa.sin_addr.s_addr = INADDR_ANY; + sa.sin_port = htons(smtp_port); + sa.sin_addr.s_addr = listen_addr.s_addr; - /* Need to do this while we're still root */ + /* + Need to do this while we're still root + */ - if ( bind(listen_fd, (struct sockaddr *)&sa, sizeof(sa)) < 0 ) { - syslog(LOG_ERR, "Can't bind listen socket to port 25 in daemon mode (%m)"); + if (bind(listen_fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { + syslog(LOG_ERR, "Can't bind listen socket to port %ld in daemon mode (%m)", smtp_port); exit(EX_OSERR); } - } - /* we may have requested that children do not re-open syslogs in case + /* + we may have requested that children do not re-open syslogs in case * we haven't set up the chroot for dealing with them. in this case, * reopen the logs as the master to not show process id, (as to not * be misleading when child processes use the open fd for syslog). @@ -2241,7 +2472,24 @@ openlog("smtpd", LOG_NDELAY, LOG_FACILITY); syslog(LOG_INFO, "Log reopened."); } + if (daemon_mode) { + /* + open pid file fd while we're still root. + */ + if ((pid_fname == NULL) && + (((pid_fname = malloc(sizeof(SMTPD_PID_DIR) + + sizeof(SMTPD_PID_FILENAME) + 2))) + != NULL)) { + (void) sprintf(pid_fname, "%s/%s", SMTPD_PID_DIR, SMTPD_PID_FILENAME); + } + if (pid_fname != NULL) { + if ((pid_fd = open(pid_fname, O_CREAT | O_WRONLY, 0644)) < 0) { + syslog(LOG_ERR, "Couldn't create pid file %s: %m", pid_fname); + exit(EX_CONFIG); + } + } + } if (chrootdir != NULL) { if (chdir(chrootdir) != 0) { syslog(LOG_CRIT, "Couldn't chdir to directory %s! (%m)", @@ -2276,21 +2524,52 @@ * Ok, the world seems good. Should we run as a daemon? */ - if ( daemon_mode ) { + if (daemon_mode) { int failures; int rval; + /* + fork into background unless wa are asked not to do so + */ + + if (!dont_fork) { + syslog(LOG_DEBUG, "forking into background"); rval = fork(); - if ( rval > 0 ) { - /* Parent - just exit */ + if (rval > 0) { + /* + Parent - just exit + */ exit(EX_OK); - } else if ( rval < 0 ) { + } else if (rval < 0) { syslog(LOG_ERR, "Can't do first fork in daemon mode (%m)"); exit(EX_OSERR); } setsid(); + } + /* + write our pid into the (inherited) pid_fd + */ - if ( listen(listen_fd,10) < 0 ) { + if (pid_fd >= 0) { + char buf[80]; + +#ifdef USE_FLOCK + if (lockf(pid_fd, F_TLOCK, 0) != 0) +#else + if (flock(pid_fd, LOCK_EX | LOCK_NB) != 0) +#endif + { + syslog(LOG_ERR, + "Couldn't get lock on pid file %s! Am I already running?", pid_fname); + exit(1); + } + sprintf(buf, "%d\n", getpid()); + write(pid_fd, buf, strlen(buf)); + /* + do not close - leave this fd open to keep lock + */ + } + if (listen(listen_fd, 10) < 0) { syslog(LOG_ERR, "Can't listen on socket in daemon mode (%m)"); exit(EX_OSERR); } @@ -2294,9 +2573,9 @@ syslog(LOG_ERR, "Can't listen on socket in daemon mode (%m)"); exit(EX_OSERR); } - failures = 0; - syslog(LOG_INFO,"smtpd running in daemon mode - ready to accept connections"); + syslog(LOG_INFO, "smtpd running in daemon mode - ready to accept connectionson %s:%ld", inet_ntoa(listen_addr), smtp_port); + while (1) { int fd; @@ -2304,16 +2583,15 @@ struct sockaddr_in peer; int status; - while ( waitpid(0,&status,WNOHANG) > 0 ) - ; + while (waitpid(0, &status, WNOHANG) > 0); slen = sizeof(peer); - fd = accept(listen_fd, (struct sockaddr *)&peer, &slen); - if ( fd < 0 ) { - if ( failures++ < 10 ) { - syslog(LOG_INFO,"accept call failed in daemon mode (%m) - continuing"); + fd = accept(listen_fd, (struct sockaddr *) &peer, &slen); + if (fd < 0) { + if (failures++ < 10) { + syslog(LOG_INFO, "accept call failed in daemon mode (%m) - continuing"); } else { - syslog(LOG_ERR,"too many consecutive accept call failures in daemon mode (%m)"); + syslog(LOG_ERR, "too many consecutive accept call failures in daemon mode (%m)"); exit(EX_OSERR); } } else { @@ -2322,7 +2600,7 @@ failures = 0; rval = fork(); - if ( rval == 0 ) { + if (rval > 0) { /* * Parent - close the accepted fd and continue the loop @@ -2330,16 +2608,19 @@ close(fd); - } else if ( rval > 0 ) { + } else if (rval == 0) { /* * Child - make ourselves look like an inetd child * and break out of the loop to allow the regular inetd-style * processing to occur. */ + close(pid_fd); /* + we don't need this anymore + */ - dup2(fd,0); - dup2(fd,1); + dup2(fd, 0); + dup2(fd, 1); close(fd); if (!child_no_openlog) { closelog(); @@ -2360,19 +2641,21 @@ } } - - /* We need to ignore SIGPIPE */ + /* + We need to ignore SIGPIPE + */ #ifdef BSD_SIGNAL signal(SIGPIPE, SIG_IGN); #else + memset(&new_sa, 0, sizeof(new_sa)); new_sa.sa_handler = SIG_IGN; - (void)sigemptyset(&new_sa.sa_mask); + (void) sigemptyset(&new_sa.sa_mask); new_sa.sa_flags = SA_RESTART; #ifdef __linux__ new_sa.sa_restorer = NULL; #endif - if ( sigaction( SIGPIPE, &new_sa, &old_sa ) != 0 ) { - syslog(LOG_CRIT,"CRITICAL - sigaction failed (%m)"); + if (sigaction(SIGPIPE, &new_sa, NULL) != 0) { + syslog(LOG_CRIT, "CRITICAL - sigaction failed (%m)"); exit(EX_OSERR); } #endif @@ -2504,7 +2787,8 @@ * then grumble (and exit if paranoid mode is set). */ - /* Andreas Borchert noticed + /* + Andreas Borchert noticed * That I was using strcmp here instead of strcasecmp. The match * should be made case-insensitevly according to rfc 1033 */ @@ -2524,14 +2808,13 @@ * didn't get one from a getsockname. get our hostname and use * that. */ - char hname[66]; + char hname[MAXHOSTNAMELEN]; struct hostent *hp; - if (gethostname(hname, 65) != 0) { + if (gethostname(hname, sizeof hname) != 0) { syslog(LOG_ERR, "gethostname() call failed! (%m) Who am I?"); exit(EX_OSERR); } - hname[65] = '\0'; if ((hp = gethostbyname(hname)) != NULL) { peerinfo.my_clean_reverse_name = strdup(hp->h_name); } else { @@ -2567,6 +2850,30 @@ zap_state(current_state); zap_state(last_state); + if (!daemon_mode && listen_addr.s_addr != INADDR_ANY) { + /* + Are we allowed to talk on the address we accepted this connection + * on? - check to see that we are the defined listening address, or + * the loopback. + */ + if ((listen_addr.s_addr != peerinfo.my_sa->sin_addr.s_addr) + && (listen_addr.s_addr != htonl(INADDR_LOOPBACK)) + ) { + /* + tell the client to go away - we're not allowed to talk. + */ + writereply(reply_buf, 521, 0, + peerinfo.my_clean_reverse_name, + " ", + m521msg, + NULL); + flush_smtp_mbuf(reply_buf, replyfd, reply_buf->offset); + syslog(LOG_INFO, "Refused connection attempt from %s(%s) to %s(%s)", + peerinfo.peer_clean_reverse_name, peerinfo.peer_ok_addr, + peerinfo.my_clean_reverse_name, inet_ntoa(listen_addr)); + smtp_exit(EX_OK); + } + } writereply(reply_buf, 220, 0, peerinfo.my_clean_reverse_name, " ", @@ -2588,7 +2895,11 @@ /* * eof */ + if (VerboseSyslog) { syslog(LOG_INFO, "EOF on client fd. At least they could say goodbye!"); + } else { + accumlog(LOG_INFO, "EOF on client fd."); + } smtp_exit(EX_OSERR); } offset = 0; @@ -2646,8 +2957,16 @@ smtp_close_spoolfile(outfd); writereply(reply_buf, 250, 0, m250gotit, NULL); flush_smtp_mbuf(reply_buf, replyfd, reply_buf->offset); + if (VerboseSyslog) { syslog(LOG_INFO, "Received %ld bytes of message body from %s(%s)", - msize, peerinfo.peer_clean_reverse_name, peerinfo.peer_ok_addr); + msize, peerinfo.peer_clean_reverse_name, + peerinfo.peer_ok_addr); + } else { + accumlog(LOG_INFO, " bytes=%ld", msize); + accumlog(LOG_INFO, 0); /* + flush + */ + } clear_state(SNARF_DATA, current_state); clear_state(OK_RCPT, current_state); clear_state(OK_MAIL, current_state); diff -b -B --unified smtpd-2.0-orig/smtpd.h smtpd-2.0/smtpd.h --- smtpd-2.0-orig/smtpd.h Wed Oct 6 02:35:03 1999 +++ smtpd-2.0/smtpd.h Wed Oct 6 02:34:43 1999 @@ -1,6 +1,6 @@ /* Obtuse smtpd SMTP store daemon header file * - * $Id: smtpd-2.0-drt-0.1.patch 750 2005-08-13 20:28:39Z md $ + * $Id: smtpd-2.0-drt-0.1.patch 750 2005-08-13 20:28:39Z md $ * * Copyright (c) 1996, 1997 Obtuse Systems Corporation. All rights * reserved. @@ -164,13 +164,9 @@ #define m554msg "This daemon finds you amusing.. Go read the forging FAQ.." #define m554norcpt "I gotta know who gets this masterpiece of forgery!" #define m554nofrom "Yeesh! Ya gotta give a FROM when forging mail, that's the whole point!" - -#ifdef USE_521 -#define m521msg "doesn't talk SMTP, Sorry" -#define m521first "Sorry, I've been told I can't talk to you" -#endif +#define m521msg "says \"Go away or I shall taunt you a second time you second-hand electric donkey-bottom biters..\"" #else /* Boring sendmail/RFC821-ish messages */ -#define m220msg "Sendmail ready. " +#define m220msg "Sendmail 4.1/SMI-4.1 ready." #define m221msg "Closing connection" #define m250helook "pleased to meet you," #define m250fromok "sender OK" @@ -202,9 +198,5 @@ #define m554msg "Transaction failed" #define m554norcpt "Transaction failed" #define m554nofrom "Transaction failed" - -#ifdef USE_521 #define m521msg "Doesn't talk SMTP, Sorry" -#define m521first "Doesn't talk SMTP, Sorry" -#endif #endif Only in smtpd-2.0: smtpfwdd.8 diff -b -B --unified smtpd-2.0-orig/smtpfwdd.c smtpd-2.0/smtpfwdd.c --- smtpd-2.0-orig/smtpfwdd.c Wed Oct 6 02:35:03 1999 +++ smtpd-2.0/smtpfwdd.c Thu Oct 7 15:38:46 1999 @@ -4,7 +4,8 @@ * to pick it up and invokes sendmail (or sendmail-like agent) to * deliver it. * - * $Id: smtpd-2.0-drt-0.1.patch 750 2005-08-13 20:28:39Z md $ + * originalId: smtpfwdd.c,v 1.4 1999/05/25 16:40:55 millert Exp + * $Id: smtpd-2.0-drt-0.1.patch 750 2005-08-13 20:28:39Z md $ * * Copyright (c) 1996, 1997 Obtuse Systems Corporation. All rights * reserved. @@ -38,10 +39,17 @@ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * $Log: smtpfwdd.c,v $ + * Revision 1.2 1999/10/07 13:27:47 drt + * Fixed output of show_usage(). + * + * Revision 1.1 1999/10/07 12:38:15 drt + * Initial revision + * */ char *obtuse_copyright = "Copyright 1996 - Obtuse Systems Corporation - All rights reserved."; -char *obtuse_rcsid = "$Id: smtpd-2.0-drt-0.1.patch 750 2005-08-13 20:28:39Z md $"; +char *obtuse_rcsid = "$Id: smtpd-2.0-drt-0.1.patch 750 2005-08-13 20:28:39Z md $"; #include #include @@ -57,7 +65,9 @@ #include #include #ifdef IRIX_BROKEN_INCLUDES -/* IRIX 5.3 defines EX_OK (see sysexits.h) as something very strange in unistd.h :-) */ +/* + IRIX 5.3 defines EX_OK (see sysexits.h) as something very strange in unistd.h :-) + */ #ifdef EX_OK #undef EX_OK #endif @@ -122,6 +132,8 @@ int maxchildren = MAXCHILDREN; int poll_time = POLL_TIME; int gc_int = COMPLETION_WAIT; +int VerboseSyslog = 1; + #ifdef SUNOS_GETOPT extern char *optarg; @@ -138,7 +152,8 @@ fail_abort(FILE * f, char *fname) { if (unlink(fname) != 0) { - /* we could be here after a sibling removed the file. If this is + /* + we could be here after a sibling removed the file. If this is * the case, no problem. Otherwise something's wrong with our * setup. */ @@ -238,7 +253,7 @@ #ifdef VERBOSE syslog(LOG_DEBUG, "%s not complete now.", fname); #endif - if (gc_int && (buf.st_mtime+gc_int <= time(NULL))) { + if (gc_int && (buf.st_mtime + gc_int <= time(NULL))) { /* * This file has been hanging around incomplete for more than * gc_int, This could be due simply to a (really) slow connection/big @@ -271,8 +287,7 @@ syslog(LOG_DEBUG, "Skipping file %s, delivery last attempted at %s.", fname, ctime(&(buf.st_mtime))); #endif return (0); - } - else { + } else { syslog(LOG_DEBUG, "Retrying delivery of file %s, last attempted at %s.", fname, ctime(&(buf.st_mtime))); } } @@ -339,7 +354,14 @@ void show_usage() { - fprintf(stderr, "usage: smtpdfwdd [-u user] [-g group] [-g spooldir] [-s sendmailprog]\n"); + fprintf(stderr, "usage: smtpdfwdd [-u user] [-g group] [-d spooldir] [-s sendmailprog] [-q] [-M children] [-P intervall]\n"); + fprintf(stderr, "\t -d \t use spooldir \n"); + fprintf(stderr, "\t -u \t switch to \n"); + fprintf(stderr, "\t -g \t switch to \n"); + fprintf(stderr, "\t -s \t name of programm to feed mail to\n"); + fprintf(stderr, "\t -q \t don't brabble too much to syslog\n"); + fprintf(stderr, "\t -M \t maximum number of children\n"); + fprintf(stderr, "\t -P \t poll interval\n"); } /* @@ -467,7 +489,8 @@ * Bail out. If the file still exists, it will get tried again later. */ - /* If we locked the file (above) and have discovered it isn't complete, + /* + If we locked the file (above) and have discovered it isn't complete, * be sure to unlock it. Sadly, some OS's seem to think that locks * can stay after a process goes away. Sigh. -BB */ @@ -514,13 +537,13 @@ syslog(LOG_INFO, "Malloc failed - retrying later"); fail_retry(f, fname); } - #if STRIP_QUOTES - /* remove <> quotes from sender, as some MTA's (like qmail) don't deal + /* + remove <> quotes from sender, as some MTA's (like qmail) don't deal * with it well. */ - if ((from[0]=='<') && (from[strlen(from)-1]=='>')) { - from[strlen(from)-1]='\0'; + if ((from[0] == '<') && (from[strlen(from) - 1] == '>')) { + from[strlen(from) - 1] = '\0'; from++; } #endif @@ -564,9 +587,11 @@ fail_retry(f, fname); } #if STRIP_QUOTES - /* again, strip <> if present in case MTA can't handle it */ - if ((victim->name[0]=='<') && (victim->name[strlen(victim->name)-1]=='>')) { - victim->name[strlen(victim->name)-1]='\0'; + /* + again, strip <> if present in case MTA can't handle it + */ + if ((victim->name[0] == '<') && (victim->name[strlen(victim->name) - 1] == '>')) { + victim->name[strlen(victim->name) - 1] = '\0'; (victim->name)++; } #endif @@ -591,12 +616,15 @@ body = ftell(f); victim = victims; sentout = 0; + if (!VerboseSyslog) { + accumlog(LOG_INFO, "Forwading %s", fname); + } while (victim != NULL) { int status, pid, pidw, i, rstart; struct smtp_victim *sv = victim; char *av[MAXARGS]; - i=0; + i = 0; av[i++] = mailagent; #if SENDMAIL_OITRUE if (strstr(mailagent, "sendmail") != 0) { @@ -616,7 +644,11 @@ av[i++] = from; rstart = i; while (i < MAXARGS - 2) { + if (VerboseSyslog) { syslog(LOG_INFO, "forwarding to recipient %s", victim->name); + } else { + accumlog(LOG_INFO, " to=%s", victim->name); + } av[i++] = victim->name; victim = victim->next; if (victim == NULL) { @@ -731,8 +762,14 @@ /* * All seems to have worked */ - + if (VerboseSyslog) { syslog(LOG_INFO, "%s forwarded to %d recipients", fname, sentout); + } else { + accumlog(LOG_INFO, ", forwarded to %d recipients", sentout); + accumlog(LOG_INFO, 0); /* + flush + */ + } if (unlink(fname) != 0) { syslog(LOG_CRIT, "Couldn't remove spool file %s! (%m)", fname); exit(EX_CONFIG); @@ -760,11 +797,11 @@ * The brains of this operation */ -void +int main(int argc, char **argv) { int opt; - char *optstring = "u:g:d:s:C:M:P:"; + char *optstring = "qu:g:d:s:M:P:"; int pid; char *username = SMTP_USER; @@ -780,9 +817,12 @@ #ifdef GETOPT_EOF while ((opt = getopt(argc, argv, optstring)) != EOF) { #else - while ((opt = getopt(argc, argv, optstring)) > 0) { + while ((opt = getopt(argc, argv, optstring)) != -1) { #endif switch (opt) { + case 'q': + VerboseSyslog = 0; + break; case 'd': if (optarg[0] != '/') { fprintf(stderr, "The \"-d\" option requires an absolute pathname argument, \"%s\" is bogus\n", optarg); @@ -1009,8 +1049,9 @@ perror("Setuid failed!"); exit(EX_CONFIG); } - - /* If we didn't get a spooldir, use the default SPOOLDIR.SPOOLSUBDIR */ + /* + If we didn't get a spooldir, use the default SPOOLDIR.SPOOLSUBDIR + */ if (spooldir == NULL) { spooldir = (char *) malloc((strlen(SPOOLDIR) + strlen(SPOOLSUBDIR) + 2) * sizeof(char)); @@ -1020,7 +1062,6 @@ } sprintf(spooldir, "%s/%s", SPOOLDIR, SPOOLSUBDIR); } - /* * OK, we're now running as a non-root user and group, hopefully one * that can run sendmail -f and have it work. @@ -1101,6 +1142,12 @@ } sleep(1); reap_children(); + } + if (!VerboseSyslog) { + /* + should be empty - but just in case + */ + accumlog(LOG_INFO, 0); } /* * If we have a file with an appropriate name and it is