1 /*
2  * Copyright (c) 1999-2009, 2012, 2013 Proofpoint, 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 
13 SM_RCSID("$MirOS: src/gnu/usr.sbin/sendmail/sendmail/milter.c,v 1.8 2014/06/09 15:17:51 tg Exp $")
14 SM_RCSID("@(#)$Id: milter.c,v 8.281 2013-11-22 20:51:56 ca Exp $")
15 
16 #if MILTER
17 # include <sm/sendmail.h>
18 # include <libmilter/mfapi.h>
19 # include <libmilter/mfdef.h>
20 
21 # include <errno.h>
22 # include <sm/time.h>
23 # include <sys/uio.h>
24 
25 # if NETINET || NETINET6
26 #  include <arpa/inet.h>
27 #  if MILTER_NO_NAGLE
28 #   include <netinet/tcp.h>
29 #  endif /* MILTER_NO_NAGLE */
30 # endif /* NETINET || NETINET6 */
31 
32 # include <sm/fdset.h>
33 
34 static void	milter_connect_timeout __P((int));
35 static void	milter_error __P((struct milter *, ENVELOPE *));
36 static int	milter_open __P((struct milter *, bool, ENVELOPE *));
37 static void	milter_parse_timeouts __P((char *, struct milter *));
38 static char	*milter_sysread __P((struct milter *, char *, ssize_t, time_t,
39 			ENVELOPE *, const char *));
40 static char	*milter_read __P((struct milter *, char *, ssize_t *, time_t,
41 			ENVELOPE *, const char *));
42 static char	*milter_write __P((struct milter *, int, char *, ssize_t,
43 			time_t, ENVELOPE *, const char *));
44 static char	*milter_send_command __P((struct milter *, int, void *,
45 			ssize_t, ENVELOPE *, char *, const char *));
46 static char	*milter_command __P((int, void *, ssize_t, int,
47 			ENVELOPE *, char *, const char *, bool));
48 static char	*milter_body __P((struct milter *, ENVELOPE *, char *));
49 static int	milter_reopen_df __P((ENVELOPE *));
50 static int	milter_reset_df __P((ENVELOPE *));
51 static void	milter_quit_filter __P((struct milter *, ENVELOPE *));
52 static void	milter_abort_filter __P((struct milter *, ENVELOPE *));
53 static void	milter_send_macros __P((struct milter *, char **, int,
54 			ENVELOPE *));
55 static int	milter_negotiate __P((struct milter *, ENVELOPE *,
56 			milters_T *));
57 static void	milter_per_connection_check __P((ENVELOPE *));
58 static char	*milter_headers __P((struct milter *, ENVELOPE *, char *));
59 static void	milter_addheader __P((struct milter *, char *, ssize_t,
60 			ENVELOPE *));
61 static void	milter_insheader __P((struct milter *, char *, ssize_t,
62 			ENVELOPE *));
63 static void	milter_changeheader __P((struct milter *, char *, ssize_t,
64 			ENVELOPE *));
65 static void	milter_chgfrom __P((char *, ssize_t, ENVELOPE *));
66 static void	milter_addrcpt __P((char *, ssize_t, ENVELOPE *));
67 static void	milter_addrcpt_par __P((char *, ssize_t, ENVELOPE *));
68 static void	milter_delrcpt __P((char *, ssize_t, ENVELOPE *));
69 static int	milter_replbody __P((char *, ssize_t, bool, ENVELOPE *));
70 static int	milter_set_macros __P((char *, char **, char *, int));
71 
72 
73 /* milter states */
74 # define SMFS_CLOSED		'C'	/* closed for all further actions */
75 # define SMFS_OPEN		'O'	/* connected to remote milter filter */
76 # define SMFS_INMSG		'M'	/* currently servicing a message */
77 # define SMFS_DONE		'D'	/* done with current message */
78 # define SMFS_CLOSABLE		'Q'	/* done with current connection */
79 # define SMFS_ERROR		'E'	/* error state */
80 # define SMFS_READY		'R'	/* ready for action */
81 # define SMFS_SKIP		'S'	/* skip body */
82 
83 /*
84 **  MilterMacros contains the milter macros for each milter and each stage.
85 **  indices are (in order): stages, milter-index, macro
86 **  milter-index == 0: "global" macros (not for a specific milter).
87 */
88 
89 static char *MilterMacros[SMFIM_LAST + 1][MAXFILTERS + 1][MAXFILTERMACROS + 1];
90 static size_t MilterMaxDataSize = MILTER_MAX_DATA_SIZE;
91 
92 # define MILTER_CHECK_DONE_MSG() \
93 	if (*state == SMFIR_REPLYCODE || \
94 	    *state == SMFIR_REJECT || \
95 	    *state == SMFIR_DISCARD || \
96 	    *state == SMFIR_TEMPFAIL) \
97 	{ \
98 		/* Abort the filters to let them know we are done with msg */ \
99 		milter_abort(e); \
100 	}
101 
102 /* set state in case of an error */
103 # define MILTER_SET_STATE	\
104 	if (bitnset(SMF_TEMPFAIL, m->mf_flags)) \
105 		*state = SMFIR_TEMPFAIL; \
106 	else if (bitnset(SMF_TEMPDROP, m->mf_flags)) \
107 		*state = SMFIR_SHUTDOWN; \
108 	else if (bitnset(SMF_REJECT, m->mf_flags)) \
109 		*state = SMFIR_REJECT
110 
111 /* flow through code maybe using continue; don't wrap in do {} while */
112 # define MILTER_CHECK_ERROR(initial, action) \
113 	if (!initial && tTd(71, 100)) \
114 	{ \
115 		if (e->e_quarmsg == NULL) \
116 		{ \
117 			e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool, \
118 							 "filter failure"); \
119 			macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), \
120 				  e->e_quarmsg); \
121 		} \
122 	} \
123 	else if (tTd(71, 101)) \
124 	{ \
125 		if (e->e_quarmsg == NULL) \
126 		{ \
127 			e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool, \
128 							 "filter failure"); \
129 			macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), \
130 				  e->e_quarmsg); \
131 		} \
132 	} \
133 	else MILTER_SET_STATE;	\
134 	else \
135 		action;
136 
137 # define MILTER_CHECK_REPLYCODE(default) \
138 	if (response == NULL || \
139 	    strlen(response) + 1 != (size_t) rlen || \
140 	    rlen < 3 || \
141 	    (response[0] != '4' && response[0] != '5') || \
142 	    !isascii(response[1]) || !isdigit(response[1]) || \
143 	    !isascii(response[2]) || !isdigit(response[2])) \
144 	{ \
145 		if (response != NULL) \
146 			sm_free(response); /* XXX */ \
147 		response = newstr(default); \
148 	} \
149 	else \
150 	{ \
151 		char *ptr = response; \
152  \
153 		/* Check for unprotected %'s in the string */ \
154 		while (*ptr != '\0') \
155 		{ \
156 			if (*ptr == '%' && *++ptr != '%') \
157 			{ \
158 				sm_free(response); /* XXX */ \
159 				response = newstr(default); \
160 				break; \
161 			} \
162 			ptr++; \
163 		} \
164 	}
165 
166 # define MILTER_DF_ERROR(msg) \
167 { \
168 	int save_errno = errno; \
169  \
170 	if (tTd(64, 5)) \
171 	{ \
172 		sm_dprintf(msg, dfname, sm_errstring(save_errno)); \
173 		sm_dprintf("\n"); \
174 	} \
175 	if (MilterLogLevel > 0) \
176 		sm_syslog(LOG_ERR, e->e_id, msg, dfname, sm_errstring(save_errno)); \
177 	if (SuperSafe == SAFE_REALLY) \
178 	{ \
179 		if (e->e_dfp != NULL) \
180 		{ \
181 			(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT); \
182 			e->e_dfp = NULL; \
183 		} \
184 		e->e_flags &= ~EF_HAS_DF; \
185 	} \
186 	errno = save_errno; \
187 }
188 
189 /*
190 **  MILTER_TIMEOUT -- make sure socket is ready in time
191 **
192 **	Parameters:
193 **		routine -- routine name for debug/logging
194 **		secs -- number of seconds in timeout
195 **		write -- waiting to read or write?
196 **		started -- whether this is part of a previous sequence
197 **
198 **	Assumes 'm' is a milter structure for the current socket.
199 */
200 
201 # define MILTER_TIMEOUT(routine, secs, write, started, function) \
202 { \
203 	int ret; \
204 	int save_errno; \
205 	fd_set fds; \
206 	struct timeval tv; \
207  \
208 	if (SM_FD_SETSIZE > 0 && m->mf_sock >= SM_FD_SETSIZE) \
209 	{ \
210 		if (tTd(64, 5)) \
211 			sm_dprintf("milter_%s(%s): socket %d is larger than FD_SETSIZE %d\n", \
212 				   (routine), m->mf_name, m->mf_sock, \
213 				   SM_FD_SETSIZE); \
214 		if (MilterLogLevel > 0) \
215 			sm_syslog(LOG_ERR, e->e_id, \
216 				  "Milter (%s): socket(%s) %d is larger than FD_SETSIZE %d", \
217 				  m->mf_name, (routine), m->mf_sock, \
218 				  SM_FD_SETSIZE); \
219 		milter_error(m, e); \
220 		return NULL; \
221 	} \
222  \
223 	do \
224 	{ \
225 		FD_ZERO(&fds); \
226 		SM_FD_SET(m->mf_sock, &fds); \
227 		tv.tv_sec = (secs); \
228 		tv.tv_usec = 0; \
229 		ret = select(m->mf_sock + 1, \
230 			     (write) ? NULL : &fds, \
231 			     (write) ? &fds : NULL, \
232 			     NULL, &tv); \
233 	} while (ret < 0 && errno == EINTR); \
234  \
235 	switch (ret) \
236 	{ \
237 	  case 0: \
238 		if (tTd(64, 5)) \
239 			sm_dprintf("milter_%s(%s): timeout, where=%s\n", \
240 				(routine), m->mf_name, (function)); \
241 		if (MilterLogLevel > 0) \
242 			sm_syslog(LOG_ERR, e->e_id, \
243 				  "Milter (%s): timeout %s data %s, where=%s", \
244 				  m->mf_name, \
245 				  started ? "during" : "before", \
246 				  (routine), (function)); \
247 		milter_error(m, e); \
248 		return NULL; \
249  \
250 	  case -1: \
251 		save_errno = errno; \
252 		if (tTd(64, 5)) \
253 			sm_dprintf("milter_%s(%s): select: %s\n", (routine), \
254 				   m->mf_name, sm_errstring(save_errno)); \
255 		if (MilterLogLevel > 0) \
256 		{ \
257 			sm_syslog(LOG_ERR, e->e_id, \
258 				  "Milter (%s): select(%s): %s", \
259 				  m->mf_name, (routine), \
260 				  sm_errstring(save_errno)); \
261 		} \
262 		milter_error(m, e); \
263 		return NULL; \
264  \
265 	  default: \
266 		if (SM_FD_ISSET(m->mf_sock, &fds)) \
267 			break; \
268 		if (tTd(64, 5)) \
269 			sm_dprintf("milter_%s(%s): socket not ready\n", \
270 				(routine), m->mf_name); \
271 		if (MilterLogLevel > 0) \
272 		{ \
273 			sm_syslog(LOG_ERR, e->e_id, \
274 				  "Milter (%s): socket(%s) not ready", \
275 				  m->mf_name, (routine)); \
276 		} \
277 		milter_error(m, e); \
278 		return NULL; \
279 	} \
280 }
281 
282 /*
283 **  Low level functions
284 */
285 
286 /*
287 **  MILTER_READ -- read from a remote milter filter
288 **
289 **	Parameters:
290 **		m -- milter to read from.
291 **		cmd -- return param for command read.
292 **		rlen -- return length of response string.
293 **		to -- timeout in seconds.
294 **		e -- current envelope.
295 **
296 **	Returns:
297 **		response string (may be NULL)
298 */
299 
300 static char *
milter_sysread(m,buf,sz,to,e,where)301 milter_sysread(m, buf, sz, to, e, where)
302 	struct milter *m;
303 	char *buf;
304 	ssize_t sz;
305 	time_t to;
306 	ENVELOPE *e;
307 	const char *where;
308 {
309 	time_t readstart = 0;
310 	ssize_t len, curl;
311 	bool started = false;
312 
313 	curl = 0;
314 
315 	if (to > 0)
316 		readstart = curtime();
317 
318 	for (;;)
319 	{
320 		if (to > 0)
321 		{
322 			time_t now;
323 
324 			now = curtime();
325 			if (now - readstart >= to)
326 			{
327 				if (tTd(64, 5))
328 					sm_dprintf("milter_sys_read (%s): timeout %s data read in %s",
329 						  m->mf_name,
330 						  started ? "during" : "before",
331 						  where);
332 				if (MilterLogLevel > 0)
333 					sm_syslog(LOG_ERR, e->e_id,
334 						  "Milter (%s): timeout %s data read in %s",
335 						  m->mf_name,
336 						  started ? "during" : "before",
337 						  where);
338 				milter_error(m, e);
339 				return NULL;
340 			}
341 			to -= now - readstart;
342 			readstart = now;
343 			MILTER_TIMEOUT("read", to, false, started, where);
344 		}
345 
346 		len = read(m->mf_sock, buf + curl, sz - curl);
347 
348 		if (len < 0)
349 		{
350 			int save_errno = errno;
351 
352 			if (tTd(64, 5))
353 				sm_dprintf("milter_sys_read(%s): read returned %ld: %s\n",
354 					m->mf_name, (long) len,
355 					sm_errstring(save_errno));
356 			if (MilterLogLevel > 0)
357 				sm_syslog(LOG_ERR, e->e_id,
358 					  "Milter (%s): read returned %ld: %s",
359 					  m->mf_name, (long) len,
360 					  sm_errstring(save_errno));
361 			milter_error(m, e);
362 			return NULL;
363 		}
364 
365 		started = true;
366 		curl += len;
367 		if (len == 0 || curl >= sz)
368 			break;
369 
370 	}
371 
372 	if (curl != sz)
373 	{
374 		if (tTd(64, 5))
375 			sm_dprintf("milter_sys_read(%s): cmd read returned %ld, expecting %ld\n",
376 				m->mf_name, (long) curl, (long) sz);
377 		if (MilterLogLevel > 0)
378 			sm_syslog(LOG_ERR, e->e_id,
379 				  "milter_sys_read(%s): cmd read returned %ld, expecting %ld",
380 				  m->mf_name, (long) curl, (long) sz);
381 		milter_error(m, e);
382 		return NULL;
383 	}
384 	return buf;
385 }
386 
387 static char *
milter_read(m,cmd,rlen,to,e,where)388 milter_read(m, cmd, rlen, to, e, where)
389 	struct milter *m;
390 	char *cmd;
391 	ssize_t *rlen;
392 	time_t to;
393 	ENVELOPE *e;
394 	const char *where;
395 {
396 	time_t readstart = 0;
397 	ssize_t expl;
398 	mi_int32 i;
399 # if MILTER_NO_NAGLE && defined(TCP_CORK)
400 	int cork = 0;
401 # endif /* MILTER_NO_NAGLE && defined(TCP_CORK) */
402 	char *buf;
403 	char data[MILTER_LEN_BYTES + 1];
404 
405 	if (m->mf_sock < 0)
406 	{
407 		if (MilterLogLevel > 0)
408 			sm_syslog(LOG_ERR, e->e_id,
409 				  "milter_read(%s): socket closed, where=%s",
410 				  m->mf_name, where);
411 		milter_error(m, e);
412 		return NULL;
413 	}
414 
415 	*rlen = 0;
416 	*cmd = '\0';
417 
418 	if (to > 0)
419 		readstart = curtime();
420 
421 # if MILTER_NO_NAGLE && defined(TCP_CORK)
422 	setsockopt(m->mf_sock, IPPROTO_TCP, TCP_CORK, (char *)&cork,
423 		   sizeof(cork));
424 # endif /* MILTER_NO_NAGLE && defined(TCP_CORK) */
425 
426 	if (milter_sysread(m, data, sizeof(data), to, e, where) == NULL)
427 		return NULL;
428 
429 # if MILTER_NO_NAGLE && defined(TCP_CORK)
430 	cork = 1;
431 	setsockopt(m->mf_sock, IPPROTO_TCP, TCP_CORK, (char *)&cork,
432 		   sizeof(cork));
433 # endif /* MILTER_NO_NAGLE && defined(TCP_CORK) */
434 
435 	/* reset timeout */
436 	if (to > 0)
437 	{
438 		time_t now;
439 
440 		now = curtime();
441 		if (now - readstart >= to)
442 		{
443 			if (tTd(64, 5))
444 				sm_dprintf("milter_read(%s): timeout before data read, where=%s\n",
445 					m->mf_name, where);
446 			if (MilterLogLevel > 0)
447 				sm_syslog(LOG_ERR, e->e_id,
448 					  "Milter read(%s): timeout before data read, where=%s",
449 					  m->mf_name, where);
450 			milter_error(m, e);
451 			return NULL;
452 		}
453 		to -= now - readstart;
454 	}
455 
456 	*cmd = data[MILTER_LEN_BYTES];
457 	data[MILTER_LEN_BYTES] = '\0';
458 	(void) memcpy(&i, data, MILTER_LEN_BYTES);
459 	expl = ntohl(i) - 1;
460 
461 	if (tTd(64, 25))
462 		sm_dprintf("milter_read(%s): expecting %ld bytes\n",
463 			m->mf_name, (long) expl);
464 
465 	if (expl < 0)
466 	{
467 		if (tTd(64, 5))
468 			sm_dprintf("milter_read(%s): read size %ld out of range, where=%s\n",
469 				m->mf_name, (long) expl, where);
470 		if (MilterLogLevel > 0)
471 			sm_syslog(LOG_ERR, e->e_id,
472 				  "milter_read(%s): read size %ld out of range, where=%s",
473 				  m->mf_name, (long) expl, where);
474 		milter_error(m, e);
475 		return NULL;
476 	}
477 
478 	if (expl == 0)
479 		return NULL;
480 
481 	buf = (char *) xalloc(expl);
482 
483 	if (milter_sysread(m, buf, expl, to, e, where) == NULL)
484 	{
485 		sm_free(buf); /* XXX */
486 		return NULL;
487 	}
488 
489 	if (tTd(64, 50))
490 		sm_dprintf("milter_read(%s): Returning %*s\n",
491 			m->mf_name, (int) expl, buf);
492 	*rlen = expl;
493 	return buf;
494 }
495 
496 /*
497 **  MILTER_WRITE -- write to a remote milter filter
498 **
499 **	Parameters:
500 **		m -- milter to read from.
501 **		cmd -- command to send.
502 **		buf -- optional command data.
503 **		len -- length of buf.
504 **		to -- timeout in seconds.
505 **		e -- current envelope.
506 **
507 **	Returns:
508 **		buf if successful, NULL otherwise
509 **		Not actually used anywhere but function prototype
510 **			must match milter_read()
511 */
512 
513 static char *
milter_write(m,cmd,buf,len,to,e,where)514 milter_write(m, cmd, buf, len, to, e, where)
515 	struct milter *m;
516 	int cmd;
517 	char *buf;
518 	ssize_t len;
519 	time_t to;
520 	ENVELOPE *e;
521 	const char *where;
522 {
523 	ssize_t sl, i;
524 	int num_vectors;
525 	mi_int32 nl;
526 	char command = (char) cmd;
527 	char data[MILTER_LEN_BYTES + 1];
528 	bool started = false;
529 	struct iovec vector[2];
530 
531 	/*
532 	**  At most two buffers will be written, though
533 	**  only one may actually be used (see num_vectors).
534 	**  The first is the size/command and the second is the command data.
535 	*/
536 
537 	if (len < 0 || len > MilterMaxDataSize)
538 	{
539 		if (tTd(64, 5))
540 		{
541 			sm_dprintf("milter_write(%s): length %ld out of range, cmd=%c\n",
542 				m->mf_name, (long) len, command);
543 			sm_dprintf("milter_write(%s): buf=%s\n",
544 				m->mf_name, str2prt(buf));
545 		}
546 		if (MilterLogLevel > 0)
547 			sm_syslog(LOG_ERR, e->e_id,
548 				  "milter_write(%s): length %ld out of range, cmd=%c",
549 				  m->mf_name, (long) len, command);
550 		milter_error(m, e);
551 		return NULL;
552 	}
553 	if (m->mf_sock < 0)
554 	{
555 		if (MilterLogLevel > 0)
556 			sm_syslog(LOG_ERR, e->e_id,
557 				  "milter_write(%s): socket closed",
558 				  m->mf_name);
559 		milter_error(m, e);
560 		return NULL;
561 	}
562 
563 	if (tTd(64, 20))
564 		sm_dprintf("milter_write(%s): cmd %c, len %ld\n",
565 			   m->mf_name, command, (long) len);
566 
567 	nl = htonl(len + 1);	/* add 1 for the command char */
568 	(void) memcpy(data, (char *) &nl, MILTER_LEN_BYTES);
569 	data[MILTER_LEN_BYTES] = command;
570 	sl = MILTER_LEN_BYTES + 1;
571 
572 	/* set up the vector for the size / command */
573 	vector[0].iov_base = (void *) data;
574 	vector[0].iov_len  = sl;
575 
576 	/*
577 	**  Determine if there is command data.  If so, there will be two
578 	**  vectors.  If not, there will be only one.  The vectors are set
579 	**  up here and 'num_vectors' and 'sl' are set appropriately.
580 	*/
581 
582 	/* NOTE:  len<0 has already been checked for.  Pedantic */
583 	if (len <= 0 || buf == NULL)
584 	{
585 		/* There is no command data -- only a size / command data */
586 		num_vectors = 1;
587 	}
588 	else
589 	{
590 		/*
591 		**  There is both size / command and command data.
592 		**  Set up the vector for the command data.
593 		*/
594 
595 		num_vectors = 2;
596 		sl += len;
597 		vector[1].iov_base = (void *) buf;
598 		vector[1].iov_len  = len;
599 
600 		if (tTd(64, 50))
601 			sm_dprintf("milter_write(%s): Sending %*s\n",
602 				   m->mf_name, (int) len, buf);
603 	}
604 
605 	if (to > 0)
606 		MILTER_TIMEOUT("write", to, true, started, where);
607 
608 	/* write the vector(s) */
609 	i = writev(m->mf_sock, vector, num_vectors);
610 	if (i != sl)
611 	{
612 		int save_errno = errno;
613 
614 		if (tTd(64, 5))
615 			sm_dprintf("milter_write(%s): write(%c) returned %ld, expected %ld: %s\n",
616 				   m->mf_name, command, (long) i, (long) sl,
617 				   sm_errstring(save_errno));
618 		if (MilterLogLevel > 0)
619 			sm_syslog(LOG_ERR, e->e_id,
620 				  "Milter (%s): write(%c) returned %ld, expected %ld: %s",
621 				  m->mf_name, command, (long) i, (long) sl,
622 				  sm_errstring(save_errno));
623 		milter_error(m, e);
624 		return NULL;
625 	}
626 	return buf;
627 }
628 
629 /*
630 **  Utility functions
631 */
632 
633 /*
634 **  MILTER_OPEN -- connect to remote milter filter
635 **
636 **	Parameters:
637 **		m -- milter to connect to.
638 **		parseonly -- parse but don't connect.
639 **		e -- current envelope.
640 **
641 **	Returns:
642 **		connected socket if successful && !parseonly,
643 **		0 upon parse success if parseonly,
644 **		-1 otherwise.
645 */
646 
647 static jmp_buf	MilterConnectTimeout;
648 
649 static int
milter_open(m,parseonly,e)650 milter_open(m, parseonly, e)
651 	struct milter *m;
652 	bool parseonly;
653 	ENVELOPE *e;
654 {
655 	int sock = 0;
656 	SOCKADDR_LEN_T addrlen = 0;
657 	int addrno = 0;
658 	int save_errno;
659 	char *p;
660 	char *colon;
661 	char *at;
662 	struct hostent *hp = NULL;
663 	SOCKADDR addr;
664 
665 	if (m->mf_conn == NULL || m->mf_conn[0] == '\0')
666 	{
667 		if (tTd(64, 5))
668 			sm_dprintf("X%s: empty or missing socket information\n",
669 				   m->mf_name);
670 		if (parseonly)
671 			syserr("X%s: empty or missing socket information",
672 			       m->mf_name);
673 		else if (MilterLogLevel > 0)
674 			sm_syslog(LOG_ERR, e->e_id,
675 				  "Milter (%s): empty or missing socket information",
676 				  m->mf_name);
677 		milter_error(m, e);
678 		return -1;
679 	}
680 
681 	/* protocol:filename or protocol:port@host */
682 	memset(&addr, '\0', sizeof(addr));
683 	p = m->mf_conn;
684 	colon = strchr(p, ':');
685 	if (colon != NULL)
686 	{
687 		*colon = '\0';
688 
689 		if (*p == '\0')
690 		{
691 # if NETUNIX
692 			/* default to AF_UNIX */
693 			addr.sa.sa_family = AF_UNIX;
694 # else /* NETUNIX */
695 #  if NETINET
696 			/* default to AF_INET */
697 			addr.sa.sa_family = AF_INET;
698 #  else /* NETINET */
699 #   if NETINET6
700 			/* default to AF_INET6 */
701 			addr.sa.sa_family = AF_INET6;
702 #   else /* NETINET6 */
703 			/* no protocols available */
704 			if (MilterLogLevel > 0)
705 				sm_syslog(LOG_ERR, e->e_id,
706 					  "Milter (%s): no valid socket protocols available",
707 					  m->mf_name);
708 			milter_error(m, e);
709 			return -1;
710 #   endif /* NETINET6 */
711 #  endif /* NETINET */
712 # endif /* NETUNIX */
713 		}
714 # if NETUNIX
715 		else if (sm_strcasecmp(p, "unix") == 0 ||
716 			 sm_strcasecmp(p, "local") == 0)
717 			addr.sa.sa_family = AF_UNIX;
718 # endif /* NETUNIX */
719 # if NETINET
720 		else if (sm_strcasecmp(p, "inet") == 0)
721 			addr.sa.sa_family = AF_INET;
722 # endif /* NETINET */
723 # if NETINET6
724 		else if (sm_strcasecmp(p, "inet6") == 0)
725 			addr.sa.sa_family = AF_INET6;
726 # endif /* NETINET6 */
727 		else
728 		{
729 # ifdef EPROTONOSUPPORT
730 			errno = EPROTONOSUPPORT;
731 # else /* EPROTONOSUPPORT */
732 			errno = EINVAL;
733 # endif /* EPROTONOSUPPORT */
734 			if (tTd(64, 5))
735 				sm_dprintf("X%s: unknown socket type %s\n",
736 					m->mf_name, p);
737 			if (parseonly)
738 				syserr("X%s: unknown socket type %s",
739 				       m->mf_name, p);
740 			else if (MilterLogLevel > 0)
741 				sm_syslog(LOG_ERR, e->e_id,
742 					  "Milter (%s): unknown socket type %s",
743 					  m->mf_name, p);
744 			milter_error(m, e);
745 			return -1;
746 		}
747 		*colon++ = ':';
748 	}
749 	else
750 	{
751 		/* default to AF_UNIX */
752 		addr.sa.sa_family = AF_UNIX;
753 		colon = p;
754 	}
755 
756 # if NETUNIX
757 	if (addr.sa.sa_family == AF_UNIX)
758 	{
759 		long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_EXECOK;
760 
761 		at = colon;
762 		if (strlen(colon) >= sizeof(addr.sunix.sun_path))
763 		{
764 			if (tTd(64, 5))
765 				sm_dprintf("X%s: local socket name %s too long\n",
766 					m->mf_name, colon);
767 			errno = EINVAL;
768 			if (parseonly)
769 				syserr("X%s: local socket name %s too long",
770 				       m->mf_name, colon);
771 			else if (MilterLogLevel > 0)
772 				sm_syslog(LOG_ERR, e->e_id,
773 					  "Milter (%s): local socket name %s too long",
774 					  m->mf_name, colon);
775 			milter_error(m, e);
776 			return -1;
777 		}
778 		errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff,
779 				 S_IRUSR|S_IWUSR, NULL);
780 
781 		/* if just parsing .cf file, socket doesn't need to exist */
782 		if (parseonly && errno == ENOENT)
783 		{
784 			if (OpMode == MD_DAEMON ||
785 			    OpMode == MD_FGDAEMON)
786 				(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
787 						     "WARNING: X%s: local socket name %s missing\n",
788 						     m->mf_name, colon);
789 		}
790 		else if (errno != 0)
791 		{
792 			/* if not safe, don't create */
793 			save_errno = errno;
794 			if (tTd(64, 5))
795 				sm_dprintf("X%s: local socket name %s unsafe\n",
796 					m->mf_name, colon);
797 			errno = save_errno;
798 			if (parseonly)
799 			{
800 				if (OpMode == MD_DAEMON ||
801 				    OpMode == MD_FGDAEMON ||
802 				    OpMode == MD_SMTP)
803 					syserr("X%s: local socket name %s unsafe",
804 					       m->mf_name, colon);
805 			}
806 			else if (MilterLogLevel > 0)
807 				sm_syslog(LOG_ERR, e->e_id,
808 					  "Milter (%s): local socket name %s unsafe",
809 					  m->mf_name, colon);
810 			milter_error(m, e);
811 			return -1;
812 		}
813 
814 		(void) sm_strlcpy(addr.sunix.sun_path, colon,
815 			       sizeof(addr.sunix.sun_path));
816 		addrlen = sizeof(struct sockaddr_un);
817 	}
818 	else
819 # endif /* NETUNIX */
820 # if NETINET || NETINET6
821 	if (false
822 #  if NETINET
823 		 || addr.sa.sa_family == AF_INET
824 #  endif /* NETINET */
825 #  if NETINET6
826 		 || addr.sa.sa_family == AF_INET6
827 #  endif /* NETINET6 */
828 		 )
829 	{
830 		unsigned short port;
831 
832 		/* Parse port@host */
833 		at = strchr(colon, '@');
834 		if (at == NULL)
835 		{
836 			if (tTd(64, 5))
837 				sm_dprintf("X%s: bad address %s (expected port@host)\n",
838 					m->mf_name, colon);
839 			if (parseonly)
840 				syserr("X%s: bad address %s (expected port@host)",
841 				       m->mf_name, colon);
842 			else if (MilterLogLevel > 0)
843 				sm_syslog(LOG_ERR, e->e_id,
844 					  "Milter (%s): bad address %s (expected port@host)",
845 					  m->mf_name, colon);
846 			milter_error(m, e);
847 			return -1;
848 		}
849 		*at = '\0';
850 		if (isascii(*colon) && isdigit(*colon))
851 			port = htons((unsigned short) atoi(colon));
852 		else
853 		{
854 #  ifdef NO_GETSERVBYNAME
855 			if (tTd(64, 5))
856 				sm_dprintf("X%s: invalid port number %s\n",
857 					m->mf_name, colon);
858 			if (parseonly)
859 				syserr("X%s: invalid port number %s",
860 				       m->mf_name, colon);
861 			else if (MilterLogLevel > 0)
862 				sm_syslog(LOG_ERR, e->e_id,
863 					  "Milter (%s): invalid port number %s",
864 					  m->mf_name, colon);
865 			milter_error(m, e);
866 			return -1;
867 #  else /* NO_GETSERVBYNAME */
868 			struct servent *sp;
869 
870 			sp = getservbyname(colon, "tcp");
871 			if (sp == NULL)
872 			{
873 				save_errno = errno;
874 				if (tTd(64, 5))
875 					sm_dprintf("X%s: unknown port name %s\n",
876 						m->mf_name, colon);
877 				errno = save_errno;
878 				if (parseonly)
879 					syserr("X%s: unknown port name %s",
880 					       m->mf_name, colon);
881 				else if (MilterLogLevel > 0)
882 					sm_syslog(LOG_ERR, e->e_id,
883 						  "Milter (%s): unknown port name %s",
884 						  m->mf_name, colon);
885 				milter_error(m, e);
886 				return -1;
887 			}
888 			port = sp->s_port;
889 #  endif /* NO_GETSERVBYNAME */
890 		}
891 		*at++ = '@';
892 		if (*at == '[')
893 		{
894 			char *end;
895 
896 			end = strchr(at, ']');
897 			if (end != NULL)
898 			{
899 				bool found = false;
900 #  if NETINET
901 				unsigned long hid = INADDR_NONE;
902 #  endif /* NETINET */
903 #  if NETINET6
904 				struct sockaddr_in6 hid6;
905 #  endif /* NETINET6 */
906 
907 				*end = '\0';
908 #  if NETINET
909 				if (addr.sa.sa_family == AF_INET &&
910 				    (hid = inet_addr(&at[1])) != INADDR_NONE)
911 				{
912 					addr.sin.sin_addr.s_addr = hid;
913 					addr.sin.sin_port = port;
914 					found = true;
915 				}
916 #  endif /* NETINET */
917 #  if NETINET6
918 				(void) memset(&hid6, '\0', sizeof(hid6));
919 				if (addr.sa.sa_family == AF_INET6 &&
920 				    anynet_pton(AF_INET6, &at[1],
921 						&hid6.sin6_addr) == 1)
922 				{
923 					addr.sin6.sin6_addr = hid6.sin6_addr;
924 					addr.sin6.sin6_port = port;
925 					found = true;
926 				}
927 #  endif /* NETINET6 */
928 				*end = ']';
929 				if (!found)
930 				{
931 					if (tTd(64, 5))
932 						sm_dprintf("X%s: Invalid numeric domain spec \"%s\"\n",
933 							m->mf_name, at);
934 					if (parseonly)
935 						syserr("X%s: Invalid numeric domain spec \"%s\"",
936 						       m->mf_name, at);
937 					else if (MilterLogLevel > 0)
938 						sm_syslog(LOG_ERR, e->e_id,
939 							  "Milter (%s): Invalid numeric domain spec \"%s\"",
940 							  m->mf_name, at);
941 					milter_error(m, e);
942 					return -1;
943 				}
944 			}
945 			else
946 			{
947 				if (tTd(64, 5))
948 					sm_dprintf("X%s: Invalid numeric domain spec \"%s\"\n",
949 						m->mf_name, at);
950 				if (parseonly)
951 					syserr("X%s: Invalid numeric domain spec \"%s\"",
952 					       m->mf_name, at);
953 				else if (MilterLogLevel > 0)
954 					sm_syslog(LOG_ERR, e->e_id,
955 						  "Milter (%s): Invalid numeric domain spec \"%s\"",
956 						  m->mf_name, at);
957 				milter_error(m, e);
958 				return -1;
959 			}
960 		}
961 		else
962 		{
963 			hp = sm_gethostbyname(at, addr.sa.sa_family);
964 			if (hp == NULL)
965 			{
966 				save_errno = errno;
967 				if (tTd(64, 5))
968 					sm_dprintf("X%s: Unknown host name %s\n",
969 						   m->mf_name, at);
970 				errno = save_errno;
971 				if (parseonly)
972 					syserr("X%s: Unknown host name %s",
973 					       m->mf_name, at);
974 				else if (MilterLogLevel > 0)
975 					sm_syslog(LOG_ERR, e->e_id,
976 						  "Milter (%s): Unknown host name %s",
977 						  m->mf_name, at);
978 				milter_error(m, e);
979 				return -1;
980 			}
981 			addr.sa.sa_family = hp->h_addrtype;
982 			switch (hp->h_addrtype)
983 			{
984 #  if NETINET
985 			  case AF_INET:
986 				memmove(&addr.sin.sin_addr,
987 					hp->h_addr, INADDRSZ);
988 				addr.sin.sin_port = port;
989 				addrlen = sizeof(struct sockaddr_in);
990 				addrno = 1;
991 				break;
992 #  endif /* NETINET */
993 
994 #  if NETINET6
995 			  case AF_INET6:
996 				memmove(&addr.sin6.sin6_addr,
997 					hp->h_addr, IN6ADDRSZ);
998 				addr.sin6.sin6_port = port;
999 				addrlen = sizeof(struct sockaddr_in6);
1000 				addrno = 1;
1001 				break;
1002 #  endif /* NETINET6 */
1003 
1004 			  default:
1005 				if (tTd(64, 5))
1006 					sm_dprintf("X%s: Unknown protocol for %s (%d)\n",
1007 						   m->mf_name, at,
1008 						   hp->h_addrtype);
1009 				if (parseonly)
1010 					syserr("X%s: Unknown protocol for %s (%d)",
1011 					       m->mf_name, at, hp->h_addrtype);
1012 				else if (MilterLogLevel > 0)
1013 					sm_syslog(LOG_ERR, e->e_id,
1014 						  "Milter (%s): Unknown protocol for %s (%d)",
1015 						  m->mf_name, at,
1016 						  hp->h_addrtype);
1017 				milter_error(m, e);
1018 #  if NETINET6
1019 				freehostent(hp);
1020 #  endif /* NETINET6 */
1021 				return -1;
1022 			}
1023 		}
1024 	}
1025 	else
1026 # endif /* NETINET || NETINET6 */
1027 	{
1028 		if (tTd(64, 5))
1029 			sm_dprintf("X%s: unknown socket protocol\n",
1030 				   m->mf_name);
1031 		if (parseonly)
1032 			syserr("X%s: unknown socket protocol", m->mf_name);
1033 		else if (MilterLogLevel > 0)
1034 			sm_syslog(LOG_ERR, e->e_id,
1035 				  "Milter (%s): unknown socket protocol",
1036 				  m->mf_name);
1037 		milter_error(m, e);
1038 		return -1;
1039 	}
1040 
1041 	/* just parsing through? */
1042 	if (parseonly)
1043 	{
1044 		m->mf_state = SMFS_READY;
1045 # if NETINET6
1046 		if (hp != NULL)
1047 			freehostent(hp);
1048 # endif /* NETINET6 */
1049 		return 0;
1050 	}
1051 
1052 	/* sanity check */
1053 	if (m->mf_state != SMFS_READY &&
1054 	    m->mf_state != SMFS_CLOSED)
1055 	{
1056 		/* shouldn't happen */
1057 		if (tTd(64, 1))
1058 			sm_dprintf("Milter (%s): Trying to open filter in state %c\n",
1059 				   m->mf_name, (char) m->mf_state);
1060 		milter_error(m, e);
1061 # if NETINET6
1062 		if (hp != NULL)
1063 			freehostent(hp);
1064 # endif /* NETINET6 */
1065 		return -1;
1066 	}
1067 
1068 	/* nope, actually connecting */
1069 	for (;;)
1070 	{
1071 		sock = socket(addr.sa.sa_family, SOCK_STREAM, 0);
1072 		if (sock < 0)
1073 		{
1074 			save_errno = errno;
1075 			if (tTd(64, 5))
1076 				sm_dprintf("Milter (%s): error creating socket: %s\n",
1077 					   m->mf_name,
1078 					   sm_errstring(save_errno));
1079 			if (MilterLogLevel > 0)
1080 				sm_syslog(LOG_ERR, e->e_id,
1081 					  "Milter (%s): error creating socket: %s",
1082 					  m->mf_name, sm_errstring(save_errno));
1083 			milter_error(m, e);
1084 # if NETINET6
1085 			if (hp != NULL)
1086 				freehostent(hp);
1087 # endif /* NETINET6 */
1088 			return -1;
1089 		}
1090 
1091 		if (setjmp(MilterConnectTimeout) == 0)
1092 		{
1093 			SM_EVENT *ev = NULL;
1094 			int i;
1095 
1096 			if (m->mf_timeout[SMFTO_CONNECT] > 0)
1097 				ev = sm_setevent(m->mf_timeout[SMFTO_CONNECT],
1098 						 milter_connect_timeout, 0);
1099 
1100 			i = connect(sock, (struct sockaddr *) &addr, addrlen);
1101 			save_errno = errno;
1102 			if (ev != NULL)
1103 				sm_clrevent(ev);
1104 			errno = save_errno;
1105 			if (i >= 0)
1106 				break;
1107 		}
1108 
1109 		/* couldn't connect.... try next address */
1110 		save_errno = errno;
1111 		p = CurHostName;
1112 		CurHostName = at;
1113 		if (tTd(64, 5))
1114 			sm_dprintf("milter_open (%s): open %s failed: %s\n",
1115 				   m->mf_name, at, sm_errstring(save_errno));
1116 		if (MilterLogLevel > 13)
1117 			sm_syslog(LOG_INFO, e->e_id,
1118 				  "Milter (%s): open %s failed: %s",
1119 				  m->mf_name, at, sm_errstring(save_errno));
1120 		CurHostName = p;
1121 		(void) close(sock);
1122 
1123 		/* try next address */
1124 		if (hp != NULL && hp->h_addr_list[addrno] != NULL)
1125 		{
1126 			switch (addr.sa.sa_family)
1127 			{
1128 # if NETINET
1129 			  case AF_INET:
1130 				memmove(&addr.sin.sin_addr,
1131 					hp->h_addr_list[addrno++],
1132 					INADDRSZ);
1133 				break;
1134 # endif /* NETINET */
1135 
1136 # if NETINET6
1137 			  case AF_INET6:
1138 				memmove(&addr.sin6.sin6_addr,
1139 					hp->h_addr_list[addrno++],
1140 					IN6ADDRSZ);
1141 				break;
1142 # endif /* NETINET6 */
1143 
1144 			  default:
1145 				if (tTd(64, 5))
1146 					sm_dprintf("X%s: Unknown protocol for %s (%d)\n",
1147 						   m->mf_name, at,
1148 						   hp->h_addrtype);
1149 				if (MilterLogLevel > 0)
1150 					sm_syslog(LOG_ERR, e->e_id,
1151 						  "Milter (%s): Unknown protocol for %s (%d)",
1152 						  m->mf_name, at,
1153 						  hp->h_addrtype);
1154 				milter_error(m, e);
1155 # if NETINET6
1156 				freehostent(hp);
1157 # endif /* NETINET6 */
1158 				return -1;
1159 			}
1160 			continue;
1161 		}
1162 		p = CurHostName;
1163 		CurHostName = at;
1164 		if (tTd(64, 5))
1165 			sm_dprintf("X%s: error connecting to filter: %s\n",
1166 				   m->mf_name, sm_errstring(save_errno));
1167 		if (MilterLogLevel > 0)
1168 			sm_syslog(LOG_ERR, e->e_id,
1169 				  "Milter (%s): error connecting to filter: %s",
1170 				  m->mf_name, sm_errstring(save_errno));
1171 		CurHostName = p;
1172 		milter_error(m, e);
1173 # if NETINET6
1174 		if (hp != NULL)
1175 			freehostent(hp);
1176 # endif /* NETINET6 */
1177 		return -1;
1178 	}
1179 	m->mf_state = SMFS_OPEN;
1180 # if NETINET6
1181 	if (hp != NULL)
1182 	{
1183 		freehostent(hp);
1184 		hp = NULL;
1185 	}
1186 # endif /* NETINET6 */
1187 # if MILTER_NO_NAGLE && !defined(TCP_CORK)
1188 	{
1189 		int nodelay = 1;
1190 
1191 		setsockopt(m->mf_sock, IPPROTO_TCP, TCP_NODELAY,
1192 			   (char *)&nodelay, sizeof(nodelay));
1193 	}
1194 # endif /* MILTER_NO_NAGLE && !defined(TCP_CORK) */
1195 	return sock;
1196 }
1197 
1198 static void
milter_connect_timeout(ignore)1199 milter_connect_timeout(ignore)
1200 	int ignore;
1201 {
1202 	/*
1203 	**  NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
1204 	**	ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
1205 	**	DOING.
1206 	*/
1207 
1208 	errno = ETIMEDOUT;
1209 	longjmp(MilterConnectTimeout, 1);
1210 }
1211 
1212 /*
1213 **  MILTER_SETUP -- setup structure for a mail filter
1214 **
1215 **	Parameters:
1216 **		line -- the options line.
1217 **
1218 **	Returns:
1219 **		none
1220 */
1221 
1222 void
milter_setup(line)1223 milter_setup(line)
1224 	char *line;
1225 {
1226 	char fcode;
1227 	char *p;
1228 	struct milter *m;
1229 	STAB *s;
1230 	static int idx = 0;
1231 
1232 	/* collect the filter name */
1233 	for (p = line;
1234 	     *p != '\0' && *p != ',' && !(isascii(*p) && isspace(*p));
1235 	     p++)
1236 		continue;
1237 	if (*p != '\0')
1238 		*p++ = '\0';
1239 	if (line[0] == '\0')
1240 	{
1241 		syserr("name required for mail filter");
1242 		return;
1243 	}
1244 	m = (struct milter *) xalloc(sizeof(*m));
1245 	memset((char *) m, '\0', sizeof(*m));
1246 	m->mf_name = newstr(line);
1247 	m->mf_state = SMFS_READY;
1248 	m->mf_sock = -1;
1249 	m->mf_timeout[SMFTO_CONNECT] = (time_t) 300;
1250 	m->mf_timeout[SMFTO_WRITE] = (time_t) 10;
1251 	m->mf_timeout[SMFTO_READ] = (time_t) 10;
1252 	m->mf_timeout[SMFTO_EOM] = (time_t) 300;
1253 #if _FFR_MILTER_CHECK
1254 	m->mf_mta_prot_version = SMFI_PROT_VERSION;
1255 	m->mf_mta_prot_flags = SMFI_CURR_PROT;
1256 	m->mf_mta_actions = SMFI_CURR_ACTS;
1257 #endif /* _FFR_MILTER_CHECK */
1258 
1259 	/* now scan through and assign info from the fields */
1260 	while (*p != '\0')
1261 	{
1262 		char *delimptr;
1263 
1264 		while (*p != '\0' &&
1265 		       (*p == ',' || (isascii(*p) && isspace(*p))))
1266 			p++;
1267 
1268 		/* p now points to field code */
1269 		fcode = *p;
1270 		while (*p != '\0' && *p != '=' && *p != ',')
1271 			p++;
1272 		if (*p++ != '=')
1273 		{
1274 			syserr("X%s: `=' expected", m->mf_name);
1275 			return;
1276 		}
1277 		while (isascii(*p) && isspace(*p))
1278 			p++;
1279 
1280 		/* p now points to the field body */
1281 		p = munchstring(p, &delimptr, ',');
1282 
1283 		/* install the field into the filter struct */
1284 		switch (fcode)
1285 		{
1286 		  case 'S':		/* socket */
1287 			if (p == NULL)
1288 				m->mf_conn = NULL;
1289 			else
1290 				m->mf_conn = newstr(p);
1291 			break;
1292 
1293 		  case 'F':		/* Milter flags configured on MTA */
1294 			for (; *p != '\0'; p++)
1295 			{
1296 				if (!(isascii(*p) && isspace(*p)))
1297 					setbitn(bitidx(*p), m->mf_flags);
1298 			}
1299 			break;
1300 
1301 		  case 'T':		/* timeouts */
1302 			milter_parse_timeouts(p, m);
1303 			break;
1304 
1305 #if _FFR_MILTER_CHECK
1306 		  case 'a':
1307 			m->mf_mta_actions = strtoul(p, NULL, 0);
1308 			break;
1309 		  case 'f':
1310 			m->mf_mta_prot_flags = strtoul(p, NULL, 0);
1311 			break;
1312 		  case 'v':
1313 			m->mf_mta_prot_version = strtoul(p, NULL, 0);
1314 			break;
1315 #endif /* _FFR_MILTER_CHECK */
1316 
1317 		  default:
1318 			syserr("X%s: unknown filter equate %c=",
1319 			       m->mf_name, fcode);
1320 			break;
1321 		}
1322 		p = delimptr;
1323 	}
1324 
1325 	/* early check for errors */
1326 	(void) milter_open(m, true, CurEnv);
1327 
1328 	/* enter the filter into the symbol table */
1329 	s = stab(m->mf_name, ST_MILTER, ST_ENTER);
1330 	if (s->s_milter != NULL)
1331 		syserr("X%s: duplicate filter definition", m->mf_name);
1332 	else
1333 	{
1334 		s->s_milter = m;
1335 		m->mf_idx = ++idx;
1336 	}
1337 }
1338 
1339 /*
1340 **  MILTER_CONFIG -- parse option list into an array and check config
1341 **
1342 **	Called when reading configuration file.
1343 **
1344 **	Parameters:
1345 **		spec -- the filter list.
1346 **		list -- the array to fill in.
1347 **		max -- the maximum number of entries in list.
1348 **
1349 **	Returns:
1350 **		none
1351 */
1352 
1353 void
milter_config(spec,list,max)1354 milter_config(spec, list, max)
1355 	char *spec;
1356 	struct milter **list;
1357 	int max;
1358 {
1359 	int numitems = 0;
1360 	char *p;
1361 
1362 	/* leave one for the NULL signifying the end of the list */
1363 	max--;
1364 
1365 	for (p = spec; p != NULL; )
1366 	{
1367 		STAB *s;
1368 
1369 		while (isascii(*p) && isspace(*p))
1370 			p++;
1371 		if (*p == '\0')
1372 			break;
1373 		spec = p;
1374 
1375 		if (numitems >= max)
1376 		{
1377 			syserr("Too many filters defined, %d max", max);
1378 			if (max > 0)
1379 				list[0] = NULL;
1380 			return;
1381 		}
1382 		p = strpbrk(p, ";,");
1383 		if (p != NULL)
1384 			*p++ = '\0';
1385 
1386 		s = stab(spec, ST_MILTER, ST_FIND);
1387 		if (s == NULL)
1388 		{
1389 			syserr("InputFilter %s not defined", spec);
1390 			ExitStat = EX_CONFIG;
1391 			return;
1392 		}
1393 		list[numitems++] = s->s_milter;
1394 	}
1395 	list[numitems] = NULL;
1396 
1397 	/* if not set, set to LogLevel */
1398 	if (MilterLogLevel == -1)
1399 		MilterLogLevel = LogLevel;
1400 }
1401 
1402 /*
1403 **  MILTER_PARSE_TIMEOUTS -- parse timeout list
1404 **
1405 **	Called when reading configuration file.
1406 **
1407 **	Parameters:
1408 **		spec -- the timeout list.
1409 **		m -- milter to set.
1410 **
1411 **	Returns:
1412 **		none
1413 */
1414 
1415 static void
milter_parse_timeouts(spec,m)1416 milter_parse_timeouts(spec, m)
1417 	char *spec;
1418 	struct milter *m;
1419 {
1420 	char fcode;
1421 	int tcode;
1422 	char *p;
1423 
1424 	p = spec;
1425 
1426 	/* now scan through and assign info from the fields */
1427 	while (*p != '\0')
1428 	{
1429 		char *delimptr;
1430 
1431 		while (*p != '\0' &&
1432 		       (*p == ';' || (isascii(*p) && isspace(*p))))
1433 			p++;
1434 
1435 		/* p now points to field code */
1436 		fcode = *p;
1437 		while (*p != '\0' && *p != ':')
1438 			p++;
1439 		if (*p++ != ':')
1440 		{
1441 			syserr("X%s, T=: `:' expected", m->mf_name);
1442 			return;
1443 		}
1444 		while (isascii(*p) && isspace(*p))
1445 			p++;
1446 
1447 		/* p now points to the field body */
1448 		p = munchstring(p, &delimptr, ';');
1449 		tcode = -1;
1450 
1451 		/* install the field into the filter struct */
1452 		switch (fcode)
1453 		{
1454 		  case 'C':
1455 			tcode = SMFTO_CONNECT;
1456 			break;
1457 
1458 		  case 'S':
1459 			tcode = SMFTO_WRITE;
1460 			break;
1461 
1462 		  case 'R':
1463 			tcode = SMFTO_READ;
1464 			break;
1465 
1466 		  case 'E':
1467 			tcode = SMFTO_EOM;
1468 			break;
1469 
1470 		  default:
1471 			if (tTd(64, 5))
1472 				sm_dprintf("X%s: %c unknown\n",
1473 					   m->mf_name, fcode);
1474 			syserr("X%s: unknown filter timeout %c",
1475 			       m->mf_name, fcode);
1476 			break;
1477 		}
1478 		if (tcode >= 0)
1479 		{
1480 			m->mf_timeout[tcode] = convtime(p, 's');
1481 			if (tTd(64, 5))
1482 				sm_dprintf("X%s: %c=%ld\n",
1483 					   m->mf_name, fcode,
1484 					   (u_long) m->mf_timeout[tcode]);
1485 		}
1486 		p = delimptr;
1487 	}
1488 }
1489 
1490 /*
1491 **  MILTER_SET_MACROS -- set milter macros
1492 **
1493 **	Parameters:
1494 **		name -- name of milter.
1495 **		macros -- where to store macros.
1496 **		val -- the value of the option.
1497 **		nummac -- current number of macros
1498 **
1499 **	Returns:
1500 **		new number of macros
1501 */
1502 
1503 static int
milter_set_macros(name,macros,val,nummac)1504 milter_set_macros(name, macros, val, nummac)
1505 	char *name;
1506 	char **macros;
1507 	char *val;
1508 	int nummac;
1509 {
1510 	char *p;
1511 
1512 	p = newstr(val);
1513 	while (*p != '\0')
1514 	{
1515 		char *macro;
1516 
1517 		/* Skip leading commas, spaces */
1518 		while (*p != '\0' &&
1519 		       (*p == ',' || (isascii(*p) && isspace(*p))))
1520 			p++;
1521 
1522 		if (*p == '\0')
1523 			break;
1524 
1525 		/* Find end of macro */
1526 		macro = p;
1527 		while (*p != '\0' && *p != ',' &&
1528 		       isascii(*p) && !isspace(*p))
1529 			p++;
1530 		if (*p != '\0')
1531 			*p++ = '\0';
1532 
1533 		if (nummac >= MAXFILTERMACROS)
1534 		{
1535 			syserr("milter_set_option: too many macros in Milter.%s (max %d)",
1536 			       name, MAXFILTERMACROS);
1537 			macros[nummac] = NULL;
1538 			return -1;
1539 		}
1540 		macros[nummac++] = macro;
1541 	}
1542 	macros[nummac] = NULL;
1543 	return nummac;
1544 }
1545 
1546 /*
1547 **  MILTER_SET_OPTION -- set an individual milter option
1548 **
1549 **	Parameters:
1550 **		name -- the name of the option.
1551 **		val -- the value of the option.
1552 **		sticky -- if set, don't let other setoptions override
1553 **			this value.
1554 **
1555 **	Returns:
1556 **		none.
1557 */
1558 
1559 /* set if Milter sub-option is stuck */
1560 static BITMAP256	StickyMilterOpt;
1561 
1562 static struct milteropt
1563 {
1564 	char		*mo_name;	/* long name of milter option */
1565 	unsigned char	mo_code;	/* code for option */
1566 } MilterOptTab[] =
1567 {
1568 	{ "macros.connect",		SMFIM_CONNECT			},
1569 	{ "macros.helo",		SMFIM_HELO			},
1570 	{ "macros.envfrom",		SMFIM_ENVFROM			},
1571 	{ "macros.envrcpt",		SMFIM_ENVRCPT			},
1572 	{ "macros.data",		SMFIM_DATA			},
1573 	{ "macros.eom",			SMFIM_EOM			},
1574 	{ "macros.eoh",			SMFIM_EOH			},
1575 
1576 # define MO_LOGLEVEL			0x07
1577 	{ "loglevel",			MO_LOGLEVEL			},
1578 # if _FFR_MAXDATASIZE || _FFR_MDS_NEGOTIATE
1579 #  define MO_MAXDATASIZE		0x08
1580 	{ "maxdatasize",		MO_MAXDATASIZE			},
1581 # endif /* _FFR_MAXDATASIZE || _FFR_MDS_NEGOTIATE */
1582 	{ NULL,				(unsigned char)-1		},
1583 };
1584 
1585 void
milter_set_option(name,val,sticky)1586 milter_set_option(name, val, sticky)
1587 	char *name;
1588 	char *val;
1589 	bool sticky;
1590 {
1591 	int nummac, r;
1592 	struct milteropt *mo;
1593 	char **macros = NULL;
1594 
1595 	nummac = 0;
1596 	if (tTd(37, 2) || tTd(64, 5))
1597 		sm_dprintf("milter_set_option(%s = %s)", name, val);
1598 
1599 	if (name == NULL)
1600 	{
1601 		syserr("milter_set_option: invalid Milter option, must specify suboption");
1602 		return;
1603 	}
1604 
1605 	for (mo = MilterOptTab; mo->mo_name != NULL; mo++)
1606 	{
1607 		if (sm_strcasecmp(mo->mo_name, name) == 0)
1608 			break;
1609 	}
1610 
1611 	if (mo->mo_name == NULL)
1612 	{
1613 		syserr("milter_set_option: invalid Milter option %s", name);
1614 		return;
1615 	}
1616 
1617 	/*
1618 	**  See if this option is preset for us.
1619 	*/
1620 
1621 	if (!sticky && bitnset(mo->mo_code, StickyMilterOpt))
1622 	{
1623 		if (tTd(37, 2) || tTd(64,5))
1624 			sm_dprintf(" (ignored)\n");
1625 		return;
1626 	}
1627 
1628 	if (tTd(37, 2) || tTd(64,5))
1629 		sm_dprintf("\n");
1630 
1631 	switch (mo->mo_code)
1632 	{
1633 	  case MO_LOGLEVEL:
1634 		MilterLogLevel = atoi(val);
1635 		break;
1636 
1637 # if _FFR_MAXDATASIZE || _FFR_MDS_NEGOTIATE
1638 	  case MO_MAXDATASIZE:
1639 #  if _FFR_MDS_NEGOTIATE
1640 		MilterMaxDataSize = (size_t)atol(val);
1641 		if (MilterMaxDataSize != MILTER_MDS_64K &&
1642 		    MilterMaxDataSize != MILTER_MDS_256K &&
1643 		    MilterMaxDataSize != MILTER_MDS_1M)
1644 		{
1645 			sm_syslog(LOG_WARNING, NOQID,
1646 				"WARNING: Milter.%s=%d, allowed are only %d, %d, and %d",
1647 				name, MilterMaxDataSize,
1648 				MILTER_MDS_64K, MILTER_MDS_256K,
1649 				MILTER_MDS_1M);
1650 			if (MilterMaxDataSize < MILTER_MDS_64K)
1651 				MilterMaxDataSize = MILTER_MDS_64K;
1652 			else if (MilterMaxDataSize < MILTER_MDS_256K)
1653 				MilterMaxDataSize = MILTER_MDS_256K;
1654 			else
1655 				MilterMaxDataSize = MILTER_MDS_1M;
1656 		}
1657 #  endif /* _FFR_MDS_NEGOTIATE */
1658 		break;
1659 # endif /* _FFR_MAXDATASIZE || _FFR_MDS_NEGOTIATE */
1660 
1661 	  case SMFIM_CONNECT:
1662 	  case SMFIM_HELO:
1663 	  case SMFIM_ENVFROM:
1664 	  case SMFIM_ENVRCPT:
1665 	  case SMFIM_EOH:
1666 	  case SMFIM_EOM:
1667 	  case SMFIM_DATA:
1668 		macros = MilterMacros[mo->mo_code][0];
1669 
1670 		r = milter_set_macros(name, macros, val, nummac);
1671 		if (r >= 0)
1672 			nummac = r;
1673 		break;
1674 
1675 	  default:
1676 		syserr("milter_set_option: invalid Milter option %s", name);
1677 		break;
1678 	}
1679 	if (sticky)
1680 		setbitn(mo->mo_code, StickyMilterOpt);
1681 }
1682 
1683 /*
1684 **  MILTER_REOPEN_DF -- open & truncate the data file (for replbody)
1685 **
1686 **	Parameters:
1687 **		e -- current envelope.
1688 **
1689 **	Returns:
1690 **		0 if succesful, -1 otherwise
1691 */
1692 
1693 static int
milter_reopen_df(e)1694 milter_reopen_df(e)
1695 	ENVELOPE *e;
1696 {
1697 	char dfname[MAXPATHLEN];
1698 
1699 	(void) sm_strlcpy(dfname, queuename(e, DATAFL_LETTER), sizeof(dfname));
1700 
1701 	/*
1702 	**  In SuperSafe == SAFE_REALLY mode, e->e_dfp is a read-only FP so
1703 	**  close and reopen writable (later close and reopen
1704 	**  read only again).
1705 	**
1706 	**  In SuperSafe != SAFE_REALLY mode, e->e_dfp still points at the
1707 	**  buffered file I/O descriptor, still open for writing so there
1708 	**  isn't any work to do here (except checking for consistency).
1709 	*/
1710 
1711 	if (SuperSafe == SAFE_REALLY)
1712 	{
1713 		/* close read-only data file */
1714 		if (bitset(EF_HAS_DF, e->e_flags) && e->e_dfp != NULL)
1715 		{
1716 			(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
1717 			e->e_flags &= ~EF_HAS_DF;
1718 		}
1719 
1720 		/* open writable */
1721 		if ((e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, dfname,
1722 					   SM_IO_RDWR_B, NULL)) == NULL)
1723 		{
1724 			MILTER_DF_ERROR("milter_reopen_df: sm_io_open %s: %s");
1725 			return -1;
1726 		}
1727 	}
1728 	else if (e->e_dfp == NULL)
1729 	{
1730 		/* shouldn't happen */
1731 		errno = ENOENT;
1732 		MILTER_DF_ERROR("milter_reopen_df: NULL e_dfp (%s: %s)");
1733 		return -1;
1734 	}
1735 	return 0;
1736 }
1737 
1738 /*
1739 **  MILTER_RESET_DF -- re-open read-only the data file (for replbody)
1740 **
1741 **	Parameters:
1742 **		e -- current envelope.
1743 **
1744 **	Returns:
1745 **		0 if succesful, -1 otherwise
1746 */
1747 
1748 static int
milter_reset_df(e)1749 milter_reset_df(e)
1750 	ENVELOPE *e;
1751 {
1752 	int afd;
1753 	char dfname[MAXPATHLEN];
1754 
1755 	(void) sm_strlcpy(dfname, queuename(e, DATAFL_LETTER), sizeof(dfname));
1756 
1757 	if (sm_io_flush(e->e_dfp, SM_TIME_DEFAULT) != 0 ||
1758 	    sm_io_error(e->e_dfp))
1759 	{
1760 		MILTER_DF_ERROR("milter_reset_df: error writing/flushing %s: %s");
1761 		return -1;
1762 	}
1763 	else if (SuperSafe != SAFE_REALLY)
1764 	{
1765 		/* skip next few clauses */
1766 		/* EMPTY */
1767 	}
1768 	else if ((afd = sm_io_getinfo(e->e_dfp, SM_IO_WHAT_FD, NULL)) >= 0
1769 		 && fsync(afd) < 0)
1770 	{
1771 		MILTER_DF_ERROR("milter_reset_df: error sync'ing %s: %s");
1772 		return -1;
1773 	}
1774 	else if (sm_io_close(e->e_dfp, SM_TIME_DEFAULT) < 0)
1775 	{
1776 		MILTER_DF_ERROR("milter_reset_df: error closing %s: %s");
1777 		return -1;
1778 	}
1779 	else if ((e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, dfname,
1780 					SM_IO_RDONLY_B, NULL)) == NULL)
1781 	{
1782 		MILTER_DF_ERROR("milter_reset_df: error reopening %s: %s");
1783 		return -1;
1784 	}
1785 	else
1786 		e->e_flags |= EF_HAS_DF;
1787 	return 0;
1788 }
1789 
1790 /*
1791 **  MILTER_QUIT_FILTER -- close down a single filter
1792 **
1793 **	Parameters:
1794 **		m -- milter structure of filter to close down.
1795 **		e -- current envelope.
1796 **
1797 **	Returns:
1798 **		none
1799 */
1800 
1801 static void
milter_quit_filter(m,e)1802 milter_quit_filter(m, e)
1803 	struct milter *m;
1804 	ENVELOPE *e;
1805 {
1806 	if (tTd(64, 10))
1807 		sm_dprintf("milter_quit_filter(%s)\n", m->mf_name);
1808 	if (MilterLogLevel > 18)
1809 		sm_syslog(LOG_INFO, e->e_id, "Milter (%s): quit filter",
1810 			  m->mf_name);
1811 
1812 	/* Never replace error state */
1813 	if (m->mf_state == SMFS_ERROR)
1814 		return;
1815 
1816 	if (m->mf_sock < 0 ||
1817 	    m->mf_state == SMFS_CLOSED ||
1818 	    m->mf_state == SMFS_READY)
1819 	{
1820 		m->mf_sock = -1;
1821 		m->mf_state = SMFS_CLOSED;
1822 		return;
1823 	}
1824 
1825 	(void) milter_write(m, SMFIC_QUIT, (char *) NULL, 0,
1826 			    m->mf_timeout[SMFTO_WRITE], e, "quit_filter");
1827 	if (m->mf_sock >= 0)
1828 	{
1829 		(void) close(m->mf_sock);
1830 		m->mf_sock = -1;
1831 	}
1832 	if (m->mf_state != SMFS_ERROR)
1833 		m->mf_state = SMFS_CLOSED;
1834 }
1835 
1836 /*
1837 **  MILTER_ABORT_FILTER -- tell filter to abort current message
1838 **
1839 **	Parameters:
1840 **		m -- milter structure of filter to abort.
1841 **		e -- current envelope.
1842 **
1843 **	Returns:
1844 **		none
1845 */
1846 
1847 static void
milter_abort_filter(m,e)1848 milter_abort_filter(m, e)
1849 	struct milter *m;
1850 	ENVELOPE *e;
1851 {
1852 	if (tTd(64, 10))
1853 		sm_dprintf("milter_abort_filter(%s)\n", m->mf_name);
1854 	if (MilterLogLevel > 10)
1855 		sm_syslog(LOG_INFO, e->e_id, "Milter (%s): abort filter",
1856 			  m->mf_name);
1857 
1858 	if (m->mf_sock < 0 ||
1859 	    m->mf_state != SMFS_INMSG)
1860 		return;
1861 
1862 	(void) milter_write(m, SMFIC_ABORT, (char *) NULL, 0,
1863 			    m->mf_timeout[SMFTO_WRITE], e, "abort_filter");
1864 	if (m->mf_state != SMFS_ERROR)
1865 		m->mf_state = SMFS_DONE;
1866 }
1867 
1868 /*
1869 **  MILTER_SEND_MACROS -- provide macros to the filters
1870 **
1871 **	Parameters:
1872 **		m -- milter to send macros to.
1873 **		macros -- macros to send for filter smfi_getsymval().
1874 **		cmd -- which command the macros are associated with.
1875 **		e -- current envelope (for macro access).
1876 **
1877 **	Returns:
1878 **		none
1879 */
1880 
1881 static void
milter_send_macros(m,macros,cmd,e)1882 milter_send_macros(m, macros, cmd, e)
1883 	struct milter *m;
1884 	char **macros;
1885 	int cmd;
1886 	ENVELOPE *e;
1887 {
1888 	int i;
1889 	int mid;
1890 	char command = (char) cmd;
1891 	char *v;
1892 	char *buf, *bp;
1893 	char exp[MAXLINE];
1894 	ssize_t s;
1895 
1896 	/* sanity check */
1897 	if (macros == NULL || macros[0] == NULL)
1898 		return;
1899 
1900 	/* put together data */
1901 	s = 1;			/* for the command character */
1902 	for (i = 0; macros[i] != NULL; i++)
1903 	{
1904 		mid = macid(macros[i]);
1905 		if (mid == 0)
1906 			continue;
1907 		v = macvalue(mid, e);
1908 		if (v == NULL)
1909 			continue;
1910 		expand(v, exp, sizeof(exp), e);
1911 		s += strlen(macros[i]) + 1 + strlen(exp) + 1;
1912 	}
1913 
1914 	if (s < 0)
1915 		return;
1916 
1917 	buf = (char *) xalloc(s);
1918 	bp = buf;
1919 	*bp++ = command;
1920 	for (i = 0; macros[i] != NULL; i++)
1921 	{
1922 		mid = macid(macros[i]);
1923 		if (mid == 0)
1924 			continue;
1925 		v = macvalue(mid, e);
1926 		if (v == NULL)
1927 			continue;
1928 		expand(v, exp, sizeof(exp), e);
1929 
1930 		if (tTd(64, 10))
1931 			sm_dprintf("milter_send_macros(%s, %c): %s=%s\n",
1932 				m->mf_name, command, macros[i], exp);
1933 
1934 		(void) sm_strlcpy(bp, macros[i], s - (bp - buf));
1935 		bp += strlen(bp) + 1;
1936 		(void) sm_strlcpy(bp, exp, s - (bp - buf));
1937 		bp += strlen(bp) + 1;
1938 	}
1939 	(void) milter_write(m, SMFIC_MACRO, buf, s,
1940 			    m->mf_timeout[SMFTO_WRITE], e, "send_macros");
1941 	sm_free(buf);
1942 }
1943 
1944 /*
1945 **  MILTER_SEND_COMMAND -- send a command and return the response for a filter
1946 **
1947 **	Parameters:
1948 **		m -- current milter filter
1949 **		cmd -- command to send.
1950 **		data -- optional command data.
1951 **		sz -- length of buf.
1952 **		e -- current envelope (for e->e_id).
1953 **		state -- return state word.
1954 **
1955 **	Returns:
1956 **		response string (may be NULL)
1957 */
1958 
1959 static char *
milter_send_command(m,cmd,data,sz,e,state,where)1960 milter_send_command(m, cmd, data, sz, e, state, where)
1961 	struct milter *m;
1962 	int cmd;
1963 	void *data;
1964 	ssize_t sz;
1965 	ENVELOPE *e;
1966 	char *state;
1967 	const char *where;
1968 {
1969 	char rcmd;
1970 	ssize_t rlen;
1971 	unsigned long skipflag;
1972 	unsigned long norespflag = 0;
1973 	char command = (char) cmd;
1974 	char *action;
1975 	char *defresponse;
1976 	char *response;
1977 
1978 	if (tTd(64, 10))
1979 		sm_dprintf("milter_send_command(%s): cmd %c len %ld\n",
1980 			m->mf_name, (char) command, (long) sz);
1981 
1982 	/* find skip flag and default failure */
1983 	switch (command)
1984 	{
1985 	  case SMFIC_CONNECT:
1986 		skipflag = SMFIP_NOCONNECT;
1987 		norespflag = SMFIP_NR_CONN;
1988 		action = "connect";
1989 		defresponse = "554 Command rejected";
1990 		break;
1991 
1992 	  case SMFIC_HELO:
1993 		skipflag = SMFIP_NOHELO;
1994 		norespflag = SMFIP_NR_HELO;
1995 		action = "helo";
1996 		defresponse = "550 Command rejected";
1997 		break;
1998 
1999 	  case SMFIC_MAIL:
2000 		skipflag = SMFIP_NOMAIL;
2001 		norespflag = SMFIP_NR_MAIL;
2002 		action = "mail";
2003 		defresponse = "550 5.7.1 Command rejected";
2004 		break;
2005 
2006 	  case SMFIC_RCPT:
2007 		skipflag = SMFIP_NORCPT;
2008 		norespflag = SMFIP_NR_RCPT;
2009 		action = "rcpt";
2010 		defresponse = "550 5.7.1 Command rejected";
2011 		break;
2012 
2013 	  case SMFIC_HEADER:
2014 		skipflag = SMFIP_NOHDRS;
2015 		norespflag = SMFIP_NR_HDR;
2016 		action = "header";
2017 		defresponse = "550 5.7.1 Command rejected";
2018 		break;
2019 
2020 	  case SMFIC_BODY:
2021 		skipflag = SMFIP_NOBODY;
2022 		norespflag = SMFIP_NR_BODY;
2023 		action = "body";
2024 		defresponse = "554 5.7.1 Command rejected";
2025 		break;
2026 
2027 	  case SMFIC_EOH:
2028 		skipflag = SMFIP_NOEOH;
2029 		norespflag = SMFIP_NR_EOH;
2030 		action = "eoh";
2031 		defresponse = "550 5.7.1 Command rejected";
2032 		break;
2033 
2034 	  case SMFIC_UNKNOWN:
2035 		skipflag = SMFIP_NOUNKNOWN;
2036 		norespflag = SMFIP_NR_UNKN;
2037 		action = "unknown";
2038 		defresponse = "550 5.7.1 Command rejected";
2039 		break;
2040 
2041 	  case SMFIC_DATA:
2042 		skipflag = SMFIP_NODATA;
2043 		norespflag = SMFIP_NR_DATA;
2044 		action = "data";
2045 		defresponse = "550 5.7.1 Command rejected";
2046 		break;
2047 
2048 	  case SMFIC_BODYEOB:
2049 	  case SMFIC_OPTNEG:
2050 	  case SMFIC_MACRO:
2051 	  case SMFIC_ABORT:
2052 	  case SMFIC_QUIT:
2053 		/* NOTE: not handled by milter_send_command() */
2054 		/* FALLTHROUGH */
2055 
2056 	  default:
2057 		skipflag = 0;
2058 		action = "default";
2059 		defresponse = "550 5.7.1 Command rejected";
2060 		break;
2061 	}
2062 
2063 	if (tTd(64, 10))
2064 		sm_dprintf("milter_send_command(%s): skip=%lx, pflags=%x\n",
2065 			m->mf_name, skipflag, m->mf_pflags);
2066 
2067 	/* check if filter wants this command */
2068 	if (skipflag != 0 && bitset(skipflag, m->mf_pflags))
2069 		return NULL;
2070 
2071 	/* send the command to the filter */
2072 	(void) milter_write(m, command, data, sz,
2073 			    m->mf_timeout[SMFTO_WRITE], e, where);
2074 	if (m->mf_state == SMFS_ERROR)
2075 	{
2076 		MILTER_CHECK_ERROR(false, return NULL);
2077 		return NULL;
2078 	}
2079 
2080 	/* check if filter sends response to this command */
2081 	if (norespflag != 0 && bitset(norespflag, m->mf_pflags))
2082 		return NULL;
2083 
2084 	/* get the response from the filter */
2085 	response = milter_read(m, &rcmd, &rlen,
2086 			       m->mf_timeout[SMFTO_READ], e, where);
2087 	if (m->mf_state == SMFS_ERROR)
2088 	{
2089 		MILTER_CHECK_ERROR(false, return NULL);
2090 		return NULL;
2091 	}
2092 
2093 	if (tTd(64, 10))
2094 		sm_dprintf("milter_send_command(%s): returned %c\n",
2095 			   m->mf_name, (char) rcmd);
2096 
2097 	switch (rcmd)
2098 	{
2099 	  case SMFIR_REPLYCODE:
2100 		MILTER_CHECK_REPLYCODE(defresponse);
2101 		if (MilterLogLevel > 10)
2102 			sm_syslog(LOG_INFO, e->e_id,
2103 				  "milter=%s, action=%s, reject=%s",
2104 				  m->mf_name, action, response);
2105 		*state = rcmd;
2106 		break;
2107 
2108 	  case SMFIR_REJECT:
2109 		if (MilterLogLevel > 10)
2110 			sm_syslog(LOG_INFO, e->e_id,
2111 				  "milter=%s, action=%s, reject",
2112 				  m->mf_name, action);
2113 		*state = rcmd;
2114 		break;
2115 
2116 	  case SMFIR_DISCARD:
2117 		if (MilterLogLevel > 10)
2118 			sm_syslog(LOG_INFO, e->e_id,
2119 				  "milter=%s, action=%s, discard",
2120 				  m->mf_name, action);
2121 		*state = rcmd;
2122 		break;
2123 
2124 	  case SMFIR_TEMPFAIL:
2125 		if (MilterLogLevel > 10)
2126 			sm_syslog(LOG_INFO, e->e_id,
2127 				  "milter=%s, action=%s, tempfail",
2128 				  m->mf_name, action);
2129 		*state = rcmd;
2130 		break;
2131 
2132 	  case SMFIR_ACCEPT:
2133 		/* this filter is done with message/connection */
2134 		if (command == SMFIC_HELO ||
2135 		    command == SMFIC_CONNECT)
2136 			m->mf_state = SMFS_CLOSABLE;
2137 		else
2138 			m->mf_state = SMFS_DONE;
2139 		if (MilterLogLevel > 10)
2140 			sm_syslog(LOG_INFO, e->e_id,
2141 				  "milter=%s, action=%s, accepted",
2142 				  m->mf_name, action);
2143 		break;
2144 
2145 	  case SMFIR_CONTINUE:
2146 		/* if MAIL command is ok, filter is in message state */
2147 		if (command == SMFIC_MAIL)
2148 			m->mf_state = SMFS_INMSG;
2149 		if (MilterLogLevel > 12)
2150 			sm_syslog(LOG_INFO, e->e_id,
2151 				  "milter=%s, action=%s, continue",
2152 				  m->mf_name, action);
2153 		break;
2154 
2155 	  case SMFIR_SKIP:
2156 		if (MilterLogLevel > 12)
2157 			sm_syslog(LOG_INFO, e->e_id,
2158 				  "milter=%s, action=%s, skip",
2159 				  m->mf_name, action);
2160 		m->mf_state = SMFS_SKIP;
2161 		break;
2162 
2163 	  default:
2164 		/* Invalid response to command */
2165 		if (MilterLogLevel > 0)
2166 			sm_syslog(LOG_ERR, e->e_id,
2167 				  "milter_send_command(%s): action=%s returned bogus response %c",
2168 				  m->mf_name, action, rcmd);
2169 		milter_error(m, e); /* NO ERROR CHECK? */
2170 		break;
2171 	}
2172 
2173 	if (*state != SMFIR_REPLYCODE && response != NULL)
2174 	{
2175 		sm_free(response); /* XXX */
2176 		response = NULL;
2177 	}
2178 	return response;
2179 }
2180 
2181 /*
2182 **  MILTER_COMMAND -- send a command and return the response for each filter
2183 **
2184 **	Parameters:
2185 **		cmd -- command to send.
2186 **		data -- optional command data.
2187 **		sz -- length of buf.
2188 **		stage -- index of macros to send for filter smfi_getsymval().
2189 **		e -- current envelope (for macro access).
2190 **		state -- return state word.
2191 **		where -- description of calling function (logging).
2192 **		cmd_error -- did the SMTP command cause an error?
2193 **
2194 **	Returns:
2195 **		response string (may be NULL)
2196 */
2197 
2198 static char *
milter_command(cmd,data,sz,stage,e,state,where,cmd_error)2199 milter_command(cmd, data, sz, stage, e, state, where, cmd_error)
2200 	int cmd;
2201 	void *data;
2202 	ssize_t sz;
2203 	int stage;
2204 	ENVELOPE *e;
2205 	char *state;
2206 	const char *where;
2207 	bool cmd_error;
2208 {
2209 	int i;
2210 	char command = (char) cmd;
2211 	char *response = NULL;
2212 	time_t tn = 0;
2213 
2214 	if (tTd(64, 10))
2215 		sm_dprintf("milter_command: cmd %c len %ld\n",
2216 			command, (long) sz);
2217 
2218 	*state = SMFIR_CONTINUE;
2219 	for (i = 0; InputFilters[i] != NULL; i++)
2220 	{
2221 		struct milter *m = InputFilters[i];
2222 
2223 		/* previous problem? */
2224 		if (m->mf_state == SMFS_ERROR)
2225 		{
2226 			MILTER_CHECK_ERROR(false, continue);
2227 			break;
2228 		}
2229 
2230 		/* sanity check */
2231 		if (m->mf_sock < 0 ||
2232 		    (m->mf_state != SMFS_OPEN && m->mf_state != SMFS_INMSG))
2233 			continue;
2234 
2235 		if (stage >= SMFIM_FIRST && stage <= SMFIM_LAST)
2236 		{
2237 			int idx;
2238 			char **macros;
2239 
2240 			if ((m->mf_lflags & MI_LFLAGS_SYM(stage)) != 0)
2241 				idx = m->mf_idx;
2242 			else
2243 				idx = 0;
2244 			SM_ASSERT(idx >= 0 && idx <= MAXFILTERS);
2245 			macros = MilterMacros[stage][idx];
2246 
2247 			/* send macros (regardless of whether we send cmd) */
2248 			if (macros != NULL && macros[0] != NULL)
2249 			{
2250 				milter_send_macros(m, macros, command, e);
2251 				if (m->mf_state == SMFS_ERROR)
2252 				{
2253 					MILTER_CHECK_ERROR(false, continue);
2254 					break;
2255 				}
2256 			}
2257 		}
2258 
2259 		if (MilterLogLevel > 21)
2260 			tn = curtime();
2261 
2262 		/*
2263 		**  send the command if
2264 		**	there is no error
2265 		**	or it's RCPT and the client asked for it:
2266 		**	!cmd_error ||
2267 		**	where == "rcpt" && m->mf_pflags & SMFIP_RCPT_REJ != 0
2268 		**  negate that condition and use continue
2269 		*/
2270 
2271 		if (cmd_error &&
2272 		    (strcmp(where, "rcpt") != 0 ||
2273 		     (m->mf_pflags & SMFIP_RCPT_REJ) == 0))
2274 			continue;
2275 
2276 		response = milter_send_command(m, command, data, sz, e, state,
2277 						where);
2278 
2279 		if (MilterLogLevel > 21)
2280 		{
2281 			/* log the time it took for the command per filter */
2282 			sm_syslog(LOG_INFO, e->e_id,
2283 				  "Milter (%s): time command (%c), %d",
2284 				  m->mf_name, command, (int) (tn - curtime()));
2285 		}
2286 
2287 		if (*state != SMFIR_CONTINUE)
2288 			break;
2289 	}
2290 	return response;
2291 }
2292 
2293 static int milter_getsymlist __P((struct milter *, char *, int, int));
2294 
2295 static int
milter_getsymlist(m,buf,rlen,offset)2296 milter_getsymlist(m, buf, rlen, offset)
2297 	struct milter *m;
2298 	char *buf;
2299 	int rlen;
2300 	int offset;
2301 {
2302 	int i, r, nummac;
2303 	mi_int32 v;
2304 
2305 	SM_ASSERT(m != NULL);
2306 	SM_ASSERT(buf != NULL);
2307 
2308 	while (offset + MILTER_LEN_BYTES < rlen)
2309 	{
2310 		size_t len;
2311 		char **macros;
2312 
2313 		nummac = 0;
2314 		(void) memcpy((char *) &v, buf + offset, MILTER_LEN_BYTES);
2315 		i = ntohl(v);
2316 		if (i < SMFIM_FIRST || i > SMFIM_LAST)
2317 			return -1;
2318 		offset += MILTER_LEN_BYTES;
2319 		macros = NULL;
2320 
2321 		switch (i)
2322 		{
2323 		  case SMFIM_CONNECT:
2324 		  case SMFIM_HELO:
2325 		  case SMFIM_ENVFROM:
2326 		  case SMFIM_ENVRCPT:
2327 		  case SMFIM_EOH:
2328 		  case SMFIM_EOM:
2329 		  case SMFIM_DATA:
2330 			SM_ASSERT(m->mf_idx > 0 && m->mf_idx < MAXFILTERS);
2331 			macros = MilterMacros[i][m->mf_idx];
2332 			m->mf_lflags |= MI_LFLAGS_SYM(i);
2333 			len = strlen(buf + offset);
2334 			if (len > 0)
2335 			{
2336 				r = milter_set_macros(m->mf_name, macros,
2337 						buf + offset, nummac);
2338 				if (r >= 0)
2339 					nummac = r;
2340 				if (tTd(64, 5))
2341 					sm_dprintf("milter_getsymlist(%s, %s)=%d\n",
2342 						m->mf_name, buf + offset, r);
2343 			}
2344 			break;
2345 
2346 		  default:
2347 			return -1;
2348 		}
2349 		if (len == 0)
2350 			return -1;
2351 		offset += len + 1;
2352 	}
2353 
2354 	return 0;
2355 }
2356 
2357 /*
2358 **  MILTER_NEGOTIATE -- get version and flags from filter
2359 **
2360 **	Parameters:
2361 **		m -- milter filter structure.
2362 **		e -- current envelope.
2363 **		milters -- milters structure.
2364 **
2365 **	Returns:
2366 **		0 on success, -1 otherwise
2367 */
2368 
2369 static int
milter_negotiate(m,e,milters)2370 milter_negotiate(m, e, milters)
2371 	struct milter *m;
2372 	ENVELOPE *e;
2373 	milters_T *milters;
2374 {
2375 	char rcmd;
2376 	mi_int32 fvers, fflags, pflags;
2377 	mi_int32 mta_prot_vers, mta_prot_flags, mta_actions;
2378 	ssize_t rlen;
2379 	char *response;
2380 	char data[MILTER_OPTLEN];
2381 
2382 	/* sanity check */
2383 	if (m->mf_sock < 0 || m->mf_state != SMFS_OPEN)
2384 	{
2385 		if (MilterLogLevel > 0)
2386 			sm_syslog(LOG_ERR, e->e_id,
2387 				  "Milter (%s): negotiate, impossible state",
2388 				  m->mf_name);
2389 		milter_error(m, e);
2390 		return -1;
2391 	}
2392 
2393 #if _FFR_MILTER_CHECK
2394 	mta_prot_vers = m->mf_mta_prot_version;
2395 	mta_prot_flags = m->mf_mta_prot_flags;
2396 	mta_actions = m->mf_mta_actions;
2397 #else /* _FFR_MILTER_CHECK */
2398 	mta_prot_vers = SMFI_PROT_VERSION;
2399 	mta_prot_flags = SMFI_CURR_PROT;
2400 	mta_actions = SMFI_CURR_ACTS;
2401 #endif /* _FFR_MILTER_CHECK */
2402 #if _FFR_MDS_NEGOTIATE
2403 	if (MilterMaxDataSize == MILTER_MDS_256K)
2404 		mta_prot_flags |= SMFIP_MDS_256K;
2405 	else if (MilterMaxDataSize == MILTER_MDS_1M)
2406 		mta_prot_flags |= SMFIP_MDS_1M;
2407 #endif /* _FFR_MDS_NEGOTIATE */
2408 
2409 	fvers = htonl(mta_prot_vers);
2410 	pflags = htonl(mta_prot_flags);
2411 	fflags = htonl(mta_actions);
2412 	(void) memcpy(data, (char *) &fvers, MILTER_LEN_BYTES);
2413 	(void) memcpy(data + MILTER_LEN_BYTES,
2414 		      (char *) &fflags, MILTER_LEN_BYTES);
2415 	(void) memcpy(data + (MILTER_LEN_BYTES * 2),
2416 		      (char *) &pflags, MILTER_LEN_BYTES);
2417 	(void) milter_write(m, SMFIC_OPTNEG, data, sizeof(data),
2418 			    m->mf_timeout[SMFTO_WRITE], e, "negotiate");
2419 
2420 	if (m->mf_state == SMFS_ERROR)
2421 		return -1;
2422 
2423 	if (tTd(64, 5))
2424 		sm_dprintf("milter_negotiate(%s): send: version %lu, fflags 0x%lx, pflags 0x%lx\n",
2425 			m->mf_name, (unsigned long)ntohl(fvers),
2426 			(unsigned long)ntohl(fflags), (unsigned long)ntohl(pflags));
2427 
2428 	response = milter_read(m, &rcmd, &rlen, m->mf_timeout[SMFTO_READ], e,
2429 				"negotiate");
2430 	if (m->mf_state == SMFS_ERROR)
2431 		return -1;
2432 
2433 	if (rcmd != SMFIC_OPTNEG)
2434 	{
2435 		if (tTd(64, 5))
2436 			sm_dprintf("milter_negotiate(%s): returned %c instead of %c\n",
2437 				m->mf_name, rcmd, SMFIC_OPTNEG);
2438 		if (MilterLogLevel > 0)
2439 			sm_syslog(LOG_ERR, e->e_id,
2440 				  "Milter (%s): negotiate: returned %c instead of %c",
2441 				  m->mf_name, rcmd, SMFIC_OPTNEG);
2442 		if (response != NULL)
2443 			sm_free(response); /* XXX */
2444 		milter_error(m, e);
2445 		return -1;
2446 	}
2447 
2448 	/* Make sure we have enough bytes for the version */
2449 	if (response == NULL || rlen < MILTER_LEN_BYTES)
2450 	{
2451 		if (tTd(64, 5))
2452 			sm_dprintf("milter_negotiate(%s): did not return valid info\n",
2453 				m->mf_name);
2454 		if (MilterLogLevel > 0)
2455 			sm_syslog(LOG_ERR, e->e_id,
2456 				  "Milter (%s): negotiate: did not return valid info",
2457 				  m->mf_name);
2458 		if (response != NULL)
2459 			sm_free(response); /* XXX */
2460 		milter_error(m, e);
2461 		return -1;
2462 	}
2463 
2464 	/* extract information */
2465 	(void) memcpy((char *) &fvers, response, MILTER_LEN_BYTES);
2466 
2467 	/* Now make sure we have enough for the feature bitmap */
2468 	if (rlen < MILTER_OPTLEN)
2469 	{
2470 		if (tTd(64, 5))
2471 			sm_dprintf("milter_negotiate(%s): did not return enough info\n",
2472 				m->mf_name);
2473 		if (MilterLogLevel > 0)
2474 			sm_syslog(LOG_ERR, e->e_id,
2475 				  "Milter (%s): negotiate: did not return enough info",
2476 				  m->mf_name);
2477 		if (response != NULL)
2478 			sm_free(response); /* XXX */
2479 		milter_error(m, e);
2480 		return -1;
2481 	}
2482 
2483 	(void) memcpy((char *) &fflags, response + MILTER_LEN_BYTES,
2484 		      MILTER_LEN_BYTES);
2485 	(void) memcpy((char *) &pflags, response + (MILTER_LEN_BYTES * 2),
2486 		      MILTER_LEN_BYTES);
2487 
2488 	m->mf_fvers = ntohl(fvers);
2489 	m->mf_fflags = ntohl(fflags);
2490 	m->mf_pflags = ntohl(pflags);
2491 
2492 	/* check for version compatibility */
2493 	if (m->mf_fvers == 1 ||
2494 	    m->mf_fvers > SMFI_VERSION)
2495 	{
2496 		if (tTd(64, 5))
2497 			sm_dprintf("milter_negotiate(%s): version %d != MTA milter version %d\n",
2498 				m->mf_name, m->mf_fvers, SMFI_VERSION);
2499 		if (MilterLogLevel > 0)
2500 			sm_syslog(LOG_ERR, e->e_id,
2501 				  "Milter (%s): negotiate: version %d != MTA milter version %d",
2502 				  m->mf_name, m->mf_fvers, SMFI_VERSION);
2503 		milter_error(m, e);
2504 		goto error;
2505 	}
2506 
2507 	/* check for filter feature mismatch */
2508 	if ((m->mf_fflags & mta_actions) != m->mf_fflags)
2509 	{
2510 		if (tTd(64, 5))
2511 			sm_dprintf("milter_negotiate(%s): filter abilities 0x%x != MTA milter abilities 0x%lx\n",
2512 				m->mf_name, m->mf_fflags,
2513 				(unsigned long) mta_actions);
2514 		if (MilterLogLevel > 0)
2515 			sm_syslog(LOG_ERR, e->e_id,
2516 				  "Milter (%s): negotiate: filter abilities 0x%x != MTA milter abilities 0x%lx",
2517 				  m->mf_name, m->mf_fflags,
2518 				  (unsigned long) mta_actions);
2519 		milter_error(m, e);
2520 		goto error;
2521 	}
2522 
2523 #if _FFR_MDS_NEGOTIATE
2524 	/* use a table instead of sequence? */
2525 	if (bitset(SMFIP_MDS_1M, m->mf_pflags))
2526 	{
2527 		if (MilterMaxDataSize != MILTER_MDS_1M)
2528 		{
2529 			/* this should not happen... */
2530 			sm_syslog(LOG_WARNING, NOQID,
2531 				  "WARNING: Milter.maxdatasize: configured=%d, set by libmilter=%d",
2532 		    		  MilterMaxDataSize, MILTER_MDS_1M);
2533 			MilterMaxDataSize = MILTER_MDS_1M;
2534 		}
2535 	}
2536 	else if (bitset(SMFIP_MDS_256K, m->mf_pflags))
2537 	{
2538 		if (MilterMaxDataSize != MILTER_MDS_256K)
2539 		{
2540 			sm_syslog(LOG_WARNING, NOQID,
2541 				  "WARNING: Milter.maxdatasize: configured=%d, set by libmilter=%d",
2542 		    		  MilterMaxDataSize, MILTER_MDS_256K);
2543 			MilterMaxDataSize = MILTER_MDS_256K;
2544 		}
2545 	}
2546 	else if (MilterMaxDataSize != MILTER_MDS_64K)
2547 	{
2548 		sm_syslog(LOG_WARNING, NOQID,
2549 			  "WARNING: Milter.maxdatasize: configured=%d, set by libmilter=%d",
2550 	    		  MilterMaxDataSize, MILTER_MDS_64K);
2551 		MilterMaxDataSize = MILTER_MDS_64K;
2552 	}
2553 	m->mf_pflags &= ~SMFI_INTERNAL;
2554 #endif /* _FFR_MDS_NEGOTIATE */
2555 
2556 	/* check for protocol feature mismatch */
2557 	if ((m->mf_pflags & mta_prot_flags) != m->mf_pflags)
2558 	{
2559 		if (tTd(64, 5))
2560 			sm_dprintf("milter_negotiate(%s): protocol abilities 0x%x != MTA milter abilities 0x%lx\n",
2561 				m->mf_name, m->mf_pflags,
2562 				(unsigned long) mta_prot_flags);
2563 		if (MilterLogLevel > 0)
2564 			sm_syslog(LOG_ERR, e->e_id,
2565 				  "Milter (%s): negotiate: protocol abilities 0x%x != MTA milter abilities 0x%lx",
2566 				  m->mf_name, m->mf_pflags,
2567 				  (unsigned long) mta_prot_flags);
2568 		milter_error(m, e);
2569 		goto error;
2570 	}
2571 
2572 	if (m->mf_fvers <= 2)
2573 		m->mf_pflags |= SMFIP_NOUNKNOWN;
2574 	if (m->mf_fvers <= 3)
2575 		m->mf_pflags |= SMFIP_NODATA;
2576 
2577 	if (rlen > MILTER_OPTLEN)
2578 	{
2579 		milter_getsymlist(m, response, rlen, MILTER_OPTLEN);
2580 	}
2581 
2582 	if (bitset(SMFIF_DELRCPT, m->mf_fflags))
2583 		milters->mis_flags |= MIS_FL_DEL_RCPT;
2584 	if (!bitset(SMFIP_NORCPT, m->mf_pflags) &&
2585 	    !bitset(SMFIP_NR_RCPT, m->mf_pflags))
2586 		milters->mis_flags |= MIS_FL_REJ_RCPT;
2587 
2588 	if (tTd(64, 5))
2589 		sm_dprintf("milter_negotiate(%s): received: version %u, fflags 0x%x, pflags 0x%x\n",
2590 			m->mf_name, m->mf_fvers, m->mf_fflags, m->mf_pflags);
2591 	return 0;
2592 
2593   error:
2594 	if (response != NULL)
2595 		sm_free(response); /* XXX */
2596 	return -1;
2597 }
2598 
2599 /*
2600 **  MILTER_PER_CONNECTION_CHECK -- checks on per-connection commands
2601 **
2602 **	Reduce code duplication by putting these checks in one place
2603 **
2604 **	Parameters:
2605 **		e -- current envelope.
2606 **
2607 **	Returns:
2608 **		none
2609 */
2610 
2611 static void
milter_per_connection_check(e)2612 milter_per_connection_check(e)
2613 	ENVELOPE *e;
2614 {
2615 	int i;
2616 
2617 	/* see if we are done with any of the filters */
2618 	for (i = 0; InputFilters[i] != NULL; i++)
2619 	{
2620 		struct milter *m = InputFilters[i];
2621 
2622 		if (m->mf_state == SMFS_CLOSABLE)
2623 			milter_quit_filter(m, e);
2624 	}
2625 }
2626 
2627 /*
2628 **  MILTER_ERROR -- Put a milter filter into error state
2629 **
2630 **	Parameters:
2631 **		m -- the broken filter.
2632 **		e -- current envelope.
2633 **
2634 **	Returns:
2635 **		none
2636 */
2637 
2638 static void
milter_error(m,e)2639 milter_error(m, e)
2640 	struct milter *m;
2641 	ENVELOPE *e;
2642 {
2643 	/*
2644 	**  We could send a quit here but we may have gotten here due to
2645 	**  an I/O error so we don't want to try to make things worse.
2646 	*/
2647 
2648 	if (m->mf_sock >= 0)
2649 	{
2650 		(void) close(m->mf_sock);
2651 		m->mf_sock = -1;
2652 	}
2653 	m->mf_state = SMFS_ERROR;
2654 
2655 	if (MilterLogLevel > 0)
2656 		sm_syslog(LOG_INFO, e->e_id, "Milter (%s): to error state",
2657 			  m->mf_name);
2658 }
2659 
2660 /*
2661 **  MILTER_HEADERS -- send headers to a single milter filter
2662 **
2663 **	Parameters:
2664 **		m -- current filter.
2665 **		e -- current envelope.
2666 **		state -- return state from response.
2667 **
2668 **	Returns:
2669 **		response string (may be NULL)
2670 */
2671 
2672 static char *
milter_headers(m,e,state)2673 milter_headers(m, e, state)
2674 	struct milter *m;
2675 	ENVELOPE *e;
2676 	char *state;
2677 {
2678 	char *response = NULL;
2679 	HDR *h;
2680 
2681 	if (MilterLogLevel > 17)
2682 		sm_syslog(LOG_INFO, e->e_id, "Milter (%s): headers, send",
2683 			  m->mf_name);
2684 
2685 	for (h = e->e_header; h != NULL; h = h->h_link)
2686 	{
2687 		int len_n, len_v, len_t, len_f;
2688 		char *buf, *hv;
2689 
2690 		/* don't send over deleted headers */
2691 		if (h->h_value == NULL)
2692 		{
2693 			/* strip H_USER so not counted in milter_changeheader() */
2694 			h->h_flags &= ~H_USER;
2695 			continue;
2696 		}
2697 
2698 		/* skip auto-generated */
2699 		if (!bitset(H_USER, h->h_flags))
2700 			continue;
2701 
2702 		if (tTd(64, 10))
2703 			sm_dprintf("milter_headers: %s:%s\n",
2704 				h->h_field, h->h_value);
2705 		if (MilterLogLevel > 21)
2706 			sm_syslog(LOG_INFO, e->e_id, "Milter (%s): header, %s",
2707 				  m->mf_name, h->h_field);
2708 
2709 		if (bitset(SMFIP_HDR_LEADSPC, m->mf_pflags)
2710 		    || *(h->h_value) != ' ')
2711 			hv = h->h_value;
2712 		else
2713 			hv = h->h_value + 1;
2714 		len_f = strlen(h->h_field) + 1;
2715 		len_t = len_f + strlen(hv) + 1;
2716 		if (len_t < 0)
2717 			continue;
2718 		buf = (char *) xalloc(len_t);
2719 
2720 		/*
2721 		**  Note: currently the call to dequote_internal_chars()
2722 		**  is not required as h_field is supposed to be 7-bit US-ASCII.
2723 		*/
2724 
2725 		len_n = dequote_internal_chars(h->h_field, buf, len_f);
2726 		SM_ASSERT(len_n < len_f);
2727 		len_v = dequote_internal_chars(hv, buf + len_n + 1,
2728 						len_t - len_n - 1);
2729 		SM_ASSERT(len_t >= len_n + 1 + len_v + 1);
2730 		len_t = len_n + 1 + len_v + 1;
2731 
2732 		/* send it over */
2733 		response = milter_send_command(m, SMFIC_HEADER, buf,
2734 					       len_t, e, state, "header");
2735 		sm_free(buf);
2736 		if (m->mf_state == SMFS_ERROR ||
2737 		    m->mf_state == SMFS_DONE ||
2738 		    *state != SMFIR_CONTINUE)
2739 			break;
2740 	}
2741 	if (MilterLogLevel > 17)
2742 		sm_syslog(LOG_INFO, e->e_id, "Milter (%s): headers, sent",
2743 			  m->mf_name);
2744 	return response;
2745 }
2746 
2747 /*
2748 **  MILTER_BODY -- send the body to a filter
2749 **
2750 **	Parameters:
2751 **		m -- current filter.
2752 **		e -- current envelope.
2753 **		state -- return state from response.
2754 **
2755 **	Returns:
2756 **		response string (may be NULL)
2757 */
2758 
2759 static char *
milter_body(m,e,state)2760 milter_body(m, e, state)
2761 	struct milter *m;
2762 	ENVELOPE *e;
2763 	char *state;
2764 {
2765 	char bufchar = '\0';
2766 	char prevchar = '\0';
2767 	int c;
2768 	char *response = NULL;
2769 	char *bp;
2770 	char buf[MILTER_CHUNK_SIZE];
2771 
2772 	if (tTd(64, 10))
2773 		sm_dprintf("milter_body\n");
2774 
2775 	if (bfrewind(e->e_dfp) < 0)
2776 	{
2777 		ExitStat = EX_IOERR;
2778 		*state = SMFIR_TEMPFAIL;
2779 		syserr("milter_body: %s/%cf%s: rewind error",
2780 		       qid_printqueue(e->e_qgrp, e->e_qdir),
2781 		       DATAFL_LETTER, e->e_id);
2782 		return NULL;
2783 	}
2784 
2785 	if (MilterLogLevel > 17)
2786 		sm_syslog(LOG_INFO, e->e_id, "Milter (%s): body, send",
2787 			  m->mf_name);
2788 	bp = buf;
2789 	while ((c = sm_io_getc(e->e_dfp, SM_TIME_DEFAULT)) != SM_IO_EOF)
2790 	{
2791 		/*  Change LF to CRLF */
2792 		if (c == '\n')
2793 		{
2794 #if !_FFR_MILTER_CONVERT_ALL_LF_TO_CRLF
2795 			/* Not a CRLF already? */
2796 			if (prevchar != '\r')
2797 #endif /* !_FFR_MILTER_CONVERT_ALL_LF_TO_CRLF */
2798 			{
2799 				/* Room for CR now? */
2800 				if (bp + 2 > &buf[sizeof(buf)])
2801 				{
2802 					/* No room, buffer LF */
2803 					bufchar = c;
2804 
2805 					/* and send CR now */
2806 					c = '\r';
2807 				}
2808 				else
2809 				{
2810 					/* Room to do it now */
2811 					*bp++ = '\r';
2812 					prevchar = '\r';
2813 				}
2814 			}
2815 		}
2816 		*bp++ = (char) c;
2817 		prevchar = c;
2818 		if (bp >= &buf[sizeof(buf)])
2819 		{
2820 			/* send chunk */
2821 			response = milter_send_command(m, SMFIC_BODY, buf,
2822 						       bp - buf, e, state,
2823 							"body chunk");
2824 			bp = buf;
2825 			if (bufchar != '\0')
2826 			{
2827 				*bp++ = bufchar;
2828 				bufchar = '\0';
2829 				prevchar = bufchar;
2830 			}
2831 		}
2832 		if (m->mf_state == SMFS_ERROR ||
2833 		    m->mf_state == SMFS_DONE ||
2834 		    m->mf_state == SMFS_SKIP ||
2835 		    *state != SMFIR_CONTINUE)
2836 			break;
2837 	}
2838 
2839 	/* check for read errors */
2840 	if (sm_io_error(e->e_dfp))
2841 	{
2842 		ExitStat = EX_IOERR;
2843 		if (*state == SMFIR_CONTINUE ||
2844 		    *state == SMFIR_ACCEPT ||
2845 		    m->mf_state == SMFS_SKIP)
2846 		{
2847 			*state = SMFIR_TEMPFAIL;
2848 			if (response != NULL)
2849 			{
2850 				sm_free(response); /* XXX */
2851 				response = NULL;
2852 			}
2853 		}
2854 		syserr("milter_body: %s/%cf%s: read error",
2855 		       qid_printqueue(e->e_qgrp, e->e_qdir),
2856 		       DATAFL_LETTER, e->e_id);
2857 		return response;
2858 	}
2859 
2860 	/* send last body chunk */
2861 	if (bp > buf &&
2862 	    m->mf_state != SMFS_ERROR &&
2863 	    m->mf_state != SMFS_DONE &&
2864 	    m->mf_state != SMFS_SKIP &&
2865 	    *state == SMFIR_CONTINUE)
2866 	{
2867 		/* send chunk */
2868 		response = milter_send_command(m, SMFIC_BODY, buf, bp - buf,
2869 					       e, state, "last body chunk");
2870 		bp = buf;
2871 	}
2872 	if (MilterLogLevel > 17)
2873 		sm_syslog(LOG_INFO, e->e_id, "Milter (%s): body, sent",
2874 			  m->mf_name);
2875 	if (m->mf_state == SMFS_SKIP)
2876 	{
2877 		*state = SMFIR_CONTINUE;
2878 		m->mf_state = SMFS_READY;
2879 	}
2880 
2881 	return response;
2882 }
2883 
2884 /*
2885 **  Actions
2886 */
2887 
2888 /*
2889 **  ADDLEADINGSPACE -- Add a leading space to a string
2890 **
2891 **	Parameters:
2892 **		str -- string
2893 **		rp -- resource pool for allocations
2894 **
2895 **	Returns:
2896 **		pointer to new string
2897 */
2898 
2899 static char *addleadingspace __P((char *, SM_RPOOL_T *));
2900 
2901 static char *
addleadingspace(str,rp)2902 addleadingspace(str, rp)
2903 	char *str;
2904 	SM_RPOOL_T *rp;
2905 {
2906 	size_t l;
2907 	char *new;
2908 
2909 	SM_ASSERT(str != NULL);
2910 	l = strlen(str);
2911 	SM_ASSERT(l + 2 > l);
2912 	new = sm_rpool_malloc_x(rp, l + 2);
2913 	new[0] = ' ';
2914 	new[1] = '\0';
2915 	sm_strlcpy(new + 1, str, l + 1);
2916 	return new;
2917 }
2918 
2919 /*
2920 **  MILTER_ADDHEADER -- Add the supplied header to the message
2921 **
2922 **	Parameters:
2923 **		m -- current filter.
2924 **		response -- encoded form of header/value.
2925 **		rlen -- length of response.
2926 **		e -- current envelope.
2927 **
2928 **	Returns:
2929 **		none
2930 */
2931 
2932 static void
milter_addheader(m,response,rlen,e)2933 milter_addheader(m, response, rlen, e)
2934 	struct milter *m;
2935 	char *response;
2936 	ssize_t rlen;
2937 	ENVELOPE *e;
2938 {
2939 	int mh_v_len;
2940 	char *val, *mh_value;
2941 	HDR *h;
2942 
2943 	if (tTd(64, 10))
2944 		sm_dprintf("milter_addheader: ");
2945 
2946 	/* sanity checks */
2947 	if (response == NULL)
2948 	{
2949 		if (tTd(64, 10))
2950 			sm_dprintf("NULL response\n");
2951 		return;
2952 	}
2953 
2954 	if (rlen < 2 || strlen(response) + 1 >= (size_t) rlen)
2955 	{
2956 		if (tTd(64, 10))
2957 			sm_dprintf("didn't follow protocol (total len %d != rlen %d)\n",
2958 				   (int) strlen(response), (int) (rlen - 1));
2959 		return;
2960 	}
2961 
2962 	/* Find separating NUL */
2963 	val = response + strlen(response) + 1;
2964 
2965 	/* another sanity check */
2966 	if (strlen(response) + strlen(val) + 2 != (size_t) rlen)
2967 	{
2968 		if (tTd(64, 10))
2969 			sm_dprintf("didn't follow protocol (part len)\n");
2970 		return;
2971 	}
2972 
2973 	if (*response == '\0')
2974 	{
2975 		if (tTd(64, 10))
2976 			sm_dprintf("empty field name\n");
2977 		return;
2978 	}
2979 
2980 	for (h = e->e_header; h != NULL; h = h->h_link)
2981 	{
2982 		if (sm_strcasecmp(h->h_field, response) == 0 &&
2983 		    !bitset(H_USER, h->h_flags) &&
2984 		    !bitset(H_TRACE, h->h_flags))
2985 			break;
2986 	}
2987 
2988 	mh_v_len = 0;
2989 	mh_value = quote_internal_chars(val, NULL, &mh_v_len);
2990 
2991 	/* add to e_msgsize */
2992 	e->e_msgsize += strlen(response) + 2 + strlen(val);
2993 
2994 	if (h != NULL)
2995 	{
2996 		if (tTd(64, 10))
2997 			sm_dprintf("Replace default header %s value with %s\n",
2998 				   h->h_field, mh_value);
2999 		if (MilterLogLevel > 8)
3000 			sm_syslog(LOG_INFO, e->e_id,
3001 				  "Milter change: default header %s value with %s",
3002 				  h->h_field, mh_value);
3003 		if (bitset(SMFIP_HDR_LEADSPC, m->mf_pflags))
3004 			h->h_value = mh_value;
3005 		else
3006 		{
3007 			h->h_value = addleadingspace(mh_value, e->e_rpool);
3008 			SM_FREE(mh_value);
3009 		}
3010 		h->h_flags |= H_USER;
3011 	}
3012 	else
3013 	{
3014 		if (tTd(64, 10))
3015 			sm_dprintf("Add %s: %s\n", response, mh_value);
3016 		if (MilterLogLevel > 8)
3017 			sm_syslog(LOG_INFO, e->e_id,
3018 				  "Milter add: header: %s: %s",
3019 				  response, mh_value);
3020 		addheader(newstr(response), mh_value, H_USER, e,
3021 			!bitset(SMFIP_HDR_LEADSPC, m->mf_pflags));
3022 		SM_FREE(mh_value);
3023 	}
3024 }
3025 
3026 /*
3027 **  MILTER_INSHEADER -- Insert the supplied header
3028 **
3029 **	Parameters:
3030 **		m -- current filter.
3031 **		response -- encoded form of header/value.
3032 **		rlen -- length of response.
3033 **		e -- current envelope.
3034 **
3035 **	Returns:
3036 **		none
3037 **
3038 **	Notes:
3039 **		Unlike milter_addheader(), this does not attempt to determine
3040 **		if the header already exists in the envelope, even a
3041 **		deleted version.  It just blindly inserts.
3042 */
3043 
3044 static void
milter_insheader(m,response,rlen,e)3045 milter_insheader(m, response, rlen, e)
3046 	struct milter *m;
3047 	char *response;
3048 	ssize_t rlen;
3049 	ENVELOPE *e;
3050 {
3051 	mi_int32 idx, i;
3052 	int mh_v_len;
3053 	char *field, *val, *mh_value;
3054 
3055 	if (tTd(64, 10))
3056 		sm_dprintf("milter_insheader: ");
3057 
3058 	/* sanity checks */
3059 	if (response == NULL)
3060 	{
3061 		if (tTd(64, 10))
3062 			sm_dprintf("NULL response\n");
3063 		return;
3064 	}
3065 
3066 	if (rlen < 2 || strlen(response) + 1 >= (size_t) rlen)
3067 	{
3068 		if (tTd(64, 10))
3069 			sm_dprintf("didn't follow protocol (total len)\n");
3070 		return;
3071 	}
3072 
3073 	/* decode */
3074 	(void) memcpy((char *) &i, response, MILTER_LEN_BYTES);
3075 	idx = ntohl(i);
3076 	field = response + MILTER_LEN_BYTES;
3077 	val = field + strlen(field) + 1;
3078 
3079 	/* another sanity check */
3080 	if (MILTER_LEN_BYTES + strlen(field) + 1 +
3081 	    strlen(val) + 1 != (size_t) rlen)
3082 	{
3083 		if (tTd(64, 10))
3084 			sm_dprintf("didn't follow protocol (part len)\n");
3085 		return;
3086 	}
3087 
3088 	if (*field == '\0')
3089 	{
3090 		if (tTd(64, 10))
3091 			sm_dprintf("empty field name\n");
3092 		return;
3093 	}
3094 
3095 	/* add to e_msgsize */
3096 	e->e_msgsize += strlen(response) + 2 + strlen(val);
3097 
3098 	if (tTd(64, 10))
3099 		sm_dprintf("Insert (%d) %s: %s\n", idx, field, val);
3100 	if (MilterLogLevel > 8)
3101 		sm_syslog(LOG_INFO, e->e_id,
3102 			  "Milter insert (%d): header: %s: %s",
3103 			  idx, field, val);
3104 	mh_v_len = 0;
3105 	mh_value = quote_internal_chars(val, NULL, &mh_v_len);
3106 	insheader(idx, newstr(field), mh_value, H_USER, e,
3107 		!bitset(SMFIP_HDR_LEADSPC, m->mf_pflags));
3108 	SM_FREE(mh_value);
3109 }
3110 
3111 /*
3112 **  MILTER_CHANGEHEADER -- Change the supplied header in the message
3113 **
3114 **	Parameters:
3115 **		m -- current filter.
3116 **		response -- encoded form of header/index/value.
3117 **		rlen -- length of response.
3118 **		e -- current envelope.
3119 **
3120 **	Returns:
3121 **		none
3122 */
3123 
3124 static void
milter_changeheader(m,response,rlen,e)3125 milter_changeheader(m, response, rlen, e)
3126 	struct milter *m;
3127 	char *response;
3128 	ssize_t rlen;
3129 	ENVELOPE *e;
3130 {
3131 	mi_int32 i, index;
3132 	int mh_v_len;
3133 	char *field, *val, *mh_value;
3134 	HDR *h, *sysheader;
3135 
3136 	if (tTd(64, 10))
3137 		sm_dprintf("milter_changeheader: ");
3138 
3139 	/* sanity checks */
3140 	if (response == NULL)
3141 	{
3142 		if (tTd(64, 10))
3143 			sm_dprintf("NULL response\n");
3144 		return;
3145 	}
3146 
3147 	if (rlen < 2 || strlen(response) + 1 >= (size_t) rlen)
3148 	{
3149 		if (tTd(64, 10))
3150 			sm_dprintf("didn't follow protocol (total len)\n");
3151 		return;
3152 	}
3153 
3154 	/* Find separating NUL */
3155 	(void) memcpy((char *) &i, response, MILTER_LEN_BYTES);
3156 	index = ntohl(i);
3157 	field = response + MILTER_LEN_BYTES;
3158 	val = field + strlen(field) + 1;
3159 
3160 	/* another sanity check */
3161 	if (MILTER_LEN_BYTES + strlen(field) + 1 +
3162 	    strlen(val) + 1 != (size_t) rlen)
3163 	{
3164 		if (tTd(64, 10))
3165 			sm_dprintf("didn't follow protocol (part len)\n");
3166 		return;
3167 	}
3168 
3169 	if (*field == '\0')
3170 	{
3171 		if (tTd(64, 10))
3172 			sm_dprintf("empty field name\n");
3173 		return;
3174 	}
3175 
3176 	mh_v_len = 0;
3177 	mh_value = quote_internal_chars(val, NULL, &mh_v_len);
3178 
3179 	sysheader = NULL;
3180 	for (h = e->e_header; h != NULL; h = h->h_link)
3181 	{
3182 		if (sm_strcasecmp(h->h_field, field) == 0)
3183 		{
3184 			if (bitset(H_USER, h->h_flags) && --index <= 0)
3185 			{
3186 				sysheader = NULL;
3187 				break;
3188 			}
3189 			else if (!bitset(H_USER, h->h_flags) &&
3190 				 !bitset(H_TRACE, h->h_flags))
3191 			{
3192 				/*
3193 				**  DRUMS msg-fmt draft says can only have
3194 				**  multiple occurences of trace fields,
3195 				**  so make sure we replace any non-trace,
3196 				**  non-user field.
3197 				*/
3198 
3199 				sysheader = h;
3200 			}
3201 		}
3202 	}
3203 
3204 	/* if not found as user-provided header at index, use sysheader */
3205 	if (h == NULL)
3206 		h = sysheader;
3207 
3208 	if (h == NULL)
3209 	{
3210 		if (*val == '\0')
3211 		{
3212 			if (tTd(64, 10))
3213 				sm_dprintf("Delete (noop) %s\n", field);
3214 			if (MilterLogLevel > 8)
3215 				sm_syslog(LOG_INFO, e->e_id,
3216 					"Milter delete (noop): header: %s"
3217 					, field);
3218 		}
3219 		else
3220 		{
3221 			/* treat modify value with no existing header as add */
3222 			if (tTd(64, 10))
3223 				sm_dprintf("Add %s: %s\n", field, mh_value);
3224 			if (MilterLogLevel > 8)
3225 				sm_syslog(LOG_INFO, e->e_id,
3226 					"Milter change (add): header: %s: %s"
3227 					, field, mh_value);
3228 			addheader(newstr(field), mh_value, H_USER, e,
3229 				!bitset(SMFIP_HDR_LEADSPC, m->mf_pflags));
3230 		}
3231 		return;
3232 	}
3233 
3234 	if (tTd(64, 10))
3235 	{
3236 		if (*val == '\0')
3237 		{
3238 			sm_dprintf("Delete%s %s:%s\n",
3239 				   h == sysheader ? " (default header)" : "",
3240 				   field,
3241 				   h->h_value == NULL ? "<NULL>" : h->h_value);
3242 		}
3243 		else
3244 		{
3245 			sm_dprintf("Change%s %s: from %s to %s\n",
3246 				   h == sysheader ? " (default header)" : "",
3247 				   field,
3248 				   h->h_value == NULL ? "<NULL>" : h->h_value,
3249 				   mh_value);
3250 		}
3251 	}
3252 
3253 	if (MilterLogLevel > 8)
3254 	{
3255 		if (*val == '\0')
3256 		{
3257 			sm_syslog(LOG_INFO, e->e_id,
3258 				  "Milter delete: header%s %s:%s",
3259 				  h == sysheader ? " (default header)" : "",
3260 				  field,
3261 				  h->h_value == NULL ? "<NULL>" : h->h_value);
3262 		}
3263 		else
3264 		{
3265 			sm_syslog(LOG_INFO, e->e_id,
3266 				  "Milter change: header%s %s: from %s to %s",
3267 				  h == sysheader ? " (default header)" : "",
3268 				  field,
3269 				  h->h_value == NULL ? "<NULL>" : h->h_value,
3270 				  mh_value);
3271 		}
3272 	}
3273 
3274 	if (h != sysheader && h->h_value != NULL)
3275 	{
3276 		size_t l;
3277 
3278 		l = strlen(h->h_value);
3279 		if (l > e->e_msgsize)
3280 			e->e_msgsize = 0;
3281 		else
3282 			e->e_msgsize -= l;
3283 		/* rpool, don't free: sm_free(h->h_value); XXX */
3284 	}
3285 
3286 	if (*val == '\0')
3287 	{
3288 		/* Remove "Field: " from message size */
3289 		if (h != sysheader)
3290 		{
3291 			size_t l;
3292 
3293 			l = strlen(h->h_field) + 2;
3294 			if (l > e->e_msgsize)
3295 				e->e_msgsize = 0;
3296 			else
3297 				e->e_msgsize -= l;
3298 		}
3299 		h->h_value = NULL;
3300 		SM_FREE(mh_value);
3301 	}
3302 	else
3303 	{
3304 		if (bitset(SMFIP_HDR_LEADSPC, m->mf_pflags))
3305 			h->h_value = mh_value;
3306 		else
3307 		{
3308 			h->h_value = addleadingspace(mh_value, e->e_rpool);
3309 			SM_FREE(mh_value);
3310 		}
3311 		h->h_flags |= H_USER;
3312 		e->e_msgsize += strlen(h->h_value);
3313 	}
3314 }
3315 
3316 /*
3317 **  MILTER_SPLIT_RESPONSE -- Split response into fields.
3318 **
3319 **	Parameters:
3320 **		response -- encoded repsonse.
3321 **		rlen -- length of response.
3322 **		pargc -- number of arguments (ouput)
3323 **
3324 **	Returns:
3325 **		array of pointers to the individual strings
3326 */
3327 
3328 static char **milter_split_response __P((char *, ssize_t, int *));
3329 
3330 static char **
milter_split_response(response,rlen,pargc)3331 milter_split_response(response, rlen, pargc)
3332 	char *response;
3333 	ssize_t rlen;
3334 	int *pargc;
3335 {
3336 	char **s;
3337 	size_t i;
3338 	int elem, nelem;
3339 
3340 	SM_ASSERT(response != NULL);
3341 	SM_ASSERT(pargc != NULL);
3342 	*pargc = 0;
3343 	if (rlen < 2 || strlen(response) >= (size_t) rlen)
3344 	{
3345 		if (tTd(64, 10))
3346 			sm_dprintf("didn't follow protocol (total len %d != rlen %d)\n",
3347 				   (int) strlen(response), (int) (rlen - 1));
3348 		return NULL;
3349 	}
3350 
3351 	nelem = 0;
3352 	for (i = 0; i < rlen; i++)
3353 	{
3354 		if (response[i] == '\0')
3355 			++nelem;
3356 	}
3357 	if (nelem == 0)
3358 		return NULL;
3359 
3360 	/* last entry is only for the name */
3361 	s = (char **)malloc((nelem + 1) * (sizeof(*s)));
3362 	if (s == NULL)
3363 		return NULL;
3364 	s[0] = response;
3365 	for (i = 0, elem = 0; i < rlen && elem < nelem; i++)
3366 	{
3367 		if (response[i] == '\0')
3368 		{
3369 			++elem;
3370 			if (i + 1 >= rlen)
3371 				s[elem] = NULL;
3372 			else
3373 				s[elem] = &(response[i + 1]);
3374 		}
3375 	}
3376 	*pargc = nelem;
3377 
3378 	if (tTd(64, 10))
3379 	{
3380 		for (elem = 0; elem < nelem; elem++)
3381 			sm_dprintf("argv[%d]=\"%s\"\n", elem, s[elem]);
3382 	}
3383 
3384 	/* overwrite last entry (already done above, just paranoia) */
3385 	s[elem] = NULL;
3386 	return s;
3387 }
3388 
3389 /*
3390 **  MILTER_CHGFROM -- Change the envelope sender address
3391 **
3392 **	Parameters:
3393 **		response -- encoded form of recipient address.
3394 **		rlen -- length of response.
3395 **		e -- current envelope.
3396 **
3397 **	Returns:
3398 **		none
3399 */
3400 
3401 static void
milter_chgfrom(response,rlen,e)3402 milter_chgfrom(response, rlen, e)
3403 	char *response;
3404 	ssize_t rlen;
3405 	ENVELOPE *e;
3406 {
3407 	int olderrors, argc;
3408 	char **argv;
3409 
3410 	if (tTd(64, 10))
3411 		sm_dprintf("milter_chgfrom: ");
3412 
3413 	/* sanity checks */
3414 	if (response == NULL)
3415 	{
3416 		if (tTd(64, 10))
3417 			sm_dprintf("NULL response\n");
3418 		return;
3419 	}
3420 
3421 	if (*response == '\0' ||
3422 	    strlen(response) + 1 > (size_t) rlen)
3423 	{
3424 		if (tTd(64, 10))
3425 			sm_dprintf("didn't follow protocol (total len %d != rlen %d)\n",
3426 				   (int) strlen(response), (int) (rlen - 1));
3427 		return;
3428 	}
3429 
3430 	if (tTd(64, 10))
3431 		sm_dprintf("%s\n", response);
3432 	if (MilterLogLevel > 8)
3433 		sm_syslog(LOG_INFO, e->e_id, "Milter chgfrom: %s", response);
3434 	argv = milter_split_response(response, rlen, &argc);
3435 	if (argc < 1 || argc > 2)
3436 	{
3437 		if (tTd(64, 10))
3438 			sm_dprintf("didn't follow protocol argc=%d\n", argc);
3439 		return;
3440 	}
3441 
3442 	olderrors = Errors;
3443 	setsender(argv[0], e, NULL, '\0', false);
3444 	if (argc == 2)
3445 	{
3446 		reset_mail_esmtp_args(e);
3447 
3448 		/*
3449 		**  need "features" here: how to get those? via e?
3450 		**  "fake" it for now: allow everything.
3451 		*/
3452 
3453 		parse_esmtp_args(e, NULL, argv[0], argv[1], "MAIL", NULL,
3454 				mail_esmtp_args);
3455 	}
3456 	Errors = olderrors;
3457 	return;
3458 }
3459 
3460 /*
3461 **  MILTER_ADDRCPT_PAR -- Add the supplied recipient to the message
3462 **
3463 **	Parameters:
3464 **		response -- encoded form of recipient address.
3465 **		rlen -- length of response.
3466 **		e -- current envelope.
3467 **
3468 **	Returns:
3469 **		none
3470 */
3471 
3472 static void
milter_addrcpt_par(response,rlen,e)3473 milter_addrcpt_par(response, rlen, e)
3474 	char *response;
3475 	ssize_t rlen;
3476 	ENVELOPE *e;
3477 {
3478 	int olderrors, argc;
3479 	char *delimptr;
3480 	char **argv;
3481 	ADDRESS *a;
3482 
3483 	if (tTd(64, 10))
3484 		sm_dprintf("milter_addrcpt_par: ");
3485 
3486 	/* sanity checks */
3487 	if (response == NULL)
3488 	{
3489 		if (tTd(64, 10))
3490 			sm_dprintf("NULL response\n");
3491 		return;
3492 	}
3493 
3494 	if (tTd(64, 10))
3495 		sm_dprintf("%s\n", response);
3496 	if (MilterLogLevel > 8)
3497 		sm_syslog(LOG_INFO, e->e_id, "Milter add: rcpt: %s", response);
3498 
3499 	argv = milter_split_response(response, rlen, &argc);
3500 	if (argc < 1 || argc > 2)
3501 	{
3502 		if (tTd(64, 10))
3503 			sm_dprintf("didn't follow protocol argc=%d\n", argc);
3504 		return;
3505 	}
3506 	olderrors = Errors;
3507 
3508 	/* how to set ESMTP arguments? */
3509 	a = parseaddr(argv[0], NULLADDR, RF_COPYALL, ' ', &delimptr, e, true);
3510 
3511 	if (a != NULL && olderrors == Errors)
3512 	{
3513 		parse_esmtp_args(e, a, argv[0], argv[1], "RCPT", NULL,
3514 				rcpt_esmtp_args);
3515 		if (olderrors == Errors)
3516 			a = recipient(a, &e->e_sendqueue, 0, e);
3517 		else
3518 			sm_dprintf("olderrors=%d, Errors=%d\n",
3519 				olderrors, Errors);
3520 	}
3521 	else
3522 	{
3523 		sm_dprintf("a=%p, olderrors=%d, Errors=%d\n",
3524 			a, olderrors, Errors);
3525 	}
3526 
3527 	Errors = olderrors;
3528 	return;
3529 }
3530 
3531 /*
3532 **  MILTER_ADDRCPT -- Add the supplied recipient to the message
3533 **
3534 **	Parameters:
3535 **		response -- encoded form of recipient address.
3536 **		rlen -- length of response.
3537 **		e -- current envelope.
3538 **
3539 **	Returns:
3540 **		none
3541 */
3542 
3543 static void
milter_addrcpt(response,rlen,e)3544 milter_addrcpt(response, rlen, e)
3545 	char *response;
3546 	ssize_t rlen;
3547 	ENVELOPE *e;
3548 {
3549 	int olderrors;
3550 
3551 	if (tTd(64, 10))
3552 		sm_dprintf("milter_addrcpt: ");
3553 
3554 	/* sanity checks */
3555 	if (response == NULL)
3556 	{
3557 		if (tTd(64, 10))
3558 			sm_dprintf("NULL response\n");
3559 		return;
3560 	}
3561 
3562 	if (*response == '\0' ||
3563 	    strlen(response) + 1 != (size_t) rlen)
3564 	{
3565 		if (tTd(64, 10))
3566 			sm_dprintf("didn't follow protocol (total len %d != rlen %d)\n",
3567 				   (int) strlen(response), (int) (rlen - 1));
3568 		return;
3569 	}
3570 
3571 	if (tTd(64, 10))
3572 		sm_dprintf("%s\n", response);
3573 	if (MilterLogLevel > 8)
3574 		sm_syslog(LOG_INFO, e->e_id, "Milter add: rcpt: %s", response);
3575 	olderrors = Errors;
3576 	(void) sendtolist(response, NULLADDR, &e->e_sendqueue, 0, e);
3577 	Errors = olderrors;
3578 	return;
3579 }
3580 
3581 /*
3582 **  MILTER_DELRCPT -- Delete the supplied recipient from the message
3583 **
3584 **	Parameters:
3585 **		response -- encoded form of recipient address.
3586 **		rlen -- length of response.
3587 **		e -- current envelope.
3588 **
3589 **	Returns:
3590 **		none
3591 */
3592 
3593 static void
milter_delrcpt(response,rlen,e)3594 milter_delrcpt(response, rlen, e)
3595 	char *response;
3596 	ssize_t rlen;
3597 	ENVELOPE *e;
3598 {
3599 	if (tTd(64, 10))
3600 		sm_dprintf("milter_delrcpt: ");
3601 
3602 	/* sanity checks */
3603 	if (response == NULL)
3604 	{
3605 		if (tTd(64, 10))
3606 			sm_dprintf("NULL response\n");
3607 		return;
3608 	}
3609 
3610 	if (*response == '\0' ||
3611 	    strlen(response) + 1 != (size_t) rlen)
3612 	{
3613 		if (tTd(64, 10))
3614 			sm_dprintf("didn't follow protocol (total len %d != rlen %d)\n",
3615 				   (int) strlen(response), (int) (rlen - 1));
3616 		return;
3617 	}
3618 
3619 	if (tTd(64, 10))
3620 		sm_dprintf("%s\n", response);
3621 	if (MilterLogLevel > 8)
3622 		sm_syslog(LOG_INFO, e->e_id, "Milter delete: rcpt %s",
3623 			  response);
3624 	(void) removefromlist(response, &e->e_sendqueue, e);
3625 	return;
3626 }
3627 
3628 /*
3629 **  MILTER_REPLBODY -- Replace the current data file with new body
3630 **
3631 **	Parameters:
3632 **		response -- encoded form of new body.
3633 **		rlen -- length of response.
3634 **		newfilter -- if first time called by a new filter
3635 **		e -- current envelope.
3636 **
3637 **	Returns:
3638 **		0 upon success, -1 upon failure
3639 */
3640 
3641 static int
milter_replbody(response,rlen,newfilter,e)3642 milter_replbody(response, rlen, newfilter, e)
3643 	char *response;
3644 	ssize_t rlen;
3645 	bool newfilter;
3646 	ENVELOPE *e;
3647 {
3648 	static char prevchar;
3649 	int i;
3650 
3651 	if (tTd(64, 10))
3652 		sm_dprintf("milter_replbody\n");
3653 
3654 	/* If a new filter, reset previous character and truncate data file */
3655 	if (newfilter)
3656 	{
3657 		off_t prevsize;
3658 		char dfname[MAXPATHLEN];
3659 
3660 		(void) sm_strlcpy(dfname, queuename(e, DATAFL_LETTER),
3661 				  sizeof(dfname));
3662 
3663 		/* Reset prevchar */
3664 		prevchar = '\0';
3665 
3666 		/* Get the current data file information */
3667 		prevsize = sm_io_getinfo(e->e_dfp, SM_IO_WHAT_SIZE, NULL);
3668 		if (prevsize < 0)
3669 			prevsize = 0;
3670 
3671 		/* truncate current data file */
3672 		if (sm_io_getinfo(e->e_dfp, SM_IO_WHAT_ISTYPE, BF_FILE_TYPE))
3673 		{
3674 			if (sm_io_setinfo(e->e_dfp, SM_BF_TRUNCATE, NULL) < 0)
3675 			{
3676 				MILTER_DF_ERROR("milter_replbody: sm_io truncate %s: %s");
3677 				return -1;
3678 			}
3679 		}
3680 		else
3681 		{
3682 			int err;
3683 
3684 			err = sm_io_error(e->e_dfp);
3685 			(void) sm_io_flush(e->e_dfp, SM_TIME_DEFAULT);
3686 
3687 			/*
3688 			**  Clear error if tried to fflush()
3689 			**  a read-only file pointer and
3690 			**  there wasn't a previous error.
3691 			*/
3692 
3693 			if (err == 0)
3694 				sm_io_clearerr(e->e_dfp);
3695 
3696 			/* errno is set implicitly by fseek() before return */
3697 			err = sm_io_seek(e->e_dfp, SM_TIME_DEFAULT,
3698 					 0, SEEK_SET);
3699 			if (err < 0)
3700 			{
3701 				MILTER_DF_ERROR("milter_replbody: sm_io_seek %s: %s");
3702 				return -1;
3703 			}
3704 # if NOFTRUNCATE
3705 			/* XXX: Not much we can do except rewind it */
3706 			errno = EINVAL;
3707 			MILTER_DF_ERROR("milter_replbody: ftruncate not available on this platform (%s:%s)");
3708 			return -1;
3709 # else /* NOFTRUNCATE */
3710 			err = ftruncate(sm_io_getinfo(e->e_dfp,
3711 						      SM_IO_WHAT_FD, NULL),
3712 					0);
3713 			if (err < 0)
3714 			{
3715 				MILTER_DF_ERROR("milter_replbody: sm_io ftruncate %s: %s");
3716 				return -1;
3717 			}
3718 # endif /* NOFTRUNCATE */
3719 		}
3720 
3721 		if (prevsize > e->e_msgsize)
3722 			e->e_msgsize = 0;
3723 		else
3724 			e->e_msgsize -= prevsize;
3725 	}
3726 
3727 	if (newfilter && MilterLogLevel > 8)
3728 		sm_syslog(LOG_INFO, e->e_id, "Milter message: body replaced");
3729 
3730 	if (response == NULL)
3731 	{
3732 		/* Flush the buffered '\r' */
3733 		if (prevchar == '\r')
3734 		{
3735 			(void) sm_io_putc(e->e_dfp, SM_TIME_DEFAULT, prevchar);
3736 			e->e_msgsize++;
3737 		}
3738 		return 0;
3739 	}
3740 
3741 	for (i = 0; i < rlen; i++)
3742 	{
3743 		/* Buffered char from last chunk */
3744 		if (i == 0 && prevchar == '\r')
3745 		{
3746 			/* Not CRLF, output prevchar */
3747 			if (response[i] != '\n')
3748 			{
3749 				(void) sm_io_putc(e->e_dfp, SM_TIME_DEFAULT,
3750 						  prevchar);
3751 				e->e_msgsize++;
3752 			}
3753 			prevchar = '\0';
3754 		}
3755 
3756 		/* Turn CRLF into LF */
3757 		if (response[i] == '\r')
3758 		{
3759 			/* check if at end of chunk */
3760 			if (i + 1 < rlen)
3761 			{
3762 				/* If LF, strip CR */
3763 				if (response[i + 1] == '\n')
3764 					i++;
3765 			}
3766 			else
3767 			{
3768 				/* check next chunk */
3769 				prevchar = '\r';
3770 				continue;
3771 			}
3772 		}
3773 		(void) sm_io_putc(e->e_dfp, SM_TIME_DEFAULT, response[i]);
3774 		e->e_msgsize++;
3775 	}
3776 	return 0;
3777 }
3778 
3779 /*
3780 **  MTA callouts
3781 */
3782 
3783 /*
3784 **  MILTER_INIT -- open and negotiate with all of the filters
3785 **
3786 **	Parameters:
3787 **		e -- current envelope.
3788 **		state -- return state from response.
3789 **		milters -- milters structure.
3790 **
3791 **	Returns:
3792 **		true iff at least one filter is active
3793 */
3794 
3795 /* ARGSUSED */
3796 bool
milter_init(e,state,milters)3797 milter_init(e, state, milters)
3798 	ENVELOPE *e;
3799 	char *state;
3800 	milters_T *milters;
3801 {
3802 	int i;
3803 
3804 	if (tTd(64, 10))
3805 		sm_dprintf("milter_init\n");
3806 
3807 	memset(milters, '\0', sizeof(*milters));
3808 	*state = SMFIR_CONTINUE;
3809 	if (InputFilters[0] == NULL)
3810 	{
3811 		if (MilterLogLevel > 10)
3812 			sm_syslog(LOG_INFO, e->e_id,
3813 				  "Milter: no active filter");
3814 		return false;
3815 	}
3816 
3817 	for (i = 0; InputFilters[i] != NULL; i++)
3818 	{
3819 		struct milter *m = InputFilters[i];
3820 
3821 		m->mf_sock = milter_open(m, false, e);
3822 		if (m->mf_state == SMFS_ERROR)
3823 		{
3824 			MILTER_CHECK_ERROR(true, continue);
3825 			break;
3826 		}
3827 
3828 		if (m->mf_sock < 0 ||
3829 		    milter_negotiate(m, e, milters) < 0 ||
3830 		    m->mf_state == SMFS_ERROR)
3831 		{
3832 			if (tTd(64, 5))
3833 				sm_dprintf("milter_init(%s): failed to %s\n",
3834 					   m->mf_name,
3835 					   m->mf_sock < 0 ? "open" :
3836 							    "negotiate");
3837 			if (MilterLogLevel > 0)
3838 				sm_syslog(LOG_ERR, e->e_id,
3839 					  "Milter (%s): init failed to %s",
3840 					  m->mf_name,
3841 					  m->mf_sock < 0 ? "open" :
3842 							   "negotiate");
3843 
3844 			/* if negotiation failure, close socket */
3845 			milter_error(m, e);
3846 			MILTER_CHECK_ERROR(true, continue);
3847 			continue;
3848 		}
3849 		if (MilterLogLevel > 9)
3850 			sm_syslog(LOG_INFO, e->e_id,
3851 				  "Milter (%s): init success to %s",
3852 				  m->mf_name,
3853 				  m->mf_sock < 0 ? "open" : "negotiate");
3854 	}
3855 
3856 	/*
3857 	**  If something temp/perm failed with one of the filters,
3858 	**  we won't be using any of them, so clear any existing
3859 	**  connections.
3860 	*/
3861 
3862 	if (*state != SMFIR_CONTINUE)
3863 		milter_quit(e);
3864 
3865 	return true;
3866 }
3867 
3868 /*
3869 **  MILTER_CONNECT -- send connection info to milter filters
3870 **
3871 **	Parameters:
3872 **		hostname -- hostname of remote machine.
3873 **		addr -- address of remote machine.
3874 **		e -- current envelope.
3875 **		state -- return state from response.
3876 **
3877 **	Returns:
3878 **		response string (may be NULL)
3879 */
3880 
3881 char *
milter_connect(hostname,addr,e,state)3882 milter_connect(hostname, addr, e, state)
3883 	char *hostname;
3884 	SOCKADDR addr;
3885 	ENVELOPE *e;
3886 	char *state;
3887 {
3888 	char family;
3889 	unsigned short port;
3890 	char *buf, *bp;
3891 	char *response;
3892 	char *sockinfo = NULL;
3893 	ssize_t s;
3894 # if NETINET6
3895 	char buf6[INET6_ADDRSTRLEN];
3896 # endif /* NETINET6 */
3897 
3898 	if (tTd(64, 10))
3899 		sm_dprintf("milter_connect(%s)\n", hostname);
3900 	if (MilterLogLevel > 9)
3901 		sm_syslog(LOG_INFO, e->e_id, "Milter: connect to filters");
3902 
3903 	/* gather data */
3904 	switch (addr.sa.sa_family)
3905 	{
3906 # if NETUNIX
3907 	  case AF_UNIX:
3908 		family = SMFIA_UNIX;
3909 		port = htons(0);
3910 		sockinfo = addr.sunix.sun_path;
3911 		break;
3912 # endif /* NETUNIX */
3913 
3914 # if NETINET
3915 	  case AF_INET:
3916 		family = SMFIA_INET;
3917 		port = addr.sin.sin_port;
3918 		sockinfo = (char *) inet_ntoa(addr.sin.sin_addr);
3919 		break;
3920 # endif /* NETINET */
3921 
3922 # if NETINET6
3923 	  case AF_INET6:
3924 		if (IN6_IS_ADDR_V4MAPPED(&addr.sin6.sin6_addr))
3925 			family = SMFIA_INET;
3926 		else
3927 			family = SMFIA_INET6;
3928 		port = addr.sin6.sin6_port;
3929 		sockinfo = anynet_ntop(&addr.sin6.sin6_addr, buf6,
3930 				       sizeof(buf6));
3931 		if (sockinfo == NULL)
3932 			sockinfo = "";
3933 		break;
3934 # endif /* NETINET6 */
3935 
3936 	  default:
3937 		family = SMFIA_UNKNOWN;
3938 		break;
3939 	}
3940 
3941 	s = strlen(hostname) + 1 + sizeof(family);
3942 	if (family != SMFIA_UNKNOWN)
3943 		s += sizeof(port) + strlen(sockinfo) + 1;
3944 
3945 	buf = (char *) xalloc(s);
3946 	bp = buf;
3947 
3948 	/* put together data */
3949 	(void) memcpy(bp, hostname, strlen(hostname));
3950 	bp += strlen(hostname);
3951 	*bp++ = '\0';
3952 	(void) memcpy(bp, &family, sizeof(family));
3953 	bp += sizeof(family);
3954 	if (family != SMFIA_UNKNOWN)
3955 	{
3956 		(void) memcpy(bp, &port, sizeof(port));
3957 		bp += sizeof(port);
3958 
3959 		/* include trailing '\0' */
3960 		(void) memcpy(bp, sockinfo, strlen(sockinfo) + 1);
3961 	}
3962 
3963 	response = milter_command(SMFIC_CONNECT, buf, s, SMFIM_CONNECT,
3964 				e, state, "connect", false);
3965 	sm_free(buf); /* XXX */
3966 
3967 	/*
3968 	**  If this message connection is done for,
3969 	**  close the filters.
3970 	*/
3971 
3972 	if (*state != SMFIR_CONTINUE)
3973 	{
3974 		if (MilterLogLevel > 9)
3975 			sm_syslog(LOG_INFO, e->e_id, "Milter: connect, ending");
3976 		milter_quit(e);
3977 	}
3978 	else
3979 		milter_per_connection_check(e);
3980 
3981 	/*
3982 	**  SMFIR_REPLYCODE can't work with connect due to
3983 	**  the requirements of SMTP.  Therefore, ignore the
3984 	**  reply code text but keep the state it would reflect.
3985 	*/
3986 
3987 	if (*state == SMFIR_REPLYCODE)
3988 	{
3989 		if (response != NULL &&
3990 		    *response == '4')
3991 		{
3992 			if (strncmp(response, "421 ", 4) == 0)
3993 				*state = SMFIR_SHUTDOWN;
3994 			else
3995 				*state = SMFIR_TEMPFAIL;
3996 		}
3997 		else
3998 			*state = SMFIR_REJECT;
3999 		if (response != NULL)
4000 		{
4001 			sm_free(response); /* XXX */
4002 			response = NULL;
4003 		}
4004 	}
4005 	return response;
4006 }
4007 
4008 /*
4009 **  MILTER_HELO -- send SMTP HELO/EHLO command info to milter filters
4010 **
4011 **	Parameters:
4012 **		helo -- argument to SMTP HELO/EHLO command.
4013 **		e -- current envelope.
4014 **		state -- return state from response.
4015 **
4016 **	Returns:
4017 **		response string (may be NULL)
4018 */
4019 
4020 char *
milter_helo(helo,e,state)4021 milter_helo(helo, e, state)
4022 	char *helo;
4023 	ENVELOPE *e;
4024 	char *state;
4025 {
4026 	int i;
4027 	char *response;
4028 
4029 	if (tTd(64, 10))
4030 		sm_dprintf("milter_helo(%s)\n", helo);
4031 
4032 	/* HELO/EHLO can come at any point */
4033 	for (i = 0; InputFilters[i] != NULL; i++)
4034 	{
4035 		struct milter *m = InputFilters[i];
4036 
4037 		switch (m->mf_state)
4038 		{
4039 		  case SMFS_INMSG:
4040 			/* abort in message filters */
4041 			milter_abort_filter(m, e);
4042 			/* FALLTHROUGH */
4043 
4044 		  case SMFS_DONE:
4045 			/* reset done filters */
4046 			m->mf_state = SMFS_OPEN;
4047 			break;
4048 		}
4049 	}
4050 
4051 	response = milter_command(SMFIC_HELO, helo, strlen(helo) + 1,
4052 				  SMFIM_HELO, e, state, "helo", false);
4053 	milter_per_connection_check(e);
4054 	return response;
4055 }
4056 
4057 /*
4058 **  MILTER_ENVFROM -- send SMTP MAIL command info to milter filters
4059 **
4060 **	Parameters:
4061 **		args -- SMTP MAIL command args (args[0] == sender).
4062 **		e -- current envelope.
4063 **		state -- return state from response.
4064 **
4065 **	Returns:
4066 **		response string (may be NULL)
4067 */
4068 
4069 char *
milter_envfrom(args,e,state)4070 milter_envfrom(args, e, state)
4071 	char **args;
4072 	ENVELOPE *e;
4073 	char *state;
4074 {
4075 	int i;
4076 	char *buf, *bp;
4077 	char *response;
4078 	ssize_t s;
4079 
4080 	if (tTd(64, 10))
4081 	{
4082 		sm_dprintf("milter_envfrom:");
4083 		for (i = 0; args[i] != NULL; i++)
4084 			sm_dprintf(" %s", args[i]);
4085 		sm_dprintf("\n");
4086 	}
4087 
4088 	/* sanity check */
4089 	if (args[0] == NULL)
4090 	{
4091 		*state = SMFIR_REJECT;
4092 		if (MilterLogLevel > 10)
4093 			sm_syslog(LOG_INFO, e->e_id,
4094 				  "Milter: reject, no sender");
4095 		return NULL;
4096 	}
4097 
4098 	/* new message, so ... */
4099 	for (i = 0; InputFilters[i] != NULL; i++)
4100 	{
4101 		struct milter *m = InputFilters[i];
4102 
4103 		switch (m->mf_state)
4104 		{
4105 		  case SMFS_INMSG:
4106 			/* abort in message filters */
4107 			milter_abort_filter(m, e);
4108 			/* FALLTHROUGH */
4109 
4110 		  case SMFS_DONE:
4111 			/* reset done filters */
4112 			m->mf_state = SMFS_OPEN;
4113 			break;
4114 		}
4115 	}
4116 
4117 	/* put together data */
4118 	s = 0;
4119 	for (i = 0; args[i] != NULL; i++)
4120 		s += strlen(args[i]) + 1;
4121 
4122 	if (s < 0)
4123 	{
4124 		*state = SMFIR_TEMPFAIL;
4125 		return NULL;
4126 	}
4127 
4128 	buf = (char *) xalloc(s);
4129 	bp = buf;
4130 	for (i = 0; args[i] != NULL; i++)
4131 	{
4132 		(void) sm_strlcpy(bp, args[i], s - (bp - buf));
4133 		bp += strlen(bp) + 1;
4134 	}
4135 
4136 	if (MilterLogLevel > 14)
4137 		sm_syslog(LOG_INFO, e->e_id, "Milter: sender: %s", buf);
4138 
4139 	/* send it over */
4140 	response = milter_command(SMFIC_MAIL, buf, s, SMFIM_ENVFROM,
4141 				e, state, "mail", false);
4142 	sm_free(buf); /* XXX */
4143 
4144 	/*
4145 	**  If filter rejects/discards a per message command,
4146 	**  abort the other filters since we are done with the
4147 	**  current message.
4148 	*/
4149 
4150 	MILTER_CHECK_DONE_MSG();
4151 	if (MilterLogLevel > 10 && *state == SMFIR_REJECT)
4152 		sm_syslog(LOG_INFO, e->e_id, "Milter: reject, sender");
4153 	return response;
4154 }
4155 
4156 /*
4157 **  MILTER_ENVRCPT -- send SMTP RCPT command info to milter filters
4158 **
4159 **	Parameters:
4160 **		args -- SMTP MAIL command args (args[0] == recipient).
4161 **		e -- current envelope.
4162 **		state -- return state from response.
4163 **		rcpt_error -- does RCPT have an error?
4164 **
4165 **	Returns:
4166 **		response string (may be NULL)
4167 */
4168 
4169 char *
milter_envrcpt(args,e,state,rcpt_error)4170 milter_envrcpt(args, e, state, rcpt_error)
4171 	char **args;
4172 	ENVELOPE *e;
4173 	char *state;
4174 	bool rcpt_error;
4175 {
4176 	int i;
4177 	char *buf, *bp;
4178 	char *response;
4179 	ssize_t s;
4180 
4181 	if (tTd(64, 10))
4182 	{
4183 		sm_dprintf("milter_envrcpt:");
4184 		for (i = 0; args[i] != NULL; i++)
4185 			sm_dprintf(" %s", args[i]);
4186 		sm_dprintf("\n");
4187 	}
4188 
4189 	/* sanity check */
4190 	if (args[0] == NULL)
4191 	{
4192 		*state = SMFIR_REJECT;
4193 		if (MilterLogLevel > 10)
4194 			sm_syslog(LOG_INFO, e->e_id, "Milter: reject, no rcpt");
4195 		return NULL;
4196 	}
4197 
4198 	/* put together data */
4199 	s = 0;
4200 	for (i = 0; args[i] != NULL; i++)
4201 		s += strlen(args[i]) + 1;
4202 
4203 	if (s < 0)
4204 	{
4205 		*state = SMFIR_TEMPFAIL;
4206 		return NULL;
4207 	}
4208 
4209 	buf = (char *) xalloc(s);
4210 	bp = buf;
4211 	for (i = 0; args[i] != NULL; i++)
4212 	{
4213 		(void) sm_strlcpy(bp, args[i], s - (bp - buf));
4214 		bp += strlen(bp) + 1;
4215 	}
4216 
4217 	if (MilterLogLevel > 14)
4218 		sm_syslog(LOG_INFO, e->e_id, "Milter: rcpts: %s", buf);
4219 
4220 	/* send it over */
4221 	response = milter_command(SMFIC_RCPT, buf, s, SMFIM_ENVRCPT,
4222 				e, state, "rcpt", rcpt_error);
4223 	sm_free(buf); /* XXX */
4224 	return response;
4225 }
4226 
4227 /*
4228 **  MILTER_DATA_CMD -- send SMTP DATA command info to milter filters
4229 **
4230 **	Parameters:
4231 **		e -- current envelope.
4232 **		state -- return state from response.
4233 **
4234 **	Returns:
4235 **		response string (may be NULL)
4236 */
4237 
4238 char *
milter_data_cmd(e,state)4239 milter_data_cmd(e, state)
4240 	ENVELOPE *e;
4241 	char *state;
4242 {
4243 	if (tTd(64, 10))
4244 		sm_dprintf("milter_data_cmd\n");
4245 
4246 	/* send it over */
4247 	return milter_command(SMFIC_DATA, NULL, 0, SMFIM_DATA,
4248 				e, state, "data", false);
4249 }
4250 
4251 /*
4252 **  MILTER_DATA -- send message headers/body and gather final message results
4253 **
4254 **	Parameters:
4255 **		e -- current envelope.
4256 **		state -- return state from response.
4257 **
4258 **	Returns:
4259 **		response string (may be NULL)
4260 **
4261 **	Side effects:
4262 **		- Uses e->e_dfp for access to the body
4263 **		- Can call the various milter action routines to
4264 **		  modify the envelope or message.
4265 */
4266 
4267 /* flow through code using continue; don't wrap in do {} while */
4268 # define MILTER_CHECK_RESULTS() \
4269 	if (m->mf_state == SMFS_ERROR && *state == SMFIR_CONTINUE) \
4270 	{ \
4271 			MILTER_SET_STATE;	\
4272 	} \
4273 	if (*state == SMFIR_ACCEPT || \
4274 	    m->mf_state == SMFS_DONE || \
4275 	    m->mf_state == SMFS_ERROR) \
4276 	{ \
4277 		if (m->mf_state != SMFS_ERROR) \
4278 			m->mf_state = SMFS_DONE; \
4279 		continue;	/* to next filter */ \
4280 	} \
4281 	if (*state != SMFIR_CONTINUE) \
4282 	{ \
4283 		m->mf_state = SMFS_DONE; \
4284 		goto finishup; \
4285 	}
4286 
4287 char *
milter_data(e,state)4288 milter_data(e, state)
4289 	ENVELOPE *e;
4290 	char *state;
4291 {
4292 	bool replbody = false;		/* milter_replbody() called? */
4293 	bool replfailed = false;	/* milter_replbody() failed? */
4294 	bool rewind = false;		/* rewind data file? */
4295 	bool dfopen = false;		/* data file open for writing? */
4296 	bool newfilter;			/* reset on each new filter */
4297 	char rcmd;
4298 	int i;
4299 	int save_errno;
4300 	char *response = NULL;
4301 	time_t eomsent;
4302 	ssize_t rlen;
4303 
4304 	if (tTd(64, 10))
4305 		sm_dprintf("milter_data\n");
4306 
4307 	*state = SMFIR_CONTINUE;
4308 
4309 	/*
4310 	**  XXX: Should actually send body chunks to each filter
4311 	**  a chunk at a time instead of sending the whole body to
4312 	**  each filter in turn.  However, only if the filters don't
4313 	**  change the body.
4314 	*/
4315 
4316 	for (i = 0; InputFilters[i] != NULL; i++)
4317 	{
4318 		int idx;
4319 		char **macros;
4320 		struct milter *m = InputFilters[i];
4321 
4322 		if (*state != SMFIR_CONTINUE &&
4323 		    *state != SMFIR_ACCEPT)
4324 		{
4325 			/*
4326 			**  A previous filter has dealt with the message,
4327 			**  safe to stop processing the filters.
4328 			*/
4329 
4330 			break;
4331 		}
4332 
4333 		/* Now reset state for later evaluation */
4334 		*state = SMFIR_CONTINUE;
4335 		newfilter = true;
4336 
4337 		/* previous problem? */
4338 		if (m->mf_state == SMFS_ERROR)
4339 		{
4340 			MILTER_CHECK_ERROR(false, continue);
4341 			break;
4342 		}
4343 
4344 		/* sanity checks */
4345 		if (m->mf_sock < 0 ||
4346 		    (m->mf_state != SMFS_OPEN && m->mf_state != SMFS_INMSG))
4347 			continue;
4348 
4349 		m->mf_state = SMFS_INMSG;
4350 
4351 		/* check if filter wants the headers */
4352 		if (!bitset(SMFIP_NOHDRS, m->mf_pflags))
4353 		{
4354 			response = milter_headers(m, e, state);
4355 			MILTER_CHECK_RESULTS();
4356 		}
4357 
4358 		/* check if filter wants EOH */
4359 		if (!bitset(SMFIP_NOEOH, m->mf_pflags))
4360 		{
4361 			if (tTd(64, 10))
4362 				sm_dprintf("milter_data: eoh\n");
4363 
4364 			if ((m->mf_lflags & MI_LFLAGS_SYM(SMFIM_EOH)) != 0)
4365 				idx = m->mf_idx;
4366 			else
4367 				idx = 0;
4368 			SM_ASSERT(idx >= 0 && idx <= MAXFILTERS);
4369 			macros = MilterMacros[SMFIM_EOH][idx];
4370 
4371 			if (macros != NULL)
4372 			{
4373 				milter_send_macros(m, macros, SMFIC_EOH, e);
4374 				MILTER_CHECK_RESULTS();
4375 			}
4376 
4377 			/* send it over */
4378 			response = milter_send_command(m, SMFIC_EOH, NULL, 0,
4379 						       e, state, "eoh");
4380 			MILTER_CHECK_RESULTS();
4381 		}
4382 
4383 		/* check if filter wants the body */
4384 		if (!bitset(SMFIP_NOBODY, m->mf_pflags) &&
4385 		    e->e_dfp != NULL)
4386 		{
4387 			rewind = true;
4388 			response = milter_body(m, e, state);
4389 			MILTER_CHECK_RESULTS();
4390 		}
4391 
4392 		if ((m->mf_lflags & MI_LFLAGS_SYM(SMFIM_EOH)) != 0)
4393 			idx = m->mf_idx;
4394 		else
4395 			idx = 0;
4396 		SM_ASSERT(idx >= 0 && idx <= MAXFILTERS);
4397 		macros = MilterMacros[SMFIM_EOM][idx];
4398 		if (macros != NULL)
4399 		{
4400 			milter_send_macros(m, macros, SMFIC_BODYEOB, e);
4401 			MILTER_CHECK_RESULTS();
4402 		}
4403 
4404 		/* send the final body chunk */
4405 		(void) milter_write(m, SMFIC_BODYEOB, NULL, 0,
4406 				    m->mf_timeout[SMFTO_WRITE], e, "eom");
4407 
4408 		/* Get time EOM sent for timeout */
4409 		eomsent = curtime();
4410 
4411 		/* deal with the possibility of multiple responses */
4412 		while (*state == SMFIR_CONTINUE)
4413 		{
4414 			/* Check total timeout from EOM to final ACK/NAK */
4415 			if (m->mf_timeout[SMFTO_EOM] > 0 &&
4416 			    curtime() - eomsent >= m->mf_timeout[SMFTO_EOM])
4417 			{
4418 				if (tTd(64, 5))
4419 					sm_dprintf("milter_data(%s): EOM ACK/NAK timeout\n",
4420 						m->mf_name);
4421 				if (MilterLogLevel > 0)
4422 					sm_syslog(LOG_ERR, e->e_id,
4423 						  "milter_data(%s): EOM ACK/NAK timeout",
4424 						  m->mf_name);
4425 				milter_error(m, e);
4426 				MILTER_CHECK_ERROR(false, break);
4427 				break;
4428 			}
4429 
4430 			response = milter_read(m, &rcmd, &rlen,
4431 					       m->mf_timeout[SMFTO_READ], e,
4432 						"eom");
4433 			if (m->mf_state == SMFS_ERROR)
4434 				break;
4435 
4436 			if (tTd(64, 10))
4437 				sm_dprintf("milter_data(%s): state %c\n",
4438 					   m->mf_name, (char) rcmd);
4439 
4440 			switch (rcmd)
4441 			{
4442 			  case SMFIR_REPLYCODE:
4443 				MILTER_CHECK_REPLYCODE("554 5.7.1 Command rejected");
4444 				if (MilterLogLevel > 12)
4445 					sm_syslog(LOG_INFO, e->e_id, "milter=%s, reject=%s",
4446 						  m->mf_name, response);
4447 				*state = rcmd;
4448 				m->mf_state = SMFS_DONE;
4449 				break;
4450 
4451 			  case SMFIR_REJECT: /* log msg at end of function */
4452 				if (MilterLogLevel > 12)
4453 					sm_syslog(LOG_INFO, e->e_id, "milter=%s, reject",
4454 						  m->mf_name);
4455 				*state = rcmd;
4456 				m->mf_state = SMFS_DONE;
4457 				break;
4458 
4459 			  case SMFIR_DISCARD:
4460 				if (MilterLogLevel > 12)
4461 					sm_syslog(LOG_INFO, e->e_id, "milter=%s, discard",
4462 						  m->mf_name);
4463 				*state = rcmd;
4464 				m->mf_state = SMFS_DONE;
4465 				break;
4466 
4467 			  case SMFIR_TEMPFAIL:
4468 				if (MilterLogLevel > 12)
4469 					sm_syslog(LOG_INFO, e->e_id, "milter=%s, tempfail",
4470 						  m->mf_name);
4471 				*state = rcmd;
4472 				m->mf_state = SMFS_DONE;
4473 				break;
4474 
4475 			  case SMFIR_CONTINUE:
4476 			  case SMFIR_ACCEPT:
4477 				/* this filter is done with message */
4478 				if (replfailed)
4479 					*state = SMFIR_TEMPFAIL;
4480 				else
4481 					*state = SMFIR_ACCEPT;
4482 				m->mf_state = SMFS_DONE;
4483 				break;
4484 
4485 			  case SMFIR_PROGRESS:
4486 				break;
4487 
4488 			  case SMFIR_QUARANTINE:
4489 				if (!bitset(SMFIF_QUARANTINE, m->mf_fflags))
4490 				{
4491 					if (MilterLogLevel > 9)
4492 						sm_syslog(LOG_WARNING, e->e_id,
4493 							  "milter_data(%s): lied about quarantining, honoring request anyway",
4494 							  m->mf_name);
4495 				}
4496 				if (response == NULL)
4497 					response = newstr("");
4498 				if (MilterLogLevel > 3)
4499 					sm_syslog(LOG_INFO, e->e_id,
4500 						  "milter=%s, quarantine=%s",
4501 						  m->mf_name, response);
4502 				e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool,
4503 								 response);
4504 				macdefine(&e->e_macro, A_PERM,
4505 					  macid("{quarantine}"), e->e_quarmsg);
4506 				break;
4507 
4508 			  case SMFIR_ADDHEADER:
4509 				if (!bitset(SMFIF_ADDHDRS, m->mf_fflags))
4510 				{
4511 					if (MilterLogLevel > 9)
4512 						sm_syslog(LOG_WARNING, e->e_id,
4513 							  "milter_data(%s): lied about adding headers, honoring request anyway",
4514 							  m->mf_name);
4515 				}
4516 				milter_addheader(m, response, rlen, e);
4517 				break;
4518 
4519 			  case SMFIR_INSHEADER:
4520 				if (!bitset(SMFIF_ADDHDRS, m->mf_fflags))
4521 				{
4522 					if (MilterLogLevel > 9)
4523 						sm_syslog(LOG_WARNING, e->e_id,
4524 							  "milter_data(%s): lied about adding headers, honoring request anyway",
4525 							  m->mf_name);
4526 				}
4527 				milter_insheader(m, response, rlen, e);
4528 				break;
4529 
4530 			  case SMFIR_CHGHEADER:
4531 				if (!bitset(SMFIF_CHGHDRS, m->mf_fflags))
4532 				{
4533 					if (MilterLogLevel > 9)
4534 						sm_syslog(LOG_WARNING, e->e_id,
4535 							  "milter_data(%s): lied about changing headers, honoring request anyway",
4536 							  m->mf_name);
4537 				}
4538 				milter_changeheader(m, response, rlen, e);
4539 				break;
4540 
4541 			  case SMFIR_CHGFROM:
4542 				if (!bitset(SMFIF_CHGFROM, m->mf_fflags))
4543 				{
4544 					if (MilterLogLevel > 9)
4545 						sm_syslog(LOG_WARNING, e->e_id,
4546 							  "milter_data(%s) lied about changing sender, honoring request anyway",
4547 							  m->mf_name);
4548 				}
4549 				milter_chgfrom(response, rlen, e);
4550 				break;
4551 
4552 			  case SMFIR_ADDRCPT:
4553 				if (!bitset(SMFIF_ADDRCPT, m->mf_fflags))
4554 				{
4555 					if (MilterLogLevel > 9)
4556 						sm_syslog(LOG_WARNING, e->e_id,
4557 							  "milter_data(%s) lied about adding recipients, honoring request anyway",
4558 							  m->mf_name);
4559 				}
4560 				milter_addrcpt(response, rlen, e);
4561 				break;
4562 
4563 			  case SMFIR_ADDRCPT_PAR:
4564 				if (!bitset(SMFIF_ADDRCPT_PAR, m->mf_fflags))
4565 				{
4566 					if (MilterLogLevel > 9)
4567 						sm_syslog(LOG_WARNING, e->e_id,
4568 							  "milter_data(%s) lied about adding recipients with parameters, honoring request anyway",
4569 							  m->mf_name);
4570 				}
4571 				milter_addrcpt_par(response, rlen, e);
4572 				break;
4573 
4574 			  case SMFIR_DELRCPT:
4575 				if (!bitset(SMFIF_DELRCPT, m->mf_fflags))
4576 				{
4577 					if (MilterLogLevel > 9)
4578 						sm_syslog(LOG_WARNING, e->e_id,
4579 							  "milter_data(%s): lied about removing recipients, honoring request anyway",
4580 							  m->mf_name);
4581 				}
4582 				milter_delrcpt(response, rlen, e);
4583 				break;
4584 
4585 			  case SMFIR_REPLBODY:
4586 				if (!bitset(SMFIF_MODBODY, m->mf_fflags))
4587 				{
4588 					if (MilterLogLevel > 0)
4589 						sm_syslog(LOG_ERR, e->e_id,
4590 							  "milter_data(%s): lied about replacing body, rejecting request and tempfailing message",
4591 							  m->mf_name);
4592 					replfailed = true;
4593 					break;
4594 				}
4595 
4596 				/* already failed in attempt */
4597 				if (replfailed)
4598 					break;
4599 
4600 				if (!dfopen)
4601 				{
4602 					if (milter_reopen_df(e) < 0)
4603 					{
4604 						replfailed = true;
4605 						break;
4606 					}
4607 					dfopen = true;
4608 					rewind = true;
4609 				}
4610 
4611 				if (milter_replbody(response, rlen,
4612 						    newfilter, e) < 0)
4613 					replfailed = true;
4614 				newfilter = false;
4615 				replbody = true;
4616 				break;
4617 
4618 			  default:
4619 				/* Invalid response to command */
4620 				if (MilterLogLevel > 0)
4621 					sm_syslog(LOG_ERR, e->e_id,
4622 						  "milter_data(%s): returned bogus response %c",
4623 						  m->mf_name, rcmd);
4624 				milter_error(m, e);
4625 				break;
4626 			}
4627 			if (rcmd != SMFIR_REPLYCODE && response != NULL)
4628 			{
4629 				sm_free(response); /* XXX */
4630 				response = NULL;
4631 			}
4632 
4633 			if (m->mf_state == SMFS_ERROR)
4634 				break;
4635 		}
4636 
4637 		if (replbody && !replfailed)
4638 		{
4639 			/* flush possible buffered character */
4640 			milter_replbody(NULL, 0, !replbody, e);
4641 			replbody = false;
4642 		}
4643 
4644 		if (m->mf_state == SMFS_ERROR)
4645 		{
4646 			MILTER_CHECK_ERROR(false, continue);
4647 			goto finishup;
4648 		}
4649 	}
4650 
4651 finishup:
4652 	/* leave things in the expected state if we touched it */
4653 	if (replfailed)
4654 	{
4655 		if (*state == SMFIR_CONTINUE ||
4656 		    *state == SMFIR_ACCEPT)
4657 		{
4658 			*state = SMFIR_TEMPFAIL;
4659 			SM_FREE_CLR(response);
4660 		}
4661 
4662 		if (dfopen)
4663 		{
4664 			(void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
4665 			e->e_dfp = NULL;
4666 			e->e_flags &= ~EF_HAS_DF;
4667 			dfopen = false;
4668 		}
4669 		rewind = false;
4670 	}
4671 
4672 	if ((dfopen && milter_reset_df(e) < 0) ||
4673 	    (rewind && bfrewind(e->e_dfp) < 0))
4674 	{
4675 		save_errno = errno;
4676 		ExitStat = EX_IOERR;
4677 
4678 		/*
4679 		**  If filter told us to keep message but we had
4680 		**  an error, we can't really keep it, tempfail it.
4681 		*/
4682 
4683 		if (*state == SMFIR_CONTINUE ||
4684 		    *state == SMFIR_ACCEPT)
4685 		{
4686 			*state = SMFIR_TEMPFAIL;
4687 			SM_FREE_CLR(response);
4688 		}
4689 
4690 		errno = save_errno;
4691 		syserr("milter_data: %s/%cf%s: read error",
4692 		       qid_printqueue(e->e_qgrp, e->e_qdir),
4693 		       DATAFL_LETTER, e->e_id);
4694 	}
4695 
4696 	MILTER_CHECK_DONE_MSG();
4697 	if (MilterLogLevel > 10 && *state == SMFIR_REJECT)
4698 		sm_syslog(LOG_INFO, e->e_id, "Milter: reject, data");
4699 	return response;
4700 }
4701 
4702 /*
4703 **  MILTER_UNKNOWN -- send any unrecognized or unimplemented command
4704 **			string to milter filters
4705 **
4706 **	Parameters:
4707 **		smtpcmd -- the string itself.
4708 **		e -- current envelope.
4709 **		state -- return state from response.
4710 **
4711 **
4712 **	Returns:
4713 **		response string (may be NULL)
4714 */
4715 
4716 char *
milter_unknown(smtpcmd,e,state)4717 milter_unknown(smtpcmd, e, state)
4718 	char *smtpcmd;
4719 	ENVELOPE *e;
4720 	char *state;
4721 {
4722 	if (tTd(64, 10))
4723 		sm_dprintf("milter_unknown(%s)\n", smtpcmd);
4724 
4725 	return milter_command(SMFIC_UNKNOWN, smtpcmd, strlen(smtpcmd) + 1,
4726 				SMFIM_NOMACROS, e, state, "unknown", false);
4727 }
4728 
4729 /*
4730 **  MILTER_QUIT -- informs the filter(s) we are done and closes connection(s)
4731 **
4732 **	Parameters:
4733 **		e -- current envelope.
4734 **
4735 **	Returns:
4736 **		none
4737 */
4738 
4739 void
milter_quit(e)4740 milter_quit(e)
4741 	ENVELOPE *e;
4742 {
4743 	int i;
4744 
4745 	if (tTd(64, 10))
4746 		sm_dprintf("milter_quit(%s)\n", e->e_id);
4747 
4748 	for (i = 0; InputFilters[i] != NULL; i++)
4749 		milter_quit_filter(InputFilters[i], e);
4750 }
4751 
4752 /*
4753 **  MILTER_ABORT -- informs the filter(s) that we are aborting current message
4754 **
4755 **	Parameters:
4756 **		e -- current envelope.
4757 **
4758 **	Returns:
4759 **		none
4760 */
4761 
4762 void
milter_abort(e)4763 milter_abort(e)
4764 	ENVELOPE *e;
4765 {
4766 	int i;
4767 
4768 	if (tTd(64, 10))
4769 		sm_dprintf("milter_abort\n");
4770 
4771 	for (i = 0; InputFilters[i] != NULL; i++)
4772 	{
4773 		struct milter *m = InputFilters[i];
4774 
4775 		/* sanity checks */
4776 		if (m->mf_sock < 0 || m->mf_state != SMFS_INMSG)
4777 			continue;
4778 
4779 		milter_abort_filter(m, e);
4780 	}
4781 }
4782 #endif /* MILTER */
4783