aboutsummaryrefslogtreecommitdiffstats
path: root/common/rfb/SSecurityTLS.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'common/rfb/SSecurityTLS.cxx')
-rw-r--r--common/rfb/SSecurityTLS.cxx102
1 files changed, 30 insertions, 72 deletions
diff --git a/common/rfb/SSecurityTLS.cxx b/common/rfb/SSecurityTLS.cxx
index 2e173771..17497b8e 100644
--- a/common/rfb/SSecurityTLS.cxx
+++ b/common/rfb/SSecurityTLS.cxx
@@ -2,7 +2,7 @@
* Copyright (C) 2004 Red Hat Inc.
* Copyright (C) 2005 Martin Koegler
* Copyright (C) 2010 TigerVNC Team
- * Copyright (C) 2012-2021 Pierre Ossman for Cendio AB
+ * Copyright 2012-2025 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -37,8 +37,7 @@
#include <rfb/Exception.h>
#include <rdr/TLSException.h>
-#include <rdr/TLSInStream.h>
-#include <rdr/TLSOutStream.h>
+#include <rdr/TLSSocket.h>
#include <gnutls/x509.h>
@@ -72,7 +71,7 @@ static core::LogWriter vlog("TLS");
SSecurityTLS::SSecurityTLS(SConnection* sc_, bool _anon)
: SSecurity(sc_), session(nullptr), anon_cred(nullptr),
- cert_cred(nullptr), anon(_anon), tlsis(nullptr), tlsos(nullptr),
+ cert_cred(nullptr), anon(_anon), tlssock(nullptr),
rawis(nullptr), rawos(nullptr)
{
int ret;
@@ -88,32 +87,13 @@ SSecurityTLS::SSecurityTLS(SConnection* sc_, bool _anon)
void SSecurityTLS::shutdown()
{
- if (tlsos) {
- try {
- if (tlsos->hasBufferedData()) {
- tlsos->cork(false);
- tlsos->flush();
- if (tlsos->hasBufferedData())
- vlog.error("Failed to flush remaining socket data on close");
- }
- } catch (std::exception& e) {
- vlog.error("Failed to flush remaining socket data on close: %s", e.what());
- }
- }
-
- if (session) {
- int ret;
- // FIXME: We can't currently wait for the response, so we only send
- // our close and hope for the best
- ret = gnutls_bye(session, GNUTLS_SHUT_WR);
- if ((ret != GNUTLS_E_SUCCESS) && (ret != GNUTLS_E_INVALID_SESSION))
- vlog.error("TLS shutdown failed: %s", gnutls_strerror(ret));
- }
+ if (tlssock)
+ tlssock->shutdown();
#if defined (SSECURITYTLS__USE_DEPRECATED_DH)
if (dh_params) {
gnutls_dh_params_deinit(dh_params);
- dh_params = 0;
+ dh_params = nullptr;
}
#endif
@@ -133,13 +113,9 @@ void SSecurityTLS::shutdown()
rawos = nullptr;
}
- if (tlsis) {
- delete tlsis;
- tlsis = nullptr;
- }
- if (tlsos) {
- delete tlsos;
- tlsos = nullptr;
+ if (tlssock) {
+ delete tlssock;
+ tlssock = nullptr;
}
if (session) {
@@ -185,56 +161,46 @@ bool SSecurityTLS::processMsg()
os->writeU8(1);
os->flush();
- // Create these early as they set up the push/pull functions
- // for GnuTLS
- tlsis = new rdr::TLSInStream(is, session);
- tlsos = new rdr::TLSOutStream(os, session);
+ tlssock = new rdr::TLSSocket(is, os, session);
rawis = is;
rawos = os;
}
- err = gnutls_handshake(session);
- if (err != GNUTLS_E_SUCCESS) {
- if (!gnutls_error_is_fatal(err)) {
- vlog.debug("Deferring completion of TLS handshake: %s", gnutls_strerror(err));
+ try {
+ if (!tlssock->handshake())
return false;
- }
- vlog.error("TLS Handshake failed: %s", gnutls_strerror (err));
+ } catch (std::exception&) {
shutdown();
- throw rdr::tls_error("TLS Handshake failed", err);
+ throw;
}
vlog.debug("TLS handshake completed with %s",
gnutls_session_get_desc(session));
- sc->setStreams(tlsis, tlsos);
+ sc->setStreams(&tlssock->inStream(), &tlssock->outStream());
return true;
}
void SSecurityTLS::setParams()
{
- static const char kx_anon_priority[] = ":+ANON-ECDH:+ANON-DH";
+ static const char kx_anon_priority[] = "+ANON-ECDH:+ANON-DH";
int ret;
// Custom priority string specified?
if (strcmp(Security::GnuTLSPriority, "") != 0) {
- char *prio;
+ std::string prio;
const char *err;
- prio = new char[strlen(Security::GnuTLSPriority) +
- strlen(kx_anon_priority) + 1];
-
- strcpy(prio, Security::GnuTLSPriority);
- if (anon)
- strcat(prio, kx_anon_priority);
-
- ret = gnutls_priority_set_direct(session, prio, &err);
-
- delete [] prio;
+ prio = (const char*)Security::GnuTLSPriority;
+ if (anon) {
+ prio += ":";
+ prio += kx_anon_priority;
+ }
+ ret = gnutls_priority_set_direct(session, prio.c_str(), &err);
if (ret != GNUTLS_E_SUCCESS) {
if (ret == GNUTLS_E_INVALID_REQUEST)
vlog.error("GnuTLS priority syntax error at: %s", err);
@@ -244,30 +210,22 @@ void SSecurityTLS::setParams()
const char *err;
#if GNUTLS_VERSION_NUMBER >= 0x030603
- // gnutls_set_default_priority_appends() expects a normal priority string that
- // doesn't start with ":".
- ret = gnutls_set_default_priority_append(session, kx_anon_priority + 1, &err, 0);
+ ret = gnutls_set_default_priority_append(session, kx_anon_priority, &err, 0);
if (ret != GNUTLS_E_SUCCESS) {
if (ret == GNUTLS_E_INVALID_REQUEST)
vlog.error("GnuTLS priority syntax error at: %s", err);
throw rdr::tls_error("gnutls_set_default_priority_append()", ret);
}
#else
+ std::string prio;
+
// We don't know what the system default priority is, so we guess
// it's what upstream GnuTLS has
- static const char gnutls_default_priority[] = "NORMAL";
- char *prio;
-
- prio = new char[strlen(gnutls_default_priority) +
- strlen(kx_anon_priority) + 1];
-
- strcpy(prio, gnutls_default_priority);
- strcat(prio, kx_anon_priority);
-
- ret = gnutls_priority_set_direct(session, prio, &err);
-
- delete [] prio;
+ prio = "NORMAL";
+ prio += ":";
+ prio += kx_anon_priority;
+ ret = gnutls_priority_set_direct(session, prio.c_str(), &err);
if (ret != GNUTLS_E_SUCCESS) {
if (ret == GNUTLS_E_INVALID_REQUEST)
vlog.error("GnuTLS priority syntax error at: %s", err);