diff options
| author | cjs <cjs@NetBSD.org> | 1997-07-13 19:42:13 +0000 |
|---|---|---|
| committer | cjs <cjs@NetBSD.org> | 1997-07-13 19:42:13 +0000 |
| commit | fce01e04e20bca396dc45dc38e3658469ea93b7a (patch) | |
| tree | a6c5aeae79876b5d2801e4e1d72d89341a58077b /usr.sbin/sendmail/src | |
| parent | 28db57eb43fee36a8c41b7116507ddf46495f6f6 (diff) | |
Resolve conflicts in 8.8.6 import.
Diffstat (limited to 'usr.sbin/sendmail/src')
| -rw-r--r-- | usr.sbin/sendmail/src/clock.c | 47 | ||||
| -rw-r--r-- | usr.sbin/sendmail/src/collect.c | 39 | ||||
| -rw-r--r-- | usr.sbin/sendmail/src/conf.c | 843 | ||||
| -rw-r--r-- | usr.sbin/sendmail/src/conf.h | 141 | ||||
| -rw-r--r-- | usr.sbin/sendmail/src/convtime.c | 4 | ||||
| -rw-r--r-- | usr.sbin/sendmail/src/daemon.c | 251 | ||||
| -rw-r--r-- | usr.sbin/sendmail/src/deliver.c | 186 | ||||
| -rw-r--r-- | usr.sbin/sendmail/src/domain.c | 8 | ||||
| -rw-r--r-- | usr.sbin/sendmail/src/envelope.c | 39 | ||||
| -rw-r--r-- | usr.sbin/sendmail/src/err.c | 91 | ||||
| -rw-r--r-- | usr.sbin/sendmail/src/headers.c | 155 | ||||
| -rw-r--r-- | usr.sbin/sendmail/src/macro.c | 4 | ||||
| -rw-r--r-- | usr.sbin/sendmail/src/main.c | 193 | ||||
| -rw-r--r-- | usr.sbin/sendmail/src/makesendmail | 14 | ||||
| -rw-r--r-- | usr.sbin/sendmail/src/map.c | 361 | ||||
| -rw-r--r-- | usr.sbin/sendmail/src/mci.c | 54 | ||||
| -rw-r--r-- | usr.sbin/sendmail/src/mime.c | 36 | ||||
| -rw-r--r-- | usr.sbin/sendmail/src/newaliases.1 | 5 |
18 files changed, 1676 insertions, 795 deletions
diff --git a/usr.sbin/sendmail/src/clock.c b/usr.sbin/sendmail/src/clock.c index 5639f440517..6940b297894 100644 --- a/usr.sbin/sendmail/src/clock.c +++ b/usr.sbin/sendmail/src/clock.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983, 1995, 1996 Eric P. Allman + * Copyright (c) 1983, 1995-1997 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,7 +33,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)clock.c 8.18 (Berkeley) 12/31/96"; +static char sccsid[] = "@(#)clock.c 8.24 (Berkeley) 4/19/97"; #endif /* not lint */ # include "sendmail.h" @@ -60,7 +60,9 @@ static char sccsid[] = "@(#)clock.c 8.18 (Berkeley) 12/31/96"; ** none. */ -static SIGFUNC_DECL tick __P((int)); +EVENT *FreeEventList; /* list of free events */ + +static SIGFUNC_DECL tick __P((int)); EVENT * setevent(intvl, func, arg) @@ -71,6 +73,7 @@ setevent(intvl, func, arg) register EVENT **evp; register EVENT *ev; auto time_t now; + int wasblocked; if (intvl <= 0) { @@ -78,7 +81,7 @@ setevent(intvl, func, arg) return (NULL); } - (void) setsignal(SIGALRM, SIG_IGN); + wasblocked = blocksignal(SIGALRM); (void) time(&now); /* search event queue for correct position */ @@ -89,7 +92,11 @@ setevent(intvl, func, arg) } /* insert new event */ - ev = (EVENT *) xalloc(sizeof *ev); + ev = FreeEventList; + if (ev == NULL) + ev = (EVENT *) xalloc(sizeof *ev); + else + FreeEventList = ev->ev_link; ev->ev_time = now + intvl; ev->ev_func = func; ev->ev_arg = arg; @@ -101,7 +108,11 @@ setevent(intvl, func, arg) printf("setevent: intvl=%ld, for=%ld, func=%lx, arg=%d, ev=%lx\n", intvl, now + intvl, (u_long) func, arg, (u_long) ev); - tick(0); + setsignal(SIGALRM, tick); + intvl = EventQueue->ev_time - now; + (void) alarm((unsigned) intvl < 1 ? 1 : intvl); + if (wasblocked == 0) + (void) releasesignal(SIGALRM); return (ev); } /* @@ -122,6 +133,7 @@ clrevent(ev) register EVENT *ev; { register EVENT **evp; + int wasblocked; if (tTd(5, 5)) printf("clrevent: ev=%lx\n", (u_long) ev); @@ -129,7 +141,7 @@ clrevent(ev) return; /* find the parent event */ - (void) setsignal(SIGALRM, SIG_IGN); + wasblocked = blocksignal(SIGALRM); for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) { if (*evp == ev) @@ -140,16 +152,22 @@ clrevent(ev) if (*evp != NULL) { *evp = ev->ev_link; - free((char *) ev); + ev->ev_link = FreeEventList; + FreeEventList = ev; } /* restore clocks and pick up anything spare */ - tick(0); + if (wasblocked == 0) + releasesignal(SIGALRM); + if (EventQueue != NULL) + kill(getpid(), SIGALRM); } /* ** TICK -- take a clock tick ** ** Called by the alarm clock. This routine runs events as needed. +** Always called as a signal handler, so we assume that SIGALRM +** has been blocked. ** ** Parameters: ** One that is ignored; for compatibility with signal handlers. @@ -170,13 +188,14 @@ tick(arg) int mypid = getpid(); int olderrno = errno; - (void) setsignal(SIGALRM, SIG_IGN); (void) alarm(0); now = curtime(); if (tTd(5, 4)) printf("tick: now=%ld\n", now); + /* reset signal in case System V semantics */ + (void) setsignal(SIGALRM, tick); while ((ev = EventQueue) != NULL && (ev->ev_time <= now || ev->ev_pid != mypid)) { @@ -196,7 +215,8 @@ tick(arg) f = ev->ev_func; arg = ev->ev_arg; pid = ev->ev_pid; - free((char *) ev); + ev->ev_link = FreeEventList; + FreeEventList = ev; if (pid != getpid()) continue; if (EventQueue != NULL) @@ -207,17 +227,12 @@ tick(arg) (void) alarm(3); } - /* restore signals so that we can take ticks while in ev_func */ - (void) setsignal(SIGALRM, tick); - (void) releasesignal(SIGALRM); - /* call ev_func */ errno = olderrno; (*f)(arg); (void) alarm(0); now = curtime(); } - (void) setsignal(SIGALRM, tick); if (EventQueue != NULL) (void) alarm((unsigned) (EventQueue->ev_time - now)); errno = olderrno; diff --git a/usr.sbin/sendmail/src/collect.c b/usr.sbin/sendmail/src/collect.c index 660521cf8c7..219a47f7b8b 100644 --- a/usr.sbin/sendmail/src/collect.c +++ b/usr.sbin/sendmail/src/collect.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983, 1995, 1996 Eric P. Allman + * Copyright (c) 1983, 1995-1997 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,7 +33,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)collect.c 8.62 (Berkeley) 12/11/96"; +static char sccsid[] = "@(#)collect.c 8.69 (Berkeley) 5/29/97"; #endif /* not lint */ # include <errno.h> @@ -52,8 +52,6 @@ static char sccsid[] = "@(#)collect.c 8.62 (Berkeley) 12/11/96"; ** style message to say we are ready to collect ** input, and never ignore a single dot to mean ** end of message. -** requeueflag -- this message will be requeued later, so -** don't do final processing on it. ** hdrp -- the location to stash the header. ** e -- the current envelope. ** @@ -83,10 +81,9 @@ static EVENT *CollectTimeout; #define MS_BODY 2 /* reading message body */ void -collect(fp, smtpmode, requeueflag, hdrp, e) +collect(fp, smtpmode, hdrp, e) FILE *fp; bool smtpmode; - bool requeueflag; HDR **hdrp; register ENVELOPE *e; { @@ -94,7 +91,7 @@ collect(fp, smtpmode, requeueflag, hdrp, e) volatile bool ignrdot = smtpmode ? FALSE : IgnrDot; volatile time_t dbto = smtpmode ? TimeOuts.to_datablock : 0; register char *volatile bp; - volatile int c = '\0'; + volatile int c = EOF; volatile bool inputerr = FALSE; bool headeronly; char *volatile buf; @@ -103,7 +100,7 @@ collect(fp, smtpmode, requeueflag, hdrp, e) volatile int mstate; u_char *volatile pbp; u_char peekbuf[8]; - char dfname[20]; + char dfname[MAXQFNAME]; char bufbuf[MAXLINE]; extern bool isheader(); extern void eatheader(); @@ -117,10 +114,12 @@ collect(fp, smtpmode, requeueflag, hdrp, e) if (!headeronly) { + int tfd; struct stat stbuf; strcpy(dfname, queuename(e, 'd')); - if ((tf = dfopen(dfname, O_WRONLY|O_CREAT|O_TRUNC, FileMode)) == NULL) + tfd = dfopen(dfname, O_WRONLY|O_CREAT|O_TRUNC, FileMode, SFF_ANYFILE); + if (tfd < 0 || (tf = fdopen(tfd, "w")) == NULL) { syserr("Cannot create %s", dfname); e->e_flags |= EF_NO_BODY_RETN; @@ -169,12 +168,10 @@ collect(fp, smtpmode, requeueflag, hdrp, e) /* handle possible input timeout */ if (setjmp(CtxCollectTimeout) != 0) { -#ifdef LOG if (LogLevel > 2) - syslog(LOG_NOTICE, + sm_syslog(LOG_NOTICE, e->e_id, "timeout waiting for input from %s during message collect", CurHostName ? CurHostName : "<local machine>"); -#endif errno = 0; usrerr("451 timeout waiting for input during message collect"); goto readerr; @@ -417,10 +414,9 @@ readerr: if (tTd(30, 1)) printf("collect: premature EOM: %s\n", errmsg); -#ifdef LOG if (LogLevel >= 2) - syslog(LOG_WARNING, "collect: premature EOM: %s", errmsg); -#endif + sm_syslog(LOG_WARNING, e->e_id, + "collect: premature EOM: %s", errmsg); inputerr = TRUE; } @@ -455,14 +451,12 @@ readerr: problem = "I/O error"; else problem = "read timeout"; -# ifdef LOG if (LogLevel > 0 && feof(fp)) - syslog(LOG_NOTICE, + sm_syslog(LOG_NOTICE, e->e_id, "collect: %s on connection from %.100s, sender=%s: %s", problem, host, shortenstring(e->e_from.q_paddr, 203), errstring(errno)); -# endif if (feof(fp)) usrerr("451 collect: %s on connection from %s, from=%s", problem, host, @@ -501,7 +495,7 @@ readerr: markstats(e, (ADDRESS *) NULL); } -#ifdef _FFR_DSN_RRT +#if _FFR_DSN_RRT_OPTION /* ** If we have a Return-Receipt-To:, turn it into a DSN. */ @@ -576,11 +570,10 @@ readerr: e->e_status = "5.2.3"; usrerr("552 Message exceeds maximum fixed size (%ld)", MaxMessageSize); -# ifdef LOG if (LogLevel > 6) - syslog(LOG_NOTICE, "%s: message size (%ld) exceeds maximum (%ld)", - e->e_id, e->e_msgsize, MaxMessageSize); -# endif + sm_syslog(LOG_NOTICE, e->e_id, + "message size (%ld) exceeds maximum (%ld)", + e->e_msgsize, MaxMessageSize); } /* check for illegal 8-bit data */ diff --git a/usr.sbin/sendmail/src/conf.c b/usr.sbin/sendmail/src/conf.c index 4c050dd5b7a..fa22ae2eefe 100644 --- a/usr.sbin/sendmail/src/conf.c +++ b/usr.sbin/sendmail/src/conf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983, 1995, 1996 Eric P. Allman + * Copyright (c) 1983, 1995-1997 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,7 +33,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)conf.c 8.333 (Berkeley) 1/21/97"; +static char sccsid[] = "@(#)conf.c 8.362 (Berkeley) 6/14/97"; #endif /* not lint */ # include "sendmail.h" @@ -140,6 +140,9 @@ struct prival PrivacyValues[] = { "novrfy", PRIV_NOVRFY }, { "restrictmailq", PRIV_RESTRICTMAILQ }, { "restrictqrun", PRIV_RESTRICTQRUN }, +#if _FFR_PRIVACY_NOETRN + { "noetrn", PRIV_NOETRN }, +#endif { "authwarnings", PRIV_AUTHWARNINGS }, { "noreceipts", PRIV_NORECEIPTS }, { "goaway", PRIV_GOAWAY }, @@ -187,6 +190,7 @@ setdefaults(e) extern void setdefuser(); extern void setupmaps(); extern void setupmailers(); + extern void setupheaders(); SpaceSub = ' '; /* option B */ QueueLA = 8; /* option x */ @@ -233,6 +237,7 @@ setdefaults(e) setdefuser(); setupmaps(); setupmailers(); + setupheaders(); } @@ -252,48 +257,6 @@ setdefuser() defpwent == NULL ? "nobody" : defpwent->pw_name); } /* -** HOST_MAP_INIT -- initialize host class structures -*/ - -bool host_map_init __P((MAP *map, char *args)); - -bool -host_map_init(map, args) - MAP *map; - char *args; -{ - register char *p = args; - - for (;;) - { - while (isascii(*p) && isspace(*p)) - p++; - if (*p != '-') - break; - switch (*++p) - { - case 'a': - map->map_app = ++p; - break; - - case 'm': - map->map_mflags |= MF_MATCHONLY; - break; - - case 't': - map->map_mflags |= MF_NODEFER; - break; - } - while (*p != '\0' && !(isascii(*p) && isspace(*p))) - p++; - if (*p != '\0') - *p++ = '\0'; - } - if (map->map_app != NULL) - map->map_app = newstr(map->map_app); - return TRUE; -} -/* ** SETUPMAILERS -- initialize default mailers */ @@ -368,8 +331,8 @@ setupmaps() #endif #ifdef LDAPMAP MAPDEF("ldapx", NULL, 0, - ldap_map_parseargs, ldap_map_open, ldap_map_close, - ldap_map_lookup, null_map_store); + ldap_map_parseargs, ldap_map_open, ldap_map_close, + ldap_map_lookup, null_map_store); #endif #ifdef HESIOD @@ -1062,7 +1025,11 @@ setsignal(sig, handler) sigfunc_t handler; { #if defined(SYS5SIGNALS) || defined(BSD4_3) +# ifdef BSD4_3 return signal(sig, handler); +# else + return sigset(sig, handler); +# endif #else struct sigaction n, o; @@ -1525,8 +1492,8 @@ getla() dg_sys_info((long *)&load_info, DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0); - if (tTd(3, 1)) - printf("getla: %d\n", (int) (load_info.one_minute + 0.5)); + if (tTd(3, 1)) + printf("getla: %d\n", (int) (load_info.one_minute + 0.5)); return((int) (load_info.one_minute + 0.5)); } @@ -1557,8 +1524,8 @@ getla() (size_t) 1, 0) == -1) return 0; - if (tTd(3, 1)) - printf("getla: %d\n", (int) (pstd.psd_avg_1_min + 0.5)); + if (tTd(3, 1)) + printf("getla: %d\n", (int) (pstd.psd_avg_1_min + 0.5)); return (int) (pstd.psd_avg_1_min + 0.5); } @@ -1699,8 +1666,7 @@ int getla(void) static int kmem = -1; static enum { getla_none, getla_32, getla_64 } kernel_type = getla_none; - uint32_t avenrun32[3]; - uint64_t avenrun64[3]; + uint32_t avenrun[3]; if (kernel_type == getla_none) { @@ -1783,57 +1749,47 @@ int getla(void) switch (kernel_type) { + case getla_none: + return -1; + case getla_32: if (lseek(kmem, (off_t) Nl32[X_AVENRUN].n_value, SEEK_SET) == -1 || - read(kmem, (char *) avenrun32, sizeof(avenrun32)) < sizeof(avenrun32)) + read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) { if (tTd(3, 1)) printf("getla: lseek or read: %s\n", errstring(errno)); return -1; } - if (tTd(3, 5)) - { - printf("getla: avenrun{32} = %ld", - (long int) avenrun32[0]); - if (tTd(3, 15)) - printf(", %ld, %ld", - (long int)avenrun32[1], - (long int)avenrun32[2]); - printf("\n"); - } - if (tTd(3, 1)) - printf("getla: %d\n", - (int) (avenrun32[0] + FSCALE/2) >> FSHIFT); - return ((int) (avenrun32[0] + FSCALE/2) >> FSHIFT); + break; case getla_64: /* Using of lseek64 is perhaps overkill ... */ if (lseek64(kmem, (off64_t) Nl64[X_AVENRUN].n_value, SEEK_SET) == -1 || - read(kmem, (char *) avenrun64, sizeof(avenrun64)) < - sizeof(avenrun64)) + read(kmem, (char *) avenrun, sizeof(avenrun)) < + sizeof(avenrun)) { if (tTd(3, 1)) printf("getla: lseek64 or read: %s\n", errstring(errno)); return -1; } - if (tTd(3, 5)) - { - printf("getla: avenrun{64} = %lld", - (long long int) avenrun64[0]); - if (tTd(3, 15)) - printf(", %lld, %lld", - (long long int) avenrun64[1], - (long long int) avenrun64[2]); - printf("\n"); - } - if (tTd(3, 1)) - printf("getla: %d\n", - (int) (avenrun64[0] + FSCALE/2) >> FSHIFT); - return ((int) (avenrun64[0] + FSCALE/2) >> FSHIFT); + break; } - return -1; + if (tTd(3, 5)) + { + printf("getla: avenrun = %ld", + (long int) avenrun[0]); + if (tTd(3, 15)) + printf(", %ld, %ld", + (long int)avenrun[1], + (long int)avenrun[2]); + printf("\n"); + } + if (tTd(3, 1)) + printf("getla: %d\n", + (int) (avenrun[0] + FSCALE/2) >> FSHIFT); + return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); } #endif @@ -1913,7 +1869,9 @@ getla() afd = open(_PATH_AVENRUN, O_RDONLY|O_SYNC); if (afd < 0) { - syslog(LOG_ERR, "can't open %s: %m", _PATH_AVENRUN); + sm_syslog(LOG_ERR, NOQID, + "can't open %s: %m", + _PATH_AVENRUN); return -1; } } @@ -1998,7 +1956,7 @@ getla() /* Non Apollo stuff removed by Don Lewis 11/15/93 */ #ifndef lint -static char rcsid[] = "@(#)$Id: conf.c,v 1.18 1997/01/24 04:01:55 cjs Exp $"; +static char rcsid[] = "@(#)Id: getloadavg.c,v 1.16 1991/06/21 12:51:15 paul Exp "; #endif /* !lint */ #ifdef apollo @@ -2036,16 +1994,19 @@ int getloadavg( call_data ) ** none. */ +extern int get_num_procs_online __P((void)); + bool shouldqueue(pri, ctime) long pri; time_t ctime; { bool rval; + int queuela = QueueLA * get_num_procs_online(); if (tTd(3, 30)) printf("shouldqueue: CurrentLA=%d, pri=%ld: ", CurrentLA, pri); - if (CurrentLA < QueueLA) + if (CurrentLA < queuela) { if (tTd(3, 30)) printf("FALSE (CurrentLA < QueueLA)\n"); @@ -2059,7 +2020,7 @@ shouldqueue(pri, ctime) return (TRUE); } #endif - rval = pri > (QueueFactor / (CurrentLA - QueueLA + 1)); + rval = pri > (QueueFactor / (CurrentLA - queuela + 1)); if (tTd(3, 30)) printf("%s (by calculation)\n", rval ? "TRUE" : "FALSE"); return rval; @@ -2083,6 +2044,7 @@ bool refuseconnections(port) int port; { + int refusela = RefuseLA * get_num_procs_online(); time_t now; static time_t lastconn = (time_t) 0; static int conncnt = 0; @@ -2105,24 +2067,22 @@ refuseconnections(port) /* sleep to flatten out connection load */ setproctitle("deferring connections on port %d: %d per second", port, ConnRateThrottle); -#ifdef LOG if (LogLevel >= 14) - syslog(LOG_INFO, "deferring connections on port %d: %d per second", + sm_syslog(LOG_INFO, NOQID, + "deferring connections on port %d: %d per second", port, ConnRateThrottle); -#endif sleep(1); } CurrentLA = getla(); - if (CurrentLA >= RefuseLA) + if (CurrentLA >= refusela) { setproctitle("rejecting connections on port %d: load average: %d", port, CurrentLA); -#ifdef LOG if (LogLevel >= 14) - syslog(LOG_INFO, "rejecting connections on port %d: load average: %d", + sm_syslog(LOG_INFO, NOQID, + "rejecting connections on port %d: load average: %d", port, CurrentLA); -#endif return TRUE; } @@ -2130,11 +2090,10 @@ refuseconnections(port) { setproctitle("rejecting connections on port %d: min free: %d", port, MinBlocksFree); -#ifdef LOG if (LogLevel >= 14) - syslog(LOG_INFO, "rejecting connections on port %d: min free: %d", + sm_syslog(LOG_INFO, NOQID, + "rejecting connections on port %d: min free: %d", port, MinBlocksFree); -#endif return TRUE; } @@ -2147,11 +2106,10 @@ refuseconnections(port) { setproctitle("rejecting connections on port %d: %d children, max %d", port, CurChildren, MaxChildren); -#ifdef LOG if (LogLevel >= 14) - syslog(LOG_INFO, "rejecting connections on port %d: %d children, max %d", + sm_syslog(LOG_INFO, NOQID, + "rejecting connections on port %d: %d children, max %d", port, CurChildren, MaxChildren); -#endif return TRUE; } } @@ -2180,6 +2138,7 @@ refuseconnections(port) #define SPT_PSSTRINGS 4 /* use PS_STRINGS->... */ #define SPT_SYSMIPS 5 /* use sysmips() supported by NEWS-OS 6 */ #define SPT_SCO 6 /* write kernel u. area */ +#define SPT_CHANGEARGV 7 /* write our own strings into argv[] */ #ifndef SPT_TYPE # define SPT_TYPE SPT_REUSEARGV @@ -2204,7 +2163,7 @@ typedef unsigned int *pt_entry_t; # endif # endif -# if SPT_TYPE == SPT_PSSTRINGS +# if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV # define SETPROC_STATIC static # else # define SETPROC_STATIC @@ -2253,7 +2212,7 @@ initsetproctitle(argc, argv, envp) extern char **environ; /* - ** Move the environment so setproctitle can use the space at + ** Move the environment so setproctitle can use the space at ** the top of memory. */ @@ -2355,11 +2314,65 @@ setproctitle(fmt, va_alist) *p++ = SPT_PADCHAR; Argv[1] = NULL; # endif +# if SPT_TYPE == SPT_CHANGEARGV + Argv[0] = buf; + Argv[1] = 0; +# endif # endif /* SPT_TYPE != SPT_NONE */ } #endif /* SPT_TYPE != SPT_BUILTIN */ /* +** WAITFOR -- wait for a particular process id. +** +** Parameters: +** pid -- process id to wait for. +** +** Returns: +** status of pid. +** -1 if pid never shows up. +** +** Side Effects: +** none. +*/ + +int +waitfor(pid) + pid_t pid; +{ +#ifdef WAITUNION + union wait st; +#else + auto int st; +#endif + pid_t i; +#if defined(ISC_UNIX) || defined(_SCO_unix_) + int savesig; +#endif + + do + { + errno = 0; +#if defined(ISC_UNIX) || defined(_SCO_unix_) + savesig = releasesignal(SIGCHLD); +#endif + i = wait(&st); +#if defined(ISC_UNIX) || defined(_SCO_unix_) + if (savesig > 0) + blocksignal(SIGCHLD); +#endif + if (i > 0) + proc_list_drop(i); + } while ((i >= 0 || errno == EINTR) && i != pid); + if (i < 0) + return -1; +#ifdef WAITUNION + return st.w_status; +#else + return st; +#endif +} +/* ** REAPCHILD -- pick up the body of my child, lest it become a zombie ** ** Parameters: @@ -2387,12 +2400,10 @@ reapchild(sig) { if (count++ > 1000) { -#ifdef LOG if (LogLevel > 0) - syslog(LOG_ALERT, + sm_syslog(LOG_ALERT, NOQID, "reapchild: waitpid loop: pid=%d, status=%x", pid, status); -#endif break; } proc_list_drop(pid); @@ -2406,7 +2417,14 @@ reapchild(sig) # else /* WNOHANG */ auto int status; - while ((pid = wait(&status)) > 0) + /* + ** Catch one zombie -- we will be re-invoked (we hope) if there + ** are more. Unreliable signals probably break this, but this + ** is the "old system" situation -- waitpid or wait3 are to be + ** strongly preferred. + */ + + if ((pid = wait(&status)) > 0) proc_list_drop(pid); # endif /* WNOHANG */ # endif @@ -2880,12 +2898,10 @@ vsprintf(s, fmt, ap) ** %lx has been added. */ -#if !HASSNPRINTF - /************************************************************** * Original: * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 - * A bombproof version of doprnt (dopr) included. + * A bombproof version of doprnt (sm_dopr) included. * Sigh. This sort of thing is always nasty do deal with. Note that * the version here does not include floating point... * @@ -2896,11 +2912,13 @@ vsprintf(s, fmt, ap) * causing nast effects. **************************************************************/ -/*static char _id[] = "$Id: conf.c,v 1.18 1997/01/24 04:01:55 cjs Exp $";*/ -static void dopr(); -static char *end; +/*static char _id[] = "Id: snprintf.c,v 1.2 1995/10/09 11:19:47 roberto Exp ";*/ +static void sm_dopr(); +static char *DoprEnd; static int SnprfOverflow; +#if !HASSNPRINTF + /* VARARGS3 */ int # ifdef __STDC__ @@ -2932,19 +2950,22 @@ vsnprintf(str, count, fmt, args) va_list args; { str[0] = 0; - end = str + count - 1; + DoprEnd = str + count - 1; SnprfOverflow = 0; - dopr( str, fmt, args ); + sm_dopr( str, fmt, args ); if (count > 0) - end[0] = 0; + DoprEnd[0] = 0; if (SnprfOverflow && tTd(57, 2)) printf("\nvsnprintf overflow, len = %d, str = %s", count, shortenstring(str, 203)); return strlen(str); } +# endif /* !luna2 */ +#endif /* !HASSNPRINTF */ + /* - * dopr(): poor man's version of doprintf + * sm_dopr(): poor man's version of doprintf */ static void fmtstr __P((char *value, int ljust, int len, int zpad, int maxwidth)); @@ -2952,9 +2973,10 @@ static void fmtnum __P((long value, int base, int dosign, int ljust, int len, in static void dostr __P(( char * , int )); static char *output; static void dopr_outch __P(( int c )); +static int SyslogErrno; static void -dopr( buffer, format, args ) +sm_dopr( buffer, format, args ) char *buffer; const char *format; va_list args; @@ -2968,30 +2990,35 @@ dopr( buffer, format, args ) int ljust; int len; int zpad; +# if !HASSTRERROR && !defined(ERRLIST_PREDEFINED) + extern char *sys_errlist[]; + extern int sys_nerr; +# endif + output = buffer; while( (ch = *format++) ){ - switch( ch ){ - case '%': - ljust = len = zpad = maxwidth = 0; - longflag = pointflag = 0; - nextch: - ch = *format++; - switch( ch ){ - case 0: - dostr( "**end of format**" , 0); - return; - case '-': ljust = 1; goto nextch; - case '0': /* set zero padding if len not set */ - if(len==0 && !pointflag) zpad = '0'; - case '1': case '2': case '3': - case '4': case '5': case '6': - case '7': case '8': case '9': + switch( ch ){ + case '%': + ljust = len = zpad = maxwidth = 0; + longflag = pointflag = 0; + nextch: + ch = *format++; + switch( ch ){ + case 0: + dostr( "**end of format**" , 0); + return; + case '-': ljust = 1; goto nextch; + case '0': /* set zero padding if len not set */ + if(len==0 && !pointflag) zpad = '0'; + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': if (pointflag) maxwidth = maxwidth*10 + ch - '0'; else len = len*10 + ch - '0'; - goto nextch; + goto nextch; case '*': if (pointflag) maxwidth = va_arg( args, int ); @@ -2999,64 +3026,78 @@ dopr( buffer, format, args ) len = va_arg( args, int ); goto nextch; case '.': pointflag = 1; goto nextch; - case 'l': longflag = 1; goto nextch; - case 'u': case 'U': - /*fmtnum(value,base,dosign,ljust,len,zpad) */ - if( longflag ){ - value = va_arg( args, long ); - } else { - value = va_arg( args, int ); - } - fmtnum( value, 10,0, ljust, len, zpad ); break; - case 'o': case 'O': - /*fmtnum(value,base,dosign,ljust,len,zpad) */ - if( longflag ){ - value = va_arg( args, long ); - } else { - value = va_arg( args, int ); - } - fmtnum( value, 8,0, ljust, len, zpad ); break; - case 'd': case 'D': - if( longflag ){ - value = va_arg( args, long ); - } else { - value = va_arg( args, int ); - } - fmtnum( value, 10,1, ljust, len, zpad ); break; - case 'x': - if( longflag ){ - value = va_arg( args, long ); - } else { - value = va_arg( args, int ); - } - fmtnum( value, 16,0, ljust, len, zpad ); break; - case 'X': - if( longflag ){ - value = va_arg( args, long ); - } else { - value = va_arg( args, int ); - } - fmtnum( value,-16,0, ljust, len, zpad ); break; - case 's': - strvalue = va_arg( args, char *); + case 'l': longflag = 1; goto nextch; + case 'u': case 'U': + /*fmtnum(value,base,dosign,ljust,len,zpad) */ + if( longflag ){ + value = va_arg( args, long ); + } else { + value = va_arg( args, int ); + } + fmtnum( value, 10,0, ljust, len, zpad ); break; + case 'o': case 'O': + /*fmtnum(value,base,dosign,ljust,len,zpad) */ + if( longflag ){ + value = va_arg( args, long ); + } else { + value = va_arg( args, int ); + } + fmtnum( value, 8,0, ljust, len, zpad ); break; + case 'd': case 'D': + if( longflag ){ + value = va_arg( args, long ); + } else { + value = va_arg( args, int ); + } + fmtnum( value, 10,1, ljust, len, zpad ); break; + case 'x': + if( longflag ){ + value = va_arg( args, long ); + } else { + value = va_arg( args, int ); + } + fmtnum( value, 16,0, ljust, len, zpad ); break; + case 'X': + if( longflag ){ + value = va_arg( args, long ); + } else { + value = va_arg( args, int ); + } + fmtnum( value,-16,0, ljust, len, zpad ); break; + case 's': + strvalue = va_arg( args, char *); if (maxwidth > 0 || !pointflag) { if (pointflag && len > maxwidth) len = maxwidth; /* Adjust padding */ fmtstr( strvalue,ljust,len,zpad, maxwidth); } break; - case 'c': - ch = va_arg( args, int ); - dopr_outch( ch ); break; - case '%': dopr_outch( ch ); continue; - default: - dostr( "???????" , 0); - } - break; - default: - dopr_outch( ch ); - break; - } + case 'c': + ch = va_arg( args, int ); + dopr_outch( ch ); break; + case 'm': +#if HASSTRERROR + dostr(strerror(SyslogErrno), 0); +#else + if (SyslogErrno < 0 || SyslogErrno > sys_nerr) + { + dostr("Error ", 0); + fmtnum(SyslogErrno, 10, 0, 0, 0, 0); + } + else + dostr(sys_errlist[SyslogErrno], 0); +#endif + break; + + case '%': dopr_outch( ch ); continue; + default: + dostr( "???????" , 0); + } + break; + default: + dopr_outch( ch ); + break; + } } *output = 0; } @@ -3069,7 +3110,7 @@ fmtstr( value, ljust, len, zpad, maxwidth ) int padlen, strlen; /* amount to pad */ if( value == 0 ){ - value = "<NULL>"; + value = "<NULL>"; } for( strlen = 0; value[strlen]; ++ strlen ); /* strlen */ if (strlen > maxwidth && maxwidth) @@ -3078,13 +3119,13 @@ fmtstr( value, ljust, len, zpad, maxwidth ) if( padlen < 0 ) padlen = 0; if( ljust ) padlen = -padlen; while( padlen > 0 ) { - dopr_outch( ' ' ); - --padlen; + dopr_outch( ' ' ); + --padlen; } dostr( value, maxwidth ); while( padlen < 0 ) { - dopr_outch( ' ' ); - ++padlen; + dopr_outch( ' ' ); + ++padlen; } } @@ -3101,50 +3142,50 @@ fmtnum( value, base, dosign, ljust, len, zpad ) int caps = 0; /* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n", - value, base, dosign, ljust, len, zpad )); */ + value, base, dosign, ljust, len, zpad )); */ uvalue = value; if( dosign ){ - if( value < 0 ) { - signvalue = '-'; - uvalue = -value; - } + if( value < 0 ) { + signvalue = '-'; + uvalue = -value; + } } if( base < 0 ){ - caps = 1; - base = -base; + caps = 1; + base = -base; } do{ - convert[place++] = - (caps? "0123456789ABCDEF":"0123456789abcdef") - [uvalue % (unsigned)base ]; - uvalue = (uvalue / (unsigned)base ); + convert[place++] = + (caps? "0123456789ABCDEF":"0123456789abcdef") + [uvalue % (unsigned)base ]; + uvalue = (uvalue / (unsigned)base ); }while(uvalue); convert[place] = 0; padlen = len - place; if( padlen < 0 ) padlen = 0; if( ljust ) padlen = -padlen; /* DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n", - convert,place,signvalue,padlen)); */ + convert,place,signvalue,padlen)); */ if( zpad && padlen > 0 ){ - if( signvalue ){ - dopr_outch( signvalue ); - --padlen; - signvalue = 0; - } - while( padlen > 0 ){ - dopr_outch( zpad ); - --padlen; - } + if( signvalue ){ + dopr_outch( signvalue ); + --padlen; + signvalue = 0; + } + while( padlen > 0 ){ + dopr_outch( zpad ); + --padlen; + } } while( padlen > 0 ) { - dopr_outch( ' ' ); - --padlen; + dopr_outch( ' ' ); + --padlen; } if( signvalue ) dopr_outch( signvalue ); while( place > 0 ) dopr_outch( convert[--place] ); while( padlen < 0 ){ - dopr_outch( ' ' ); - ++padlen; + dopr_outch( ' ' ); + ++padlen; } } @@ -3166,20 +3207,16 @@ dopr_outch( c ) { #if 0 if( iscntrl(c) && c != '\n' && c != '\t' ){ - c = '@' + (c & 0x1F); - if( end == 0 || output < end ) - *output++ = '^'; + c = '@' + (c & 0x1F); + if( DoprEnd == 0 || output < DoprEnd ) + *output++ = '^'; } #endif - if( end == 0 || output < end ) - *output++ = c; + if( DoprEnd == 0 || output < DoprEnd ) + *output++ = c; else SnprfOverflow++; } - -# endif /* !luna2 */ - -#endif /* !HASSNPRINTF */ /* ** USERSHELLOK -- tell if a user's shell is ok for unrestricted use ** @@ -3434,7 +3471,7 @@ freediskspace(dir, bsize) { if (bsize != NULL) *bsize = FSBLOCKSIZE; - if (fs.SFS_BAVAIL < 0) + if (fs.SFS_BAVAIL <= 0) return 0; else return fs.SFS_BAVAIL; @@ -3483,15 +3520,12 @@ enoughdiskspace(msize) if (bfree < msize) { -#ifdef LOG if (LogLevel > 0) - syslog(LOG_ALERT, - "%s: low on space (have %ld, %s needs %ld in %s)", - CurEnv->e_id == NULL ? "[NOQUEUE]" : CurEnv->e_id, + sm_syslog(LOG_ALERT, CurEnv->e_id, + "low on space (have %ld, %s needs %ld in %s)", bfree, CurHostName == NULL ? "SMTP-DAEMON" : CurHostName, msize, QueueDir); -#endif return FALSE; } } @@ -3597,7 +3631,7 @@ transienterror(err) #if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR)) case ENOSR: /* Out of streams resources */ #endif - case EOPENTIMEOUT: /* PSEUDO: open timed out */ + case E_SM_OPENTIMEOUT: /* PSEUDO: open timed out */ return TRUE; } @@ -3627,6 +3661,7 @@ lockfile(fd, filename, ext, type) char *ext; int type; { + int i; # if !HASFLOCK int action; struct flock lfd; @@ -3651,7 +3686,9 @@ lockfile(fd, filename, ext, type) printf("lockfile(%s%s, action=%d, type=%d): ", filename, ext, action, lfd.l_type); - if (fcntl(fd, action, &lfd) >= 0) + while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR) + continue; + if (i >= 0) { if (tTd(55, 60)) printf("SUCCESS\n"); @@ -3697,7 +3734,9 @@ lockfile(fd, filename, ext, type) if (tTd(55, 60)) printf("lockfile(%s%s, type=%o): ", filename, ext, type); - if (flock(fd, type) >= 0) + while ((i = flock(fd, type)) < 0 && errno == EINTR) + continue; + if (i >= 0) { if (tTd(55, 60)) printf("SUCCESS\n"); @@ -3728,53 +3767,73 @@ lockfile(fd, filename, ext, type) /* ** CHOWNSAFE -- tell if chown is "safe" (executable only by root) ** +** Unfortunately, given that we can't predict other systems on which +** a remote mounted (NFS) filesystem will be mounted, the answer is +** almost always that this is unsafe. +** +** Note also that many operating systems have non-compliant +** implementations of the _POSIX_CHOWN_RESTRICTED variable and the +** fpathconf() routine. According to IEEE 1003.1-1990, if +** _POSIX_CHOWN_RESTRICTED is defined and not equal to -1, then +** no non-root process can give away the file. However, vendors +** don't take NFS into account, so a comfortable value of +** _POSIX_CHOWN_RESTRICTED tells us nothing. +** +** Also, some systems (e.g., IRIX 6.2) return 1 from fpathconf() +** even on files where chown is not restricted. Many systems get +** this wrong on NFS-based filesystems (that is, they say that chown +** is restricted [safe] on NFS filesystems where it may not be, since +** other systems can access the same filesystem and do file giveaway; +** only the NFS server knows for sure!) Hence, it is important to +** get the value of SAFENFSPATHCONF correct -- it should be defined +** _only_ after testing (see test/t_pathconf.c) a system on an unsafe +** NFS-based filesystem to ensure that you can get meaningful results. +** If in doubt, assume unsafe! +** +** You may also need to tweak IS_SAFE_CHOWN -- it should be a +** condition indicating whether the return from pathconf indicates +** that chown is safe (typically either > 0 or >= 0 -- there isn't +** even any agreement about whether a zero return means that a file +** is or is not safe). It defaults to "> 0". +** +** If the parent directory is safe (writable only by owner back +** to the root) then we can relax slightly and trust fpathconf +** in more circumstances. This is really a crock -- if this is an +** NFS mounted filesystem then we really know nothing about the +** underlying implementation. However, most systems pessimize and +** return an error (EINVAL or EOPNOTSUPP) on NFS filesystems, which +** we interpret as unsafe, as we should. Thus, this heuristic gets +** us into a possible problem only on systems that have a broken +** pathconf implementation and which are also poorly configured +** (have :include: files in group- or world-writable directories). +** ** Parameters: ** fd -- the file descriptor to check. +** safedir -- set if the parent directory is safe. ** ** Returns: -** TRUE -- if only root can chown the file to an arbitrary -** user. +** TRUE -- if the chown(2) operation is "safe" -- that is, +** only root can chown the file to an arbitrary user. ** FALSE -- if an arbitrary user can give away a file. */ +#ifndef IS_SAFE_CHOWN +# define IS_SAFE_CHOWN > 0 +#endif + bool -chownsafe(fd) +chownsafe(fd, safedir) int fd; + bool safedir; { -#ifdef __hpux - char *s; - int tfd; - uid_t o_uid, o_euid; - gid_t o_gid, o_egid; - bool rval; - struct stat stbuf; - - o_uid = getuid(); - o_euid = geteuid(); - o_gid = getgid(); - o_egid = getegid(); - fstat(fd, &stbuf); - setresuid(stbuf.st_uid, stbuf.st_uid, -1); - setresgid(stbuf.st_gid, stbuf.st_gid, -1); - s = tmpnam(NULL); - tfd = open(s, O_RDONLY|O_CREAT, 0600); - rval = fchown(tfd, DefUid, DefGid) != 0; - close(tfd); - setresuid(o_uid, o_euid, -1); - setresgid(o_gid, o_egid, -1); - unlink(s); - return rval; -#else -# ifdef _POSIX_CHOWN_RESTRICTED -# if _POSIX_CHOWN_RESTRICTED == -1 - return FALSE; -# else - return TRUE; -# endif -# else -# ifdef _PC_CHOWN_RESTRICTED +#if !defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1 +# if defined(_PC_CHOWN_RESTRICTED) int rval; + /* give the system administrator a chance to override */ + if (ChownAlwaysSafe) + return TRUE; + /* ** Some systems (e.g., SunOS) seem to have the call and the ** #define _PC_CHOWN_RESTRICTED, but don't actually implement @@ -3783,15 +3842,14 @@ chownsafe(fd) errno = 0; rval = fpathconf(fd, _PC_CHOWN_RESTRICTED); - if (errno == 0) - return rval > 0; -# endif -# ifdef BSD - return TRUE; +# if SAFENFSPATHCONF + return errno == 0 && rval IS_SAFE_CHOWN; # else - return FALSE; + return safedir && errno == 0 && rval IS_SAFE_CHOWN; # endif # endif +#else + return ChownAlwaysSafe; #endif } /* @@ -4028,11 +4086,10 @@ validate_connection(sap, hostname, e) #if TCPWRAPPERS if (!hosts_ctl("sendmail", hostname, anynet_ntoa(sap), STRING_UNKNOWN)) { -# ifdef LOG if (LogLevel >= 4) - syslog(LOG_NOTICE, "tcpwrappers (%s, %s) rejection", + sm_syslog(LOG_NOTICE, NOQID, + "tcpwrappers (%s, %s) rejection", hostname, anynet_ntoa(sap)); -# endif return FALSE; } #endif @@ -4385,7 +4442,7 @@ secureware_setup_secure(uid) ** Loads $=w with the names of all the interfaces. */ -#ifdef SIOCGIFCONF +#if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN struct rtentry; struct mbuf; # include <arpa/inet.h> @@ -4398,19 +4455,38 @@ struct mbuf; void load_if_names() { -#ifdef SIOCGIFCONF +#if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN int s; int i; - struct ifconf ifc; - char interfacebuf[10240]; + struct ifconf ifc; + int numifs; s = socket(AF_INET, SOCK_DGRAM, 0); if (s == -1) return; /* get the list of known IP address from the kernel */ - ifc.ifc_buf = interfacebuf; - ifc.ifc_len = sizeof interfacebuf; +# ifdef SIOCGIFNUM + if (ioctl(s, SIOCGIFNUM, (char *) &numifs) < 0) + { + /* can't get number of interfaces -- fall back */ + if (tTd(0, 4)) + printf("SIOCGIFNUM failed: %s\n", errstring(errno)); + numifs = -1; + } + else if (tTd(0, 42)) + printf("system has %d interfaces\n", numifs); + if (numifs < 0) +# endif + numifs = 512; + + if (numifs <= 0) + { + close(s); + return; + } + ifc.ifc_len = numifs * sizeof (struct ifreq); + ifc.ifc_buf = xalloc(ifc.ifc_len); if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { if (tTd(0, 4)) @@ -4435,7 +4511,6 @@ load_if_names() #endif char ip_addr[256]; extern char *inet_ntoa(); - extern struct hostent *gethostbyaddr(); #ifdef BSD4_4_SOCKADDR if (sa->sa_len > sizeof ifr->ifr_addr) @@ -4456,12 +4531,12 @@ load_if_names() ioctl(s, SIOCGIFFLAGS, (char *) &ifrf); if (tTd(0, 41)) printf("\tflags: %x\n", ifrf.ifr_flags); - if (!bitset(IFF_UP, ifrf.ifr_flags)) - continue; +# define IFRFREF ifrf #else - if (!bitset(IFF_UP, ifr->ifr_flags)) - continue; +# define IFRFREF (*ifr) #endif + if (!bitset(IFF_UP, IFRFREF.ifr_flags)) + continue; /* extract IP address from the list*/ ia = (((struct sockaddr_in *) sa)->sin_addr); @@ -4484,18 +4559,21 @@ load_if_names() } /* skip "loopback" interface "lo" */ - if (strcmp("lo0", ifr->ifr_name) == 0) + if (bitset(IFF_LOOPBACK, IFRFREF.ifr_flags)) continue; /* lookup name with IP address */ hp = sm_gethostbyaddr((char *) &ia, sizeof(ia), AF_INET); if (hp == NULL) { -#ifdef LOG if (LogLevel > 3) - syslog(LOG_WARNING, - "gethostbyaddr() failed for %.100s\n", - inet_ntoa(ia)); + sm_syslog(LOG_WARNING, NOQID, + "gethostbyaddr(%.100s) failed: %d\n", + inet_ntoa(ia), +#if NAMED_BIND + h_errno); +#else + -1); #endif continue; } @@ -4520,7 +4598,166 @@ load_if_names() hp->h_aliases++; } } + free(ifc.ifc_buf); close(s); +# undef IFRFREF +#endif +} +/* +** GET_NUM_PROCS_ONLINE -- return the number of processors currently online +** +** Parameters: +** none. +** +** Returns: +** The number of processors online. +*/ + +int +get_num_procs_online() +{ + int nproc = 0; + +#if _FFR_SCALE_LA_BY_NUM_PROCS +#ifdef _SC_NPROCESSORS_ONLN + nproc = (int) sysconf(_SC_NPROCESSORS_ONLN); +#endif +#endif + if (nproc <= 0) + nproc = 1; + return nproc; +} +/* +** SM_SYSLOG -- syslog wrapper to keep messages under SYSLOG_BUFSIZE +** +** Parameters: +** level -- syslog level +** id -- envelope ID or NULL (NOQUEUE) +** fmt -- format string +** arg... -- arguments as implied by fmt. +** +** Returns: +** none +*/ + +/* VARARGS3 */ +void +# ifdef __STDC__ +sm_syslog(int level, const char *id, const char *fmt, ...) +# else +sm_syslog(level, id, fmt, va_alist) + int level; + const char *id; + const char *fmt; + va_dcl +#endif +{ + static char *buf = NULL; + static size_t bufsize = MAXLINE; + char *begin, *end; + int seq = 1; + int idlen; + extern int SnprfOverflow; + VA_LOCAL_DECL + + SyslogErrno = errno; + if (id == NULL) + { + id = "NOQUEUE"; + idlen = 9; + } + else if (strcmp(id, NOQID) == 0) + { + id = ""; + idlen = 0; + } + else + idlen = strlen(id + 2); +bufalloc: + if (buf == NULL) + buf = (char *) xalloc(sizeof(char) * bufsize); + + /* do a virtual vsnprintf into buf */ + VA_START(fmt); + buf[0] = 0; + DoprEnd = buf + bufsize - 1; + SnprfOverflow = 0; + sm_dopr(buf, fmt, ap); + *DoprEnd = '\0'; + VA_END; + /* end of virtual vsnprintf */ + + if (SnprfOverflow) + { + /* String too small, redo with correct size */ + bufsize += SnprfOverflow + 1; + free(buf); + buf = NULL; + goto bufalloc; + } + if ((strlen(buf) + idlen + 1) < SYSLOG_BUFSIZE) + { +#if LOG + if (*id == '\0') + syslog(level, "%s", buf); + else + syslog(level, "%s: %s", id, buf); +#else + /*XXX should do something more sensible */ + if (*id == '\0') + fprintf(stderr, "%s\n", buf); + else + fprintf(stderr, "%s: %s\n", id, buf); +#endif + return; + } + + begin = buf; + while (*begin != '\0' && + (strlen(begin) + idlen + 5) > SYSLOG_BUFSIZE) + { + char save; + + if (seq == 999) + { + /* Too many messages */ + break; + } + end = begin + SYSLOG_BUFSIZE - idlen - 12; + while (end > begin) + { + /* Break on comma or space */ + if (*end == ',' || *end == ' ') + { + end++; /* Include separator */ + break; + } + end--; + } + /* No separator, break midstring... */ + if (end == begin) + end = begin + SYSLOG_BUFSIZE - idlen - 12; + save = *end; + *end = 0; +#if LOG + syslog(level, "%s[%d]: %s ...", id, seq++, begin); +#else + fprintf(stderr, "%s[%d]: %s ...\n", id, seq++, begin); +#endif + *end = save; + begin = end; + } + if (seq == 999) +#if LOG + syslog(level, "%s[%d]: log terminated, too many parts", id, seq); +#else + fprintf(stderr, "%s[%d]: log terminated, too many parts\n", id, seq); +#endif + else if (*begin != '\0') +#if LOG + syslog(level, "%s[%d]: %s", id, seq, begin); +#else + fprintf(stderr, "%s[%d]: %s\n", id, seq, begin); #endif } /* @@ -4553,7 +4790,7 @@ hard_syslog(pri, msg, va_alist) # endif { int i; - char buf[SYSLOG_BUFSIZE * 2]; + char buf[SYSLOG_BUFSIZE]; VA_LOCAL_DECL; VA_START(msg); @@ -4613,7 +4850,7 @@ char *CompileOptions[] = #if LDAPMAP "LDAPMAP", #endif -#ifdef LOG +#if LOG "LOG", #endif #if MATCHGECOS @@ -4695,6 +4932,9 @@ char *CompileOptions[] = char *OsCompileOptions[] = { +#if BOGUS_O_EXCL + "BOGUS_O_EXCL", +#endif #if HASFCHMOD "HASFCHMOD", #endif @@ -4731,6 +4971,9 @@ char *OsCompileOptions[] = #if HASSNPRINTF "HASSNPRINTF", #endif +#if HASSTRERROR + "HASSTRERROR", +#endif #if HASULIMIT "HASULIMIT", #endif @@ -4758,12 +5001,18 @@ char *OsCompileOptions[] = #if RLIMIT_NEEDS_SYS_TIME_H "RLIMIT_NEEDS_SYS_TIME_H", #endif +#if SAFENFSPATHCONF + "SAFENFSPATHCONF", +#endif #if SECUREWARE "SECUREWARE", #endif #if SHARE_V1 "SHARE_V1", #endif +#if SIOCGIFCONF_IS_BROKEN + "SIOCGIFCONF_IS_BROKEN", +#endif #if SYS5SETPGRP "SYS5SETPGRP", #endif diff --git a/usr.sbin/sendmail/src/conf.h b/usr.sbin/sendmail/src/conf.h index 595ed433e0a..bf81bbfa342 100644 --- a/usr.sbin/sendmail/src/conf.h +++ b/usr.sbin/sendmail/src/conf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983, 1995, 1996 Eric P. Allman + * Copyright (c) 1983, 1995-1997 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -31,7 +31,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)conf.h 8.288 (Berkeley) 1/17/97 + * @(#)conf.h 8.313 (Berkeley) 6/11/97 */ /* @@ -79,6 +79,7 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */ # define MAXMIMEARGS 20 /* max args in Content-Type: */ # define MAXMIMENESTING 20 /* max MIME multipart nesting */ # define QUEUESEGSIZE 1000 /* increment for queue size */ +# define MAXQFNAME 20 /* max qf file name length */ /********************************************************************** ** Compilation options. @@ -130,7 +131,7 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */ ** be turned off unless absolutely necessary. **********************************************************************/ -# define LOG /* enable logging -- don't turn off */ +# define LOG 1 /* enable logging -- don't turn off */ /********************************************************************** ** End of site-specific configuration. @@ -175,6 +176,7 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define USESETEUID 1 /* has useable seteuid(2) call */ +# define BOGUS_O_EXCL 1 /* exclusive open follows symlinks */ # define seteuid(e) setresuid(-1, e, -1) # define IP_SRCROUTE 1 /* can check IP source routing */ # define LA_TYPE LA_HPUX @@ -185,6 +187,7 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */ # define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */ # endif # define syslog hard_syslog +# define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */ # ifdef V4FS /* HP-UX 10.x */ @@ -217,6 +220,7 @@ extern void hard_syslog(int, char *, ...); */ #ifdef _AIX4 +# include <sys/select.h> # define _AIX3 1 /* pull in AIX3 stuff */ # define USESETEUID 1 /* seteuid(2) works */ # define TZ_TYPE TZ_NAME /* use tzname[] vector */ @@ -336,6 +340,7 @@ typedef int pid_t; # define SFS_BAVAIL f_bfree /* alternate field name */ # ifdef IRIX6 # define LA_TYPE LA_IRIX6 /* figure out at run time */ +# define SAFENFSPATHCONF 0 /* pathconf(2) lies on NFS filesystems */ # else # define LA_TYPE LA_INT @@ -373,6 +378,7 @@ typedef int pid_t; # define HASGETUSERSHELL 1 /* DOES have getusershell(3) call in libc */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define IP_SRCROUTE 1 /* can check IP source routing */ +# define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */ # ifdef SOLARIS_2_3 # define SOLARIS 20300 /* for back compat only -- use -DSOLARIS=20300 */ @@ -402,6 +408,9 @@ typedef int pid_t; # ifndef SYSLOG_BUFSIZE # define SYSLOG_BUFSIZE 1024 /* allow full size syslog buffer */ # endif +# ifndef TZ_TYPE +# define TZ_TYPE TZ_TZNAME +# endif # if SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) # define USESETEUID 1 /* seteuid works as of 2.3 */ # endif @@ -529,6 +538,7 @@ extern long dgux_inet_addr(); # ifndef IDENTPROTO # define IDENTPROTO 0 /* pre-4.4 TCP/IP implementation is broken */ # endif +# define SYSLOG_BUFSIZE 256 #endif @@ -558,6 +568,8 @@ extern long dgux_inet_addr(); # ifndef TZ_TYPE # define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ # endif +# define GIDSET_T gid_t +# define MAXNAMLEN NAME_MAX #endif @@ -600,8 +612,10 @@ extern long dgux_inet_addr(); # define UID_T int /* compiler gripes on uid_t */ # define GID_T int /* ditto for gid_t */ # define MODE_T int /* and mode_t */ -# define sleep sleepX # define setpgid setpgrp +# ifndef NOT_SENDMAIL +# define sleep sleepX +# endif # ifndef LA_TYPE # define LA_TYPE LA_MACH # endif @@ -624,12 +638,13 @@ typedef int pid_t; ** See also BSD defines. */ -#if defined(BSD4_4) && !defined(__bsdi__) +#if defined(BSD4_4) && !defined(__bsdi__) && !defined(__GNU__) # include <paths.h> # define HASUNSETENV 1 /* has unsetenv(3) call */ # define USESETEUID 1 /* has useable seteuid(2) call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ +# define HASSTRERROR 1 /* has strerror(3) */ # include <sys/cdefs.h> # define ERRLIST_PREDEFINED /* don't declare sys_errlist */ # define BSD4_4_SOCKADDR /* has sa_len */ @@ -655,6 +670,7 @@ typedef int pid_t; # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ # define HASUNAME 1 /* has uname(2) syscall */ +# define HASSTRERROR 1 /* has strerror(3) */ # include <sys/cdefs.h> # define ERRLIST_PREDEFINED /* don't declare sys_errlist */ # define BSD4_4_SOCKADDR /* has sa_len */ @@ -696,10 +712,12 @@ typedef int pid_t; # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ # define HASUNAME 1 /* has uname(2) syscall */ +# define HASSTRERROR 1 /* has strerror(3) */ # include <sys/cdefs.h> # define ERRLIST_PREDEFINED /* don't declare sys_errlist */ # define BSD4_4_SOCKADDR /* has sa_len */ # define NETLINK 1 /* supports AF_LINK */ +# define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */ # define GIDSET_T gid_t # ifndef LA_TYPE # define LA_TYPE LA_SUBR @@ -737,7 +755,7 @@ typedef int pid_t; ** For mt Xinu's Mach386 system. */ -#if defined(MACH) && defined(i386) +#if defined(MACH) && defined(i386) && !defined(__GNU__) # define MACH386 1 # define HASUNSETENV 1 /* has unsetenv(3) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ @@ -761,6 +779,50 @@ typedef int pid_t; #endif + +/* +** GNU OS (hurd) +** Largely BSD & posix compatible. +** Port contributed by Miles Bader <miles@gnu.ai.mit.edu>. +*/ + +#ifdef __GNU_HURD__ +# define SIOCGIFCONF_IS_BROKEN 1 +# define IP_SRCROUTE 0 +# define HASFCHMOD 1 +# define HASFLOCK 1 +# define HASUNAME 1 +# define HASUNSETENV 1 +# define HASSETSID 1 +# define HASINITGROUPS 1 +# define HASSETVBUF 1 +# define HASSETREUID 1 +# define USESETEUID 1 +# define HASLSTAT 1 +# define HASSETRLIMIT 1 +# define HASWAITPID 1 +# define HASGETDTABLESIZE 1 +# define HASSTRERROR 1 +/* # define NEEDGETOPT 1 */ +# define HASGETUSERSHELL 1 +# define ERRLIST_PREDEFINED 1 +# define BSD4_4_SOCKADDR 1 +# define GIDSET_T gid_t +# define LA_TYPE LA_MACH + +/* GNU uses mach[34], which renames some rpcs from mach2.x. */ +# define host_self mach_host_self +# define SFS_TYPE SFS_STATFS +# define SPT_TYPE SPT_CHANGEARGV + +/* GNU has no MAXPATHLEN; ideally the code should be changed to not use it. */ +# define MAXPATHLEN 2048 + +/* Define device num frobbing macros. */ +# define major(x) ((x)>>8) +# define minor(x) ((x)&0xFF) +#endif /* GNU */ + /* ** 4.3 BSD -- this is for very old systems ** @@ -1066,6 +1128,7 @@ extern void *malloc(); # define GIDSET_T gid_t /* from <linux/types.h> */ # define HASGETUSERSHELL 0 /* getusershell(3) broken in Slackware 2.0 */ # define IP_SRCROUTE 0 /* linux <= 1.2.8 doesn't support IP_OPTIONS */ +# define USE_SIGLONGJMP 1 /* sigsetjmp needed for signal handling */ # ifndef HASFLOCK # include <linux/version.h> # if LINUX_VERSION_CODE < 66399 @@ -1117,10 +1180,12 @@ extern void *malloc(); # define HASUNAME 1 /* use System V uname(2) system call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASINITGROUPS 1 /* has initgroups(3) call */ -# define HASSETVBUF 1 /* we have setvbuf(3) in libc */ +# define HASSETVBUF 1 /* has setvbuf(3) in libc */ +# define HASSTRERROR 1 /* has strerror(3) */ # define SIGFUNC_DEFINED /* sigfunc_t already defined */ -# define SIGFUNC_RETURN (0) /* XXX this is a guess */ -# define SIGFUNC_DECL int /* XXX this is a guess */ +# define SIGFUNC_RETURN /* POSIX-mode */ +# define SIGFUNC_DECL void /* POSIX-mode */ +# define ERRLIST_PREDEFINED 1 # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ # endif @@ -1829,7 +1894,7 @@ typedef struct msgb mblk_t; ** are closed. Some firewalls return this error if you try to connect ** to the IDENT port (113), so you can't receive email from these hosts ** on these systems. The firewall really should use a more specific -** message such as ICMP_UNREACH_PROTOCOL or _PORT or _NET_PROHIB. If +** message such as ICMP_UNREACH_PROTOCOL or _PORT or _FILTER_PROHIB. If ** not explicitly set to zero above, default it on. */ @@ -1930,12 +1995,21 @@ typedef struct msgb mblk_t; #if !defined(S_ISLNK) && defined(S_IFLNK) # define S_ISLNK(foo) ((foo & S_IFMT) == S_IFLNK) #endif +#ifndef S_IRUSR +# define S_IRUSR 0400 +#endif #ifndef S_IWUSR # define S_IWUSR 0200 #endif +#ifndef S_IRGRP +# define S_IRGRP 0040 +#endif #ifndef S_IWGRP # define S_IWGRP 0020 #endif +#ifndef S_IROTH +# define S_IROTH 0004 +#endif #ifndef S_IWOTH # define S_IWOTH 0002 #endif @@ -1957,6 +2031,13 @@ typedef struct msgb mblk_t; /* +** An "impossible" file mode to indicate that the file does not exist. +*/ + +#define ST_MODE_NOFILE 0171147 /* unlikely to occur */ + + +/* ** These are used in a few cases where we need some special ** error codes, but where the system doesn't provide something ** reasonable. They are printed in errstring. @@ -1966,7 +2047,16 @@ typedef struct msgb mblk_t; # define E_PSEUDOBASE 256 #endif -#define EOPENTIMEOUT (E_PSEUDOBASE + 0) /* timeout on open */ +#define E_SM_OPENTIMEOUT (E_PSEUDOBASE + 0) /* Timeout on file open */ +#define E_SM_NOSLINK (E_PSEUDOBASE + 1) /* Symbolic links not allowed */ +#define E_SM_NOHLINK (E_PSEUDOBASE + 2) /* Hard links not allowed */ +#define E_SM_REGONLY (E_PSEUDOBASE + 3) /* Regular files only */ +#define E_SM_ISEXEC (E_PSEUDOBASE + 4) /* Executable files not allowed */ +#define E_SM_WWDIR (E_PSEUDOBASE + 5) /* World writable directory */ +#define E_SM_GWDIR (E_PSEUDOBASE + 6) /* Group writable directory */ +#define E_SM_FILECHANGE (E_PSEUDOBASE + 7) /* File changed after open */ +#define E_SM_WWFILE (E_PSEUDOBASE + 8) /* World writable file */ +#define E_SM_GWFILE (E_PSEUDOBASE + 9) /* Group writable file */ #define E_DNSBASE (E_PSEUDOBASE + 20) /* base for DNS h_errno */ /* type of arbitrary pointer */ @@ -1978,16 +2068,8 @@ typedef struct msgb mblk_t; # include "cdefs.h" #endif -#if NAMED_BIND -# include <arpa/nameser.h> -# ifdef __svr4__ -# ifdef NOERROR -# undef NOERROR /* avoid compiler conflict with stream.h */ -# endif -# endif -# ifndef __ksr__ -extern int h_errno; -# endif +#if NAMED_BIND && !defined(__ksr__) +extern int h_errno; #endif /* @@ -2133,7 +2215,7 @@ typedef void (*sigfunc_t) __P((int)); # if (SYSLOG_BUFSIZE) > 768 # define TOBUFSIZE (SYSLOG_BUFSIZE - 512) # else -# define TOBUFSIZE 256 +# define TOBUFSIZE (SYSLOG_BUFSIZE / 2) # endif #endif @@ -2182,3 +2264,18 @@ typedef void (*sigfunc_t) __P((int)); #if !defined(NGROUPS_MAX) && defined(NGROUPS) # define NGROUPS_MAX NGROUPS /* POSIX naming convention */ #endif + +/* +** If we don't have a system syslog, simulate it. +*/ + +#if !LOG +# define LOG_EMERG 0 /* system is unusable */ +# define LOG_ALERT 1 /* action must be taken immediately */ +# define LOG_CRIT 2 /* critical conditions */ +# define LOG_ERR 3 /* error conditions */ +# define LOG_WARNING 4 /* warning conditions */ +# define LOG_NOTICE 5 /* normal but significant condition */ +# define LOG_INFO 6 /* informational */ +# define LOG_DEBUG 7 /* debug-level messages */ +#endif diff --git a/usr.sbin/sendmail/src/convtime.c b/usr.sbin/sendmail/src/convtime.c index 65994f88758..5ca1b39149e 100644 --- a/usr.sbin/sendmail/src/convtime.c +++ b/usr.sbin/sendmail/src/convtime.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983, 1995, 1996 Eric P. Allman + * Copyright (c) 1983, 1995-1997 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,7 +33,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)convtime.c 8.8 (Berkeley) 11/24/96"; +static char sccsid[] = "@(#)convtime.c 8.9 (Berkeley) 2/1/97"; #endif /* not lint */ # include "sendmail.h" diff --git a/usr.sbin/sendmail/src/daemon.c b/usr.sbin/sendmail/src/daemon.c index 7529e36cf32..1a202bf0a4e 100644 --- a/usr.sbin/sendmail/src/daemon.c +++ b/usr.sbin/sendmail/src/daemon.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983, 1995, 1996 Eric P. Allman + * Copyright (c) 1983, 1995-1997 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -37,13 +37,17 @@ #ifndef lint #ifdef DAEMON -static char sccsid[] = "@(#)daemon.c 8.159 (Berkeley) 1/14/97 (with daemon mode)"; +static char sccsid[] = "@(#)daemon.c 8.175 (Berkeley) 6/1/97 (with daemon mode)"; #else -static char sccsid[] = "@(#)daemon.c 8.159 (Berkeley) 1/14/97 (without daemon mode)"; +static char sccsid[] = "@(#)daemon.c 8.175 (Berkeley) 6/1/97 (without daemon mode)"; #endif #endif /* not lint */ -#if DAEMON || defined(SOCK_STREAM) +#if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) +# define USE_SOCK_STREAM 1 +#endif + +#if DAEMON || defined(USE_SOCK_STREAM) # include <arpa/inet.h> # if NAMED_BIND # include <resolv.h> @@ -55,6 +59,8 @@ static char sccsid[] = "@(#)daemon.c 8.159 (Berkeley) 1/14/97 (without daemon mo #if DAEMON +# include <sys/time.h> + # if IP_SRCROUTE # include <netinet/in_systm.h> # include <netinet/ip.h> @@ -166,8 +172,12 @@ getrequests(e) /* write the pid to the log file for posterity */ pidf = safefopen(PidFile, O_WRONLY|O_CREAT|O_TRUNC, 0644, - SFF_NOSLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT); - if (pidf != NULL) + SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT); + if (pidf == NULL) + { + sm_syslog(LOG_ERR, NOQID, "unable to write %s", PidFile); + } + else { extern char *CommandLineArgs; @@ -200,7 +210,6 @@ getrequests(e) int savederrno; int pipefd[2]; extern bool refuseconnections(); - extern int getla(); /* see if we are rejecting connections */ (void) blocksignal(SIGALRM); @@ -234,13 +243,15 @@ getrequests(e) if (!wordinclass(jbuf, 'w')) { dumpstate("daemon lost $j"); - syslog(LOG_ALERT, "daemon process doesn't have $j in $=w; see syslog"); + sm_syslog(LOG_ALERT, NOQID, + "daemon process doesn't have $j in $=w; see syslog"); abort(); } else if (j_has_dot && strchr(jbuf, '.') == NULL) { dumpstate("daemon $j lost dot"); - syslog(LOG_ALERT, "daemon process $j lost dot; see syslog"); + sm_syslog(LOG_ALERT, NOQID, + "daemon process $j lost dot; see syslog"); abort(); } } @@ -260,13 +271,29 @@ getrequests(e) log an error here; #endif (void) releasesignal(SIGALRM); - do + for (;;) { + fd_set readfds; + struct timeval timeout; + + FD_ZERO(&readfds); + FD_SET(DaemonSocket, &readfds); + timeout.tv_sec = 60; + timeout.tv_usec = 0; + + t = select(DaemonSocket + 1, &readfds, NULL, NULL, &timeout); + if (DoQueueRun) + (void) runqueue(TRUE, FALSE); + if (t <= 0 || !FD_ISSET(DaemonSocket, &readfds)) + continue; + errno = 0; lotherend = socksize; t = accept(DaemonSocket, (struct sockaddr *)&RealHostAddr, &lotherend); - } while (t < 0 && errno == EINTR); + if (t >= 0 || errno != EINTR) + break; + } savederrno = errno; (void) blocksignal(SIGALRM); if (t < 0) @@ -381,6 +408,9 @@ getrequests(e) OutChannel = outchannel; DisConnected = FALSE; + /* open maps for check_relay ruleset */ + initmaps(FALSE, e); + /* validate the connection */ HoldErrs = TRUE; nullconn = !validate_connection(&RealHostAddr, RealHostName, e); @@ -463,10 +493,9 @@ opendaemonsocket(firsttime) saveerrno = errno; syserr("opendaemonsocket: can't create server SMTP socket"); severe: -# ifdef LOG if (LogLevel > 0) - syslog(LOG_ALERT, "problem creating SMTP socket"); -# endif /* LOG */ + sm_syslog(LOG_ALERT, NOQID, + "problem creating SMTP socket"); DaemonSocket = -1; continue; } @@ -747,7 +776,7 @@ makeconnection(host, port, mci, e) register MCI *mci; ENVELOPE *e; { - register volatile int i = 0; + register volatile int addrno = 0; register volatile int s; register struct hostent *volatile hp = (struct hostent *)NULL; SOCKADDR addr; @@ -867,7 +896,7 @@ gothostent: hp->h_length); break; } - i = 1; + addrno = 1; } /* @@ -880,10 +909,9 @@ gothostent: if (sp == NULL) { -#ifdef LOG if (LogLevel > 2) - syslog(LOG_ERR, "makeconnection: service \"smtp\" unknown"); -#endif + sm_syslog(LOG_ERR, NOQID, + "makeconnection: service \"smtp\" unknown"); port = htons(25); } else @@ -985,22 +1013,23 @@ gothostent: if (setjmp(CtxConnectTimeout) == 0) { + int i; + if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0) ev = setevent(TimeOuts.to_iconnect, connecttimeout, 0); else if (TimeOuts.to_connect != 0) ev = setevent(TimeOuts.to_connect, connecttimeout, 0); else ev = NULL; - if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) - { - if (ev != NULL) - clrevent(ev); + i = connect(s, (struct sockaddr *) &addr, addrlen); + sav_errno = errno; + if (ev != NULL) + clrevent(ev); + if (i >= 0) break; - } } - sav_errno = errno; - if (ev != NULL) - clrevent(ev); + else + sav_errno = errno; /* if running demand-dialed connection, try again */ if (DialDelay > 0 && firstconnect) @@ -1015,7 +1044,7 @@ gothostent: /* couldn't connect.... figure out why */ (void) close(s); - if (hp != NULL && hp->h_addr_list[i]) + if (hp != NULL && hp->h_addr_list[addrno]) { if (tTd(16, 1)) printf("Connect failed (%s); trying new address....\n", @@ -1024,14 +1053,14 @@ gothostent: { #if NETINET case AF_INET: - bcopy(hp->h_addr_list[i++], + bcopy(hp->h_addr_list[addrno++], &addr.sin.sin_addr, INADDRSZ); break; #endif default: - bcopy(hp->h_addr_list[i++], + bcopy(hp->h_addr_list[addrno++], addr.sa.sa_data, hp->h_length); break; @@ -1126,19 +1155,17 @@ myhostname(hostbuf, size) if (strchr(hostbuf, '.') == NULL && !getcanonname(hostbuf, size, TRUE)) { -#ifdef LOG - syslog(LOG_CRIT, "My unqualified host name (%s) unknown; sleeping for retry", + sm_syslog(LOG_CRIT, NOQID, + "My unqualified host name (%s) unknown; sleeping for retry", hostbuf); -#endif message("My unqualified host name (%s) unknown; sleeping for retry", hostbuf); sleep(60); if (!getcanonname(hostbuf, size, TRUE)) { -#ifdef LOG - syslog(LOG_ALERT, "unable to qualify my own domain name (%s) -- using short name", + sm_syslog(LOG_ALERT, NOQID, + "unable to qualify my own domain name (%s) -- using short name", hostbuf); -#endif message("WARNING: unable to qualify my own domain name (%s) -- using short name", hostbuf); } @@ -1178,6 +1205,9 @@ getauthinfo(fd) int i; EVENT *ev; int nleft; + struct hostent *hp; + char **ha; + bool may_be_forged; char ibuf[MAXNAME + 1]; static char hbuf[MAXNAME * 2 + 2]; @@ -1200,6 +1230,30 @@ getauthinfo(fd) RealHostName[MAXNAME - 1] = '\0'; } + /* cross check RealHostName with forward DNS lookup */ + if (anynet_ntoa(&RealHostAddr)[0] == '[') + { + /* address is not a socket */ + may_be_forged = FALSE; + } + else + { + /* try to match the reverse against the forward lookup */ + hp = gethostbyname(RealHostName); + + if (hp == NULL) + may_be_forged = TRUE; + else + { + for (ha = hp->h_addr_list; *ha != NULL; ha++) + if (bcmp(*ha, + (char *) &RealHostAddr.sin.sin_addr, + hp->h_length) == 0) + break; + may_be_forged = *ha == NULL; + } + } + if (TimeOuts.to_ident == 0) goto noident; @@ -1337,6 +1391,9 @@ noident: postident: #if IP_SRCROUTE +# ifndef GET_IPOPT_DST +# define GET_IPOPT_DST(dst) (dst) +# endif /* ** Extract IP source routing information. ** @@ -1380,21 +1437,31 @@ postident: case IPOPT_SSRR: case IPOPT_LSRR: + /* + ** Source routing. + ** o[0] is the option type (loose/strict). + ** o[1] is the length of this option, + ** including option type and + ** length. + ** o[2] is the pointer into the route + ** data. + ** o[3] begins the route data. + */ + p = &hbuf[strlen(hbuf)]; l = sizeof hbuf - (hbuf - p) - 6; snprintf(p, SPACELEFT(hbuf, p), " [%s@%.*s", *o == IPOPT_SSRR ? "!" : "", l > 240 ? 120 : l / 2, - inet_ntoa(ipopt.ipopt_dst)); + inet_ntoa(GET_IPOPT_DST(ipopt.ipopt_dst))); i = strlen(p); p += i; l -= strlen(p); - /* o[1] is option length */ - j = *++o / sizeof(struct in_addr) - 1; + j = o[1] / sizeof(struct in_addr) - 1; /* q skips length and router pointer to data */ - q = o + 2; + q = &o[3]; for ( ; j >= 0; j--) { memcpy(&addr, q, sizeof(addr)); @@ -1409,7 +1476,7 @@ postident: l -= i + 1; q += sizeof(struct in_addr); } - o += *o; + o += o[1]; break; default: @@ -1430,6 +1497,11 @@ noipsr: (void) snprintf(p, SPACELEFT(hbuf, p), " [%.100s]", anynet_ntoa(&RealHostAddr)); } + if (may_be_forged) + { + p = &hbuf[strlen(hbuf)]; + (void) snprintf(p, SPACELEFT(hbuf, p), " (may be forged)"); + } postipsr: if (tTd(9, 1)) @@ -1440,7 +1512,7 @@ postipsr: ** HOST_MAP_LOOKUP -- turn a hostname into canonical form ** ** Parameters: -** map -- a pointer to this map (unused). +** map -- a pointer to this map. ** name -- the (presumably unqualified) hostname. ** av -- unused -- for compatibility with other mapping ** functions. @@ -1454,7 +1526,8 @@ postipsr: ** Side Effects: ** Looks up the host specified in hbuf. If it is not ** the canonical name for that host, return the canonical -** name. +** name (unless MF_MATCHONLY is set, which will cause the +** status only to be returned). */ char * @@ -1495,7 +1568,16 @@ host_map_lookup(map, name, av, statp) message("851 %s: Name server timeout", shortenstring(name, 33)); } - return s->s_namecanon.nc_cname; + if (*statp != EX_OK) + return NULL; + if (bitset(MF_MATCHONLY, map->map_mflags)) + cp = map_rewrite(map, name, strlen(name), NULL); + else + cp = map_rewrite(map, + s->s_namecanon.nc_cname, + strlen(s->s_namecanon.nc_cname), + av); + return cp; } /* @@ -1529,16 +1611,12 @@ host_map_lookup(map, name, av, statp) { if (tTd(9, 1)) printf("%s\n", hbuf); + s->s_namecanon.nc_stat = EX_OK; + s->s_namecanon.nc_cname = newstr(hbuf); if (bitset(MF_MATCHONLY, map->map_mflags)) - { - cp = map_rewrite(map, name, strlen(name), av); - s->s_namecanon.nc_cname = newstr(hbuf); - } + cp = map_rewrite(map, name, strlen(name), NULL); else - { cp = map_rewrite(map, hbuf, strlen(hbuf), av); - s->s_namecanon.nc_cname = newstr(cp); - } return cp; } else @@ -1586,9 +1664,10 @@ host_map_lookup(map, name, av, statp) return (NULL); *cp = '\0'; (void) inet_aton(&name[1], &in_addr); - - /* nope -- ask the name server */ - hp = gethostbyaddr((char *)&in_addr, sizeof(in_addr), AF_INET); + *cp = ']'; + + /* nope -- ask the name server */ + hp = sm_gethostbyaddr((char *)&in_addr, INADDRSZ, AF_INET); s->s_namecanon.nc_errno = errno; #if NAMED_BIND s->s_namecanon.nc_herrno = h_errno; @@ -1601,9 +1680,12 @@ host_map_lookup(map, name, av, statp) } /* found a match -- copy out */ - cp = map_rewrite(map, (char *) hp->h_name, strlen(hp->h_name), av); s->s_namecanon.nc_stat = *statp = EX_OK; - s->s_namecanon.nc_cname = newstr(cp); + s->s_namecanon.nc_cname = newstr(hp->h_name); + if (bitset(MF_MATCHONLY, map->map_mflags)) + cp = map_rewrite(map, name, strlen(name), NULL); + else + cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); return cp; } @@ -1685,16 +1767,63 @@ host_map_lookup(map, name, avp, statp) char *statp; { register struct hostent *hp; + char *cp; hp = sm_gethostbyname(name); - if (hp != NULL) - return hp->h_name; - *statp = EX_NOHOST; - return NULL; + if (hp == NULL) + { + *statp = EX_NOHOST; + return NULL; + } + if (bitset(MF_MATCHONLY, map->map_mflags)) + cp = map_rewrite(map, name, strlen(name), NULL); + else + cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); + return cp; } #endif /* DAEMON */ /* +** HOST_MAP_INIT -- initialize host class structures +*/ + +bool +host_map_init(map, args) + MAP *map; + char *args; +{ + register char *p = args; + + for (;;) + { + while (isascii(*p) && isspace(*p)) + p++; + if (*p != '-') + break; + switch (*++p) + { + case 'a': + map->map_app = ++p; + break; + + case 'm': + map->map_mflags |= MF_MATCHONLY; + break; + + case 't': + map->map_mflags |= MF_NODEFER; + break; + } + while (*p != '\0' && !(isascii(*p) && isspace(*p))) + p++; + if (*p != '\0') + *p++ = '\0'; + } + if (map->map_app != NULL) + map->map_app = newstr(map->map_app); + return TRUE; +} +/* ** ANYNET_NTOA -- convert a network address to printable form. ** ** Parameters: @@ -1704,7 +1833,7 @@ host_map_lookup(map, name, avp, statp) ** A printable version of that sockaddr. */ -#ifdef SOCK_STREAM +#ifdef USE_SOCK_STREAM #if NETLINK # include <net/if_dl.h> diff --git a/usr.sbin/sendmail/src/deliver.c b/usr.sbin/sendmail/src/deliver.c index 97a1050552a..c98c4bcbca9 100644 --- a/usr.sbin/sendmail/src/deliver.c +++ b/usr.sbin/sendmail/src/deliver.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983, 1995, 1996 Eric P. Allman + * Copyright (c) 1983, 1995-1997 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,7 +33,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)deliver.c 8.266 (Berkeley) 1/17/97"; +static char sccsid[] = "@(#)deliver.c 8.282 (Berkeley) 6/11/97"; #endif /* not lint */ #include "sendmail.h" @@ -76,7 +76,7 @@ sendall(e, mode) int otherowners; register ENVELOPE *ee; ENVELOPE *splitenv = NULL; - bool oldverbose = Verbose; + int oldverbose = Verbose; bool somedeliveries = FALSE; pid_t pid; extern void sendenvelope(); @@ -96,7 +96,6 @@ sendall(e, mode) } /* determine actual delivery mode */ - CurrentLA = getla(); if (mode == SM_DEFAULT) { mode = e->e_sendmode; @@ -295,6 +294,7 @@ sendall(e, mode) { extern HDR *copyheader(); extern ADDRESS *copyqueue(); + extern void dup_queue_file __P((ENVELOPE *, ENVELOPE *, int)); /* ** Split this envelope into two. @@ -360,42 +360,12 @@ sendall(e, mode) } if (mode != SM_VERIFY && bitset(EF_HAS_DF, e->e_flags)) - { - char df1buf[20], df2buf[20]; - - ee->e_dfp = NULL; - snprintf(df1buf, sizeof df1buf, "%s", - queuename(e, 'd')); - snprintf(df2buf, sizeof df2buf, "%s", - queuename(ee, 'd')); - if (link(df1buf, df2buf) < 0) - { - int saverrno = errno; - - syserr("sendall: link(%s, %s)", - df1buf, df2buf); - if (saverrno == EEXIST) - { - if (unlink(df2buf) < 0) - { - syserr("!sendall: unlink(%s): permanent", - df2buf); - /*NOTREACHED*/ - } - if (link(df1buf, df2buf) < 0) - { - syserr("!sendall: link(%s, %s): permanent", - df1buf, df2buf); - /*NOTREACHED*/ - } - } - } - } -#ifdef LOG + dup_queue_file(e, ee, 'd'); + openxscript(ee); if (LogLevel > 4) - syslog(LOG_INFO, "%s: clone %s, owner=%s", - ee->e_id, e->e_id, owner); -#endif + sm_syslog(LOG_INFO, ee->e_id, + "clone %s, owner=%s", + e->e_id, owner); } } @@ -420,6 +390,15 @@ sendall(e, mode) if (tTd(13, 29)) printf("No deliveries: auto-queuing\n"); mode = SM_QUEUE; + + /* treat this as a delivery in terms of counting tries */ + e->e_dtime = curtime(); + e->e_ntries++; + for (ee = splitenv; ee != NULL; ee = ee->e_sibling) + { + ee->e_dtime = curtime(); + ee->e_ntries++; + } } # if QUEUE @@ -462,7 +441,7 @@ sendall(e, mode) switch (mode) { case SM_VERIFY: - Verbose = TRUE; + Verbose = 2; break; case SM_QUEUE: @@ -563,6 +542,9 @@ sendall(e, mode) finis(); } + /* be sure to give error messages in child */ + QuickAbort = OnlyOneError = FALSE; + /* ** Close any cached connections. ** @@ -619,12 +601,10 @@ sendenvelope(e, mode) printf("sendenvelope(%s) e_flags=0x%lx\n", e->e_id == NULL ? "[NOQUEUE]" : e->e_id, e->e_flags); -#ifdef LOG if (LogLevel > 80) - syslog(LOG_DEBUG, "%s: sendenvelope, flags=0x%x", - e->e_id == NULL ? "[NOQUEUE]" : e->e_id, + sm_syslog(LOG_DEBUG, e->e_id, + "sendenvelope, flags=0x%x", e->e_flags); -#endif /* ** If we have had global, fatal errors, don't bother sending @@ -709,6 +689,51 @@ sendenvelope(e, mode) #endif } /* +** DUP_QUEUE_FILE -- duplicate a queue file into a split queue +** +** Parameters: +** e -- the existing envelope +** ee -- the new envelope +** type -- the queue file type (e.g., 'd') +** +** Returns: +** none +*/ + +void +dup_queue_file(e, ee, type) + struct envelope *e, *ee; + int type; +{ + char f1buf[MAXQFNAME], f2buf[MAXQFNAME]; + + ee->e_dfp = NULL; + ee->e_xfp = NULL; + snprintf(f1buf, sizeof f1buf, "%s", queuename(e, type)); + snprintf(f2buf, sizeof f2buf, "%s", queuename(ee, type)); + if (link(f1buf, f2buf) < 0) + { + int saverrno = errno; + + syserr("sendall: link(%s, %s)", f1buf, f2buf); + if (saverrno == EEXIST) + { + if (unlink(f2buf) < 0) + { + syserr("!sendall: unlink(%s): permanent", + f2buf); + /*NOTREACHED*/ + } + if (link(f1buf, f2buf) < 0) + { + syserr("!sendall: link(%s, %s): permanent", + f1buf, f2buf); + /*NOTREACHED*/ + } + } + } +} +/* ** DOFORK -- do a fork, retrying a couple of times on failure. ** ** This MUST be a macro, since after a vfork we are running @@ -826,6 +851,7 @@ deliver(e, firstto) time_t xstart; bool suidwarn; bool anyok; /* at least one address was OK */ + bool goodmxfound = FALSE; /* at least one MX was OK */ int mpvect[2]; int rpvect[2]; char *pv[MAXPV+1]; @@ -1018,6 +1044,7 @@ deliver(e, firstto) e->e_flags |= EF_NO_BODY_RETN; to->q_status = "5.2.3"; usrerr("552 Message is too large; %ld bytes max", m->m_maxsize); + markfailure(e, to, NULL, EX_UNAVAILABLE); giveresponse(EX_UNAVAILABLE, m, NULL, ctladdr, xstart, e); continue; } @@ -1294,8 +1321,11 @@ tryhost: curhost++; continue; } - strncpy(hostbuf, curhost, p - curhost); - hostbuf[p - curhost] = '\0'; + i = p - curhost; + if (i >= sizeof hostbuf) + i = sizeof hostbuf - 1; + strncpy(hostbuf, curhost, i); + hostbuf[i] = '\0'; if (*p != '\0') p++; curhost = p; @@ -1318,11 +1348,16 @@ tryhost: } mci->mci_mailer = m; if (mci->mci_exitstat != EX_OK) + { + if (mci->mci_exitstat == EX_TEMPFAIL) + goodmxfound = TRUE; continue; + } if (mci_lock_host(mci) != EX_OK) { mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); + goodmxfound = TRUE; continue; } @@ -1343,6 +1378,7 @@ tryhost: #endif if (i == EX_OK) { + goodmxfound = TRUE; mci->mci_state = MCIS_OPENING; mci_cache(mci); if (TrafficLogFile != NULL) @@ -1355,6 +1391,8 @@ tryhost: if (tTd(11, 1)) printf("openmailer: makeconnection => stat=%d, errno=%d\n", i, errno); + if (i == EX_TEMPFAIL) + goodmxfound = TRUE; mci_unlock_host(mci); } @@ -1863,7 +1901,12 @@ tryhost: for (to = tochain; to != NULL; to = to->q_tchain) { e->e_to = to->q_paddr; - if ((i = smtprcpt(to, m, mci, e)) != EX_OK) + if (strlen(to->q_paddr) + (t - tobuf) + 2 >= sizeof tobuf) + { + /* not enough room */ + continue; + } + else if ((i = smtprcpt(to, m, mci, e)) != EX_OK) { markfailure(e, to, mci, i); giveresponse(i, m, mci, ctladdr, xstart, e); @@ -1948,8 +1991,15 @@ tryhost: rcode = smtpgetstat(m, mci, e); if (rcode == EX_OK) { - strcat(tobuf, ","); - strcat(tobuf, to->q_paddr); + if (strlen(to->q_paddr) + strlen(tobuf) + 2 >= sizeof tobuf) + { + syserr("LMTP tobuf overflow"); + } + else + { + strcat(tobuf, ","); + strcat(tobuf, to->q_paddr); + } anyok = TRUE; } else @@ -1968,6 +2018,8 @@ tryhost: /* mark bad addresses */ if (rcode != EX_OK) { + if (goodmxfound && rcode == EX_NOHOST) + rcode = EX_TEMPFAIL; markfailure(e, to, mci, rcode); continue; } @@ -2084,6 +2136,7 @@ markfailure(e, q, mci, rcode) case EX_IOERR: case EX_OSERR: q->q_flags |= QQUEUEUP; + q->q_flags &= ~QDONTSEND; break; default: @@ -2203,7 +2256,7 @@ endmailer(mci, e, pv) if (mci->mci_pid == 0) return (EX_OK); -#ifdef _FFR_TIMEOUT_WAIT +#if _FFR_TIMEOUT_WAIT put a timeout around the wait #endif @@ -2428,7 +2481,6 @@ logdelivery(m, mci, stat, ctladdr, xstart, e) time_t xstart; register ENVELOPE *e; { -# ifdef LOG register char *bp; register char *p; int l; @@ -2533,11 +2585,12 @@ logdelivery(m, mci, stat, ctladdr, xstart, e) if (q == NULL) break; - syslog(LOG_INFO, "%s: to=%.*s [more]%s", - e->e_id, ++q - p, p, buf); + sm_syslog(LOG_INFO, e->e_id, + "to=%.*s [more]%s", + ++q - p, p, buf); p = q; } - syslog(LOG_INFO, "%s: to=%s%s", e->e_id, p, buf); + sm_syslog(LOG_INFO, e->e_id, "to=%s%s", p, buf); # else /* we have a very short log buffer size */ @@ -2549,11 +2602,12 @@ logdelivery(m, mci, stat, ctladdr, xstart, e) if (q == NULL) break; - syslog(LOG_INFO, "%s: to=%.*s [more]", - e->e_id, ++q - p, p); + sm_syslog(LOG_INFO, e->e_id, + "to=%.*s [more]", + ++q - p, p); p = q; } - syslog(LOG_INFO, "%s: to=%s", e->e_id, p); + sm_syslog(LOG_INFO, e->e_id, "to=%s", p); if (ctladdr != NULL) { @@ -2567,7 +2621,7 @@ logdelivery(m, mci, stat, ctladdr, xstart, e) ctladdr->q_uid, ctladdr->q_gid); bp += strlen(bp); } - syslog(LOG_INFO, "%s: %s", e->e_id, buf); + sm_syslog(LOG_INFO, e->e_id, "%s", buf); } bp = buf; snprintf(bp, SPACELEFT(buf, bp), "delay=%s", @@ -2585,7 +2639,7 @@ logdelivery(m, mci, stat, ctladdr, xstart, e) snprintf(bp, SPACELEFT(buf, bp), ", mailer=%s", m->m_name); bp += strlen(bp); } - syslog(LOG_INFO, "%s: %.1000s", e->e_id, buf); + sm_syslog(LOG_INFO, e->e_id, "%.1000s", buf); buf[0] = '\0'; bp = buf; @@ -2612,11 +2666,10 @@ logdelivery(m, mci, stat, ctladdr, xstart, e) snprintf(buf, sizeof buf, "relay=%.100s", p); } if (buf[0] != '\0') - syslog(LOG_INFO, "%s: %.1000s", e->e_id, buf); + sm_syslog(LOG_INFO, e->e_id, "%.1000s", buf); - syslog(LOG_INFO, "%s: stat=%s", e->e_id, shortenstring(stat, 63)); + sm_syslog(LOG_INFO, e->e_id, "stat=%s", shortenstring(stat, 63)); # endif /* short log buffer */ -# endif /* LOG */ } /* ** PUTFROMLINE -- output a UNIX-style from line (or whatever) @@ -2688,7 +2741,7 @@ putfromline(mci, e) } } expand(template, buf, sizeof buf, e); - putxline(buf, mci, PXLF_NOTHINGSPECIAL); + putxline(buf, strlen(buf), mci, PXLF_NOTHINGSPECIAL); } /* ** PUTBODY -- put the body of a message. @@ -2828,7 +2881,7 @@ putbody(mci, e, separator) switch (ostate) { case OS_HEAD: -#ifdef _FFR_NONULLS +#if _FFR_NONULLS if (c == '\0' && bitnset(M_NONULLS, mci->mci_mailer->m_flags)) break; @@ -2933,7 +2986,7 @@ putbody(mci, e, separator) ostate = OS_CR; continue; } -#ifdef _FFR_NONULLS +#if _FFR_NONULLS if (c == '\0' && bitnset(M_NONULLS, mci->mci_mailer->m_flags)) break; @@ -3214,7 +3267,7 @@ mailfile(filename, ctladdr, sfflags, e) if (setuid(RealUid) < 0 && suidwarn) syserr("mailfile: setuid(%ld) failed", (long) RealUid); - sfflags |= SFF_NOPATHCHECK; + sfflags |= SFF_NOPATHCHECK|SFF_NOLINK; sfflags &= ~SFF_OPENASROOT; f = safefopen(filename, oflags, FileMode, sfflags); if (f == NULL) @@ -3252,6 +3305,7 @@ mailfile(filename, ctladdr, sfflags, e) #endif (void) xfclose(f, "mailfile", filename); (void) fflush(stdout); + setuid(RealUid); exit(ExitStat); /*NOTREACHED*/ } diff --git a/usr.sbin/sendmail/src/domain.c b/usr.sbin/sendmail/src/domain.c index 70706555f0d..920b618f5b3 100644 --- a/usr.sbin/sendmail/src/domain.c +++ b/usr.sbin/sendmail/src/domain.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1986, 1995, 1996 Eric P. Allman + * Copyright (c) 1986, 1995-1997 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -36,9 +36,9 @@ #ifndef lint #if NAMED_BIND -static char sccsid[] = "@(#)domain.c 8.64 (Berkeley) 10/30/96 (with name server)"; +static char sccsid[] = "@(#)domain.c 8.67 (Berkeley) 4/9/97 (with name server)"; #else -static char sccsid[] = "@(#)domain.c 8.64 (Berkeley) 10/30/96 (without name server)"; +static char sccsid[] = "@(#)domain.c 8.67 (Berkeley) 4/9/97 (without name server)"; #endif #endif /* not lint */ @@ -197,6 +197,7 @@ getmxrr(host, mxhosts, droplocalhost, rcode) goto punt; case TRY_AGAIN: + case -1: /* couldn't connect to the name server */ if (fallbackMX != NULL) { @@ -881,6 +882,7 @@ gethostalias(host) fclose(fp); return NULL; } + fclose(fp); /* got a match; extract the equivalent name */ while (*p != '\0' && isascii(*p) && isspace(*p)) diff --git a/usr.sbin/sendmail/src/envelope.c b/usr.sbin/sendmail/src/envelope.c index c5e98f7e3f1..4dc07ae7fc3 100644 --- a/usr.sbin/sendmail/src/envelope.c +++ b/usr.sbin/sendmail/src/envelope.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983, 1995, 1996 Eric P. Allman + * Copyright (c) 1983, 1995-1997 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,7 +33,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)envelope.c 8.101 (Berkeley) 12/16/96"; +static char sccsid[] = "@(#)envelope.c 8.104 (Berkeley) 6/3/97"; #endif /* not lint */ #include "sendmail.h" @@ -121,12 +121,10 @@ dropenvelope(e, fulldrop) } } -#ifdef LOG if (LogLevel > 84) - syslog(LOG_DEBUG, "%s: dropenvelope, e_flags=0x%x, OpMode=%c, pid=%d", - id == NULL ? "[NOQUEUE]" : id, + sm_syslog(LOG_DEBUG, id, + "dropenvelope, e_flags=0x%x, OpMode=%c, pid=%d", e->e_flags, OpMode, getpid()); -#endif /* we must have an id to remove disk files */ if (id == NULL) @@ -168,8 +166,9 @@ dropenvelope(e, fulldrop) queueit = TRUE; #if XDEBUG else if (bitset(QQUEUEUP, q->q_flags)) - syslog(LOG_DEBUG, "dropenvelope: %s: q_flags = %x, paddr = %s", - e->e_id, q->q_flags, q->q_paddr); + sm_syslog(LOG_DEBUG, e->e_id, + "dropenvelope: q_flags = %x, paddr = %s", + q->q_flags, q->q_paddr); #endif /* see if a notification is needed */ @@ -296,6 +295,8 @@ dropenvelope(e, fulldrop) { auto ADDRESS *rlist = NULL; + if (tTd(50, 8)) + printf("dropenvelope(%s): sending return receipt\n", id); e->e_flags |= EF_SENDRECEIPT; (void) sendtolist(e->e_from.q_paddr, NULLADDR, &rlist, 0, e); (void) returntosender("Return receipt", rlist, RTSF_NO_BODY, e); @@ -310,6 +311,8 @@ dropenvelope(e, fulldrop) { extern void savemail __P((ENVELOPE *, bool)); + if (tTd(50, 8)) + printf("dropenvelope(%s): saving mail\n", id); savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags)); } @@ -323,6 +326,8 @@ dropenvelope(e, fulldrop) { auto ADDRESS *rlist = NULL; + if (tTd(50, 8)) + printf("dropenvelope(%s): sending postmaster copy\n", id); (void) sendtolist(PostMasterCopy, NULLADDR, &rlist, 0, e); (void) returntosender(e->e_message, rlist, RTSF_PM_BOUNCE, e); } @@ -332,6 +337,9 @@ dropenvelope(e, fulldrop) */ simpledrop: + if (tTd(50, 8)) + printf("dropenvelope(%s): at simpledrop, queueit=%d\n", + id, queueit); if (!queueit || bitset(EF_CLRQUEUE, e->e_flags)) { if (tTd(50, 1)) @@ -345,10 +353,8 @@ simpledrop: xunlink(queuename(e, 'd')); xunlink(queuename(e, 'q')); -#ifdef LOG if (LogLevel > 10) - syslog(LOG_INFO, "%s: done", id); -#endif + sm_syslog(LOG_INFO, id, "done"); } else if (queueit || !bitset(EF_INQUEUE, e->e_flags)) { @@ -360,6 +366,8 @@ simpledrop: } /* now unlock the job */ + if (tTd(50, 8)) + printf("dropenvelope(%s): unlocking job\n", id); closexscript(e); unlockqueue(e); @@ -698,7 +706,6 @@ setsender(from, e, delimptr, delimchar, internal) e->e_from.q_mailer == InclMailer) { /* log garbage addresses for traceback */ -# ifdef LOG if (from != NULL && LogLevel > 2) { char *p; @@ -716,11 +723,10 @@ setsender(from, e, delimptr, delimchar, internal) MAXNAME, host); p = ebuf; } - syslog(LOG_NOTICE, + sm_syslog(LOG_NOTICE, e->e_id, "setsender: %s: invalid or unparseable, received from %s", shortenstring(from, 83), p); } -# endif /* LOG */ if (from != NULL) { if (!bitset(QBADADDR, e->e_from.q_flags)) @@ -838,11 +844,10 @@ setsender(from, e, delimptr, delimchar, internal) if (pvp == NULL) { /* don't need to give error -- prescan did that already */ -# ifdef LOG if (LogLevel > 2) - syslog(LOG_NOTICE, "cannot prescan from (%s)", + sm_syslog(LOG_NOTICE, e->e_id, + "cannot prescan from (%s)", shortenstring(from, 203)); -# endif finis(); } (void) rewrite(pvp, 3, 0, e); diff --git a/usr.sbin/sendmail/src/err.c b/usr.sbin/sendmail/src/err.c index 2e0f0b91004..5bec0884d02 100644 --- a/usr.sbin/sendmail/src/err.c +++ b/usr.sbin/sendmail/src/err.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983, 1995, 1996 Eric P. Allman + * Copyright (c) 1983, 1995-1997 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,7 +33,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)err.c 8.52 (Berkeley) 12/1/96"; +static char sccsid[] = "@(#)err.c 8.62 (Berkeley) 6/5/97"; #endif /* not lint */ # include "sendmail.h" @@ -42,8 +42,7 @@ static char sccsid[] = "@(#)err.c 8.52 (Berkeley) 12/1/96"; /* ** SYSERR -- Print error message. ** -** Prints an error message via printf to the diagnostic -** output. If LOG is defined, it logs it also. +** Prints an error message via printf to the diagnostic output. ** ** If the first character of the syserr message is `!' it will ** log this as an ALERT message and exit immediately. This can @@ -90,16 +89,17 @@ syserr(fmt, va_alist) register char *p; int olderrno = errno; bool panic; -#ifdef LOG char *uname; struct passwd *pw; char ubuf[80]; -#endif VA_LOCAL_DECL panic = *fmt == '!'; if (panic) + { fmt++; + HoldErrs = FALSE; + } /* format and output the error message */ if (olderrno == 0) @@ -130,7 +130,6 @@ syserr(fmt, va_alist) printf("syserr: ExitStat = %d\n", ExitStat); } -# ifdef LOG pw = sm_getpwuid(getuid()); if (pw != NULL) uname = pw->pw_name; @@ -141,10 +140,9 @@ syserr(fmt, va_alist) } if (LogLevel > 0) - syslog(panic ? LOG_ALERT : LOG_CRIT, "%s: SYSERR(%s): %.900s", - CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id, + sm_syslog(panic ? LOG_ALERT : LOG_CRIT, CurEnv->e_id, + "SYSERR(%s): %.900s", uname, &MsgBuf[4]); -# endif /* LOG */ switch (olderrno) { case EBADF: @@ -180,7 +178,7 @@ syserr(fmt, va_alist) exit(EX_OSERR); } errno = 0; - if (QuickAbort) + if (QuickAbort || (OnlyOneError && !HoldErrs)) longjmp(TopFrame, 2); } /* @@ -251,14 +249,12 @@ usrerr(fmt, va_alist) puterrmsg(MsgBuf); -# ifdef LOG if (LogLevel > 3 && LogUsrErrs) - syslog(LOG_NOTICE, "%s: %.900s", - CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id, + sm_syslog(LOG_NOTICE, CurEnv->e_id, + "%.900s", &MsgBuf[4]); -# endif /* LOG */ - if (QuickAbort) + if (QuickAbort || (OnlyOneError && !HoldErrs)) longjmp(TopFrame, 1); } /* @@ -404,10 +400,10 @@ putoutmsg(msg, holdmsg, heldmsg) if (!heldmsg && CurEnv->e_xfp != NULL && strchr("45", msg[0]) != NULL) fprintf(CurEnv->e_xfp, "%s\n", msg); -#ifdef LOG if (LogLevel >= 15 && (OpMode == MD_SMTP || OpMode == MD_DAEMON)) - syslog(LOG_INFO, "--> %s%s", msg, holdmsg ? " (held)" : ""); -#endif + sm_syslog(LOG_INFO, CurEnv->e_id, + "--> %s%s", + msg, holdmsg ? " (held)" : ""); if (msgcode == '8') msg[0] = '0'; @@ -450,14 +446,11 @@ putoutmsg(msg, holdmsg, heldmsg) /* can't call syserr, 'cause we are using MsgBuf */ HoldErrs = TRUE; -#ifdef LOG if (LogLevel > 0) - syslog(LOG_CRIT, - "%s: SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s", - CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id, + sm_syslog(LOG_CRIT, CurEnv->e_id, + "SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s", CurHostName == NULL ? "NO-HOST" : CurHostName, shortenstring(msg, 203), errstring(errno)); -#endif } /* ** PUTERRMSG -- like putoutmsg, but does special processing for error messages @@ -522,7 +515,6 @@ fmtmsg(eb, to, num, eno, fmt, ap) va_list ap; { char del; - char *meb; int l; int spaceleft = sizeof MsgBuf; @@ -559,8 +551,6 @@ fmtmsg(eb, to, num, eno, fmt, ap) *eb++ &= 0177; } - meb = eb; - /* output the message */ (void) vsnprintf(eb, spaceleft, fmt, ap); spaceleft -= strlen(eb); @@ -627,7 +617,7 @@ errstring(errnum) char *dnsmsg; char *bp; static char buf[MAXLINE]; -# ifndef ERRLIST_PREDEFINED +# if !HASSTRERROR && !defined(ERRLIST_PREDEFINED) extern char *sys_errlist[]; extern int sys_nerr; # endif @@ -648,7 +638,11 @@ errstring(errnum) case ETIMEDOUT: case ECONNRESET: bp = buf; +#if HASSTRERROR + snprintf(bp, SPACELEFT(buf, bp), "%s", strerror(errnum)); +#else snprintf(bp, SPACELEFT(buf, bp), "%s", sys_errlist[errnum]); +#endif bp += strlen(bp); if (CurHostName != NULL) { @@ -690,9 +684,6 @@ errstring(errnum) return (buf); # endif - case EOPENTIMEOUT: - return "Timeout on file open"; - # if NAMED_BIND case HOST_NOT_FOUND + E_DNSBASE: dnsmsg = "host not found"; @@ -714,6 +705,40 @@ errstring(errnum) case EPERM: /* SunOS gives "Not owner" -- this is the POSIX message */ return "Operation not permitted"; + + /* + ** Error messages used internally in sendmail. + */ + + case E_SM_OPENTIMEOUT: + return "Timeout on file open"; + + case E_SM_NOSLINK: + return "Symbolic links not allowed"; + + case E_SM_NOHLINK: + return "Hard links not allowed"; + + case E_SM_REGONLY: + return "Regular files only"; + + case E_SM_ISEXEC: + return "Executable files not allowed"; + + case E_SM_WWDIR: + return "World writable directory"; + + case E_SM_GWDIR: + return "Group writable directory"; + + case E_SM_FILECHANGE: + return "File changed after open"; + + case E_SM_WWFILE: + return "World writable file"; + + case E_SM_GWFILE: + return "Group writable file"; } if (dnsmsg != NULL) @@ -731,9 +756,13 @@ errstring(errnum) return buf; } +#if HASSTRERROR + return strerror(errnum); +#else if (errnum > 0 && errnum < sys_nerr) return (sys_errlist[errnum]); (void) snprintf(buf, sizeof buf, "Error %d", errnum); return (buf); +#endif } diff --git a/usr.sbin/sendmail/src/headers.c b/usr.sbin/sendmail/src/headers.c index d40d95f470a..a4ece010dde 100644 --- a/usr.sbin/sendmail/src/headers.c +++ b/usr.sbin/sendmail/src/headers.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983, 1995, 1996 Eric P. Allman + * Copyright (c) 1983, 1995-1997 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,13 +33,36 @@ */ #ifndef lint -static char sccsid[] = "@(#)headers.c 8.103 (Berkeley) 12/11/96"; +static char sccsid[] = "@(#)headers.c 8.110 (Berkeley) 6/14/97"; #endif /* not lint */ # include <errno.h> # include "sendmail.h" /* +** SETUPHEADERS -- initialize headers in symbol table +** +** Parameters: +** none +** +** Returns: +** none +*/ + +void +setupheaders() +{ + struct hdrinfo *hi; + STAB *s; + + for (hi = HdrInfo; hi->hi_field != NULL; hi++) + { + s = stab(hi->hi_field, ST_HEADER, ST_ENTER); + s->s_header.hi_flags = hi->hi_flags; + s->s_header.hi_ruleset = NULL; + } +} +/* ** CHOMPHEADER -- process and save a header line. ** ** Called by collect and by readcf to deal with header lines. @@ -58,6 +81,8 @@ static char sccsid[] = "@(#)headers.c 8.103 (Berkeley) 12/11/96"; ** Contents of 'line' are destroyed. */ +struct hdrinfo NormalHeader = { NULL, 0, NULL }; + int chompheader(line, def, hdrp, e) char *line; @@ -70,9 +95,10 @@ chompheader(line, def, hdrp, e) HDR **hp; char *fname; char *fvalue; - struct hdrinfo *hi; bool cond = FALSE; bool headeronly; + STAB *s; + struct hdrinfo *hi; BITMAP mopts; if (tTd(31, 6)) @@ -116,7 +142,7 @@ chompheader(line, def, hdrp, e) if (*p++ != ':' || fname == fvalue) { syserr("553 header syntax error, line \"%s\"", line); - return (0); + return 0; } *fvalue = '\0'; fvalue = p; @@ -129,19 +155,44 @@ chompheader(line, def, hdrp, e) if (strlen(fname) > 100) return H_EOH; - /* see if it is a known type */ - for (hi = HdrInfo; hi->hi_field != NULL; hi++) +#if _FFR_HEADER_RSCHECK + /* check to see if it represents a ruleset call */ + if (def) { - if (strcasecmp(hi->hi_field, fname) == 0) - break; + char hbuf[50]; + + (void) expand(fvalue, hbuf, sizeof hbuf, e); + for (p = hbuf; isascii(*p) && isspace(*p); ) + p++; + if ((*p++ & 0377) == CALLSUBR) + { + auto char *endp; + + if (strtorwset(p, &endp, ST_ENTER) > 0) + { + *endp = '\0'; + s = stab(fname, ST_HEADER, ST_ENTER); + s->s_header.hi_ruleset = newstr(p); + } + return 0; + } } +#endif + + /* see if it is a known type */ + s = stab(fname, ST_HEADER, ST_FIND); + if (s != NULL) + hi = &s->s_header; + else + hi = &NormalHeader; if (tTd(31, 9)) { - if (hi->hi_field == NULL) - printf("no header match\n"); + if (s == NULL) + printf("no header flags match\n"); else - printf("header match, hi_flags=%x\n", hi->hi_flags); + printf("header match, flags=%x, ruleset=%s\n", + hi->hi_flags, hi->hi_ruleset); } /* see if this is a resent message */ @@ -155,7 +206,7 @@ chompheader(line, def, hdrp, e) /* if this means "end of header" quit now */ if (bitset(H_EOH, hi->hi_flags)) - return (hi->hi_flags); + return hi->hi_flags; /* ** Horrible hack to work around problem with Lotus Notes SMTP @@ -172,6 +223,13 @@ chompheader(line, def, hdrp, e) } /* + ** If there is a check ruleset, verify it against the header. + */ + + if (!def && hi->hi_ruleset != NULL) + (void) rscheck(hi->hi_ruleset, fvalue, NULL, e); + + /* ** Drop explicit From: if same as what we would generate. ** This is to make MH (which doesn't always give a full name) ** insert the full name information in all circumstances. @@ -191,7 +249,7 @@ chompheader(line, def, hdrp, e) if (e->e_from.q_paddr != NULL && (strcmp(fvalue, e->e_from.q_paddr) == 0 || strcmp(fvalue, e->e_from.q_user) == 0)) - return (hi->hi_flags); + return hi->hi_flags; } /* delete default value for this header */ @@ -232,7 +290,7 @@ chompheader(line, def, hdrp, e) e->e_flags &= ~EF_OLDSTYLE; } - return (h->h_flags); + return h->h_flags; } /* ** ADDHEADER -- add a header entry to the end of the queue. @@ -258,15 +316,11 @@ addheader(field, value, hdrlist) HDR **hdrlist; { register HDR *h; - register struct hdrinfo *hi; + STAB *s; HDR **hp; /* find info struct */ - for (hi = HdrInfo; hi->hi_field != NULL; hi++) - { - if (strcasecmp(field, hi->hi_field) == 0) - break; - } + s = stab(field, ST_HEADER, ST_FIND); /* find current place in list -- keep back pointer? */ for (hp = hdrlist; (h = *hp) != NULL; hp = &h->h_link) @@ -280,7 +334,9 @@ addheader(field, value, hdrlist) h->h_field = field; h->h_value = newstr(value); h->h_link = *hp; - h->h_flags = hi->hi_flags | H_DEFAULT; + h->h_flags = H_DEFAULT; + if (s != NULL) + h->h_flags |= s->s_header.hi_flags; clrbitmap(h->h_mflags); *hp = h; } @@ -577,10 +633,8 @@ eatheader(e, full) ** Log collection information. */ -# ifdef LOG if (bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4) logsender(e, msgid); -# endif /* LOG */ e->e_flags &= ~EF_LOGSENDER; } /* @@ -599,7 +653,6 @@ logsender(e, msgid) register ENVELOPE *e; char *msgid; { -# ifdef LOG char *name; register char *sbp; register char *p; @@ -663,37 +716,39 @@ logsender(e, msgid) p = macvalue('r', e); if (p != NULL) (void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", proto=%.20s", p); - syslog(LOG_INFO, "%s: %.850s, relay=%.100s", - e->e_id, sbuf, name); + sm_syslog(LOG_INFO, e->e_id, + "%.850s, relay=%.100s", + sbuf, name); # else /* short syslog buffer */ - syslog(LOG_INFO, "%s: from=%s", - e->e_id, e->e_from.q_paddr == NULL ? "<NONE>" : - shortenstring(e->e_from.q_paddr, 83)); - syslog(LOG_INFO, "%s: size=%ld, class=%ld, pri=%ld, nrcpts=%d", - e->e_id, e->e_msgsize, e->e_class, - e->e_msgpriority, e->e_nrcpts); + sm_syslog(LOG_INFO, e->e_id, + "from=%s", + e->e_from.q_paddr == NULL ? "<NONE>" + : shortenstring(e->e_from.q_paddr, 83)); + sm_syslog(LOG_INFO, e->e_id, + "size=%ld, class=%ld, pri=%ld, nrcpts=%d", + e->e_msgsize, e->e_class, e->e_msgpriority, e->e_nrcpts); if (msgid != NULL) - syslog(LOG_INFO, "%s: msgid=%s", - e->e_id, shortenstring(mbuf, 83)); + sm_syslog(LOG_INFO, e->e_id, + "msgid=%s", + shortenstring(mbuf, 83)); sbp = sbuf; - snprintf(sbp, SPACELEFT(sbuf, sbp), "%s:", e->e_id); - sbp += strlen(sbp); + *sbp = '\0'; if (e->e_bodytype != NULL) { - snprintf(sbp, SPACELEFT(sbuf, sbp), " bodytype=%.20s,", e->e_bodytype); + snprintf(sbp, SPACELEFT(sbuf, sbp), "bodytype=%.20s, ", e->e_bodytype); sbp += strlen(sbp); } p = macvalue('r', e); if (p != NULL) { - snprintf(sbp, SPACELEFT(sbuf, sbp), " proto=%.20s,", p); + snprintf(sbp, SPACELEFT(sbuf, sbp), "proto=%.20s, ", p); sbp += strlen(sbp); } - syslog(LOG_INFO, "%.400s relay=%.100s", sbuf, name); + sm_syslog(LOG_INFO, e->e_id, + "%.400srelay=%.100s", sbuf, name); # endif -# endif } /* ** PRIENCODE -- encode external priority names into internal values. @@ -788,7 +843,7 @@ crackaddr(addr) */ bp = bufhead = buf; - buflim = &buf[sizeof buf - 6]; + buflim = &buf[sizeof buf - 7]; p = addrhead = addr; copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0; bracklev = 0; @@ -1165,7 +1220,7 @@ putheader(mci, hdr, e) /* suppress return receipts if requested */ if (bitset(H_RECEIPTTO, h->h_flags) && -#if _FFR_DSN_RRT +#if _FFR_DSN_RRT_OPTION (RrtImpliesDsn || bitset(EF_NORECEIPT, e->e_flags))) #else bitset(EF_NORECEIPT, e->e_flags)) @@ -1181,7 +1236,7 @@ putheader(mci, hdr, e) { expand(p, buf, sizeof buf, e); p = buf; - if (p == NULL || *p == '\0') + if (*p == '\0') { if (tTd(34, 11)) printf(" (skipped -- null value)\n"); @@ -1275,7 +1330,7 @@ put_vanilla_header(h, v, mci) char obuf[MAXLINE]; putflags = 0; -#ifdef _FFR_7BITHDRS +#if _FFR_7BITHDRS if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags)) putflags |= PXLF_STRIP8BIT; #endif @@ -1290,7 +1345,7 @@ put_vanilla_header(h, v, mci) l = sizeof obuf - (obp - obuf); snprintf(obp, SPACELEFT(obuf, obp), "%.*s", l, v); - putxline(obuf, mci, putflags); + putxline(obuf, strlen(obuf), mci, putflags); v += l + 1; obp = obuf; if (*v != ' ' && *v != '\t') @@ -1298,7 +1353,7 @@ put_vanilla_header(h, v, mci) } snprintf(obp, SPACELEFT(obuf, obp), "%.*s", sizeof obuf - (obp - obuf) - 1, v); - putxline(obuf, mci, putflags); + putxline(obuf, strlen(obuf), mci, putflags); } /* ** COMMAIZE -- output a header field, making a comma-translated list. @@ -1340,7 +1395,7 @@ commaize(h, p, oldstyle, mci, e) if (tTd(14, 2)) printf("commaize(%s: %s)\n", h->h_field, p); -#ifdef _FFR_7BITHDRS +#if _FFR_7BITHDRS if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags)) putflags |= PXLF_STRIP8BIT; #endif @@ -1348,6 +1403,8 @@ commaize(h, p, oldstyle, mci, e) obp = obuf; (void) snprintf(obp, SPACELEFT(obuf, obp), "%.200s: ", h->h_field); opos = strlen(h->h_field) + 2; + if (opos > 202) + opos = 202; obp += opos; omax = mci->mci_mailer->m_linelimit - 2; if (omax < 0 || omax > 78) @@ -1441,7 +1498,7 @@ commaize(h, p, oldstyle, mci, e) if (opos > omax && !firstone) { snprintf(obp, SPACELEFT(obuf, obp), ",\n"); - putxline(obuf, mci, putflags); + putxline(obuf, strlen(obuf), mci, putflags); obp = obuf; (void) strcpy(obp, " "); opos = strlen(obp); @@ -1460,7 +1517,7 @@ commaize(h, p, oldstyle, mci, e) *p = savechar; } *obp = '\0'; - putxline(obuf, mci, putflags); + putxline(obuf, strlen(obuf), mci, putflags); } /* ** COPYHEADER -- copy header list diff --git a/usr.sbin/sendmail/src/macro.c b/usr.sbin/sendmail/src/macro.c index e31d0deb21c..0f31d11f3b4 100644 --- a/usr.sbin/sendmail/src/macro.c +++ b/usr.sbin/sendmail/src/macro.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983, 1995, 1996 Eric P. Allman + * Copyright (c) 1983, 1995-1997 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,7 +33,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)macro.c 8.17 (Berkeley) 5/13/96"; +static char sccsid[] = "@(#)macro.c 8.18 (Berkeley) 2/1/97"; #endif /* not lint */ # include "sendmail.h" diff --git a/usr.sbin/sendmail/src/main.c b/usr.sbin/sendmail/src/main.c index 3c30fb3e617..880b181ca25 100644 --- a/usr.sbin/sendmail/src/main.c +++ b/usr.sbin/sendmail/src/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983, 1995, 1996 Eric P. Allman + * Copyright (c) 1983, 1995-1997 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -39,7 +39,7 @@ static char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)main.c 8.230 (Berkeley) 1/17/97"; +static char sccsid[] = "@(#)main.c 8.246 (Berkeley) 6/11/97"; #endif /* not lint */ #define _DEFINE @@ -62,13 +62,8 @@ char edata, end; ** turn calls a bunch of mail servers that do the real work of ** delivering the mail. ** -** Sendmail is driven by tables read in from /usr/lib/sendmail.cf -** (read by readcf.c). Some more static configuration info, -** including some code that you may want to tailor for your -** installation, is in conf.c. You may also want to touch -** daemon.c (if you have some other IPC mechanism), acct.c -** (to change your accounting), names.c (to adjust the name -** server mechanism). +** Sendmail is driven by settings read in from /etc/sendmail.cf +** (read by readcf.c). ** ** Usage: ** /usr/lib/sendmail [flags] addr ... @@ -82,7 +77,7 @@ char edata, end; ** International Computer Science Institute ** (11/88 - 9/89). ** UCB/Mammoth Project (10/89 - 7/95). -** InReference, Inc. (8/95 - present). +** InReference, Inc. (8/95 - 1/97). ** The support of the my employers is gratefully acknowledged. ** Few of them (Britton-Lee in particular) have had ** anything to gain from my involvement in this project. @@ -99,6 +94,10 @@ char *CommandLineArgs; /* command line args for pid file */ bool Warn_Q_option = FALSE; /* warn about Q option use */ char **SaveArgv; /* argument vector for re-execing */ +#ifdef NGROUPS_MAX +GIDSET_T InitialGidSet[NGROUPS_MAX]; +#endif + static void obsolete(); extern void printmailer __P((MAILER *)); extern void tTflag __P((char *)); @@ -219,7 +218,7 @@ main(argc, argv, envp) } errno = 0; -#ifdef LOG +#if LOG # ifdef LOG_MAIL openlog("sendmail", LOG_PID, LOG_MAIL); # else @@ -229,6 +228,15 @@ main(argc, argv, envp) tTsetup(tTdvect, sizeof tTdvect, "0-99.1"); +#ifdef NGROUPS_MAX + /* save initial group set for future checks */ + i = getgroups(NGROUPS_MAX, InitialGidSet); + if (i == 0) + InitialGidSet[0] = (GID_T) -1; + while (i < NGROUPS_MAX) + InitialGidSet[i++] = InitialGidSet[0]; +#endif + /* drop group id privileges (RunAsUser not yet set) */ drop_privileges(); @@ -489,9 +497,6 @@ main(argc, argv, envp) #endif } - /* probe interfaces and locate any additional names */ - load_if_names(); - /* current time */ define('b', arpadate((char *) NULL), CurEnv); @@ -828,6 +833,10 @@ main(argc, argv, envp) expand("\201m", jbuf, sizeof jbuf, CurEnv); setclass('m', jbuf); + /* probe interfaces and locate any additional names */ + if (!DontProbeInterfaces) + load_if_names(); + if (tTd(0, 1)) { printf("\n============ SYSTEM IDENTITY (after readcf) ============"); @@ -880,6 +889,10 @@ main(argc, argv, envp) setuserenv("TZ", NULL); tzset(); + /* be sure we don't pick up bogus HOSTALIASES environment variable */ + if (queuemode && RealUid != 0) + (void) unsetenv("HOSTALIASES"); + /* check for sane configuration level */ if (ConfigLevel > MAXCONFIGLEVEL) { @@ -904,13 +917,12 @@ main(argc, argv, envp) /* check for permissions */ if ((OpMode == MD_DAEMON || OpMode == MD_PURGESTAT) && RealUid != 0) { -#ifdef LOG if (LogLevel > 1) - syslog(LOG_ALERT, "user %d attempted to %s", + sm_syslog(LOG_ALERT, NOQID, + "user %d attempted to %s", RealUid, OpMode == MD_DAEMON ? "run daemon" : "purge host status"); -#endif usrerr("Permission denied"); exit(EX_USAGE); } @@ -923,6 +935,8 @@ main(argc, argv, envp) case MD_TEST: /* don't have persistent host status in test mode */ HostStatDir = NULL; + Verbose = 2; + CurEnv->e_errormode = EM_PRINT; break; case MD_FGDAEMON: @@ -938,10 +952,9 @@ main(argc, argv, envp) GrabTo = FALSE; /* arrange to restart on hangup signal */ -#ifdef LOG if (SaveArgv[0] == NULL || SaveArgv[0][0] != '/') - syslog(LOG_WARNING, "daemon invoked without full pathname; kill -1 won't work"); -#endif + sm_syslog(LOG_WARNING, NOQID, + "daemon invoked without full pathname; kill -1 won't work"); setsignal(SIGHUP, sighup); /* workaround: can't seem to release the signal in the parent */ @@ -949,7 +962,8 @@ main(argc, argv, envp) break; case MD_INITALIAS: - Verbose = TRUE; + Verbose = 2; + CurEnv->e_errormode = EM_PRINT; /* fall through... */ case MD_PRINT: @@ -1088,17 +1102,23 @@ main(argc, argv, envp) #endif /* operate in queue directory */ - if (OpMode == MD_TEST) - /* nothing -- just avoid further if clauses */ ; - else if (QueueDir == NULL) + if (QueueDir == NULL) { - syserr("QueueDirectory (Q) option must be set"); - ExitStat = EX_CONFIG; + if (OpMode != MD_TEST) + { + syserr("QueueDirectory (Q) option must be set"); + ExitStat = EX_CONFIG; + } } - else if (chdir(QueueDir) < 0) + else { - syserr("cannot chdir(%s)", QueueDir); - ExitStat = EX_CONFIG; + /* test path to get warning messages */ + (void) safedirpath(QueueDir, (uid_t) 0, (gid_t) 0, NULL, SFF_ANYFILE); + if (OpMode != MD_TEST && chdir(QueueDir) < 0) + { + syserr("cannot chdir(%s)", QueueDir); + ExitStat = EX_CONFIG; + } } /* check host status directory for validity */ @@ -1226,7 +1246,7 @@ main(argc, argv, envp) SIGFUNC_DECL intindebug __P((int)); if (isatty(fileno(stdin))) - Verbose = TRUE; + Verbose = 2; if (Verbose) { @@ -1261,7 +1281,6 @@ main(argc, argv, envp) if (queuemode && OpMode != MD_DAEMON && QueueIntvl == 0) { - (void) unsetenv("HOSTALIASES"); (void) runqueue(FALSE, Verbose); finis(); } @@ -1305,9 +1324,8 @@ main(argc, argv, envp) if (tTd(0, 1)) strcat(dtype, "+debugging"); -#ifdef LOG - syslog(LOG_INFO, "starting daemon (%s): %s", Version, dtype + 1); -#endif + sm_syslog(LOG_INFO, NOQID, + "starting daemon (%s): %s", Version, dtype + 1); #ifdef XLA xla_create_file(); #endif @@ -1317,8 +1335,14 @@ main(argc, argv, envp) { (void) runqueue(TRUE, FALSE); if (OpMode != MD_DAEMON) + { for (;;) + { pause(); + if (DoQueueRun) + (void) runqueue(TRUE, FALSE); + } + } } # endif /* QUEUE */ dropenvelope(CurEnv, TRUE); @@ -1402,7 +1426,7 @@ main(argc, argv, envp) /* collect body for UUCP return */ if (OpMode != MD_VERIFY) - collect(InChannel, FALSE, FALSE, NULL, CurEnv); + collect(InChannel, FALSE, NULL, CurEnv); finis(); } @@ -1423,8 +1447,21 @@ main(argc, argv, envp) CurEnv->e_to = NULL; if (OpMode != MD_VERIFY || GrabTo) { + long savedflags = CurEnv->e_flags & EF_FATALERRS; + CurEnv->e_flags |= EF_GLOBALERRS; - collect(InChannel, FALSE, FALSE, NULL, CurEnv); + CurEnv->e_flags &= ~EF_FATALERRS; + collect(InChannel, FALSE, NULL, CurEnv); + + /* bail out if there were fatal errors in collect */ + if (OpMode != MD_VERIFY && bitset(EF_FATALERRS, CurEnv->e_flags)) + { + CurEnv->e_flags |= EF_CLRQUEUE; + finis(); + /*NOTREACHED*/ + return -1; + } + CurEnv->e_flags |= savedflags; } errno = 0; @@ -1443,6 +1480,7 @@ main(argc, argv, envp) printaddr(&CurEnv->e_from, FALSE); } CurEnv->e_to = NULL; + CurrentLA = getla(); sendall(CurEnv, SM_DEFAULT); /* @@ -1493,6 +1531,13 @@ finis() if (tTd(2, 9)) printopenfds(FALSE); + /* if we fail in finis(), just exit */ + if (setjmp(TopFrame) != 0) + { + /* failed -- just give it up */ + goto forceexit; + } + /* clean up temp files */ CurEnv->e_to = NULL; if (CurEnv->e_id != NULL) @@ -1507,10 +1552,11 @@ finis() # endif /* and exit */ -# ifdef LOG + forceexit: if (LogLevel > 78) - syslog(LOG_DEBUG, "finis, pid=%d", getpid()); -# endif /* LOG */ + sm_syslog(LOG_DEBUG, CurEnv->e_id, + "finis, pid=%d", + getpid()); if (ExitStat == EX_TEMPFAIL || CurEnv->e_errormode == EM_BERKNET) ExitStat = EX_OK; @@ -1540,11 +1586,8 @@ SIGFUNC_DECL intsig(sig) int sig; { -#ifdef LOG if (LogLevel > 79) - syslog(LOG_DEBUG, "%s: interrupt", - CurEnv->e_id == NULL ? "[NOQUEUE]" : CurEnv->e_id); -#endif + sm_syslog(LOG_DEBUG, CurEnv->e_id, "interrupt"); FileName = NULL; unlockqueue(CurEnv); #ifdef XLA @@ -1665,11 +1708,10 @@ disconnect(droplev, e) printf("don't\n"); return; } -#ifdef LOG if (LogLevel > 93) - syslog(LOG_DEBUG, "%s: disconnect level %d", - e->e_id == NULL ? "[NOQUEUE]" : e->e_id, droplev); -#endif + sm_syslog(LOG_DEBUG, e->e_id, + "disconnect level %d", + droplev); /* be sure we don't get nasty signals */ (void) setsignal(SIGINT, SIG_IGN); @@ -1678,7 +1720,7 @@ disconnect(droplev, e) /* we can't communicate with our caller, so.... */ HoldErrs = TRUE; CurEnv->e_errormode = EM_MAIL; - Verbose = FALSE; + Verbose = 0; DisConnected = TRUE; /* all input from /dev/null */ @@ -1719,10 +1761,10 @@ disconnect(droplev, e) checkfd012("disconnect"); #endif -# ifdef LOG if (LogLevel > 71) - syslog(LOG_DEBUG, "in background, pid=%d", getpid()); -# endif /* LOG */ + sm_syslog(LOG_DEBUG, e->e_id, + "in background, pid=%d", + getpid()); errno = 0; } @@ -1822,11 +1864,10 @@ auth_warning(e, msg, va_alist) vsnprintf(p, SPACELEFT(buf, p), msg, ap); VA_END; addheader("X-Authentication-Warning", buf, &e->e_header); -#ifdef LOG if (LogLevel > 3) - syslog(LOG_INFO, "%s: Authentication-Warning: %.400s", - e->e_id == NULL ? "[NOQUEUE]" : e->e_id, buf); -#endif + sm_syslog(LOG_INFO, e->e_id, + "Authentication-Warning: %.400s", + buf); } } /* @@ -1916,22 +1957,23 @@ void dumpstate(when) char *when; { -#ifdef LOG register char *j = macvalue('j', CurEnv); int rs; - syslog(LOG_DEBUG, "--- dumping state on %s: $j = %s ---", + sm_syslog(LOG_DEBUG, CurEnv->e_id, + "--- dumping state on %s: $j = %s ---", when, j == NULL ? "<NULL>" : j); if (j != NULL) { if (!wordinclass(j, 'w')) - syslog(LOG_DEBUG, "*** $j not in $=w ***"); + sm_syslog(LOG_DEBUG, CurEnv->e_id, + "*** $j not in $=w ***"); } - syslog(LOG_DEBUG, "CurChildren = %d", CurChildren); - syslog(LOG_DEBUG, "--- open file descriptors: ---"); + sm_syslog(LOG_DEBUG, CurEnv->e_id, "CurChildren = %d", CurChildren); + sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- open file descriptors: ---"); printopenfds(TRUE); - syslog(LOG_DEBUG, "--- connection cache: ---"); + sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- connection cache: ---"); mci_dump_all(TRUE); rs = strtorwset("debug_dumpstate", NULL, ST_FIND); if (rs > 0) @@ -1942,14 +1984,13 @@ dumpstate(when) pv[0] = NULL; stat = rewrite(pv, rs, 0, CurEnv); - syslog(LOG_DEBUG, + sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- ruleset debug_dumpstate returns stat %d, pv: ---", stat); for (pvp = pv; *pvp != NULL; pvp++) - syslog(LOG_DEBUG, "%s", *pvp); + sm_syslog(LOG_DEBUG, CurEnv->e_id, "%s", *pvp); } - syslog(LOG_DEBUG, "--- end of state dump ---"); -#endif + sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- end of state dump ---"); } @@ -1968,31 +2009,24 @@ sighup(sig) { if (SaveArgv[0][0] != '/') { -#ifdef LOG if (LogLevel > 3) - syslog(LOG_INFO, "could not restart: need full path"); -#endif + sm_syslog(LOG_INFO, NOQID, "could not restart: need full path"); exit(EX_OSFILE); } -#ifdef LOG if (LogLevel > 3) - syslog(LOG_INFO, "restarting %s on signal", SaveArgv[0]); -#endif + sm_syslog(LOG_INFO, NOQID, "restarting %s on signal", SaveArgv[0]); + alarm(0); releasesignal(SIGHUP); if (setgid(RealGid) < 0 || setuid(RealUid) < 0) { -#ifdef LOG if (LogLevel > 0) - syslog(LOG_ALERT, "could not set[ug]id(%d, %d): %m", + sm_syslog(LOG_ALERT, NOQID, "could not set[ug]id(%d, %d): %m", RealUid, RealGid); -#endif exit(EX_OSERR); } execv(SaveArgv[0], (ARGV_T) SaveArgv); -#ifdef LOG if (LogLevel > 0) - syslog(LOG_ALERT, "could not exec %s: %m", SaveArgv[0]); -#endif + sm_syslog(LOG_ALERT, NOQID, "could not exec %s: %m", SaveArgv[0]); exit(EX_OSFILE); } /* @@ -2285,6 +2319,11 @@ testmodeline(line, e) printf("Map named \"%s\" not found\n", p); return; } + if (!bitset(MF_OPEN, map->s_map.map_mflags)) + { + printf("Map named \"%s\" not open\n", p); + return; + } printf("map_lookup: %s (%s) ", p, q); p = (*map->s_map.map_class->map_lookup) (&map->s_map, q, NULL, &rcode); diff --git a/usr.sbin/sendmail/src/makesendmail b/usr.sbin/sendmail/src/makesendmail index 41b73202fae..a28e2f4cc4e 100644 --- a/usr.sbin/sendmail/src/makesendmail +++ b/usr.sbin/sendmail/src/makesendmail @@ -1,6 +1,6 @@ #!/bin/sh -# Copyright (c) 1993, 1996 Eric P. Allman +# Copyright (c) 1993, 1996-1997 Eric P. Allman # Copyright (c) 1993 The Regents of the University of California. # All rights reserved. # @@ -32,7 +32,7 @@ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # -# @(#)makesendmail 8.43 (Berkeley) 12/14/96 +# @(#)makesendmail 8.45 (Berkeley) 4/12/97 # # @@ -115,6 +115,16 @@ then # old versions of SCO UNIX set uname -s the same as uname -n os=SCO_SV fi +if [ "$os" = "$node" -a "$rel" = 4.0 -a "$arch" = "3360,3430-R" ] +then + # AT&T/NCR Machines also set uname -s == uname -n + if [ -d /usr/sadm/sysadm/add-ons/WIN-TCP ] + then + os=NCR.MP-RAS.2.x + else + os=NCR.MP-RAS.3.x + fi +fi case $os in diff --git a/usr.sbin/sendmail/src/map.c b/usr.sbin/sendmail/src/map.c index 3d40d62e511..e0a0fd24088 100644 --- a/usr.sbin/sendmail/src/map.c +++ b/usr.sbin/sendmail/src/map.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1992, 1995, 1996 Eric P. Allman. + * Copyright (c) 1992, 1995-1997 Eric P. Allman. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,7 +33,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)map.c 8.147 (Berkeley) 1/17/97"; +static char sccsid[] = "@(#)map.c 8.168 (Berkeley) 6/14/97"; #endif /* not lint */ #include "sendmail.h" @@ -107,11 +107,23 @@ static char sccsid[] = "@(#)map.c 8.147 (Berkeley) 1/17/97"; extern bool aliaswait __P((MAP *, char *, int)); extern bool extract_canonname __P((char *, char *, char[], int)); -#if O_EXLOCK && HASFLOCK +#if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL # define LOCK_ON_OPEN 1 /* we can open/create a locked file */ #else # define LOCK_ON_OPEN 0 /* no such luck -- bend over backwards */ #endif + +#ifndef O_LEAVELOCKED +# if O_SHLOCK +# define O_LEAVELOCKED O_SHLOCK +# else +# define O_LEAVELOCKED 0x1000 +# endif +#endif + +#ifndef O_ACCMODE +# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) +#endif /* ** MAP_PARSEARGS -- parse config line arguments for database lookup ** @@ -284,7 +296,7 @@ map_parseargs(map, ap) char * map_rewrite(map, s, slen, av) register MAP *map; - register char *s; + register const char *s; int slen; char **av; { @@ -314,14 +326,15 @@ map_rewrite(map, s, slen, av) i = len = slen; if (av != NULL) { - bp = s; - for (i = slen; --i >= 0 && (c = *bp++) != 0; ) + const char *sp = s; + + for (i = slen; --i >= 0 && (c = *sp++) != 0; ) { if (c != '%') continue; if (--i < 0) break; - c = *bp++; + c = *sp++; if (!(isascii(c) && isdigit(c))) continue; for (avp = av; --c >= '0' && *avp != NULL; avp++) @@ -675,11 +688,9 @@ extract_canonname(name, line, cbuf, cbuflen) int i; char *p; bool found = FALSE; - int l; extern char *get_column __P((char *, int, char, char *, int)); cbuf[0] = '\0'; - l = cbuflen; if (line[0] == '#') return FALSE; @@ -733,11 +744,49 @@ ndbm_map_open(map, mode) register DBM *dbm; struct stat st; int fd; + int sff; + int ret; + int smode = S_IREAD; + char dirfile[MAXNAME + 1]; + char pagfile[MAXNAME + 1]; + struct stat std, stp; if (tTd(38, 2)) printf("ndbm_map_open(%s, %s, %d)\n", map->map_mname, map->map_file, mode); map->map_lockfd = -1; + mode &= O_ACCMODE; + + /* do initial file and directory checks */ + snprintf(dirfile, sizeof dirfile, "%s.dir", map->map_file); + snprintf(pagfile, sizeof pagfile, "%s.pag", map->map_file); + sff = SFF_ROOTOK|SFF_REGONLY|SFF_CREAT; + if (mode == O_RDWR) + { + sff |= SFF_NOLINK; + smode = S_IWRITE; + } + else + { + sff |= SFF_NOWLINK; + } + if (FatalWritableDirs) + sff |= SFF_SAFEDIRPATH; + if ((ret = safefile(dirfile, RunAsUid, RunAsGid, RunAsUserName, + sff, smode, &std)) != 0 || + (ret = safefile(pagfile, RunAsUid, RunAsGid, RunAsUserName, + sff, smode, &stp)) != 0) + { + /* cannot open this map */ + if (tTd(38, 2)) + printf("\tunsafe map file: %d\n", ret); + if (!bitset(MF_OPTIONAL, map->map_mflags)) + syserr("dbm map \"%s\": unsafe map file %s", + map->map_mname, map->map_file); + return FALSE; + } + if (std.st_mode == ST_MODE_NOFILE) + mode |= O_EXCL; #if LOCK_ON_OPEN if (mode == O_RDONLY) @@ -745,12 +794,14 @@ ndbm_map_open(map, mode) else mode |= O_CREAT|O_TRUNC|O_EXLOCK; #else - if (mode == O_RDWR) + if ((mode & O_ACCMODE) == O_RDWR) { # if NOFTRUNCATE /* ** Warning: race condition. Try to lock the file as ** quickly as possible after opening it. + ** This may also have security problems on some systems, + ** but there isn't anything we can do about it. */ mode |= O_CREAT|O_TRUNC; @@ -763,13 +814,11 @@ ndbm_map_open(map, mode) int dirfd; int pagfd; - char dirfile[MAXNAME + 1]; - char pagfile[MAXNAME + 1]; - snprintf(dirfile, sizeof dirfile, "%s.dir", map->map_file); - snprintf(pagfile, sizeof pagfile, "%s.pag", map->map_file); - dirfd = open(dirfile, mode|O_CREAT, DBMMODE); - pagfd = open(pagfile, mode|O_CREAT, DBMMODE); + dirfd = safeopen(dirfile, mode|O_CREAT, DBMMODE, + SFF_NOLINK|SFF_CREAT|SFF_OPENASROOT); + pagfd = safeopen(pagfile, mode|O_CREAT, DBMMODE, + SFF_NOLINK|SFF_CREAT|SFF_OPENASROOT); if (dirfd < 0 || pagfd < 0) { @@ -779,9 +828,6 @@ ndbm_map_open(map, mode) close(pagfd); return FALSE; } - if (!lockfile(dirfd, map->map_file, ".dir", LOCK_EX)) - syserr("ndbm_map_open: cannot lock %s.dir", - map->map_file); if (ftruncate(dirfd, (off_t) 0) < 0) syserr("ndbm_map_open: cannot truncate %s.dir", map->map_file); @@ -805,8 +851,25 @@ ndbm_map_open(map, mode) return TRUE; if (!bitset(MF_OPTIONAL, map->map_mflags)) syserr("Cannot open DBM database %s", map->map_file); +#if !LOCK_ON_OPEN && !NOFTRUNCATE + if (map->map_lockfd >= 0) + close(map->map_lockfd); +#endif + return FALSE; + } + if (filechanged(dirfile, dbm_dirfno(dbm), &std, sff) || + filechanged(pagfile, dbm_pagfno(dbm), &stp, sff)) + { + syserr("ndbm_map_open(%s): file changed after open", + map->map_file); + dbm_close(dbm); +#if !LOCK_ON_OPEN && !NOFTRUNCATE + if (map->map_lockfd >= 0) + close(map->map_lockfd); +#endif return FALSE; } + map->map_db1 = (void *) dbm; fd = dbm_dirfno((DBM *) map->map_db1); if (mode == O_RDONLY) @@ -1036,7 +1099,7 @@ ndbm_map_close(map) ** be pokey about it. That's hard to do. */ -extern bool db_map_open __P((MAP *, int, DBTYPE, const void *)); +extern bool db_map_open __P((MAP *, int, char *, DBTYPE, const void *)); /* these should be K line arguments */ #ifndef DB_CACHE_SIZE @@ -1059,7 +1122,7 @@ bt_map_open(map, mode) bzero(&btinfo, sizeof btinfo); btinfo.cachesize = DB_CACHE_SIZE; - return db_map_open(map, mode, DB_BTREE, &btinfo); + return db_map_open(map, mode, "btree", DB_BTREE, &btinfo); } bool @@ -1076,32 +1139,65 @@ hash_map_open(map, mode) bzero(&hinfo, sizeof hinfo); hinfo.nelem = DB_HASH_NELEM; hinfo.cachesize = DB_CACHE_SIZE; - return db_map_open(map, mode, DB_HASH, &hinfo); + return db_map_open(map, mode, "hash", DB_HASH, &hinfo); } bool -db_map_open(map, mode, dbtype, openinfo) +db_map_open(map, mode, mapclassname, dbtype, openinfo) MAP *map; int mode; + char *mapclassname; DBTYPE dbtype; const void *openinfo; { DB *db; int i; int omode; + int smode = S_IREAD; int fd; + int sff; int saveerrno; + bool leavelocked = bitset(O_LEAVELOCKED, mode); struct stat st; char buf[MAXNAME + 1]; + /* do initial file and directory checks */ snprintf(buf, sizeof buf - 3, "%s", map->map_file); i = strlen(buf); if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) (void) strcat(buf, ".db"); - map->map_lockfd = -1; + mode &= O_ACCMODE; omode = mode; + sff = SFF_ROOTOK|SFF_REGONLY|SFF_CREAT; + if (mode == O_RDWR) + { + sff |= SFF_NOLINK; + smode = S_IWRITE; + } + else + { + sff |= SFF_NOWLINK; + } + if (FatalWritableDirs) + sff |= SFF_SAFEDIRPATH; + if ((i = safefile(buf, RunAsUid, RunAsGid, RunAsUserName, + sff, smode, &st)) != 0) + { + /* cannot open this map */ + if (tTd(38, 2)) + printf("\tunsafe map file: %d\n", i); + if (!bitset(MF_OPTIONAL, map->map_mflags)) + syserr("%s map \"%s\": unsafe map file %s", + mapclassname, map->map_mname, map->map_file); + return FALSE; + } + if (st.st_mode == ST_MODE_NOFILE) + omode |= O_EXCL; + + map->map_lockfd = -1; + #if LOCK_ON_OPEN if (mode == O_RDWR) omode |= O_CREAT|O_TRUNC|O_EXLOCK; @@ -1139,7 +1235,7 @@ db_map_open(map, mode, dbtype, openinfo) saveerrno = errno; #if !LOCK_ON_OPEN - if (mode == O_RDWR) + if (leavelocked || mode == O_RDWR) map->map_lockfd = fd; else (void) close(fd); @@ -1152,7 +1248,23 @@ db_map_open(map, mode, dbtype, openinfo) return TRUE; errno = saveerrno; if (!bitset(MF_OPTIONAL, map->map_mflags)) - syserr("Cannot open DB database %s", map->map_file); + syserr("Cannot open %s database %s", + mapclassname, map->map_file); +#if !LOCK_ON_OPEN + if (map->map_lockfd >= 0) + (void) close(map->map_lockfd); +#endif + return FALSE; + } + + if (filechanged(buf, db->fd(db), &st, sff)) + { + syserr("db_map_open(%s): file changed after open", buf); + db->close(db); +#if !LOCK_ON_OPEN + if (map->map_lockfd >= 0) + close(map->map_lockfd); +#endif return FALSE; } @@ -1161,7 +1273,7 @@ db_map_open(map, mode, dbtype, openinfo) #if !OLD_NEWDB fd = db->fd(db); # if LOCK_ON_OPEN - if (fd >= 0 && mode == O_RDONLY) + if (fd >= 0 && mode == O_RDONLY && !leavelocked) { (void) lockfile(fd, map->map_file, ".db", LOCK_UN); } @@ -1203,6 +1315,7 @@ db_map_lookup(map, name, av, statp) int st; int saveerrno; int fd; + struct stat stbuf; char keybuf[MAXNAME + 1]; if (tTd(38, 20)) @@ -1220,8 +1333,41 @@ db_map_lookup(map, name, av, statp) #if !OLD_NEWDB fd = db->fd(db); if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) - (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH); + (void) lockfile(fd, map->map_file, ".db", LOCK_SH); + if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime) + { + /* Reopen the database to sync the cache */ + int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR + : O_RDONLY; + + map->map_class->map_close(map); + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + omode |= O_LEAVELOCKED; + if (map->map_class->map_open(map, omode)) + { + map->map_mflags |= MF_OPEN; + if ((omode && O_ACCMODE) == O_RDWR) + map->map_mflags |= MF_WRITABLE; + db = (DB *) map->map_db2; + fd = db->fd(db); + } + else + { + if (!bitset(MF_OPTIONAL, map->map_mflags)) + { + extern MAPCLASS BogusMapClass; + + *statp = EX_TEMPFAIL; + map->map_class = &BogusMapClass; + map->map_mflags |= MF_OPEN; + syserr("Cannot reopen DB database %s", + map->map_file); + } + return NULL; + } + } #endif + st = 1; if (bitset(MF_TRY0NULL, map->map_mflags)) { @@ -1392,6 +1538,7 @@ nis_map_open(map, mode) printf("nis_map_open(%s, %s, %d)\n", map->map_mname, map->map_file, mode); + mode &= O_ACCMODE; if (mode != O_RDONLY) { /* issue a pseudo-error message */ @@ -1581,6 +1728,8 @@ nis_getcanonname(name, hbsize, statp) *statp = EX_UNAVAILABLE; return FALSE; } + if (vsize >= sizeof host_record) + vsize = sizeof host_record - 1; strncpy(host_record, vp, vsize); host_record[vsize] = '\0'; if (tTd(38, 44)) @@ -1637,6 +1786,7 @@ nisplus_map_open(map, mode) printf("nisplus_map_open(%s, %s, %d)\n", map->map_mname, map->map_file, mode); + mode &= O_ACCMODE; if (mode != O_RDONLY) { errno = ENODEV; @@ -1657,15 +1807,17 @@ nisplus_map_open(map, mode) map->map_file, map->map_domain); } if (!PARTIAL_NAME(map->map_file)) + { map->map_domain = newstr(""); - - /* check to see if this map actually exists */ - if (PARTIAL_NAME(map->map_file)) + snprintf(qbuf, sizeof qbuf, "%s", map->map_file); + } + else + { + /* check to see if this map actually exists */ snprintf(qbuf, sizeof qbuf, "%s.%s", map->map_file, map->map_domain); - else - strcpy(qbuf, map->map_file); - + } + retry_cnt = 0; while (res == NULL || res->status != NIS_SUCCESS) { @@ -1769,10 +1921,11 @@ nisplus_map_lookup(map, name, av, statp) char **av; int *statp; { - char *vp; + char *p; auto int vsize; - int buflen; - char search_key[MAXNAME + 1]; + char *skp; + int skleft; + char search_key[MAXNAME + 4]; char qbuf[MAXLINE + NIS_MAXNAMELEN]; nis_result *result; @@ -1791,11 +1944,40 @@ nisplus_map_lookup(map, name, av, statp) } } - buflen = strlen(name); - if (buflen > sizeof search_key - 1) - buflen = sizeof search_key - 1; - bcopy(name, search_key, buflen); - search_key[buflen] = '\0'; + /* + ** Copy the name to the key buffer, escaping double quote characters + ** by doubling them and quoting "]" and "," to avoid having the + ** NIS+ parser choke on them. + */ + + skleft = sizeof search_key - 4; + skp = search_key; + for (p = name; *p != '\0' && skleft > 0; p++) + { + switch (*p) + { + case ']': + case ',': + /* quote the character */ + *skp++ = '"'; + *skp++ = *p; + *skp++ = '"'; + skleft -= 3; + break; + + case '"': + /* double the quote */ + *skp++ = '"'; + skleft--; + /* fall through... */ + + default: + *skp++ = *p; + skleft--; + break; + } + } + *skp = '\0'; if (!bitset(MF_NOFOLDCASE, map->map_mflags)) makelower(search_key); @@ -1819,7 +2001,7 @@ nisplus_map_lookup(map, name, av, statp) if ((count = NIS_RES_NUMOBJ(result)) != 1) { if (LogLevel > 10) - syslog(LOG_WARNING, + sm_syslog(LOG_WARNING, CurEnv->e_id, "%s: lookup error, expected 1 entry, got %d", map->map_file, count); @@ -1829,18 +2011,18 @@ nisplus_map_lookup(map, name, av, statp) name, count); } - vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); + p = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); /* set the length of the result */ - if (vp == NULL) - vp = ""; - vsize = strlen(vp); + if (p == NULL) + p = ""; + vsize = strlen(p); if (tTd(38, 20)) printf("nisplus_map_lookup(%s), found %s\n", - name, vp); + name, p); if (bitset(MF_MATCHONLY, map->map_mflags)) str = map_rewrite(map, name, strlen(name), NULL); else - str = map_rewrite(map, vp, vsize, av); + str = map_rewrite(map, p, vsize, av); nis_freeresult(result); *statp = EX_OK; return str; @@ -1923,12 +2105,10 @@ nisplus_getcanonname(name, hbsize, statp) if ((count = NIS_RES_NUMOBJ(result)) != 1) { -#ifdef LOG if (LogLevel > 10) - syslog(LOG_WARNING, + sm_syslog(LOG_WARNING, CurEnv->e_id, "nisplus_getcanonname: lookup error, expected 1 entry, got %d", count); -#endif /* ignore second entry */ if (tTd(38, 20)) @@ -2031,6 +2211,7 @@ ldap_map_open(map, mode) if (tTd(38, 2)) printf("ldap_map_open(%s, %d)\n", map->map_mname, mode); + mode &= O_ACCMODE; if (mode != O_RDONLY) { /* issue a pseudo-error message */ @@ -2207,7 +2388,7 @@ ldap_map_lookup(map, name, av, statp) snprintf(filter, sizeof filter, lmap->filter, keybuf); if (ldap_search_st(lmap->ld, lmap->base,lmap->scope,filter, - &(lmap->attr), lmap->attrsonly, &(lmap->timeout), + lmap->attr, lmap->attrsonly, &(lmap->timeout), &(lmap->res)) != LDAP_SUCCESS) { /* try close/opening map */ @@ -2219,7 +2400,7 @@ ldap_map_lookup(map, name, av, statp) goto quick_exit; } if (ldap_search_st(lmap->ld, lmap->base, lmap->scope, filter, - &(lmap->attr), lmap->attrsonly, + lmap->attr, lmap->attrsonly, &(lmap->timeout), &(lmap->res)) != LDAP_SUCCESS) { @@ -2243,7 +2424,7 @@ ldap_map_lookup(map, name, av, statp) } /* Need to build the args for map_rewrite here */ - attr_values = ldap_get_values(lmap->ld,entry,lmap->attr); + attr_values = ldap_get_values(lmap->ld,entry,lmap->attr[0]); if (attr_values == NULL) { /* bad things happened */ @@ -2258,12 +2439,10 @@ ldap_map_lookup(map, name, av, statp) vp = attr_values[0]; vsize = strlen(vp); -# ifdef LOG if (LogLevel > 9) - syslog(LOG_INFO, "%s: ldap %.100s => %s", - CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id, + sm_syslog(LOG_INFO, CurEnv->e_id, + "ldap %.100s => %s", name, vp); -# endif if (bitset(MF_MATCHONLY, map->map_mflags)) result = map_rewrite(map, name, strlen(name), NULL); else @@ -2398,7 +2577,8 @@ ldap_map_parseargs(map,args) case 'v': /* attr to return */ while (isascii(*++p) && isspace(*p)) continue; - lmap->attr = p; + lmap->attr[0] = p; + lmap->attr[1] = NULL; break; /* args stolen from ldapsearch.c */ @@ -2538,8 +2718,8 @@ ldap_map_parseargs(map,args) return FALSE; } } - if (lmap->attr != NULL) - lmap->attr = newstr(ldap_map_dequote(lmap->attr)); + if (lmap->attr[0] != NULL) + lmap->attr[0] = newstr(ldap_map_dequote(lmap->attr[0])); else { if (!bitset(MCF_OPTFILE, map->map_class->map_cflags)) @@ -2690,6 +2870,7 @@ ni_map_open(map, mode) if (tTd(38, 2)) printf("ni_map_open(%s, %s, %d)\n", map->map_mname, map->map_file, mode); + mode &= O_ACCMODE; if (*map->map_file == '\0') map->map_file = NETINFO_DEFAULT_DIR; @@ -2970,6 +3151,8 @@ ni_propval(keydir, keyprop, keyval, valprop, sepchar) ** This code donated by Sun Microsystems. */ +#define map_sff map_lockfd /* overload field */ + /* ** TEXT_MAP_OPEN -- open text table @@ -2980,12 +3163,14 @@ text_map_open(map, mode) MAP *map; int mode; { - struct stat sbuf; + int sff; + int i; if (tTd(38, 2)) printf("text_map_open(%s, %s, %d)\n", map->map_mname, map->map_file, mode); + mode &= O_ACCMODE; if (mode != O_RDONLY) { errno = ENODEV; @@ -3005,33 +3190,22 @@ text_map_open(map, mode) map->map_mname); return FALSE; } - /* check to see if this map actually accessable */ - if (access(map->map_file, R_OK) <0) + + sff = SFF_ROOTOK|SFF_REGONLY|SFF_NOWLINK; + if (FatalWritableDirs) + sff |= SFF_SAFEDIRPATH; + if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName, + sff, S_IRUSR, NULL)) != 0) { + /* cannot open this map */ if (tTd(38, 2)) - printf("text_map_open(%s, %s): cannot access: %s\n", - map->map_mname, map->map_file, errstring(errno)); + printf("\tunsafe map file: %d\n", i); if (!bitset(MF_OPTIONAL, map->map_mflags)) - syserr("text map \"%s\": cannot access file %s", + syserr("text map \"%s\": unsafe map file %s", map->map_mname, map->map_file); return FALSE; } - /* check to see if this map actually exist */ - if (stat(map->map_file, &sbuf) <0) - { - syserr("text_map_open(%s, %s): cannot stat", - map->map_mname, map->map_file); - return FALSE; - } - - if (!S_ISREG(sbuf.st_mode)) - { - syserr("text map \"%s\": %s is not a regular file", - map->map_mname, map->map_file); - return FALSE; - } - if (map->map_keycolnm == NULL) map->map_keycolno = 0; else @@ -3070,6 +3244,7 @@ text_map_open(map, mode) printf("%c\n", map->map_coldelim); } + map->map_sff = sff; return TRUE; } @@ -3088,13 +3263,14 @@ text_map_lookup(map, name, av, statp) char *vp; auto int vsize; int buflen; - char search_key[MAXNAME + 1]; - char linebuf[MAXLINE]; FILE *f; - char buf[MAXNAME + 1]; char delim; int key_idx; bool found_it; + int sff = map->map_sff; + char search_key[MAXNAME + 1]; + char linebuf[MAXLINE]; + char buf[MAXNAME + 1]; extern char *get_column __P((char *, int, char, char *, int)); found_it = FALSE; @@ -3109,7 +3285,7 @@ text_map_lookup(map, name, av, statp) if (!bitset(MF_NOFOLDCASE, map->map_mflags)) makelower(search_key); - f = fopen(map->map_file, "r"); + f = safefopen(map->map_file, O_RDONLY, FileMode, sff); if (f == NULL) { map->map_mflags &= ~(MF_VALID|MF_OPEN); @@ -3166,7 +3342,6 @@ text_getcanonname(name, hbsize, statp) char linebuf[MAXLINE]; char cbuf[MAXNAME + 1]; char nbuf[MAXNAME + 1]; - extern char *get_column __P((char *, int, char, char *, int)); if (tTd(38, 20)) printf("text_getcanonname(%s)\n", name); @@ -3272,19 +3447,24 @@ stab_map_open(map, mode) int mode; { FILE *af; + int sff; struct stat st; if (tTd(38, 2)) printf("stab_map_open(%s, %s, %d)\n", map->map_mname, map->map_file, mode); + mode &= O_ACCMODE; if (mode != O_RDONLY) { errno = ENODEV; return FALSE; } - af = fopen(map->map_file, "r"); + sff = SFF_ROOTOK|SFF_REGONLY|SFF_NOWLINK; + if (FatalWritableDirs) + sff |= SFF_SAFEDIRPATH; + af = safefopen(map->map_file, O_RDONLY, 0444, sff); if (af == NULL) return FALSE; readaliases(map, af, FALSE, FALSE); @@ -3365,6 +3545,7 @@ impl_map_open(map, mode) printf("impl_map_open(%s, %s, %d)\n", map->map_mname, map->map_file, mode); + mode &= O_ACCMODE; #ifdef NEWDB map->map_mflags |= MF_IMPL_HASH; if (hash_map_open(map, mode)) @@ -3447,6 +3628,7 @@ user_map_open(map, mode) printf("user_map_open(%s, %d)\n", map->map_mname, mode); + mode &= O_ACCMODE; if (mode != O_RDONLY) { /* issue a pseudo-error message */ @@ -3768,6 +3950,7 @@ switch_map_open(map, mode) printf("switch_map_open(%s, %s, %d)\n", map->map_mname, map->map_file, mode); + mode &= O_ACCMODE; nmaps = switch_map_find(map->map_file, maptype, map->map_return); if (tTd(38, 19)) { diff --git a/usr.sbin/sendmail/src/mci.c b/usr.sbin/sendmail/src/mci.c index a81e61de2c7..f8ba789ff8a 100644 --- a/usr.sbin/sendmail/src/mci.c +++ b/usr.sbin/sendmail/src/mci.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 1996 Eric P. Allman + * Copyright (c) 1995-1997 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,7 +33,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)mci.c 8.54 (Berkeley) 12/1/96"; +static char sccsid[] = "@(#)mci.c 8.62 (Berkeley) 5/29/97"; #endif /* not lint */ #include "sendmail.h" @@ -116,12 +116,10 @@ mci_cache(mci) if (tTd(42, 5)) printf("mci_cache: caching %lx (%s) in slot %d\n", (u_long) mci, mci->mci_host, mcislot - MciCache); -#ifdef LOG if (tTd(91, 100)) - syslog(LOG_DEBUG, "%s: mci_cache: caching %x (%.100s) in slot %d", - CurEnv->e_id ? CurEnv->e_id : "NOQUEUE", + sm_syslog(LOG_DEBUG, CurEnv->e_id, + "mci_cache: caching %x (%.100s) in slot %d", mci, mci->mci_host, mcislot - MciCache); -#endif *mcislot = mci; mci->mci_flags |= MCIF_CACHED; @@ -216,12 +214,10 @@ mci_uncache(mcislot, doquit) if (tTd(42, 5)) printf("mci_uncache: uncaching %lx (%s) from slot %d (%d)\n", (u_long) mci, mci->mci_host, mcislot - MciCache, doquit); -#ifdef LOG if (tTd(91, 100)) - syslog(LOG_DEBUG, "%s: mci_uncache: uncaching %x (%.100s) from slot %d (%d)", - CurEnv->e_id ? CurEnv->e_id : "NOQUEUE", + sm_syslog(LOG_DEBUG, CurEnv->e_id, + "mci_uncache: uncaching %x (%.100s) from slot %d (%d)", mci, mci->mci_host, mcislot - MciCache, doquit); -#endif #if SMTP if (doquit) @@ -485,11 +481,9 @@ mci_dump(mci, logit) mci->mci_host == NULL ? "NULL" : mci->mci_host, ctime(&mci->mci_lastuse)); printit: -#ifdef LOG if (logit) - syslog(LOG_DEBUG, "%.1000s", buf); + sm_syslog(LOG_DEBUG, CurEnv->e_id, "%.1000s", buf); else -#endif printf("%s\n", buf); } /* @@ -577,8 +571,8 @@ mci_lock_host_statfile(mci) goto cleanup; } - if ((mci->mci_statfile = fopen(fname, "r+")) == NULL) - mci->mci_statfile = fopen(fname, "w"); + mci->mci_statfile = safefopen(fname, O_RDWR|O_CREAT, FileMode, + SFF_NOLOCK|SFF_NOLINK|SFF_OPENASROOT|SFF_REGONLY|SFF_CREAT); if (mci->mci_statfile == NULL) { @@ -699,7 +693,8 @@ mci_load_persistent(mci) goto cleanup; } - fp = fopen(fname, "r"); + fp = safefopen(fname, O_RDONLY, FileMode, + SFF_NOLOCK|SFF_NOLINK|SFF_OPENASROOT|SFF_REGONLY); if (fp == NULL) { /* I can't think of any reason this should ever happen */ @@ -744,6 +739,7 @@ mci_read_persistent(fp, mci) { int ver; register char *p; + int saveLineNumber = LineNumber; char buf[MAXLINE]; if (fp == NULL) @@ -763,8 +759,10 @@ mci_read_persistent(fp, mci) rewind(fp); ver = -1; + LineNumber = 0; while (fgets(buf, sizeof buf, fp) != NULL) { + LineNumber++; p = strchr(buf, '\n'); if (p != NULL) *p = '\0'; @@ -806,9 +804,11 @@ mci_read_persistent(fp, mci) default: syserr("Unknown host status line \"%s\"", buf); + LineNumber = saveLineNumber; return -1; } } + LineNumber = saveLineNumber; if (ver < 0) return -1; return 0; @@ -1053,7 +1053,8 @@ mci_print_persistent(pathname, hostname) printf(" -------------- Hostname --------------- How long ago ---------Results---------\n"); } - fp = fopen(pathname, "r+"); + fp = safefopen(pathname, O_RDWR, FileMode, + SFF_NOLOCK|SFF_NOLINK|SFF_OPENASROOT|SFF_REGONLY); if (fp == NULL) { @@ -1063,16 +1064,19 @@ mci_print_persistent(pathname, hostname) return 0; } + FileName = pathname; bzero(&mcib, sizeof mcib); if (mci_read_persistent(fp, &mcib) < 0) { syserr("%s: could not read status file", pathname); fclose(fp); + FileName = NULL; return 0; } locked = !lockfile(fileno(fp), pathname, "", LOCK_EX|LOCK_NB); fclose(fp); + FileName = NULL; printf("%c%-39s %12s ", locked ? '*' : ' ', hostname, @@ -1193,13 +1197,22 @@ mci_generate_persistent_path(host, path, pathlen, createflag) */ if (host == NULL) + { syserr("mci_generate_persistent_path: null host"); + return -1; + } if (path == NULL) + { syserr("mci_generate_persistent_path: null path"); + return -1; + } if (tTd(56, 80)) printf("mci_generate_persistent_path(%s): ", host); + if (*host == '\0') + return -1; + /* make certain this is not a bracketed host number */ if (strlen(host) > sizeof t_host - 1) return -1; @@ -1214,16 +1227,19 @@ mci_generate_persistent_path(host, path, pathlen, createflag) */ elem = t_host + strlen(t_host); - while (elem > t_host && (elem[-1] == '.' || elem[-1] == ']')) + while (elem > t_host && + (elem[-1] == '.' || (host[0] == '[' && elem[-1] == ']'))) *--elem = '\0'; /* check for what will be the final length of the path */ len = strlen(HostStatDir) + 2; for (p = (char *) host; *p != '\0'; p++) { - if (*p == '|' || *p != '.') + if (*p == '|' || *p == '.') len++; len++; + if (p[0] == '.' && p[1] == '.') + return -1; } if (len > pathlen) return -1; diff --git a/usr.sbin/sendmail/src/mime.c b/usr.sbin/sendmail/src/mime.c index 999c5ab5897..3e5a610bb39 100644 --- a/usr.sbin/sendmail/src/mime.c +++ b/usr.sbin/sendmail/src/mime.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 1996 Eric P. Allman + * Copyright (c) 1994, 1996-1997 Eric P. Allman * Copyright (c) 1994 * The Regents of the University of California. All rights reserved. * @@ -36,7 +36,7 @@ # include <string.h> #ifndef lint -static char sccsid[] = "@(#)mime.c 8.54 (Berkeley) 1/14/97"; +static char sccsid[] = "@(#)mime.c 8.59 (Berkeley) 5/6/97"; #endif /* not lint */ /* @@ -259,10 +259,10 @@ mime8to7(mci, header, e, boundaries, flags) if (strcasecmp(argv[i].field, "boundary") == 0) break; } - if (i >= argc) + if (i >= argc || argv[i].value == NULL) { - syserr("mime8to7: Content-Type: \"%s\": missing boundary", - p); + syserr("mime8to7: Content-Type: \"%s\": %s boundary", + i >= argc ? "missing" : "bogus", p); p = "---"; /* avoid bounce loops */ @@ -311,7 +311,7 @@ mime8to7(mci, header, e, boundaries, flags) bt = mimeboundary(buf, boundaries); if (bt != MBT_NOTSEP) break; - putxline(buf, mci, PXLF_MAPFROM|PXLF_STRIP8BIT); + putxline(buf, strlen(buf), mci, PXLF_MAPFROM|PXLF_STRIP8BIT); if (tTd(43, 99)) printf(" ...%s", buf); } @@ -325,7 +325,7 @@ mime8to7(mci, header, e, boundaries, flags) putline(buf, mci); if (tTd(43, 35)) printf(" ...%s\n", buf); - collect(e->e_dfp, FALSE, FALSE, &hdr, e); + collect(e->e_dfp, FALSE, &hdr, e); if (tTd(43, 101)) putline("+++after collect", mci); putheader(mci, hdr, e); @@ -346,7 +346,7 @@ mime8to7(mci, header, e, boundaries, flags) bt = mimeboundary(buf, boundaries); if (bt != MBT_NOTSEP) break; - putxline(buf, mci, PXLF_MAPFROM|PXLF_STRIP8BIT); + putxline(buf, strlen(buf), mci, PXLF_MAPFROM|PXLF_STRIP8BIT); if (tTd(43, 99)) printf(" ...%s", buf); } @@ -377,7 +377,7 @@ mime8to7(mci, header, e, boundaries, flags) putline("", mci); mci->mci_flags |= MCIF_INMIME; - collect(e->e_dfp, FALSE, FALSE, &hdr, e); + collect(e->e_dfp, FALSE, &hdr, e); if (tTd(43, 101)) putline("+++after collect", mci); putheader(mci, hdr, e); @@ -1048,8 +1048,8 @@ mime7to8(mci, header, e) if (*--fbufp != '\n' || (fbufp > fbuf && *--fbufp != '\r')) fbufp++; - *fbufp = '\0'; - putline((char *) fbuf, mci); + putxline((char *) fbuf, fbufp - fbuf, + mci, PXLF_MAPFROM); fbufp = fbuf; } if (c3 == '=') @@ -1061,8 +1061,8 @@ mime7to8(mci, header, e) if (*--fbufp != '\n' || (fbufp > fbuf && *--fbufp != '\r')) fbufp++; - *fbufp = '\0'; - putline((char *) fbuf, mci); + putxline((char *) fbuf, fbufp - fbuf, + mci, PXLF_MAPFROM); fbufp = fbuf; } if (c4 == '=') @@ -1074,8 +1074,8 @@ mime7to8(mci, header, e) if (*--fbufp != '\n' || (fbufp > fbuf && *--fbufp != '\r')) fbufp++; - *fbufp = '\0'; - putline((char *) fbuf, mci); + putxline((char *) fbuf, fbufp - fbuf, + mci, PXLF_MAPFROM); fbufp = fbuf; } } @@ -1090,7 +1090,9 @@ mime7to8(mci, header, e) &fbuf[MAXLINE] - fbufp) == 0) continue; - putline((char *) fbuf, mci); + if (fbufp - fbuf > 0) + putxline((char *) fbuf, fbufp - fbuf - 1, mci, + PXLF_MAPFROM); fbufp = fbuf; } } @@ -1099,7 +1101,7 @@ mime7to8(mci, header, e) if (fbufp > fbuf) { *fbufp = '\0'; - putline((char *) fbuf, mci); + putxline((char *) fbuf, fbufp - fbuf, mci, PXLF_MAPFROM); } if (tTd(43, 3)) printf("\t\t\tmime7to8 => %s to 8bit done\n", cte); diff --git a/usr.sbin/sendmail/src/newaliases.1 b/usr.sbin/sendmail/src/newaliases.1 index c611b78b62b..7168c1303f4 100644 --- a/usr.sbin/sendmail/src/newaliases.1 +++ b/usr.sbin/sendmail/src/newaliases.1 @@ -1,3 +1,4 @@ +.\" Copyright (c) 1983, 1997 Eric P. Allman .\" Copyright (c) 1985, 1990, 1993 .\" The Regents of the University of California. All rights reserved. .\" @@ -29,9 +30,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" @(#)newaliases.1 8.4 (Berkeley) 2/22/94 +.\" @(#)newaliases.1 8.5 (Berkeley) 2/1/97 .\" -.Dd February 22, 1994 +.Dd February 1, 1997 .Dt NEWALIASES 1 .Os BSD 4 .Sh NAME |
