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