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