diff options
Diffstat (limited to 'cpp/src/IceSSL/SecureTransportTransceiverI.cpp')
-rw-r--r-- | cpp/src/IceSSL/SecureTransportTransceiverI.cpp | 221 |
1 files changed, 110 insertions, 111 deletions
diff --git a/cpp/src/IceSSL/SecureTransportTransceiverI.cpp b/cpp/src/IceSSL/SecureTransportTransceiverI.cpp index c6d78809827..020d3c30e39 100644 --- a/cpp/src/IceSSL/SecureTransportTransceiverI.cpp +++ b/cpp/src/IceSSL/SecureTransportTransceiverI.cpp @@ -18,6 +18,7 @@ using namespace std; using namespace Ice; +using namespace IceInternal; using namespace IceSSL; namespace @@ -96,7 +97,8 @@ socketRead(SSLConnectionRef connection, void* data, size_t* length) } bool -checkTrustResult(SecTrustRef trust, const SecureTransportEnginePtr& engine, const InstancePtr& instance) +checkTrustResult(SecTrustRef trust, const SecureTransportEnginePtr& engine, const IceSSL::InstancePtr& instance, + const string& host) { OSStatus err = noErr; SecTrustResultType trustResult = kSecTrustResultOtherError; @@ -115,6 +117,27 @@ checkTrustResult(SecTrustRef trust, const SecureTransportEnginePtr& engine, cons throw SecurityException(__FILE__, __LINE__, "IceSSL: handshake failure:\n" + errorToString(err)); } +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) + if(engine->getCheckCertName() && !host.empty()) + { + // + // Add SSL trust policy if we need to check the certificate name. + // + UniqueRef<SecPolicyRef> policy(SecPolicyCreateSSL(false, toCFString(host))); + UniqueRef<CFArrayRef> policies; + if((err = SecTrustCopyPolicies(trust, &policies.get()))) + { + throw SecurityException(__FILE__, __LINE__, "IceSSL: handshake failure:\n" + errorToString(err)); + } + UniqueRef<CFMutableArrayRef> newPolicies(CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, policies.get())); + CFArrayAppendValue(newPolicies.get(), policy.release()); + if((err = SecTrustSetPolicies(trust, newPolicies.release()))) + { + throw SecurityException(__FILE__, __LINE__, "IceSSL: handshake failure:\n" + errorToString(err)); + } + } +#endif + // // Evaluate the trust // @@ -171,32 +194,43 @@ checkTrustResult(SecTrustRef trust, const SecureTransportEnginePtr& engine, cons IceInternal::NativeInfoPtr IceSSL::TransceiverI::getNativeInfo() { - return _stream; + return _delegate->getNativeInfo(); } IceInternal::SocketOperation -IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::Buffer& writeBuffer, bool&) +IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::Buffer& writeBuffer) { - IceInternal::SocketOperation status = _stream->connect(readBuffer, writeBuffer); - if(status != IceInternal::SocketOperationNone) + if(!_connected) { - return status; + IceInternal::SocketOperation status = _delegate->initialize(readBuffer, writeBuffer); + if(status != IceInternal::SocketOperationNone) + { + return status; + } + _connected = true; } + // + // Limit the size of packets passed to SSLWrite/SSLRead to avoid + // blocking and holding too much memory. + // + _maxSendPacketSize = std::max(512, IceInternal::getSendBufferSize(_delegate->getNativeInfo()->fd())); + _maxRecvPacketSize = std::max(512, IceInternal::getRecvBufferSize(_delegate->getNativeInfo()->fd())); + OSStatus err = 0; if(!_ssl) { // // Initialize SSL context // - _ssl = _engine->newContext(_incoming); - if((err = SSLSetIOFuncs(_ssl, socketRead, socketWrite))) + _ssl.reset(_engine->newContext(_incoming)); + if((err = SSLSetIOFuncs(_ssl.get(), socketRead, socketWrite))) { throw SecurityException(__FILE__, __LINE__, "IceSSL: setting IO functions failed\n" + errorToString(err)); } - if((err = SSLSetConnection(_ssl, reinterpret_cast<SSLConnectionRef>(this)))) + if((err = SSLSetConnection(_ssl.get(), reinterpret_cast<SSLConnectionRef>(this)))) { throw SecurityException(__FILE__, __LINE__, "IceSSL: setting SSL connection failed\n" + errorToString(err)); @@ -204,14 +238,14 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B } SSLSessionState state; - SSLGetSessionState(_ssl, &state); + SSLGetSessionState(_ssl.get(), &state); // // SSL Handshake // while(state == kSSLHandshake || state == kSSLIdle) { - err = SSLHandshake(_ssl); + err = SSLHandshake(_ssl.get()); if(err == noErr) { break; // We're done! @@ -224,8 +258,9 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B else if(err == errSSLPeerAuthCompleted) { assert(!_trust); - err = SSLCopyPeerTrust(_ssl, &_trust); - if(_incoming && _engine->getVerifyPeer() == 1 && (err == errSSLBadCert || _trust == 0)) + err = SSLCopyPeerTrust(_ssl.get(), &_trust.get()); + + if(_incoming && _engine->getVerifyPeer() == 1 && (err == errSSLBadCert || !_trust)) { // This is expected if the client doesn't provide a certificate. With 10.10 and 10.11 errSSLBadCert // is expected, the server is configured to verify but not require the client @@ -234,7 +269,7 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B } if(err == noErr) { - _verified = checkTrustResult(_trust, _engine, _instance); + _verified = checkTrustResult(_trust.get(), _engine, _instance, _host); continue; // Call SSLHandshake to resume the handsake. } // Let it fall through, this will raise a SecurityException with the SSLCopyPeerTrust error. @@ -244,18 +279,12 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B throw ConnectionLostException(__FILE__, __LINE__, 0); } - IceInternal::Address remoteAddr; - string desc = "<not available>"; - if(IceInternal::fdToRemoteAddress(_stream->fd(), remoteAddr)) - { - desc = IceInternal::addrToString(remoteAddr); - } ostringstream os; os << "IceSSL: ssl error occurred for new " << (_incoming ? "incoming" : "outgoing") << " connection:\n" - << "remote address = " << desc << "\n" << errorToString(err); + << _delegate->toString() << "\n" << errorToString(err); throw ProtocolException(__FILE__, __LINE__, os.str()); } - _engine->verifyPeer(_stream->fd(), _host, NativeConnectionInfoPtr::dynamicCast(getInfo())); + _engine->verifyPeer(_host, ICE_DYNAMIC_CAST(NativeConnectionInfo, getInfo()), toString()); if(_instance->engine()->securityTraceLevel() >= 1) { @@ -264,11 +293,11 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B out << "SSL summary for " << (_incoming ? "incoming" : "outgoing") << " connection\n"; SSLProtocol protocol; - SSLGetNegotiatedProtocolVersion(_ssl, &protocol); + SSLGetNegotiatedProtocolVersion(_ssl.get(), &protocol); const string sslProtocolName = protocolName(protocol); SSLCipherSuite cipher; - SSLGetNegotiatedCipher(_ssl, &cipher); + SSLGetNegotiatedCipher(_ssl.get(), &cipher); const string sslCipherName = _engine->getCipherName(cipher); if(sslCipherName.empty()) @@ -297,28 +326,22 @@ IceSSL::TransceiverI::closing(bool initiator, const Ice::LocalException&) void IceSSL::TransceiverI::close() { - if(_trust) - { - CFRelease(_trust); - _trust = 0; - } - + _trust.reset(0); if(_ssl) { - SSLClose(_ssl); - CFRelease(_ssl); - _ssl = 0; + SSLClose(_ssl.get()); } + _ssl.reset(0); - _stream->close(); + _delegate->close(); } IceInternal::SocketOperation IceSSL::TransceiverI::write(IceInternal::Buffer& buf) { - if(!_stream->isConnected()) + if(!_connected) { - return _stream->write(buf); + return _delegate->write(buf); } if(buf.i == buf.b.end()) @@ -333,8 +356,8 @@ IceSSL::TransceiverI::write(IceInternal::Buffer& buf) while(buf.i != buf.b.end()) { size_t processed = 0; - OSStatus err = _buffered ? SSLWrite(_ssl, 0, 0, &processed) : - SSLWrite(_ssl, reinterpret_cast<const void*>(buf.i), packetSize, &processed); + OSStatus err = _buffered ? SSLWrite(_ssl.get(), 0, 0, &processed) : + SSLWrite(_ssl.get(), reinterpret_cast<const void*>(buf.i), packetSize, &processed); if(err) { @@ -393,11 +416,11 @@ IceSSL::TransceiverI::write(IceInternal::Buffer& buf) } IceInternal::SocketOperation -IceSSL::TransceiverI::read(IceInternal::Buffer& buf, bool& hasMoreData) +IceSSL::TransceiverI::read(IceInternal::Buffer& buf) { - if(!_stream->isConnected()) + if(!_connected) { - return _stream->read(buf); + return _delegate->read(buf); } if(buf.i == buf.b.end()) @@ -405,11 +428,13 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf, bool& hasMoreData) return IceInternal::SocketOperationNone; } + _delegate->getNativeInfo()->ready(IceInternal::SocketOperationRead, false); + size_t packetSize = std::min(static_cast<size_t>(buf.b.end() - buf.i), _maxRecvPacketSize); while(buf.i != buf.b.end()) { size_t processed = 0; - OSStatus err = SSLRead(_ssl, reinterpret_cast<void*>(buf.i), packetSize, &processed); + OSStatus err = SSLRead(_ssl.get(), reinterpret_cast<void*>(buf.i), packetSize, &processed); if(err) { if(err == errSSLWouldBlock) @@ -453,16 +478,16 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf, bool& hasMoreData) } // - // Check if there's still buffered data to read. In this case, set hasMoreData to true. + // Check if there's still buffered data to read. In this case, set the read ready status. // size_t buffered = 0; - OSStatus err = SSLGetBufferedReadSize(_ssl, &buffered); + OSStatus err = SSLGetBufferedReadSize(_ssl.get(), &buffered); if(err) { errno = err; throw SocketException(__FILE__, __LINE__, IceInternal::getSocketErrno()); } - hasMoreData = buffered > 0; + _delegate->getNativeInfo()->ready(IceInternal::SocketOperationRead, buffered > 0); return IceInternal::SocketOperationNone; } @@ -475,7 +500,7 @@ IceSSL::TransceiverI::protocol() const string IceSSL::TransceiverI::toString() const { - return _stream->toString(); + return _delegate->toString(); } string @@ -487,17 +512,31 @@ IceSSL::TransceiverI::toDetailedString() const Ice::ConnectionInfoPtr IceSSL::TransceiverI::getInfo() const { - NativeConnectionInfoPtr info = new NativeConnectionInfo(); - fillConnectionInfo(info, info->nativeCerts); - return info; -} + NativeConnectionInfoPtr info = ICE_MAKE_SHARED(NativeConnectionInfo); + info->underlying = _delegate->getInfo(); + info->incoming = _incoming; + info->adapterName = _adapterName; + if(_ssl) + { + for(int i = 0, count = SecTrustGetCertificateCount(_trust.get()); i < count; ++i) + { + SecCertificateRef cert = SecTrustGetCertificateAtIndex(_trust.get(), i); + CFRetain(cert); -Ice::ConnectionInfoPtr -IceSSL::TransceiverI::getWSInfo(const Ice::HeaderDict& headers) const -{ - WSSNativeConnectionInfoPtr info = new WSSNativeConnectionInfo(); - fillConnectionInfo(info, info->nativeCerts); - info->headers = headers; + CertificatePtr certificate = ICE_MAKE_SHARED(Certificate, cert); + info->nativeCerts.push_back(certificate); + info->certs.push_back(certificate->encode()); + } + + SSLCipherSuite cipher; + SSLGetNegotiatedCipher(_ssl.get(), &cipher); + info->cipher = _engine->getCipherName(cipher); + info->verified = _verified; + } + else + { + info->verified = false; + } return info; } @@ -509,11 +548,11 @@ IceSSL::TransceiverI::checkSendSize(const IceInternal::Buffer&) void IceSSL::TransceiverI::setBufferSize(int rcvSize, int sndSize) { - _stream->setBufferSize(rcvSize, sndSize); + _delegate->setBufferSize(rcvSize, sndSize); } -IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance, - const IceInternal::StreamSocketPtr& stream, +IceSSL::TransceiverI::TransceiverI(const IceSSL::InstancePtr& instance, + const IceInternal::TransceiverPtr& delegate, const string& hostOrAdapterName, bool incoming) : _instance(instance), @@ -521,61 +560,17 @@ IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance, _host(incoming ? "" : hostOrAdapterName), _adapterName(incoming ? hostOrAdapterName : ""), _incoming(incoming), - _stream(stream), - _ssl(0), - _trust(0), + _delegate(delegate), + _connected(false), _verified(false), _buffered(0) { - // - // Limit the size of packets passed to SSLWrite/SSLRead to avoid - // blocking and holding too much memory. - // - _maxSendPacketSize = std::max(512, IceInternal::getSendBufferSize(_stream->fd())); - _maxRecvPacketSize = std::max(512, IceInternal::getRecvBufferSize(_stream->fd())); } IceSSL::TransceiverI::~TransceiverI() { } -void -IceSSL::TransceiverI::fillConnectionInfo(const ConnectionInfoPtr& info, std::vector<CertificatePtr>& nativeCerts) const -{ - IceInternal::fdToAddressAndPort(_stream->fd(), info->localAddress, info->localPort, info->remoteAddress, - info->remotePort); - if(_stream->fd() != INVALID_SOCKET) - { - info->rcvSize = IceInternal::getRecvBufferSize(_stream->fd()); - info->sndSize = IceInternal::getSendBufferSize(_stream->fd()); - } - - if(_ssl) - { - for(int i = 0, count = SecTrustGetCertificateCount(_trust); i < count; ++i) - { - SecCertificateRef cert = SecTrustGetCertificateAtIndex(_trust, i); - CFRetain(cert); - - CertificatePtr certificate = new Certificate(cert); - nativeCerts.push_back(certificate); - info->certs.push_back(certificate->encode()); - } - - SSLCipherSuite cipher; - SSLGetNegotiatedCipher(_ssl, &cipher); - info->cipher = _engine->getCipherName(cipher); - info->verified = _verified; - } - else - { - info->verified = false; - } - - info->adapterName = _adapterName; - info->incoming = _incoming; -} - OSStatus IceSSL::TransceiverI::writeRaw(const char* data, size_t* length) const { @@ -583,13 +578,15 @@ IceSSL::TransceiverI::writeRaw(const char* data, size_t* length) const try { - ssize_t ret = _stream->write(data, *length); - if(ret < *length) + IceInternal::Buffer buf(reinterpret_cast<const Ice::Byte*>(data), reinterpret_cast<const Ice::Byte*>(data) + *length); + IceInternal::SocketOperation op = _delegate->write(buf); + if(op == IceInternal::SocketOperationWrite) { - *length = static_cast<size_t>(ret); + *length = buf.i - buf.b.begin(); _flags |= SSLWantWrite; return errSSLWouldBlock; } + assert(op == IceInternal::SocketOperationNone); } catch(const Ice::ConnectionLostException&) { @@ -614,13 +611,15 @@ IceSSL::TransceiverI::readRaw(char* data, size_t* length) const try { - ssize_t ret = _stream->read(data, *length); - if(ret < *length) + IceInternal::Buffer buf(reinterpret_cast<Ice::Byte*>(data), reinterpret_cast<Ice::Byte*>(data) + *length); + IceInternal::SocketOperation op = _delegate->read(buf); + if(op == IceInternal::SocketOperationRead) { - *length = static_cast<size_t>(ret); + *length = buf.i - buf.b.begin(); _flags |= SSLWantRead; return errSSLWouldBlock; } + assert(op == IceInternal::SocketOperationNone); } catch(const Ice::ConnectionLostException&) { |