summaryrefslogtreecommitdiff
path: root/src/SocketCore.cc
diff options
context:
space:
mode:
authorNils Maier <maierman@web.de>2014-12-29 03:50:26 +0100
committerNils Maier <maierman@web.de>2014-12-30 22:36:24 +0100
commit0895008e5c542297162517f11809e8f0aacbd78d (patch)
tree87fc32a9e4dac5f41cd514612ff6fff61e27e3f8 /src/SocketCore.cc
parent590aa21c68b854a7acdacc34d5a1f10f73483432 (diff)
Fix SSLv3 warnings being issued on connection reuse.
And also improve tlsHandshake code a bit in the process, mostly by being more explicit about error conditions.
Diffstat (limited to 'src/SocketCore.cc')
-rw-r--r--src/SocketCore.cc114
1 files changed, 73 insertions, 41 deletions
diff --git a/src/SocketCore.cc b/src/SocketCore.cc
index a4c0aafc..a726a9ab 100644
--- a/src/SocketCore.cc
+++ b/src/SocketCore.cc
@@ -831,16 +831,19 @@ bool SocketCore::tlsConnect(const std::string& hostname)
bool SocketCore::tlsHandshake(TLSContext* tlsctx, const std::string& hostname)
{
- TLSVersion ver = TLS_PROTO_NONE;
- int rv = 0;
- std::string handshakeError;
wantRead_ = false;
wantWrite_ = false;
- switch(secure_) {
- case A2_TLS_NONE:
+
+ if(secure_ == A2_TLS_CONNECTED) {
+ // Already connected!
+ return true;
+ }
+
+ if(secure_ == A2_TLS_NONE) {
+ // Do some initial setup
A2_LOG_DEBUG("Creating TLS session");
tlsSession_.reset(TLSSession::make(tlsctx));
- rv = tlsSession_->init(sockfd_);
+ auto rv = tlsSession_->init(sockfd_);
if(rv != TLS_ERR_OK) {
std::string error = tlsSession_->getLastErrorString();
tlsSession_.reset();
@@ -857,59 +860,88 @@ bool SocketCore::tlsHandshake(TLSContext* tlsctx, const std::string& hostname)
tlsSession_->getLastErrorString().c_str()));
}
}
+ // Done with the setup, now let handshaking begin immediately.
secure_ = A2_TLS_HANDSHAKING;
A2_LOG_DEBUG("TLS Handshaking");
- // Fall through
- case A2_TLS_HANDSHAKING:
+ }
+
+ if(secure_ == A2_TLS_HANDSHAKING) {
+ // Starting handshake after intial setup or still handshaking.
+ TLSVersion ver = TLS_PROTO_NONE;
+ int rv = 0;
+ std::string handshakeError;
+
if(tlsctx->getSide() == TLS_CLIENT) {
rv = tlsSession_->tlsConnect(hostname, ver, handshakeError);
} else {
rv = tlsSession_->tlsAccept(ver);
}
+
if(rv == TLS_ERR_OK) {
+ // We're good, more or less.
+ // 1. Construct peerinfo
+ std::stringstream ss;
+ if (!hostname.empty()) {
+ ss << hostname << " (";
+ }
+ std::pair<std::string, uint16_t> peer;
+ getPeerInfo(peer);
+ ss << peer.first << ":" << peer.second;
+ if (!hostname.empty()) {
+ ss << ")";
+ }
+ auto peerInfo = ss.str();
+
+ // 2. Issue any warnings
+ switch(ver) {
+ case TLS_PROTO_NONE:
+ A2_LOG_WARN(fmt(MSG_WARN_UNKNOWN_TLS_CONNECTION, peerInfo.c_str()));
+ break;
+ case TLS_PROTO_SSL3:
+ A2_LOG_WARN(fmt(MSG_WARN_OLD_TLS_CONNECTION,
+ "SSLv3", peerInfo.c_str()));
+ break;
+ default:
+ A2_LOG_DEBUG(fmt("Securely connected to %s", peerInfo.c_str()));
+ break;
+ }
+
+ // 3. We're connected now!
secure_ = A2_TLS_CONNECTED;
- break;
+ return true;
}
- if(rv != TLS_ERR_WOULDBLOCK) {
+
+ if(rv == TLS_ERR_WOULDBLOCK) {
+ // We're not done yet...
+ if(tlsSession_->checkDirection() == TLS_WANT_READ) {
+ // ... but read buffers are empty.
+ wantRead_ = true;
+ } else {
+ // ... but write buffers are full.
+ wantWrite_ = true;
+ }
+ // Returning false (instead of true==success or throwing) will cause this
+ // function to be called again once buffering is dealt with
+ return false;
+ }
+
+ if (rv == TLS_ERR_ERROR) {
+ // Damn those error.
throw DL_ABORT_EX(fmt("SSL/TLS handshake failure: %s",
handshakeError.empty() ?
tlsSession_->getLastErrorString().c_str() :
handshakeError.c_str()));
}
- if(tlsSession_->checkDirection() == TLS_WANT_READ) {
- wantRead_ = true;
- } else {
- wantWrite_ = true;
- }
- return false;
- default:
- break;
- }
-
- std::stringstream ss;
- if (!hostname.empty()) {
- ss << hostname << " (";
- }
- std::pair<std::string, uint16_t> peer;
- getPeerInfo(peer);
- ss << peer.first << ":" << peer.second;
- if (!hostname.empty()) {
- ss << ")";
- }
- auto peerInfo = ss.str();
- switch(ver) {
- case TLS_PROTO_NONE:
- A2_LOG_WARN(fmt(MSG_WARN_UNKNOWN_TLS_CONNECTION, peerInfo.c_str()));
- break;
- case TLS_PROTO_SSL3:
- A2_LOG_WARN(fmt(MSG_WARN_OLD_TLS_CONNECTION, "SSLv3", peerInfo.c_str()));
- break;
- default:
- break;
+ // Some implementation passed back an invalid result.
+ throw DL_ABORT_EX(fmt(EX_SSL_INIT_FAILURE,
+ "Invalid connect state (this is a bug in the TLS "
+ "backend!)"));
}
- return true;
+ // We should never get here, i.e. all possible states should have been handled
+ // and returned from a branch before! Getting here is a bug, of course!
+ throw DL_ABORT_EX(fmt(EX_SSL_INIT_FAILURE, "Invalid state (this is a bug!)"));
}
#endif // ENABLE_SSL