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