diff options
Diffstat (limited to 'cpp/src/IceSSL/OpenSSLTransceiverI.cpp')
-rw-r--r-- | cpp/src/IceSSL/OpenSSLTransceiverI.cpp | 367 |
1 files changed, 170 insertions, 197 deletions
diff --git a/cpp/src/IceSSL/OpenSSLTransceiverI.cpp b/cpp/src/IceSSL/OpenSSLTransceiverI.cpp index a8341206ebf..8df471c87eb 100644 --- a/cpp/src/IceSSL/OpenSSLTransceiverI.cpp +++ b/cpp/src/IceSSL/OpenSSLTransceiverI.cpp @@ -74,275 +74,242 @@ IceSSL::TransceiverI::getNativeInfo() IceInternal::SocketOperation IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::Buffer& writeBuffer, bool&) { - try + if(_state == StateNeedConnect) { - if(_state == StateNeedConnect) - { - _state = StateConnectPending; - return IceInternal::SocketOperationConnect; - } - else if(_state <= StateConnectPending) - { - IceInternal::doFinishConnect(_fd); + _state = StateConnectPending; + return IceInternal::SocketOperationConnect; + } + else if(_state <= StateConnectPending) + { + IceInternal::doFinishConnect(_fd); - _desc = IceInternal::fdToString(_fd, _proxy, _addr, true); + _desc = IceInternal::fdToString(_fd, _proxy, _addr, true); + + if(_proxy) + { + // + // Prepare the read & write buffers in advance. + // + _proxy->beginWriteConnectRequest(_addr, writeBuffer); + _proxy->beginReadConnectRequestResponse(readBuffer); - if(_proxy) + // + // Write the proxy connection message using TCP. + // + if(writeRaw(writeBuffer)) { // - // Prepare the read & write buffers in advance. + // Write completed without blocking. // - _proxy->beginWriteConnectRequest(_addr, writeBuffer); - _proxy->beginReadConnectRequestResponse(readBuffer); + _proxy->endWriteConnectRequest(writeBuffer); // - // Write the proxy connection message using TCP. + // Try to read the response using TCP. // - if(writeRaw(writeBuffer)) + if(readRaw(readBuffer)) { // - // Write completed without blocking. - // - _proxy->endWriteConnectRequest(writeBuffer); - - // - // Try to read the response using TCP. + // Read completed without blocking - fall through. // - if(readRaw(readBuffer)) - { - // - // Read completed without blocking - fall through. - // - _proxy->endReadConnectRequestResponse(readBuffer); - } - else - { - // - // Return SocketOperationRead to indicate we need to complete the read. - // - _state = StateProxyConnectRequestPending; // Wait for proxy response - return IceInternal::SocketOperationRead; - } + _proxy->endReadConnectRequestResponse(readBuffer); } else { // - // Return SocketOperationWrite to indicate we need to complete the write. + // Return SocketOperationRead to indicate we need to complete the read. // - _state = StateProxyConnectRequest; // Send proxy connect request - return IceInternal::SocketOperationWrite; + _state = StateProxyConnectRequestPending; // Wait for proxy response + return IceInternal::SocketOperationRead; } } - - _state = StateConnected; - } - else if(_state == StateProxyConnectRequest) - { - // - // Write completed. - // - _proxy->endWriteConnectRequest(writeBuffer); - _state = StateProxyConnectRequestPending; // Wait for proxy response - return IceInternal::SocketOperationRead; + else + { + // + // Return SocketOperationWrite to indicate we need to complete the write. + // + _state = StateProxyConnectRequest; // Send proxy connect request + return IceInternal::SocketOperationWrite; + } } - else if(_state == StateProxyConnectRequestPending) + + _state = StateConnected; + } + else if(_state == StateProxyConnectRequest) + { + // + // Write completed. + // + _proxy->endWriteConnectRequest(writeBuffer); + _state = StateProxyConnectRequestPending; // Wait for proxy response + return IceInternal::SocketOperationRead; + } + else if(_state == StateProxyConnectRequestPending) + { + // + // Read completed. + // + _proxy->endReadConnectRequestResponse(readBuffer); + _state = StateConnected; + } + + assert(_state == StateConnected); + + if(!_ssl) + { + // + // This static_cast is necessary due to 64bit windows. There SOCKET is a non-int type. + // + BIO* bio = BIO_new_socket(static_cast<int>(_fd), 0); + if(!bio) { - // - // Read completed. - // - _proxy->endReadConnectRequestResponse(readBuffer); - _state = StateConnected; + SecurityException ex(__FILE__, __LINE__); + ex.reason = "openssl failure"; + throw ex; } - assert(_state == StateConnected); - + _ssl = SSL_new(_engine->context()); if(!_ssl) { - // - // This static_cast is necessary due to 64bit windows. There SOCKET is a non-int type. - // - BIO* bio = BIO_new_socket(static_cast<int>(_fd), 0); - if(!bio) - { - SecurityException ex(__FILE__, __LINE__); - ex.reason = "openssl failure"; - throw ex; - } - - _ssl = SSL_new(_engine->context()); - if(!_ssl) - { - BIO_free(bio); - SecurityException ex(__FILE__, __LINE__); - ex.reason = "openssl failure"; - throw ex; - } - SSL_set_bio(_ssl, bio, bio); + BIO_free(bio); + SecurityException ex(__FILE__, __LINE__); + ex.reason = "openssl failure"; + throw ex; } + SSL_set_bio(_ssl, bio, bio); + } - while(!SSL_is_init_finished(_ssl)) - { - // - // Only one thread calls initialize(), so synchronization is not necessary here. - // + while(!SSL_is_init_finished(_ssl)) + { + // + // Only one thread calls initialize(), so synchronization is not necessary here. + // - // - // BUGFIX: an openssl bug that affects OpensSSL < 1.0.0k - // could cause a deadlock when decoding public keys. - // - // See: http://cvs.openssl.org/chngview?cn=22569 - // + // + // BUGFIX: an openssl bug that affects OpensSSL < 1.0.0k + // could cause a deadlock when decoding public keys. + // + // See: http://cvs.openssl.org/chngview?cn=22569 + // #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x100000bfL - IceUtilInternal::MutexPtrLock<IceUtil::Mutex> sync(sslMutex); + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> sync(sslMutex); #endif - int ret = _incoming ? SSL_accept(_ssl) : SSL_connect(_ssl); + int ret = _incoming ? SSL_accept(_ssl) : SSL_connect(_ssl); #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x100000bfL - sync.release(); + sync.release(); #endif - if(ret <= 0) + if(ret <= 0) + { + switch(SSL_get_error(_ssl, ret)) { - switch(SSL_get_error(_ssl, ret)) - { - case SSL_ERROR_NONE: - assert(SSL_is_init_finished(_ssl)); - break; - case SSL_ERROR_ZERO_RETURN: + case SSL_ERROR_NONE: + assert(SSL_is_init_finished(_ssl)); + break; + case SSL_ERROR_ZERO_RETURN: + { + ConnectionLostException ex(__FILE__, __LINE__); + ex.error = IceInternal::getSocketErrno(); + throw ex; + } + case SSL_ERROR_WANT_READ: + { + return IceInternal::SocketOperationRead; + } + case SSL_ERROR_WANT_WRITE: + { + return IceInternal::SocketOperationWrite; + } + case SSL_ERROR_SYSCALL: + { + if(ret == 0) { ConnectionLostException ex(__FILE__, __LINE__); - ex.error = IceInternal::getSocketErrno(); + ex.error = 0; throw ex; } - case SSL_ERROR_WANT_READ: - { - return IceInternal::SocketOperationRead; - } - case SSL_ERROR_WANT_WRITE: - { - return IceInternal::SocketOperationWrite; - } - case SSL_ERROR_SYSCALL: + + if(ret == -1) { - if(ret == 0) + if(IceInternal::interrupted()) { - ConnectionLostException ex(__FILE__, __LINE__); - ex.error = 0; - throw ex; + break; } - if(ret == -1) + if(IceInternal::wouldBlock()) { - if(IceInternal::interrupted()) + if(SSL_want_read(_ssl)) { - break; + return IceInternal::SocketOperationRead; } - - if(IceInternal::wouldBlock()) + else if(SSL_want_write(_ssl)) { - if(SSL_want_read(_ssl)) - { - return IceInternal::SocketOperationRead; - } - else if(SSL_want_write(_ssl)) - { - return IceInternal::SocketOperationWrite; - } - - break; + return IceInternal::SocketOperationWrite; } - if(IceInternal::connectionLost()) - { - ConnectionLostException ex(__FILE__, __LINE__); - ex.error = IceInternal::getSocketErrno(); - throw ex; - } + break; } - SocketException ex(__FILE__, __LINE__); - ex.error = IceInternal::getSocketErrno(); - throw ex; - } - case SSL_ERROR_SSL: - { - IceInternal::Address remoteAddr; - string desc = "<not available>"; - if(IceInternal::fdToRemoteAddress(_fd, remoteAddr)) + + if(IceInternal::connectionLost()) { - desc = IceInternal::addrToString(remoteAddr); + ConnectionLostException ex(__FILE__, __LINE__); + ex.error = IceInternal::getSocketErrno(); + throw ex; } - ostringstream ostr; - ostr << "SSL error occurred for new " << (_incoming ? "incoming" : "outgoing") - << " connection:\nremote address = " << desc << "\n" << _engine->sslErrors(); - ProtocolException ex(__FILE__, __LINE__); - ex.reason = ostr.str(); - throw ex; - } } + SocketException ex(__FILE__, __LINE__); + ex.error = IceInternal::getSocketErrno(); + throw ex; } - } - - long result = SSL_get_verify_result(_ssl); - if(result != X509_V_OK) - { - if(_engine->getVerifyPeer() == 0) + case SSL_ERROR_SSL: { - if(_engine->securityTraceLevel() >= 1) + IceInternal::Address remoteAddr; + string desc = "<not available>"; + if(IceInternal::fdToRemoteAddress(_fd, remoteAddr)) { - ostringstream ostr; - ostr << "IceSSL: ignoring certificate verification failure:\n" - << X509_verify_cert_error_string(result); - _instance->logger()->trace(_instance->traceCategory(), ostr.str()); + desc = IceInternal::addrToString(remoteAddr); } - } - else - { ostringstream ostr; - ostr << "IceSSL: certificate verification failed:\n" << X509_verify_cert_error_string(result); - string msg = ostr.str(); - if(_engine->securityTraceLevel() >= 1) - { - _instance->logger()->trace(_instance->traceCategory(), msg); - } - SecurityException ex(__FILE__, __LINE__); - ex.reason = msg; + ostr << "SSL error occurred for new " << (_incoming ? "incoming" : "outgoing") + << " connection:\nremote address = " << desc << "\n" << _engine->sslErrors(); + ProtocolException ex(__FILE__, __LINE__); + ex.reason = ostr.str(); throw ex; } - } - _engine->verifyPeer(_fd, _host, getNativeConnectionInfo()); - _state = StateHandshakeComplete; - } - catch(const Ice::LocalException& ex) - { - if(_instance->traceLevel() >= 2) - { - Trace out(_instance->logger(), _instance->traceCategory()); - out << "failed to establish " << _instance->protocol() << " connection\n"; - if(_incoming) - { - out << IceInternal::fdToString(_fd) << "\n" << ex; - } - else - { - out << IceInternal::fdToString(_fd, _proxy, _addr, false) << "\n" << ex; } } - throw; } - if(_instance->traceLevel() >= 1) + long result = SSL_get_verify_result(_ssl); + if(result != X509_V_OK) { - Trace out(_instance->logger(), _instance->traceCategory()); - if(_incoming) + if(_engine->getVerifyPeer() == 0) { - out << "accepted " << _instance->protocol() << " connection\n" << _desc; + if(_engine->securityTraceLevel() >= 1) + { + ostringstream ostr; + ostr << "IceSSL: ignoring certificate verification failure:\n" + << X509_verify_cert_error_string(result); + _instance->logger()->trace(_instance->traceCategory(), ostr.str()); + } } else { - out << _instance->protocol() << " connection established\n" << _desc; + ostringstream ostr; + ostr << "IceSSL: certificate verification failed:\n" << X509_verify_cert_error_string(result); + string msg = ostr.str(); + if(_engine->securityTraceLevel() >= 1) + { + _instance->logger()->trace(_instance->traceCategory(), msg); + } + SecurityException ex(__FILE__, __LINE__); + ex.reason = msg; + throw ex; } } + _engine->verifyPeer(_fd, _host, getNativeConnectionInfo()); + _state = StateHandshakeComplete; if(_engine->securityTraceLevel() >= 1) { @@ -706,6 +673,12 @@ IceSSL::TransceiverI::toString() const return _desc; } +string +IceSSL::TransceiverI::toDetailedString() const +{ + return toString(); +} + Ice::ConnectionInfoPtr IceSSL::TransceiverI::getInfo() const { |