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