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