diff --git a/postfix/HISTORY b/postfix/HISTORY index b69e9ed84..51750adaa 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -14439,7 +14439,26 @@ Apologies for any names omitted. (Postfix 2.1) and smtp/lmtp_generic_maps (Postfix 2.3). File: global/mail_params.h. - Cleanup: the SMTP server's XFORWARD and XCLIENT support - was not updated when the smtpd_client_port_logging configuration + Cleanup: the SMTP server's XFORWARD and XCLIENT support was + not updated when the smtpd_client_port_logging configuration parameter was added. Code by Victor Duchovni. Files: smtpd/smtpd.c, smtpd/smtpd_peer.c. + +20080508 + + Cleanup: delivery status notifications now prepend a + Return-Path: message header to the returned message. + File: bounce/bounce_notify_util.c. + +20080509 + + Bugfix: null-terminate CN comment string after sanitization. + File: smtpd/smtpd.c. + +20080510 + + Cleanup: when extracting common name and issuer name from + TLS certificates, convert the result into UTF-8, and use + RFC 2047 encoding when logging these as Received: header + comment fields. Based remotely on code by Victor Duchovni. + Files: smtpd/smtpd.c, tls/tls_verify.c. diff --git a/postfix/README_FILES/SMTPD_POLICY_README b/postfix/README_FILES/SMTPD_POLICY_README index dbedde37d..80e2edbe9 100644 --- a/postfix/README_FILES/SMTPD_POLICY_README +++ b/postfix/README_FILES/SMTPD_POLICY_README @@ -126,7 +126,10 @@ Notes: how the client was authenticated via TLS. These attributes are empty in case of no certificate authentication. As of Postfix 2.2.11 these attribute values are encoded as xtext: some characters are represented by +XX, where - XX is the two-digit hexadecimal representation of the character value. + XX is the two-digit hexadecimal representation of the character value. With + Postfix 2.5 and later, the decoded string may contain non-ASCII characters. + If so, this is a UTF-8 string; xtext encoding works with the bytes of the + UTF-8 string, not the characters. * The "encryption_*" attributes (Postfix 2.3 and later) specify information about how the connection is encrypted. With plaintext connections the diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index d3ec800e2..fb605fea6 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -17,6 +17,13 @@ Incompatibility with Postfix 2.4 and earlier If you upgrade from Postfix 2.4 or earlier, read RELEASE_NOTES-2.5 before proceeding. +Incompatibility with snapshot 20080510 +====================================== + +In the policy delegation protocol, certificate common name attributes +are now xtext encoded UTF-8. The xtext decoded attributes may contain +any UTF-8 value including control characters. + Incompatibility with snapshot 20080428 ====================================== diff --git a/postfix/conf/access b/postfix/conf/access index 9d396594e..18930449e 100644 --- a/postfix/conf/access +++ b/postfix/conf/access @@ -192,24 +192,24 @@ # # REJECT optional text... # Reject the address etc. that matches the pattern. -# Reply with $reject_code optional text... when the -# optional text is specified, otherwise reply with a -# generic error response message. +# Reply with "$access_map_reject_code optional +# text..." when the optional text is specified, oth- +# erwise reply with a generic error response message. # # DEFER_IF_REJECT optional text... -# Defer the request if some later restriction would -# result in a REJECT action. Reply with "450 4.7.1 -# optional text... when the optional text is speci- +# Defer the request if some later restriction would +# result in a REJECT action. Reply with "450 4.7.1 +# optional text..." when the optional text is speci- # fied, otherwise reply with a generic error response # message. # # This feature is available in Postfix 2.1 and later. # # DEFER_IF_PERMIT optional text... -# Defer the request if some later restriction would -# result in a an explicit or implicit PERMIT action. -# Reply with "450 4.7.1 optional text... when the -# optional text is specified, otherwise reply with a +# Defer the request if some later restriction would +# result in a an explicit or implicit PERMIT action. +# Reply with "450 4.7.1 optional text..." when the +# optional text is specified, otherwise reply with a # generic error response message. # # This feature is available in Postfix 2.1 and later. @@ -220,169 +220,169 @@ # reject_unauth_destination, and so on). # # BCC user@domain -# Send one copy of the message to the specified +# Send one copy of the message to the specified # recipient. # -# If multiple BCC actions are specified within the -# same SMTP MAIL transaction, only the last action +# If multiple BCC actions are specified within the +# same SMTP MAIL transaction, only the last action # will be used. # -# This feature is not part of the stable Postfix +# This feature is not part of the stable Postfix # release. # # DISCARD optional text... -# Claim successful delivery and silently discard the -# message. Log the optional text if specified, oth- +# Claim successful delivery and silently discard the +# message. Log the optional text if specified, oth- # erwise log a generic message. # -# Note: this action currently affects all recipients -# of the message. To discard only one recipient -# without discarding the entire message, use the +# Note: this action currently affects all recipients +# of the message. To discard only one recipient +# without discarding the entire message, use the # transport(5) table to direct mail to the discard(8) # service. # # This feature is available in Postfix 2.0 and later. # -# DUNNO Pretend that the lookup key was not found. This -# prevents Postfix from trying substrings of the -# lookup key (such as a subdomain name, or a network +# DUNNO Pretend that the lookup key was not found. This +# prevents Postfix from trying substrings of the +# lookup key (such as a subdomain name, or a network # address subnetwork). # # This feature is available in Postfix 2.0 and later. # # FILTER transport:destination -# After the message is queued, send the entire mes- +# After the message is queued, send the entire mes- # sage through the specified external content filter. -# The transport:destination syntax is described in -# the transport(5) manual page. More information -# about external content filters is in the Postfix +# The transport:destination syntax is described in +# the transport(5) manual page. More information +# about external content filters is in the Postfix # FILTER_README file. # # Note: this action overrides the content_filter set- -# ting, and currently affects all recipients of the +# ting, and currently affects all recipients of the # message. # # This feature is available in Postfix 2.0 and later. # # HOLD optional text... -# Place the message on the hold queue, where it will -# sit until someone either deletes it or releases it -# for delivery. Log the optional text if specified, +# Place the message on the hold queue, where it will +# sit until someone either deletes it or releases it +# for delivery. Log the optional text if specified, # otherwise log a generic message. # -# Mail that is placed on hold can be examined with -# the postcat(1) command, and can be destroyed or +# Mail that is placed on hold can be examined with +# the postcat(1) command, and can be destroyed or # released with the postsuper(1) command. # -# Note: use "postsuper -r" to release mail that was -# kept on hold for a significant fraction of $maxi- +# Note: use "postsuper -r" to release mail that was +# kept on hold for a significant fraction of $maxi- # mal_queue_lifetime or $bounce_queue_lifetime, or -# longer. Use "postsuper -H" only for mail that will +# longer. Use "postsuper -H" only for mail that will # not expire within a few delivery attempts. # -# Note: this action currently affects all recipients +# Note: this action currently affects all recipients # of the message. # # This feature is available in Postfix 2.0 and later. # # PREPEND headername: headervalue -# Prepend the specified message header to the mes- -# sage. When more than one PREPEND action executes, -# the first prepended header appears before the sec- +# Prepend the specified message header to the mes- +# sage. When more than one PREPEND action executes, +# the first prepended header appears before the sec- # ond etc. prepended header. # -# Note: this action must execute before the message -# content is received; it cannot execute in the con- +# Note: this action must execute before the message +# content is received; it cannot execute in the con- # text of smtpd_end_of_data_restrictions. # # This feature is available in Postfix 2.1 and later. # # REDIRECT user@domain -# After the message is queued, send the message to +# After the message is queued, send the message to # the specified address instead of the intended # recipient(s). # -# Note: this action overrides the FILTER action, and +# Note: this action overrides the FILTER action, and # currently affects all recipients of the message. # # This feature is available in Postfix 2.1 and later. # # WARN optional text... # Log a warning with the optional text, together with -# client information and if available, with helo, +# client information and if available, with helo, # sender, recipient and protocol information. # # This feature is available in Postfix 2.1 and later. # # ENHANCED STATUS CODES -# Postfix version 2.3 and later support enhanced status -# codes as defined in RFC 3463. When an enhanced status -# code is specified in an access table, it is subject to -# modification. The following transformations are needed -# when the same access table is used for client, helo, -# sender, or recipient access restrictions; they happen +# Postfix version 2.3 and later support enhanced status +# codes as defined in RFC 3463. When an enhanced status +# code is specified in an access table, it is subject to +# modification. The following transformations are needed +# when the same access table is used for client, helo, +# sender, or recipient access restrictions; they happen # regardless of whether Postfix replies to a MAIL FROM, RCPT # TO or other SMTP command. # -# o When a sender address matches a REJECT action, the -# Postfix SMTP server will transform a recipient DSN -# status (e.g., 4.1.1-4.1.6) into the corresponding +# o When a sender address matches a REJECT action, the +# Postfix SMTP server will transform a recipient DSN +# status (e.g., 4.1.1-4.1.6) into the corresponding # sender DSN status, and vice versa. # -# o When non-address information matches a REJECT -# action (such as the HELO command argument or the -# client hostname/address), the Postfix SMTP server -# will transform a sender or recipient DSN status -# into a generic non-address DSN status (e.g., +# o When non-address information matches a REJECT +# action (such as the HELO command argument or the +# client hostname/address), the Postfix SMTP server +# will transform a sender or recipient DSN status +# into a generic non-address DSN status (e.g., # 4.0.0). # # REGULAR EXPRESSION TABLES -# This section describes how the table lookups change when +# This section describes how the table lookups change when # the table is given in the form of regular expressions. For -# a description of regular expression lookup table syntax, +# a description of regular expression lookup table syntax, # see regexp_table(5) or pcre_table(5). # -# Each pattern is a regular expression that is applied to +# Each pattern is a regular expression that is applied to # the entire string being looked up. Depending on the appli- -# cation, that string is an entire client hostname, an +# cation, that string is an entire client hostname, an # entire client IP address, or an entire mail address. Thus, # no parent domain or parent network search is done, -# user@domain mail addresses are not broken up into their +# user@domain mail addresses are not broken up into their # user@ and domain constituent parts, nor is user+foo broken # up into user and foo. # -# Patterns are applied in the order as specified in the ta- -# ble, until a pattern is found that matches the search +# Patterns are applied in the order as specified in the ta- +# ble, until a pattern is found that matches the search # string. # -# Actions are the same as with indexed file lookups, with -# the additional feature that parenthesized substrings from +# Actions are the same as with indexed file lookups, with +# the additional feature that parenthesized substrings from # the pattern can be interpolated as $1, $2 and so on. # # TCP-BASED TABLES -# This section describes how the table lookups change when +# This section describes how the table lookups change when # lookups are directed to a TCP-based server. For a descrip- # tion of the TCP client/server lookup protocol, see tcp_ta- # ble(5). This feature is not available up to and including # Postfix version 2.4. # -# Each lookup operation uses the entire query string once. -# Depending on the application, that string is an entire +# Each lookup operation uses the entire query string once. +# Depending on the application, that string is an entire # client hostname, an entire client IP address, or an entire -# mail address. Thus, no parent domain or parent network -# search is done, user@domain mail addresses are not broken -# up into their user@ and domain constituent parts, nor is +# mail address. Thus, no parent domain or parent network +# search is done, user@domain mail addresses are not broken +# up into their user@ and domain constituent parts, nor is # user+foo broken up into user and foo. # # Actions are the same as with indexed file lookups. # # EXAMPLE -# The following example uses an indexed file, so that the -# order of table entries does not matter. The example per- -# mits access by the client at address 1.2.3.4 but rejects -# all other clients in 1.2.3.0/24. Instead of hash lookup -# tables, some systems use dbm. Use the command "postconf -# -m" to find out what lookup tables Postfix supports on +# The following example uses an indexed file, so that the +# order of table entries does not matter. The example per- +# mits access by the client at address 1.2.3.4 but rejects +# all other clients in 1.2.3.0/24. Instead of hash lookup +# tables, some systems use dbm. Use the command "postconf +# -m" to find out what lookup tables Postfix supports on # your system. # # /etc/postfix/main.cf: @@ -393,11 +393,11 @@ # 1.2.3 REJECT # 1.2.3.4 OK # -# Execute the command "postmap /etc/postfix/access" after +# Execute the command "postmap /etc/postfix/access" after # editing the file. # # BUGS -# The table format does not understand quoting conventions. +# The table format does not understand quoting conventions. # # SEE ALSO # postmap(1), Postfix lookup table manager @@ -406,13 +406,13 @@ # transport(5), transport:nexthop syntax # # README FILES -# Use "postconf readme_directory" or "postconf html_direc- +# Use "postconf readme_directory" or "postconf html_direc- # tory" to locate this information. # SMTPD_ACCESS_README, built-in SMTP server access control # DATABASE_README, Postfix lookup table overview # # LICENSE -# The Secure Mailer license must be distributed with this +# The Secure Mailer license must be distributed with this # software. # # AUTHOR(S) diff --git a/postfix/html/SMTPD_POLICY_README.html b/postfix/html/SMTPD_POLICY_README.html index 1ad5441f6..4471aaf16 100644 --- a/postfix/html/SMTPD_POLICY_README.html +++ b/postfix/html/SMTPD_POLICY_README.html @@ -173,7 +173,10 @@ stress= These attributes are empty in case of no certificate authentication. As of Postfix 2.2.11 these attribute values are encoded as xtext: some characters are represented by +XX, where XX is the - two-digit hexadecimal representation of the character value. + two-digit hexadecimal representation of the character value. With + Postfix 2.5 and later, the decoded string may contain non-ASCII + characters. If so, this is a UTF-8 string; xtext encoding works + with the bytes of the UTF-8 string, not the characters.
The "encryption_*" attributes (Postfix 2.3 and later) diff --git a/postfix/html/access.5.html b/postfix/html/access.5.html index 230c1dcf1..7f7977df2 100644 --- a/postfix/html/access.5.html +++ b/postfix/html/access.5.html @@ -198,24 +198,24 @@ ACCESS(5) ACCESS(5) REJECT optional text... Reject the address etc. that matches the pattern. - Reply with $reject_code optional text... when the - optional text is specified, otherwise reply with a - generic error response message. + Reply with "$access_map_reject_code optional + text..." when the optional text is specified, oth- + erwise reply with a generic error response message. DEFER_IF_REJECT optional text... - Defer the request if some later restriction would - result in a REJECT action. Reply with "450 4.7.1 - optional text... when the optional text is speci- + Defer the request if some later restriction would + result in a REJECT action. Reply with "450 4.7.1 + optional text..." when the optional text is speci- fied, otherwise reply with a generic error response message. This feature is available in Postfix 2.1 and later. DEFER_IF_PERMIT optional text... - Defer the request if some later restriction would - result in a an explicit or implicit PERMIT action. - Reply with "450 4.7.1 optional text... when the - optional text is specified, otherwise reply with a + Defer the request if some later restriction would + result in a an explicit or implicit PERMIT action. + Reply with "450 4.7.1 optional text..." when the + optional text is specified, otherwise reply with a generic error response message. This feature is available in Postfix 2.1 and later. @@ -226,169 +226,169 @@ ACCESS(5) ACCESS(5) reject_unauth_destination, and so on). BCC user@domain - Send one copy of the message to the specified + Send one copy of the message to the specified recipient. - If multiple BCC actions are specified within the - same SMTP MAIL transaction, only the last action + If multiple BCC actions are specified within the + same SMTP MAIL transaction, only the last action will be used. - This feature is not part of the stable Postfix + This feature is not part of the stable Postfix release. DISCARD optional text... - Claim successful delivery and silently discard the - message. Log the optional text if specified, oth- + Claim successful delivery and silently discard the + message. Log the optional text if specified, oth- erwise log a generic message. - Note: this action currently affects all recipients - of the message. To discard only one recipient - without discarding the entire message, use the + Note: this action currently affects all recipients + of the message. To discard only one recipient + without discarding the entire message, use the transport(5) table to direct mail to the discard(8) service. This feature is available in Postfix 2.0 and later. - DUNNO Pretend that the lookup key was not found. This - prevents Postfix from trying substrings of the - lookup key (such as a subdomain name, or a network + DUNNO Pretend that the lookup key was not found. This + prevents Postfix from trying substrings of the + lookup key (such as a subdomain name, or a network address subnetwork). This feature is available in Postfix 2.0 and later. FILTER transport:destination - After the message is queued, send the entire mes- + After the message is queued, send the entire mes- sage through the specified external content filter. - The transport:destination syntax is described in - the transport(5) manual page. More information - about external content filters is in the Postfix + The transport:destination syntax is described in + the transport(5) manual page. More information + about external content filters is in the Postfix FILTER_README file. Note: this action overrides the content_filter set- - ting, and currently affects all recipients of the + ting, and currently affects all recipients of the message. This feature is available in Postfix 2.0 and later. HOLD optional text... - Place the message on the hold queue, where it will - sit until someone either deletes it or releases it - for delivery. Log the optional text if specified, + Place the message on the hold queue, where it will + sit until someone either deletes it or releases it + for delivery. Log the optional text if specified, otherwise log a generic message. - Mail that is placed on hold can be examined with - the postcat(1) command, and can be destroyed or + Mail that is placed on hold can be examined with + the postcat(1) command, and can be destroyed or released with the postsuper(1) command. - Note: use "postsuper -r" to release mail that was - kept on hold for a significant fraction of $maxi- + Note: use "postsuper -r" to release mail that was + kept on hold for a significant fraction of $maxi- mal_queue_lifetime or $bounce_queue_lifetime, or - longer. Use "postsuper -H" only for mail that will + longer. Use "postsuper -H" only for mail that will not expire within a few delivery attempts. - Note: this action currently affects all recipients + Note: this action currently affects all recipients of the message. This feature is available in Postfix 2.0 and later. PREPEND headername: headervalue - Prepend the specified message header to the mes- - sage. When more than one PREPEND action executes, - the first prepended header appears before the sec- + Prepend the specified message header to the mes- + sage. When more than one PREPEND action executes, + the first prepended header appears before the sec- ond etc. prepended header. - Note: this action must execute before the message - content is received; it cannot execute in the con- + Note: this action must execute before the message + content is received; it cannot execute in the con- text of smtpd_end_of_data_restrictions. This feature is available in Postfix 2.1 and later. REDIRECT user@domain - After the message is queued, send the message to + After the message is queued, send the message to the specified address instead of the intended recipient(s). - Note: this action overrides the FILTER action, and + Note: this action overrides the FILTER action, and currently affects all recipients of the message. This feature is available in Postfix 2.1 and later. WARN optional text... Log a warning with the optional text, together with - client information and if available, with helo, + client information and if available, with helo, sender, recipient and protocol information. This feature is available in Postfix 2.1 and later. ENHANCED STATUS CODES - Postfix version 2.3 and later support enhanced status - codes as defined in RFC 3463. When an enhanced status - code is specified in an access table, it is subject to - modification. The following transformations are needed - when the same access table is used for client, helo, - sender, or recipient access restrictions; they happen + Postfix version 2.3 and later support enhanced status + codes as defined in RFC 3463. When an enhanced status + code is specified in an access table, it is subject to + modification. The following transformations are needed + when the same access table is used for client, helo, + sender, or recipient access restrictions; they happen regardless of whether Postfix replies to a MAIL FROM, RCPT TO or other SMTP command. - o When a sender address matches a REJECT action, the - Postfix SMTP server will transform a recipient DSN - status (e.g., 4.1.1-4.1.6) into the corresponding + o When a sender address matches a REJECT action, the + Postfix SMTP server will transform a recipient DSN + status (e.g., 4.1.1-4.1.6) into the corresponding sender DSN status, and vice versa. - o When non-address information matches a REJECT - action (such as the HELO command argument or the - client hostname/address), the Postfix SMTP server - will transform a sender or recipient DSN status - into a generic non-address DSN status (e.g., + o When non-address information matches a REJECT + action (such as the HELO command argument or the + client hostname/address), the Postfix SMTP server + will transform a sender or recipient DSN status + into a generic non-address DSN status (e.g., 4.0.0). REGULAR EXPRESSION TABLES - This section describes how the table lookups change when + This section describes how the table lookups change when the table is given in the form of regular expressions. For - a description of regular expression lookup table syntax, + a description of regular expression lookup table syntax, see regexp_table(5) or pcre_table(5). - Each pattern is a regular expression that is applied to + Each pattern is a regular expression that is applied to the entire string being looked up. Depending on the appli- - cation, that string is an entire client hostname, an + cation, that string is an entire client hostname, an entire client IP address, or an entire mail address. Thus, no parent domain or parent network search is done, - user@domain mail addresses are not broken up into their + user@domain mail addresses are not broken up into their user@ and domain constituent parts, nor is user+foo broken up into user and foo. - Patterns are applied in the order as specified in the ta- - ble, until a pattern is found that matches the search + Patterns are applied in the order as specified in the ta- + ble, until a pattern is found that matches the search string. - Actions are the same as with indexed file lookups, with - the additional feature that parenthesized substrings from + Actions are the same as with indexed file lookups, with + the additional feature that parenthesized substrings from the pattern can be interpolated as $1, $2 and so on. TCP-BASED TABLES - This section describes how the table lookups change when + This section describes how the table lookups change when lookups are directed to a TCP-based server. For a descrip- tion of the TCP client/server lookup protocol, see tcp_ta- ble(5). This feature is not available up to and including Postfix version 2.4. - Each lookup operation uses the entire query string once. - Depending on the application, that string is an entire + Each lookup operation uses the entire query string once. + Depending on the application, that string is an entire client hostname, an entire client IP address, or an entire - mail address. Thus, no parent domain or parent network - search is done, user@domain mail addresses are not broken - up into their user@ and domain constituent parts, nor is + mail address. Thus, no parent domain or parent network + search is done, user@domain mail addresses are not broken + up into their user@ and domain constituent parts, nor is user+foo broken up into user and foo. Actions are the same as with indexed file lookups. EXAMPLE - The following example uses an indexed file, so that the - order of table entries does not matter. The example per- - mits access by the client at address 1.2.3.4 but rejects - all other clients in 1.2.3.0/24. Instead of hash lookup - tables, some systems use dbm. Use the command "postconf - -m" to find out what lookup tables Postfix supports on + The following example uses an indexed file, so that the + order of table entries does not matter. The example per- + mits access by the client at address 1.2.3.4 but rejects + all other clients in 1.2.3.0/24. Instead of hash lookup + tables, some systems use dbm. Use the command "postconf + -m" to find out what lookup tables Postfix supports on your system. /etc/postfix/main.cf: @@ -399,11 +399,11 @@ ACCESS(5) ACCESS(5) 1.2.3 REJECT 1.2.3.4 OK - Execute the command "postmap /etc/postfix/access" after + Execute the command "postmap /etc/postfix/access" after editing the file. BUGS - The table format does not understand quoting conventions. + The table format does not understand quoting conventions. SEE ALSO postmap(1), Postfix lookup table manager @@ -416,7 +416,7 @@ ACCESS(5) ACCESS(5) DATABASE_README, Postfix lookup table overview LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/makedefs b/postfix/makedefs index df3e7717c..0053b4508 100644 --- a/postfix/makedefs +++ b/postfix/makedefs @@ -479,7 +479,7 @@ esac : ${CC='gcc $(WARN)'} ${OPT='-O'} ${DEBUG='-g'} ${AWK=awk} \ ${WARN='-Wall -Wno-comment -Wformat -Wimplicit -Wmissing-prototypes \ -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \ - -Wunused'} + -Wunused -Wno-missing-braces'} export SYSTYPE AR ARFL RANLIB SYSLIBS CC OPT DEBUG AWK OPTS diff --git a/postfix/man/man5/access.5 b/postfix/man/man5/access.5 index e96f4ad3b..a35383b7c 100644 --- a/postfix/man/man5/access.5 +++ b/postfix/man/man5/access.5 @@ -190,12 +190,13 @@ The reply code "421" causes Postfix to disconnect immediately (Postfix version 2.3 and later). .IP "\fBREJECT \fIoptional text...\fR Reject the address etc. that matches the pattern. Reply with -\fI$reject_code optional text...\fR when the optional text is +"\fB$access_map_reject_code \fIoptional text...\fR" when the +optional text is specified, otherwise reply with a generic error response message. .IP "\fBDEFER_IF_REJECT \fIoptional text...\fR Defer the request if some later restriction would result in a REJECT action. Reply with "\fB450 4.7.1 \fI optional -text...\fR when the +text...\fR" when the optional text is specified, otherwise reply with a generic error response message. .sp @@ -203,7 +204,7 @@ This feature is available in Postfix 2.1 and later. .IP "\fBDEFER_IF_PERMIT \fIoptional text...\fR Defer the request if some later restriction would result in a an explicit or implicit PERMIT action. -Reply with "\fB450 4.7.1 \fI optional text...\fR when the +Reply with "\fB450 4.7.1 \fI optional text...\fR" when the optional text is specified, otherwise reply with a generic error response message. .sp diff --git a/postfix/proto/SMTPD_POLICY_README.html b/postfix/proto/SMTPD_POLICY_README.html index bdf797097..d3e6f005f 100644 --- a/postfix/proto/SMTPD_POLICY_README.html +++ b/postfix/proto/SMTPD_POLICY_README.html @@ -173,7 +173,10 @@ stress= These attributes are empty in case of no certificate authentication. As of Postfix 2.2.11 these attribute values are encoded as xtext: some characters are represented by +XX, where XX is the - two-digit hexadecimal representation of the character value. + two-digit hexadecimal representation of the character value. With + Postfix 2.5 and later, the decoded string may contain non-ASCII + characters. If so, this is a UTF-8 string; xtext encoding works + with the bytes of the UTF-8 string, not the characters.
The "encryption_*" attributes (Postfix 2.3 and later) diff --git a/postfix/proto/access b/postfix/proto/access index 665cc9e8f..088b87eee 100644 --- a/postfix/proto/access +++ b/postfix/proto/access @@ -170,12 +170,13 @@ # (Postfix version 2.3 and later). # .IP "\fBREJECT \fIoptional text...\fR # Reject the address etc. that matches the pattern. Reply with -# \fI$reject_code optional text...\fR when the optional text is +# "\fB$access_map_reject_code \fIoptional text...\fR" when the +# optional text is # specified, otherwise reply with a generic error response message. # .IP "\fBDEFER_IF_REJECT \fIoptional text...\fR # Defer the request if some later restriction would result in a # REJECT action. Reply with "\fB450 4.7.1 \fI optional -# text...\fR when the +# text...\fR" when the # optional text is specified, otherwise reply with a generic error # response message. # .sp @@ -183,7 +184,7 @@ # .IP "\fBDEFER_IF_PERMIT \fIoptional text...\fR # Defer the request if some later restriction would result in a # an explicit or implicit PERMIT action. -# Reply with "\fB450 4.7.1 \fI optional text...\fR when the +# Reply with "\fB450 4.7.1 \fI optional text...\fR" when the # optional text is specified, otherwise reply with a generic error # response message. # .sp diff --git a/postfix/src/bounce/bounce_notify_util.c b/postfix/src/bounce/bounce_notify_util.c index 44a91ab55..9cdf264ff 100644 --- a/postfix/src/bounce/bounce_notify_util.c +++ b/postfix/src/bounce/bounce_notify_util.c @@ -772,6 +772,16 @@ int bounce_original(VSTREAM *bounce, BOUNCE_INFO *bounce_info, return (vstream_ferror(bounce)); } + /* + * XXX The cleanup server removes Return-Path: headers. This should be + * done only with mail that enters via a non-SMTP channel, but changing + * this now could break other software. Removing Return-Path: could break + * digital signatures, though this is unlikely. In any case, + * header_checks are more effective when the Return-Path: header is + * present, so we prepend one to the bounce message. + */ + post_mail_fprintf(bounce, "Return-Path: <%s>", STR(bounce_info->sender)); + /* * Copy the original message contents. We're doing raw record output here * so that we don't throw away binary transparency yet. diff --git a/postfix/src/global/header_opts.c b/postfix/src/global/header_opts.c index 0461502ff..08808f2d9 100644 --- a/postfix/src/global/header_opts.c +++ b/postfix/src/global/header_opts.c @@ -47,6 +47,10 @@ /* * Header names are given in the preferred capitalization. The lookups are * case-insensitive. + * + * XXX Removing Return-Path: headers should probably be done only with mail + * that enters via a non-SMTP channel. Changing this now could break other + * software. See also comments in bounce_notify_util.c. */ static const HEADER_OPTS header_opts[] = { "Apparently-To", HDR_APPARENTLY_TO, HDR_OPT_RECIP, diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 8da1f6906..c3fdb6d8d 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 "20080428" +#define MAIL_RELEASE_DATE "20080510" #define MAIL_VERSION_NUMBER "2.6" #ifdef SNAPSHOT diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index a3b32d79f..c1c3b8710 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -2496,6 +2496,60 @@ static void rcpt_reset(SMTPD_STATE *state) state->rcpt_overshoot = 0; } +/* rfc2047_comment_encode - encode comment string */ + +static VSTRING *rfc2047_comment_encode(const char *str, const char *charset) +{ + VSTRING *buf = vstring_alloc(30); + const unsigned char *cp; + int ch; + + /* + * XXX Most of the RFC 2047 "especials" are not special in RFC*822 + * comments, but we encode them anyway to avoid complaints. + * + * XXX In Received: header comments we enclose peer and issuer common names + * with "" quotes. This is the cause of several quirks. + * + * 1) We encode text that contains the " character, even though that + * character is not special for RFC*822. + * + * 2) Long comments look ugly when folded in-between quotes, so we ignore + * the recommended limit of 75 characters per encoded word. + * + * 3) We must encode the the enclosing quotes, to avoid producing invalid + * encoded words. + */ +#define ESPECIALS "()<>@,;:\"/[]?.=" /* Special in RFC 2047 */ +#define CSPECIALS "\\\"()" /* Special in our comments */ + + /* Don't encode if not needed. */ + for (cp = (unsigned char *) str; /* see below */ ; ++cp) { + if ((ch = *cp) == 0) { + vstring_sprintf(buf, "\"%s\"", str); + return (buf); + } + if (!ISPRINT(ch) || strchr(CSPECIALS, ch)) + break; + } + + /* + * Use quoted-printable (like) encoding with spaces mapped to underscore. + */ + vstring_sprintf(buf, "=?%s?Q?=%02X", charset, '"'); + for (cp = (unsigned char *) str; (ch = *cp) != 0; ++cp) { + if (!ISPRINT(ch) || strchr(ESPECIALS CSPECIALS, ch)) { + vstring_sprintf_append(buf, "=%02X", ch); + } else if (ch == ' ') { + VSTRING_ADDCH(buf, '_'); + } else { + VSTRING_ADDCH(buf, ch); + } + } + vstring_sprintf_append(buf, "=%02X?=", '"'); + return (buf); +} + /* comment_sanitize - clean up comment string */ static void comment_sanitize(VSTRING *comment_string) @@ -2526,6 +2580,7 @@ static void comment_sanitize(VSTRING *comment_string) } while (pc-- > 0) VSTRING_ADDCH(comment_string, ')'); + VSTRING_TERMINATE(comment_string); } /* data_cmd - process DATA command */ @@ -2654,6 +2709,10 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) #define VSTRING_STRDUP(s) vstring_strcpy(vstring_alloc(strlen(s) + 1), (s)) + /* + * Certificate CN information is arbitrary content in the UTF-8 + * character set. + */ #ifdef USE_TLS if (var_smtpd_tls_received_header && state->tls_context) { out_fprintf(out_stream, REC_TYPE_NORM, @@ -2663,13 +2722,14 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) state->tls_context->cipher_usebits, state->tls_context->cipher_algbits); if (TLS_CERT_IS_PRESENT(state->tls_context)) { - peer_CN = VSTRING_STRDUP(state->tls_context->peer_CN); - comment_sanitize(peer_CN); - issuer_CN = VSTRING_STRDUP(state->tls_context->issuer_CN ? - state->tls_context->issuer_CN : ""); - comment_sanitize(issuer_CN); + peer_CN = + rfc2047_comment_encode(state->tls_context->peer_CN, + "utf-8"); + issuer_CN = + rfc2047_comment_encode(state->tls_context->issuer_CN, + "utf-8"); out_fprintf(out_stream, REC_TYPE_NORM, - "\t(Client CN \"%s\", Issuer \"%s\" (%s))", + "\t(Client CN %s, Issuer %s (%s))", STR(peer_CN), STR(issuer_CN), TLS_CERT_IS_TRUSTED(state->tls_context) ? "verified OK" : "not verified"); diff --git a/postfix/src/smtpd/smtpd.h b/postfix/src/smtpd/smtpd.h index ac7bb5430..bc3aa25c6 100644 --- a/postfix/src/smtpd/smtpd.h +++ b/postfix/src/smtpd/smtpd.h @@ -180,14 +180,6 @@ typedef struct SMTPD_STATE { ssize_t milter_argc; } SMTPD_STATE; - /* - * Construct name[addr] or name[addr]:port as appropriate - */ -#define SMTPD_BUILD_NAMADDRPORT(name, addr, port) \ - concatenate((name), "[", (addr), "]", \ - var_smtpd_client_port_log ? ":" : (char *) 0, \ - (port), (char *) 0) - #define SMTPD_FLAG_HANGUP (1<<0) /* disconnect */ #define SMTPD_STATE_XFORWARD_INIT (1<<0) /* xforward preset done */ @@ -287,6 +279,14 @@ extern void smtpd_peer_reset(SMTPD_STATE *state); #define SMTPD_PEER_CODE_PERM 5 #define SMTPD_PEER_CODE_FORGED 6 + /* + * Construct name[addr] or name[addr]:port as appropriate + */ +#define SMTPD_BUILD_NAMADDRPORT(name, addr, port) \ + concatenate((name), "[", (addr), "]", \ + var_smtpd_client_port_log ? ":" : (char *) 0, \ + (port), (char *) 0) + /* * Choose between normal or forwarded attributes. * diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index d4fadde95..c88e5df96 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -1813,7 +1813,6 @@ static int reject_unverified_address(SMTPD_STATE *state, const char *addr, SND_DSN : "4.1.1", "<%s>: %s rejected: address verification problem", reply_name, reply_class); - rqst_status = SMTPD_CHECK_DUNNO; } else { switch (rcpt_status) { default: diff --git a/postfix/src/tls/tls_verify.c b/postfix/src/tls/tls_verify.c index 0c9075061..5a5e07668 100644 --- a/postfix/src/tls/tls_verify.c +++ b/postfix/src/tls/tls_verify.c @@ -30,12 +30,12 @@ /* tls_peer_CN() returns the text CommonName for the peer /* certificate subject, or an empty string if no CommonName was /* found. The result is allocated with mymalloc() and must be -/* freed by the caller. +/* freed by the caller; it is arbitrary UTF-8 content. /* /* tls_issuer_CN() returns the text CommonName for the peer /* certificate issuer, or an empty string if no CommonName was /* found. The result is allocated with mymalloc() and must be -/* freed by the caller. +/* freed by the caller; it is arbitrary UTF-8 content. /* /* tls_dns_name() returns the string value of a GENERAL_NAME /* from a DNS subjectAltName extension. If non-printable characters @@ -278,11 +278,9 @@ static char *tls_text_name(X509_NAME *name, int nid, const char *label, int pos; X509_NAME_ENTRY *entry; ASN1_STRING *entry_str; - int typ; - int len; - unsigned char *val; - unsigned char *utf; - char *cp; + int asn1_type; + int utf8_length; + unsigned char *utf8_value; if (name == 0 || (pos = X509_NAME_get_index_by_NID(name, nid, -1)) < 0) { if (gripe != DONT_GRIPE) { @@ -321,96 +319,72 @@ static char *tls_text_name(X509_NAME *name, int nid, const char *label, } /* - * Peername checks are security sensitive, carefully scrutinize the - * input! + * XXX Convert everything into UTF-8. This is a super-set of ASCII, so we + * don't have to bother with separate code paths for ASCII-like content. + * If the payload is ASCII then we won't waste lots of CPU cycles + * converting it into UTF-8. It's up to OpenSSL to do something + * reasonable when converting ASCII formats that contain non-ASCII + * content. + * + * XXX Don't bother optimizing the string length error check. It is not + * worth the complexity. */ - typ = ASN1_STRING_type(entry_str); - len = ASN1_STRING_length(entry_str); - val = ASN1_STRING_data(entry_str); + asn1_type = ASN1_STRING_type(entry_str); + if ((utf8_length = ASN1_STRING_to_UTF8(&utf8_value, entry_str)) < 0) { + msg_warn("%s: %s: error decoding peer %s of ASN.1 type=%d", + myname, TLScontext->namaddr, label, asn1_type); + tls_print_errors(); + return (0); + } /* - * http://www.apps.ietf.org/rfc/rfc3280.html#sec-4.1.2.4 Quick Summary: - * - * The DirectoryString type is defined as a choice of PrintableString, - * TeletexString, BMPString, UTF8String, and UniversalString. The - * UTF8String encoding is the preferred encoding, and all certificates - * issued after December 31, 2003 MUST use the UTF8String encoding of - * DirectoryString (except as noted below). - * - * XXX: 2007, the above has not happened yet (of course), and we continue to - * see new certificates with T61STRING (Teletex) attribute values. - * - * XXX: 2007, at this time there are only two ASN.1 fixed width multi-byte - * string encodings, BMPSTRING (16 bit Unicode) and UniversalString - * (32-bit Unicode). The only variable width ASN.1 string encoding is - * UTF8 with all the other encodings being 1 byte wide subsets or subsets - * of ASCII. - * - * Relying on this could simplify the code, because we would never convert - * unexpected single-byte encodings, but is involves too many cases to be - * sure that we have a complete set and the assumptions may become false. - * So, we pessimistically convert encodings not blessed by RFC 2459, and - * filter out all types that are not string types as a side-effect of - * UTF8 conversion (the ASN.1 library knows which types are string types - * and how wide they are...). - * - * XXX: Two possible states after switch, either "utf == val" and it MUST - * NOT be freed with OPENSSL_free(), or "utf != val" and it MUST be freed - * with OPENSSL_free(). + * No returns without cleaning up. A good optimizer will replace multiple + * blocks of identical code by jumps to just one such block. */ - switch (typ) { - case V_ASN1_PRINTABLESTRING: /* X.500 portable ASCII - * printables */ - case V_ASN1_IA5STRING: /* ISO 646 ~ ASCII */ - case V_ASN1_T61STRING: /* Essentially ISO-Latin */ - case V_ASN1_UTF8STRING: /* UTF8 */ - utf = val; - break; +#define TLS_TEXT_NAME_RETURN(x) do { \ + char *__tls_text_name_temp = (x); \ + OPENSSL_free(utf8_value); \ + return (__tls_text_name_temp); \ + } while (0) - default: - - /* - * May shrink in wash, but BMPSTRING only shrinks by 50%. Others may - * shrink by up to 75%. We Sanity check the length before bothering - * to copy any large strings to convert to UTF8, only to find out - * they don't fit. So long as no new MB types are introduced, and - * weird string encodings unsanctioned by RFC 3280, are used in the - * issuer or subject DN, this "conservative" estimate will be exact. - */ - len >>= (typ == V_ASN1_BMPSTRING) ? 1 : 2; - if (len >= CCERT_BUFSIZ) { - msg_warn("%s: %s: peer %s too long: %d", - myname, TLScontext->namaddr, label, len); - return (0); - } - if ((len = ASN1_STRING_to_UTF8(&utf, entry_str)) < 0) { - msg_warn("%s: %s: error decoding peer %s of ASN.1 type=%d", - myname, TLScontext->namaddr, label, typ); - tls_print_errors(); - return (0); - } - } -#define RETURN(x) do { if (utf!=val) OPENSSL_free(utf); return (x); } while (0) - - if (len >= CCERT_BUFSIZ) { - msg_warn("%s: %s: peer %s too long: %d", - myname, TLScontext->namaddr, label, len); - RETURN(0); - } - if (len != strlen((char *) utf)) { - msg_warn("%s: %s: internal NUL in peer %s", - myname, TLScontext->namaddr, label); - RETURN(0); - } - for (cp = (char *) utf; *cp; cp++) { - if (!ISASCII(*cp) || !ISPRINT(*cp)) { - msg_warn("%s: %s: non-printable characters in peer %s", +#if 0 + for (cp = utf8_value; (ch = *cp) != 0; cp++) { + if (ISASCII(ch) && !ISPRINT(ch)) { + msg_warn("%s: %s: non-printable content in peer %s", myname, TLScontext->namaddr, label); - RETURN(0); + TLS_TEXT_NAME_RETURN(0); } } - cp = mystrdup((char *) utf); - RETURN(cp); +#endif + + /* + * Remove trailing null characters. They would give false alarms with the + * length check and with the embedded null check. + */ +#define TRIM0(s, l) do { while ((l) > 0 && (s)[(l)-1] == 0) --(l); } while (0) + + TRIM0(utf8_value, utf8_length); + + /* + * Enforce the length limit, because the caller will copy the result into + * a fixed-length buffer. + */ + if (utf8_length >= CCERT_BUFSIZ) { + msg_warn("%s: %s: peer %s too long: %d", + myname, TLScontext->namaddr, label, utf8_length); + TLS_TEXT_NAME_RETURN(0); + } + + /* + * Don't allow embedded nulls in ASCII or UTF-8 names. OpenSSL is + * responsible for producing properly-formatted UTF-8. + */ + if (utf8_length != strlen((char *) utf8_value)) { + msg_warn("%s: %s: NULL character in peer %s", + myname, TLScontext->namaddr, label); + TLS_TEXT_NAME_RETURN(0); + } + TLS_TEXT_NAME_RETURN(mystrdup((char *) utf8_value)); } /* tls_dns_name - Extract valid DNS name from subjectAltName value */ @@ -421,6 +395,7 @@ const char *tls_dns_name(const GENERAL_NAME * gn, const char *myname = "tls_dns_name"; char *cp; const char *dnsname; + int len; /* * Peername checks are security sensitive, carefully scrutinize the @@ -443,6 +418,8 @@ const char *tls_dns_name(const GENERAL_NAME * gn, * Safe to treat as an ASCII string possibly holding a DNS name */ dnsname = (char *) ASN1_STRING_data(gn->d.ia5); + len = ASN1_STRING_length(gn->d.ia5); + TRIM0(dnsname, len); /* * Per Dr. Steven Henson of the OpenSSL development team, ASN1_IA5STRING @@ -451,7 +428,7 @@ const char *tls_dns_name(const GENERAL_NAME * gn, * always appended to make sure that the string is terminated, but the * ASN.1 length may differ from strlen(). */ - if (ASN1_STRING_length(gn->d.ia5) != strlen(dnsname)) { + if (len != strlen(dnsname)) { msg_warn("%s: %s: internal NUL in subjectAltName", myname, TLScontext->namaddr); return 0; @@ -463,14 +440,13 @@ const char *tls_dns_name(const GENERAL_NAME * gn, * compare equal to the expected peername, so being more strict than * "printable" is likely excessive... */ - for (cp = (char *) dnsname; cp && *cp; cp++) - if (!ISASCII(*cp) || !ISPRINT(*cp)) { - cp = mystrdup(dnsname); - msg_warn("%s: %s: non-printable characters in subjectAltName: %s", - myname, TLScontext->namaddr, printable(cp, '?')); - myfree(cp); - return 0; - } + if (*dnsname && !allprint(dnsname)) { + cp = mystrdup(dnsname); + msg_warn("%s: %s: non-printable characters in subjectAltName: %.100s", + myname, TLScontext->namaddr, printable(cp, '?')); + myfree(cp); + return 0; + } return (dnsname); }