From 5f0a27f981ca0058a10a9068455a738c6f715b08 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Sun, 12 Oct 2008 00:00:00 -0500 Subject: [PATCH] postfix-2.6-20081012 --- postfix/HISTORY | 13 +++++- postfix/README_FILES/XFORWARD_README | 13 ++---- postfix/RELEASE_NOTES | 19 ++++---- postfix/html/XFORWARD_README.html | 12 ++--- postfix/proto/XFORWARD_README.html | 12 ++--- postfix/src/global/deliver_request.h | 6 +++ postfix/src/global/mail_proto.h | 20 +------- postfix/src/global/mail_version.h | 10 ++-- postfix/src/oqmgr/qmgr_message.c | 2 - postfix/src/qmgr/qmgr_message.c | 2 - postfix/src/qmqpd/qmqpd.c | 17 +++++-- postfix/src/smtp/smtp_proto.c | 69 +++++++++++++--------------- postfix/src/smtpd/smtpd.c | 58 ++++++++--------------- postfix/src/smtpd/smtpd.h | 65 +++++++++++--------------- 14 files changed, 133 insertions(+), 185 deletions(-) diff --git a/postfix/HISTORY b/postfix/HISTORY index 2753ba705..d23f3ac6b 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -14669,7 +14669,9 @@ Apologies for any names omitted. from an SMTP-based content filter. This was fixed with a a minor semantic change to the XFORWARD protocol. Files: smtpd/smtpd.c, qmqpd/qmqpd.c, smtp/smtp_proto.c, - cleanup/cleanup_envelope.c, proto/XFORWARD.html. + cleanup/cleanup_envelope.c, proto/XFORWARD.html. Note: the + changes to propagate local submission details were undone + 20082012. Feature: a DUNNO lookup result in per_sender_relayhost_maps stops the search without replacing the next-hop destination. @@ -14715,7 +14717,14 @@ Apologies for any names omitted. Feature: controls for opportunistic TLS protocols and ciphers. The smtp_tls_protocols, smtp_tls_ciphers, and equivalent parameters for lmtp and smtpd provide global - settings; The SMTP client TLS policy table provides ciphers + settings; the SMTP client TLS policy table provides ciphers and protocols settings for specific peers. Code by Victor Duchovni. Files: smtp/smtp.c, smtp/smtp_session.c, smtpd/smtpd.c and documentation. + +20081012 + + Cleanup: simplify the 20081003 changes and don't try to + propagate local submission information through XFORWARD. + Files: smtpd/smtpd.c, qmqpd/qmqpd.c, smtp/smtp_proto.c, + cleanup/cleanup_envelope.c, proto/XFORWARD.html. diff --git a/postfix/README_FILES/XFORWARD_README b/postfix/README_FILES/XFORWARD_README index 187b7ef93..0742dbe93 100644 --- a/postfix/README_FILES/XFORWARD_README +++ b/postfix/README_FILES/XFORWARD_README @@ -33,9 +33,9 @@ XFORWARD. The keyword is followed by the names of the attributes that the XFORWARD implementation supports. After receiving the server's announcement for XFORWARD support, the client may -send one or more XFORWARD requests at any time except in the middle of a mail -delivery transaction (i.e. between MAIL and RSET or DOT). The command may be -pipelined when the server supports ESMTP command pipelining. +send XFORWARD requests at any time except in the middle of a mail delivery +transaction (i.e. between MAIL and RSET or DOT). The command may be pipelined +when the server supports ESMTP command pipelining. The syntax of XFORWARD requests is described below. Upper case and quoted strings specify terminals, lowercase strings specify meta terminals, and SP is @@ -58,9 +58,6 @@ are in fact case insensitive. when the address information is unavailable. Address information is not enclosed with []. - * When both the NAME and ADDR attributes have the value [UNAVAILABLE], the - upcoming MAIL FROM transaction corresponds to a local submission. - * The PORT attribute specifies an up-stream client TCP port number in decimal, or [UNAVAILABLE] when the information is unavailable. @@ -106,8 +103,8 @@ Upon receipt of an initial XFORWARD command, the SMTP server initializes all XFORWARD attributes to [UNAVAILABLE]. With each valid XFORWARD command, the server updates XFORWARD attributes with the specified values. -When the server uses XFORWARD attributes for logging purposes, it must not mix -XFORWARD attributes with attributes from the current SMTP session. +The server must not mix client attributes from XFORWARD with client attributes +from the current SMTP session. At the end of each MAIL FROM transaction (i.e. RSET or DOT), the server resets all XFORWARD attributes to the undefined state, and is ready to receive another diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 58fd83e58..18c91c1c1 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -11,18 +11,15 @@ instead, a new snapshot is released. The mail_release_date configuration parameter (format: yyyymmdd) specifies the release date of a stable release or snapshot release. -Incompatibility with snapshot 20081003 -====================================== +Major changes with snapshot 20081010 +==================================== -This release fixes cosmetic bugs in the way that Postfix propagates -the origin of email messages through SMTP-based content filters. -This changes the results of $name expansions by the local(8) and -pipe(8) delivery agents. With a local submission, the $client_hostname -etc. attributes now correctly expand into the empty string, instead -of information about the host that runs the content filter; and -with a remote submission from a client with an unknown hostname, -the $client_hostname attribute now correctly expands into "unknown" -instead of the empty string. +Controls for the protocols and ciphers that Postfix will use with +opportunistic TLS. The smtp_tls_protocols, smtp_tls_ciphers, and +equivalent parameters for lmtp and smtpd provide global settings; +the SMTP client TLS policy table provides ciphers and protocols +settings for specific peers. Code by Victor Duchovni. Details are +given in the TLS_README and postconf(5) documents. Incompatibility with snapshot 20080814 ====================================== diff --git a/postfix/html/XFORWARD_README.html b/postfix/html/XFORWARD_README.html index 64b60c662..64c81e244 100644 --- a/postfix/html/XFORWARD_README.html +++ b/postfix/html/XFORWARD_README.html @@ -56,8 +56,7 @@ extension is XFORWARD. The keyword is followed by the names of the attributes that the XFORWARD implementation supports.

After receiving the server's announcement for XFORWARD support, -the client may send one or more XFORWARD requests at any time except -in +the client may send XFORWARD requests at any time except in the middle of a mail delivery transaction (i.e. between MAIL and RSET or DOT). The command may be pipelined when the server supports ESMTP command pipelining.

@@ -95,10 +94,6 @@ names are shown in upper case, they are in fact case insensitive. is unavailable. Address information is not enclosed with [].

-
  • When both the NAME and ADDR attributes have the value - [UNAVAILABLE], the upcoming MAIL FROM transaction corresponds - to a local submission.

    -
  • The PORT attribute specifies an up-stream client TCP port number in decimal, or [UNAVAILABLE] when the information is unavailable.

    @@ -155,9 +150,8 @@ initializes all XFORWARD attributes to [UNAVAILABLE]. With each valid XFORWARD command, the server updates XFORWARD attributes with the specified values.

    -

    When the server uses XFORWARD attributes for logging purposes, -it must not mix XFORWARD attributes with attributes from the current -SMTP session.

    +

    The server must not mix client attributes from XFORWARD with +client attributes from the current SMTP session.

    At the end of each MAIL FROM transaction (i.e. RSET or DOT), the server resets all XFORWARD attributes to the undefined state, diff --git a/postfix/proto/XFORWARD_README.html b/postfix/proto/XFORWARD_README.html index 3762b537f..9e17db825 100644 --- a/postfix/proto/XFORWARD_README.html +++ b/postfix/proto/XFORWARD_README.html @@ -56,8 +56,7 @@ extension is XFORWARD. The keyword is followed by the names of the attributes that the XFORWARD implementation supports.

    After receiving the server's announcement for XFORWARD support, -the client may send one or more XFORWARD requests at any time except -in +the client may send XFORWARD requests at any time except in the middle of a mail delivery transaction (i.e. between MAIL and RSET or DOT). The command may be pipelined when the server supports ESMTP command pipelining.

    @@ -95,10 +94,6 @@ names are shown in upper case, they are in fact case insensitive. is unavailable. Address information is not enclosed with [].

    -
  • When both the NAME and ADDR attributes have the value - [UNAVAILABLE], the upcoming MAIL FROM transaction corresponds - to a local submission.

    -
  • The PORT attribute specifies an up-stream client TCP port number in decimal, or [UNAVAILABLE] when the information is unavailable.

    @@ -155,9 +150,8 @@ initializes all XFORWARD attributes to [UNAVAILABLE]. With each valid XFORWARD command, the server updates XFORWARD attributes with the specified values.

    -

    When the server uses XFORWARD attributes for logging purposes, -it must not mix XFORWARD attributes with attributes from the current -SMTP session.

    +

    The server must not mix client attributes from XFORWARD with +client attributes from the current SMTP session.

    At the end of each MAIL FROM transaction (i.e. RSET or DOT), the server resets all XFORWARD attributes to the undefined state, diff --git a/postfix/src/global/deliver_request.h b/postfix/src/global/deliver_request.h index 1d8372e0b..2c74c00f7 100644 --- a/postfix/src/global/deliver_request.h +++ b/postfix/src/global/deliver_request.h @@ -53,6 +53,12 @@ typedef struct DELIVER_REQUEST { int dsn_ret; /* DSN full/header notification */ } DELIVER_REQUEST; + /* + * Since we can't send null pointers, null strings represent unavailable + * attributes instead. They're less likely to explode in our face, too. + */ +#define DEL_REQ_ATTR_AVAIL(a) (*(a)) + /* * How to deliver, really? */ diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h index a3a9fde6a..4f92c15e5 100644 --- a/postfix/src/global/mail_proto.h +++ b/postfix/src/global/mail_proto.h @@ -174,7 +174,7 @@ extern char *mail_pathname(const char *, const char *); #define MAIL_ATTR_LOG_CLIENT_PORT "log_client_port" /* client port */ #define MAIL_ATTR_LOG_HELO_NAME "log_helo_name" /* SMTP helo name */ #define MAIL_ATTR_LOG_PROTO_NAME "log_protocol_name" /* SMTP/ESMTP/QMQP */ -#define MAIL_ATTR_LOG_CLIENT_DUMMY "log_client_dummy" /* none of the above */ +#define MAIL_ATTR_LOG_ORIGIN "log_message_origin" /* name[addr]:port */ #define MAIL_ATTR_ACT_CLIENT "client"/* client name addr */ #define MAIL_ATTR_ACT_CLIENT_NAME "client_name" /* client name */ @@ -187,27 +187,9 @@ extern char *mail_pathname(const char *, const char *); #define MAIL_ATTR_ACT_FORWARD_CLIENT_NAME "forward_client_name" #define MAIL_ATTR_PROTO_STATE "protocol_state" /* MAIL/RCPT/... */ - - /* - * Local submissions do not provide an origin record. - */ -#define MAIL_ATTR_LOG_ORIGIN "log_message_origin" /* name[addr]:port */ #define MAIL_ATTR_ORG_NONE "unknown" /* origin unknown */ #define MAIL_ATTR_ORG_LOCAL "local" /* local submission */ - /* - * Non-existent attribute values are represented as empty strings (e.g. no - * remote client, or no HELO hostname). Unknown attribute values are - * represented as "unknown" (e.g., unknown remote client hostname). An empty - * string is more convenient to send than a null pointer, and is less likely - * to blow up. - */ -#define MAIL_ATTR_VAL_NONEXIST "" -#define MAIL_ATTR_VAL_UNKNOWN "unknown" - -#define MAIL_ATTR_IS_EXIST(a) (*(a)) -#define MAIL_ATTR_IS_KNOWN(a) ((*(a)) && strcmp((a), MAIL_ATTR_VAL_UNKNOWN)) - /* * XCLIENT/XFORWARD in SMTP. */ diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 0aabde098..a2cbf9e62 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,19 +20,19 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20081010" +#define MAIL_RELEASE_DATE "20081012" #define MAIL_VERSION_NUMBER "2.6" #ifdef SNAPSHOT -#define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE +# define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE #else -#define MAIL_VERSION_DATE "" +# define MAIL_VERSION_DATE "" #endif #ifdef NONPROD -#define MAIL_VERSION_PROD "-nonprod" +# define MAIL_VERSION_PROD "-nonprod" #else -#define MAIL_VERSION_PROD "" +# define MAIL_VERSION_PROD "" #endif #define VAR_MAIL_VERSION "mail_version" diff --git a/postfix/src/oqmgr/qmgr_message.c b/postfix/src/oqmgr/qmgr_message.c index 8d738d4b7..b3a7b15a1 100644 --- a/postfix/src/oqmgr/qmgr_message.c +++ b/postfix/src/oqmgr/qmgr_message.c @@ -662,8 +662,6 @@ static int qmgr_message_read(QMGR_MESSAGE *message) myfree(message->client_helo); message->client_helo = mystrdup(value); have_log_client_attr = 1; - } else if (strcmp(name, MAIL_ATTR_LOG_CLIENT_DUMMY) == 0) { - have_log_client_attr = 1; } else if (strcmp(name, MAIL_ATTR_SASL_METHOD) == 0) { if (message->sasl_method == 0) message->sasl_method = mystrdup(value); diff --git a/postfix/src/qmgr/qmgr_message.c b/postfix/src/qmgr/qmgr_message.c index 4b1a26d9c..24a981ed7 100644 --- a/postfix/src/qmgr/qmgr_message.c +++ b/postfix/src/qmgr/qmgr_message.c @@ -703,8 +703,6 @@ static int qmgr_message_read(QMGR_MESSAGE *message) myfree(message->client_helo); message->client_helo = mystrdup(value); have_log_client_attr = 1; - } else if (strcmp(name, MAIL_ATTR_LOG_CLIENT_DUMMY) == 0) { - have_log_client_attr = 1; } else if (strcmp(name, MAIL_ATTR_SASL_METHOD) == 0) { if (message->sasl_method == 0) message->sasl_method = mystrdup(value); diff --git a/postfix/src/qmqpd/qmqpd.c b/postfix/src/qmqpd/qmqpd.c index 30bc49d7b..bb86c614d 100644 --- a/postfix/src/qmqpd/qmqpd.c +++ b/postfix/src/qmqpd/qmqpd.c @@ -318,10 +318,18 @@ static void qmqpd_write_attributes(QMQPD_STATE *state) { /* - * Logging attribute for the Postfix 2.3+ cleanup server. + * Logging attributes, also used for XFORWARD. */ + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_LOG_CLIENT_NAME, state->name); + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_LOG_CLIENT_ADDR, state->rfc_addr); + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_LOG_CLIENT_PORT, state->port); rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_LOG_ORIGIN, state->namaddr); + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_LOG_PROTO_NAME, state->protocol); /* * For consistency with the smtpd Milter client, we need to provide the @@ -334,15 +342,16 @@ static void qmqpd_write_attributes(QMQPD_STATE *state) */ rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_ACT_CLIENT_NAME, state->name); - /* XXX Backwards compatibility: include IPv6: prefix. */ rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", - MAIL_ATTR_ACT_CLIENT_ADDR, state->rfc_addr); + MAIL_ATTR_ACT_CLIENT_ADDR, state->addr); rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_ACT_CLIENT_PORT, state->port); rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%u", MAIL_ATTR_ACT_CLIENT_AF, state->addr_family); rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", - MAIL_ATTR_ACT_PROTO_NAME, state->protocol); + MAIL_ATTR_ACT_PROTO_NAME, state->protocol); + + /* XXX What about the address rewriting context? */ } /* qmqpd_copy_recipients - copy message recipients */ diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c index 26668620e..ab80bcc63 100644 --- a/postfix/src/smtp/smtp_proto.c +++ b/postfix/src/smtp/smtp_proto.c @@ -1221,23 +1221,20 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state, */ case SMTP_STATE_XFORWARD_NAME_ADDR: vstring_strcpy(next_command, XFORWARD_CMD); - if (session->features & SMTP_FEATURE_XFORWARD_NAME) { + if ((session->features & SMTP_FEATURE_XFORWARD_NAME) + && DEL_REQ_ATTR_AVAIL(request->client_name)) { vstring_strcat(next_command, " " XFORWARD_NAME "="); - xtext_quote_append(next_command, - MAIL_ATTR_IS_KNOWN(request->client_name) ? - request->client_name : XFORWARD_UNAVAILABLE, ""); + xtext_quote_append(next_command, request->client_name, ""); } - if (session->features & SMTP_FEATURE_XFORWARD_ADDR) { + if ((session->features & SMTP_FEATURE_XFORWARD_ADDR) + && DEL_REQ_ATTR_AVAIL(request->client_addr)) { vstring_strcat(next_command, " " XFORWARD_ADDR "="); - xtext_quote_append(next_command, - MAIL_ATTR_IS_KNOWN(request->client_addr) ? - request->client_addr : XFORWARD_UNAVAILABLE, ""); + xtext_quote_append(next_command, request->client_addr, ""); } - if (session->features & SMTP_FEATURE_XFORWARD_PORT) { + if ((session->features & SMTP_FEATURE_XFORWARD_PORT) + && DEL_REQ_ATTR_AVAIL(request->client_port)) { vstring_strcat(next_command, " " XFORWARD_PORT "="); - xtext_quote_append(next_command, - MAIL_ATTR_IS_KNOWN(request->client_port) ? - request->client_port : XFORWARD_UNAVAILABLE, ""); + xtext_quote_append(next_command, request->client_port, ""); } if (session->send_proto_helo) next_state = SMTP_STATE_XFORWARD_PROTO_HELO; @@ -1247,23 +1244,20 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state, case SMTP_STATE_XFORWARD_PROTO_HELO: vstring_strcpy(next_command, XFORWARD_CMD); - if (session->features & SMTP_FEATURE_XFORWARD_PROTO) { + if ((session->features & SMTP_FEATURE_XFORWARD_PROTO) + && DEL_REQ_ATTR_AVAIL(request->client_proto)) { vstring_strcat(next_command, " " XFORWARD_PROTO "="); - xtext_quote_append(next_command, - MAIL_ATTR_IS_KNOWN(request->client_proto) ? - request->client_proto : XFORWARD_UNAVAILABLE, ""); + xtext_quote_append(next_command, request->client_proto, ""); } - if (session->features & SMTP_FEATURE_XFORWARD_HELO) { + if ((session->features & SMTP_FEATURE_XFORWARD_HELO) + && DEL_REQ_ATTR_AVAIL(request->client_helo)) { vstring_strcat(next_command, " " XFORWARD_HELO "="); - xtext_quote_append(next_command, - MAIL_ATTR_IS_EXIST(request->client_helo) ? - request->client_helo : XFORWARD_UNAVAILABLE, ""); + xtext_quote_append(next_command, request->client_helo, ""); } - if (session->features & SMTP_FEATURE_XFORWARD_DOMAIN) { + if ((session->features & SMTP_FEATURE_XFORWARD_DOMAIN) + && DEL_REQ_ATTR_AVAIL(request->rewrite_context)) { vstring_strcat(next_command, " " XFORWARD_DOMAIN "="); xtext_quote_append(next_command, - MAIL_ATTR_IS_EXIST(request->rewrite_context) == 0 ? - XFORWARD_UNAVAILABLE : strcmp(request->rewrite_context, MAIL_ATTR_RWR_LOCAL) ? XFORWARD_DOM_REMOTE : XFORWARD_DOM_LOCAL, ""); } @@ -1932,24 +1926,27 @@ int smtp_xfer(SMTP_STATE *state) /* * Use XFORWARD to forward the origin of this email message across an - * SMTP-based content filter. Send client attribute information even in - * the case of local submissions, which have no client attributes. This - * fixes a minor problem that was introduced with Postfix 2.1: no client - * attribute information was sent in the case of local submissions, and - * therefore local submissions appeared to originate from the SMTP-based - * content filter. To make this work we introduced one change to the - * XFORWARD protocol: when both NAME and ADDR values are [UNAVAILABLE], - * this is a local submission. + * SMTP-based content filter. Send client attribute information only if + * it exists (i.e. remote submission). Local submissions have no client + * attributes; the mail will appear to originate from the content filter + * which is acceptable. */ send_name_addr = var_smtp_send_xforward - && (session->features & (SMTP_FEATURE_XFORWARD_NAME - | SMTP_FEATURE_XFORWARD_ADDR)); + && (((session->features & SMTP_FEATURE_XFORWARD_NAME) + && DEL_REQ_ATTR_AVAIL(request->client_name)) + || ((session->features & SMTP_FEATURE_XFORWARD_ADDR) + && DEL_REQ_ATTR_AVAIL(request->client_addr)) + || ((session->features & SMTP_FEATURE_XFORWARD_PORT) + && DEL_REQ_ATTR_AVAIL(request->client_port))); session->send_proto_helo = var_smtp_send_xforward - && (session->features & (SMTP_FEATURE_XFORWARD_PROTO - | SMTP_FEATURE_XFORWARD_HELO - | SMTP_FEATURE_XFORWARD_DOMAIN)); + && (((session->features & SMTP_FEATURE_XFORWARD_PROTO) + && DEL_REQ_ATTR_AVAIL(request->client_proto)) + || ((session->features & SMTP_FEATURE_XFORWARD_HELO) + && DEL_REQ_ATTR_AVAIL(request->client_helo)) + || ((session->features & SMTP_FEATURE_XFORWARD_DOMAIN) + && DEL_REQ_ATTR_AVAIL(request->rewrite_context))); if (send_name_addr) recv_state = send_state = SMTP_STATE_XFORWARD_NAME_ADDR; else if (session->send_proto_helo) diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 3440430c5..4d4c76239 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -1763,46 +1763,26 @@ static int mail_open_stream(SMTPD_STATE *state) if (SMTPD_STAND_ALONE(state) == 0) { /* - * Forwarded client attributes. These propagate original client - * information through an SMTP-based content filter, to improve - * the logging from an after-filter MTA. + * Attributes for logging, also used for XFORWARD. * - * In the case of a remote submission, send all client attributes, - * including ones with missing values. Otherwise, an unknown - * client hostname would be treated as a non-existent hostname - * (i.e. local submission). - * - * In the case of a forwarded local submission, specify explicitly - * that the original client attributes are non-existent. - * Otherwise, the real client attributes would be used, and mail - * would appear to come from the content filter. + * We store all client attributes, including ones with unknown + * values. Otherwise, an unknown client hostname would be treated + * as a non-existent hostname (i.e. local submission). */ - if (SMTPD_HAVE_XFORWARD_ATTR(state)) { - if (MAIL_ATTR_IS_KNOWN(state->xforward.name) - || MAIL_ATTR_IS_KNOWN(state->xforward.addr)) { - rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", - MAIL_ATTR_LOG_CLIENT_NAME, state->xforward.name); - /* XXX Backwards compatibility: include IPv6: prefix. */ - rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", - MAIL_ATTR_LOG_CLIENT_ADDR, state->xforward.rfc_addr); - rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", - MAIL_ATTR_LOG_ORIGIN, state->xforward.namaddr); - rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", - MAIL_ATTR_LOG_CLIENT_PORT, state->xforward.port); - if (state->xforward.helo_name) - rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", - MAIL_ATTR_LOG_HELO_NAME, state->xforward.helo_name); - rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", - MAIL_ATTR_LOG_PROTO_NAME, state->xforward.protocol); - } else { - /* Local submission. See also qmgr_message_read(). */ - rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", - MAIL_ATTR_LOG_CLIENT_DUMMY, "dummy"); - } - } else { + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_LOG_CLIENT_NAME, FORWARD_NAME(state)); + /* XXX Note: state->rfc_addr, not state->addr. */ + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_LOG_CLIENT_ADDR, FORWARD_ADDR(state)); + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_LOG_CLIENT_PORT, FORWARD_PORT(state)); + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_LOG_ORIGIN, FORWARD_NAMADDR(state)); + if (FORWARD_HELO(state)) rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", - MAIL_ATTR_LOG_ORIGIN, state->namaddr); - } + MAIL_ATTR_LOG_HELO_NAME, FORWARD_HELO(state)); + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_LOG_PROTO_NAME, FORWARD_PROTO(state)); /* * Attributes with actual client information. These are used by @@ -1818,9 +1798,9 @@ static int mail_open_stream(SMTPD_STATE *state) MAIL_ATTR_ACT_CLIENT_NAME, state->name); rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_ACT_REVERSE_CLIENT_NAME, state->reverse_name); - /* XXX Backwards compatibility: include IPv6: prefix. */ + /* XXX Note: state->addr, not state->rfc_addr. */ rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", - MAIL_ATTR_ACT_CLIENT_ADDR, state->rfc_addr); + MAIL_ATTR_ACT_CLIENT_ADDR, state->addr); rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_ACT_CLIENT_PORT, state->port); if (state->helo_name) diff --git a/postfix/src/smtpd/smtpd.h b/postfix/src/smtpd/smtpd.h index e796ac65d..cef00062f 100644 --- a/postfix/src/smtpd/smtpd.h +++ b/postfix/src/smtpd/smtpd.h @@ -228,20 +228,29 @@ extern void smtpd_state_reset(SMTPD_STATE *); #define SMTPD_CMD_UNKNOWN "UNKNOWN" /* - * Representation of missing and non-existent client information. Throughout - * Postfix, we use the "unknown" string value for missing client information - * (e.g., unknown remote client hostname), and we use the empty string or - * null pointer for non-existent client information (e.g., no HELO command, - * or local submission). + * Representation of unknown and non-existent client information. Throughout + * Postfix, we use the "unknown" string value for unknown client information + * (e.g., unknown remote client hostname), and we use the empty string, null + * pointer or "no queue file record" for non-existent client information + * (e.g., no HELO command, or local submission). * - * When XFORWARD support was introduced with Postfix 2.1, the specification - * failed to clearly distinguish between missing and non-existent client - * information. This ambiguity affected the implementation: unknown client - * hostnames could become empty strings (as if a submission was local), and - * local submissions could appear to originate from an SMTP-based content - * filter. This was corrected during the Postfix 2.6 development cycle by - * introducing one semantic change to the XFORWARD protocol: when both NAME - * and ADDR values are [UNAVAILABLE], this is a local submission. + * Inside the SMTP server, unknown real client attributes are represented by + * the string "unknown", and non-existent HELO is represented as a null + * pointer. The SMTP server uses this same representation internally for + * forwarded client attributes; the XFORWARD syntax makes no distinction + * between unknown (remote submission) and non-existent (local submission). + * + * The SMTP client sends forwarded client attributes only when upstream client + * attributes exist (i.e. remote submission). Thus, local submissions will + * appear to come from an SMTP-based content filter, which is acceptable. + * + * Known/unknown client attribute values use the SMTP server's internal + * representation in queue files, in queue manager delivery requests, and in + * delivery agent $name expansions. + * + * Non-existent attribute values are never present in queue files. Non-existent + * information is represented as empty strings in queue manager delivery + * requests and in delivery agent $name expansions. */ #define CLIENT_ATTR_UNKNOWN "unknown" @@ -299,34 +308,12 @@ extern void smtpd_peer_reset(SMTPD_STATE *state); (port), (char *) 0) /* - * Choose between normal or forwarded attributes. - * - * Inside the SMTP server, unknown real client attributes are represented by - * the string "unknown", and non-existent HELO is represented as a null - * pointer. The SMTP server uses this same representation internally for - * forwarded client attributes; the XFORWARD syntax makes no distinction - * between unknown (remote submission) and non-existent (local submission). - * The SMTP server decides between remote and local submission when it - * generates queue file records (see below) so that the correct result is - * produced with down-stream logging and with $name expansion in delivery - * agents. - * - * Known/unknown client attribute values use the SMTP server's internal - * representation in queue files, in queue manager delivery requests, and in - * delivery agent $name expansions. - * - * Non-existent attribute values are never present in queue files. The SMTP - * server stores a dummy attribute to indicate that no client attributes - * exist. Non-existent information is represented as empty strings in queue - * manager delivery requests and in delivery agent $name expansions. - * - * When forwarding client information, don't mix information from the current - * SMTP session with forwarded information from an up-stream session. + * Don't mix information from the current SMTP session with forwarded + * information from an up-stream session. */ -#define SMTPD_HAVE_XFORWARD_ATTR(s) \ - ((s)->xforward.flags & SMTPD_STATE_XFORWARD_INIT) #define FORWARD_CLIENT_ATTR(s, a) \ - (SMTPD_HAVE_XFORWARD_ATTR(s) ? (s)->xforward.a : (s)->a) + (((s)->xforward.flags & SMTPD_STATE_XFORWARD_CLIENT_MASK) ? \ + (s)->xforward.a : (s)->a) #define FORWARD_ADDR(s) FORWARD_CLIENT_ATTR((s), rfc_addr) #define FORWARD_NAME(s) FORWARD_CLIENT_ATTR((s), name)