From: Wietse Venema Date: Thu, 25 Apr 2013 23:28:31 +0000 (-0400) Subject: postfix-2.11-20130425-nonprod X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a5ce16d806c16ab081bf1ee65cf43d34a4f52ba9;p=thirdparty%2Fpostfix.git postfix-2.11-20130425-nonprod --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 270abd967..a9ff8cc5c 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -18514,3 +18514,22 @@ Apologies for any names omitted. posttls-finger/Makefile.in, posttls-finger/posttls-finger.c, posttls-finger/tlsmgrmem.c, posttls-finger/tlsmgrmem.h, tls/tls.h, tls/tls_misc.c. + +20130426 + + Non-production fixes: revert to using proxies (sender, + nexthop, hostname) to distinguish between different SASL + credentials for connections to the same IP address and port. + Files: smtp/smtp.h smtp/smtp_connect.c, smtp/smtp_key.c. + + Non-production cleanup: documentation, identifiers. Viktor + Dukhovni. Files: proto/postconf.proto, src/dns/dns.h, + src/dns/dns_lookup.c, src/dns/dns_rr.c, src/dns/test_dns_lookup.c, + src/global/mail_proto.h, src/posttls-finger/posttls-finger.c, + src/smtp/smtp.h, src/smtp/smtp_addr.c, src/smtp/smtp_connect.c, + src/smtp/smtp_session.c, src/smtp/smtp_tls_policy.c, + src/smtpd/smtpd_check.c, src/tls/tls.h, src/tls/tls_client.c, + src/tls/tls_dane.c, src/tls/tls_fprint.c, src/tls/tls_misc.c, + src/tls/tls_proxy_clnt.c, src/tls/tls_proxy_print.c, + src/tls/tls_proxy_scan.c, src/tls/tls_server.c, + src/tls/tls_verify.c. diff --git a/postfix/WISHLIST b/postfix/WISHLIST index be937b5c5..a870849aa 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -54,8 +54,6 @@ Wish list: some_bound". Instead of bare numbers use named constants in function argument lists. - Code clarity: replace "valid" with or "dnssec_valid". - Code clarity: replace obscure macro/function names: for example SMTP_X(XXX) -> VAR_SMTP(XXX), as the purpose is to choose between VAR_SMTP_XXX or VAR_LMTP_XXX; replace @@ -64,18 +62,6 @@ Wish list: contents of a buffer with the specified length). Replace r with res_opt, ditto for other 1-letter names. - Code consistency: replace the VSTRING-based digest output - loop with a tls_digest_encode() call. - - Code clarity: rename tls_fingerprint() to tls_cert_fprint() - (compute certifate fingerprint). Keep tls_pkey_fprint() - (compute public-key fingerprint). Rename tls_fprint() to - tls_data_fprint() (compute fingerprint for arbitrary data). - - Collect SMTP client connection-management state in one - iterator object, that provides the same information for - SMTP reuse policy, TLS policy, and SASL password lookups. - Unnecessary complexity: the SMTP_SESSION "tls" field is mandatory (always allocated) therefore the content can be a permanent part of the SMTP_SESSION structure, just like @@ -83,10 +69,6 @@ Wish list: all over the code, as well as awkward smtp_tls_sess_alloc() error semantics. - Provide an iterator object API that provides consistent - search key generation for SMTP reuse policy, TLS policy, - and SASL password lookups. - We have smtp_host_lookup, smtp_dns_resolver_options, and now smtp_dns_support_level. Of these, smtp_dns_resolver_options is orthogonal but the rest has overlap. diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index f311d75b5..cfed7f3d7 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -12076,19 +12076,20 @@ the remote SMTP server, and any untrusted issuing parent certificates will be ignored. Specify a list of pathnames separated by comma or whitespace.

-

This feature is implemented for completeness, to allow installations -with a small set of SMTP peers to set global policy in main.cf, -that at most sites would be set via smtp_tls_policy_maps. In almost -all cases it is better to use it on a per-destination basis via the -"tafile" policy attribute of the "verify" and "secure" levels leaving -the global main.cf setting empty.

- -

When used on a per-destination basis, each "tafile" PEM file -must be accessible to the Postfix SMTP client in the chroot jail -if applicable. The files should not contain any sensitive data, -and must be readable by the non-privileged $mail_owner user. This -allows destinations to be bound to a set of specific CAs or public -keys without trusting the same CAs for all destinations.

+

Whether specified in main.cf, or on a per-destination basis, +the trust-anchor PEM file must be accessible to the Postfix SMTP +client in the chroot jail if applicable. The trust-anchor file +should contain only certificates and public keys, no private key +material, and must be readable by the non-privileged $mail_owner +user. This allows destinations to be bound to a set of specific +CAs or public keys without trusting the same CAs for all destinations. +

+ +

The main.cf parameter supports single-purpose Postfix installations +that send mail to a fixed set of SMTP peers. At most sites, if +trust-anchor files are used at all, they will be specified on a +per-destination basis via the "tafile" attribute of the "verify" +and "secure" levels in smtp_tls_policy_maps.

The underlying mechanism is in support of RFC 6698 (DANE TLSA), which defines mechanisms for a client to securely determine server diff --git a/postfix/html/posttls-finger.1.html b/postfix/html/posttls-finger.1.html index 45553369c..f07aacc8f 100644 --- a/postfix/html/posttls-finger.1.html +++ b/postfix/html/posttls-finger.1.html @@ -92,208 +92,211 @@ POSTTLS-FINGER(1) POSTTLS-FINGER(1) Arguments: - -a Address family preference: ipv4, ipv6 or any. When + -a family (default: any) + Address family preference: ipv4, ipv6 or any. When using any, posttls-finger will randomly select one of the two as the more preferred, and exhaust all MX preferences for the first address family before - trying any addresses for the other. The default - value is any. + trying any addresses for the other. - -A A list of PEM trust-anchor files that overrides - CAfile and CApath trust chain verification. Spec- - ify the option multiple times to specify multiple + -A trust-anchor.pem (default: none) + A list of PEM trust-anchor files that overrides + CAfile and CApath trust chain verification. Spec- + ify the option multiple times to specify multiple files. See the main.cf documentation for smtp_tls_trust_anchor_file for details. - -c Disable SMTP chat logging; only TLS-related infor- + -c Disable SMTP chat logging; only TLS-related infor- mation is logged. - -C Print the remote SMTP server certificate trust - chain in PEM format. The issuer DN, subject DN, - certificate and public key fingerprints (see -d + -C Print the remote SMTP server certificate trust + chain in PEM format. The issuer DN, subject DN, + certificate and public key fingerprints (see -d mdalg option below) are printed above each PEM cer- - tificate block. If you specify -F CAfile or -P - CApath, the OpenSSL library may augment the chain + tificate block. If you specify -F CAfile or -P + CApath, the OpenSSL library may augment the chain with missing issuer certificates. To see the - actual chain sent by the remote SMTP server leave + actual chain sent by the remote SMTP server leave CAfile and CApath unset. - -d mdalg - The message digest algorithm to use for reporting - remote SMTP server fingerprints and matching - against user provided certificate fingerprints - (with DANE TLSA records the algorithm is specified - in the DNS). The default algorithm is sha1. + -d mdalg (default: sha1) + The message digest algorithm to use for reporting + remote SMTP server fingerprints and matching + against user provided certificate fingerprints + (with DANE TLSA records the algorithm is specified + in the DNS). - -F CAfile.pem - The PEM formatted CAfile for remote SMTP server - certificate verification. By default no CAfile is + -F CAfile.pem (default: none) + The PEM formatted CAfile for remote SMTP server + certificate verification. By default no CAfile is used and no public CAs are trusted. - -h host_lookup - The hostname lookup methods used for the connec- - tion. See the documentation of smtp_host_lookup + -h host_lookup (default: dns) + The hostname lookup methods used for the connec- + tion. See the documentation of smtp_host_lookup for syntax and semantics. - -l level + -l level (default: dane or secure) The security level for the connection, default dane or secure depending on whether DNSSEC is available. - For syntax and semantics, see the documentation of - smtp_tls_security_level. When dane is supported - and selected, if no TLSA records are found, or all - the records found are unusable, the degraded level - will be secure. The main additional level to con- - sider is fingerprint, which allows you test cer- - tificate or public-key fingerprint matches before + For syntax and semantics, see the documentation of + smtp_tls_security_level. When dane is supported + and selected, if no TLSA records are found, or all + the records found are unusable, the degraded level + will be secure. The main additional level to con- + sider is fingerprint, which allows you test cer- + tificate or public-key fingerprint matches before you deploy them in the policy table. - Note, since posttls-finger does not actually - deliver any email, the none, may and encrypt secu- - rity levels are not very useful. Since may and - encrypt don't require peer certificates, they will - often negotiate anonymous TLS ciphersuites, so you - won't learn much about the remote SMTP server's - certificates at these levels if it also supports + Note, since posttls-finger does not actually + deliver any email, the none, may and encrypt secu- + rity levels are not very useful. Since may and + encrypt don't require peer certificates, they will + often negotiate anonymous TLS ciphersuites, so you + won't learn much about the remote SMTP server's + certificates at these levels if it also supports anonymous TLS (though you may learn that the server supports anonymous TLS). - -L logopts - Fine-grained TLS logging options. To tune the TLS - features logged during the TLS handshake, specify + -L logopts (default: routine,certmatch) + Fine-grained TLS logging options. To tune the TLS + features logged during the TLS handshake, specify one or more of: - 0, none + 0, none These yield no TLS logging; you'll generally - want more, but this is handy if you just + want more, but this is handy if you just want the trust chain: $ posttls-finger -cC -L none destination - 1, routine, summary - These synonymous values yield a normal one- + 1, routine, summary + These synonymous values yield a normal one- line summary of the TLS connection. - 2, debug + 2, debug These synonymous values combine routine, ssl-debug, cache and verbose. - 3, ssl-expert - These synonymous values combine debug with - ssl-handshake-packet-dump. For experts + 3, ssl-expert + These synonymous values combine debug with + ssl-handshake-packet-dump. For experts only. - 4, ssl-developer - These synonymous values combine ssl-expert - with ssl-session-packet-dump. For experts + 4, ssl-developer + These synonymous values combine ssl-expert + with ssl-session-packet-dump. For experts only, and in most cases, use wireshark instead. - ssl-debug - Turn on OpenSSL logging of the progress of + ssl-debug + Turn on OpenSSL logging of the progress of the SSL handshake. - ssl-handshake-packet-dump - Log hexadecimal packet dumps of the SSL + ssl-handshake-packet-dump + Log hexadecimal packet dumps of the SSL handshake; for experts only. - ssl-session-packet-dump - Log hexadecimal packet dumps of the entire - SSL session; only useful to those who can - debug SSL protocol problems from hex dumps. + ssl-session-packet-dump + Log hexadecimal packet dumps of the entire + SSL session; only useful to those who can + debug SSL protocol problems from hex dumps. - untrusted - Logs trust chain verification problems. - This is turned on automatically at security - levels that use peer names signed by cer- - tificate authorities to validate certifi- + untrusted + Logs trust chain verification problems. + This is turned on automatically at security + levels that use peer names signed by cer- + tificate authorities to validate certifi- cates. So while this setting is recognized, - you should never need to set it explicitly. + you should never need to set it explicitly. - peercert - This logs a one line summary of the remote + peercert + This logs a one line summary of the remote SMTP server certificate subject, issuer, and fingerprints. - certmatch - This logs remote SMTP server certificate - matching, showing the CN and each subjec- + certmatch + This logs remote SMTP server certificate + matching, showing the CN and each subjec- tAltName and which name matched. With DANE, - logs matching of TLSA record trust-anchor + logs matching of TLSA record trust-anchor and end-entity certificates. - cache This logs session cache operations, showing - whether session caching is effective with - the remote SMTP server. Automatically used + cache This logs session cache operations, showing + whether session caching is effective with + the remote SMTP server. Automatically used when reconnecting with the -r option; rarely needs to be set explicitly. - verbose - Enables verbose logging in the Postfix TLS - driver; includes all of peercert..cache and + verbose + Enables verbose logging in the Postfix TLS + driver; includes all of peercert..cache and more. - The default is routine,certmatch. After a recon- - nect, the log level is unconditionally rou- + The default is routine,certmatch. After a recon- + nect, the log level is unconditionally rou- tine,cache. - -m count - When the -r delay option is specified, the -m - option determines the maximum number of reconnect - attempts to use with a server behind a load-bal- - acer, to see whether connection caching is likely - to be effective for this destination. Some MTAs - don't expose the underlying server identity in - their EHLO response; with these servers there will + -m count (default: 5) + When the -r delay option is specified, the -m + option determines the maximum number of reconnect + attempts to use with a server behind a load-bal- + acer, to see whether connection caching is likely + to be effective for this destination. Some MTAs + don't expose the underlying server identity in + their EHLO response; with these servers there will never be more than 1 reconnection attempt. -o name=value Specify zero or more times to override the value of - the main.cf parameter name with value. Possible - use-cases include overriding the values of TLS - library parameters or "myhostname" to configure the - SMTP EHLO name sent to the remote server. - - -P CApath/ - The OpenSSL CApath/ directory (indexed via - c_rehash(1)) for remote SMTP server certificate - verification. By default no CApath is used and no + the main.cf parameter name with value. Possible + use-cases include overriding the values of TLS + library parameters, or "myhostname" to configure + the SMTP EHLO name sent to the remote server. + + -P CApath/ (default: none) + The OpenSSL CApath/ directory (indexed via + c_rehash(1)) for remote SMTP server certificate + verification. By default no CApath is used and no public CAs are trusted. -r delay - With a cachable TLS session, disconnect and recon- - nect after delay seconds. Report whether the ses- - sion is re-used. Retry if a new server is encoun- - tered, up to 5 times or as specified with the -m - option. + With a cachable TLS session, disconnect and recon- + nect after delay seconds. Report whether the ses- + sion is re-used. Retry if a new server is encoun- + tered, up to 5 times or as specified with the -m + option. By default reconnection is disabled, spec- + ify a positive delay to enable this behavior. -S Disable SMTP; that is, connect to an LMTP server. The default port for LMTP over TCP is 24. Alterna- tive ports can specified by appending ":service- name" or ":portnumber" to the destination argument. - -t timeout + -t timeout (default: 5) The TCP connection timeout to use. This is also the timeout for reading the remote server's 220 banner. - -T timeout + -T timeout (default: 30) The SMTP/LMTP command timeout for EHLO/LHLO, START- TLS and QUIT. - -v Enable more verbose logging. + -v Enable verose Postfix logging. Specify more than + once to increase the level of verbose logging. [inet:]domain[:port] - Connect via TCP to domain domain, port port. The - default port is smtp (or 24 with LMTP). With SMTP - an MX lookup is performed to resolve the domain to - a host, unless the domain is enclosed in []. If - you want to connect to a specific MX host, for + Connect via TCP to domain domain, port port. The + default port is smtp (or 24 with LMTP). With SMTP + an MX lookup is performed to resolve the domain to + a host, unless the domain is enclosed in []. If + you want to connect to a specific MX host, for instance mx1.example.com, specify [mx1.example.com] as the destination and example.com as a match argu- - ment. When using DNS, the destination domain is - assumed fully qualified and no default domain or - search suffixes are applied; you must use fully- - qualified names or also enable native host lookups - (these don't support dane as no DNSSEC validation + ment. When using DNS, the destination domain is + assumed fully qualified and no default domain or + search suffixes are applied; you must use fully- + qualified names or also enable native host lookups + (these don't support dane as no DNSSEC validation information is available via native lookups). unix:pathname @@ -304,20 +307,20 @@ POSTTLS-FINGER(1) POSTTLS-FINGER(1) With no match arguments specified, certificate peername matching uses the compiled-in default strategies for each security level. If you specify - one or more arguments, these will be used as the - list of certificate or public-key digests to match - for the fingerprint level, or as the list of DNS + one or more arguments, these will be used as the + list of certificate or public-key digests to match + for the fingerprint level, or as the list of DNS names to match in the certificate at the verify and - secure levels. If the security level is dane, and - usable TLSA records are found, the match names are + secure levels. If the security level is dane, and + usable TLSA records are found, the match names are ignored, and hostname, nexthop strategies are used. - If no TLSA records are found or none are usable, - the level degrades to secure and the provided list + If no TLSA records are found or none are usable, + the level degrades to secure and the provided list is used to match names in the certificate. ENVIRONMENT MAIL_CONFIG - Read configuration parameters from a non-default + Read configuration parameters from a non-default location. MAIL_VERBOSE @@ -331,7 +334,7 @@ POSTTLS-FINGER(1) POSTTLS-FINGER(1) TLS_README, Postfix STARTTLS howto 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/man/man1/posttls-finger.1 b/postfix/man/man1/posttls-finger.1 index b9855a7e1..f76cf22d0 100644 --- a/postfix/man/man1/posttls-finger.1 +++ b/postfix/man/man1/posttls-finger.1 @@ -82,13 +82,12 @@ otherwise, specify an optional \fBinet:\fR prefix followed by a SMTP. The default TCP port for LMTP is 24. Arguments: -.IP "\fB-a\fR" +.IP "\fB-a\fR \fIfamily\fR (default: \fBany\fR)" Address family preference: \fBipv4\fR, \fBipv6\fR or \fBany\fR. When using \fBany\fR, posttls-finger will randomly select one of the two as the more preferred, and exhaust all MX preferences for the first -address family before trying any addresses for the other. The -default value is \fBany\fR. -.IP "\fB-A\fR" +address family before trying any addresses for the other. +.IP "\fB-A\fR \fItrust-anchor.pem\fR (default: none)" A list of PEM trust-anchor files that overrides CAfile and CApath trust chain verification. Specify the option multiple times to specify multiple files. See the main.cf documentation for @@ -103,19 +102,19 @@ certificate block. If you specify \fB-F \fICAfile\fR or \fB-P \fICApath\fR, the OpenSSL library may augment the chain with missing issuer certificates. To see the actual chain sent by the remote SMTP server leave \fICAfile\fR and \fICApath\fR unset. -.IP "\fB-d \fImdalg\fR" +.IP "\fB-d \fImdalg\fR (default: \fBsha1\fR)" The message digest algorithm to use for reporting remote SMTP server fingerprints and matching against user provided certificate fingerprints (with DANE TLSA records the algorithm is specified -in the DNS). The default algorithm is sha1. -.IP "\fB-F \fICAfile.pem\fR" +in the DNS). +.IP "\fB-F \fICAfile.pem\fR (default: none)" The PEM formatted CAfile for remote SMTP server certificate verification. By default no CAfile is used and no public CAs are trusted. -.IP "\fB-h \fIhost_lookup\fR" +.IP "\fB-h \fIhost_lookup\fR (default: \fBdns\fR)" The hostname lookup methods used for the connection. See the documentation of smtp_host_lookup for syntax and semantics. -.IP "\fB-l \fIlevel\fR" +.IP "\fB-l \fIlevel\fR (default: \fBdane\fR or \fBsecure\fR)" The security level for the connection, default \fBdane\fR or \fBsecure\fR depending on whether DNSSEC is available. For syntax and semantics, see the documentation of smtp_tls_security_level. @@ -132,11 +131,11 @@ certificates, they will often negotiate anonymous TLS ciphersuites, so you won't learn much about the remote SMTP server's certificates at these levels if it also supports anonymous TLS (though you may learn that the server supports anonymous TLS). -.IP "\fB-L \fIlogopts\fR" +.IP "\fB-L \fIlogopts\fR (default: \fBroutine,certmatch\fR)" Fine-grained TLS logging options. To tune the TLS features logged during the TLS handshake, specify one or more of: .RS -.IP "0, none" +.IP "\fB0, none\fR" These yield no TLS logging; you'll generally want more, but this is handy if you just want the trust chain: .RS @@ -145,62 +144,63 @@ is handy if you just want the trust chain: $ posttls-finger -cC -L none destination .fi .RE -.IP "1, routine, summary" +.IP "\fB1, routine, summary\fR" These synonymous values yield a normal one-line summary of the TLS connection. -.IP "2, debug" +.IP "\fB2, debug\fR" These synonymous values combine routine, ssl-debug, cache and verbose. -.IP "3, ssl-expert" +.IP "\fB3, ssl-expert\fR" These synonymous values combine debug with ssl-handshake-packet-dump. For experts only. -.IP "4, ssl-developer" +.IP "\fB4, ssl-developer\fR" These synonymous values combine ssl-expert with ssl-session-packet-dump. For experts only, and in most cases, use wireshark instead. -.IP ssl-debug +.IP "\fBssl-debug\fR" Turn on OpenSSL logging of the progress of the SSL handshake. -.IP ssl-handshake-packet-dump +.IP "\fBssl-handshake-packet-dump\fR" Log hexadecimal packet dumps of the SSL handshake; for experts only. -.IP ssl-session-packet-dump +.IP "\fBssl-session-packet-dump\fR" Log hexadecimal packet dumps of the entire SSL session; only useful to those who can debug SSL protocol problems from hex dumps. -.IP untrusted +.IP "\fBuntrusted\fR" Logs trust chain verification problems. This is turned on automatically at security levels that use peer names signed by certificate authorities to validate certificates. So while this setting is recognized, you should never need to set it explicitly. -.IP peercert +.IP "\fBpeercert\fR" This logs a one line summary of the remote SMTP server certificate subject, issuer, and fingerprints. -.IP certmatch +.IP "\fBcertmatch\fR" This logs remote SMTP server certificate matching, showing the CN and each subjectAltName and which name matched. With DANE, logs matching of TLSA record trust-anchor and end-entity certificates. -.IP cache +.IP "\fBcache\fR" This logs session cache operations, showing whether session caching is effective with the remote SMTP server. Automatically used when reconnecting with the \fB-r\fR option; rarely needs to be set explicitly. -.IP verbose +.IP "\fBverbose\fR" Enables verbose logging in the Postfix TLS driver; includes all of peercert..cache and more. .RE .IP The default is \fBroutine,certmatch\fR. After a reconnect, the log level is unconditionally \fBroutine,cache\fR. -.IP "\fB-m \fIcount\fR" +.IP "\fB-m \fIcount\fR (default: \fB5\fR)" When the \fB-r \fIdelay\fR option is specified, the \fB-m\fR option determines the maximum number of reconnect attempts to use with a server behind a load-balacer, to see whether connection caching -is likely to be effective for this destination. Some MTAs don't -expose the underlying server identity in their EHLO response; with -these servers there will never be more than 1 reconnection attempt. +is likely to be effective for this destination. Some MTAs +don't expose the underlying server identity in their EHLO +response; with these servers there will never be more than +1 reconnection attempt. .IP "\fB-o \fIname=value\fR" Specify zero or more times to override the value of the main.cf parameter \fIname\fR with \fIvalue\fR. Possible use-cases include -overriding the values of TLS library parameters or "myhostname" to +overriding the values of TLS library parameters, or "myhostname" to configure the SMTP EHLO name sent to the remote server. -.IP "\fB-P \fICApath/\fR" +.IP "\fB-P \fICApath/\fR (default: none)" The OpenSSL CApath/ directory (indexed via c_rehash(1)) for remote SMTP server certificate verification. By default no CApath is used and no public CAs are trusted. @@ -208,18 +208,21 @@ and no public CAs are trusted. With a cachable TLS session, disconnect and reconnect after \fIdelay\fR seconds. Report whether the session is re-used. Retry if a new server is encountered, up to 5 times or as specified with the \fB-m\fR option. +By default reconnection is disabled, specify a positive delay to +enable this behavior. .IP "\fB-S\fR" Disable SMTP; that is, connect to an LMTP server. The default port for LMTP over TCP is 24. Alternative ports can specified by appending "\fI:servicename\fR" or ":\fIportnumber\fR" to the destination argument. -.IP "\fB-t \fItimeout\fR" +.IP "\fB-t \fItimeout\fR (default: \fB5\fR)" The TCP connection timeout to use. This is also the timeout for reading the remote server's 220 banner. -.IP "\fB-T \fItimeout\fR" +.IP "\fB-T \fItimeout\fR (default: \fB30\fR)" The SMTP/LMTP command timeout for EHLO/LHLO, STARTTLS and QUIT. .IP "\fB-v\fR" -Enable more verbose logging. +Enable verose Postfix logging. Specify more than once to increase +the level of verbose logging. .IP "[\fBinet:\fR]\fIdomain\fR[:\fIport\fR]" Connect via TCP to domain \fIdomain\fR, port \fIport\fR. The default port is \fBsmtp\fR (or 24 with LMTP). With SMTP an MX lookup is diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 4f007bab4..dc87ce2ef 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -7785,19 +7785,19 @@ the remote SMTP server, and any untrusted issuing parent certificates will be ignored. Specify a list of pathnames separated by comma or whitespace. .PP -This feature is implemented for completeness, to allow installations -with a small set of SMTP peers to set global policy in main.cf, -that at most sites would be set via smtp_tls_policy_maps. In almost -all cases it is better to use it on a per-destination basis via the -"tafile" policy attribute of the "verify" and "secure" levels leaving -the global main.cf setting empty. -.PP -When used on a per-destination basis, each "tafile" PEM file -must be accessible to the Postfix SMTP client in the chroot jail -if applicable. The files should not contain any sensitive data, -and must be readable by the non-privileged $mail_owner user. This -allows destinations to be bound to a set of specific CAs or public -keys without trusting the same CAs for all destinations. +Whether specified in main.cf, or on a per-destination basis, +the trust-anchor PEM file must be accessible to the Postfix SMTP +client in the chroot jail if applicable. The trust-anchor file +should contain only certificates and public keys, no private key +material, and must be readable by the non-privileged $mail_owner +user. This allows destinations to be bound to a set of specific +CAs or public keys without trusting the same CAs for all destinations. +.PP +The main.cf parameter supports single-purpose Postfix installations +that send mail to a fixed set of SMTP peers. At most sites, if +trust-anchor files are used at all, they will be specified on a +per-destination basis via the "tafile" attribute of the "verify" +and "secure" levels in smtp_tls_policy_maps. .PP The underlying mechanism is in support of RFC 6698 (DANE TLSA), which defines mechanisms for a client to securely determine server diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index 588d020a0..03a3dc4de 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -15129,19 +15129,20 @@ the remote SMTP server, and any untrusted issuing parent certificates will be ignored. Specify a list of pathnames separated by comma or whitespace.

-

This feature is implemented for completeness, to allow installations -with a small set of SMTP peers to set global policy in main.cf, -that at most sites would be set via smtp_tls_policy_maps. In almost -all cases it is better to use it on a per-destination basis via the -"tafile" policy attribute of the "verify" and "secure" levels leaving -the global main.cf setting empty.

- -

When used on a per-destination basis, each "tafile" PEM file -must be accessible to the Postfix SMTP client in the chroot jail -if applicable. The files should not contain any sensitive data, -and must be readable by the non-privileged $mail_owner user. This -allows destinations to be bound to a set of specific CAs or public -keys without trusting the same CAs for all destinations.

+

Whether specified in main.cf, or on a per-destination basis, +the trust-anchor PEM file must be accessible to the Postfix SMTP +client in the chroot jail if applicable. The trust-anchor file +should contain only certificates and public keys, no private key +material, and must be readable by the non-privileged $mail_owner +user. This allows destinations to be bound to a set of specific +CAs or public keys without trusting the same CAs for all destinations. +

+ +

The main.cf parameter supports single-purpose Postfix installations +that send mail to a fixed set of SMTP peers. At most sites, if +trust-anchor files are used at all, they will be specified on a +per-destination basis via the "tafile" attribute of the "verify" +and "secure" levels in smtp_tls_policy_maps.

The underlying mechanism is in support of RFC 6698 (DANE TLSA), which defines mechanisms for a client to securely determine server diff --git a/postfix/src/dns/dns.h b/postfix/src/dns/dns.h index bedbbdddc..345495a9b 100644 --- a/postfix/src/dns/dns.h +++ b/postfix/src/dns/dns.h @@ -132,7 +132,7 @@ typedef struct DNS_RR { unsigned short type; /* T_A, T_CNAME, etc. */ unsigned short class; /* C_IN, etc. */ unsigned int ttl; /* always */ - unsigned int validated; /* DNSSEC */ + unsigned int dnssec_valid; /* DNSSEC validated */ unsigned short pref; /* T_MX only */ struct DNS_RR *next; /* linkage */ size_t data_len; /* actual data size */ diff --git a/postfix/src/dns/dns_lookup.c b/postfix/src/dns/dns_lookup.c index daaaa9e18..43b50ba16 100644 --- a/postfix/src/dns/dns_lookup.c +++ b/postfix/src/dns/dns_lookup.c @@ -166,7 +166,7 @@ typedef struct DNS_REPLY { unsigned char *buf; /* raw reply data */ size_t buf_len; /* reply buffer length */ - int validated; /* DNSSEC AD bit */ + int dnssec_valid; /* DNSSEC AD bit */ int query_count; /* number of queries */ int answer_count; /* number of answers */ unsigned char *query_start; /* start of query data */ @@ -281,9 +281,9 @@ static int dns_query(const char *name, int type, int flags, * the fly while the reply is being parsed. */ #if RES_USE_DNSSEC != 0 - reply->validated = (flags & RES_USE_DNSSEC) ? reply_header->ad : 0; + reply->dnssec_valid = (flags & RES_USE_DNSSEC) ? reply_header->ad : 0; #else - reply->validated = 0; + reply->dnssec_valid = 0; #endif reply->end = reply->buf + len; reply->query_start = reply->buf + sizeof(HEADER); @@ -573,7 +573,7 @@ static int dns_get_answer(const char *orig_name, DNS_REPLY *reply, int type, if ((status = dns_get_rr(&rr, orig_name, reply, pos, rr_name, &fixed)) == DNS_OK) { resource_found++; - rr->validated = (reply->validated & *validate_mask); + rr->dnssec_valid = (reply->dnssec_valid & *validate_mask); *rrlist = dns_rr_append(*rrlist, rr); } else if (not_found_status != DNS_RETRY) not_found_status = status; @@ -584,7 +584,7 @@ static int dns_get_answer(const char *orig_name, DNS_REPLY *reply, int type, if (cname && c_len > 0) if ((status = dns_get_alias(reply, pos, &fixed, cname, c_len)) != DNS_OK) CORRUPT(status); - *validate_mask &= reply->validated; + *validate_mask &= reply->dnssec_valid; } pos += fixed.length; } diff --git a/postfix/src/dns/dns_rr.c b/postfix/src/dns/dns_rr.c index 1e566949d..870a78f75 100644 --- a/postfix/src/dns/dns_rr.c +++ b/postfix/src/dns/dns_rr.c @@ -123,7 +123,7 @@ DNS_RR *dns_rr_create(const char *qname, const char *rname, rr->type = type; rr->class = class; rr->ttl = ttl; - rr->validated = 0; + rr->dnssec_valid = 0; rr->pref = pref; if (data && data_len > 0) memcpy(rr->data, data, data_len); diff --git a/postfix/src/dns/test_dns_lookup.c b/postfix/src/dns/test_dns_lookup.c index da3b3758c..49ed9025b 100644 --- a/postfix/src/dns/test_dns_lookup.c +++ b/postfix/src/dns/test_dns_lookup.c @@ -46,7 +46,7 @@ static void print_rr(DNS_RR *rr) size_t i; while (rr) { - printf("%s: ad: %d, ttl: %9d ", rr->rname, rr->validated, rr->ttl); + printf("%s: ad: %d, ttl: %9d ", rr->rname, rr->dnssec_valid, rr->ttl); switch (rr->type) { case T_A: #ifdef T_AAAA diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h index a4dd8d4c4..976b12590 100644 --- a/postfix/src/global/mail_proto.h +++ b/postfix/src/global/mail_proto.h @@ -144,7 +144,7 @@ extern char *mail_pathname(const char *, const char *); #define MAIL_ATTR_FUNC "function" #define MAIL_ATTR_CCERT_SUBJECT "ccert_subject" #define MAIL_ATTR_CCERT_ISSUER "ccert_issuer" -#define MAIL_ATTR_CCERT_FINGERPRINT "ccert_fingerprint" +#define MAIL_ATTR_CCERT_CERT_FPRINT "ccert_fingerprint" #define MAIL_ATTR_CCERT_PKEY_FPRINT "ccert_pubkey_fingerprint" #define MAIL_ATTR_CRYPTO_PROTOCOL "encryption_protocol" #define MAIL_ATTR_CRYPTO_CIPHER "encryption_cipher" @@ -255,7 +255,7 @@ extern char *mail_pathname(const char *, const char *); #define MAIL_ATTR_TIMEOUT "timeout" #define MAIL_ATTR_PEER_CN "peer_CN" #define MAIL_ATTR_ISSUER_CN "issuer_CN" -#define MAIL_ATTR_PEER_FPT "peer_fingerprint" +#define MAIL_ATTR_PEER_CERT_FPT "peer_fingerprint" #define MAIL_ATTR_PEER_PKEY_FPT "peer_pubkey_fingerprint" #define MAIL_ATTR_PEER_STATUS "peer_status" #define MAIL_ATTR_CIPHER_PROTOCOL "cipher_protocol" diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index db9bbf94f..20f208bd8 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 "20130422" +#define MAIL_RELEASE_DATE "20130425" #define MAIL_VERSION_NUMBER "2.11" #ifdef SNAPSHOT diff --git a/postfix/src/posttls-finger/posttls-finger.c b/postfix/src/posttls-finger/posttls-finger.c index d5aed3816..42a90ef2f 100644 --- a/postfix/src/posttls-finger/posttls-finger.c +++ b/postfix/src/posttls-finger/posttls-finger.c @@ -76,13 +76,12 @@ /* SMTP. The default TCP port for LMTP is 24. /* /* Arguments: -/* .IP "\fB-a\fR" +/* .IP "\fB-a\fR \fIfamily\fR (default: \fBany\fR)" /* Address family preference: \fBipv4\fR, \fBipv6\fR or \fBany\fR. When /* using \fBany\fR, posttls-finger will randomly select one of the two as /* the more preferred, and exhaust all MX preferences for the first -/* address family before trying any addresses for the other. The -/* default value is \fBany\fR. -/* .IP "\fB-A\fR" +/* address family before trying any addresses for the other. +/* .IP "\fB-A\fR \fItrust-anchor.pem\fR (default: none)" /* A list of PEM trust-anchor files that overrides CAfile and CApath /* trust chain verification. Specify the option multiple times to /* specify multiple files. See the main.cf documentation for @@ -97,19 +96,19 @@ /* \fB-P \fICApath\fR, the OpenSSL library may augment the chain with /* missing issuer certificates. To see the actual chain sent by the /* remote SMTP server leave \fICAfile\fR and \fICApath\fR unset. -/* .IP "\fB-d \fImdalg\fR" +/* .IP "\fB-d \fImdalg\fR (default: \fBsha1\fR)" /* The message digest algorithm to use for reporting remote SMTP server /* fingerprints and matching against user provided certificate /* fingerprints (with DANE TLSA records the algorithm is specified -/* in the DNS). The default algorithm is sha1. -/* .IP "\fB-F \fICAfile.pem\fR" +/* in the DNS). +/* .IP "\fB-F \fICAfile.pem\fR (default: none)" /* The PEM formatted CAfile for remote SMTP server certificate /* verification. By default no CAfile is used and no public CAs /* are trusted. -/* .IP "\fB-h \fIhost_lookup\fR" +/* .IP "\fB-h \fIhost_lookup\fR (default: \fBdns\fR)" /* The hostname lookup methods used for the connection. See the /* documentation of smtp_host_lookup for syntax and semantics. -/* .IP "\fB-l \fIlevel\fR" +/* .IP "\fB-l \fIlevel\fR (default: \fBdane\fR or \fBsecure\fR)" /* The security level for the connection, default \fBdane\fR or /* \fBsecure\fR depending on whether DNSSEC is available. For syntax /* and semantics, see the documentation of smtp_tls_security_level. @@ -126,11 +125,11 @@ /* so you won't learn much about the remote SMTP server's certificates /* at these levels if it also supports anonymous TLS (though you may /* learn that the server supports anonymous TLS). -/* .IP "\fB-L \fIlogopts\fR" +/* .IP "\fB-L \fIlogopts\fR (default: \fBroutine,certmatch\fR)" /* Fine-grained TLS logging options. To tune the TLS features logged /* during the TLS handshake, specify one or more of: /* .RS -/* .IP "0, none" +/* .IP "\fB0, none\fR" /* These yield no TLS logging; you'll generally want more, but this /* is handy if you just want the trust chain: /* .RS @@ -139,62 +138,63 @@ /* $ posttls-finger -cC -L none destination /* .fi /* .RE -/* .IP "1, routine, summary" +/* .IP "\fB1, routine, summary\fR" /* These synonymous values yield a normal one-line summary of the TLS /* connection. -/* .IP "2, debug" +/* .IP "\fB2, debug\fR" /* These synonymous values combine routine, ssl-debug, cache and verbose. -/* .IP "3, ssl-expert" +/* .IP "\fB3, ssl-expert\fR" /* These synonymous values combine debug with ssl-handshake-packet-dump. /* For experts only. -/* .IP "4, ssl-developer" +/* .IP "\fB4, ssl-developer\fR" /* These synonymous values combine ssl-expert with ssl-session-packet-dump. /* For experts only, and in most cases, use wireshark instead. -/* .IP ssl-debug +/* .IP "\fBssl-debug\fR" /* Turn on OpenSSL logging of the progress of the SSL handshake. -/* .IP ssl-handshake-packet-dump +/* .IP "\fBssl-handshake-packet-dump\fR" /* Log hexadecimal packet dumps of the SSL handshake; for experts only. -/* .IP ssl-session-packet-dump +/* .IP "\fBssl-session-packet-dump\fR" /* Log hexadecimal packet dumps of the entire SSL session; only useful /* to those who can debug SSL protocol problems from hex dumps. -/* .IP untrusted +/* .IP "\fBuntrusted\fR" /* Logs trust chain verification problems. This is turned on /* automatically at security levels that use peer names signed /* by certificate authorities to validate certificates. So while /* this setting is recognized, you should never need to set it /* explicitly. -/* .IP peercert +/* .IP "\fBpeercert\fR" /* This logs a one line summary of the remote SMTP server certificate /* subject, issuer, and fingerprints. -/* .IP certmatch +/* .IP "\fBcertmatch\fR" /* This logs remote SMTP server certificate matching, showing the CN /* and each subjectAltName and which name matched. With DANE, logs /* matching of TLSA record trust-anchor and end-entity certificates. -/* .IP cache +/* .IP "\fBcache\fR" /* This logs session cache operations, showing whether session caching /* is effective with the remote SMTP server. Automatically used when /* reconnecting with the \fB-r\fR option; rarely needs to be set /* explicitly. -/* .IP verbose +/* .IP "\fBverbose\fR" /* Enables verbose logging in the Postfix TLS driver; includes all of /* peercert..cache and more. /* .RE /* .IP /* The default is \fBroutine,certmatch\fR. After a reconnect, the log /* level is unconditionally \fBroutine,cache\fR. -/* .IP "\fB-m \fIcount\fR" +/* .IP "\fB-m \fIcount\fR (default: \fB5\fR)" /* When the \fB-r \fIdelay\fR option is specified, the \fB-m\fR option /* determines the maximum number of reconnect attempts to use with /* a server behind a load-balacer, to see whether connection caching -/* is likely to be effective for this destination. Some MTAs don't -/* expose the underlying server identity in their EHLO response; with -/* these servers there will never be more than 1 reconnection attempt. +/* is likely to be effective for this destination. Some MTAs +/* don't expose the underlying server identity in their EHLO +/* response; with these servers there will never be more than +/* 1 reconnection attempt. /* .IP "\fB-o \fIname=value\fR" /* Specify zero or more times to override the value of the main.cf /* parameter \fIname\fR with \fIvalue\fR. Possible use-cases include -/* overriding the values of TLS library parameters or "myhostname" to +/* overriding the values of TLS library parameters, or "myhostname" to /* configure the SMTP EHLO name sent to the remote server. -/* .IP "\fB-P \fICApath/\fR" +/* .IP "\fB-P \fICApath/\fR (default: none)" /* The OpenSSL CApath/ directory (indexed via c_rehash(1)) for remote /* SMTP server certificate verification. By default no CApath is used /* and no public CAs are trusted. @@ -202,18 +202,21 @@ /* With a cachable TLS session, disconnect and reconnect after \fIdelay\fR /* seconds. Report whether the session is re-used. Retry if a new server /* is encountered, up to 5 times or as specified with the \fB-m\fR option. +/* By default reconnection is disabled, specify a positive delay to +/* enable this behavior. /* .IP "\fB-S\fR" /* Disable SMTP; that is, connect to an LMTP server. The default port for /* LMTP over TCP is 24. Alternative ports can specified by appending /* "\fI:servicename\fR" or ":\fIportnumber\fR" to the destination /* argument. -/* .IP "\fB-t \fItimeout\fR" +/* .IP "\fB-t \fItimeout\fR (default: \fB5\fR)" /* The TCP connection timeout to use. This is also the timeout for /* reading the remote server's 220 banner. -/* .IP "\fB-T \fItimeout\fR" +/* .IP "\fB-T \fItimeout\fR (default: \fB30\fR)" /* The SMTP/LMTP command timeout for EHLO/LHLO, STARTTLS and QUIT. /* .IP "\fB-v\fR" -/* Enable more verbose logging. +/* Enable verose Postfix logging. Specify more than once to increase +/* the level of verbose logging. /* .IP "[\fBinet:\fR]\fIdomain\fR[:\fIport\fR]" /* Connect via TCP to domain \fIdomain\fR, port \fIport\fR. The default /* port is \fBsmtp\fR (or 24 with LMTP). With SMTP an MX lookup is @@ -424,7 +427,7 @@ typedef struct STATE { static DNS_RR *host_addr(STATE *, const char *); -#define HNAME(addr) (addr->validated ? addr->rname : addr->qname) +#define HNAME(addr) (addr->dnssec_valid ? addr->rname : addr->qname) /* * Structure with broken-up SMTP server response. @@ -588,7 +591,7 @@ static void print_trust_info(STATE *state) X509_NAME_oneline(xn, buf, sizeof buf); BIO_printf(state->tls_bio, " issuer: %s\n", buf); } - digest = tls_fingerprint(cert, state->mdalg); + digest = tls_cert_fprint(cert, state->mdalg); BIO_printf(state->tls_bio, " cert digest=%s\n", digest); myfree(digest); @@ -1040,7 +1043,7 @@ static DNS_RR *mx_addr_list(STATE *state, DNS_RR *mx_names) static const char *myname = "mx_addr_list"; DNS_RR *addr_list = 0; DNS_RR *rr; - int res_opt = mx_names->validated ? RES_USE_DNSSEC : 0; + int res_opt = mx_names->dnssec_valid ? RES_USE_DNSSEC : 0; for (rr = mx_names; rr; rr = rr->next) { if (rr->type != T_MX) @@ -1133,7 +1136,7 @@ static int dane_host_level(STATE *state, DNS_RR *addr, unsigned port) #ifdef USE_TLS if (level == TLS_LEV_DANE) { - if (addr->validated) { + if (addr->dnssec_valid) { if (state->log_mask & (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE)) tls_dane_verbose(1); else @@ -1765,4 +1768,3 @@ int main(int argc, char *argv[]) return (0); } - diff --git a/postfix/src/smtp/smtp.h b/postfix/src/smtp/smtp.h index 14a9aba16..70ffd567e 100644 --- a/postfix/src/smtp/smtp.h +++ b/postfix/src/smtp/smtp.h @@ -233,15 +233,14 @@ typedef struct SMTP_STATE { */ #define SMTP_MISC_FLAG_LOOP_DETECT (1<<0) #define SMTP_MISC_FLAG_IN_STARTTLS (1<<1) -#define SMTP_MISC_FLAG_TLSA_HOST (1<<2) -#define SMTP_MISC_FLAG_FIRST_NEXTHOP (1<<3) -#define SMTP_MISC_FLAG_FINAL_NEXTHOP (1<<4) -#define SMTP_MISC_FLAG_FINAL_SERVER (1<<5) -#define SMTP_MISC_FLAG_CONN_LOAD (1<<6) -#define SMTP_MISC_FLAG_CONN_STORE (1<<7) -#define SMTP_MISC_FLAG_COMPLETE_SESSION (1<<8) -#define SMTP_MISC_FLAG_PREF_IPV6 (1<<9) -#define SMTP_MISC_FLAG_PREF_IPV4 (1<<10) +#define SMTP_MISC_FLAG_FIRST_NEXTHOP (1<<2) +#define SMTP_MISC_FLAG_FINAL_NEXTHOP (1<<3) +#define SMTP_MISC_FLAG_FINAL_SERVER (1<<4) +#define SMTP_MISC_FLAG_CONN_LOAD (1<<5) +#define SMTP_MISC_FLAG_CONN_STORE (1<<6) +#define SMTP_MISC_FLAG_COMPLETE_SESSION (1<<7) +#define SMTP_MISC_FLAG_PREF_IPV6 (1<<8) +#define SMTP_MISC_FLAG_PREF_IPV4 (1<<9) #define SMTP_MISC_FLAG_CONN_CACHE_MASK \ (SMTP_MISC_FLAG_CONN_LOAD | SMTP_MISC_FLAG_CONN_STORE) @@ -352,7 +351,7 @@ extern SMTP_SESSION *smtp_session_activate(int, SMTP_ITERATOR *, VSTRING *, VSTR /* * What's in a name? With DANE TLSA we need the rr->rname (if validated). */ -#define SMTP_HNAME(rr) ( (var_smtp_cname_overr || rr->validated) ? \ +#define SMTP_HNAME(rr) ( (var_smtp_cname_overr || rr->dnssec_valid) ? \ (rr)->rname : (rr)->qname ) /* @@ -565,15 +564,34 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int); #define SMTP_KEY_FLAG_HOSTNAME (1<<4) /* remote host name */ #define SMTP_KEY_FLAG_ADDR (1<<5) /* remote address */ #define SMTP_KEY_FLAG_PORT (1<<6) /* remote port */ -#define SMTP_KEY_FLAG_SASL (1<<7) /* username, password */ -#define SMTP_KEY_FLAG_NOSASL (1<<8) /* dummy-user, dummy-pass */ #define SMTP_KEY_MASK_ALL \ (SMTP_KEY_FLAG_SERVICE | SMTP_KEY_FLAG_SENDER | \ SMTP_KEY_FLAG_REQ_NEXTHOP | \ SMTP_KEY_FLAG_NEXTHOP | SMTP_KEY_FLAG_HOSTNAME | \ - SMTP_KEY_FLAG_ADDR | SMTP_KEY_FLAG_PORT | \ - SMTP_KEY_FLAG_SASL | SMTP_KEY_FLAG_NOSASL) + SMTP_KEY_FLAG_ADDR | SMTP_KEY_FLAG_PORT) + + /* + * Connection-cache destination lookup key. The SENDER attribute is a proxy + * for sender-dependent SASL credentials (or absence thereof), and prevents + * false connection sharing when different SASL credentials may be required + * for different deliveries to the same domain and port. The SERVICE + * attribute is a proxy for all request-independent configuration details. + */ +#define SMTP_KEY_MASK_SCACHE_DEST_LABEL \ + (SMTP_KEY_FLAG_SERVICE | SMTP_KEY_FLAG_SENDER \ + | SMTP_KEY_FLAG_REQ_NEXTHOP) + + /* + * Connection-cache endpoint lookup key. The SENDER, NEXTHOP, and HOSTNAME + * attributes are proxies for SASL credentials (or absence thereof), and + * prevent false connection sharing when different SASL credentials may be + * required for different deliveries to the same IP address and port. + */ +#define SMTP_KEY_MASK_SCACHE_ENDP_LABEL \ + (SMTP_KEY_FLAG_SERVICE | SMTP_KEY_FLAG_SENDER \ + | SMTP_KEY_FLAG_REQ_NEXTHOP | SMTP_KEY_FLAG_HOSTNAME \ + | SMTP_KEY_FLAG_ADDR | SMTP_KEY_FLAG_PORT) /* * Silly little macros. diff --git a/postfix/src/smtp/smtp_addr.c b/postfix/src/smtp/smtp_addr.c index 4f9853e13..b4b253e7b 100644 --- a/postfix/src/smtp/smtp_addr.c +++ b/postfix/src/smtp/smtp_addr.c @@ -237,7 +237,7 @@ static DNS_RR *smtp_addr_list(DNS_RR *mx_names, DSN_BUF *why) { DNS_RR *addr_list = 0; DNS_RR *rr; - int res_opt = mx_names->validated ? RES_USE_DNSSEC : 0; + int res_opt = mx_names->dnssec_valid ? RES_USE_DNSSEC : 0; /* * As long as we are able to look up any host address, we ignore problems diff --git a/postfix/src/smtp/smtp_connect.c b/postfix/src/smtp/smtp_connect.c index 06a6ad92b..337a8371b 100644 --- a/postfix/src/smtp/smtp_connect.c +++ b/postfix/src/smtp/smtp_connect.c @@ -269,9 +269,6 @@ static SMTP_SESSION *smtp_connect_addr(SMTP_ITERATOR *iter, DSN_BUF *why, msg_info("%s: trying: %s[%s] port %d...", myname, STR(iter->host), STR(iter->addr), ntohs(port)); - if (addr->validated) - sess_flags |= SMTP_MISC_FLAG_TLSA_HOST; - return (smtp_connect_sock(sock, sa, salen, iter, why, sess_flags)); } @@ -399,11 +396,6 @@ static void smtp_cleanup_session(SMTP_STATE *state) * hosts. In fact, this is the only benefit of caching logical to * physical bindings; caching a session under its own hostname provides * no performance benefit, given the way smtp_connect() works. - * - * The SMTP_KEY_FLAG_SASL attribute is required in the endpoint label to - * avoid false sharing of SASL-authenticated and -unauthenticated - * connections to the same IP address. We don't have this problem with - * UNIX-domain connections as long as we use nexthop == address. */ bad_session = THIS_SESSION_IS_BAD; /* smtp_quit() may fail */ if (THIS_SESSION_IS_EXPIRED) @@ -412,13 +404,8 @@ static void smtp_cleanup_session(SMTP_STATE *state) /* Redundant tests for safety... */ && vstream_ferror(session->stream) == 0 && vstream_feof(session->stream) == 0) { - smtp_save_session(state, SMTP_KEY_FLAG_SERVICE - | SMTP_KEY_FLAG_SENDER - | SMTP_KEY_FLAG_REQ_NEXTHOP, - SMTP_KEY_FLAG_SERVICE - | SMTP_KEY_FLAG_SASL - | SMTP_KEY_FLAG_ADDR - | SMTP_KEY_FLAG_PORT); + smtp_save_session(state, SMTP_KEY_MASK_SCACHE_DEST_LABEL, + SMTP_KEY_MASK_SCACHE_ENDP_LABEL); } else { smtp_session_free(session); } @@ -530,9 +517,8 @@ static void smtp_connect_local(SMTP_STATE *state, const char *path) } #endif if ((state->misc_flags & SMTP_MISC_FLAG_CONN_LOAD) == 0 - || (session = smtp_reuse_nexthop(state, SMTP_KEY_FLAG_SERVICE - | SMTP_KEY_FLAG_SENDER - | SMTP_KEY_FLAG_REQ_NEXTHOP)) == 0) + || (session = smtp_reuse_nexthop(state, + SMTP_KEY_MASK_SCACHE_DEST_LABEL)) == 0) session = smtp_connect_unix(iter, why, state->misc_flags); if ((state->session = session) != 0) { session->state = state; @@ -681,9 +667,7 @@ static int smtp_reuse_session(SMTP_STATE *state, DNS_RR **addr_list, #endif SMTP_ITER_SAVE_DEST(state->iterator); if (*addr_list && SMTP_RCPT_LEFT(state) > 0 - && (session = smtp_reuse_nexthop(state, SMTP_KEY_FLAG_SERVICE - | SMTP_KEY_FLAG_SENDER - | SMTP_KEY_FLAG_REQ_NEXTHOP)) != 0) { + && (session = smtp_reuse_nexthop(state, SMTP_KEY_MASK_SCACHE_DEST_LABEL)) != 0) { session_count = 1; smtp_update_addr_list(addr_list, session->addr, session_count); if ((state->misc_flags & SMTP_MISC_FLAG_FINAL_NEXTHOP) @@ -739,10 +723,8 @@ static int smtp_reuse_session(SMTP_STATE *state, DNS_RR **addr_list, /* XXX Assume there is no code at the end of this loop. */ } #endif - if ((session = smtp_reuse_addr(state, SMTP_KEY_FLAG_SERVICE - | SMTP_KEY_FLAG_NOSASL - | SMTP_KEY_FLAG_ADDR - | SMTP_KEY_FLAG_PORT)) != 0) { + if ((session = smtp_reuse_addr(state, + SMTP_KEY_MASK_SCACHE_ENDP_LABEL)) != 0) { session->features |= SMTP_FEATURE_BEST_MX; session_count += 1; smtp_update_addr_list(addr_list, session->addr, session_count); @@ -989,10 +971,8 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop, #endif if ((state->misc_flags & SMTP_MISC_FLAG_CONN_LOAD) == 0 || addr->pref == domain_best_pref - || !(session = smtp_reuse_addr(state, SMTP_KEY_FLAG_SERVICE - | SMTP_KEY_FLAG_NOSASL - | SMTP_KEY_FLAG_ADDR - | SMTP_KEY_FLAG_PORT))) + || !(session = smtp_reuse_addr(state, + SMTP_KEY_MASK_SCACHE_ENDP_LABEL))) session = smtp_connect_addr(iter, why, state->misc_flags); if ((state->session = session) != 0) { session->state = state; diff --git a/postfix/src/smtp/smtp_key.c b/postfix/src/smtp/smtp_key.c index f92540428..6cfe299e4 100644 --- a/postfix/src/smtp/smtp_key.c +++ b/postfix/src/smtp/smtp_key.c @@ -128,19 +128,6 @@ static void smtp_key_append_na(VSTRING *buffer, const char *delim_na) VSTRING_ADDCH(buffer, delim_na[0]); } -/* smtp_key_append_base64 - append base64-encoded key field */ - -static void smtp_key_append_base64(VSTRING *buffer, const char *str, - const char *delim_na) -{ - if (str == 0 || str[0] == 0) { - smtp_key_append_na(buffer, delim_na); - } else { - base64_encode_opt(buffer, str, strlen(str), BASE64_FLAG_APPEND); - VSTRING_ADDCH(buffer, delim_na[0]); - } -} - /* smtp_key_append_str - append string-valued key field */ static void smtp_key_append_str(VSTRING *buffer, const char *str, @@ -171,7 +158,6 @@ char *smtp_key_prefix(VSTRING *buffer, const char *delim_na, { const char myname[] = "smtp_key_prefix"; SMTP_STATE *state = iter->parent; /* private member */ - SMTP_SESSION *session; /* * Sanity checks. @@ -222,24 +208,6 @@ char *smtp_key_prefix(VSTRING *buffer, const char *delim_na, if (flags & SMTP_KEY_FLAG_PORT) smtp_key_append_uint(buffer, ntohs(iter->port), delim_na); - /* - * Security attributes. - */ -#ifdef USE_SASL_AUTH - if (flags & SMTP_KEY_FLAG_NOSASL) { - smtp_key_append_na(buffer, delim_na); /* username n/a */ - smtp_key_append_na(buffer, delim_na); /* password n/a */ - } - if (flags & SMTP_KEY_FLAG_SASL) { - if ((session = state->session) == 0 || session->sasl_username == 0) { - smtp_key_append_na(buffer, delim_na); /* username n/a */ - smtp_key_append_na(buffer, delim_na); /* password n/a */ - } else { - smtp_key_append_base64(buffer, session->sasl_username, delim_na); - smtp_key_append_base64(buffer, session->sasl_passwd, delim_na); - } - } -#endif /* Similarly, provide unique TLS fingerprint when applicable. */ VSTRING_TERMINATE(buffer); diff --git a/postfix/src/smtp/smtp_reuse.c b/postfix/src/smtp/smtp_reuse.c index a1ba7112f..eeadbb20d 100644 --- a/postfix/src/smtp/smtp_reuse.c +++ b/postfix/src/smtp/smtp_reuse.c @@ -242,31 +242,9 @@ SMTP_SESSION *smtp_reuse_nexthop(SMTP_STATE *state, int name_key_flags) SMTP_SESSION *smtp_reuse_addr(SMTP_STATE *state, int endp_key_flags) { - const char *myname = "smtp_reuse_addr"; SMTP_SESSION *session; int fd; - /* - * Sanity check. We currently lack support to look up SASL credentials. - */ -#ifdef USE_SASL_AUTH - if ((endp_key_flags & SMTP_KEY_FLAG_SASL) != 0) - msg_panic("%s: SASL credential lookup is not supported", myname); -#endif - - /* - * Don't look up an existing SASL-unauthenticated connection when a new - * connection may require authentication. We conservatively test below if - * unauthenticated connection reuse is guaranteed to be OK. This test can - * be replaced later with a more precise one. - */ -#ifdef USE_SASL_AUTH - if ((endp_key_flags & SMTP_KEY_FLAG_NOSASL) != 0 - && var_smtp_sasl_enable != 0 - && *var_smtp_sasl_passwd != 0) - return (0); -#endif - /* * Don't look up an existing plaintext connection when a new connection * would (try to) use TLS. diff --git a/postfix/src/smtp/smtp_session.c b/postfix/src/smtp/smtp_session.c index a8eaae188..2336f0b0a 100644 --- a/postfix/src/smtp/smtp_session.c +++ b/postfix/src/smtp/smtp_session.c @@ -57,8 +57,6 @@ /* .IP flags /* Zero or more of the following: /* .RS -/* .IP SMTP_MISC_FLAG_TLSA_HOST -/* The hostname is DNSSEC-validated. /* .IP SMTP_MISC_FLAG_CONN_LOAD /* Enable re-use of cached SMTP or LMTP connections. /* .IP SMTP_MISC_FLAG_CONN_STORE diff --git a/postfix/src/smtp/smtp_tls_policy.c b/postfix/src/smtp/smtp_tls_policy.c index f0ec16415..836dc407a 100644 --- a/postfix/src/smtp/smtp_tls_policy.c +++ b/postfix/src/smtp/smtp_tls_policy.c @@ -679,7 +679,7 @@ int smtp_tls_policy_cache_query(DSN_BUF *why, SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter) { VSTRING *key; - int valid = iter->rr && iter->rr->validated; + int valid = iter->rr && iter->rr->dnssec_valid; /* * Create an empty TLS Policy cache on the fly. @@ -803,7 +803,7 @@ static int global_tls_level(void) static void dane_init(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter) { TLS_DANE *dane; - int valid = iter->rr && iter->rr->validated; + int valid = iter->rr && iter->rr->dnssec_valid; if (!iter->port) { msg_warn("%s: the \"dane\" security level is invalid for delivery via" diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 52ebc66c1..e5b165bf1 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -1336,7 +1336,7 @@ static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs) int i; char *prints[2]; - prints[0] = state->tls_context->peer_fingerprint; + prints[0] = state->tls_context->peer_cert_fprint; prints[1] = state->tls_context->peer_pkey_fprint; /* After lookup error, leave relay_ccerts->error at non-zero value. */ @@ -2794,7 +2794,7 @@ static int check_ccert_access(SMTPD_STATE *state, const char *table, int i; char *prints[2]; - prints[0] = state->tls_context->peer_fingerprint; + prints[0] = state->tls_context->peer_cert_fprint; prints[1] = state->tls_context->peer_pkey_fprint; for (i = 0; i < 2; ++i) { @@ -3614,8 +3614,8 @@ static int check_policy_service(SMTPD_STATE *state, const char *server, * When directly checking the fingerprint, it is OK if the issuing CA is * not trusted. */ - ATTR_TYPE_STR, MAIL_ATTR_CCERT_FINGERPRINT, - IF_ENCRYPTED(state->tls_context->peer_fingerprint, ""), + ATTR_TYPE_STR, MAIL_ATTR_CCERT_CERT_FPRINT, + IF_ENCRYPTED(state->tls_context->peer_cert_fprint, ""), ATTR_TYPE_STR, MAIL_ATTR_CCERT_PKEY_FPRINT, IF_ENCRYPTED(state->tls_context->peer_pkey_fprint, ""), ATTR_TYPE_STR, MAIL_ATTR_CRYPTO_PROTOCOL, @@ -5689,14 +5689,14 @@ int main(int argc, char **argv) (TLS_SESS_STATE *) mymalloc(sizeof(*state.tls_context)); memset((char *) state.tls_context, 0, sizeof(*state.tls_context)); - state.tls_context->peer_fingerprint = + state.tls_context->peer_cert_fprint = state.tls_context->peer_pkey_fprint = 0; } state.tls_context->peer_status |= TLS_CERT_FLAG_PRESENT; - UPDATE_STRING(state.tls_context->peer_fingerprint, + UPDATE_STRING(state.tls_context->peer_cert_fprint, args->argv[1]); state.tls_context->peer_pkey_fprint = - state.tls_context->peer_fingerprint; + state.tls_context->peer_cert_fprint; resp = "OK"; break; #endif @@ -5738,7 +5738,7 @@ int main(int argc, char **argv) FREE_STRING(state.helo_name); FREE_STRING(state.sender); if (state.tls_context) { - FREE_STRING(state.tls_context->peer_fingerprint); + FREE_STRING(state.tls_context->peer_cert_fprint); myfree((char *) state.tls_context); } exit(0); diff --git a/postfix/src/tls/tls.h b/postfix/src/tls/tls.h index 138b5b4fa..2465ad847 100644 --- a/postfix/src/tls/tls.h +++ b/postfix/src/tls/tls.h @@ -180,7 +180,7 @@ typedef struct { /* Public, read-only. */ char *peer_CN; /* Peer Common Name */ char *issuer_CN; /* Issuer Common Name */ - char *peer_fingerprint; /* ASCII fingerprint */ + char *peer_cert_fprint; /* ASCII certificate fingerprint */ char *peer_pkey_fprint; /* ASCII public key fingerprint */ int peer_status; /* Certificate and match status */ const char *protocol; @@ -513,8 +513,8 @@ extern void tls_log_verify_error(TLS_SESS_STATE *); * tls_fprint.c */ extern char *tls_digest_encode(const unsigned char *, int); -extern char *tls_fprint(const char *, int, const char *); -extern char *tls_fingerprint(X509 *, const char *); +extern char *tls_data_fprint(const char *, int, const char *); +extern char *tls_cert_fprint(X509 *, const char *); extern char *tls_pkey_fprint(X509 *, const char *); extern char *tls_serverid_digest(const TLS_CLIENT_START_PROPS *, long, const char *); diff --git a/postfix/src/tls/tls_client.c b/postfix/src/tls/tls_client.c index 920ef929c..3d5ff9f98 100644 --- a/postfix/src/tls/tls_client.c +++ b/postfix/src/tls/tls_client.c @@ -91,7 +91,7 @@ /* .IP TLScontext->issuer_CN /* Extracted CommonName of the issuer, or zero-length string if the /* information could not be extracted. -/* .IP TLScontext->peer_fingerprint +/* .IP TLScontext->peer_cert_fprint /* At the fingerprint security level, if the peer presented a certificate /* the fingerprint of the certificate. /* .PP @@ -585,8 +585,8 @@ static void verify_extract_name(TLS_SESS_STATE *TLScontext, X509 *peercert, * peername if using traditional PKI or DANE with trust-anchors. */ if (!TLS_CERT_IS_MATCHED(TLScontext) - && TLS_CERT_IS_TRUSTED(TLScontext) - && TLS_MUST_TRUST(props->tls_level)) + && TLS_CERT_IS_TRUSTED(TLScontext) + && TLS_MUST_TRUST(props->tls_level)) verify_peername = 1; /* Force cert processing so we can log the data? */ @@ -711,7 +711,7 @@ static void verify_extract_name(TLS_SESS_STATE *TLScontext, X509 *peercert, static void verify_extract_print(TLS_SESS_STATE *TLScontext, X509 *peercert, const TLS_CLIENT_START_PROPS *props) { - TLScontext->peer_fingerprint = tls_fingerprint(peercert, props->mdalg); + TLScontext->peer_cert_fprint = tls_cert_fprint(peercert, props->mdalg); TLScontext->peer_pkey_fprint = tls_pkey_fprint(peercert, props->mdalg); /* @@ -750,10 +750,10 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) /* * When certificate verification is required, log trust chain validation * errors even when disabled by default for opportunistic sessions. For - * "dane" this only applies when using trust-anchors associations. + * "dane" this only applies when using trust-anchors associations. */ if (TLS_MUST_TRUST(props->tls_level) - && (props->tls_level != TLS_LEV_DANE || TLS_DANE_HASTA(props->dane))) + && (props->tls_level != TLS_LEV_DANE || TLS_DANE_HASTA(props->dane))) log_mask |= TLS_LOG_UNTRUSTED; if (log_mask & TLS_LOG_VERBOSE) @@ -774,7 +774,7 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) } /* The DANE level requires TLS 1.0 or later, not SSLv2 or SSLv3. */ if (props->tls_level == TLS_LEV_DANE) - protomask |= TLS_PROTOCOL_SSLv3 | TLS_PROTOCOL_SSLv2; + protomask |= TLS_PROTOCOL_SSLv3 | TLS_PROTOCOL_SSLv2; /* * Per session cipher selection for sessions with mandatory encryption @@ -872,11 +872,11 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) SSL_SESSION_free(session); /* 200411 */ } } - #ifdef TLSEXT_MAXLEN_host_name if (session == 0 - && props->tls_level == TLS_LEV_DANE - && strlen(props->host) <= TLSEXT_MAXLEN_host_name) { + && props->tls_level == TLS_LEV_DANE + && strlen(props->host) <= TLSEXT_MAXLEN_host_name) { + /* * With new DANE sessions, send an SNI hint. We don't care whether * the server reports finding a matching certificate or not, so no @@ -886,7 +886,7 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) * the associated TLSA RRs. (Generally, server administrators should * avoid SNI, and there are no plans to support SNI in the Postfix * SMTP server). - * + * * Since the hostname is DNSSEC-validated, it must be a DNS FQDN and * thererefore valid for use with SNI. Failure to set a valid SNI * hostname is a memory allocation error, and thus transient. Since @@ -991,7 +991,7 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) /* * Peer name or fingerprint verification as requested. - * Unconditionally set peer_CN, issuer_CN and peer_fingerprint. Check + * Unconditionally set peer_CN, issuer_CN and peer_cert_fprint. Check * fingerprint first, and avoid logging verified as untrusted in the * call to verify_extract_name(). */ @@ -1003,13 +1003,13 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) msg_info("%s: subject_CN=%s, issuer_CN=%s, " "fingerprint=%s, pkey_fingerprint=%s", props->namaddr, TLScontext->peer_CN, TLScontext->issuer_CN, - TLScontext->peer_fingerprint, + TLScontext->peer_cert_fprint, TLScontext->peer_pkey_fprint); X509_free(peercert); } else { TLScontext->issuer_CN = mystrdup(""); TLScontext->peer_CN = mystrdup(""); - TLScontext->peer_fingerprint = mystrdup(""); + TLScontext->peer_cert_fprint = mystrdup(""); TLScontext->peer_pkey_fprint = mystrdup(""); } diff --git a/postfix/src/tls/tls_dane.c b/postfix/src/tls/tls_dane.c index f57b30614..d961199bf 100644 --- a/postfix/src/tls/tls_dane.c +++ b/postfix/src/tls/tls_dane.c @@ -649,7 +649,7 @@ static void parse_tlsa_rrs(TLS_DANE *dane, DNS_RR *rr) * and encode the digest value. We choose SHA256. */ dane_add(dane, usage, selector, sha256, - digest = tls_fprint((char *)ip, mlen, sha256)); + digest = tls_data_fprint((char *)ip, mlen, sha256)); break; } if (msg_verbose || dane_verbose) @@ -688,7 +688,7 @@ static void *dane_lookup(const char *tlsa_fqdn, void *unused_ctx) /* One more second to account for discrete time */ dane->expires = 1 + event_time() + rrs->ttl; - if (rrs->validated) + if (rrs->dnssec_valid) parse_tlsa_rrs(dane, rrs); dns_rr_free(rrs); @@ -779,7 +779,7 @@ int tls_dane_load_trustfile(TLS_DANE *dane, const char *tafile) if (cert && (p - data) == len) { selector = DNS_TLSA_SELECTOR_FULL_CERTIFICATE; - digest = tls_fprint((char *)data, len, sha256); + digest = tls_data_fprint((char *)data, len, sha256); dane_add(dane, usage, selector, sha256, digest); myfree(digest); ta_cert_insert(dane, cert); @@ -792,7 +792,7 @@ int tls_dane_load_trustfile(TLS_DANE *dane, const char *tafile) if (pkey && (p - data) == len) { selector = DNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO; - digest = tls_fprint((char *)data, len, sha256); + digest = tls_data_fprint((char *)data, len, sha256); dane_add(dane, usage, selector, sha256, digest); myfree(digest); ta_pkey_insert(dane, pkey); diff --git a/postfix/src/tls/tls_fprint.c b/postfix/src/tls/tls_fprint.c index cc83686b4..8f731e6ea 100644 --- a/postfix/src/tls/tls_fprint.c +++ b/postfix/src/tls/tls_fprint.c @@ -15,12 +15,12 @@ /* const unsigned char *md_buf; /* const char *md_len; /* -/* char *tls_fprint(buf, len, mdalg) +/* char *tls_data_fprint(buf, len, mdalg) /* const char *buf; /* int len; /* const char *mdalg; /* -/* char *tls_fingerprint(peercert, mdalg) +/* char *tls_cert_fprint(peercert, mdalg) /* X509 *peercert; /* const char *mdalg; /* @@ -33,12 +33,12 @@ /* The return value is dynamically allocated with mymalloc(), /* and the caller must eventually free it with myfree(). /* -/* tls_fprint() digests unstructured data, and encodes the digested -/* result via tls_digest_encode(). -/* The return value is dynamically allocated with mymalloc(), -/* and the caller must eventually free it with myfree(). +/* tls_data_fprint() digests unstructured data, and encodes the digested +/* result via tls_digest_encode(). The return value is dynamically +/* allocated with mymalloc(), and the caller must eventually free it +/* with myfree(). /* -/* tls_fingerprint() returns a fingerprint of the the given +/* tls_cert_fprint() returns a fingerprint of the the given /* certificate using the requested message digest, formatted /* with tls_digest_encode(). Panics if the /* (previously verified) digest algorithm is not found. The return @@ -46,7 +46,7 @@ /* must eventually free it with myfree(). /* /* tls_pkey_fprint() returns a public-key fingerprint; in all -/* other respects the function behaves as tls_fingerprint(). +/* other respects the function behaves as tls_cert_fprint(). /* The var_tls_bc_pkey_fprint variable enables an incorrect /* algorithm that was used in Postfix versions 2.9.[0-5]. /* The return value is dynamically allocated with mymalloc(), @@ -125,35 +125,36 @@ static const char hexcodes[] = "0123456789ABCDEF"; -#define chknonzero(ret) (ok &= ((ret) ? 1 : 0)) -#define digestpl(p, l) chknonzero(EVP_DigestUpdate(mdctx, (char *)(p), (l))) -#define digestptr(p) digestpl((p), sizeof(*(p))) -#define digeststr(s) digestpl((s), strlen(s)+1) +#define checkok(ret) (ok &= ((ret) ? 1 : 0)) +#define digest_data(p, l) checkok(EVP_DigestUpdate(mdctx, (char *)(p), (l))) +#define digest_object(p) digest_data((p), sizeof(*(p))) +#define digest_string(s) digest_data((s), strlen(s)+1) -#define digestdane(dane, memb) do { \ +#define digest_dane(dane, memb) do { \ if ((dane)->memb != 0) \ - chknonzero(tlsa_digest(mdctx, (dane)->memb, #memb)); \ + checkok(digest_tlsa_usage(mdctx, (dane)->memb, #memb)); \ } while (0) -#define digesttlsa(tlsa, memb) do { \ +#define digest_tlsa_argv(tlsa, memb) do { \ if ((tlsa)->memb) { \ - digeststr(#memb); \ + digest_string(#memb); \ for (dgst = (tlsa)->memb->argv; *dgst; ++dgst) \ - digeststr(*dgst); \ + digest_string(*dgst); \ } \ } while (0) -/* tlsa_digest - digest a pre-sorted by caller TLSA match list */ +/* digest_tlsa_usage - digest TA or EE match list sorted by alg and value */ -static int tlsa_digest(EVP_MD_CTX *mdctx, TLS_TLSA *tlsa, const char *usage) +static int digest_tlsa_usage(EVP_MD_CTX * mdctx, TLS_TLSA *tlsa, + const char *usage) { char **dgst; int ok = 1; - for (digeststr(usage); tlsa; tlsa = tlsa->next) { - digeststr(tlsa->mdalg); - digesttlsa(tlsa, pkeys); - digesttlsa(tlsa, certs); + for (digest_string(usage); tlsa; tlsa = tlsa->next) { + digest_string(tlsa->mdalg); + digest_tlsa_argv(tlsa, pkeys); + digest_tlsa_argv(tlsa, certs); } return (ok); } @@ -190,34 +191,34 @@ char *tls_serverid_digest(const TLS_CLIENT_START_PROPS *props, long protomask, sslversion = SSLeay(); mdctx = EVP_MD_CTX_create(); - chknonzero(EVP_DigestInit_ex(mdctx, md, NULL)); - digeststr(props->helo ? props->helo : ""); - digestptr(&sslversion); - digestptr(&protomask); - digeststr(ciphers); + checkok(EVP_DigestInit_ex(mdctx, md, NULL)); + digest_string(props->helo ? props->helo : ""); + digest_object(&sslversion); + digest_object(&protomask); + digest_string(ciphers); /* * All we get from the session cache is a single bit telling us whether * the certificate is trusted or not, but we need to know whether the * trust is CA-based (in that case we must do name checks) or whether it - * is a direct end-point match. We mustn't confuse the two, so it is best - * to process only TA trust in the verify callback and check the EE trust - * after. This works since re-used sessions always have access to the leaf - * certificate, while only the original session has the leaf and the full - * trust chain. - * - * Only the trust anchor matchlist is hashed into the session key. - * The end entity certs are not used to determine whether a certificate - * is trusted or not, rather these are rechecked against the leaf cert + * is a direct end-point match. We mustn't confuse the two, so it is + * best to process only TA trust in the verify callback and check the EE + * trust after. This works since re-used sessions always have access to + * the leaf certificate, while only the original session has the leaf and + * the full trust chain. + * + * Only the trust anchor matchlist is hashed into the session key. The end + * entity certs are not used to determine whether a certificate is + * trusted or not, rather these are rechecked against the leaf cert * outside the verification callback, each time a session is created or * reused. - * - * Therefore, the security context of the session does not depend on the - * EE matching data, which is checked separately each time. So we exclude + * + * Therefore, the security context of the session does not depend on the EE + * matching data, which is checked separately each time. So we exclude * the EE part of the DANE structure from the serverid digest. - * + * * If this changes, also update tls_dane_final() in tls_dane.c. - * + * * If the security level is "dane", we send SNI information to the peer. * This may cause it to respond with a non-default certificate. Since * certificates for sessions with no or different SNI data may not match, @@ -226,14 +227,14 @@ char *tls_serverid_digest(const TLS_CLIENT_START_PROPS *props, long protomask, if (props->dane) { int mixed = (props->dane->flags & TLS_DANE_FLAG_MIXED); - digestptr(&mixed); - digestdane(props->dane, ta); + digest_object(&mixed); + digest_dane(props->dane, ta); #if 0 - digestdane(props->dane, ee); /* See above */ + digest_dane(props->dane, ee); /* See above */ #endif - digeststr(props->tls_level == TLS_LEV_DANE ? props->host : ""); + digest_string(props->tls_level == TLS_LEV_DANE ? props->host : ""); } - chknonzero(EVP_DigestFinal_ex(mdctx, md_buf, &md_len)); + checkok(EVP_DigestFinal_ex(mdctx, md_buf, &md_len)); EVP_MD_CTX_destroy(mdctx); if (!ok) msg_fatal("error computing %s message digest", mdalg); @@ -242,7 +243,17 @@ char *tls_serverid_digest(const TLS_CLIENT_START_PROPS *props, long protomask, if (md_len > EVP_MAX_MD_SIZE) msg_panic("unexpectedly large %s digest size: %u", mdalg, md_len); - /* Append the digest to the serverid */ + /* + * Append the digest to the serverid. We don't compare this digest to + * any user-specified fingerprints. Therefore, we don't need to use a + * colon-separated format, which saves space in the TLS session cache and + * makes logging of session cache lookup keys more readable. + * + * This does however duplicate a few lines of code from the digest encoder + * for colon-separated cert and pkey fingerprints. If that is a + * compelling reason to consolidate, we could use that and append the + * result. + */ result = vstring_alloc(strlen(props->serverid) + 1 + 2 * md_len); vstring_strcpy(result, props->serverid); VSTRING_ADDCH(result, ':'); @@ -274,9 +285,9 @@ char *tls_digest_encode(const unsigned char *md_buf, int md_len) return (result); } -/* tls_fprint - compute and encode digest of DER-encoded object */ +/* tls_data_fprint - compute and encode digest of binary object */ -char *tls_fprint(const char *buf, int len, const char *mdalg) +char *tls_data_fprint(const char *buf, int len, const char *mdalg) { EVP_MD_CTX *mdctx; const EVP_MD *md; @@ -289,9 +300,9 @@ char *tls_fprint(const char *buf, int len, const char *mdalg) msg_panic("digest algorithm \"%s\" not found", mdalg); mdctx = EVP_MD_CTX_create(); - chknonzero(EVP_DigestInit_ex(mdctx, md, NULL)); - digestpl(buf, len); - chknonzero(EVP_DigestFinal_ex(mdctx, md_buf, &md_len)); + checkok(EVP_DigestInit_ex(mdctx, md, NULL)); + digest_data(buf, len); + checkok(EVP_DigestFinal_ex(mdctx, md_buf, &md_len)); EVP_MD_CTX_destroy(mdctx); if (!ok) msg_fatal("error computing %s message digest", mdalg); @@ -299,9 +310,9 @@ char *tls_fprint(const char *buf, int len, const char *mdalg) return (tls_digest_encode(md_buf, md_len)); } -/* tls_fingerprint - extract certificate fingerprint */ +/* tls_cert_fprint - extract certificate fingerprint */ -char *tls_fingerprint(X509 *peercert, const char *mdalg) +char *tls_cert_fprint(X509 *peercert, const char *mdalg) { int len; char *buf; @@ -314,7 +325,7 @@ char *tls_fingerprint(X509 *peercert, const char *mdalg) if (buf2 - buf != len) msg_panic("i2d_X509 invalid result length"); - result = tls_fprint(buf, len, mdalg); + result = tls_data_fprint(buf, len, mdalg); myfree(buf); return (result); @@ -334,7 +345,7 @@ char *tls_pkey_fprint(X509 *peercert, const char *mdalg) msg_fatal("%s: error extracting legacy public-key fingerprint: %m", myname); - result = tls_fprint((char *) key->data, key->length, mdalg); + result = tls_data_fprint((char *) key->data, key->length, mdalg); return (result); } else { int len; @@ -348,7 +359,7 @@ char *tls_pkey_fprint(X509 *peercert, const char *mdalg) if (buf2 - buf != len) msg_panic("i2d_X509_PUBKEY invalid result length"); - result = tls_fprint(buf, len, mdalg); + result = tls_data_fprint(buf, len, mdalg); myfree(buf); return (result); } diff --git a/postfix/src/tls/tls_misc.c b/postfix/src/tls/tls_misc.c index 5fbb417cd..086aaf76a 100644 --- a/postfix/src/tls/tls_misc.c +++ b/postfix/src/tls/tls_misc.c @@ -402,7 +402,7 @@ int tls_log_mask(const char *log_param, const char *log_level) /* tls_update_app_logmask - update log level after init */ -void tls_update_app_logmask(TLS_APPL_STATE *app_ctx, int log_mask) +void tls_update_app_logmask(TLS_APPL_STATE *app_ctx, int log_mask) { app_ctx->log_mask = log_mask; } @@ -755,14 +755,15 @@ TLS_SESS_STATE *tls_alloc_sess_context(int log_mask, const char *namaddr) TLScontext->serverid = 0; TLScontext->peer_CN = 0; TLScontext->issuer_CN = 0; - TLScontext->peer_fingerprint = 0; + TLScontext->peer_cert_fprint = 0; TLScontext->peer_pkey_fprint = 0; TLScontext->protocol = 0; TLScontext->cipher_name = 0; TLScontext->log_mask = log_mask; TLScontext->namaddr = lowercase(mystrdup(namaddr)); - TLScontext->mdalg = 0; /* Alias for props->mdalg */ - TLScontext->dane = 0; /* Alias for client props->dane */ + TLScontext->mdalg = 0; /* Alias for props->mdalg */ + TLScontext->dane = 0; /* Alias for client + * props->dane */ TLScontext->trustdepth = -1; TLScontext->chaindepth = -1; TLScontext->errordepth = -1; @@ -794,8 +795,8 @@ void tls_free_context(TLS_SESS_STATE *TLScontext) myfree(TLScontext->peer_CN); if (TLScontext->issuer_CN) myfree(TLScontext->issuer_CN); - if (TLScontext->peer_fingerprint) - myfree(TLScontext->peer_fingerprint); + if (TLScontext->peer_cert_fprint) + myfree(TLScontext->peer_cert_fprint); if (TLScontext->peer_pkey_fprint) myfree(TLScontext->peer_pkey_fprint); if (TLScontext->errorcert) diff --git a/postfix/src/tls/tls_proxy_clnt.c b/postfix/src/tls/tls_proxy_clnt.c index cf7c32f3e..2cacf4441 100644 --- a/postfix/src/tls/tls_proxy_clnt.c +++ b/postfix/src/tls/tls_proxy_clnt.c @@ -233,8 +233,8 @@ void tls_proxy_context_free(TLS_SESS_STATE *tls_context) myfree(tls_context->peer_CN); if (tls_context->issuer_CN) myfree(tls_context->issuer_CN); - if (tls_context->peer_fingerprint) - myfree(tls_context->peer_fingerprint); + if (tls_context->peer_cert_fprint) + myfree(tls_context->peer_cert_fprint); if (tls_context->protocol) myfree((char *) tls_context->protocol); if (tls_context->cipher_name) diff --git a/postfix/src/tls/tls_proxy_print.c b/postfix/src/tls/tls_proxy_print.c index e919a9ee8..a850cb1d4 100644 --- a/postfix/src/tls/tls_proxy_print.c +++ b/postfix/src/tls/tls_proxy_print.c @@ -65,8 +65,8 @@ int tls_proxy_context_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp, STRING_OR_EMPTY(tp->peer_CN), ATTR_TYPE_STR, MAIL_ATTR_ISSUER_CN, STRING_OR_EMPTY(tp->issuer_CN), - ATTR_TYPE_STR, MAIL_ATTR_PEER_FPT, - STRING_OR_EMPTY(tp->peer_fingerprint), + ATTR_TYPE_STR, MAIL_ATTR_PEER_CERT_FPT, + STRING_OR_EMPTY(tp->peer_cert_fprint), ATTR_TYPE_STR, MAIL_ATTR_PEER_PKEY_FPT, STRING_OR_EMPTY(tp->peer_pkey_fprint), ATTR_TYPE_INT, MAIL_ATTR_PEER_STATUS, diff --git a/postfix/src/tls/tls_proxy_scan.c b/postfix/src/tls/tls_proxy_scan.c index 33db215dd..428f24a57 100644 --- a/postfix/src/tls/tls_proxy_scan.c +++ b/postfix/src/tls/tls_proxy_scan.c @@ -59,7 +59,7 @@ int tls_proxy_context_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp, int ret; VSTRING *peer_CN = vstring_alloc(25); VSTRING *issuer_CN = vstring_alloc(25); - VSTRING *peer_fingerprint = vstring_alloc(60); /* 60 for SHA-1 */ + VSTRING *peer_cert_fprint = vstring_alloc(60); /* 60 for SHA-1 */ VSTRING *peer_pkey_fprint = vstring_alloc(60); /* 60 for SHA-1 */ VSTRING *protocol = vstring_alloc(25); VSTRING *cipher_name = vstring_alloc(25); @@ -71,7 +71,7 @@ int tls_proxy_context_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp, ret = scan_fn(fp, flags | ATTR_FLAG_MORE, ATTR_TYPE_STR, MAIL_ATTR_PEER_CN, peer_CN, ATTR_TYPE_STR, MAIL_ATTR_ISSUER_CN, issuer_CN, - ATTR_TYPE_STR, MAIL_ATTR_PEER_FPT, peer_fingerprint, + ATTR_TYPE_STR, MAIL_ATTR_PEER_CERT_FPT, peer_cert_fprint, ATTR_TYPE_STR, MAIL_ATTR_PEER_PKEY_FPT, peer_pkey_fprint, ATTR_TYPE_INT, MAIL_ATTR_PEER_STATUS, &tls_context->peer_status, @@ -84,7 +84,7 @@ int tls_proxy_context_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp, ATTR_TYPE_END); tls_context->peer_CN = vstring_export(peer_CN); tls_context->issuer_CN = vstring_export(issuer_CN); - tls_context->peer_fingerprint = vstring_export(peer_fingerprint); + tls_context->peer_cert_fprint = vstring_export(peer_cert_fprint); tls_context->peer_pkey_fprint = vstring_export(peer_pkey_fprint); tls_context->protocol = vstring_export(protocol); tls_context->cipher_name = vstring_export(cipher_name); diff --git a/postfix/src/tls/tls_server.c b/postfix/src/tls/tls_server.c index 56e651fc5..37cfb8975 100644 --- a/postfix/src/tls/tls_server.c +++ b/postfix/src/tls/tls_server.c @@ -70,7 +70,7 @@ /* .IP TLScontext->issuer_CN /* Extracted CommonName of the issuer, or zero-length string /* when information could not be extracted. -/* .IP TLScontext->peer_fingerprint +/* .IP TLScontext->peer_cert_fprint /* Fingerprint of the certificate, or zero-length string when no peer /* certificate is available. /* .PP @@ -761,7 +761,7 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext) } TLScontext->peer_CN = tls_peer_CN(peer, TLScontext); TLScontext->issuer_CN = tls_issuer_CN(peer, TLScontext); - TLScontext->peer_fingerprint = tls_fingerprint(peer, TLScontext->mdalg); + TLScontext->peer_cert_fprint = tls_cert_fprint(peer, TLScontext->mdalg); TLScontext->peer_pkey_fprint = tls_pkey_fprint(peer, TLScontext->mdalg); if (TLScontext->log_mask & (TLS_LOG_VERBOSE | TLS_LOG_PEERCERT)) { @@ -769,14 +769,14 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext) ", pkey_fingerprint=%s", TLScontext->namaddr, TLScontext->peer_CN, TLScontext->issuer_CN, - TLScontext->peer_fingerprint, + TLScontext->peer_cert_fprint, TLScontext->peer_pkey_fprint); } X509_free(peer); } else { TLScontext->peer_CN = mystrdup(""); TLScontext->issuer_CN = mystrdup(""); - TLScontext->peer_fingerprint = mystrdup(""); + TLScontext->peer_cert_fprint = mystrdup(""); TLScontext->peer_pkey_fprint = mystrdup(""); } diff --git a/postfix/src/tls/tls_verify.c b/postfix/src/tls/tls_verify.c index 3977b155c..b1fe441ce 100644 --- a/postfix/src/tls/tls_verify.c +++ b/postfix/src/tls/tls_verify.c @@ -214,7 +214,7 @@ int tls_cert_match(TLS_SESS_STATE *TLScontext, int usage, X509 *cert, int de } certs = mixed ? tlsa->pkeys : tlsa->certs; if (certs != 0 && !matched) { - char *cert_dgst = tls_fingerprint(cert, tlsa->mdalg); + char *cert_dgst = tls_cert_fprint(cert, tlsa->mdalg); for (dgst = certs->argv; !matched && *dgst; ++dgst) if (strcasecmp(cert_dgst, *dgst) == 0)