diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/src/deliver.c | 8 | ||||
-rw-r--r-- | src/src/expand.c | 2 | ||||
-rw-r--r-- | src/src/globals.c | 1 | ||||
-rw-r--r-- | src/src/globals.h | 1 | ||||
-rw-r--r-- | src/src/smtp_in.c | 2 | ||||
-rw-r--r-- | src/src/spool_in.c | 19 | ||||
-rw-r--r-- | src/src/spool_out.c | 1 | ||||
-rw-r--r-- | src/src/structs.h | 1 | ||||
-rw-r--r-- | src/src/tls-gnu.c | 11 | ||||
-rw-r--r-- | src/src/tls-openssl.c | 28 | ||||
-rw-r--r-- | src/src/transports/smtp.c | 3 |
11 files changed, 58 insertions, 19 deletions
diff --git a/src/src/deliver.c b/src/src/deliver.c index 34990b71e..94bc9a89c 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -1610,6 +1610,7 @@ if (result == OK) tls_out.peercert = addr->peercert; addr->peercert = NULL; + tls_out.ver = addr->tlsver; tls_out.cipher = addr->cipher; tls_out.peerdn = addr->peerdn; tls_out.ocsp = addr->ocsp; @@ -1623,6 +1624,7 @@ if (result == OK) #ifndef DISABLE_TLS tls_free_cert(&tls_out.ourcert); tls_free_cert(&tls_out.peercert); + tls_out.ver = NULL; tls_out.cipher = NULL; tls_out.peerdn = NULL; tls_out.ocsp = OCSP_NOT_REQ; @@ -3480,11 +3482,13 @@ while (!done) switch (*subid) { case '1': - addr->cipher = NULL; - addr->peerdn = NULL; + addr->tlsver = addr->cipher = addr->peerdn = NULL; if (*ptr) + { addr->cipher = string_copy(ptr); + addr->tlsver = string_copyn(ptr, Ustrchr(ptr, ':') - ptr); + } while (*ptr++); if (*ptr) addr->peerdn = string_copy(ptr); diff --git a/src/src/expand.c b/src/src/expand.c index 9706f2a6b..21686e99c 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -760,6 +760,7 @@ static var_entry var_table[] = { #ifndef DISABLE_TLS { "tls_in_sni", vtype_stringptr, &tls_in.sni }, #endif + { "tls_in_ver", vtype_stringptr, &tls_in.ver }, { "tls_out_bits", vtype_int, &tls_out.bits }, { "tls_out_certificate_verified", vtype_int,&tls_out.certificate_verified }, { "tls_out_cipher", vtype_stringptr, &tls_out.cipher }, @@ -780,6 +781,7 @@ static var_entry var_table[] = { #ifdef SUPPORT_DANE { "tls_out_tlsa_usage", vtype_int, &tls_out.tlsa_usage }, #endif + { "tls_out_ver", vtype_stringptr, &tls_out.ver }, { "tls_peerdn", vtype_stringptr, &tls_in.peerdn }, /* mind the alphabetical order! */ #ifndef DISABLE_TLS diff --git a/src/src/globals.c b/src/src/globals.c index 07665bf75..358c380a8 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -1233,6 +1233,7 @@ uschar *received_header_text = US "by $primary_hostname " "${if def:received_protocol {with $received_protocol }}" #ifndef DISABLE_TLS + "${if def:tls_in_ver { ($tls_in_ver)}}" "${if def:tls_in_cipher_std { tls $tls_in_cipher_std\n\t}}" #endif "(Exim $version_number)\n\t" diff --git a/src/src/globals.h b/src/src/globals.h index 0466da500..ca342acc2 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -89,6 +89,7 @@ typedef struct { #endif uschar *cipher; /* Cipher used */ const uschar *cipher_stdname; /* Cipher used, RFC version */ + const uschar *ver; /* TLS version */ BOOL on_connect; /* For older MTAs that don't STARTTLS */ uschar *on_connect_ports; /* Ports always tls-on-connect */ diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index 671798641..18e04dc2e 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -2466,7 +2466,7 @@ if (!host_checking && !f.sender_host_notsocket) authenticated_by = NULL; #ifndef DISABLE_TLS -tls_in.cipher = tls_in.peerdn = NULL; +tls_in.ver = tls_in.cipher = tls_in.peerdn = NULL; tls_in.ourcert = tls_in.peercert = NULL; tls_in.sni = NULL; tls_in.ocsp = OCSP_NOT_REQ; diff --git a/src/src/spool_in.c b/src/src/spool_in.c index 7c60a12a0..8d5f5a729 100644 --- a/src/src/spool_in.c +++ b/src/src/spool_in.c @@ -278,7 +278,7 @@ tls_in.certificate_verified = FALSE; # ifdef SUPPORT_DANE tls_in.dane_verified = FALSE; # endif -tls_in.cipher = NULL; +tls_in.ver = tls_in.cipher = NULL; # ifndef COMPILE_UTILITY /* tls support fns not built in */ tls_free_cert(&tls_in.ourcert); tls_free_cert(&tls_in.peercert); @@ -669,24 +669,25 @@ for (;;) if (Ustrncmp(q, "certificate_verified", 20) == 0) tls_in.certificate_verified = TRUE; else if (Ustrncmp(q, "cipher", 6) == 0) - tls_in.cipher = string_copy_taint(var + 11, tainted); + tls_in.cipher = string_copy_taint(q+7, tainted); # ifndef COMPILE_UTILITY /* tls support fns not built in */ else if (Ustrncmp(q, "ourcert", 7) == 0) - (void) tls_import_cert(var + 12, &tls_in.ourcert); + (void) tls_import_cert(q+8, &tls_in.ourcert); else if (Ustrncmp(q, "peercert", 8) == 0) - (void) tls_import_cert(var + 13, &tls_in.peercert); + (void) tls_import_cert(q+9, &tls_in.peercert); # endif else if (Ustrncmp(q, "peerdn", 6) == 0) - tls_in.peerdn = string_unprinting(string_copy_taint(var + 11, tainted)); + tls_in.peerdn = string_unprinting(string_copy_taint(q+7, tainted)); else if (Ustrncmp(q, "sni", 3) == 0) - tls_in.sni = string_unprinting(string_copy_taint(var + 8, tainted)); + tls_in.sni = string_unprinting(string_copy_taint(q+4, tainted)); else if (Ustrncmp(q, "ocsp", 4) == 0) - tls_in.ocsp = var[9] - '0'; + tls_in.ocsp = q[5] - '0'; # ifdef EXPERIMENTAL_TLS_RESUME else if (Ustrncmp(q, "resumption", 10) == 0) - tls_in.resumption = var[15] - 'A'; + tls_in.resumption = q[11] - 'A'; # endif - + else if (Ustrncmp(q, "ver", 3) == 0) + tls_in.ver = string_copy_taint(q+4, tainted); } break; #endif diff --git a/src/src/spool_out.c b/src/src/spool_out.c index 00361ab7c..892ea2f52 100644 --- a/src/src/spool_out.c +++ b/src/src/spool_out.c @@ -263,6 +263,7 @@ if (tls_in.ocsp) fprintf(fp, "-tls_ocsp %d\n", tls_in.ocsp); # ifdef EXPERIMENTAL_TLS_RESUME fprintf(fp, "-tls_resumption %c\n", 'A' + tls_in.resumption); # endif +if (tls_in.ver) spool_var_write(fp, US"tls_ver", tls_in.ver); #endif #ifdef SUPPORT_I18N diff --git a/src/src/structs.h b/src/src/structs.h index 338dccbf1..3b5818df0 100644 --- a/src/src/structs.h +++ b/src/src/structs.h @@ -570,6 +570,7 @@ typedef struct address_item { uschar *shadow_message; /* info about shadow transporting */ #ifndef DISABLE_TLS + const uschar *tlsver; /* version used for transport */ uschar *cipher; /* Cipher used for transport */ void *ourcert; /* Certificate offered to peer, binary */ void *peercert; /* Certificate from peer, binary */ diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index f18c244ee..fc426a251 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -480,6 +480,7 @@ Sets: tls_bits strength indicator tls_certificate_verified bool indicator tls_channelbinding_b64 for some SASL mechanisms + tls_ver a string tls_cipher a string tls_peercert pointer to library internal tls_peerdn a string @@ -1766,11 +1767,17 @@ old_pool = store_pool; /* debug_printf("peer_status: gnutls_session_get_desc %s\n", s); */ for (s++; (c = *s) && c != ')'; s++) g = string_catn(g, s, 1); + + tlsp->ver = string_copyn(g->s, g->ptr); + for (uschar * p = US tlsp->ver; *p; p++) + if (*p == '-') { *p = '\0'; break; } /* TLS1.0-PKIX -> TLS1.0 */ + g = string_catn(g, US":", 1); if (*s) s++; /* now on _ between groups */ while ((c = *s)) { - for (*++s && ++s; (c = *s) && c != ')'; s++) g = string_catn(g, c == '-' ? US"_" : s, 1); + for (*++s && ++s; (c = *s) && c != ')'; s++) + g = string_catn(g, c == '-' ? US"_" : s, 1); /* now on ) closing group */ if ((c = *s) && *++s == '-') g = string_catn(g, US"__", 2); /* now on _ between groups */ @@ -1790,6 +1797,8 @@ old_pool = store_pool; releases did return "TLS 1.0"; play it safe, just in case. */ for (uschar * p = state->ciphersuite; *p; p++) if (isspace(*p)) *p = '-'; + tlsp->ver = string_copyn(state->ciphersuite, + Ustrchr(state->ciphersuite, ':') - state->ciphersuite); #endif /* debug_printf("peer_status: ciphersuite %s\n", state->ciphersuite); */ diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index bef3fb4f1..063c23df7 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -2281,14 +2281,13 @@ Returns: pointer to allocated string in perm-pool */ static uschar * -construct_cipher_name(SSL * ssl, int * bits) +construct_cipher_name(SSL * ssl, const uschar * ver, int * bits) { int pool = store_pool; /* With OpenSSL 1.0.0a, 'c' needs to be const but the documentation doesn't yet reflect that. It should be a safe change anyway, even 0.9.8 versions have the accessor functions use const in the prototype. */ -const uschar * ver = CUS SSL_get_version(ssl); const SSL_CIPHER * c = (const SSL_CIPHER *) SSL_get_current_cipher(ssl); uschar * s; @@ -2319,6 +2318,21 @@ return cipher_stdname(id >> 8, id & 0xff); } +static const uschar * +tlsver_name(SSL * ssl) +{ +uschar * s, * p; +int pool = store_pool; + +store_pool = POOL_PERM; +s = string_copy(US SSL_get_version(ssl)); +store_pool = pool; +if ((p = Ustrchr(s, 'v'))) /* TLSv1.2 -> TLS1.2 */ + for (;; p++) if (!(*p = p[1])) break; +return CUS s; +} + + static void peer_cert(SSL * ssl, tls_support * tlsp, uschar * peerdn, unsigned siz) { @@ -2767,12 +2781,13 @@ if (SSL_session_reused(server_ssl)) } #endif -/* TLS has been set up. Adjust the input functions to read via TLS, -and initialize things. */ +/* TLS has been set up. Record data for the connection, +adjust the input functions to read via TLS, and initialize things. */ peer_cert(server_ssl, &tls_in, peerdn, sizeof(peerdn)); -tls_in.cipher = construct_cipher_name(server_ssl, &tls_in.bits); +tls_in.ver = tlsver_name(server_ssl); +tls_in.cipher = construct_cipher_name(server_ssl, tls_in.ver, &tls_in.bits); tls_in.cipher_stdname = cipher_stdname_ssl(server_ssl); DEBUG(D_tls) @@ -3357,7 +3372,8 @@ tls_client_resume_posthandshake(exim_client_ctx, tlsp); peer_cert(exim_client_ctx->ssl, tlsp, peerdn, sizeof(peerdn)); -tlsp->cipher = construct_cipher_name(exim_client_ctx->ssl, &tlsp->bits); +tlsp->ver = tlsver_name(exim_client_ctx->ssl); +tlsp->cipher = construct_cipher_name(exim_client_ctx->ssl, tlsp->ver, &tlsp->bits); tlsp->cipher_stdname = cipher_stdname_ssl(exim_client_ctx->ssl); /* Record the certificate we presented */ diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 9f8603323..3fd94a19c 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -1968,6 +1968,7 @@ tls_out.ocsp = OCSP_NOT_REQ; #ifdef EXPERIMENTAL_TLS_RESUME tls_out.resumption = 0; #endif +tls_out.ver = NULL; /* Flip the legacy TLS-related variables over to the outbound set in case they're used in the context of the transport. Don't bother resetting @@ -2488,6 +2489,7 @@ if ( smtp_peer_options & OPTION_TLS addr->peercert = tls_out.peercert; addr->peerdn = tls_out.peerdn; addr->ocsp = tls_out.ocsp; + addr->tlsver = tls_out.ver; } } } @@ -4440,6 +4442,7 @@ for (address_item * addr = addrlist; addr; addr = addr->next) addr->peercert = NULL; addr->peerdn = NULL; addr->ocsp = OCSP_NOT_REQ; + addr->tlsver = NULL; #endif #ifdef EXPERIMENTAL_DSN_INFO addr->smtp_greeting = NULL; |