aboutsummaryrefslogtreecommitdiffstats
path: root/common/rdr
diff options
context:
space:
mode:
Diffstat (limited to 'common/rdr')
-rw-r--r--common/rdr/BufferedInStream.cxx14
-rw-r--r--common/rdr/BufferedOutStream.cxx13
-rw-r--r--common/rdr/CMakeLists.txt11
-rw-r--r--common/rdr/Exception.cxx135
-rw-r--r--common/rdr/Exception.h80
-rw-r--r--common/rdr/FdInStream.cxx9
-rw-r--r--common/rdr/FdOutStream.cxx14
-rw-r--r--common/rdr/FileInStream.cxx7
-rw-r--r--common/rdr/HexInStream.cxx6
-rw-r--r--common/rdr/HexOutStream.cxx7
-rw-r--r--common/rdr/InStream.h13
-rw-r--r--common/rdr/MemInStream.h1
-rw-r--r--common/rdr/RandomStream.cxx14
-rw-r--r--common/rdr/TLSException.cxx29
-rw-r--r--common/rdr/TLSException.h8
-rw-r--r--common/rdr/TLSInStream.cxx98
-rw-r--r--common/rdr/TLSInStream.h18
-rw-r--r--common/rdr/TLSOutStream.cxx82
-rw-r--r--common/rdr/TLSOutStream.h17
-rw-r--r--common/rdr/TLSSocket.cxx228
-rw-r--r--common/rdr/TLSSocket.h81
-rw-r--r--common/rdr/ZlibOutStream.cxx5
22 files changed, 425 insertions, 465 deletions
diff --git a/common/rdr/BufferedInStream.cxx b/common/rdr/BufferedInStream.cxx
index bf94a950..bcdeef4a 100644
--- a/common/rdr/BufferedInStream.cxx
+++ b/common/rdr/BufferedInStream.cxx
@@ -23,9 +23,9 @@
#include <assert.h>
-#include <rdr/BufferedInStream.h>
+#include <core/string.h>
-#include <rfb/util.h>
+#include <rdr/BufferedInStream.h>
using namespace rdr;
@@ -64,12 +64,10 @@ void BufferedInStream::ensureSpace(size_t needed)
uint8_t* newBuffer;
if (needed > MAX_BUF_SIZE)
- throw std::out_of_range(rfb::format("BufferedInStream overrun: "
- "requested size of %lu bytes "
- "exceeds maximum of %lu "
- "bytes",
- (long unsigned)needed,
- (long unsigned)MAX_BUF_SIZE));
+ throw std::out_of_range(core::format(
+ "BufferedInStream overrun: requested size of %lu bytes exceeds "
+ "maximum of %lu bytes",
+ (long unsigned)needed, (long unsigned)MAX_BUF_SIZE));
newSize = DEFAULT_BUF_SIZE;
while (newSize < needed)
diff --git a/common/rdr/BufferedOutStream.cxx b/common/rdr/BufferedOutStream.cxx
index efb71dd7..e2b756bb 100644
--- a/common/rdr/BufferedOutStream.cxx
+++ b/common/rdr/BufferedOutStream.cxx
@@ -22,9 +22,9 @@
#include <config.h>
#endif
-#include <rdr/BufferedOutStream.h>
+#include <core/string.h>
-#include <rfb/util.h>
+#include <rdr/BufferedOutStream.h>
using namespace rdr;
@@ -138,11 +138,10 @@ void BufferedOutStream::overrun(size_t needed)
// We'll need to allocate more buffer space...
if (totalNeeded > MAX_BUF_SIZE)
- throw std::out_of_range(rfb::format("BufferedOutStream overrun: "
- "requested size of %lu bytes "
- "exceeds maximum of %lu bytes",
- (long unsigned)totalNeeded,
- (long unsigned)MAX_BUF_SIZE));
+ throw std::out_of_range(core::format(
+ "BufferedOutStream overrun: requested size of %lu bytes exceeds "
+ "maximum of %lu bytes",
+ (long unsigned)totalNeeded, (long unsigned)MAX_BUF_SIZE));
newSize = DEFAULT_BUF_SIZE;
while (newSize < totalNeeded)
diff --git a/common/rdr/CMakeLists.txt b/common/rdr/CMakeLists.txt
index 2897119b..526b2971 100644
--- a/common/rdr/CMakeLists.txt
+++ b/common/rdr/CMakeLists.txt
@@ -3,7 +3,6 @@ add_library(rdr STATIC
AESOutStream.cxx
BufferedInStream.cxx
BufferedOutStream.cxx
- Exception.cxx
FdInStream.cxx
FdOutStream.cxx
FileInStream.cxx
@@ -13,17 +12,14 @@ add_library(rdr STATIC
TLSException.cxx
TLSInStream.cxx
TLSOutStream.cxx
+ TLSSocket.cxx
ZlibInStream.cxx
ZlibOutStream.cxx)
target_include_directories(rdr PUBLIC ${CMAKE_SOURCE_DIR}/common)
target_include_directories(rdr SYSTEM PUBLIC ${ZLIB_INCLUDE_DIRS})
-target_link_libraries(rdr ${ZLIB_LIBRARIES} os rfb)
-
-if(MSVC)
- # undef min and max macro
- target_compile_definitions(rfb PRIVATE NOMINMAX)
-endif()
+target_link_libraries(rdr core)
+target_link_libraries(rdr ${ZLIB_LIBRARIES})
if(GNUTLS_FOUND)
target_include_directories(rdr SYSTEM PUBLIC ${GNUTLS_INCLUDE_DIR})
@@ -32,7 +28,6 @@ endif()
if (NETTLE_FOUND)
target_include_directories(rdr SYSTEM PUBLIC ${NETTLE_INCLUDE_DIRS})
target_link_libraries(rdr ${NETTLE_LIBRARIES})
- target_link_directories(rdr PUBLIC ${NETTLE_LIBRARY_DIRS})
endif()
if(WIN32)
target_link_libraries(rdr ws2_32)
diff --git a/common/rdr/Exception.cxx b/common/rdr/Exception.cxx
deleted file mode 100644
index f0c04a6a..00000000
--- a/common/rdr/Exception.cxx
+++ /dev/null
@@ -1,135 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright (C) 2004 Red Hat Inc.
- * Copyright (C) 2010 TigerVNC Team
- * Copyright 2014-2024 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdarg.h>
-
-#include <rdr/Exception.h>
-#include <rdr/TLSException.h>
-#include <rfb/util.h>
-
-#ifdef _WIN32
-#include <winsock2.h>
-#include <windows.h>
-#include <ws2tcpip.h>
-#else
-#include <netdb.h>
-#endif
-
-#include <string.h>
-
-using namespace rdr;
-
-
-getaddrinfo_error::getaddrinfo_error(const char* s, int err_) noexcept
- : std::runtime_error(rfb::format("%s: %s (%d)", s,
- strerror(err_).c_str(), err_)),
- err(err_)
-{
-}
-
-getaddrinfo_error::getaddrinfo_error(const std::string& s,
- int err_) noexcept
- : std::runtime_error(rfb::format("%s: %s (%d)", s.c_str(),
- strerror(err_).c_str(), err_)),
- err(err_)
-{
-}
-
-std::string getaddrinfo_error::strerror(int err_) const noexcept
-{
-#ifdef _WIN32
- char str[256];
-
- WideCharToMultiByte(CP_UTF8, 0, gai_strerrorW(err_), -1, str,
- sizeof(str), nullptr, nullptr);
-
- return str;
-#else
- return gai_strerror(err_);
-#endif
-}
-
-posix_error::posix_error(const char* what_arg, int err_) noexcept
- : std::runtime_error(rfb::format("%s: %s (%d)", what_arg,
- strerror(err_).c_str(), err_)),
- err(err_)
-{
-}
-
-posix_error::posix_error(const std::string& what_arg, int err_) noexcept
- : std::runtime_error(rfb::format("%s: %s (%d)", what_arg.c_str(),
- strerror(err_).c_str(), err_)),
- err(err_)
-{
-}
-
-std::string posix_error::strerror(int err_) const noexcept
-{
-#ifdef _WIN32
- char str[256];
-
- WideCharToMultiByte(CP_UTF8, 0, _wcserror(err_), -1, str,
- sizeof(str), nullptr, nullptr);
-
- return str;
-#else
- return ::strerror(err_);
-#endif
-}
-
-#ifdef WIN32
-win32_error::win32_error(const char* what_arg, unsigned err_) noexcept
- : std::runtime_error(rfb::format("%s: %s (%d)", what_arg,
- strerror(err_).c_str(), err_)),
- err(err_)
-{
-}
-
-win32_error::win32_error(const std::string& what_arg,
- unsigned err_) noexcept
- : std::runtime_error(rfb::format("%s: %s (%d)", what_arg.c_str(),
- strerror(err_).c_str(), err_)),
- err(err_)
-{
-}
-
-std::string win32_error::strerror(unsigned err_) const noexcept
-{
- wchar_t wstr[256];
- char str[256];
-
- FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- nullptr, err_, 0, wstr, sizeof(wstr), nullptr);
- WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str,
- sizeof(str), nullptr, nullptr);
-
- int l = strlen(str);
- if ((l >= 2) && (str[l-2] == '\r') && (str[l-1] == '\n'))
- str[l-2] = 0;
-
- return str;
-}
-#endif
diff --git a/common/rdr/Exception.h b/common/rdr/Exception.h
deleted file mode 100644
index d3cecc18..00000000
--- a/common/rdr/Exception.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright (C) 2004 Red Hat Inc.
- * Copyright (C) 2010 TigerVNC Team
- * Copyright 2015-2024 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#ifndef __RDR_EXCEPTION_H__
-#define __RDR_EXCEPTION_H__
-
-#include <stdexcept>
-#include <string>
-
-namespace rdr {
-
- class posix_error : public std::runtime_error {
- public:
- int err;
- posix_error(const char* what_arg, int err_) noexcept;
- posix_error(const std::string& what_arg, int err_) noexcept;
- private:
- std::string strerror(int err_) const noexcept;
- };
-
-#ifdef WIN32
- class win32_error : public std::runtime_error {
- public:
- unsigned err;
- win32_error(const char* what_arg, unsigned err_) noexcept;
- win32_error(const std::string& what_arg, unsigned err_) noexcept;
- private:
- std::string strerror(unsigned err_) const noexcept;
- };
-#endif
-
-#ifdef WIN32
- class socket_error : public win32_error {
- public:
- socket_error(const char* what_arg, unsigned err_) noexcept : win32_error(what_arg, err_) {}
- socket_error(const std::string& what_arg, unsigned err_) noexcept : win32_error(what_arg, err_) {}
- };
-#else
- class socket_error : public posix_error {
- public:
- socket_error(const char* what_arg, unsigned err_) noexcept : posix_error(what_arg, err_) {}
- socket_error(const std::string& what_arg, unsigned err_) noexcept : posix_error(what_arg, err_) {}
- };
-#endif
-
- class getaddrinfo_error : public std::runtime_error {
- public:
- int err;
- getaddrinfo_error(const char* s, int err_) noexcept;
- getaddrinfo_error(const std::string& s, int err_) noexcept;
- private:
- std::string strerror(int err_) const noexcept;
- };
-
- class end_of_stream : public std::runtime_error {
- public:
- end_of_stream() noexcept : std::runtime_error("End of stream") {}
- };
-
-}
-
-#endif
diff --git a/common/rdr/FdInStream.cxx b/common/rdr/FdInStream.cxx
index 23ea2f8c..25542a01 100644
--- a/common/rdr/FdInStream.cxx
+++ b/common/rdr/FdInStream.cxx
@@ -28,7 +28,7 @@
#include <winsock2.h>
#define errorNumber WSAGetLastError()
#define close closesocket
-#include <os/winerrno.h>
+#include <core/winerrno.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
@@ -41,8 +41,9 @@
#include <sys/select.h>
#endif
+#include <core/Exception.h>
+
#include <rdr/FdInStream.h>
-#include <rdr/Exception.h>
using namespace rdr;
@@ -92,7 +93,7 @@ size_t FdInStream::readFd(uint8_t* buf, size_t len)
} while (n < 0 && errorNumber == EINTR);
if (n < 0)
- throw socket_error("select", errorNumber);
+ throw core::socket_error("select", errorNumber);
if (n == 0)
return 0;
@@ -102,7 +103,7 @@ size_t FdInStream::readFd(uint8_t* buf, size_t len)
} while (n < 0 && errorNumber == EINTR);
if (n < 0)
- throw socket_error("read", errorNumber);
+ throw core::socket_error("read", errorNumber);
if (n == 0)
throw end_of_stream();
diff --git a/common/rdr/FdOutStream.cxx b/common/rdr/FdOutStream.cxx
index 6db8c0bb..416926c1 100644
--- a/common/rdr/FdOutStream.cxx
+++ b/common/rdr/FdOutStream.cxx
@@ -28,7 +28,7 @@
#ifdef _WIN32
#include <winsock2.h>
#define errorNumber WSAGetLastError()
-#include <os/winerrno.h>
+#include <core/winerrno.h>
#else
#include <sys/types.h>
#include <unistd.h>
@@ -44,10 +44,10 @@
#include <sys/select.h>
#endif
-#include <rdr/FdOutStream.h>
-#include <rdr/Exception.h>
-#include <rfb/util.h>
+#include <core/Exception.h>
+#include <core/time.h>
+#include <rdr/FdOutStream.h>
using namespace rdr;
@@ -68,7 +68,7 @@ FdOutStream::~FdOutStream()
unsigned FdOutStream::getIdleTime()
{
- return rfb::msSince(&lastWrite);
+ return core::msSince(&lastWrite);
}
void FdOutStream::cork(bool enable)
@@ -117,7 +117,7 @@ size_t FdOutStream::writeFd(const uint8_t* data, size_t length)
} while (n < 0 && errorNumber == EINTR);
if (n < 0)
- throw socket_error("select", errorNumber);
+ throw core::socket_error("select", errorNumber);
if (n == 0)
return 0;
@@ -134,7 +134,7 @@ size_t FdOutStream::writeFd(const uint8_t* data, size_t length)
} while (n < 0 && (errorNumber == EINTR));
if (n < 0)
- throw socket_error("write", errorNumber);
+ throw core::socket_error("write", errorNumber);
gettimeofday(&lastWrite, nullptr);
diff --git a/common/rdr/FileInStream.cxx b/common/rdr/FileInStream.cxx
index df09ea76..4dbe2d1f 100644
--- a/common/rdr/FileInStream.cxx
+++ b/common/rdr/FileInStream.cxx
@@ -24,7 +24,8 @@
#include <errno.h>
-#include <rdr/Exception.h>
+#include <core/Exception.h>
+
#include <rdr/FileInStream.h>
using namespace rdr;
@@ -33,7 +34,7 @@ FileInStream::FileInStream(const char *fileName)
{
file = fopen(fileName, "rb");
if (!file)
- throw posix_error("fopen", errno);
+ throw core::posix_error("fopen", errno);
}
FileInStream::~FileInStream(void) {
@@ -48,7 +49,7 @@ bool FileInStream::fillBuffer()
size_t n = fread((uint8_t*)end, 1, availSpace(), file);
if (n == 0) {
if (ferror(file))
- throw posix_error("fread", errno);
+ throw core::posix_error("fread", errno);
if (feof(file))
throw end_of_stream();
return false;
diff --git a/common/rdr/HexInStream.cxx b/common/rdr/HexInStream.cxx
index 69c3e260..b5a8826c 100644
--- a/common/rdr/HexInStream.cxx
+++ b/common/rdr/HexInStream.cxx
@@ -22,8 +22,10 @@
#endif
#include <algorithm>
+
+#include <core/string.h>
+
#include <rdr/HexInStream.h>
-#include <rfb/util.h>
using namespace rdr;
@@ -44,7 +46,7 @@ bool HexInStream::fillBuffer() {
uint8_t* optr = (uint8_t*) end;
for (size_t i=0; i<length; i++) {
- if (!rfb::hexToBin((const char*)&iptr[i*2], 2, &optr[i], 1))
+ if (!core::hexToBin((const char*)&iptr[i*2], 2, &optr[i], 1))
throw std::runtime_error("HexInStream: Invalid input data");
}
diff --git a/common/rdr/HexOutStream.cxx b/common/rdr/HexOutStream.cxx
index efab77f8..b3749c0d 100644
--- a/common/rdr/HexOutStream.cxx
+++ b/common/rdr/HexOutStream.cxx
@@ -20,9 +20,12 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+
#include <algorithm>
+
+#include <core/string.h>
+
#include <rdr/HexOutStream.h>
-#include <rfb/util.h>
using namespace rdr;
@@ -42,7 +45,7 @@ bool HexOutStream::flushBuffer()
size_t length = std::min((size_t)(ptr-sentUpTo), out_stream.avail()/2);
for (size_t i=0; i<length; i++)
- rfb::binToHex(&sentUpTo[i], 1, (char*)&optr[i*2], 2);
+ core::binToHex(&sentUpTo[i], 1, (char*)&optr[i*2], 2);
out_stream.setptr(length*2);
sentUpTo += length;
diff --git a/common/rdr/InStream.h b/common/rdr/InStream.h
index 5623142c..7ad4996f 100644
--- a/common/rdr/InStream.h
+++ b/common/rdr/InStream.h
@@ -38,6 +38,11 @@
namespace rdr {
+ class end_of_stream : public std::runtime_error {
+ public:
+ end_of_stream() noexcept : std::runtime_error("End of stream") {}
+ };
+
class InStream {
public:
@@ -182,9 +187,7 @@ namespace rdr {
private:
const uint8_t* restorePoint;
-#ifdef RFB_INSTREAM_CHECK
size_t checkedBytes;
-#endif
inline void check(size_t bytes) {
#ifdef RFB_INSTREAM_CHECK
@@ -204,11 +207,7 @@ namespace rdr {
protected:
- InStream() : restorePoint(nullptr)
-#ifdef RFB_INSTREAM_CHECK
- ,checkedBytes(0)
-#endif
- {}
+ InStream() : restorePoint(nullptr), checkedBytes(0) {}
const uint8_t* ptr;
const uint8_t* end;
};
diff --git a/common/rdr/MemInStream.h b/common/rdr/MemInStream.h
index 78ee2dee..a92e18f9 100644
--- a/common/rdr/MemInStream.h
+++ b/common/rdr/MemInStream.h
@@ -28,7 +28,6 @@
#define __RDR_MEMINSTREAM_H__
#include <rdr/InStream.h>
-#include <rdr/Exception.h>
namespace rdr {
diff --git a/common/rdr/RandomStream.cxx b/common/rdr/RandomStream.cxx
index 3a524102..9784c220 100644
--- a/common/rdr/RandomStream.cxx
+++ b/common/rdr/RandomStream.cxx
@@ -20,9 +20,11 @@
#include <config.h>
#endif
+#include <core/Exception.h>
+#include <core/LogWriter.h>
+
#include <rdr/RandomStream.h>
-#include <rdr/Exception.h>
-#include <rfb/LogWriter.h>
+
#include <time.h>
#include <stdlib.h>
#ifndef WIN32
@@ -35,7 +37,7 @@
#endif
#endif
-static rfb::LogWriter vlog("RandomStream");
+static core::LogWriter vlog("RandomStream");
using namespace rdr;
@@ -89,7 +91,7 @@ bool RandomStream::fillBuffer() {
#ifdef RFB_HAVE_WINCRYPT
if (provider) {
if (!CryptGenRandom(provider, availSpace(), (uint8_t*)end))
- throw rdr::win32_error("Unable to CryptGenRandom", GetLastError());
+ throw core::win32_error("Unable to CryptGenRandom", GetLastError());
end += availSpace();
} else {
#else
@@ -97,8 +99,8 @@ bool RandomStream::fillBuffer() {
if (fp) {
size_t n = fread((uint8_t*)end, 1, availSpace(), fp);
if (n <= 0)
- throw rdr::posix_error("Reading /dev/urandom or /dev/random "
- "failed", errno);
+ throw core::posix_error(
+ "Reading /dev/urandom or /dev/random failed", errno);
end += n;
} else {
#else
diff --git a/common/rdr/TLSException.cxx b/common/rdr/TLSException.cxx
index ee4f587b..8c93a3d3 100644
--- a/common/rdr/TLSException.cxx
+++ b/common/rdr/TLSException.cxx
@@ -22,9 +22,9 @@
#include <config.h>
#endif
-#include <rdr/TLSException.h>
+#include <core/string.h>
-#include <rfb/util.h>
+#include <rdr/TLSException.h>
#include <string.h>
#include <stdio.h>
@@ -35,11 +35,28 @@
using namespace rdr;
#ifdef HAVE_GNUTLS
-tls_error::tls_error(const char* s, int err_) noexcept
- : std::runtime_error(rfb::format("%s: %s (%d)", s,
- gnutls_strerror(err_), err_)),
- err(err_)
+tls_error::tls_error(const char* s, int err_, int alert_) noexcept
+ : std::runtime_error(core::format("%s: %s (%d)", s,
+ strerror(err_, alert_), err_)),
+ err(err_), alert(alert_)
+{
+}
+
+const char* tls_error::strerror(int err_, int alert_) const noexcept
{
+ const char* msg;
+
+ msg = nullptr;
+
+ if ((alert_ != -1) &&
+ ((err_ == GNUTLS_E_WARNING_ALERT_RECEIVED) ||
+ (err_ == GNUTLS_E_FATAL_ALERT_RECEIVED)))
+ msg = gnutls_alert_get_name((gnutls_alert_description_t)alert_);
+
+ if (msg == nullptr)
+ msg = gnutls_strerror(err_);
+
+ return msg;
}
#endif /* HAVE_GNUTLS */
diff --git a/common/rdr/TLSException.h b/common/rdr/TLSException.h
index 62b090ba..75ee94f5 100644
--- a/common/rdr/TLSException.h
+++ b/common/rdr/TLSException.h
@@ -21,14 +21,16 @@
#ifndef __RDR_TLSEXCEPTION_H__
#define __RDR_TLSEXCEPTION_H__
-#include <rdr/Exception.h>
+#include <stdexcept>
namespace rdr {
class tls_error : public std::runtime_error {
public:
- int err;
- tls_error(const char* s, int err_) noexcept;
+ int err, alert;
+ tls_error(const char* s, int err_, int alert_=-1) noexcept;
+ private:
+ const char* strerror(int err_, int alert_) const noexcept;
};
}
diff --git a/common/rdr/TLSInStream.cxx b/common/rdr/TLSInStream.cxx
index ee2739f4..3e5ea2be 100644
--- a/common/rdr/TLSInStream.cxx
+++ b/common/rdr/TLSInStream.cxx
@@ -1,7 +1,7 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* 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
@@ -23,74 +23,25 @@
#include <config.h>
#endif
-#include <rdr/Exception.h>
-#include <rdr/TLSException.h>
#include <rdr/TLSInStream.h>
-#include <rfb/LogWriter.h>
-#include <errno.h>
+#include <rdr/TLSSocket.h>
-#ifdef HAVE_GNUTLS
-using namespace rdr;
-
-static rfb::LogWriter vlog("TLSInStream");
-
-ssize_t TLSInStream::pull(gnutls_transport_ptr_t str, void* data, size_t size)
-{
- TLSInStream* self= (TLSInStream*) str;
- InStream *in = self->in;
-
- self->streamEmpty = false;
- delete self->saved_exception;
- self->saved_exception = nullptr;
+#ifdef HAVE_GNUTLS
- try {
- if (!in->hasData(1)) {
- self->streamEmpty = true;
- gnutls_transport_set_errno(self->session, EAGAIN);
- return -1;
- }
-
- if (in->avail() < size)
- size = in->avail();
-
- in->readBytes((uint8_t*)data, size);
- } catch (end_of_stream&) {
- return 0;
- } catch (socket_error& e) {
- vlog.error("Failure reading TLS data: %s", e.what());
- gnutls_transport_set_errno(self->session, e.err);
- self->saved_exception = new socket_error(e);
- return -1;
- } catch (std::exception& e) {
- vlog.error("Failure reading TLS data: %s", e.what());
- gnutls_transport_set_errno(self->session, EINVAL);
- self->saved_exception = new std::runtime_error(e.what());
- return -1;
- }
-
- return size;
-}
+using namespace rdr;
-TLSInStream::TLSInStream(InStream* _in, gnutls_session_t _session)
- : session(_session), in(_in), saved_exception(nullptr)
+TLSInStream::TLSInStream(TLSSocket* sock_)
+ : sock(sock_)
{
- gnutls_transport_ptr_t recv, send;
-
- gnutls_transport_set_pull_function(session, pull);
- gnutls_transport_get_ptr2(session, &recv, &send);
- gnutls_transport_set_ptr2(session, this, send);
}
TLSInStream::~TLSInStream()
{
- gnutls_transport_set_pull_function(session, nullptr);
-
- delete saved_exception;
}
bool TLSInStream::fillBuffer()
{
- size_t n = readTLS((uint8_t*) end, availSpace());
+ size_t n = sock->readTLS((uint8_t*) end, availSpace());
if (n == 0)
return false;
end += n;
@@ -98,39 +49,4 @@ bool TLSInStream::fillBuffer()
return true;
}
-size_t TLSInStream::readTLS(uint8_t* buf, size_t len)
-{
- int n;
-
- while (true) {
- streamEmpty = false;
- n = gnutls_record_recv(session, (void *) buf, len);
- if (n == GNUTLS_E_INTERRUPTED || n == GNUTLS_E_AGAIN) {
- // GnuTLS returns GNUTLS_E_AGAIN for a bunch of other scenarios
- // other than the pull function returning EAGAIN, so we have to
- // double check that the underlying stream really is empty
- if (!streamEmpty)
- continue;
- else
- return 0;
- }
- break;
- };
-
- if (n == GNUTLS_E_PULL_ERROR) {
- if (dynamic_cast<socket_error*>(saved_exception))
- throw *dynamic_cast<socket_error*>(saved_exception);
- else
- throw std::runtime_error(saved_exception->what());
- }
-
- if (n < 0)
- throw tls_error("readTLS", n);
-
- if (n == 0)
- throw end_of_stream();
-
- return n;
-}
-
#endif
diff --git a/common/rdr/TLSInStream.h b/common/rdr/TLSInStream.h
index 2269b09d..94266e50 100644
--- a/common/rdr/TLSInStream.h
+++ b/common/rdr/TLSInStream.h
@@ -1,5 +1,6 @@
/* Copyright (C) 2005 Martin Koegler
* Copyright (C) 2010 TigerVNC Team
+ * 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
@@ -22,28 +23,25 @@
#ifdef HAVE_GNUTLS
-#include <gnutls/gnutls.h>
#include <rdr/BufferedInStream.h>
namespace rdr {
+ class TLSSocket;
+
class TLSInStream : public BufferedInStream {
public:
- TLSInStream(InStream* in, gnutls_session_t session);
+ TLSInStream(TLSSocket* sock);
virtual ~TLSInStream();
private:
bool fillBuffer() override;
- size_t readTLS(uint8_t* buf, size_t len);
- static ssize_t pull(gnutls_transport_ptr_t str, void* data, size_t size);
-
- gnutls_session_t session;
- InStream* in;
- bool streamEmpty;
- std::exception* saved_exception;
+ TLSSocket* sock;
};
-};
+
+}
#endif
+
#endif
diff --git a/common/rdr/TLSOutStream.cxx b/common/rdr/TLSOutStream.cxx
index 365ffd60..ba9d182f 100644
--- a/common/rdr/TLSOutStream.cxx
+++ b/common/rdr/TLSOutStream.cxx
@@ -1,7 +1,7 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* 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
@@ -23,108 +23,42 @@
#include <config.h>
#endif
-#include <rdr/Exception.h>
-#include <rdr/TLSException.h>
#include <rdr/TLSOutStream.h>
-#include <rfb/LogWriter.h>
-#include <errno.h>
+#include <rdr/TLSSocket.h>
#ifdef HAVE_GNUTLS
-using namespace rdr;
-
-static rfb::LogWriter vlog("TLSOutStream");
-
-ssize_t TLSOutStream::push(gnutls_transport_ptr_t str, const void* data,
- size_t size)
-{
- TLSOutStream* self= (TLSOutStream*) str;
- OutStream *out = self->out;
-
- delete self->saved_exception;
- self->saved_exception = nullptr;
- try {
- out->writeBytes((const uint8_t*)data, size);
- out->flush();
- } catch (socket_error& e) {
- vlog.error("Failure sending TLS data: %s", e.what());
- gnutls_transport_set_errno(self->session, e.err);
- self->saved_exception = new socket_error(e);
- return -1;
- } catch (std::exception& e) {
- vlog.error("Failure sending TLS data: %s", e.what());
- gnutls_transport_set_errno(self->session, EINVAL);
- self->saved_exception = new std::runtime_error(e.what());
- return -1;
- }
-
- return size;
-}
+using namespace rdr;
-TLSOutStream::TLSOutStream(OutStream* _out, gnutls_session_t _session)
- : session(_session), out(_out), saved_exception(nullptr)
+TLSOutStream::TLSOutStream(TLSSocket* sock_)
+ : sock(sock_)
{
- gnutls_transport_ptr_t recv, send;
-
- gnutls_transport_set_push_function(session, push);
- gnutls_transport_get_ptr2(session, &recv, &send);
- gnutls_transport_set_ptr2(session, recv, this);
}
TLSOutStream::~TLSOutStream()
{
-#if 0
- try {
-// flush();
- } catch (Exception&) {
- }
-#endif
- gnutls_transport_set_push_function(session, nullptr);
-
- delete saved_exception;
}
void TLSOutStream::flush()
{
BufferedOutStream::flush();
- out->flush();
+ sock->out->flush();
}
void TLSOutStream::cork(bool enable)
{
BufferedOutStream::cork(enable);
- out->cork(enable);
+ sock->out->cork(enable);
}
bool TLSOutStream::flushBuffer()
{
while (sentUpTo < ptr) {
- size_t n = writeTLS(sentUpTo, ptr - sentUpTo);
+ size_t n = sock->writeTLS(sentUpTo, ptr - sentUpTo);
sentUpTo += n;
}
return true;
}
-size_t TLSOutStream::writeTLS(const uint8_t* data, size_t length)
-{
- int n;
-
- n = gnutls_record_send(session, data, length);
- if (n == GNUTLS_E_INTERRUPTED || n == GNUTLS_E_AGAIN)
- return 0;
-
- if (n == GNUTLS_E_PUSH_ERROR) {
- if (dynamic_cast<socket_error*>(saved_exception))
- throw *dynamic_cast<socket_error*>(saved_exception);
- else
- throw std::runtime_error(saved_exception->what());
- }
-
- if (n < 0)
- throw tls_error("writeTLS", n);
-
- return n;
-}
-
#endif
diff --git a/common/rdr/TLSOutStream.h b/common/rdr/TLSOutStream.h
index 659f16f0..aa9572ba 100644
--- a/common/rdr/TLSOutStream.h
+++ b/common/rdr/TLSOutStream.h
@@ -21,14 +21,16 @@
#define __RDR_TLSOUTSTREAM_H__
#ifdef HAVE_GNUTLS
-#include <gnutls/gnutls.h>
+
#include <rdr/BufferedOutStream.h>
namespace rdr {
+ class TLSSocket;
+
class TLSOutStream : public BufferedOutStream {
public:
- TLSOutStream(OutStream* out, gnutls_session_t session);
+ TLSOutStream(TLSSocket* out);
virtual ~TLSOutStream();
void flush() override;
@@ -36,15 +38,12 @@ namespace rdr {
private:
bool flushBuffer() override;
- size_t writeTLS(const uint8_t* data, size_t length);
- static ssize_t push(gnutls_transport_ptr_t str, const void* data, size_t size);
-
- gnutls_session_t session;
- OutStream* out;
- std::exception* saved_exception;
+ TLSSocket* sock;
};
-};
+
+}
#endif
+
#endif
diff --git a/common/rdr/TLSSocket.cxx b/common/rdr/TLSSocket.cxx
new file mode 100644
index 00000000..a29e41c1
--- /dev/null
+++ b/common/rdr/TLSSocket.cxx
@@ -0,0 +1,228 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright (C) 2005 Martin Koegler
+ * Copyright (C) 2010 TigerVNC Team
+ * Copyright (C) 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <core/Exception.h>
+#include <core/LogWriter.h>
+
+#include <rdr/InStream.h>
+#include <rdr/OutStream.h>
+#include <rdr/TLSException.h>
+#include <rdr/TLSSocket.h>
+
+#include <errno.h>
+
+#ifdef HAVE_GNUTLS
+
+using namespace rdr;
+
+static core::LogWriter vlog("TLSSocket");
+
+TLSSocket::TLSSocket(InStream* in_, OutStream* out_,
+ gnutls_session_t session_)
+ : session(session_), in(in_), out(out_), tlsin(this), tlsout(this)
+{
+ gnutls_transport_set_pull_function(
+ session, [](gnutls_transport_ptr_t sock, void* data, size_t size) {
+ return ((TLSSocket*)sock)->pull(data, size);
+ });
+ gnutls_transport_set_push_function(
+ session, [](gnutls_transport_ptr_t sock, const void* data, size_t size) {
+ return ((TLSSocket*)sock)->push(data, size);
+ });
+ gnutls_transport_set_ptr(session, this);
+}
+
+TLSSocket::~TLSSocket()
+{
+ gnutls_transport_set_pull_function(session, nullptr);
+ gnutls_transport_set_push_function(session, nullptr);
+ gnutls_transport_set_ptr(session, nullptr);
+}
+
+bool TLSSocket::handshake()
+{
+ int err;
+
+ err = gnutls_handshake(session);
+ if (err != GNUTLS_E_SUCCESS) {
+ gnutls_alert_description_t alert;
+ const char* msg;
+
+ if ((err == GNUTLS_E_PULL_ERROR) || (err == GNUTLS_E_PUSH_ERROR))
+ std::rethrow_exception(saved_exception);
+
+ alert = gnutls_alert_get(session);
+ msg = nullptr;
+
+ if ((err == GNUTLS_E_WARNING_ALERT_RECEIVED) ||
+ (err == GNUTLS_E_FATAL_ALERT_RECEIVED))
+ msg = gnutls_alert_get_name(alert);
+
+ if (msg == nullptr)
+ msg = gnutls_strerror(err);
+
+ if (!gnutls_error_is_fatal(err)) {
+ vlog.debug("Deferring completion of TLS handshake: %s", msg);
+ return false;
+ }
+
+ vlog.error("TLS Handshake failed: %s\n", msg);
+ gnutls_alert_send_appropriate(session, err);
+ throw rdr::tls_error("TLS Handshake failed", err, alert);
+ }
+
+ return true;
+}
+
+void TLSSocket::shutdown()
+{
+ int ret;
+
+ try {
+ if (tlsout.hasBufferedData()) {
+ tlsout.cork(false);
+ tlsout.flush();
+ if (tlsout.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());
+ }
+
+ // 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));
+}
+
+size_t TLSSocket::readTLS(uint8_t* buf, size_t len)
+{
+ int n;
+
+ while (true) {
+ streamEmpty = false;
+ n = gnutls_record_recv(session, (void *) buf, len);
+ if (n == GNUTLS_E_INTERRUPTED || n == GNUTLS_E_AGAIN) {
+ // GnuTLS returns GNUTLS_E_AGAIN for a bunch of other scenarios
+ // other than the pull function returning EAGAIN, so we have to
+ // double check that the underlying stream really is empty
+ if (!streamEmpty)
+ continue;
+ else
+ return 0;
+ }
+ break;
+ };
+
+ if (n == GNUTLS_E_PULL_ERROR)
+ std::rethrow_exception(saved_exception);
+
+ if (n < 0) {
+ gnutls_alert_send_appropriate(session, n);
+ throw tls_error("readTLS", n, gnutls_alert_get(session));
+ }
+
+ if (n == 0)
+ throw end_of_stream();
+
+ return n;
+}
+
+size_t TLSSocket::writeTLS(const uint8_t* data, size_t length)
+{
+ int n;
+
+ n = gnutls_record_send(session, data, length);
+ if (n == GNUTLS_E_INTERRUPTED || n == GNUTLS_E_AGAIN)
+ return 0;
+
+ if (n == GNUTLS_E_PUSH_ERROR)
+ std::rethrow_exception(saved_exception);
+
+ if (n < 0) {
+ gnutls_alert_send_appropriate(session, n);
+ throw tls_error("writeTLS", n, gnutls_alert_get(session));
+ }
+
+ return n;
+}
+
+ssize_t TLSSocket::pull(void* data, size_t size)
+{
+ streamEmpty = false;
+ saved_exception = nullptr;
+
+ try {
+ if (!in->hasData(1)) {
+ streamEmpty = true;
+ gnutls_transport_set_errno(session, EAGAIN);
+ return -1;
+ }
+
+ if (in->avail() < size)
+ size = in->avail();
+
+ in->readBytes((uint8_t*)data, size);
+ } catch (end_of_stream&) {
+ return 0;
+ } catch (std::exception& e) {
+ core::socket_error* se;
+ vlog.error("Failure reading TLS data: %s", e.what());
+ se = dynamic_cast<core::socket_error*>(&e);
+ if (se)
+ gnutls_transport_set_errno(session, se->err);
+ else
+ gnutls_transport_set_errno(session, EINVAL);
+ saved_exception = std::current_exception();
+ return -1;
+ }
+
+ return size;
+}
+
+ssize_t TLSSocket::push(const void* data, size_t size)
+{
+ saved_exception = nullptr;
+
+ try {
+ out->writeBytes((const uint8_t*)data, size);
+ out->flush();
+ } catch (std::exception& e) {
+ core::socket_error* se;
+ vlog.error("Failure sending TLS data: %s", e.what());
+ se = dynamic_cast<core::socket_error*>(&e);
+ if (se)
+ gnutls_transport_set_errno(session, se->err);
+ else
+ gnutls_transport_set_errno(session, EINVAL);
+ saved_exception = std::current_exception();
+ return -1;
+ }
+
+ return size;
+}
+
+#endif
diff --git a/common/rdr/TLSSocket.h b/common/rdr/TLSSocket.h
new file mode 100644
index 00000000..ca29f8bc
--- /dev/null
+++ b/common/rdr/TLSSocket.h
@@ -0,0 +1,81 @@
+/* Copyright (C) 2005 Martin Koegler
+ * Copyright (C) 2010 TigerVNC Team
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef __RDR_TLSSOCKET_H__
+#define __RDR_TLSSOCKET_H__
+
+#ifdef HAVE_GNUTLS
+
+#include <exception>
+
+#include <gnutls/gnutls.h>
+
+#include <rdr/TLSInStream.h>
+#include <rdr/TLSOutStream.h>
+
+namespace rdr {
+
+ class InStream;
+ class OutStream;
+
+ class TLSInStream;
+ class TLSOutStream;
+
+ class TLSSocket {
+ public:
+ TLSSocket(InStream* in, OutStream* out, gnutls_session_t session);
+ virtual ~TLSSocket();
+
+ TLSInStream& inStream() { return tlsin; }
+ TLSOutStream& outStream() { return tlsout; }
+
+ bool handshake();
+ void shutdown();
+
+ protected:
+ /* Used by the stream classes */
+ size_t readTLS(uint8_t* buf, size_t len);
+ size_t writeTLS(const uint8_t* data, size_t length);
+
+ friend TLSInStream;
+ friend TLSOutStream;
+
+ private:
+ ssize_t pull(void* data, size_t size);
+ ssize_t push(const void* data, size_t size);
+
+ gnutls_session_t session;
+
+ InStream* in;
+ OutStream* out;
+
+ TLSInStream tlsin;
+ TLSOutStream tlsout;
+
+ bool streamEmpty;
+
+ std::exception_ptr saved_exception;
+ };
+
+}
+
+#endif
+
+#endif
diff --git a/common/rdr/ZlibOutStream.cxx b/common/rdr/ZlibOutStream.cxx
index 73b5d459..1b8ac307 100644
--- a/common/rdr/ZlibOutStream.cxx
+++ b/common/rdr/ZlibOutStream.cxx
@@ -23,14 +23,15 @@
#include <stdio.h>
+#include <core/LogWriter.h>
+
#include <rdr/ZlibOutStream.h>
-#include <rfb/LogWriter.h>
#include <zlib.h>
#undef ZLIBOUT_DEBUG
-static rfb::LogWriter vlog("ZlibOutStream");
+static core::LogWriter vlog("ZlibOutStream");
using namespace rdr;