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