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