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