xref: /freebsd/contrib/sendmail/src/srvrsmtp.c (revision 6990ffd8a95caaba6858ad44ff1b3157d1efba8f)
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
19 static char id[] = "@(#)$Id: srvrsmtp.c,v 8.471.2.2.2.78 2001/06/26 18:52:21 gshapiro Exp $ (with SMTP)";
20 # else /* SMTP */
21 static char id[] = "@(#)$Id: srvrsmtp.c,v 8.471.2.2.2.78 2001/06/26 18:52:21 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)
31 static 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 
42 static SSL	*srv_ssl = NULL;
43 static SSL_CTX	*srv_ctx = NULL;
44 #  if !TLS_NO_RSA
45 static RSA	*rsa = NULL;
46 #  endif /* !TLS_NO_RSA */
47 static bool	tls_ok_srv = FALSE;
48 static 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 
54 static time_t	checksmtpattack __P((volatile int *, int, bool,
55 				     char *, ENVELOPE *));
56 static void	mail_esmtp_args __P((char *, char *, ENVELOPE *));
57 static void	printvrfyaddr __P((ADDRESS *, bool, bool));
58 static void	rcpt_esmtp_args __P((ADDRESS *, char *, char *, ENVELOPE *));
59 static int	runinchild __P((char *, ENVELOPE *));
60 static char	*skipword __P((char *volatile, char *));
61 extern 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 
79 struct 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 
122 static 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 
157 static bool	OneXact = FALSE;	/* one xaction only this run */
158 static 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 
172 void
173 smtp(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 				/* FALLTHROUGH */
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_srv)
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_srv = 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_srv = 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 						sm_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_srv && 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 ||
1529 			     e->e_msgsize < 0))
1530 			{
1531 				usrerr("552 5.2.3 Message size exceeds fixed maximum message size (%ld)",
1532 					MaxMessageSize);
1533 				goto undo_subproc_no_pm;
1534 			}
1535 
1536 			if (!enoughdiskspace(e->e_msgsize, TRUE))
1537 			{
1538 				usrerr("452 4.4.5 Insufficient disk space; try again later");
1539 				goto undo_subproc_no_pm;
1540 			}
1541 			if (Errors > 0)
1542 				goto undo_subproc_no_pm;
1543 
1544 # if _FFR_MILTER
1545 			LogUsrErrs = TRUE;
1546 			if (milterize && !bitset(EF_DISCARD, e->e_flags))
1547 			{
1548 				char state;
1549 				char *response;
1550 
1551 				response = milter_envfrom(args, e, &state);
1552 				switch (state)
1553 				{
1554 				  case SMFIR_REPLYCODE:
1555 					usrerr(response);
1556 					break;
1557 
1558 				  case SMFIR_REJECT:
1559 					usrerr("550 5.7.1 Command rejected");
1560 					break;
1561 
1562 				  case SMFIR_DISCARD:
1563 					e->e_flags |= EF_DISCARD;
1564 					break;
1565 
1566 				  case SMFIR_TEMPFAIL:
1567 					usrerr("451 4.7.1 Please try again later");
1568 					break;
1569 				}
1570 				if (response != NULL)
1571 					sm_free(response);
1572 			}
1573 # endif /* _FFR_MILTER */
1574 			if (Errors > 0)
1575 				goto undo_subproc_no_pm;
1576 
1577 			message("250 2.1.0 Sender ok");
1578 			gotmail = TRUE;
1579 			break;
1580 
1581 		  case CMDRCPT:		/* rcpt -- designate recipient */
1582 			if (!gotmail)
1583 			{
1584 				usrerr("503 5.0.0 Need MAIL before RCPT");
1585 				break;
1586 			}
1587 			SmtpPhase = "server RCPT";
1588 			if (setjmp(TopFrame) > 0)
1589 			{
1590 				e->e_flags &= ~(EF_FATALERRS|EF_PM_NOTIFY);
1591 				break;
1592 			}
1593 			QuickAbort = TRUE;
1594 			LogUsrErrs = TRUE;
1595 
1596 			/* limit flooding of our machine */
1597 			if (MaxRcptPerMsg > 0 && nrcpts >= MaxRcptPerMsg)
1598 			{
1599 				usrerr("452 4.5.3 Too many recipients");
1600 				break;
1601 			}
1602 
1603 			if (e->e_sendmode != SM_DELIVER)
1604 				e->e_flags |= EF_VRFYONLY;
1605 
1606 # if _FFR_MILTER
1607 			/*
1608 			**  If the filter will be deleting recipients,
1609 			**  don't expand them at RCPT time (in the call
1610 			**  to recipient()).  If they are expanded, it
1611 			**  is impossible for removefromlist() to figure
1612 			**  out the expanded members of the original
1613 			**  recipient and mark them as QS_DONTSEND.
1614 			*/
1615 
1616 			if (milter_can_delrcpts())
1617 				e->e_flags |= EF_VRFYONLY;
1618 # endif /* _FFR_MILTER */
1619 
1620 			p = skipword(p, "to");
1621 			if (p == NULL)
1622 				break;
1623 # if _FFR_ADDR_TYPE
1624 			define(macid("{addr_type}", NULL), "e r", e);
1625 # endif /* _FFR_ADDR_TYPE */
1626 			a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', &delimptr, e);
1627 #if _FFR_ADDR_TYPE
1628 			define(macid("{addr_type}", NULL), NULL, e);
1629 #endif /* _FFR_ADDR_TYPE */
1630 			if (Errors > 0)
1631 				break;
1632 			if (a == NULL)
1633 			{
1634 				usrerr("501 5.0.0 Missing recipient");
1635 				break;
1636 			}
1637 
1638 			if (delimptr != NULL && *delimptr != '\0')
1639 				*delimptr++ = '\0';
1640 
1641 			/* put resulting triple from parseaddr() into macros */
1642 			if (a->q_mailer != NULL)
1643 				define(macid("{rcpt_mailer}", NULL),
1644 				       a->q_mailer->m_name, e);
1645 			else
1646 				define(macid("{rcpt_mailer}", NULL),
1647 				       NULL, e);
1648 			if (a->q_host != NULL)
1649 				define(macid("{rcpt_host}", NULL),
1650 				       a->q_host, e);
1651 			else
1652 				define(macid("{rcpt_host}", NULL),
1653 				       "localhost", e);
1654 			if (a->q_user != NULL)
1655 				define(macid("{rcpt_addr}", NULL),
1656 				       a->q_user, e);
1657 			else
1658 				define(macid("{rcpt_addr}", NULL),
1659 				       NULL, e);
1660 			if (Errors > 0)
1661 				break;
1662 
1663 			/* now parse ESMTP arguments */
1664 			addr = p;
1665 			argno = 0;
1666 			args[argno++] = p;
1667 			p = delimptr;
1668 			while (p != NULL && *p != '\0')
1669 			{
1670 				char *kp;
1671 				char *vp = NULL;
1672 				char *equal = NULL;
1673 
1674 				/* locate the beginning of the keyword */
1675 				while (isascii(*p) && isspace(*p))
1676 					p++;
1677 				if (*p == '\0')
1678 					break;
1679 				kp = p;
1680 
1681 				/* skip to the value portion */
1682 				while ((isascii(*p) && isalnum(*p)) || *p == '-')
1683 					p++;
1684 				if (*p == '=')
1685 				{
1686 					equal = p;
1687 					*p++ = '\0';
1688 					vp = p;
1689 
1690 					/* skip to the end of the value */
1691 					while (*p != '\0' && *p != ' ' &&
1692 					       !(isascii(*p) && iscntrl(*p)) &&
1693 					       *p != '=')
1694 						p++;
1695 				}
1696 
1697 				if (*p != '\0')
1698 					*p++ = '\0';
1699 
1700 				if (tTd(19, 1))
1701 					dprintf("RCPT: got arg %s=\"%s\"\n", kp,
1702 						vp == NULL ? "<null>" : vp);
1703 
1704 				rcpt_esmtp_args(a, kp, vp, e);
1705 				if (equal != NULL)
1706 					*equal = '=';
1707 				args[argno++] = kp;
1708 				if (argno >= MAXSMTPARGS - 1)
1709 					usrerr("501 5.5.4 Too many parameters");
1710 				if (Errors > 0)
1711 					break;
1712 			}
1713 			args[argno] = NULL;
1714 			if (Errors > 0)
1715 				break;
1716 
1717 			/* do config file checking of the recipient */
1718 			if (rscheck("check_rcpt", addr,
1719 				    NULL, e, TRUE, TRUE, 4, NULL) != EX_OK ||
1720 			    Errors > 0)
1721 				break;
1722 
1723 # if _FFR_MILTER
1724 			if (milterize && !bitset(EF_DISCARD, e->e_flags))
1725 			{
1726 				char state;
1727 				char *response;
1728 
1729 				response = milter_envrcpt(args, e, &state);
1730 				switch (state)
1731 				{
1732 				  case SMFIR_REPLYCODE:
1733 					usrerr(response);
1734 					break;
1735 
1736 				  case SMFIR_REJECT:
1737 					usrerr("550 5.7.1 Command rejected");
1738 					break;
1739 
1740 				  case SMFIR_DISCARD:
1741 					e->e_flags |= EF_DISCARD;
1742 					break;
1743 
1744 				  case SMFIR_TEMPFAIL:
1745 					usrerr("451 4.7.1 Please try again later");
1746 					break;
1747 				}
1748 				if (response != NULL)
1749 					sm_free(response);
1750 			}
1751 # endif /* _FFR_MILTER */
1752 
1753 			define(macid("{rcpt_mailer}", NULL), NULL, e);
1754 			define(macid("{rcpt_relay}", NULL), NULL, e);
1755 			define(macid("{rcpt_addr}", NULL), NULL, e);
1756 			define(macid("{dsn_notify}", NULL), NULL, e);
1757 			if (Errors > 0)
1758 				break;
1759 
1760 			/* save in recipient list after ESMTP mods */
1761 			a = recipient(a, &e->e_sendqueue, 0, e);
1762 			if (Errors > 0)
1763 				break;
1764 
1765 			/* no errors during parsing, but might be a duplicate */
1766 			e->e_to = a->q_paddr;
1767 			if (!QS_IS_BADADDR(a->q_state))
1768 			{
1769 				if (e->e_queuedir == NOQDIR)
1770 					initsys(e);
1771 				message("250 2.1.5 Recipient ok%s",
1772 					QS_IS_QUEUEUP(a->q_state) ?
1773 						" (will queue)" : "");
1774 				nrcpts++;
1775 			}
1776 			else
1777 			{
1778 				/* punt -- should keep message in ADDRESS.... */
1779 				usrerr("550 5.1.1 Addressee unknown");
1780 			}
1781 			break;
1782 
1783 		  case CMDDATA:		/* data -- text of mail */
1784 			SmtpPhase = "server DATA";
1785 			if (!gotmail)
1786 			{
1787 				usrerr("503 5.0.0 Need MAIL command");
1788 				break;
1789 			}
1790 			else if (nrcpts <= 0)
1791 			{
1792 				usrerr("503 5.0.0 Need RCPT (recipient)");
1793 				break;
1794 			}
1795 
1796 			/* put back discard bit */
1797 			if (discard)
1798 				e->e_flags |= EF_DISCARD;
1799 
1800 			/* check to see if we need to re-expand aliases */
1801 			/* also reset QS_BADADDR on already-diagnosted addrs */
1802 			doublequeue = FALSE;
1803 			for (a = e->e_sendqueue; a != NULL; a = a->q_next)
1804 			{
1805 				if (QS_IS_VERIFIED(a->q_state) &&
1806 				    !bitset(EF_DISCARD, e->e_flags))
1807 				{
1808 					/* need to re-expand aliases */
1809 					doublequeue = TRUE;
1810 				}
1811 				if (QS_IS_BADADDR(a->q_state))
1812 				{
1813 					/* make this "go away" */
1814 					a->q_state = QS_DONTSEND;
1815 				}
1816 			}
1817 
1818 			/* collect the text of the message */
1819 			SmtpPhase = "collect";
1820 			buffer_errors();
1821 			collect(InChannel, TRUE, NULL, e);
1822 
1823 # if _FFR_MILTER
1824 			if (milterize &&
1825 			    Errors <= 0 &&
1826 			    !bitset(EF_DISCARD, e->e_flags))
1827 			{
1828 				char state;
1829 				char *response;
1830 
1831 				response = milter_data(e, &state);
1832 				switch (state)
1833 				{
1834 				  case SMFIR_REPLYCODE:
1835 					usrerr(response);
1836 					break;
1837 
1838 				  case SMFIR_REJECT:
1839 					usrerr("554 5.7.1 Command rejected");
1840 					break;
1841 
1842 				  case SMFIR_DISCARD:
1843 					e->e_flags |= EF_DISCARD;
1844 					break;
1845 
1846 				  case SMFIR_TEMPFAIL:
1847 					usrerr("451 4.7.1 Please try again later");
1848 					break;
1849 				}
1850 				if (response != NULL)
1851 					sm_free(response);
1852 			}
1853 
1854 			/* abort message filters that didn't get the body */
1855 			if (milterize)
1856 				milter_abort(e);
1857 # endif /* _FFR_MILTER */
1858 
1859 			/* redefine message size */
1860 			if ((q = macvalue(macid("{msg_size}", NULL), e))
1861 			    != NULL)
1862 				sm_free(q);
1863 			snprintf(inp, sizeof inp, "%ld", e->e_msgsize);
1864 			define(macid("{msg_size}", NULL), newstr(inp), e);
1865 			if (Errors > 0)
1866 			{
1867 				/* Log who the mail would have gone to */
1868 				if (LogLevel > 8 &&
1869 				    e->e_message != NULL)
1870 				{
1871 					for (a = e->e_sendqueue;
1872 					     a != NULL;
1873 					     a = a->q_next)
1874 					{
1875 						if (!QS_IS_UNDELIVERED(a->q_state))
1876 							continue;
1877 
1878 						e->e_to = a->q_paddr;
1879 						logdelivery(NULL, NULL,
1880 							    a->q_status,
1881 							    e->e_message,
1882 							    NULL,
1883 							    (time_t) 0, e);
1884 					}
1885 					e->e_to = NULL;
1886 				}
1887 				flush_errors(TRUE);
1888 				buffer_errors();
1889 				goto abortmessage;
1890 			}
1891 
1892 			/* make sure we actually do delivery */
1893 			e->e_flags &= ~EF_CLRQUEUE;
1894 
1895 			/* from now on, we have to operate silently */
1896 			buffer_errors();
1897 			e->e_errormode = EM_MAIL;
1898 
1899 			/*
1900 			**  Arrange to send to everyone.
1901 			**	If sending to multiple people, mail back
1902 			**		errors rather than reporting directly.
1903 			**	In any case, don't mail back errors for
1904 			**		anything that has happened up to
1905 			**		now (the other end will do this).
1906 			**	Truncate our transcript -- the mail has gotten
1907 			**		to us successfully, and if we have
1908 			**		to mail this back, it will be easier
1909 			**		on the reader.
1910 			**	Then send to everyone.
1911 			**	Finally give a reply code.  If an error has
1912 			**		already been given, don't mail a
1913 			**		message back.
1914 			**	We goose error returns by clearing error bit.
1915 			*/
1916 
1917 			SmtpPhase = "delivery";
1918 			(void) bftruncate(e->e_xfp);
1919 			id = e->e_id;
1920 
1921 			/*
1922 			**  If a header/body check (header checks or milter)
1923 			**  set EF_DISCARD, don't queueup the message --
1924 			**  that would lose the EF_DISCARD bit and deliver
1925 			**  the message.
1926 			*/
1927 
1928 			if (bitset(EF_DISCARD, e->e_flags))
1929 				doublequeue = FALSE;
1930 
1931 			if (doublequeue)
1932 			{
1933 				/* make sure it is in the queue */
1934 				queueup(e, FALSE);
1935 			}
1936 			else
1937 			{
1938 				/* send to all recipients */
1939 # if NAMED_BIND
1940 				_res.retry = TimeOuts.res_retry[RES_TO_FIRST];
1941 				_res.retrans = TimeOuts.res_retrans[RES_TO_FIRST];
1942 # endif /* NAMED_BIND */
1943 				sendall(e, SM_DEFAULT);
1944 			}
1945 			e->e_to = NULL;
1946 
1947 			/* issue success message */
1948 			message("250 2.0.0 %s Message accepted for delivery", id);
1949 
1950 			/* if we just queued, poke it */
1951 			if (doublequeue &&
1952 			    e->e_sendmode != SM_QUEUE &&
1953 			    e->e_sendmode != SM_DEFER)
1954 			{
1955 				CurrentLA = sm_getla(e);
1956 
1957 				if (!shouldqueue(e->e_msgpriority, e->e_ctime))
1958 				{
1959 					/* close all the queue files */
1960 					closexscript(e);
1961 					if (e->e_dfp != NULL)
1962 						(void) bfclose(e->e_dfp);
1963 					e->e_dfp = NULL;
1964 					unlockqueue(e);
1965 
1966 					(void) dowork(e->e_queuedir, id,
1967 						      TRUE, TRUE, e);
1968 				}
1969 			}
1970 
1971   abortmessage:
1972 			if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
1973 				logsender(e, NULL);
1974 			e->e_flags &= ~EF_LOGSENDER;
1975 
1976 			/* if in a child, pop back to our parent */
1977 			if (InChild)
1978 				finis(TRUE, ExitStat);
1979 
1980 			/* clean up a bit */
1981 			gotmail = FALSE;
1982 			dropenvelope(e, TRUE);
1983 			CurEnv = e = newenvelope(e, CurEnv);
1984 			e->e_flags = BlankEnvelope.e_flags;
1985 			break;
1986 
1987 		  case CMDRSET:		/* rset -- reset state */
1988 # if _FFR_MILTER
1989 			/* abort milter filters */
1990 			milter_abort(e);
1991 # endif /* _FFR_MILTER */
1992 
1993 			if (tTd(94, 100))
1994 				message("451 4.0.0 Test failure");
1995 			else
1996 				message("250 2.0.0 Reset state");
1997 
1998 			/* arrange to ignore any current send list */
1999 			e->e_sendqueue = NULL;
2000 			e->e_flags |= EF_CLRQUEUE;
2001 
2002 			if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
2003 				logsender(e, NULL);
2004 			e->e_flags &= ~EF_LOGSENDER;
2005 
2006 			if (InChild)
2007 				finis(TRUE, ExitStat);
2008 
2009 			/* clean up a bit */
2010 			gotmail = FALSE;
2011 			SuprErrs = TRUE;
2012 			dropenvelope(e, TRUE);
2013 			CurEnv = e = newenvelope(e, CurEnv);
2014 			break;
2015 
2016 		  case CMDVRFY:		/* vrfy -- verify address */
2017 		  case CMDEXPN:		/* expn -- expand address */
2018 			if (tempfail)
2019 			{
2020 				if (LogLevel > 9)
2021 					sm_syslog(LOG_INFO, e->e_id,
2022 						  "SMTP %s command (%.100s) from %.100s tempfailed (due to previous checks)",
2023 						  c->cmd_code == CMDVRFY ? "VRFY" : "EXPN",
2024 						  p, CurSmtpClient);
2025 				usrerr("550 5.7.1 Please try again later");
2026 				break;
2027 			}
2028 			wt = checksmtpattack(&nverifies, MAXVRFYCOMMANDS, FALSE,
2029 				c->cmd_code == CMDVRFY ? "VRFY" : "EXPN", e);
2030 			previous = curtime();
2031 			vrfy = c->cmd_code == CMDVRFY;
2032 			if (bitset(vrfy ? PRIV_NOVRFY : PRIV_NOEXPN,
2033 						PrivacyFlags))
2034 			{
2035 				if (vrfy)
2036 					message("252 2.5.2 Cannot VRFY user; try RCPT to attempt delivery (or try finger)");
2037 				else
2038 					message("502 5.7.0 Sorry, we do not allow this operation");
2039 				if (LogLevel > 5)
2040 					sm_syslog(LOG_INFO, e->e_id,
2041 						  "%.100s: %s [rejected]",
2042 						  CurSmtpClient,
2043 						  shortenstring(inp, MAXSHORTSTR));
2044 				break;
2045 			}
2046 			else if (!gothello &&
2047 				 bitset(vrfy ? PRIV_NEEDVRFYHELO : PRIV_NEEDEXPNHELO,
2048 						PrivacyFlags))
2049 			{
2050 				usrerr("503 5.0.0 I demand that you introduce yourself first");
2051 				break;
2052 			}
2053 			if (runinchild(vrfy ? "SMTP-VRFY" : "SMTP-EXPN", e) > 0)
2054 				break;
2055 			if (Errors > 0)
2056 				goto undo_subproc;
2057 			if (LogLevel > 5)
2058 				sm_syslog(LOG_INFO, e->e_id,
2059 					  "%.100s: %s",
2060 					  CurSmtpClient,
2061 					  shortenstring(inp, MAXSHORTSTR));
2062 			if (setjmp(TopFrame) > 0)
2063 				goto undo_subproc;
2064 			QuickAbort = TRUE;
2065 			vrfyqueue = NULL;
2066 			if (vrfy)
2067 				e->e_flags |= EF_VRFYONLY;
2068 			while (*p != '\0' && isascii(*p) && isspace(*p))
2069 				p++;
2070 			if (*p == '\0')
2071 			{
2072 				usrerr("501 5.5.2 Argument required");
2073 			}
2074 			else
2075 			{
2076 				/* do config file checking of the address */
2077 				if (rscheck(vrfy ? "check_vrfy" : "check_expn",
2078 					    p, NULL, e, TRUE, FALSE, 4, NULL)
2079 				    != EX_OK || Errors > 0)
2080 					goto undo_subproc;
2081 				(void) sendtolist(p, NULLADDR, &vrfyqueue, 0, e);
2082 			}
2083 			if (wt > 0)
2084 			{
2085 				time_t t;
2086 
2087 				t = wt - (curtime() - previous);
2088 				if (t > 0)
2089 					(void) sleep(t);
2090 			}
2091 			if (Errors > 0)
2092 				goto undo_subproc;
2093 			if (vrfyqueue == NULL)
2094 			{
2095 				usrerr("554 5.5.2 Nothing to %s", vrfy ? "VRFY" : "EXPN");
2096 			}
2097 			while (vrfyqueue != NULL)
2098 			{
2099 				if (!QS_IS_UNDELIVERED(vrfyqueue->q_state))
2100 				{
2101 					vrfyqueue = vrfyqueue->q_next;
2102 					continue;
2103 				}
2104 
2105 				/* see if there is more in the vrfy list */
2106 				a = vrfyqueue;
2107 				while ((a = a->q_next) != NULL &&
2108 				       (!QS_IS_UNDELIVERED(a->q_state)))
2109 					continue;
2110 				printvrfyaddr(vrfyqueue, a == NULL, vrfy);
2111 				vrfyqueue = a;
2112 			}
2113 			if (InChild)
2114 				finis(TRUE, ExitStat);
2115 			break;
2116 
2117 		  case CMDETRN:		/* etrn -- force queue flush */
2118 			if (bitset(PRIV_NOETRN, PrivacyFlags) ||
2119 			    bitnset(D_NOETRN, d_flags))
2120 			{
2121 				/* different message for MSA ? */
2122 				message("502 5.7.0 Sorry, we do not allow this operation");
2123 				if (LogLevel > 5)
2124 					sm_syslog(LOG_INFO, e->e_id,
2125 						  "%.100s: %s [rejected]",
2126 						  CurSmtpClient,
2127 						  shortenstring(inp, MAXSHORTSTR));
2128 				break;
2129 			}
2130 			if (tempfail)
2131 			{
2132 				if (LogLevel > 9)
2133 					sm_syslog(LOG_INFO, e->e_id,
2134 						  "SMTP ETRN command (%.100s) from %.100s tempfailed (due to previous checks)",
2135 						  p, CurSmtpClient);
2136 				usrerr("451 4.7.1 Please try again later");
2137 				break;
2138 			}
2139 
2140 			if (strlen(p) <= 0)
2141 			{
2142 				usrerr("500 5.5.2 Parameter required");
2143 				break;
2144 			}
2145 
2146 			/* crude way to avoid denial-of-service attacks */
2147 			(void) checksmtpattack(&n_etrn, MAXETRNCOMMANDS, TRUE,
2148 					     "ETRN", e);
2149 
2150 			/* do config file checking of the parameter */
2151 			if (rscheck("check_etrn", p, NULL, e, TRUE, FALSE, 4,
2152 				    NULL) != EX_OK || Errors > 0)
2153 				break;
2154 
2155 			if (LogLevel > 5)
2156 				sm_syslog(LOG_INFO, e->e_id,
2157 					  "%.100s: ETRN %s",
2158 					  CurSmtpClient,
2159 					  shortenstring(p, MAXSHORTSTR));
2160 
2161 			id = p;
2162 			if (*id == '@')
2163 				id++;
2164 			else
2165 				*--id = '@';
2166 
2167 			new = (QUEUE_CHAR *)xalloc(sizeof(QUEUE_CHAR));
2168 			new->queue_match = id;
2169 			new->queue_next = NULL;
2170 			QueueLimitRecipient = new;
2171 			ok = runqueue(TRUE, FALSE);
2172 			sm_free(QueueLimitRecipient);
2173 			QueueLimitRecipient = NULL;
2174 			if (ok && Errors == 0)
2175 				message("250 2.0.0 Queuing for node %s started", p);
2176 			break;
2177 
2178 		  case CMDHELP:		/* help -- give user info */
2179 			help(p, e);
2180 			break;
2181 
2182 		  case CMDNOOP:		/* noop -- do nothing */
2183 			(void) checksmtpattack(&n_noop, MAXNOOPCOMMANDS, TRUE,
2184 					       "NOOP", e);
2185 			message("250 2.0.0 OK");
2186 			break;
2187 
2188 		  case CMDQUIT:		/* quit -- leave mail */
2189 			message("221 2.0.0 %s closing connection", MyHostName);
2190 
2191 			/* arrange to ignore any current send list */
2192 			e->e_sendqueue = NULL;
2193 
2194 # if STARTTLS
2195 			/* shutdown TLS connection */
2196 			if (tls_active)
2197 			{
2198 				(void) endtls(srv_ssl, "server");
2199 				tls_active = FALSE;
2200 			}
2201 # endif /* STARTTLS */
2202 # if SASL
2203 			if (authenticating == SASL_IS_AUTH)
2204 			{
2205 				sasl_dispose(&conn);
2206 				authenticating = SASL_NOT_AUTH;
2207 			}
2208 # endif /* SASL */
2209 
2210 doquit:
2211 			/* avoid future 050 messages */
2212 			disconnect(1, e);
2213 
2214 # if _FFR_MILTER
2215 			/* close out milter filters */
2216 			milter_quit(e);
2217 # endif /* _FFR_MILTER */
2218 
2219 			if (InChild)
2220 				ExitStat = EX_QUIT;
2221 
2222 			if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
2223 				logsender(e, NULL);
2224 			e->e_flags &= ~EF_LOGSENDER;
2225 
2226 			if (lognullconnection && LogLevel > 5)
2227 			{
2228 				char *d;
2229 
2230 				d = macvalue(macid("{daemon_name}", NULL), e);
2231 				if (d == NULL)
2232 					d = "stdin";
2233 				sm_syslog(LOG_INFO, NULL,
2234 					 "%.100s did not issue MAIL/EXPN/VRFY/ETRN during connection to %s",
2235 					  CurSmtpClient, d);
2236 			}
2237 			finis(TRUE, ExitStat);
2238 			/* NOTREACHED */
2239 
2240 		  case CMDVERB:		/* set verbose mode */
2241 			if (bitset(PRIV_NOEXPN, PrivacyFlags) ||
2242 			    bitset(PRIV_NOVERB, PrivacyFlags))
2243 			{
2244 				/* this would give out the same info */
2245 				message("502 5.7.0 Verbose unavailable");
2246 				break;
2247 			}
2248 			(void) checksmtpattack(&n_noop, MAXNOOPCOMMANDS, TRUE,
2249 					       "VERB", e);
2250 			Verbose = 1;
2251 			set_delivery_mode(SM_DELIVER, e);
2252 			message("250 2.0.0 Verbose mode");
2253 			break;
2254 
2255 		  case CMDONEX:		/* doing one transaction only */
2256 			(void) checksmtpattack(&n_noop, MAXNOOPCOMMANDS, TRUE,
2257 					       "ONEX", e);
2258 			OneXact = TRUE;
2259 			message("250 2.0.0 Only one transaction");
2260 			break;
2261 
2262 		  case CMDXUSR:		/* initial (user) submission */
2263 			(void) checksmtpattack(&n_noop, MAXNOOPCOMMANDS, TRUE,
2264 					       "XUSR", e);
2265 			define(macid("{daemon_flags}", NULL), "c u", CurEnv);
2266 			message("250 2.0.0 Initial submission");
2267 			break;
2268 
2269 # if SMTPDEBUG
2270 		  case CMDDBGQSHOW:	/* show queues */
2271 			printf("Send Queue=");
2272 			printaddr(e->e_sendqueue, TRUE);
2273 			break;
2274 
2275 		  case CMDDBGDEBUG:	/* set debug mode */
2276 			tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
2277 			tTflag(p);
2278 			message("200 2.0.0 Debug set");
2279 			break;
2280 
2281 # else /* SMTPDEBUG */
2282 		  case CMDDBGQSHOW:	/* show queues */
2283 		  case CMDDBGDEBUG:	/* set debug mode */
2284 # endif /* SMTPDEBUG */
2285 		  case CMDLOGBOGUS:	/* bogus command */
2286 			if (LogLevel > 0)
2287 				sm_syslog(LOG_CRIT, e->e_id,
2288 					  "\"%s\" command from %.100s (%.100s)",
2289 					  c->cmd_name, CurSmtpClient,
2290 					  anynet_ntoa(&RealHostAddr));
2291 			/* FALLTHROUGH */
2292 
2293 		  case CMDERROR:	/* unknown command */
2294 			if (++badcommands > MAXBADCOMMANDS)
2295 			{
2296 				message("421 4.7.0 %s Too many bad commands; closing connection",
2297 					MyHostName);
2298 
2299 				/* arrange to ignore any current send list */
2300 				e->e_sendqueue = NULL;
2301 				goto doquit;
2302 			}
2303 
2304 			usrerr("500 5.5.1 Command unrecognized: \"%s\"",
2305 			       shortenstring(inp, MAXSHORTSTR));
2306 			break;
2307 
2308 		  case CMDUNIMPL:
2309 			usrerr("502 5.5.1 Command not implemented: \"%s\"",
2310 			       shortenstring(inp, MAXSHORTSTR));
2311 			break;
2312 
2313 		  default:
2314 			errno = 0;
2315 			syserr("500 5.5.0 smtp: unknown code %d", c->cmd_code);
2316 			break;
2317 		}
2318 # if SASL
2319 		}
2320 # endif /* SASL */
2321 	}
2322 
2323 }
2324 /*
2325 **  CHECKSMTPATTACK -- check for denial-of-service attack by repetition
2326 **
2327 **	Parameters:
2328 **		pcounter -- pointer to a counter for this command.
2329 **		maxcount -- maximum value for this counter before we
2330 **			slow down.
2331 **		waitnow -- sleep now (in this routine)?
2332 **		cname -- command name for logging.
2333 **		e -- the current envelope.
2334 **
2335 **	Returns:
2336 **		time to wait.
2337 **
2338 **	Side Effects:
2339 **		Slows down if we seem to be under attack.
2340 */
2341 
2342 static time_t
2343 checksmtpattack(pcounter, maxcount, waitnow, cname, e)
2344 	volatile int *pcounter;
2345 	int maxcount;
2346 	bool waitnow;
2347 	char *cname;
2348 	ENVELOPE *e;
2349 {
2350 	if (++(*pcounter) >= maxcount)
2351 	{
2352 		time_t s;
2353 
2354 		if (*pcounter == maxcount && LogLevel > 5)
2355 		{
2356 			sm_syslog(LOG_INFO, e->e_id,
2357 				  "%.100s: possible SMTP attack: command=%.40s, count=%d",
2358 				  CurSmtpClient, cname, *pcounter);
2359 		}
2360 		s = 1 << (*pcounter - maxcount);
2361 		if (s >= MAXTIMEOUT)
2362 			s = MAXTIMEOUT;
2363 		/* sleep at least 1 second before returning */
2364 		(void) sleep(*pcounter / maxcount);
2365 		s -= *pcounter / maxcount;
2366 		if (waitnow)
2367 		{
2368 			(void) sleep(s);
2369 			return(0);
2370 		}
2371 		return(s);
2372 	}
2373 	return((time_t) 0);
2374 }
2375 /*
2376 **  SKIPWORD -- skip a fixed word.
2377 **
2378 **	Parameters:
2379 **		p -- place to start looking.
2380 **		w -- word to skip.
2381 **
2382 **	Returns:
2383 **		p following w.
2384 **		NULL on error.
2385 **
2386 **	Side Effects:
2387 **		clobbers the p data area.
2388 */
2389 
2390 static char *
2391 skipword(p, w)
2392 	register char *volatile p;
2393 	char *w;
2394 {
2395 	register char *q;
2396 	char *firstp = p;
2397 
2398 	/* find beginning of word */
2399 	while (isascii(*p) && isspace(*p))
2400 		p++;
2401 	q = p;
2402 
2403 	/* find end of word */
2404 	while (*p != '\0' && *p != ':' && !(isascii(*p) && isspace(*p)))
2405 		p++;
2406 	while (isascii(*p) && isspace(*p))
2407 		*p++ = '\0';
2408 	if (*p != ':')
2409 	{
2410 	  syntax:
2411 		usrerr("501 5.5.2 Syntax error in parameters scanning \"%s\"",
2412 			shortenstring(firstp, MAXSHORTSTR));
2413 		return NULL;
2414 	}
2415 	*p++ = '\0';
2416 	while (isascii(*p) && isspace(*p))
2417 		p++;
2418 
2419 	if (*p == '\0')
2420 		goto syntax;
2421 
2422 	/* see if the input word matches desired word */
2423 	if (strcasecmp(q, w))
2424 		goto syntax;
2425 
2426 	return p;
2427 }
2428 /*
2429 **  MAIL_ESMTP_ARGS -- process ESMTP arguments from MAIL line
2430 **
2431 **	Parameters:
2432 **		kp -- the parameter key.
2433 **		vp -- the value of that parameter.
2434 **		e -- the envelope.
2435 **
2436 **	Returns:
2437 **		none.
2438 */
2439 
2440 static void
2441 mail_esmtp_args(kp, vp, e)
2442 	char *kp;
2443 	char *vp;
2444 	ENVELOPE *e;
2445 {
2446 	if (strcasecmp(kp, "size") == 0)
2447 	{
2448 		if (vp == NULL)
2449 		{
2450 			usrerr("501 5.5.2 SIZE requires a value");
2451 			/* NOTREACHED */
2452 		}
2453 		define(macid("{msg_size}", NULL), newstr(vp), e);
2454 		e->e_msgsize = strtol(vp, (char **) NULL, 10);
2455 		if (e->e_msgsize == LONG_MAX && errno == ERANGE)
2456 		{
2457 			usrerr("552 5.2.3 Message size exceeds maximum value");
2458 			/* NOTREACHED */
2459 		}
2460 	}
2461 	else if (strcasecmp(kp, "body") == 0)
2462 	{
2463 		if (vp == NULL)
2464 		{
2465 			usrerr("501 5.5.2 BODY requires a value");
2466 			/* NOTREACHED */
2467 		}
2468 		else if (strcasecmp(vp, "8bitmime") == 0)
2469 		{
2470 			SevenBitInput = FALSE;
2471 		}
2472 		else if (strcasecmp(vp, "7bit") == 0)
2473 		{
2474 			SevenBitInput = TRUE;
2475 		}
2476 		else
2477 		{
2478 			usrerr("501 5.5.4 Unknown BODY type %s",
2479 				vp);
2480 			/* NOTREACHED */
2481 		}
2482 		e->e_bodytype = newstr(vp);
2483 	}
2484 	else if (strcasecmp(kp, "envid") == 0)
2485 	{
2486 		if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
2487 		{
2488 			usrerr("504 5.7.0 Sorry, ENVID not supported, we do not allow DSN");
2489 			/* NOTREACHED */
2490 		}
2491 		if (vp == NULL)
2492 		{
2493 			usrerr("501 5.5.2 ENVID requires a value");
2494 			/* NOTREACHED */
2495 		}
2496 		if (!xtextok(vp))
2497 		{
2498 			usrerr("501 5.5.4 Syntax error in ENVID parameter value");
2499 			/* NOTREACHED */
2500 		}
2501 		if (e->e_envid != NULL)
2502 		{
2503 			usrerr("501 5.5.0 Duplicate ENVID parameter");
2504 			/* NOTREACHED */
2505 		}
2506 		e->e_envid = newstr(vp);
2507 		define(macid("{dsn_envid}", NULL), newstr(vp), e);
2508 	}
2509 	else if (strcasecmp(kp, "ret") == 0)
2510 	{
2511 		if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
2512 		{
2513 			usrerr("504 5.7.0 Sorry, RET not supported, we do not allow DSN");
2514 			/* NOTREACHED */
2515 		}
2516 		if (vp == NULL)
2517 		{
2518 			usrerr("501 5.5.2 RET requires a value");
2519 			/* NOTREACHED */
2520 		}
2521 		if (bitset(EF_RET_PARAM, e->e_flags))
2522 		{
2523 			usrerr("501 5.5.0 Duplicate RET parameter");
2524 			/* NOTREACHED */
2525 		}
2526 		e->e_flags |= EF_RET_PARAM;
2527 		if (strcasecmp(vp, "hdrs") == 0)
2528 			e->e_flags |= EF_NO_BODY_RETN;
2529 		else if (strcasecmp(vp, "full") != 0)
2530 		{
2531 			usrerr("501 5.5.2 Bad argument \"%s\" to RET", vp);
2532 			/* NOTREACHED */
2533 		}
2534 		define(macid("{dsn_ret}", NULL), newstr(vp), e);
2535 	}
2536 # if SASL
2537 	else if (strcasecmp(kp, "auth") == 0)
2538 	{
2539 		int len;
2540 		char *q;
2541 		char *auth_param;	/* the value of the AUTH=x */
2542 		bool saveQuickAbort = QuickAbort;
2543 		bool saveSuprErrs = SuprErrs;
2544 		char pbuf[256];
2545 
2546 		if (vp == NULL)
2547 		{
2548 			usrerr("501 5.5.2 AUTH= requires a value");
2549 			/* NOTREACHED */
2550 		}
2551 		if (e->e_auth_param != NULL)
2552 		{
2553 			usrerr("501 5.5.0 Duplicate AUTH parameter");
2554 			/* NOTREACHED */
2555 		}
2556 		if ((q = strchr(vp, ' ')) != NULL)
2557 			len = q - vp + 1;
2558 		else
2559 			len = strlen(vp) + 1;
2560 		auth_param = xalloc(len);
2561 		(void) strlcpy(auth_param, vp, len);
2562 		if (!xtextok(auth_param))
2563 		{
2564 			usrerr("501 5.5.4 Syntax error in AUTH parameter value");
2565 			/* just a warning? */
2566 			/* NOTREACHED */
2567 		}
2568 
2569 		/* XXX this might be cut off */
2570 		snprintf(pbuf, sizeof pbuf, "%s", xuntextify(auth_param));
2571 		/* xalloc() the buffer instead? */
2572 
2573 		/* XXX define this always or only if trusted? */
2574 		define(macid("{auth_author}", NULL), newstr(pbuf), e);
2575 
2576 		/*
2577 		**  call Strust_auth to find out whether
2578 		**  auth_param is acceptable (trusted)
2579 		**  we shouldn't trust it if not authenticated
2580 		**  (required by RFC, leave it to ruleset?)
2581 		*/
2582 
2583 		SuprErrs = TRUE;
2584 		QuickAbort = FALSE;
2585 		if (strcmp(auth_param, "<>") != 0 &&
2586 		     (rscheck("trust_auth", pbuf, NULL, e, TRUE, FALSE, 10,
2587 			      NULL) != EX_OK || Errors > 0))
2588 		{
2589 			if (tTd(95, 8))
2590 			{
2591 				q = e->e_auth_param;
2592 				dprintf("auth=\"%.100s\" not trusted user=\"%.100s\"\n",
2593 					pbuf, (q == NULL) ? "" : q);
2594 			}
2595 			/* not trusted */
2596 			e->e_auth_param = newstr("<>");
2597 		}
2598 		else
2599 		{
2600 			if (tTd(95, 8))
2601 				dprintf("auth=\"%.100s\" trusted\n", pbuf);
2602 			e->e_auth_param = newstr(auth_param);
2603 		}
2604 		sm_free(auth_param);
2605 
2606 		/* reset values */
2607 		Errors = 0;
2608 		QuickAbort = saveQuickAbort;
2609 		SuprErrs = saveSuprErrs;
2610 	}
2611 # endif /* SASL */
2612 	else
2613 	{
2614 		usrerr("555 5.5.4 %s parameter unrecognized", kp);
2615 		/* NOTREACHED */
2616 	}
2617 }
2618 /*
2619 **  RCPT_ESMTP_ARGS -- process ESMTP arguments from RCPT line
2620 **
2621 **	Parameters:
2622 **		a -- the address corresponding to the To: parameter.
2623 **		kp -- the parameter key.
2624 **		vp -- the value of that parameter.
2625 **		e -- the envelope.
2626 **
2627 **	Returns:
2628 **		none.
2629 */
2630 
2631 static void
2632 rcpt_esmtp_args(a, kp, vp, e)
2633 	ADDRESS *a;
2634 	char *kp;
2635 	char *vp;
2636 	ENVELOPE *e;
2637 {
2638 	if (strcasecmp(kp, "notify") == 0)
2639 	{
2640 		char *p;
2641 
2642 		if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
2643 		{
2644 			usrerr("504 5.7.0 Sorry, NOTIFY not supported, we do not allow DSN");
2645 			/* NOTREACHED */
2646 		}
2647 		if (vp == NULL)
2648 		{
2649 			usrerr("501 5.5.2 NOTIFY requires a value");
2650 			/* NOTREACHED */
2651 		}
2652 		a->q_flags &= ~(QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY);
2653 		a->q_flags |= QHASNOTIFY;
2654 		define(macid("{dsn_notify}", NULL), newstr(vp), e);
2655 
2656 		if (strcasecmp(vp, "never") == 0)
2657 			return;
2658 		for (p = vp; p != NULL; vp = p)
2659 		{
2660 			p = strchr(p, ',');
2661 			if (p != NULL)
2662 				*p++ = '\0';
2663 			if (strcasecmp(vp, "success") == 0)
2664 				a->q_flags |= QPINGONSUCCESS;
2665 			else if (strcasecmp(vp, "failure") == 0)
2666 				a->q_flags |= QPINGONFAILURE;
2667 			else if (strcasecmp(vp, "delay") == 0)
2668 				a->q_flags |= QPINGONDELAY;
2669 			else
2670 			{
2671 				usrerr("501 5.5.4 Bad argument \"%s\"  to NOTIFY",
2672 					vp);
2673 				/* NOTREACHED */
2674 			}
2675 		}
2676 	}
2677 	else if (strcasecmp(kp, "orcpt") == 0)
2678 	{
2679 		if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
2680 		{
2681 			usrerr("504 5.7.0 Sorry, ORCPT not supported, we do not allow DSN");
2682 			/* NOTREACHED */
2683 		}
2684 		if (vp == NULL)
2685 		{
2686 			usrerr("501 5.5.2 ORCPT requires a value");
2687 			/* NOTREACHED */
2688 		}
2689 		if (strchr(vp, ';') == NULL || !xtextok(vp))
2690 		{
2691 			usrerr("501 5.5.4 Syntax error in ORCPT parameter value");
2692 			/* NOTREACHED */
2693 		}
2694 		if (a->q_orcpt != NULL)
2695 		{
2696 			usrerr("501 5.5.0 Duplicate ORCPT parameter");
2697 			/* NOTREACHED */
2698 		}
2699 		a->q_orcpt = newstr(vp);
2700 	}
2701 	else
2702 	{
2703 		usrerr("555 5.5.4 %s parameter unrecognized", kp);
2704 		/* NOTREACHED */
2705 	}
2706 }
2707 /*
2708 **  PRINTVRFYADDR -- print an entry in the verify queue
2709 **
2710 **	Parameters:
2711 **		a -- the address to print
2712 **		last -- set if this is the last one.
2713 **		vrfy -- set if this is a VRFY command.
2714 **
2715 **	Returns:
2716 **		none.
2717 **
2718 **	Side Effects:
2719 **		Prints the appropriate 250 codes.
2720 */
2721 #define OFFF	(3 + 1 + 5 + 1)	/* offset in fmt: SMTP reply + enh. code */
2722 
2723 static void
2724 printvrfyaddr(a, last, vrfy)
2725 	register ADDRESS *a;
2726 	bool last;
2727 	bool vrfy;
2728 {
2729 	char fmtbuf[30];
2730 
2731 	if (vrfy && a->q_mailer != NULL &&
2732 	    !bitnset(M_VRFY250, a->q_mailer->m_flags))
2733 		(void) strlcpy(fmtbuf, "252", sizeof fmtbuf);
2734 	else
2735 		(void) strlcpy(fmtbuf, "250", sizeof fmtbuf);
2736 	fmtbuf[3] = last ? ' ' : '-';
2737 	(void) strlcpy(&fmtbuf[4], "2.1.5 ", sizeof fmtbuf - 4);
2738 	if (a->q_fullname == NULL)
2739 	{
2740 		if ((a->q_mailer == NULL ||
2741 		     a->q_mailer->m_addrtype == NULL ||
2742 		     strcasecmp(a->q_mailer->m_addrtype, "rfc822") == 0) &&
2743 		    strchr(a->q_user, '@') == NULL)
2744 			(void) strlcpy(&fmtbuf[OFFF], "<%s@%s>",
2745 				       sizeof fmtbuf - OFFF);
2746 		else
2747 			(void) strlcpy(&fmtbuf[OFFF], "<%s>",
2748 				       sizeof fmtbuf - OFFF);
2749 		message(fmtbuf, a->q_user, MyHostName);
2750 	}
2751 	else
2752 	{
2753 		if ((a->q_mailer == NULL ||
2754 		     a->q_mailer->m_addrtype == NULL ||
2755 		     strcasecmp(a->q_mailer->m_addrtype, "rfc822") == 0) &&
2756 		    strchr(a->q_user, '@') == NULL)
2757 			(void) strlcpy(&fmtbuf[OFFF], "%s <%s@%s>",
2758 				       sizeof fmtbuf - OFFF);
2759 		else
2760 			(void) strlcpy(&fmtbuf[OFFF], "%s <%s>",
2761 				       sizeof fmtbuf - OFFF);
2762 		message(fmtbuf, a->q_fullname, a->q_user, MyHostName);
2763 	}
2764 }
2765 /*
2766 **  RUNINCHILD -- return twice -- once in the child, then in the parent again
2767 **
2768 **	Parameters:
2769 **		label -- a string used in error messages
2770 **
2771 **	Returns:
2772 **		RIC_INCHILD in the child
2773 **		RIC_INPARENT in the parent
2774 **		RIC_TEMPFAIL tempfail condition
2775 **
2776 **	Side Effects:
2777 **		none.
2778 */
2779 
2780 static int
2781 runinchild(label, e)
2782 	char *label;
2783 	register ENVELOPE *e;
2784 {
2785 	pid_t childpid;
2786 
2787 	if (!OneXact)
2788 	{
2789 		extern int NumQueues;
2790 
2791 		/*
2792 		**  advance state of PRNG
2793 		**  this is necessary because otherwise all child processes
2794 		**  will produce the same PRN sequence and hence the selection
2795 		**  of a queue directory is not "really" random.
2796 		*/
2797 		if (NumQueues > 1)
2798 			(void) get_random();
2799 
2800 		/*
2801 		**  Disable child process reaping, in case ETRN has preceded
2802 		**  MAIL command, and then fork.
2803 		*/
2804 
2805 		(void) blocksignal(SIGCHLD);
2806 
2807 
2808 		childpid = dofork();
2809 		if (childpid < 0)
2810 		{
2811 			syserr("451 4.3.0 %s: cannot fork", label);
2812 			(void) releasesignal(SIGCHLD);
2813 			return RIC_INPARENT;
2814 		}
2815 		if (childpid > 0)
2816 		{
2817 			auto int st;
2818 
2819 			/* parent -- wait for child to complete */
2820 			sm_setproctitle(TRUE, e, "server %s child wait",
2821 					CurSmtpClient);
2822 			st = waitfor(childpid);
2823 			if (st == -1)
2824 				syserr("451 4.3.0 %s: lost child", label);
2825 			else if (!WIFEXITED(st))
2826 			{
2827 				syserr("451 4.3.0 %s: died on signal %d",
2828 				       label, st & 0177);
2829 				return RIC_TEMPFAIL;
2830 			}
2831 
2832 			/* if exited on a QUIT command, complete the process */
2833 			if (WEXITSTATUS(st) == EX_QUIT)
2834 			{
2835 				disconnect(1, e);
2836 				finis(TRUE, ExitStat);
2837 			}
2838 
2839 			/* restore the child signal */
2840 			(void) releasesignal(SIGCHLD);
2841 
2842 			return RIC_INPARENT;
2843 		}
2844 		else
2845 		{
2846 			/* child */
2847 			InChild = TRUE;
2848 			QuickAbort = FALSE;
2849 
2850 			/* Reset global flags */
2851 			RestartRequest = NULL;
2852 			ShutdownRequest = NULL;
2853 			PendingSignal = 0;
2854 
2855 			clearstats();
2856 			clearenvelope(e, FALSE);
2857 			assign_queueid(e);
2858 			(void) setsignal(SIGCHLD, SIG_DFL);
2859 			(void) releasesignal(SIGCHLD);
2860 		}
2861 	}
2862 	return RIC_INCHILD;
2863 }
2864 
2865 # if SASL
2866 
2867 /*
2868 **  SASLMECHS -- get list of possible AUTH mechanisms
2869 **
2870 **	Parameters:
2871 **		conn -- SASL connection info
2872 **		mechlist -- output parameter for list of mechanisms
2873 **
2874 **	Returns:
2875 **		number of mechs
2876 */
2877 
2878 static int
2879 saslmechs(conn, mechlist)
2880 	sasl_conn_t *conn;
2881 	char **mechlist;
2882 {
2883 	int len, num, result;
2884 
2885 	/* "user" is currently unused */
2886 	result = sasl_listmech(conn, "user", /* XXX */
2887 			       "", " ", "", mechlist,
2888 			       (u_int *)&len, (u_int *)&num);
2889 	if (result == SASL_OK && num > 0)
2890 	{
2891 		if (LogLevel > 11)
2892 			sm_syslog(LOG_INFO, NOQID,
2893 				  "SASL: available mech=%s, allowed mech=%s",
2894 				  *mechlist, AuthMechanisms);
2895 		*mechlist = intersect(AuthMechanisms, *mechlist);
2896 	}
2897 	else
2898 	{
2899 		if (LogLevel > 9)
2900 			sm_syslog(LOG_WARNING, NOQID,
2901 				  "SASL error: listmech=%d, num=%d",
2902 				  result, num);
2903 		num = 0;
2904 	}
2905 	return num;
2906 }
2907 
2908 /*
2909 **  PROXY_POLICY -- define proxy policy for AUTH
2910 **
2911 **	Parameters:
2912 **		conntext -- unused
2913 **		auth_identity -- authentication identity
2914 **		requested_user -- authorization identity
2915 **		user -- allowed user (output)
2916 **		errstr -- possible error string (output)
2917 **
2918 **	Returns:
2919 **		ok?
2920 */
2921 
2922 int
2923 proxy_policy(context, auth_identity, requested_user, user, errstr)
2924 	void *context;
2925 	const char *auth_identity;
2926 	const char *requested_user;
2927 	const char **user;
2928 	const char **errstr;
2929 {
2930 	if (user == NULL || auth_identity == NULL)
2931 		return SASL_FAIL;
2932 	*user = newstr(auth_identity);
2933 	return SASL_OK;
2934 }
2935 
2936 # endif /* SASL */
2937 
2938 # if STARTTLS
2939 #  if !TLS_NO_RSA
2940 RSA *rsa_tmp;	/* temporary RSA key */
2941 static RSA * tmp_rsa_key __P((SSL *, int, int));
2942 #  endif /* !TLS_NO_RSA */
2943 
2944 # if !NO_DH
2945 static DH *get_dh512 __P((void));
2946 
2947 static unsigned char dh512_p[] =
2948 {
2949 	0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75,
2950 	0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F,
2951 	0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3,
2952 	0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12,
2953 	0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C,
2954 	0x47,0x74,0xE8,0x33
2955 };
2956 static unsigned char dh512_g[] =
2957 {
2958 	0x02
2959 };
2960 
2961 static DH *
2962 get_dh512()
2963 {
2964 	DH *dh = NULL;
2965 
2966 	if ((dh = DH_new()) == NULL)
2967 		return(NULL);
2968 	dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL);
2969 	dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL);
2970 	if ((dh->p == NULL) || (dh->g == NULL))
2971 		return(NULL);
2972 	return(dh);
2973 }
2974 # endif /* !NO_DH */
2975 
2976 /*
2977 **  TLS_RAND_INIT -- initialize STARTTLS random generator
2978 **
2979 **	Parameters:
2980 **		randfile -- name of file with random data
2981 **		logl -- loglevel
2982 **
2983 **	Returns:
2984 **		success/failure
2985 **
2986 **	Side Effects:
2987 **		initializes PRNG for tls library.
2988 */
2989 
2990 #define MIN_RAND_BYTES	16	/* 128 bits */
2991 
2992 bool
2993 tls_rand_init(randfile, logl)
2994 	char *randfile;
2995 	int logl;
2996 {
2997 # ifndef HASURANDOMDEV
2998 	/* not required if /dev/urandom exists, OpenSSL does it internally */
2999 #define RF_OK		0	/* randfile OK */
3000 #define RF_MISS		1	/* randfile == NULL || *randfile == '\0' */
3001 #define RF_UNKNOWN	2	/* unknown prefix for randfile */
3002 
3003 #define RI_NONE		0	/* no init yet */
3004 #define RI_SUCCESS	1	/* init was successful */
3005 #define RI_FAIL		2	/* init failed */
3006 
3007 	bool ok;
3008 	int randdef;
3009 	static int done = RI_NONE;
3010 
3011 	/*
3012 	**  initialize PRNG
3013 	*/
3014 
3015 	/* did we try this before? if yes: return old value */
3016 	if (done != RI_NONE)
3017 		return done == RI_SUCCESS;
3018 
3019 	/* set default values */
3020 	ok = FALSE;
3021 	done = RI_FAIL;
3022 	randdef = (randfile == NULL || *randfile == '\0') ? RF_MISS : RF_OK;
3023 #    if EGD
3024 	if (randdef == RF_OK && strncasecmp(randfile, "egd:", 4) == 0)
3025 	{
3026 		randfile += 4;
3027 		if (RAND_egd(randfile) < 0)
3028 		{
3029 			sm_syslog(LOG_WARNING, NOQID,
3030 				  "TLS: RAND_egd(%s) failed: random number generator not seeded",
3031 				   randfile);
3032 		}
3033 		else
3034 			ok = TRUE;
3035 	}
3036 	else
3037 #    endif /* EGD */
3038 	if (randdef == RF_OK && strncasecmp(randfile, "file:", 5) == 0)
3039 	{
3040 		int fd;
3041 		long sff;
3042 		struct stat st;
3043 
3044 		randfile += 5;
3045 		sff = SFF_SAFEDIRPATH | SFF_NOWLINK
3046 		      | SFF_NOGWFILES | SFF_NOWWFILES
3047 		      | SFF_NOGRFILES | SFF_NOWRFILES
3048 		      | SFF_MUSTOWN | SFF_ROOTOK | SFF_OPENASROOT;
3049 		if ((fd = safeopen(randfile, O_RDONLY, 0, sff)) >= 0)
3050 		{
3051 			if (fstat(fd, &st) < 0)
3052 			{
3053 				if (LogLevel > logl)
3054 					sm_syslog(LOG_ERR, NOQID,
3055 						  "TLS: can't fstat(%s)",
3056 						  randfile);
3057 			}
3058 			else
3059 			{
3060 				bool use, problem;
3061 
3062 				use = TRUE;
3063 				problem = FALSE;
3064 				if (st.st_mtime + 600 < curtime())
3065 				{
3066 					use = bitnset(DBS_INSUFFICIENTENTROPY,
3067 						      DontBlameSendmail);
3068 					problem = TRUE;
3069 					if (LogLevel > logl)
3070 						sm_syslog(LOG_ERR, NOQID,
3071 							  "TLS: RandFile %s too old: %s",
3072 							  randfile,
3073 							  use ? "unsafe" :
3074 								"unusable");
3075 				}
3076 				if (use && st.st_size < MIN_RAND_BYTES)
3077 				{
3078 					use = bitnset(DBS_INSUFFICIENTENTROPY,
3079 						      DontBlameSendmail);
3080 					problem = TRUE;
3081 					if (LogLevel > logl)
3082 						sm_syslog(LOG_ERR, NOQID,
3083 							  "TLS: size(%s) < %d: %s",
3084 							  randfile,
3085 							  MIN_RAND_BYTES,
3086 							  use ? "unsafe" :
3087 								"unusable");
3088 				}
3089 				if (use)
3090 					ok = RAND_load_file(randfile, -1) >=
3091 					     MIN_RAND_BYTES;
3092 				if (use && !ok)
3093 				{
3094 					if (LogLevel > logl)
3095 						sm_syslog(LOG_WARNING,
3096 							  NOQID,
3097 							  "TLS: RAND_load_file(%s) failed: random number generator not seeded",
3098 							  randfile);
3099 				}
3100 				if (problem)
3101 					ok = FALSE;
3102 			}
3103 			if (ok || bitnset(DBS_INSUFFICIENTENTROPY,
3104 					  DontBlameSendmail))
3105 			{
3106 				/* add this even if fstat() failed */
3107 				RAND_seed((void *) &st, sizeof st);
3108 			}
3109 			(void) close(fd);
3110 		}
3111 		else
3112 		{
3113 			if (LogLevel > logl)
3114 				sm_syslog(LOG_WARNING, NOQID,
3115 					  "TLS: Warning: safeopen(%s) failed",
3116 					  randfile);
3117 		}
3118 	}
3119 	else if (randdef == RF_OK)
3120 	{
3121 		if (LogLevel > logl)
3122 			sm_syslog(LOG_WARNING, NOQID,
3123 				  "TLS: Error: no proper random file definition %s",
3124 				  randfile);
3125 		randdef = RF_UNKNOWN;
3126 	}
3127 	if (randdef == RF_MISS)
3128 	{
3129 		if (LogLevel > logl)
3130 			sm_syslog(LOG_WARNING, NOQID,
3131 				  "TLS: Error: missing random file definition");
3132 	}
3133 	if (!ok && bitnset(DBS_INSUFFICIENTENTROPY, DontBlameSendmail))
3134 	{
3135 		int i;
3136 		long r;
3137 		unsigned char buf[MIN_RAND_BYTES];
3138 
3139 		/* assert((MIN_RAND_BYTES % sizeof(long)) == 0); */
3140 		for (i = 0; i <= sizeof(buf) - sizeof(long); i += sizeof(long))
3141 		{
3142 			r = get_random();
3143 			(void) memcpy(buf + i, (void *) &r, sizeof(long));
3144 		}
3145 		RAND_seed(buf, sizeof buf);
3146 		if (LogLevel > logl)
3147 			sm_syslog(LOG_WARNING, NOQID,
3148 				  "TLS: Warning: random number generator not properly seeded");
3149 		ok = TRUE;
3150 	}
3151 	done = ok ? RI_SUCCESS : RI_FAIL;
3152 	return ok;
3153 # else /* !HASURANDOMDEV */
3154 	return TRUE;
3155 # endif /* !HASURANDOMDEV */
3156 }
3157 
3158 /*
3159 **  status in initialization
3160 **  these flags keep track of the status of the initialization
3161 **  i.e., whether a file exists (_EX) and whether it can be used (_OK)
3162 **  [due to permissions]
3163 */
3164 #define TLS_S_NONE	0x00000000	/* none yet  */
3165 #define TLS_S_CERT_EX	0x00000001	/* CERT file exists */
3166 #define TLS_S_CERT_OK	0x00000002	/* CERT file is ok */
3167 #define TLS_S_KEY_EX	0x00000004	/* KEY file exists */
3168 #define TLS_S_KEY_OK	0x00000008	/* KEY file is ok */
3169 #define TLS_S_CERTP_EX	0x00000010	/* CA CERT PATH exists */
3170 #define TLS_S_CERTP_OK	0x00000020	/* CA CERT PATH is ok */
3171 #define TLS_S_CERTF_EX	0x00000040	/* CA CERT FILE exists */
3172 #define TLS_S_CERTF_OK	0x00000080	/* CA CERT FILE is ok */
3173 
3174 # if _FFR_TLS_1
3175 #define TLS_S_CERT2_EX	0x00001000	/* 2nd CERT file exists */
3176 #define TLS_S_CERT2_OK	0x00002000	/* 2nd CERT file is ok */
3177 #define TLS_S_KEY2_EX	0x00004000	/* 2nd KEY file exists */
3178 #define TLS_S_KEY2_OK	0x00008000	/* 2nd KEY file is ok */
3179 # endif /* _FFR_TLS_1 */
3180 
3181 #define TLS_S_DH_OK	0x00200000	/* DH cert is ok */
3182 #define TLS_S_DHPAR_EX	0x00400000	/* DH param file exists */
3183 #define TLS_S_DHPAR_OK	0x00800000	/* DH param file is ok to use */
3184 
3185 /*
3186 **  TLS_OK_F -- can var be an absolute filename?
3187 **
3188 **	Parameters:
3189 **		var -- filename
3190 **		fn -- what is the filename used for?
3191 **
3192 **	Returns:
3193 **		ok?
3194 */
3195 
3196 static bool
3197 tls_ok_f(var, fn)
3198 	char *var;
3199 	char *fn;
3200 {
3201 	/* must be absolute pathname */
3202 	if (var != NULL && *var == '/')
3203 		return TRUE;
3204 	if (LogLevel > 12)
3205 		sm_syslog(LOG_WARNING, NOQID, "TLS: file %s missing", fn);
3206 	return FALSE;
3207 }
3208 
3209 /*
3210 **  TLS_SAFE_F -- is a file safe to use?
3211 **
3212 **	Parameters:
3213 **		var -- filename
3214 **		sff -- flags for safefile()
3215 **
3216 **	Returns:
3217 **		ok?
3218 */
3219 
3220 static bool
3221 tls_safe_f(var, sff)
3222 	char *var;
3223 	long sff;
3224 {
3225 	int ret;
3226 
3227 	if ((ret = safefile(var, RunAsUid, RunAsGid, RunAsUserName, sff,
3228 			    S_IRUSR, NULL)) == 0)
3229 		return TRUE;
3230 	if (LogLevel > 7)
3231 		sm_syslog(LOG_WARNING, NOQID, "TLS: file %s unsafe: %s",
3232 			  var, errstring(ret));
3233 	return FALSE;
3234 }
3235 
3236 /*
3237 **  TLS_OK_F -- macro to simplify calls to tls_ok_f
3238 **
3239 **	Parameters:
3240 **		var -- filename
3241 **		fn -- what is the filename used for?
3242 **		req -- is the file required?
3243 **		st -- status bit to set if ok
3244 **
3245 **	Side Effects:
3246 **		uses r, ok; may change ok and status.
3247 **
3248 */
3249 
3250 #define TLS_OK_F(var, fn, req, st) if (ok) \
3251 	{ \
3252 		r = tls_ok_f(var, fn); \
3253 		if (r) \
3254 			status |= st; \
3255 		else if (req) \
3256 			ok = FALSE; \
3257 	}
3258 
3259 /*
3260 **  TLS_UNR -- macro to return whether a file should be unreadable
3261 **
3262 **	Parameters:
3263 **		bit -- flag to test
3264 **		req -- flags
3265 **
3266 **	Returns:
3267 **		0/SFF_NORFILES
3268 */
3269 #define TLS_UNR(bit, req)	(bitset(bit, req) ? SFF_NORFILES : 0)
3270 
3271 /*
3272 **  TLS_SAFE_F -- macro to simplify calls to tls_safe_f
3273 **
3274 **	Parameters:
3275 **		var -- filename
3276 **		sff -- flags for safefile()
3277 **		req -- is the file required?
3278 **		ex -- does the file exist?
3279 **		st -- status bit to set if ok
3280 **
3281 **	Side Effects:
3282 **		uses r, ok, ex; may change ok and status.
3283 **
3284 */
3285 
3286 #define TLS_SAFE_F(var, sff, req, ex, st) if (ex && ok) \
3287 	{ \
3288 		r = tls_safe_f(var, sff); \
3289 		if (r) \
3290 			status |= st;	\
3291 		else if (req) \
3292 			ok = FALSE;	\
3293 	}
3294 /*
3295 **  INIT_TLS_LIBRARY -- calls functions which setup TLS library for global use
3296 **
3297 **	Parameters:
3298 **		none.
3299 **
3300 **	Returns:
3301 **		succeeded?
3302 **
3303 **	Side Effects:
3304 **		Sets tls_ok_srv static, even when called from main()
3305 */
3306 
3307 bool
3308 init_tls_library()
3309 {
3310 	/*
3311 	**  basic TLS initialization
3312 	**  ignore result for now
3313 	*/
3314 
3315 	SSL_library_init();
3316 	SSL_load_error_strings();
3317 # if 0
3318 	/* this is currently a macro for SSL_library_init */
3319 	SSLeay_add_ssl_algorithms();
3320 # endif /* 0 */
3321 
3322 	/* initialize PRNG */
3323 	tls_ok_srv = tls_rand_init(RandFile, 7);
3324 
3325 	return tls_ok_srv;
3326 }
3327 /*
3328 **  INITTLS -- initialize TLS
3329 **
3330 **	Parameters:
3331 **		ctx -- pointer to context
3332 **		req -- requirements for initialization (see sendmail.h)
3333 **		srv -- server side?
3334 **		certfile -- filename of certificate
3335 **		keyfile -- filename of private key
3336 **		cacertpath -- path to CAs
3337 **		cacertfile -- file with CA
3338 **		dhparam -- parameters for DH
3339 **
3340 **	Returns:
3341 **		succeeded?
3342 */
3343 
3344 bool
3345 inittls(ctx, req, srv, certfile, keyfile, cacertpath, cacertfile, dhparam)
3346 	SSL_CTX **ctx;
3347 	u_long req;
3348 	bool srv;
3349 	char *certfile, *keyfile, *cacertpath, *cacertfile, *dhparam;
3350 {
3351 # if !NO_DH
3352 	static DH *dh = NULL;
3353 # endif /* !NO_DH */
3354 	int r;
3355 	bool ok;
3356 	long sff, status;
3357 	char *who;
3358 # if _FFR_TLS_1
3359 	char *cf2, *kf2;
3360 # endif /* _FFR_TLS_1 */
3361 
3362 	status = TLS_S_NONE;
3363 	who = srv ? "srv" : "clt";
3364 	if (ctx == NULL)
3365 		syserr("TLS: %s:inittls: ctx == NULL", who);
3366 
3367 	/* already initialized? (we could re-init...) */
3368 	if (*ctx != NULL)
3369 		return TRUE;
3370 
3371 	/* PRNG seeded? */
3372 	if (!tls_rand_init(RandFile, 10))
3373 		return FALSE;
3374 
3375 	/* let's start with the assumption it will work */
3376 	ok = TRUE;
3377 
3378 # if _FFR_TLS_1
3379 	/*
3380 	**  look for a second filename: it must be separated by a ','
3381 	**  no blanks allowed (they won't be skipped).
3382 	**  we change a global variable here! this change will be undone
3383 	**  before return from the function but only if it returns TRUE.
3384 	**  this isn't a problem since in a failure case this function
3385 	**  won't be called again with the same (overwritten) values.
3386 	**  otherwise each return must be replaced with a goto endinittls.
3387 	*/
3388 	cf2 = NULL;
3389 	kf2 = NULL;
3390 	if (certfile != NULL && (cf2 = strchr(certfile, ',')) != NULL)
3391 	{
3392 		*cf2++ = '\0';
3393 		if (keyfile != NULL && (kf2 = strchr(keyfile, ',')) != NULL)
3394 			*kf2++ = '\0';
3395 	}
3396 # endif /* _FFR_TLS_1 */
3397 
3398 	/*
3399 	**  what do we require from the client?
3400 	**  must it have CERTs?
3401 	**  introduce an option and decide based on that
3402 	*/
3403 
3404 	TLS_OK_F(certfile, "CertFile", bitset(TLS_I_CERT_EX, req),
3405 		 TLS_S_CERT_EX);
3406 	TLS_OK_F(keyfile, "KeyFile", bitset(TLS_I_KEY_EX, req),
3407 		 TLS_S_KEY_EX);
3408 	TLS_OK_F(cacertpath, "CACERTPath", bitset(TLS_I_CERTP_EX, req),
3409 		 TLS_S_CERTP_EX);
3410 	TLS_OK_F(cacertfile, "CACERTFile", bitset(TLS_I_CERTF_EX, req),
3411 		 TLS_S_CERTF_EX);
3412 
3413 # if _FFR_TLS_1
3414 	if (cf2 != NULL)
3415 	{
3416 		TLS_OK_F(cf2, "CertFile", bitset(TLS_I_CERT_EX, req),
3417 			 TLS_S_CERT2_EX);
3418 	}
3419 	if (kf2 != NULL)
3420 	{
3421 		TLS_OK_F(kf2, "KeyFile", bitset(TLS_I_KEY_EX, req),
3422 			 TLS_S_KEY2_EX);
3423 	}
3424 # endif /* _FFR_TLS_1 */
3425 
3426 	/*
3427 	**  valid values for dhparam are (only the first char is checked)
3428 	**  none	no parameters: don't use DH
3429 	**  512		generate 512 bit parameters (fixed)
3430 	**  1024	generate 1024 bit parameters
3431 	**  /file/name	read parameters from /file/name
3432 	**  default is: 1024 for server, 512 for client (OK? XXX)
3433 	*/
3434 	if (bitset(TLS_I_TRY_DH, req))
3435 	{
3436 		if (dhparam != NULL)
3437 		{
3438 			char c = *dhparam;
3439 
3440 			if (c == '1')
3441 				req |= TLS_I_DH1024;
3442 			else if (c == '5')
3443 				req |= TLS_I_DH512;
3444 			else if (c != 'n' && c != 'N' && c != '/')
3445 			{
3446 				if (LogLevel > 12)
3447 					sm_syslog(LOG_WARNING, NOQID,
3448 						  "TLS: error: illegal value '%s' for DHParam",
3449 						  dhparam);
3450 				dhparam = NULL;
3451 			}
3452 		}
3453 		if (dhparam == NULL)
3454 			dhparam = srv ? "1" : "5";
3455 		else if (*dhparam == '/')
3456 		{
3457 			TLS_OK_F(dhparam, "DHParameters",
3458 				 bitset(TLS_I_DHPAR_EX, req),
3459 				 TLS_S_DHPAR_EX);
3460 		}
3461 	}
3462 	if (!ok)
3463 		return ok;
3464 
3465 	/* certfile etc. must be "safe". */
3466 	sff = SFF_REGONLY | SFF_SAFEDIRPATH | SFF_NOWLINK
3467 	     | SFF_NOGWFILES | SFF_NOWWFILES
3468 	     | SFF_MUSTOWN | SFF_ROOTOK | SFF_OPENASROOT;
3469 	if (DontLockReadFiles)
3470 		sff |= SFF_NOLOCK;
3471 
3472 	TLS_SAFE_F(certfile, sff | TLS_UNR(TLS_I_CERT_UNR, req),
3473 		   bitset(TLS_I_CERT_EX, req),
3474 		   bitset(TLS_S_CERT_EX, status), TLS_S_CERT_OK);
3475 	TLS_SAFE_F(keyfile, sff | TLS_UNR(TLS_I_KEY_UNR, req),
3476 		   bitset(TLS_I_KEY_EX, req),
3477 		   bitset(TLS_S_KEY_EX, status), TLS_S_KEY_OK);
3478 	TLS_SAFE_F(cacertfile, sff | TLS_UNR(TLS_I_CERTF_UNR, req),
3479 		   bitset(TLS_I_CERTF_EX, req),
3480 		   bitset(TLS_S_CERTF_EX, status), TLS_S_CERTF_OK);
3481 	TLS_SAFE_F(dhparam, sff | TLS_UNR(TLS_I_DHPAR_UNR, req),
3482 		   bitset(TLS_I_DHPAR_EX, req),
3483 		   bitset(TLS_S_DHPAR_EX, status), TLS_S_DHPAR_OK);
3484 	if (!ok)
3485 		return ok;
3486 # if _FFR_TLS_1
3487 	if (cf2 != NULL)
3488 	{
3489 		TLS_SAFE_F(cf2, sff | TLS_UNR(TLS_I_CERT_UNR, req),
3490 			   bitset(TLS_I_CERT_EX, req),
3491 			   bitset(TLS_S_CERT2_EX, status), TLS_S_CERT2_OK);
3492 	}
3493 	if (kf2 != NULL)
3494 	{
3495 		TLS_SAFE_F(kf2, sff | TLS_UNR(TLS_I_KEY_UNR, req),
3496 			   bitset(TLS_I_KEY_EX, req),
3497 			   bitset(TLS_S_KEY2_EX, status), TLS_S_KEY2_OK);
3498 	}
3499 # endif /* _FFR_TLS_1 */
3500 
3501 	/* create a method and a new context */
3502 	if (srv)
3503 	{
3504 		if ((*ctx = SSL_CTX_new(SSLv23_server_method())) == NULL)
3505 		{
3506 			if (LogLevel > 7)
3507 				sm_syslog(LOG_WARNING, NOQID,
3508 					  "TLS: error: SSL_CTX_new(SSLv23_server_method()) failed");
3509 			if (LogLevel > 9)
3510 				tlslogerr();
3511 			return FALSE;
3512 		}
3513 	}
3514 	else
3515 	{
3516 		if ((*ctx = SSL_CTX_new(SSLv23_client_method())) == NULL)
3517 		{
3518 			if (LogLevel > 7)
3519 				sm_syslog(LOG_WARNING, NOQID,
3520 					  "TLS: error: SSL_CTX_new(SSLv23_client_method()) failed");
3521 			if (LogLevel > 9)
3522 				tlslogerr();
3523 			return FALSE;
3524 		}
3525 	}
3526 
3527 #  if TLS_NO_RSA
3528 	/* turn off backward compatibility, required for no-rsa */
3529 	SSL_CTX_set_options(*ctx, SSL_OP_NO_SSLv2);
3530 #  endif /* TLS_NO_RSA */
3531 
3532 
3533 #  if !TLS_NO_RSA
3534 	/*
3535 	**  Create a temporary RSA key
3536 	**  XXX  Maybe we shouldn't create this always (even though it
3537 	**  is only at startup).
3538 	**  It is a time-consuming operation and it is not always necessary.
3539 	**  maybe we should do it only on demand...
3540 	*/
3541 	if (bitset(TLS_I_RSA_TMP, req) &&
3542 	    (rsa_tmp = RSA_generate_key(RSA_KEYLENGTH, RSA_F4, NULL,
3543 					NULL)) == NULL
3544 	   )
3545 	{
3546 		if (LogLevel > 7)
3547 		{
3548 			sm_syslog(LOG_WARNING, NOQID,
3549 				  "TLS: error: %s: RSA_generate_key failed",
3550 				  who);
3551 			if (LogLevel > 9)
3552 				tlslogerr();
3553 		}
3554 		return FALSE;
3555 	}
3556 #  endif /* !TLS_NO_RSA */
3557 
3558 	/*
3559 	**  load private key
3560 	**  XXX change this for DSA-only version
3561 	*/
3562 	if (bitset(TLS_S_KEY_OK, status) &&
3563 	    SSL_CTX_use_PrivateKey_file(*ctx, keyfile,
3564 					 SSL_FILETYPE_PEM) <= 0)
3565 	{
3566 		if (LogLevel > 7)
3567 		{
3568 			sm_syslog(LOG_WARNING, NOQID,
3569 				  "TLS: error: %s: SSL_CTX_use_PrivateKey_file(%s) failed",
3570 				  who, keyfile);
3571 			if (LogLevel > 9)
3572 				tlslogerr();
3573 		}
3574 		if (bitset(TLS_I_USE_KEY, req))
3575 			return FALSE;
3576 	}
3577 
3578 	/* get the certificate file */
3579 	if (bitset(TLS_S_CERT_OK, status) &&
3580 	    SSL_CTX_use_certificate_file(*ctx, certfile,
3581 					 SSL_FILETYPE_PEM) <= 0)
3582 	{
3583 		if (LogLevel > 7)
3584 		{
3585 			sm_syslog(LOG_WARNING, NOQID,
3586 				  "TLS: error: %s: SSL_CTX_use_certificate_file(%s) failed",
3587 				  who, certfile);
3588 			if (LogLevel > 9)
3589 				tlslogerr();
3590 		}
3591 		if (bitset(TLS_I_USE_CERT, req))
3592 			return FALSE;
3593 	}
3594 
3595 	/* check the private key */
3596 	if (bitset(TLS_S_KEY_OK, status) &&
3597 	    (r = SSL_CTX_check_private_key(*ctx)) <= 0)
3598 	{
3599 		/* Private key does not match the certificate public key */
3600 		if (LogLevel > 5)
3601 		{
3602 			sm_syslog(LOG_WARNING, NOQID,
3603 				  "TLS: error: %s: SSL_CTX_check_private_key failed(%s): %d",
3604 				  who, keyfile, r);
3605 			if (LogLevel > 9)
3606 				tlslogerr();
3607 		}
3608 		if (bitset(TLS_I_USE_KEY, req))
3609 			return FALSE;
3610 	}
3611 
3612 # if _FFR_TLS_1
3613 	/* XXX this code is pretty much duplicated from above! */
3614 
3615 	/* load private key */
3616 	if (bitset(TLS_S_KEY2_OK, status) &&
3617 	    SSL_CTX_use_PrivateKey_file(*ctx, kf2, SSL_FILETYPE_PEM) <= 0)
3618 	{
3619 		if (LogLevel > 7)
3620 		{
3621 			sm_syslog(LOG_WARNING, NOQID,
3622 				  "TLS: error: %s: SSL_CTX_use_PrivateKey_file(%s) failed",
3623 				  who, kf2);
3624 			if (LogLevel > 9)
3625 				tlslogerr();
3626 		}
3627 	}
3628 
3629 	/* get the certificate file */
3630 	if (bitset(TLS_S_CERT2_OK, status) &&
3631 	    SSL_CTX_use_certificate_file(*ctx, cf2, SSL_FILETYPE_PEM) <= 0)
3632 	{
3633 		if (LogLevel > 7)
3634 		{
3635 			sm_syslog(LOG_WARNING, NOQID,
3636 				  "TLS: error: %s: SSL_CTX_use_certificate_file(%s) failed",
3637 				  who, cf2);
3638 			if (LogLevel > 9)
3639 				tlslogerr();
3640 		}
3641 	}
3642 
3643 	/* we should also check the private key: */
3644 	if (bitset(TLS_S_KEY2_OK, status) &&
3645 	    (r = SSL_CTX_check_private_key(*ctx)) <= 0)
3646 	{
3647 		/* Private key does not match the certificate public key */
3648 		if (LogLevel > 5)
3649 		{
3650 			sm_syslog(LOG_WARNING, NOQID,
3651 				  "TLS: error: %s: SSL_CTX_check_private_key 2 failed: %d",
3652 				  who, r);
3653 			if (LogLevel > 9)
3654 				tlslogerr();
3655 		}
3656 	}
3657 # endif /* _FFR_TLS_1 */
3658 
3659 	/* SSL_CTX_set_quiet_shutdown(*ctx, 1); violation of standard? */
3660 	SSL_CTX_set_options(*ctx, SSL_OP_ALL);	/* XXX bug compatibility? */
3661 
3662 # if !NO_DH
3663 	/* Diffie-Hellman initialization */
3664 	if (bitset(TLS_I_TRY_DH, req))
3665 	{
3666 		if (bitset(TLS_S_DHPAR_OK, status))
3667 		{
3668 			BIO *bio;
3669 
3670 			if ((bio = BIO_new_file(dhparam, "r")) != NULL)
3671 			{
3672 				dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
3673 				BIO_free(bio);
3674 				if (dh == NULL && LogLevel > 7)
3675 				{
3676 					u_long err;
3677 
3678 					err = ERR_get_error();
3679 					sm_syslog(LOG_WARNING, NOQID,
3680 						  "TLS: error: %s: cannot read DH parameters(%s): %s",
3681 						  who, dhparam,
3682 						  ERR_error_string(err, NULL));
3683 					if (LogLevel > 9)
3684 						tlslogerr();
3685 				}
3686 			}
3687 			else
3688 			{
3689 				if (LogLevel > 5)
3690 				{
3691 					sm_syslog(LOG_WARNING, NOQID,
3692 						  "TLS: error: %s: BIO_new_file(%s) failed",
3693 						  who, dhparam);
3694 					if (LogLevel > 9)
3695 						tlslogerr();
3696 				}
3697 			}
3698 		}
3699 		if (dh == NULL && bitset(TLS_I_DH1024, req))
3700 		{
3701 			DSA *dsa;
3702 
3703 			/* this takes a while! (7-130s on a 450MHz AMD K6-2) */
3704 			dsa = DSA_generate_parameters(1024, NULL, 0, NULL,
3705 						      NULL, 0, NULL);
3706 			dh = DSA_dup_DH(dsa);
3707 			DSA_free(dsa);
3708 		}
3709 		else
3710 		if (dh == NULL && bitset(TLS_I_DH512, req))
3711 			dh = get_dh512();
3712 
3713 		if (dh == NULL)
3714 		{
3715 			if (LogLevel > 9)
3716 			{
3717 				u_long err;
3718 
3719 				err = ERR_get_error();
3720 				sm_syslog(LOG_WARNING, NOQID,
3721 					  "TLS: error: %s: cannot read or set DH parameters(%s): %s",
3722 					  who, dhparam,
3723 					  ERR_error_string(err, NULL));
3724 			}
3725 			if (bitset(TLS_I_REQ_DH, req))
3726 				return FALSE;
3727 		}
3728 		else
3729 		{
3730 			SSL_CTX_set_tmp_dh(*ctx, dh);
3731 
3732 			/* important to avoid small subgroup attacks */
3733 			SSL_CTX_set_options(*ctx, SSL_OP_SINGLE_DH_USE);
3734 			if (LogLevel > 12)
3735 				sm_syslog(LOG_INFO, NOQID,
3736 					  "TLS: %s: Diffie-Hellman init, key=%d bit (%c)",
3737 					  who, 8 * DH_size(dh), *dhparam);
3738 			DH_free(dh);
3739 		}
3740 	}
3741 # endif /* !NO_DH */
3742 
3743 
3744 	/* XXX do we need this cache here? */
3745 	if (bitset(TLS_I_CACHE, req))
3746 		SSL_CTX_sess_set_cache_size(*ctx, 128);
3747 	/* timeout? SSL_CTX_set_timeout(*ctx, TimeOut...); */
3748 
3749 	/* load certificate locations and default CA paths */
3750 	if (bitset(TLS_S_CERTP_EX, status) && bitset(TLS_S_CERTF_EX, status))
3751 	{
3752 		if ((r = SSL_CTX_load_verify_locations(*ctx, cacertfile,
3753 						       cacertpath)) == 1)
3754 		{
3755 #  if !TLS_NO_RSA
3756 			if (bitset(TLS_I_RSA_TMP, req))
3757 				SSL_CTX_set_tmp_rsa_callback(*ctx, tmp_rsa_key);
3758 #  endif /* !TLS_NO_RSA */
3759 
3760 			/* ask to verify the peer */
3761 			SSL_CTX_set_verify(*ctx, SSL_VERIFY_PEER, NULL);
3762 
3763 			/* install verify callback */
3764 			SSL_CTX_set_cert_verify_callback(*ctx, tls_verify_cb,
3765 							 NULL);
3766 			SSL_CTX_set_client_CA_list(*ctx,
3767 				SSL_load_client_CA_file(cacertfile));
3768 		}
3769 		else
3770 		{
3771 			/*
3772 			**  can't load CA data; do we care?
3773 			**  the data is necessary to authenticate the client,
3774 			**  which in turn would be necessary
3775 			**  if we want to allow relaying based on it.
3776 			*/
3777 			if (LogLevel > 5)
3778 			{
3779 				sm_syslog(LOG_WARNING, NOQID,
3780 					  "TLS: error: %s: %d load verify locs %s, %s",
3781 					  who, r, cacertpath, cacertfile);
3782 				if (LogLevel > 9)
3783 					tlslogerr();
3784 			}
3785 			if (bitset(TLS_I_VRFY_LOC, req))
3786 				return FALSE;
3787 		}
3788 	}
3789 
3790 	/* XXX: make this dependent on an option? */
3791 	if (tTd(96, 9))
3792 		SSL_CTX_set_info_callback(*ctx, apps_ssl_info_cb);
3793 
3794 #  if _FFR_TLS_1
3795 	/*
3796 	**  XXX install our own cipher list: option?
3797 	*/
3798 	if (CipherList != NULL && *CipherList != '\0')
3799 	{
3800 		if (SSL_CTX_set_cipher_list(*ctx, CipherList) <= 0)
3801 		{
3802 			if (LogLevel > 7)
3803 			{
3804 				sm_syslog(LOG_WARNING, NOQID,
3805 					  "TLS: error: %s: SSL_CTX_set_cipher_list(%s) failed, list ignored",
3806 					  who, CipherList);
3807 
3808 				if (LogLevel > 9)
3809 					tlslogerr();
3810 			}
3811 			/* failure if setting to this list is required? */
3812 		}
3813 	}
3814 #  endif /* _FFR_TLS_1 */
3815 	if (LogLevel > 12)
3816 		sm_syslog(LOG_INFO, NOQID, "TLS: init(%s)=%d", who, ok);
3817 
3818 # if _FFR_TLS_1
3819 #  if 0
3820 	/*
3821 	**  this label is required if we want to have a "clean" exit
3822 	**  see the comments above at the initialization of cf2
3823 	*/
3824     endinittls:
3825 #  endif /* 0 */
3826 
3827 	/* undo damage to global variables */
3828 	if (cf2 != NULL)
3829 		*--cf2 = ',';
3830 	if (kf2 != NULL)
3831 		*--kf2 = ',';
3832 # endif /* _FFR_TLS_1 */
3833 
3834 	return ok;
3835 }
3836 /*
3837 **  INITSRVTLS -- initialize server side TLS
3838 **
3839 **	Parameters:
3840 **		none.
3841 **
3842 **	Returns:
3843 **		succeeded?
3844 **
3845 **	Side Effects:
3846 **		sets tls_ok_srv static, even when called from main()
3847 */
3848 
3849 bool
3850 initsrvtls()
3851 {
3852 
3853 	tls_ok_srv = inittls(&srv_ctx, TLS_I_SRV, TRUE, SrvCERTfile,
3854 			     Srvkeyfile, CACERTpath, CACERTfile, DHParams);
3855 	return tls_ok_srv;
3856 }
3857 /*
3858 **  TLS_GET_INFO -- get information about TLS connection
3859 **
3860 **	Parameters:
3861 **		ssl -- SSL connection structure
3862 **		e -- current envelope
3863 **		srv -- server or client
3864 **		host -- hostname of other side
3865 **		log -- log connection information?
3866 **
3867 **	Returns:
3868 **		result of authentication.
3869 **
3870 **	Side Effects:
3871 **		sets ${cipher}, ${tls_version}, ${verify}, ${cipher_bits},
3872 **		${cert}
3873 */
3874 
3875 int
3876 tls_get_info(ssl, e, srv, host, log)
3877 	SSL *ssl;
3878 	ENVELOPE *e;
3879 	bool srv;
3880 	char *host;
3881 	bool log;
3882 {
3883 	SSL_CIPHER *c;
3884 	int b, r;
3885 	char *s;
3886 	char bitstr[16];
3887 	X509 *cert;
3888 
3889 	c = SSL_get_current_cipher(ssl);
3890 	define(macid("{cipher}", NULL), newstr(SSL_CIPHER_get_name(c)), e);
3891 	b = SSL_CIPHER_get_bits(c, &r);
3892 	(void) snprintf(bitstr, sizeof bitstr, "%d", b);
3893 	define(macid("{cipher_bits}", NULL), newstr(bitstr), e);
3894 # if _FFR_TLS_1
3895 	(void) snprintf(bitstr, sizeof bitstr, "%d", r);
3896 	define(macid("{alg_bits}", NULL), newstr(bitstr), e);
3897 # endif /* _FFR_TLS_1 */
3898 	s = SSL_CIPHER_get_version(c);
3899 	if (s == NULL)
3900 		s = "UNKNOWN";
3901 	define(macid("{tls_version}", NULL), newstr(s), e);
3902 
3903 	cert = SSL_get_peer_certificate(ssl);
3904 	if (log && LogLevel >= 14)
3905 		sm_syslog(LOG_INFO, e->e_id,
3906 			  "TLS: get_verify in %s: %ld get_peer: 0x%lx",
3907 			  srv ? "srv" : "clt",
3908 			  SSL_get_verify_result(ssl), (u_long) cert);
3909 	if (cert != NULL)
3910 	{
3911 		char buf[MAXNAME];
3912 
3913 		X509_NAME_oneline(X509_get_subject_name(cert),
3914 				  buf, sizeof buf);
3915 		define(macid("{cert_subject}", NULL),
3916 			       newstr(xtextify(buf, "<>\")")), e);
3917 		X509_NAME_oneline(X509_get_issuer_name(cert),
3918 				  buf, sizeof buf);
3919 		define(macid("{cert_issuer}", NULL),
3920 		       newstr(xtextify(buf, "<>\")")), e);
3921 # if _FFR_TLS_1
3922 		X509_NAME_get_text_by_NID(X509_get_subject_name(cert),
3923 					  NID_commonName, buf, sizeof buf);
3924 		define(macid("{cn_subject}", NULL),
3925 		       newstr(xtextify(buf, "<>\")")), e);
3926 		X509_NAME_get_text_by_NID(X509_get_issuer_name(cert),
3927 					  NID_commonName, buf, sizeof buf);
3928 		define(macid("{cn_issuer}", NULL),
3929 		       newstr(xtextify(buf, "<>\")")), e);
3930 # endif /* _FFR_TLS_1 */
3931 	}
3932 	else
3933 	{
3934 		define(macid("{cert_subject}", NULL), "", e);
3935 		define(macid("{cert_issuer}", NULL), "", e);
3936 # if _FFR_TLS_1
3937 		define(macid("{cn_subject}", NULL), "", e);
3938 		define(macid("{cn_issuer}", NULL), "", e);
3939 # endif /* _FFR_TLS_1 */
3940 	}
3941 	switch(SSL_get_verify_result(ssl))
3942 	{
3943 	  case X509_V_OK:
3944 		if (cert != NULL)
3945 		{
3946 			s = "OK";
3947 			r = TLS_AUTH_OK;
3948 		}
3949 		else
3950 		{
3951 			s = "NO";
3952 			r = TLS_AUTH_NO;
3953 		}
3954 		break;
3955 	  default:
3956 		s = "FAIL";
3957 		r = TLS_AUTH_FAIL;
3958 		break;
3959 	}
3960 	define(macid("{verify}", NULL), newstr(s), e);
3961 	if (cert != NULL)
3962 		X509_free(cert);
3963 
3964 	/* do some logging */
3965 	if (log && LogLevel > 9)
3966 	{
3967 		char *vers, *s1, *s2, *bits;
3968 
3969 		vers = macvalue(macid("{tls_version}", NULL), e);
3970 		bits = macvalue(macid("{cipher_bits}", NULL), e);
3971 		s1 = macvalue(macid("{verify}", NULL), e);
3972 		s2 = macvalue(macid("{cipher}", NULL), e);
3973 		sm_syslog(LOG_INFO, NOQID,
3974 			  "TLS: connection %s %.64s, version=%.16s, verify=%.16s, cipher=%.64s, bits=%.6s",
3975 			  srv ? "from" : "to",
3976 			  host == NULL ? "none" : host,
3977 			  vers == NULL ? "none" : vers,
3978 			  s1 == NULL ? "none" : s1,
3979 			  s2 == NULL ? "none" : s2,
3980 			  bits == NULL ? "0" : bits);
3981 		if (LogLevel > 11)
3982 		{
3983 			/*
3984 			**  maybe run xuntextify on the strings?
3985 			**  that is easier to read but makes it maybe a bit
3986 			**  more complicated to figure out the right values
3987 			**  for the access map...
3988 			*/
3989 			s1 = macvalue(macid("{cert_subject}", NULL), e);
3990 			s2 = macvalue(macid("{cert_issuer}", NULL), e);
3991 			sm_syslog(LOG_INFO, NOQID,
3992 				  "TLS: %s cert subject:%.128s, cert issuer=%.128s",
3993 				  srv ? "client" : "server",
3994 				  s1 == NULL ? "none" : s1,
3995 				  s2 == NULL ? "none" : s2);
3996 		}
3997 	}
3998 
3999 	return r;
4000 }
4001 
4002 # if !TLS_NO_RSA
4003 /*
4004 **  TMP_RSA_KEY -- return temporary RSA key
4005 **
4006 **	Parameters:
4007 **		s -- SSL connection structure
4008 **		export --
4009 **		keylength --
4010 **
4011 **	Returns:
4012 **		temporary RSA key.
4013 */
4014 
4015 /* ARGUSED0 */
4016 static RSA *
4017 tmp_rsa_key(s, export, keylength)
4018 	SSL *s;
4019 	int export;
4020 	int keylength;
4021 {
4022 	return rsa_tmp;
4023 }
4024 # endif /* !TLS_NO_RSA */
4025 /*
4026 **  APPS_SSL_INFO_CB -- info callback for TLS connections
4027 **
4028 **	Parameters:
4029 **		s -- SSL connection structure
4030 **		where --
4031 **		ret --
4032 **
4033 **	Returns:
4034 **		none.
4035 */
4036 
4037 void
4038 apps_ssl_info_cb(s, where, ret)
4039 	SSL *s;
4040 	int where;
4041 	int ret;
4042 {
4043 	char *str;
4044 	int w;
4045 	BIO *bio_err = NULL;
4046 
4047 	if (LogLevel > 14)
4048 		sm_syslog(LOG_INFO, NOQID,
4049 			  "info_callback where 0x%x ret %d", where, ret);
4050 
4051 	w = where & ~SSL_ST_MASK;
4052 	if (bio_err == NULL)
4053 		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
4054 
4055 	if (w & SSL_ST_CONNECT)
4056 		str = "SSL_connect";
4057 	else if (w & SSL_ST_ACCEPT)
4058 		str = "SSL_accept";
4059 	else
4060 		str = "undefined";
4061 
4062 	if (where & SSL_CB_LOOP)
4063 	{
4064 		if (LogLevel > 12)
4065 			sm_syslog(LOG_NOTICE, NOQID,
4066 			"%s:%s\n", str, SSL_state_string_long(s));
4067 	}
4068 	else if (where & SSL_CB_ALERT)
4069 	{
4070 		str = (where & SSL_CB_READ) ? "read" : "write";
4071 		if (LogLevel > 12)
4072 			sm_syslog(LOG_NOTICE, NOQID,
4073 		"SSL3 alert %s:%s:%s\n",
4074 			   str, SSL_alert_type_string_long(ret),
4075 			   SSL_alert_desc_string_long(ret));
4076 	}
4077 	else if (where & SSL_CB_EXIT)
4078 	{
4079 		if (ret == 0)
4080 		{
4081 			if (LogLevel > 7)
4082 				sm_syslog(LOG_WARNING, NOQID,
4083 					"%s:failed in %s\n",
4084 					str, SSL_state_string_long(s));
4085 		}
4086 		else if (ret < 0)
4087 		{
4088 			if (LogLevel > 7)
4089 				sm_syslog(LOG_WARNING, NOQID,
4090 					"%s:error in %s\n",
4091 					str, SSL_state_string_long(s));
4092 		}
4093 	}
4094 }
4095 /*
4096 **  TLS_VERIFY_LOG -- log verify error for TLS certificates
4097 **
4098 **	Parameters:
4099 **		ok -- verify ok?
4100 **		ctx -- x509 context
4101 **
4102 **	Returns:
4103 **		0 -- fatal error
4104 **		1 -- ok
4105 */
4106 
4107 static int
4108 tls_verify_log(ok, ctx)
4109 	int ok;
4110 	X509_STORE_CTX *ctx;
4111 {
4112 	SSL *ssl;
4113 	X509 *cert;
4114 	int reason, depth;
4115 	char buf[512];
4116 
4117 	cert = X509_STORE_CTX_get_current_cert(ctx);
4118 	reason = X509_STORE_CTX_get_error(ctx);
4119 	depth = X509_STORE_CTX_get_error_depth(ctx);
4120 	ssl = (SSL *)X509_STORE_CTX_get_ex_data(ctx,
4121 			SSL_get_ex_data_X509_STORE_CTX_idx());
4122 
4123 	if (ssl == NULL)
4124 	{
4125 		/* internal error */
4126 		sm_syslog(LOG_ERR, NOQID,
4127 			  "TLS: internal error: tls_verify_cb: ssl == NULL");
4128 		return 0;
4129 	}
4130 
4131 	X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof buf);
4132 	sm_syslog(LOG_INFO, NOQID,
4133 		  "TLS cert verify: depth=%d %s, state=%d, reason=%s\n",
4134 		  depth, buf, ok, X509_verify_cert_error_string(reason));
4135 	return 1;
4136 }
4137 
4138 /*
4139 **  TLS_VERIFY_CB -- verify callback for TLS certificates
4140 **
4141 **	Parameters:
4142 **		ctx -- x509 context
4143 **
4144 **	Returns:
4145 **		accept connection?
4146 **		currently: always yes.
4147 */
4148 
4149 static int
4150 tls_verify_cb(ctx)
4151 	X509_STORE_CTX *ctx;
4152 {
4153 	int ok;
4154 
4155 	ok = X509_verify_cert(ctx);
4156 	if (ok == 0)
4157 	{
4158 		if (LogLevel > 13)
4159 			return tls_verify_log(ok, ctx);
4160 		return 1;	/* override it */
4161 	}
4162 	return ok;
4163 }
4164 
4165 
4166 /*
4167 **  TLSLOGERR -- log the errors from the TLS error stack
4168 **
4169 **	Parameters:
4170 **		none.
4171 **
4172 **	Returns:
4173 **		none.
4174 */
4175 
4176 void
4177 tlslogerr()
4178 {
4179 	unsigned long l;
4180 	int line, flags;
4181 	unsigned long es;
4182 	char *file, *data;
4183 	char buf[256];
4184 #define CP (const char **)
4185 
4186 	es = CRYPTO_thread_id();
4187 	while ((l = ERR_get_error_line_data(CP &file, &line, CP &data, &flags))
4188 		!= 0)
4189 	{
4190 		sm_syslog(LOG_WARNING, NOQID,
4191 			 "TLS: %lu:%s:%s:%d:%s\n", es, ERR_error_string(l, buf),
4192 			 file, line, (flags & ERR_TXT_STRING) ? data : "");
4193 	}
4194 }
4195 
4196 # endif /* STARTTLS */
4197 #endif /* SMTP */
4198 /*
4199 **  HELP -- implement the HELP command.
4200 **
4201 **	Parameters:
4202 **		topic -- the topic we want help for.
4203 **		e -- envelope
4204 **
4205 **	Returns:
4206 **		none.
4207 **
4208 **	Side Effects:
4209 **		outputs the help file to message output.
4210 */
4211 #define HELPVSTR	"#vers	"
4212 #define HELPVERSION	2
4213 
4214 void
4215 help(topic, e)
4216 	char *topic;
4217 	ENVELOPE *e;
4218 {
4219 	register FILE *hf;
4220 	register char *p;
4221 	int len;
4222 	bool noinfo;
4223 	bool first = TRUE;
4224 	long sff = SFF_OPENASROOT|SFF_REGONLY;
4225 	char buf[MAXLINE];
4226 	char inp[MAXLINE];
4227 	static int foundvers = -1;
4228 	extern char Version[];
4229 
4230 	if (DontLockReadFiles)
4231 		sff |= SFF_NOLOCK;
4232 	if (!bitnset(DBS_HELPFILEINUNSAFEDIRPATH, DontBlameSendmail))
4233 		sff |= SFF_SAFEDIRPATH;
4234 
4235 	if (HelpFile == NULL ||
4236 	    (hf = safefopen(HelpFile, O_RDONLY, 0444, sff)) == NULL)
4237 	{
4238 		/* no help */
4239 		errno = 0;
4240 		message("502 5.3.0 Sendmail %s -- HELP not implemented",
4241 			Version);
4242 		return;
4243 	}
4244 
4245 	if (topic == NULL || *topic == '\0')
4246 	{
4247 		topic = "smtp";
4248 		noinfo = FALSE;
4249 	}
4250 	else
4251 	{
4252 		makelower(topic);
4253 		noinfo = TRUE;
4254 	}
4255 
4256 	len = strlen(topic);
4257 
4258 	while (fgets(buf, sizeof buf, hf) != NULL)
4259 	{
4260 		if (buf[0] == '#')
4261 		{
4262 			if (foundvers < 0 &&
4263 			    strncmp(buf, HELPVSTR, strlen(HELPVSTR)) == 0)
4264 			{
4265 				int h;
4266 
4267 				if (sscanf(buf + strlen(HELPVSTR), "%d",
4268 					   &h) == 1)
4269 					foundvers = h;
4270 			}
4271 			continue;
4272 		}
4273 		if (strncmp(buf, topic, len) == 0)
4274 		{
4275 			if (first)
4276 			{
4277 				first = FALSE;
4278 
4279 				/* print version if no/old vers# in file */
4280 				if (foundvers < 2 && !noinfo)
4281 					message("214-2.0.0 This is Sendmail version %s", Version);
4282 			}
4283 			p = strpbrk(buf, " \t");
4284 			if (p == NULL)
4285 				p = buf + strlen(buf) - 1;
4286 			else
4287 				p++;
4288 			fixcrlf(p, TRUE);
4289 			if (foundvers >= 2)
4290 			{
4291 				translate_dollars(p);
4292 				expand(p, inp, sizeof inp, e);
4293 				p = inp;
4294 			}
4295 			message("214-2.0.0 %s", p);
4296 			noinfo = FALSE;
4297 		}
4298 	}
4299 
4300 	if (noinfo)
4301 		message("504 5.3.0 HELP topic \"%.10s\" unknown", topic);
4302 	else
4303 		message("214 2.0.0 End of HELP info");
4304 
4305 	if (foundvers != 0 && foundvers < HELPVERSION)
4306 	{
4307 		if (LogLevel > 1)
4308 			sm_syslog(LOG_WARNING, e->e_id,
4309 				  "%s too old (require version %d)",
4310 				  HelpFile, HELPVERSION);
4311 
4312 		/* avoid log next time */
4313 		foundvers = 0;
4314 	}
4315 
4316 	(void) fclose(hf);
4317 }
4318