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