srvrsmtp.c revision 111823
1/*
2 * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
3 *	All rights reserved.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5 * Copyright (c) 1988, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
11 *
12 */
13
14#include <sendmail.h>
15#if MILTER
16# include <libmilter/mfdef.h>
17#endif /* MILTER */
18
19SM_RCSID("@(#)$Id: srvrsmtp.c,v 8.829.2.21 2003/01/15 19:17:14 ca Exp $")
20
21#if SASL || STARTTLS
22# include <sys/time.h>
23# include "sfsasl.h"
24#endif /* SASL || STARTTLS */
25#if SASL
26# define ENC64LEN(l)	(((l) + 2) * 4 / 3 + 1)
27static int saslmechs __P((sasl_conn_t *, char **));
28#endif /* SASL */
29#if STARTTLS
30# include <sysexits.h>
31
32static SSL_CTX	*srv_ctx = NULL;	/* TLS server context */
33static SSL	*srv_ssl = NULL;	/* per connection context */
34
35static bool	tls_ok_srv = false;
36
37extern void	tls_set_verify __P((SSL_CTX *, SSL *, bool));
38# define TLS_VERIFY_CLIENT() tls_set_verify(srv_ctx, srv_ssl, \
39				bitset(SRV_VRFY_CLT, features))
40#endif /* STARTTLS */
41
42/* server features */
43#define SRV_NONE	0x0000	/* none... */
44#define SRV_OFFER_TLS	0x0001	/* offer STARTTLS */
45#define SRV_VRFY_CLT	0x0002	/* request a cert */
46#define SRV_OFFER_AUTH	0x0004	/* offer AUTH */
47#define SRV_OFFER_ETRN	0x0008	/* offer ETRN */
48#define SRV_OFFER_VRFY	0x0010	/* offer VRFY (not yet used) */
49#define SRV_OFFER_EXPN	0x0020	/* offer EXPN */
50#define SRV_OFFER_VERB	0x0040	/* offer VERB */
51#define SRV_OFFER_DSN	0x0080	/* offer DSN */
52#if PIPELINING
53# define SRV_OFFER_PIPE	0x0100	/* offer PIPELINING */
54# if _FFR_NO_PIPE
55#  define SRV_NO_PIPE	0x0200	/* disable PIPELINING, sleep if used */
56# endif /* _FFR_NO_PIPE */
57#endif /* PIPELINING */
58#define SRV_REQ_AUTH	0x0400	/* require AUTH */
59#define SRV_TMP_FAIL	0x1000	/* ruleset caused a temporary failure */
60
61static unsigned int	srvfeatures __P((ENVELOPE *, char *, unsigned int));
62
63static time_t	checksmtpattack __P((volatile unsigned int *, int, bool,
64				     char *, ENVELOPE *));
65static void	mail_esmtp_args __P((char *, char *, ENVELOPE *));
66static void	printvrfyaddr __P((ADDRESS *, bool, bool));
67static void	rcpt_esmtp_args __P((ADDRESS *, char *, char *, ENVELOPE *));
68static char	*skipword __P((char *volatile, char *));
69static void	setup_smtpd_io __P((void));
70extern ENVELOPE	BlankEnvelope;
71
72#define SKIP_SPACE(s)	while (isascii(*s) && isspace(*s))	\
73				(s)++
74
75/*
76**  SMTP -- run the SMTP protocol.
77**
78**	Parameters:
79**		nullserver -- if non-NULL, rejection message for
80**			(almost) all SMTP commands.
81**		d_flags -- daemon flags
82**		e -- the envelope.
83**
84**	Returns:
85**		never.
86**
87**	Side Effects:
88**		Reads commands from the input channel and processes them.
89*/
90
91/*
92**  Notice: The smtp server doesn't have a session context like the client
93**	side has (mci). Therefore some data (session oriented) is allocated
94**	or assigned to the "wrong" structure (esp. STARTTLS, AUTH).
95**	This should be fixed in a successor version.
96*/
97
98struct cmd
99{
100	char	*cmd_name;	/* command name */
101	int	cmd_code;	/* internal code, see below */
102};
103
104/* values for cmd_code */
105#define CMDERROR	0	/* bad command */
106#define CMDMAIL	1	/* mail -- designate sender */
107#define CMDRCPT	2	/* rcpt -- designate recipient */
108#define CMDDATA	3	/* data -- send message text */
109#define CMDRSET	4	/* rset -- reset state */
110#define CMDVRFY	5	/* vrfy -- verify address */
111#define CMDEXPN	6	/* expn -- expand address */
112#define CMDNOOP	7	/* noop -- do nothing */
113#define CMDQUIT	8	/* quit -- close connection and die */
114#define CMDHELO	9	/* helo -- be polite */
115#define CMDHELP	10	/* help -- give usage info */
116#define CMDEHLO	11	/* ehlo -- extended helo (RFC 1425) */
117#define CMDETRN	12	/* etrn -- flush queue */
118#if SASL
119# define CMDAUTH	13	/* auth -- SASL authenticate */
120#endif /* SASL */
121#if STARTTLS
122# define CMDSTLS	14	/* STARTTLS -- start TLS session */
123#endif /* STARTTLS */
124/* non-standard commands */
125#define CMDVERB	17	/* verb -- go into verbose mode */
126/* unimplemented commands from RFC 821 */
127#define CMDUNIMPL	19	/* unimplemented rfc821 commands */
128/* use this to catch and log "door handle" attempts on your system */
129#define CMDLOGBOGUS	23	/* bogus command that should be logged */
130/* debugging-only commands, only enabled if SMTPDEBUG is defined */
131#define CMDDBGQSHOW	24	/* showq -- show send queue */
132#define CMDDBGDEBUG	25	/* debug -- set debug mode */
133
134/*
135**  Note: If you change this list, remember to update 'helpfile'
136*/
137
138static struct cmd	CmdTab[] =
139{
140	{ "mail",	CMDMAIL		},
141	{ "rcpt",	CMDRCPT		},
142	{ "data",	CMDDATA		},
143	{ "rset",	CMDRSET		},
144	{ "vrfy",	CMDVRFY		},
145	{ "expn",	CMDEXPN		},
146	{ "help",	CMDHELP		},
147	{ "noop",	CMDNOOP		},
148	{ "quit",	CMDQUIT		},
149	{ "helo",	CMDHELO		},
150	{ "ehlo",	CMDEHLO		},
151	{ "etrn",	CMDETRN		},
152	{ "verb",	CMDVERB		},
153	{ "send",	CMDUNIMPL	},
154	{ "saml",	CMDUNIMPL	},
155	{ "soml",	CMDUNIMPL	},
156	{ "turn",	CMDUNIMPL	},
157#if SASL
158	{ "auth",	CMDAUTH,	},
159#endif /* SASL */
160#if STARTTLS
161	{ "starttls",	CMDSTLS,	},
162#endif /* STARTTLS */
163    /* remaining commands are here only to trap and log attempts to use them */
164	{ "showq",	CMDDBGQSHOW	},
165	{ "debug",	CMDDBGDEBUG	},
166	{ "wiz",	CMDLOGBOGUS	},
167
168	{ NULL,		CMDERROR	}
169};
170
171static char	*CurSmtpClient;		/* who's at the other end of channel */
172
173#ifndef MAXBADCOMMANDS
174# define MAXBADCOMMANDS 25	/* maximum number of bad commands */
175#endif /* ! MAXBADCOMMANDS */
176#ifndef MAXNOOPCOMMANDS
177# define MAXNOOPCOMMANDS 20	/* max "noise" commands before slowdown */
178#endif /* ! MAXNOOPCOMMANDS */
179#ifndef MAXHELOCOMMANDS
180# define MAXHELOCOMMANDS 3	/* max HELO/EHLO commands before slowdown */
181#endif /* ! MAXHELOCOMMANDS */
182#ifndef MAXVRFYCOMMANDS
183# define MAXVRFYCOMMANDS 6	/* max VRFY/EXPN commands before slowdown */
184#endif /* ! MAXVRFYCOMMANDS */
185#ifndef MAXETRNCOMMANDS
186# define MAXETRNCOMMANDS 8	/* max ETRN commands before slowdown */
187#endif /* ! MAXETRNCOMMANDS */
188#ifndef MAXTIMEOUT
189# define MAXTIMEOUT (4 * 60)	/* max timeout for bad commands */
190#endif /* ! MAXTIMEOUT */
191
192#if SM_HEAP_CHECK
193static SM_DEBUG_T DebugLeakSmtp = SM_DEBUG_INITIALIZER("leak_smtp",
194	"@(#)$Debug: leak_smtp - trace memory leaks during SMTP processing $");
195#endif /* SM_HEAP_CHECK */
196
197typedef struct
198{
199	bool	sm_gotmail;	/* mail command received */
200	unsigned int sm_nrcpts;	/* number of successful RCPT commands */
201#if _FFR_ADAPTIVE_EOL
202WARNING: do NOT use this FFR, it is most likely broken
203	bool	sm_crlf;	/* input in CRLF form? */
204#endif /* _FFR_ADAPTIVE_EOL */
205	bool	sm_discard;
206#if MILTER
207	bool	sm_milterize;
208	bool	sm_milterlist;	/* any filters in the list? */
209#endif /* MILTER */
210#if _FFR_QUARANTINE
211	char	*sm_quarmsg;	/* carry quarantining across messages */
212#endif /* _FFR_QUARANTINE */
213} SMTP_T;
214
215static void	smtp_data __P((SMTP_T *, ENVELOPE *));
216
217#define MSG_TEMPFAIL "451 4.7.1 Please try again later"
218
219#if MILTER
220# define MILTER_ABORT(e)	milter_abort((e))
221
222#if _FFR_MILTER_421
223# define MILTER_SHUTDOWN						\
224			if (strncmp(response, "421 ", 4) == 0)		\
225			{						\
226				e->e_sendqueue = NULL;			\
227				goto doquit;				\
228			}
229#else /* _FFR_MILTER_421 */
230# define MILTER_SHUTDOWN
231#endif /* _FFR_MILTER_421 */
232
233# define MILTER_REPLY(str)						\
234	{								\
235		int savelogusrerrs = LogUsrErrs;			\
236									\
237		switch (state)						\
238		{							\
239		  case SMFIR_REPLYCODE:					\
240			if (MilterLogLevel > 3)				\
241			{						\
242				sm_syslog(LOG_INFO, e->e_id,		\
243					  "Milter: %s=%s, reject=%s",	\
244					  str, addr, response);		\
245				LogUsrErrs = false;			\
246			}						\
247			usrerr(response);				\
248			MILTER_SHUTDOWN					\
249			break;						\
250									\
251		  case SMFIR_REJECT:					\
252			if (MilterLogLevel > 3)				\
253			{						\
254				sm_syslog(LOG_INFO, e->e_id,		\
255					  "Milter: %s=%s, reject=550 5.7.1 Command rejected", \
256					  str, addr);			\
257				LogUsrErrs = false;			\
258			}						\
259			usrerr("550 5.7.1 Command rejected");		\
260			break;						\
261									\
262		  case SMFIR_DISCARD:					\
263			if (MilterLogLevel > 3)				\
264				sm_syslog(LOG_INFO, e->e_id,		\
265					  "Milter: %s=%s, discard",	\
266					  str, addr);			\
267			e->e_flags |= EF_DISCARD;			\
268			break;						\
269									\
270		  case SMFIR_TEMPFAIL:					\
271			if (MilterLogLevel > 3)				\
272			{						\
273				sm_syslog(LOG_INFO, e->e_id,		\
274					  "Milter: %s=%s, reject=%s",	\
275					  str, addr, MSG_TEMPFAIL);	\
276				LogUsrErrs = false;			\
277			}						\
278			usrerr(MSG_TEMPFAIL);				\
279			break;						\
280		}							\
281		LogUsrErrs = savelogusrerrs;				\
282		if (response != NULL)					\
283			sm_free(response); /* XXX */			\
284	}
285
286#else /* MILTER */
287# define MILTER_ABORT(e)
288#endif /* MILTER */
289
290/* clear all SMTP state (for HELO/EHLO/RSET) */
291#define CLEAR_STATE(cmd)					\
292{								\
293	/* abort milter filters */				\
294	MILTER_ABORT(e);					\
295								\
296	if (smtp.sm_nrcpts > 0)					\
297	{							\
298		logundelrcpts(e, cmd, 10, false);		\
299		smtp.sm_nrcpts = 0;				\
300		macdefine(&e->e_macro, A_PERM,			\
301			  macid("{nrcpts}"), "0");		\
302	}							\
303								\
304	e->e_sendqueue = NULL;					\
305	e->e_flags |= EF_CLRQUEUE;				\
306								\
307	if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))	\
308		logsender(e, NULL);				\
309	e->e_flags &= ~EF_LOGSENDER;				\
310								\
311	/* clean up a bit */					\
312	smtp.sm_gotmail = false;				\
313	SuprErrs = true;					\
314	dropenvelope(e, true, false);				\
315	sm_rpool_free(e->e_rpool);				\
316	e = newenvelope(e, CurEnv, sm_rpool_new_x(NULL));	\
317	CurEnv = e;						\
318}
319
320/* sleep to flatten out connection load */
321#define MIN_DELAY_LOG	15	/* wait before logging this again */
322
323/* is it worth setting the process title for 1s? */
324#define DELAY_CONN(cmd)						\
325	if (DelayLA > 0 && (CurrentLA = getla()) >= DelayLA)	\
326	{							\
327		time_t dnow;					\
328								\
329		sm_setproctitle(true, e,			\
330				"%s: %s: delaying %s: load average: %d", \
331				qid_printname(e), CurSmtpClient,	\
332				cmd, DelayLA);	\
333		if (LogLevel > 8 && (dnow = curtime()) > log_delay)	\
334		{						\
335			sm_syslog(LOG_INFO, e->e_id,		\
336				  "delaying=%s, load average=%d >= %d",	\
337				  cmd, CurrentLA, DelayLA);		\
338			log_delay = dnow + MIN_DELAY_LOG;	\
339		}						\
340		(void) sleep(1);				\
341		sm_setproctitle(true, e, "%s %s: %.80s",	\
342				qid_printname(e), CurSmtpClient, inp);	\
343	}
344
345
346void
347smtp(nullserver, d_flags, e)
348	char *volatile nullserver;
349	BITMAP256 d_flags;
350	register ENVELOPE *volatile e;
351{
352	register char *volatile p;
353	register struct cmd *volatile c = NULL;
354	char *cmd;
355	auto ADDRESS *vrfyqueue;
356	ADDRESS *a;
357	volatile bool gothello;		/* helo command received */
358	bool vrfy;			/* set if this is a vrfy command */
359	char *volatile protocol;	/* sending protocol */
360	char *volatile sendinghost;	/* sending hostname */
361	char *volatile peerhostname;	/* name of SMTP peer or "localhost" */
362	auto char *delimptr;
363	char *id;
364	volatile unsigned int n_badcmds = 0;	/* count of bad commands */
365	volatile unsigned int n_badrcpts = 0;	/* number of rejected RCPT */
366	volatile unsigned int n_verifies = 0;	/* count of VRFY/EXPN */
367	volatile unsigned int n_etrn = 0;	/* count of ETRN */
368	volatile unsigned int n_noop = 0;	/* count of NOOP/VERB/etc */
369	volatile unsigned int n_helo = 0;	/* count of HELO/EHLO */
370	bool ok;
371#if _FFR_BLOCK_PROXIES || _FFR_ADAPTIVE_EOL
372	volatile bool first;
373#endif /* _FFR_BLOCK_PROXIES || _FFR_ADAPTIVE_EOL */
374	volatile bool tempfail = false;
375	volatile time_t wt;		/* timeout after too many commands */
376	volatile time_t previous;	/* time after checksmtpattack() */
377	volatile bool lognullconnection = true;
378	register char *q;
379	SMTP_T smtp;
380	char *addr;
381	char *greetcode = "220";
382	char *hostname;			/* my hostname ($j) */
383	QUEUE_CHAR *new;
384	int argno;
385	char *args[MAXSMTPARGS];
386	char inp[MAXLINE];
387	char cmdbuf[MAXLINE];
388#if SASL
389	sasl_conn_t *conn;
390	volatile bool sasl_ok;
391	volatile unsigned int n_auth = 0;	/* count of AUTH commands */
392	bool ismore;
393	int result;
394	volatile int authenticating;
395	char *user;
396	char *in, *out2;
397# if SASL >= 20000
398	char *auth_id;
399	const char *out;
400	sasl_ssf_t ext_ssf;
401# else /* SASL >= 20000 */
402	char *out;
403	const char *errstr;
404	sasl_external_properties_t ext_ssf;
405# endif /* SASL >= 20000 */
406	sasl_security_properties_t ssp;
407	sasl_ssf_t *ssf;
408	unsigned int inlen, out2len;
409	unsigned int outlen;
410	char *volatile auth_type;
411	char *mechlist;
412	volatile unsigned int n_mechs;
413	unsigned int len;
414#endif /* SASL */
415#if STARTTLS
416	int r;
417	int rfd, wfd;
418	volatile bool tls_active = false;
419# if _FFR_SMTP_SSL
420	volatile bool smtps = false;
421# endif /* _FFR_SMTP_SSL */
422	bool saveQuickAbort;
423	bool saveSuprErrs;
424	time_t tlsstart;
425#endif /* STARTTLS */
426	volatile unsigned int features;
427#if PIPELINING
428# if _FFR_NO_PIPE
429	int np_log = 0;
430# endif /* _FFR_NO_PIPE */
431#endif /* PIPELINING */
432	volatile time_t log_delay = (time_t) 0;
433
434	smtp.sm_nrcpts = 0;
435#if MILTER
436	smtp.sm_milterize = (nullserver == NULL);
437	smtp.sm_milterlist = false;
438#endif /* MILTER */
439
440	/* setup I/O fd correctly for the SMTP server */
441	setup_smtpd_io();
442
443#if SM_HEAP_CHECK
444	if (sm_debug_active(&DebugLeakSmtp, 1))
445	{
446		sm_heap_newgroup();
447		sm_dprintf("smtp() heap group #%d\n", sm_heap_group());
448	}
449#endif /* SM_HEAP_CHECK */
450
451	/* XXX the rpool should be set when e is initialized in main() */
452	e->e_rpool = sm_rpool_new_x(NULL);
453	e->e_macro.mac_rpool = e->e_rpool;
454
455	settime(e);
456	sm_getla();
457	peerhostname = RealHostName;
458	if (peerhostname == NULL)
459		peerhostname = "localhost";
460	CurHostName = peerhostname;
461	CurSmtpClient = macvalue('_', e);
462	if (CurSmtpClient == NULL)
463		CurSmtpClient = CurHostName;
464
465	/* check_relay may have set discard bit, save for later */
466	smtp.sm_discard = bitset(EF_DISCARD, e->e_flags);
467
468#if PIPELINING
469	/* auto-flush output when reading input */
470	(void) sm_io_autoflush(InChannel, OutChannel);
471#endif /* PIPELINING */
472
473	sm_setproctitle(true, e, "server %s startup", CurSmtpClient);
474
475	/* Set default features for server. */
476	features = ((bitset(PRIV_NOETRN, PrivacyFlags) ||
477		     bitnset(D_NOETRN, d_flags)) ? SRV_NONE : SRV_OFFER_ETRN)
478		| (bitnset(D_AUTHREQ, d_flags) ? SRV_REQ_AUTH : SRV_NONE)
479		| (bitset(PRIV_NOEXPN, PrivacyFlags) ? SRV_NONE
480			: (SRV_OFFER_EXPN
481			  | (bitset(PRIV_NOVERB, PrivacyFlags)
482			     ? SRV_NONE : SRV_OFFER_VERB)))
483		| (bitset(PRIV_NORECEIPTS, PrivacyFlags) ? SRV_NONE
484							 : SRV_OFFER_DSN)
485#if SASL
486		| (bitnset(D_NOAUTH, d_flags) ? SRV_NONE : SRV_OFFER_AUTH)
487#endif /* SASL */
488#if PIPELINING
489		| SRV_OFFER_PIPE
490#endif /* PIPELINING */
491#if STARTTLS
492		| (bitnset(D_NOTLS, d_flags) ? SRV_NONE : SRV_OFFER_TLS)
493		| (bitset(TLS_I_NO_VRFY, TLS_Srv_Opts) ? SRV_NONE
494						       : SRV_VRFY_CLT)
495#endif /* STARTTLS */
496		;
497	if (nullserver == NULL)
498	{
499		features = srvfeatures(e, CurSmtpClient, features);
500		if (bitset(SRV_TMP_FAIL, features))
501		{
502			if (LogLevel > 4)
503				sm_syslog(LOG_ERR, NOQID,
504					  "ERROR: srv_features=tempfail, relay=%.100s, access temporarily disabled",
505					  CurSmtpClient);
506			nullserver = "450 4.3.0 Please try again later.";
507		}
508#if PIPELINING
509# if _FFR_NO_PIPE
510		else if (bitset(SRV_NO_PIPE, features))
511		{
512			/* for consistency */
513			features &= ~SRV_OFFER_PIPE;
514		}
515# endif /* _FFR_NO_PIPE */
516#endif /* PIPELINING */
517	}
518
519	hostname = macvalue('j', e);
520
521
522#if SASL
523	sasl_ok = bitset(SRV_OFFER_AUTH, features);
524	n_mechs = 0;
525	authenticating = SASL_NOT_AUTH;
526
527	/* SASL server new connection */
528	if (sasl_ok)
529	{
530# if SASL >= 20000
531		result = sasl_server_new("smtp", hostname, NULL, NULL, NULL,
532					 NULL, 0, &conn);
533# elif SASL > 10505
534		/* use empty realm: only works in SASL > 1.5.5 */
535		result = sasl_server_new("smtp", hostname, "", NULL, 0, &conn);
536# else /* SASL >= 20000 */
537		/* use no realm -> realm is set to hostname by SASL lib */
538		result = sasl_server_new("smtp", hostname, NULL, NULL, 0,
539					 &conn);
540# endif /* SASL >= 20000 */
541		sasl_ok = result == SASL_OK;
542		if (!sasl_ok)
543		{
544			if (LogLevel > 9)
545				sm_syslog(LOG_WARNING, NOQID,
546					  "AUTH error: sasl_server_new failed=%d",
547					  result);
548		}
549	}
550	if (sasl_ok)
551	{
552		/*
553		**  SASL set properties for sasl
554		**  set local/remote IP
555		**  XXX Cyrus SASL v1 only supports IPv4
556		**
557		**  XXX where exactly are these used/required?
558		**  Kerberos_v4
559		*/
560
561# if SASL >= 20000
562#  if NETINET || NETINET6
563		in = macvalue(macid("{daemon_family}"), e);
564		if (in != NULL && (
565#   if NETINET6
566		    strcmp(in, "inet6") == 0 ||
567#   endif /* NETINET6 */
568		    strcmp(in, "inet") == 0))
569		{
570			SOCKADDR_LEN_T addrsize;
571			SOCKADDR saddr_l;
572			SOCKADDR saddr_r;
573			char localip[60], remoteip[60];
574
575			addrsize = sizeof(saddr_r);
576			if (getpeername(sm_io_getinfo(InChannel, SM_IO_WHAT_FD,
577						      NULL),
578					(struct sockaddr *) &saddr_r,
579					&addrsize) == 0)
580			{
581				if (iptostring(&saddr_r, addrsize,
582					       remoteip, sizeof remoteip))
583				{
584					sasl_setprop(conn, SASL_IPREMOTEPORT,
585						     remoteip);
586				}
587				addrsize = sizeof(saddr_l);
588				if (getsockname(sm_io_getinfo(InChannel,
589							      SM_IO_WHAT_FD,
590							      NULL),
591						(struct sockaddr *) &saddr_l,
592						&addrsize) == 0)
593				{
594					if (iptostring(&saddr_l, addrsize,
595						       localip,
596						       sizeof localip))
597					{
598						sasl_setprop(conn,
599							     SASL_IPLOCALPORT,
600							     localip);
601					}
602				}
603			}
604		}
605#  endif /* NETINET || NETINET6 */
606# else /* SASL >= 20000 */
607#  if NETINET
608		in = macvalue(macid("{daemon_family}"), e);
609		if (in != NULL && strcmp(in, "inet") == 0)
610		{
611			SOCKADDR_LEN_T addrsize;
612			struct sockaddr_in saddr_l;
613			struct sockaddr_in saddr_r;
614
615			addrsize = sizeof(struct sockaddr_in);
616			if (getpeername(sm_io_getinfo(InChannel, SM_IO_WHAT_FD,
617						      NULL),
618					(struct sockaddr *)&saddr_r,
619					&addrsize) == 0)
620			{
621				sasl_setprop(conn, SASL_IP_REMOTE, &saddr_r);
622				addrsize = sizeof(struct sockaddr_in);
623				if (getsockname(sm_io_getinfo(InChannel,
624							      SM_IO_WHAT_FD,
625							      NULL),
626						(struct sockaddr *)&saddr_l,
627						&addrsize) == 0)
628					sasl_setprop(conn, SASL_IP_LOCAL,
629						     &saddr_l);
630			}
631		}
632#  endif /* NETINET */
633# endif /* SASL >= 20000 */
634
635		auth_type = NULL;
636		mechlist = NULL;
637		user = NULL;
638# if 0
639		macdefine(&BlankEnvelope.e_macro, A_PERM,
640			macid("{auth_author}"), NULL);
641# endif /* 0 */
642
643		/* set properties */
644		(void) memset(&ssp, '\0', sizeof ssp);
645
646		/* XXX should these be options settable via .cf ? */
647		/* ssp.min_ssf = 0; is default due to memset() */
648# if STARTTLS
649# endif /* STARTTLS */
650		{
651			ssp.max_ssf = MaxSLBits;
652			ssp.maxbufsize = MAXOUTLEN;
653		}
654		ssp.security_flags = SASLOpts & SASL_SEC_MASK;
655		sasl_ok = sasl_setprop(conn, SASL_SEC_PROPS, &ssp) == SASL_OK;
656
657		if (sasl_ok)
658		{
659			/*
660			**  external security strength factor;
661			**	currently we have none so zero
662			*/
663
664# if SASL >= 20000
665			ext_ssf = 0;
666			auth_id = NULL;
667			sasl_ok = ((sasl_setprop(conn, SASL_SSF_EXTERNAL,
668						 &ext_ssf) == SASL_OK) &&
669				   (sasl_setprop(conn, SASL_AUTH_EXTERNAL,
670						 auth_id) == SASL_OK));
671# else /* SASL >= 20000 */
672			ext_ssf.ssf = 0;
673			ext_ssf.auth_id = NULL;
674			sasl_ok = sasl_setprop(conn, SASL_SSF_EXTERNAL,
675					       &ext_ssf) == SASL_OK;
676# endif /* SASL >= 20000 */
677		}
678		if (sasl_ok)
679			n_mechs = saslmechs(conn, &mechlist);
680	}
681#endif /* SASL */
682
683#if MILTER
684	if (smtp.sm_milterize)
685	{
686		char state;
687
688		/* initialize mail filter connection */
689		smtp.sm_milterlist = milter_init(e, &state);
690		switch (state)
691		{
692		  case SMFIR_REJECT:
693			if (MilterLogLevel > 3)
694				sm_syslog(LOG_INFO, e->e_id,
695					  "Milter: initialization failed, rejecting commands");
696			greetcode = "554";
697			nullserver = "Command rejected";
698			smtp.sm_milterize = false;
699			break;
700
701		  case SMFIR_TEMPFAIL:
702			if (MilterLogLevel > 3)
703				sm_syslog(LOG_INFO, e->e_id,
704					  "Milter: initialization failed, temp failing commands");
705			tempfail = true;
706			smtp.sm_milterize = false;
707			break;
708		}
709	}
710
711	if (smtp.sm_milterlist && smtp.sm_milterize &&
712	    !bitset(EF_DISCARD, e->e_flags))
713	{
714		char state;
715		char *response;
716
717		response = milter_connect(peerhostname, RealHostAddr,
718					  e, &state);
719		switch (state)
720		{
721		  case SMFIR_REPLYCODE:	/* REPLYCODE shouldn't happen */
722		  case SMFIR_REJECT:
723			if (MilterLogLevel > 3)
724				sm_syslog(LOG_INFO, e->e_id,
725					  "Milter: connect: host=%s, addr=%s, rejecting commands",
726					  peerhostname,
727					  anynet_ntoa(&RealHostAddr));
728			greetcode = "554";
729			nullserver = "Command rejected";
730			smtp.sm_milterize = false;
731			break;
732
733		  case SMFIR_TEMPFAIL:
734			if (MilterLogLevel > 3)
735				sm_syslog(LOG_INFO, e->e_id,
736					  "Milter: connect: host=%s, addr=%s, temp failing commands",
737					  peerhostname,
738					  anynet_ntoa(&RealHostAddr));
739			tempfail = true;
740			smtp.sm_milterize = false;
741			break;
742
743#if _FFR_MILTER_421
744		  case SMFIR_SHUTDOWN:
745			if (MilterLogLevel > 3)
746				sm_syslog(LOG_INFO, e->e_id,
747					  "Milter: connect: host=%s, addr=%s, shutdown",
748					  peerhostname,
749					  anynet_ntoa(&RealHostAddr));
750			tempfail = true;
751			smtp.sm_milterize = false;
752			message("421 4.7.0 %s closing connection",
753					MyHostName);
754
755			/* arrange to ignore send list */
756			e->e_sendqueue = NULL;
757			goto doquit;
758#endif /* _FFR_MILTER_421 */
759		}
760		if (response != NULL)
761
762			sm_free(response); /* XXX */
763	}
764#endif /* MILTER */
765
766#if STARTTLS
767# if _FFR_SMTP_SSL
768	/* If this an smtps connection, start TLS now */
769	smtps = bitnset(D_SMTPS, d_flags);
770	if (smtps)
771		goto starttls;
772
773  greeting:
774
775# endif /* _FFR_SMTP_SSL */
776#endif /* STARTTLS */
777
778	/* output the first line, inserting "ESMTP" as second word */
779	if (*greetcode == '5')
780		(void) sm_snprintf(inp, sizeof inp, "%s not accepting messages",
781				   hostname);
782	else
783		expand(SmtpGreeting, inp, sizeof inp, e);
784
785	p = strchr(inp, '\n');
786	if (p != NULL)
787		*p++ = '\0';
788	id = strchr(inp, ' ');
789	if (id == NULL)
790		id = &inp[strlen(inp)];
791	if (p == NULL)
792		(void) sm_snprintf(cmdbuf, sizeof cmdbuf,
793			 "%s %%.*s ESMTP%%s", greetcode);
794	else
795		(void) sm_snprintf(cmdbuf, sizeof cmdbuf,
796			 "%s-%%.*s ESMTP%%s", greetcode);
797	message(cmdbuf, (int) (id - inp), inp, id);
798
799	/* output remaining lines */
800	while ((id = p) != NULL && (p = strchr(id, '\n')) != NULL)
801	{
802		*p++ = '\0';
803		if (isascii(*id) && isspace(*id))
804			id++;
805		(void) sm_strlcpyn(cmdbuf, sizeof cmdbuf, 2, greetcode, "-%s");
806		message(cmdbuf, id);
807	}
808	if (id != NULL)
809	{
810		if (isascii(*id) && isspace(*id))
811			id++;
812		(void) sm_strlcpyn(cmdbuf, sizeof cmdbuf, 2, greetcode, " %s");
813		message(cmdbuf, id);
814	}
815
816	protocol = NULL;
817	sendinghost = macvalue('s', e);
818
819#if _FFR_QUARANTINE
820	/* If quarantining by a connect/ehlo action, save between messages */
821	if (e->e_quarmsg == NULL)
822		smtp.sm_quarmsg = NULL;
823	else
824		smtp.sm_quarmsg = newstr(e->e_quarmsg);
825#endif /* _FFR_QUARANTINE */
826
827	/* sendinghost's storage must outlive the current envelope */
828	if (sendinghost != NULL)
829		sendinghost = sm_strdup_x(sendinghost);
830#if _FFR_BLOCK_PROXIES || _FFR_ADAPTIVE_EOL
831	first = true;
832#endif /* _FFR_BLOCK_PROXIES || _FFR_ADAPTIVE_EOL */
833	gothello = false;
834	smtp.sm_gotmail = false;
835	for (;;)
836	{
837	    SM_TRY
838	    {
839		QuickAbort = false;
840		HoldErrs = false;
841		SuprErrs = false;
842		LogUsrErrs = false;
843		OnlyOneError = true;
844		e->e_flags &= ~(EF_VRFYONLY|EF_GLOBALERRS);
845
846		/* setup for the read */
847		e->e_to = NULL;
848		Errors = 0;
849		FileName = NULL;
850		(void) sm_io_flush(smioout, SM_TIME_DEFAULT);
851
852		/* read the input line */
853		SmtpPhase = "server cmd read";
854		sm_setproctitle(true, e, "server %s cmd read", CurSmtpClient);
855#if SASL
856		/*
857		**  XXX SMTP AUTH requires accepting any length,
858		**	at least for challenge/response
859		*/
860#endif /* SASL */
861
862		/* handle errors */
863		if (sm_io_error(OutChannel) ||
864		    (p = sfgets(inp, sizeof inp, InChannel,
865				TimeOuts.to_nextcommand, SmtpPhase)) == NULL)
866		{
867			char *d;
868
869			d = macvalue(macid("{daemon_name}"), e);
870			if (d == NULL)
871				d = "stdin";
872			/* end of file, just die */
873			disconnect(1, e);
874
875#if MILTER
876			/* close out milter filters */
877			milter_quit(e);
878#endif /* MILTER */
879
880			message("421 4.4.1 %s Lost input channel from %s",
881				MyHostName, CurSmtpClient);
882			if (LogLevel > (smtp.sm_gotmail ? 1 : 19))
883				sm_syslog(LOG_NOTICE, e->e_id,
884					  "lost input channel from %s to %s after %s",
885					  CurSmtpClient, d,
886					  (c == NULL || c->cmd_name == NULL) ? "startup" : c->cmd_name);
887			/*
888			**  If have not accepted mail (DATA), do not bounce
889			**  bad addresses back to sender.
890			*/
891
892			if (bitset(EF_CLRQUEUE, e->e_flags))
893				e->e_sendqueue = NULL;
894			goto doquit;
895		}
896
897#if _FFR_BLOCK_PROXIES || _FFR_ADAPTIVE_EOL
898		if (first)
899		{
900#if _FFR_BLOCK_PROXIES
901			size_t inplen, cmdlen;
902			int idx;
903			char *http_cmd;
904			static char *http_cmds[] = { "GET", "POST",
905						     "CONNECT", "USER", NULL };
906
907			inplen = strlen(inp);
908			for (idx = 0; (http_cmd = http_cmds[idx]) != NULL;
909			     idx++)
910			{
911				cmdlen = strlen(http_cmd);
912				if (cmdlen < inplen &&
913				    sm_strncasecmp(inp, http_cmd, cmdlen) == 0 &&
914				    isascii(inp[cmdlen]) && isspace(inp[cmdlen]))
915				{
916					/* Open proxy, drop it */
917					message("421 4.7.0 %s Rejecting open proxy %s",
918						MyHostName, CurSmtpClient);
919					sm_syslog(LOG_INFO, e->e_id,
920						  "%s: probable open proxy: command=%.40s",
921						  CurSmtpClient, inp);
922					goto doquit;
923				}
924			}
925#endif /* _FFR_BLOCK_PROXIES */
926#if _FFR_ADAPTIVE_EOL
927			char *p;
928
929			smtp.sm_crlf = true;
930			p = strchr(inp, '\n');
931			if (p == NULL || p <= inp || p[-1] != '\r')
932			{
933				smtp.sm_crlf = false;
934				if (tTd(66, 1) && LogLevel > 8)
935				{
936					/* how many bad guys are there? */
937					sm_syslog(LOG_INFO, NOQID,
938						  "%s did not use CRLF",
939						  CurSmtpClient);
940				}
941			}
942#endif /* _FFR_ADAPTIVE_EOL */
943			first = false;
944		}
945#endif /* _FFR_BLOCK_PROXIES || _FFR_ADAPTIVE_EOL */
946
947		/* clean up end of line */
948		fixcrlf(inp, true);
949
950#if PIPELINING
951# if _FFR_NO_PIPE
952		/*
953		**  if there is more input and pipelining is disabled:
954		**	delay ... (and maybe discard the input?)
955		**  XXX this doesn't really work, at least in tests using
956		**  telnet SM_IO_IS_READABLE only returns 1 if there were
957		**  more than 2 input lines available.
958		*/
959
960		if (bitset(SRV_NO_PIPE, features) &&
961		    sm_io_getinfo(InChannel, SM_IO_IS_READABLE, NULL) > 0)
962		{
963			if (++np_log < 3)
964				sm_syslog(LOG_INFO, NOQID,
965					  "unauthorized PIPELINING, sleeping");
966			sleep(1);
967		}
968
969# endif /* _FFR_NO_PIPE */
970#endif /* PIPELINING */
971
972#if SASL
973		if (authenticating == SASL_PROC_AUTH)
974		{
975# if 0
976			if (*inp == '\0')
977			{
978				authenticating = SASL_NOT_AUTH;
979				message("501 5.5.2 missing input");
980				continue;
981			}
982# endif /* 0 */
983			if (*inp == '*' && *(inp + 1) == '\0')
984			{
985				authenticating = SASL_NOT_AUTH;
986
987				/* rfc 2254 4. */
988				message("501 5.0.0 AUTH aborted");
989				continue;
990			}
991
992			/* could this be shorter? XXX */
993# if SASL >= 20000
994			in = xalloc(strlen(inp) + 1);
995			result = sasl_decode64(inp, strlen(inp), in,
996					       strlen(inp), &inlen);
997# else /* SASL >= 20000 */
998			out = xalloc(strlen(inp));
999			result = sasl_decode64(inp, strlen(inp), out, &outlen);
1000# endif /* SASL >= 20000 */
1001			if (result != SASL_OK)
1002			{
1003				authenticating = SASL_NOT_AUTH;
1004
1005				/* rfc 2254 4. */
1006				message("501 5.5.4 cannot decode AUTH parameter %s",
1007					inp);
1008# if SASL >= 20000
1009				sm_free(in);
1010# endif /* SASL >= 20000 */
1011				continue;
1012			}
1013
1014# if SASL >= 20000
1015			result = sasl_server_step(conn,	in, inlen,
1016						  &out, &outlen);
1017			sm_free(in);
1018# else /* SASL >= 20000 */
1019			result = sasl_server_step(conn,	out, outlen,
1020						  &out, &outlen, &errstr);
1021# endif /* SASL >= 20000 */
1022
1023			/* get an OK if we're done */
1024			if (result == SASL_OK)
1025			{
1026  authenticated:
1027				message("235 2.0.0 OK Authenticated");
1028				authenticating = SASL_IS_AUTH;
1029				macdefine(&BlankEnvelope.e_macro, A_TEMP,
1030					macid("{auth_type}"), auth_type);
1031
1032# if SASL >= 20000
1033				user = macvalue(macid("{auth_authen}"), e);
1034
1035				/* get security strength (features) */
1036				result = sasl_getprop(conn, SASL_SSF,
1037						      (const void **) &ssf);
1038# else /* SASL >= 20000 */
1039				result = sasl_getprop(conn, SASL_USERNAME,
1040						      (void **)&user);
1041				if (result != SASL_OK)
1042				{
1043					user = "";
1044					macdefine(&BlankEnvelope.e_macro,
1045						  A_PERM,
1046						  macid("{auth_authen}"), NULL);
1047				}
1048				else
1049				{
1050					macdefine(&BlankEnvelope.e_macro,
1051						  A_TEMP,
1052						  macid("{auth_authen}"), user);
1053				}
1054
1055# if 0
1056				/* get realm? */
1057				sasl_getprop(conn, SASL_REALM, (void **) &data);
1058# endif /* 0 */
1059
1060				/* get security strength (features) */
1061				result = sasl_getprop(conn, SASL_SSF,
1062						      (void **) &ssf);
1063# endif /* SASL >= 20000 */
1064				if (result != SASL_OK)
1065				{
1066					macdefine(&BlankEnvelope.e_macro,
1067						  A_PERM,
1068						  macid("{auth_ssf}"), "0");
1069					ssf = NULL;
1070				}
1071				else
1072				{
1073					char pbuf[8];
1074
1075					(void) sm_snprintf(pbuf, sizeof pbuf,
1076							   "%u", *ssf);
1077					macdefine(&BlankEnvelope.e_macro,
1078						  A_TEMP,
1079						  macid("{auth_ssf}"), pbuf);
1080					if (tTd(95, 8))
1081						sm_dprintf("AUTH auth_ssf: %u\n",
1082							   *ssf);
1083				}
1084
1085				/*
1086				**  Only switch to encrypted connection
1087				**  if a security layer has been negotiated
1088				*/
1089
1090				if (ssf != NULL && *ssf > 0)
1091				{
1092					/*
1093					**  Convert I/O layer to use SASL.
1094					**  If the call fails, the connection
1095					**  is aborted.
1096					*/
1097
1098					if (sfdcsasl(&InChannel, &OutChannel,
1099						     conn) == 0)
1100					{
1101						/* restart dialogue */
1102						n_helo = 0;
1103# if PIPELINING
1104						(void) sm_io_autoflush(InChannel,
1105								       OutChannel);
1106# endif /* PIPELINING */
1107					}
1108					else
1109						syserr("503 5.3.3 SASL TLS failed");
1110				}
1111
1112				/* NULL pointer ok since it's our function */
1113				if (LogLevel > 8)
1114					sm_syslog(LOG_INFO, NOQID,
1115						  "AUTH=server, relay=%s, authid=%.128s, mech=%.16s, bits=%d",
1116						  CurSmtpClient,
1117						  shortenstring(user, 128),
1118						  auth_type, *ssf);
1119			}
1120			else if (result == SASL_CONTINUE)
1121			{
1122				len = ENC64LEN(outlen);
1123				out2 = xalloc(len);
1124				result = sasl_encode64(out, outlen, out2, len,
1125						       &out2len);
1126				if (result != SASL_OK)
1127				{
1128					/* correct code? XXX */
1129					/* 454 Temp. authentication failure */
1130					message("454 4.5.4 Internal error: unable to encode64");
1131					if (LogLevel > 5)
1132						sm_syslog(LOG_WARNING, e->e_id,
1133							  "AUTH encode64 error [%d for \"%s\"]",
1134							  result, out);
1135					/* start over? */
1136					authenticating = SASL_NOT_AUTH;
1137				}
1138				else
1139				{
1140					message("334 %s", out2);
1141					if (tTd(95, 2))
1142						sm_dprintf("AUTH continue: msg='%s' len=%u\n",
1143							   out2, out2len);
1144				}
1145# if SASL >= 20000
1146				sm_free(out2);
1147# endif /* SASL >= 20000 */
1148			}
1149			else
1150			{
1151				/* not SASL_OK or SASL_CONT */
1152				message("535 5.7.0 authentication failed");
1153				if (LogLevel > 9)
1154					sm_syslog(LOG_WARNING, e->e_id,
1155						  "AUTH failure (%s): %s (%d) %s",
1156						  auth_type,
1157						  sasl_errstring(result, NULL,
1158								 NULL),
1159						  result,
1160# if SASL >= 20000
1161						  sasl_errdetail(conn));
1162# else /* SASL >= 20000 */
1163						  errstr == NULL ? "" : errstr);
1164# endif /* SASL >= 20000 */
1165				authenticating = SASL_NOT_AUTH;
1166			}
1167		}
1168		else
1169		{
1170			/* don't want to do any of this if authenticating */
1171#endif /* SASL */
1172
1173		/* echo command to transcript */
1174		if (e->e_xfp != NULL)
1175			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
1176					     "<<< %s\n", inp);
1177
1178		if (LogLevel > 14)
1179			sm_syslog(LOG_INFO, e->e_id, "<-- %s", inp);
1180
1181		/* break off command */
1182		for (p = inp; isascii(*p) && isspace(*p); p++)
1183			continue;
1184		cmd = cmdbuf;
1185		while (*p != '\0' &&
1186		       !(isascii(*p) && isspace(*p)) &&
1187		       cmd < &cmdbuf[sizeof cmdbuf - 2])
1188			*cmd++ = *p++;
1189		*cmd = '\0';
1190
1191		/* throw away leading whitespace */
1192		SKIP_SPACE(p);
1193
1194		/* decode command */
1195		for (c = CmdTab; c->cmd_name != NULL; c++)
1196		{
1197			if (sm_strcasecmp(c->cmd_name, cmdbuf) == 0)
1198				break;
1199		}
1200
1201		/* reset errors */
1202		errno = 0;
1203
1204		/* check whether a "non-null" command has been used */
1205		switch (c->cmd_code)
1206		{
1207#if SASL
1208		  case CMDAUTH:
1209			/* avoid information leak; take first two words? */
1210			q = "AUTH";
1211			break;
1212#endif /* SASL */
1213
1214		  case CMDMAIL:
1215		  case CMDEXPN:
1216		  case CMDVRFY:
1217		  case CMDETRN:
1218			lognullconnection = false;
1219			/* FALLTHROUGH */
1220		  default:
1221			q = inp;
1222			break;
1223		}
1224
1225		if (e->e_id == NULL)
1226			sm_setproctitle(true, e, "%s: %.80s",
1227					CurSmtpClient, q);
1228		else
1229			sm_setproctitle(true, e, "%s %s: %.80s",
1230					qid_printname(e),
1231					CurSmtpClient, q);
1232
1233		/*
1234		**  Process command.
1235		**
1236		**	If we are running as a null server, return 550
1237		**	to almost everything.
1238		*/
1239
1240		if (nullserver != NULL || bitnset(D_ETRNONLY, d_flags))
1241		{
1242			switch (c->cmd_code)
1243			{
1244			  case CMDQUIT:
1245			  case CMDHELO:
1246			  case CMDEHLO:
1247			  case CMDNOOP:
1248			  case CMDRSET:
1249				/* process normally */
1250				break;
1251
1252			  case CMDETRN:
1253				if (bitnset(D_ETRNONLY, d_flags) &&
1254				    nullserver == NULL)
1255					break;
1256				DELAY_CONN("ETRN");
1257				/* FALLTHROUGH */
1258
1259			  default:
1260#if MAXBADCOMMANDS > 0
1261				/* theoretically this could overflow */
1262				if (nullserver != NULL &&
1263				    ++n_badcmds > MAXBADCOMMANDS)
1264				{
1265					message("421 4.7.0 %s Too many bad commands; closing connection",
1266						MyHostName);
1267
1268					/* arrange to ignore send list */
1269					e->e_sendqueue = NULL;
1270					goto doquit;
1271				}
1272#endif /* MAXBADCOMMANDS > 0 */
1273				if (nullserver != NULL)
1274				{
1275					if (ISSMTPREPLY(nullserver))
1276						usrerr(nullserver);
1277					else
1278						usrerr("550 5.0.0 %s",
1279						       nullserver);
1280				}
1281				else
1282					usrerr("452 4.4.5 Insufficient disk space; try again later");
1283				continue;
1284			}
1285		}
1286
1287		switch (c->cmd_code)
1288		{
1289#if SASL
1290		  case CMDAUTH: /* sasl */
1291			DELAY_CONN("AUTH");
1292			if (!sasl_ok || n_mechs <= 0)
1293			{
1294				message("503 5.3.3 AUTH not available");
1295				break;
1296			}
1297			if (authenticating == SASL_IS_AUTH)
1298			{
1299				message("503 5.5.0 Already Authenticated");
1300				break;
1301			}
1302			if (smtp.sm_gotmail)
1303			{
1304				message("503 5.5.0 AUTH not permitted during a mail transaction");
1305				break;
1306			}
1307			if (tempfail)
1308			{
1309				if (LogLevel > 9)
1310					sm_syslog(LOG_INFO, e->e_id,
1311						  "SMTP AUTH command (%.100s) from %s tempfailed (due to previous checks)",
1312						  p, CurSmtpClient);
1313				usrerr("454 4.7.1 Please try again later");
1314				break;
1315			}
1316
1317			ismore = false;
1318
1319			/* crude way to avoid crack attempts */
1320			(void) checksmtpattack(&n_auth, n_mechs + 1, true,
1321					       "AUTH", e);
1322
1323			/* make sure mechanism (p) is a valid string */
1324			for (q = p; *q != '\0' && isascii(*q); q++)
1325			{
1326				if (isspace(*q))
1327				{
1328					*q = '\0';
1329					while (*++q != '\0' &&
1330					       isascii(*q) && isspace(*q))
1331						continue;
1332					*(q - 1) = '\0';
1333					ismore = (*q != '\0');
1334					break;
1335				}
1336			}
1337
1338			if (*p == '\0')
1339			{
1340				message("501 5.5.2 AUTH mechanism must be specified");
1341				break;
1342			}
1343
1344			/* check whether mechanism is available */
1345			if (iteminlist(p, mechlist, " ") == NULL)
1346			{
1347				message("504 5.3.3 AUTH mechanism %.32s not available",
1348					p);
1349				break;
1350			}
1351
1352			if (ismore)
1353			{
1354				/* could this be shorter? XXX */
1355# if SASL >= 20000
1356				in = xalloc(strlen(q) + 1);
1357				result = sasl_decode64(q, strlen(q), in,
1358						       strlen(q), &inlen);
1359# else /* SASL >= 20000 */
1360				in = sm_rpool_malloc(e->e_rpool, strlen(q));
1361				result = sasl_decode64(q, strlen(q), in,
1362						       &inlen);
1363# endif /* SASL >= 20000 */
1364				if (result != SASL_OK)
1365				{
1366					message("501 5.5.4 cannot BASE64 decode '%s'",
1367						q);
1368					if (LogLevel > 5)
1369						sm_syslog(LOG_WARNING, e->e_id,
1370							  "AUTH decode64 error [%d for \"%s\"]",
1371							  result, q);
1372					/* start over? */
1373					authenticating = SASL_NOT_AUTH;
1374# if SASL >= 20000
1375					sm_free(in);
1376# endif /* SASL >= 20000 */
1377					in = NULL;
1378					inlen = 0;
1379					break;
1380				}
1381			}
1382			else
1383			{
1384				in = NULL;
1385				inlen = 0;
1386			}
1387
1388			/* see if that auth type exists */
1389# if SASL >= 20000
1390			result = sasl_server_start(conn, p, in, inlen,
1391						   &out, &outlen);
1392			if (in != NULL)
1393				sm_free(in);
1394# else /* SASL >= 20000 */
1395			result = sasl_server_start(conn, p, in, inlen,
1396						   &out, &outlen, &errstr);
1397# endif /* SASL >= 20000 */
1398
1399			if (result != SASL_OK && result != SASL_CONTINUE)
1400			{
1401				message("535 5.7.0 authentication failed");
1402				if (LogLevel > 9)
1403					sm_syslog(LOG_ERR, e->e_id,
1404						  "AUTH failure (%s): %s (%d) %s",
1405						  p,
1406						  sasl_errstring(result, NULL,
1407								 NULL),
1408						  result,
1409# if SASL >= 20000
1410						  sasl_errdetail(conn));
1411# else /* SASL >= 20000 */
1412						  errstr);
1413# endif /* SASL >= 20000 */
1414				break;
1415			}
1416			auth_type = newstr(p);
1417
1418			if (result == SASL_OK)
1419			{
1420				/* ugly, but same code */
1421				goto authenticated;
1422				/* authenticated by the initial response */
1423			}
1424
1425			/* len is at least 2 */
1426			len = ENC64LEN(outlen);
1427			out2 = xalloc(len);
1428			result = sasl_encode64(out, outlen, out2, len,
1429					       &out2len);
1430
1431			if (result != SASL_OK)
1432			{
1433				message("454 4.5.4 Temporary authentication failure");
1434				if (LogLevel > 5)
1435					sm_syslog(LOG_WARNING, e->e_id,
1436						  "AUTH encode64 error [%d for \"%s\"]",
1437						  result, out);
1438
1439				/* start over? */
1440				authenticating = SASL_NOT_AUTH;
1441			}
1442			else
1443			{
1444				message("334 %s", out2);
1445				authenticating = SASL_PROC_AUTH;
1446			}
1447# if SASL >= 20000
1448			sm_free(out2);
1449# endif /* SASL >= 20000 */
1450			break;
1451#endif /* SASL */
1452
1453#if STARTTLS
1454		  case CMDSTLS: /* starttls */
1455			DELAY_CONN("STARTTLS");
1456			if (*p != '\0')
1457			{
1458				message("501 5.5.2 Syntax error (no parameters allowed)");
1459				break;
1460			}
1461			if (!bitset(SRV_OFFER_TLS, features))
1462			{
1463				message("503 5.5.0 TLS not available");
1464				break;
1465			}
1466			if (!tls_ok_srv)
1467			{
1468				message("454 4.3.3 TLS not available after start");
1469				break;
1470			}
1471			if (smtp.sm_gotmail)
1472			{
1473				message("503 5.5.0 TLS not permitted during a mail transaction");
1474				break;
1475			}
1476			if (tempfail)
1477			{
1478				if (LogLevel > 9)
1479					sm_syslog(LOG_INFO, e->e_id,
1480						  "SMTP STARTTLS command (%.100s) from %s tempfailed (due to previous checks)",
1481						  p, CurSmtpClient);
1482				usrerr("454 4.7.1 Please try again later");
1483				break;
1484			}
1485# if _FFR_SMTP_SSL
1486  starttls:
1487# endif /* _FFR_SMTP_SSL */
1488# if TLS_NO_RSA
1489			/*
1490			**  XXX do we need a temp key ?
1491			*/
1492# else /* TLS_NO_RSA */
1493# endif /* TLS_NO_RSA */
1494
1495# if TLS_VRFY_PER_CTX
1496			/*
1497			**  Note: this sets the verification globally
1498			**  (per SSL_CTX)
1499			**  it's ok since it applies only to one transaction
1500			*/
1501
1502			TLS_VERIFY_CLIENT();
1503# endif /* TLS_VRFY_PER_CTX */
1504
1505			if (srv_ssl != NULL)
1506				SSL_clear(srv_ssl);
1507			else if ((srv_ssl = SSL_new(srv_ctx)) == NULL)
1508			{
1509				message("454 4.3.3 TLS not available: error generating SSL handle");
1510# if _FFR_SMTP_SSL
1511				goto tls_done;
1512# else /* _FFR_SMTP_SSL */
1513				break;
1514# endif /* _FFR_SMTP_SSL */
1515			}
1516
1517# if !TLS_VRFY_PER_CTX
1518			/*
1519			**  this could be used if it were possible to set
1520			**  verification per SSL (connection)
1521			**  not just per SSL_CTX (global)
1522			*/
1523
1524			TLS_VERIFY_CLIENT();
1525# endif /* !TLS_VRFY_PER_CTX */
1526
1527			rfd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL);
1528			wfd = sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL);
1529
1530			if (rfd < 0 || wfd < 0 ||
1531			    SSL_set_rfd(srv_ssl, rfd) <= 0 ||
1532			    SSL_set_wfd(srv_ssl, wfd) <= 0)
1533			{
1534				message("454 4.3.3 TLS not available: error set fd");
1535				SSL_free(srv_ssl);
1536				srv_ssl = NULL;
1537# if _FFR_SMTP_SSL
1538				goto tls_done;
1539# else /* _FFR_SMTP_SSL */
1540				break;
1541# endif /* _FFR_SMTP_SSL */
1542			}
1543# if _FFR_SMTP_SSL
1544			if (!smtps)
1545# endif /* _FFR_SMTP_SSL */
1546				message("220 2.0.0 Ready to start TLS");
1547# if PIPELINING
1548			(void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
1549# endif /* PIPELINING */
1550
1551			SSL_set_accept_state(srv_ssl);
1552
1553#  define SSL_ACC(s)	SSL_accept(s)
1554
1555			tlsstart = curtime();
1556  ssl_retry:
1557			if ((r = SSL_ACC(srv_ssl)) <= 0)
1558			{
1559				int i;
1560				bool timedout;
1561				time_t left;
1562				time_t now = curtime();
1563				struct timeval tv;
1564
1565				/* what to do in this case? */
1566				i = SSL_get_error(srv_ssl, r);
1567
1568				/*
1569				**  For SSL_ERROR_WANT_{READ,WRITE}:
1570				**  There is no SSL record available yet
1571				**  or there is only a partial SSL record
1572				**  removed from the network (socket) buffer
1573				**  into the SSL buffer. The SSL_accept will
1574				**  only succeed when a full SSL record is
1575				**  available (assuming a "real" error
1576				**  doesn't happen). To handle when a "real"
1577				**  error does happen the select is set for
1578				**  exceptions too.
1579				**  The connection may be re-negotiated
1580				**  during this time so both read and write
1581				**  "want errors" need to be handled.
1582				**  A select() exception loops back so that
1583				**  a proper SSL error message can be gotten.
1584				*/
1585
1586				left = TimeOuts.to_starttls - (now - tlsstart);
1587				timedout = left <= 0;
1588				if (!timedout)
1589				{
1590					tv.tv_sec = left;
1591					tv.tv_usec = 0;
1592				}
1593
1594				if (!timedout && FD_SETSIZE > 0 &&
1595				    (rfd >= FD_SETSIZE ||
1596				     (i == SSL_ERROR_WANT_WRITE &&
1597				      wfd >= FD_SETSIZE)))
1598				{
1599					if (LogLevel > 5)
1600					{
1601						sm_syslog(LOG_ERR, NOQID,
1602							  "STARTTLS=server, error: fd %d/%d too large",
1603							  rfd, wfd);
1604						if (LogLevel > 8)
1605							tlslogerr("server");
1606					}
1607					goto tlsfail;
1608				}
1609
1610				/* XXX what about SSL_pending() ? */
1611				if (!timedout && i == SSL_ERROR_WANT_READ)
1612				{
1613					fd_set ssl_maskr, ssl_maskx;
1614
1615					FD_ZERO(&ssl_maskr);
1616					FD_SET(rfd, &ssl_maskr);
1617					FD_ZERO(&ssl_maskx);
1618					FD_SET(rfd, &ssl_maskx);
1619					if (select(rfd + 1, &ssl_maskr, NULL,
1620						   &ssl_maskx, &tv) > 0)
1621						goto ssl_retry;
1622				}
1623				if (!timedout && i == SSL_ERROR_WANT_WRITE)
1624				{
1625					fd_set ssl_maskw, ssl_maskx;
1626
1627					FD_ZERO(&ssl_maskw);
1628					FD_SET(wfd, &ssl_maskw);
1629					FD_ZERO(&ssl_maskx);
1630					FD_SET(rfd, &ssl_maskx);
1631					if (select(wfd + 1, NULL, &ssl_maskw,
1632						   &ssl_maskx, &tv) > 0)
1633						goto ssl_retry;
1634				}
1635				if (LogLevel > 5)
1636				{
1637					sm_syslog(LOG_WARNING, NOQID,
1638						  "STARTTLS=server, error: accept failed=%d, SSL_error=%d, timedout=%d, errno=%d",
1639						  r, i, (int) timedout, errno);
1640					if (LogLevel > 8)
1641						tlslogerr("server");
1642				}
1643tlsfail:
1644				tls_ok_srv = false;
1645				SSL_free(srv_ssl);
1646				srv_ssl = NULL;
1647
1648				/*
1649				**  according to the next draft of
1650				**  RFC 2487 the connection should be dropped
1651				*/
1652
1653				/* arrange to ignore any current send list */
1654				e->e_sendqueue = NULL;
1655				goto doquit;
1656			}
1657
1658			/* ignore return code for now, it's in {verify} */
1659			(void) tls_get_info(srv_ssl, true,
1660					    CurSmtpClient,
1661					    &BlankEnvelope.e_macro,
1662					    bitset(SRV_VRFY_CLT, features));
1663
1664			/*
1665			**  call Stls_client to find out whether
1666			**  to accept the connection from the client
1667			*/
1668
1669			saveQuickAbort = QuickAbort;
1670			saveSuprErrs = SuprErrs;
1671			SuprErrs = true;
1672			QuickAbort = false;
1673			if (rscheck("tls_client",
1674				     macvalue(macid("{verify}"), e),
1675				     "STARTTLS", e,
1676				     RSF_RMCOMM|RSF_COUNT,
1677				     5, NULL, NOQID) != EX_OK ||
1678			    Errors > 0)
1679			{
1680				extern char MsgBuf[];
1681
1682				if (MsgBuf[0] != '\0' && ISSMTPREPLY(MsgBuf))
1683					nullserver = newstr(MsgBuf);
1684				else
1685					nullserver = "503 5.7.0 Authentication required.";
1686			}
1687			QuickAbort = saveQuickAbort;
1688			SuprErrs = saveSuprErrs;
1689
1690			tls_ok_srv = false;	/* don't offer STARTTLS again */
1691			n_helo = 0;
1692# if SASL
1693			if (sasl_ok)
1694			{
1695				char *s;
1696
1697				s = macvalue(macid("{cipher_bits}"), e);
1698#  if SASL >= 20000
1699				if (s != NULL && (ext_ssf = atoi(s)) > 0)
1700				{
1701					auth_id = macvalue(macid("{cert_subject}"),
1702								   e);
1703					sasl_ok = ((sasl_setprop(conn, SASL_SSF_EXTERNAL,
1704								 &ext_ssf) == SASL_OK) &&
1705						   (sasl_setprop(conn, SASL_AUTH_EXTERNAL,
1706								 auth_id) == SASL_OK));
1707#  else /* SASL >= 20000 */
1708				if (s != NULL && (ext_ssf.ssf = atoi(s)) > 0)
1709				{
1710					ext_ssf.auth_id = macvalue(macid("{cert_subject}"),
1711								   e);
1712					sasl_ok = sasl_setprop(conn, SASL_SSF_EXTERNAL,
1713							       &ext_ssf) == SASL_OK;
1714#  endif /* SASL >= 20000 */
1715					mechlist = NULL;
1716					if (sasl_ok)
1717						n_mechs = saslmechs(conn,
1718								    &mechlist);
1719				}
1720			}
1721# endif /* SASL */
1722
1723			/* switch to secure connection */
1724			if (sfdctls(&InChannel, &OutChannel, srv_ssl) == 0)
1725			{
1726				tls_active = true;
1727# if PIPELINING
1728				(void) sm_io_autoflush(InChannel, OutChannel);
1729# endif /* PIPELINING */
1730			}
1731			else
1732			{
1733				/*
1734				**  XXX this is an internal error
1735				**  how to deal with it?
1736				**  we can't generate an error message
1737				**  since the other side switched to an
1738				**  encrypted layer, but we could not...
1739				**  just "hang up"?
1740				*/
1741
1742				nullserver = "454 4.3.3 TLS not available: can't switch to encrypted layer";
1743				syserr("STARTTLS: can't switch to encrypted layer");
1744			}
1745# if _FFR_SMTP_SSL
1746		  tls_done:
1747			if (smtps)
1748			{
1749				if (tls_active)
1750					goto greeting;
1751				else
1752					goto doquit;
1753			}
1754# endif /* _FFR_SMTP_SSL */
1755			break;
1756#endif /* STARTTLS */
1757
1758		  case CMDHELO:		/* hello -- introduce yourself */
1759		  case CMDEHLO:		/* extended hello */
1760			DELAY_CONN("EHLO");
1761			if (c->cmd_code == CMDEHLO)
1762			{
1763				protocol = "ESMTP";
1764				SmtpPhase = "server EHLO";
1765			}
1766			else
1767			{
1768				protocol = "SMTP";
1769				SmtpPhase = "server HELO";
1770			}
1771
1772			/* avoid denial-of-service */
1773			(void) checksmtpattack(&n_helo, MAXHELOCOMMANDS, true,
1774					       "HELO/EHLO", e);
1775
1776#if 0
1777			/* RFC2821 4.1.4 allows duplicate HELO/EHLO */
1778			/* check for duplicate HELO/EHLO per RFC 1651 4.2 */
1779			if (gothello)
1780			{
1781				usrerr("503 %s Duplicate HELO/EHLO",
1782				       MyHostName);
1783				break;
1784			}
1785#endif /* 0 */
1786
1787			/* check for valid domain name (re 1123 5.2.5) */
1788			if (*p == '\0' && !AllowBogusHELO)
1789			{
1790				usrerr("501 %s requires domain address",
1791					cmdbuf);
1792				break;
1793			}
1794
1795			/* check for long domain name (hides Received: info) */
1796			if (strlen(p) > MAXNAME)
1797			{
1798				usrerr("501 Invalid domain name");
1799				if (LogLevel > 9)
1800					sm_syslog(LOG_INFO, CurEnv->e_id,
1801						  "invalid domain name (too long) from %s",
1802						  CurSmtpClient);
1803				break;
1804			}
1805
1806			ok = true;
1807			for (q = p; *q != '\0'; q++)
1808			{
1809				if (!isascii(*q))
1810					break;
1811				if (isalnum(*q))
1812					continue;
1813				if (isspace(*q))
1814				{
1815					*q = '\0';
1816
1817					/* only complain if strict check */
1818					ok = AllowBogusHELO;
1819					break;
1820				}
1821				if (strchr("[].-_#", *q) == NULL)
1822					break;
1823			}
1824
1825			if (*q == '\0' && ok)
1826			{
1827				q = "pleased to meet you";
1828				sendinghost = sm_strdup_x(p);
1829			}
1830			else if (!AllowBogusHELO)
1831			{
1832				usrerr("501 Invalid domain name");
1833				if (LogLevel > 9)
1834					sm_syslog(LOG_INFO, CurEnv->e_id,
1835						  "invalid domain name (%s) from %.100s",
1836						  p, CurSmtpClient);
1837				break;
1838			}
1839			else
1840			{
1841				q = "accepting invalid domain name";
1842			}
1843
1844			if (gothello)
1845			{
1846				CLEAR_STATE(cmdbuf);
1847
1848#if _FFR_QUARANTINE
1849				/* restore connection quarantining */
1850				if (smtp.sm_quarmsg == NULL)
1851				{
1852					e->e_quarmsg = NULL;
1853					macdefine(&e->e_macro, A_PERM,
1854						  macid("{quarantine}"), "");
1855				}
1856				else
1857				{
1858					e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool,
1859									 smtp.sm_quarmsg);
1860					macdefine(&e->e_macro, A_PERM,
1861						  macid("{quarantine}"),
1862						  e->e_quarmsg);
1863				}
1864#endif /* _FFR_QUARANTINE */
1865			}
1866
1867#if MILTER
1868			if (smtp.sm_milterlist && smtp.sm_milterize &&
1869			    !bitset(EF_DISCARD, e->e_flags))
1870			{
1871				char state;
1872				char *response;
1873
1874				response = milter_helo(p, e, &state);
1875				switch (state)
1876				{
1877				  case SMFIR_REPLYCODE:
1878					if (MilterLogLevel > 3)
1879						sm_syslog(LOG_INFO, e->e_id,
1880							  "Milter: helo=%s, reject=%s",
1881							  p, response);
1882					nullserver = newstr(response);
1883					smtp.sm_milterize = false;
1884					break;
1885
1886				  case SMFIR_REJECT:
1887					if (MilterLogLevel > 3)
1888						sm_syslog(LOG_INFO, e->e_id,
1889							  "Milter: helo=%s, reject=Command rejected",
1890							  p);
1891					nullserver = "Command rejected";
1892					smtp.sm_milterize = false;
1893					break;
1894
1895				  case SMFIR_TEMPFAIL:
1896					if (MilterLogLevel > 3)
1897						sm_syslog(LOG_INFO, e->e_id,
1898							  "Milter: helo=%s, reject=%s",
1899							  p, MSG_TEMPFAIL);
1900					tempfail = true;
1901					smtp.sm_milterize = false;
1902					break;
1903				}
1904				if (response != NULL)
1905					sm_free(response);
1906
1907# if _FFR_QUARANTINE
1908				/*
1909				**  If quarantining by a connect/ehlo action,
1910				**  save between messages
1911				*/
1912
1913				if (smtp.sm_quarmsg == NULL &&
1914				    e->e_quarmsg != NULL)
1915					smtp.sm_quarmsg = newstr(e->e_quarmsg);
1916# endif /* _FFR_QUARANTINE */
1917			}
1918#endif /* MILTER */
1919			gothello = true;
1920
1921			/* print HELO response message */
1922			if (c->cmd_code != CMDEHLO)
1923			{
1924				message("250 %s Hello %s, %s",
1925					MyHostName, CurSmtpClient, q);
1926				break;
1927			}
1928
1929			message("250-%s Hello %s, %s",
1930				MyHostName, CurSmtpClient, q);
1931
1932			/* offer ENHSC even for nullserver */
1933			if (nullserver != NULL)
1934			{
1935				message("250 ENHANCEDSTATUSCODES");
1936				break;
1937			}
1938
1939			/*
1940			**  print EHLO features list
1941			**
1942			**  Note: If you change this list,
1943			**	  remember to update 'helpfile'
1944			*/
1945
1946			message("250-ENHANCEDSTATUSCODES");
1947#if PIPELINING
1948			if (bitset(SRV_OFFER_PIPE, features))
1949				message("250-PIPELINING");
1950#endif /* PIPELINING */
1951			if (bitset(SRV_OFFER_EXPN, features))
1952			{
1953				message("250-EXPN");
1954				if (bitset(SRV_OFFER_VERB, features))
1955					message("250-VERB");
1956			}
1957#if MIME8TO7
1958			message("250-8BITMIME");
1959#endif /* MIME8TO7 */
1960			if (MaxMessageSize > 0)
1961				message("250-SIZE %ld", MaxMessageSize);
1962			else
1963				message("250-SIZE");
1964#if DSN
1965			if (SendMIMEErrors && bitset(SRV_OFFER_DSN, features))
1966				message("250-DSN");
1967#endif /* DSN */
1968			if (bitset(SRV_OFFER_ETRN, features))
1969				message("250-ETRN");
1970#if SASL
1971			if (sasl_ok && mechlist != NULL && *mechlist != '\0')
1972				message("250-AUTH %s", mechlist);
1973#endif /* SASL */
1974#if STARTTLS
1975			if (tls_ok_srv &&
1976			    bitset(SRV_OFFER_TLS, features))
1977				message("250-STARTTLS");
1978#endif /* STARTTLS */
1979			if (DeliverByMin > 0)
1980				message("250-DELIVERBY %ld",
1981					(long) DeliverByMin);
1982			else if (DeliverByMin == 0)
1983				message("250-DELIVERBY");
1984
1985			/* < 0: no deliver-by */
1986
1987			message("250 HELP");
1988			break;
1989
1990		  case CMDMAIL:		/* mail -- designate sender */
1991			SmtpPhase = "server MAIL";
1992			DELAY_CONN("MAIL");
1993
1994			/* check for validity of this command */
1995			if (!gothello && bitset(PRIV_NEEDMAILHELO, PrivacyFlags))
1996			{
1997				usrerr("503 5.0.0 Polite people say HELO first");
1998				break;
1999			}
2000			if (smtp.sm_gotmail)
2001			{
2002				usrerr("503 5.5.0 Sender already specified");
2003				break;
2004			}
2005#if SASL
2006			if (bitset(SRV_REQ_AUTH, features) &&
2007			    authenticating != SASL_IS_AUTH)
2008			{
2009				usrerr("530 5.7.0 Authentication required");
2010				break;
2011			}
2012#endif /* SASL */
2013
2014			p = skipword(p, "from");
2015			if (p == NULL)
2016				break;
2017			if (tempfail)
2018			{
2019				if (LogLevel > 9)
2020					sm_syslog(LOG_INFO, e->e_id,
2021						  "SMTP MAIL command (%.100s) from %s tempfailed (due to previous checks)",
2022						  p, CurSmtpClient);
2023				usrerr(MSG_TEMPFAIL);
2024				break;
2025			}
2026
2027			/* make sure we know who the sending host is */
2028			if (sendinghost == NULL)
2029				sendinghost = peerhostname;
2030
2031
2032#if SM_HEAP_CHECK
2033			if (sm_debug_active(&DebugLeakSmtp, 1))
2034			{
2035				sm_heap_newgroup();
2036				sm_dprintf("smtp() heap group #%d\n",
2037					sm_heap_group());
2038			}
2039#endif /* SM_HEAP_CHECK */
2040
2041			if (Errors > 0)
2042				goto undo_no_pm;
2043			if (!gothello)
2044			{
2045				auth_warning(e, "%s didn't use HELO protocol",
2046					     CurSmtpClient);
2047			}
2048#ifdef PICKY_HELO_CHECK
2049			if (sm_strcasecmp(sendinghost, peerhostname) != 0 &&
2050			    (sm_strcasecmp(peerhostname, "localhost") != 0 ||
2051			     sm_strcasecmp(sendinghost, MyHostName) != 0))
2052			{
2053				auth_warning(e, "Host %s claimed to be %s",
2054					     CurSmtpClient, sendinghost);
2055			}
2056#endif /* PICKY_HELO_CHECK */
2057
2058			if (protocol == NULL)
2059				protocol = "SMTP";
2060			macdefine(&e->e_macro, A_PERM, 'r', protocol);
2061			macdefine(&e->e_macro, A_PERM, 's', sendinghost);
2062
2063			if (Errors > 0)
2064				goto undo_no_pm;
2065			smtp.sm_nrcpts = 0;
2066			n_badrcpts = 0;
2067			macdefine(&e->e_macro, A_PERM, macid("{ntries}"), "0");
2068			macdefine(&e->e_macro, A_PERM, macid("{nrcpts}"), "0");
2069			e->e_flags |= EF_CLRQUEUE;
2070			sm_setproctitle(true, e, "%s %s: %.80s",
2071					qid_printname(e),
2072					CurSmtpClient, inp);
2073
2074			/* do the processing */
2075		    SM_TRY
2076		    {
2077			extern char *FullName;
2078
2079			QuickAbort = true;
2080			SM_FREE_CLR(FullName);
2081
2082			/* must parse sender first */
2083			delimptr = NULL;
2084			setsender(p, e, &delimptr, ' ', false);
2085			if (delimptr != NULL && *delimptr != '\0')
2086				*delimptr++ = '\0';
2087			if (Errors > 0)
2088				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2089
2090			/* Successfully set e_from, allow logging */
2091			e->e_flags |= EF_LOGSENDER;
2092
2093			/* put resulting triple from parseaddr() into macros */
2094			if (e->e_from.q_mailer != NULL)
2095				 macdefine(&e->e_macro, A_PERM,
2096					macid("{mail_mailer}"),
2097					e->e_from.q_mailer->m_name);
2098			else
2099				 macdefine(&e->e_macro, A_PERM,
2100					macid("{mail_mailer}"), NULL);
2101			if (e->e_from.q_host != NULL)
2102				macdefine(&e->e_macro, A_PERM,
2103					macid("{mail_host}"),
2104					e->e_from.q_host);
2105			else
2106				macdefine(&e->e_macro, A_PERM,
2107					macid("{mail_host}"), "localhost");
2108			if (e->e_from.q_user != NULL)
2109				macdefine(&e->e_macro, A_PERM,
2110					macid("{mail_addr}"),
2111					e->e_from.q_user);
2112			else
2113				macdefine(&e->e_macro, A_PERM,
2114					macid("{mail_addr}"), NULL);
2115			if (Errors > 0)
2116				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2117
2118			/* check for possible spoofing */
2119			if (RealUid != 0 && OpMode == MD_SMTP &&
2120			    !wordinclass(RealUserName, 't') &&
2121			    (!bitnset(M_LOCALMAILER,
2122				      e->e_from.q_mailer->m_flags) ||
2123			     strcmp(e->e_from.q_user, RealUserName) != 0))
2124			{
2125				auth_warning(e, "%s owned process doing -bs",
2126					RealUserName);
2127			}
2128
2129			/* now parse ESMTP arguments */
2130			e->e_msgsize = 0;
2131			addr = p;
2132			argno = 0;
2133			args[argno++] = p;
2134			p = delimptr;
2135			while (p != NULL && *p != '\0')
2136			{
2137				char *kp;
2138				char *vp = NULL;
2139				char *equal = NULL;
2140
2141				/* locate the beginning of the keyword */
2142				SKIP_SPACE(p);
2143				if (*p == '\0')
2144					break;
2145				kp = p;
2146
2147				/* skip to the value portion */
2148				while ((isascii(*p) && isalnum(*p)) || *p == '-')
2149					p++;
2150				if (*p == '=')
2151				{
2152					equal = p;
2153					*p++ = '\0';
2154					vp = p;
2155
2156					/* skip to the end of the value */
2157					while (*p != '\0' && *p != ' ' &&
2158					       !(isascii(*p) && iscntrl(*p)) &&
2159					       *p != '=')
2160						p++;
2161				}
2162
2163				if (*p != '\0')
2164					*p++ = '\0';
2165
2166				if (tTd(19, 1))
2167					sm_dprintf("MAIL: got arg %s=\"%s\"\n", kp,
2168						vp == NULL ? "<null>" : vp);
2169
2170				mail_esmtp_args(kp, vp, e);
2171				if (equal != NULL)
2172					*equal = '=';
2173				args[argno++] = kp;
2174				if (argno >= MAXSMTPARGS - 1)
2175					usrerr("501 5.5.4 Too many parameters");
2176				if (Errors > 0)
2177					sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2178			}
2179			args[argno] = NULL;
2180			if (Errors > 0)
2181				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2182
2183#if SASL
2184# if _FFR_AUTH_PASSING
2185			/* set the default AUTH= if the sender didn't */
2186			if (e->e_auth_param == NULL)
2187			{
2188				/* XXX only do this for an MSA? */
2189				e->e_auth_param = macvalue(macid("{auth_authen}"),
2190							   e);
2191				if (e->e_auth_param == NULL)
2192					e->e_auth_param = "<>";
2193
2194				/*
2195				**  XXX should we invoke Strust_auth now?
2196				**  authorizing as the client that just
2197				**  authenticated, so we'll trust implicitly
2198				*/
2199			}
2200# endif /* _FFR_AUTH_PASSING */
2201#endif /* SASL */
2202
2203			/* do config file checking of the sender */
2204			macdefine(&e->e_macro, A_PERM,
2205				macid("{addr_type}"), "e s");
2206#if _FFR_MAIL_MACRO
2207			/* make the "real" sender address available */
2208			macdefine(&e->e_macro, A_TEMP, macid("{mail_from}"),
2209				  e->e_from.q_paddr);
2210#endif /* _FFR_MAIL_MACRO */
2211			if (rscheck("check_mail", addr,
2212				    NULL, e, RSF_RMCOMM|RSF_COUNT, 3,
2213				    NULL, e->e_id) != EX_OK ||
2214			    Errors > 0)
2215				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2216			macdefine(&e->e_macro, A_PERM,
2217				  macid("{addr_type}"), NULL);
2218
2219			if (MaxMessageSize > 0 &&
2220			    (e->e_msgsize > MaxMessageSize ||
2221			     e->e_msgsize < 0))
2222			{
2223				usrerr("552 5.2.3 Message size exceeds fixed maximum message size (%ld)",
2224					MaxMessageSize);
2225				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2226			}
2227
2228			/*
2229			**  XXX always check whether there is at least one fs
2230			**  with enough space?
2231			**  However, this may not help much: the queue group
2232			**  selection may later on select a FS that hasn't
2233			**  enough space.
2234			*/
2235
2236			if ((NumFileSys == 1 || NumQueue == 1) &&
2237			    !enoughdiskspace(e->e_msgsize, e)
2238#if _FFR_ANY_FREE_FS
2239			    && !filesys_free(e->e_msgsize)
2240#endif /* _FFR_ANY_FREE_FS */
2241			   )
2242			{
2243				/*
2244				**  We perform this test again when the
2245				**  queue directory is selected, in collect.
2246				*/
2247
2248				usrerr("452 4.4.5 Insufficient disk space; try again later");
2249				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2250			}
2251			if (Errors > 0)
2252				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2253
2254			LogUsrErrs = true;
2255#if MILTER
2256			if (smtp.sm_milterlist && smtp.sm_milterize &&
2257			    !bitset(EF_DISCARD, e->e_flags))
2258			{
2259				char state;
2260				char *response;
2261
2262				response = milter_envfrom(args, e, &state);
2263				MILTER_REPLY("from");
2264			}
2265#endif /* MILTER */
2266			if (Errors > 0)
2267				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2268
2269			message("250 2.1.0 Sender ok");
2270			smtp.sm_gotmail = true;
2271		    }
2272		    SM_EXCEPT(exc, "[!F]*")
2273		    {
2274			/*
2275			**  An error occurred while processing a MAIL command.
2276			**  Jump to the common error handling code.
2277			*/
2278
2279			sm_exc_free(exc);
2280			goto undo_no_pm;
2281		    }
2282		    SM_END_TRY
2283			break;
2284
2285		  undo_no_pm:
2286			e->e_flags &= ~EF_PM_NOTIFY;
2287		  undo:
2288			break;
2289
2290		  case CMDRCPT:		/* rcpt -- designate recipient */
2291			DELAY_CONN("RCPT");
2292			if (!smtp.sm_gotmail)
2293			{
2294				usrerr("503 5.0.0 Need MAIL before RCPT");
2295				break;
2296			}
2297			SmtpPhase = "server RCPT";
2298		    SM_TRY
2299		    {
2300			QuickAbort = true;
2301			LogUsrErrs = true;
2302
2303			/* limit flooding of our machine */
2304			if (MaxRcptPerMsg > 0 &&
2305			    smtp.sm_nrcpts >= MaxRcptPerMsg)
2306			{
2307				/* sleep(1); / * slow down? */
2308				usrerr("452 4.5.3 Too many recipients");
2309				goto rcpt_done;
2310			}
2311
2312			if (e->e_sendmode != SM_DELIVER)
2313				e->e_flags |= EF_VRFYONLY;
2314
2315#if MILTER
2316			/*
2317			**  If the filter will be deleting recipients,
2318			**  don't expand them at RCPT time (in the call
2319			**  to recipient()).  If they are expanded, it
2320			**  is impossible for removefromlist() to figure
2321			**  out the expanded members of the original
2322			**  recipient and mark them as QS_DONTSEND.
2323			*/
2324
2325			if (milter_can_delrcpts())
2326				e->e_flags |= EF_VRFYONLY;
2327#endif /* MILTER */
2328
2329			p = skipword(p, "to");
2330			if (p == NULL)
2331				goto rcpt_done;
2332			macdefine(&e->e_macro, A_PERM,
2333				macid("{addr_type}"), "e r");
2334			a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', &delimptr,
2335				      e, true);
2336			macdefine(&e->e_macro, A_PERM,
2337				macid("{addr_type}"), NULL);
2338			if (BadRcptThrottle > 0 &&
2339			    n_badrcpts >= BadRcptThrottle)
2340			{
2341				if (LogLevel > 5 &&
2342				    n_badrcpts == BadRcptThrottle)
2343				{
2344					sm_syslog(LOG_INFO, e->e_id,
2345						  "%s: Possible SMTP RCPT flood, throttling.",
2346						  CurSmtpClient);
2347
2348					/* To avoid duplicated message */
2349					n_badrcpts++;
2350				}
2351
2352				/*
2353				**  Don't use exponential backoff for now.
2354				**  Some servers will open more connections
2355				**  and actually overload the receiver even
2356				**  more.
2357				*/
2358
2359				(void) sleep(1);
2360			}
2361			if (Errors > 0)
2362				goto rcpt_done;
2363			if (a == NULL)
2364			{
2365				usrerr("501 5.0.0 Missing recipient");
2366				goto rcpt_done;
2367			}
2368
2369			if (delimptr != NULL && *delimptr != '\0')
2370				*delimptr++ = '\0';
2371
2372			/* put resulting triple from parseaddr() into macros */
2373			if (a->q_mailer != NULL)
2374				macdefine(&e->e_macro, A_PERM,
2375					macid("{rcpt_mailer}"),
2376					a->q_mailer->m_name);
2377			else
2378				macdefine(&e->e_macro, A_PERM,
2379					macid("{rcpt_mailer}"), NULL);
2380			if (a->q_host != NULL)
2381				macdefine(&e->e_macro, A_PERM,
2382					macid("{rcpt_host}"), a->q_host);
2383			else
2384				macdefine(&e->e_macro, A_PERM,
2385					macid("{rcpt_host}"), "localhost");
2386			if (a->q_user != NULL)
2387				macdefine(&e->e_macro, A_PERM,
2388					macid("{rcpt_addr}"), a->q_user);
2389			else
2390				macdefine(&e->e_macro, A_PERM,
2391					macid("{rcpt_addr}"), NULL);
2392			if (Errors > 0)
2393				goto rcpt_done;
2394
2395			/* now parse ESMTP arguments */
2396			addr = p;
2397			argno = 0;
2398			args[argno++] = p;
2399			p = delimptr;
2400			while (p != NULL && *p != '\0')
2401			{
2402				char *kp;
2403				char *vp = NULL;
2404				char *equal = NULL;
2405
2406				/* locate the beginning of the keyword */
2407				SKIP_SPACE(p);
2408				if (*p == '\0')
2409					break;
2410				kp = p;
2411
2412				/* skip to the value portion */
2413				while ((isascii(*p) && isalnum(*p)) || *p == '-')
2414					p++;
2415				if (*p == '=')
2416				{
2417					equal = p;
2418					*p++ = '\0';
2419					vp = p;
2420
2421					/* skip to the end of the value */
2422					while (*p != '\0' && *p != ' ' &&
2423					       !(isascii(*p) && iscntrl(*p)) &&
2424					       *p != '=')
2425						p++;
2426				}
2427
2428				if (*p != '\0')
2429					*p++ = '\0';
2430
2431				if (tTd(19, 1))
2432					sm_dprintf("RCPT: got arg %s=\"%s\"\n", kp,
2433						vp == NULL ? "<null>" : vp);
2434
2435				rcpt_esmtp_args(a, kp, vp, e);
2436				if (equal != NULL)
2437					*equal = '=';
2438				args[argno++] = kp;
2439				if (argno >= MAXSMTPARGS - 1)
2440					usrerr("501 5.5.4 Too many parameters");
2441				if (Errors > 0)
2442					break;
2443			}
2444			args[argno] = NULL;
2445			if (Errors > 0)
2446				goto rcpt_done;
2447
2448			/* do config file checking of the recipient */
2449			macdefine(&e->e_macro, A_PERM,
2450				macid("{addr_type}"), "e r");
2451			if (rscheck("check_rcpt", addr,
2452				    NULL, e, RSF_RMCOMM|RSF_COUNT, 3,
2453				    NULL, e->e_id) != EX_OK ||
2454			    Errors > 0)
2455				goto rcpt_done;
2456			macdefine(&e->e_macro, A_PERM,
2457				macid("{addr_type}"), NULL);
2458
2459			/* If discarding, don't bother to verify user */
2460			if (bitset(EF_DISCARD, e->e_flags))
2461				a->q_state = QS_VERIFIED;
2462
2463#if MILTER
2464			if (smtp.sm_milterlist && smtp.sm_milterize &&
2465			    !bitset(EF_DISCARD, e->e_flags))
2466			{
2467				char state;
2468				char *response;
2469
2470				response = milter_envrcpt(args, e, &state);
2471				MILTER_REPLY("to");
2472			}
2473#endif /* MILTER */
2474
2475			macdefine(&e->e_macro, A_PERM,
2476				macid("{rcpt_mailer}"), NULL);
2477			macdefine(&e->e_macro, A_PERM,
2478				macid("{rcpt_host}"), NULL);
2479			macdefine(&e->e_macro, A_PERM,
2480				macid("{rcpt_addr}"), NULL);
2481			macdefine(&e->e_macro, A_PERM,
2482				macid("{dsn_notify}"), NULL);
2483			if (Errors > 0)
2484				goto rcpt_done;
2485
2486			/* save in recipient list after ESMTP mods */
2487			a = recipient(a, &e->e_sendqueue, 0, e);
2488			if (Errors > 0)
2489				goto rcpt_done;
2490
2491			/* no errors during parsing, but might be a duplicate */
2492			e->e_to = a->q_paddr;
2493			if (!QS_IS_BADADDR(a->q_state))
2494			{
2495				if (smtp.sm_nrcpts == 0)
2496					initsys(e);
2497				message("250 2.1.5 Recipient ok%s",
2498					QS_IS_QUEUEUP(a->q_state) ?
2499						" (will queue)" : "");
2500				smtp.sm_nrcpts++;
2501			}
2502			else
2503			{
2504				/* punt -- should keep message in ADDRESS.... */
2505				usrerr("550 5.1.1 Addressee unknown");
2506			}
2507		    rcpt_done:
2508			if (Errors > 0)
2509				++n_badrcpts;
2510		    }
2511		    SM_EXCEPT(exc, "[!F]*")
2512		    {
2513			/* An exception occurred while processing RCPT */
2514			e->e_flags &= ~(EF_FATALERRS|EF_PM_NOTIFY);
2515			++n_badrcpts;
2516		    }
2517		    SM_END_TRY
2518			break;
2519
2520		  case CMDDATA:		/* data -- text of mail */
2521			DELAY_CONN("DATA");
2522			smtp_data(&smtp, e);
2523			break;
2524
2525		  case CMDRSET:		/* rset -- reset state */
2526			if (tTd(94, 100))
2527				message("451 4.0.0 Test failure");
2528			else
2529				message("250 2.0.0 Reset state");
2530			CLEAR_STATE(cmdbuf);
2531#if _FFR_QUARANTINE
2532			/* restore connection quarantining */
2533			if (smtp.sm_quarmsg == NULL)
2534			{
2535				e->e_quarmsg = NULL;
2536				macdefine(&e->e_macro, A_PERM,
2537					  macid("{quarantine}"), "");
2538			}
2539			else
2540			{
2541				e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool,
2542								 smtp.sm_quarmsg);
2543				macdefine(&e->e_macro, A_PERM,
2544					  macid("{quarantine}"), e->e_quarmsg);
2545			}
2546#endif /* _FFR_QUARANTINE */
2547			break;
2548
2549		  case CMDVRFY:		/* vrfy -- verify address */
2550		  case CMDEXPN:		/* expn -- expand address */
2551			vrfy = c->cmd_code == CMDVRFY;
2552			DELAY_CONN(vrfy ? "VRFY" : "EXPN");
2553			if (tempfail)
2554			{
2555				if (LogLevel > 9)
2556					sm_syslog(LOG_INFO, e->e_id,
2557						  "SMTP %s command (%.100s) from %s tempfailed (due to previous checks)",
2558						  vrfy ? "VRFY" : "EXPN",
2559						  p, CurSmtpClient);
2560
2561				/* RFC 821 doesn't allow 4xy reply code */
2562				usrerr("550 5.7.1 Please try again later");
2563				break;
2564			}
2565			wt = checksmtpattack(&n_verifies, MAXVRFYCOMMANDS,
2566					     false, vrfy ? "VRFY" : "EXPN", e);
2567			previous = curtime();
2568			if ((vrfy && bitset(PRIV_NOVRFY, PrivacyFlags)) ||
2569			    (!vrfy && !bitset(SRV_OFFER_EXPN, features)))
2570			{
2571				if (vrfy)
2572					message("252 2.5.2 Cannot VRFY user; try RCPT to attempt delivery (or try finger)");
2573				else
2574					message("502 5.7.0 Sorry, we do not allow this operation");
2575				if (LogLevel > 5)
2576					sm_syslog(LOG_INFO, e->e_id,
2577						  "%s: %s [rejected]",
2578						  CurSmtpClient,
2579						  shortenstring(inp, MAXSHORTSTR));
2580				break;
2581			}
2582			else if (!gothello &&
2583				 bitset(vrfy ? PRIV_NEEDVRFYHELO : PRIV_NEEDEXPNHELO,
2584						PrivacyFlags))
2585			{
2586				usrerr("503 5.0.0 I demand that you introduce yourself first");
2587				break;
2588			}
2589			if (Errors > 0)
2590				break;
2591			if (LogLevel > 5)
2592				sm_syslog(LOG_INFO, e->e_id, "%s: %s",
2593					  CurSmtpClient,
2594					  shortenstring(inp, MAXSHORTSTR));
2595		    SM_TRY
2596		    {
2597			QuickAbort = true;
2598			vrfyqueue = NULL;
2599			if (vrfy)
2600				e->e_flags |= EF_VRFYONLY;
2601			while (*p != '\0' && isascii(*p) && isspace(*p))
2602				p++;
2603			if (*p == '\0')
2604			{
2605				usrerr("501 5.5.2 Argument required");
2606			}
2607			else
2608			{
2609				/* do config file checking of the address */
2610				if (rscheck(vrfy ? "check_vrfy" : "check_expn",
2611					    p, NULL, e, RSF_RMCOMM,
2612					    3, NULL, NOQID) != EX_OK ||
2613				    Errors > 0)
2614					sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2615				(void) sendtolist(p, NULLADDR, &vrfyqueue, 0, e);
2616			}
2617			if (wt > 0)
2618			{
2619				time_t t;
2620
2621				t = wt - (curtime() - previous);
2622				if (t > 0)
2623					(void) sleep(t);
2624			}
2625			if (Errors > 0)
2626				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2627			if (vrfyqueue == NULL)
2628			{
2629				usrerr("554 5.5.2 Nothing to %s", vrfy ? "VRFY" : "EXPN");
2630			}
2631			while (vrfyqueue != NULL)
2632			{
2633				if (!QS_IS_UNDELIVERED(vrfyqueue->q_state))
2634				{
2635					vrfyqueue = vrfyqueue->q_next;
2636					continue;
2637				}
2638
2639				/* see if there is more in the vrfy list */
2640				a = vrfyqueue;
2641				while ((a = a->q_next) != NULL &&
2642				       (!QS_IS_UNDELIVERED(a->q_state)))
2643					continue;
2644				printvrfyaddr(vrfyqueue, a == NULL, vrfy);
2645				vrfyqueue = a;
2646			}
2647		    }
2648		    SM_EXCEPT(exc, "[!F]*")
2649		    {
2650			/*
2651			**  An exception occurred while processing VRFY/EXPN
2652			*/
2653
2654			sm_exc_free(exc);
2655			goto undo;
2656		    }
2657		    SM_END_TRY
2658			break;
2659
2660		  case CMDETRN:		/* etrn -- force queue flush */
2661			DELAY_CONN("ETRN");
2662
2663			/* Don't leak queue information via debug flags */
2664			if (!bitset(SRV_OFFER_ETRN, features) || UseMSP ||
2665			    (RealUid != 0 && RealUid != TrustedUid &&
2666			     OpMode == MD_SMTP))
2667			{
2668				/* different message for MSA ? */
2669				message("502 5.7.0 Sorry, we do not allow this operation");
2670				if (LogLevel > 5)
2671					sm_syslog(LOG_INFO, e->e_id,
2672						  "%s: %s [rejected]",
2673						  CurSmtpClient,
2674						  shortenstring(inp, MAXSHORTSTR));
2675				break;
2676			}
2677			if (tempfail)
2678			{
2679				if (LogLevel > 9)
2680					sm_syslog(LOG_INFO, e->e_id,
2681						  "SMTP ETRN command (%.100s) from %s tempfailed (due to previous checks)",
2682						  p, CurSmtpClient);
2683				usrerr(MSG_TEMPFAIL);
2684				break;
2685			}
2686
2687			if (strlen(p) <= 0)
2688			{
2689				usrerr("500 5.5.2 Parameter required");
2690				break;
2691			}
2692
2693			/* crude way to avoid denial-of-service attacks */
2694			(void) checksmtpattack(&n_etrn, MAXETRNCOMMANDS, true,
2695					     "ETRN", e);
2696
2697			/*
2698			**  Do config file checking of the parameter.
2699			**  Even though we have srv_features now, we still
2700			**  need this ruleset because the former is called
2701			**  when the connection has been established, while
2702			**  this ruleset is called when the command is
2703			**  actually issued and therefore has all information
2704			**  available to make a decision.
2705			*/
2706
2707			if (rscheck("check_etrn", p, NULL, e,
2708				    RSF_RMCOMM, 3, NULL, NOQID) != EX_OK ||
2709			    Errors > 0)
2710				break;
2711
2712			if (LogLevel > 5)
2713				sm_syslog(LOG_INFO, e->e_id,
2714					  "%s: ETRN %s", CurSmtpClient,
2715					  shortenstring(p, MAXSHORTSTR));
2716
2717			id = p;
2718			if (*id == '#')
2719			{
2720				int i, qgrp;
2721
2722				id++;
2723				qgrp = name2qid(id);
2724				if (!ISVALIDQGRP(qgrp))
2725				{
2726					usrerr("459 4.5.4 Queue %s unknown",
2727					       id);
2728					break;
2729				}
2730				for (i = 0; i < NumQueue && Queue[i] != NULL;
2731				     i++)
2732					Queue[i]->qg_nextrun = (time_t) -1;
2733				Queue[qgrp]->qg_nextrun = 0;
2734				ok = run_work_group(Queue[qgrp]->qg_wgrp,
2735						    RWG_FORK|RWG_FORCE);
2736				if (ok && Errors == 0)
2737					message("250 2.0.0 Queuing for queue group %s started", id);
2738				break;
2739			}
2740
2741			if (*id == '@')
2742				id++;
2743			else
2744				*--id = '@';
2745
2746			new = (QUEUE_CHAR *) sm_malloc(sizeof(QUEUE_CHAR));
2747			if (new == NULL)
2748			{
2749				syserr("500 5.5.0 ETRN out of memory");
2750				break;
2751			}
2752			new->queue_match = id;
2753			new->queue_negate = false;
2754			new->queue_next = NULL;
2755			QueueLimitRecipient = new;
2756			ok = runqueue(true, false, false, true);
2757			sm_free(QueueLimitRecipient); /* XXX */
2758			QueueLimitRecipient = NULL;
2759			if (ok && Errors == 0)
2760				message("250 2.0.0 Queuing for node %s started", p);
2761			break;
2762
2763		  case CMDHELP:		/* help -- give user info */
2764			DELAY_CONN("HELP");
2765			help(p, e);
2766			break;
2767
2768		  case CMDNOOP:		/* noop -- do nothing */
2769			DELAY_CONN("NOOP");
2770			(void) checksmtpattack(&n_noop, MAXNOOPCOMMANDS, true,
2771					       "NOOP", e);
2772			message("250 2.0.0 OK");
2773			break;
2774
2775		  case CMDQUIT:		/* quit -- leave mail */
2776			message("221 2.0.0 %s closing connection", MyHostName);
2777#if PIPELINING
2778			(void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
2779#endif /* PIPELINING */
2780
2781			if (smtp.sm_nrcpts > 0)
2782				logundelrcpts(e, "aborted by sender", 9, false);
2783
2784			/* arrange to ignore any current send list */
2785			e->e_sendqueue = NULL;
2786
2787#if STARTTLS
2788			/* shutdown TLS connection */
2789			if (tls_active)
2790			{
2791				(void) endtls(srv_ssl, "server");
2792				tls_active = false;
2793			}
2794#endif /* STARTTLS */
2795#if SASL
2796			if (authenticating == SASL_IS_AUTH)
2797			{
2798				sasl_dispose(&conn);
2799				authenticating = SASL_NOT_AUTH;
2800				/* XXX sasl_done(); this is a child */
2801			}
2802#endif /* SASL */
2803
2804doquit:
2805			/* avoid future 050 messages */
2806			disconnect(1, e);
2807
2808#if MILTER
2809			/* close out milter filters */
2810			milter_quit(e);
2811#endif /* MILTER */
2812
2813			if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
2814				logsender(e, NULL);
2815			e->e_flags &= ~EF_LOGSENDER;
2816
2817			if (lognullconnection && LogLevel > 5 &&
2818			    nullserver == NULL)
2819			{
2820				char *d;
2821
2822				d = macvalue(macid("{daemon_name}"), e);
2823				if (d == NULL)
2824					d = "stdin";
2825
2826				/*
2827				**  even though this id is "bogus", it makes
2828				**  it simpler to "grep" related events, e.g.,
2829				**  timeouts for the same connection.
2830				*/
2831
2832				sm_syslog(LOG_INFO, e->e_id,
2833					  "%s did not issue MAIL/EXPN/VRFY/ETRN during connection to %s",
2834					  CurSmtpClient, d);
2835			}
2836			if (tTd(93, 100))
2837			{
2838				/* return to handle next connection */
2839				return;
2840			}
2841			finis(true, true, ExitStat);
2842			/* NOTREACHED */
2843
2844		  case CMDVERB:		/* set verbose mode */
2845			DELAY_CONN("VERB");
2846			if (!bitset(SRV_OFFER_EXPN, features) ||
2847			    !bitset(SRV_OFFER_VERB, features))
2848			{
2849				/* this would give out the same info */
2850				message("502 5.7.0 Verbose unavailable");
2851				break;
2852			}
2853			(void) checksmtpattack(&n_noop, MAXNOOPCOMMANDS, true,
2854					       "VERB", e);
2855			Verbose = 1;
2856			set_delivery_mode(SM_DELIVER, e);
2857			message("250 2.0.0 Verbose mode");
2858			break;
2859
2860#if SMTPDEBUG
2861		  case CMDDBGQSHOW:	/* show queues */
2862			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
2863					     "Send Queue=");
2864			printaddr(e->e_sendqueue, true);
2865			break;
2866
2867		  case CMDDBGDEBUG:	/* set debug mode */
2868			tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
2869			tTflag(p);
2870			message("200 2.0.0 Debug set");
2871			break;
2872
2873#else /* SMTPDEBUG */
2874		  case CMDDBGQSHOW:	/* show queues */
2875		  case CMDDBGDEBUG:	/* set debug mode */
2876#endif /* SMTPDEBUG */
2877		  case CMDLOGBOGUS:	/* bogus command */
2878			DELAY_CONN("Bogus");
2879			if (LogLevel > 0)
2880				sm_syslog(LOG_CRIT, e->e_id,
2881					  "\"%s\" command from %s (%.100s)",
2882					  c->cmd_name, CurSmtpClient,
2883					  anynet_ntoa(&RealHostAddr));
2884			/* FALLTHROUGH */
2885
2886		  case CMDERROR:	/* unknown command */
2887#if MAXBADCOMMANDS > 0
2888			if (++n_badcmds > MAXBADCOMMANDS)
2889			{
2890				message("421 4.7.0 %s Too many bad commands; closing connection",
2891					MyHostName);
2892
2893				/* arrange to ignore any current send list */
2894				e->e_sendqueue = NULL;
2895				goto doquit;
2896			}
2897#endif /* MAXBADCOMMANDS > 0 */
2898
2899			usrerr("500 5.5.1 Command unrecognized: \"%s\"",
2900			       shortenstring(inp, MAXSHORTSTR));
2901			break;
2902
2903		  case CMDUNIMPL:
2904			DELAY_CONN("Unimpl");
2905			usrerr("502 5.5.1 Command not implemented: \"%s\"",
2906			       shortenstring(inp, MAXSHORTSTR));
2907			break;
2908
2909		  default:
2910			DELAY_CONN("default");
2911			errno = 0;
2912			syserr("500 5.5.0 smtp: unknown code %d", c->cmd_code);
2913			break;
2914		}
2915#if SASL
2916		}
2917#endif /* SASL */
2918	    }
2919	    SM_EXCEPT(exc, "[!F]*")
2920	    {
2921		/*
2922		**  The only possible exception is "E:mta.quickabort".
2923		**  There is nothing to do except fall through and loop.
2924		*/
2925	    }
2926	    SM_END_TRY
2927	}
2928}
2929/*
2930**  SMTP_DATA -- implement the SMTP DATA command.
2931**
2932**	Parameters:
2933**		smtp -- status of SMTP connection.
2934**		e -- envelope.
2935**
2936**	Returns:
2937**		none.
2938**
2939**	Side Effects:
2940**		possibly sends message.
2941*/
2942
2943static void
2944smtp_data(smtp, e)
2945	SMTP_T *smtp;
2946	ENVELOPE *e;
2947{
2948#if MILTER
2949	bool milteraccept;
2950#endif /* MILTER */
2951	bool aborting;
2952	bool doublequeue;
2953	ADDRESS *a;
2954	ENVELOPE *ee;
2955	char *id;
2956	char *oldid;
2957	char buf[32];
2958
2959	SmtpPhase = "server DATA";
2960	if (!smtp->sm_gotmail)
2961	{
2962		usrerr("503 5.0.0 Need MAIL command");
2963		return;
2964	}
2965	else if (smtp->sm_nrcpts <= 0)
2966	{
2967		usrerr("503 5.0.0 Need RCPT (recipient)");
2968		return;
2969	}
2970	(void) sm_snprintf(buf, sizeof buf, "%u", smtp->sm_nrcpts);
2971	if (rscheck("check_data", buf, NULL, e,
2972		    RSF_RMCOMM|RSF_UNSTRUCTURED|RSF_COUNT, 3, NULL,
2973		    e->e_id) != EX_OK)
2974		return;
2975
2976	/* put back discard bit */
2977	if (smtp->sm_discard)
2978		e->e_flags |= EF_DISCARD;
2979
2980	/* check to see if we need to re-expand aliases */
2981	/* also reset QS_BADADDR on already-diagnosted addrs */
2982	doublequeue = false;
2983	for (a = e->e_sendqueue; a != NULL; a = a->q_next)
2984	{
2985		if (QS_IS_VERIFIED(a->q_state) &&
2986		    !bitset(EF_DISCARD, e->e_flags))
2987		{
2988			/* need to re-expand aliases */
2989			doublequeue = true;
2990		}
2991		if (QS_IS_BADADDR(a->q_state))
2992		{
2993			/* make this "go away" */
2994			a->q_state = QS_DONTSEND;
2995		}
2996	}
2997
2998	/* collect the text of the message */
2999	SmtpPhase = "collect";
3000	buffer_errors();
3001
3002#if _FFR_ADAPTIVE_EOL
3003	/* triggers error in collect, disabled for now */
3004	if (smtp->sm_crlf)
3005		e->e_flags |= EF_NL_NOT_EOL;
3006#endif /* _FFR_ADAPTIVE_EOL */
3007
3008	collect(InChannel, true, NULL, e);
3009
3010	/* redefine message size */
3011	(void) sm_snprintf(buf, sizeof buf, "%ld", e->e_msgsize);
3012	macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), buf);
3013
3014#if _FFR_CHECK_EOM
3015	/* rscheck() will set Errors or EF_DISCARD if it trips */
3016	(void) rscheck("check_eom", buf, NULL, e, RSF_UNSTRUCTURED|RSF_COUNT,
3017		       3, NULL, e->e_id);
3018#endif /* _FFR_CHECK_EOM */
3019
3020#if MILTER
3021	milteraccept = true;
3022	if (smtp->sm_milterlist && smtp->sm_milterize &&
3023	    Errors <= 0 &&
3024	    !bitset(EF_DISCARD, e->e_flags))
3025	{
3026		char state;
3027		char *response;
3028
3029		response = milter_data(e, &state);
3030		switch (state)
3031		{
3032		  case SMFIR_REPLYCODE:
3033			if (MilterLogLevel > 3)
3034				sm_syslog(LOG_INFO, e->e_id,
3035					  "Milter: data, reject=%s",
3036					  response);
3037			milteraccept = false;
3038			usrerr(response);
3039			break;
3040
3041		  case SMFIR_REJECT:
3042			milteraccept = false;
3043			if (MilterLogLevel > 3)
3044				sm_syslog(LOG_INFO, e->e_id,
3045					  "Milter: data, reject=554 5.7.1 Command rejected");
3046			usrerr("554 5.7.1 Command rejected");
3047			break;
3048
3049		  case SMFIR_DISCARD:
3050			if (MilterLogLevel > 3)
3051				sm_syslog(LOG_INFO, e->e_id,
3052					  "Milter: data, discard");
3053			milteraccept = false;
3054			e->e_flags |= EF_DISCARD;
3055			break;
3056
3057		  case SMFIR_TEMPFAIL:
3058			if (MilterLogLevel > 3)
3059				sm_syslog(LOG_INFO, e->e_id,
3060					  "Milter: data, reject=%s",
3061					  MSG_TEMPFAIL);
3062			milteraccept = false;
3063			usrerr(MSG_TEMPFAIL);
3064			break;
3065		}
3066		if (response != NULL)
3067			sm_free(response);
3068	}
3069
3070	/* Milter may have changed message size */
3071	(void) sm_snprintf(buf, sizeof buf, "%ld", e->e_msgsize);
3072	macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), buf);
3073
3074	/* abort message filters that didn't get the body & log msg is OK */
3075	if (smtp->sm_milterlist && smtp->sm_milterize)
3076	{
3077		milter_abort(e);
3078		if (milteraccept && MilterLogLevel > 9)
3079			sm_syslog(LOG_INFO, e->e_id, "Milter accept: message");
3080	}
3081#endif /* MILTER */
3082
3083#if _FFR_QUARANTINE
3084	/* Check if quarantining stats should be updated */
3085	if (e->e_quarmsg != NULL)
3086		markstats(e, NULL, STATS_QUARANTINE);
3087#endif /* _FFR_QUARANTINE */
3088
3089	/*
3090	**  If a header/body check (header checks or milter)
3091	**  set EF_DISCARD, don't queueup the message --
3092	**  that would lose the EF_DISCARD bit and deliver
3093	**  the message.
3094	*/
3095
3096	if (bitset(EF_DISCARD, e->e_flags))
3097		doublequeue = false;
3098
3099	aborting = Errors > 0;
3100	if (!aborting &&
3101#if _FFR_QUARANTINE
3102	    (QueueMode == QM_QUARANTINE || e->e_quarmsg == NULL) &&
3103#endif /* _FFR_QUARANTINE */
3104	    !split_by_recipient(e))
3105		aborting = bitset(EF_FATALERRS, e->e_flags);
3106
3107	if (aborting)
3108	{
3109		/* Log who the mail would have gone to */
3110		logundelrcpts(e, e->e_message, 8, false);
3111		flush_errors(true);
3112		buffer_errors();
3113		goto abortmessage;
3114	}
3115
3116	/* from now on, we have to operate silently */
3117	buffer_errors();
3118
3119#if 0
3120	/*
3121	**  Clear message, it may contain an error from the SMTP dialogue.
3122	**  This error must not show up in the queue.
3123	**	Some error message should show up, e.g., alias database
3124	**	not available, but others shouldn't, e.g., from check_rcpt.
3125	*/
3126
3127	e->e_message = NULL;
3128#endif /* 0 */
3129
3130	/*
3131	**  Arrange to send to everyone.
3132	**	If sending to multiple people, mail back
3133	**		errors rather than reporting directly.
3134	**	In any case, don't mail back errors for
3135	**		anything that has happened up to
3136	**		now (the other end will do this).
3137	**	Truncate our transcript -- the mail has gotten
3138	**		to us successfully, and if we have
3139	**		to mail this back, it will be easier
3140	**		on the reader.
3141	**	Then send to everyone.
3142	**	Finally give a reply code.  If an error has
3143	**		already been given, don't mail a
3144	**		message back.
3145	**	We goose error returns by clearing error bit.
3146	*/
3147
3148	SmtpPhase = "delivery";
3149	(void) sm_io_setinfo(e->e_xfp, SM_BF_TRUNCATE, NULL);
3150	id = e->e_id;
3151
3152#if NAMED_BIND
3153	_res.retry = TimeOuts.res_retry[RES_TO_FIRST];
3154	_res.retrans = TimeOuts.res_retrans[RES_TO_FIRST];
3155#endif /* NAMED_BIND */
3156
3157	for (ee = e; ee != NULL; ee = ee->e_sibling)
3158	{
3159		/* make sure we actually do delivery */
3160		ee->e_flags &= ~EF_CLRQUEUE;
3161
3162		/* from now on, operate silently */
3163		ee->e_errormode = EM_MAIL;
3164
3165		if (doublequeue)
3166		{
3167			/* make sure it is in the queue */
3168			queueup(ee, false, true);
3169		}
3170		else
3171		{
3172			/* send to all recipients */
3173			sendall(ee, SM_DEFAULT);
3174		}
3175		ee->e_to = NULL;
3176	}
3177
3178	/* put back id for SMTP logging in putoutmsg() */
3179	oldid = CurEnv->e_id;
3180	CurEnv->e_id = id;
3181
3182	/* issue success message */
3183	message("250 2.0.0 %s Message accepted for delivery", id);
3184	CurEnv->e_id = oldid;
3185
3186	/* if we just queued, poke it */
3187	if (doublequeue)
3188	{
3189		bool anything_to_send = false;
3190
3191		sm_getla();
3192		for (ee = e; ee != NULL; ee = ee->e_sibling)
3193		{
3194			if (WILL_BE_QUEUED(ee->e_sendmode))
3195				continue;
3196			if (shouldqueue(ee->e_msgpriority, ee->e_ctime))
3197			{
3198				ee->e_sendmode = SM_QUEUE;
3199				continue;
3200			}
3201#if _FFR_QUARANTINE
3202			else if (QueueMode != QM_QUARANTINE &&
3203				 ee->e_quarmsg != NULL)
3204			{
3205				ee->e_sendmode = SM_QUEUE;
3206				continue;
3207			}
3208#endif /* _FFR_QUARANTINE */
3209			anything_to_send = true;
3210
3211			/* close all the queue files */
3212			closexscript(ee);
3213			if (ee->e_dfp != NULL)
3214			{
3215				(void) sm_io_close(ee->e_dfp, SM_TIME_DEFAULT);
3216				ee->e_dfp = NULL;
3217			}
3218			unlockqueue(ee);
3219		}
3220		if (anything_to_send)
3221		{
3222#if PIPELINING
3223			/*
3224			**  XXX if we don't do this, we get 250 twice
3225			**	because it is also flushed in the child.
3226			*/
3227
3228			(void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
3229#endif /* PIPELINING */
3230			(void) doworklist(e, true, true);
3231		}
3232	}
3233
3234  abortmessage:
3235	if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
3236		logsender(e, NULL);
3237	e->e_flags &= ~EF_LOGSENDER;
3238
3239	/* clean up a bit */
3240	smtp->sm_gotmail = false;
3241
3242	/*
3243	**  Call dropenvelope if and only if the envelope is *not*
3244	**  being processed by the child process forked by doworklist().
3245	*/
3246
3247	if (aborting || bitset(EF_DISCARD, e->e_flags))
3248		dropenvelope(e, true, false);
3249	else
3250	{
3251		for (ee = e; ee != NULL; ee = ee->e_sibling)
3252		{
3253#if _FFR_QUARANTINE
3254			if (!doublequeue &&
3255			    QueueMode != QM_QUARANTINE &&
3256			    ee->e_quarmsg != NULL)
3257			{
3258				dropenvelope(ee, true, false);
3259				continue;
3260			}
3261#endif /* _FFR_QUARANTINE */
3262			if (WILL_BE_QUEUED(ee->e_sendmode))
3263				dropenvelope(ee, true, false);
3264		}
3265	}
3266	sm_rpool_free(e->e_rpool);
3267
3268	/*
3269	**  At this point, e == &MainEnvelope, but if we did splitting,
3270	**  then CurEnv may point to an envelope structure that was just
3271	**  freed with the rpool.  So reset CurEnv *before* calling
3272	**  newenvelope.
3273	*/
3274
3275	CurEnv = e;
3276	newenvelope(e, e, sm_rpool_new_x(NULL));
3277	e->e_flags = BlankEnvelope.e_flags;
3278
3279#if _FFR_QUARANTINE
3280	/* restore connection quarantining */
3281	if (smtp->sm_quarmsg == NULL)
3282	{
3283		e->e_quarmsg = NULL;
3284		macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), "");
3285	}
3286	else
3287	{
3288		e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool, smtp->sm_quarmsg);
3289		macdefine(&e->e_macro, A_PERM,
3290			  macid("{quarantine}"), e->e_quarmsg);
3291	}
3292#endif /* _FFR_QUARANTINE */
3293}
3294/*
3295**  LOGUNDELRCPTS -- log undelivered (or all) recipients.
3296**
3297**	Parameters:
3298**		e -- envelope.
3299**		msg -- message for Stat=
3300**		level -- log level.
3301**		all -- log all recipients.
3302**
3303**	Returns:
3304**		none.
3305**
3306**	Side Effects:
3307**		logs undelivered (or all) recipients
3308*/
3309
3310void
3311logundelrcpts(e, msg, level, all)
3312	ENVELOPE *e;
3313	char *msg;
3314	int level;
3315	bool all;
3316{
3317	ADDRESS *a;
3318
3319	if (LogLevel <= level || msg == NULL || *msg == '\0')
3320		return;
3321
3322	/* Clear $h so relay= doesn't get mislogged by logdelivery() */
3323	macdefine(&e->e_macro, A_PERM, 'h', NULL);
3324
3325	/* Log who the mail would have gone to */
3326	for (a = e->e_sendqueue; a != NULL; a = a->q_next)
3327	{
3328		if (!QS_IS_UNDELIVERED(a->q_state) && !all)
3329			continue;
3330		e->e_to = a->q_paddr;
3331		logdelivery(NULL, NULL, a->q_status, msg, NULL,
3332			    (time_t) 0, e);
3333	}
3334	e->e_to = NULL;
3335}
3336/*
3337**  CHECKSMTPATTACK -- check for denial-of-service attack by repetition
3338**
3339**	Parameters:
3340**		pcounter -- pointer to a counter for this command.
3341**		maxcount -- maximum value for this counter before we
3342**			slow down.
3343**		waitnow -- sleep now (in this routine)?
3344**		cname -- command name for logging.
3345**		e -- the current envelope.
3346**
3347**	Returns:
3348**		time to wait.
3349**
3350**	Side Effects:
3351**		Slows down if we seem to be under attack.
3352*/
3353
3354static time_t
3355checksmtpattack(pcounter, maxcount, waitnow, cname, e)
3356	volatile unsigned int *pcounter;
3357	int maxcount;
3358	bool waitnow;
3359	char *cname;
3360	ENVELOPE *e;
3361{
3362	if (maxcount <= 0)	/* no limit */
3363		return (time_t) 0;
3364
3365	if (++(*pcounter) >= maxcount)
3366	{
3367		time_t s;
3368
3369		if (*pcounter == maxcount && LogLevel > 5)
3370		{
3371			sm_syslog(LOG_INFO, e->e_id,
3372				  "%s: possible SMTP attack: command=%.40s, count=%u",
3373				  CurSmtpClient, cname, *pcounter);
3374		}
3375		s = 1 << (*pcounter - maxcount);
3376		if (s >= MAXTIMEOUT || s <= 0)
3377			s = MAXTIMEOUT;
3378
3379		/* sleep at least 1 second before returning */
3380		(void) sleep(*pcounter / maxcount);
3381		s -= *pcounter / maxcount;
3382		if (waitnow)
3383		{
3384			(void) sleep(s);
3385			return 0;
3386		}
3387		return s;
3388	}
3389	return (time_t) 0;
3390}
3391/*
3392**  SETUP_SMTPD_IO -- setup I/O fd correctly for the SMTP server
3393**
3394**	Parameters:
3395**		none.
3396**
3397**	Returns:
3398**		nothing.
3399**
3400**	Side Effects:
3401**		may change I/O fd.
3402*/
3403
3404static void
3405setup_smtpd_io()
3406{
3407	int inchfd, outchfd, outfd;
3408
3409	inchfd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL);
3410	outchfd  = sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL);
3411	outfd = sm_io_getinfo(smioout, SM_IO_WHAT_FD, NULL);
3412	if (outchfd != outfd)
3413	{
3414		/* arrange for debugging output to go to remote host */
3415		(void) dup2(outchfd, outfd);
3416	}
3417
3418	/*
3419	**  if InChannel and OutChannel are stdin/stdout
3420	**  and connected to ttys
3421	**  and fcntl(STDIN, F_SETFL, O_NONBLOCKING) also changes STDOUT,
3422	**  then "chain" them together.
3423	*/
3424
3425	if (inchfd == STDIN_FILENO && outchfd == STDOUT_FILENO &&
3426	    isatty(inchfd) && isatty(outchfd))
3427	{
3428		int inmode, outmode;
3429
3430		inmode = fcntl(inchfd, F_GETFL, 0);
3431		if (inmode == -1)
3432		{
3433			if (LogLevel > 11)
3434				sm_syslog(LOG_INFO, NOQID,
3435					"fcntl(inchfd, F_GETFL) failed: %s",
3436					sm_errstring(errno));
3437			return;
3438		}
3439		outmode = fcntl(outchfd, F_GETFL, 0);
3440		if (outmode == -1)
3441		{
3442			if (LogLevel > 11)
3443				sm_syslog(LOG_INFO, NOQID,
3444					"fcntl(outchfd, F_GETFL) failed: %s",
3445					sm_errstring(errno));
3446			return;
3447		}
3448		if (bitset(O_NONBLOCK, inmode) ||
3449		    bitset(O_NONBLOCK, outmode) ||
3450		    fcntl(inchfd, F_SETFL, inmode | O_NONBLOCK) == -1)
3451			return;
3452		outmode = fcntl(outchfd, F_GETFL, 0);
3453		if (outmode != -1 && bitset(O_NONBLOCK, outmode))
3454		{
3455			/* changing InChannel also changes OutChannel */
3456			sm_io_automode(OutChannel, InChannel);
3457			if (tTd(97, 4) && LogLevel > 9)
3458				sm_syslog(LOG_INFO, NOQID,
3459					  "set automode for I (%d)/O (%d) in SMTP server",
3460					  inchfd, outchfd);
3461		}
3462
3463		/* undo change of inchfd */
3464		(void) fcntl(inchfd, F_SETFL, inmode);
3465	}
3466}
3467/*
3468**  SKIPWORD -- skip a fixed word.
3469**
3470**	Parameters:
3471**		p -- place to start looking.
3472**		w -- word to skip.
3473**
3474**	Returns:
3475**		p following w.
3476**		NULL on error.
3477**
3478**	Side Effects:
3479**		clobbers the p data area.
3480*/
3481
3482static char *
3483skipword(p, w)
3484	register char *volatile p;
3485	char *w;
3486{
3487	register char *q;
3488	char *firstp = p;
3489
3490	/* find beginning of word */
3491	SKIP_SPACE(p);
3492	q = p;
3493
3494	/* find end of word */
3495	while (*p != '\0' && *p != ':' && !(isascii(*p) && isspace(*p)))
3496		p++;
3497	while (isascii(*p) && isspace(*p))
3498		*p++ = '\0';
3499	if (*p != ':')
3500	{
3501	  syntax:
3502		usrerr("501 5.5.2 Syntax error in parameters scanning \"%s\"",
3503			shortenstring(firstp, MAXSHORTSTR));
3504		return NULL;
3505	}
3506	*p++ = '\0';
3507	SKIP_SPACE(p);
3508
3509	if (*p == '\0')
3510		goto syntax;
3511
3512	/* see if the input word matches desired word */
3513	if (sm_strcasecmp(q, w))
3514		goto syntax;
3515
3516	return p;
3517}
3518/*
3519**  MAIL_ESMTP_ARGS -- process ESMTP arguments from MAIL line
3520**
3521**	Parameters:
3522**		kp -- the parameter key.
3523**		vp -- the value of that parameter.
3524**		e -- the envelope.
3525**
3526**	Returns:
3527**		none.
3528*/
3529
3530static void
3531mail_esmtp_args(kp, vp, e)
3532	char *kp;
3533	char *vp;
3534	ENVELOPE *e;
3535{
3536	if (sm_strcasecmp(kp, "size") == 0)
3537	{
3538		if (vp == NULL)
3539		{
3540			usrerr("501 5.5.2 SIZE requires a value");
3541			/* NOTREACHED */
3542		}
3543		macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), vp);
3544		errno = 0;
3545		e->e_msgsize = strtol(vp, (char **) NULL, 10);
3546		if (e->e_msgsize == LONG_MAX && errno == ERANGE)
3547		{
3548			usrerr("552 5.2.3 Message size exceeds maximum value");
3549			/* NOTREACHED */
3550		}
3551		if (e->e_msgsize < 0)
3552		{
3553			usrerr("552 5.2.3 Message size invalid");
3554			/* NOTREACHED */
3555		}
3556	}
3557	else if (sm_strcasecmp(kp, "body") == 0)
3558	{
3559		if (vp == NULL)
3560		{
3561			usrerr("501 5.5.2 BODY requires a value");
3562			/* NOTREACHED */
3563		}
3564		else if (sm_strcasecmp(vp, "8bitmime") == 0)
3565		{
3566			SevenBitInput = false;
3567		}
3568		else if (sm_strcasecmp(vp, "7bit") == 0)
3569		{
3570			SevenBitInput = true;
3571		}
3572		else
3573		{
3574			usrerr("501 5.5.4 Unknown BODY type %s", vp);
3575			/* NOTREACHED */
3576		}
3577		e->e_bodytype = sm_rpool_strdup_x(e->e_rpool, vp);
3578	}
3579	else if (sm_strcasecmp(kp, "envid") == 0)
3580	{
3581		if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
3582		{
3583			usrerr("504 5.7.0 Sorry, ENVID not supported, we do not allow DSN");
3584			/* NOTREACHED */
3585		}
3586		if (vp == NULL)
3587		{
3588			usrerr("501 5.5.2 ENVID requires a value");
3589			/* NOTREACHED */
3590		}
3591		if (!xtextok(vp))
3592		{
3593			usrerr("501 5.5.4 Syntax error in ENVID parameter value");
3594			/* NOTREACHED */
3595		}
3596		if (e->e_envid != NULL)
3597		{
3598			usrerr("501 5.5.0 Duplicate ENVID parameter");
3599			/* NOTREACHED */
3600		}
3601		e->e_envid = sm_rpool_strdup_x(e->e_rpool, vp);
3602		macdefine(&e->e_macro, A_PERM,
3603			macid("{dsn_envid}"), e->e_envid);
3604	}
3605	else if (sm_strcasecmp(kp, "ret") == 0)
3606	{
3607		if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
3608		{
3609			usrerr("504 5.7.0 Sorry, RET not supported, we do not allow DSN");
3610			/* NOTREACHED */
3611		}
3612		if (vp == NULL)
3613		{
3614			usrerr("501 5.5.2 RET requires a value");
3615			/* NOTREACHED */
3616		}
3617		if (bitset(EF_RET_PARAM, e->e_flags))
3618		{
3619			usrerr("501 5.5.0 Duplicate RET parameter");
3620			/* NOTREACHED */
3621		}
3622		e->e_flags |= EF_RET_PARAM;
3623		if (sm_strcasecmp(vp, "hdrs") == 0)
3624			e->e_flags |= EF_NO_BODY_RETN;
3625		else if (sm_strcasecmp(vp, "full") != 0)
3626		{
3627			usrerr("501 5.5.2 Bad argument \"%s\" to RET", vp);
3628			/* NOTREACHED */
3629		}
3630		macdefine(&e->e_macro, A_TEMP, macid("{dsn_ret}"), vp);
3631	}
3632#if SASL
3633	else if (sm_strcasecmp(kp, "auth") == 0)
3634	{
3635		int len;
3636		char *q;
3637		char *auth_param;	/* the value of the AUTH=x */
3638		bool saveQuickAbort = QuickAbort;
3639		bool saveSuprErrs = SuprErrs;
3640		bool saveExitStat = ExitStat;
3641		char pbuf[256];
3642
3643		if (vp == NULL)
3644		{
3645			usrerr("501 5.5.2 AUTH= requires a value");
3646			/* NOTREACHED */
3647		}
3648		if (e->e_auth_param != NULL)
3649		{
3650			usrerr("501 5.5.0 Duplicate AUTH parameter");
3651			/* NOTREACHED */
3652		}
3653		if ((q = strchr(vp, ' ')) != NULL)
3654			len = q - vp + 1;
3655		else
3656			len = strlen(vp) + 1;
3657		auth_param = xalloc(len);
3658		(void) sm_strlcpy(auth_param, vp, len);
3659		if (!xtextok(auth_param))
3660		{
3661			usrerr("501 5.5.4 Syntax error in AUTH parameter value");
3662			/* just a warning? */
3663			/* NOTREACHED */
3664		}
3665
3666		/* XXX this might be cut off */
3667		(void) sm_strlcpy(pbuf, xuntextify(auth_param), sizeof pbuf);
3668		/* xalloc() the buffer instead? */
3669
3670		/* XXX define this always or only if trusted? */
3671		macdefine(&e->e_macro, A_TEMP, macid("{auth_author}"), pbuf);
3672
3673		/*
3674		**  call Strust_auth to find out whether
3675		**  auth_param is acceptable (trusted)
3676		**  we shouldn't trust it if not authenticated
3677		**  (required by RFC, leave it to ruleset?)
3678		*/
3679
3680		SuprErrs = true;
3681		QuickAbort = false;
3682		if (strcmp(auth_param, "<>") != 0 &&
3683		     (rscheck("trust_auth", pbuf, NULL, e, RSF_RMCOMM,
3684			      9, NULL, NOQID) != EX_OK || Errors > 0))
3685		{
3686			if (tTd(95, 8))
3687			{
3688				q = e->e_auth_param;
3689				sm_dprintf("auth=\"%.100s\" not trusted user=\"%.100s\"\n",
3690					pbuf, (q == NULL) ? "" : q);
3691			}
3692
3693			/* not trusted */
3694			e->e_auth_param = "<>";
3695# if _FFR_AUTH_PASSING
3696			macdefine(&BlankEnvelope.e_macro, A_PERM,
3697				  macid("{auth_author}"), NULL);
3698# endif /* _FFR_AUTH_PASSING */
3699		}
3700		else
3701		{
3702			if (tTd(95, 8))
3703				sm_dprintf("auth=\"%.100s\" trusted\n", pbuf);
3704			e->e_auth_param = sm_rpool_strdup_x(e->e_rpool,
3705							    auth_param);
3706		}
3707		sm_free(auth_param); /* XXX */
3708
3709		/* reset values */
3710		Errors = 0;
3711		QuickAbort = saveQuickAbort;
3712		SuprErrs = saveSuprErrs;
3713		ExitStat = saveExitStat;
3714	}
3715#endif /* SASL */
3716#define PRTCHAR(c)	((isascii(c) && isprint(c)) ? (c) : '?')
3717
3718	/*
3719	**  "by" is only accepted if DeliverByMin >= 0.
3720	**  We maybe could add this to the list of server_features.
3721	*/
3722
3723	else if (sm_strcasecmp(kp, "by") == 0 && DeliverByMin >= 0)
3724	{
3725		char *s;
3726
3727		if (vp == NULL)
3728		{
3729			usrerr("501 5.5.2 BY= requires a value");
3730			/* NOTREACHED */
3731		}
3732		errno = 0;
3733		e->e_deliver_by = strtol(vp, &s, 10);
3734		if (e->e_deliver_by == LONG_MIN ||
3735		    e->e_deliver_by == LONG_MAX ||
3736		    e->e_deliver_by > 999999999l ||
3737		    e->e_deliver_by < -999999999l)
3738		{
3739			usrerr("501 5.5.2 BY=%s out of range", vp);
3740			/* NOTREACHED */
3741		}
3742		if (s == NULL || *s != ';')
3743		{
3744			usrerr("501 5.5.2 BY= missing ';'");
3745			/* NOTREACHED */
3746		}
3747		e->e_dlvr_flag = 0;
3748		++s;	/* XXX: spaces allowed? */
3749		SKIP_SPACE(s);
3750		switch (tolower(*s))
3751		{
3752		  case 'n':
3753			e->e_dlvr_flag = DLVR_NOTIFY;
3754			break;
3755		  case 'r':
3756			e->e_dlvr_flag = DLVR_RETURN;
3757			if (e->e_deliver_by <= 0)
3758			{
3759				usrerr("501 5.5.4 mode R requires BY time > 0");
3760				/* NOTREACHED */
3761			}
3762			if (DeliverByMin > 0 && e->e_deliver_by > 0 &&
3763			    e->e_deliver_by < DeliverByMin)
3764			{
3765				usrerr("555 5.5.2 time %ld less than %ld",
3766					e->e_deliver_by, (long) DeliverByMin);
3767				/* NOTREACHED */
3768			}
3769			break;
3770		  default:
3771			usrerr("501 5.5.2 illegal by-mode '%c'", PRTCHAR(*s));
3772			/* NOTREACHED */
3773		}
3774		++s;	/* XXX: spaces allowed? */
3775		SKIP_SPACE(s);
3776		switch (tolower(*s))
3777		{
3778		  case 't':
3779			e->e_dlvr_flag |= DLVR_TRACE;
3780			break;
3781		  case '\0':
3782			break;
3783		  default:
3784			usrerr("501 5.5.2 illegal by-trace '%c'", PRTCHAR(*s));
3785			/* NOTREACHED */
3786		}
3787
3788		/* XXX: check whether more characters follow? */
3789	}
3790	else
3791	{
3792		usrerr("555 5.5.4 %s parameter unrecognized", kp);
3793		/* NOTREACHED */
3794	}
3795}
3796/*
3797**  RCPT_ESMTP_ARGS -- process ESMTP arguments from RCPT line
3798**
3799**	Parameters:
3800**		a -- the address corresponding to the To: parameter.
3801**		kp -- the parameter key.
3802**		vp -- the value of that parameter.
3803**		e -- the envelope.
3804**
3805**	Returns:
3806**		none.
3807*/
3808
3809static void
3810rcpt_esmtp_args(a, kp, vp, e)
3811	ADDRESS *a;
3812	char *kp;
3813	char *vp;
3814	ENVELOPE *e;
3815{
3816	if (sm_strcasecmp(kp, "notify") == 0)
3817	{
3818		char *p;
3819
3820		if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
3821		{
3822			usrerr("504 5.7.0 Sorry, NOTIFY not supported, we do not allow DSN");
3823			/* NOTREACHED */
3824		}
3825		if (vp == NULL)
3826		{
3827			usrerr("501 5.5.2 NOTIFY requires a value");
3828			/* NOTREACHED */
3829		}
3830		a->q_flags &= ~(QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY);
3831		a->q_flags |= QHASNOTIFY;
3832		macdefine(&e->e_macro, A_TEMP, macid("{dsn_notify}"), vp);
3833
3834		if (sm_strcasecmp(vp, "never") == 0)
3835			return;
3836		for (p = vp; p != NULL; vp = p)
3837		{
3838			p = strchr(p, ',');
3839			if (p != NULL)
3840				*p++ = '\0';
3841			if (sm_strcasecmp(vp, "success") == 0)
3842				a->q_flags |= QPINGONSUCCESS;
3843			else if (sm_strcasecmp(vp, "failure") == 0)
3844				a->q_flags |= QPINGONFAILURE;
3845			else if (sm_strcasecmp(vp, "delay") == 0)
3846				a->q_flags |= QPINGONDELAY;
3847			else
3848			{
3849				usrerr("501 5.5.4 Bad argument \"%s\"  to NOTIFY",
3850					vp);
3851				/* NOTREACHED */
3852			}
3853		}
3854	}
3855	else if (sm_strcasecmp(kp, "orcpt") == 0)
3856	{
3857		if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
3858		{
3859			usrerr("504 5.7.0 Sorry, ORCPT not supported, we do not allow DSN");
3860			/* NOTREACHED */
3861		}
3862		if (vp == NULL)
3863		{
3864			usrerr("501 5.5.2 ORCPT requires a value");
3865			/* NOTREACHED */
3866		}
3867		if (strchr(vp, ';') == NULL || !xtextok(vp))
3868		{
3869			usrerr("501 5.5.4 Syntax error in ORCPT parameter value");
3870			/* NOTREACHED */
3871		}
3872		if (a->q_orcpt != NULL)
3873		{
3874			usrerr("501 5.5.0 Duplicate ORCPT parameter");
3875			/* NOTREACHED */
3876		}
3877		a->q_orcpt = sm_rpool_strdup_x(e->e_rpool, vp);
3878	}
3879	else
3880	{
3881		usrerr("555 5.5.4 %s parameter unrecognized", kp);
3882		/* NOTREACHED */
3883	}
3884}
3885/*
3886**  PRINTVRFYADDR -- print an entry in the verify queue
3887**
3888**	Parameters:
3889**		a -- the address to print.
3890**		last -- set if this is the last one.
3891**		vrfy -- set if this is a VRFY command.
3892**
3893**	Returns:
3894**		none.
3895**
3896**	Side Effects:
3897**		Prints the appropriate 250 codes.
3898*/
3899#define OFFF	(3 + 1 + 5 + 1)	/* offset in fmt: SMTP reply + enh. code */
3900
3901static void
3902printvrfyaddr(a, last, vrfy)
3903	register ADDRESS *a;
3904	bool last;
3905	bool vrfy;
3906{
3907	char fmtbuf[30];
3908
3909	if (vrfy && a->q_mailer != NULL &&
3910	    !bitnset(M_VRFY250, a->q_mailer->m_flags))
3911		(void) sm_strlcpy(fmtbuf, "252", sizeof fmtbuf);
3912	else
3913		(void) sm_strlcpy(fmtbuf, "250", sizeof fmtbuf);
3914	fmtbuf[3] = last ? ' ' : '-';
3915	(void) sm_strlcpy(&fmtbuf[4], "2.1.5 ", sizeof fmtbuf - 4);
3916	if (a->q_fullname == NULL)
3917	{
3918		if ((a->q_mailer == NULL ||
3919		     a->q_mailer->m_addrtype == NULL ||
3920		     sm_strcasecmp(a->q_mailer->m_addrtype, "rfc822") == 0) &&
3921		    strchr(a->q_user, '@') == NULL)
3922			(void) sm_strlcpy(&fmtbuf[OFFF], "<%s@%s>",
3923				       sizeof fmtbuf - OFFF);
3924		else
3925			(void) sm_strlcpy(&fmtbuf[OFFF], "<%s>",
3926				       sizeof fmtbuf - OFFF);
3927		message(fmtbuf, a->q_user, MyHostName);
3928	}
3929	else
3930	{
3931		if ((a->q_mailer == NULL ||
3932		     a->q_mailer->m_addrtype == NULL ||
3933		     sm_strcasecmp(a->q_mailer->m_addrtype, "rfc822") == 0) &&
3934		    strchr(a->q_user, '@') == NULL)
3935			(void) sm_strlcpy(&fmtbuf[OFFF], "%s <%s@%s>",
3936				       sizeof fmtbuf - OFFF);
3937		else
3938			(void) sm_strlcpy(&fmtbuf[OFFF], "%s <%s>",
3939				       sizeof fmtbuf - OFFF);
3940		message(fmtbuf, a->q_fullname, a->q_user, MyHostName);
3941	}
3942}
3943
3944#if SASL
3945/*
3946**  SASLMECHS -- get list of possible AUTH mechanisms
3947**
3948**	Parameters:
3949**		conn -- SASL connection info.
3950**		mechlist -- output parameter for list of mechanisms.
3951**
3952**	Returns:
3953**		number of mechs.
3954*/
3955
3956static int
3957saslmechs(conn, mechlist)
3958	sasl_conn_t *conn;
3959	char **mechlist;
3960{
3961	int len, num, result;
3962
3963	/* "user" is currently unused */
3964# if SASL >= 20000
3965	result = sasl_listmech(conn, NULL,
3966			       "", " ", "", (const char **) mechlist,
3967			       (unsigned int *)&len, (unsigned int *)&num);
3968# else /* SASL >= 20000 */
3969	result = sasl_listmech(conn, "user", /* XXX */
3970			       "", " ", "", mechlist,
3971			       (unsigned int *)&len, (unsigned int *)&num);
3972# endif /* SASL >= 20000 */
3973	if (result != SASL_OK)
3974	{
3975		if (LogLevel > 9)
3976			sm_syslog(LOG_WARNING, NOQID,
3977				  "AUTH error: listmech=%d, num=%d",
3978				  result, num);
3979		num = 0;
3980	}
3981	if (num > 0)
3982	{
3983		if (LogLevel > 11)
3984			sm_syslog(LOG_INFO, NOQID,
3985				  "AUTH: available mech=%s, allowed mech=%s",
3986				  *mechlist, AuthMechanisms);
3987		*mechlist = intersect(AuthMechanisms, *mechlist, NULL);
3988	}
3989	else
3990	{
3991		*mechlist = NULL;	/* be paranoid... */
3992		if (result == SASL_OK && LogLevel > 9)
3993			sm_syslog(LOG_WARNING, NOQID,
3994				  "AUTH warning: no mechanisms");
3995	}
3996	return num;
3997}
3998
3999# if SASL >= 20000
4000/*
4001**  PROXY_POLICY -- define proxy policy for AUTH
4002**
4003**	Parameters:
4004**		conn -- unused.
4005**		context -- unused.
4006**		requested_user -- authorization identity.
4007**		rlen -- authorization identity length.
4008**		auth_identity -- authentication identity.
4009**		alen -- authentication identity length.
4010**		def_realm -- default user realm.
4011**		urlen -- user realm length.
4012**		propctx -- unused.
4013**
4014**	Returns:
4015**		ok?
4016**
4017**	Side Effects:
4018**		sets {auth_authen} macro.
4019*/
4020
4021int
4022proxy_policy(conn, context, requested_user, rlen, auth_identity, alen,
4023	     def_realm, urlen, propctx)
4024	sasl_conn_t *conn;
4025	void *context;
4026	const char *requested_user;
4027	unsigned rlen;
4028	const char *auth_identity;
4029	unsigned alen;
4030	const char *def_realm;
4031	unsigned urlen;
4032	struct propctx *propctx;
4033{
4034	if (auth_identity == NULL)
4035		return SASL_FAIL;
4036
4037	macdefine(&BlankEnvelope.e_macro, A_TEMP,
4038		  macid("{auth_authen}"), (char *) auth_identity);
4039
4040	return SASL_OK;
4041}
4042# else /* SASL >= 20000 */
4043
4044/*
4045**  PROXY_POLICY -- define proxy policy for AUTH
4046**
4047**	Parameters:
4048**		context -- unused.
4049**		auth_identity -- authentication identity.
4050**		requested_user -- authorization identity.
4051**		user -- allowed user (output).
4052**		errstr -- possible error string (output).
4053**
4054**	Returns:
4055**		ok?
4056*/
4057
4058int
4059proxy_policy(context, auth_identity, requested_user, user, errstr)
4060	void *context;
4061	const char *auth_identity;
4062	const char *requested_user;
4063	const char **user;
4064	const char **errstr;
4065{
4066	if (user == NULL || auth_identity == NULL)
4067		return SASL_FAIL;
4068	*user = newstr(auth_identity);
4069	return SASL_OK;
4070}
4071# endif /* SASL >= 20000 */
4072#endif /* SASL */
4073
4074#if STARTTLS
4075/*
4076**  INITSRVTLS -- initialize server side TLS
4077**
4078**	Parameters:
4079**		tls_ok -- should tls initialization be done?
4080**
4081**	Returns:
4082**		succeeded?
4083**
4084**	Side Effects:
4085**		sets tls_ok_srv which is a static variable in this module.
4086**		Do NOT remove assignments to it!
4087*/
4088
4089bool
4090initsrvtls(tls_ok)
4091	bool tls_ok;
4092{
4093	if (!tls_ok)
4094		return false;
4095
4096	/* do NOT remove assignment */
4097	tls_ok_srv = inittls(&srv_ctx, TLS_Srv_Opts, true, SrvCertFile,
4098			     SrvKeyFile, CACertPath, CACertFile, DHParams);
4099	return tls_ok_srv;
4100}
4101#endif /* STARTTLS */
4102/*
4103**  SRVFEATURES -- get features for SMTP server
4104**
4105**	Parameters:
4106**		e -- envelope (should be session context).
4107**		clientname -- name of client.
4108**		features -- default features for this invocation.
4109**
4110**	Returns:
4111**		server features.
4112*/
4113
4114/* table with options: it uses just one character, how about strings? */
4115static struct
4116{
4117	char		srvf_opt;
4118	unsigned int	srvf_flag;
4119} srv_feat_table[] =
4120{
4121	{ 'A',	SRV_OFFER_AUTH	},
4122	{ 'B',	SRV_OFFER_VERB	},	/* FFR; not documented in 8.12 */
4123	{ 'D',	SRV_OFFER_DSN	},	/* FFR; not documented in 8.12 */
4124	{ 'E',	SRV_OFFER_ETRN	},	/* FFR; not documented in 8.12 */
4125	{ 'L',	SRV_REQ_AUTH	},	/* FFR; not documented in 8.12 */
4126#if PIPELINING
4127# if _FFR_NO_PIPE
4128	{ 'N',	SRV_NO_PIPE	},
4129# endif /* _FFR_NO_PIPE */
4130	{ 'P',	SRV_OFFER_PIPE	},
4131#endif /* PIPELINING */
4132	{ 'R',	SRV_VRFY_CLT	},	/* FFR; not documented in 8.12 */
4133	{ 'S',	SRV_OFFER_TLS	},
4134/*	{ 'T',	SRV_TMP_FAIL	},	*/
4135	{ 'V',	SRV_VRFY_CLT	},
4136	{ 'X',	SRV_OFFER_EXPN	},	/* FFR; not documented in 8.12 */
4137/*	{ 'Y',	SRV_OFFER_VRFY	},	*/
4138	{ '\0',	SRV_NONE	}
4139};
4140
4141static unsigned int
4142srvfeatures(e, clientname, features)
4143	ENVELOPE *e;
4144	char *clientname;
4145	unsigned int features;
4146{
4147	int r, i, j;
4148	char **pvp, c, opt;
4149	char pvpbuf[PSBUFSIZE];
4150
4151	pvp = NULL;
4152	r = rscap("srv_features", clientname, "", e, &pvp, pvpbuf,
4153		  sizeof(pvpbuf));
4154	if (r != EX_OK)
4155		return features;
4156	if (pvp == NULL || pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
4157		return features;
4158	if (pvp[1] != NULL && sm_strncasecmp(pvp[1], "temp", 4) == 0)
4159		return SRV_TMP_FAIL;
4160
4161	/*
4162	**  General rule (see sendmail.h, d_flags):
4163	**  lower case: required/offered, upper case: Not required/available
4164	**
4165	**  Since we can change some features per daemon, we have both
4166	**  cases here: turn on/off a feature.
4167	*/
4168
4169	for (i = 1; pvp[i] != NULL; i++)
4170	{
4171		c = pvp[i][0];
4172		j = 0;
4173		for (;;)
4174		{
4175			if ((opt = srv_feat_table[j].srvf_opt) == '\0')
4176			{
4177				if (LogLevel > 9)
4178					sm_syslog(LOG_WARNING, e->e_id,
4179						  "srvfeatures: unknown feature %s",
4180						  pvp[i]);
4181				break;
4182			}
4183			if (c == opt)
4184			{
4185				features &= ~(srv_feat_table[j].srvf_flag);
4186				break;
4187			}
4188			if (c == tolower(opt))
4189			{
4190				features |= srv_feat_table[j].srvf_flag;
4191				break;
4192			}
4193			++j;
4194		}
4195	}
4196	return features;
4197}
4198
4199/*
4200**  HELP -- implement the HELP command.
4201**
4202**	Parameters:
4203**		topic -- the topic we want help for.
4204**		e -- envelope.
4205**
4206**	Returns:
4207**		none.
4208**
4209**	Side Effects:
4210**		outputs the help file to message output.
4211*/
4212#define HELPVSTR	"#vers	"
4213#define HELPVERSION	2
4214
4215void
4216help(topic, e)
4217	char *topic;
4218	ENVELOPE *e;
4219{
4220	register SM_FILE_T *hf;
4221	register char *p;
4222	int len;
4223	bool noinfo;
4224	bool first = true;
4225	long sff = SFF_OPENASROOT|SFF_REGONLY;
4226	char buf[MAXLINE];
4227	char inp[MAXLINE];
4228	static int foundvers = -1;
4229	extern char Version[];
4230
4231	if (DontLockReadFiles)
4232		sff |= SFF_NOLOCK;
4233	if (!bitnset(DBS_HELPFILEINUNSAFEDIRPATH, DontBlameSendmail))
4234		sff |= SFF_SAFEDIRPATH;
4235
4236	if (HelpFile == NULL ||
4237	    (hf = safefopen(HelpFile, O_RDONLY, 0444, sff)) == NULL)
4238	{
4239		/* no help */
4240		errno = 0;
4241		message("502 5.3.0 Sendmail %s -- HELP not implemented",
4242			Version);
4243		return;
4244	}
4245
4246	if (topic == NULL || *topic == '\0')
4247	{
4248		topic = "smtp";
4249		noinfo = false;
4250	}
4251	else
4252	{
4253		makelower(topic);
4254		noinfo = true;
4255	}
4256
4257	len = strlen(topic);
4258
4259	while (sm_io_fgets(hf, SM_TIME_DEFAULT, buf, sizeof buf) != NULL)
4260	{
4261		if (buf[0] == '#')
4262		{
4263			if (foundvers < 0 &&
4264			    strncmp(buf, HELPVSTR, strlen(HELPVSTR)) == 0)
4265			{
4266				int h;
4267
4268				if (sm_io_sscanf(buf + strlen(HELPVSTR), "%d",
4269						 &h) == 1)
4270					foundvers = h;
4271			}
4272			continue;
4273		}
4274		if (strncmp(buf, topic, len) == 0)
4275		{
4276			if (first)
4277			{
4278				first = false;
4279
4280				/* print version if no/old vers# in file */
4281				if (foundvers < 2 && !noinfo)
4282					message("214-2.0.0 This is Sendmail version %s", Version);
4283			}
4284			p = strpbrk(buf, " \t");
4285			if (p == NULL)
4286				p = buf + strlen(buf) - 1;
4287			else
4288				p++;
4289			fixcrlf(p, true);
4290			if (foundvers >= 2)
4291			{
4292				translate_dollars(p);
4293				expand(p, inp, sizeof inp, e);
4294				p = inp;
4295			}
4296			message("214-2.0.0 %s", p);
4297			noinfo = false;
4298		}
4299	}
4300
4301	if (noinfo)
4302		message("504 5.3.0 HELP topic \"%.10s\" unknown", topic);
4303	else
4304		message("214 2.0.0 End of HELP info");
4305
4306	if (foundvers != 0 && foundvers < HELPVERSION)
4307	{
4308		if (LogLevel > 1)
4309			sm_syslog(LOG_WARNING, e->e_id,
4310				  "%s too old (require version %d)",
4311				  HelpFile, HELPVERSION);
4312
4313		/* avoid log next time */
4314		foundvers = 0;
4315	}
4316
4317	(void) sm_io_close(hf, SM_TIME_DEFAULT);
4318}
4319