← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 3175: Improve OpenSSL error handling

 

------------------------------------------------------------
revno: 3175
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Mon 2013-01-21 17:09:46 +0100
message:
  Improve OpenSSL error handling
modified:
  changelog.txt
  dcpp/SSLSocket.cpp
  dcpp/SSLSocket.h


--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk

Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'changelog.txt'
--- changelog.txt	2013-01-18 21:01:15 +0000
+++ changelog.txt	2013-01-21 16:09:46 +0000
@@ -16,6 +16,7 @@
 * [L#1096465] Add "user online" / "user offline" status lines to PMs (emtee, poy)
 * Apply "send unknown /commands" to PMs (poy)
 * Don't clear the message box when trying to send a message to a disconnected hub (poy)
+* Improve OpenSSL error handling
 
 Note: The hash registry will be upgraded when running this version for the
 first time. Make sure all your drives are connected to avoid re-hashing.

=== modified file 'dcpp/SSLSocket.cpp'
--- dcpp/SSLSocket.cpp	2013-01-18 21:28:38 +0000
+++ dcpp/SSLSocket.cpp	2013-01-21 16:09:46 +0000
@@ -144,21 +144,33 @@
 		return -1;
 	}
 	if(ret <= 0) {
-		int err = SSL_get_error(ssl, ret);
+		/* inspired by boost.asio (asio/ssl/detail/impl/engine.ipp, function engine::perform) and
+		the SSL_get_error doc at <https://www.openssl.org/docs/ssl/SSL_get_error.html>. */
+		auto err = SSL_get_error(ssl, ret);
 		switch(err) {
-			case SSL_ERROR_NONE:		// Fallthrough - YaSSL doesn't for example return an openssl compatible error on recv fail
-			case SSL_ERROR_WANT_READ:	// Fallthrough
-			case SSL_ERROR_WANT_WRITE:
-				return -1;
-			case SSL_ERROR_ZERO_RETURN:
-				throw SocketException(_("Connection closed"));
-			default:
-				{
-					ssl.reset();
-					// @todo replace 80 with MAX_ERROR_SZ or whatever's appropriate for yaSSL in some nice way...
-					char errbuf[80];
-					throw SSLSocketException(str(F_("SSL Error: %1% (%2%, %3%)") % ERR_error_string(err, errbuf) % ret % err));
+		case SSL_ERROR_NONE:		// Fallthrough - YaSSL doesn't for example return an openssl compatible error on recv fail
+		case SSL_ERROR_WANT_READ:	// Fallthrough
+		case SSL_ERROR_WANT_WRITE:
+			return -1;
+		case SSL_ERROR_ZERO_RETURN:
+			throw SocketException(_("Connection closed"));
+		case SSL_ERROR_SYSCALL:
+			{
+				auto sys_err = ERR_get_error();
+				if(sys_err == 0) {
+					if(ret == 0) {
+						throw SSLSocketException(_("TLS error"));
+					}
+					sys_err = ::GetLastError();
 				}
+				throw SSLSocketException(sys_err);
+			}
+		default:
+			/* don't bother getting error messages from the codes because 1) there is some
+			additional management necessary (eg SSL_load_error_strings) and 2) openssl error codes
+			aren't shown to the end user; they only hit standard output in debug builds. */
+			dcdebug("TLS error: call ret = %1%, SSL_get_error = %2%, ERR_get_error = %3%", ret, err, ERR_get_error());
+			throw SSLSocketException(_("TLS error"));
 		}
 	}
 	return ret;

=== modified file 'dcpp/SSLSocket.h'
--- dcpp/SSLSocket.h	2013-01-18 21:28:38 +0000
+++ dcpp/SSLSocket.h	2013-01-21 16:09:46 +0000
@@ -33,6 +33,7 @@
 #else //_DEBUG
 	SSLSocketException(const string& aError) noexcept : SocketException(aError) { }
 #endif // _DEBUG
+	SSLSocketException(int aError) noexcept : SocketException(aError) { }
 
 	virtual ~SSLSocketException() throw() { }
 };