From: Wietse Venema Date: Thu, 7 Jul 2005 05:00:00 +0000 (-0500) Subject: postfix-2.3-20050707 X-Git-Tag: v2.3-RC1~67 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=61523e3f67dfb9b951bb8c4a850f69e3142adc9e;p=thirdparty%2Fpostfix.git postfix-2.3-20050707 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index aba7fed55..76b932dfd 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -10967,6 +10967,17 @@ Apologies for any names omitted. systems (inherited from Stevens Network Programming). Files: util/unix_send_fd.c, util/unix_recv_fd.c. +20050706 + + Robustness: the connection cache client now disables caching + when it is unable to communicate with the scache(8) server, + instead of looping forever. File: global/scache_clnt.c. + + Portability: after sending a socket, the scache(8) server + now waits for an ACK from the connection cache client before + closing the socket that it just sent. Files: scache/scache.c, + global/scache_clnt.c. + Open problems: Look for systems with XPG basename() declared in , diff --git a/postfix/README_FILES/SMTPD_POLICY_README b/postfix/README_FILES/SMTPD_POLICY_README index 27ddd95e9..c2c714c36 100644 --- a/postfix/README_FILES/SMTPD_POLICY_README +++ b/postfix/README_FILES/SMTPD_POLICY_README @@ -96,7 +96,7 @@ The following is specific to SMTPD delegated policy requests: * Protocol names are ESMTP or SMTP. - * Protocol states are CONNECT, EHLO, HELO, MAIL, RCPT, DATA, END-OF-DATA, + * Protocol states are CONNECT, EHLO, HELO, MAIL, RCPT, DATA, END-OF-MESSAGE, VRFY or ETRN; these are the SMTP protocol states where the Postfix SMTP server makes an OK/REJECT/HOLD/etc. decision. diff --git a/postfix/README_FILES/TUNING_README b/postfix/README_FILES/TUNING_README index 58e5edd98..c544ffc2a 100644 --- a/postfix/README_FILES/TUNING_README +++ b/postfix/README_FILES/TUNING_README @@ -157,12 +157,18 @@ will suffer grotesque delays if you do so. simultaneous connections (default: 50). This is half the default process limit. + * An SMTP client may make up to $smtpd_client_message_rate_limit message + delivery requests per unit time (default: no limit). + + * An SMTP client may send up to $smtpd_client_recipient_rate_limit recipient + addresses per unit time (default: no limit). + * An SMTP client may make up to $smtpd_client_connection_rate_limit connections per unit time (default: no limit). * These limits are not applied to SMTP clients in the networks specified with - $smtpd_client_connection_limit_exceptions (default: clients in $mynetworks - may make an unlimited number of connections). + $smtpd_client_event_limit_exceptions (default: clients in $mynetworks may + make an unlimited number of connections). * The anvil_rate_time_unit parameter specifies the time unit over which client connection rates are computed (default: 60s). diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 9e87262ee..a12abd678 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -17,6 +17,12 @@ Incompatibility with Postfix 2.1 and earlier If you upgrade from Postfix 2.1 or earlier, read RELEASE_NOTES-2.2 before proceeding. +Incompatibility with snapshot 20050707 +====================================== + +The connection cache protocol is changed. You may need to "postfix +reload" after upgrading. + Incompatibility with snapshot 20050627 ====================================== diff --git a/postfix/html/SMTPD_POLICY_README.html b/postfix/html/SMTPD_POLICY_README.html index df8f3ccd6..e4ee237aa 100644 --- a/postfix/html/SMTPD_POLICY_README.html +++ b/postfix/html/SMTPD_POLICY_README.html @@ -146,7 +146,7 @@ size=12345
  • Protocol names are ESMTP or SMTP.

  • Protocol states are CONNECT, EHLO, HELO, MAIL, RCPT, - DATA, END-OF-DATA, VRFY or ETRN; these are the SMTP protocol + DATA, END-OF-MESSAGE, VRFY or ETRN; these are the SMTP protocol states where the Postfix SMTP server makes an OK/REJECT/HOLD/etc. decision.

    diff --git a/postfix/html/TUNING_README.html b/postfix/html/TUNING_README.html index f0911ee98..cf7e2a3ea 100644 --- a/postfix/html/TUNING_README.html +++ b/postfix/html/TUNING_README.html @@ -242,11 +242,17 @@ traffic: mail will suffer grotesque delays if you do so.

    simultaneous connections (default: 50). This is half the default process limit.

    +
  • An SMTP client may make up to $smtpd_client_message_rate_limit +message delivery requests per unit time (default: no limit).

    + +
  • An SMTP client may send up to $smtpd_client_recipient_rate_limit +recipient addresses per unit time (default: no limit).

    +
  • An SMTP client may make up to $smtpd_client_connection_rate_limit connections per unit time (default: no limit).

  • These limits are not applied to SMTP clients in the networks -specified with $smtpd_client_connection_limit_exceptions (default: +specified with $smtpd_client_event_limit_exceptions (default: clients in $mynetworks may make an unlimited number of connections).

  • The anvil_rate_time_unit parameter specifies the time diff --git a/postfix/html/pipe.8.html b/postfix/html/pipe.8.html index abec1f678..05599514e 100644 --- a/postfix/html/pipe.8.html +++ b/postfix/html/pipe.8.html @@ -157,7 +157,7 @@ PIPE(8) PIPE(8) size=size_limit (optional) Messages greater in size than this limit (in bytes) - will be bounced back to the sender. + will be returned to the sender as undeliverable. user=username (required) diff --git a/postfix/man/man8/pipe.8 b/postfix/man/man8/pipe.8 index 44f02efae..9e4dbc660 100644 --- a/postfix/man/man8/pipe.8 +++ b/postfix/man/man8/pipe.8 @@ -144,8 +144,8 @@ specify \fB$sender\fR as an argument by itself. .sp This feature is available with Postfix 2.3 and later. .IP "\fBsize\fR=\fIsize_limit\fR (optional)" -Messages greater in size than this limit (in bytes) will be bounced -back to the sender. +Messages greater in size than this limit (in bytes) will +be returned to the sender as undeliverable. .IP "\fBuser\fR=\fIusername\fR (required)" .IP "\fBuser\fR=\fIusername\fR:\fIgroupname\fR" The external command is executed with the rights of the diff --git a/postfix/proto/SMTPD_POLICY_README.html b/postfix/proto/SMTPD_POLICY_README.html index 84e25c79c..fb2bcb83e 100644 --- a/postfix/proto/SMTPD_POLICY_README.html +++ b/postfix/proto/SMTPD_POLICY_README.html @@ -146,7 +146,7 @@ size=12345

  • Protocol names are ESMTP or SMTP.

  • Protocol states are CONNECT, EHLO, HELO, MAIL, RCPT, - DATA, END-OF-DATA, VRFY or ETRN; these are the SMTP protocol + DATA, END-OF-MESSAGE, VRFY or ETRN; these are the SMTP protocol states where the Postfix SMTP server makes an OK/REJECT/HOLD/etc. decision.

    diff --git a/postfix/proto/TUNING_README.html b/postfix/proto/TUNING_README.html index 43eb87784..9882044aa 100644 --- a/postfix/proto/TUNING_README.html +++ b/postfix/proto/TUNING_README.html @@ -242,11 +242,17 @@ traffic: mail will suffer grotesque delays if you do so.

    simultaneous connections (default: 50). This is half the default process limit.

    +
  • An SMTP client may make up to $smtpd_client_message_rate_limit +message delivery requests per unit time (default: no limit).

    + +
  • An SMTP client may send up to $smtpd_client_recipient_rate_limit +recipient addresses per unit time (default: no limit).

    +
  • An SMTP client may make up to $smtpd_client_connection_rate_limit connections per unit time (default: no limit).

  • These limits are not applied to SMTP clients in the networks -specified with $smtpd_client_connection_limit_exceptions (default: +specified with $smtpd_client_event_limit_exceptions (default: clients in $mynetworks may make an unlimited number of connections).

  • The anvil_rate_time_unit parameter specifies the time diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 9db66ece7..0476ecb43 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 "20050630" +#define MAIL_RELEASE_DATE "20050707" #define MAIL_VERSION_NUMBER "2.3" #define VAR_MAIL_VERSION "mail_version" diff --git a/postfix/src/global/scache_clnt.c b/postfix/src/global/scache_clnt.c index 9c1e482df..4749d6931 100644 --- a/postfix/src/global/scache_clnt.c +++ b/postfix/src/global/scache_clnt.c @@ -25,6 +25,7 @@ /* Upper bound on the time that a connection is allowed to persist. /* DIAGNOSTICS /* Fatal error: memory allocation problem; +/* warning: communication error; /* panic: internal consistency failure. /* SEE ALSO /* scache(3), generic session cache API @@ -73,6 +74,8 @@ typedef struct { #define STR(x) vstring_str(x) +#define SCACHE_MAX_TRIES 2 + /* scache_clnt_save_endp - save endpoint */ static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl, @@ -83,6 +86,7 @@ static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl, const char *myname = "scache_clnt_save_endp"; VSTREAM *stream; int status; + int tries; if (msg_verbose) msg_info("%s: endp=%s prop=%s fd=%d", @@ -95,11 +99,11 @@ static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl, msg_panic("%s: bad endp_ttl: %d", myname, endp_ttl); /* - * Keep trying until we get a complete response. The session cache - * service is CPU bound and making the client asynchronous would just - * complicate the code. + * Try a few times before disabling the cache. We use synchronous calls; + * the session cache service is CPU bound and making the client + * asynchronous would just complicate the code. */ - for (;;) { + for (tries = 0; sp->clnt_stream != 0 ; tries++) { stream = clnt_stream_access(sp->clnt_stream); errno = 0; if (attr_print(stream, ATTR_FLAG_NONE, @@ -121,14 +125,26 @@ static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl, if (msg_verbose || (errno != EPIPE && errno != ENOENT)) msg_warn("problem talking to service %s: %m", VSTREAM_PATH(stream)); + /* Give up or recover. */ } else { - if (close(fd) < 0) - msg_warn("%s: close(%d): %m", myname, fd); + if (msg_verbose && status != 0) + msg_warn("%s: descriptor save failed with status %d", + myname, status); + break; + } + /* Give up or recover. */ + if (tries >= SCACHE_MAX_TRIES - 1) { + msg_warn("disabling connection caching"); + clnt_stream_free(sp->clnt_stream); + sp->clnt_stream = 0; break; } sleep(1); /* XXX make configurable */ clnt_stream_recover(sp->clnt_stream); } + /* Always close the descriptor before returning. */ + if (close(fd) < 0) + msg_warn("%s: close(%d): %m", myname, fd); } /* scache_clnt_find_endp - look up cached session */ @@ -140,14 +156,15 @@ static int scache_clnt_find_endp(SCACHE *scache, const char *endp_label, const char *myname = "scache_clnt_find_endp"; VSTREAM *stream; int status; + int tries; int fd; /* - * Keep trying until we get a complete response. The session cache - * service is CPU bound and making the client asynchronous would just - * complicate the code. + * Try a few times before disabling the cache. We use synchronous calls; + * the session cache service is CPU bound and making the client + * asynchronous would just complicate the code. */ - for (;;) { + for (tries = 0; sp->clnt_stream != 0 ; tries++) { stream = clnt_stream_access(sp->clnt_stream); errno = 0; if (attr_print(stream, ATTR_FLAG_NONE, @@ -158,37 +175,51 @@ static int scache_clnt_find_endp(SCACHE *scache, const char *endp_label, || attr_scan(stream, ATTR_FLAG_STRICT, ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, ATTR_TYPE_STR, MAIL_ATTR_PROP, endp_prop, - ATTR_TYPE_END) != 2 - || (status == 0 - && ( + ATTR_TYPE_END) != 2) { + if (msg_verbose || (errno != EPIPE && errno != ENOENT)) + msg_warn("problem talking to service %s: %m", + VSTREAM_PATH(stream)); + /* Give up or recover. */ + } else if (status != 0) { + if (msg_verbose) + msg_info("%s: not found: %s", myname, endp_label); + return (-1); + } else if ( #ifdef CANT_WRITE_BEFORE_SENDING_FD - attr_print(stream, ATTR_FLAG_NONE, - ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "", - ATTR_TYPE_END) != 0 - || vstream_fflush(stream) != 0 - || read_wait(vstream_fileno(stream), - stream->timeout) < 0 || /* XXX */ + attr_print(stream, ATTR_FLAG_NONE, + ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "", + ATTR_TYPE_END) != 0 + || vstream_fflush(stream) != 0 + || read_wait(vstream_fileno(stream), + stream->timeout) < 0 || /* XXX */ #endif - (fd = LOCAL_RECV_FD(vstream_fileno(stream))) < 0))) { + (fd = LOCAL_RECV_FD(vstream_fileno(stream))) < 0) { if (msg_verbose || (errno != EPIPE && errno != ENOENT)) msg_warn("problem talking to service %s: %m", VSTREAM_PATH(stream)); + /* Give up or recover. */ } else { - break; +#ifdef MUST_READ_AFTER_SENDING_FD + (void) attr_print(stream, ATTR_FLAG_NONE, + ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "", + ATTR_TYPE_END); + (void) vstream_fflush(stream); +#endif + if (msg_verbose) + msg_info("%s: endp=%s prop=%s fd=%d", + myname, endp_label, STR(endp_prop), fd); + return (fd); + } + /* Give up or recover. */ + if (tries >= SCACHE_MAX_TRIES - 1) { + msg_warn("disabling connection caching"); + clnt_stream_free(sp->clnt_stream); + sp->clnt_stream = 0; + return (-1); } sleep(1); /* XXX make configurable */ clnt_stream_recover(sp->clnt_stream); } - - if (status == 0) { - if (msg_verbose) - msg_info("%s: endp=%s prop=%s fd=%d", - myname, endp_label, STR(endp_prop), fd); - return (fd); - } - if (msg_verbose) - msg_info("%s: not found: %s", myname, endp_label); - return (-1); } /* scache_clnt_save_dest - create destination/endpoint association */ @@ -202,6 +233,7 @@ static void scache_clnt_save_dest(SCACHE *scache, int dest_ttl, const char *myname = "scache_clnt_save_dest"; VSTREAM *stream; int status; + int tries; if (msg_verbose) msg_info("%s: dest_label=%s dest_prop=%s endp_label=%s", @@ -214,11 +246,11 @@ static void scache_clnt_save_dest(SCACHE *scache, int dest_ttl, msg_panic("%s: bad dest_ttl: %d", myname, dest_ttl); /* - * Keep trying until we get a complete response. The session cache - * service is CPU bound and making the client asynchronous would just - * complicate the code. + * Try a few times before disabling the cache. We use synchronous calls; + * the session cache service is CPU bound and making the client + * asynchronous would just complicate the code. */ - for (;;) { + for (tries = 0; sp->clnt_stream != 0 ; tries++) { stream = clnt_stream_access(sp->clnt_stream); errno = 0; if (attr_print(stream, ATTR_FLAG_NONE, @@ -235,7 +267,18 @@ static void scache_clnt_save_dest(SCACHE *scache, int dest_ttl, if (msg_verbose || (errno != EPIPE && errno != ENOENT)) msg_warn("problem talking to service %s: %m", VSTREAM_PATH(stream)); + /* Give up or recover. */ } else { + if (msg_verbose && status != 0) + msg_warn("%s: destination save failed with status %d", + myname, status); + break; + } + /* Give up or recover. */ + if (tries >= SCACHE_MAX_TRIES - 1) { + msg_warn("disabling connection caching"); + clnt_stream_free(sp->clnt_stream); + sp->clnt_stream = 0; break; } sleep(1); /* XXX make configurable */ @@ -253,14 +296,15 @@ static int scache_clnt_find_dest(SCACHE *scache, const char *dest_label, const char *myname = "scache_clnt_find_dest"; VSTREAM *stream; int status; + int tries; int fd; /* - * Keep trying until we get a complete response. The session cache - * service is CPU bound and making the client asynchronous would just - * complicate the code. + * Try a few times before disabling the cache. We use synchronous calls; + * the session cache service is CPU bound and making the client + * asynchronous would just complicate the code. */ - for (;;) { + for (tries = 0; sp->clnt_stream != 0 ; tries++) { stream = clnt_stream_access(sp->clnt_stream); errno = 0; if (attr_print(stream, ATTR_FLAG_NONE, @@ -272,38 +316,51 @@ static int scache_clnt_find_dest(SCACHE *scache, const char *dest_label, ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, ATTR_TYPE_STR, MAIL_ATTR_PROP, dest_prop, ATTR_TYPE_STR, MAIL_ATTR_PROP, endp_prop, - ATTR_TYPE_END) != 3 - || (status == 0 - && ( + ATTR_TYPE_END) != 3) { + if (msg_verbose || (errno != EPIPE && errno != ENOENT)) + msg_warn("problem talking to service %s: %m", + VSTREAM_PATH(stream)); + /* Give up or recover. */ + } else if (status != 0) { + if (msg_verbose) + msg_info("%s: not found: %s", myname, dest_label); + return (-1); + } else if ( #ifdef CANT_WRITE_BEFORE_SENDING_FD - attr_print(stream, ATTR_FLAG_NONE, - ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "", - ATTR_TYPE_END) != 0 - || vstream_fflush(stream) != 0 - || read_wait(vstream_fileno(stream), - stream->timeout) < 0 || /* XXX */ + attr_print(stream, ATTR_FLAG_NONE, + ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "", + ATTR_TYPE_END) != 0 + || vstream_fflush(stream) != 0 + || read_wait(vstream_fileno(stream), + stream->timeout) < 0 || /* XXX */ #endif - (fd = LOCAL_RECV_FD(vstream_fileno(stream))) < 0))) { + (fd = LOCAL_RECV_FD(vstream_fileno(stream))) < 0) { if (msg_verbose || (errno != EPIPE && errno != ENOENT)) msg_warn("problem talking to service %s: %m", VSTREAM_PATH(stream)); + /* Give up or recover. */ } else { - break; +#ifdef MUST_READ_AFTER_SENDING_FD + (void) attr_print(stream, ATTR_FLAG_NONE, + ATTR_TYPE_STR, MAIL_ATTR_DUMMY, "", + ATTR_TYPE_END); + (void) vstream_fflush(stream); +#endif + if (msg_verbose) + msg_info("%s: dest=%s dest_prop=%s endp_prop=%s fd=%d", + myname, dest_label, STR(dest_prop), STR(endp_prop), fd); + return (fd); + } + /* Give up or recover. */ + if (tries >= SCACHE_MAX_TRIES - 1) { + msg_warn("disabling connection caching"); + clnt_stream_free(sp->clnt_stream); + sp->clnt_stream = 0; + return (-1); } sleep(1); /* XXX make configurable */ clnt_stream_recover(sp->clnt_stream); } - - if (status == 0) { - if (msg_verbose) - msg_info("%s: dest=%s dest_prop=%s endp_prop=%s fd=%d", - myname, dest_label, STR(dest_prop), STR(endp_prop), fd); - return (fd); - } - if (msg_verbose) - msg_info("%s: not found: %s", myname, dest_label); - - return (-1); } /* scache_clnt_size - dummy */ @@ -322,7 +379,8 @@ static void scache_clnt_free(SCACHE *scache) { SCACHE_CLNT *sp = (SCACHE_CLNT *) scache; - clnt_stream_free(sp->clnt_stream); + if (sp->clnt_stream) + clnt_stream_free(sp->clnt_stream); #ifdef CANT_WRITE_BEFORE_SENDING_FD vstring_free(sp->dummy); #endif @@ -342,6 +400,7 @@ SCACHE *scache_clnt_create(const char *server, int idle_limit, int ttl_limit) sp->scache->size = scache_clnt_size; sp->scache->free = scache_clnt_free; + /* XXX Need flags to stop looping on ECONNREFUSED errors. */ sp->clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE, server, idle_limit, ttl_limit); #ifdef CANT_WRITE_BEFORE_SENDING_FD diff --git a/postfix/src/pipe/pipe.c b/postfix/src/pipe/pipe.c index f2bfd0b72..795030d48 100644 --- a/postfix/src/pipe/pipe.c +++ b/postfix/src/pipe/pipe.c @@ -134,8 +134,8 @@ /* .sp /* This feature is available with Postfix 2.3 and later. /* .IP "\fBsize\fR=\fIsize_limit\fR (optional)" -/* Messages greater in size than this limit (in bytes) will be bounced -/* back to the sender. +/* Messages greater in size than this limit (in bytes) will +/* be returned to the sender as undeliverable. /* .IP "\fBuser\fR=\fIusername\fR (required)" /* .IP "\fBuser\fR=\fIusername\fR:\fIgroupname\fR" /* The external command is executed with the rights of the diff --git a/postfix/src/scache/scache.c b/postfix/src/scache/scache.c index 8687a8ab2..deb6f0dad 100644 --- a/postfix/src/scache/scache.c +++ b/postfix/src/scache/scache.c @@ -241,17 +241,17 @@ static void scache_save_endp_service(VSTREAM *client_stream) #endif (fd = LOCAL_RECV_FD(vstream_fileno(client_stream))) < 0) { msg_warn("%s: unable to receive file descriptor: %m", myname); - attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_FAIL, - ATTR_TYPE_END); + (void) attr_print(client_stream, ATTR_FLAG_NONE, + ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_FAIL, + ATTR_TYPE_END); return; } else { scache_save_endp(scache, ttl > var_scache_ttl_lim ? var_scache_ttl_lim : ttl, STR(scache_endp_label), STR(scache_endp_prop), fd); - attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_OK, - ATTR_TYPE_END); + (void) attr_print(client_stream, ATTR_FLAG_NONE, + ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_OK, + ATTR_TYPE_END); scache_size(scache, &size); if (size.endp_count > scache_endp_count) scache_endp_count = size.endp_count; @@ -297,7 +297,13 @@ static void scache_find_endp_service(VSTREAM *client_stream) ATTR_TYPE_STR, MAIL_ATTR_DUMMY, scache_dummy, ATTR_TYPE_END) != 1 #endif - || LOCAL_SEND_FD(vstream_fileno(client_stream), fd) < 0) + || LOCAL_SEND_FD(vstream_fileno(client_stream), fd) < 0 +#ifdef MUST_READ_AFTER_SENDING_FD + || attr_scan(client_stream, ATTR_FLAG_STRICT, + ATTR_TYPE_STR, MAIL_ATTR_DUMMY, scache_dummy, + ATTR_TYPE_END) != 1 +#endif + ) msg_warn("%s: cannot send file descriptor: %m", myname); if (close(fd) < 0) msg_warn("close(%d): %m", fd); @@ -384,7 +390,13 @@ static void scache_find_dest_service(VSTREAM *client_stream) ATTR_TYPE_STR, MAIL_ATTR_DUMMY, scache_dummy, ATTR_TYPE_END) != 1 #endif - || LOCAL_SEND_FD(vstream_fileno(client_stream), fd) < 0) + || LOCAL_SEND_FD(vstream_fileno(client_stream), fd) < 0 +#ifdef MUST_READ_AFTER_SENDING_FD + || attr_scan(client_stream, ATTR_FLAG_STRICT, + ATTR_TYPE_STR, MAIL_ATTR_DUMMY, scache_dummy, + ATTR_TYPE_END) != 1 +#endif + ) msg_warn("%s: cannot send file descriptor: %m", myname); if (close(fd) < 0) msg_warn("close(%d): %m", fd); diff --git a/postfix/src/smtpd/smtpd_peer.c b/postfix/src/smtpd/smtpd_peer.c index fd4c84724..dc6b08e8b 100644 --- a/postfix/src/smtpd/smtpd_peer.c +++ b/postfix/src/smtpd/smtpd_peer.c @@ -20,7 +20,8 @@ /* smtpd_peer_init() updates the following fields: /* .IP name /* The client hostname. An unknown name is represented by the -/* string "unknown". +/* string "unknown". This includes names that could not be +/* verified with forward DNS lookups. /* .IP addr /* Printable representation of the client address. /* .IP namaddr @@ -213,6 +214,9 @@ void smtpd_peer_init(SMTPD_STATE *state) /* * Reject the hostname if it does not list the peer address. + * Without further validation or qualification, such information + * must not be allowed to enter the audit trail, as people would + * draw false conclusions. */ aierr = hostname_to_sockaddr(state->name, (char *) 0, 0, &res0); if (aierr) { diff --git a/postfix/src/util/sys_defs.h b/postfix/src/util/sys_defs.h index 44df40131..f2a1bb372 100644 --- a/postfix/src/util/sys_defs.h +++ b/postfix/src/util/sys_defs.h @@ -1308,6 +1308,15 @@ typedef int pid_t; */ #ifndef CAN_WRITE_BEFORE_SENDING_FD #define CANT_WRITE_BEFORE_SENDING_FD +#endif + + /* + * FreeBSD sendmsg(2) says that after sending a file descriptor, the sender + * must not immediately close the descriptor, otherwise it may close the + * descriptor before it is actually sent. + */ +#ifndef DONT_WAIT_AFTER_SENDING_FD +#define MUST_READ_AFTER_SENDING_FD #endif /*