summaryrefslogtreecommitdiff
path: root/cpp/src/IceSSL/SecureTransportTransceiverI.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/IceSSL/SecureTransportTransceiverI.cpp')
-rw-r--r--cpp/src/IceSSL/SecureTransportTransceiverI.cpp221
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&)
{