7 /* MTA-side Sendmail 8 Milter protocol
9 /* #include <milter8.h>
11 /* MILTER *milter8_create(name, conn_timeout, cmd_timeout, msg_timeout,
12 /* protocol, def_action, parent)
17 /* const char *protocol;
18 /* const char *def_action;
21 /* MILTER *milter8_receive(stream)
24 /* This module implements the MTA side of the Sendmail 8 mail
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.
34 /* milter8_receive() receives a mail filter definition from the
35 /* specified stream. The result is zero in case of success.
39 /* The Milter application endpoint, either inet:host:port or
42 /* Panic: interface violation. Fatal errors: out of memory.
43 /* CONFIGURATION PARAMETERS
44 /* milter8_protocol, protocol version and extensions
46 /* milter(3) generic Milter interface
50 /* The Secure Mailer license must be distributed with this software.
53 /* IBM T.J. Watson Research
55 /* Yorktown Heights, NY 10598, USA
61 #include <sys/socket.h>
62 #include <netinet/in.h>
63 #include <arpa/inet.h>
65 #include <stddef.h> /* offsetof() */
69 #include <limits.h> /* INT_MAX */
75 /* Utility library. */
82 #include <name_mask.h>
83 #include <name_code.h>
84 #include <stringops.h>
88 #include <mail_params.h>
89 #include <mail_proto.h>
92 #include <mime_state.h>
93 #include <is_header.h>
95 /* Postfix Milter library. */
99 /* Application-specific. */
102 * Use our own protocol definitions, so that Postfix can be built even when
103 * libmilter is not installed. This means that we must specify the libmilter
104 * protocol version in main.cf, and that we must send only the commands that
105 * are supported for that protocol version.
109 * Commands from MTA to filter.
111 #define SMFIC_ABORT 'A' /* Abort */
112 #define SMFIC_BODY 'B' /* Body chunk */
113 #define SMFIC_CONNECT 'C' /* Connection information */
114 #define SMFIC_MACRO 'D' /* Define macro */
115 #define SMFIC_BODYEOB 'E' /* final body chunk (End) */
116 #define SMFIC_HELO 'H' /* HELO/EHLO */
117 #define SMFIC_HEADER 'L' /* Header */
118 #define SMFIC_MAIL 'M' /* MAIL from */
119 #define SMFIC_EOH 'N' /* EOH */
120 #define SMFIC_OPTNEG 'O' /* Option negotiation */
121 #define SMFIC_QUIT 'Q' /* QUIT */
122 #define SMFIC_RCPT 'R' /* RCPT to */
123 #define SMFIC_DATA 'T' /* DATA */
124 #define SMFIC_UNKNOWN 'U' /* Any unknown command */
125 /* Introduced with Sendmail 8.14. */
126 #define SMFIC_QUIT_NC 'K' /* Quit + new connection */
128 static const NAME_CODE smfic_table
[] = {
129 "SMFIC_ABORT", SMFIC_ABORT
,
130 "SMFIC_BODY", SMFIC_BODY
,
131 "SMFIC_CONNECT", SMFIC_CONNECT
,
132 "SMFIC_MACRO", SMFIC_MACRO
,
133 "SMFIC_BODYEOB", SMFIC_BODYEOB
,
134 "SMFIC_HELO", SMFIC_HELO
,
135 "SMFIC_HEADER", SMFIC_HEADER
,
136 "SMFIC_MAIL", SMFIC_MAIL
,
137 "SMFIC_EOH", SMFIC_EOH
,
138 "SMFIC_OPTNEG", SMFIC_OPTNEG
,
139 "SMFIC_QUIT", SMFIC_QUIT
,
140 "SMFIC_RCPT", SMFIC_RCPT
,
141 "SMFIC_DATA", SMFIC_DATA
,
142 "SMFIC_UNKNOWN", SMFIC_UNKNOWN
,
143 /* Introduced with Sendmail 8.14. */
144 "SMFIC_QUIT_NC", SMFIC_QUIT_NC
,
149 * Responses from filter to MTA.
151 #define SMFIR_ADDRCPT '+' /* add recipient */
152 #define SMFIR_DELRCPT '-' /* remove recipient */
153 #define SMFIR_ACCEPT 'a' /* accept */
154 #define SMFIR_REPLBODY 'b' /* replace body (chunk) */
155 #define SMFIR_CONTINUE 'c' /* continue */
156 #define SMFIR_DISCARD 'd' /* discard */
157 #define SMFIR_CONN_FAIL 'f' /* cause a connection failure */
158 #define SMFIR_CHGHEADER 'm' /* change header */
159 #define SMFIR_PROGRESS 'p' /* progress */
160 #define SMFIR_REJECT 'r' /* reject */
161 #define SMFIR_TEMPFAIL 't' /* tempfail */
162 #define SMFIR_SHUTDOWN '4' /* 421: shutdown (internal to MTA) */
163 #define SMFIR_ADDHEADER 'h' /* add header */
164 #define SMFIR_INSHEADER 'i' /* insert header */
165 #define SMFIR_REPLYCODE 'y' /* reply code etc */
166 #define SMFIR_QUARANTINE 'q' /* quarantine */
167 /* Introduced with Sendmail 8.14. */
168 #define SMFIR_SKIP 's' /* skip further events of this type */
169 #define SMFIR_CHGFROM 'e' /* change sender (incl. ESMTP args) */
170 #define SMFIR_ADDRCPT_PAR '2' /* add recipient (incl. ESMTP args) */
171 #define SMFIR_SETSYMLIST 'l' /* set list of symbols (macros) */
173 static const NAME_CODE smfir_table
[] = {
174 "SMFIR_ADDRCPT", SMFIR_ADDRCPT
,
175 "SMFIR_DELRCPT", SMFIR_DELRCPT
,
176 "SMFIR_ACCEPT", SMFIR_ACCEPT
,
177 "SMFIR_REPLBODY", SMFIR_REPLBODY
,
178 "SMFIR_CONTINUE", SMFIR_CONTINUE
,
179 "SMFIR_DISCARD", SMFIR_DISCARD
,
180 "SMFIR_CONN_FAIL", SMFIR_CONN_FAIL
,
181 "SMFIR_CHGHEADER", SMFIR_CHGHEADER
,
182 "SMFIR_PROGRESS", SMFIR_PROGRESS
,
183 "SMFIR_REJECT", SMFIR_REJECT
,
184 "SMFIR_TEMPFAIL", SMFIR_TEMPFAIL
,
185 "SMFIR_SHUTDOWN", SMFIR_SHUTDOWN
,
186 "SMFIR_ADDHEADER", SMFIR_ADDHEADER
,
187 "SMFIR_INSHEADER", SMFIR_INSHEADER
,
188 "SMFIR_REPLYCODE", SMFIR_REPLYCODE
,
189 "SMFIR_QUARANTINE", SMFIR_QUARANTINE
,
190 /* Introduced with Sendmail 8.14. */
191 "SMFIR_SKIP", SMFIR_SKIP
,
192 "SMFIR_CHGFROM", SMFIR_CHGFROM
,
193 "SMFIR_ADDRCPT_PAR", SMFIR_ADDRCPT_PAR
,
194 "SMFIR_SETSYMLIST", SMFIR_SETSYMLIST
,
199 * Commands that the filter does not want to receive, and replies that the
200 * filter will not send. Plus some other random stuff.
202 #define SMFIP_NOCONNECT (1L<<0) /* filter does not want connect info */
203 #define SMFIP_NOHELO (1L<<1) /* filter does not want HELO info */
204 #define SMFIP_NOMAIL (1L<<2) /* filter does not want MAIL info */
205 #define SMFIP_NORCPT (1L<<3) /* filter does not want RCPT info */
206 #define SMFIP_NOBODY (1L<<4) /* filter does not want body */
207 #define SMFIP_NOHDRS (1L<<5) /* filter does not want headers */
208 #define SMFIP_NOEOH (1L<<6) /* filter does not want EOH */
209 #define SMFIP_NR_HDR (1L<<7) /* filter won't reply for header */
210 #define SMFIP_NOHREPL SMFIP_NR_HDR
211 #define SMFIP_NOUNKNOWN (1L<<8) /* filter does not want unknown cmd */
212 #define SMFIP_NODATA (1L<<9) /* filter does not want DATA */
213 /* Introduced with Sendmail 8.14. */
214 #define SMFIP_SKIP (1L<<10)/* MTA supports SMFIS_SKIP */
215 #define SMFIP_RCPT_REJ (1L<<11)/* filter wants rejected RCPTs */
216 #define SMFIP_NR_CONN (1L<<12)/* filter won't reply for connect */
217 #define SMFIP_NR_HELO (1L<<13)/* filter won't reply for HELO */
218 #define SMFIP_NR_MAIL (1L<<14)/* filter won't reply for MAIL */
219 #define SMFIP_NR_RCPT (1L<<15)/* filter won't reply for RCPT */
220 #define SMFIP_NR_DATA (1L<<16)/* filter won't reply for DATA */
221 #define SMFIP_NR_UNKN (1L<<17)/* filter won't reply for UNKNOWN */
222 #define SMFIP_NR_EOH (1L<<18)/* filter won't reply for eoh */
223 #define SMFIP_NR_BODY (1L<<19)/* filter won't reply for body chunk */
224 #define SMFIP_HDR_LEADSPC (1L<<20)/* header value has leading space */
226 #define SMFIP_NOSEND_MASK \
227 (SMFIP_NOCONNECT | SMFIP_NOHELO | SMFIP_NOMAIL | SMFIP_NORCPT \
228 | SMFIP_NOBODY | SMFIP_NOHDRS | SMFIP_NOEOH | SMFIP_NOUNKNOWN \
231 #define SMFIP_NOREPLY_MASK \
232 (SMFIP_NR_CONN | SMFIP_NR_HELO | SMFIP_NR_MAIL | SMFIP_NR_RCPT \
233 | SMFIP_NR_DATA | SMFIP_NR_UNKN | SMFIP_NR_HDR | SMFIP_NR_EOH | \
236 static const NAME_MASK smfip_table
[] = {
237 "SMFIP_NOCONNECT", SMFIP_NOCONNECT
,
238 "SMFIP_NOHELO", SMFIP_NOHELO
,
239 "SMFIP_NOMAIL", SMFIP_NOMAIL
,
240 "SMFIP_NORCPT", SMFIP_NORCPT
,
241 "SMFIP_NOBODY", SMFIP_NOBODY
,
242 "SMFIP_NOHDRS", SMFIP_NOHDRS
,
243 "SMFIP_NOEOH", SMFIP_NOEOH
,
244 "SMFIP_NR_HDR", SMFIP_NR_HDR
,
245 "SMFIP_NOUNKNOWN", SMFIP_NOUNKNOWN
,
246 "SMFIP_NODATA", SMFIP_NODATA
,
247 /* Introduced with Sendmail 8.14. */
248 "SMFIP_SKIP", SMFIP_SKIP
,
249 "SMFIP_RCPT_REJ", SMFIP_RCPT_REJ
,
250 "SMFIP_NR_CONN", SMFIP_NR_CONN
,
251 "SMFIP_NR_HELO", SMFIP_NR_HELO
,
252 "SMFIP_NR_MAIL", SMFIP_NR_MAIL
,
253 "SMFIP_NR_RCPT", SMFIP_NR_RCPT
,
254 "SMFIP_NR_DATA", SMFIP_NR_DATA
,
255 "SMFIP_NR_UNKN", SMFIP_NR_UNKN
,
256 "SMFIP_NR_EOH", SMFIP_NR_EOH
,
257 "SMFIP_NR_BODY", SMFIP_NR_BODY
,
258 "SMFIP_HDR_LEADSPC", SMFIP_HDR_LEADSPC
,
263 * Options that the filter may send at initial handshake time, and message
264 * modifications that the filter may request at the end of the message body.
266 #define SMFIF_ADDHDRS (1L<<0) /* filter may add headers */
267 #define SMFIF_CHGBODY (1L<<1) /* filter may replace body */
268 #define SMFIF_ADDRCPT (1L<<2) /* filter may add recipients */
269 #define SMFIF_DELRCPT (1L<<3) /* filter may delete recipients */
270 #define SMFIF_CHGHDRS (1L<<4) /* filter may change/delete headers */
271 #define SMFIF_QUARANTINE (1L<<5) /* filter may quarantine envelope */
272 /* Introduced with Sendmail 8.14. */
273 #define SMFIF_CHGFROM (1L<<6) /* filter may replace sender */
274 #define SMFIF_ADDRCPT_PAR (1L<<7) /* filter may add recipients + args */
275 #define SMFIF_SETSYMLIST (1L<<8) /* filter may send macro names */
277 static const NAME_MASK smfif_table
[] = {
278 "SMFIF_ADDHDRS", SMFIF_ADDHDRS
,
279 "SMFIF_CHGBODY", SMFIF_CHGBODY
,
280 "SMFIF_ADDRCPT", SMFIF_ADDRCPT
,
281 "SMFIF_DELRCPT", SMFIF_DELRCPT
,
282 "SMFIF_CHGHDRS", SMFIF_CHGHDRS
,
283 "SMFIF_QUARANTINE", SMFIF_QUARANTINE
,
284 /* Introduced with Sendmail 8.14. */
285 "SMFIF_CHGFROM", SMFIF_CHGFROM
,
286 "SMFIF_ADDRCPT_PAR", SMFIF_ADDRCPT_PAR
,
287 "SMFIF_SETSYMLIST", SMFIF_SETSYMLIST
,
292 * Network protocol families, used when sending CONNECT information.
294 #define SMFIA_UNKNOWN 'U' /* unknown */
295 #define SMFIA_UNIX 'L' /* unix/local */
296 #define SMFIA_INET '4' /* inet */
297 #define SMFIA_INET6 '6' /* inet6 */
300 * External macro class numbers, to identify the optional macro name lists
301 * that may be sent after the initial negotiation header.
303 #define SMFIM_CONNECT 0 /* macros for connect */
304 #define SMFIM_HELO 1 /* macros for HELO */
305 #define SMFIM_ENVFROM 2 /* macros for MAIL */
306 #define SMFIM_ENVRCPT 3 /* macros for RCPT */
307 #define SMFIM_DATA 4 /* macros for DATA */
308 #define SMFIM_EOM 5 /* macros for end-of-message */
309 #define SMFIM_EOH 6 /* macros for end-of-header */
311 static const NAME_CODE smfim_table
[] = {
312 "SMFIM_CONNECT", SMFIM_CONNECT
,
313 "SMFIM_HELO", SMFIM_HELO
,
314 "SMFIM_ENVFROM", SMFIM_ENVFROM
,
315 "SMFIM_ENVRCPT", SMFIM_ENVRCPT
,
316 "SMFIM_DATA", SMFIM_DATA
,
317 "SMFIM_EOM", SMFIM_EOM
,
318 "SMFIM_EOH", SMFIM_EOH
,
323 * Mapping from external macro class numbers to our internal MILTER_MACROS
324 * structure members, without using a switch statement.
326 static const size_t milter8_macro_offsets
[] = {
327 offsetof(MILTER_MACROS
, conn_macros
), /* SMFIM_CONNECT */
328 offsetof(MILTER_MACROS
, helo_macros
), /* SMFIM_HELO */
329 offsetof(MILTER_MACROS
, mail_macros
), /* SMFIM_ENVFROM */
330 offsetof(MILTER_MACROS
, rcpt_macros
), /* SMFIM_ENVRCPT */
331 offsetof(MILTER_MACROS
, data_macros
), /* SMFIM_DATA */
332 offsetof(MILTER_MACROS
, eod_macros
),/* Note: SMFIM_EOM < SMFIM_EOH */
333 offsetof(MILTER_MACROS
, eoh_macros
),/* Note: SMFIM_EOH > SMFIM_EOM */
336 #define MILTER8_MACRO_PTR(__macros, __class) \
337 ((char **) (((char *) (__macros)) + milter8_macro_offsets[(__class)]))
340 * How much buffer space is available for sending body content.
342 #define MILTER_CHUNK_SIZE 65535 /* body chunk size */
344 /*#define msg_verbose 2*/
347 * Sendmail 8 mail filter client.
350 MILTER m
; /* parent class */
351 int conn_timeout
; /* connect timeout */
352 int cmd_timeout
; /* per-command timeout */
353 int msg_timeout
; /* content inspection timeout */
354 char *protocol
; /* protocol version/extension */
355 char *def_action
; /* action if unavailable */
356 int version
; /* application protocol version */
357 int rq_mask
; /* application requests (SMFIF_*) */
358 int ev_mask
; /* application events (SMFIP_*) */
359 int np_mask
; /* events outside my protocol version */
360 VSTRING
*buf
; /* I/O buffer */
361 VSTRING
*body
; /* I/O buffer */
362 VSTREAM
*fp
; /* stream or null (closed) */
365 * Following fields must be reset after successful CONNECT, to avoid
366 * leakage from one use to another.
368 int state
; /* MILTER8_STAT_mumble */
369 char *def_reply
; /* error response or null */
370 int skip_event_type
; /* skip operations of this type */
374 * XXX Sendmail 8 libmilter automatically closes the MTA-to-filter socket
375 * when it finds out that the SMTP client has disconnected. Because of this
376 * behavior, Postfix has to open a new MTA-to-filter socket each time an
377 * SMTP client connects.
379 #define LIBMILTER_AUTO_DISCONNECT
382 * Milter internal state. For the external representation we use SMTP
383 * replies (4XX X.Y.Z text, 5XX X.Y.Z text) and one-letter strings
384 * (H=quarantine, D=discard, S=shutdown).
386 #define MILTER8_STAT_ERROR 1 /* error, must be non-zero */
387 #define MILTER8_STAT_CLOSED 2 /* no connection */
388 #define MILTER8_STAT_READY 3 /* wait for connect event */
389 #define MILTER8_STAT_ENVELOPE 4 /* in envelope */
390 #define MILTER8_STAT_MESSAGE 5 /* in message */
391 #define MILTER8_STAT_ACCEPT_CON 6 /* accept all commands */
392 #define MILTER8_STAT_ACCEPT_MSG 7 /* accept one message */
393 #define MILTER8_STAT_REJECT_CON 8 /* reject all commands */
396 * Protocol formatting requests. Note: the terms "long" and "short" refer to
397 * the data types manipulated by htonl(), htons() and friends. These types
398 * are network specific, not host platform specific.
400 #define MILTER8_DATA_END 0 /* no more arguments */
401 #define MILTER8_DATA_HLONG 1 /* host long */
402 #define MILTER8_DATA_BUFFER 2 /* network-formatted buffer */
403 #define MILTER8_DATA_STRING 3 /* null-terminated string */
404 #define MILTER8_DATA_NSHORT 4 /* network short */
405 #define MILTER8_DATA_ARGV 5 /* array of null-terminated strings */
406 #define MILTER8_DATA_OCTET 6 /* byte */
407 #define MILTER8_DATA_MORE 7 /* more arguments in next call */
410 * We don't accept insane amounts of data.
412 #define XXX_MAX_DATA (INT_MAX / 2)
413 #define XXX_TIMEOUT 10
416 * We implement the protocol up to and including version 6, and configure in
417 * main.cf what protocol version we will use. The version is the first data
418 * item in the SMFIC_OPTNEG packet.
420 * We must send only events that are defined for the specified protocol
421 * version. Libmilter may disconnect when we send unexpected events.
423 * The following events are supported in all our milter protocol versions.
425 #define MILTER8_V2_PROTO_MASK \
426 (SMFIP_NOCONNECT | SMFIP_NOHELO | SMFIP_NOMAIL | SMFIP_NORCPT | \
427 SMFIP_NOBODY | SMFIP_NOHDRS | SMFIP_NOEOH)
430 * Events supported by later versions.
432 #define MILTER8_V3_PROTO_MASK (MILTER8_V2_PROTO_MASK | SMFIP_NOUNKNOWN)
433 #define MILTER8_V4_PROTO_MASK (MILTER8_V3_PROTO_MASK | SMFIP_NODATA)
434 #define MILTER8_V6_PROTO_MASK \
435 (MILTER8_V4_PROTO_MASK | SMFIP_SKIP | SMFIP_RCPT_REJ \
436 | SMFIP_NOREPLY_MASK | SMFIP_HDR_LEADSPC)
439 * What events we can send to the milter application. The milter8_protocol
440 * parameter can specify a protocol version as well as protocol extensions
441 * such as "no_header_reply", a feature that speeds up the protocol by not
442 * sending a filter reply for every individual message header.
444 * This looks unclean because the user can specify multiple protocol versions,
445 * but that is taken care of by the table that follows this one.
447 * XXX Is this still needed? Sendmail 8.14 provides a proper way to negotiate
448 * what replies the mail filter will send.
450 static const NAME_CODE milter8_event_masks
[] = {
451 "2", MILTER8_V2_PROTO_MASK
,
452 "3", MILTER8_V3_PROTO_MASK
,
453 "4", MILTER8_V4_PROTO_MASK
,
454 "6", MILTER8_V6_PROTO_MASK
,
455 "no_header_reply", SMFIP_NOHREPL
,
460 * The following table lets us use the same milter8_protocol parameter
461 * setting to derive the protocol version number. In this case we ignore
462 * protocol extensions such as "no_header_reply", and require that exactly
463 * one version number is specified.
465 static const NAME_CODE milter8_versions
[] = {
470 "no_header_reply", 0,
476 #define STR(x) vstring_str(x)
477 #define LEN(x) VSTRING_LEN(x)
479 /* milter8_def_reply - set persistent response */
481 static const char *milter8_def_reply(MILTER8
*milter
, const char *reply
)
483 if (milter
->def_reply
)
484 myfree(milter
->def_reply
);
485 milter
->def_reply
= reply
? mystrdup(reply
) : 0;
486 return (milter
->def_reply
);
489 /* milter8_conf_error - local/remote configuration error */
491 static int milter8_conf_error(MILTER8
*milter
)
496 * XXX When the cleanup server closes its end of the Milter socket while
497 * editing a queue file, the SMTP server is left out of sync with the
498 * Milter. Sending an ABORT to the Milters will not restore
499 * synchronization, because there may be any number of Milter replies
500 * already in flight. Workaround: poison the socket and force the SMTP
501 * server to abandon it.
503 if (milter
->fp
!= 0) {
504 (void) shutdown(vstream_fileno(milter
->fp
), SHUT_RDWR
);
505 (void) vstream_fclose(milter
->fp
);
508 if (strcasecmp(milter
->def_action
, "accept") == 0) {
510 } else if (strcasecmp(milter
->def_action
, "quarantine") == 0) {
513 reply
= "451 4.3.5 Server configuration problem - try again later";
515 milter8_def_reply(milter
, reply
);
516 return (milter
->state
= MILTER8_STAT_ERROR
);
519 /* milter8_comm_error - read/write/format communication error */
521 static int milter8_comm_error(MILTER8
*milter
)
526 * XXX When the cleanup server closes its end of the Milter socket while
527 * editing a queue file, the SMTP server is left out of sync with the
528 * Milter. Sending an ABORT to the Milters will not restore
529 * synchronization, because there may be any number of Milter replies
530 * already in flight. Workaround: poison the socket and force the SMTP
531 * server to abandon it.
533 if (milter
->fp
!= 0) {
534 (void) shutdown(vstream_fileno(milter
->fp
), SHUT_RDWR
);
535 (void) vstream_fclose(milter
->fp
);
538 if (strcasecmp(milter
->def_action
, "accept") == 0) {
540 } else if (strcasecmp(milter
->def_action
, "reject") == 0) {
541 reply
= "550 5.5.0 Service unavailable";
542 } else if (strcasecmp(milter
->def_action
, "tempfail") == 0) {
543 reply
= "451 4.7.1 Service unavailable - try again later";
544 } else if (strcasecmp(milter
->def_action
, "quarantine") == 0) {
547 msg_warn("milter %s: unrecognized default action: %s",
548 milter
->m
.name
, milter
->def_action
);
549 reply
= "451 4.3.5 Server configuration problem - try again later";
551 milter8_def_reply(milter
, reply
);
552 return (milter
->state
= MILTER8_STAT_ERROR
);
555 /* milter8_close_stream - close stream to milter application */
557 static void milter8_close_stream(MILTER8
*milter
)
559 if (milter
->fp
!= 0) {
560 (void) vstream_fclose(milter
->fp
);
563 milter
->state
= MILTER8_STAT_CLOSED
;
566 /* milter8_read_resp - receive command code now, receive data later */
568 static int milter8_read_resp(MILTER8
*milter
, int event
, unsigned char *command
,
573 const char *smfic_name
;
577 * Receive the packet length.
579 if ((vstream_fread(milter
->fp
, (char *) &len
, UINT32_SIZE
))
581 smfic_name
= str_name_code(smfic_table
, event
);
582 msg_warn("milter %s: can't read %s reply packet header: %m",
583 milter
->m
.name
, smfic_name
!= 0 ?
584 smfic_name
: "(unknown MTA event)");
585 return (milter8_comm_error(milter
));
586 } else if ((pkt_len
= ntohl(len
)) < 1) {
587 msg_warn("milter %s: bad packet length: %ld",
588 milter
->m
.name
, (long) pkt_len
);
589 return (milter8_comm_error(milter
));
590 } else if (pkt_len
> XXX_MAX_DATA
) {
591 msg_warn("milter %s: unreasonable packet length: %ld > %ld",
592 milter
->m
.name
, (long) pkt_len
, (long) XXX_MAX_DATA
);
593 return (milter8_comm_error(milter
));
597 * Receive the command code.
599 else if ((cmd
= VSTREAM_GETC(milter
->fp
)) == VSTREAM_EOF
) {
600 msg_warn("milter %s: EOF while reading command code: %m",
602 return (milter8_comm_error(milter
));
610 *data_len
= pkt_len
- 1;
615 static int milter8_read_data(MILTER8
*milter
, ssize_t
*data_len
,...);
617 /* vmilter8_read_data - read command data */
619 static int vmilter8_read_data(MILTER8
*milter
, ssize_t
*data_len
, va_list ap
)
621 const char *myname
= "milter8_read_data";
623 UINT32_TYPE net_long
;
624 UINT32_TYPE
*host_long_ptr
;
628 while ((arg_type
= va_arg(ap
, int)) > 0 && arg_type
!= MILTER8_DATA_MORE
) {
634 case MILTER8_DATA_HLONG
:
635 if (*data_len
< UINT32_SIZE
) {
636 msg_warn("milter %s: input packet too short for network long",
638 return (milter8_comm_error(milter
));
640 host_long_ptr
= va_arg(ap
, UINT32_TYPE
*);
641 if (vstream_fread(milter
->fp
, (char *) &net_long
, UINT32_SIZE
)
643 msg_warn("milter %s: EOF while reading network long: %m",
645 return (milter8_comm_error(milter
));
647 *data_len
-= UINT32_SIZE
;
648 *host_long_ptr
= ntohl(net_long
);
652 * Raw on-the-wire format, without explicit null terminator.
654 case MILTER8_DATA_BUFFER
:
656 msg_warn("milter %s: no data in input packet", milter
->m
.name
);
657 return (milter8_comm_error(milter
));
659 buf
= va_arg(ap
, VSTRING
*);
661 VSTRING_SPACE(buf
, *data_len
);
662 if (vstream_fread(milter
->fp
, (char *) STR(buf
), *data_len
)
664 msg_warn("milter %s: EOF while reading data: %m", milter
->m
.name
);
665 return (milter8_comm_error(milter
));
667 VSTRING_AT_OFFSET(buf
, *data_len
);
672 * Pointer to null-terminated string.
674 case MILTER8_DATA_STRING
:
676 msg_warn("milter %s: packet too short for string",
678 return (milter8_comm_error(milter
));
680 buf
= va_arg(ap
, VSTRING
*);
683 if ((ch
= VSTREAM_GETC(milter
->fp
)) == VSTREAM_EOF
) {
684 msg_warn("%s: milter %s: EOF while reading string: %m",
685 myname
, milter
->m
.name
);
686 return (milter8_comm_error(milter
));
691 VSTRING_ADDCH(buf
, ch
);
692 if (*data_len
<= 0) {
693 msg_warn("%s: milter %s: missing string null termimator",
694 myname
, milter
->m
.name
);
695 return (milter8_comm_error(milter
));
698 VSTRING_TERMINATE(buf
);
705 msg_panic("%s: unknown argument type: %d", myname
, arg_type
);
710 * Sanity checks. We may have excess data when the sender is confused. We
711 * may have a negative count when we're confused ourselves.
713 if (arg_type
!= MILTER8_DATA_MORE
&& *data_len
> 0) {
714 msg_warn("%s: left-over data %ld bytes", myname
, (long) *data_len
);
715 return (milter8_comm_error(milter
));
718 msg_panic("%s: bad left-over data count %ld",
719 myname
, (long) *data_len
);
723 /* milter8_read_data - read command data */
725 static int milter8_read_data(MILTER8
*milter
, ssize_t
*data_len
,...)
730 va_start(ap
, data_len
);
731 ret
= vmilter8_read_data(milter
, data_len
, ap
);
736 /* vmilter8_size_data - compute command data length */
738 static ssize_t
vmilter8_size_data(va_list ap
)
740 const char *myname
= "vmilter8_size_data";
750 for (data_len
= 0; (arg_type
= va_arg(ap
, int)) > 0; /* void */ ) {
756 case MILTER8_DATA_HLONG
:
757 (void) va_arg(ap
, UINT32_TYPE
);
758 data_len
+= UINT32_SIZE
;
762 * Raw on-the-wire format.
764 case MILTER8_DATA_BUFFER
:
765 buf
= va_arg(ap
, VSTRING
*);
766 data_len
+= LEN(buf
);
770 * Pointer to null-terminated string.
772 case MILTER8_DATA_STRING
:
773 str
= va_arg(ap
, char *);
774 data_len
+= strlen(str
) + 1;
778 * Array of pointers to null-terminated strings.
780 case MILTER8_DATA_ARGV
:
781 for (cpp
= va_arg(ap
, const char **); *cpp
; cpp
++)
782 data_len
+= strlen(*cpp
) + 1;
786 * Network order short, promoted to int.
788 case MILTER8_DATA_NSHORT
:
789 (void) va_arg(ap
, unsigned);
790 data_len
+= UINT16_SIZE
;
794 * Octet, promoted to int.
796 case MILTER8_DATA_OCTET
:
797 (void) va_arg(ap
, unsigned);
805 msg_panic("%s: bad argument type: %d", myname
, arg_type
);
812 /* vmilter8_write_cmd - write command to Sendmail 8 Milter */
814 static int vmilter8_write_cmd(MILTER8
*milter
, int command
, ssize_t data_len
,
817 const char *myname
= "vmilter8_write_cmd";
820 UINT32_TYPE host_long
;
821 UINT32_TYPE net_long
;
822 UINT16_TYPE net_short
;
829 * Deliver the packet.
831 if ((pkt_len
= 1 + data_len
) < 1)
832 msg_panic("%s: bad packet length %d", myname
, pkt_len
);
833 pkt_len
= htonl(pkt_len
);
834 (void) vstream_fwrite(milter
->fp
, (char *) &pkt_len
, UINT32_SIZE
);
835 (void) VSTREAM_PUTC(command
, milter
->fp
);
836 while ((arg_type
= va_arg(ap
, int)) > 0) {
842 case MILTER8_DATA_HLONG
:
843 host_long
= va_arg(ap
, UINT32_TYPE
);
844 net_long
= htonl(host_long
);
845 (void) vstream_fwrite(milter
->fp
, (char *) &net_long
, UINT32_SIZE
);
849 * Raw on-the-wire format.
851 case MILTER8_DATA_BUFFER
:
852 buf
= va_arg(ap
, VSTRING
*);
853 (void) vstream_fwrite(milter
->fp
, STR(buf
), LEN(buf
));
857 * Pointer to null-terminated string.
859 case MILTER8_DATA_STRING
:
860 str
= va_arg(ap
, char *);
861 (void) vstream_fwrite(milter
->fp
, str
, strlen(str
) + 1);
865 * Octet, promoted to int.
867 case MILTER8_DATA_OCTET
:
868 ch
= va_arg(ap
, unsigned);
869 (void) vstream_fwrite(milter
->fp
, &ch
, 1);
873 * Array of pointers to null-terminated strings.
875 case MILTER8_DATA_ARGV
:
876 for (cpp
= va_arg(ap
, const char **); *cpp
; cpp
++)
877 (void) vstream_fwrite(milter
->fp
, *cpp
, strlen(*cpp
) + 1);
881 * Network order short, promoted to int.
883 case MILTER8_DATA_NSHORT
:
884 net_short
= va_arg(ap
, unsigned);
885 (void) vstream_fwrite(milter
->fp
, (char *) &net_short
, UINT16_SIZE
);
892 msg_panic("%s: bad argument type: %d", myname
, arg_type
);
896 * Report errors immediately.
898 if (vstream_ferror(milter
->fp
)) {
899 msg_warn("milter %s: error writing command: %m", milter
->m
.name
);
900 milter8_comm_error(milter
);
905 return (milter
->state
== MILTER8_STAT_ERROR
);
908 /* milter8_write_cmd - write command to Sendmail 8 Milter */
910 static int milter8_write_cmd(MILTER8
*milter
, int command
,...)
917 * Size the command data.
919 va_start(ap
, command
);
920 data_len
= vmilter8_size_data(ap
);
924 * Send the command and data.
926 va_start(ap
, command
);
927 err
= vmilter8_write_cmd(milter
, command
, data_len
, ap
);
933 /* milter8_event - report event and receive reply */
935 static const char *milter8_event(MILTER8
*milter
, int event
,
940 const char *myname
= "milter8_event";
946 const char *smfic_name
;
947 const char *smfir_name
;
948 MILTERS
*parent
= milter
->m
.parent
;
950 const char *edit_resp
= 0;
951 const char *retval
= 0;
952 VSTRING
*body_line_buf
= 0;
954 int body_edit_lockout
= 0;
956 #define DONT_SKIP_REPLY 0
961 if (milter
->fp
== 0 || milter
->def_reply
!= 0) {
962 msg_warn("%s: attempt to send event %s to milter %s after error",
964 (smfic_name
= str_name_code(smfic_table
, event
)) != 0 ?
965 smfic_name
: "(unknown MTA event)", milter
->m
.name
);
966 return (milter
->def_reply
);
970 * Skip this event if it doesn't exist in the protocol that I announced.
972 if ((skip_event_flag
& milter
->np_mask
) != 0) {
974 msg_info("skipping non-protocol event %s for milter %s",
975 (smfic_name
= str_name_code(smfic_table
, event
)) != 0 ?
976 smfic_name
: "(unknown MTA event)", milter
->m
.name
);
977 return (milter
->def_reply
);
981 * Skip further events of this type if the filter told us so.
983 if (milter
->skip_event_type
!= 0) {
984 if (event
== milter
->skip_event_type
) {
986 msg_info("skipping event %s after SMFIR_SKIP from milter %s",
987 (smfic_name
= str_name_code(smfic_table
, event
)) != 0 ?
988 smfic_name
: "(unknown MTA event)", milter
->m
.name
);
989 return (milter
->def_reply
);
991 milter
->skip_event_type
= 0;
996 * Send the macros for this event, even when we're not reporting the
997 * event itself. This does not introduce a performance problem because
998 * we're sending macros and event parameters in one VSTREAM transaction.
1000 * XXX Is this still necessary?
1003 VSTRING
*buf
= vstring_alloc(100);
1006 if (macros
->argc
> 0) {
1009 for (cpp
= macros
->argv
; *cpp
&& cpp
[1]; cpp
+= 2)
1010 vstring_sprintf_append(buf
, " %s=%s", *cpp
, cpp
[1]);
1013 msg_info("event: %s; macros:%s",
1014 (smfic_name
= str_name_code(smfic_table
, event
)) != 0 ?
1015 smfic_name
: "(unknown MTA event)", *STR(buf
) ?
1016 STR(buf
) : " (none)");
1020 if (milter8_write_cmd(milter
, SMFIC_MACRO
,
1021 MILTER8_DATA_OCTET
, event
,
1022 MILTER8_DATA_ARGV
, macros
->argv
,
1023 MILTER8_DATA_END
) != 0)
1024 return (milter
->def_reply
);
1028 * Skip this event if the Milter told us not to send it.
1030 if ((skip_event_flag
& milter
->ev_mask
) != 0) {
1032 msg_info("skipping event %s for milter %s",
1033 (smfic_name
= str_name_code(smfic_table
, event
)) != 0 ?
1034 smfic_name
: "(unknown MTA event)", milter
->m
.name
);
1035 return (milter
->def_reply
);
1039 * Compute the command data size. This is necessary because the protocol
1040 * sends length before content.
1042 va_start(ap
, macros
);
1043 data_len
= vmilter8_size_data(ap
);
1047 * Send the command and data.
1049 va_start(ap
, macros
);
1050 err
= vmilter8_write_cmd(milter
, event
, data_len
, ap
);
1053 return (milter
->def_reply
);
1056 * Special feature: don't wait for one reply per header. This allows us
1057 * to send multiple headers in one VSTREAM transaction, and improves
1058 * over-all performance.
1062 msg_info("skipping reply for event %s from milter %s",
1063 (smfic_name
= str_name_code(smfic_table
, event
)) != 0 ?
1064 smfic_name
: "(unknown MTA event)", milter
->m
.name
);
1065 return (milter
->def_reply
);
1069 * Receive the reply or replies.
1071 * Intercept all loop exits so that we can do post header/body edit
1074 * XXX Bound the loop iteration count.
1076 * In the end-of-body stage, the Milter may reply with one or more queue
1077 * file edit requests before it replies with its final decision: accept,
1078 * reject, etc. After a local queue file edit error (file too big, media
1079 * write error), do not close the Milter socket in the cleanup server.
1080 * Instead skip all further Milter replies until the final decision. This
1081 * way the Postfix SMTP server stays in sync with the Milter, and Postfix
1082 * doesn't have to lose the ability to handle multiple deliveries within
1083 * the same SMTP session. This requires that the Postfix SMTP server uses
1084 * something other than CLEANUP_STAT_WRITE when it loses contact with the
1087 #define IN_CONNECT_EVENT(e) ((e) == SMFIC_CONNECT || (e) == SMFIC_HELO)
1090 * XXX Don't evaluate this macro's argument multiple times. Since we use
1091 * "continue" the macro can't be enclosed in do .. while (0).
1093 #define MILTER8_EVENT_BREAK(s) { \
1105 if (milter8_read_resp(milter
, event
, &cmd
, &data_size
) != 0)
1106 MILTER8_EVENT_BREAK(milter
->def_reply
);
1108 msg_info("reply: %s data %ld bytes",
1109 (smfir_name
= str_name_code(smfir_table
, cmd
)) != 0 ?
1110 smfir_name
: "unknown", (long) data_size
);
1113 * Handle unfinished message body replacement first.
1115 * XXX When SMFIR_REPLBODY is followed by some different request, we
1116 * assume that the body replacement operation is complete. The queue
1117 * file editing implementation currently does not support sending
1118 * part 1 of the body replacement text, doing some other queue file
1119 * updates, and then sending part 2 of the body replacement text. To
1120 * avoid loss of data, we log an error when SMFIR_REPLBODY requests
1121 * are alternated with other requests.
1123 if (body_line_buf
!= 0 && cmd
!= SMFIR_REPLBODY
) {
1124 /* In case the last body replacement line didn't end in CRLF. */
1125 if (edit_resp
== 0 && LEN(body_line_buf
) > 0)
1126 edit_resp
= parent
->repl_body(parent
->chg_context
,
1130 edit_resp
= parent
->repl_body(parent
->chg_context
,
1133 body_edit_lockout
= 1;
1134 vstring_free(body_line_buf
);
1140 * Still working on it.
1142 case SMFIR_PROGRESS
:
1148 * Decision: continue processing.
1150 case SMFIR_CONTINUE
:
1153 MILTER8_EVENT_BREAK(milter
->def_reply
);
1156 * Decision: accept this message, or accept all further commands
1157 * in this SMTP connection. This decision is final (i.e. Sendmail
1158 * 8 changes receiver state).
1163 if (IN_CONNECT_EVENT(event
)) {
1164 #ifdef LIBMILTER_AUTO_DISCONNECT
1165 milter8_close_stream(milter
);
1167 /* No more events for this SMTP connection. */
1168 milter
->state
= MILTER8_STAT_ACCEPT_CON
;
1170 /* No more events for this message. */
1171 milter
->state
= MILTER8_STAT_ACCEPT_MSG
;
1173 MILTER8_EVENT_BREAK(milter
->def_reply
);
1176 * Decision: accept and silently discard this message. According
1177 * to the milter API documentation there will be no action when
1178 * this is requested by a connection-level function. This
1179 * decision is final (i.e. Sendmail 8 changes receiver state).
1184 if (IN_CONNECT_EVENT(event
)) {
1185 msg_warn("milter %s: DISCARD action is not allowed "
1186 "for connect or helo", milter
->m
.name
);
1187 MILTER8_EVENT_BREAK(milter
->def_reply
);
1189 /* No more events for this message. */
1190 milter
->state
= MILTER8_STAT_ACCEPT_MSG
;
1191 MILTER8_EVENT_BREAK("D");
1195 * Decision: reject connection, message or recipient. This
1196 * decision is final (i.e. Sendmail 8 changes receiver state).
1201 if (IN_CONNECT_EVENT(event
)) {
1202 #ifdef LIBMILTER_AUTO_DISCONNECT
1203 milter8_close_stream(milter
);
1205 milter
->state
= MILTER8_STAT_REJECT_CON
;
1206 MILTER8_EVENT_BREAK(milter8_def_reply(milter
, "550 5.7.1 Command rejected"));
1208 MILTER8_EVENT_BREAK("550 5.7.1 Command rejected");
1212 * Decision: tempfail. This decision is final (i.e. Sendmail 8
1213 * changes receiver state).
1215 case SMFIR_TEMPFAIL
:
1218 if (IN_CONNECT_EVENT(event
)) {
1219 #ifdef LIBMILTER_AUTO_DISCONNECT
1220 milter8_close_stream(milter
);
1222 milter
->state
= MILTER8_STAT_REJECT_CON
;
1223 MILTER8_EVENT_BREAK(milter8_def_reply(milter
,
1224 "451 4.7.1 Service unavailable - try again later"));
1226 MILTER8_EVENT_BREAK("451 4.7.1 Service unavailable - try again later");
1230 * Decision: disconnect. This decision is final (i.e. Sendmail 8
1231 * changes receiver state).
1233 case SMFIR_SHUTDOWN
:
1236 #ifdef LIBMILTER_AUTO_DISCONNECT
1237 milter8_close_stream(milter
);
1239 milter
->state
= MILTER8_STAT_REJECT_CON
;
1240 MILTER8_EVENT_BREAK(milter8_def_reply(milter
, "S"));
1243 * Decision: "ddd d.d+.d+ text". This decision is final (i.e.
1244 * Sendmail 8 changes receiver state). Note: the reply may be in
1245 * multi-line SMTP format.
1247 * XXX Sendmail compatibility: sendmail 8 uses the reply as a format
1248 * string; therefore any '%' characters in the reply are doubled.
1249 * Postfix doesn't use replies as format strings; we replace '%%'
1250 * by '%', and remove single (i.e. invalid) '%' characters.
1252 case SMFIR_REPLYCODE
:
1253 if (milter8_read_data(milter
, &data_size
,
1254 MILTER8_DATA_BUFFER
, milter
->buf
,
1255 MILTER8_DATA_END
) != 0)
1256 MILTER8_EVENT_BREAK(milter
->def_reply
);
1257 if ((STR(milter
->buf
)[0] != '4' && STR(milter
->buf
)[0] != '5')
1258 || !ISDIGIT(STR(milter
->buf
)[1])
1259 || !ISDIGIT(STR(milter
->buf
)[2])
1260 || (STR(milter
->buf
)[3] != ' ' && STR(milter
->buf
)[3] != '-')
1261 || STR(milter
->buf
)[4] != STR(milter
->buf
)[0]) {
1262 msg_warn("milter %s: malformed reply: %s",
1263 milter
->m
.name
, STR(milter
->buf
));
1264 milter8_conf_error(milter
);
1265 MILTER8_EVENT_BREAK(milter
->def_reply
);
1267 if ((rp
= cp
= strchr(STR(milter
->buf
), '%')) != 0) {
1269 if ((ch
= *cp
++) == '%')
1276 if (var_soft_bounce
) {
1277 for (cp
= STR(milter
->buf
); /* void */ ; cp
= next
) {
1283 if ((next
= strstr(cp
, "\r\n")) == 0)
1288 if (IN_CONNECT_EVENT(event
)) {
1289 #ifdef LIBMILTER_AUTO_DISCONNECT
1290 milter8_close_stream(milter
);
1292 milter
->state
= MILTER8_STAT_REJECT_CON
;
1293 MILTER8_EVENT_BREAK(milter8_def_reply(milter
, STR(milter
->buf
)));
1295 MILTER8_EVENT_BREAK(STR(milter
->buf
));
1299 * Decision: quarantine. In Sendmail 8.13 this does not imply a
1300 * transition in the receiver state (reply, reject, tempfail,
1301 * accept, discard). We should not transition, either, otherwise
1302 * we get out of sync.
1304 case SMFIR_QUARANTINE
:
1305 /* XXX What to do with the "reason" text? */
1306 if (milter8_read_data(milter
, &data_size
,
1307 MILTER8_DATA_BUFFER
, milter
->buf
,
1308 MILTER8_DATA_END
) != 0)
1309 MILTER8_EVENT_BREAK(milter
->def_reply
);
1310 milter8_def_reply(milter
, "H");
1314 * Decision: skip further events of this type.
1319 milter
->skip_event_type
= event
;
1320 MILTER8_EVENT_BREAK(milter
->def_reply
);
1323 * Modification request or error.
1326 if (event
== SMFIC_BODYEOB
) {
1329 #define MILTER8_HDR_SPACE(m) (((m)->ev_mask & SMFIP_HDR_LEADSPC) ? "" : " ")
1332 * Modification request: replace, insert or delete
1333 * header. Index 1 means the first instance.
1335 case SMFIR_CHGHEADER
:
1336 if (milter8_read_data(milter
, &data_size
,
1337 MILTER8_DATA_HLONG
, &index
,
1338 MILTER8_DATA_STRING
, milter
->buf
,
1339 MILTER8_DATA_STRING
, milter
->body
,
1340 MILTER8_DATA_END
) != 0)
1341 MILTER8_EVENT_BREAK(milter
->def_reply
);
1342 /* Skip to the next request after previous edit error. */
1345 /* XXX Sendmail 8 compatibility. */
1348 if ((ssize_t
) index
< 1) {
1349 msg_warn("milter %s: bad change header index: %ld",
1350 milter
->m
.name
, (long) index
);
1351 milter8_conf_error(milter
);
1352 MILTER8_EVENT_BREAK(milter
->def_reply
);
1354 if (LEN(milter
->buf
) == 0) {
1355 msg_warn("milter %s: null change header name",
1357 milter8_conf_error(milter
);
1358 MILTER8_EVENT_BREAK(milter
->def_reply
);
1360 if (STR(milter
->body
)[0])
1361 edit_resp
= parent
->upd_header(parent
->chg_context
,
1364 MILTER8_HDR_SPACE(milter
),
1367 edit_resp
= parent
->del_header(parent
->chg_context
,
1373 * Modification request: append header.
1375 case SMFIR_ADDHEADER
:
1376 if (milter8_read_data(milter
, &data_size
,
1377 MILTER8_DATA_STRING
, milter
->buf
,
1378 MILTER8_DATA_STRING
, milter
->body
,
1379 MILTER8_DATA_END
) != 0)
1380 MILTER8_EVENT_BREAK(milter
->def_reply
);
1381 /* Skip to the next request after previous edit error. */
1384 edit_resp
= parent
->add_header(parent
->chg_context
,
1386 MILTER8_HDR_SPACE(milter
),
1391 * Modification request: insert header. With Sendmail 8,
1392 * index 0 means the top-most header. We use 1-based
1393 * indexing for consistency with header change
1396 case SMFIR_INSHEADER
:
1397 if (milter8_read_data(milter
, &data_size
,
1398 MILTER8_DATA_HLONG
, &index
,
1399 MILTER8_DATA_STRING
, milter
->buf
,
1400 MILTER8_DATA_STRING
, milter
->body
,
1401 MILTER8_DATA_END
) != 0)
1402 MILTER8_EVENT_BREAK(milter
->def_reply
);
1403 /* Skip to the next request after previous edit error. */
1406 if ((ssize_t
) index
+ 1 < 1) {
1407 msg_warn("milter %s: bad insert header index: %ld",
1408 milter
->m
.name
, (long) index
);
1409 milter8_conf_error(milter
);
1410 MILTER8_EVENT_BREAK(milter
->def_reply
);
1412 edit_resp
= parent
->ins_header(parent
->chg_context
,
1413 (ssize_t
) index
+ 1,
1415 MILTER8_HDR_SPACE(milter
),
1420 * Modification request: replace sender, with optional
1424 if (milter8_read_data(milter
, &data_size
,
1425 MILTER8_DATA_STRING
, milter
->buf
,
1426 MILTER8_DATA_MORE
) != 0)
1427 MILTER8_EVENT_BREAK(milter
->def_reply
);
1428 if (data_size
> 0) {
1429 if (milter8_read_data(milter
, &data_size
,
1430 MILTER8_DATA_STRING
, milter
->body
,
1431 MILTER8_DATA_END
) != 0)
1432 MILTER8_EVENT_BREAK(milter
->def_reply
);
1434 VSTRING_RESET(milter
->body
);
1435 VSTRING_TERMINATE(milter
->body
);
1437 /* Skip to the next request after previous edit error. */
1440 edit_resp
= parent
->chg_from(parent
->chg_context
,
1446 * Modification request: append recipient.
1449 if (milter8_read_data(milter
, &data_size
,
1450 MILTER8_DATA_STRING
, milter
->buf
,
1451 MILTER8_DATA_END
) != 0)
1452 MILTER8_EVENT_BREAK(milter
->def_reply
);
1453 /* Skip to the next request after previous edit error. */
1456 edit_resp
= parent
->add_rcpt(parent
->chg_context
,
1461 * Modification request: append recipient, with optional
1464 case SMFIR_ADDRCPT_PAR
:
1465 if (milter8_read_data(milter
, &data_size
,
1466 MILTER8_DATA_STRING
, milter
->buf
,
1467 MILTER8_DATA_MORE
) != 0)
1468 MILTER8_EVENT_BREAK(milter
->def_reply
);
1469 if (data_size
> 0) {
1470 if (milter8_read_data(milter
, &data_size
,
1471 MILTER8_DATA_STRING
, milter
->body
,
1472 MILTER8_DATA_END
) != 0)
1473 MILTER8_EVENT_BREAK(milter
->def_reply
);
1475 VSTRING_RESET(milter
->body
);
1476 VSTRING_TERMINATE(milter
->body
);
1478 /* Skip to the next request after previous edit error. */
1481 edit_resp
= parent
->add_rcpt_par(parent
->chg_context
,
1487 * Modification request: delete (expansion of) recipient.
1490 if (milter8_read_data(milter
, &data_size
,
1491 MILTER8_DATA_STRING
, milter
->buf
,
1492 MILTER8_DATA_END
) != 0)
1493 MILTER8_EVENT_BREAK(milter
->def_reply
);
1494 /* Skip to the next request after previous edit error. */
1497 edit_resp
= parent
->del_rcpt(parent
->chg_context
,
1502 * Modification request: replace the message body, and
1503 * update the message size.
1505 case SMFIR_REPLBODY
:
1506 if (body_edit_lockout
) {
1507 msg_warn("milter %s: body replacement requests can't "
1508 "currently be mixed with other requests",
1510 milter8_conf_error(milter
);
1511 MILTER8_EVENT_BREAK(milter
->def_reply
);
1513 if (milter8_read_data(milter
, &data_size
,
1514 MILTER8_DATA_BUFFER
, milter
->body
,
1515 MILTER8_DATA_END
) != 0)
1516 MILTER8_EVENT_BREAK(milter
->def_reply
);
1517 /* Skip to the next request after previous edit error. */
1520 /* Start body replacement. */
1521 if (body_line_buf
== 0) {
1522 body_line_buf
= vstring_alloc(var_line_limit
);
1523 edit_resp
= parent
->repl_body(parent
->chg_context
,
1527 /* Extract lines from the on-the-wire CRLF format. */
1528 for (cp
= STR(milter
->body
); edit_resp
== 0
1529 && cp
< vstring_end(milter
->body
); cp
++) {
1530 ch
= *(unsigned char *) cp
;
1532 if (LEN(body_line_buf
) > 0
1533 && vstring_end(body_line_buf
)[-1] == '\r')
1534 vstring_truncate(body_line_buf
,
1535 LEN(body_line_buf
) - 1);
1536 edit_resp
= parent
->repl_body(parent
->chg_context
,
1539 VSTRING_RESET(body_line_buf
);
1541 VSTRING_ADDCH(body_line_buf
, ch
);
1547 msg_warn("milter %s: unexpected filter response %s after event %s",
1549 (smfir_name
= str_name_code(smfir_table
, cmd
)) != 0 ?
1550 smfir_name
: "(unknown filter reply)",
1551 (smfic_name
= str_name_code(smfic_table
, event
)) != 0 ?
1552 smfic_name
: "(unknown MTA event)");
1553 milter8_comm_error(milter
);
1554 MILTER8_EVENT_BREAK(milter
->def_reply
);
1558 * Get here when the reply was followed by data bytes that weren't
1559 * supposed to be there.
1561 msg_warn("milter %s: reply %s was followed by %ld data bytes",
1562 milter
->m
.name
, (smfir_name
= str_name_code(smfir_table
, cmd
)) != 0 ?
1563 smfir_name
: "unknown", (long) data_len
);
1564 milter8_comm_error(milter
);
1565 MILTER8_EVENT_BREAK(milter
->def_reply
);
1569 * Clean up after aborted message body replacement.
1572 vstring_free(body_line_buf
);
1575 * XXX Some cleanup clients ask the cleanup server to bounce mail for
1576 * them. In that case we must override a hard reject retval result after
1577 * queue file update failure. This is not a big problem; the odds are
1578 * small that a Milter application sends a hard reject after replacing
1581 if (edit_resp
&& (retval
== 0 || strchr("DS4", retval
[0]) == 0))
1586 /* milter8_connect - connect to filter */
1588 static void milter8_connect(MILTER8
*milter
)
1590 const char *myname
= "milter8_connect";
1595 int (*connect_fn
) (const char *, int, int);
1597 const UINT32_TYPE my_actions
= (SMFIF_ADDHDRS
| SMFIF_ADDRCPT
1598 | SMFIF_DELRCPT
| SMFIF_CHGHDRS
1605 UINT32_TYPE my_version
= 0;
1606 UINT32_TYPE my_events
= 0;
1607 char *saved_version
;
1614 if (milter
->fp
!= 0)
1615 msg_panic("%s: milter %s: socket is not closed",
1616 myname
, milter
->m
.name
);
1619 * For user friendliness reasons the milter_protocol configuration
1620 * parameter can specify both the protocol version and protocol
1621 * extensions (e.g., don't reply for each individual message header).
1623 * The protocol version is sent as is to the milter application.
1625 * The version and extensions determine what events we can send to the
1626 * milter application.
1628 * We don't announce support for events that aren't defined for my protocol
1629 * version. Today's libmilter implementations don't seem to care, but we
1630 * don't want to take the risk that a future version will be more picky.
1632 cp
= saved_version
= mystrdup(milter
->protocol
);
1633 while ((name
= mystrtok(&cp
, " ,\t\r\n")) != 0) {
1637 if ((mask
= name_code(milter8_event_masks
,
1638 NAME_CODE_FLAG_NONE
, name
)) == -1
1639 || (vers
= name_code(milter8_versions
,
1640 NAME_CODE_FLAG_NONE
, name
)) == -1
1641 || (vers
!= 0 && my_version
!= 0)) {
1642 msg_warn("milter %s: bad protocol information: %s",
1643 milter
->m
.name
, name
);
1644 milter8_conf_error(milter
);
1651 myfree(saved_version
);
1652 if (my_events
== 0 || my_version
== 0) {
1653 msg_warn("milter %s: no protocol version information", milter
->m
.name
);
1654 milter8_conf_error(milter
);
1659 * Don't send events that aren't defined for my protocol version.
1661 milter
->np_mask
= (SMFIP_NOSEND_MASK
& ~my_events
);
1663 msg_info("%s: non-protocol events for protocol version %d: %s",
1665 str_name_mask_opt(milter
->buf
, "non-protocol event mask",
1666 smfip_table
, milter
->np_mask
, NAME_MASK_NUMBER
));
1669 * Parse the Milter application endpoint.
1671 #define FREE_TRANSPORT_AND_BAIL_OUT(milter, milter_error) do { \
1672 myfree(transport); \
1673 milter_error(milter); \
1677 transport
= mystrdup(milter
->m
.name
);
1678 if ((endpoint
= split_at(transport
, ':')) == 0
1679 || *endpoint
== 0 || *transport
== 0) {
1680 msg_warn("Milter service needs transport:endpoint instead of \"%s\"",
1682 FREE_TRANSPORT_AND_BAIL_OUT(milter
, milter8_conf_error
);
1685 msg_info("%s: transport=%s endpoint=%s", myname
, transport
, endpoint
);
1686 if (strcmp(transport
, "inet") == 0) {
1687 connect_fn
= inet_connect
;
1688 } else if (strcmp(transport
, "unix") == 0) {
1689 connect_fn
= unix_connect
;
1690 } else if (strcmp(transport
, "local") == 0) {
1691 connect_fn
= LOCAL_CONNECT
;
1693 msg_warn("invalid transport name: %s in Milter service: %s",
1694 transport
, milter
->m
.name
);
1695 FREE_TRANSPORT_AND_BAIL_OUT(milter
, milter8_conf_error
);
1699 * Connect to the Milter application.
1701 if ((fd
= connect_fn(endpoint
, BLOCKING
, milter
->conn_timeout
)) < 0) {
1702 msg_warn("connect to Milter service %s: %m", milter
->m
.name
);
1703 FREE_TRANSPORT_AND_BAIL_OUT(milter
, milter8_comm_error
);
1706 milter
->fp
= vstream_fdopen(fd
, O_RDWR
);
1707 vstream_control(milter
->fp
,
1709 VSTREAM_CTL_TIMEOUT
, milter
->cmd_timeout
,
1711 /* Avoid poor performance when TCP MSS > VSTREAM_BUFSIZE. */
1712 if (connect_fn
== inet_connect
)
1713 vstream_tweak_tcp(milter
->fp
);
1716 * Open the negotiations by sending what actions the Milter may request
1717 * and what events the Milter can receive.
1720 msg_info("%s: my_version=0x%lx", myname
, (long) my_version
);
1721 msg_info("%s: my_actions=0x%lx %s", myname
, (long) my_actions
,
1722 str_name_mask_opt(milter
->buf
, "request mask",
1723 smfif_table
, my_actions
, NAME_MASK_NUMBER
));
1724 msg_info("%s: my_events=0x%lx %s", myname
, (long) my_events
,
1725 str_name_mask_opt(milter
->buf
, "event mask",
1726 smfip_table
, my_events
, NAME_MASK_NUMBER
));
1729 if (milter8_write_cmd(milter
, SMFIC_OPTNEG
,
1730 MILTER8_DATA_HLONG
, my_version
,
1731 MILTER8_DATA_HLONG
, my_actions
,
1732 MILTER8_DATA_HLONG
, my_events
,
1733 MILTER8_DATA_END
) != 0) {
1734 msg_warn("milter %s: write error in initial handshake",
1736 /* milter8_write_cmd() called milter8_comm_error() */
1741 * Receive the filter's response and verify that we are compatible.
1743 if (milter8_read_resp(milter
, SMFIC_OPTNEG
, &cmd
, &data_len
) != 0) {
1744 msg_warn("milter %s: read error in initial handshake", milter
->m
.name
);
1745 /* milter8_read_resp() called milter8_comm_error() */
1748 if (cmd
!= SMFIC_OPTNEG
) {
1749 msg_warn("milter %s: unexpected reply \"%c\" in initial handshake",
1750 milter
->m
.name
, cmd
);
1751 (void) milter8_comm_error(milter
);
1754 if (milter8_read_data(milter
, &data_len
,
1755 MILTER8_DATA_HLONG
, &milter
->version
,
1756 MILTER8_DATA_HLONG
, &milter
->rq_mask
,
1757 MILTER8_DATA_HLONG
, &milter
->ev_mask
,
1758 MILTER8_DATA_MORE
) != 0) {
1759 msg_warn("milter %s: read error in initial handshake", milter
->m
.name
);
1760 /* milter8_read_data() called milter8_comm_error() */
1763 if (milter
->version
> my_version
) {
1764 msg_warn("milter %s: protocol version %d conflict"
1765 " with MTA protocol version %d",
1766 milter
->m
.name
, milter
->version
, my_version
);
1767 (void) milter8_comm_error(milter
);
1770 if ((milter
->rq_mask
& my_actions
) != milter
->rq_mask
) {
1771 msg_warn("milter %s: request mask 0x%x conflict"
1772 " with MTA request mask 0x%lx",
1773 milter
->m
.name
, milter
->rq_mask
, (long) my_actions
);
1774 (void) milter8_comm_error(milter
);
1777 if (milter
->ev_mask
& SMFIP_RCPT_REJ
)
1778 milter
->m
.flags
|= MILTER_FLAG_WANT_RCPT_REJ
;
1781 * Initial negotiations completed.
1784 if ((milter
->ev_mask
& my_events
) != milter
->ev_mask
)
1785 msg_info("milter %s: event mask 0x%x includes features not"
1786 " offered in MTA event mask 0x%lx",
1787 milter
->m
.name
, milter
->ev_mask
, (long) my_events
);
1788 msg_info("%s: milter %s version %d",
1789 myname
, milter
->m
.name
, milter
->version
);
1790 msg_info("%s: events %s", myname
,
1791 str_name_mask_opt(milter
->buf
, "event mask",
1792 smfip_table
, milter
->ev_mask
, NAME_MASK_NUMBER
));
1793 msg_info("%s: requests %s", myname
,
1794 str_name_mask_opt(milter
->buf
, "request mask",
1795 smfif_table
, milter
->rq_mask
, NAME_MASK_NUMBER
));
1797 milter
->state
= MILTER8_STAT_READY
;
1798 milter8_def_reply(milter
, 0);
1799 milter
->skip_event_type
= 0;
1802 * Secondary negotiations: override lists of macro names.
1805 VSTRING
*buf
= vstring_alloc(100);
1806 UINT32_TYPE mac_type
;
1807 const char *smfim_name
;
1808 char **mac_value_ptr
;
1810 milter
->m
.macros
= milter_macros_alloc(MILTER_MACROS_ALLOC_EMPTY
);
1813 && milter8_read_data(milter
, &data_len
,
1814 MILTER8_DATA_HLONG
, &mac_type
,
1815 MILTER8_DATA_STRING
, buf
,
1816 MILTER8_DATA_MORE
) == 0) {
1817 smfim_name
= str_name_code(smfim_table
, mac_type
);
1818 if (smfim_name
== 0) {
1819 msg_warn("milter %s: ignoring unknown macro type %u",
1820 milter
->m
.name
, (unsigned) mac_type
);
1823 msg_info("override %s macro list with \"%s\"",
1824 smfim_name
, STR(buf
));
1825 mac_value_ptr
= MILTER8_MACRO_PTR(milter
->m
.macros
, mac_type
);
1826 myfree(*mac_value_ptr
);
1827 *mac_value_ptr
= mystrdup(STR(buf
));
1830 /* milter8_read_data() calls milter8_comm_error() after error. */
1832 /* At this point the filter state is either READY or ERROR. */
1836 /* milter8_conn_event - report connect event to Sendmail 8 milter */
1838 static const char *milter8_conn_event(MILTER
*m
,
1839 const char *client_name
,
1840 const char *client_addr
,
1841 const char *client_port
,
1842 unsigned addr_family
,
1845 const char *myname
= "milter8_conn_event";
1846 MILTER8
*milter
= (MILTER8
*) m
;
1849 const char *sm_name
;
1854 * Need a global definition for "unknown" host name or address that is
1855 * shared by smtpd, cleanup and libmilter.
1857 #define XXX_UNKNOWN "unknown"
1858 #define STR_EQ(x,y) (strcmp((x), (y)) == 0)
1859 #define STR_NE(x,y) (strcmp((x), (y)) != 0)
1862 * XXX Sendmail 8 libmilter closes the MTA-to-filter socket when it finds
1863 * out that the SMTP client has disconnected. Because of this, Postfix
1864 * has to open a new MTA-to-filter socket for each SMTP client.
1866 #ifdef LIBMILTER_AUTO_DISCONNECT
1867 milter8_connect(milter
);
1873 switch (milter
->state
) {
1874 case MILTER8_STAT_ERROR
:
1876 msg_info("%s: skip milter %s", myname
, milter
->m
.name
);
1877 return (milter
->def_reply
);
1878 case MILTER8_STAT_READY
:
1880 msg_info("%s: milter %s: connect %s/%s",
1881 myname
, milter
->m
.name
, client_name
, client_addr
);
1882 if (client_port
== 0) {
1884 } else if (!alldig(client_port
) || (port
= atoi(client_port
)) < 0
1886 msg_warn("milter %s: bad client port number %s",
1887 milter
->m
.name
, client_port
);
1890 milter
->state
= MILTER8_STAT_ENVELOPE
;
1891 skip_reply
= ((milter
->ev_mask
& SMFIP_NR_CONN
) != 0);
1892 /* Transform unknown hostname from Postfix to Sendmail form. */
1893 sm_name
= (STR_NE(client_name
, XXX_UNKNOWN
) ? client_name
:
1894 STR_EQ(client_addr
, XXX_UNKNOWN
) ? client_name
:
1895 (ptr
= concatenate("[", client_addr
, "]", (char *) 0)));
1896 switch (addr_family
) {
1898 resp
= milter8_event(milter
, SMFIC_CONNECT
, SMFIP_NOCONNECT
,
1900 MILTER8_DATA_STRING
, sm_name
,
1901 MILTER8_DATA_OCTET
, SMFIA_INET
,
1902 MILTER8_DATA_NSHORT
, htons(port
),
1903 MILTER8_DATA_STRING
, client_addr
,
1908 resp
= milter8_event(milter
, SMFIC_CONNECT
, SMFIP_NOCONNECT
,
1910 MILTER8_DATA_STRING
, sm_name
,
1911 MILTER8_DATA_OCTET
, SMFIA_INET6
,
1912 MILTER8_DATA_NSHORT
, htons(port
),
1913 MILTER8_DATA_STRING
, client_addr
,
1918 resp
= milter8_event(milter
, SMFIC_CONNECT
, SMFIP_NOCONNECT
,
1920 MILTER8_DATA_STRING
, sm_name
,
1921 MILTER8_DATA_OCTET
, SMFIA_UNIX
,
1922 MILTER8_DATA_NSHORT
, htons(0),
1923 MILTER8_DATA_STRING
, client_addr
,
1927 resp
= milter8_event(milter
, SMFIC_CONNECT
, SMFIP_NOCONNECT
,
1929 MILTER8_DATA_STRING
, sm_name
,
1930 MILTER8_DATA_OCTET
, SMFIA_UNKNOWN
,
1938 msg_panic("%s: milter %s: bad state %d",
1939 myname
, milter
->m
.name
, milter
->state
);
1943 /* milter8_helo_event - report HELO/EHLO command to Sendmail 8 milter */
1945 static const char *milter8_helo_event(MILTER
*m
, const char *helo_name
,
1949 const char *myname
= "milter8_helo_event";
1950 MILTER8
*milter
= (MILTER8
*) m
;
1956 switch (milter
->state
) {
1957 case MILTER8_STAT_ERROR
:
1958 case MILTER8_STAT_ACCEPT_CON
:
1959 case MILTER8_STAT_REJECT_CON
:
1961 msg_info("%s: skip milter %s", myname
, milter
->m
.name
);
1962 return (milter
->def_reply
);
1963 case MILTER8_STAT_ENVELOPE
:
1964 case MILTER8_STAT_ACCEPT_MSG
:
1965 /* With HELO after MAIL, smtpd(8) calls milter8_abort() next. */
1967 msg_info("%s: milter %s: helo %s",
1968 myname
, milter
->m
.name
, helo_name
);
1969 skip_reply
= ((milter
->ev_mask
& SMFIP_NR_HELO
) != 0);
1970 return (milter8_event(milter
, SMFIC_HELO
, SMFIP_NOHELO
,
1972 MILTER8_DATA_STRING
, helo_name
,
1975 msg_panic("%s: milter %s: bad state %d",
1976 myname
, milter
->m
.name
, milter
->state
);
1980 /* milter8_mail_event - report MAIL command to Sendmail 8 milter */
1982 static const char *milter8_mail_event(MILTER
*m
, const char **argv
,
1985 const char *myname
= "milter8_mail_event";
1986 MILTER8
*milter
= (MILTER8
*) m
;
1993 switch (milter
->state
) {
1994 case MILTER8_STAT_ERROR
:
1995 case MILTER8_STAT_ACCEPT_CON
:
1996 case MILTER8_STAT_REJECT_CON
:
1998 msg_info("%s: skip milter %s", myname
, milter
->m
.name
);
1999 return (milter
->def_reply
);
2000 case MILTER8_STAT_ENVELOPE
:
2002 VSTRING
*buf
= vstring_alloc(100);
2004 for (cpp
= argv
; *cpp
; cpp
++)
2005 vstring_sprintf_append(buf
, " %s", *cpp
);
2006 msg_info("%s: milter %s: mail%s",
2007 myname
, milter
->m
.name
, STR(buf
));
2010 skip_reply
= ((milter
->ev_mask
& SMFIP_NR_MAIL
) != 0);
2011 return (milter8_event(milter
, SMFIC_MAIL
, SMFIP_NOMAIL
,
2013 MILTER8_DATA_ARGV
, argv
,
2016 msg_panic("%s: milter %s: bad state %d",
2017 myname
, milter
->m
.name
, milter
->state
);
2021 /* milter8_rcpt_event - report RCPT command to Sendmail 8 milter */
2023 static const char *milter8_rcpt_event(MILTER
*m
, const char **argv
,
2026 const char *myname
= "milter8_rcpt_event";
2027 MILTER8
*milter
= (MILTER8
*) m
;
2034 switch (milter
->state
) {
2035 case MILTER8_STAT_ERROR
:
2036 case MILTER8_STAT_ACCEPT_CON
:
2037 case MILTER8_STAT_REJECT_CON
:
2038 case MILTER8_STAT_ACCEPT_MSG
:
2040 msg_info("%s: skip milter %s", myname
, milter
->m
.name
);
2041 return (milter
->def_reply
);
2042 case MILTER8_STAT_ENVELOPE
:
2044 VSTRING
*buf
= vstring_alloc(100);
2046 for (cpp
= argv
; *cpp
; cpp
++)
2047 vstring_sprintf_append(buf
, " %s", *cpp
);
2048 msg_info("%s: milter %s: rcpt%s",
2049 myname
, milter
->m
.name
, STR(buf
));
2052 skip_reply
= ((milter
->ev_mask
& SMFIP_NR_RCPT
) != 0);
2053 return (milter8_event(milter
, SMFIC_RCPT
, SMFIP_NORCPT
,
2055 MILTER8_DATA_ARGV
, argv
,
2058 msg_panic("%s: milter %s: bad state %d",
2059 myname
, milter
->m
.name
, milter
->state
);
2063 /* milter8_data_event - report DATA command to Sendmail 8 milter */
2065 static const char *milter8_data_event(MILTER
*m
, ARGV
*macros
)
2067 const char *myname
= "milter8_data_event";
2068 MILTER8
*milter
= (MILTER8
*) m
;
2074 switch (milter
->state
) {
2075 case MILTER8_STAT_ERROR
:
2076 case MILTER8_STAT_ACCEPT_CON
:
2077 case MILTER8_STAT_REJECT_CON
:
2078 case MILTER8_STAT_ACCEPT_MSG
:
2080 msg_info("%s: skip milter %s", myname
, milter
->m
.name
);
2081 return (milter
->def_reply
);
2082 case MILTER8_STAT_ENVELOPE
:
2084 msg_info("%s: milter %s: data command", myname
, milter
->m
.name
);
2085 skip_reply
= ((milter
->ev_mask
& SMFIP_NR_DATA
) != 0);
2086 return (milter8_event(milter
, SMFIC_DATA
, SMFIP_NODATA
,
2090 msg_panic("%s: milter %s: bad state %d",
2091 myname
, milter
->m
.name
, milter
->state
);
2095 /* milter8_unknown_event - report unknown SMTP command to Sendmail 8 milter */
2097 static const char *milter8_unknown_event(MILTER
*m
, const char *command
,
2100 const char *myname
= "milter8_unknown_event";
2101 MILTER8
*milter
= (MILTER8
*) m
;
2107 switch (milter
->state
) {
2108 case MILTER8_STAT_ERROR
:
2109 case MILTER8_STAT_ACCEPT_CON
:
2110 case MILTER8_STAT_REJECT_CON
:
2111 case MILTER8_STAT_ACCEPT_MSG
:
2113 msg_info("%s: skip milter %s", myname
, milter
->m
.name
);
2114 return (milter
->def_reply
);
2115 case MILTER8_STAT_ENVELOPE
:
2117 msg_info("%s: milter %s: unknown command: %s",
2118 myname
, milter
->m
.name
, command
);
2119 /* XXX Sendmail doesn't send macros (checked with 8.6.13). */
2120 skip_reply
= ((milter
->ev_mask
& SMFIP_NR_UNKN
) != 0);
2121 return (milter8_event(milter
, SMFIC_UNKNOWN
, SMFIP_NOUNKNOWN
,
2123 MILTER8_DATA_STRING
, command
,
2126 msg_panic("%s: milter %s: bad state %d",
2127 myname
, milter
->m
.name
, milter
->state
);
2131 /* milter8_other_event - reply for other event */
2133 static const char *milter8_other_event(MILTER
*m
)
2135 const char *myname
= "milter8_other_event";
2136 MILTER8
*milter
= (MILTER8
*) m
;
2139 * Return the default reply.
2142 msg_info("%s: milter %s", myname
, milter
->m
.name
);
2143 return (milter
->def_reply
);
2146 /* milter8_abort - cancel one milter's message receiving state */
2148 static void milter8_abort(MILTER
*m
)
2150 const char *myname
= "milter8_abort";
2151 MILTER8
*milter
= (MILTER8
*) m
;
2154 * XXX Sendmail 8 libmilter closes the MTA-to-filter socket when it finds
2155 * out that the SMTP client has disconnected. Because of this, Postfix
2156 * has to open a new MTA-to-filter socket for each SMTP client.
2158 switch (milter
->state
) {
2159 case MILTER8_STAT_CLOSED
:
2160 case MILTER8_STAT_READY
:
2162 case MILTER8_STAT_ERROR
:
2163 case MILTER8_STAT_ACCEPT_CON
:
2164 case MILTER8_STAT_REJECT_CON
:
2166 msg_info("%s: skip milter %s", myname
, milter
->m
.name
);
2168 case MILTER8_STAT_ENVELOPE
:
2169 case MILTER8_STAT_MESSAGE
:
2170 case MILTER8_STAT_ACCEPT_MSG
:
2172 msg_info("%s: abort milter %s", myname
, milter
->m
.name
);
2173 (void) milter8_write_cmd(milter
, SMFIC_ABORT
, MILTER8_DATA_END
);
2174 if (milter
->state
!= MILTER8_STAT_ERROR
)
2175 milter
->state
= MILTER8_STAT_ENVELOPE
;
2178 msg_panic("%s: milter %s: bad state %d",
2179 myname
, milter
->m
.name
, milter
->state
);
2183 /* milter8_disc_event - report client disconnect event */
2185 static void milter8_disc_event(MILTER
*m
)
2187 const char *myname
= "milter8_disc_event";
2188 MILTER8
*milter
= (MILTER8
*) m
;
2191 * XXX Sendmail 8 libmilter closes the MTA-to-filter socket when it finds
2192 * out that the SMTP client has disconnected. Because of this, Postfix
2193 * has to open a new MTA-to-filter socket for each SMTP client.
2195 switch (milter
->state
) {
2196 case MILTER8_STAT_CLOSED
:
2197 case MILTER8_STAT_READY
:
2199 case MILTER8_STAT_ERROR
:
2200 #ifdef LIBMILTER_AUTO_DISCONNECT
2201 case MILTER8_STAT_ACCEPT_CON
:
2202 case MILTER8_STAT_REJECT_CON
:
2205 msg_info("%s: skip quit milter %s", myname
, milter
->m
.name
);
2207 case MILTER8_STAT_ENVELOPE
:
2208 case MILTER8_STAT_MESSAGE
:
2209 #ifndef LIBMILTER_AUTO_DISCONNECT
2210 case MILTER8_STAT_ACCEPT_CON
:
2211 case MILTER8_STAT_REJECT_CON
:
2213 case MILTER8_STAT_ACCEPT_MSG
:
2215 msg_info("%s: quit milter %s", myname
, milter
->m
.name
);
2216 (void) milter8_write_cmd(milter
, SMFIC_QUIT
, MILTER8_DATA_END
);
2219 #ifdef LIBMILTER_AUTO_DISCONNECT
2220 milter8_close_stream(milter
);
2222 if (milter
->state
!= MILTER8_STAT_ERROR
)
2223 milter
->state
= MILTER8_STAT_READY
;
2225 milter8_def_reply(milter
, 0);
2229 * Structure to ship context across the MIME_STATE engine.
2232 MILTER8
*milter
; /* milter client */
2233 ARGV
*eoh_macros
; /* end-of-header macros */
2234 ARGV
*eod_macros
; /* end-of-body macros */
2235 int first_header
; /* first header */
2236 int first_body
; /* first body line */
2237 const char *resp
; /* milter application response */
2238 } MILTER_MSG_CONTEXT
;
2240 /* milter8_header - milter8_message call-back for message header */
2242 static void milter8_header(void *ptr
, int unused_header_class
,
2243 const HEADER_OPTS
*header_info
,
2244 VSTRING
*buf
, off_t unused_offset
)
2246 const char *myname
= "milter8_header";
2247 MILTER_MSG_CONTEXT
*msg_ctx
= (MILTER_MSG_CONTEXT
*) ptr
;
2248 MILTER8
*milter
= msg_ctx
->milter
;
2253 * XXX Workaround: mime_state_update() may invoke multiple call-backs
2254 * before returning to the caller.
2256 #define MILTER8_MESSAGE_DONE(milter, msg_ctx) \
2257 ((milter)->state != MILTER8_STAT_MESSAGE || (msg_ctx)->resp != 0)
2259 if (MILTER8_MESSAGE_DONE(milter
, msg_ctx
))
2263 * XXX Sendmail compatibility. Don't expose our first (received) header
2264 * to mail filter applications. See also cleanup_milter.c for code to
2265 * ensure that header replace requests are relative to the message
2266 * content as received, that is, without our own first (received) header,
2267 * while header insert requests are relative to the message as delivered,
2268 * that is, including our own first (received) header.
2270 * XXX But this breaks when they delete our own Received: header with
2271 * header_checks before it reaches the queue file. Even then we must not
2272 * expose the first header to mail filter applications, otherwise the
2273 * dk-filter signature will be inserted at the wrong position. It should
2274 * precede the headers that it signs.
2276 * XXX Sendmail compatibility. It eats the first space (not tab) after the
2277 * header label and ":".
2279 if (msg_ctx
->first_header
) {
2280 msg_ctx
->first_header
= 0;
2285 * Sendmail 8 sends multi-line headers as text separated by newline.
2287 * We destroy the header buffer to split it into label and value. Changing
2288 * the buffer is explicitly allowed by the mime_state(3) interface.
2290 if (msg_verbose
> 1)
2291 msg_info("%s: header milter %s: %.100s",
2292 myname
, milter
->m
.name
, STR(buf
));
2293 cp
= STR(buf
) + (header_info
? strlen(header_info
->name
) :
2294 is_header(STR(buf
)));
2295 /* XXX Following matches is_header.c */
2296 while (*cp
== ' ' || *cp
== '\t')
2299 msg_panic("%s: header label not followed by ':'", myname
);
2301 /* XXX Sendmail by default eats one space (not tab) after the colon. */
2302 if ((milter
->ev_mask
& SMFIP_HDR_LEADSPC
) == 0 && *cp
== ' ')
2304 skip_reply
= ((milter
->ev_mask
& SMFIP_NOHREPL
) != 0);
2306 milter8_event(milter
, SMFIC_HEADER
, SMFIP_NOHDRS
,
2307 skip_reply
, msg_ctx
->eoh_macros
,
2308 MILTER8_DATA_STRING
, STR(buf
),
2309 MILTER8_DATA_STRING
, cp
,
2313 /* milter8_eoh - milter8_message call-back for end-of-header */
2315 static void milter8_eoh(void *ptr
)
2317 const char *myname
= "milter8_eoh";
2318 MILTER_MSG_CONTEXT
*msg_ctx
= (MILTER_MSG_CONTEXT
*) ptr
;
2319 MILTER8
*milter
= msg_ctx
->milter
;
2322 if (MILTER8_MESSAGE_DONE(milter
, msg_ctx
))
2325 msg_info("%s: eoh milter %s", myname
, milter
->m
.name
);
2326 skip_reply
= ((milter
->ev_mask
& SMFIP_NR_EOH
) != 0);
2328 milter8_event(milter
, SMFIC_EOH
, SMFIP_NOEOH
,
2329 skip_reply
, msg_ctx
->eoh_macros
,
2333 /* milter8_body - milter8_message call-back for body content */
2335 static void milter8_body(void *ptr
, int rec_type
,
2336 const char *buf
, ssize_t len
,
2339 const char *myname
= "milter8_body";
2340 MILTER_MSG_CONTEXT
*msg_ctx
= (MILTER_MSG_CONTEXT
*) ptr
;
2341 MILTER8
*milter
= msg_ctx
->milter
;
2343 const char *bp
= buf
;
2348 if (MILTER8_MESSAGE_DONE(milter
, msg_ctx
))
2352 * XXX Sendmail compatibility: don't expose our first body line.
2354 if (msg_ctx
->first_body
) {
2355 msg_ctx
->first_body
= 0;
2360 * XXX I thought I was going to delegate all the on-the-wire formatting
2361 * to a common lower layer, but unfortunately it's not practical. If we
2362 * were to do MILTER_CHUNK_SIZE buffering in a common lower layer, then
2363 * we would have to pass along call-backs and state, so that the
2364 * call-back can invoke milter8_event() with the right arguments when the
2365 * MILTER_CHUNK_SIZE buffer reaches capacity. That's just too ugly.
2367 * To recover the cost of making an extra copy of body content from Milter
2368 * buffer to VSTREAM buffer, we could make vstream_fwrite() a little
2369 * smarter so that it does large transfers directly from the user buffer
2370 * instead of copying the data one block at a time into a VSTREAM buffer.
2372 if (msg_verbose
> 1)
2373 msg_info("%s: body milter %s: %.100s", myname
, milter
->m
.name
, buf
);
2374 skip_reply
= ((milter
->ev_mask
& SMFIP_NR_BODY
) != 0);
2375 /* To append \r\n, simply redirect input to another buffer. */
2376 if (rec_type
== REC_TYPE_NORM
&& todo
== 0) {
2379 rec_type
= REC_TYPE_EOF
;
2382 /* Append one REC_TYPE_NORM or REC_TYPE_CONT to body chunk buffer. */
2383 space
= MILTER_CHUNK_SIZE
- LEN(milter
->body
);
2385 msg_panic("%s: bad buffer size: %ld",
2386 myname
, (long) LEN(milter
->body
));
2387 count
= (todo
> space
? space
: todo
);
2388 vstring_memcat(milter
->body
, bp
, count
);
2391 /* Flush body chunk buffer when full. See also milter8_eob(). */
2392 if (LEN(milter
->body
) == MILTER_CHUNK_SIZE
) {
2394 milter8_event(milter
, SMFIC_BODY
, SMFIP_NOBODY
,
2395 skip_reply
, msg_ctx
->eod_macros
,
2396 MILTER8_DATA_BUFFER
, milter
->body
,
2398 if (MILTER8_MESSAGE_DONE(milter
, msg_ctx
))
2400 VSTRING_RESET(milter
->body
);
2402 /* To append \r\n, simply redirect input to another buffer. */
2403 if (rec_type
== REC_TYPE_NORM
&& todo
== 0) {
2406 rec_type
= REC_TYPE_EOF
;
2411 /* milter8_eob - milter8_message call-back for end-of-body */
2413 static void milter8_eob(void *ptr
)
2415 const char *myname
= "milter8_eob";
2416 MILTER_MSG_CONTEXT
*msg_ctx
= (MILTER_MSG_CONTEXT
*) ptr
;
2417 MILTER8
*milter
= msg_ctx
->milter
;
2420 if (MILTER8_MESSAGE_DONE(milter
, msg_ctx
))
2423 msg_info("%s: eob milter %s", myname
, milter
->m
.name
);
2426 * Flush partial body chunk buffer. See also milter8_body().
2428 * XXX Sendmail 8 libmilter accepts SMFIC_EOB+data, and delivers it to the
2429 * application as two events: SMFIC_BODY+data followed by SMFIC_EOB. This
2430 * breaks with the PMilter 0.95 protocol re-implementation, which
2431 * delivers the SMFIC_EOB event and ignores the data. To avoid such
2432 * compatibility problems we separate the events in the client. With
2433 * this, we also prepare for a future where different event types can
2434 * have different macro lists.
2436 if (LEN(milter
->body
) > 0) {
2437 skip_reply
= ((milter
->ev_mask
& SMFIP_NR_BODY
) != 0);
2439 milter8_event(milter
, SMFIC_BODY
, SMFIP_NOBODY
,
2440 skip_reply
, msg_ctx
->eod_macros
,
2441 MILTER8_DATA_BUFFER
, milter
->body
,
2443 if (MILTER8_MESSAGE_DONE(milter
, msg_ctx
))
2447 milter8_event(msg_ctx
->milter
, SMFIC_BODYEOB
, 0,
2448 DONT_SKIP_REPLY
, msg_ctx
->eod_macros
,
2452 /* milter8_message - send message content and receive reply */
2454 static const char *milter8_message(MILTER
*m
, VSTREAM
*qfile
,
2459 const char *myname
= "milter8_message";
2460 MILTER8
*milter
= (MILTER8
*) m
;
2461 MIME_STATE
*mime_state
;
2463 const MIME_STATE_DETAIL
*detail
;
2465 MILTER_MSG_CONTEXT msg_ctx
;
2468 switch (milter
->state
) {
2469 case MILTER8_STAT_ERROR
:
2470 case MILTER8_STAT_ACCEPT_CON
:
2471 case MILTER8_STAT_REJECT_CON
:
2472 case MILTER8_STAT_ACCEPT_MSG
:
2474 msg_info("%s: skip message to milter %s", myname
, milter
->m
.name
);
2475 return (milter
->def_reply
);
2476 case MILTER8_STAT_ENVELOPE
:
2478 msg_info("%s: message to milter %s", myname
, milter
->m
.name
);
2479 if (vstream_fseek(qfile
, data_offset
, SEEK_SET
) < 0) {
2480 msg_warn("%s: vstream_fseek %s: %m", myname
, VSTREAM_PATH(qfile
));
2481 return ("450 4.3.0 Queue file write error");
2483 msg_ctx
.milter
= milter
;
2484 msg_ctx
.eoh_macros
= eoh_macros
;
2485 msg_ctx
.eod_macros
= eod_macros
;
2486 msg_ctx
.first_header
= 1;
2487 msg_ctx
.first_body
= 1;
2490 mime_state_alloc(MIME_OPT_DISABLE_MIME
,
2491 (milter
->ev_mask
& SMFIP_NOHDRS
) ?
2492 (MIME_STATE_HEAD_OUT
) 0 : milter8_header
,
2493 (milter
->ev_mask
& SMFIP_NOEOH
) ?
2494 (MIME_STATE_ANY_END
) 0 : milter8_eoh
,
2495 (milter
->ev_mask
& SMFIP_NOBODY
) ?
2496 (MIME_STATE_BODY_OUT
) 0 : milter8_body
,
2498 (MIME_STATE_ERR_PRINT
) 0,
2500 buf
= vstring_alloc(100);
2501 milter
->state
= MILTER8_STAT_MESSAGE
;
2502 VSTRING_RESET(milter
->body
);
2503 vstream_control(milter
->fp
,
2505 VSTREAM_CTL_TIMEOUT
, milter
->msg_timeout
,
2509 * XXX When the message (not MIME body part) does not end in CRLF
2510 * (i.e. the last record was REC_TYPE_CONT), do we send a CRLF
2511 * terminator before triggering the end-of-body condition?
2514 if ((rec_type
= rec_get(qfile
, buf
, 0)) < 0) {
2515 msg_warn("%s: error reading %s: %m",
2516 myname
, VSTREAM_PATH(qfile
));
2517 msg_ctx
.resp
= "450 4.3.0 Queue file write error";
2520 /* Invoke the appropriate call-back routine. */
2521 mime_errs
= mime_state_update(mime_state
, rec_type
,
2522 STR(buf
), LEN(buf
));
2524 detail
= mime_state_detail(mime_errs
);
2525 msg_warn("%s: MIME problem %s in %s",
2526 myname
, detail
->text
, VSTREAM_PATH(qfile
));
2527 msg_ctx
.resp
= "450 4.3.0 Queue file write error";
2530 if (MILTER8_MESSAGE_DONE(milter
, &msg_ctx
))
2532 if (rec_type
!= REC_TYPE_NORM
&& rec_type
!= REC_TYPE_CONT
)
2535 mime_state_free(mime_state
);
2538 vstream_control(milter
->fp
,
2540 VSTREAM_CTL_TIMEOUT
, milter
->cmd_timeout
,
2542 if (milter
->state
== MILTER8_STAT_MESSAGE
2543 || milter
->state
== MILTER8_STAT_ACCEPT_MSG
)
2544 milter
->state
= MILTER8_STAT_ENVELOPE
;
2545 return (msg_ctx
.resp
);
2547 msg_panic("%s: milter %s: bad state %d",
2548 myname
, milter
->m
.name
, milter
->state
);
2553 * Preliminary protocol to send/receive milter instances. This needs to be
2554 * extended with type information once we support multiple milter protocols.
2556 #define MAIL_ATTR_MILT_NAME "milter_name"
2557 #define MAIL_ATTR_MILT_VERS "milter_version"
2558 #define MAIL_ATTR_MILT_ACTS "milter_actions"
2559 #define MAIL_ATTR_MILT_EVTS "milter_events"
2560 #define MAIL_ATTR_MILT_NPTS "milter_non_events"
2561 #define MAIL_ATTR_MILT_STAT "milter_state"
2562 #define MAIL_ATTR_MILT_CONN "milter_conn_timeout"
2563 #define MAIL_ATTR_MILT_CMD "milter_cmd_timeout"
2564 #define MAIL_ATTR_MILT_MSG "milter_msg_timeout"
2565 #define MAIL_ATTR_MILT_ACT "milter_action"
2566 #define MAIL_ATTR_MILT_MAC "milter_macro_list"
2568 /* milter8_active - report if this milter still wants events */
2570 static int milter8_active(MILTER
*m
)
2572 MILTER8
*milter
= (MILTER8
*) m
;
2574 return (milter
->fp
!= 0
2575 && (milter
->state
== MILTER8_STAT_ENVELOPE
2576 || milter
->state
== MILTER8_STAT_READY
));
2579 /* milter8_send - send milter instance */
2581 static int milter8_send(MILTER
*m
, VSTREAM
*stream
)
2583 const char *myname
= "milter8_send";
2584 MILTER8
*milter
= (MILTER8
*) m
;
2587 msg_info("%s: milter %s", myname
, milter
->m
.name
);
2589 if (attr_print(stream
, ATTR_FLAG_MORE
,
2590 ATTR_TYPE_STR
, MAIL_ATTR_MILT_NAME
, milter
->m
.name
,
2591 ATTR_TYPE_INT
, MAIL_ATTR_MILT_VERS
, milter
->version
,
2592 ATTR_TYPE_INT
, MAIL_ATTR_MILT_ACTS
, milter
->rq_mask
,
2593 ATTR_TYPE_INT
, MAIL_ATTR_MILT_EVTS
, milter
->ev_mask
,
2594 ATTR_TYPE_INT
, MAIL_ATTR_MILT_NPTS
, milter
->np_mask
,
2595 ATTR_TYPE_INT
, MAIL_ATTR_MILT_STAT
, milter
->state
,
2596 ATTR_TYPE_INT
, MAIL_ATTR_MILT_CONN
, milter
->conn_timeout
,
2597 ATTR_TYPE_INT
, MAIL_ATTR_MILT_CMD
, milter
->cmd_timeout
,
2598 ATTR_TYPE_INT
, MAIL_ATTR_MILT_MSG
, milter
->msg_timeout
,
2599 ATTR_TYPE_STR
, MAIL_ATTR_MILT_ACT
, milter
->def_action
,
2600 ATTR_TYPE_INT
, MAIL_ATTR_MILT_MAC
, milter
->m
.macros
!= 0,
2602 || (milter
->m
.macros
!= 0
2603 && attr_print(stream
, ATTR_FLAG_NONE
,
2604 ATTR_TYPE_FUNC
, milter_macros_print
,
2605 (void *) milter
->m
.macros
,
2606 ATTR_TYPE_END
) != 0)
2607 || (milter
->m
.macros
== 0
2608 && attr_print(stream
, ATTR_FLAG_NONE
,
2609 ATTR_TYPE_END
) != 0)
2610 || vstream_fflush(stream
) != 0) {
2612 #ifdef CANT_WRITE_BEFORE_SENDING_FD
2613 } else if (attr_scan(stream
, ATTR_FLAG_STRICT
,
2614 ATTR_TYPE_STR
, MAIL_ATTR_DUMMY
, milter
->buf
,
2615 ATTR_TYPE_END
) != 1) {
2618 } else if (LOCAL_SEND_FD(vstream_fileno(stream
),
2619 vstream_fileno(milter
->fp
)) < 0) {
2621 #ifdef MUST_READ_AFTER_SENDING_FD
2622 } else if (attr_scan(stream
, ATTR_FLAG_STRICT
,
2623 ATTR_TYPE_STR
, MAIL_ATTR_DUMMY
, milter
->buf
,
2624 ATTR_TYPE_END
) != 1) {
2632 static MILTER8
*milter8_alloc(const char *, int, int, int, const char *,
2633 const char *, MILTERS
*);
2635 /* milter8_receive - receive milter instance */
2637 MILTER
*milter8_receive(VSTREAM
*stream
, MILTERS
*parent
)
2639 const char *myname
= "milter8_receive";
2640 static VSTRING
*name_buf
;
2641 static VSTRING
*act_buf
;
2653 MILTER_MACROS
*macros
= 0;
2655 #define FREE_MACROS_AND_RETURN(x) do { \
2657 milter_macros_free(macros); \
2661 if (name_buf
== 0) {
2662 name_buf
= vstring_alloc(10);
2663 act_buf
= vstring_alloc(10);
2665 if (attr_scan(stream
, ATTR_FLAG_STRICT
| ATTR_FLAG_MORE
,
2666 ATTR_TYPE_STR
, MAIL_ATTR_MILT_NAME
, name_buf
,
2667 ATTR_TYPE_INT
, MAIL_ATTR_MILT_VERS
, &version
,
2668 ATTR_TYPE_INT
, MAIL_ATTR_MILT_ACTS
, &rq_mask
,
2669 ATTR_TYPE_INT
, MAIL_ATTR_MILT_EVTS
, &ev_mask
,
2670 ATTR_TYPE_INT
, MAIL_ATTR_MILT_NPTS
, &np_mask
,
2671 ATTR_TYPE_INT
, MAIL_ATTR_MILT_STAT
, &state
,
2672 ATTR_TYPE_INT
, MAIL_ATTR_MILT_CONN
, &conn_timeout
,
2673 ATTR_TYPE_INT
, MAIL_ATTR_MILT_CMD
, &cmd_timeout
,
2674 ATTR_TYPE_INT
, MAIL_ATTR_MILT_MSG
, &msg_timeout
,
2675 ATTR_TYPE_STR
, MAIL_ATTR_MILT_ACT
, act_buf
,
2676 ATTR_TYPE_INT
, MAIL_ATTR_MILT_MAC
, &has_macros
,
2679 && attr_scan(stream
, ATTR_FLAG_STRICT
,
2680 ATTR_TYPE_FUNC
, milter_macros_scan
,
2682 milter_macros_alloc(MILTER_MACROS_ALLOC_ZERO
)),
2685 && attr_scan(stream
, ATTR_FLAG_STRICT
,
2686 ATTR_TYPE_END
) < 0)) {
2687 FREE_MACROS_AND_RETURN(0);
2688 #ifdef CANT_WRITE_BEFORE_SENDING_FD
2689 } else if (attr_print(stream
, ATTR_FLAG_NONE
,
2690 ATTR_TYPE_STR
, MAIL_ATTR_DUMMY
, "",
2692 || vstream_fflush(stream
) != 0) {
2693 FREE_MACROS_AND_RETURN(0);
2695 } else if ((fd
= LOCAL_RECV_FD(vstream_fileno(stream
))) < 0) {
2696 FREE_MACROS_AND_RETURN(0);
2698 #ifdef MUST_READ_AFTER_SENDING_FD
2699 (void) attr_print(stream
, ATTR_FLAG_NONE
,
2700 ATTR_TYPE_STR
, MAIL_ATTR_DUMMY
, "",
2703 #define NO_PROTOCOL ((char *) 0)
2706 msg_info("%s: milter %s", myname
, STR(name_buf
));
2708 milter
= milter8_alloc(STR(name_buf
), conn_timeout
, cmd_timeout
,
2709 msg_timeout
, NO_PROTOCOL
, STR(act_buf
), parent
);
2710 milter
->fp
= vstream_fdopen(fd
, O_RDWR
);
2711 milter
->m
.macros
= macros
;
2712 vstream_control(milter
->fp
, VSTREAM_CTL_DOUBLE
, VSTREAM_CTL_END
);
2713 /* Avoid poor performance when TCP MSS > VSTREAM_BUFSIZE. */
2714 vstream_tweak_sock(milter
->fp
);
2715 milter
->version
= version
;
2716 milter
->rq_mask
= rq_mask
;
2717 milter
->ev_mask
= ev_mask
;
2718 milter
->np_mask
= np_mask
;
2719 milter
->state
= state
;
2720 return (&milter
->m
);
2724 /* milter8_free - destroy Milter instance */
2726 static void milter8_free(MILTER
*m
)
2728 MILTER8
*milter
= (MILTER8
*) m
;
2731 msg_info("free milter %s", milter
->m
.name
);
2733 (void) vstream_fclose(milter
->fp
);
2734 myfree(milter
->m
.name
);
2735 vstring_free(milter
->buf
);
2736 vstring_free(milter
->body
);
2737 if (milter
->protocol
)
2738 myfree(milter
->protocol
);
2739 myfree(milter
->def_action
);
2740 if (milter
->def_reply
)
2741 myfree(milter
->def_reply
);
2742 if (milter
->m
.macros
)
2743 milter_macros_free(milter
->m
.macros
);
2744 myfree((char *) milter
);
2747 /* milter8_alloc - create MTA-side Sendmail 8 Milter instance */
2749 static MILTER8
*milter8_alloc(const char *name
, int conn_timeout
,
2750 int cmd_timeout
, int msg_timeout
,
2751 const char *protocol
,
2752 const char *def_action
,
2758 * Fill in the structure.
2760 milter
= (MILTER8
*) mymalloc(sizeof(*milter
));
2761 milter
->m
.name
= mystrdup(name
);
2762 milter
->m
.flags
= 0;
2764 milter
->m
.parent
= parent
;
2765 milter
->m
.macros
= 0;
2766 milter
->m
.conn_event
= milter8_conn_event
;
2767 milter
->m
.helo_event
= milter8_helo_event
;
2768 milter
->m
.mail_event
= milter8_mail_event
;
2769 milter
->m
.rcpt_event
= milter8_rcpt_event
;
2770 milter
->m
.data_event
= milter8_data_event
; /* may be null */
2771 milter
->m
.message
= milter8_message
;
2772 milter
->m
.unknown_event
= milter8_unknown_event
; /* may be null */
2773 milter
->m
.other_event
= milter8_other_event
;
2774 milter
->m
.abort
= milter8_abort
;
2775 milter
->m
.disc_event
= milter8_disc_event
;
2776 milter
->m
.active
= milter8_active
;
2777 milter
->m
.send
= milter8_send
;
2778 milter
->m
.free
= milter8_free
;
2780 milter
->buf
= vstring_alloc(100);
2781 milter
->body
= vstring_alloc(100);
2782 milter
->version
= 0;
2783 milter
->rq_mask
= 0;
2784 milter
->ev_mask
= 0;
2785 milter
->state
= MILTER8_STAT_CLOSED
;
2786 milter
->conn_timeout
= conn_timeout
;
2787 milter
->cmd_timeout
= cmd_timeout
;
2788 milter
->msg_timeout
= msg_timeout
;
2789 milter
->protocol
= (protocol
? mystrdup(protocol
) : 0);
2790 milter
->def_action
= mystrdup(def_action
);
2791 milter
->def_reply
= 0;
2792 milter
->skip_event_type
= 0;
2797 /* milter8_create - create MTA-side Sendmail 8 Milter instance */
2799 MILTER
*milter8_create(const char *name
, int conn_timeout
, int cmd_timeout
,
2800 int msg_timeout
, const char *protocol
,
2801 const char *def_action
, MILTERS
*parent
)
2806 * Fill in the structure.
2808 milter
= milter8_alloc(name
, conn_timeout
, cmd_timeout
, msg_timeout
,
2809 protocol
, def_action
, parent
);
2812 * XXX Sendmail 8 libmilter closes the MTA-to-filter socket when it finds
2813 * out that the SMTP client has disconnected. Because of this, Postfix
2814 * has to open a new MTA-to-filter socket for each SMTP client.
2816 #ifndef LIBMILTER_AUTO_DISCONNECT
2817 milter8_connect(milter
);
2819 return (&milter
->m
);