diff options
Diffstat (limited to 'usr.sbin/sendmail/src/recipient.c')
-rw-r--r-- | usr.sbin/sendmail/src/recipient.c | 615 |
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; -} |