X-Git-Url: https://vcs.fsf.org/?p=exim.git;a=blobdiff_plain;f=src%2Fsrc%2Ftls-openssl.c;h=7a3ca81c269dae57a7bf6065ab9fbc4b1623493b;hp=f1176a63e512484937abca78c772505991148a6b;hb=f9ba5e2255cf18092750fffacb6a9603571a2be5;hpb=3af849e2045f7c580d4c533d829dc9d567162d36 diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index f1176a63e..7a3ca81c2 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2017 */ +/* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ /* Portions Copyright (c) The OpenSSL Project 1999 */ @@ -51,7 +51,7 @@ functions from the OpenSSL library. */ # define EXIM_HAVE_RAND_PSEUDO #endif #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256) -# define EXIM_HAVE_SHA256 +# define EXIM_HAVE_SHA256 /*MMMM*/ #endif /* @@ -81,7 +81,7 @@ functions from the OpenSSL library. */ || LIBRESSL_VERSION_NUMBER >= 0x20010000L # if !defined(OPENSSL_NO_ECDH) # if OPENSSL_VERSION_NUMBER >= 0x0090800fL -# define EXIM_HAVE_ECDH +# define EXIM_HAVE_ECDH /*MMMM*/ # endif # if OPENSSL_VERSION_NUMBER >= 0x10002000L # define EXIM_HAVE_OPENSSL_EC_NIST2NID @@ -94,6 +94,10 @@ functions from the OpenSSL library. */ # define DISABLE_OCSP #endif +#ifdef EXIM_HAVE_OPENSSL_CHECKHOST +# include +#endif + /* Structure for collecting random data for seeding. */ typedef struct randstuff { @@ -147,8 +151,8 @@ static BOOL reexpand_tls_files_for_sni = FALSE; typedef struct tls_ext_ctx_cb { uschar *certificate; uschar *privatekey; -#ifndef DISABLE_OCSP BOOL is_server; +#ifndef DISABLE_OCSP STACK_OF(X509) *verify_stack; /* chain for verifying the proof */ union { struct { @@ -228,14 +232,13 @@ return host ? FAIL : DEFER; -#ifdef EXIM_HAVE_EPHEM_RSA_KEX /************************************************* * Callback to generate RSA key * *************************************************/ /* Arguments: - s SSL connection + s SSL connection (not used) export not used keylength keylength @@ -270,7 +273,6 @@ if (!(rsa_key = RSA_generate_key(keylength, RSA_F4, NULL, NULL))) } return rsa_key; } -#endif @@ -538,8 +540,21 @@ DEBUG(D_tls) debug_printf("verify_callback_client_dane: %s depth %d %s\n", #endif if (preverify_ok == 1) - tls_out.dane_verified = - tls_out.certificate_verified = TRUE; + { + tls_out.dane_verified = tls_out.certificate_verified = TRUE; +#ifndef DISABLE_OCSP + if (client_static_cbinfo->u_ocsp.client.verify_store) + { /* client, wanting stapling */ + /* Add the server cert's signing chain as the one + for the verification of the OCSP stapled information. */ + + if (!X509_STORE_add_cert(client_static_cbinfo->u_ocsp.client.verify_store, + cert)) + ERR_clear_error(); + sk_X509_push(client_static_cbinfo->verify_stack, cert); + } +#endif + } else { int err = X509_STORE_CTX_get_error(x509ctx); @@ -935,7 +950,7 @@ if (!OCSP_check_validity(thisupd, nextupd, EXIM_OCSP_SKEW_SECONDS, EXIM_OCSP_MAX } supply_response: - cbinfo->u_ocsp.server.response = resp; + cbinfo->u_ocsp.server.response = resp; /*XXX stack?*/ return; bad: @@ -943,7 +958,7 @@ bad: { extern char ** environ; uschar ** p; - if (environ) for (p = USS environ; *p != NULL; p++) + if (environ) for (p = USS environ; *p; p++) if (Ustrncmp(*p, "EXIM_TESTHARNESS_DISABLE_OCSPVALIDITYCHECK", 42) == 0) { DEBUG(D_tls) debug_printf("Supplying known bad OCSP response\n"); @@ -977,8 +992,7 @@ if (!(x509 = X509_new())) goto err; where = US"generating pkey"; - /* deprecated, use RSA_generate_key_ex() */ -if (!(rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL))) +if (!(rsa = rsa_callback(NULL, 0, 1024))) goto err; where = US"assigning pkey"; @@ -1133,6 +1147,7 @@ else #ifndef DISABLE_OCSP if (cbinfo->is_server && cbinfo->u_ocsp.server.file) { + /*XXX stack*/ if (!expand_check(cbinfo->u_ocsp.server.file, US"tls_ocsp_file", &expanded, errstr)) return DEFER; @@ -1270,9 +1285,15 @@ static int tls_server_stapling_cb(SSL *s, void *arg) { const tls_ext_ctx_cb *cbinfo = (tls_ext_ctx_cb *) arg; -uschar *response_der; +uschar *response_der; /*XXX blob */ int response_der_len; +/*XXX stack: use SSL_get_certificate() to see which cert; from that work +out which ocsp blob to send. Unfortunately, SSL_get_certificate is known +buggy in current OpenSSL; it returns the last cert loaded always rather than +the one actually presented. So we can't support a stack of OCSP proofs at +this time. */ + DEBUG(D_tls) debug_printf("Received TLS status request (OCSP stapling); %s response\n", cbinfo->u_ocsp.server.response ? "have" : "lack"); @@ -1282,7 +1303,7 @@ if (!cbinfo->u_ocsp.server.response) return SSL_TLSEXT_ERR_NOACK; response_der = NULL; -response_der_len = i2d_OCSP_RESPONSE(cbinfo->u_ocsp.server.response, +response_der_len = i2d_OCSP_RESPONSE(cbinfo->u_ocsp.server.response, /*XXX stack*/ &response_der); if (response_der_len <= 0) return SSL_TLSEXT_ERR_NOACK; @@ -1356,7 +1377,7 @@ if(!(bs = OCSP_response_get1_basic(rsp))) int status, reason; ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; - DEBUG(D_tls) bp = BIO_new_fp(stderr, BIO_NOCLOSE); + DEBUG(D_tls) bp = BIO_new_fp(debug_file, BIO_NOCLOSE); /*OCSP_RESPONSE_print(bp, rsp, 0); extreme debug: stapling content */ @@ -1367,10 +1388,12 @@ if(!(bs = OCSP_response_get1_basic(rsp))) cbinfo->u_ocsp.client.verify_store, 0)) <= 0) { tls_out.ocsp = OCSP_FAILED; - if (LOGGING(tls_cipher)) - log_write(0, LOG_MAIN, "Received TLS cert status response, itself unverifiable"); + if (LOGGING(tls_cipher)) log_write(0, LOG_MAIN, + "Received TLS cert status response, itself unverifiable: %s", + ERR_reason_error_string(ERR_peek_error())); BIO_printf(bp, "OCSP response verify failure\n"); ERR_print_errors(bp); + OCSP_RESPONSE_print(bp, rsp, 0); goto failed; } @@ -1474,7 +1497,7 @@ static int tls_init(SSL_CTX **ctxp, host_item *host, uschar *dhparam, uschar *certificate, uschar *privatekey, #ifndef DISABLE_OCSP - uschar *ocsp_file, + uschar *ocsp_file, /*XXX stack, in server*/ #endif address_item *addr, tls_ext_ctx_cb ** cbp, uschar ** errstr) { @@ -1486,9 +1509,10 @@ tls_ext_ctx_cb * cbinfo; cbinfo = store_malloc(sizeof(tls_ext_ctx_cb)); cbinfo->certificate = certificate; cbinfo->privatekey = privatekey; +cbinfo->is_server = host==NULL; #ifndef DISABLE_OCSP cbinfo->verify_stack = NULL; -if ((cbinfo->is_server = host==NULL)) +if (!host) { cbinfo->u_ocsp.server.file = ocsp_file; cbinfo->u_ocsp.server.file_expanded = NULL; @@ -1801,7 +1825,7 @@ if (expcerts && *expcerts) ) { log_write(0, LOG_MAIN|LOG_PANIC, - "failed to load cert hain from %s", file); + "failed to load cert chain from %s", file); return DEFER; } #endif @@ -1944,7 +1968,7 @@ the error. */ rc = tls_init(&server_ctx, NULL, tls_dhparam, tls_certificate, tls_privatekey, #ifndef DISABLE_OCSP - tls_ocsp_file, + tls_ocsp_file, /*XXX stack*/ #endif NULL, &server_static_cbinfo, errstr); if (rc != OK) return rc;