diff --git a/postfix/HISTORY b/postfix/HISTORY index 5e90db6fd..a5890f1c3 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -14057,8 +14057,17 @@ Apologies for any names omitted. 20071123 Further polishing of the Milter code. With SETSYMLIST, each - Milter can update its own macros instead of clobbering - the global copy is shared with other Milters. Also an + Milter can now update its own macros instead of clobbering + the global copy that is shared with other Milters. Also an opportunity to clean up some ad-hoc code for sending macro lists from smtp(8) to cleanup(8). Files: milter/milter.c, milter/milter8.c, milter/milter_macros.c. + +20071224 + + Further polishing of the Milter code. Eliminated unnecessary + steps from the initial smtpd/cleanup Milter handshake. Files: + milter/milter.c, milter/milter8.c, milter/milter_macros.c. + + Cleanup: name_code(3) and name_mask(3) now support read-only + tables. Files: util/name_code.[hc] util/name_mask.[hc]. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 504707671..c953a33dd 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -11,6 +11,17 @@ instead, a new snapshot is released. The mail_release_date configuration parameter (format: yyyymmdd) specifies the release date of a stable release or snapshot release. +Incompatibility with Postfix snapshot 20071224 +============================================== + +The protocol to send Milter information from smtpd(8) to cleanup(8) +processes was cleaned up. If you use the Milter feature, and upgrade +a live Postfix system, you may see an "unexpected record type" +warning from a cleanup(8) server process. To prevent this, execute +the command "postfix reload". The incompatibility affects only +systems that use the Milter feature. It does not cause loss of mail, +just a minor delay until the remote SMTP client retries. + Major changes with Postfix snapshot 20071221 ============================================ diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index 13d051ff5..5c0872ada 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -264,7 +264,7 @@ SMTPD(8) SMTPD(8) milter_end_of_header_macros (see postconf -n output) The macros that are sent to Milter (mail filter) - applications after the message header. + applications after the end of the message header. milter_end_of_data_macros (see postconf -n output) The macros that are sent to Milter (mail filter) diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8 index 565c1e65e..118ff8b95 100644 --- a/postfix/man/man8/smtpd.8 +++ b/postfix/man/man8/smtpd.8 @@ -235,7 +235,7 @@ The macros that are sent to version 3 or higher Milter (mail filter) applications after an unknown SMTP command. .IP "\fBmilter_end_of_header_macros (see postconf -n output)\fR" The macros that are sent to Milter (mail filter) applications -after the message header. +after the end of the message header. .IP "\fBmilter_end_of_data_macros (see postconf -n output)\fR" The macros that are sent to Milter (mail filter) applications after the message end-of-data. diff --git a/postfix/src/cleanup/cleanup_envelope.c b/postfix/src/cleanup/cleanup_envelope.c index 830f37093..b21da3e85 100644 --- a/postfix/src/cleanup/cleanup_envelope.c +++ b/postfix/src/cleanup/cleanup_envelope.c @@ -146,6 +146,14 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type, return; } #endif + + /* + * XXX We instantiate a MILTERS structure even when the filter count is + * zero (for example, all filters are in ACCEPT state, or the SMTP server + * sends a dummy MILTERS structure without any filters), otherwise the + * cleanup server would apply the non_smtpd_milters setting + * inappropriately. + */ if (type == REC_TYPE_MILT_COUNT) { /* Not part of queue file format. */ if ((milter_count = atoi(buf)) >= 0) diff --git a/postfix/src/cleanup/cleanup_milter.c b/postfix/src/cleanup/cleanup_milter.c index 8b9a81b77..9a060326b 100644 --- a/postfix/src/cleanup/cleanup_milter.c +++ b/postfix/src/cleanup/cleanup_milter.c @@ -1332,6 +1332,8 @@ void cleanup_milter_receive(CLEANUP_STATE *state, int count) state->milters = milter_receive(state->src, count); if (state->milters == 0) msg_fatal("cleanup_milter_receive: milter receive failed"); + if (count <= 0) + return; milter_macro_callback(state->milters, cleanup_milter_eval, (void *) state); milter_edit_callback(state->milters, cleanup_add_header, cleanup_upd_header, diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 70c942d3c..78c67017d 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20071223" +#define MAIL_RELEASE_DATE "20071224" #define MAIL_VERSION_NUMBER "2.5" #ifdef SNAPSHOT diff --git a/postfix/src/milter/milter.c b/postfix/src/milter/milter.c index 54871653d..c8a6b556a 100644 --- a/postfix/src/milter/milter.c +++ b/postfix/src/milter/milter.c @@ -603,6 +603,10 @@ int milter_send(MILTERS *milters, VSTREAM *stream) * to a cleanup server. For now we skip only the filters that are known * to be disabled (either in global error state or in global accept * state). + * + * XXX We must send *some* information, even when there are no active + * filters, otherwise the cleanup server would try to apply its own + * non_smtpd_milters settings. */ if (milters != 0) for (m = milters->milter_list; m != 0; m = m->next) @@ -611,7 +615,14 @@ int milter_send(MILTERS *milters, VSTREAM *stream) (void) rec_fprintf(stream, REC_TYPE_MILT_COUNT, "%d", count); /* - * Send the filter macro names. + * XXX Optimization: don't send or receive further information when there + * aren't any active filters. + */ + if (count <= 0) + return (0); + + /* + * Send the filter macro name lists. */ (void) attr_print(stream, ATTR_FLAG_MORE, ATTR_TYPE_FUNC, milter_macros_print, @@ -624,6 +635,10 @@ int milter_send(MILTERS *milters, VSTREAM *stream) for (m = milters->milter_list; m != 0; m = m->next) if (m->active(m) && (status = m->send(m, stream)) != 0) break; + + /* + * Over to you. + */ if (status != 0 || attr_scan(stream, ATTR_FLAG_STRICT, ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, @@ -643,20 +658,39 @@ MILTERS *milter_receive(VSTREAM *stream, int count) MILTER *head = 0; MILTER *tail = 0; MILTER *milter = 0; - MILTER_MACROS *macros = milter_macros_alloc(MILTER_MACROS_ALLOC_ZERO); - if (attr_scan(stream, ATTR_FLAG_STRICT | ATTR_FLAG_MORE, - ATTR_TYPE_FUNC, milter_macros_scan, (void *) macros, - ATTR_TYPE_END) != 1) { - milter_macros_free(macros); - return (0); - } + /* + * XXX We must instantiate a MILTERS structure even when the sender has + * no active filters, otherwise the cleanup server would try to use its + * own non_smtpd_milters settings. + */ #define NO_MILTERS ((char *) 0) #define NO_TIMEOUTS 0, 0, 0 #define NO_PROTOCOL ((char *) 0) #define NO_ACTION ((char *) 0) +#define NO_MACROS ((MILTER_MACROS *) 0) - milters = milter_new(NO_MILTERS, NO_TIMEOUTS, NO_PROTOCOL, NO_ACTION, macros); + milters = milter_new(NO_MILTERS, NO_TIMEOUTS, NO_PROTOCOL, NO_ACTION, + NO_MACROS); + + /* + * XXX Optimization: don't send or receive further information when there + * aren't any active filters. + */ + if (count <= 0) + return (milters); + + /* + * Receive the global macro name lists. + */ + milters->macros = milter_macros_alloc(MILTER_MACROS_ALLOC_ZERO); + if (attr_scan(stream, ATTR_FLAG_STRICT | ATTR_FLAG_MORE, + ATTR_TYPE_FUNC, milter_macros_scan, + (void *) milters->macros, + ATTR_TYPE_END) != 1) { + milter_free(milters); + return (0); + } /* * Receive the filters. @@ -677,6 +711,9 @@ MILTERS *milter_receive(VSTREAM *stream, int count) tail = milter; } + /* + * Over to you. + */ (void) attr_print(stream, ATTR_FLAG_NONE, ATTR_TYPE_INT, MAIL_ATTR_STATUS, 0, ATTR_TYPE_END); diff --git a/postfix/src/milter/milter.h b/postfix/src/milter/milter.h index 1f9b7f629..f27c047d8 100644 --- a/postfix/src/milter/milter.h +++ b/postfix/src/milter/milter.h @@ -80,42 +80,6 @@ extern int milter_macros_scan(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *); #define MILTER_MACROS_ALLOC_ZERO 1 /* null pointer */ #define MILTER_MACROS_ALLOC_EMPTY 2 /* mystrdup(""); */ -#define milter_macros_wipe(mp) do { \ - MILTER_MACROS *__mp = mp; \ - if (__mp->conn_macros) \ - myfree(__mp->conn_macros); \ - if (__mp->helo_macros) \ - myfree(__mp->helo_macros); \ - if (__mp->mail_macros) \ - myfree(__mp->mail_macros); \ - if (__mp->rcpt_macros) \ - myfree(__mp->rcpt_macros); \ - if (__mp->data_macros) \ - myfree(__mp->data_macros); \ - if (__mp->eoh_macros) \ - myfree(__mp->eoh_macros); \ - if (__mp->eod_macros) \ - myfree(__mp->eod_macros); \ - if (__mp->unk_macros) \ - myfree(__mp->unk_macros); \ - } while (0) - -#define milter_macros_zero(mp) milter_macros_init(mp, 0) - -#define milter_macros_init(mp, expr) do { \ - MILTER_MACROS *__mp = (mp); \ - char *__expr = (expr); \ - __mp->conn_macros = __expr; \ - __mp->helo_macros = __expr; \ - __mp->mail_macros = __expr; \ - __mp->rcpt_macros = __expr; \ - __mp->data_macros = __expr; \ - __mp->eoh_macros = __expr; \ - __mp->eod_macros = __expr; \ - __mp->unk_macros = __expr; \ - } while (0) - - /* * A bunch of Milters. */ diff --git a/postfix/src/milter/milter8.c b/postfix/src/milter/milter8.c index fc2cccc33..17aa1ee02 100644 --- a/postfix/src/milter/milter8.c +++ b/postfix/src/milter/milter8.c @@ -123,7 +123,7 @@ /* Introduced with Sendmail 8.14. */ #define SMFIC_QUIT_NC 'K' /* Quit + new connection */ -static NAME_CODE smfic_table[] = { +static const NAME_CODE smfic_table[] = { "SMFIC_ABORT", SMFIC_ABORT, "SMFIC_BODY", SMFIC_BODY, "SMFIC_CONNECT", SMFIC_CONNECT, @@ -168,7 +168,7 @@ static NAME_CODE smfic_table[] = { #define SMFIR_ADDRCPT_PAR '2' /* add recipient (incl. ESMTP args) */ #define SMFIR_SETSYMLIST 'l' /* set list of symbols (macros) */ -static NAME_CODE smfir_table[] = { +static const NAME_CODE smfir_table[] = { "SMFIR_ADDRCPT", SMFIR_ADDRCPT, "SMFIR_DELRCPT", SMFIR_DELRCPT, "SMFIR_ACCEPT", SMFIR_ACCEPT, @@ -231,7 +231,7 @@ static NAME_CODE smfir_table[] = { | SMFIP_NR_DATA | SMFIP_NR_UNKN | SMFIP_NR_HDR | SMFIP_NR_EOH | \ SMFIP_NR_BODY) -static NAME_MASK smfip_table[] = { +static const NAME_MASK smfip_table[] = { "SMFIP_NOCONNECT", SMFIP_NOCONNECT, "SMFIP_NOHELO", SMFIP_NOHELO, "SMFIP_NOMAIL", SMFIP_NOMAIL, @@ -272,7 +272,7 @@ static NAME_MASK smfip_table[] = { #define SMFIF_ADDRCPT_PAR (1L<<7) /* filter may add recipients + args */ #define SMFIF_SETSYMLIST (1L<<8) /* filter may send macro names */ -static NAME_MASK smfif_table[] = { +static const NAME_MASK smfif_table[] = { "SMFIF_ADDHDRS", SMFIF_ADDHDRS, "SMFIF_CHGBODY", SMFIF_CHGBODY, "SMFIF_ADDRCPT", SMFIF_ADDRCPT, @@ -306,7 +306,7 @@ static NAME_MASK smfif_table[] = { #define SMFIM_EOM 5 /* macros for end-of-message */ #define SMFIM_EOH 6 /* macros for end-of-header */ -static NAME_CODE smfim_table[] = { +static const NAME_CODE smfim_table[] = { "SMFIM_CONNECT", SMFIM_CONNECT, "SMFIM_HELO", SMFIM_HELO, "SMFIM_ENVFROM", SMFIM_ENVFROM, @@ -318,10 +318,10 @@ static NAME_CODE smfim_table[] = { }; /* - * Mapping from external macro set numbers to our internal MILTERS structure - * members, without using a switch statement. + * Mapping from external macro set numbers to our internal MILTER_MACROS + * structure members, without using an array or switch statement. */ -static size_t milter8_macro_offsets[] = { +static const size_t milter8_macro_offsets[] = { offsetof(MILTER_MACROS, conn_macros), /* SMFIM_CONNECT */ offsetof(MILTER_MACROS, helo_macros), /* SMFIM_HELO */ offsetof(MILTER_MACROS, mail_macros), /* SMFIM_ENVFROM */ @@ -445,7 +445,7 @@ typedef struct { * XXX Is this still needed? Sendmail 8.14 provides a proper way to negotiate * what replies the mail filter will send. */ -static NAME_CODE milter8_event_masks[] = { +static const NAME_CODE milter8_event_masks[] = { "2", MILTER8_V2_PROTO_MASK, "3", MILTER8_V3_PROTO_MASK, "4", MILTER8_V4_PROTO_MASK, @@ -460,7 +460,7 @@ static NAME_CODE milter8_event_masks[] = { * protocol extensions such as "no_header_reply", and require that exactly * one version number is specified. */ -static NAME_CODE milter8_versions[] = { +static const NAME_CODE milter8_versions[] = { "2", 2, "3", 3, "4", 4, @@ -1750,8 +1750,7 @@ static void milter8_connect(MILTER8 *milter) msg_info("override %s macro list with \"%s\"", smfim_name, STR(buf)); mac_value_ptr = MILTER8_MACRO_PTR(milter->m.macros, mac_type); - if (*mac_value_ptr != 0) - myfree(*mac_value_ptr); + myfree(*mac_value_ptr); *mac_value_ptr = mystrdup(STR(buf)); } } @@ -2536,7 +2535,7 @@ static int milter8_send(MILTER *m, VSTREAM *stream) } static MILTER8 *milter8_alloc(const char *, int, int, int, const char *, - const char *, MILTERS *); + const char *, MILTERS *); /* milter8_receive - receive milter instance */ @@ -2712,7 +2711,7 @@ MILTER *milter8_create(const char *name, int conn_timeout, int cmd_timeout, * Fill in the structure. */ milter = milter8_alloc(name, conn_timeout, cmd_timeout, msg_timeout, - protocol, def_action, parent); + protocol, def_action, parent); /* * XXX Sendmail 8 libmilter closes the MTA-to-filter socket when it finds diff --git a/postfix/src/milter/milter_macros.c b/postfix/src/milter/milter_macros.c index db5c36db9..b62f32be7 100644 --- a/postfix/src/milter/milter_macros.c +++ b/postfix/src/milter/milter_macros.c @@ -38,47 +38,52 @@ /* void *ptr; /* DESCRIPTION /* Sendmail mail filter (Milter) applications receive sets of -/* macro (name=value) pairs with each SMTP or content event. -/* In Postfix, the lists of names are stored in MILTER_MACROS -/* structures. By default, the same structure is shared by all -/* Milter applications; it is initialized with information -/* from main.cf. With Sendmail 8.14 a Milter can override one -/* or more lists of macro names, and individual filters may -/* have their own partial list. +/* macro name=value pairs with each SMTP or content event. +/* In Postfix, these macro names are stored in MILTER_MACROS +/* structures, as one list for each event type. By default, +/* the same structure is shared by all Milter applications; +/* it is initialized with information from main.cf. With +/* Sendmail 8.14 a Milter can override one or more lists of +/* macro names. Postfix implements this by giving the Milter +/* its own MILTER_MACROS structure and by storing the per-Milter +/* information there. /* -/* This module maintains the macro name lists as mystrdup()'ed -/* values. The user is explicitly allowed to update these -/* values directly, as long as they respect the mystrdup() -/* interface. +/* This module maintains per-event macro name lists as +/* mystrdup()'ed values. The user is explicitly allowed to +/* update these values directly, as long as the result is +/* compatible with mystrdup(). /* /* milter_macros_create() creates a MILTER_MACROS structure /* and initializes it with copies of its string arguments. +/* Null pointers are not valid as input. /* -/* milter_macros_alloc() creates a MILTER_MACROS structure +/* milter_macros_alloc() creates am empty MILTER_MACROS structure /* that is initialized according to its init_mode argument. /* .IP MILTER_MACROS_ALLOC_ZERO -/* Initialize all members as null pointers. This mode is -/* recommended for applications that use milter_macros_scan(). +/* Initialize all structure members as null pointers. This +/* mode must be used with milter_macros_scan(), because that +/* function blindly overwrites all structure members. No other +/* function except milter_macros_free() allows structure members +/* with null pointer values. /* .IP MILTER_MACROS_ALLOC_EMPTY -/* Initialize all members with mystrdup(""). This is not as -/* expensive as it appears to be. This mode is recommend for -/* applications that update individual MILTER_MACROS members -/* directly. +/* Initialize all structure members with mystrdup(""). This +/* is not as expensive as it appears to be. /* .PP /* milter_macros_free() destroys a MILTER_MACROS structure and /* frees any strings referenced by it. /* /* milter_macros_print() writes the contents of a MILTER_MACROS /* structure to the named stream using the specified attribute -/* print routine. milter_macros_print() is meant to be passed +/* print routine. milter_macros_print() is meant to be passed /* as a call-back to attr_print*(), thusly: /* /* ATTR_TYPE_FUNC, milter_macros_print, (void *) macros, /* /* milter_macros_scan() reads a MILTER_MACROS structure from /* the named stream using the specified attribute scan routine. -/* milter_macros_scan() is meant to be passed as a call-back -/* to attr_scan*(), thusly: +/* No attempt is made to free the memory of existing structure +/* members. milter_macros_scan() is meant to be passed as a +/* call-back to attr_scan*(), thusly: /* /* ATTR_TYPE_FUNC, milter_macros_scan, (void *) macros, /* DIAGNOSTICS @@ -121,7 +126,7 @@ #define MAIL_ATTR_MILT_MAC_EOD "eod_macros" #define MAIL_ATTR_MILT_MAC_UNK "unk_macros" -/* milter_macros_print - write recipient to stream */ +/* milter_macros_print - write macros structure to stream */ int milter_macros_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp, int flags, void *ptr) @@ -146,13 +151,17 @@ int milter_macros_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp, return (ret); } -/* milter_macros_scan - receive milter macro name list */ +/* milter_macros_scan - receive macros structure from stream */ int milter_macros_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp, int flags, void *ptr) { MILTER_MACROS *mp = (MILTER_MACROS *) ptr; int ret; + + /* + * We could simplify this by moving memory allocation into attr_scan*(). + */ VSTRING *conn_macros = vstring_alloc(10); VSTRING *helo_macros = vstring_alloc(10); VSTRING *mail_macros = vstring_alloc(10); @@ -218,12 +227,28 @@ MILTER_MACROS *milter_macros_create(const char *conn_macros, return (mp); } -/* milter_macros_alloc - allocate memory for structure with simple initialization */ +/* milter_macros_alloc - allocate macros structure with simple initialization */ MILTER_MACROS *milter_macros_alloc(int mode) { MILTER_MACROS *mp; + /* + * This macro was originally in milter.h, but no-one else needed it. + */ +#define milter_macros_init(mp, expr) do { \ + MILTER_MACROS *__mp = (mp); \ + char *__expr = (expr); \ + __mp->conn_macros = __expr; \ + __mp->helo_macros = __expr; \ + __mp->mail_macros = __expr; \ + __mp->rcpt_macros = __expr; \ + __mp->data_macros = __expr; \ + __mp->eoh_macros = __expr; \ + __mp->eod_macros = __expr; \ + __mp->unk_macros = __expr; \ + } while (0) + mp = (MILTER_MACROS *) mymalloc(sizeof(*mp)); switch (mode) { case MILTER_MACROS_ALLOC_ZERO: @@ -242,6 +267,30 @@ MILTER_MACROS *milter_macros_alloc(int mode) void milter_macros_free(MILTER_MACROS *mp) { + + /* + * This macro was originally in milter.h, but no-one else needed it. + */ +#define milter_macros_wipe(mp) do { \ + MILTER_MACROS *__mp = mp; \ + if (__mp->conn_macros) \ + myfree(__mp->conn_macros); \ + if (__mp->helo_macros) \ + myfree(__mp->helo_macros); \ + if (__mp->mail_macros) \ + myfree(__mp->mail_macros); \ + if (__mp->rcpt_macros) \ + myfree(__mp->rcpt_macros); \ + if (__mp->data_macros) \ + myfree(__mp->data_macros); \ + if (__mp->eoh_macros) \ + myfree(__mp->eoh_macros); \ + if (__mp->eod_macros) \ + myfree(__mp->eod_macros); \ + if (__mp->unk_macros) \ + myfree(__mp->unk_macros); \ + } while (0) + milter_macros_wipe(mp); myfree((char *) mp); } diff --git a/postfix/src/milter/test-milter.c b/postfix/src/milter/test-milter.c index c13f6be67..cc65212da 100644 --- a/postfix/src/milter/test-milter.c +++ b/postfix/src/milter/test-milter.c @@ -18,7 +18,7 @@ /* Arguments (multiple alternatives are separated by "\fB|\fR"): /* .IP "\fB-a accept|tempfail|reject|discard|skip|\fIddd x.y.z text\fR" /* Specifies a non-default reply for the MTA command specified -/* with \fB-a\fR. The default is \fBtempfail\fR. +/* with \fB-c\fR. The default is \fBtempfail\fR. /* .IP "\fB-d\fI level\fR" /* Enable libmilter debugging at the specified level. /* .IP "\fB-c connect|helo|mail|rcpt|data|header|eoh|body|eom|unknown|close|abort\fR" @@ -28,6 +28,9 @@ /* Terminate after \fIcount\fR connections. /* .IP "\fB-i \fI'index header-label header-value'\fR" /* Insert header at specified position. +/* .IP "\fB-l\fR" +/* Header values include leading space. Specify this option +/* before \fB-i\fR or \fB-r\fR. /* .IP "\fB-m connect|helo|mail|rcpt|data|eoh|eom\fR" /* The protocol stage that receives the list of macros specified /* with \fB-M\fR. The default protocol stage is \fBconnect\fR. @@ -100,7 +103,7 @@ struct command_map { int *reply; }; -static struct command_map command_map[] = { +static const struct command_map command_map[] = { "connect", &test_connect_reply, "helo", &test_helo_reply, "mail", &test_mail_reply, @@ -387,7 +390,7 @@ struct noproto_map { FILTER_ACTION *action; }; -static struct noproto_map noproto_map[] = { +static const struct noproto_map noproto_map[] = { "connect", SMFIP_NOCONNECT, SMFIP_NR_CONN, &test_connect_reply, &smfilter.xxfi_connect, "helo", SMFIP_NOHELO, SMFIP_NR_HELO, &test_helo_reply, &smfilter.xxfi_helo, "mail", SMFIP_NOMAIL, SMFIP_NR_MAIL, &test_mail_reply, &smfilter.xxfi_envfrom, @@ -402,6 +405,7 @@ static struct noproto_map noproto_map[] = { static int nosend_mask; static int noreply_mask; +static int misc_mask; static sfsistat test_negotiate(SMFICTX *ctx, unsigned long f0, @@ -420,10 +424,10 @@ static sfsistat test_negotiate(SMFICTX *ctx, smfi_setsymlist(ctx, set_macro_state, set_macro_list); } if (verbose) - printf("negotiate f0=%lx *pf0 = %lx f1=%lx *pf1=%lx nosend=%lx noreply=%lx\n", - f0, *pf0, f1, *pf1, (long) nosend_mask, (long) noreply_mask); + printf("negotiate f0=%lx *pf0 = %lx f1=%lx *pf1=%lx nosend=%lx noreply=%lx misc=%lx\n", + f0, *pf0, f1, *pf1, (long) nosend_mask, (long) noreply_mask, (long) misc_mask); *pf0 = f0; - *pf1 = f1 & (nosend_mask | noreply_mask); + *pf1 = f1 & (nosend_mask | noreply_mask | misc_mask); return (SMFIS_CONTINUE); } @@ -439,7 +443,9 @@ static void parse_hdr_info(const char *optarg, int *idx, fprintf(stderr, "out of memory\n"); exit(1); } - if (sscanf(optarg, "%d %s %[^\n]", idx, *hdr, *value) != 3) { + if ((misc_mask & SMFIP_HDR_LEADSPC) == 0 ? + sscanf(optarg, "%d %s %[^\n]", idx, *hdr, *value) != 3 : + sscanf(optarg, "%d %[^ ]%[^\n]", idx, *hdr, *value) != 3) { fprintf(stderr, "bad header info: %s\n", optarg); exit(1); } @@ -449,16 +455,16 @@ int main(int argc, char **argv) { char *action = 0; char *command = 0; - struct command_map *cp; + const struct command_map *cp; int ch; int code; const char **cpp; char *set_macro_state_arg = 0; char *nosend = 0; char *noreply = 0; - struct noproto_map *np; + const struct noproto_map *np; - while ((ch = getopt(argc, argv, "a:c:C:d:i:m:M:n:N:p:r:R:v")) > 0) { + while ((ch = getopt(argc, argv, "a:c:C:d:i:lm:M:n:N:p:r:R:v")) > 0) { switch (ch) { case 'a': action = optarg; @@ -482,6 +488,18 @@ int main(int argc, char **argv) #else fprintf(stderr, "no libmilter support to insert header\n"); exit(1); +#endif + break; + case 'l': +#if SMFI_VERSION > 5 + if (ins_hdr || chg_hdr) { + fprintf(stderr, "specify -l before -i or -r\n"); + exit(1); + } + misc_mask |= SMFIP_HDR_LEADSPC; +#else + fprintf(stderr, "no libmilter support for leading space\n"); + exit(1); #endif break; case 'm': @@ -493,6 +511,7 @@ int main(int argc, char **argv) set_macro_state_arg = optarg; #else fprintf(stderr, "no libmilter support to specify macro list\n"); + exit(1); #endif break; case 'M': diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 16e550b46..231fe99f3 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -211,7 +211,7 @@ /* filter) applications after an unknown SMTP command. /* .IP "\fBmilter_end_of_header_macros (see postconf -n output)\fR" /* The macros that are sent to Milter (mail filter) applications -/* after the message header. +/* after the end of the message header. /* .IP "\fBmilter_end_of_data_macros (see postconf -n output)\fR" /* The macros that are sent to Milter (mail filter) applications /* after the message end-of-data. @@ -1654,6 +1654,11 @@ static int mail_open_stream(SMTPD_STATE *state) * XXX Send Milter information first, because this will hang when cleanup * goes into "throw away" mode. Also, cleanup needs to know early on * whether or not it has to do its own SMTP event emulation. + * + * XXX At this point we send only dummy information to keep the cleanup + * server from using its non_smtpd_milters settings. We have to send + * up-to-date Milter information after DATA so that the cleanup server + * knows the actual Milter state. */ if (state->dest) { state->cleanup = state->dest->stream; diff --git a/postfix/src/util/name_code.c b/postfix/src/util/name_code.c index dce373bbb..0fd9f99cb 100644 --- a/postfix/src/util/name_code.c +++ b/postfix/src/util/name_code.c @@ -14,12 +14,12 @@ /* } NAME_CODE; /* /* int name_code(table, flags, name) -/* NAME_CODE *table; +/* const NAME_CODE *table; /* int flags; /* const char *name; /* /* const char *str_name_code(table, code) -/* NAME_CODE *table; +/* const NAME_CODE *table; /* int code; /* DESCRIPTION /* This module does simple name<->number mapping. The process @@ -66,9 +66,9 @@ /* name_code - look up code by name */ -int name_code(NAME_CODE *table, int flags, const char *name) +int name_code(const NAME_CODE *table, int flags, const char *name) { - NAME_CODE *np; + const NAME_CODE *np; int (*lookup) (const char *, const char *); if (flags & NAME_CODE_FLAG_STRICT_CASE) @@ -84,9 +84,9 @@ int name_code(NAME_CODE *table, int flags, const char *name) /* str_name_code - look up name by code */ -const char *str_name_code(NAME_CODE *table, int code) +const char *str_name_code(const NAME_CODE *table, int code) { - NAME_CODE *np; + const NAME_CODE *np; for (np = table; np->name; np++) if (code == np->code) diff --git a/postfix/src/util/name_code.h b/postfix/src/util/name_code.h index dd251b7aa..e08618d46 100644 --- a/postfix/src/util/name_code.h +++ b/postfix/src/util/name_code.h @@ -22,8 +22,8 @@ typedef struct { #define NAME_CODE_FLAG_NONE 0 #define NAME_CODE_FLAG_STRICT_CASE (1<<0) -extern int name_code(NAME_CODE *, int, const char *); -extern const char *str_name_code(NAME_CODE *, int); +extern int name_code(const NAME_CODE *, int, const char *); +extern const char *str_name_code(const NAME_CODE *, int); /* LICENSE /* .ad diff --git a/postfix/src/util/name_mask.c b/postfix/src/util/name_mask.c index bee3735f4..9565461db 100644 --- a/postfix/src/util/name_mask.c +++ b/postfix/src/util/name_mask.c @@ -8,23 +8,23 @@ /* /* int name_mask(context, table, names) /* const char *context; -/* NAME_MASK *table; +/* const NAME_MASK *table; /* const char *names; /* /* const char *str_name_mask(context, table, mask) /* const char *context; -/* NAME_MASK *table; +/* const NAME_MASK *table; /* int mask; /* /* int name_mask_opt(context, table, names, flags) /* const char *context; -/* NAME_MASK *table; +/* const NAME_MASK *table; /* const char *names; /* int flags; /* /* int name_mask_delim_opt(context, table, names, delim, flags) /* const char *context; -/* NAME_MASK *table; +/* const NAME_MASK *table; /* const char *names; /* const char *delim; /* int flags; @@ -32,7 +32,7 @@ /* const char *str_name_mask_opt(buf, context, table, mask, flags) /* VSTRING *buf; /* const char *context; -/* NAME_MASK *table; +/* const NAME_MASK *table; /* int mask; /* int flags; /* DESCRIPTION @@ -129,14 +129,14 @@ /* name_mask_delim_opt - compute mask corresponding to list of names */ -int name_mask_delim_opt(const char *context, NAME_MASK *table, +int name_mask_delim_opt(const char *context, const NAME_MASK *table, const char *names, const char *delim, int flags) { const char *myname = "name_mask"; char *saved_names = mystrdup(names); char *bp = saved_names; int result = 0; - NAME_MASK *np; + const NAME_MASK *np; char *name; int (*lookup) (const char *, const char *); @@ -177,11 +177,11 @@ int name_mask_delim_opt(const char *context, NAME_MASK *table, /* str_name_mask_opt - mask to string */ const char *str_name_mask_opt(VSTRING *buf, const char *context, - NAME_MASK *table, + const NAME_MASK *table, int mask, int flags) { const char *myname = "name_mask"; - NAME_MASK *np; + const NAME_MASK *np; int len; static VSTRING *my_buf = 0; int delim = (flags & NAME_MASK_COMMA ? ',' : @@ -230,7 +230,7 @@ const char *str_name_mask_opt(VSTRING *buf, const char *context, int main(int argc, char **argv) { - static NAME_MASK table[] = { + static const NAME_MASK table[] = { "zero", 1 << 0, "one", 1 << 1, "two", 1 << 2, diff --git a/postfix/src/util/name_mask.h b/postfix/src/util/name_mask.h index 69631d38e..91df83f79 100644 --- a/postfix/src/util/name_mask.h +++ b/postfix/src/util/name_mask.h @@ -45,8 +45,8 @@ typedef struct { #define str_name_mask(tag, table, mask) \ str_name_mask_opt(((VSTRING *) 0), (tag), (table), (mask), NAME_MASK_DEFAULT) -extern int name_mask_delim_opt(const char *, NAME_MASK *, const char *, const char *, int); -extern const char *str_name_mask_opt(VSTRING *, const char *, NAME_MASK *, int, int); +extern int name_mask_delim_opt(const char *, const NAME_MASK *, const char *, const char *, int); +extern const char *str_name_mask_opt(VSTRING *, const char *, const NAME_MASK *, int, int); /* LICENSE /* .ad