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