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