envelope.c revision 132943
138032Speter/*
2132943Sgshapiro * Copyright (c) 1998-2003 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
16132943SgshapiroSM_RCSID("@(#)$Id: envelope.c,v 8.293 2004/02/18 00:46:18 gshapiro 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{
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
8790792Sgshapiro	if (e == parent)
8838032Speter		parent = e->e_parent;
8990792Sgshapiro	clearenvelope(e, true, rpool);
9038032Speter	if (e == CurEnv)
9164562Sgshapiro		memmove((char *) &e->e_from,
9264562Sgshapiro			(char *) &NullAddress,
9364562Sgshapiro			sizeof e->e_from);
9438032Speter	else
9564562Sgshapiro		memmove((char *) &e->e_from,
9664562Sgshapiro			(char *) &CurEnv->e_from,
9764562Sgshapiro			sizeof e->e_from);
9838032Speter	e->e_parent = parent;
9964562Sgshapiro	assign_queueid(e);
10038032Speter	e->e_ctime = curtime();
10138032Speter	if (parent != NULL)
10290792Sgshapiro	{
10338032Speter		e->e_msgpriority = parent->e_msgsize;
10490792Sgshapiro		if (parent->e_quarmsg == NULL)
10590792Sgshapiro		{
10690792Sgshapiro			e->e_quarmsg = NULL;
10790792Sgshapiro			macdefine(&e->e_macro, A_PERM,
10890792Sgshapiro				  macid("{quarantine}"), "");
10990792Sgshapiro		}
11090792Sgshapiro		else
11190792Sgshapiro		{
11290792Sgshapiro			e->e_quarmsg = sm_rpool_strdup_x(rpool,
11390792Sgshapiro							 parent->e_quarmsg);
11490792Sgshapiro			macdefine(&e->e_macro, A_PERM,
11590792Sgshapiro				  macid("{quarantine}"), e->e_quarmsg);
11690792Sgshapiro		}
11790792Sgshapiro	}
11838032Speter	e->e_puthdr = putheader;
11938032Speter	e->e_putbody = putbody;
12038032Speter	if (CurEnv->e_xfp != NULL)
12190792Sgshapiro		(void) sm_io_flush(CurEnv->e_xfp, SM_TIME_DEFAULT);
12238032Speter
12364562Sgshapiro	return e;
12438032Speter}
12590792Sgshapiro
12690792Sgshapiro/* values for msg_timeout, see also IS_* below for usage (bit layout) */
12790792Sgshapiro#define MSG_T_O		0x01	/* normal timeout */
12890792Sgshapiro#define MSG_T_O_NOW	0x02	/* NOW timeout */
12990792Sgshapiro#define MSG_NOT_BY	0x04	/* Deliver-By time exceeded, mode R */
13090792Sgshapiro#define MSG_WARN	0x10	/* normal queue warning */
13190792Sgshapiro#define MSG_WARN_BY	0x20	/* Deliver-By time exceeded, mode N */
13290792Sgshapiro
13390792Sgshapiro#define IS_MSG_ERR(x)	(((x) & 0x0f) != 0)	/* return an error */
13490792Sgshapiro
13590792Sgshapiro/* immediate return */
13690792Sgshapiro#define IS_IMM_RET(x)	(((x) & (MSG_T_O_NOW|MSG_NOT_BY)) != 0)
13790792Sgshapiro#define IS_MSG_WARN(x)	(((x) & 0xf0) != 0)	/* return a warning */
13890792Sgshapiro
13990792Sgshapiro/*
14038032Speter**  DROPENVELOPE -- deallocate an envelope.
14138032Speter**
14238032Speter**	Parameters:
14338032Speter**		e -- the envelope to deallocate.
14438032Speter**		fulldrop -- if set, do return receipts.
14590792Sgshapiro**		split -- if true, split by recipient if message is queued up
14638032Speter**
14738032Speter**	Returns:
14838032Speter**		none.
14938032Speter**
15038032Speter**	Side Effects:
15138032Speter**		housekeeping necessary to dispose of an envelope.
15238032Speter**		Unlocks this queue file.
15338032Speter*/
15438032Speter
15538032Spetervoid
15690792Sgshapirodropenvelope(e, fulldrop, split)
15738032Speter	register ENVELOPE *e;
15838032Speter	bool fulldrop;
15990792Sgshapiro	bool split;
16038032Speter{
16190792Sgshapiro	bool panic = false;
16290792Sgshapiro	bool queueit = false;
16390792Sgshapiro	int msg_timeout = 0;
16490792Sgshapiro	bool failure_return = false;
16590792Sgshapiro	bool delay_return = false;
16690792Sgshapiro	bool success_return = false;
16764562Sgshapiro	bool pmnotify = bitset(EF_PM_NOTIFY, e->e_flags);
16890792Sgshapiro	bool done = false;
16938032Speter	register ADDRESS *q;
17038032Speter	char *id = e->e_id;
17171345Sgshapiro	time_t now;
17238032Speter	char buf[MAXLINE];
17338032Speter
17438032Speter	if (tTd(50, 1))
17538032Speter	{
17690792Sgshapiro		sm_dprintf("dropenvelope %p: id=", e);
177132943Sgshapiro		xputs(sm_debug_file(), e->e_id);
17890792Sgshapiro		sm_dprintf(", flags=");
17938032Speter		printenvflags(e);
18038032Speter		if (tTd(50, 10))
18138032Speter		{
18290792Sgshapiro			sm_dprintf("sendq=");
183132943Sgshapiro			printaddr(sm_debug_file(), e->e_sendqueue, true);
18438032Speter		}
18538032Speter	}
18638032Speter
18738032Speter	if (LogLevel > 84)
18838032Speter		sm_syslog(LOG_DEBUG, id,
18964562Sgshapiro			  "dropenvelope, e_flags=0x%lx, OpMode=%c, pid=%d",
19090792Sgshapiro			  e->e_flags, OpMode, (int) CurrentPid);
19138032Speter
19238032Speter	/* we must have an id to remove disk files */
19338032Speter	if (id == NULL)
19438032Speter		return;
19538032Speter
19638032Speter	/* if verify-only mode, we can skip most of this */
19738032Speter	if (OpMode == MD_VERIFY)
19838032Speter		goto simpledrop;
19938032Speter
20038032Speter	if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
20138032Speter		logsender(e, NULL);
20238032Speter	e->e_flags &= ~EF_LOGSENDER;
20338032Speter
20438032Speter	/* post statistics */
20538032Speter	poststats(StatFile);
20638032Speter
20738032Speter	/*
20838032Speter	**  Extract state information from dregs of send list.
20938032Speter	*/
21038032Speter
21171345Sgshapiro	now = curtime();
21277349Sgshapiro	if (now >= e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass])
21390792Sgshapiro		msg_timeout = MSG_T_O;
21490792Sgshapiro	if (IS_DLVR_RETURN(e) && e->e_deliver_by > 0 &&
21590792Sgshapiro	    now >= e->e_ctime + e->e_deliver_by &&
21664562Sgshapiro	    !bitset(EF_RESPONSE, e->e_flags))
21764562Sgshapiro	{
21890792Sgshapiro		msg_timeout = MSG_NOT_BY;
21964562Sgshapiro		e->e_flags |= EF_FATALERRS|EF_CLRQUEUE;
22064562Sgshapiro	}
22190792Sgshapiro	else if (TimeOuts.to_q_return[e->e_timeoutclass] == NOW &&
22290792Sgshapiro		 !bitset(EF_RESPONSE, e->e_flags))
22390792Sgshapiro	{
22490792Sgshapiro		msg_timeout = MSG_T_O_NOW;
22590792Sgshapiro		e->e_flags |= EF_FATALERRS|EF_CLRQUEUE;
22690792Sgshapiro	}
22764562Sgshapiro
22838032Speter	e->e_flags &= ~EF_QUEUERUN;
22938032Speter	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
23038032Speter	{
23164562Sgshapiro		if (QS_IS_UNDELIVERED(q->q_state))
23290792Sgshapiro			queueit = true;
23338032Speter
23438032Speter		/* see if a notification is needed */
23538032Speter		if (bitset(QPINGONFAILURE, q->q_flags) &&
23690792Sgshapiro		    ((IS_MSG_ERR(msg_timeout) &&
23790792Sgshapiro		      QS_IS_UNDELIVERED(q->q_state)) ||
23864562Sgshapiro		     QS_IS_BADADDR(q->q_state) ||
23990792Sgshapiro		     IS_IMM_RET(msg_timeout)))
24038032Speter		{
24190792Sgshapiro			failure_return = true;
24264562Sgshapiro			if (!done && q->q_owner == NULL &&
24364562Sgshapiro			    !emptyaddr(&e->e_from))
24464562Sgshapiro			{
24538032Speter				(void) sendtolist(e->e_from.q_paddr, NULLADDR,
24638032Speter						  &e->e_errorqueue, 0, e);
24790792Sgshapiro				done = true;
24864562Sgshapiro			}
24938032Speter		}
25090792Sgshapiro		else if ((bitset(QPINGONSUCCESS, q->q_flags) &&
25190792Sgshapiro			  ((QS_IS_SENT(q->q_state) &&
25290792Sgshapiro			    bitnset(M_LOCALMAILER, q->q_mailer->m_flags)) ||
25390792Sgshapiro			   bitset(QRELAYED|QEXPANDED|QDELIVERED, q->q_flags))) ||
25490792Sgshapiro			  bitset(QBYTRACE, q->q_flags) ||
25590792Sgshapiro			  bitset(QBYNRELAY, q->q_flags))
25638032Speter		{
25790792Sgshapiro			success_return = true;
25838032Speter		}
25938032Speter	}
26038032Speter
26138032Speter	if (e->e_class < 0)
26238032Speter		e->e_flags |= EF_NO_BODY_RETN;
26338032Speter
26438032Speter	/*
26538032Speter	**  See if the message timed out.
26638032Speter	*/
26738032Speter
26838032Speter	if (!queueit)
26964562Sgshapiro		/* EMPTY */
27038032Speter		/* nothing to do */ ;
27190792Sgshapiro	else if (IS_MSG_ERR(msg_timeout))
27238032Speter	{
27338032Speter		if (failure_return)
27438032Speter		{
27590792Sgshapiro			if (msg_timeout == MSG_NOT_BY)
27690792Sgshapiro			{
27790792Sgshapiro				(void) sm_snprintf(buf, sizeof buf,
27890792Sgshapiro					"delivery time expired %lds",
27990792Sgshapiro					e->e_deliver_by);
28090792Sgshapiro			}
28190792Sgshapiro			else
28290792Sgshapiro			{
28390792Sgshapiro				(void) sm_snprintf(buf, sizeof buf,
28464562Sgshapiro					"Cannot send message for %s",
28590792Sgshapiro					pintvl(TimeOuts.to_q_return[e->e_timeoutclass],
28690792Sgshapiro						false));
28790792Sgshapiro			}
28890792Sgshapiro
28990792Sgshapiro			/* don't free, allocated from e_rpool */
29090792Sgshapiro			e->e_message = sm_rpool_strdup_x(e->e_rpool, buf);
29138032Speter			message(buf);
29238032Speter			e->e_flags |= EF_CLRQUEUE;
29338032Speter		}
29490792Sgshapiro		if (msg_timeout == MSG_NOT_BY)
29590792Sgshapiro		{
29690792Sgshapiro			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
29790792Sgshapiro				"Delivery time (%lds) expired\n",
29890792Sgshapiro				e->e_deliver_by);
29990792Sgshapiro		}
30090792Sgshapiro		else
30190792Sgshapiro			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
30290792Sgshapiro				"Message could not be delivered for %s\n",
30390792Sgshapiro				pintvl(TimeOuts.to_q_return[e->e_timeoutclass],
30490792Sgshapiro					false));
30590792Sgshapiro		(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
30690792Sgshapiro			"Message will be deleted from queue\n");
30738032Speter		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
30838032Speter		{
30964562Sgshapiro			if (QS_IS_UNDELIVERED(q->q_state))
31038032Speter			{
31164562Sgshapiro				q->q_state = QS_BADADDR;
31290792Sgshapiro				if (msg_timeout == MSG_NOT_BY)
31390792Sgshapiro					q->q_status = "5.4.7";
31490792Sgshapiro				else
31590792Sgshapiro					q->q_status = "4.4.7";
31638032Speter			}
31738032Speter		}
31838032Speter	}
31990792Sgshapiro	else
32038032Speter	{
32190792Sgshapiro		if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 &&
32290792Sgshapiro		    now >= e->e_ctime +
32390792Sgshapiro				TimeOuts.to_q_warning[e->e_timeoutclass])
32490792Sgshapiro			msg_timeout = MSG_WARN;
32590792Sgshapiro		else if (IS_DLVR_NOTIFY(e) &&
32690792Sgshapiro			 e->e_deliver_by > 0 &&
32790792Sgshapiro			 now >= e->e_ctime + e->e_deliver_by)
32890792Sgshapiro			msg_timeout = MSG_WARN_BY;
32990792Sgshapiro
33090792Sgshapiro		if (IS_MSG_WARN(msg_timeout))
33138032Speter		{
33290792Sgshapiro			if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) &&
33390792Sgshapiro			    e->e_class >= 0 &&
33490792Sgshapiro			    e->e_from.q_paddr != NULL &&
33590792Sgshapiro			    strcmp(e->e_from.q_paddr, "<>") != 0 &&
33690792Sgshapiro			    sm_strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 &&
33790792Sgshapiro			    (strlen(e->e_from.q_paddr) <= 8 ||
33890792Sgshapiro			     sm_strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8],
33990792Sgshapiro					   "-request") != 0))
34038032Speter			{
34190792Sgshapiro				for (q = e->e_sendqueue; q != NULL;
34290792Sgshapiro				     q = q->q_next)
34390792Sgshapiro				{
34490792Sgshapiro					if (QS_IS_UNDELIVERED(q->q_state)
34564562Sgshapiro#if _FFR_NODELAYDSN_ON_HOLD
34690792Sgshapiro					    && !bitnset(M_HOLD,
34790792Sgshapiro							q->q_mailer->m_flags)
34864562Sgshapiro#endif /* _FFR_NODELAYDSN_ON_HOLD */
34990792Sgshapiro					   )
35090792Sgshapiro					{
35190792Sgshapiro						if (msg_timeout ==
35290792Sgshapiro						    MSG_WARN_BY &&
35390792Sgshapiro						    (bitset(QPINGONDELAY,
35490792Sgshapiro							    q->q_flags) ||
35590792Sgshapiro						    !bitset(QHASNOTIFY,
35690792Sgshapiro							    q->q_flags))
35790792Sgshapiro						   )
35890792Sgshapiro						{
35990792Sgshapiro							q->q_flags |= QBYNDELAY;
36090792Sgshapiro							delay_return = true;
36190792Sgshapiro						}
36290792Sgshapiro						if (bitset(QPINGONDELAY,
36390792Sgshapiro							   q->q_flags))
36490792Sgshapiro						{
36590792Sgshapiro							q->q_flags |= QDELAYED;
36690792Sgshapiro							delay_return = true;
36790792Sgshapiro						}
36890792Sgshapiro					}
36990792Sgshapiro				}
37090792Sgshapiro			}
37190792Sgshapiro			if (delay_return)
37290792Sgshapiro			{
37390792Sgshapiro				if (msg_timeout == MSG_WARN_BY)
37438032Speter				{
37590792Sgshapiro					(void) sm_snprintf(buf, sizeof buf,
37690792Sgshapiro						"Warning: Delivery time (%lds) exceeded",
37790792Sgshapiro						e->e_deliver_by);
37838032Speter				}
37990792Sgshapiro				else
38090792Sgshapiro					(void) sm_snprintf(buf, sizeof buf,
38190792Sgshapiro						"Warning: could not send message for past %s",
38290792Sgshapiro						pintvl(TimeOuts.to_q_warning[e->e_timeoutclass],
38390792Sgshapiro							false));
38490792Sgshapiro
38590792Sgshapiro				/* don't free, allocated from e_rpool */
38690792Sgshapiro				e->e_message = sm_rpool_strdup_x(e->e_rpool,
38790792Sgshapiro								 buf);
38890792Sgshapiro				message(buf);
38990792Sgshapiro				e->e_flags |= EF_WARNING;
39038032Speter			}
39190792Sgshapiro			if (msg_timeout == MSG_WARN_BY)
39290792Sgshapiro			{
39390792Sgshapiro				(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
39490792Sgshapiro					"Warning: Delivery time (%lds) exceeded\n",
39590792Sgshapiro					e->e_deliver_by);
39690792Sgshapiro			}
39790792Sgshapiro			else
39890792Sgshapiro				(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
39990792Sgshapiro					"Warning: message still undelivered after %s\n",
40090792Sgshapiro					pintvl(TimeOuts.to_q_warning[e->e_timeoutclass],
40190792Sgshapiro					     false));
40290792Sgshapiro			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
40390792Sgshapiro				      "Will keep trying until message is %s old\n",
40490792Sgshapiro				      pintvl(TimeOuts.to_q_return[e->e_timeoutclass],
40590792Sgshapiro					     false));
40638032Speter		}
40738032Speter	}
40838032Speter
40938032Speter	if (tTd(50, 2))
41090792Sgshapiro		sm_dprintf("failure_return=%d delay_return=%d success_return=%d queueit=%d\n",
41138032Speter			failure_return, delay_return, success_return, queueit);
41238032Speter
41338032Speter	/*
41438032Speter	**  If we had some fatal error, but no addresses are marked as
41538032Speter	**  bad, mark them _all_ as bad.
41638032Speter	*/
41738032Speter
41838032Speter	if (bitset(EF_FATALERRS, e->e_flags) && !failure_return)
41938032Speter	{
42038032Speter		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
42138032Speter		{
42264562Sgshapiro			if ((QS_IS_OK(q->q_state) ||
42364562Sgshapiro			     QS_IS_VERIFIED(q->q_state)) &&
42438032Speter			    bitset(QPINGONFAILURE, q->q_flags))
42538032Speter			{
42690792Sgshapiro				failure_return = true;
42764562Sgshapiro				q->q_state = QS_BADADDR;
42838032Speter			}
42938032Speter		}
43038032Speter	}
43138032Speter
43238032Speter	/*
43338032Speter	**  Send back return receipts as requested.
43438032Speter	*/
43538032Speter
43638032Speter	if (success_return && !failure_return && !delay_return && fulldrop &&
43738032Speter	    !bitset(PRIV_NORECEIPTS, PrivacyFlags) &&
43838032Speter	    strcmp(e->e_from.q_paddr, "<>") != 0)
43938032Speter	{
44038032Speter		auto ADDRESS *rlist = NULL;
44138032Speter
44238032Speter		if (tTd(50, 8))
44390792Sgshapiro			sm_dprintf("dropenvelope(%s): sending return receipt\n",
44464562Sgshapiro				id);
44538032Speter		e->e_flags |= EF_SENDRECEIPT;
44638032Speter		(void) sendtolist(e->e_from.q_paddr, NULLADDR, &rlist, 0, e);
44738032Speter		(void) returntosender("Return receipt", rlist, RTSF_NO_BODY, e);
44838032Speter	}
44938032Speter	e->e_flags &= ~EF_SENDRECEIPT;
45038032Speter
45138032Speter	/*
45238032Speter	**  Arrange to send error messages if there are fatal errors.
45338032Speter	*/
45438032Speter
45538032Speter	if ((failure_return || delay_return) && e->e_errormode != EM_QUIET)
45638032Speter	{
45738032Speter		if (tTd(50, 8))
45890792Sgshapiro			sm_dprintf("dropenvelope(%s): saving mail\n", id);
45990792Sgshapiro		panic = savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags));
46038032Speter	}
46138032Speter
46238032Speter	/*
46338032Speter	**  Arrange to send warning messages to postmaster as requested.
46438032Speter	*/
46538032Speter
46664562Sgshapiro	if ((failure_return || pmnotify) &&
46738032Speter	    PostMasterCopy != NULL &&
46864562Sgshapiro	    !bitset(EF_RESPONSE, e->e_flags) &&
46964562Sgshapiro	    e->e_class >= 0)
47038032Speter	{
47138032Speter		auto ADDRESS *rlist = NULL;
47264562Sgshapiro		char pcopy[MAXNAME];
47338032Speter
47464562Sgshapiro		if (failure_return)
47564562Sgshapiro		{
47664562Sgshapiro			expand(PostMasterCopy, pcopy, sizeof pcopy, e);
47764562Sgshapiro
47864562Sgshapiro			if (tTd(50, 8))
47990792Sgshapiro				sm_dprintf("dropenvelope(%s): sending postmaster copy to %s\n",
48064562Sgshapiro					id, pcopy);
48164562Sgshapiro			(void) sendtolist(pcopy, NULLADDR, &rlist, 0, e);
48264562Sgshapiro		}
48364562Sgshapiro		if (pmnotify)
48464562Sgshapiro			(void) sendtolist("postmaster", NULLADDR,
48564562Sgshapiro					  &rlist, 0, e);
48664562Sgshapiro		(void) returntosender(e->e_message, rlist,
48764562Sgshapiro				      RTSF_PM_BOUNCE|RTSF_NO_BODY, e);
48838032Speter	}
48938032Speter
49038032Speter	/*
49138032Speter	**  Instantiate or deinstantiate the queue.
49238032Speter	*/
49338032Speter
49438032Spetersimpledrop:
49538032Speter	if (tTd(50, 8))
49690792Sgshapiro		sm_dprintf("dropenvelope(%s): at simpledrop, queueit=%d\n",
49738032Speter			id, queueit);
49838032Speter	if (!queueit || bitset(EF_CLRQUEUE, e->e_flags))
49938032Speter	{
50038032Speter		if (tTd(50, 1))
50138032Speter		{
50290792Sgshapiro			sm_dprintf("\n===== Dropping queue files for %s... queueit=%d, e_flags=",
50338032Speter				e->e_id, queueit);
50438032Speter			printenvflags(e);
50538032Speter		}
50690792Sgshapiro		if (!panic)
50790792Sgshapiro			(void) xunlink(queuename(e, DATAFL_LETTER));
50890792Sgshapiro		if (panic && QueueMode == QM_LOST)
50990792Sgshapiro		{
51090792Sgshapiro			/*
51190792Sgshapiro			**  leave the Qf file behind as
51290792Sgshapiro			**  the delivery attempt failed.
51390792Sgshapiro			*/
51438032Speter
51590792Sgshapiro			/* EMPTY */
51690792Sgshapiro		}
51790792Sgshapiro		else
51890792Sgshapiro		if (xunlink(queuename(e, ANYQFL_LETTER)) == 0)
51990792Sgshapiro		{
52090792Sgshapiro			/* add to available space in filesystem */
52190792Sgshapiro			updfs(e, true, !panic);
52290792Sgshapiro		}
52390792Sgshapiro
52464562Sgshapiro		if (e->e_ntries > 0 && LogLevel > 9)
52564562Sgshapiro			sm_syslog(LOG_INFO, id, "done; delay=%s, ntries=%d",
52690792Sgshapiro				  pintvl(curtime() - e->e_ctime, true),
52764562Sgshapiro				  e->e_ntries);
52838032Speter	}
52938032Speter	else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
53038032Speter	{
53190792Sgshapiro		if (!split)
53290792Sgshapiro			queueup(e, false, true);
53390792Sgshapiro		else
53490792Sgshapiro		{
53590792Sgshapiro			ENVELOPE *oldsib;
53690792Sgshapiro			ENVELOPE *ee;
53790792Sgshapiro
53890792Sgshapiro			/*
53990792Sgshapiro			**  Save old sibling and set it to NULL to avoid
54090792Sgshapiro			**  queueing up the same envelopes again.
54190792Sgshapiro			**  This requires that envelopes in that list have
54290792Sgshapiro			**  been take care of before (or at some other place).
54390792Sgshapiro			*/
54490792Sgshapiro
54590792Sgshapiro			oldsib = e->e_sibling;
54690792Sgshapiro			e->e_sibling = NULL;
54790792Sgshapiro			if (!split_by_recipient(e) &&
54890792Sgshapiro			    bitset(EF_FATALERRS, e->e_flags))
54990792Sgshapiro			{
55090792Sgshapiro				syserr("!dropenvelope(%s): cannot commit data file %s, uid=%d",
55190792Sgshapiro					e->e_id, queuename(e, DATAFL_LETTER),
55298121Sgshapiro					(int) geteuid());
55390792Sgshapiro			}
55490792Sgshapiro			for (ee = e->e_sibling; ee != NULL; ee = ee->e_sibling)
55590792Sgshapiro				queueup(ee, false, true);
55690792Sgshapiro			queueup(e, false, true);
55790792Sgshapiro
55890792Sgshapiro			/* clean up */
55990792Sgshapiro			for (ee = e->e_sibling; ee != NULL; ee = ee->e_sibling)
56090792Sgshapiro			{
56190792Sgshapiro				/* now unlock the job */
56290792Sgshapiro				if (tTd(50, 8))
56390792Sgshapiro					sm_dprintf("dropenvelope(%s): unlocking job\n",
56490792Sgshapiro						   ee->e_id);
56590792Sgshapiro				closexscript(ee);
56690792Sgshapiro				unlockqueue(ee);
56790792Sgshapiro
56890792Sgshapiro				/* this envelope is marked unused */
56990792Sgshapiro				if (ee->e_dfp != NULL)
57090792Sgshapiro				{
57190792Sgshapiro					(void) sm_io_close(ee->e_dfp,
57290792Sgshapiro							   SM_TIME_DEFAULT);
57390792Sgshapiro					ee->e_dfp = NULL;
57490792Sgshapiro				}
57590792Sgshapiro				ee->e_id = NULL;
57690792Sgshapiro				ee->e_flags &= ~EF_HAS_DF;
57790792Sgshapiro			}
57890792Sgshapiro			e->e_sibling = oldsib;
57990792Sgshapiro		}
58038032Speter	}
58138032Speter
58238032Speter	/* now unlock the job */
58338032Speter	if (tTd(50, 8))
58490792Sgshapiro		sm_dprintf("dropenvelope(%s): unlocking job\n", id);
58538032Speter	closexscript(e);
58638032Speter	unlockqueue(e);
58738032Speter
58838032Speter	/* make sure that this envelope is marked unused */
58938032Speter	if (e->e_dfp != NULL)
59090792Sgshapiro	{
59190792Sgshapiro		(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
59290792Sgshapiro		e->e_dfp = NULL;
59390792Sgshapiro	}
59438032Speter	e->e_id = NULL;
59538032Speter	e->e_flags &= ~EF_HAS_DF;
59638032Speter}
59790792Sgshapiro/*
59838032Speter**  CLEARENVELOPE -- clear an envelope without unlocking
59938032Speter**
60038032Speter**	This is normally used by a child process to get a clean
60138032Speter**	envelope without disturbing the parent.
60238032Speter**
60338032Speter**	Parameters:
60438032Speter**		e -- the envelope to clear.
60538032Speter**		fullclear - if set, the current envelope is total
60638032Speter**			garbage and should be ignored; otherwise,
60738032Speter**			release any resources it may indicate.
60890792Sgshapiro**		rpool -- either NULL, or a pointer to a resource pool
60990792Sgshapiro**			from which envelope memory is allocated, and
61090792Sgshapiro**			to which envelope resources are attached.
61138032Speter**
61238032Speter**	Returns:
61338032Speter**		none.
61438032Speter**
61538032Speter**	Side Effects:
61638032Speter**		Closes files associated with the envelope.
61738032Speter**		Marks the envelope as unallocated.
61838032Speter*/
61938032Speter
62038032Spetervoid
62190792Sgshapiroclearenvelope(e, fullclear, rpool)
62238032Speter	register ENVELOPE *e;
62338032Speter	bool fullclear;
62490792Sgshapiro	SM_RPOOL_T *rpool;
62538032Speter{
62638032Speter	register HDR *bh;
62738032Speter	register HDR **nhp;
62838032Speter	extern ENVELOPE BlankEnvelope;
62990792Sgshapiro	char **p;
63038032Speter
63138032Speter	if (!fullclear)
63238032Speter	{
63338032Speter		/* clear out any file information */
63438032Speter		if (e->e_xfp != NULL)
63590792Sgshapiro			(void) sm_io_close(e->e_xfp, SM_TIME_DEFAULT);
63638032Speter		if (e->e_dfp != NULL)
63790792Sgshapiro			(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
63838032Speter		e->e_xfp = e->e_dfp = NULL;
63938032Speter	}
64038032Speter
64190792Sgshapiro	/*
64290792Sgshapiro	**  Copy BlankEnvelope into *e.
64390792Sgshapiro	**  It is not safe to simply copy pointers to strings;
64490792Sgshapiro	**  the strings themselves must be copied (or set to NULL).
64590792Sgshapiro	**  The problem is that when we assign a new string value to
64690792Sgshapiro	**  a member of BlankEnvelope, we free the old string.
64790792Sgshapiro	**  We did not need to do this copying in sendmail 8.11 :-(
64890792Sgshapiro	**  and it is a potential performance hit.  Reference counted
64990792Sgshapiro	**  strings are one way out.
65090792Sgshapiro	*/
65190792Sgshapiro
65290792Sgshapiro	*e = BlankEnvelope;
65338032Speter	e->e_message = NULL;
65490792Sgshapiro	e->e_qfletter = '\0';
65590792Sgshapiro	e->e_quarmsg = NULL;
65690792Sgshapiro	macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), "");
65790792Sgshapiro
65890792Sgshapiro	/*
65990792Sgshapiro	**  Copy the macro table.
66090792Sgshapiro	**  We might be able to avoid this by zeroing the macro table
66190792Sgshapiro	**  and always searching BlankEnvelope.e_macro after e->e_macro
66290792Sgshapiro	**  in macvalue().
66390792Sgshapiro	*/
66490792Sgshapiro
66590792Sgshapiro	for (p = &e->e_macro.mac_table[0];
66690792Sgshapiro	     p <= &e->e_macro.mac_table[MAXMACROID];
66790792Sgshapiro	     ++p)
66890792Sgshapiro	{
66990792Sgshapiro		if (*p != NULL)
67090792Sgshapiro			*p = sm_rpool_strdup_x(rpool, *p);
67190792Sgshapiro	}
67290792Sgshapiro
67390792Sgshapiro	/*
67490792Sgshapiro	**  XXX There are many strings in the envelope structure
67590792Sgshapiro	**  XXX that we are not attempting to copy here.
67690792Sgshapiro	**  XXX Investigate this further.
67790792Sgshapiro	*/
67890792Sgshapiro
67990792Sgshapiro	e->e_rpool = rpool;
68090792Sgshapiro	e->e_macro.mac_rpool = rpool;
68138032Speter	if (Verbose)
68264562Sgshapiro		set_delivery_mode(SM_DELIVER, e);
68338032Speter	bh = BlankEnvelope.e_header;
68438032Speter	nhp = &e->e_header;
68538032Speter	while (bh != NULL)
68638032Speter	{
68790792Sgshapiro		*nhp = (HDR *) sm_rpool_malloc_x(rpool, sizeof *bh);
68864562Sgshapiro		memmove((char *) *nhp, (char *) bh, sizeof *bh);
68938032Speter		bh = bh->h_link;
69038032Speter		nhp = &(*nhp)->h_link;
69138032Speter	}
69238032Speter}
69390792Sgshapiro/*
69438032Speter**  INITSYS -- initialize instantiation of system
69538032Speter**
69638032Speter**	In Daemon mode, this is done in the child.
69738032Speter**
69838032Speter**	Parameters:
69964562Sgshapiro**		e -- the envelope to use.
70038032Speter**
70138032Speter**	Returns:
70238032Speter**		none.
70338032Speter**
70438032Speter**	Side Effects:
70538032Speter**		Initializes the system macros, some global variables,
70638032Speter**		etc.  In particular, the current time in various
70738032Speter**		forms is set.
70838032Speter*/
70938032Speter
71038032Spetervoid
71138032Speterinitsys(e)
71238032Speter	register ENVELOPE *e;
71338032Speter{
71490792Sgshapiro	char buf[10];
71538032Speter#ifdef TTYNAME
71638032Speter	static char ybuf[60];			/* holds tty id */
71738032Speter	register char *p;
71838032Speter	extern char *ttyname();
71938032Speter#endif /* TTYNAME */
72038032Speter
72138032Speter	/*
72238032Speter	**  Give this envelope a reality.
72338032Speter	**	I.e., an id, a transcript, and a creation time.
72490792Sgshapiro	**  We don't select the queue until all of the recipients are known.
72538032Speter	*/
72638032Speter
72738032Speter	openxscript(e);
72838032Speter	e->e_ctime = curtime();
72990792Sgshapiro	e->e_qfletter = '\0';
73038032Speter
73138032Speter	/*
73238032Speter	**  Set OutChannel to something useful if stdout isn't it.
73338032Speter	**	This arranges that any extra stuff the mailer produces
73438032Speter	**	gets sent back to the user on error (because it is
73538032Speter	**	tucked away in the transcript).
73638032Speter	*/
73738032Speter
73838032Speter	if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) &&
73938032Speter	    e->e_xfp != NULL)
74038032Speter		OutChannel = e->e_xfp;
74138032Speter
74238032Speter	/*
74338032Speter	**  Set up some basic system macros.
74438032Speter	*/
74538032Speter
74638032Speter	/* process id */
74790792Sgshapiro	(void) sm_snprintf(buf, sizeof buf, "%d", (int) CurrentPid);
74890792Sgshapiro	macdefine(&e->e_macro, A_TEMP, 'p', buf);
74938032Speter
75038032Speter	/* hop count */
75190792Sgshapiro	(void) sm_snprintf(buf, sizeof buf, "%d", e->e_hopcount);
75290792Sgshapiro	macdefine(&e->e_macro, A_TEMP, 'c', buf);
75338032Speter
75438032Speter	/* time as integer, unix time, arpa time */
75538032Speter	settime(e);
75638032Speter
75764562Sgshapiro	/* Load average */
75890792Sgshapiro	sm_getla();
75964562Sgshapiro
76038032Speter#ifdef TTYNAME
76138032Speter	/* tty name */
76238032Speter	if (macvalue('y', e) == NULL)
76338032Speter	{
76438032Speter		p = ttyname(2);
76538032Speter		if (p != NULL)
76638032Speter		{
76738032Speter			if (strrchr(p, '/') != NULL)
76838032Speter				p = strrchr(p, '/') + 1;
76990792Sgshapiro			(void) sm_strlcpy(ybuf, sizeof ybuf, p);
77090792Sgshapiro			macdefine(&e->e_macro, A_PERM, 'y', ybuf);
77138032Speter		}
77238032Speter	}
77338032Speter#endif /* TTYNAME */
77438032Speter}
77590792Sgshapiro/*
77638032Speter**  SETTIME -- set the current time.
77738032Speter**
77838032Speter**	Parameters:
77964562Sgshapiro**		e -- the envelope in which the macros should be set.
78038032Speter**
78138032Speter**	Returns:
78238032Speter**		none.
78338032Speter**
78438032Speter**	Side Effects:
78538032Speter**		Sets the various time macros -- $a, $b, $d, $t.
78638032Speter*/
78738032Speter
78838032Spetervoid
78938032Spetersettime(e)
79038032Speter	register ENVELOPE *e;
79138032Speter{
79238032Speter	register char *p;
79338032Speter	auto time_t now;
79490792Sgshapiro	char buf[30];
79538032Speter	register struct tm *tm;
79638032Speter
79738032Speter	now = curtime();
798132943Sgshapiro	(void) sm_snprintf(buf, sizeof buf, "%ld", (long) now);
799132943Sgshapiro	macdefine(&e->e_macro, A_TEMP, macid("{time}"), buf);
80038032Speter	tm = gmtime(&now);
80190792Sgshapiro	(void) sm_snprintf(buf, sizeof buf, "%04d%02d%02d%02d%02d",
80290792Sgshapiro			   tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
80390792Sgshapiro			   tm->tm_hour, tm->tm_min);
80490792Sgshapiro	macdefine(&e->e_macro, A_TEMP, 't', buf);
80590792Sgshapiro	(void) sm_strlcpy(buf, ctime(&now), sizeof buf);
80690792Sgshapiro	p = strchr(buf, '\n');
80738032Speter	if (p != NULL)
80838032Speter		*p = '\0';
80990792Sgshapiro	macdefine(&e->e_macro, A_TEMP, 'd', buf);
81090792Sgshapiro	macdefine(&e->e_macro, A_TEMP, 'b', arpadate(buf));
81138032Speter	if (macvalue('a', e) == NULL)
81290792Sgshapiro		macdefine(&e->e_macro, A_PERM, 'a', macvalue('b', e));
81338032Speter}
81490792Sgshapiro/*
81538032Speter**  OPENXSCRIPT -- Open transcript file
81638032Speter**
81738032Speter**	Creates a transcript file for possible eventual mailing or
81838032Speter**	sending back.
81938032Speter**
82038032Speter**	Parameters:
82138032Speter**		e -- the envelope to create the transcript in/for.
82238032Speter**
82338032Speter**	Returns:
82438032Speter**		none
82538032Speter**
82638032Speter**	Side Effects:
82738032Speter**		Creates the transcript file.
82838032Speter*/
82938032Speter
83038032Speter#ifndef O_APPEND
83164562Sgshapiro# define O_APPEND	0
83264562Sgshapiro#endif /* ! O_APPEND */
83338032Speter
83438032Spetervoid
83538032Speteropenxscript(e)
83638032Speter	register ENVELOPE *e;
83738032Speter{
83838032Speter	register char *p;
83938032Speter
84038032Speter	if (e->e_xfp != NULL)
84138032Speter		return;
84264562Sgshapiro
84364562Sgshapiro#if 0
84464562Sgshapiro	if (e->e_lockfp == NULL && bitset(EF_INQUEUE, e->e_flags))
84564562Sgshapiro		syserr("openxscript: job not locked");
84664562Sgshapiro#endif /* 0 */
84764562Sgshapiro
84890792Sgshapiro	p = queuename(e, XSCRPT_LETTER);
84964562Sgshapiro	e->e_xfp = bfopen(p, FileMode, XscriptFileBufferSize,
85064562Sgshapiro			  SFF_NOTEXCL|SFF_OPENASROOT);
85164562Sgshapiro
85264562Sgshapiro	if (e->e_xfp == NULL)
85338032Speter	{
85438032Speter		syserr("Can't create transcript file %s", p);
85590792Sgshapiro		e->e_xfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT,
85690792Sgshapiro				      SM_PATH_DEVNULL, SM_IO_RDWR, NULL);
85764562Sgshapiro		if (e->e_xfp == NULL)
85890792Sgshapiro			syserr("!Can't open %s", SM_PATH_DEVNULL);
85938032Speter	}
86090792Sgshapiro	(void) sm_io_setvbuf(e->e_xfp, SM_TIME_DEFAULT, NULL, SM_IO_LBF, 0);
86138032Speter	if (tTd(46, 9))
86238032Speter	{
86390792Sgshapiro		sm_dprintf("openxscript(%s):\n  ", p);
86490792Sgshapiro		dumpfd(sm_io_getinfo(e->e_xfp, SM_IO_WHAT_FD, NULL), true,
86590792Sgshapiro		       false);
86638032Speter	}
86738032Speter}
86890792Sgshapiro/*
86938032Speter**  CLOSEXSCRIPT -- close the transcript file.
87038032Speter**
87138032Speter**	Parameters:
87238032Speter**		e -- the envelope containing the transcript to close.
87338032Speter**
87438032Speter**	Returns:
87538032Speter**		none.
87638032Speter**
87738032Speter**	Side Effects:
87838032Speter**		none.
87938032Speter*/
88038032Speter
88138032Spetervoid
88238032Speterclosexscript(e)
88338032Speter	register ENVELOPE *e;
88438032Speter{
88538032Speter	if (e->e_xfp == NULL)
88638032Speter		return;
88764562Sgshapiro#if 0
88864562Sgshapiro	if (e->e_lockfp == NULL)
88964562Sgshapiro		syserr("closexscript: job not locked");
89064562Sgshapiro#endif /* 0 */
89190792Sgshapiro	(void) sm_io_close(e->e_xfp, SM_TIME_DEFAULT);
89238032Speter	e->e_xfp = NULL;
89338032Speter}
89490792Sgshapiro/*
89538032Speter**  SETSENDER -- set the person who this message is from
89638032Speter**
89738032Speter**	Under certain circumstances allow the user to say who
89838032Speter**	s/he is (using -f or -r).  These are:
89938032Speter**	1.  The user's uid is zero (root).
90038032Speter**	2.  The user's login name is in an approved list (typically
90138032Speter**	    from a network server).
90238032Speter**	3.  The address the user is trying to claim has a
90338032Speter**	    "!" character in it (since #2 doesn't do it for
90438032Speter**	    us if we are dialing out for UUCP).
90538032Speter**	A better check to replace #3 would be if the
90638032Speter**	effective uid is "UUCP" -- this would require me
90738032Speter**	to rewrite getpwent to "grab" uucp as it went by,
90838032Speter**	make getname more nasty, do another passwd file
90938032Speter**	scan, or compile the UID of "UUCP" into the code,
91038032Speter**	all of which are reprehensible.
91138032Speter**
91238032Speter**	Assuming all of these fail, we figure out something
91338032Speter**	ourselves.
91438032Speter**
91538032Speter**	Parameters:
91638032Speter**		from -- the person we would like to believe this message
91738032Speter**			is from, as specified on the command line.
91838032Speter**		e -- the envelope in which we would like the sender set.
91938032Speter**		delimptr -- if non-NULL, set to the location of the
92038032Speter**			trailing delimiter.
92138032Speter**		delimchar -- the character that will delimit the sender
92238032Speter**			address.
92338032Speter**		internal -- set if this address is coming from an internal
92438032Speter**			source such as an owner alias.
92538032Speter**
92638032Speter**	Returns:
92738032Speter**		none.
92838032Speter**
92938032Speter**	Side Effects:
93038032Speter**		sets sendmail's notion of who the from person is.
93138032Speter*/
93238032Speter
93338032Spetervoid
93438032Spetersetsender(from, e, delimptr, delimchar, internal)
93538032Speter	char *from;
93638032Speter	register ENVELOPE *e;
93738032Speter	char **delimptr;
93838032Speter	int delimchar;
93938032Speter	bool internal;
94038032Speter{
94138032Speter	register char **pvp;
94238032Speter	char *realname = NULL;
94338032Speter	char *bp;
94438032Speter	char buf[MAXNAME + 2];
94538032Speter	char pvpbuf[PSBUFSIZE];
94638032Speter	extern char *FullName;
94738032Speter
94838032Speter	if (tTd(45, 1))
94990792Sgshapiro		sm_dprintf("setsender(%s)\n", from == NULL ? "" : from);
95038032Speter
951110560Sgshapiro	/* may be set from earlier calls */
952110560Sgshapiro	macdefine(&e->e_macro, A_PERM, 'x', "");
953110560Sgshapiro
95438032Speter	/*
95538032Speter	**  Figure out the real user executing us.
95638032Speter	**	Username can return errno != 0 on non-errors.
95738032Speter	*/
95838032Speter
95938032Speter	if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP ||
96038032Speter	    OpMode == MD_ARPAFTP || OpMode == MD_DAEMON)
96138032Speter		realname = from;
96238032Speter	if (realname == NULL || realname[0] == '\0')
96338032Speter		realname = username();
96438032Speter
96538032Speter	if (ConfigLevel < 2)
96690792Sgshapiro		SuprErrs = true;
96738032Speter
96890792Sgshapiro	macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e s");
96990792Sgshapiro
97064562Sgshapiro	/* preset state for then clause in case from == NULL */
97164562Sgshapiro	e->e_from.q_state = QS_BADADDR;
97264562Sgshapiro	e->e_from.q_flags = 0;
97338032Speter	if (from == NULL ||
97438032Speter	    parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR,
97590792Sgshapiro		      delimchar, delimptr, e, false) == NULL ||
97664562Sgshapiro	    QS_IS_BADADDR(e->e_from.q_state) ||
97738032Speter	    e->e_from.q_mailer == ProgMailer ||
97838032Speter	    e->e_from.q_mailer == FileMailer ||
97938032Speter	    e->e_from.q_mailer == InclMailer)
98038032Speter	{
98138032Speter		/* log garbage addresses for traceback */
98238032Speter		if (from != NULL && LogLevel > 2)
98338032Speter		{
98438032Speter			char *p;
98538032Speter			char ebuf[MAXNAME * 2 + 2];
98638032Speter
98738032Speter			p = macvalue('_', e);
98838032Speter			if (p == NULL)
98938032Speter			{
99038032Speter				char *host = RealHostName;
99138032Speter
99238032Speter				if (host == NULL)
99338032Speter					host = MyHostName;
99490792Sgshapiro				(void) sm_snprintf(ebuf, sizeof ebuf,
99590792Sgshapiro						   "%.*s@%.*s", MAXNAME,
99690792Sgshapiro						   realname, MAXNAME, host);
99738032Speter				p = ebuf;
99838032Speter			}
99938032Speter			sm_syslog(LOG_NOTICE, e->e_id,
100064562Sgshapiro				  "setsender: %s: invalid or unparsable, received from %s",
100164562Sgshapiro				  shortenstring(from, 83), p);
100238032Speter		}
100338032Speter		if (from != NULL)
100438032Speter		{
100564562Sgshapiro			if (!QS_IS_BADADDR(e->e_from.q_state))
100638032Speter			{
100738032Speter				/* it was a bogus mailer in the from addr */
100838032Speter				e->e_status = "5.1.7";
100964562Sgshapiro				usrerrenh(e->e_status,
101064562Sgshapiro					  "553 Invalid sender address");
101138032Speter			}
101290792Sgshapiro			SuprErrs = true;
101338032Speter		}
101438032Speter		if (from == realname ||
101590792Sgshapiro		    parseaddr(from = realname,
101690792Sgshapiro			      &e->e_from, RF_COPYALL|RF_SENDERADDR, ' ',
101790792Sgshapiro			      NULL, e, false) == NULL)
101838032Speter		{
101938032Speter			char nbuf[100];
102038032Speter
102190792Sgshapiro			SuprErrs = true;
102238032Speter			expand("\201n", nbuf, sizeof nbuf, e);
102390792Sgshapiro			from = sm_rpool_strdup_x(e->e_rpool, nbuf);
102490792Sgshapiro			if (parseaddr(from, &e->e_from, RF_COPYALL, ' ',
102590792Sgshapiro				      NULL, e, false) == NULL &&
102638032Speter			    parseaddr(from = "postmaster", &e->e_from,
102790792Sgshapiro				      RF_COPYALL, ' ', NULL, e, false) == NULL)
102864562Sgshapiro				syserr("553 5.3.0 setsender: can't even parse postmaster!");
102938032Speter		}
103038032Speter	}
103138032Speter	else
103290792Sgshapiro		FromFlag = true;
103364562Sgshapiro	e->e_from.q_state = QS_SENDER;
103438032Speter	if (tTd(45, 5))
103538032Speter	{
103690792Sgshapiro		sm_dprintf("setsender: QS_SENDER ");
1037132943Sgshapiro		printaddr(sm_debug_file(), &e->e_from, false);
103838032Speter	}
103990792Sgshapiro	SuprErrs = false;
104038032Speter
104164562Sgshapiro#if USERDB
104238032Speter	if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags))
104338032Speter	{
104438032Speter		register char *p;
104538032Speter
104690792Sgshapiro		p = udbsender(e->e_from.q_user, e->e_rpool);
104738032Speter		if (p != NULL)
104838032Speter			from = p;
104938032Speter	}
105064562Sgshapiro#endif /* USERDB */
105138032Speter
105238032Speter	if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags))
105338032Speter	{
105490792Sgshapiro		SM_MBDB_T user;
105590792Sgshapiro
105638032Speter		if (!internal)
105738032Speter		{
105838032Speter			/* if the user already given fullname don't redefine */
105938032Speter			if (FullName == NULL)
106038032Speter				FullName = macvalue('x', e);
106194334Sgshapiro			if (FullName != NULL)
106294334Sgshapiro			{
106394334Sgshapiro				if (FullName[0] == '\0')
106494334Sgshapiro					FullName = NULL;
106594334Sgshapiro				else
106694334Sgshapiro					FullName = newstr(FullName);
106794334Sgshapiro			}
106838032Speter		}
106938032Speter
107038032Speter		if (e->e_from.q_user[0] != '\0' &&
107190792Sgshapiro		    sm_mbdb_lookup(e->e_from.q_user, &user) == EX_OK)
107238032Speter		{
107338032Speter			/*
107438032Speter			**  Process passwd file entry.
107538032Speter			*/
107638032Speter
107738032Speter			/* extract home directory */
107890792Sgshapiro			if (*user.mbdb_homedir == '\0')
107966494Sgshapiro				e->e_from.q_home = NULL;
108090792Sgshapiro			else if (strcmp(user.mbdb_homedir, "/") == 0)
108190792Sgshapiro				e->e_from.q_home = "";
108238032Speter			else
108390792Sgshapiro				e->e_from.q_home = sm_rpool_strdup_x(e->e_rpool,
108490792Sgshapiro							user.mbdb_homedir);
108590792Sgshapiro			macdefine(&e->e_macro, A_PERM, 'z', e->e_from.q_home);
108638032Speter
108738032Speter			/* extract user and group id */
108890792Sgshapiro			if (user.mbdb_uid != SM_NO_UID)
108990792Sgshapiro			{
109090792Sgshapiro				e->e_from.q_uid = user.mbdb_uid;
109190792Sgshapiro				e->e_from.q_gid = user.mbdb_gid;
109290792Sgshapiro				e->e_from.q_flags |= QGOODUID;
109390792Sgshapiro			}
109438032Speter
109538032Speter			/* extract full name from passwd file */
109690792Sgshapiro			if (FullName == NULL && !internal &&
109790792Sgshapiro			    user.mbdb_fullname[0] != '\0' &&
109890792Sgshapiro			    strcmp(user.mbdb_name, e->e_from.q_user) == 0)
109938032Speter			{
110090792Sgshapiro				FullName = newstr(user.mbdb_fullname);
110138032Speter			}
110238032Speter		}
110338032Speter		else
110438032Speter		{
110564562Sgshapiro			e->e_from.q_home = NULL;
110638032Speter		}
110738032Speter		if (FullName != NULL && !internal)
1108110560Sgshapiro			macdefine(&e->e_macro, A_TEMP, 'x', FullName);
110938032Speter	}
111043730Speter	else if (!internal && OpMode != MD_DAEMON && OpMode != MD_SMTP)
111138032Speter	{
111238032Speter		if (e->e_from.q_home == NULL)
111338032Speter		{
111438032Speter			e->e_from.q_home = getenv("HOME");
111566494Sgshapiro			if (e->e_from.q_home != NULL)
111666494Sgshapiro			{
111766494Sgshapiro				if (*e->e_from.q_home == '\0')
111866494Sgshapiro					e->e_from.q_home = NULL;
111966494Sgshapiro				else if (strcmp(e->e_from.q_home, "/") == 0)
112066494Sgshapiro					e->e_from.q_home++;
112166494Sgshapiro			}
112238032Speter		}
112338032Speter		e->e_from.q_uid = RealUid;
112438032Speter		e->e_from.q_gid = RealGid;
112538032Speter		e->e_from.q_flags |= QGOODUID;
112638032Speter	}
112738032Speter
112838032Speter	/*
112938032Speter	**  Rewrite the from person to dispose of possible implicit
113038032Speter	**	links in the net.
113138032Speter	*/
113238032Speter
1133132943Sgshapiro	pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL, NULL, false);
113438032Speter	if (pvp == NULL)
113538032Speter	{
113638032Speter		/* don't need to give error -- prescan did that already */
113738032Speter		if (LogLevel > 2)
113838032Speter			sm_syslog(LOG_NOTICE, e->e_id,
113964562Sgshapiro				  "cannot prescan from (%s)",
114064562Sgshapiro				  shortenstring(from, MAXSHORTSTR));
114190792Sgshapiro		finis(true, true, ExitStat);
114238032Speter	}
114390792Sgshapiro	(void) REWRITE(pvp, 3, e);
114490792Sgshapiro	(void) REWRITE(pvp, 1, e);
114590792Sgshapiro	(void) REWRITE(pvp, 4, e);
114690792Sgshapiro	macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL);
114738032Speter	bp = buf + 1;
114838032Speter	cataddr(pvp, NULL, bp, sizeof buf - 2, '\0');
114938032Speter	if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags))
115038032Speter	{
115138032Speter		/* heuristic: route-addr: add angle brackets */
115290792Sgshapiro		(void) sm_strlcat(bp, ">", sizeof buf - 1);
115338032Speter		*--bp = '<';
115438032Speter	}
115590792Sgshapiro	e->e_sender = sm_rpool_strdup_x(e->e_rpool, bp);
115690792Sgshapiro	macdefine(&e->e_macro, A_PERM, 'f', e->e_sender);
115738032Speter
115838032Speter	/* save the domain spec if this mailer wants it */
115938032Speter	if (e->e_from.q_mailer != NULL &&
116038032Speter	    bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags))
116138032Speter	{
116238032Speter		char **lastat;
116338032Speter
116438032Speter		/* get rid of any pesky angle brackets */
116590792Sgshapiro		macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e s");
116690792Sgshapiro		(void) REWRITE(pvp, 3, e);
116790792Sgshapiro		(void) REWRITE(pvp, 1, e);
116890792Sgshapiro		(void) REWRITE(pvp, 4, e);
116990792Sgshapiro		macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL);
117038032Speter
117138032Speter		/* strip off to the last "@" sign */
117238032Speter		for (lastat = NULL; *pvp != NULL; pvp++)
1173132943Sgshapiro		{
117438032Speter			if (strcmp(*pvp, "@") == 0)
117538032Speter				lastat = pvp;
1176132943Sgshapiro		}
117738032Speter		if (lastat != NULL)
117838032Speter		{
117990792Sgshapiro			e->e_fromdomain = copyplist(lastat, true, e->e_rpool);
118038032Speter			if (tTd(45, 3))
118138032Speter			{
118290792Sgshapiro				sm_dprintf("Saving from domain: ");
1183132943Sgshapiro				printav(sm_debug_file(), e->e_fromdomain);
118438032Speter			}
118538032Speter		}
118638032Speter	}
118738032Speter}
118890792Sgshapiro/*
118938032Speter**  PRINTENVFLAGS -- print envelope flags for debugging
119038032Speter**
119138032Speter**	Parameters:
119238032Speter**		e -- the envelope with the flags to be printed.
119338032Speter**
119438032Speter**	Returns:
119538032Speter**		none.
119638032Speter*/
119738032Speter
119838032Speterstruct eflags
119938032Speter{
120090792Sgshapiro	char		*ef_name;
120190792Sgshapiro	unsigned long	ef_bit;
120238032Speter};
120338032Speter
120464562Sgshapirostatic struct eflags	EnvelopeFlags[] =
120538032Speter{
120638032Speter	{ "OLDSTYLE",		EF_OLDSTYLE	},
120738032Speter	{ "INQUEUE",		EF_INQUEUE	},
120838032Speter	{ "NO_BODY_RETN",	EF_NO_BODY_RETN	},
120938032Speter	{ "CLRQUEUE",		EF_CLRQUEUE	},
121038032Speter	{ "SENDRECEIPT",	EF_SENDRECEIPT	},
121138032Speter	{ "FATALERRS",		EF_FATALERRS	},
121238032Speter	{ "DELETE_BCC",		EF_DELETE_BCC	},
121338032Speter	{ "RESPONSE",		EF_RESPONSE	},
121438032Speter	{ "RESENT",		EF_RESENT	},
121538032Speter	{ "VRFYONLY",		EF_VRFYONLY	},
121638032Speter	{ "WARNING",		EF_WARNING	},
121738032Speter	{ "QUEUERUN",		EF_QUEUERUN	},
121838032Speter	{ "GLOBALERRS",		EF_GLOBALERRS	},
121938032Speter	{ "PM_NOTIFY",		EF_PM_NOTIFY	},
122038032Speter	{ "METOO",		EF_METOO	},
122138032Speter	{ "LOGSENDER",		EF_LOGSENDER	},
122238032Speter	{ "NORECEIPT",		EF_NORECEIPT	},
122338032Speter	{ "HAS8BIT",		EF_HAS8BIT	},
122438032Speter	{ "NL_NOT_EOL",		EF_NL_NOT_EOL	},
122538032Speter	{ "CRLF_NOT_EOL",	EF_CRLF_NOT_EOL	},
122638032Speter	{ "RET_PARAM",		EF_RET_PARAM	},
122738032Speter	{ "HAS_DF",		EF_HAS_DF	},
122838032Speter	{ "IS_MIME",		EF_IS_MIME	},
122938032Speter	{ "DONT_MIME",		EF_DONT_MIME	},
123090792Sgshapiro	{ "DISCARD",		EF_DISCARD	},
123190792Sgshapiro	{ "TOOBIG",		EF_TOOBIG	},
123290792Sgshapiro	{ "SPLIT",		EF_SPLIT	},
123390792Sgshapiro	{ "UNSAFE",		EF_UNSAFE	},
123471345Sgshapiro	{ NULL,			0		}
123538032Speter};
123638032Speter
123738032Spetervoid
123838032Speterprintenvflags(e)
123938032Speter	register ENVELOPE *e;
124038032Speter{
124138032Speter	register struct eflags *ef;
124290792Sgshapiro	bool first = true;
124338032Speter
1244132943Sgshapiro	sm_dprintf("%lx", e->e_flags);
124538032Speter	for (ef = EnvelopeFlags; ef->ef_name != NULL; ef++)
124638032Speter	{
124738032Speter		if (!bitset(ef->ef_bit, e->e_flags))
124838032Speter			continue;
124938032Speter		if (first)
1250132943Sgshapiro			sm_dprintf("<%s", ef->ef_name);
125138032Speter		else
1252132943Sgshapiro			sm_dprintf(",%s", ef->ef_name);
125390792Sgshapiro		first = false;
125438032Speter	}
125538032Speter	if (!first)
1256132943Sgshapiro		sm_dprintf(">\n");
125738032Speter}
1258