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