diff options
Diffstat (limited to 'src/recipient.c')
-rw-r--r-- | src/recipient.c | 193 |
1 files changed, 135 insertions, 58 deletions
diff --git a/src/recipient.c b/src/recipient.c index adcce7a..f7e221f 100644 --- a/src/recipient.c +++ b/src/recipient.c @@ -1,42 +1,21 @@ /* - * 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 sccsid[] = "@(#)recipient.c 8.133 (Berkeley) 10/19/97"; +static char sccsid[] = "@(#)recipient.c 8.163 (Berkeley) 1/23/1999"; #endif /* not lint */ # include "sendmail.h" +# include <grp.h> /* ** SENDTOLIST -- Designate a send list. @@ -134,7 +113,7 @@ sendtolist(list, ctladdr, sendq, aliaslevel, e) if (ctladdr != NULL) { ADDRESS *b; - extern ADDRESS *self_reference(); + extern ADDRESS *self_reference __P((ADDRESS *, ENVELOPE *)); /* self reference test */ if (sameaddr(ctladdr, a)) @@ -312,6 +291,7 @@ recipient(a, sendq, aliaslevel, e) { a->q_flags |= QBADADDR; a->q_status = "5.7.1"; + a->q_rstatus = newstr("Unsafe for mailing to programs"); usrerr("550 Address %s is unsafe for mailing to programs", a->q_alias->q_paddr); } @@ -328,7 +308,9 @@ recipient(a, sendq, aliaslevel, e) for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next) { - if (sameaddr(q, a) && bitset(QRCPTOK, q->q_flags)) + if (sameaddr(q, a) && + (bitset(QRCPTOK, q->q_flags) || + !bitset(QPRIMARY, q->q_flags))) { if (tTd(26, 1)) { @@ -349,8 +331,11 @@ recipient(a, sendq, aliaslevel, e) } /* add address on list */ - *pq = a; - a->q_next = NULL; + if (pq != NULL) + { + *pq = a; + a->q_next = NULL; + } /* ** Alias the name and handle special mailer types. @@ -358,7 +343,10 @@ recipient(a, sendq, aliaslevel, e) trylocaluser: if (tTd(29, 7)) - printf("at trylocaluser %s\n", a->q_user); + { + printf("at trylocaluser: "); + printaddr(a, FALSE); + } if (bitset(QDONTSEND|QBADADDR|QVERIFIED, a->q_flags)) goto testselfdestruct; @@ -383,12 +371,12 @@ recipient(a, sendq, aliaslevel, e) if (LogLevel > 2) sm_syslog(LOG_ERR, e->e_id, "include %s: transient error: %s", - shortenstring(a->q_user, 203), + shortenstring(a->q_user, MAXSHORTSTR), errstring(ret)); a->q_flags |= QQUEUEUP; a->q_flags &= ~QDONTSEND; usrerr("451 Cannot open %s: %s", - shortenstring(a->q_user, 203), + shortenstring(a->q_user, MAXSHORTSTR), errstring(ret)); } else if (ret != 0) @@ -396,14 +384,14 @@ recipient(a, sendq, aliaslevel, e) a->q_flags |= QBADADDR; a->q_status = "5.2.4"; usrerr("550 Cannot open %s: %s", - shortenstring(a->q_user, 203), + shortenstring(a->q_user, MAXSHORTSTR), errstring(ret)); } } } else if (m == FileMailer) { - extern bool writable(); + extern bool writable __P((char *, ADDRESS *, int)); /* check if writable or creatable */ if (a->q_alias == NULL) @@ -427,6 +415,7 @@ recipient(a, sendq, aliaslevel, e) { a->q_flags |= QBADADDR; a->q_status = "5.7.1"; + a->q_rstatus = newstr("Unsafe for mailing to files"); usrerr("550 Address %s is unsafe for mailing to files", a->q_alias->q_paddr); } @@ -452,7 +441,7 @@ recipient(a, sendq, aliaslevel, e) if (!bitset(QDONTSEND|QNOTREMOTE|QVERIFIED, a->q_flags) && bitnset(M_CHECKUDB, m->m_flags)) { - extern int udbexpand(); + extern int udbexpand __P((ADDRESS *, ADDRESS **, int, ENVELOPE *)); if (udbexpand(a, sendq, aliaslevel, e) == EX_TEMPFAIL) { @@ -856,7 +845,11 @@ writable(filename, ctladdr, flags) if (geteuid() == 0 && (ctladdr == NULL || !bitset(QGOODUID, ctladdr->q_flags))) flags |= SFF_SETUIDOK; - flags |= SFF_NOLINK; + + if (!bitset(DBS_FILEDELIVERYTOSYMLINK, DontBlameSendmail)) + flags |= SFF_NOSLINK; + if (!bitset(DBS_FILEDELIVERYTOHARDLINK, DontBlameSendmail)) + flags |= SFF_NOHLINK; errno = safefile(filename, euid, egid, uname, flags, S_IWRITE, NULL); return errno == 0; @@ -898,7 +891,7 @@ writable(filename, ctladdr, flags) */ static jmp_buf CtxIncludeTimeout; -static void includetimeout(); +static void includetimeout __P((void)); int include(fname, forwarding, ctladdr, sendq, aliaslevel, e) @@ -915,6 +908,7 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e) int oldlinenumber = LineNumber; register EVENT *ev = NULL; int nincludes; + int mode; register ADDRESS *ca; volatile uid_t saveduid, uid; volatile gid_t savedgid, gid; @@ -926,7 +920,7 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e) volatile bool safedir = FALSE; struct stat st; char buf[MAXLINE]; - extern bool chownsafe(); + extern bool chownsafe __P((int, bool)); if (tTd(27, 2)) printf("include(%s)\n", fname); @@ -943,7 +937,7 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e) (int) getuid(), (int) geteuid()); if (forwarding) - sfflags |= SFF_MUSTOWN|SFF_ROOTOK|SFF_NOSLINK; + sfflags |= SFF_MUSTOWN|SFF_ROOTOK|SFF_NOWLINK; ca = getctladdr(ctladdr); if (ca == NULL) @@ -964,9 +958,22 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e) if (saveduid == 0) { if (!DontInitGroups) - initgroups(uname, gid); - if (gid != 0) - (void) setgid(gid); + { + if (initgroups(uname, gid) == -1) + syserr("include: initgroups(%s, %d) failed", + uname, gid); + } + else + { + GIDSET_T gidset[1]; + + gidset[0] = gid; + if (setgroups(1, gidset) == -1) + syserr("include: setgroups() failed"); + } + + if (gid != 0 && setgid(gid) < -1) + syserr("setgid(%d) failure", gid); if (uid != 0) { # if USESETEUID @@ -978,8 +985,6 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e) syserr("setreuid(0, %d) failure (real=%d, eff=%d)", uid, getuid(), geteuid()); # endif - else - sfflags |= SFF_NOPATHCHECK; } } #endif @@ -1011,18 +1016,63 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e) p = strrchr(fname, '/'); if (p != NULL) { + int ret; + *p = '\0'; - if (safedirpath(fname, uid, gid, uname, sfflags|SFF_SAFEDIRPATH) == 0) + ret = safedirpath(fname, uid, gid, uname, sfflags|SFF_SAFEDIRPATH); + if (ret == 0) { /* in safe directory: relax chown & link rules */ safedir = TRUE; sfflags |= SFF_NOPATHCHECK; } + else + { + if (bitset((forwarding ? + DBS_FORWARDFILEINUNSAFEDIRPATH : + DBS_INCLUDEFILEINUNSAFEDIRPATH), + DontBlameSendmail)) + sfflags |= SFF_NOPATHCHECK; + else if (bitset((forwarding ? + DBS_FORWARDFILEINGROUPWRITABLEDIRPATH : + DBS_INCLUDEFILEINGROUPWRITABLEDIRPATH), + DontBlameSendmail) && + ret == E_SM_GWDIR) + { + DontBlameSendmail |= DBS_GROUPWRITABLEDIRPATHSAFE; + ret = safedirpath(fname, uid, + gid, uname, + sfflags|SFF_SAFEDIRPATH); + DontBlameSendmail &= ~DBS_GROUPWRITABLEDIRPATHSAFE; + if (ret == 0) + sfflags |= SFF_NOPATHCHECK; + else + sfflags |= SFF_SAFEDIRPATH; + } + else + sfflags |= SFF_SAFEDIRPATH; + if (ret > E_PSEUDOBASE && + !bitset((forwarding ? + DBS_FORWARDFILEINUNSAFEDIRPATHSAFE : + DBS_INCLUDEFILEINUNSAFEDIRPATHSAFE), + DontBlameSendmail)) + { + if (LogLevel >= 12) + sm_syslog(LOG_INFO, e->e_id, + "%s: unsafe directory path, marked unsafe", + shortenstring(fname, MAXSHORTSTR)); + ctladdr->q_flags |= QUNSAFEADDR; + } + } *p = '/'; } /* allow links only in unwritable directories */ - if (!safedir) + if (!safedir && + !bitset((forwarding ? + DBS_LINKEDFORWARDFILEINWRITABLEDIR : + DBS_LINKEDINCLUDEFILEINWRITABLEDIR), + DontBlameSendmail)) sfflags |= SFF_NOLINK; rval = safefile(fname, uid, gid, uname, sfflags, S_IREAD, &st); @@ -1039,7 +1089,7 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e) if (tTd(27, 4)) printf("include: open: %s\n", errstring(rval)); } - else if (filechanged(fname, fileno(fp), &st, sfflags)) + else if (filechanged(fname, fileno(fp), &st)) { rval = E_SM_FILECHANGE; if (tTd(27, 4)) @@ -1130,7 +1180,7 @@ resetuid: if (LogLevel >= 12) sm_syslog(LOG_INFO, e->e_id, "%s: user %s has bad shell %s, marked %s", - shortenstring(fname, 203), + shortenstring(fname, MAXSHORTSTR), pw->pw_name, sh, safechown ? "bogus" : "unsafe"); if (safechown) @@ -1145,28 +1195,37 @@ resetuid: { /* don't do any more now */ ctladdr->q_flags |= QVERIFIED; + ctladdr->q_flags &= ~QDONTSEND; e->e_nrcpts++; xfclose(fp, "include", fname); return rval; } /* - ** Check to see if some bad guy can write this file + ** Check to see if some bad guy can write this file ** ** Group write checking could be more clever, e.g., ** guessing as to which groups are actually safe ("sys" ** may be; "user" probably is not). - ** Also, we don't check for writable - ** directories in the path. We've got to leave - ** something for the local sysad to do. */ - if (bitset(S_IWOTH | (UnsafeGroupWrites ? S_IWGRP : 0), st.st_mode)) + mode = S_IWOTH; + if (!bitset((forwarding ? + DBS_GROUPWRITABLEFORWARDFILESAFE : + DBS_GROUPWRITABLEINCLUDEFILESAFE), + DontBlameSendmail)) + mode |= S_IWGRP; + + if (bitset(mode, st.st_mode)) { + if (tTd(27, 6)) + printf("include: %s is %s writable, marked unsafe\n", + shortenstring(fname, MAXSHORTSTR), + bitset(S_IWOTH, st.st_mode) ? "world" : "group"); if (LogLevel >= 12) sm_syslog(LOG_INFO, e->e_id, "%s: %s writable %s file, marked unsafe", - shortenstring(fname, 203), + shortenstring(fname, MAXSHORTSTR), bitset(S_IWOTH, st.st_mode) ? "world" : "group", forwarding ? "forward" : ":include:"); ctladdr->q_flags |= QUNSAFEADDR; @@ -1208,7 +1267,7 @@ resetuid: if (forwarding && LogLevel > 9) sm_syslog(LOG_INFO, e->e_id, "forward %.200s => %s", - oldto, shortenstring(buf, 203)); + oldto, shortenstring(buf, MAXSHORTSTR)); nincludes += sendtolist(buf, ctladdr, sendq, aliaslevel + 1, e); } @@ -1351,6 +1410,8 @@ self_reference(a, e) c = a; while (c != NULL) { + if (tTd(27, 10)) + printf(" %s", c->q_user); if (bitnset(M_HASPWENT, c->q_mailer->m_flags)) { if (tTd(27, 2)) @@ -1369,6 +1430,22 @@ self_reference(a, e) if (tTd(27, 2)) printf("failed\n"); } + else + { + /* if local delivery, compare usernames */ + if (bitnset(M_LOCALMAILER, c->q_mailer->m_flags) && + b->q_mailer == c->q_mailer) + { + if (tTd(27, 2)) + printf("\t... local match (%s)\n", c->q_user); + if (sameaddr(b, c)) + return b; + else + return c; + } + } + if (tTd(27, 10)) + printf("\n"); c = c->q_alias; } |