X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Ftls-openssl.c;h=0dfd8e01a321d56c234b884be3f390099d8d059c;hb=191d76b569c84b5664e47949727bf88ae0c978a9;hp=b8466ee22317b8c066b8863a06d65ea90279be65;hpb=ea19ad2276a93548c8a799b1466fd7996c48be04;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index b8466ee22..0dfd8e01a 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -704,12 +704,12 @@ if (Ustrcmp(exp_curve, "auto") == 0) #else # if defined SSL_CTRL_SET_ECDH_AUTO DEBUG(D_tls) debug_printf( - "ECDH OpenSSL 1.0.2+ temp key parameter settings: autoselection\n"); + "ECDH OpenSSL 1.0.2+: temp key parameter settings: autoselection\n"); SSL_CTX_set_ecdh_auto(sctx, 1); return TRUE; # else DEBUG(D_tls) debug_printf( - "ECDH OpenSSL 1.1.0+ temp key parameter settings: default selection\n"); + "ECDH OpenSSL 1.1.0+: temp key parameter settings: default selection\n"); return TRUE; # endif #endif @@ -794,6 +794,9 @@ return rsa_key; /* Create and install a selfsigned certificate, for use in server mode */ +/*XXX we could arrange to call this during prelo for a null tls_certificate option. +The normal cache inval + relo will suffice. +Just need a timer for inval. */ static int tls_install_selfsign(SSL_CTX * sctx, uschar ** errstr) @@ -804,6 +807,7 @@ RSA * rsa; X509_NAME * name; uschar * where; +DEBUG(D_tls) debug_printf("TLS: generating selfsigned server cert\n"); where = US"allocating pkey"; if (!(pkey = EVP_PKEY_new())) goto err; @@ -823,7 +827,7 @@ if (!EVP_PKEY_assign_RSA(pkey, rsa)) X509_set_version(x509, 2); /* N+1 - version 3 */ ASN1_INTEGER_set(X509_get_serialNumber(x509), 1); X509_gmtime_adj(X509_get_notBefore(x509), 0); -X509_gmtime_adj(X509_get_notAfter(x509), (long)60 * 60); /* 1 hour */ +X509_gmtime_adj(X509_get_notAfter(x509), (long)2 * 60 * 60); /* 2 hour */ X509_set_pubkey(x509, pkey); name = X509_get_subject_name(x509); @@ -1572,220 +1576,6 @@ return OK; * One-time init credentials for server and client * **************************************************/ - -#ifdef gnutls -static void -creds_basic_init(gnutls_certificate_credentials_t x509_cred, BOOL server) -{ -} -#endif - -static int -creds_load_server_certs(/*exim_gnutls_state_st * state,*/ const uschar * cert, - const uschar * pkey, const uschar * ocsp, uschar ** errstr) -{ -#ifdef gnutls -const uschar * clist = cert; -const uschar * klist = pkey; -const uschar * olist; -int csep = 0, ksep = 0, osep = 0, cnt = 0, rc; -uschar * cfile, * kfile, * ofile; -#ifndef DISABLE_OCSP -# ifdef SUPPORT_GNUTLS_EXT_RAW_PARSE -gnutls_x509_crt_fmt_t ocsp_fmt = GNUTLS_X509_FMT_DER; -# endif - -if (!expand_check(ocsp, US"tls_ocsp_file", &ofile, errstr)) - return DEFER; -olist = ofile; -#endif - -while (cfile = string_nextinlist(&clist, &csep, NULL, 0)) - - if (!(kfile = string_nextinlist(&klist, &ksep, NULL, 0))) - return tls_error(US"cert/key setup: out of keys", NULL, NULL, errstr); - else if ((rc = tls_add_certfile(state, NULL, cfile, kfile, errstr)) > 0) - return rc; - else - { - int gnutls_cert_index = -rc; - DEBUG(D_tls) debug_printf("TLS: cert/key %d %s registered\n", - gnutls_cert_index, cfile); - -#ifndef DISABLE_OCSP - if (ocsp) - { - /* Set the OCSP stapling server info */ - if (gnutls_buggy_ocsp) - { - DEBUG(D_tls) - debug_printf("GnuTLS library is buggy for OCSP; avoiding\n"); - } - else if ((ofile = string_nextinlist(&olist, &osep, NULL, 0))) - { - DEBUG(D_tls) debug_printf("OCSP response file %d = %s\n", - gnutls_cert_index, ofile); -# ifdef SUPPORT_GNUTLS_EXT_RAW_PARSE - if (Ustrncmp(ofile, US"PEM ", 4) == 0) - { - ocsp_fmt = GNUTLS_X509_FMT_PEM; - ofile += 4; - } - else if (Ustrncmp(ofile, US"DER ", 4) == 0) - { - ocsp_fmt = GNUTLS_X509_FMT_DER; - ofile += 4; - } - - if ((rc = gnutls_certificate_set_ocsp_status_request_file2( - state->lib_state.x509_cred, CCS ofile, gnutls_cert_index, - ocsp_fmt)) < 0) - return tls_error_gnu( - US"gnutls_certificate_set_ocsp_status_request_file2", - rc, NULL, errstr); - DEBUG(D_tls) - debug_printf(" %d response%s loaded\n", rc, rc>1 ? "s":""); - - /* Arrange callbacks for OCSP request observability */ - - if (state->session) - gnutls_handshake_set_hook_function(state->session, - GNUTLS_HANDSHAKE_ANY, GNUTLS_HOOK_POST, tls_server_hook_cb); - else - state->lib_state.ocsp_hook = TRUE; - - -# else -# if defined(SUPPORT_SRV_OCSP_STACK) - if ((rc = gnutls_certificate_set_ocsp_status_request_function2( - state->lib_state.x509_cred, gnutls_cert_index, - server_ocsp_stapling_cb, ofile))) - return tls_error_gnu( - US"gnutls_certificate_set_ocsp_status_request_function2", - rc, NULL, errstr); - else -# endif - { - if (cnt++ > 0) - { - DEBUG(D_tls) - debug_printf("oops; multiple OCSP files not supported\n"); - break; - } - gnutls_certificate_set_ocsp_status_request_function( - state->lib_state.x509_cred, server_ocsp_stapling_cb, ofile); - } -# endif /* SUPPORT_GNUTLS_EXT_RAW_PARSE */ - } - else - DEBUG(D_tls) debug_printf("ran out of OCSP response files in list\n"); - } -#endif /* DISABLE_OCSP */ - } -return 0; -#endif /*gnutls*/ -} - -static int -creds_load_client_certs(/*exim_gnutls_state_st * state,*/ const host_item * host, - const uschar * cert, const uschar * pkey, uschar ** errstr) -{ -return 0; -} - -static int -creds_load_cabundle(/*exim_gnutls_state_st * state,*/ const uschar * bundle, - const host_item * host, uschar ** errstr) -{ -#ifdef gnutls -int cert_count; -struct stat statbuf; - -#ifdef SUPPORT_SYSDEFAULT_CABUNDLE -if (Ustrcmp(bundle, "system") == 0 || Ustrncmp(bundle, "system,", 7) == 0) - cert_count = gnutls_certificate_set_x509_system_trust(state->lib_state.x509_cred); -else -#endif - { - if (Ustat(bundle, &statbuf) < 0) - { - log_write(0, LOG_MAIN|LOG_PANIC, "could not stat '%s' " - "(tls_verify_certificates): %s", bundle, strerror(errno)); - return DEFER; - } - -#ifndef SUPPORT_CA_DIR - /* The test suite passes in /dev/null; we could check for that path explicitly, - but who knows if someone has some weird FIFO which always dumps some certs, or - other weirdness. The thing we really want to check is that it's not a - directory, since while OpenSSL supports that, GnuTLS does not. - So s/!S_ISREG/S_ISDIR/ and change some messaging ... */ - if (S_ISDIR(statbuf.st_mode)) - { - log_write(0, LOG_MAIN|LOG_PANIC, - "tls_verify_certificates \"%s\" is a directory", bundle); - return DEFER; - } -#endif - - DEBUG(D_tls) debug_printf("verify certificates = %s size=" OFF_T_FMT "\n", - bundle, statbuf.st_size); - - if (statbuf.st_size == 0) - { - DEBUG(D_tls) - debug_printf("cert file empty, no certs, no verification, ignoring any CRL\n"); - return OK; - } - - cert_count = - -#ifdef SUPPORT_CA_DIR - (statbuf.st_mode & S_IFMT) == S_IFDIR - ? - gnutls_certificate_set_x509_trust_dir(state->lib_state.x509_cred, - CS bundle, GNUTLS_X509_FMT_PEM) - : -#endif - gnutls_certificate_set_x509_trust_file(state->lib_state.x509_cred, - CS bundle, GNUTLS_X509_FMT_PEM); - -#ifdef SUPPORT_CA_DIR - /* Mimic the behaviour with OpenSSL of not advertising a usable-cert list - when using the directory-of-certs config model. */ - - if ((statbuf.st_mode & S_IFMT) == S_IFDIR) - if (state->session) - gnutls_certificate_send_x509_rdn_sequence(state->session, 1); - else - state->lib_state.ca_rdn_emulate = TRUE; -#endif - } - -if (cert_count < 0) - return tls_error_gnu(US"setting certificate trust", cert_count, host, errstr); -DEBUG(D_tls) - debug_printf("Added %d certificate authorities\n", cert_count); - -#endif /*gnutls*/ -return OK; -} - - -static int -creds_load_crl(/*exim_gnutls_state_st * state,*/ const uschar * crl, uschar ** errstr) -{ -return FAIL; -} - - -static int -creds_load_pristring(/*exim_gnutls_state_st * state,*/ const uschar * p, - const char ** errpos) -{ -return FAIL; -} - static int server_load_ciphers(SSL_CTX * ctx, exim_openssl_state_st * state, uschar * ciphers, uschar ** errstr) @@ -1833,18 +1623,19 @@ return OK; } -static void +static unsigned tls_server_creds_init(void) { SSL_CTX * ctx; uschar * dummy_errstr; +unsigned lifetime = 0; tls_openssl_init(); state_server.lib_state = null_tls_preload; if (lib_ctx_new(&ctx, NULL, &dummy_errstr) != OK) - return; + return 0; state_server.lib_state.lib_ctx = ctx; /* Preload DH params and EC curve */ @@ -1862,7 +1653,7 @@ if (opt_unset_or_noexpand(tls_eccurve)) state_server.lib_state.ecdh = TRUE; } -#ifdef EXIM_HAVE_INOTIFY +#if defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT) /* If we can, preload the server-side cert, key and ocsp */ if ( opt_set_and_noexpand(tls_certificate) @@ -1872,8 +1663,7 @@ if ( opt_set_and_noexpand(tls_certificate) && opt_unset_or_noexpand(tls_privatekey)) { /* Set watches on the filenames. The implementation does de-duplication - so we can just blindly do them all. - */ + so we can just blindly do them all. */ if ( tls_set_watch(tls_certificate, TRUE) # ifndef DISABLE_OCSP @@ -1892,6 +1682,18 @@ if ( opt_set_and_noexpand(tls_certificate) state_server.lib_state.conn_certs = TRUE; } } +else if ( !tls_certificate && !tls_privatekey +# ifndef DISABLE_OCSP + && !tls_ocsp_file +#endif + ) + { /* Generate & preload a selfsigned cert. No files to watch. */ + if (tls_expand_session_files(ctx, &state_server, &dummy_errstr) == OK) + { + state_server.lib_state.conn_certs = TRUE; + lifetime = f.running_in_test_harness ? 2 : 60 * 60; /* 1 hour */ + } + } else DEBUG(D_tls) debug_printf("TLS: not preloading server certs\n"); @@ -1932,6 +1734,7 @@ if (opt_set_and_noexpand(tls_require_ciphers)) } else DEBUG(D_tls) debug_printf("TLS: not preloading cipher list for server\n"); +return lifetime; } @@ -1973,7 +1776,7 @@ if (opt_unset_or_noexpand(tls_eccurve)) ob->tls_preload.ecdh = TRUE; } -#ifdef EXIM_HAVE_INOTIFY +#if defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT) if ( opt_set_and_noexpand(ob->tls_certificate) && opt_unset_or_noexpand(ob->tls_privatekey)) { @@ -2026,7 +1829,7 @@ else } -#ifdef EXIM_HAVE_INOTIFY +#if defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT) /* Invalidate the creds cached, by dropping the current ones. Call when we notice one of the source files has changed. */ @@ -2045,6 +1848,17 @@ smtp_transport_options_block * ob = t->options_block; SSL_CTX_free(ob->tls_preload.lib_ctx); ob->tls_preload = null_tls_preload; } + +#else + +static void +tls_server_creds_invalidate(void) +{ return; } + +static void +tls_client_creds_invalidate(transport_instance * t) +{ return; } + #endif /*EXIM_HAVE_INOTIFY*/