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