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