2 * Copyright (c) 1998 Sendmail, Inc. All rights reserved.
3 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
7 * By using this file, you agree to the terms and conditions set
8 * forth in the LICENSE file which can be found at the top level of
9 * the sendmail distribution.
14 static char sccsid[] = "@(#)recipient.c 8.163 (Berkeley) 1/23/1999";
17 # include "sendmail.h"
21 ** SENDTOLIST -- Designate a send list.
23 ** The parameter is a comma-separated list of people to send to.
24 ** This routine arranges to send to all of them.
27 ** list -- the send list.
28 ** ctladdr -- the address template for the person to
29 ** send to -- effective uid/gid are important.
30 ** This is typically the alias that caused this
32 ** sendq -- a pointer to the head of a queue to put
34 ** aliaslevel -- the current alias nesting depth -- to
36 ** e -- the envelope in which to add these recipients.
39 ** The number of addresses actually on the list.
45 /* q_flags bits inherited from ctladdr */
46 #define QINHERITEDBITS (QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY|QHASNOTIFY)
49 sendtolist(list, ctladdr, sendq, aliaslevel, e)
57 register ADDRESS *al; /* list of addresses to send to */
58 char delimiter; /* the address delimiter */
61 char *oldto = e->e_to;
63 char buf[MAXNAME + 1];
67 syserr("sendtolist: null list");
73 printf("sendto: %s\n ctladdr=", list);
74 printaddr(ctladdr, FALSE);
77 /* heuristic to determine old versus new style addresses */
78 if (ctladdr == NULL &&
79 (strchr(list, ',') != NULL || strchr(list, ';') != NULL ||
80 strchr(list, '<') != NULL || strchr(list, '(') != NULL))
81 e->e_flags &= ~EF_OLDSTYLE;
83 if (!bitset(EF_OLDSTYLE, e->e_flags) || ctladdr != NULL)
89 /* make sure we have enough space to copy the string */
95 strcpy(bufp, denlstring(list, FALSE, TRUE));
97 for (p = bufp; *p != '\0'; )
102 /* parse the address */
103 while ((isascii(*p) && isspace(*p)) || *p == ',')
105 a = parseaddr(p, NULLADDR, RF_COPYALL, delimiter, &delimptr, e);
110 a->q_alias = ctladdr;
112 /* arrange to inherit attributes from parent */
116 extern ADDRESS *self_reference __P((ADDRESS *, ENVELOPE *));
118 /* self reference test */
119 if (sameaddr(ctladdr, a))
123 printf("sendtolist: QSELFREF ");
124 printaddr(ctladdr, FALSE);
126 ctladdr->q_flags |= QSELFREF;
129 /* check for address loops */
130 b = self_reference(a, e);
133 b->q_flags |= QSELFREF;
136 printf("sendtolist: QSELFREF ");
143 printf("sendtolist: QDONTSEND ");
146 a->q_flags |= QDONTSEND;
147 b->q_flags |= a->q_flags & QNOTREMOTE;
153 if (a->q_fullname == NULL)
154 a->q_fullname = ctladdr->q_fullname;
156 /* various flag bits */
157 a->q_flags &= ~QINHERITEDBITS;
158 a->q_flags |= ctladdr->q_flags & QINHERITEDBITS;
160 /* original recipient information */
161 a->q_orcpt = ctladdr->q_orcpt;
167 /* arrange to send to everyone on the local send list */
170 register ADDRESS *a = al;
173 a = recipient(a, sendq, aliaslevel, e);
183 ** RECIPIENT -- Designate a message recipient
185 ** Saves the named person for future mailing.
188 ** a -- the (preparsed) address header for the recipient.
189 ** sendq -- a pointer to the head of a queue to put the
190 ** recipient in. Duplicate supression is done
192 ** aliaslevel -- the current alias nesting depth.
193 ** e -- the current envelope.
196 ** The actual address in the queue. This will be "a" if
197 ** the address is not a duplicate, else the original address.
204 recipient(a, sendq, aliaslevel, e)
206 register ADDRESS **sendq;
208 register ENVELOPE *e;
212 register struct mailer *m;
214 bool quoted = FALSE; /* set if the addr has a quote bit */
215 int findusercount = 0;
216 bool initialdontsend = bitset(QDONTSEND, a->q_flags);
219 char buf0[MAXNAME + 1]; /* unquoted image of the user name */
220 extern void alias __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
222 e->e_to = a->q_paddr;
226 a->q_flags |= QPRIMARY;
229 printf("\nrecipient (%d): ", aliaslevel);
233 /* if this is primary, add it to the original recipient list */
234 if (a->q_alias == NULL)
236 if (e->e_origrcpt == NULL)
237 e->e_origrcpt = a->q_paddr;
238 else if (e->e_origrcpt != a->q_paddr)
242 /* break aliasing loops */
243 if (aliaslevel > MaxAliasRecursion)
245 a->q_flags |= QBADADDR;
246 a->q_status = "5.4.6";
247 usrerr("554 aliasing/forwarding loop broken (%d aliases deep; %d max)",
248 aliaslevel, MaxAliasRecursion);
253 ** Finish setting up address structure.
256 /* get unquoted user for file, program or user.name check */
257 i = strlen(a->q_user);
258 if (i >= sizeof buf0)
262 (void) strcpy(buf, a->q_user);
263 for (p = buf; *p != '\0' && !quoted; p++)
270 /* check for direct mailing to restricted mailers */
273 if (a->q_alias == NULL)
275 a->q_flags |= QBADADDR;
276 a->q_status = "5.7.1";
277 usrerr("550 Cannot mail directly to programs");
279 else if (bitset(QBOGUSSHELL, a->q_alias->q_flags))
281 a->q_flags |= QBADADDR;
282 a->q_status = "5.7.1";
283 if (a->q_alias->q_ruser == NULL)
284 usrerr("550 UID %d is an unknown user: cannot mail to programs",
287 usrerr("550 User %s@%s doesn't have a valid shell for mailing to programs",
288 a->q_alias->q_ruser, MyHostName);
290 else if (bitset(QUNSAFEADDR, a->q_alias->q_flags))
292 a->q_flags |= QBADADDR;
293 a->q_status = "5.7.1";
294 a->q_rstatus = newstr("Unsafe for mailing to programs");
295 usrerr("550 Address %s is unsafe for mailing to programs",
296 a->q_alias->q_paddr);
301 ** Look up this person in the recipient list.
302 ** If they are there already, return, otherwise continue.
303 ** If the list is empty, just add it. Notice the cute
304 ** hack to make from addresses suppress things correctly:
305 ** the QDONTSEND bit will be set in the send list.
306 ** [Please note: the emphasis is on "hack."]
309 for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next)
311 if (sameaddr(q, a) &&
312 (bitset(QRCPTOK, q->q_flags) ||
313 !bitset(QPRIMARY, q->q_flags)))
317 printf("%s in sendq: ", a->q_paddr);
320 if (!bitset(QPRIMARY, q->q_flags))
322 if (!bitset(QDONTSEND, a->q_flags))
323 message("duplicate suppressed");
324 q->q_flags |= a->q_flags;
326 else if (bitset(QSELFREF, q->q_flags))
327 q->q_flags |= a->q_flags & ~QDONTSEND;
333 /* add address on list */
341 ** Alias the name and handle special mailer types.
347 printf("at trylocaluser: ");
351 if (bitset(QDONTSEND|QBADADDR|QVERIFIED, a->q_flags))
352 goto testselfdestruct;
356 a->q_flags |= QDONTSEND;
357 if (a->q_alias == NULL)
359 a->q_flags |= QBADADDR;
360 a->q_status = "5.7.1";
361 usrerr("550 Cannot mail directly to :include:s");
367 message("including file %s", a->q_user);
368 ret = include(a->q_user, FALSE, a, sendq, aliaslevel, e);
369 if (transienterror(ret))
372 sm_syslog(LOG_ERR, e->e_id,
373 "include %s: transient error: %s",
374 shortenstring(a->q_user, MAXSHORTSTR),
376 a->q_flags |= QQUEUEUP;
377 a->q_flags &= ~QDONTSEND;
378 usrerr("451 Cannot open %s: %s",
379 shortenstring(a->q_user, MAXSHORTSTR),
384 a->q_flags |= QBADADDR;
385 a->q_status = "5.2.4";
386 usrerr("550 Cannot open %s: %s",
387 shortenstring(a->q_user, MAXSHORTSTR),
392 else if (m == FileMailer)
394 extern bool writable __P((char *, ADDRESS *, int));
396 /* check if writable or creatable */
397 if (a->q_alias == NULL)
399 a->q_flags |= QBADADDR;
400 a->q_status = "5.7.1";
401 usrerr("550 Cannot mail directly to files");
403 else if (bitset(QBOGUSSHELL, a->q_alias->q_flags))
405 a->q_flags |= QBADADDR;
406 a->q_status = "5.7.1";
407 if (a->q_alias->q_ruser == NULL)
408 usrerr("550 UID %d is an unknown user: cannot mail to files",
411 usrerr("550 User %s@%s doesn't have a valid shell for mailing to files",
412 a->q_alias->q_ruser, MyHostName);
414 else if (bitset(QUNSAFEADDR, a->q_alias->q_flags))
416 a->q_flags |= QBADADDR;
417 a->q_status = "5.7.1";
418 a->q_rstatus = newstr("Unsafe for mailing to files");
419 usrerr("550 Address %s is unsafe for mailing to files",
420 a->q_alias->q_paddr);
422 else if (strcmp(buf, "/dev/null") == 0)
424 /* /dev/null is always accepted */
426 else if (!writable(buf, a->q_alias, SFF_CREAT))
428 a->q_flags |= QBADADDR;
429 giveresponse(EX_CANTCREAT, m, NULL, a->q_alias,
435 if (!quoted && !bitset(QDONTSEND, a->q_flags) &&
436 bitnset(M_ALIASABLE, m->m_flags))
437 alias(a, sendq, aliaslevel, e);
440 /* if not aliased, look it up in the user database */
441 if (!bitset(QDONTSEND|QNOTREMOTE|QVERIFIED, a->q_flags) &&
442 bitnset(M_CHECKUDB, m->m_flags))
444 extern int udbexpand __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
446 if (udbexpand(a, sendq, aliaslevel, e) == EX_TEMPFAIL)
448 a->q_flags |= QQUEUEUP;
449 if (e->e_message == NULL)
450 e->e_message = newstr("Deferred: user database error");
452 sm_syslog(LOG_INFO, e->e_id,
453 "deferred: udbexpand: %s",
455 message("queued (user database error): %s",
458 goto testselfdestruct;
464 ** If we have a level two config file, then pass the name through
465 ** Ruleset 5 before sending it off. Ruleset 5 has the right
466 ** to send rewrite it to another mailer. This gives us a hook
467 ** after local aliasing has been done.
472 printf("recipient: testing local? cl=%d, rr5=%lx\n\t",
473 ConfigLevel, (u_long) RewriteRules[5]);
476 if (!bitset(QNOTREMOTE|QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags) &&
477 ConfigLevel >= 2 && RewriteRules[5] != NULL &&
478 bitnset(M_TRYRULESET5, m->m_flags))
480 extern void maplocaluser __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
482 maplocaluser(a, sendq, aliaslevel + 1, e);
486 ** If it didn't get rewritten to another mailer, go ahead
490 if (!bitset(QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags) &&
491 bitnset(M_HASPWENT, m->m_flags))
494 register struct passwd *pw;
495 extern void forward __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
497 /* warning -- finduser may trash buf */
498 pw = finduser(buf, &fuzzy);
499 if (pw == NULL || strlen(pw->pw_name) > MAXNAME)
501 a->q_flags |= QBADADDR;
502 a->q_status = "5.1.1";
503 giveresponse(EX_NOUSER, m, NULL, a->q_alias,
508 char nbuf[MAXNAME + 1];
512 /* name was a fuzzy match */
513 a->q_user = newstr(pw->pw_name);
514 if (findusercount++ > 3)
516 a->q_flags |= QBADADDR;
517 a->q_status = "5.4.6";
518 usrerr("554 aliasing/forwarding loop for %s broken",
523 /* see if it aliases */
524 (void) strcpy(buf, pw->pw_name);
527 if (strcmp(pw->pw_dir, "/") == 0)
530 a->q_home = newstr(pw->pw_dir);
531 a->q_uid = pw->pw_uid;
532 a->q_gid = pw->pw_gid;
533 a->q_ruser = newstr(pw->pw_name);
534 a->q_flags |= QGOODUID;
535 buildfname(pw->pw_gecos, pw->pw_name, nbuf, sizeof nbuf);
537 a->q_fullname = newstr(nbuf);
538 if (!usershellok(pw->pw_name, pw->pw_shell))
540 a->q_flags |= QBOGUSSHELL;
542 if (bitset(EF_VRFYONLY, e->e_flags))
544 /* don't do any more now */
545 a->q_flags |= QVERIFIED;
548 forward(a, sendq, aliaslevel, e);
551 if (!bitset(QDONTSEND, a->q_flags))
555 a->q_flags |= QTHISPASS;
558 printf("testselfdestruct: ");
563 printaddr(*sendq, TRUE);
567 if (a->q_alias == NULL && a != &e->e_from &&
568 bitset(QDONTSEND, a->q_flags))
570 for (q = *sendq; q != NULL; q = q->q_next)
572 if (!bitset(QDONTSEND, q->q_flags))
577 a->q_flags |= QBADADDR;
578 a->q_status = "5.4.6";
579 usrerr("554 aliasing/forwarding loop broken");
584 a->q_flags |= QTHISPASS;
589 ** If we are at the top level, check to see if this has
590 ** expanded to exactly one address. If so, it can inherit
591 ** the primaryness of the address.
593 ** While we're at it, clear the QTHISPASS bits.
599 ADDRESS *only = NULL;
601 for (q = *sendq; q != NULL; q = q->q_next)
603 if (bitset(QTHISPASS, q->q_flags) &&
604 !bitset(QDONTSEND|QBADADDR, q->q_flags))
609 q->q_flags &= ~QTHISPASS;
613 /* check to see if this actually got a new owner */
615 while ((q = q->q_alias) != NULL)
617 if (q->q_owner != NULL)
621 only->q_flags |= QPRIMARY;
623 else if (!initialdontsend && nrcpts > 0)
625 /* arrange for return receipt */
626 e->e_flags |= EF_SENDRECEIPT;
627 a->q_flags |= QEXPANDED;
628 if (e->e_xfp != NULL && bitset(QPINGONSUCCESS, a->q_flags))
630 "%s... expanded to multiple addresses\n",
634 a->q_flags |= QRCPTOK;
638 ** FINDUSER -- find the password entry for a user.
640 ** This looks a lot like getpwnam, except that it may want to
641 ** do some fancier pattern matching in /etc/passwd.
643 ** This routine contains most of the time of many sendmail runs.
644 ** It deserves to be optimized.
647 ** name -- the name to match against.
648 ** fuzzyp -- an outarg that is set to TRUE if this entry
649 ** was found using the fuzzy matching algorithm;
650 ** set to FALSE otherwise.
653 ** A pointer to a pw struct.
654 ** NULL if name is unknown or ambiguous.
661 finduser(name, fuzzyp)
665 register struct passwd *pw;
670 printf("finduser(%s): ", name);
675 /* DEC Hesiod getpwnam accepts numeric strings -- short circuit it */
676 for (p = name; *p != '\0'; p++)
677 if (!isascii(*p) || !isdigit(*p))
682 printf("failed (numeric input)\n");
687 /* look up this login name using fast path */
688 if ((pw = sm_getpwnam(name)) != NULL)
691 printf("found (non-fuzzy)\n");
695 /* try mapping it to lower case */
697 for (p = name; *p != '\0'; p++)
699 if (isascii(*p) && isupper(*p))
705 if (tryagain && (pw = sm_getpwnam(name)) != NULL)
708 printf("found (lower case)\n");
714 /* see if fuzzy matching allowed */
718 printf("not found (fuzzy disabled)\n");
722 /* search for a matching full name instead */
723 for (p = name; *p != '\0'; p++)
725 if (*p == (SpaceSub & 0177) || *p == '_')
729 while ((pw = getpwent()) != NULL)
731 char buf[MAXNAME + 1];
734 if (strcasecmp(pw->pw_name, name) == 0)
737 printf("found (case wrapped)\n");
742 buildfname(pw->pw_gecos, pw->pw_name, buf, sizeof buf);
743 if (strchr(buf, ' ') != NULL && !strcasecmp(buf, name))
746 printf("fuzzy matches %s\n", pw->pw_name);
747 message("sending to login name %s", pw->pw_name);
754 printf("no fuzzy match found\n");
755 # if DEC_OSF_BROKEN_GETPWENT /* DEC OSF/1 3.2 or earlier */
761 printf("not found (fuzzy disabled)\n");
766 ** WRITABLE -- predicate returning if the file is writable.
768 ** This routine must duplicate the algorithm in sys/fio.c.
769 ** Unfortunately, we cannot use the access call since we
770 ** won't necessarily be the real uid when we try to
771 ** actually open the file.
773 ** Notice that ANY file with ANY execute bit is automatically
774 ** not writable. This is also enforced by mailfile.
777 ** filename -- the file name to check.
778 ** ctladdr -- the controlling address for this file.
779 ** flags -- SFF_* flags to control the function.
782 ** TRUE -- if we will be able to write this file.
783 ** FALSE -- if we cannot write this file.
790 writable(filename, ctladdr, flags)
800 printf("writable(%s, 0x%x)\n", filename, flags);
803 ** File does exist -- check that it is writable.
812 else if (ctladdr != NULL)
814 euid = ctladdr->q_uid;
815 egid = ctladdr->q_gid;
816 uname = ctladdr->q_user;
818 else if (bitset(SFF_RUNASREALUID, flags))
822 uname = RealUserName;
824 else if (FileMailer != NULL && !bitset(SFF_ROOTOK, flags))
826 euid = FileMailer->m_uid;
827 egid = FileMailer->m_gid;
835 if (!bitset(SFF_ROOTOK, flags))
845 if (geteuid() == 0 &&
846 (ctladdr == NULL || !bitset(QGOODUID, ctladdr->q_flags)))
847 flags |= SFF_SETUIDOK;
849 if (!bitset(DBS_FILEDELIVERYTOSYMLINK, DontBlameSendmail))
850 flags |= SFF_NOSLINK;
851 if (!bitset(DBS_FILEDELIVERYTOHARDLINK, DontBlameSendmail))
852 flags |= SFF_NOHLINK;
854 errno = safefile(filename, euid, egid, uname, flags, S_IWRITE, NULL);
858 ** INCLUDE -- handle :include: specification.
861 ** fname -- filename to include.
862 ** forwarding -- if TRUE, we are reading a .forward file.
863 ** if FALSE, it's a :include: file.
864 ** ctladdr -- address template to use to fill in these
865 ** addresses -- effective user/group id are
866 ** the important things.
867 ** sendq -- a pointer to the head of the send queue
868 ** to put these addresses in.
869 ** aliaslevel -- the alias nesting depth.
870 ** e -- the current envelope.
876 ** reads the :include: file and sends to everyone
877 ** listed in that file.
880 ** If you have restricted chown (that is, you can't
881 ** give a file away), it is reasonable to allow programs
882 ** and files called from this :include: file to be to be
883 ** run as the owner of the :include: file. This is bogus
884 ** if there is any chance of someone giving away a file.
885 ** We assume that pre-POSIX systems can give away files.
887 ** There is an additional restriction that if you
888 ** forward to a :include: file, it will not take on
889 ** the ownership of the :include: file. This may not
890 ** be necessary, but shouldn't hurt.
893 static jmp_buf CtxIncludeTimeout;
894 static void includetimeout __P((void));
897 include(fname, forwarding, ctladdr, sendq, aliaslevel, e)
905 FILE *volatile fp = NULL;
906 char *oldto = e->e_to;
907 char *oldfilename = FileName;
908 int oldlinenumber = LineNumber;
909 register EVENT *ev = NULL;
912 register ADDRESS *ca;
913 volatile uid_t saveduid, uid;
914 volatile gid_t savedgid, gid;
915 char *volatile uname;
917 volatile int sfflags = SFF_REGONLY;
919 bool safechown = FALSE;
920 volatile bool safedir = FALSE;
923 extern bool chownsafe __P((int, bool));
926 printf("include(%s)\n", fname);
928 printf(" ruid=%d euid=%d\n", (int) getuid(), (int) geteuid());
932 printaddr(ctladdr, FALSE);
936 printf("include: old uid = %d/%d\n",
937 (int) getuid(), (int) geteuid());
940 sfflags |= SFF_MUSTOWN|SFF_ROOTOK|SFF_NOWLINK;
942 ca = getctladdr(ctladdr);
955 #if HASSETREUID || USESETEUID
956 saveduid = geteuid();
957 savedgid = getegid();
962 if (initgroups(uname, gid) == -1)
963 syserr("include: initgroups(%s, %d) failed",
971 if (setgroups(1, gidset) == -1)
972 syserr("include: setgroups() failed");
975 if (gid != 0 && setgid(gid) < -1)
976 syserr("setgid(%d) failure", gid);
980 if (seteuid(uid) < 0)
981 syserr("seteuid(%d) failure (real=%d, eff=%d)",
982 uid, getuid(), geteuid());
984 if (setreuid(0, uid) < 0)
985 syserr("setreuid(0, %d) failure (real=%d, eff=%d)",
986 uid, getuid(), geteuid());
993 printf("include: new uid = %d/%d\n",
994 (int) getuid(), (int) geteuid());
997 ** If home directory is remote mounted but server is down,
998 ** this can hang or give errors; use a timeout to avoid this
1001 if (setjmp(CtxIncludeTimeout) != 0)
1003 ctladdr->q_flags |= QQUEUEUP;
1006 /* return pseudo-error code */
1007 rval = E_SM_OPENTIMEOUT;
1010 if (TimeOuts.to_fileopen > 0)
1011 ev = setevent(TimeOuts.to_fileopen, includetimeout, 0);
1015 /* check for writable parent directory */
1016 p = strrchr(fname, '/');
1022 ret = safedirpath(fname, uid, gid, uname, sfflags|SFF_SAFEDIRPATH);
1025 /* in safe directory: relax chown & link rules */
1027 sfflags |= SFF_NOPATHCHECK;
1031 if (bitset((forwarding ?
1032 DBS_FORWARDFILEINUNSAFEDIRPATH :
1033 DBS_INCLUDEFILEINUNSAFEDIRPATH),
1035 sfflags |= SFF_NOPATHCHECK;
1036 else if (bitset((forwarding ?
1037 DBS_FORWARDFILEINGROUPWRITABLEDIRPATH :
1038 DBS_INCLUDEFILEINGROUPWRITABLEDIRPATH),
1039 DontBlameSendmail) &&
1042 DontBlameSendmail |= DBS_GROUPWRITABLEDIRPATHSAFE;
1043 ret = safedirpath(fname, uid,
1045 sfflags|SFF_SAFEDIRPATH);
1046 DontBlameSendmail &= ~DBS_GROUPWRITABLEDIRPATHSAFE;
1048 sfflags |= SFF_NOPATHCHECK;
1050 sfflags |= SFF_SAFEDIRPATH;
1053 sfflags |= SFF_SAFEDIRPATH;
1054 if (ret > E_PSEUDOBASE &&
1055 !bitset((forwarding ?
1056 DBS_FORWARDFILEINUNSAFEDIRPATHSAFE :
1057 DBS_INCLUDEFILEINUNSAFEDIRPATHSAFE),
1061 sm_syslog(LOG_INFO, e->e_id,
1062 "%s: unsafe directory path, marked unsafe",
1063 shortenstring(fname, MAXSHORTSTR));
1064 ctladdr->q_flags |= QUNSAFEADDR;
1070 /* allow links only in unwritable directories */
1072 !bitset((forwarding ?
1073 DBS_LINKEDFORWARDFILEINWRITABLEDIR :
1074 DBS_LINKEDINCLUDEFILEINWRITABLEDIR),
1076 sfflags |= SFF_NOLINK;
1078 rval = safefile(fname, uid, gid, uname, sfflags, S_IREAD, &st);
1081 /* don't use this :include: file */
1083 printf("include: not safe (uid=%d): %s\n",
1084 (int) uid, errstring(rval));
1086 else if ((fp = fopen(fname, "r")) == NULL)
1090 printf("include: open: %s\n", errstring(rval));
1092 else if (filechanged(fname, fileno(fp), &st))
1094 rval = E_SM_FILECHANGE;
1096 printf("include: file changed after open\n");
1103 #if HASSETREUID || USESETEUID
1110 syserr("seteuid(0) failure (real=%d, eff=%d)",
1111 getuid(), geteuid());
1113 if (setreuid(-1, 0) < 0)
1114 syserr("setreuid(-1, 0) failure (real=%d, eff=%d)",
1115 getuid(), geteuid());
1116 if (setreuid(RealUid, 0) < 0)
1117 syserr("setreuid(%d, 0) failure (real=%d, eff=%d)",
1118 RealUid, getuid(), geteuid());
1126 printf("include: reset uid = %d/%d\n",
1127 (int) getuid(), (int) geteuid());
1129 if (rval == E_SM_OPENTIMEOUT)
1130 usrerr("451 open timeout on %s", fname);
1135 if (fstat(fileno(fp), &st) < 0)
1138 syserr("Cannot fstat %s!", fname);
1142 /* if path was writable, check to avoid file giveaway tricks */
1143 safechown = chownsafe(fileno(fp), safedir);
1145 printf("include: parent of %s is %s, chown is %ssafe\n",
1147 safedir ? "safe" : "dangerous",
1148 safechown ? "" : "un");
1150 if (ca == NULL && safechown)
1152 ctladdr->q_uid = st.st_uid;
1153 ctladdr->q_gid = st.st_gid;
1154 ctladdr->q_flags |= QGOODUID;
1156 if (ca != NULL && ca->q_uid == st.st_uid)
1158 /* optimization -- avoid getpwuid if we already have info */
1159 ctladdr->q_flags |= ca->q_flags & QBOGUSSHELL;
1160 ctladdr->q_ruser = ca->q_ruser;
1162 else if (!forwarding)
1164 register struct passwd *pw;
1166 pw = sm_getpwuid(st.st_uid);
1168 ctladdr->q_flags |= QBOGUSSHELL;
1173 ctladdr->q_ruser = newstr(pw->pw_name);
1177 sh = "/SENDMAIL/ANY/SHELL/";
1178 if (!usershellok(pw->pw_name, sh))
1181 sm_syslog(LOG_INFO, e->e_id,
1182 "%s: user %s has bad shell %s, marked %s",
1183 shortenstring(fname, MAXSHORTSTR),
1185 safechown ? "bogus" : "unsafe");
1187 ctladdr->q_flags |= QBOGUSSHELL;
1189 ctladdr->q_flags |= QUNSAFEADDR;
1194 if (bitset(EF_VRFYONLY, e->e_flags))
1196 /* don't do any more now */
1197 ctladdr->q_flags |= QVERIFIED;
1198 ctladdr->q_flags &= ~QDONTSEND;
1200 xfclose(fp, "include", fname);
1205 ** Check to see if some bad guy can write this file
1207 ** Group write checking could be more clever, e.g.,
1208 ** guessing as to which groups are actually safe ("sys"
1209 ** may be; "user" probably is not).
1213 if (!bitset((forwarding ?
1214 DBS_GROUPWRITABLEFORWARDFILESAFE :
1215 DBS_GROUPWRITABLEINCLUDEFILESAFE),
1219 if (bitset(mode, st.st_mode))
1222 printf("include: %s is %s writable, marked unsafe\n",
1223 shortenstring(fname, MAXSHORTSTR),
1224 bitset(S_IWOTH, st.st_mode) ? "world" : "group");
1226 sm_syslog(LOG_INFO, e->e_id,
1227 "%s: %s writable %s file, marked unsafe",
1228 shortenstring(fname, MAXSHORTSTR),
1229 bitset(S_IWOTH, st.st_mode) ? "world" : "group",
1230 forwarding ? "forward" : ":include:");
1231 ctladdr->q_flags |= QUNSAFEADDR;
1234 /* read the file -- each line is a comma-separated list. */
1237 ctladdr->q_flags &= ~QSELFREF;
1239 while (fgets(buf, sizeof buf, fp) != NULL)
1241 register char *p = strchr(buf, '\n');
1246 if (buf[0] == '#' || buf[0] == '\0')
1249 /* <sp>#@# introduces a comment anywhere */
1250 /* for Japanese character sets */
1251 for (p = buf; (p = strchr(++p, '#')) != NULL; )
1253 if (p[1] == '@' && p[2] == '#' &&
1254 isascii(p[-1]) && isspace(p[-1]) &&
1255 (p[3] == '\0' || (isascii(p[3]) && isspace(p[3]))))
1266 forwarding ? "forwarding" : "sending", buf);
1267 if (forwarding && LogLevel > 9)
1268 sm_syslog(LOG_INFO, e->e_id,
1269 "forward %.200s => %s",
1270 oldto, shortenstring(buf, MAXSHORTSTR));
1272 nincludes += sendtolist(buf, ctladdr, sendq, aliaslevel + 1, e);
1275 if (ferror(fp) && tTd(27, 3))
1276 printf("include: read error: %s\n", errstring(errno));
1277 if (nincludes > 0 && !bitset(QSELFREF, ctladdr->q_flags))
1281 printf("include: QDONTSEND ");
1282 printaddr(ctladdr, FALSE);
1284 ctladdr->q_flags |= QDONTSEND;
1287 (void) xfclose(fp, "include", fname);
1288 FileName = oldfilename;
1289 LineNumber = oldlinenumber;
1297 longjmp(CtxIncludeTimeout, 1);
1300 ** SENDTOARGV -- send to an argument vector.
1303 ** argv -- argument vector to send to.
1304 ** e -- the current envelope.
1310 ** puts all addresses on the argument vector onto the
1316 register char **argv;
1317 register ENVELOPE *e;
1321 while ((p = *argv++) != NULL)
1323 (void) sendtolist(p, NULLADDR, &e->e_sendqueue, 0, e);
1327 ** GETCTLADDR -- get controlling address from an address header.
1329 ** If none, get one corresponding to the effective userid.
1332 ** a -- the address to find the controller of.
1335 ** the controlling address.
1343 register ADDRESS *a;
1345 while (a != NULL && !bitset(QGOODUID, a->q_flags))
1350 ** SELF_REFERENCE -- check to see if an address references itself
1352 ** The check is done through a chain of aliases. If it is part of
1353 ** a loop, break the loop at the "best" address, that is, the one
1354 ** that exists as a real user.
1356 ** This is to handle the case of:
1357 ** awc: Andrew.Chang
1358 ** Andrew.Chang: awc@mail.server
1359 ** which is a problem only on mail.server.
1362 ** a -- the address to check.
1363 ** e -- the current envelope.
1366 ** The address that should be retained.
1370 self_reference(a, e)
1374 ADDRESS *b; /* top entry in self ref loop */
1375 ADDRESS *c; /* entry that point to a real mail box */
1378 printf("self_reference(%s)\n", a->q_paddr);
1380 for (b = a->q_alias; b != NULL; b = b->q_alias)
1389 printf("\t... no self ref\n");
1394 ** Pick the first address that resolved to a real mail box
1395 ** i.e has a pw entry. The returned value will be marked
1396 ** QSELFREF in recipient(), which in turn will disable alias()
1397 ** from marking it QDONTSEND, which mean it will be used
1398 ** as a deliverable address.
1400 ** The 2 key thing to note here are:
1401 ** 1) we are in a recursive call sequence:
1402 ** alias->sentolist->recipient->alias
1403 ** 2) normally, when we return back to alias(), the address
1404 ** will be marked QDONTSEND, since alias() assumes the
1405 ** expanded form will be used instead of the current address.
1406 ** This behaviour is turned off if the address is marked
1407 ** QSELFREF We set QSELFREF when we return to recipient().
1414 printf(" %s", c->q_user);
1415 if (bitnset(M_HASPWENT, c->q_mailer->m_flags))
1418 printf("\t... getpwnam(%s)... ", c->q_user);
1419 if (sm_getpwnam(c->q_user) != NULL)
1424 /* ought to cache results here */
1435 /* if local delivery, compare usernames */
1436 if (bitnset(M_LOCALMAILER, c->q_mailer->m_flags) &&
1437 b->q_mailer == c->q_mailer)
1440 printf("\t... local match (%s)\n", c->q_user);
1453 printf("\t... cannot break loop for \"%s\"\n", a->q_paddr);