aboutsummaryrefslogtreecommitdiffstats
path: root/common/rfb/CSecurityTLS.cxx
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2023-07-05 11:10:08 +0200
committerPierre Ossman <ossman@cendio.se>2023-07-05 14:23:53 +0200
commita2be8fbcc0d00a21ce2614c07e3f4af5523fe6d1 (patch)
treec7cce195a27bf4de2b04f18b12191d94f0fe5440 /common/rfb/CSecurityTLS.cxx
parentaf3dae278cc8974b980a72fa0c7679a5182c4a04 (diff)
downloadtigervnc-a2be8fbcc0d00a21ce2614c07e3f4af5523fe6d1.tar.gz
tigervnc-a2be8fbcc0d00a21ce2614c07e3f4af5523fe6d1.zip
Improve reporting of certificate errors
GnuTLS can help use translate certificate issues in to user presentable strings, so let's clean up that reporting.
Diffstat (limited to 'common/rfb/CSecurityTLS.cxx')
-rw-r--r--common/rfb/CSecurityTLS.cxx76
1 files changed, 44 insertions, 32 deletions
diff --git a/common/rfb/CSecurityTLS.cxx b/common/rfb/CSecurityTLS.cxx
index 6bdf720a..3081b7c9 100644
--- a/common/rfb/CSecurityTLS.cxx
+++ b/common/rfb/CSecurityTLS.cxx
@@ -46,6 +46,16 @@
#include <gnutls/x509.h>
+/*
+ * GNUTLS doesn't correctly export gnutls_free symbol which is
+ * a function pointer. Linking with Visual Studio 2008 Express will
+ * fail when you call gnutls_free().
+ */
+#if WIN32
+#undef gnutls_free
+#define gnutls_free free
+#endif
+
using namespace rfb;
static const char* homedirfn(const char* fn);
@@ -313,10 +323,40 @@ void CSecurityTLS::checkSession()
throw AuthFailureException("server certificate verification failed");
}
- if (status & GNUTLS_CERT_REVOKED)
- throw AuthFailureException("server certificate has been revoked");
+ if (status != 0) {
+ gnutls_datum_t status_str;
+ unsigned int fatal_status;
+
+ fatal_status = status & (~allowed_errors);
+
+ if (fatal_status != 0) {
+ std::string error;
+
+ if (gnutls_certificate_verification_status_print(fatal_status,
+ GNUTLS_CRT_X509,
+ &status_str,
+ 0) < 0)
+ throw Exception("Failed to get certificate error description");
+
+ error = format("Invalid server certificate: %s", status_str.data);
+
+ gnutls_free(status_str.data);
- /* Process other errors later */
+ throw AuthFailureException(error.c_str());
+ }
+
+ if (gnutls_certificate_verification_status_print(status,
+ GNUTLS_CRT_X509,
+ &status_str,
+ 0) < 0)
+ throw Exception("Failed to get certificate error description");
+
+ vlog.info("Server certificate errors: %s", status_str.data);
+
+ gnutls_free(status_str.data);
+ }
+
+ /* Process overridable errors later */
cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
if (!cert_list_size)
@@ -346,27 +386,8 @@ void CSecurityTLS::checkSession()
gnutls_x509_crt_deinit(crt);
return;
}
-
- if (status & GNUTLS_CERT_INVALID)
- vlog.debug("server certificate invalid");
- if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
- vlog.debug("server cert signer not found");
- if (status & GNUTLS_CERT_SIGNER_NOT_CA)
- vlog.debug("server cert signer not CA");
- if (status & GNUTLS_CERT_NOT_ACTIVATED)
- vlog.debug("server certificate has not yet been activated");
- if (status & GNUTLS_CERT_EXPIRED)
- vlog.debug("server certificate has expired");
- if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
- vlog.debug("server certificate uses an insecure algorithm");
-
- if ((status & (~allowed_errors)) != 0) {
- /* No other errors are allowed */
- vlog.debug("GNUTLS status of certificate verification: 0x%x", status);
- throw AuthFailureException("Invalid status of server certificate verification");
- }
- /* Certificate is fine, except we don't know the issuer, so TOFU time */
+ /* Certificate has some user overridable problems, so TOFU time */
homeDir = os::getvnchomedir();
if (homeDir == NULL) {
@@ -599,15 +620,6 @@ void CSecurityTLS::checkSession()
vlog.error("Failed to store server certificate to known hosts database");
gnutls_x509_crt_deinit(crt);
- /*
- * GNUTLS doesn't correctly export gnutls_free symbol which is
- * a function pointer. Linking with Visual Studio 2008 Express will
- * fail when you call gnutls_free().
- */
-#if WIN32
- free(info.data);
-#else
gnutls_free(info.data);
-#endif
}