diff options
author | Andreas Beckmann <debian@abeckmann.de> | 2012-10-01 19:58:38 +0200 |
---|---|---|
committer | Andreas Beckmann <debian@abeckmann.de> | 2012-10-01 19:58:38 +0200 |
commit | 6b71060b84a2d9111ec847e66cc5160aab8a45e8 (patch) | |
tree | 599eb55ae3e0ec0f95d829c185831f3027eec78b /src/main.c | |
parent | 6c193ce1dd1d07ebdc1372e38bc4908ab1c37705 (diff) | |
download | sendmail-6b71060b84a2d9111ec847e66cc5160aab8a45e8.tar.gz |
Imported Upstream version 8.9.3upstream/8.9.3
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 432 |
1 files changed, 304 insertions, 128 deletions
@@ -1,51 +1,32 @@ /* - * Copyright (c) 1983, 1995-1997 Eric P. Allman + * Copyright (c) 1998 Sendmail, Inc. All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. */ #ifndef lint static char copyright[] = -"@(#) Copyright (c) 1988, 1993\n\ +"@(#) Copyright (c) 1998 Sendmail, Inc. All rights reserved.\n\ + Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.\n\ + Copyright (c) 1988, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)main.c 8.258 (Berkeley) 10/20/97"; +static char sccsid[] = "@(#)main.c 8.322 (Berkeley) 12/18/1998"; #endif /* not lint */ #define _DEFINE #include "sendmail.h" #include <arpa/inet.h> +#include <grp.h> #if NAMED_BIND #include <resolv.h> #endif @@ -74,6 +55,7 @@ static char sccsid[] = "@(#)main.c 8.258 (Berkeley) 10/20/97"; ** (11/88 - 9/89). ** UCB/Mammoth Project (10/89 - 7/95). ** InReference, Inc. (8/95 - 1/97). +** Sendmail, Inc. (1/98 - present). ** The support of the my employers is gratefully acknowledged. ** Few of them (Britton-Lee in particular) have had ** anything to gain from my involvement in this project. @@ -95,7 +77,7 @@ int MissingFds = 0; /* bit map of fds missing on startup */ GIDSET_T InitialGidSet[NGROUPS_MAX]; #endif -static void obsolete(); +static void obsolete __P((char **)); extern void printmailer __P((MAILER *)); extern void tTflag __P((char *)); @@ -106,7 +88,7 @@ ERROR %%%% Cannot have DAEMON mode without SMTP %%%% ERROR ERROR %%%% Cannot have SMTP mode without QUEUE %%%% ERROR #endif /* DAEMON && !SMTP */ -#define MAXCONFIGLEVEL 7 /* highest config version level known */ +#define MAXCONFIGLEVEL 8 /* highest config version level known */ int main(argc, argv, envp) @@ -129,22 +111,25 @@ main(argc, argv, envp) static bool reenter = FALSE; struct passwd *pw; struct hostent *hp; - bool nullserver = FALSE; + char *nullserver = NULL; + bool forged; char jbuf[MAXHOSTNAMELEN]; /* holds MyHostName */ static char rnamebuf[MAXNAME]; /* holds RealUserName */ char *emptyenviron[1]; + QUEUE_CHAR *new; extern int DtableSize; extern int optind; extern int opterr; extern char *optarg; extern char **environ; - extern time_t convtime(); + extern time_t convtime __P((char *, char)); extern SIGFUNC_DECL intsig __P((int)); - extern struct hostent *myhostname(); - extern char *getauthinfo(); - extern char *getcfname(); + extern struct hostent *myhostname __P((char *, int)); + extern char *getauthinfo __P((int, bool *)); + extern char *getcfname __P((void)); extern SIGFUNC_DECL sigusr1 __P((int)); extern SIGFUNC_DECL sighup __P((int)); + extern SIGFUNC_DECL quiesce __P((int)); extern void initmacros __P((ENVELOPE *)); extern void init_md __P((int, char **)); extern int getdtsize __P((void)); @@ -159,6 +144,9 @@ main(argc, argv, envp) extern void printqueue __P((void)); extern void sendtoargv __P((char **, ENVELOPE *)); extern void resetlimits __P((void)); +#ifndef HASUNSETENV + extern void unsetenv __P((char *)); +#endif /* ** Check to see if we reentered. @@ -250,6 +238,9 @@ main(argc, argv, envp) setsignal(SIGUSR1, sigusr1); #endif + /* initialize for setproctitle */ + initsetproctitle(argc, argv, envp); + /* Handle any non-getoptable constructions. */ obsolete(argv); @@ -311,17 +302,36 @@ main(argc, argv, envp) (void) snprintf(rnamebuf, sizeof rnamebuf, "Unknown UID %d", RealUid); RealUserName = rnamebuf; - /* if running non-setuid binary, pretend we are the RunAsUid */ - if (geteuid() == RealUid) + if (tTd(0, 101)) + { + printf("Version %s\n", Version); + finis(FALSE, EX_OK); + } + + /* + ** if running non-setuid binary as non-root, pretend + ** we are the RunAsUid + */ + if (RealUid != 0 && geteuid() == RealUid) { if (tTd(47, 1)) printf("Non-setuid binary: RunAsUid = RealUid = %d\n", - RealUid); + (int)RealUid); RunAsUid = RealUid; } - if (getegid() == RealGid) + else if (geteuid() != 0) + RunAsUid = geteuid(); + + if (RealUid != 0 && getegid() == RealGid) RunAsGid = RealGid; + if (tTd(47, 5)) + { + printf("main: e/ruid = %d/%d e/rgid = %d/%d\n", + (int)geteuid(), (int)getuid(), (int)getegid(), (int)getgid()); + printf("main: RunAsUser = %d:%d\n", (int)RunAsUid, (int)RunAsGid); + } + /* save command line arguments */ i = 0; for (av = argv; *av != NULL; ) @@ -402,14 +412,26 @@ main(argc, argv, envp) InChannel = stdin; OutChannel = stdout; - /* initialize for setproctitle */ - initsetproctitle(argc, argv, envp); - /* clear sendmail's environment */ ExternalEnviron = environ; emptyenviron[0] = NULL; environ = emptyenviron; + /* + ** restore any original TZ setting until TimeZoneSpec has been + ** determined - or early log messages may get bogus time stamps + */ + if ((p = getextenv("TZ")) != NULL) + { + char *tz; + int tzlen; + + tzlen = strlen(p) + 4; + tz = xalloc(tzlen); + snprintf(tz, tzlen, "TZ=%s", p); + putenv(tz); + } + /* prime the child environment */ setuserenv("AGENT", "sendmail"); @@ -504,8 +526,6 @@ main(argc, argv, envp) #if NETINET if (hp->h_addrtype == AF_INET && hp->h_length == INADDRSZ) { - register int i; - for (i = 0; hp->h_addr_list[i] != NULL; i++) { char ipbuf[103]; @@ -523,8 +543,12 @@ main(argc, argv, envp) /* current time */ define('b', arpadate((char *) NULL), CurEnv); + QueueLimitRecipient = (QUEUE_CHAR *) NULL; + QueueLimitSender = (QUEUE_CHAR *) NULL; + QueueLimitId = (QUEUE_CHAR *) NULL; + /* - ** Crack argv. + ** Crack argv. */ av = argv; @@ -690,15 +714,27 @@ main(argc, argv, envp) switch (optarg[0]) { case 'I': - QueueLimitId = newstr(&optarg[1]); + if ((new = (QUEUE_CHAR *)malloc(sizeof(QUEUE_CHAR))) == NULL) + syserr("!Out of memory!!"); + new->queue_match = newstr(&optarg[1]); + new->queue_next = QueueLimitId; + QueueLimitId = new; break; case 'R': - QueueLimitRecipient = newstr(&optarg[1]); + if ((new = (QUEUE_CHAR *)malloc(sizeof(QUEUE_CHAR))) == NULL) + syserr("!Out of memory!!"); + new->queue_match = newstr(&optarg[1]); + new->queue_next = QueueLimitRecipient; + QueueLimitRecipient = new; break; case 'S': - QueueLimitSender = newstr(&optarg[1]); + if ((new = (QUEUE_CHAR *)malloc(sizeof(QUEUE_CHAR))) == NULL) + syserr("!Out of memory!!"); + new->queue_match = newstr(&optarg[1]); + new->queue_next = QueueLimitSender; + QueueLimitSender = new; break; default: @@ -798,8 +834,7 @@ main(argc, argv, envp) # endif default: - ExitStat = EX_USAGE; - finis(); + finis(TRUE, EX_USAGE); break; } } @@ -850,7 +885,7 @@ main(argc, argv, envp) ** Find our real host name for future logging. */ - p = getauthinfo(STDIN_FILENO); + p = getauthinfo(STDIN_FILENO, &forged); define('_', p, CurEnv); /* suppress error printing if errors mailed back or whatever */ @@ -934,16 +969,20 @@ main(argc, argv, envp) } /* check for permissions */ - if ((OpMode == MD_DAEMON || OpMode == MD_PURGESTAT) && RealUid != 0) + if ((OpMode == MD_DAEMON || + OpMode == MD_FGDAEMON || + OpMode == MD_PURGESTAT) && + RealUid != 0 && + RealUid != TrustedUid) { if (LogLevel > 1) sm_syslog(LOG_ALERT, NOQID, "user %d attempted to %s", RealUid, - OpMode == MD_DAEMON ? "run daemon" - : "purge host status"); + OpMode != MD_PURGESTAT ? "run daemon" + : "purge host status"); usrerr("Permission denied"); - exit(EX_USAGE); + finis(FALSE, EX_USAGE); } if (MeToo) @@ -954,8 +993,18 @@ main(argc, argv, envp) case MD_TEST: /* don't have persistent host status in test mode */ HostStatDir = NULL; - Verbose = 2; + if (Verbose == 0) + Verbose = 2; + CurEnv->e_errormode = EM_PRINT; + HoldErrs = FALSE; + break; + + 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) + setsignal(SIGHUP, intsig); break; case MD_FGDAEMON: @@ -983,6 +1032,7 @@ main(argc, argv, envp) case MD_INITALIAS: Verbose = 2; CurEnv->e_errormode = EM_PRINT; + HoldErrs = FALSE; /* fall through... */ case MD_PRINT: @@ -997,9 +1047,32 @@ main(argc, argv, envp) break; } - /* full names can't have newlines */ - if (FullName != NULL && strchr(FullName, '\n') != NULL) - FullName = newstr(denlstring(FullName, TRUE, TRUE)); + /* special considerations for FullName */ + if (FullName != NULL) + { + char *full = NULL; + extern bool rfc822_string __P((char *)); + + /* full names can't have newlines */ + if (strchr(FullName, '\n') != NULL) + { + FullName = full = newstr(denlstring(FullName, TRUE, TRUE)); + } + /* check for characters that may have to be quoted */ + if (!rfc822_string(FullName)) + { + extern char *addquotes __P((char *)); + + /* + ** Quote a full name with special characters + ** as a comment so crackaddr() doesn't destroy + ** the name portion of the address. + */ + FullName = addquotes(FullName); + if (full != NULL) + free(full); + } + } /* do heuristic mode adjustment */ if (Verbose) @@ -1011,6 +1084,24 @@ main(argc, argv, envp) setoption('d', "", TRUE, FALSE, CurEnv); } +#ifdef VENDOR_CODE + /* check for vendor mismatch */ + if (VendorCode != VENDOR_CODE) + { + extern char *getvendor __P((int)); + + message("Warning: .cf file vendor code mismatch: sendmail expects vendor %s, .cf file vendor is %s", + getvendor(VENDOR_CODE), getvendor(VendorCode)); + } +#endif + + /* check for out of date configuration level */ + if (ConfigLevel < MAXCONFIGLEVEL) + { + message("Warning: .cf file is out of date: sendmail %s supports version %d, .cf file is version %d", + Version, MAXCONFIGLEVEL, ConfigLevel); + } + if (ConfigLevel < 3) { UseErrorsTo = TRUE; @@ -1120,6 +1211,22 @@ main(argc, argv, envp) setclass('b', "application/octet-stream"); #endif +#if _FFR_MAX_MIME_HEADER_LENGTH + /* MIME headers which have fields to check for overflow */ + setclass(macid("{checkMIMEFieldHeaders}", NULL), "content-disposition"); + setclass(macid("{checkMIMEFieldHeaders}", NULL), "content-type"); + + /* MIME headers to check for length overflow */ + setclass(macid("{checkMIMETextHeaders}", NULL), "content-description"); + + /* MIME headers to check for overflow and rebalance */ + setclass(macid("{checkMIMEHeaders}", NULL), "content-disposition"); + setclass(macid("{checkMIMEHeaders}", NULL), "content-id"); + setclass(macid("{checkMIMEHeaders}", NULL), "content-transfer-encoding"); + setclass(macid("{checkMIMEHeaders}", NULL), "content-type"); + setclass(macid("{checkMIMEHeaders}", NULL), "mime-version"); +#endif + /* operate in queue directory */ if (QueueDir == NULL) { @@ -1162,18 +1269,14 @@ main(argc, argv, envp) { /* nope, really a botch */ usrerr("You do not have permission to process the queue"); - exit (EX_NOPERM); + finis(FALSE, EX_NOPERM); } } # endif /* QUEUE */ /* if we've had errors so far, exit now */ if (ExitStat != EX_OK && OpMode != MD_TEST) - { - endpwent(); - setuid(RealUid); - exit(ExitStat); - } + finis(FALSE, ExitStat); #if XDEBUG checkfd012("before main() initmaps"); @@ -1189,47 +1292,44 @@ main(argc, argv, envp) /* print the queue */ #if QUEUE dropenvelope(CurEnv, TRUE); + signal(SIGPIPE, quiesce); printqueue(); - endpwent(); - setuid(RealUid); - exit(EX_OK); + finis(FALSE, EX_OK); #else /* QUEUE */ usrerr("No queue to print"); - finis(); + finis(FALSE, ExitStat); #endif /* QUEUE */ + break; case MD_HOSTSTAT: + signal(SIGPIPE, quiesce); mci_traverse_persistent(mci_print_persistent, NULL); - exit(EX_OK); + finis(FALSE, EX_OK); break; case MD_PURGESTAT: mci_traverse_persistent(mci_purge_persistent, NULL); - exit(EX_OK); + finis(FALSE, EX_OK); break; case MD_INITALIAS: - /* initialize alias database */ + /* initialize maps */ initmaps(TRUE, CurEnv); - endpwent(); - setuid(RealUid); - exit(ExitStat); + finis(FALSE, ExitStat); + break; case MD_SMTP: - nullserver = FALSE; - /* fall through... */ - case MD_DAEMON: /* reset DSN parameters */ DefaultNotify = QPINGONFAILURE|QPINGONDELAY; CurEnv->e_envid = NULL; CurEnv->e_flags &= ~(EF_RET_PARAM|EF_NO_BODY_RETN); - /* don't open alias database -- done in srvrsmtp */ + /* don't open maps for daemon -- done below in child */ break; default: - /* open the alias database */ + /* open the maps */ initmaps(FALSE, CurEnv); break; } @@ -1279,15 +1379,15 @@ main(argc, argv, envp) { extern void testmodeline __P((char *, ENVELOPE *)); - if (Verbose) + if (Verbose == 2) printf("> "); (void) fflush(stdout); if (fgets(buf, sizeof buf, stdin) == NULL) - finis(); + finis(TRUE, ExitStat); p = strchr(buf, '\n'); if (p != NULL) *p = '\0'; - if (!Verbose) + if (Verbose < 2) printf("> %s\n", buf); testmodeline(buf, CurEnv); } @@ -1301,7 +1401,7 @@ main(argc, argv, envp) if (queuemode && OpMode != MD_DAEMON && QueueIntvl == 0) { (void) runqueue(FALSE, Verbose); - finis(); + finis(TRUE, ExitStat); } # endif /* QUEUE */ @@ -1326,7 +1426,7 @@ main(argc, argv, envp) if (i < 0) syserr("daemon: cannot fork"); if (i != 0) - exit(0); + finis(FALSE, EX_OK); /* disconnect from our controlling tty */ disconnect(2, CurEnv); @@ -1379,13 +1479,8 @@ main(argc, argv, envp) ** Get authentication data */ - p = getauthinfo(fileno(InChannel)); + p = getauthinfo(fileno(InChannel), &forged); define('_', p, &BlankEnvelope); - - /* validate the connection */ - HoldErrs = TRUE; - nullserver = !validate_connection(&RealHostAddr, RealHostName, CurEnv); - HoldErrs = FALSE; #endif /* DAEMON */ } @@ -1398,13 +1493,24 @@ main(argc, argv, envp) if (OpMode == MD_SMTP || OpMode == MD_DAEMON) { char pbuf[20]; - extern void smtp __P((bool, ENVELOPE *)); + extern void smtp __P((char *, ENVELOPE *)); /* ** Save some macros for check_* rulesets. */ - define(macid("{client_name}", NULL), RealHostName, &BlankEnvelope); + if (forged) + { + char ipbuf[103]; + + snprintf(ipbuf, sizeof ipbuf, "[%.100s]", + inet_ntoa(RealHostAddr.sin.sin_addr)); + + define(macid("{client_name}", NULL), + newstr(ipbuf), &BlankEnvelope); + } + else + define(macid("{client_name}", NULL), RealHostName, &BlankEnvelope); define(macid("{client_addr}", NULL), newstr(anynet_ntoa(&RealHostAddr)), &BlankEnvelope); if (RealHostAddr.sa.sa_family == AF_INET) @@ -1413,6 +1519,17 @@ main(argc, argv, envp) snprintf(pbuf, sizeof pbuf, "0"); define(macid("{client_port}", NULL), newstr(pbuf), &BlankEnvelope); + /* initialize maps now for check_relay ruleset */ + initmaps(FALSE, CurEnv); + + if (OpMode == MD_DAEMON) + { + /* validate the connection */ + HoldErrs = TRUE; + nullserver = validate_connection(&RealHostAddr, + RealHostName, CurEnv); + HoldErrs = FALSE; + } smtp(nullserver, CurEnv); } # endif /* SMTP */ @@ -1421,9 +1538,7 @@ main(argc, argv, envp) if (OpMode == MD_VERIFY) { CurEnv->e_sendmode = SM_VERIFY; - CurEnv->e_errormode = EM_PRINT; PostMasterCopy = NULL; - HoldErrs = FALSE; } else { @@ -1451,7 +1566,7 @@ main(argc, argv, envp) /* collect body for UUCP return */ if (OpMode != MD_VERIFY) collect(InChannel, FALSE, NULL, CurEnv); - finis(); + finis(TRUE, ExitStat); } /* @@ -1464,6 +1579,21 @@ main(argc, argv, envp) if (Errors > 0 && ExitStat == EX_OK) ExitStat = EX_USAGE; +#if _FFR_FIX_DASHT + /* + ** If using -t, force not sending to argv recipients, even + ** if they are mentioned in the headers. + */ + + if (GrabTo) + { + ADDRESS *q; + + for (q = CurEnv->e_sendqueue; q != NULL; q = q->q_next) + q->q_flags |= QDONTSEND; + } +#endif + /* ** Read the input mail. */ @@ -1480,7 +1610,7 @@ main(argc, argv, envp) /* bail out if message too large */ if (bitset(EF_CLRQUEUE, CurEnv->e_flags)) { - finis(); + finis(TRUE, ExitStat); /*NOTREACHED*/ return -1; } @@ -1504,6 +1634,7 @@ main(argc, argv, envp) } CurEnv->e_to = NULL; CurrentLA = getla(); + GrabTo = FALSE; sendall(CurEnv, SM_DEFAULT); /* @@ -1511,12 +1642,20 @@ main(argc, argv, envp) ** Don't send return error message if in VERIFY mode. */ - finis(); + finis(TRUE, ExitStat); /*NOTREACHED*/ return -1; } +/* ARGSUSED */ +SIGFUNC_DECL +quiesce(sig) + int sig; +{ + finis(FALSE, EX_OK); +} +/* ARGSUSED */ SIGFUNC_DECL intindebug(sig) int sig; @@ -1530,7 +1669,8 @@ intindebug(sig) ** FINIS -- Clean up and exit. ** ** Parameters: -** none +** drop -- whether or not to drop CurEnv envelope +** exitstat -- exit status to use for exit() call ** ** Returns: ** never @@ -1540,14 +1680,21 @@ intindebug(sig) */ void -finis() +finis(drop, exitstat) + bool drop; + volatile int exitstat; { + extern void closemaps __P((void)); +#ifdef USERDB + extern void _udbx_close __P((void)); +#endif + if (tTd(2, 1)) { - extern void printenvflags(); + extern void printenvflags __P((ENVELOPE *)); printf("\n====finis: stat %d e_id=%s e_flags=", - ExitStat, + exitstat, CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id); printenvflags(CurEnv); } @@ -1563,12 +1710,20 @@ finis() /* clean up temp files */ CurEnv->e_to = NULL; - if (CurEnv->e_id != NULL) + if (drop && CurEnv->e_id != NULL) dropenvelope(CurEnv, TRUE); /* flush any cached connections */ mci_flush(TRUE, NULL); + /* close maps belonging to this pid */ + closemaps(); + +#ifdef USERDB + /* close UserDatabase */ + _udbx_close(); +#endif + # ifdef XLA /* clean up extended load average stuff */ xla_all_end(); @@ -1580,14 +1735,14 @@ finis() sm_syslog(LOG_DEBUG, CurEnv->e_id, "finis, pid=%d", getpid()); - if (ExitStat == EX_TEMPFAIL || CurEnv->e_errormode == EM_BERKNET) - ExitStat = EX_OK; + if (exitstat == EX_TEMPFAIL || CurEnv->e_errormode == EM_BERKNET) + exitstat = EX_OK; /* reset uid for process accounting */ endpwent(); setuid(RealUid); - exit(ExitStat); + exit(exitstat); } /* ** INTSIG -- clean up on interrupt @@ -1605,6 +1760,7 @@ finis() ** Unlocks the current job. */ +/* ARGSUSED */ SIGFUNC_DECL intsig(sig) int sig; @@ -1613,15 +1769,11 @@ intsig(sig) sm_syslog(LOG_DEBUG, CurEnv->e_id, "interrupt"); FileName = NULL; unlockqueue(CurEnv); + closecontrolsocket(TRUE); #ifdef XLA xla_all_end(); #endif - - /* reset uid for process accounting */ - endpwent(); - setuid(RealUid); - - exit(EX_OK); + finis(FALSE, EX_OK); } /* ** INITMACROS -- initialize the macro system @@ -1752,7 +1904,10 @@ disconnect(droplev, e) (void) fclose(InChannel); InChannel = stdin; } - (void) freopen("/dev/null", "r", stdin); + if (freopen("/dev/null", "r", stdin) == NULL) + sm_syslog(LOG_ERR, e->e_id, + "disconnect: freopen(\"/dev/null\") failed: %s", + errstring(errno)); /* output to the transcript */ if (OutChannel != stdout) @@ -1763,9 +1918,21 @@ disconnect(droplev, e) if (droplev > 0) { if (e->e_xfp == NULL) + { fd = open("/dev/null", O_WRONLY, 0666); + if (fd == -1) + sm_syslog(LOG_ERR, e->e_id, + "disconnect: open(\"/dev/null\") failed: %s", + errstring(errno)); + } else + { fd = fileno(e->e_xfp); + if (fd == -1) + sm_syslog(LOG_ERR, e->e_id, + "disconnect: fileno(e->e_xfp) failed: %s", + errstring(errno)); + } (void) fflush(stdout); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); @@ -1876,7 +2043,7 @@ auth_warning(e, msg, va_alist) { register char *p; static char hostbuf[48]; - extern struct hostent *myhostname(); + extern struct hostent *myhostname __P((char *, int)); if (hostbuf[0] == '\0') (void) myhostname(hostbuf, sizeof hostbuf); @@ -2017,6 +2184,7 @@ dumpstate(when) } +/* ARGSUSED */ SIGFUNC_DECL sigusr1(sig) int sig; @@ -2026,6 +2194,7 @@ sigusr1(sig) } +/* ARGSUSED */ SIGFUNC_DECL sighup(sig) int sig; @@ -2034,23 +2203,24 @@ sighup(sig) { if (LogLevel > 3) sm_syslog(LOG_INFO, NOQID, "could not restart: need full path"); - exit(EX_OSFILE); + finis(FALSE, EX_OSFILE); } if (LogLevel > 3) sm_syslog(LOG_INFO, NOQID, "restarting %s on signal", SaveArgv[0]); alarm(0); 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); - exit(EX_OSERR); + finis(FALSE, EX_OSERR); } execve(SaveArgv[0], (ARGV_T) SaveArgv, (ARGV_T) ExternalEnviron); if (LogLevel > 0) sm_syslog(LOG_ALERT, NOQID, "could not exec %s: %m", SaveArgv[0]); - exit(EX_OSFILE); + finis(FALSE, EX_OSFILE); } /* ** DROP_PRIVILEGES -- reduce privileges to those of the RunAsUser option @@ -2069,13 +2239,11 @@ drop_privileges(to_real_uid) bool to_real_uid; { int rval = EX_OK; -#ifdef NGROUPS_MAX - GIDSET_T emptygidset[NGROUPS_MAX]; -#endif + GIDSET_T emptygidset[1]; if (tTd(47, 1)) printf("drop_privileges(%d): Real[UG]id=%d:%d, RunAs[UG]id=%d:%d\n", - to_real_uid, RealUid, RealGid, RunAsUid, RunAsGid); + (int)to_real_uid, (int)RealUid, (int)RealGid, (int)RunAsUid, (int)RunAsGid); if (to_real_uid) { @@ -2087,17 +2255,22 @@ drop_privileges(to_real_uid) /* make sure no one can grab open descriptors for secret files */ endpwent(); -#ifdef NGROUPS_MAX /* reset group permissions; these can be set later */ emptygidset[0] = (to_real_uid || RunAsGid != 0) ? RunAsGid : getegid(); - (void) setgroups(1, emptygidset); -#endif + if (setgroups(1, emptygidset) == -1 && geteuid() == 0) + rval = EX_OSERR; /* reset primary group and user id */ if ((to_real_uid || RunAsGid != 0) && setgid(RunAsGid) < 0) rval = EX_OSERR; if ((to_real_uid || RunAsUid != 0) && setuid(RunAsUid) < 0) rval = EX_OSERR; + if (tTd(47, 5)) + { + printf("drop_privileges: e/ruid = %d/%d e/rgid = %d/%d\n", + (int)geteuid(), (int)getuid(), (int)getegid(), (int)getgid()); + printf("drop_privileges: RunAsUser = %d:%d\n", (int)RunAsUid, (int)RunAsGid); + } return rval; } /* @@ -2387,13 +2560,14 @@ testmodeline(line, e) else if (strcasecmp(&line[1], "map") == 0) { auto int rcode = EX_OK; + char *av[2]; if (*p == '\0') { printf("Usage: /map mapname key\n"); return; } - for (q = p; *q != '\0' && !isspace(*q); q++) + for (q = p; *q != '\0' && !(isascii(*q) && isspace(*q)); q++) continue; if (*q == '\0') { @@ -2413,8 +2587,10 @@ testmodeline(line, e) return; } printf("map_lookup: %s (%s) ", p, q); + av[0] = q; + av[1] = NULL; p = (*map->s_map.map_class->map_lookup) - (&map->s_map, q, NULL, &rcode); + (&map->s_map, q, av, &rcode); if (p == NULL) printf("no match (%d)\n", rcode); else @@ -2542,8 +2718,8 @@ testmodeline(line, e) while (*p != '\0') { int stat; - int rs = strtorwset(p, NULL, ST_FIND); + rs = strtorwset(p, NULL, ST_FIND); if (rs < 0) { printf("Undefined ruleset %s\n", p); |