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