diff options
author | gshapiro <gshapiro@FreeBSD.org> | 2001-05-28 17:08:52 +0000 |
---|---|---|
committer | gshapiro <gshapiro@FreeBSD.org> | 2001-05-28 17:08:52 +0000 |
commit | 5338b6ff5f88e435da457fd0ec979a333012a0ef (patch) | |
tree | a5a76aa374529c5644a8991fe62c81f6b9b89964 /contrib/sendmail/src | |
parent | 8d82727087db5182be90a20f20175cc720c5d1e5 (diff) | |
download | FreeBSD-src-5338b6ff5f88e435da457fd0ec979a333012a0ef.zip FreeBSD-src-5338b6ff5f88e435da457fd0ec979a333012a0ef.tar.gz |
Import sendmail 8.11.4
Diffstat (limited to 'contrib/sendmail/src')
33 files changed, 1690 insertions, 662 deletions
diff --git a/contrib/sendmail/src/README b/contrib/sendmail/src/README index fc8917a..53380d5 100644 --- a/contrib/sendmail/src/README +++ b/contrib/sendmail/src/README @@ -9,7 +9,7 @@ # the sendmail distribution. # # -# $Id: README,v 8.263.2.1.2.32 2001/01/29 23:45:22 gshapiro Exp $ +# $Id: README,v 8.263.2.1.2.35 2001/05/09 20:58:32 gshapiro Exp $ # This directory contains the source files for sendmail(TM). @@ -459,6 +459,9 @@ SNPRINTF_IS_BROKEN Set this if your system has an snprintf() implementation which does not NUL terminate the string being filled in. Use test/t_snprintf.c to test your system. +NEEDSGETIPNODE Set this if your system supports IPv6 but doesn't include + the getipnodeby{name,addr}() functions. Set automatically + for Linux's glibc. +-----------------------+ | COMPILE-TIME FEATURES | @@ -1448,6 +1451,21 @@ UNICOS 8.0.3.4 problems. You may want to turn this off if you have problems running sendmail. Reported by Jerry G. DeLapp <jgd@acl.lanl.gov>. +Mac OS X (10.0.X) + From: Mike Zimmerman <zimmy@torrentnet.com> + From scratch here is what Darwin users need to do to the standard + 10.0.0, 10.0.1 install to get sendmail working. + From http://www.macosx.com/forums/showthread.php?s=6dac0e9e1f3fd118a4870a8a9b559491&threadid=2242: + 1. chmod g-w / /private /private/etc + 2. Properly set HOSTNAME in /etc/hostconfig to your FQDN: + HOSTNAME=-my.domain.com- + 3. Edit /etc/rc.boot: + hostname my.domain.com + domainname domain.com + 4. Edit /System/Library/StartupItems/Sendmail/Sendmail: + Remove the "&" after the sendmail command: + /usr/sbin/sendmail -bd -q1h + GNU getopt I'm told that GNU getopt has a problem in that it gets confused by the double call. Use the version in conf.c instead. @@ -1688,4 +1706,4 @@ util.c Some general purpose routines used by sendmail. version.c The version number and information about this version of sendmail. -(Version $Revision: 8.263.2.1.2.32 $, last update $Date: 2001/01/29 23:45:22 $ ) +(Version $Revision: 8.263.2.1.2.35 $, last update $Date: 2001/05/09 20:58:32 $ ) diff --git a/contrib/sendmail/src/TRACEFLAGS b/contrib/sendmail/src/TRACEFLAGS index b48e75d..09f7d35 100644 --- a/contrib/sendmail/src/TRACEFLAGS +++ b/contrib/sendmail/src/TRACEFLAGS @@ -1,4 +1,4 @@ -# $Id: TRACEFLAGS,v 8.29 1999/11/04 23:31:02 gshapiro Exp $ +# $Id: TRACEFLAGS,v 8.29.16.1 2001/05/03 17:24:00 gshapiro Exp $ 0, 1 main.c main skip background fork 0, 4 main.c main canonical name, UUCP node name, a.k.a.s 0, 15 main.c main print configuration @@ -75,6 +75,7 @@ 62 multiple file descriptor checking 63 queue.c runqueue process watching 64 multiple Milter +67 conf.c signals 80 content length 81 sun remote mode 91 mci.c syslogging of MCI cache information diff --git a/contrib/sendmail/src/alias.c b/contrib/sendmail/src/alias.c index 4c6a174..070da59 100644 --- a/contrib/sendmail/src/alias.c +++ b/contrib/sendmail/src/alias.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -13,7 +13,7 @@ #include <sendmail.h> #ifndef lint -static char id[] = "@(#)$Id: alias.c,v 8.142.4.9 2000/11/08 20:58:42 geir Exp $"; +static char id[] = "@(#)$Id: alias.c,v 8.142.4.11 2001/05/03 17:24:01 gshapiro Exp $"; #endif /* ! lint */ # define SEPARATOR ':' @@ -405,8 +405,9 @@ aliaswait(map, ext, isopen) dprintf("aliaswait: sleeping for %u seconds\n", sleeptime); + map->map_mflags |= MF_CLOSING; map->map_class->map_close(map); - map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); (void) sleep(sleeptime); sleeptime *= 2; if (sleeptime > 60) @@ -449,8 +450,9 @@ aliaswait(map, ext, isopen) SuprErrs = TRUE; if (isopen) { + map->map_mflags |= MF_CLOSING; map->map_class->map_close(map); - map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); } (void) rebuildaliases(map, TRUE); isopen = map->map_class->map_open(map, O_RDONLY); @@ -595,8 +597,9 @@ rebuildaliases(map, automatic) /* add distinguished entries and close the database */ if (bitset(MF_OPEN, map->map_mflags)) { + map->map_mflags |= MF_CLOSING; map->map_class->map_close(map); - map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); } /* restore the old signals */ @@ -827,11 +830,11 @@ readaliases(map, af, announcestats, logstats) } if (al.q_paddr != NULL) - free(al.q_paddr); + sm_free(al.q_paddr); if (al.q_host != NULL) - free(al.q_host); + sm_free(al.q_host); if (al.q_user != NULL) - free(al.q_user); + sm_free(al.q_user); } CurEnv->e_to = NULL; diff --git a/contrib/sendmail/src/arpadate.c b/contrib/sendmail/src/arpadate.c index c265cdb..c67c3b9 100644 --- a/contrib/sendmail/src/arpadate.c +++ b/contrib/sendmail/src/arpadate.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998, 1999, 2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: arpadate.c,v 8.23 1999/09/23 19:59:18 ca Exp $"; +static char id[] = "@(#)$Id: arpadate.c,v 8.23.20.2 2001/05/07 22:07:26 gshapiro Exp $"; #endif /* ! lint */ #include <sendmail.h> @@ -117,11 +117,12 @@ arpadate(ud) *q++ = *p++; /* - * should really get the timezone from the time in "ud" (which - * is only different if a non-null arg was passed which is different - * from the current time), but for all practical purposes, returning - * the current local zone will do (its all that is ever needed). - */ + ** should really get the timezone from the time in "ud" (which + ** is only different if a non-null arg was passed which is different + ** from the current time), but for all practical purposes, returning + ** the current local zone will do (its all that is ever needed). + */ + gmt = *gmtime(&t); lt = localtime(&t); diff --git a/contrib/sendmail/src/bf_portable.c b/contrib/sendmail/src/bf_portable.c index 3c09cec..f14077f 100644 --- a/contrib/sendmail/src/bf_portable.c +++ b/contrib/sendmail/src/bf_portable.c @@ -11,7 +11,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: bf_portable.c,v 8.25.4.5 2001/02/14 04:07:27 gshapiro Exp $"; +static char id[] = "@(#)$Id: bf_portable.c,v 8.25.4.6 2001/05/03 17:24:01 gshapiro Exp $"; #endif /* ! lint */ #if SFIO @@ -28,9 +28,12 @@ static char id[] = "@(#)$Id: bf_portable.c,v 8.25.4.5 2001/02/14 04:07:27 gshapi #if !SFIO # include <stdio.h> #endif /* !SFIO */ -#ifndef BF_STANDALONE +#ifdef BF_STANDALONE +# define sm_free free +# define xalloc malloc +#else /* BF_STANDALONE */ # include "sendmail.h" -#endif /* ! BF_STANDALONE */ +#endif /* BF_STANDALONE */ #include "bf_portable.h" #include "bf.h" @@ -95,7 +98,7 @@ bfopen(filename, fmode, bsize, flags) } /* Allocate memory */ - bfp = (struct bf *)malloc(sizeof(struct bf)); + bfp = (struct bf *)xalloc(sizeof(struct bf)); if (bfp == NULL) { (void) fclose(retval); @@ -110,10 +113,10 @@ bfopen(filename, fmode, bsize, flags) filename, (long) sizeof(struct bf)); l = strlen(filename) + 1; - bfp->bf_filename = (char *)malloc(l); + bfp->bf_filename = (char *)xalloc(l); if (bfp->bf_filename == NULL) { - free(bfp); + sm_free(bfp); (void) fclose(retval); /* don't care about errors */ @@ -224,7 +227,6 @@ bfrewind(fp) /* check to see if there is an error on the stream */ err = ferror(fp); - (void) fflush(fp); /* @@ -379,8 +381,8 @@ bfclose(fp) if (!bfp->bf_committed) retval = unlink(bfp->bf_filename); - free(bfp->bf_filename); - free(bfp); + sm_free(bfp->bf_filename); + sm_free(bfp); if (tTd(58, 8)) dprintf("bfclose: freed %ld\n", (long) sizeof(struct bf)); diff --git a/contrib/sendmail/src/bf_torek.c b/contrib/sendmail/src/bf_torek.c index d58abc9..f74aecd 100644 --- a/contrib/sendmail/src/bf_torek.c +++ b/contrib/sendmail/src/bf_torek.c @@ -11,7 +11,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: bf_torek.c,v 8.19.18.4 2001/02/14 04:07:27 gshapiro Exp $"; +static char id[] = "@(#)$Id: bf_torek.c,v 8.19.18.6 2001/05/08 06:52:19 gshapiro Exp $"; #endif /* ! lint */ #if SFIO @@ -26,9 +26,12 @@ static char id[] = "@(#)$Id: bf_torek.c,v 8.19.18.4 2001/02/14 04:07:27 gshapiro #include <string.h> #include <errno.h> #include <stdio.h> -#ifndef BF_STANDALONE +#ifdef BF_STANDALONE +# define sm_free free +# define xalloc malloc +#else /* BF_STANDALONE */ # include "sendmail.h" -#endif /* ! BF_STANDALONE */ +#endif /* BF_STANDALONE */ #include "bf_torek.h" #include "bf.h" @@ -90,7 +93,7 @@ bfopen(filename, fmode, bsize, flags) } /* Allocate memory */ - bfp = (struct bf *)malloc(sizeof(struct bf)); + bfp = (struct bf *)xalloc(sizeof(struct bf)); if (bfp == NULL) { errno = ENOMEM; @@ -100,10 +103,10 @@ bfopen(filename, fmode, bsize, flags) /* A zero bsize is valid, just don't allocate memory */ if (bsize > 0) { - bfp->bf_buf = (char *)malloc(bsize); + bfp->bf_buf = (char *)xalloc(bsize); if (bfp->bf_buf == NULL) { - free(bfp); + sm_free(bfp); errno = ENOMEM; return NULL; } @@ -119,12 +122,12 @@ bfopen(filename, fmode, bsize, flags) bfp->bf_bufsize = bsize; bfp->bf_buffilled = 0; l = strlen(filename) + 1; - bfp->bf_filename = (char *)malloc(l); + bfp->bf_filename = (char *)xalloc(l); if (bfp->bf_filename == NULL) { - free(bfp); if (bfp->bf_buf != NULL) - free(bfp->bf_buf); + sm_free(bfp->bf_buf); + sm_free(bfp); errno = ENOMEM; return NULL; } @@ -142,10 +145,10 @@ bfopen(filename, fmode, bsize, flags) { /* Just in case free() sets errno */ save_errno = errno; - free(bfp); - free(bfp->bf_filename); + sm_free(bfp->bf_filename); if (bfp->bf_buf != NULL) - free(bfp->bf_buf); + sm_free(bfp->bf_buf); + sm_free(bfp); errno = save_errno; return NULL; } @@ -285,7 +288,7 @@ bfcommit(fp) { /* Don't need buffer anymore; free it */ bfp->bf_bufsize = 0; - free(bfp->bf_buf); + sm_free(bfp->bf_buf); } return 0; } @@ -317,7 +320,6 @@ bfrewind(fp) /* check to see if there is an error on the stream */ err = ferror(fp); - (void) fflush(fp); /* @@ -530,10 +532,10 @@ _bfclose(cookie) /* Need to free the buffer */ if (bfp->bf_bufsize > 0) - free(bfp->bf_buf); + sm_free(bfp->bf_buf); /* Finally, free the structure */ - free(bfp); + sm_free(bfp); return 0; } diff --git a/contrib/sendmail/src/clock.c b/contrib/sendmail/src/clock.c index 8788291..bf5ef1c 100644 --- a/contrib/sendmail/src/clock.c +++ b/contrib/sendmail/src/clock.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: clock.c,v 8.52.18.3 2000/09/17 17:04:26 gshapiro Exp $"; +static char id[] = "@(#)$Id: clock.c,v 8.52.18.14 2001/05/17 18:12:28 gshapiro Exp $"; #endif /* ! lint */ #include <sendmail.h> @@ -21,6 +21,7 @@ static char id[] = "@(#)$Id: clock.c,v 8.52.18.3 2000/09/17 17:04:26 gshapiro Ex # define sigmask(s) (1 << ((s) - 1)) #endif /* ! sigmask */ +static SIGFUNC_DECL tick __P((int)); static void endsleep __P((void)); @@ -42,7 +43,8 @@ static void endsleep __P((void)); ** none. */ -EVENT *FreeEventList; /* list of free events */ +static EVENT *volatile EventQueue; /* head of event queue */ +static EVENT *volatile FreeEventList; /* list of free events */ EVENT * setevent(intvl, func, arg) @@ -50,10 +52,7 @@ setevent(intvl, func, arg) void (*func)(); int arg; { - register EVENT **evp; register EVENT *ev; - auto time_t now; - int wasblocked; if (intvl <= 0) { @@ -61,33 +60,88 @@ setevent(intvl, func, arg) return NULL; } + ENTER_CRITICAL(); + if (FreeEventList == NULL) + { + FreeEventList = (EVENT *) xalloc(sizeof *FreeEventList); + FreeEventList->ev_link = NULL; + } + LEAVE_CRITICAL(); + + ev = sigsafe_setevent(intvl, func, arg); + + if (tTd(5, 5)) + dprintf("setevent: intvl=%ld, for=%ld, func=%lx, arg=%d, ev=%lx\n", + (long) intvl, (long) (curtime() + intvl), + (u_long) func, arg, + ev == NULL ? 0 : (u_long) ev); + + return ev; +} + +/* +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +EVENT * +sigsafe_setevent(intvl, func, arg) + time_t intvl; + void (*func)(); + int arg; +{ + register EVENT **evp; + register EVENT *ev; + auto time_t now; + int wasblocked; + + if (intvl <= 0) + return NULL; + wasblocked = blocksignal(SIGALRM); now = curtime(); /* search event queue for correct position */ - for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link) + for (evp = (EVENT **) (&EventQueue); + (ev = *evp) != NULL; + evp = &ev->ev_link) { if (ev->ev_time >= now + intvl) break; } - /* insert new event */ - ev = FreeEventList; - if (ev == NULL) - ev = (EVENT *) xalloc(sizeof *ev); + ENTER_CRITICAL(); + if (FreeEventList == NULL) + { + /* + ** This shouldn't happen. If called from setevent(), + ** we have just malloced a FreeEventList entry. If + ** called from a signal handler, it should have been + ** from an existing event which tick() just added to the + ** FreeEventList. + */ + + LEAVE_CRITICAL(); + return NULL; + } else + { + ev = FreeEventList; FreeEventList = ev->ev_link; + } + LEAVE_CRITICAL(); + + /* insert new event */ ev->ev_time = now + intvl; ev->ev_func = func; ev->ev_arg = arg; ev->ev_pid = getpid(); + ENTER_CRITICAL(); ev->ev_link = *evp; *evp = ev; - - if (tTd(5, 5)) - dprintf("setevent: intvl=%ld, for=%ld, func=%lx, arg=%d, ev=%lx\n", - (long) intvl, (long)(now + intvl), (u_long) func, - arg, (u_long) ev); + LEAVE_CRITICAL(); (void) setsignal(SIGALRM, tick); intvl = EventQueue->ev_time - now; @@ -123,7 +177,9 @@ clrevent(ev) /* find the parent event */ wasblocked = blocksignal(SIGALRM); - for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) + for (evp = (EVENT **) (&EventQueue); + *evp != NULL; + evp = &(*evp)->ev_link) { if (*evp == ev) break; @@ -132,9 +188,11 @@ clrevent(ev) /* now remove it */ if (*evp != NULL) { + ENTER_CRITICAL(); *evp = ev->ev_link; ev->ev_link = FreeEventList; FreeEventList = ev; + LEAVE_CRITICAL(); } /* restore clocks and pick up anything spare */ @@ -178,9 +236,11 @@ clear_events() for (ev = EventQueue; ev->ev_link != NULL; ev = ev->ev_link) continue; + ENTER_CRITICAL(); ev->ev_link = FreeEventList; FreeEventList = EventQueue; EventQueue = NULL; + LEAVE_CRITICAL(); /* restore clocks and pick up anything spare */ if (wasblocked == 0) @@ -201,6 +261,10 @@ clear_events() ** ** Side Effects: ** calls the next function in EventQueue. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. */ /* ARGSUSED */ @@ -210,27 +274,67 @@ tick(sig) { register time_t now; register EVENT *ev; - int mypid = getpid(); + pid_t mypid; int save_errno = errno; (void) alarm(0); - now = curtime(); + FIX_SYSV_SIGNAL(sig, tick); + + errno = save_errno; + CHECK_CRITICAL(sig); + + mypid = getpid(); + while (PendingSignal != 0) + { + int sigbit; + int sig; + + if (bitset(PEND_SIGHUP, PendingSignal)) + { + sigbit = PEND_SIGHUP; + sig = SIGHUP; + } + else if (bitset(PEND_SIGINT, PendingSignal)) + { + sigbit = PEND_SIGINT; + sig = SIGINT; + } + else if (bitset(PEND_SIGTERM, PendingSignal)) + { + sigbit = PEND_SIGTERM; + sig = SIGTERM; + } + else if (bitset(PEND_SIGUSR1, PendingSignal)) + { + sigbit = PEND_SIGUSR1; + sig = SIGUSR1; + } + else + { + /* If we get here, we are in trouble */ + abort(); + } + PendingSignal &= ~sigbit; + kill(mypid, sig); + } + + now = curtime(); if (tTd(5, 4)) dprintf("tick: now=%ld\n", (long) now); - /* reset signal in case System V semantics */ - (void) setsignal(SIGALRM, tick); while ((ev = EventQueue) != NULL && (ev->ev_time <= now || ev->ev_pid != mypid)) { void (*f)(); int arg; - int pid; + pid_t pid; /* process the event on the top of the queue */ + ENTER_CRITICAL(); ev = EventQueue; EventQueue = EventQueue->ev_link; + LEAVE_CRITICAL(); if (tTd(5, 6)) dprintf("tick: ev=%lx, func=%lx, arg=%d, pid=%d\n", (u_long) ev, (u_long) ev->ev_func, @@ -240,9 +344,11 @@ tick(sig) f = ev->ev_func; arg = ev->ev_arg; pid = ev->ev_pid; + ENTER_CRITICAL(); ev->ev_link = FreeEventList; FreeEventList = ev; - if (pid != getpid()) + LEAVE_CRITICAL(); + if (pid != mypid) continue; if (EventQueue != NULL) { @@ -264,6 +370,72 @@ tick(sig) return SIGFUNC_RETURN; } /* +** PEND_SIGNAL -- Add a signal to the pending signal list +** +** Parameters: +** sig -- signal to add +** +** Returns: +** none. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +void +pend_signal(sig) + int sig; +{ + int sigbit; + int save_errno = errno; + + /* + ** Don't want to interrupt something critical, hence delay + ** the alarm for one second. Hopefully, by then we + ** will be out of the critical section. If not, then + ** we will just delay again. The events to be run will + ** still all be run, maybe just a little bit late. + */ + + switch (sig) + { + case SIGHUP: + sigbit = PEND_SIGHUP; + break; + + case SIGINT: + sigbit = PEND_SIGINT; + break; + + case SIGTERM: + sigbit = PEND_SIGTERM; + break; + + case SIGUSR1: + sigbit = PEND_SIGUSR1; + break; + + case SIGALRM: + /* don't have to pend these */ + sigbit = 0; + break; + + default: + /* If we get here, we are in trouble */ + abort(); + + /* NOTREACHED */ + break; + } + + if (sigbit != 0) + PendingSignal |= sigbit; + (void) setsignal(SIGALRM, tick); + (void) alarm(1); + errno = save_errno; +} +/* ** SLEEP -- a version of sleep that works with this stuff ** ** Because sleep uses the alarm facility, I must reimplement @@ -281,7 +453,7 @@ tick(sig) */ -static bool SleepDone; +static bool volatile SleepDone; #ifndef SLEEP_T # define SLEEP_T unsigned int @@ -308,5 +480,11 @@ sleep(intvl) static void endsleep() { + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + SleepDone = TRUE; } diff --git a/contrib/sendmail/src/collect.c b/contrib/sendmail/src/collect.c index d1c7f1c..e9a2006 100644 --- a/contrib/sendmail/src/collect.c +++ b/contrib/sendmail/src/collect.c @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: collect.c,v 8.136.4.15 2001/02/21 01:05:59 gshapiro Exp $"; +static char id[] = "@(#)$Id: collect.c,v 8.136.4.21 2001/05/17 18:10:14 gshapiro Exp $"; #endif /* ! lint */ #include <sendmail.h> @@ -47,8 +47,8 @@ static void eatfrom __P((char *volatile, ENVELOPE *)); */ static jmp_buf CtxCollectTimeout; -static bool CollectProgress; -static EVENT *CollectTimeout; +static bool volatile CollectProgress; +static EVENT *volatile CollectTimeout = NULL; /* values for input state machine */ #define IS_NORM 0 /* middle of line */ @@ -212,10 +212,12 @@ collect(fp, smtpmode, hdrp, e) if (TrafficLogFile != NULL && !headeronly) { if (istate == IS_BOL) - (void) fprintf(TrafficLogFile, "%05d <<< ", - (int) getpid()); + (void) fprintf(TrafficLogFile, + "%05d <<< ", + (int) getpid()); if (c == EOF) - (void) fprintf(TrafficLogFile, "[EOF]\n"); + (void) fprintf(TrafficLogFile, + "[EOF]\n"); else (void) putc(c, TrafficLogFile); } @@ -312,7 +314,6 @@ bufferchar: /* just put the character out */ if (!bitset(EF_TOOBIG, e->e_flags)) (void) putc(c, df); - /* FALLTHROUGH */ case MS_DISCARD: @@ -337,7 +338,7 @@ bufferchar: memmove(buf, obuf, bp - obuf); bp = &buf[bp - obuf]; if (obuf != bufbuf) - free(obuf); + sm_free(obuf); } if (c >= 0200 && c <= 0237) { @@ -479,7 +480,8 @@ readerr: } /* reset global timer */ - clrevent(CollectTimeout); + if (CollectTimeout != NULL) + clrevent(CollectTimeout); if (headeronly) return; @@ -721,15 +723,37 @@ static void collecttimeout(timeout) time_t timeout; { - /* if no progress was made, die now */ - if (!CollectProgress) + int save_errno = errno; + + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + + if (CollectProgress) + { + /* reset the timeout */ + CollectTimeout = sigsafe_setevent(timeout, collecttimeout, + timeout); + CollectProgress = FALSE; + } + else + { + /* event is done */ + CollectTimeout = NULL; + } + + /* if no progress was made or problem resetting event, die now */ + if (CollectTimeout == NULL) + { + errno = ETIMEDOUT; longjmp(CtxCollectTimeout, 1); + } - /* otherwise reset the timeout */ - CollectTimeout = setevent(timeout, collecttimeout, timeout); - CollectProgress = FALSE; + errno = save_errno; } -/* +/* ** DFERROR -- signal error on writing the data file. ** ** Parameters: diff --git a/contrib/sendmail/src/conf.c b/contrib/sendmail/src/conf.c index bff13f4..4fa8c74 100644 --- a/contrib/sendmail/src/conf.c +++ b/contrib/sendmail/src/conf.c @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: conf.c,v 8.646.2.2.2.69 2001/02/27 19:50:11 gshapiro Exp $"; +static char id[] = "@(#)$Id: conf.c,v 8.646.2.2.2.86 2001/05/17 18:18:40 ca Exp $"; #endif /* ! lint */ #include <sendmail.h> @@ -976,7 +976,7 @@ switch_map_find(service, maptype, mapreturn) st = stab(buf, ST_SERVICE, ST_ENTER); if (st->s_service[0] != NULL) - free((void *) st->s_service[0]); + sm_free((void *) st->s_service[0]); p = newstr(p); for (svcno = 0; svcno < MAXMAPSTACK; ) { @@ -1226,6 +1226,10 @@ checkcompat(to, e) ** SETSIGNAL -- set a signal handler ** ** This is essentially old BSD "signal(3)". +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. */ sigfunc_t @@ -1233,14 +1237,16 @@ setsignal(sig, handler) int sig; sigfunc_t handler; { +# if defined(SA_RESTART) || (!defined(SYS5SIGNALS) && !defined(BSD4_3)) + struct sigaction n, o; +# endif /* defined(SA_RESTART) || (!defined(SYS5SIGNALS) && !defined(BSD4_3)) */ + /* ** First, try for modern signal calls ** and restartable syscalls */ # ifdef SA_RESTART - struct sigaction n, o; - memset(&n, '\0', sizeof n); # if USE_SA_SIGACTION n.sa_sigaction = (void(*)(int, siginfo_t *, void *)) handler; @@ -1272,8 +1278,6 @@ setsignal(sig, handler) ** go for a default */ - struct sigaction n, o; - memset(&n, '\0', sizeof n); n.sa_handler = handler; if (sigaction(sig, &n, &o) < 0) @@ -1283,6 +1287,73 @@ setsignal(sig, handler) # endif /* SA_RESTART */ } /* +** ALLSIGNALS -- act on all signals +** +** Parameters: +** block -- whether to block or release all signals. +** +** Returns: +** none. +*/ + +void +allsignals(block) + bool block; +{ +# ifdef BSD4_3 +# ifndef sigmask +# define sigmask(s) (1 << ((s) - 1)) +# endif /* ! sigmask */ + if (block) + { + int mask = 0; + + mask |= sigmask(SIGALRM); + mask |= sigmask(SIGCHLD); + mask |= sigmask(SIGHUP); + mask |= sigmask(SIGINT); + mask |= sigmask(SIGTERM); + mask |= sigmask(SIGUSR1); + + (void) sigblock(mask); + } + else + sigsetmask(0); +# else /* BSD4_3 */ +# ifdef ALTOS_SYSTEM_V + if (block) + { + (void) sigset(SIGALRM, SIG_HOLD); + (void) sigset(SIGCHLD, SIG_HOLD); + (void) sigset(SIGHUP, SIG_HOLD); + (void) sigset(SIGINT, SIG_HOLD); + (void) sigset(SIGTERM, SIG_HOLD); + (void) sigset(SIGUSR1, SIG_HOLD); + } + else + { + (void) sigset(SIGALRM, SIG_DFL); + (void) sigset(SIGCHLD, SIG_DFL); + (void) sigset(SIGHUP, SIG_DFL); + (void) sigset(SIGINT, SIG_DFL); + (void) sigset(SIGTERM, SIG_DFL); + (void) sigset(SIGUSR1, SIG_DFL); + } +# else /* ALTOS_SYSTEM_V */ + sigset_t sset; + + (void) sigemptyset(&sset); + (void) sigaddset(&sset, SIGALRM); + (void) sigaddset(&sset, SIGCHLD); + (void) sigaddset(&sset, SIGHUP); + (void) sigaddset(&sset, SIGINT); + (void) sigaddset(&sset, SIGTERM); + (void) sigaddset(&sset, SIGUSR1); + (void) sigprocmask(block ? SIG_BLOCK : SIG_UNBLOCK, &sset, NULL); +# endif /* ALTOS_SYSTEM_V */ +# endif /* BSD4_3 */ +} +/* ** BLOCKSIGNAL -- hold a signal to prevent delivery ** ** Parameters: @@ -2441,7 +2512,7 @@ setproctitle(fmt, va_alist) # if SPT_TYPE == SPT_SCO off_t seek_off; static int kmem = -1; - static int kmempid = -1; + static pid_t kmempid = -1; struct user u; # endif /* SPT_TYPE == SPT_SCO */ @@ -2619,6 +2690,10 @@ waitfor(pid) ** Side Effects: ** Picks up extant zombies. ** Control socket exits may restart/shutdown daemon. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. */ /* ARGSUSED0 */ @@ -2629,32 +2704,30 @@ reapchild(sig) int save_errno = errno; int st; pid_t pid; -#if HASWAITPID +# if HASWAITPID auto int status; int count; +# else /* HASWAITPID */ +# ifdef WNOHANG + union wait status; +# else /* WNOHANG */ + auto int status; +# endif /* WNOHANG */ +# endif /* HASWAITPID */ +# if HASWAITPID count = 0; while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { st = status; if (count++ > 1000) - { - if (LogLevel > 0) - sm_syslog(LOG_ALERT, NOQID, - "reapchild: waitpid loop: pid=%d, status=%x", - pid, status); break; - } -#else /* HASWAITPID */ -# ifdef WNOHANG - union wait status; - +# else /* HASWAITPID */ +# ifdef WNOHANG while ((pid = wait3(&status, WNOHANG, (struct rusage *) NULL)) > 0) { st = status.w_status; -# else /* WNOHANG */ - auto int status; - +# else /* WNOHANG */ /* ** Catch one zombie -- we will be re-invoked (we hope) if there ** are more. Unreliable signals probably break this, but this @@ -2665,8 +2738,8 @@ reapchild(sig) if ((pid = wait(&status)) > 0) { st = status; -# endif /* WNOHANG */ -#endif /* HASWAITPID */ +# endif /* WNOHANG */ +# endif /* HASWAITPID */ /* Drop PID and check if it was a control socket child */ if (proc_list_drop(pid) == PROC_CONTROL && WIFEXITED(st)) @@ -2674,21 +2747,17 @@ reapchild(sig) /* if so, see if we need to restart or shutdown */ if (WEXITSTATUS(st) == EX_RESTART) { - /* emulate a SIGHUP restart */ - sighup(0); - /* NOTREACHED */ + RestartRequest = "control socket"; } else if (WEXITSTATUS(st) == EX_SHUTDOWN) { /* emulate a SIGTERM shutdown */ - intsig(0); + ShutdownRequest = "control socket"; /* NOTREACHED */ } } } -#ifdef SYS5SIGNALS - (void) setsignal(SIGCHLD, reapchild); -#endif /* SYS5SIGNALS */ + FIX_SYSV_SIGNAL(sig, reapchild); errno = save_errno; return SIGFUNC_RETURN; } @@ -2753,18 +2822,14 @@ putenv(str) */ if (first) { - newenv = (char **) malloc(sizeof(char *) * (envlen + 2)); - if (newenv == NULL) - return -1; - + newenv = (char **) xalloc(sizeof(char *) * (envlen + 2)); first = FALSE; (void) memcpy(newenv, environ, sizeof(char *) * envlen); } else { - newenv = (char **) realloc((char *)environ, sizeof(char *) * (envlen + 2)); - if (newenv == NULL) - return -1; + newenv = (char **) xrealloc((char *)environ, + sizeof(char *) * (envlen + 2)); } /* actually add in the new entry */ @@ -4327,7 +4392,7 @@ strstr(big, little) ** Support IPv6 as well as IPv4. */ -#if NETINET6 && NEEDSGETIPNODE && __RES < 19990909 +#if NETINET6 && NEEDSGETIPNODE # ifndef AI_DEFAULT # define AI_DEFAULT 0 /* dummy */ @@ -4394,7 +4459,7 @@ freehostent(h) return; } # endif /* _FFR_FREEHOSTENT */ -#endif /* NEEDSGETIPNODE && NETINET6 && __RES < 19990909 */ +#endif /* NEEDSGETIPNODE && NETINET6 */ struct hostent * sm_gethostbyname(name, family) @@ -4582,8 +4647,8 @@ sm_gethostbyaddr(addr, len, type) # else /* NETINET6 */ hp = gethostbyaddr(addr, len, type); # endif /* NETINET6 */ - return hp; #endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */ + return hp; } /* ** SM_GETPW{NAM,UID} -- wrapper for getpwnam and getpwuid @@ -4869,7 +4934,7 @@ load_if_names() if (tTd(0, 4)) dprintf("SIOCGLIFCONF failed: %s\n", errstring(errno)); (void) close(s); - free(lifc.lifc_buf); + sm_free(lifc.lifc_buf); return; } @@ -4903,7 +4968,7 @@ load_if_names() s = socket(af, SOCK_DGRAM, 0); if (s == -1) { - free(lifc.lifc_buf); + sm_free(lifc.lifc_buf); return; } @@ -5018,7 +5083,7 @@ load_if_names() # endif /* SIOCGLIFFLAGS */ (void) add_hostnames(sa); } - free(lifc.lifc_buf); + sm_free(lifc.lifc_buf); (void) close(s); #else /* NETINET6 && defined(SIOCGLIFCONF) */ # if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN @@ -5058,7 +5123,7 @@ load_if_names() if (tTd(0, 4)) dprintf("SIOCGIFCONF failed: %s\n", errstring(errno)); (void) close(s); - free(ifc.ifc_buf); + sm_free(ifc.ifc_buf); return; } @@ -5201,7 +5266,7 @@ load_if_names() (void) add_hostnames(sa); } - free(ifc.ifc_buf); + sm_free(ifc.ifc_buf); (void) close(s); # undef IFRFREF # endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */ @@ -5375,7 +5440,7 @@ sm_syslog(level, id, fmt, va_alist) /* String too small, redo with correct size */ bufsize += SnprfOverflow + 1; if (buf != buf0) - free(buf); + sm_free(buf); buf = xalloc(bufsize * sizeof (char)); } if ((strlen(buf) + idlen + 1) < SYSLOG_BUFSIZE) @@ -5532,6 +5597,9 @@ local_hostname_length(hostname) char *CompileOptions[] = { +#if EGD + "EGD", +#endif /* EGD */ #ifdef HESIOD "HESIOD", #endif /* HESIOD */ diff --git a/contrib/sendmail/src/conf.h b/contrib/sendmail/src/conf.h index f98533d..e56da30 100644 --- a/contrib/sendmail/src/conf.h +++ b/contrib/sendmail/src/conf.h @@ -10,7 +10,7 @@ * the sendmail distribution. * * - * $Id: conf.h,v 8.496.4.37 2001/02/12 21:40:16 gshapiro Exp $ + * $Id: conf.h,v 8.496.4.43 2001/05/20 22:29:59 gshapiro Exp $ */ /* @@ -84,7 +84,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 */ +#define MAXQFNAME 21 /* max qf file name length */ #define MACBUFSIZE 4096 /* max expanded macro buffer size */ #define TOBUFSIZE SM_ARG_MAX /* max buffer to hold address list */ #define MAXSHORTSTR 203 /* max short string length */ @@ -551,6 +551,9 @@ typedef int pid_t; # undef _PATH_SENDMAILPID /* tmpfs /var/run added in 2.8 */ # define _PATH_SENDMAILPID "/var/run/sendmail.pid" # endif /* SOLARIS >= 20800 || (SOLARIS < 10000 && SOLARIS >= 208) */ +# if SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209) +# define HASURANDOMDEV 1 /* /dev/[u]random added in S9 */ +# endif /* SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209) */ # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps pre-2.7 */ # endif /* ! HASGETUSERSHELL */ @@ -1002,6 +1005,7 @@ typedef int pid_t; # undef SPT_TYPE # define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */ # define HASSETLOGIN 1 /* has setlogin(2) */ +# define HASSETREUID 0 /* OpenBSD has broken setreuid(2) emulation */ # define HASURANDOMDEV 1 /* has /dev/urandom(4) */ # if OpenBSD < 199912 # define HASSTRL 0 /* strlcat(3) is broken in 2.5 and earlier */ @@ -1468,10 +1472,10 @@ extern void *malloc(); # else /* (GLIBC_VERSION >= 0x201) */ # include <linux/in6.h> /* IPv6 support */ # endif /* (GLIBC_VERSION >= 0x201) */ -# if (GLIBC_VERSION == 0x201 && !defined(NEEDSGETIPNODE)) +# if (GLIBC_VERSION >= 0x201 && !defined(NEEDSGETIPNODE)) /* Have APIs in <netdb.h>, but no support in glibc */ # define NEEDSGETIPNODE 1 -# endif /* (GLIBC_VERSION == 0x201 && ! NEEDSGETIPNODE) */ +# endif /* (GLIBC_VERSION >= 0x201 && !defined(NEEDSGETIPNODE)) */ # undef GLIBC_VERSION # endif /* defined(__GLIBC__) && defined(__GLIBC_MINOR__) */ # endif /* NETINET6 */ @@ -2243,7 +2247,9 @@ typedef struct msgb mblk_t; /* general BSD defines */ #ifdef BSD # define HASGETDTABLESIZE 1 /* has getdtablesize(2) call */ -# define HASSETREUID 1 /* has setreuid(2) call */ +# ifndef HASSETREUID +# define HASSETREUID 1 /* has setreuid(2) call */ +# endif /* ! HASSETREUID */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # ifndef IP_SRCROUTE # define IP_SRCROUTE 1 /* can check IP source routing */ diff --git a/contrib/sendmail/src/control.c b/contrib/sendmail/src/control.c index 95506ab..b30c63f 100644 --- a/contrib/sendmail/src/control.c +++ b/contrib/sendmail/src/control.c @@ -9,11 +9,33 @@ */ #ifndef lint -static char id[] = "@(#)$Id: control.c,v 8.44.14.15 2001/01/22 19:00:22 gshapiro Exp $"; +static char id[] = "@(#)$Id: control.c,v 8.44.14.20 2001/05/03 17:24:03 gshapiro Exp $"; #endif /* ! lint */ #include <sendmail.h> +/* values for cmd_code */ +# define CMDERROR 0 /* bad command */ +# define CMDRESTART 1 /* restart daemon */ +# define CMDSHUTDOWN 2 /* end daemon */ +# define CMDHELP 3 /* help */ +# define CMDSTATUS 4 /* daemon status */ + +struct cmd +{ + char *cmd_name; /* command name */ + int cmd_code; /* internal code, see below */ +}; + +static struct cmd CmdTab[] = +{ + { "help", CMDHELP }, + { "restart", CMDRESTART }, + { "shutdown", CMDSHUTDOWN }, + { "status", CMDSTATUS }, + { NULL, CMDERROR } +}; + int ControlSocket = -1; @@ -208,34 +230,19 @@ clrcontrol() ** none. */ -struct cmd -{ - char *cmd_name; /* command name */ - int cmd_code; /* internal code, see below */ -}; - -/* values for cmd_code */ -# define CMDERROR 0 /* bad command */ -# define CMDRESTART 1 /* restart daemon */ -# define CMDSHUTDOWN 2 /* end daemon */ -# define CMDHELP 3 /* help */ -# define CMDSTATUS 4 /* daemon status */ - -static struct cmd CmdTab[] = -{ - { "help", CMDHELP }, - { "restart", CMDRESTART }, - { "shutdown", CMDSHUTDOWN }, - { "status", CMDSTATUS }, - { NULL, CMDERROR } -}; - static jmp_buf CtxControlTimeout; static void controltimeout(timeout) time_t timeout; { + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + + errno = ETIMEDOUT; longjmp(CtxControlTimeout, 1); } diff --git a/contrib/sendmail/src/daemon.c b/contrib/sendmail/src/daemon.c index f4b07d4..1fdd3d7 100644 --- a/contrib/sendmail/src/daemon.c +++ b/contrib/sendmail/src/daemon.c @@ -16,9 +16,9 @@ #ifndef lint # ifdef DAEMON -static char id[] = "@(#)$Id: daemon.c,v 8.401.4.51 2001/02/23 18:57:27 geir Exp $ (with daemon mode)"; +static char id[] = "@(#)$Id: daemon.c,v 8.401.4.61 2001/05/27 22:14:40 gshapiro Exp $ (with daemon mode)"; # else /* DAEMON */ -static char id[] = "@(#)$Id: daemon.c,v 8.401.4.51 2001/02/23 18:57:27 geir Exp $ (without daemon mode)"; +static char id[] = "@(#)$Id: daemon.c,v 8.401.4.61 2001/05/27 22:14:40 gshapiro Exp $ (without daemon mode)"; # endif /* DAEMON */ #endif /* ! lint */ @@ -87,6 +87,8 @@ typedef struct daemon DAEMON_T; static void connecttimeout __P((void)); static int opendaemonsocket __P((struct daemon *, bool)); static u_short setupdaemon __P((SOCKADDR *)); +static SIGFUNC_DECL sighup __P((int)); +static void restart_daemon __P((void)); /* ** DAEMON.C -- routines to use when running as a daemon. @@ -194,6 +196,10 @@ getrequests(e) ControlSocketName, errstring(errno)); (void) setsignal(SIGCHLD, reapchild); + (void) setsignal(SIGHUP, sighup); + + /* workaround: can't seem to release the signal in the parent */ + (void) releasesignal(SIGHUP); /* write the pid to file */ log_sendmail_pid(e); @@ -235,6 +241,11 @@ getrequests(e) /* see if we are rejecting connections */ (void) blocksignal(SIGALRM); + if (ShutdownRequest != NULL) + shutdown_daemon(); + else if (RestartRequest != NULL) + restart_daemon(); + timenow = curtime(); /* @@ -296,6 +307,12 @@ getrequests(e) } } + /* May have been sleeping above, check again */ + if (ShutdownRequest != NULL) + shutdown_daemon(); + else if (RestartRequest != NULL) + restart_daemon(); + if (timenow >= last_disk_space_check) { bool logged = FALSE; @@ -389,6 +406,11 @@ getrequests(e) fd_set readfds; struct timeval timeout; + if (ShutdownRequest != NULL) + shutdown_daemon(); + else if (RestartRequest != NULL) + restart_daemon(); + FD_ZERO(&readfds); for (idx = 0; idx < ndaemons; idx++) @@ -419,24 +441,18 @@ getrequests(e) } # endif /* NETUNIX */ - /* - ** if one socket is closed, set the timeout - ** to 5 seconds (so it might get reopened soon), - ** otherwise (all sockets open) 60. - */ - - idx = 0; - while (idx < ndaemons && Daemons[idx].d_socket >= 0) - idx++; - if (idx < ndaemons) - timeout.tv_sec = 5; - else - timeout.tv_sec = 60; + timeout.tv_sec = 5; timeout.tv_usec = 0; t = select(highest + 1, FDSET_CAST &readfds, NULL, NULL, &timeout); + /* Did someone signal while waiting? */ + if (ShutdownRequest != NULL) + shutdown_daemon(); + else if (RestartRequest != NULL) + restart_daemon(); + if (DoQueueRun) @@ -675,6 +691,18 @@ getrequests(e) ** Verify calling user id if possible here. */ + /* Reset global flags */ + RestartRequest = NULL; + ShutdownRequest = NULL; + PendingSignal = 0; + + (void) releasesignal(SIGALRM); + (void) releasesignal(SIGCHLD); + (void) setsignal(SIGCHLD, SIG_DFL); + (void) setsignal(SIGHUP, SIG_DFL); + (void) setsignal(SIGTERM, intsig); + + if (!control) { define(macid("{daemon_addr}", NULL), @@ -686,10 +714,6 @@ getrequests(e) newstr(status), &BlankEnvelope); } - (void) releasesignal(SIGALRM); - (void) releasesignal(SIGCHLD); - (void) setsignal(SIGCHLD, SIG_DFL); - (void) setsignal(SIGHUP, intsig); for (idx = 0; idx < ndaemons; idx++) { if (Daemons[idx].d_socket >= 0) @@ -1709,7 +1733,7 @@ makeconnection(host, port, mci, e) { STRUCTCOPY(ClientAddr, clt_addr); if (clt_addr.sa.sa_family == AF_UNSPEC) - clt_addr.sa.sa_family = InetMode; + clt_addr.sa.sa_family = family; switch (clt_addr.sa.sa_family) { # if NETINET @@ -1998,8 +2022,9 @@ gothostent: for (;;) { if (tTd(16, 1)) - dprintf("makeconnection (%s [%s])\n", - host, anynet_ntoa(&addr)); + dprintf("makeconnection (%s [%s].%d (%d))\n", + host, anynet_ntoa(&addr), ntohs(port), + addr.sa.sa_family); /* save for logging */ CurHostAddr = addr; @@ -2012,7 +2037,7 @@ gothostent: } else { - s = socket(addr.sa.sa_family, SOCK_STREAM, 0); + s = socket(clt_addr.sa.sa_family, SOCK_STREAM, 0); } if (s < 0) { @@ -2118,9 +2143,11 @@ gothostent: int i; if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0) - ev = setevent(TimeOuts.to_iconnect, connecttimeout, 0); + ev = setevent(TimeOuts.to_iconnect, + connecttimeout, 0); else if (TimeOuts.to_connect != 0) - ev = setevent(TimeOuts.to_connect, connecttimeout, 0); + ev = setevent(TimeOuts.to_connect, + connecttimeout, 0); else ev = NULL; @@ -2306,6 +2333,12 @@ gothostent: static void connecttimeout() { + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + errno = ETIMEDOUT; longjmp(CtxConnectTimeout, 1); } @@ -2406,6 +2439,124 @@ int makeconnection_ds(mux_path, mci) } # endif /* NETUNIX */ /* +** SIGHUP -- handle a SIGHUP signal +** +** Parameters: +** sig -- incoming signal. +** +** Returns: +** none. +** +** Side Effects: +** Sets RestartRequest which should cause the daemon +** to restart. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +/* ARGSUSED */ +static SIGFUNC_DECL +sighup(sig) + int sig; +{ + int save_errno = errno; + + FIX_SYSV_SIGNAL(sig, sighup); + RestartRequest = "signal"; + errno = save_errno; + return SIGFUNC_RETURN; +} +/* +** RESTART_DAEMON -- Performs a clean restart of the daemon +** +** Parameters: +** none. +** +** Returns: +** none. +** +** Side Effects: +** restarts the daemon or exits if restart fails. +*/ + +static void +restart_daemon() +{ + int i; + int save_errno; + char *reason; + sigfunc_t oalrm, ochld, ohup, oint, opipe, oterm, ousr1; + extern int DtableSize; + + allsignals(TRUE); + + reason = RestartRequest; + RestartRequest = NULL; + PendingSignal = 0; + + if (SaveArgv[0][0] != '/') + { + if (LogLevel > 3) + sm_syslog(LOG_INFO, NOQID, + "could not restart: need full path"); + finis(FALSE, EX_OSFILE); + } + if (LogLevel > 3) + sm_syslog(LOG_INFO, NOQID, "restarting %s due to %s", + SaveArgv[0], + reason == NULL ? "implicit call" : reason); + + closecontrolsocket(TRUE); + if (drop_privileges(TRUE) != EX_OK) + { + if (LogLevel > 0) + sm_syslog(LOG_ALERT, NOQID, + "could not set[ug]id(%d, %d): %m", + RunAsUid, RunAsGid); + finis(FALSE, EX_OSERR); + } + + /* arrange for all the files to be closed */ + for (i = 3; i < DtableSize; i++) + { + register int j; + + if ((j = fcntl(i, F_GETFD, 0)) != -1) + (void) fcntl(i, F_SETFD, j | FD_CLOEXEC); + } + + /* need to allow signals before execve() so make them harmless */ + oalrm = setsignal(SIGALRM, SIG_DFL); + ochld = setsignal(SIGCHLD, SIG_DFL); + ohup = setsignal(SIGHUP, SIG_DFL); + oint = setsignal(SIGINT, SIG_DFL); + opipe = setsignal(SIGPIPE, SIG_DFL); + oterm = setsignal(SIGTERM, SIG_DFL); + ousr1 = setsignal(SIGUSR1, SIG_DFL); + allsignals(FALSE); + + (void) execve(SaveArgv[0], (ARGV_T) SaveArgv, (ARGV_T) ExternalEnviron); + save_errno = errno; + + /* restore signals */ + allsignals(TRUE); + (void) setsignal(SIGALRM, oalrm); + (void) setsignal(SIGCHLD, ochld); + (void) setsignal(SIGHUP, ohup); + (void) setsignal(SIGINT, oint); + (void) setsignal(SIGPIPE, opipe); + (void) setsignal(SIGTERM, oterm); + (void) setsignal(SIGUSR1, ousr1); + + errno = save_errno; + if (LogLevel > 0) + sm_syslog(LOG_ALERT, NOQID, "could not exec %s: %m", + SaveArgv[0]); + finis(FALSE, EX_OSFILE); +} +/* ** MYHOSTNAME -- return the name of this host. ** ** Parameters: @@ -2568,6 +2719,13 @@ static jmp_buf CtxAuthTimeout; static void authtimeout() { + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + + errno = ETIMEDOUT; longjmp(CtxAuthTimeout, 1); } diff --git a/contrib/sendmail/src/deliver.c b/contrib/sendmail/src/deliver.c index 689ceeb..347b7a5 100644 --- a/contrib/sendmail/src/deliver.c +++ b/contrib/sendmail/src/deliver.c @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: deliver.c,v 8.600.2.1.2.66 2001/02/25 23:30:35 gshapiro Exp $"; +static char id[] = "@(#)$Id: deliver.c,v 8.600.2.1.2.81 2001/05/23 02:15:42 ca Exp $"; #endif /* ! lint */ #include <sendmail.h> @@ -135,22 +135,31 @@ sendall(e, mode) if (e->e_hopcount > MaxHopCount) { + char *recip; + + if (e->e_sendqueue != NULL && + e->e_sendqueue->q_paddr != NULL) + recip = e->e_sendqueue->q_paddr; + else + recip = "(nobody)"; + errno = 0; #if QUEUE queueup(e, mode == SM_QUEUE || mode == SM_DEFER); #endif /* QUEUE */ e->e_flags |= EF_FATALERRS|EF_PM_NOTIFY|EF_CLRQUEUE; ExitStat = EX_UNAVAILABLE; - syserr("554 5.0.0 Too many hops %d (%d max): from %s via %s, to %s", - e->e_hopcount, MaxHopCount, e->e_from.q_paddr, - RealHostName == NULL ? "localhost" : RealHostName, - e->e_sendqueue->q_paddr); + syserr("554 5.4.6 Too many hops %d (%d max): from %s via %s, to %s", + e->e_hopcount, MaxHopCount, e->e_from.q_paddr, + RealHostName == NULL ? "localhost" : RealHostName, + recip); for (q = e->e_sendqueue; q != NULL; q = q->q_next) { if (QS_IS_DEAD(q->q_state)) continue; q->q_state = QS_BADADDR; q->q_status = "5.4.6"; + q->q_rstatus = "554 5.4.6 Too many hops"; } return; } @@ -635,6 +644,11 @@ sendall(e, mode) return; } + /* Reset global flags */ + RestartRequest = NULL; + ShutdownRequest = NULL; + PendingSignal = 0; + /* ** Since we have accepted responsbility for the message, ** change the SIGTERM handler. intsig() (the old handler) @@ -931,7 +945,7 @@ dup_queue_file(e, ee, type) ** returns twice, once in parent and once in child. */ -int +pid_t dofork() { register pid_t pid = -1; @@ -1451,7 +1465,7 @@ deliver(e, firstto) if (l > tobufsize) { if (tobuf != NULL) - free(tobuf); + sm_free(tobuf); tobufsize = l; tobuf = xalloc(tobufsize); } @@ -1719,10 +1733,10 @@ tryhost: m->m_name); i = makeconnection(hostbuf, port, mci, e); } + mci->mci_errno = errno; mci->mci_lastuse = curtime(); mci->mci_deliveries = 0; mci->mci_exitstat = i; - mci->mci_errno = errno; # if NAMED_BIND mci->mci_herrno = h_errno; # endif /* NAMED_BIND */ @@ -1913,6 +1927,11 @@ tryhost: struct stat stb; extern int DtableSize; + /* Reset global flags */ + RestartRequest = NULL; + ShutdownRequest = NULL; + PendingSignal = 0; + if (e->e_lockfp != NULL) (void) close(fileno(e->e_lockfp)); @@ -2511,7 +2530,9 @@ reconnect: /* after switching to an authenticated connection */ mci->mci_host, macvalue(macid("{auth_type}", NULL), e), - *ssf); + result == SASL_OK ? *ssf + : 0); + /* ** only switch to encrypted connection ** if a security layer has been negotiated @@ -3041,6 +3062,12 @@ static jmp_buf EndWaitTimeout; static void endwaittimeout() { + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + errno = ETIMEDOUT; longjmp(EndWaitTimeout, 1); } @@ -3059,6 +3086,19 @@ endmailer(mci, e, pv) mci_unlock_host(mci); + /* close output to mailer */ + if (mci->mci_out != NULL) + (void) fclose(mci->mci_out); + + /* copy any remaining input to transcript */ + if (mci->mci_in != NULL && mci->mci_state != MCIS_ERROR && + e->e_xfp != NULL) + { + while (sfgets(buf, sizeof buf, mci->mci_in, + TimeOuts.to_quit, "Draining Input") != NULL) + (void) fputs(buf, e->e_xfp); + } + #if SASL /* shutdown SASL */ if (bitset(MCIF_AUTHACT, mci->mci_flags)) @@ -3073,19 +3113,6 @@ endmailer(mci, e, pv) (void) endtlsclt(mci); #endif /* STARTTLS */ - /* close output to mailer */ - if (mci->mci_out != NULL) - (void) fclose(mci->mci_out); - - /* copy any remaining input to transcript */ - if (mci->mci_in != NULL && mci->mci_state != MCIS_ERROR && - e->e_xfp != NULL) - { - while (sfgets(buf, sizeof buf, mci->mci_in, - TimeOuts.to_quit, "Draining Input") != NULL) - (void) fputs(buf, e->e_xfp); - } - /* now close the input */ if (mci->mci_in != NULL) (void) fclose(mci->mci_in); @@ -3375,7 +3402,7 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e) if (status != EX_OK && (status != EX_TEMPFAIL || e->e_message == NULL)) { if (e->e_message != NULL) - free(e->e_message); + sm_free(e->e_message); e->e_message = newstr(statmsg + off); } errno = 0; @@ -3947,7 +3974,7 @@ putbody(mci, e, separator) TrafficLogFile); if (c == '\n') (void) fputs(mci->mci_mailer->m_eol, - TrafficLogFile); + TrafficLogFile); } if (padc != EOF) { @@ -4375,6 +4402,11 @@ mailfile(filename, mailer, ctladdr, sfflags, e) int err; volatile int oflags = O_WRONLY|O_APPEND; + /* Reset global flags */ + RestartRequest = NULL; + ShutdownRequest = NULL; + PendingSignal = 0; + if (e->e_lockfp != NULL) (void) close(fileno(e->e_lockfp)); @@ -4391,7 +4423,8 @@ mailfile(filename, mailer, ctladdr, sfflags, e) } if (TimeOuts.to_fileopen > 0) - ev = setevent(TimeOuts.to_fileopen, mailfiletimeout, 0); + ev = setevent(TimeOuts.to_fileopen, + mailfiletimeout, 0); else ev = NULL; @@ -4705,7 +4738,7 @@ mailfile(filename, mailer, ctladdr, sfflags, e) (*e->e_puthdr)(&mcibuf, e->e_header, e, M87F_OUTER); (*e->e_putbody)(&mcibuf, e, NULL); putline("\n", &mcibuf); - if (fflush(f) < 0 || + if (fflush(f) != 0 || (SuperSafe && fsync(fileno(f)) < 0) || ferror(f)) { @@ -4755,6 +4788,13 @@ mailfile(filename, mailer, ctladdr, sfflags, e) static void mailfiletimeout() { + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + + errno = ETIMEDOUT; longjmp(CtxMailfileTimeout, 1); } /* @@ -4802,17 +4842,19 @@ hostsignature(m, host) dprintf("hostsignature(%s)\n", host); /* - ** If local delivery, just return a constant. + ** If local delivery (and not remote), just return a constant. */ - if (bitnset(M_LOCALMAILER, m->m_flags)) + p = m->m_mailer; + if (bitnset(M_LOCALMAILER, m->m_flags) && + strcmp(p, "[IPC]") != 0 && + strcmp(p, "[TCP]") != 0) return "localhost"; /* ** Check to see if this uses IPC -- if not, it can't have MX records. */ - p = m->m_mailer; if (strcmp(p, "[IPC]") != 0 && strcmp(p, "[TCP]") != 0) { @@ -4920,7 +4962,7 @@ hostsignature(m, host) if (s->s_hostsig != NULL) { (void) strlcpy(p, s->s_hostsig, len); - free(s->s_hostsig); + sm_free(s->s_hostsig); s->s_hostsig = p; hl = strlen(p); p += hl; diff --git a/contrib/sendmail/src/envelope.c b/contrib/sendmail/src/envelope.c index a708589..bed63e4 100644 --- a/contrib/sendmail/src/envelope.c +++ b/contrib/sendmail/src/envelope.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: envelope.c,v 8.180.14.6 2000/11/30 00:39:46 gshapiro Exp $"; +static char id[] = "@(#)$Id: envelope.c,v 8.180.14.10 2001/05/03 17:24:06 gshapiro Exp $"; #endif /* ! lint */ #include <sendmail.h> @@ -132,7 +132,7 @@ dropenvelope(e, fulldrop) */ now = curtime(); - if (now > e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass]) + if (now >= e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass]) message_timeout = TRUE; if (TimeOuts.to_q_return[e->e_timeoutclass] == NOW && @@ -150,7 +150,7 @@ dropenvelope(e, fulldrop) /* see if a notification is needed */ if (bitset(QPINGONFAILURE, q->q_flags) && - ((message_timeout && QS_IS_QUEUEUP(q->q_state)) || + ((message_timeout && QS_IS_UNDELIVERED(q->q_state)) || QS_IS_BADADDR(q->q_state) || (TimeOuts.to_q_return[e->e_timeoutclass] == NOW && !bitset(EF_RESPONSE, e->e_flags)))) @@ -192,7 +192,7 @@ dropenvelope(e, fulldrop) "Cannot send message for %s", pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE)); if (e->e_message != NULL) - free(e->e_message); + sm_free(e->e_message); e->e_message = newstr(buf); message(buf); e->e_flags |= EF_CLRQUEUE; @@ -210,7 +210,7 @@ dropenvelope(e, fulldrop) } } else if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 && - now > e->e_ctime + TimeOuts.to_q_warning[e->e_timeoutclass]) + now >= e->e_ctime + TimeOuts.to_q_warning[e->e_timeoutclass]) { if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) && e->e_class >= 0 && @@ -222,7 +222,7 @@ dropenvelope(e, fulldrop) { for (q = e->e_sendqueue; q != NULL; q = q->q_next) { - if (QS_IS_QUEUEUP(q->q_state) && + if (QS_IS_UNDELIVERED(q->q_state) && #if _FFR_NODELAYDSN_ON_HOLD !bitnset(M_HOLD, q->q_mailer->m_flags) && #endif /* _FFR_NODELAYDSN_ON_HOLD */ @@ -239,7 +239,7 @@ dropenvelope(e, fulldrop) "Warning: could not send message for past %s", pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE)); if (e->e_message != NULL) - free(e->e_message); + sm_free(e->e_message); e->e_message = newstr(buf); message(buf); e->e_flags |= EF_WARNING; diff --git a/contrib/sendmail/src/err.c b/contrib/sendmail/src/err.c index 78b5c5d..9e3e572 100644 --- a/contrib/sendmail/src/err.c +++ b/contrib/sendmail/src/err.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: err.c,v 8.120.4.1 2000/05/25 18:56:15 gshapiro Exp $"; +static char id[] = "@(#)$Id: err.c,v 8.120.4.2 2001/05/03 17:24:06 gshapiro Exp $"; #endif /* ! lint */ #include <sendmail.h> @@ -107,7 +107,7 @@ syserr(fmt, va_alist) if (!panic && CurEnv != NULL) { if (CurEnv->e_message != NULL) - free(CurEnv->e_message); + sm_free(CurEnv->e_message); CurEnv->e_message = newstr(errtxt); } @@ -122,13 +122,13 @@ syserr(fmt, va_alist) dprintf("syserr: ExitStat = %d\n", ExitStat); } - pw = sm_getpwuid(getuid()); + pw = sm_getpwuid(RealUid); if (pw != NULL) user = pw->pw_name; else { user = ubuf; - snprintf(ubuf, sizeof ubuf, "UID%d", (int) getuid()); + snprintf(ubuf, sizeof ubuf, "UID%d", (int) RealUid); } if (LogLevel > 0) @@ -237,7 +237,7 @@ usrerr(fmt, va_alist) case '5': case '6': if (CurEnv->e_message != NULL) - free(CurEnv->e_message); + sm_free(CurEnv->e_message); if (MsgBuf[0] == '6') { char buf[MAXLINE]; @@ -323,7 +323,7 @@ usrerrenh(enhsc, fmt, va_alist) case '5': case '6': if (CurEnv->e_message != NULL) - free(CurEnv->e_message); + sm_free(CurEnv->e_message); if (MsgBuf[0] == '6') { char buf[MAXLINE]; @@ -392,7 +392,7 @@ message(msg, va_alist) case '5': if (CurEnv->e_message != NULL) - free(CurEnv->e_message); + sm_free(CurEnv->e_message); CurEnv->e_message = newstr(errtxt); break; } @@ -446,7 +446,7 @@ nmessage(msg, va_alist) case '5': if (CurEnv->e_message != NULL) - free(CurEnv->e_message); + sm_free(CurEnv->e_message); CurEnv->e_message = newstr(errtxt); break; } diff --git a/contrib/sendmail/src/headers.c b/contrib/sendmail/src/headers.c index c191252..4c6259d 100644 --- a/contrib/sendmail/src/headers.c +++ b/contrib/sendmail/src/headers.c @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: headers.c,v 8.203.4.12 2001/01/22 19:00:22 gshapiro Exp $"; +static char id[] = "@(#)$Id: headers.c,v 8.203.4.13 2001/05/03 17:24:06 gshapiro Exp $"; #endif /* ! lint */ #include <sendmail.h> @@ -341,7 +341,7 @@ hse: } if ((sp = macvalue(macid("{currHeader}", NULL), e)) != NULL) - free(sp); + sm_free(sp); define(macid("{currHeader}", NULL), newstr(qval), e); define(macid("{hdr_name}", NULL), newstr(fname), e); (void) rscheck(rs, fvalue, NULL, e, stripcom, TRUE, 4, diff --git a/contrib/sendmail/src/main.c b/contrib/sendmail/src/main.c index bf976e0..34d5041 100644 --- a/contrib/sendmail/src/main.c +++ b/contrib/sendmail/src/main.c @@ -21,7 +21,7 @@ static char copyright[] = #endif /* ! lint */ #ifndef lint -static char id[] = "@(#)$Id: main.c,v 8.485.4.44 2001/02/08 14:06:55 ca Exp $"; +static char id[] = "@(#)$Id: main.c,v 8.485.4.60 2001/05/27 22:00:26 gshapiro Exp $"; #endif /* ! lint */ #define _DEFINE @@ -33,6 +33,10 @@ static char id[] = "@(#)$Id: main.c,v 8.485.4.44 2001/02/08 14:06:55 ca Exp $"; # include <arpa/inet.h> #endif /* NETINET || NETINET6 */ +static SIGFUNC_DECL intindebug __P((int)); +static SIGFUNC_DECL quiesce __P((int)); +static SIGFUNC_DECL sigusr1 __P((int)); +static SIGFUNC_DECL term_daemon __P((int)); static void dump_class __P((STAB *, int)); static void obsolete __P((char **)); static void testmodeline __P((char *, ENVELOPE *)); @@ -76,7 +80,6 @@ ADDRESS NullAddress = /* a null address */ { "", "", NULL, "" }; 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 */ static int MissingFds = 0; /* bit map of fds missing on startup */ #ifdef NGROUPS_MAX @@ -161,6 +164,14 @@ main(argc, argv, envp) /* avoid null pointer dereferences */ TermEscape.te_rv_on = TermEscape.te_rv_off = ""; + /* + ** Seed the random number generator. + ** Used for queue file names, picking a queue directory, and + ** MX randomization. + */ + + seed_random(); + /* do machine-dependent initializations */ init_md(argc, argv); @@ -218,14 +229,6 @@ main(argc, argv, envp) checkfd012("after openlog"); #endif /* XDEBUG */ - /* - ** Seed the random number generator. - ** Used for queue file names, picking a queue directory, and - ** MX randomization. - */ - - seed_random(); - tTsetup(tTdvect, sizeof tTdvect, "0-99.1"); #ifdef NGROUPS_MAX @@ -242,8 +245,13 @@ main(argc, argv, envp) setstat(dp); # ifdef SIGUSR1 - /* arrange to dump state on user-1 signal */ - (void) setsignal(SIGUSR1, sigusr1); + /* Only allow root (or non-set-*-ID binaries) to use SIGUSR1 */ + if (getuid() == 0 || + (getuid() == geteuid() && getgid() == getegid())) + { + /* arrange to dump state on user-1 signal */ + (void) setsignal(SIGUSR1, sigusr1); + } # endif /* SIGUSR1 */ /* initialize for setproctitle */ @@ -300,17 +308,23 @@ main(argc, argv, envp) } opterr = 1; +#if LOG if (sysloglabel != NULL) { -#if LOG + /* Sanitize the string */ + for (p = sysloglabel; *p != '\0'; p++) + { + if (!isascii(*p) || !isprint(*p) || *p == '%') + *p = '*'; + } closelog(); # ifdef LOG_MAIL openlog(sysloglabel, LOG_PID, LOG_MAIL); # else /* LOG_MAIL */ openlog(sysloglabel, LOG_PID); # endif /* LOG_MAIL */ -#endif /* LOG */ } +#endif /* LOG */ /* set up the blank envelope */ BlankEnvelope.e_puthdr = putheader; @@ -349,6 +363,7 @@ main(argc, argv, envp) ** if running non-setuid binary as non-root, pretend ** we are the RunAsUid */ + if (RealUid != 0 && geteuid() == RealUid) { if (tTd(47, 1)) @@ -471,11 +486,8 @@ main(argc, argv, envp) /* prime the child environment */ setuserenv("AGENT", "sendmail"); - - if (setsignal(SIGINT, SIG_IGN) != SIG_IGN) - (void) setsignal(SIGINT, intsig); - (void) setsignal(SIGTERM, intsig); (void) setsignal(SIGPIPE, SIG_IGN); + OldUmask = umask(022); OpMode = MD_DELIVER; FullName = getextenv("NAME"); @@ -1025,6 +1037,59 @@ main(argc, argv, envp) ConfigFileRead = TRUE; vendor_post_defaults(CurEnv); + /* Remove the ability for a normal user to send signals */ + if (RealUid != 0 && + RealUid != geteuid()) + { + uid_t new_uid = geteuid(); + +#if HASSETREUID + /* + ** Since we can differentiate between uid and euid, + ** make the uid a different user so the real user + ** can't send signals. However, it doesn't need to be + ** root (euid has root). + */ + + if (new_uid == 0) + new_uid = DefUid; + if (tTd(47, 5)) + dprintf("Changing real uid to %d\n", (int) new_uid); + if (setreuid(new_uid, geteuid()) < 0) + { + syserr("main: setreuid(%d, %d) failed", + (int) new_uid, (int) geteuid()); + finis(FALSE, EX_OSERR); + /* NOTREACHED */ + } + if (tTd(47, 10)) + dprintf("Now running as e/ruid %d:%d\n", + (int) geteuid(), (int) getuid()); +#else /* HASSETREUID */ + /* + ** Have to change both effective and real so need to + ** change them both to effective to keep privs. + */ + + if (tTd(47, 5)) + dprintf("Changing uid to %d\n", (int) new_uid); + if (setuid(new_uid) < 0) + { + syserr("main: setuid(%d) failed", (int) new_uid); + finis(FALSE, EX_OSERR); + /* NOTREACHED */ + } + if (tTd(47, 10)) + dprintf("Now running as e/ruid %d:%d\n", + (int) geteuid(), (int) getuid()); +#endif /* HASSETREUID */ + } + + /* set up the basic signal handlers */ + if (setsignal(SIGINT, SIG_IGN) != SIG_IGN) + (void) setsignal(SIGINT, intsig); + (void) setsignal(SIGTERM, intsig); + /* Enforce use of local time (null string overrides this) */ if (TimeZoneSpec == NULL) unsetenv("TZ"); @@ -1184,6 +1249,7 @@ main(argc, argv, envp) case MD_VERIFY: CurEnv->e_errormode = EM_PRINT; HoldErrs = FALSE; + /* arrange to exit cleanly on hangup signal */ if (setsignal(SIGHUP, SIG_IGN) == (sigfunc_t) SIG_DFL) (void) setsignal(SIGHUP, intsig); @@ -1205,10 +1271,7 @@ main(argc, argv, envp) if (SaveArgv[0] == NULL || SaveArgv[0][0] != '/') sm_syslog(LOG_WARNING, NOQID, "daemon invoked without full pathname; kill -1 won't work"); - (void) setsignal(SIGHUP, sighup); - - /* workaround: can't seem to release the signal in the parent */ - (void) releasesignal(SIGHUP); + (void) setsignal(SIGTERM, term_daemon); break; case MD_INITALIAS: @@ -1247,7 +1310,7 @@ main(argc, argv, envp) FullName = addquotes(FullName); if (full != NULL) - free(full); + sm_free(full); } } @@ -1589,20 +1652,7 @@ main(argc, argv, envp) #if SMTP # if STARTTLS - /* - ** basic TLS initialization - ** ignore result for now - */ - SSL_library_init(); - SSL_load_error_strings(); -# if 0 - /* this is currently a macro for SSL_library_init */ - SSLeay_add_ssl_algorithms(); -# endif /* 0 */ - - /* initialize PRNG */ - tls_ok = tls_rand_init(RandFile, 7); - + tls_ok = init_tls_library(); # endif /* STARTTLS */ #endif /* SMTP */ @@ -1698,10 +1748,13 @@ main(argc, argv, envp) { /* write the pid to file */ log_sendmail_pid(CurEnv); + (void) setsignal(SIGTERM, term_daemon); for (;;) { (void) pause(); - if (DoQueueRun) + if (ShutdownRequest != NULL) + shutdown_daemon(); + else if (DoQueueRun) (void) runqueue(TRUE, FALSE); } } @@ -1996,21 +2049,89 @@ main(argc, argv, envp) /* NOTREACHED */ return ExitStat; } +/* +** QUIESCE -- signal handler for SIGPIPE +** +** Parameters: +** sig -- incoming signal. +** +** Returns: +** none. +** +** Side Effects: +** Sets StopRequest which should cause the mailq/hoststatus +** display to stop. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ /* ARGSUSED */ -SIGFUNC_DECL +static SIGFUNC_DECL quiesce(sig) int sig; { - clear_events(); - finis(FALSE, EX_OK); + int save_errno = errno; + + FIX_SYSV_SIGNAL(sig, quiesce); + StopRequest = TRUE; + errno = save_errno; + return SIGFUNC_RETURN; +} +/* +** STOP_SENDMAIL -- Stop the running program +** +** Parameters: +** none. +** +** Returns: +** none. +** +** Side Effects: +** exits. +*/ + +void +stop_sendmail() +{ + /* reset uid for process accounting */ + endpwent(); + (void) setuid(RealUid); + exit(EX_OK); } +/* +** INTINDEBUG -- signal handler for SIGINT in -bt mode +** +** Parameters: +** sig -- incoming signal. +** +** Returns: +** none. +** +** Side Effects: +** longjmps back to test mode loop. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +** +** XXX: More work is needed for this signal handler. +*/ + /* ARGSUSED */ -SIGFUNC_DECL +static SIGFUNC_DECL intindebug(sig) int sig; { + int save_errno = errno; + + FIX_SYSV_SIGNAL(sig, intindebug); + errno = save_errno; + CHECK_CRITICAL(sig); + + errno = save_errno; longjmp(TopFrame, 1); return SIGFUNC_RETURN; } @@ -2033,6 +2154,9 @@ finis(drop, exitstat) bool drop; volatile int exitstat; { + /* Still want to process new timeouts added below */ + clear_events(); + releasesignal(SIGALRM); if (tTd(2, 1)) { @@ -2082,7 +2206,7 @@ finis(drop, exitstat) if (LogLevel > 78) sm_syslog(LOG_DEBUG, CurEnv->e_id, "finis, pid=%d", - getpid()); + (int) getpid()); if (exitstat == EX_TEMPFAIL || CurEnv->e_errormode == EM_BERKNET) exitstat = EX_OK; @@ -2094,6 +2218,71 @@ finis(drop, exitstat) exit(exitstat); } /* +** TERM_DEAMON -- SIGTERM handler for the daemon +** +** Parameters: +** sig -- signal number. +** +** Returns: +** none. +** +** Side Effects: +** Sets ShutdownRequest which will hopefully trigger +** the daemon to exit. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +/* ARGSUSED */ +static SIGFUNC_DECL +term_daemon(sig) + int sig; +{ + int save_errno = errno; + + FIX_SYSV_SIGNAL(sig, term_daemon); + ShutdownRequest = "signal"; + errno = save_errno; + return SIGFUNC_RETURN; +} +/* +** SHUTDOWN_DAEMON -- Performs a clean shutdown of the daemon +** +** Parameters: +** none. +** +** Returns: +** none. +** +** Side Effects: +** closes control socket, exits. +*/ + +void +shutdown_daemon() +{ + char *reason; + + allsignals(TRUE); + + reason = ShutdownRequest; + ShutdownRequest = NULL; + PendingSignal = 0; + + if (LogLevel > 79) + sm_syslog(LOG_DEBUG, CurEnv->e_id, "interrupt"); + + FileName = NULL; + closecontrolsocket(TRUE); +#ifdef XLA + xla_all_end(); +#endif /* XLA */ + + finis(FALSE, EX_OK); +} +/* ** INTSIG -- clean up on interrupt ** ** This just arranges to exit. It pessimizes in that it @@ -2107,6 +2296,12 @@ finis(drop, exitstat) ** ** Side Effects: ** Unlocks the current job. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +** +** XXX: More work is needed for this signal handler. */ /* ARGSUSED */ @@ -2115,15 +2310,15 @@ intsig(sig) int sig; { bool drop = FALSE; + int save_errno = errno; - clear_events(); + FIX_SYSV_SIGNAL(sig, intsig); + errno = save_errno; + CHECK_CRITICAL(sig); + allsignals(TRUE); if (sig != 0 && LogLevel > 79) sm_syslog(LOG_DEBUG, CurEnv->e_id, "interrupt"); FileName = NULL; - closecontrolsocket(TRUE); -#ifdef XLA - xla_all_end(); -#endif /* XLA */ /* Clean-up on aborted stdin message submission */ if (CurEnv->e_id != NULL && @@ -2324,7 +2519,7 @@ disconnect(droplev, e) if (LogLevel > 71) sm_syslog(LOG_DEBUG, e->e_id, "in background, pid=%d", - getpid()); + (int) getpid()); errno = 0; } @@ -2563,69 +2758,36 @@ dumpstate(when) } sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- end of state dump ---"); } - +/* +** SIGUSR1 -- Signal a request to dump state. +** +** Parameters: +** sig -- calling signal. +** +** Returns: +** none. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +** +** XXX: More work is needed for this signal handler. +*/ /* ARGSUSED */ -SIGFUNC_DECL +static SIGFUNC_DECL sigusr1(sig) int sig; { + int save_errno = errno; + + FIX_SYSV_SIGNAL(sig, sigusr1); + errno = save_errno; + CHECK_CRITICAL(sig); dumpstate("user signal"); + errno = save_errno; return SIGFUNC_RETURN; } - - -/* ARGSUSED */ -SIGFUNC_DECL -sighup(sig) - int sig; -{ - int i; - extern int DtableSize; - - clear_events(); - (void) alarm(0); - if (SaveArgv[0][0] != '/') - { - if (LogLevel > 3) - sm_syslog(LOG_INFO, NOQID, - "could not restart: need full path"); - finis(FALSE, EX_OSFILE); - } - if (LogLevel > 3) - sm_syslog(LOG_INFO, NOQID, "restarting %s %s", - sig == 0 ? "due to control command" : "on signal", - SaveArgv[0]); - - /* Control socket restart? */ - if (sig != 0) - (void) releasesignal(SIGHUP); - - closecontrolsocket(TRUE); - if (drop_privileges(TRUE) != EX_OK) - { - if (LogLevel > 0) - sm_syslog(LOG_ALERT, NOQID, - "could not set[ug]id(%d, %d): %m", - RunAsUid, RunAsGid); - finis(FALSE, EX_OSERR); - } - - /* arrange for all the files to be closed */ - for (i = 3; i < DtableSize; i++) - { - register int j; - - if ((j = fcntl(i, F_GETFD, 0)) != -1) - (void) fcntl(i, F_SETFD, j | FD_CLOEXEC); - } - - (void) execve(SaveArgv[0], (ARGV_T) SaveArgv, (ARGV_T) ExternalEnviron); - if (LogLevel > 0) - sm_syslog(LOG_ALERT, NOQID, "could not exec %s: %m", - SaveArgv[0]); - finis(FALSE, EX_OSFILE); -} /* ** DROP_PRIVILEGES -- reduce privileges to those of the RunAsUser option ** diff --git a/contrib/sendmail/src/map.c b/contrib/sendmail/src/map.c index 4a10c81..fc0d07f 100644 --- a/contrib/sendmail/src/map.c +++ b/contrib/sendmail/src/map.c @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: map.c,v 8.414.4.39 2001/02/22 18:56:22 gshapiro Exp $"; +static char id[] = "@(#)$Id: map.c,v 8.414.4.53 2001/05/04 01:29:00 gshapiro Exp $"; #endif /* ! lint */ #include <sendmail.h> @@ -370,7 +370,7 @@ map_rewrite(map, s, slen, av) /* need to malloc additional space */ buflen = len; if (buf != NULL) - free(buf); + sm_free(buf); buf = xalloc(buflen); } @@ -492,8 +492,9 @@ map_init(s, unused) /* if already open, close it (for nested open) */ if (bitset(MF_OPEN, map->map_mflags)) { + map->map_mflags |= MF_CLOSING; map->map_class->map_close(map); - map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); } (void) rebuildaliases(map, FALSE); @@ -627,6 +628,7 @@ map_close(s, unused) if (!bitset(MF_VALID, map->map_mflags) || !bitset(MF_OPEN, map->map_mflags) || + bitset(MF_CLOSING, map->map_mflags) || map->map_pid != getpid()) return; @@ -635,8 +637,9 @@ map_close(s, unused) map->map_mname == NULL ? "NULL" : map->map_mname, map->map_file == NULL ? "NULL" : map->map_file); + map->map_mflags |= MF_CLOSING; map->map_class->map_close(map); - map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); } /* ** GETCANONNAME -- look up name using service switch @@ -1079,7 +1082,7 @@ ndbm_map_open(map, mode) ** map_mtime to be set */ - if (fstat(dfd, &st) >= 0) + if (fstat(pfd, &st) >= 0) map->map_mtime = st.st_mtime; if (mode == O_RDONLY) @@ -1130,7 +1133,7 @@ ndbm_map_lookup(map, name, av, statp) int *statp; { datum key, val; - int fd; + int dfd, pfd; char keybuf[MAXNAME + 1]; struct stat stbuf; @@ -1150,19 +1153,22 @@ ndbm_map_lookup(map, name, av, statp) key.dptr = keybuf; } lockdbm: - fd = dbm_dirfno((DBM *) map->map_db1); - if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) - (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); - if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime) + dfd = dbm_dirfno((DBM *) map->map_db1); + if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) + (void) lockfile(dfd, map->map_file, ".dir", LOCK_SH); + pfd = dbm_pagfno((DBM *) map->map_db1); + if (pfd < 0 || fstat(pfd, &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; - if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) - (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); + if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) + (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); + map->map_mflags |= MF_CLOSING; map->map_class->map_close(map); - map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); if (map->map_class->map_open(map, omode)) { map->map_mflags |= MF_OPEN; @@ -1201,8 +1207,8 @@ lockdbm: if (val.dptr != NULL) map->map_mflags &= ~MF_TRY0NULL; } - if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) - (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); + if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) + (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); if (val.dptr == NULL) return NULL; if (bitset(MF_MATCHONLY, map->map_mflags)) @@ -1272,7 +1278,7 @@ ndbm_map_store(map, lhs, rhs) if (data.dsize + old.dsize + 2 > bufsiz) { if (buf != NULL) - (void) free(buf); + sm_free(buf); bufsiz = data.dsize + old.dsize + 2; buf = xalloc(bufsiz); } @@ -1803,8 +1809,9 @@ db_map_lookup(map, name, av, statp) if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) (void) lockfile(fd, buf, ".db", LOCK_UN); + map->map_mflags |= MF_CLOSING; map->map_class->map_close(map); - map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); if (map->map_class->map_open(map, omode)) { map->map_mflags |= MF_OPEN; @@ -1983,7 +1990,7 @@ db_map_store(map, lhs, rhs) if (data.size + old.size + 2 > (size_t)bufsiz) { if (buf != NULL) - (void) free(buf); + sm_free(buf); bufsiz = data.size + old.size + 2; buf = xalloc(bufsiz); } @@ -2141,7 +2148,7 @@ nis_map_open(map, mode) dprintf("nis_map_open: yp_match(@, %s, %s) => %s\n", map->map_domain, map->map_file, yperr_string(yperr)); if (vp != NULL) - free(vp); + sm_free(vp); if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) { @@ -2211,7 +2218,7 @@ nis_map_lookup(map, name, av, statp) { if (vp != NULL) { - free(vp); + sm_free(vp); vp = NULL; } buflen++; @@ -2225,7 +2232,7 @@ nis_map_lookup(map, name, av, statp) if (yperr != YPERR_KEY && yperr != YPERR_BUSY) map->map_mflags &= ~(MF_VALID|MF_OPEN); if (vp != NULL) - free(vp); + sm_free(vp); return NULL; } if (bitset(MF_MATCHONLY, map->map_mflags)) @@ -2236,7 +2243,7 @@ nis_map_lookup(map, name, av, statp) ret = map_rewrite(map, vp, vsize, av); if (vp != NULL) - free(vp); + sm_free(vp); return ret; } } @@ -2290,7 +2297,7 @@ nis_getcanonname(name, hbsize, statp) { if (vp != NULL) { - free(vp); + sm_free(vp); vp = NULL; } keylen++; @@ -2308,11 +2315,11 @@ nis_getcanonname(name, hbsize, statp) else *statp = EX_UNAVAILABLE; if (vp != NULL) - free(vp); + sm_free(vp); return FALSE; } (void) strlcpy(host_record, vp, sizeof host_record); - free(vp); + sm_free(vp); if (tTd(38, 44)) dprintf("got record `%s'\n", host_record); if (!extract_canonname(nbuf, NULL, host_record, cbuf, sizeof cbuf)) @@ -2850,10 +2857,15 @@ ldapmap_open(map, mode) lmap = (LDAPMAP_STRUCT *) map->map_db1; s = ldapmap_findconn(lmap); - if (s->s_ldap != NULL) + if (s->s_lmap != NULL) { /* Already have a connection open to this LDAP server */ - lmap->ldap_ld = s->s_ldap; + lmap->ldap_ld = ((LDAPMAP_STRUCT *)s->s_lmap->map_db1)->ldap_ld; + + /* Add this map as head of linked list */ + lmap->ldap_next = s->s_lmap; + s->s_lmap = map; + if (tTd(38, 2)) dprintf("using cached connection\n"); return TRUE; @@ -2867,7 +2879,7 @@ ldapmap_open(map, mode) return FALSE; /* Save connection for reuse */ - s->s_ldap = lmap->ldap_ld; + s->s_lmap = map; return TRUE; } @@ -3036,6 +3048,13 @@ static void ldaptimeout(sig_no) int sig_no; { + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + + errno = ETIMEDOUT; longjmp(LDAPTimeout, 1); } @@ -3059,20 +3078,25 @@ ldapmap_close(map) if (lmap->ldap_ld == NULL) return; + /* Close the LDAP connection */ + ldap_unbind(lmap->ldap_ld); + + /* Mark all the maps that share the connection as closed */ s = ldapmap_findconn(lmap); - /* Check if already closed */ - if (s->s_ldap == NULL) - return; + while (s->s_lmap != NULL) + { + MAP *smap = s->s_lmap; - /* If same as saved connection, stored connection is going away */ - if (s->s_ldap == lmap->ldap_ld) - s->s_ldap = NULL; + if (tTd(38, 2) && smap != map) + dprintf("ldapmap_close(%s): closed %s (shared LDAP connection)\n", + map->map_mname, smap->map_mname); - if (lmap->ldap_ld != NULL) - { - ldap_unbind(lmap->ldap_ld); + smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + lmap = (LDAPMAP_STRUCT *) smap->map_db1; lmap->ldap_ld = NULL; + s->s_lmap = lmap->ldap_next; + lmap->ldap_next = NULL; } } @@ -3214,7 +3238,10 @@ ldapmap_lookup(map, name, av, statp) lmap->ldap_attrsonly); if (msgid == -1) { + int save_errno; + errno = ldapmap_geterrno(lmap->ldap_ld) + E_LDAPBASE; + save_errno = errno; if (!bitset(MF_OPTIONAL, map->map_mflags)) { if (bitset(MF_NODEFER, map->map_mflags)) @@ -3226,16 +3253,14 @@ ldapmap_lookup(map, name, av, statp) } *statp = EX_TEMPFAIL; #ifdef LDAP_SERVER_DOWN - if (errno == LDAP_SERVER_DOWN) + errno = save_errno; + if (errno == LDAP_SERVER_DOWN + E_LDAPBASE) { - int save_errno = errno; - /* server disappeared, try reopen on next search */ - map->map_class->map_close(map); - map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); - errno = save_errno; + ldapmap_close(map); } #endif /* LDAP_SERVER_DOWN */ + errno = save_errno; return NULL; } @@ -3265,7 +3290,7 @@ ldapmap_lookup(map, name, av, statp) } (void) ldap_abandon(lmap->ldap_ld, msgid); if (vp != NULL) - free(vp); + sm_free(vp); if (tTd(38, 25)) dprintf("ldap search found multiple on a single match query\n"); return NULL; @@ -3348,7 +3373,7 @@ ldapmap_lookup(map, name, av, statp) (void) ldap_abandon(lmap->ldap_ld, msgid); if (vp != NULL) - free(vp); + sm_free(vp); return NULL; } } @@ -3419,7 +3444,7 @@ ldapmap_lookup(map, name, av, statp) snprintf(tmp, vsize, "%s%c%s", vp, map->map_coldelim, attr); - free(vp); + sm_free(vp); vp = tmp; } # if USING_NETSCAPE_LDAP @@ -3465,8 +3490,8 @@ ldapmap_lookup(map, name, av, statp) snprintf(tmp, vsize, "%s%c%s", vp, map->map_coldelim, vp_tmp); - free(vp); - free(vp_tmp); + sm_free(vp); + sm_free(vp_tmp); vp = tmp; } errno = ldapmap_geterrno(lmap->ldap_ld); @@ -3502,7 +3527,7 @@ ldapmap_lookup(map, name, av, statp) } (void) ldap_abandon(lmap->ldap_ld, msgid); if (vp != NULL) - free(vp); + sm_free(vp); return NULL; } @@ -3532,7 +3557,7 @@ ldapmap_lookup(map, name, av, statp) } (void) ldap_abandon(lmap->ldap_ld, msgid); if (vp != NULL) - free(vp); + sm_free(vp); return NULL; } ldap_msgfree(lmap->ldap_res); @@ -3557,7 +3582,7 @@ ldapmap_lookup(map, name, av, statp) lmap->ldap_res = NULL; } if (vp != NULL) - free(vp); + sm_free(vp); return NULL; } *statp = EX_OK; @@ -3569,9 +3594,13 @@ ldapmap_lookup(map, name, av, statp) errno = ldapmap_geterrno(lmap->ldap_ld); if (errno != LDAP_SUCCESS) { + int save_errno; + /* Must be an error */ if (ret != 0) errno += E_LDAPBASE; + save_errno = errno; + if (!bitset(MF_OPTIONAL, map->map_mflags)) { if (bitset(MF_NODEFER, map->map_mflags)) @@ -3583,7 +3612,16 @@ ldapmap_lookup(map, name, av, statp) } *statp = EX_TEMPFAIL; if (vp != NULL) - free(vp); + sm_free(vp); +#ifdef LDAP_SERVER_DOWN + errno = save_errno; + if (errno == LDAP_SERVER_DOWN + E_LDAPBASE) + { + /* server disappeared, try reopen on next search */ + ldapmap_close(map); + } +#endif /* LDAP_SERVER_DOWN */ + errno = save_errno; return NULL; } @@ -3601,7 +3639,7 @@ ldapmap_lookup(map, name, av, statp) if (bitset(MF_NOREWRITE, map->map_mflags)) { if (vp != NULL) - free(vp); + sm_free(vp); return ""; } @@ -3619,7 +3657,7 @@ ldapmap_lookup(map, name, av, statp) result = map_rewrite(map, vp, strlen(vp), av); } if (vp != NULL) - free(vp); + sm_free(vp); } return result; } @@ -3664,9 +3702,9 @@ ldapmap_findconn(lmap) (lmap->ldap_binddn == NULL ? "" : lmap->ldap_binddn), CONDELSE, (lmap->ldap_secret == NULL ? "" : lmap->ldap_secret), - getpid()); - s = stab(nbuf, ST_LDAP, ST_ENTER); - free(nbuf); + (int) getpid()); + s = stab(nbuf, ST_LMAP, ST_ENTER); + sm_free(nbuf); return s; } /* @@ -4309,6 +4347,7 @@ ldapmap_clear(lmap) lmap->ldap_filter = NULL; lmap->ldap_attr[0] = NULL; lmap->ldap_res = NULL; + lmap->ldap_next = NULL; } /* ** LDAPMAP_SET_DEFAULTS -- Read default map spec from LDAPDefaults in .cf @@ -4357,12 +4396,12 @@ ldapmap_set_defaults(spec) syserr("readcf: option LDAPDefaultSpec: Do not set non-LDAP specific flags"); if (map.map_app != NULL) { - free(map.map_app); + sm_free(map.map_app); map.map_app = NULL; } if (map.map_tapp != NULL) { - free(map.map_tapp); + sm_free(map.map_tapp); map.map_tapp = NULL; } } @@ -4594,9 +4633,16 @@ static jmp_buf PHTimeout; /* ARGSUSED */ static void -ph_timeout_func(sig_no) - int sig_no; +ph_timeout(sig) + int sig; { + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + + errno = ETIMEDOUT; longjmp(PHTimeout, 1); } #else /* _FFR_PHMAP_TIMEOUT */ @@ -4695,7 +4741,7 @@ ph_map_open(map, mode) # endif /* ETIMEDOUT */ goto ph_map_open_abort; } - ev = setevent(pmap->ph_timeout, ph_timeout_func, 0); + ev = setevent(pmap->ph_timeout, ph_timeout, 0); } if (!OpenQiSock(tmp, &(pmap->ph_sockfd)) && !Sock2FILEs(pmap->ph_sockfd, &(pmap->ph_to_server), @@ -4714,7 +4760,7 @@ ph_map_open(map, mode) { if (fprintf(pmap->ph_to_server, "id sendmail+phmap\n") < 0 || - fflush(pmap->ph_to_server) < 0 || + fflush(pmap->ph_to_server) != 0 || (server_data = ReadQi(pmap->ph_from_server, &j)) == NULL || server_data->code != 200) @@ -4727,7 +4773,7 @@ ph_map_open(map, mode) if (server_data != NULL) FreeQIR(server_data); #endif /* _FFR_PHMAP_TIMEOUT */ - free(hostlist); + sm_free(hostlist); return TRUE; } #if _FFR_PHMAP_TIMEOUT @@ -4759,7 +4805,7 @@ ph_map_open(map, mode) sm_syslog(LOG_NOTICE, CurEnv->e_id, "ph_map_open: %s: cannot connect to PH server", map->map_mname); - free(hostlist); + sm_free(hostlist); return FALSE; } @@ -4814,7 +4860,7 @@ ph_map_lookup(map, key, args, pstat) *pstat = EX_TEMPFAIL; goto ph_map_lookup_abort; } - ev = setevent(pmap->ph_timeout, ph_timeout_func, 0); + ev = setevent(pmap->ph_timeout, ph_timeout, 0); } #endif /* _FFR_PHMAP_TIMEOUT */ @@ -4883,7 +4929,7 @@ ph_map_lookup(map, key, args, pstat) if (fprintf(pmap->ph_to_server, "query %s=%s return email\n", tmp2, fmtkey) < 0) message = "qi query command failed"; - else if (fflush(pmap->ph_to_server) < 0) + else if (fflush(pmap->ph_to_server) != 0) message = "qi fflush failed"; else if ((server_data = ReadQi(pmap->ph_from_server, &j)) == NULL) @@ -5271,6 +5317,7 @@ hes_map_lookup(map, name, av, statp) { char *np; int nl; + int save_errno; char nbuf[MAXNAME]; nl = strlen(name); @@ -5285,8 +5332,10 @@ hes_map_lookup(map, name, av, statp) # else /* HESIOD_INIT */ hp = hes_resolve(np, map->map_file); # endif /* HESIOD_INIT */ + save_errno = errno; if (np != nbuf) - free(np); + sm_free(np); + errno = save_errno; } else { @@ -5297,11 +5346,8 @@ hes_map_lookup(map, name, av, statp) # endif /* HESIOD_INIT */ } # ifdef HESIOD_INIT - if (hp == NULL) - return NULL; - if (*hp == NULL) + if (hp == NULL || *hp == NULL) { - hesiod_free_list(HesiodContext, hp); switch (errno) { case ENOENT: @@ -5316,6 +5362,7 @@ hes_map_lookup(map, name, av, statp) *statp = EX_UNAVAILABLE; break; } + hesiod_free_list(HesiodContext, hp); return NULL; } # else /* HESIOD_INIT */ @@ -5413,7 +5460,7 @@ ni_map_lookup(map, name, av, statp) res = map_rewrite(map, name, strlen(name), NULL); else res = map_rewrite(map, propval, strlen(propval), av); - free(propval); + sm_free(propval); return res; } @@ -5461,12 +5508,12 @@ ni_getcanonname(name, hbsize, statp) if (hbsize >= strlen(vptr)) { (void) strlcpy(name, vptr, hbsize); - free(vptr); + sm_free(vptr); *statp = EX_OK; return TRUE; } *statp = EX_UNAVAILABLE; - free(vptr); + sm_free(vptr); return FALSE; } @@ -6352,7 +6399,7 @@ prog_map_lookup(map, name, av, statp) if (bitset(MF_MATCHONLY, map->map_mflags)) rval = map_rewrite(map, name, strlen(name), NULL); else - rval = map_rewrite(map, buf, strlen(buf), NULL); + rval = map_rewrite(map, buf, strlen(buf), av); /* now flush any additional output */ while ((i = read(fd, buf, sizeof buf)) > 0) @@ -6543,8 +6590,9 @@ seq_map_close(map) if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags)) continue; + mm->map_mflags |= MF_CLOSING; mm->map_class->map_close(mm); - mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); } } @@ -6892,8 +6940,8 @@ regex_map_init(map, ap) (void) regerror(regerr, map_p->regex_pattern_buf, errbuf, ERRBUF_SIZE); syserr("pattern-compile-error: %s\n", errbuf); - free(map_p->regex_pattern_buf); - free(map_p); + sm_free(map_p->regex_pattern_buf); + sm_free(map_p); return FALSE; } @@ -6919,8 +6967,8 @@ regex_map_init(map, ap) if (substrings >= MAX_MATCH) { syserr("too many substrings, %d max\n", MAX_MATCH); - free(map_p->regex_pattern_buf); - free(map_p); + sm_free(map_p->regex_pattern_buf); + sm_free(map_p); return FALSE; } if (sub_param != NULL && sub_param[0] != '\0') @@ -6965,7 +7013,7 @@ regex_map_rewrite(map, s, slen, av) if (bitset(MF_MATCHONLY, map->map_mflags)) return map_rewrite(map, av[0], strlen(av[0]), NULL); else - return map_rewrite(map, s, slen, NULL); + return map_rewrite(map, s, slen, av); } char * @@ -7194,7 +7242,11 @@ nsd_map_lookup(map, name, av, statp) *statp = EX_TEMPFAIL; return NULL; } - if (r == NS_BADREQ || r == NS_NOPERM) + if (r == NS_BADREQ +# ifdef NS_NOPERM + || r == NS_NOPERM +# endif /* NS_NOPERM */ + ) { *statp = EX_CONFIG; return NULL; diff --git a/contrib/sendmail/src/mci.c b/contrib/sendmail/src/mci.c index 073c6bd..198a18b 100644 --- a/contrib/sendmail/src/mci.c +++ b/contrib/sendmail/src/mci.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: mci.c,v 8.133.10.7 2000/12/12 00:39:34 ca Exp $"; +static char id[] = "@(#)$Id: mci.c,v 8.133.10.8 2001/05/03 17:24:10 gshapiro Exp $"; #endif /* ! lint */ #include <sendmail.h> @@ -422,7 +422,7 @@ mci_setstat(mci, xstat, dstat, rstat) mci->mci_status = dstat; if (mci->mci_rstatus != NULL) - free(mci->mci_rstatus); + sm_free(mci->mci_rstatus); if (rstat != NULL) rstat = newstr(rstat); mci->mci_rstatus = rstat; @@ -807,7 +807,7 @@ mci_read_persistent(fp, mci) mci->mci_status = NULL; if (mci->mci_rstatus != NULL) - free(mci->mci_rstatus); + sm_free(mci->mci_rstatus); mci->mci_rstatus = NULL; rewind(fp); @@ -1026,6 +1026,8 @@ mci_traverse_persistent(action, pathname) sizeof newpath - (newptr - newpath)); + if (StopRequest) + stop_sendmail(); ret = mci_traverse_persistent(action, newpath); if (ret < 0) break; @@ -1126,6 +1128,9 @@ mci_print_persistent(pathname, hostname) if (hostname == NULL) return 0; + if (StopRequest) + stop_sendmail(); + if (!initflag) { initflag = TRUE; diff --git a/contrib/sendmail/src/milter.c b/contrib/sendmail/src/milter.c index 0698573..f4ce5b8 100644 --- a/contrib/sendmail/src/milter.c +++ b/contrib/sendmail/src/milter.c @@ -9,7 +9,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: milter.c,v 8.50.4.44 2001/01/23 19:43:57 gshapiro Exp $"; +static char id[] = "@(#)$Id: milter.c,v 8.50.4.46 2001/05/11 18:11:36 gshapiro Exp $"; #endif /* ! lint */ #if _FFR_MILTER @@ -62,7 +62,7 @@ static char *MilterEnvRcptMacros[MAXFILTERMACROS + 1]; !isascii(response[2]) || !isdigit(response[2])) \ { \ if (response != NULL) \ - free(response); \ + sm_free(response); \ response = newstr(default); \ } \ else \ @@ -74,7 +74,7 @@ static char *MilterEnvRcptMacros[MAXFILTERMACROS + 1]; { \ if (*ptr == '%' && *++ptr != '%') \ { \ - free(response); \ + sm_free(response); \ response = newstr(default); \ break; \ } \ @@ -354,7 +354,7 @@ milter_read(m, cmd, rlen, to, e) if (milter_sysread(m, buf, expl, to, e) == NULL) { - free(buf); + sm_free(buf); return NULL; } @@ -1007,12 +1007,12 @@ milter_open(m, parseonly, e) continue; } if (tTd(64, 5)) - dprintf("X%s: error connecting to filter\n", - m->mf_name); + dprintf("X%s: error connecting to filter: %s\n", + m->mf_name, errstring(save_errno)); if (LogLevel > 0) sm_syslog(LOG_ERR, e->e_id, - "X%s: error connecting to filter", - m->mf_name); + "X%s: error connecting to filter: %s", + m->mf_name, errstring(save_errno)); milter_error(m); # if _FFR_FREEHOSTENT && NETINET6 if (hp != NULL) @@ -1681,7 +1681,7 @@ milter_send_macros(m, macros, cmd, e) } (void) milter_write(m, SMFIC_MACRO, buf, s, m->mf_timeout[SMFTO_WRITE], e); - free(buf); + sm_free(buf); } /* @@ -1836,7 +1836,7 @@ milter_send_command(m, command, data, sz, e, state) if (*state != SMFIR_REPLYCODE && response != NULL) { - free(response); + sm_free(response); response = NULL; } return response; @@ -1970,7 +1970,7 @@ milter_negotiate(m, e) "milter_negotiate(%s): returned %c instead of %c", m->mf_name, rcmd, SMFIC_OPTNEG); if (response != NULL) - free(response); + sm_free(response); milter_error(m); return -1; } @@ -1986,7 +1986,7 @@ milter_negotiate(m, e) "milter_negotiate(%s): did not return valid info", m->mf_name); if (response != NULL) - free(response); + sm_free(response); milter_error(m); return -1; } @@ -2005,7 +2005,7 @@ milter_negotiate(m, e) "milter_negotiate(%s): did not return enough info", m->mf_name); if (response != NULL) - free(response); + sm_free(response); milter_error(m); return -1; } @@ -2014,7 +2014,7 @@ milter_negotiate(m, e) MILTER_LEN_BYTES); (void) memcpy((char *) &pflags, response + (MILTER_LEN_BYTES * 2), MILTER_LEN_BYTES); - free(response); + sm_free(response); response = NULL; m->mf_fvers = ntohl(fvers); @@ -2178,7 +2178,7 @@ milter_headers(m, e, state) /* send it over */ response = milter_send_command(m, SMFIC_HEADER, buf, s, e, state); - free(buf); + sm_free(buf); if (m->mf_state == SMFS_ERROR || m->mf_state == SMFS_DONE || *state != SMFIR_CONTINUE) @@ -2280,7 +2280,7 @@ milter_body(m, e, state) *state = SMFIR_TEMPFAIL; if (response != NULL) { - free(response); + sm_free(response); response = NULL; } } @@ -2522,7 +2522,7 @@ milter_changeheader(response, rlen, e) if (h != sysheader && h->h_value != NULL) { e->e_msgsize -= strlen(h->h_value); - free(h->h_value); + sm_free(h->h_value); } if (*val == '\0') @@ -2889,7 +2889,7 @@ milter_connect(hostname, addr, e, state) response = milter_command(SMFIC_CONNECT, buf, s, MilterConnectMacros, e, state); - free(buf); + sm_free(buf); /* ** If this message connection is done for, @@ -2916,7 +2916,7 @@ milter_connect(hostname, addr, e, state) *state = SMFIR_REJECT; if (response != NULL) { - free(response); + sm_free(response); response = NULL; } } @@ -3042,7 +3042,7 @@ milter_envfrom(args, e, state) /* send it over */ response = milter_command(SMFIC_MAIL, buf, s, MilterEnvFromMacros, e, state); - free(buf); + sm_free(buf); /* ** If filter rejects/discards a per message command, @@ -3106,7 +3106,7 @@ milter_envrcpt(args, e, state) /* send it over */ response = milter_command(SMFIC_RCPT, buf, s, MilterEnvRcptMacros, e, state); - free(buf); + sm_free(buf); return response; } /* @@ -3382,7 +3382,7 @@ milter_data(e, state) if (rcmd != SMFIR_REPLYCODE && response != NULL) { - free(response); + sm_free(response); response = NULL; } @@ -3414,7 +3414,7 @@ finishup: *state = SMFIR_TEMPFAIL; if (response != NULL) { - free(response); + sm_free(response); response = NULL; } } @@ -3446,7 +3446,7 @@ finishup: *state = SMFIR_TEMPFAIL; if (response != NULL) { - free(response); + sm_free(response); response = NULL; } } diff --git a/contrib/sendmail/src/parseaddr.c b/contrib/sendmail/src/parseaddr.c index 0a2d8ad..adbb8b1 100644 --- a/contrib/sendmail/src/parseaddr.c +++ b/contrib/sendmail/src/parseaddr.c @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: parseaddr.c,v 8.234.4.11 2001/02/14 04:07:27 gshapiro Exp $"; +static char id[] = "@(#)$Id: parseaddr.c,v 8.234.4.12 2001/05/03 17:24:11 gshapiro Exp $"; #endif /* ! lint */ #include <sendmail.h> @@ -1157,7 +1157,7 @@ rewrite(pvp, ruleset, reclevel, e) if ((size_t) trsize > pvpb1_size) { if (pvpb1 != NULL) - free(pvpb1); + sm_free(pvpb1); pvpb1 = (char **)xalloc(trsize); pvpb1_size = trsize; } @@ -1583,7 +1583,7 @@ map_lookup(smap, key, argvect, pstat, e) if (i > rwbuflen) { if (rwbuf != NULL) - free(rwbuf); + sm_free(rwbuf); rwbuflen = i; rwbuf = (char *) xalloc(rwbuflen); } @@ -2461,7 +2461,7 @@ maplocaluser(a, sendq, aliaslevel, e) if (tTd(29, 9)) dprintf("maplocaluser: address unchanged\n"); if (a1 != NULL) - free(a1); + sm_free(a1); return; } @@ -2808,7 +2808,7 @@ rscheck(rwset, p1, p2, e, rmcomm, cnt, logl, host) QuickAbort = saveQuickAbort; setstat(rstat); if (buf != buf0) - free(buf); + sm_free(buf); if (rstat != EX_OK && QuickAbort) longjmp(TopFrame, 2); diff --git a/contrib/sendmail/src/queue.c b/contrib/sendmail/src/queue.c index f94498e..6a66cf6 100644 --- a/contrib/sendmail/src/queue.c +++ b/contrib/sendmail/src/queue.c @@ -16,9 +16,9 @@ #ifndef lint # if QUEUE -static char id[] = "@(#)$Id: queue.c,v 8.343.4.44 2001/02/22 00:55:35 ca Exp $ (with queueing)"; +static char id[] = "@(#)$Id: queue.c,v 8.343.4.55 2001/05/03 23:37:11 gshapiro Exp $ (with queueing)"; # else /* QUEUE */ -static char id[] = "@(#)$Id: queue.c,v 8.343.4.44 2001/02/22 00:55:35 ca Exp $ (without queueing)"; +static char id[] = "@(#)$Id: queue.c,v 8.343.4.55 2001/05/03 23:37:11 gshapiro Exp $ (without queueing)"; # endif /* QUEUE */ #endif /* ! lint */ @@ -507,7 +507,7 @@ queueup(e, announce) fprintf(tfp, ".\n"); - if (fflush(tfp) < 0 || + if (fflush(tfp) != 0 || (SuperSafe && fsync(fileno(tfp)) < 0) || ferror(tfp)) { @@ -793,6 +793,12 @@ run_single_queue(queuedir, forkflag, verbose) return TRUE; } /* child -- clean up signals */ + + /* Reset global flags */ + RestartRequest = NULL; + ShutdownRequest = NULL; + PendingSignal = 0; + clrcontrol(); proc_list_clear(); @@ -801,8 +807,8 @@ run_single_queue(queuedir, forkflag, verbose) PROC_QUEUE_CHILD); (void) releasesignal(SIGCHLD); (void) setsignal(SIGCHLD, SIG_DFL); - (void) setsignal(SIGHUP, intsig); - + (void) setsignal(SIGHUP, SIG_DFL); + (void) setsignal(SIGTERM, intsig); } sm_setproctitle(TRUE, CurEnv, "running queue: %s", @@ -811,7 +817,7 @@ run_single_queue(queuedir, forkflag, verbose) if (LogLevel > 69 || tTd(63, 99)) sm_syslog(LOG_DEBUG, NOQID, "runqueue %s, pid=%d, forkflag=%d", - qid_printqueue(queuedir), getpid(), forkflag); + qid_printqueue(queuedir), (int) getpid(), forkflag); /* ** Release any resources used by the daemon code. @@ -953,10 +959,10 @@ run_single_queue(queuedir, forkflag, verbose) if (pid != 0) (void) waitfor(pid); } - free(w->w_name); + sm_free(w->w_name); if (w->w_host) - free(w->w_host); - free((char *) w); + sm_free(w->w_host); + sm_free((char *) w); } /* exit without the usual cleanup */ @@ -969,6 +975,16 @@ run_single_queue(queuedir, forkflag, verbose) /* ** RUNQUEUEEVENT -- stub for use in setevent +** +** Parameters: +** none. +** +** Returns: +** none. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. */ static void @@ -1061,10 +1077,10 @@ orderq(queuedir, doall) register WORK *nw = w->w_next; WorkQ = nw; - free(w->w_name); + sm_free(w->w_name); if (w->w_host != NULL) - free(w->w_host); - free((char *) w); + sm_free(w->w_host); + sm_free((char *) w); w = nw; } @@ -1312,9 +1328,9 @@ orderq(queuedir, doall) /* don't even bother sorting this job in */ if (tTd(41, 49)) dprintf("skipping %s (%x)\n", w->w_name, i); - free(w->w_name); + sm_free(w->w_name); if (w->w_host) - free(w->w_host); + sm_free(w->w_host); wn--; } } @@ -1415,7 +1431,7 @@ orderq(queuedir, doall) WorkQ = w; } if (WorkList != NULL) - free(WorkList); + sm_free(WorkList); WorkList = NULL; WorkListSize = 0; @@ -1464,8 +1480,8 @@ grow_wlist(queuedir) else { int newsize = WorkListSize + QUEUESEGSIZE; - WORK *newlist = (WORK *) realloc((char *)WorkList, - (unsigned)sizeof(WORK) * (newsize + 1)); + WORK *newlist = (WORK *) xrealloc((char *)WorkList, + (unsigned)sizeof(WORK) * (newsize + 1)); if (newlist != NULL) { @@ -1762,6 +1778,11 @@ dowork(queuedir, id, forkflag, requeueflag, e) ** can recover on interrupt. */ + /* Reset global flags */ + RestartRequest = NULL; + ShutdownRequest = NULL; + PendingSignal = 0; + /* set basic modes, etc. */ (void) alarm(0); clearstats(); @@ -1782,7 +1803,7 @@ dowork(queuedir, id, forkflag, requeueflag, e) if (LogLevel > 76) sm_syslog(LOG_DEBUG, e->e_id, "dowork, pid=%d", - getpid()); + (int) getpid()); /* don't use the headers from sendmail.cf... */ e->e_header = NULL; @@ -1838,7 +1859,7 @@ readqf(e) { register FILE *qfp; ADDRESS *ctladdr; - struct stat st; + struct stat st, stf; char *bp; int qfver = 0; long hdrsize = 0; @@ -1883,19 +1904,59 @@ readqf(e) } /* - ** Check the queue file for plausibility to avoid attacks. + ** Prevent locking race condition. + ** + ** Process A: readqf(): qfp = fopen(qffile) + ** Process B: queueup(): rename(tf, qf) + ** Process B: unlocks(tf) + ** Process A: lockfile(qf); + ** + ** Process A (us) has the old qf file (before the rename deleted + ** the directory entry) and will be delivering based on old data. + ** This can lead to multiple deliveries of the same recipients. + ** + ** Catch this by checking if the underlying qf file has changed + ** *after* acquiring our lock and if so, act as though the file + ** was still locked (i.e., just return like the lockfile() case + ** above. */ - if (fstat(fileno(qfp), &st) < 0) + if (stat(qf, &stf) < 0 || + fstat(fileno(qfp), &st) < 0) { /* must have been being processed by someone else */ if (tTd(40, 8)) - dprintf("readqf(%s): fstat failure (%s)\n", + dprintf("readqf(%s): [f]stat failure (%s)\n", qf, errstring(errno)); (void) fclose(qfp); return FALSE; } + if (st.st_nlink != stf.st_nlink || + st.st_dev != stf.st_dev || + st.st_ino != stf.st_ino || +# if HAS_ST_GEN && 0 /* AFS returns garbage in st_gen */ + st.st_gen != stf.st_gen || +# endif /* HAS_ST_GEN && 0 */ + st.st_uid != stf.st_uid || + st.st_gid != stf.st_gid || + st.st_size != stf.st_size) + { + /* changed after opened */ + if (Verbose) + printf("%s: changed\n", e->e_id); + if (tTd(40, 8)) + dprintf("%s: changed\n", e->e_id); + if (LogLevel > 19) + sm_syslog(LOG_DEBUG, e->e_id, "changed"); + (void) fclose(qfp); + return FALSE; + } + + /* + ** Check the queue file for plausibility to avoid attacks. + */ + qsafe = S_IWOTH|S_IWGRP; #if _FFR_QUEUE_FILE_MODE if (bitset(S_IWGRP, QueueFileMode)) @@ -2243,7 +2304,7 @@ readqf(e) } if (bp != buf) - free(bp); + sm_free(bp); } /* @@ -2351,7 +2412,11 @@ printqueue() int i, nrequests = 0; for (i = 0; i < NumQueues; i++) + { + if (StopRequest) + stop_sendmail(); nrequests += print_single_queue(i); + } if (NumQueues > 1) printf("\t\tTotal Requests: %d\n", nrequests); } @@ -2467,6 +2532,9 @@ print_single_queue(queuedir) char bodytype[MAXNAME + 1]; char qf[MAXPATHLEN]; + if (StopRequest) + stop_sendmail(); + printf("%12s", w->w_name + 2); (void) snprintf(qf, sizeof qf, "%s/%s", qd, w->w_name); f = fopen(qf, "r"); @@ -2499,6 +2567,9 @@ print_single_queue(queuedir) register int i; register char *p; + if (StopRequest) + stop_sendmail(); + fixcrlf(buf, TRUE); switch (buf[0]) { @@ -2680,7 +2751,8 @@ queuename(e, type) ** none. */ -static char Base60Code[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx"; +static const char QueueIdChars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx"; +# define QIC_LEN 60 void assign_queueid(e) @@ -2696,7 +2768,7 @@ assign_queueid(e) return; /* see if we need to get a new base time/pid */ - if (cX >= 60 || LastQueueTime == 0 || LastQueuePid != pid) + if (cX >= QIC_LEN || LastQueueTime == 0 || LastQueuePid != pid) { time_t then = LastQueueTime; @@ -2714,16 +2786,16 @@ assign_queueid(e) } if (tTd(7, 50)) dprintf("assign_queueid: random_offset = %ld (%d)\n", - random_offset, (int)(cX + random_offset) % 60); + random_offset, (int)(cX + random_offset) % QIC_LEN); tm = gmtime(&LastQueueTime); - idbuf[0] = Base60Code[tm->tm_year % 60]; - idbuf[1] = Base60Code[tm->tm_mon]; - idbuf[2] = Base60Code[tm->tm_mday]; - idbuf[3] = Base60Code[tm->tm_hour]; - idbuf[4] = Base60Code[tm->tm_min]; - idbuf[5] = Base60Code[tm->tm_sec]; - idbuf[6] = Base60Code[((int)cX++ + random_offset) % 60]; + idbuf[0] = QueueIdChars[tm->tm_year % QIC_LEN]; + idbuf[1] = QueueIdChars[tm->tm_mon]; + idbuf[2] = QueueIdChars[tm->tm_mday]; + idbuf[3] = QueueIdChars[tm->tm_hour]; + idbuf[4] = QueueIdChars[tm->tm_min]; + idbuf[5] = QueueIdChars[tm->tm_sec]; + idbuf[6] = QueueIdChars[((int)cX++ + random_offset) % QIC_LEN]; (void) snprintf(&idbuf[7], sizeof idbuf - 7, "%05d", (int) LastQueuePid); e->e_id = newstr(idbuf); @@ -3056,7 +3128,7 @@ chkqdir(name, sff) /* skip over . and .. directories */ if (name[0] == '.' && - (name[1] == '\0' || (name[2] == '.' && name[3] == '\0'))) + (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) return FALSE; # if HASLSTAT if (lstat(name, &statb) < 0) @@ -3137,9 +3209,9 @@ multiqueue_cache() for (i = 0; i < NumQueues; i++) { if (QPaths[i].qp_name != NULL) - (void) free(QPaths[i].qp_name); + sm_free(QPaths[i].qp_name); } - (void) free((char *)QPaths); + sm_free((char *)QPaths); QPaths = NULL; NumQueues = 0; } @@ -3232,9 +3304,9 @@ multiqueue_cache() } else if (slotsleft < 1) { - QPaths = (QPATHS *)realloc((char *)QPaths, - (sizeof *QPaths) * - (NumQueues + 10)); + QPaths = (QPATHS *)xrealloc((char *)QPaths, + (sizeof *QPaths) * + (NumQueues + 10)); if (QPaths == NULL) { (void) closedir(dp); diff --git a/contrib/sendmail/src/readcf.c b/contrib/sendmail/src/readcf.c index fa99423..f8aefd1 100644 --- a/contrib/sendmail/src/readcf.c +++ b/contrib/sendmail/src/readcf.c @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: readcf.c,v 8.382.4.38 2001/02/17 00:05:12 geir Exp $"; +static char id[] = "@(#)$Id: readcf.c,v 8.382.4.40 2001/05/03 17:24:13 gshapiro Exp $"; #endif /* ! lint */ #include <sendmail.h> @@ -148,7 +148,7 @@ readcf(cfname, safe, e) if (bp[0] == '#') { if (bp != buf) - free(bp); + sm_free(bp); continue; } @@ -545,7 +545,7 @@ readcf(cfname, safe, e) syserr("unknown configuration line \"%s\"", bp); } if (bp != buf) - free(bp); + sm_free(bp); } if (ferror(cf)) { @@ -1269,7 +1269,7 @@ makemailer(line) if (s->s_mailer != NULL) { i = s->s_mailer->m_mno; - free(s->s_mailer); + sm_free(s->s_mailer); } else { @@ -1548,9 +1548,7 @@ static struct optioninfo { "RemoteMode", '>', OI_NONE }, #endif /* defined(SUN_EXTENSIONS) && defined(REMOTE_MODE) */ { "SevenBitInput", '7', OI_SAFE }, -#if MIME8TO7 { "EightBitMode", '8', OI_SAFE }, -#endif /* MIME8TO7 */ { "AliasFile", 'A', OI_NONE }, { "AliasWait", 'a', OI_NONE }, { "BlankSub", 'B', OI_NONE }, @@ -1898,8 +1896,8 @@ setoption(opt, val, safe, sticky, e) SevenBitInput = atobool(val); break; -#if MIME8TO7 case '8': /* handling of 8-bit input */ +#if MIME8TO7 switch (*val) { case 'm': /* convert 8-bit, convert MIME */ @@ -1936,8 +1934,10 @@ setoption(opt, val, safe, sticky, e) syserr("Unknown 8-bit mode %c", *val); finis(FALSE, EX_USAGE); } - break; +#else /* MIME8TO7 */ + printf("Warning: Option EightBitMode requires MIME8TO7 support\n"); #endif /* MIME8TO7 */ + break; case 'A': /* set default alias file */ if (val[0] == '\0') @@ -2641,7 +2641,7 @@ setoption(opt, val, safe, sticky, e) case O_PIDFILE: if (PidFile != NULL) - free(PidFile); + sm_free(PidFile); PidFile = newstr(val); break; @@ -2688,7 +2688,7 @@ setoption(opt, val, safe, sticky, e) case O_DEADLETTER: if (DeadLetterDrop != NULL) - free(DeadLetterDrop); + sm_free(DeadLetterDrop); DeadLetterDrop = newstr(val); break; @@ -2778,7 +2778,7 @@ setoption(opt, val, safe, sticky, e) case O_CONTROLSOCKET: if (ControlSocketName != NULL) - free(ControlSocketName); + sm_free(ControlSocketName); ControlSocketName = newstr(val); break; @@ -2792,7 +2792,7 @@ setoption(opt, val, safe, sticky, e) case O_PROCTITLEPREFIX: if (ProcTitlePrefix != NULL) - free(ProcTitlePrefix); + sm_free(ProcTitlePrefix); ProcTitlePrefix = newstr(val); break; @@ -2818,13 +2818,13 @@ setoption(opt, val, safe, sticky, e) } #endif /* _FFR_ALLOW_SASLINFO */ if (SASLInfo != NULL) - free(SASLInfo); + sm_free(SASLInfo); SASLInfo = newstr(val); break; case O_SASLMECH: if (AuthMechanisms != NULL) - free(AuthMechanisms); + sm_free(AuthMechanisms); if (*val != '\0') AuthMechanisms = newstr(val); else @@ -2886,63 +2886,63 @@ setoption(opt, val, safe, sticky, e) #if STARTTLS case O_SRVCERTFILE: if (SrvCERTfile != NULL) - free(SrvCERTfile); + sm_free(SrvCERTfile); SrvCERTfile = newstr(val); break; case O_SRVKEYFILE: if (Srvkeyfile != NULL) - free(Srvkeyfile); + sm_free(Srvkeyfile); Srvkeyfile = newstr(val); break; case O_CLTCERTFILE: if (CltCERTfile != NULL) - free(CltCERTfile); + sm_free(CltCERTfile); CltCERTfile = newstr(val); break; case O_CLTKEYFILE: if (Cltkeyfile != NULL) - free(Cltkeyfile); + sm_free(Cltkeyfile); Cltkeyfile = newstr(val); break; case O_CACERTFILE: if (CACERTfile != NULL) - free(CACERTfile); + sm_free(CACERTfile); CACERTfile = newstr(val); break; case O_CACERTPATH: if (CACERTpath != NULL) - free(CACERTpath); + sm_free(CACERTpath); CACERTpath = newstr(val); break; case O_DHPARAMS: if (DHParams != NULL) - free(DHParams); + sm_free(DHParams); DHParams = newstr(val); break; # if _FFR_TLS_1 case O_DHPARAMS5: if (DHParams5 != NULL) - free(DHParams5); + sm_free(DHParams5); DHParams5 = newstr(val); break; case O_CIPHERLIST: if (CipherList != NULL) - free(CipherList); + sm_free(CipherList); CipherList = newstr(val); break; # endif /* _FFR_TLS_1 */ case O_RANDFILE: if (RandFile != NULL) - free(RandFile); + sm_free(RandFile); RandFile= newstr(val); break; @@ -3272,7 +3272,7 @@ strtorwset(p, endp, stabmode) char *h = NULL; if (RuleSetNames[ruleset] != NULL) - free(RuleSetNames[ruleset]); + sm_free(RuleSetNames[ruleset]); if (delim != '\0' && (h = strchr(q, delim)) != NULL) *h = '\0'; RuleSetNames[ruleset] = newstr(q); diff --git a/contrib/sendmail/src/recipient.c b/contrib/sendmail/src/recipient.c index 258e7e2..bfed632 100644 --- a/contrib/sendmail/src/recipient.c +++ b/contrib/sendmail/src/recipient.c @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: recipient.c,v 8.231.14.10 2001/02/14 04:07:30 gshapiro Exp $"; +static char id[] = "@(#)$Id: recipient.c,v 8.231.14.11 2001/05/03 17:24:14 gshapiro Exp $"; #endif /* ! lint */ #include <sendmail.h> @@ -185,7 +185,7 @@ sendtolist(list, ctladdr, sendq, aliaslevel, e) e->e_to = oldto; if (bufp != buf) - free(bufp); + sm_free(bufp); #if _FFR_ADDR_TYPE define(macid("{addr_type}", NULL), NULL, e); #endif /* _FFR_ADDR_TYPE */ @@ -293,7 +293,7 @@ removefromlist(list, sendq, e) e->e_to = oldto; if (bufp != buf) - free(bufp); + sm_free(bufp); #if _FFR_ADDR_TYPE define(macid("{addr_type}", NULL), NULL, e); #endif /* _FFR_ADDR_TYPE */ @@ -780,7 +780,7 @@ recipient(a, sendq, aliaslevel, e) done: a->q_flags |= QTHISPASS; if (buf != buf0) - free(buf); + sm_free(buf); /* ** If we are at the top level, check to see if this has @@ -1573,6 +1573,13 @@ resetuid: static void includetimeout() { + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + + errno = ETIMEDOUT; longjmp(CtxIncludeTimeout, 1); } /* diff --git a/contrib/sendmail/src/savemail.c b/contrib/sendmail/src/savemail.c index 101dc71..fb7f8fd 100644 --- a/contrib/sendmail/src/savemail.c +++ b/contrib/sendmail/src/savemail.c @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: savemail.c,v 8.212.4.12 2001/01/07 19:31:05 gshapiro Exp $"; +static char id[] = "@(#)$Id: savemail.c,v 8.212.4.13 2001/05/03 17:24:15 gshapiro Exp $"; #endif /* ! lint */ #include <sendmail.h> @@ -1413,7 +1413,7 @@ xtextify(t, taboo) if (l > bplen) { if (bp != NULL) - free(bp); + sm_free(bp); bp = xalloc(l); bplen = l; } @@ -1466,7 +1466,7 @@ xuntextify(t) if (l > bplen) { if (bp != NULL) - free(bp); + sm_free(bp); bp = xalloc(l); bplen = l; } diff --git a/contrib/sendmail/src/sendmail.h b/contrib/sendmail/src/sendmail.h index ffb0b33..17f379f 100644 --- a/contrib/sendmail/src/sendmail.h +++ b/contrib/sendmail/src/sendmail.h @@ -20,7 +20,7 @@ #ifdef _DEFINE # define EXTERN # ifndef lint -static char SmailId[] = "@(#)$Id: sendmail.h,v 8.517.4.50 2001/02/22 18:56:24 gshapiro Exp $"; +static char SmailId[] = "@(#)$Id: sendmail.h,v 8.517.4.64 2001/05/23 17:49:13 ca Exp $"; # endif /* ! lint */ #else /* _DEFINE */ # define EXTERN extern @@ -881,6 +881,7 @@ MAP #define MF_DEFER 0x00080000 /* don't lookup map in defer mode */ #define MF_SINGLEMATCH 0x00100000 /* successful only if match one key */ #define MF_NOREWRITE 0x00200000 /* don't rewrite result, return as-is */ +#define MF_CLOSING 0x00400000 /* map is being closed */ #define DYNOPENMAP(map) if (!bitset(MF_OPEN, (map)->map_mflags)) \ { \ @@ -969,6 +970,9 @@ struct ldapmap_struct /* args for ldap_result */ struct timeval ldap_timeout; LDAPMessage *ldap_res; + + /* Linked list of maps sharing the same LDAP binding */ + MAP *ldap_next; }; typedef struct ldapmap_struct LDAPMAP_STRUCT; @@ -1076,7 +1080,7 @@ struct symtab struct hdrinfo sv_header; /* header metainfo */ char *sv_service[MAXMAPSTACK]; /* service switch */ #ifdef LDAPMAP - LDAP *sv_ldap; /* LDAP connection */ + MAP *sv_lmap; /* Maps for LDAP connection */ #endif /* LDAPMAP */ #if _FFR_MILTER struct milter *sv_milter; /* milter filter name */ @@ -1101,7 +1105,7 @@ typedef struct symtab STAB; #define ST_SERVICE 11 /* service switch entry */ #define ST_HEADER 12 /* special header flags */ #ifdef LDAPMAP -# define ST_LDAP 13 /* LDAP connection */ +# define ST_LMAP 13 /* List head of maps for LDAP connection */ #endif /* LDAPMAP */ #if _FFR_MILTER # define ST_MILTER 14 /* milter filter */ @@ -1122,7 +1126,7 @@ typedef struct symtab STAB; #define s_service s_value.sv_service #define s_header s_value.sv_header #ifdef LDAPMAP -# define s_ldap s_value.sv_ldap +# define s_lmap s_value.sv_lmap #endif /* LDAPMAP */ #if _FFR_MILTER # define s_milter s_value.sv_milter @@ -1151,7 +1155,7 @@ struct event void (*ev_func)__P((int)); /* function to call */ int ev_arg; /* argument to ev_func */ - int ev_pid; /* pid that set this event */ + pid_t ev_pid; /* pid that set this event */ struct event *ev_link; /* link to next item */ }; @@ -1161,6 +1165,7 @@ typedef struct event EVENT; extern void clrevent __P((EVENT *)); extern void clear_events __P((void)); extern EVENT *setevent __P((time_t, void(*)(), int)); +extern EVENT *sigsafe_setevent __P((time_t, void(*)(), int)); /* ** Operation, send, error, and MIME modes @@ -1626,6 +1631,51 @@ extern void inittimeouts __P((char *, bool)); /* variables */ extern u_char tTdvect[100]; /* trace vector */ /* +** Critical signal sections +*/ + +#define PEND_SIGHUP 0x0001 +#define PEND_SIGINT 0x0002 +#define PEND_SIGTERM 0x0004 +#define PEND_SIGUSR1 0x0008 + +#define ENTER_CRITICAL() InCriticalSection++ + +#define LEAVE_CRITICAL() \ +do \ +{ \ + if (InCriticalSection > 0) \ + InCriticalSection--; \ +} while (0) + +#define CHECK_CRITICAL(sig) \ +{ \ + if (InCriticalSection > 0 && (sig) != 0) \ + { \ + pend_signal((sig)); \ + return SIGFUNC_RETURN; \ + } \ +} + +/* reset signal in case System V semantics */ +#ifdef SYS5SIGNALS +# define FIX_SYSV_SIGNAL(sig, handler) \ +{ \ + if ((sig) != 0) \ + (void) setsignal((sig), (handler)); \ +} +#else /* SYS5SIGNALS */ +# define FIX_SYSV_SIGNAL(sig, handler) { /* EMPTY */ } +#endif /* SYS5SIGNALS */ + +/* variables */ +EXTERN u_int volatile InCriticalSection; /* >0 if in a critical section */ +EXTERN int volatile PendingSignal; /* pending signal to resend */ + +/* functions */ +extern void pend_signal __P((int)); + +/* ** Miscellaneous information. */ @@ -1662,9 +1712,9 @@ EXTERN bool CheckAliases; /* parse addresses during newaliases */ EXTERN bool ChownAlwaysSafe; /* treat chown(2) as safe */ EXTERN bool ColonOkInAddr; /* single colon legal in address */ EXTERN bool ConfigFileRead; /* configuration file has been read */ -EXTERN bool DataProgress; /* have we sent anything since last check */ +EXTERN bool volatile DataProgress; /* have we sent anything since last check */ EXTERN bool DisConnected; /* running with OutChannel redirected to xf */ -EXTERN bool DoQueueRun; /* non-interrupt time queue run needed */ +EXTERN bool volatile DoQueueRun; /* non-interrupt time queue run needed */ EXTERN bool DontExpandCnames; /* do not $[...$] expand CNAMEs */ EXTERN bool DontInitGroups; /* avoid initgroups() because of NIS cost */ EXTERN bool DontLockReadFiles; /* don't read lock support files */ @@ -1693,6 +1743,7 @@ EXTERN bool SendMIMEErrors; /* send error messages in MIME format */ EXTERN bool SevenBitInput; /* force 7-bit data on input */ EXTERN bool SingleLineFromHeader; /* force From: header to be one line */ EXTERN bool SingleThreadDelivery; /* single thread hosts on delivery */ +EXTERN bool volatile StopRequest; /* stop sending output */ EXTERN bool SuperSafe; /* be extra careful, even if expensive */ EXTERN bool SuprErrs; /* set if we are suppressing errors */ EXTERN bool TryNullMXList; /* if we are the best MX, try host directly */ @@ -1708,7 +1759,7 @@ EXTERN char SpaceSub; /* substitution for <lwsp> */ EXTERN int CheckpointInterval; /* queue file checkpoint interval */ EXTERN int ConfigLevel; /* config file level */ EXTERN int ConnRateThrottle; /* throttle for SMTP connection rate */ -EXTERN int CurChildren; /* current number of daemonic children */ +EXTERN int volatile CurChildren; /* current number of daemonic children */ EXTERN int CurrentLA; /* current load average */ EXTERN int DefaultNotify; /* default DSN notification flags */ EXTERN int Errors; /* set if errors (local to single pass) */ @@ -1813,9 +1864,11 @@ EXTERN time_t QueueMaxDelay; /* maximum queue delay */ #endif /* _FFR_QUEUEDELAY */ EXTERN char *RealHostName; /* name of host we are talking to */ EXTERN char *RealUserName; /* real user name of caller */ +EXTERN char *volatile RestartRequest;/* a sendmail restart has been requested */ EXTERN char *RunAsUserName; /* user to become for bulk of run */ EXTERN char *SafeFileEnv; /* chroot location for file delivery */ EXTERN char *ServiceSwitchFile; /* backup service switch */ +EXTERN char *volatile ShutdownRequest;/* a sendmail shutdown has been requested */ EXTERN char *SmtpGreeting; /* SMTP greeting message (old $e macro) */ EXTERN char *SmtpPhase; /* current phase in SMTP processing */ EXTERN char SmtpError[MAXLINE]; /* save failure error messages */ @@ -1825,6 +1878,7 @@ EXTERN char *UdbSpec; /* user database source spec */ EXTERN char *UnixFromLine; /* UNIX From_ line (old $l macro) */ EXTERN char **ExternalEnviron; /* input environment */ /* saved user environment */ +EXTERN char **SaveArgv; /* argument vector for re-execing */ EXTERN BITMAP256 DontBlameSendmail; /* DontBlameSendmail bits */ #if SFIO EXTERN Sfio_t *InChannel; /* input connection */ @@ -1838,7 +1892,6 @@ EXTERN FILE *TrafficLogFile; /* file in which to log all traffic */ EXTERN void *HesiodContext; #endif /* HESIOD */ EXTERN ENVELOPE *CurEnv; /* envelope currently being processed */ -EXTERN EVENT *EventQueue; /* head of event queue */ EXTERN MAILER *LocalMailer; /* ptr to local mailer */ EXTERN MAILER *ProgMailer; /* ptr to program mailer */ EXTERN MAILER *FileMailer; /* ptr to *file* mailer */ @@ -1876,6 +1929,7 @@ extern int sasl_encode64 __P((const char *, unsigned, char *, unsigned, unsigned #if STARTTLS extern void apps_ssl_info_cb __P((SSL *, int , int)); +extern bool init_tls_library __P((void)); extern bool inittls __P((SSL_CTX **, u_long, bool, char *, char *, char *, char *, char *)); extern bool initclttls __P((void)); extern bool initsrvtls __P((void)); @@ -1972,6 +2026,7 @@ extern char *milter_data __P((ENVELOPE *, char *)); #endif /* _FFR_MILTER */ extern char *addquotes __P((char *)); +extern void allsignals __P((bool)); extern char *arpadate __P((char *)); extern bool atobool __P((char *)); extern int atooct __P((char *)); @@ -1998,7 +2053,7 @@ extern char *defcharset __P((ENVELOPE *)); extern char *denlstring __P((char *, bool, bool)); extern void disconnect __P((int, ENVELOPE *)); extern bool dns_getcanonname __P((char *, int, bool, int *)); -extern int dofork __P((void)); +extern pid_t dofork __P((void)); extern int drop_privileges __P((bool)); extern int dsntoexitstat __P((char *)); extern void dumpfd __P((int, bool, bool)); @@ -2012,6 +2067,11 @@ extern struct passwd *finduser __P((char *, bool *)); extern void finis __P((bool, volatile int)); extern void fixcrlf __P((char *, bool)); extern long freediskspace __P((char *, long *)); +#if NETINET6 && NEEDSGETIPNODE +# if _FFR_FREEHOSTENT +extern void freehostent __P((struct hostent *)); +# endif /* _FFR_FREEHOSTENT */ +#endif /* NEEDSGETIPNODE && NETINET6 */ extern char *get_column __P((char *, int, int, char *, int)); extern char *getauthinfo __P((int, bool *)); extern char *getcfname __P((void)); @@ -2026,7 +2086,6 @@ extern void inithostmaps __P((void)); extern void initmacros __P((ENVELOPE *)); extern void initsetproctitle __P((int, char **, char **)); extern void init_vendor_macros __P((ENVELOPE *)); -extern SIGFUNC_DECL intindebug __P((int)); extern SIGFUNC_DECL intsig __P((int)); extern bool isloopback __P((SOCKADDR sa)); extern void load_if_names __P((void)); @@ -2046,11 +2105,10 @@ extern void printmailer __P((MAILER *)); extern void printopenfds __P((bool)); extern void printqueue __P((void)); extern void printrules __P((void)); -extern int prog_open __P((char **, int *, ENVELOPE *)); +extern pid_t prog_open __P((char **, int *, ENVELOPE *)); extern void putline __P((char *, MCI *)); extern void putxline __P((char *, size_t, MCI *, int)); extern void queueup_macros __P((int, FILE *, ENVELOPE *)); -extern SIGFUNC_DECL quiesce __P((int)); extern void readcf __P((char *, bool, ENVELOPE *)); extern SIGFUNC_DECL reapchild __P((int)); extern int releasesignal __P((int)); @@ -2072,9 +2130,9 @@ extern char *sfgets __P((char *, int, FILE *, time_t, char *)); extern char *shortenstring __P((const char *, int)); extern char *shorten_hostname __P((char [])); extern bool shorten_rfc822_string __P((char *, size_t)); -extern SIGFUNC_DECL sigusr1 __P((int)); -extern SIGFUNC_DECL sighup __P((int)); +extern void shutdown_daemon __P((void)); extern void sm_dopr __P((char *, const char *, va_list)); +extern void sm_free __P((void *)); extern struct hostent *sm_gethostbyname __P((char *, int)); extern struct hostent *sm_gethostbyaddr __P((char *, int, int)); extern int sm_getla __P((ENVELOPE *)); @@ -2082,13 +2140,13 @@ extern struct passwd *sm_getpwnam __P((char *)); extern struct passwd *sm_getpwuid __P((UID_T)); extern void sm_setproctitle __P((bool, ENVELOPE *, const char *, ...)); extern int sm_strcasecmp __P((const char *, const char *)); +extern void stop_sendmail __P((void)); extern bool strcontainedin __P((char *, char *)); extern void stripquotes __P((char *)); extern int switch_map_find __P((char *, char *[], short [])); extern bool transienterror __P((int)); extern void tTflag __P((char *)); extern void tTsetup __P((u_char *, int, char *)); -extern SIGFUNC_DECL tick __P((int)); extern char *ttypath __P((void)); extern void unlockqueue __P((ENVELOPE *)); #if !HASUNSETENV @@ -2101,6 +2159,8 @@ extern void vendor_pre_defaults __P((ENVELOPE *)); extern int waitfor __P((pid_t)); extern bool writable __P((char *, ADDRESS *, long)); extern char *xalloc __P((int)); +extern char *xcalloc __P((size_t, size_t)); +extern char *xrealloc __P((void *, size_t)); extern void xputs __P((const char *)); extern char *xtextify __P((char *, char *)); extern bool xtextok __P((char *)); diff --git a/contrib/sendmail/src/sfsasl.c b/contrib/sendmail/src/sfsasl.c index c09e4e8..17e90be 100644 --- a/contrib/sendmail/src/sfsasl.c +++ b/contrib/sendmail/src/sfsasl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set @@ -9,7 +9,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: sfsasl.c,v 8.17.4.13 2000/11/03 00:24:49 gshapiro Exp $"; +static char id[] = "@(#)$Id: sfsasl.c,v 8.17.4.14 2001/05/03 17:24:16 gshapiro Exp $"; #endif /* ! lint */ #if SFIO @@ -28,7 +28,7 @@ static char id[] = "@(#)$Id: sfsasl.c,v 8.17.4.13 2000/11/03 00:24:49 gshapiro E # include "sfsasl.h" /* how to deallocate a buffer allocated by SASL */ -# define SASL_DEALLOC(b) free(b) +# define SASL_DEALLOC(b) sm_free(b) static ssize_t sasl_read(f, buf, size, disc) @@ -134,14 +134,8 @@ sfdcsasl(fin, fout, conn) return 0; } - if ((saslin = (Sasldisc_t *) malloc(sizeof(Sasldisc_t))) == NULL) - return -1; - if ((saslout = (Sasldisc_t *) malloc(sizeof(Sasldisc_t))) == NULL) - { - free(saslin); - return -1; - } - + saslin = (Sasldisc_t *) xalloc(sizeof(Sasldisc_t)); + saslout = (Sasldisc_t *) xalloc(sizeof(Sasldisc_t)); saslin->disc.readf = sasl_read; saslin->disc.writef = sasl_write; saslin->disc.seekf = NULL; @@ -158,8 +152,8 @@ sfdcsasl(fin, fout, conn) if (sfdisc(fin, (Sfdisc_t *) saslin) != (Sfdisc_t *) saslin || sfdisc(fout, (Sfdisc_t *) saslout) != (Sfdisc_t *) saslout) { - free(saslin); - free(saslout); + sm_free(saslin); + sm_free(saslout); return -1; } return 0; @@ -310,7 +304,7 @@ tls_close(cookie) tc->fp = NULL; } - free(tc); + sm_free(tc); return retval; } # endif /* !SFIO */ @@ -336,14 +330,8 @@ sfdctls(fin, fout, con) if (con == NULL) return 0; - if ((tlsin = (Tlsdisc_t *) malloc(sizeof(Tlsdisc_t))) == NULL) - return -1; - if ((tlsout = (Tlsdisc_t *) malloc(sizeof(Tlsdisc_t))) == NULL) - { - free(tlsin); - return -1; - } - + tlsin = (Tlsdisc_t *) xalloc(sizeof(Tlsdisc_t)); + tlsout = (Tlsdisc_t *) xalloc(sizeof(Tlsdisc_t)); # if SFIO tlsin->disc.readf = tls_read; tlsin->disc.writef = tls_write; @@ -362,15 +350,15 @@ sfdctls(fin, fout, con) if (rfd < 0 || wfd < 0 || SSL_set_rfd(con, rfd) <= 0 || SSL_set_wfd(con, wfd) <= 0) { - free(tlsin); - free(tlsout); + sm_free(tlsin); + sm_free(tlsout); return -1; } if (sfdisc(fin, (Sfdisc_t *) tlsin) != (Sfdisc_t *) tlsin || sfdisc(fout, (Sfdisc_t *) tlsout) != (Sfdisc_t *) tlsout) { - free(tlsin); - free(tlsout); + sm_free(tlsin); + sm_free(tlsout); return -1; } # else /* SFIO */ @@ -379,7 +367,7 @@ sfdctls(fin, fout, con) fp = funopen(tlsin, tls_read, tls_write, NULL, tls_close); if (fp == NULL) { - free(tlsin); + sm_free(tlsin); return -1; } *fin = fp; @@ -396,7 +384,7 @@ sfdctls(fin, fout, con) tlsin->fp = NULL; fclose(*fin); *fin = save; - free(tlsout); + sm_free(tlsout); return -1; } *fout = fp; diff --git a/contrib/sendmail/src/srvrsmtp.c b/contrib/sendmail/src/srvrsmtp.c index 72d22c0..f655565 100644 --- a/contrib/sendmail/src/srvrsmtp.c +++ b/contrib/sendmail/src/srvrsmtp.c @@ -16,9 +16,9 @@ #ifndef lint # if SMTP -static char id[] = "@(#)$Id: srvrsmtp.c,v 8.471.2.2.2.67 2001/01/07 19:31:05 gshapiro Exp $ (with SMTP)"; +static char id[] = "@(#)$Id: srvrsmtp.c,v 8.471.2.2.2.77 2001/05/27 22:20:30 gshapiro Exp $ (with SMTP)"; # else /* SMTP */ -static char id[] = "@(#)$Id: srvrsmtp.c,v 8.471.2.2.2.67 2001/01/07 19:31:05 gshapiro Exp $ (without SMTP)"; +static char id[] = "@(#)$Id: srvrsmtp.c,v 8.471.2.2.2.77 2001/05/27 22:20:30 gshapiro Exp $ (without SMTP)"; # endif /* SMTP */ #endif /* ! lint */ @@ -44,7 +44,7 @@ static SSL_CTX *srv_ctx = NULL; # if !TLS_NO_RSA static RSA *rsa = NULL; # endif /* !TLS_NO_RSA */ -static bool tls_ok = FALSE; +static bool tls_ok_srv = FALSE; static int tls_verify_cb __P((X509_STORE_CTX *)); # if !TLS_NO_RSA # define RSA_KEYLENGTH 512 @@ -966,7 +966,7 @@ smtp(nullserver, d_flags, e) message("503 5.5.0 TLS not available"); break; } - if (!tls_ok) + if (!tls_ok_srv) { message("454 4.3.3 TLS not available after start"); break; @@ -1038,7 +1038,7 @@ smtp(nullserver, d_flags, e) if (LogLevel > 9) tlslogerr(); } - tls_ok = FALSE; + tls_ok_srv = FALSE; SSL_free(srv_ssl); srv_ssl = NULL; @@ -1080,7 +1080,7 @@ smtp(nullserver, d_flags, e) QuickAbort = saveQuickAbort; SuprErrs = saveSuprErrs; - tls_ok = FALSE; /* don't offer STARTTLS again */ + tls_ok_srv = FALSE; /* don't offer STARTTLS again */ gothello = FALSE; /* discard info */ n_helo = 0; OneXact = TRUE; /* only one xaction this run */ @@ -1100,7 +1100,7 @@ smtp(nullserver, d_flags, e) sasl_ok = sasl_setprop(conn, SASL_SSF_EXTERNAL, &ext_ssf) == SASL_OK; if (mechlist != NULL) - free(mechlist); + sm_free(mechlist); mechlist = NULL; if (sasl_ok) { @@ -1301,7 +1301,7 @@ smtp(nullserver, d_flags, e) message("250-AUTH %s", mechlist); # endif /* SASL */ # if STARTTLS - if (tls_ok && usetls) + if (tls_ok_srv && usetls) message("250-STARTTLS"); # endif /* STARTTLS */ message("250 HELP"); @@ -1525,7 +1525,8 @@ smtp(nullserver, d_flags, e) goto undo_subproc_no_pm; if (MaxMessageSize > 0 && - (e->e_msgsize > MaxMessageSize || e->e_msgsize < 0)) + (e->e_msgsize > MaxMessageSize || + e->e_msgsize < 0)) { usrerr("552 5.2.3 Message size exceeds fixed maximum message size (%ld)", MaxMessageSize); @@ -1567,7 +1568,7 @@ smtp(nullserver, d_flags, e) break; } if (response != NULL) - free(response); + sm_free(response); } # endif /* _FFR_MILTER */ if (Errors > 0) @@ -1745,7 +1746,7 @@ smtp(nullserver, d_flags, e) break; } if (response != NULL) - free(response); + sm_free(response); } # endif /* _FFR_MILTER */ @@ -1847,7 +1848,7 @@ smtp(nullserver, d_flags, e) break; } if (response != NULL) - free(response); + sm_free(response); } /* abort message filters that didn't get the body */ @@ -1858,7 +1859,7 @@ smtp(nullserver, d_flags, e) /* redefine message size */ if ((q = macvalue(macid("{msg_size}", NULL), e)) != NULL) - free(q); + sm_free(q); snprintf(inp, sizeof inp, "%ld", e->e_msgsize); define(macid("{msg_size}", NULL), newstr(inp), e); if (Errors > 0) @@ -2163,16 +2164,12 @@ smtp(nullserver, d_flags, e) else *--id = '@'; - if ((new = (QUEUE_CHAR *)malloc(sizeof(QUEUE_CHAR))) == NULL) - { - syserr("500 5.5.0 ETRN out of memory"); - break; - } + new = (QUEUE_CHAR *)xalloc(sizeof(QUEUE_CHAR)); new->queue_match = id; new->queue_next = NULL; QueueLimitRecipient = new; ok = runqueue(TRUE, FALSE); - free(QueueLimitRecipient); + sm_free(QueueLimitRecipient); QueueLimitRecipient = NULL; if (ok && Errors == 0) message("250 2.0.0 Queuing for node %s started", p); @@ -2357,8 +2354,8 @@ checksmtpattack(pcounter, maxcount, waitnow, cname, e) if (*pcounter == maxcount && LogLevel > 5) { sm_syslog(LOG_INFO, e->e_id, - "%.100s: %.40s attack?", - CurSmtpClient, cname); + "%.100s: possible SMTP attack: command=%.40s, count=%d", + CurSmtpClient, cname, *pcounter); } s = 1 << (*pcounter - maxcount); if (s >= MAXTIMEOUT) @@ -2604,7 +2601,8 @@ mail_esmtp_args(kp, vp, e) dprintf("auth=\"%.100s\" trusted\n", pbuf); e->e_auth_param = newstr(auth_param); } - free(auth_param); + sm_free(auth_param); + /* reset values */ Errors = 0; QuickAbort = saveQuickAbort; @@ -2848,6 +2846,12 @@ runinchild(label, e) /* child */ InChild = TRUE; QuickAbort = FALSE; + + /* Reset global flags */ + RestartRequest = NULL; + ShutdownRequest = NULL; + PendingSignal = 0; + clearstats(); clearenvelope(e, FALSE); assign_queueid(e); @@ -2992,7 +2996,6 @@ tls_rand_init(randfile, logl) { # ifndef HASURANDOMDEV /* not required if /dev/urandom exists, OpenSSL does it internally */ - #define RF_OK 0 /* randfile OK */ #define RF_MISS 1 /* randfile == NULL || *randfile == '\0' */ #define RF_UNKNOWN 2 /* unknown prefix for randfile */ @@ -3017,7 +3020,7 @@ tls_rand_init(randfile, logl) ok = FALSE; done = RI_FAIL; randdef = (randfile == NULL || *randfile == '\0') ? RF_MISS : RF_OK; -# if EGD +# if EGD if (randdef == RF_OK && strncasecmp(randfile, "egd:", 4) == 0) { randfile += 4; @@ -3031,7 +3034,7 @@ tls_rand_init(randfile, logl) ok = TRUE; } else -# endif /* EGD */ +# endif /* EGD */ if (randdef == RF_OK && strncasecmp(randfile, "file:", 5) == 0) { int fd; @@ -3288,7 +3291,39 @@ tls_safe_f(var, sff) else if (req) \ ok = FALSE; \ } +/* +** INIT_TLS_LIBRARY -- calls functions which setup TLS library for global use +** +** Parameters: +** none. +** +** Returns: +** succeeded? +** +** Side Effects: +** Sets tls_ok_srv static, even when called from main() +*/ + +bool +init_tls_library() +{ + /* + ** basic TLS initialization + ** ignore result for now + */ + + SSL_library_init(); + SSL_load_error_strings(); +# if 0 + /* this is currently a macro for SSL_library_init */ + SSLeay_add_ssl_algorithms(); +# endif /* 0 */ + + /* initialize PRNG */ + tls_ok_srv = tls_rand_init(RandFile, 7); + return tls_ok_srv; +} /* ** INITTLS -- initialize TLS ** @@ -3471,6 +3506,8 @@ inittls(ctx, req, srv, certfile, keyfile, cacertpath, cacertfile, dhparam) if (LogLevel > 7) sm_syslog(LOG_WARNING, NOQID, "TLS: error: SSL_CTX_new(SSLv23_server_method()) failed"); + if (LogLevel > 9) + tlslogerr(); return FALSE; } } @@ -3481,6 +3518,8 @@ inittls(ctx, req, srv, certfile, keyfile, cacertpath, cacertfile, dhparam) if (LogLevel > 7) sm_syslog(LOG_WARNING, NOQID, "TLS: error: SSL_CTX_new(SSLv23_client_method()) failed"); + if (LogLevel > 9) + tlslogerr(); return FALSE; } } @@ -3802,15 +3841,18 @@ inittls(ctx, req, srv, certfile, keyfile, cacertpath, cacertfile, dhparam) ** ** Returns: ** succeeded? +** +** Side Effects: +** sets tls_ok_srv static, even when called from main() */ bool initsrvtls() { - tls_ok = inittls(&srv_ctx, TLS_I_SRV, TRUE, SrvCERTfile, Srvkeyfile, - CACERTpath, CACERTfile, DHParams); - return tls_ok; + tls_ok_srv = inittls(&srv_ctx, TLS_I_SRV, TRUE, SrvCERTfile, + Srvkeyfile, CACERTpath, CACERTfile, DHParams); + return tls_ok_srv; } /* ** TLS_GET_INFO -- get information about TLS connection diff --git a/contrib/sendmail/src/stab.c b/contrib/sendmail/src/stab.c index 1249f9d..82775bc 100644 --- a/contrib/sendmail/src/stab.c +++ b/contrib/sendmail/src/stab.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: stab.c,v 8.40.16.3 2000/10/09 02:46:12 gshapiro Exp $"; +static char id[] = "@(#)$Id: stab.c,v 8.40.16.7 2001/05/07 22:06:41 gshapiro Exp $"; #endif /* ! lint */ #include <sendmail.h> @@ -160,8 +160,8 @@ stab(name, type, op) break; #ifdef LDAPMAP - case ST_LDAP: - len = sizeof s->s_ldap; + case ST_LMAP: + len = sizeof s->s_lmap; break; #endif /* LDAPMAP */ diff --git a/contrib/sendmail/src/udb.c b/contrib/sendmail/src/udb.c index 9b8ccd0..d835326 100644 --- a/contrib/sendmail/src/udb.c +++ b/contrib/sendmail/src/udb.c @@ -15,9 +15,9 @@ #ifndef lint # if USERDB -static char id[] = "@(#)$Id: udb.c,v 8.111.16.1 2001/01/04 18:18:37 gshapiro Exp $ (with USERDB)"; +static char id[] = "@(#)$Id: udb.c,v 8.111.16.2 2001/05/03 17:24:17 gshapiro Exp $ (with USERDB)"; # else /* USERDB */ -static char id[] = "@(#)$Id: udb.c,v 8.111.16.1 2001/01/04 18:18:37 gshapiro Exp $ (without USERDB)"; +static char id[] = "@(#)$Id: udb.c,v 8.111.16.2 2001/05/03 17:24:17 gshapiro Exp $ (without USERDB)"; # endif /* USERDB */ #endif /* ! lint */ @@ -290,7 +290,7 @@ udbexpand(a, sendq, aliaslevel, e) memmove(nuser, user, usersize); if (user != userbuf) - free(user); + sm_free(user); user = nuser; usersize += size; userleft += size; @@ -545,7 +545,7 @@ udbexpand(a, sendq, aliaslevel, e) break; } if (user != userbuf) - free(user); + sm_free(user); } return EX_OK; } @@ -1055,11 +1055,11 @@ _udbx_init(e) errstring(errno)); up->udb_type = UDB_EOLIST; if (up->udb_dbname != spec) - free(up->udb_dbname); + sm_free(up->udb_dbname); goto tempfail; } if (up->udb_dbname != spec) - free(up->udb_dbname); + sm_free(up->udb_dbname); break; } if (tTd(28, 1)) diff --git a/contrib/sendmail/src/usersmtp.c b/contrib/sendmail/src/usersmtp.c index 83034dc..a1aeac5 100644 --- a/contrib/sendmail/src/usersmtp.c +++ b/contrib/sendmail/src/usersmtp.c @@ -15,9 +15,9 @@ #ifndef lint # if SMTP -static char id[] = "@(#)$Id: usersmtp.c,v 8.245.4.24 2001/02/21 00:59:09 gshapiro Exp $ (with SMTP)"; +static char id[] = "@(#)$Id: usersmtp.c,v 8.245.4.33 2001/05/23 18:53:09 ca Exp $ (with SMTP)"; # else /* SMTP */ -static char id[] = "@(#)$Id: usersmtp.c,v 8.245.4.24 2001/02/21 00:59:09 gshapiro Exp $ (without SMTP)"; +static char id[] = "@(#)$Id: usersmtp.c,v 8.245.4.33 2001/05/23 18:53:09 ca Exp $ (without SMTP)"; # endif /* SMTP */ #endif /* ! lint */ @@ -199,7 +199,8 @@ tryhelo: { syserr("553 5.3.5 %s config error: mail loops back to me (MX problem?)", CurHostName); - mci_setstat(mci, EX_CONFIG, "5.3.5", "system config error"); + mci_setstat(mci, EX_CONFIG, "5.3.5", + "553 5.3.5 system config error"); mci->mci_errno = 0; smtpquit(m, mci, e); return; @@ -303,15 +304,9 @@ str_union(s1, s2) l1 = strlen(s1); l2 = strlen(s2); rl = l1 + l2; - res = (char *)malloc(rl + 2); - if (res == NULL) - { - if (l1 > l2) - return s1; - return s2; - } + res = (char *)xalloc(rl + 2); (void) strlcpy(res, s1, rl); - hr = res; + hr = res + l1; h1 = s2; h = s2; @@ -374,7 +369,7 @@ helo_options(line, firstline, m, mci, e) { # if SASL if (mci->mci_saslcap != NULL) - free(mci->mci_saslcap); + sm_free(mci->mci_saslcap); mci->mci_saslcap = NULL; # endif /* SASL */ return; @@ -424,7 +419,7 @@ helo_options(line, firstline, m, mci, e) h = mci->mci_saslcap; mci->mci_saslcap = str_union(h, p); if (h != mci->mci_saslcap) - free(h); + sm_free(h); mci->mci_flags |= MCIF_AUTH; } else @@ -432,14 +427,9 @@ helo_options(line, firstline, m, mci, e) int l; l = strlen(p) + 1; - mci->mci_saslcap = (char *)malloc(l); - - /* XXX this may be leaked */ - if (mci->mci_saslcap != NULL) - { - (void) strlcpy(mci->mci_saslcap, p, l); - mci->mci_flags |= MCIF_AUTH; - } + mci->mci_saslcap = (char *)xalloc(l); + (void) strlcpy(mci->mci_saslcap, p, l); + mci->mci_flags |= MCIF_AUTH; } } } @@ -501,7 +491,7 @@ getsasldata(line, firstline, m, mci, e) { if (mci->mci_sasl_string_len <= len) { - free(mci->mci_sasl_string); + sm_free(mci->mci_sasl_string); mci->mci_sasl_string = xalloc(len + 1); } } @@ -511,7 +501,7 @@ getsasldata(line, firstline, m, mci, e) memcpy(mci->mci_sasl_string, out, len); mci->mci_sasl_string[len] = '\0'; mci->mci_sasl_string_len = len; - free(out); + sm_free(out); return; } @@ -728,7 +718,8 @@ getsimple(context, id, result, len) ** workaround: don't free() it here ** this can cause a memory leak! */ - free(authid); + + sm_free(authid); # endif /* SASL > 10522 */ authid = NULL; addedrealm = addrealm; @@ -804,9 +795,7 @@ getsecret(conn, context, id, psecret) authpass = newstr(h); } len = strlen(authpass); - *psecret = (sasl_secret_t *) malloc(sizeof(sasl_secret_t) + len + 1); - if (*psecret == NULL) - return SASL_FAIL; + *psecret = (sasl_secret_t *) xalloc(sizeof(sasl_secret_t) + len + 1); (void) strlcpy((*psecret)->data, authpass, len + 1); (*psecret)->len = len; return SASL_OK; @@ -1057,9 +1046,7 @@ intersect(s1, s2) l1 = strlen(s1); l2 = strlen(s2); rl = min(l1, l2); - res = (char *)malloc(rl + 1); - if (res == NULL) - return NULL; + res = (char *)xalloc(rl + 1); *res = '\0'; if (rl == 0) /* at least one string empty? */ return res; @@ -1751,6 +1738,7 @@ smtprcpt(to, m, mci, e) */ static jmp_buf CtxDataTimeout; +static EVENT *volatile DataTimeout = NULL; int smtpdata(m, mci, e) @@ -1759,13 +1747,13 @@ smtpdata(m, mci, e) register ENVELOPE *e; { register int r; - register EVENT *ev; int rstat; int xstat; time_t timeout; char *enhsc; enhsc = NULL; + /* ** Send the data. ** First send the command and check that it is ok. @@ -1840,27 +1828,29 @@ smtpdata(m, mci, e) else timeout = DATA_PROGRESS_TIMEOUT; - ev = setevent(timeout, datatimeout, 0); + DataTimeout = setevent(timeout, datatimeout, 0); - if (tTd(18, 101)) - { - /* simulate a DATA timeout */ - (void) sleep(1); - } - /* ** Output the actual message. */ (*e->e_puthdr)(mci, e->e_header, e, M87F_OUTER); + + if (tTd(18, 101)) + { + /* simulate a DATA timeout */ + (void) sleep(2); + } + (*e->e_putbody)(mci, e, NULL); /* ** Cleanup after sending message. */ - clrevent(ev); + if (DataTimeout != NULL) + clrevent(DataTimeout); # if _FFR_CATCH_BROKEN_MTAS { @@ -1938,7 +1928,7 @@ smtpdata(m, mci, e) mci_setstat(mci, xstat, ENHSCN(enhsc, smtptodsn(r)), SmtpReplyBuffer); if (e->e_statmsg != NULL) - free(e->e_statmsg); + sm_free(e->e_statmsg); if (bitset(MCIF_ENHSTAT, mci->mci_flags) && (r = isenhsc(SmtpReplyBuffer + 4, ' ')) > 0) r += 5; @@ -1963,10 +1953,17 @@ smtpdata(m, mci, e) static void datatimeout() { + int save_errno = errno; + + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + if (DataProgress) { time_t timeout; - register EVENT *ev; /* check back again later */ if (tTd(18, 101)) @@ -1977,14 +1974,24 @@ datatimeout() else timeout = DATA_PROGRESS_TIMEOUT; + /* reset the timeout */ + DataTimeout = sigsafe_setevent(timeout, datatimeout, 0); DataProgress = FALSE; - ev = setevent(timeout, datatimeout, 0); } else { - /* no progress, give up */ + /* event is done */ + DataTimeout = NULL; + } + + /* if no progress was made or problem resetting event, die now */ + if (DataTimeout == NULL) + { + errno = ETIMEDOUT; longjmp(CtxDataTimeout, 1); } + + errno = save_errno; } /* ** SMTPGETSTAT -- get status code from DATA in LMTP @@ -2027,7 +2034,7 @@ smtpgetstat(m, mci, e) else status = EX_PROTOCOL; if (e->e_statmsg != NULL) - free(e->e_statmsg); + sm_free(e->e_statmsg); if (bitset(MCIF_ENHSTAT, mci->mci_flags) && (r = isenhsc(SmtpReplyBuffer + 4, ' ')) > 0) r += 5; diff --git a/contrib/sendmail/src/util.c b/contrib/sendmail/src/util.c index 6b301cb..f023865 100644 --- a/contrib/sendmail/src/util.c +++ b/contrib/sendmail/src/util.c @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: util.c,v 8.225.2.1.2.19 2001/02/22 18:56:24 gshapiro Exp $"; +static char id[] = "@(#)$Id: util.c,v 8.225.2.1.2.23 2001/05/17 18:10:18 gshapiro Exp $"; #endif /* ! lint */ #include <sendmail.h> @@ -378,15 +378,122 @@ xalloc(sz) if (sz <= 0) sz = 1; + ENTER_CRITICAL(); p = malloc((unsigned) sz); + LEAVE_CRITICAL(); if (p == NULL) { syserr("!Out of memory!!"); - /* exit(EX_UNAVAILABLE); */ + + /* NOTREACHED */ + exit(EX_UNAVAILABLE); + } + return p; +} +/* +** XREALLOC -- Reallocate memory and bitch wildly on failure. +** +** THIS IS A CLUDGE. This should be made to give a proper +** error -- but after all, what can we do? +** +** Parameters: +** ptr -- original area. +** sz -- size of new area to allocate. +** +** Returns: +** pointer to data region. +** +** Side Effects: +** Memory is allocated. +*/ + +char * +xrealloc(ptr, sz) + void *ptr; + size_t sz; +{ + register char *p; + + /* some systems can't handle size zero mallocs */ + if (sz <= 0) + sz = 1; + + ENTER_CRITICAL(); + p = realloc(ptr, (unsigned) sz); + LEAVE_CRITICAL(); + if (p == NULL) + { + syserr("!Out of memory!!"); + + /* NOTREACHED */ + exit(EX_UNAVAILABLE); } return p; } /* +** XCALLOC -- Allocate memory and bitch wildly on failure. +** +** THIS IS A CLUDGE. This should be made to give a proper +** error -- but after all, what can we do? +** +** Parameters: +** num -- number of items to allocate +** sz -- size of new area to allocate. +** +** Returns: +** pointer to data region. +** +** Side Effects: +** Memory is allocated. +*/ + +char * +xcalloc(num, sz) + size_t num; + size_t sz; +{ + register char *p; + + /* some systems can't handle size zero mallocs */ + if (num <= 0) + num = 1; + if (sz <= 0) + sz = 1; + + ENTER_CRITICAL(); + p = calloc((unsigned) num, (unsigned) sz); + LEAVE_CRITICAL(); + if (p == NULL) + { + syserr("!Out of memory!!"); + + /* NOTREACHED */ + exit(EX_UNAVAILABLE); + } + return p; +} +/* +** SM_FREE -- Free memory safely. +** +** Parameters: +** ptr -- area to free +** +** Returns: +** none. +** +** Side Effects: +** Memory is freed. +*/ + +void +sm_free(ptr) + void *ptr; +{ + ENTER_CRITICAL(); + free(ptr); + LEAVE_CRITICAL(); +} +/* ** COPYPLIST -- copy list of pointers. ** ** This routine is the equivalent of newstr for lists of @@ -502,13 +609,13 @@ log_sendmail_pid(e) } else { - long pid; + pid_t pid; extern char *CommandLineArgs; - pid = (long) getpid(); + pid = getpid(); /* write the process id on line 1 */ - fprintf(pidf, "%ld\n", pid); + fprintf(pidf, "%ld\n", (long) pid); /* line 2 contains all command line flags */ fprintf(pidf, "%s\n", CommandLineArgs); @@ -1212,6 +1319,13 @@ static void readtimeout(timeout) time_t timeout; { + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + + errno = ETIMEDOUT; longjmp(CtxReadTimeout, 1); } /* @@ -1271,7 +1385,7 @@ fgetfolded(buf, n, f) memmove(nbp, bp, p - bp); p = &nbp[p - bp]; if (bp != buf) - free(bp); + sm_free(bp); bp = nbp; n = nn - (p - bp); } @@ -1836,13 +1950,13 @@ shorten_hostname(host) ** pid of the process -- -1 if it failed. */ -int +pid_t prog_open(argv, pfd, e) char **argv; int *pfd; ENVELOPE *e; { - int pid; + pid_t pid; int i; int save_errno; int fdv[2]; @@ -1874,6 +1988,11 @@ prog_open(argv, pfd, e) /* child -- close stdin */ (void) close(0); + /* Reset global flags */ + RestartRequest = NULL; + ShutdownRequest = NULL; + PendingSignal = 0; + /* stdout goes back to parent */ (void) close(fdv[0]); if (dup2(fdv[1], 1) < 0) @@ -2119,7 +2238,7 @@ denlstring(s, strict, logattacks) { /* allocate more space */ if (bp != NULL) - free(bp); + sm_free(bp); bp = xalloc(l); bl = l; } @@ -2199,7 +2318,7 @@ path_is_dir(pathname, createflag) ** none */ -static struct procs *ProcListVec = NULL; +static struct procs *volatile ProcListVec = NULL; static int ProcListSize = 0; void @@ -2238,7 +2357,7 @@ proc_list_add(pid, task, type) { memmove(npv, ProcListVec, ProcListSize * sizeof (struct procs)); - free(ProcListVec); + sm_free(ProcListVec); } for (i = ProcListSize; i < ProcListSize + PROC_LIST_SEG; i++) { @@ -2252,7 +2371,7 @@ proc_list_add(pid, task, type) } ProcListVec[i].proc_pid = pid; if (ProcListVec[i].proc_task != NULL) - free(ProcListVec[i].proc_task); + sm_free(ProcListVec[i].proc_task); ProcListVec[i].proc_task = newstr(task); ProcListVec[i].proc_type = type; @@ -2283,7 +2402,7 @@ proc_list_set(pid, task) if (ProcListVec[i].proc_pid == pid) { if (ProcListVec[i].proc_task != NULL) - free(ProcListVec[i].proc_task); + sm_free(ProcListVec[i].proc_task); ProcListVec[i].proc_task = newstr(task); break; } @@ -2297,6 +2416,10 @@ proc_list_set(pid, task) ** ** Returns: ** type of process +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. */ int diff --git a/contrib/sendmail/src/version.c b/contrib/sendmail/src/version.c index 60a42c6..3b4c4e8 100644 --- a/contrib/sendmail/src/version.c +++ b/contrib/sendmail/src/version.c @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: version.c,v 8.43.4.30 2001/02/27 19:22:31 gshapiro Exp $"; +static char id[] = "@(#)$Id: version.c,v 8.43.4.33 2001/05/27 21:39:21 gshapiro Exp $"; #endif /* ! lint */ -char Version[] = "8.11.3"; +char Version[] = "8.11.4"; |