138032Speter/* 2168515Sgshapiro * Copyright (c) 1998-2003, 2006 Sendmail, Inc. and its suppliers. 364562Sgshapiro * All rights reserved. 438032Speter * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 538032Speter * Copyright (c) 1988, 1993 638032Speter * The Regents of the University of California. All rights reserved. 738032Speter * 838032Speter * By using this file, you agree to the terms and conditions set 938032Speter * forth in the LICENSE file which can be found at the top level of 1038032Speter * the sendmail distribution. 1138032Speter * 1238032Speter */ 1338032Speter 1464562Sgshapiro#include <sendmail.h> 1538032Speter 16223067SgshapiroSM_RCSID("@(#)$Id: envelope.c,v 8.312 2010/02/03 16:36:40 ca Exp $") 1764562Sgshapiro 1838032Speter/* 19110560Sgshapiro** CLRSESSENVELOPE -- clear session oriented data in an envelope 20110560Sgshapiro** 21110560Sgshapiro** Parameters: 22110560Sgshapiro** e -- the envelope to clear. 23110560Sgshapiro** 24110560Sgshapiro** Returns: 25110560Sgshapiro** none. 26110560Sgshapiro*/ 27110560Sgshapiro 28110560Sgshapirovoid 29110560Sgshapiroclrsessenvelope(e) 30110560Sgshapiro ENVELOPE *e; 31110560Sgshapiro{ 32110560Sgshapiro#if SASL 33110560Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{auth_type}"), ""); 34110560Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{auth_authen}"), ""); 35110560Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{auth_author}"), ""); 36110560Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{auth_ssf}"), ""); 37110560Sgshapiro#endif /* SASL */ 38110560Sgshapiro#if STARTTLS 39110560Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{cert_issuer}"), ""); 40110560Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{cert_subject}"), ""); 41110560Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{cipher_bits}"), ""); 42110560Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{cipher}"), ""); 43110560Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{tls_version}"), ""); 44110560Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{verify}"), ""); 45110560Sgshapiro# if _FFR_TLS_1 46110560Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{alg_bits}"), ""); 47110560Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{cn_issuer}"), ""); 48110560Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{cn_subject}"), ""); 49110560Sgshapiro# endif /* _FFR_TLS_1 */ 50110560Sgshapiro#endif /* STARTTLS */ 51110560Sgshapiro} 52110560Sgshapiro 53110560Sgshapiro/* 5490792Sgshapiro** NEWENVELOPE -- fill in a new envelope 5538032Speter** 5638032Speter** Supports inheritance. 5738032Speter** 5838032Speter** Parameters: 5938032Speter** e -- the new envelope to fill in. 6038032Speter** parent -- the envelope to be the parent of e. 6190792Sgshapiro** rpool -- either NULL, or a pointer to a resource pool 6290792Sgshapiro** from which envelope memory is allocated, and 6390792Sgshapiro** to which envelope resources are attached. 6438032Speter** 6538032Speter** Returns: 6638032Speter** e. 6738032Speter** 6838032Speter** Side Effects: 6938032Speter** none. 7038032Speter*/ 7138032Speter 7238032SpeterENVELOPE * 7390792Sgshapironewenvelope(e, parent, rpool) 7438032Speter register ENVELOPE *e; 7538032Speter register ENVELOPE *parent; 7690792Sgshapiro SM_RPOOL_T *rpool; 7738032Speter{ 78182352Sgshapiro int sendmode; 79157001Sgshapiro 8090792Sgshapiro /* 8190792Sgshapiro ** This code used to read: 8290792Sgshapiro ** if (e == parent && e->e_parent != NULL) 8390792Sgshapiro ** parent = e->e_parent; 8490792Sgshapiro ** So if e == parent && e->e_parent == NULL then we would 8590792Sgshapiro ** set e->e_parent = e, which creates a loop in the e_parent chain. 8690792Sgshapiro ** This meant macvalue() could go into an infinite loop. 8790792Sgshapiro */ 8890792Sgshapiro 89157001Sgshapiro if (parent != NULL) 90157001Sgshapiro sendmode = parent->e_sendmode; 91157001Sgshapiro else 92157001Sgshapiro sendmode = DM_NOTSET; 93157001Sgshapiro 9490792Sgshapiro if (e == parent) 9538032Speter parent = e->e_parent; 9690792Sgshapiro clearenvelope(e, true, rpool); 9738032Speter if (e == CurEnv) 9864562Sgshapiro memmove((char *) &e->e_from, 9964562Sgshapiro (char *) &NullAddress, 100168515Sgshapiro sizeof(e->e_from)); 10138032Speter else 10264562Sgshapiro memmove((char *) &e->e_from, 10364562Sgshapiro (char *) &CurEnv->e_from, 104168515Sgshapiro sizeof(e->e_from)); 10538032Speter e->e_parent = parent; 10664562Sgshapiro assign_queueid(e); 10738032Speter e->e_ctime = curtime(); 108173340Sgshapiro#if _FFR_SESSID 109173340Sgshapiro e->e_sessid = e->e_id; 110173340Sgshapiro#endif /* _FFR_SESSID */ 11138032Speter if (parent != NULL) 11290792Sgshapiro { 11338032Speter e->e_msgpriority = parent->e_msgsize; 114173340Sgshapiro#if _FFR_SESSID 115173340Sgshapiro if (parent->e_sessid != NULL) 116173340Sgshapiro e->e_sessid = sm_rpool_strdup_x(rpool, 117173340Sgshapiro parent->e_sessid); 118173340Sgshapiro#endif /* _FFR_SESSID */ 119173340Sgshapiro 12090792Sgshapiro if (parent->e_quarmsg == NULL) 12190792Sgshapiro { 12290792Sgshapiro e->e_quarmsg = NULL; 12390792Sgshapiro macdefine(&e->e_macro, A_PERM, 12490792Sgshapiro macid("{quarantine}"), ""); 12590792Sgshapiro } 12690792Sgshapiro else 12790792Sgshapiro { 12890792Sgshapiro e->e_quarmsg = sm_rpool_strdup_x(rpool, 12990792Sgshapiro parent->e_quarmsg); 13090792Sgshapiro macdefine(&e->e_macro, A_PERM, 13190792Sgshapiro macid("{quarantine}"), e->e_quarmsg); 13290792Sgshapiro } 13390792Sgshapiro } 13438032Speter e->e_puthdr = putheader; 13538032Speter e->e_putbody = putbody; 13638032Speter if (CurEnv->e_xfp != NULL) 13790792Sgshapiro (void) sm_io_flush(CurEnv->e_xfp, SM_TIME_DEFAULT); 138157001Sgshapiro if (sendmode != DM_NOTSET) 139182352Sgshapiro set_delivery_mode(sendmode, e); 14038032Speter 14164562Sgshapiro return e; 14238032Speter} 14390792Sgshapiro 14490792Sgshapiro/* values for msg_timeout, see also IS_* below for usage (bit layout) */ 14590792Sgshapiro#define MSG_T_O 0x01 /* normal timeout */ 14690792Sgshapiro#define MSG_T_O_NOW 0x02 /* NOW timeout */ 14790792Sgshapiro#define MSG_NOT_BY 0x04 /* Deliver-By time exceeded, mode R */ 14890792Sgshapiro#define MSG_WARN 0x10 /* normal queue warning */ 14990792Sgshapiro#define MSG_WARN_BY 0x20 /* Deliver-By time exceeded, mode N */ 15090792Sgshapiro 15190792Sgshapiro#define IS_MSG_ERR(x) (((x) & 0x0f) != 0) /* return an error */ 15290792Sgshapiro 15390792Sgshapiro/* immediate return */ 15490792Sgshapiro#define IS_IMM_RET(x) (((x) & (MSG_T_O_NOW|MSG_NOT_BY)) != 0) 15590792Sgshapiro#define IS_MSG_WARN(x) (((x) & 0xf0) != 0) /* return a warning */ 15690792Sgshapiro 15790792Sgshapiro/* 15838032Speter** DROPENVELOPE -- deallocate an envelope. 15938032Speter** 16038032Speter** Parameters: 16138032Speter** e -- the envelope to deallocate. 16238032Speter** fulldrop -- if set, do return receipts. 16390792Sgshapiro** split -- if true, split by recipient if message is queued up 16438032Speter** 16538032Speter** Returns: 166203004Sgshapiro** EX_* status (currently: 0: success, EX_IOERR on panic) 16738032Speter** 16838032Speter** Side Effects: 16938032Speter** housekeeping necessary to dispose of an envelope. 17038032Speter** Unlocks this queue file. 17138032Speter*/ 17238032Speter 173203004Sgshapiroint 17490792Sgshapirodropenvelope(e, fulldrop, split) 17538032Speter register ENVELOPE *e; 17638032Speter bool fulldrop; 17790792Sgshapiro bool split; 17838032Speter{ 17990792Sgshapiro bool panic = false; 18090792Sgshapiro bool queueit = false; 18190792Sgshapiro int msg_timeout = 0; 18290792Sgshapiro bool failure_return = false; 18390792Sgshapiro bool delay_return = false; 18490792Sgshapiro bool success_return = false; 18564562Sgshapiro bool pmnotify = bitset(EF_PM_NOTIFY, e->e_flags); 18690792Sgshapiro bool done = false; 18738032Speter register ADDRESS *q; 18838032Speter char *id = e->e_id; 18971345Sgshapiro time_t now; 19038032Speter char buf[MAXLINE]; 19138032Speter 19238032Speter if (tTd(50, 1)) 19338032Speter { 19490792Sgshapiro sm_dprintf("dropenvelope %p: id=", e); 195132943Sgshapiro xputs(sm_debug_file(), e->e_id); 19690792Sgshapiro sm_dprintf(", flags="); 19738032Speter printenvflags(e); 19838032Speter if (tTd(50, 10)) 19938032Speter { 20090792Sgshapiro sm_dprintf("sendq="); 201132943Sgshapiro printaddr(sm_debug_file(), e->e_sendqueue, true); 20238032Speter } 20338032Speter } 20438032Speter 20538032Speter if (LogLevel > 84) 20638032Speter sm_syslog(LOG_DEBUG, id, 20764562Sgshapiro "dropenvelope, e_flags=0x%lx, OpMode=%c, pid=%d", 20890792Sgshapiro e->e_flags, OpMode, (int) CurrentPid); 20938032Speter 21038032Speter /* we must have an id to remove disk files */ 21138032Speter if (id == NULL) 212203004Sgshapiro return EX_OK; 21338032Speter 21438032Speter /* if verify-only mode, we can skip most of this */ 21538032Speter if (OpMode == MD_VERIFY) 21638032Speter goto simpledrop; 21738032Speter 218203004Sgshapiro if (tTd(92, 2)) 219203004Sgshapiro sm_dprintf("dropenvelope: e_id=%s, EF_LOGSENDER=%d, LogLevel=%d\n", 220203004Sgshapiro e->e_id, bitset(EF_LOGSENDER, e->e_flags), LogLevel); 22138032Speter if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags)) 22238032Speter logsender(e, NULL); 22338032Speter e->e_flags &= ~EF_LOGSENDER; 22438032Speter 22538032Speter /* post statistics */ 22638032Speter poststats(StatFile); 22738032Speter 22838032Speter /* 22938032Speter ** Extract state information from dregs of send list. 23038032Speter */ 23138032Speter 23271345Sgshapiro now = curtime(); 23377349Sgshapiro if (now >= e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass]) 23490792Sgshapiro msg_timeout = MSG_T_O; 23590792Sgshapiro if (IS_DLVR_RETURN(e) && e->e_deliver_by > 0 && 23690792Sgshapiro now >= e->e_ctime + e->e_deliver_by && 23764562Sgshapiro !bitset(EF_RESPONSE, e->e_flags)) 23864562Sgshapiro { 23990792Sgshapiro msg_timeout = MSG_NOT_BY; 24064562Sgshapiro e->e_flags |= EF_FATALERRS|EF_CLRQUEUE; 24164562Sgshapiro } 24290792Sgshapiro else if (TimeOuts.to_q_return[e->e_timeoutclass] == NOW && 24390792Sgshapiro !bitset(EF_RESPONSE, e->e_flags)) 24490792Sgshapiro { 24590792Sgshapiro msg_timeout = MSG_T_O_NOW; 24690792Sgshapiro e->e_flags |= EF_FATALERRS|EF_CLRQUEUE; 24790792Sgshapiro } 24864562Sgshapiro 249223067Sgshapiro 25038032Speter e->e_flags &= ~EF_QUEUERUN; 25138032Speter for (q = e->e_sendqueue; q != NULL; q = q->q_next) 25238032Speter { 25364562Sgshapiro if (QS_IS_UNDELIVERED(q->q_state)) 25490792Sgshapiro queueit = true; 25538032Speter 256223067Sgshapiro 25738032Speter /* see if a notification is needed */ 25838032Speter if (bitset(QPINGONFAILURE, q->q_flags) && 25990792Sgshapiro ((IS_MSG_ERR(msg_timeout) && 26090792Sgshapiro QS_IS_UNDELIVERED(q->q_state)) || 26164562Sgshapiro QS_IS_BADADDR(q->q_state) || 26290792Sgshapiro IS_IMM_RET(msg_timeout))) 26338032Speter { 26490792Sgshapiro failure_return = true; 26564562Sgshapiro if (!done && q->q_owner == NULL && 26664562Sgshapiro !emptyaddr(&e->e_from)) 26764562Sgshapiro { 26838032Speter (void) sendtolist(e->e_from.q_paddr, NULLADDR, 26938032Speter &e->e_errorqueue, 0, e); 27090792Sgshapiro done = true; 27164562Sgshapiro } 27238032Speter } 27390792Sgshapiro else if ((bitset(QPINGONSUCCESS, q->q_flags) && 27490792Sgshapiro ((QS_IS_SENT(q->q_state) && 27590792Sgshapiro bitnset(M_LOCALMAILER, q->q_mailer->m_flags)) || 27690792Sgshapiro bitset(QRELAYED|QEXPANDED|QDELIVERED, q->q_flags))) || 27790792Sgshapiro bitset(QBYTRACE, q->q_flags) || 27890792Sgshapiro bitset(QBYNRELAY, q->q_flags)) 27938032Speter { 28090792Sgshapiro success_return = true; 28138032Speter } 28238032Speter } 28338032Speter 28438032Speter if (e->e_class < 0) 28538032Speter e->e_flags |= EF_NO_BODY_RETN; 28638032Speter 28738032Speter /* 28838032Speter ** See if the message timed out. 28938032Speter */ 29038032Speter 29138032Speter if (!queueit) 29264562Sgshapiro /* EMPTY */ 29338032Speter /* nothing to do */ ; 29490792Sgshapiro else if (IS_MSG_ERR(msg_timeout)) 29538032Speter { 29638032Speter if (failure_return) 29738032Speter { 29890792Sgshapiro if (msg_timeout == MSG_NOT_BY) 29990792Sgshapiro { 300168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), 30190792Sgshapiro "delivery time expired %lds", 30290792Sgshapiro e->e_deliver_by); 30390792Sgshapiro } 30490792Sgshapiro else 30590792Sgshapiro { 306168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), 30764562Sgshapiro "Cannot send message for %s", 30890792Sgshapiro pintvl(TimeOuts.to_q_return[e->e_timeoutclass], 30990792Sgshapiro false)); 31090792Sgshapiro } 31190792Sgshapiro 31290792Sgshapiro /* don't free, allocated from e_rpool */ 31390792Sgshapiro e->e_message = sm_rpool_strdup_x(e->e_rpool, buf); 31438032Speter message(buf); 31538032Speter e->e_flags |= EF_CLRQUEUE; 31638032Speter } 31790792Sgshapiro if (msg_timeout == MSG_NOT_BY) 31890792Sgshapiro { 31990792Sgshapiro (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, 32090792Sgshapiro "Delivery time (%lds) expired\n", 32190792Sgshapiro e->e_deliver_by); 32290792Sgshapiro } 32390792Sgshapiro else 32490792Sgshapiro (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, 32590792Sgshapiro "Message could not be delivered for %s\n", 32690792Sgshapiro pintvl(TimeOuts.to_q_return[e->e_timeoutclass], 32790792Sgshapiro false)); 32890792Sgshapiro (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, 32990792Sgshapiro "Message will be deleted from queue\n"); 33038032Speter for (q = e->e_sendqueue; q != NULL; q = q->q_next) 33138032Speter { 33264562Sgshapiro if (QS_IS_UNDELIVERED(q->q_state)) 33338032Speter { 33464562Sgshapiro q->q_state = QS_BADADDR; 33590792Sgshapiro if (msg_timeout == MSG_NOT_BY) 33690792Sgshapiro q->q_status = "5.4.7"; 33790792Sgshapiro else 33890792Sgshapiro q->q_status = "4.4.7"; 33938032Speter } 34038032Speter } 34138032Speter } 34290792Sgshapiro else 34338032Speter { 34490792Sgshapiro if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 && 34590792Sgshapiro now >= e->e_ctime + 34690792Sgshapiro TimeOuts.to_q_warning[e->e_timeoutclass]) 34790792Sgshapiro msg_timeout = MSG_WARN; 34890792Sgshapiro else if (IS_DLVR_NOTIFY(e) && 34990792Sgshapiro e->e_deliver_by > 0 && 35090792Sgshapiro now >= e->e_ctime + e->e_deliver_by) 35190792Sgshapiro msg_timeout = MSG_WARN_BY; 35290792Sgshapiro 35390792Sgshapiro if (IS_MSG_WARN(msg_timeout)) 35438032Speter { 35590792Sgshapiro if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) && 35690792Sgshapiro e->e_class >= 0 && 35790792Sgshapiro e->e_from.q_paddr != NULL && 35890792Sgshapiro strcmp(e->e_from.q_paddr, "<>") != 0 && 35990792Sgshapiro sm_strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 && 36090792Sgshapiro (strlen(e->e_from.q_paddr) <= 8 || 36190792Sgshapiro sm_strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8], 36290792Sgshapiro "-request") != 0)) 36338032Speter { 36490792Sgshapiro for (q = e->e_sendqueue; q != NULL; 36590792Sgshapiro q = q->q_next) 36690792Sgshapiro { 36790792Sgshapiro if (QS_IS_UNDELIVERED(q->q_state) 36864562Sgshapiro#if _FFR_NODELAYDSN_ON_HOLD 36990792Sgshapiro && !bitnset(M_HOLD, 37090792Sgshapiro q->q_mailer->m_flags) 37164562Sgshapiro#endif /* _FFR_NODELAYDSN_ON_HOLD */ 37290792Sgshapiro ) 37390792Sgshapiro { 37490792Sgshapiro if (msg_timeout == 37590792Sgshapiro MSG_WARN_BY && 37690792Sgshapiro (bitset(QPINGONDELAY, 37790792Sgshapiro q->q_flags) || 37890792Sgshapiro !bitset(QHASNOTIFY, 37990792Sgshapiro q->q_flags)) 38090792Sgshapiro ) 38190792Sgshapiro { 38290792Sgshapiro q->q_flags |= QBYNDELAY; 38390792Sgshapiro delay_return = true; 38490792Sgshapiro } 38590792Sgshapiro if (bitset(QPINGONDELAY, 38690792Sgshapiro q->q_flags)) 38790792Sgshapiro { 38890792Sgshapiro q->q_flags |= QDELAYED; 38990792Sgshapiro delay_return = true; 39090792Sgshapiro } 39190792Sgshapiro } 39290792Sgshapiro } 39390792Sgshapiro } 39490792Sgshapiro if (delay_return) 39590792Sgshapiro { 39690792Sgshapiro if (msg_timeout == MSG_WARN_BY) 39738032Speter { 398168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), 39990792Sgshapiro "Warning: Delivery time (%lds) exceeded", 40090792Sgshapiro e->e_deliver_by); 40138032Speter } 40290792Sgshapiro else 403168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), 40490792Sgshapiro "Warning: could not send message for past %s", 40590792Sgshapiro pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], 40690792Sgshapiro false)); 40790792Sgshapiro 40890792Sgshapiro /* don't free, allocated from e_rpool */ 40990792Sgshapiro e->e_message = sm_rpool_strdup_x(e->e_rpool, 41090792Sgshapiro buf); 41190792Sgshapiro message(buf); 41290792Sgshapiro e->e_flags |= EF_WARNING; 41338032Speter } 41490792Sgshapiro if (msg_timeout == MSG_WARN_BY) 41590792Sgshapiro { 41690792Sgshapiro (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, 41790792Sgshapiro "Warning: Delivery time (%lds) exceeded\n", 41890792Sgshapiro e->e_deliver_by); 41990792Sgshapiro } 42090792Sgshapiro else 42190792Sgshapiro (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, 42290792Sgshapiro "Warning: message still undelivered after %s\n", 42390792Sgshapiro pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], 42490792Sgshapiro false)); 42590792Sgshapiro (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, 42690792Sgshapiro "Will keep trying until message is %s old\n", 42790792Sgshapiro pintvl(TimeOuts.to_q_return[e->e_timeoutclass], 42890792Sgshapiro false)); 42938032Speter } 43038032Speter } 43138032Speter 43238032Speter if (tTd(50, 2)) 43390792Sgshapiro sm_dprintf("failure_return=%d delay_return=%d success_return=%d queueit=%d\n", 43438032Speter failure_return, delay_return, success_return, queueit); 43538032Speter 43638032Speter /* 43738032Speter ** If we had some fatal error, but no addresses are marked as 43838032Speter ** bad, mark them _all_ as bad. 43938032Speter */ 44038032Speter 44138032Speter if (bitset(EF_FATALERRS, e->e_flags) && !failure_return) 44238032Speter { 44338032Speter for (q = e->e_sendqueue; q != NULL; q = q->q_next) 44438032Speter { 44564562Sgshapiro if ((QS_IS_OK(q->q_state) || 44664562Sgshapiro QS_IS_VERIFIED(q->q_state)) && 44738032Speter bitset(QPINGONFAILURE, q->q_flags)) 44838032Speter { 44990792Sgshapiro failure_return = true; 45064562Sgshapiro q->q_state = QS_BADADDR; 45138032Speter } 45238032Speter } 45338032Speter } 45438032Speter 45538032Speter /* 45638032Speter ** Send back return receipts as requested. 45738032Speter */ 45838032Speter 45938032Speter if (success_return && !failure_return && !delay_return && fulldrop && 46038032Speter !bitset(PRIV_NORECEIPTS, PrivacyFlags) && 46138032Speter strcmp(e->e_from.q_paddr, "<>") != 0) 46238032Speter { 46338032Speter auto ADDRESS *rlist = NULL; 46438032Speter 46538032Speter if (tTd(50, 8)) 46690792Sgshapiro sm_dprintf("dropenvelope(%s): sending return receipt\n", 46764562Sgshapiro id); 46838032Speter e->e_flags |= EF_SENDRECEIPT; 46938032Speter (void) sendtolist(e->e_from.q_paddr, NULLADDR, &rlist, 0, e); 47038032Speter (void) returntosender("Return receipt", rlist, RTSF_NO_BODY, e); 47138032Speter } 47238032Speter e->e_flags &= ~EF_SENDRECEIPT; 47338032Speter 47438032Speter /* 47538032Speter ** Arrange to send error messages if there are fatal errors. 47638032Speter */ 47738032Speter 47838032Speter if ((failure_return || delay_return) && e->e_errormode != EM_QUIET) 47938032Speter { 48038032Speter if (tTd(50, 8)) 48190792Sgshapiro sm_dprintf("dropenvelope(%s): saving mail\n", id); 48290792Sgshapiro panic = savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags)); 48338032Speter } 48438032Speter 48538032Speter /* 48638032Speter ** Arrange to send warning messages to postmaster as requested. 48738032Speter */ 48838032Speter 48964562Sgshapiro if ((failure_return || pmnotify) && 49038032Speter PostMasterCopy != NULL && 49164562Sgshapiro !bitset(EF_RESPONSE, e->e_flags) && 49264562Sgshapiro e->e_class >= 0) 49338032Speter { 49438032Speter auto ADDRESS *rlist = NULL; 49564562Sgshapiro char pcopy[MAXNAME]; 49638032Speter 49764562Sgshapiro if (failure_return) 49864562Sgshapiro { 499168515Sgshapiro expand(PostMasterCopy, pcopy, sizeof(pcopy), e); 50064562Sgshapiro 50164562Sgshapiro if (tTd(50, 8)) 50290792Sgshapiro sm_dprintf("dropenvelope(%s): sending postmaster copy to %s\n", 50364562Sgshapiro id, pcopy); 50464562Sgshapiro (void) sendtolist(pcopy, NULLADDR, &rlist, 0, e); 50564562Sgshapiro } 50664562Sgshapiro if (pmnotify) 50764562Sgshapiro (void) sendtolist("postmaster", NULLADDR, 50864562Sgshapiro &rlist, 0, e); 50964562Sgshapiro (void) returntosender(e->e_message, rlist, 51064562Sgshapiro RTSF_PM_BOUNCE|RTSF_NO_BODY, e); 51138032Speter } 51238032Speter 51338032Speter /* 51438032Speter ** Instantiate or deinstantiate the queue. 51538032Speter */ 51638032Speter 51738032Spetersimpledrop: 51838032Speter if (tTd(50, 8)) 51990792Sgshapiro sm_dprintf("dropenvelope(%s): at simpledrop, queueit=%d\n", 52038032Speter id, queueit); 52138032Speter if (!queueit || bitset(EF_CLRQUEUE, e->e_flags)) 52238032Speter { 52338032Speter if (tTd(50, 1)) 52438032Speter { 52590792Sgshapiro sm_dprintf("\n===== Dropping queue files for %s... queueit=%d, e_flags=", 52638032Speter e->e_id, queueit); 52738032Speter printenvflags(e); 52838032Speter } 52990792Sgshapiro if (!panic) 530159609Sgshapiro { 531159609Sgshapiro if (e->e_dfp != NULL) 532159609Sgshapiro { 533159609Sgshapiro (void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT); 534159609Sgshapiro e->e_dfp = NULL; 535159609Sgshapiro } 53690792Sgshapiro (void) xunlink(queuename(e, DATAFL_LETTER)); 537159609Sgshapiro } 53890792Sgshapiro if (panic && QueueMode == QM_LOST) 53990792Sgshapiro { 54090792Sgshapiro /* 54190792Sgshapiro ** leave the Qf file behind as 54290792Sgshapiro ** the delivery attempt failed. 54390792Sgshapiro */ 54438032Speter 54590792Sgshapiro /* EMPTY */ 54690792Sgshapiro } 54790792Sgshapiro else 54890792Sgshapiro if (xunlink(queuename(e, ANYQFL_LETTER)) == 0) 54990792Sgshapiro { 55090792Sgshapiro /* add to available space in filesystem */ 551147078Sgshapiro updfs(e, -1, panic ? 0 : -1, "dropenvelope"); 55290792Sgshapiro } 55390792Sgshapiro 55464562Sgshapiro if (e->e_ntries > 0 && LogLevel > 9) 55564562Sgshapiro sm_syslog(LOG_INFO, id, "done; delay=%s, ntries=%d", 55690792Sgshapiro pintvl(curtime() - e->e_ctime, true), 55764562Sgshapiro e->e_ntries); 55838032Speter } 55938032Speter else if (queueit || !bitset(EF_INQUEUE, e->e_flags)) 56038032Speter { 56190792Sgshapiro if (!split) 56290792Sgshapiro queueup(e, false, true); 56390792Sgshapiro else 56490792Sgshapiro { 56590792Sgshapiro ENVELOPE *oldsib; 56690792Sgshapiro ENVELOPE *ee; 56790792Sgshapiro 56890792Sgshapiro /* 56990792Sgshapiro ** Save old sibling and set it to NULL to avoid 57090792Sgshapiro ** queueing up the same envelopes again. 57190792Sgshapiro ** This requires that envelopes in that list have 57290792Sgshapiro ** been take care of before (or at some other place). 57390792Sgshapiro */ 57490792Sgshapiro 57590792Sgshapiro oldsib = e->e_sibling; 57690792Sgshapiro e->e_sibling = NULL; 57790792Sgshapiro if (!split_by_recipient(e) && 57890792Sgshapiro bitset(EF_FATALERRS, e->e_flags)) 57990792Sgshapiro { 58090792Sgshapiro syserr("!dropenvelope(%s): cannot commit data file %s, uid=%d", 58190792Sgshapiro e->e_id, queuename(e, DATAFL_LETTER), 58298121Sgshapiro (int) geteuid()); 58390792Sgshapiro } 58490792Sgshapiro for (ee = e->e_sibling; ee != NULL; ee = ee->e_sibling) 58590792Sgshapiro queueup(ee, false, true); 58690792Sgshapiro queueup(e, false, true); 58790792Sgshapiro 58890792Sgshapiro /* clean up */ 58990792Sgshapiro for (ee = e->e_sibling; ee != NULL; ee = ee->e_sibling) 59090792Sgshapiro { 59190792Sgshapiro /* now unlock the job */ 59290792Sgshapiro if (tTd(50, 8)) 59390792Sgshapiro sm_dprintf("dropenvelope(%s): unlocking job\n", 59490792Sgshapiro ee->e_id); 59590792Sgshapiro closexscript(ee); 59690792Sgshapiro unlockqueue(ee); 59790792Sgshapiro 59890792Sgshapiro /* this envelope is marked unused */ 59990792Sgshapiro if (ee->e_dfp != NULL) 60090792Sgshapiro { 60190792Sgshapiro (void) sm_io_close(ee->e_dfp, 60290792Sgshapiro SM_TIME_DEFAULT); 60390792Sgshapiro ee->e_dfp = NULL; 60490792Sgshapiro } 60590792Sgshapiro ee->e_id = NULL; 60690792Sgshapiro ee->e_flags &= ~EF_HAS_DF; 60790792Sgshapiro } 60890792Sgshapiro e->e_sibling = oldsib; 60990792Sgshapiro } 61038032Speter } 61138032Speter 61238032Speter /* now unlock the job */ 61338032Speter if (tTd(50, 8)) 61490792Sgshapiro sm_dprintf("dropenvelope(%s): unlocking job\n", id); 61538032Speter closexscript(e); 61638032Speter unlockqueue(e); 61738032Speter 61838032Speter /* make sure that this envelope is marked unused */ 61938032Speter if (e->e_dfp != NULL) 62090792Sgshapiro { 62190792Sgshapiro (void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT); 62290792Sgshapiro e->e_dfp = NULL; 62390792Sgshapiro } 62438032Speter e->e_id = NULL; 62538032Speter e->e_flags &= ~EF_HAS_DF; 626203004Sgshapiro if (panic) 627203004Sgshapiro return EX_IOERR; 628203004Sgshapiro return EX_OK; 62938032Speter} 630203004Sgshapiro 63190792Sgshapiro/* 63238032Speter** CLEARENVELOPE -- clear an envelope without unlocking 63338032Speter** 63438032Speter** This is normally used by a child process to get a clean 63538032Speter** envelope without disturbing the parent. 63638032Speter** 63738032Speter** Parameters: 63838032Speter** e -- the envelope to clear. 63938032Speter** fullclear - if set, the current envelope is total 64038032Speter** garbage and should be ignored; otherwise, 64138032Speter** release any resources it may indicate. 64290792Sgshapiro** rpool -- either NULL, or a pointer to a resource pool 64390792Sgshapiro** from which envelope memory is allocated, and 64490792Sgshapiro** to which envelope resources are attached. 64538032Speter** 64638032Speter** Returns: 64738032Speter** none. 64838032Speter** 64938032Speter** Side Effects: 65038032Speter** Closes files associated with the envelope. 65138032Speter** Marks the envelope as unallocated. 65238032Speter*/ 65338032Speter 65438032Spetervoid 65590792Sgshapiroclearenvelope(e, fullclear, rpool) 65638032Speter register ENVELOPE *e; 65738032Speter bool fullclear; 65890792Sgshapiro SM_RPOOL_T *rpool; 65938032Speter{ 66038032Speter register HDR *bh; 66138032Speter register HDR **nhp; 66238032Speter extern ENVELOPE BlankEnvelope; 66390792Sgshapiro char **p; 66438032Speter 66538032Speter if (!fullclear) 66638032Speter { 66738032Speter /* clear out any file information */ 66838032Speter if (e->e_xfp != NULL) 66990792Sgshapiro (void) sm_io_close(e->e_xfp, SM_TIME_DEFAULT); 67038032Speter if (e->e_dfp != NULL) 67190792Sgshapiro (void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT); 67238032Speter e->e_xfp = e->e_dfp = NULL; 67338032Speter } 67438032Speter 67590792Sgshapiro /* 67690792Sgshapiro ** Copy BlankEnvelope into *e. 67790792Sgshapiro ** It is not safe to simply copy pointers to strings; 67890792Sgshapiro ** the strings themselves must be copied (or set to NULL). 67990792Sgshapiro ** The problem is that when we assign a new string value to 68090792Sgshapiro ** a member of BlankEnvelope, we free the old string. 68190792Sgshapiro ** We did not need to do this copying in sendmail 8.11 :-( 68290792Sgshapiro ** and it is a potential performance hit. Reference counted 68390792Sgshapiro ** strings are one way out. 68490792Sgshapiro */ 68590792Sgshapiro 68690792Sgshapiro *e = BlankEnvelope; 68738032Speter e->e_message = NULL; 68890792Sgshapiro e->e_qfletter = '\0'; 68990792Sgshapiro e->e_quarmsg = NULL; 69090792Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), ""); 69190792Sgshapiro 69290792Sgshapiro /* 69390792Sgshapiro ** Copy the macro table. 69490792Sgshapiro ** We might be able to avoid this by zeroing the macro table 69590792Sgshapiro ** and always searching BlankEnvelope.e_macro after e->e_macro 69690792Sgshapiro ** in macvalue(). 69790792Sgshapiro */ 69890792Sgshapiro 69990792Sgshapiro for (p = &e->e_macro.mac_table[0]; 70090792Sgshapiro p <= &e->e_macro.mac_table[MAXMACROID]; 70190792Sgshapiro ++p) 70290792Sgshapiro { 70390792Sgshapiro if (*p != NULL) 70490792Sgshapiro *p = sm_rpool_strdup_x(rpool, *p); 70590792Sgshapiro } 70690792Sgshapiro 70790792Sgshapiro /* 70890792Sgshapiro ** XXX There are many strings in the envelope structure 70990792Sgshapiro ** XXX that we are not attempting to copy here. 71090792Sgshapiro ** XXX Investigate this further. 71190792Sgshapiro */ 71290792Sgshapiro 71390792Sgshapiro e->e_rpool = rpool; 71490792Sgshapiro e->e_macro.mac_rpool = rpool; 71538032Speter if (Verbose) 71664562Sgshapiro set_delivery_mode(SM_DELIVER, e); 71738032Speter bh = BlankEnvelope.e_header; 71838032Speter nhp = &e->e_header; 71938032Speter while (bh != NULL) 72038032Speter { 721168515Sgshapiro *nhp = (HDR *) sm_rpool_malloc_x(rpool, sizeof(*bh)); 722168515Sgshapiro memmove((char *) *nhp, (char *) bh, sizeof(*bh)); 72338032Speter bh = bh->h_link; 72438032Speter nhp = &(*nhp)->h_link; 72538032Speter } 726203004Sgshapiro#if _FFR_MILTER_ENHSC 727203004Sgshapiro e->e_enhsc[0] = '\0'; 728203004Sgshapiro#endif /* _FFR_MILTER_ENHSC */ 72938032Speter} 73090792Sgshapiro/* 73138032Speter** INITSYS -- initialize instantiation of system 73238032Speter** 73338032Speter** In Daemon mode, this is done in the child. 73438032Speter** 73538032Speter** Parameters: 73664562Sgshapiro** e -- the envelope to use. 73738032Speter** 73838032Speter** Returns: 73938032Speter** none. 74038032Speter** 74138032Speter** Side Effects: 74238032Speter** Initializes the system macros, some global variables, 74338032Speter** etc. In particular, the current time in various 74438032Speter** forms is set. 74538032Speter*/ 74638032Speter 74738032Spetervoid 74838032Speterinitsys(e) 74938032Speter register ENVELOPE *e; 75038032Speter{ 75190792Sgshapiro char buf[10]; 75238032Speter#ifdef TTYNAME 75338032Speter static char ybuf[60]; /* holds tty id */ 75438032Speter register char *p; 75538032Speter extern char *ttyname(); 75638032Speter#endif /* TTYNAME */ 75738032Speter 75838032Speter /* 75938032Speter ** Give this envelope a reality. 76038032Speter ** I.e., an id, a transcript, and a creation time. 76190792Sgshapiro ** We don't select the queue until all of the recipients are known. 76238032Speter */ 76338032Speter 76438032Speter openxscript(e); 76538032Speter e->e_ctime = curtime(); 76690792Sgshapiro e->e_qfletter = '\0'; 76738032Speter 76838032Speter /* 76938032Speter ** Set OutChannel to something useful if stdout isn't it. 77038032Speter ** This arranges that any extra stuff the mailer produces 77138032Speter ** gets sent back to the user on error (because it is 77238032Speter ** tucked away in the transcript). 77338032Speter */ 77438032Speter 77538032Speter if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) && 77638032Speter e->e_xfp != NULL) 77738032Speter OutChannel = e->e_xfp; 77838032Speter 77938032Speter /* 78038032Speter ** Set up some basic system macros. 78138032Speter */ 78238032Speter 78338032Speter /* process id */ 784168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), "%d", (int) CurrentPid); 78590792Sgshapiro macdefine(&e->e_macro, A_TEMP, 'p', buf); 78638032Speter 78738032Speter /* hop count */ 788168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), "%d", e->e_hopcount); 78990792Sgshapiro macdefine(&e->e_macro, A_TEMP, 'c', buf); 79038032Speter 79138032Speter /* time as integer, unix time, arpa time */ 79238032Speter settime(e); 79338032Speter 79464562Sgshapiro /* Load average */ 79590792Sgshapiro sm_getla(); 79664562Sgshapiro 79738032Speter#ifdef TTYNAME 79838032Speter /* tty name */ 79938032Speter if (macvalue('y', e) == NULL) 80038032Speter { 80138032Speter p = ttyname(2); 80238032Speter if (p != NULL) 80338032Speter { 80438032Speter if (strrchr(p, '/') != NULL) 80538032Speter p = strrchr(p, '/') + 1; 806168515Sgshapiro (void) sm_strlcpy(ybuf, sizeof(ybuf), p); 80790792Sgshapiro macdefine(&e->e_macro, A_PERM, 'y', ybuf); 80838032Speter } 80938032Speter } 81038032Speter#endif /* TTYNAME */ 81138032Speter} 81290792Sgshapiro/* 81338032Speter** SETTIME -- set the current time. 81438032Speter** 81538032Speter** Parameters: 81664562Sgshapiro** e -- the envelope in which the macros should be set. 81738032Speter** 81838032Speter** Returns: 81938032Speter** none. 82038032Speter** 82138032Speter** Side Effects: 82238032Speter** Sets the various time macros -- $a, $b, $d, $t. 82338032Speter*/ 82438032Speter 82538032Spetervoid 82638032Spetersettime(e) 82738032Speter register ENVELOPE *e; 82838032Speter{ 82938032Speter register char *p; 83038032Speter auto time_t now; 83190792Sgshapiro char buf[30]; 83238032Speter register struct tm *tm; 83338032Speter 83438032Speter now = curtime(); 835168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), "%ld", (long) now); 836132943Sgshapiro macdefine(&e->e_macro, A_TEMP, macid("{time}"), buf); 83738032Speter tm = gmtime(&now); 838168515Sgshapiro (void) sm_snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d", 83990792Sgshapiro tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, 84090792Sgshapiro tm->tm_hour, tm->tm_min); 84190792Sgshapiro macdefine(&e->e_macro, A_TEMP, 't', buf); 842168515Sgshapiro (void) sm_strlcpy(buf, ctime(&now), sizeof(buf)); 84390792Sgshapiro p = strchr(buf, '\n'); 84438032Speter if (p != NULL) 84538032Speter *p = '\0'; 84690792Sgshapiro macdefine(&e->e_macro, A_TEMP, 'd', buf); 84790792Sgshapiro macdefine(&e->e_macro, A_TEMP, 'b', arpadate(buf)); 84838032Speter if (macvalue('a', e) == NULL) 84990792Sgshapiro macdefine(&e->e_macro, A_PERM, 'a', macvalue('b', e)); 85038032Speter} 85190792Sgshapiro/* 85238032Speter** OPENXSCRIPT -- Open transcript file 85338032Speter** 85438032Speter** Creates a transcript file for possible eventual mailing or 85538032Speter** sending back. 85638032Speter** 85738032Speter** Parameters: 85838032Speter** e -- the envelope to create the transcript in/for. 85938032Speter** 86038032Speter** Returns: 86138032Speter** none 86238032Speter** 86338032Speter** Side Effects: 86438032Speter** Creates the transcript file. 86538032Speter*/ 86638032Speter 86738032Speter#ifndef O_APPEND 86864562Sgshapiro# define O_APPEND 0 86964562Sgshapiro#endif /* ! O_APPEND */ 87038032Speter 87138032Spetervoid 87238032Speteropenxscript(e) 87338032Speter register ENVELOPE *e; 87438032Speter{ 87538032Speter register char *p; 87638032Speter 87738032Speter if (e->e_xfp != NULL) 87838032Speter return; 87964562Sgshapiro 88064562Sgshapiro#if 0 88164562Sgshapiro if (e->e_lockfp == NULL && bitset(EF_INQUEUE, e->e_flags)) 88264562Sgshapiro syserr("openxscript: job not locked"); 88364562Sgshapiro#endif /* 0 */ 88464562Sgshapiro 88590792Sgshapiro p = queuename(e, XSCRPT_LETTER); 88664562Sgshapiro e->e_xfp = bfopen(p, FileMode, XscriptFileBufferSize, 88764562Sgshapiro SFF_NOTEXCL|SFF_OPENASROOT); 88864562Sgshapiro 88964562Sgshapiro if (e->e_xfp == NULL) 89038032Speter { 89138032Speter syserr("Can't create transcript file %s", p); 89290792Sgshapiro e->e_xfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, 89390792Sgshapiro SM_PATH_DEVNULL, SM_IO_RDWR, NULL); 89464562Sgshapiro if (e->e_xfp == NULL) 89590792Sgshapiro syserr("!Can't open %s", SM_PATH_DEVNULL); 89638032Speter } 89790792Sgshapiro (void) sm_io_setvbuf(e->e_xfp, SM_TIME_DEFAULT, NULL, SM_IO_LBF, 0); 89838032Speter if (tTd(46, 9)) 89938032Speter { 90090792Sgshapiro sm_dprintf("openxscript(%s):\n ", p); 90190792Sgshapiro dumpfd(sm_io_getinfo(e->e_xfp, SM_IO_WHAT_FD, NULL), true, 90290792Sgshapiro false); 90338032Speter } 90438032Speter} 90590792Sgshapiro/* 90638032Speter** CLOSEXSCRIPT -- close the transcript file. 90738032Speter** 90838032Speter** Parameters: 90938032Speter** e -- the envelope containing the transcript to close. 91038032Speter** 91138032Speter** Returns: 91238032Speter** none. 91338032Speter** 91438032Speter** Side Effects: 91538032Speter** none. 91638032Speter*/ 91738032Speter 91838032Spetervoid 91938032Speterclosexscript(e) 92038032Speter register ENVELOPE *e; 92138032Speter{ 92238032Speter if (e->e_xfp == NULL) 92338032Speter return; 92464562Sgshapiro#if 0 92564562Sgshapiro if (e->e_lockfp == NULL) 92664562Sgshapiro syserr("closexscript: job not locked"); 92764562Sgshapiro#endif /* 0 */ 92890792Sgshapiro (void) sm_io_close(e->e_xfp, SM_TIME_DEFAULT); 92938032Speter e->e_xfp = NULL; 93038032Speter} 93190792Sgshapiro/* 93238032Speter** SETSENDER -- set the person who this message is from 93338032Speter** 93438032Speter** Under certain circumstances allow the user to say who 93538032Speter** s/he is (using -f or -r). These are: 93638032Speter** 1. The user's uid is zero (root). 93738032Speter** 2. The user's login name is in an approved list (typically 93838032Speter** from a network server). 93938032Speter** 3. The address the user is trying to claim has a 94038032Speter** "!" character in it (since #2 doesn't do it for 94138032Speter** us if we are dialing out for UUCP). 94238032Speter** A better check to replace #3 would be if the 94338032Speter** effective uid is "UUCP" -- this would require me 94438032Speter** to rewrite getpwent to "grab" uucp as it went by, 94538032Speter** make getname more nasty, do another passwd file 94638032Speter** scan, or compile the UID of "UUCP" into the code, 94738032Speter** all of which are reprehensible. 94838032Speter** 94938032Speter** Assuming all of these fail, we figure out something 95038032Speter** ourselves. 95138032Speter** 95238032Speter** Parameters: 95338032Speter** from -- the person we would like to believe this message 95438032Speter** is from, as specified on the command line. 95538032Speter** e -- the envelope in which we would like the sender set. 95638032Speter** delimptr -- if non-NULL, set to the location of the 95738032Speter** trailing delimiter. 95838032Speter** delimchar -- the character that will delimit the sender 95938032Speter** address. 96038032Speter** internal -- set if this address is coming from an internal 96138032Speter** source such as an owner alias. 96238032Speter** 96338032Speter** Returns: 96438032Speter** none. 96538032Speter** 96638032Speter** Side Effects: 96738032Speter** sets sendmail's notion of who the from person is. 96838032Speter*/ 96938032Speter 97038032Spetervoid 97138032Spetersetsender(from, e, delimptr, delimchar, internal) 97238032Speter char *from; 97338032Speter register ENVELOPE *e; 97438032Speter char **delimptr; 97538032Speter int delimchar; 97638032Speter bool internal; 97738032Speter{ 97838032Speter register char **pvp; 97938032Speter char *realname = NULL; 98038032Speter char *bp; 98138032Speter char buf[MAXNAME + 2]; 98238032Speter char pvpbuf[PSBUFSIZE]; 98338032Speter extern char *FullName; 98438032Speter 98538032Speter if (tTd(45, 1)) 98690792Sgshapiro sm_dprintf("setsender(%s)\n", from == NULL ? "" : from); 98738032Speter 988110560Sgshapiro /* may be set from earlier calls */ 989110560Sgshapiro macdefine(&e->e_macro, A_PERM, 'x', ""); 990110560Sgshapiro 99138032Speter /* 99238032Speter ** Figure out the real user executing us. 99338032Speter ** Username can return errno != 0 on non-errors. 99438032Speter */ 99538032Speter 99638032Speter if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP || 99738032Speter OpMode == MD_ARPAFTP || OpMode == MD_DAEMON) 99838032Speter realname = from; 99938032Speter if (realname == NULL || realname[0] == '\0') 100038032Speter realname = username(); 100138032Speter 100238032Speter if (ConfigLevel < 2) 100390792Sgshapiro SuprErrs = true; 100438032Speter 100590792Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e s"); 100690792Sgshapiro 100764562Sgshapiro /* preset state for then clause in case from == NULL */ 100864562Sgshapiro e->e_from.q_state = QS_BADADDR; 100964562Sgshapiro e->e_from.q_flags = 0; 101038032Speter if (from == NULL || 101138032Speter parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR, 101290792Sgshapiro delimchar, delimptr, e, false) == NULL || 101364562Sgshapiro QS_IS_BADADDR(e->e_from.q_state) || 101438032Speter e->e_from.q_mailer == ProgMailer || 101538032Speter e->e_from.q_mailer == FileMailer || 101638032Speter e->e_from.q_mailer == InclMailer) 101738032Speter { 101838032Speter /* log garbage addresses for traceback */ 101938032Speter if (from != NULL && LogLevel > 2) 102038032Speter { 102138032Speter char *p; 102238032Speter char ebuf[MAXNAME * 2 + 2]; 102338032Speter 102438032Speter p = macvalue('_', e); 102538032Speter if (p == NULL) 102638032Speter { 102738032Speter char *host = RealHostName; 102838032Speter 102938032Speter if (host == NULL) 103038032Speter host = MyHostName; 1031168515Sgshapiro (void) sm_snprintf(ebuf, sizeof(ebuf), 103290792Sgshapiro "%.*s@%.*s", MAXNAME, 103390792Sgshapiro realname, MAXNAME, host); 103438032Speter p = ebuf; 103538032Speter } 103638032Speter sm_syslog(LOG_NOTICE, e->e_id, 103764562Sgshapiro "setsender: %s: invalid or unparsable, received from %s", 103864562Sgshapiro shortenstring(from, 83), p); 103938032Speter } 104038032Speter if (from != NULL) 104138032Speter { 104264562Sgshapiro if (!QS_IS_BADADDR(e->e_from.q_state)) 104338032Speter { 104438032Speter /* it was a bogus mailer in the from addr */ 104538032Speter e->e_status = "5.1.7"; 104664562Sgshapiro usrerrenh(e->e_status, 104764562Sgshapiro "553 Invalid sender address"); 104838032Speter } 104990792Sgshapiro SuprErrs = true; 105038032Speter } 105138032Speter if (from == realname || 105290792Sgshapiro parseaddr(from = realname, 105390792Sgshapiro &e->e_from, RF_COPYALL|RF_SENDERADDR, ' ', 105490792Sgshapiro NULL, e, false) == NULL) 105538032Speter { 105638032Speter char nbuf[100]; 105738032Speter 105890792Sgshapiro SuprErrs = true; 1059168515Sgshapiro expand("\201n", nbuf, sizeof(nbuf), e); 106090792Sgshapiro from = sm_rpool_strdup_x(e->e_rpool, nbuf); 106190792Sgshapiro if (parseaddr(from, &e->e_from, RF_COPYALL, ' ', 106290792Sgshapiro NULL, e, false) == NULL && 106338032Speter parseaddr(from = "postmaster", &e->e_from, 106490792Sgshapiro RF_COPYALL, ' ', NULL, e, false) == NULL) 106564562Sgshapiro syserr("553 5.3.0 setsender: can't even parse postmaster!"); 106638032Speter } 106738032Speter } 106838032Speter else 106990792Sgshapiro FromFlag = true; 107064562Sgshapiro e->e_from.q_state = QS_SENDER; 107138032Speter if (tTd(45, 5)) 107238032Speter { 107390792Sgshapiro sm_dprintf("setsender: QS_SENDER "); 1074132943Sgshapiro printaddr(sm_debug_file(), &e->e_from, false); 107538032Speter } 107690792Sgshapiro SuprErrs = false; 107738032Speter 107864562Sgshapiro#if USERDB 107938032Speter if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags)) 108038032Speter { 108138032Speter register char *p; 108238032Speter 108390792Sgshapiro p = udbsender(e->e_from.q_user, e->e_rpool); 108438032Speter if (p != NULL) 108538032Speter from = p; 108638032Speter } 108764562Sgshapiro#endif /* USERDB */ 108838032Speter 108938032Speter if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags)) 109038032Speter { 109190792Sgshapiro SM_MBDB_T user; 109290792Sgshapiro 109338032Speter if (!internal) 109438032Speter { 109538032Speter /* if the user already given fullname don't redefine */ 109638032Speter if (FullName == NULL) 109738032Speter FullName = macvalue('x', e); 109894334Sgshapiro if (FullName != NULL) 109994334Sgshapiro { 110094334Sgshapiro if (FullName[0] == '\0') 110194334Sgshapiro FullName = NULL; 110294334Sgshapiro else 110394334Sgshapiro FullName = newstr(FullName); 110494334Sgshapiro } 110538032Speter } 110638032Speter 110738032Speter if (e->e_from.q_user[0] != '\0' && 110890792Sgshapiro sm_mbdb_lookup(e->e_from.q_user, &user) == EX_OK) 110938032Speter { 111038032Speter /* 111138032Speter ** Process passwd file entry. 111238032Speter */ 111338032Speter 111438032Speter /* extract home directory */ 111590792Sgshapiro if (*user.mbdb_homedir == '\0') 111666494Sgshapiro e->e_from.q_home = NULL; 111790792Sgshapiro else if (strcmp(user.mbdb_homedir, "/") == 0) 111890792Sgshapiro e->e_from.q_home = ""; 111938032Speter else 112090792Sgshapiro e->e_from.q_home = sm_rpool_strdup_x(e->e_rpool, 112190792Sgshapiro user.mbdb_homedir); 112290792Sgshapiro macdefine(&e->e_macro, A_PERM, 'z', e->e_from.q_home); 112338032Speter 112438032Speter /* extract user and group id */ 112590792Sgshapiro if (user.mbdb_uid != SM_NO_UID) 112690792Sgshapiro { 112790792Sgshapiro e->e_from.q_uid = user.mbdb_uid; 112890792Sgshapiro e->e_from.q_gid = user.mbdb_gid; 112990792Sgshapiro e->e_from.q_flags |= QGOODUID; 113090792Sgshapiro } 113138032Speter 113238032Speter /* extract full name from passwd file */ 113390792Sgshapiro if (FullName == NULL && !internal && 113490792Sgshapiro user.mbdb_fullname[0] != '\0' && 113590792Sgshapiro strcmp(user.mbdb_name, e->e_from.q_user) == 0) 113638032Speter { 113790792Sgshapiro FullName = newstr(user.mbdb_fullname); 113838032Speter } 113938032Speter } 114038032Speter else 114138032Speter { 114264562Sgshapiro e->e_from.q_home = NULL; 114338032Speter } 114438032Speter if (FullName != NULL && !internal) 1145110560Sgshapiro macdefine(&e->e_macro, A_TEMP, 'x', FullName); 114638032Speter } 114743730Speter else if (!internal && OpMode != MD_DAEMON && OpMode != MD_SMTP) 114838032Speter { 114938032Speter if (e->e_from.q_home == NULL) 115038032Speter { 115138032Speter e->e_from.q_home = getenv("HOME"); 115266494Sgshapiro if (e->e_from.q_home != NULL) 115366494Sgshapiro { 115466494Sgshapiro if (*e->e_from.q_home == '\0') 115566494Sgshapiro e->e_from.q_home = NULL; 115666494Sgshapiro else if (strcmp(e->e_from.q_home, "/") == 0) 115766494Sgshapiro e->e_from.q_home++; 115866494Sgshapiro } 115938032Speter } 116038032Speter e->e_from.q_uid = RealUid; 116138032Speter e->e_from.q_gid = RealGid; 116238032Speter e->e_from.q_flags |= QGOODUID; 116338032Speter } 116438032Speter 116538032Speter /* 116638032Speter ** Rewrite the from person to dispose of possible implicit 116738032Speter ** links in the net. 116838032Speter */ 116938032Speter 1170168515Sgshapiro pvp = prescan(from, delimchar, pvpbuf, sizeof(pvpbuf), NULL, 1171168515Sgshapiro IntTokenTab, false); 117238032Speter if (pvp == NULL) 117338032Speter { 117438032Speter /* don't need to give error -- prescan did that already */ 117538032Speter if (LogLevel > 2) 117638032Speter sm_syslog(LOG_NOTICE, e->e_id, 117764562Sgshapiro "cannot prescan from (%s)", 117864562Sgshapiro shortenstring(from, MAXSHORTSTR)); 117990792Sgshapiro finis(true, true, ExitStat); 118038032Speter } 118190792Sgshapiro (void) REWRITE(pvp, 3, e); 118290792Sgshapiro (void) REWRITE(pvp, 1, e); 118390792Sgshapiro (void) REWRITE(pvp, 4, e); 118490792Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL); 118538032Speter bp = buf + 1; 1186168515Sgshapiro cataddr(pvp, NULL, bp, sizeof(buf) - 2, '\0', false); 118738032Speter if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags)) 118838032Speter { 118938032Speter /* heuristic: route-addr: add angle brackets */ 1190168515Sgshapiro (void) sm_strlcat(bp, ">", sizeof(buf) - 1); 119138032Speter *--bp = '<'; 119238032Speter } 119390792Sgshapiro e->e_sender = sm_rpool_strdup_x(e->e_rpool, bp); 119490792Sgshapiro macdefine(&e->e_macro, A_PERM, 'f', e->e_sender); 119538032Speter 119638032Speter /* save the domain spec if this mailer wants it */ 119738032Speter if (e->e_from.q_mailer != NULL && 119838032Speter bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags)) 119938032Speter { 120038032Speter char **lastat; 120138032Speter 120238032Speter /* get rid of any pesky angle brackets */ 120390792Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e s"); 120490792Sgshapiro (void) REWRITE(pvp, 3, e); 120590792Sgshapiro (void) REWRITE(pvp, 1, e); 120690792Sgshapiro (void) REWRITE(pvp, 4, e); 120790792Sgshapiro macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL); 120838032Speter 120938032Speter /* strip off to the last "@" sign */ 121038032Speter for (lastat = NULL; *pvp != NULL; pvp++) 1211132943Sgshapiro { 121238032Speter if (strcmp(*pvp, "@") == 0) 121338032Speter lastat = pvp; 1214132943Sgshapiro } 121538032Speter if (lastat != NULL) 121638032Speter { 121790792Sgshapiro e->e_fromdomain = copyplist(lastat, true, e->e_rpool); 121838032Speter if (tTd(45, 3)) 121938032Speter { 122090792Sgshapiro sm_dprintf("Saving from domain: "); 1221132943Sgshapiro printav(sm_debug_file(), e->e_fromdomain); 122238032Speter } 122338032Speter } 122438032Speter } 122538032Speter} 122690792Sgshapiro/* 122738032Speter** PRINTENVFLAGS -- print envelope flags for debugging 122838032Speter** 122938032Speter** Parameters: 123038032Speter** e -- the envelope with the flags to be printed. 123138032Speter** 123238032Speter** Returns: 123338032Speter** none. 123438032Speter*/ 123538032Speter 123638032Speterstruct eflags 123738032Speter{ 123890792Sgshapiro char *ef_name; 123990792Sgshapiro unsigned long ef_bit; 124038032Speter}; 124138032Speter 124264562Sgshapirostatic struct eflags EnvelopeFlags[] = 124338032Speter{ 124438032Speter { "OLDSTYLE", EF_OLDSTYLE }, 124538032Speter { "INQUEUE", EF_INQUEUE }, 124638032Speter { "NO_BODY_RETN", EF_NO_BODY_RETN }, 124738032Speter { "CLRQUEUE", EF_CLRQUEUE }, 124838032Speter { "SENDRECEIPT", EF_SENDRECEIPT }, 124938032Speter { "FATALERRS", EF_FATALERRS }, 125038032Speter { "DELETE_BCC", EF_DELETE_BCC }, 125138032Speter { "RESPONSE", EF_RESPONSE }, 125238032Speter { "RESENT", EF_RESENT }, 125338032Speter { "VRFYONLY", EF_VRFYONLY }, 125438032Speter { "WARNING", EF_WARNING }, 125538032Speter { "QUEUERUN", EF_QUEUERUN }, 125638032Speter { "GLOBALERRS", EF_GLOBALERRS }, 125738032Speter { "PM_NOTIFY", EF_PM_NOTIFY }, 125838032Speter { "METOO", EF_METOO }, 125938032Speter { "LOGSENDER", EF_LOGSENDER }, 126038032Speter { "NORECEIPT", EF_NORECEIPT }, 126138032Speter { "HAS8BIT", EF_HAS8BIT }, 126238032Speter { "NL_NOT_EOL", EF_NL_NOT_EOL }, 126338032Speter { "CRLF_NOT_EOL", EF_CRLF_NOT_EOL }, 126438032Speter { "RET_PARAM", EF_RET_PARAM }, 126538032Speter { "HAS_DF", EF_HAS_DF }, 126638032Speter { "IS_MIME", EF_IS_MIME }, 126738032Speter { "DONT_MIME", EF_DONT_MIME }, 126890792Sgshapiro { "DISCARD", EF_DISCARD }, 126990792Sgshapiro { "TOOBIG", EF_TOOBIG }, 127090792Sgshapiro { "SPLIT", EF_SPLIT }, 127190792Sgshapiro { "UNSAFE", EF_UNSAFE }, 127271345Sgshapiro { NULL, 0 } 127338032Speter}; 127438032Speter 127538032Spetervoid 127638032Speterprintenvflags(e) 127738032Speter register ENVELOPE *e; 127838032Speter{ 127938032Speter register struct eflags *ef; 128090792Sgshapiro bool first = true; 128138032Speter 1282132943Sgshapiro sm_dprintf("%lx", e->e_flags); 128338032Speter for (ef = EnvelopeFlags; ef->ef_name != NULL; ef++) 128438032Speter { 128538032Speter if (!bitset(ef->ef_bit, e->e_flags)) 128638032Speter continue; 128738032Speter if (first) 1288132943Sgshapiro sm_dprintf("<%s", ef->ef_name); 128938032Speter else 1290132943Sgshapiro sm_dprintf(",%s", ef->ef_name); 129190792Sgshapiro first = false; 129238032Speter } 129338032Speter if (!first) 1294132943Sgshapiro sm_dprintf(">\n"); 129538032Speter} 1296