milter.c revision 98841
1/*
2 * Copyright (c) 1999-2002 Sendmail, Inc. and its suppliers.
3 *	All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 *
9 */
10
11#include <sendmail.h>
12
13SM_RCSID("@(#)$Id: milter.c,v 8.197 2002/06/12 22:33:48 gshapiro Exp $")
14
15#if MILTER
16# include <libmilter/mfapi.h>
17# include <libmilter/mfdef.h>
18
19# include <errno.h>
20# include <sys/time.h>
21
22# if NETINET || NETINET6
23#  include <arpa/inet.h>
24# endif /* NETINET || NETINET6 */
25
26# include <sm/fdset.h>
27
28static void	milter_connect_timeout __P((void));
29static void	milter_error __P((struct milter *, ENVELOPE *));
30static int	milter_open __P((struct milter *, bool, ENVELOPE *));
31static void	milter_parse_timeouts __P((char *, struct milter *));
32
33static char *MilterConnectMacros[MAXFILTERMACROS + 1];
34static char *MilterHeloMacros[MAXFILTERMACROS + 1];
35static char *MilterEnvFromMacros[MAXFILTERMACROS + 1];
36static char *MilterEnvRcptMacros[MAXFILTERMACROS + 1];
37
38# define MILTER_CHECK_DONE_MSG() \
39	if (*state == SMFIR_REPLYCODE || \
40	    *state == SMFIR_REJECT || \
41	    *state == SMFIR_DISCARD || \
42	    *state == SMFIR_TEMPFAIL) \
43	{ \
44		/* Abort the filters to let them know we are done with msg */ \
45		milter_abort(e); \
46	}
47
48# define MILTER_CHECK_ERROR(action) \
49	if (bitnset(SMF_TEMPFAIL, m->mf_flags)) \
50		*state = SMFIR_TEMPFAIL; \
51	else if (bitnset(SMF_REJECT, m->mf_flags)) \
52		*state = SMFIR_REJECT; \
53	else \
54		action;
55
56# define MILTER_CHECK_REPLYCODE(default) \
57	if (response == NULL || \
58	    strlen(response) + 1 != (size_t) rlen || \
59	    rlen < 3 || \
60	    (response[0] != '4' && response[0] != '5') || \
61	    !isascii(response[1]) || !isdigit(response[1]) || \
62	    !isascii(response[2]) || !isdigit(response[2])) \
63	{ \
64		if (response != NULL) \
65			sm_free(response); /* XXX */ \
66		response = newstr(default); \
67	} \
68	else \
69	{ \
70		char *ptr = response; \
71 \
72		/* Check for unprotected %'s in the string */ \
73		while (*ptr != '\0') \
74		{ \
75			if (*ptr == '%' && *++ptr != '%') \
76			{ \
77				sm_free(response); /* XXX */ \
78				response = newstr(default); \
79				break; \
80			} \
81			ptr++; \
82		} \
83	}
84
85# define MILTER_DF_ERROR(msg) \
86{ \
87	int save_errno = errno; \
88 \
89	if (tTd(64, 5)) \
90	{ \
91		sm_dprintf(msg, dfname, sm_errstring(save_errno)); \
92		sm_dprintf("\n"); \
93	} \
94	if (MilterLogLevel > 0) \
95		sm_syslog(LOG_ERR, e->e_id, msg, dfname, sm_errstring(save_errno)); \
96	if (SuperSafe == SAFE_REALLY) \
97	{ \
98		if (e->e_dfp != NULL) \
99		{ \
100			(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT); \
101			e->e_dfp = NULL; \
102		} \
103		e->e_flags &= ~EF_HAS_DF; \
104	} \
105	errno = save_errno; \
106}
107
108/*
109**  MILTER_TIMEOUT -- make sure socket is ready in time
110**
111**	Parameters:
112**		routine -- routine name for debug/logging
113**		secs -- number of seconds in timeout
114**		write -- waiting to read or write?
115**		started -- whether this is part of a previous sequence
116**
117**	Assumes 'm' is a milter structure for the current socket.
118*/
119
120# define MILTER_TIMEOUT(routine, secs, write, started) \
121{ \
122	int ret; \
123	int save_errno; \
124	fd_set fds; \
125	struct timeval tv; \
126 \
127	if (SM_FD_SETSIZE > 0 && m->mf_sock >= SM_FD_SETSIZE) \
128	{ \
129		if (tTd(64, 5)) \
130			sm_dprintf("milter_%s(%s): socket %d is larger than FD_SETSIZE %d\n", \
131				   (routine), m->mf_name, m->mf_sock, \
132				   SM_FD_SETSIZE); \
133		if (MilterLogLevel > 0) \
134			sm_syslog(LOG_ERR, e->e_id, \
135				  "Milter (%s): socket(%s) %d is larger than FD_SETSIZE %d", \
136				  m->mf_name, (routine), m->mf_sock, \
137				  SM_FD_SETSIZE); \
138		milter_error(m, e); \
139		return NULL; \
140	} \
141 \
142	do \
143	{ \
144		FD_ZERO(&fds); \
145		SM_FD_SET(m->mf_sock, &fds); \
146		tv.tv_sec = (secs); \
147		tv.tv_usec = 0; \
148		ret = select(m->mf_sock + 1, \
149			     (write) ? NULL : &fds, \
150			     (write) ? &fds : NULL, \
151			     NULL, &tv); \
152	} while (ret < 0 && errno == EINTR); \
153 \
154	switch (ret) \
155	{ \
156	  case 0: \
157		if (tTd(64, 5)) \
158			sm_dprintf("milter_%s(%s): timeout\n", (routine), \
159				   m->mf_name); \
160		if (MilterLogLevel > 0) \
161			sm_syslog(LOG_ERR, e->e_id, \
162				  "Milter (%s): %s %s %s %s", \
163				  m->mf_name, "timeout", \
164				  started ? "during" : "before", \
165				  "data", (routine)); \
166		milter_error(m, e); \
167		return NULL; \
168 \
169	  case -1: \
170		save_errno = errno; \
171		if (tTd(64, 5)) \
172			sm_dprintf("milter_%s(%s): select: %s\n", (routine), \
173				   m->mf_name, sm_errstring(save_errno)); \
174		if (MilterLogLevel > 0) \
175		{ \
176			sm_syslog(LOG_ERR, e->e_id, \
177				  "Milter (%s): select(%s): %s", \
178				  m->mf_name, (routine), \
179				  sm_errstring(save_errno)); \
180		} \
181		milter_error(m, e); \
182		return NULL; \
183 \
184	  default: \
185		if (SM_FD_ISSET(m->mf_sock, &fds)) \
186			break; \
187		if (tTd(64, 5)) \
188			sm_dprintf("milter_%s(%s): socket not ready\n", \
189				(routine), m->mf_name); \
190		if (MilterLogLevel > 0) \
191		{ \
192			sm_syslog(LOG_ERR, e->e_id, \
193				  "Milter (%s): socket(%s) not ready", \
194				  m->mf_name, (routine)); \
195		} \
196		milter_error(m, e); \
197		return NULL; \
198	} \
199}
200
201/*
202**  Low level functions
203*/
204
205/*
206**  MILTER_READ -- read from a remote milter filter
207**
208**	Parameters:
209**		m -- milter to read from.
210**		cmd -- return param for command read.
211**		rlen -- return length of response string.
212**		to -- timeout in seconds.
213**		e -- current envelope.
214**
215**	Returns:
216**		response string (may be NULL)
217*/
218
219static char *
220milter_sysread(m, buf, sz, to, e)
221	struct milter *m;
222	char *buf;
223	ssize_t sz;
224	time_t to;
225	ENVELOPE *e;
226{
227	time_t readstart = 0;
228	ssize_t len, curl;
229	bool started = false;
230
231	curl = 0;
232
233	if (to > 0)
234		readstart = curtime();
235
236	for (;;)
237	{
238		if (to > 0)
239		{
240			time_t now;
241
242			now = curtime();
243			if (now - readstart >= to)
244			{
245				if (tTd(64, 5))
246					sm_dprintf("milter_read (%s): %s %s %s",
247						  m->mf_name, "timeout",
248						  started ? "during" : "before",
249						  "data read");
250				if (MilterLogLevel > 0)
251					sm_syslog(LOG_ERR, e->e_id,
252						  "Milter (%s): %s %s %s",
253						  m->mf_name, "timeout",
254						  started ? "during" : "before",
255						  "data read");
256				milter_error(m, e);
257				return NULL;
258			}
259			to -= now - readstart;
260			readstart = now;
261			MILTER_TIMEOUT("read", to, false, started);
262		}
263
264		len = read(m->mf_sock, buf + curl, sz - curl);
265
266		if (len < 0)
267		{
268			int save_errno = errno;
269
270			if (tTd(64, 5))
271				sm_dprintf("milter_read(%s): read returned %ld: %s\n",
272					m->mf_name, (long) len,
273					sm_errstring(save_errno));
274			if (MilterLogLevel > 0)
275				sm_syslog(LOG_ERR, e->e_id,
276					  "Milter (%s): read returned %ld: %s",
277					  m->mf_name, (long) len,
278					  sm_errstring(save_errno));
279			milter_error(m, e);
280			return NULL;
281		}
282
283		started = true;
284		curl += len;
285		if (len == 0 || curl >= sz)
286			break;
287
288	}
289
290	if (curl != sz)
291	{
292		if (tTd(64, 5))
293			sm_dprintf("milter_read(%s): cmd read returned %ld, expecting %ld\n",
294				m->mf_name, (long) curl, (long) sz);
295		if (MilterLogLevel > 0)
296			sm_syslog(LOG_ERR, e->e_id,
297				  "milter_read(%s): cmd read returned %ld, expecting %ld",
298				  m->mf_name, (long) curl, (long) sz);
299		milter_error(m, e);
300		return NULL;
301	}
302	return buf;
303}
304
305static char *
306milter_read(m, cmd, rlen, to, e)
307	struct milter *m;
308	char *cmd;
309	ssize_t *rlen;
310	time_t to;
311	ENVELOPE *e;
312{
313	time_t readstart = 0;
314	ssize_t expl;
315	mi_int32 i;
316	char *buf;
317	char data[MILTER_LEN_BYTES + 1];
318
319	*rlen = 0;
320	*cmd = '\0';
321
322	if (to > 0)
323		readstart = curtime();
324
325	if (milter_sysread(m, data, sizeof data, to, e) == NULL)
326		return NULL;
327
328	/* reset timeout */
329	if (to > 0)
330	{
331		time_t now;
332
333		now = curtime();
334		if (now - readstart >= to)
335		{
336			if (tTd(64, 5))
337				sm_dprintf("milter_read(%s): timeout before data read\n",
338					m->mf_name);
339			if (MilterLogLevel > 0)
340				sm_syslog(LOG_ERR, e->e_id,
341					  "Milter read(%s): timeout before data read",
342					  m->mf_name);
343			milter_error(m, e);
344			return NULL;
345		}
346		to -= now - readstart;
347	}
348
349	*cmd = data[MILTER_LEN_BYTES];
350	data[MILTER_LEN_BYTES] = '\0';
351	(void) memcpy(&i, data, MILTER_LEN_BYTES);
352	expl = ntohl(i) - 1;
353
354	if (tTd(64, 25))
355		sm_dprintf("milter_read(%s): expecting %ld bytes\n",
356			m->mf_name, (long) expl);
357
358	if (expl < 0)
359	{
360		if (tTd(64, 5))
361			sm_dprintf("milter_read(%s): read size %ld out of range\n",
362				m->mf_name, (long) expl);
363		if (MilterLogLevel > 0)
364			sm_syslog(LOG_ERR, e->e_id,
365				  "milter_read(%s): read size %ld out of range",
366				  m->mf_name, (long) expl);
367		milter_error(m, e);
368		return NULL;
369	}
370
371	if (expl == 0)
372		return NULL;
373
374	buf = (char *) xalloc(expl);
375
376	if (milter_sysread(m, buf, expl, to, e) == NULL)
377	{
378		sm_free(buf); /* XXX */
379		return NULL;
380	}
381
382	if (tTd(64, 50))
383		sm_dprintf("milter_read(%s): Returning %*s\n",
384			m->mf_name, (int) expl, buf);
385	*rlen = expl;
386	return buf;
387}
388/*
389**  MILTER_WRITE -- write to a remote milter filter
390**
391**	Parameters:
392**		m -- milter to read from.
393**		cmd -- command to send.
394**		buf -- optional command data.
395**		len -- length of buf.
396**		to -- timeout in seconds.
397**		e -- current envelope.
398**
399**	Returns:
400**		buf if successful, NULL otherwise
401**		Not actually used anywhere but function prototype
402**			must match milter_read()
403*/
404
405static char *
406milter_write(m, cmd, buf, len, to, e)
407	struct milter *m;
408	char cmd;
409	char *buf;
410	ssize_t len;
411	time_t to;
412	ENVELOPE *e;
413{
414	time_t writestart = (time_t) 0;
415	ssize_t sl, i;
416	mi_int32 nl;
417	char data[MILTER_LEN_BYTES + 1];
418	bool started = false;
419
420	if (len < 0 || len > MILTER_CHUNK_SIZE)
421	{
422		if (tTd(64, 5))
423			sm_dprintf("milter_write(%s): length %ld out of range\n",
424				m->mf_name, (long) len);
425		if (MilterLogLevel > 0)
426			sm_syslog(LOG_ERR, e->e_id,
427				  "milter_write(%s): length %ld out of range",
428				  m->mf_name, (long) len);
429		milter_error(m, e);
430		return NULL;
431	}
432
433	if (tTd(64, 20))
434		sm_dprintf("milter_write(%s): cmd %c, len %ld\n",
435			   m->mf_name, cmd, (long) len);
436
437	nl = htonl(len + 1);	/* add 1 for the cmd char */
438	(void) memcpy(data, (char *) &nl, MILTER_LEN_BYTES);
439	data[MILTER_LEN_BYTES] = cmd;
440	sl = MILTER_LEN_BYTES + 1;
441
442	if (to > 0)
443	{
444		writestart = curtime();
445		MILTER_TIMEOUT("write", to, true, started);
446	}
447
448	/* use writev() instead to send the whole stuff at once? */
449	i = write(m->mf_sock, (void *) data, sl);
450	if (i != sl)
451	{
452		int save_errno = errno;
453
454		if (tTd(64, 5))
455			sm_dprintf("milter_write (%s): write(%c) returned %ld, expected %ld: %s\n",
456				   m->mf_name, cmd, (long) i, (long) sl,
457				   sm_errstring(save_errno));
458		if (MilterLogLevel > 0)
459			sm_syslog(LOG_ERR, e->e_id,
460				  "Milter (%s): write(%c) returned %ld, expected %ld: %s",
461				  m->mf_name, cmd, (long) i, (long) sl,
462				  sm_errstring(save_errno));
463		milter_error(m, e);
464		return buf;
465	}
466
467	if (len <= 0 || buf == NULL)
468		return buf;
469
470	if (tTd(64, 50))
471		sm_dprintf("milter_write(%s): Sending %*s\n",
472			   m->mf_name, (int) len, buf);
473	started = true;
474
475	if (to > 0)
476	{
477		time_t now;
478
479		now = curtime();
480		if (now - writestart >= to)
481		{
482			if (tTd(64, 5))
483				sm_dprintf("milter_write(%s): timeout before data write\n",
484					   m->mf_name);
485			if (MilterLogLevel > 0)
486				sm_syslog(LOG_ERR, e->e_id,
487					  "Milter (%s): timeout before data write",
488					  m->mf_name);
489			milter_error(m, e);
490			return NULL;
491		}
492		else
493		{
494			to -= now - writestart;
495			MILTER_TIMEOUT("write", to, true, started);
496		}
497	}
498
499	i = write(m->mf_sock, (void *) buf, len);
500	if (i != len)
501	{
502		int save_errno = errno;
503
504		if (tTd(64, 5))
505			sm_dprintf("milter_write(%s): write(%c) returned %ld, expected %ld: %s\n",
506				   m->mf_name, cmd, (long) i, (long) sl,
507				   sm_errstring(save_errno));
508		if (MilterLogLevel > 0)
509			sm_syslog(LOG_ERR, e->e_id,
510				  "Milter (%s): write(%c) returned %ld, expected %ld: %s",
511				  m->mf_name, cmd, (long) i, (long) len,
512				  sm_errstring(save_errno));
513		milter_error(m, e);
514		return NULL;
515	}
516	return buf;
517}
518
519/*
520**  Utility functions
521*/
522
523/*
524**  MILTER_OPEN -- connect to remote milter filter
525**
526**	Parameters:
527**		m -- milter to connect to.
528**		parseonly -- parse but don't connect.
529**		e -- current envelope.
530**
531**	Returns:
532**		connected socket if sucessful && !parseonly,
533**		0 upon parse success if parseonly,
534**		-1 otherwise.
535*/
536
537static jmp_buf	MilterConnectTimeout;
538
539static int
540milter_open(m, parseonly, e)
541	struct milter *m;
542	bool parseonly;
543	ENVELOPE *e;
544{
545	int sock = 0;
546	SOCKADDR_LEN_T addrlen = 0;
547	int addrno = 0;
548	int save_errno;
549	char *p;
550	char *colon;
551	char *at;
552	struct hostent *hp = NULL;
553	SOCKADDR addr;
554
555	if (m->mf_conn == NULL || m->mf_conn[0] == '\0')
556	{
557		if (tTd(64, 5))
558			sm_dprintf("X%s: empty or missing socket information\n",
559				   m->mf_name);
560		if (parseonly)
561			syserr("X%s: empty or missing socket information",
562			       m->mf_name);
563		else if (MilterLogLevel > 10)
564			sm_syslog(LOG_ERR, e->e_id,
565				  "Milter (%s): empty or missing socket information",
566				  m->mf_name);
567		milter_error(m, e);
568		return -1;
569	}
570
571	/* protocol:filename or protocol:port@host */
572	memset(&addr, '\0', sizeof addr);
573	p = m->mf_conn;
574	colon = strchr(p, ':');
575	if (colon != NULL)
576	{
577		*colon = '\0';
578
579		if (*p == '\0')
580		{
581# if NETUNIX
582			/* default to AF_UNIX */
583			addr.sa.sa_family = AF_UNIX;
584# else /* NETUNIX */
585#  if NETINET
586			/* default to AF_INET */
587			addr.sa.sa_family = AF_INET;
588#  else /* NETINET */
589#   if NETINET6
590			/* default to AF_INET6 */
591			addr.sa.sa_family = AF_INET6;
592#   else /* NETINET6 */
593			/* no protocols available */
594			sm_syslog(LOG_ERR, e->e_id,
595				  "Milter (%s): no valid socket protocols available",
596				  m->mf_name);
597			milter_error(m, e);
598			return -1;
599#   endif /* NETINET6 */
600#  endif /* NETINET */
601# endif /* NETUNIX */
602		}
603# if NETUNIX
604		else if (sm_strcasecmp(p, "unix") == 0 ||
605			 sm_strcasecmp(p, "local") == 0)
606			addr.sa.sa_family = AF_UNIX;
607# endif /* NETUNIX */
608# if NETINET
609		else if (sm_strcasecmp(p, "inet") == 0)
610			addr.sa.sa_family = AF_INET;
611# endif /* NETINET */
612# if NETINET6
613		else if (sm_strcasecmp(p, "inet6") == 0)
614			addr.sa.sa_family = AF_INET6;
615# endif /* NETINET6 */
616		else
617		{
618# ifdef EPROTONOSUPPORT
619			errno = EPROTONOSUPPORT;
620# else /* EPROTONOSUPPORT */
621			errno = EINVAL;
622# endif /* EPROTONOSUPPORT */
623			if (tTd(64, 5))
624				sm_dprintf("X%s: unknown socket type %s\n",
625					m->mf_name, p);
626			if (parseonly)
627				syserr("X%s: unknown socket type %s",
628				       m->mf_name, p);
629			else if (MilterLogLevel > 10)
630				sm_syslog(LOG_ERR, e->e_id,
631					  "Milter (%s): unknown socket type %s",
632					  m->mf_name, p);
633			milter_error(m, e);
634			return -1;
635		}
636		*colon++ = ':';
637	}
638	else
639	{
640		/* default to AF_UNIX */
641		addr.sa.sa_family = AF_UNIX;
642		colon = p;
643	}
644
645# if NETUNIX
646	if (addr.sa.sa_family == AF_UNIX)
647	{
648		long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_EXECOK;
649
650		at = colon;
651		if (strlen(colon) >= sizeof addr.sunix.sun_path)
652		{
653			if (tTd(64, 5))
654				sm_dprintf("X%s: local socket name %s too long\n",
655					m->mf_name, colon);
656			errno = EINVAL;
657			if (parseonly)
658				syserr("X%s: local socket name %s too long",
659				       m->mf_name, colon);
660			else if (MilterLogLevel > 10)
661				sm_syslog(LOG_ERR, e->e_id,
662					  "Milter (%s): local socket name %s too long",
663					  m->mf_name, colon);
664			milter_error(m, e);
665			return -1;
666		}
667		errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff,
668				 S_IRUSR|S_IWUSR, NULL);
669
670		/* if just parsing .cf file, socket doesn't need to exist */
671		if (parseonly && errno == ENOENT)
672		{
673			if (OpMode == MD_DAEMON ||
674			    OpMode == MD_FGDAEMON)
675				(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
676						     "WARNING: X%s: local socket name %s missing\n",
677						     m->mf_name, colon);
678		}
679		else if (errno != 0)
680		{
681			/* if not safe, don't create */
682			save_errno = errno;
683			if (tTd(64, 5))
684				sm_dprintf("X%s: local socket name %s unsafe\n",
685					m->mf_name, colon);
686			errno = save_errno;
687			if (parseonly)
688			{
689				if (OpMode == MD_DAEMON ||
690				    OpMode == MD_FGDAEMON ||
691				    OpMode == MD_SMTP)
692					syserr("X%s: local socket name %s unsafe",
693					       m->mf_name, colon);
694			}
695			else if (MilterLogLevel > 10)
696				sm_syslog(LOG_ERR, e->e_id,
697					  "Milter (%s): local socket name %s unsafe",
698					  m->mf_name, colon);
699			milter_error(m, e);
700			return -1;
701		}
702
703		(void) sm_strlcpy(addr.sunix.sun_path, colon,
704			       sizeof addr.sunix.sun_path);
705		addrlen = sizeof (struct sockaddr_un);
706	}
707	else
708# endif /* NETUNIX */
709# if NETINET || NETINET6
710	if (false
711#  if NETINET
712		 || addr.sa.sa_family == AF_INET
713#  endif /* NETINET */
714#  if NETINET6
715		 || addr.sa.sa_family == AF_INET6
716#  endif /* NETINET6 */
717		 )
718	{
719		unsigned short port;
720
721		/* Parse port@host */
722		at = strchr(colon, '@');
723		if (at == NULL)
724		{
725			if (tTd(64, 5))
726				sm_dprintf("X%s: bad address %s (expected port@host)\n",
727					m->mf_name, colon);
728			if (parseonly)
729				syserr("X%s: bad address %s (expected port@host)",
730				       m->mf_name, colon);
731			else if (MilterLogLevel > 10)
732				sm_syslog(LOG_ERR, e->e_id,
733					  "Milter (%s): bad address %s (expected port@host)",
734					  m->mf_name, colon);
735			milter_error(m, e);
736			return -1;
737		}
738		*at = '\0';
739		if (isascii(*colon) && isdigit(*colon))
740			port = htons((unsigned short) atoi(colon));
741		else
742		{
743#  ifdef NO_GETSERVBYNAME
744			if (tTd(64, 5))
745				sm_dprintf("X%s: invalid port number %s\n",
746					m->mf_name, colon);
747			if (parseonly)
748				syserr("X%s: invalid port number %s",
749				       m->mf_name, colon);
750			else if (MilterLogLevel > 10)
751				sm_syslog(LOG_ERR, e->e_id,
752					  "Milter (%s): invalid port number %s",
753					  m->mf_name, colon);
754			milter_error(m, e);
755			return -1;
756#  else /* NO_GETSERVBYNAME */
757			register struct servent *sp;
758
759			sp = getservbyname(colon, "tcp");
760			if (sp == NULL)
761			{
762				save_errno = errno;
763				if (tTd(64, 5))
764					sm_dprintf("X%s: unknown port name %s\n",
765						m->mf_name, colon);
766				errno = save_errno;
767				if (parseonly)
768					syserr("X%s: unknown port name %s",
769					       m->mf_name, colon);
770				else if (MilterLogLevel > 10)
771					sm_syslog(LOG_ERR, e->e_id,
772						  "Milter (%s): unknown port name %s",
773						  m->mf_name, colon);
774				milter_error(m, e);
775				return -1;
776			}
777			port = sp->s_port;
778#  endif /* NO_GETSERVBYNAME */
779		}
780		*at++ = '@';
781		if (*at == '[')
782		{
783			char *end;
784
785			end = strchr(at, ']');
786			if (end != NULL)
787			{
788				bool found = false;
789#  if NETINET
790				unsigned long hid = INADDR_NONE;
791#  endif /* NETINET */
792#  if NETINET6
793				struct sockaddr_in6 hid6;
794#  endif /* NETINET6 */
795
796				*end = '\0';
797#  if NETINET
798				if (addr.sa.sa_family == AF_INET &&
799				    (hid = inet_addr(&at[1])) != INADDR_NONE)
800				{
801					addr.sin.sin_addr.s_addr = hid;
802					addr.sin.sin_port = port;
803					found = true;
804				}
805#  endif /* NETINET */
806#  if NETINET6
807				(void) memset(&hid6, '\0', sizeof hid6);
808				if (addr.sa.sa_family == AF_INET6 &&
809				    anynet_pton(AF_INET6, &at[1],
810						&hid6.sin6_addr) == 1)
811				{
812					addr.sin6.sin6_addr = hid6.sin6_addr;
813					addr.sin6.sin6_port = port;
814					found = true;
815				}
816#  endif /* NETINET6 */
817				*end = ']';
818				if (!found)
819				{
820					if (tTd(64, 5))
821						sm_dprintf("X%s: Invalid numeric domain spec \"%s\"\n",
822							m->mf_name, at);
823					if (parseonly)
824						syserr("X%s: Invalid numeric domain spec \"%s\"",
825						       m->mf_name, at);
826					else if (MilterLogLevel > 10)
827						sm_syslog(LOG_ERR, e->e_id,
828							  "Milter (%s): Invalid numeric domain spec \"%s\"",
829							  m->mf_name, at);
830					milter_error(m, e);
831					return -1;
832				}
833			}
834			else
835			{
836				if (tTd(64, 5))
837					sm_dprintf("X%s: Invalid numeric domain spec \"%s\"\n",
838						m->mf_name, at);
839				if (parseonly)
840					syserr("X%s: Invalid numeric domain spec \"%s\"",
841					       m->mf_name, at);
842				else if (MilterLogLevel > 10)
843					sm_syslog(LOG_ERR, e->e_id,
844						  "Milter (%s): Invalid numeric domain spec \"%s\"",
845						  m->mf_name, at);
846				milter_error(m, e);
847				return -1;
848			}
849		}
850		else
851		{
852			hp = sm_gethostbyname(at, addr.sa.sa_family);
853			if (hp == NULL)
854			{
855				save_errno = errno;
856				if (tTd(64, 5))
857					sm_dprintf("X%s: Unknown host name %s\n",
858						   m->mf_name, at);
859				errno = save_errno;
860				if (parseonly)
861					syserr("X%s: Unknown host name %s",
862					       m->mf_name, at);
863				else if (MilterLogLevel > 10)
864					sm_syslog(LOG_ERR, e->e_id,
865						  "Milter (%s): Unknown host name %s",
866						  m->mf_name, at);
867				milter_error(m, e);
868				return -1;
869			}
870			addr.sa.sa_family = hp->h_addrtype;
871			switch (hp->h_addrtype)
872			{
873#  if NETINET
874			  case AF_INET:
875				memmove(&addr.sin.sin_addr,
876					hp->h_addr, INADDRSZ);
877				addr.sin.sin_port = port;
878				addrlen = sizeof (struct sockaddr_in);
879				addrno = 1;
880				break;
881#  endif /* NETINET */
882
883#  if NETINET6
884			  case AF_INET6:
885				memmove(&addr.sin6.sin6_addr,
886					hp->h_addr, IN6ADDRSZ);
887				addr.sin6.sin6_port = port;
888				addrlen = sizeof (struct sockaddr_in6);
889				addrno = 1;
890				break;
891#  endif /* NETINET6 */
892
893			  default:
894				if (tTd(64, 5))
895					sm_dprintf("X%s: Unknown protocol for %s (%d)\n",
896						   m->mf_name, at,
897						   hp->h_addrtype);
898				if (parseonly)
899					syserr("X%s: Unknown protocol for %s (%d)",
900					       m->mf_name, at, hp->h_addrtype);
901				else if (MilterLogLevel > 10)
902					sm_syslog(LOG_ERR, e->e_id,
903						  "Milter (%s): Unknown protocol for %s (%d)",
904						  m->mf_name, at,
905						  hp->h_addrtype);
906				milter_error(m, e);
907#  if NETINET6
908				freehostent(hp);
909#  endif /* NETINET6 */
910				return -1;
911			}
912		}
913	}
914	else
915# endif /* NETINET || NETINET6 */
916	{
917		if (tTd(64, 5))
918			sm_dprintf("X%s: unknown socket protocol\n",
919				   m->mf_name);
920		if (parseonly)
921			syserr("X%s: unknown socket protocol", m->mf_name);
922		else if (MilterLogLevel > 10)
923			sm_syslog(LOG_ERR, e->e_id,
924				  "Milter (%s): unknown socket protocol",
925				  m->mf_name);
926		milter_error(m, e);
927		return -1;
928	}
929
930	/* just parsing through? */
931	if (parseonly)
932	{
933		m->mf_state = SMFS_READY;
934# if NETINET6
935		if (hp != NULL)
936			freehostent(hp);
937# endif /* NETINET6 */
938		return 0;
939	}
940
941	/* sanity check */
942	if (m->mf_state != SMFS_READY &&
943	    m->mf_state != SMFS_CLOSED)
944	{
945		/* shouldn't happen */
946		if (tTd(64, 1))
947			sm_dprintf("Milter (%s): Trying to open filter in state %c\n",
948				   m->mf_name, (char) m->mf_state);
949		milter_error(m, e);
950# if NETINET6
951		if (hp != NULL)
952			freehostent(hp);
953# endif /* NETINET6 */
954		return -1;
955	}
956
957	/* nope, actually connecting */
958	for (;;)
959	{
960		sock = socket(addr.sa.sa_family, SOCK_STREAM, 0);
961		if (sock < 0)
962		{
963			save_errno = errno;
964			if (tTd(64, 5))
965				sm_dprintf("Milter (%s): error creating socket: %s\n",
966					   m->mf_name,
967					   sm_errstring(save_errno));
968			if (MilterLogLevel > 0)
969				sm_syslog(LOG_ERR, e->e_id,
970					  "Milter (%s): error creating socket: %s",
971					  m->mf_name, sm_errstring(save_errno));
972			milter_error(m, e);
973# if NETINET6
974			if (hp != NULL)
975				freehostent(hp);
976# endif /* NETINET6 */
977			return -1;
978		}
979
980		if (setjmp(MilterConnectTimeout) == 0)
981		{
982			SM_EVENT *ev = NULL;
983			int i;
984
985			if (m->mf_timeout[SMFTO_CONNECT] > 0)
986				ev = sm_setevent(m->mf_timeout[SMFTO_CONNECT],
987						 milter_connect_timeout, 0);
988
989			i = connect(sock, (struct sockaddr *) &addr, addrlen);
990			save_errno = errno;
991			if (ev != NULL)
992				sm_clrevent(ev);
993			errno = save_errno;
994			if (i >= 0)
995				break;
996		}
997
998		/* couldn't connect.... try next address */
999		save_errno = errno;
1000		p = CurHostName;
1001		CurHostName = at;
1002		if (tTd(64, 5))
1003			sm_dprintf("milter_open (%s): open %s failed: %s\n",
1004				   m->mf_name, at, sm_errstring(save_errno));
1005		if (MilterLogLevel > 13)
1006			sm_syslog(LOG_INFO, e->e_id,
1007				  "Milter (%s): open %s failed: %s",
1008				  m->mf_name, at, sm_errstring(save_errno));
1009		CurHostName = p;
1010		(void) close(sock);
1011
1012		/* try next address */
1013		if (hp != NULL && hp->h_addr_list[addrno] != NULL)
1014		{
1015			switch (addr.sa.sa_family)
1016			{
1017# if NETINET
1018			  case AF_INET:
1019				memmove(&addr.sin.sin_addr,
1020					hp->h_addr_list[addrno++],
1021					INADDRSZ);
1022				break;
1023# endif /* NETINET */
1024
1025# if NETINET6
1026			  case AF_INET6:
1027				memmove(&addr.sin6.sin6_addr,
1028					hp->h_addr_list[addrno++],
1029					IN6ADDRSZ);
1030				break;
1031# endif /* NETINET6 */
1032
1033			  default:
1034				if (tTd(64, 5))
1035					sm_dprintf("X%s: Unknown protocol for %s (%d)\n",
1036						   m->mf_name, at,
1037						   hp->h_addrtype);
1038				if (MilterLogLevel > 0)
1039					sm_syslog(LOG_ERR, e->e_id,
1040						  "Milter (%s): Unknown protocol for %s (%d)",
1041						  m->mf_name, at,
1042						  hp->h_addrtype);
1043				milter_error(m, e);
1044# if NETINET6
1045				freehostent(hp);
1046# endif /* NETINET6 */
1047				return -1;
1048			}
1049			continue;
1050		}
1051		p = CurHostName;
1052		CurHostName = at;
1053		if (tTd(64, 5))
1054			sm_dprintf("X%s: error connecting to filter: %s\n",
1055				   m->mf_name, sm_errstring(save_errno));
1056		if (MilterLogLevel > 0)
1057			sm_syslog(LOG_ERR, e->e_id,
1058				  "Milter (%s): error connecting to filter: %s",
1059				  m->mf_name, sm_errstring(save_errno));
1060		CurHostName = p;
1061		milter_error(m, e);
1062# if NETINET6
1063		if (hp != NULL)
1064			freehostent(hp);
1065# endif /* NETINET6 */
1066		return -1;
1067	}
1068	m->mf_state = SMFS_OPEN;
1069# if NETINET6
1070	if (hp != NULL)
1071	{
1072		freehostent(hp);
1073		hp = NULL;
1074	}
1075# endif /* NETINET6 */
1076	return sock;
1077}
1078
1079static void
1080milter_connect_timeout()
1081{
1082	/*
1083	**  NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
1084	**	ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
1085	**	DOING.
1086	*/
1087
1088	errno = ETIMEDOUT;
1089	longjmp(MilterConnectTimeout, 1);
1090}
1091/*
1092**  MILTER_SETUP -- setup structure for a mail filter
1093**
1094**	Parameters:
1095**		line -- the options line.
1096**
1097**	Returns:
1098**		none
1099*/
1100
1101void
1102milter_setup(line)
1103	char *line;
1104{
1105	char fcode;
1106	register char *p;
1107	register struct milter *m;
1108	STAB *s;
1109
1110	/* collect the filter name */
1111	for (p = line;
1112	     *p != '\0' && *p != ',' && !(isascii(*p) && isspace(*p));
1113	     p++)
1114		continue;
1115	if (*p != '\0')
1116		*p++ = '\0';
1117	if (line[0] == '\0')
1118	{
1119		syserr("name required for mail filter");
1120		return;
1121	}
1122	m = (struct milter *) xalloc(sizeof *m);
1123	memset((char *) m, '\0', sizeof *m);
1124	m->mf_name = newstr(line);
1125	m->mf_state = SMFS_READY;
1126	m->mf_sock = -1;
1127	m->mf_timeout[SMFTO_CONNECT] = (time_t) 300;
1128	m->mf_timeout[SMFTO_WRITE] = (time_t) 10;
1129	m->mf_timeout[SMFTO_READ] = (time_t) 10;
1130	m->mf_timeout[SMFTO_EOM] = (time_t) 300;
1131
1132	/* now scan through and assign info from the fields */
1133	while (*p != '\0')
1134	{
1135		char *delimptr;
1136
1137		while (*p != '\0' &&
1138		       (*p == ',' || (isascii(*p) && isspace(*p))))
1139			p++;
1140
1141		/* p now points to field code */
1142		fcode = *p;
1143		while (*p != '\0' && *p != '=' && *p != ',')
1144			p++;
1145		if (*p++ != '=')
1146		{
1147			syserr("X%s: `=' expected", m->mf_name);
1148			return;
1149		}
1150		while (isascii(*p) && isspace(*p))
1151			p++;
1152
1153		/* p now points to the field body */
1154		p = munchstring(p, &delimptr, ',');
1155
1156		/* install the field into the filter struct */
1157		switch (fcode)
1158		{
1159		  case 'S':		/* socket */
1160			if (p == NULL)
1161				m->mf_conn = NULL;
1162			else
1163				m->mf_conn = newstr(p);
1164			break;
1165
1166		  case 'F':		/* Milter flags configured on MTA */
1167			for (; *p != '\0'; p++)
1168			{
1169				if (!(isascii(*p) && isspace(*p)))
1170					setbitn(bitidx(*p), m->mf_flags);
1171			}
1172			break;
1173
1174		  case 'T':		/* timeouts */
1175			milter_parse_timeouts(p, m);
1176			break;
1177
1178		  default:
1179			syserr("X%s: unknown filter equate %c=",
1180			       m->mf_name, fcode);
1181			break;
1182		}
1183		p = delimptr;
1184	}
1185
1186	/* early check for errors */
1187	(void) milter_open(m, true, CurEnv);
1188
1189	/* enter the filter into the symbol table */
1190	s = stab(m->mf_name, ST_MILTER, ST_ENTER);
1191	if (s->s_milter != NULL)
1192		syserr("X%s: duplicate filter definition", m->mf_name);
1193	else
1194		s->s_milter = m;
1195}
1196/*
1197**  MILTER_CONFIG -- parse option list into an array and check config
1198**
1199**	Called when reading configuration file.
1200**
1201**	Parameters:
1202**		spec -- the filter list.
1203**		list -- the array to fill in.
1204**		max -- the maximum number of entries in list.
1205**
1206**	Returns:
1207**		none
1208*/
1209
1210void
1211milter_config(spec, list, max)
1212	char *spec;
1213	struct milter **list;
1214	int max;
1215{
1216	int numitems = 0;
1217	register char *p;
1218
1219	/* leave one for the NULL signifying the end of the list */
1220	max--;
1221
1222	for (p = spec; p != NULL; )
1223	{
1224		STAB *s;
1225
1226		while (isascii(*p) && isspace(*p))
1227			p++;
1228		if (*p == '\0')
1229			break;
1230		spec = p;
1231
1232		if (numitems >= max)
1233		{
1234			syserr("Too many filters defined, %d max", max);
1235			if (max > 0)
1236				list[0] = NULL;
1237			return;
1238		}
1239#if _FFR_MILTER_PERDAEMON
1240		p = strpbrk(p, ";,");
1241#else /* _FFR_MILTER_PERDAEMON */
1242		p = strpbrk(p, ",");
1243#endif /* _FFR_MILTER_PERDAEMON */
1244		if (p != NULL)
1245			*p++ = '\0';
1246
1247		s = stab(spec, ST_MILTER, ST_FIND);
1248		if (s == NULL)
1249		{
1250			syserr("InputFilter %s not defined", spec);
1251			ExitStat = EX_CONFIG;
1252			return;
1253		}
1254		list[numitems++] = s->s_milter;
1255	}
1256	list[numitems] = NULL;
1257
1258	/* if not set, set to LogLevel */
1259	if (MilterLogLevel == -1)
1260		MilterLogLevel = LogLevel;
1261}
1262/*
1263**  MILTER_PARSE_TIMEOUTS -- parse timeout list
1264**
1265**	Called when reading configuration file.
1266**
1267**	Parameters:
1268**		spec -- the timeout list.
1269**		m -- milter to set.
1270**
1271**	Returns:
1272**		none
1273*/
1274
1275static void
1276milter_parse_timeouts(spec, m)
1277	char *spec;
1278	struct milter *m;
1279{
1280	char fcode;
1281	register char *p;
1282
1283	p = spec;
1284
1285	/* now scan through and assign info from the fields */
1286	while (*p != '\0')
1287	{
1288		char *delimptr;
1289
1290		while (*p != '\0' &&
1291		       (*p == ';' || (isascii(*p) && isspace(*p))))
1292			p++;
1293
1294		/* p now points to field code */
1295		fcode = *p;
1296		while (*p != '\0' && *p != ':')
1297			p++;
1298		if (*p++ != ':')
1299		{
1300			syserr("X%s, T=: `:' expected", m->mf_name);
1301			return;
1302		}
1303		while (isascii(*p) && isspace(*p))
1304			p++;
1305
1306		/* p now points to the field body */
1307		p = munchstring(p, &delimptr, ';');
1308
1309		/* install the field into the filter struct */
1310		switch (fcode)
1311		{
1312		  case 'C':
1313			m->mf_timeout[SMFTO_CONNECT] = convtime(p, 's');
1314			if (tTd(64, 5))
1315				sm_dprintf("X%s: %c=%lu\n",
1316					   m->mf_name, fcode,
1317					   (unsigned long) m->mf_timeout[SMFTO_CONNECT]);
1318			break;
1319
1320		  case 'S':
1321			m->mf_timeout[SMFTO_WRITE] = convtime(p, 's');
1322			if (tTd(64, 5))
1323				sm_dprintf("X%s: %c=%lu\n",
1324					   m->mf_name, fcode,
1325					   (unsigned long) m->mf_timeout[SMFTO_WRITE]);
1326			break;
1327
1328		  case 'R':
1329			m->mf_timeout[SMFTO_READ] = convtime(p, 's');
1330			if (tTd(64, 5))
1331				sm_dprintf("X%s: %c=%lu\n",
1332					   m->mf_name, fcode,
1333					   (unsigned long) m->mf_timeout[SMFTO_READ]);
1334			break;
1335
1336		  case 'E':
1337			m->mf_timeout[SMFTO_EOM] = convtime(p, 's');
1338			if (tTd(64, 5))
1339				sm_dprintf("X%s: %c=%lu\n",
1340					   m->mf_name, fcode,
1341					   (unsigned long) m->mf_timeout[SMFTO_EOM]);
1342			break;
1343
1344		  default:
1345			if (tTd(64, 5))
1346				sm_dprintf("X%s: %c unknown\n",
1347					   m->mf_name, fcode);
1348			syserr("X%s: unknown filter timeout %c",
1349			       m->mf_name, fcode);
1350			break;
1351		}
1352		p = delimptr;
1353	}
1354}
1355/*
1356**  MILTER_SET_OPTION -- set an individual milter option
1357**
1358**	Parameters:
1359**		name -- the name of the option.
1360**		val -- the value of the option.
1361**		sticky -- if set, don't let other setoptions override
1362**			this value.
1363**
1364**	Returns:
1365**		none.
1366*/
1367
1368/* set if Milter sub-option is stuck */
1369static BITMAP256	StickyMilterOpt;
1370
1371static struct milteropt
1372{
1373	char		*mo_name;	/* long name of milter option */
1374	unsigned char	mo_code;	/* code for option */
1375} MilterOptTab[] =
1376{
1377# define MO_MACROS_CONNECT		0x01
1378	{ "macros.connect",		MO_MACROS_CONNECT		},
1379# define MO_MACROS_HELO			0x02
1380	{ "macros.helo",		MO_MACROS_HELO			},
1381# define MO_MACROS_ENVFROM		0x03
1382	{ "macros.envfrom",		MO_MACROS_ENVFROM		},
1383# define MO_MACROS_ENVRCPT		0x04
1384	{ "macros.envrcpt",		MO_MACROS_ENVRCPT		},
1385# define MO_LOGLEVEL			0x05
1386	{ "loglevel",			MO_LOGLEVEL			},
1387	{ NULL,				0				},
1388};
1389
1390void
1391milter_set_option(name, val, sticky)
1392	char *name;
1393	char *val;
1394	bool sticky;
1395{
1396	int nummac = 0;
1397	register struct milteropt *mo;
1398	char *p;
1399	char **macros = NULL;
1400
1401	if (tTd(37, 2) || tTd(64, 5))
1402		sm_dprintf("milter_set_option(%s = %s)", name, val);
1403
1404	if (name == NULL)
1405	{
1406		syserr("milter_set_option: invalid Milter option, must specify suboption");
1407		return;
1408	}
1409
1410	for (mo = MilterOptTab; mo->mo_name != NULL; mo++)
1411	{
1412		if (sm_strcasecmp(mo->mo_name, name) == 0)
1413			break;
1414	}
1415
1416	if (mo->mo_name == NULL)
1417	{
1418		syserr("milter_set_option: invalid Milter option %s", name);
1419		return;
1420	}
1421
1422	/*
1423	**  See if this option is preset for us.
1424	*/
1425
1426	if (!sticky && bitnset(mo->mo_code, StickyMilterOpt))
1427	{
1428		if (tTd(37, 2) || tTd(64,5))
1429			sm_dprintf(" (ignored)\n");
1430		return;
1431	}
1432
1433	if (tTd(37, 2) || tTd(64,5))
1434		sm_dprintf("\n");
1435
1436	switch (mo->mo_code)
1437	{
1438	  case MO_LOGLEVEL:
1439		MilterLogLevel = atoi(val);
1440		break;
1441
1442	  case MO_MACROS_CONNECT:
1443		if (macros == NULL)
1444			macros = MilterConnectMacros;
1445		/* FALLTHROUGH */
1446
1447	  case MO_MACROS_HELO:
1448		if (macros == NULL)
1449			macros = MilterHeloMacros;
1450		/* FALLTHROUGH */
1451
1452	  case MO_MACROS_ENVFROM:
1453		if (macros == NULL)
1454			macros = MilterEnvFromMacros;
1455		/* FALLTHROUGH */
1456
1457	  case MO_MACROS_ENVRCPT:
1458		if (macros == NULL)
1459			macros = MilterEnvRcptMacros;
1460
1461		p = newstr(val);
1462		while (*p != '\0')
1463		{
1464			char *macro;
1465
1466			/* Skip leading commas, spaces */
1467			while (*p != '\0' &&
1468			       (*p == ',' || (isascii(*p) && isspace(*p))))
1469				p++;
1470
1471			if (*p == '\0')
1472				break;
1473
1474			/* Find end of macro */
1475			macro = p;
1476			while (*p != '\0' && *p != ',' &&
1477			       isascii(*p) && !isspace(*p))
1478				p++;
1479			if (*p != '\0')
1480				*p++ = '\0';
1481
1482			if (nummac >= MAXFILTERMACROS)
1483			{
1484				syserr("milter_set_option: too many macros in Milter.%s (max %d)",
1485				       name, MAXFILTERMACROS);
1486				macros[nummac] = NULL;
1487				break;
1488			}
1489			macros[nummac++] = macro;
1490		}
1491		macros[nummac] = NULL;
1492		break;
1493
1494	  default:
1495		syserr("milter_set_option: invalid Milter option %s", name);
1496		break;
1497	}
1498	if (sticky)
1499		setbitn(mo->mo_code, StickyMilterOpt);
1500}
1501/*
1502**  MILTER_REOPEN_DF -- open & truncate the data file (for replbody)
1503**
1504**	Parameters:
1505**		e -- current envelope.
1506**
1507**	Returns:
1508**		0 if succesful, -1 otherwise
1509*/
1510
1511static int
1512milter_reopen_df(e)
1513	ENVELOPE *e;
1514{
1515	char dfname[MAXPATHLEN];
1516
1517	(void) sm_strlcpy(dfname, queuename(e, DATAFL_LETTER), sizeof dfname);
1518
1519	/*
1520	**  In SuperSafe == SAFE_REALLY mode, e->e_dfp is a read-only FP so
1521	**  close and reopen writable (later close and reopen
1522	**  read only again).
1523	**
1524	**  In SuperSafe != SAFE_REALLY mode, e->e_dfp still points at the
1525	**  buffered file I/O descriptor, still open for writing
1526	**  so there isn't as much work to do, just truncate it
1527	**  and go.
1528	*/
1529
1530	if (SuperSafe == SAFE_REALLY)
1531	{
1532		/* close read-only data file */
1533		if (bitset(EF_HAS_DF, e->e_flags) && e->e_dfp != NULL)
1534		{
1535			(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
1536			e->e_flags &= ~EF_HAS_DF;
1537		}
1538
1539		/* open writable */
1540		if ((e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, dfname,
1541					   SM_IO_RDWR, NULL)) == NULL)
1542		{
1543			MILTER_DF_ERROR("milter_reopen_df: sm_io_open %s: %s");
1544			return -1;
1545		}
1546	}
1547	else if (e->e_dfp == NULL)
1548	{
1549		/* shouldn't happen */
1550		errno = ENOENT;
1551		MILTER_DF_ERROR("milter_reopen_df: NULL e_dfp (%s: %s)");
1552		return -1;
1553	}
1554	return 0;
1555}
1556/*
1557**  MILTER_RESET_DF -- re-open read-only the data file (for replbody)
1558**
1559**	Parameters:
1560**		e -- current envelope.
1561**
1562**	Returns:
1563**		0 if succesful, -1 otherwise
1564*/
1565
1566static int
1567milter_reset_df(e)
1568	ENVELOPE *e;
1569{
1570	int afd;
1571	char dfname[MAXPATHLEN];
1572
1573	(void) sm_strlcpy(dfname, queuename(e, DATAFL_LETTER), sizeof dfname);
1574
1575	if (sm_io_flush(e->e_dfp, SM_TIME_DEFAULT) != 0 ||
1576	    sm_io_error(e->e_dfp))
1577	{
1578		MILTER_DF_ERROR("milter_reset_df: error writing/flushing %s: %s");
1579		return -1;
1580	}
1581	else if (SuperSafe != SAFE_REALLY)
1582	{
1583		/* skip next few clauses */
1584		/* EMPTY */
1585	}
1586	else if ((afd = sm_io_getinfo(e->e_dfp, SM_IO_WHAT_FD, NULL)) >= 0
1587		 && fsync(afd) < 0)
1588	{
1589		MILTER_DF_ERROR("milter_reset_df: error sync'ing %s: %s");
1590		return -1;
1591	}
1592	else if (sm_io_close(e->e_dfp, SM_TIME_DEFAULT) < 0)
1593	{
1594		MILTER_DF_ERROR("milter_reset_df: error closing %s: %s");
1595		return -1;
1596	}
1597	else if ((e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, dfname,
1598					SM_IO_RDONLY, NULL)) == NULL)
1599	{
1600		MILTER_DF_ERROR("milter_reset_df: error reopening %s: %s");
1601		return -1;
1602	}
1603	else
1604		e->e_flags |= EF_HAS_DF;
1605	return 0;
1606}
1607/*
1608**  MILTER_CAN_DELRCPTS -- can any milter filters delete recipients?
1609**
1610**	Parameters:
1611**		none
1612**
1613**	Returns:
1614**		true if any filter deletes recipients, false otherwise
1615*/
1616
1617bool
1618milter_can_delrcpts()
1619{
1620	bool can = false;
1621	int i;
1622
1623	if (tTd(64, 10))
1624		sm_dprintf("milter_can_delrcpts:");
1625
1626	for (i = 0; InputFilters[i] != NULL; i++)
1627	{
1628		struct milter *m = InputFilters[i];
1629
1630		if (bitset(SMFIF_DELRCPT, m->mf_fflags))
1631		{
1632			can = true;
1633			break;
1634		}
1635	}
1636	if (tTd(64, 10))
1637		sm_dprintf("%s\n", can ? "true" : "false");
1638
1639	return can;
1640}
1641/*
1642**  MILTER_QUIT_FILTER -- close down a single filter
1643**
1644**	Parameters:
1645**		m -- milter structure of filter to close down.
1646**		e -- current envelope.
1647**
1648**	Returns:
1649**		none
1650*/
1651
1652static void
1653milter_quit_filter(m, e)
1654	struct milter *m;
1655	ENVELOPE *e;
1656{
1657	if (tTd(64, 10))
1658		sm_dprintf("milter_quit_filter(%s)\n", m->mf_name);
1659	if (MilterLogLevel > 18)
1660		sm_syslog(LOG_INFO, e->e_id, "Milter (%s): quit filter",
1661			  m->mf_name);
1662
1663	/* Never replace error state */
1664	if (m->mf_state == SMFS_ERROR)
1665		return;
1666
1667	if (m->mf_sock < 0 ||
1668	    m->mf_state == SMFS_CLOSED ||
1669	    m->mf_state == SMFS_READY)
1670	{
1671		m->mf_sock = -1;
1672		m->mf_state = SMFS_CLOSED;
1673		return;
1674	}
1675
1676	(void) milter_write(m, SMFIC_QUIT, (char *) NULL, 0,
1677			    m->mf_timeout[SMFTO_WRITE], e);
1678	if (m->mf_sock >= 0)
1679	{
1680		(void) close(m->mf_sock);
1681		m->mf_sock = -1;
1682	}
1683	if (m->mf_state != SMFS_ERROR)
1684		m->mf_state = SMFS_CLOSED;
1685}
1686/*
1687**  MILTER_ABORT_FILTER -- tell filter to abort current message
1688**
1689**	Parameters:
1690**		m -- milter structure of filter to abort.
1691**		e -- current envelope.
1692**
1693**	Returns:
1694**		none
1695*/
1696
1697static void
1698milter_abort_filter(m, e)
1699	struct milter *m;
1700	ENVELOPE *e;
1701{
1702	if (tTd(64, 10))
1703		sm_dprintf("milter_abort_filter(%s)\n", m->mf_name);
1704	if (MilterLogLevel > 10)
1705		sm_syslog(LOG_INFO, e->e_id, "Milter (%s): abort filter",
1706			  m->mf_name);
1707
1708	if (m->mf_sock < 0 ||
1709	    m->mf_state != SMFS_INMSG)
1710		return;
1711
1712	(void) milter_write(m, SMFIC_ABORT, (char *) NULL, 0,
1713			    m->mf_timeout[SMFTO_WRITE], e);
1714	if (m->mf_state != SMFS_ERROR)
1715		m->mf_state = SMFS_DONE;
1716}
1717/*
1718**  MILTER_SEND_MACROS -- provide macros to the filters
1719**
1720**	Parameters:
1721**		m -- milter to send macros to.
1722**		macros -- macros to send for filter smfi_getsymval().
1723**		cmd -- which command the macros are associated with.
1724**		e -- current envelope (for macro access).
1725**
1726**	Returns:
1727**		none
1728*/
1729
1730static void
1731milter_send_macros(m, macros, cmd, e)
1732	struct milter *m;
1733	char **macros;
1734	char cmd;
1735	ENVELOPE *e;
1736{
1737	int i;
1738	int mid;
1739	char *v;
1740	char *buf, *bp;
1741	char exp[MAXLINE];
1742	ssize_t s;
1743
1744	/* sanity check */
1745	if (macros == NULL || macros[0] == NULL)
1746		return;
1747
1748	/* put together data */
1749	s = 1;			/* for the command character */
1750	for (i = 0; macros[i] != NULL; i++)
1751	{
1752		mid = macid(macros[i]);
1753		if (mid == 0)
1754			continue;
1755		v = macvalue(mid, e);
1756		if (v == NULL)
1757			continue;
1758		expand(v, exp, sizeof(exp), e);
1759		s += strlen(macros[i]) + 1 + strlen(exp) + 1;
1760	}
1761
1762	if (s < 0)
1763		return;
1764
1765	buf = (char *) xalloc(s);
1766	bp = buf;
1767	*bp++ = cmd;
1768	for (i = 0; macros[i] != NULL; i++)
1769	{
1770		mid = macid(macros[i]);
1771		if (mid == 0)
1772			continue;
1773		v = macvalue(mid, e);
1774		if (v == NULL)
1775			continue;
1776		expand(v, exp, sizeof(exp), e);
1777
1778		if (tTd(64, 10))
1779			sm_dprintf("milter_send_macros(%s, %c): %s=%s\n",
1780				m->mf_name, cmd, macros[i], exp);
1781
1782		(void) sm_strlcpy(bp, macros[i], s - (bp - buf));
1783		bp += strlen(bp) + 1;
1784		(void) sm_strlcpy(bp, exp, s - (bp - buf));
1785		bp += strlen(bp) + 1;
1786	}
1787	(void) milter_write(m, SMFIC_MACRO, buf, s,
1788			    m->mf_timeout[SMFTO_WRITE], e);
1789	sm_free(buf); /* XXX */
1790}
1791
1792/*
1793**  MILTER_SEND_COMMAND -- send a command and return the response for a filter
1794**
1795**	Parameters:
1796**		m -- current milter filter
1797**		command -- command to send.
1798**		data -- optional command data.
1799**		sz -- length of buf.
1800**		e -- current envelope (for e->e_id).
1801**		state -- return state word.
1802**
1803**	Returns:
1804**		response string (may be NULL)
1805*/
1806
1807static char *
1808milter_send_command(m, command, data, sz, e, state)
1809	struct milter *m;
1810	char command;
1811	void *data;
1812	ssize_t sz;
1813	ENVELOPE *e;
1814	char *state;
1815{
1816	char rcmd;
1817	ssize_t rlen;
1818	unsigned long skipflag;
1819	char *action;
1820	char *defresponse;
1821	char *response;
1822
1823	if (tTd(64, 10))
1824		sm_dprintf("milter_send_command(%s): cmd %c len %ld\n",
1825			m->mf_name, (char) command, (long) sz);
1826
1827	/* find skip flag and default failure */
1828	switch (command)
1829	{
1830	  case SMFIC_CONNECT:
1831		skipflag = SMFIP_NOCONNECT;
1832		action = "connect";
1833		defresponse = "554 Command rejected";
1834		break;
1835
1836	  case SMFIC_HELO:
1837		skipflag = SMFIP_NOHELO;
1838		action = "helo";
1839		defresponse = "550 Command rejected";
1840		break;
1841
1842	  case SMFIC_MAIL:
1843		skipflag = SMFIP_NOMAIL;
1844		action = "mail";
1845		defresponse = "550 5.7.1 Command rejected";
1846		break;
1847
1848	  case SMFIC_RCPT:
1849		skipflag = SMFIP_NORCPT;
1850		action = "rcpt";
1851		defresponse = "550 5.7.1 Command rejected";
1852		break;
1853
1854	  case SMFIC_HEADER:
1855		skipflag = SMFIP_NOHDRS;
1856		action = "header";
1857		defresponse = "550 5.7.1 Command rejected";
1858		break;
1859
1860	  case SMFIC_BODY:
1861		skipflag = SMFIP_NOBODY;
1862		action = "body";
1863		defresponse = "554 5.7.1 Command rejected";
1864		break;
1865
1866	  case SMFIC_EOH:
1867		skipflag = SMFIP_NOEOH;
1868		action = "eoh";
1869		defresponse = "550 5.7.1 Command rejected";
1870		break;
1871
1872	  case SMFIC_BODYEOB:
1873	  case SMFIC_OPTNEG:
1874	  case SMFIC_MACRO:
1875	  case SMFIC_ABORT:
1876	  case SMFIC_QUIT:
1877		/* NOTE: not handled by milter_send_command() */
1878		/* FALLTHROUGH */
1879
1880	  default:
1881		skipflag = 0;
1882		action = "default";
1883		defresponse = "550 5.7.1 Command rejected";
1884		break;
1885	}
1886
1887	/* check if filter wants this command */
1888	if (skipflag != 0 &&
1889	    bitset(skipflag, m->mf_pflags))
1890		return NULL;
1891
1892	/* send the command to the filter */
1893	(void) milter_write(m, command, data, sz,
1894			    m->mf_timeout[SMFTO_WRITE], e);
1895	if (m->mf_state == SMFS_ERROR)
1896	{
1897		MILTER_CHECK_ERROR(return NULL);
1898		return NULL;
1899	}
1900
1901	/* get the response from the filter */
1902	response = milter_read(m, &rcmd, &rlen,
1903			       m->mf_timeout[SMFTO_READ], e);
1904	if (m->mf_state == SMFS_ERROR)
1905	{
1906		MILTER_CHECK_ERROR(return NULL);
1907		return NULL;
1908	}
1909
1910	if (tTd(64, 10))
1911		sm_dprintf("milter_send_command(%s): returned %c\n",
1912			   m->mf_name, (char) rcmd);
1913
1914	switch (rcmd)
1915	{
1916	  case SMFIR_REPLYCODE:
1917		MILTER_CHECK_REPLYCODE(defresponse);
1918		if (MilterLogLevel > 10)
1919			sm_syslog(LOG_INFO, e->e_id, "milter=%s, action=%s, reject=%s",
1920				  m->mf_name, action, response);
1921		*state = rcmd;
1922		break;
1923
1924	  case SMFIR_REJECT:
1925		if (MilterLogLevel > 10)
1926			sm_syslog(LOG_INFO, e->e_id, "milter=%s, action=%s, reject",
1927				  m->mf_name, action);
1928		*state = rcmd;
1929		break;
1930
1931	  case SMFIR_DISCARD:
1932		if (MilterLogLevel > 10)
1933			sm_syslog(LOG_INFO, e->e_id, "milter=%s, action=%s, discard",
1934				  m->mf_name, action);
1935		*state = rcmd;
1936		break;
1937
1938	  case SMFIR_TEMPFAIL:
1939		if (MilterLogLevel > 10)
1940			sm_syslog(LOG_INFO, e->e_id, "milter=%s, action=%s, tempfail",
1941				  m->mf_name, action);
1942		*state = rcmd;
1943		break;
1944
1945	  case SMFIR_ACCEPT:
1946		/* this filter is done with message/connection */
1947		if (command == SMFIC_HELO ||
1948		    command == SMFIC_CONNECT)
1949			m->mf_state = SMFS_CLOSABLE;
1950		else
1951			m->mf_state = SMFS_DONE;
1952		if (MilterLogLevel > 10)
1953			sm_syslog(LOG_INFO, e->e_id, "milter=%s, action=%s, accepted",
1954				  m->mf_name, action);
1955		break;
1956
1957	  case SMFIR_CONTINUE:
1958		/* if MAIL command is ok, filter is in message state */
1959		if (command == SMFIC_MAIL)
1960			m->mf_state = SMFS_INMSG;
1961		if (MilterLogLevel > 12)
1962			sm_syslog(LOG_INFO, e->e_id, "milter=%s, action=%s, continue",
1963				  m->mf_name, action);
1964		break;
1965
1966	  default:
1967		/* Invalid response to command */
1968		if (MilterLogLevel > 0)
1969			sm_syslog(LOG_ERR, e->e_id,
1970				  "milter_send_command(%s): action=%s returned bogus response %c",
1971				  m->mf_name, action, rcmd);
1972		milter_error(m, e);
1973		break;
1974	}
1975
1976	if (*state != SMFIR_REPLYCODE &&
1977	    response != NULL)
1978	{
1979		sm_free(response); /* XXX */
1980		response = NULL;
1981	}
1982	return response;
1983}
1984
1985/*
1986**  MILTER_COMMAND -- send a command and return the response for each filter
1987**
1988**	Parameters:
1989**		command -- command to send.
1990**		data -- optional command data.
1991**		sz -- length of buf.
1992**		macros -- macros to send for filter smfi_getsymval().
1993**		e -- current envelope (for macro access).
1994**		state -- return state word.
1995**
1996**	Returns:
1997**		response string (may be NULL)
1998*/
1999
2000static char *
2001milter_command(command, data, sz, macros, e, state)
2002	char command;
2003	void *data;
2004	ssize_t sz;
2005	char **macros;
2006	ENVELOPE *e;
2007	char *state;
2008{
2009	int i;
2010	char *response = NULL;
2011	time_t tn = 0;
2012
2013	if (tTd(64, 10))
2014		sm_dprintf("milter_command: cmd %c len %ld\n",
2015			(char) command, (long) sz);
2016
2017	*state = SMFIR_CONTINUE;
2018	for (i = 0; InputFilters[i] != NULL; i++)
2019	{
2020		struct milter *m = InputFilters[i];
2021
2022		/* previous problem? */
2023		if (m->mf_state == SMFS_ERROR)
2024		{
2025			MILTER_CHECK_ERROR(continue);
2026			break;
2027		}
2028
2029		/* sanity check */
2030		if (m->mf_sock < 0 ||
2031		    (m->mf_state != SMFS_OPEN && m->mf_state != SMFS_INMSG))
2032			continue;
2033
2034		/* send macros (regardless of whether we send command) */
2035		if (macros != NULL && macros[0] != NULL)
2036		{
2037			milter_send_macros(m, macros, command, e);
2038			if (m->mf_state == SMFS_ERROR)
2039			{
2040				MILTER_CHECK_ERROR(continue);
2041				break;
2042			}
2043		}
2044
2045		if (MilterLogLevel > 21)
2046			tn = curtime();
2047
2048		response = milter_send_command(m, command, data, sz, e, state);
2049
2050		if (MilterLogLevel > 21)
2051		{
2052			/* log the time it took for the command per filter */
2053			sm_syslog(LOG_INFO, e->e_id,
2054				  "Milter (%s): time command (%c), %d",
2055				  m->mf_name, command, (int) (tn - curtime()));
2056		}
2057
2058		if (*state != SMFIR_CONTINUE)
2059			break;
2060	}
2061	return response;
2062}
2063/*
2064**  MILTER_NEGOTIATE -- get version and flags from filter
2065**
2066**	Parameters:
2067**		m -- milter filter structure.
2068**		e -- current envelope.
2069**
2070**	Returns:
2071**		0 on success, -1 otherwise
2072*/
2073
2074static int
2075milter_negotiate(m, e)
2076	struct milter *m;
2077	ENVELOPE *e;
2078{
2079	char rcmd;
2080	mi_int32 fvers;
2081	mi_int32 fflags;
2082	mi_int32 pflags;
2083	char *response;
2084	ssize_t rlen;
2085	char data[MILTER_OPTLEN];
2086
2087	/* sanity check */
2088	if (m->mf_sock < 0 || m->mf_state != SMFS_OPEN)
2089	{
2090		if (MilterLogLevel > 0)
2091			sm_syslog(LOG_ERR, e->e_id,
2092				  "Milter (%s): negotiate, impossible state",
2093				  m->mf_name);
2094		milter_error(m, e);
2095		return -1;
2096	}
2097
2098	fvers = htonl(SMFI_VERSION);
2099	fflags = htonl(SMFI_CURR_ACTS);
2100	pflags = htonl(SMFI_CURR_PROT);
2101	(void) memcpy(data, (char *) &fvers, MILTER_LEN_BYTES);
2102	(void) memcpy(data + MILTER_LEN_BYTES,
2103		      (char *) &fflags, MILTER_LEN_BYTES);
2104	(void) memcpy(data + (MILTER_LEN_BYTES * 2),
2105		      (char *) &pflags, MILTER_LEN_BYTES);
2106	(void) milter_write(m, SMFIC_OPTNEG, data, sizeof data,
2107			    m->mf_timeout[SMFTO_WRITE], e);
2108
2109	if (m->mf_state == SMFS_ERROR)
2110		return -1;
2111
2112	response = milter_read(m, &rcmd, &rlen, m->mf_timeout[SMFTO_READ], e);
2113	if (m->mf_state == SMFS_ERROR)
2114		return -1;
2115
2116	if (rcmd != SMFIC_OPTNEG)
2117	{
2118		if (tTd(64, 5))
2119			sm_dprintf("milter_negotiate(%s): returned %c instead of %c\n",
2120				m->mf_name, rcmd, SMFIC_OPTNEG);
2121		if (MilterLogLevel > 0)
2122			sm_syslog(LOG_ERR, e->e_id,
2123				  "Milter (%s): negotiate: returned %c instead of %c",
2124				  m->mf_name, rcmd, SMFIC_OPTNEG);
2125		if (response != NULL)
2126			sm_free(response); /* XXX */
2127		milter_error(m, e);
2128		return -1;
2129	}
2130
2131	/* Make sure we have enough bytes for the version */
2132	if (response == NULL || rlen < MILTER_LEN_BYTES)
2133	{
2134		if (tTd(64, 5))
2135			sm_dprintf("milter_negotiate(%s): did not return valid info\n",
2136				m->mf_name);
2137		if (MilterLogLevel > 0)
2138			sm_syslog(LOG_ERR, e->e_id,
2139				  "Milter (%s): negotiate: did not return valid info",
2140				  m->mf_name);
2141		if (response != NULL)
2142			sm_free(response); /* XXX */
2143		milter_error(m, e);
2144		return -1;
2145	}
2146
2147	/* extract information */
2148	(void) memcpy((char *) &fvers, response, MILTER_LEN_BYTES);
2149
2150	/* Now make sure we have enough for the feature bitmap */
2151	if (rlen != MILTER_OPTLEN)
2152	{
2153		if (tTd(64, 5))
2154			sm_dprintf("milter_negotiate(%s): did not return enough info\n",
2155				m->mf_name);
2156		if (MilterLogLevel > 0)
2157			sm_syslog(LOG_ERR, e->e_id,
2158				  "Milter (%s): negotiate: did not return enough info",
2159				  m->mf_name);
2160		if (response != NULL)
2161			sm_free(response); /* XXX */
2162		milter_error(m, e);
2163		return -1;
2164	}
2165
2166	(void) memcpy((char *) &fflags, response + MILTER_LEN_BYTES,
2167		      MILTER_LEN_BYTES);
2168	(void) memcpy((char *) &pflags, response + (MILTER_LEN_BYTES * 2),
2169		      MILTER_LEN_BYTES);
2170	sm_free(response); /* XXX */
2171	response = NULL;
2172
2173	m->mf_fvers = ntohl(fvers);
2174	m->mf_fflags = ntohl(fflags);
2175	m->mf_pflags = ntohl(pflags);
2176
2177	/* check for version compatibility */
2178	if (m->mf_fvers == 1 ||
2179	    m->mf_fvers > SMFI_VERSION)
2180	{
2181		if (tTd(64, 5))
2182			sm_dprintf("milter_negotiate(%s): version %d != MTA milter version %d\n",
2183				m->mf_name, m->mf_fvers, SMFI_VERSION);
2184		if (MilterLogLevel > 0)
2185			sm_syslog(LOG_ERR, e->e_id,
2186				  "Milter (%s): negotiate: version %d != MTA milter version %d",
2187				  m->mf_name, m->mf_fvers, SMFI_VERSION);
2188		milter_error(m, e);
2189		return -1;
2190	}
2191
2192	/* check for filter feature mismatch */
2193	if ((m->mf_fflags & SMFI_CURR_ACTS) != m->mf_fflags)
2194	{
2195		if (tTd(64, 5))
2196			sm_dprintf("milter_negotiate(%s): filter abilities 0x%x != MTA milter abilities 0x%lx\n",
2197				m->mf_name, m->mf_fflags,
2198				SMFI_CURR_ACTS);
2199		if (MilterLogLevel > 0)
2200			sm_syslog(LOG_ERR, e->e_id,
2201				  "Milter (%s): negotiate: filter abilities 0x%x != MTA milter abilities 0x%lx",
2202				  m->mf_name, m->mf_fflags,
2203				  (unsigned long) SMFI_CURR_ACTS);
2204		milter_error(m, e);
2205		return -1;
2206	}
2207
2208	/* check for protocol feature mismatch */
2209	if ((m->mf_pflags & SMFI_CURR_PROT) != m->mf_pflags)
2210	{
2211		if (tTd(64, 5))
2212			sm_dprintf("milter_negotiate(%s): protocol abilities 0x%x != MTA milter abilities 0x%lx\n",
2213				m->mf_name, m->mf_pflags,
2214				(unsigned long) SMFI_CURR_PROT);
2215		if (MilterLogLevel > 0)
2216			sm_syslog(LOG_ERR, e->e_id,
2217				  "Milter (%s): negotiate: protocol abilities 0x%x != MTA milter abilities 0x%lx",
2218				  m->mf_name, m->mf_pflags,
2219				  (unsigned long) SMFI_CURR_PROT);
2220		milter_error(m, e);
2221		return -1;
2222	}
2223
2224	if (tTd(64, 5))
2225		sm_dprintf("milter_negotiate(%s): version %u, fflags 0x%x, pflags 0x%x\n",
2226			m->mf_name, m->mf_fvers, m->mf_fflags, m->mf_pflags);
2227	return 0;
2228}
2229/*
2230**  MILTER_PER_CONNECTION_CHECK -- checks on per-connection commands
2231**
2232**	Reduce code duplication by putting these checks in one place
2233**
2234**	Parameters:
2235**		e -- current envelope.
2236**
2237**	Returns:
2238**		none
2239*/
2240
2241static void
2242milter_per_connection_check(e)
2243	ENVELOPE *e;
2244{
2245	int i;
2246
2247	/* see if we are done with any of the filters */
2248	for (i = 0; InputFilters[i] != NULL; i++)
2249	{
2250		struct milter *m = InputFilters[i];
2251
2252		if (m->mf_state == SMFS_CLOSABLE)
2253			milter_quit_filter(m, e);
2254	}
2255}
2256/*
2257**  MILTER_ERROR -- Put a milter filter into error state
2258**
2259**	Parameters:
2260**		m -- the broken filter.
2261**
2262**	Returns:
2263**		none
2264*/
2265
2266static void
2267milter_error(m, e)
2268	struct milter *m;
2269	ENVELOPE *e;
2270{
2271	/*
2272	**  We could send a quit here but
2273	**  we may have gotten here due to
2274	**  an I/O error so we don't want
2275	**  to try to make things worse.
2276	*/
2277
2278	if (m->mf_sock >= 0)
2279	{
2280		(void) close(m->mf_sock);
2281		m->mf_sock = -1;
2282	}
2283	m->mf_state = SMFS_ERROR;
2284
2285	if (MilterLogLevel > 0)
2286		sm_syslog(LOG_INFO, e->e_id, "Milter (%s): to error state",
2287			  m->mf_name);
2288}
2289/*
2290**  MILTER_HEADERS -- send headers to a single milter filter
2291**
2292**	Parameters:
2293**		m -- current filter.
2294**		e -- current envelope.
2295**		state -- return state from response.
2296**
2297**	Returns:
2298**		response string (may be NULL)
2299*/
2300
2301static char *
2302milter_headers(m, e, state)
2303	struct milter *m;
2304	ENVELOPE *e;
2305	char *state;
2306{
2307	char *response = NULL;
2308	HDR *h;
2309
2310	if (MilterLogLevel > 17)
2311		sm_syslog(LOG_INFO, e->e_id, "Milter (%s): headers, send",
2312			  m->mf_name);
2313
2314	for (h = e->e_header; h != NULL; h = h->h_link)
2315	{
2316		char *buf;
2317		ssize_t s;
2318
2319		/* don't send over deleted headers */
2320		if (h->h_value == NULL)
2321		{
2322			/* strip H_USER so not counted in milter_chgheader() */
2323			h->h_flags &= ~H_USER;
2324			continue;
2325		}
2326
2327		/* skip auto-generated */
2328		if (!bitset(H_USER, h->h_flags))
2329			continue;
2330
2331		if (tTd(64, 10))
2332			sm_dprintf("milter_headers: %s: %s\n",
2333				h->h_field, h->h_value);
2334		if (MilterLogLevel > 21)
2335			sm_syslog(LOG_INFO, e->e_id, "Milter (%s): header, %s",
2336				  m->mf_name, h->h_field);
2337
2338		s = strlen(h->h_field) + 1 + strlen(h->h_value) + 1;
2339		if (s < 0)
2340			continue;
2341		buf = (char *) xalloc(s);
2342		(void) sm_snprintf(buf, s, "%s%c%s",
2343			h->h_field, '\0', h->h_value);
2344
2345		/* send it over */
2346		response = milter_send_command(m, SMFIC_HEADER, buf,
2347					       s, e, state);
2348		sm_free(buf); /* XXX */
2349		if (m->mf_state == SMFS_ERROR ||
2350		    m->mf_state == SMFS_DONE ||
2351		    *state != SMFIR_CONTINUE)
2352			break;
2353	}
2354	if (MilterLogLevel > 17)
2355		sm_syslog(LOG_INFO, e->e_id, "Milter (%s): headers, sent",
2356			  m->mf_name);
2357	return response;
2358}
2359/*
2360**  MILTER_BODY -- send the body to a filter
2361**
2362**	Parameters:
2363**		m -- current filter.
2364**		e -- current envelope.
2365**		state -- return state from response.
2366**
2367**	Returns:
2368**		response string (may be NULL)
2369*/
2370
2371static char *
2372milter_body(m, e, state)
2373	struct milter *m;
2374	ENVELOPE *e;
2375	char *state;
2376{
2377	char bufchar = '\0';
2378	char prevchar = '\0';
2379	int c;
2380	char *response = NULL;
2381	char *bp;
2382	char buf[MILTER_CHUNK_SIZE];
2383
2384	if (tTd(64, 10))
2385		sm_dprintf("milter_body\n");
2386
2387	if (bfrewind(e->e_dfp) < 0)
2388	{
2389		ExitStat = EX_IOERR;
2390		*state = SMFIR_TEMPFAIL;
2391		syserr("milter_body: %s/%cf%s: rewind error",
2392		       qid_printqueue(e->e_qgrp, e->e_qdir),
2393		       DATAFL_LETTER, e->e_id);
2394		return NULL;
2395	}
2396
2397	if (MilterLogLevel > 17)
2398		sm_syslog(LOG_INFO, e->e_id, "Milter (%s): body, send",
2399			  m->mf_name);
2400	bp = buf;
2401	while ((c = sm_io_getc(e->e_dfp, SM_TIME_DEFAULT)) != SM_IO_EOF)
2402	{
2403		/*  Change LF to CRLF */
2404		if (c == '\n')
2405		{
2406			/* Not a CRLF already? */
2407			if (prevchar != '\r')
2408			{
2409				/* Room for CR now? */
2410				if (bp + 2 > &buf[sizeof buf])
2411				{
2412					/* No room, buffer LF */
2413					bufchar = c;
2414
2415					/* and send CR now */
2416					c = '\r';
2417				}
2418				else
2419				{
2420					/* Room to do it now */
2421					*bp++ = '\r';
2422					prevchar = '\r';
2423				}
2424			}
2425		}
2426		*bp++ = (char) c;
2427		prevchar = c;
2428		if (bp >= &buf[sizeof buf])
2429		{
2430			/* send chunk */
2431			response = milter_send_command(m, SMFIC_BODY, buf,
2432						       bp - buf, e, state);
2433			bp = buf;
2434			if (bufchar != '\0')
2435			{
2436				*bp++ = bufchar;
2437				bufchar = '\0';
2438				prevchar = bufchar;
2439			}
2440		}
2441		if (m->mf_state == SMFS_ERROR ||
2442		    m->mf_state == SMFS_DONE ||
2443		    *state != SMFIR_CONTINUE)
2444			break;
2445	}
2446
2447	/* check for read errors */
2448	if (sm_io_error(e->e_dfp))
2449	{
2450		ExitStat = EX_IOERR;
2451		if (*state == SMFIR_CONTINUE ||
2452		    *state == SMFIR_ACCEPT)
2453		{
2454			*state = SMFIR_TEMPFAIL;
2455			if (response != NULL)
2456			{
2457				sm_free(response); /* XXX */
2458				response = NULL;
2459			}
2460		}
2461		syserr("milter_body: %s/%cf%s: read error",
2462		       qid_printqueue(e->e_qgrp, e->e_qdir),
2463		       DATAFL_LETTER, e->e_id);
2464		return response;
2465	}
2466
2467	/* send last body chunk */
2468	if (bp > buf &&
2469	    m->mf_state != SMFS_ERROR &&
2470	    m->mf_state != SMFS_DONE &&
2471	    *state == SMFIR_CONTINUE)
2472	{
2473		/* send chunk */
2474		response = milter_send_command(m, SMFIC_BODY, buf, bp - buf,
2475					       e, state);
2476		bp = buf;
2477	}
2478	if (MilterLogLevel > 17)
2479		sm_syslog(LOG_INFO, e->e_id, "Milter (%s): body, sent",
2480			  m->mf_name);
2481	return response;
2482}
2483
2484/*
2485**  Actions
2486*/
2487
2488/*
2489**  MILTER_ADDHEADER -- Add the supplied header to the message
2490**
2491**	Parameters:
2492**		response -- encoded form of header/value.
2493**		rlen -- length of response.
2494**		e -- current envelope.
2495**
2496**	Returns:
2497**		none
2498*/
2499
2500static void
2501milter_addheader(response, rlen, e)
2502	char *response;
2503	ssize_t rlen;
2504	ENVELOPE *e;
2505{
2506	char *val;
2507	HDR *h;
2508
2509	if (tTd(64, 10))
2510		sm_dprintf("milter_addheader: ");
2511
2512	/* sanity checks */
2513	if (response == NULL)
2514	{
2515		if (tTd(64, 10))
2516			sm_dprintf("NULL response\n");
2517		return;
2518	}
2519
2520	if (rlen < 2 || strlen(response) + 1 >= (size_t) rlen)
2521	{
2522		if (tTd(64, 10))
2523			sm_dprintf("didn't follow protocol (total len)\n");
2524		return;
2525	}
2526
2527	/* Find separating NUL */
2528	val = response + strlen(response) + 1;
2529
2530	/* another sanity check */
2531	if (strlen(response) + strlen(val) + 2 != (size_t) rlen)
2532	{
2533		if (tTd(64, 10))
2534			sm_dprintf("didn't follow protocol (part len)\n");
2535		return;
2536	}
2537
2538	if (*response == '\0')
2539	{
2540		if (tTd(64, 10))
2541			sm_dprintf("empty field name\n");
2542		return;
2543	}
2544
2545	for (h = e->e_header; h != NULL; h = h->h_link)
2546	{
2547		if (sm_strcasecmp(h->h_field, response) == 0 &&
2548		    !bitset(H_USER, h->h_flags) &&
2549		    !bitset(H_TRACE, h->h_flags))
2550			break;
2551	}
2552
2553	/* add to e_msgsize */
2554	e->e_msgsize += strlen(response) + 2 + strlen(val);
2555
2556	if (h != NULL)
2557	{
2558		if (tTd(64, 10))
2559			sm_dprintf("Replace default header %s value with %s\n",
2560				   h->h_field, val);
2561		if (MilterLogLevel > 8)
2562			sm_syslog(LOG_INFO, e->e_id,
2563				  "Milter change: default header %s value with %s",
2564				  h->h_field, val);
2565		h->h_value = newstr(val);
2566		h->h_flags |= H_USER;
2567	}
2568	else
2569	{
2570		if (tTd(64, 10))
2571			sm_dprintf("Add %s: %s\n", response, val);
2572		if (MilterLogLevel > 8)
2573			sm_syslog(LOG_INFO, e->e_id, "Milter add: header: %s: %s",
2574				  response, val);
2575		addheader(newstr(response), val, H_USER, e);
2576	}
2577}
2578/*
2579**  MILTER_CHANGEHEADER -- Change the supplied header in the message
2580**
2581**	Parameters:
2582**		response -- encoded form of header/index/value.
2583**		rlen -- length of response.
2584**		e -- current envelope.
2585**
2586**	Returns:
2587**		none
2588*/
2589
2590static void
2591milter_changeheader(response, rlen, e)
2592	char *response;
2593	ssize_t rlen;
2594	ENVELOPE *e;
2595{
2596	mi_int32 i, index;
2597	char *field, *val;
2598	HDR *h, *sysheader;
2599
2600	if (tTd(64, 10))
2601		sm_dprintf("milter_changeheader: ");
2602
2603	/* sanity checks */
2604	if (response == NULL)
2605	{
2606		if (tTd(64, 10))
2607			sm_dprintf("NULL response\n");
2608		return;
2609	}
2610
2611	if (rlen < 2 || strlen(response) + 1 >= (size_t) rlen)
2612	{
2613		if (tTd(64, 10))
2614			sm_dprintf("didn't follow protocol (total len)\n");
2615		return;
2616	}
2617
2618	/* Find separating NUL */
2619	(void) memcpy((char *) &i, response, MILTER_LEN_BYTES);
2620	index = ntohl(i);
2621	field = response + MILTER_LEN_BYTES;
2622	val = field + strlen(field) + 1;
2623
2624	/* another sanity check */
2625	if (MILTER_LEN_BYTES + strlen(field) + 1 +
2626	    strlen(val) + 1 != (size_t) rlen)
2627	{
2628		if (tTd(64, 10))
2629			sm_dprintf("didn't follow protocol (part len)\n");
2630		return;
2631	}
2632
2633	if (*field == '\0')
2634	{
2635		if (tTd(64, 10))
2636			sm_dprintf("empty field name\n");
2637		return;
2638	}
2639
2640	sysheader = NULL;
2641	for (h = e->e_header; h != NULL; h = h->h_link)
2642	{
2643		if (sm_strcasecmp(h->h_field, field) == 0)
2644		{
2645			if (bitset(H_USER, h->h_flags) &&
2646			    --index <= 0)
2647			{
2648				sysheader = NULL;
2649				break;
2650			}
2651			else if (!bitset(H_USER, h->h_flags) &&
2652				 !bitset(H_TRACE, h->h_flags))
2653			{
2654				/*
2655				**  DRUMS msg-fmt draft says can only have
2656				**  multiple occurences of trace fields,
2657				**  so make sure we replace any non-trace,
2658				**  non-user field.
2659				*/
2660
2661				sysheader = h;
2662			}
2663		}
2664	}
2665
2666	/* if not found as user-provided header at index, use sysheader */
2667	if (h == NULL)
2668		h = sysheader;
2669
2670	if (h == NULL)
2671	{
2672		if (*val == '\0')
2673		{
2674			if (tTd(64, 10))
2675				sm_dprintf("Delete (noop) %s:\n", field);
2676		}
2677		else
2678		{
2679			/* treat modify value with no existing header as add */
2680			if (tTd(64, 10))
2681				sm_dprintf("Add %s: %s\n", field, val);
2682			addheader(newstr(field), val, H_USER, e);
2683		}
2684		return;
2685	}
2686
2687	if (tTd(64, 10))
2688	{
2689		if (*val == '\0')
2690		{
2691			sm_dprintf("Delete%s %s: %s\n",
2692				   h == sysheader ? " (default header)" : "",
2693				   field,
2694				   h->h_value == NULL ? "<NULL>" : h->h_value);
2695		}
2696		else
2697		{
2698			sm_dprintf("Change%s %s: from %s to %s\n",
2699				   h == sysheader ? " (default header)" : "",
2700				   field,
2701				   h->h_value == NULL ? "<NULL>" : h->h_value,
2702				   val);
2703		}
2704	}
2705
2706	if (MilterLogLevel > 8)
2707	{
2708		if (*val == '\0')
2709		{
2710			sm_syslog(LOG_INFO, e->e_id,
2711				  "Milter delete: header %s %s: %s",
2712				  h == sysheader ? " (default header)" : "",
2713				  field,
2714				  h->h_value == NULL ? "<NULL>" : h->h_value);
2715		}
2716		else
2717		{
2718			sm_syslog(LOG_INFO, e->e_id,
2719				  "Milter change: header %s %s: from %s to %s",
2720				  h == sysheader ? " (default header)" : "",
2721				  field,
2722				  h->h_value == NULL ? "<NULL>" : h->h_value,
2723				  val);
2724		}
2725	}
2726
2727	if (h != sysheader && h->h_value != NULL)
2728	{
2729		size_t l;
2730
2731		l = strlen(h->h_value);
2732		if (l > e->e_msgsize)
2733			e->e_msgsize = 0;
2734		else
2735			e->e_msgsize -= l;
2736		/* rpool, don't free: sm_free(h->h_value); XXX */
2737	}
2738
2739	if (*val == '\0')
2740	{
2741		/* Remove "Field: " from message size */
2742		if (h != sysheader)
2743		{
2744			size_t l;
2745
2746			l = strlen(h->h_field) + 2;
2747			if (l > e->e_msgsize)
2748				e->e_msgsize = 0;
2749			else
2750				e->e_msgsize -= l;
2751		}
2752		h->h_value = NULL;
2753	}
2754	else
2755	{
2756		h->h_value = newstr(val);
2757		h->h_flags |= H_USER;
2758		e->e_msgsize += strlen(h->h_value);
2759	}
2760}
2761/*
2762**  MILTER_ADDRCPT -- Add the supplied recipient to the message
2763**
2764**	Parameters:
2765**		response -- encoded form of recipient address.
2766**		rlen -- length of response.
2767**		e -- current envelope.
2768**
2769**	Returns:
2770**		none
2771*/
2772
2773static void
2774milter_addrcpt(response, rlen, e)
2775	char *response;
2776	ssize_t rlen;
2777	ENVELOPE *e;
2778{
2779	if (tTd(64, 10))
2780		sm_dprintf("milter_addrcpt: ");
2781
2782	/* sanity checks */
2783	if (response == NULL)
2784	{
2785		if (tTd(64, 10))
2786			sm_dprintf("NULL response\n");
2787		return;
2788	}
2789
2790	if (*response == '\0' ||
2791	    strlen(response) + 1 != (size_t) rlen)
2792	{
2793		if (tTd(64, 10))
2794			sm_dprintf("didn't follow protocol (total len %d != rlen %d)\n",
2795				   (int) strlen(response), (int) (rlen - 1));
2796		return;
2797	}
2798
2799	if (tTd(64, 10))
2800		sm_dprintf("%s\n", response);
2801	if (MilterLogLevel > 8)
2802		sm_syslog(LOG_INFO, e->e_id, "Milter add: rcpt: %s", response);
2803	(void) sendtolist(response, NULLADDR, &e->e_sendqueue, 0, e);
2804	return;
2805}
2806/*
2807**  MILTER_DELRCPT -- Delete the supplied recipient from the message
2808**
2809**	Parameters:
2810**		response -- encoded form of recipient address.
2811**		rlen -- length of response.
2812**		e -- current envelope.
2813**
2814**	Returns:
2815**		none
2816*/
2817
2818static void
2819milter_delrcpt(response, rlen, e)
2820	char *response;
2821	ssize_t rlen;
2822	ENVELOPE *e;
2823{
2824	if (tTd(64, 10))
2825		sm_dprintf("milter_delrcpt: ");
2826
2827	/* sanity checks */
2828	if (response == NULL)
2829	{
2830		if (tTd(64, 10))
2831			sm_dprintf("NULL response\n");
2832		return;
2833	}
2834
2835	if (*response == '\0' ||
2836	    strlen(response) + 1 != (size_t) rlen)
2837	{
2838		if (tTd(64, 10))
2839			sm_dprintf("didn't follow protocol (total len)\n");
2840		return;
2841	}
2842
2843	if (tTd(64, 10))
2844		sm_dprintf("%s\n", response);
2845	if (MilterLogLevel > 8)
2846		sm_syslog(LOG_INFO, e->e_id, "Milter delete: rcpt %s",
2847			  response);
2848	(void) removefromlist(response, &e->e_sendqueue, e);
2849	return;
2850}
2851/*
2852**  MILTER_REPLBODY -- Replace the current data file with new body
2853**
2854**	Parameters:
2855**		response -- encoded form of new body.
2856**		rlen -- length of response.
2857**		newfilter -- if first time called by a new filter
2858**		e -- current envelope.
2859**
2860**	Returns:
2861**		0 upon success, -1 upon failure
2862*/
2863
2864static int
2865milter_replbody(response, rlen, newfilter, e)
2866	char *response;
2867	ssize_t rlen;
2868	bool newfilter;
2869	ENVELOPE *e;
2870{
2871	static char prevchar;
2872	int i;
2873
2874	if (tTd(64, 10))
2875		sm_dprintf("milter_replbody\n");
2876
2877	/* If a new filter, reset previous character and truncate data file */
2878	if (newfilter)
2879	{
2880		off_t prevsize;
2881		char dfname[MAXPATHLEN];
2882
2883		(void) sm_strlcpy(dfname, queuename(e, DATAFL_LETTER),
2884				  sizeof dfname);
2885
2886		/* Reset prevchar */
2887		prevchar = '\0';
2888
2889		/* Get the current data file information */
2890		prevsize = sm_io_getinfo(e->e_dfp, SM_IO_WHAT_SIZE, NULL);
2891		if (prevsize < 0)
2892			prevsize = 0;
2893
2894		/* truncate current data file */
2895		if (sm_io_getinfo(e->e_dfp, SM_IO_WHAT_ISTYPE, BF_FILE_TYPE))
2896		{
2897			if (sm_io_setinfo(e->e_dfp, SM_BF_TRUNCATE, NULL) < 0)
2898			{
2899				MILTER_DF_ERROR("milter_replbody: sm_io truncate %s: %s");
2900				return -1;
2901			}
2902		}
2903		else
2904		{
2905			int err;
2906
2907			err = sm_io_error(e->e_dfp);
2908			(void) sm_io_flush(e->e_dfp, SM_TIME_DEFAULT);
2909
2910			/*
2911			**  Clear error if tried to fflush()
2912			**  a read-only file pointer and
2913			**  there wasn't a previous error.
2914			*/
2915
2916			if (err == 0)
2917				sm_io_clearerr(e->e_dfp);
2918
2919			/* errno is set implicitly by fseek() before return */
2920			err = sm_io_seek(e->e_dfp, SM_TIME_DEFAULT,
2921					 0, SEEK_SET);
2922			if (err < 0)
2923			{
2924				MILTER_DF_ERROR("milter_replbody: sm_io_seek %s: %s");
2925				return -1;
2926			}
2927# if NOFTRUNCATE
2928			/* XXX: Not much we can do except rewind it */
2929			errno = EINVAL;
2930			MILTER_DF_ERROR("milter_replbody: ftruncate not available on this platform (%s:%s)");
2931			return -1;
2932# else /* NOFTRUNCATE */
2933			err = ftruncate(sm_io_getinfo(e->e_dfp,
2934						      SM_IO_WHAT_FD, NULL),
2935					0);
2936			if (err < 0)
2937			{
2938				MILTER_DF_ERROR("milter_replbody: sm_io ftruncate %s: %s");
2939				return -1;
2940			}
2941# endif /* NOFTRUNCATE */
2942		}
2943
2944		if (prevsize > e->e_msgsize)
2945			e->e_msgsize = 0;
2946		else
2947			e->e_msgsize -= prevsize;
2948	}
2949
2950	if (newfilter && MilterLogLevel > 8)
2951		sm_syslog(LOG_INFO, e->e_id, "Milter message: body replaced");
2952
2953	if (response == NULL)
2954	{
2955		/* Flush the buffered '\r' */
2956		if (prevchar == '\r')
2957		{
2958			(void) sm_io_putc(e->e_dfp, SM_TIME_DEFAULT, prevchar);
2959			e->e_msgsize++;
2960		}
2961		return 0;
2962	}
2963
2964	for (i = 0; i < rlen; i++)
2965	{
2966		/* Buffered char from last chunk */
2967		if (i == 0 && prevchar == '\r')
2968		{
2969			/* Not CRLF, output prevchar */
2970			if (response[i] != '\n')
2971			{
2972				(void) sm_io_putc(e->e_dfp, SM_TIME_DEFAULT,
2973						  prevchar);
2974				e->e_msgsize++;
2975			}
2976			prevchar = '\0';
2977		}
2978
2979		/* Turn CRLF into LF */
2980		if (response[i] == '\r')
2981		{
2982			/* check if at end of chunk */
2983			if (i + 1 < rlen)
2984			{
2985				/* If LF, strip CR */
2986				if (response[i + 1] == '\n')
2987					i++;
2988			}
2989			else
2990			{
2991				/* check next chunk */
2992				prevchar = '\r';
2993				continue;
2994			}
2995		}
2996		(void) sm_io_putc(e->e_dfp, SM_TIME_DEFAULT, response[i]);
2997		e->e_msgsize++;
2998	}
2999	return 0;
3000}
3001
3002/*
3003**  MTA callouts
3004*/
3005
3006/*
3007**  MILTER_INIT -- open and negotiate with all of the filters
3008**
3009**	Parameters:
3010**		e -- current envelope.
3011**		state -- return state from response.
3012**
3013**	Returns:
3014**		true iff at least one filter is active
3015*/
3016
3017/* ARGSUSED */
3018bool
3019milter_init(e, state)
3020	ENVELOPE *e;
3021	char *state;
3022{
3023	int i;
3024
3025	if (tTd(64, 10))
3026		sm_dprintf("milter_init\n");
3027
3028	*state = SMFIR_CONTINUE;
3029	if (InputFilters[0] == NULL)
3030	{
3031		if (MilterLogLevel > 10)
3032			sm_syslog(LOG_INFO, e->e_id,
3033				  "Milter: no active filter");
3034		return false;
3035	}
3036
3037	for (i = 0; InputFilters[i] != NULL; i++)
3038	{
3039		struct milter *m = InputFilters[i];
3040
3041		m->mf_sock = milter_open(m, false, e);
3042		if (m->mf_state == SMFS_ERROR)
3043		{
3044			MILTER_CHECK_ERROR(continue);
3045			break;
3046		}
3047
3048		if (m->mf_sock < 0 ||
3049		    milter_negotiate(m, e) < 0 ||
3050		    m->mf_state == SMFS_ERROR)
3051		{
3052			if (tTd(64, 5))
3053				sm_dprintf("milter_init(%s): failed to %s\n",
3054					   m->mf_name,
3055					   m->mf_sock < 0 ? "open" :
3056							    "negotiate");
3057			if (MilterLogLevel > 0)
3058				sm_syslog(LOG_ERR, e->e_id,
3059					  "Milter (%s): init failed to %s",
3060					  m->mf_name,
3061					  m->mf_sock < 0 ? "open" :
3062							   "negotiate");
3063
3064			/* if negotation failure, close socket */
3065			milter_error(m, e);
3066			MILTER_CHECK_ERROR(continue);
3067		}
3068		if (MilterLogLevel > 9)
3069			sm_syslog(LOG_INFO, e->e_id,
3070				  "Milter (%s): init success to %s",
3071				  m->mf_name,
3072				  m->mf_sock < 0 ? "open" : "negotiate");
3073	}
3074
3075	/*
3076	**  If something temp/perm failed with one of the filters,
3077	**  we won't be using any of them, so clear any existing
3078	**  connections.
3079	*/
3080
3081	if (*state != SMFIR_CONTINUE)
3082		milter_quit(e);
3083
3084	return true;
3085}
3086/*
3087**  MILTER_CONNECT -- send connection info to milter filters
3088**
3089**	Parameters:
3090**		hostname -- hostname of remote machine.
3091**		addr -- address of remote machine.
3092**		e -- current envelope.
3093**		state -- return state from response.
3094**
3095**	Returns:
3096**		response string (may be NULL)
3097*/
3098
3099char *
3100milter_connect(hostname, addr, e, state)
3101	char *hostname;
3102	SOCKADDR addr;
3103	ENVELOPE *e;
3104	char *state;
3105{
3106	char family;
3107	unsigned short port;
3108	char *buf, *bp;
3109	char *response;
3110	char *sockinfo = NULL;
3111	ssize_t s;
3112# if NETINET6
3113	char buf6[INET6_ADDRSTRLEN];
3114# endif /* NETINET6 */
3115
3116	if (tTd(64, 10))
3117		sm_dprintf("milter_connect(%s)\n", hostname);
3118	if (MilterLogLevel > 9)
3119		sm_syslog(LOG_INFO, e->e_id, "Milter: connect to filters");
3120
3121	/* gather data */
3122	switch (addr.sa.sa_family)
3123	{
3124# if NETUNIX
3125	  case AF_UNIX:
3126		family = SMFIA_UNIX;
3127		port = htons(0);
3128		sockinfo = addr.sunix.sun_path;
3129		break;
3130# endif /* NETUNIX */
3131
3132# if NETINET
3133	  case AF_INET:
3134		family = SMFIA_INET;
3135		port = addr.sin.sin_port;
3136		sockinfo = (char *) inet_ntoa(addr.sin.sin_addr);
3137		break;
3138# endif /* NETINET */
3139
3140# if NETINET6
3141	  case AF_INET6:
3142		if (IN6_IS_ADDR_V4MAPPED(&addr.sin6.sin6_addr))
3143			family = SMFIA_INET;
3144		else
3145			family = SMFIA_INET6;
3146		port = addr.sin6.sin6_port;
3147		sockinfo = anynet_ntop(&addr.sin6.sin6_addr, buf6,
3148				       sizeof buf6);
3149		if (sockinfo == NULL)
3150			sockinfo = "";
3151		break;
3152# endif /* NETINET6 */
3153
3154	  default:
3155		family = SMFIA_UNKNOWN;
3156		break;
3157	}
3158
3159	s = strlen(hostname) + 1 + sizeof(family);
3160	if (family != SMFIA_UNKNOWN)
3161		s += sizeof(port) + strlen(sockinfo) + 1;
3162
3163	buf = (char *) xalloc(s);
3164	bp = buf;
3165
3166	/* put together data */
3167	(void) memcpy(bp, hostname, strlen(hostname));
3168	bp += strlen(hostname);
3169	*bp++ = '\0';
3170	(void) memcpy(bp, &family, sizeof family);
3171	bp += sizeof family;
3172	if (family != SMFIA_UNKNOWN)
3173	{
3174		(void) memcpy(bp, &port, sizeof port);
3175		bp += sizeof port;
3176
3177		/* include trailing '\0' */
3178		(void) memcpy(bp, sockinfo, strlen(sockinfo) + 1);
3179	}
3180
3181	response = milter_command(SMFIC_CONNECT, buf, s,
3182				  MilterConnectMacros, e, state);
3183	sm_free(buf); /* XXX */
3184
3185	/*
3186	**  If this message connection is done for,
3187	**  close the filters.
3188	*/
3189
3190	if (*state != SMFIR_CONTINUE)
3191	{
3192		if (MilterLogLevel > 9)
3193			sm_syslog(LOG_INFO, e->e_id, "Milter: connect, ending");
3194		milter_quit(e);
3195	}
3196	else
3197		milter_per_connection_check(e);
3198
3199	/*
3200	**  SMFIR_REPLYCODE can't work with connect due to
3201	**  the requirements of SMTP.  Therefore, ignore the
3202	**  reply code text but keep the state it would reflect.
3203	*/
3204
3205	if (*state == SMFIR_REPLYCODE)
3206	{
3207		if (response != NULL &&
3208		    *response == '4')
3209			*state = SMFIR_TEMPFAIL;
3210		else
3211			*state = SMFIR_REJECT;
3212		if (response != NULL)
3213		{
3214			sm_free(response); /* XXX */
3215			response = NULL;
3216		}
3217	}
3218	return response;
3219}
3220/*
3221**  MILTER_HELO -- send SMTP HELO/EHLO command info to milter filters
3222**
3223**	Parameters:
3224**		helo -- argument to SMTP HELO/EHLO command.
3225**		e -- current envelope.
3226**		state -- return state from response.
3227**
3228**	Returns:
3229**		response string (may be NULL)
3230*/
3231
3232char *
3233milter_helo(helo, e, state)
3234	char *helo;
3235	ENVELOPE *e;
3236	char *state;
3237{
3238	int i;
3239	char *response;
3240
3241	if (tTd(64, 10))
3242		sm_dprintf("milter_helo(%s)\n", helo);
3243
3244	/* HELO/EHLO can come at any point */
3245	for (i = 0; InputFilters[i] != NULL; i++)
3246	{
3247		struct milter *m = InputFilters[i];
3248
3249		switch (m->mf_state)
3250		{
3251		  case SMFS_INMSG:
3252			/* abort in message filters */
3253			milter_abort_filter(m, e);
3254			/* FALLTHROUGH */
3255
3256		  case SMFS_DONE:
3257			/* reset done filters */
3258			m->mf_state = SMFS_OPEN;
3259			break;
3260		}
3261	}
3262
3263	response = milter_command(SMFIC_HELO, helo, strlen(helo) + 1,
3264				  MilterHeloMacros, e, state);
3265	milter_per_connection_check(e);
3266	return response;
3267}
3268/*
3269**  MILTER_ENVFROM -- send SMTP MAIL command info to milter filters
3270**
3271**	Parameters:
3272**		args -- SMTP MAIL command args (args[0] == sender).
3273**		e -- current envelope.
3274**		state -- return state from response.
3275**
3276**	Returns:
3277**		response string (may be NULL)
3278*/
3279
3280char *
3281milter_envfrom(args, e, state)
3282	char **args;
3283	ENVELOPE *e;
3284	char *state;
3285{
3286	int i;
3287	char *buf, *bp;
3288	char *response;
3289	ssize_t s;
3290
3291	if (tTd(64, 10))
3292	{
3293		sm_dprintf("milter_envfrom:");
3294		for (i = 0; args[i] != NULL; i++)
3295			sm_dprintf(" %s", args[i]);
3296		sm_dprintf("\n");
3297	}
3298
3299	/* sanity check */
3300	if (args[0] == NULL)
3301	{
3302		*state = SMFIR_REJECT;
3303		if (MilterLogLevel > 10)
3304			sm_syslog(LOG_INFO, e->e_id,
3305				  "Milter: reject, no sender");
3306		return NULL;
3307	}
3308
3309	/* new message, so ... */
3310	for (i = 0; InputFilters[i] != NULL; i++)
3311	{
3312		struct milter *m = InputFilters[i];
3313
3314		switch (m->mf_state)
3315		{
3316		  case SMFS_INMSG:
3317			/* abort in message filters */
3318			milter_abort_filter(m, e);
3319			/* FALLTHROUGH */
3320
3321		  case SMFS_DONE:
3322			/* reset done filters */
3323			m->mf_state = SMFS_OPEN;
3324			break;
3325		}
3326	}
3327
3328	/* put together data */
3329	s = 0;
3330	for (i = 0; args[i] != NULL; i++)
3331		s += strlen(args[i]) + 1;
3332
3333	if (s < 0)
3334	{
3335		*state = SMFIR_TEMPFAIL;
3336		return NULL;
3337	}
3338
3339	buf = (char *) xalloc(s);
3340	bp = buf;
3341	for (i = 0; args[i] != NULL; i++)
3342	{
3343		(void) sm_strlcpy(bp, args[i], s - (bp - buf));
3344		bp += strlen(bp) + 1;
3345	}
3346
3347	if (MilterLogLevel > 14)
3348		sm_syslog(LOG_INFO, e->e_id, "Milter: senders: %s", buf);
3349
3350	/* send it over */
3351	response = milter_command(SMFIC_MAIL, buf, s,
3352				  MilterEnvFromMacros, e, state);
3353	sm_free(buf); /* XXX */
3354
3355	/*
3356	**  If filter rejects/discards a per message command,
3357	**  abort the other filters since we are done with the
3358	**  current message.
3359	*/
3360
3361	MILTER_CHECK_DONE_MSG();
3362	if (MilterLogLevel > 10 && *state == SMFIR_REJECT)
3363		sm_syslog(LOG_INFO, e->e_id, "Milter: reject, senders");
3364	return response;
3365}
3366/*
3367**  MILTER_ENVRCPT -- send SMTP RCPT command info to milter filters
3368**
3369**	Parameters:
3370**		args -- SMTP MAIL command args (args[0] == recipient).
3371**		e -- current envelope.
3372**		state -- return state from response.
3373**
3374**	Returns:
3375**		response string (may be NULL)
3376*/
3377
3378char *
3379milter_envrcpt(args, e, state)
3380	char **args;
3381	ENVELOPE *e;
3382	char *state;
3383{
3384	int i;
3385	char *buf, *bp;
3386	char *response;
3387	ssize_t s;
3388
3389	if (tTd(64, 10))
3390	{
3391		sm_dprintf("milter_envrcpt:");
3392		for (i = 0; args[i] != NULL; i++)
3393			sm_dprintf(" %s", args[i]);
3394		sm_dprintf("\n");
3395	}
3396
3397	/* sanity check */
3398	if (args[0] == NULL)
3399	{
3400		*state = SMFIR_REJECT;
3401		if (MilterLogLevel > 10)
3402			sm_syslog(LOG_INFO, e->e_id, "Milter: reject, no rcpt");
3403		return NULL;
3404	}
3405
3406	/* put together data */
3407	s = 0;
3408	for (i = 0; args[i] != NULL; i++)
3409		s += strlen(args[i]) + 1;
3410
3411	if (s < 0)
3412	{
3413		*state = SMFIR_TEMPFAIL;
3414		return NULL;
3415	}
3416
3417	buf = (char *) xalloc(s);
3418	bp = buf;
3419	for (i = 0; args[i] != NULL; i++)
3420	{
3421		(void) sm_strlcpy(bp, args[i], s - (bp - buf));
3422		bp += strlen(bp) + 1;
3423	}
3424
3425	if (MilterLogLevel > 14)
3426		sm_syslog(LOG_INFO, e->e_id, "Milter: rcpts: %s", buf);
3427
3428	/* send it over */
3429	response = milter_command(SMFIC_RCPT, buf, s,
3430				  MilterEnvRcptMacros, e, state);
3431	sm_free(buf); /* XXX */
3432	return response;
3433}
3434/*
3435**  MILTER_DATA -- send message headers/body and gather final message results
3436**
3437**	Parameters:
3438**		e -- current envelope.
3439**		state -- return state from response.
3440**
3441**	Returns:
3442**		response string (may be NULL)
3443**
3444**	Side effects:
3445**		- Uses e->e_dfp for access to the body
3446**		- Can call the various milter action routines to
3447**		  modify the envelope or message.
3448*/
3449
3450# define MILTER_CHECK_RESULTS() \
3451	if (*state == SMFIR_ACCEPT || \
3452	    m->mf_state == SMFS_DONE || \
3453	    m->mf_state == SMFS_ERROR) \
3454	{ \
3455		if (m->mf_state != SMFS_ERROR) \
3456			m->mf_state = SMFS_DONE; \
3457		continue;	/* to next filter */ \
3458	} \
3459	if (*state != SMFIR_CONTINUE) \
3460	{ \
3461		m->mf_state = SMFS_DONE; \
3462		goto finishup; \
3463	}
3464
3465char *
3466milter_data(e, state)
3467	ENVELOPE *e;
3468	char *state;
3469{
3470	bool replbody = false;		/* milter_replbody() called? */
3471	bool replfailed = false;	/* milter_replbody() failed? */
3472	bool rewind = false;		/* rewind data file? */
3473	bool dfopen = false;		/* data file open for writing? */
3474	bool newfilter;			/* reset on each new filter */
3475	char rcmd;
3476	int i;
3477	int save_errno;
3478	char *response = NULL;
3479	time_t eomsent;
3480	ssize_t rlen;
3481
3482	if (tTd(64, 10))
3483		sm_dprintf("milter_data\n");
3484
3485	*state = SMFIR_CONTINUE;
3486
3487	/*
3488	**  XXX: Should actually send body chunks to each filter
3489	**  a chunk at a time instead of sending the whole body to
3490	**  each filter in turn.  However, only if the filters don't
3491	**  change the body.
3492	*/
3493
3494	for (i = 0; InputFilters[i] != NULL; i++)
3495	{
3496		struct milter *m = InputFilters[i];
3497
3498		if (*state != SMFIR_CONTINUE &&
3499		    *state != SMFIR_ACCEPT)
3500		{
3501			/*
3502			**  A previous filter has dealt with the message,
3503			**  safe to stop processing the filters.
3504			*/
3505
3506			break;
3507		}
3508
3509		/* Now reset state for later evaluation */
3510		*state = SMFIR_CONTINUE;
3511		newfilter = true;
3512
3513		/* previous problem? */
3514		if (m->mf_state == SMFS_ERROR)
3515		{
3516			MILTER_CHECK_ERROR(continue);
3517			break;
3518		}
3519
3520		/* sanity checks */
3521		if (m->mf_sock < 0 ||
3522		    (m->mf_state != SMFS_OPEN && m->mf_state != SMFS_INMSG))
3523			continue;
3524
3525		m->mf_state = SMFS_INMSG;
3526
3527		/* check if filter wants the headers */
3528		if (!bitset(SMFIP_NOHDRS, m->mf_pflags))
3529		{
3530			response = milter_headers(m, e, state);
3531			MILTER_CHECK_RESULTS();
3532		}
3533
3534		/* check if filter wants EOH */
3535		if (!bitset(SMFIP_NOEOH, m->mf_pflags))
3536		{
3537			if (tTd(64, 10))
3538				sm_dprintf("milter_data: eoh\n");
3539
3540			/* send it over */
3541			response = milter_send_command(m, SMFIC_EOH, NULL, 0,
3542						       e, state);
3543			MILTER_CHECK_RESULTS();
3544		}
3545
3546		/* check if filter wants the body */
3547		if (!bitset(SMFIP_NOBODY, m->mf_pflags) &&
3548		    e->e_dfp != NULL)
3549		{
3550			rewind = true;
3551			response = milter_body(m, e, state);
3552			MILTER_CHECK_RESULTS();
3553		}
3554
3555		/* send the final body chunk */
3556		(void) milter_write(m, SMFIC_BODYEOB, NULL, 0,
3557				    m->mf_timeout[SMFTO_WRITE], e);
3558
3559		/* Get time EOM sent for timeout */
3560		eomsent = curtime();
3561
3562		/* deal with the possibility of multiple responses */
3563		while (*state == SMFIR_CONTINUE)
3564		{
3565			/* Check total timeout from EOM to final ACK/NAK */
3566			if (m->mf_timeout[SMFTO_EOM] > 0 &&
3567			    curtime() - eomsent >= m->mf_timeout[SMFTO_EOM])
3568			{
3569				if (tTd(64, 5))
3570					sm_dprintf("milter_data(%s): EOM ACK/NAK timeout\n",
3571						m->mf_name);
3572				if (MilterLogLevel > 0)
3573					sm_syslog(LOG_ERR, e->e_id,
3574						  "milter_data(%s): EOM ACK/NAK timeout",
3575						  m->mf_name);
3576				milter_error(m, e);
3577				MILTER_CHECK_ERROR(break);
3578				break;
3579			}
3580
3581			response = milter_read(m, &rcmd, &rlen,
3582					       m->mf_timeout[SMFTO_READ], e);
3583			if (m->mf_state == SMFS_ERROR)
3584				break;
3585
3586			if (tTd(64, 10))
3587				sm_dprintf("milter_data(%s): state %c\n",
3588					   m->mf_name, (char) rcmd);
3589
3590			switch (rcmd)
3591			{
3592			  case SMFIR_REPLYCODE:
3593				MILTER_CHECK_REPLYCODE("554 5.7.1 Command rejected");
3594				if (MilterLogLevel > 12)
3595					sm_syslog(LOG_INFO, e->e_id, "milter=%s, reject=%s",
3596						  m->mf_name, response);
3597				*state = rcmd;
3598				m->mf_state = SMFS_DONE;
3599				break;
3600
3601			  case SMFIR_REJECT: /* log msg at end of function */
3602				if (MilterLogLevel > 12)
3603					sm_syslog(LOG_INFO, e->e_id, "milter=%s, reject",
3604						  m->mf_name);
3605				*state = rcmd;
3606				m->mf_state = SMFS_DONE;
3607				break;
3608
3609			  case SMFIR_DISCARD:
3610				if (MilterLogLevel > 12)
3611					sm_syslog(LOG_INFO, e->e_id, "milter=%s, discard",
3612						  m->mf_name);
3613				*state = rcmd;
3614				m->mf_state = SMFS_DONE;
3615				break;
3616
3617			  case SMFIR_TEMPFAIL:
3618				if (MilterLogLevel > 12)
3619					sm_syslog(LOG_INFO, e->e_id, "milter=%s, tempfail",
3620						  m->mf_name);
3621				*state = rcmd;
3622				m->mf_state = SMFS_DONE;
3623				break;
3624
3625			  case SMFIR_CONTINUE:
3626			  case SMFIR_ACCEPT:
3627				/* this filter is done with message */
3628				if (replfailed)
3629					*state = SMFIR_TEMPFAIL;
3630				else
3631					*state = SMFIR_ACCEPT;
3632				m->mf_state = SMFS_DONE;
3633				break;
3634
3635			  case SMFIR_PROGRESS:
3636				break;
3637
3638# if _FFR_QUARANTINE
3639			  case SMFIR_QUARANTINE:
3640				if (!bitset(SMFIF_QUARANTINE, m->mf_fflags))
3641				{
3642					if (MilterLogLevel > 9)
3643						sm_syslog(LOG_WARNING, e->e_id,
3644							  "milter_data(%s): lied about quarantining, honoring request anyway",
3645							  m->mf_name);
3646				}
3647				if (response == NULL)
3648					response = newstr("");
3649				if (MilterLogLevel > 3)
3650					sm_syslog(LOG_INFO, e->e_id,
3651						  "milter=%s, quarantine=%s",
3652						  m->mf_name, response);
3653				e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool,
3654								 response);
3655				macdefine(&e->e_macro, A_PERM,
3656					  macid("{quarantine}"), e->e_quarmsg);
3657				break;
3658# endif /* _FFR_QUARANTINE */
3659
3660			  case SMFIR_ADDHEADER:
3661				if (!bitset(SMFIF_ADDHDRS, m->mf_fflags))
3662				{
3663					if (MilterLogLevel > 9)
3664						sm_syslog(LOG_WARNING, e->e_id,
3665							  "milter_data(%s): lied about adding headers, honoring request anyway",
3666							  m->mf_name);
3667				}
3668				milter_addheader(response, rlen, e);
3669				break;
3670
3671			  case SMFIR_CHGHEADER:
3672				if (!bitset(SMFIF_CHGHDRS, m->mf_fflags))
3673				{
3674					if (MilterLogLevel > 9)
3675						sm_syslog(LOG_WARNING, e->e_id,
3676							  "milter_data(%s): lied about changing headers, honoring request anyway",
3677							  m->mf_name);
3678				}
3679				milter_changeheader(response, rlen, e);
3680				break;
3681
3682			  case SMFIR_ADDRCPT:
3683				if (!bitset(SMFIF_ADDRCPT, m->mf_fflags))
3684				{
3685					if (MilterLogLevel > 9)
3686						sm_syslog(LOG_WARNING, e->e_id,
3687							  "milter_data(%s) lied about adding recipients, honoring request anyway",
3688							  m->mf_name);
3689				}
3690				milter_addrcpt(response, rlen, e);
3691				break;
3692
3693			  case SMFIR_DELRCPT:
3694				if (!bitset(SMFIF_DELRCPT, m->mf_fflags))
3695				{
3696					if (MilterLogLevel > 9)
3697						sm_syslog(LOG_WARNING, e->e_id,
3698							  "milter_data(%s): lied about removing recipients, honoring request anyway",
3699							  m->mf_name);
3700				}
3701				milter_delrcpt(response, rlen, e);
3702				break;
3703
3704			  case SMFIR_REPLBODY:
3705				if (!bitset(SMFIF_MODBODY, m->mf_fflags))
3706				{
3707					if (MilterLogLevel > 0)
3708						sm_syslog(LOG_ERR, e->e_id,
3709							  "milter_data(%s): lied about replacing body, rejecting request and tempfailing message",
3710							  m->mf_name);
3711					replfailed = true;
3712					break;
3713				}
3714
3715				/* already failed in attempt */
3716				if (replfailed)
3717					break;
3718
3719				if (!dfopen)
3720				{
3721					if (milter_reopen_df(e) < 0)
3722					{
3723						replfailed = true;
3724						break;
3725					}
3726					dfopen = true;
3727					rewind = true;
3728				}
3729
3730				if (milter_replbody(response, rlen,
3731						    newfilter, e) < 0)
3732					replfailed = true;
3733				newfilter = false;
3734				replbody = true;
3735				break;
3736
3737			  default:
3738				/* Invalid response to command */
3739				if (MilterLogLevel > 0)
3740					sm_syslog(LOG_ERR, e->e_id,
3741						  "milter_data(%s): returned bogus response %c",
3742						  m->mf_name, rcmd);
3743				milter_error(m, e);
3744				break;
3745			}
3746			if (rcmd != SMFIR_REPLYCODE && response != NULL)
3747			{
3748				sm_free(response); /* XXX */
3749				response = NULL;
3750			}
3751
3752			if (m->mf_state == SMFS_ERROR)
3753				break;
3754		}
3755
3756		if (replbody && !replfailed)
3757		{
3758			/* flush possible buffered character */
3759			milter_replbody(NULL, 0, !replbody, e);
3760			replbody = false;
3761		}
3762
3763		if (m->mf_state == SMFS_ERROR)
3764		{
3765			MILTER_CHECK_ERROR(continue);
3766			goto finishup;
3767		}
3768	}
3769
3770finishup:
3771	/* leave things in the expected state if we touched it */
3772	if (replfailed)
3773	{
3774		if (*state == SMFIR_CONTINUE ||
3775		    *state == SMFIR_ACCEPT)
3776		{
3777			*state = SMFIR_TEMPFAIL;
3778			SM_FREE_CLR(response);
3779		}
3780
3781		if (dfopen)
3782		{
3783			(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
3784			e->e_dfp = NULL;
3785			e->e_flags &= ~EF_HAS_DF;
3786			dfopen = false;
3787		}
3788		rewind = false;
3789	}
3790
3791	if ((dfopen && milter_reset_df(e) < 0) ||
3792	    (rewind && bfrewind(e->e_dfp) < 0))
3793	{
3794		save_errno = errno;
3795		ExitStat = EX_IOERR;
3796
3797		/*
3798		**  If filter told us to keep message but we had
3799		**  an error, we can't really keep it, tempfail it.
3800		*/
3801
3802		if (*state == SMFIR_CONTINUE ||
3803		    *state == SMFIR_ACCEPT)
3804		{
3805			*state = SMFIR_TEMPFAIL;
3806			SM_FREE_CLR(response);
3807		}
3808
3809		errno = save_errno;
3810		syserr("milter_data: %s/%cf%s: read error",
3811		       qid_printqueue(e->e_qgrp, e->e_qdir),
3812		       DATAFL_LETTER, e->e_id);
3813	}
3814
3815	MILTER_CHECK_DONE_MSG();
3816	if (MilterLogLevel > 10 && *state == SMFIR_REJECT)
3817		sm_syslog(LOG_INFO, e->e_id, "Milter: reject, data");
3818	return response;
3819}
3820/*
3821**  MILTER_QUIT -- informs the filter(s) we are done and closes connection(s)
3822**
3823**	Parameters:
3824**		e -- current envelope.
3825**
3826**	Returns:
3827**		none
3828*/
3829
3830void
3831milter_quit(e)
3832	ENVELOPE *e;
3833{
3834	int i;
3835
3836	if (tTd(64, 10))
3837		sm_dprintf("milter_quit(%s)\n", e->e_id);
3838
3839	for (i = 0; InputFilters[i] != NULL; i++)
3840		milter_quit_filter(InputFilters[i], e);
3841}
3842/*
3843**  MILTER_ABORT -- informs the filter(s) that we are aborting current message
3844**
3845**	Parameters:
3846**		e -- current envelope.
3847**
3848**	Returns:
3849**		none
3850*/
3851
3852void
3853milter_abort(e)
3854	ENVELOPE *e;
3855{
3856	int i;
3857
3858	if (tTd(64, 10))
3859		sm_dprintf("milter_abort\n");
3860
3861	for (i = 0; InputFilters[i] != NULL; i++)
3862	{
3863		struct milter *m = InputFilters[i];
3864
3865		/* sanity checks */
3866		if (m->mf_sock < 0 || m->mf_state != SMFS_INMSG)
3867			continue;
3868
3869		milter_abort_filter(m, e);
3870	}
3871}
3872#endif /* MILTER */
3873