1 /*        $NetBSD: milter8.c,v 1.6 2025/02/25 19:15:46 christos Exp $ */
2 
3 /*++
4 /* NAME
5 /*        milter8 3
6 /* SUMMARY
7 /*        MTA-side Sendmail 8 Milter protocol
8 /* SYNOPSIS
9 /*        #include <milter8.h>
10 /*
11 /*        MILTER    *milter8_create(name, conn_timeout, cmd_timeout, msg_timeout,
12 /*                                      protocol, def_action, parent)
13 /*        const char *name;
14 /*        int conn_timeout;
15 /*        int cmd_timeout;
16 /*        int msg_timeout;
17 /*        const char *protocol;
18 /*        const char *def_action;
19 /*        MILTERS *parent;
20 /*
21 /*        MILTER    *milter8_receive(stream)
22 /*        VSTREAM   *stream;
23 /* DESCRIPTION
24 /*        This module implements the MTA side of the Sendmail 8 mail
25 /*        filter protocol.
26 /*
27 /*        milter8_create() creates a MILTER data structure with virtual
28 /*        functions that implement a client for the Sendmail 8 Milter
29 /*        protocol. These virtual functions are then invoked via the
30 /*        milter(3) interface.  The *timeout, protocol and def_action
31 /*        arguments come directly from milter_create(). The parent
32 /*        argument specifies a context for content editing.
33 /*
34 /*        milter8_receive() receives a mail filter definition from the
35 /*        specified stream. The result is zero in case of success.
36 /*
37 /*        Arguments:
38 /* .IP name
39 /*        The Milter application endpoint, either inet:host:port or
40 /*        unix:/pathname.
41 /* DIAGNOSTICS
42 /*        Panic: interface violation.  Fatal errors: out of memory.
43 /* CONFIGURATION PARAMETERS
44 /*        milter8_protocol, protocol version and extensions
45 /* SEE ALSO
46 /*        milter(3) generic Milter interface
47 /* LICENSE
48 /* .ad
49 /* .fi
50 /*        The Secure Mailer license must be distributed with this software.
51 /* AUTHOR(S)
52 /*        Wietse Venema
53 /*        IBM T.J. Watson Research
54 /*        P.O. Box 704
55 /*        Yorktown Heights, NY 10598, USA
56 /*
57 /*        Wietse Venema
58 /*        Google, Inc.
59 /*        111 8th Avenue
60 /*        New York, NY 10011, USA
61 /*--*/
62 
63 /* System library. */
64 
65 #include <sys_defs.h>
66 #include <sys/socket.h>
67 #include <netinet/in.h>
68 #include <arpa/inet.h>
69 #include <errno.h>
70 #include <stddef.h>                     /* offsetof() */
71 #include <stdlib.h>
72 #include <string.h>
73 #include <stdarg.h>
74 #include <limits.h>                     /* INT_MAX */
75 
76 #ifndef SHUT_RDWR
77 #define SHUT_RDWR   2
78 #endif
79 
80 #ifdef STRCASECMP_IN_STRINGS_H
81 #include <strings.h>
82 #endif
83 
84 /* Utility library. */
85 
86 #include <msg.h>
87 #include <mymalloc.h>
88 #include <split_at.h>
89 #include <connect.h>
90 #include <argv.h>
91 #include <name_mask.h>
92 #include <name_code.h>
93 #include <stringops.h>
94 #include <compat_va_copy.h>
95 
96 /* Global library. */
97 
98 #include <mail_params.h>
99 #include <mail_proto.h>
100 #include <rec_type.h>
101 #include <record.h>
102 #include <mime_state.h>
103 #include <is_header.h>
104 
105 /* Postfix Milter library. */
106 
107 #include <milter.h>
108 
109 /* Application-specific. */
110 
111  /*
112   * Use our own protocol definitions, so that Postfix can be built even when
113   * libmilter is not installed. This means that we must specify the libmilter
114   * protocol version in main.cf, and that we must send only the commands that
115   * are supported for that protocol version.
116   */
117 
118  /*
119   * Commands from MTA to filter.
120   */
121 #define SMFIC_ABORT           'A'       /* Abort */
122 #define SMFIC_BODY            'B'       /* Body chunk */
123 #define SMFIC_CONNECT                   'C'       /* Connection information */
124 #define SMFIC_MACRO           'D'       /* Define macro */
125 #define SMFIC_BODYEOB                   'E'       /* final body chunk (End) */
126 #define SMFIC_HELO            'H'       /* HELO/EHLO */
127 #define SMFIC_HEADER                    'L'       /* Header */
128 #define SMFIC_MAIL            'M'       /* MAIL from */
129 #define SMFIC_EOH             'N'       /* EOH */
130 #define SMFIC_OPTNEG                    'O'       /* Option negotiation */
131 #define SMFIC_QUIT            'Q'       /* QUIT */
132 #define SMFIC_RCPT            'R'       /* RCPT to */
133  /* Introduced with Sendmail 8.13. */
134 #define SMFIC_DATA            'T'       /* DATA */
135 #define SMFIC_UNKNOWN                   'U'       /* Any unknown command */
136  /* Introduced with Sendmail 8.14. */
137 #define SMFIC_QUIT_NC                   'K'       /* Quit + new connection */
138 
139 static const NAME_CODE smfic_table[] = {
140     "SMFIC_ABORT", SMFIC_ABORT,
141     "SMFIC_BODY", SMFIC_BODY,
142     "SMFIC_CONNECT", SMFIC_CONNECT,
143     "SMFIC_MACRO", SMFIC_MACRO,
144     "SMFIC_BODYEOB", SMFIC_BODYEOB,
145     "SMFIC_HELO", SMFIC_HELO,
146     "SMFIC_HEADER", SMFIC_HEADER,
147     "SMFIC_MAIL", SMFIC_MAIL,
148     "SMFIC_EOH", SMFIC_EOH,
149     "SMFIC_OPTNEG", SMFIC_OPTNEG,
150     "SMFIC_QUIT", SMFIC_QUIT,
151     "SMFIC_RCPT", SMFIC_RCPT,
152     /* Introduced with Sendmail 8.13. */
153     "SMFIC_DATA", SMFIC_DATA,
154     "SMFIC_UNKNOWN", SMFIC_UNKNOWN,
155     /* Introduced with Sendmail 8.14. */
156     "SMFIC_QUIT_NC", SMFIC_QUIT_NC,
157     0, 0,
158 };
159 
160  /*
161   * Responses from filter to MTA.
162   */
163 #define SMFIR_ADDRCPT                   '+'       /* add recipient */
164 #define SMFIR_DELRCPT                   '-'       /* remove recipient */
165 #define SMFIR_ACCEPT                    'a'       /* accept */
166 #define SMFIR_REPLBODY                  'b'       /* replace body (chunk) */
167 #define SMFIR_CONTINUE                  'c'       /* continue */
168 #define SMFIR_DISCARD                   'd'       /* discard */
169 #define SMFIR_CONN_FAIL                 'f'       /* cause a connection failure */
170 #define SMFIR_CHGHEADER                 'm'       /* change header */
171 #define SMFIR_PROGRESS                  'p'       /* progress */
172 #define SMFIR_REJECT                    'r'       /* reject */
173 #define SMFIR_TEMPFAIL                  't'       /* tempfail */
174 #define SMFIR_SHUTDOWN                  '4'       /* 421: shutdown (internal to MTA) */
175 #define SMFIR_ADDHEADER                 'h'       /* add header */
176 #define SMFIR_INSHEADER                 'i'       /* insert header */
177 #define SMFIR_REPLYCODE                 'y'       /* reply code etc */
178 #define SMFIR_QUARANTINE      'q'       /* quarantine */
179  /* Introduced with Sendmail 8.14. */
180 #define SMFIR_SKIP            's'       /* skip further events of this type */
181 #define SMFIR_CHGFROM                   'e'       /* change sender (incl. ESMTP args) */
182 #define SMFIR_ADDRCPT_PAR     '2'       /* add recipient (incl. ESMTP args) */
183 #define SMFIR_SETSYMLIST      'l'       /* set list of symbols (macros) */
184 
185 static const NAME_CODE smfir_table[] = {
186     "SMFIR_ADDRCPT", SMFIR_ADDRCPT,
187     "SMFIR_DELRCPT", SMFIR_DELRCPT,
188     "SMFIR_ACCEPT", SMFIR_ACCEPT,
189     "SMFIR_REPLBODY", SMFIR_REPLBODY,
190     "SMFIR_CONTINUE", SMFIR_CONTINUE,
191     "SMFIR_DISCARD", SMFIR_DISCARD,
192     "SMFIR_CONN_FAIL", SMFIR_CONN_FAIL,
193     "SMFIR_CHGHEADER", SMFIR_CHGHEADER,
194     "SMFIR_PROGRESS", SMFIR_PROGRESS,
195     "SMFIR_REJECT", SMFIR_REJECT,
196     "SMFIR_TEMPFAIL", SMFIR_TEMPFAIL,
197     "SMFIR_SHUTDOWN", SMFIR_SHUTDOWN,
198     "SMFIR_ADDHEADER", SMFIR_ADDHEADER,
199     "SMFIR_INSHEADER", SMFIR_INSHEADER,
200     "SMFIR_REPLYCODE", SMFIR_REPLYCODE,
201     "SMFIR_QUARANTINE", SMFIR_QUARANTINE,
202     /* Introduced with Sendmail 8.14. */
203     "SMFIR_SKIP", SMFIR_SKIP,
204     "SMFIR_CHGFROM", SMFIR_CHGFROM,
205     "SMFIR_ADDRCPT_PAR", SMFIR_ADDRCPT_PAR,
206     "SMFIR_SETSYMLIST", SMFIR_SETSYMLIST,
207     0, 0,
208 };
209 
210  /*
211   * Commands that the filter does not want to receive, and replies that the
212   * filter will not send. Plus some other random stuff.
213   */
214 #define SMFIP_NOCONNECT                 (1L<<0)   /* filter does not want connect info */
215 #define SMFIP_NOHELO                    (1L<<1)   /* filter does not want HELO info */
216 #define SMFIP_NOMAIL                    (1L<<2)   /* filter does not want MAIL info */
217 #define SMFIP_NORCPT                    (1L<<3)   /* filter does not want RCPT info */
218 #define SMFIP_NOBODY                    (1L<<4)   /* filter does not want body */
219 #define SMFIP_NOHDRS                    (1L<<5)   /* filter does not want headers */
220 #define SMFIP_NOEOH           (1L<<6)   /* filter does not want EOH */
221  /* Introduced with Sendmail 8.13. */
222 #define SMFIP_NOHREPL                   SMFIP_NR_HDR
223  /* Introduced with Sendmail 8.14. */
224 #define SMFIP_NR_HDR                    (1L<<7)   /* filter won't reply for header */
225 #define SMFIP_NOUNKNOWN       (1L<<8)   /* filter does not want unknown cmd */
226 #define SMFIP_NODATA                    (1L<<9)   /* filter does not want DATA */
227 #define SMFIP_SKIP            (1L<<10)/* MTA supports SMFIR_SKIP */
228 #define SMFIP_RCPT_REJ                  (1L<<11)/* filter wants rejected RCPTs */
229 #define SMFIP_NR_CONN                   (1L<<12)/* filter won't reply for connect */
230 #define SMFIP_NR_HELO                   (1L<<13)/* filter won't reply for HELO */
231 #define SMFIP_NR_MAIL                   (1L<<14)/* filter won't reply for MAIL */
232 #define SMFIP_NR_RCPT                   (1L<<15)/* filter won't reply for RCPT */
233 #define SMFIP_NR_DATA                   (1L<<16)/* filter won't reply for DATA */
234 #define SMFIP_NR_UNKN                   (1L<<17)/* filter won't reply for UNKNOWN */
235 #define SMFIP_NR_EOH                    (1L<<18)/* filter won't reply for eoh */
236 #define SMFIP_NR_BODY                   (1L<<19)/* filter won't reply for body chunk */
237 #define SMFIP_HDR_LEADSPC     (1L<<20)/* header value has leading space */
238 
239 #define SMFIP_NOSEND_MASK \
240           (SMFIP_NOCONNECT | SMFIP_NOHELO | SMFIP_NOMAIL | SMFIP_NORCPT \
241           | SMFIP_NOBODY | SMFIP_NOHDRS | SMFIP_NOEOH | SMFIP_NOUNKNOWN \
242           | SMFIP_NODATA)
243 
244 #define SMFIP_NOREPLY_MASK \
245           (SMFIP_NR_CONN | SMFIP_NR_HELO | SMFIP_NR_MAIL | SMFIP_NR_RCPT \
246           | SMFIP_NR_DATA | SMFIP_NR_UNKN | SMFIP_NR_HDR | SMFIP_NR_EOH | \
247           SMFIP_NR_BODY)
248 
249 static const NAME_MASK smfip_table[] = {
250     "SMFIP_NOCONNECT", SMFIP_NOCONNECT,
251     "SMFIP_NOHELO", SMFIP_NOHELO,
252     "SMFIP_NOMAIL", SMFIP_NOMAIL,
253     "SMFIP_NORCPT", SMFIP_NORCPT,
254     "SMFIP_NOBODY", SMFIP_NOBODY,
255     "SMFIP_NOHDRS", SMFIP_NOHDRS,
256     "SMFIP_NOEOH", SMFIP_NOEOH,
257     /* Introduced with Sendmail 8.14. */
258     "SMFIP_NR_HDR", SMFIP_NR_HDR,
259     "SMFIP_NOUNKNOWN", SMFIP_NOUNKNOWN,
260     "SMFIP_NODATA", SMFIP_NODATA,
261     "SMFIP_SKIP", SMFIP_SKIP,
262     "SMFIP_RCPT_REJ", SMFIP_RCPT_REJ,
263     "SMFIP_NR_CONN", SMFIP_NR_CONN,
264     "SMFIP_NR_HELO", SMFIP_NR_HELO,
265     "SMFIP_NR_MAIL", SMFIP_NR_MAIL,
266     "SMFIP_NR_RCPT", SMFIP_NR_RCPT,
267     "SMFIP_NR_DATA", SMFIP_NR_DATA,
268     "SMFIP_NR_UNKN", SMFIP_NR_UNKN,
269     "SMFIP_NR_EOH", SMFIP_NR_EOH,
270     "SMFIP_NR_BODY", SMFIP_NR_BODY,
271     "SMFIP_HDR_LEADSPC", SMFIP_HDR_LEADSPC,
272     0, 0,
273 };
274 
275  /*
276   * Options that the filter may send at initial handshake time, and message
277   * modifications that the filter may request at the end of the message body.
278   */
279 #define SMFIF_ADDHDRS                   (1L<<0)   /* filter may add headers */
280 #define SMFIF_CHGBODY                   (1L<<1)   /* filter may replace body */
281 #define SMFIF_ADDRCPT                   (1L<<2)   /* filter may add recipients */
282 #define SMFIF_DELRCPT                   (1L<<3)   /* filter may delete recipients */
283 #define SMFIF_CHGHDRS                   (1L<<4)   /* filter may change/delete headers */
284  /* Introduced with Sendmail 8.13. */
285 #define SMFIF_QUARANTINE      (1L<<5)   /* filter may quarantine envelope */
286  /* Introduced with Sendmail 8.14. */
287 #define SMFIF_CHGFROM                   (1L<<6)   /* filter may replace sender */
288 #define SMFIF_ADDRCPT_PAR     (1L<<7)   /* filter may add recipients + args */
289 #define SMFIF_SETSYMLIST      (1L<<8)   /* filter may send macro names */
290 
291 static const NAME_MASK smfif_table[] = {
292     "SMFIF_ADDHDRS", SMFIF_ADDHDRS,
293     "SMFIF_CHGBODY", SMFIF_CHGBODY,
294     "SMFIF_ADDRCPT", SMFIF_ADDRCPT,
295     "SMFIF_DELRCPT", SMFIF_DELRCPT,
296     "SMFIF_CHGHDRS", SMFIF_CHGHDRS,
297     /* Introduced with Sendmail 8.13. */
298     "SMFIF_QUARANTINE", SMFIF_QUARANTINE,
299     /* Introduced with Sendmail 8.14. */
300     "SMFIF_CHGFROM", SMFIF_CHGFROM,
301     "SMFIF_ADDRCPT_PAR", SMFIF_ADDRCPT_PAR,
302     "SMFIF_SETSYMLIST", SMFIF_SETSYMLIST,
303     0, 0,
304 };
305 
306  /*
307   * Network protocol families, used when sending CONNECT information.
308   */
309 #define SMFIA_UNKNOWN                   'U'       /* unknown */
310 #define SMFIA_UNIX            'L'       /* unix/local */
311 #define SMFIA_INET            '4'       /* inet */
312 #define SMFIA_INET6           '6'       /* inet6 */
313 
314  /*
315   * External macro class numbers, to identify the optional macro name lists
316   * that may be sent after the initial negotiation header.
317   */
318 #define SMFIM_CONNECT         0                   /* macros for connect */
319 #define SMFIM_HELO  1                   /* macros for HELO */
320 #define SMFIM_ENVFROM         2                   /* macros for MAIL */
321 #define SMFIM_ENVRCPT         3                   /* macros for RCPT */
322 #define SMFIM_DATA  4                   /* macros for DATA */
323 #define SMFIM_EOM   5                   /* macros for end-of-message */
324 #define SMFIM_EOH   6                   /* macros for end-of-header */
325 
326 static const NAME_CODE smfim_table[] = {
327     "SMFIM_CONNECT", SMFIM_CONNECT,
328     "SMFIM_HELO", SMFIM_HELO,
329     "SMFIM_ENVFROM", SMFIM_ENVFROM,
330     "SMFIM_ENVRCPT", SMFIM_ENVRCPT,
331     "SMFIM_DATA", SMFIM_DATA,
332     "SMFIM_EOM", SMFIM_EOM,
333     "SMFIM_EOH", SMFIM_EOH,
334     0, 0,
335 };
336 
337  /*
338   * Mapping from external macro class numbers to our internal MILTER_MACROS
339   * structure members, without using a switch statement.
340   */
341 static const size_t milter8_macro_offsets[] = {
342     offsetof(MILTER_MACROS, conn_macros),         /* SMFIM_CONNECT */
343     offsetof(MILTER_MACROS, helo_macros),         /* SMFIM_HELO */
344     offsetof(MILTER_MACROS, mail_macros),         /* SMFIM_ENVFROM */
345     offsetof(MILTER_MACROS, rcpt_macros),         /* SMFIM_ENVRCPT */
346     offsetof(MILTER_MACROS, data_macros),         /* SMFIM_DATA */
347     offsetof(MILTER_MACROS, eod_macros),/* Note: SMFIM_EOM < SMFIM_EOH */
348     offsetof(MILTER_MACROS, eoh_macros),/* Note: SMFIM_EOH > SMFIM_EOM */
349 };
350 
351 #define MILTER8_MACRO_PTR(__macros, __class) \
352           ((char **) (((char *) (__macros)) + milter8_macro_offsets[(__class)]))
353 
354  /*
355   * How much buffer space is available for sending body content.
356   */
357 #define MILTER_CHUNK_SIZE     65535     /* body chunk size */
358 
359 /*#define msg_verbose 2*/
360 
361  /*
362   * Sendmail 8 mail filter client.
363   */
364 typedef struct {
365     MILTER  m;                                    /* parent class */
366     int     conn_timeout;               /* connect timeout */
367     int     cmd_timeout;                /* per-command timeout */
368     int     msg_timeout;                /* content inspection timeout */
369     char   *protocol;                             /* protocol version/extension */
370     char   *def_action;                           /* action if unavailable */
371     int     version;                              /* application protocol version */
372     int     rq_mask;                              /* application requests (SMFIF_*) */
373     int     ev_mask;                              /* application events (SMFIP_*) */
374     int     np_mask;                              /* events outside my protocol version */
375     VSTRING *buf;                       /* I/O buffer */
376     VSTRING *body;                      /* I/O buffer */
377     VSTREAM *fp;                        /* stream or null (closed) */
378 
379     /*
380      * Following fields must be reset after successful CONNECT, to avoid
381      * leakage from one use to another.
382      */
383     int     state;                      /* MILTER8_STAT_mumble */
384     char   *def_reply;                            /* error response or null */
385     int     skip_event_type;            /* skip operations of this type */
386 } MILTER8;
387 
388  /*
389   * XXX Sendmail 8 libmilter automatically closes the MTA-to-filter socket
390   * when it finds out that the SMTP client has disconnected. Because of this
391   * behavior, Postfix has to open a new MTA-to-filter socket each time an
392   * SMTP client connects.
393   */
394 #define LIBMILTER_AUTO_DISCONNECT
395 
396  /*
397   * Milter internal state. For the external representation we use SMTP
398   * replies (4XX X.Y.Z text, 5XX X.Y.Z text) and one-letter strings
399   * (H=quarantine, D=discard, S=shutdown).
400   */
401 #define MILTER8_STAT_ERROR    1         /* error, must be non-zero */
402 #define MILTER8_STAT_CLOSED   2         /* no connection */
403 #define MILTER8_STAT_READY    3         /* wait for connect event */
404 #define MILTER8_STAT_ENVELOPE 4         /* in envelope */
405 #define MILTER8_STAT_MESSAGE  5         /* in message */
406 #define MILTER8_STAT_ACCEPT_CON         6         /* accept all commands */
407 #define MILTER8_STAT_ACCEPT_MSG         7         /* accept one message */
408 #define MILTER8_STAT_REJECT_CON         8         /* reject all commands */
409 
410  /*
411   * Protocol formatting requests. Note: the terms "long" and "short" refer to
412   * the data types manipulated by htonl(), htons() and friends. These types
413   * are network specific, not host platform specific.
414   */
415 #define MILTER8_DATA_END      0         /* no more arguments */
416 #define MILTER8_DATA_HLONG    1         /* host long */
417 #define MILTER8_DATA_BUFFER   2         /* network-formatted buffer */
418 #define MILTER8_DATA_STRING   3         /* null-terminated string */
419 #define MILTER8_DATA_NSHORT   4         /* network short */
420 #define MILTER8_DATA_ARGV     5         /* array of null-terminated strings */
421 #define MILTER8_DATA_OCTET    6         /* byte */
422 #define MILTER8_DATA_MORE     7         /* more arguments in next call */
423 
424  /*
425   * We don't accept insane amounts of data.
426   */
427 #define XXX_MAX_DATA          (INT_MAX / 2)
428 #define XXX_TIMEOUT 10
429 
430  /*
431   * We implement the protocol up to and including version 6, and configure in
432   * main.cf what protocol version we will use. The version is the first data
433   * item in the SMFIC_OPTNEG packet.
434   *
435   * We must send only events that are defined for the specified protocol
436   * version. Libmilter may disconnect when we send unexpected events.
437   *
438   * The following events are supported in all our milter protocol versions.
439   */
440 #define MILTER8_V2_PROTO_MASK \
441           (SMFIP_NOCONNECT | SMFIP_NOHELO | SMFIP_NOMAIL | SMFIP_NORCPT | \
442           SMFIP_NOBODY | SMFIP_NOHDRS | SMFIP_NOEOH)
443 
444  /*
445   * Events supported by later versions.
446   */
447 #define MILTER8_V3_PROTO_MASK (MILTER8_V2_PROTO_MASK | SMFIP_NOUNKNOWN)
448 #define MILTER8_V4_PROTO_MASK (MILTER8_V3_PROTO_MASK | SMFIP_NODATA)
449 #define MILTER8_V6_PROTO_MASK \
450           (MILTER8_V4_PROTO_MASK | SMFIP_SKIP | SMFIP_RCPT_REJ \
451           | SMFIP_NOREPLY_MASK | SMFIP_HDR_LEADSPC)
452 
453  /*
454   * What events we can send to the milter application. The milter8_protocol
455   * parameter can specify a protocol version as well as protocol extensions
456   * such as "no_header_reply", a feature that speeds up the protocol by not
457   * sending a filter reply for every individual message header.
458   *
459   * This looks unclean because the user can specify multiple protocol versions,
460   * but that is taken care of by the table that follows this one.
461   *
462   * XXX Is this still needed? Sendmail 8.14 provides a proper way to negotiate
463   * what replies the mail filter will send.
464   *
465   * XXX Keep this table in reverse numerical order. This is needed by the code
466   * that implements compatibility with older Milter protocol versions.
467   */
468 static const NAME_CODE milter8_event_masks[] = {
469     "6", MILTER8_V6_PROTO_MASK,
470     "4", MILTER8_V4_PROTO_MASK,
471     "3", MILTER8_V3_PROTO_MASK,
472     "2", MILTER8_V2_PROTO_MASK,
473     "no_header_reply", SMFIP_NOHREPL,
474     0, -1,
475 };
476 
477  /*
478   * The following table lets us use the same milter8_protocol parameter
479   * setting to derive the protocol version number. In this case we ignore
480   * protocol extensions such as "no_header_reply", and require that exactly
481   * one version number is specified.
482   */
483 static const NAME_CODE milter8_versions[] = {
484     "2", 2,
485     "3", 3,
486     "4", 4,
487     "6", 6,
488     "no_header_reply", 0,
489     0, -1,
490 };
491 
492 /* SLMs. */
493 
494 #define STR(x) vstring_str(x)
495 #define LEN(x) VSTRING_LEN(x)
496 
497 /* milter8_def_reply - set persistent response */
498 
milter8_def_reply(MILTER8 * milter,const char * reply)499 static const char *milter8_def_reply(MILTER8 *milter, const char *reply)
500 {
501     if (milter->def_reply)
502           myfree(milter->def_reply);
503     milter->def_reply = reply ? mystrdup(reply) : 0;
504     return (milter->def_reply);
505 }
506 
507 /* milter8_conf_error - local/remote configuration error */
508 
milter8_conf_error(MILTER8 * milter)509 static int milter8_conf_error(MILTER8 *milter)
510 {
511     const char *reply;
512 
513     /*
514      * XXX When the cleanup server closes its end of the Milter socket while
515      * editing a queue file, the SMTP server is left out of sync with the
516      * Milter. Sending an ABORT to the Milters will not restore
517      * synchronization, because there may be any number of Milter replies
518      * already in flight. Workaround: poison the socket and force the SMTP
519      * server to abandon it.
520      */
521     if (milter->fp != 0) {
522           (void) shutdown(vstream_fileno(milter->fp), SHUT_RDWR);
523           (void) vstream_fclose(milter->fp);
524           milter->fp = 0;
525     }
526     if (strcasecmp(milter->def_action, "accept") == 0) {
527           reply = 0;
528     } else if (strcasecmp(milter->def_action, "quarantine") == 0) {
529           reply = "Hdefault_action";
530     } else {
531           reply = "451 4.3.5 Server configuration problem - try again later";
532     }
533     milter8_def_reply(milter, reply);
534     return (milter->state = MILTER8_STAT_ERROR);
535 }
536 
537 /* milter8_comm_error - read/write/format communication error */
538 
milter8_comm_error(MILTER8 * milter)539 static int milter8_comm_error(MILTER8 *milter)
540 {
541     const char *reply;
542 
543     /*
544      * XXX When the cleanup server closes its end of the Milter socket while
545      * editing a queue file, the SMTP server is left out of sync with the
546      * Milter. Sending an ABORT to the Milters will not restore
547      * synchronization, because there may be any number of Milter replies
548      * already in flight. Workaround: poison the socket and force the SMTP
549      * server to abandon it.
550      */
551     if (milter->fp != 0) {
552           (void) shutdown(vstream_fileno(milter->fp), SHUT_RDWR);
553           (void) vstream_fclose(milter->fp);
554           milter->fp = 0;
555     }
556     if (strcasecmp(milter->def_action, "accept") == 0) {
557           reply = 0;
558     } else if (strcasecmp(milter->def_action, "reject") == 0) {
559           reply = "550 5.5.0 Service unavailable";
560     } else if (strcasecmp(milter->def_action, "tempfail") == 0) {
561           reply = "451 4.7.1 Service unavailable - try again later";
562     } else if (strcasecmp(milter->def_action, "quarantine") == 0) {
563           reply = "Hdefault_action";
564     } else {
565           msg_warn("milter %s: unrecognized default action: %s",
566                      milter->m.name, milter->def_action);
567           reply = "451 4.3.5 Server configuration problem - try again later";
568     }
569     milter8_def_reply(milter, reply);
570     return (milter->state = MILTER8_STAT_ERROR);
571 }
572 
573 /* milter8_close_stream - close stream to milter application */
574 
milter8_close_stream(MILTER8 * milter)575 static void milter8_close_stream(MILTER8 *milter)
576 {
577     if (milter->fp != 0) {
578           (void) vstream_fclose(milter->fp);
579           milter->fp = 0;
580     }
581     milter->state = MILTER8_STAT_CLOSED;
582 }
583 
584 /* milter8_read_resp - receive command code now, receive data later */
585 
milter8_read_resp(MILTER8 * milter,int event,unsigned char * command,ssize_t * data_len)586 static int milter8_read_resp(MILTER8 *milter, int event, unsigned char *command,
587                                            ssize_t *data_len)
588 {
589     UINT32_TYPE len;
590     ssize_t pkt_len;
591     const char *smfic_name;
592     int     cmd;
593 
594     /*
595      * Receive the packet length.
596      */
597     if ((vstream_fread(milter->fp, (void *) &len, UINT32_SIZE))
598           != UINT32_SIZE) {
599           smfic_name = str_name_code(smfic_table, event);
600           msg_warn("milter %s: can't read %s reply packet header: %m",
601                      milter->m.name, smfic_name != 0 ?
602                      smfic_name : "(unknown MTA event)");
603           return (milter8_comm_error(milter));
604     } else if ((pkt_len = ntohl(len)) < 1) {
605           msg_warn("milter %s: bad packet length: %ld",
606                      milter->m.name, (long) pkt_len);
607           return (milter8_comm_error(milter));
608     } else if (pkt_len > XXX_MAX_DATA) {
609           msg_warn("milter %s: unreasonable packet length: %ld > %ld",
610                      milter->m.name, (long) pkt_len, (long) XXX_MAX_DATA);
611           return (milter8_comm_error(milter));
612     }
613 
614     /*
615      * Receive the command code.
616      */
617     else if ((cmd = VSTREAM_GETC(milter->fp)) == VSTREAM_EOF) {
618           msg_warn("milter %s: EOF while reading command code: %m",
619                      milter->m.name);
620           return (milter8_comm_error(milter));
621     }
622 
623     /*
624      * All is well.
625      */
626     else {
627           *command = cmd;
628           *data_len = pkt_len - 1;
629           return (0);
630     }
631 }
632 
633 static int milter8_read_data(MILTER8 *milter, ssize_t *data_len,...);
634 
635 /* vmilter8_read_data - read command data */
636 
vmilter8_read_data(MILTER8 * milter,ssize_t * data_len,va_list ap)637 static int vmilter8_read_data(MILTER8 *milter, ssize_t *data_len, va_list ap)
638 {
639     const char *myname = "milter8_read_data";
640     int     arg_type;
641     UINT32_TYPE net_long;
642     UINT32_TYPE *host_long_ptr;
643     VSTRING *buf;
644     int     ch;
645 
646     while ((arg_type = va_arg(ap, int)) > 0 && arg_type != MILTER8_DATA_MORE) {
647           switch (arg_type) {
648 
649               /*
650                * Host order long.
651                */
652           case MILTER8_DATA_HLONG:
653               if (*data_len < UINT32_SIZE) {
654                     msg_warn("milter %s: input packet too short for network long",
655                                milter->m.name);
656                     return (milter8_comm_error(milter));
657               }
658               host_long_ptr = va_arg(ap, UINT32_TYPE *);
659               if (vstream_fread(milter->fp, (void *) &net_long, UINT32_SIZE)
660                     != UINT32_SIZE) {
661                     msg_warn("milter %s: EOF while reading network long: %m",
662                                milter->m.name);
663                     return (milter8_comm_error(milter));
664               }
665               *data_len -= UINT32_SIZE;
666               *host_long_ptr = ntohl(net_long);
667               break;
668 
669               /*
670                * Raw on-the-wire format, without explicit null terminator.
671                */
672           case MILTER8_DATA_BUFFER:
673               if (*data_len < 0) {
674                     msg_warn("milter %s: no data in input packet", milter->m.name);
675                     return (milter8_comm_error(milter));
676               }
677               buf = va_arg(ap, VSTRING *);
678               if (vstream_fread_buf(milter->fp, buf, *data_len)
679                     != *data_len) {
680                     msg_warn("milter %s: EOF while reading data: %m", milter->m.name);
681                     return (milter8_comm_error(milter));
682               }
683               *data_len = 0;
684               break;
685 
686               /*
687                * Pointer to null-terminated string.
688                */
689           case MILTER8_DATA_STRING:
690               if (*data_len < 1) {
691                     msg_warn("milter %s: packet too short for string",
692                                milter->m.name);
693                     return (milter8_comm_error(milter));
694               }
695               buf = va_arg(ap, VSTRING *);
696               VSTRING_RESET(buf);
697               for (;;) {
698                     if ((ch = VSTREAM_GETC(milter->fp)) == VSTREAM_EOF) {
699                         msg_warn("%s: milter %s: EOF while reading string: %m",
700                                    myname, milter->m.name);
701                         return (milter8_comm_error(milter));
702                     }
703                     *data_len -= 1;
704                     if (ch == 0)
705                         break;
706                     VSTRING_ADDCH(buf, ch);
707                     if (*data_len <= 0) {
708                         msg_warn("%s: milter %s: missing string null termimator",
709                                    myname, milter->m.name);
710                         return (milter8_comm_error(milter));
711                     }
712               }
713               VSTRING_TERMINATE(buf);
714               break;
715 
716               /*
717                * Error.
718                */
719           default:
720               msg_panic("%s: unknown argument type: %d", myname, arg_type);
721           }
722     }
723 
724     /*
725      * Sanity checks. We may have excess data when the sender is confused. We
726      * may have a negative count when we're confused ourselves.
727      */
728     if (arg_type != MILTER8_DATA_MORE && *data_len > 0) {
729           msg_warn("%s: left-over data %ld bytes", myname, (long) *data_len);
730           return (milter8_comm_error(milter));
731     }
732     if (*data_len < 0)
733           msg_panic("%s: bad left-over data count %ld",
734                       myname, (long) *data_len);
735     return (0);
736 }
737 
738 /* milter8_read_data - read command data */
739 
milter8_read_data(MILTER8 * milter,ssize_t * data_len,...)740 static int milter8_read_data(MILTER8 *milter, ssize_t *data_len,...)
741 {
742     va_list ap;
743     int     ret;
744 
745     va_start(ap, data_len);
746     ret = vmilter8_read_data(milter, data_len, ap);
747     va_end(ap);
748     return (ret);
749 }
750 
751 /* vmilter8_size_data - compute command data length */
752 
vmilter8_size_data(va_list ap)753 static ssize_t vmilter8_size_data(va_list ap)
754 {
755     const char *myname = "vmilter8_size_data";
756     ssize_t data_len;
757     int     arg_type;
758     VSTRING *buf;
759     const char *str;
760     const char **cpp;
761 
762     /*
763      * Compute data size.
764      */
765     for (data_len = 0; (arg_type = va_arg(ap, int)) > 0; /* void */ ) {
766           switch (arg_type) {
767 
768               /*
769                * Host order long.
770                */
771           case MILTER8_DATA_HLONG:
772               (void) va_arg(ap, UINT32_TYPE);
773               data_len += UINT32_SIZE;
774               break;
775 
776               /*
777                * Raw on-the-wire format.
778                */
779           case MILTER8_DATA_BUFFER:
780               buf = va_arg(ap, VSTRING *);
781               data_len += LEN(buf);
782               break;
783 
784               /*
785                * Pointer to null-terminated string.
786                */
787           case MILTER8_DATA_STRING:
788               str = va_arg(ap, char *);
789               data_len += strlen(str) + 1;
790               break;
791 
792               /*
793                * Array of pointers to null-terminated strings.
794                */
795           case MILTER8_DATA_ARGV:
796               for (cpp = va_arg(ap, const char **); *cpp; cpp++)
797                     data_len += strlen(*cpp) + 1;
798               break;
799 
800               /*
801                * Network order short, promoted to int.
802                */
803           case MILTER8_DATA_NSHORT:
804               (void) va_arg(ap, unsigned);
805               data_len += UINT16_SIZE;
806               break;
807 
808               /*
809                * Octet, promoted to int.
810                */
811           case MILTER8_DATA_OCTET:
812               (void) va_arg(ap, unsigned);
813               data_len += 1;
814               break;
815 
816               /*
817                * Error.
818                */
819           default:
820               msg_panic("%s: bad argument type: %d", myname, arg_type);
821           }
822     }
823     va_end(ap);
824     return (data_len);
825 }
826 
827 /* vmilter8_write_cmd - write command to Sendmail 8 Milter */
828 
vmilter8_write_cmd(MILTER8 * milter,int command,ssize_t data_len,va_list ap)829 static int vmilter8_write_cmd(MILTER8 *milter, int command, ssize_t data_len,
830                                             va_list ap)
831 {
832     const char *myname = "vmilter8_write_cmd";
833     int     arg_type;
834     UINT32_TYPE pkt_len;
835     UINT32_TYPE host_long;
836     UINT32_TYPE net_long;
837     UINT16_TYPE net_short;
838     VSTRING *buf;
839     const char *str;
840     const char **cpp;
841     char    ch;
842 
843     /*
844      * Deliver the packet.
845      */
846     if ((pkt_len = 1 + data_len) < 1)
847           msg_panic("%s: bad packet length %d", myname, pkt_len);
848     pkt_len = htonl(pkt_len);
849     (void) vstream_fwrite(milter->fp, (void *) &pkt_len, UINT32_SIZE);
850     (void) VSTREAM_PUTC(command, milter->fp);
851     while ((arg_type = va_arg(ap, int)) > 0) {
852           switch (arg_type) {
853 
854               /*
855                * Network long.
856                */
857           case MILTER8_DATA_HLONG:
858               host_long = va_arg(ap, UINT32_TYPE);
859               net_long = htonl(host_long);
860               (void) vstream_fwrite(milter->fp, (void *) &net_long, UINT32_SIZE);
861               break;
862 
863               /*
864                * Raw on-the-wire format.
865                */
866           case MILTER8_DATA_BUFFER:
867               buf = va_arg(ap, VSTRING *);
868               (void) vstream_fwrite(milter->fp, STR(buf), LEN(buf));
869               break;
870 
871               /*
872                * Pointer to null-terminated string.
873                */
874           case MILTER8_DATA_STRING:
875               str = va_arg(ap, char *);
876               (void) vstream_fwrite(milter->fp, str, strlen(str) + 1);
877               break;
878 
879               /*
880                * Octet, promoted to int.
881                */
882           case MILTER8_DATA_OCTET:
883               ch = va_arg(ap, unsigned);
884               (void) vstream_fwrite(milter->fp, &ch, 1);
885               break;
886 
887               /*
888                * Array of pointers to null-terminated strings.
889                */
890           case MILTER8_DATA_ARGV:
891               for (cpp = va_arg(ap, const char **); *cpp; cpp++)
892                     (void) vstream_fwrite(milter->fp, *cpp, strlen(*cpp) + 1);
893               break;
894 
895               /*
896                * Network order short, promoted to int.
897                */
898           case MILTER8_DATA_NSHORT:
899               net_short = va_arg(ap, unsigned);
900               (void) vstream_fwrite(milter->fp, (void *) &net_short, UINT16_SIZE);
901               break;
902 
903               /*
904                * Error.
905                */
906           default:
907               msg_panic("%s: bad argument type: %d", myname, arg_type);
908           }
909 
910           /*
911            * Report errors immediately.
912            */
913           if (vstream_ferror(milter->fp)) {
914               msg_warn("milter %s: error writing command: %m", milter->m.name);
915               milter8_comm_error(milter);
916               break;
917           }
918     }
919     va_end(ap);
920     return (milter->state == MILTER8_STAT_ERROR);
921 }
922 
923 /* milter8_write_cmd - write command to Sendmail 8 Milter */
924 
milter8_write_cmd(MILTER8 * milter,int command,...)925 static int milter8_write_cmd(MILTER8 *milter, int command,...)
926 {
927     va_list ap;
928     va_list ap2;
929     ssize_t data_len;
930     int     err;
931 
932     /*
933      * Initialize argument lists.
934      */
935     va_start(ap, command);
936     VA_COPY(ap2, ap);
937 
938     /*
939      * Size the command data.
940      */
941     data_len = vmilter8_size_data(ap);
942     va_end(ap);
943 
944     /*
945      * Send the command and data.
946      */
947     err = vmilter8_write_cmd(milter, command, data_len, ap2);
948     va_end(ap2);
949 
950     return (err);
951 }
952 
953 /* milter8_event - report event and receive reply */
954 
milter8_event(MILTER8 * milter,int event,int skip_event_flag,int skip_reply,ARGV * macros,...)955 static const char *milter8_event(MILTER8 *milter, int event,
956                                                  int skip_event_flag,
957                                                  int skip_reply,
958                                                  ARGV *macros,...)
959 {
960     const char *myname = "milter8_event";
961     va_list ap;
962     va_list ap2;
963     ssize_t data_len;
964     int     err;
965     unsigned char cmd;
966     ssize_t data_size;
967     const char *smfic_name;
968     const char *smfir_name;
969     MILTERS *parent = milter->m.parent;
970     UINT32_TYPE index;
971     const char *edit_resp = 0;
972     const char *retval = 0;
973     VSTRING *body_line_buf = 0;
974     int     done = 0;
975     int     body_edit_lockout = 0;
976 
977 #define DONT_SKIP_REPLY       0
978 
979     /*
980      * Sanity check.
981      */
982     if (milter->fp == 0 || milter->def_reply != 0) {
983           msg_warn("%s: attempt to send event %s to milter %s after error",
984                      myname,
985                      (smfic_name = str_name_code(smfic_table, event)) != 0 ?
986                      smfic_name : "(unknown MTA event)", milter->m.name);
987           return (milter->def_reply);
988     }
989 
990     /*
991      * Skip this event if it doesn't exist in the protocol that I announced.
992      */
993     if ((skip_event_flag & milter->np_mask) != 0) {
994           if (msg_verbose)
995               msg_info("skipping non-protocol event %s for milter %s",
996                          (smfic_name = str_name_code(smfic_table, event)) != 0 ?
997                          smfic_name : "(unknown MTA event)", milter->m.name);
998           return (milter->def_reply);
999     }
1000 
1001     /*
1002      * Skip further events of this type if the filter told us so.
1003      */
1004     if (milter->skip_event_type != 0) {
1005           if (event == milter->skip_event_type) {
1006               if (msg_verbose)
1007                     msg_info("skipping event %s after SMFIR_SKIP from milter %s",
1008                          (smfic_name = str_name_code(smfic_table, event)) != 0 ?
1009                                smfic_name : "(unknown MTA event)", milter->m.name);
1010               return (milter->def_reply);
1011           } else {
1012               milter->skip_event_type = 0;
1013           }
1014     }
1015 
1016     /*
1017      * Send the macros for this event, even when we're not reporting the
1018      * event itself. This does not introduce a performance problem because
1019      * we're sending macros and event parameters in one VSTREAM transaction.
1020      *
1021      * XXX Is this still necessary?
1022      */
1023     if (msg_verbose) {
1024           VSTRING *buf = vstring_alloc(100);
1025 
1026           if (macros) {
1027               if (macros->argc > 0) {
1028                     char  **cpp;
1029 
1030                     for (cpp = macros->argv; *cpp && cpp[1]; cpp += 2)
1031                         vstring_sprintf_append(buf, " %s=%s", *cpp, cpp[1]);
1032               }
1033           }
1034           msg_info("event: %s; macros:%s",
1035                      (smfic_name = str_name_code(smfic_table, event)) != 0 ?
1036                      smfic_name : "(unknown MTA event)", *STR(buf) ?
1037                      STR(buf) : " (none)");
1038           vstring_free(buf);
1039     }
1040     if (macros) {
1041           if (milter8_write_cmd(milter, SMFIC_MACRO,
1042                                     MILTER8_DATA_OCTET, event,
1043                                     MILTER8_DATA_ARGV, macros->argv,
1044                                     MILTER8_DATA_END) != 0)
1045               return (milter->def_reply);
1046     }
1047 
1048     /*
1049      * Skip this event if the Milter told us not to send it.
1050      */
1051     if ((skip_event_flag & milter->ev_mask) != 0) {
1052           if (msg_verbose)
1053               msg_info("skipping event %s for milter %s",
1054                          (smfic_name = str_name_code(smfic_table, event)) != 0 ?
1055                          smfic_name : "(unknown MTA event)", milter->m.name);
1056           return (milter->def_reply);
1057     }
1058 
1059     /*
1060      * Initialize argument lists.
1061      */
1062     va_start(ap, macros);
1063     VA_COPY(ap2, ap);
1064 
1065     /*
1066      * Compute the command data size. This is necessary because the protocol
1067      * sends length before content.
1068      */
1069     data_len = vmilter8_size_data(ap);
1070     va_end(ap);
1071 
1072     /*
1073      * Send the command and data.
1074      */
1075     err = vmilter8_write_cmd(milter, event, data_len, ap2);
1076     va_end(ap2);
1077 
1078     /*
1079      * C99 requires that we finalize argument lists before returning.
1080      */
1081     if (err != 0)
1082           return (milter->def_reply);
1083 
1084     /*
1085      * Special feature: don't wait for one reply per header. This allows us
1086      * to send multiple headers in one VSTREAM transaction, and improves
1087      * over-all performance.
1088      */
1089     if (skip_reply) {
1090           if (msg_verbose)
1091               msg_info("skipping reply for event %s from milter %s",
1092                          (smfic_name = str_name_code(smfic_table, event)) != 0 ?
1093                          smfic_name : "(unknown MTA event)", milter->m.name);
1094           return (milter->def_reply);
1095     }
1096 
1097     /*
1098      * Receive the reply or replies.
1099      *
1100      * Intercept all loop exits so that we can do post header/body edit
1101      * processing.
1102      *
1103      * XXX Bound the loop iteration count.
1104      *
1105      * In the end-of-body stage, the Milter may reply with one or more queue
1106      * file edit requests before it replies with its final decision: accept,
1107      * reject, etc. After a local queue file edit error (file too big, media
1108      * write error), do not close the Milter socket in the cleanup server.
1109      * Instead skip all further Milter replies until the final decision. This
1110      * way the Postfix SMTP server stays in sync with the Milter, and Postfix
1111      * doesn't have to lose the ability to handle multiple deliveries within
1112      * the same SMTP session. This requires that the Postfix SMTP server uses
1113      * something other than CLEANUP_STAT_WRITE when it loses contact with the
1114      * cleanup server.
1115      */
1116 #define IN_CONNECT_EVENT(e) ((e) == SMFIC_CONNECT || (e) == SMFIC_HELO)
1117 
1118     /*
1119      * XXX Don't evaluate this macro's argument multiple times. Since we use
1120      * "continue" the macro can't be enclosed in do .. while (0).
1121      */
1122 #define MILTER8_EVENT_BREAK(s) { \
1123           retval = (s); \
1124           done = 1; \
1125           continue; \
1126     }
1127 
1128     while (done == 0) {
1129           char   *cp;
1130           char   *rp;
1131           char    ch;
1132           char   *next;
1133 
1134           if (milter8_read_resp(milter, event, &cmd, &data_size) != 0)
1135               MILTER8_EVENT_BREAK(milter->def_reply);
1136           if (msg_verbose)
1137               msg_info("reply: %s data %ld bytes",
1138                          (smfir_name = str_name_code(smfir_table, cmd)) != 0 ?
1139                          smfir_name : "unknown", (long) data_size);
1140 
1141           /*
1142            * Handle unfinished message body replacement first.
1143            *
1144            * XXX When SMFIR_REPLBODY is followed by some different request, we
1145            * assume that the body replacement operation is complete. The queue
1146            * file editing implementation currently does not support sending
1147            * part 1 of the body replacement text, doing some other queue file
1148            * updates, and then sending part 2 of the body replacement text. To
1149            * avoid loss of data, we log an error when SMFIR_REPLBODY requests
1150            * are alternated with other requests.
1151            */
1152           if (body_line_buf != 0 && cmd != SMFIR_REPLBODY) {
1153               /* In case the last body replacement line didn't end in CRLF. */
1154               if (edit_resp == 0 && LEN(body_line_buf) > 0)
1155                     edit_resp = parent->repl_body(parent->chg_context,
1156                                                         MILTER_BODY_LINE,
1157                                                         REC_TYPE_NORM,
1158                                                         body_line_buf);
1159               if (edit_resp == 0)
1160                     edit_resp = parent->repl_body(parent->chg_context,
1161                                                         MILTER_BODY_END,
1162                                                          /* unused */ 0,
1163                                                         (VSTRING *) 0);
1164               body_edit_lockout = 1;
1165               vstring_free(body_line_buf);
1166               body_line_buf = 0;
1167           }
1168           switch (cmd) {
1169 
1170               /*
1171                * Still working on it.
1172                */
1173           case SMFIR_PROGRESS:
1174               if (data_size != 0)
1175                     break;
1176               continue;
1177 
1178               /*
1179                * Decision: continue processing.
1180                */
1181           case SMFIR_CONTINUE:
1182               if (data_size != 0)
1183                     break;
1184               MILTER8_EVENT_BREAK(milter->def_reply);
1185 
1186               /*
1187                * Decision: accept this message, or accept all further commands
1188                * in this SMTP connection. This decision is final (i.e. Sendmail
1189                * 8 changes receiver state).
1190                */
1191           case SMFIR_ACCEPT:
1192               if (data_size != 0)
1193                     break;
1194               if (IN_CONNECT_EVENT(event)) {
1195 #ifdef LIBMILTER_AUTO_DISCONNECT
1196                     milter8_close_stream(milter);
1197 #endif
1198                     /* No more events for this SMTP connection. */
1199                     milter->state = MILTER8_STAT_ACCEPT_CON;
1200               } else {
1201                     /* No more events for this message. */
1202                     milter->state = MILTER8_STAT_ACCEPT_MSG;
1203               }
1204               MILTER8_EVENT_BREAK(milter->def_reply);
1205 
1206               /*
1207                * Decision: accept and silently discard this message. According
1208                * to the milter API documentation there will be no action when
1209                * this is requested by a connection-level function. This
1210                * decision is final (i.e. Sendmail 8 changes receiver state).
1211                */
1212           case SMFIR_DISCARD:
1213               if (data_size != 0)
1214                     break;
1215               if (IN_CONNECT_EVENT(event)) {
1216                     msg_warn("milter %s: DISCARD action is not allowed "
1217                                "for connect or helo", milter->m.name);
1218                     MILTER8_EVENT_BREAK(milter->def_reply);
1219               } else {
1220                     /* No more events for this message. */
1221                     milter->state = MILTER8_STAT_ACCEPT_MSG;
1222                     MILTER8_EVENT_BREAK("D");
1223               }
1224 
1225               /*
1226                * Decision: reject connection, message or recipient. This
1227                * decision is final (i.e. Sendmail 8 changes receiver state).
1228                */
1229           case SMFIR_REJECT:
1230               if (data_size != 0)
1231                     break;
1232               if (IN_CONNECT_EVENT(event)) {
1233 #ifdef LIBMILTER_AUTO_DISCONNECT
1234                     milter8_close_stream(milter);
1235 #endif
1236                     milter->state = MILTER8_STAT_REJECT_CON;
1237                     MILTER8_EVENT_BREAK(milter8_def_reply(milter, "550 5.7.1 Command rejected"));
1238               } else {
1239                     MILTER8_EVENT_BREAK("550 5.7.1 Command rejected");
1240               }
1241 
1242               /*
1243                * Decision: tempfail. This decision is final (i.e. Sendmail 8
1244                * changes receiver state).
1245                */
1246           case SMFIR_TEMPFAIL:
1247               if (data_size != 0)
1248                     break;
1249               if (IN_CONNECT_EVENT(event)) {
1250 #ifdef LIBMILTER_AUTO_DISCONNECT
1251                     milter8_close_stream(milter);
1252 #endif
1253                     milter->state = MILTER8_STAT_REJECT_CON;
1254                     MILTER8_EVENT_BREAK(milter8_def_reply(milter,
1255                               "451 4.7.1 Service unavailable - try again later"));
1256               } else {
1257                     MILTER8_EVENT_BREAK("451 4.7.1 Service unavailable - try again later");
1258               }
1259 
1260               /*
1261                * Decision: disconnect. This decision is final (i.e. Sendmail 8
1262                * changes receiver state).
1263                */
1264           case SMFIR_SHUTDOWN:
1265               if (data_size != 0)
1266                     break;
1267 #ifdef LIBMILTER_AUTO_DISCONNECT
1268               milter8_close_stream(milter);
1269 #endif
1270               milter->state = MILTER8_STAT_REJECT_CON;
1271               MILTER8_EVENT_BREAK(milter8_def_reply(milter, "S"));
1272 
1273               /*
1274                * Decision: "ddd d.d+.d+ text". This decision is final (i.e.
1275                * Sendmail 8 changes receiver state). Note: the reply may be in
1276                * multi-line SMTP format.
1277                *
1278                * XXX Sendmail compatibility: sendmail 8 uses the reply as a format
1279                * string; therefore any '%' characters in the reply are doubled.
1280                * Postfix doesn't use replies as format strings; we replace '%%'
1281                * by '%', and remove single (i.e. invalid) '%' characters.
1282                */
1283           case SMFIR_REPLYCODE:
1284               if (milter8_read_data(milter, &data_size,
1285                                           MILTER8_DATA_BUFFER, milter->buf,
1286                                           MILTER8_DATA_END) != 0)
1287                     MILTER8_EVENT_BREAK(milter->def_reply);
1288               /* XXX Enforce this for each line of a multi-line reply. */
1289               if ((STR(milter->buf)[0] != '4' && STR(milter->buf)[0] != '5')
1290                     || !ISDIGIT(STR(milter->buf)[1])
1291                     || !ISDIGIT(STR(milter->buf)[2])
1292                     || (STR(milter->buf)[3] != ' ' && STR(milter->buf)[3] != '-')
1293                     || (ISDIGIT(STR(milter->buf)[4])
1294                         && (STR(milter->buf)[4] != STR(milter->buf)[0]))) {
1295                     msg_warn("milter %s: malformed reply: %s",
1296                                milter->m.name, STR(milter->buf));
1297                     milter8_conf_error(milter);
1298                     MILTER8_EVENT_BREAK(milter->def_reply);
1299               }
1300               if ((rp = cp = strchr(STR(milter->buf), '%')) != 0) {
1301                     for (;;) {
1302                         if ((ch = *cp++) == '%')
1303                               ch = *cp++;
1304                         *rp++ = ch;
1305                         if (ch == 0)
1306                               break;
1307                     }
1308               }
1309               if (var_soft_bounce) {
1310                     for (cp = STR(milter->buf); /* void */ ; cp = next) {
1311                         if (cp[0] == '5') {
1312                               cp[0] = '4';
1313                               if (cp[4] == '5')
1314                                   cp[4] = '4';
1315                         }
1316                         if ((next = strstr(cp, "\r\n")) == 0)
1317                               break;
1318                         next += 2;
1319                     }
1320               }
1321               if (IN_CONNECT_EVENT(event)) {
1322 #ifdef LIBMILTER_AUTO_DISCONNECT
1323                     milter8_close_stream(milter);
1324 #endif
1325                     milter->state = MILTER8_STAT_REJECT_CON;
1326                     MILTER8_EVENT_BREAK(milter8_def_reply(milter, STR(milter->buf)));
1327               } else {
1328                     MILTER8_EVENT_BREAK(STR(milter->buf));
1329               }
1330 
1331               /*
1332                * Decision: quarantine. In Sendmail 8.13 this does not imply a
1333                * transition in the receiver state (reply, reject, tempfail,
1334                * accept, discard). We should not transition, either, otherwise
1335                * we get out of sync.
1336                */
1337           case SMFIR_QUARANTINE:{
1338                     VSTRING *reply;
1339                     ssize_t saved_size = data_size;
1340 
1341                     if (milter8_read_data(milter, &data_size,
1342                                               MILTER8_DATA_BUFFER, milter->buf,
1343                                               MILTER8_DATA_END) != 0)
1344                         MILTER8_EVENT_BREAK(milter->def_reply);
1345                     /* XXX This should be reported with a call-back. */
1346                     reply = vstring_alloc(100);
1347                     if (saved_size > 100)
1348                         saved_size=100;
1349                     vstring_sprintf(reply, "H%.*s", (int) saved_size,
1350                                         STR(milter->buf));
1351                     milter8_def_reply(milter, STR(reply));
1352                     vstring_free(reply);
1353                     continue;
1354               }
1355 
1356               /*
1357                * Decision: skip further events of this type.
1358                */
1359           case SMFIR_SKIP:
1360               if (data_size != 0)
1361                     break;
1362               milter->skip_event_type = event;
1363               MILTER8_EVENT_BREAK(milter->def_reply);
1364 
1365               /*
1366                * Modification request or error.
1367                */
1368           default:
1369               if (event == SMFIC_BODYEOB) {
1370                     switch (cmd) {
1371 
1372 #define MILTER8_HDR_SPACE(m) (((m)->ev_mask & SMFIP_HDR_LEADSPC) ? "" : " ")
1373 
1374                         /*
1375                          * Modification request: replace, insert or delete
1376                          * header. Index 1 means the first instance.
1377                          */
1378                     case SMFIR_CHGHEADER:
1379                         if (milter8_read_data(milter, &data_size,
1380                                                     MILTER8_DATA_HLONG, &index,
1381                                                     MILTER8_DATA_STRING, milter->buf,
1382                                                     MILTER8_DATA_STRING, milter->body,
1383                                                     MILTER8_DATA_END) != 0)
1384                               MILTER8_EVENT_BREAK(milter->def_reply);
1385                         /* Skip to the next request after previous edit error. */
1386                         if (edit_resp)
1387                               continue;
1388                         /* XXX Sendmail 8 compatibility. */
1389                         if (index == 0)
1390                               index = 1;
1391                         if ((ssize_t) index < 1) {
1392                               msg_warn("milter %s: bad change header index: %ld",
1393                                          milter->m.name, (long) index);
1394                               milter8_conf_error(milter);
1395                               MILTER8_EVENT_BREAK(milter->def_reply);
1396                         }
1397                         if (LEN(milter->buf) == 0) {
1398                               msg_warn("milter %s: null change header name",
1399                                          milter->m.name);
1400                               milter8_conf_error(milter);
1401                               MILTER8_EVENT_BREAK(milter->def_reply);
1402                         }
1403                         if (STR(milter->body)[0])
1404                               edit_resp = parent->upd_header(parent->chg_context,
1405                                                                    (ssize_t) index,
1406                                                                    STR(milter->buf),
1407                                                               MILTER8_HDR_SPACE(milter),
1408                                                                    STR(milter->body));
1409                         else
1410                               edit_resp = parent->del_header(parent->chg_context,
1411                                                                    (ssize_t) index,
1412                                                                    STR(milter->buf));
1413                         continue;
1414 
1415                         /*
1416                          * Modification request: append header.
1417                          */
1418                     case SMFIR_ADDHEADER:
1419                         if (milter8_read_data(milter, &data_size,
1420                                                     MILTER8_DATA_STRING, milter->buf,
1421                                                     MILTER8_DATA_STRING, milter->body,
1422                                                     MILTER8_DATA_END) != 0)
1423                               MILTER8_EVENT_BREAK(milter->def_reply);
1424                         /* Skip to the next request after previous edit error. */
1425                         if (edit_resp)
1426                               continue;
1427                         edit_resp = parent->add_header(parent->chg_context,
1428                                                                STR(milter->buf),
1429                                                                MILTER8_HDR_SPACE(milter),
1430                                                                STR(milter->body));
1431                         continue;
1432 
1433                         /*
1434                          * Modification request: insert header. With Sendmail 8,
1435                          * index 0 means the top-most header. We use 1-based
1436                          * indexing for consistency with header change
1437                          * operations.
1438                          */
1439                     case SMFIR_INSHEADER:
1440                         if (milter8_read_data(milter, &data_size,
1441                                                     MILTER8_DATA_HLONG, &index,
1442                                                     MILTER8_DATA_STRING, milter->buf,
1443                                                     MILTER8_DATA_STRING, milter->body,
1444                                                     MILTER8_DATA_END) != 0)
1445                               MILTER8_EVENT_BREAK(milter->def_reply);
1446                         /* Skip to the next request after previous edit error. */
1447                         if (edit_resp)
1448                               continue;
1449                         if ((ssize_t) index + 1 < 1) {
1450                               msg_warn("milter %s: bad insert header index: %ld",
1451                                          milter->m.name, (long) index);
1452                               milter8_conf_error(milter);
1453                               MILTER8_EVENT_BREAK(milter->def_reply);
1454                         }
1455                         edit_resp = parent->ins_header(parent->chg_context,
1456                                                                (ssize_t) index + 1,
1457                                                                STR(milter->buf),
1458                                                                MILTER8_HDR_SPACE(milter),
1459                                                                STR(milter->body));
1460                         continue;
1461 
1462                         /*
1463                          * Modification request: replace sender, with optional
1464                          * ESMTP args.
1465                          */
1466                     case SMFIR_CHGFROM:
1467                         if (milter8_read_data(milter, &data_size,
1468                                                     MILTER8_DATA_STRING, milter->buf,
1469                                                     MILTER8_DATA_MORE) != 0)
1470                               MILTER8_EVENT_BREAK(milter->def_reply);
1471                         if (data_size > 0) {
1472                               if (milter8_read_data(milter, &data_size,
1473                                                     MILTER8_DATA_STRING, milter->body,
1474                                                         MILTER8_DATA_END) != 0)
1475                                   MILTER8_EVENT_BREAK(milter->def_reply);
1476                         } else {
1477                               VSTRING_RESET(milter->body);
1478                               VSTRING_TERMINATE(milter->body);
1479                         }
1480                         /* Skip to the next request after previous edit error. */
1481                         if (edit_resp)
1482                               continue;
1483                         edit_resp = parent->chg_from(parent->chg_context,
1484                                                              STR(milter->buf),
1485                                                              STR(milter->body));
1486                         continue;
1487 
1488                         /*
1489                          * Modification request: append recipient.
1490                          */
1491                     case SMFIR_ADDRCPT:
1492                         if (milter8_read_data(milter, &data_size,
1493                                                     MILTER8_DATA_STRING, milter->buf,
1494                                                     MILTER8_DATA_END) != 0)
1495                               MILTER8_EVENT_BREAK(milter->def_reply);
1496                         /* Skip to the next request after previous edit error. */
1497                         if (edit_resp)
1498                               continue;
1499                         edit_resp = parent->add_rcpt(parent->chg_context,
1500                                                              STR(milter->buf));
1501                         continue;
1502 
1503                         /*
1504                          * Modification request: append recipient, with optional
1505                          * ESMTP args.
1506                          */
1507                     case SMFIR_ADDRCPT_PAR:
1508                         if (milter8_read_data(milter, &data_size,
1509                                                     MILTER8_DATA_STRING, milter->buf,
1510                                                     MILTER8_DATA_MORE) != 0)
1511                               MILTER8_EVENT_BREAK(milter->def_reply);
1512                         if (data_size > 0) {
1513                               if (milter8_read_data(milter, &data_size,
1514                                                     MILTER8_DATA_STRING, milter->body,
1515                                                         MILTER8_DATA_END) != 0)
1516                                   MILTER8_EVENT_BREAK(milter->def_reply);
1517                         } else {
1518                               VSTRING_RESET(milter->body);
1519                               VSTRING_TERMINATE(milter->body);
1520                         }
1521                         /* Skip to the next request after previous edit error. */
1522                         if (edit_resp)
1523                               continue;
1524                         edit_resp = parent->add_rcpt_par(parent->chg_context,
1525                                                                  STR(milter->buf),
1526                                                                  STR(milter->body));
1527                         continue;
1528 
1529                         /*
1530                          * Modification request: delete (expansion of) recipient.
1531                          */
1532                     case SMFIR_DELRCPT:
1533                         if (milter8_read_data(milter, &data_size,
1534                                                     MILTER8_DATA_STRING, milter->buf,
1535                                                     MILTER8_DATA_END) != 0)
1536                               MILTER8_EVENT_BREAK(milter->def_reply);
1537                         /* Skip to the next request after previous edit error. */
1538                         if (edit_resp)
1539                               continue;
1540                         edit_resp = parent->del_rcpt(parent->chg_context,
1541                                                              STR(milter->buf));
1542                         continue;
1543 
1544                         /*
1545                          * Modification request: replace the message body, and
1546                          * update the message size.
1547                          */
1548                     case SMFIR_REPLBODY:
1549                         if (body_edit_lockout) {
1550                               msg_warn("milter %s: body replacement requests can't "
1551                                          "currently be mixed with other requests",
1552                                          milter->m.name);
1553                               milter8_conf_error(milter);
1554                               MILTER8_EVENT_BREAK(milter->def_reply);
1555                         }
1556                         if (milter8_read_data(milter, &data_size,
1557                                                     MILTER8_DATA_BUFFER, milter->body,
1558                                                     MILTER8_DATA_END) != 0)
1559                               MILTER8_EVENT_BREAK(milter->def_reply);
1560                         /* Skip to the next request after previous edit error. */
1561                         if (edit_resp)
1562                               continue;
1563                         /* Start body replacement. */
1564                         if (body_line_buf == 0) {
1565                               body_line_buf = vstring_alloc(var_line_limit);
1566                               edit_resp = parent->repl_body(parent->chg_context,
1567                                                                   MILTER_BODY_START,
1568                                                                    /* unused */ 0,
1569                                                                   (VSTRING *) 0);
1570                         }
1571                         /* Extract lines from the on-the-wire CRLF format. */
1572                         for (cp = STR(milter->body); edit_resp == 0
1573                                && cp < vstring_end(milter->body); cp++) {
1574                               ch = *(unsigned char *) cp;
1575                               if (ch == '\n') {
1576                                   if (LEN(body_line_buf) > 0
1577                                         && vstring_end(body_line_buf)[-1] == '\r')
1578                                         vstring_truncate(body_line_buf,
1579                                                              LEN(body_line_buf) - 1);
1580                                   edit_resp = parent->repl_body(parent->chg_context,
1581                                                                         MILTER_BODY_LINE,
1582                                                                         REC_TYPE_NORM,
1583                                                                         body_line_buf);
1584                                   VSTRING_RESET(body_line_buf);
1585                               } else {
1586                                   /* Preserves \r if not followed by \n. */
1587                                   if (LEN(body_line_buf) == var_line_limit) {
1588                                         edit_resp = parent->repl_body(parent->chg_context,
1589                                                                          MILTER_BODY_LINE,
1590                                                                             REC_TYPE_CONT,
1591                                                                             body_line_buf);
1592                                         VSTRING_RESET(body_line_buf);
1593                                   }
1594                                   VSTRING_ADDCH(body_line_buf, ch);
1595                               }
1596                         }
1597                         continue;
1598                     }
1599               }
1600               msg_warn("milter %s: unexpected filter response %s after event %s",
1601                          milter->m.name,
1602                          (smfir_name = str_name_code(smfir_table, cmd)) != 0 ?
1603                          smfir_name : "(unknown filter reply)",
1604                          (smfic_name = str_name_code(smfic_table, event)) != 0 ?
1605                          smfic_name : "(unknown MTA event)");
1606               milter8_comm_error(milter);
1607               MILTER8_EVENT_BREAK(milter->def_reply);
1608           }
1609 
1610           /*
1611            * Get here when the reply was followed by data bytes that weren't
1612            * supposed to be there.
1613            */
1614           msg_warn("milter %s: reply %s was followed by %ld data bytes",
1615           milter->m.name, (smfir_name = str_name_code(smfir_table, cmd)) != 0 ?
1616                      smfir_name : "unknown", (long) data_len);
1617           milter8_comm_error(milter);
1618           MILTER8_EVENT_BREAK(milter->def_reply);
1619     }
1620 
1621     /*
1622      * Clean up after aborted message body replacement.
1623      */
1624     if (body_line_buf)
1625           vstring_free(body_line_buf);
1626 
1627     /*
1628      * XXX Some cleanup clients ask the cleanup server to bounce mail for
1629      * them. In that case we must override a hard reject retval result after
1630      * queue file update failure. This is not a big problem; the odds are
1631      * small that a Milter application sends a hard reject after replacing
1632      * the message body.
1633      */
1634     if (edit_resp && (retval == 0 || strchr("DS4", retval[0]) == 0))
1635           retval = edit_resp;
1636     return (retval);
1637 }
1638 
1639 /* milter8_connect - connect to filter */
1640 
milter8_connect(MILTER8 * milter)1641 static void milter8_connect(MILTER8 *milter)
1642 {
1643     const char *myname = "milter8_connect";
1644     ssize_t data_len;
1645     unsigned char cmd;
1646     char   *transport;
1647     char   *endpoint;
1648     int     (*connect_fn) (const char *, int, int);
1649     int     fd;
1650     const UINT32_TYPE my_actions = (SMFIF_ADDHDRS | SMFIF_ADDRCPT
1651                                             | SMFIF_DELRCPT | SMFIF_CHGHDRS
1652                                             | SMFIF_CHGBODY
1653                                             | SMFIF_QUARANTINE
1654                                             | SMFIF_CHGFROM
1655                                             | SMFIF_ADDRCPT_PAR
1656                                             | SMFIF_SETSYMLIST
1657     );
1658     UINT32_TYPE my_version = 0;
1659     UINT32_TYPE my_events = 0;
1660     char   *saved_version;
1661     char   *cp;
1662     char   *name;
1663 
1664     /*
1665      * Sanity check.
1666      */
1667     if (milter->fp != 0)
1668           msg_panic("%s: milter %s: socket is not closed",
1669                       myname, milter->m.name);
1670 
1671     /*
1672      * For user friendliness reasons the milter_protocol configuration
1673      * parameter can specify both the protocol version and protocol
1674      * extensions (e.g., don't reply for each individual message header).
1675      *
1676      * The protocol version is sent as is to the milter application.
1677      *
1678      * The version and extensions determine what events we can send to the
1679      * milter application.
1680      *
1681      * We don't announce support for events that aren't defined for my protocol
1682      * version. Today's libmilter implementations don't seem to care, but we
1683      * don't want to take the risk that a future version will be more picky.
1684      */
1685     cp = saved_version = mystrdup(milter->protocol);
1686     while ((name = mystrtok(&cp, CHARS_COMMA_SP)) != 0) {
1687           int     mask;
1688           int     vers;
1689 
1690           if ((mask = name_code(milter8_event_masks,
1691                                     NAME_CODE_FLAG_NONE, name)) == -1
1692               || (vers = name_code(milter8_versions,
1693                                          NAME_CODE_FLAG_NONE, name)) == -1
1694               || (vers != 0 && my_version != 0)) {
1695               msg_warn("milter %s: bad protocol information: %s",
1696                          milter->m.name, name);
1697               milter8_conf_error(milter);
1698               return;
1699           }
1700           if (vers != 0)
1701               my_version = vers;
1702           my_events |= mask;
1703     }
1704     myfree(saved_version);
1705     if (my_events == 0 || my_version == 0) {
1706           msg_warn("milter %s: no protocol version information", milter->m.name);
1707           milter8_conf_error(milter);
1708           return;
1709     }
1710 
1711     /*
1712      * Don't send events that aren't defined for my protocol version.
1713      */
1714     milter->np_mask = (SMFIP_NOSEND_MASK & ~my_events);
1715     if (msg_verbose)
1716           msg_info("%s: non-protocol events for protocol version %d: %s",
1717                      myname, my_version,
1718                      str_name_mask_opt(milter->buf, "non-protocol event mask",
1719                                  smfip_table, milter->np_mask, NAME_MASK_NUMBER));
1720 
1721     /*
1722      * Parse the Milter application endpoint.
1723      */
1724 #define FREE_TRANSPORT_AND_BAIL_OUT(milter, milter_error) do { \
1725           myfree(transport); \
1726           milter_error(milter); \
1727           return; \
1728     } while (0);
1729 
1730     transport = mystrdup(milter->m.name);
1731     if ((endpoint = split_at(transport, ':')) == 0
1732           || *endpoint == 0 || *transport == 0) {
1733           msg_warn("Milter service needs transport:endpoint instead of \"%s\"",
1734                      milter->m.name);
1735           FREE_TRANSPORT_AND_BAIL_OUT(milter, milter8_conf_error);
1736     }
1737     if (msg_verbose)
1738           msg_info("%s: transport=%s endpoint=%s", myname, transport, endpoint);
1739     if (strcmp(transport, "inet") == 0) {
1740           connect_fn = inet_connect;
1741     } else if (strcmp(transport, "unix") == 0) {
1742           connect_fn = unix_connect;
1743     } else if (strcmp(transport, "local") == 0) {
1744           connect_fn = LOCAL_CONNECT;
1745     } else {
1746           msg_warn("invalid transport name: %s in Milter service: %s",
1747                      transport, milter->m.name);
1748           FREE_TRANSPORT_AND_BAIL_OUT(milter, milter8_conf_error);
1749     }
1750 
1751     /*
1752      * Connect to the Milter application.
1753      */
1754     if ((fd = connect_fn(endpoint, BLOCKING, milter->conn_timeout)) < 0) {
1755           msg_warn("connect to Milter service %s: %m", milter->m.name);
1756           FREE_TRANSPORT_AND_BAIL_OUT(milter, milter8_comm_error);
1757     }
1758     myfree(transport);
1759     milter->fp = vstream_fdopen(fd, O_RDWR);
1760     vstream_control(milter->fp,
1761                         CA_VSTREAM_CTL_DOUBLE,
1762                         CA_VSTREAM_CTL_TIMEOUT(milter->cmd_timeout),
1763                         CA_VSTREAM_CTL_END);
1764     /* Avoid poor performance when TCP MSS > VSTREAM_BUFSIZE. */
1765     if (connect_fn == inet_connect)
1766           vstream_tweak_tcp(milter->fp);
1767 
1768     /*
1769      * Open the negotiations by sending what actions the Milter may request
1770      * and what events the Milter can receive.
1771      */
1772     if (msg_verbose) {
1773           msg_info("%s: my_version=0x%lx", myname, (long) my_version);
1774           msg_info("%s: my_actions=0x%lx %s", myname, (long) my_actions,
1775                      str_name_mask_opt(milter->buf, "request mask",
1776                                         smfif_table, my_actions, NAME_MASK_NUMBER));
1777           msg_info("%s: my_events=0x%lx %s", myname, (long) my_events,
1778                      str_name_mask_opt(milter->buf, "event mask",
1779                                          smfip_table, my_events, NAME_MASK_NUMBER));
1780     }
1781     errno = 0;
1782     if (milter8_write_cmd(milter, SMFIC_OPTNEG,
1783                                 MILTER8_DATA_HLONG, my_version,
1784                                 MILTER8_DATA_HLONG, my_actions,
1785                                 MILTER8_DATA_HLONG, my_events,
1786                                 MILTER8_DATA_END) != 0) {
1787           msg_warn("milter %s: write error in initial handshake",
1788                      milter->m.name);
1789           /* milter8_write_cmd() called milter8_comm_error() */
1790           return;
1791     }
1792 
1793     /*
1794      * Receive the filter's response and verify that we are compatible.
1795      */
1796     if (milter8_read_resp(milter, SMFIC_OPTNEG, &cmd, &data_len) != 0) {
1797           msg_warn("milter %s: read error in initial handshake", milter->m.name);
1798           /* milter8_read_resp() called milter8_comm_error() */
1799           return;
1800     }
1801     if (cmd != SMFIC_OPTNEG) {
1802           msg_warn("milter %s: unexpected reply \"%c\" in initial handshake",
1803                      milter->m.name, cmd);
1804           (void) milter8_comm_error(milter);
1805           return;
1806     }
1807     if (milter8_read_data(milter, &data_len,
1808                                 MILTER8_DATA_HLONG, &milter->version,
1809                                 MILTER8_DATA_HLONG, &milter->rq_mask,
1810                                 MILTER8_DATA_HLONG, &milter->ev_mask,
1811                                 MILTER8_DATA_MORE) != 0) {
1812           msg_warn("milter %s: read error in initial handshake", milter->m.name);
1813           /* milter8_read_data() called milter8_comm_error() */
1814           return;
1815     }
1816     if (milter->version > my_version) {
1817           msg_warn("milter %s: protocol version %d conflict"
1818                      " with MTA protocol version %d",
1819                      milter->m.name, milter->version, my_version);
1820           (void) milter8_comm_error(milter);
1821           return;
1822     }
1823     if ((milter->rq_mask & my_actions) != milter->rq_mask) {
1824           msg_warn("milter %s: request mask 0x%x conflict"
1825                      " with MTA request mask 0x%lx",
1826                      milter->m.name, milter->rq_mask, (long) my_actions);
1827           (void) milter8_comm_error(milter);
1828           return;
1829     }
1830     if (milter->ev_mask & SMFIP_RCPT_REJ)
1831           milter->m.flags |= MILTER_FLAG_WANT_RCPT_REJ;
1832 
1833     /*
1834      * Allow the remote application to run an older protocol version, but
1835      * don't them send events that their protocol version doesn't support.
1836      * Based on a suggestion by Kouhei Sutou.
1837      *
1838      * XXX When the Milter sends a protocol version that we don't have
1839      * information for, use the information for the next-lower protocol
1840      * version instead. This code assumes that the milter8_event_masks table
1841      * is organized in reverse numerical order.
1842      */
1843     if (milter->version < my_version) {
1844           const NAME_CODE *np;
1845           int     version;
1846 
1847           for (np = milter8_event_masks; /* see below */ ; np++) {
1848               if (np->name == 0) {
1849                     msg_warn("milter %s: unexpected protocol version %d",
1850                                milter->m.name, milter->version);
1851                     break;
1852               }
1853               if ((version = atoi(np->name)) > 0 && version <= milter->version) {
1854                     milter->np_mask |= (SMFIP_NOSEND_MASK & ~np->code);
1855                     if (msg_verbose)
1856                         msg_info("%s: non-protocol events for milter %s"
1857                                    " protocol version %d: %s",
1858                                    myname, milter->m.name, milter->version,
1859                                    str_name_mask_opt(milter->buf,
1860                                                          "non-protocol event mask",
1861                                                          smfip_table, milter->np_mask,
1862                                                          NAME_MASK_NUMBER));
1863                     break;
1864               }
1865           }
1866     }
1867 
1868     /*
1869      * Initial negotiations completed.
1870      */
1871     if (msg_verbose) {
1872           if ((milter->ev_mask & my_events) != milter->ev_mask)
1873               msg_info("milter %s: event mask 0x%x includes features not"
1874                          " offered in MTA event mask 0x%lx",
1875                          milter->m.name, milter->ev_mask, (long) my_events);
1876           msg_info("%s: milter %s version %d",
1877                      myname, milter->m.name, milter->version);
1878           msg_info("%s: events %s", myname,
1879                      str_name_mask_opt(milter->buf, "event mask",
1880                                  smfip_table, milter->ev_mask, NAME_MASK_NUMBER));
1881           msg_info("%s: requests %s", myname,
1882                      str_name_mask_opt(milter->buf, "request mask",
1883                                  smfif_table, milter->rq_mask, NAME_MASK_NUMBER));
1884     }
1885     milter->state = MILTER8_STAT_READY;
1886     milter8_def_reply(milter, 0);
1887     milter->skip_event_type = 0;
1888 
1889     /*
1890      * Secondary negotiations: override lists of macro names.
1891      */
1892     if (data_len > 0) {
1893           VSTRING *buf = vstring_alloc(100);
1894           UINT32_TYPE mac_type;
1895           const char *smfim_name;
1896           char  **mac_value_ptr;
1897 
1898           milter->m.macros = milter_macros_alloc(MILTER_MACROS_ALLOC_EMPTY);
1899 
1900           while (data_len > 0
1901                  && milter8_read_data(milter, &data_len,
1902                                             MILTER8_DATA_HLONG, &mac_type,
1903                                             MILTER8_DATA_STRING, buf,
1904                                             MILTER8_DATA_MORE) == 0) {
1905               smfim_name = str_name_code(smfim_table, mac_type);
1906               if (smfim_name == 0) {
1907                     msg_warn("milter %s: ignoring unknown macro type %u",
1908                                milter->m.name, (unsigned) mac_type);
1909               } else {
1910                     if (msg_verbose)
1911                         msg_info("override %s macro list with \"%s\"",
1912                                    smfim_name, STR(buf));
1913                     mac_value_ptr = MILTER8_MACRO_PTR(milter->m.macros, mac_type);
1914                     myfree(*mac_value_ptr);
1915                     *mac_value_ptr = mystrdup(STR(buf));
1916               }
1917           }
1918           /* milter8_read_data() calls milter8_comm_error() after error. */
1919           vstring_free(buf);
1920           /* At this point the filter state is either READY or ERROR. */
1921     }
1922 }
1923 
1924 /* milter8_conn_event - report connect event to Sendmail 8 milter */
1925 
milter8_conn_event(MILTER * m,const char * client_name,const char * client_addr,const char * client_port,unsigned addr_family,ARGV * macros)1926 static const char *milter8_conn_event(MILTER *m,
1927                                                       const char *client_name,
1928                                                       const char *client_addr,
1929                                                       const char *client_port,
1930                                                       unsigned addr_family,
1931                                                       ARGV *macros)
1932 {
1933     const char *myname = "milter8_conn_event";
1934     MILTER8 *milter = (MILTER8 *) m;
1935     int     port;
1936     int     skip_reply;
1937     const char *sm_name;
1938     char   *ptr = 0;
1939     const char *resp;
1940 
1941     /*
1942      * Need a global definition for "unknown" host name or address that is
1943      * shared by smtpd, cleanup and libmilter.
1944      */
1945 #define XXX_UNKNOWN "unknown"
1946 #define STR_EQ(x,y) (strcmp((x), (y)) == 0)
1947 #define STR_NE(x,y) (strcmp((x), (y)) != 0)
1948 
1949     /*
1950      * Report the event.
1951      */
1952     switch (milter->state) {
1953     case MILTER8_STAT_ERROR:
1954           if (msg_verbose)
1955               msg_info("%s: skip milter %s", myname, milter->m.name);
1956           return (milter->def_reply);
1957     case MILTER8_STAT_READY:
1958           if (msg_verbose)
1959               msg_info("%s: milter %s: connect %s/%s",
1960                          myname, milter->m.name, client_name, client_addr);
1961           if (client_port == 0) {
1962               port = 0;
1963           } else if (!alldig(client_port) || (port = atoi(client_port)) < 0
1964                        || port > 65535) {
1965               msg_warn("milter %s: bad client port number %s",
1966                          milter->m.name, client_port);
1967               port = 0;
1968           }
1969           milter->state = MILTER8_STAT_ENVELOPE;
1970           skip_reply = ((milter->ev_mask & SMFIP_NR_CONN) != 0);
1971           /* Transform unknown hostname from Postfix to Sendmail form. */
1972           sm_name = (STR_NE(client_name, XXX_UNKNOWN) ? client_name :
1973                        STR_EQ(client_addr, XXX_UNKNOWN) ? client_name :
1974                        (ptr = concatenate("[", client_addr, "]", (char *) 0)));
1975           switch (addr_family) {
1976           case AF_INET:
1977               resp = milter8_event(milter, SMFIC_CONNECT, SMFIP_NOCONNECT,
1978                                          skip_reply, macros,
1979                                          MILTER8_DATA_STRING, sm_name,
1980                                          MILTER8_DATA_OCTET, SMFIA_INET,
1981                                          MILTER8_DATA_NSHORT, htons(port),
1982                                          MILTER8_DATA_STRING, client_addr,
1983                                          MILTER8_DATA_END);
1984               break;
1985 #ifdef HAS_IPV6
1986           case AF_INET6:
1987               resp = milter8_event(milter, SMFIC_CONNECT, SMFIP_NOCONNECT,
1988                                          skip_reply, macros,
1989                                          MILTER8_DATA_STRING, sm_name,
1990                                          MILTER8_DATA_OCTET, SMFIA_INET6,
1991                                          MILTER8_DATA_NSHORT, htons(port),
1992                                          MILTER8_DATA_STRING, client_addr,
1993                                          MILTER8_DATA_END);
1994               break;
1995 #endif
1996           case AF_UNIX:
1997               resp = milter8_event(milter, SMFIC_CONNECT, SMFIP_NOCONNECT,
1998                                          skip_reply, macros,
1999                                          MILTER8_DATA_STRING, sm_name,
2000                                          MILTER8_DATA_OCTET, SMFIA_UNIX,
2001                                          MILTER8_DATA_NSHORT, htons(0),
2002                                          MILTER8_DATA_STRING, client_addr,
2003                                          MILTER8_DATA_END);
2004               break;
2005           default:
2006               resp = milter8_event(milter, SMFIC_CONNECT, SMFIP_NOCONNECT,
2007                                          skip_reply, macros,
2008                                          MILTER8_DATA_STRING, sm_name,
2009                                          MILTER8_DATA_OCTET, SMFIA_UNKNOWN,
2010                                          MILTER8_DATA_END);
2011               break;
2012           }
2013           if (ptr != 0)
2014               myfree(ptr);
2015           return (resp);
2016     default:
2017           msg_panic("%s: milter %s: bad state %d",
2018                       myname, milter->m.name, milter->state);
2019     }
2020 }
2021 
2022 /* milter8_helo_event - report HELO/EHLO command to Sendmail 8 milter */
2023 
milter8_helo_event(MILTER * m,const char * helo_name,int unused_esmtp,ARGV * macros)2024 static const char *milter8_helo_event(MILTER *m, const char *helo_name,
2025                                                       int unused_esmtp,
2026                                                       ARGV *macros)
2027 {
2028     const char *myname = "milter8_helo_event";
2029     MILTER8 *milter = (MILTER8 *) m;
2030     int     skip_reply;
2031 
2032     /*
2033      * Report the event.
2034      */
2035     switch (milter->state) {
2036     case MILTER8_STAT_ERROR:
2037     case MILTER8_STAT_ACCEPT_CON:
2038     case MILTER8_STAT_REJECT_CON:
2039           if (msg_verbose)
2040               msg_info("%s: skip milter %s", myname, milter->m.name);
2041           return (milter->def_reply);
2042     case MILTER8_STAT_ENVELOPE:
2043     case MILTER8_STAT_ACCEPT_MSG:
2044           /* With HELO after MAIL, smtpd(8) calls milter8_abort() next. */
2045           if (msg_verbose)
2046               msg_info("%s: milter %s: helo %s",
2047                          myname, milter->m.name, helo_name);
2048           skip_reply = ((milter->ev_mask & SMFIP_NR_HELO) != 0);
2049           return (milter8_event(milter, SMFIC_HELO, SMFIP_NOHELO,
2050                                     skip_reply, macros,
2051                                     MILTER8_DATA_STRING, helo_name,
2052                                     MILTER8_DATA_END));
2053     default:
2054           msg_panic("%s: milter %s: bad state %d",
2055                       myname, milter->m.name, milter->state);
2056     }
2057 }
2058 
2059 /* milter8_mail_event - report MAIL command to Sendmail 8 milter */
2060 
milter8_mail_event(MILTER * m,const char ** argv,ARGV * macros)2061 static const char *milter8_mail_event(MILTER *m, const char **argv,
2062                                                       ARGV *macros)
2063 {
2064     const char *myname = "milter8_mail_event";
2065     MILTER8 *milter = (MILTER8 *) m;
2066     const char **cpp;
2067     int     skip_reply;
2068 
2069     /*
2070      * Report the event.
2071      */
2072     switch (milter->state) {
2073     case MILTER8_STAT_ERROR:
2074     case MILTER8_STAT_ACCEPT_CON:
2075     case MILTER8_STAT_REJECT_CON:
2076           if (msg_verbose)
2077               msg_info("%s: skip milter %s", myname, milter->m.name);
2078           return (milter->def_reply);
2079     case MILTER8_STAT_ENVELOPE:
2080           if (msg_verbose) {
2081               VSTRING *buf = vstring_alloc(100);
2082 
2083               for (cpp = argv; *cpp; cpp++)
2084                     vstring_sprintf_append(buf, " %s", *cpp);
2085               msg_info("%s: milter %s: mail%s",
2086                          myname, milter->m.name, STR(buf));
2087               vstring_free(buf);
2088           }
2089           skip_reply = ((milter->ev_mask & SMFIP_NR_MAIL) != 0);
2090           return (milter8_event(milter, SMFIC_MAIL, SMFIP_NOMAIL,
2091                                     skip_reply, macros,
2092                                     MILTER8_DATA_ARGV, argv,
2093                                     MILTER8_DATA_END));
2094     default:
2095           msg_panic("%s: milter %s: bad state %d",
2096                       myname, milter->m.name, milter->state);
2097     }
2098 }
2099 
2100 /* milter8_rcpt_event - report RCPT command to Sendmail 8 milter */
2101 
milter8_rcpt_event(MILTER * m,const char ** argv,ARGV * macros)2102 static const char *milter8_rcpt_event(MILTER *m, const char **argv,
2103                                                       ARGV *macros)
2104 {
2105     const char *myname = "milter8_rcpt_event";
2106     MILTER8 *milter = (MILTER8 *) m;
2107     const char **cpp;
2108     int     skip_reply;
2109 
2110     /*
2111      * Report the event.
2112      */
2113     switch (milter->state) {
2114     case MILTER8_STAT_ERROR:
2115     case MILTER8_STAT_ACCEPT_CON:
2116     case MILTER8_STAT_REJECT_CON:
2117     case MILTER8_STAT_ACCEPT_MSG:
2118           if (msg_verbose)
2119               msg_info("%s: skip milter %s", myname, milter->m.name);
2120           return (milter->def_reply);
2121     case MILTER8_STAT_ENVELOPE:
2122           if (msg_verbose) {
2123               VSTRING *buf = vstring_alloc(100);
2124 
2125               for (cpp = argv; *cpp; cpp++)
2126                     vstring_sprintf_append(buf, " %s", *cpp);
2127               msg_info("%s: milter %s: rcpt%s",
2128                          myname, milter->m.name, STR(buf));
2129               vstring_free(buf);
2130           }
2131           skip_reply = ((milter->ev_mask & SMFIP_NR_RCPT) != 0);
2132           return (milter8_event(milter, SMFIC_RCPT, SMFIP_NORCPT,
2133                                     skip_reply, macros,
2134                                     MILTER8_DATA_ARGV, argv,
2135                                     MILTER8_DATA_END));
2136     default:
2137           msg_panic("%s: milter %s: bad state %d",
2138                       myname, milter->m.name, milter->state);
2139     }
2140 }
2141 
2142 /* milter8_data_event - report DATA command to Sendmail 8 milter */
2143 
milter8_data_event(MILTER * m,ARGV * macros)2144 static const char *milter8_data_event(MILTER *m, ARGV *macros)
2145 {
2146     const char *myname = "milter8_data_event";
2147     MILTER8 *milter = (MILTER8 *) m;
2148     int     skip_reply;
2149 
2150     /*
2151      * Report the event.
2152      */
2153     switch (milter->state) {
2154     case MILTER8_STAT_ERROR:
2155     case MILTER8_STAT_ACCEPT_CON:
2156     case MILTER8_STAT_REJECT_CON:
2157     case MILTER8_STAT_ACCEPT_MSG:
2158           if (msg_verbose)
2159               msg_info("%s: skip milter %s", myname, milter->m.name);
2160           return (milter->def_reply);
2161     case MILTER8_STAT_ENVELOPE:
2162           if (msg_verbose)
2163               msg_info("%s: milter %s: data command", myname, milter->m.name);
2164           skip_reply = ((milter->ev_mask & SMFIP_NR_DATA) != 0);
2165           return (milter8_event(milter, SMFIC_DATA, SMFIP_NODATA,
2166                                     skip_reply, macros,
2167                                     MILTER8_DATA_END));
2168     default:
2169           msg_panic("%s: milter %s: bad state %d",
2170                       myname, milter->m.name, milter->state);
2171     }
2172 }
2173 
2174 /* milter8_unknown_event - report unknown SMTP command to Sendmail 8 milter */
2175 
milter8_unknown_event(MILTER * m,const char * command,ARGV * macros)2176 static const char *milter8_unknown_event(MILTER *m, const char *command,
2177                                                            ARGV *macros)
2178 {
2179     const char *myname = "milter8_unknown_event";
2180     MILTER8 *milter = (MILTER8 *) m;
2181     int     skip_reply;
2182 
2183     /*
2184      * Report the event.
2185      */
2186     switch (milter->state) {
2187     case MILTER8_STAT_ERROR:
2188     case MILTER8_STAT_ACCEPT_CON:
2189     case MILTER8_STAT_REJECT_CON:
2190     case MILTER8_STAT_ACCEPT_MSG:
2191           if (msg_verbose)
2192               msg_info("%s: skip milter %s", myname, milter->m.name);
2193           return (milter->def_reply);
2194     case MILTER8_STAT_ENVELOPE:
2195           if (msg_verbose)
2196               msg_info("%s: milter %s: unknown command: %s",
2197                          myname, milter->m.name, command);
2198           /* XXX Sendmail doesn't send macros (checked with 8.6.13). */
2199           skip_reply = ((milter->ev_mask & SMFIP_NR_UNKN) != 0);
2200           return (milter8_event(milter, SMFIC_UNKNOWN, SMFIP_NOUNKNOWN,
2201                                     skip_reply, macros,
2202                                     MILTER8_DATA_STRING, command,
2203                                     MILTER8_DATA_END));
2204     default:
2205           msg_panic("%s: milter %s: bad state %d",
2206                       myname, milter->m.name, milter->state);
2207     }
2208 }
2209 
2210 /* milter8_other_event - reply for other event */
2211 
milter8_other_event(MILTER * m)2212 static const char *milter8_other_event(MILTER *m)
2213 {
2214     const char *myname = "milter8_other_event";
2215     MILTER8 *milter = (MILTER8 *) m;
2216 
2217     /*
2218      * Return the default reply.
2219      */
2220     if (msg_verbose)
2221           msg_info("%s: milter %s", myname, milter->m.name);
2222     return (milter->def_reply);
2223 }
2224 
2225 /* milter8_abort - cancel one milter's message receiving state */
2226 
milter8_abort(MILTER * m)2227 static void milter8_abort(MILTER *m)
2228 {
2229     const char *myname = "milter8_abort";
2230     MILTER8 *milter = (MILTER8 *) m;
2231 
2232     /*
2233      * XXX Sendmail 8 libmilter closes the MTA-to-filter socket when it finds
2234      * out that the SMTP client has disconnected. Because of this, Postfix
2235      * has to open a new MTA-to-filter socket for each SMTP client.
2236      */
2237     switch (milter->state) {
2238     case MILTER8_STAT_CLOSED:
2239     case MILTER8_STAT_READY:
2240           return;
2241     case MILTER8_STAT_ERROR:
2242     case MILTER8_STAT_ACCEPT_CON:
2243     case MILTER8_STAT_REJECT_CON:
2244           if (msg_verbose)
2245               msg_info("%s: skip milter %s", myname, milter->m.name);
2246           break;
2247     case MILTER8_STAT_ENVELOPE:
2248     case MILTER8_STAT_MESSAGE:
2249     case MILTER8_STAT_ACCEPT_MSG:
2250           if (msg_verbose)
2251               msg_info("%s: abort milter %s", myname, milter->m.name);
2252           (void) milter8_write_cmd(milter, SMFIC_ABORT, MILTER8_DATA_END);
2253           if (milter->state != MILTER8_STAT_ERROR)
2254               milter->state = MILTER8_STAT_ENVELOPE;
2255           break;
2256     default:
2257           msg_panic("%s: milter %s: bad state %d",
2258                       myname, milter->m.name, milter->state);
2259     }
2260 }
2261 
2262 /* milter8_disc_event - report client disconnect event */
2263 
milter8_disc_event(MILTER * m)2264 static void milter8_disc_event(MILTER *m)
2265 {
2266     const char *myname = "milter8_disc_event";
2267     MILTER8 *milter = (MILTER8 *) m;
2268 
2269     /*
2270      * XXX Sendmail 8 libmilter closes the MTA-to-filter socket when it finds
2271      * out that the SMTP client has disconnected. Because of this, Postfix
2272      * has to open a new MTA-to-filter socket for each SMTP client.
2273      */
2274     switch (milter->state) {
2275     case MILTER8_STAT_CLOSED:
2276     case MILTER8_STAT_READY:
2277           return;
2278     case MILTER8_STAT_ERROR:
2279 #ifdef LIBMILTER_AUTO_DISCONNECT
2280     case MILTER8_STAT_ACCEPT_CON:
2281     case MILTER8_STAT_REJECT_CON:
2282 #endif
2283           if (msg_verbose)
2284               msg_info("%s: skip quit milter %s", myname, milter->m.name);
2285           break;
2286     case MILTER8_STAT_ENVELOPE:
2287     case MILTER8_STAT_MESSAGE:
2288 #ifndef LIBMILTER_AUTO_DISCONNECT
2289     case MILTER8_STAT_ACCEPT_CON:
2290     case MILTER8_STAT_REJECT_CON:
2291 #endif
2292     case MILTER8_STAT_ACCEPT_MSG:
2293           if (msg_verbose)
2294               msg_info("%s: quit milter %s", myname, milter->m.name);
2295           (void) milter8_write_cmd(milter, SMFIC_QUIT, MILTER8_DATA_END);
2296           break;
2297     }
2298 #ifdef LIBMILTER_AUTO_DISCONNECT
2299     milter8_close_stream(milter);
2300 #else
2301     if (milter->state != MILTER8_STAT_ERROR)
2302           milter->state = MILTER8_STAT_READY;
2303 #endif
2304     milter8_def_reply(milter, 0);
2305 }
2306 
2307  /*
2308   * Structure to ship context across the MIME_STATE engine.
2309   */
2310 typedef struct {
2311     MILTER8 *milter;                              /* milter client */
2312     ARGV   *eoh_macros;                           /* end-of-header macros */
2313     ARGV   *eod_macros;                           /* end-of-body macros */
2314     ARGV   *auto_hdrs;                            /* auto-generated headers */
2315     int     auto_done;                            /* good enough for now */
2316     int     first_header;               /* first header */
2317     int     first_body;                           /* first body line */
2318     const char *resp;                             /* milter application response */
2319 } MILTER_MSG_CONTEXT;
2320 
2321 /* milter8_header - milter8_message call-back for message header */
2322 
milter8_header(void * ptr,int unused_header_class,const HEADER_OPTS * header_info,VSTRING * buf,off_t unused_offset)2323 static void milter8_header(void *ptr, int unused_header_class,
2324                                          const HEADER_OPTS *header_info,
2325                                          VSTRING *buf, off_t unused_offset)
2326 {
2327     const char *myname = "milter8_header";
2328     MILTER_MSG_CONTEXT *msg_ctx = (MILTER_MSG_CONTEXT *) ptr;
2329     MILTER8 *milter = msg_ctx->milter;
2330     char   *cp;
2331     int     skip_reply;
2332     char  **cpp;
2333     unsigned done;
2334 
2335     /*
2336      * XXX Workaround: mime_state_update() may invoke multiple call-backs
2337      * before returning to the caller.
2338      */
2339 #define MILTER8_MESSAGE_DONE(milter, msg_ctx) \
2340           ((milter)->state != MILTER8_STAT_MESSAGE || (msg_ctx)->resp != 0)
2341 
2342     if (MILTER8_MESSAGE_DONE(milter, msg_ctx))
2343           return;
2344 
2345     /*
2346      * XXX Sendmail compatibility. Don't expose our first (received) header
2347      * to mail filter applications. See also cleanup_milter.c for code to
2348      * ensure that header replace requests are relative to the message
2349      * content as received, that is, without our own first (received) header,
2350      * while header insert requests are relative to the message as delivered,
2351      * that is, including our own first (received) header.
2352      *
2353      * XXX But this breaks when they delete our own Received: header with
2354      * header_checks before it reaches the queue file. Even then we must not
2355      * expose the first header to mail filter applications, otherwise the
2356      * dk-filter signature will be inserted at the wrong position. It should
2357      * precede the headers that it signs.
2358      *
2359      * XXX Sendmail compatibility. It eats the first space (not tab) after the
2360      * header label and ":".
2361      */
2362     for (cpp = msg_ctx->auto_hdrs->argv, done = 1; *cpp; cpp++, done <<= 1)
2363           if ((msg_ctx->auto_done & done) == 0 && strcmp(*cpp, STR(buf)) == 0) {
2364               msg_ctx->auto_done |= done;
2365               return;
2366           }
2367 
2368     /*
2369      * Sendmail 8 sends multi-line headers as text separated by newline.
2370      *
2371      * We destroy the header buffer to split it into label and value. Changing
2372      * the buffer is explicitly allowed by the mime_state(3) interface.
2373      */
2374     if (msg_verbose > 1)
2375           msg_info("%s: header milter %s: %.100s",
2376                      myname, milter->m.name, STR(buf));
2377     cp = STR(buf) + (header_info ? strlen(header_info->name) :
2378                          is_header(STR(buf)));
2379     /* XXX Following matches is_header.c */
2380     while (*cp == ' ' || *cp == '\t')
2381           *cp++ = 0;
2382     if (*cp != ':')
2383           msg_panic("%s: header label not followed by ':'", myname);
2384     *cp++ = 0;
2385     /* XXX Sendmail by default eats one space (not tab) after the colon. */
2386     if ((milter->ev_mask & SMFIP_HDR_LEADSPC) == 0 && *cp == ' ')
2387           cp++;
2388     skip_reply = ((milter->ev_mask & SMFIP_NOHREPL) != 0);
2389     msg_ctx->resp =
2390           milter8_event(milter, SMFIC_HEADER, SMFIP_NOHDRS,
2391                           skip_reply, msg_ctx->eoh_macros,
2392                           MILTER8_DATA_STRING, STR(buf),
2393                           MILTER8_DATA_STRING, cp,
2394                           MILTER8_DATA_END);
2395 }
2396 
2397 /* milter8_eoh - milter8_message call-back for end-of-header */
2398 
milter8_eoh(void * ptr)2399 static void milter8_eoh(void *ptr)
2400 {
2401     const char *myname = "milter8_eoh";
2402     MILTER_MSG_CONTEXT *msg_ctx = (MILTER_MSG_CONTEXT *) ptr;
2403     MILTER8 *milter = msg_ctx->milter;
2404     int     skip_reply;
2405 
2406     if (MILTER8_MESSAGE_DONE(milter, msg_ctx))
2407           return;
2408     if (msg_verbose)
2409           msg_info("%s: eoh milter %s", myname, milter->m.name);
2410     skip_reply = ((milter->ev_mask & SMFIP_NR_EOH) != 0);
2411     msg_ctx->resp =
2412           milter8_event(milter, SMFIC_EOH, SMFIP_NOEOH,
2413                           skip_reply, msg_ctx->eoh_macros,
2414                           MILTER8_DATA_END);
2415 }
2416 
2417 /* milter8_body - milter8_message call-back for body content */
2418 
milter8_body(void * ptr,int rec_type,const char * buf,ssize_t len,off_t offset)2419 static void milter8_body(void *ptr, int rec_type,
2420                                        const char *buf, ssize_t len,
2421                                        off_t offset)
2422 {
2423     const char *myname = "milter8_body";
2424     MILTER_MSG_CONTEXT *msg_ctx = (MILTER_MSG_CONTEXT *) ptr;
2425     MILTER8 *milter = msg_ctx->milter;
2426     ssize_t todo = len;
2427     const char *bp = buf;
2428     ssize_t space;
2429     ssize_t count;
2430     int     skip_reply;
2431 
2432     if (MILTER8_MESSAGE_DONE(milter, msg_ctx))
2433           return;
2434 
2435     /*
2436      * XXX Sendmail compatibility: don't expose our first body line.
2437      */
2438     if (msg_ctx->first_body) {
2439           msg_ctx->first_body = 0;
2440           return;
2441     }
2442 
2443     /*
2444      * XXX I thought I was going to delegate all the on-the-wire formatting
2445      * to a common lower layer, but unfortunately it's not practical. If we
2446      * were to do MILTER_CHUNK_SIZE buffering in a common lower layer, then
2447      * we would have to pass along call-backs and state, so that the
2448      * call-back can invoke milter8_event() with the right arguments when the
2449      * MILTER_CHUNK_SIZE buffer reaches capacity. That's just too ugly.
2450      *
2451      * To recover the cost of making an extra copy of body content from Milter
2452      * buffer to VSTREAM buffer, we could make vstream_fwrite() a little
2453      * smarter so that it does large transfers directly from the user buffer
2454      * instead of copying the data one block at a time into a VSTREAM buffer.
2455      */
2456     if (msg_verbose > 1)
2457           msg_info("%s: body milter %s: %.100s", myname, milter->m.name, buf);
2458     skip_reply = ((milter->ev_mask & SMFIP_NR_BODY) != 0);
2459     /* To append \r\n, simply redirect input to another buffer. */
2460     if (rec_type == REC_TYPE_NORM && todo == 0) {
2461           bp = "\r\n";
2462           todo = 2;
2463           rec_type = REC_TYPE_EOF;
2464     }
2465     while (todo > 0) {
2466           /* Append one REC_TYPE_NORM or REC_TYPE_CONT to body chunk buffer. */
2467           space = MILTER_CHUNK_SIZE - LEN(milter->body);
2468           if (space <= 0)
2469               msg_panic("%s: bad buffer size: %ld",
2470                           myname, (long) LEN(milter->body));
2471           count = (todo > space ? space : todo);
2472           vstring_memcat(milter->body, bp, count);
2473           bp += count;
2474           todo -= count;
2475           /* Flush body chunk buffer when full. See also milter8_eob(). */
2476           if (LEN(milter->body) == MILTER_CHUNK_SIZE) {
2477               msg_ctx->resp =
2478                     milter8_event(milter, SMFIC_BODY, SMFIP_NOBODY,
2479                                     skip_reply, msg_ctx->eod_macros,
2480                                     MILTER8_DATA_BUFFER, milter->body,
2481                                     MILTER8_DATA_END);
2482               if (MILTER8_MESSAGE_DONE(milter, msg_ctx))
2483                     break;
2484               VSTRING_RESET(milter->body);
2485           }
2486           /* To append \r\n, simply redirect input to another buffer. */
2487           if (rec_type == REC_TYPE_NORM && todo == 0) {
2488               bp = "\r\n";
2489               todo = 2;
2490               rec_type = REC_TYPE_EOF;
2491           }
2492     }
2493 }
2494 
2495 /* milter8_eob - milter8_message call-back for end-of-body */
2496 
milter8_eob(void * ptr)2497 static void milter8_eob(void *ptr)
2498 {
2499     const char *myname = "milter8_eob";
2500     MILTER_MSG_CONTEXT *msg_ctx = (MILTER_MSG_CONTEXT *) ptr;
2501     MILTER8 *milter = msg_ctx->milter;
2502     int     skip_reply;
2503 
2504     if (MILTER8_MESSAGE_DONE(milter, msg_ctx))
2505           return;
2506     if (msg_verbose)
2507           msg_info("%s: eob milter %s", myname, milter->m.name);
2508 
2509     /*
2510      * Flush partial body chunk buffer. See also milter8_body().
2511      *
2512      * XXX Sendmail 8 libmilter accepts SMFIC_EOB+data, and delivers it to the
2513      * application as two events: SMFIC_BODY+data followed by SMFIC_EOB. This
2514      * breaks with the PMilter 0.95 protocol re-implementation, which
2515      * delivers the SMFIC_EOB event and ignores the data. To avoid such
2516      * compatibility problems we separate the events in the client. With
2517      * this, we also prepare for a future where different event types can
2518      * have different macro lists.
2519      */
2520     if (LEN(milter->body) > 0) {
2521           skip_reply = ((milter->ev_mask & SMFIP_NR_BODY) != 0);
2522           msg_ctx->resp =
2523               milter8_event(milter, SMFIC_BODY, SMFIP_NOBODY,
2524                                 skip_reply, msg_ctx->eod_macros,
2525                                 MILTER8_DATA_BUFFER, milter->body,
2526                                 MILTER8_DATA_END);
2527           if (MILTER8_MESSAGE_DONE(milter, msg_ctx))
2528               return;
2529     }
2530     msg_ctx->resp =
2531           milter8_event(msg_ctx->milter, SMFIC_BODYEOB, 0,
2532                           DONT_SKIP_REPLY, msg_ctx->eod_macros,
2533                           MILTER8_DATA_END);
2534 }
2535 
2536 /* milter8_message - send message content and receive reply */
2537 
milter8_message(MILTER * m,VSTREAM * qfile,off_t data_offset,ARGV * eoh_macros,ARGV * eod_macros,ARGV * auto_hdrs)2538 static const char *milter8_message(MILTER *m, VSTREAM *qfile,
2539                                                    off_t data_offset,
2540                                                    ARGV *eoh_macros,
2541                                                    ARGV *eod_macros,
2542                                                    ARGV *auto_hdrs)
2543 {
2544     const char *myname = "milter8_message";
2545     MILTER8 *milter = (MILTER8 *) m;
2546     MIME_STATE *mime_state;
2547     int     rec_type;
2548     const MIME_STATE_DETAIL *detail;
2549     int     mime_errs = 0;
2550     MILTER_MSG_CONTEXT msg_ctx;
2551     VSTRING *buf;
2552     int     saved_errno;
2553 
2554     switch (milter->state) {
2555     case MILTER8_STAT_ERROR:
2556     case MILTER8_STAT_ACCEPT_CON:
2557     case MILTER8_STAT_REJECT_CON:
2558     case MILTER8_STAT_ACCEPT_MSG:
2559           if (msg_verbose)
2560               msg_info("%s: skip message to milter %s", myname, milter->m.name);
2561           return (milter->def_reply);
2562     case MILTER8_STAT_ENVELOPE:
2563           if (msg_verbose)
2564               msg_info("%s: message to milter %s", myname, milter->m.name);
2565           if (vstream_fseek(qfile, data_offset, SEEK_SET) < 0) {
2566               saved_errno = errno;
2567               msg_warn("%s: vstream_fseek %s: %m", myname, VSTREAM_PATH(qfile));
2568               /* XXX This should be available from cleanup_strerror.c. */
2569               return (saved_errno == EFBIG ?
2570                         "552 5.3.4 Message file too big" :
2571                         "451 4.3.0 Queue file write error");
2572           }
2573           msg_ctx.milter = milter;
2574           msg_ctx.eoh_macros = eoh_macros;
2575           msg_ctx.eod_macros = eod_macros;
2576           msg_ctx.auto_hdrs = auto_hdrs;
2577           msg_ctx.auto_done = 0;
2578           msg_ctx.first_header = 1;
2579           msg_ctx.first_body = 1;
2580           msg_ctx.resp = 0;
2581           mime_state =
2582               mime_state_alloc(MIME_OPT_DISABLE_MIME,
2583                                    (milter->ev_mask & SMFIP_NOHDRS) ?
2584                                    (MIME_STATE_HEAD_OUT) 0 : milter8_header,
2585                                    (milter->ev_mask & SMFIP_NOEOH) ?
2586                                    (MIME_STATE_ANY_END) 0 : milter8_eoh,
2587                                    (milter->ev_mask & SMFIP_NOBODY) ?
2588                                    (MIME_STATE_BODY_OUT) 0 : milter8_body,
2589                                    milter8_eob,
2590                                    (MIME_STATE_ERR_PRINT) 0,
2591                                    (void *) &msg_ctx);
2592           buf = vstring_alloc(100);
2593           milter->state = MILTER8_STAT_MESSAGE;
2594           VSTRING_RESET(milter->body);
2595           vstream_control(milter->fp,
2596                               CA_VSTREAM_CTL_DOUBLE,
2597                               CA_VSTREAM_CTL_TIMEOUT(milter->msg_timeout),
2598                               CA_VSTREAM_CTL_END);
2599 
2600           /*
2601            * XXX When the message (not MIME body part) does not end in CRLF
2602            * (i.e. the last record was REC_TYPE_CONT), do we send a CRLF
2603            * terminator before triggering the end-of-body condition?
2604            */
2605           for (;;) {
2606               if ((rec_type = rec_get(qfile, buf, 0)) < 0) {
2607                     msg_warn("%s: error reading %s: %m",
2608                                myname, VSTREAM_PATH(qfile));
2609                     msg_ctx.resp = "450 4.3.0 Queue file write error";
2610                     break;
2611               }
2612               /* Invoke the appropriate call-back routine. */
2613               mime_errs = mime_state_update(mime_state, rec_type,
2614                                                     STR(buf), LEN(buf));
2615               if (mime_errs) {
2616                     detail = mime_state_detail(mime_errs);
2617                     msg_warn("%s: MIME problem %s in %s",
2618                                myname, detail->text, VSTREAM_PATH(qfile));
2619                     msg_ctx.resp = "450 4.3.0 Queue file write error";
2620                     break;
2621               }
2622               if (MILTER8_MESSAGE_DONE(milter, &msg_ctx))
2623                     break;
2624               if (rec_type != REC_TYPE_NORM && rec_type != REC_TYPE_CONT)
2625                     break;
2626           }
2627           mime_state_free(mime_state);
2628           vstring_free(buf);
2629           if (milter->fp)
2630               vstream_control(milter->fp,
2631                                   CA_VSTREAM_CTL_DOUBLE,
2632                                   CA_VSTREAM_CTL_TIMEOUT(milter->cmd_timeout),
2633                                   CA_VSTREAM_CTL_END);
2634           if (milter->state == MILTER8_STAT_MESSAGE
2635               || milter->state == MILTER8_STAT_ACCEPT_MSG)
2636               milter->state = MILTER8_STAT_ENVELOPE;
2637           return (msg_ctx.resp);
2638     default:
2639           msg_panic("%s: milter %s: bad state %d",
2640                       myname, milter->m.name, milter->state);
2641     }
2642 }
2643 
2644  /*
2645   * Preliminary protocol to send/receive milter instances. This needs to be
2646   * extended with type information once we support multiple milter protocols.
2647   */
2648 #define MAIL_ATTR_MILT_NAME   "milter_name"
2649 #define MAIL_ATTR_MILT_VERS   "milter_version"
2650 #define MAIL_ATTR_MILT_ACTS   "milter_actions"
2651 #define MAIL_ATTR_MILT_EVTS   "milter_events"
2652 #define MAIL_ATTR_MILT_NPTS   "milter_non_events"
2653 #define MAIL_ATTR_MILT_STAT   "milter_state"
2654 #define MAIL_ATTR_MILT_CONN   "milter_conn_timeout"
2655 #define MAIL_ATTR_MILT_CMD    "milter_cmd_timeout"
2656 #define MAIL_ATTR_MILT_MSG    "milter_msg_timeout"
2657 #define MAIL_ATTR_MILT_ACT    "milter_action"
2658 #define MAIL_ATTR_MILT_MAC    "milter_macro_list"
2659 
2660 /* milter8_active - report if this milter still wants events */
2661 
milter8_active(MILTER * m)2662 static int milter8_active(MILTER *m)
2663 {
2664     MILTER8 *milter = (MILTER8 *) m;
2665 
2666     return (milter->fp != 0
2667               && (milter->state == MILTER8_STAT_ENVELOPE
2668                     || milter->state == MILTER8_STAT_READY));
2669 }
2670 
2671 /* milter8_send - send milter instance */
2672 
milter8_send(MILTER * m,VSTREAM * stream)2673 static int milter8_send(MILTER *m, VSTREAM *stream)
2674 {
2675     const char *myname = "milter8_send";
2676     MILTER8 *milter = (MILTER8 *) m;
2677 
2678     if (msg_verbose)
2679           msg_info("%s: milter %s", myname, milter->m.name);
2680 
2681     /*
2682      * The next read on this Milter socket happens in a different process. It
2683      * will not automatically flush the output buffer in this process.
2684      */
2685     if (milter->fp)
2686           vstream_fflush(milter->fp);
2687 
2688     if (attr_print(stream, ATTR_FLAG_MORE,
2689                        SEND_ATTR_STR(MAIL_ATTR_MILT_NAME, milter->m.name),
2690                        SEND_ATTR_INT(MAIL_ATTR_MILT_VERS, milter->version),
2691                        SEND_ATTR_INT(MAIL_ATTR_MILT_ACTS, milter->rq_mask),
2692                        SEND_ATTR_INT(MAIL_ATTR_MILT_EVTS, milter->ev_mask),
2693                        SEND_ATTR_INT(MAIL_ATTR_MILT_NPTS, milter->np_mask),
2694                        SEND_ATTR_INT(MAIL_ATTR_MILT_STAT, milter->state),
2695                        SEND_ATTR_INT(MAIL_ATTR_MILT_CONN, milter->conn_timeout),
2696                        SEND_ATTR_INT(MAIL_ATTR_MILT_CMD, milter->cmd_timeout),
2697                        SEND_ATTR_INT(MAIL_ATTR_MILT_MSG, milter->msg_timeout),
2698                        SEND_ATTR_STR(MAIL_ATTR_MILT_ACT, milter->def_action),
2699                        SEND_ATTR_INT(MAIL_ATTR_MILT_MAC, milter->m.macros != 0),
2700                        ATTR_TYPE_END) != 0
2701           || (milter->m.macros != 0
2702               && attr_print(stream, ATTR_FLAG_NONE,
2703                                 SEND_ATTR_FUNC(milter_macros_print,
2704                                                    (const void *) milter->m.macros),
2705                                 ATTR_TYPE_END) != 0)
2706           || (milter->m.macros == 0
2707               && attr_print(stream, ATTR_FLAG_NONE,
2708                                 ATTR_TYPE_END) != 0)
2709           || vstream_fflush(stream) != 0) {
2710           return (-1);
2711 #ifdef CANT_WRITE_BEFORE_SENDING_FD
2712     } else if (attr_scan(stream, ATTR_FLAG_STRICT,
2713                                RECV_ATTR_STR(MAIL_ATTR_DUMMY, milter->buf),
2714                                ATTR_TYPE_END) != 1) {
2715           return (-1);
2716 #endif
2717     } else if (LOCAL_SEND_FD(vstream_fileno(stream),
2718                                    vstream_fileno(milter->fp)) < 0) {
2719           return (-1);
2720 #ifdef MUST_READ_AFTER_SENDING_FD
2721     } else if (attr_scan(stream, ATTR_FLAG_STRICT,
2722                                RECV_ATTR_STR(MAIL_ATTR_DUMMY, milter->buf),
2723                                ATTR_TYPE_END) != 1) {
2724           return (-1);
2725 #endif
2726     } else {
2727           return (0);
2728     }
2729 }
2730 
2731 static MILTER8 *milter8_alloc(const char *, int, int, int, const char *,
2732                                             const char *, MILTERS *);
2733 
2734 /* milter8_receive - receive milter instance */
2735 
milter8_receive(VSTREAM * stream,MILTERS * parent)2736 MILTER *milter8_receive(VSTREAM *stream, MILTERS *parent)
2737 {
2738     const char *myname = "milter8_receive";
2739     static VSTRING *name_buf;
2740     static VSTRING *act_buf;
2741     MILTER8 *milter;
2742     int     version;
2743     int     rq_mask;
2744     int     ev_mask;
2745     int     np_mask;
2746     int     state;
2747     int     conn_timeout;
2748     int     cmd_timeout;
2749     int     msg_timeout;
2750     int     fd;
2751     int     has_macros;
2752     MILTER_MACROS *macros = 0;
2753 
2754 #define FREE_MACROS_AND_RETURN(x) do { \
2755           if (macros) \
2756               milter_macros_free(macros); \
2757           return (x); \
2758     } while (0)
2759 
2760     if (name_buf == 0) {
2761           name_buf = vstring_alloc(10);
2762           act_buf = vstring_alloc(10);
2763     }
2764     if (attr_scan(stream, ATTR_FLAG_STRICT | ATTR_FLAG_MORE,
2765                       RECV_ATTR_STR(MAIL_ATTR_MILT_NAME, name_buf),
2766                       RECV_ATTR_INT(MAIL_ATTR_MILT_VERS, &version),
2767                       RECV_ATTR_INT(MAIL_ATTR_MILT_ACTS, &rq_mask),
2768                       RECV_ATTR_INT(MAIL_ATTR_MILT_EVTS, &ev_mask),
2769                       RECV_ATTR_INT(MAIL_ATTR_MILT_NPTS, &np_mask),
2770                       RECV_ATTR_INT(MAIL_ATTR_MILT_STAT, &state),
2771                       RECV_ATTR_INT(MAIL_ATTR_MILT_CONN, &conn_timeout),
2772                       RECV_ATTR_INT(MAIL_ATTR_MILT_CMD, &cmd_timeout),
2773                       RECV_ATTR_INT(MAIL_ATTR_MILT_MSG, &msg_timeout),
2774                       RECV_ATTR_STR(MAIL_ATTR_MILT_ACT, act_buf),
2775                       RECV_ATTR_INT(MAIL_ATTR_MILT_MAC, &has_macros),
2776                       ATTR_TYPE_END) < 10
2777           || (has_macros != 0
2778               && attr_scan(stream, ATTR_FLAG_STRICT,
2779                                RECV_ATTR_FUNC(milter_macros_scan,
2780                                                   (void *) (macros =
2781                                   milter_macros_alloc(MILTER_MACROS_ALLOC_ZERO))),
2782                                ATTR_TYPE_END) < 1)
2783           || (has_macros == 0
2784               && attr_scan(stream, ATTR_FLAG_STRICT,
2785                                ATTR_TYPE_END) < 0)) {
2786           FREE_MACROS_AND_RETURN(0);
2787 #ifdef CANT_WRITE_BEFORE_SENDING_FD
2788     } else if (attr_print(stream, ATTR_FLAG_NONE,
2789                                 SEND_ATTR_STR(MAIL_ATTR_DUMMY, ""),
2790                                 ATTR_TYPE_END) != 0
2791                  || vstream_fflush(stream) != 0) {
2792           FREE_MACROS_AND_RETURN(0);
2793 #endif
2794     } else if ((fd = LOCAL_RECV_FD(vstream_fileno(stream))) < 0) {
2795           FREE_MACROS_AND_RETURN(0);
2796     } else {
2797 #ifdef MUST_READ_AFTER_SENDING_FD
2798           (void) attr_print(stream, ATTR_FLAG_NONE,
2799                                 SEND_ATTR_STR(MAIL_ATTR_DUMMY, ""),
2800                                 ATTR_TYPE_END);
2801 #endif
2802 #define NO_PROTOCOL ((char *) 0)
2803 
2804           if (msg_verbose)
2805               msg_info("%s: milter %s", myname, STR(name_buf));
2806 
2807           milter = milter8_alloc(STR(name_buf), conn_timeout, cmd_timeout,
2808                                   msg_timeout, NO_PROTOCOL, STR(act_buf), parent);
2809           milter->fp = vstream_fdopen(fd, O_RDWR);
2810           milter->m.macros = macros;
2811           vstream_control(milter->fp, CA_VSTREAM_CTL_DOUBLE, CA_VSTREAM_CTL_END);
2812           /* Avoid poor performance when TCP MSS > VSTREAM_BUFSIZE. */
2813           vstream_tweak_sock(milter->fp);
2814           milter->version = version;
2815           milter->rq_mask = rq_mask;
2816           milter->ev_mask = ev_mask;
2817           milter->np_mask = np_mask;
2818           milter->state = state;
2819           return (&milter->m);
2820     }
2821 }
2822 
2823 /* milter8_free - destroy Milter instance */
2824 
milter8_free(MILTER * m)2825 static void milter8_free(MILTER *m)
2826 {
2827     MILTER8 *milter = (MILTER8 *) m;
2828 
2829     if (msg_verbose)
2830           msg_info("free milter %s", milter->m.name);
2831     if (milter->fp)
2832           (void) vstream_fclose(milter->fp);
2833     myfree(milter->m.name);
2834     vstring_free(milter->buf);
2835     vstring_free(milter->body);
2836     if (milter->protocol)
2837           myfree(milter->protocol);
2838     myfree(milter->def_action);
2839     if (milter->def_reply)
2840           myfree(milter->def_reply);
2841     if (milter->m.macros)
2842           milter_macros_free(milter->m.macros);
2843     myfree((void *) milter);
2844 }
2845 
2846 /* milter8_alloc - create MTA-side Sendmail 8 Milter instance */
2847 
milter8_alloc(const char * name,int conn_timeout,int cmd_timeout,int msg_timeout,const char * protocol,const char * def_action,MILTERS * parent)2848 static MILTER8 *milter8_alloc(const char *name, int conn_timeout,
2849                                             int cmd_timeout, int msg_timeout,
2850                                             const char *protocol,
2851                                             const char *def_action,
2852                                             MILTERS *parent)
2853 {
2854     MILTER8 *milter;
2855 
2856     /*
2857      * Fill in the structure. Note: all strings must be copied.
2858      *
2859      * XXX Sendmail 8 libmilter closes the MTA-to-filter socket when it finds
2860      * out that the SMTP client has disconnected. Because of this, Postfix
2861      * has to open a new MTA-to-filter socket for each SMTP client.
2862      */
2863     milter = (MILTER8 *) mymalloc(sizeof(*milter));
2864     milter->m.name = mystrdup(name);
2865     milter->m.flags = 0;
2866     milter->m.next = 0;
2867     milter->m.parent = parent;
2868     milter->m.macros = 0;
2869 #ifdef LIBMILTER_AUTO_DISCONNECT
2870     milter->m.connect_on_demand = (void (*) (struct MILTER *)) milter8_connect;
2871 #else
2872     milter->m.connect_on_demand = 0;
2873 #endif
2874     milter->m.conn_event = milter8_conn_event;
2875     milter->m.helo_event = milter8_helo_event;
2876     milter->m.mail_event = milter8_mail_event;
2877     milter->m.rcpt_event = milter8_rcpt_event;
2878     milter->m.data_event = milter8_data_event;    /* may be null */
2879     milter->m.message = milter8_message;
2880     milter->m.unknown_event = milter8_unknown_event;        /* may be null */
2881     milter->m.other_event = milter8_other_event;
2882     milter->m.abort = milter8_abort;
2883     milter->m.disc_event = milter8_disc_event;
2884     milter->m.active = milter8_active;
2885     milter->m.send = milter8_send;
2886     milter->m.free = milter8_free;
2887     milter->fp = 0;
2888     milter->buf = vstring_alloc(100);
2889     milter->body = vstring_alloc(100);
2890     milter->version = 0;
2891     milter->rq_mask = 0;
2892     milter->ev_mask = 0;
2893     milter->state = MILTER8_STAT_CLOSED;
2894     milter->conn_timeout = conn_timeout;
2895     milter->cmd_timeout = cmd_timeout;
2896     milter->msg_timeout = msg_timeout;
2897     milter->protocol = (protocol ? mystrdup(protocol) : 0);
2898     milter->def_action = mystrdup(def_action);
2899     milter->def_reply = 0;
2900     milter->skip_event_type = 0;
2901 
2902     return (milter);
2903 }
2904 
2905 /* milter8_create - create MTA-side Sendmail 8 Milter instance */
2906 
milter8_create(const char * name,int conn_timeout,int cmd_timeout,int msg_timeout,const char * protocol,const char * def_action,MILTERS * parent)2907 MILTER *milter8_create(const char *name, int conn_timeout, int cmd_timeout,
2908                                    int msg_timeout, const char *protocol,
2909                                    const char *def_action, MILTERS *parent)
2910 {
2911     MILTER8 *milter;
2912 
2913     /*
2914      * Fill in the structure.
2915      */
2916     milter = milter8_alloc(name, conn_timeout, cmd_timeout, msg_timeout,
2917                                  protocol, def_action, parent);
2918 
2919     /*
2920      * XXX Sendmail 8 libmilter closes the MTA-to-filter socket when it finds
2921      * out that the SMTP client has disconnected. Because of this, Postfix
2922      * has to open a new MTA-to-filter socket for each SMTP client.
2923      */
2924 #ifndef LIBMILTER_AUTO_DISCONNECT
2925     milter8_connect(milter);
2926 #endif
2927     return (&milter->m);
2928 }
2929