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