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