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