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