138032Speter/*
2261194Sgshapiro * Copyright (c) 1998-2003, 2006 Proofpoint, 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
16266527SgshapiroSM_RCSID("@(#)$Id: envelope.c,v 8.313 2013-11-22 20:51:55 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	macdefine(&e->e_macro, A_PERM, macid("{alg_bits}"), "");
46110560Sgshapiro	macdefine(&e->e_macro, A_PERM, macid("{cn_issuer}"), "");
47110560Sgshapiro	macdefine(&e->e_macro, A_PERM, macid("{cn_subject}"), "");
48110560Sgshapiro#endif /* STARTTLS */
49110560Sgshapiro}
50110560Sgshapiro
51110560Sgshapiro/*
5290792Sgshapiro**  NEWENVELOPE -- fill in a new envelope
5338032Speter**
5438032Speter**	Supports inheritance.
5538032Speter**
5638032Speter**	Parameters:
5738032Speter**		e -- the new envelope to fill in.
5838032Speter**		parent -- the envelope to be the parent of e.
5990792Sgshapiro**		rpool -- either NULL, or a pointer to a resource pool
6090792Sgshapiro**			from which envelope memory is allocated, and
6190792Sgshapiro**			to which envelope resources are attached.
6238032Speter**
6338032Speter**	Returns:
6438032Speter**		e.
6538032Speter**
6638032Speter**	Side Effects:
6738032Speter**		none.
6838032Speter*/
6938032Speter
7038032SpeterENVELOPE *
7190792Sgshapironewenvelope(e, parent, rpool)
7238032Speter	register ENVELOPE *e;
7338032Speter	register ENVELOPE *parent;
7490792Sgshapiro	SM_RPOOL_T *rpool;
7538032Speter{
76182352Sgshapiro	int sendmode;
77157001Sgshapiro
7890792Sgshapiro	/*
7990792Sgshapiro	**  This code used to read:
8090792Sgshapiro	**	if (e == parent && e->e_parent != NULL)
8190792Sgshapiro	**		parent = e->e_parent;
8290792Sgshapiro	**  So if e == parent && e->e_parent == NULL then we would
8390792Sgshapiro	**  set e->e_parent = e, which creates a loop in the e_parent chain.
8490792Sgshapiro	**  This meant macvalue() could go into an infinite loop.
8590792Sgshapiro	*/
8690792Sgshapiro
87157001Sgshapiro	if (parent != NULL)
88157001Sgshapiro		sendmode = parent->e_sendmode;
89157001Sgshapiro	else
90157001Sgshapiro		sendmode = DM_NOTSET;
91157001Sgshapiro
9290792Sgshapiro	if (e == parent)
9338032Speter		parent = e->e_parent;
9490792Sgshapiro	clearenvelope(e, true, rpool);
9538032Speter	if (e == CurEnv)
9664562Sgshapiro		memmove((char *) &e->e_from,
9764562Sgshapiro			(char *) &NullAddress,
98168515Sgshapiro			sizeof(e->e_from));
9938032Speter	else
10064562Sgshapiro		memmove((char *) &e->e_from,
10164562Sgshapiro			(char *) &CurEnv->e_from,
102168515Sgshapiro			sizeof(e->e_from));
10338032Speter	e->e_parent = parent;
10464562Sgshapiro	assign_queueid(e);
10538032Speter	e->e_ctime = curtime();
106173340Sgshapiro#if _FFR_SESSID
107173340Sgshapiro	e->e_sessid = e->e_id;
108173340Sgshapiro#endif /* _FFR_SESSID */
10938032Speter	if (parent != NULL)
11090792Sgshapiro	{
11138032Speter		e->e_msgpriority = parent->e_msgsize;
112173340Sgshapiro#if _FFR_SESSID
113173340Sgshapiro		if (parent->e_sessid != NULL)
114173340Sgshapiro			e->e_sessid = sm_rpool_strdup_x(rpool,
115173340Sgshapiro							parent->e_sessid);
116173340Sgshapiro#endif /* _FFR_SESSID */
117173340Sgshapiro
11890792Sgshapiro		if (parent->e_quarmsg == NULL)
11990792Sgshapiro		{
12090792Sgshapiro			e->e_quarmsg = NULL;
12190792Sgshapiro			macdefine(&e->e_macro, A_PERM,
12290792Sgshapiro				  macid("{quarantine}"), "");
12390792Sgshapiro		}
12490792Sgshapiro		else
12590792Sgshapiro		{
12690792Sgshapiro			e->e_quarmsg = sm_rpool_strdup_x(rpool,
12790792Sgshapiro							 parent->e_quarmsg);
12890792Sgshapiro			macdefine(&e->e_macro, A_PERM,
12990792Sgshapiro				  macid("{quarantine}"), e->e_quarmsg);
13090792Sgshapiro		}
13190792Sgshapiro	}
13238032Speter	e->e_puthdr = putheader;
13338032Speter	e->e_putbody = putbody;
13438032Speter	if (CurEnv->e_xfp != NULL)
13590792Sgshapiro		(void) sm_io_flush(CurEnv->e_xfp, SM_TIME_DEFAULT);
136157001Sgshapiro	if (sendmode != DM_NOTSET)
137182352Sgshapiro		set_delivery_mode(sendmode, e);
13838032Speter
13964562Sgshapiro	return e;
14038032Speter}
14190792Sgshapiro
14290792Sgshapiro/* values for msg_timeout, see also IS_* below for usage (bit layout) */
14390792Sgshapiro#define MSG_T_O		0x01	/* normal timeout */
14490792Sgshapiro#define MSG_T_O_NOW	0x02	/* NOW timeout */
14590792Sgshapiro#define MSG_NOT_BY	0x04	/* Deliver-By time exceeded, mode R */
14690792Sgshapiro#define MSG_WARN	0x10	/* normal queue warning */
14790792Sgshapiro#define MSG_WARN_BY	0x20	/* Deliver-By time exceeded, mode N */
14890792Sgshapiro
14990792Sgshapiro#define IS_MSG_ERR(x)	(((x) & 0x0f) != 0)	/* return an error */
15090792Sgshapiro
15190792Sgshapiro/* immediate return */
15290792Sgshapiro#define IS_IMM_RET(x)	(((x) & (MSG_T_O_NOW|MSG_NOT_BY)) != 0)
15390792Sgshapiro#define IS_MSG_WARN(x)	(((x) & 0xf0) != 0)	/* return a warning */
15490792Sgshapiro
15590792Sgshapiro/*
15638032Speter**  DROPENVELOPE -- deallocate an envelope.
15738032Speter**
15838032Speter**	Parameters:
15938032Speter**		e -- the envelope to deallocate.
16038032Speter**		fulldrop -- if set, do return receipts.
16190792Sgshapiro**		split -- if true, split by recipient if message is queued up
16238032Speter**
16338032Speter**	Returns:
164203004Sgshapiro**		EX_* status (currently: 0: success, EX_IOERR on panic)
16538032Speter**
16638032Speter**	Side Effects:
16738032Speter**		housekeeping necessary to dispose of an envelope.
16838032Speter**		Unlocks this queue file.
16938032Speter*/
17038032Speter
171203004Sgshapiroint
17290792Sgshapirodropenvelope(e, fulldrop, split)
17338032Speter	register ENVELOPE *e;
17438032Speter	bool fulldrop;
17590792Sgshapiro	bool split;
17638032Speter{
17790792Sgshapiro	bool panic = false;
17890792Sgshapiro	bool queueit = false;
17990792Sgshapiro	int msg_timeout = 0;
18090792Sgshapiro	bool failure_return = false;
18190792Sgshapiro	bool delay_return = false;
18290792Sgshapiro	bool success_return = false;
18364562Sgshapiro	bool pmnotify = bitset(EF_PM_NOTIFY, e->e_flags);
18490792Sgshapiro	bool done = false;
18538032Speter	register ADDRESS *q;
18638032Speter	char *id = e->e_id;
18771345Sgshapiro	time_t now;
18838032Speter	char buf[MAXLINE];
18938032Speter
19038032Speter	if (tTd(50, 1))
19138032Speter	{
19290792Sgshapiro		sm_dprintf("dropenvelope %p: id=", e);
193132943Sgshapiro		xputs(sm_debug_file(), e->e_id);
19490792Sgshapiro		sm_dprintf(", flags=");
19538032Speter		printenvflags(e);
19638032Speter		if (tTd(50, 10))
19738032Speter		{
19890792Sgshapiro			sm_dprintf("sendq=");
199132943Sgshapiro			printaddr(sm_debug_file(), e->e_sendqueue, true);
20038032Speter		}
20138032Speter	}
20238032Speter
20338032Speter	if (LogLevel > 84)
20438032Speter		sm_syslog(LOG_DEBUG, id,
20564562Sgshapiro			  "dropenvelope, e_flags=0x%lx, OpMode=%c, pid=%d",
20690792Sgshapiro			  e->e_flags, OpMode, (int) CurrentPid);
20738032Speter
20838032Speter	/* we must have an id to remove disk files */
20938032Speter	if (id == NULL)
210203004Sgshapiro		return EX_OK;
21138032Speter
21238032Speter	/* if verify-only mode, we can skip most of this */
21338032Speter	if (OpMode == MD_VERIFY)
21438032Speter		goto simpledrop;
21538032Speter
216203004Sgshapiro	if (tTd(92, 2))
217203004Sgshapiro		sm_dprintf("dropenvelope: e_id=%s, EF_LOGSENDER=%d, LogLevel=%d\n",
218203004Sgshapiro			e->e_id, bitset(EF_LOGSENDER, e->e_flags), LogLevel);
21938032Speter	if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
22038032Speter		logsender(e, NULL);
22138032Speter	e->e_flags &= ~EF_LOGSENDER;
22238032Speter
22338032Speter	/* post statistics */
22438032Speter	poststats(StatFile);
22538032Speter
22638032Speter	/*
22738032Speter	**  Extract state information from dregs of send list.
22838032Speter	*/
22938032Speter
23071345Sgshapiro	now = curtime();
23177349Sgshapiro	if (now >= e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass])
23290792Sgshapiro		msg_timeout = MSG_T_O;
23390792Sgshapiro	if (IS_DLVR_RETURN(e) && e->e_deliver_by > 0 &&
23490792Sgshapiro	    now >= e->e_ctime + e->e_deliver_by &&
23564562Sgshapiro	    !bitset(EF_RESPONSE, e->e_flags))
23664562Sgshapiro	{
23790792Sgshapiro		msg_timeout = MSG_NOT_BY;
23864562Sgshapiro		e->e_flags |= EF_FATALERRS|EF_CLRQUEUE;
23964562Sgshapiro	}
24090792Sgshapiro	else if (TimeOuts.to_q_return[e->e_timeoutclass] == NOW &&
24190792Sgshapiro		 !bitset(EF_RESPONSE, e->e_flags))
24290792Sgshapiro	{
24390792Sgshapiro		msg_timeout = MSG_T_O_NOW;
24490792Sgshapiro		e->e_flags |= EF_FATALERRS|EF_CLRQUEUE;
24590792Sgshapiro	}
24664562Sgshapiro
247285229Sgshapiro#if _FFR_PROXY
248285229Sgshapiro	if (tTd(87, 2))
249285229Sgshapiro	{
250285229Sgshapiro		q = e->e_sendqueue;
251285229Sgshapiro		sm_dprintf("dropenvelope: mode=%c, e=%p, sibling=%p, nrcpts=%d, sendqueue=%p, next=%p, state=%d\n",
252285229Sgshapiro			e->e_sendmode, e, e->e_sibling, e->e_nrcpts, q,
253285229Sgshapiro			(q == NULL) ? (void *)0 : q->q_next,
254285229Sgshapiro			(q == NULL) ? -1 : q->q_state);
255285229Sgshapiro	}
256285229Sgshapiro#endif /* _FFR_PROXY */
257223067Sgshapiro
25838032Speter	e->e_flags &= ~EF_QUEUERUN;
25938032Speter	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
26038032Speter	{
26164562Sgshapiro		if (QS_IS_UNDELIVERED(q->q_state))
26290792Sgshapiro			queueit = true;
26338032Speter
264285229Sgshapiro#if _FFR_PROXY
265285229Sgshapiro		if (queueit && e->e_sendmode == SM_PROXY)
266285229Sgshapiro			queueit = false;
267285229Sgshapiro#endif /* _FFR_PROXY */
268223067Sgshapiro
26938032Speter		/* see if a notification is needed */
27038032Speter		if (bitset(QPINGONFAILURE, q->q_flags) &&
27190792Sgshapiro		    ((IS_MSG_ERR(msg_timeout) &&
27290792Sgshapiro		      QS_IS_UNDELIVERED(q->q_state)) ||
27364562Sgshapiro		     QS_IS_BADADDR(q->q_state) ||
27490792Sgshapiro		     IS_IMM_RET(msg_timeout)))
27538032Speter		{
27690792Sgshapiro			failure_return = true;
27764562Sgshapiro			if (!done && q->q_owner == NULL &&
27864562Sgshapiro			    !emptyaddr(&e->e_from))
27964562Sgshapiro			{
28038032Speter				(void) sendtolist(e->e_from.q_paddr, NULLADDR,
28138032Speter						  &e->e_errorqueue, 0, e);
28290792Sgshapiro				done = true;
28364562Sgshapiro			}
28438032Speter		}
28590792Sgshapiro		else if ((bitset(QPINGONSUCCESS, q->q_flags) &&
28690792Sgshapiro			  ((QS_IS_SENT(q->q_state) &&
28790792Sgshapiro			    bitnset(M_LOCALMAILER, q->q_mailer->m_flags)) ||
28890792Sgshapiro			   bitset(QRELAYED|QEXPANDED|QDELIVERED, q->q_flags))) ||
28990792Sgshapiro			  bitset(QBYTRACE, q->q_flags) ||
29090792Sgshapiro			  bitset(QBYNRELAY, q->q_flags))
29138032Speter		{
29290792Sgshapiro			success_return = true;
29338032Speter		}
29438032Speter	}
29538032Speter
29638032Speter	if (e->e_class < 0)
29738032Speter		e->e_flags |= EF_NO_BODY_RETN;
29838032Speter
29938032Speter	/*
30038032Speter	**  See if the message timed out.
30138032Speter	*/
30238032Speter
30338032Speter	if (!queueit)
30464562Sgshapiro		/* EMPTY */
30538032Speter		/* nothing to do */ ;
30690792Sgshapiro	else if (IS_MSG_ERR(msg_timeout))
30738032Speter	{
30838032Speter		if (failure_return)
30938032Speter		{
31090792Sgshapiro			if (msg_timeout == MSG_NOT_BY)
31190792Sgshapiro			{
312168515Sgshapiro				(void) sm_snprintf(buf, sizeof(buf),
31390792Sgshapiro					"delivery time expired %lds",
31490792Sgshapiro					e->e_deliver_by);
31590792Sgshapiro			}
31690792Sgshapiro			else
31790792Sgshapiro			{
318168515Sgshapiro				(void) sm_snprintf(buf, sizeof(buf),
31964562Sgshapiro					"Cannot send message for %s",
32090792Sgshapiro					pintvl(TimeOuts.to_q_return[e->e_timeoutclass],
32190792Sgshapiro						false));
32290792Sgshapiro			}
32390792Sgshapiro
32490792Sgshapiro			/* don't free, allocated from e_rpool */
32590792Sgshapiro			e->e_message = sm_rpool_strdup_x(e->e_rpool, buf);
32638032Speter			message(buf);
32738032Speter			e->e_flags |= EF_CLRQUEUE;
32838032Speter		}
32990792Sgshapiro		if (msg_timeout == MSG_NOT_BY)
33090792Sgshapiro		{
33190792Sgshapiro			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
33290792Sgshapiro				"Delivery time (%lds) expired\n",
33390792Sgshapiro				e->e_deliver_by);
33490792Sgshapiro		}
33590792Sgshapiro		else
33690792Sgshapiro			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
33790792Sgshapiro				"Message could not be delivered for %s\n",
33890792Sgshapiro				pintvl(TimeOuts.to_q_return[e->e_timeoutclass],
33990792Sgshapiro					false));
34090792Sgshapiro		(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
34190792Sgshapiro			"Message will be deleted from queue\n");
34238032Speter		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
34338032Speter		{
34464562Sgshapiro			if (QS_IS_UNDELIVERED(q->q_state))
34538032Speter			{
34664562Sgshapiro				q->q_state = QS_BADADDR;
34790792Sgshapiro				if (msg_timeout == MSG_NOT_BY)
34890792Sgshapiro					q->q_status = "5.4.7";
34990792Sgshapiro				else
35090792Sgshapiro					q->q_status = "4.4.7";
35138032Speter			}
35238032Speter		}
35338032Speter	}
35490792Sgshapiro	else
35538032Speter	{
35690792Sgshapiro		if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 &&
35790792Sgshapiro		    now >= e->e_ctime +
35890792Sgshapiro				TimeOuts.to_q_warning[e->e_timeoutclass])
35990792Sgshapiro			msg_timeout = MSG_WARN;
36090792Sgshapiro		else if (IS_DLVR_NOTIFY(e) &&
36190792Sgshapiro			 e->e_deliver_by > 0 &&
36290792Sgshapiro			 now >= e->e_ctime + e->e_deliver_by)
36390792Sgshapiro			msg_timeout = MSG_WARN_BY;
36490792Sgshapiro
36590792Sgshapiro		if (IS_MSG_WARN(msg_timeout))
36638032Speter		{
36790792Sgshapiro			if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) &&
36890792Sgshapiro			    e->e_class >= 0 &&
36990792Sgshapiro			    e->e_from.q_paddr != NULL &&
37090792Sgshapiro			    strcmp(e->e_from.q_paddr, "<>") != 0 &&
37190792Sgshapiro			    sm_strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 &&
37290792Sgshapiro			    (strlen(e->e_from.q_paddr) <= 8 ||
37390792Sgshapiro			     sm_strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8],
37490792Sgshapiro					   "-request") != 0))
37538032Speter			{
37690792Sgshapiro				for (q = e->e_sendqueue; q != NULL;
37790792Sgshapiro				     q = q->q_next)
37890792Sgshapiro				{
37990792Sgshapiro					if (QS_IS_UNDELIVERED(q->q_state)
38064562Sgshapiro#if _FFR_NODELAYDSN_ON_HOLD
38190792Sgshapiro					    && !bitnset(M_HOLD,
38290792Sgshapiro							q->q_mailer->m_flags)
38364562Sgshapiro#endif /* _FFR_NODELAYDSN_ON_HOLD */
38490792Sgshapiro					   )
38590792Sgshapiro					{
38690792Sgshapiro						if (msg_timeout ==
38790792Sgshapiro						    MSG_WARN_BY &&
38890792Sgshapiro						    (bitset(QPINGONDELAY,
38990792Sgshapiro							    q->q_flags) ||
39090792Sgshapiro						    !bitset(QHASNOTIFY,
39190792Sgshapiro							    q->q_flags))
39290792Sgshapiro						   )
39390792Sgshapiro						{
39490792Sgshapiro							q->q_flags |= QBYNDELAY;
39590792Sgshapiro							delay_return = true;
39690792Sgshapiro						}
39790792Sgshapiro						if (bitset(QPINGONDELAY,
39890792Sgshapiro							   q->q_flags))
39990792Sgshapiro						{
40090792Sgshapiro							q->q_flags |= QDELAYED;
40190792Sgshapiro							delay_return = true;
40290792Sgshapiro						}
40390792Sgshapiro					}
40490792Sgshapiro				}
40590792Sgshapiro			}
40690792Sgshapiro			if (delay_return)
40790792Sgshapiro			{
40890792Sgshapiro				if (msg_timeout == MSG_WARN_BY)
40938032Speter				{
410168515Sgshapiro					(void) sm_snprintf(buf, sizeof(buf),
41190792Sgshapiro						"Warning: Delivery time (%lds) exceeded",
41290792Sgshapiro						e->e_deliver_by);
41338032Speter				}
41490792Sgshapiro				else
415168515Sgshapiro					(void) sm_snprintf(buf, sizeof(buf),
41690792Sgshapiro						"Warning: could not send message for past %s",
41790792Sgshapiro						pintvl(TimeOuts.to_q_warning[e->e_timeoutclass],
41890792Sgshapiro							false));
41990792Sgshapiro
42090792Sgshapiro				/* don't free, allocated from e_rpool */
42190792Sgshapiro				e->e_message = sm_rpool_strdup_x(e->e_rpool,
42290792Sgshapiro								 buf);
42390792Sgshapiro				message(buf);
42490792Sgshapiro				e->e_flags |= EF_WARNING;
42538032Speter			}
42690792Sgshapiro			if (msg_timeout == MSG_WARN_BY)
42790792Sgshapiro			{
42890792Sgshapiro				(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
42990792Sgshapiro					"Warning: Delivery time (%lds) exceeded\n",
43090792Sgshapiro					e->e_deliver_by);
43190792Sgshapiro			}
43290792Sgshapiro			else
43390792Sgshapiro				(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
43490792Sgshapiro					"Warning: message still undelivered after %s\n",
43590792Sgshapiro					pintvl(TimeOuts.to_q_warning[e->e_timeoutclass],
43690792Sgshapiro					     false));
43790792Sgshapiro			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
43890792Sgshapiro				      "Will keep trying until message is %s old\n",
43990792Sgshapiro				      pintvl(TimeOuts.to_q_return[e->e_timeoutclass],
44090792Sgshapiro					     false));
44138032Speter		}
44238032Speter	}
44338032Speter
44438032Speter	if (tTd(50, 2))
44590792Sgshapiro		sm_dprintf("failure_return=%d delay_return=%d success_return=%d queueit=%d\n",
44638032Speter			failure_return, delay_return, success_return, queueit);
44738032Speter
44838032Speter	/*
44938032Speter	**  If we had some fatal error, but no addresses are marked as
45038032Speter	**  bad, mark them _all_ as bad.
45138032Speter	*/
45238032Speter
45338032Speter	if (bitset(EF_FATALERRS, e->e_flags) && !failure_return)
45438032Speter	{
45538032Speter		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
45638032Speter		{
45764562Sgshapiro			if ((QS_IS_OK(q->q_state) ||
45864562Sgshapiro			     QS_IS_VERIFIED(q->q_state)) &&
45938032Speter			    bitset(QPINGONFAILURE, q->q_flags))
46038032Speter			{
46190792Sgshapiro				failure_return = true;
46264562Sgshapiro				q->q_state = QS_BADADDR;
46338032Speter			}
46438032Speter		}
46538032Speter	}
46638032Speter
46738032Speter	/*
46838032Speter	**  Send back return receipts as requested.
46938032Speter	*/
47038032Speter
47138032Speter	if (success_return && !failure_return && !delay_return && fulldrop &&
47238032Speter	    !bitset(PRIV_NORECEIPTS, PrivacyFlags) &&
47338032Speter	    strcmp(e->e_from.q_paddr, "<>") != 0)
47438032Speter	{
47538032Speter		auto ADDRESS *rlist = NULL;
47638032Speter
47738032Speter		if (tTd(50, 8))
47890792Sgshapiro			sm_dprintf("dropenvelope(%s): sending return receipt\n",
47964562Sgshapiro				id);
48038032Speter		e->e_flags |= EF_SENDRECEIPT;
48138032Speter		(void) sendtolist(e->e_from.q_paddr, NULLADDR, &rlist, 0, e);
48238032Speter		(void) returntosender("Return receipt", rlist, RTSF_NO_BODY, e);
48338032Speter	}
48438032Speter	e->e_flags &= ~EF_SENDRECEIPT;
48538032Speter
48638032Speter	/*
48738032Speter	**  Arrange to send error messages if there are fatal errors.
48838032Speter	*/
48938032Speter
49038032Speter	if ((failure_return || delay_return) && e->e_errormode != EM_QUIET)
49138032Speter	{
49238032Speter		if (tTd(50, 8))
49390792Sgshapiro			sm_dprintf("dropenvelope(%s): saving mail\n", id);
49490792Sgshapiro		panic = savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags));
49538032Speter	}
49638032Speter
49738032Speter	/*
49838032Speter	**  Arrange to send warning messages to postmaster as requested.
49938032Speter	*/
50038032Speter
50164562Sgshapiro	if ((failure_return || pmnotify) &&
50238032Speter	    PostMasterCopy != NULL &&
50364562Sgshapiro	    !bitset(EF_RESPONSE, e->e_flags) &&
50464562Sgshapiro	    e->e_class >= 0)
50538032Speter	{
50638032Speter		auto ADDRESS *rlist = NULL;
50764562Sgshapiro		char pcopy[MAXNAME];
50838032Speter
50964562Sgshapiro		if (failure_return)
51064562Sgshapiro		{
511168515Sgshapiro			expand(PostMasterCopy, pcopy, sizeof(pcopy), e);
51264562Sgshapiro
51364562Sgshapiro			if (tTd(50, 8))
51490792Sgshapiro				sm_dprintf("dropenvelope(%s): sending postmaster copy to %s\n",
51564562Sgshapiro					id, pcopy);
51664562Sgshapiro			(void) sendtolist(pcopy, NULLADDR, &rlist, 0, e);
51764562Sgshapiro		}
51864562Sgshapiro		if (pmnotify)
51964562Sgshapiro			(void) sendtolist("postmaster", NULLADDR,
52064562Sgshapiro					  &rlist, 0, e);
52164562Sgshapiro		(void) returntosender(e->e_message, rlist,
52264562Sgshapiro				      RTSF_PM_BOUNCE|RTSF_NO_BODY, e);
52338032Speter	}
52438032Speter
52538032Speter	/*
52638032Speter	**  Instantiate or deinstantiate the queue.
52738032Speter	*/
52838032Speter
52938032Spetersimpledrop:
53038032Speter	if (tTd(50, 8))
53190792Sgshapiro		sm_dprintf("dropenvelope(%s): at simpledrop, queueit=%d\n",
53238032Speter			id, queueit);
53338032Speter	if (!queueit || bitset(EF_CLRQUEUE, e->e_flags))
53438032Speter	{
53538032Speter		if (tTd(50, 1))
53638032Speter		{
53790792Sgshapiro			sm_dprintf("\n===== Dropping queue files for %s... queueit=%d, e_flags=",
53838032Speter				e->e_id, queueit);
53938032Speter			printenvflags(e);
54038032Speter		}
54190792Sgshapiro		if (!panic)
542159609Sgshapiro		{
543159609Sgshapiro			if (e->e_dfp != NULL)
544159609Sgshapiro			{
545159609Sgshapiro				(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
546159609Sgshapiro				e->e_dfp = NULL;
547159609Sgshapiro			}
54890792Sgshapiro			(void) xunlink(queuename(e, DATAFL_LETTER));
549159609Sgshapiro		}
55090792Sgshapiro		if (panic && QueueMode == QM_LOST)
55190792Sgshapiro		{
55290792Sgshapiro			/*
55390792Sgshapiro			**  leave the Qf file behind as
55490792Sgshapiro			**  the delivery attempt failed.
55590792Sgshapiro			*/
55638032Speter
55790792Sgshapiro			/* EMPTY */
55890792Sgshapiro		}
55990792Sgshapiro		else
56090792Sgshapiro		if (xunlink(queuename(e, ANYQFL_LETTER)) == 0)
56190792Sgshapiro		{
56290792Sgshapiro			/* add to available space in filesystem */
563147078Sgshapiro			updfs(e, -1, panic ? 0 : -1, "dropenvelope");
56490792Sgshapiro		}
56590792Sgshapiro
56664562Sgshapiro		if (e->e_ntries > 0 && LogLevel > 9)
56764562Sgshapiro			sm_syslog(LOG_INFO, id, "done; delay=%s, ntries=%d",
56890792Sgshapiro				  pintvl(curtime() - e->e_ctime, true),
56964562Sgshapiro				  e->e_ntries);
57038032Speter	}
57138032Speter	else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
57238032Speter	{
57390792Sgshapiro		if (!split)
57490792Sgshapiro			queueup(e, false, true);
57590792Sgshapiro		else
57690792Sgshapiro		{
57790792Sgshapiro			ENVELOPE *oldsib;
57890792Sgshapiro			ENVELOPE *ee;
57990792Sgshapiro
58090792Sgshapiro			/*
58190792Sgshapiro			**  Save old sibling and set it to NULL to avoid
58290792Sgshapiro			**  queueing up the same envelopes again.
58390792Sgshapiro			**  This requires that envelopes in that list have
58490792Sgshapiro			**  been take care of before (or at some other place).
58590792Sgshapiro			*/
58690792Sgshapiro
58790792Sgshapiro			oldsib = e->e_sibling;
58890792Sgshapiro			e->e_sibling = NULL;
58990792Sgshapiro			if (!split_by_recipient(e) &&
59090792Sgshapiro			    bitset(EF_FATALERRS, e->e_flags))
59190792Sgshapiro			{
592285229Sgshapiro				syserr("!dropenvelope(%s): cannot commit data file %s, uid=%ld",
59390792Sgshapiro					e->e_id, queuename(e, DATAFL_LETTER),
594285229Sgshapiro					(long) geteuid());
59590792Sgshapiro			}
59690792Sgshapiro			for (ee = e->e_sibling; ee != NULL; ee = ee->e_sibling)
59790792Sgshapiro				queueup(ee, false, true);
59890792Sgshapiro			queueup(e, false, true);
59990792Sgshapiro
60090792Sgshapiro			/* clean up */
60190792Sgshapiro			for (ee = e->e_sibling; ee != NULL; ee = ee->e_sibling)
60290792Sgshapiro			{
60390792Sgshapiro				/* now unlock the job */
60490792Sgshapiro				if (tTd(50, 8))
60590792Sgshapiro					sm_dprintf("dropenvelope(%s): unlocking job\n",
60690792Sgshapiro						   ee->e_id);
60790792Sgshapiro				closexscript(ee);
60890792Sgshapiro				unlockqueue(ee);
60990792Sgshapiro
61090792Sgshapiro				/* this envelope is marked unused */
61190792Sgshapiro				if (ee->e_dfp != NULL)
61290792Sgshapiro				{
61390792Sgshapiro					(void) sm_io_close(ee->e_dfp,
61490792Sgshapiro							   SM_TIME_DEFAULT);
61590792Sgshapiro					ee->e_dfp = NULL;
61690792Sgshapiro				}
61790792Sgshapiro				ee->e_id = NULL;
61890792Sgshapiro				ee->e_flags &= ~EF_HAS_DF;
61990792Sgshapiro			}
62090792Sgshapiro			e->e_sibling = oldsib;
62190792Sgshapiro		}
62238032Speter	}
62338032Speter
62438032Speter	/* now unlock the job */
62538032Speter	if (tTd(50, 8))
62690792Sgshapiro		sm_dprintf("dropenvelope(%s): unlocking job\n", id);
62738032Speter	closexscript(e);
62838032Speter	unlockqueue(e);
62938032Speter
63038032Speter	/* make sure that this envelope is marked unused */
63138032Speter	if (e->e_dfp != NULL)
63290792Sgshapiro	{
63390792Sgshapiro		(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
63490792Sgshapiro		e->e_dfp = NULL;
63590792Sgshapiro	}
63638032Speter	e->e_id = NULL;
63738032Speter	e->e_flags &= ~EF_HAS_DF;
638203004Sgshapiro	if (panic)
639203004Sgshapiro		return EX_IOERR;
640203004Sgshapiro	return EX_OK;
64138032Speter}
642203004Sgshapiro
64390792Sgshapiro/*
64438032Speter**  CLEARENVELOPE -- clear an envelope without unlocking
64538032Speter**
64638032Speter**	This is normally used by a child process to get a clean
64738032Speter**	envelope without disturbing the parent.
64838032Speter**
64938032Speter**	Parameters:
65038032Speter**		e -- the envelope to clear.
65138032Speter**		fullclear - if set, the current envelope is total
65238032Speter**			garbage and should be ignored; otherwise,
65338032Speter**			release any resources it may indicate.
65490792Sgshapiro**		rpool -- either NULL, or a pointer to a resource pool
65590792Sgshapiro**			from which envelope memory is allocated, and
65690792Sgshapiro**			to which envelope resources are attached.
65738032Speter**
65838032Speter**	Returns:
65938032Speter**		none.
66038032Speter**
66138032Speter**	Side Effects:
66238032Speter**		Closes files associated with the envelope.
66338032Speter**		Marks the envelope as unallocated.
66438032Speter*/
66538032Speter
66638032Spetervoid
66790792Sgshapiroclearenvelope(e, fullclear, rpool)
66838032Speter	register ENVELOPE *e;
66938032Speter	bool fullclear;
67090792Sgshapiro	SM_RPOOL_T *rpool;
67138032Speter{
67238032Speter	register HDR *bh;
67338032Speter	register HDR **nhp;
67438032Speter	extern ENVELOPE BlankEnvelope;
67590792Sgshapiro	char **p;
67638032Speter
67738032Speter	if (!fullclear)
67838032Speter	{
67938032Speter		/* clear out any file information */
68038032Speter		if (e->e_xfp != NULL)
68190792Sgshapiro			(void) sm_io_close(e->e_xfp, SM_TIME_DEFAULT);
68238032Speter		if (e->e_dfp != NULL)
68390792Sgshapiro			(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
68438032Speter		e->e_xfp = e->e_dfp = NULL;
68538032Speter	}
68638032Speter
68790792Sgshapiro	/*
68890792Sgshapiro	**  Copy BlankEnvelope into *e.
68990792Sgshapiro	**  It is not safe to simply copy pointers to strings;
69090792Sgshapiro	**  the strings themselves must be copied (or set to NULL).
69190792Sgshapiro	**  The problem is that when we assign a new string value to
69290792Sgshapiro	**  a member of BlankEnvelope, we free the old string.
69390792Sgshapiro	**  We did not need to do this copying in sendmail 8.11 :-(
69490792Sgshapiro	**  and it is a potential performance hit.  Reference counted
69590792Sgshapiro	**  strings are one way out.
69690792Sgshapiro	*/
69790792Sgshapiro
69890792Sgshapiro	*e = BlankEnvelope;
69938032Speter	e->e_message = NULL;
70090792Sgshapiro	e->e_qfletter = '\0';
70190792Sgshapiro	e->e_quarmsg = NULL;
70290792Sgshapiro	macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), "");
70390792Sgshapiro
70490792Sgshapiro	/*
70590792Sgshapiro	**  Copy the macro table.
70690792Sgshapiro	**  We might be able to avoid this by zeroing the macro table
70790792Sgshapiro	**  and always searching BlankEnvelope.e_macro after e->e_macro
70890792Sgshapiro	**  in macvalue().
70990792Sgshapiro	*/
71090792Sgshapiro
71190792Sgshapiro	for (p = &e->e_macro.mac_table[0];
71290792Sgshapiro	     p <= &e->e_macro.mac_table[MAXMACROID];
71390792Sgshapiro	     ++p)
71490792Sgshapiro	{
71590792Sgshapiro		if (*p != NULL)
71690792Sgshapiro			*p = sm_rpool_strdup_x(rpool, *p);
71790792Sgshapiro	}
71890792Sgshapiro
71990792Sgshapiro	/*
72090792Sgshapiro	**  XXX There are many strings in the envelope structure
72190792Sgshapiro	**  XXX that we are not attempting to copy here.
72290792Sgshapiro	**  XXX Investigate this further.
72390792Sgshapiro	*/
72490792Sgshapiro
72590792Sgshapiro	e->e_rpool = rpool;
72690792Sgshapiro	e->e_macro.mac_rpool = rpool;
72738032Speter	if (Verbose)
72864562Sgshapiro		set_delivery_mode(SM_DELIVER, e);
72938032Speter	bh = BlankEnvelope.e_header;
73038032Speter	nhp = &e->e_header;
73138032Speter	while (bh != NULL)
73238032Speter	{
733168515Sgshapiro		*nhp = (HDR *) sm_rpool_malloc_x(rpool, sizeof(*bh));
734168515Sgshapiro		memmove((char *) *nhp, (char *) bh, sizeof(*bh));
73538032Speter		bh = bh->h_link;
73638032Speter		nhp = &(*nhp)->h_link;
73738032Speter	}
738203004Sgshapiro#if _FFR_MILTER_ENHSC
739203004Sgshapiro	e->e_enhsc[0] = '\0';
740203004Sgshapiro#endif /* _FFR_MILTER_ENHSC */
74138032Speter}
74290792Sgshapiro/*
74338032Speter**  INITSYS -- initialize instantiation of system
74438032Speter**
74538032Speter**	In Daemon mode, this is done in the child.
74638032Speter**
74738032Speter**	Parameters:
74864562Sgshapiro**		e -- the envelope to use.
74938032Speter**
75038032Speter**	Returns:
75138032Speter**		none.
75238032Speter**
75338032Speter**	Side Effects:
75438032Speter**		Initializes the system macros, some global variables,
75538032Speter**		etc.  In particular, the current time in various
75638032Speter**		forms is set.
75738032Speter*/
75838032Speter
75938032Spetervoid
76038032Speterinitsys(e)
76138032Speter	register ENVELOPE *e;
76238032Speter{
76390792Sgshapiro	char buf[10];
76438032Speter#ifdef TTYNAME
76538032Speter	static char ybuf[60];			/* holds tty id */
76638032Speter	register char *p;
76738032Speter	extern char *ttyname();
76838032Speter#endif /* TTYNAME */
76938032Speter
77038032Speter	/*
77138032Speter	**  Give this envelope a reality.
77238032Speter	**	I.e., an id, a transcript, and a creation time.
77390792Sgshapiro	**  We don't select the queue until all of the recipients are known.
77438032Speter	*/
77538032Speter
77638032Speter	openxscript(e);
77738032Speter	e->e_ctime = curtime();
77890792Sgshapiro	e->e_qfletter = '\0';
77938032Speter
78038032Speter	/*
78138032Speter	**  Set OutChannel to something useful if stdout isn't it.
78238032Speter	**	This arranges that any extra stuff the mailer produces
78338032Speter	**	gets sent back to the user on error (because it is
78438032Speter	**	tucked away in the transcript).
78538032Speter	*/
78638032Speter
78738032Speter	if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) &&
78838032Speter	    e->e_xfp != NULL)
78938032Speter		OutChannel = e->e_xfp;
79038032Speter
79138032Speter	/*
79238032Speter	**  Set up some basic system macros.
79338032Speter	*/
79438032Speter
79538032Speter	/* process id */
796168515Sgshapiro	(void) sm_snprintf(buf, sizeof(buf), "%d", (int) CurrentPid);
79790792Sgshapiro	macdefine(&e->e_macro, A_TEMP, 'p', buf);
79838032Speter
79938032Speter	/* hop count */
800168515Sgshapiro	(void) sm_snprintf(buf, sizeof(buf), "%d", e->e_hopcount);
80190792Sgshapiro	macdefine(&e->e_macro, A_TEMP, 'c', buf);
80238032Speter
80338032Speter	/* time as integer, unix time, arpa time */
80438032Speter	settime(e);
80538032Speter
80664562Sgshapiro	/* Load average */
80790792Sgshapiro	sm_getla();
80864562Sgshapiro
80938032Speter#ifdef TTYNAME
81038032Speter	/* tty name */
81138032Speter	if (macvalue('y', e) == NULL)
81238032Speter	{
81338032Speter		p = ttyname(2);
81438032Speter		if (p != NULL)
81538032Speter		{
81638032Speter			if (strrchr(p, '/') != NULL)
81738032Speter				p = strrchr(p, '/') + 1;
818168515Sgshapiro			(void) sm_strlcpy(ybuf, sizeof(ybuf), p);
81990792Sgshapiro			macdefine(&e->e_macro, A_PERM, 'y', ybuf);
82038032Speter		}
82138032Speter	}
82238032Speter#endif /* TTYNAME */
82338032Speter}
82490792Sgshapiro/*
82538032Speter**  SETTIME -- set the current time.
82638032Speter**
82738032Speter**	Parameters:
82864562Sgshapiro**		e -- the envelope in which the macros should be set.
82938032Speter**
83038032Speter**	Returns:
83138032Speter**		none.
83238032Speter**
83338032Speter**	Side Effects:
83438032Speter**		Sets the various time macros -- $a, $b, $d, $t.
83538032Speter*/
83638032Speter
83738032Spetervoid
83838032Spetersettime(e)
83938032Speter	register ENVELOPE *e;
84038032Speter{
84138032Speter	register char *p;
84238032Speter	auto time_t now;
84390792Sgshapiro	char buf[30];
84438032Speter	register struct tm *tm;
84538032Speter
84638032Speter	now = curtime();
847168515Sgshapiro	(void) sm_snprintf(buf, sizeof(buf), "%ld", (long) now);
848132943Sgshapiro	macdefine(&e->e_macro, A_TEMP, macid("{time}"), buf);
84938032Speter	tm = gmtime(&now);
850168515Sgshapiro	(void) sm_snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d",
85190792Sgshapiro			   tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
85290792Sgshapiro			   tm->tm_hour, tm->tm_min);
85390792Sgshapiro	macdefine(&e->e_macro, A_TEMP, 't', buf);
854168515Sgshapiro	(void) sm_strlcpy(buf, ctime(&now), sizeof(buf));
85590792Sgshapiro	p = strchr(buf, '\n');
85638032Speter	if (p != NULL)
85738032Speter		*p = '\0';
85890792Sgshapiro	macdefine(&e->e_macro, A_TEMP, 'd', buf);
85990792Sgshapiro	macdefine(&e->e_macro, A_TEMP, 'b', arpadate(buf));
86038032Speter	if (macvalue('a', e) == NULL)
86190792Sgshapiro		macdefine(&e->e_macro, A_PERM, 'a', macvalue('b', e));
86238032Speter}
86390792Sgshapiro/*
86438032Speter**  OPENXSCRIPT -- Open transcript file
86538032Speter**
86638032Speter**	Creates a transcript file for possible eventual mailing or
86738032Speter**	sending back.
86838032Speter**
86938032Speter**	Parameters:
87038032Speter**		e -- the envelope to create the transcript in/for.
87138032Speter**
87238032Speter**	Returns:
87338032Speter**		none
87438032Speter**
87538032Speter**	Side Effects:
87638032Speter**		Creates the transcript file.
87738032Speter*/
87838032Speter
87938032Speter#ifndef O_APPEND
88064562Sgshapiro# define O_APPEND	0
88164562Sgshapiro#endif /* ! O_APPEND */
88238032Speter
88338032Spetervoid
88438032Speteropenxscript(e)
88538032Speter	register ENVELOPE *e;
88638032Speter{
88738032Speter	register char *p;
88838032Speter
88938032Speter	if (e->e_xfp != NULL)
89038032Speter		return;
89164562Sgshapiro
89264562Sgshapiro#if 0
89364562Sgshapiro	if (e->e_lockfp == NULL && bitset(EF_INQUEUE, e->e_flags))
89464562Sgshapiro		syserr("openxscript: job not locked");
89564562Sgshapiro#endif /* 0 */
89664562Sgshapiro
89790792Sgshapiro	p = queuename(e, XSCRPT_LETTER);
89864562Sgshapiro	e->e_xfp = bfopen(p, FileMode, XscriptFileBufferSize,
89964562Sgshapiro			  SFF_NOTEXCL|SFF_OPENASROOT);
90064562Sgshapiro
90164562Sgshapiro	if (e->e_xfp == NULL)
90238032Speter	{
90338032Speter		syserr("Can't create transcript file %s", p);
90490792Sgshapiro		e->e_xfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT,
90590792Sgshapiro				      SM_PATH_DEVNULL, SM_IO_RDWR, NULL);
90664562Sgshapiro		if (e->e_xfp == NULL)
90790792Sgshapiro			syserr("!Can't open %s", SM_PATH_DEVNULL);
90838032Speter	}
90990792Sgshapiro	(void) sm_io_setvbuf(e->e_xfp, SM_TIME_DEFAULT, NULL, SM_IO_LBF, 0);
91038032Speter	if (tTd(46, 9))
91138032Speter	{
91290792Sgshapiro		sm_dprintf("openxscript(%s):\n  ", p);
91390792Sgshapiro		dumpfd(sm_io_getinfo(e->e_xfp, SM_IO_WHAT_FD, NULL), true,
91490792Sgshapiro		       false);
91538032Speter	}
91638032Speter}
91790792Sgshapiro/*
91838032Speter**  CLOSEXSCRIPT -- close the transcript file.
91938032Speter**
92038032Speter**	Parameters:
92138032Speter**		e -- the envelope containing the transcript to close.
92238032Speter**
92338032Speter**	Returns:
92438032Speter**		none.
92538032Speter**
92638032Speter**	Side Effects:
92738032Speter**		none.
92838032Speter*/
92938032Speter
93038032Spetervoid
93138032Speterclosexscript(e)
93238032Speter	register ENVELOPE *e;
93338032Speter{
93438032Speter	if (e->e_xfp == NULL)
93538032Speter		return;
93664562Sgshapiro#if 0
93764562Sgshapiro	if (e->e_lockfp == NULL)
93864562Sgshapiro		syserr("closexscript: job not locked");
93964562Sgshapiro#endif /* 0 */
94090792Sgshapiro	(void) sm_io_close(e->e_xfp, SM_TIME_DEFAULT);
94138032Speter	e->e_xfp = NULL;
94238032Speter}
94390792Sgshapiro/*
94438032Speter**  SETSENDER -- set the person who this message is from
94538032Speter**
94638032Speter**	Under certain circumstances allow the user to say who
94738032Speter**	s/he is (using -f or -r).  These are:
94838032Speter**	1.  The user's uid is zero (root).
94938032Speter**	2.  The user's login name is in an approved list (typically
95038032Speter**	    from a network server).
95138032Speter**	3.  The address the user is trying to claim has a
95238032Speter**	    "!" character in it (since #2 doesn't do it for
95338032Speter**	    us if we are dialing out for UUCP).
95438032Speter**	A better check to replace #3 would be if the
95538032Speter**	effective uid is "UUCP" -- this would require me
95638032Speter**	to rewrite getpwent to "grab" uucp as it went by,
95738032Speter**	make getname more nasty, do another passwd file
95838032Speter**	scan, or compile the UID of "UUCP" into the code,
95938032Speter**	all of which are reprehensible.
96038032Speter**
96138032Speter**	Assuming all of these fail, we figure out something
96238032Speter**	ourselves.
96338032Speter**
96438032Speter**	Parameters:
96538032Speter**		from -- the person we would like to believe this message
96638032Speter**			is from, as specified on the command line.
96738032Speter**		e -- the envelope in which we would like the sender set.
96838032Speter**		delimptr -- if non-NULL, set to the location of the
96938032Speter**			trailing delimiter.
97038032Speter**		delimchar -- the character that will delimit the sender
97138032Speter**			address.
97238032Speter**		internal -- set if this address is coming from an internal
97338032Speter**			source such as an owner alias.
97438032Speter**
97538032Speter**	Returns:
97638032Speter**		none.
97738032Speter**
97838032Speter**	Side Effects:
97938032Speter**		sets sendmail's notion of who the from person is.
98038032Speter*/
98138032Speter
98238032Spetervoid
98338032Spetersetsender(from, e, delimptr, delimchar, internal)
98438032Speter	char *from;
98538032Speter	register ENVELOPE *e;
98638032Speter	char **delimptr;
98738032Speter	int delimchar;
98838032Speter	bool internal;
98938032Speter{
99038032Speter	register char **pvp;
99138032Speter	char *realname = NULL;
99238032Speter	char *bp;
99338032Speter	char buf[MAXNAME + 2];
99438032Speter	char pvpbuf[PSBUFSIZE];
99538032Speter	extern char *FullName;
99638032Speter
99738032Speter	if (tTd(45, 1))
99890792Sgshapiro		sm_dprintf("setsender(%s)\n", from == NULL ? "" : from);
99938032Speter
1000110560Sgshapiro	/* may be set from earlier calls */
1001110560Sgshapiro	macdefine(&e->e_macro, A_PERM, 'x', "");
1002110560Sgshapiro
100338032Speter	/*
100438032Speter	**  Figure out the real user executing us.
100538032Speter	**	Username can return errno != 0 on non-errors.
100638032Speter	*/
100738032Speter
100838032Speter	if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP ||
100938032Speter	    OpMode == MD_ARPAFTP || OpMode == MD_DAEMON)
101038032Speter		realname = from;
101138032Speter	if (realname == NULL || realname[0] == '\0')
101238032Speter		realname = username();
101338032Speter
101438032Speter	if (ConfigLevel < 2)
101590792Sgshapiro		SuprErrs = true;
101638032Speter
101790792Sgshapiro	macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e s");
101890792Sgshapiro
101964562Sgshapiro	/* preset state for then clause in case from == NULL */
102064562Sgshapiro	e->e_from.q_state = QS_BADADDR;
102164562Sgshapiro	e->e_from.q_flags = 0;
102238032Speter	if (from == NULL ||
102338032Speter	    parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR,
102490792Sgshapiro		      delimchar, delimptr, e, false) == NULL ||
102564562Sgshapiro	    QS_IS_BADADDR(e->e_from.q_state) ||
102638032Speter	    e->e_from.q_mailer == ProgMailer ||
102738032Speter	    e->e_from.q_mailer == FileMailer ||
102838032Speter	    e->e_from.q_mailer == InclMailer)
102938032Speter	{
103038032Speter		/* log garbage addresses for traceback */
103138032Speter		if (from != NULL && LogLevel > 2)
103238032Speter		{
103338032Speter			char *p;
103438032Speter			char ebuf[MAXNAME * 2 + 2];
103538032Speter
103638032Speter			p = macvalue('_', e);
103738032Speter			if (p == NULL)
103838032Speter			{
103938032Speter				char *host = RealHostName;
104038032Speter
104138032Speter				if (host == NULL)
104238032Speter					host = MyHostName;
1043168515Sgshapiro				(void) sm_snprintf(ebuf, sizeof(ebuf),
104490792Sgshapiro						   "%.*s@%.*s", MAXNAME,
104590792Sgshapiro						   realname, MAXNAME, host);
104638032Speter				p = ebuf;
104738032Speter			}
104838032Speter			sm_syslog(LOG_NOTICE, e->e_id,
104964562Sgshapiro				  "setsender: %s: invalid or unparsable, received from %s",
105064562Sgshapiro				  shortenstring(from, 83), p);
105138032Speter		}
105238032Speter		if (from != NULL)
105338032Speter		{
105464562Sgshapiro			if (!QS_IS_BADADDR(e->e_from.q_state))
105538032Speter			{
105638032Speter				/* it was a bogus mailer in the from addr */
105738032Speter				e->e_status = "5.1.7";
105864562Sgshapiro				usrerrenh(e->e_status,
105964562Sgshapiro					  "553 Invalid sender address");
106038032Speter			}
106190792Sgshapiro			SuprErrs = true;
106238032Speter		}
106338032Speter		if (from == realname ||
106490792Sgshapiro		    parseaddr(from = realname,
106590792Sgshapiro			      &e->e_from, RF_COPYALL|RF_SENDERADDR, ' ',
106690792Sgshapiro			      NULL, e, false) == NULL)
106738032Speter		{
106838032Speter			char nbuf[100];
106938032Speter
107090792Sgshapiro			SuprErrs = true;
1071168515Sgshapiro			expand("\201n", nbuf, sizeof(nbuf), e);
107290792Sgshapiro			from = sm_rpool_strdup_x(e->e_rpool, nbuf);
107390792Sgshapiro			if (parseaddr(from, &e->e_from, RF_COPYALL, ' ',
107490792Sgshapiro				      NULL, e, false) == NULL &&
107538032Speter			    parseaddr(from = "postmaster", &e->e_from,
107690792Sgshapiro				      RF_COPYALL, ' ', NULL, e, false) == NULL)
107764562Sgshapiro				syserr("553 5.3.0 setsender: can't even parse postmaster!");
107838032Speter		}
107938032Speter	}
108038032Speter	else
108190792Sgshapiro		FromFlag = true;
108264562Sgshapiro	e->e_from.q_state = QS_SENDER;
108338032Speter	if (tTd(45, 5))
108438032Speter	{
108590792Sgshapiro		sm_dprintf("setsender: QS_SENDER ");
1086132943Sgshapiro		printaddr(sm_debug_file(), &e->e_from, false);
108738032Speter	}
108890792Sgshapiro	SuprErrs = false;
108938032Speter
109064562Sgshapiro#if USERDB
109138032Speter	if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags))
109238032Speter	{
109338032Speter		register char *p;
109438032Speter
109590792Sgshapiro		p = udbsender(e->e_from.q_user, e->e_rpool);
109638032Speter		if (p != NULL)
109738032Speter			from = p;
109838032Speter	}
109964562Sgshapiro#endif /* USERDB */
110038032Speter
110138032Speter	if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags))
110238032Speter	{
110390792Sgshapiro		SM_MBDB_T user;
110490792Sgshapiro
110538032Speter		if (!internal)
110638032Speter		{
110738032Speter			/* if the user already given fullname don't redefine */
110838032Speter			if (FullName == NULL)
110938032Speter				FullName = macvalue('x', e);
111094334Sgshapiro			if (FullName != NULL)
111194334Sgshapiro			{
111294334Sgshapiro				if (FullName[0] == '\0')
111394334Sgshapiro					FullName = NULL;
111494334Sgshapiro				else
111594334Sgshapiro					FullName = newstr(FullName);
111694334Sgshapiro			}
111738032Speter		}
111838032Speter
111938032Speter		if (e->e_from.q_user[0] != '\0' &&
112090792Sgshapiro		    sm_mbdb_lookup(e->e_from.q_user, &user) == EX_OK)
112138032Speter		{
112238032Speter			/*
112338032Speter			**  Process passwd file entry.
112438032Speter			*/
112538032Speter
112638032Speter			/* extract home directory */
112790792Sgshapiro			if (*user.mbdb_homedir == '\0')
112866494Sgshapiro				e->e_from.q_home = NULL;
112990792Sgshapiro			else if (strcmp(user.mbdb_homedir, "/") == 0)
113090792Sgshapiro				e->e_from.q_home = "";
113138032Speter			else
113290792Sgshapiro				e->e_from.q_home = sm_rpool_strdup_x(e->e_rpool,
113390792Sgshapiro							user.mbdb_homedir);
113490792Sgshapiro			macdefine(&e->e_macro, A_PERM, 'z', e->e_from.q_home);
113538032Speter
113638032Speter			/* extract user and group id */
113790792Sgshapiro			if (user.mbdb_uid != SM_NO_UID)
113890792Sgshapiro			{
113990792Sgshapiro				e->e_from.q_uid = user.mbdb_uid;
114090792Sgshapiro				e->e_from.q_gid = user.mbdb_gid;
114190792Sgshapiro				e->e_from.q_flags |= QGOODUID;
114290792Sgshapiro			}
114338032Speter
114438032Speter			/* extract full name from passwd file */
114590792Sgshapiro			if (FullName == NULL && !internal &&
114690792Sgshapiro			    user.mbdb_fullname[0] != '\0' &&
114790792Sgshapiro			    strcmp(user.mbdb_name, e->e_from.q_user) == 0)
114838032Speter			{
114990792Sgshapiro				FullName = newstr(user.mbdb_fullname);
115038032Speter			}
115138032Speter		}
115238032Speter		else
115338032Speter		{
115464562Sgshapiro			e->e_from.q_home = NULL;
115538032Speter		}
115638032Speter		if (FullName != NULL && !internal)
1157110560Sgshapiro			macdefine(&e->e_macro, A_TEMP, 'x', FullName);
115838032Speter	}
115943730Speter	else if (!internal && OpMode != MD_DAEMON && OpMode != MD_SMTP)
116038032Speter	{
116138032Speter		if (e->e_from.q_home == NULL)
116238032Speter		{
116338032Speter			e->e_from.q_home = getenv("HOME");
116466494Sgshapiro			if (e->e_from.q_home != NULL)
116566494Sgshapiro			{
116666494Sgshapiro				if (*e->e_from.q_home == '\0')
116766494Sgshapiro					e->e_from.q_home = NULL;
116866494Sgshapiro				else if (strcmp(e->e_from.q_home, "/") == 0)
116966494Sgshapiro					e->e_from.q_home++;
117066494Sgshapiro			}
117138032Speter		}
117238032Speter		e->e_from.q_uid = RealUid;
117338032Speter		e->e_from.q_gid = RealGid;
117438032Speter		e->e_from.q_flags |= QGOODUID;
117538032Speter	}
117638032Speter
117738032Speter	/*
117838032Speter	**  Rewrite the from person to dispose of possible implicit
117938032Speter	**	links in the net.
118038032Speter	*/
118138032Speter
1182168515Sgshapiro	pvp = prescan(from, delimchar, pvpbuf, sizeof(pvpbuf), NULL,
1183168515Sgshapiro			IntTokenTab, false);
118438032Speter	if (pvp == NULL)
118538032Speter	{
118638032Speter		/* don't need to give error -- prescan did that already */
118738032Speter		if (LogLevel > 2)
118838032Speter			sm_syslog(LOG_NOTICE, e->e_id,
118964562Sgshapiro				  "cannot prescan from (%s)",
119064562Sgshapiro				  shortenstring(from, MAXSHORTSTR));
119190792Sgshapiro		finis(true, true, ExitStat);
119238032Speter	}
119390792Sgshapiro	(void) REWRITE(pvp, 3, e);
119490792Sgshapiro	(void) REWRITE(pvp, 1, e);
119590792Sgshapiro	(void) REWRITE(pvp, 4, e);
119690792Sgshapiro	macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL);
119738032Speter	bp = buf + 1;
1198168515Sgshapiro	cataddr(pvp, NULL, bp, sizeof(buf) - 2, '\0', false);
119938032Speter	if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags))
120038032Speter	{
120138032Speter		/* heuristic: route-addr: add angle brackets */
1202168515Sgshapiro		(void) sm_strlcat(bp, ">", sizeof(buf) - 1);
120338032Speter		*--bp = '<';
120438032Speter	}
120590792Sgshapiro	e->e_sender = sm_rpool_strdup_x(e->e_rpool, bp);
120690792Sgshapiro	macdefine(&e->e_macro, A_PERM, 'f', e->e_sender);
120738032Speter
120838032Speter	/* save the domain spec if this mailer wants it */
120938032Speter	if (e->e_from.q_mailer != NULL &&
121038032Speter	    bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags))
121138032Speter	{
121238032Speter		char **lastat;
121338032Speter
121438032Speter		/* get rid of any pesky angle brackets */
121590792Sgshapiro		macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e s");
121690792Sgshapiro		(void) REWRITE(pvp, 3, e);
121790792Sgshapiro		(void) REWRITE(pvp, 1, e);
121890792Sgshapiro		(void) REWRITE(pvp, 4, e);
121990792Sgshapiro		macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL);
122038032Speter
122138032Speter		/* strip off to the last "@" sign */
122238032Speter		for (lastat = NULL; *pvp != NULL; pvp++)
1223132943Sgshapiro		{
122438032Speter			if (strcmp(*pvp, "@") == 0)
122538032Speter				lastat = pvp;
1226132943Sgshapiro		}
122738032Speter		if (lastat != NULL)
122838032Speter		{
122990792Sgshapiro			e->e_fromdomain = copyplist(lastat, true, e->e_rpool);
123038032Speter			if (tTd(45, 3))
123138032Speter			{
123290792Sgshapiro				sm_dprintf("Saving from domain: ");
1233132943Sgshapiro				printav(sm_debug_file(), e->e_fromdomain);
123438032Speter			}
123538032Speter		}
123638032Speter	}
123738032Speter}
123890792Sgshapiro/*
123938032Speter**  PRINTENVFLAGS -- print envelope flags for debugging
124038032Speter**
124138032Speter**	Parameters:
124238032Speter**		e -- the envelope with the flags to be printed.
124338032Speter**
124438032Speter**	Returns:
124538032Speter**		none.
124638032Speter*/
124738032Speter
124838032Speterstruct eflags
124938032Speter{
125090792Sgshapiro	char		*ef_name;
125190792Sgshapiro	unsigned long	ef_bit;
125238032Speter};
125338032Speter
125464562Sgshapirostatic struct eflags	EnvelopeFlags[] =
125538032Speter{
125638032Speter	{ "OLDSTYLE",		EF_OLDSTYLE	},
125738032Speter	{ "INQUEUE",		EF_INQUEUE	},
125838032Speter	{ "NO_BODY_RETN",	EF_NO_BODY_RETN	},
125938032Speter	{ "CLRQUEUE",		EF_CLRQUEUE	},
126038032Speter	{ "SENDRECEIPT",	EF_SENDRECEIPT	},
126138032Speter	{ "FATALERRS",		EF_FATALERRS	},
126238032Speter	{ "DELETE_BCC",		EF_DELETE_BCC	},
126338032Speter	{ "RESPONSE",		EF_RESPONSE	},
126438032Speter	{ "RESENT",		EF_RESENT	},
126538032Speter	{ "VRFYONLY",		EF_VRFYONLY	},
126638032Speter	{ "WARNING",		EF_WARNING	},
126738032Speter	{ "QUEUERUN",		EF_QUEUERUN	},
126838032Speter	{ "GLOBALERRS",		EF_GLOBALERRS	},
126938032Speter	{ "PM_NOTIFY",		EF_PM_NOTIFY	},
127038032Speter	{ "METOO",		EF_METOO	},
127138032Speter	{ "LOGSENDER",		EF_LOGSENDER	},
127238032Speter	{ "NORECEIPT",		EF_NORECEIPT	},
127338032Speter	{ "HAS8BIT",		EF_HAS8BIT	},
127438032Speter	{ "NL_NOT_EOL",		EF_NL_NOT_EOL	},
127538032Speter	{ "CRLF_NOT_EOL",	EF_CRLF_NOT_EOL	},
127638032Speter	{ "RET_PARAM",		EF_RET_PARAM	},
127738032Speter	{ "HAS_DF",		EF_HAS_DF	},
127838032Speter	{ "IS_MIME",		EF_IS_MIME	},
127938032Speter	{ "DONT_MIME",		EF_DONT_MIME	},
128090792Sgshapiro	{ "DISCARD",		EF_DISCARD	},
128190792Sgshapiro	{ "TOOBIG",		EF_TOOBIG	},
128290792Sgshapiro	{ "SPLIT",		EF_SPLIT	},
128390792Sgshapiro	{ "UNSAFE",		EF_UNSAFE	},
128471345Sgshapiro	{ NULL,			0		}
128538032Speter};
128638032Speter
128738032Spetervoid
128838032Speterprintenvflags(e)
128938032Speter	register ENVELOPE *e;
129038032Speter{
129138032Speter	register struct eflags *ef;
129290792Sgshapiro	bool first = true;
129338032Speter
1294132943Sgshapiro	sm_dprintf("%lx", e->e_flags);
129538032Speter	for (ef = EnvelopeFlags; ef->ef_name != NULL; ef++)
129638032Speter	{
129738032Speter		if (!bitset(ef->ef_bit, e->e_flags))
129838032Speter			continue;
129938032Speter		if (first)
1300132943Sgshapiro			sm_dprintf("<%s", ef->ef_name);
130138032Speter		else
1302132943Sgshapiro			sm_dprintf(",%s", ef->ef_name);
130390792Sgshapiro		first = false;
130438032Speter	}
130538032Speter	if (!first)
1306132943Sgshapiro		sm_dprintf(">\n");
130738032Speter}
1308