X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Ftls-gnu.c;h=44a20adf83a499a5fcdf00d8f4e2344d11886384;hb=c09dbcfb71f4b9a42cbfd8a20e0be6bfa1b12488;hp=7d52369e0604ea82fab16f2eeb3dd6bf3a937f54;hpb=ffc3d145e3819e1a3762caa1bbe8b07e723fbaf2;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index 7d52369e0..44a20adf8 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -238,7 +238,7 @@ static gnutls_dh_params_t dh_server_params = NULL; static const int ssl_session_timeout = 200; -static const char * const exim_default_gnutls_priority = "NORMAL"; +static const uschar * const exim_default_gnutls_priority = US"NORMAL"; /* Guard library core initialisation */ @@ -362,7 +362,7 @@ Argument: state the current GnuTLS exim state container rc the GnuTLS error code, or 0 if it's a local error when text identifying read or write - text local error text when ec is 0 + text local error text when rc is 0 Returns: nothing */ @@ -374,7 +374,7 @@ const uschar * msg; uschar * errstr; if (rc == GNUTLS_E_FATAL_ALERT_RECEIVED) - msg = string_sprintf("%s: %s", US gnutls_strerror(rc), + msg = string_sprintf("A TLS fatal alert has been received: %s", US gnutls_alert_get_name(gnutls_alert_get(state->session))); else msg = US gnutls_strerror(rc); @@ -1287,7 +1287,6 @@ int rc; size_t sz; const char *errpos; uschar *p; -BOOL want_default_priorities; if (!exim_gnutls_base_init_done) { @@ -1313,7 +1312,7 @@ if (!exim_gnutls_base_init_done) DEBUG(D_tls) { gnutls_global_set_log_function(exim_gnutls_logger_cb); - /* arbitrarily chosen level; bump upto 9 for more */ + /* arbitrarily chosen level; bump up to 9 for more */ gnutls_global_set_log_level(EXIM_GNUTLS_LIBRARY_LOG_LEVEL); } #endif @@ -1396,32 +1395,24 @@ and replaces gnutls_require_kx, gnutls_require_mac & gnutls_require_protocols. This was backwards incompatible, but means Exim no longer needs to track all algorithms and provide string forms for them. */ -want_default_priorities = TRUE; - +p = NULL; if (state->tls_require_ciphers && *state->tls_require_ciphers) { if (!expand_check_tlsvar(tls_require_ciphers, errstr)) return DEFER; if (state->exp_tls_require_ciphers && *state->exp_tls_require_ciphers) { - DEBUG(D_tls) debug_printf("GnuTLS session cipher/priority \"%s\"\n", - state->exp_tls_require_ciphers); - - rc = gnutls_priority_init(&state->priority_cache, - CS state->exp_tls_require_ciphers, &errpos); - want_default_priorities = FALSE; p = state->exp_tls_require_ciphers; + DEBUG(D_tls) debug_printf("GnuTLS session cipher/priority \"%s\"\n", p); } } -if (want_default_priorities) +if (!p) { + p = exim_default_gnutls_priority; DEBUG(D_tls) - debug_printf("GnuTLS using default session cipher/priority \"%s\"\n", - exim_default_gnutls_priority); - rc = gnutls_priority_init(&state->priority_cache, - exim_default_gnutls_priority, &errpos); - p = US exim_default_gnutls_priority; + debug_printf("GnuTLS using default session cipher/priority \"%s\"\n", p); } +rc = gnutls_priority_init(&state->priority_cache, CCS p, &errpos); exim_gnutls_err_check(rc, string_sprintf( "gnutls_priority_init(%s) failed at offset %ld, \"%.6s..\"", @@ -1557,10 +1548,9 @@ if (!cert_list || cert_list_size == 0) return OK; } -ct = gnutls_certificate_type_get(state->session); -if (ct != GNUTLS_CRT_X509) +if ((ct = gnutls_certificate_type_get(state->session)) != GNUTLS_CRT_X509) { - const uschar *ctn = US gnutls_certificate_type_get_name(ct); + const uschar * ctn = US 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) @@ -1636,7 +1626,7 @@ if (state->verify_requirement == VERIFY_NONE) DEBUG(D_tls) debug_printf("TLS: checking peer certificate\n"); *errstr = NULL; -if ((rc = peer_status(state, errstr)) != OK) +if ((rc = peer_status(state, errstr)) != OK || !state->peerdn) { verify = GNUTLS_CERT_INVALID; *errstr = US"certificate not supplied"; @@ -2334,36 +2324,29 @@ return TRUE; /* Called from the smtp transport after STARTTLS has been accepted. Arguments: - fd the fd of the connection - host connected host (for messages and option-tests) - addr the first address (not used) - tb transport (always smtp) - tlsa_dnsa non-NULL, either request or require dane for this host, and - a TLSA record found. Therefore, dane verify required. - Which implies cert must be requested and supplied, dane - verify must pass, and cert verify irrelevant (incl. - hostnames), and (caller handled) require_tls - tlsp record details of channel configuration - errstr error string pointer - -Returns: Pointer to TLS session context, or NULL on error + cctx connection context + conn_args connection details + cookie datum for randomness (not used) + tlsp record details of channel configuration here; must be non-NULL + errstr error string pointer + +Returns: TRUE for success with TLS session context set in smtp context, + FALSE on error */ -void * -tls_client_start(int fd, host_item *host, - address_item *addr ARG_UNUSED, - transport_instance * tb, -#ifdef SUPPORT_DANE - dns_answer * tlsa_dnsa, -#endif - tls_support * tlsp, uschar ** errstr) +BOOL +tls_client_start(client_conn_ctx * cctx, smtp_connect_args * conn_args, + void * cookie ARG_UNUSED, + tls_support * tlsp, uschar ** errstr) { -smtp_transport_options_block *ob = tb +host_item * host = conn_args->host; /* for msgs and option-tests */ +transport_instance * tb = conn_args->tblock; /* always smtp or NULL */ +smtp_transport_options_block * ob = tb ? (smtp_transport_options_block *)tb->options_block : &smtp_transport_option_defaults; int rc; exim_gnutls_state_st * state = NULL; -uschar *cipher_list = NULL; +uschar * cipher_list = NULL; #ifndef DISABLE_OCSP BOOL require_ocsp = @@ -2372,15 +2355,20 @@ BOOL request_ocsp = require_ocsp ? TRUE : verify_check_given_host(CUSS &ob->hosts_request_ocsp, host) == OK; #endif -DEBUG(D_tls) debug_printf("initialising GnuTLS as a client on fd %d\n", fd); +DEBUG(D_tls) debug_printf("initialising GnuTLS as a client on fd %d\n", cctx->sock); #ifdef SUPPORT_DANE -if (tlsa_dnsa && ob->dane_require_tls_ciphers) +/* If dane is flagged, have either request or require dane for this host, and +a TLSA record found. Therefore, dane verify required. Which implies cert must +be requested and supplied, dane verify must pass, and cert verify irrelevant +(incl. hostnames), and (caller handled) require_tls */ + +if (conn_args->dane && ob->dane_require_tls_ciphers) { /* not using expand_check_tlsvar because not yet in state */ if (!expand_check(ob->dane_require_tls_ciphers, US"dane_require_tls_ciphers", &cipher_list, errstr)) - return NULL; + return FALSE; cipher_list = cipher_list && *cipher_list ? ob->dane_require_tls_ciphers : ob->tls_require_ciphers; } @@ -2392,7 +2380,7 @@ if (!cipher_list) if (tls_init(host, ob->tls_certificate, ob->tls_privatekey, ob->tls_sni, ob->tls_verify_certificates, ob->tls_crl, cipher_list, &state, tlsp, errstr) != OK) - return NULL; + return FALSE; { int dh_min_bits = ob->tls_dh_min_bits; @@ -2416,7 +2404,7 @@ set but both tls_verify_hosts and tls_try_verify_hosts are unset. Check only the specified host patterns if one of them is defined */ #ifdef SUPPORT_DANE -if (tlsa_dnsa && dane_tlsa_load(state, tlsa_dnsa)) +if (conn_args->dane && dane_tlsa_load(state, &conn_args->tlsa_dnsa)) { DEBUG(D_tls) debug_printf("TLS: server certificate DANE required.\n"); @@ -2463,7 +2451,7 @@ if (request_ocsp) NULL, 0, NULL)) != OK) { tls_error(US"cert-status-req", US gnutls_strerror(rc), state->host, errstr); - return NULL; + return FALSE; } tlsp->ocsp = OCSP_NOT_RESP; } @@ -2478,9 +2466,9 @@ if (tb && tb->event_action) } #endif -gnutls_transport_set_ptr(state->session, (gnutls_transport_ptr_t)(long) fd); -state->fd_in = fd; -state->fd_out = fd; +gnutls_transport_set_ptr(state->session, (gnutls_transport_ptr_t)(long) cctx->sock); +state->fd_in = cctx->sock; +state->fd_out = cctx->sock; DEBUG(D_tls) debug_printf("about to gnutls_handshake\n"); /* There doesn't seem to be a built-in timeout on connection. */ @@ -2501,7 +2489,7 @@ if (rc != GNUTLS_E_SUCCESS) } else tls_error(US"gnutls_handshake", US gnutls_strerror(rc), state->host, errstr); - return NULL; + return FALSE; } DEBUG(D_tls) @@ -2528,7 +2516,7 @@ DEBUG(D_tls) if (!verify_certificate(state, errstr)) { tls_error(US"certificate verification failed", *errstr, state->host, errstr); - return NULL; + return FALSE; } #ifndef DISABLE_OCSP @@ -2556,7 +2544,7 @@ if (require_ocsp) { tlsp->ocsp = OCSP_FAILED; tls_error(US"certificate status check failed", NULL, state->host, errstr); - return NULL; + return FALSE; } DEBUG(D_tls) debug_printf("Passed OCSP checking\n"); tlsp->ocsp = OCSP_VFIED; @@ -2566,13 +2554,14 @@ if (require_ocsp) /* Figure out peer DN, and if authenticated, etc. */ if (peer_status(state, errstr) != OK) - return NULL; + return FALSE; /* Sets various Exim expansion variables; may need to adjust for ACL callouts */ extract_exim_vars_from_tls_state(state); -return state; +cctx->tls_ctx = state; +return TRUE; } @@ -2695,7 +2684,7 @@ else if (inbytes == 0) else if (inbytes < 0) { - DEBUG(D_tls) debug_printf("%s: err from gnutls_record_recv(\n", __FUNCTION__); + DEBUG(D_tls) debug_printf("%s: err from gnutls_record_recv\n", __FUNCTION__); record_io_error(state, (int) inbytes, US"recv", NULL); state->xfer_error = TRUE; return FALSE; @@ -2718,7 +2707,7 @@ Only used by the server-side TLS. This feeds DKIM and should be used for all message-body reads. -Arguments: lim Maximum amount to read/bufffer +Arguments: lim Maximum amount to read/buffer Returns: the next character or EOF */ @@ -2828,7 +2817,7 @@ if (inbytes == 0) } else { - DEBUG(D_tls) debug_printf("%s: err from gnutls_record_recv(\n", __FUNCTION__); + DEBUG(D_tls) debug_printf("%s: err from gnutls_record_recv\n", __FUNCTION__); record_io_error(state, (int)inbytes, US"recv", NULL); }