Home | History | Annotate | Download | only in src
      1     0  stevel /*
      2  6562   jbeck  * Copyright (c) 1998-2008 Sendmail, Inc. and its suppliers.
      3     0  stevel  *	All rights reserved.
      4     0  stevel  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
      5     0  stevel  * Copyright (c) 1988, 1993
      6     0  stevel  *	The Regents of the University of California.  All rights reserved.
      7     0  stevel  *
      8     0  stevel  * By using this file, you agree to the terms and conditions set
      9     0  stevel  * forth in the LICENSE file which can be found at the top level of
     10     0  stevel  * the sendmail distribution.
     11     0  stevel  *
     12     0  stevel  */
     13     0  stevel 
     14     0  stevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
     15     0  stevel 
     16     0  stevel #include <sendmail.h>
     17     0  stevel #if MILTER
     18     0  stevel # include <libmilter/mfapi.h>
     19     0  stevel # include <libmilter/mfdef.h>
     20     0  stevel #endif /* MILTER */
     21     0  stevel 
     22  6562   jbeck SM_RCSID("@(#)$Id: srvrsmtp.c,v 8.975 2008/03/31 16:32:13 ca Exp $")
     23   616   jbeck 
     24   616   jbeck #include <sm/time.h>
     25     0  stevel #include <sm/fdset.h>
     26     0  stevel 
     27     0  stevel #if SASL || STARTTLS
     28     0  stevel # include "sfsasl.h"
     29     0  stevel #endif /* SASL || STARTTLS */
     30     0  stevel #if SASL
     31     0  stevel # define ENC64LEN(l)	(((l) + 2) * 4 / 3 + 1)
     32     0  stevel static int saslmechs __P((sasl_conn_t *, char **));
     33     0  stevel #endif /* SASL */
     34     0  stevel #if STARTTLS
     35     0  stevel # include <sysexits.h>
     36     0  stevel 
     37     0  stevel static SSL_CTX	*srv_ctx = NULL;	/* TLS server context */
     38     0  stevel static SSL	*srv_ssl = NULL;	/* per connection context */
     39     0  stevel 
     40     0  stevel static bool	tls_ok_srv = false;
     41  3544   jbeck 
     42  3544   jbeck # define TLS_VERIFY_CLIENT() tls_set_verify(srv_ctx, srv_ssl, \
     43  3544   jbeck 				bitset(SRV_VRFY_CLT, features))
     44  3544   jbeck #endif /* STARTTLS */
     45  3544   jbeck 
     46  1658   jbeck #if _FFR_DM_ONE
     47  1658   jbeck static bool	NotFirstDelivery = false;
     48  1658   jbeck #endif /* _FFR_DM_ONE */
     49     0  stevel 
     50     0  stevel /* server features */
     51     0  stevel #define SRV_NONE	0x0000	/* none... */
     52     0  stevel #define SRV_OFFER_TLS	0x0001	/* offer STARTTLS */
     53     0  stevel #define SRV_VRFY_CLT	0x0002	/* request a cert */
     54     0  stevel #define SRV_OFFER_AUTH	0x0004	/* offer AUTH */
     55     0  stevel #define SRV_OFFER_ETRN	0x0008	/* offer ETRN */
     56     0  stevel #define SRV_OFFER_VRFY	0x0010	/* offer VRFY (not yet used) */
     57     0  stevel #define SRV_OFFER_EXPN	0x0020	/* offer EXPN */
     58     0  stevel #define SRV_OFFER_VERB	0x0040	/* offer VERB */
     59     0  stevel #define SRV_OFFER_DSN	0x0080	/* offer DSN */
     60     0  stevel #if PIPELINING
     61     0  stevel # define SRV_OFFER_PIPE	0x0100	/* offer PIPELINING */
     62     0  stevel # if _FFR_NO_PIPE
     63     0  stevel #  define SRV_NO_PIPE	0x0200	/* disable PIPELINING, sleep if used */
     64     0  stevel # endif /* _FFR_NO_PIPE */
     65     0  stevel #endif /* PIPELINING */
     66     0  stevel #define SRV_REQ_AUTH	0x0400	/* require AUTH */
     67     0  stevel #define SRV_REQ_SEC	0x0800	/* require security - equiv to AuthOptions=p */
     68     0  stevel #define SRV_TMP_FAIL	0x1000	/* ruleset caused a temporary failure */
     69     0  stevel 
     70     0  stevel static unsigned int	srvfeatures __P((ENVELOPE *, char *, unsigned int));
     71     0  stevel 
     72     0  stevel #define	STOP_ATTACK	((time_t) -1)
     73     0  stevel static time_t	checksmtpattack __P((volatile unsigned int *, unsigned int,
     74     0  stevel 				     bool, char *, ENVELOPE *));
     75     0  stevel static void	printvrfyaddr __P((ADDRESS *, bool, bool));
     76     0  stevel static char	*skipword __P((char *volatile, char *));
     77     0  stevel static void	setup_smtpd_io __P((void));
     78     0  stevel 
     79     0  stevel #if SASL
     80     0  stevel # if SASL >= 20000
     81     0  stevel static int reset_saslconn __P((sasl_conn_t **_conn, char *_hostname,
     82     0  stevel 				char *_remoteip, char *_localip,
     83     0  stevel 				char *_auth_id, sasl_ssf_t *_ext_ssf));
     84     0  stevel 
     85     0  stevel # define RESET_SASLCONN	\
     86     0  stevel 	do							\
     87     0  stevel 	{							\
     88     0  stevel 		result = reset_saslconn(&conn, AuthRealm, remoteip, \
     89     0  stevel 					localip, auth_id, &ext_ssf); \
     90     0  stevel 		if (result != SASL_OK)				\
     91     0  stevel 			sasl_ok = false;			\
     92     0  stevel 	} while (0)
     93     0  stevel 
     94     0  stevel # else /* SASL >= 20000 */
     95     0  stevel static int reset_saslconn __P((sasl_conn_t **_conn, char *_hostname,
     96     0  stevel 				struct sockaddr_in *_saddr_r,
     97     0  stevel 				struct sockaddr_in *_saddr_l,
     98     0  stevel 				sasl_external_properties_t *_ext_ssf));
     99     0  stevel # define RESET_SASLCONN	\
    100     0  stevel 	do							\
    101     0  stevel 	{							\
    102     0  stevel 		result = reset_saslconn(&conn, AuthRealm, &saddr_r, \
    103     0  stevel 					&saddr_l, &ext_ssf);	\
    104     0  stevel 		if (result != SASL_OK)				\
    105     0  stevel 			sasl_ok = false;			\
    106     0  stevel 	} while (0)
    107     0  stevel 
    108     0  stevel # endif /* SASL >= 20000 */
    109     0  stevel #endif /* SASL */
    110     0  stevel 
    111     0  stevel extern ENVELOPE	BlankEnvelope;
    112     0  stevel 
    113     0  stevel #define NBADRCPTS						\
    114     0  stevel 	do							\
    115     0  stevel 	{							\
    116     0  stevel 		char buf[16];					\
    117  3544   jbeck 		(void) sm_snprintf(buf, sizeof(buf), "%d",	\
    118     0  stevel 			BadRcptThrottle > 0 && n_badrcpts > BadRcptThrottle \
    119     0  stevel 				? n_badrcpts - 1 : n_badrcpts);	\
    120     0  stevel 		macdefine(&e->e_macro, A_TEMP, macid("{nbadrcpts}"), buf); \
    121     0  stevel 	} while (0)
    122     0  stevel 
    123     0  stevel #define SKIP_SPACE(s)	while (isascii(*s) && isspace(*s))	\
    124     0  stevel 				(s)++
    125  3544   jbeck 
    126  3544   jbeck /*
    127  3544   jbeck **  PARSE_ESMTP_ARGS -- parse EMSTP arguments (for MAIL, RCPT)
    128  3544   jbeck **
    129  3544   jbeck **	Parameters:
    130  3544   jbeck **		e -- the envelope
    131  3544   jbeck **		addr_st -- address (RCPT only)
    132  3544   jbeck **		p -- read buffer
    133  3544   jbeck **		delimptr -- current position in read buffer
    134  3544   jbeck **		which -- MAIL/RCPT
    135  3544   jbeck **		args -- arguments (output)
    136  3544   jbeck **		esmtp_args -- function to process a single ESMTP argument
    137  3544   jbeck **
    138  3544   jbeck **	Returns:
    139  3544   jbeck **		none
    140  3544   jbeck */
    141  3544   jbeck 
    142  3544   jbeck void
    143  3544   jbeck parse_esmtp_args(e, addr_st, p, delimptr, which, args, esmtp_args)
    144  3544   jbeck 	ENVELOPE *e;
    145  3544   jbeck 	ADDRESS *addr_st;
    146  3544   jbeck 	char *p;
    147  3544   jbeck 	char *delimptr;
    148  3544   jbeck 	char *which;
    149  3544   jbeck 	char *args[];
    150  3544   jbeck 	esmtp_args_F esmtp_args;
    151  3544   jbeck {
    152  3544   jbeck 	int argno;
    153  3544   jbeck 
    154  3544   jbeck 	argno = 0;
    155  3544   jbeck 	if (args != NULL)
    156  3544   jbeck 		args[argno++] = p;
    157  3544   jbeck 	p = delimptr;
    158  3544   jbeck 	while (p != NULL && *p != '\0')
    159  3544   jbeck 	{
    160  3544   jbeck 		char *kp;
    161  3544   jbeck 		char *vp = NULL;
    162  3544   jbeck 		char *equal = NULL;
    163  3544   jbeck 
    164  3544   jbeck 		/* locate the beginning of the keyword */
    165  3544   jbeck 		SKIP_SPACE(p);
    166  3544   jbeck 		if (*p == '\0')
    167  3544   jbeck 			break;
    168  3544   jbeck 		kp = p;
    169  3544   jbeck 
    170  3544   jbeck 		/* skip to the value portion */
    171  3544   jbeck 		while ((isascii(*p) && isalnum(*p)) || *p == '-')
    172  3544   jbeck 			p++;
    173  3544   jbeck 		if (*p == '=')
    174  3544   jbeck 		{
    175  3544   jbeck 			equal = p;
    176  3544   jbeck 			*p++ = '\0';
    177  3544   jbeck 			vp = p;
    178  3544   jbeck 
    179  3544   jbeck 			/* skip to the end of the value */
    180  3544   jbeck 			while (*p != '\0' && *p != ' ' &&
    181  3544   jbeck 			       !(isascii(*p) && iscntrl(*p)) &&
    182  3544   jbeck 			       *p != '=')
    183  3544   jbeck 				p++;
    184  3544   jbeck 		}
    185  3544   jbeck 
    186  3544   jbeck 		if (*p != '\0')
    187  3544   jbeck 			*p++ = '\0';
    188  3544   jbeck 
    189  3544   jbeck 		if (tTd(19, 1))
    190  3544   jbeck 			sm_dprintf("%s: got arg %s=\"%s\"\n", which, kp,
    191  3544   jbeck 				vp == NULL ? "<null>" : vp);
    192  3544   jbeck 
    193  3544   jbeck 		esmtp_args(addr_st, kp, vp, e);
    194  3544   jbeck 		if (equal != NULL)
    195  3544   jbeck 			*equal = '=';
    196  3544   jbeck 		if (args != NULL)
    197  3544   jbeck 			args[argno] = kp;
    198  3544   jbeck 		argno++;
    199  3544   jbeck 		if (argno >= MAXSMTPARGS - 1)
    200  3544   jbeck 			usrerr("501 5.5.4 Too many parameters");
    201  3544   jbeck 		if (Errors > 0)
    202  3544   jbeck 			break;
    203  3544   jbeck 	}
    204  3544   jbeck 	if (args != NULL)
    205  3544   jbeck 		args[argno] = NULL;
    206  3544   jbeck }
    207     0  stevel 
    208     0  stevel /*
    209     0  stevel **  SMTP -- run the SMTP protocol.
    210     0  stevel **
    211     0  stevel **	Parameters:
    212     0  stevel **		nullserver -- if non-NULL, rejection message for
    213     0  stevel **			(almost) all SMTP commands.
    214     0  stevel **		d_flags -- daemon flags
    215     0  stevel **		e -- the envelope.
    216     0  stevel **
    217     0  stevel **	Returns:
    218     0  stevel **		never.
    219     0  stevel **
    220     0  stevel **	Side Effects:
    221     0  stevel **		Reads commands from the input channel and processes them.
    222     0  stevel */
    223     0  stevel 
    224     0  stevel /*
    225     0  stevel **  Notice: The smtp server doesn't have a session context like the client
    226     0  stevel **	side has (mci). Therefore some data (session oriented) is allocated
    227     0  stevel **	or assigned to the "wrong" structure (esp. STARTTLS, AUTH).
    228     0  stevel **	This should be fixed in a successor version.
    229     0  stevel */
    230     0  stevel 
    231     0  stevel struct cmd
    232     0  stevel {
    233     0  stevel 	char	*cmd_name;	/* command name */
    234     0  stevel 	int	cmd_code;	/* internal code, see below */
    235     0  stevel };
    236     0  stevel 
    237     0  stevel /* values for cmd_code */
    238     0  stevel #define CMDERROR	0	/* bad command */
    239     0  stevel #define CMDMAIL	1	/* mail -- designate sender */
    240     0  stevel #define CMDRCPT	2	/* rcpt -- designate recipient */
    241     0  stevel #define CMDDATA	3	/* data -- send message text */
    242     0  stevel #define CMDRSET	4	/* rset -- reset state */
    243     0  stevel #define CMDVRFY	5	/* vrfy -- verify address */
    244     0  stevel #define CMDEXPN	6	/* expn -- expand address */
    245     0  stevel #define CMDNOOP	7	/* noop -- do nothing */
    246     0  stevel #define CMDQUIT	8	/* quit -- close connection and die */
    247     0  stevel #define CMDHELO	9	/* helo -- be polite */
    248     0  stevel #define CMDHELP	10	/* help -- give usage info */
    249     0  stevel #define CMDEHLO	11	/* ehlo -- extended helo (RFC 1425) */
    250     0  stevel #define CMDETRN	12	/* etrn -- flush queue */
    251     0  stevel #if SASL
    252     0  stevel # define CMDAUTH	13	/* auth -- SASL authenticate */
    253     0  stevel #endif /* SASL */
    254     0  stevel #if STARTTLS
    255     0  stevel # define CMDSTLS	14	/* STARTTLS -- start TLS session */
    256     0  stevel #endif /* STARTTLS */
    257     0  stevel /* non-standard commands */
    258     0  stevel #define CMDVERB	17	/* verb -- go into verbose mode */
    259     0  stevel /* unimplemented commands from RFC 821 */
    260     0  stevel #define CMDUNIMPL	19	/* unimplemented rfc821 commands */
    261     0  stevel /* use this to catch and log "door handle" attempts on your system */
    262     0  stevel #define CMDLOGBOGUS	23	/* bogus command that should be logged */
    263     0  stevel /* debugging-only commands, only enabled if SMTPDEBUG is defined */
    264     0  stevel #define CMDDBGQSHOW	24	/* showq -- show send queue */
    265     0  stevel #define CMDDBGDEBUG	25	/* debug -- set debug mode */
    266     0  stevel 
    267     0  stevel /*
    268     0  stevel **  Note: If you change this list, remember to update 'helpfile'
    269     0  stevel */
    270     0  stevel 
    271     0  stevel static struct cmd	CmdTab[] =
    272     0  stevel {
    273     0  stevel 	{ "mail",	CMDMAIL		},
    274     0  stevel 	{ "rcpt",	CMDRCPT		},
    275     0  stevel 	{ "data",	CMDDATA		},
    276     0  stevel 	{ "rset",	CMDRSET		},
    277     0  stevel 	{ "vrfy",	CMDVRFY		},
    278     0  stevel 	{ "expn",	CMDEXPN		},
    279     0  stevel 	{ "help",	CMDHELP		},
    280     0  stevel 	{ "noop",	CMDNOOP		},
    281     0  stevel 	{ "quit",	CMDQUIT		},
    282     0  stevel 	{ "helo",	CMDHELO		},
    283     0  stevel 	{ "ehlo",	CMDEHLO		},
    284     0  stevel 	{ "etrn",	CMDETRN		},
    285     0  stevel 	{ "verb",	CMDVERB		},
    286     0  stevel 	{ "send",	CMDUNIMPL	},
    287     0  stevel 	{ "saml",	CMDUNIMPL	},
    288     0  stevel 	{ "soml",	CMDUNIMPL	},
    289     0  stevel 	{ "turn",	CMDUNIMPL	},
    290     0  stevel #if SASL
    291     0  stevel 	{ "auth",	CMDAUTH,	},
    292     0  stevel #endif /* SASL */
    293     0  stevel #if STARTTLS
    294     0  stevel 	{ "starttls",	CMDSTLS,	},
    295     0  stevel #endif /* STARTTLS */
    296     0  stevel     /* remaining commands are here only to trap and log attempts to use them */
    297     0  stevel 	{ "showq",	CMDDBGQSHOW	},
    298     0  stevel 	{ "debug",	CMDDBGDEBUG	},
    299     0  stevel 	{ "wiz",	CMDLOGBOGUS	},
    300     0  stevel 
    301     0  stevel 	{ NULL,		CMDERROR	}
    302     0  stevel };
    303     0  stevel 
    304     0  stevel static char	*CurSmtpClient;		/* who's at the other end of channel */
    305     0  stevel 
    306     0  stevel #ifndef MAXBADCOMMANDS
    307     0  stevel # define MAXBADCOMMANDS 25	/* maximum number of bad commands */
    308     0  stevel #endif /* ! MAXBADCOMMANDS */
    309     0  stevel #ifndef MAXHELOCOMMANDS
    310     0  stevel # define MAXHELOCOMMANDS 3	/* max HELO/EHLO commands before slowdown */
    311     0  stevel #endif /* ! MAXHELOCOMMANDS */
    312     0  stevel #ifndef MAXVRFYCOMMANDS
    313     0  stevel # define MAXVRFYCOMMANDS 6	/* max VRFY/EXPN commands before slowdown */
    314     0  stevel #endif /* ! MAXVRFYCOMMANDS */
    315     0  stevel #ifndef MAXETRNCOMMANDS
    316     0  stevel # define MAXETRNCOMMANDS 8	/* max ETRN commands before slowdown */
    317     0  stevel #endif /* ! MAXETRNCOMMANDS */
    318     0  stevel #ifndef MAXTIMEOUT
    319     0  stevel # define MAXTIMEOUT (4 * 60)	/* max timeout for bad commands */
    320     0  stevel #endif /* ! MAXTIMEOUT */
    321     0  stevel 
    322     0  stevel /*
    323     0  stevel **  Maximum shift value to compute timeout for bad commands.
    324     0  stevel **  This introduces an upper limit of 2^MAXSHIFT for the timeout.
    325     0  stevel */
    326     0  stevel 
    327     0  stevel #ifndef MAXSHIFT
    328     0  stevel # define MAXSHIFT 8
    329     0  stevel #endif /* ! MAXSHIFT */
    330     0  stevel #if MAXSHIFT > 31
    331     0  stevel  ERROR _MAXSHIFT > 31 is invalid
    332     0  stevel #endif /* MAXSHIFT */
    333     0  stevel 
    334     0  stevel 
    335     0  stevel #if MAXBADCOMMANDS > 0
    336     0  stevel # define STOP_IF_ATTACK(r)	do		\
    337     0  stevel 	{					\
    338     0  stevel 		if ((r) == STOP_ATTACK)		\
    339     0  stevel 			goto stopattack;	\
    340     0  stevel 	} while (0)
    341     0  stevel 
    342     0  stevel #else /* MAXBADCOMMANDS > 0 */
    343     0  stevel # define STOP_IF_ATTACK(r)	r
    344     0  stevel #endif /* MAXBADCOMMANDS > 0 */
    345     0  stevel 
    346     0  stevel 
    347     0  stevel #if SM_HEAP_CHECK
    348     0  stevel static SM_DEBUG_T DebugLeakSmtp = SM_DEBUG_INITIALIZER("leak_smtp",
    349     0  stevel 	"@(#)$Debug: leak_smtp - trace memory leaks during SMTP processing $");
    350     0  stevel #endif /* SM_HEAP_CHECK */
    351     0  stevel 
    352     0  stevel typedef struct
    353     0  stevel {
    354  5402   jbeck 	bool		sm_gotmail;	/* mail command received */
    355  5402   jbeck 	unsigned int	sm_nrcpts;	/* number of successful RCPT commands */
    356  5402   jbeck 	bool		sm_discard;
    357  5402   jbeck #if MILTER
    358  5402   jbeck 	bool		sm_milterize;
    359  5402   jbeck 	bool		sm_milterlist;	/* any filters in the list? */
    360  5402   jbeck 	milters_T	sm_milters;
    361  5402   jbeck 
    362  5402   jbeck 	/* e_nrcpts from envelope before recipient() call */
    363  5402   jbeck 	unsigned int	sm_e_nrcpts_orig;
    364  5402   jbeck #endif /* MILTER */
    365  5402   jbeck 	char		*sm_quarmsg;	/* carry quarantining across messages */
    366     0  stevel } SMTP_T;
    367     0  stevel 
    368     0  stevel static bool	smtp_data __P((SMTP_T *, ENVELOPE *));
    369     0  stevel 
    370     0  stevel #define MSG_TEMPFAIL "451 4.3.2 Please try again later"
    371     0  stevel 
    372     0  stevel #if MILTER
    373     0  stevel # define MILTER_ABORT(e)	milter_abort((e))
    374     0  stevel 
    375     0  stevel # define MILTER_REPLY(str)						\
    376     0  stevel 	{								\
    377     0  stevel 		int savelogusrerrs = LogUsrErrs;			\
    378     0  stevel 									\
    379  3966   jbeck 		milter_cmd_fail = true;					\
    380     0  stevel 		switch (state)						\
    381     0  stevel 		{							\
    382  1658   jbeck 		  case SMFIR_SHUTDOWN:					\
    383  1658   jbeck 			if (MilterLogLevel > 3)				\
    384  1658   jbeck 			{						\
    385  1658   jbeck 				sm_syslog(LOG_INFO, e->e_id,		\
    386  1658   jbeck 					  "Milter: %s=%s, reject=421, errormode=4",	\
    387  1658   jbeck 					  str, addr);			\
    388  1658   jbeck 				LogUsrErrs = false;			\
    389  1658   jbeck 			}						\
    390  1658   jbeck 			{						\
    391  1658   jbeck 				bool tsave = QuickAbort;		\
    392  1658   jbeck 									\
    393  1658   jbeck 				QuickAbort = false;			\
    394  1658   jbeck 				usrerr("421 4.3.0 closing connection");	\
    395  1658   jbeck 				QuickAbort = tsave;			\
    396  1658   jbeck 				e->e_sendqueue = NULL;			\
    397  1658   jbeck 				goto doquit;				\
    398  1658   jbeck 			}						\
    399  1658   jbeck 			break;						\
    400     0  stevel 		  case SMFIR_REPLYCODE:					\
    401     0  stevel 			if (MilterLogLevel > 3)				\
    402     0  stevel 			{						\
    403     0  stevel 				sm_syslog(LOG_INFO, e->e_id,		\
    404     0  stevel 					  "Milter: %s=%s, reject=%s",	\
    405     0  stevel 					  str, addr, response);		\
    406     0  stevel 				LogUsrErrs = false;			\
    407     0  stevel 			}						\
    408   616   jbeck 			if (strncmp(response, "421 ", 4) == 0		\
    409   616   jbeck 			    || strncmp(response, "421-", 4) == 0)	\
    410     0  stevel 			{						\
    411     0  stevel 				bool tsave = QuickAbort;		\
    412     0  stevel 									\
    413     0  stevel 				QuickAbort = false;			\
    414     0  stevel 				usrerr(response);			\
    415     0  stevel 				QuickAbort = tsave;			\
    416     0  stevel 				e->e_sendqueue = NULL;			\
    417     0  stevel 				goto doquit;				\
    418     0  stevel 			}						\
    419     0  stevel 			else						\
    420     0  stevel 				usrerr(response);			\
    421     0  stevel 			break;						\
    422     0  stevel 									\
    423     0  stevel 		  case SMFIR_REJECT:					\
    424     0  stevel 			if (MilterLogLevel > 3)				\
    425     0  stevel 			{						\
    426     0  stevel 				sm_syslog(LOG_INFO, e->e_id,		\
    427     0  stevel 					  "Milter: %s=%s, reject=550 5.7.1 Command rejected", \
    428     0  stevel 					  str, addr);			\
    429     0  stevel 				LogUsrErrs = false;			\
    430     0  stevel 			}						\
    431     0  stevel 			usrerr("550 5.7.1 Command rejected");		\
    432     0  stevel 			break;						\
    433     0  stevel 									\
    434     0  stevel 		  case SMFIR_DISCARD:					\
    435     0  stevel 			if (MilterLogLevel > 3)				\
    436     0  stevel 				sm_syslog(LOG_INFO, e->e_id,		\
    437     0  stevel 					  "Milter: %s=%s, discard",	\
    438     0  stevel 					  str, addr);			\
    439     0  stevel 			e->e_flags |= EF_DISCARD;			\
    440  3966   jbeck 			milter_cmd_fail = false;			\
    441     0  stevel 			break;						\
    442     0  stevel 									\
    443     0  stevel 		  case SMFIR_TEMPFAIL:					\
    444     0  stevel 			if (MilterLogLevel > 3)				\
    445     0  stevel 			{						\
    446     0  stevel 				sm_syslog(LOG_INFO, e->e_id,		\
    447     0  stevel 					  "Milter: %s=%s, reject=%s",	\
    448     0  stevel 					  str, addr, MSG_TEMPFAIL);	\
    449     0  stevel 				LogUsrErrs = false;			\
    450     0  stevel 			}						\
    451     0  stevel 			usrerr(MSG_TEMPFAIL);				\
    452  3966   jbeck 			break;						\
    453  3966   jbeck 		  default:						\
    454  3966   jbeck 			milter_cmd_fail = false;			\
    455     0  stevel 			break;						\
    456     0  stevel 		}							\
    457     0  stevel 		LogUsrErrs = savelogusrerrs;				\
    458     0  stevel 		if (response != NULL)					\
    459     0  stevel 			sm_free(response); /* XXX */			\
    460     0  stevel 	}
    461     0  stevel 
    462     0  stevel #else /* MILTER */
    463     0  stevel # define MILTER_ABORT(e)
    464     0  stevel #endif /* MILTER */
    465     0  stevel 
    466     0  stevel /* clear all SMTP state (for HELO/EHLO/RSET) */
    467     0  stevel #define CLEAR_STATE(cmd)					\
    468     0  stevel do								\
    469     0  stevel {								\
    470     0  stevel 	/* abort milter filters */				\
    471     0  stevel 	MILTER_ABORT(e);					\
    472     0  stevel 								\
    473     0  stevel 	if (smtp.sm_nrcpts > 0)					\
    474     0  stevel 	{							\
    475     0  stevel 		logundelrcpts(e, cmd, 10, false);		\
    476     0  stevel 		smtp.sm_nrcpts = 0;				\
    477     0  stevel 		macdefine(&e->e_macro, A_PERM,			\
    478     0  stevel 			  macid("{nrcpts}"), "0");		\
    479     0  stevel 	}							\
    480     0  stevel 								\
    481     0  stevel 	e->e_sendqueue = NULL;					\
    482     0  stevel 	e->e_flags |= EF_CLRQUEUE;				\
    483     0  stevel 								\
    484     0  stevel 	if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))	\
    485     0  stevel 		logsender(e, NULL);				\
    486     0  stevel 	e->e_flags &= ~EF_LOGSENDER;				\
    487     0  stevel 								\
    488     0  stevel 	/* clean up a bit */					\
    489     0  stevel 	smtp.sm_gotmail = false;				\
    490     0  stevel 	SuprErrs = true;					\
    491     0  stevel 	dropenvelope(e, true, false);				\
    492     0  stevel 	sm_rpool_free(e->e_rpool);				\
    493     0  stevel 	e = newenvelope(e, CurEnv, sm_rpool_new_x(NULL));	\
    494     0  stevel 	CurEnv = e;						\
    495  3544   jbeck 	e->e_features = features;				\
    496     0  stevel 								\
    497     0  stevel 	/* put back discard bit */				\
    498     0  stevel 	if (smtp.sm_discard)					\
    499     0  stevel 		e->e_flags |= EF_DISCARD;			\
    500     0  stevel 								\
    501     0  stevel 	/* restore connection quarantining */			\
    502     0  stevel 	if (smtp.sm_quarmsg == NULL)				\
    503     0  stevel 	{							\
    504     0  stevel 		e->e_quarmsg = NULL;				\
    505     0  stevel 		macdefine(&e->e_macro, A_PERM,			\
    506     0  stevel 			macid("{quarantine}"), "");		\
    507     0  stevel 	}							\
    508     0  stevel 	else							\
    509     0  stevel 	{							\
    510     0  stevel 		e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool,	\
    511     0  stevel 						smtp.sm_quarmsg);	\
    512     0  stevel 		macdefine(&e->e_macro, A_PERM, macid("{quarantine}"),	\
    513     0  stevel 			  e->e_quarmsg);			\
    514     0  stevel 	}							\
    515     0  stevel } while (0)
    516     0  stevel 
    517     0  stevel /* sleep to flatten out connection load */
    518     0  stevel #define MIN_DELAY_LOG	15	/* wait before logging this again */
    519     0  stevel 
    520     0  stevel /* is it worth setting the process title for 1s? */
    521     0  stevel #define DELAY_CONN(cmd)						\
    522     0  stevel 	if (DelayLA > 0 && (CurrentLA = getla()) >= DelayLA)	\
    523     0  stevel 	{							\
    524     0  stevel 		time_t dnow;					\
    525     0  stevel 								\
    526     0  stevel 		sm_setproctitle(true, e,			\
    527     0  stevel 				"%s: %s: delaying %s: load average: %d", \
    528     0  stevel 				qid_printname(e), CurSmtpClient,	\
    529     0  stevel 				cmd, DelayLA);	\
    530     0  stevel 		if (LogLevel > 8 && (dnow = curtime()) > log_delay)	\
    531     0  stevel 		{						\
    532     0  stevel 			sm_syslog(LOG_INFO, e->e_id,		\
    533     0  stevel 				  "delaying=%s, load average=%d >= %d",	\
    534     0  stevel 				  cmd, CurrentLA, DelayLA);		\
    535     0  stevel 			log_delay = dnow + MIN_DELAY_LOG;	\
    536     0  stevel 		}						\
    537     0  stevel 		(void) sleep(1);				\
    538     0  stevel 		sm_setproctitle(true, e, "%s %s: %.80s",	\
    539     0  stevel 				qid_printname(e), CurSmtpClient, inp);	\
    540     0  stevel 	}
    541     0  stevel 
    542  3544   jbeck static bool SevenBitInput_Saved;	/* saved version of SevenBitInput */
    543     0  stevel 
    544     0  stevel void
    545     0  stevel smtp(nullserver, d_flags, e)
    546     0  stevel 	char *volatile nullserver;
    547     0  stevel 	BITMAP256 d_flags;
    548     0  stevel 	register ENVELOPE *volatile e;
    549     0  stevel {
    550     0  stevel 	register char *volatile p;
    551     0  stevel 	register struct cmd *volatile c = NULL;
    552     0  stevel 	char *cmd;
    553     0  stevel 	auto ADDRESS *vrfyqueue;
    554     0  stevel 	ADDRESS *a;
    555     0  stevel 	volatile bool gothello;		/* helo command received */
    556     0  stevel 	bool vrfy;			/* set if this is a vrfy command */
    557     0  stevel 	char *volatile protocol;	/* sending protocol */
    558     0  stevel 	char *volatile sendinghost;	/* sending hostname */
    559     0  stevel 	char *volatile peerhostname;	/* name of SMTP peer or "localhost" */
    560     0  stevel 	auto char *delimptr;
    561     0  stevel 	char *id;
    562     0  stevel 	volatile unsigned int n_badcmds = 0;	/* count of bad commands */
    563     0  stevel 	volatile unsigned int n_badrcpts = 0;	/* number of rejected RCPT */
    564     0  stevel 	volatile unsigned int n_verifies = 0;	/* count of VRFY/EXPN */
    565     0  stevel 	volatile unsigned int n_etrn = 0;	/* count of ETRN */
    566     0  stevel 	volatile unsigned int n_noop = 0;	/* count of NOOP/VERB/etc */
    567     0  stevel 	volatile unsigned int n_helo = 0;	/* count of HELO/EHLO */
    568     0  stevel 	bool ok;
    569     0  stevel 	volatile bool first;
    570     0  stevel 	volatile bool tempfail = false;
    571     0  stevel 	volatile time_t wt;		/* timeout after too many commands */
    572     0  stevel 	volatile time_t previous;	/* time after checksmtpattack() */
    573     0  stevel 	volatile bool lognullconnection = true;
    574     0  stevel 	register char *q;
    575     0  stevel 	SMTP_T smtp;
    576     0  stevel 	char *addr;
    577     0  stevel 	char *greetcode = "220";
    578     0  stevel 	char *hostname;			/* my hostname ($j) */
    579     0  stevel 	QUEUE_CHAR *new;
    580     0  stevel 	char *args[MAXSMTPARGS];
    581  3544   jbeck 	char inp[MAXINPLINE];
    582  3544   jbeck #if MAXINPLINE < MAXLINE
    583  3544   jbeck  ERROR _MAXINPLINE must NOT be less than _MAXLINE: MAXINPLINE < MAXLINE
    584  3544   jbeck #endif /* MAXINPLINE < MAXLINE */
    585     0  stevel 	char cmdbuf[MAXLINE];
    586     0  stevel #if SASL
    587     0  stevel 	sasl_conn_t *conn;
    588     0  stevel 	volatile bool sasl_ok;
    589     0  stevel 	volatile unsigned int n_auth = 0;	/* count of AUTH commands */
    590     0  stevel 	bool ismore;
    591     0  stevel 	int result;
    592     0  stevel 	volatile int authenticating;
    593     0  stevel 	char *user;
    594     0  stevel 	char *in, *out2;
    595     0  stevel # if SASL >= 20000
    596  3544   jbeck 	char *auth_id = NULL;
    597     0  stevel 	const char *out;
    598     0  stevel 	sasl_ssf_t ext_ssf;
    599     0  stevel 	char localip[60], remoteip[60];
    600     0  stevel # else /* SASL >= 20000 */
    601     0  stevel 	char *out;
    602     0  stevel 	const char *errstr;
    603     0  stevel 	sasl_external_properties_t ext_ssf;
    604     0  stevel 	struct sockaddr_in saddr_l;
    605     0  stevel 	struct sockaddr_in saddr_r;
    606     0  stevel # endif /* SASL >= 20000 */
    607     0  stevel 	sasl_security_properties_t ssp;
    608     0  stevel 	sasl_ssf_t *ssf;
    609     0  stevel 	unsigned int inlen, out2len;
    610     0  stevel 	unsigned int outlen;
    611     0  stevel 	char *volatile auth_type;
    612     0  stevel 	char *mechlist;
    613     0  stevel 	volatile unsigned int n_mechs;
    614     0  stevel 	unsigned int len;
    615  3544   jbeck #else /* SASL */
    616     0  stevel #endif /* SASL */
    617     0  stevel 	int r;
    618     0  stevel #if STARTTLS
    619     0  stevel 	int rfd, wfd;
    620     0  stevel 	volatile bool tls_active = false;
    621     0  stevel 	volatile bool smtps = bitnset(D_SMTPS, d_flags);
    622     0  stevel 	bool saveQuickAbort;
    623     0  stevel 	bool saveSuprErrs;
    624     0  stevel 	time_t tlsstart;
    625     0  stevel #endif /* STARTTLS */
    626     0  stevel 	volatile unsigned int features;
    627     0  stevel #if PIPELINING
    628     0  stevel # if _FFR_NO_PIPE
    629     0  stevel 	int np_log = 0;
    630     0  stevel # endif /* _FFR_NO_PIPE */
    631     0  stevel #endif /* PIPELINING */
    632     0  stevel 	volatile time_t log_delay = (time_t) 0;
    633  3544   jbeck #if MILTER
    634  3544   jbeck 	volatile bool milter_cmd_done, milter_cmd_safe;
    635  3966   jbeck 	volatile bool milter_rcpt_added, milter_cmd_fail;
    636  3544   jbeck 	ADDRESS addr_st;
    637  3544   jbeck # define p_addr_st	&addr_st
    638  3544   jbeck #else /* MILTER */
    639  3544   jbeck # define p_addr_st	NULL
    640  3544   jbeck #endif /* MILTER */
    641  3544   jbeck 	size_t inplen;
    642  6562   jbeck #if _FFR_BADRCPT_SHUTDOWN
    643  6562   jbeck 	int n_badrcpts_adj;
    644  6562   jbeck #endif /* _FFR_BADRCPT_SHUTDOWN */
    645  3544   jbeck 
    646  3544   jbeck 	SevenBitInput_Saved = SevenBitInput;
    647     0  stevel 	smtp.sm_nrcpts = 0;
    648     0  stevel #if MILTER
    649     0  stevel 	smtp.sm_milterize = (nullserver == NULL);
    650     0  stevel 	smtp.sm_milterlist = false;
    651  3544   jbeck 	addr = NULL;
    652     0  stevel #endif /* MILTER */
    653     0  stevel 
    654     0  stevel 	/* setup I/O fd correctly for the SMTP server */
    655     0  stevel 	setup_smtpd_io();
    656     0  stevel 
    657     0  stevel #if SM_HEAP_CHECK
    658     0  stevel 	if (sm_debug_active(&DebugLeakSmtp, 1))
    659     0  stevel 	{
    660     0  stevel 		sm_heap_newgroup();
    661     0  stevel 		sm_dprintf("smtp() heap group #%d\n", sm_heap_group());
    662     0  stevel 	}
    663     0  stevel #endif /* SM_HEAP_CHECK */
    664     0  stevel 
    665     0  stevel 	/* XXX the rpool should be set when e is initialized in main() */
    666     0  stevel 	e->e_rpool = sm_rpool_new_x(NULL);
    667     0  stevel 	e->e_macro.mac_rpool = e->e_rpool;
    668     0  stevel 
    669     0  stevel 	settime(e);
    670     0  stevel 	sm_getla();
    671     0  stevel 	peerhostname = RealHostName;
    672     0  stevel 	if (peerhostname == NULL)
    673     0  stevel 		peerhostname = "localhost";
    674     0  stevel 	CurHostName = peerhostname;
    675     0  stevel 	CurSmtpClient = macvalue('_', e);
    676     0  stevel 	if (CurSmtpClient == NULL)
    677     0  stevel 		CurSmtpClient = CurHostName;
    678     0  stevel 
    679     0  stevel 	/* check_relay may have set discard bit, save for later */
    680     0  stevel 	smtp.sm_discard = bitset(EF_DISCARD, e->e_flags);
    681     0  stevel 
    682     0  stevel #if PIPELINING
    683     0  stevel 	/* auto-flush output when reading input */
    684     0  stevel 	(void) sm_io_autoflush(InChannel, OutChannel);
    685     0  stevel #endif /* PIPELINING */
    686     0  stevel 
    687     0  stevel 	sm_setproctitle(true, e, "server %s startup", CurSmtpClient);
    688     0  stevel 
    689     0  stevel 	/* Set default features for server. */
    690     0  stevel 	features = ((bitset(PRIV_NOETRN, PrivacyFlags) ||
    691     0  stevel 		     bitnset(D_NOETRN, d_flags)) ? SRV_NONE : SRV_OFFER_ETRN)
    692     0  stevel 		| (bitnset(D_AUTHREQ, d_flags) ? SRV_REQ_AUTH : SRV_NONE)
    693     0  stevel 		| (bitset(PRIV_NOEXPN, PrivacyFlags) ? SRV_NONE
    694     0  stevel 			: (SRV_OFFER_EXPN
    695     0  stevel 			  | (bitset(PRIV_NOVERB, PrivacyFlags)
    696     0  stevel 			     ? SRV_NONE : SRV_OFFER_VERB)))
    697  2197   jbeck 		| ((bitset(PRIV_NORECEIPTS, PrivacyFlags) || !SendMIMEErrors)
    698  2197   jbeck 			 ? SRV_NONE : SRV_OFFER_DSN)
    699     0  stevel #if SASL
    700     0  stevel 		| (bitnset(D_NOAUTH, d_flags) ? SRV_NONE : SRV_OFFER_AUTH)
    701     0  stevel 		| (bitset(SASL_SEC_NOPLAINTEXT, SASLOpts) ? SRV_REQ_SEC
    702     0  stevel 							  : SRV_NONE)
    703     0  stevel #endif /* SASL */
    704     0  stevel #if PIPELINING
    705     0  stevel 		| SRV_OFFER_PIPE
    706     0  stevel #endif /* PIPELINING */
    707     0  stevel #if STARTTLS
    708     0  stevel 		| (bitnset(D_NOTLS, d_flags) ? SRV_NONE : SRV_OFFER_TLS)
    709     0  stevel 		| (bitset(TLS_I_NO_VRFY, TLS_Srv_Opts) ? SRV_NONE
    710     0  stevel 						       : SRV_VRFY_CLT)
    711     0  stevel #endif /* STARTTLS */
    712     0  stevel 		;
    713     0  stevel 	if (nullserver == NULL)
    714     0  stevel 	{
    715     0  stevel 		features = srvfeatures(e, CurSmtpClient, features);
    716     0  stevel 		if (bitset(SRV_TMP_FAIL, features))
    717     0  stevel 		{
    718     0  stevel 			if (LogLevel > 4)
    719     0  stevel 				sm_syslog(LOG_ERR, NOQID,
    720     0  stevel 					  "ERROR: srv_features=tempfail, relay=%.100s, access temporarily disabled",
    721     0  stevel 					  CurSmtpClient);
    722     0  stevel 			nullserver = "450 4.3.0 Please try again later.";
    723     0  stevel 		}
    724     0  stevel 		else
    725     0  stevel 		{
    726     0  stevel #if PIPELINING
    727     0  stevel # if _FFR_NO_PIPE
    728     0  stevel 			if (bitset(SRV_NO_PIPE, features))
    729     0  stevel 			{
    730     0  stevel 				/* for consistency */
    731     0  stevel 				features &= ~SRV_OFFER_PIPE;
    732     0  stevel 			}
    733     0  stevel # endif /* _FFR_NO_PIPE */
    734     0  stevel #endif /* PIPELINING */
    735     0  stevel #if SASL
    736     0  stevel 			if (bitset(SRV_REQ_SEC, features))
    737     0  stevel 				SASLOpts |= SASL_SEC_NOPLAINTEXT;
    738     0  stevel 			else
    739     0  stevel 				SASLOpts &= ~SASL_SEC_NOPLAINTEXT;
    740     0  stevel #endif /* SASL */
    741     0  stevel 		}
    742     0  stevel 	}
    743     0  stevel 	else if (strncmp(nullserver, "421 ", 4) == 0)
    744     0  stevel 	{
    745     0  stevel 		message(nullserver);
    746     0  stevel 		goto doquit;
    747     0  stevel 	}
    748     0  stevel 
    749  3544   jbeck 	e->e_features = features;
    750     0  stevel 	hostname = macvalue('j', e);
    751     0  stevel #if SASL
    752     0  stevel 	if (AuthRealm == NULL)
    753     0  stevel 		AuthRealm = hostname;
    754     0  stevel 	sasl_ok = bitset(SRV_OFFER_AUTH, features);
    755     0  stevel 	n_mechs = 0;
    756     0  stevel 	authenticating = SASL_NOT_AUTH;
    757     0  stevel 
    758     0  stevel 	/* SASL server new connection */
    759     0  stevel 	if (sasl_ok)
    760     0  stevel 	{
    761     0  stevel # if SASL >= 20000
    762     0  stevel 		result = sasl_server_new("smtp", AuthRealm, NULL, NULL, NULL,
    763     0  stevel 					 NULL, 0, &conn);
    764     0  stevel # elif SASL > 10505
    765     0  stevel 		/* use empty realm: only works in SASL > 1.5.5 */
    766     0  stevel 		result = sasl_server_new("smtp", AuthRealm, "", NULL, 0, &conn);
    767     0  stevel # else /* SASL >= 20000 */
    768     0  stevel 		/* use no realm -> realm is set to hostname by SASL lib */
    769     0  stevel 		result = sasl_server_new("smtp", AuthRealm, NULL, NULL, 0,
    770     0  stevel 					 &conn);
    771     0  stevel # endif /* SASL >= 20000 */
    772     0  stevel 		sasl_ok = result == SASL_OK;
    773     0  stevel 		if (!sasl_ok)
    774     0  stevel 		{
    775     0  stevel 			if (LogLevel > 9)
    776     0  stevel 				sm_syslog(LOG_WARNING, NOQID,
    777     0  stevel 					  "AUTH error: sasl_server_new failed=%d",
    778     0  stevel 					  result);
    779     0  stevel 		}
    780     0  stevel 	}
    781     0  stevel 	if (sasl_ok)
    782     0  stevel 	{
    783     0  stevel 		/*
    784     0  stevel 		**  SASL set properties for sasl
    785     0  stevel 		**  set local/remote IP
    786     0  stevel 		**  XXX Cyrus SASL v1 only supports IPv4
    787     0  stevel 		**
    788     0  stevel 		**  XXX where exactly are these used/required?
    789     0  stevel 		**  Kerberos_v4
    790     0  stevel 		*/
    791     0  stevel 
    792     0  stevel # if SASL >= 20000
    793     0  stevel 		localip[0] = remoteip[0] = '\0';
    794     0  stevel #  if NETINET || NETINET6
    795     0  stevel 		in = macvalue(macid("{daemon_family}"), e);
    796     0  stevel 		if (in != NULL && (
    797     0  stevel #   if NETINET6
    798     0  stevel 		    strcmp(in, "inet6") == 0 ||
    799     0  stevel #   endif /* NETINET6 */
    800     0  stevel 		    strcmp(in, "inet") == 0))
    801     0  stevel 		{
    802     0  stevel 			SOCKADDR_LEN_T addrsize;
    803     0  stevel 			SOCKADDR saddr_l;
    804     0  stevel 			SOCKADDR saddr_r;
    805     0  stevel 
    806     0  stevel 			addrsize = sizeof(saddr_r);
    807     0  stevel 			if (getpeername(sm_io_getinfo(InChannel, SM_IO_WHAT_FD,
    808     0  stevel 						      NULL),
    809     0  stevel 					(struct sockaddr *) &saddr_r,
    810     0  stevel 					&addrsize) == 0)
    811     0  stevel 			{
    812     0  stevel 				if (iptostring(&saddr_r, addrsize,
    813  3544   jbeck 					       remoteip, sizeof(remoteip)))
    814     0  stevel 				{
    815     0  stevel 					sasl_setprop(conn, SASL_IPREMOTEPORT,
    816     0  stevel 						     remoteip);
    817     0  stevel 				}
    818     0  stevel 				addrsize = sizeof(saddr_l);
    819     0  stevel 				if (getsockname(sm_io_getinfo(InChannel,
    820     0  stevel 							      SM_IO_WHAT_FD,
    821     0  stevel 							      NULL),
    822     0  stevel 						(struct sockaddr *) &saddr_l,
    823     0  stevel 						&addrsize) == 0)
    824     0  stevel 				{
    825     0  stevel 					if (iptostring(&saddr_l, addrsize,
    826     0  stevel 						       localip,
    827  3544   jbeck 						       sizeof(localip)))
    828     0  stevel 					{
    829     0  stevel 						sasl_setprop(conn,
    830     0  stevel 							     SASL_IPLOCALPORT,
    831     0  stevel 							     localip);
    832     0  stevel 					}
    833     0  stevel 				}
    834     0  stevel 			}
    835     0  stevel 		}
    836     0  stevel #  endif /* NETINET || NETINET6 */
    837     0  stevel # else /* SASL >= 20000 */
    838     0  stevel #  if NETINET
    839     0  stevel 		in = macvalue(macid("{daemon_family}"), e);
    840     0  stevel 		if (in != NULL && strcmp(in, "inet") == 0)
    841     0  stevel 		{
    842     0  stevel 			SOCKADDR_LEN_T addrsize;
    843     0  stevel 
    844     0  stevel 			addrsize = sizeof(struct sockaddr_in);
    845     0  stevel 			if (getpeername(sm_io_getinfo(InChannel, SM_IO_WHAT_FD,
    846     0  stevel 						      NULL),
    847     0  stevel 					(struct sockaddr *)&saddr_r,
    848     0  stevel 					&addrsize) == 0)
    849     0  stevel 			{
    850     0  stevel 				sasl_setprop(conn, SASL_IP_REMOTE, &saddr_r);
    851     0  stevel 				addrsize = sizeof(struct sockaddr_in);
    852     0  stevel 				if (getsockname(sm_io_getinfo(InChannel,
    853     0  stevel 							      SM_IO_WHAT_FD,
    854     0  stevel 							      NULL),
    855     0  stevel 						(struct sockaddr *)&saddr_l,
    856     0  stevel 						&addrsize) == 0)
    857     0  stevel 					sasl_setprop(conn, SASL_IP_LOCAL,
    858     0  stevel 						     &saddr_l);
    859     0  stevel 			}
    860     0  stevel 		}
    861     0  stevel #  endif /* NETINET */
    862     0  stevel # endif /* SASL >= 20000 */
    863     0  stevel 
    864     0  stevel 		auth_type = NULL;
    865     0  stevel 		mechlist = NULL;
    866     0  stevel 		user = NULL;
    867     0  stevel # if 0
    868     0  stevel 		macdefine(&BlankEnvelope.e_macro, A_PERM,
    869     0  stevel 			macid("{auth_author}"), NULL);
    870     0  stevel # endif /* 0 */
    871     0  stevel 
    872     0  stevel 		/* set properties */
    873  3544   jbeck 		(void) memset(&ssp, '\0', sizeof(ssp));
    874     0  stevel 
    875     0  stevel 		/* XXX should these be options settable via .cf ? */
    876     0  stevel 		/* ssp.min_ssf = 0; is default due to memset() */
    877     0  stevel 		{
    878     0  stevel 			ssp.max_ssf = MaxSLBits;
    879     0  stevel 			ssp.maxbufsize = MAXOUTLEN;
    880     0  stevel 		}
    881     0  stevel 		ssp.security_flags = SASLOpts & SASL_SEC_MASK;
    882     0  stevel 		sasl_ok = sasl_setprop(conn, SASL_SEC_PROPS, &ssp) == SASL_OK;
    883     0  stevel 
    884     0  stevel 		if (sasl_ok)
    885     0  stevel 		{
    886     0  stevel 			/*
    887     0  stevel 			**  external security strength factor;
    888     0  stevel 			**	currently we have none so zero
    889     0  stevel 			*/
    890     0  stevel 
    891     0  stevel # if SASL >= 20000
    892     0  stevel 			ext_ssf = 0;
    893     0  stevel 			auth_id = NULL;
    894     0  stevel 			sasl_ok = ((sasl_setprop(conn, SASL_SSF_EXTERNAL,
    895     0  stevel 						 &ext_ssf) == SASL_OK) &&
    896     0  stevel 				   (sasl_setprop(conn, SASL_AUTH_EXTERNAL,
    897     0  stevel 						 auth_id) == SASL_OK));
    898     0  stevel # else /* SASL >= 20000 */
    899     0  stevel 			ext_ssf.ssf = 0;
    900     0  stevel 			ext_ssf.auth_id = NULL;
    901     0  stevel 			sasl_ok = sasl_setprop(conn, SASL_SSF_EXTERNAL,
    902     0  stevel 					       &ext_ssf) == SASL_OK;
    903     0  stevel # endif /* SASL >= 20000 */
    904     0  stevel 		}
    905     0  stevel 		if (sasl_ok)
    906     0  stevel 			n_mechs = saslmechs(conn, &mechlist);
    907     0  stevel 	}
    908     0  stevel #endif /* SASL */
    909     0  stevel 
    910     0  stevel #if STARTTLS
    911  6562   jbeck 
    912  6562   jbeck 	set_tls_rd_tmo(TimeOuts.to_nextcommand);
    913     0  stevel #endif /* STARTTLS */
    914     0  stevel 
    915     0  stevel #if MILTER
    916     0  stevel 	if (smtp.sm_milterize)
    917     0  stevel 	{
    918     0  stevel 		char state;
    919     0  stevel 
    920     0  stevel 		/* initialize mail filter connection */
    921  5402   jbeck 		smtp.sm_milterlist = milter_init(e, &state, &smtp.sm_milters);
    922     0  stevel 		switch (state)
    923     0  stevel 		{
    924     0  stevel 		  case SMFIR_REJECT:
    925     0  stevel 			if (MilterLogLevel > 3)
    926     0  stevel 				sm_syslog(LOG_INFO, e->e_id,
    927     0  stevel 					  "Milter: initialization failed, rejecting commands");
    928     0  stevel 			greetcode = "554";
    929     0  stevel 			nullserver = "Command rejected";
    930     0  stevel 			smtp.sm_milterize = false;
    931     0  stevel 			break;
    932     0  stevel 
    933     0  stevel 		  case SMFIR_TEMPFAIL:
    934     0  stevel 			if (MilterLogLevel > 3)
    935     0  stevel 				sm_syslog(LOG_INFO, e->e_id,
    936     0  stevel 					  "Milter: initialization failed, temp failing commands");
    937     0  stevel 			tempfail = true;
    938     0  stevel 			smtp.sm_milterize = false;
    939     0  stevel 			break;
    940  1658   jbeck 
    941  1658   jbeck 		  case SMFIR_SHUTDOWN:
    942  1658   jbeck 			if (MilterLogLevel > 3)
    943  1658   jbeck 				sm_syslog(LOG_INFO, e->e_id,
    944  1658   jbeck 					  "Milter: initialization failed, closing connection");
    945  1658   jbeck 			tempfail = true;
    946  1658   jbeck 			smtp.sm_milterize = false;
    947  1658   jbeck 			message("421 4.7.0 %s closing connection",
    948  1658   jbeck 					MyHostName);
    949  1658   jbeck 
    950  1658   jbeck 			/* arrange to ignore send list */
    951  1658   jbeck 			e->e_sendqueue = NULL;
    952  6562   jbeck 			lognullconnection = false;
    953  1658   jbeck 			goto doquit;
    954     0  stevel 		}
    955     0  stevel 	}
    956     0  stevel 
    957     0  stevel 	if (smtp.sm_milterlist && smtp.sm_milterize &&
    958     0  stevel 	    !bitset(EF_DISCARD, e->e_flags))
    959     0  stevel 	{
    960     0  stevel 		char state;
    961     0  stevel 		char *response;
    962     0  stevel 
    963  2526   jbeck 		q = macvalue(macid("{client_name}"), e);
    964  3544   jbeck 		SM_ASSERT(q != NULL || OpMode == MD_SMTP);
    965  3544   jbeck 		if (q == NULL)
    966  3544   jbeck 			q = "localhost";
    967  2526   jbeck 		response = milter_connect(q, RealHostAddr, e, &state);
    968     0  stevel 		switch (state)
    969     0  stevel 		{
    970     0  stevel 		  case SMFIR_REPLYCODE:	/* REPLYCODE shouldn't happen */
    971     0  stevel 		  case SMFIR_REJECT:
    972     0  stevel 			if (MilterLogLevel > 3)
    973     0  stevel 				sm_syslog(LOG_INFO, e->e_id,
    974     0  stevel 					  "Milter: connect: host=%s, addr=%s, rejecting commands",
    975     0  stevel 					  peerhostname,
    976     0  stevel 					  anynet_ntoa(&RealHostAddr));
    977     0  stevel 			greetcode = "554";
    978     0  stevel 			nullserver = "Command rejected";
    979     0  stevel 			smtp.sm_milterize = false;
    980     0  stevel 			break;
    981     0  stevel 
    982     0  stevel 		  case SMFIR_TEMPFAIL:
    983     0  stevel 			if (MilterLogLevel > 3)
    984     0  stevel 				sm_syslog(LOG_INFO, e->e_id,
    985     0  stevel 					  "Milter: connect: host=%s, addr=%s, temp failing commands",
    986     0  stevel 					  peerhostname,
    987     0  stevel 					  anynet_ntoa(&RealHostAddr));
    988     0  stevel 			tempfail = true;
    989     0  stevel 			smtp.sm_milterize = false;
    990     0  stevel 			break;
    991     0  stevel 
    992     0  stevel 		  case SMFIR_SHUTDOWN:
    993     0  stevel 			if (MilterLogLevel > 3)
    994     0  stevel 				sm_syslog(LOG_INFO, e->e_id,
    995     0  stevel 					  "Milter: connect: host=%s, addr=%s, shutdown",
    996     0  stevel 					  peerhostname,
    997     0  stevel 					  anynet_ntoa(&RealHostAddr));
    998     0  stevel 			tempfail = true;
    999     0  stevel 			smtp.sm_milterize = false;
   1000     0  stevel 			message("421 4.7.0 %s closing connection",
   1001     0  stevel 					MyHostName);
   1002     0  stevel 
   1003     0  stevel 			/* arrange to ignore send list */
   1004     0  stevel 			e->e_sendqueue = NULL;
   1005     0  stevel 			goto doquit;
   1006     0  stevel 		}
   1007     0  stevel 		if (response != NULL)
   1008     0  stevel 			sm_free(response); /* XXX */
   1009     0  stevel 	}
   1010     0  stevel #endif /* MILTER */
   1011     0  stevel 
   1012     0  stevel 	/*
   1013     0  stevel 	**  Broken proxies and SMTP slammers
   1014     0  stevel 	**  push data without waiting, catch them
   1015     0  stevel 	*/
   1016     0  stevel 
   1017     0  stevel 	if (
   1018     0  stevel #if STARTTLS
   1019     0  stevel 	    !smtps &&
   1020     0  stevel #endif /* STARTTLS */
   1021  3544   jbeck 	    *greetcode == '2' && nullserver == NULL)
   1022     0  stevel 	{
   1023     0  stevel 		time_t msecs = 0;
   1024     0  stevel 		char **pvp;
   1025     0  stevel 		char pvpbuf[PSBUFSIZE];
   1026     0  stevel 
   1027     0  stevel 		/* Ask the rulesets how long to pause */
   1028     0  stevel 		pvp = NULL;
   1029     0  stevel 		r = rscap("greet_pause", peerhostname,
   1030     0  stevel 			  anynet_ntoa(&RealHostAddr), e,
   1031     0  stevel 			  &pvp, pvpbuf, sizeof(pvpbuf));
   1032     0  stevel 		if (r == EX_OK && pvp != NULL && pvp[0] != NULL &&
   1033     0  stevel 		    (pvp[0][0] & 0377) == CANONNET && pvp[1] != NULL)
   1034     0  stevel 		{
   1035     0  stevel 			msecs = strtol(pvp[1], NULL, 10);
   1036     0  stevel 		}
   1037     0  stevel 
   1038     0  stevel 		if (msecs > 0)
   1039     0  stevel 		{
   1040     0  stevel 			int fd;
   1041     0  stevel 			fd_set readfds;
   1042     0  stevel 			struct timeval timeout;
   1043   616   jbeck 			struct timeval bp, ep, tp; /* {begin,end,total}pause */
   1044  3544   jbeck 			int eoftest;
   1045     0  stevel 
   1046     0  stevel 			/* pause for a moment */
   1047     0  stevel 			timeout.tv_sec = msecs / 1000;
   1048     0  stevel 			timeout.tv_usec = (msecs % 1000) * 1000;
   1049     0  stevel 
   1050     0  stevel 			/* Obey RFC 2821: 4.3.5.2: 220 timeout of 5 minutes */
   1051     0  stevel 			if (timeout.tv_sec >= 300)
   1052     0  stevel 			{
   1053     0  stevel 				timeout.tv_sec = 300;
   1054     0  stevel 				timeout.tv_usec = 0;
   1055     0  stevel 			}
   1056     0  stevel 
   1057     0  stevel 			/* check if data is on the socket during the pause */
   1058     0  stevel 			fd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL);
   1059     0  stevel 			FD_ZERO(&readfds);
   1060     0  stevel 			SM_FD_SET(fd, &readfds);
   1061   616   jbeck 			gettimeofday(&bp, NULL);
   1062     0  stevel 			if (select(fd + 1, FDSET_CAST &readfds,
   1063     0  stevel 			    NULL, NULL, &timeout) > 0 &&
   1064  3544   jbeck 			    FD_ISSET(fd, &readfds) &&
   1065  6562   jbeck 			    (eoftest = sm_io_getc(InChannel, SM_TIME_DEFAULT))
   1066  3544   jbeck 			    != SM_IO_EOF)
   1067  3544   jbeck 			{
   1068  6562   jbeck 				sm_io_ungetc(InChannel, SM_TIME_DEFAULT,
   1069  3544   jbeck 					     eoftest);
   1070   616   jbeck 				gettimeofday(&ep, NULL);
   1071   616   jbeck 				timersub(&ep, &bp, &tp);
   1072     0  stevel 				greetcode = "554";
   1073     0  stevel 				nullserver = "Command rejected";
   1074     0  stevel 				sm_syslog(LOG_INFO, e->e_id,
   1075  3544   jbeck 					  "rejecting commands from %s [%s] due to pre-greeting traffic after %d seconds",
   1076     0  stevel 					  peerhostname,
   1077  3544   jbeck 					  anynet_ntoa(&RealHostAddr),
   1078  3544   jbeck 					  (int) tp.tv_sec +
   1079   616   jbeck 						(tp.tv_usec >= 500000 ? 1 : 0)
   1080   616   jbeck 					 );
   1081     0  stevel 			}
   1082     0  stevel 		}
   1083     0  stevel 	}
   1084     0  stevel 
   1085     0  stevel #if STARTTLS
   1086     0  stevel 	/* If this an smtps connection, start TLS now */
   1087     0  stevel 	if (smtps)
   1088     0  stevel 	{
   1089     0  stevel 		Errors = 0;
   1090     0  stevel 		goto starttls;
   1091     0  stevel 	}
   1092     0  stevel 
   1093     0  stevel   greeting:
   1094     0  stevel 
   1095     0  stevel #endif /* STARTTLS */
   1096     0  stevel 
   1097     0  stevel 	/* output the first line, inserting "ESMTP" as second word */
   1098     0  stevel 	if (*greetcode == '5')
   1099  3544   jbeck 		(void) sm_snprintf(inp, sizeof(inp),
   1100  3544   jbeck 				"%s not accepting messages", hostname);
   1101  3544   jbeck 	else
   1102  3544   jbeck 		expand(SmtpGreeting, inp, sizeof(inp), e);
   1103     0  stevel 
   1104     0  stevel 	p = strchr(inp, '\n');
   1105     0  stevel 	if (p != NULL)
   1106     0  stevel 		*p++ = '\0';
   1107     0  stevel 	id = strchr(inp, ' ');
   1108     0  stevel 	if (id == NULL)
   1109     0  stevel 		id = &inp[strlen(inp)];
   1110     0  stevel 	if (p == NULL)
   1111  3544   jbeck 		(void) sm_snprintf(cmdbuf, sizeof(cmdbuf),
   1112     0  stevel 			 "%s %%.*s ESMTP%%s", greetcode);
   1113     0  stevel 	else
   1114  3544   jbeck 		(void) sm_snprintf(cmdbuf, sizeof(cmdbuf),
   1115     0  stevel 			 "%s-%%.*s ESMTP%%s", greetcode);
   1116     0  stevel 	message(cmdbuf, (int) (id - inp), inp, id);
   1117     0  stevel 
   1118     0  stevel 	/* output remaining lines */
   1119     0  stevel 	while ((id = p) != NULL && (p = strchr(id, '\n')) != NULL)
   1120     0  stevel 	{
   1121     0  stevel 		*p++ = '\0';
   1122     0  stevel 		if (isascii(*id) && isspace(*id))
   1123     0  stevel 			id++;
   1124  3544   jbeck 		(void) sm_strlcpyn(cmdbuf, sizeof(cmdbuf), 2, greetcode, "-%s");
   1125     0  stevel 		message(cmdbuf, id);
   1126     0  stevel 	}
   1127     0  stevel 	if (id != NULL)
   1128     0  stevel 	{
   1129     0  stevel 		if (isascii(*id) && isspace(*id))
   1130     0  stevel 			id++;
   1131  3544   jbeck 		(void) sm_strlcpyn(cmdbuf, sizeof(cmdbuf), 2, greetcode, " %s");
   1132     0  stevel 		message(cmdbuf, id);
   1133     0  stevel 	}
   1134     0  stevel 
   1135     0  stevel 	protocol = NULL;
   1136     0  stevel 	sendinghost = macvalue('s', e);
   1137     0  stevel 
   1138     0  stevel 	/* If quarantining by a connect/ehlo action, save between messages */
   1139     0  stevel 	if (e->e_quarmsg == NULL)
   1140     0  stevel 		smtp.sm_quarmsg = NULL;
   1141     0  stevel 	else
   1142     0  stevel 		smtp.sm_quarmsg = newstr(e->e_quarmsg);
   1143     0  stevel 
   1144     0  stevel 	/* sendinghost's storage must outlive the current envelope */
   1145     0  stevel 	if (sendinghost != NULL)
   1146     0  stevel 		sendinghost = sm_strdup_x(sendinghost);
   1147     0  stevel 	first = true;
   1148     0  stevel 	gothello = false;
   1149     0  stevel 	smtp.sm_gotmail = false;
   1150     0  stevel 	for (;;)
   1151     0  stevel 	{
   1152     0  stevel 	    SM_TRY
   1153     0  stevel 	    {
   1154     0  stevel 		QuickAbort = false;
   1155     0  stevel 		HoldErrs = false;
   1156     0  stevel 		SuprErrs = false;
   1157     0  stevel 		LogUsrErrs = false;
   1158     0  stevel 		OnlyOneError = true;
   1159     0  stevel 		e->e_flags &= ~(EF_VRFYONLY|EF_GLOBALERRS);
   1160  3966   jbeck #if MILTER
   1161  3966   jbeck 		milter_cmd_fail = false;
   1162  3966   jbeck #endif /* MILTER */
   1163     0  stevel 
   1164     0  stevel 		/* setup for the read */
   1165     0  stevel 		e->e_to = NULL;
   1166     0  stevel 		Errors = 0;
   1167     0  stevel 		FileName = NULL;
   1168     0  stevel 		(void) sm_io_flush(smioout, SM_TIME_DEFAULT);
   1169     0  stevel 
   1170     0  stevel 		/* read the input line */
   1171     0  stevel 		SmtpPhase = "server cmd read";
   1172     0  stevel 		sm_setproctitle(true, e, "server %s cmd read", CurSmtpClient);
   1173     0  stevel 
   1174     0  stevel 		/* handle errors */
   1175     0  stevel 		if (sm_io_error(OutChannel) ||
   1176  3544   jbeck 		    (p = sfgets(inp, sizeof(inp), InChannel,
   1177     0  stevel 				TimeOuts.to_nextcommand, SmtpPhase)) == NULL)
   1178     0  stevel 		{
   1179     0  stevel 			char *d;
   1180     0  stevel 
   1181     0  stevel 			d = macvalue(macid("{daemon_name}"), e);
   1182     0  stevel 			if (d == NULL)
   1183     0  stevel 				d = "stdin";
   1184     0  stevel 			/* end of file, just die */
   1185     0  stevel 			disconnect(1, e);
   1186     0  stevel 
   1187     0  stevel #if MILTER
   1188     0  stevel 			/* close out milter filters */
   1189     0  stevel 			milter_quit(e);
   1190     0  stevel #endif /* MILTER */
   1191     0  stevel 
   1192     0  stevel 			message("421 4.4.1 %s Lost input channel from %s",
   1193     0  stevel 				MyHostName, CurSmtpClient);
   1194     0  stevel 			if (LogLevel > (smtp.sm_gotmail ? 1 : 19))
   1195     0  stevel 				sm_syslog(LOG_NOTICE, e->e_id,
   1196     0  stevel 					  "lost input channel from %s to %s after %s",
   1197     0  stevel 					  CurSmtpClient, d,
   1198     0  stevel 					  (c == NULL || c->cmd_name == NULL) ? "startup" : c->cmd_name);
   1199     0  stevel 			/*
   1200     0  stevel 			**  If have not accepted mail (DATA), do not bounce
   1201     0  stevel 			**  bad addresses back to sender.
   1202     0  stevel 			*/
   1203     0  stevel 
   1204     0  stevel 			if (bitset(EF_CLRQUEUE, e->e_flags))
   1205     0  stevel 				e->e_sendqueue = NULL;
   1206     0  stevel 			goto doquit;
   1207     0  stevel 		}
   1208     0  stevel 
   1209  3544   jbeck 		/* also used by "proxy" check below */
   1210  3544   jbeck 		inplen = strlen(inp);
   1211  3544   jbeck #if SASL
   1212  3544   jbeck 		/*
   1213  3544   jbeck 		**  SMTP AUTH requires accepting any length,
   1214  3544   jbeck 		**  at least for challenge/response. However, not imposing
   1215  3544   jbeck 		**  a limit is a bad idea (denial of service).
   1216  3544   jbeck 		*/
   1217  3544   jbeck 
   1218  3544   jbeck 		if (authenticating != SASL_PROC_AUTH
   1219  3544   jbeck 		    && sm_strncasecmp(inp, "AUTH ", 5) != 0
   1220  3544   jbeck 		    && inplen > MAXLINE)
   1221  3544   jbeck 		{
   1222  3544   jbeck 			message("421 4.7.0 %s Command too long, possible attack %s",
   1223  3544   jbeck 				MyHostName, CurSmtpClient);
   1224  3544   jbeck 			sm_syslog(LOG_INFO, e->e_id,
   1225  3544   jbeck 				  "%s: SMTP violation, input too long: %lu",
   1226  3544   jbeck 				  CurSmtpClient, (unsigned long) inplen);
   1227  3544   jbeck 			goto doquit;
   1228  3544   jbeck 		}
   1229  3544   jbeck #endif /* SASL */
   1230  3544   jbeck 
   1231     0  stevel 		if (first)
   1232     0  stevel 		{
   1233  3544   jbeck 			size_t cmdlen;
   1234     0  stevel 			int idx;
   1235     0  stevel 			char *http_cmd;
   1236     0  stevel 			static char *http_cmds[] = { "GET", "POST",
   1237     0  stevel 						     "CONNECT", "USER", NULL };
   1238     0  stevel 
   1239     0  stevel 			for (idx = 0; (http_cmd = http_cmds[idx]) != NULL;
   1240     0  stevel 			     idx++)
   1241     0  stevel 			{
   1242     0  stevel 				cmdlen = strlen(http_cmd);
   1243     0  stevel 				if (cmdlen < inplen &&
   1244     0  stevel 				    sm_strncasecmp(inp, http_cmd, cmdlen) == 0 &&
   1245     0  stevel 				    isascii(inp[cmdlen]) && isspace(inp[cmdlen]))
   1246     0  stevel 				{
   1247     0  stevel 					/* Open proxy, drop it */
   1248     0  stevel 					message("421 4.7.0 %s Rejecting open proxy %s",
   1249     0  stevel 						MyHostName, CurSmtpClient);
   1250     0  stevel 					sm_syslog(LOG_INFO, e->e_id,
   1251     0  stevel 						  "%s: probable open proxy: command=%.40s",
   1252     0  stevel 						  CurSmtpClient, inp);
   1253     0  stevel 					goto doquit;
   1254     0  stevel 				}
   1255     0  stevel 			}
   1256     0  stevel 			first = false;
   1257     0  stevel 		}
   1258     0  stevel 
   1259     0  stevel 		/* clean up end of line */
   1260     0  stevel 		fixcrlf(inp, true);
   1261     0  stevel 
   1262     0  stevel #if PIPELINING
   1263     0  stevel # if _FFR_NO_PIPE
   1264     0  stevel 		/*
   1265     0  stevel 		**  if there is more input and pipelining is disabled:
   1266     0  stevel 		**	delay ... (and maybe discard the input?)
   1267     0  stevel 		**  XXX this doesn't really work, at least in tests using
   1268     0  stevel 		**  telnet SM_IO_IS_READABLE only returns 1 if there were
   1269     0  stevel 		**  more than 2 input lines available.
   1270     0  stevel 		*/
   1271     0  stevel 
   1272     0  stevel 		if (bitset(SRV_NO_PIPE, features) &&
   1273     0  stevel 		    sm_io_getinfo(InChannel, SM_IO_IS_READABLE, NULL) > 0)
   1274     0  stevel 		{
   1275     0  stevel 			if (++np_log < 3)
   1276     0  stevel 				sm_syslog(LOG_INFO, NOQID,
   1277     0  stevel 					  "unauthorized PIPELINING, sleeping");
   1278     0  stevel 			sleep(1);
   1279     0  stevel 		}
   1280     0  stevel 
   1281     0  stevel # endif /* _FFR_NO_PIPE */
   1282     0  stevel #endif /* PIPELINING */
   1283     0  stevel 
   1284     0  stevel #if SASL
   1285     0  stevel 		if (authenticating == SASL_PROC_AUTH)
   1286     0  stevel 		{
   1287     0  stevel # if 0
   1288     0  stevel 			if (*inp == '\0')
   1289     0  stevel 			{
   1290     0  stevel 				authenticating = SASL_NOT_AUTH;
   1291     0  stevel 				message("501 5.5.2 missing input");
   1292     0  stevel 				RESET_SASLCONN;
   1293     0  stevel 				continue;
   1294     0  stevel 			}
   1295     0  stevel # endif /* 0 */
   1296     0  stevel 			if (*inp == '*' && *(inp + 1) == '\0')
   1297     0  stevel 			{
   1298     0  stevel 				authenticating = SASL_NOT_AUTH;
   1299     0  stevel 
   1300  5402   jbeck 				/* RFC 2554 4. */
   1301     0  stevel 				message("501 5.0.0 AUTH aborted");
   1302     0  stevel 				RESET_SASLCONN;
   1303     0  stevel 				continue;
   1304     0  stevel 			}
   1305     0  stevel 
   1306     0  stevel 			/* could this be shorter? XXX */
   1307     0  stevel # if SASL >= 20000
   1308     0  stevel 			in = xalloc(strlen(inp) + 1);
   1309     0  stevel 			result = sasl_decode64(inp, strlen(inp), in,
   1310     0  stevel 					       strlen(inp), &inlen);
   1311     0  stevel # else /* SASL >= 20000 */
   1312     0  stevel 			out = xalloc(strlen(inp));
   1313     0  stevel 			result = sasl_decode64(inp, strlen(inp), out, &outlen);
   1314     0  stevel # endif /* SASL >= 20000 */
   1315     0  stevel 			if (result != SASL_OK)
   1316     0  stevel 			{
   1317     0  stevel 				authenticating = SASL_NOT_AUTH;
   1318     0  stevel 
   1319  5402   jbeck 				/* RFC 2554 4. */
   1320     0  stevel 				message("501 5.5.4 cannot decode AUTH parameter %s",
   1321     0  stevel 					inp);
   1322     0  stevel # if SASL >= 20000
   1323     0  stevel 				sm_free(in);
   1324     0  stevel # endif /* SASL >= 20000 */
   1325     0  stevel 				RESET_SASLCONN;
   1326     0  stevel 				continue;
   1327     0  stevel 			}
   1328     0  stevel 
   1329     0  stevel # if SASL >= 20000
   1330     0  stevel 			result = sasl_server_step(conn,	in, inlen,
   1331     0  stevel 						  &out, &outlen);
   1332     0  stevel 			sm_free(in);
   1333     0  stevel # else /* SASL >= 20000 */
   1334     0  stevel 			result = sasl_server_step(conn,	out, outlen,
   1335     0  stevel 						  &out, &outlen, &errstr);
   1336     0  stevel # endif /* SASL >= 20000 */
   1337     0  stevel 
   1338     0  stevel 			/* get an OK if we're done */
   1339     0  stevel 			if (result == SASL_OK)
   1340     0  stevel 			{
   1341     0  stevel   authenticated:
   1342     0  stevel 				message("235 2.0.0 OK Authenticated");
   1343     0  stevel 				authenticating = SASL_IS_AUTH;
   1344     0  stevel 				macdefine(&BlankEnvelope.e_macro, A_TEMP,
   1345     0  stevel 					macid("{auth_type}"), auth_type);
   1346     0  stevel 
   1347     0  stevel # if SASL >= 20000
   1348     0  stevel 				user = macvalue(macid("{auth_authen}"), e);
   1349     0  stevel 
   1350     0  stevel 				/* get security strength (features) */
   1351     0  stevel 				result = sasl_getprop(conn, SASL_SSF,
   1352     0  stevel 						      (const void **) &ssf);
   1353     0  stevel # else /* SASL >= 20000 */
   1354     0  stevel 				result = sasl_getprop(conn, SASL_USERNAME,
   1355     0  stevel 						      (void **)&user);
   1356     0  stevel 				if (result != SASL_OK)
   1357     0  stevel 				{
   1358     0  stevel 					user = "";
   1359     0  stevel 					macdefine(&BlankEnvelope.e_macro,
   1360     0  stevel 						  A_PERM,
   1361     0  stevel 						  macid("{auth_authen}"), NULL);
   1362     0  stevel 				}
   1363     0  stevel 				else
   1364     0  stevel 				{
   1365     0  stevel 					macdefine(&BlankEnvelope.e_macro,
   1366     0  stevel 						  A_TEMP,
   1367     0  stevel 						  macid("{auth_authen}"),
   1368     0  stevel 						  xtextify(user, "<>\")"));
   1369     0  stevel 				}
   1370     0  stevel 
   1371     0  stevel # if 0
   1372     0  stevel 				/* get realm? */
   1373     0  stevel 				sasl_getprop(conn, SASL_REALM, (void **) &data);
   1374     0  stevel # endif /* 0 */
   1375     0  stevel 
   1376     0  stevel 				/* get security strength (features) */
   1377     0  stevel 				result = sasl_getprop(conn, SASL_SSF,
   1378     0  stevel 						      (void **) &ssf);
   1379     0  stevel # endif /* SASL >= 20000 */
   1380     0  stevel 				if (result != SASL_OK)
   1381     0  stevel 				{
   1382     0  stevel 					macdefine(&BlankEnvelope.e_macro,
   1383     0  stevel 						  A_PERM,
   1384     0  stevel 						  macid("{auth_ssf}"), "0");
   1385     0  stevel 					ssf = NULL;
   1386     0  stevel 				}
   1387     0  stevel 				else
   1388     0  stevel 				{
   1389     0  stevel 					char pbuf[8];
   1390     0  stevel 
   1391  3544   jbeck 					(void) sm_snprintf(pbuf, sizeof(pbuf),
   1392     0  stevel 							   "%u", *ssf);
   1393     0  stevel 					macdefine(&BlankEnvelope.e_macro,
   1394     0  stevel 						  A_TEMP,
   1395     0  stevel 						  macid("{auth_ssf}"), pbuf);
   1396     0  stevel 					if (tTd(95, 8))
   1397     0  stevel 						sm_dprintf("AUTH auth_ssf: %u\n",
   1398     0  stevel 							   *ssf);
   1399     0  stevel 				}
   1400     0  stevel 
   1401     0  stevel 				/*
   1402     0  stevel 				**  Only switch to encrypted connection
   1403     0  stevel 				**  if a security layer has been negotiated
   1404     0  stevel 				*/
   1405     0  stevel 
   1406     0  stevel 				if (ssf != NULL && *ssf > 0)
   1407     0  stevel 				{
   1408  2197   jbeck 					int tmo;
   1409  2197   jbeck 
   1410     0  stevel 					/*
   1411     0  stevel 					**  Convert I/O layer to use SASL.
   1412     0  stevel 					**  If the call fails, the connection
   1413     0  stevel 					**  is aborted.
   1414     0  stevel 					*/
   1415     0  stevel 
   1416  2197   jbeck 					tmo = TimeOuts.to_datablock * 1000;
   1417     0  stevel 					if (sfdcsasl(&InChannel, &OutChannel,
   1418  2197   jbeck 						     conn, tmo) == 0)
   1419     0  stevel 					{
   1420     0  stevel 						/* restart dialogue */
   1421     0  stevel 						n_helo = 0;
   1422     0  stevel # if PIPELINING
   1423     0  stevel 						(void) sm_io_autoflush(InChannel,
   1424     0  stevel 								       OutChannel);
   1425     0  stevel # endif /* PIPELINING */
   1426     0  stevel 					}
   1427     0  stevel 					else
   1428     0  stevel 						syserr("503 5.3.3 SASL TLS failed");
   1429     0  stevel 				}
   1430     0  stevel 
   1431     0  stevel 				/* NULL pointer ok since it's our function */
   1432     0  stevel 				if (LogLevel > 8)
   1433     0  stevel 					sm_syslog(LOG_INFO, NOQID,
   1434     0  stevel 						  "AUTH=server, relay=%s, authid=%.128s, mech=%.16s, bits=%d",
   1435     0  stevel 						  CurSmtpClient,
   1436     0  stevel 						  shortenstring(user, 128),
   1437     0  stevel 						  auth_type, *ssf);
   1438     0  stevel 			}
   1439     0  stevel 			else if (result == SASL_CONTINUE)
   1440     0  stevel 			{
   1441     0  stevel 				len = ENC64LEN(outlen);
   1442     0  stevel 				out2 = xalloc(len);
   1443     0  stevel 				result = sasl_encode64(out, outlen, out2, len,
   1444     0  stevel 						       &out2len);
   1445     0  stevel 				if (result != SASL_OK)
   1446     0  stevel 				{
   1447     0  stevel 					/* correct code? XXX */
   1448     0  stevel 					/* 454 Temp. authentication failure */
   1449     0  stevel 					message("454 4.5.4 Internal error: unable to encode64");
   1450     0  stevel 					if (LogLevel > 5)
   1451     0  stevel 						sm_syslog(LOG_WARNING, e->e_id,
   1452     0  stevel 							  "AUTH encode64 error [%d for \"%s\"]",
   1453     0  stevel 							  result, out);
   1454     0  stevel 					/* start over? */
   1455     0  stevel 					authenticating = SASL_NOT_AUTH;
   1456     0  stevel 				}
   1457     0  stevel 				else
   1458     0  stevel 				{
   1459     0  stevel 					message("334 %s", out2);
   1460     0  stevel 					if (tTd(95, 2))
   1461     0  stevel 						sm_dprintf("AUTH continue: msg='%s' len=%u\n",
   1462     0  stevel 							   out2, out2len);
   1463     0  stevel 				}
   1464     0  stevel # if SASL >= 20000
   1465     0  stevel 				sm_free(out2);
   1466     0  stevel # endif /* SASL >= 20000 */
   1467     0  stevel 			}
   1468     0  stevel 			else
   1469     0  stevel 			{
   1470     0  stevel 				/* not SASL_OK or SASL_CONT */
   1471     0  stevel 				message("535 5.7.0 authentication failed");
   1472     0  stevel 				if (LogLevel > 9)
   1473     0  stevel 					sm_syslog(LOG_WARNING, e->e_id,
   1474     0  stevel 						  "AUTH failure (%s): %s (%d) %s",
   1475     0  stevel 						  auth_type,
   1476     0  stevel 						  sasl_errstring(result, NULL,
   1477     0  stevel 								 NULL),
   1478     0  stevel 						  result,
   1479     0  stevel # if SASL >= 20000
   1480     0  stevel 						  sasl_errdetail(conn));
   1481     0  stevel # else /* SASL >= 20000 */
   1482     0  stevel 						  errstr == NULL ? "" : errstr);
   1483     0  stevel # endif /* SASL >= 20000 */
   1484     0  stevel 				RESET_SASLCONN;
   1485     0  stevel 				authenticating = SASL_NOT_AUTH;
   1486     0  stevel 			}
   1487     0  stevel 		}
   1488     0  stevel 		else
   1489     0  stevel 		{
   1490     0  stevel 			/* don't want to do any of this if authenticating */
   1491     0  stevel #endif /* SASL */
   1492     0  stevel 
   1493     0  stevel 		/* echo command to transcript */
   1494     0  stevel 		if (e->e_xfp != NULL)
   1495     0  stevel 			(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
   1496     0  stevel 					     "<<< %s\n", inp);
   1497     0  stevel 
   1498     0  stevel 		if (LogLevel > 14)
   1499     0  stevel 			sm_syslog(LOG_INFO, e->e_id, "<-- %s", inp);
   1500     0  stevel 
   1501     0  stevel 		/* break off command */
   1502     0  stevel 		for (p = inp; isascii(*p) && isspace(*p); p++)
   1503     0  stevel 			continue;
   1504     0  stevel 		cmd = cmdbuf;
   1505     0  stevel 		while (*p != '\0' &&
   1506     0  stevel 		       !(isascii(*p) && isspace(*p)) &&
   1507  3544   jbeck 		       cmd < &cmdbuf[sizeof(cmdbuf) - 2])
   1508     0  stevel 			*cmd++ = *p++;
   1509     0  stevel 		*cmd = '\0';
   1510     0  stevel 
   1511     0  stevel 		/* throw away leading whitespace */
   1512     0  stevel 		SKIP_SPACE(p);
   1513     0  stevel 
   1514     0  stevel 		/* decode command */
   1515     0  stevel 		for (c = CmdTab; c->cmd_name != NULL; c++)
   1516     0  stevel 		{
   1517     0  stevel 			if (sm_strcasecmp(c->cmd_name, cmdbuf) == 0)
   1518     0  stevel 				break;
   1519     0  stevel 		}
   1520     0  stevel 
   1521     0  stevel 		/* reset errors */
   1522     0  stevel 		errno = 0;
   1523     0  stevel 
   1524     0  stevel 		/* check whether a "non-null" command has been used */
   1525     0  stevel 		switch (c->cmd_code)
   1526     0  stevel 		{
   1527     0  stevel #if SASL
   1528     0  stevel 		  case CMDAUTH:
   1529     0  stevel 			/* avoid information leak; take first two words? */
   1530     0  stevel 			q = "AUTH";
   1531     0  stevel 			break;
   1532     0  stevel #endif /* SASL */
   1533     0  stevel 
   1534     0  stevel 		  case CMDMAIL:
   1535     0  stevel 		  case CMDEXPN:
   1536     0  stevel 		  case CMDVRFY:
   1537     0  stevel 		  case CMDETRN:
   1538     0  stevel 			lognullconnection = false;
   1539     0  stevel 			/* FALLTHROUGH */
   1540     0  stevel 		  default:
   1541     0  stevel 			q = inp;
   1542     0  stevel 			break;
   1543     0  stevel 		}
   1544     0  stevel 
   1545     0  stevel 		if (e->e_id == NULL)
   1546     0  stevel 			sm_setproctitle(true, e, "%s: %.80s",
   1547     0  stevel 					CurSmtpClient, q);
   1548     0  stevel 		else
   1549     0  stevel 			sm_setproctitle(true, e, "%s %s: %.80s",
   1550     0  stevel 					qid_printname(e),
   1551     0  stevel 					CurSmtpClient, q);
   1552     0  stevel 
   1553     0  stevel 		/*
   1554     0  stevel 		**  Process command.
   1555     0  stevel 		**
   1556     0  stevel 		**	If we are running as a null server, return 550
   1557     0  stevel 		**	to almost everything.
   1558     0  stevel 		*/
   1559     0  stevel 
   1560     0  stevel 		if (nullserver != NULL || bitnset(D_ETRNONLY, d_flags))
   1561     0  stevel 		{
   1562     0  stevel 			switch (c->cmd_code)
   1563     0  stevel 			{
   1564     0  stevel 			  case CMDQUIT:
   1565     0  stevel 			  case CMDHELO:
   1566     0  stevel 			  case CMDEHLO:
   1567     0  stevel 			  case CMDNOOP:
   1568     0  stevel 			  case CMDRSET:
   1569     0  stevel 			  case CMDERROR:
   1570     0  stevel 				/* process normally */
   1571     0  stevel 				break;
   1572     0  stevel 
   1573     0  stevel 			  case CMDETRN:
   1574     0  stevel 				if (bitnset(D_ETRNONLY, d_flags) &&
   1575     0  stevel 				    nullserver == NULL)
   1576     0  stevel 					break;
   1577     0  stevel 				DELAY_CONN("ETRN");
   1578     0  stevel 				/* FALLTHROUGH */
   1579     0  stevel 
   1580     0  stevel 			  default:
   1581     0  stevel #if MAXBADCOMMANDS > 0
   1582     0  stevel 				/* theoretically this could overflow */
   1583     0  stevel 				if (nullserver != NULL &&
   1584     0  stevel 				    ++n_badcmds > MAXBADCOMMANDS)
   1585     0  stevel 				{
   1586     0  stevel 					message("421 4.7.0 %s Too many bad commands; closing connection",
   1587     0  stevel 						MyHostName);
   1588     0  stevel 
   1589     0  stevel 					/* arrange to ignore send list */
   1590     0  stevel 					e->e_sendqueue = NULL;
   1591     0  stevel 					goto doquit;
   1592     0  stevel 				}
   1593     0  stevel #endif /* MAXBADCOMMANDS > 0 */
   1594     0  stevel 				if (nullserver != NULL)
   1595     0  stevel 				{
   1596     0  stevel 					if (ISSMTPREPLY(nullserver))
   1597     0  stevel 						usrerr(nullserver);
   1598     0  stevel 					else
   1599     0  stevel 						usrerr("550 5.0.0 %s",
   1600     0  stevel 						       nullserver);
   1601     0  stevel 				}
   1602     0  stevel 				else
   1603     0  stevel 					usrerr("452 4.4.5 Insufficient disk space; try again later");
   1604     0  stevel 				continue;
   1605     0  stevel 			}
   1606     0  stevel 		}
   1607     0  stevel 
   1608     0  stevel 		switch (c->cmd_code)
   1609     0  stevel 		{
   1610     0  stevel #if SASL
   1611     0  stevel 		  case CMDAUTH: /* sasl */
   1612     0  stevel 			DELAY_CONN("AUTH");
   1613     0  stevel 			if (!sasl_ok || n_mechs <= 0)
   1614     0  stevel 			{
   1615     0  stevel 				message("503 5.3.3 AUTH not available");
   1616     0  stevel 				break;
   1617     0  stevel 			}
   1618     0  stevel 			if (authenticating == SASL_IS_AUTH)
   1619     0  stevel 			{
   1620     0  stevel 				message("503 5.5.0 Already Authenticated");
   1621     0  stevel 				break;
   1622     0  stevel 			}
   1623     0  stevel 			if (smtp.sm_gotmail)
   1624     0  stevel 			{
   1625     0  stevel 				message("503 5.5.0 AUTH not permitted during a mail transaction");
   1626     0  stevel 				break;
   1627     0  stevel 			}
   1628     0  stevel 			if (tempfail)
   1629     0  stevel 			{
   1630     0  stevel 				if (LogLevel > 9)
   1631     0  stevel 					sm_syslog(LOG_INFO, e->e_id,
   1632     0  stevel 						  "SMTP AUTH command (%.100s) from %s tempfailed (due to previous checks)",
   1633     0  stevel 						  p, CurSmtpClient);
   1634     0  stevel 				usrerr("454 4.3.0 Please try again later");
   1635     0  stevel 				break;
   1636     0  stevel 			}
   1637     0  stevel 
   1638     0  stevel 			ismore = false;
   1639     0  stevel 
   1640     0  stevel 			/* crude way to avoid crack attempts */
   1641     0  stevel 			STOP_IF_ATTACK(checksmtpattack(&n_auth, n_mechs + 1,
   1642     0  stevel 							true, "AUTH", e));
   1643     0  stevel 
   1644     0  stevel 			/* make sure mechanism (p) is a valid string */
   1645     0  stevel 			for (q = p; *q != '\0' && isascii(*q); q++)
   1646     0  stevel 			{
   1647     0  stevel 				if (isspace(*q))
   1648     0  stevel 				{
   1649     0  stevel 					*q = '\0';
   1650     0  stevel 					while (*++q != '\0' &&
   1651     0  stevel 					       isascii(*q) && isspace(*q))
   1652     0  stevel 						continue;
   1653     0  stevel 					*(q - 1) = '\0';
   1654     0  stevel 					ismore = (*q != '\0');
   1655     0  stevel 					break;
   1656     0  stevel 				}
   1657     0  stevel 			}
   1658     0  stevel 
   1659     0  stevel 			if (*p == '\0')
   1660     0  stevel 			{
   1661     0  stevel 				message("501 5.5.2 AUTH mechanism must be specified");
   1662     0  stevel 				break;
   1663     0  stevel 			}
   1664     0  stevel 
   1665     0  stevel 			/* check whether mechanism is available */
   1666     0  stevel 			if (iteminlist(p, mechlist, " ") == NULL)
   1667     0  stevel 			{
   1668     0  stevel 				message("504 5.3.3 AUTH mechanism %.32s not available",
   1669     0  stevel 					p);
   1670     0  stevel 				break;
   1671     0  stevel 			}
   1672     0  stevel 
   1673  5402   jbeck 			/*
   1674  5402   jbeck 			**  RFC 2554 4.
   1675  5402   jbeck 			**  Unlike a zero-length client answer to a
   1676  5402   jbeck 			**  334 reply, a zero- length initial response
   1677  5402   jbeck 			**  is sent as a single equals sign ("=").
   1678  5402   jbeck 			*/
   1679  5402   jbeck 
   1680  5402   jbeck 			if (ismore && *q == '=' && *(q + 1) == '\0')
   1681  5402   jbeck 			{
   1682  5402   jbeck 				/* will be free()d, don't use in=""; */
   1683  5402   jbeck 				in = xalloc(1);
   1684  5402   jbeck 				*in = '\0';
   1685  5402   jbeck 				inlen = 0;
   1686  5402   jbeck 			}
   1687  5402   jbeck 			else if (ismore)
   1688     0  stevel 			{
   1689     0  stevel 				/* could this be shorter? XXX */
   1690     0  stevel # if SASL >= 20000
   1691     0  stevel 				in = xalloc(strlen(q) + 1);
   1692     0  stevel 				result = sasl_decode64(q, strlen(q), in,
   1693     0  stevel 						       strlen(q), &inlen);
   1694     0  stevel # else /* SASL >= 20000 */
   1695     0  stevel 				in = sm_rpool_malloc(e->e_rpool, strlen(q));
   1696     0  stevel 				result = sasl_decode64(q, strlen(q), in,
   1697     0  stevel 						       &inlen);
   1698     0  stevel # endif /* SASL >= 20000 */
   1699     0  stevel 				if (result != SASL_OK)
   1700     0  stevel 				{
   1701     0  stevel 					message("501 5.5.4 cannot BASE64 decode '%s'",
   1702     0  stevel 						q);
   1703     0  stevel 					if (LogLevel > 5)
   1704     0  stevel 						sm_syslog(LOG_WARNING, e->e_id,
   1705     0  stevel 							  "AUTH decode64 error [%d for \"%s\"]",
   1706     0  stevel 							  result, q);
   1707     0  stevel 					/* start over? */
   1708     0  stevel 					authenticating = SASL_NOT_AUTH;
   1709     0  stevel # if SASL >= 20000
   1710     0  stevel 					sm_free(in);
   1711     0  stevel # endif /* SASL >= 20000 */
   1712     0  stevel 					in = NULL;
   1713     0  stevel 					inlen = 0;
   1714     0  stevel 					break;
   1715     0  stevel 				}
   1716     0  stevel 			}
   1717     0  stevel 			else
   1718     0  stevel 			{
   1719     0  stevel 				in = NULL;
   1720     0  stevel 				inlen = 0;
   1721     0  stevel 			}
   1722     0  stevel 
   1723     0  stevel 			/* see if that auth type exists */
   1724     0  stevel # if SASL >= 20000
   1725     0  stevel 			result = sasl_server_start(conn, p, in, inlen,
   1726     0  stevel 						   &out, &outlen);
   1727     0  stevel 			if (in != NULL)
   1728     0  stevel 				sm_free(in);
   1729     0  stevel # else /* SASL >= 20000 */
   1730     0  stevel 			result = sasl_server_start(conn, p, in, inlen,
   1731     0  stevel 						   &out, &outlen, &errstr);
   1732     0  stevel # endif /* SASL >= 20000 */
   1733     0  stevel 
   1734     0  stevel 			if (result != SASL_OK && result != SASL_CONTINUE)
   1735     0  stevel 			{
   1736     0  stevel 				message("535 5.7.0 authentication failed");
   1737     0  stevel 				if (LogLevel > 9)
   1738     0  stevel 					sm_syslog(LOG_ERR, e->e_id,
   1739     0  stevel 						  "AUTH failure (%s): %s (%d) %s",
   1740     0  stevel 						  p,
   1741     0  stevel 						  sasl_errstring(result, NULL,
   1742     0  stevel 								 NULL),
   1743     0  stevel 						  result,
   1744     0  stevel # if SASL >= 20000
   1745     0  stevel 						  sasl_errdetail(conn));
   1746     0  stevel # else /* SASL >= 20000 */
   1747     0  stevel 						  errstr);
   1748     0  stevel # endif /* SASL >= 20000 */
   1749     0  stevel 				RESET_SASLCONN;
   1750     0  stevel 				break;
   1751     0  stevel 			}
   1752     0  stevel 			auth_type = newstr(p);
   1753     0  stevel 
   1754     0  stevel 			if (result == SASL_OK)
   1755     0  stevel 			{
   1756     0  stevel 				/* ugly, but same code */
   1757     0  stevel 				goto authenticated;
   1758     0  stevel 				/* authenticated by the initial response */
   1759     0  stevel 			}
   1760     0  stevel 
   1761     0  stevel 			/* len is at least 2 */
   1762     0  stevel 			len = ENC64LEN(outlen);
   1763     0  stevel 			out2 = xalloc(len);
   1764     0  stevel 			result = sasl_encode64(out, outlen, out2, len,
   1765     0  stevel 					       &out2len);
   1766     0  stevel 
   1767     0  stevel 			if (result != SASL_OK)
   1768     0  stevel 			{
   1769     0  stevel 				message("454 4.5.4 Temporary authentication failure");
   1770     0  stevel 				if (LogLevel > 5)
   1771     0  stevel 					sm_syslog(LOG_WARNING, e->e_id,
   1772     0  stevel 						  "AUTH encode64 error [%d for \"%s\"]",
   1773     0  stevel 						  result, out);
   1774     0  stevel 
   1775     0  stevel 				/* start over? */
   1776     0  stevel 				authenticating = SASL_NOT_AUTH;
   1777     0  stevel 				RESET_SASLCONN;
   1778     0  stevel 			}
   1779     0  stevel 			else
   1780     0  stevel 			{
   1781     0  stevel 				message("334 %s", out2);
   1782     0  stevel 				authenticating = SASL_PROC_AUTH;
   1783     0  stevel 			}
   1784     0  stevel # if SASL >= 20000
   1785     0  stevel 			sm_free(out2);
   1786     0  stevel # endif /* SASL >= 20000 */
   1787     0  stevel 			break;
   1788     0  stevel #endif /* SASL */
   1789     0  stevel 
   1790     0  stevel #if STARTTLS
   1791     0  stevel 		  case CMDSTLS: /* starttls */
   1792     0  stevel 			DELAY_CONN("STARTTLS");
   1793     0  stevel 			if (*p != '\0')
   1794     0  stevel 			{
   1795     0  stevel 				message("501 5.5.2 Syntax error (no parameters allowed)");
   1796     0  stevel 				break;
   1797     0  stevel 			}
   1798     0  stevel 			if (!bitset(SRV_OFFER_TLS, features))
   1799     0  stevel 			{
   1800     0  stevel 				message("503 5.5.0 TLS not available");
   1801     0  stevel 				break;
   1802     0  stevel 			}
   1803     0  stevel 			if (!tls_ok_srv)
   1804     0  stevel 			{
   1805     0  stevel 				message("454 4.3.3 TLS not available after start");
   1806     0  stevel 				break;
   1807     0  stevel 			}
   1808     0  stevel 			if (smtp.sm_gotmail)
   1809     0  stevel 			{
   1810     0  stevel 				message("503 5.5.0 TLS not permitted during a mail transaction");
   1811     0  stevel 				break;
   1812     0  stevel 			}
   1813     0  stevel 			if (tempfail)
   1814     0  stevel 			{
   1815     0  stevel 				if (LogLevel > 9)
   1816     0  stevel 					sm_syslog(LOG_INFO, e->e_id,
   1817     0  stevel 						  "SMTP STARTTLS command (%.100s) from %s tempfailed (due to previous checks)",
   1818     0  stevel 						  p, CurSmtpClient);
   1819     0  stevel 				usrerr("454 4.7.0 Please try again later");
   1820     0  stevel 				break;
   1821     0  stevel 			}
   1822     0  stevel   starttls:
   1823     0  stevel # if TLS_NO_RSA
   1824     0  stevel 			/*
   1825     0  stevel 			**  XXX do we need a temp key ?
   1826     0  stevel 			*/
   1827     0  stevel # else /* TLS_NO_RSA */
   1828     0  stevel # endif /* TLS_NO_RSA */
   1829     0  stevel 
   1830     0  stevel # if TLS_VRFY_PER_CTX
   1831     0  stevel 			/*
   1832     0  stevel 			**  Note: this sets the verification globally
   1833     0  stevel 			**  (per SSL_CTX)
   1834     0  stevel 			**  it's ok since it applies only to one transaction
   1835     0  stevel 			*/
   1836     0  stevel 
   1837     0  stevel 			TLS_VERIFY_CLIENT();
   1838     0  stevel # endif /* TLS_VRFY_PER_CTX */
   1839     0  stevel 
   1840     0  stevel 			if (srv_ssl != NULL)
   1841     0  stevel 				SSL_clear(srv_ssl);
   1842     0  stevel 			else if ((srv_ssl = SSL_new(srv_ctx)) == NULL)
   1843     0  stevel 			{
   1844     0  stevel 				message("454 4.3.3 TLS not available: error generating SSL handle");
   1845     0  stevel 				if (LogLevel > 8)
   1846     0  stevel 					tlslogerr("server");
   1847     0  stevel 				goto tls_done;
   1848     0  stevel 			}
   1849     0  stevel 
   1850     0  stevel # if !TLS_VRFY_PER_CTX
   1851     0  stevel 			/*
   1852     0  stevel 			**  this could be used if it were possible to set
   1853     0  stevel 			**  verification per SSL (connection)
   1854     0  stevel 			**  not just per SSL_CTX (global)
   1855     0  stevel 			*/
   1856     0  stevel 
   1857     0  stevel 			TLS_VERIFY_CLIENT();
   1858     0  stevel # endif /* !TLS_VRFY_PER_CTX */
   1859     0  stevel 
   1860     0  stevel 			rfd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL);
   1861     0  stevel 			wfd = sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL);
   1862     0  stevel 
   1863     0  stevel 			if (rfd < 0 || wfd < 0 ||
   1864     0  stevel 			    SSL_set_rfd(srv_ssl, rfd) <= 0 ||
   1865     0  stevel 			    SSL_set_wfd(srv_ssl, wfd) <= 0)
   1866     0  stevel 			{
   1867     0  stevel 				message("454 4.3.3 TLS not available: error set fd");
   1868     0  stevel 				SSL_free(srv_ssl);
   1869     0  stevel 				srv_ssl = NULL;
   1870     0  stevel 				goto tls_done;
   1871     0  stevel 			}
   1872     0  stevel 			if (!smtps)
   1873     0  stevel 				message("220 2.0.0 Ready to start TLS");
   1874     0  stevel # if PIPELINING
   1875     0  stevel 			(void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
   1876     0  stevel # endif /* PIPELINING */
   1877     0  stevel 
   1878     0  stevel 			SSL_set_accept_state(srv_ssl);
   1879     0  stevel 
   1880     0  stevel #  define SSL_ACC(s)	SSL_accept(s)
   1881     0  stevel 
   1882     0  stevel 			tlsstart = curtime();
   1883     0  stevel   ssl_retry:
   1884     0  stevel 			if ((r = SSL_ACC(srv_ssl)) <= 0)
   1885     0  stevel 			{
   1886  1658   jbeck 				int i, ssl_err;
   1887  1658   jbeck 
   1888  1658   jbeck 				ssl_err = SSL_get_error(srv_ssl, r);
   1889  1658   jbeck 				i = tls_retry(srv_ssl, rfd, wfd, tlsstart,
   1890  1658   jbeck 						TimeOuts.to_starttls, ssl_err,
   1891  1658   jbeck 						"server");
   1892  1658   jbeck 				if (i > 0)
   1893  1658   jbeck 					goto ssl_retry;
   1894  1658   jbeck 
   1895     0  stevel 				if (LogLevel > 5)
   1896     0  stevel 				{
   1897     0  stevel 					sm_syslog(LOG_WARNING, NOQID,
   1898  1658   jbeck 						  "STARTTLS=server, error: accept failed=%d, SSL_error=%d, errno=%d, retry=%d",
   1899  1658   jbeck 						  r, ssl_err, errno, i);
   1900     0  stevel 					if (LogLevel > 8)
   1901     0  stevel 						tlslogerr("server");
   1902     0  stevel 				}
   1903     0  stevel 				tls_ok_srv = false;
   1904     0  stevel 				SSL_free(srv_ssl);
   1905     0  stevel 				srv_ssl = NULL;
   1906     0  stevel 
   1907     0  stevel 				/*
   1908     0  stevel 				**  according to the next draft of
   1909     0  stevel 				**  RFC 2487 the connection should be dropped
   1910     0  stevel 				*/
   1911     0  stevel 
   1912     0  stevel 				/* arrange to ignore any current send list */
   1913     0  stevel 				e->e_sendqueue = NULL;
   1914     0  stevel 				goto doquit;
   1915     0  stevel 			}
   1916     0  stevel 
   1917     0  stevel 			/* ignore return code for now, it's in {verify} */
   1918     0  stevel 			(void) tls_get_info(srv_ssl, true,
   1919     0  stevel 					    CurSmtpClient,
   1920     0  stevel 					    &BlankEnvelope.e_macro,
   1921     0  stevel 					    bitset(SRV_VRFY_CLT, features));
   1922     0  stevel 
   1923     0  stevel 			/*
   1924     0  stevel 			**  call Stls_client to find out whether
   1925     0  stevel 			**  to accept the connection from the client
   1926     0  stevel 			*/
   1927     0  stevel 
   1928     0  stevel 			saveQuickAbort = QuickAbort;
   1929     0  stevel 			saveSuprErrs = SuprErrs;
   1930     0  stevel 			SuprErrs = true;
   1931     0  stevel 			QuickAbort = false;
   1932     0  stevel 			if (rscheck("tls_client",
   1933     0  stevel 				     macvalue(macid("{verify}"), e),
   1934     0  stevel 				     "STARTTLS", e,
   1935     0  stevel 				     RSF_RMCOMM|RSF_COUNT,
   1936  3544   jbeck 				     5, NULL, NOQID, NULL) != EX_OK ||
   1937     0  stevel 			    Errors > 0)
   1938     0  stevel 			{
   1939     0  stevel 				extern char MsgBuf[];
   1940     0  stevel 
   1941     0  stevel 				if (MsgBuf[0] != '\0' && ISSMTPREPLY(MsgBuf))
   1942     0  stevel 					nullserver = newstr(MsgBuf);
   1943     0  stevel 				else
   1944     0  stevel 					nullserver = "503 5.7.0 Authentication required.";
   1945     0  stevel 			}
   1946     0  stevel 			QuickAbort = saveQuickAbort;
   1947     0  stevel 			SuprErrs = saveSuprErrs;
   1948     0  stevel 
   1949     0  stevel 			tls_ok_srv = false;	/* don't offer STARTTLS again */
   1950     0  stevel 			n_helo = 0;
   1951     0  stevel # if SASL
   1952     0  stevel 			if (sasl_ok)
   1953     0  stevel 			{
   1954     0  stevel 				int cipher_bits;
   1955     0  stevel 				bool verified;
   1956     0  stevel 				char *s, *v, *c;
   1957     0  stevel 
   1958     0  stevel 				s = macvalue(macid("{cipher_bits}"), e);
   1959     0  stevel 				v = macvalue(macid("{verify}"), e);
   1960     0  stevel 				c = macvalue(macid("{cert_subject}"), e);
   1961     0  stevel 				verified = (v != NULL && strcmp(v, "OK") == 0);
   1962     0  stevel 				if (s != NULL && (cipher_bits = atoi(s)) > 0)
   1963     0  stevel 				{
   1964     0  stevel #  if SASL >= 20000
   1965     0  stevel 					ext_ssf = cipher_bits;
   1966     0  stevel 					auth_id = verified ? c : NULL;
   1967     0  stevel 					sasl_ok = ((sasl_setprop(conn,
   1968     0  stevel 							SASL_SSF_EXTERNAL,
   1969     0  stevel 							&ext_ssf) == SASL_OK) &&
   1970     0  stevel 						   (sasl_setprop(conn,
   1971     0  stevel 							SASL_AUTH_EXTERNAL,
   1972     0  stevel 							auth_id) == SASL_OK));
   1973     0  stevel #  else /* SASL >= 20000 */
   1974     0  stevel 					ext_ssf.ssf = cipher_bits;
   1975     0  stevel 					ext_ssf.auth_id = verified ? c : NULL;
   1976     0  stevel 					sasl_ok = sasl_setprop(conn,
   1977     0  stevel 							SASL_SSF_EXTERNAL,
   1978     0  stevel 							&ext_ssf) == SASL_OK;
   1979     0  stevel #  endif /* SASL >= 20000 */
   1980     0  stevel 					mechlist = NULL;
   1981     0  stevel 					if (sasl_ok)
   1982     0  stevel 						n_mechs = saslmechs(conn,
   1983     0  stevel 								    &mechlist);
   1984     0  stevel 				}
   1985     0  stevel 			}
   1986     0  stevel # endif /* SASL */
   1987     0  stevel 
   1988     0  stevel 			/* switch to secure connection */
   1989     0  stevel 			if (sfdctls(&InChannel, &OutChannel, srv_ssl) == 0)
   1990     0  stevel 			{
   1991     0  stevel 				tls_active = true;
   1992     0  stevel # if PIPELINING
   1993     0  stevel 				(void) sm_io_autoflush(InChannel, OutChannel);
   1994     0  stevel # endif /* PIPELINING */
   1995     0  stevel 			}
   1996     0  stevel 			else
   1997     0  stevel 			{
   1998     0  stevel 				/*
   1999     0  stevel 				**  XXX this is an internal error
   2000     0  stevel 				**  how to deal with it?
   2001     0  stevel 				**  we can't generate an error message
   2002     0  stevel 				**  since the other side switched to an
   2003     0  stevel 				**  encrypted layer, but we could not...
   2004     0  stevel 				**  just "hang up"?
   2005     0  stevel 				*/
   2006     0  stevel 
   2007     0  stevel 				nullserver = "454 4.3.3 TLS not available: can't switch to encrypted layer";
   2008     0  stevel 				syserr("STARTTLS: can't switch to encrypted layer");
   2009     0  stevel 			}
   2010     0  stevel 		  tls_done:
   2011     0  stevel 			if (smtps)
   2012     0  stevel 			{
   2013     0  stevel 				if (tls_active)
   2014     0  stevel 					goto greeting;
   2015     0  stevel 				else
   2016     0  stevel 					goto doquit;
   2017     0  stevel 			}
   2018     0  stevel 			break;
   2019     0  stevel #endif /* STARTTLS */
   2020     0  stevel 
   2021     0  stevel 		  case CMDHELO:		/* hello -- introduce yourself */
   2022     0  stevel 		  case CMDEHLO:		/* extended hello */
   2023     0  stevel 			DELAY_CONN("EHLO");
   2024     0  stevel 			if (c->cmd_code == CMDEHLO)
   2025     0  stevel 			{
   2026     0  stevel 				protocol = "ESMTP";
   2027     0  stevel 				SmtpPhase = "server EHLO";
   2028     0  stevel 			}
   2029     0  stevel 			else
   2030     0  stevel 			{
   2031     0  stevel 				protocol = "SMTP";
   2032     0  stevel 				SmtpPhase = "server HELO";
   2033     0  stevel 			}
   2034     0  stevel 
   2035     0  stevel 			/* avoid denial-of-service */
   2036     0  stevel 			STOP_IF_ATTACK(checksmtpattack(&n_helo, MAXHELOCOMMANDS,
   2037     0  stevel 							true, "HELO/EHLO", e));
   2038     0  stevel 
   2039     0  stevel #if 0
   2040     0  stevel 			/* RFC2821 4.1.4 allows duplicate HELO/EHLO */
   2041     0  stevel 			/* check for duplicate HELO/EHLO per RFC 1651 4.2 */
   2042     0  stevel 			if (gothello)
   2043     0  stevel 			{
   2044     0  stevel 				usrerr("503 %s Duplicate HELO/EHLO",
   2045     0  stevel 				       MyHostName);
   2046     0  stevel 				break;
   2047     0  stevel 			}
   2048     0  stevel #endif /* 0 */
   2049     0  stevel 
   2050     0  stevel 			/* check for valid domain name (re 1123 5.2.5) */
   2051     0  stevel 			if (*p == '\0' && !AllowBogusHELO)
   2052     0  stevel 			{
   2053     0  stevel 				usrerr("501 %s requires domain address",
   2054     0  stevel 					cmdbuf);
   2055     0  stevel 				break;
   2056     0  stevel 			}
   2057     0  stevel 
   2058     0  stevel 			/* check for long domain name (hides Received: info) */
   2059     0  stevel 			if (strlen(p) > MAXNAME)
   2060     0  stevel 			{
   2061     0  stevel 				usrerr("501 Invalid domain name");
   2062     0  stevel 				if (LogLevel > 9)
   2063     0  stevel 					sm_syslog(LOG_INFO, CurEnv->e_id,
   2064     0  stevel 						  "invalid domain name (too long) from %s",
   2065     0  stevel 						  CurSmtpClient);
   2066     0  stevel 				break;
   2067     0  stevel 			}
   2068     0  stevel 
   2069     0  stevel 			ok = true;
   2070     0  stevel 			for (q = p; *q != '\0'; q++)
   2071     0  stevel 			{
   2072     0  stevel 				if (!isascii(*q))
   2073     0  stevel 					break;
   2074     0  stevel 				if (isalnum(*q))
   2075     0  stevel 					continue;
   2076     0  stevel 				if (isspace(*q))
   2077     0  stevel 				{
   2078     0  stevel 					*q = '\0';
   2079     0  stevel 
   2080     0  stevel 					/* only complain if strict check */
   2081     0  stevel 					ok = AllowBogusHELO;
   2082     0  stevel 
   2083     0  stevel 					/* allow trailing whitespace */
   2084     0  stevel 					while (!ok && *++q != '\0' &&
   2085     0  stevel 					       isspace(*q))
   2086     0  stevel 						;
   2087     0  stevel 					if (*q == '\0')
   2088     0  stevel 						ok = true;
   2089     0  stevel 					break;
   2090     0  stevel 				}
   2091     0  stevel 				if (strchr("[].-_#:", *q) == NULL)
   2092     0  stevel 					break;
   2093     0  stevel 			}
   2094     0  stevel 
   2095     0  stevel 			if (*q == '\0' && ok)
   2096     0  stevel 			{
   2097     0  stevel 				q = "pleased to meet you";
   2098     0  stevel 				sendinghost = sm_strdup_x(p);
   2099     0  stevel 			}
   2100     0  stevel 			else if (!AllowBogusHELO)
   2101     0  stevel 			{
   2102     0  stevel 				usrerr("501 Invalid domain name");
   2103     0  stevel 				if (LogLevel > 9)
   2104     0  stevel 					sm_syslog(LOG_INFO, CurEnv->e_id,
   2105     0  stevel 						  "invalid domain name (%s) from %.100s",
   2106     0  stevel 						  p, CurSmtpClient);
   2107     0  stevel 				break;
   2108     0  stevel 			}
   2109     0  stevel 			else
   2110     0  stevel 			{
   2111     0  stevel 				q = "accepting invalid domain name";
   2112     0  stevel 			}
   2113     0  stevel 
   2114  1658   jbeck 			if (gothello || smtp.sm_gotmail)
   2115     0  stevel 				CLEAR_STATE(cmdbuf);
   2116     0  stevel 
   2117     0  stevel #if MILTER
   2118     0  stevel 			if (smtp.sm_milterlist && smtp.sm_milterize &&
   2119     0  stevel 			    !bitset(EF_DISCARD, e->e_flags))
   2120     0  stevel 			{
   2121     0  stevel 				char state;
   2122     0  stevel 				char *response;
   2123     0  stevel 
   2124     0  stevel 				response = milter_helo(p, e, &state);
   2125     0  stevel 				switch (state)
   2126     0  stevel 				{
   2127     0  stevel 				  case SMFIR_REJECT:
   2128     0  stevel 					if (MilterLogLevel > 3)
   2129     0  stevel 						sm_syslog(LOG_INFO, e->e_id,
   2130     0  stevel 							  "Milter: helo=%s, reject=Command rejected",
   2131     0  stevel 							  p);
   2132     0  stevel 					nullserver = "Command rejected";
   2133     0  stevel 					smtp.sm_milterize = false;
   2134     0  stevel 					break;
   2135     0  stevel 
   2136     0  stevel 				  case SMFIR_TEMPFAIL:
   2137     0  stevel 					if (MilterLogLevel > 3)
   2138     0  stevel 						sm_syslog(LOG_INFO, e->e_id,
   2139     0  stevel 							  "Milter: helo=%s, reject=%s",
   2140     0  stevel 							  p, MSG_TEMPFAIL);
   2141     0  stevel 					tempfail = true;
   2142     0  stevel 					smtp.sm_milterize = false;
   2143     0  stevel 					break;
   2144  1658   jbeck 
   2145  3544   jbeck 				  case SMFIR_REPLYCODE:
   2146  3544   jbeck 					if (MilterLogLevel > 3)
   2147  3544   jbeck 						sm_syslog(LOG_INFO, e->e_id,
   2148  3544   jbeck 							  "Milter: helo=%s, reject=%s",
   2149  3544   jbeck 							  p, response);
   2150  3544   jbeck 					if (strncmp(response, "421 ", 4) != 0
   2151  3544   jbeck 					    && strncmp(response, "421-", 4) != 0)
   2152  3544   jbeck 					{
   2153  3544   jbeck 						nullserver = newstr(response);
   2154  3544   jbeck 						smtp.sm_milterize = false;
   2155  3544   jbeck 						break;
   2156  3544   jbeck 					}
   2157  3544   jbeck 					/* FALLTHROUGH */
   2158  3544   jbeck 
   2159  1658   jbeck 				  case SMFIR_SHUTDOWN:
   2160  3544   jbeck 					if (MilterLogLevel > 3 &&
   2161  3544   jbeck 					    response == NULL)
   2162  1658   jbeck 						sm_syslog(LOG_INFO, e->e_id,
   2163  2197   jbeck 							  "Milter: helo=%s, reject=421 4.7.0 %s closing connection",
   2164  1658   jbeck 							  p, MyHostName);
   2165  1658   jbeck 					tempfail = true;
   2166  1658   jbeck 					smtp.sm_milterize = false;
   2167  3544   jbeck 					if (response != NULL)
   2168  3544   jbeck 						usrerr(response);
   2169  3544   jbeck 					else
   2170  3544   jbeck 						message("421 4.7.0 %s closing connection",
   2171  3544   jbeck 							MyHostName);
   2172  1658   jbeck 					/* arrange to ignore send list */
   2173  1658   jbeck 					e->e_sendqueue = NULL;
   2174  3544   jbeck 					lognullconnection = false;
   2175  1658   jbeck 					goto doquit;
   2176     0  stevel 				}
   2177     0  stevel 				if (response != NULL)
   2178     0  stevel 					sm_free(response);
   2179     0  stevel 
   2180     0  stevel 				/*
   2181     0  stevel 				**  If quarantining by a connect/ehlo action,
   2182     0  stevel 				**  save between messages
   2183     0  stevel 				*/
   2184     0  stevel 
   2185     0  stevel 				if (smtp.sm_quarmsg == NULL &&
   2186     0  stevel 				    e->e_quarmsg != NULL)
   2187     0  stevel 					smtp.sm_quarmsg = newstr(e->e_quarmsg);
   2188     0  stevel 			}
   2189     0  stevel #endif /* MILTER */
   2190     0  stevel 			gothello = true;
   2191     0  stevel 
   2192     0  stevel 			/* print HELO response message */
   2193     0  stevel 			if (c->cmd_code != CMDEHLO)
   2194     0  stevel 			{
   2195     0  stevel 				message("250 %s Hello %s, %s",
   2196     0  stevel 					MyHostName, CurSmtpClient, q);
   2197     0  stevel 				break;
   2198     0  stevel 			}
   2199     0  stevel 
   2200     0  stevel 			message("250-%s Hello %s, %s",
   2201     0  stevel 				MyHostName, CurSmtpClient, q);
   2202     0  stevel 
   2203     0  stevel 			/* offer ENHSC even for nullserver */
   2204     0  stevel 			if (nullserver != NULL)
   2205     0  stevel 			{
   2206     0  stevel 				message("250 ENHANCEDSTATUSCODES");
   2207     0  stevel 				break;
   2208     0  stevel 			}
   2209     0  stevel 
   2210     0  stevel 			/*
   2211     0  stevel 			**  print EHLO features list
   2212     0  stevel 			**
   2213     0  stevel 			**  Note: If you change this list,
   2214     0  stevel 			**	  remember to update 'helpfile'
   2215     0  stevel 			*/
   2216     0  stevel 
   2217     0  stevel 			message("250-ENHANCEDSTATUSCODES");
   2218     0  stevel #if PIPELINING
   2219     0  stevel 			if (bitset(SRV_OFFER_PIPE, features))
   2220     0  stevel 				message("250-PIPELINING");
   2221     0  stevel #endif /* PIPELINING */
   2222     0  stevel 			if (bitset(SRV_OFFER_EXPN, features))
   2223     0  stevel 			{
   2224     0  stevel 				message("250-EXPN");
   2225     0  stevel 				if (bitset(SRV_OFFER_VERB, features))
   2226     0  stevel 					message("250-VERB");
   2227     0  stevel 			}
   2228     0  stevel #if MIME8TO7
   2229     0  stevel 			message("250-8BITMIME");
   2230     0  stevel #endif /* MIME8TO7 */
   2231     0  stevel 			if (MaxMessageSize > 0)
   2232     0  stevel 				message("250-SIZE %ld", MaxMessageSize);
   2233     0  stevel 			else
   2234     0  stevel 				message("250-SIZE");
   2235     0  stevel #if DSN
   2236     0  stevel 			if (SendMIMEErrors && bitset(SRV_OFFER_DSN, features))
   2237     0  stevel 				message("250-DSN");
   2238     0  stevel #endif /* DSN */
   2239     0  stevel 			if (bitset(SRV_OFFER_ETRN, features))
   2240     0  stevel 				message("250-ETRN");
   2241     0  stevel #if SASL
   2242     0  stevel 			if (sasl_ok && mechlist != NULL && *mechlist != '\0')
   2243     0  stevel 				message("250-AUTH %s", mechlist);
   2244     0  stevel #endif /* SASL */
   2245     0  stevel #if STARTTLS
   2246     0  stevel 			if (tls_ok_srv &&
   2247     0  stevel 			    bitset(SRV_OFFER_TLS, features))
   2248     0  stevel 				message("250-STARTTLS");
   2249     0  stevel #endif /* STARTTLS */
   2250     0  stevel 			if (DeliverByMin > 0)
   2251     0  stevel 				message("250-DELIVERBY %ld",
   2252     0  stevel 					(long) DeliverByMin);
   2253     0  stevel 			else if (DeliverByMin == 0)
   2254     0  stevel 				message("250-DELIVERBY");
   2255     0  stevel 
   2256     0  stevel 			/* < 0: no deliver-by */
   2257     0  stevel 
   2258     0  stevel 			message("250 HELP");
   2259     0  stevel 			break;
   2260     0  stevel 
   2261     0  stevel 		  case CMDMAIL:		/* mail -- designate sender */
   2262     0  stevel 			SmtpPhase = "server MAIL";
   2263     0  stevel 			DELAY_CONN("MAIL");
   2264     0  stevel 
   2265     0  stevel 			/* check for validity of this command */
   2266     0  stevel 			if (!gothello && bitset(PRIV_NEEDMAILHELO, PrivacyFlags))
   2267     0  stevel 			{
   2268     0  stevel 				usrerr("503 5.0.0 Polite people say HELO first");
   2269     0  stevel 				break;
   2270     0  stevel 			}
   2271     0  stevel 			if (smtp.sm_gotmail)
   2272     0  stevel 			{
   2273     0  stevel 				usrerr("503 5.5.0 Sender already specified");
   2274     0  stevel 				break;
   2275     0  stevel 			}
   2276     0  stevel #if SASL
   2277     0  stevel 			if (bitset(SRV_REQ_AUTH, features) &&
   2278     0  stevel 			    authenticating != SASL_IS_AUTH)
   2279     0  stevel 			{
   2280     0  stevel 				usrerr("530 5.7.0 Authentication required");
   2281     0  stevel 				break;
   2282     0  stevel 			}
   2283     0  stevel #endif /* SASL */
   2284     0  stevel 
   2285     0  stevel 			p = skipword(p, "from");
   2286     0  stevel 			if (p == NULL)
   2287     0  stevel 				break;
   2288     0  stevel 			if (tempfail)
   2289     0  stevel 			{
   2290     0  stevel 				if (LogLevel > 9)
   2291     0  stevel 					sm_syslog(LOG_INFO, e->e_id,
   2292     0  stevel 						  "SMTP MAIL command (%.100s) from %s tempfailed (due to previous checks)",
   2293     0  stevel 						  p, CurSmtpClient);
   2294     0  stevel 				usrerr(MSG_TEMPFAIL);
   2295     0  stevel 				break;
   2296     0  stevel 			}
   2297     0  stevel 
   2298     0  stevel 			/* make sure we know who the sending host is */
   2299     0  stevel 			if (sendinghost == NULL)
   2300     0  stevel 				sendinghost = peerhostname;
   2301     0  stevel 
   2302     0  stevel 
   2303     0  stevel #if SM_HEAP_CHECK
   2304     0  stevel 			if (sm_debug_active(&DebugLeakSmtp, 1))
   2305     0  stevel 			{
   2306     0  stevel 				sm_heap_newgroup();
   2307     0  stevel 				sm_dprintf("smtp() heap group #%d\n",
   2308     0  stevel 					sm_heap_group());
   2309     0  stevel 			}
   2310     0  stevel #endif /* SM_HEAP_CHECK */
   2311     0  stevel 
   2312     0  stevel 			if (Errors > 0)
   2313     0  stevel 				goto undo_no_pm;
   2314     0  stevel 			if (!gothello)
   2315     0  stevel 			{
   2316     0  stevel 				auth_warning(e, "%s didn't use HELO protocol",
   2317     0  stevel 					     CurSmtpClient);
   2318     0  stevel 			}
   2319     0  stevel #ifdef PICKY_HELO_CHECK
   2320     0  stevel 			if (sm_strcasecmp(sendinghost, peerhostname) != 0 &&
   2321     0  stevel 			    (sm_strcasecmp(peerhostname, "localhost") != 0 ||
   2322     0  stevel 			     sm_strcasecmp(sendinghost, MyHostName) != 0))
   2323     0  stevel 			{
   2324     0  stevel 				auth_warning(e, "Host %s claimed to be %s",
   2325     0  stevel 					     CurSmtpClient, sendinghost);
   2326     0  stevel 			}
   2327     0  stevel #endif /* PICKY_HELO_CHECK */
   2328     0  stevel 
   2329     0  stevel 			if (protocol == NULL)
   2330     0  stevel 				protocol = "SMTP";
   2331     0  stevel 			macdefine(&e->e_macro, A_PERM, 'r', protocol);
   2332     0  stevel 			macdefine(&e->e_macro, A_PERM, 's', sendinghost);
   2333     0  stevel 
   2334     0  stevel 			if (Errors > 0)
   2335     0  stevel 				goto undo_no_pm;
   2336     0  stevel 			smtp.sm_nrcpts = 0;
   2337     0  stevel 			n_badrcpts = 0;
   2338     0  stevel 			macdefine(&e->e_macro, A_PERM, macid("{ntries}"), "0");
   2339     0  stevel 			macdefine(&e->e_macro, A_PERM, macid("{nrcpts}"), "0");
   2340     0  stevel 			macdefine(&e->e_macro, A_PERM, macid("{nbadrcpts}"),
   2341     0  stevel 				"0");
   2342     0  stevel 			e->e_flags |= EF_CLRQUEUE;
   2343     0  stevel 			sm_setproctitle(true, e, "%s %s: %.80s",
   2344     0  stevel 					qid_printname(e),
   2345     0  stevel 					CurSmtpClient, inp);
   2346     0  stevel 
   2347     0  stevel 			/* do the processing */
   2348     0  stevel 		    SM_TRY
   2349     0  stevel 		    {
   2350     0  stevel 			extern char *FullName;
   2351     0  stevel 
   2352     0  stevel 			QuickAbort = true;
   2353     0  stevel 			SM_FREE_CLR(FullName);
   2354     0  stevel 
   2355     0  stevel 			/* must parse sender first */
   2356     0  stevel 			delimptr = NULL;
   2357     0  stevel 			setsender(p, e, &delimptr, ' ', false);
   2358     0  stevel 			if (delimptr != NULL && *delimptr != '\0')
   2359     0  stevel 				*delimptr++ = '\0';
   2360     0  stevel 			if (Errors > 0)
   2361     0  stevel 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
   2362     0  stevel 
   2363     0  stevel 			/* Successfully set e_from, allow logging */
   2364     0  stevel 			e->e_flags |= EF_LOGSENDER;
   2365     0  stevel 
   2366     0  stevel 			/* put resulting triple from parseaddr() into macros */
   2367     0  stevel 			if (e->e_from.q_mailer != NULL)
   2368     0  stevel 				 macdefine(&e->e_macro, A_PERM,
   2369     0  stevel 					macid("{mail_mailer}"),
   2370     0  stevel 					e->e_from.q_mailer->m_name);
   2371     0  stevel 			else
   2372     0  stevel 				 macdefine(&e->e_macro, A_PERM,
   2373     0  stevel 					macid("{mail_mailer}"), NULL);
   2374     0  stevel 			if (e->e_from.q_host != NULL)
   2375     0  stevel 				macdefine(&e->e_macro, A_PERM,
   2376     0  stevel 					macid("{mail_host}"),
   2377     0  stevel 					e->e_from.q_host);
   2378     0  stevel 			else
   2379     0  stevel 				macdefine(&e->e_macro, A_PERM,
   2380     0  stevel 					macid("{mail_host}"), "localhost");
   2381     0  stevel 			if (e->e_from.q_user != NULL)
   2382     0  stevel 				macdefine(&e->e_macro, A_PERM,
   2383     0  stevel 					macid("{mail_addr}"),
   2384     0  stevel 					e->e_from.q_user);
   2385     0  stevel 			else
   2386     0  stevel 				macdefine(&e->e_macro, A_PERM,
   2387     0  stevel 					macid("{mail_addr}"), NULL);
   2388     0  stevel 			if (Errors > 0)
   2389     0  stevel 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
   2390     0  stevel 
   2391     0  stevel 			/* check for possible spoofing */
   2392     0  stevel 			if (RealUid != 0 && OpMode == MD_SMTP &&
   2393     0  stevel 			    !wordinclass(RealUserName, 't') &&
   2394     0  stevel 			    (!bitnset(M_LOCALMAILER,
   2395     0  stevel 				      e->e_from.q_mailer->m_flags) ||
   2396     0  stevel 			     strcmp(e->e_from.q_user, RealUserName) != 0))
   2397     0  stevel 			{
   2398     0  stevel 				auth_warning(e, "%s owned process doing -bs",
   2399     0  stevel 					RealUserName);
   2400     0  stevel 			}
   2401     0  stevel 
   2402     0  stevel 			/* reset to default value */
   2403  3544   jbeck 			SevenBitInput = SevenBitInput_Saved;
   2404     0  stevel 
   2405     0  stevel 			/* now parse ESMTP arguments */
   2406     0  stevel 			e->e_msgsize = 0;
   2407     0  stevel 			addr = p;
   2408  3544   jbeck 			parse_esmtp_args(e, NULL, p, delimptr, "MAIL", args,
   2409  3544   jbeck 					mail_esmtp_args);
   2410     0  stevel 			if (Errors > 0)
   2411     0  stevel 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
   2412     0  stevel 
   2413     0  stevel #if SASL
   2414     0  stevel # if _FFR_AUTH_PASSING
   2415     0  stevel 			/* set the default AUTH= if the sender didn't */
   2416     0  stevel 			if (e->e_auth_param == NULL)
   2417     0  stevel 			{
   2418     0  stevel 				/* XXX only do this for an MSA? */
   2419     0  stevel 				e->e_auth_param = macvalue(macid("{auth_authen}"),
   2420     0  stevel 							   e);
   2421     0  stevel 				if (e->e_auth_param == NULL)
   2422     0  stevel 					e->e_auth_param = "<>";
   2423     0  stevel 
   2424     0  stevel 				/*
   2425     0  stevel 				**  XXX should we invoke Strust_auth now?
   2426     0  stevel 				**  authorizing as the client that just
   2427     0  stevel 				**  authenticated, so we'll trust implicitly
   2428     0  stevel 				*/
   2429     0  stevel 			}
   2430     0  stevel # endif /* _FFR_AUTH_PASSING */
   2431     0  stevel #endif /* SASL */
   2432     0  stevel 
   2433     0  stevel 			/* do config file checking of the sender */
   2434     0  stevel 			macdefine(&e->e_macro, A_PERM,
   2435     0  stevel 				macid("{addr_type}"), "e s");
   2436     0  stevel #if _FFR_MAIL_MACRO
   2437     0  stevel 			/* make the "real" sender address available */
   2438     0  stevel 			macdefine(&e->e_macro, A_TEMP, macid("{mail_from}"),
   2439     0  stevel 				  e->e_from.q_paddr);
   2440     0  stevel #endif /* _FFR_MAIL_MACRO */
   2441     0  stevel 			if (rscheck("check_mail", addr,
   2442     0  stevel 				    NULL, e, RSF_RMCOMM|RSF_COUNT, 3,
   2443  3544   jbeck 				    NULL, e->e_id, NULL) != EX_OK ||
   2444     0  stevel 			    Errors > 0)
   2445     0  stevel 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
   2446     0  stevel 			macdefine(&e->e_macro, A_PERM,
   2447     0  stevel 				  macid("{addr_type}"), NULL);
   2448     0  stevel 
   2449     0  stevel 			if (MaxMessageSize > 0 &&
   2450     0  stevel 			    (e->e_msgsize > MaxMessageSize ||
   2451     0  stevel 			     e->e_msgsize < 0))
   2452     0  stevel 			{
   2453     0  stevel 				usrerr("552 5.2.3 Message size exceeds fixed maximum message size (%ld)",
   2454     0  stevel 					MaxMessageSize);
   2455     0  stevel 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
   2456     0  stevel 			}
   2457     0  stevel 
   2458     0  stevel 			/*
   2459     0  stevel 			**  XXX always check whether there is at least one fs
   2460     0  stevel 			**  with enough space?
   2461     0  stevel 			**  However, this may not help much: the queue group
   2462     0  stevel 			**  selection may later on select a FS that hasn't
   2463     0  stevel 			**  enough space.
   2464     0  stevel 			*/
   2465     0  stevel 
   2466     0  stevel 			if ((NumFileSys == 1 || NumQueue == 1) &&
   2467     0  stevel 			    !enoughdiskspace(e->e_msgsize, e)
   2468     0  stevel #if _FFR_ANY_FREE_FS
   2469     0  stevel 			    && !filesys_free(e->e_msgsize)
   2470     0  stevel #endif /* _FFR_ANY_FREE_FS */
   2471     0  stevel 			   )
   2472     0  stevel 			{
   2473     0  stevel 				/*
   2474     0  stevel 				**  We perform this test again when the
   2475     0  stevel 				**  queue directory is selected, in collect.
   2476     0  stevel 				*/
   2477     0  stevel 
   2478     0  stevel 				usrerr("452 4.4.5 Insufficient disk space; try again later");
   2479     0  stevel 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
   2480     0  stevel 			}
   2481     0  stevel 			if (Errors > 0)
   2482     0  stevel 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
   2483     0  stevel 
   2484     0  stevel 			LogUsrErrs = true;
   2485     0  stevel #if MILTER
   2486     0  stevel 			if (smtp.sm_milterlist && smtp.sm_milterize &&
   2487     0  stevel 			    !bitset(EF_DISCARD, e->e_flags))
   2488     0  stevel 			{
   2489     0  stevel 				char state;
   2490     0  stevel 				char *response;
   2491     0  stevel 
   2492     0  stevel 				response = milter_envfrom(args, e, &state);
   2493     0  stevel 				MILTER_REPLY("from");
   2494     0  stevel 			}
   2495     0  stevel #endif /* MILTER */
   2496     0  stevel 			if (Errors > 0)
   2497     0  stevel 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
   2498     0  stevel 
   2499     0  stevel 			message("250 2.1.0 Sender ok");
   2500     0  stevel 			smtp.sm_gotmail = true;
   2501     0  stevel 		    }
   2502     0  stevel 		    SM_EXCEPT(exc, "[!F]*")
   2503     0  stevel 		    {
   2504     0  stevel 			/*
   2505     0  stevel 			**  An error occurred while processing a MAIL command.
   2506     0  stevel 			**  Jump to the common error handling code.
   2507     0  stevel 			*/
   2508     0  stevel 
   2509     0  stevel 			sm_exc_free(exc);
   2510     0  stevel 			goto undo_no_pm;
   2511     0  stevel 		    }
   2512     0  stevel 		    SM_END_TRY
   2513     0  stevel 			break;
   2514     0  stevel 
   2515     0  stevel 		  undo_no_pm:
   2516     0  stevel 			e->e_flags &= ~EF_PM_NOTIFY;
   2517     0  stevel 		  undo:
   2518     0  stevel 			break;
   2519     0  stevel 
   2520     0  stevel 		  case CMDRCPT:		/* rcpt -- designate recipient */
   2521     0  stevel 			DELAY_CONN("RCPT");
   2522  3544   jbeck 			macdefine(&e->e_macro, A_PERM,
   2523  3544   jbeck 				macid("{rcpt_mailer}"), NULL);
   2524  3544   jbeck 			macdefine(&e->e_macro, A_PERM,
   2525  3544   jbeck 				macid("{rcpt_host}"), NULL);
   2526  3544   jbeck 			macdefine(&e->e_macro, A_PERM,
   2527  3544   jbeck 				macid("{rcpt_addr}"), NULL);
   2528  3544   jbeck #if MILTER
   2529  3544   jbeck 			(void) memset(&addr_st, '\0', sizeof(addr_st));
   2530  3544   jbeck 			a = NULL;
   2531  3966   jbeck 			milter_rcpt_added = false;
   2532  5402   jbeck 			smtp.sm_e_nrcpts_orig = e->e_nrcpts;
   2533  3544   jbeck #endif
   2534  6562   jbeck #if _FFR_BADRCPT_SHUTDOWN
   2535  6562   jbeck 			/*
   2536  6562   jbeck 			**  hack to deal with hack, see below:
   2537  6562   jbeck 			**  n_badrcpts is increased is limit is reached.
   2538  6562   jbeck 			*/
   2539  6562   jbeck 
   2540  6562   jbeck 			n_badrcpts_adj = (BadRcptThrottle > 0 &&
   2541  6562   jbeck 					  n_badrcpts > BadRcptThrottle &&
   2542  6562   jbeck 					  LogLevel > 5)
   2543  6562   jbeck 					  ? n_badrcpts - 1 : n_badrcpts;
   2544  6562   jbeck 			if (BadRcptShutdown > 0 &&
   2545  6562   jbeck 			    n_badrcpts_adj >= BadRcptShutdown &&
   2546  6562   jbeck 			    (BadRcptShutdownGood == 0 ||
   2547  6562   jbeck 			     smtp.sm_nrcpts == 0 ||
   2548  6562   jbeck 			     (n_badrcpts_adj * 100 /
   2549  6562   jbeck 			      (smtp.sm_nrcpts + n_badrcpts) >=
   2550  6562   jbeck 			      BadRcptShutdownGood)))
   2551  6562   jbeck 			{
   2552  6562   jbeck 				if (LogLevel > 5)
   2553  6562   jbeck 					sm_syslog(LOG_INFO, e->e_id,
   2554  6562   jbeck 						  "%s: Possible SMTP RCPT flood, shutting down connection.",
   2555  6562   jbeck 						  CurSmtpClient);
   2556  6562   jbeck 				message("421 4.7.0 %s Too many bad recipients; closing connection",
   2557  6562   jbeck 				MyHostName);
   2558  6562   jbeck 
   2559  6562   jbeck 				/* arrange to ignore any current send list */
   2560  6562   jbeck 				e->e_sendqueue = NULL;
   2561  6562   jbeck 				goto doquit;
   2562  6562   jbeck 			}
   2563  6562   jbeck #endif /* _FFR_BADRCPT_SHUTDOWN */
   2564     0  stevel 			if (BadRcptThrottle > 0 &&
   2565     0  stevel 			    n_badrcpts >= BadRcptThrottle)
   2566     0  stevel 			{
   2567     0  stevel 				if (LogLevel > 5 &&
   2568     0  stevel 				    n_badrcpts == BadRcptThrottle)
   2569     0  stevel 				{
   2570     0  stevel 					sm_syslog(LOG_INFO, e->e_id,
   2571     0  stevel 						  "%s: Possible SMTP RCPT flood, throttling.",
   2572     0  stevel 						  CurSmtpClient);
   2573     0  stevel 
   2574     0  stevel 					/* To avoid duplicated message */
   2575     0  stevel 					n_badrcpts++;
   2576     0  stevel 				}
   2577     0  stevel 				NBADRCPTS;
   2578     0  stevel 
   2579     0  stevel 				/*
   2580     0  stevel 				**  Don't use exponential backoff for now.
   2581     0  stevel 				**  Some servers will open more connections
   2582     0  stevel 				**  and actually overload the receiver even
   2583     0  stevel 				**  more.
   2584     0  stevel 				*/
   2585     0  stevel 
   2586     0  stevel 				(void) sleep(1);
   2587     0  stevel 			}
   2588     0  stevel 			if (!smtp.sm_gotmail)
   2589     0  stevel 			{
   2590     0  stevel 				usrerr("503 5.0.0 Need MAIL before RCPT");
   2591     0  stevel 				break;
   2592     0  stevel 			}
   2593     0  stevel 			SmtpPhase = "server RCPT";
   2594     0  stevel 		    SM_TRY
   2595     0  stevel 		    {
   2596     0  stevel 			QuickAbort = true;
   2597     0  stevel 			LogUsrErrs = true;
   2598     0  stevel 
   2599     0  stevel 			/* limit flooding of our machine */
   2600     0  stevel 			if (MaxRcptPerMsg > 0 &&
   2601     0  stevel 			    smtp.sm_nrcpts >= MaxRcptPerMsg)
   2602     0  stevel 			{
   2603     0  stevel 				/* sleep(1); / * slow down? */
   2604     0  stevel 				usrerr("452 4.5.3 Too many recipients");
   2605     0  stevel 				goto rcpt_done;
   2606     0  stevel 			}
   2607     0  stevel 
   2608  1658   jbeck 			if (e->e_sendmode != SM_DELIVER
   2609  1658   jbeck #if _FFR_DM_ONE
   2610  1658   jbeck 			    && (NotFirstDelivery || SM_DM_ONE != e->e_sendmode)
   2611  1658   jbeck #endif /* _FFR_DM_ONE */
   2612  1658   jbeck 			   )
   2613     0  stevel 				e->e_flags |= EF_VRFYONLY;
   2614     0  stevel 
   2615     0  stevel #if MILTER
   2616     0  stevel 			/*
   2617  3966   jbeck 			**  Do not expand recipients at RCPT time (in the call
   2618  5402   jbeck 			**  to recipient()) if a milter can delete or reject
   2619  5402   jbeck 			**  a RCPT.  If they are expanded, it is impossible
   2620  5402   jbeck 			**  for removefromlist() to figure out the expanded
   2621  5402   jbeck 			**  members of the original recipient and mark them
   2622  5402   jbeck 			**  as QS_DONTSEND.
   2623  5402   jbeck 			*/
   2624  5402   jbeck 
   2625  5402   jbeck 			if (!(smtp.sm_milterlist && smtp.sm_milterize &&
   2626  5402   jbeck 			      !bitset(EF_DISCARD, e->e_flags)) &&
   2627  5402   jbeck 			    (smtp.sm_milters.mis_flags &
   2628  5402   jbeck 			     (MIS_FL_DEL_RCPT|MIS_FL_REJ_RCPT)) != 0)
   2629  5402   jbeck 				e->e_flags |= EF_VRFYONLY;
   2630  3544   jbeck 			milter_cmd_done = false;
   2631  3544   jbeck 			milter_cmd_safe = false;
   2632     0  stevel #endif /* MILTER */
   2633     0  stevel 
   2634     0  stevel 			p = skipword(p, "to");
   2635     0  stevel 			if (p == NULL)
   2636     0  stevel 				goto rcpt_done;
   2637     0  stevel 			macdefine(&e->e_macro, A_PERM,
   2638     0  stevel 				macid("{addr_type}"), "e r");
   2639     0  stevel 			a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', &delimptr,
   2640     0  stevel 				      e, true);
   2641     0  stevel 			macdefine(&e->e_macro, A_PERM,
   2642     0  stevel 				macid("{addr_type}"), NULL);
   2643     0  stevel 			if (Errors > 0)
   2644     0  stevel 				goto rcpt_done;
   2645     0  stevel 			if (a == NULL)
   2646     0  stevel 			{
   2647     0  stevel 				usrerr("501 5.0.0 Missing recipient");
   2648     0  stevel 				goto rcpt_done;
   2649     0  stevel 			}
   2650     0  stevel 
   2651     0  stevel 			if (delimptr != NULL && *delimptr != '\0')
   2652     0  stevel 				*delimptr++ = '\0';
   2653     0  stevel 
   2654     0  stevel 			/* put resulting triple from parseaddr() into macros */
   2655     0  stevel 			if (a->q_mailer != NULL)
   2656     0  stevel 				macdefine(&e->e_macro, A_PERM,
   2657     0  stevel 					macid("{rcpt_mailer}"),
   2658     0  stevel 					a->q_mailer->m_name);
   2659     0  stevel 			else
   2660     0  stevel 				macdefine(&e->e_macro, A_PERM,
   2661     0  stevel 					macid("{rcpt_mailer}"), NULL);
   2662     0  stevel 			if (a->q_host != NULL)
   2663     0  stevel 				macdefine(&e->e_macro, A_PERM,
   2664     0  stevel 					macid("{rcpt_host}"), a->q_host);
   2665     0  stevel 			else
   2666     0  stevel 				macdefine(&e->e_macro, A_PERM,
   2667     0  stevel 					macid("{rcpt_host}"), "localhost");
   2668     0  stevel 			if (a->q_user != NULL)
   2669     0  stevel 				macdefine(&e->e_macro, A_PERM,
   2670     0  stevel 					macid("{rcpt_addr}"), a->q_user);
   2671     0  stevel 			else
   2672     0  stevel 				macdefine(&e->e_macro, A_PERM,
   2673     0  stevel 					macid("{rcpt_addr}"), NULL);
   2674     0  stevel 			if (Errors > 0)
   2675     0  stevel 				goto rcpt_done;
   2676     0  stevel 
   2677     0  stevel 			/* now parse ESMTP arguments */
   2678     0  stevel 			addr = p;
   2679  3544   jbeck 			parse_esmtp_args(e, a, p, delimptr, "RCPT", args,
   2680  3544   jbeck 					rcpt_esmtp_args);
   2681     0  stevel 			if (Errors > 0)
   2682     0  stevel 				goto rcpt_done;
   2683  3966   jbeck 
   2684  3966   jbeck #if MILTER
   2685  3966   jbeck 			/*
   2686  3966   jbeck 			**  rscheck() can trigger an "exception"
   2687  3966   jbeck 			**  in which case the execution continues at
   2688  3966   jbeck 			**  SM_EXCEPT(exc, "[!F]*")
   2689  3966   jbeck 			**  This means milter_cmd_safe is not set
   2690  3966   jbeck 			**  and hence milter is not invoked.
   2691  3966   jbeck 			**  Would it be "safe" to change that, i.e., use
   2692  3966   jbeck 			**  milter_cmd_safe = true;
   2693  3966   jbeck 			**  here so a milter is informed (if requested)
   2694  3966   jbeck 			**  about RCPTs that are rejected by check_rcpt?
   2695  3966   jbeck 			*/
   2696  3966   jbeck # if _FFR_MILTER_CHECK_REJECTIONS_TOO
   2697  3966   jbeck 			milter_cmd_safe = true;
   2698  3966   jbeck # endif
   2699  3966   jbeck #endif
   2700     0  stevel 
   2701     0  stevel 			/* do config file checking of the recipient */
   2702     0  stevel 			macdefine(&e->e_macro, A_PERM,
   2703     0  stevel 				macid("{addr_type}"), "e r");
   2704     0  stevel 			if (rscheck("check_rcpt", addr,
   2705     0  stevel 				    NULL, e, RSF_RMCOMM|RSF_COUNT, 3,
   2706  3544   jbeck 				    NULL, e->e_id, p_addr_st) != EX_OK ||
   2707     0  stevel 			    Errors > 0)
   2708     0  stevel 				goto rcpt_done;
   2709     0  stevel 			macdefine(&e->e_macro, A_PERM,
   2710     0  stevel 				macid("{addr_type}"), NULL);
   2711     0  stevel 
   2712     0  stevel 			/* If discarding, don't bother to verify user */
   2713     0  stevel 			if (bitset(EF_DISCARD, e->e_flags))
   2714     0  stevel 				a->q_state = QS_VERIFIED;
   2715  3544   jbeck #if MILTER
   2716  3544   jbeck 			milter_cmd_safe = true;
   2717  3544   jbeck #endif
   2718     0  stevel 
   2719     0  stevel 			/* save in recipient list after ESMTP mods */
   2720     0  stevel 			a = recipient(a, &e->e_sendqueue, 0, e);
   2721  3544   jbeck 			/* may trigger exception... */
   2722  3966   jbeck 
   2723  3966   jbeck #if MILTER
   2724  3966   jbeck 			milter_rcpt_added = true;
   2725  3966   jbeck #endif
   2726  3544   jbeck 
   2727  3544   jbeck 			if(!(Errors > 0) && QS_IS_BADADDR(a->q_state))
   2728  3544   jbeck 			{
   2729  3544   jbeck 				/* punt -- should keep message in ADDRESS.... */
   2730  3544   jbeck 				usrerr("550 5.1.1 Addressee unknown");
   2731  3544   jbeck 			}
   2732  3544   jbeck 
   2733  3544   jbeck #if MILTER
   2734  3544   jbeck 		rcpt_done:
   2735  3544   jbeck 			if (smtp.sm_milterlist && smtp.sm_milterize &&
   2736  3544   jbeck 			    !bitset(EF_DISCARD, e->e_flags))
   2737  3544   jbeck 			{
   2738  3544   jbeck 				char state;
   2739  3544   jbeck 				char *response;
   2740  3544   jbeck 
   2741  3544   jbeck 				/* how to get the error codes? */
   2742  3544   jbeck 				if (Errors > 0)
   2743  3544   jbeck 				{
   2744  3544   jbeck 					macdefine(&e->e_macro, A_PERM,
   2745  3544   jbeck 						macid("{rcpt_mailer}"),
   2746  3544   jbeck 						"error");
   2747  3544   jbeck 					if (a != NULL &&
   2748  3544   jbeck 					    a->q_status != NULL &&
   2749  3544   jbeck 					    a->q_rstatus != NULL)
   2750  3544   jbeck 					{
   2751  3544   jbeck 						macdefine(&e->e_macro, A_PERM,
   2752  3544   jbeck 							macid("{rcpt_host}"),
   2753  3544   jbeck 							a->q_status);
   2754  3544   jbeck 						macdefine(&e->e_macro, A_PERM,
   2755  3544   jbeck 							macid("{rcpt_addr}"),
   2756  3544   jbeck 							a->q_rstatus);
   2757  3544   jbeck 					}
   2758  3544   jbeck 					else
   2759  3544   jbeck 					{
   2760  3544   jbeck 						if (addr_st.q_host != NULL)
   2761  3544   jbeck 							macdefine(&e->e_macro,
   2762  3544   jbeck 								A_PERM,
   2763  3544   jbeck 								macid("{rcpt_host}"),
   2764  3544   jbeck 								addr_st.q_host);
   2765  3544   jbeck 						if (addr_st.q_user != NULL)
   2766  3544   jbeck 							macdefine(&e->e_macro,
   2767  3544   jbeck 								A_PERM,
   2768  3544   jbeck 								macid("{rcpt_addr}"),
   2769  3544   jbeck 								addr_st.q_user);
   2770  3544   jbeck 					}
   2771  3544   jbeck 				}
   2772  3544   jbeck 
   2773  3544   jbeck 				response = milter_envrcpt(args, e, &state,
   2774  3544   jbeck 							Errors > 0);
   2775  3544   jbeck 				milter_cmd_done = true;
   2776  3544   jbeck 				MILTER_REPLY("to");
   2777  3544   jbeck 			}
   2778  3544   jbeck #endif /* MILTER */
   2779     0  stevel 
   2780     0  stevel 			/* no errors during parsing, but might be a duplicate */
   2781     0  stevel 			e->e_to = a->q_paddr;
   2782  3544   jbeck 			if (!(Errors > 0) && !QS_IS_BADADDR(a->q_state))
   2783     0  stevel 			{
   2784     0  stevel 				if (smtp.sm_nrcpts == 0)
   2785     0  stevel 					initsys(e);
   2786     0  stevel 				message("250 2.1.5 Recipient ok%s",
   2787     0  stevel 					QS_IS_QUEUEUP(a->q_state) ?
   2788     0  stevel 						" (will queue)" : "");
   2789     0  stevel 				smtp.sm_nrcpts++;
   2790     0  stevel 			}
   2791  3544   jbeck 
   2792  3544   jbeck 			/* Is this needed? */
   2793  3544   jbeck #if !MILTER
   2794  3544   jbeck 		rcpt_done:
   2795  3544   jbeck #endif /* !MILTER */
   2796  3544   jbeck 			macdefine(&e->e_macro, A_PERM,
   2797  3544   jbeck 				macid("{rcpt_mailer}"), NULL);
   2798  3544   jbeck 			macdefine(&e->e_macro, A_PERM,
   2799  3544   jbeck 				macid("{rcpt_host}"), NULL);
   2800  3544   jbeck 			macdefine(&e->e_macro, A_PERM,
   2801  3544   jbeck 				macid("{rcpt_addr}"), NULL);
   2802  3544   jbeck 			macdefine(&e->e_macro, A_PERM,
   2803  3544   jbeck 				macid("{dsn_notify}"), NULL);
   2804  3544   jbeck 
   2805     0  stevel 			if (Errors > 0)
   2806     0  stevel 			{
   2807     0  stevel 				++n_badrcpts;
   2808     0  stevel 				NBADRCPTS;
   2809     0  stevel 			}
   2810     0  stevel 		    }
   2811     0  stevel 		    SM_EXCEPT(exc, "[!F]*")
   2812     0  stevel 		    {
   2813     0  stevel 			/* An exception occurred while processing RCPT */
   2814     0  stevel 			e->e_flags &= ~(EF_FATALERRS|EF_PM_NOTIFY);
   2815     0  stevel 			++n_badrcpts;
   2816     0  stevel 			NBADRCPTS;
   2817  3544   jbeck #if MILTER
   2818  3544   jbeck 			if (smtp.sm_milterlist && smtp.sm_milterize &&
   2819  3544   jbeck 			    !bitset(EF_DISCARD, e->e_flags) &&
   2820  3544   jbeck 			    !milter_cmd_done && milter_cmd_safe)
   2821  3544   jbeck 			{
   2822  3544   jbeck 				char state;
   2823  3544   jbeck 				char *response;
   2824  3544   jbeck 
   2825  3544   jbeck 				macdefine(&e->e_macro, A_PERM,
   2826  3544   jbeck 					macid("{rcpt_mailer}"), "error");
   2827  3544   jbeck 
   2828  3544   jbeck 				/* how to get the error codes? */
   2829  3544   jbeck 				if (addr_st.q_host != NULL)
   2830  3544   jbeck 					macdefine(&e->e_macro, A_PERM,
   2831  3544   jbeck 						macid("{rcpt_host}"),
   2832  3544   jbeck 						addr_st.q_host);
   2833  3544   jbeck 				else if (a != NULL && a->q_status != NULL)
   2834  3544   jbeck 					macdefine(&e->e_macro, A_PERM,
   2835  3544   jbeck 						macid("{rcpt_host}"),
   2836  3544   jbeck 						a->q_status);
   2837  3544   jbeck 
   2838  3544   jbeck 				if (addr_st.q_user != NULL)
   2839  3544   jbeck 					macdefine(&e->e_macro, A_PERM,
   2840  3544   jbeck 						macid("{rcpt_addr}"),
   2841  3544   jbeck 						addr_st.q_user);
   2842  3544   jbeck 				else if (a != NULL && a->q_rstatus != NULL)
   2843  3544   jbeck 					macdefine(&e->e_macro, A_PERM,
   2844  3544   jbeck 						macid("{rcpt_addr}"),
   2845  3544   jbeck 						a->q_rstatus);
   2846  3544   jbeck 
   2847  3544   jbeck 				response = milter_envrcpt(args, e, &state,
   2848  3544   jbeck 							true);
   2849  3544   jbeck 				milter_cmd_done = true;
   2850  3544   jbeck 				MILTER_REPLY("to");
   2851  3544   jbeck 				macdefine(&e->e_macro, A_PERM,
   2852  3544   jbeck 					macid("{rcpt_mailer}"), NULL);
   2853  3544   jbeck 				macdefine(&e->e_macro, A_PERM,
   2854  3544   jbeck 					macid("{rcpt_host}"), NULL);
   2855  3544   jbeck 				macdefine(&e->e_macro, A_PERM,
   2856  3544   jbeck 					macid("{rcpt_addr}"), NULL);
   2857  3966   jbeck 			}
   2858  3966   jbeck 			if (smtp.sm_milterlist && smtp.sm_milterize &&
   2859  3966   jbeck 			    milter_rcpt_added && milter_cmd_done &&
   2860  3966   jbeck 			    milter_cmd_fail)
   2861  3966   jbeck 			{
   2862  3966   jbeck 				(void) removefromlist(addr, &e->e_sendqueue, e);
   2863  3966   jbeck 				milter_cmd_fail = false;
   2864  5402   jbeck 				if (smtp.sm_e_nrcpts_orig < e->e_nrcpts)
   2865  5402   jbeck 					e->e_nrcpts = smtp.sm_e_nrcpts_orig;
   2866  3544   jbeck 			}
   2867  3544   jbeck #endif /* MILTER */
   2868     0  stevel 		    }
   2869     0  stevel 		    SM_END_TRY
   2870     0  stevel 			break;
   2871     0  stevel 
   2872     0  stevel 		  case CMDDATA:		/* data -- text of mail */
   2873     0  stevel 			DELAY_CONN("DATA");
   2874     0  stevel 			if (!smtp_data(&smtp, e))
   2875     0  stevel 				goto doquit;
   2876     0  stevel 			break;
   2877     0  stevel 
   2878     0  stevel 		  case CMDRSET:		/* rset -- reset state */
   2879     0  stevel 			if (tTd(94, 100))
   2880     0  stevel 				message("451 4.0.0 Test failure");
   2881     0  stevel 			else
   2882     0  stevel 				message("250 2.0.0 Reset state");
   2883     0  stevel 			CLEAR_STATE(cmdbuf);
   2884     0  stevel 			break;
   2885     0  stevel 
   2886     0  stevel 		  case CMDVRFY:		/* vrfy -- verify address */
   2887     0  stevel 		  case CMDEXPN:		/* expn -- expand address */
   2888     0  stevel 			vrfy = c->cmd_code == CMDVRFY;
   2889     0  stevel 			DELAY_CONN(vrfy ? "VRFY" : "EXPN");
   2890     0  stevel 			if (tempfail)
   2891     0  stevel 			{
   2892     0  stevel 				if (LogLevel > 9)
   2893     0  stevel 					sm_syslog(LOG_INFO, e->e_id,
   2894     0  stevel 						  "SMTP %s command (%.100s) from %s tempfailed (due to previous checks)",
   2895     0  stevel 						  vrfy ? "VRFY" : "EXPN",
   2896     0  stevel 						  p, CurSmtpClient);
   2897     0  stevel 
   2898     0  stevel 				/* RFC 821 doesn't allow 4xy reply code */
   2899     0  stevel 				usrerr("550 5.7.1 Please try again later");
   2900     0  stevel 				break;
   2901     0  stevel 			}
   2902     0  stevel 			wt = checksmtpattack(&n_verifies, MAXVRFYCOMMANDS,
   2903     0  stevel 					     false, vrfy ? "VRFY" : "EXPN", e);
   2904     0  stevel 			STOP_IF_ATTACK(wt);
   2905     0  stevel 			previous = curtime();
   2906     0  stevel 			if ((vrfy && bitset(PRIV_NOVRFY, PrivacyFlags)) ||
   2907     0  stevel 			    (!vrfy && !bitset(SRV_OFFER_EXPN, features)))
   2908     0  stevel 			{
   2909     0  stevel 				if (vrfy)
   2910     0  stevel 					message("252 2.5.2 Cannot VRFY user; try RCPT to attempt delivery (or try finger)");
   2911     0  stevel 				else
   2912     0  stevel 					message("502 5.7.0 Sorry, we do not allow this operation");
   2913     0  stevel 				if (LogLevel > 5)
   2914     0  stevel 					sm_syslog(LOG_INFO, e->e_id,
   2915     0  stevel 						  "%s: %s [rejected]",
   2916     0  stevel 						  CurSmtpClient,
   2917     0  stevel 						  shortenstring(inp, MAXSHORTSTR));
   2918     0  stevel 				break;
   2919     0  stevel 			}
   2920     0  stevel 			else if (!gothello &&
   2921     0  stevel 				 bitset(vrfy ? PRIV_NEEDVRFYHELO : PRIV_NEEDEXPNHELO,
   2922     0  stevel 						PrivacyFlags))
   2923     0  stevel 			{
   2924     0  stevel 				usrerr("503 5.0.0 I demand that you introduce yourself first");
   2925     0  stevel 				break;
   2926     0  stevel 			}
   2927     0  stevel 			if (Errors > 0)
   2928     0  stevel 				break;
   2929     0  stevel 			if (LogLevel > 5)
   2930     0  stevel 				sm_syslog(LOG_INFO, e->e_id, "%s: %s",
   2931     0  stevel 					  CurSmtpClient,
   2932     0  stevel 					  shortenstring(inp, MAXSHORTSTR));
   2933     0  stevel 		    SM_TRY
   2934     0  stevel 		    {
   2935     0  stevel 			QuickAbort = true;
   2936     0  stevel 			vrfyqueue = NULL;
   2937     0  stevel 			if (vrfy)
   2938     0  stevel 				e->e_flags |= EF_VRFYONLY;
   2939     0  stevel 			while (*p != '\0' && isascii(*p) && isspace(*p))
   2940     0  stevel 				p++;
   2941     0  stevel 			if (*p == '\0')
   2942     0  stevel 			{
   2943     0  stevel 				usrerr("501 5.5.2 Argument required");
   2944     0  stevel 			}
   2945     0  stevel 			else
   2946     0  stevel 			{
   2947     0  stevel 				/* do config file checking of the address */
   2948     0  stevel 				if (rscheck(vrfy ? "check_vrfy" : "check_expn",
   2949     0  stevel 					    p, NULL, e, RSF_RMCOMM,
   2950  3544   jbeck 					    3, NULL, NOQID, NULL) != EX_OK ||
   2951     0  stevel 				    Errors > 0)
   2952     0  stevel 					sm_exc_raisenew_x(&EtypeQuickAbort, 1);
   2953     0  stevel 				(void) sendtolist(p, NULLADDR, &vrfyqueue, 0, e);
   2954     0  stevel 			}
   2955     0  stevel 			if (wt > 0)
   2956     0  stevel 			{
   2957     0  stevel 				time_t t;
   2958     0  stevel 
   2959     0  stevel 				t = wt - (curtime() - previous);
   2960     0  stevel 				if (t > 0)
   2961     0  stevel 					(void) sleep(t);
   2962     0  stevel 			}
   2963     0  stevel 			if (Errors > 0)
   2964     0  stevel 				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
   2965     0  stevel 			if (vrfyqueue == NULL)
   2966     0  stevel 			{
   2967     0  stevel 				usrerr("554 5.5.2 Nothing to %s", vrfy ? "VRFY" : "EXPN");
   2968     0  stevel 			}
   2969     0  stevel 			while (vrfyqueue != NULL)
   2970     0  stevel 			{
   2971     0  stevel 				if (!QS_IS_UNDELIVERED(vrfyqueue->q_state))
   2972     0  stevel 				{
   2973     0  stevel 					vrfyqueue = vrfyqueue->q_next;
   2974     0  stevel 					continue;
   2975     0  stevel 				}
   2976     0  stevel 
   2977     0  stevel 				/* see if there is more in the vrfy list */
   2978     0  stevel 				a = vrfyqueue;
   2979     0  stevel 				while ((a = a->q_next) != NULL &&
   2980     0  stevel 				       (!QS_IS_UNDELIVERED(a->q_state)))
   2981     0  stevel 					continue;
   2982     0  stevel 				printvrfyaddr(vrfyqueue, a == NULL, vrfy);
   2983     0  stevel 				vrfyqueue = a;
   2984     0  stevel 			}
   2985     0  stevel 		    }
   2986     0  stevel 		    SM_EXCEPT(exc, "[!F]*")
   2987     0  stevel 		    {
   2988     0  stevel 			/*
   2989     0  stevel 			**  An exception occurred while processing VRFY/EXPN
   2990     0  stevel 			*/
   2991     0  stevel 
   2992     0  stevel 			sm_exc_free(exc);
   2993     0  stevel 			goto undo;
   2994     0  stevel 		    }
   2995     0  stevel 		    SM_END_TRY
   2996     0  stevel 			break;
   2997     0  stevel 
   2998     0  stevel 		  case CMDETRN:		/* etrn -- force queue flush */
   2999     0  stevel 			DELAY_CONN("ETRN");
   3000     0  stevel 
   3001     0  stevel 			/* Don't leak queue information via debug flags */
   3002     0  stevel 			if (!bitset(SRV_OFFER_ETRN, features) || UseMSP ||
   3003     0  stevel 			    (RealUid != 0 && RealUid != TrustedUid &&
   3004     0  stevel 			     OpMode == MD_SMTP))
   3005     0  stevel 			{
   3006     0  stevel 				/* different message for MSA ? */
   3007     0  stevel 				message("502 5.7.0 Sorry, we do not allow this operation");
   3008     0  stevel 				if (LogLevel > 5)
   3009     0  stevel 					sm_syslog(LOG_INFO, e->e_id,
   3010     0  stevel 						  "%s: %s [rejected]",
   3011     0  stevel 						  CurSmtpClient,
   3012     0  stevel 						  shortenstring(inp, MAXSHORTSTR));
   3013     0  stevel 				break;
   3014     0  stevel 			}
   3015     0  stevel 			if (tempfail)
   3016     0  stevel 			{
   3017     0  stevel 				if (LogLevel > 9)
   3018     0  stevel 					sm_syslog(LOG_INFO, e->e_id,
   3019     0  stevel 						  "SMTP ETRN command (%.100s) from %s tempfailed (due to previous checks)",
   3020     0  stevel 						  p, CurSmtpClient);
   3021     0  stevel 				usrerr(MSG_TEMPFAIL);
   3022     0  stevel 				break;
   3023     0  stevel 			}
   3024     0  stevel 
   3025     0  stevel 			if (strlen(p) <= 0)
   3026     0  stevel 			{
   3027     0  stevel 				usrerr("500 5.5.2 Parameter required");
   3028     0  stevel 				break;
   3029     0  stevel 			}
   3030     0  stevel 
   3031     0  stevel 			/* crude way to avoid denial-of-service attacks */
   3032     0  stevel 			STOP_IF_ATTACK(checksmtpattack(&n_etrn, MAXETRNCOMMANDS,
   3033     0  stevel 							true, "ETRN", e));
   3034     0  stevel 
   3035     0  stevel 			/*
   3036     0  stevel 			**  Do config file checking of the parameter.
   3037     0  stevel 			**  Even though we have srv_features now, we still
   3038     0  stevel 			**  need this ruleset because the former is called
   3039     0  stevel 			**  when the connection has been established, while
   3040     0  stevel 			**  this ruleset is called when the command is
   3041     0  stevel 			**  actually issued and therefore has all information
   3042     0  stevel 			**  available to make a decision.
   3043     0  stevel 			*/
   3044     0  stevel 
   3045     0  stevel 			if (rscheck("check_etrn", p, NULL, e,
   3046  3544   jbeck 				    RSF_RMCOMM, 3, NULL, NOQID, NULL)
   3047  3544   jbeck 								!= EX_OK ||
   3048     0  stevel 			    Errors > 0)
   3049     0  stevel 				break;
   3050     0  stevel 
   3051     0  stevel 			if (LogLevel > 5)
   3052     0  stevel 				sm_syslog(LOG_INFO, e->e_id,
   3053     0  stevel 					  "%s: ETRN %s", CurSmtpClient,
   3054     0  stevel 					  shortenstring(p, MAXSHORTSTR));
   3055     0  stevel 
   3056     0  stevel 			id = p;
   3057     0  stevel 			if (*id == '#')
   3058     0  stevel 			{
   3059     0  stevel 				int i, qgrp;
   3060     0  stevel 
   3061     0  stevel 				id++;
   3062     0  stevel 				qgrp = name2qid(id);
   3063     0  stevel 				if (!ISVALIDQGRP(qgrp))
   3064     0  stevel 				{
   3065     0  stevel 					usrerr("459 4.5.4 Queue %s unknown",
   3066     0  stevel 					       id);
   3067     0  stevel 					break;
   3068     0  stevel 				}
   3069     0  stevel 				for (i = 0; i < NumQueue && Queue[i] != NULL;
   3070     0  stevel 				     i++)
   3071     0  stevel 					Queue[i]->qg_nextrun = (time_t) -1;
   3072     0  stevel 				Queue[qgrp]->qg_nextrun = 0;
   3073     0  stevel 				ok = run_work_group(Queue[qgrp]->qg_wgrp,
   3074     0  stevel 						    RWG_FORK|RWG_FORCE);
   3075     0  stevel 				if (ok && Errors == 0)
   3076     0  stevel 					message("250 2.0.0 Queuing for queue group %s started", id);
   3077     0  stevel 				break;
   3078     0  stevel 			}
   3079     0  stevel 
   3080     0  stevel 			if (*id == '@')
   3081     0  stevel 				id++;
   3082     0  stevel 			else
   3083     0  stevel 				*--id = '@';
   3084     0  stevel 
   3085     0  stevel 			new = (QUEUE_CHAR *) sm_malloc(sizeof(QUEUE_CHAR));
   3086     0  stevel 			if (new == NULL)
   3087     0  stevel 			{
   3088     0  stevel 				syserr("500 5.5.0 ETRN out of memory");
   3089     0  stevel 				break;
   3090     0  stevel 			}
   3091     0  stevel 			new->queue_match = id;
   3092     0  stevel 			new->queue_negate = false;
   3093     0  stevel 			new->queue_next = NULL;
   3094     0  stevel 			QueueLimitRecipient = new;
   3095     0  stevel 			ok = runqueue(true, false, false, true);
   3096     0  stevel 			sm_free(QueueLimitRecipient); /* XXX */
   3097     0  stevel 			QueueLimitRecipient = NULL;
   3098     0  stevel 			if (ok && Errors == 0)
   3099     0  stevel 				message("250 2.0.0 Queuing for node %s started", p);
   3100     0  stevel 			break;
   3101     0  stevel 
   3102     0  stevel 		  case CMDHELP:		/* help -- give user info */
   3103     0  stevel 			DELAY_CONN("HELP");
   3104     0  stevel 			help(p, e);
   3105     0  stevel 			break;
   3106     0  stevel 
   3107     0  stevel 		  case CMDNOOP:		/* noop -- do nothing */
   3108     0  stevel 			DELAY_CONN("NOOP");
   3109  1658   jbeck 			STOP_IF_ATTACK(checksmtpattack(&n_noop, MaxNOOPCommands,
   3110     0  stevel 							true, "NOOP", e));
   3111     0  stevel 			message("250 2.0.0 OK");
   3112     0  stevel 			break;
   3113     0  stevel 
   3114     0  stevel 		  case CMDQUIT:		/* quit -- leave mail */
   3115     0  stevel 			message("221 2.0.0 %s closing connection", MyHostName);
   3116     0  stevel #if PIPELINING
   3117     0  stevel 			(void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
   3118     0  stevel #endif /* PIPELINING */
   3119     0  stevel 
   3120     0  stevel 			if (smtp.sm_nrcpts > 0)
   3121     0  stevel 				logundelrcpts(e, "aborted by sender", 9, false);
   3122     0  stevel 
   3123     0  stevel 			/* arrange to ignore any current send list */
   3124     0  stevel 			e->e_sendqueue = NULL;
   3125     0  stevel 
   3126     0  stevel #if STARTTLS
   3127     0  stevel 			/* shutdown TLS connection */
   3128     0  stevel 			if (tls_active)
   3129     0  stevel 			{
   3130     0  stevel 				(void) endtls(srv_ssl, "server");
   3131     0  stevel 				tls_active = false;
   3132     0  stevel 			}
   3133     0  stevel #endif /* STARTTLS */
   3134     0  stevel #if SASL
   3135     0  stevel 			if (authenticating == SASL_IS_AUTH)
   3136     0  stevel 			{
   3137     0  stevel 				sasl_dispose(&conn);
   3138     0  stevel 				authenticating = SASL_NOT_AUTH;
   3139     0  stevel 				/* XXX sasl_done(); this is a child */
   3140     0  stevel 			}
   3141     0  stevel #endif /* SASL */
   3142     0  stevel 
   3143     0  stevel doquit:
   3144     0  stevel 			/* avoid future 050 messages */
   3145     0  stevel 			disconnect(1, e);
   3146     0  stevel 
   3147     0  stevel #if MILTER
   3148     0  stevel 			/* close out milter filters */
   3149     0  stevel 			milter_quit(e);
   3150     0  stevel #endif /* MILTER */
   3151     0  stevel 
   3152     0  stevel 			if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
   3153     0  stevel 				logsender(e, NULL);
   3154     0  stevel 			e->e_flags &= ~EF_LOGSENDER;
   3155     0  stevel 
   3156     0  stevel 			if (lognullconnection && LogLevel > 5 &&
   3157     0  stevel 			    nullserver == NULL)
   3158     0  stevel 			{
   3159     0  stevel 				char *d;
   3160     0  stevel 
   3161     0  stevel 				d = macvalue(macid("{daemon_name}"), e);
   3162     0  stevel 				if (d == NULL)
   3163     0  stevel 					d = "stdin";
   3164     0  stevel 
   3165     0  stevel 				/*
   3166     0  stevel 				**  even though this id is "bogus", it makes
   3167     0  stevel 				**  it simpler to "grep" related events, e.g.,
   3168     0  stevel 				**  timeouts for the same connection.
   3169     0  stevel 				*/
   3170     0  stevel 
   3171     0  stevel 				sm_syslog(LOG_INFO, e->e_id,
   3172     0  stevel 					  "%s did not issue MAIL/EXPN/VRFY/ETRN during connection to %s",
   3173     0  stevel 					  CurSmtpClient, d);
   3174     0  stevel 			}
   3175     0  stevel 			if (tTd(93, 100))
   3176     0  stevel 			{
   3177     0  stevel 				/* return to handle next connection */
   3178     0  stevel 				return;
   3179     0  stevel 			}
   3180     0  stevel 			finis(true, true, ExitStat);
   3181     0  stevel 			/* NOTREACHED */
   3182  1658   jbeck 
   3183  1658   jbeck 			/* just to avoid bogus warning from some compilers */
   3184  1658   jbeck 			exit(EX_OSERR);
   3185     0  stevel 
   3186     0  stevel 		  case CMDVERB:		/* set verbose mode */
   3187     0  stevel 			DELAY_CONN("VERB");
   3188     0  stevel 			if (!bitset(SRV_OFFER_EXPN, features) ||
   3189     0  stevel 			    !bitset(SRV_OFFER_VERB, features))
   3190     0  stevel 			{
   3191     0  stevel 				/* this would give out the same info */
   3192     0  stevel 				message("502 5.7.0 Verbose unavailable");
   3193     0  stevel 				break;
   3194     0  stevel 			}
   3195  1658   jbeck 			STOP_IF_ATTACK(checksmtpattack(&n_noop, MaxNOOPCommands,
   3196     0  stevel 							true, "VERB", e));
   3197     0  stevel 			Verbose = 1;
   3198     0  stevel 			set_delivery_mode(SM_DELIVER, e);
   3199     0  stevel 			message("250 2.0.0 Verbose mode");
   3200     0  stevel 			break;
   3201     0  stevel 
   3202     0  stevel #if SMTPDEBUG
   3203     0  stevel 		  case CMDDBGQSHOW:	/* show queues */
   3204     0  stevel 			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
   3205     0  stevel 					     "Send Queue=");
   3206     0  stevel 			printaddr(smioout, e->e_sendqueue, true);
   3207     0  stevel 			break;
   3208     0  stevel 
   3209     0  stevel 		  case CMDDBGDEBUG:	/* set debug mode */
   3210  3544   jbeck 			tTsetup(tTdvect, sizeof(tTdvect), "0-99.1");
   3211     0  stevel 			tTflag(p);
   3212     0  stevel 			message("200 2.0.0 Debug set");
   3213     0  stevel 			break;
   3214     0  stevel 
   3215     0  stevel #else /* SMTPDEBUG */
   3216     0  stevel 		  case CMDDBGQSHOW:	/* show queues */
   3217     0  stevel 		  case CMDDBGDEBUG:	/* set debug mode */
   3218     0  stevel #endif /* SMTPDEBUG */
   3219     0  stevel 		  case CMDLOGBOGUS:	/* bogus command */
   3220     0  stevel 			DELAY_CONN("Bogus");
   3221     0  stevel 			if (LogLevel > 0)
   3222     0  stevel