From: Wietse Venema Date: Sat, 17 Nov 2018 05:00:00 +0000 (-0500) Subject: postfix-3.2.7-RC3 X-Git-Tag: v3.2.7-RC3^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0dca544c22d4437bfd8169443a17130ffff633fa;p=thirdparty%2Fpostfix.git postfix-3.2.7-RC3 --- diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 6a98ec87e..ec8d3b6d3 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -346,6 +346,7 @@ -TTLS_PKEYS -TTLS_PRNG_SEED_INFO -TTLS_PRNG_SRC +-TTLS_ROLE -TTLS_SCACHE -TTLS_SCACHE_ENTRY -TTLS_SERVER_INIT_PROPS @@ -353,6 +354,7 @@ -TTLS_SESS_STATE -TTLS_TICKET_KEY -TTLS_TLSA +-TTLS_USAGE -TTLS_VINFO -TTLScontext_t -TTOK822 diff --git a/postfix/HISTORY b/postfix/HISTORY index 78641566d..2228dc450 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -23110,7 +23110,23 @@ Apologies for any names omitted. proto/TLS_README.html, tls/tls.h, tls/tls_server.c, tls/tls_misc.c. +20181106 + + Bugfix (introduced: 3.0): smtpd_discard_ehlo_keywords could + not disable "SMTPUTF8". because the lookup table was using + "EHLO_MASK_SMTPUTF8" instead. File: global/ehlo_mask.c. + 20181110 Documentation: update documentation for Postfix versions that support disabling TLS 1.3. File: proto/postconf.proto. + +20181117 + + Improved logging of TLS 1.3 summary information, and improved + reporting of the same info in Received: message headers. + Viktor Dukhovni. Files: proto/FORWARD_SECRECY_README.html, + posttls-finger/posttls-finger.c, smtpd/smtpd.c, tls/tls.h, + tls/tls_client.c, tls/tls_misc.c, tls/tls_proxy.h, + tls/tls_proxy_context_print.c, tls/tls_proxy_context_scan.c, + tls/tls_server.c. diff --git a/postfix/README_FILES/FORWARD_SECRECY_README b/postfix/README_FILES/FORWARD_SECRECY_README index f2a88b8f4..921036e3f 100644 --- a/postfix/README_FILES/FORWARD_SECRECY_README +++ b/postfix/README_FILES/FORWARD_SECRECY_README @@ -294,7 +294,8 @@ verification status. * With "smtp_tls_loglevel = 1" and "smtpd_tls_loglevel = 1", the Postfix SMTP client and server will log TLS connection information to the maillog file. - The general logfile format is: + The general logfile format is shown below. With TLS 1.3 there may be + additional properties logged after the cipher name and bits. postfix/smtp[process-id]: Untrusted TLS connection established to host.example.com[192.168.0.2]:25: TLSv1 with cipher cipher-name @@ -307,7 +308,8 @@ verification status. * With "smtpd_tls_received_header = yes", the Postfix SMTP server will record TLS connection information in the Received: header in the form of comments (text inside parentheses). The general format depends on the - smtpd_tls_ask_ccert setting: + smtpd_tls_ask_ccert setting. With TLS 1.3 there may be additional + properties logged after the cipher name and bits. Received: from host.example.com (host.example.com [192.168.0.2]) (using TLSv1 with cipher cipher-name @@ -320,6 +322,47 @@ verification status. (actual-key-size/raw-key-size bits)) (No client certificate requested) + TLS 1.3 examples. Some of the new attributes may not appear when not + applicable or not available in older versions of the OpenSSL library. + + Received: from localhost (localhost [127.0.0.1]) + (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 + bits) + key-exchange X25519 server-signature RSA-PSS (2048 bits) + server-digest SHA256) + (No client certificate requested) + + Received: from localhost (localhost [127.0.0.1]) + (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 + bits) + key-exchange X25519 server-signature RSA-PSS (2048 bits) + server-digest SHA256 + client-signature ECDSA (P-256) client-digest SHA256) + (Client CN "example.org", Issuer "example.org" (not verified)) + + o The "key-exchange" attribute records the type of "Diffie-Hellman" group + used for key agreement. Possible values include "DHE", "ECDHE", + "X25519" and "X448". With "DHE", the bit size of the prime will be + reported in parentheses after the algorithm name, with "ECDHE", the + curve name. + + o The "server-signature" attribute shows the public key signature + algorithm used by the server. With "RSA-PSS", the bit size of the + modulus will be reported in parentheses. With "ECDSA", the curve name. + If, for example, the server has both an RSA and an ECDSA private key + and certificate, it will be possible to track which one was used for a + given connection. + + o The new "server-digest" attribute records the digest algorithm used by + the server to prepare handshake messages for signing. The Ed25519 and + Ed448 signature algorithms do not make use of such a digest, so no + "server-digest" will be shown for these signature algorithms. + + o When a client certificate is requested with "smtpd_tls_ask_ccert" and + the client uses a TLS client-certificate, the "client-signature" and + "client-digest" attributes will record the corresponding properties of + the client's TLS handshake signature. + The next sections will explain what cipher-name, key-size, and peer verification status information to expect. @@ -361,6 +404,51 @@ The actual key length and raw algorithm key length are generally the same with non-export ciphers, but may they differ for the legacy export ciphers where the actual key is artificially shortened. +Starting with TLS 1.3 the cipher name no longer contains enough information to +determine which forward-secrecy scheme was employed, but TLS 1.3 aallwwaayyss uses +forward-secrecy. On the client side, up-to-date Postfix releases log additional +information for TLS 1.3 connections, reporting the signature and key exchange +algorithms. Two examples below (the long single line messages are folded across +multiple lines for readability): + + postfix/smtp[process-id]: + Untrusted TLS connection established to 127.0.0.1[127.0.0.1]:25: + TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) + key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest + SHA256 + client-signature ECDSA (P-256) client-digest SHA256 + + postfix/smtp[process-id]: + Untrusted TLS connection established to 127.0.0.1[127.0.0.1]:25: + TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) + key-exchange ECDHE (P-256) server-signature ECDSA (P-256) server-digest + SHA256 + +In the above connections, the "key-exchange" value records the "Diffie-Hellman" +algorithm used for key agreement. The "server-signature" value records the +public key algoritm used by the server to sign the key exchange. The "server- +digest" value records any hash algorithm used to prepare the data for signing. +With "ED25519" and "ED448", no separate hash algorithm is used. + +Examples of Postfix SMTP server logging: + + postfix/smtpd[process-id]: + Untrusted TLS connection established from localhost[127.0.0.1]:25: + TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) + key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest + SHA256 + client-signature ECDSA (P-256) client-digest SHA256 + + postfix/smtpd[process-id]: + Anonymous TLS connection established from localhost[127.0.0.1]: + TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) + server-signature RSA-PSS (2048 bits) server-digest SHA256 + + postfix/smtpd[process-id]: + Anonymous TLS connection established from localhost[127.0.0.1]: + TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) + server-signature ED25519 + WWhhaatt ddoo ""AAnnoonnyymmoouuss"",, ""UUnnttrruusstteedd"",, eettcc.. iinn PPoossttffiixx llooggggiinngg mmeeaann?? The verification levels below are subject to man-in-the-middle attacks to diff --git a/postfix/html/FORWARD_SECRECY_README.html b/postfix/html/FORWARD_SECRECY_README.html index b18d892d5..641b38148 100644 --- a/postfix/html/FORWARD_SECRECY_README.html +++ b/postfix/html/FORWARD_SECRECY_README.html @@ -397,7 +397,9 @@ peer certificate or public-key verification status.

  • With "smtp_tls_loglevel = 1" and "smtpd_tls_loglevel = 1", the Postfix SMTP client and server will log TLS connection information -to the maillog file. The general logfile format is:

    +to the maillog file. The general logfile format is shown below. +With TLS 1.3 there may be additional properties logged after the +cipher name and bits.

    @@ -414,7 +416,8 @@ from host.example.com[192.168.0.2]: TLSv1 with cipher cipher-name
     
  • With "smtpd_tls_received_header = yes", the Postfix SMTP server will record TLS connection information in the Received: header in the form of comments (text inside parentheses). The general -format depends on the smtpd_tls_ask_ccert setting: +format depends on the smtpd_tls_ask_ccert setting. With TLS 1.3 there +may be additional properties logged after the cipher name and bits.

    @@ -430,6 +433,46 @@ Received: from host.example.com (host.example.com [192.168.0.2])
     
    +

    TLS 1.3 examples. Some of the new attributes may not appear when not +applicable or not available in older versions of the OpenSSL library.

    + +
    +
    +Received: from localhost (localhost [127.0.0.1])
    +        (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
    +         key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256)
    +        (No client certificate requested)
    +
    +Received: from localhost (localhost [127.0.0.1])
    +        (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
    +         key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
    +         client-signature ECDSA (P-256) client-digest SHA256)
    +        (Client CN "example.org", Issuer "example.org" (not verified))
    +
    +
    + +
      +
    • The "key-exchange" attribute records the type of "Diffie-Hellman" +group used for key agreement. Possible values include "DHE", "ECDHE", "X25519" +and "X448". With "DHE", the bit size of the prime will be reported in +parentheses after the algorithm name, with "ECDHE", the curve name.

      + +
    • The "server-signature" attribute shows the public key signature +algorithm used by the server. With "RSA-PSS", the bit size of the modulus will +be reported in parentheses. With "ECDSA", the curve name. If, for example, +the server has both an RSA and an ECDSA private key and certificate, it will be +possible to track which one was used for a given connection.

      + +
    • The new "server-digest" attribute records the digest algorithm used by +the server to prepare handshake messages for signing. The Ed25519 and Ed448 +signature algorithms do not make use of such a digest, so no "server-digest" +will be shown for these signature algorithms.

      + +
    • When a client certificate is requested with "smtpd_tls_ask_ccert" and +the client uses a TLS client-certificate, the "client-signature" and +"client-digest" attributes will record the corresponding properties of the +client's TLS handshake signature.

    +

    The next sections will explain what cipher-name, @@ -481,6 +524,58 @@ are generally the same with non-export ciphers, but may they differ for the legacy export ciphers where the actual key is artificially shortened.

    +

    Starting with TLS 1.3 the cipher name no longer contains enough +information to determine which forward-secrecy scheme was employed, +but TLS 1.3 always uses forward-secrecy. On the client side, +up-to-date Postfix releases log additional information for TLS 1.3 +connections, reporting the signature and key exchange algorithms. +Two examples below (the long single line messages are folded across +multiple lines for readability):

    + +
    +
    +postfix/smtp[process-id]:
    +  Untrusted TLS connection established to 127.0.0.1[127.0.0.1]:25:
    +  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
    +  key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
    +  client-signature ECDSA (P-256) client-digest SHA256
    +
    +postfix/smtp[process-id]:
    +  Untrusted TLS connection established to 127.0.0.1[127.0.0.1]:25:
    +  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
    +  key-exchange ECDHE (P-256) server-signature ECDSA (P-256) server-digest SHA256
    +
    +
    + +

    In the above connections, the "key-exchange" value records the +"Diffie-Hellman" algorithm used for key agreement. The "server-signature" value +records the public key algoritm used by the server to sign the key exchange. +The "server-digest" value records any hash algorithm used to prepare the data +for signing. With "ED25519" and "ED448", no separate hash algorithm is used. +

    + +

    Examples of Postfix SMTP server logging:

    + +
    +
    +postfix/smtpd[process-id]:
    +  Untrusted TLS connection established from localhost[127.0.0.1]:25:
    +  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
    +  key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
    +  client-signature ECDSA (P-256) client-digest SHA256
    +
    +postfix/smtpd[process-id]:
    +  Anonymous TLS connection established from localhost[127.0.0.1]:
    +  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
    +  server-signature RSA-PSS (2048 bits) server-digest SHA256
    +
    +postfix/smtpd[process-id]:
    +  Anonymous TLS connection established from localhost[127.0.0.1]:
    +  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
    +  server-signature ED25519
    +
    +
    +

    What do "Anonymous", "Untrusted", etc. in Postfix logging mean?

    diff --git a/postfix/proto/FORWARD_SECRECY_README.html b/postfix/proto/FORWARD_SECRECY_README.html index 62593d291..a755204c6 100644 --- a/postfix/proto/FORWARD_SECRECY_README.html +++ b/postfix/proto/FORWARD_SECRECY_README.html @@ -397,7 +397,9 @@ peer certificate or public-key verification status.

  • With "smtp_tls_loglevel = 1" and "smtpd_tls_loglevel = 1", the Postfix SMTP client and server will log TLS connection information -to the maillog file. The general logfile format is:

    +to the maillog file. The general logfile format is shown below. +With TLS 1.3 there may be additional properties logged after the +cipher name and bits.

    @@ -414,7 +416,8 @@ from host.example.com[192.168.0.2]: TLSv1 with cipher cipher-name
     
  • With "smtpd_tls_received_header = yes", the Postfix SMTP server will record TLS connection information in the Received: header in the form of comments (text inside parentheses). The general -format depends on the smtpd_tls_ask_ccert setting: +format depends on the smtpd_tls_ask_ccert setting. With TLS 1.3 there +may be additional properties logged after the cipher name and bits.

    @@ -430,6 +433,46 @@ Received: from host.example.com (host.example.com [192.168.0.2])
     
    +

    TLS 1.3 examples. Some of the new attributes may not appear when not +applicable or not available in older versions of the OpenSSL library.

    + +
    +
    +Received: from localhost (localhost [127.0.0.1])
    +        (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
    +         key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256)
    +        (No client certificate requested)
    +
    +Received: from localhost (localhost [127.0.0.1])
    +        (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
    +         key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
    +         client-signature ECDSA (P-256) client-digest SHA256)
    +        (Client CN "example.org", Issuer "example.org" (not verified))
    +
    +
    + +
      +
    • The "key-exchange" attribute records the type of "Diffie-Hellman" +group used for key agreement. Possible values include "DHE", "ECDHE", "X25519" +and "X448". With "DHE", the bit size of the prime will be reported in +parentheses after the algorithm name, with "ECDHE", the curve name.

      + +
    • The "server-signature" attribute shows the public key signature +algorithm used by the server. With "RSA-PSS", the bit size of the modulus will +be reported in parentheses. With "ECDSA", the curve name. If, for example, +the server has both an RSA and an ECDSA private key and certificate, it will be +possible to track which one was used for a given connection.

      + +
    • The new "server-digest" attribute records the digest algorithm used by +the server to prepare handshake messages for signing. The Ed25519 and Ed448 +signature algorithms do not make use of such a digest, so no "server-digest" +will be shown for these signature algorithms.

      + +
    • When a client certificate is requested with "smtpd_tls_ask_ccert" and +the client uses a TLS client-certificate, the "client-signature" and +"client-digest" attributes will record the corresponding properties of the +client's TLS handshake signature.

    +

    The next sections will explain what cipher-name, @@ -481,6 +524,58 @@ are generally the same with non-export ciphers, but may they differ for the legacy export ciphers where the actual key is artificially shortened.

    +

    Starting with TLS 1.3 the cipher name no longer contains enough +information to determine which forward-secrecy scheme was employed, +but TLS 1.3 always uses forward-secrecy. On the client side, +up-to-date Postfix releases log additional information for TLS 1.3 +connections, reporting the signature and key exchange algorithms. +Two examples below (the long single line messages are folded across +multiple lines for readability):

    + +
    +
    +postfix/smtp[process-id]:
    +  Untrusted TLS connection established to 127.0.0.1[127.0.0.1]:25:
    +  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
    +  key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
    +  client-signature ECDSA (P-256) client-digest SHA256
    +
    +postfix/smtp[process-id]:
    +  Untrusted TLS connection established to 127.0.0.1[127.0.0.1]:25:
    +  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
    +  key-exchange ECDHE (P-256) server-signature ECDSA (P-256) server-digest SHA256
    +
    +
    + +

    In the above connections, the "key-exchange" value records the +"Diffie-Hellman" algorithm used for key agreement. The "server-signature" value +records the public key algoritm used by the server to sign the key exchange. +The "server-digest" value records any hash algorithm used to prepare the data +for signing. With "ED25519" and "ED448", no separate hash algorithm is used. +

    + +

    Examples of Postfix SMTP server logging:

    + +
    +
    +postfix/smtpd[process-id]:
    +  Untrusted TLS connection established from localhost[127.0.0.1]:25:
    +  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
    +  key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
    +  client-signature ECDSA (P-256) client-digest SHA256
    +
    +postfix/smtpd[process-id]:
    +  Anonymous TLS connection established from localhost[127.0.0.1]:
    +  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
    +  server-signature RSA-PSS (2048 bits) server-digest SHA256
    +
    +postfix/smtpd[process-id]:
    +  Anonymous TLS connection established from localhost[127.0.0.1]:
    +  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
    +  server-signature ED25519
    +
    +
    +

    What do "Anonymous", "Untrusted", etc. in Postfix logging mean?

    diff --git a/postfix/src/global/ehlo_mask.c b/postfix/src/global/ehlo_mask.c index 1671beb3e..d5cb67b0a 100644 --- a/postfix/src/global/ehlo_mask.c +++ b/postfix/src/global/ehlo_mask.c @@ -77,6 +77,7 @@ static const NAME_MASK ehlo_mask_table[] = { "ENHANCEDSTATUSCODES", EHLO_MASK_ENHANCEDSTATUSCODES, "DSN", EHLO_MASK_DSN, "EHLO_MASK_SMTPUTF8", EHLO_MASK_SMTPUTF8, + "SMTPUTF8", EHLO_MASK_SMTPUTF8, "SILENT-DISCARD", EHLO_MASK_SILENT, /* XXX In-band signaling */ 0, }; diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h index 363bc71ec..3b18333ab 100644 --- a/postfix/src/global/mail_proto.h +++ b/postfix/src/global/mail_proto.h @@ -293,6 +293,18 @@ extern char *mail_pathname(const char *, const char *); #define MAIL_ATTR_CIPHER_NAME "cipher_name" #define MAIL_ATTR_CIPHER_USEBITS "cipher_usebits" #define MAIL_ATTR_CIPHER_ALGBITS "cipher_algbits" +#define MAIL_ATTR_KEX_NAME "key_exchange" +#define MAIL_ATTR_KEX_CURVE "key_exchange_curve" +#define MAIL_ATTR_KEX_BITS "key_exchange_bits" +#define MAIL_ATTR_CLNT_SIG_NAME "clnt_signature" +#define MAIL_ATTR_CLNT_SIG_CURVE "clnt_signature_curve" +#define MAIL_ATTR_CLNT_SIG_BITS "clnt_signature_bits" +#define MAIL_ATTR_CLNT_SIG_DGST "clnt_signature_digest" +#define MAIL_ATTR_SRVR_SIG_NAME "srvr_signature" +#define MAIL_ATTR_SRVR_SIG_CURVE "srvr_signature_curve" +#define MAIL_ATTR_SRVR_SIG_BITS "srvr_signature_bits" +#define MAIL_ATTR_SRVR_SIG_DGST "srvr_signature_digest" +#define MAIL_ATTR_NAMADDR "namaddr" #define MAIL_ATTR_SERVER_ID "server_id" /* diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 4e452e390..2cbd9eaa5 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,8 +20,8 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20181110" -#define MAIL_VERSION_NUMBER "3.2.7-RC2" +#define MAIL_RELEASE_DATE "20181117" +#define MAIL_VERSION_NUMBER "3.2.7-RC3" #ifdef SNAPSHOT #define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 40d49f623..cd4600936 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -3240,12 +3240,70 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) #ifdef USE_TLS if (var_smtpd_tls_received_header && state->tls_context) { - out_fprintf(out_stream, REC_TYPE_NORM, - "\t(using %s with cipher %s (%d/%d bits))", - state->tls_context->protocol, - state->tls_context->cipher_name, - state->tls_context->cipher_usebits, - state->tls_context->cipher_algbits); + int cont = 0; + + vstring_sprintf(state->buffer, + "\t(using %s with cipher %s (%d/%d bits)", + state->tls_context->protocol, + state->tls_context->cipher_name, + state->tls_context->cipher_usebits, + state->tls_context->cipher_algbits); + if (state->tls_context->kex_name && *state->tls_context->kex_name) { + out_record(out_stream, REC_TYPE_NORM, STR(state->buffer), + LEN(state->buffer)); + vstring_sprintf(state->buffer, "\t key-exchange %s", + state->tls_context->kex_name); + if (state->tls_context->kex_curve + && *state->tls_context->kex_curve) + vstring_sprintf_append(state->buffer, " (%s)", + state->tls_context->kex_curve); + else if (state->tls_context->kex_bits > 0) + vstring_sprintf_append(state->buffer, " (%d bits)", + state->tls_context->kex_bits); + cont = 1; + } + if (state->tls_context->srvr_sig_name + && *state->tls_context->srvr_sig_name) { + if (cont) { + vstring_sprintf_append(state->buffer, " server-signature %s", + state->tls_context->srvr_sig_name); + } else { + out_record(out_stream, REC_TYPE_NORM, STR(state->buffer), + LEN(state->buffer)); + vstring_sprintf(state->buffer, "\t server-signature %s", + state->tls_context->srvr_sig_name); + } + if (state->tls_context->srvr_sig_curve + && *state->tls_context->srvr_sig_curve) + vstring_sprintf_append(state->buffer, " (%s)", + state->tls_context->srvr_sig_curve); + else if (state->tls_context->srvr_sig_bits > 0) + vstring_sprintf_append(state->buffer, " (%d bits)", + state->tls_context->srvr_sig_bits); + if (state->tls_context->srvr_sig_dgst + && *state->tls_context->srvr_sig_dgst) + vstring_sprintf_append(state->buffer, " server-digest %s", + state->tls_context->srvr_sig_dgst); + } + if (state->tls_context->clnt_sig_name + && *state->tls_context->clnt_sig_name) { + out_record(out_stream, REC_TYPE_NORM, STR(state->buffer), + LEN(state->buffer)); + vstring_sprintf(state->buffer, "\t client-signature %s", + state->tls_context->clnt_sig_name); + if (state->tls_context->clnt_sig_curve + && *state->tls_context->clnt_sig_curve) + vstring_sprintf_append(state->buffer, " (%s)", + state->tls_context->clnt_sig_curve); + else if (state->tls_context->clnt_sig_bits > 0) + vstring_sprintf_append(state->buffer, " (%d bits)", + state->tls_context->clnt_sig_bits); + if (state->tls_context->clnt_sig_dgst + && *state->tls_context->clnt_sig_dgst) + vstring_sprintf_append(state->buffer, " client-digest %s", + state->tls_context->clnt_sig_dgst); + } + out_fprintf(out_stream, REC_TYPE_NORM, "%s)", STR(state->buffer)); if (TLS_CERT_IS_PRESENT(state->tls_context)) { peer_CN = VSTRING_STRDUP(state->tls_context->peer_CN); comment_sanitize(peer_CN); diff --git a/postfix/src/tls/tls.h b/postfix/src/tls/tls.h index dfd2cbc75..2cd1b5b96 100644 --- a/postfix/src/tls/tls.h +++ b/postfix/src/tls/tls.h @@ -112,6 +112,22 @@ extern const char *str_tls_level(int); /* Backwards compatibility with OpenSSL < 1.1.1 */ #if OPENSSL_VERSION_NUMBER < 0x1010100fUL #define SSL_CTX_set_num_tickets(ctx, num) ((void)0) +#endif + + /*- + * Backwards compatibility with OpenSSL < 1.1.1a. + * + * In OpenSSL 1.1.1a the client-only interface SSL_get_server_tmp_key() was + * updated to work on both the client and the server, and was renamed to + * SSL_get_peer_tmp_key(), with the original name left behind as an alias. We + * use the new name when available. + */ +#if OPENSSL_VERSION_NUMBER < 0x1010101fUL +#undef SSL_get_signature_nid +#define SSL_get_signature_nid(ssl, pnid) (NID_undef) +#define tls_get_peer_dh_pubkey SSL_get_server_tmp_key +#else +#define tls_get_peer_dh_pubkey SSL_get_peer_tmp_key #endif /* SSL_CIPHER_get_name() got constified in 0.9.7g */ @@ -140,6 +156,17 @@ extern const char *str_tls_level(int); */ #include + /* + * TLS role, presently for logging. + */ +typedef enum { + TLS_ROLE_CLIENT, TLS_ROLE_SERVER, +} TLS_ROLE; + +typedef enum { + TLS_USAGE_NEW, TLS_USAGE_USED, +} TLS_USAGE; + /* * Names of valid tlsmgr(8) session caches. */ @@ -239,6 +266,17 @@ typedef struct { const char *cipher_name; int cipher_usebits; int cipher_algbits; + const char *kex_name; /* shared key-exchange algorithm */ + const char *kex_curve; /* shared key-exchange ECDHE curve */ + int kex_bits; /* shared FFDHE key exchange bits */ + const char *clnt_sig_name; /* client's signature key algorithm */ + const char *clnt_sig_curve; /* client's ECDSA curve name */ + int clnt_sig_bits; /* client's RSA signature key bits */ + const char *clnt_sig_dgst; /* client's signature digest */ + const char *srvr_sig_name; /* server's signature key algorithm */ + const char *srvr_sig_curve; /* server's ECDSA curve name */ + int srvr_sig_bits; /* server's RSA signature key bits */ + const char *srvr_sig_dgst; /* server's signature digest */ /* Private. */ SSL *con; char *cache_type; /* tlsmgr(8) cache type if enabled */ @@ -434,7 +472,12 @@ extern const NAME_CODE tls_cipher_grade_table[]; extern const char *tls_set_ciphers(TLS_APPL_STATE *, const char *, const char *, const char *); -#endif + /* + * Populate TLS context with TLS 1.3-related signature parameters. + */ +extern void tls_get_signature_params(TLS_SESS_STATE *); + +#endif /* TLS_INTERNAL */ /* * tls_client.c @@ -562,6 +605,7 @@ extern void tls_session_stop(TLS_APPL_STATE *, VSTREAM *, int, int, TLS_SESS_STA extern const char *tls_compile_version(void); extern const char *tls_run_version(void); extern const char **tls_pkey_algorithms(void); +extern void tls_log_summary(TLS_ROLE, TLS_USAGE, TLS_SESS_STATE *); #ifdef TLS_INTERNAL diff --git a/postfix/src/tls/tls_client.c b/postfix/src/tls/tls_client.c index bbe18f905..6bc1c3acd 100644 --- a/postfix/src/tls/tls_client.c +++ b/postfix/src/tls/tls_client.c @@ -1140,16 +1140,12 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) TLScontext->peer_status |= TLS_CERT_FLAG_SECURED; /* - * All the key facts in a single log entry. + * With the handshake done, extract TLS 1.3 signature metadata. */ + tls_get_signature_params(TLScontext); + if (log_mask & TLS_LOG_SUMMARY) - msg_info("%s TLS connection established to %s: %s with cipher %s " - "(%d/%d bits)", - !TLS_CERT_IS_PRESENT(TLScontext) ? "Anonymous" : - TLS_CERT_IS_SECURED(TLScontext) ? "Verified" : - TLS_CERT_IS_TRUSTED(TLScontext) ? "Trusted" : "Untrusted", - props->namaddr, TLScontext->protocol, TLScontext->cipher_name, - TLScontext->cipher_usebits, TLScontext->cipher_algbits); + tls_log_summary(TLS_ROLE_CLIENT, TLS_USAGE_NEW, TLScontext); tls_int_seed(); diff --git a/postfix/src/tls/tls_misc.c b/postfix/src/tls/tls_misc.c index 351f576cc..9460d9fd6 100644 --- a/postfix/src/tls/tls_misc.c +++ b/postfix/src/tls/tls_misc.c @@ -4,6 +4,25 @@ /* SUMMARY /* miscellaneous TLS support routines /* SYNOPSIS +/* .SH Public functions +/* .nf +/* .na +/* #include +/* +/* void tls_log_summary(role, usage, TLScontext) +/* TLS_ROLE role; +/* TLS_USAGE usage; +/* TLS_SESS_STATE *TLScontext; +/* +/* const char *tls_compile_version(void) +/* +/* const char *tls_run_version(void) +/* +/* const char **tls_pkey_algorithms(void) +/* +/* .SH Internal functions +/* .nf +/* .na /* #define TLS_INTERNAL /* #include /* @@ -62,6 +81,9 @@ /* int grade; /* const char *exclusions; /* +/* void tls_get_signature_params(TLScontext) +/* TLS_SESS_STATE *TLScontext; +/* /* void tls_print_errors() /* /* void tls_info_callback(ssl, where, ret) @@ -87,15 +109,24 @@ /* /* int tls_validate_digest(dgst) /* const char *dgst; +/* DESCRIPTION +/* This module implements public and internal routines that +/* support the TLS client and server. /* -/* const char *tls_compile_version(void) +/* tls_log_summary() logs a summary of a completed TLS connection. +/* The "role" argument must be TLS_ROLE_CLIENT for outgoing client +/* connections, or TLS_ROLE_SERVER for incoming server connections, +/* and the "usage" must be TLS_USAGE_NEW or TLS_USAGE_USED. /* -/* const char *tls_run_version(void) +/* tls_compile_version() returns a text string description of +/* the compile-time TLS library. /* -/* const char **tls_pkey_algorithms(void) -/* DESCRIPTION -/* This module implements routines that support the TLS client -/* and server internals. +/* tls_run_version() is just tls_compile_version() but with the runtime +/* version instead of the compile-time version. +/* +/* tls_pkey_algorithms() returns a pointer to null-terminated +/* array of string constants with the names of the supported +/* public-key algorithms. /* /* tls_alloc_app_context() creates an application context that /* holds the SSL context for the application and related cached state. @@ -143,6 +174,12 @@ /* When the input is invalid, tls_set_ciphers() logs a warning with /* the specified context, and returns a null pointer result. /* +/* tls_get_signature_params() updates the "TLScontext" with handshake +/* signature parameters pertaining to TLS 1.3, where the ciphersuite +/* no longer describes the asymmetric algorithms employed in the +/* handshake, which are negotiated separately. This function +/* has no effect for TLS 1.2 and earlier. +/* /* tls_print_errors() queries the OpenSSL error stack, /* logs the error messages, and clears the error stack. /* @@ -163,16 +200,6 @@ /* /* tls_validate_digest() returns non-zero if the named digest /* is usable and zero otherwise. -/* -/* tls_compile_version() returns a text string description of -/* the compile-time TLS library. -/* -/* tls_run_version() is just tls_compile_version() but with the runtime -/* version instead of the compile-time version. -/* -/* tls_pkey_algorithms() returns a pointer to null-terminated -/* array of string constants with the names of the supported -/* public-key algorithms. /* LICENSE /* .ad /* .fi @@ -366,11 +393,11 @@ static const LONG_NAME_MASK ssl_bug_tweaks[] = { /* * XXX: New with OpenSSL 1.1.1, this is turned on implicitly in * SSL_CTX_new() and is not included in SSL_OP_ALL. Allowing users to - * disable this would thus a code change that would clearing bug - * work-around bits in SSL_CTX, after setting SSL_OP_ALL. Since this is - * presumably required for TLS 1.3 on today's Internet, the code change - * will be done separately later. For now this implicit bug work-around - * cannot be disabled via supported Postfix mechanisms. + * disable this would thus be a code change that would require clearing + * bug work-around bits in SSL_CTX, after setting SSL_OP_ALL. Since this + * is presumably required for TLS 1.3 on today's Internet, the code + * change will be done separately later. For now this implicit bug + * work-around cannot be disabled via supported Postfix mechanisms. */ #ifndef SSL_OP_ENABLE_MIDDLEBOX_COMPAT #define SSL_OP_ENABLE_MIDDLEBOX_COMPAT 0 @@ -826,6 +853,224 @@ const char *tls_set_ciphers(TLS_APPL_STATE *app_ctx, const char *context, return (app_ctx->cipher_list = mystrdup(new_list)); } +/* tls_get_signature_params - TLS 1.3 signature details */ + +void tls_get_signature_params(TLS_SESS_STATE *TLScontext) +{ +#if OPENSSL_VERSION_NUMBER >= 0x1010100fUL && defined(TLS1_3_VERSION) + const char *kex_name = 0; + const char *kex_curve = 0; + const char *locl_sig_name = 0; + const char *locl_sig_curve = 0; + const char *locl_sig_dgst = 0; + const char *peer_sig_name = 0; + const char *peer_sig_curve = 0; + const char *peer_sig_dgst = 0; + int nid; + int got_kex_key; + SSL *ssl = TLScontext->con; + int srvr = SSL_is_server(ssl); + X509 *cert; + EVP_PKEY *pkey = 0; + +#ifndef OPENSSL_NO_EC + EC_KEY *eckey; + +#endif + +#define SIG_PROP(c, s, p) (*((s) ? &c->srvr_sig_##p : &c->clnt_sig_##p)) + + if (SSL_version(ssl) < TLS1_3_VERSION) + return; + + if (tls_get_peer_dh_pubkey(ssl, &pkey)) { + switch (nid = EVP_PKEY_id(pkey)) { + default: + kex_name = OBJ_nid2sn(EVP_PKEY_type(nid)); + break; + + case EVP_PKEY_DH: + kex_name = "DHE"; + TLScontext->kex_bits = EVP_PKEY_bits(pkey); + break; + +#ifndef OPENSSL_NO_EC + case EVP_PKEY_EC: + kex_name = "ECDHE"; + eckey = EVP_PKEY_get0_EC_KEY(pkey); + nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)); + kex_curve = EC_curve_nid2nist(nid); + if (!kex_curve) + kex_curve = OBJ_nid2sn(nid); + break; +#endif + } + EVP_PKEY_free(pkey); + } + + /* + * On the client end, the certificate may be preset, but not used, so we + * check via SSL_get_signature_nid(). This means that local signature + * data on clients requires at least 1.1.1a. + */ + if (srvr || SSL_get_signature_nid(ssl, &nid)) + cert = SSL_get_certificate(ssl); + else + cert = 0; + + /* Signature algorithms for the local end of the connection */ + if (cert) { + pkey = X509_get0_pubkey(cert); + + /* + * Override the built-in name for the "ECDSA" algorithms OID, with + * the more familiar name. For "RSA" keys report "RSA-PSS", which + * must be used with TLS 1.3. + */ + if ((nid = EVP_PKEY_type(EVP_PKEY_id(pkey))) != NID_undef) { + switch (nid) { + default: + locl_sig_name = OBJ_nid2sn(nid); + break; + + case EVP_PKEY_RSA: + /* For RSA, TLS 1.3 mandates PSS signatures */ + locl_sig_name = "RSA-PSS"; + SIG_PROP(TLScontext, srvr, bits) = EVP_PKEY_bits(pkey); + break; + +#ifndef OPENSSL_NO_EC + case EVP_PKEY_EC: + locl_sig_name = "ECDSA"; + eckey = EVP_PKEY_get0_EC_KEY(pkey); + nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)); + locl_sig_curve = EC_curve_nid2nist(nid); + if (!locl_sig_curve) + locl_sig_curve = OBJ_nid2sn(nid); + break; +#endif + } + } + + /* + * With Ed25519 and Ed448 there is no pre-signature digest, but the + * accessor does not fail, rather we get NID_undef. + */ + if (SSL_get_signature_nid(ssl, &nid) && nid != NID_undef) + locl_sig_dgst = OBJ_nid2sn(nid); + } + /* Signature algorithms for the peer end of the connection */ + if ((cert = SSL_get_peer_certificate(ssl)) != 0) { + pkey = X509_get0_pubkey(cert); + + /* + * Override the built-in name for the "ECDSA" algorithms OID, with + * the more familiar name. For "RSA" keys report "RSA-PSS", which + * must be used with TLS 1.3. + */ + if ((nid = EVP_PKEY_type(EVP_PKEY_id(pkey))) != NID_undef) { + switch (nid) { + default: + peer_sig_name = OBJ_nid2sn(nid); + break; + + case EVP_PKEY_RSA: + /* For RSA, TLS 1.3 mandates PSS signatures */ + peer_sig_name = "RSA-PSS"; + SIG_PROP(TLScontext, !srvr, bits) = EVP_PKEY_bits(pkey); + break; + +#ifndef OPENSSL_NO_EC + case EVP_PKEY_EC: + peer_sig_name = "ECDSA"; + eckey = EVP_PKEY_get0_EC_KEY(pkey); + nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)); + peer_sig_curve = EC_curve_nid2nist(nid); + if (!peer_sig_curve) + peer_sig_curve = OBJ_nid2sn(nid); + break; +#endif + } + } + + /* + * With Ed25519 and Ed448 there is no pre-signature digest, but the + * accessor does not fail, rather we get NID_undef. + */ + if (SSL_get_peer_signature_nid(ssl, &nid) && nid != NID_undef) + peer_sig_dgst = OBJ_nid2sn(nid); + } + if (kex_name) { + TLScontext->kex_name = mystrdup(kex_name); + if (kex_curve) + TLScontext->kex_curve = mystrdup(kex_curve); + } + if (locl_sig_name) { + SIG_PROP(TLScontext, srvr, name) = mystrdup(locl_sig_name); + if (locl_sig_curve) + SIG_PROP(TLScontext, srvr, curve) = mystrdup(locl_sig_curve); + if (locl_sig_dgst) + SIG_PROP(TLScontext, srvr, dgst) = mystrdup(locl_sig_dgst); + } + if (peer_sig_name) { + SIG_PROP(TLScontext, !srvr, name) = mystrdup(peer_sig_name); + if (peer_sig_curve) + SIG_PROP(TLScontext, !srvr, curve) = mystrdup(peer_sig_curve); + if (peer_sig_dgst) + SIG_PROP(TLScontext, !srvr, dgst) = mystrdup(peer_sig_dgst); + } +#endif /* OPENSSL_VERSION_NUMBER ... */ +} + +/* tls_log_summary - TLS loglevel 1 one-liner, embellished with TLS 1.3 details */ + +void tls_log_summary(TLS_ROLE role, TLS_USAGE usage, TLS_SESS_STATE *ctx) +{ + VSTRING *msg = vstring_alloc(100); + const char *direction = (role == TLS_ROLE_CLIENT) ? "to" : "from"; + + vstring_sprintf(msg, "%s TLS connection %s %s %s: %s" + " with cipher %s (%d/%d bits)", + !TLS_CERT_IS_PRESENT(ctx) ? "Anonymous" : + TLS_CERT_IS_SECURED(ctx) ? "Verified" : + TLS_CERT_IS_TRUSTED(ctx) ? "Trusted" : "Untrusted", + usage == TLS_USAGE_NEW ? "established" : "reused", + direction, ctx->namaddr, ctx->protocol, ctx->cipher_name, + ctx->cipher_usebits, ctx->cipher_algbits); + + if (ctx->kex_name && *ctx->kex_name) { + vstring_sprintf_append(msg, " key-exchange %s", ctx->kex_name); + if (ctx->kex_curve && *ctx->kex_curve) + vstring_sprintf_append(msg, " (%s)", ctx->kex_curve); + else if (ctx->kex_bits > 0) + vstring_sprintf_append(msg, " (%d bits)", ctx->kex_bits); + } + if (ctx->srvr_sig_name && *ctx->srvr_sig_name) { + vstring_sprintf_append(msg, " server-signature %s", + ctx->srvr_sig_name); + if (ctx->srvr_sig_curve && *ctx->srvr_sig_curve) + vstring_sprintf_append(msg, " (%s)", ctx->srvr_sig_curve); + else if (ctx->srvr_sig_bits > 0) + vstring_sprintf_append(msg, " (%d bits)", ctx->srvr_sig_bits); + if (ctx->srvr_sig_dgst && *ctx->srvr_sig_dgst) + vstring_sprintf_append(msg, " server-digest %s", + ctx->srvr_sig_dgst); + } + if (ctx->clnt_sig_name && *ctx->clnt_sig_name) { + vstring_sprintf_append(msg, " client-signature %s", + ctx->clnt_sig_name); + if (ctx->clnt_sig_curve && *ctx->clnt_sig_curve) + vstring_sprintf_append(msg, " (%s)", ctx->clnt_sig_curve); + else if (ctx->clnt_sig_bits > 0) + vstring_sprintf_append(msg, " (%d bits)", ctx->clnt_sig_bits); + if (ctx->clnt_sig_dgst && *ctx->clnt_sig_dgst) + vstring_sprintf_append(msg, " client-digest %s", + ctx->clnt_sig_dgst); + } + msg_info("%s", vstring_str(msg)); + vstring_free(msg); +} + /* tls_alloc_app_context - allocate TLS application context */ TLS_APPL_STATE *tls_alloc_app_context(SSL_CTX *ssl_ctx, int log_mask) @@ -893,6 +1138,14 @@ TLS_SESS_STATE *tls_alloc_sess_context(int log_mask, const char *namaddr) TLScontext->peer_pkey_fprint = 0; TLScontext->protocol = 0; TLScontext->cipher_name = 0; + TLScontext->kex_name = 0; + TLScontext->kex_curve = 0; + TLScontext->clnt_sig_name = 0; + TLScontext->clnt_sig_curve = 0; + TLScontext->clnt_sig_dgst = 0; + TLScontext->srvr_sig_name = 0; + TLScontext->srvr_sig_curve = 0; + TLScontext->srvr_sig_dgst = 0; TLScontext->log_mask = log_mask; TLScontext->namaddr = lowercase(mystrdup(namaddr)); TLScontext->mdalg = 0; /* Alias for props->mdalg */ diff --git a/postfix/src/tls/tls_proxy_clnt.c b/postfix/src/tls/tls_proxy_clnt.c index ea10fbda4..62f37992c 100644 --- a/postfix/src/tls/tls_proxy_clnt.c +++ b/postfix/src/tls/tls_proxy_clnt.c @@ -239,6 +239,24 @@ void tls_proxy_context_free(TLS_SESS_STATE *tls_context) myfree((void *) tls_context->protocol); if (tls_context->cipher_name) myfree((void *) tls_context->cipher_name); + if (tls_context->kex_name) + myfree((void *) tls_context->kex_name); + if (tls_context->kex_curve) + myfree((void *) tls_context->kex_curve); + if (tls_context->clnt_sig_name) + myfree((void *) tls_context->clnt_sig_name); + if (tls_context->clnt_sig_curve) + myfree((void *) tls_context->clnt_sig_curve); + if (tls_context->clnt_sig_dgst) + myfree((void *) tls_context->clnt_sig_dgst); + if (tls_context->srvr_sig_name) + myfree((void *) tls_context->srvr_sig_name); + if (tls_context->srvr_sig_curve) + myfree((void *) tls_context->srvr_sig_curve); + if (tls_context->srvr_sig_dgst) + myfree((void *) tls_context->srvr_sig_dgst); + if (tls_context->namaddr) + myfree((void *) tls_context->namaddr); myfree((void *) tls_context); } diff --git a/postfix/src/tls/tls_proxy_print.c b/postfix/src/tls/tls_proxy_print.c index e30e8be88..ed08ed8b1 100644 --- a/postfix/src/tls/tls_proxy_print.c +++ b/postfix/src/tls/tls_proxy_print.c @@ -79,6 +79,30 @@ int tls_proxy_context_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp, tp->cipher_usebits), SEND_ATTR_INT(MAIL_ATTR_CIPHER_ALGBITS, tp->cipher_algbits), + SEND_ATTR_STR(MAIL_ATTR_KEX_NAME, + STRING_OR_EMPTY(tp->kex_name)), + SEND_ATTR_STR(MAIL_ATTR_KEX_CURVE, + STRING_OR_EMPTY(tp->kex_curve)), + SEND_ATTR_INT(MAIL_ATTR_KEX_BITS, + tp->kex_bits), + SEND_ATTR_STR(MAIL_ATTR_CLNT_SIG_NAME, + STRING_OR_EMPTY(tp->clnt_sig_name)), + SEND_ATTR_STR(MAIL_ATTR_CLNT_SIG_CURVE, + STRING_OR_EMPTY(tp->clnt_sig_curve)), + SEND_ATTR_INT(MAIL_ATTR_CLNT_SIG_BITS, + tp->clnt_sig_bits), + SEND_ATTR_STR(MAIL_ATTR_CLNT_SIG_DGST, + STRING_OR_EMPTY(tp->clnt_sig_dgst)), + SEND_ATTR_STR(MAIL_ATTR_SRVR_SIG_NAME, + STRING_OR_EMPTY(tp->srvr_sig_name)), + SEND_ATTR_STR(MAIL_ATTR_SRVR_SIG_CURVE, + STRING_OR_EMPTY(tp->srvr_sig_curve)), + SEND_ATTR_INT(MAIL_ATTR_SRVR_SIG_BITS, + tp->srvr_sig_bits), + SEND_ATTR_STR(MAIL_ATTR_SRVR_SIG_DGST, + STRING_OR_EMPTY(tp->srvr_sig_dgst)), + SEND_ATTR_STR(MAIL_ATTR_NAMADDR, + STRING_OR_EMPTY(tp->namaddr)), ATTR_TYPE_END); return (ret); } diff --git a/postfix/src/tls/tls_proxy_scan.c b/postfix/src/tls/tls_proxy_scan.c index 29a0cd9f9..256781fa8 100644 --- a/postfix/src/tls/tls_proxy_scan.c +++ b/postfix/src/tls/tls_proxy_scan.c @@ -63,6 +63,15 @@ int tls_proxy_context_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp, VSTRING *peer_pkey_fprint = vstring_alloc(60); /* 60 for SHA-1 */ VSTRING *protocol = vstring_alloc(25); VSTRING *cipher_name = vstring_alloc(25); + VSTRING *kex_name = vstring_alloc(25); + VSTRING *kex_curve = vstring_alloc(25); + VSTRING *clnt_sig_name = vstring_alloc(25); + VSTRING *clnt_sig_curve = vstring_alloc(25); + VSTRING *clnt_sig_dgst = vstring_alloc(25); + VSTRING *srvr_sig_name = vstring_alloc(25); + VSTRING *srvr_sig_curve = vstring_alloc(25); + VSTRING *srvr_sig_dgst = vstring_alloc(25); + VSTRING *namaddr = vstring_alloc(100); /* * Note: memset() is not a portable way to initialize non-integer types. @@ -81,6 +90,18 @@ int tls_proxy_context_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp, &tls_context->cipher_usebits), RECV_ATTR_INT(MAIL_ATTR_CIPHER_ALGBITS, &tls_context->cipher_algbits), + RECV_ATTR_STR(MAIL_ATTR_KEX_NAME, kex_name), + RECV_ATTR_STR(MAIL_ATTR_KEX_CURVE, kex_curve), + RECV_ATTR_INT(MAIL_ATTR_KEX_BITS, &tls_context->kex_bits), + RECV_ATTR_STR(MAIL_ATTR_CLNT_SIG_NAME, clnt_sig_name), + RECV_ATTR_STR(MAIL_ATTR_CLNT_SIG_CURVE, clnt_sig_curve), + RECV_ATTR_INT(MAIL_ATTR_CLNT_SIG_BITS, &tls_context->clnt_sig_bits), + RECV_ATTR_STR(MAIL_ATTR_CLNT_SIG_DGST, clnt_sig_dgst), + RECV_ATTR_STR(MAIL_ATTR_SRVR_SIG_NAME, srvr_sig_name), + RECV_ATTR_STR(MAIL_ATTR_SRVR_SIG_CURVE, srvr_sig_curve), + RECV_ATTR_INT(MAIL_ATTR_SRVR_SIG_BITS, &tls_context->srvr_sig_bits), + RECV_ATTR_STR(MAIL_ATTR_SRVR_SIG_DGST, srvr_sig_dgst), + RECV_ATTR_STR(MAIL_ATTR_NAMADDR, namaddr), ATTR_TYPE_END); tls_context->peer_CN = vstring_export(peer_CN); tls_context->issuer_CN = vstring_export(issuer_CN); @@ -88,7 +109,16 @@ int tls_proxy_context_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp, tls_context->peer_pkey_fprint = vstring_export(peer_pkey_fprint); tls_context->protocol = vstring_export(protocol); tls_context->cipher_name = vstring_export(cipher_name); - return (ret == 9 ? 1 : -1); + tls_context->kex_name = vstring_export(kex_name); + tls_context->kex_curve = vstring_export(kex_curve); + tls_context->clnt_sig_name = vstring_export(clnt_sig_name); + tls_context->clnt_sig_curve = vstring_export(clnt_sig_curve); + tls_context->clnt_sig_dgst = vstring_export(clnt_sig_dgst); + tls_context->srvr_sig_name = vstring_export(srvr_sig_name); + tls_context->srvr_sig_curve = vstring_export(srvr_sig_curve); + tls_context->srvr_sig_dgst = vstring_export(srvr_sig_dgst); + tls_context->namaddr = vstring_export(namaddr); + return (ret == 21 ? 1 : -1); } #endif diff --git a/postfix/src/tls/tls_server.c b/postfix/src/tls/tls_server.c index ee715c07f..9c25c2fe2 100644 --- a/postfix/src/tls/tls_server.c +++ b/postfix/src/tls/tls_server.c @@ -953,14 +953,12 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext) tls_stream_start(TLScontext->stream, TLScontext); /* - * All the key facts in a single log entry. + * With the handshake done, extract TLS 1.3 signature metadata. */ + tls_get_signature_params(TLScontext); + if (TLScontext->log_mask & TLS_LOG_SUMMARY) - msg_info("%s TLS connection established from %s: %s with cipher %s " - "(%d/%d bits)", !TLS_CERT_IS_PRESENT(TLScontext) ? "Anonymous" - : TLS_CERT_IS_TRUSTED(TLScontext) ? "Trusted" : "Untrusted", - TLScontext->namaddr, TLScontext->protocol, TLScontext->cipher_name, - TLScontext->cipher_usebits, TLScontext->cipher_algbits); + tls_log_summary(TLS_ROLE_SERVER, TLS_USAGE_NEW, TLScontext); tls_int_seed();