xref: /freebsd/contrib/sendmail/src/srvrsmtp.c (revision 9768746b)
1 /*
2  * Copyright (c) 1998-2010, 2012-2014 Proofpoint, 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/mfapi.h>
17 # include <libmilter/mfdef.h>
18 #endif
19 
20 SM_RCSID("@(#)$Id: srvrsmtp.c,v 8.1016 2013-11-22 20:51:56 ca Exp $")
21 
22 #include <sm/sendmail.h>
23 #if _FFR_8BITENVADDR
24 # include <sm/ixlen.h>
25 #endif
26 #include <sm/time.h>
27 #include <sm/fdset.h>
28 
29 #if SASL || STARTTLS
30 # include <tls.h>
31 # include "sfsasl.h"
32 #endif
33 #if SASL
34 # define ENC64LEN(l)	(((l) + 2) * 4 / 3 + 1)
35 static int saslmechs __P((sasl_conn_t *, char **));
36 #endif
37 #if STARTTLS
38 # include <openssl/err.h>
39 
40 static SSL_CTX	*srv_ctx = NULL;	/* TLS server context */
41 static SSL	*srv_ssl = NULL;	/* per connection context */
42 static tlsi_ctx_T tlsi_ctx;		/* TLS information context */
43 
44 static bool	tls_ok_srv = false;
45 
46 # define TLS_VERIFY_CLIENT() tls_set_verify(srv_ctx, srv_ssl, \
47 				bitset(SRV_VRFY_CLT, features))
48 #endif /* STARTTLS */
49 
50 #if _FFR_DM_ONE
51 static bool	NotFirstDelivery = false;
52 #endif
53 
54 /* server features */
55 #define SRV_NONE	0x0000	/* none... */
56 #define SRV_OFFER_TLS	0x0001	/* offer STARTTLS */
57 #define SRV_VRFY_CLT	0x0002	/* request a cert */
58 #define SRV_OFFER_AUTH	0x0004	/* offer AUTH */
59 #define SRV_OFFER_ETRN	0x0008	/* offer ETRN */
60 #define SRV_OFFER_VRFY	0x0010	/* offer VRFY (not yet used) */
61 #define SRV_OFFER_EXPN	0x0020	/* offer EXPN */
62 #define SRV_OFFER_VERB	0x0040	/* offer VERB */
63 #define SRV_OFFER_DSN	0x0080	/* offer DSN */
64 #if PIPELINING
65 # define SRV_OFFER_PIPE	0x0100	/* offer PIPELINING */
66 # if _FFR_NO_PIPE
67 #  define SRV_NO_PIPE	0x0200	/* disable PIPELINING, sleep if used */
68 # endif
69 #endif /* PIPELINING */
70 #define SRV_REQ_AUTH	0x0400	/* require AUTH */
71 #define SRV_REQ_SEC	0x0800	/* require security - equiv to AuthOptions=p */
72 #define SRV_TMP_FAIL	0x1000	/* ruleset caused a temporary failure */
73 #if USE_EAI
74 # define SRV_OFFER_EAI	0x2000	/* offer SMTPUTF8 */
75 #endif
76 #define SRV_NO_HTTP_CMD	0x4000	/* always reject HTTP commands */
77 
78 static unsigned int	srvfeatures __P((ENVELOPE *, char *, unsigned int));
79 
80 #define	STOP_ATTACK	((time_t) -1)
81 static time_t	checksmtpattack __P((volatile unsigned int *, unsigned int,
82 				     bool, char *, ENVELOPE *));
83 static void	printvrfyaddr __P((ADDRESS *, bool, bool));
84 static char	*skipword __P((char *volatile, char *));
85 static void	setup_smtpd_io __P((void));
86 
87 #if SASL
88 # ifndef MAX_AUTH_USER_LEN
89 #  define MAX_AUTH_USER_LEN 256
90 # endif
91 # ifndef MAX_AUTH_LOG_LEN
92 #  define MAX_AUTH_LOG_LEN 64
93 # endif
94 static void get_sasl_user __P((char *, unsigned int, const char *, char *out, size_t));
95 # define RESET_AUTH_FAIL_LOG_USER	\
96 	do	\
97 	{	\
98 		(void) memset(auth_user, 0, sizeof(auth_user));	\
99 		(void) memset(auth_user_tmp, 0, sizeof(auth_user_tmp));	\
100 		auth_user_len = 0;	\
101 	} while (0)
102 # define SET_AUTH_USER_TMP(s, len)	\
103 	do	\
104 	{	\
105 		auth_user_len = SM_MIN(len, MAX_AUTH_USER_LEN-1);	\
106 		(void) memcpy(auth_user_tmp, s, auth_user_len);	\
107 	} while (0)
108 # define SET_AUTH_USER	\
109 	get_sasl_user(auth_user_tmp, auth_user_len, auth_type, auth_user, sizeof(auth_user))
110 # define SET_AUTH_USER_CONDITIONALLY	\
111 		if ('\0' == auth_user[0])	\
112 			SET_AUTH_USER;
113 # define LOG_AUTH_FAIL_USER ", user=", (int)MAX_AUTH_LOG_LEN, auth_user
114 # if SASL >= 20000
115 static int reset_saslconn __P((sasl_conn_t **_conn, char *_hostname,
116 				char *_remoteip, char *_localip,
117 				char *_auth_id, sasl_ssf_t *_ext_ssf));
118 
119 # define RESET_SASLCONN	\
120 	do							\
121 	{							\
122 		RESET_AUTH_FAIL_LOG_USER;			\
123 		result = reset_saslconn(&conn, AuthRealm, remoteip, \
124 					localip, auth_id, &ext_ssf); \
125 		if (result != SASL_OK)				\
126 			sasl_ok = false;			\
127 	} while (0)
128 
129 # else /* SASL >= 20000 */
130 static int reset_saslconn __P((sasl_conn_t **_conn, char *_hostname,
131 				struct sockaddr_in *_saddr_r,
132 				struct sockaddr_in *_saddr_l,
133 				sasl_external_properties_t *_ext_ssf));
134 # define RESET_SASLCONN	\
135 	do							\
136 	{							\
137 		RESET_AUTH_FAIL_LOG_USER;			\
138 		result = reset_saslconn(&conn, AuthRealm, &saddr_r, \
139 					&saddr_l, &ext_ssf);	\
140 		if (result != SASL_OK)				\
141 			sasl_ok = false;			\
142 	} while (0)
143 
144 # endif /* SASL >= 20000 */
145 #endif /* SASL */
146 
147 #if !defined(RESET_AUTH_FAIL_LOG_USER)
148 # define RESET_AUTH_FAIL_LOG_USER
149 #endif
150 
151 extern ENVELOPE	BlankEnvelope;
152 
153 #define NBADRCPTS						\
154 	do							\
155 	{							\
156 		char buf[16];					\
157 		(void) sm_snprintf(buf, sizeof(buf), "%d",	\
158 			BadRcptThrottle > 0 && n_badrcpts > BadRcptThrottle \
159 				? n_badrcpts - 1 : n_badrcpts);	\
160 		macdefine(&e->e_macro, A_TEMP, macid("{nbadrcpts}"), buf); \
161 	} while (0)
162 
163 #define SKIP_SPACE(s)	while (SM_ISSPACE(*s))	\
164 				(s)++
165 
166 #if USE_EAI
167 /*
168 **  ADDR_IS_ASCII -- check whether an address is 100% printable ASCII
169 **
170 **	Parameters:
171 **		a -- an address (or other string)
172 **
173 **	Returns:
174 **		TRUE if a is non-NULL and points to only printable ASCII
175 **		FALSE if a is NULL and points to printable ASCII
176 **		FALSE if a is non-NULL and points to something containing 8-bittery
177 */
178 
179 bool
180 addr_is_ascii(a)
181 	const char *a;
182 {
183 	while (a != NULL && *a != '\0' && *a >= ' ' && (unsigned char)*a < 127)
184 		a++;
185 	return (a != NULL && *a == '\0');
186 }
187 
188 # define CHECK_UTF8_ADDR(a, q)	\
189 	do	\
190 	{	\
191 		q = NULL;	\
192 		if (addr_is_ascii(a))	\
193 			break;	\
194 		if (!SMTPUTF8)	\
195 			break;	\
196 		if (!e->e_smtputf8)	\
197 			q = "553 5.6.7 Address requires SMTPUTF8";	\
198 		else	\
199 		{	\
200 			char str[MAXNAME];	\
201 			dequote_internal_chars(a, str, sizeof(str));	\
202 			if (!utf8_valid(str, strlen(str)) && SMTPUTF8 <= 1) \
203 				q = "553 5.6.7 Address not valid UTF8";	\
204 		}	\
205 	} while (0)
206 #endif /* USE_EAI */
207 
208 /*
209 **  PARSE_ESMTP_ARGS -- parse ESMTP arguments (for MAIL, RCPT)
210 **
211 **	Parameters:
212 **		e -- the envelope
213 **		addr_st -- address (RCPT only)
214 **		p -- read buffer
215 **		delimptr -- current position in read buffer
216 **		which -- MAIL/RCPT
217 **		args -- arguments (output)
218 **		esmtp_args -- function to process a single ESMTP argument
219 **
220 **	Returns:
221 **		none
222 */
223 
224 void
225 parse_esmtp_args(e, addr_st, p, delimptr, which, args, esmtp_args)
226 	ENVELOPE *e;
227 	ADDRESS *addr_st;
228 	char *p;
229 	char *delimptr;
230 	char *which;
231 	char *args[];
232 	esmtp_args_F esmtp_args;
233 {
234 	int argno;
235 
236 	argno = 0;
237 	if (args != NULL)
238 		args[argno++] = p;
239 	p = delimptr;
240 	while (p != NULL && *p != '\0')
241 	{
242 		char *kp;
243 		char *vp = NULL;
244 		char *equal = NULL;
245 
246 		/* locate the beginning of the keyword */
247 		SKIP_SPACE(p);
248 		if (*p == '\0')
249 			break;
250 		kp = p;
251 
252 		/* skip to the value portion */
253 		while ((isascii(*p) && isalnum(*p)) || *p == '-')
254 			p++;
255 		if (*p == '=')
256 		{
257 			equal = p;
258 			*p++ = '\0';
259 			vp = p;
260 
261 			/* skip to the end of the value */
262 			while (*p != '\0' && *p != ' ' &&
263 			       !(isascii(*p) && iscntrl(*p)) &&
264 			       *p != '=')
265 				p++;
266 		}
267 
268 		if (*p != '\0')
269 			*p++ = '\0';
270 
271 		if (tTd(19, 1))
272 			sm_dprintf("%s: got arg %s=\"%s\"\n", which, kp,
273 				vp == NULL ? "<null>" : vp);
274 
275 		esmtp_args(addr_st, kp, vp, e);
276 		if (equal != NULL)
277 			*equal = '=';
278 		if (args != NULL)
279 			args[argno] = kp;
280 		argno++;
281 		if (argno >= MAXSMTPARGS - 1)
282 			usrerr("501 5.5.4 Too many parameters");
283 		if (Errors > 0)
284 			break;
285 	}
286 	if (args != NULL)
287 		args[argno] = NULL;
288 }
289 
290 #if _FFR_ADD_BCC
291 
292 /*
293 **  ADDRCPT -- Add a rcpt to sendq list
294 **
295 **	Parameters:
296 **		rcpt -- rcpt [i]
297 **		sendq -- a pointer to the head of a queue to put
298 **			these people into.
299 **		e -- the envelope in which to add these recipients.
300 **
301 **	Returns:
302 **		The number of addresses added to the list.
303 */
304 
305 static int
306 addrcpt(rcpt, sendq, e)
307 	char *rcpt;
308 	ADDRESS **sendq;
309 	ENVELOPE *e;
310 {
311 	int r;
312 	char *oldto;
313 	ADDRESS *a;
314 
315 	SM_REQUIRE(rcpt != NULL);
316 	SM_REQUIRE(sendq != NULL);
317 	SM_REQUIRE(e != NULL);
318 	oldto = e->e_to;
319 	if (tTd(25, 1))
320 		sm_dprintf("addrcpt: rcpt=%s\n", rcpt);
321 	r = Errors;
322 	a = NULL;
323 	SM_TRY
324 	{
325 		macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e b");
326 /* XXX rcpt must be [i] */
327 		a = parseaddr(rcpt, NULLADDR, RF_COPYALL, ' ', NULL, e, true);
328 		if (a == NULL)
329 			return 0;
330 
331 		a->q_flags &= ~Q_PINGFLAGS;
332 		a->q_flags |= QINTBCC;
333 		a->q_owner = "<>";
334 
335 		/* disable alias expansion? */
336 		a = recipient(a, sendq, 0, e);
337 	}
338 	SM_FINALLY
339 	{
340 		e->e_to = oldto;
341 		macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL);
342 	}
343 	SM_END_TRY
344 	if (tTd(25, 1))
345 		sm_dprintf("addrcpt: rcpt=%s, flags=%#lx\n", rcpt,
346 			a != NULL ? a->q_flags : 0);
347 	Errors = r;
348 	return 1;
349 }
350 
351 /*
352 **  ADDBCC -- Maybe create a copy of an e-mail
353 **
354 **	Parameters:
355 **		a -- current RCPT
356 **		e -- the envelope.
357 **
358 **	Returns:
359 **		nothing
360 **
361 **	Side Effects:
362 **		rscheck() can trigger an "exception"
363 */
364 
365 static void
366 addbcc(a, e)
367 	ADDRESS *a;
368 	ENVELOPE *e;
369 {
370 	int nobcc;
371 	char *newrcpt, empty[1];
372 
373 	if (!AddBcc)
374 		return;
375 
376 	nobcc = false;
377 	empty[0] = '\0';
378 	newrcpt = empty;
379 
380 	nobcc = rscheck("bcc", a->q_paddr, NULL, e, RSF_ADDR, 12, NULL, NOQID,
381 			NULL, &newrcpt);
382 	if (tTd(25, 1))
383 		sm_dprintf("addbcc: nobcc=%d, Errors=%d, newrcpt=<%s>\n", nobcc, Errors, newrcpt);
384 	if (nobcc != EX_OK || Errors > 0 || *newrcpt == '\0')
385 		return;
386 
387 	(void) addrcpt(newrcpt, &e->e_sendqueue, e);
388 	return;
389 }
390 #else /* _FFR_ADD_BCC */
391 # define addbcc(a, e)
392 #endif /* _FFR_ADD_BCC */
393 
394 #if _FFR_RCPTFLAGS
395 /*
396 **  RCPTMODS -- Perform rcpt modifications if requested
397 **
398 **	Parameters:
399 **		rcpt -- current RCPT
400 **		e -- the envelope.
401 **
402 **	Returns:
403 **		nothing.
404 */
405 
406 void
407 rcptmods(rcpt, e)
408 	ADDRESS *rcpt;
409 	ENVELOPE *e;
410 {
411 	char *fl;
412 
413 	SM_REQUIRE(rcpt != NULL);
414 	SM_REQUIRE(e != NULL);
415 
416 	fl = macvalue(macid("{rcpt_flags}"), e);
417 	if (SM_IS_EMPTY(fl))
418 		return;
419 	if (tTd(25, 1))
420 		sm_dprintf("rcptmods: rcpt=%s, flags=%s\n", rcpt->q_paddr, fl);
421 
422 	/* parse flags */
423 	for ( ; *fl != '\0'; ++fl)
424 	{
425 		switch (*fl)
426 		{
427 		  case 'n':
428 			rcpt->q_flags &= ~Q_PINGFLAGS;
429 			rcpt->q_flags |= QINTBCC;
430 			rcpt->q_owner = "<>";
431 			break;
432 
433 		  case 'N':
434 			rcpt->q_flags &= ~Q_PINGFLAGS;
435 			rcpt->q_owner = "<>";
436 			break;
437 
438 		  case QDYNMAILFLG:
439 			rcpt->q_flags |= QDYNMAILER;
440 			newmodmailer(rcpt, *fl);
441 			break;
442 
443 		  default:
444 			sm_syslog(LOG_INFO, e->e_id,
445 				  "rcpt=%s, rcpt_flags=%s, status=unknown",
446 				  rcpt->q_paddr, fl);
447 			break;
448 		}
449 	}
450 
451 	/* reset macro to avoid confusion later on */
452 	macdefine(&e->e_macro, A_PERM, macid("{rcpt_flags}"), NULL);
453 
454 }
455 #else /* _FFR_RCPTFLAGS */
456 # define rcptmods(a, e)
457 #endif /* _FFR_RCPTFLAGS */
458 
459 /*
460 **  SMTP -- run the SMTP protocol.
461 **
462 **	Parameters:
463 **		nullserver -- if non-NULL, rejection message for
464 **			(almost) all SMTP commands.
465 **		d_flags -- daemon flags
466 **		e -- the envelope.
467 **
468 **	Returns:
469 **		never.
470 **
471 **	Side Effects:
472 **		Reads commands from the input channel and processes them.
473 */
474 
475 /*
476 **  Notice: The smtp server doesn't have a session context like the client
477 **	side has (mci). Therefore some data (session oriented) is allocated
478 **	or assigned to the "wrong" structure (esp. STARTTLS, AUTH).
479 **	This should be fixed in a successor version.
480 */
481 
482 struct cmd
483 {
484 	char	*cmd_name;	/* command name */
485 	int	cmd_code;	/* internal code, see below */
486 };
487 
488 /* values for cmd_code */
489 #define CMDERROR	0	/* bad command */
490 #define CMDMAIL	1	/* mail -- designate sender */
491 #define CMDRCPT	2	/* rcpt -- designate recipient */
492 #define CMDDATA	3	/* data -- send message text */
493 #define CMDRSET	4	/* rset -- reset state */
494 #define CMDVRFY	5	/* vrfy -- verify address */
495 #define CMDEXPN	6	/* expn -- expand address */
496 #define CMDNOOP	7	/* noop -- do nothing */
497 #define CMDQUIT	8	/* quit -- close connection and die */
498 #define CMDHELO	9	/* helo -- be polite */
499 #define CMDHELP	10	/* help -- give usage info */
500 #define CMDEHLO	11	/* ehlo -- extended helo (RFC 1425) */
501 #define CMDETRN	12	/* etrn -- flush queue */
502 #if SASL
503 # define CMDAUTH	13	/* auth -- SASL authenticate */
504 #endif
505 #if STARTTLS
506 # define CMDSTLS	14	/* STARTTLS -- start TLS session */
507 #endif
508 /* non-standard commands */
509 #define CMDVERB	17	/* verb -- go into verbose mode */
510 /* unimplemented commands from RFC 821 */
511 #define CMDUNIMPL	19	/* unimplemented rfc821 commands */
512 /* use this to catch and log "door handle" attempts on your system */
513 #define CMDLOGBOGUS	23	/* bogus command that should be logged */
514 /* debugging-only commands, only enabled if SMTPDEBUG is defined */
515 #define CMDDBGQSHOW	24	/* showq -- show send queue */
516 #define CMDDBGDEBUG	25	/* debug -- set debug mode */
517 
518 /*
519 **  Note: If you change this list, remember to update 'helpfile'
520 */
521 
522 static struct cmd	CmdTab[] =
523 {
524 	{ "mail",	CMDMAIL		},
525 	{ "rcpt",	CMDRCPT		},
526 	{ "data",	CMDDATA		},
527 	{ "rset",	CMDRSET		},
528 	{ "vrfy",	CMDVRFY		},
529 	{ "expn",	CMDEXPN		},
530 	{ "help",	CMDHELP		},
531 	{ "noop",	CMDNOOP		},
532 	{ "quit",	CMDQUIT		},
533 	{ "helo",	CMDHELO		},
534 	{ "ehlo",	CMDEHLO		},
535 	{ "etrn",	CMDETRN		},
536 	{ "verb",	CMDVERB		},
537 	{ "send",	CMDUNIMPL	},
538 	{ "saml",	CMDUNIMPL	},
539 	{ "soml",	CMDUNIMPL	},
540 	{ "turn",	CMDUNIMPL	},
541 #if SASL
542 	{ "auth",	CMDAUTH,	},
543 #endif
544 #if STARTTLS
545 	{ "starttls",	CMDSTLS,	},
546 #endif
547     /* remaining commands are here only to trap and log attempts to use them */
548 	{ "showq",	CMDDBGQSHOW	},
549 	{ "debug",	CMDDBGDEBUG	},
550 	{ "wiz",	CMDLOGBOGUS	},
551 
552 	{ NULL,		CMDERROR	}
553 };
554 
555 static char	*CurSmtpClient;		/* who's at the other end of channel */
556 
557 #ifndef MAXBADCOMMANDS
558 # define MAXBADCOMMANDS 25	/* maximum number of bad commands */
559 #endif
560 #ifndef MAXHELOCOMMANDS
561 # define MAXHELOCOMMANDS 3	/* max HELO/EHLO commands before slowdown */
562 #endif
563 #ifndef MAXVRFYCOMMANDS
564 # define MAXVRFYCOMMANDS 6	/* max VRFY/EXPN commands before slowdown */
565 #endif
566 #ifndef MAXETRNCOMMANDS
567 # define MAXETRNCOMMANDS 8	/* max ETRN commands before slowdown */
568 #endif
569 #ifndef MAXTIMEOUT
570 # define MAXTIMEOUT (4 * 60)	/* max timeout for bad commands */
571 #endif
572 
573 /*
574 **  Maximum shift value to compute timeout for bad commands.
575 **  This introduces an upper limit of 2^MAXSHIFT for the timeout.
576 */
577 
578 #ifndef MAXSHIFT
579 # define MAXSHIFT 8
580 #endif
581 #if MAXSHIFT > 31
582 # ERROR "MAXSHIFT > 31 is invalid"
583 #endif
584 
585 
586 #if MAXBADCOMMANDS > 0
587 # define STOP_IF_ATTACK(r)	do		\
588 	{					\
589 		if ((r) == STOP_ATTACK)		\
590 			goto stopattack;	\
591 	} while (0)
592 
593 #else /* MAXBADCOMMANDS > 0 */
594 # define STOP_IF_ATTACK(r)	r
595 #endif /* MAXBADCOMMANDS > 0 */
596 
597 
598 #if SM_HEAP_CHECK
599 static SM_DEBUG_T DebugLeakSmtp = SM_DEBUG_INITIALIZER("leak_smtp",
600 	"@(#)$Debug: leak_smtp - trace memory leaks during SMTP processing $");
601 #endif
602 
603 typedef struct
604 {
605 	bool		sm_gotmail;	/* mail command received */
606 	unsigned int	sm_nrcpts;	/* number of successful RCPT commands */
607 	bool		sm_discard;
608 #if MILTER
609 	bool		sm_milterize;
610 	bool		sm_milterlist;	/* any filters in the list? */
611 	milters_T	sm_milters;
612 
613 	/* e_nrcpts from envelope before recipient() call */
614 	unsigned int	sm_e_nrcpts_orig;
615 #endif /* MILTER */
616 	char		*sm_quarmsg;	/* carry quarantining across messages */
617 } SMTP_T;
618 
619 static bool	smtp_data __P((SMTP_T *, ENVELOPE *));
620 
621 #define MSG_TEMPFAIL "451 4.3.2 Please try again later"
622 
623 #if MILTER
624 # define MILTER_ABORT(e)	milter_abort((e))
625 
626 # define MILTER_REPLY(str)						\
627 	{								\
628 		int savelogusrerrs = LogUsrErrs;			\
629 									\
630 		milter_cmd_fail = true;					\
631 		switch (state)						\
632 		{							\
633 		  case SMFIR_SHUTDOWN:					\
634 			if (MilterLogLevel > 3)				\
635 			{						\
636 				sm_syslog(LOG_INFO, e->e_id,		\
637 					  "Milter: %s=%s, reject=421, errormode=4",	\
638 					  str, addr);			\
639 				LogUsrErrs = false;			\
640 			}						\
641 			{						\
642 				bool tsave = QuickAbort;		\
643 									\
644 				QuickAbort = false;			\
645 				usrerr("421 4.3.0 closing connection");	\
646 				QuickAbort = tsave;			\
647 				e->e_sendqueue = NULL;			\
648 				goto doquit;				\
649 			}						\
650 			break;						\
651 		  case SMFIR_REPLYCODE:					\
652 			if (MilterLogLevel > 3)				\
653 			{						\
654 				sm_syslog(LOG_INFO, e->e_id,		\
655 					  "Milter: %s=%s, reject=%s",	\
656 					  str, addr, response);		\
657 				LogUsrErrs = false;			\
658 			}						\
659 			if (strncmp(response, "421 ", 4) == 0		\
660 			    || strncmp(response, "421-", 4) == 0)	\
661 			{						\
662 				bool tsave = QuickAbort;		\
663 									\
664 				QuickAbort = false;			\
665 				usrerr(response);			\
666 				QuickAbort = tsave;			\
667 				e->e_sendqueue = NULL;			\
668 				goto doquit;				\
669 			}						\
670 			else						\
671 				usrerr(response);			\
672 			break;						\
673 									\
674 		  case SMFIR_REJECT:					\
675 			if (MilterLogLevel > 3)				\
676 			{						\
677 				sm_syslog(LOG_INFO, e->e_id,		\
678 					  "Milter: %s=%s, reject=550 5.7.1 Command rejected", \
679 					  str, addr);			\
680 				LogUsrErrs = false;			\
681 			}						\
682 			usrerr("550 5.7.1 Command rejected");		\
683 			break;						\
684 									\
685 		  case SMFIR_DISCARD:					\
686 			if (MilterLogLevel > 3)				\
687 				sm_syslog(LOG_INFO, e->e_id,		\
688 					  "Milter: %s=%s, discard",	\
689 					  str, addr);			\
690 			e->e_flags |= EF_DISCARD;			\
691 			milter_cmd_fail = false;			\
692 			break;						\
693 									\
694 		  case SMFIR_TEMPFAIL:					\
695 			if (MilterLogLevel > 3)				\
696 			{						\
697 				sm_syslog(LOG_INFO, e->e_id,		\
698 					  "Milter: %s=%s, reject=%s",	\
699 					  str, addr, MSG_TEMPFAIL);	\
700 				LogUsrErrs = false;			\
701 			}						\
702 			usrerr(MSG_TEMPFAIL);				\
703 			break;						\
704 		  default:						\
705 			milter_cmd_fail = false;			\
706 			break;						\
707 		}							\
708 		LogUsrErrs = savelogusrerrs;				\
709 		if (response != NULL)					\
710 			sm_free(response); /* XXX */			\
711 	}
712 
713 #else /* MILTER */
714 # define MILTER_ABORT(e)
715 #endif /* MILTER */
716 
717 /* clear all SMTP state (for HELO/EHLO/RSET) */
718 #define CLEAR_STATE(cmd)					\
719 do								\
720 {								\
721 	/* abort milter filters */				\
722 	MILTER_ABORT(e);					\
723 								\
724 	if (smtp.sm_nrcpts > 0)					\
725 	{							\
726 		logundelrcpts(e, cmd, 10, false);		\
727 		smtp.sm_nrcpts = 0;				\
728 		macdefine(&e->e_macro, A_PERM,			\
729 			  macid("{nrcpts}"), "0");		\
730 	}							\
731 								\
732 	e->e_sendqueue = NULL;					\
733 	e->e_flags |= EF_CLRQUEUE;				\
734 								\
735 	if (tTd(92, 2))						\
736 		sm_dprintf("CLEAR_STATE: e_id=%s, EF_LOGSENDER=%d, LogLevel=%d\n",\
737 			e->e_id, bitset(EF_LOGSENDER, e->e_flags), LogLevel);\
738 	if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))	\
739 		logsender(e, NULL);				\
740 	e->e_flags &= ~EF_LOGSENDER;				\
741 								\
742 	/* clean up a bit */					\
743 	smtp.sm_gotmail = false;				\
744 	SuprErrs = true;					\
745 	(void) dropenvelope(e, true, false);			\
746 	sm_rpool_free(e->e_rpool);				\
747 	e = newenvelope(e, CurEnv, sm_rpool_new_x(NULL));	\
748 	CurEnv = e;						\
749 	e->e_features = features;				\
750 								\
751 	/* put back discard bit */				\
752 	if (smtp.sm_discard)					\
753 		e->e_flags |= EF_DISCARD;			\
754 								\
755 	/* restore connection quarantining */			\
756 	if (smtp.sm_quarmsg == NULL)				\
757 	{							\
758 		e->e_quarmsg = NULL;				\
759 		macdefine(&e->e_macro, A_PERM,			\
760 			macid("{quarantine}"), "");		\
761 	}							\
762 	else							\
763 	{							\
764 		e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool,	\
765 						smtp.sm_quarmsg);	\
766 		macdefine(&e->e_macro, A_PERM, macid("{quarantine}"),	\
767 			  e->e_quarmsg);			\
768 	}							\
769 } while (0)
770 
771 /* sleep to flatten out connection load */
772 #define MIN_DELAY_LOG	15	/* wait before logging this again */
773 
774 /* is it worth setting the process title for 1s? */
775 #define DELAY_CONN(cmd)						\
776 	if (DelayLA > 0 && (CurrentLA = getla()) >= DelayLA)	\
777 	{							\
778 		time_t dnow;					\
779 								\
780 		sm_setproctitle(true, e,			\
781 				"%s: %s: delaying %s: load average: %d", \
782 				qid_printname(e), CurSmtpClient,	\
783 				cmd, DelayLA);	\
784 		if (LogLevel > 8 && (dnow = curtime()) > log_delay)	\
785 		{						\
786 			sm_syslog(LOG_INFO, e->e_id,		\
787 				  "delaying=%s, load average=%d >= %d",	\
788 				  cmd, CurrentLA, DelayLA);		\
789 			log_delay = dnow + MIN_DELAY_LOG;	\
790 		}						\
791 		(void) sleep(1);				\
792 		sm_setproctitle(true, e, "%s %s: %.80s",	\
793 				qid_printname(e), CurSmtpClient, inp);	\
794 	}
795 
796 /*
797 **  Determine the correct protocol keyword to use in the
798 **  Received: header, following RFC 3848.
799 */
800 
801 #if !STARTTLS
802 # define tls_active	false
803 #endif
804 #if SASL
805 # define auth_active	(authenticating == SASL_IS_AUTH)
806 #else
807 # define auth_active	false
808 #endif
809 #if USE_EAI
810 #define GET_PROTOCOL()					\
811 	(e->e_smtputf8					\
812 	    ? (auth_active				\
813 		? (tls_active ? "UTF8SMTPSA" : "UTF8SMTPA") \
814 		: (tls_active ? "UTF8SMTPS"  : "UTF8SMTP")) \
815 	    : (auth_active				\
816 		? (tls_active ? "ESMTPSA" : "ESMTPA")	\
817 		: (tls_active ? "ESMTPS"  : "ESMTP")))
818 #else /* USE_EAI */
819 #define GET_PROTOCOL()					\
820 	(auth_active					\
821 	    ? (tls_active ? "ESMTPSA" : "ESMTPA")	\
822 	    : (tls_active ? "ESMTPS"  : "ESMTP"))
823 #endif /* USE_EAI */
824 
825 static bool SevenBitInput_Saved;	/* saved version of SevenBitInput */
826 
827 #if _FFR_NOREFLECT
828 # define SHOWCMDINREPLY(inp) (bitset(PRIV_NOREFLECTION, PrivacyFlags) ? \
829 		"(suppressed)" : inp)
830 # define SHOWSHRTCMDINREPLY(inp) (bitset(PRIV_NOREFLECTION, PrivacyFlags) ? \
831 		"(suppressed)" : shortenstring(inp, MAXSHORTSTR))
832 #else
833 # define SHOWCMDINREPLY(inp) inp
834 # define SHOWSHRTCMDINREPLY(inp) shortenstring(inp, MAXSHORTSTR)
835 #endif
836 
837 void
838 smtp(nullserver, d_flags, e)
839 	char *volatile nullserver;
840 	BITMAP256 d_flags;
841 	register ENVELOPE *volatile e;
842 {
843 	register char *volatile p;
844 	register struct cmd *volatile c = NULL;
845 	char *cmd;
846 	auto ADDRESS *vrfyqueue;
847 	ADDRESS *a;
848 	volatile bool gothello;		/* helo command received */
849 	bool vrfy;			/* set if this is a vrfy command */
850 	char *volatile protocol;	/* sending protocol */
851 	char *volatile sendinghost;	/* sending hostname */
852 	char *volatile peerhostname;	/* name of SMTP peer or "localhost" */
853 	auto char *delimptr;
854 	char *id;
855 	volatile unsigned int n_badcmds = 0;	/* count of bad commands */
856 	volatile unsigned int n_badrcpts = 0;	/* number of rejected RCPT */
857 	volatile unsigned int n_verifies = 0;	/* count of VRFY/EXPN */
858 	volatile unsigned int n_etrn = 0;	/* count of ETRN */
859 	volatile unsigned int n_noop = 0;	/* count of NOOP/VERB/etc */
860 	volatile unsigned int n_helo = 0;	/* count of HELO/EHLO */
861 	bool ok;
862 	volatile bool first;
863 	volatile bool tempfail = false;
864 	volatile time_t wt;		/* timeout after too many commands */
865 	volatile time_t previous;	/* time after checksmtpattack() */
866 	volatile bool lognullconnection = true;
867 	register char *q;
868 	SMTP_T smtp;
869 	char *addr;
870 	char *greetcode = "220";
871 	const char *greetmsg = "not accepting messages";
872 	char *hostname;			/* my hostname ($j) */
873 	QUEUE_CHAR *new;
874 	char *args[MAXSMTPARGS];
875 	char inp[MAXINPLINE];
876 #if MAXINPLINE < MAXLINE
877 # ERROR "MAXINPLINE must NOT be less than MAXLINE"
878 #endif
879 	char cmdbuf[MAXLINE];
880 #if SASL
881 	sasl_conn_t *conn;
882 	volatile bool sasl_ok;
883 	volatile unsigned int n_auth = 0;	/* count of AUTH commands */
884 	bool ismore;
885 	int result;
886 	volatile int authenticating;
887 	char *user;
888 	char *in, *out2;
889 	char auth_user[MAX_AUTH_USER_LEN], auth_user_tmp[MAX_AUTH_USER_LEN];
890 	unsigned int auth_user_len;
891 # if SASL >= 20000
892 	char *auth_id = NULL;
893 	const char *out;
894 	sasl_ssf_t ext_ssf;
895 	char localip[60], remoteip[60];
896 # else /* SASL >= 20000 */
897 	char *out;
898 	const char *errstr;
899 	sasl_external_properties_t ext_ssf;
900 	struct sockaddr_in saddr_l;
901 	struct sockaddr_in saddr_r;
902 # endif /* SASL >= 20000 */
903 	sasl_security_properties_t ssp;
904 	sasl_ssf_t *ssf;
905 	unsigned int inlen, out2len;
906 	unsigned int outlen;
907 	char *volatile auth_type;
908 	char *mechlist;
909 	volatile unsigned int n_mechs;
910 	unsigned int len;
911 #endif /* SASL */
912 	int r;
913 #if STARTTLS
914 	int rfd, wfd;
915 	volatile bool tls_active = false;
916 	volatile bool smtps = bitnset(D_SMTPS, d_flags);
917 	bool saveQuickAbort;
918 	bool saveSuprErrs;
919 	time_t tlsstart;
920 	int ssl_err, tlsret;
921 	int save_errno;
922 	extern int TLSsslidx;
923 #endif /* STARTTLS */
924 	volatile unsigned int features;
925 #if PIPELINING
926 # if _FFR_NO_PIPE
927 	int np_log = 0;
928 # endif
929 #endif
930 	volatile time_t log_delay = (time_t) 0;
931 #if MILTER
932 	volatile bool milter_cmd_done, milter_cmd_safe;
933 	volatile bool milter_rcpt_added, milter_cmd_fail;
934 	ADDRESS addr_st;
935 # define p_addr_st	&addr_st
936 #else /* MILTER */
937 # define p_addr_st	NULL
938 #endif /* MILTER */
939 	size_t inplen;
940 #if _FFR_BADRCPT_SHUTDOWN
941 	int n_badrcpts_adj;
942 #endif
943 
944 	RESET_AUTH_FAIL_LOG_USER;
945 	SevenBitInput_Saved = SevenBitInput;
946 	smtp.sm_nrcpts = 0;
947 #if MILTER
948 	smtp.sm_milterize = (nullserver == NULL);
949 	smtp.sm_milterlist = false;
950 	addr = NULL;
951 #endif
952 
953 	/* setup I/O fd correctly for the SMTP server */
954 	setup_smtpd_io();
955 
956 #if SM_HEAP_CHECK
957 	if (sm_debug_active(&DebugLeakSmtp, 1))
958 	{
959 		sm_heap_newgroup();
960 		sm_dprintf("smtp() heap group #%d\n", sm_heap_group());
961 	}
962 #endif /* SM_HEAP_CHECK */
963 
964 	/* XXX the rpool should be set when e is initialized in main() */
965 	e->e_rpool = sm_rpool_new_x(NULL);
966 	e->e_macro.mac_rpool = e->e_rpool;
967 
968 	settime(e);
969 	sm_getla();
970 	peerhostname = RealHostName;
971 	if (peerhostname == NULL)
972 		peerhostname = "localhost";
973 	CurHostName = peerhostname;
974 	CurSmtpClient = macvalue('_', e);
975 	if (CurSmtpClient == NULL)
976 		CurSmtpClient = CurHostName;
977 
978 	/* check_relay may have set discard bit, save for later */
979 	smtp.sm_discard = bitset(EF_DISCARD, e->e_flags);
980 
981 #if PIPELINING
982 	/* auto-flush output when reading input */
983 	(void) sm_io_autoflush(InChannel, OutChannel);
984 #endif
985 
986 	sm_setproctitle(true, e, "server %s startup", CurSmtpClient);
987 
988 	/* Set default features for server. */
989 	features = ((bitset(PRIV_NOETRN, PrivacyFlags) ||
990 		     bitnset(D_NOETRN, d_flags)) ? SRV_NONE : SRV_OFFER_ETRN)
991 		| (bitnset(D_AUTHREQ, d_flags) ? SRV_REQ_AUTH : SRV_NONE)
992 		| (bitset(PRIV_NOEXPN, PrivacyFlags) ? SRV_NONE
993 			: (SRV_OFFER_EXPN
994 			  | (bitset(PRIV_NOVERB, PrivacyFlags)
995 			     ? SRV_NONE : SRV_OFFER_VERB)))
996 		| ((bitset(PRIV_NORECEIPTS, PrivacyFlags) || !SendMIMEErrors)
997 			 ? SRV_NONE : SRV_OFFER_DSN)
998 #if SASL
999 		| (bitnset(D_NOAUTH, d_flags) ? SRV_NONE : SRV_OFFER_AUTH)
1000 		| (bitset(SASL_SEC_NOPLAINTEXT, SASLOpts) ? SRV_REQ_SEC
1001 							  : SRV_NONE)
1002 #endif /* SASL */
1003 #if PIPELINING
1004 		| SRV_OFFER_PIPE
1005 #endif
1006 #if STARTTLS
1007 		| (bitnset(D_NOTLS, d_flags) ? SRV_NONE : SRV_OFFER_TLS)
1008 		| (bitset(TLS_I_NO_VRFY, TLS_Srv_Opts) ? SRV_NONE
1009 						       : SRV_VRFY_CLT)
1010 #endif
1011 #if USE_EAI
1012 		| (SMTPUTF8 ? SRV_OFFER_EAI : 0)
1013 #endif
1014 		;
1015 	if (nullserver == NULL)
1016 	{
1017 		features = srvfeatures(e, CurSmtpClient, features);
1018 		if (bitset(SRV_TMP_FAIL, features))
1019 		{
1020 			if (LogLevel > 4)
1021 				sm_syslog(LOG_ERR, NOQID,
1022 					  "ERROR: srv_features=tempfail, relay=%.100s, access temporarily disabled",
1023 					  CurSmtpClient);
1024 			nullserver = "450 4.3.0 Please try again later.";
1025 		}
1026 		else
1027 		{
1028 #if PIPELINING
1029 # if _FFR_NO_PIPE
1030 			if (bitset(SRV_NO_PIPE, features))
1031 			{
1032 				/* for consistency */
1033 				features &= ~SRV_OFFER_PIPE;
1034 			}
1035 # endif /* _FFR_NO_PIPE */
1036 #endif /* PIPELINING */
1037 #if SASL
1038 			if (bitset(SRV_REQ_SEC, features))
1039 				SASLOpts |= SASL_SEC_NOPLAINTEXT;
1040 			else
1041 				SASLOpts &= ~SASL_SEC_NOPLAINTEXT;
1042 #endif /* SASL */
1043 		}
1044 	}
1045 	else if (strncmp(nullserver, "421 ", 4) == 0)
1046 	{
1047 		/* Can't use ("%s", ...) due to message() requirements */
1048 		message(nullserver);
1049 		goto doquit;
1050 	}
1051 
1052 	e->e_features = features;
1053 	hostname = macvalue('j', e);
1054 #if SASL
1055 	if (AuthRealm == NULL)
1056 		AuthRealm = hostname;
1057 	sasl_ok = bitset(SRV_OFFER_AUTH, features);
1058 	n_mechs = 0;
1059 	authenticating = SASL_NOT_AUTH;
1060 
1061 	/* SASL server new connection */
1062 	if (sasl_ok)
1063 	{
1064 # if SASL >= 20000
1065 		result = sasl_server_new("smtp", AuthRealm, NULL, NULL, NULL,
1066 					 NULL, 0, &conn);
1067 # elif SASL > 10505
1068 		/* use empty realm: only works in SASL > 1.5.5 */
1069 		result = sasl_server_new("smtp", AuthRealm, "", NULL, 0, &conn);
1070 # else /* SASL >= 20000 */
1071 		/* use no realm -> realm is set to hostname by SASL lib */
1072 		result = sasl_server_new("smtp", AuthRealm, NULL, NULL, 0,
1073 					 &conn);
1074 # endif /* SASL >= 20000 */
1075 		sasl_ok = result == SASL_OK;
1076 		if (!sasl_ok)
1077 		{
1078 			if (LogLevel > 9)
1079 				sm_syslog(LOG_WARNING, NOQID,
1080 					  "AUTH error: sasl_server_new failed=%d",
1081 					  result);
1082 		}
1083 	}
1084 	if (sasl_ok)
1085 	{
1086 		/*
1087 		**  SASL set properties for sasl
1088 		**  set local/remote IP
1089 		**  XXX Cyrus SASL v1 only supports IPv4
1090 		**
1091 		**  XXX where exactly are these used/required?
1092 		**  Kerberos_v4
1093 		*/
1094 
1095 # if SASL >= 20000
1096 		localip[0] = remoteip[0] = '\0';
1097 #  if NETINET || NETINET6
1098 		in = macvalue(macid("{daemon_family}"), e);
1099 		if (in != NULL && (
1100 #   if NETINET6
1101 		    strcmp(in, "inet6") == 0 ||
1102 #   endif
1103 		    strcmp(in, "inet") == 0))
1104 		{
1105 			SOCKADDR_LEN_T addrsize;
1106 			SOCKADDR saddr_l;
1107 			SOCKADDR saddr_r;
1108 
1109 			addrsize = sizeof(saddr_r);
1110 			if (getpeername(sm_io_getinfo(InChannel, SM_IO_WHAT_FD,
1111 						      NULL),
1112 					(struct sockaddr *) &saddr_r,
1113 					&addrsize) == 0)
1114 			{
1115 				if (iptostring(&saddr_r, addrsize,
1116 					       remoteip, sizeof(remoteip)))
1117 				{
1118 					sasl_setprop(conn, SASL_IPREMOTEPORT,
1119 						     remoteip);
1120 				}
1121 				addrsize = sizeof(saddr_l);
1122 				if (getsockname(sm_io_getinfo(InChannel,
1123 							      SM_IO_WHAT_FD,
1124 							      NULL),
1125 						(struct sockaddr *) &saddr_l,
1126 						&addrsize) == 0)
1127 				{
1128 					if (iptostring(&saddr_l, addrsize,
1129 						       localip,
1130 						       sizeof(localip)))
1131 					{
1132 						sasl_setprop(conn,
1133 							     SASL_IPLOCALPORT,
1134 							     localip);
1135 					}
1136 				}
1137 			}
1138 		}
1139 #  endif /* NETINET || NETINET6 */
1140 # else /* SASL >= 20000 */
1141 #  if NETINET
1142 		in = macvalue(macid("{daemon_family}"), e);
1143 		if (in != NULL && strcmp(in, "inet") == 0)
1144 		{
1145 			SOCKADDR_LEN_T addrsize;
1146 
1147 			addrsize = sizeof(struct sockaddr_in);
1148 			if (getpeername(sm_io_getinfo(InChannel, SM_IO_WHAT_FD,
1149 						      NULL),
1150 					(struct sockaddr *)&saddr_r,
1151 					&addrsize) == 0)
1152 			{
1153 				sasl_setprop(conn, SASL_IP_REMOTE, &saddr_r);
1154 				addrsize = sizeof(struct sockaddr_in);
1155 				if (getsockname(sm_io_getinfo(InChannel,
1156 							      SM_IO_WHAT_FD,
1157 							      NULL),
1158 						(struct sockaddr *)&saddr_l,
1159 						&addrsize) == 0)
1160 					sasl_setprop(conn, SASL_IP_LOCAL,
1161 						     &saddr_l);
1162 			}
1163 		}
1164 #  endif /* NETINET */
1165 # endif /* SASL >= 20000 */
1166 
1167 		auth_type = NULL;
1168 		mechlist = NULL;
1169 		user = NULL;
1170 # if 0
1171 		macdefine(&BlankEnvelope.e_macro, A_PERM,
1172 			macid("{auth_author}"), NULL);
1173 # endif
1174 
1175 		/* set properties */
1176 		(void) memset(&ssp, '\0', sizeof(ssp));
1177 
1178 		/* XXX should these be options settable via .cf ? */
1179 		/* ssp.min_ssf = 0; is default due to memset() */
1180 		ssp.max_ssf = MaxSLBits;
1181 		ssp.maxbufsize = MAXOUTLEN;
1182 		ssp.security_flags = SASLOpts & SASL_SEC_MASK;
1183 		sasl_ok = sasl_setprop(conn, SASL_SEC_PROPS, &ssp) == SASL_OK;
1184 
1185 		if (sasl_ok)
1186 		{
1187 			/*
1188 			**  external security strength factor;
1189 			**	currently we have none so zero
1190 			*/
1191 
1192 # if SASL >= 20000
1193 			ext_ssf = 0;
1194 			auth_id = NULL;
1195 			sasl_ok = ((sasl_setprop(conn, SASL_SSF_EXTERNAL,
1196 						 &ext_ssf) == SASL_OK) &&
1197 				   (sasl_setprop(conn, SASL_AUTH_EXTERNAL,
1198 						 auth_id) == SASL_OK));
1199 # else /* SASL >= 20000 */
1200 			ext_ssf.ssf = 0;
1201 			ext_ssf.auth_id = NULL;
1202 			sasl_ok = sasl_setprop(conn, SASL_SSF_EXTERNAL,
1203 					       &ext_ssf) == SASL_OK;
1204 # endif /* SASL >= 20000 */
1205 		}
1206 		if (sasl_ok)
1207 			n_mechs = saslmechs(conn, &mechlist);
1208 	}
1209 #endif /* SASL */
1210 
1211 	(void) set_tls_rd_tmo(TimeOuts.to_nextcommand);
1212 
1213 #if MILTER
1214 	if (smtp.sm_milterize)
1215 	{
1216 		char state;
1217 
1218 		/* initialize mail filter connection */
1219 		smtp.sm_milterlist = milter_init(e, &state, &smtp.sm_milters);
1220 		switch (state)
1221 		{
1222 		  case SMFIR_REJECT:
1223 			if (MilterLogLevel > 3)
1224 				sm_syslog(LOG_INFO, e->e_id,
1225 					  "Milter: initialization failed, rejecting commands");
1226 			greetcode = "554";
1227 			nullserver = "Command rejected";
1228 			smtp.sm_milterize = false;
1229 			break;
1230 
1231 		  case SMFIR_TEMPFAIL:
1232 			if (MilterLogLevel > 3)
1233 				sm_syslog(LOG_INFO, e->e_id,
1234 					  "Milter: initialization failed, temp failing commands");
1235 			tempfail = true;
1236 			smtp.sm_milterize = false;
1237 			break;
1238 
1239 		  case SMFIR_SHUTDOWN:
1240 			if (MilterLogLevel > 3)
1241 				sm_syslog(LOG_INFO, e->e_id,
1242 					  "Milter: initialization failed, closing connection");
1243 			tempfail = true;
1244 			smtp.sm_milterize = false;
1245 			message("421 4.7.0 %s closing connection",
1246 					MyHostName);
1247 
1248 			/* arrange to ignore send list */
1249 			e->e_sendqueue = NULL;
1250 			lognullconnection = false;
1251 			goto doquit;
1252 		}
1253 	}
1254 
1255 	if (smtp.sm_milterlist && smtp.sm_milterize &&
1256 	    !bitset(EF_DISCARD, e->e_flags))
1257 	{
1258 		char state;
1259 		char *response;
1260 
1261 		q = macvalue(macid("{client_name}"), e);
1262 		SM_ASSERT(q != NULL || OpMode == MD_SMTP);
1263 		if (q == NULL)
1264 			q = "localhost";
1265 		response = milter_connect(q, RealHostAddr, e, &state);
1266 		switch (state)
1267 		{
1268 # if _FFR_MILTER_CONNECT_REPLYCODE
1269 		  case SMFIR_REPLYCODE:
1270 			if (*response == '5')
1271 			{
1272 				if (MilterLogLevel > 3)
1273 					sm_syslog(LOG_INFO, e->e_id,
1274 						  "Milter: connect: host=%s, addr=%s, reject=%s",
1275 						  peerhostname,
1276 						  anynet_ntoa(&RealHostAddr),
1277 						  response);
1278 				greetcode = "554"; /* Required by 2821 3.1 */
1279 				nullserver = newstr(response);
1280 				if (strlen(nullserver) > 4)
1281 				{
1282 					int skip;
1283 
1284 					greetmsg = nullserver + 4;
1285 
1286 					/* skip over enhanced status code */
1287 					skip = isenhsc(greetmsg, ' ');
1288 					if (skip > 0)
1289 						greetmsg += skip + 1;
1290 				}
1291 				smtp.sm_milterize = false;
1292 				break;
1293 			}
1294 			else if (strncmp(response, "421 ", 4) == 0)
1295 			{
1296 				int skip;
1297 				const char *msg = response + 4;
1298 
1299 				if (MilterLogLevel > 3)
1300 					sm_syslog(LOG_INFO, e->e_id,
1301 						  "Milter: connect: host=%s, addr=%s, shutdown=%s",
1302 						  peerhostname,
1303 						  anynet_ntoa(&RealHostAddr),
1304 						  response);
1305 				tempfail = true;
1306 				smtp.sm_milterize = false;
1307 
1308 				/* skip over enhanced status code */
1309 				skip = isenhsc(msg, ' ');
1310 				if (skip > 0)
1311 					msg += skip + 1;
1312 				message("421 %s %s", MyHostName, msg);
1313 
1314 				/* arrange to ignore send list */
1315 				e->e_sendqueue = NULL;
1316 				goto doquit;
1317 			}
1318 			else
1319 			{
1320 				if (MilterLogLevel > 3)
1321 					sm_syslog(LOG_INFO, e->e_id,
1322 						  "Milter: connect: host=%s, addr=%s, temp failing commands=%s",
1323 						  peerhostname,
1324 						  anynet_ntoa(&RealHostAddr),
1325 						  response);
1326 				/*tempfail = true;*/
1327 				smtp.sm_milterize = false;
1328 				nullserver = newstr(response);
1329 				break;
1330 			}
1331 
1332 # else /* _FFR_MILTER_CONNECT_REPLYCODE */
1333 		  case SMFIR_REPLYCODE:	/* REPLYCODE shouldn't happen */
1334 # endif /* _FFR_MILTER_CONNECT_REPLYCODE */
1335 		  case SMFIR_REJECT:
1336 			if (MilterLogLevel > 3)
1337 				sm_syslog(LOG_INFO, e->e_id,
1338 					  "Milter: connect: host=%s, addr=%s, rejecting commands",
1339 					  peerhostname,
1340 					  anynet_ntoa(&RealHostAddr));
1341 			greetcode = "554";
1342 			nullserver = "Command rejected";
1343 			smtp.sm_milterize = false;
1344 			break;
1345 
1346 		  case SMFIR_TEMPFAIL:
1347 			if (MilterLogLevel > 3)
1348 				sm_syslog(LOG_INFO, e->e_id,
1349 					  "Milter: connect: host=%s, addr=%s, temp failing commands",
1350 					  peerhostname,
1351 					  anynet_ntoa(&RealHostAddr));
1352 			tempfail = true;
1353 			smtp.sm_milterize = false;
1354 			break;
1355 
1356 		  case SMFIR_SHUTDOWN:
1357 			if (MilterLogLevel > 3)
1358 				sm_syslog(LOG_INFO, e->e_id,
1359 					  "Milter: connect: host=%s, addr=%s, shutdown",
1360 					  peerhostname,
1361 					  anynet_ntoa(&RealHostAddr));
1362 			tempfail = true;
1363 			smtp.sm_milterize = false;
1364 			message("421 4.7.0 %s closing connection",
1365 					MyHostName);
1366 
1367 			/* arrange to ignore send list */
1368 			e->e_sendqueue = NULL;
1369 			goto doquit;
1370 		}
1371 		if (response != NULL)
1372 			sm_free(response);
1373 	}
1374 #endif /* MILTER */
1375 
1376 	/*
1377 	**  Broken proxies and SMTP slammers
1378 	**  push data without waiting, catch them
1379 	*/
1380 
1381 	if (
1382 #if STARTTLS
1383 	    !smtps &&
1384 #endif
1385 	    *greetcode == '2' && nullserver == NULL)
1386 	{
1387 		time_t msecs = 0;
1388 		char **pvp;
1389 		char pvpbuf[PSBUFSIZE];
1390 
1391 		/* Ask the rulesets how long to pause */
1392 		pvp = NULL;
1393 		r = rscap("greet_pause", peerhostname,
1394 			  anynet_ntoa(&RealHostAddr), e,
1395 			  &pvp, pvpbuf, sizeof(pvpbuf));
1396 		if (r == EX_OK && pvp != NULL && pvp[0] != NULL &&
1397 		    (pvp[0][0] & 0377) == CANONNET && pvp[1] != NULL)
1398 		{
1399 			msecs = strtol(pvp[1], NULL, 10);
1400 		}
1401 
1402 		if (msecs > 0)
1403 		{
1404 			int fd;
1405 			fd_set readfds;
1406 			struct timeval timeout;
1407 			struct timeval bp, ep, tp; /* {begin,end,total}pause */
1408 			int eoftest;
1409 
1410 			/* pause for a moment */
1411 			timeout.tv_sec = msecs / 1000;
1412 			timeout.tv_usec = (msecs % 1000) * 1000;
1413 
1414 			/* Obey RFC 2821: 4.3.5.2: 220 timeout of 5 minutes */
1415 			if (timeout.tv_sec >= 300)
1416 			{
1417 				timeout.tv_sec = 300;
1418 				timeout.tv_usec = 0;
1419 			}
1420 
1421 			/* check if data is on the socket during the pause */
1422 			fd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL);
1423 			FD_ZERO(&readfds);
1424 			SM_FD_SET(fd, &readfds);
1425 			gettimeofday(&bp, NULL);
1426 			if (select(fd + 1, FDSET_CAST &readfds,
1427 			    NULL, NULL, &timeout) > 0 &&
1428 			    FD_ISSET(fd, &readfds) &&
1429 			    (eoftest = sm_io_getc(InChannel, SM_TIME_DEFAULT))
1430 			    != SM_IO_EOF)
1431 			{
1432 				sm_io_ungetc(InChannel, SM_TIME_DEFAULT,
1433 					     eoftest);
1434 				gettimeofday(&ep, NULL);
1435 				timersub(&ep, &bp, &tp);
1436 				greetcode = "554";
1437 				nullserver = "Command rejected";
1438 				sm_syslog(LOG_INFO, e->e_id,
1439 					  "rejecting commands from %s [%s] due to pre-greeting traffic after %d seconds",
1440 					  peerhostname,
1441 					  anynet_ntoa(&RealHostAddr),
1442 					  (int) tp.tv_sec +
1443 						(tp.tv_usec >= 500000 ? 1 : 0)
1444 					 );
1445 			}
1446 		}
1447 	}
1448 
1449 #if STARTTLS
1450 	/* If this an smtps connection, start TLS now */
1451 	if (smtps)
1452 	{
1453 		if (!tls_ok_srv || srv_ctx == NULL)
1454 		{
1455 			sm_syslog(LOG_ERR, e->e_id,
1456 				"smtps: TLS not available, exiting");
1457 			exit(EX_CONFIG);
1458 		}
1459 		Errors = 0;
1460 		first = true;
1461 		gothello = false;
1462 		smtp.sm_gotmail = false;
1463 		goto starttls;
1464 	}
1465 
1466   greeting:
1467 
1468 #endif /* STARTTLS */
1469 
1470 	/* output the first line, inserting "ESMTP" as second word */
1471 	if (*greetcode == '5')
1472 		(void) sm_snprintf(inp, sizeof(inp), "%s %s", hostname,
1473 				   greetmsg);
1474 	else
1475 		expand(SmtpGreeting, inp, sizeof(inp), e);
1476 
1477 	p = strchr(inp, '\n');
1478 	if (p != NULL)
1479 		*p++ = '\0';
1480 	id = strchr(inp, ' ');
1481 	if (id == NULL)
1482 		id = &inp[strlen(inp)];
1483 	if (p == NULL)
1484 		(void) sm_snprintf(cmdbuf, sizeof(cmdbuf),
1485 			 "%s %%.*s ESMTP%%s", greetcode);
1486 	else
1487 		(void) sm_snprintf(cmdbuf, sizeof(cmdbuf),
1488 			 "%s-%%.*s ESMTP%%s", greetcode);
1489 	message(cmdbuf, (int) (id - inp), inp, id);
1490 
1491 	/* output remaining lines */
1492 	while ((id = p) != NULL && (p = strchr(id, '\n')) != NULL)
1493 	{
1494 		*p++ = '\0';
1495 		if (SM_ISSPACE(*id))
1496 			id++;
1497 		(void) sm_strlcpyn(cmdbuf, sizeof(cmdbuf), 2, greetcode, "-%s");
1498 		message(cmdbuf, id);
1499 	}
1500 	if (id != NULL)
1501 	{
1502 		if (SM_ISSPACE(*id))
1503 			id++;
1504 		(void) sm_strlcpyn(cmdbuf, sizeof(cmdbuf), 2, greetcode, " %s");
1505 		message(cmdbuf, id);
1506 	}
1507 
1508 	protocol = NULL;
1509 	sendinghost = macvalue('s', e);
1510 
1511 	/* If quarantining by a connect/ehlo action, save between messages */
1512 	if (e->e_quarmsg == NULL)
1513 		smtp.sm_quarmsg = NULL;
1514 	else
1515 		smtp.sm_quarmsg = newstr(e->e_quarmsg);
1516 
1517 	/* sendinghost's storage must outlive the current envelope */
1518 	if (sendinghost != NULL)
1519 		sendinghost = sm_strdup_x(sendinghost);
1520 	first = true;
1521 	gothello = false;
1522 	smtp.sm_gotmail = false;
1523 	for (;;)
1524 	{
1525 	    SM_TRY
1526 	    {
1527 		QuickAbort = false;
1528 		HoldErrs = false;
1529 		SuprErrs = false;
1530 		LogUsrErrs = false;
1531 		OnlyOneError = true;
1532 		e->e_flags &= ~(EF_VRFYONLY|EF_GLOBALERRS);
1533 #if MILTER
1534 		milter_cmd_fail = false;
1535 #endif
1536 
1537 		/* setup for the read */
1538 		e->e_to = NULL;
1539 		Errors = 0;
1540 		FileName = NULL;
1541 		(void) sm_io_flush(smioout, SM_TIME_DEFAULT);
1542 
1543 		/* read the input line */
1544 		SmtpPhase = "server cmd read";
1545 		sm_setproctitle(true, e, "server %s cmd read", CurSmtpClient);
1546 
1547 		/* handle errors */
1548 		if (sm_io_error(OutChannel) ||
1549 		    (p = sfgets(inp, sizeof(inp), InChannel,
1550 				TimeOuts.to_nextcommand, SmtpPhase)) == NULL)
1551 		{
1552 			char *d;
1553 
1554 			d = macvalue(macid("{daemon_name}"), e);
1555 			if (d == NULL)
1556 				d = "stdin";
1557 			/* end of file, just die */
1558 			disconnect(1, e);
1559 
1560 #if MILTER
1561 			/* close out milter filters */
1562 			milter_quit(e);
1563 #endif
1564 
1565 			message("421 4.4.1 %s Lost input channel from %s",
1566 				MyHostName, CurSmtpClient);
1567 			if (LogLevel > (smtp.sm_gotmail ? 1 : 19))
1568 				sm_syslog(LOG_NOTICE, e->e_id,
1569 					  "lost input channel from %s to %s after %s",
1570 					  CurSmtpClient, d,
1571 					  (c == NULL || c->cmd_name == NULL) ? "startup" : c->cmd_name);
1572 			/*
1573 			**  If have not accepted mail (DATA), do not bounce
1574 			**  bad addresses back to sender.
1575 			*/
1576 
1577 			if (bitset(EF_CLRQUEUE, e->e_flags))
1578 				e->e_sendqueue = NULL;
1579 			goto doquit;
1580 		}
1581 
1582 		/* also used by "proxy" check below */
1583 		inplen = strlen(inp);
1584 #if SASL
1585 		/*
1586 		**  SMTP AUTH requires accepting any length,
1587 		**  at least for challenge/response. However, not imposing
1588 		**  a limit is a bad idea (denial of service).
1589 		*/
1590 
1591 		if (authenticating != SASL_PROC_AUTH
1592 		    && sm_strncasecmp(inp, "AUTH ", 5) != 0
1593 		    && inplen > MAXLINE)
1594 		{
1595 			message("421 4.7.0 %s Command too long, possible attack %s",
1596 				MyHostName, CurSmtpClient);
1597 			sm_syslog(LOG_INFO, e->e_id,
1598 				  "%s: SMTP violation, input too long: %lu",
1599 				  CurSmtpClient, (unsigned long) inplen);
1600 			goto doquit;
1601 		}
1602 #endif /* SASL */
1603 
1604 		if (first || bitset(SRV_NO_HTTP_CMD, features))
1605 		{
1606 			size_t cmdlen;
1607 			int idx;
1608 			char *http_cmd;
1609 			static char *http_cmds[] = { "GET", "POST",
1610 						     "CONNECT", "USER", NULL };
1611 
1612 			for (idx = 0; (http_cmd = http_cmds[idx]) != NULL;
1613 			     idx++)
1614 			{
1615 				cmdlen = strlen(http_cmd);
1616 				if (cmdlen < inplen &&
1617 				    sm_strncasecmp(inp, http_cmd, cmdlen) == 0 &&
1618 				    SM_ISSPACE(inp[cmdlen]))
1619 				{
1620 					/* Open proxy, drop it */
1621 					message("421 4.7.0 %s %s %s",
1622 						MyHostName,
1623 						first ? "Rejecting open proxy"
1624 							: "HTTP command",
1625 						CurSmtpClient);
1626 					sm_syslog(LOG_INFO, e->e_id,
1627 						  "%s: probable open proxy: command=%.40s",
1628 						  CurSmtpClient, inp);
1629 					goto doquit;
1630 				}
1631 			}
1632 			first = false;
1633 		}
1634 
1635 		/* clean up end of line */
1636 		fixcrlf(inp, true);
1637 
1638 #if PIPELINING
1639 # if _FFR_NO_PIPE
1640 		/*
1641 		**  if there is more input and pipelining is disabled:
1642 		**	delay ... (and maybe discard the input?)
1643 		**  XXX this doesn't really work, at least in tests using
1644 		**  telnet SM_IO_IS_READABLE only returns 1 if there were
1645 		**  more than 2 input lines available.
1646 		*/
1647 
1648 		if (bitset(SRV_NO_PIPE, features) &&
1649 		    sm_io_getinfo(InChannel, SM_IO_IS_READABLE, NULL) > 0)
1650 		{
1651 			if (++np_log < 3)
1652 				sm_syslog(LOG_INFO, NOQID,
1653 					  "unauthorized PIPELINING, sleeping, relay=%.100s",
1654 					   CurSmtpClient);
1655 			sleep(1);
1656 		}
1657 
1658 # endif /* _FFR_NO_PIPE */
1659 #endif /* PIPELINING */
1660 
1661 #if SASL
1662 		if (authenticating == SASL_PROC_AUTH)
1663 		{
1664 # if 0
1665 			if (*inp == '\0')
1666 			{
1667 				authenticating = SASL_NOT_AUTH;
1668 				message("501 5.5.2 missing input");
1669 				RESET_SASLCONN;
1670 				continue;
1671 			}
1672 # endif /* 0 */
1673 			if (*inp == '*' && *(inp + 1) == '\0')
1674 			{
1675 				authenticating = SASL_NOT_AUTH;
1676 
1677 				/* RFC 2554 4. */
1678 				message("501 5.0.0 AUTH aborted");
1679 				RESET_SASLCONN;
1680 				continue;
1681 			}
1682 
1683 			/* could this be shorter? XXX */
1684 # if SASL >= 20000
1685 			in = xalloc(strlen(inp) + 1);
1686 			result = sasl_decode64(inp, strlen(inp), in,
1687 					       strlen(inp), &inlen);
1688 # else /* SASL >= 20000 */
1689 			out = xalloc(strlen(inp));
1690 			result = sasl_decode64(inp, strlen(inp), out, &outlen);
1691 # endif /* SASL >= 20000 */
1692 			if (result != SASL_OK)
1693 			{
1694 				authenticating = SASL_NOT_AUTH;
1695 
1696 				/* RFC 2554 4. */
1697 				message("501 5.5.4 cannot decode AUTH parameter %s",
1698 					inp);
1699 # if SASL >= 20000
1700 				sm_free(in);
1701 # endif
1702 				RESET_SASLCONN;
1703 				continue;
1704 			}
1705 
1706 # if SASL >= 20000
1707 			SET_AUTH_USER_TMP(in, inlen);
1708 			result = sasl_server_step(conn,	in, inlen,
1709 						  &out, &outlen);
1710 			sm_free(in);
1711 # else /* SASL >= 20000 */
1712 			SET_AUTH_USER_TMP(out, outlen);
1713 			result = sasl_server_step(conn,	out, outlen,
1714 						  &out, &outlen, &errstr);
1715 # endif /* SASL >= 20000 */
1716 
1717 			/* get an OK if we're done */
1718 			if (result == SASL_OK)
1719 			{
1720   authenticated:
1721 				message("235 2.0.0 OK Authenticated");
1722 				authenticating = SASL_IS_AUTH;
1723 				macdefine(&BlankEnvelope.e_macro, A_TEMP,
1724 					macid("{auth_type}"), auth_type);
1725 
1726 # if SASL >= 20000
1727 				user = macvalue(macid("{auth_authen}"), e);
1728 
1729 				/* get security strength (features) */
1730 				result = sasl_getprop(conn, SASL_SSF,
1731 						      (const void **) &ssf);
1732 # else /* SASL >= 20000 */
1733 				result = sasl_getprop(conn, SASL_USERNAME,
1734 						      (void **)&user);
1735 				if (result != SASL_OK)
1736 				{
1737 					user = "";
1738 					macdefine(&BlankEnvelope.e_macro,
1739 						  A_PERM,
1740 						  macid("{auth_authen}"), NULL);
1741 				}
1742 				else
1743 				{
1744 					macdefine(&BlankEnvelope.e_macro,
1745 						  A_TEMP,
1746 						  macid("{auth_authen}"),
1747 						  xtextify(user, "<>\")"));
1748 				}
1749 
1750 #  if 0
1751 				/* get realm? */
1752 				sasl_getprop(conn, SASL_REALM, (void **) &data);
1753 #  endif
1754 
1755 				/* get security strength (features) */
1756 				result = sasl_getprop(conn, SASL_SSF,
1757 						      (void **) &ssf);
1758 # endif /* SASL >= 20000 */
1759 				if (result != SASL_OK)
1760 				{
1761 					macdefine(&BlankEnvelope.e_macro,
1762 						  A_PERM,
1763 						  macid("{auth_ssf}"), "0");
1764 					ssf = NULL;
1765 				}
1766 				else
1767 				{
1768 					char pbuf[8];
1769 
1770 					(void) sm_snprintf(pbuf, sizeof(pbuf),
1771 							   "%u", *ssf);
1772 					macdefine(&BlankEnvelope.e_macro,
1773 						  A_TEMP,
1774 						  macid("{auth_ssf}"), pbuf);
1775 					if (tTd(95, 8))
1776 						sm_dprintf("AUTH auth_ssf: %u\n",
1777 							   *ssf);
1778 				}
1779 
1780 				protocol = GET_PROTOCOL();
1781 
1782 				/*
1783 				**  Only switch to encrypted connection
1784 				**  if a security layer has been negotiated
1785 				*/
1786 
1787 				if (ssf != NULL && *ssf > 0)
1788 				{
1789 					int tmo;
1790 
1791 					/*
1792 					**  Convert I/O layer to use SASL.
1793 					**  If the call fails, the connection
1794 					**  is aborted.
1795 					*/
1796 
1797 					tmo = TimeOuts.to_datablock * 1000;
1798 					if (sfdcsasl(&InChannel, &OutChannel,
1799 						     conn, tmo) == 0)
1800 					{
1801 						/* restart dialogue */
1802 						n_helo = 0;
1803 # if PIPELINING
1804 						(void) sm_io_autoflush(InChannel,
1805 								       OutChannel);
1806 # endif /* PIPELINING */
1807 					}
1808 					else
1809 						syserr("503 5.3.3 SASL TLS failed");
1810 				}
1811 
1812 				/* NULL pointer ok since it's our function */
1813 				if (LogLevel > 8)
1814 					sm_syslog(LOG_INFO, NOQID,
1815 						  "AUTH=server, relay=%s, authid=%.128s, mech=%.16s, bits=%d",
1816 						  CurSmtpClient,
1817 						  shortenstring(user, 128),
1818 						  auth_type, *ssf);
1819 			}
1820 			else if (result == SASL_CONTINUE)
1821 			{
1822 				SET_AUTH_USER;
1823 
1824 				len = ENC64LEN(outlen);
1825 				out2 = xalloc(len);
1826 				result = sasl_encode64(out, outlen, out2, len,
1827 						       &out2len);
1828 				if (result != SASL_OK)
1829 				{
1830 					/* correct code? XXX */
1831 					/* 454 Temp. authentication failure */
1832 					message("454 4.5.4 Internal error: unable to encode64");
1833 					if (LogLevel > 5)
1834 						sm_syslog(LOG_WARNING, e->e_id,
1835 							  "AUTH encode64 error [%d for \"%s\"], relay=%.100s",
1836 							  result, out,
1837 							  CurSmtpClient);
1838 					/* start over? */
1839 					authenticating = SASL_NOT_AUTH;
1840 				}
1841 				else
1842 				{
1843 					message("334 %s", out2);
1844 					if (tTd(95, 2))
1845 						sm_dprintf("AUTH continue: msg='%s' len=%u\n",
1846 							   out2, out2len);
1847 				}
1848 # if SASL >= 20000
1849 				sm_free(out2);
1850 # endif
1851 			}
1852 			else
1853 			{
1854 
1855 # if SASL >= 20000
1856 #  define SASLERR sasl_errdetail(conn)
1857 # else
1858 #  define SASLERR errstr == NULL ? "" : errstr
1859 # endif
1860 #define LOGAUTHFAIL	\
1861 	do	\
1862 	{	\
1863 		SET_AUTH_USER_CONDITIONALLY	\
1864 		message("535 5.7.0 authentication failed");	\
1865 		if (LogLevel >= 9)	\
1866 			sm_syslog(LOG_WARNING, e->e_id,	\
1867 				  "AUTH failure (%s): %s (%d) %s%s%.*s, relay=%.100s",	\
1868 				  (auth_type != NULL) ? auth_type : "unknown", \
1869 				  sasl_errstring(result, NULL, NULL),	\
1870 				  result,	\
1871 				  SASLERR, \
1872 				  LOG_AUTH_FAIL_USER,	\
1873 				  CurSmtpClient);	\
1874 		RESET_SASLCONN;	\
1875 	} while (0)
1876 
1877 
1878 				LOGAUTHFAIL;
1879 				authenticating = SASL_NOT_AUTH;
1880 			}
1881 		}
1882 		else
1883 		{
1884 			/* don't want to do any of this if authenticating */
1885 #endif /* SASL */
1886 
1887 		/* echo command to transcript */
1888 		if (e->e_xfp != NULL)
1889 			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
1890 					     "<<< %s\n", inp);
1891 
1892 		if (LogLevel > 14)
1893 			sm_syslog(LOG_INFO, e->e_id, "<-- %s", inp);
1894 
1895 		/* break off command */
1896 		for (p = inp; SM_ISSPACE(*p); p++)
1897 			continue;
1898 		cmd = cmdbuf;
1899 		while (*p != '\0' &&
1900 		       !(SM_ISSPACE(*p)) &&
1901 		       cmd < &cmdbuf[sizeof(cmdbuf) - 2])
1902 			*cmd++ = *p++;
1903 		*cmd = '\0';
1904 
1905 		/* throw away leading whitespace */
1906 		SKIP_SPACE(p);
1907 
1908 		/* decode command */
1909 		for (c = CmdTab; c->cmd_name != NULL; c++)
1910 		{
1911 			if (SM_STRCASEEQ(c->cmd_name, cmdbuf))
1912 				break;
1913 		}
1914 
1915 		/* reset errors */
1916 		errno = 0;
1917 
1918 		/* check whether a "non-null" command has been used */
1919 		switch (c->cmd_code)
1920 		{
1921 #if SASL
1922 		  case CMDAUTH:
1923 			/* avoid information leak; take first two words? */
1924 			q = "AUTH";
1925 			break;
1926 #endif /* SASL */
1927 
1928 		  case CMDMAIL:
1929 		  case CMDEXPN:
1930 		  case CMDVRFY:
1931 		  case CMDETRN:
1932 			lognullconnection = false;
1933 			/* FALLTHROUGH */
1934 		  default:
1935 			q = inp;
1936 			break;
1937 		}
1938 
1939 		if (e->e_id == NULL)
1940 			sm_setproctitle(true, e, "%s: %.80s",
1941 					CurSmtpClient, q);
1942 		else
1943 			sm_setproctitle(true, e, "%s %s: %.80s",
1944 					qid_printname(e),
1945 					CurSmtpClient, q);
1946 
1947 		/*
1948 		**  Process command.
1949 		**
1950 		**	If we are running as a null server, return 550
1951 		**	to almost everything.
1952 		*/
1953 
1954 		if (nullserver != NULL || bitnset(D_ETRNONLY, d_flags))
1955 		{
1956 			switch (c->cmd_code)
1957 			{
1958 			  case CMDQUIT:
1959 			  case CMDHELO:
1960 			  case CMDEHLO:
1961 			  case CMDNOOP:
1962 			  case CMDRSET:
1963 			  case CMDERROR:
1964 				/* process normally */
1965 				break;
1966 
1967 			  case CMDETRN:
1968 				if (bitnset(D_ETRNONLY, d_flags) &&
1969 				    nullserver == NULL)
1970 					break;
1971 				DELAY_CONN("ETRN");
1972 				/* FALLTHROUGH */
1973 
1974 			  default:
1975 #if MAXBADCOMMANDS > 0
1976 				/* theoretically this could overflow */
1977 				if (nullserver != NULL &&
1978 				    ++n_badcmds > MAXBADCOMMANDS)
1979 				{
1980 					message("421 4.7.0 %s Too many bad commands; closing connection",
1981 						MyHostName);
1982 
1983 					/* arrange to ignore send list */
1984 					e->e_sendqueue = NULL;
1985 					goto doquit;
1986 				}
1987 #endif /* MAXBADCOMMANDS > 0 */
1988 				if (nullserver != NULL)
1989 				{
1990 					if (ISSMTPREPLY(nullserver))
1991 					{
1992 						/* Can't use ("%s", ...) due to usrerr() requirements */
1993 						usrerr(nullserver);
1994 					}
1995 					else
1996 					{
1997 						usrerr("550 5.0.0 %s",
1998 						       nullserver);
1999 					}
2000 				}
2001 				else
2002 					usrerr("452 4.4.5 Insufficient disk space; try again later");
2003 				continue;
2004 			}
2005 		}
2006 
2007 		switch (c->cmd_code)
2008 		{
2009 #if SASL
2010 		  case CMDAUTH: /* sasl */
2011 			DELAY_CONN("AUTH");
2012 			if (!sasl_ok || n_mechs <= 0)
2013 			{
2014 				message("503 5.3.3 AUTH not available");
2015 				break;
2016 			}
2017 			if (authenticating == SASL_IS_AUTH)
2018 			{
2019 				message("503 5.5.0 Already Authenticated");
2020 				break;
2021 			}
2022 			if (smtp.sm_gotmail)
2023 			{
2024 				message("503 5.5.0 AUTH not permitted during a mail transaction");
2025 				break;
2026 			}
2027 			if (tempfail)
2028 			{
2029 				if (LogLevel > 9)
2030 					sm_syslog(LOG_INFO, e->e_id,
2031 						  "SMTP AUTH command (%.100s) from %s tempfailed (due to previous checks)",
2032 						  p, CurSmtpClient);
2033 				usrerr("454 4.3.0 Please try again later");
2034 				break;
2035 			}
2036 
2037 			ismore = false;
2038 
2039 			/* crude way to avoid crack attempts */
2040 			STOP_IF_ATTACK(checksmtpattack(&n_auth, n_mechs + 1,
2041 							true, "AUTH", e));
2042 
2043 			/* make sure mechanism (p) is a valid string */
2044 			for (q = p; *q != '\0' && isascii(*q); q++)
2045 			{
2046 				if (isspace(*q))
2047 				{
2048 					*q = '\0';
2049 					while (*++q != '\0' && SM_ISSPACE(*q))
2050 						continue;
2051 					*(q - 1) = '\0';
2052 					ismore = (*q != '\0');
2053 					break;
2054 				}
2055 			}
2056 
2057 			if (*p == '\0')
2058 			{
2059 				message("501 5.5.2 AUTH mechanism must be specified");
2060 				break;
2061 			}
2062 
2063 			/* check whether mechanism is available */
2064 			if (iteminlist(p, mechlist, " ") == NULL)
2065 			{
2066 				message("504 5.3.3 AUTH mechanism %.32s not available",
2067 					p);
2068 				break;
2069 			}
2070 
2071 			/*
2072 			**  RFC 2554 4.
2073 			**  Unlike a zero-length client answer to a
2074 			**  334 reply, a zero- length initial response
2075 			**  is sent as a single equals sign ("=").
2076 			*/
2077 
2078 			if (ismore && *q == '=' && *(q + 1) == '\0')
2079 			{
2080 				/* will be free()d, don't use in=""; */
2081 				in = xalloc(1);
2082 				*in = '\0';
2083 				inlen = 0;
2084 			}
2085 			else if (ismore)
2086 			{
2087 				/* could this be shorter? XXX */
2088 # if SASL >= 20000
2089 				in = xalloc(strlen(q) + 1);
2090 				result = sasl_decode64(q, strlen(q), in,
2091 						       strlen(q), &inlen);
2092 # else /* SASL >= 20000 */
2093 				in = sm_rpool_malloc(e->e_rpool, strlen(q));
2094 				result = sasl_decode64(q, strlen(q), in,
2095 						       &inlen);
2096 # endif /* SASL >= 20000 */
2097 
2098 				if (result != SASL_OK)
2099 				{
2100 					message("501 5.5.4 cannot BASE64 decode '%s'",
2101 						q);
2102 					if (LogLevel > 5)
2103 						sm_syslog(LOG_WARNING, e->e_id,
2104 							  "AUTH decode64 error [%d for \"%s\"], relay=%.100s",
2105 							  result, q,
2106 							  CurSmtpClient);
2107 					/* start over? */
2108 					authenticating = SASL_NOT_AUTH;
2109 # if SASL >= 20000
2110 					sm_free(in);
2111 # endif
2112 					in = NULL;
2113 					inlen = 0;
2114 					break;
2115 				}
2116 				SET_AUTH_USER_TMP(in, inlen);
2117 			}
2118 			else
2119 			{
2120 				in = NULL;
2121 				inlen = 0;
2122 			}
2123 
2124 			/* see if that auth type exists */
2125 # if SASL >= 20000
2126 			result = sasl_server_start(conn, p, in, inlen,
2127 						   &out, &outlen);
2128 			SM_FREE(in);
2129 # else /* SASL >= 20000 */
2130 			result = sasl_server_start(conn, p, in, inlen,
2131 						   &out, &outlen, &errstr);
2132 # endif /* SASL >= 20000 */
2133 
2134 			if (p != NULL)
2135 				auth_type = newstr(p);
2136 			if (result != SASL_OK && result != SASL_CONTINUE)
2137 			{
2138 				LOGAUTHFAIL;
2139 				break;
2140 			}
2141 
2142 			if (result == SASL_OK)
2143 			{
2144 				/* ugly, but same code */
2145 				goto authenticated;
2146 				/* authenticated by the initial response */
2147 			}
2148 
2149 			SET_AUTH_USER;
2150 
2151 			/* len is at least 2 */
2152 			len = ENC64LEN(outlen);
2153 			out2 = xalloc(len);
2154 			result = sasl_encode64(out, outlen, out2, len,
2155 					       &out2len);
2156 
2157 			if (result != SASL_OK)
2158 			{
2159 				message("454 4.5.4 Temporary authentication failure");
2160 				if (LogLevel > 5)
2161 					sm_syslog(LOG_WARNING, e->e_id,
2162 						  "AUTH encode64 error [%d for \"%s\"]",
2163 						  result, out);
2164 
2165 				/* start over? */
2166 				authenticating = SASL_NOT_AUTH;
2167 				RESET_SASLCONN;
2168 			}
2169 			else
2170 			{
2171 				message("334 %s", out2);
2172 				authenticating = SASL_PROC_AUTH;
2173 			}
2174 # if SASL >= 20000
2175 			sm_free(out2);
2176 # endif
2177 			break;
2178 #endif /* SASL */
2179 
2180 #if STARTTLS
2181 		  case CMDSTLS: /* starttls */
2182 			DELAY_CONN("STARTTLS");
2183 			if (*p != '\0')
2184 			{
2185 				message("501 5.5.2 Syntax error (no parameters allowed)");
2186 				break;
2187 			}
2188 			if (!bitset(SRV_OFFER_TLS, features))
2189 			{
2190 				message("503 5.5.0 TLS not available");
2191 				break;
2192 			}
2193   starttls:
2194 			if (!tls_ok_srv)
2195 			{
2196 				message("454 4.3.3 TLS not available after start");
2197 				break;
2198 			}
2199 			if (smtp.sm_gotmail)
2200 			{
2201 				message("503 5.5.0 TLS not permitted during a mail transaction");
2202 				break;
2203 			}
2204 			if (tempfail)
2205 			{
2206 				if (LogLevel > 9)
2207 					sm_syslog(LOG_INFO, e->e_id,
2208 						  "SMTP STARTTLS command (%.100s) from %s tempfailed (due to previous checks)",
2209 						  p, CurSmtpClient);
2210 				usrerr("454 4.7.0 Please try again later");
2211 				break;
2212 			}
2213 			if (!TLS_set_engine(SSLEngine, false))
2214 			{
2215 				sm_syslog(LOG_ERR, NOQID,
2216 					  "STARTTLS=server, engine=%s, TLS_set_engine=failed",
2217 					  SSLEngine);
2218 				tls_ok_srv = false;
2219 				message("454 4.3.3 TLS not available right now");
2220 				break;
2221 			}
2222 # if TLS_NO_RSA
2223 			/*
2224 			**  XXX do we need a temp key ?
2225 			*/
2226 # endif
2227 
2228 # if TLS_VRFY_PER_CTX
2229 			/*
2230 			**  Note: this sets the verification globally
2231 			**  (per SSL_CTX)
2232 			**  it's ok since it applies only to one transaction
2233 			*/
2234 
2235 			TLS_VERIFY_CLIENT();
2236 # endif /* TLS_VRFY_PER_CTX */
2237 
2238 #define SMTLSFAILED				\
2239 	do {					\
2240 		SM_SSL_FREE(srv_ssl);		\
2241 		goto tls_done;			\
2242 	} while (0)
2243 
2244 			if (srv_ssl != NULL)
2245 				SSL_clear(srv_ssl);
2246 			else if ((srv_ssl = SSL_new(srv_ctx)) == NULL)
2247 			{
2248 				message("454 4.3.3 TLS not available: error generating SSL handle");
2249 				tlslogerr(LOG_WARNING, 8, "server");
2250 				goto tls_done;
2251 			}
2252 			if (get_tls_se_features(e, srv_ssl, &tlsi_ctx, true)
2253 			    != EX_OK)
2254 			{
2255 				/* do not offer too much info to client */
2256 				message("454 4.3.3 TLS curently not available");
2257 				SMTLSFAILED;
2258 			}
2259 			r = SSL_set_ex_data(srv_ssl, TLSsslidx, &tlsi_ctx);
2260 			if (0 == r)
2261 			{
2262 				if (LogLevel > 5)
2263 				{
2264 					sm_syslog(LOG_ERR, NOQID,
2265 						"STARTTLS=server, error: SSL_set_ex_data failed=%d",
2266 						r);
2267 					tlslogerr(LOG_WARNING, 9, "server");
2268 				}
2269 				SMTLSFAILED;
2270 			}
2271 
2272 # if !TLS_VRFY_PER_CTX
2273 			/*
2274 			**  this could be used if it were possible to set
2275 			**  verification per SSL (connection)
2276 			**  not just per SSL_CTX (global)
2277 			*/
2278 
2279 			TLS_VERIFY_CLIENT();
2280 # endif /* !TLS_VRFY_PER_CTX */
2281 
2282 			rfd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL);
2283 			wfd = sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL);
2284 
2285 			if (rfd < 0 || wfd < 0 ||
2286 			    SSL_set_rfd(srv_ssl, rfd) <= 0 ||
2287 			    SSL_set_wfd(srv_ssl, wfd) <= 0)
2288 			{
2289 				message("454 4.3.3 TLS not available: error set fd");
2290 				SMTLSFAILED;
2291 			}
2292 			if (!smtps)
2293 				message("220 2.0.0 Ready to start TLS");
2294 # if PIPELINING
2295 			(void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
2296 # endif
2297 
2298 			SSL_set_accept_state(srv_ssl);
2299 
2300 			tlsstart = curtime();
2301 
2302 			ssl_err = SSL_ERROR_WANT_READ;
2303 			save_errno = 0;
2304 			do
2305 			{
2306 				tlsret = tls_retry(srv_ssl, rfd, wfd, tlsstart,
2307 						TimeOuts.to_starttls, ssl_err,
2308 						"server");
2309 				if (tlsret <= 0)
2310 				{
2311 					if (LogLevel > 5)
2312 					{
2313 						unsigned long l;
2314 						const char *sr;
2315 
2316 						l = ERR_peek_error();
2317 						sr = ERR_reason_error_string(l);
2318 
2319 						sm_syslog(LOG_WARNING, NOQID,
2320 							  "STARTTLS=server, error: accept failed=%d, reason=%s, SSL_error=%d, errno=%d, retry=%d, relay=%.100s",
2321 							  r, sr == NULL ? "unknown"
2322 									: sr,
2323 							  ssl_err, save_errno,
2324 							  tlsret, CurSmtpClient);
2325 						tlslogerr(LOG_WARNING, 9, "server");
2326 					}
2327 					tls_ok_srv = false;
2328 					SM_SSL_FREE(srv_ssl);
2329 
2330 					/*
2331 					**  according to the next draft of
2332 					**  RFC 2487 the connection should
2333 					**  be dropped
2334 					**
2335 					**  arrange to ignore any current
2336 					**  send list
2337 					*/
2338 
2339 					e->e_sendqueue = NULL;
2340 					goto doquit;
2341 				}
2342 
2343 				r = SSL_accept(srv_ssl);
2344 				save_errno = 0;
2345 				if (r <= 0)
2346 					ssl_err = SSL_get_error(srv_ssl, r);
2347 			} while (r <= 0);
2348 
2349 			/* ignore return code for now, it's in {verify} */
2350 			(void) tls_get_info(srv_ssl, true,
2351 					    CurSmtpClient,
2352 					    &BlankEnvelope.e_macro,
2353 					    bitset(SRV_VRFY_CLT, features));
2354 
2355 			/*
2356 			**  call Stls_client to find out whether
2357 			**  to accept the connection from the client
2358 			*/
2359 
2360 			saveQuickAbort = QuickAbort;
2361 			saveSuprErrs = SuprErrs;
2362 			SuprErrs = true;
2363 			QuickAbort = false;
2364 			if (rscheck("tls_client",
2365 				     macvalue(macid("{verify}"), e),
2366 				     "STARTTLS", e,
2367 				     RSF_RMCOMM|RSF_COUNT,
2368 				     5, NULL, NOQID, NULL, NULL) != EX_OK ||
2369 			    Errors > 0)
2370 			{
2371 				extern char MsgBuf[];
2372 
2373 				if (MsgBuf[0] != '\0' && ISSMTPREPLY(MsgBuf))
2374 					nullserver = newstr(MsgBuf);
2375 				else
2376 					nullserver = "503 5.7.0 Authentication required.";
2377 			}
2378 			QuickAbort = saveQuickAbort;
2379 			SuprErrs = saveSuprErrs;
2380 
2381 			tls_ok_srv = false;	/* don't offer STARTTLS again */
2382 			first = true;
2383 			n_helo = 0;
2384 # if SASL
2385 			if (sasl_ok)
2386 			{
2387 				int cipher_bits;
2388 				bool verified;
2389 				char *s, *v, *c;
2390 
2391 				s = macvalue(macid("{cipher_bits}"), e);
2392 				v = macvalue(macid("{verify}"), e);
2393 				c = macvalue(macid("{cert_subject}"), e);
2394 				verified = (v != NULL && strcmp(v, "OK") == 0);
2395 				if (s != NULL && (cipher_bits = atoi(s)) > 0)
2396 				{
2397 #  if SASL >= 20000
2398 					ext_ssf = cipher_bits;
2399 					auth_id = verified ? c : NULL;
2400 					sasl_ok = ((sasl_setprop(conn,
2401 							SASL_SSF_EXTERNAL,
2402 							&ext_ssf) == SASL_OK) &&
2403 						   (sasl_setprop(conn,
2404 							SASL_AUTH_EXTERNAL,
2405 							auth_id) == SASL_OK));
2406 #  else /* SASL >= 20000 */
2407 					ext_ssf.ssf = cipher_bits;
2408 					ext_ssf.auth_id = verified ? c : NULL;
2409 					sasl_ok = sasl_setprop(conn,
2410 							SASL_SSF_EXTERNAL,
2411 							&ext_ssf) == SASL_OK;
2412 #  endif /* SASL >= 20000 */
2413 					mechlist = NULL;
2414 					if (sasl_ok)
2415 						n_mechs = saslmechs(conn,
2416 								    &mechlist);
2417 				}
2418 			}
2419 # endif /* SASL */
2420 
2421 			/* switch to secure connection */
2422 			if (sfdctls(&InChannel, &OutChannel, srv_ssl) == 0)
2423 			{
2424 				tls_active = true;
2425 # if PIPELINING
2426 				(void) sm_io_autoflush(InChannel, OutChannel);
2427 # endif
2428 			}
2429 			else
2430 			{
2431 				/*
2432 				**  XXX this is an internal error
2433 				**  how to deal with it?
2434 				**  we can't generate an error message
2435 				**  since the other side switched to an
2436 				**  encrypted layer, but we could not...
2437 				**  just "hang up"?
2438 				*/
2439 
2440 				nullserver = "454 4.3.3 TLS not available: can't switch to encrypted layer";
2441 				syserr("STARTTLS: can't switch to encrypted layer");
2442 			}
2443 		  tls_done:
2444 			if (smtps)
2445 			{
2446 				if (tls_active)
2447 					goto greeting;
2448 				else
2449 					goto doquit;
2450 			}
2451 			break;
2452 #endif /* STARTTLS */
2453 
2454 		  case CMDHELO:		/* hello -- introduce yourself */
2455 		  case CMDEHLO:		/* extended hello */
2456 			DELAY_CONN("EHLO");
2457 			if (c->cmd_code == CMDEHLO)
2458 			{
2459 				protocol = GET_PROTOCOL();
2460 				SmtpPhase = "server EHLO";
2461 			}
2462 			else
2463 			{
2464 				protocol = "SMTP";
2465 				SmtpPhase = "server HELO";
2466 			}
2467 
2468 			/* avoid denial-of-service */
2469 			STOP_IF_ATTACK(checksmtpattack(&n_helo, MAXHELOCOMMANDS,
2470 							true, "HELO/EHLO", e));
2471 
2472 #if 0
2473 			/* RFC2821 4.1.4 allows duplicate HELO/EHLO */
2474 			/* check for duplicate HELO/EHLO per RFC 1651 4.2 */
2475 			if (gothello)
2476 			{
2477 				usrerr("503 %s Duplicate HELO/EHLO",
2478 				       MyHostName);
2479 				break;
2480 			}
2481 #endif /* 0 */
2482 
2483 			/* check for valid domain name (re 1123 5.2.5) */
2484 			if (*p == '\0' && !AllowBogusHELO)
2485 			{
2486 				usrerr("501 %s requires domain address",
2487 					cmdbuf);
2488 				break;
2489 			}
2490 
2491 			/* check for long domain name (hides Received: info) */
2492 			if (strlen(p) > MAXNAME) /* EAI:ok:EHLO name must be ASCII */
2493 			{
2494 				usrerr("501 Invalid domain name");
2495 				if (LogLevel > 9)
2496 					sm_syslog(LOG_INFO, CurEnv->e_id,
2497 						  "invalid domain name (too long) from %s",
2498 						  CurSmtpClient);
2499 				break;
2500 			}
2501 
2502 			ok = true;
2503 			for (q = p; *q != '\0'; q++)
2504 			{
2505 				if (!isascii(*q))
2506 					break;
2507 				if (isalnum(*q))
2508 					continue;
2509 				if (isspace(*q))
2510 				{
2511 					*q = '\0';
2512 
2513 					/* only complain if strict check */
2514 					ok = AllowBogusHELO;
2515 
2516 					/* allow trailing whitespace */
2517 					while (!ok && *++q != '\0' &&
2518 					       isspace(*q))
2519 						;
2520 					if (*q == '\0')
2521 						ok = true;
2522 					break;
2523 				}
2524 				if (strchr("[].-_#:", *q) == NULL)
2525 					break;
2526 			}
2527 
2528 			if (*q == '\0' && ok)
2529 			{
2530 				q = "pleased to meet you";
2531 				sendinghost = sm_strdup_x(p);
2532 			}
2533 			else if (!AllowBogusHELO)
2534 			{
2535 				usrerr("501 Invalid domain name");
2536 				if (LogLevel > 9)
2537 					sm_syslog(LOG_INFO, CurEnv->e_id,
2538 						  "invalid domain name (%s) from %.100s",
2539 						  p, CurSmtpClient);
2540 				break;
2541 			}
2542 			else
2543 			{
2544 				q = "accepting invalid domain name";
2545 			}
2546 
2547 			if (gothello || smtp.sm_gotmail)
2548 				CLEAR_STATE(cmdbuf);
2549 
2550 #if MILTER
2551 			if (smtp.sm_milterlist && smtp.sm_milterize &&
2552 			    !bitset(EF_DISCARD, e->e_flags))
2553 			{
2554 				char state;
2555 				char *response;
2556 
2557 				response = milter_helo(p, e, &state);
2558 				switch (state)
2559 				{
2560 				  case SMFIR_REJECT:
2561 					if (MilterLogLevel > 3)
2562 						sm_syslog(LOG_INFO, e->e_id,
2563 							  "Milter: helo=%s, reject=Command rejected",
2564 							  p);
2565 					nullserver = "Command rejected";
2566 					smtp.sm_milterize = false;
2567 					break;
2568 
2569 				  case SMFIR_TEMPFAIL:
2570 					if (MilterLogLevel > 3)
2571 						sm_syslog(LOG_INFO, e->e_id,
2572 							  "Milter: helo=%s, reject=%s",
2573 							  p, MSG_TEMPFAIL);
2574 					tempfail = true;
2575 					smtp.sm_milterize = false;
2576 					break;
2577 
2578 				  case SMFIR_REPLYCODE:
2579 					if (MilterLogLevel > 3)
2580 						sm_syslog(LOG_INFO, e->e_id,
2581 							  "Milter: helo=%s, reject=%s",
2582 							  p, response);
2583 					if (strncmp(response, "421 ", 4) != 0
2584 					    && strncmp(response, "421-", 4) != 0)
2585 					{
2586 						nullserver = newstr(response);
2587 						smtp.sm_milterize = false;
2588 						break;
2589 					}
2590 					/* FALLTHROUGH */
2591 
2592 				  case SMFIR_SHUTDOWN:
2593 					if (MilterLogLevel > 3 &&
2594 					    response == NULL)
2595 						sm_syslog(LOG_INFO, e->e_id,
2596 							  "Milter: helo=%s, reject=421 4.7.0 %s closing connection",
2597 							  p, MyHostName);
2598 					tempfail = true;
2599 					smtp.sm_milterize = false;
2600 					if (response != NULL)
2601 					{
2602 						/* Can't use ("%s", ...) due to usrerr() requirements */
2603 						usrerr(response);
2604 					}
2605 					else
2606 					{
2607 						message("421 4.7.0 %s closing connection",
2608 							MyHostName);
2609 					}
2610 					/* arrange to ignore send list */
2611 					e->e_sendqueue = NULL;
2612 					lognullconnection = false;
2613 					goto doquit;
2614 				}
2615 				if (response != NULL)
2616 					sm_free(response);
2617 
2618 				/*
2619 				**  If quarantining by a connect/ehlo action,
2620 				**  save between messages
2621 				*/
2622 
2623 				if (smtp.sm_quarmsg == NULL &&
2624 				    e->e_quarmsg != NULL)
2625 					smtp.sm_quarmsg = newstr(e->e_quarmsg);
2626 			}
2627 #endif /* MILTER */
2628 			gothello = true;
2629 
2630 			/* print HELO response message */
2631 			if (c->cmd_code != CMDEHLO)
2632 			{
2633 				message("250 %s Hello %s, %s",
2634 					MyHostName, CurSmtpClient, q);
2635 				break;
2636 			}
2637 
2638 			message("250-%s Hello %s, %s",
2639 				MyHostName, CurSmtpClient, q);
2640 
2641 			/* offer ENHSC even for nullserver */
2642 			if (nullserver != NULL)
2643 			{
2644 				message("250 ENHANCEDSTATUSCODES");
2645 				break;
2646 			}
2647 
2648 			/*
2649 			**  print EHLO features list
2650 			**
2651 			**  Note: If you change this list,
2652 			**	  remember to update 'helpfile'
2653 			*/
2654 
2655 			message("250-ENHANCEDSTATUSCODES");
2656 #if PIPELINING
2657 			if (bitset(SRV_OFFER_PIPE, features))
2658 				message("250-PIPELINING");
2659 #endif
2660 			if (bitset(SRV_OFFER_EXPN, features))
2661 			{
2662 				message("250-EXPN");
2663 				if (bitset(SRV_OFFER_VERB, features))
2664 					message("250-VERB");
2665 			}
2666 #if MIME8TO7
2667 			message("250-8BITMIME");
2668 #endif
2669 			if (MaxMessageSize > 0)
2670 				message("250-SIZE %ld", MaxMessageSize);
2671 			else
2672 				message("250-SIZE");
2673 #if DSN
2674 			if (SendMIMEErrors && bitset(SRV_OFFER_DSN, features))
2675 				message("250-DSN");
2676 #endif
2677 #if USE_EAI
2678 			if (bitset(SRV_OFFER_EAI, features))
2679 				message("250-SMTPUTF8");
2680 #endif
2681 			if (bitset(SRV_OFFER_ETRN, features))
2682 				message("250-ETRN");
2683 #if SASL
2684 			if (sasl_ok && mechlist != NULL && *mechlist != '\0')
2685 				message("250-AUTH %s", mechlist);
2686 #endif
2687 #if STARTTLS
2688 			if (tls_ok_srv && bitset(SRV_OFFER_TLS, features))
2689 				message("250-STARTTLS");
2690 #endif
2691 			if (DeliverByMin > 0)
2692 				message("250-DELIVERBY %ld",
2693 					(long) DeliverByMin);
2694 			else if (DeliverByMin == 0)
2695 				message("250-DELIVERBY");
2696 
2697 			/* < 0: no deliver-by */
2698 
2699 			message("250 HELP");
2700 			break;
2701 
2702 		  case CMDMAIL:		/* mail -- designate sender */
2703 			SmtpPhase = "server MAIL";
2704 			DELAY_CONN("MAIL");
2705 
2706 			/* check for validity of this command */
2707 			if (!gothello && bitset(PRIV_NEEDMAILHELO, PrivacyFlags))
2708 			{
2709 				usrerr("503 5.0.0 Polite people say HELO first");
2710 				break;
2711 			}
2712 			if (smtp.sm_gotmail)
2713 			{
2714 				usrerr("503 5.5.0 Sender already specified");
2715 				break;
2716 			}
2717 #if SASL
2718 			if (bitset(SRV_REQ_AUTH, features) &&
2719 			    authenticating != SASL_IS_AUTH)
2720 			{
2721 				usrerr("530 5.7.0 Authentication required");
2722 				break;
2723 			}
2724 #endif /* SASL */
2725 
2726 			p = skipword(p, "from");
2727 			if (p == NULL)
2728 				break;
2729 			if (tempfail)
2730 			{
2731 				if (LogLevel > 9)
2732 					sm_syslog(LOG_INFO, e->e_id,
2733 						  "SMTP MAIL command (%.100s) from %s tempfailed (due to previous checks)",
2734 						  p, CurSmtpClient);
2735 				/* Can't use ("%s", ...) due to usrerr() requirements */
2736 				usrerr(MSG_TEMPFAIL);
2737 				break;
2738 			}
2739 
2740 			/* make sure we know who the sending host is */
2741 			if (sendinghost == NULL)
2742 				sendinghost = peerhostname;
2743 
2744 
2745 #if SM_HEAP_CHECK
2746 			if (sm_debug_active(&DebugLeakSmtp, 1))
2747 			{
2748 				sm_heap_newgroup();
2749 				sm_dprintf("smtp() heap group #%d\n",
2750 					sm_heap_group());
2751 			}
2752 #endif /* SM_HEAP_CHECK */
2753 
2754 			if (Errors > 0)
2755 				goto undo_no_pm;
2756 			if (!gothello)
2757 			{
2758 				auth_warning(e, "%s didn't use HELO protocol",
2759 					     CurSmtpClient);
2760 			}
2761 #ifdef PICKY_HELO_CHECK
2762 			if (sm_strcasecmp(sendinghost, peerhostname) != 0 &&
2763 			    (sm_strcasecmp(peerhostname, "localhost") != 0 ||
2764 			     sm_strcasecmp(sendinghost, MyHostName) != 0))
2765 			{
2766 				auth_warning(e, "Host %s claimed to be %s",
2767 					     CurSmtpClient, sendinghost);
2768 			}
2769 #endif /* PICKY_HELO_CHECK */
2770 
2771 			if (protocol == NULL)
2772 				protocol = "SMTP";
2773 			macdefine(&e->e_macro, A_PERM, 'r', protocol);
2774 			macdefine(&e->e_macro, A_PERM, 's', sendinghost);
2775 
2776 			if (Errors > 0)
2777 				goto undo_no_pm;
2778 			smtp.sm_nrcpts = 0;
2779 			n_badrcpts = 0;
2780 			macdefine(&e->e_macro, A_PERM, macid("{ntries}"), "0");
2781 			macdefine(&e->e_macro, A_PERM, macid("{nrcpts}"), "0");
2782 			macdefine(&e->e_macro, A_PERM, macid("{nbadrcpts}"),
2783 				"0");
2784 			e->e_flags |= EF_CLRQUEUE;
2785 			sm_setproctitle(true, e, "%s %s: %.80s",
2786 					qid_printname(e),
2787 					CurSmtpClient, inp);
2788 
2789 			/* do the processing */
2790 		    SM_TRY
2791 		    {
2792 			extern char *FullName;
2793 #if _FFR_8BITENVADDR
2794 			char *origp;
2795 			char iaddr[MAXLINE * 2];
2796 			int len;
2797 #else
2798 # define origp	p
2799 #endif
2800 
2801 			QuickAbort = true;
2802 			SM_FREE(FullName);
2803 #if _FFR_8BITENVADDR
2804 			len = sizeof(iaddr);
2805 			origp = p;
2806 
2807 			/* HACK!!!! p is more than the address! */
2808 			p = quote_internal_chars(p, iaddr, &len, NULL);
2809 #endif
2810 
2811 			/* must parse sender first */
2812 			delimptr = NULL;
2813 			setsender(p, e, &delimptr, ' ', false);
2814 			if (delimptr != NULL && *delimptr != '\0')
2815 			{
2816 				*delimptr++ = '\0';
2817 #if _FFR_8BITENVADDR
2818 				len = sizeof(iaddr) - (delimptr - iaddr);
2819 				(void) dequote_internal_chars(delimptr, delimptr, len);
2820 #endif
2821 			}
2822 			if (Errors > 0)
2823 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2824 
2825 			/* Successfully set e_from, allow logging */
2826 			e->e_flags |= EF_LOGSENDER;
2827 
2828 			/* put resulting triple from parseaddr() into macros */
2829 			if (e->e_from.q_mailer != NULL)
2830 				 macdefine(&e->e_macro, A_PERM,
2831 					macid("{mail_mailer}"),
2832 					e->e_from.q_mailer->m_name);
2833 			else
2834 				 macdefine(&e->e_macro, A_PERM,
2835 					macid("{mail_mailer}"), NULL);
2836 			if (e->e_from.q_host != NULL)
2837 				macdefine(&e->e_macro, A_PERM,
2838 					macid("{mail_host}"),
2839 					e->e_from.q_host);
2840 			else
2841 				macdefine(&e->e_macro, A_PERM,
2842 					macid("{mail_host}"), "localhost");
2843 			if (e->e_from.q_user != NULL)
2844 				macdefine(&e->e_macro, A_PERM,
2845 					macid("{mail_addr}"),
2846 					e->e_from.q_user);
2847 			else
2848 				macdefine(&e->e_macro, A_PERM,
2849 					macid("{mail_addr}"), NULL);
2850 			if (Errors > 0)
2851 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2852 
2853 			/* check for possible spoofing */
2854 			if (RealUid != 0 && OpMode == MD_SMTP &&
2855 			    !wordinclass(RealUserName, 't') &&
2856 			    (!bitnset(M_LOCALMAILER,
2857 				      e->e_from.q_mailer->m_flags) ||
2858 			     strcmp(e->e_from.q_user, RealUserName) != 0))
2859 			{
2860 				auth_warning(e, "%s owned process doing -bs",
2861 					RealUserName);
2862 			}
2863 
2864 			/* reset to default value */
2865 			SevenBitInput = SevenBitInput_Saved;
2866 
2867 			/* now parse ESMTP arguments */
2868 			e->e_msgsize = 0;
2869 			addr = p;
2870 			parse_esmtp_args(e, NULL, origp, delimptr, "MAIL", args,
2871 					mail_esmtp_args);
2872 			if (Errors > 0)
2873 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2874 
2875 #if USE_EAI
2876 			if (e->e_smtputf8)
2877 			{
2878 				protocol = GET_PROTOCOL();
2879 				macdefine(&e->e_macro, A_PERM, 'r', protocol);
2880 			}
2881 
2882 			/* UTF8 addresses are only legal with SMTPUTF8 */
2883 /* XXX different error if SMTPUTF8 is not enabled? */
2884 			CHECK_UTF8_ADDR(e->e_from.q_paddr, q);
2885 			if (q != NULL)
2886 			{
2887 				usrerr(q);
2888 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2889 			}
2890 #endif
2891 
2892 #if SASL
2893 # if _FFR_AUTH_PASSING
2894 			/* set the default AUTH= if the sender didn't */
2895 			if (e->e_auth_param == NULL)
2896 			{
2897 				/* XXX only do this for an MSA? */
2898 				e->e_auth_param = macvalue(macid("{auth_authen}"),
2899 							   e);
2900 				if (e->e_auth_param == NULL)
2901 					e->e_auth_param = "<>";
2902 
2903 				/*
2904 				**  XXX should we invoke Strust_auth now?
2905 				**  authorizing as the client that just
2906 				**  authenticated, so we'll trust implicitly
2907 				*/
2908 			}
2909 # endif /* _FFR_AUTH_PASSING */
2910 #endif /* SASL */
2911 
2912 			/* do config file checking of the sender */
2913 			macdefine(&e->e_macro, A_PERM,
2914 				macid("{addr_type}"), "e s");
2915 #if _FFR_MAIL_MACRO
2916 			/* make the "real" sender address available */
2917 			macdefine(&e->e_macro, A_TEMP, macid("{mail_from}"),
2918 				  e->e_from.q_paddr);
2919 #endif
2920 			if (rscheck("check_mail", addr,
2921 				    NULL, e, RSF_RMCOMM|RSF_COUNT, 3,
2922 				    NULL, e->e_id, NULL, NULL) != EX_OK ||
2923 			    Errors > 0)
2924 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2925 			macdefine(&e->e_macro, A_PERM,
2926 				  macid("{addr_type}"), NULL);
2927 
2928 			if (MaxMessageSize > 0 &&
2929 			    (e->e_msgsize > MaxMessageSize ||
2930 			     e->e_msgsize < 0))
2931 			{
2932 				usrerr("552 5.2.3 Message size exceeds fixed maximum message size (%ld)",
2933 					MaxMessageSize);
2934 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2935 			}
2936 
2937 			/*
2938 			**  XXX always check whether there is at least one fs
2939 			**  with enough space?
2940 			**  However, this may not help much: the queue group
2941 			**  selection may later on select a FS that hasn't
2942 			**  enough space.
2943 			*/
2944 
2945 			if ((NumFileSys == 1 || NumQueue == 1) &&
2946 			    !enoughdiskspace(e->e_msgsize, e)
2947 #if _FFR_ANY_FREE_FS
2948 			    && !filesys_free(e->e_msgsize)
2949 #endif
2950 			   )
2951 			{
2952 				/*
2953 				**  We perform this test again when the
2954 				**  queue directory is selected, in collect.
2955 				*/
2956 
2957 				usrerr("452 4.4.5 Insufficient disk space; try again later");
2958 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2959 			}
2960 			if (Errors > 0)
2961 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2962 
2963 			LogUsrErrs = true;
2964 #if MILTER
2965 			if (smtp.sm_milterlist && smtp.sm_milterize &&
2966 			    !bitset(EF_DISCARD, e->e_flags))
2967 			{
2968 				char state;
2969 				char *response;
2970 
2971 				response = milter_envfrom(args, e, &state);
2972 				MILTER_REPLY("from");
2973 			}
2974 #endif /* MILTER */
2975 			if (Errors > 0)
2976 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2977 
2978 			message("250 2.1.0 Sender ok");
2979 			smtp.sm_gotmail = true;
2980 		    }
2981 		    SM_EXCEPT(exc, "[!F]*")
2982 		    {
2983 			/*
2984 			**  An error occurred while processing a MAIL command.
2985 			**  Jump to the common error handling code.
2986 			*/
2987 
2988 			sm_exc_free(exc);
2989 			goto undo_no_pm;
2990 		    }
2991 		    SM_END_TRY
2992 			break;
2993 
2994 		  undo_no_pm:
2995 			e->e_flags &= ~EF_PM_NOTIFY;
2996 		  undo:
2997 			break;
2998 
2999 		  case CMDRCPT:		/* rcpt -- designate recipient */
3000 			DELAY_CONN("RCPT");
3001 			macdefine(&e->e_macro, A_PERM,
3002 				macid("{rcpt_mailer}"), NULL);
3003 			macdefine(&e->e_macro, A_PERM,
3004 				macid("{rcpt_host}"), NULL);
3005 			macdefine(&e->e_macro, A_PERM,
3006 				macid("{rcpt_addr}"), NULL);
3007 #if MILTER
3008 			(void) memset(&addr_st, '\0', sizeof(addr_st));
3009 			a = NULL;
3010 			milter_rcpt_added = false;
3011 			smtp.sm_e_nrcpts_orig = e->e_nrcpts;
3012 #endif
3013 #if _FFR_BADRCPT_SHUTDOWN
3014 			/*
3015 			**  hack to deal with hack, see below:
3016 			**  n_badrcpts is increased if limit is reached.
3017 			*/
3018 
3019 			n_badrcpts_adj = (BadRcptThrottle > 0 &&
3020 					  n_badrcpts > BadRcptThrottle &&
3021 					  LogLevel > 5)
3022 					  ? n_badrcpts - 1 : n_badrcpts;
3023 			if (BadRcptShutdown > 0 &&
3024 			    n_badrcpts_adj >= BadRcptShutdown &&
3025 			    (BadRcptShutdownGood == 0 ||
3026 			     smtp.sm_nrcpts == 0 ||
3027 			     (n_badrcpts_adj * 100 /
3028 			      (smtp.sm_nrcpts + n_badrcpts) >=
3029 			      BadRcptShutdownGood)))
3030 			{
3031 				if (LogLevel > 5)
3032 					sm_syslog(LOG_INFO, e->e_id,
3033 						  "%s: Possible SMTP RCPT flood, shutting down connection.",
3034 						  CurSmtpClient);
3035 				message("421 4.7.0 %s Too many bad recipients; closing connection",
3036 				MyHostName);
3037 
3038 				/* arrange to ignore any current send list */
3039 				e->e_sendqueue = NULL;
3040 				goto doquit;
3041 			}
3042 #endif /* _FFR_BADRCPT_SHUTDOWN */
3043 			if (BadRcptThrottle > 0 &&
3044 			    n_badrcpts >= BadRcptThrottle)
3045 			{
3046 				if (LogLevel > 5 &&
3047 				    n_badrcpts == BadRcptThrottle)
3048 				{
3049 					sm_syslog(LOG_INFO, e->e_id,
3050 						  "%s: Possible SMTP RCPT flood, throttling.",
3051 						  CurSmtpClient);
3052 
3053 					/* To avoid duplicated message */
3054 					n_badrcpts++;
3055 				}
3056 				NBADRCPTS;
3057 
3058 				/*
3059 				**  Don't use exponential backoff for now.
3060 				**  Some systems will open more connections
3061 				**  and actually overload the receiver even
3062 				**  more.
3063 				*/
3064 
3065 				(void) sleep(BadRcptThrottleDelay);
3066 			}
3067 			if (!smtp.sm_gotmail)
3068 			{
3069 				usrerr("503 5.0.0 Need MAIL before RCPT");
3070 				break;
3071 			}
3072 			SmtpPhase = "server RCPT";
3073 		    SM_TRY
3074 		    {
3075 #if _FFR_8BITENVADDR
3076 			char iaddr[MAXLINE * 2];
3077 			int len;
3078 			char *origp;
3079 #endif
3080 
3081 			QuickAbort = true;
3082 			LogUsrErrs = true;
3083 
3084 			/* limit flooding of our machine */
3085 			if (MaxRcptPerMsg > 0 &&
3086 			    smtp.sm_nrcpts >= MaxRcptPerMsg)
3087 			{
3088 				/* sleep(1); / * slow down? */
3089 				usrerr("452 4.5.3 Too many recipients");
3090 				goto rcpt_done;
3091 			}
3092 
3093 			if (!SM_IS_INTERACTIVE(e->e_sendmode)
3094 #if _FFR_DM_ONE
3095 			    && (NotFirstDelivery || SM_DM_ONE != e->e_sendmode)
3096 #endif
3097 			   )
3098 				e->e_flags |= EF_VRFYONLY;
3099 
3100 #if MILTER
3101 			/*
3102 			**  Do not expand recipients at RCPT time (in the call
3103 			**  to recipient()) if a milter can delete or reject
3104 			**  a RCPT.  If they are expanded, it is impossible
3105 			**  for removefromlist() to figure out the expanded
3106 			**  members of the original recipient and mark them
3107 			**  as QS_DONTSEND.
3108 			*/
3109 
3110 			if (smtp.sm_milterlist && smtp.sm_milterize &&
3111 			      !bitset(EF_DISCARD, e->e_flags) &&
3112 			    (smtp.sm_milters.mis_flags &
3113 			     (MIS_FL_DEL_RCPT|MIS_FL_REJ_RCPT)) != 0)
3114 				e->e_flags |= EF_VRFYONLY;
3115 			milter_cmd_done = false;
3116 			milter_cmd_safe = false;
3117 #endif /* MILTER */
3118 
3119 			p = skipword(p, "to");
3120 			if (p == NULL)
3121 				goto rcpt_done;
3122 			macdefine(&e->e_macro, A_PERM,
3123 				macid("{addr_type}"), "e r");
3124 #if _FFR_8BITENVADDR
3125 			len = sizeof(iaddr);
3126 			origp = p;
3127 
3128 			/* HACK!!!! p is more than the address! */
3129 			p = quote_internal_chars(p, iaddr, &len, NULL);
3130 #endif
3131 			a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', &delimptr,
3132 				      e, true);
3133 			macdefine(&e->e_macro, A_PERM,
3134 				macid("{addr_type}"), NULL);
3135 			if (Errors > 0)
3136 				goto rcpt_done;
3137 			if (a == NULL)
3138 			{
3139 				usrerr("501 5.0.0 Missing recipient");
3140 				goto rcpt_done;
3141 			}
3142 #if USE_EAI
3143 			CHECK_UTF8_ADDR(a->q_paddr, q);
3144 			if (q != NULL)
3145 			{
3146 				usrerr(q);
3147 				goto rcpt_done;
3148 			}
3149 #endif
3150 
3151 			if (delimptr != NULL && *delimptr != '\0')
3152 			{
3153 				*delimptr++ = '\0';
3154 #if _FFR_8BITENVADDR
3155 				len = sizeof(iaddr) - (delimptr - iaddr);
3156 				(void) dequote_internal_chars(delimptr, delimptr, len);
3157 #endif
3158 			}
3159 
3160 			/* put resulting triple from parseaddr() into macros */
3161 			if (a->q_mailer != NULL)
3162 				macdefine(&e->e_macro, A_PERM,
3163 					macid("{rcpt_mailer}"),
3164 					a->q_mailer->m_name);
3165 			else
3166 				macdefine(&e->e_macro, A_PERM,
3167 					macid("{rcpt_mailer}"), NULL);
3168 			if (a->q_host != NULL)
3169 				macdefine(&e->e_macro, A_PERM,
3170 					macid("{rcpt_host}"), a->q_host);
3171 			else
3172 				macdefine(&e->e_macro, A_PERM,
3173 					macid("{rcpt_host}"), "localhost");
3174 			if (a->q_user != NULL)
3175 				macdefine(&e->e_macro, A_PERM,
3176 					macid("{rcpt_addr}"), a->q_user);
3177 			else
3178 				macdefine(&e->e_macro, A_PERM,
3179 					macid("{rcpt_addr}"), NULL);
3180 			if (Errors > 0)
3181 				goto rcpt_done;
3182 
3183 			/* now parse ESMTP arguments */
3184 			addr = sm_rpool_strdup_x(e->e_rpool, p);
3185 			parse_esmtp_args(e, a, origp, delimptr, "RCPT", args,
3186 					rcpt_esmtp_args);
3187 			if (Errors > 0)
3188 				goto rcpt_done;
3189 
3190 #if MILTER
3191 			/*
3192 			**  rscheck() can trigger an "exception"
3193 			**  in which case the execution continues at
3194 			**  SM_EXCEPT(exc, "[!F]*")
3195 			**  This means milter_cmd_safe is not set
3196 			**  and hence milter is not invoked.
3197 			**  Would it be "safe" to change that, i.e., use
3198 			**  milter_cmd_safe = true;
3199 			**  here so a milter is informed (if requested)
3200 			**  about RCPTs that are rejected by check_rcpt?
3201 			*/
3202 # if _FFR_MILTER_CHECK_REJECTIONS_TOO
3203 			milter_cmd_safe = true;
3204 # endif
3205 #endif
3206 
3207 			/* do config file checking of the recipient */
3208 			macdefine(&e->e_macro, A_PERM,
3209 				macid("{addr_type}"), "e r");
3210 			if (rscheck("check_rcpt", addr,
3211 				    NULL, e, RSF_RMCOMM|RSF_COUNT, 3,
3212 				    NULL, e->e_id, p_addr_st, NULL) != EX_OK ||
3213 			    Errors > 0)
3214 				goto rcpt_done;
3215 			macdefine(&e->e_macro, A_PERM,
3216 				macid("{addr_type}"), NULL);
3217 
3218 			/* If discarding, don't bother to verify user */
3219 			if (bitset(EF_DISCARD, e->e_flags))
3220 				a->q_state = QS_VERIFIED;
3221 #if MILTER
3222 			milter_cmd_safe = true;
3223 #endif
3224 
3225 			addbcc(a, e);
3226 			rcptmods(a, e);
3227 
3228 			/* save in recipient list after ESMTP mods */
3229 			a = recipient(a, &e->e_sendqueue, 0, e);
3230 			/* may trigger exception... */
3231 
3232 #if MILTER
3233 			milter_rcpt_added = true;
3234 #endif
3235 
3236 			if(!(Errors > 0) && QS_IS_BADADDR(a->q_state))
3237 			{
3238 				/* punt -- should keep message in ADDRESS.... */
3239 				usrerr("550 5.1.1 Addressee unknown");
3240 			}
3241 
3242 #if MILTER
3243 		rcpt_done:
3244 			if (smtp.sm_milterlist && smtp.sm_milterize &&
3245 			    !bitset(EF_DISCARD, e->e_flags))
3246 			{
3247 				char state;
3248 				char *response;
3249 
3250 				/* how to get the error codes? */
3251 				if (Errors > 0)
3252 				{
3253 					macdefine(&e->e_macro, A_PERM,
3254 						macid("{rcpt_mailer}"),
3255 						"error");
3256 					if (a != NULL &&
3257 					    a->q_status != NULL &&
3258 					    a->q_rstatus != NULL)
3259 					{
3260 						macdefine(&e->e_macro, A_PERM,
3261 							macid("{rcpt_host}"),
3262 							a->q_status);
3263 						macdefine(&e->e_macro, A_PERM,
3264 							macid("{rcpt_addr}"),
3265 							a->q_rstatus);
3266 					}
3267 					else
3268 					{
3269 						if (addr_st.q_host != NULL)
3270 							macdefine(&e->e_macro,
3271 								A_PERM,
3272 								macid("{rcpt_host}"),
3273 								addr_st.q_host);
3274 						if (addr_st.q_user != NULL)
3275 							macdefine(&e->e_macro,
3276 								A_PERM,
3277 								macid("{rcpt_addr}"),
3278 								addr_st.q_user);
3279 					}
3280 				}
3281 
3282 				response = milter_envrcpt(args, e, &state,
3283 							Errors > 0);
3284 				milter_cmd_done = true;
3285 				MILTER_REPLY("to");
3286 			}
3287 #endif /* MILTER */
3288 
3289 			/* no errors during parsing, but might be a duplicate */
3290 			e->e_to = a->q_paddr;
3291 			if (!(Errors > 0) && !QS_IS_BADADDR(a->q_state))
3292 			{
3293 				if (smtp.sm_nrcpts == 0)
3294 					initsys(e);
3295 				message("250 2.1.5 Recipient ok%s",
3296 					QS_IS_QUEUEUP(a->q_state) ?
3297 						" (will queue)" : "");
3298 				smtp.sm_nrcpts++;
3299 			}
3300 
3301 			/* Is this needed? */
3302 #if !MILTER
3303 		rcpt_done:
3304 #endif
3305 
3306 			macdefine(&e->e_macro, A_PERM,
3307 				macid("{rcpt_mailer}"), NULL);
3308 			macdefine(&e->e_macro, A_PERM,
3309 				macid("{rcpt_host}"), NULL);
3310 			macdefine(&e->e_macro, A_PERM,
3311 				macid("{rcpt_addr}"), NULL);
3312 			macdefine(&e->e_macro, A_PERM,
3313 				macid("{dsn_notify}"), NULL);
3314 
3315 			if (Errors > 0)
3316 			{
3317 				++n_badrcpts;
3318 				NBADRCPTS;
3319 			}
3320 		    }
3321 		    SM_EXCEPT(exc, "[!F]*")
3322 		    {
3323 			/* An exception occurred while processing RCPT */
3324 			e->e_flags &= ~(EF_FATALERRS|EF_PM_NOTIFY);
3325 			++n_badrcpts;
3326 			NBADRCPTS;
3327 #if MILTER
3328 			if (smtp.sm_milterlist && smtp.sm_milterize &&
3329 			    !bitset(EF_DISCARD, e->e_flags) &&
3330 			    !milter_cmd_done && milter_cmd_safe)
3331 			{
3332 				char state;
3333 				char *response;
3334 
3335 				macdefine(&e->e_macro, A_PERM,
3336 					macid("{rcpt_mailer}"), "error");
3337 
3338 				/* how to get the error codes? */
3339 				if (addr_st.q_host != NULL)
3340 					macdefine(&e->e_macro, A_PERM,
3341 						macid("{rcpt_host}"),
3342 						addr_st.q_host);
3343 				else if (a != NULL && a->q_status != NULL)
3344 					macdefine(&e->e_macro, A_PERM,
3345 						macid("{rcpt_host}"),
3346 						a->q_status);
3347 
3348 				if (addr_st.q_user != NULL)
3349 					macdefine(&e->e_macro, A_PERM,
3350 						macid("{rcpt_addr}"),
3351 						addr_st.q_user);
3352 				else if (a != NULL && a->q_rstatus != NULL)
3353 					macdefine(&e->e_macro, A_PERM,
3354 						macid("{rcpt_addr}"),
3355 						a->q_rstatus);
3356 
3357 				response = milter_envrcpt(args, e, &state,
3358 							true);
3359 				milter_cmd_done = true;
3360 				MILTER_REPLY("to");
3361 				macdefine(&e->e_macro, A_PERM,
3362 					macid("{rcpt_mailer}"), NULL);
3363 				macdefine(&e->e_macro, A_PERM,
3364 					macid("{rcpt_host}"), NULL);
3365 				macdefine(&e->e_macro, A_PERM,
3366 					macid("{rcpt_addr}"), NULL);
3367 			}
3368 			if (smtp.sm_milterlist && smtp.sm_milterize &&
3369 			    milter_rcpt_added && milter_cmd_done &&
3370 			    milter_cmd_fail)
3371 			{
3372 				(void) removefromlist(addr, &e->e_sendqueue, e);
3373 				milter_cmd_fail = false;
3374 				if (smtp.sm_e_nrcpts_orig < e->e_nrcpts)
3375 					e->e_nrcpts = smtp.sm_e_nrcpts_orig;
3376 			}
3377 #endif /* MILTER */
3378 		    }
3379 		    SM_END_TRY
3380 			break;
3381 
3382 		  case CMDDATA:		/* data -- text of mail */
3383 			DELAY_CONN("DATA");
3384 			if (!smtp_data(&smtp, e))
3385 				goto doquit;
3386 			break;
3387 
3388 		  case CMDRSET:		/* rset -- reset state */
3389 			if (tTd(94, 100))
3390 				message("451 4.0.0 Test failure");
3391 			else
3392 				message("250 2.0.0 Reset state");
3393 			CLEAR_STATE(cmdbuf);
3394 			break;
3395 
3396 		  case CMDVRFY:		/* vrfy -- verify address */
3397 		  case CMDEXPN:		/* expn -- expand address */
3398 			vrfy = c->cmd_code == CMDVRFY;
3399 			DELAY_CONN(vrfy ? "VRFY" : "EXPN");
3400 			if (tempfail)
3401 			{
3402 				if (LogLevel > 9)
3403 					sm_syslog(LOG_INFO, e->e_id,
3404 						  "SMTP %s command (%.100s) from %s tempfailed (due to previous checks)",
3405 						  vrfy ? "VRFY" : "EXPN",
3406 						  p, CurSmtpClient);
3407 
3408 				/* RFC 821 doesn't allow 4xy reply code */
3409 				usrerr("550 5.7.1 Please try again later");
3410 				break;
3411 			}
3412 			wt = checksmtpattack(&n_verifies, MAXVRFYCOMMANDS,
3413 					     false, vrfy ? "VRFY" : "EXPN", e);
3414 			STOP_IF_ATTACK(wt);
3415 			previous = curtime();
3416 			if ((vrfy && bitset(PRIV_NOVRFY, PrivacyFlags)) ||
3417 			    (!vrfy && !bitset(SRV_OFFER_EXPN, features)))
3418 			{
3419 				if (vrfy)
3420 					message("252 2.5.2 Cannot VRFY user; try RCPT to attempt delivery (or try finger)");
3421 				else
3422 					message("502 5.7.0 Sorry, we do not allow this operation");
3423 				if (LogLevel > 5)
3424 					sm_syslog(LOG_INFO, e->e_id,
3425 						  "%s: %s [rejected]",
3426 						  CurSmtpClient,
3427 						  shortenstring(inp, MAXSHORTSTR));
3428 				break;
3429 			}
3430 			else if (!gothello &&
3431 				 bitset(vrfy ? PRIV_NEEDVRFYHELO : PRIV_NEEDEXPNHELO,
3432 						PrivacyFlags))
3433 			{
3434 				usrerr("503 5.0.0 I demand that you introduce yourself first");
3435 				break;
3436 			}
3437 			if (Errors > 0)
3438 				break;
3439 			if (LogLevel > 5)
3440 				sm_syslog(LOG_INFO, e->e_id, "%s: %s",
3441 					  CurSmtpClient,
3442 					  shortenstring(inp, MAXSHORTSTR));
3443 		    SM_TRY
3444 		    {
3445 			QuickAbort = true;
3446 			vrfyqueue = NULL;
3447 			if (vrfy)
3448 				e->e_flags |= EF_VRFYONLY;
3449 			while (*p != '\0' && SM_ISSPACE(*p))
3450 				p++;
3451 			if (*p == '\0')
3452 			{
3453 				usrerr("501 5.5.2 Argument required");
3454 			}
3455 			else
3456 			{
3457 				/* do config file checking of the address */
3458 				if (rscheck(vrfy ? "check_vrfy" : "check_expn",
3459 					    p, NULL, e, RSF_RMCOMM, 3, NULL,
3460 					    NOQID, NULL, NULL) != EX_OK ||
3461 				    Errors > 0)
3462 					sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3463 				(void) sendtolist(p, NULLADDR, &vrfyqueue, 0, e);
3464 			}
3465 			if (wt > 0)
3466 			{
3467 				time_t t;
3468 
3469 				t = wt - (curtime() - previous);
3470 				if (t > 0)
3471 					(void) sleep(t);
3472 			}
3473 			if (Errors > 0)
3474 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3475 			if (vrfyqueue == NULL)
3476 			{
3477 				usrerr("554 5.5.2 Nothing to %s", vrfy ? "VRFY" : "EXPN");
3478 			}
3479 			while (vrfyqueue != NULL)
3480 			{
3481 				if (!QS_IS_UNDELIVERED(vrfyqueue->q_state))
3482 				{
3483 					vrfyqueue = vrfyqueue->q_next;
3484 					continue;
3485 				}
3486 
3487 				/* see if there is more in the vrfy list */
3488 				a = vrfyqueue;
3489 				while ((a = a->q_next) != NULL &&
3490 				       (!QS_IS_UNDELIVERED(a->q_state)))
3491 					continue;
3492 				printvrfyaddr(vrfyqueue, a == NULL, vrfy);
3493 				vrfyqueue = a;
3494 			}
3495 		    }
3496 		    SM_EXCEPT(exc, "[!F]*")
3497 		    {
3498 			/*
3499 			**  An exception occurred while processing VRFY/EXPN
3500 			*/
3501 
3502 			sm_exc_free(exc);
3503 			goto undo;
3504 		    }
3505 		    SM_END_TRY
3506 			break;
3507 
3508 		  case CMDETRN:		/* etrn -- force queue flush */
3509 			DELAY_CONN("ETRN");
3510 
3511 			/* Don't leak queue information via debug flags */
3512 			if (!bitset(SRV_OFFER_ETRN, features) || UseMSP ||
3513 			    (RealUid != 0 && RealUid != TrustedUid &&
3514 			     OpMode == MD_SMTP))
3515 			{
3516 				/* different message for MSA ? */
3517 				message("502 5.7.0 Sorry, we do not allow this operation");
3518 				if (LogLevel > 5)
3519 					sm_syslog(LOG_INFO, e->e_id,
3520 						  "%s: %s [rejected]",
3521 						  CurSmtpClient,
3522 						  shortenstring(inp, MAXSHORTSTR));
3523 				break;
3524 			}
3525 			if (tempfail)
3526 			{
3527 				if (LogLevel > 9)
3528 					sm_syslog(LOG_INFO, e->e_id,
3529 						  "SMTP ETRN command (%.100s) from %s tempfailed (due to previous checks)",
3530 						  p, CurSmtpClient);
3531 				/* Can't use ("%s", ...) due to usrerr() requirements */
3532 				usrerr(MSG_TEMPFAIL);
3533 				break;
3534 			}
3535 
3536 			if (strlen(p) <= 0)
3537 			{
3538 				usrerr("500 5.5.2 Parameter required");
3539 				break;
3540 			}
3541 
3542 			/* crude way to avoid denial-of-service attacks */
3543 			STOP_IF_ATTACK(checksmtpattack(&n_etrn, MAXETRNCOMMANDS,
3544 							true, "ETRN", e));
3545 
3546 			/*
3547 			**  Do config file checking of the parameter.
3548 			**  Even though we have srv_features now, we still
3549 			**  need this ruleset because the former is called
3550 			**  when the connection has been established, while
3551 			**  this ruleset is called when the command is
3552 			**  actually issued and therefore has all information
3553 			**  available to make a decision.
3554 			*/
3555 
3556 			if (rscheck("check_etrn", p, NULL, e, RSF_RMCOMM, 3,
3557 				    NULL, NOQID, NULL, NULL) != EX_OK ||
3558 			    Errors > 0)
3559 				break;
3560 
3561 			if (LogLevel > 5)
3562 				sm_syslog(LOG_INFO, e->e_id,
3563 					  "%s: ETRN %s", CurSmtpClient,
3564 					  shortenstring(p, MAXSHORTSTR));
3565 
3566 			id = p;
3567 			if (*id == '#')
3568 			{
3569 				int i, qgrp;
3570 
3571 				id++;
3572 				qgrp = name2qid(id);
3573 				if (!ISVALIDQGRP(qgrp))
3574 				{
3575 					usrerr("459 4.5.4 Queue %s unknown",
3576 					       id);
3577 					break;
3578 				}
3579 				for (i = 0; i < NumQueue && Queue[i] != NULL;
3580 				     i++)
3581 					Queue[i]->qg_nextrun = (time_t) -1;
3582 				Queue[qgrp]->qg_nextrun = 0;
3583 				ok = run_work_group(Queue[qgrp]->qg_wgrp,
3584 						    RWG_FORK|RWG_FORCE);
3585 				if (ok && Errors == 0)
3586 					message("250 2.0.0 Queuing for queue group %s started", id);
3587 				break;
3588 			}
3589 
3590 			if (*id == '@')
3591 				id++;
3592 			else
3593 				*--id = '@';
3594 
3595 			new = (QUEUE_CHAR *) sm_malloc(sizeof(QUEUE_CHAR));
3596 			if (new == NULL)
3597 			{
3598 				syserr("500 5.5.0 ETRN out of memory");
3599 				break;
3600 			}
3601 			new->queue_match = id;
3602 			new->queue_negate = false;
3603 			new->queue_next = NULL;
3604 			QueueLimitRecipient = new;
3605 			ok = runqueue(true, false, false, true);
3606 			sm_free(QueueLimitRecipient); /* XXX */
3607 			QueueLimitRecipient = NULL;
3608 			if (ok && Errors == 0)
3609 				message("250 2.0.0 Queuing for node %s started", p);
3610 			break;
3611 
3612 		  case CMDHELP:		/* help -- give user info */
3613 			DELAY_CONN("HELP");
3614 			help(p, e);
3615 			break;
3616 
3617 #define CHECK_OTHER(type) do	\
3618 	{							\
3619 		bool saveQuickAbort = QuickAbort;		\
3620 		extern char MsgBuf[];				\
3621 		int rsc;					\
3622 		QuickAbort = false;				\
3623 		if ((rsc = rscheck("check_other", inp, type, e,	\
3624 			    RSF_UNSTRUCTURED, 3, NULL, NOQID, NULL, NULL)) \
3625 			!= EX_OK ||				\
3626 		    Errors > 0)					\
3627 		{						\
3628 			if (strncmp(MsgBuf, "421 ", 4) == 0)	\
3629 			{					\
3630 				e->e_sendqueue = NULL;		\
3631 				goto doquit;			\
3632 			}					\
3633 		}						\
3634 		QuickAbort = saveQuickAbort;			\
3635 	} while (0)
3636 
3637 		  case CMDNOOP:		/* noop -- do nothing */
3638 			DELAY_CONN("NOOP");
3639 			STOP_IF_ATTACK(checksmtpattack(&n_noop, MaxNOOPCommands,
3640 							true, "NOOP", e));
3641 			CHECK_OTHER("2");
3642 			message("250 2.0.0 OK");
3643 			break;
3644 
3645 		  case CMDQUIT:		/* quit -- leave mail */
3646 			message("221 2.0.0 %s closing connection", MyHostName);
3647 #if PIPELINING
3648 			(void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
3649 #endif
3650 
3651 			if (smtp.sm_nrcpts > 0)
3652 				logundelrcpts(e, "aborted by sender", 9, false);
3653 
3654 			/* arrange to ignore any current send list */
3655 			e->e_sendqueue = NULL;
3656 
3657 #if STARTTLS
3658 			/* shutdown TLS connection */
3659 			if (tls_active)
3660 			{
3661 				(void) endtls(&srv_ssl, "server");
3662 				tls_active = false;
3663 			}
3664 #endif /* STARTTLS */
3665 #if SASL
3666 			if (authenticating == SASL_IS_AUTH)
3667 			{
3668 				sasl_dispose(&conn);
3669 				authenticating = SASL_NOT_AUTH;
3670 				/* XXX sasl_done(); this is a child */
3671 			}
3672 #endif /* SASL */
3673 
3674 doquit:
3675 			/* avoid future 050 messages */
3676 			disconnect(1, e);
3677 
3678 #if MILTER
3679 			/* close out milter filters */
3680 			milter_quit(e);
3681 #endif
3682 
3683 			if (tTd(92, 2))
3684 				sm_dprintf("QUIT: e_id=%s, EF_LOGSENDER=%d, LogLevel=%d\n",
3685 					e->e_id,
3686 					bitset(EF_LOGSENDER, e->e_flags),
3687 					LogLevel);
3688 			if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
3689 				logsender(e, NULL);
3690 			e->e_flags &= ~EF_LOGSENDER;
3691 
3692 			if (lognullconnection && LogLevel > 5 &&
3693 			    nullserver == NULL)
3694 			{
3695 				char *d;
3696 
3697 				d = macvalue(macid("{daemon_name}"), e);
3698 				if (d == NULL)
3699 					d = "stdin";
3700 
3701 				/*
3702 				**  even though this id is "bogus", it makes
3703 				**  it simpler to "grep" related events, e.g.,
3704 				**  timeouts for the same connection.
3705 				*/
3706 
3707 				sm_syslog(LOG_INFO, e->e_id,
3708 					  "%s did not issue MAIL/EXPN/VRFY/ETRN during connection to %s",
3709 					  CurSmtpClient, d);
3710 			}
3711 			if (tTd(93, 100))
3712 			{
3713 				/* return to handle next connection */
3714 #if SM_HEAP_CHECK
3715 # define SM_HC_TRIGGER "heapdump"
3716 				if (sm_debug_active(&SmHeapCheck, 2)
3717 				    && access(SM_HC_TRIGGER, F_OK) == 0
3718 				   )
3719 				{
3720 					SM_FILE_T *out;
3721 
3722 					remove(SM_HC_TRIGGER);
3723 					out = sm_io_open(SmFtStdio,
3724 						SM_TIME_DEFAULT, SM_HC_TRIGGER ".heap",
3725 						SM_IO_APPEND, NULL);
3726 					if (out != NULL)
3727 					{
3728 						(void) sm_io_fprintf(out, SM_TIME_DEFAULT, "----------------------\n");
3729 						sm_heap_report(out,
3730 							sm_debug_level(&SmHeapCheck) - 1);
3731 						(void) sm_io_close(out, SM_TIME_DEFAULT);
3732 					}
3733 				}
3734 #endif /* SM_HEAP_CHECK */
3735 				return;
3736 			}
3737 			finis(true, true, ExitStat);
3738 			/* NOTREACHED */
3739 
3740 			/* just to avoid bogus warning from some compilers */
3741 			exit(EX_OSERR);
3742 
3743 		  case CMDVERB:		/* set verbose mode */
3744 			DELAY_CONN("VERB");
3745 			if (!bitset(SRV_OFFER_EXPN, features) ||
3746 			    !bitset(SRV_OFFER_VERB, features))
3747 			{
3748 				/* this would give out the same info */
3749 				message("502 5.7.0 Verbose unavailable");
3750 				break;
3751 			}
3752 			STOP_IF_ATTACK(checksmtpattack(&n_noop, MaxNOOPCommands,
3753 							true, "VERB", e));
3754 			CHECK_OTHER("2");
3755 			Verbose = 1;
3756 			set_delivery_mode(SM_DELIVER, e);
3757 			message("250 2.0.0 Verbose mode");
3758 			break;
3759 
3760 #if SMTPDEBUG
3761 		  case CMDDBGQSHOW:	/* show queues */
3762 			CHECK_OTHER("2");
3763 			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
3764 					     "Send Queue=");
3765 			printaddr(smioout, e->e_sendqueue, true);
3766 			break;
3767 
3768 		  case CMDDBGDEBUG:	/* set debug mode */
3769 			CHECK_OTHER("2");
3770 			tTsetup(tTdvect, sizeof(tTdvect), "0-99.1");
3771 			tTflag(p);
3772 			message("200 2.0.0 Debug set");
3773 			break;
3774 
3775 #else /* SMTPDEBUG */
3776 		  case CMDDBGQSHOW:	/* show queues */
3777 		  case CMDDBGDEBUG:	/* set debug mode */
3778 #endif /* SMTPDEBUG */
3779 		  case CMDLOGBOGUS:	/* bogus command */
3780 			DELAY_CONN("Bogus");
3781 			if (LogLevel > 0)
3782 				sm_syslog(LOG_CRIT, e->e_id,
3783 					  "\"%s\" command from %s (%.100s)",
3784 					  c->cmd_name, CurSmtpClient,
3785 					  anynet_ntoa(&RealHostAddr));
3786 			/* FALLTHROUGH */
3787 
3788 		  case CMDERROR:	/* unknown command */
3789 #if MAXBADCOMMANDS > 0
3790 			if (++n_badcmds > MAXBADCOMMANDS)
3791 			{
3792   stopattack:
3793 				message("421 4.7.0 %s Too many bad commands; closing connection",
3794 					MyHostName);
3795 
3796 				/* arrange to ignore any current send list */
3797 				e->e_sendqueue = NULL;
3798 				goto doquit;
3799 			}
3800 #endif /* MAXBADCOMMANDS > 0 */
3801 
3802 #if MILTER && SMFI_VERSION > 2
3803 			if (smtp.sm_milterlist && smtp.sm_milterize &&
3804 			    !bitset(EF_DISCARD, e->e_flags))
3805 			{
3806 				char state;
3807 				char *response;
3808 
3809 				if (MilterLogLevel > 9)
3810 					sm_syslog(LOG_INFO, e->e_id,
3811 						"Sending \"%s\" to Milter", inp);
3812 				response = milter_unknown(inp, e, &state);
3813 				MILTER_REPLY("unknown");
3814 				if (state == SMFIR_REPLYCODE ||
3815 				    state == SMFIR_REJECT ||
3816 				    state == SMFIR_TEMPFAIL ||
3817 				    state == SMFIR_SHUTDOWN)
3818 				{
3819 					/* MILTER_REPLY already gave an error */
3820 					break;
3821 				}
3822 			}
3823 #endif /* MILTER && SMFI_VERSION > 2 */
3824 
3825 			CHECK_OTHER("5");
3826 			usrerr("500 5.5.1 Command unrecognized: \"%s\"",
3827 			       SHOWSHRTCMDINREPLY(inp));
3828 			break;
3829 
3830 		  case CMDUNIMPL:
3831 			DELAY_CONN("Unimpl");
3832 			CHECK_OTHER("5");
3833 			usrerr("502 5.5.1 Command not implemented: \"%s\"",
3834 			       SHOWSHRTCMDINREPLY(inp));
3835 			break;
3836 
3837 		  default:
3838 			DELAY_CONN("default");
3839 			CHECK_OTHER("5");
3840 			errno = 0;
3841 			syserr("500 5.5.0 smtp: unknown code %d", c->cmd_code);
3842 			break;
3843 		}
3844 #if SASL
3845 		}
3846 #endif
3847 	    }
3848 	    SM_EXCEPT(exc, "[!F]*")
3849 	    {
3850 		/*
3851 		**  The only possible exception is "E:mta.quickabort".
3852 		**  There is nothing to do except fall through and loop.
3853 		*/
3854 	    }
3855 	    SM_END_TRY
3856 	}
3857 }
3858 /*
3859 **  SMTP_DATA -- implement the SMTP DATA command.
3860 **
3861 **	Parameters:
3862 **		smtp -- status of SMTP connection.
3863 **		e -- envelope.
3864 **
3865 **	Returns:
3866 **		true iff SMTP session can continue.
3867 **
3868 **	Side Effects:
3869 **		possibly sends message.
3870 */
3871 
3872 static bool
3873 smtp_data(smtp, e)
3874 	SMTP_T *smtp;
3875 	ENVELOPE *e;
3876 {
3877 #if MILTER
3878 	bool milteraccept;
3879 #endif
3880 	bool aborting;
3881 	bool doublequeue;
3882 	bool rv = true;
3883 	ADDRESS *a;
3884 	ENVELOPE *ee;
3885 	char *id;
3886 	char *oldid;
3887 	unsigned int features;
3888 	char buf[32];
3889 
3890 	SmtpPhase = "server DATA";
3891 	if (!smtp->sm_gotmail)
3892 	{
3893 		usrerr("503 5.0.0 Need MAIL command");
3894 		return true;
3895 	}
3896 	else if (smtp->sm_nrcpts <= 0)
3897 	{
3898 		usrerr("503 5.0.0 Need RCPT (recipient)");
3899 		return true;
3900 	}
3901 	(void) sm_snprintf(buf, sizeof(buf), "%u", smtp->sm_nrcpts);
3902 	if (rscheck("check_data", buf, NULL, e,
3903 		    RSF_RMCOMM|RSF_UNSTRUCTURED|RSF_COUNT, 3, NULL,
3904 		    e->e_id, NULL, NULL) != EX_OK)
3905 		return true;
3906 
3907 #if MILTER && SMFI_VERSION > 3
3908 	if (smtp->sm_milterlist && smtp->sm_milterize &&
3909 	    !bitset(EF_DISCARD, e->e_flags))
3910 	{
3911 		char state;
3912 		char *response;
3913 		int savelogusrerrs = LogUsrErrs;
3914 
3915 		response = milter_data_cmd(e, &state);
3916 		switch (state)
3917 		{
3918 		  case SMFIR_REPLYCODE:
3919 			if (MilterLogLevel > 3)
3920 			{
3921 				sm_syslog(LOG_INFO, e->e_id,
3922 					  "Milter: cmd=data, reject=%s",
3923 					  response);
3924 				LogUsrErrs = false;
3925 			}
3926 # if _FFR_MILTER_ENHSC
3927 			if (ISSMTPCODE(response))
3928 				(void) extenhsc(response + 4, ' ', e->e_enhsc);
3929 # endif
3930 
3931 			/* Can't use ("%s", ...) due to usrerr() requirements */
3932 			usrerr(response);
3933 			if (strncmp(response, "421 ", 4) == 0
3934 			    || strncmp(response, "421-", 4) == 0)
3935 			{
3936 				e->e_sendqueue = NULL;
3937 				return false;
3938 			}
3939 			return true;
3940 
3941 		  case SMFIR_REJECT:
3942 			if (MilterLogLevel > 3)
3943 			{
3944 				sm_syslog(LOG_INFO, e->e_id,
3945 					  "Milter: cmd=data, reject=550 5.7.1 Command rejected");
3946 				LogUsrErrs = false;
3947 			}
3948 # if _FFR_MILTER_ENHSC
3949 			(void) sm_strlcpy(e->e_enhsc, "5.7.1",
3950 					 sizeof(e->e_enhsc));
3951 # endif
3952 			usrerr("550 5.7.1 Command rejected");
3953 			return true;
3954 
3955 		  case SMFIR_DISCARD:
3956 			if (MilterLogLevel > 3)
3957 				sm_syslog(LOG_INFO, e->e_id,
3958 					  "Milter: cmd=data, discard");
3959 			e->e_flags |= EF_DISCARD;
3960 			break;
3961 
3962 		  case SMFIR_TEMPFAIL:
3963 			if (MilterLogLevel > 3)
3964 			{
3965 				sm_syslog(LOG_INFO, e->e_id,
3966 					  "Milter: cmd=data, reject=%s",
3967 					  MSG_TEMPFAIL);
3968 				LogUsrErrs = false;
3969 			}
3970 # if _FFR_MILTER_ENHSC
3971 			(void) extenhsc(MSG_TEMPFAIL + 4, ' ', e->e_enhsc);
3972 # endif
3973 			/* Can't use ("%s", ...) due to usrerr() requirements */
3974 			usrerr(MSG_TEMPFAIL);
3975 			return true;
3976 
3977 		  case SMFIR_SHUTDOWN:
3978 			if (MilterLogLevel > 3)
3979 			{
3980 				sm_syslog(LOG_INFO, e->e_id,
3981 					  "Milter: cmd=data, reject=421 4.7.0 %s closing connection",
3982 					  MyHostName);
3983 				LogUsrErrs = false;
3984 			}
3985 			usrerr("421 4.7.0 %s closing connection", MyHostName);
3986 			e->e_sendqueue = NULL;
3987 			return false;
3988 		}
3989 		LogUsrErrs = savelogusrerrs;
3990 		if (response != NULL)
3991 			sm_free(response); /* XXX */
3992 	}
3993 #endif /* MILTER && SMFI_VERSION > 3 */
3994 
3995 	/* put back discard bit */
3996 	if (smtp->sm_discard)
3997 		e->e_flags |= EF_DISCARD;
3998 
3999 	/* check to see if we need to re-expand aliases */
4000 	/* also reset QS_BADADDR on already-diagnosted addrs */
4001 	doublequeue = false;
4002 	for (a = e->e_sendqueue; a != NULL; a = a->q_next)
4003 	{
4004 		if (QS_IS_VERIFIED(a->q_state) &&
4005 		    !bitset(EF_DISCARD, e->e_flags))
4006 		{
4007 			/* need to re-expand aliases */
4008 			doublequeue = true;
4009 		}
4010 		if (QS_IS_BADADDR(a->q_state))
4011 		{
4012 			/* make this "go away" */
4013 			a->q_state = QS_DONTSEND;
4014 		}
4015 	}
4016 
4017 	/* collect the text of the message */
4018 	SmtpPhase = "collect";
4019 	buffer_errors();
4020 
4021 	collect(InChannel, true, NULL, e, true);
4022 
4023 	/* redefine message size */
4024 	(void) sm_snprintf(buf, sizeof(buf), "%ld", PRT_NONNEGL(e->e_msgsize));
4025 	macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), buf);
4026 
4027 	/* rscheck() will set Errors or EF_DISCARD if it trips */
4028 	(void) rscheck("check_eom", buf, NULL, e, RSF_UNSTRUCTURED|RSF_COUNT,
4029 		       3, NULL, e->e_id, NULL, NULL);
4030 
4031 #if MILTER
4032 	milteraccept = true;
4033 	if (smtp->sm_milterlist && smtp->sm_milterize &&
4034 	    Errors <= 0 &&
4035 	    !bitset(EF_DISCARD, e->e_flags))
4036 	{
4037 		char state;
4038 		char *response;
4039 
4040 		response = milter_data(e, &state);
4041 		switch (state)
4042 		{
4043 		  case SMFIR_REPLYCODE:
4044 			if (MilterLogLevel > 3)
4045 				sm_syslog(LOG_INFO, e->e_id,
4046 					  "Milter: data, reject=%s",
4047 					  response);
4048 			milteraccept = false;
4049 # if _FFR_MILTER_ENHSC
4050 			if (ISSMTPCODE(response))
4051 				(void) extenhsc(response + 4, ' ', e->e_enhsc);
4052 # endif
4053 			/* Can't use ("%s", ...) due to usrerr() requirements */
4054 			usrerr(response);
4055 			if (strncmp(response, "421 ", 4) == 0
4056 			    || strncmp(response, "421-", 4) == 0)
4057 				rv = false;
4058 			break;
4059 
4060 		  case SMFIR_REJECT:
4061 			milteraccept = false;
4062 			if (MilterLogLevel > 3)
4063 				sm_syslog(LOG_INFO, e->e_id,
4064 					  "Milter: data, reject=554 5.7.1 Command rejected");
4065 			usrerr("554 5.7.1 Command rejected");
4066 			break;
4067 
4068 		  case SMFIR_DISCARD:
4069 			if (MilterLogLevel > 3)
4070 				sm_syslog(LOG_INFO, e->e_id,
4071 					  "Milter: data, discard");
4072 			milteraccept = false;
4073 			e->e_flags |= EF_DISCARD;
4074 			break;
4075 
4076 		  case SMFIR_TEMPFAIL:
4077 			if (MilterLogLevel > 3)
4078 				sm_syslog(LOG_INFO, e->e_id,
4079 					  "Milter: data, reject=%s",
4080 					  MSG_TEMPFAIL);
4081 			milteraccept = false;
4082 # if _FFR_MILTER_ENHSC
4083 			(void) extenhsc(MSG_TEMPFAIL + 4, ' ', e->e_enhsc);
4084 # endif
4085 			/* Can't use ("%s", ...) due to usrerr() requirements */
4086 			usrerr(MSG_TEMPFAIL);
4087 			break;
4088 
4089 		  case SMFIR_SHUTDOWN:
4090 			if (MilterLogLevel > 3)
4091 				sm_syslog(LOG_INFO, e->e_id,
4092 					  "Milter: data, reject=421 4.7.0 %s closing connection",
4093 					  MyHostName);
4094 			milteraccept = false;
4095 			usrerr("421 4.7.0 %s closing connection", MyHostName);
4096 			rv = false;
4097 			break;
4098 		}
4099 		if (response != NULL)
4100 			sm_free(response);
4101 	}
4102 
4103 	/* Milter may have changed message size */
4104 	(void) sm_snprintf(buf, sizeof(buf), "%ld", PRT_NONNEGL(e->e_msgsize));
4105 	macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), buf);
4106 
4107 	/* abort message filters that didn't get the body & log msg is OK */
4108 	if (smtp->sm_milterlist && smtp->sm_milterize)
4109 	{
4110 		milter_abort(e);
4111 		if (milteraccept && MilterLogLevel > 9)
4112 			sm_syslog(LOG_INFO, e->e_id, "Milter accept: message");
4113 	}
4114 
4115 	/*
4116 	**  If SuperSafe is SAFE_REALLY_POSTMILTER, and we don't have milter or
4117 	**  milter accepted message, sync it now
4118 	**
4119 	**  XXX This is almost a copy of the code in collect(): put it into
4120 	**	a function that is called from both places?
4121 	*/
4122 
4123 	if (milteraccept && SuperSafe == SAFE_REALLY_POSTMILTER)
4124 	{
4125 		int afd;
4126 		SM_FILE_T *volatile df;
4127 		char *dfname;
4128 
4129 		df = e->e_dfp;
4130 		dfname = queuename(e, DATAFL_LETTER);
4131 		if (sm_io_setinfo(df, SM_BF_COMMIT, NULL) < 0
4132 		    && errno != EINVAL)
4133 		{
4134 			int save_errno;
4135 
4136 			save_errno = errno;
4137 			if (save_errno == EEXIST)
4138 			{
4139 				struct stat st;
4140 				int dfd;
4141 
4142 				if (stat(dfname, &st) < 0)
4143 					st.st_size = -1;
4144 				errno = EEXIST;
4145 				syserr("@collect: bfcommit(%s): already on disk, size=%ld",
4146 				       dfname, (long) st.st_size);
4147 				dfd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL);
4148 				if (dfd >= 0)
4149 					dumpfd(dfd, true, true);
4150 			}
4151 			errno = save_errno;
4152 			dferror(df, "bfcommit", e);
4153 			flush_errors(true);
4154 			finis(save_errno != EEXIST, true, ExitStat);
4155 		}
4156 		else if ((afd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL)) < 0)
4157 		{
4158 			dferror(df, "sm_io_getinfo", e);
4159 			flush_errors(true);
4160 			finis(true, true, ExitStat);
4161 			/* NOTREACHED */
4162 		}
4163 		else if (fsync(afd) < 0)
4164 		{
4165 			dferror(df, "fsync", e);
4166 			flush_errors(true);
4167 			finis(true, true, ExitStat);
4168 			/* NOTREACHED */
4169 		}
4170 		else if (sm_io_close(df, SM_TIME_DEFAULT) < 0)
4171 		{
4172 			dferror(df, "sm_io_close", e);
4173 			flush_errors(true);
4174 			finis(true, true, ExitStat);
4175 			/* NOTREACHED */
4176 		}
4177 
4178 		/* Now reopen the df file */
4179 		e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, dfname,
4180 					SM_IO_RDONLY, NULL);
4181 		if (e->e_dfp == NULL)
4182 		{
4183 			/* we haven't acked receipt yet, so just chuck this */
4184 			syserr("@Cannot reopen %s", dfname);
4185 			finis(true, true, ExitStat);
4186 			/* NOTREACHED */
4187 		}
4188 	}
4189 #endif /* MILTER */
4190 
4191 	/* Check if quarantining stats should be updated */
4192 	if (e->e_quarmsg != NULL)
4193 		markstats(e, NULL, STATS_QUARANTINE);
4194 
4195 	/*
4196 	**  If a header/body check (header checks or milter)
4197 	**  set EF_DISCARD, don't queueup the message --
4198 	**  that would lose the EF_DISCARD bit and deliver
4199 	**  the message.
4200 	*/
4201 
4202 	if (bitset(EF_DISCARD, e->e_flags))
4203 		doublequeue = false;
4204 
4205 	aborting = Errors > 0;
4206 	if (!(aborting || bitset(EF_DISCARD, e->e_flags)) &&
4207 	    (QueueMode == QM_QUARANTINE || e->e_quarmsg == NULL) &&
4208 	    !split_by_recipient(e))
4209 		aborting = bitset(EF_FATALERRS, e->e_flags);
4210 
4211 	if (aborting)
4212 	{
4213 		ADDRESS *q;
4214 
4215 		/* Log who the mail would have gone to */
4216 		logundelrcpts(e, e->e_message, 8, false);
4217 
4218 		/*
4219 		**  If something above refused the message, we still haven't
4220 		**  accepted responsibility for it.  Don't send DSNs.
4221 		*/
4222 
4223 		for (q = e->e_sendqueue; q != NULL; q = q->q_next)
4224 			q->q_flags &= ~Q_PINGFLAGS;
4225 
4226 		flush_errors(true);
4227 		buffer_errors();
4228 		goto abortmessage;
4229 	}
4230 
4231 	/* from now on, we have to operate silently */
4232 	buffer_errors();
4233 
4234 #if 0
4235 	/*
4236 	**  Clear message, it may contain an error from the SMTP dialogue.
4237 	**  This error must not show up in the queue.
4238 	**	Some error message should show up, e.g., alias database
4239 	**	not available, but others shouldn't, e.g., from check_rcpt.
4240 	*/
4241 
4242 	e->e_message = NULL;
4243 #endif /* 0 */
4244 
4245 	/*
4246 	**  Arrange to send to everyone.
4247 	**	If sending to multiple people, mail back
4248 	**		errors rather than reporting directly.
4249 	**	In any case, don't mail back errors for
4250 	**		anything that has happened up to
4251 	**		now (the other end will do this).
4252 	**	Truncate our transcript -- the mail has gotten
4253 	**		to us successfully, and if we have
4254 	**		to mail this back, it will be easier
4255 	**		on the reader.
4256 	**	Then send to everyone.
4257 	**	Finally give a reply code.  If an error has
4258 	**		already been given, don't mail a
4259 	**		message back.
4260 	**	We goose error returns by clearing error bit.
4261 	*/
4262 
4263 	SmtpPhase = "delivery";
4264 	(void) sm_io_setinfo(e->e_xfp, SM_BF_TRUNCATE, NULL);
4265 	id = e->e_id;
4266 
4267 #if NAMED_BIND
4268 	_res.retry = TimeOuts.res_retry[RES_TO_FIRST];
4269 	_res.retrans = TimeOuts.res_retrans[RES_TO_FIRST];
4270 #endif
4271 
4272 #if _FFR_PROXY
4273 	if (SM_PROXY_REQ == e->e_sendmode)
4274 	{
4275 		/* is proxy mode possible? */
4276 		if (e->e_sibling == NULL && e->e_nrcpts == 1
4277 		    && smtp->sm_nrcpts == 1
4278 		    && (a = e->e_sendqueue) != NULL && a->q_next == NULL)
4279 		{
4280 			a->q_flags &= ~(QPINGONFAILURE|QPINGONSUCCESS|
4281 					QPINGONDELAY);
4282 			e->e_errormode = EM_QUIET;
4283 			e->e_sendmode = SM_PROXY;
4284 		}
4285 		else
4286 		{
4287 			if (tTd(87, 2))
4288 			{
4289 				a = e->e_sendqueue;
4290 				sm_dprintf("srv: mode=%c, e=%p, sibling=%p, nrcpts=%d, sm_nrcpts=%d, sendqueue=%p, next=%p\n",
4291 				e->e_sendmode, e, e->e_sibling, e->e_nrcpts,
4292 				smtp->sm_nrcpts, a,
4293 				(a == NULL) ? (void *)0 : a->q_next);
4294 			}
4295 
4296 			/* switch to interactive mode */
4297 			e->e_sendmode = SM_DELIVER;
4298 			if (LogLevel > 9)
4299 				sm_syslog(LOG_DEBUG, e->e_id,
4300 					  "proxy mode requested but not possible");
4301 		}
4302 	}
4303 #endif /* _FFR_PROXY */
4304 
4305 #if _FFR_DMTRIGGER
4306 	if (SM_TRIGGER == e->e_sendmode)
4307 		doublequeue = true;
4308 #endif
4309 	for (ee = e; ee != NULL; ee = ee->e_sibling)
4310 	{
4311 		/* make sure we actually do delivery */
4312 		ee->e_flags &= ~EF_CLRQUEUE;
4313 
4314 		/* from now on, operate silently */
4315 		ee->e_errormode = EM_MAIL;
4316 
4317 		if (doublequeue)
4318 		{
4319 			unsigned int qup_flags;
4320 
4321 			qup_flags = QUP_FL_MSYNC;
4322 #if _FFR_DMTRIGGER
4323 			if (IS_SM_TRIGGER(ee->e_sendmode))
4324 				qup_flags |= QUP_FL_UNLOCK;
4325 #endif
4326 			/* make sure it is in the queue */
4327 			queueup(ee, qup_flags);
4328 		}
4329 		else
4330 		{
4331 			int mode;
4332 
4333 			/* send to all recipients */
4334 			mode = SM_DEFAULT;
4335 #if _FFR_DM_ONE
4336 			if (SM_DM_ONE == e->e_sendmode)
4337 			{
4338 				if (NotFirstDelivery)
4339 				{
4340 					mode = SM_QUEUE;
4341 					e->e_sendmode = SM_QUEUE;
4342 				}
4343 				else
4344 				{
4345 					mode = SM_FORK;
4346 					NotFirstDelivery = true;
4347 				}
4348 			}
4349 #endif /* _FFR_DM_ONE */
4350 			sendall(ee, mode);
4351 		}
4352 		ee->e_to = NULL;
4353 	}
4354 
4355 	/* put back id for SMTP logging in putoutmsg() */
4356 	oldid = CurEnv->e_id;
4357 	CurEnv->e_id = id;
4358 
4359 #if _FFR_PROXY
4360 	a = e->e_sendqueue;
4361 	if (tTd(87, 1))
4362 	{
4363 		sm_dprintf("srv: mode=%c, e=%p, sibling=%p, nrcpts=%d, msg=%s, sendqueue=%p, next=%p, state=%d, SmtpError=%s, rcode=%d, renhsc=%s, text=%s\n",
4364 		e->e_sendmode, e, e->e_sibling, e->e_nrcpts, e->e_message, a,
4365 		(a == NULL) ? (void *)0 : a->q_next,
4366 		(a == NULL) ? -1 : a->q_state, SmtpError, e->e_rcode,
4367 		e->e_renhsc, e->e_text);
4368 	}
4369 
4370 	if (SM_PROXY == e->e_sendmode && a->q_state != QS_SENT &&
4371 	    a->q_state != QS_VERIFIED) /* discarded! */
4372 	{
4373 		char *m, *errtext;
4374 		char replycode[4];
4375 		char enhsc[10];
4376 		int offset;
4377 
4378 #define NN_MSG(e)	(((e)->e_message != NULL) ? (e)->e_message : "")
4379 		m = e->e_message;
4380 #define SM_MSG_DEFERRED "Deferred: "
4381 		if (m != NULL && strncmp(SM_MSG_DEFERRED, m,
4382 					 sizeof(SM_MSG_DEFERRED) - 1) == 0)
4383 			m += sizeof(SM_MSG_DEFERRED) - 1;
4384 		offset = extsc(m, ' ', replycode, enhsc);
4385 
4386 		if (tTd(87, 2))
4387 		{
4388 			sm_dprintf("srv: SmtpError=%s, rcode=%d, renhsc=%s, replycode=%s, enhsc=%s, offset=%d\n",
4389 				SmtpError, e->e_rcode, e->e_renhsc,
4390 				replycode, enhsc, offset);
4391 		}
4392 
4393 #define DIG2CHAR(d)	((d) + '0')
4394 		if (e->e_rcode != 0 && (replycode[0] == '\0' ||
4395 		    replycode[0] == DIG2CHAR(REPLYTYPE(e->e_rcode))))
4396 		{
4397 			replycode[0] = DIG2CHAR(REPLYTYPE(e->e_rcode));
4398 			replycode[1] = DIG2CHAR(REPLYCLASS(e->e_rcode));
4399 			replycode[2] = DIG2CHAR(REPLYMINOR(e->e_rcode));
4400 			replycode[3] = '\0';
4401 			if (e->e_renhsc[0] == replycode[0])
4402 				sm_strlcpy(enhsc, e->e_renhsc, sizeof(enhsc));
4403 			if (offset < 0)
4404 				offset = 0;
4405 		}
4406 		if (e->e_text != NULL)
4407 		{
4408 			(void) strreplnonprt(e->e_text, '_');
4409 			errtext = e->e_text;
4410 		}
4411 		else
4412 			errtext = m + offset;
4413 
4414 		if (replycode[0] != '\0' && enhsc[0] != '\0')
4415 			emessage(replycode, enhsc, "%s", errtext);
4416 		else if (replycode[0] != '\0')
4417 			emessage(replycode, smtptodsn(atoi(replycode)),
4418 				 "%s", errtext);
4419 		else if (QS_IS_TEMPFAIL(a->q_state))
4420 		{
4421 			if (m != NULL)
4422 				message("450 4.5.1 %s", m);
4423 			else
4424 				message("450 4.5.1 Temporary error");
4425 		}
4426 		else
4427 		{
4428 			if (m != NULL)
4429 				message("550 5.5.1 %s", m);
4430 			else
4431 				message("550 5.0.0 Permanent error");
4432 		}
4433 	}
4434 	else
4435 	{
4436 #endif /* _FFR_PROXY */
4437 		/* issue success message */
4438 #if _FFR_MSG_ACCEPT
4439 		if (MessageAccept != NULL && *MessageAccept != '\0')
4440 		{
4441 			char msg[MAXLINE];
4442 
4443 			expand(MessageAccept, msg, sizeof(msg), e);
4444 			message("250 2.0.0 %s", msg);
4445 		}
4446 		else
4447 #endif /* _FFR_MSG_ACCEPT */
4448 		/* "else" in #if code above */
4449 		message("250 2.0.0 %s Message accepted for delivery", id);
4450 #if _FFR_PROXY
4451 	}
4452 #endif
4453 	CurEnv->e_id = oldid;
4454 
4455 	/* if we just queued, poke it */
4456 	if (doublequeue)
4457 	{
4458 		bool anything_to_send = false;
4459 
4460 		sm_getla();
4461 		for (ee = e; ee != NULL; ee = ee->e_sibling)
4462 		{
4463 #if _FFR_DMTRIGGER
4464 			if (SM_TRIGGER == ee->e_sendmode)
4465 			{
4466 				sm_syslog(LOG_DEBUG, ee->e_id,
4467 					"smtp: doublequeue, mode=%c", ee->e_sendmode);
4468 				ee->e_sendmode = SM_DELIVER;
4469 
4470 				/* close all the queue files */
4471 				/* almost the same as below */
4472 				closexscript(ee);
4473 				SM_CLOSE_FP(ee->e_dfp);
4474 				continue;
4475 			}
4476 #endif /* _FFR_DMTRIGGER */
4477 			if (WILL_BE_QUEUED(ee->e_sendmode))
4478 				continue;
4479 			if (shouldqueue(ee->e_msgpriority, ee->e_ctime))
4480 			{
4481 				ee->e_sendmode = SM_QUEUE;
4482 				continue;
4483 			}
4484 			else if (QueueMode != QM_QUARANTINE &&
4485 				 ee->e_quarmsg != NULL)
4486 			{
4487 				ee->e_sendmode = SM_QUEUE;
4488 				continue;
4489 			}
4490 			anything_to_send = true;
4491 
4492 			/* close all the queue files */
4493 			closexscript(ee);
4494 			SM_CLOSE_FP(ee->e_dfp);
4495 			unlockqueue(ee);
4496 		}
4497 		if (anything_to_send)
4498 		{
4499 #if PIPELINING
4500 			/*
4501 			**  XXX if we don't do this, we get 250 twice
4502 			**	because it is also flushed in the child.
4503 			*/
4504 
4505 			(void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
4506 #endif /* PIPELINING */
4507 #if _FFR_DMTRIGGER
4508 			sm_syslog(LOG_DEBUG, e->e_id, "smtp: doublequeue=send");
4509 #endif
4510 			(void) doworklist(e, true, true);
4511 		}
4512 	}
4513 
4514   abortmessage:
4515 	if (tTd(92, 2))
4516 		sm_dprintf("abortmessage: e_id=%s, EF_LOGSENDER=%d, LogLevel=%d\n",
4517 			e->e_id, bitset(EF_LOGSENDER, e->e_flags), LogLevel);
4518 	if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
4519 		logsender(e, NULL);
4520 	e->e_flags &= ~EF_LOGSENDER;
4521 
4522 	/* clean up a bit */
4523 	smtp->sm_gotmail = false;
4524 
4525 	/*
4526 	**  Call dropenvelope if and only if the envelope is *not*
4527 	**  being processed by the child process forked by doworklist().
4528 	*/
4529 
4530 	if (aborting || bitset(EF_DISCARD, e->e_flags))
4531 		(void) dropenvelope(e, true, false);
4532 	else
4533 	{
4534 		for (ee = e; ee != NULL; ee = ee->e_sibling)
4535 		{
4536 			if (!doublequeue &&
4537 			    QueueMode != QM_QUARANTINE &&
4538 			    ee->e_quarmsg != NULL)
4539 			{
4540 				(void) dropenvelope(ee, true, false);
4541 				continue;
4542 			}
4543 			if (WILL_BE_QUEUED(ee->e_sendmode))
4544 				(void) dropenvelope(ee, true, false);
4545 		}
4546 	}
4547 
4548 	CurEnv = e;
4549 	features = e->e_features;
4550 	sm_rpool_free(e->e_rpool);
4551 	newenvelope(e, e, sm_rpool_new_x(NULL));
4552 	e->e_flags = BlankEnvelope.e_flags;
4553 	e->e_features = features;
4554 
4555 	/* restore connection quarantining */
4556 	if (smtp->sm_quarmsg == NULL)
4557 	{
4558 		e->e_quarmsg = NULL;
4559 		macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), "");
4560 	}
4561 	else
4562 	{
4563 		e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool, smtp->sm_quarmsg);
4564 		macdefine(&e->e_macro, A_PERM,
4565 			  macid("{quarantine}"), e->e_quarmsg);
4566 	}
4567 	return rv;
4568 }
4569 /*
4570 **  LOGUNDELRCPTS -- log undelivered (or all) recipients.
4571 **
4572 **	Parameters:
4573 **		e -- envelope.
4574 **		msg -- message for Stat=
4575 **		level -- log level.
4576 **		all -- log all recipients.
4577 **
4578 **	Returns:
4579 **		none.
4580 **
4581 **	Side Effects:
4582 **		logs undelivered (or all) recipients
4583 */
4584 
4585 void
4586 logundelrcpts(e, msg, level, all)
4587 	ENVELOPE *e;
4588 	char *msg;
4589 	int level;
4590 	bool all;
4591 {
4592 	ADDRESS *a;
4593 
4594 	if (LogLevel <= level || msg == NULL || *msg == '\0')
4595 		return;
4596 
4597 	/* Clear $h so relay= doesn't get mislogged by logdelivery() */
4598 	macdefine(&e->e_macro, A_PERM, 'h', NULL);
4599 
4600 	/* Log who the mail would have gone to */
4601 	for (a = e->e_sendqueue; a != NULL; a = a->q_next)
4602 	{
4603 		if (!QS_IS_UNDELIVERED(a->q_state) && !all)
4604 			continue;
4605 		e->e_to = a->q_paddr;
4606 		logdelivery(NULL, NULL,
4607 #if _FFR_MILTER_ENHSC
4608 			    (a->q_status == NULL && e->e_enhsc[0] != '\0')
4609 			    ? e->e_enhsc :
4610 #endif
4611 /* not yet documented or tested */
4612 #if _FFR_USE_E_STATUS
4613 			    (NULL == a->q_status) ? e->e_status :
4614 #endif
4615 			    a->q_status,
4616 			    msg, NULL, (time_t) 0, e, a, EX_OK /* ??? */);
4617 	}
4618 	e->e_to = NULL;
4619 }
4620 /*
4621 **  CHECKSMTPATTACK -- check for denial-of-service attack by repetition
4622 **
4623 **	Parameters:
4624 **		pcounter -- pointer to a counter for this command.
4625 **		maxcount -- maximum value for this counter before we
4626 **			slow down.
4627 **		waitnow -- sleep now (in this routine)?
4628 **		cname -- command name for logging.
4629 **		e -- the current envelope.
4630 **
4631 **	Returns:
4632 **		time to wait,
4633 **		STOP_ATTACK if twice as many commands as allowed and
4634 **			MaxChildren > 0.
4635 **
4636 **	Side Effects:
4637 **		Slows down if we seem to be under attack.
4638 */
4639 
4640 static time_t
4641 checksmtpattack(pcounter, maxcount, waitnow, cname, e)
4642 	volatile unsigned int *pcounter;
4643 	unsigned int maxcount;
4644 	bool waitnow;
4645 	char *cname;
4646 	ENVELOPE *e;
4647 {
4648 	if (maxcount <= 0)	/* no limit */
4649 		return (time_t) 0;
4650 
4651 	if (++(*pcounter) >= maxcount)
4652 	{
4653 		unsigned int shift;
4654 		time_t s;
4655 
4656 		if (*pcounter == maxcount && LogLevel > 5)
4657 		{
4658 			sm_syslog(LOG_INFO, e->e_id,
4659 				  "%s: possible SMTP attack: command=%.40s, count=%u",
4660 				  CurSmtpClient, cname, *pcounter);
4661 		}
4662 		shift = *pcounter - maxcount;
4663 		s = 1 << shift;
4664 		if (shift > MAXSHIFT || s >= MAXTIMEOUT || s <= 0)
4665 			s = MAXTIMEOUT;
4666 
4667 #define IS_ATTACK(s)	((MaxChildren > 0 && *pcounter >= maxcount * 2)	\
4668 				? STOP_ATTACK : (time_t) s)
4669 
4670 		/* sleep at least 1 second before returning */
4671 		(void) sleep(*pcounter / maxcount);
4672 		s -= *pcounter / maxcount;
4673 		if (s >= MAXTIMEOUT || s < 0)
4674 			s = MAXTIMEOUT;
4675 		if (waitnow && s > 0)
4676 		{
4677 			(void) sleep(s);
4678 			return IS_ATTACK(0);
4679 		}
4680 		return IS_ATTACK(s);
4681 	}
4682 	return (time_t) 0;
4683 }
4684 /*
4685 **  SETUP_SMTPD_IO -- setup I/O fd correctly for the SMTP server
4686 **
4687 **	Parameters:
4688 **		none.
4689 **
4690 **	Returns:
4691 **		nothing.
4692 **
4693 **	Side Effects:
4694 **		may change I/O fd.
4695 */
4696 
4697 static void
4698 setup_smtpd_io()
4699 {
4700 	int inchfd, outchfd, outfd;
4701 
4702 	inchfd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL);
4703 	outchfd  = sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL);
4704 	outfd = sm_io_getinfo(smioout, SM_IO_WHAT_FD, NULL);
4705 	if (outchfd != outfd)
4706 	{
4707 		/* arrange for debugging output to go to remote host */
4708 		(void) dup2(outchfd, outfd);
4709 	}
4710 
4711 	/*
4712 	**  if InChannel and OutChannel are stdin/stdout
4713 	**  and connected to ttys
4714 	**  and fcntl(STDIN, F_SETFL, O_NONBLOCKING) also changes STDOUT,
4715 	**  then "chain" them together.
4716 	*/
4717 
4718 	if (inchfd == STDIN_FILENO && outchfd == STDOUT_FILENO &&
4719 	    isatty(inchfd) && isatty(outchfd))
4720 	{
4721 		int inmode, outmode;
4722 
4723 		inmode = fcntl(inchfd, F_GETFL, 0);
4724 		if (inmode == -1)
4725 		{
4726 			if (LogLevel > 11)
4727 				sm_syslog(LOG_INFO, NOQID,
4728 					"fcntl(inchfd, F_GETFL) failed: %s",
4729 					sm_errstring(errno));
4730 			return;
4731 		}
4732 		outmode = fcntl(outchfd, F_GETFL, 0);
4733 		if (outmode == -1)
4734 		{
4735 			if (LogLevel > 11)
4736 				sm_syslog(LOG_INFO, NOQID,
4737 					"fcntl(outchfd, F_GETFL) failed: %s",
4738 					sm_errstring(errno));
4739 			return;
4740 		}
4741 		if (bitset(O_NONBLOCK, inmode) ||
4742 		    bitset(O_NONBLOCK, outmode) ||
4743 		    fcntl(inchfd, F_SETFL, inmode | O_NONBLOCK) == -1)
4744 			return;
4745 		outmode = fcntl(outchfd, F_GETFL, 0);
4746 		if (outmode != -1 && bitset(O_NONBLOCK, outmode))
4747 		{
4748 			/* changing InChannel also changes OutChannel */
4749 			sm_io_automode(OutChannel, InChannel);
4750 			if (tTd(97, 4) && LogLevel > 9)
4751 				sm_syslog(LOG_INFO, NOQID,
4752 					  "set automode for I (%d)/O (%d) in SMTP server",
4753 					  inchfd, outchfd);
4754 		}
4755 
4756 		/* undo change of inchfd */
4757 		(void) fcntl(inchfd, F_SETFL, inmode);
4758 	}
4759 }
4760 /*
4761 **  SKIPWORD -- skip a fixed word.
4762 **
4763 **	Parameters:
4764 **		p -- place to start looking.
4765 **		w -- word to skip.
4766 **
4767 **	Returns:
4768 **		p following w.
4769 **		NULL on error.
4770 **
4771 **	Side Effects:
4772 **		clobbers the p data area.
4773 */
4774 
4775 static char *
4776 skipword(p, w)
4777 	register char *volatile p;
4778 	char *w;
4779 {
4780 	register char *q;
4781 	char *firstp = p;
4782 
4783 	/* find beginning of word */
4784 	SKIP_SPACE(p);
4785 	q = p;
4786 
4787 	/* find end of word */
4788 	while (*p != '\0' && *p != ':' && !(SM_ISSPACE(*p)))
4789 		p++;
4790 	while (SM_ISSPACE(*p))
4791 		*p++ = '\0';
4792 	if (*p != ':')
4793 	{
4794 	  syntax:
4795 		usrerr("501 5.5.2 Syntax error in parameters scanning \"%s\"",
4796 			SHOWSHRTCMDINREPLY(firstp));
4797 		return NULL;
4798 	}
4799 	*p++ = '\0';
4800 	SKIP_SPACE(p);
4801 
4802 	if (*p == '\0')
4803 		goto syntax;
4804 
4805 	/* see if the input word matches desired word */
4806 	if (sm_strcasecmp(q, w))
4807 		goto syntax;
4808 
4809 	return p;
4810 }
4811 
4812 /*
4813 **  RESET_MAIL_ESMTP_ARGS -- process ESMTP arguments from MAIL line
4814 **
4815 **	Parameters:
4816 **		e -- the envelope.
4817 **
4818 **	Returns:
4819 **		none.
4820 */
4821 
4822 void
4823 reset_mail_esmtp_args(e)
4824 	ENVELOPE *e;
4825 {
4826 	/* "size": no reset */
4827 
4828 	/* "body" */
4829 	SevenBitInput = SevenBitInput_Saved;
4830 	e->e_bodytype = NULL;
4831 
4832 	/* "envid" */
4833 	e->e_envid = NULL;
4834 	macdefine(&e->e_macro, A_PERM, macid("{dsn_envid}"), NULL);
4835 
4836 	/* "ret" */
4837 	e->e_flags &= ~(EF_RET_PARAM|EF_NO_BODY_RETN);
4838 	macdefine(&e->e_macro, A_TEMP, macid("{dsn_ret}"), NULL);
4839 
4840 #if SASL
4841 	/* "auth" */
4842 	macdefine(&e->e_macro, A_TEMP, macid("{auth_author}"), NULL);
4843 	e->e_auth_param = "";
4844 # if _FFR_AUTH_PASSING
4845 	macdefine(&BlankEnvelope.e_macro, A_PERM,
4846 				  macid("{auth_author}"), NULL);
4847 # endif
4848 #endif /* SASL */
4849 
4850 	/* "by" */
4851 	e->e_deliver_by = 0;
4852 	e->e_dlvr_flag = 0;
4853 }
4854 
4855 /*
4856 **  MAIL_ESMTP_ARGS -- process ESMTP arguments from MAIL line
4857 **
4858 **	Parameters:
4859 **		a -- address (unused, for compatibility with rcpt_esmtp_args)
4860 **		kp -- the parameter key.
4861 **		vp -- the value of that parameter.
4862 **		e -- the envelope.
4863 **
4864 **	Returns:
4865 **		none.
4866 */
4867 
4868 void
4869 mail_esmtp_args(a, kp, vp, e)
4870 	ADDRESS *a;
4871 	char *kp;
4872 	char *vp;
4873 	ENVELOPE *e;
4874 {
4875 	if (SM_STRCASEEQ(kp, "size"))
4876 	{
4877 		if (vp == NULL)
4878 		{
4879 			usrerr("501 5.5.2 SIZE requires a value");
4880 			/* NOTREACHED */
4881 		}
4882 		macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), vp);
4883 		errno = 0;
4884 		e->e_msgsize = strtol(vp, (char **) NULL, 10);
4885 		if (e->e_msgsize == LONG_MAX && errno == ERANGE)
4886 		{
4887 			usrerr("552 5.2.3 Message size exceeds maximum value");
4888 			/* NOTREACHED */
4889 		}
4890 		if (e->e_msgsize < 0)
4891 		{
4892 			usrerr("552 5.2.3 Message size invalid");
4893 			/* NOTREACHED */
4894 		}
4895 	}
4896 	else if (SM_STRCASEEQ(kp, "body"))
4897 	{
4898 		if (vp == NULL)
4899 		{
4900 			usrerr("501 5.5.2 BODY requires a value");
4901 			/* NOTREACHED */
4902 		}
4903 		else if (SM_STRCASEEQ(vp, "8bitmime"))
4904 		{
4905 			SevenBitInput = false;
4906 		}
4907 		else if (SM_STRCASEEQ(vp, "7bit"))
4908 		{
4909 			SevenBitInput = true;
4910 		}
4911 		else
4912 		{
4913 			usrerr("501 5.5.4 Unknown BODY type %s",
4914 				SHOWCMDINREPLY(vp));
4915 			/* NOTREACHED */
4916 		}
4917 		e->e_bodytype = sm_rpool_strdup_x(e->e_rpool, vp);
4918 	}
4919 	else if (SM_STRCASEEQ(kp, "envid"))
4920 	{
4921 		if (!bitset(SRV_OFFER_DSN, e->e_features))
4922 		{
4923 			usrerr("504 5.7.0 Sorry, ENVID not supported, we do not allow DSN");
4924 			/* NOTREACHED */
4925 		}
4926 		if (vp == NULL)
4927 		{
4928 			usrerr("501 5.5.2 ENVID requires a value");
4929 			/* NOTREACHED */
4930 		}
4931 		if (!xtextok(vp))
4932 		{
4933 			usrerr("501 5.5.4 Syntax error in ENVID parameter value");
4934 			/* NOTREACHED */
4935 		}
4936 		if (e->e_envid != NULL)
4937 		{
4938 			usrerr("501 5.5.0 Duplicate ENVID parameter");
4939 			/* NOTREACHED */
4940 		}
4941 		e->e_envid = sm_rpool_strdup_x(e->e_rpool, vp);
4942 		macdefine(&e->e_macro, A_PERM,
4943 			macid("{dsn_envid}"), e->e_envid);
4944 	}
4945 	else if (SM_STRCASEEQ(kp, "ret"))
4946 	{
4947 		if (!bitset(SRV_OFFER_DSN, e->e_features))
4948 		{
4949 			usrerr("504 5.7.0 Sorry, RET not supported, we do not allow DSN");
4950 			/* NOTREACHED */
4951 		}
4952 		if (vp == NULL)
4953 		{
4954 			usrerr("501 5.5.2 RET requires a value");
4955 			/* NOTREACHED */
4956 		}
4957 		if (bitset(EF_RET_PARAM, e->e_flags))
4958 		{
4959 			usrerr("501 5.5.0 Duplicate RET parameter");
4960 			/* NOTREACHED */
4961 		}
4962 		e->e_flags |= EF_RET_PARAM;
4963 		if (SM_STRCASEEQ(vp, "hdrs"))
4964 			e->e_flags |= EF_NO_BODY_RETN;
4965 		else if (sm_strcasecmp(vp, "full") != 0)
4966 		{
4967 			usrerr("501 5.5.2 Bad argument \"%s\" to RET",
4968 				SHOWCMDINREPLY(vp));
4969 			/* NOTREACHED */
4970 		}
4971 		macdefine(&e->e_macro, A_TEMP, macid("{dsn_ret}"), vp);
4972 	}
4973 #if SASL
4974 	else if (SM_STRCASEEQ(kp, "auth"))
4975 	{
4976 		int len;
4977 		char *q;
4978 		char *auth_param;	/* the value of the AUTH=x */
4979 		bool saveQuickAbort = QuickAbort;
4980 		bool saveSuprErrs = SuprErrs;
4981 		bool saveExitStat = ExitStat;
4982 
4983 		if (vp == NULL)
4984 		{
4985 			usrerr("501 5.5.2 AUTH= requires a value");
4986 			/* NOTREACHED */
4987 		}
4988 		if (e->e_auth_param != NULL)
4989 		{
4990 			usrerr("501 5.5.0 Duplicate AUTH parameter");
4991 			/* NOTREACHED */
4992 		}
4993 		if ((q = strchr(vp, ' ')) != NULL)
4994 			len = q - vp + 1;
4995 		else
4996 			len = strlen(vp) + 1;
4997 		auth_param = xalloc(len);
4998 		(void) sm_strlcpy(auth_param, vp, len);
4999 		if (!xtextok(auth_param))
5000 		{
5001 			usrerr("501 5.5.4 Syntax error in AUTH parameter value");
5002 			/* just a warning? */
5003 			/* NOTREACHED */
5004 		}
5005 
5006 		/* XXX define this always or only if trusted? */
5007 		macdefine(&e->e_macro, A_TEMP, macid("{auth_author}"),
5008 			  auth_param);
5009 
5010 		/*
5011 		**  call Strust_auth to find out whether
5012 		**  auth_param is acceptable (trusted)
5013 		**  we shouldn't trust it if not authenticated
5014 		**  (required by RFC, leave it to ruleset?)
5015 		*/
5016 
5017 		SuprErrs = true;
5018 		QuickAbort = false;
5019 		if (strcmp(auth_param, "<>") != 0 &&
5020 		     (rscheck("trust_auth", auth_param, NULL, e, RSF_RMCOMM, 9,
5021 			      NULL, NOQID, NULL, NULL) != EX_OK || Errors > 0))
5022 		{
5023 			if (tTd(95, 8))
5024 			{
5025 				q = e->e_auth_param;
5026 				sm_dprintf("auth=\"%.100s\" not trusted user=\"%.100s\"\n",
5027 					auth_param, (q == NULL) ? "" : q);
5028 			}
5029 
5030 			/* not trusted */
5031 			e->e_auth_param = "<>";
5032 # if _FFR_AUTH_PASSING
5033 			macdefine(&BlankEnvelope.e_macro, A_PERM,
5034 				  macid("{auth_author}"), NULL);
5035 # endif
5036 		}
5037 		else
5038 		{
5039 			if (tTd(95, 8))
5040 				sm_dprintf("auth=\"%.100s\" trusted\n", auth_param);
5041 			e->e_auth_param = sm_rpool_strdup_x(e->e_rpool,
5042 							    auth_param);
5043 		}
5044 		sm_free(auth_param); /* XXX */
5045 
5046 		/* reset values */
5047 		Errors = 0;
5048 		QuickAbort = saveQuickAbort;
5049 		SuprErrs = saveSuprErrs;
5050 		ExitStat = saveExitStat;
5051 	}
5052 #endif /* SASL */
5053 #define PRTCHAR(c)	((isascii(c) && isprint(c)) ? (c) : '?')
5054 
5055 	/*
5056 	**  "by" is only accepted if DeliverByMin >= 0.
5057 	**  We maybe could add this to the list of server_features.
5058 	*/
5059 
5060 	else if (SM_STRCASEEQ(kp, "by") && DeliverByMin >= 0)
5061 	{
5062 		char *s;
5063 
5064 		if (vp == NULL)
5065 		{
5066 			usrerr("501 5.5.2 BY= requires a value");
5067 			/* NOTREACHED */
5068 		}
5069 		errno = 0;
5070 		e->e_deliver_by = strtol(vp, &s, 10);
5071 		if (e->e_deliver_by == LONG_MIN ||
5072 		    e->e_deliver_by == LONG_MAX ||
5073 		    e->e_deliver_by > 999999999l ||
5074 		    e->e_deliver_by < -999999999l)
5075 		{
5076 			usrerr("501 5.5.2 BY=%s out of range",
5077 				SHOWCMDINREPLY(vp));
5078 			/* NOTREACHED */
5079 		}
5080 		if (s == NULL || *s != ';')
5081 		{
5082 			usrerr("501 5.5.2 BY= missing ';'");
5083 			/* NOTREACHED */
5084 		}
5085 		e->e_dlvr_flag = 0;
5086 		++s;	/* XXX: spaces allowed? */
5087 		SKIP_SPACE(s);
5088 		switch (tolower(*s))
5089 		{
5090 		  case 'n':
5091 			e->e_dlvr_flag = DLVR_NOTIFY;
5092 			break;
5093 		  case 'r':
5094 			e->e_dlvr_flag = DLVR_RETURN;
5095 			if (e->e_deliver_by <= 0)
5096 			{
5097 				usrerr("501 5.5.4 mode R requires BY time > 0");
5098 				/* NOTREACHED */
5099 			}
5100 			if (DeliverByMin > 0 && e->e_deliver_by > 0 &&
5101 			    e->e_deliver_by < DeliverByMin)
5102 			{
5103 				usrerr("555 5.5.2 time %ld less than %ld",
5104 					e->e_deliver_by, (long) DeliverByMin);
5105 				/* NOTREACHED */
5106 			}
5107 			break;
5108 		  default:
5109 			usrerr("501 5.5.2 illegal by-mode '%c'", PRTCHAR(*s));
5110 			/* NOTREACHED */
5111 		}
5112 		++s;	/* XXX: spaces allowed? */
5113 		SKIP_SPACE(s);
5114 		switch (tolower(*s))
5115 		{
5116 		  case 't':
5117 			e->e_dlvr_flag |= DLVR_TRACE;
5118 			break;
5119 		  case '\0':
5120 			break;
5121 		  default:
5122 			usrerr("501 5.5.2 illegal by-trace '%c'", PRTCHAR(*s));
5123 			/* NOTREACHED */
5124 		}
5125 
5126 		/* XXX: check whether more characters follow? */
5127 	}
5128 #if USE_EAI
5129 	else if (SM_STRCASEEQ(kp, "smtputf8"))
5130 	{
5131 		if (!bitset(SRV_OFFER_EAI, e->e_features))
5132 		{
5133 			usrerr("504 5.7.0 Sorry, SMTPUTF8 not supported");
5134 			/* NOTREACHED */
5135 		}
5136 		e->e_smtputf8 = true;
5137 	}
5138 #endif
5139 	else
5140 	{
5141 		usrerr("555 5.5.4 %s parameter unrecognized",
5142 			SHOWCMDINREPLY(kp));
5143 		/* NOTREACHED */
5144 	}
5145 }
5146 
5147 /*
5148 **  RCPT_ESMTP_ARGS -- process ESMTP arguments from RCPT line
5149 **
5150 **	Parameters:
5151 **		a -- the address corresponding to the To: parameter.
5152 **		kp -- the parameter key.
5153 **		vp -- the value of that parameter.
5154 **		e -- the envelope.
5155 **
5156 **	Returns:
5157 **		none.
5158 */
5159 
5160 void
5161 rcpt_esmtp_args(a, kp, vp, e)
5162 	ADDRESS *a;
5163 	char *kp;
5164 	char *vp;
5165 	ENVELOPE *e;
5166 {
5167 	if (SM_STRCASEEQ(kp, "notify"))
5168 	{
5169 		char *p;
5170 
5171 		if (!bitset(SRV_OFFER_DSN, e->e_features))
5172 		{
5173 			usrerr("504 5.7.0 Sorry, NOTIFY not supported, we do not allow DSN");
5174 			/* NOTREACHED */
5175 		}
5176 		if (vp == NULL)
5177 		{
5178 			usrerr("501 5.5.2 NOTIFY requires a value");
5179 			/* NOTREACHED */
5180 		}
5181 		a->q_flags &= ~(QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY);
5182 		a->q_flags |= QHASNOTIFY;
5183 		macdefine(&e->e_macro, A_TEMP, macid("{dsn_notify}"), vp);
5184 
5185 		if (SM_STRCASEEQ(vp, "never"))
5186 			return;
5187 		for (p = vp; p != NULL; vp = p)
5188 		{
5189 			char *s;
5190 
5191 			s = p = strchr(p, ',');
5192 			if (p != NULL)
5193 				*p++ = '\0';
5194 			if (SM_STRCASEEQ(vp, "success"))
5195 				a->q_flags |= QPINGONSUCCESS;
5196 			else if (SM_STRCASEEQ(vp, "failure"))
5197 				a->q_flags |= QPINGONFAILURE;
5198 			else if (SM_STRCASEEQ(vp, "delay"))
5199 				a->q_flags |= QPINGONDELAY;
5200 			else
5201 			{
5202 				usrerr("501 5.5.4 Bad argument \"%s\"  to NOTIFY",
5203 					SHOWCMDINREPLY(vp));
5204 				/* NOTREACHED */
5205 			}
5206 			if (s != NULL)
5207 				*s = ',';
5208 		}
5209 	}
5210 	else if (SM_STRCASEEQ(kp, "orcpt"))
5211 	{
5212 		char *p;
5213 
5214 		if (!bitset(SRV_OFFER_DSN, e->e_features))
5215 		{
5216 			usrerr("504 5.7.0 Sorry, ORCPT not supported, we do not allow DSN");
5217 			/* NOTREACHED */
5218 		}
5219 		if (vp == NULL)
5220 		{
5221 			usrerr("501 5.5.2 ORCPT requires a value");
5222 			/* NOTREACHED */
5223 		}
5224 		if (a->q_orcpt != NULL)
5225 		{
5226 			usrerr("501 5.5.0 Duplicate ORCPT parameter");
5227 			/* NOTREACHED */
5228 		}
5229 		p = strchr(vp, ';');
5230 		if (p == NULL)
5231 		{
5232 			usrerr("501 5.5.4 Syntax error in ORCPT parameter value");
5233 			/* NOTREACHED */
5234 		}
5235 		*p = '\0';
5236 #if USE_EAI
5237 		if (SM_STRCASEEQ(vp, "utf-8"))
5238 		{
5239 			/* XXX check syntax of p+1 ! */
5240 			if (!xtextok(p + 1) &&
5241 			    uxtext_unquote(p + 1, NULL, MAXNAME_I) <= 0)
5242 			{
5243 				*p = ';';
5244 				usrerr("501 5.5.4 Syntax error in UTF-8 ORCPT parameter value");
5245 				/* NOTREACHED */
5246 			}
5247 # if 0
5248 complicated... see grammar!
5249 RFC 6533 Internationalized Delivery Status and Disposition Notifications
5250 utf-8-enc-addr = utf-8-addr-xtext / utf-8-addr-unitext / utf-8-address
5251 # endif
5252 		}
5253 		else
5254 #endif /* USE_EAI */
5255 		/* "else" in #if code above */
5256 		if (!isatom(vp) || !xtextok(p + 1))
5257 		{
5258 			*p = ';';
5259 			usrerr("501 5.5.4 Syntax error in ORCPT parameter value");
5260 			/* NOTREACHED */
5261 		}
5262 		*p = ';';
5263 		a->q_orcpt = sm_rpool_strdup_x(e->e_rpool, vp);
5264 	}
5265 	else
5266 	{
5267 		usrerr("555 5.5.4 %s parameter unrecognized",
5268 			SHOWCMDINREPLY(kp));
5269 		/* NOTREACHED */
5270 	}
5271 }
5272 /*
5273 **  PRINTVRFYADDR -- print an entry in the verify queue
5274 **
5275 **	Parameters:
5276 **		a -- the address to print.
5277 **		last -- set if this is the last one.
5278 **		vrfy -- set if this is a VRFY command.
5279 **
5280 **	Returns:
5281 **		none.
5282 **
5283 **	Side Effects:
5284 **		Prints the appropriate 250 codes.
5285 */
5286 #define OFFF	(3 + 1 + 5 + 1)	/* offset in fmt: SMTP reply + enh. code */
5287 
5288 static void
5289 printvrfyaddr(a, last, vrfy)
5290 	register ADDRESS *a;
5291 	bool last;
5292 	bool vrfy;
5293 {
5294 	char fmtbuf[30];
5295 
5296 	if (vrfy && a->q_mailer != NULL &&
5297 	    !bitnset(M_VRFY250, a->q_mailer->m_flags))
5298 		(void) sm_strlcpy(fmtbuf, "252", sizeof(fmtbuf));
5299 	else
5300 		(void) sm_strlcpy(fmtbuf, "250", sizeof(fmtbuf));
5301 	fmtbuf[3] = last ? ' ' : '-';
5302 	(void) sm_strlcpy(&fmtbuf[4], "2.1.5 ", sizeof(fmtbuf) - 4);
5303 	if (a->q_fullname == NULL)
5304 	{
5305 		if ((a->q_mailer == NULL ||
5306 		     a->q_mailer->m_addrtype == NULL ||
5307 		     SM_STRCASEEQ(a->q_mailer->m_addrtype, "rfc822")) &&
5308 		    strchr(a->q_user, '@') == NULL)
5309 			(void) sm_strlcpy(&fmtbuf[OFFF], "<%s@%s>",
5310 				       sizeof(fmtbuf) - OFFF);
5311 		else
5312 			(void) sm_strlcpy(&fmtbuf[OFFF], "<%s>",
5313 				       sizeof(fmtbuf) - OFFF);
5314 		message(fmtbuf, a->q_user, MyHostName);
5315 	}
5316 	else
5317 	{
5318 		if ((a->q_mailer == NULL ||
5319 		     a->q_mailer->m_addrtype == NULL ||
5320 		     SM_STRCASEEQ(a->q_mailer->m_addrtype, "rfc822")) &&
5321 		    strchr(a->q_user, '@') == NULL)
5322 			(void) sm_strlcpy(&fmtbuf[OFFF], "%s <%s@%s>",
5323 				       sizeof(fmtbuf) - OFFF);
5324 		else
5325 			(void) sm_strlcpy(&fmtbuf[OFFF], "%s <%s>",
5326 				       sizeof(fmtbuf) - OFFF);
5327 		message(fmtbuf, a->q_fullname, a->q_user, MyHostName);
5328 	}
5329 }
5330 
5331 #if SASL
5332 /*
5333 **  SASLMECHS -- get list of possible AUTH mechanisms
5334 **
5335 **	Parameters:
5336 **		conn -- SASL connection info.
5337 **		mechlist -- output parameter for list of mechanisms.
5338 **
5339 **	Returns:
5340 **		number of mechs.
5341 */
5342 
5343 static int
5344 saslmechs(conn, mechlist)
5345 	sasl_conn_t *conn;
5346 	char **mechlist;
5347 {
5348 	int len, num, result;
5349 
5350 	/* "user" is currently unused */
5351 # if SASL >= 20000
5352 	result = sasl_listmech(conn, NULL,
5353 			       "", " ", "", (const char **) mechlist,
5354 			       (unsigned int *)&len, &num);
5355 # else /* SASL >= 20000 */
5356 	result = sasl_listmech(conn, "user", /* XXX */
5357 			       "", " ", "", mechlist,
5358 			       (unsigned int *)&len, (unsigned int *)&num);
5359 # endif /* SASL >= 20000 */
5360 	if (result != SASL_OK)
5361 	{
5362 		if (LogLevel > 9)
5363 			sm_syslog(LOG_WARNING, NOQID,
5364 				  "AUTH error: listmech=%d, num=%d",
5365 				  result, num);
5366 		num = 0;
5367 	}
5368 	if (num > 0)
5369 	{
5370 		if (LogLevel > 11)
5371 			sm_syslog(LOG_INFO, NOQID,
5372 				  "AUTH: available mech=%s, allowed mech=%s",
5373 				  *mechlist, AuthMechanisms);
5374 		*mechlist = intersect(AuthMechanisms, *mechlist, NULL);
5375 	}
5376 	else
5377 	{
5378 		*mechlist = NULL;	/* be paranoid... */
5379 		if (result == SASL_OK && LogLevel > 9)
5380 			sm_syslog(LOG_WARNING, NOQID,
5381 				  "AUTH warning: no mechanisms");
5382 	}
5383 	return num;
5384 }
5385 
5386 # if SASL >= 20000
5387 /*
5388 **  PROXY_POLICY -- define proxy policy for AUTH
5389 **
5390 **	Parameters:
5391 **		conn -- unused.
5392 **		context -- unused.
5393 **		requested_user -- authorization identity.
5394 **		rlen -- authorization identity length.
5395 **		auth_identity -- authentication identity.
5396 **		alen -- authentication identity length.
5397 **		def_realm -- default user realm.
5398 **		urlen -- user realm length.
5399 **		propctx -- unused.
5400 **
5401 **	Returns:
5402 **		ok?
5403 **
5404 **	Side Effects:
5405 **		sets {auth_authen} macro.
5406 */
5407 
5408 int
5409 proxy_policy(conn, context, requested_user, rlen, auth_identity, alen,
5410 	     def_realm, urlen, propctx)
5411 	sasl_conn_t *conn;
5412 	void *context;
5413 	const char *requested_user;
5414 	unsigned rlen;
5415 	const char *auth_identity;
5416 	unsigned alen;
5417 	const char *def_realm;
5418 	unsigned urlen;
5419 	struct propctx *propctx;
5420 {
5421 	if (auth_identity == NULL)
5422 		return SASL_FAIL;
5423 
5424 	macdefine(&BlankEnvelope.e_macro, A_TEMP,
5425 		  macid("{auth_authen}"),
5426 		  xtextify((char *) auth_identity, "=<>\")"));
5427 
5428 	return SASL_OK;
5429 }
5430 # else /* SASL >= 20000 */
5431 
5432 /*
5433 **  PROXY_POLICY -- define proxy policy for AUTH
5434 **
5435 **	Parameters:
5436 **		context -- unused.
5437 **		auth_identity -- authentication identity.
5438 **		requested_user -- authorization identity.
5439 **		user -- allowed user (output).
5440 **		errstr -- possible error string (output).
5441 **
5442 **	Returns:
5443 **		ok?
5444 */
5445 
5446 int
5447 proxy_policy(context, auth_identity, requested_user, user, errstr)
5448 	void *context;
5449 	const char *auth_identity;
5450 	const char *requested_user;
5451 	const char **user;
5452 	const char **errstr;
5453 {
5454 	if (user == NULL || auth_identity == NULL)
5455 		return SASL_FAIL;
5456 	*user = newstr(auth_identity);
5457 	return SASL_OK;
5458 }
5459 # endif /* SASL >= 20000 */
5460 #endif /* SASL */
5461 
5462 #if STARTTLS
5463 /*
5464 **  INITSRVTLS -- initialize server side TLS
5465 **
5466 **	Parameters:
5467 **		tls_ok -- should tls initialization be done?
5468 **
5469 **	Returns:
5470 **		succeeded?
5471 **
5472 **	Side Effects:
5473 **		sets tls_ok_srv which is a static variable in this module.
5474 **		Do NOT remove assignments to it!
5475 */
5476 
5477 bool
5478 initsrvtls(tls_ok)
5479 	bool tls_ok;
5480 {
5481 	if (!tls_ok)
5482 		return false;
5483 
5484 	/* do NOT remove assignment */
5485 	tls_ok_srv = inittls(&srv_ctx, TLS_Srv_Opts, Srv_SSL_Options, true,
5486 			     SrvCertFile, SrvKeyFile,
5487 			     CACertPath, CACertFile, DHParams);
5488 	return tls_ok_srv;
5489 }
5490 #endif /* STARTTLS */
5491 /*
5492 **  SRVFEATURES -- get features for SMTP server
5493 **
5494 **	Parameters:
5495 **		e -- envelope (should be session context).
5496 **		clientname -- name of client.
5497 **		features -- default features for this invocation.
5498 **
5499 **	Returns:
5500 **		server features.
5501 */
5502 
5503 /* table with options: it uses just one character, how about strings? */
5504 static struct
5505 {
5506 	char		srvf_opt;
5507 	unsigned int	srvf_flag;
5508 } srv_feat_table[] =
5509 {
5510 	{ 'A',	SRV_OFFER_AUTH	},
5511 	{ 'B',	SRV_OFFER_VERB	},
5512 	{ 'C',	SRV_REQ_SEC	},
5513 	{ 'D',	SRV_OFFER_DSN	},
5514 	{ 'E',	SRV_OFFER_ETRN	},
5515 	{ 'H',	SRV_NO_HTTP_CMD	},
5516 #if USE_EAI
5517 	{ 'I',	SRV_OFFER_EAI	},
5518 #endif
5519 	{ 'L',	SRV_REQ_AUTH	},
5520 #if PIPELINING
5521 # if _FFR_NO_PIPE
5522 	{ 'N',	SRV_NO_PIPE	},
5523 # endif
5524 	{ 'P',	SRV_OFFER_PIPE	},
5525 #endif /* PIPELINING */
5526 	{ 'R',	SRV_VRFY_CLT	},	/* same as V; not documented */
5527 	{ 'S',	SRV_OFFER_TLS	},
5528 /*	{ 'T',	SRV_TMP_FAIL	},	*/
5529 	{ 'V',	SRV_VRFY_CLT	},
5530 	{ 'X',	SRV_OFFER_EXPN	},
5531 /*	{ 'Y',	SRV_OFFER_VRFY	},	*/
5532 	{ '\0',	SRV_NONE	}
5533 };
5534 
5535 static unsigned int
5536 srvfeatures(e, clientname, features)
5537 	ENVELOPE *e;
5538 	char *clientname;
5539 	unsigned int features;
5540 {
5541 	int r, i, j;
5542 	char **pvp, c, opt;
5543 	char pvpbuf[PSBUFSIZE];
5544 
5545 	pvp = NULL;
5546 	r = rscap("srv_features", clientname, "", e, &pvp, pvpbuf,
5547 		  sizeof(pvpbuf));
5548 	if (r != EX_OK)
5549 		return features;
5550 	if (pvp == NULL || pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
5551 		return features;
5552 	if (pvp[1] != NULL && sm_strncasecmp(pvp[1], "temp", 4) == 0)
5553 		return SRV_TMP_FAIL;
5554 
5555 	/*
5556 	**  General rule (see sendmail.h, d_flags):
5557 	**  lower case: required/offered, upper case: Not required/available
5558 	**
5559 	**  Since we can change some features per daemon, we have both
5560 	**  cases here: turn on/off a feature.
5561 	*/
5562 
5563 	for (i = 1; pvp[i] != NULL; i++)
5564 	{
5565 		c = pvp[i][0];
5566 		j = 0;
5567 		for (;;)
5568 		{
5569 			if ((opt = srv_feat_table[j].srvf_opt) == '\0')
5570 			{
5571 				if (LogLevel > 9)
5572 					sm_syslog(LOG_WARNING, e->e_id,
5573 						  "srvfeatures: unknown feature %s",
5574 						  pvp[i]);
5575 				break;
5576 			}
5577 			if (c == opt)
5578 			{
5579 				features &= ~(srv_feat_table[j].srvf_flag);
5580 				break;
5581 			}
5582 			if (c == tolower(opt))
5583 			{
5584 				features |= srv_feat_table[j].srvf_flag;
5585 				break;
5586 			}
5587 			++j;
5588 		}
5589 	}
5590 	return features;
5591 }
5592 
5593 /*
5594 **  HELP -- implement the HELP command.
5595 **
5596 **	Parameters:
5597 **		topic -- the topic we want help for.
5598 **		e -- envelope.
5599 **
5600 **	Returns:
5601 **		none.
5602 **
5603 **	Side Effects:
5604 **		outputs the help file to message output.
5605 */
5606 #define HELPVSTR	"#vers	"
5607 #define HELPVERSION	2
5608 
5609 void
5610 help(topic, e)
5611 	char *topic;
5612 	ENVELOPE *e;
5613 {
5614 	register SM_FILE_T *hf;
5615 	register char *p;
5616 	char *lstr;
5617 	int len;
5618 	bool noinfo;
5619 	bool first = true;
5620 	long sff = SFF_OPENASROOT|SFF_REGONLY;
5621 	char buf[MAXLINE];
5622 	char inp[MAXLINE];
5623 	static int foundvers = -1;
5624 	extern char Version[];
5625 
5626 	if (DontLockReadFiles)
5627 		sff |= SFF_NOLOCK;
5628 	if (!bitnset(DBS_HELPFILEINUNSAFEDIRPATH, DontBlameSendmail))
5629 		sff |= SFF_SAFEDIRPATH;
5630 
5631 	if (HelpFile == NULL ||
5632 	    (hf = safefopen(HelpFile, O_RDONLY, 0444, sff)) == NULL)
5633 	{
5634 		/* no help */
5635 		errno = 0;
5636 		message("502 5.3.0 Sendmail %s -- HELP not implemented",
5637 			Version);
5638 		return;
5639 	}
5640 
5641 	lstr = NULL;
5642 	if (SM_IS_EMPTY(topic))
5643 	{
5644 		topic = "smtp";
5645 		noinfo = false;
5646 	}
5647 	else
5648 	{
5649 
5650 		lstr = makelower_a(&topic, NULL);
5651 		if (lstr != topic)
5652 			topic = lstr;
5653 		else
5654 			lstr = NULL;
5655 		noinfo = true;
5656 	}
5657 
5658 	len = strlen(topic);
5659 
5660 	while (sm_io_fgets(hf, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0)
5661 	{
5662 		if (buf[0] == '#')
5663 		{
5664 			if (foundvers < 0 &&
5665 			    strncmp(buf, HELPVSTR, strlen(HELPVSTR)) == 0)
5666 			{
5667 				int h;
5668 
5669 				if (sm_io_sscanf(buf + strlen(HELPVSTR), "%d",
5670 						 &h) == 1)
5671 					foundvers = h;
5672 			}
5673 			continue;
5674 		}
5675 		if (strncmp(buf, topic, len) == 0)
5676 		{
5677 			if (first)
5678 			{
5679 				first = false;
5680 
5681 				/* print version if no/old vers# in file */
5682 				if (foundvers < 2 && !noinfo)
5683 					message("214-2.0.0 This is Sendmail version %s", Version);
5684 			}
5685 			p = strpbrk(buf, " \t");
5686 			if (p == NULL)
5687 				p = buf + strlen(buf) - 1;
5688 			else
5689 				p++;
5690 			fixcrlf(p, true);
5691 			if (foundvers >= 2)
5692 			{
5693 				char *lbp;
5694 				int lbs = sizeof(buf) - (p - buf);
5695 
5696 				lbp = translate_dollars(p, p, &lbs);
5697 				expand(lbp, inp, sizeof(inp), e);
5698 				if (p != lbp)
5699 					sm_free(lbp);
5700 				p = inp;
5701 			}
5702 			message("214-2.0.0 %s", p);
5703 			noinfo = false;
5704 		}
5705 	}
5706 
5707 	if (noinfo)
5708 		message("504 5.3.0 HELP topic \"%.10s\" unknown", topic);
5709 	else
5710 		message("214 2.0.0 End of HELP info");
5711 
5712 	if (foundvers != 0 && foundvers < HELPVERSION)
5713 	{
5714 		if (LogLevel > 1)
5715 			sm_syslog(LOG_WARNING, e->e_id,
5716 				  "%s too old (require version %d)",
5717 				  HelpFile, HELPVERSION);
5718 
5719 		/* avoid log next time */
5720 		foundvers = 0;
5721 	}
5722 
5723 	(void) sm_io_close(hf, SM_TIME_DEFAULT);
5724 	SM_FREE(lstr);
5725 }
5726 
5727 #if SASL
5728 /*
5729 **  RESET_SASLCONN -- reset SASL connection data
5730 **
5731 **	Parameters:
5732 **		conn -- SASL connection context
5733 **		hostname -- host name
5734 **		various connection data
5735 **
5736 **	Returns:
5737 **		SASL result
5738 */
5739 
5740 #ifdef __STDC__
5741 static int
5742 reset_saslconn(sasl_conn_t **conn, char *hostname,
5743 # if SASL >= 20000
5744 	       char *remoteip, char *localip,
5745 	       char *auth_id, sasl_ssf_t * ext_ssf)
5746 # else /* SASL >= 20000 */
5747 	       struct sockaddr_in *saddr_r, struct sockaddr_in *saddr_l,
5748 	       sasl_external_properties_t * ext_ssf)
5749 # endif /* SASL >= 20000 */
5750 #else /* __STDC__ */
5751 # ERROR "SASL requires __STDC__"
5752 #endif /* __STDC__ */
5753 {
5754 	int result;
5755 
5756 	sasl_dispose(conn);
5757 # if SASL >= 20000
5758 	result = sasl_server_new("smtp", hostname, NULL, NULL, NULL,
5759 				 NULL, 0, conn);
5760 # elif SASL > 10505
5761 	/* use empty realm: only works in SASL > 1.5.5 */
5762 	result = sasl_server_new("smtp", hostname, "", NULL, 0, conn);
5763 # else /* SASL >= 20000 */
5764 	/* use no realm -> realm is set to hostname by SASL lib */
5765 	result = sasl_server_new("smtp", hostname, NULL, NULL, 0,
5766 				 conn);
5767 # endif /* SASL >= 20000 */
5768 	if (result != SASL_OK)
5769 		return result;
5770 
5771 # if SASL >= 20000
5772 #  if NETINET || NETINET6
5773 	if (remoteip != NULL && *remoteip != '\0')
5774 		result = sasl_setprop(*conn, SASL_IPREMOTEPORT, remoteip);
5775 	if (result != SASL_OK)
5776 		return result;
5777 
5778 	if (localip != NULL && *localip != '\0')
5779 		result = sasl_setprop(*conn, SASL_IPLOCALPORT, localip);
5780 	if (result != SASL_OK)
5781 		return result;
5782 #  endif /* NETINET || NETINET6 */
5783 
5784 	result = sasl_setprop(*conn, SASL_SSF_EXTERNAL, ext_ssf);
5785 	if (result != SASL_OK)
5786 		return result;
5787 
5788 	result = sasl_setprop(*conn, SASL_AUTH_EXTERNAL, auth_id);
5789 	if (result != SASL_OK)
5790 		return result;
5791 # else /* SASL >= 20000 */
5792 #  if NETINET
5793 	if (saddr_r != NULL)
5794 		result = sasl_setprop(*conn, SASL_IP_REMOTE, saddr_r);
5795 	if (result != SASL_OK)
5796 		return result;
5797 
5798 	if (saddr_l != NULL)
5799 		result = sasl_setprop(*conn, SASL_IP_LOCAL, saddr_l);
5800 	if (result != SASL_OK)
5801 		return result;
5802 #  endif /* NETINET */
5803 
5804 	result = sasl_setprop(*conn, SASL_SSF_EXTERNAL, ext_ssf);
5805 	if (result != SASL_OK)
5806 		return result;
5807 # endif /* SASL >= 20000 */
5808 	return SASL_OK;
5809 }
5810 
5811 /*
5812 **  GET_SASL_USER -- extract user part from SASL reply
5813 **
5814 **	Parameters:
5815 **		val -- sasl reply (may contain NUL)
5816 **		len -- length of val
5817 **		auth_type -- auth_type (can be NULL)
5818 **		user -- output buffer for extract user
5819 **		user_len -- length of output buffer (user)
5820 **
5821 **	Returns:
5822 **		none.
5823 **
5824 **	Note: val is supplied by the client and hence may contain "bad"
5825 **		(non-printable) characters, but the returned value (user)
5826 **		is only used for logging which converts those characters.
5827 */
5828 
5829 static void
5830 get_sasl_user(val, len, auth_type, user, user_len)
5831 	char *val;
5832 	unsigned int len;
5833 	const char *auth_type;
5834 	char *user;
5835 	size_t user_len;
5836 {
5837 	unsigned int u;
5838 
5839 	SM_ASSERT(val != NULL);
5840 	SM_ASSERT(user != NULL);
5841 	SM_ASSERT(user_len > 0);
5842 
5843 	*user = '\0';
5844 	if (SM_IS_EMPTY(auth_type))
5845 		return;
5846 	if (0 == len)
5847 		return;
5848 
5849 # define DIGMD5U	"username=\""
5850 # define DIGMD5U_L	(sizeof(DIGMD5U) - 1)
5851 	if (SM_STRCASEEQ(auth_type, "digest-md5") &&
5852 	    strncmp(val, DIGMD5U, DIGMD5U_L) == 0)
5853 	{
5854 		char *s;
5855 
5856 		val += DIGMD5U_L;
5857 		if (len <= DIGMD5U_L)
5858 			return;
5859 		len -= DIGMD5U_L;
5860 
5861 		/* format? could there be a quoted '"'? */
5862 		for (s = val, u = 0; *s != '\0' && u < len; s++)
5863 		{
5864 			if ('"' == *s)
5865 			{
5866 				*s = '\0';
5867 				break;
5868 			}
5869 			if ('\\' == *s)
5870 			{
5871 				++s;
5872 				if ('\0' == *s)
5873 					break;
5874 			}
5875 		}
5876 	}
5877 	else if (SM_STRCASEEQ(auth_type, "cram-md5"))
5878 	{
5879 		char *s;
5880 
5881 		for (s = val, u = 0; *s != '\0' && u < len; s++)
5882 		{
5883 			if (' ' == *s)
5884 			{
5885 				*s = '\0';
5886 				break;
5887 			}
5888 		}
5889 	}
5890 
5891 	else if (SM_STRCASEEQ(auth_type, "plain") ||
5892 		 SM_STRCASEEQ(auth_type, "login"))
5893 	{
5894 		/*
5895 		**  RFC 4616: The PLAIN Simple Authentication and
5896 		**	Security Layer (SASL) Mechanism
5897 		**    message   = [authzid] UTF8NUL authcid UTF8NUL passwd
5898 		**  each part: 1*SAFE ; MUST accept up to 255 octets
5899 		**  UTF8NUL   = %x00 ; UTF-8 encoded NUL character
5900 		**
5901 		**  draft-murchison-sasl-login: it's just username by its own
5902 		*/
5903 
5904 		for (u = 0; u < len; u++)
5905 		{
5906 			if (val[u] == '\0')
5907 			{
5908 				val[u] = '/';
5909 				(void) sm_strlcpy(user,
5910 						val + ((0 == u) ? 1 : 0),
5911 						user_len);
5912 				return;
5913 			}
5914 		}
5915 	}
5916 	else
5917 	{
5918 		/*
5919 		**  Extracting the "user" from other mechanisms
5920 		**  is currently not supported.
5921 		*/
5922 
5923 		return;
5924 	}
5925 
5926 	/*
5927 	**  Does the input buffer has an NUL in it so it can be treated
5928 	**  as a C string?
5929 	*/
5930 
5931 	/* SM_ASSERT(len > 0); see above */
5932 	u = len - 1;
5933 	if (val[u] != '\0')
5934 	{
5935 		for (u = 0; u < len; u++)
5936 		{
5937 			if (val[u] == '\0')
5938 				break;
5939 		}
5940 	}
5941 	if (val[u] != '\0')
5942 		user_len = SM_MIN(len, user_len);
5943 
5944 	(void) sm_strlcpy(user, val, user_len);
5945 }
5946 #endif /* SASL */
5947