From: Stefan Metzmacher Date: Mon, 12 Feb 2024 11:35:02 +0000 (+0100) Subject: s4:lib/tls: split out tstream_tls_prepare_gnutls() X-Git-Tag: tdb-1.4.11~988 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=60b11645b0d1c8304eabbb2aeca8a6b5190a3a2e;p=thirdparty%2Fsamba.git s4:lib/tls: split out tstream_tls_prepare_gnutls() Review with: git show --patience BUG: https://bugzilla.samba.org/show_bug.cgi?id=15621 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- diff --git a/source4/lib/tls/tls_tstream.c b/source4/lib/tls/tls_tstream.c index 347c47ed48e..9a69a015403 100644 --- a/source4/lib/tls/tls_tstream.c +++ b/source4/lib/tls/tls_tstream.c @@ -30,6 +30,7 @@ #include #include +#include "lib/crypto/gnutls_helpers.h" #define DH_BITS 2048 @@ -63,6 +64,8 @@ struct tstream_tls { gnutls_session_t tls_session; + bool is_server; + enum tls_verify_peer_state verify_peer; const char *peer_name; @@ -983,40 +986,28 @@ NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -struct tstream_tls_connect_state { - struct tstream_context *tls_stream; -}; - -struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct tstream_context *plain_stream, - struct tstream_tls_params *_tls_params, - const char *location) +static NTSTATUS tstream_tls_prepare_gnutls(struct tstream_tls_params *_tlsp, + struct tstream_tls *tlss) { - struct tevent_req *req; - struct tstream_tls_connect_state *state; - const char *error_pos; - struct tstream_tls *tlss; - struct tstream_tls_params_internal *tls_params = NULL; + struct tstream_tls_params_internal *tlsp = NULL; int ret; - unsigned int flags = GNUTLS_CLIENT; - - req = tevent_req_create(mem_ctx, &state, - struct tstream_tls_connect_state); - if (req == NULL) { - return NULL; - } + unsigned int flags; - state->tls_stream = tstream_context_create(state, - &tstream_tls_ops, - &tlss, - struct tstream_tls, - location); - if (tevent_req_nomem(state->tls_stream, req)) { - return tevent_req_post(req, ev); + if (tlss->is_server) { + flags = GNUTLS_SERVER; + } else { + flags = GNUTLS_CLIENT; +#ifdef GNUTLS_NO_TICKETS + /* + * tls_tstream can't properly handle 'New Session Ticket' + * messages sent 'after' the client sends the 'Finished' + * message. GNUTLS_NO_TICKETS was introduced in GnuTLS 3.5.6. + * This flag is to indicate the session Flag session should not + * use resumption with session tickets. + */ + flags |= GNUTLS_NO_TICKETS; +#endif } - ZERO_STRUCTP(tlss); - talloc_set_destructor(tlss, tstream_tls_destructor); /* * Note we need to make sure x509_cred and dh_params @@ -1028,71 +1019,109 @@ struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx, * * Note: here we use talloc_reference() in a way * that does not expose it to the caller. - * */ - tls_params = talloc_reference(tlss, _tls_params->internal); - if (tevent_req_nomem(tls_params, req)) { - return tevent_req_post(req, ev); + tlsp = talloc_reference(tlss, _tlsp->internal); + if (tlsp == NULL) { + return NT_STATUS_NO_MEMORY; } - tlss->plain_stream = plain_stream; - tlss->verify_peer = tls_params->verify_peer; - if (tls_params->peer_name != NULL) { - tlss->peer_name = talloc_strdup(tlss, tls_params->peer_name); - if (tevent_req_nomem(tlss->peer_name, req)) { - return tevent_req_post(req, ev); + tlss->verify_peer = tlsp->verify_peer; + if (tlsp->peer_name != NULL) { + tlss->peer_name = talloc_strdup(tlss, tlsp->peer_name); + if (tlss->peer_name == NULL) { + return NT_STATUS_NO_MEMORY; } } - tlss->current_ev = ev; - tlss->retry_im = tevent_create_immediate(tlss); - if (tevent_req_nomem(tlss->retry_im, req)) { - return tevent_req_post(req, ev); + if (tlss->current_ev != NULL) { + tlss->retry_im = tevent_create_immediate(tlss); + if (tlss->retry_im == NULL) { + return NT_STATUS_NO_MEMORY; + } } -#ifdef GNUTLS_NO_TICKETS - /* - * tls_tstream can't properly handle 'New Session Ticket' messages - * sent 'after' the client sends the 'Finished' message. - * GNUTLS_NO_TICKETS was introduced in GnuTLS 3.5.6. This flag is to - * indicate the session Flag session should not use resumption with - * session tickets. - */ - flags |= GNUTLS_NO_TICKETS; -#endif - ret = gnutls_init(&tlss->tls_session, flags); if (ret != GNUTLS_E_SUCCESS) { - DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret))); - tevent_req_error(req, EINVAL); - return tevent_req_post(req, ev); + return gnutls_error_to_ntstatus(ret, + NT_STATUS_CRYPTO_SYSTEM_INVALID); } ret = gnutls_set_default_priority(tlss->tls_session); if (ret != GNUTLS_E_SUCCESS) { - DBG_ERR("TLS %s - %s. Failed to set default priorities\n", - __location__, gnutls_strerror(ret)); - tevent_req_error(req, EINVAL); - return tevent_req_post(req, ev); + return gnutls_error_to_ntstatus(ret, + NT_STATUS_CRYPTO_SYSTEM_INVALID); } - if (strlen(tls_params->tls_priority) > 0) { + if (strlen(tlsp->tls_priority) > 0) { + const char *error_pos = NULL; + ret = gnutls_priority_set_direct(tlss->tls_session, - tls_params->tls_priority, + tlsp->tls_priority, &error_pos); if (ret != GNUTLS_E_SUCCESS) { - DEBUG(0,("TLS %s - %s. Check 'tls priority' option at '%s'\n", - __location__, gnutls_strerror(ret), error_pos)); - tevent_req_error(req, EINVAL); - return tevent_req_post(req, ev); + return gnutls_error_to_ntstatus(ret, + NT_STATUS_CRYPTO_SYSTEM_INVALID); } } ret = gnutls_credentials_set(tlss->tls_session, GNUTLS_CRD_CERTIFICATE, - tls_params->x509_cred); + tlsp->x509_cred); if (ret != GNUTLS_E_SUCCESS) { - DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret))); + return gnutls_error_to_ntstatus(ret, + NT_STATUS_CRYPTO_SYSTEM_INVALID); + } + + if (tlss->is_server) { + gnutls_certificate_server_set_request(tlss->tls_session, + GNUTLS_CERT_REQUEST); + gnutls_dh_set_prime_bits(tlss->tls_session, DH_BITS); + } + + return NT_STATUS_OK; +} + +struct tstream_tls_connect_state { + struct tstream_context *tls_stream; +}; + +struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct tstream_context *plain_stream, + struct tstream_tls_params *_tls_params, + const char *location) +{ + struct tevent_req *req; + struct tstream_tls_connect_state *state; + struct tstream_tls *tlss; + NTSTATUS status; + + req = tevent_req_create(mem_ctx, &state, + struct tstream_tls_connect_state); + if (req == NULL) { + return NULL; + } + + state->tls_stream = tstream_context_create(state, + &tstream_tls_ops, + &tlss, + struct tstream_tls, + location); + if (tevent_req_nomem(state->tls_stream, req)) { + return tevent_req_post(req, ev); + } + ZERO_STRUCTP(tlss); + talloc_set_destructor(tlss, tstream_tls_destructor); + tlss->plain_stream = plain_stream; + tlss->is_server = false; + tlss->current_ev = ev; + + status = tstream_tls_prepare_gnutls(_tls_params, tlss); + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) { + tevent_req_oom(req); + return tevent_req_post(req, ev); + } + if (!NT_STATUS_IS_OK(status)) { tevent_req_error(req, EINVAL); return tevent_req_post(req, ev); } @@ -1313,9 +1342,7 @@ struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx, struct tevent_req *req; struct tstream_tls_accept_state *state; struct tstream_tls *tlss; - const char *error_pos; - struct tstream_tls_params_internal *tlsp = NULL; - int ret; + NTSTATUS status; req = tevent_req_create(mem_ctx, &state, struct tstream_tls_accept_state); @@ -1333,70 +1360,20 @@ struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx, } ZERO_STRUCTP(tlss); talloc_set_destructor(tlss, tstream_tls_destructor); - - /* - * Note we need to make sure x509_cred and dh_params - * from tstream_tls_params_internal stay alive for - * the whole lifetime of this session! - * - * See 'man gnutls_credentials_set' and - * 'man gnutls_certificate_set_dh_params'. - * - * Note: here we use talloc_reference() in a way - * that does not expose it to the caller. - */ - tlsp = talloc_reference(tlss, _tlsp->internal); - if (tevent_req_nomem(tlsp, req)) { - return tevent_req_post(req, ev); - } - tlss->plain_stream = plain_stream; - + tlss->is_server = true; tlss->current_ev = ev; - tlss->retry_im = tevent_create_immediate(tlss); - if (tevent_req_nomem(tlss->retry_im, req)) { - return tevent_req_post(req, ev); - } - ret = gnutls_init(&tlss->tls_session, GNUTLS_SERVER); - if (ret != GNUTLS_E_SUCCESS) { - DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret))); - tevent_req_error(req, EINVAL); + status = tstream_tls_prepare_gnutls(_tlsp, tlss); + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) { + tevent_req_oom(req); return tevent_req_post(req, ev); } - - ret = gnutls_set_default_priority(tlss->tls_session); - if (ret != GNUTLS_E_SUCCESS) { - DBG_ERR("TLS %s - %s. Failed to set default priorities\n", - __location__, gnutls_strerror(ret)); + if (!NT_STATUS_IS_OK(status)) { tevent_req_error(req, EINVAL); return tevent_req_post(req, ev); } - if (strlen(tlsp->tls_priority) > 0) { - ret = gnutls_priority_set_direct(tlss->tls_session, - tlsp->tls_priority, - &error_pos); - if (ret != GNUTLS_E_SUCCESS) { - DEBUG(0,("TLS %s - %s. Check 'tls priority' option at '%s'\n", - __location__, gnutls_strerror(ret), error_pos)); - tevent_req_error(req, EINVAL); - return tevent_req_post(req, ev); - } - } - - ret = gnutls_credentials_set(tlss->tls_session, GNUTLS_CRD_CERTIFICATE, - tlsp->x509_cred); - if (ret != GNUTLS_E_SUCCESS) { - DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret))); - tevent_req_error(req, EINVAL); - return tevent_req_post(req, ev); - } - - gnutls_certificate_server_set_request(tlss->tls_session, - GNUTLS_CERT_REQUEST); - gnutls_dh_set_prime_bits(tlss->tls_session, DH_BITS); - gnutls_transport_set_ptr(tlss->tls_session, (gnutls_transport_ptr_t)state->tls_stream); gnutls_transport_set_pull_function(tlss->tls_session, diff --git a/source4/lib/tls/wscript_build b/source4/lib/tls/wscript_build index 7980a633574..8fe77da8489 100644 --- a/source4/lib/tls/wscript_build +++ b/source4/lib/tls/wscript_build @@ -8,6 +8,7 @@ bld.SAMBA_SUBSYSTEM('LIBTLS', public_deps=''' talloc gnutls + GNUTLS_HELPERS samba-hostconfig LIBTSOCKET tevent