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