From 9c407d2a0bc11697ae8413a8e6bea21813fd6072 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 10 Jun 2021 16:34:15 +0200 Subject: [PATCH] Propagate exceptions from GnuTLS push/pull functions Gives us a more meaningful error rather than just "Error in push/pull function". --- common/rdr/TLSInStream.cxx | 15 +++++++++++++-- common/rdr/TLSInStream.h | 2 ++ common/rdr/TLSOutStream.cxx | 12 +++++++++++- common/rdr/TLSOutStream.h | 2 ++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/common/rdr/TLSInStream.cxx b/common/rdr/TLSInStream.cxx index 94e6109b..451855c7 100644 --- a/common/rdr/TLSInStream.cxx +++ b/common/rdr/TLSInStream.cxx @@ -39,6 +39,9 @@ ssize_t TLSInStream::pull(gnutls_transport_ptr_t str, void* data, size_t size) TLSInStream* self= (TLSInStream*) str; InStream *in = self->in; + delete self->saved_exception; + self->saved_exception = NULL; + try { if (!in->hasData(1)) { gnutls_transport_set_errno(self->session, EAGAIN); @@ -54,10 +57,12 @@ ssize_t TLSInStream::pull(gnutls_transport_ptr_t str, void* data, size_t size) } catch (SystemException &e) { vlog.error("Failure reading TLS data: %s", e.str()); gnutls_transport_set_errno(self->session, e.err); + self->saved_exception = new SystemException(e); return -1; } catch (Exception& e) { vlog.error("Failure reading TLS data: %s", e.str()); gnutls_transport_set_errno(self->session, EINVAL); + self->saved_exception = new Exception(e); return -1; } @@ -65,7 +70,7 @@ ssize_t TLSInStream::pull(gnutls_transport_ptr_t str, void* data, size_t size) } TLSInStream::TLSInStream(InStream* _in, gnutls_session_t _session) - : session(_session), in(_in) + : session(_session), in(_in), saved_exception(NULL) { gnutls_transport_ptr_t recv, send; @@ -77,6 +82,8 @@ TLSInStream::TLSInStream(InStream* _in, gnutls_session_t _session) TLSInStream::~TLSInStream() { gnutls_transport_set_pull_function(session, NULL); + + delete saved_exception; } bool TLSInStream::fillBuffer(size_t maxSize) @@ -97,7 +104,11 @@ size_t TLSInStream::readTLS(U8* buf, size_t len) if (n == GNUTLS_E_INTERRUPTED || n == GNUTLS_E_AGAIN) return 0; - if (n < 0) throw TLSException("readTLS", n); + if (n == GNUTLS_E_PULL_ERROR) + throw *saved_exception; + + if (n < 0) + throw TLSException("readTLS", n); if (n == 0) throw EndOfStream(); diff --git a/common/rdr/TLSInStream.h b/common/rdr/TLSInStream.h index df5ebb48..8fe35d26 100644 --- a/common/rdr/TLSInStream.h +++ b/common/rdr/TLSInStream.h @@ -43,6 +43,8 @@ namespace rdr { gnutls_session_t session; InStream* in; + + Exception* saved_exception; }; }; diff --git a/common/rdr/TLSOutStream.cxx b/common/rdr/TLSOutStream.cxx index 0fa14b39..dc6b55aa 100644 --- a/common/rdr/TLSOutStream.cxx +++ b/common/rdr/TLSOutStream.cxx @@ -42,16 +42,21 @@ ssize_t TLSOutStream::push(gnutls_transport_ptr_t str, const void* data, TLSOutStream* self= (TLSOutStream*) str; OutStream *out = self->out; + delete self->saved_exception; + self->saved_exception = NULL; + try { out->writeBytes(data, size); out->flush(); } catch (SystemException &e) { vlog.error("Failure sending TLS data: %s", e.str()); gnutls_transport_set_errno(self->session, e.err); + self->saved_exception = new SystemException(e); return -1; } catch (Exception& e) { vlog.error("Failure sending TLS data: %s", e.str()); gnutls_transport_set_errno(self->session, EINVAL); + self->saved_exception = new Exception(e); return -1; } @@ -59,7 +64,8 @@ ssize_t TLSOutStream::push(gnutls_transport_ptr_t str, const void* data, } TLSOutStream::TLSOutStream(OutStream* _out, gnutls_session_t _session) - : session(_session), out(_out), bufSize(DEFAULT_BUF_SIZE), offset(0) + : session(_session), out(_out), bufSize(DEFAULT_BUF_SIZE), offset(0), + saved_exception(NULL) { gnutls_transport_ptr_t recv, send; @@ -82,6 +88,7 @@ TLSOutStream::~TLSOutStream() gnutls_transport_set_push_function(session, NULL); delete [] start; + delete saved_exception; } size_t TLSOutStream::length() @@ -134,6 +141,9 @@ size_t TLSOutStream::writeTLS(const U8* data, size_t length) if (n == GNUTLS_E_INTERRUPTED || n == GNUTLS_E_AGAIN) return 0; + if (n == GNUTLS_E_PUSH_ERROR) + throw *saved_exception; + if (n < 0) throw TLSException("writeTLS", n); diff --git a/common/rdr/TLSOutStream.h b/common/rdr/TLSOutStream.h index c9750463..c5579127 100644 --- a/common/rdr/TLSOutStream.h +++ b/common/rdr/TLSOutStream.h @@ -51,6 +51,8 @@ namespace rdr { size_t bufSize; U8* start; size_t offset; + + Exception* saved_exception; }; }; -- 2.39.5