recipient.c revision 98121
11573Srgrimes/* 210818Sphk * Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers. 310818Sphk * All rights reserved. 410818Sphk * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 510818Sphk * Copyright (c) 1988, 1993 610818Sphk * The Regents of the University of California. All rights reserved. 710818Sphk * 81573Srgrimes * By using this file, you agree to the terms and conditions set 912918Sphk * forth in the LICENSE file which can be found at the top level of 101573Srgrimes * the sendmail distribution. 111573Srgrimes * 121573Srgrimes */ 1310818Sphk 1411338Sphk#include <sendmail.h> 1511338Sphk 1610818SphkSM_RCSID("@(#)$Id: recipient.c,v 8.330 2002/05/29 18:20:03 gshapiro Exp $") 1711665Sphk 181573Srgrimesstatic void includetimeout __P((void)); 191573Srgrimesstatic ADDRESS *self_reference __P((ADDRESS *)); 2012776Speterstatic int sortexpensive __P((ADDRESS *, ADDRESS *)); 2112776Speterstatic int sortbysignature __P((ADDRESS *, ADDRESS *)); 2212776Speterstatic int sorthost __P((ADDRESS *, ADDRESS *)); 2312776Speter 2412776Spetertypedef int sortfn_t __P((ADDRESS *, ADDRESS *)); 2512776Speter 2612776Speter/* 2712776Speter** SORTHOST -- strcmp()-like func for host portion of an ADDRESS 2812776Speter** 2912776Speter** Parameters: 3012776Speter** xx -- first ADDRESS 3111338Sphk** yy -- second ADDRESS 321573Srgrimes** 3311338Sphk** Returns: 341573Srgrimes** <0 when xx->q_host is less than yy->q_host 3510818Sphk** >0 when xx->q_host is greater than yy->q_host 3611338Sphk** 0 when equal 3711338Sphk*/ 3810818Sphk 3910818Sphkstatic int 4010818Sphksorthost(xx, yy) 4110818Sphk register ADDRESS *xx; 4211338Sphk register ADDRESS *yy; 4311338Sphk{ 4410818Sphk#if _FFR_HOST_SORT_REVERSE 4510818Sphk /* XXX maybe compare hostnames from the end? */ 4610818Sphk return sm_strrevcasecmp(xx->q_host, yy->q_host); 471573Srgrimes#else /* _FFR_HOST_SORT_REVERSE */ 481573Srgrimes return sm_strcasecmp(xx->q_host, yy->q_host); 4910818Sphk#endif /* _FFR_HOST_SORT_REVERSE */ 5010818Sphk} 5110818Sphk 5210818Sphk/* 5310818Sphk** SORTEXPENSIVE -- strcmp()-like func for expensive mailers 541573Srgrimes** 5510818Sphk** The mailer has been noted already as "expensive" for 'xx'. This 5611338Sphk** will give a result relative to 'yy'. Expensive mailers get rated 5710818Sphk** "greater than" non-expensive mailers because during the delivery phase 581573Srgrimes** it will get queued -- no use it getting in the way of less expensive 5910818Sphk** recipients. We avoid an MX RR lookup when both 'xx' and 'yy' are 6010818Sphk** expensive since an MX RR lookup happens when extracted from the queue 6110818Sphk** later. 6210818Sphk** 6310818Sphk** Parameters: 6410818Sphk** xx -- first ADDRESS 6510818Sphk** yy -- second ADDRESS 6610818Sphk** 6710818Sphk** Returns: 681573Srgrimes** <0 when xx->q_host is less than yy->q_host and both are 6911338Sphk** expensive 7011338Sphk** >0 when xx->q_host is greater than yy->q_host, or when 7111338Sphk** 'yy' is non-expensive 7211338Sphk** 0 when equal (by expense and q_host) 7310818Sphk*/ 7410818Sphk 7510818Sphkstatic int 7610818Sphksortexpensive(xx, yy) 7710818Sphk ADDRESS *xx; 7810818Sphk ADDRESS *yy; 7910818Sphk{ 8010818Sphk if (!bitnset(M_EXPENSIVE, yy->q_mailer->m_flags)) 811573Srgrimes return 1; /* xx should go later */ 8210818Sphk#if _FFR_HOST_SORT_REVERSE 8310818Sphk /* XXX maybe compare hostnames from the end? */ 841573Srgrimes return sm_strrevcasecmp(xx->q_host, yy->q_host); 8510818Sphk#else /* _FFR_HOST_SORT_REVERSE */ 861573Srgrimes return sm_strcasecmp(xx->q_host, yy->q_host); 8710818Sphk#endif /* _FFR_HOST_SORT_REVERSE */ 8810818Sphk} 8910818Sphk 9010818Sphk/* 9110818Sphk** SORTBYSIGNATURE -- a strcmp()-like func for q_mailer and q_host in ADDRESS 9210818Sphk** 9310818Sphk** Parameters: 9410818Sphk** xx -- first ADDRESS 951573Srgrimes** yy -- second ADDRESS 9610818Sphk** 9710818Sphk** Returns: 9811338Sphk** 0 when the "signature"'s are same 9911338Sphk** <0 when xx->q_signature is less than yy->q_signature 10010818Sphk** >0 when xx->q_signature is greater than yy->q_signature 10110818Sphk** 10210818Sphk** Side Effect: 10310818Sphk** May set ADDRESS pointer for q_signature if not already set. 10410818Sphk*/ 10510818Sphk 10610818Sphkstatic int 10710818Sphksortbysignature(xx, yy) 10810818Sphk ADDRESS *xx; 10910818Sphk ADDRESS *yy; 1101573Srgrimes{ 11110818Sphk register int ret; 11210818Sphk 11310818Sphk /* Let's avoid redoing the signature over and over again */ 11410818Sphk if (xx->q_signature == NULL) 11510818Sphk xx->q_signature = hostsignature(xx->q_mailer, xx->q_host); 11610818Sphk if (yy->q_signature == NULL) 11710818Sphk yy->q_signature = hostsignature(yy->q_mailer, yy->q_host); 11810818Sphk ret = strcmp(xx->q_signature, yy->q_signature); 11910818Sphk 12010818Sphk /* 12110818Sphk ** If the two signatures are the same then we will return a sort 12210818Sphk ** value based on 'q_user'. But note that we have reversed xx and yy 12310818Sphk ** on purpose. This additional compare helps reduce the number of 12410818Sphk ** sameaddr() calls and loops in recipient() for the case when 12510818Sphk ** the rcpt list has been provided already in-order. 12610818Sphk */ 12710818Sphk 12810818Sphk if (ret == 0) 12910818Sphk return strcmp(yy->q_user, xx->q_user); 13010818Sphk else 13110818Sphk return ret; 13210818Sphk} 13310818Sphk 13410818Sphk/* 13510818Sphk** SENDTOLIST -- Designate a send list. 13611338Sphk** 13710818Sphk** The parameter is a comma-separated list of people to send to. 1381573Srgrimes** This routine arranges to send to all of them. 13910818Sphk** 1401573Srgrimes** Parameters: 14110818Sphk** list -- the send list. 1421573Srgrimes** ctladdr -- the address template for the person to 14310818Sphk** send to -- effective uid/gid are important. 14410818Sphk** This is typically the alias that caused this 14510818Sphk** expansion. 14610818Sphk** sendq -- a pointer to the head of a queue to put 14710818Sphk** these people into. 14811338Sphk** aliaslevel -- the current alias nesting depth -- to 14911338Sphk** diagnose loops. 15011338Sphk** e -- the envelope in which to add these recipients. 1511573Srgrimes** 1521573Srgrimes** Returns: 15311338Sphk** The number of addresses actually on the list. 1541573Srgrimes*/ 15511338Sphk 1561573Srgrimes/* q_flags bits inherited from ctladdr */ 15711338Sphk#define QINHERITEDBITS (QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY|QHASNOTIFY) 15811338Sphk 15911338Sphkint 16010818Sphksendtolist(list, ctladdr, sendq, aliaslevel, e) 16110818Sphk char *list; 16210818Sphk ADDRESS *ctladdr; 16310818Sphk ADDRESS **sendq; 16410818Sphk int aliaslevel; 16510818Sphk register ENVELOPE *e; 16610818Sphk{ 16710818Sphk register char *p; 16810818Sphk register ADDRESS *SM_NONVOLATILE al; /* list of addresses to send to */ 16910818Sphk SM_NONVOLATILE char delimiter; /* the address delimiter */ 17010818Sphk SM_NONVOLATILE int naddrs; 17110818Sphk SM_NONVOLATILE int i; 17210818Sphk char *oldto = e->e_to; 17310818Sphk char *SM_NONVOLATILE bufp; 17410818Sphk char buf[MAXNAME + 1]; 17510818Sphk 17610818Sphk if (list == NULL) 17710818Sphk { 17810818Sphk syserr("sendtolist: null list"); 17910818Sphk return 0; 18010818Sphk } 18110818Sphk 18210818Sphk if (tTd(25, 1)) 18310818Sphk { 18411338Sphk sm_dprintf("sendto: %s\n ctladdr=", list); 18511338Sphk printaddr(ctladdr, false); 18611338Sphk } 18710818Sphk 18810818Sphk /* heuristic to determine old versus new style addresses */ 18910818Sphk if (ctladdr == NULL && 19010818Sphk (strchr(list, ',') != NULL || strchr(list, ';') != NULL || 19110818Sphk strchr(list, '<') != NULL || strchr(list, '(') != NULL)) 19210818Sphk e->e_flags &= ~EF_OLDSTYLE; 19310818Sphk delimiter = ' '; 19410818Sphk if (!bitset(EF_OLDSTYLE, e->e_flags) || ctladdr != NULL) 19510818Sphk delimiter = ','; 19610818Sphk 19710818Sphk al = NULL; 19810818Sphk naddrs = 0; 19910818Sphk 20010818Sphk /* make sure we have enough space to copy the string */ 20110818Sphk i = strlen(list) + 1; 20210818Sphk if (i <= sizeof buf) 20310818Sphk { 20410818Sphk bufp = buf; 20510818Sphk i = sizeof buf; 20610818Sphk } 20710818Sphk else 20810818Sphk bufp = sm_malloc_x(i); 20910818Sphk 21010818Sphk SM_TRY 21110818Sphk { 21210818Sphk (void) sm_strlcpy(bufp, denlstring(list, false, true), i); 21311338Sphk 21410818Sphk macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e r"); 21510818Sphk for (p = bufp; *p != '\0'; ) 21610818Sphk { 21710818Sphk auto char *delimptr; 21810818Sphk register ADDRESS *a; 21910818Sphk 22010818Sphk /* parse the address */ 22110818Sphk while ((isascii(*p) && isspace(*p)) || *p == ',') 22210818Sphk p++; 22310818Sphk a = parseaddr(p, NULLADDR, RF_COPYALL, delimiter, 22410818Sphk &delimptr, e, true); 22510818Sphk p = delimptr; 22610818Sphk if (a == NULL) 22712776Speter continue; 22810818Sphk a->q_next = al; 22910818Sphk a->q_alias = ctladdr; 23010818Sphk 23110818Sphk /* arrange to inherit attributes from parent */ 23212776Speter if (ctladdr != NULL) 23310818Sphk { 23410818Sphk ADDRESS *b; 23510818Sphk 23610818Sphk /* self reference test */ 23710818Sphk if (sameaddr(ctladdr, a)) 23810818Sphk { 23910818Sphk if (tTd(27, 5)) 24011338Sphk { 24111338Sphk sm_dprintf("sendtolist: QSELFREF "); 24211338Sphk printaddr(ctladdr, false); 24311338Sphk } 24411338Sphk ctladdr->q_flags |= QSELFREF; 24511338Sphk } 24611338Sphk 24711338Sphk /* check for address loops */ 24811338Sphk b = self_reference(a); 24911338Sphk if (b != NULL) 25010818Sphk { 25110818Sphk b->q_flags |= QSELFREF; 25210818Sphk if (tTd(27, 5)) 25310818Sphk { 25410818Sphk sm_dprintf("sendtolist: QSELFREF "); 25510818Sphk printaddr(b, false); 25610818Sphk } 25710818Sphk if (a != b) 25810818Sphk { 25911338Sphk if (tTd(27, 5)) 26011338Sphk { 26111338Sphk sm_dprintf("sendtolist: QS_DONTSEND "); 26211338Sphk printaddr(a, false); 26310818Sphk } 26412776Speter a->q_state = QS_DONTSEND; 26510818Sphk b->q_flags |= a->q_flags & QNOTREMOTE; 26610818Sphk continue; 2671573Srgrimes } 26810818Sphk } 26910818Sphk 27010818Sphk /* full name */ 27110818Sphk if (a->q_fullname == NULL) 27210818Sphk a->q_fullname = ctladdr->q_fullname; 27310818Sphk 27410818Sphk /* various flag bits */ 27510818Sphk a->q_flags &= ~QINHERITEDBITS; 27610818Sphk a->q_flags |= ctladdr->q_flags & QINHERITEDBITS; 27710818Sphk 27810818Sphk /* DSN recipient information */ 27910818Sphk a->q_finalrcpt = ctladdr->q_finalrcpt; 28010818Sphk a->q_orcpt = ctladdr->q_orcpt; 28110818Sphk } 28210818Sphk 28310818Sphk al = a; 28410818Sphk } 28510818Sphk 28610818Sphk /* arrange to send to everyone on the local send list */ 28710818Sphk while (al != NULL) 28810818Sphk { 28910818Sphk register ADDRESS *a = al; 29010818Sphk 29110818Sphk al = a->q_next; 29210818Sphk a = recipient(a, sendq, aliaslevel, e); 29310818Sphk naddrs++; 29410818Sphk } 29510818Sphk } 29611338Sphk SM_FINALLY 29710818Sphk { 29810818Sphk e->e_to = oldto; 29910818Sphk if (bufp != buf) 30010818Sphk sm_free(bufp); 30110818Sphk macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL); 30210818Sphk } 30310818Sphk SM_END_TRY 30410818Sphk return naddrs; 30510818Sphk} 30610818Sphk#if MILTER 30710818Sphk/* 30810818Sphk** REMOVEFROMLIST -- Remove addresses from a send list. 30910818Sphk** 31010818Sphk** The parameter is a comma-separated list of recipients to remove. 31110818Sphk** Note that it only deletes matching addresses. If those addresses 31210818Sphk** have been expanded already in the sendq, it won't mark the 31310818Sphk** expanded recipients as QS_REMOVED. 31410818Sphk** 31510818Sphk** Parameters: 31610818Sphk** list -- the list to remove. 31710818Sphk** sendq -- a pointer to the head of a queue to remove 31810818Sphk** these addresses from. 31910818Sphk** e -- the envelope in which to remove these recipients. 32012776Speter** 32110818Sphk** Returns: 32210818Sphk** The number of addresses removed from the list. 32310818Sphk** 32410818Sphk*/ 32511338Sphk 32610818Sphkint 32710818Sphkremovefromlist(list, sendq, e) 32810818Sphk char *list; 32912776Speter ADDRESS **sendq; 33011338Sphk ENVELOPE *e; 33111338Sphk{ 33212776Speter SM_NONVOLATILE char delimiter; /* the address delimiter */ 33310818Sphk SM_NONVOLATILE int naddrs; 33410818Sphk SM_NONVOLATILE int i; 33510818Sphk char *p; 33610818Sphk char *oldto = e->e_to; 33710818Sphk char *SM_NONVOLATILE bufp; 33810818Sphk char buf[MAXNAME + 1]; 33911338Sphk 34011338Sphk if (list == NULL) 34111338Sphk { 34210818Sphk syserr("removefromlist: null list"); 34310818Sphk return 0; 3441573Srgrimes } 34510818Sphk 34611338Sphk if (tTd(25, 1)) 34710818Sphk sm_dprintf("removefromlist: %s\n", list); 34810818Sphk 34910818Sphk /* heuristic to determine old versus new style addresses */ 35010818Sphk if (strchr(list, ',') != NULL || strchr(list, ';') != NULL || 35110952Sphk strchr(list, '<') != NULL || strchr(list, '(') != NULL) 35210952Sphk e->e_flags &= ~EF_OLDSTYLE; 35310818Sphk delimiter = ' '; 35410952Sphk if (!bitset(EF_OLDSTYLE, e->e_flags)) 35510952Sphk delimiter = ','; 35610952Sphk 35710818Sphk naddrs = 0; 35811338Sphk 35910818Sphk /* make sure we have enough space to copy the string */ 36010818Sphk i = strlen(list) + 1; 36110818Sphk if (i <= sizeof buf) 36210818Sphk { 36310818Sphk bufp = buf; 36410818Sphk i = sizeof buf; 36510818Sphk } 36610818Sphk else 36710818Sphk bufp = sm_malloc_x(i); 36810818Sphk 36911338Sphk SM_TRY 37010818Sphk { 37111338Sphk (void) sm_strlcpy(bufp, denlstring(list, false, true), i); 37211338Sphk 37311338Sphk macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e r"); 37411338Sphk for (p = bufp; *p != '\0'; ) 37511338Sphk { 37611338Sphk ADDRESS a; /* parsed address to be removed */ 37710818Sphk ADDRESS *q; 37811338Sphk ADDRESS **pq; 37911338Sphk char *delimptr; 38011338Sphk 38111338Sphk /* parse the address */ 38211338Sphk while ((isascii(*p) && isspace(*p)) || *p == ',') 38311338Sphk p++; 38411338Sphk if (parseaddr(p, &a, RF_COPYALL, 38511338Sphk delimiter, &delimptr, e, true) == NULL) 38610818Sphk { 3871573Srgrimes p = delimptr; 38810818Sphk continue; 38910818Sphk } 39010818Sphk p = delimptr; 39110818Sphk for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next) 39210818Sphk { 39310818Sphk if (!QS_IS_DEAD(q->q_state) && 39410818Sphk sameaddr(q, &a)) 39510818Sphk { 39610818Sphk if (tTd(25, 5)) 39710818Sphk { 39810818Sphk sm_dprintf("removefromlist: QS_REMOVED "); 39910818Sphk printaddr(&a, false); 40010818Sphk } 40110818Sphk q->q_state = QS_REMOVED; 40210818Sphk naddrs++; 40310818Sphk break; 40410818Sphk } 40510818Sphk } 40610818Sphk } 40710818Sphk } 40810818Sphk SM_FINALLY 40910818Sphk { 41010818Sphk e->e_to = oldto; 41110818Sphk if (bufp != buf) 41210818Sphk sm_free(bufp); 41310818Sphk macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL); 41410818Sphk } 41510818Sphk SM_END_TRY 41610818Sphk return naddrs; 41710818Sphk} 41810818Sphk#endif /* MILTER */ 41910818Sphk/* 42010818Sphk** RECIPIENT -- Designate a message recipient 42110818Sphk** 42210818Sphk** Saves the named person for future mailing. 42310818Sphk** 42410818Sphk** Parameters: 42510818Sphk** new -- the (preparsed) address header for the recipient. 42610818Sphk** sendq -- a pointer to the head of a queue to put the 42710818Sphk** recipient in. Duplicate suppression is done 42810818Sphk** in this queue. 42910818Sphk** aliaslevel -- the current alias nesting depth. 43010818Sphk** e -- the current envelope. 43110818Sphk** 43210818Sphk** Returns: 43310818Sphk** The actual address in the queue. This will be "a" if 43410818Sphk** the address is not a duplicate, else the original address. 43510818Sphk** 43610818Sphk*/ 43710818Sphk 43810818SphkADDRESS * 43911338Sphkrecipient(new, sendq, aliaslevel, e) 44010818Sphk register ADDRESS *new; 44110818Sphk register ADDRESS **sendq; 44212776Speter int aliaslevel; 44310818Sphk register ENVELOPE *e; 44410818Sphk{ 44510818Sphk register ADDRESS *q; 44610818Sphk ADDRESS **pq; 44710818Sphk ADDRESS **prev; 44810818Sphk register struct mailer *m; 44912776Speter register char *p; 45012776Speter int i, buflen; 45112776Speter bool quoted; /* set if the addr has a quote bit */ 45212776Speter bool insert; 45312776Speter int findusercount; 45412776Speter bool initialdontsend; 45512776Speter char *buf; 45612776Speter char buf0[MAXNAME + 1]; /* unquoted image of the user name */ 45712776Speter sortfn_t *sortfn; 45812776Speter 45912776Speter p = NULL; 46012776Speter quoted = false; 46112776Speter insert = false; 46212776Speter findusercount = 0; 46312776Speter initialdontsend = QS_IS_DEAD(new->q_state); 46412776Speter e->e_to = new->q_paddr; 46512776Speter m = new->q_mailer; 46612776Speter errno = 0; 46711338Sphk if (aliaslevel == 0) 46812776Speter new->q_flags |= QPRIMARY; 46912776Speter if (tTd(26, 1)) 47012776Speter { 47110818Sphk sm_dprintf("\nrecipient (%d): ", aliaslevel); 47210818Sphk printaddr(new, false); 47310818Sphk } 47410818Sphk 47510818Sphk /* if this is primary, use it as original recipient */ 47610818Sphk if (new->q_alias == NULL) 47710818Sphk { 47810818Sphk if (e->e_origrcpt == NULL) 47910818Sphk e->e_origrcpt = new->q_paddr; 48010818Sphk else if (e->e_origrcpt != new->q_paddr) 48110818Sphk e->e_origrcpt = ""; 48210818Sphk } 48310818Sphk 48410818Sphk /* find parent recipient for finalrcpt and orcpt */ 48512776Speter for (q = new; q->q_alias != NULL; q = q->q_alias) 48610818Sphk continue; 48710818Sphk 48810818Sphk /* find final recipient DSN address */ 48910818Sphk if (new->q_finalrcpt == NULL && 49010818Sphk e->e_from.q_mailer != NULL) 49110818Sphk { 49210818Sphk char frbuf[MAXLINE]; 49310818Sphk 49410818Sphk p = e->e_from.q_mailer->m_addrtype; 49510818Sphk if (p == NULL) 49610818Sphk p = "rfc822"; 49711338Sphk if (sm_strcasecmp(p, "rfc822") != 0) 49811338Sphk { 49911338Sphk (void) sm_snprintf(frbuf, sizeof frbuf, "%s; %.800s", 50011338Sphk q->q_mailer->m_addrtype, 50110818Sphk q->q_user); 50210818Sphk } 50311338Sphk else if (strchr(q->q_user, '@') != NULL) 50411338Sphk { 50512776Speter (void) sm_snprintf(frbuf, sizeof frbuf, "%s; %.800s", 50611338Sphk p, q->q_user); 50711338Sphk } 50812776Speter else if (strchr(q->q_paddr, '@') != NULL) 50910818Sphk { 51010818Sphk char *qp; 51111338Sphk bool b; 51211338Sphk 51311338Sphk qp = q->q_paddr; 51411338Sphk 51510818Sphk /* strip brackets from address */ 51611338Sphk b = false; 51711338Sphk if (*qp == '<') 51810818Sphk { 51910818Sphk b = qp[strlen(qp) - 1] == '>'; 52010818Sphk if (b) 52110818Sphk qp[strlen(qp) - 1] = '\0'; 52211338Sphk qp++; 52311338Sphk } 52411338Sphk (void) sm_snprintf(frbuf, sizeof frbuf, "%s; %.800s", 52511338Sphk p, qp); 52611338Sphk 52711338Sphk /* undo damage */ 52811338Sphk if (b) 52911338Sphk qp[strlen(qp)] = '>'; 53010818Sphk } 53110818Sphk else 53211338Sphk { 53310818Sphk (void) sm_snprintf(frbuf, sizeof frbuf, 53410818Sphk "%s; %.700s@%.100s", 53510818Sphk p, q->q_user, MyHostName); 53610818Sphk } 53710818Sphk new->q_finalrcpt = sm_rpool_strdup_x(e->e_rpool, frbuf); 53810818Sphk } 53911338Sphk 54011338Sphk#if _FFR_GEN_ORCPT 54111338Sphk /* set ORCPT DSN arg if not already set */ 54211338Sphk if (new->q_orcpt == NULL) 54310818Sphk { 54411665Sphk /* check for an existing ORCPT */ 54511665Sphk if (q->q_orcpt != NULL) 54610818Sphk new->q_orcpt = q->q_orcpt; 54710818Sphk else 54810818Sphk { 54911665Sphk /* make our own */ 55010818Sphk bool b = false; 55110818Sphk char *qp; 55210818Sphk char obuf[MAXLINE]; 55311338Sphk 55410818Sphk if (e->e_from.q_mailer != NULL) 55510818Sphk p = e->e_from.q_mailer->m_addrtype; 55610818Sphk if (p == NULL) 55711665Sphk p = "rfc822"; 55811665Sphk (void) sm_strlcpyn(obuf, sizeof obuf, 2, p, ";"); 55910818Sphk 56010818Sphk qp = q->q_paddr; 56110818Sphk 56210818Sphk /* FFR: Needs to strip comments from stdin addrs */ 56310818Sphk 56410818Sphk /* strip brackets from address */ 56510818Sphk if (*qp == '<') 56610818Sphk { 56710818Sphk b = qp[strlen(qp) - 1] == '>'; 56810818Sphk if (b) 56910818Sphk qp[strlen(qp) - 1] = '\0'; 57010818Sphk qp++; 57110818Sphk } 57210818Sphk 57310818Sphk p = xtextify(denlstring(qp, true, false), NULL); 57410818Sphk 57510818Sphk if (sm_strlcat(obuf, p, sizeof obuf) >= sizeof obuf) 57610818Sphk { 57710818Sphk /* if too big, don't use it */ 57811665Sphk obuf[0] = '\0'; 57910818Sphk } 58010818Sphk 58110818Sphk /* undo damage */ 58212776Speter if (b) 58312776Speter qp[strlen(qp)] = '>'; 58412776Speter 58511338Sphk if (obuf[0] != '\0') 58610818Sphk new->q_orcpt = 58710818Sphk sm_rpool_strdup_x(e->e_rpool, obuf); 58810818Sphk } 58910818Sphk } 59010818Sphk#endif /* _FFR_GEN_ORCPT */ 59112776Speter 59210818Sphk /* break aliasing loops */ 59310818Sphk if (aliaslevel > MaxAliasRecursion) 59410818Sphk { 59510818Sphk new->q_state = QS_BADADDR; 59610818Sphk new->q_status = "5.4.6"; 59710818Sphk usrerrenh(new->q_status, 59812918Sphk "554 aliasing/forwarding loop broken (%d aliases deep; %d max)", 59912918Sphk aliaslevel, MaxAliasRecursion); 60012918Sphk return new; 60112918Sphk } 60212918Sphk 60312918Sphk /* 60410818Sphk ** Finish setting up address structure. 60510818Sphk */ 60610818Sphk 60710818Sphk /* get unquoted user for file, program or user.name check */ 60810818Sphk i = strlen(new->q_user); 6091573Srgrimes if (i >= sizeof buf0) 61010818Sphk { 6111573Srgrimes buflen = i + 1; 61210818Sphk buf = xalloc(buflen); 61310818Sphk } 61410818Sphk else 61510818Sphk { 6161573Srgrimes buf = buf0; 61711338Sphk buflen = sizeof buf0; 61810818Sphk } 61910818Sphk (void) sm_strlcpy(buf, new->q_user, buflen); 62010818Sphk for (p = buf; *p != '\0' && !quoted; p++) 62110818Sphk { 62211338Sphk if (*p == '\\') 62310818Sphk quoted = true; 62411338Sphk } 62511338Sphk stripquotes(buf); 62611338Sphk 62711338Sphk /* check for direct mailing to restricted mailers */ 62810818Sphk if (m == ProgMailer) 62911338Sphk { 63011338Sphk if (new->q_alias == NULL || UseMSP || 63111338Sphk bitset(EF_UNSAFE, e->e_flags)) 63211338Sphk { 63311338Sphk new->q_state = QS_BADADDR; 63411338Sphk new->q_status = "5.7.1"; 63511338Sphk usrerrenh(new->q_status, 63611338Sphk "550 Cannot mail directly to programs"); 63711338Sphk } 63810818Sphk else if (bitset(QBOGUSSHELL, new->q_alias->q_flags)) 63911338Sphk { 64011338Sphk new->q_state = QS_BADADDR; 64110818Sphk new->q_status = "5.7.1"; 64211338Sphk if (new->q_alias->q_ruser == NULL) 64311338Sphk usrerrenh(new->q_status, 64410818Sphk "550 UID %d is an unknown user: cannot mail to programs", 64510818Sphk new->q_alias->q_uid); 64610818Sphk else 64710818Sphk usrerrenh(new->q_status, 64810818Sphk "550 User %s@%s doesn't have a valid shell for mailing to programs", 64910818Sphk new->q_alias->q_ruser, MyHostName); 65011338Sphk } 65111338Sphk else if (bitset(QUNSAFEADDR, new->q_alias->q_flags)) 65211338Sphk { 65311338Sphk new->q_state = QS_BADADDR; 65411338Sphk new->q_status = "5.7.1"; 65511338Sphk new->q_rstatus = "550 Unsafe for mailing to programs"; 65610818Sphk usrerrenh(new->q_status, 65711338Sphk "550 Address %s is unsafe for mailing to programs", 65810818Sphk new->q_alias->q_paddr); 65911338Sphk } 66011338Sphk } 66110818Sphk 66210818Sphk /* 66310818Sphk ** Look up this person in the recipient list. 66410818Sphk ** If they are there already, return, otherwise continue. 66510818Sphk ** If the list is empty, just add it. Notice the cute 66610818Sphk ** hack to make from addresses suppress things correctly: 66710818Sphk ** the QS_DUPLICATE state will be set in the send list. 66810818Sphk ** [Please note: the emphasis is on "hack."] 66910818Sphk */ 67011338Sphk 67111338Sphk prev = NULL; 67210818Sphk 67310818Sphk /* 67410818Sphk ** If this message is going to the queue or FastSplit is set 67511338Sphk ** and it is the first try and the envelope hasn't split, then we 67611338Sphk ** avoid doing an MX RR lookup now because one will be done when the 67711338Sphk ** message is extracted from the queue later. It can go to the queue 67810818Sphk ** because all messages are going to the queue or this mailer of 67911338Sphk ** the current recipient is marked expensive. 68010818Sphk */ 68111338Sphk 68210818Sphk if (WILL_BE_QUEUED(e->e_sendmode) || 68310818Sphk (!bitset(EF_SPLIT, e->e_flags) && e->e_ntries == 0 && 68410818Sphk FastSplit > 0)) 68510818Sphk sortfn = sorthost; 68611338Sphk else if (NoConnect && bitnset(M_EXPENSIVE, new->q_mailer->m_flags)) 68710818Sphk sortfn = sortexpensive; 6881573Srgrimes else 6891573Srgrimes sortfn = sortbysignature; 6901573Srgrimes 69110818Sphk for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next) 6921573Srgrimes { 69310818Sphk /* 69410818Sphk ** If address is "less than" it should be inserted now. 69510818Sphk ** If address is "greater than" current comparison it'll 6961573Srgrimes ** insert later in the list; so loop again (if possible). 69710818Sphk ** If address is "equal" (different equal than sameaddr() 69810818Sphk ** call) then check if sameaddr() will be true. 69910818Sphk ** Because this list is now sorted, it'll mean fewer 7001573Srgrimes ** comparisons and fewer loops which is important for more 70110818Sphk ** recipients. 70210818Sphk */ 70310818Sphk 70410818Sphk i = (*sortfn)(new, q); 70511338Sphk if (i == 0) /* equal */ 70611338Sphk { 70710818Sphk /* 70810818Sphk ** Sortbysignature() has said that the two have 70910818Sphk ** equal MX RR's and the same user. Calling sameaddr() 71011338Sphk ** now checks if the two hosts are as identical as the 71111338Sphk ** MX RR's are (which might not be the case) 71210818Sphk ** before saying these are the identical addresses. 71310818Sphk */ 71410818Sphk 71510818Sphk if (sameaddr(q, new) && 71611338Sphk (bitset(QRCPTOK, q->q_flags) || 71711338Sphk !bitset(QPRIMARY, q->q_flags))) 71810818Sphk { 71911338Sphk if (tTd(26, 1)) 72010818Sphk { 72110818Sphk sm_dprintf("%s in sendq: ", 72210818Sphk new->q_paddr); 72310818Sphk printaddr(q, false); 72410818Sphk } 72511338Sphk if (!bitset(QPRIMARY, q->q_flags)) 72611338Sphk { 72711338Sphk if (!QS_IS_DEAD(new->q_state)) 72810818Sphk message("duplicate suppressed"); 72910818Sphk else 73010818Sphk q->q_state = QS_DUPLICATE; 73110818Sphk q->q_flags |= new->q_flags; 73210818Sphk } 73311338Sphk else if (bitset(QSELFREF, q->q_flags) 73411338Sphk || q->q_state == QS_REMOVED) 73510818Sphk { 73610818Sphk /* 73711338Sphk ** If an earlier milter removed the 73810818Sphk ** address, a later one can still add 73910818Sphk ** it back. 74010818Sphk */ 74111338Sphk 74211338Sphk q->q_state = new->q_state; 74311338Sphk q->q_flags |= new->q_flags; 74411338Sphk } 74511338Sphk new = q; 74611338Sphk goto done; 74711338Sphk } 74811338Sphk } 74911338Sphk else if (i < 0) /* less than */ 75010818Sphk { 75110818Sphk insert = true; 7521573Srgrimes break; 7531573Srgrimes } 75410818Sphk prev = pq; 75510818Sphk } 75610818Sphk 75710818Sphk /* pq should point to an address, never NULL */ 75810818Sphk SM_ASSERT(pq != NULL); 7598870Srgrimes 76010818Sphk /* add address on list */ 76110818Sphk if (insert) 76210818Sphk { 76310818Sphk /* 7641573Srgrimes ** insert before 'pq'. Only possible when at least 1 76510818Sphk ** ADDRESS is in the list already. 76610818Sphk */ 76710818Sphk 76810818Sphk new->q_next = *pq; 76910818Sphk if (prev == NULL) 77010818Sphk *sendq = new; /* To be the first ADDRESS */ 77110818Sphk else 77210818Sphk (*prev)->q_next = new; 77310818Sphk } 77410818Sphk else 77510818Sphk { 77610818Sphk /* 77710818Sphk ** Place in list at current 'pq' position. Possible 77810818Sphk ** when there are 0 or more ADDRESS's in the list. 77910818Sphk */ 78010818Sphk 78110818Sphk new->q_next = NULL; 78211338Sphk *pq = new; 78310818Sphk } 78410818Sphk 78511338Sphk /* added a new address: clear split flag */ 78611338Sphk e->e_flags &= ~EF_SPLIT; 78711338Sphk 78810818Sphk /* 78910818Sphk ** Alias the name and handle special mailer types. 79010818Sphk */ 79111338Sphk 79211338Sphk trylocaluser: 79310818Sphk if (tTd(29, 7)) 79411338Sphk { 79511338Sphk sm_dprintf("at trylocaluser: "); 79611338Sphk printaddr(new, false); 79711338Sphk } 79811338Sphk 79911338Sphk if (!QS_IS_OK(new->q_state)) 8001573Srgrimes { 8011573Srgrimes if (QS_IS_UNDELIVERED(new->q_state)) 8021573Srgrimes e->e_nrcpts++; 80310818Sphk goto testselfdestruct; 8041573Srgrimes } 80510818Sphk 80610818Sphk if (m == InclMailer) 80710818Sphk { 80810818Sphk new->q_state = QS_INCLUDED; 8091573Srgrimes if (new->q_alias == NULL || UseMSP || 81010818Sphk bitset(EF_UNSAFE, e->e_flags)) 81110818Sphk { 81210818Sphk new->q_state = QS_BADADDR; 81310818Sphk new->q_status = "5.7.1"; 81410818Sphk usrerrenh(new->q_status, 81510818Sphk "550 Cannot mail directly to :include:s"); 81610818Sphk } 81710818Sphk else 81810818Sphk { 81910818Sphk int ret; 82011338Sphk 82110818Sphk message("including file %s", new->q_user); 82211338Sphk ret = include(new->q_user, false, new, 82311338Sphk sendq, aliaslevel, e); 82411338Sphk if (transienterror(ret)) 82511338Sphk { 82611338Sphk if (LogLevel > 2) 82710818Sphk sm_syslog(LOG_ERR, e->e_id, 82810818Sphk "include %s: transient error: %s", 82910818Sphk shortenstring(new->q_user, 83010818Sphk MAXSHORTSTR), 83111338Sphk sm_errstring(ret)); 83210818Sphk new->q_state = QS_QUEUEUP; 8331573Srgrimes usrerr("451 4.2.4 Cannot open %s: %s", 83410818Sphk shortenstring(new->q_user, 8358870Srgrimes MAXSHORTSTR), 83610818Sphk sm_errstring(ret)); 83711338Sphk } 83810818Sphk else if (ret != 0) 83911338Sphk { 8401573Srgrimes new->q_state = QS_BADADDR; 84110818Sphk new->q_status = "5.2.4"; 84211338Sphk usrerrenh(new->q_status, 84310818Sphk "550 Cannot open %s: %s", 84411338Sphk shortenstring(new->q_user, 84511338Sphk MAXSHORTSTR), 84611338Sphk sm_errstring(ret)); 84711338Sphk } 84811338Sphk } 84911338Sphk } 85011338Sphk else if (m == FileMailer) 85111338Sphk { 85211338Sphk /* check if allowed */ 85310818Sphk if (new->q_alias == NULL || UseMSP || 85410818Sphk bitset(EF_UNSAFE, e->e_flags)) 85510818Sphk { 85610818Sphk new->q_state = QS_BADADDR; 85711338Sphk new->q_status = "5.7.1"; 85810818Sphk usrerrenh(new->q_status, 85911338Sphk "550 Cannot mail directly to files"); 86011338Sphk } 86111338Sphk else if (bitset(QBOGUSSHELL, new->q_alias->q_flags)) 86211338Sphk { 86310818Sphk new->q_state = QS_BADADDR; 86411338Sphk new->q_status = "5.7.1"; 86511338Sphk if (new->q_alias->q_ruser == NULL) 86610818Sphk usrerrenh(new->q_status, 86710818Sphk "550 UID %d is an unknown user: cannot mail to files", 86810818Sphk new->q_alias->q_uid); 86910818Sphk else 87011338Sphk usrerrenh(new->q_status, 87111338Sphk "550 User %s@%s doesn't have a valid shell for mailing to files", 87211338Sphk new->q_alias->q_ruser, MyHostName); 87311338Sphk } 87411338Sphk else if (bitset(QUNSAFEADDR, new->q_alias->q_flags)) 87511338Sphk { 87611338Sphk new->q_state = QS_BADADDR; 87711338Sphk new->q_status = "5.7.1"; 87811338Sphk new->q_rstatus = "550 Unsafe for mailing to files"; 87911338Sphk usrerrenh(new->q_status, 88011338Sphk "550 Address %s is unsafe for mailing to files", 88110818Sphk new->q_alias->q_paddr); 88211338Sphk } 88311338Sphk } 88411338Sphk 88511338Sphk /* try aliasing */ 88611338Sphk if (!quoted && QS_IS_OK(new->q_state) && 88711338Sphk bitnset(M_ALIASABLE, m->m_flags)) 88811338Sphk alias(new, sendq, aliaslevel, e); 88911338Sphk 89011338Sphk#if USERDB 89111338Sphk /* if not aliased, look it up in the user database */ 89211338Sphk if (!bitset(QNOTREMOTE, new->q_flags) && 89311338Sphk QS_IS_SENDABLE(new->q_state) && 8941573Srgrimes bitnset(M_CHECKUDB, m->m_flags)) 89511338Sphk { 89611338Sphk if (udbexpand(new, sendq, aliaslevel, e) == EX_TEMPFAIL) 89711338Sphk { 89811338Sphk new->q_state = QS_QUEUEUP; 89911338Sphk if (e->e_message == NULL) 90011338Sphk e->e_message = "Deferred: user database error"; 90111338Sphk if (new->q_message == NULL) 90211338Sphk new->q_message = "Deferred: user database error"; 90311338Sphk if (LogLevel > 8) 90411338Sphk sm_syslog(LOG_INFO, e->e_id, 90510818Sphk "deferred: udbexpand: %s", 90611338Sphk sm_errstring(errno)); 90711338Sphk message("queued (user database error): %s", 90811338Sphk sm_errstring(errno)); 90911338Sphk e->e_nrcpts++; 91011338Sphk goto testselfdestruct; 91111338Sphk } 91211338Sphk } 91310818Sphk#endif /* USERDB */ 91411338Sphk 91511338Sphk /* 91610818Sphk ** If we have a level two config file, then pass the name through 91710818Sphk ** Ruleset 5 before sending it off. Ruleset 5 has the right 91810818Sphk ** to rewrite it to another mailer. This gives us a hook 91910818Sphk ** after local aliasing has been done. 92010818Sphk */ 92111338Sphk 92210818Sphk if (tTd(29, 5)) 92310818Sphk { 9241573Srgrimes sm_dprintf("recipient: testing local? cl=%d, rr5=%p\n\t", 92510818Sphk ConfigLevel, RewriteRules[5]); 92610818Sphk printaddr(new, false); 92711338Sphk } 92810818Sphk if (ConfigLevel >= 2 && RewriteRules[5] != NULL && 9291573Srgrimes bitnset(M_TRYRULESET5, m->m_flags) && 9301573Srgrimes !bitset(QNOTREMOTE, new->q_flags) && 9311573Srgrimes QS_IS_OK(new->q_state)) 93210818Sphk { 9331573Srgrimes maplocaluser(new, sendq, aliaslevel + 1, e); 93410818Sphk } 93510818Sphk 93611338Sphk /* 9371573Srgrimes ** If it didn't get rewritten to another mailer, go ahead 93810818Sphk ** and deliver it. 93910818Sphk */ 94010818Sphk 94110818Sphk if (QS_IS_OK(new->q_state) && 9421573Srgrimes bitnset(M_HASPWENT, m->m_flags)) 94310818Sphk { 94411338Sphk auto bool fuzzy; 94510818Sphk SM_MBDB_T user; 94610818Sphk int status; 94710818Sphk 94811338Sphk /* warning -- finduser may trash buf */ 94911338Sphk status = finduser(buf, &fuzzy, &user); 95011338Sphk switch (status) 95111338Sphk { 95210818Sphk case EX_TEMPFAIL: 95311338Sphk new->q_state = QS_QUEUEUP; 95411338Sphk new->q_status = "4.5.2"; 95511338Sphk giveresponse(EX_TEMPFAIL, new->q_status, m, NULL, 95611338Sphk new->q_alias, (time_t) 0, e, new); 95710818Sphk break; 95811338Sphk default: 95910818Sphk new->q_state = QS_BADADDR; 96010818Sphk new->q_status = "5.1.1"; 96110818Sphk new->q_rstatus = "550 5.1.1 User unknown"; 96210818Sphk giveresponse(EX_NOUSER, new->q_status, m, NULL, 96310818Sphk new->q_alias, (time_t) 0, e, new); 96410818Sphk break; 96510818Sphk case EX_OK: 96610818Sphk if (fuzzy) 96710818Sphk { 96810818Sphk /* name was a fuzzy match */ 96911338Sphk new->q_user = sm_rpool_strdup_x(e->e_rpool, 97010818Sphk user.mbdb_name); 97110818Sphk if (findusercount++ > 3) 97210818Sphk { 97310818Sphk new->q_state = QS_BADADDR; 97411338Sphk new->q_status = "5.4.6"; 97511338Sphk usrerrenh(new->q_status, 97610818Sphk "554 aliasing/forwarding loop for %s broken", 97710818Sphk user.mbdb_name); 97810818Sphk goto done; 97910818Sphk } 98010818Sphk 98111338Sphk /* see if it aliases */ 98210818Sphk (void) sm_strlcpy(buf, user.mbdb_name, buflen); 98311338Sphk goto trylocaluser; 98411338Sphk } 98510818Sphk if (*user.mbdb_homedir == '\0') 98611338Sphk new->q_home = NULL; 98711338Sphk else if (strcmp(user.mbdb_homedir, "/") == 0) 98811338Sphk new->q_home = ""; 98911338Sphk else 99011338Sphk new->q_home = sm_rpool_strdup_x(e->e_rpool, 99111338Sphk user.mbdb_homedir); 99211338Sphk if (user.mbdb_uid != SM_NO_UID) 99311338Sphk { 99411338Sphk new->q_uid = user.mbdb_uid; 99511338Sphk new->q_gid = user.mbdb_gid; 99611338Sphk new->q_flags |= QGOODUID; 99711338Sphk } 99811338Sphk new->q_ruser = sm_rpool_strdup_x(e->e_rpool, 99912918Sphk user.mbdb_name); 100011338Sphk if (user.mbdb_fullname[0] != '\0') 100111338Sphk new->q_fullname = sm_rpool_strdup_x(e->e_rpool, 100211338Sphk user.mbdb_fullname); 100311338Sphk if (!usershellok(user.mbdb_name, user.mbdb_shell)) 100411338Sphk { 100511338Sphk new->q_flags |= QBOGUSSHELL; 100611338Sphk } 100711338Sphk if (bitset(EF_VRFYONLY, e->e_flags)) 100811338Sphk { 100911338Sphk /* don't do any more now */ 101011338Sphk new->q_state = QS_VERIFIED; 101110818Sphk } 101211338Sphk else if (!quoted) 101311338Sphk forward(new, sendq, aliaslevel, e); 101411338Sphk } 101511338Sphk } 101611338Sphk if (!QS_IS_DEAD(new->q_state)) 101711338Sphk e->e_nrcpts++; 101811338Sphk 101911338Sphk testselfdestruct: 102011338Sphk new->q_flags |= QTHISPASS; 102111338Sphk if (tTd(26, 8)) 102211338Sphk { 102311338Sphk sm_dprintf("testselfdestruct: "); 102411338Sphk printaddr(new, false); 10251573Srgrimes if (tTd(26, 10)) 102610818Sphk { 102711338Sphk sm_dprintf("SENDQ:\n"); 102811338Sphk printaddr(*sendq, true); 102911338Sphk sm_dprintf("----\n"); 103011338Sphk } 103111338Sphk } 103211338Sphk if (new->q_alias == NULL && new != &e->e_from && 103311338Sphk QS_IS_DEAD(new->q_state)) 103411338Sphk { 103511338Sphk for (q = *sendq; q != NULL; q = q->q_next) 103611338Sphk { 103711338Sphk if (!QS_IS_DEAD(q->q_state)) 103810818Sphk break; 103910818Sphk } 104011338Sphk if (q == NULL) 104110818Sphk { 104210818Sphk new->q_state = QS_BADADDR; 104311338Sphk new->q_status = "5.4.6"; 104411338Sphk usrerrenh(new->q_status, 104511338Sphk "554 aliasing/forwarding loop broken"); 104611338Sphk } 104710818Sphk } 104810818Sphk 104911338Sphk done: 105011338Sphk new->q_flags |= QTHISPASS; 105110818Sphk if (buf != buf0) 10521573Srgrimes sm_free(buf); /* XXX leak if above code raises exception */ 10531573Srgrimes 10541573Srgrimes /* 105510818Sphk ** If we are at the top level, check to see if this has 10561573Srgrimes ** expanded to exactly one address. If so, it can inherit 105710818Sphk ** the primaryness of the address. 105810818Sphk ** 105911338Sphk ** While we're at it, clear the QTHISPASS bits. 10601573Srgrimes */ 106110818Sphk 106210818Sphk if (aliaslevel == 0) 106310818Sphk { 10641573Srgrimes int nrcpts = 0; 106510818Sphk ADDRESS *only = NULL; 106610818Sphk 106710818Sphk for (q = *sendq; q != NULL; q = q->q_next) 106811338Sphk { 106911338Sphk if (bitset(QTHISPASS, q->q_flags) && 107011338Sphk QS_IS_SENDABLE(q->q_state)) 107111338Sphk { 107211338Sphk nrcpts++; 107310818Sphk only = q; 107411338Sphk } 107510818Sphk q->q_flags &= ~QTHISPASS; 107610818Sphk } 107710818Sphk if (nrcpts == 1) 107810818Sphk { 107910818Sphk /* check to see if this actually got a new owner */ 108010818Sphk q = only; 108111338Sphk while ((q = q->q_alias) != NULL) 108211338Sphk { 108310818Sphk if (q->q_owner != NULL) 108411338Sphk break; 108511338Sphk } 108611338Sphk if (q == NULL) 108710818Sphk only->q_flags |= QPRIMARY; 108811338Sphk } 108910818Sphk else if (!initialdontsend && nrcpts > 0) 109010818Sphk { 109110818Sphk /* arrange for return receipt */ 109210818Sphk e->e_flags |= EF_SENDRECEIPT; 109310818Sphk new->q_flags |= QEXPANDED; 109410818Sphk if (e->e_xfp != NULL && 109510818Sphk bitset(QPINGONSUCCESS, new->q_flags)) 109610818Sphk (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, 109710818Sphk "%s... expanded to multiple addresses\n", 109810818Sphk new->q_paddr); 109910818Sphk } 110010818Sphk } 110110818Sphk new->q_flags |= QRCPTOK; 110210818Sphk (void) sm_snprintf(buf0, sizeof buf0, "%d", e->e_nrcpts); 110311338Sphk macdefine(&e->e_macro, A_TEMP, macid("{nrcpts}"), buf0); 110411338Sphk return new; 110511338Sphk} 110610818Sphk/* 110710818Sphk** FINDUSER -- find the password entry for a user. 110810818Sphk** 110910818Sphk** This looks a lot like getpwnam, except that it may want to 111011338Sphk** do some fancier pattern matching in /etc/passwd. 111111338Sphk** 111211338Sphk** This routine contains most of the time of many sendmail runs. 111310818Sphk** It deserves to be optimized. 111411338Sphk** 11151573Srgrimes** Parameters: 111610818Sphk** name -- the name to match against. 111710818Sphk** fuzzyp -- an outarg that is set to true if this entry 111810818Sphk** was found using the fuzzy matching algorithm; 111910818Sphk** set to false otherwise. 112010818Sphk** user -- structure to fill in if user is found 112110818Sphk** 112210818Sphk** Returns: 112310818Sphk** On success, fill in *user, set *fuzzyp and return EX_OK. 112410818Sphk** If the user was not found, return EX_NOUSER. 112510818Sphk** On error, return EX_TEMPFAIL or EX_OSERR. 112610818Sphk** 112710818Sphk** Side Effects: 112811338Sphk** may modify name. 112910818Sphk*/ 113010818Sphk 113110818Sphkint 113211338Sphkfinduser(name, fuzzyp, user) 113310818Sphk char *name; 113411338Sphk bool *fuzzyp; 113510818Sphk SM_MBDB_T *user; 113611338Sphk{ 113710818Sphk#if MATCHGECOS 113810818Sphk register struct passwd *pw; 113911338Sphk#endif /* MATCHGECOS */ 114010818Sphk register char *p; 114110818Sphk bool tryagain; 114211338Sphk int status; 114310818Sphk 114411338Sphk if (tTd(29, 4)) 114510818Sphk sm_dprintf("finduser(%s): ", name); 114610818Sphk 114710818Sphk *fuzzyp = false; 114810818Sphk 114911338Sphk#if HESIOD 115010818Sphk /* DEC Hesiod getpwnam accepts numeric strings -- short circuit it */ 115111338Sphk for (p = name; *p != '\0'; p++) 115211338Sphk if (!isascii(*p) || !isdigit(*p)) 115311338Sphk break; 115410818Sphk if (*p == '\0') 115510818Sphk { 1156 if (tTd(29, 4)) 1157 sm_dprintf("failed (numeric input)\n"); 1158 return EX_NOUSER; 1159 } 1160#endif /* HESIOD */ 1161 1162 /* look up this login name using fast path */ 1163 status = sm_mbdb_lookup(name, user); 1164 if (status != EX_NOUSER) 1165 { 1166 if (tTd(29, 4)) 1167 sm_dprintf("%s (non-fuzzy)\n", sm_strexit(status)); 1168 return status; 1169 } 1170 1171 /* try mapping it to lower case */ 1172 tryagain = false; 1173 for (p = name; *p != '\0'; p++) 1174 { 1175 if (isascii(*p) && isupper(*p)) 1176 { 1177 *p = tolower(*p); 1178 tryagain = true; 1179 } 1180 } 1181 if (tryagain && (status = sm_mbdb_lookup(name, user)) != EX_NOUSER) 1182 { 1183 if (tTd(29, 4)) 1184 sm_dprintf("%s (lower case)\n", sm_strexit(status)); 1185 *fuzzyp = true; 1186 return status; 1187 } 1188 1189#if MATCHGECOS 1190 /* see if fuzzy matching allowed */ 1191 if (!MatchGecos) 1192 { 1193 if (tTd(29, 4)) 1194 sm_dprintf("not found (fuzzy disabled)\n"); 1195 return EX_NOUSER; 1196 } 1197 1198 /* search for a matching full name instead */ 1199 for (p = name; *p != '\0'; p++) 1200 { 1201 if (*p == (SpaceSub & 0177) || *p == '_') 1202 *p = ' '; 1203 } 1204 (void) setpwent(); 1205 while ((pw = getpwent()) != NULL) 1206 { 1207 char buf[MAXNAME + 1]; 1208 1209# if 0 1210 if (sm_strcasecmp(pw->pw_name, name) == 0) 1211 { 1212 if (tTd(29, 4)) 1213 sm_dprintf("found (case wrapped)\n"); 1214 break; 1215 } 1216# endif /* 0 */ 1217 1218 sm_pwfullname(pw->pw_gecos, pw->pw_name, buf, sizeof buf); 1219 if (strchr(buf, ' ') != NULL && sm_strcasecmp(buf, name) == 0) 1220 { 1221 if (tTd(29, 4)) 1222 sm_dprintf("fuzzy matches %s\n", pw->pw_name); 1223 message("sending to login name %s", pw->pw_name); 1224 break; 1225 } 1226 } 1227 if (pw != NULL) 1228 *fuzzyp = true; 1229 else if (tTd(29, 4)) 1230 sm_dprintf("no fuzzy match found\n"); 1231# if DEC_OSF_BROKEN_GETPWENT /* DEC OSF/1 3.2 or earlier */ 1232 endpwent(); 1233# endif /* DEC_OSF_BROKEN_GETPWENT */ 1234 if (pw == NULL) 1235 return EX_NOUSER; 1236 sm_mbdb_frompw(user, pw); 1237 return EX_OK; 1238#else /* MATCHGECOS */ 1239 if (tTd(29, 4)) 1240 sm_dprintf("not found (fuzzy disabled)\n"); 1241 return EX_NOUSER; 1242#endif /* MATCHGECOS */ 1243} 1244/* 1245** WRITABLE -- predicate returning if the file is writable. 1246** 1247** This routine must duplicate the algorithm in sys/fio.c. 1248** Unfortunately, we cannot use the access call since we 1249** won't necessarily be the real uid when we try to 1250** actually open the file. 1251** 1252** Notice that ANY file with ANY execute bit is automatically 1253** not writable. This is also enforced by mailfile. 1254** 1255** Parameters: 1256** filename -- the file name to check. 1257** ctladdr -- the controlling address for this file. 1258** flags -- SFF_* flags to control the function. 1259** 1260** Returns: 1261** true -- if we will be able to write this file. 1262** false -- if we cannot write this file. 1263** 1264** Side Effects: 1265** none. 1266*/ 1267 1268bool 1269writable(filename, ctladdr, flags) 1270 char *filename; 1271 ADDRESS *ctladdr; 1272 long flags; 1273{ 1274 uid_t euid = 0; 1275 gid_t egid = 0; 1276 char *user = NULL; 1277 1278 if (tTd(44, 5)) 1279 sm_dprintf("writable(%s, 0x%lx)\n", filename, flags); 1280 1281 /* 1282 ** File does exist -- check that it is writable. 1283 */ 1284 1285 if (geteuid() != 0) 1286 { 1287 euid = geteuid(); 1288 egid = getegid(); 1289 user = NULL; 1290 } 1291 else if (ctladdr != NULL) 1292 { 1293 euid = ctladdr->q_uid; 1294 egid = ctladdr->q_gid; 1295 user = ctladdr->q_user; 1296 } 1297 else if (bitset(SFF_RUNASREALUID, flags)) 1298 { 1299 euid = RealUid; 1300 egid = RealGid; 1301 user = RealUserName; 1302 } 1303 else if (FileMailer != NULL && !bitset(SFF_ROOTOK, flags)) 1304 { 1305 euid = FileMailer->m_uid; 1306 egid = FileMailer->m_gid; 1307 user = NULL; 1308 } 1309 else 1310 { 1311 euid = egid = 0; 1312 user = NULL; 1313 } 1314 if (!bitset(SFF_ROOTOK, flags)) 1315 { 1316 if (euid == 0) 1317 { 1318 euid = DefUid; 1319 user = DefUser; 1320 } 1321 if (egid == 0) 1322 egid = DefGid; 1323 } 1324 if (geteuid() == 0 && 1325 (ctladdr == NULL || !bitset(QGOODUID, ctladdr->q_flags))) 1326 flags |= SFF_SETUIDOK; 1327 1328 if (!bitnset(DBS_FILEDELIVERYTOSYMLINK, DontBlameSendmail)) 1329 flags |= SFF_NOSLINK; 1330 if (!bitnset(DBS_FILEDELIVERYTOHARDLINK, DontBlameSendmail)) 1331 flags |= SFF_NOHLINK; 1332 1333 errno = safefile(filename, euid, egid, user, flags, S_IWRITE, NULL); 1334 return errno == 0; 1335} 1336/* 1337** INCLUDE -- handle :include: specification. 1338** 1339** Parameters: 1340** fname -- filename to include. 1341** forwarding -- if true, we are reading a .forward file. 1342** if false, it's a :include: file. 1343** ctladdr -- address template to use to fill in these 1344** addresses -- effective user/group id are 1345** the important things. 1346** sendq -- a pointer to the head of the send queue 1347** to put these addresses in. 1348** aliaslevel -- the alias nesting depth. 1349** e -- the current envelope. 1350** 1351** Returns: 1352** open error status 1353** 1354** Side Effects: 1355** reads the :include: file and sends to everyone 1356** listed in that file. 1357** 1358** Security Note: 1359** If you have restricted chown (that is, you can't 1360** give a file away), it is reasonable to allow programs 1361** and files called from this :include: file to be to be 1362** run as the owner of the :include: file. This is bogus 1363** if there is any chance of someone giving away a file. 1364** We assume that pre-POSIX systems can give away files. 1365** 1366** There is an additional restriction that if you 1367** forward to a :include: file, it will not take on 1368** the ownership of the :include: file. This may not 1369** be necessary, but shouldn't hurt. 1370*/ 1371 1372static jmp_buf CtxIncludeTimeout; 1373 1374int 1375include(fname, forwarding, ctladdr, sendq, aliaslevel, e) 1376 char *fname; 1377 bool forwarding; 1378 ADDRESS *ctladdr; 1379 ADDRESS **sendq; 1380 int aliaslevel; 1381 ENVELOPE *e; 1382{ 1383 SM_FILE_T *volatile fp = NULL; 1384 char *oldto = e->e_to; 1385 char *oldfilename = FileName; 1386 int oldlinenumber = LineNumber; 1387 register SM_EVENT *ev = NULL; 1388 int nincludes; 1389 int mode; 1390 volatile bool maxreached = false; 1391 register ADDRESS *ca; 1392 volatile uid_t saveduid; 1393 volatile gid_t savedgid; 1394 volatile uid_t uid; 1395 volatile gid_t gid; 1396 char *volatile user; 1397 int rval = 0; 1398 volatile long sfflags = SFF_REGONLY; 1399 register char *p; 1400 bool safechown = false; 1401 volatile bool safedir = false; 1402 struct stat st; 1403 char buf[MAXLINE]; 1404 1405 if (tTd(27, 2)) 1406 sm_dprintf("include(%s)\n", fname); 1407 if (tTd(27, 4)) 1408 sm_dprintf(" ruid=%d euid=%d\n", 1409 (int) getuid(), (int) geteuid()); 1410 if (tTd(27, 14)) 1411 { 1412 sm_dprintf("ctladdr "); 1413 printaddr(ctladdr, false); 1414 } 1415 1416 if (tTd(27, 9)) 1417 sm_dprintf("include: old uid = %d/%d\n", 1418 (int) getuid(), (int) geteuid()); 1419 1420 if (forwarding) 1421 { 1422 sfflags |= SFF_MUSTOWN|SFF_ROOTOK; 1423 if (!bitnset(DBS_GROUPWRITABLEFORWARDFILE, DontBlameSendmail)) 1424 sfflags |= SFF_NOGWFILES; 1425 if (!bitnset(DBS_WORLDWRITABLEFORWARDFILE, DontBlameSendmail)) 1426 sfflags |= SFF_NOWWFILES; 1427 } 1428 else 1429 { 1430 if (!bitnset(DBS_GROUPWRITABLEINCLUDEFILE, DontBlameSendmail)) 1431 sfflags |= SFF_NOGWFILES; 1432 if (!bitnset(DBS_WORLDWRITABLEINCLUDEFILE, DontBlameSendmail)) 1433 sfflags |= SFF_NOWWFILES; 1434 } 1435 1436 /* 1437 ** If RunAsUser set, won't be able to run programs as user 1438 ** so mark them as unsafe unless the administrator knows better. 1439 */ 1440 1441 if ((geteuid() != 0 || RunAsUid != 0) && 1442 !bitnset(DBS_NONROOTSAFEADDR, DontBlameSendmail)) 1443 { 1444 if (tTd(27, 4)) 1445 sm_dprintf("include: not safe (euid=%d, RunAsUid=%d)\n", 1446 (int) geteuid(), (int) RunAsUid); 1447 ctladdr->q_flags |= QUNSAFEADDR; 1448 } 1449 1450 ca = getctladdr(ctladdr); 1451 if (ca == NULL || 1452 (ca->q_uid == DefUid && ca->q_gid == 0)) 1453 { 1454 uid = DefUid; 1455 gid = DefGid; 1456 user = DefUser; 1457 } 1458 else 1459 { 1460 uid = ca->q_uid; 1461 gid = ca->q_gid; 1462 user = ca->q_user; 1463 } 1464#if MAILER_SETUID_METHOD != USE_SETUID 1465 saveduid = geteuid(); 1466 savedgid = getegid(); 1467 if (saveduid == 0) 1468 { 1469 if (!DontInitGroups) 1470 { 1471 if (initgroups(user, gid) == -1) 1472 { 1473 rval = EAGAIN; 1474 syserr("include: initgroups(%s, %d) failed", 1475 user, gid); 1476 goto resetuid; 1477 } 1478 } 1479 else 1480 { 1481 GIDSET_T gidset[1]; 1482 1483 gidset[0] = gid; 1484 if (setgroups(1, gidset) == -1) 1485 { 1486 rval = EAGAIN; 1487 syserr("include: setgroups() failed"); 1488 goto resetuid; 1489 } 1490 } 1491 1492 if (gid != 0 && setgid(gid) < -1) 1493 { 1494 rval = EAGAIN; 1495 syserr("setgid(%d) failure", gid); 1496 goto resetuid; 1497 } 1498 if (uid != 0) 1499 { 1500# if MAILER_SETUID_METHOD == USE_SETEUID 1501 if (seteuid(uid) < 0) 1502 { 1503 rval = EAGAIN; 1504 syserr("seteuid(%d) failure (real=%d, eff=%d)", 1505 uid, (int) getuid(), (int) geteuid()); 1506 goto resetuid; 1507 } 1508# endif /* MAILER_SETUID_METHOD == USE_SETEUID */ 1509# if MAILER_SETUID_METHOD == USE_SETREUID 1510 if (setreuid(0, uid) < 0) 1511 { 1512 rval = EAGAIN; 1513 syserr("setreuid(0, %d) failure (real=%d, eff=%d)", 1514 uid, (int) getuid(), (int) geteuid()); 1515 goto resetuid; 1516 } 1517# endif /* MAILER_SETUID_METHOD == USE_SETREUID */ 1518 } 1519 } 1520#endif /* MAILER_SETUID_METHOD != USE_SETUID */ 1521 1522 if (tTd(27, 9)) 1523 sm_dprintf("include: new uid = %d/%d\n", 1524 (int) getuid(), (int) geteuid()); 1525 1526 /* 1527 ** If home directory is remote mounted but server is down, 1528 ** this can hang or give errors; use a timeout to avoid this 1529 */ 1530 1531 if (setjmp(CtxIncludeTimeout) != 0) 1532 { 1533 ctladdr->q_state = QS_QUEUEUP; 1534 errno = 0; 1535 1536 /* return pseudo-error code */ 1537 rval = E_SM_OPENTIMEOUT; 1538 goto resetuid; 1539 } 1540 if (TimeOuts.to_fileopen > 0) 1541 ev = sm_setevent(TimeOuts.to_fileopen, includetimeout, 0); 1542 else 1543 ev = NULL; 1544 1545 1546 /* check for writable parent directory */ 1547 p = strrchr(fname, '/'); 1548 if (p != NULL) 1549 { 1550 int ret; 1551 1552 *p = '\0'; 1553 ret = safedirpath(fname, uid, gid, user, 1554 sfflags|SFF_SAFEDIRPATH, 0, 0); 1555 if (ret == 0) 1556 { 1557 /* in safe directory: relax chown & link rules */ 1558 safedir = true; 1559 sfflags |= SFF_NOPATHCHECK; 1560 } 1561 else 1562 { 1563 if (bitnset((forwarding ? 1564 DBS_FORWARDFILEINUNSAFEDIRPATH : 1565 DBS_INCLUDEFILEINUNSAFEDIRPATH), 1566 DontBlameSendmail)) 1567 sfflags |= SFF_NOPATHCHECK; 1568 else if (bitnset((forwarding ? 1569 DBS_FORWARDFILEINGROUPWRITABLEDIRPATH : 1570 DBS_INCLUDEFILEINGROUPWRITABLEDIRPATH), 1571 DontBlameSendmail) && 1572 ret == E_SM_GWDIR) 1573 { 1574 setbitn(DBS_GROUPWRITABLEDIRPATHSAFE, 1575 DontBlameSendmail); 1576 ret = safedirpath(fname, uid, gid, user, 1577 sfflags|SFF_SAFEDIRPATH, 1578 0, 0); 1579 clrbitn(DBS_GROUPWRITABLEDIRPATHSAFE, 1580 DontBlameSendmail); 1581 if (ret == 0) 1582 sfflags |= SFF_NOPATHCHECK; 1583 else 1584 sfflags |= SFF_SAFEDIRPATH; 1585 } 1586 else 1587 sfflags |= SFF_SAFEDIRPATH; 1588 if (ret > E_PSEUDOBASE && 1589 !bitnset((forwarding ? 1590 DBS_FORWARDFILEINUNSAFEDIRPATHSAFE : 1591 DBS_INCLUDEFILEINUNSAFEDIRPATHSAFE), 1592 DontBlameSendmail)) 1593 { 1594 if (LogLevel > 11) 1595 sm_syslog(LOG_INFO, e->e_id, 1596 "%s: unsafe directory path, marked unsafe", 1597 shortenstring(fname, MAXSHORTSTR)); 1598 ctladdr->q_flags |= QUNSAFEADDR; 1599 } 1600 } 1601 *p = '/'; 1602 } 1603 1604 /* allow links only in unwritable directories */ 1605 if (!safedir && 1606 !bitnset((forwarding ? 1607 DBS_LINKEDFORWARDFILEINWRITABLEDIR : 1608 DBS_LINKEDINCLUDEFILEINWRITABLEDIR), 1609 DontBlameSendmail)) 1610 sfflags |= SFF_NOLINK; 1611 1612 rval = safefile(fname, uid, gid, user, sfflags, S_IREAD, &st); 1613 if (rval != 0) 1614 { 1615 /* don't use this :include: file */ 1616 if (tTd(27, 4)) 1617 sm_dprintf("include: not safe (uid=%d): %s\n", 1618 (int) uid, sm_errstring(rval)); 1619 } 1620 else if ((fp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, fname, 1621 SM_IO_RDONLY, NULL)) == NULL) 1622 { 1623 rval = errno; 1624 if (tTd(27, 4)) 1625 sm_dprintf("include: open: %s\n", sm_errstring(rval)); 1626 } 1627 else if (filechanged(fname, sm_io_getinfo(fp,SM_IO_WHAT_FD, NULL), &st)) 1628 { 1629 rval = E_SM_FILECHANGE; 1630 if (tTd(27, 4)) 1631 sm_dprintf("include: file changed after open\n"); 1632 } 1633 if (ev != NULL) 1634 sm_clrevent(ev); 1635 1636resetuid: 1637 1638#if HASSETREUID || USESETEUID 1639 if (saveduid == 0) 1640 { 1641 if (uid != 0) 1642 { 1643# if USESETEUID 1644 if (seteuid(0) < 0) 1645 syserr("!seteuid(0) failure (real=%d, eff=%d)", 1646 (int) getuid(), (int) geteuid()); 1647# else /* USESETEUID */ 1648 if (setreuid(-1, 0) < 0) 1649 syserr("!setreuid(-1, 0) failure (real=%d, eff=%d)", 1650 (int) getuid(), (int) geteuid()); 1651 if (setreuid(RealUid, 0) < 0) 1652 syserr("!setreuid(%d, 0) failure (real=%d, eff=%d)", 1653 (int) RealUid, (int) getuid(), 1654 (int) geteuid()); 1655# endif /* USESETEUID */ 1656 } 1657 if (setgid(savedgid) < 0) 1658 syserr("!setgid(%d) failure (real=%d eff=%d)", 1659 (int) savedgid, (int) getgid(), 1660 (int) getegid()); 1661 } 1662#endif /* HASSETREUID || USESETEUID */ 1663 1664 if (tTd(27, 9)) 1665 sm_dprintf("include: reset uid = %d/%d\n", 1666 (int) getuid(), (int) geteuid()); 1667 1668 if (rval == E_SM_OPENTIMEOUT) 1669 usrerr("451 4.4.1 open timeout on %s", fname); 1670 1671 if (fp == NULL) 1672 return rval; 1673 1674 if (fstat(sm_io_getinfo(fp, SM_IO_WHAT_FD, NULL), &st) < 0) 1675 { 1676 rval = errno; 1677 syserr("Cannot fstat %s!", fname); 1678 (void) sm_io_close(fp, SM_TIME_DEFAULT); 1679 return rval; 1680 } 1681 1682 /* if path was writable, check to avoid file giveaway tricks */ 1683 safechown = chownsafe(sm_io_getinfo(fp, SM_IO_WHAT_FD, NULL), safedir); 1684 if (tTd(27, 6)) 1685 sm_dprintf("include: parent of %s is %s, chown is %ssafe\n", 1686 fname, safedir ? "safe" : "dangerous", 1687 safechown ? "" : "un"); 1688 1689 /* if no controlling user or coming from an alias delivery */ 1690 if (safechown && 1691 (ca == NULL || 1692 (ca->q_uid == DefUid && ca->q_gid == 0))) 1693 { 1694 ctladdr->q_uid = st.st_uid; 1695 ctladdr->q_gid = st.st_gid; 1696 ctladdr->q_flags |= QGOODUID; 1697 } 1698 if (ca != NULL && ca->q_uid == st.st_uid) 1699 { 1700 /* optimization -- avoid getpwuid if we already have info */ 1701 ctladdr->q_flags |= ca->q_flags & QBOGUSSHELL; 1702 ctladdr->q_ruser = ca->q_ruser; 1703 } 1704 else if (!forwarding) 1705 { 1706 register struct passwd *pw; 1707 1708 pw = sm_getpwuid(st.st_uid); 1709 if (pw == NULL) 1710 { 1711 ctladdr->q_uid = st.st_uid; 1712 ctladdr->q_flags |= QBOGUSSHELL; 1713 } 1714 else 1715 { 1716 char *sh; 1717 1718 ctladdr->q_ruser = sm_rpool_strdup_x(e->e_rpool, 1719 pw->pw_name); 1720 if (safechown) 1721 sh = pw->pw_shell; 1722 else 1723 sh = "/SENDMAIL/ANY/SHELL/"; 1724 if (!usershellok(pw->pw_name, sh)) 1725 { 1726 if (LogLevel > 11) 1727 sm_syslog(LOG_INFO, e->e_id, 1728 "%s: user %s has bad shell %s, marked %s", 1729 shortenstring(fname, 1730 MAXSHORTSTR), 1731 pw->pw_name, sh, 1732 safechown ? "bogus" : "unsafe"); 1733 if (safechown) 1734 ctladdr->q_flags |= QBOGUSSHELL; 1735 else 1736 ctladdr->q_flags |= QUNSAFEADDR; 1737 } 1738 } 1739 } 1740 1741 if (bitset(EF_VRFYONLY, e->e_flags)) 1742 { 1743 /* don't do any more now */ 1744 ctladdr->q_state = QS_VERIFIED; 1745 e->e_nrcpts++; 1746 (void) sm_io_close(fp, SM_TIME_DEFAULT); 1747 return rval; 1748 } 1749 1750 /* 1751 ** Check to see if some bad guy can write this file 1752 ** 1753 ** Group write checking could be more clever, e.g., 1754 ** guessing as to which groups are actually safe ("sys" 1755 ** may be; "user" probably is not). 1756 */ 1757 1758 mode = S_IWOTH; 1759 if (!bitnset((forwarding ? 1760 DBS_GROUPWRITABLEFORWARDFILESAFE : 1761 DBS_GROUPWRITABLEINCLUDEFILESAFE), 1762 DontBlameSendmail)) 1763 mode |= S_IWGRP; 1764 1765 if (bitset(mode, st.st_mode)) 1766 { 1767 if (tTd(27, 6)) 1768 sm_dprintf("include: %s is %s writable, marked unsafe\n", 1769 shortenstring(fname, MAXSHORTSTR), 1770 bitset(S_IWOTH, st.st_mode) ? "world" 1771 : "group"); 1772 if (LogLevel > 11) 1773 sm_syslog(LOG_INFO, e->e_id, 1774 "%s: %s writable %s file, marked unsafe", 1775 shortenstring(fname, MAXSHORTSTR), 1776 bitset(S_IWOTH, st.st_mode) ? "world" : "group", 1777 forwarding ? "forward" : ":include:"); 1778 ctladdr->q_flags |= QUNSAFEADDR; 1779 } 1780 1781 /* read the file -- each line is a comma-separated list. */ 1782 FileName = fname; 1783 LineNumber = 0; 1784 ctladdr->q_flags &= ~QSELFREF; 1785 nincludes = 0; 1786 while (sm_io_fgets(fp, SM_TIME_DEFAULT, buf, sizeof buf) != NULL && 1787 !maxreached) 1788 { 1789 fixcrlf(buf, true); 1790 LineNumber++; 1791 if (buf[0] == '#' || buf[0] == '\0') 1792 continue; 1793 1794 /* <sp>#@# introduces a comment anywhere */ 1795 /* for Japanese character sets */ 1796 for (p = buf; (p = strchr(++p, '#')) != NULL; ) 1797 { 1798 if (p[1] == '@' && p[2] == '#' && 1799 isascii(p[-1]) && isspace(p[-1]) && 1800 (p[3] == '\0' || (isascii(p[3]) && isspace(p[3])))) 1801 { 1802 --p; 1803 while (p > buf && isascii(p[-1]) && 1804 isspace(p[-1])) 1805 --p; 1806 p[0] = '\0'; 1807 break; 1808 } 1809 } 1810 if (buf[0] == '\0') 1811 continue; 1812 1813 e->e_to = NULL; 1814 message("%s to %s", 1815 forwarding ? "forwarding" : "sending", buf); 1816 if (forwarding && LogLevel > 10) 1817 sm_syslog(LOG_INFO, e->e_id, 1818 "forward %.200s => %s", 1819 oldto, shortenstring(buf, MAXSHORTSTR)); 1820 1821 nincludes += sendtolist(buf, ctladdr, sendq, aliaslevel + 1, e); 1822 1823 if (forwarding && 1824 MaxForwardEntries > 0 && 1825 nincludes >= MaxForwardEntries) 1826 { 1827 /* just stop reading and processing further entries */ 1828#if 0 1829 /* additional: (?) */ 1830 ctladdr->q_state = QS_DONTSEND; 1831#endif /* 0 */ 1832 1833 syserr("Attempt to forward to more than %d addresses (in %s)!", 1834 MaxForwardEntries, fname); 1835 maxreached = true; 1836 } 1837 } 1838 1839 if (sm_io_error(fp) && tTd(27, 3)) 1840 sm_dprintf("include: read error: %s\n", sm_errstring(errno)); 1841 if (nincludes > 0 && !bitset(QSELFREF, ctladdr->q_flags)) 1842 { 1843 if (tTd(27, 5)) 1844 { 1845 sm_dprintf("include: QS_DONTSEND "); 1846 printaddr(ctladdr, false); 1847 } 1848 ctladdr->q_state = QS_DONTSEND; 1849 } 1850 1851 (void) sm_io_close(fp, SM_TIME_DEFAULT); 1852 FileName = oldfilename; 1853 LineNumber = oldlinenumber; 1854 e->e_to = oldto; 1855 return rval; 1856} 1857 1858static void 1859includetimeout() 1860{ 1861 /* 1862 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 1863 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 1864 ** DOING. 1865 */ 1866 1867 errno = ETIMEDOUT; 1868 longjmp(CtxIncludeTimeout, 1); 1869} 1870/* 1871** SENDTOARGV -- send to an argument vector. 1872** 1873** Parameters: 1874** argv -- argument vector to send to. 1875** e -- the current envelope. 1876** 1877** Returns: 1878** none. 1879** 1880** Side Effects: 1881** puts all addresses on the argument vector onto the 1882** send queue. 1883*/ 1884 1885void 1886sendtoargv(argv, e) 1887 register char **argv; 1888 register ENVELOPE *e; 1889{ 1890 register char *p; 1891 1892 while ((p = *argv++) != NULL) 1893 (void) sendtolist(p, NULLADDR, &e->e_sendqueue, 0, e); 1894} 1895/* 1896** GETCTLADDR -- get controlling address from an address header. 1897** 1898** If none, get one corresponding to the effective userid. 1899** 1900** Parameters: 1901** a -- the address to find the controller of. 1902** 1903** Returns: 1904** the controlling address. 1905*/ 1906 1907ADDRESS * 1908getctladdr(a) 1909 register ADDRESS *a; 1910{ 1911 while (a != NULL && !bitset(QGOODUID, a->q_flags)) 1912 a = a->q_alias; 1913 return a; 1914} 1915/* 1916** SELF_REFERENCE -- check to see if an address references itself 1917** 1918** The check is done through a chain of aliases. If it is part of 1919** a loop, break the loop at the "best" address, that is, the one 1920** that exists as a real user. 1921** 1922** This is to handle the case of: 1923** awc: Andrew.Chang 1924** Andrew.Chang: awc@mail.server 1925** which is a problem only on mail.server. 1926** 1927** Parameters: 1928** a -- the address to check. 1929** 1930** Returns: 1931** The address that should be retained. 1932*/ 1933 1934static ADDRESS * 1935self_reference(a) 1936 ADDRESS *a; 1937{ 1938 ADDRESS *b; /* top entry in self ref loop */ 1939 ADDRESS *c; /* entry that point to a real mail box */ 1940 1941 if (tTd(27, 1)) 1942 sm_dprintf("self_reference(%s)\n", a->q_paddr); 1943 1944 for (b = a->q_alias; b != NULL; b = b->q_alias) 1945 { 1946 if (sameaddr(a, b)) 1947 break; 1948 } 1949 1950 if (b == NULL) 1951 { 1952 if (tTd(27, 1)) 1953 sm_dprintf("\t... no self ref\n"); 1954 return NULL; 1955 } 1956 1957 /* 1958 ** Pick the first address that resolved to a real mail box 1959 ** i.e has a mbdb entry. The returned value will be marked 1960 ** QSELFREF in recipient(), which in turn will disable alias() 1961 ** from marking it as QS_IS_DEAD(), which mean it will be used 1962 ** as a deliverable address. 1963 ** 1964 ** The 2 key thing to note here are: 1965 ** 1) we are in a recursive call sequence: 1966 ** alias->sendtolist->recipient->alias 1967 ** 2) normally, when we return back to alias(), the address 1968 ** will be marked QS_EXPANDED, since alias() assumes the 1969 ** expanded form will be used instead of the current address. 1970 ** This behaviour is turned off if the address is marked 1971 ** QSELFREF. We set QSELFREF when we return to recipient(). 1972 */ 1973 1974 c = a; 1975 while (c != NULL) 1976 { 1977 if (tTd(27, 10)) 1978 sm_dprintf(" %s", c->q_user); 1979 if (bitnset(M_HASPWENT, c->q_mailer->m_flags)) 1980 { 1981 SM_MBDB_T user; 1982 1983 if (tTd(27, 2)) 1984 sm_dprintf("\t... getpwnam(%s)... ", c->q_user); 1985 if (sm_mbdb_lookup(c->q_user, &user) == EX_OK) 1986 { 1987 if (tTd(27, 2)) 1988 sm_dprintf("found\n"); 1989 1990 /* ought to cache results here */ 1991 if (sameaddr(b, c)) 1992 return b; 1993 else 1994 return c; 1995 } 1996 if (tTd(27, 2)) 1997 sm_dprintf("failed\n"); 1998 } 1999 else 2000 { 2001 /* if local delivery, compare usernames */ 2002 if (bitnset(M_LOCALMAILER, c->q_mailer->m_flags) && 2003 b->q_mailer == c->q_mailer) 2004 { 2005 if (tTd(27, 2)) 2006 sm_dprintf("\t... local match (%s)\n", 2007 c->q_user); 2008 if (sameaddr(b, c)) 2009 return b; 2010 else 2011 return c; 2012 } 2013 } 2014 if (tTd(27, 10)) 2015 sm_dprintf("\n"); 2016 c = c->q_alias; 2017 } 2018 2019 if (tTd(27, 1)) 2020 sm_dprintf("\t... cannot break loop for \"%s\"\n", a->q_paddr); 2021 2022 return NULL; 2023} 2024