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