summaryrefslogtreecommitdiffstats
path: root/usr.sbin/sendmail/src/recipient.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/sendmail/src/recipient.c')
-rw-r--r--usr.sbin/sendmail/src/recipient.c615
1 files changed, 169 insertions, 446 deletions
diff --git a/usr.sbin/sendmail/src/recipient.c b/usr.sbin/sendmail/src/recipient.c
index 79126e9..0b12c2c 100644
--- a/usr.sbin/sendmail/src/recipient.c
+++ b/usr.sbin/sendmail/src/recipient.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,10 +33,11 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)recipient.c 8.108 (Berkeley) 10/30/95";
+static char sccsid[] = "@(#)recipient.c 8.44.1.6 (Berkeley) 3/5/95";
#endif /* not lint */
# include "sendmail.h"
+# include <pwd.h>
/*
** SENDTOLIST -- Designate a send list.
@@ -52,8 +53,6 @@ static char sccsid[] = "@(#)recipient.c 8.108 (Berkeley) 10/30/95";
** expansion.
** sendq -- a pointer to the head of a queue to put
** these people into.
-** aliaslevel -- the current alias nesting depth -- to
-** diagnose loops.
** e -- the envelope in which to add these recipients.
**
** Returns:
@@ -63,15 +62,12 @@ static char sccsid[] = "@(#)recipient.c 8.108 (Berkeley) 10/30/95";
** none.
*/
-/* q_flags bits inherited from ctladdr */
-#define QINHERITEDBITS (QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY|QHASNOTIFY)
+# define MAXRCRSN 10
-int
-sendtolist(list, ctladdr, sendq, aliaslevel, e)
+sendtolist(list, ctladdr, sendq, e)
char *list;
ADDRESS *ctladdr;
ADDRESS **sendq;
- int aliaslevel;
register ENVELOPE *e;
{
register char *p;
@@ -132,58 +128,13 @@ sendtolist(list, ctladdr, sendq, aliaslevel, e)
a->q_next = al;
a->q_alias = ctladdr;
- /* arrange to inherit attributes from parent */
- if (ctladdr != NULL)
- {
- ADDRESS *b;
- extern ADDRESS *self_reference();
-
- /* self reference test */
- if (sameaddr(ctladdr, a))
- {
- if (tTd(27, 5))
- {
- printf("sendtolist: QSELFREF ");
- printaddr(ctladdr, FALSE);
- }
- ctladdr->q_flags |= QSELFREF;
- }
-
- /* check for address loops */
- b = self_reference(a, e);
- if (b != NULL)
- {
- b->q_flags |= QSELFREF;
- if (tTd(27, 5))
- {
- printf("sendtolist: QSELFREF ");
- printaddr(b, FALSE);
- }
- if (a != b)
- {
- if (tTd(27, 5))
- {
- printf("sendtolist: QDONTSEND ");
- printaddr(a, FALSE);
- }
- a->q_flags |= QDONTSEND;
- b->q_flags |= a->q_flags & QNOTREMOTE;
- continue;
- }
- }
-
- /* full name */
- if (a->q_fullname == NULL)
- a->q_fullname = ctladdr->q_fullname;
-
- /* various flag bits */
- a->q_flags &= ~QINHERITEDBITS;
- a->q_flags |= ctladdr->q_flags & QINHERITEDBITS;
-
- /* original recipient information */
- a->q_orcpt = ctladdr->q_orcpt;
- }
+ /* see if this should be marked as a primary address */
+ if (ctladdr == NULL ||
+ (firstone && *p == '\0' && bitset(QPRIMARY, ctladdr->q_flags)))
+ a->q_flags |= QPRIMARY;
+ if (ctladdr != NULL && sameaddr(ctladdr, a))
+ ctladdr->q_flags |= QSELFREF;
al = a;
firstone = FALSE;
}
@@ -194,7 +145,11 @@ sendtolist(list, ctladdr, sendq, aliaslevel, e)
register ADDRESS *a = al;
al = a->q_next;
- a = recipient(a, sendq, aliaslevel, e);
+ a = recipient(a, sendq, e);
+
+ /* arrange to inherit full name */
+ if (a->q_fullname == NULL && ctladdr != NULL)
+ a->q_fullname = ctladdr->q_fullname;
naddrs++;
}
@@ -213,7 +168,6 @@ sendtolist(list, ctladdr, sendq, aliaslevel, e)
** sendq -- a pointer to the head of a queue to put the
** recipient in. Duplicate supression is done
** in this queue.
-** aliaslevel -- the current alias nesting depth.
** e -- the current envelope.
**
** Returns:
@@ -225,10 +179,9 @@ sendtolist(list, ctladdr, sendq, aliaslevel, e)
*/
ADDRESS *
-recipient(a, sendq, aliaslevel, e)
+recipient(a, sendq, e)
register ADDRESS *a;
register ADDRESS **sendq;
- int aliaslevel;
register ENVELOPE *e;
{
register ADDRESS *q;
@@ -237,20 +190,15 @@ recipient(a, sendq, aliaslevel, e)
register char *p;
bool quoted = FALSE; /* set if the addr has a quote bit */
int findusercount = 0;
- bool initialdontsend = bitset(QDONTSEND, a->q_flags);
- int i;
- char *buf;
- char buf0[MAXNAME + 1]; /* unquoted image of the user name */
+ char buf[MAXNAME]; /* unquoted image of the user name */
extern int safefile();
e->e_to = a->q_paddr;
m = a->q_mailer;
errno = 0;
- if (aliaslevel == 0)
- a->q_flags |= QPRIMARY;
if (tTd(26, 1))
{
- printf("\nrecipient (%d): ", aliaslevel);
+ printf("\nrecipient: ");
printaddr(a, FALSE);
}
@@ -264,11 +212,9 @@ recipient(a, sendq, aliaslevel, e)
}
/* break aliasing loops */
- if (aliaslevel > MaxAliasRecursion)
+ if (AliasLevel > MAXRCRSN)
{
- a->q_status = "5.4.6";
- usrerr("554 aliasing/forwarding loop broken (%d aliases deep; %d max",
- aliaslevel, MaxAliasRecursion);
+ usrerr("554 aliasing/forwarding loop broken");
return (a);
}
@@ -276,12 +222,10 @@ recipient(a, sendq, aliaslevel, e)
** Finish setting up address structure.
*/
+ /* set the queue timeout */
+ a->q_timeout = TimeOuts.to_q_return;
+
/* get unquoted user for file, program or user.name check */
- i = strlen(a->q_user);
- if (i >= sizeof buf0)
- buf = xalloc(i + 1);
- else
- buf = buf0;
(void) strcpy(buf, a->q_user);
for (p = buf; *p != '\0' && !quoted; p++)
{
@@ -296,20 +240,17 @@ recipient(a, sendq, aliaslevel, e)
if (a->q_alias == NULL)
{
a->q_flags |= QBADADDR;
- a->q_status = "5.7.1";
usrerr("550 Cannot mail directly to programs");
}
else if (bitset(QBOGUSSHELL, a->q_alias->q_flags))
{
a->q_flags |= QBADADDR;
- a->q_status = "5.7.1";
usrerr("550 User %s@%s doesn't have a valid shell for mailing to programs",
a->q_alias->q_ruser, MyHostName);
}
else if (bitset(QUNSAFEADDR, a->q_alias->q_flags))
{
a->q_flags |= QBADADDR;
- a->q_status = "5.7.1";
usrerr("550 Address %s is unsafe for mailing to programs",
a->q_alias->q_paddr);
}
@@ -342,7 +283,7 @@ recipient(a, sendq, aliaslevel, e)
else if (bitset(QSELFREF, q->q_flags))
q->q_flags |= a->q_flags & ~QDONTSEND;
a = q;
- goto done;
+ goto testselfdestruct;
}
}
@@ -367,7 +308,6 @@ recipient(a, sendq, aliaslevel, e)
if (a->q_alias == NULL)
{
a->q_flags |= QBADADDR;
- a->q_status = "5.7.1";
usrerr("550 Cannot mail directly to :include:s");
}
else
@@ -375,29 +315,25 @@ recipient(a, sendq, aliaslevel, e)
int ret;
message("including file %s", a->q_user);
- ret = include(a->q_user, FALSE, a, sendq, aliaslevel, e);
+ ret = include(a->q_user, FALSE, a, sendq, e);
if (transienterror(ret))
{
#ifdef LOG
if (LogLevel > 2)
syslog(LOG_ERR, "%s: include %s: transient error: %s",
e->e_id == NULL ? "NOQUEUE" : e->e_id,
- shortenstring(a->q_user, 203),
- errstring(ret));
+ a->q_user, errstring(ret));
#endif
a->q_flags |= QQUEUEUP;
a->q_flags &= ~QDONTSEND;
usrerr("451 Cannot open %s: %s",
- shortenstring(a->q_user, 203),
- errstring(ret));
+ a->q_user, errstring(ret));
}
else if (ret != 0)
{
a->q_flags |= QBADADDR;
- a->q_status = "5.2.4";
usrerr("550 Cannot open %s: %s",
- shortenstring(a->q_user, 203),
- errstring(ret));
+ a->q_user, errstring(ret));
}
}
}
@@ -409,44 +345,44 @@ recipient(a, sendq, aliaslevel, e)
if (a->q_alias == NULL)
{
a->q_flags |= QBADADDR;
- a->q_status = "5.7.1";
usrerr("550 Cannot mail directly to files");
}
else if (bitset(QBOGUSSHELL, a->q_alias->q_flags))
{
a->q_flags |= QBADADDR;
- a->q_status = "5.7.1";
usrerr("550 User %s@%s doesn't have a valid shell for mailing to files",
a->q_alias->q_ruser, MyHostName);
}
else if (bitset(QUNSAFEADDR, a->q_alias->q_flags))
{
a->q_flags |= QBADADDR;
- a->q_status = "5.7.1";
usrerr("550 Address %s is unsafe for mailing to files",
a->q_alias->q_paddr);
}
- else if (!writable(buf, a->q_alias, SFF_CREAT))
+ else if (!writable(buf, getctladdr(a), SFF_ANYFILE))
{
a->q_flags |= QBADADDR;
- giveresponse(EX_CANTCREAT, m, NULL, a->q_alias,
- (time_t) 0, e);
+ giveresponse(EX_CANTCREAT, m, NULL, a->q_alias, e);
}
}
+ if (m != LocalMailer)
+ {
+ if (!bitset(QDONTSEND, a->q_flags))
+ e->e_nrcpts++;
+ goto testselfdestruct;
+ }
+
/* try aliasing */
- if (!quoted && !bitset(QDONTSEND, a->q_flags) &&
- bitnset(M_ALIASABLE, m->m_flags))
- alias(a, sendq, aliaslevel, e);
+ alias(a, sendq, e);
-# if USERDB
+# ifdef USERDB
/* if not aliased, look it up in the user database */
- if (!bitset(QDONTSEND|QNOTREMOTE|QVERIFIED, a->q_flags) &&
- bitnset(M_CHECKUDB, m->m_flags))
+ if (!bitset(QDONTSEND|QNOTREMOTE|QVERIFIED, a->q_flags))
{
extern int udbexpand();
- if (udbexpand(a, sendq, aliaslevel, e) == EX_TEMPFAIL)
+ if (udbexpand(a, sendq, e) == EX_TEMPFAIL)
{
a->q_flags |= QQUEUEUP;
if (e->e_message == NULL)
@@ -465,6 +401,10 @@ recipient(a, sendq, aliaslevel, e)
}
# endif
+ /* if it was an alias or a UDB expansion, just return now */
+ if (bitset(QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags))
+ goto testselfdestruct;
+
/*
** If we have a level two config file, then pass the name through
** Ruleset 5 before sending it off. Ruleset 5 has the right
@@ -478,11 +418,10 @@ recipient(a, sendq, aliaslevel, e)
ConfigLevel, RewriteRules[5]);
printaddr(a, FALSE);
}
- if (!bitset(QNOTREMOTE|QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags) &&
- ConfigLevel >= 2 && RewriteRules[5] != NULL &&
- bitnset(M_TRYRULESET5, m->m_flags))
+ if (!bitset(QNOTREMOTE, a->q_flags) && ConfigLevel >= 2 &&
+ RewriteRules[5] != NULL)
{
- maplocaluser(a, sendq, aliaslevel + 1, e);
+ maplocaluser(a, sendq, e);
}
/*
@@ -490,8 +429,7 @@ recipient(a, sendq, aliaslevel, e)
** and deliver it.
*/
- if (!bitset(QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags) &&
- bitnset(M_HASPWENT, m->m_flags))
+ if (!bitset(QDONTSEND|QQUEUEUP, a->q_flags))
{
auto bool fuzzy;
register struct passwd *pw;
@@ -502,13 +440,11 @@ recipient(a, sendq, aliaslevel, e)
if (pw == NULL)
{
a->q_flags |= QBADADDR;
- a->q_status = "5.1.1";
- giveresponse(EX_NOUSER, m, NULL, a->q_alias,
- (time_t) 0, e);
+ giveresponse(EX_NOUSER, m, NULL, a->q_alias, e);
}
else
{
- char nbuf[MAXNAME + 1];
+ char nbuf[MAXNAME];
if (fuzzy)
{
@@ -517,10 +453,9 @@ recipient(a, sendq, aliaslevel, e)
if (findusercount++ > 3)
{
a->q_flags |= QBADADDR;
- a->q_status = "5.4.6";
usrerr("554 aliasing/forwarding loop for %s broken",
pw->pw_name);
- goto done;
+ return (a);
}
/* see if it aliases */
@@ -538,103 +473,36 @@ recipient(a, sendq, aliaslevel, e)
buildfname(pw->pw_gecos, pw->pw_name, nbuf);
if (nbuf[0] != '\0')
a->q_fullname = newstr(nbuf);
- if (!usershellok(pw->pw_name, pw->pw_shell))
+ if (pw->pw_shell != NULL && pw->pw_shell[0] != '\0' &&
+ !usershellok(pw->pw_shell))
{
a->q_flags |= QBOGUSSHELL;
}
- if (bitset(EF_VRFYONLY, e->e_flags))
- {
- /* don't do any more now */
- a->q_flags |= QVERIFIED;
- }
- else if (!quoted)
- forward(a, sendq, aliaslevel, e);
+ if (!quoted)
+ forward(a, sendq, e);
}
}
if (!bitset(QDONTSEND, a->q_flags))
e->e_nrcpts++;
testselfdestruct:
- a->q_flags |= QTHISPASS;
if (tTd(26, 8))
{
printf("testselfdestruct: ");
- printaddr(a, FALSE);
- if (tTd(26, 10))
- {
- printf("SENDQ:\n");
- printaddr(*sendq, TRUE);
- printf("----\n");
- }
+ printaddr(a, TRUE);
}
if (a->q_alias == NULL && a != &e->e_from &&
bitset(QDONTSEND, a->q_flags))
{
- for (q = *sendq; q != NULL; q = q->q_next)
- {
- if (!bitset(QDONTSEND, q->q_flags))
- break;
- }
+ q = *sendq;
+ while (q != NULL && bitset(QDONTSEND, q->q_flags))
+ q = q->q_next;
if (q == NULL)
{
a->q_flags |= QBADADDR;
- a->q_status = "5.4.6";
usrerr("554 aliasing/forwarding loop broken");
}
}
-
- done:
- a->q_flags |= QTHISPASS;
- if (buf != buf0)
- free(buf);
-
- /*
- ** If we are at the top level, check to see if this has
- ** expanded to exactly one address. If so, it can inherit
- ** the primaryness of the address.
- **
- ** While we're at it, clear the QTHISPASS bits.
- */
-
- if (aliaslevel == 0)
- {
- int nrcpts = 0;
- ADDRESS *only;
-
- for (q = *sendq; q != NULL; q = q->q_next)
- {
- if (bitset(QTHISPASS, q->q_flags) &&
- !bitset(QDONTSEND|QBADADDR, q->q_flags))
- {
- nrcpts++;
- only = q;
- }
- q->q_flags &= ~QTHISPASS;
- }
- if (nrcpts == 1)
- {
- /* check to see if this actually got a new owner */
- q = only;
- while ((q = q->q_alias) != NULL)
- {
- if (q->q_owner != NULL)
- break;
- }
- if (q == NULL)
- only->q_flags |= QPRIMARY;
- }
- else if (!initialdontsend && nrcpts > 0)
- {
- /* arrange for return receipt */
- e->e_flags |= EF_SENDRECEIPT;
- a->q_flags |= QEXPANDED;
- if (e->e_xfp != NULL && bitset(QPINGONSUCCESS, a->q_flags))
- fprintf(e->e_xfp,
- "%s... expanded to multiple addresses\n",
- a->q_paddr);
- }
- }
-
return (a);
}
/*
@@ -667,14 +535,14 @@ finduser(name, fuzzyp)
{
register struct passwd *pw;
register char *p;
- bool tryagain;
+ extern struct passwd *getpwent();
+ extern struct passwd *getpwnam();
if (tTd(29, 4))
printf("finduser(%s): ", name);
*fuzzyp = FALSE;
-#ifdef HESIOD
/* DEC Hesiod getpwnam accepts numeric strings -- short circuit it */
for (p = name; *p != '\0'; p++)
if (!isascii(*p) || !isdigit(*p))
@@ -685,35 +553,16 @@ finduser(name, fuzzyp)
printf("failed (numeric input)\n");
return NULL;
}
-#endif
/* look up this login name using fast path */
- if ((pw = sm_getpwnam(name)) != NULL)
+ if ((pw = getpwnam(name)) != NULL)
{
if (tTd(29, 4))
printf("found (non-fuzzy)\n");
return (pw);
}
- /* try mapping it to lower case */
- tryagain = FALSE;
- for (p = name; *p != '\0'; p++)
- {
- if (isascii(*p) && isupper(*p))
- {
- *p = tolower(*p);
- tryagain = TRUE;
- }
- }
- if (tryagain && (pw = sm_getpwnam(name)) != NULL)
- {
- if (tTd(29, 4))
- printf("found (lower case)\n");
- *fuzzyp = TRUE;
- return pw;
- }
-
-#if MATCHGECOS
+#ifdef MATCHGECOS
/* see if fuzzy matching allowed */
if (!MatchGecos)
{
@@ -731,17 +580,7 @@ finduser(name, fuzzyp)
(void) setpwent();
while ((pw = getpwent()) != NULL)
{
- char buf[MAXNAME + 1];
-
-# if 0
- if (strcasecmp(pw->pw_name, name) == 0)
- {
- if (tTd(29, 4))
- printf("found (case wrapped)\n");
- *fuzzyp = TRUE;
- return pw;
- }
-# endif
+ char buf[MAXNAME];
buildfname(pw->pw_gecos, pw->pw_name, buf);
if (strchr(buf, ' ') != NULL && !strcasecmp(buf, name))
@@ -793,53 +632,90 @@ writable(filename, ctladdr, flags)
{
uid_t euid;
gid_t egid;
+ int bits;
+ register char *p;
char *uname;
+ struct stat stb;
+ extern char RealUserName[];
+
+ if (tTd(29, 5))
+ printf("writable(%s, %x)\n", filename, flags);
+
+#ifdef HASLSTAT
+ if ((bitset(SFF_NOSLINK, flags) ? lstat(filename, &stb)
+ : stat(filename, &stb)) < 0)
+#else
+ if (stat(filename, &stb) < 0)
+#endif
+ {
+ /* file does not exist -- see if directory is safe */
+ p = strrchr(filename, '/');
+ if (p == NULL)
+ {
+ errno = ENOTDIR;
+ return FALSE;
+ }
+ *p = '\0';
+ errno = safefile(filename, RealUid, RealGid, RealUserName,
+ SFF_MUSTOWN, S_IWRITE|S_IEXEC);
+ *p = '/';
+ return errno == 0;
+ }
- if (tTd(44, 5))
- printf("writable(%s, 0x%x)\n", filename, flags);
+#ifdef SUID_ROOT_FILES_OK
+ /* really ought to be passed down -- and not a good idea */
+ flags |= SFF_ROOTOK;
+#endif
/*
** File does exist -- check that it is writable.
*/
+ if (bitset(0111, stb.st_mode))
+ {
+ if (tTd(29, 5))
+ printf("failed (mode %o: x bits)\n", stb.st_mode);
+ errno = EPERM;
+ return (FALSE);
+ }
+
if (ctladdr != NULL && geteuid() == 0)
{
euid = ctladdr->q_uid;
egid = ctladdr->q_gid;
uname = ctladdr->q_user;
}
- else if (bitset(SFF_RUNASREALUID, flags))
+ else
{
euid = RealUid;
egid = RealGid;
uname = RealUserName;
}
- else if (FileMailer != NULL && !bitset(SFF_ROOTOK, flags))
+ if (euid == 0)
{
- euid = FileMailer->m_uid;
- egid = FileMailer->m_gid;
- uname = NULL;
- }
- else
- {
- euid = egid = 0;
- uname = NULL;
+ euid = DefUid;
+ uname = DefUser;
}
- if (!bitset(SFF_ROOTOK, flags))
+ if (egid == 0)
+ egid = DefGid;
+ if (geteuid() == 0)
{
- if (euid == 0)
+ if (bitset(S_ISUID, stb.st_mode) &&
+ (stb.st_uid != 0 || bitset(SFF_ROOTOK, flags)))
{
- euid = DefUid;
- uname = DefUser;
+ euid = stb.st_uid;
+ uname = NULL;
}
- if (egid == 0)
- egid = DefGid;
+ if (bitset(S_ISGID, stb.st_mode) &&
+ (stb.st_gid != 0 || bitset(SFF_ROOTOK, flags)))
+ egid = stb.st_gid;
}
- if (geteuid() == 0 &&
- (ctladdr == NULL || !bitset(QGOODUID, ctladdr->q_flags)))
- flags |= SFF_SETUIDOK;
- errno = safefile(filename, euid, egid, uname, flags, S_IWRITE, NULL);
+ if (tTd(29, 5))
+ printf("\teu/gid=%d/%d, st_u/gid=%d/%d\n",
+ euid, egid, stb.st_uid, stb.st_gid);
+
+ errno = safefile(filename, euid, egid, uname, flags, S_IWRITE);
return errno == 0;
}
/*
@@ -854,8 +730,6 @@ writable(filename, ctladdr, flags)
** the important things.
** sendq -- a pointer to the head of the send queue
** to put these addresses in.
-** aliaslevel -- the alias nesting depth.
-** e -- the current envelope.
**
** Returns:
** open error status
@@ -879,29 +753,32 @@ writable(filename, ctladdr, flags)
*/
static jmp_buf CtxIncludeTimeout;
-static void includetimeout();
+static int includetimeout();
+
+#ifndef S_IWOTH
+# define S_IWOTH (S_IWRITE >> 6)
+#endif
int
-include(fname, forwarding, ctladdr, sendq, aliaslevel, e)
+include(fname, forwarding, ctladdr, sendq, e)
char *fname;
bool forwarding;
ADDRESS *ctladdr;
ADDRESS **sendq;
- int aliaslevel;
ENVELOPE *e;
{
- FILE *volatile fp = NULL;
+ register FILE *fp = NULL;
char *oldto = e->e_to;
char *oldfilename = FileName;
int oldlinenumber = LineNumber;
register EVENT *ev = NULL;
int nincludes;
register ADDRESS *ca;
- volatile uid_t saveduid, uid;
- volatile gid_t savedgid, gid;
- char *volatile uname;
+ uid_t saveduid, uid;
+ gid_t savedgid, gid;
+ char *uname;
int rval = 0;
- int sfflags = SFF_REGONLY;
+ int sfflags = forwarding ? SFF_MUSTOWN : SFF_ANYFILE;
struct stat st;
char buf[MAXLINE];
#ifdef _POSIX_CHOWN_RESTRICTED
@@ -936,47 +813,30 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e)
if (tTd(27, 9))
printf("include: old uid = %d/%d\n", getuid(), geteuid());
- if (forwarding)
- sfflags |= SFF_MUSTOWN|SFF_ROOTOK|SFF_NOSLINK;
-
ca = getctladdr(ctladdr);
if (ca == NULL)
{
uid = DefUid;
gid = DefGid;
uname = DefUser;
+ saveduid = -1;
}
else
{
uid = ca->q_uid;
gid = ca->q_gid;
uname = ca->q_user;
- }
-#if HASSETREUID || USESETEUID
- saveduid = geteuid();
- savedgid = getegid();
- if (saveduid == 0)
- {
- if (!DontInitGroups)
- initgroups(uname, gid);
- if (gid != 0)
- (void) setgid(gid);
- if (uid != 0)
+#ifdef HASSETREUID
+ saveduid = geteuid();
+ savedgid = getegid();
+ if (saveduid == 0)
{
-# if USESETEUID
- if (seteuid(uid) < 0)
- syserr("seteuid(%d) failure (real=%d, eff=%d)",
- uid, getuid(), geteuid());
-# else
- if (setreuid(0, uid) < 0)
- syserr("setreuid(0, %d) failure (real=%d, eff=%d)",
- uid, getuid(), geteuid());
-# endif
- else
- sfflags |= SFF_NOPATHCHECK;
+ initgroups(uname, gid);
+ if (uid != 0)
+ (void) setreuid(0, uid);
}
- }
#endif
+ }
if (tTd(27, 9))
printf("include: new uid = %d/%d\n", getuid(), geteuid());
@@ -995,13 +855,10 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e)
rval = EOPENTIMEOUT;
goto resetuid;
}
- if (TimeOuts.to_fileopen > 0)
- ev = setevent(TimeOuts.to_fileopen, includetimeout, 0);
- else
- ev = NULL;
+ ev = setevent((time_t) 60, includetimeout, 0);
/* the input file must be marked safe */
- rval = safefile(fname, uid, gid, uname, sfflags, S_IREAD, NULL);
+ rval = safefile(fname, uid, gid, uname, sfflags, S_IREAD);
if (rval != 0)
{
/* don't use this :include: file */
@@ -1019,29 +876,17 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e)
printf("include: open: %s\n", errstring(rval));
}
}
- if (ev != NULL)
- clrevent(ev);
+ clrevent(ev);
resetuid:
-#if HASSETREUID || USESETEUID
+#ifdef HASSETREUID
if (saveduid == 0)
{
if (uid != 0)
- {
-# if USESETEUID
- if (seteuid(0) < 0)
- syserr("seteuid(0) failure (real=%d, eff=%d)",
- getuid(), geteuid());
-# else
- if (setreuid(-1, 0) < 0)
- syserr("setreuid(-1, 0) failure (real=%d, eff=%d)",
- getuid(), geteuid());
- if (setreuid(RealUid, 0) < 0)
+ if (setreuid(-1, 0) < 0 || setreuid(RealUid, 0) < 0)
syserr("setreuid(%d, 0) failure (real=%d, eff=%d)",
RealUid, getuid(), geteuid());
-# endif
- }
setgid(savedgid);
}
#endif
@@ -1079,34 +924,25 @@ resetuid:
}
else
{
+ char *sh;
register struct passwd *pw;
- pw = sm_getpwuid(st.st_uid);
- if (pw == NULL)
- ctladdr->q_flags |= QBOGUSSHELL;
- else
+ sh = "/SENDMAIL/ANY/SHELL/";
+ pw = getpwuid(st.st_uid);
+ if (pw != NULL)
{
- char *sh;
-
ctladdr->q_ruser = newstr(pw->pw_name);
if (safechown)
sh = pw->pw_shell;
+ }
+ if (pw == NULL)
+ ctladdr->q_flags |= QBOGUSSHELL;
+ else if(!usershellok(sh))
+ {
+ if (safechown)
+ ctladdr->q_flags |= QBOGUSSHELL;
else
- sh = "/SENDMAIL/ANY/SHELL/";
- if (!usershellok(pw->pw_name, sh))
- {
-#ifdef LOG
- if (LogLevel >= 12)
- syslog(LOG_INFO, "%s: user %s has bad shell %s, marked %s",
- shortenstring(fname, 203),
- pw->pw_name, sh,
- safechown ? "bogus" : "unsafe");
-#endif
- if (safechown)
- ctladdr->q_flags |= QBOGUSSHELL;
- else
- ctladdr->q_flags |= QUNSAFEADDR;
- }
+ ctladdr->q_flags |= QUNSAFEADDR;
}
}
@@ -1130,15 +966,7 @@ resetuid:
*/
if (bitset(S_IWOTH, st.st_mode))
- {
-#ifdef LOG
- if (LogLevel >= 12)
- syslog(LOG_INFO, "%s: world writable %s file, marked unsafe",
- shortenstring(fname, 203),
- forwarding ? "forward" : ":include:");
-#endif
ctladdr->q_flags |= QUNSAFEADDR;
- }
/* read the file -- each line is a comma-separated list. */
FileName = fname;
@@ -1154,33 +982,19 @@ resetuid:
*p = '\0';
if (buf[0] == '#' || buf[0] == '\0')
continue;
-
- /* <sp>#@# introduces a comment anywhere */
- /* for Japanese character sets */
- for (p = buf; (p = strchr(++p, '#')) != NULL; )
- {
- if (p[1] == '@' && p[2] == '#' &&
- isascii(p[-1]) && isspace(p[-1]) &&
- (p[3] == '\0' || (isascii(p[3]) && isspace(p[3]))))
- {
- p[-1] = '\0';
- break;
- }
- }
- if (buf[0] == '\0')
- continue;
-
e->e_to = NULL;
message("%s to %s",
forwarding ? "forwarding" : "sending", buf);
#ifdef LOG
if (forwarding && LogLevel > 9)
- syslog(LOG_INFO, "%s: forward %.200s => %s",
+ syslog(LOG_INFO, "%s: forward %s => %s",
e->e_id == NULL ? "NOQUEUE" : e->e_id,
- oldto, shortenstring(buf, 203));
+ oldto, buf);
#endif
- nincludes += sendtolist(buf, ctladdr, sendq, aliaslevel + 1, e);
+ AliasLevel++;
+ nincludes += sendtolist(buf, ctladdr, sendq, e);
+ AliasLevel--;
}
if (ferror(fp) && tTd(27, 3))
@@ -1202,7 +1016,7 @@ resetuid:
return rval;
}
-static void
+static
includetimeout()
{
longjmp(CtxIncludeTimeout, 1);
@@ -1222,7 +1036,6 @@ includetimeout()
** send queue.
*/
-void
sendtoargv(argv, e)
register char **argv;
register ENVELOPE *e;
@@ -1231,7 +1044,7 @@ sendtoargv(argv, e)
while ((p = *argv++) != NULL)
{
- (void) sendtolist(p, NULLADDR, &e->e_sendqueue, 0, e);
+ (void) sendtolist(p, NULLADDR, &e->e_sendqueue, e);
}
}
/*
@@ -1257,93 +1070,3 @@ getctladdr(a)
a = a->q_alias;
return (a);
}
- /*
-** SELF_REFERENCE -- check to see if an address references itself
-**
-** The check is done through a chain of aliases. If it is part of
-** a loop, break the loop at the "best" address, that is, the one
-** that exists as a real user.
-**
-** This is to handle the case of:
-** awc: Andrew.Chang
-** Andrew.Chang: awc@mail.server
-** which is a problem only on mail.server.
-**
-** Parameters:
-** a -- the address to check.
-** e -- the current envelope.
-**
-** Returns:
-** The address that should be retained.
-*/
-
-ADDRESS *
-self_reference(a, e)
- ADDRESS *a;
- ENVELOPE *e;
-{
- ADDRESS *b; /* top entry in self ref loop */
- ADDRESS *c; /* entry that point to a real mail box */
-
- if (tTd(27, 1))
- printf("self_reference(%s)\n", a->q_paddr);
-
- for (b = a->q_alias; b != NULL; b = b->q_alias)
- {
- if (sameaddr(a, b))
- break;
- }
-
- if (b == NULL)
- {
- if (tTd(27, 1))
- printf("\t... no self ref\n");
- return NULL;
- }
-
- /*
- ** Pick the first address that resolved to a real mail box
- ** i.e has a pw entry. The returned value will be marked
- ** QSELFREF in recipient(), which in turn will disable alias()
- ** from marking it QDONTSEND, which mean it will be used
- ** as a deliverable address.
- **
- ** The 2 key thing to note here are:
- ** 1) we are in a recursive call sequence:
- ** alias->sentolist->recipient->alias
- ** 2) normally, when we return back to alias(), the address
- ** will be marked QDONTSEND, since alias() assumes the
- ** expanded form will be used instead of the current address.
- ** This behaviour is turned off if the address is marked
- ** QSELFREF We set QSELFREF when we return to recipient().
- */
-
- c = a;
- while (c != NULL)
- {
- if (bitnset(M_HASPWENT, c->q_mailer->m_flags))
- {
- if (tTd(27, 2))
- printf("\t... getpwnam(%s)... ", c->q_user);
- if (sm_getpwnam(c->q_user) != NULL)
- {
- if (tTd(27, 2))
- printf("found\n");
-
- /* ought to cache results here */
- if (sameaddr(b, c))
- return b;
- else
- return c;
- }
- if (tTd(27, 2))
- printf("failed\n");
- }
- c = c->q_alias;
- }
-
- if (tTd(27, 1))
- printf("\t... cannot break loop for \"%s\"\n", a->q_paddr);
-
- return NULL;
-}
OpenPOWER on IntegriCloud