summaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
authorAndreas Beckmann <debian@abeckmann.de>2012-10-01 19:58:38 +0200
committerAndreas Beckmann <debian@abeckmann.de>2012-10-01 19:58:38 +0200
commit6b71060b84a2d9111ec847e66cc5160aab8a45e8 (patch)
tree599eb55ae3e0ec0f95d829c185831f3027eec78b /src/main.c
parent6c193ce1dd1d07ebdc1372e38bc4908ab1c37705 (diff)
downloadsendmail-6b71060b84a2d9111ec847e66cc5160aab8a45e8.tar.gz
Imported Upstream version 8.9.3upstream/8.9.3
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c432
1 files changed, 304 insertions, 128 deletions
diff --git a/src/main.c b/src/main.c
index c496adb..cea9d15 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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);