diff options
Diffstat (limited to 'cpp/src/IceSSL/SslTransceiver.cpp')
-rw-r--r-- | cpp/src/IceSSL/SslTransceiver.cpp | 995 |
1 files changed, 478 insertions, 517 deletions
diff --git a/cpp/src/IceSSL/SslTransceiver.cpp b/cpp/src/IceSSL/SslTransceiver.cpp index 501fb30248e..b23974e1ebf 100644 --- a/cpp/src/IceSSL/SslTransceiver.cpp +++ b/cpp/src/IceSSL/SslTransceiver.cpp @@ -9,23 +9,16 @@ #include <Ice/LoggerUtil.h> #include <Ice/Stats.h> -#include <Ice/Buffer.h> #include <Ice/Network.h> #include <Ice/LocalException.h> -#include <Ice/Properties.h> -#include <IceSSL/OpenSSL.h> #include <IceSSL/SslTransceiver.h> -#include <IceSSL/OpenSSLPluginI.h> #include <IceSSL/TraceLevels.h> #include <IceSSL/Exception.h> #include <IceSSL/OpenSSLPluginI.h> -#include <IceSSL/CertificateVerifierOpenSSL.h> #include <IceSSL/OpenSSLUtils.h> #include <openssl/err.h> -#include <sstream> - using namespace std; using namespace Ice; using namespace IceInternal; @@ -63,19 +56,12 @@ IceSSL::SslTransceiver::close() try { - int shutdown = 0; - int numRetries = 100; - int retries = -numRetries; - do - { - shutdown = internalShutdownWrite(0); - retries++; - } - while((shutdown == 0) && (retries < 0)); + internalShutdownWrite(10 * 1000); } - catch(...) + catch(const Ice::Exception& e) { - // Ignore, close() should not throw exceptions. + Warning warn(_logger); + warn << "error in shutting down ssl connection " << e; } assert(_fd != INVALID_SOCKET); @@ -100,15 +86,15 @@ IceSSL::SslTransceiver::shutdownWrite() out << "shutting down ssl connection for writing\n" << toString(); } - int shutdown = 0; - int numRetries = 100; - int retries = -numRetries; - do + try { - shutdown = internalShutdownWrite(0); - retries++; + internalShutdownWrite(10 * 1000); + } + catch(const Ice::Exception& e) + { + Warning warn(_logger); + warn << "error in shutting down ssl connection " << e; } - while((shutdown == 0) && (retries < 0)); assert(_fd != INVALID_SOCKET); shutdownSocketWrite(_fd); @@ -123,212 +109,267 @@ IceSSL::SslTransceiver::shutdownReadWrite() out << "shutting down ssl connection for reading and writing\n" << toString(); } -/* - int shutdown = 0; - int numRetries = 100; - int retries = -numRetries; - do - { - shutdown = internalShutdownWrite(0); - retries++; - } - while((shutdown == 0) && (retries < 0)); -*/ - assert(_fd != INVALID_SOCKET); shutdownSocketReadWrite(_fd); } void -IceSSL::SslTransceiver::read(Buffer& buf, int timeout) +IceSSL::SslTransceiver::write(Buffer& buf, int timeout) { assert(_fd != INVALID_SOCKET); _plugin->registerThread(); + Buffer::Container::difference_type packetSize = static_cast<Buffer::Container::difference_type>(buf.b.end() - buf.i); - int totalBytesRead = 0; - int bytesRead; - int initReturn = 0; +#ifdef _WIN32 + // + // Limit packet size to avoid performance problems on WIN32. + // + if(packetSize > 64 * 1024) + { + packetSize = 64 * 1024; + } +#endif - // We keep reading until we're done. + // We keep writing until we're done. while(buf.i != buf.b.end()) { - // Ensure we're initialized. - initReturn = initialize(timeout); - - if(initReturn == -1) + ERR_clear_error(); + int ret = SSL_write(_sslConnection, &*buf.i, static_cast<int>(packetSize)); + switch(SSL_get_error(_sslConnection, ret)) { - // Handshake underway, timeout immediately, easy way to deal with this. - throw TimeoutException(__FILE__, __LINE__); - } + case SSL_ERROR_NONE: + break; + + case SSL_ERROR_WANT_WRITE: + { + writeSelect(timeout); + break; + } + + // + // If session renegotiation is ever enabled this could + // occur. + // + //case SSL_ERROR_WANT_READ: + //{ + // readSelect(timeout); + // break; + //} - if(initReturn == 0) - { - // Retry the initialize call - continue; - } + case SSL_ERROR_SYSCALL: + { + if(ret == -1) + { + // IO Error in underlying BIO - // initReturn must be > 0, so we're okay to try a read + if(interrupted()) + { + continue; + } - if(!pending() && !readSelect(_readTimeout)) - { - // Nothing is left to read (according to SSL). - if(_traceLevels->security >= IceSSL::SECURITY_PROTOCOL) + if(noBuffers() && packetSize > 1024) + { + packetSize /= 2; + continue; + } + + // + // Its not clear whether this can occur, isn't + // this the same as SSL_ERROR_WANT_WRITE? + // + if(wouldBlock()) + { + writeSelect(timeout); + continue; + } + + if(connectionLost()) + { + ConnectionLostException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } + else + { + SocketException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } + } + // fall through + } + + case SSL_ERROR_ZERO_RETURN: { - Trace out(_logger, _traceLevels->securityCat); - out << "no pending application-level bytes"; + assert(ret == 0); + ConnectionLostException ex(__FILE__, __LINE__); + ex.error = 0; + throw ex; } - // We're done here. - break; + case SSL_ERROR_SSL: + { + ProtocolException ex(__FILE__, __LINE__); + ex.message = "encountered a violation of the ssl protocol\n"; + ex.message += IceSSL::sslGetErrors(); + throw ex; + } + + default: + { + Warning warn(_logger); + warn << "IceSSL: unexpected result from SSL_write: " << SSL_get_error(_sslConnection, ret); + } } - _readTimeout = timeout; + if(_traceLevels->network >= 3) + { + Trace out(_logger, _traceLevels->networkCat); + out << "sent " << ret << " of " << packetSize; out << " bytes via ssl\n" + << fdToString(SSL_get_fd(_sslConnection)); + } - bytesRead = sslRead(&*buf.i, static_cast<Int>(packetSize)); + if(_stats) + { + _stats->bytesSent(type(), ret); + } - switch(getLastError()) - { - case SSL_ERROR_NONE: - { - if(bytesRead > 0) - { - if(_traceLevels->network >= 3) - { - Trace out(_logger, _traceLevels->networkCat); - out << "received " << bytesRead << " of " << packetSize; - out << " bytes via ssl\n" << toString(); - } + buf.i += ret; - if(_stats) - { - _stats->bytesReceived(type(), bytesRead); - } + if(packetSize > buf.b.end() - buf.i) + { + packetSize = static_cast<Buffer::Container::difference_type>(buf.b.end() - buf.i); + } + } +} - totalBytesRead += bytesRead; +void +IceSSL::SslTransceiver::read(Buffer& buf, int timeout) +{ + assert(_fd != INVALID_SOCKET); - buf.i += bytesRead; + _plugin->registerThread(); - if(packetSize > buf.b.end() - buf.i) - { - packetSize = static_cast<Buffer::Container::difference_type>(buf.b.end() - buf.i); - } - } - continue; - } + Buffer::Container::difference_type packetSize = + static_cast<Buffer::Container::difference_type>(buf.b.end() - buf.i); + + while(buf.i != buf.b.end()) + { + ERR_clear_error(); + int ret = SSL_read(_sslConnection, &*buf.i, static_cast<Int>(packetSize)); + switch(SSL_get_error(_sslConnection, ret)) + { + case SSL_ERROR_NONE: + break; case SSL_ERROR_WANT_READ: { - if(!readSelect(timeout)) - { - // Timeout and wait for them to arrive. - throw TimeoutException(__FILE__, __LINE__); - } + readSelect(timeout); continue; } - case SSL_ERROR_WANT_WRITE: - case SSL_ERROR_WANT_X509_LOOKUP: - { - // Perform another read. The read should take care of this. - continue; - } + // + // If session renegotiation is ever enabled this could + // occur. + // + //case SSL_ERROR_WANT_WRITE: + //{ + // writeSelect(timeout); + // break; + //} case SSL_ERROR_SYSCALL: { - if(bytesRead == -1) + if(ret == -1) { // IO Error in underlying BIO if(interrupted()) { - break; + continue; } + if(noBuffers() && packetSize > 1024) + { + packetSize /= 2; + continue; + } + + // + // Its not clear whether this can occur, isn't + // this the same as SSL_ERROR_WANT_READ? + // if(wouldBlock()) { - break; + readSelect(timeout); + continue; } - if(connectionLost()) + if(!connectionLost()) { - // - // If the connection is lost when reading data, we shut - // down the write end of the socket. This helps to unblock - // threads that are stuck in send() or select() while - // sending data. Note: I don't really understand why - // send() or select() sometimes don't detect a connection - // loss. Therefore this helper to make them detect it. - // - //assert(_fd != INVALID_SOCKET); - //shutdownSocket(_fd); - - ConnectionLostException ex(__FILE__, __LINE__); - ex.error = getSocketErrno(); - throw ex; - } - - SocketException ex(__FILE__, __LINE__); - ex.error = getSocketErrno(); - throw ex; - } - else // (bytesRead == 0) - { - // - // See the commment above about shutting down the - // socket if the connection is lost while reading - // data. - // - //assert(_fd != INVALID_SOCKET); - //shutdownSocket(_fd); - - ConnectionLostException ex(__FILE__, __LINE__); - ex.error = 0; - throw ex; + SocketException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } } - } - - case SSL_ERROR_SSL: - { - ProtocolException protocolEx(__FILE__, __LINE__); - - protocolEx.message = "encountered a violation of the ssl protocol\n"; - protocolEx.message += sslGetErrors(); - - throw protocolEx; - } + // fall throught + } case SSL_ERROR_ZERO_RETURN: - { + { + // - // See the commment above about shutting down the - // socket if the connection is lost while reading - // data. + // If the connection is lost when reading data, we shut + // down the write end of the socket. This helps to unblock + // threads that are stuck in send() or select() while + // sending data. Note: I don't really understand why + // send() or select() sometimes don't detect a connection + // loss. Therefore this helper to make them detect it. // //assert(_fd != INVALID_SOCKET); //shutdownSocket(_fd); - // Indicates that that the SSL Connection has been closed. - // But does not necessarily indicate that the underlying transport - // has been closed (in the case of Ice, it definitely hasn't yet). + ConnectionLostException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } - ConnectionLostException ex(__FILE__, __LINE__); - ex.error = getSocketErrno(); + case SSL_ERROR_SSL: + { + ProtocolException ex(__FILE__, __LINE__); + ex.message = "encountered a violation of the ssl protocol\n"; + ex.message += sslGetErrors(); throw ex; } - } - } - if(totalBytesRead == 0) - { - if(_traceLevels->security >= IceSSL::SECURITY_WARNINGS) - { - Trace out(_logger, _traceLevels->securityCat); - out << "WRN reading from ssl connection returns no bytes"; + default: + { + Warning warn(_logger); + warn << "IceSSL: unexpected result from SSL_write: " << SSL_get_error(_sslConnection, ret); + } } + + if(_traceLevels->network >= 3) + { + Trace out(_logger, _traceLevels->networkCat); + out << "received " << ret << " of " << packetSize; out << " bytes via ssl\n" << toString(); + } + + if(_stats) + { + _stats->bytesReceived(type(), ret); + } + + buf.i += ret; + + if(packetSize > buf.b.end() - buf.i) + { + packetSize = static_cast<Buffer::Container::difference_type>(buf.b.end() - buf.i); + } } } @@ -345,48 +386,163 @@ IceSSL::SslTransceiver::toString() const } void -IceSSL::SslTransceiver::forceHandshake() +IceSSL::SslTransceiver::initialize(int timeout) { - try - { - if(handshake(_readTimeout) > 0) - { - return; // Handshake complete. - } - } - catch(const TimeoutException&) + assert(_sslConnection != 0); + + if(_traceLevels->security >= IceSSL::SECURITY_PROTOCOL) { - // Fall through. + Trace out(_logger, _traceLevels->securityCat); + out << "Performing handshake.\n"; + out << fdToString(SSL_get_fd(_sslConnection)); } - if(_traceLevels->security >= IceSSL::SECURITY_WARNINGS) + while(true) { - Trace out(_logger, _traceLevels->securityCat); - if(_readTimeout >= 0) + ERR_clear_error(); + int result; + if(_contextType == IceSSL::Client) { - out << "Timeout occurred during SSL handshake.\n" << toString(); + result = SSL_connect(_sslConnection); } else { - out << "Failure occurred during SSL handshake.\n" << toString(); + result = SSL_accept(_sslConnection); } - } - - close(); - if(_readTimeout >= 0) - { - throw ConnectTimeoutException(__FILE__, __LINE__); - } - else - { - ConnectionRefusedException ex(__FILE__, __LINE__); -#ifdef _WIN32 - ex.error = WSAECONNREFUSED; -#else - ex.error = ECONNREFUSED; + // + // Success? + // + if(result == 1) + { + assert(SSL_is_init_finished(_sslConnection)); + + // + // Init finished, look at the connection information. + // + if((_traceLevels->security >= IceSSL::SECURITY_PROTOCOL_DEBUG) && 0) + { +#ifdef ICE_SSL_EXTRA_TRACING + // + // Only in extreme cases do we enable this, partially because it doesn't use the Logger. + // + BIOJanitor bioJanitor(BIO_new_fp(stdout, BIO_NOCLOSE)); + BIO* bio = bioJanitor.get(); + + showCertificateChain(bio); + + showPeerCertificate(bio, _contextType == IceSSL::Server : "Server" ? "Client"); + + showSharedCiphers(bio); + + showSelectedCipherInfo(bio); + + showHandshakeStats(bio); + + showSessionInfo(bio); #endif - throw ex; + } + return; + } + + switch(SSL_get_error(_sslConnection, result)) + { + case SSL_ERROR_WANT_READ: + { + readSelect(timeout); + continue; + } + + case SSL_ERROR_WANT_WRITE: + { + writeSelect(timeout); + continue; + } + + case SSL_ERROR_NONE: + { + continue; + } + + case SSL_ERROR_WANT_X509_LOOKUP: + { + Warning warn(_logger); + warn << "SSL_ERROR_NONE"; + continue; + } + + case SSL_ERROR_SYSCALL: + { + if(result == -1) + { + if(interrupted()) + { + break; + } + + assert(!wouldBlock()); + + if(connectionLost()) + { + ConnectionLostException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } + } + + SocketException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } + + case SSL_ERROR_SSL: + { + long err = SSL_get_verify_result(_sslConnection); + if(err != X509_V_OK) + { + // + // On a client we raise the CertificateVerificationException. On the + // server side we simply close the connection. + // + if(_contextType == IceSSL::Client) + { + CertificateVerificationException ex(__FILE__, __LINE__); + ex.message = getVerificationError(err); + string errors = sslGetErrors(); + if(!errors.empty()) + { + ex.message += "\n"; + ex.message += errors; + } + throw ex; + } + else + { + // + // Validation failed, close the connection. + // + throw ConnectionRefusedException(__FILE__, __LINE__); + } + } + + // + // This happens if the client or server silently drop + // the connection. That can occur if the server + // doesn't trust the client for example. + // + ProtocolException ex(__FILE__, __LINE__); + ex.message = "encountered a violation of the ssl protocol during handshake\n"; + ex.message += sslGetErrors(); + throw ex; + } + + case SSL_ERROR_ZERO_RETURN: + { + ConnectionLostException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } + } } } @@ -405,10 +561,11 @@ IceSSL::SslTransceiver::getTransceiver(SSL* sslPtr) } // -// Note: Do not throw exceptions from verifyCertificate - it would rip through the OpenSSL system, -// interfering with the usual handling and alert system of the handshake. Exceptions should -// be caught here (if they can be generated), logged and then a fail return code (0) should -// returned. +// Note: Do not throw exceptions from verifyCertificate - it would rip +// through the OpenSSL system, interfering with the usual handling and +// alert system of the handshake. Exceptions should be caught here +// (if they can be generated), logged and then a fail return code (0) +// should returned. // int IceSSL::SslTransceiver::verifyCertificate(int preVerifyOkay, X509_STORE_CTX* x509StoreContext) @@ -468,305 +625,112 @@ IceSSL::SslTransceiver::verifyCertificate(int preVerifyOkay, X509_STORE_CTX* x50 // Protected Methods // -// Note: I would use a using directive of the form: -// using IceSSL::CertificateVerifierPtr; -// but unfortunately, it appears that this is not properly picked up. -// - -int +void IceSSL::SslTransceiver::internalShutdownWrite(int timeout) { - if(_sslConnection == 0) - { - return 1; - } - - int retCode = 0; - - if(_initWantWrite) - { - int i = writeSelect(timeout); - - if(i == 0) - { - return 0; - } - - _initWantWrite = 0; - } - else if(_initWantRead) - { - int i = readSelect(timeout); - - if(i == 0) - { - return 0; - } - - _initWantRead = 0; - } - - ERR_clear_error(); - - retCode = SSL_shutdown(_sslConnection); - - if(retCode == 1) - { - // Shutdown successful - shut down the socket for writing. - shutdownSocketWrite(SSL_get_fd(_sslConnection)); - } - else if(retCode == -1) - { - setLastError(retCode); - - // Shutdown failed due to an error. - - switch(getLastError()) - { - case SSL_ERROR_WANT_WRITE: - { - _initWantWrite = 1; - retCode = 0; - break; - } - - case SSL_ERROR_WANT_READ: - { - _initWantRead = 1; - retCode = 0; - break; - } - - case SSL_ERROR_NONE: - case SSL_ERROR_WANT_X509_LOOKUP: - { - // Ignore - retCode = 0; - break; - } - - case SSL_ERROR_SYSCALL: - { - // - // Some error with the underlying transport. - // - - if(interrupted()) - { - retCode = 0; - break; - } - - if(wouldBlock()) - { - readSelect(timeout); - retCode = 0; - break; - } - - if(connectionLost()) - { - ConnectionLostException ex(__FILE__, __LINE__); - ex.error = getSocketErrno(); - throw ex; - } - - // - // Non-specific socket problem. - // - SocketException ex(__FILE__, __LINE__); - ex.error = getSocketErrno(); - throw ex; - } - - case SSL_ERROR_SSL: - { - // - // Error in the SSL library, usually a Protocol error. - // - - ProtocolException protocolEx(__FILE__, __LINE__); - - protocolEx.message = "encountered a violation of the ssl protocol during shutdown\n"; - protocolEx.message += sslGetErrors(); - - throw protocolEx; - } - - case SSL_ERROR_ZERO_RETURN: - { - // - // Indicates that the SSL connection has been closed. For SSLv3.0 - // and TLSv1.0, it indicates that a closure alert was received, - // and thus the connection has been closed cleanly. - // - - CloseConnectionException ex(__FILE__, __LINE__); - throw ex; - } - } - } - - return retCode; -} - -int -IceSSL::SslTransceiver::connect() -{ - assert(_sslConnection != 0); - - ERR_clear_error(); - int result = SSL_connect(_sslConnection); - - setLastError(result); - - return result; -} - -int -IceSSL::SslTransceiver::accept() -{ - assert(_sslConnection != 0); - - ERR_clear_error(); - int result = SSL_accept(_sslConnection); - - setLastError(result); - - return result; -} - -// NOTE: Currently not used, maybe later. -int -IceSSL::SslTransceiver::renegotiate() -{ - assert(_sslConnection != 0); - return SSL_renegotiate(_sslConnection); -} - -int -IceSSL::SslTransceiver::initialize(int timeout) -{ - int retCode = 0; - while(true) { - // One lucky thread will get the honor of carrying out the hanshake, - // if there is one to perform. The HandshakeSentinel effectively - // establishes a first-come, first-serve policy. One thread will own - // the handshake, and the others will either return rejected to the - // caller (who will figure out what to do with them) OR wait until - // our lead thread is done. Then, the shuffle begins again. - // Eventually, all threads will filter through. - - HandshakeSentinel handshakeSentinel(_handshakeFlag); - - if(!handshakeSentinel.ownHandshake()) - { - if(timeout >= 0) - { - // We should return immediately here - do not block, - // leave it to the caller to figure this out. - retCode = -1; - break; - } - else - { - // We will wait here - blocking IO is being used. - IceUtil::Mutex::Lock sync(_handshakeWaitMutex); - } - } - else - { - // Perform our init(), then leave. - IceUtil::Mutex::Lock sync(_handshakeWaitMutex); - - // Here we 'take the ball and run with it' for as long as we can - // get away with it. As long as we don't encounter some error - // status (or completion), this thread continues to service the - // initialize() call. - while(retCode == 0) - { - switch(_phase) - { - case Handshake : - { - retCode = handshake(timeout); - break; - } - - case Shutdown : - { - retCode = internalShutdownWrite(timeout); - break; - } - - case Connected : - { - retCode = SSL_is_init_finished(_sslConnection); - - if(!retCode) - { - // In this case, we are essentially renegotiating - // the connection at the behest of the peer. - _phase = Handshake; - continue; - } - - // Done here. - return retCode; - } - } - } - - break; - } - } - - return retCode; -} - -int -IceSSL::SslTransceiver::pending() -{ - assert(_sslConnection != 0); - return SSL_pending(_sslConnection); -} - -int -IceSSL::SslTransceiver::getLastError() const -{ - assert(_sslConnection != 0); - return SSL_get_error(_sslConnection, _lastError); -} - -int -IceSSL::SslTransceiver::sslRead(unsigned char* buffer, int bufferSize) -{ - assert(_sslConnection != 0); - - ERR_clear_error(); - int bytesRead = SSL_read(_sslConnection, buffer, bufferSize); + ERR_clear_error(); + int result = SSL_shutdown(_sslConnection); + if(result == 0) + { + // + // From the documentation: + // + // The shutdown is not yet finished. Call SSL_shutdown() + // for a second time, if a bidirectional shutdown shall be + // performed. The output of SSL_get_error(3) may be + // misleading, as an erroneous SSL_ERROR_SYSCALL may be + // flagged even though no error occurred. + // + // Call it one more time. If the result is 0 then we're done. + // + result = SSL_shutdown(_sslConnection); + if(result == 0) + { + return; + } + } + if(result == 1) + { + // Shutdown successful - shut down the socket for writing. + shutdownSocketWrite(SSL_get_fd(_sslConnection)); + return; + } + else if(result == -1) + { + switch(SSL_get_error(_sslConnection, result)) + { + case SSL_ERROR_WANT_WRITE: + { + writeSelect(timeout); + continue; + } + + case SSL_ERROR_WANT_READ: + { + readSelect(timeout); + continue; + } + + case SSL_ERROR_NONE: + case SSL_ERROR_WANT_X509_LOOKUP: + { + continue; + } + + case SSL_ERROR_SYSCALL: + { + if(interrupted()) + { + continue; + } - setLastError(bytesRead); + assert(!wouldBlock()); - return bytesRead; -} + if(connectionLost()) + { + ConnectionLostException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } -int -IceSSL::SslTransceiver::sslWrite(unsigned char* buffer, int bufferSize) -{ - assert(_sslConnection != 0); + // + // Non-specific socket problem. + // + SocketException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } - ERR_clear_error(); - int bytesWritten = SSL_write(_sslConnection, buffer, bufferSize); + case SSL_ERROR_SSL: + { + // + // Error in the SSL library, usually a Protocol error. + // - setLastError(bytesWritten); + ProtocolException ex(__FILE__, __LINE__); + ex.message = "encountered a violation of the ssl protocol during shutdown\n"; + ex.message += sslGetErrors(); + throw ex; + } - return bytesWritten; + case SSL_ERROR_ZERO_RETURN: + { + // + // Indicates that the SSL connection has been + // closed. For SSLv3.0 and TLSv1.0, it indicates + // that a closure alert was received, and thus the + // connection has been closed cleanly. + // + throw CloseConnectionException(__FILE__, __LINE__); + } + } + } + } } -int +void IceSSL::SslTransceiver::select(int timeout, bool write) { int ret; @@ -824,20 +788,18 @@ IceSSL::SslTransceiver::select(int timeout, bool write) { throw TimeoutException(__FILE__, __LINE__); } - - return FD_ISSET(fd, &rwFdSet); } -int +void IceSSL::SslTransceiver::readSelect(int timeout) { - return select(timeout, false); + select(timeout, false); } -int +void IceSSL::SslTransceiver::writeSelect(int timeout) { - return select(timeout, true); + select(timeout, true); } // @@ -1044,34 +1006,34 @@ IceSSL::SslTransceiver::showClientCAList(BIO* bio, const char* connType) // Private Methods // -IceSSL::SslTransceiver::SslTransceiver(const OpenSSLPluginIPtr& plugin, +IceSSL::SslTransceiver::SslTransceiver(const ContextType contextType, + const OpenSSLPluginIPtr& plugin, SOCKET fd, const CertificateVerifierPtr& certificateVerifier, SSL* sslConnection, int timeout) : - _sslConnection(sslConnection), - _readTimeout(timeout), + _contextType(contextType), _plugin(plugin), - _traceLevels(plugin->getTraceLevels()), - _logger(plugin->getLogger()), - _stats(plugin->getStats()), _fd(fd), - _certificateVerifier(certificateVerifier) + _certificateVerifier(certificateVerifier), + _sslConnection(sslConnection), + _logger(plugin->getLogger()), + _traceLevels(plugin->getTraceLevels()), + _stats(plugin->getStats()) { assert(sslConnection != 0); - FD_ZERO(&_rFdSet); - FD_ZERO(&_wFdSet); - SSL_set_ex_data(sslConnection, 0, static_cast<void*>(plugin.get())); - // We always start off in a Handshake - _phase = Handshake; - - _lastError = SSL_ERROR_NONE; - - _initWantRead = 0; - _initWantWrite = 0; + // Set the Connect Connection state for this connection. + if(contextType == IceSSL::Client) + { + SSL_set_connect_state(_sslConnection); + } + else + { + SSL_set_accept_state(_sslConnection); + } // Set up the SSL to be able to refer back to our connection object. addTransceiver(_sslConnection, this); @@ -1079,11 +1041,10 @@ IceSSL::SslTransceiver::SslTransceiver(const OpenSSLPluginIPtr& plugin, IceSSL::SslTransceiver::~SslTransceiver() { - if(_sslConnection != 0) - { - removeTransceiver(_sslConnection); - SSL_set_ex_data(_sslConnection, 0, 0); - SSL_free(_sslConnection); - _sslConnection = 0; - } + assert(_sslConnection != 0); + + removeTransceiver(_sslConnection); + SSL_set_ex_data(_sslConnection, 0, 0); + SSL_free(_sslConnection); + _sslConnection = 0; } |