From e51c7be22dfccad376659a1a46cee93c9979bbf7 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 20 May 2014 21:25:10 +0100 Subject: Support optional server certificate name checking. Bug 1479 Enable EXPERIMENTAL_CERTNAMES to include. --- doc/doc-txt/experimental-spec.txt | 19 +++ src/src/EDITME | 4 + src/src/config.h.defaults | 1 + src/src/exim.c | 3 + src/src/functions.h | 7 +- src/src/tls-gnu.c | 131 +++++++++++++++----- src/src/tls-openssl.c | 69 ++++++++++- src/src/tls.c | 74 ++++++++++++ src/src/tlscert-gnu.c | 5 +- src/src/tlscert-openssl.c | 10 +- src/src/transports/smtp.c | 7 ++ src/src/transports/smtp.h | 15 ++- test/confs/2012 | 80 +++++++++++-- test/confs/2112 | 78 ++++++++++-- test/confs/5440 | 172 +++++++++++++++++++++++++++ test/confs/5450 | 172 +++++++++++++++++++++++++++ test/log/2012 | 4 +- test/log/2112 | 14 ++- test/log/5440 | 17 +++ test/log/5450 | 28 +++++ test/scripts/5440-certnames-GnuTLS/5440 | 14 +++ test/scripts/5440-certnames-GnuTLS/REQUIRES | 3 + test/scripts/5450-certnames-OpenSSL/5450 | 16 +++ test/scripts/5450-certnames-OpenSSL/REQUIRES | 3 + 24 files changed, 868 insertions(+), 78 deletions(-) create mode 100644 test/confs/5440 create mode 100644 test/confs/5450 create mode 100644 test/log/5440 create mode 100644 test/log/5450 create mode 100644 test/scripts/5440-certnames-GnuTLS/5440 create mode 100644 test/scripts/5440-certnames-GnuTLS/REQUIRES create mode 100644 test/scripts/5450-certnames-OpenSSL/5450 create mode 100644 test/scripts/5450-certnames-OpenSSL/REQUIRES diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt index d8c26bf93..588543454 100644 --- a/doc/doc-txt/experimental-spec.txt +++ b/doc/doc-txt/experimental-spec.txt @@ -1147,6 +1147,25 @@ QUIT +Certificate name checking +-------------------------------------------------------------- +The X509 certificates used for TLS are supposed be verified +that they are owned by the expected host. The coding of TLS +support to date has not made these checks. + +If built with EXPERIMENTAL_CERTNAMES defined, code is +included to do so, and a new smtp transport option +"tls_verify_cert_hostname" supported which takes a list of +names for which the checks must be made. The host must +also be in "tls_verify_hosts". + +Both Subject and Subject-Alternate-Name certificate fields +are supported, as are wildcard certificates (limited to +a single wildcard being the initial component of a 3-or-more +component FQDN). + + + -------------------------------------------------------------- End of file -------------------------------------------------------------- diff --git a/src/src/EDITME b/src/src/EDITME index 7d58af744..83ca43cd1 100644 --- a/src/src/EDITME +++ b/src/src/EDITME @@ -485,6 +485,10 @@ EXIM_MONITOR=eximon.bin # Uncomment the following line to enable Experimental Proxy Protocol # EXPERIMENTAL_PROXY=yes +# Uncomment the following line to enable support for checking certiticate +# ownership +# EXPERIMENTAL_CERTNAMES=yes + ############################################################################### # THESE ARE THINGS YOU MIGHT WANT TO SPECIFY # diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults index 69df842e7..3ab73d861 100644 --- a/src/src/config.h.defaults +++ b/src/src/config.h.defaults @@ -165,6 +165,7 @@ it's a default value. */ /* EXPERIMENTAL features */ #define EXPERIMENTAL_BRIGHTMAIL +#define EXPERIMENTAL_CERTNAMES #define EXPERIMENTAL_DCC #define EXPERIMENTAL_DMARC #define EXPERIMENTAL_OCSP diff --git a/src/src/exim.c b/src/src/exim.c index ded12fa34..bca6cc8a4 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -831,6 +831,9 @@ fprintf(f, "Support for:"); #ifdef EXPERIMENTAL_REDIS fprintf(f, " Experimental_Redis"); #endif +#ifdef EXPERIMENTAL_CERTNAMES + fprintf(f, " Experimental_Certnames"); +#endif fprintf(f, "\n"); fprintf(f, "Lookups (built-in):"); diff --git a/src/src/functions.h b/src/src/functions.h index 741b632a9..a6257a913 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -59,10 +59,13 @@ extern int tls_ungetc(int); extern int tls_write(BOOL, const uschar *, size_t); extern uschar *tls_validate_require_cipher(void); extern void tls_version_report(FILE *); -#ifndef USE_GNUTLS +# ifndef USE_GNUTLS extern BOOL tls_openssl_options_parse(uschar *, long *); -#endif +# endif extern uschar * tls_field_from_dn(uschar *, uschar *); +# ifdef EXPERIMENTAL_CERTNAMES +extern BOOL tls_is_name_for_cert(uschar *, void *); +# endif #endif /*SUPPORT_TLS*/ diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index 3c926c0d4..af43686e4 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -60,7 +60,12 @@ Changes: /* Values for verify_requirement */ -enum peer_verify_requirement { VERIFY_NONE, VERIFY_OPTIONAL, VERIFY_REQUIRED }; +enum peer_verify_requirement + { VERIFY_NONE, VERIFY_OPTIONAL, VERIFY_REQUIRED +#ifdef EXPERIMENTAL_CERTNAMES + ,VERIFY_WITHHOST +#endif + }; /* This holds most state for server or client; with this, we can set up an outbound TLS-enabled connection in an ACL callout, while not stomping all @@ -95,6 +100,7 @@ typedef struct exim_gnutls_state { const uschar *tls_verify_certificates; const uschar *tls_crl; const uschar *tls_require_ciphers; + uschar *exp_tls_certificate; uschar *exp_tls_privatekey; uschar *exp_tls_sni; @@ -102,6 +108,9 @@ typedef struct exim_gnutls_state { uschar *exp_tls_crl; uschar *exp_tls_require_ciphers; uschar *exp_tls_ocsp_file; +#ifdef EXPERIMENTAL_CERTNAMES + uschar *exp_tls_verify_cert_hostnames; +#endif tls_support *tlsp; /* set in tls_init() */ @@ -117,6 +126,9 @@ static const exim_gnutls_state_st exim_gnutls_state_init = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +#ifdef EXPERIMENTAL_CERTNAMES + NULL, +#endif NULL, NULL, 0, 0, 0, 0, }; @@ -178,18 +190,18 @@ before, for now. */ #define expand_check_tlsvar(Varname) expand_check(state->Varname, US #Varname, &state->exp_##Varname) #if GNUTLS_VERSION_NUMBER >= 0x020c00 -#define HAVE_GNUTLS_SESSION_CHANNEL_BINDING -#define HAVE_GNUTLS_SEC_PARAM_CONSTANTS -#define HAVE_GNUTLS_RND +# define HAVE_GNUTLS_SESSION_CHANNEL_BINDING +# define HAVE_GNUTLS_SEC_PARAM_CONSTANTS +# define HAVE_GNUTLS_RND /* The security fix we provide with the gnutls_allow_auto_pkcs11 option * (4.82 PP/09) introduces a compatibility regression. The symbol simply * isn't available sometimes, so this needs to become a conditional * compilation; the sanest way to deal with this being a problem on * older OSes is to block it in the Local/Makefile with this compiler * definition */ -#ifndef AVOID_GNUTLS_PKCS11 -#define HAVE_GNUTLS_PKCS11 -#endif /* AVOID_GNUTLS_PKCS11 */ +# ifndef AVOID_GNUTLS_PKCS11 +# define HAVE_GNUTLS_PKCS11 +# endif /* AVOID_GNUTLS_PKCS11 */ #endif @@ -294,10 +306,16 @@ tls_error(when, msg, state->host); * Set various Exim expansion vars * *************************************************/ -#define exim_gnutls_cert_err(Label) do { \ - if (rc != GNUTLS_E_SUCCESS) { \ - DEBUG(D_tls) debug_printf("TLS: cert problem: %s: %s\n", (Label), gnutls_strerror(rc)); \ - return rc; } } while (0) +#define exim_gnutls_cert_err(Label) \ + do \ + { \ + if (rc != GNUTLS_E_SUCCESS) \ + { \ + DEBUG(D_tls) debug_printf("TLS: cert problem: %s: %s\n", \ + (Label), gnutls_strerror(rc)); \ + return rc; \ + } \ + } while (0) static int import_cert(const gnutls_datum * cert, gnutls_x509_crt_t * crtp) @@ -1220,7 +1238,7 @@ if (cert_list == NULL || cert_list_size == 0) { DEBUG(D_tls) debug_printf("TLS: no certificate from peer (%p & %d)\n", cert_list, cert_list_size); - if (state->verify_requirement == VERIFY_REQUIRED) + if (state->verify_requirement >= VERIFY_REQUIRED) return tls_error(US"certificate verification failed", "no certificate received from peer", state->host); return OK; @@ -1232,17 +1250,23 @@ if (ct != GNUTLS_CRT_X509) const char *ctn = gnutls_certificate_type_get_name(ct); DEBUG(D_tls) debug_printf("TLS: peer cert not X.509 but instead \"%s\"\n", ctn); - if (state->verify_requirement == VERIFY_REQUIRED) + if (state->verify_requirement >= VERIFY_REQUIRED) return tls_error(US"certificate verification not possible, unhandled type", ctn, state->host); return OK; } -#define exim_gnutls_peer_err(Label) do { \ - if (rc != GNUTLS_E_SUCCESS) { \ - DEBUG(D_tls) debug_printf("TLS: peer cert problem: %s: %s\n", (Label), gnutls_strerror(rc)); \ - if (state->verify_requirement == VERIFY_REQUIRED) { return tls_error((Label), gnutls_strerror(rc), state->host); } \ - return OK; } } while (0) +#define exim_gnutls_peer_err(Label) \ + do { \ + if (rc != GNUTLS_E_SUCCESS) \ + { \ + DEBUG(D_tls) debug_printf("TLS: peer cert problem: %s: %s\n", \ + (Label), gnutls_strerror(rc)); \ + if (state->verify_requirement >= VERIFY_REQUIRED) \ + return tls_error((Label), gnutls_strerror(rc), state->host); \ + return OK; \ + } \ + } while (0) rc = import_cert(&cert_list[0], &crt); exim_gnutls_peer_err(US"cert 0"); @@ -1306,7 +1330,9 @@ else /* Handle the result of verification. INVALID seems to be set as well as REVOKED, but leave the test for both. */ -if (rc < 0 || verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED)) +if (rc < 0 || + verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED) + ) { state->peer_cert_verified = FALSE; if (!*error) @@ -1314,21 +1340,42 @@ if (rc < 0 || verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED)) ? "certificate revoked" : "certificate invalid"; DEBUG(D_tls) - debug_printf("TLS certificate verification failed (%s): peerdn=%s\n", + debug_printf("TLS certificate verification failed (%s): peerdn=\"%s\"\n", *error, state->peerdn ? state->peerdn : US""); - if (state->verify_requirement == VERIFY_REQUIRED) + if (state->verify_requirement >= VERIFY_REQUIRED) { - gnutls_alert_send(state->session, GNUTLS_AL_FATAL, GNUTLS_A_BAD_CERTIFICATE); + gnutls_alert_send(state->session, + GNUTLS_AL_FATAL, GNUTLS_A_BAD_CERTIFICATE); return FALSE; } DEBUG(D_tls) debug_printf("TLS verify failure overridden (host in tls_try_verify_hosts)\n"); } + else { +#ifdef EXPERIMENTAL_CERTNAMES + if (state->verify_requirement == VERIFY_WITHHOST) + { + int sep = 0; + uschar * list = state->exp_tls_verify_cert_hostnames; + uschar * name; + while (name = string_nextinlist(&list, &sep, NULL, 0)) + if (gnutls_x509_crt_check_hostname(state->tlsp->peercert, CS name)) + break; + if (!name) + { + DEBUG(D_tls) + debug_printf("TLS certificate verification failed: cert name mismatch\n"); + gnutls_alert_send(state->session, + GNUTLS_AL_FATAL, GNUTLS_A_BAD_CERTIFICATE); + return FALSE; + } + } +#endif state->peer_cert_verified = TRUE; - DEBUG(D_tls) debug_printf("TLS certificate verified: peerdn=%s\n", + DEBUG(D_tls) debug_printf("TLS certificate verified: peerdn=\"%s\"\n", state->peerdn ? state->peerdn : US""); } @@ -1517,19 +1564,22 @@ optional, set up appropriately. */ if (verify_check_host(&tls_verify_hosts) == OK) { - DEBUG(D_tls) debug_printf("TLS: a client certificate will be required.\n"); + DEBUG(D_tls) + debug_printf("TLS: a client certificate will be required.\n"); state->verify_requirement = VERIFY_REQUIRED; gnutls_certificate_server_set_request(state->session, GNUTLS_CERT_REQUIRE); } else if (verify_check_host(&tls_try_verify_hosts) == OK) { - DEBUG(D_tls) debug_printf("TLS: a client certificate will be requested but not required.\n"); + DEBUG(D_tls) + debug_printf("TLS: a client certificate will be requested but not required.\n"); state->verify_requirement = VERIFY_OPTIONAL; gnutls_certificate_server_set_request(state->session, GNUTLS_CERT_REQUEST); } else { - DEBUG(D_tls) debug_printf("TLS: a client certificate will not be requested.\n"); + DEBUG(D_tls) + debug_printf("TLS: a client certificate will not be requested.\n"); state->verify_requirement = VERIFY_NONE; gnutls_certificate_server_set_request(state->session, GNUTLS_CERT_IGNORE); } @@ -1699,19 +1749,40 @@ if (( state->exp_tls_verify_certificates verify_check_host(&ob->tls_verify_hosts) == OK ) { - DEBUG(D_tls) debug_printf("TLS: server certificate verification required.\n"); - state->verify_requirement = VERIFY_REQUIRED; +#ifdef EXPERIMENTAL_CERTNAMES + if (ob->tls_verify_cert_hostnames) + { + DEBUG(D_tls) + debug_printf("TLS: server cert incl. hostname verification required.\n"); + state->verify_requirement = VERIFY_WITHHOST; + if (!expand_check(ob->tls_verify_cert_hostnames, + US"tls_verify_cert_hostnames", + &state->exp_tls_verify_cert_hostnames)) + return FAIL; + if (state->exp_tls_verify_cert_hostnames) + DEBUG(D_tls) debug_printf("Cert hostname to check: \"%s\"\n", + state->exp_tls_verify_cert_hostnames); + } + else +#endif + { + DEBUG(D_tls) + debug_printf("TLS: server certificate verification required.\n"); + state->verify_requirement = VERIFY_REQUIRED; + } gnutls_certificate_server_set_request(state->session, GNUTLS_CERT_REQUIRE); } else if (verify_check_host(&ob->tls_try_verify_hosts) == OK) { - DEBUG(D_tls) debug_printf("TLS: server certificate verification optional.\n"); + DEBUG(D_tls) + debug_printf("TLS: server certificate verification optional.\n"); state->verify_requirement = VERIFY_OPTIONAL; gnutls_certificate_server_set_request(state->session, GNUTLS_CERT_REQUEST); } else { - DEBUG(D_tls) debug_printf("TLS: server certificate verification not required.\n"); + DEBUG(D_tls) + debug_printf("TLS: server certificate verification not required.\n"); state->verify_requirement = VERIFY_NONE; gnutls_certificate_server_set_request(state->session, GNUTLS_CERT_IGNORE); } diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index 3000b8fcb..1d6b91470 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -23,7 +23,7 @@ functions from the OpenSSL library. */ #include #include #ifdef EXPERIMENTAL_OCSP -#include +# include #endif #ifdef EXPERIMENTAL_OCSP @@ -32,7 +32,7 @@ functions from the OpenSSL library. */ #endif #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) -#define EXIM_HAVE_OPENSSL_TLSEXT +# define EXIM_HAVE_OPENSSL_TLSEXT #endif /* Structure for collecting random data for seeding. */ @@ -107,6 +107,10 @@ typedef struct tls_ext_ctx_cb { uschar *server_cipher_list; /* only passed down to tls_error: */ host_item *host; + +#ifdef EXPERIMENTAL_CERTNAMES + uschar * verify_cert_hostnames; +#endif } tls_ext_ctx_cb; /* should figure out a cleanup of API to handle state preserved per @@ -268,8 +272,7 @@ verify_callback(int state, X509_STORE_CTX *x509ctx, X509 * cert = X509_STORE_CTX_get_current_cert(x509ctx); static uschar txt[256]; -X509_NAME_oneline(X509_get_subject_name(cert), - CS txt, sizeof(txt)); +X509_NAME_oneline(X509_get_subject_name(cert), CS txt, sizeof(txt)); if (state == 0) { @@ -306,8 +309,43 @@ else if (X509_STORE_CTX_get_error_depth(x509ctx) != 0) } else { +#ifdef EXPERIMENTAL_CERTNAMES + uschar * verify_cert_hostnames; +#endif + tlsp->peerdn = txt; tlsp->peercert = X509_dup(cert); + +#ifdef EXPERIMENTAL_CERTNAMES + if ( tlsp == &tls_out + && ((verify_cert_hostnames = client_static_cbinfo->verify_cert_hostnames))) + /* client, wanting hostname check */ + +# if OPENSSL_VERSION_NUMBER >= 0x010100000L || OPENSSL_VERSION_NUMBER >= 0x010002000L + { + int sep = 0; + uschar * list = verify_cert_hostnames; + uschar * name; + while (name = string_nextinlist(&list, &sep, NULL, 0)) + if (X509_check_host(cert, name, 0, 0)) + break; + if (!name) + { + log_write(0, LOG_MAIN, + "SSL verify error: certificate name mismatch: \"%s\"\n", txt); + return 0; /* reject */ + } + } +# else + if (!tls_is_name_for_cert(verify_cert_hostnames, cert)) + { + log_write(0, LOG_MAIN, + "SSL verify error: certificate name mismatch: \"%s\"\n", txt); + return 0; /* reject */ + } +# endif +#endif + DEBUG(D_tls) debug_printf("SSL%s verify ok: depth=0 SN=%s\n", *calledp ? "" : " authenticated", txt); if (!*calledp) tlsp->certificate_verified = TRUE; @@ -955,8 +993,8 @@ return i; * Initialize for TLS * *************************************************/ -/* Called from both server and client code, to do preliminary initialization of -the library. +/* Called from both server and client code, to do preliminary initialization +of the library. We allocate and return a context structure. Arguments: host connected host, if client; NULL if server @@ -965,6 +1003,7 @@ Arguments: privatekey private key ocsp_file file of stapling info (server); flag for require ocsp (client) addr address if client; NULL if server (for some randomness) + cbp place to put allocated context Returns: OK/DEFER/FAIL */ @@ -1118,6 +1157,10 @@ else /* client */ # endif #endif +#ifdef EXPERIMENTAL_CERTNAMES +cbinfo->verify_cert_hostnames = NULL; +#endif + /* Set up the RSA callback */ SSL_CTX_set_tmp_rsa_callback(*ctxp, rsa_callback); @@ -1545,6 +1588,7 @@ if (expciphers != NULL) /* stick to the old behaviour for compatibility if tls_verify_certificates is set but both tls_verify_hosts and tls_try_verify_hosts is not set. Check only the specified host patterns if one of them is defined */ + if ((!ob->tls_verify_hosts && !ob->tls_try_verify_hosts) || (verify_check_host(&ob->tls_verify_hosts) == OK)) { @@ -1552,6 +1596,19 @@ if ((!ob->tls_verify_hosts && !ob->tls_try_verify_hosts) || ob->tls_crl, host, FALSE, verify_callback_client)) != OK) return rc; client_verify_optional = FALSE; + +#ifdef EXPERIMENTAL_CERTNAMES + if (ob->tls_verify_cert_hostnames) + { + if (!expand_check(ob->tls_verify_cert_hostnames, + US"tls_verify_cert_hostnames", + &client_static_cbinfo->verify_cert_hostnames)) + return FAIL; + if (client_static_cbinfo->verify_cert_hostnames) + DEBUG(D_tls) debug_printf("Cert hostname to check: \"%s\"\n", + client_static_cbinfo->verify_cert_hostnames); + } +#endif } else if (verify_check_host(&ob->tls_try_verify_hosts) == OK) { diff --git a/src/src/tls.c b/src/src/tls.c index 75c46e9e4..b5ef96595 100644 --- a/src/src/tls.c +++ b/src/src/tls.c @@ -255,6 +255,80 @@ return list; } +#ifdef EXPERIMENTAL_CERTNAMES +/* Compare a domain name with a possibly-wildcarded name. Wildcards +are restricted to a single one, as the first element of patterns +having at least three dot-separated elements. Case-independent. +Return TRUE for a match +*/ +static BOOL +is_name_match(const uschar * name, const uschar * pat) +{ +uschar * cp; +return *pat == '*' /* possible wildcard match */ + ? *++pat == '.' /* starts star, dot */ + && !Ustrchr(++pat, '*') /* has no more stars */ + && Ustrchr(pat, '.') /* and has another dot. */ + && (cp = Ustrchr(name, '.'))/* The name has at least one dot */ + && strcmpic(++cp, pat) == 0 /* and we only compare after it. */ + : !Ustrchr(pat+1, '*') + && strcmpic(name, pat) == 0; +} + +/* Compare a list of names with the dnsname elements +of the Subject Alternate Name, if any, and the +Subject otherwise. + +Arguments: + namelist names to compare + cert certificate + +Returns: + TRUE/FALSE +*/ + +BOOL +tls_is_name_for_cert(uschar * namelist, void * cert) +{ +uschar * altnames = tls_cert_subject_altname(cert, US"dns"); +uschar * subjdn; +uschar * certname; +int cmp_sep = 0; +uschar * cmpname; + +if ((altnames = tls_cert_subject_altname(cert, US"dns"))) + { + int alt_sep = '\n'; + while (cmpname = string_nextinlist(&namelist, &cmp_sep, NULL, 0)) + { + uschar * an = altnames; + while (certname = string_nextinlist(&an, &alt_sep, NULL, 0)) + if (is_name_match(cmpname, certname)) + return TRUE; + } + } + +else if ((subjdn = tls_cert_subject(cert, NULL))) + { + int sn_sep = ','; + uschar * sn; + + dn_to_list(subjdn); + while (cmpname = string_nextinlist(&namelist, &cmp_sep, NULL, 0)) + { + uschar * sn = subjdn; + while (certname = string_nextinlist(&sn, &sn_sep, NULL, 0)) + if ( *certname++ == 'C' + && *certname++ == 'N' + && *certname++ == '=' + && is_name_match(cmpname, certname) + ) + return TRUE; + } + } +return FALSE; +} +#endif /* vi: aw ai sw=2 */ diff --git a/src/src/tlscert-gnu.c b/src/src/tlscert-gnu.c index 9b9c83d8b..737637302 100644 --- a/src/src/tlscert-gnu.c +++ b/src/src/tlscert-gnu.c @@ -268,7 +268,7 @@ for(index = 0;; index++) { siz = 0; switch(ret = gnutls_x509_crt_get_subject_alt_name( - (gnutls_x509_crt_t)cert, index, NULL, &siz, NULL)) + (gnutls_x509_crt_t)cert, index, NULL, &siz, NULL)) { case GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE: return list; /* no more elements; normal exit */ @@ -286,7 +286,8 @@ for(index = 0;; index++) return g_err("gs1", __FUNCTION__, ret); ele[siz] = '\0'; - if (match != -1 && match != ret) + if ( match != -1 && match != ret /* wrong type of SAN */ + || Ustrlen(ele) != siz) /* contains a NUL */ continue; switch (ret) { diff --git a/src/src/tlscert-openssl.c b/src/src/tlscert-openssl.c index 29095782a..0614b4025 100644 --- a/src/src/tlscert-openssl.c +++ b/src/src/tlscert-openssl.c @@ -237,6 +237,7 @@ uschar sep = '\n'; uschar * tag = US""; uschar * ele; int match = -1; +int len; if (!san) return NULL; @@ -262,19 +263,26 @@ while (sk_GENERAL_NAME_num(san) > 0) case GEN_DNS: tag = US"DNS"; ele = ASN1_STRING_data(namePart->d.dNSName); + len = ASN1_STRING_length(namePart->d.dNSName); break; case GEN_URI: tag = US"URI"; ele = ASN1_STRING_data(namePart->d.uniformResourceIdentifier); + len = ASN1_STRING_length(namePart->d.uniformResourceIdentifier); break; case GEN_EMAIL: tag = US"MAIL"; ele = ASN1_STRING_data(namePart->d.rfc822Name); + len = ASN1_STRING_length(namePart->d.rfc822Name); break; default: continue; /* ignore unrecognised types */ } - list = string_append_listele(list, sep, + if (ele[len]) /* not nul-terminated */ + ele = string_copyn(ele, len); + + if (strnlen(CS ele, len) == len) /* ignore any with embedded nul */ + list = string_append_listele(list, sep, match == -1 ? string_sprintf("%s=%s", tag, ele) : ele); } diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 71a9f2376..c175d2ffe 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -163,6 +163,10 @@ optionlist smtp_transport_options[] = { (void *)offsetof(smtp_transport_options_block, tls_tempfail_tryclear) }, { "tls_try_verify_hosts", opt_stringptr, (void *)offsetof(smtp_transport_options_block, tls_try_verify_hosts) }, +#ifdef EXPERIMENTAL_CERTNAMES + { "tls_verify_cert_hostnames", opt_stringptr, + (void *)offsetof(smtp_transport_options_block,tls_verify_cert_hostnames)}, +#endif { "tls_verify_certificates", opt_stringptr, (void *)offsetof(smtp_transport_options_block, tls_verify_certificates) }, { "tls_verify_hosts", opt_stringptr, @@ -245,6 +249,9 @@ smtp_transport_options_block smtp_transport_option_defaults = { TRUE, /* tls_tempfail_tryclear */ NULL, /* tls_verify_hosts */ NULL /* tls_try_verify_hosts */ +# ifdef EXPERIMENTAL_CERTNAMES + ,NULL /* tls_verify_cert_hostnames */ +# endif #endif #ifndef DISABLE_DKIM ,NULL, /* dkim_canon */ diff --git a/src/src/transports/smtp.h b/src/src/transports/smtp.h index c7de0091a..a481943bb 100644 --- a/src/src/transports/smtp.h +++ b/src/src/transports/smtp.h @@ -55,7 +55,7 @@ typedef struct { BOOL keepalive; BOOL lmtp_ignore_quota; BOOL retry_include_ip_address; - #ifdef SUPPORT_TLS +#ifdef SUPPORT_TLS uschar *tls_certificate; uschar *tls_crl; uschar *tls_privatekey; @@ -69,18 +69,21 @@ typedef struct { BOOL tls_tempfail_tryclear; uschar *tls_verify_hosts; uschar *tls_try_verify_hosts; - #endif - #ifndef DISABLE_DKIM +# ifdef EXPERIMENTAL_CERTNAMES + uschar *tls_verify_cert_hostnames; +# endif +#endif +#ifndef DISABLE_DKIM uschar *dkim_domain; uschar *dkim_private_key; uschar *dkim_selector; uschar *dkim_canon; uschar *dkim_sign_headers; uschar *dkim_strict; - #endif - #ifdef EXPERIMENTAL_TPDA +#endif +#ifdef EXPERIMENTAL_TPDA uschar *tpda_host_defer_action; - #endif +#endif } smtp_transport_options_block; /* Data for reading the private options. */ diff --git a/test/confs/2012 b/test/confs/2012 index 263034435..97dc25e75 100644 --- a/test/confs/2012 +++ b/test/confs/2012 @@ -12,6 +12,16 @@ log_file_path = DIR/spool/log/SERVER%slog gecos_pattern = "" gecos_name = CALLER_NAME +FX = DIR/aux-fixed +S1 = FX/exim-ca/example.com/server1.example.com + +CA1 = S1/ca_chain.pem +CERT1 = S1/server1.example.com.pem +KEY1 = S1/server1.example.com.unlocked.key +CA2 = FX/cert2 +CERT2 = FX/cert2 +KEY2 = FX/cert2 + # ----- Main settings ----- acl_smtp_rcpt = accept @@ -25,11 +35,11 @@ tls_advertise_hosts = * # Set certificate only if server -tls_certificate = ${if eq {SERVER}{server}{DIR/aux-fixed/cert1}fail} -tls_privatekey = ${if eq {SERVER}{server}{DIR/aux-fixed/cert1}fail} +tls_certificate = ${if eq {SERVER}{server}{CERT1}fail} +tls_privatekey = ${if eq {SERVER}{server}{KEY1}fail} tls_verify_hosts = * -tls_verify_certificates = ${if eq {SERVER}{server}{DIR/aux-fixed/cert2}fail} +tls_verify_certificates = ${if eq {SERVER}{server}{CERT2}fail} # ----- Routers ----- @@ -66,6 +76,18 @@ client_q: retry_use_local_part transport = send_to_server_req_fail +client_r: + driver = accept + local_parts = userr + retry_use_local_part + transport = send_to_server_req_failname + +client_s: + driver = accept + local_parts = users + retry_use_local_part + transport = send_to_server_req_passname + # ----- Transports ----- @@ -78,8 +100,10 @@ send_to_server_failcert: hosts = HOSTIPV4 hosts_require_tls = HOSTIPV4 port = PORT_D - tls_certificate = DIR/aux-fixed/cert2 - tls_verify_certificates = DIR/aux-fixed/cert2 + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = CA2 # this will fail to verify the cert at HOSTIPV4 so fail the crypt, then retry on 127.1; ok send_to_server_retry: @@ -88,19 +112,23 @@ send_to_server_retry: hosts = HOSTIPV4 : 127.0.0.1 hosts_require_tls = HOSTIPV4 port = PORT_D - tls_certificate = DIR/aux-fixed/cert2 + tls_certificate = CERT2 + tls_privatekey = CERT2 + tls_verify_certificates = \ - ${if eq{$host_address}{127.0.0.1}{DIR/aux-fixed/cert1}{DIR/aux-fixed/cert2}} + ${if eq{$host_address}{127.0.0.1}{CA1}{CA2}} -# this will fail to verify the cert at HOSTIPV4 but continue unverified though crypted +# this will fail to verify the cert but continue unverified though crypted send_to_server_crypt: driver = smtp allow_localhost hosts = HOSTIPV4 hosts_require_tls = HOSTIPV4 port = PORT_D - tls_certificate = DIR/aux-fixed/cert2 - tls_verify_certificates = DIR/aux-fixed/cert2 + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = CA2 tls_try_verify_hosts = * # this will fail to verify the cert at HOSTIPV4 and fallback to unencrypted @@ -109,8 +137,36 @@ send_to_server_req_fail: allow_localhost hosts = HOSTIPV4 port = PORT_D - tls_certificate = DIR/aux-fixed/cert2 - tls_verify_certificates = DIR/aux-fixed/cert2 + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = CA2 tls_verify_hosts = * +# # this will fail to verify the cert name and fallback to unencrypted +# send_to_server_req_failname: +# driver = smtp +# allow_localhost +# hosts = HOSTIPV4 +# port = PORT_D +# tls_certificate = CERT2 +# tls_privatekey = CERT2 +# +# tls_verify_certificates = CA1 +# tls_verify_cert_hostnames = server1.example.net : server1.example.org +# tls_verify_hosts = * +# +# # this will pass the cert verify including name check +# send_to_server_req_passname: +# driver = smtp +# allow_localhost +# hosts = HOSTIPV4 +# port = PORT_D +# tls_certificate = CERT2 +# tls_privatekey = CERT2 +# +# tls_verify_certificates = CA1 +# tls_verify_cert_hostnames = noway.example.com : server1.example.com +# tls_verify_hosts = * + # End diff --git a/test/confs/2112 b/test/confs/2112 index deb02944d..4751e6015 100644 --- a/test/confs/2112 +++ b/test/confs/2112 @@ -12,6 +12,16 @@ log_file_path = DIR/spool/log/SERVER%slog gecos_pattern = "" gecos_name = CALLER_NAME +FX = DIR/aux-fixed +S1 = FX/exim-ca/example.com/server1.example.com + +CA1 = S1/ca_chain.pem +CERT1 = S1/server1.example.com.pem +KEY1 = S1/server1.example.com.unlocked.key +CA2 = FX/cert2 +CERT2 = FX/cert2 +KEY2 = FX/cert2 + # ----- Main settings ----- acl_smtp_rcpt = accept @@ -25,11 +35,11 @@ tls_advertise_hosts = * # Set certificate only if server -tls_certificate = ${if eq {SERVER}{server}{DIR/aux-fixed/cert1}fail} -tls_privatekey = ${if eq {SERVER}{server}{DIR/aux-fixed/cert1}fail} +tls_certificate = ${if eq {SERVER}{server}{CERT1}fail} +tls_privatekey = ${if eq {SERVER}{server}{KEY1}fail} tls_verify_hosts = * -tls_verify_certificates = ${if eq {SERVER}{server}{DIR/aux-fixed/cert2}fail} +tls_verify_certificates = ${if eq {SERVER}{server}{CERT2}fail} # ----- Routers ----- @@ -66,6 +76,18 @@ client_q: retry_use_local_part transport = send_to_server_req_fail +client_r: + driver = accept + local_parts = userr + retry_use_local_part + transport = send_to_server_req_failname + +client_s: + driver = accept + local_parts = users + retry_use_local_part + transport = send_to_server_req_passname + # ----- Transports ----- @@ -78,8 +100,10 @@ send_to_server_failcert: hosts = HOSTIPV4 hosts_require_tls = HOSTIPV4 port = PORT_D - tls_certificate = DIR/aux-fixed/cert2 - tls_verify_certificates = DIR/aux-fixed/cert2 + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = CA2 # this will fail to verify the cert at HOSTIPV4 so fail the crypt, then retry on 127.1; ok send_to_server_retry: @@ -88,9 +112,11 @@ send_to_server_retry: hosts = HOSTIPV4 : 127.0.0.1 hosts_require_tls = HOSTIPV4 port = PORT_D - tls_certificate = DIR/aux-fixed/cert2 + tls_certificate = CERT2 + tls_privatekey = CERT2 + tls_verify_certificates = \ - ${if eq{$host_address}{127.0.0.1}{DIR/aux-fixed/cert1}{DIR/aux-fixed/cert2}} + ${if eq{$host_address}{127.0.0.1}{CA1}{CA2}} # this will fail to verify the cert but continue unverified though crypted send_to_server_crypt: @@ -99,8 +125,10 @@ send_to_server_crypt: hosts = HOSTIPV4 hosts_require_tls = HOSTIPV4 port = PORT_D - tls_certificate = DIR/aux-fixed/cert2 - tls_verify_certificates = DIR/aux-fixed/cert2 + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = CA2 tls_try_verify_hosts = * # this will fail to verify the cert at HOSTIPV4 and fallback to unencrypted @@ -109,8 +137,36 @@ send_to_server_req_fail: allow_localhost hosts = HOSTIPV4 port = PORT_D - tls_certificate = DIR/aux-fixed/cert2 - tls_verify_certificates = DIR/aux-fixed/cert2 + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = CA2 tls_verify_hosts = * +# # this will fail to verify the cert name and fallback to unencrypted +# send_to_server_req_failname: +# driver = smtp +# allow_localhost +# hosts = HOSTIPV4 +# port = PORT_D +# tls_certificate = CERT2 +# tls_privatekey = CERT2 +# +# tls_verify_certificates = CA1 +# tls_verify_cert_hostnames = server1.example.net : server1.example.org +# tls_verify_hosts = * +# +# # this will pass the cert verify including name check +# send_to_server_req_passname: +# driver = smtp +# allow_localhost +# hosts = HOSTIPV4 +# port = PORT_D +# tls_certificate = CERT2 +# tls_privatekey = CERT2 +# +# tls_verify_certificates = CA1 +# tls_verify_cert_hostnames = noway.example.com : server1.example.com +# tls_verify_hosts = * + # End diff --git a/test/confs/5440 b/test/confs/5440 new file mode 100644 index 000000000..955641246 --- /dev/null +++ b/test/confs/5440 @@ -0,0 +1,172 @@ +# Exim test configuration 2012 +# TLS client: verify certificate from server - fails + +SERVER= + +exim_path = EXIM_PATH +host_lookup_order = bydns +primary_hostname = myhost.test.ex +rfc1413_query_timeout = 0s +spool_directory = DIR/spool +log_file_path = DIR/spool/log/SERVER%slog +gecos_pattern = "" +gecos_name = CALLER_NAME + +FX = DIR/aux-fixed +S1 = FX/exim-ca/example.com/server1.example.com + +CA1 = S1/ca_chain.pem +CERT1 = S1/server1.example.com.pem +KEY1 = S1/server1.example.com.unlocked.key +CA2 = FX/cert2 +CERT2 = FX/cert2 +KEY2 = FX/cert2 + +# ----- Main settings ----- + +acl_smtp_rcpt = accept + +log_selector = +tls_peerdn+tls_certificate_verified + +queue_only +queue_run_in_order + +tls_advertise_hosts = * + +# Set certificate only if server + +tls_certificate = ${if eq {SERVER}{server}{CERT1}fail} +tls_privatekey = ${if eq {SERVER}{server}{KEY1}fail} + +tls_verify_hosts = * +tls_verify_certificates = ${if eq {SERVER}{server}{CERT2}fail} + + +# ----- Routers ----- + +begin routers + +server_dump: + driver = redirect + condition = ${if eq {SERVER}{server}{yes}{no}} + data = :blackhole: + +client_x: + driver = accept + local_parts = userx + retry_use_local_part + transport = send_to_server_failcert + errors_to = "" + +client_y: + driver = accept + local_parts = usery + retry_use_local_part + transport = send_to_server_retry + +client_z: + driver = accept + local_parts = userz + retry_use_local_part + transport = send_to_server_crypt + +client_q: + driver = accept + local_parts = userq + retry_use_local_part + transport = send_to_server_req_fail + +client_r: + driver = accept + local_parts = userr + retry_use_local_part + transport = send_to_server_req_failname + +client_s: + driver = accept + local_parts = users + retry_use_local_part + transport = send_to_server_req_passname + + +# ----- Transports ----- + +begin transports + +# this will fail to verify the cert at HOSTIPV4 so fail the crypt requirement +send_to_server_failcert: + driver = smtp + allow_localhost + hosts = HOSTIPV4 + hosts_require_tls = HOSTIPV4 + port = PORT_D + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = CA2 + +# this will fail to verify the cert at HOSTIPV4 so fail the crypt, then retry on 127.1; ok +send_to_server_retry: + driver = smtp + allow_localhost + hosts = HOSTIPV4 : 127.0.0.1 + hosts_require_tls = HOSTIPV4 + port = PORT_D + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = \ + ${if eq{$host_address}{127.0.0.1}{CA1}{CA2}} + +# this will fail to verify the cert but continue unverified though crypted +send_to_server_crypt: + driver = smtp + allow_localhost + hosts = HOSTIPV4 + hosts_require_tls = HOSTIPV4 + port = PORT_D + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = CA2 + tls_try_verify_hosts = * + +# this will fail to verify the cert at HOSTIPV4 and fallback to unencrypted +send_to_server_req_fail: + driver = smtp + allow_localhost + hosts = HOSTIPV4 + port = PORT_D + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = CA2 + tls_verify_hosts = * + +# this will fail to verify the cert name and fallback to unencrypted +send_to_server_req_failname: + driver = smtp + allow_localhost + hosts = HOSTIPV4 + port = PORT_D + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = CA1 + tls_verify_cert_hostnames = server1.example.net : server1.example.org + tls_verify_hosts = * + +# this will pass the cert verify including name check +send_to_server_req_passname: + driver = smtp + allow_localhost + hosts = HOSTIPV4 + port = PORT_D + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = CA1 + tls_verify_cert_hostnames = noway.example.com : server1.example.com + tls_verify_hosts = * + +# End diff --git a/test/confs/5450 b/test/confs/5450 new file mode 100644 index 000000000..398871c64 --- /dev/null +++ b/test/confs/5450 @@ -0,0 +1,172 @@ +# Exim test configuration 2112 +# TLS client: verify certificate from server - fails + +SERVER= + +exim_path = EXIM_PATH +host_lookup_order = bydns +primary_hostname = myhost.test.ex +rfc1413_query_timeout = 0s +spool_directory = DIR/spool +log_file_path = DIR/spool/log/SERVER%slog +gecos_pattern = "" +gecos_name = CALLER_NAME + +FX = DIR/aux-fixed +S1 = FX/exim-ca/example.com/server1.example.com + +CA1 = S1/ca_chain.pem +CERT1 = S1/server1.example.com.pem +KEY1 = S1/server1.example.com.unlocked.key +CA2 = FX/cert2 +CERT2 = FX/cert2 +KEY2 = FX/cert2 + +# ----- Main settings ----- + +acl_smtp_rcpt = accept + +log_selector = +tls_peerdn+tls_certificate_verified + +queue_only +queue_run_in_order + +tls_advertise_hosts = * + +# Set certificate only if server + +tls_certificate = ${if eq {SERVER}{server}{CERT1}fail} +tls_privatekey = ${if eq {SERVER}{server}{KEY1}fail} + +tls_verify_hosts = * +tls_verify_certificates = ${if eq {SERVER}{server}{CERT2}fail} + + +# ----- Routers ----- + +begin routers + +server_dump: + driver = redirect + condition = ${if eq {SERVER}{server}{yes}{no}} + data = :blackhole: + +client_x: + driver = accept + local_parts = userx + retry_use_local_part + transport = send_to_server_failcert + errors_to = "" + +client_y: + driver = accept + local_parts = usery + retry_use_local_part + transport = send_to_server_retry + +client_z: + driver = accept + local_parts = userz + retry_use_local_part + transport = send_to_server_crypt + +client_q: + driver = accept + local_parts = userq + retry_use_local_part + transport = send_to_server_req_fail + +client_r: + driver = accept + local_parts = userr + retry_use_local_part + transport = send_to_server_req_failname + +client_s: + driver = accept + local_parts = users + retry_use_local_part + transport = send_to_server_req_passname + + +# ----- Transports ----- + +begin transports + +# this will fail to verify the cert at HOSTIPV4 so fail the crypt requirement +send_to_server_failcert: + driver = smtp + allow_localhost + hosts = HOSTIPV4 + hosts_require_tls = HOSTIPV4 + port = PORT_D + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = CA2 + +# this will fail to verify the cert at HOSTIPV4 so fail the crypt, then retry on 127.1; ok +send_to_server_retry: + driver = smtp + allow_localhost + hosts = HOSTIPV4 : 127.0.0.1 + hosts_require_tls = HOSTIPV4 + port = PORT_D + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = \ + ${if eq{$host_address}{127.0.0.1}{CA1}{CA2}} + +# this will fail to verify the cert but continue unverified though crypted +send_to_server_crypt: + driver = smtp + allow_localhost + hosts = HOSTIPV4 + hosts_require_tls = HOSTIPV4 + port = PORT_D + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = CA2 + tls_try_verify_hosts = * + +# this will fail to verify the cert at HOSTIPV4 and fallback to unencrypted +send_to_server_req_fail: + driver = smtp + allow_localhost + hosts = HOSTIPV4 + port = PORT_D + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = CA2 + tls_verify_hosts = * + +# this will fail to verify the cert name and fallback to unencrypted +send_to_server_req_failname: + driver = smtp + allow_localhost + hosts = HOSTIPV4 + port = PORT_D + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = CA1 + tls_verify_cert_hostnames = server1.example.net : server1.example.org + tls_verify_hosts = * + +# this will pass the cert verify including name check +send_to_server_req_passname: + driver = smtp + allow_localhost + hosts = HOSTIPV4 + port = PORT_D + tls_certificate = CERT2 + tls_privatekey = CERT2 + + tls_verify_certificates = CA1 + tls_verify_cert_hostnames = noway.example.com : server1.example.com + tls_verify_hosts = * + +# End diff --git a/test/log/2012 b/test/log/2012 index dbb3273af..bcb1e6fd8 100644 --- a/test/log/2012 +++ b/test/log/2012 @@ -9,9 +9,9 @@ 1999-03-02 09:44:33 10HmaX-0005vi-00 userx@test.ex: error ignored 1999-03-02 09:44:33 10HmaX-0005vi-00 Completed 1999-03-02 09:44:33 10HmaY-0005vi-00 TLS error on connection to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (certificate verification failed): certificate invalid -1999-03-02 09:44:33 10HmaY-0005vi-00 => usery@test.ex R=client_y T=send_to_server_retry H=127.0.0.1 [127.0.0.1] X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 CV=yes DN="C=UK,O=The Exim Maintainers,OU=Test Suite,CN=Phil Pennock" C="250 OK id=10HmbB-0005vi-00" +1999-03-02 09:44:33 10HmaY-0005vi-00 => usery@test.ex R=client_y T=send_to_server_retry H=127.0.0.1 [127.0.0.1] X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 CV=yes DN="CN=server1.example.com" C="250 OK id=10HmbB-0005vi-00" 1999-03-02 09:44:33 10HmaY-0005vi-00 Completed -1999-03-02 09:44:33 10HmaZ-0005vi-00 => userz@test.ex R=client_z T=send_to_server_crypt H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 CV=no DN="C=UK,O=The Exim Maintainers,OU=Test Suite,CN=Phil Pennock" C="250 OK id=10HmbC-0005vi-00" +1999-03-02 09:44:33 10HmaZ-0005vi-00 => userz@test.ex R=client_z T=send_to_server_crypt H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 CV=no DN="CN=server1.example.com" C="250 OK id=10HmbC-0005vi-00" 1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed 1999-03-02 09:44:33 10HmbA-0005vi-00 TLS error on connection to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (certificate verification failed): certificate invalid 1999-03-02 09:44:33 10HmbA-0005vi-00 TLS session failure: delivering unencrypted to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (not in hosts_require_tls) diff --git a/test/log/2112 b/test/log/2112 index 3f77e65ea..ea09dd9a9 100644 --- a/test/log/2112 +++ b/test/log/2112 @@ -3,20 +3,22 @@ 1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss 1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss 1999-03-02 09:44:33 Start queue run: pid=pppp -qf -1999-03-02 09:44:33 10HmaX-0005vi-00 SSL verify error: depth=0 error=self signed certificate cert=/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock +1999-03-02 09:44:33 10HmaX-0005vi-00 SSL verify error: depth=0 error=unable to get local issuer certificate cert=/CN=server1.example.com 1999-03-02 09:44:33 10HmaX-0005vi-00 TLS error on connection to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (SSL_connect): error: <> 1999-03-02 09:44:33 10HmaX-0005vi-00 == userx@test.ex R=client_x T=send_to_server_failcert defer (-37): failure while setting up TLS session 1999-03-02 09:44:33 10HmaX-0005vi-00 ** userx@test.ex: retry timeout exceeded 1999-03-02 09:44:33 10HmaX-0005vi-00 userx@test.ex: error ignored 1999-03-02 09:44:33 10HmaX-0005vi-00 Completed -1999-03-02 09:44:33 10HmaY-0005vi-00 SSL verify error: depth=0 error=self signed certificate cert=/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock +1999-03-02 09:44:33 10HmaY-0005vi-00 SSL verify error: depth=0 error=unable to get local issuer certificate cert=/CN=server1.example.com 1999-03-02 09:44:33 10HmaY-0005vi-00 TLS error on connection to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (SSL_connect): error: <> -1999-03-02 09:44:33 10HmaY-0005vi-00 => usery@test.ex R=client_y T=send_to_server_retry H=127.0.0.1 [127.0.0.1] X=TLSv1:AES256-SHA:256 CV=yes DN="/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock" C="250 OK id=10HmbB-0005vi-00" +1999-03-02 09:44:33 10HmaY-0005vi-00 => usery@test.ex R=client_y T=send_to_server_retry H=127.0.0.1 [127.0.0.1] X=TLSv1:AES256-SHA:256 CV=yes DN="/CN=server1.example.com" C="250 OK id=10HmbB-0005vi-00" 1999-03-02 09:44:33 10HmaY-0005vi-00 Completed -1999-03-02 09:44:33 10HmaZ-0005vi-00 SSL verify error: depth=0 error=self signed certificate cert=/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock -1999-03-02 09:44:33 10HmaZ-0005vi-00 => userz@test.ex R=client_z T=send_to_server_crypt H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLSv1:AES256-SHA:256 CV=no DN="/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock" C="250 OK id=10HmbC-0005vi-00" +1999-03-02 09:44:33 10HmaZ-0005vi-00 SSL verify error: depth=0 error=unable to get local issuer certificate cert=/CN=server1.example.com +1999-03-02 09:44:33 10HmaZ-0005vi-00 SSL verify error: depth=0 error=certificate not trusted cert=/CN=server1.example.com +1999-03-02 09:44:33 10HmaZ-0005vi-00 SSL verify error: depth=0 error=unable to verify the first certificate cert=/CN=server1.example.com +1999-03-02 09:44:33 10HmaZ-0005vi-00 => userz@test.ex R=client_z T=send_to_server_crypt H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLSv1:AES256-SHA:256 CV=no DN="/CN=server1.example.com" C="250 OK id=10HmbC-0005vi-00" 1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed -1999-03-02 09:44:33 10HmbA-0005vi-00 SSL verify error: depth=0 error=self signed certificate cert=/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock +1999-03-02 09:44:33 10HmbA-0005vi-00 SSL verify error: depth=0 error=unable to get local issuer certificate cert=/CN=server1.example.com 1999-03-02 09:44:33 10HmbA-0005vi-00 TLS error on connection to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (SSL_connect): error: <> 1999-03-02 09:44:33 10HmbA-0005vi-00 TLS session failure: delivering unencrypted to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (not in hosts_require_tls) 1999-03-02 09:44:33 10HmbA-0005vi-00 => userq@test.ex R=client_q T=send_to_server_req_fail H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbD-0005vi-00" diff --git a/test/log/5440 b/test/log/5440 new file mode 100644 index 000000000..4d600ebc6 --- /dev/null +++ b/test/log/5440 @@ -0,0 +1,17 @@ +1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss +1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss +1999-03-02 09:44:33 Start queue run: pid=pppp -qf +1999-03-02 09:44:33 10HmaX-0005vi-00 TLS error on connection to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (certificate verification failed) +1999-03-02 09:44:33 10HmaX-0005vi-00 TLS session failure: delivering unencrypted to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (not in hosts_require_tls) +1999-03-02 09:44:33 10HmaX-0005vi-00 => userr@test.ex R=client_r T=send_to_server_req_failname H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmaZ-0005vi-00" +1999-03-02 09:44:33 10HmaX-0005vi-00 Completed +1999-03-02 09:44:33 10HmaY-0005vi-00 => users@test.ex R=client_s T=send_to_server_req_passname H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 CV=yes DN="CN=server1.example.com" C="250 OK id=10HmbA-0005vi-00" +1999-03-02 09:44:33 10HmaY-0005vi-00 Completed +1999-03-02 09:44:33 End queue run: pid=pppp -qf + +******** SERVER ******** +1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 +1999-03-02 09:44:33 TLS error on connection from the.local.host.name [ip4.ip4.ip4.ip4] (recv): A TLS fatal alert has been received.: Certificate is bad +1999-03-02 09:44:33 TLS error on connection from the.local.host.name [ip4.ip4.ip4.ip4] (send): The specified session has been invalidated for some reason. +1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmaX-0005vi-00@myhost.test.ex +1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 CV=yes DN="C=UK,O=The Exim Maintainers,OU=Test Suite,CN=Phil Pennock" S=sss id=E10HmaY-0005vi-00@myhost.test.ex diff --git a/test/log/5450 b/test/log/5450 new file mode 100644 index 000000000..2a8aec4e7 --- /dev/null +++ b/test/log/5450 @@ -0,0 +1,28 @@ +1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss +1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss +1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss +1999-03-02 09:44:33 Start queue run: pid=pppp -qf +1999-03-02 09:44:33 10HmaX-0005vi-00 SSL verify error: depth=0 error=unable to get local issuer certificate cert=/CN=server1.example.com +1999-03-02 09:44:33 10HmaX-0005vi-00 TLS error on connection to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (SSL_connect): error: <> +1999-03-02 09:44:33 10HmaX-0005vi-00 TLS session failure: delivering unencrypted to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (not in hosts_require_tls) +1999-03-02 09:44:33 10HmaX-0005vi-00 => userq@test.ex R=client_q T=send_to_server_req_fail H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbA-0005vi-00" +1999-03-02 09:44:33 10HmaX-0005vi-00 Completed +1999-03-02 09:44:33 10HmaY-0005vi-00 SSL verify error: certificate name mismatch: "/CN=server1.example.com" + +1999-03-02 09:44:33 10HmaY-0005vi-00 TLS error on connection to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (SSL_connect): error: <> +1999-03-02 09:44:33 10HmaY-0005vi-00 TLS session failure: delivering unencrypted to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (not in hosts_require_tls) +1999-03-02 09:44:33 10HmaY-0005vi-00 => userr@test.ex R=client_r T=send_to_server_req_failname H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] C="250 OK id=10HmbB-0005vi-00" +1999-03-02 09:44:33 10HmaY-0005vi-00 Completed +1999-03-02 09:44:33 10HmaZ-0005vi-00 => users@test.ex R=client_s T=send_to_server_req_passname H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLSv1:AES256-SHA:256 CV=yes DN="/CN=server1.example.com" C="250 OK id=10HmbC-0005vi-00" +1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed +1999-03-02 09:44:33 End queue run: pid=pppp -qf + +******** SERVER ******** +1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 +1999-03-02 09:44:33 TLS error on connection from the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] (SSL_accept): error: <> +1999-03-02 09:44:33 TLS client disconnected cleanly (rejected our certificate?) +1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmaX-0005vi-00@myhost.test.ex +1999-03-02 09:44:33 TLS error on connection from the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] (SSL_accept): error: <> +1999-03-02 09:44:33 TLS client disconnected cleanly (rejected our certificate?) +1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmaY-0005vi-00@myhost.test.ex +1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLSv1:AES256-SHA:256 CV=yes DN="/C=UK/O=The Exim Maintainers/OU=Test Suite/CN=Phil Pennock" S=sss id=E10HmaZ-0005vi-00@myhost.test.ex diff --git a/test/scripts/5440-certnames-GnuTLS/5440 b/test/scripts/5440-certnames-GnuTLS/5440 new file mode 100644 index 000000000..fea9551c0 --- /dev/null +++ b/test/scripts/5440-certnames-GnuTLS/5440 @@ -0,0 +1,14 @@ +# TLS client: verify certificate from server - fails +gnutls +exim -DSERVER=server -bd -oX PORT_D +**** +exim userr@test.ex +Testing +**** +exim users@test.ex +Testing +**** +exim -qf +**** +killdaemon +no_msglog_check diff --git a/test/scripts/5440-certnames-GnuTLS/REQUIRES b/test/scripts/5440-certnames-GnuTLS/REQUIRES new file mode 100644 index 000000000..5a5fac1f1 --- /dev/null +++ b/test/scripts/5440-certnames-GnuTLS/REQUIRES @@ -0,0 +1,3 @@ +support GnuTLS +support Experimental_Certnames +running IPv4 diff --git a/test/scripts/5450-certnames-OpenSSL/5450 b/test/scripts/5450-certnames-OpenSSL/5450 new file mode 100644 index 000000000..c94d1a5b2 --- /dev/null +++ b/test/scripts/5450-certnames-OpenSSL/5450 @@ -0,0 +1,16 @@ +# TLS client: verify certificate from server - fails +exim -DSERVER=server -bd -oX PORT_D +**** +exim userq@test.ex +Testing +**** +exim userr@test.ex +Testing +**** +exim users@test.ex +Testing +**** +exim -qf +**** +killdaemon +no_msglog_check diff --git a/test/scripts/5450-certnames-OpenSSL/REQUIRES b/test/scripts/5450-certnames-OpenSSL/REQUIRES new file mode 100644 index 000000000..663b390a9 --- /dev/null +++ b/test/scripts/5450-certnames-OpenSSL/REQUIRES @@ -0,0 +1,3 @@ +support OpenSSL +support Experimental_Certnames +running IPv4 -- cgit v1.2.3