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