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