source: trunk/third/sendmail/sendmail/milter.c @ 19204

Revision 19204, 82.6 KB checked in by zacheiss, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19203, which included commits to RCS files with non-trunk default branches.
Line 
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 1.1.1.1 2003-04-08 15:09:16 zacheiss Exp $")
14
15#if MILTER
16# include <libmilter/mfapi.h>
17# include <libmilter/mfdef.h>
18
19# include <errno.h>
20# include <sys/time.h>
21
22# if NETINET || NETINET6
23#  include <arpa/inet.h>
24# endif /* NETINET || NETINET6 */
25
26# include <sm/fdset.h>
27
28static void     milter_connect_timeout __P((void));
29static void     milter_error __P((struct milter *, ENVELOPE *));
30static int      milter_open __P((struct milter *, bool, ENVELOPE *));
31static void     milter_parse_timeouts __P((char *, struct milter *));
32
33static char *MilterConnectMacros[MAXFILTERMACROS + 1];
34static char *MilterHeloMacros[MAXFILTERMACROS + 1];
35static char *MilterEnvFromMacros[MAXFILTERMACROS + 1];
36static char *MilterEnvRcptMacros[MAXFILTERMACROS + 1];
37
38# define MILTER_CHECK_DONE_MSG() \
39        if (*state == SMFIR_REPLYCODE || \
40            *state == SMFIR_REJECT || \
41            *state == SMFIR_DISCARD || \
42            *state == SMFIR_TEMPFAIL) \
43        { \
44                /* Abort the filters to let them know we are done with msg */ \
45                milter_abort(e); \
46        }
47
48# 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                     },
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;
1491
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, 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, 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        if (tTd(64, 10))
2811                sm_dprintf("milter_addrcpt: ");
2812
2813        /* sanity checks */
2814        if (response == NULL)
2815        {
2816                if (tTd(64, 10))
2817                        sm_dprintf("NULL response\n");
2818                return;
2819        }
2820
2821        if (*response == '\0' ||
2822            strlen(response) + 1 != (size_t) rlen)
2823        {
2824                if (tTd(64, 10))
2825                        sm_dprintf("didn't follow protocol (total len %d != rlen %d)\n",
2826                                   (int) strlen(response), (int) (rlen - 1));
2827                return;
2828        }
2829
2830        if (tTd(64, 10))
2831                sm_dprintf("%s\n", response);
2832        if (MilterLogLevel > 8)
2833                sm_syslog(LOG_INFO, e->e_id, "Milter add: rcpt: %s", response);
2834        (void) sendtolist(response, NULLADDR, &e->e_sendqueue, 0, e);
2835        return;
2836}
2837/*
2838**  MILTER_DELRCPT -- Delete the supplied recipient from the message
2839**
2840**      Parameters:
2841**              response -- encoded form of recipient address.
2842**              rlen -- length of response.
2843**              e -- current envelope.
2844**
2845**      Returns:
2846**              none
2847*/
2848
2849static void
2850milter_delrcpt(response, rlen, e)
2851        char *response;
2852        ssize_t rlen;
2853        ENVELOPE *e;
2854{
2855        if (tTd(64, 10))
2856                sm_dprintf("milter_delrcpt: ");
2857
2858        /* sanity checks */
2859        if (response == NULL)
2860        {
2861                if (tTd(64, 10))
2862                        sm_dprintf("NULL response\n");
2863                return;
2864        }
2865
2866        if (*response == '\0' ||
2867            strlen(response) + 1 != (size_t) rlen)
2868        {
2869                if (tTd(64, 10))
2870                        sm_dprintf("didn't follow protocol (total len)\n");
2871                return;
2872        }
2873
2874        if (tTd(64, 10))
2875                sm_dprintf("%s\n", response);
2876        if (MilterLogLevel > 8)
2877                sm_syslog(LOG_INFO, e->e_id, "Milter delete: rcpt %s",
2878                          response);
2879        (void) removefromlist(response, &e->e_sendqueue, e);
2880        return;
2881}
2882/*
2883**  MILTER_REPLBODY -- Replace the current data file with new body
2884**
2885**      Parameters:
2886**              response -- encoded form of new body.
2887**              rlen -- length of response.
2888**              newfilter -- if first time called by a new filter
2889**              e -- current envelope.
2890**
2891**      Returns:
2892**              0 upon success, -1 upon failure
2893*/
2894
2895static int
2896milter_replbody(response, rlen, newfilter, e)
2897        char *response;
2898        ssize_t rlen;
2899        bool newfilter;
2900        ENVELOPE *e;
2901{
2902        static char prevchar;
2903        int i;
2904
2905        if (tTd(64, 10))
2906                sm_dprintf("milter_replbody\n");
2907
2908        /* If a new filter, reset previous character and truncate data file */
2909        if (newfilter)
2910        {
2911                off_t prevsize;
2912                char dfname[MAXPATHLEN];
2913
2914                (void) sm_strlcpy(dfname, queuename(e, DATAFL_LETTER),
2915                                  sizeof dfname);
2916
2917                /* Reset prevchar */
2918                prevchar = '\0';
2919
2920                /* Get the current data file information */
2921                prevsize = sm_io_getinfo(e->e_dfp, SM_IO_WHAT_SIZE, NULL);
2922                if (prevsize < 0)
2923                        prevsize = 0;
2924
2925                /* truncate current data file */
2926                if (sm_io_getinfo(e->e_dfp, SM_IO_WHAT_ISTYPE, BF_FILE_TYPE))
2927                {
2928                        if (sm_io_setinfo(e->e_dfp, SM_BF_TRUNCATE, NULL) < 0)
2929                        {
2930                                MILTER_DF_ERROR("milter_replbody: sm_io truncate %s: %s");
2931                                return -1;
2932                        }
2933                }
2934                else
2935                {
2936                        int err;
2937
2938                        err = sm_io_error(e->e_dfp);
2939                        (void) sm_io_flush(e->e_dfp, SM_TIME_DEFAULT);
2940
2941                        /*
2942                        **  Clear error if tried to fflush()
2943                        **  a read-only file pointer and
2944                        **  there wasn't a previous error.
2945                        */
2946
2947                        if (err == 0)
2948                                sm_io_clearerr(e->e_dfp);
2949
2950                        /* errno is set implicitly by fseek() before return */
2951                        err = sm_io_seek(e->e_dfp, SM_TIME_DEFAULT,
2952                                         0, SEEK_SET);
2953                        if (err < 0)
2954                        {
2955                                MILTER_DF_ERROR("milter_replbody: sm_io_seek %s: %s");
2956                                return -1;
2957                        }
2958# if NOFTRUNCATE
2959                        /* XXX: Not much we can do except rewind it */
2960                        errno = EINVAL;
2961                        MILTER_DF_ERROR("milter_replbody: ftruncate not available on this platform (%s:%s)");
2962                        return -1;
2963# else /* NOFTRUNCATE */
2964                        err = ftruncate(sm_io_getinfo(e->e_dfp,
2965                                                      SM_IO_WHAT_FD, NULL),
2966                                        0);
2967                        if (err < 0)
2968                        {
2969                                MILTER_DF_ERROR("milter_replbody: sm_io ftruncate %s: %s");
2970                                return -1;
2971                        }
2972# endif /* NOFTRUNCATE */
2973                }
2974
2975                if (prevsize > e->e_msgsize)
2976                        e->e_msgsize = 0;
2977                else
2978                        e->e_msgsize -= prevsize;
2979        }
2980
2981        if (newfilter && MilterLogLevel > 8)
2982                sm_syslog(LOG_INFO, e->e_id, "Milter message: body replaced");
2983
2984        if (response == NULL)
2985        {
2986                /* Flush the buffered '\r' */
2987                if (prevchar == '\r')
2988                {
2989                        (void) sm_io_putc(e->e_dfp, SM_TIME_DEFAULT, prevchar);
2990                        e->e_msgsize++;
2991                }
2992                return 0;
2993        }
2994
2995        for (i = 0; i < rlen; i++)
2996        {
2997                /* Buffered char from last chunk */
2998                if (i == 0 && prevchar == '\r')
2999                {
3000                        /* Not CRLF, output prevchar */
3001                        if (response[i] != '\n')
3002                        {
3003                                (void) sm_io_putc(e->e_dfp, SM_TIME_DEFAULT,
3004                                                  prevchar);
3005                                e->e_msgsize++;
3006                        }
3007                        prevchar = '\0';
3008                }
3009
3010                /* Turn CRLF into LF */
3011                if (response[i] == '\r')
3012                {
3013                        /* check if at end of chunk */
3014                        if (i + 1 < rlen)
3015                        {
3016                                /* If LF, strip CR */
3017                                if (response[i + 1] == '\n')
3018                                        i++;
3019                        }
3020                        else
3021                        {
3022                                /* check next chunk */
3023                                prevchar = '\r';
3024                                continue;
3025                        }
3026                }
3027                (void) sm_io_putc(e->e_dfp, SM_TIME_DEFAULT, response[i]);
3028                e->e_msgsize++;
3029        }
3030        return 0;
3031}
3032
3033/*
3034**  MTA callouts
3035*/
3036
3037/*
3038**  MILTER_INIT -- open and negotiate with all of the filters
3039**
3040**      Parameters:
3041**              e -- current envelope.
3042**              state -- return state from response.
3043**
3044**      Returns:
3045**              true iff at least one filter is active
3046*/
3047
3048/* ARGSUSED */
3049bool
3050milter_init(e, state)
3051        ENVELOPE *e;
3052        char *state;
3053{
3054        int i;
3055
3056        if (tTd(64, 10))
3057                sm_dprintf("milter_init\n");
3058
3059        *state = SMFIR_CONTINUE;
3060        if (InputFilters[0] == NULL)
3061        {
3062                if (MilterLogLevel > 10)
3063                        sm_syslog(LOG_INFO, e->e_id,
3064                                  "Milter: no active filter");
3065                return false;
3066        }
3067
3068        for (i = 0; InputFilters[i] != NULL; i++)
3069        {
3070                struct milter *m = InputFilters[i];
3071
3072                m->mf_sock = milter_open(m, false, e);
3073                if (m->mf_state == SMFS_ERROR)
3074                {
3075                        MILTER_CHECK_ERROR(true, continue);
3076                        break;
3077                }
3078
3079                if (m->mf_sock < 0 ||
3080                    milter_negotiate(m, e) < 0 ||
3081                    m->mf_state == SMFS_ERROR)
3082                {
3083                        if (tTd(64, 5))
3084                                sm_dprintf("milter_init(%s): failed to %s\n",
3085                                           m->mf_name,
3086                                           m->mf_sock < 0 ? "open" :
3087                                                            "negotiate");
3088                        if (MilterLogLevel > 0)
3089                                sm_syslog(LOG_ERR, e->e_id,
3090                                          "Milter (%s): init failed to %s",
3091                                          m->mf_name,
3092                                          m->mf_sock < 0 ? "open" :
3093                                                           "negotiate");
3094
3095                        /* if negotation failure, close socket */
3096                        milter_error(m, e);
3097                        MILTER_CHECK_ERROR(true, continue);
3098                }
3099                if (MilterLogLevel > 9)
3100                        sm_syslog(LOG_INFO, e->e_id,
3101                                  "Milter (%s): init success to %s",
3102                                  m->mf_name,
3103                                  m->mf_sock < 0 ? "open" : "negotiate");
3104        }
3105
3106        /*
3107        **  If something temp/perm failed with one of the filters,
3108        **  we won't be using any of them, so clear any existing
3109        **  connections.
3110        */
3111
3112        if (*state != SMFIR_CONTINUE)
3113                milter_quit(e);
3114
3115        return true;
3116}
3117/*
3118**  MILTER_CONNECT -- send connection info to milter filters
3119**
3120**      Parameters:
3121**              hostname -- hostname of remote machine.
3122**              addr -- address of remote machine.
3123**              e -- current envelope.
3124**              state -- return state from response.
3125**
3126**      Returns:
3127**              response string (may be NULL)
3128*/
3129
3130char *
3131milter_connect(hostname, addr, e, state)
3132        char *hostname;
3133        SOCKADDR addr;
3134        ENVELOPE *e;
3135        char *state;
3136{
3137        char family;
3138        unsigned short port;
3139        char *buf, *bp;
3140        char *response;
3141        char *sockinfo = NULL;
3142        ssize_t s;
3143# if NETINET6
3144        char buf6[INET6_ADDRSTRLEN];
3145# endif /* NETINET6 */
3146
3147        if (tTd(64, 10))
3148                sm_dprintf("milter_connect(%s)\n", hostname);
3149        if (MilterLogLevel > 9)
3150                sm_syslog(LOG_INFO, e->e_id, "Milter: connect to filters");
3151
3152        /* gather data */
3153        switch (addr.sa.sa_family)
3154        {
3155# if NETUNIX
3156          case AF_UNIX:
3157                family = SMFIA_UNIX;
3158                port = htons(0);
3159                sockinfo = addr.sunix.sun_path;
3160                break;
3161# endif /* NETUNIX */
3162
3163# if NETINET
3164          case AF_INET:
3165                family = SMFIA_INET;
3166                port = addr.sin.sin_port;
3167                sockinfo = (char *) inet_ntoa(addr.sin.sin_addr);
3168                break;
3169# endif /* NETINET */
3170
3171# if NETINET6
3172          case AF_INET6:
3173                if (IN6_IS_ADDR_V4MAPPED(&addr.sin6.sin6_addr))
3174                        family = SMFIA_INET;
3175                else
3176                        family = SMFIA_INET6;
3177                port = addr.sin6.sin6_port;
3178                sockinfo = anynet_ntop(&addr.sin6.sin6_addr, buf6,
3179                                       sizeof buf6);
3180                if (sockinfo == NULL)
3181                        sockinfo = "";
3182                break;
3183# endif /* NETINET6 */
3184
3185          default:
3186                family = SMFIA_UNKNOWN;
3187                break;
3188        }
3189
3190        s = strlen(hostname) + 1 + sizeof(family);
3191        if (family != SMFIA_UNKNOWN)
3192                s += sizeof(port) + strlen(sockinfo) + 1;
3193
3194        buf = (char *) xalloc(s);
3195        bp = buf;
3196
3197        /* put together data */
3198        (void) memcpy(bp, hostname, strlen(hostname));
3199        bp += strlen(hostname);
3200        *bp++ = '\0';
3201        (void) memcpy(bp, &family, sizeof family);
3202        bp += sizeof family;
3203        if (family != SMFIA_UNKNOWN)
3204        {
3205                (void) memcpy(bp, &port, sizeof port);
3206                bp += sizeof port;
3207
3208                /* include trailing '\0' */
3209                (void) memcpy(bp, sockinfo, strlen(sockinfo) + 1);
3210        }
3211
3212        response = milter_command(SMFIC_CONNECT, buf, s,
3213                                  MilterConnectMacros, e, state);
3214        sm_free(buf); /* XXX */
3215
3216        /*
3217        **  If this message connection is done for,
3218        **  close the filters.
3219        */
3220
3221        if (*state != SMFIR_CONTINUE)
3222        {
3223                if (MilterLogLevel > 9)
3224                        sm_syslog(LOG_INFO, e->e_id, "Milter: connect, ending");
3225                milter_quit(e);
3226        }
3227        else
3228                milter_per_connection_check(e);
3229
3230        /*
3231        **  SMFIR_REPLYCODE can't work with connect due to
3232        **  the requirements of SMTP.  Therefore, ignore the
3233        **  reply code text but keep the state it would reflect.
3234        */
3235
3236        if (*state == SMFIR_REPLYCODE)
3237        {
3238                if (response != NULL &&
3239                    *response == '4')
3240                {
3241#if _FFR_MILTER_421
3242                        if (strncmp(response, "421 ", 4) == 0)
3243                                *state = SMFIR_SHUTDOWN;
3244                        else
3245#endif /* _FFR_MILTER_421 */
3246                                *state = SMFIR_TEMPFAIL;
3247                }
3248                else
3249                        *state = SMFIR_REJECT;
3250                if (response != NULL)
3251                {
3252                        sm_free(response); /* XXX */
3253                        response = NULL;
3254                }
3255        }
3256        return response;
3257}
3258/*
3259**  MILTER_HELO -- send SMTP HELO/EHLO command info to milter filters
3260**
3261**      Parameters:
3262**              helo -- argument to SMTP HELO/EHLO command.
3263**              e -- current envelope.
3264**              state -- return state from response.
3265**
3266**      Returns:
3267**              response string (may be NULL)
3268*/
3269
3270char *
3271milter_helo(helo, e, state)
3272        char *helo;
3273        ENVELOPE *e;
3274        char *state;
3275{
3276        int i;
3277        char *response;
3278
3279        if (tTd(64, 10))
3280                sm_dprintf("milter_helo(%s)\n", helo);
3281
3282        /* HELO/EHLO can come at any point */
3283        for (i = 0; InputFilters[i] != NULL; i++)
3284        {
3285                struct milter *m = InputFilters[i];
3286
3287                switch (m->mf_state)
3288                {
3289                  case SMFS_INMSG:
3290                        /* abort in message filters */
3291                        milter_abort_filter(m, e);
3292                        /* FALLTHROUGH */
3293
3294                  case SMFS_DONE:
3295                        /* reset done filters */
3296                        m->mf_state = SMFS_OPEN;
3297                        break;
3298                }
3299        }
3300
3301        response = milter_command(SMFIC_HELO, helo, strlen(helo) + 1,
3302                                  MilterHeloMacros, e, state);
3303        milter_per_connection_check(e);
3304        return response;
3305}
3306/*
3307**  MILTER_ENVFROM -- send SMTP MAIL command info to milter filters
3308**
3309**      Parameters:
3310**              args -- SMTP MAIL command args (args[0] == sender).
3311**              e -- current envelope.
3312**              state -- return state from response.
3313**
3314**      Returns:
3315**              response string (may be NULL)
3316*/
3317
3318char *
3319milter_envfrom(args, e, state)
3320        char **args;
3321        ENVELOPE *e;
3322        char *state;
3323{
3324        int i;
3325        char *buf, *bp;
3326        char *response;
3327        ssize_t s;
3328
3329        if (tTd(64, 10))
3330        {
3331                sm_dprintf("milter_envfrom:");
3332                for (i = 0; args[i] != NULL; i++)
3333                        sm_dprintf(" %s", args[i]);
3334                sm_dprintf("\n");
3335        }
3336
3337        /* sanity check */
3338        if (args[0] == NULL)
3339        {
3340                *state = SMFIR_REJECT;
3341                if (MilterLogLevel > 10)
3342                        sm_syslog(LOG_INFO, e->e_id,
3343                                  "Milter: reject, no sender");
3344                return NULL;
3345        }
3346
3347        /* new message, so ... */
3348        for (i = 0; InputFilters[i] != NULL; i++)
3349        {
3350                struct milter *m = InputFilters[i];
3351
3352                switch (m->mf_state)
3353                {
3354                  case SMFS_INMSG:
3355                        /* abort in message filters */
3356                        milter_abort_filter(m, e);
3357                        /* FALLTHROUGH */
3358
3359                  case SMFS_DONE:
3360                        /* reset done filters */
3361                        m->mf_state = SMFS_OPEN;
3362                        break;
3363                }
3364        }
3365
3366        /* put together data */
3367        s = 0;
3368        for (i = 0; args[i] != NULL; i++)
3369                s += strlen(args[i]) + 1;
3370
3371        if (s < 0)
3372        {
3373                *state = SMFIR_TEMPFAIL;
3374                return NULL;
3375        }
3376
3377        buf = (char *) xalloc(s);
3378        bp = buf;
3379        for (i = 0; args[i] != NULL; i++)
3380        {
3381                (void) sm_strlcpy(bp, args[i], s - (bp - buf));
3382                bp += strlen(bp) + 1;
3383        }
3384
3385        if (MilterLogLevel > 14)
3386                sm_syslog(LOG_INFO, e->e_id, "Milter: senders: %s", buf);
3387
3388        /* send it over */
3389        response = milter_command(SMFIC_MAIL, buf, s,
3390                                  MilterEnvFromMacros, e, state);
3391        sm_free(buf); /* XXX */
3392
3393        /*
3394        **  If filter rejects/discards a per message command,
3395        **  abort the other filters since we are done with the
3396        **  current message.
3397        */
3398
3399        MILTER_CHECK_DONE_MSG();
3400        if (MilterLogLevel > 10 && *state == SMFIR_REJECT)
3401                sm_syslog(LOG_INFO, e->e_id, "Milter: reject, senders");
3402        return response;
3403}
3404/*
3405**  MILTER_ENVRCPT -- send SMTP RCPT command info to milter filters
3406**
3407**      Parameters:
3408**              args -- SMTP MAIL command args (args[0] == recipient).
3409**              e -- current envelope.
3410**              state -- return state from response.
3411**
3412**      Returns:
3413**              response string (may be NULL)
3414*/
3415
3416char *
3417milter_envrcpt(args, e, state)
3418        char **args;
3419        ENVELOPE *e;
3420        char *state;
3421{
3422        int i;
3423        char *buf, *bp;
3424        char *response;
3425        ssize_t s;
3426
3427        if (tTd(64, 10))
3428        {
3429                sm_dprintf("milter_envrcpt:");
3430                for (i = 0; args[i] != NULL; i++)
3431                        sm_dprintf(" %s", args[i]);
3432                sm_dprintf("\n");
3433        }
3434
3435        /* sanity check */
3436        if (args[0] == NULL)
3437        {
3438                *state = SMFIR_REJECT;
3439                if (MilterLogLevel > 10)
3440                        sm_syslog(LOG_INFO, e->e_id, "Milter: reject, no rcpt");
3441                return NULL;
3442        }
3443
3444        /* put together data */
3445        s = 0;
3446        for (i = 0; args[i] != NULL; i++)
3447                s += strlen(args[i]) + 1;
3448
3449        if (s < 0)
3450        {
3451                *state = SMFIR_TEMPFAIL;
3452                return NULL;
3453        }
3454
3455        buf = (char *) xalloc(s);
3456        bp = buf;
3457        for (i = 0; args[i] != NULL; i++)
3458        {
3459                (void) sm_strlcpy(bp, args[i], s - (bp - buf));
3460                bp += strlen(bp) + 1;
3461        }
3462
3463        if (MilterLogLevel > 14)
3464                sm_syslog(LOG_INFO, e->e_id, "Milter: rcpts: %s", buf);
3465
3466        /* send it over */
3467        response = milter_command(SMFIC_RCPT, buf, s,
3468                                  MilterEnvRcptMacros, e, state);
3469        sm_free(buf); /* XXX */
3470        return response;
3471}
3472/*
3473**  MILTER_DATA -- send message headers/body and gather final message results
3474**
3475**      Parameters:
3476**              e -- current envelope.
3477**              state -- return state from response.
3478**
3479**      Returns:
3480**              response string (may be NULL)
3481**
3482**      Side effects:
3483**              - Uses e->e_dfp for access to the body
3484**              - Can call the various milter action routines to
3485**                modify the envelope or message.
3486*/
3487
3488# define MILTER_CHECK_RESULTS() \
3489        if (*state == SMFIR_ACCEPT || \
3490            m->mf_state == SMFS_DONE || \
3491            m->mf_state == SMFS_ERROR) \
3492        { \
3493                if (m->mf_state != SMFS_ERROR) \
3494                        m->mf_state = SMFS_DONE; \
3495                continue;       /* to next filter */ \
3496        } \
3497        if (*state != SMFIR_CONTINUE) \
3498        { \
3499                m->mf_state = SMFS_DONE; \
3500                goto finishup; \
3501        }
3502
3503char *
3504milter_data(e, state)
3505        ENVELOPE *e;
3506        char *state;
3507{
3508        bool replbody = false;          /* milter_replbody() called? */
3509        bool replfailed = false;        /* milter_replbody() failed? */
3510        bool rewind = false;            /* rewind data file? */
3511        bool dfopen = false;            /* data file open for writing? */
3512        bool newfilter;                 /* reset on each new filter */
3513        char rcmd;
3514        int i;
3515        int save_errno;
3516        char *response = NULL;
3517        time_t eomsent;
3518        ssize_t rlen;
3519
3520        if (tTd(64, 10))
3521                sm_dprintf("milter_data\n");
3522
3523        *state = SMFIR_CONTINUE;
3524
3525        /*
3526        **  XXX: Should actually send body chunks to each filter
3527        **  a chunk at a time instead of sending the whole body to
3528        **  each filter in turn.  However, only if the filters don't
3529        **  change the body.
3530        */
3531
3532        for (i = 0; InputFilters[i] != NULL; i++)
3533        {
3534                struct milter *m = InputFilters[i];
3535
3536                if (*state != SMFIR_CONTINUE &&
3537                    *state != SMFIR_ACCEPT)
3538                {
3539                        /*
3540                        **  A previous filter has dealt with the message,
3541                        **  safe to stop processing the filters.
3542                        */
3543
3544                        break;
3545                }
3546
3547                /* Now reset state for later evaluation */
3548                *state = SMFIR_CONTINUE;
3549                newfilter = true;
3550
3551                /* previous problem? */
3552                if (m->mf_state == SMFS_ERROR)
3553                {
3554                        MILTER_CHECK_ERROR(false, continue);
3555                        break;
3556                }
3557
3558                /* sanity checks */
3559                if (m->mf_sock < 0 ||
3560                    (m->mf_state != SMFS_OPEN && m->mf_state != SMFS_INMSG))
3561                        continue;
3562
3563                m->mf_state = SMFS_INMSG;
3564
3565                /* check if filter wants the headers */
3566                if (!bitset(SMFIP_NOHDRS, m->mf_pflags))
3567                {
3568                        response = milter_headers(m, e, state);
3569                        MILTER_CHECK_RESULTS();
3570                }
3571
3572                /* check if filter wants EOH */
3573                if (!bitset(SMFIP_NOEOH, m->mf_pflags))
3574                {
3575                        if (tTd(64, 10))
3576                                sm_dprintf("milter_data: eoh\n");
3577
3578                        /* send it over */
3579                        response = milter_send_command(m, SMFIC_EOH, NULL, 0,
3580                                                       e, state);
3581                        MILTER_CHECK_RESULTS();
3582                }
3583
3584                /* check if filter wants the body */
3585                if (!bitset(SMFIP_NOBODY, m->mf_pflags) &&
3586                    e->e_dfp != NULL)
3587                {
3588                        rewind = true;
3589                        response = milter_body(m, e, state);
3590                        MILTER_CHECK_RESULTS();
3591                }
3592
3593                /* send the final body chunk */
3594                (void) milter_write(m, SMFIC_BODYEOB, NULL, 0,
3595                                    m->mf_timeout[SMFTO_WRITE], e);
3596
3597                /* Get time EOM sent for timeout */
3598                eomsent = curtime();
3599
3600                /* deal with the possibility of multiple responses */
3601                while (*state == SMFIR_CONTINUE)
3602                {
3603                        /* Check total timeout from EOM to final ACK/NAK */
3604                        if (m->mf_timeout[SMFTO_EOM] > 0 &&
3605                            curtime() - eomsent >= m->mf_timeout[SMFTO_EOM])
3606                        {
3607                                if (tTd(64, 5))
3608                                        sm_dprintf("milter_data(%s): EOM ACK/NAK timeout\n",
3609                                                m->mf_name);
3610                                if (MilterLogLevel > 0)
3611                                        sm_syslog(LOG_ERR, e->e_id,
3612                                                  "milter_data(%s): EOM ACK/NAK timeout",
3613                                                  m->mf_name);
3614                                milter_error(m, e);
3615                                MILTER_CHECK_ERROR(false, break);
3616                                break;
3617                        }
3618
3619                        response = milter_read(m, &rcmd, &rlen,
3620                                               m->mf_timeout[SMFTO_READ], e);
3621                        if (m->mf_state == SMFS_ERROR)
3622                                break;
3623
3624                        if (tTd(64, 10))
3625                                sm_dprintf("milter_data(%s): state %c\n",
3626                                           m->mf_name, (char) rcmd);
3627
3628                        switch (rcmd)
3629                        {
3630                          case SMFIR_REPLYCODE:
3631                                MILTER_CHECK_REPLYCODE("554 5.7.1 Command rejected");
3632                                if (MilterLogLevel > 12)
3633                                        sm_syslog(LOG_INFO, e->e_id, "milter=%s, reject=%s",
3634                                                  m->mf_name, response);
3635                                *state = rcmd;
3636                                m->mf_state = SMFS_DONE;
3637                                break;
3638
3639                          case SMFIR_REJECT: /* log msg at end of function */
3640                                if (MilterLogLevel > 12)
3641                                        sm_syslog(LOG_INFO, e->e_id, "milter=%s, reject",
3642                                                  m->mf_name);
3643                                *state = rcmd;
3644                                m->mf_state = SMFS_DONE;
3645                                break;
3646
3647                          case SMFIR_DISCARD:
3648                                if (MilterLogLevel > 12)
3649                                        sm_syslog(LOG_INFO, e->e_id, "milter=%s, discard",
3650                                                  m->mf_name);
3651                                *state = rcmd;
3652                                m->mf_state = SMFS_DONE;
3653                                break;
3654
3655                          case SMFIR_TEMPFAIL:
3656                                if (MilterLogLevel > 12)
3657                                        sm_syslog(LOG_INFO, e->e_id, "milter=%s, tempfail",
3658                                                  m->mf_name);
3659                                *state = rcmd;
3660                                m->mf_state = SMFS_DONE;
3661                                break;
3662
3663                          case SMFIR_CONTINUE:
3664                          case SMFIR_ACCEPT:
3665                                /* this filter is done with message */
3666                                if (replfailed)
3667                                        *state = SMFIR_TEMPFAIL;
3668                                else
3669                                        *state = SMFIR_ACCEPT;
3670                                m->mf_state = SMFS_DONE;
3671                                break;
3672
3673                          case SMFIR_PROGRESS:
3674                                break;
3675
3676# if _FFR_QUARANTINE
3677                          case SMFIR_QUARANTINE:
3678                                if (!bitset(SMFIF_QUARANTINE, m->mf_fflags))
3679                                {
3680                                        if (MilterLogLevel > 9)
3681                                                sm_syslog(LOG_WARNING, e->e_id,
3682                                                          "milter_data(%s): lied about quarantining, honoring request anyway",
3683                                                          m->mf_name);
3684                                }
3685                                if (response == NULL)
3686                                        response = newstr("");
3687                                if (MilterLogLevel > 3)
3688                                        sm_syslog(LOG_INFO, e->e_id,
3689                                                  "milter=%s, quarantine=%s",
3690                                                  m->mf_name, response);
3691                                e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool,
3692                                                                 response);
3693                                macdefine(&e->e_macro, A_PERM,
3694                                          macid("{quarantine}"), e->e_quarmsg);
3695                                break;
3696# endif /* _FFR_QUARANTINE */
3697
3698                          case SMFIR_ADDHEADER:
3699                                if (!bitset(SMFIF_ADDHDRS, m->mf_fflags))
3700                                {
3701                                        if (MilterLogLevel > 9)
3702                                                sm_syslog(LOG_WARNING, e->e_id,
3703                                                          "milter_data(%s): lied about adding headers, honoring request anyway",
3704                                                          m->mf_name);
3705                                }
3706                                milter_addheader(response, rlen, e);
3707                                break;
3708
3709                          case SMFIR_CHGHEADER:
3710                                if (!bitset(SMFIF_CHGHDRS, m->mf_fflags))
3711                                {
3712                                        if (MilterLogLevel > 9)
3713                                                sm_syslog(LOG_WARNING, e->e_id,
3714                                                          "milter_data(%s): lied about changing headers, honoring request anyway",
3715                                                          m->mf_name);
3716                                }
3717                                milter_changeheader(response, rlen, e);
3718                                break;
3719
3720                          case SMFIR_ADDRCPT:
3721                                if (!bitset(SMFIF_ADDRCPT, m->mf_fflags))
3722                                {
3723                                        if (MilterLogLevel > 9)
3724                                                sm_syslog(LOG_WARNING, e->e_id,
3725                                                          "milter_data(%s) lied about adding recipients, honoring request anyway",
3726                                                          m->mf_name);
3727                                }
3728                                milter_addrcpt(response, rlen, e);
3729                                break;
3730
3731                          case SMFIR_DELRCPT:
3732                                if (!bitset(SMFIF_DELRCPT, m->mf_fflags))
3733                                {
3734                                        if (MilterLogLevel > 9)
3735                                                sm_syslog(LOG_WARNING, e->e_id,
3736                                                          "milter_data(%s): lied about removing recipients, honoring request anyway",
3737                                                          m->mf_name);
3738                                }
3739                                milter_delrcpt(response, rlen, e);
3740                                break;
3741
3742                          case SMFIR_REPLBODY:
3743                                if (!bitset(SMFIF_MODBODY, m->mf_fflags))
3744                                {
3745                                        if (MilterLogLevel > 9)
3746                                                sm_syslog(LOG_ERR, e->e_id,
3747                                                          "milter_data(%s): lied about replacing body, rejecting request and tempfailing message",
3748                                                          m->mf_name);
3749                                        replfailed = true;
3750                                        break;
3751                                }
3752
3753                                /* already failed in attempt */
3754                                if (replfailed)
3755                                        break;
3756
3757                                if (!dfopen)
3758                                {
3759                                        if (milter_reopen_df(e) < 0)
3760                                        {
3761                                                replfailed = true;
3762                                                break;
3763                                        }
3764                                        dfopen = true;
3765                                        rewind = true;
3766                                }
3767
3768                                if (milter_replbody(response, rlen,
3769                                                    newfilter, e) < 0)
3770                                        replfailed = true;
3771                                newfilter = false;
3772                                replbody = true;
3773                                break;
3774
3775                          default:
3776                                /* Invalid response to command */
3777                                if (MilterLogLevel > 0)
3778                                        sm_syslog(LOG_ERR, e->e_id,
3779                                                  "milter_data(%s): returned bogus response %c",
3780                                                  m->mf_name, rcmd);
3781                                milter_error(m, e);
3782                                break;
3783                        }
3784                        if (rcmd != SMFIR_REPLYCODE && response != NULL)
3785                        {
3786                                sm_free(response); /* XXX */
3787                                response = NULL;
3788                        }
3789
3790                        if (m->mf_state == SMFS_ERROR)
3791                                break;
3792                }
3793
3794                if (replbody && !replfailed)
3795                {
3796                        /* flush possible buffered character */
3797                        milter_replbody(NULL, 0, !replbody, e);
3798                        replbody = false;
3799                }
3800
3801                if (m->mf_state == SMFS_ERROR)
3802                {
3803                        MILTER_CHECK_ERROR(false, continue);
3804                        goto finishup;
3805                }
3806        }
3807
3808finishup:
3809        /* leave things in the expected state if we touched it */
3810        if (replfailed)
3811        {
3812                if (*state == SMFIR_CONTINUE ||
3813                    *state == SMFIR_ACCEPT)
3814                {
3815                        *state = SMFIR_TEMPFAIL;
3816                        SM_FREE_CLR(response);
3817                }
3818
3819                if (dfopen)
3820                {
3821                        (void) sm_io_close(e->e_dfp, SM_TIME_DEFAULT);
3822                        e->e_dfp = NULL;
3823                        e->e_flags &= ~EF_HAS_DF;
3824                        dfopen = false;
3825                }
3826                rewind = false;
3827        }
3828
3829        if ((dfopen && milter_reset_df(e) < 0) ||
3830            (rewind && bfrewind(e->e_dfp) < 0))
3831        {
3832                save_errno = errno;
3833                ExitStat = EX_IOERR;
3834
3835                /*
3836                **  If filter told us to keep message but we had
3837                **  an error, we can't really keep it, tempfail it.
3838                */
3839
3840                if (*state == SMFIR_CONTINUE ||
3841                    *state == SMFIR_ACCEPT)
3842                {
3843                        *state = SMFIR_TEMPFAIL;
3844                        SM_FREE_CLR(response);
3845                }
3846
3847                errno = save_errno;
3848                syserr("milter_data: %s/%cf%s: read error",
3849                       qid_printqueue(e->e_qgrp, e->e_qdir),
3850                       DATAFL_LETTER, e->e_id);
3851        }
3852
3853        MILTER_CHECK_DONE_MSG();
3854        if (MilterLogLevel > 10 && *state == SMFIR_REJECT)
3855                sm_syslog(LOG_INFO, e->e_id, "Milter: reject, data");
3856        return response;
3857}
3858/*
3859**  MILTER_QUIT -- informs the filter(s) we are done and closes connection(s)
3860**
3861**      Parameters:
3862**              e -- current envelope.
3863**
3864**      Returns:
3865**              none
3866*/
3867
3868void
3869milter_quit(e)
3870        ENVELOPE *e;
3871{
3872        int i;
3873
3874        if (tTd(64, 10))
3875                sm_dprintf("milter_quit(%s)\n", e->e_id);
3876
3877        for (i = 0; InputFilters[i] != NULL; i++)
3878                milter_quit_filter(InputFilters[i], e);
3879}
3880/*
3881**  MILTER_ABORT -- informs the filter(s) that we are aborting current message
3882**
3883**      Parameters:
3884**              e -- current envelope.
3885**
3886**      Returns:
3887**              none
3888*/
3889
3890void
3891milter_abort(e)
3892        ENVELOPE *e;
3893{
3894        int i;
3895
3896        if (tTd(64, 10))
3897                sm_dprintf("milter_abort\n");
3898
3899        for (i = 0; InputFilters[i] != NULL; i++)
3900        {
3901                struct milter *m = InputFilters[i];
3902
3903                /* sanity checks */
3904                if (m->mf_sock < 0 || m->mf_state != SMFS_INMSG)
3905                        continue;
3906
3907                milter_abort_filter(m, e);
3908        }
3909}
3910#endif /* MILTER */
Note: See TracBrowser for help on using the repository browser.