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