From 939fd116824b78c4ff0010ba4f0c8eda1180de64 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 8 Jan 2025 14:56:42 -0800 Subject: [PATCH] Refactor: libcrmcommon: Use gnutls_session_set_verify_cert() Instead of calling gnutls_certificate_set_verify_function() with the custom callback verify_peer_cert(). gnutls_session_set_verify_cert() is available since GnuTLS 3.4.6. It sets a verify function for the entire session, overriding any verify function set for a particular certificate (for example, using gnutls_certificate_set_verify_function()). For our purposes, each session has a unique certificate anyway, so the effect is the same either way. gnutls_session_set_verify_cert() sets up a verify callback function automatically, using hostname and flags parameters. At the time of this commit, it's called auto_verify_cb(); it calls gnutls_certificate_verify_peers() or a related function and returns 0 on success or GNUTLS_E_CERTIFICATE_ERROR or GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR on error. * Our verify_peer_cert() function passes NULL to gnutls_certificate_verify_peers3() to disable hostname verification. Accordingly, we pass NULL to gnutls_session_set_verify_cert(). * We don't currently override the default verify flags (which would have required a call to gnutls_certificate_set_verify_flags()). So we pass 0 for the flags argument here, which says to use the defaults. There will be changes in the output upon error, as we lose our custom error processing from verify_peer_cert(), but that seems acceptable. Closes T967 Signed-off-by: Reid Wahl --- lib/common/tls.c | 46 ++-------------------------------------------- 1 file changed, 2 insertions(+), 44 deletions(-) diff --git a/lib/common/tls.c b/lib/common/tls.c index dbf34898975..2bdd2aab927 100644 --- a/lib/common/tls.c +++ b/lib/common/tls.c @@ -99,44 +99,6 @@ tls_load_x509_data(pcmk__tls_t *tls) return pcmk_rc_ok; } -/*! - * \internal - * \brief Verify a peer's certificate - * - * \return 0 if the certificate is trusted and the gnutls handshake should - * continue, -1 otherwise - */ -static int -verify_peer_cert(gnutls_session_t session) -{ - int rc; - int type; - unsigned int status; - gnutls_datum_t out; - - /* NULL = no hostname comparison will be performed */ - rc = gnutls_certificate_verify_peers3(session, NULL, &status); - - /* Success means it was able to perform the verification. We still have - * to check status to see whether the cert is valid or not. - */ - if (rc != GNUTLS_E_SUCCESS) { - crm_err("Failed to verify peer certificate: %s", gnutls_strerror(rc)); - return -1; - } - - if (status == 0) { - /* The certificate is trusted. */ - return 0; - } - - type = gnutls_certificate_type_get(session); - gnutls_certificate_verification_status_print(status, type, &out, 0); - crm_err("Peer certificate invalid: %s", out.data); - gnutls_free(out.data); - return GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR; -} - static void _gnutls_log_func(int level, const char *msg) { @@ -368,12 +330,8 @@ pcmk__new_tls_session(pcmk__tls_t *tls, int csock) gnutls_certificate_server_set_request(session, GNUTLS_CERT_REQUIRE); } - /* Register a function to verify the peer's certificate. - * - * FIXME: When we can require gnutls >= 3.4.6, remove verify_peer_cert - * and use gnutls_session_set_verify_cert instead. - */ - gnutls_certificate_set_verify_function(tls->credentials.cert, verify_peer_cert); + // Register a function to verify the peer's certificate + gnutls_session_set_verify_cert(session, NULL, 0); } return session;