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