Merge branch 'sslwarn'

pull/324/head
Tatsuhiro Tsujikawa 2015-01-05 18:57:24 +09:00
commit cc36df2625
1 changed files with 74 additions and 42 deletions

View File

@ -831,16 +831,19 @@ bool SocketCore::tlsConnect(const std::string& hostname)
bool SocketCore::tlsHandshake(TLSContext* tlsctx, 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; wantRead_ = false;
wantWrite_ = 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"); A2_LOG_DEBUG("Creating TLS session");
tlsSession_.reset(TLSSession::make(tlsctx)); tlsSession_.reset(TLSSession::make(tlsctx));
rv = tlsSession_->init(sockfd_); auto rv = tlsSession_->init(sockfd_);
if(rv != TLS_ERR_OK) { if(rv != TLS_ERR_OK) {
std::string error = tlsSession_->getLastErrorString(); std::string error = tlsSession_->getLastErrorString();
tlsSession_.reset(); tlsSession_.reset();
@ -857,59 +860,88 @@ bool SocketCore::tlsHandshake(TLSContext* tlsctx, const std::string& hostname)
tlsSession_->getLastErrorString().c_str())); tlsSession_->getLastErrorString().c_str()));
} }
} }
// Done with the setup, now let handshaking begin immediately.
secure_ = A2_TLS_HANDSHAKING; secure_ = A2_TLS_HANDSHAKING;
A2_LOG_DEBUG("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) { if(tlsctx->getSide() == TLS_CLIENT) {
rv = tlsSession_->tlsConnect(hostname, ver, handshakeError); rv = tlsSession_->tlsConnect(hostname, ver, handshakeError);
} else { } else {
rv = tlsSession_->tlsAccept(ver); rv = tlsSession_->tlsAccept(ver);
} }
if(rv == TLS_ERR_OK) { 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; 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", throw DL_ABORT_EX(fmt("SSL/TLS handshake failure: %s",
handshakeError.empty() ? handshakeError.empty() ?
tlsSession_->getLastErrorString().c_str() : tlsSession_->getLastErrorString().c_str() :
handshakeError.c_str())); handshakeError.c_str()));
} }
if(tlsSession_->checkDirection() == TLS_WANT_READ) {
wantRead_ = true; // Some implementation passed back an invalid result.
} else { throw DL_ABORT_EX(fmt(EX_SSL_INIT_FAILURE,
wantWrite_ = true; "Invalid connect state (this is a bug in the TLS "
} "backend!)"));
return false;
default:
break;
} }
std::stringstream ss; // We should never get here, i.e. all possible states should have been handled
if (!hostname.empty()) { // and returned from a branch before! Getting here is a bug, of course!
ss << hostname << " ("; throw DL_ABORT_EX(fmt(EX_SSL_INIT_FAILURE, "Invalid state (this is a bug!)"));
}
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;
}
return true;
} }
#endif // ENABLE_SSL #endif // ENABLE_SSL