From 6f6ad903d9e248f59bddedb3ab4cae41a7d8bec0 Mon Sep 17 00:00:00 2001
From: Edwin Mons <edwin.mons@isode.com>
Date: Tue, 8 Jan 2019 17:43:31 +0100
Subject: Add optional message to TLSError

TLSError now takes an optional error message.  OpenSSLContext has been
updated to send out one, and calls to SWIFT_LOG have been removed from
it for anything but setCertificateChain.

OpenSSLContext::handleDataFromApplication misinterpreted the return code
of SSL_write, triggering an onError in cases where more network I/O was
required.

Test-Information:

Unit tests pass on Debian 9
Server test code no longer emits undesirable warnings to stderr on macOS
10.14.

Change-Id: If0f932693361ef9738ae50d5445bfb4d3ed9b28f

diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index d3711cb..ccde0c2 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -316,6 +316,8 @@ void CoreClient::handleSessionFinished(std::shared_ptr<Error> error) {
                     clientError = ClientError(ClientError::CertificateCardRemoved);
                     break;
                 case TLSError::UnknownError:
+                case TLSError::AcceptFailed:
+                case TLSError::ConnectFailed:
                     clientError = ClientError(ClientError::TLSError);
                     break;
             }
diff --git a/Swiften/Network/BOSHConnection.cpp b/Swiften/Network/BOSHConnection.cpp
index 4bbb121..aaec9f2 100644
--- a/Swiften/Network/BOSHConnection.cpp
+++ b/Swiften/Network/BOSHConnection.cpp
@@ -5,7 +5,7 @@
  */
 
 /*
- * Copyright (c) 2011-2018 Isode Limited.
+ * Copyright (c) 2011-2019 Isode Limited.
  * All rights reserved.
  * See the COPYING file for more information.
  */
@@ -93,8 +93,8 @@ void BOSHConnection::handleRawDataRead(std::shared_ptr<SafeByteArray> data) {
     tlsLayer_->handleDataRead(*data.get());
 }
 
-void BOSHConnection::handleTLSError(std::shared_ptr<TLSError> /* error */) {
-
+void BOSHConnection::handleTLSError(std::shared_ptr<TLSError> error) {
+    SWIFT_LOG(debug) << (error ? error->getMessage() : "Unknown TLS error") << std::endl;
 }
 
 void BOSHConnection::writeData(const SafeByteArray& data) {
diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
index 89917ee..968ef8f 100644
--- a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
+++ b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2018 Isode Limited.
+ * Copyright (c) 2010-2019 Isode Limited.
  * All rights reserved.
  * See the COPYING file for more information.
  */
@@ -180,7 +180,7 @@ void OpenSSLContext::accept() {
     handle_ = std::unique_ptr<SSL>(SSL_new(context_.get()));
     if (!handle_) {
         state_ = State::Error;
-        onError(std::make_shared<TLSError>());
+        onError(std::make_shared<TLSError>(TLSError::AcceptFailed, openSSLInternalErrorToString()));
         return;
     }
 
@@ -199,13 +199,14 @@ void OpenSSLContext::connect(const std::string& requestedServerName) {
     handle_ = std::unique_ptr<SSL>(SSL_new(context_.get()));
     if (!handle_) {
         state_ = State::Error;
-        onError(std::make_shared<TLSError>());
+        onError(std::make_shared<TLSError>(TLSError::ConnectFailed, openSSLInternalErrorToString()));
         return;
     }
 
     if (!requestedServerName.empty()) {
         if (SSL_set_tlsext_host_name(handle_.get(), const_cast<char*>(requestedServerName.c_str())) != 1) {
-            SWIFT_LOG(error) << "Failed on SSL_set_tlsext_host_name()." << std::endl;
+            onError(std::make_shared<TLSError>(TLSError::ConnectFailed, "Failed to set Server Name Indication: " + openSSLInternalErrorToString()));\
+            return;
         }
     }
 
@@ -237,9 +238,8 @@ void OpenSSLContext::doAccept() {
             sendPendingDataToNetwork();
             break;
         default:
-            SWIFT_LOG(warning) << openSSLInternalErrorToString() << std::endl;
             state_ = State::Error;
-            onError(std::make_shared<TLSError>());
+            onError(std::make_shared<TLSError>(TLSError::AcceptFailed, openSSLInternalErrorToString()));
             sendPendingDataToNetwork();
     }
 }
@@ -260,9 +260,9 @@ void OpenSSLContext::doConnect() {
             sendPendingDataToNetwork();
             break;
         default:
-            SWIFT_LOG(warning) << openSSLInternalErrorToString() << std::endl;
             state_ = State::Error;
             onError(std::make_shared<TLSError>());
+            onError(std::make_shared<TLSError>(TLSError::ConnectFailed, openSSLInternalErrorToString()));
     }
 }
 
@@ -312,12 +312,13 @@ void OpenSSLContext::handleDataFromNetwork(const SafeByteArray& data) {
 }
 
 void OpenSSLContext::handleDataFromApplication(const SafeByteArray& data) {
-    if (SSL_write(handle_.get(), vecptr(data), data.size()) >= 0) {
-        sendPendingDataToNetwork();
+    auto ret = SSL_write(handle_.get(), vecptr(data), data.size());
+    if (ret > 0 || SSL_get_error(handle_.get(), ret) == SSL_ERROR_WANT_READ) {
+            sendPendingDataToNetwork();
     }
     else {
         state_ = State::Error;
-        onError(std::make_shared<TLSError>());
+        onError(std::make_shared<TLSError>(TLSError::UnknownError, openSSLInternalErrorToString()));
     }
 }
 
@@ -333,7 +334,7 @@ void OpenSSLContext::sendPendingDataToApplication() {
     }
     if (ret < 0 && SSL_get_error(handle_.get(), ret) != SSL_ERROR_WANT_READ) {
         state_ = State::Error;
-        onError(std::make_shared<TLSError>());
+        onError(std::make_shared<TLSError>(TLSError::UnknownError, openSSLInternalErrorToString()));
     }
 }
 
diff --git a/Swiften/TLS/TLSContext.h b/Swiften/TLS/TLSContext.h
index 55a86cd..9b0a2eb 100644
--- a/Swiften/TLS/TLSContext.h
+++ b/Swiften/TLS/TLSContext.h
@@ -50,7 +50,6 @@ namespace Swift {
             virtual ByteArray getFinishMessage() const = 0;
             virtual ByteArray getPeerFinishMessage() const;
 
-
         public:
             enum class Mode {
                 Client,
diff --git a/Swiften/TLS/TLSError.h b/Swiften/TLS/TLSError.h
index ae775e6..9e4af2f 100644
--- a/Swiften/TLS/TLSError.h
+++ b/Swiften/TLS/TLSError.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2016 Isode Limited.
+ * Copyright (c) 2012-2019 Isode Limited.
  * All rights reserved.
  * See the COPYING file for more information.
  */
@@ -7,6 +7,7 @@
 #pragma once
 
 #include <memory>
+#include <string>
 
 #include <Swiften/Base/API.h>
 #include <Swiften/Base/Error.h>
@@ -18,16 +19,23 @@ namespace Swift {
 
             enum Type {
                 UnknownError,
-                CertificateCardRemoved
+                CertificateCardRemoved,
+                AcceptFailed,
+                ConnectFailed
             };
 
-            TLSError(Type type = UnknownError) : type(type) {}
+            TLSError(Type type = UnknownError, std::string message = "") : type_(type), message_(std::move(message)) {}
 
             Type getType() const {
-                return type;
+                return type_;
+            }
+
+            const std::string& getMessage() const {
+                return message_;
             }
 
         private:
-            Type type;
+            Type type_;
+            std::string message_;
     };
 }
-- 
cgit v0.10.2-6-g49f6