From 1bf7c76b40e92b86de386d5d731bd80a765a85f9 Mon Sep 17 00:00:00 2001 From: Eric Allman Date: Wed, 16 Sep 1981 23:08:24 -0800 Subject: [PATCH] run as the user forwarding mail after a .forward operation; fix a bug in .forwarding that caused recursive expansion; restrict mail to programs, files, and with :include: for security reasons. SCCS-vsn: usr.sbin/sendmail/src/alias.c 3.22 SCCS-vsn: usr.sbin/sendmail/src/deliver.c 3.39 SCCS-vsn: usr.sbin/sendmail/src/sendmail.h 3.42 SCCS-vsn: usr.sbin/sendmail/src/savemail.c 3.18 SCCS-vsn: usr.sbin/sendmail/src/version.c 3.29 SCCS-vsn: usr.sbin/sendmail/src/main.c 3.37 SCCS-vsn: usr.sbin/sendmail/src/headers.c 3.8 SCCS-vsn: usr.sbin/sendmail/src/recipient.c 3.17 --- usr/src/usr.sbin/sendmail/src/alias.c | 8 +-- usr/src/usr.sbin/sendmail/src/deliver.c | 34 +++++++--- usr/src/usr.sbin/sendmail/src/headers.c | 4 +- usr/src/usr.sbin/sendmail/src/main.c | 7 ++- usr/src/usr.sbin/sendmail/src/recipient.c | 75 +++++++++++++++++++---- usr/src/usr.sbin/sendmail/src/savemail.c | 4 +- usr/src/usr.sbin/sendmail/src/sendmail.h | 4 +- usr/src/usr.sbin/sendmail/src/version.c | 4 +- 8 files changed, 106 insertions(+), 34 deletions(-) diff --git a/usr/src/usr.sbin/sendmail/src/alias.c b/usr/src/usr.sbin/sendmail/src/alias.c index f79cec8a4c..d52ffa3c08 100644 --- a/usr/src/usr.sbin/sendmail/src/alias.c +++ b/usr/src/usr.sbin/sendmail/src/alias.c @@ -4,9 +4,9 @@ # include "sendmail.h" # ifdef DBM -static char SccsId[] = "@(#)alias.c 3.21 %G% (with DBM)"; +static char SccsId[] = "@(#)alias.c 3.22 %G% (with DBM)"; # else DBM -static char SccsId[] = "@(#)alias.c 3.21 %G% (without DBM)"; +static char SccsId[] = "@(#)alias.c 3.22 %G% (without DBM)"; # endif DBM /* @@ -113,7 +113,7 @@ alias(a) message(Arpa_Info, "aliased to %s", p); a->q_flags |= QDONTSEND; AliasLevel++; - sendto(p, 1); + sendto(p, 1, a); AliasLevel--; } /* @@ -452,5 +452,5 @@ forward(user) /* we do have an address to forward to -- do it */ user->q_flags |= QDONTSEND; - include(buf, "forwarding"); + include(buf, "forwarding", user); } diff --git a/usr/src/usr.sbin/sendmail/src/deliver.c b/usr/src/usr.sbin/sendmail/src/deliver.c index f8dae595d3..c48b708a9f 100644 --- a/usr/src/usr.sbin/sendmail/src/deliver.c +++ b/usr/src/usr.sbin/sendmail/src/deliver.c @@ -7,7 +7,7 @@ # include # endif LOG -static char SccsId[] = "@(#)deliver.c 3.38 %G%"; +static char SccsId[] = "@(#)deliver.c 3.39 %G%"; /* ** DELIVER -- Deliver a message to a list of addresses. @@ -49,6 +49,8 @@ deliver(to, editfcn) char *pv[MAXPV+1]; char tobuf[MAXLINE]; char buf[MAXNAME]; + ADDRESS *ctladdr; + extern ADDRESS *getctladdr(); if (!ForceMail && bitset(QDONTSEND, to->q_flags)) return (0); @@ -124,6 +126,7 @@ deliver(to, editfcn) tobuf[0] = '\0'; To = tobuf; + ctladdr = NULL; for (; to != NULL; to = to->q_next) { /* avoid sending multiple recipients to dumb mailers */ @@ -134,6 +137,11 @@ deliver(to, editfcn) if ((!ForceMail && bitset(QDONTSEND, to->q_flags)) || strcmp(to->q_host, host) != 0) continue; + + /* compute effective uid/gid when sending */ + if (to->q_mailer == MN_PROG) + ctladdr = getctladdr(to); + user = to->q_user; To = to->q_paddr; to->q_flags |= QDONTSEND; @@ -199,7 +207,7 @@ deliver(to, editfcn) { if (index(user, '/') != NULL) { - i = mailfile(user); + i = mailfile(user, getctladdr(to)); giveresponse(i, TRUE, m); continue; } @@ -256,7 +264,9 @@ deliver(to, editfcn) if (editfcn == NULL) editfcn = putmessage; - i = sendoff(m, pv, editfcn); + if (ctladdr == NULL) + ctladdr = &From; + i = sendoff(m, pv, editfcn, ctladdr); return (i); } @@ -308,6 +318,8 @@ deliver(to, editfcn) ** m -- mailer descriptor. ** pvp -- parameter vector to send to it. ** editfcn -- function to pipe it through. +** ctladdr -- an address pointer controlling the +** user/groupid etc. of the mailer. ** ** Returns: ** exit status of mailer. @@ -316,10 +328,11 @@ deliver(to, editfcn) ** none. */ -sendoff(m, pvp, editfcn) +sendoff(m, pvp, editfcn, ctladdr) struct mailer *m; char **pvp; int (*editfcn)(); + ADDRESS *ctladdr; { auto int st; register int i; @@ -371,8 +384,8 @@ sendoff(m, pvp, editfcn) (void) close(pvect[1]); if (!bitset(M_RESTR, m->m_flags)) { - (void) setuid(getuid()); - (void) setgid(getgid()); + (void) setuid(ctladdr->q_uid); + (void) setgid(ctladdr->q_gid); } # ifndef VFORK /* @@ -660,6 +673,8 @@ samefrom(ifrom, efrom) ** ** Parameters: ** filename -- the name of the file to send to. +** ctladdr -- the controlling address header -- includes +** the userid/groupid to be when sending. ** ** Returns: ** The exit code associated with the operation. @@ -668,8 +683,9 @@ samefrom(ifrom, efrom) ** none. */ -mailfile(filename) +mailfile(filename, ctladdr) char *filename; + ADDRESS *ctladdr; { register FILE *f; register int pid; @@ -698,9 +714,9 @@ mailfile(filename) if (bitset(0111, stb.st_mode)) exit(EX_CANTCREAT); if (!bitset(S_ISGID, stb.st_mode) || setgid(stb.st_gid) < 0) - (void) setgid(getgid()); + (void) setgid(ctladdr->q_gid); if (!bitset(S_ISUID, stb.st_mode) || setuid(stb.st_uid) < 0) - (void) setuid(getuid()); + (void) setuid(ctladdr->q_uid); f = fopen(filename, "a"); if (f == NULL) exit(EX_CANTCREAT); diff --git a/usr/src/usr.sbin/sendmail/src/headers.c b/usr/src/usr.sbin/sendmail/src/headers.c index 840124f709..17a47923c6 100644 --- a/usr/src/usr.sbin/sendmail/src/headers.c +++ b/usr/src/usr.sbin/sendmail/src/headers.c @@ -1,7 +1,7 @@ # include # include "sendmail.h" -static char SccsId[] = "@(#)headers.c 3.7 %G%"; +static char SccsId[] = "@(#)headers.c 3.8 %G%"; /* ** CHOMPHEADER -- process and save a header line. @@ -95,7 +95,7 @@ chompheader(line, def) free(h->h_value); h->h_value = newstr(fvalue); if (!def && GrabTo && bitset(H_ADDR, h->h_flags)) - sendto(h->h_value, 0); + sendto(h->h_value, 0, &From); return (h->h_flags); } diff --git a/usr/src/usr.sbin/sendmail/src/main.c b/usr/src/usr.sbin/sendmail/src/main.c index 124784ddfe..1b50051833 100644 --- a/usr/src/usr.sbin/sendmail/src/main.c +++ b/usr/src/usr.sbin/sendmail/src/main.c @@ -6,7 +6,7 @@ # include # endif LOG -static char SccsId[] = "@(#)main.c 3.36 %G%"; +static char SccsId[] = "@(#)main.c 3.37 %G%"; /* ** SENDMAIL -- Post mail to a set of destinations. @@ -642,6 +642,11 @@ setfrom(from, realname) else FromFlag = TRUE; SuprErrs = FALSE; + From.q_uid = getuid(); + From.q_gid = getgid(); +# ifndef V6 + From.q_home = getenv("HOME"); +# endif V6 /* ** Rewrite the from person to dispose of possible implicit diff --git a/usr/src/usr.sbin/sendmail/src/recipient.c b/usr/src/usr.sbin/sendmail/src/recipient.c index acece92306..267dc1af03 100644 --- a/usr/src/usr.sbin/sendmail/src/recipient.c +++ b/usr/src/usr.sbin/sendmail/src/recipient.c @@ -3,7 +3,7 @@ # include # include "sendmail.h" -static char SccsId[] = "@(#)recipient.c 3.16 %G%"; +static char SccsId[] = "@(#)recipient.c 3.17 %G%"; /* ** SENDTO -- Designate a send list. @@ -14,6 +14,8 @@ static char SccsId[] = "@(#)recipient.c 3.16 %G%"; ** Parameters: ** list -- the send list. ** copyf -- the copy flag; passed to parse. +** ctladdr -- the address template for the person to +** send to -- effective uid/gid are important. ** ** Returns: ** none @@ -24,9 +26,10 @@ static char SccsId[] = "@(#)recipient.c 3.16 %G%"; # define MAXRCRSN 10 -sendto(list, copyf) +sendto(list, copyf, ctladdr) char *list; int copyf; + ADDRESS *ctladdr; { register char *p; bool more; /* set if more addresses to send to */ @@ -64,6 +67,7 @@ sendto(list, copyf) /* put it on the local send list */ a->q_next = al; + a->q_alias = ctladdr; al = a; } @@ -99,6 +103,7 @@ recipient(a) register ADDRESS *q; ADDRESS **pq; register struct mailer *m; + extern ADDRESS *getctladdr(); To = a->q_paddr; m = Mailer[a->q_mailer]; @@ -126,13 +131,11 @@ recipient(a) a->q_mailer = MN_PROG; m = Mailer[MN_PROG]; a->q_user++; -# ifdef PARANOID - if (AliasLevel <= 0) + if (getctladdr(a) == &From && Debug == 0) { usrerr("Cannot mail directly to programs"); a->q_flags |= QDONTSEND; } -# endif PARANOID } } @@ -171,9 +174,14 @@ recipient(a) if (strncmp(a->q_user, ":include:", 9) == 0) { a->q_flags |= QDONTSEND; - if (Verbose) - message(Arpa_Info, "including file %s", &a->q_user[9]); - include(&a->q_user[9], " sending"); + if (getctladdr(a) == &From && Debug == 0) + usrerr("Cannot mail directly to :include:s"); + else + { + if (Verbose) + message(Arpa_Info, "including file %s", &a->q_user[9]); + include(&a->q_user[9], " sending", a); + } } else alias(a); @@ -193,15 +201,26 @@ recipient(a) register char *p; struct stat stb; extern bool writable(); + bool quoted = FALSE; strcpy(buf, a->q_user); + for (p = buf; *p != '\0' && !quoted; p++) + { + if (!isascii(*p)) + quoted = TRUE; + } stripquotes(buf, TRUE); /* see if this is to a file */ if ((p = rindex(buf, '/')) != NULL) { /* check if writable or creatable */ - if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) : + if (getctladdr(a) == &From && Debug == 0) + { + usrerr("Cannot mail directly to files"); + a->q_flags |= QDONTSEND; + } + else if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) : (*p = '\0', access(buf, 3) < 0)) { a->q_flags |= QBADADDR; @@ -228,7 +247,8 @@ recipient(a) } a->q_home = newstr(pw->pw_dir); a->q_uid = pw->pw_uid; - if (strcmp(buf, a->q_user) == 0) + a->q_gid = pw->pw_gid; + if (!quoted) forward(a); } } @@ -343,6 +363,9 @@ writable(s) ** Parameters: ** fname -- filename to include. ** msg -- message to print in verbose mode. +** ctladdr -- address template to use to fill in these +** addresses -- effective user/group id are +** the important things. ** ** Returns: ** none. @@ -352,9 +375,10 @@ writable(s) ** listed in that file. */ -include(fname, msg) +include(fname, msg, ctladdr) char *fname; char *msg; + ADDRESS *ctladdr; { char buf[MAXLINE]; register FILE *fp; @@ -380,7 +404,7 @@ include(fname, msg) if (Verbose) message(Arpa_Info, "%s to %s", msg, buf); AliasLevel++; - sendto(buf, 1); + sendto(buf, 1, ctladdr); AliasLevel--; } @@ -423,6 +447,31 @@ sendtoargv(argv) argv += 2; } } - sendto(p, 0); + sendto(p, 0, &From); } } + /* +** GETCTLADDR -- get controlling address from an address header. +** +** If none, get one corresponding to the effective userid. +** +** Parameters: +** a -- the address to find the controller of. +** +** Returns: +** the controlling address. +** +** Side Effects: +** none. +*/ + +ADDRESS * +getctladdr(a) + register ADDRESS *a; +{ + while (a != NULL && a->q_home == NULL) + a = a->q_alias; + if (a == NULL) + return (&From); + return (a); +} diff --git a/usr/src/usr.sbin/sendmail/src/savemail.c b/usr/src/usr.sbin/sendmail/src/savemail.c index 85b2ccd681..98fc380cf9 100644 --- a/usr/src/usr.sbin/sendmail/src/savemail.c +++ b/usr/src/usr.sbin/sendmail/src/savemail.c @@ -1,7 +1,7 @@ # include # include "sendmail.h" -static char SccsId[] = "@(#)savemail.c 3.17 %G%"; +static char SccsId[] = "@(#)savemail.c 3.18 %G%"; /* ** SAVEMAIL -- Save mail on error @@ -169,7 +169,7 @@ savemail() define('z', p); (void) expand("$z/dead.letter", buf, &buf[sizeof buf - 1]); To = buf; - i = mailfile(buf); + i = mailfile(buf, &From); giveresponse(i, TRUE, Mailer[MN_LOCAL]); } diff --git a/usr/src/usr.sbin/sendmail/src/sendmail.h b/usr/src/usr.sbin/sendmail/src/sendmail.h index d45d34a04c..25bcd2676b 100644 --- a/usr/src/usr.sbin/sendmail/src/sendmail.h +++ b/usr/src/usr.sbin/sendmail/src/sendmail.h @@ -1,7 +1,7 @@ /* ** SENDMAIL.H -- Global definitions for sendmail. ** -** @(#)sendmail.h 3.41 %G% +** @(#)sendmail.h 3.42 %G% */ @@ -57,8 +57,10 @@ struct address short q_rmailer; /* real mailer (before mapping) */ u_short q_flags; /* status flags, see below */ short q_uid; /* user-id of receiver (if known) */ + short q_gid; /* group-id of receiver (if known) */ char *q_home; /* home dir (local mailer only) */ struct address *q_next; /* chain */ + struct address *q_alias; /* address this results from */ }; typedef struct address ADDRESS; diff --git a/usr/src/usr.sbin/sendmail/src/version.c b/usr/src/usr.sbin/sendmail/src/version.c index 6e77376cdb..8725fd1d31 100644 --- a/usr/src/usr.sbin/sendmail/src/version.c +++ b/usr/src/usr.sbin/sendmail/src/version.c @@ -1,3 +1,3 @@ -static char SccsId[] = "@(#)SendMail version 3.28 of %G%"; +static char SccsId[] = "@(#)SendMail version 3.29 of %G%"; -char Version[] = "3.28 [%G%]"; +char Version[] = "3.29 [%G%]"; -- 2.20.1