tlshd: Send fatal alert to client when there are server config issues
Resolves: RHEL-128086 Signed-off-by: Scott Mayhew <smayhew@redhat.com>
This commit is contained in:
parent
b7d9966184
commit
c943e3e1a9
@ -0,0 +1,44 @@
|
||||
From b52ca7c0a9c167340950a10d8dc56be1b95f5c40 Mon Sep 17 00:00:00 2001
|
||||
From: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Tue, 23 Sep 2025 19:30:16 -0400
|
||||
Subject: [PATCH] tlshd: Clean up logic in tlshd_start_tls_handshake()
|
||||
|
||||
gnutls_handshake() is supposed to return only a GNUTLS_E value, and
|
||||
the session_status field is supposed to contain only a positive
|
||||
errno.
|
||||
|
||||
GNUTLS_E_PREMATURE_TERMINATION is -110. It turns out that on x86,
|
||||
-ETIMEDOUT is also -110. Make sure the correct symbolic constants
|
||||
and auditing functions are utilized.
|
||||
|
||||
Fixes: b010190cfed2 ("tlshd: Pass ETIMEDOUT from gnutls to kernel")
|
||||
Reviewed-by: Benjamin Coddington <bcodding@redhat.com>
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
---
|
||||
src/tlshd/handshake.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/tlshd/handshake.c b/src/tlshd/handshake.c
|
||||
index 5a28939..f688932 100644
|
||||
--- a/src/tlshd/handshake.c
|
||||
+++ b/src/tlshd/handshake.c
|
||||
@@ -97,12 +97,12 @@ void tlshd_start_tls_handshake(gnutls_session_t session,
|
||||
case GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR:
|
||||
tlshd_log_cert_verification_error(session);
|
||||
break;
|
||||
- case -ETIMEDOUT:
|
||||
- tlshd_log_gnutls_error(ret);
|
||||
- parms->session_status = -ret;
|
||||
+ case GNUTLS_E_PREMATURE_TERMINATION:
|
||||
+ tlshd_log_error("Handshake timeout, retrying");
|
||||
+ parms->session_status = ETIMEDOUT;
|
||||
break;
|
||||
default:
|
||||
- tlshd_log_notice("tlshd_start_tls_handshake unhandled error %d, returning EACCES\n", ret);
|
||||
+ tlshd_log_gnutls_error(ret);
|
||||
}
|
||||
return;
|
||||
}
|
||||
--
|
||||
2.52.0
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
From 9e79a86b85748ba4888da49652986b09beac2459 Mon Sep 17 00:00:00 2001
|
||||
From: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Thu, 5 Feb 2026 14:40:28 -0500
|
||||
Subject: [PATCH] tlshd: Fix session leak on error paths in x509 server
|
||||
handshake
|
||||
|
||||
Conflicts: src/tlshd/server.c - context difference in
|
||||
tlshd_tls13_server_x509_handshake() because RHEL10 doesn't have
|
||||
f11519a ("tlshd: Match ingress certificates with defined TLS session
|
||||
tags")
|
||||
|
||||
After gnutls_init() succeeds, the error paths for gnutls_credentials_set()
|
||||
and tlshd_gnutls_priority_set() failures jump to out_free_certs without
|
||||
calling gnutls_deinit(session), leaking the session object.
|
||||
|
||||
Introduce an out_deinit_session label so all post-init error paths
|
||||
properly release the session before cleaning up certificates and
|
||||
credentials.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
---
|
||||
src/tlshd/server.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/tlshd/server.c b/src/tlshd/server.c
|
||||
index 4850210..3bfcca3 100644
|
||||
--- a/src/tlshd/server.c
|
||||
+++ b/src/tlshd/server.c
|
||||
@@ -424,7 +424,7 @@ static void tlshd_tls13_server_x509_handshake(struct tlshd_handshake_parms *parm
|
||||
ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);
|
||||
if (ret != GNUTLS_E_SUCCESS) {
|
||||
tlshd_log_gnutls_error(ret);
|
||||
- goto out_free_certs;
|
||||
+ goto out_deinit_session;
|
||||
}
|
||||
gnutls_certificate_set_verify_function(xcred,
|
||||
tlshd_tls13_server_x509_verify_function);
|
||||
@@ -433,7 +433,7 @@ static void tlshd_tls13_server_x509_handshake(struct tlshd_handshake_parms *parm
|
||||
ret = tlshd_gnutls_priority_set(session, parms, 0);
|
||||
if (ret) {
|
||||
tlshd_log_gnutls_error(ret);
|
||||
- goto out_free_certs;
|
||||
+ goto out_deinit_session;
|
||||
}
|
||||
|
||||
tlshd_start_tls_handshake(session, parms);
|
||||
@@ -373,6 +373,7 @@ static void tlshd_tls13_server_x509_hand
|
||||
}
|
||||
}
|
||||
|
||||
+out_deinit_session:
|
||||
gnutls_deinit(session);
|
||||
|
||||
out_free_certs:
|
||||
--
|
||||
2.52.0
|
||||
|
||||
@ -0,0 +1,185 @@
|
||||
From a58a3600f35c16e435cdda476fe7ca0554a0a466 Mon Sep 17 00:00:00 2001
|
||||
From: Scott Mayhew <smayhew@redhat.com>
|
||||
Date: Thu, 5 Feb 2026 12:28:43 -0500
|
||||
Subject: [PATCH] tlshd: Send fatal alert to client when there are server
|
||||
config issues
|
||||
|
||||
Conflicts: src/tlshd/log.c - context difference because RHEL10 doesn't
|
||||
have ff28f1f ("tlshd: Translate kernel-style Doxygen comments in
|
||||
src/tlshd/log.c")
|
||||
|
||||
Currently if a client attempts an x.509 handshake and the server is
|
||||
misconfigured (no certificates, no private keys, etc), the server simply
|
||||
closes the connection. Prior to b010190 ("tlshd: Pass ETIMEDOUT from
|
||||
gnutls to kernel"), this would result in a quick failure on the client.
|
||||
Now the client keeps retrying until the mount program times out, which
|
||||
takes several minutes.
|
||||
|
||||
A misconfigured server isn't a self-correcting problem, so send a fatal
|
||||
alert to the client when this occurs so the client stops retrying
|
||||
immediately. This requires some minor refactoring of
|
||||
tlshd_tls13_server_x509_handshake() so that the session is initialized
|
||||
before attempting to load the certs and keys (otherwise it is not
|
||||
possible to send an alert). Also log an error message to help the
|
||||
admin take corrective action.
|
||||
|
||||
Finally add some logging when an alert is received during the handshake.
|
||||
Following suit with handshake completions, alerts will only be logged if
|
||||
debug logging is enabled.
|
||||
|
||||
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
---
|
||||
src/tlshd/handshake.c | 4 ++++
|
||||
src/tlshd/log.c | 15 ++++++++++++
|
||||
src/tlshd/server.c | 55 ++++++++++++++++++++++++-------------------
|
||||
src/tlshd/tlshd.h | 1 +
|
||||
4 files changed, 51 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/src/tlshd/handshake.c b/src/tlshd/handshake.c
|
||||
index e78f78f..511a369 100644
|
||||
--- a/src/tlshd/handshake.c
|
||||
+++ b/src/tlshd/handshake.c
|
||||
@@ -115,6 +115,10 @@ void tlshd_start_tls_handshake(gnutls_session_t session,
|
||||
tlshd_log_error("Handshake timeout, retrying");
|
||||
parms->session_status = ETIMEDOUT;
|
||||
break;
|
||||
+ case GNUTLS_E_WARNING_ALERT_RECEIVED:
|
||||
+ case GNUTLS_E_FATAL_ALERT_RECEIVED:
|
||||
+ tlshd_log_alert(session);
|
||||
+ break;
|
||||
default:
|
||||
tlshd_log_gnutls_error(ret);
|
||||
}
|
||||
diff --git a/src/tlshd/log.c b/src/tlshd/log.c
|
||||
index b70d4af..a890b60 100644
|
||||
--- a/src/tlshd/log.c
|
||||
+++ b/src/tlshd/log.c
|
||||
@@ -178,6 +178,21 @@ void tlshd_log_cert_verification_error(g
|
||||
}
|
||||
|
||||
/**
|
||||
+ * @brief Report a TLS alert
|
||||
+ * @param[in] session Controlling GnuTLS session
|
||||
+ */
|
||||
+void tlshd_log_alert(gnutls_session_t session)
|
||||
+{
|
||||
+ gnutls_alert_description_t alert;
|
||||
+
|
||||
+ if (!tlshd_debug)
|
||||
+ return;
|
||||
+
|
||||
+ alert = gnutls_alert_get(session);
|
||||
+ tlshd_log_notice("Received alert: %s", gnutls_alert_get_name(alert));
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
* tlshd_log_gnutls_error - Emit "library call failed" notification
|
||||
* @error: GnuTLS error code to log
|
||||
*
|
||||
diff --git a/src/tlshd/server.c b/src/tlshd/server.c
|
||||
index 3bfcca3..8e0f192 100644
|
||||
--- a/src/tlshd/server.c
|
||||
+++ b/src/tlshd/server.c
|
||||
@@ -397,29 +397,46 @@ static void tlshd_tls13_server_x509_handshake(struct tlshd_handshake_parms *parm
|
||||
gnutls_session_t session;
|
||||
int ret;
|
||||
|
||||
- ret = gnutls_certificate_allocate_credentials(&xcred);
|
||||
+ ret = gnutls_init(&session, GNUTLS_SERVER);
|
||||
if (ret != GNUTLS_E_SUCCESS) {
|
||||
tlshd_log_gnutls_error(ret);
|
||||
return;
|
||||
}
|
||||
- ret = tlshd_server_get_truststore(xcred);
|
||||
- if (ret != GNUTLS_E_SUCCESS)
|
||||
- goto out_free_creds;
|
||||
+ gnutls_transport_set_int(session, parms->sockfd);
|
||||
+ gnutls_session_set_ptr(session, parms);
|
||||
|
||||
- if (!tlshd_x509_server_get_certs(parms))
|
||||
- goto out_free_creds;
|
||||
- if (!tlshd_x509_server_get_privkey(parms))
|
||||
- goto out_free_certs;
|
||||
- gnutls_certificate_set_retrieve_function2(xcred,
|
||||
- tlshd_x509_retrieve_key_cb);
|
||||
+ ret = tlshd_gnutls_priority_set(session, parms, 0);
|
||||
+ if (ret) {
|
||||
+ tlshd_log_gnutls_error(ret);
|
||||
+ gnutls_deinit(session);
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
- ret = gnutls_init(&session, GNUTLS_SERVER);
|
||||
+ ret = gnutls_certificate_allocate_credentials(&xcred);
|
||||
if (ret != GNUTLS_E_SUCCESS) {
|
||||
tlshd_log_gnutls_error(ret);
|
||||
- goto out_free_certs;
|
||||
+ gnutls_deinit(session);
|
||||
+ return;
|
||||
}
|
||||
- gnutls_transport_set_int(session, parms->sockfd);
|
||||
- gnutls_session_set_ptr(session, parms);
|
||||
+ ret = tlshd_server_get_truststore(xcred);
|
||||
+ if (ret != GNUTLS_E_SUCCESS) {
|
||||
+ tlshd_log_error("Failed to initialize server trust store - check the configuration");
|
||||
+ gnutls_alert_send(session, GNUTLS_AL_FATAL, GNUTLS_A_ACCESS_DENIED);
|
||||
+ goto out_deinit_session;
|
||||
+ }
|
||||
+
|
||||
+ if (!tlshd_x509_server_get_certs(parms)) {
|
||||
+ tlshd_log_error("No usable server certificates were found - check the configuration");
|
||||
+ gnutls_alert_send(session, GNUTLS_AL_FATAL, GNUTLS_A_ACCESS_DENIED);
|
||||
+ goto out_deinit_session;
|
||||
+ }
|
||||
+ if (!tlshd_x509_server_get_privkey(parms)) {
|
||||
+ tlshd_log_error("No usable private keys were found - check the configuration");
|
||||
+ gnutls_alert_send(session, GNUTLS_AL_FATAL, GNUTLS_A_ACCESS_DENIED);
|
||||
+ goto out_deinit_session;
|
||||
+ }
|
||||
+ gnutls_certificate_set_retrieve_function2(xcred,
|
||||
+ tlshd_x509_retrieve_key_cb);
|
||||
|
||||
ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);
|
||||
if (ret != GNUTLS_E_SUCCESS) {
|
||||
@@ -430,12 +447,6 @@ static void tlshd_tls13_server_x509_handshake(struct tlshd_handshake_parms *parm
|
||||
tlshd_tls13_server_x509_verify_function);
|
||||
gnutls_certificate_server_set_request(session, GNUTLS_CERT_REQUEST);
|
||||
|
||||
- ret = tlshd_gnutls_priority_set(session, parms, 0);
|
||||
- if (ret) {
|
||||
- tlshd_log_gnutls_error(ret);
|
||||
- goto out_deinit_session;
|
||||
- }
|
||||
-
|
||||
tlshd_start_tls_handshake(session, parms);
|
||||
|
||||
if (tlshd_debug &&
|
||||
@@ -464,12 +475,8 @@ static void tlshd_tls13_server_x509_handshake(struct tlshd_handshake_parms *parm
|
||||
|
||||
out_deinit_session:
|
||||
gnutls_deinit(session);
|
||||
-
|
||||
-out_free_certs:
|
||||
tlshd_x509_server_put_privkey();
|
||||
tlshd_x509_server_put_certs();
|
||||
-
|
||||
-out_free_creds:
|
||||
gnutls_certificate_free_credentials(xcred);
|
||||
}
|
||||
|
||||
diff --git a/src/tlshd/tlshd.h b/src/tlshd/tlshd.h
|
||||
index 75d9a4a..d00cfdf 100644
|
||||
--- a/src/tlshd/tlshd.h
|
||||
+++ b/src/tlshd/tlshd.h
|
||||
@@ -118,6 +118,7 @@ extern void tlshd_log_perror(const char *prefix);
|
||||
extern void tlshd_log_gai_error(int error);
|
||||
|
||||
extern void tlshd_log_cert_verification_error(gnutls_session_t session);
|
||||
+extern void tlshd_log_alert(gnutls_session_t session);
|
||||
extern void tlshd_log_gnutls_error(int error);
|
||||
extern void tlshd_gnutls_log_func(int level, const char *msg);
|
||||
extern void tlshd_gnutls_audit_func(gnutls_session_t session, const char *msg);
|
||||
--
|
||||
2.52.0
|
||||
|
||||
@ -16,10 +16,16 @@ URL: %{forgeurl}
|
||||
# FIXME: is this a bug in the tagging scheme or forgesource macro?
|
||||
Source0: %{forgeurl}/releases/download/%{name}-%{baseversion}/%{name}-%{baseversion}.tar.gz
|
||||
|
||||
#
|
||||
# RHEL10.2
|
||||
#
|
||||
Patch0: ktls-utils-1.2.1-tlshd-deduplicate-client-and-server-config-functions.patch
|
||||
Patch1: ktls-utils-1.2.1-tlshd-Fix-priority-string-to-allow-PQC.patch
|
||||
Patch2: ktls-utils-1.2.1-tlshd-Server-side-dual-certificate-support.patch
|
||||
Patch3: ktls-utils-1.2.1-tlshd-Client-side-dual-certificate-support.patch
|
||||
Patch4: ktls-utils-1.2.1-tlshd-Clean-up-logic-in-tlshd_start_tls_handshake.patch
|
||||
Patch5: ktls-utils-1.2.1-tlshd-Fix-session-leak-on-error-paths-in-x509-server.patch
|
||||
Patch6: ktls-utils-1.2.1-tlshd-Send-fatal-alert-to-client-when-there-are-serv.patch
|
||||
|
||||
BuildRequires: bash systemd-rpm-macros
|
||||
BuildRequires: gcc make coreutils
|
||||
|
||||
Loading…
Reference in New Issue
Block a user