diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 3f054f2ed..736227a07 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -1,4 +1,4 @@ --TABOUNCE +-TABOUNCE_STATE -TADDR_MATCH_LIST -TADDR_PATTERN -TALIAS_TOKEN diff --git a/postfix/HISTORY b/postfix/HISTORY index edede8a04..408c9ce38 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -25057,6 +25057,8 @@ Apologies for any names omitted. mantools/man2html, mantools/readme2html, proto/*_README.html, proto/INSTALL.html, proto/postconf.html.prolog, html/index.html. +20200830 + Refactor: moved the SASL mechanism filter code from the Postfix SMTP client to a library module, so that it can be reused in the Postfix SMTP server. Files: smtp/smtp_sasl_proto.c, @@ -25071,3 +25073,83 @@ Apologies for any names omitted. wants to anounce EXTERNAL support for which Postfix support does not exist. Files: smtpd/smtpd.[hc], smtpd_sasl_glue.[hc], global/mail_params.h, proto/postconf.proto, mantools/postlink. + +20200906 + + Cleanup: missing file. File: src/postqueue/.indent.pro. + + Cleanup: uninitialized value in unit test code. File: + global/haproxy_srvr.c. + + Cleanup: duplicate 'const' in argument declaration. File: + src/global/sasl_mech_filter.c. + +20200906-18 + + Baseline is postfix-3.6-20200906. + + Other debt: internal protocol identification. Each server + sends the name of the internal protocol that it implements, + and each client logs a warning if it receives the wrong + protocol name. With this, a client-server mismatch results + in a better error message. It is a good idea to "postfix + stop" before updating, or before backing out to an earlier + relase. To make this work consistently, a few internal + protocols were converted from "client speaks first" to + "server speaks first". Files: anvil/anvil.c, bounce/bounce.c, + cleanup/cleanup.c, flush/flush.c, global/abounce.c, + global/anvil_clnt.c, global/bounce.c, global/clnt_stream.c, + global/clnt_stream.h, global/defer.c, global/deliver_pass.c, + global/deliver_request.c, global/dict_proxy.c, global/flush_clnt.c, + global/mail_command_client.c, global/mail_proto.h, + global/mail_stream.c, global/mail_version.h, global/post_mail.c, + global/resolve_clnt.c, global/rewrite_clnt.c, global/scache_clnt.c, + global/trace.c, global/verify_clnt.c, local/forward.c, + master/event_server.c, master/mail_server.h, master/multi_server.c, + oqmgr/qmgr_deliver.c, pickup/pickup.c, postdrop/postdrop.c, + postqueue/postqueue.c, postscreen/postscreen_starttls.c, + proxymap/proxymap.c, qmgr/qmgr_deliver.c, scache/scache.c, + showq/showq.c, tls/tls_mgr.c, tls/tls_proxy_clnt.c, + tlsmgr/tlsmgr.c, tlsproxy/tlsproxy.c, + trivial-rewrite/trivial-rewrite.c, util/attr.h, util/attr_clnt.c, + util/attr_clnt.h, util/attr_print0.c, util/attr_print64.c, + util/attr_print_plain.c, util/attr_scan0.c, util/attr_scan64.c, + util/attr_scan_plain.c, util/auto_clnt.c, util/auto_clnt.h, + verify/verify.c. + + Debt: during the conversion of some internal protocols to + "server speaks first", took the opportunity to improve how + event-driven client implementations handle a server that + is locked up. Files: global/abounce.c, + postscreen/postscreen_starttls.c. + +20200919 + + Cleanup: eliminated a silly optimization for lazy clients + that read the "server speaks first" protocol announcement + after sending a client request. Files: src/anvil/anvil.c, + src/bounce/bounce.c, src/flush/flush.c, src/global/abounce.c, + src/global/anvil_clnt.c, src/global/deliver_pass.c, + src/global/deliver_request.c, src/global/dict_proxy.c, + src/global/mail_command_client.c, src/global/mail_stream.c, + src/global/resolve_clnt.c, src/global/rewrite_clnt.c, + src/global/scache_clnt.c, src/global/verify_clnt.c, + src/local/forward.c, src/oqmgr/qmgr_deliver.c, src/pickup/pickup.c, + src/postqueue/postqueue.c, src/postscreen/postscreen_starttls.c, + src/proxymap/proxymap.c, src/qmgr/qmgr_deliver.c, + src/scache/scache.c, src/showq/showq.c, src/tlsmgr/tlsmgr.c, + src/tlsproxy/tlsproxy.c, src/tls/tls_mgr.c, + src/tls/tls_proxy_clnt.c, src/trivial-rewrite/trivial-rewrite.c, + src/verify/verify.c. + + Cleanup: factored out some duplicate showq client code. + File: postqueue/postqueue.c. + +20200920 + + Cleanup: deleted the percentm module. It was obsoleted in + 19971027 by the vbuf_print() string formatter for VSTREAM + and VSTRING objects. Files: util/percentm.[hc]. + + Cleanup: replaced hard-coded 'private' with named constant. + File: global/scache_clnt.c. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index a6576c3b9..f9ce0ef5c 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -25,6 +25,22 @@ more recent Eclipse Public License 2.0. Recipients can choose to take the software under the license of their choice. Those who are more comfortable with the IPL can continue with that license. +Incompatible change with snapshot 20200920 +========================================== + +Internal protocols have changed. You need to "postfix stop" before +updating, or before backing out to an earlier release, otherwise +long-running daemons (pickup, qmgr, verify, tlsproxy, postscreen) +may fail to communicate with the rest of Postfix (warnings, timeouts). + +The purpose of this change is to produce better error messages, for +example, when someone configures the discard daemon as a bounce +service in master.cf, or vice versa. + +This change will break third-party code that implements a +Postfix-internal protocol such as qpsmtpd. Programs that depend on +Postfix internal details are not supported. + Incompatible change with snapshot 20200705 ========================================== diff --git a/postfix/WISHLIST b/postfix/WISHLIST index 8707e5e29..b2eff8711 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -1,5 +1,23 @@ Wish list: + Does tlsproxy terminate to soon after 'postfix reload'? + + The documented order of relay/recipient restrictions differs + from the implementation. This may need a new compatibility + parameter. For example: + http://postfix.1071664.n5.nabble.com/Relay-attempt-questions-td103646.html + + Hardening the half-dane behavior: some sites may rely on + current behavior which allows original MX domain name for + certificate matches. Requires a new (compatibility) parameter + setting? + + multi_server applications could be migrated to event_server; + after accept(), they would have to set up their own read + event callback for handling requests. + + Maybe expand %m to "application error" when errno == 0. + smtp_sasl_tls_security_options = noanonymous, and make smtp_sasl_security_options default dependent on the smtp_sasl_tls_security_options default (i.e. reverse the diff --git a/postfix/html/cleanup.8.html b/postfix/html/cleanup.8.html index f7f2efdc9..3d0039413 100644 --- a/postfix/html/cleanup.8.html +++ b/postfix/html/cleanup.8.html @@ -162,11 +162,12 @@ CLEANUP(8) CLEANUP(8) Postfix 2.6 the default protocol is 2. milter_default_action (tempfail) - The default action when a Milter (mail filter) application is - unavailable or mis-configured. + The default action when a Milter (mail filter) response is + unavailable (for example, bad Postfix configuration or Milter + failure). milter_macro_daemon_name ($myhostname) - The {daemon_name} macro value for Milter (mail filter) applica- + The {daemon_name} macro value for Milter (mail filter) applica- tions. milter_macro_v ($mail_name $mail_version) @@ -177,45 +178,45 @@ CLEANUP(8) CLEANUP(8) tion, and for negotiating protocol options. milter_command_timeout (30s) - The time limit for sending an SMTP command to a Milter (mail + The time limit for sending an SMTP command to a Milter (mail filter) application, and for receiving the response. milter_content_timeout (300s) - The time limit for sending message content to a Milter (mail + The time limit for sending message content to a Milter (mail filter) application, and for receiving the response. milter_connect_macros (see 'postconf -d' output) - The macros that are sent to Milter (mail filter) applications + The macros that are sent to Milter (mail filter) applications after completion of an SMTP connection. milter_helo_macros (see 'postconf -d' output) - The macros that are sent to Milter (mail filter) applications + The macros that are sent to Milter (mail filter) applications after the SMTP HELO or EHLO command. milter_mail_macros (see 'postconf -d' output) - The macros that are sent to Milter (mail filter) applications + The macros that are sent to Milter (mail filter) applications after the SMTP MAIL FROM command. milter_rcpt_macros (see 'postconf -d' output) - The macros that are sent to Milter (mail filter) applications + The macros that are sent to Milter (mail filter) applications after the SMTP RCPT TO command. milter_data_macros (see 'postconf -d' output) - The macros that are sent to version 4 or higher Milter (mail + The macros that are sent to version 4 or higher Milter (mail filter) applications after the SMTP DATA command. milter_unknown_command_macros (see 'postconf -d' output) - The macros that are sent to version 3 or higher Milter (mail + The macros that are sent to version 3 or higher Milter (mail filter) applications after an unknown SMTP command. milter_end_of_data_macros (see 'postconf -d' output) - The macros that are sent to Milter (mail filter) applications + The macros that are sent to Milter (mail filter) applications after the message end-of-data. Available in Postfix version 2.5 and later: milter_end_of_header_macros (see 'postconf -d' output) - The macros that are sent to Milter (mail filter) applications + The macros that are sent to Milter (mail filter) applications after the end of the message header. Available in Postfix version 2.7 and later: @@ -227,8 +228,8 @@ CLEANUP(8) CLEANUP(8) Available in Postfix version 3.1 and later: milter_macro_defaults (empty) - Optional list of name=value pairs that specify default values - for arbitrary macros that Postfix may send to Milter applica- + Optional list of name=value pairs that specify default values + for arbitrary macros that Postfix may send to Milter applica- tions. MIME PROCESSING CONTROLS @@ -254,91 +255,91 @@ CLEANUP(8) CLEANUP(8) ing information. strict_mime_encoding_domain (no) - Reject mail with invalid Content-Transfer-Encoding: information + Reject mail with invalid Content-Transfer-Encoding: information for the message/* or multipart/* MIME content types. Available in Postfix version 2.5 and later: detect_8bit_encoding_header (yes) - Automatically detect 8BITMIME body content by looking at Con- - tent-Transfer-Encoding: message headers; historically, this + Automatically detect 8BITMIME body content by looking at Con- + tent-Transfer-Encoding: message headers; historically, this behavior was hard-coded to be "always on". AUTOMATIC BCC RECIPIENT CONTROLS - Postfix can automatically add BCC (blind carbon copy) when mail enters + Postfix can automatically add BCC (blind carbon copy) when mail enters the mail system: always_bcc (empty) - Optional address that receives a "blind carbon copy" of each + Optional address that receives a "blind carbon copy" of each message that is received by the Postfix mail system. Available in Postfix version 2.1 and later: sender_bcc_maps (empty) - Optional BCC (blind carbon-copy) address lookup tables, indexed + Optional BCC (blind carbon-copy) address lookup tables, indexed by sender address. recipient_bcc_maps (empty) - Optional BCC (blind carbon-copy) address lookup tables, indexed + Optional BCC (blind carbon-copy) address lookup tables, indexed by recipient address. ADDRESS TRANSFORMATION CONTROLS - Address rewriting is delegated to the trivial-rewrite(8) daemon. The + Address rewriting is delegated to the trivial-rewrite(8) daemon. The cleanup(8) server implements table driven address mapping. empty_address_recipient (MAILER-DAEMON) The recipient of mail addressed to the null address. canonical_maps (empty) - Optional address mapping lookup tables for message headers and + Optional address mapping lookup tables for message headers and envelopes. recipient_canonical_maps (empty) - Optional address mapping lookup tables for envelope and header + Optional address mapping lookup tables for envelope and header recipient addresses. sender_canonical_maps (empty) - Optional address mapping lookup tables for envelope and header + Optional address mapping lookup tables for envelope and header sender addresses. masquerade_classes (envelope_sender, header_sender, header_recipient) What addresses are subject to address masquerading. masquerade_domains (empty) - Optional list of domains whose subdomain structure will be + Optional list of domains whose subdomain structure will be stripped off in email addresses. masquerade_exceptions (empty) - Optional list of user names that are not subjected to address - masquerading, even when their addresses match $masquer- + Optional list of user names that are not subjected to address + masquerading, even when their addresses match $masquer- ade_domains. propagate_unmatched_extensions (canonical, virtual) - What address lookup tables copy an address extension from the + What address lookup tables copy an address extension from the lookup key to the lookup result. Available before Postfix version 2.0: virtual_maps (empty) - Optional lookup tables with a) names of domains for which all - addresses are aliased to addresses in other local or remote + Optional lookup tables with a) names of domains for which all + addresses are aliased to addresses in other local or remote domains, and b) addresses that are aliased to addresses in other local or remote domains. Available in Postfix version 2.0 and later: virtual_alias_maps ($virtual_maps) - Optional lookup tables that alias specific mail addresses or + Optional lookup tables that alias specific mail addresses or domains to other local or remote address. Available in Postfix version 2.2 and later: - canonical_classes (envelope_sender, envelope_recipient, header_sender, + canonical_classes (envelope_sender, envelope_recipient, header_sender, header_recipient) What addresses are subject to canonical_maps address mapping. recipient_canonical_classes (envelope_recipient, header_recipient) - What addresses are subject to recipient_canonical_maps address + What addresses are subject to recipient_canonical_maps address mapping. sender_canonical_classes (envelope_sender, header_sender) @@ -346,8 +347,8 @@ CLEANUP(8) CLEANUP(8) ping. remote_header_rewrite_domain (empty) - Don't rewrite message headers from remote clients at all when - this parameter is empty; otherwise, rewrite message headers and + Don't rewrite message headers from remote clients at all when + this parameter is empty; otherwise, rewrite message headers and append the specified domain name to incomplete addresses. RESOURCE AND RATE CONTROLS @@ -357,7 +358,7 @@ CLEANUP(8) CLEANUP(8) showq(8) queue displays. header_size_limit (102400) - The maximal amount of memory in bytes for storing a message + The maximal amount of memory in bytes for storing a message header. hopcount_limit (50) @@ -365,17 +366,17 @@ CLEANUP(8) CLEANUP(8) in the primary message headers. in_flow_delay (1s) - Time to pause before accepting a new message, when the message + Time to pause before accepting a new message, when the message arrival rate exceeds the message delivery rate. message_size_limit (10240000) - The maximal size in bytes of a message, including envelope + The maximal size in bytes of a message, including envelope information. Available in Postfix version 2.0 and later: header_address_token_limit (10240) - The maximal number of address tokens are allowed in an address + The maximal number of address tokens are allowed in an address message header. mime_boundary_length_limit (2048) @@ -391,7 +392,7 @@ CLEANUP(8) CLEANUP(8) Available in Postfix version 2.1 and later: virtual_alias_expansion_limit (1000) - The maximal number of addresses that virtual alias expansion + The maximal number of addresses that virtual alias expansion produces from each original recipient. virtual_alias_recursion_limit (1000) @@ -400,50 +401,50 @@ CLEANUP(8) CLEANUP(8) Available in Postfix version 3.0 and later: virtual_alias_address_length_limit (1000) - The maximal length of an email address after virtual alias + The maximal length of an email address after virtual alias expansion. SMTPUTF8 CONTROLS Preliminary SMTPUTF8 support is introduced with Postfix 3.0. smtputf8_enable (yes) - Enable preliminary SMTPUTF8 support for the protocols described + Enable preliminary SMTPUTF8 support for the protocols described in RFC 6531..6533. smtputf8_autodetect_classes (sendmail, verify) - Detect that a message requires SMTPUTF8 support for the speci- + Detect that a message requires SMTPUTF8 support for the speci- fied mail origin classes. Available in Postfix version 3.2 and later: enable_idna2003_compatibility (no) - Enable 'transitional' compatibility between IDNA2003 and - IDNA2008, when converting UTF-8 domain names to/from the ASCII + Enable 'transitional' compatibility between IDNA2003 and + IDNA2008, when converting UTF-8 domain names to/from the ASCII form that is used for DNS lookups. MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con- figuration files. daemon_timeout (18000s) - How much time a Postfix daemon process may take to handle a + How much time a Postfix daemon process may take to handle a request before it is terminated by a built-in watchdog timer. delay_logging_resolution_limit (2) - The maximal number of digits after the decimal point when log- + The maximal number of digits after the decimal point when log- ging sub-second delay values. delay_warning_time (0h) - The time after which the sender receives a copy of the message + The time after which the sender receives a copy of the message headers of mail that is still queued. ipc_timeout (3600s) - The time limit for sending or receiving information over an + The time limit for sending or receiving information over an internal communication channel. max_idle (100s) - The maximum amount of time that an idle Postfix daemon process + The maximum amount of time that an idle Postfix daemon process waits for an incoming connection before terminating voluntarily. max_use (100) @@ -454,7 +455,7 @@ CLEANUP(8) CLEANUP(8) The internet hostname of this mail system. myorigin ($myhostname) - The domain name that locally-posted mail appears to come from, + The domain name that locally-posted mail appears to come from, and that locally posted mail is delivered to. process_id (read-only) @@ -467,21 +468,21 @@ CLEANUP(8) CLEANUP(8) The location of the Postfix top-level queue directory. soft_bounce (no) - Safety net to keep mail queued that would otherwise be returned + Safety net to keep mail queued that would otherwise be returned to the sender. syslog_facility (mail) The syslog facility of Postfix logging. syslog_name (see 'postconf -d' output) - A prefix that is prepended to the process name in syslog + A prefix that is prepended to the process name in syslog records, so that, for example, "smtpd" becomes "prefix/smtpd". Available in Postfix version 2.1 and later: enable_original_recipient (yes) - Enable support for the original recipient address after an - address is rewritten to a different address (for example with + Enable support for the original recipient address after an + address is rewritten to a different address (for example with aliasing or with canonical mapping). Available in Postfix 3.3 and later: @@ -492,7 +493,7 @@ CLEANUP(8) CLEANUP(8) Available in Postfix 3.5 and later: info_log_address_format (external) - The email address form that will be used in non-debug logging + The email address form that will be used in non-debug logging (info, warning, etc.). FILES diff --git a/postfix/html/trivial-rewrite.8.html b/postfix/html/trivial-rewrite.8.html index b6b044155..bf166d3f1 100644 --- a/postfix/html/trivial-rewrite.8.html +++ b/postfix/html/trivial-rewrite.8.html @@ -169,8 +169,8 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8) explicit ".example.com" pattern. relayhost (empty) - The next-hop destination of non-local mail; overrides non-local - domains in recipient addresses. + The next-hop destination(s) for non-local mail; overrides + non-local domains in recipient addresses. transport_maps (empty) Optional lookup tables with mappings from recipient address to diff --git a/postfix/man/man8/cleanup.8 b/postfix/man/man8/cleanup.8 index ed4e22bad..69a2940d6 100644 --- a/postfix/man/man8/cleanup.8 +++ b/postfix/man/man8/cleanup.8 @@ -164,8 +164,9 @@ The mail filter protocol version and optional protocol extensions for communication with a Milter application; prior to Postfix 2.6 the default protocol is 2. .IP "\fBmilter_default_action (tempfail)\fR" -The default action when a Milter (mail filter) application is -unavailable or mis\-configured. +The default action when a Milter (mail filter) response is +unavailable (for example, bad Postfix configuration or Milter +failure). .IP "\fBmilter_macro_daemon_name ($myhostname)\fR" The {daemon_name} macro value for Milter (mail filter) applications. .IP "\fBmilter_macro_v ($mail_name $mail_version)\fR" diff --git a/postfix/man/man8/trivial-rewrite.8 b/postfix/man/man8/trivial-rewrite.8 index 523c44c4e..6bbf7de1f 100644 --- a/postfix/man/man8/trivial-rewrite.8 +++ b/postfix/man/man8/trivial-rewrite.8 @@ -175,7 +175,7 @@ A list of Postfix features where the pattern "example.com" also matches subdomains of example.com, instead of requiring an explicit ".example.com" pattern. .IP "\fBrelayhost (empty)\fR" -The next\-hop destination of non\-local mail; overrides non\-local +The next\-hop destination(s) for non\-local mail; overrides non\-local domains in recipient addresses. .IP "\fBtransport_maps (empty)\fR" Optional lookup tables with mappings from recipient address to diff --git a/postfix/src/anvil/anvil.c b/postfix/src/anvil/anvil.c index d0a5b2a18..884be28b9 100644 --- a/postfix/src/anvil/anvil.c +++ b/postfix/src/anvil/anvil.c @@ -1006,6 +1006,21 @@ static void post_jail_init(char *unused_name, char **unused_argv) MAIL_VERSION_STAMP_DECLARE; +/* post_accept - announce our protocol */ + +static void post_accept(VSTREAM *stream, char *unused_name, + char **unused_argv, HTABLE *unused_table) +{ + + /* + * Announce the protocol. + */ + attr_print_plain(stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_ANVIL), + ATTR_TYPE_END); + (void) vstream_fflush(stream); +} + /* main - pass control to the multi-threaded skeleton */ int main(int argc, char **argv) @@ -1024,6 +1039,7 @@ int main(int argc, char **argv) multi_server_main(argc, argv, anvil_service, CA_MAIL_SERVER_TIME_TABLE(time_table), CA_MAIL_SERVER_POST_INIT(post_jail_init), + CA_MAIL_SERVER_POST_ACCEPT(post_accept), CA_MAIL_SERVER_SOLITARY, CA_MAIL_SERVER_PRE_DISCONN(anvil_service_done), CA_MAIL_SERVER_EXIT(anvil_status_dump), diff --git a/postfix/src/bounce/bounce.c b/postfix/src/bounce/bounce.c index afbeb6304..c6c979033 100644 --- a/postfix/src/bounce/bounce.c +++ b/postfix/src/bounce/bounce.c @@ -527,6 +527,14 @@ static void bounce_service(VSTREAM *client, char *service_name, char **argv) if (mail_queue_name_ok(service_name) == 0) msg_fatal("malformed service name: %s", service_name); + /* + * Announce the protocol. + */ + attr_print(client, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_BOUNCE), + ATTR_TYPE_END); + (void) vstream_fflush(client); + /* * Read and validate the first parameter of the client request. Let the * request-specific protocol routines take care of the remainder. diff --git a/postfix/src/cleanup/cleanup.c b/postfix/src/cleanup/cleanup.c index a3e86936d..e47fae6e7 100644 --- a/postfix/src/cleanup/cleanup.c +++ b/postfix/src/cleanup/cleanup.c @@ -144,8 +144,9 @@ /* for communication with a Milter application; prior to Postfix 2.6 /* the default protocol is 2. /* .IP "\fBmilter_default_action (tempfail)\fR" -/* The default action when a Milter (mail filter) application is -/* unavailable or mis-configured. +/* The default action when a Milter (mail filter) response is +/* unavailable (for example, bad Postfix configuration or Milter +/* failure). /* .IP "\fBmilter_macro_daemon_name ($myhostname)\fR" /* The {daemon_name} macro value for Milter (mail filter) applications. /* .IP "\fBmilter_macro_v ($mail_name $mail_version)\fR" @@ -503,6 +504,7 @@ static void cleanup_service(VSTREAM *src, char *unused_service, char **argv) * about the whole operation. */ attr_print(src, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP), SEND_ATTR_STR(MAIL_ATTR_QUEUEID, state->queue_id), ATTR_TYPE_END); if (attr_scan(src, ATTR_FLAG_STRICT, diff --git a/postfix/src/flush/flush.c b/postfix/src/flush/flush.c index 2e261bc32..30e5d2b2a 100644 --- a/postfix/src/flush/flush.c +++ b/postfix/src/flush/flush.c @@ -699,6 +699,14 @@ static int flush_request_receive(VSTREAM *client_stream, VSTRING *request) { int count; + /* + * Announce the protocol. + */ + attr_print(client_stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_FLUSH), + ATTR_TYPE_END); + (void) vstream_fflush(client_stream); + /* * Kluge: choose the protocol depending on the request size. */ diff --git a/postfix/src/global/abounce.c b/postfix/src/global/abounce.c index efbf1050f..5522f602e 100644 --- a/postfix/src/global/abounce.c +++ b/postfix/src/global/abounce.c @@ -169,6 +169,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -202,10 +207,11 @@ typedef struct { int command; /* bounce request type */ int flags; /* bounce options */ char *id; /* queue ID for logging */ + VSTRING *request; /* serialized request */ ABOUNCE_FN callback; /* application callback */ void *context; /* application context */ VSTREAM *fp; /* server I/O handle */ -} ABOUNCE; +} ABOUNCE_STATE; /* * Encapsulate common code. @@ -215,11 +221,6 @@ typedef struct { event_request_timer((callback), (context), (timeout)); \ } while (0) -#define ABOUNCE_EVENT_DISABLE(fd, callback, context) do { \ - event_cancel_timer((callback), (context)); \ - event_disable_readwrite(fd); \ - } while (0) - /* * If we set the reply timeout too short, then we make the problem worse by * increasing overload. With 1000s timeout mail will keep flowing, but there @@ -228,11 +229,30 @@ typedef struct { */ #define ABOUNCE_TIMEOUT 1000 + /* + * The initial buffer size for a serialized request. + */ +#define ABOUNCE_BUFSIZE VSTREAM_BUFSIZE + + /* + * We share most of the verp and non-verp code paths. + */ +#define ABOUNCE_NO_VERP ((char *) 0) + + /* + * SLMs. + */ +#define STR(x) vstring_str(x) +#define LEN(x) VSTRING_LEN(x) + /* abounce_done - deliver status to application and clean up pseudo thread */ -static void abounce_done(ABOUNCE *ap, int status) +static void abounce_done(ABOUNCE_STATE *ap, int status) { - (void) vstream_fclose(ap->fp); + if (ap->fp) { + event_disable_readwrite(vstream_fileno(ap->fp)); + (void) vstream_fclose(ap->fp); + } if (status != 0 && (ap->flags & BOUNCE_FLAG_CLEAN) == 0) msg_info("%s: status=deferred (%s failed)", ap->id, ap->command == BOUNCE_CMD_FLUSH ? "bounce" : @@ -242,65 +262,125 @@ static void abounce_done(ABOUNCE *ap, int status) "whatever"); ap->callback(status, ap->context); myfree(ap->id); + vstring_free(ap->request); myfree((void *) ap); } -/* abounce_event - resume pseudo thread after server reply event */ +/* abounce_receive - receive server reply */ -static void abounce_event(int event, void *context) +static void abounce_receive(int event, void *context) { - ABOUNCE *ap = (ABOUNCE *) context; + ABOUNCE_STATE *ap = (ABOUNCE_STATE *) context; int status; - ABOUNCE_EVENT_DISABLE(vstream_fileno(ap->fp), abounce_event, context); - abounce_done(ap, (event != EVENT_TIME - && attr_scan(ap->fp, ATTR_FLAG_STRICT, - RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), - ATTR_TYPE_END) == 1) ? status : -1); + if (event != EVENT_TIME) + event_cancel_timer(abounce_receive, context); + + if (event == EVENT_READ + && attr_scan(ap->fp, ATTR_FLAG_STRICT, + RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), + ATTR_TYPE_END) == 1) { + abounce_done(ap, status); + } else { + abounce_done(ap, -1); + } } -/* abounce_request_verp - suspend pseudo thread until server reply event */ +/* abounce_send - send the request and suspend until the server replies */ -static void abounce_request_verp(const char *class, const char *service, - int command, int flags, - const char *queue, const char *id, - const char *encoding, - int smtputf8, - const char *sender, - const char *dsn_envid, - int dsn_ret, - const char *verp, - ABOUNCE_FN callback, - void *context) +static void abounce_send(int event, void *context) { - ABOUNCE *ap; + ABOUNCE_STATE *ap = (ABOUNCE_STATE *) context; /* - * Save pseudo thread state. Connect to the server. Send the request and - * suspend the pseudo thread until the server replies (or dies). + * Receive the server's protocol name announcement. At this point the + * server is ready to receive a request without blocking the sender. Send + * the request and suspend until the server replies (or dies). */ - ap = (ABOUNCE *) mymalloc(sizeof(*ap)); + if (event != EVENT_TIME) + event_cancel_timer(abounce_send, context); + + non_blocking(vstream_fileno(ap->fp), BLOCKING); + if (event == EVENT_READ + && attr_scan(ap->fp, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_BOUNCE), + ATTR_TYPE_END) == 0 + && vstream_fwrite(ap->fp, STR(ap->request), + LEN(ap->request)) == LEN(ap->request) + && vstream_fflush(ap->fp) == 0) { + ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_receive, + (void *) ap, ABOUNCE_TIMEOUT); + } else { + abounce_done(ap, -1); + } +} + +/* abounce_connect - connect and suspend until the server replies */ + +static void abounce_connect(const char *class, const char *service, + int command, int flags, + const char *queue, const char *id, + const char *encoding, int smtputf8, + const char *sender, + const char *dsn_envid, int dsn_ret, + const char *verp, ABOUNCE_FN callback, + void *context) +{ + ABOUNCE_STATE *ap; + + /* + * Save pseudo thread state. Connect to the server. Prior to Postfix 3.6 + * the asynchronous bounce flush/warn client called mail_connect_wait() + * which sleeps and retries several times before terminating with a fatal + * error. This block-and-sleep behavior was not consistent with a) the + * rest of the code in this module, and with b) the synchronous bounce + * client which gives up immediately. It should be safe to give up + * immediately because that leaves the bounce/defer/trace logs in the + * queue. In particular, this should not increase the simultaneous number + * of asynchronous bounce/defer/trace flush/warn requests that are in + * flight. + */ + ap = (ABOUNCE_STATE *) mymalloc(sizeof(*ap)); ap->command = command; ap->flags = flags; ap->id = mystrdup(id); + ap->request = vstring_alloc(ABOUNCE_BUFSIZE); ap->callback = callback; ap->context = context; - ap->fp = mail_connect_wait(class, service); + ap->fp = mail_connect(class, service, NON_BLOCKING); - if (attr_print(ap->fp, ATTR_FLAG_NONE, - SEND_ATTR_INT(MAIL_ATTR_NREQ, command), - SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), - SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue), - SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id), - SEND_ATTR_STR(MAIL_ATTR_ENCODING, encoding), - SEND_ATTR_INT(MAIL_ATTR_SMTPUTF8, smtputf8), - SEND_ATTR_STR(MAIL_ATTR_SENDER, sender), - SEND_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid), - SEND_ATTR_INT(MAIL_ATTR_DSN_RET, dsn_ret), - SEND_ATTR_STR(MAIL_ATTR_VERPDL, verp), - ATTR_TYPE_END) == 0 - && vstream_fflush(ap->fp) == 0) { - ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_event, + /* + * Format the request now, so that we don't have to save a lot of + * arguments now and format the request later. + */ + if (ap->fp != 0) { + /* Note: all code paths must terminate or enable I/O events. */ + VSTREAM *mp = vstream_memopen(ap->request, O_WRONLY); + + if (attr_print(mp, ATTR_FLAG_MORE, + SEND_ATTR_INT(MAIL_ATTR_NREQ, command), + SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), + SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue), + SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id), + SEND_ATTR_STR(MAIL_ATTR_ENCODING, encoding), + SEND_ATTR_INT(MAIL_ATTR_SMTPUTF8, smtputf8), + SEND_ATTR_STR(MAIL_ATTR_SENDER, sender), + SEND_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid), + SEND_ATTR_INT(MAIL_ATTR_DSN_RET, dsn_ret), + ATTR_TYPE_END) != 0 + || (verp != 0 + && attr_print(mp, ATTR_FLAG_MORE, + SEND_ATTR_STR(MAIL_ATTR_VERPDL, verp), + ATTR_TYPE_END) != 0) + || attr_print(mp, ATTR_FLAG_NONE, + ATTR_TYPE_END) != 0 + || vstream_fclose(mp) != 0) + msg_panic("abounce_connect: write request to memory stream: %m"); + + /* + * Suspend until the server replies (or dies). + */ + ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_send, (void *) ap, ABOUNCE_TIMEOUT); } else { abounce_done(ap, -1); @@ -316,9 +396,9 @@ void abounce_flush_verp(int flags, const char *queue, const char *id, ABOUNCE_FN callback, void *context) { - abounce_request_verp(MAIL_CLASS_PRIVATE, var_bounce_service, - BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8, - sender, dsn_envid, dsn_ret, verp, callback, context); + abounce_connect(MAIL_CLASS_PRIVATE, var_bounce_service, + BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8, + sender, dsn_envid, dsn_ret, verp, callback, context); } /* adefer_flush_verp - asynchronous defer flush */ @@ -330,52 +410,9 @@ void adefer_flush_verp(int flags, const char *queue, const char *id, ABOUNCE_FN callback, void *context) { flags |= BOUNCE_FLAG_DELRCPT; - abounce_request_verp(MAIL_CLASS_PRIVATE, var_defer_service, - BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8, - sender, dsn_envid, dsn_ret, verp, callback, context); -} - -/* abounce_request - suspend pseudo thread until server reply event */ - -static void abounce_request(const char *class, const char *service, - int command, int flags, - const char *queue, const char *id, - const char *encoding, int smtputf8, - const char *sender, - const char *dsn_envid, int dsn_ret, - ABOUNCE_FN callback, void *context) -{ - ABOUNCE *ap; - - /* - * Save pseudo thread state. Connect to the server. Send the request and - * suspend the pseudo thread until the server replies (or dies). - */ - ap = (ABOUNCE *) mymalloc(sizeof(*ap)); - ap->command = command; - ap->flags = flags; - ap->id = mystrdup(id); - ap->callback = callback; - ap->context = context; - ap->fp = mail_connect_wait(class, service); - - if (attr_print(ap->fp, ATTR_FLAG_NONE, - SEND_ATTR_INT(MAIL_ATTR_NREQ, command), - SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), - SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue), - SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id), - SEND_ATTR_STR(MAIL_ATTR_ENCODING, encoding), - SEND_ATTR_INT(MAIL_ATTR_SMTPUTF8, smtputf8), - SEND_ATTR_STR(MAIL_ATTR_SENDER, sender), - SEND_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid), - SEND_ATTR_INT(MAIL_ATTR_DSN_RET, dsn_ret), - ATTR_TYPE_END) == 0 - && vstream_fflush(ap->fp) == 0) { - ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_event, - (void *) ap, ABOUNCE_TIMEOUT); - } else { - abounce_done(ap, -1); - } + abounce_connect(MAIL_CLASS_PRIVATE, var_defer_service, + BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8, + sender, dsn_envid, dsn_ret, verp, callback, context); } /* abounce_flush - asynchronous bounce flush */ @@ -386,9 +423,9 @@ void abounce_flush(int flags, const char *queue, const char *id, int dsn_ret, ABOUNCE_FN callback, void *context) { - abounce_request(MAIL_CLASS_PRIVATE, var_bounce_service, BOUNCE_CMD_FLUSH, + abounce_connect(MAIL_CLASS_PRIVATE, var_bounce_service, BOUNCE_CMD_FLUSH, flags, queue, id, encoding, smtputf8, sender, dsn_envid, - dsn_ret, callback, context); + dsn_ret, ABOUNCE_NO_VERP, callback, context); } /* adefer_flush - asynchronous defer flush */ @@ -399,9 +436,9 @@ void adefer_flush(int flags, const char *queue, const char *id, int dsn_ret, ABOUNCE_FN callback, void *context) { flags |= BOUNCE_FLAG_DELRCPT; - abounce_request(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_FLUSH, + abounce_connect(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_FLUSH, flags, queue, id, encoding, smtputf8, sender, dsn_envid, - dsn_ret, callback, context); + dsn_ret, ABOUNCE_NO_VERP, callback, context); } /* adefer_warn - send copy of defer log to sender as warning bounce */ @@ -411,9 +448,9 @@ void adefer_warn(int flags, const char *queue, const char *id, const char *sender, const char *dsn_envid, int dsn_ret, ABOUNCE_FN callback, void *context) { - abounce_request(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_WARN, + abounce_connect(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_WARN, flags, queue, id, encoding, smtputf8, sender, dsn_envid, - dsn_ret, callback, context); + dsn_ret, ABOUNCE_NO_VERP, callback, context); } /* atrace_flush - asynchronous trace flush */ @@ -423,7 +460,7 @@ void atrace_flush(int flags, const char *queue, const char *id, const char *sender, const char *dsn_envid, int dsn_ret, ABOUNCE_FN callback, void *context) { - abounce_request(MAIL_CLASS_PRIVATE, var_trace_service, BOUNCE_CMD_TRACE, + abounce_connect(MAIL_CLASS_PRIVATE, var_trace_service, BOUNCE_CMD_TRACE, flags, queue, id, encoding, smtputf8, sender, dsn_envid, - dsn_ret, callback, context); + dsn_ret, ABOUNCE_NO_VERP, callback, context); } diff --git a/postfix/src/global/anvil_clnt.c b/postfix/src/global/anvil_clnt.c index 60bcda3ef..fff9ec7f4 100644 --- a/postfix/src/global/anvil_clnt.c +++ b/postfix/src/global/anvil_clnt.c @@ -170,6 +170,15 @@ #define ANVIL_IDENT(service, addr) \ printable(concatenate(service, ":", addr, (char *) 0), '?') +/* anvil_clnt_handshake - receive server protocol announcement */ + +static int anvil_clnt_handshake(VSTREAM *stream) +{ + return (attr_scan_plain(stream, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_ANVIL), + ATTR_TYPE_END)); +} + /* anvil_clnt_create - instantiate connection rate service client */ ANVIL_CLNT *anvil_clnt_create(void) @@ -186,6 +195,9 @@ ANVIL_CLNT *anvil_clnt_create(void) #else anvil_clnt = attr_clnt_create(var_anvil_service, var_ipc_timeout, 0, 0); #endif + attr_clnt_control(anvil_clnt, + ATTR_CLNT_CTL_HANDSHAKE, anvil_clnt_handshake, + ATTR_CLNT_CTL_END); return ((ANVIL_CLNT *) anvil_clnt); } diff --git a/postfix/src/global/bounce.c b/postfix/src/global/bounce.c index 3d7821650..b03530750 100644 --- a/postfix/src/global/bounce.c +++ b/postfix/src/global/bounce.c @@ -186,6 +186,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -310,6 +315,7 @@ int bounce_append_intern(int flags, const char *id, MSG_STATS *stats, if (mail_command_client(MAIL_CLASS_PRIVATE, var_soft_bounce ? var_defer_service : var_bounce_service, + MAIL_ATTR_PROTO_BOUNCE, SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND), SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id), @@ -353,6 +359,7 @@ int bounce_flush(int flags, const char *queue, const char *id, if (var_soft_bounce) return (-1); if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service, + MAIL_ATTR_PROTO_BOUNCE, SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH), SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue), @@ -387,6 +394,7 @@ int bounce_flush_verp(int flags, const char *queue, const char *id, if (var_soft_bounce) return (-1); if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service, + MAIL_ATTR_PROTO_BOUNCE, SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_VERP), SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue), @@ -494,6 +502,7 @@ int bounce_one_intern(int flags, const char *queue, const char *id, my_dsn.action = "failed"; if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service, + MAIL_ATTR_PROTO_BOUNCE, SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_ONE), SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue), diff --git a/postfix/src/global/clnt_stream.c b/postfix/src/global/clnt_stream.c index 2eec1fc8b..ca3ce4f3d 100644 --- a/postfix/src/global/clnt_stream.c +++ b/postfix/src/global/clnt_stream.c @@ -6,11 +6,15 @@ /* SYNOPSIS /* #include /* -/* CLNT_STREAM *clnt_stream_create(class, service, timeout, ttl) +/* typedef void (*CLNT_STREAM_HANDSHAKE_FN)(VSTREAM *) +/* +/* CLNT_STREAM *clnt_stream_create(class, service, timeout, ttl, +/* handshake) /* const char *class; /* const char *service; /* int timeout; /* int ttl; +/* CLNT_STREAM_HANDSHAKE_FN *handshake; /* /* VSTREAM *clnt_stream_access(clnt_stream) /* CLNT_STREAM *clnt_stream; @@ -33,6 +37,8 @@ /* /* clnt_stream_access() returns an open stream to the service specified /* to clnt_stream_create(). The stream instance may change between calls. +/* This function returns null when the handshake function returned an +/* error. /* /* clnt_stream_recover() recovers from a server-initiated disconnect /* that happened in the middle of an I/O operation. @@ -49,6 +55,10 @@ /* Idle time after which the client disconnects. /* .IP ttl /* Upper bound on the time that a connection is allowed to persist. +/* .IP handshake +/* Null pointer, or pointer to function that will be called +/* at the start of a new connection and that returns 0 in case +/* of success. /* DIAGNOSTICS /* Warnings: communication failure. Fatal error: mail system is down, /* out of memory. @@ -63,6 +73,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -93,6 +108,7 @@ struct CLNT_STREAM { VSTREAM *vstream; /* buffered I/O */ int timeout; /* time before client disconnect */ int ttl; /* time before client disconnect */ + CLNT_STREAM_HANDSHAKE_FN handshake; char *class; /* server class */ char *service; /* server name */ }; @@ -205,6 +221,7 @@ void clnt_stream_recover(CLNT_STREAM *clnt_stream) VSTREAM *clnt_stream_access(CLNT_STREAM *clnt_stream) { + CLNT_STREAM_HANDSHAKE_FN handshake; /* * Open a stream or restart the idle timer. @@ -213,20 +230,26 @@ VSTREAM *clnt_stream_access(CLNT_STREAM *clnt_stream) */ if (clnt_stream->vstream == 0) { clnt_stream_open(clnt_stream); + handshake = clnt_stream->handshake; } else if (readable(vstream_fileno(clnt_stream->vstream))) { clnt_stream_close(clnt_stream); clnt_stream_open(clnt_stream); + handshake = clnt_stream->handshake; } else { event_request_timer(clnt_stream_event, (void *) clnt_stream, clnt_stream->timeout); + handshake = 0; } + if (handshake != 0 && handshake(clnt_stream->vstream) != 0) + return (0); return (clnt_stream->vstream); } /* clnt_stream_create - create client stream connection */ CLNT_STREAM *clnt_stream_create(const char *class, const char *service, - int timeout, int ttl) + int timeout, int ttl, + CLNT_STREAM_HANDSHAKE_FN handshake) { CLNT_STREAM *clnt_stream; @@ -237,6 +260,7 @@ CLNT_STREAM *clnt_stream_create(const char *class, const char *service, clnt_stream->vstream = 0; clnt_stream->timeout = timeout; clnt_stream->ttl = ttl; + clnt_stream->handshake = handshake; clnt_stream->class = mystrdup(class); clnt_stream->service = mystrdup(service); return (clnt_stream); diff --git a/postfix/src/global/clnt_stream.h b/postfix/src/global/clnt_stream.h index 0d3ee4775..bb92e2fcc 100644 --- a/postfix/src/global/clnt_stream.h +++ b/postfix/src/global/clnt_stream.h @@ -20,9 +20,12 @@ * External interface. */ typedef struct CLNT_STREAM CLNT_STREAM; +typedef int (*CLNT_STREAM_HANDSHAKE_FN)(VSTREAM *); -extern CLNT_STREAM *clnt_stream_create(const char *, const char *, int, int); +extern CLNT_STREAM *clnt_stream_create(const char *, const char *, int, int, + CLNT_STREAM_HANDSHAKE_FN); extern VSTREAM *clnt_stream_access(CLNT_STREAM *); +extern const char *clnt_stream_path(CLNT_STREAM *); extern void clnt_stream_recover(CLNT_STREAM *); extern void clnt_stream_free(CLNT_STREAM *); @@ -35,6 +38,11 @@ extern void clnt_stream_free(CLNT_STREAM *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/postfix/src/global/defer.c b/postfix/src/global/defer.c index 83e8d1491..f904ec677 100644 --- a/postfix/src/global/defer.c +++ b/postfix/src/global/defer.c @@ -153,6 +153,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -257,6 +262,7 @@ int defer_append_intern(int flags, const char *id, MSG_STATS *stats, my_dsn.action = "delayed"; if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service, + MAIL_ATTR_PROTO_BOUNCE, SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND), SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id), @@ -301,6 +307,7 @@ int defer_flush(int flags, const char *queue, const char *id, flags |= BOUNCE_FLAG_DELRCPT; if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service, + MAIL_ATTR_PROTO_BOUNCE, SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH), SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue), @@ -325,6 +332,7 @@ int defer_warn(int flags, const char *queue, const char *id, const char *sender, const char *envid, int dsn_ret) { if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service, + MAIL_ATTR_PROTO_BOUNCE, SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_WARN), SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue), diff --git a/postfix/src/global/deliver_pass.c b/postfix/src/global/deliver_pass.c index d7945fcd4..f744ad533 100644 --- a/postfix/src/global/deliver_pass.c +++ b/postfix/src/global/deliver_pass.c @@ -49,6 +49,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -79,15 +84,13 @@ static int deliver_pass_initial_reply(VSTREAM *stream) { - int stat; - if (attr_scan(stream, ATTR_FLAG_STRICT, - RECV_ATTR_INT(MAIL_ATTR_STATUS, &stat), - ATTR_TYPE_END) != 1) { + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER), + ATTR_TYPE_END) != 0) { msg_warn("%s: malformed response", VSTREAM_PATH(stream)); - stat = -1; + return (-1); } - return (stat); + return (0); } /* deliver_pass_send_request - send delivery request to delivery process */ diff --git a/postfix/src/global/deliver_request.c b/postfix/src/global/deliver_request.c index f5c775ab2..d5add7873 100644 --- a/postfix/src/global/deliver_request.c +++ b/postfix/src/global/deliver_request.c @@ -92,6 +92,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -135,13 +140,13 @@ static int deliver_request_initial(VSTREAM *stream) * delivery request; otherwise the queue manager could block in write(). */ if (msg_verbose) - msg_info("deliver_request_initial: send initial status"); + msg_info("deliver_request_initial: send initial response"); attr_print(stream, ATTR_FLAG_NONE, - SEND_ATTR_INT(MAIL_ATTR_STATUS, 0), + SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER), ATTR_TYPE_END); if ((err = vstream_fflush(stream)) != 0) if (msg_verbose) - msg_warn("send initial status: %m"); + msg_warn("send initial response: %m"); return (err); } diff --git a/postfix/src/global/dict_proxy.c b/postfix/src/global/dict_proxy.c index 924c62dcd..5aa915309 100644 --- a/postfix/src/global/dict_proxy.c +++ b/postfix/src/global/dict_proxy.c @@ -41,6 +41,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -89,6 +94,15 @@ typedef struct { static CLNT_STREAM *proxymap_stream; /* read-only maps */ static CLNT_STREAM *proxywrite_stream; /* read-write maps */ +/* dict_proxy_handshake - receive server protocol announcement */ + +static int dict_proxy_handshake(VSTREAM *stream) +{ + return (attr_scan(stream, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_PROXYMAP), + ATTR_TYPE_END)); +} + /* dict_proxy_sequence - find first/next entry */ static int dict_proxy_sequence(DICT *dict, int function, @@ -118,12 +132,13 @@ static int dict_proxy_sequence(DICT *dict, int function, stream = clnt_stream_access(dict_proxy->clnt); errno = 0; count += 1; - if (attr_print(stream, ATTR_FLAG_NONE, - SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_SEQUENCE), - SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name), - SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags), - SEND_ATTR_INT(MAIL_ATTR_FUNC, function), - ATTR_TYPE_END) != 0 + if (stream == 0 + || attr_print(stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_SEQUENCE), + SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name), + SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags), + SEND_ATTR_INT(MAIL_ATTR_FUNC, function), + ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), @@ -131,7 +146,7 @@ static int dict_proxy_sequence(DICT *dict, int function, RECV_ATTR_STR(MAIL_ATTR_VALUE, dict_proxy->result), ATTR_TYPE_END) != 3) { if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT)) - msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream)); + msg_warn("%s: service %s: %m", myname, dict_proxy->service); } else { if (msg_verbose) msg_info("%s: table=%s flags=%s func=%d -> status=%d key=%s val=%s", @@ -196,19 +211,20 @@ static const char *dict_proxy_lookup(DICT *dict, const char *key) stream = clnt_stream_access(dict_proxy->clnt); errno = 0; count += 1; - if (attr_print(stream, ATTR_FLAG_NONE, - SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_LOOKUP), - SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name), - SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags), - SEND_ATTR_STR(MAIL_ATTR_KEY, key), - ATTR_TYPE_END) != 0 + if (stream == 0 + || attr_print(stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_LOOKUP), + SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name), + SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags), + SEND_ATTR_STR(MAIL_ATTR_KEY, key), + ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), RECV_ATTR_STR(MAIL_ATTR_VALUE, dict_proxy->result), ATTR_TYPE_END) != 2) { if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT)) - msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream)); + msg_warn("%s: service %s: %m", myname, dict_proxy->service); } else { if (msg_verbose) msg_info("%s: table=%s flags=%s key=%s -> status=%d result=%s", @@ -266,19 +282,20 @@ static int dict_proxy_update(DICT *dict, const char *key, const char *value) stream = clnt_stream_access(dict_proxy->clnt); errno = 0; count += 1; - if (attr_print(stream, ATTR_FLAG_NONE, - SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_UPDATE), - SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name), - SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags), - SEND_ATTR_STR(MAIL_ATTR_KEY, key), - SEND_ATTR_STR(MAIL_ATTR_VALUE, value), - ATTR_TYPE_END) != 0 + if (stream == 0 + || attr_print(stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_UPDATE), + SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name), + SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags), + SEND_ATTR_STR(MAIL_ATTR_KEY, key), + SEND_ATTR_STR(MAIL_ATTR_VALUE, value), + ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), ATTR_TYPE_END) != 1) { if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT)) - msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream)); + msg_warn("%s: service %s: %m", myname, dict_proxy->service); } else { if (msg_verbose) msg_info("%s: table=%s flags=%s key=%s value=%s -> status=%d", @@ -335,19 +352,20 @@ static int dict_proxy_delete(DICT *dict, const char *key) stream = clnt_stream_access(dict_proxy->clnt); errno = 0; count += 1; - if (attr_print(stream, ATTR_FLAG_NONE, - SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_DELETE), - SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name), - SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags), - SEND_ATTR_STR(MAIL_ATTR_KEY, key), - ATTR_TYPE_END) != 0 + if (stream == 0 + || attr_print(stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_DELETE), + SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name), + SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags), + SEND_ATTR_STR(MAIL_ATTR_KEY, key), + ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), ATTR_TYPE_END) != 1) { if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT)) - msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream)); + msg_warn("%s: service %s: %m", myname, dict_proxy->service); } else { if (msg_verbose) msg_info("%s: table=%s flags=%s key=%s -> status=%d", @@ -443,7 +461,8 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags) prefix = kludge = concatenate(var_queue_dir, "/", MAIL_CLASS_PRIVATE, (char *) 0); *pstream = clnt_stream_create(prefix, service, var_ipc_idle_limit, - var_ipc_ttl_limit); + var_ipc_ttl_limit, + dict_proxy_handshake); if (kludge) myfree(kludge); myfree(relative_path); @@ -473,18 +492,19 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags) for (;;) { stream = clnt_stream_access(dict_proxy->clnt); errno = 0; - if (attr_print(stream, ATTR_FLAG_NONE, - SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_OPEN), - SEND_ATTR_STR(MAIL_ATTR_TABLE, dict_proxy->dict.name), + if (stream == 0 + || attr_print(stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_OPEN), + SEND_ATTR_STR(MAIL_ATTR_TABLE, dict_proxy->dict.name), SEND_ATTR_INT(MAIL_ATTR_FLAGS, dict_proxy->inst_flags), - ATTR_TYPE_END) != 0 + ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), RECV_ATTR_INT(MAIL_ATTR_FLAGS, &server_flags), ATTR_TYPE_END) != 2) { if (msg_verbose || (errno != EPIPE && errno != ENOENT)) - msg_warn("%s: service %s: %m", VSTREAM_PATH(stream), myname); + msg_warn("%s: service %s: %m", myname, dict_proxy->service); } else { if (msg_verbose) msg_info("%s: connect to map=%s status=%d server_flags=%s", diff --git a/postfix/src/global/flush_clnt.c b/postfix/src/global/flush_clnt.c index 7accaa98a..8084bf5d8 100644 --- a/postfix/src/global/flush_clnt.c +++ b/postfix/src/global/flush_clnt.c @@ -71,6 +71,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -125,6 +130,7 @@ int flush_purge(void) status = FLUSH_STAT_DENY; else status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service, + MAIL_ATTR_PROTO_FLUSH, SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_PURGE), ATTR_TYPE_END); @@ -151,6 +157,7 @@ int flush_refresh(void) status = FLUSH_STAT_DENY; else status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service, + MAIL_ATTR_PROTO_FLUSH, SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_REFRESH), ATTR_TYPE_END); @@ -182,6 +189,7 @@ int flush_send_site(const char *site) VAR_RELAY_DOMAINS "=$mydestination to flush " "mail for domain \"%s\"", site); status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service, + MAIL_ATTR_PROTO_FLUSH, SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_SEND_SITE), SEND_ATTR_STR(MAIL_ATTR_SITE, site), ATTR_TYPE_END); @@ -210,6 +218,7 @@ int flush_send_file(const char *queue_id) * Require that the service is turned on. */ status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service, + MAIL_ATTR_PROTO_FLUSH, SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_SEND_FILE), SEND_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id), ATTR_TYPE_END); @@ -242,6 +251,7 @@ int flush_add(const char *site, const char *queue_id) VAR_RELAY_DOMAINS "=$mydestination to update " "fast-flush logfile for domain \"%s\"", site); status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service, + MAIL_ATTR_PROTO_FLUSH, SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_ADD), SEND_ATTR_STR(MAIL_ATTR_SITE, site), SEND_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id), diff --git a/postfix/src/global/haproxy_srvr.c b/postfix/src/global/haproxy_srvr.c index 2c849d76c..0b40e0268 100644 --- a/postfix/src/global/haproxy_srvr.c +++ b/postfix/src/global/haproxy_srvr.c @@ -403,7 +403,6 @@ static const char *haproxy_srvr_parse_v2_hdr(const char *str, ssize_t *str_len, return ("unsupported network protocol"); } /* For now, skip and ignore TLVs. */ - *non_proxy = 0; *str_len = PP2_HEADER_LEN + ntohs(hdr_v2->len); return (0); @@ -434,6 +433,8 @@ const char *haproxy_srvr_parse(const char *str, ssize_t *str_len, if (proto_info == 0) proto_info = inet_proto_info(); + *non_proxy = 0; + /* * XXX We don't accept connections with the "UNKNOWN" protocol type, * because those would sidestep address-based access control mechanisms. @@ -471,7 +472,6 @@ const char *haproxy_srvr_parse(const char *str, ssize_t *str_len, } myfree(saved_str); - *non_proxy = 0; return (err); } diff --git a/postfix/src/global/mail_command_client.c b/postfix/src/global/mail_command_client.c index 1817b0329..3de116948 100644 --- a/postfix/src/global/mail_command_client.c +++ b/postfix/src/global/mail_command_client.c @@ -6,9 +6,10 @@ /* SYNOPSIS /* #include /* -/* int mail_command_client(class, name, type, attr, ...) +/* int mail_command_client(class, name, proto, type, attr, ...) /* const char *class; /* const char *name; +/* const char *proto; /* int type; /* const char *attr; /* DESCRIPTION @@ -21,6 +22,8 @@ /* Service type: MAIL_CLASS_PUBLIC or MAIL_CLASS_PRIVATE /* .IP name /* Service name (master.cf). +/* .IP proto +/* The expected protocol name in the server announcement. /* .IP "type, attr, ..." /* Attribute information as defined in attr_print(3). /* DIAGNOSTICS @@ -65,7 +68,8 @@ /* mail_command_client - single-command transaction with completion status */ -int mail_command_client(const char *class, const char *name,...) +int mail_command_client(const char *class, const char *name, + const char *proto,...) { va_list ap; VSTREAM *stream; @@ -82,14 +86,20 @@ int mail_command_client(const char *class, const char *name,...) msg_warn("connect to %s/%s: %m", class, name); return (-1); } - va_start(ap, name); - status = attr_vprint(stream, ATTR_FLAG_NONE, ap); - va_end(ap); - if (status != 0) { + if (attr_scan(stream, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, proto), + ATTR_TYPE_END) != 0) { + msg_warn("read %s: %m", VSTREAM_PATH(stream)); + status = -1; + } else if (va_start(ap, proto), + (status = attr_vprint(stream, ATTR_FLAG_NONE, ap)), + va_end(ap), + (status != 0)) { msg_warn("write %s: %m", VSTREAM_PATH(stream)); status = -1; } else if (attr_scan(stream, ATTR_FLAG_STRICT, - RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), 0) != 1) { + RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), + ATTR_TYPE_END) != 1) { msg_warn("write/read %s: %m", VSTREAM_PATH(stream)); status = -1; } diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h index a45466213..3ffe1fcbd 100644 --- a/postfix/src/global/mail_proto.h +++ b/postfix/src/global/mail_proto.h @@ -114,11 +114,32 @@ */ extern VSTREAM *mail_connect(const char *, const char *, int); extern VSTREAM *mail_connect_wait(const char *, const char *); -extern int mail_command_client(const char *, const char *,...); +extern int mail_command_client(const char *, const char *, const char *,...); extern int mail_command_server(VSTREAM *,...); extern int mail_trigger(const char *, const char *, const char *, ssize_t); extern char *mail_pathname(const char *, const char *); + /* + * Each Postfix internal service identifies the protocol that it intends to + * use. On the receiver end, this information does not contribute to the + * reported number of received attributes (it is a constant). + */ +#define MAIL_ATTR_PROTO "protocol" + +#define MAIL_ATTR_PROTO_ANVIL "anvil_protocol" +#define MAIL_ATTR_PROTO_BOUNCE "delivery_status_protocol" +#define MAIL_ATTR_PROTO_CLEANUP "cleanup_protocol" +#define MAIL_ATTR_PROTO_DELIVER "delivery_request_protocol" +#define MAIL_ATTR_PROTO_FLUSH "queue_flush_protocol" +#define MAIL_ATTR_PROTO_POSTDROP "postdrop_protocol" +#define MAIL_ATTR_PROTO_PROXYMAP "proxymap_protocol" +#define MAIL_ATTR_PROTO_SCACHE "connection_cache_protocol" +#define MAIL_ATTR_PROTO_SHOWQ "mail_queue_list_protocol" +#define MAIL_ATTR_PROTO_TLSMGR "tlsmgr_protocol" +#define MAIL_ATTR_PROTO_TLSPROXY "tlsproxy_protocol" +#define MAIL_ATTR_PROTO_TRIVIAL "trivial_rewrite_protocol" +#define MAIL_ATTR_PROTO_VERIFY "address_verification_prrotocol" + /* * Attribute names. */ diff --git a/postfix/src/global/mail_stream.c b/postfix/src/global/mail_stream.c index a98d3ad81..90a1ee084 100644 --- a/postfix/src/global/mail_stream.c +++ b/postfix/src/global/mail_stream.c @@ -105,6 +105,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -440,7 +445,8 @@ MAIL_STREAM *mail_stream_service(const char *class, const char *name) id_buf = vstring_alloc(10); stream = mail_connect_wait(class, name); - if (attr_scan(stream, ATTR_FLAG_MISSING, + if (attr_scan(stream, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP), RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id_buf), 0) != 1) { vstream_fclose(stream); return (0); @@ -492,7 +498,8 @@ MAIL_STREAM *mail_stream_command(const char *command) CA_VSTREAM_CTL_PATH(command), CA_VSTREAM_CTL_END); - if (attr_scan(stream, ATTR_FLAG_MISSING, + if (attr_scan(stream, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_POSTDROP), RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id_buf), 0) != 1) { if ((status = vstream_pclose(stream)) != 0) msg_warn("command \"%s\" exited with status %d", command, status); diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 6605b5043..f6ce1d215 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 "20200830" +#define MAIL_RELEASE_DATE "20200920" #define MAIL_VERSION_NUMBER "3.6" #ifdef SNAPSHOT diff --git a/postfix/src/global/post_mail.c b/postfix/src/global/post_mail.c index 1fecf3f64..e7a9a6746 100644 --- a/postfix/src/global/post_mail.c +++ b/postfix/src/global/post_mail.c @@ -231,8 +231,18 @@ static void post_mail_init(VSTREAM *stream, const char *sender, date = mail_date(now.tv_sec); /* - * XXX Don't flush buffers while sending the initial message records. - * That would cause deadlock between verify(8) and cleanup(8) servers. + * The comment in the next paragraph is likely obsolete. Fix 20030610 + * changed the verify server to use asynchronous submission of mail + * probes, to avoid blocking the post_mail client for in_flow_delay + * seconds when the cleanup service receives email messages faster than + * they are delivered. Instead, the post_mail client waits until the + * cleanup server announces its availability to receive input. A similar + * change was made at the end of submission, to avoid blocking the + * post_mail client for up to trigger_timeout seconds when the cleanup + * server attempts to notify a queue manager that is overwhelmed. + * + * XXX Don't flush buffers while sending the initial message records. That + * would cause deadlock between verify(8) and cleanup(8) servers. */ vstream_control(stream, VSTREAM_CTL_BUFSIZE, 2 * VSTREAM_BUFSIZE, VSTREAM_CTL_END); @@ -241,6 +251,7 @@ static void post_mail_init(VSTREAM *stream, const char *sender, * Negotiate with the cleanup service. Give up if we can't agree. */ if (attr_scan(stream, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP), RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id), ATTR_TYPE_END) != 1 || attr_print(stream, ATTR_FLAG_NONE, diff --git a/postfix/src/global/resolve_clnt.c b/postfix/src/global/resolve_clnt.c index 859469394..ccd67b239 100644 --- a/postfix/src/global/resolve_clnt.c +++ b/postfix/src/global/resolve_clnt.c @@ -152,6 +152,15 @@ void resolve_clnt_init(RESOLVE_REPLY *reply) reply->flags = 0; } +/* resolve_clnt_handshake - receive server protocol announcement */ + +static int resolve_clnt_handshake(VSTREAM *stream) +{ + return (attr_scan(stream, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TRIVIAL), + ATTR_TYPE_END)); +} + /* resolve_clnt - resolve address to (transport, next hop, recipient) */ void resolve_clnt(const char *class, const char *sender, @@ -219,17 +228,19 @@ void resolve_clnt(const char *class, const char *sender, rewrite_clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE, var_rewrite_service, var_ipc_idle_limit, - var_ipc_ttl_limit); + var_ipc_ttl_limit, + resolve_clnt_handshake); for (;;) { stream = clnt_stream_access(rewrite_clnt_stream); errno = 0; count += 1; - if (attr_print(stream, ATTR_FLAG_NONE, - SEND_ATTR_STR(MAIL_ATTR_REQ, class), - SEND_ATTR_STR(MAIL_ATTR_SENDER, sender), - SEND_ATTR_STR(MAIL_ATTR_ADDR, addr), - ATTR_TYPE_END) != 0 + if (stream == 0 + || attr_print(stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_REQ, class), + SEND_ATTR_STR(MAIL_ATTR_SENDER, sender), + SEND_ATTR_STR(MAIL_ATTR_ADDR, addr), + ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, RECV_ATTR_INT(MAIL_ATTR_FLAGS, &server_flags), diff --git a/postfix/src/global/rewrite_clnt.c b/postfix/src/global/rewrite_clnt.c index e11f81a4a..420c778d2 100644 --- a/postfix/src/global/rewrite_clnt.c +++ b/postfix/src/global/rewrite_clnt.c @@ -39,6 +39,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -77,6 +82,15 @@ static VSTRING *last_rule; static VSTRING *last_addr; static VSTRING *last_result; +/* rewrite_clnt_handshake - receive server protocol announcement */ + +static int rewrite_clnt_handshake(VSTREAM *stream) +{ + return (attr_scan(stream, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TRIVIAL), + ATTR_TYPE_END)); +} + /* rewrite_clnt - rewrite address to (transport, next hop, recipient) */ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result) @@ -127,17 +141,19 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result) rewrite_clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE, var_rewrite_service, var_ipc_idle_limit, - var_ipc_ttl_limit); + var_ipc_ttl_limit, + rewrite_clnt_handshake); for (;;) { stream = clnt_stream_access(rewrite_clnt_stream); errno = 0; count += 1; - if (attr_print(stream, ATTR_FLAG_NONE, - SEND_ATTR_STR(MAIL_ATTR_REQ, REWRITE_ADDR), - SEND_ATTR_STR(MAIL_ATTR_RULE, rule), - SEND_ATTR_STR(MAIL_ATTR_ADDR, addr), - ATTR_TYPE_END) != 0 + if (stream == 0 + || attr_print(stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_REQ, REWRITE_ADDR), + SEND_ATTR_STR(MAIL_ATTR_RULE, rule), + SEND_ATTR_STR(MAIL_ATTR_ADDR, addr), + ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, RECV_ATTR_INT(MAIL_ATTR_FLAGS, &server_flags), diff --git a/postfix/src/global/sasl_mech_filter.c b/postfix/src/global/sasl_mech_filter.c index b67c3051e..bbc34966b 100644 --- a/postfix/src/global/sasl_mech_filter.c +++ b/postfix/src/global/sasl_mech_filter.c @@ -68,7 +68,7 @@ /* sasl_mech_filter - filter a SASL mechanism list */ const char *sasl_mech_filter(STRING_LIST *filter, - const const char *words) + const char *words) { const char myname[] = "sasl_mech_filter"; static VSTRING *buf; diff --git a/postfix/src/global/scache_clnt.c b/postfix/src/global/scache_clnt.c index 536053234..97fe8aa28 100644 --- a/postfix/src/global/scache_clnt.c +++ b/postfix/src/global/scache_clnt.c @@ -41,6 +41,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -80,6 +85,15 @@ typedef struct { #define SCACHE_MAX_TRIES 2 +/* scache_clnt_handshake - receive server protocol announcement */ + +static int scache_clnt_handshake(VSTREAM *stream) +{ + return (attr_scan(stream, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_SCACHE), + ATTR_TYPE_END)); +} + /* scache_clnt_save_endp - save endpoint */ static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl, @@ -414,8 +428,11 @@ SCACHE *scache_clnt_create(const char *server, int timeout, sp->scache->size = scache_clnt_size; sp->scache->free = scache_clnt_free; - service = concatenate("local:private/", server, (char *) 0); + service = concatenate("local:" MAIL_CLASS_PRIVATE "/", server, (char *) 0); sp->auto_clnt = auto_clnt_create(service, timeout, idle_limit, ttl_limit); + auto_clnt_control(sp->auto_clnt, + AUTO_CLNT_CTL_HANDSHAKE, scache_clnt_handshake, + AUTO_CLNT_CTL_END); myfree(service); #ifdef CANT_WRITE_BEFORE_SENDING_FD diff --git a/postfix/src/global/trace.c b/postfix/src/global/trace.c index d451b4f45..22bdefe8b 100644 --- a/postfix/src/global/trace.c +++ b/postfix/src/global/trace.c @@ -79,6 +79,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -121,6 +126,7 @@ int trace_append(int flags, const char *id, MSG_STATS *stats, my_dsn.reason = vstring_str(why); if (mail_command_client(MAIL_CLASS_PRIVATE, var_trace_service, + MAIL_ATTR_PROTO_BOUNCE, SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND), SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id), @@ -145,6 +151,7 @@ int trace_flush(int flags, const char *queue, const char *id, const char *dsn_envid, int dsn_ret) { if (mail_command_client(MAIL_CLASS_PRIVATE, var_trace_service, + MAIL_ATTR_PROTO_BOUNCE, SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_TRACE), SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue), diff --git a/postfix/src/global/verify_clnt.c b/postfix/src/global/verify_clnt.c index 131ca1cc7..bda4eb0b3 100644 --- a/postfix/src/global/verify_clnt.c +++ b/postfix/src/global/verify_clnt.c @@ -56,6 +56,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -80,6 +85,15 @@ CLNT_STREAM *vrfy_clnt; +/* verify_clnt_handshake - receive server protocol announcement */ + +static int verify_clnt_handshake(VSTREAM *stream) +{ + return (attr_scan(stream, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_VERIFY), + ATTR_TYPE_END)); +} + /* verify_clnt_init - initialize */ static void verify_clnt_init(void) @@ -87,7 +101,8 @@ static void verify_clnt_init(void) if (vrfy_clnt != 0) msg_panic("verify_clnt_init: multiple initialization"); vrfy_clnt = clnt_stream_create(MAIL_CLASS_PRIVATE, var_verify_service, - var_ipc_idle_limit, var_ipc_ttl_limit); + var_ipc_idle_limit, var_ipc_ttl_limit, + verify_clnt_handshake); } /* verify_clnt_query - request address verification status */ @@ -111,10 +126,11 @@ int verify_clnt_query(const char *addr, int *addr_status, VSTRING *why) stream = clnt_stream_access(vrfy_clnt); errno = 0; count += 1; - if (attr_print(stream, ATTR_FLAG_NONE, - SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_QUERY), - SEND_ATTR_STR(MAIL_ATTR_ADDR, addr), - ATTR_TYPE_END) != 0 + if (stream == 0 + || attr_print(stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_QUERY), + SEND_ATTR_STR(MAIL_ATTR_ADDR, addr), + ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_MISSING, RECV_ATTR_INT(MAIL_ATTR_STATUS, &request_status), @@ -153,12 +169,13 @@ int verify_clnt_update(const char *addr, int addr_status, const char *why) for (;;) { stream = clnt_stream_access(vrfy_clnt); errno = 0; - if (attr_print(stream, ATTR_FLAG_NONE, - SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_UPDATE), - SEND_ATTR_STR(MAIL_ATTR_ADDR, addr), - SEND_ATTR_INT(MAIL_ATTR_ADDR_STATUS, addr_status), - SEND_ATTR_STR(MAIL_ATTR_WHY, why), - ATTR_TYPE_END) != 0 + if (stream == 0 + || attr_print(stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_UPDATE), + SEND_ATTR_STR(MAIL_ATTR_ADDR, addr), + SEND_ATTR_INT(MAIL_ATTR_ADDR_STATUS, addr_status), + SEND_ATTR_STR(MAIL_ATTR_WHY, why), + ATTR_TYPE_END) != 0 || attr_scan(stream, ATTR_FLAG_MISSING, RECV_ATTR_INT(MAIL_ATTR_STATUS, &request_status), ATTR_TYPE_END) != 1) { diff --git a/postfix/src/local/forward.c b/postfix/src/local/forward.c index 14367af01..722dcf712 100644 --- a/postfix/src/local/forward.c +++ b/postfix/src/local/forward.c @@ -146,6 +146,7 @@ static FORWARD_INFO *forward_open(DELIVER_REQUEST *request, const char *sender) } close_on_exec(vstream_fileno(cleanup), CLOSE_ON_EXEC); if (attr_scan(cleanup, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP), RECV_ATTR_STR(MAIL_ATTR_QUEUEID, buffer), ATTR_TYPE_END) != 1) { vstream_fclose(cleanup); diff --git a/postfix/src/master/event_server.c b/postfix/src/master/event_server.c index 0e750c0d9..9f81fc672 100644 --- a/postfix/src/master/event_server.c +++ b/postfix/src/master/event_server.c @@ -273,7 +273,6 @@ static unsigned event_server_generation; static void (*event_server_pre_disconn) (VSTREAM *, char *, char **); static void (*event_server_slow_exit) (char *, char **); static int event_server_watchdog = 1000; -static int event_server_saved_flags; /* event_server_exit - normal termination */ @@ -373,8 +372,7 @@ void event_server_disconnect(VSTREAM *stream) static void event_server_execute(int unused_event, void *context) { VSTREAM *stream = (VSTREAM *) context; - HTABLE *attr = (vstream_flags(stream) == event_server_saved_flags ? - (HTABLE *) vstream_context(stream) : 0); + HTABLE *attr = (HTABLE *) vstream_context(stream); if (event_server_lock != 0 && myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK, @@ -432,7 +430,6 @@ static void event_server_wakeup(int fd, HTABLE *attr) CA_VSTREAM_CTL_END); myfree(tmp); timed_ipc_setup(stream); - event_server_saved_flags = vstream_flags(stream); if (event_server_in_flow_delay && mail_flow_get(1) < 0) event_request_timer(event_server_execute, (void *) stream, var_in_flow_delay); diff --git a/postfix/src/master/mail_server.h b/postfix/src/master/mail_server.h index 7300b3f01..93703daf7 100644 --- a/postfix/src/master/mail_server.h +++ b/postfix/src/master/mail_server.h @@ -12,6 +12,7 @@ * Utility library. */ #include +#include /* * Global library. @@ -45,11 +46,13 @@ #define MAIL_SERVER_SLOW_EXIT 21 #define MAIL_SERVER_BOUNCE_INIT 22 #define MAIL_SERVER_RETIRE_ME 23 +#define MAIL_SERVER_POST_ACCEPT 24 typedef void (*MAIL_SERVER_INIT_FN) (char *, char **); typedef int (*MAIL_SERVER_LOOP_FN) (char *, char **); typedef void (*MAIL_SERVER_EXIT_FN) (char *, char **); typedef void (*MAIL_SERVER_ACCEPT_FN) (char *, char **); +typedef void (*MAIL_SERVER_POST_ACCEPT_FN) (VSTREAM *, char *, char **, HTABLE *); typedef void (*MAIL_SERVER_DISCONN_FN) (VSTREAM *, char *, char **); typedef void (*MAIL_SERVER_SLOW_EXIT_FN) (char *, char **); @@ -67,6 +70,7 @@ typedef void (*MAIL_SERVER_SLOW_EXIT_FN) (char *, char **); #define CA_MAIL_SERVER_LOOP(v) MAIL_SERVER_LOOP, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_LOOP_FN, (v)) #define CA_MAIL_SERVER_EXIT(v) MAIL_SERVER_EXIT, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_EXIT_FN, (v)) #define CA_MAIL_SERVER_PRE_ACCEPT(v) MAIL_SERVER_PRE_ACCEPT, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_ACCEPT_FN, (v)) +#define CA_MAIL_SERVER_POST_ACCEPT(v) MAIL_SERVER_POST_ACCEPT, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_POST_ACCEPT_FN, (v)) #define CA_MAIL_SERVER_SOLITARY MAIL_SERVER_SOLITARY #define CA_MAIL_SERVER_UNLIMITED MAIL_SERVER_UNLIMITED #define CA_MAIL_SERVER_PRE_DISCONN(v) MAIL_SERVER_PRE_DISCONN, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_DISCONN_FN, (v)) @@ -83,6 +87,7 @@ CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_INIT_FN); CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_EXIT_FN); CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_DISCONN_FN); CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_ACCEPT_FN); +CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_POST_ACCEPT_FN); CHECK_PTR_HELPER_DCL(MAIL_SERVER, int); CHECK_PTR_HELPER_DCL(MAIL_SERVER, char); CHECK_PPTR_HELPER_DCL(MAIL_SERVER, char); diff --git a/postfix/src/master/multi_server.c b/postfix/src/master/multi_server.c index 465a9e26f..fbdaf34ce 100644 --- a/postfix/src/master/multi_server.c +++ b/postfix/src/master/multi_server.c @@ -35,9 +35,6 @@ /* function is run after the program has optionally dropped its /* privileges. This function should not attempt to preserve state /* across calls. The stream initial state is non-blocking mode. -/* Optional connection attributes are provided as a hash that -/* is attached as stream context. NOTE: the attributes are -/* destroyed after this function is called. /* The service name argument corresponds to the service name in the /* master.cf file. /* The argv argument specifies command-line arguments left over @@ -114,6 +111,14 @@ /* Function to be executed prior to accepting a new connection. /* .sp /* Only the last instance of this parameter type is remembered. +/* .IP "CA_MAIL_SERVER_POST_ACCEPT(void *(VSTREAM *stream, char *service_name, char **argv, HTABLE *attr))" +/* Function to be executed after accepting a new connection. +/* The stream, service_name and argv argunents are the same +/* as with the "service" argument. The attr argument is null +/* or a pointer to a table with 'pass' connection attributes. +/* The table is destroyed after the function returns. +/* .sp +/* Only the last instance of this parameter type is remembered. /* .IP "CA_MAIL_SERVER_PRE_DISCONN(VSTREAM *, char *service_name, char **argv)" /* A pointer to a function that is called /* by the multi_server_disconnect() function (see below). @@ -250,11 +255,11 @@ static char **multi_server_argv; static void (*multi_server_accept) (int, void *); static void (*multi_server_onexit) (char *, char **); static void (*multi_server_pre_accept) (char *, char **); +static void (*multi_server_post_accept) (VSTREAM *, char *, char **, HTABLE *); static VSTREAM *multi_server_lock; static int multi_server_in_flow_delay; static unsigned multi_server_generation; static void (*multi_server_pre_disconn) (VSTREAM *, char *, char **); -static int multi_server_saved_flags; /* multi_server_exit - normal termination */ @@ -336,8 +341,6 @@ void multi_server_disconnect(VSTREAM *stream) static void multi_server_execute(int unused_event, void *context) { VSTREAM *stream = (VSTREAM *) context; - HTABLE *attr = (vstream_flags(stream) == multi_server_saved_flags ? - (HTABLE *) vstream_context(stream) : 0); if (multi_server_lock != 0 && myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK, @@ -358,8 +361,6 @@ static void multi_server_execute(int unused_event, void *context) } else { multi_server_disconnect(stream); } - if (attr) - htable_free(attr, myfree); } /* multi_server_enable_read - enable read events */ @@ -404,16 +405,20 @@ static void multi_server_wakeup(int fd, HTABLE *attr) tmp = concatenate(multi_server_name, " socket", (char *) 0); vstream_control(stream, CA_VSTREAM_CTL_PATH(tmp), - CA_VSTREAM_CTL_CONTEXT((void *) attr), CA_VSTREAM_CTL_END); myfree(tmp); timed_ipc_setup(stream); - multi_server_saved_flags = vstream_flags(stream); if (multi_server_in_flow_delay && mail_flow_get(1) < 0) event_request_timer(multi_server_enable_read, (void *) stream, var_in_flow_delay); else multi_server_enable_read(0, (void *) stream); + if (multi_server_post_accept) + multi_server_post_accept(stream, multi_server_name, multi_server_argv, attr); + else if (attr) + msg_warn("service ignores 'pass' connection attributes"); + if (attr) + htable_free(attr, myfree); } /* multi_server_accept_local - accept client connection request */ @@ -746,6 +751,9 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) case MAIL_SERVER_PRE_ACCEPT: multi_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN); break; + case MAIL_SERVER_POST_ACCEPT: + multi_server_post_accept = va_arg(ap, MAIL_SERVER_POST_ACCEPT_FN); + break; case MAIL_SERVER_PRE_DISCONN: multi_server_pre_disconn = va_arg(ap, MAIL_SERVER_DISCONN_FN); break; diff --git a/postfix/src/oqmgr/qmgr_deliver.c b/postfix/src/oqmgr/qmgr_deliver.c index d8ec7bb00..16fbc9e2a 100644 --- a/postfix/src/oqmgr/qmgr_deliver.c +++ b/postfix/src/oqmgr/qmgr_deliver.c @@ -109,12 +109,12 @@ static int qmgr_deliver_initial_reply(VSTREAM *stream) msg_warn("%s: premature disconnect", VSTREAM_PATH(stream)); return (DELIVER_STAT_CRASH); } else if (attr_scan(stream, ATTR_FLAG_STRICT, - RECV_ATTR_INT(MAIL_ATTR_STATUS, &stat), - ATTR_TYPE_END) != 1) { + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER), + ATTR_TYPE_END) != 0) { msg_warn("%s: malformed response", VSTREAM_PATH(stream)); - return (DELIVER_STAT_CRASH); + return (DELIVER_STAT_DEFER); } else { - return (stat ? DELIVER_STAT_DEFER : 0); + return (0); } } diff --git a/postfix/src/pickup/pickup.c b/postfix/src/pickup/pickup.c index 157970dbd..4a77a476e 100644 --- a/postfix/src/pickup/pickup.c +++ b/postfix/src/pickup/pickup.c @@ -488,6 +488,7 @@ static int pickup_file(PICKUP_INFO *info) cleanup = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service); if (attr_scan(cleanup, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP), RECV_ATTR_STR(MAIL_ATTR_QUEUEID, buf), ATTR_TYPE_END) != 1 || attr_print(cleanup, ATTR_FLAG_NONE, diff --git a/postfix/src/postconf/Makefile.in b/postfix/src/postconf/Makefile.in index dc382fe1f..33598bc02 100644 --- a/postfix/src/postconf/Makefile.in +++ b/postfix/src/postconf/Makefile.in @@ -9,8 +9,8 @@ OBJS = postconf.o postconf_builtin.o postconf_edit.o postconf_main.o \ postconf_lookup.o postconf_match.o postconf_print.o HDRS = postconf.h TESTSRC = -DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) -CFLAGS = $(DEBUG) $(OPT) $(DEFS) -DLEGACY_DBMS_SUPPORT +DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) -DLEGACY_DBMS_SUPPORT +CFLAGS = $(DEBUG) $(OPT) $(DEFS) TESTPROG= MAKES = bool_table.h bool_vars.h int_table.h int_vars.h str_table.h \ str_vars.h time_table.h time_vars.h raw_table.h raw_vars.h \ diff --git a/postfix/src/postdrop/postdrop.c b/postfix/src/postdrop/postdrop.c index ca7846431..7f32c95f2 100644 --- a/postfix/src/postdrop/postdrop.c +++ b/postfix/src/postdrop/postdrop.c @@ -381,6 +381,7 @@ int main(int argc, char **argv) dst = mail_stream_file(MAIL_QUEUE_MAILDROP, MAIL_CLASS_PUBLIC, var_pickup_service, 0444); attr_print(VSTREAM_OUT, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_POSTDROP), SEND_ATTR_STR(MAIL_ATTR_QUEUEID, dst->id), ATTR_TYPE_END); vstream_fflush(VSTREAM_OUT); diff --git a/postfix/src/postlogd/Makefile.in b/postfix/src/postlogd/Makefile.in index bdf7d050f..21fad76dd 100644 --- a/postfix/src/postlogd/Makefile.in +++ b/postfix/src/postlogd/Makefile.in @@ -61,14 +61,19 @@ depend: $(MAKES) # do not edit below this line - it is generated by 'make depend' postlogd.o: ../../include/check_arg.h +postlogd.o: ../../include/htable.h postlogd.o: ../../include/logwriter.h postlogd.o: ../../include/mail_conf.h postlogd.o: ../../include/mail_params.h postlogd.o: ../../include/mail_server.h +postlogd.o: ../../include/mail_task.h postlogd.o: ../../include/mail_version.h +postlogd.o: ../../include/maillog_client.h postlogd.o: ../../include/msg.h postlogd.o: ../../include/msg_logger.h +postlogd.o: ../../include/stringops.h postlogd.o: ../../include/sys_defs.h postlogd.o: ../../include/vbuf.h postlogd.o: ../../include/vstream.h +postlogd.o: ../../include/vstring.h postlogd.o: postlogd.c diff --git a/postfix/src/postqueue/.indent.pro b/postfix/src/postqueue/.indent.pro new file mode 120000 index 000000000..5c837eca6 --- /dev/null +++ b/postfix/src/postqueue/.indent.pro @@ -0,0 +1 @@ +../../.indent.pro \ No newline at end of file diff --git a/postfix/src/postqueue/postqueue.c b/postfix/src/postqueue/postqueue.c index 7efc01ff9..937176383 100644 --- a/postfix/src/postqueue/postqueue.c +++ b/postfix/src/postqueue/postqueue.c @@ -341,6 +341,26 @@ static const CONFIG_STR_TABLE str_table[] = { 0, }; +/* showq_client - run the appropriate showq protocol client */ + +static void showq_client(int mode, VSTREAM *showq) +{ + if (attr_scan(showq, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_SHOWQ), + ATTR_TYPE_END) != 0) + msg_fatal_status(EX_SOFTWARE, "malformed showq server response"); + switch (mode) { + case PQ_MODE_MAILQ_LIST: + showq_compat(showq); + break; + case PQ_MODE_JSON_LIST: + showq_json(showq); + break; + default: + msg_panic("show_queue: unknown mode %d", mode); + } +} + /* show_queue - show queue status */ static void show_queue(int mode) @@ -361,16 +381,7 @@ static void show_queue(int mode) * Connect to the show queue service. */ if ((showq = mail_connect(MAIL_CLASS_PUBLIC, var_showq_service, BLOCKING)) != 0) { - switch (mode) { - case PQ_MODE_MAILQ_LIST: - showq_compat(showq); - break; - case PQ_MODE_JSON_LIST: - showq_json(showq); - break; - default: - msg_panic("show_queue: unknown mode %d", mode); - } + showq_client(mode, showq); if (vstream_fclose(showq)) msg_warn("close: %m"); } @@ -407,23 +418,14 @@ static void show_queue(int mode) CA_VSTREAM_POPEN_END)) == 0) { stat = -1; } else { - switch (mode) { - case PQ_MODE_MAILQ_LIST: - showq_compat(showq); - break; - case PQ_MODE_JSON_LIST: - showq_json(showq); - break; - default: - msg_panic("show_queue: unknown mode %d", mode); - } + showq_client(mode, showq); stat = vstream_pclose(showq); } argv_free(argv); + myfree(showq_path); if (stat != 0) msg_fatal_status(stat < 0 ? EX_OSERR : EX_SOFTWARE, "Error running %s", showq_path); - myfree(showq_path); } /* diff --git a/postfix/src/postscreen/postscreen_starttls.c b/postfix/src/postscreen/postscreen_starttls.c index 3056d7130..67dd3c1e1 100644 --- a/postfix/src/postscreen/postscreen_starttls.c +++ b/postfix/src/postscreen/postscreen_starttls.c @@ -88,6 +88,22 @@ typedef struct { static char *psc_tlsp_service = 0; +/* Resume the dummy SMTP engine after an event handling error */ + +#define PSC_STARTTLS_EVENT_ERR_RESUME_RETURN() do { \ + event_disable_readwrite(vstream_fileno(tlsproxy_stream)); \ + PSC_STARTTLS_EVENT_RESUME_RETURN(starttls_state); \ + } while (0); + +/* Resume the dummy SMTP engine, possibly after swapping streams */ + +#define PSC_STARTTLS_EVENT_RESUME_RETURN(starttls_state) do { \ + vstream_fclose(tlsproxy_stream); \ + starttls_state->resume_event(event, (void *) smtp_state); \ + myfree((void *) starttls_state); \ + return; \ + } while (0) + /* psc_starttls_finish - complete negotiation with TLS proxy */ static void psc_starttls_finish(int event, void *context) @@ -130,10 +146,11 @@ static void psc_starttls_finish(int event, void *context) * The TLS proxy reports that the TLS engine is not available (due to * configuration error, or other causes). */ - event_disable_readwrite(vstream_fileno(tlsproxy_stream)); - vstream_fclose(tlsproxy_stream); + msg_warn("%s receiving status from %s service", + event == EVENT_TIME ? "timeout" : "problem", psc_tlsp_service); PSC_SEND_REPLY(smtp_state, "454 4.7.0 TLS not available due to local problem\r\n"); + PSC_STARTTLS_EVENT_ERR_RESUME_RETURN(); } /* @@ -145,13 +162,10 @@ static void psc_starttls_finish(int event, void *context) /* * Some error: drop the TLS proxy stream. */ - msg_warn("%s sending file handle to %s service", - event == EVENT_TIME ? "timeout" : "problem", - psc_tlsp_service); - event_disable_readwrite(vstream_fileno(tlsproxy_stream)); - vstream_fclose(tlsproxy_stream); + msg_warn("problem sending file handle to %s service", psc_tlsp_service); PSC_SEND_REPLY(smtp_state, "454 4.7.0 TLS not available due to local problem\r\n"); + PSC_STARTTLS_EVENT_ERR_RESUME_RETURN(); } /* @@ -163,9 +177,10 @@ static void psc_starttls_finish(int event, void *context) PSC_SEND_REPLY(smtp_state, "220 2.0.0 Ready to start TLS\r\n"); /* - * Replace our SMTP client stream by the TLS proxy stream. Once the - * TLS handshake is done, the TLS proxy will deliver plaintext SMTP - * commands to postscreen(8). + * Swap the SMTP client stream and the TLS proxy stream, and close + * the direct connection to the SMTP client. The TLS proxy will talk + * directly to the SMTP client, and once the TLS handshake is + * completed, the TLS proxy will talk plaintext to postscreen(8). * * Swap the file descriptors from under the VSTREAM so that we don't * have to worry about loss of user-configurable VSTREAM attributes. @@ -174,15 +189,83 @@ static void psc_starttls_finish(int event, void *context) vstream_control(smtp_state->smtp_client_stream, CA_VSTREAM_CTL_SWAP_FD(tlsproxy_stream), CA_VSTREAM_CTL_END); - vstream_fclose(tlsproxy_stream); /* direct-to-client stream! */ smtp_state->flags |= PSC_STATE_FLAG_USING_TLS; + PSC_STARTTLS_EVENT_RESUME_RETURN(starttls_state); + } +} + +/* psc_starttls_first - start negotiation with TLS proxy */ + +static void psc_starttls_first(int event, void *context) +{ + const char *myname = "psc_starttls_first"; + PSC_STARTTLS *starttls_state = (PSC_STARTTLS *) context; + PSC_STATE *smtp_state = starttls_state->smtp_state; + VSTREAM *tlsproxy_stream = starttls_state->tlsproxy_stream; + static VSTRING *remote_endpt = 0; + + if (msg_verbose) + msg_info("%s: receive server protocol on proxy socket %d" + " for smtp socket %d from [%s]:%s flags=%s", + myname, vstream_fileno(tlsproxy_stream), + vstream_fileno(smtp_state->smtp_client_stream), + smtp_state->smtp_client_addr, smtp_state->smtp_client_port, + psc_print_state_flags(smtp_state->flags, myname)); + + /* + * We leave read-event notification enabled on the postscreen to TLS + * proxy stream, to avoid two kqueue/epoll/etc. system calls: one here, + * and one when resuming the dummy SMTP engine. + */ + if (event != EVENT_TIME) + event_cancel_timer(psc_starttls_first, (void *) starttls_state); + + /* + * Receive and verify the server protocol. + */ + if (event != EVENT_READ + || attr_scan(tlsproxy_stream, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSPROXY), + ATTR_TYPE_END) != 0) { + msg_warn("%s receiving %s attribute from %s service: %m", + event == EVENT_TIME ? "timeout" : "problem", + MAIL_ATTR_PROTO, psc_tlsp_service); + PSC_SEND_REPLY(smtp_state, + "454 4.7.0 TLS not available due to local problem\r\n"); + PSC_STARTTLS_EVENT_ERR_RESUME_RETURN(); } /* - * Resume the postscreen(8) dummy SMTP engine and clean up. + * Send the data attributes now, and send the client file descriptor in a + * later transaction. We report all errors asynchronously, to avoid + * having to maintain multiple error delivery paths. + * + * XXX The formatted endpoint should be a state member. Then, we can + * simplify all the format strings throughout the program. */ - starttls_state->resume_event(event, (void *) smtp_state); - myfree((void *) starttls_state); + if (remote_endpt == 0) + remote_endpt = vstring_alloc(20); + vstring_sprintf(remote_endpt, "[%s]:%s", smtp_state->smtp_client_addr, + smtp_state->smtp_client_port); + attr_print(tlsproxy_stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, STR(remote_endpt)), + SEND_ATTR_INT(TLS_ATTR_FLAGS, TLS_PROXY_FLAG_ROLE_SERVER), + SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit), + SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit), + SEND_ATTR_STR(TLS_ATTR_SERVERID, MAIL_SERVICE_SMTPD), /* XXX */ + ATTR_TYPE_END); + if (vstream_fflush(tlsproxy_stream) != 0) { + msg_warn("error sending request to %s service: %m", psc_tlsp_service); + PSC_SEND_REPLY(smtp_state, + "454 4.7.0 TLS not available due to local problem\r\n"); + PSC_STARTTLS_EVENT_ERR_RESUME_RETURN(); + } + + /* + * Set up a read event for the next phase of the TLS proxy handshake. + */ + PSC_READ_EVENT_REQUEST(vstream_fileno(tlsproxy_stream), psc_starttls_finish, + (void *) starttls_state, TLSPROXY_INIT_TIMEOUT); } /* psc_starttls_open - open negotiations with TLS proxy */ @@ -193,12 +276,10 @@ void psc_starttls_open(PSC_STATE *smtp_state, EVENT_NOTIFY_FN resume_event) PSC_STARTTLS *starttls_state; VSTREAM *tlsproxy_stream; int fd; - static VSTRING *remote_endpt = 0; if (psc_tlsp_service == 0) { psc_tlsp_service = concatenate(MAIL_CLASS_PRIVATE "/", var_tlsproxy_service, (char *) 0); - remote_endpt = vstring_alloc(20); } /* @@ -213,38 +294,16 @@ void psc_starttls_open(PSC_STATE *smtp_state, EVENT_NOTIFY_FN resume_event) return; } if (msg_verbose) - msg_info("%s: send client name/address on proxy socket %d" + msg_info("%s: connecting to proxy socket %d" " for smtp socket %d from [%s]:%s flags=%s", myname, fd, vstream_fileno(smtp_state->smtp_client_stream), smtp_state->smtp_client_addr, smtp_state->smtp_client_port, psc_print_state_flags(smtp_state->flags, myname)); - /* - * Initial handshake. Send the data attributes now, and send the client - * file descriptor in a later transaction. We report all errors - * asynchronously, to avoid having to maintain multiple delivery paths. - * - * XXX The formatted endpoint should be a state member. Then, we can - * simplify all the format strings throughout the program. - */ tlsproxy_stream = vstream_fdopen(fd, O_RDWR); - vstring_sprintf(remote_endpt, "[%s]:%s", smtp_state->smtp_client_addr, - smtp_state->smtp_client_port); - attr_print(tlsproxy_stream, ATTR_FLAG_NONE, - SEND_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, STR(remote_endpt)), - SEND_ATTR_INT(TLS_ATTR_FLAGS, TLS_PROXY_FLAG_ROLE_SERVER), - SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit), - SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit), - SEND_ATTR_STR(TLS_ATTR_SERVERID, MAIL_SERVICE_SMTPD), /* XXX */ - ATTR_TYPE_END); - if (vstream_fflush(tlsproxy_stream) != 0) { - msg_warn("error sending request to %s service: %m", psc_tlsp_service); - vstream_fclose(tlsproxy_stream); - PSC_SEND_REPLY(smtp_state, - "454 4.7.0 TLS not available due to local problem\r\n"); - event_request_timer(resume_event, (void *) smtp_state, 0); - return; - } + vstream_control(tlsproxy_stream, + VSTREAM_CTL_PATH, psc_tlsp_service, + VSTREAM_CTL_END); /* * Set up a read event for the next phase of the TLS proxy handshake. @@ -253,6 +312,6 @@ void psc_starttls_open(PSC_STATE *smtp_state, EVENT_NOTIFY_FN resume_event) starttls_state->tlsproxy_stream = tlsproxy_stream; starttls_state->resume_event = resume_event; starttls_state->smtp_state = smtp_state; - PSC_READ_EVENT_REQUEST(vstream_fileno(tlsproxy_stream), psc_starttls_finish, + PSC_READ_EVENT_REQUEST(vstream_fileno(tlsproxy_stream), psc_starttls_first, (void *) starttls_state, TLSPROXY_INIT_TIMEOUT); } diff --git a/postfix/src/proxymap/proxymap.c b/postfix/src/proxymap/proxymap.c index e486c4685..5783c99a1 100644 --- a/postfix/src/proxymap/proxymap.c +++ b/postfix/src/proxymap/proxymap.c @@ -745,6 +745,21 @@ static void pre_accept(char *unused_name, char **unused_argv) } } +/* post_accept - anounce our protocol name */ + +static void post_accept(VSTREAM *stream, char *unused_name, char **unused_argv, + HTABLE *unused_attr) +{ + + /* + * Announce the protocol. + */ + attr_print(stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_PROXYMAP), + ATTR_TYPE_END); + (void) vstream_fflush(stream); +} + MAIL_VERSION_STAMP_DECLARE; /* main - pass control to the multi-threaded skeleton */ @@ -782,6 +797,7 @@ int main(int argc, char **argv) CA_MAIL_SERVER_STR_TABLE(str_table), CA_MAIL_SERVER_POST_INIT(post_jail_init), CA_MAIL_SERVER_PRE_ACCEPT(pre_accept), + CA_MAIL_SERVER_POST_ACCEPT(post_accept), /* XXX CA_MAIL_SERVER_SOLITARY if proxywrite */ 0); } diff --git a/postfix/src/qmgr/qmgr_deliver.c b/postfix/src/qmgr/qmgr_deliver.c index fe4cf0ca5..c87f6c6f3 100644 --- a/postfix/src/qmgr/qmgr_deliver.c +++ b/postfix/src/qmgr/qmgr_deliver.c @@ -108,18 +108,16 @@ int qmgr_deliver_concurrency; static int qmgr_deliver_initial_reply(VSTREAM *stream) { - int stat; - if (peekfd(vstream_fileno(stream)) < 0) { msg_warn("%s: premature disconnect", VSTREAM_PATH(stream)); return (DELIVER_STAT_CRASH); } else if (attr_scan(stream, ATTR_FLAG_STRICT, - RECV_ATTR_INT(MAIL_ATTR_STATUS, &stat), - ATTR_TYPE_END) != 1) { + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER), + ATTR_TYPE_END) != 0) { msg_warn("%s: malformed response", VSTREAM_PATH(stream)); - return (DELIVER_STAT_CRASH); + return (DELIVER_STAT_DEFER); } else { - return (stat ? DELIVER_STAT_DEFER : 0); + return (0); } } diff --git a/postfix/src/scache/scache.c b/postfix/src/scache/scache.c index d06cfcad1..85f32effa 100644 --- a/postfix/src/scache/scache.c +++ b/postfix/src/scache/scache.c @@ -544,6 +544,21 @@ static void post_jail_init(char *unused_name, char **unused_argv) scache_start_time = event_time(); } +/* scache_post_accept - announce our protocol */ + +static void scache_post_accept(VSTREAM *stream, char *unused_name, + char **unused_argv, HTABLE *unused_table) +{ + + /* + * Announce the protocol. + */ + attr_print(stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_SCACHE), + ATTR_TYPE_END); + (void) vstream_fflush(stream); +} + MAIL_VERSION_STAMP_DECLARE; /* main - pass control to the multi-threaded skeleton */ @@ -564,6 +579,7 @@ int main(int argc, char **argv) multi_server_main(argc, argv, scache_service, CA_MAIL_SERVER_TIME_TABLE(time_table), CA_MAIL_SERVER_POST_INIT(post_jail_init), + CA_MAIL_SERVER_POST_ACCEPT(scache_post_accept), CA_MAIL_SERVER_EXIT(scache_status_dump), CA_MAIL_SERVER_SOLITARY, 0); diff --git a/postfix/src/showq/showq.c b/postfix/src/showq/showq.c index e6ca68feb..b8dd7e994 100644 --- a/postfix/src/showq/showq.c +++ b/postfix/src/showq/showq.c @@ -360,6 +360,13 @@ static void showq_service(VSTREAM *client, char *unused_service, char **argv) if (argv[0]) msg_fatal("unexpected command-line argument: %s", argv[0]); + /* + * Protocol identification. + */ + (void) attr_print(client, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_SHOWQ), + ATTR_TYPE_END); + /* * Skip any files that have the wrong permissions. If we can't open an * existing file, assume the system is out of resources or that it is diff --git a/postfix/src/smtpd/Makefile.in b/postfix/src/smtpd/Makefile.in index e4d23b7a6..03dfd64de 100644 --- a/postfix/src/smtpd/Makefile.in +++ b/postfix/src/smtpd/Makefile.in @@ -280,7 +280,6 @@ smtpd_chat.o: ../../include/mail_params.h smtpd_chat.o: ../../include/mail_proto.h smtpd_chat.o: ../../include/mail_stream.h smtpd_chat.o: ../../include/maps.h -smtpd_chat.o: ../../include/match_list.h smtpd_chat.o: ../../include/milter.h smtpd_chat.o: ../../include/msg.h smtpd_chat.o: ../../include/myaddrinfo.h @@ -296,7 +295,6 @@ smtpd_chat.o: ../../include/smtp_reply_footer.h smtpd_chat.o: ../../include/smtp_stream.h smtpd_chat.o: ../../include/smtputf8.h smtpd_chat.o: ../../include/sock_addr.h -smtpd_chat.o: ../../include/string_list.h smtpd_chat.o: ../../include/stringops.h smtpd_chat.o: ../../include/sys_defs.h smtpd_chat.o: ../../include/tls.h @@ -400,7 +398,6 @@ smtpd_expand.o: ../../include/mac_parse.h smtpd_expand.o: ../../include/mail_params.h smtpd_expand.o: ../../include/mail_proto.h smtpd_expand.o: ../../include/mail_stream.h -smtpd_expand.o: ../../include/match_list.h smtpd_expand.o: ../../include/milter.h smtpd_expand.o: ../../include/msg.h smtpd_expand.o: ../../include/myaddrinfo.h @@ -409,7 +406,6 @@ smtpd_expand.o: ../../include/name_code.h smtpd_expand.o: ../../include/name_mask.h smtpd_expand.o: ../../include/nvtable.h smtpd_expand.o: ../../include/sock_addr.h -smtpd_expand.o: ../../include/string_list.h smtpd_expand.o: ../../include/stringops.h smtpd_expand.o: ../../include/sys_defs.h smtpd_expand.o: ../../include/tls.h @@ -428,7 +424,6 @@ smtpd_haproxy.o: ../../include/htable.h smtpd_haproxy.o: ../../include/iostuff.h smtpd_haproxy.o: ../../include/mail_params.h smtpd_haproxy.o: ../../include/mail_stream.h -smtpd_haproxy.o: ../../include/match_list.h smtpd_haproxy.o: ../../include/milter.h smtpd_haproxy.o: ../../include/msg.h smtpd_haproxy.o: ../../include/myaddrinfo.h @@ -438,7 +433,6 @@ smtpd_haproxy.o: ../../include/name_mask.h smtpd_haproxy.o: ../../include/nvtable.h smtpd_haproxy.o: ../../include/smtp_stream.h smtpd_haproxy.o: ../../include/sock_addr.h -smtpd_haproxy.o: ../../include/string_list.h smtpd_haproxy.o: ../../include/stringops.h smtpd_haproxy.o: ../../include/sys_defs.h smtpd_haproxy.o: ../../include/tls.h @@ -456,7 +450,6 @@ smtpd_milter.o: ../../include/dns.h smtpd_milter.o: ../../include/htable.h smtpd_milter.o: ../../include/mail_params.h smtpd_milter.o: ../../include/mail_stream.h -smtpd_milter.o: ../../include/match_list.h smtpd_milter.o: ../../include/milter.h smtpd_milter.o: ../../include/myaddrinfo.h smtpd_milter.o: ../../include/mymalloc.h @@ -468,7 +461,6 @@ smtpd_milter.o: ../../include/quote_flags.h smtpd_milter.o: ../../include/resolve_clnt.h smtpd_milter.o: ../../include/sock_addr.h smtpd_milter.o: ../../include/split_at.h -smtpd_milter.o: ../../include/string_list.h smtpd_milter.o: ../../include/stringops.h smtpd_milter.o: ../../include/sys_defs.h smtpd_milter.o: ../../include/tls.h @@ -491,7 +483,6 @@ smtpd_peer.o: ../../include/iostuff.h smtpd_peer.o: ../../include/mail_params.h smtpd_peer.o: ../../include/mail_proto.h smtpd_peer.o: ../../include/mail_stream.h -smtpd_peer.o: ../../include/match_list.h smtpd_peer.o: ../../include/milter.h smtpd_peer.o: ../../include/msg.h smtpd_peer.o: ../../include/myaddrinfo.h @@ -501,7 +492,6 @@ smtpd_peer.o: ../../include/name_mask.h smtpd_peer.o: ../../include/nvtable.h smtpd_peer.o: ../../include/sock_addr.h smtpd_peer.o: ../../include/split_at.h -smtpd_peer.o: ../../include/string_list.h smtpd_peer.o: ../../include/stringops.h smtpd_peer.o: ../../include/sys_defs.h smtpd_peer.o: ../../include/tls.h @@ -525,7 +515,6 @@ smtpd_proxy.o: ../../include/mail_params.h smtpd_proxy.o: ../../include/mail_proto.h smtpd_proxy.o: ../../include/mail_queue.h smtpd_proxy.o: ../../include/mail_stream.h -smtpd_proxy.o: ../../include/match_list.h smtpd_proxy.o: ../../include/milter.h smtpd_proxy.o: ../../include/msg.h smtpd_proxy.o: ../../include/myaddrinfo.h @@ -537,7 +526,6 @@ smtpd_proxy.o: ../../include/rec_type.h smtpd_proxy.o: ../../include/record.h smtpd_proxy.o: ../../include/smtp_stream.h smtpd_proxy.o: ../../include/sock_addr.h -smtpd_proxy.o: ../../include/string_list.h smtpd_proxy.o: ../../include/stringops.h smtpd_proxy.o: ../../include/sys_defs.h smtpd_proxy.o: ../../include/tls.h @@ -607,7 +595,6 @@ smtpd_sasl_proto.o: ../../include/mail_error.h smtpd_sasl_proto.o: ../../include/mail_params.h smtpd_sasl_proto.o: ../../include/mail_proto.h smtpd_sasl_proto.o: ../../include/mail_stream.h -smtpd_sasl_proto.o: ../../include/match_list.h smtpd_sasl_proto.o: ../../include/milter.h smtpd_sasl_proto.o: ../../include/msg.h smtpd_sasl_proto.o: ../../include/myaddrinfo.h @@ -616,7 +603,6 @@ smtpd_sasl_proto.o: ../../include/name_code.h smtpd_sasl_proto.o: ../../include/name_mask.h smtpd_sasl_proto.o: ../../include/nvtable.h smtpd_sasl_proto.o: ../../include/sock_addr.h -smtpd_sasl_proto.o: ../../include/string_list.h smtpd_sasl_proto.o: ../../include/stringops.h smtpd_sasl_proto.o: ../../include/sys_defs.h smtpd_sasl_proto.o: ../../include/tls.h @@ -641,7 +627,6 @@ smtpd_state.o: ../../include/mail_error.h smtpd_state.o: ../../include/mail_params.h smtpd_state.o: ../../include/mail_proto.h smtpd_state.o: ../../include/mail_stream.h -smtpd_state.o: ../../include/match_list.h smtpd_state.o: ../../include/milter.h smtpd_state.o: ../../include/msg.h smtpd_state.o: ../../include/myaddrinfo.h @@ -650,7 +635,6 @@ smtpd_state.o: ../../include/name_code.h smtpd_state.o: ../../include/name_mask.h smtpd_state.o: ../../include/nvtable.h smtpd_state.o: ../../include/sock_addr.h -smtpd_state.o: ../../include/string_list.h smtpd_state.o: ../../include/sys_defs.h smtpd_state.o: ../../include/tls.h smtpd_state.o: ../../include/vbuf.h @@ -676,7 +660,6 @@ smtpd_xforward.o: ../../include/htable.h smtpd_xforward.o: ../../include/iostuff.h smtpd_xforward.o: ../../include/mail_proto.h smtpd_xforward.o: ../../include/mail_stream.h -smtpd_xforward.o: ../../include/match_list.h smtpd_xforward.o: ../../include/milter.h smtpd_xforward.o: ../../include/msg.h smtpd_xforward.o: ../../include/myaddrinfo.h @@ -685,7 +668,6 @@ smtpd_xforward.o: ../../include/name_code.h smtpd_xforward.o: ../../include/name_mask.h smtpd_xforward.o: ../../include/nvtable.h smtpd_xforward.o: ../../include/sock_addr.h -smtpd_xforward.o: ../../include/string_list.h smtpd_xforward.o: ../../include/sys_defs.h smtpd_xforward.o: ../../include/tls.h smtpd_xforward.o: ../../include/vbuf.h diff --git a/postfix/src/spawn/Makefile.in b/postfix/src/spawn/Makefile.in index 5097697d5..74c6d6d18 100644 --- a/postfix/src/spawn/Makefile.in +++ b/postfix/src/spawn/Makefile.in @@ -62,6 +62,7 @@ depend: $(MAKES) spawn.o: ../../include/argv.h spawn.o: ../../include/check_arg.h spawn.o: ../../include/dict.h +spawn.o: ../../include/htable.h spawn.o: ../../include/mail_conf.h spawn.o: ../../include/mail_params.h spawn.o: ../../include/mail_parm_split.h diff --git a/postfix/src/tls/tls_mgr.c b/postfix/src/tls/tls_mgr.c index b2bdcdc11..b69ddf6c8 100644 --- a/postfix/src/tls/tls_mgr.c +++ b/postfix/src/tls/tls_mgr.c @@ -107,6 +107,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -144,6 +149,15 @@ static ATTR_CLNT *tls_mgr; +/* tls_mgr_handshake - receive server protocol announcement */ + +static int tls_mgr_handshake(VSTREAM *stream) +{ + return (attr_scan(stream, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSMGR), + ATTR_TYPE_END)); +} + /* tls_mgr_open - create client handle */ static void tls_mgr_open(void) @@ -168,6 +182,7 @@ static void tls_mgr_open(void) attr_clnt_control(tls_mgr, ATTR_CLNT_CTL_PROTO, attr_vprint, attr_vscan, + ATTR_CLNT_CTL_HANDSHAKE, tls_mgr_handshake, ATTR_CLNT_CTL_END); } diff --git a/postfix/src/tls/tls_proxy_clnt.c b/postfix/src/tls/tls_proxy_clnt.c index beeafa7f1..ca6a2e407 100644 --- a/postfix/src/tls/tls_proxy_clnt.c +++ b/postfix/src/tls/tls_proxy_clnt.c @@ -187,6 +187,14 @@ VSTREAM *tls_proxy_open(const char *service, int flags, * remote peer file descriptor in a later transaction. */ tlsproxy_stream = vstream_fdopen(fd, O_RDWR); + if (attr_scan(tlsproxy_stream, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSPROXY), + ATTR_TYPE_END) != 0) { + msg_warn("error receiving %s service initial response", + STR(tlsproxy_service)); + vstream_fclose(tlsproxy_stream); + return (0); + } vstring_sprintf(remote_endpt, "[%s]:%s", peer_addr, peer_port); attr_print(tlsproxy_stream, ATTR_FLAG_NONE, SEND_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, STR(remote_endpt)), diff --git a/postfix/src/tlsmgr/tlsmgr.c b/postfix/src/tlsmgr/tlsmgr.c index db48ffbc2..3b9373393 100644 --- a/postfix/src/tlsmgr/tlsmgr.c +++ b/postfix/src/tlsmgr/tlsmgr.c @@ -1004,6 +1004,22 @@ static void tlsmgr_post_init(char *unused_name, char **unused_argv) tlsmgr_cache_run_event(NULL_EVENT, (void *) ent); } +/* tlsmgr_post_accept - announce our protocol */ + +static void tlsmgr_post_accept(VSTREAM *stream, char *unused_name, + char **unused_argv, HTABLE *unused_table) +{ + + /* + * Announce the protocol. + */ + attr_print(stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSMGR), + ATTR_TYPE_END); + (void) vstream_fflush(stream); +} + + /* tlsmgr_before_exit - save PRNG state before exit */ static void tlsmgr_before_exit(char *unused_service_name, char **unused_argv) @@ -1061,6 +1077,7 @@ int main(int argc, char **argv) CA_MAIL_SERVER_STR_TABLE(str_table), CA_MAIL_SERVER_PRE_INIT(tlsmgr_pre_init), CA_MAIL_SERVER_POST_INIT(tlsmgr_post_init), + CA_MAIL_SERVER_POST_ACCEPT(tlsmgr_post_accept), CA_MAIL_SERVER_EXIT(tlsmgr_before_exit), CA_MAIL_SERVER_LOOP(tlsmgr_loop), CA_MAIL_SERVER_SOLITARY, diff --git a/postfix/src/tlsproxy/tlsproxy.c b/postfix/src/tlsproxy/tlsproxy.c index b11ce92c3..c1774a902 100644 --- a/postfix/src/tlsproxy/tlsproxy.c +++ b/postfix/src/tlsproxy/tlsproxy.c @@ -1481,6 +1481,12 @@ static void tlsp_service(VSTREAM *plaintext_stream, CA_VSTREAM_CTL_TIMEOUT(5), CA_VSTREAM_CTL_END); + (void) attr_print(plaintext_stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSPROXY), + ATTR_TYPE_END); + if (vstream_fflush(plaintext_stream) != 0) + msg_warn("write %s attribute: %m", MAIL_ATTR_PROTO); + /* * Receive postscreen's remote SMTP client address/port and socket. */ diff --git a/postfix/src/trivial-rewrite/trivial-rewrite.c b/postfix/src/trivial-rewrite/trivial-rewrite.c index 29c55c9b3..dcc555c6f 100644 --- a/postfix/src/trivial-rewrite/trivial-rewrite.c +++ b/postfix/src/trivial-rewrite/trivial-rewrite.c @@ -153,7 +153,7 @@ /* matches subdomains of example.com, /* instead of requiring an explicit ".example.com" pattern. /* .IP "\fBrelayhost (empty)\fR" -/* The next-hop destination of non-local mail; overrides non-local +/* The next-hop destination(s) for non-local mail; overrides non-local /* domains in recipient addresses. /* .IP "\fBtransport_maps (empty)\fR" /* Optional lookup tables with mappings from recipient address to @@ -522,6 +522,21 @@ static void pre_accept(char *unused_name, char **unused_argv) #endif +/* post_accept - anounce our protocol name */ + +static void post_accept(VSTREAM *stream, char *unused_name, char **unused_argv, + HTABLE *unused_attr) +{ + + /* + * Announce the protocol. + */ + attr_print(stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TRIVIAL), + ATTR_TYPE_END); + (void) vstream_fflush(stream); +} + static void check_table_stats(int unused_event, void *unused_context) { const char *table; @@ -648,5 +663,6 @@ int main(int argc, char **argv) #ifdef CHECK_TABLE_STATS_BEFORE_ACCEPT CA_MAIL_SERVER_PRE_ACCEPT(pre_accept), #endif + CA_MAIL_SERVER_POST_ACCEPT(post_accept), 0); } diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index 6c23678ab..d2815bee7 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -17,7 +17,7 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \ msg_output.c msg_syslog.c msg_vstream.c mvect.c myaddrinfo.c myflock.c \ mymalloc.c myrand.c mystrtok.c name_code.c name_mask.c netstring.c \ neuter.c non_blocking.c nvtable.c open_as.c open_limit.c open_lock.c \ - peekfd.c percentm.c posix_signals.c printable.c rand_sleep.c \ + peekfd.c posix_signals.c printable.c rand_sleep.c \ readlline.c ring.c safe_getenv.c safe_open.c \ sane_accept.c sane_connect.c sane_link.c sane_rename.c \ sane_socketpair.c sane_time.c scan_dir.c set_eugid.c set_ugid.c \ @@ -62,7 +62,7 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \ msg_output.o msg_syslog.o msg_vstream.o mvect.o myaddrinfo.o myflock.o \ mymalloc.o myrand.o mystrtok.o name_code.o name_mask.o netstring.o \ neuter.o non_blocking.o nvtable.o open_as.o open_limit.o open_lock.o \ - peekfd.o percentm.o posix_signals.o printable.o rand_sleep.o \ + peekfd.o posix_signals.o printable.o rand_sleep.o \ readlline.o ring.o safe_getenv.o safe_open.o \ sane_accept.o sane_connect.o sane_link.o sane_rename.o \ sane_socketpair.o sane_time.o scan_dir.o set_eugid.o set_ugid.o \ @@ -104,7 +104,7 @@ HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \ mac_parse.h make_dirs.h mask_addr.h match_list.h msg.h \ msg_output.h msg_syslog.h msg_vstream.h mvect.h myaddrinfo.h myflock.h \ mymalloc.h myrand.h name_code.h name_mask.h netstring.h nvtable.h \ - open_as.h open_lock.h percentm.h posix_signals.h readlline.h ring.h \ + open_as.h open_lock.h posix_signals.h readlline.h ring.h \ safe.h safe_open.h sane_accept.h sane_connect.h sane_fsops.h \ load_lib.h \ sane_socketpair.h sane_time.h scan_dir.h set_eugid.h set_ugid.h \ @@ -1949,6 +1949,8 @@ load_file.o: vbuf.h load_file.o: vstream.h load_file.o: warn_stat.h load_lib.o: load_lib.c +load_lib.o: load_lib.h +load_lib.o: msg.h load_lib.o: sys_defs.h logwriter.o: check_arg.h logwriter.o: iostuff.h @@ -2070,7 +2072,6 @@ msg_output.o: msg_output.c msg_output.o: msg_output.h msg_output.o: msg_vstream.h msg_output.o: mymalloc.h -msg_output.o: percentm.h msg_output.o: stringops.h msg_output.o: sys_defs.h msg_output.o: vbuf.h @@ -2220,12 +2221,6 @@ pass_trigger.o: trigger.h peekfd.o: iostuff.h peekfd.o: peekfd.c peekfd.o: sys_defs.h -percentm.o: check_arg.h -percentm.o: percentm.c -percentm.o: percentm.h -percentm.o: sys_defs.h -percentm.o: vbuf.h -percentm.o: vstring.h poll_fd.o: iostuff.h poll_fd.o: msg.h poll_fd.o: poll_fd.c diff --git a/postfix/src/util/attr.h b/postfix/src/util/attr.h index 754e1259f..fe44beb1e 100644 --- a/postfix/src/util/attr.h +++ b/postfix/src/util/attr.h @@ -45,6 +45,7 @@ typedef int (*ATTR_PRINT_CUSTOM_FN) (ATTR_PRINT_COMMON_FN, VSTREAM *, int, void #define ATTR_TYPE_LONG 4 /* Unsigned long */ #define ATTR_TYPE_DATA 5 /* Binary data */ #define ATTR_TYPE_FUNC 6 /* Function pointer */ +#define ATTR_TYPE_STREQ 7 /* Requires (name, value) match */ /* * Optional sender-specified grouping for hash or nameval tables. @@ -70,6 +71,7 @@ typedef int (*ATTR_PRINT_CUSTOM_FN) (ATTR_PRINT_COMMON_FN, VSTREAM *, int, void #define RECV_ATTR_INT(name, val) ATTR_TYPE_INT, CHECK_CPTR(ATTR, char, (name)), CHECK_PTR(ATTR, int, (val)) #define RECV_ATTR_STR(name, val) ATTR_TYPE_STR, CHECK_CPTR(ATTR, char, (name)), CHECK_PTR(ATTR, VSTRING, (val)) +#define RECV_ATTR_STREQ(name, val) ATTR_TYPE_STREQ, CHECK_CPTR(ATTR, char, (name)), CHECK_CPTR(ATTR, char, (val)) #define RECV_ATTR_HASH(val) ATTR_TYPE_HASH, CHECK_PTR(ATTR, HTABLE, (val)) #define RECV_ATTR_NV(val) ATTR_TYPE_NV, CHECK_PTR(ATTR, NVTABLE, (val)) #define RECV_ATTR_LONG(name, val) ATTR_TYPE_LONG, CHECK_CPTR(ATTR, char, (name)), CHECK_PTR(ATTR, long, (val)) diff --git a/postfix/src/util/attr_clnt.c b/postfix/src/util/attr_clnt.c index 0ec09449b..d944be509 100644 --- a/postfix/src/util/attr_clnt.c +++ b/postfix/src/util/attr_clnt.c @@ -8,6 +8,7 @@ /* /* typedef int (*ATTR_CLNT_PRINT_FN) (VSTREAM *, int, va_list); /* typedef int (*ATTR_CLNT_SCAN_FN) (VSTREAM *, int, va_list); +/* typedef int (*ATTR_CLNT_HANDSHAKE_FN) (VSTREAM *); /* /* ATTR_CLNT *attr_clnt_create(server, timeout, max_idle, max_ttl) /* const char *server; @@ -65,6 +66,9 @@ /* .IP "ATTR_CLNT_CTL_TRY_DELAY(int)" /* The time in seconds between attempts to send a request /* (default: 1). Specify a value greater than zero. +/* .IP "ATTR_CLNT_CTL_HANDSHAKE(VSTREAM *)" +/* A pointer to function that will be called at the start of a +/* new connection, and that returns 0 in case of success. /* DIAGNOSTICS /* Warnings: communication failure. /* SEE ALSO @@ -80,6 +84,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -254,6 +263,12 @@ void attr_clnt_control(ATTR_CLNT *client, int name,...) client->print = va_arg(ap, ATTR_CLNT_PRINT_FN); client->scan = va_arg(ap, ATTR_CLNT_SCAN_FN); break; + case ATTR_CLNT_CTL_HANDSHAKE: + auto_clnt_control(client->auto_clnt, + AUTO_CLNT_CTL_HANDSHAKE, + va_arg(ap, ATTR_CLNT_HANDSHAKE_FN), + AUTO_CLNT_CTL_END); + break; case ATTR_CLNT_CTL_REQ_LIMIT: client->req_limit = va_arg(ap, int); if (client->req_limit < 0) diff --git a/postfix/src/util/attr_clnt.h b/postfix/src/util/attr_clnt.h index c5e5ac0ae..ca630cd0e 100644 --- a/postfix/src/util/attr_clnt.h +++ b/postfix/src/util/attr_clnt.h @@ -27,6 +27,7 @@ typedef struct ATTR_CLNT ATTR_CLNT; typedef int (*ATTR_CLNT_PRINT_FN) (VSTREAM *, int, va_list); typedef int (*ATTR_CLNT_SCAN_FN) (VSTREAM *, int, va_list); +typedef int (*ATTR_CLNT_HANDSHAKE_FN) (VSTREAM *); extern ATTR_CLNT *attr_clnt_create(const char *, int, int, int); extern int attr_clnt_request(ATTR_CLNT *, int,...); @@ -38,6 +39,7 @@ extern void attr_clnt_control(ATTR_CLNT *, int,...); #define ATTR_CLNT_CTL_REQ_LIMIT 2 /* requests per connection */ #define ATTR_CLNT_CTL_TRY_LIMIT 3 /* attempts per request */ #define ATTR_CLNT_CTL_TRY_DELAY 4 /* pause between requests */ +#define ATTR_CLNT_CTL_HANDSHAKE 5 /* handshake before first request */ /* LICENSE /* .ad @@ -48,6 +50,11 @@ extern void attr_clnt_control(ATTR_CLNT *, int,...); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/postfix/src/util/attr_print0.c b/postfix/src/util/attr_print0.c index 20c2c5a1e..98c511850 100644 --- a/postfix/src/util/attr_print0.c +++ b/postfix/src/util/attr_print0.c @@ -228,6 +228,7 @@ int main(int unused_argc, char **argv) htable_enter(table, "foo-name", mystrdup("foo-value")); htable_enter(table, "bar-name", mystrdup("bar-value")); attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE, + SEND_ATTR_STR("protocol", "test"), SEND_ATTR_INT(ATTR_NAME_INT, 4711), SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L), SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"), @@ -236,11 +237,15 @@ int main(int unused_argc, char **argv) SEND_ATTR_LONG(ATTR_NAME_LONG, 4321L), ATTR_TYPE_END); attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE, + SEND_ATTR_STR("protocol", "test"), SEND_ATTR_INT(ATTR_NAME_INT, 4711), SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L), SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"), SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"), ATTR_TYPE_END); + attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE, + SEND_ATTR_STR("protocol", "not-test"), + ATTR_TYPE_END); if (vstream_fflush(VSTREAM_OUT) != 0) msg_fatal("write error: %m"); diff --git a/postfix/src/util/attr_print64.c b/postfix/src/util/attr_print64.c index 1008979aa..085ba33cc 100644 --- a/postfix/src/util/attr_print64.c +++ b/postfix/src/util/attr_print64.c @@ -269,6 +269,7 @@ int main(int unused_argc, char **argv) htable_enter(table, "foo-name", mystrdup("foo-value")); htable_enter(table, "bar-name", mystrdup("bar-value")); attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE, + SEND_ATTR_STR("protocol", "test"), SEND_ATTR_INT(ATTR_NAME_INT, 4711), SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L), SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"), @@ -277,11 +278,15 @@ int main(int unused_argc, char **argv) SEND_ATTR_LONG(ATTR_NAME_LONG, 4321L), ATTR_TYPE_END); attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE, + SEND_ATTR_STR("protocol", "test"), SEND_ATTR_INT(ATTR_NAME_INT, 4711), SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L), SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"), SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"), ATTR_TYPE_END); + attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE, + SEND_ATTR_STR("protocol", "not-test"), + ATTR_TYPE_END); if (vstream_fflush(VSTREAM_OUT) != 0) msg_fatal("write error: %m"); diff --git a/postfix/src/util/attr_print_plain.c b/postfix/src/util/attr_print_plain.c index 7ef03be8e..7d2d02fdb 100644 --- a/postfix/src/util/attr_print_plain.c +++ b/postfix/src/util/attr_print_plain.c @@ -224,6 +224,7 @@ int main(int unused_argc, char **argv) htable_enter(table, "foo-name", mystrdup("foo-value")); htable_enter(table, "bar-name", mystrdup("bar-value")); attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE, + SEND_ATTR_STR("protocol", "test"), SEND_ATTR_INT(ATTR_NAME_INT, 4711), SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L), SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"), @@ -232,11 +233,15 @@ int main(int unused_argc, char **argv) SEND_ATTR_LONG(ATTR_NAME_LONG, 4321L), ATTR_TYPE_END); attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE, + SEND_ATTR_STR("protocol", "test"), SEND_ATTR_INT(ATTR_NAME_INT, 4711), SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L), SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"), SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"), ATTR_TYPE_END); + attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE, + SEND_ATTR_STR("protocol", "not-test"), + ATTR_TYPE_END); if (vstream_fflush(VSTREAM_OUT) != 0) msg_fatal("write error: %m"); diff --git a/postfix/src/util/attr_scan0.c b/postfix/src/util/attr_scan0.c index 6dd154877..57746407c 100644 --- a/postfix/src/util/attr_scan0.c +++ b/postfix/src/util/attr_scan0.c @@ -100,6 +100,9 @@ /* This argument is followed by an attribute name and a long pointer. /* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)" /* This argument is followed by an attribute name and a VSTRING pointer. +/* .IP "RECV_ATTR_STREQ(const char *name, const char *value)" +/* The name and value must match what the client sends. +/* This attribute does not increment the result value. /* .IP "RECV_ATTR_DATA(const char *name, VSTRING *vp)" /* This argument is followed by an attribute name and a VSTRING pointer. /* .IP "RECV_ATTR_FUNC(ATTR_SCAN_CUSTOM_FN, void *data)" @@ -278,6 +281,7 @@ int attr_vscan0(VSTREAM *fp, int flags, va_list ap) int conversions; ATTR_SCAN_CUSTOM_FN scan_fn; void *scan_arg; + const char *expect_val; /* * Sanity check. @@ -421,6 +425,19 @@ int attr_vscan0(VSTREAM *fp, int flags, va_list ap) if (scan_fn(attr_scan0, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0) return (-1); break; + case ATTR_TYPE_STREQ: + expect_val = va_arg(ap, const char *); + if ((ch = attr_scan0_string(fp, str_buf, + "input attribute value")) < 0) + return (-1); + if (strcmp(expect_val, STR(str_buf)) != 0) { + msg_warn("unexpected %s %s from %s (expected: %s)", + STR(name_buf), STR(str_buf), VSTREAM_PATH(fp), + expect_val); + return (-1); + } + conversions -= 1; + break; case ATTR_TYPE_HASH: case ATTR_TYPE_CLOSE: if ((ch = attr_scan0_string(fp, str_buf, @@ -513,6 +530,7 @@ int main(int unused_argc, char **used_argv) msg_vstream_init(used_argv[0], VSTREAM_ERR); if ((ret = attr_scan0(VSTREAM_IN, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ("protocol", "test"), RECV_ATTR_INT(ATTR_NAME_INT, &int_val), RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val), RECV_ATTR_STR(ATTR_NAME_STR, str_val), @@ -534,6 +552,7 @@ int main(int unused_argc, char **used_argv) } if ((ret = attr_scan0(VSTREAM_IN, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ("protocol", "test"), RECV_ATTR_INT(ATTR_NAME_INT, &int_val), RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val), RECV_ATTR_STR(ATTR_NAME_STR, str_val), @@ -550,6 +569,11 @@ int main(int unused_argc, char **used_argv) } else { vstream_printf("return: %d\n", ret); } + if ((ret = attr_scan0(VSTREAM_IN, + ATTR_FLAG_STRICT, + RECV_ATTR_STREQ("protocol", "test"), + ATTR_TYPE_END)) != 0) + vstream_printf("return: %d\n", ret); if (vstream_fflush(VSTREAM_OUT) != 0) msg_fatal("write error: %m"); diff --git a/postfix/src/util/attr_scan0.ref b/postfix/src/util/attr_scan0.ref index 125faeb59..1fe09fc9f 100644 --- a/postfix/src/util/attr_scan0.ref +++ b/postfix/src/util/attr_scan0.ref @@ -1,3 +1,4 @@ +./attr_print0: send attr protocol = test ./attr_print0: send attr number = 4711 ./attr_print0: send attr long_number = 1234 ./attr_print0: send attr string = whoopee @@ -5,10 +6,15 @@ ./attr_print0: send attr name foo-name value foo-value ./attr_print0: send attr name bar-name value bar-value ./attr_print0: send attr long_number = 4321 +./attr_print0: send attr protocol = test ./attr_print0: send attr number = 4711 ./attr_print0: send attr long_number = 1234 ./attr_print0: send attr string = whoopee ./attr_print0: send attr data = [data 7 bytes] +./attr_print0: send attr protocol = not-test +./attr_scan0: unknown_stream: wanted attribute: protocol +./attr_scan0: input attribute name: protocol +./attr_scan0: input attribute value: test ./attr_scan0: unknown_stream: wanted attribute: number ./attr_scan0: input attribute name: number ./attr_scan0: input attribute value: 4711 @@ -36,6 +42,9 @@ ./attr_scan0: input attribute value: 4321 ./attr_scan0: unknown_stream: wanted attribute: (list terminator) ./attr_scan0: input attribute name: (end) +./attr_scan0: unknown_stream: wanted attribute: protocol +./attr_scan0: input attribute name: protocol +./attr_scan0: input attribute value: test ./attr_scan0: unknown_stream: wanted attribute: number ./attr_scan0: input attribute name: number ./attr_scan0: input attribute value: 4711 @@ -50,6 +59,10 @@ ./attr_scan0: input attribute value: d2hvb3BlZQ== ./attr_scan0: unknown_stream: wanted attribute: (list terminator) ./attr_scan0: input attribute name: (end) +./attr_scan0: unknown_stream: wanted attribute: protocol +./attr_scan0: input attribute name: protocol +./attr_scan0: input attribute value: not-test +./attr_scan0: warning: unexpected protocol not-test from unknown_stream (expected: test) number 4711 long_number 1234 string whoopee @@ -63,3 +76,4 @@ string whoopee data whoopee (hash) foo-name foo-value (hash) bar-name bar-value +return: -1 diff --git a/postfix/src/util/attr_scan64.c b/postfix/src/util/attr_scan64.c index 4ea1e2874..0a5eb3ee5 100644 --- a/postfix/src/util/attr_scan64.c +++ b/postfix/src/util/attr_scan64.c @@ -102,6 +102,9 @@ /* This argument is followed by an attribute name and a long pointer. /* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)" /* This argument is followed by an attribute name and a VSTRING pointer. +/* .IP "RECV_ATTR_STREQ(const char *name, const char *value)" +/* The name and value must match what the client sends. +/* This attribute does not increment the result value. /* .IP "RECV_ATTR_DATA(const char *name, VSTRING *vp)" /* This argument is followed by an attribute name and a VSTRING pointer. /* .IP "RECV_ATTR_FUNC(ATTR_SCAN_CUSTOM_FN, void *data)" @@ -281,6 +284,7 @@ int attr_vscan64(VSTREAM *fp, int flags, va_list ap) int conversions; ATTR_SCAN_CUSTOM_FN scan_fn; void *scan_arg; + const char *expect_val; /* * Sanity check. @@ -470,6 +474,29 @@ int attr_vscan64(VSTREAM *fp, int flags, va_list ap) if (scan_fn(attr_scan64, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0) return (-1); break; + case ATTR_TYPE_STREQ: + if (ch != ':') { + msg_warn("missing value for string attribute %s from %s", + STR(name_buf), VSTREAM_PATH(fp)); + return (-1); + } + expect_val = va_arg(ap, const char *); + if ((ch = attr_scan64_string(fp, str_buf, + "input attribute value")) < 0) + return (-1); + if (ch != '\n') { + msg_warn("multiple values for attribute %s from %s", + STR(name_buf), VSTREAM_PATH(fp)); + return (-1); + } + if (strcmp(expect_val, STR(str_buf)) != 0) { + msg_warn("unexpected %s %s from %s (expected: %s)", + STR(name_buf), STR(str_buf), VSTREAM_PATH(fp), + expect_val); + return (-1); + } + conversions -= 1; + break; case ATTR_TYPE_HASH: case ATTR_TYPE_CLOSE: if (ch != ':') { @@ -572,6 +599,7 @@ int main(int unused_argc, char **used_argv) msg_vstream_init(used_argv[0], VSTREAM_ERR); if ((ret = attr_scan64(VSTREAM_IN, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ("protocol", "test"), RECV_ATTR_INT(ATTR_NAME_INT, &int_val), RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val), RECV_ATTR_STR(ATTR_NAME_STR, str_val), @@ -593,6 +621,7 @@ int main(int unused_argc, char **used_argv) } if ((ret = attr_scan64(VSTREAM_IN, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ("protocol", "test"), RECV_ATTR_INT(ATTR_NAME_INT, &int_val), RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val), RECV_ATTR_STR(ATTR_NAME_STR, str_val), @@ -609,6 +638,11 @@ int main(int unused_argc, char **used_argv) } else { vstream_printf("return: %d\n", ret); } + if ((ret = attr_scan64(VSTREAM_IN, + ATTR_FLAG_STRICT, + RECV_ATTR_STREQ("protocol", "test"), + ATTR_TYPE_END)) != 0) + vstream_printf("return: %d\n", ret); if (vstream_fflush(VSTREAM_OUT) != 0) msg_fatal("write error: %m"); diff --git a/postfix/src/util/attr_scan64.ref b/postfix/src/util/attr_scan64.ref index 2fe353f80..9f9217afe 100644 --- a/postfix/src/util/attr_scan64.ref +++ b/postfix/src/util/attr_scan64.ref @@ -1,3 +1,4 @@ +./attr_print64: send attr protocol = test ./attr_print64: send attr number = 4711 ./attr_print64: send attr long_number = 1234 ./attr_print64: send attr string = whoopee @@ -5,10 +6,15 @@ ./attr_print64: send attr name foo-name value foo-value ./attr_print64: send attr name bar-name value bar-value ./attr_print64: send attr long_number = 4321 +./attr_print64: send attr protocol = test ./attr_print64: send attr number = 4711 ./attr_print64: send attr long_number = 1234 ./attr_print64: send attr string = whoopee ./attr_print64: send attr data = [data 7 bytes] +./attr_print64: send attr protocol = not-test +./attr_scan64: unknown_stream: wanted attribute: protocol +./attr_scan64: input attribute name: protocol +./attr_scan64: input attribute value: test ./attr_scan64: unknown_stream: wanted attribute: number ./attr_scan64: input attribute name: number ./attr_scan64: input attribute value: 4711 @@ -36,6 +42,9 @@ ./attr_scan64: input attribute value: 4321 ./attr_scan64: unknown_stream: wanted attribute: (list terminator) ./attr_scan64: input attribute name: (end) +./attr_scan64: unknown_stream: wanted attribute: protocol +./attr_scan64: input attribute name: protocol +./attr_scan64: input attribute value: test ./attr_scan64: unknown_stream: wanted attribute: number ./attr_scan64: input attribute name: number ./attr_scan64: input attribute value: 4711 @@ -50,6 +59,10 @@ ./attr_scan64: input attribute value: whoopee ./attr_scan64: unknown_stream: wanted attribute: (list terminator) ./attr_scan64: input attribute name: (end) +./attr_scan64: unknown_stream: wanted attribute: protocol +./attr_scan64: input attribute name: protocol +./attr_scan64: input attribute value: not-test +./attr_scan64: warning: unexpected protocol not-test from unknown_stream (expected: test) number 4711 long_number 1234 string whoopee @@ -63,3 +76,4 @@ string whoopee data whoopee (hash) foo-name foo-value (hash) bar-name bar-value +return: -1 diff --git a/postfix/src/util/attr_scan_plain.c b/postfix/src/util/attr_scan_plain.c index 41cfc8d4d..b003d4585 100644 --- a/postfix/src/util/attr_scan_plain.c +++ b/postfix/src/util/attr_scan_plain.c @@ -100,6 +100,9 @@ /* This argument is followed by an attribute name and a long pointer. /* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)" /* This argument is followed by an attribute name and a VSTRING pointer. +/* .IP "RECV_ATTR_STREQ(const char *name, const char *value)" +/* The name and value must match what the client sends. +/* This attribute does not increment the result value. /* .IP "RECV_ATTR_DATA(const char *name, VSTRING *vp)" /* This argument is followed by an attribute name and a VSTRING pointer. /* .IP "RECV_ATTR_FUNC(ATTR_SCAN_CUSTOM_FN, void *data)" @@ -294,6 +297,7 @@ int attr_vscan_plain(VSTREAM *fp, int flags, va_list ap) int conversions; ATTR_SCAN_CUSTOM_FN scan_fn; void *scan_arg; + const char *expect_val; /* * Sanity check. @@ -458,6 +462,24 @@ int attr_vscan_plain(VSTREAM *fp, int flags, va_list ap) if (scan_fn(attr_scan_plain, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0) return (-1); break; + case ATTR_TYPE_STREQ: + if (ch != '=') { + msg_warn("missing value for string attribute %s from %s", + STR(name_buf), VSTREAM_PATH(fp)); + return (-1); + } + expect_val = va_arg(ap, const char *); + if ((ch = attr_scan_plain_string(fp, str_buf, 0, + "input attribute value")) < 0) + return (-1); + if (strcmp(expect_val, STR(str_buf)) != 0) { + msg_warn("unexpected %s %s from %s (expected: %s)", + STR(name_buf), STR(str_buf), VSTREAM_PATH(fp), + expect_val); + return (-1); + } + conversions -= 1; + break; case ATTR_TYPE_HASH: case ATTR_TYPE_CLOSE: if (ch != '=') { @@ -555,6 +577,7 @@ int main(int unused_argc, char **used_argv) msg_vstream_init(used_argv[0], VSTREAM_ERR); if ((ret = attr_scan_plain(VSTREAM_IN, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ("protocol", "test"), RECV_ATTR_INT(ATTR_NAME_INT, &int_val), RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val), RECV_ATTR_STR(ATTR_NAME_STR, str_val), @@ -576,6 +599,7 @@ int main(int unused_argc, char **used_argv) } if ((ret = attr_scan_plain(VSTREAM_IN, ATTR_FLAG_STRICT, + RECV_ATTR_STREQ("protocol", "test"), RECV_ATTR_INT(ATTR_NAME_INT, &int_val), RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val), RECV_ATTR_STR(ATTR_NAME_STR, str_val), @@ -592,6 +616,11 @@ int main(int unused_argc, char **used_argv) } else { vstream_printf("return: %d\n", ret); } + if ((ret = attr_scan_plain(VSTREAM_IN, + ATTR_FLAG_STRICT, + RECV_ATTR_STREQ("protocol", "test"), + ATTR_TYPE_END)) != 0) + vstream_printf("return: %d\n", ret); if (vstream_fflush(VSTREAM_OUT) != 0) msg_fatal("write error: %m"); diff --git a/postfix/src/util/attr_scan_plain.ref b/postfix/src/util/attr_scan_plain.ref index 6e962c81f..994ba3ce3 100644 --- a/postfix/src/util/attr_scan_plain.ref +++ b/postfix/src/util/attr_scan_plain.ref @@ -1,3 +1,4 @@ +./attr_print_plain: send attr protocol = test ./attr_print_plain: send attr number = 4711 ./attr_print_plain: send attr long_number = 1234 ./attr_print_plain: send attr string = whoopee @@ -5,10 +6,15 @@ ./attr_print_plain: send attr name foo-name value foo-value ./attr_print_plain: send attr name bar-name value bar-value ./attr_print_plain: send attr long_number = 4321 +./attr_print_plain: send attr protocol = test ./attr_print_plain: send attr number = 4711 ./attr_print_plain: send attr long_number = 1234 ./attr_print_plain: send attr string = whoopee ./attr_print_plain: send attr data = [data 7 bytes] +./attr_print_plain: send attr protocol = not-test +./attr_scan_plain: unknown_stream: wanted attribute: protocol +./attr_scan_plain: input attribute name: protocol +./attr_scan_plain: input attribute value: test ./attr_scan_plain: unknown_stream: wanted attribute: number ./attr_scan_plain: input attribute name: number ./attr_scan_plain: input attribute value: 4711 @@ -36,6 +42,9 @@ ./attr_scan_plain: input attribute value: 4321 ./attr_scan_plain: unknown_stream: wanted attribute: (list terminator) ./attr_scan_plain: input attribute name: (end) +./attr_scan_plain: unknown_stream: wanted attribute: protocol +./attr_scan_plain: input attribute name: protocol +./attr_scan_plain: input attribute value: test ./attr_scan_plain: unknown_stream: wanted attribute: number ./attr_scan_plain: input attribute name: number ./attr_scan_plain: input attribute value: 4711 @@ -50,6 +59,10 @@ ./attr_scan_plain: input attribute value: d2hvb3BlZQ== ./attr_scan_plain: unknown_stream: wanted attribute: (list terminator) ./attr_scan_plain: input attribute name: (end) +./attr_scan_plain: unknown_stream: wanted attribute: protocol +./attr_scan_plain: input attribute name: protocol +./attr_scan_plain: input attribute value: not-test +./attr_scan_plain: warning: unexpected protocol not-test from unknown_stream (expected: test) number 4711 long_number 1234 string whoopee @@ -63,3 +76,4 @@ string whoopee data whoopee (hash) foo-name foo-value (hash) bar-name bar-value +return: -1 diff --git a/postfix/src/util/auto_clnt.c b/postfix/src/util/auto_clnt.c index 2703054e8..cdbbe2253 100644 --- a/postfix/src/util/auto_clnt.c +++ b/postfix/src/util/auto_clnt.c @@ -6,6 +6,8 @@ /* SYNOPSIS /* #include /* +/* typedef void (*AUTO_CLNT_HANDSHAKE_FN)(VSTREAM *); +/* /* AUTO_CLNT *auto_clnt_create(service, timeout, max_idle, max_ttl) /* const char *service; /* int timeout; @@ -23,6 +25,10 @@ /* /* void auto_clnt_free(auto_clnt) /* AUTO_CLNT *auto_clnt; +/* +/* void auto_clnt_control(auto_clnt, name, value, ... AUTO_CLNT_CTL_END) +/* AUTO_CLNT *auto_clnt; +/* int name; /* DESCRIPTION /* This module maintains IPC client endpoints that automatically /* disconnect after a being idle for a configurable amount of time, @@ -47,6 +53,15 @@ /* /* auto_clnt_free() destroys of the specified client endpoint. /* +/* auto_clnt_control() allows the user to fine tune the behavior of +/* the specified client. The arguments are a list of (name, value) +/* terminated with AUTO_CLNT_CTL_END. +/* The following lists the names and the types of the corresponding +/* value arguments. +/* .IP "AUTO_CLNT_CTL_HANDSHAKE(VSTREAM *)" +/* A pointer to function that will be called at the start of a +/* new connection, and that returns 0 in case of success. +/* .PP /* Arguments: /* .IP service /* The service argument specifies "transport:servername" where @@ -79,6 +94,10 @@ /* is expected to set the stream pathname to the server endpoint name. /* .IP context /* Application context that is passed to the open_action routine. +/* .IP handshake +/* A null pointer, or a pointer to function that will be called +/* at the start of a new connection and that returns 0 in case +/* of success. /* DIAGNOSTICS /* Warnings: communication failure. Fatal error: out of memory. /* LICENSE @@ -90,6 +109,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -120,6 +144,7 @@ struct AUTO_CLNT { int timeout; /* I/O time limit */ int max_idle; /* time before client disconnect */ int max_ttl; /* time before client disconnect */ + AUTO_CLNT_HANDSHAKE_FN handshake; /* new connection only */ int (*connect) (const char *, int, int); /* unix, local, inet */ }; @@ -250,6 +275,7 @@ void auto_clnt_recover(AUTO_CLNT *auto_clnt) VSTREAM *auto_clnt_access(AUTO_CLNT *auto_clnt) { + AUTO_CLNT_HANDSHAKE_FN handshake; /* * Open a stream or restart the idle timer. @@ -258,11 +284,15 @@ VSTREAM *auto_clnt_access(AUTO_CLNT *auto_clnt) */ if (auto_clnt->vstream == 0) { auto_clnt_open(auto_clnt); + handshake = (auto_clnt->vstream ? auto_clnt->handshake : 0); } else { if (auto_clnt->max_idle > 0) event_request_timer(auto_clnt_event, (void *) auto_clnt, auto_clnt->max_idle); + handshake = 0; } + if (handshake != 0 && handshake(auto_clnt->vstream) != 0) + return (0); return (auto_clnt->vstream); } @@ -290,6 +320,7 @@ AUTO_CLNT *auto_clnt_create(const char *service, int timeout, auto_clnt->timeout = timeout; auto_clnt->max_idle = max_idle; auto_clnt->max_ttl = max_ttl; + auto_clnt->handshake = 0; if (strcmp(transport, "inet") == 0) { auto_clnt->connect = inet_connect; } else if (strcmp(transport, "local") == 0) { @@ -320,3 +351,22 @@ void auto_clnt_free(AUTO_CLNT *auto_clnt) myfree(auto_clnt->endpoint); myfree((void *) auto_clnt); } + +/* auto_clnt_control - fine control */ + +void auto_clnt_control(AUTO_CLNT *client, int name,...) +{ + const char *myname = "auto_clnt_control"; + va_list ap; + + for (va_start(ap, name); name != AUTO_CLNT_CTL_END; name = va_arg(ap, int)) { + switch (name) { + case AUTO_CLNT_CTL_HANDSHAKE: + client->handshake = va_arg(ap, AUTO_CLNT_HANDSHAKE_FN); + break; + default: + msg_panic("%s: bad name %d", myname, name); + } + } + va_end(ap); +} diff --git a/postfix/src/util/auto_clnt.h b/postfix/src/util/auto_clnt.h index a168c1adc..61c66804d 100644 --- a/postfix/src/util/auto_clnt.h +++ b/postfix/src/util/auto_clnt.h @@ -20,12 +20,17 @@ * External interface. */ typedef struct AUTO_CLNT AUTO_CLNT; +typedef int (*AUTO_CLNT_HANDSHAKE_FN) (VSTREAM *); extern AUTO_CLNT *auto_clnt_create(const char *, int, int, int); extern VSTREAM *auto_clnt_access(AUTO_CLNT *); extern void auto_clnt_recover(AUTO_CLNT *); extern const char *auto_clnt_name(AUTO_CLNT *); extern void auto_clnt_free(AUTO_CLNT *); +extern void auto_clnt_control(AUTO_CLNT *, int,...); + +#define AUTO_CLNT_CTL_END 0 +#define AUTO_CLNT_CTL_HANDSHAKE 1 /* handshake before first request */ /* LICENSE /* .ad @@ -36,6 +41,11 @@ extern void auto_clnt_free(AUTO_CLNT *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/postfix/src/util/msg_output.c b/postfix/src/util/msg_output.c index 7031089a9..6663877d7 100644 --- a/postfix/src/util/msg_output.c +++ b/postfix/src/util/msg_output.c @@ -95,7 +95,6 @@ #include #include #include -#include #include /* @@ -165,7 +164,7 @@ void msg_vprintf(int level, const char *format, va_list ap) msg_vstream_init("unknown", VSTREAM_ERR); vp = msg_buffers[msg_vprintf_level - 1]; /* OK if terminating signal handler hijacks control before next stmt. */ - vstring_vsprintf(vp, percentm(format, errno), ap); + vstring_vsprintf(vp, format, ap); printable(vstring_str(vp), '?'); for (i = 0; i < msg_output_fn_count; i++) msg_output_fn[i] (level, vstring_str(vp)); diff --git a/postfix/src/util/percentm.c b/postfix/src/util/percentm.c deleted file mode 100644 index 854f1869f..000000000 --- a/postfix/src/util/percentm.c +++ /dev/null @@ -1,84 +0,0 @@ -/*++ -/* NAME -/* percentm 3 -/* SUMMARY -/* expand %m embedded in string to system error text -/* SYNOPSIS -/* #include -/* -/* char *percentm(const char *src, int err) -/* DESCRIPTION -/* The percentm() routine makes a copy of the null-terminated string -/* given via the \fIsrc\fR argument, with %m sequences replaced by -/* the system error text corresponding to the \fIerr\fR argument. -/* The result is overwritten upon each successive call. -/* -/* Arguments: -/* .IP src -/* A null-terminated input string with zero or more %m sequences. -/* .IP err -/* A legal \fIerrno\fR value. The text corresponding to this error -/* value is used when expanding %m sequences. -/* SEE ALSO -/* syslog(3) system logger library -/* HISTORY -/* .ad -/* .fi -/* A percentm() routine appears in the TCP Wrapper software -/* by Wietse Venema. -/* LICENSE -/* .ad -/* .fi -/* The Secure Mailer license must be distributed with this software. -/* AUTHOR(S) -/* Wietse Venema -/* IBM T.J. Watson Research -/* P.O. Box 704 -/* Yorktown Heights, NY 10598, USA -/*--*/ - -/* System libraries. */ - -#include -#include - -/* Utility library. */ - -#include "vstring.h" -#include "percentm.h" - -/* percentm - replace %m by error message corresponding to value in err */ - -char *percentm(const char *str, int err) -{ - static VSTRING *vp; - const unsigned char *ip = (const unsigned char *) str; - - if (vp == 0) - vp = vstring_alloc(100); /* grows on demand */ - VSTRING_RESET(vp); - - while (*ip) { - switch (*ip) { - default: - VSTRING_ADDCH(vp, *ip++); - break; - case '%': - switch (ip[1]) { - default: /* leave % alone */ - VSTRING_ADDCH(vp, *ip++); - /* FALLTHROUGH */ - case '\0': /* don't fall off end */ - VSTRING_ADDCH(vp, *ip++); - break; - case 'm': /* replace %m */ - vstring_strcat(vp, strerror(err)); - ip += 2; - break; - } - } - } - VSTRING_TERMINATE(vp); - return (vstring_str(vp)); -} - diff --git a/postfix/src/util/percentm.h b/postfix/src/util/percentm.h deleted file mode 100644 index d170e9586..000000000 --- a/postfix/src/util/percentm.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _PERCENT_H_INCLUDED_ -#define _PERCENT_H_INCLUDED_ - -/*++ -/* NAME -/* percentm 3h -/* SUMMARY -/* expand %m embedded in string to system error text -/* SYNOPSIS -/* #include -/* DESCRIPTION -/* .nf - - /* - * External interface. - */ -extern char *percentm(const char *, int); - -/* HISTORY -/* .ad -/* .fi -/* A percentm() routine appears in the TCP Wrapper software -/* by Wietse Venema. -/* LICENSE -/* .ad -/* .fi -/* The Secure Mailer license must be distributed with this software. -/* AUTHOR(S) -/* Wietse Venema -/* IBM T.J. Watson Research -/* P.O. Box 704 -/* Yorktown Heights, NY 10598, USA -/*--*/ - -#endif diff --git a/postfix/src/verify/verify.c b/postfix/src/verify/verify.c index 148f2aa32..60c5d9bc0 100644 --- a/postfix/src/verify/verify.c +++ b/postfix/src/verify/verify.c @@ -526,8 +526,8 @@ static void verify_query_service(VSTREAM *client_stream) (addr_status != DEL_RCPT_STAT_OK && updated + var_verify_neg_try < now) if (now - probed > PROBE_TTL - && (POSITIVE_REFRESH_NEEDED(addr_status, updated) - || NEGATIVE_REFRESH_NEEDED(addr_status, updated))) { + && (POSITIVE_REFRESH_NEEDED(addr_status, updated) + || NEGATIVE_REFRESH_NEEDED(addr_status, updated))) { if (msg_verbose) msg_info("PROBE %s status=%d probed=%ld updated=%ld", STR(addr), addr_status, now, updated); @@ -723,6 +723,21 @@ static void pre_jail_init(char *unused_name, char **unused_argv) RESTORE_SAVED_EUGID(); } +/* post_accept_init - announce our protocol */ + +static void post_accept_init(VSTREAM *stream, char *unused_name, + char **unused_argv, HTABLE *unused_table) +{ + + /* + * Announce the protocol. + */ + attr_print(stream, ATTR_FLAG_NONE, + SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_VERIFY), + ATTR_TYPE_END); + (void) vstream_fflush(stream); +} + MAIL_VERSION_STAMP_DECLARE; /* main - pass control to the multi-threaded skeleton */ @@ -754,6 +769,7 @@ int main(int argc, char **argv) CA_MAIL_SERVER_TIME_TABLE(time_table), CA_MAIL_SERVER_PRE_INIT(pre_jail_init), CA_MAIL_SERVER_POST_INIT(post_jail_init), + CA_MAIL_SERVER_POST_ACCEPT(post_accept_init), CA_MAIL_SERVER_SOLITARY, CA_MAIL_SERVER_EXIT(verify_dump), 0);