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