diff options
author | Benoit Foucher <benoit@zeroc.com> | 2016-06-27 17:54:30 +0200 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2016-06-27 17:54:30 +0200 |
commit | c56f8ab6ca6ca0bdb9536fcce1ef24f1ef40ddc7 (patch) | |
tree | 5cb64dfe155e5d2349efb6c7dc4b0f5b5284d44a /cpp/src/IceSSL | |
parent | Fix Windows php build to restore nuget packages (diff) | |
download | ice-c56f8ab6ca6ca0bdb9536fcce1ef24f1ef40ddc7.tar.bz2 ice-c56f8ab6ca6ca0bdb9536fcce1ef24f1ef40ddc7.tar.xz ice-c56f8ab6ca6ca0bdb9536fcce1ef24f1ef40ddc7.zip |
Refactored SSL and iAP transports, support for running SSL on top
of TCP/iAP/Bluetooth.
Diffstat (limited to 'cpp/src/IceSSL')
32 files changed, 1816 insertions, 1035 deletions
diff --git a/cpp/src/IceSSL/AcceptorI.cpp b/cpp/src/IceSSL/AcceptorI.cpp index 7f8c70341ed..8042fb8d195 100644 --- a/cpp/src/IceSSL/AcceptorI.cpp +++ b/cpp/src/IceSSL/AcceptorI.cpp @@ -11,23 +11,15 @@ #include <IceSSL/EndpointI.h> #include <IceSSL/Instance.h> + #include <IceSSL/OpenSSLTransceiverI.h> #include <IceSSL/SecureTransportTransceiverI.h> #include <IceSSL/SChannelTransceiverI.h> +#include <IceSSL/WinRTTransceiverI.h> #include <IceSSL/Util.h> -#include <Ice/Communicator.h> -#include <Ice/Exception.h> #include <Ice/LocalException.h> -#include <Ice/LoggerUtil.h> -#include <Ice/Properties.h> -#include <Ice/StreamSocket.h> -#include <IceUtil/StringUtil.h> - -#ifdef ICE_USE_IOCP -# include <Mswsock.h> -#endif using namespace std; using namespace Ice; @@ -38,90 +30,43 @@ IceUtil::Shared* IceSSL::upCast(AcceptorI* p) { return p; } IceInternal::NativeInfoPtr IceSSL::AcceptorI::getNativeInfo() { - return this; + return _delegate->getNativeInfo(); } -#ifdef ICE_USE_IOCP +#if defined(ICE_USE_IOCP) || defined(ICE_OS_WINRT) IceInternal::AsyncInfo* -IceSSL::AcceptorI::getAsyncInfo(IceInternal::SocketOperation) +IceSSL::AcceptorI::getAsyncInfo(IceInternal::SocketOperation status) { - return &_info; + return _delegate->getNativeInfo()->getAsyncInfo(status); } #endif void IceSSL::AcceptorI::close() { - if(_fd != INVALID_SOCKET) - { - IceInternal::closeSocketNoThrow(_fd); - _fd = INVALID_SOCKET; - } + _delegate->close(); } IceInternal::EndpointIPtr IceSSL::AcceptorI::listen() { - try - { - const_cast<IceInternal::Address&>(_addr) = IceInternal::doBind(_fd, _addr); - IceInternal::doListen(_fd, _backlog); - } - catch(...) - { - _fd = INVALID_SOCKET; - throw; - } - _endpoint = _endpoint->endpoint(this); + _endpoint = _endpoint->endpoint(_delegate->listen()); return _endpoint; } -#ifdef ICE_USE_IOCP +#if defined(ICE_USE_IOCP) || defined(ICE_OS_WINRT) void IceSSL::AcceptorI::startAccept() { - LPFN_ACCEPTEX AcceptEx = NULL; // a pointer to the 'AcceptEx()' function - GUID GuidAcceptEx = WSAID_ACCEPTEX; // The Guid - DWORD dwBytes; - if(WSAIoctl(_fd, - SIO_GET_EXTENSION_FUNCTION_POINTER, - &GuidAcceptEx, - sizeof(GuidAcceptEx), - &AcceptEx, - sizeof(AcceptEx), - &dwBytes, - NULL, - NULL) == SOCKET_ERROR) - { - SocketException ex(__FILE__, __LINE__); - ex.error = IceInternal::getSocketErrno(); - throw ex; - } + _delegate->startAccept(); - assert(_acceptFd == INVALID_SOCKET); - _acceptFd = IceInternal::createSocket(false, _addr); - const int sz = static_cast<int>(_acceptBuf.size() / 2); - if(!AcceptEx(_fd, _acceptFd, &_acceptBuf[0], 0, sz, sz, &_info.count, &_info)) - { - if(!IceInternal::wouldBlock()) - { - SocketException ex(__FILE__, __LINE__); - ex.error = IceInternal::getSocketErrno(); - throw ex; - } - } } void IceSSL::AcceptorI::finishAccept() { - if(static_cast<int>(_info.count) == SOCKET_ERROR || _fd == INVALID_SOCKET) - { - IceInternal::closeSocketNoThrow(_acceptFd); - _acceptFd = INVALID_SOCKET; - _acceptError = _info.error; - } + _delegate->finishAccept(); } #endif @@ -138,121 +83,36 @@ IceSSL::AcceptorI::accept() throw ex; } -#ifndef ICE_USE_IOCP - SOCKET fd = IceInternal::doAccept(_fd); -#else - if(_acceptFd == INVALID_SOCKET) - { - SocketException ex(__FILE__, __LINE__); - ex.error = _acceptError; - throw ex; - } - - if(setsockopt(_acceptFd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)&_acceptFd, sizeof(_acceptFd)) == - SOCKET_ERROR) - { - IceInternal::closeSocketNoThrow(_acceptFd); - _acceptFd = INVALID_SOCKET; - SocketException ex(__FILE__, __LINE__); - ex.error = IceInternal::getSocketErrno(); - throw ex; - } - - SOCKET fd = _acceptFd; - _acceptFd = INVALID_SOCKET; -#endif - - // - // SSL handshaking is performed in TransceiverI::initialize, since - // accept must not block. - // - return new TransceiverI(_instance, new IceInternal::StreamSocket(_instance, fd), _adapterName, true); + return new TransceiverI(_instance, _delegate->accept(), _adapterName, true); } string IceSSL::AcceptorI::protocol() const { - return _instance->protocol(); + return _delegate->protocol(); } string IceSSL::AcceptorI::toString() const { - return IceInternal::addrToString(_addr); + return _delegate->toString(); } string IceSSL::AcceptorI::toDetailedString() const { - ostringstream os; - os << "local address = " << toString(); - vector<string> intfs = getHostsForEndpointExpand(inetAddrToString(_addr), _instance->protocolSupport(), true); - if(!intfs.empty()) - { - os << "\nlocal interfaces = "; - os << IceUtilInternal::joinString(intfs, ", "); - } - return os.str(); + return _delegate->toDetailedString(); } -int -IceSSL::AcceptorI::effectivePort() const -{ - if(_addr.saStorage.ss_family == AF_INET) - { - return ntohs(_addr.saIn.sin_port); - } - else - { - return ntohs(_addr.saIn6.sin6_port); - } -} - -IceSSL::AcceptorI::AcceptorI(const EndpointIPtr& endpoint, const InstancePtr& instance, const string& adapterName, - const string& host, int port) : +IceSSL::AcceptorI::AcceptorI(const EndpointIPtr& endpoint, const InstancePtr& instance, + const IceInternal::AcceptorPtr& del, const string& adapterName) : _endpoint(endpoint), _instance(instance), - _adapterName(adapterName), - _addr(IceInternal::getAddressForServer(host, port, instance->protocolSupport(), instance->preferIPv6())) -#ifdef ICE_USE_IOCP - , _acceptFd(INVALID_SOCKET), - _info(IceInternal::SocketOperationRead) -#endif + _delegate(del), + _adapterName(adapterName) { -#ifdef SOMAXCONN - _backlog = instance->properties()->getPropertyAsIntWithDefault("Ice.TCP.Backlog", SOMAXCONN); -#else - _backlog = instance->properties()->getPropertyAsIntWithDefault("Ice.TCP.Backlog", 511); -#endif - - IceInternal::ProtocolSupport protocol = instance->protocolSupport(); - _fd = IceInternal::createServerSocket(false, _addr, protocol); -#ifdef ICE_USE_IOCP - _acceptBuf.resize((sizeof(sockaddr_storage) + 16) * 2); -#endif - IceInternal::setBlock(_fd, false); - IceInternal::setTcpBufSize(_fd, _instance); -#ifndef _WIN32 - // - // Enable SO_REUSEADDR on Unix platforms to allow re-using the - // socket even if it's in the TIME_WAIT state. On Windows, - // this doesn't appear to be necessary and enabling - // SO_REUSEADDR would actually not be a good thing since it - // allows a second process to bind to an address even it's - // already bound by another process. - // - // TODO: using SO_EXCLUSIVEADDRUSE on Windows would probably - // be better but it's only supported by recent Windows - // versions (XP SP2, Windows Server 2003). - // - IceInternal::setReuseAddress(_fd, true); -#endif } IceSSL::AcceptorI::~AcceptorI() { - assert(_fd == INVALID_SOCKET); -#ifdef ICE_USE_IOCP - assert(_acceptFd == INVALID_SOCKET); -#endif } diff --git a/cpp/src/IceSSL/AcceptorI.h b/cpp/src/IceSSL/AcceptorI.h index 465878a24c2..3ee5d5d2d4c 100644 --- a/cpp/src/IceSSL/AcceptorI.h +++ b/cpp/src/IceSSL/AcceptorI.h @@ -25,13 +25,13 @@ class AcceptorI : public IceInternal::Acceptor, public IceInternal::NativeInfo public: virtual IceInternal::NativeInfoPtr getNativeInfo(); -#ifdef ICE_USE_IOCP +#if defined(ICE_USE_IOCP) || defined(ICE_OS_WINRT) virtual IceInternal::AsyncInfo* getAsyncInfo(IceInternal::SocketOperation); #endif virtual void close(); virtual IceInternal::EndpointIPtr listen(); -#ifdef ICE_USE_IOCP +#if defined(ICE_USE_IOCP) || defined(ICE_OS_WINRT) virtual void startAccept(); virtual void finishAccept(); #endif @@ -40,25 +40,16 @@ public: virtual std::string toString() const; virtual std::string toDetailedString() const; - int effectivePort() const; - private: - AcceptorI(const EndpointIPtr&, const InstancePtr&, const std::string&, const std::string&, int); + AcceptorI(const EndpointIPtr&, const InstancePtr&, const IceInternal::AcceptorPtr&, const std::string&); virtual ~AcceptorI(); friend class EndpointI; EndpointIPtr _endpoint; const InstancePtr _instance; + const IceInternal::AcceptorPtr _delegate; const std::string _adapterName; - const IceInternal::Address _addr; - int _backlog; -#ifdef ICE_USE_IOCP - SOCKET _acceptFd; - int _acceptError; - std::vector<char> _acceptBuf; - IceInternal::AsyncInfo _info; -#endif }; } diff --git a/cpp/src/IceSSL/Certificate.cpp b/cpp/src/IceSSL/Certificate.cpp index 61597bdd0fe..5429a96b2e9 100644..100755 --- a/cpp/src/IceSSL/Certificate.cpp +++ b/cpp/src/IceSSL/Certificate.cpp @@ -15,6 +15,7 @@ #include <IceSSL/Util.h> #include <IceSSL/RFC2253.h> #include <Ice/Object.h> +#include <Ice/Base64.h> #if defined(ICE_USE_OPENSSL) # include <openssl/x509v3.h> @@ -42,12 +43,12 @@ extern "C" typedef void (*FreeFunc)(void*); #endif - using namespace std; using namespace Ice; using namespace IceSSL; #if defined(ICE_USE_SECURE_TRANSPORT) || defined(ICE_USE_SCHANNEL) + // // Map a certificate OID to its alias // @@ -80,7 +81,6 @@ const int certificateOIDSSize = sizeof(certificateOIDS) / sizeof(CertificateOID) #endif - #if defined(ICE_USE_SECURE_TRANSPORT) string @@ -98,29 +98,6 @@ certificateOIDAlias(const string& name) return name; } -// -// Map alternative name alias to its types. -// -const char* certificateAlternativeNameTypes[] = {"", "Email Address", "DNS Name", "", "Directory Name", "", "URI", - "IP Address"}; -const int certificateAlternativeNameTypesSize = sizeof(certificateAlternativeNameTypes) / sizeof(char*); - -int -certificateAlternativeNameType(const string& alias) -{ - if(!alias.empty()) - { - for(int i = 0; i < certificateAlternativeNameTypesSize; ++i) - { - if(alias == certificateAlternativeNameTypes[i]) - { - return i; - } - } - } - return -1; // Not supported -} - string escapeX509Name(const string& name) { @@ -149,6 +126,31 @@ escapeX509Name(const string& name) return os.str(); } +#if !defined(ICE_USE_SECURE_TRANSPORT_IOS) + +// +// Map alternative name alias to its types. +// +const char* certificateAlternativeNameTypes[] = {"", "Email Address", "DNS Name", "", "Directory Name", "", "URI", + "IP Address"}; +const int certificateAlternativeNameTypesSize = sizeof(certificateAlternativeNameTypes) / sizeof(char*); + +int +certificateAlternativeNameType(const string& alias) +{ + if(!alias.empty()) + { + for(int i = 0; i < certificateAlternativeNameTypesSize; ++i) + { + if(alias == certificateAlternativeNameTypes[i]) + { + return i; + } + } + } + return -1; // Not supported +} + DistinguishedName getX509Name(SecCertificateRef cert, CFTypeRef key) { @@ -256,8 +258,158 @@ getX509String(SecCertificateRef cert, CFTypeRef key) return value; } -#elif defined(ICE_USE_SCHANNEL) +#else // IOS + +// +// ASN1Parser to pase the subject/issuer ASN.1 DER encoded attributes on iOS. +// +class ASN1Parser +{ +public: + + ASN1Parser(CFDataRef data) : _data(CFDataGetBytePtr(data)), _length(CFDataGetLength(data)), _p(_data), _next(0) + { + } + + list<pair<string, string> > + parse() + { + list<pair<string, string> > rdns; + while(_p < _data + _length) + { + switch(parseByte()) + { + case 0x06: // OID + { + _rdn.first = parseOID(); + break; + } + case 0x12: // NumericString + case 0x13: // PrintableString + case 0x0C: // UTF8String + case 0x16: // IA5String + { + _rdn.second = escapeX509Name(parseUTF8String()); + break; + } + case 0x30: // SEQUENCE + case 0x31: // SET + { + int length = parseLength(0); + _next = _p + length; + if(_next > _data + _length) + { + throw CertificateEncodingException(__FILE__, __LINE__, "invalid length"); + } + break; + } + default: + { + // Unsupported tag, skip the SET. + if(!_next) + { + return rdns; + } + _p = _next; + _next = 0; + break; + } + } + if(_p == _next) + { + rdns.push_back(_rdn); + } + } + return rdns; + } + + string + parseOID() + { + int length = parseLength(1); + ostringstream oid; + unsigned char c = parseByte(); + oid << c / 40 << "." << c % 40; + while(--length > 0) + { + if((*_p & 0x80) == 0) + { + oid << "." << static_cast<int>(parseByte()); + } + else + { + uint64_t result = (uint64_t)(*_p & 127); + while(parseByte() & 128) + { + result = (result << 7) | (uint64_t)(*_p & 127); + --length; + } + oid << "." << result; + } + } + return certificateOIDAlias(oid.str()); + } + + string + parseUTF8String() + { + int length = parseLength(0); + string v(reinterpret_cast<const char*>(_p), length); + _p += length; + return v; + } + int + parseLength(int required) + { + int length = 0; + if((*_p & 0x80) == 0) + { + length = static_cast<int>(parseByte()); + } + else + { + int nbytes = static_cast<int>(parseByte()); + for(int i = 0; i < nbytes; ++i) + { + length = length * 256 + parseByte(); + } + } + if((required > 0 && length < required) || (_p + length > _data + _length)) + { + throw CertificateEncodingException(__FILE__, __LINE__, "invalid length"); + } + return length; + } + + unsigned char + parseByte() + { + if(_p >= _data + _length) + { + throw CertificateEncodingException(__FILE__, __LINE__, "invalid length"); + } + unsigned char b = *_p++; + return b; + } + +private: + + const unsigned char* _data; + const size_t _length; + const unsigned char* _p; + const unsigned char* _next; + pair<string, string> _rdn; + list<pair<string, string> > _rdns; +}; +#endif + +#elif defined(ICE_USE_SCHANNEL) || defined(ICE_OS_WINRT) + +const Ice::Long TICKS_PER_MSECOND = 10000LL; +const Ice::Long MSECS_TO_EPOCH = 11644473600000LL; + +#if defined(ICE_USE_SCHANNEL) void loadCertificate(PCERT_SIGNED_CONTENT_INFO* cert, const char* buffer, DWORD length) { @@ -294,9 +446,6 @@ loadCertificate(PCERT_SIGNED_CONTENT_INFO* cert, const string& file) loadCertificate(cert, &buffer[0], static_cast<DWORD>(buffer.size())); } -const Ice::Long TICKS_PER_MSECOND = 10000LL; -const Ice::Long MSECS_TO_EPOCH = 11644473600000LL; - IceUtil::Time filetimeToTime(FILETIME ftime) { @@ -419,6 +568,32 @@ certificateAltNames(CERT_INFO* certInfo, LPCSTR altNameOID) } return altNames; } +#else + +vector<pair<int, string> > +certificateAltNames(Windows::Security::Cryptography::Certificates::SubjectAlternativeNameInfo^ subAltNames) +{ + vector<pair<int, string> > altNames; + for (auto iter = subAltNames->EmailName->First(); iter->HasCurrent; iter->MoveNext()) + { + altNames.push_back(make_pair(AltNameEmail, IceUtil::wstringToString(iter->Current->Data()))); + } + for (auto iter = subAltNames->DnsName->First(); iter->HasCurrent; iter->MoveNext()) + { + altNames.push_back(make_pair(AltNameDNS, IceUtil::wstringToString(iter->Current->Data()))); + } + for (auto iter = subAltNames->Url->First(); iter->HasCurrent; iter->MoveNext()) + { + altNames.push_back(make_pair(AltNameURL, IceUtil::wstringToString(iter->Current->Data()))); + } + for (auto iter = subAltNames->IPAddress->First(); iter->HasCurrent; iter->MoveNext()) + { + altNames.push_back(make_pair(AltNAmeIP, IceUtil::wstringToString(iter->Current->Data()))); + } + return altNames; +} +#endif + #endif CertificateReadException::CertificateReadException(const char* file, int line, const string& r) : @@ -700,21 +875,25 @@ ParseException::ice_throw() const } #ifdef ICE_USE_OPENSSL -DistinguishedName::DistinguishedName(X509NAME* name) : - _rdns(RFC2253::parseStrict(convertX509NameToString(name))) +DistinguishedName::DistinguishedName(X509NAME* name) : _rdns(RFC2253::parseStrict(convertX509NameToString(name))) { unescape(); } #endif -DistinguishedName::DistinguishedName(const string& dn) : - _rdns(RFC2253::parseStrict(dn)) +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) +DistinguishedName::DistinguishedName(CFDataRef data) : _rdns(ASN1Parser(data).parse()) { unescape(); } +#endif -DistinguishedName::DistinguishedName(const list<pair<string, string> >& rdns) : - _rdns(rdns) +DistinguishedName::DistinguishedName(const string& dn) : _rdns(RFC2253::parseStrict(dn)) +{ + unescape(); +} + +DistinguishedName::DistinguishedName(const list<pair<string, string> >& rdns) : _rdns(rdns) { unescape(); } @@ -810,7 +989,7 @@ PublicKey::~PublicKey() { # if defined(ICE_USE_SECURE_TRANSPORT) CFRelease(_key); -# else +# elif defined(ICE_USE_OPENSSL) EVP_PKEY_free(_key); # endif } @@ -827,9 +1006,6 @@ PublicKey::key() const // The caller is responsible for incrementing the reference count. // Certificate::Certificate(X509CertificateRef cert) : _cert(cert) -#ifdef ICE_USE_SCHANNEL - , _certInfo(0) -#endif { if(!_cert) { @@ -837,6 +1013,7 @@ Certificate::Certificate(X509CertificateRef cert) : _cert(cert) } #ifdef ICE_USE_SCHANNEL + _certInfo = 0; try { // @@ -856,13 +1033,28 @@ Certificate::Certificate(X509CertificateRef cert) : _cert(cert) throw; } #endif + +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) + _subject = NULL; + _issuer = NULL; +#endif } Certificate::~Certificate() { if(_cert) { -#if defined(ICE_USE_SECURE_TRANSPORT) +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) + if(_subject) + { + CFRelease(_subject); + } + if(_issuer) + { + CFRelease(_issuer); + } + CFRelease(_cert); +#elif defined(ICE_USE_SECURE_TRANSPORT_MACOS) CFRelease(_cert); #elif defined(ICE_USE_SCHANNEL) LocalFree(_cert); @@ -870,7 +1062,7 @@ Certificate::~Certificate() { LocalFree(_certInfo); } -#else +#elif defined(ICE_USE_OPENSSL) X509_free(_cert); #endif } @@ -880,12 +1072,20 @@ CertificatePtr Certificate::load(const string& file) { #if defined(ICE_USE_SECURE_TRANSPORT) - return ICE_MAKE_SHARED(Certificate, loadCertificate(file)); + string resolved; + if(checkPath(file, "", false, resolved)) + { + return ICE_MAKE_SHARED(Certificate, loadCertificate(resolved)); + } + else + { + throw CertificateReadException(__FILE__, __LINE__, "error opening file " + file); + } #elif defined(ICE_USE_SCHANNEL) CERT_SIGNED_CONTENT_INFO* cert; loadCertificate(&cert, file); return ICE_MAKE_SHARED(Certificate, cert); -#else +#elif defined(ICE_USE_OPENSSL) BIO *cert = BIO_new(BIO_s_file()); if(BIO_read_filename(cert, file.c_str()) <= 0) { @@ -901,16 +1101,45 @@ Certificate::load(const string& file) } BIO_free(cert); return ICE_MAKE_SHARED(Certificate, x); +#elif defined(ICE_OS_WINRT) + // TODO + return ICE_NULLPTR; +#else +# error "Unknown platform" #endif } CertificatePtr Certificate::decode(const string& encoding) { -#if defined(ICE_USE_SECURE_TRANSPORT) +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) + string::size_type size, startpos, endpos = 0; + startpos = encoding.find("-----BEGIN CERTIFICATE-----", endpos); + if(startpos != string::npos) + { + startpos += sizeof("-----BEGIN CERTIFICATE-----"); + endpos = encoding.find("-----END CERTIFICATE-----", startpos); + size = endpos - startpos; + } + else + { + startpos = 0; + endpos = string::npos; + size = encoding.size(); + } + + vector<unsigned char> data(IceInternal::Base64::decode(string(&encoding[startpos], size))); + UniqueRef<CFDataRef> certdata(CFDataCreate(kCFAllocatorDefault, &data[0], data.size())); + SecCertificateRef cert = SecCertificateCreateWithData(0, certdata.get()); + if(!cert) + { + assert(false); + throw CertificateEncodingException(__FILE__, __LINE__, "certificate is not a valid PEM-encoded certificate"); + } + return ICE_MAKE_SHARED(Certificate, cert); +#elif defined(ICE_USE_SECURE_TRANSPORT_MACOS) CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const UInt8*>(encoding.c_str()), encoding.size(), kCFAllocatorNull); - SecExternalFormat format = kSecFormatUnknown; SecExternalItemType type = kSecItemTypeCertificate; @@ -929,14 +1158,13 @@ Certificate::decode(const string& encoding) SecKeychainItemRef item = (SecKeychainItemRef)CFArrayGetValueAtIndex(items, 0); CFRetain(item); CFRelease(items); - assert(SecCertificateGetTypeID() == CFGetTypeID(item)); return ICE_MAKE_SHARED(Certificate, (SecCertificateRef)item); #elif defined(ICE_USE_SCHANNEL) CERT_SIGNED_CONTENT_INFO* cert; loadCertificate(&cert, encoding.c_str(), static_cast<DWORD>(encoding.size())); return ICE_MAKE_SHARED(Certificate, cert); -#else +#elif defined(ICE_USE_OPENSSL) BIO *cert = BIO_new_mem_buf(static_cast<void*>(const_cast<char*>(&encoding[0])), static_cast<int>(encoding.size())); X509CertificateRef x = PEM_read_bio_X509_AUX(cert, NULL, NULL, NULL); if(x == NULL) @@ -946,6 +1174,11 @@ Certificate::decode(const string& encoding) } BIO_free(cert); return ICE_MAKE_SHARED(Certificate, x); +#elif defined(ICE_OS_WINRT) + // TODO + return ICE_NULLPTR; +#else +# error "Unknown platform" #endif } @@ -956,27 +1189,27 @@ Certificate::operator==(const Certificate& other) const return CFEqual(_cert, other._cert); #elif defined(ICE_USE_SCHANNEL) return CertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, _certInfo, other._certInfo); -#else +#elif defined(ICE_USE_OPENSSL) return X509_cmp(_cert, other._cert) == 0; +#elif defined(ICE_OS_WINRT) + return _cert->Equals(other._cert); +#else +# error "Unknown platform" #endif } bool Certificate::operator!=(const Certificate& other) const { -#if defined(ICE_USE_SECURE_TRANSPORT) - return !CFEqual(_cert, other._cert); -#elif defined(ICE_USE_SCHANNEL) - return !CertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, _certInfo, other._certInfo); -#else - return X509_cmp(_cert, other._cert) != 0; -#endif + return !operator==(other); } PublicKeyPtr Certificate::getPublicKey() const { -#if defined(ICE_USE_SECURE_TRANSPORT) +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) + return ICE_NULLPTR; // Not supported +#elif defined(ICE_USE_SECURE_TRANSPORT_MACOS) SecKeyRef key; OSStatus err = SecCertificateCopyPublicKey(_cert, &key); if(err) @@ -986,8 +1219,12 @@ Certificate::getPublicKey() const return ICE_MAKE_SHARED(PublicKey, shared_from_this(), key); #elif defined(ICE_USE_SCHANNEL) return ICE_MAKE_SHARED(PublicKey, shared_from_this(), &_certInfo->SubjectPublicKeyInfo); -#else +#elif defined(ICE_USE_OPENSSL) return ICE_MAKE_SHARED(PublicKey, shared_from_this(), X509_get_pubkey(_cert)); +#elif defined(ICE_OS_WINRT) + return ICE_NULLPTR; // Not supported +#else +# error "Unknown platform" #endif } @@ -996,17 +1233,20 @@ Certificate::verify(const CertificatePtr& cert) const { #if defined(ICE_USE_SECURE_TRANSPORT) // - // We first check if the given certificate subject match - // our certificate issuer. Otherwhise when use SecTrustEvaluate - // and check a certificate against itself will always return - // that is valid. + // We first check if the given certificate subject match our certificate + // issuer. Otherwhise when checking a certificate against itself + // SecTrustEvaluate always returns it is valid. // bool valid = false; - CFErrorRef error = 0; +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) + initializeAttributes(); + cert->initializeAttributes(); + valid = CFEqual(_issuer, cert->_subject); +#else CFDataRef issuer = 0; CFDataRef subject = 0; - + CFErrorRef error = 0; try { issuer = SecCertificateCopyNormalizedIssuerContent(_cert, &error); @@ -1042,7 +1282,7 @@ Certificate::verify(const CertificatePtr& cert) const CFRelease(issuer); CFRelease(subject); - +#endif if(valid) { SecPolicyRef policy = 0; @@ -1107,8 +1347,12 @@ Certificate::verify(const CertificatePtr& cert) const bool result = CryptVerifyCertificateSignature(0, X509_ASN_ENCODING, buffer, length, cert->getPublicKey()->key()); LocalFree(buffer); return result; -#else +#elif defined(ICE_USE_OPENSSL) return X509_verify(_cert, cert->getPublicKey()->key()) > 0; +#elif defined(ICE_OS_WINRT) + return false; +#else +# error "Unknown platform" #endif } @@ -1123,7 +1367,15 @@ Certificate::verify(const PublicKeyPtr& key) const string Certificate::encode() const { -#if defined(ICE_USE_SECURE_TRANSPORT) +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) + UniqueRef<CFDataRef> c(SecCertificateCopyData(_cert)); + vector<unsigned char> data(CFDataGetBytePtr(c.get()), CFDataGetBytePtr(c.get()) + CFDataGetLength(c.get())); + ostringstream os; + os << "-----BEGIN CERTIFICATE-----\n"; + os << IceInternal::Base64::encode(data); + os << "-----END CERTIFICATE-----\n"; + return os.str(); +#elif defined(ICE_USE_SECURE_TRANSPORT_MACOS) CFDataRef exported; OSStatus err = SecItemExport(_cert, kSecFormatPEMSequence, kSecItemPemArmour, 0, &exported); if(err != noErr) @@ -1170,7 +1422,7 @@ Certificate::encode() const throw; } return s; -#else +#elif defined(ICE_USE_OPENSSL) BIO* out = BIO_new(BIO_s_mem()); int i = PEM_write_bio_X509_AUX(out, _cert); if(i <= 0) @@ -1183,9 +1435,25 @@ Certificate::encode() const string result = string(p->data, p->length); BIO_free(out); return result; +#elif defined(ICE_OS_WINRT) + auto reader = Windows::Storage::Streams::DataReader::FromBuffer(_cert->GetCertificateBlob()); + std::vector<unsigned char> data(reader->UnconsumedBufferLength); + if (!data.empty()) + { + reader->ReadBytes(Platform::ArrayReference<unsigned char>(&data[0], data.size())); + } + ostringstream os; + os << "-----BEGIN CERTIFICATE-----\n"; + os << IceInternal::Base64::encode(data); + os << "-----END CERTIFICATE-----\n"; + return os.str(); +#else +# error "Unknown platform" #endif } +#if !defined(ICE_USE_SECURE_TRANSPORT_IOS) + bool Certificate::checkValidity() const { @@ -1206,8 +1474,13 @@ Certificate::getNotAfter() const return getX509Date(_cert, kSecOIDX509V1ValidityNotAfter); #elif defined(ICE_USE_SCHANNEL) return filetimeToTime(_certInfo->NotAfter); -#else +#elif defined(ICE_USE_OPENSSL) return ASMUtcTimeToIceUtilTime(X509_get_notAfter(_cert)); +#elif defined(ICE_OS_WINRT) + // Convert 100ns time from January 1, 1601 to ms from January 1, 1970 + return IceUtil::Time::milliSeconds(_cert->ValidTo.UniversalTime / TICKS_PER_MSECOND - MSECS_TO_EPOCH); +#else +# error "Unknown platform" #endif } @@ -1218,15 +1491,25 @@ Certificate::getNotBefore() const return getX509Date(_cert, kSecOIDX509V1ValidityNotBefore); #elif defined(ICE_USE_SCHANNEL) return filetimeToTime(_certInfo->NotBefore); -#else +#elif defined(ICE_USE_OPENSSL) return ASMUtcTimeToIceUtilTime(X509_get_notBefore(_cert)); +#elif defined(ICE_OS_WINRT) + // Convert 100ns time from January 1, 1601 to ms from January 1, 1970 + return IceUtil::Time::milliSeconds(_cert->ValidFrom.UniversalTime / TICKS_PER_MSECOND - MSECS_TO_EPOCH); +#else +# error "Unknown platform" #endif } +#endif + string Certificate::getSerialNumber() const { -#if defined(ICE_USE_SECURE_TRANSPORT) +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) + initializeAttributes(); + return _serial; +#elif defined(ICE_USE_SECURE_TRANSPORT_MACOS) return getX509String(_cert, kSecOIDX509V1SerialNumber); #elif defined(ICE_USE_SCHANNEL) ostringstream os; @@ -1235,14 +1518,14 @@ Certificate::getSerialNumber() const unsigned char c = _certInfo->SerialNumber.pbData[i]; os.fill('0'); os.width(2); - os << hex << (int)c; + os << hex << static_cast<int>(c); if(i) { os << ' '; } } return IceUtilInternal::toUpper(os.str()); -#else +#elif defined(ICE_USE_OPENSSL) BIGNUM* bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(_cert), 0); char* dec = BN_bn2dec(bn); string result = dec; @@ -1250,31 +1533,40 @@ Certificate::getSerialNumber() const BN_free(bn); return result; +#elif defined(ICE_OS_WINRT) + ostringstream os; + os.fill(0); + os.width(2); + for (unsigned int i = 0; i < _cert->SerialNumber->Length; i++) + { + os << hex << static_cast<int>(_cert->SerialNumber[i]); + } + return IceUtilInternal::toUpper(os.str()); +#else +# error "Unknown platform" #endif } -//string -//Certificate::getSigAlgName() const -//{ -//} - -//string -//Certificate::getSigAlgOID() const -//{ -//} - DistinguishedName Certificate::getIssuerDN() const { -#if defined(ICE_USE_SECURE_TRANSPORT) +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) + initializeAttributes(); + return _issuer ? DistinguishedName(_issuer) : DistinguishedName(""); +#elif defined(ICE_USE_SECURE_TRANSPORT_MACOS) return getX509Name(_cert, kSecOIDX509V1IssuerName); #elif defined(ICE_USE_SCHANNEL) return DistinguishedName(certNameToString(&_certInfo->Issuer)); -#else +#elif defined(ICE_USE_OPENSSL) return DistinguishedName(RFC2253::parseStrict(convertX509NameToString(X509_get_issuer_name(_cert)))); +#elif defined(ICE_OS_WINRT) + return DistinguishedName(IceUtil::wstringToString(_cert->Issuer->Data())); +#else +# error "Unknown platform" #endif } +#if !defined(ICE_USE_SECURE_TRANSPORT_IOS) vector<pair<int, string> > Certificate::getIssuerAlternativeNames() { @@ -1282,23 +1574,45 @@ Certificate::getIssuerAlternativeNames() return getX509AltName(_cert, kSecOIDIssuerAltName); #elif defined(ICE_USE_SCHANNEL) return certificateAltNames(_certInfo, szOID_ISSUER_ALT_NAME2); -#else +#elif defined(ICE_USE_OPENSSL) return convertGeneralNames(reinterpret_cast<GENERAL_NAMES*>(X509_get_ext_d2i(_cert, NID_issuer_alt_name, 0, 0))); +#elif defined(ICE_OS_WINRT) + return vector<pair<int, string> >(); // Not supported +#else +# error "Unknown platform" #endif } +#endif DistinguishedName Certificate::getSubjectDN() const { -#if defined(ICE_USE_SECURE_TRANSPORT) +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) + initializeAttributes(); + if(_subject) + { + return DistinguishedName(_subject); + } + else + { + string s = "CN="; + s += fromCFString(UniqueRef<CFStringRef>(SecCertificateCopySubjectSummary(_cert)).get()); + return DistinguishedName(s); + } +#elif defined(ICE_USE_SECURE_TRANSPORT_MACOS) return getX509Name(_cert, kSecOIDX509V1SubjectName); #elif defined(ICE_USE_SCHANNEL) return DistinguishedName(certNameToString(&_certInfo->Subject)); -#else +#elif defined(ICE_USE_OPENSSL) return DistinguishedName(RFC2253::parseStrict(convertX509NameToString(X509_get_subject_name(_cert)))); +#elif defined(ICE_OS_WINRT) + return DistinguishedName(IceUtil::wstringToString(_cert->Subject->Data())); +#else +# error "Unknown platform" #endif } +#if !defined(ICE_USE_SECURE_TRANSPORT_IOS) vector<pair<int, string> > Certificate::getSubjectAlternativeNames() { @@ -1306,20 +1620,32 @@ Certificate::getSubjectAlternativeNames() return getX509AltName(_cert, kSecOIDSubjectAltName); #elif defined(ICE_USE_SCHANNEL) return certificateAltNames(_certInfo, szOID_SUBJECT_ALT_NAME2); -#else +#elif defined(ICE_USE_OPENSSL) return convertGeneralNames(reinterpret_cast<GENERAL_NAMES*>(X509_get_ext_d2i(_cert, NID_subject_alt_name, 0, 0))); +#elif defined(ICE_OS_WINRT) + return certificateAltNames(_cert->SubjectAlternativeName); +#else +# error "Unknown platform" #endif } +#endif int Certificate::getVersion() const { -#if defined(ICE_USE_SECURE_TRANSPORT) +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) + initializeAttributes(); + return _version; +#elif defined(ICE_USE_SECURE_TRANSPORT_MACOS) return atoi(getX509String(_cert, kSecOIDX509V1Version).c_str()) - 1; #elif defined(ICE_USE_SCHANNEL) return _certInfo->dwVersion; -#else +#elif defined(ICE_USE_OPENSSL) return static_cast<int>(X509_get_version(_cert)); +#elif defined(ICE_OS_WINRT) + return -1; // Not supported +#else +# error "Unknown platform" #endif } @@ -1330,8 +1656,10 @@ Certificate::toString() const os << "serial: " << getSerialNumber() << "\n"; os << "issuer: " << string(getIssuerDN()) << "\n"; os << "subject: " << string(getSubjectDN()) << "\n"; +#if !defined(ICE_USE_SECURE_TRANSPORT_IOS) os << "notBefore: " << getNotBefore().toDateTime() << "\n"; os << "notAfter: " << getNotAfter().toDateTime(); +#endif return os.str(); } @@ -1340,3 +1668,101 @@ Certificate::getCert() const { return _cert; } + +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) + +namespace +{ + +IceUtil::Mutex* globalMutex = 0; + +class Init +{ +public: + + Init() + { + globalMutex = new IceUtil::Mutex; + } + + ~Init() + { + delete globalMutex; + globalMutex = 0; + } +}; + +Init init; + +} + +void +Certificate::initializeAttributes() const +{ + if(_subject) + { + return; + } + + // + // We need to temporarily add the certificate to the keychain in order to + // retrieve its attributes. Unfortunately kSecMatchItemList doesn't work + // on iOS. We make sure only one thread adds/removes a cert at a time here. + // + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(globalMutex); + + CFMutableDictionaryRef query; + + query = CFDictionaryCreateMutable(0, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(query, kSecValueRef, _cert); + CFDictionarySetValue(query, kSecReturnAttributes, kCFBooleanTrue); + CFDictionaryRef attributes; + OSStatus err; + if((err = SecItemAdd(query, (CFTypeRef*)&attributes)) == errSecDuplicateItem) + { + CFDictionarySetValue(query, kSecClass, kSecClassCertificate); + err = SecItemCopyMatching(query, (CFTypeRef*)&attributes); + } + else + { + CFRelease(query); + query = CFDictionaryCreateMutable(0, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(query, kSecClass, kSecClassCertificate); + CFDictionarySetValue(query, kSecValueRef, _cert); + err = SecItemDelete(query); + } + CFRelease(query); + if(err != noErr) + { + _subject = 0; + _issuer = 0; + return; + } + + _subject = (CFDataRef)CFDictionaryGetValue(attributes, kSecAttrSubject); + _issuer = (CFDataRef)CFDictionaryGetValue(attributes, kSecAttrIssuer); + CFDataRef serial = (CFDataRef)CFDictionaryGetValue(attributes, kSecAttrSerialNumber); + ostringstream os; + for(int i = 0; i < CFDataGetLength(serial); ++i) + { + int c = static_cast<int>(CFDataGetBytePtr(serial)[i]); + if(i) + { + os << ' '; + } + os.fill('0'); + os.width(2); + os << hex << c; + } + _serial = os.str(); + CFNumberRef version = (CFNumberRef)CFDictionaryGetValue(attributes, kSecAttrCertificateType); + if(!CFNumberGetValue(version, kCFNumberIntType, &_version)) + { + _version = -1; + } + CFRetain(_subject); + CFRetain(_issuer); + + CFRelease(attributes); +} +#endif
\ No newline at end of file diff --git a/cpp/src/IceSSL/ConnectorI.cpp b/cpp/src/IceSSL/ConnectorI.cpp index 51a79e1929f..532847ec0ed 100644 --- a/cpp/src/IceSSL/ConnectorI.cpp +++ b/cpp/src/IceSSL/ConnectorI.cpp @@ -13,6 +13,7 @@ #include <IceSSL/OpenSSLTransceiverI.h> #include <IceSSL/SecureTransportTransceiverI.h> #include <IceSSL/SChannelTransceiverI.h> +#include <IceSSL/WinRTTransceiverI.h> #include <IceSSL/EndpointI.h> #include <IceSSL/Util.h> @@ -39,20 +40,19 @@ IceSSL::ConnectorI::connect() throw ex; } - IceInternal::StreamSocketPtr stream = new IceInternal::StreamSocket(_instance, _proxy, _addr, _sourceAddr); - return new TransceiverI(_instance, stream, _host, false); + return new TransceiverI(_instance, _delegate->connect(), _host, false); } Short IceSSL::ConnectorI::type() const { - return _instance->type(); + return _delegate->type(); } string IceSSL::ConnectorI::toString() const { - return IceInternal::addrToString(!_proxy ? _addr : _proxy->getAddress()); + return _delegate->toString(); } bool @@ -64,22 +64,12 @@ IceSSL::ConnectorI::operator==(const IceInternal::Connector& r) const return false; } - if(IceInternal::compareAddress(_addr, p->_addr) != 0) + if(this == p) { - return false; - } - - if(_timeout != p->_timeout) - { - return false; - } - - if(IceInternal::compareAddress(_sourceAddr, p->_sourceAddr) != 0) - { - return false; + return true; } - if(_connectionId != p->_connectionId) + if(_delegate != p->_delegate) { return false; } @@ -102,47 +92,25 @@ IceSSL::ConnectorI::operator<(const IceInternal::Connector& r) const return type() < r.type(); } - if(_timeout < p->_timeout) - { - return true; - } - else if(p->_timeout < _timeout) - { - return false; - } - - int rc = compareAddress(_sourceAddr, p->_sourceAddr); - if(rc < 0) - { - return true; - } - else if(rc > 0) + if(this == p) { return false; } - if(_connectionId < p->_connectionId) + if(_delegate < p->_delegate) { return true; } - else if(p->_connectionId < _connectionId) + else if(p->_delegate < _delegate) { return false; } - return IceInternal::compareAddress(_addr, p->_addr) == -1; + return false; } -IceSSL::ConnectorI::ConnectorI(const InstancePtr& instance, const string& host, const IceInternal::Address& addr, - const IceInternal::NetworkProxyPtr& proxy, const IceInternal::Address& sourceAddr, - Ice::Int timeout, const string& connectionId) : - _instance(instance), - _host(host), - _addr(addr), - _proxy(proxy), - _sourceAddr(sourceAddr), - _timeout(timeout), - _connectionId(connectionId) +IceSSL::ConnectorI::ConnectorI(const InstancePtr& instance, const IceInternal::ConnectorPtr& del, const string& h) : + _instance(instance), _delegate(del), _host(h) { } diff --git a/cpp/src/IceSSL/ConnectorI.h b/cpp/src/IceSSL/ConnectorI.h index 48a80fdebcc..e1434d97d1b 100644 --- a/cpp/src/IceSSL/ConnectorI.h +++ b/cpp/src/IceSSL/ConnectorI.h @@ -36,19 +36,13 @@ public: private: - ConnectorI(const InstancePtr&, const std::string&, const IceInternal::Address&, - const IceInternal::NetworkProxyPtr&, const IceInternal::Address&, - Ice::Int, const std::string&); + ConnectorI(const InstancePtr&, const IceInternal::ConnectorPtr&, const std::string&); virtual ~ConnectorI(); friend class EndpointI; const InstancePtr _instance; + const IceInternal::ConnectorPtr _delegate; const std::string _host; - const IceInternal::Address _addr; - const IceInternal::NetworkProxyPtr _proxy; - const IceInternal::Address _sourceAddr; - const Ice::Int _timeout; - const std::string _connectionId; }; } diff --git a/cpp/src/IceSSL/EndpointI.cpp b/cpp/src/IceSSL/EndpointI.cpp index 0038cf9717f..1615b12d05d 100644 --- a/cpp/src/IceSSL/EndpointI.cpp +++ b/cpp/src/IceSSL/EndpointI.cpp @@ -17,101 +17,135 @@ #include <Ice/DefaultsAndOverrides.h> #include <Ice/Object.h> #include <Ice/HashUtil.h> +#include <Ice/Comparable.h> using namespace std; using namespace Ice; using namespace IceSSL; -#ifndef ICE_CPP11_MAPPING -IceUtil::Shared* IceSSL::upCast(EndpointI* p) { return p; } -#endif +namespace +{ -IceSSL::EndpointI::EndpointI(const InstancePtr& instance, const string& ho, Int po, - const IceInternal::Address& sourceAddr, Int ti, const string& conId, bool co) : - IceInternal::IPEndpointI(instance, ho, po, sourceAddr, conId), - _instance(instance), - _timeout(ti), - _compress(co) +Ice::IPEndpointInfoPtr +getIPEndpointInfo(const Ice::EndpointInfoPtr& info) { + for(Ice::EndpointInfoPtr p = info; p; p = p->underlying) + { + Ice::IPEndpointInfoPtr ipInfo = ICE_DYNAMIC_CAST(Ice::IPEndpointInfo, p); + if(ipInfo) + { + return ipInfo; + } + } + return ICE_NULLPTR; } -IceSSL::EndpointI::EndpointI(const InstancePtr& instance) : - IceInternal::IPEndpointI(instance), - _instance(instance), - _timeout(instance->defaultTimeout()), - _compress(false) +} + +#ifndef ICE_CPP11_MAPPING +IceUtil::Shared* IceSSL::upCast(EndpointI* p) { return p; } +#endif + +IceSSL::EndpointI::EndpointI(const InstancePtr& instance, const IceInternal::EndpointIPtr& del) : + _instance(instance), _delegate(del) { } -IceSSL::EndpointI::EndpointI(const InstancePtr& instance, Ice::InputStream* s) : - IPEndpointI(instance, s), - _instance(instance), - _timeout(-1), - _compress(false) +void +IceSSL::EndpointI::streamWriteImpl(Ice::OutputStream* stream) const { - s->read(const_cast<Int&>(_timeout)); - s->read(const_cast<bool&>(_compress)); + _delegate->streamWriteImpl(stream); } Ice::EndpointInfoPtr IceSSL::EndpointI::getInfo() const { EndpointInfoPtr info = ICE_MAKE_SHARED(IceInternal::InfoI<EndpointInfo>, shared_from_this()); - fillEndpointInfo(info.get()); + info->underlying = _delegate->getInfo(); + info->compress = info->underlying->compress; + info->timeout = info->underlying->timeout; return info; } -Ice::EndpointInfoPtr -IceSSL::EndpointI::getWSInfo(const string& resource) const +Ice::Short +IceSSL::EndpointI::type() const { - WSSEndpointInfoPtr info = ICE_MAKE_SHARED(IceInternal::InfoI<WSSEndpointInfo>, shared_from_this()); - fillEndpointInfo(info.get()); - info->resource = resource; - return info; + return _delegate->type(); +} + +const std::string& +IceSSL::EndpointI::protocol() const +{ + return _delegate->protocol(); } Int IceSSL::EndpointI::timeout() const { - return _timeout; + return _delegate->timeout(); } IceInternal::EndpointIPtr IceSSL::EndpointI::timeout(Int timeout) const { - if(timeout == _timeout) + if(timeout == _delegate->timeout()) { return shared_from_this(); } else { - return ICE_MAKE_SHARED(EndpointI, _instance, _host, _port, _sourceAddr, timeout, _connectionId, _compress); + return ICE_MAKE_SHARED(EndpointI, _instance, _delegate->timeout(timeout)); + } +} + +const string& +IceSSL::EndpointI::connectionId() const +{ + return _delegate->connectionId(); +} + +IceInternal::EndpointIPtr +IceSSL::EndpointI::connectionId(const string& connectionId) const +{ + if(connectionId == _delegate->connectionId()) + { + return shared_from_this(); + } + else + { + return ICE_MAKE_SHARED(EndpointI, _instance, _delegate->connectionId(connectionId)); } } bool IceSSL::EndpointI::compress() const { - return _compress; + return _delegate->compress(); } IceInternal::EndpointIPtr IceSSL::EndpointI::compress(bool compress) const { - if(compress == _compress) + if(compress == _delegate->compress()) { return shared_from_this(); } else { - return ICE_MAKE_SHARED(EndpointI, _instance, _host, _port, _sourceAddr, _timeout, _connectionId, compress); + return ICE_MAKE_SHARED(EndpointI, _instance, _delegate->compress(compress)); } } bool IceSSL::EndpointI::datagram() const { - return false; + return _delegate->datagram(); +} + +bool +IceSSL::EndpointI::secure() const +{ + return _delegate->secure(); } IceInternal::TransceiverPtr @@ -120,46 +154,90 @@ IceSSL::EndpointI::transceiver() const return 0; } +void +IceSSL::EndpointI::connectors_async(Ice::EndpointSelectionType selType, + const IceInternal::EndpointI_connectorsPtr& callback) const +{ + class CallbackI : public IceInternal::EndpointI_connectors + { + public: + + CallbackI(const IceInternal::EndpointI_connectorsPtr& callback, const InstancePtr& instance, + const string& host) : + _callback(callback), _instance(instance), _host(host) + { + } + + virtual void connectors(const vector<IceInternal::ConnectorPtr>& c) + { + vector<IceInternal::ConnectorPtr> connectors = c; + for(vector<IceInternal::ConnectorPtr>::iterator p = connectors.begin(); p != connectors.end(); ++p) + { + *p = new ConnectorI(_instance, *p, _host); + } + _callback->connectors(connectors); + } + + virtual void exception(const Ice::LocalException& ex) + { + _callback->exception(ex); + } + + private: + + const IceInternal::EndpointI_connectorsPtr _callback; + const InstancePtr _instance; + const string _host; + }; + + IPEndpointInfoPtr info = getIPEndpointInfo(_delegate->getInfo()); + _delegate->connectors_async(selType, ICE_MAKE_SHARED(CallbackI, callback, _instance, info ? info->host : string())); +} + IceInternal::AcceptorPtr IceSSL::EndpointI::acceptor(const string& adapterName) const { - return new AcceptorI(ICE_DYNAMIC_CAST(IceSSL::EndpointI, shared_from_this()), _instance, adapterName, _host, _port); + return new AcceptorI(shared_from_this(), _instance, _delegate->acceptor(adapterName), adapterName); } EndpointIPtr -IceSSL::EndpointI::endpoint(const AcceptorIPtr& acceptor) const +IceSSL::EndpointI::endpoint(const IceInternal::EndpointIPtr& delEndp) const { - return ICE_MAKE_SHARED(EndpointI, _instance, _host, acceptor->effectivePort(), _sourceAddr, _timeout, _connectionId, _compress); + return ICE_MAKE_SHARED(EndpointI, _instance, delEndp); } -string -IceSSL::EndpointI::options() const +vector<IceInternal::EndpointIPtr> +IceSSL::EndpointI::expand() const { - // - // WARNING: Certain features, such as proxy validation in Glacier2, - // depend on the format of proxy strings. Changes to toString() and - // methods called to generate parts of the reference string could break - // these features. Please review for all features that depend on the - // format of proxyToString() before changing this and related code. - // - ostringstream s; - s << IPEndpointI::options(); - - if(_timeout == -1) + vector<IceInternal::EndpointIPtr> endps = _delegate->expand(); + for(vector<IceInternal::EndpointIPtr>::iterator p = endps.begin(); p != endps.end(); ++p) { - s << " -t infinite"; - } - else - { - s << " -t " << _timeout; + *p = p->get() == _delegate.get() ? shared_from_this() : ICE_MAKE_SHARED(EndpointI, _instance, *p); } + return endps; +} - if(_compress) +bool +IceSSL::EndpointI::equivalent(const IceInternal::EndpointIPtr& endpoint) const +{ + const EndpointI* endpointI = dynamic_cast<const EndpointI*>(endpoint.get()); + if(!endpointI) { - s << " -z"; + return false; } + return _delegate->equivalent(endpointI->_delegate); +} + +Ice::Int +IceSSL::EndpointI::hash() const +{ + return _delegate->hash(); +} - return s.str(); +string +IceSSL::EndpointI::options() const +{ + return _delegate->options(); } bool @@ -169,11 +247,6 @@ IceSSL::EndpointI::operator==(const Ice::Endpoint& r) const IceSSL::EndpointI::operator==(const Ice::LocalObject& r) const #endif { - if(!IPEndpointI::operator==(r)) - { - return false; - } - const EndpointI* p = dynamic_cast<const EndpointI*>(&r); if(!p) { @@ -185,12 +258,7 @@ IceSSL::EndpointI::operator==(const Ice::LocalObject& r) const return true; } - if(_timeout != p->_timeout) - { - return false; - } - - if(_compress != p->_compress) + if(!Ice::targetEquals(_delegate, p->_delegate)) { return false; } @@ -221,119 +289,27 @@ IceSSL::EndpointI::operator<(const Ice::LocalObject& r) const return false; } - if(_timeout < p->_timeout) - { - return true; - } - else if(p->_timeout < _timeout) - { - return false; - } - - if(!_compress && p->_compress) + if(Ice::targetLess(_delegate, p->_delegate)) { return true; } - else if(p->_compress < _compress) + else if (Ice::targetLess(p->_delegate, _delegate)) { return false; } - return IPEndpointI::operator<(r); -} - -void -IceSSL::EndpointI::streamWriteImpl(Ice::OutputStream* s) const -{ - IPEndpointI::streamWriteImpl(s); - s->write(_timeout); - s->write(_compress); -} - -void -IceSSL::EndpointI::hashInit(Ice::Int& h) const -{ - IPEndpointI::hashInit(h); - IceInternal::hashAdd(h, _timeout); - IceInternal::hashAdd(h, _compress); -} - -void -IceSSL::EndpointI::fillEndpointInfo(IPEndpointInfo* info) const -{ - IPEndpointI::fillEndpointInfo(info); - info->timeout = _timeout; - info->compress = _compress; + return false; } bool IceSSL::EndpointI::checkOption(const string& option, const string& argument, const string& endpoint) { - if(IPEndpointI::checkOption(option, argument, endpoint)) - { - return true; - } - - switch(option[1]) - { - case 't': - { - if(argument.empty()) - { - EndpointParseException ex(__FILE__, __LINE__); - ex.str = "no argument provided for -t option in endpoint " + endpoint; - throw ex; - } - - if(argument == "infinite") - { - const_cast<Int&>(_timeout) = -1; - } - else - { - istringstream t(argument); - if(!(t >> const_cast<Int&>(_timeout)) || !t.eof() || _timeout < 1) - { - EndpointParseException ex(__FILE__, __LINE__); - ex.str = "invalid timeout value `" + argument + "' in endpoint " + endpoint; - throw ex; - } - } - return true; - } - - case 'z': - { - if(!argument.empty()) - { - EndpointParseException ex(__FILE__, __LINE__); - ex.str = "unexpected argument `" + argument + "' provided for -z option in " + endpoint; - throw ex; - } - const_cast<bool&>(_compress) = true; - return true; - } - - default: - { - return false; - } - } -} - -IceInternal::ConnectorPtr -IceSSL::EndpointI::createConnector(const IceInternal::Address& address, const IceInternal::NetworkProxyPtr& proxy) const -{ - return new ConnectorI(_instance, _host, address, proxy, _sourceAddr, _timeout, _connectionId); -} - -IceInternal::IPEndpointIPtr -IceSSL::EndpointI::createEndpoint(const string& host, int port, const string& connectionId) const -{ - return ICE_MAKE_SHARED(EndpointI, _instance, host, port, _sourceAddr, _timeout, connectionId, _compress); + return false; } -IceSSL::EndpointFactoryI::EndpointFactoryI(const InstancePtr& instance) : _instance(instance) +IceSSL::EndpointFactoryI::EndpointFactoryI(const InstancePtr& instance, + const IceInternal::EndpointFactoryPtr& delegate) : + _instance(instance), _delegate(delegate) { } @@ -356,25 +332,26 @@ IceSSL::EndpointFactoryI::protocol() const IceInternal::EndpointIPtr IceSSL::EndpointFactoryI::create(vector<string>& args, bool oaEndpoint) const { - IceInternal::IPEndpointIPtr endpt = ICE_MAKE_SHARED(EndpointI, _instance); - endpt->initWithOptions(args, oaEndpoint); - return endpt; + return ICE_MAKE_SHARED(EndpointI, _instance, _delegate->create(args, oaEndpoint)); } IceInternal::EndpointIPtr IceSSL::EndpointFactoryI::read(Ice::InputStream* s) const { - return ICE_MAKE_SHARED(EndpointI, _instance, s); + return ICE_MAKE_SHARED(EndpointI, _instance, _delegate->read(s)); } void IceSSL::EndpointFactoryI::destroy() { + _delegate->destroy(); _instance = 0; } IceInternal::EndpointFactoryPtr -IceSSL::EndpointFactoryI::clone(const IceInternal::ProtocolInstancePtr& instance) const +IceSSL::EndpointFactoryI::clone(const IceInternal::ProtocolInstancePtr& inst, + const IceInternal::EndpointFactoryPtr& delegate) const { - return new EndpointFactoryI(new Instance(_instance->engine(), instance->type(), instance->protocol())); + InstancePtr instance = new Instance(_instance->engine(), inst->type(), inst->protocol()); + return new EndpointFactoryI(instance, delegate ? delegate : _delegate->clone(instance, 0)); } diff --git a/cpp/src/IceSSL/EndpointI.h b/cpp/src/IceSSL/EndpointI.h index 0aec468f9c7..fd122d7b146 100644 --- a/cpp/src/IceSSL/EndpointI.h +++ b/cpp/src/IceSSL/EndpointI.h @@ -13,7 +13,6 @@ #include <Ice/EndpointI.h> #include <Ice/IPEndpointI.h> #include <Ice/EndpointFactory.h> -#include <Ice/WSEndpoint.h> #include <IceSSL/InstanceF.h> #include <IceSSL/EndpointInfo.h> #include <Ice/Network.h> @@ -21,28 +20,38 @@ namespace IceSSL { -class EndpointI : public IceInternal::IPEndpointI, public IceInternal::WSEndpointDelegate +class EndpointI : public IceInternal::EndpointI, public Ice::EnableSharedFromThis<EndpointI> { public: - EndpointI(const InstancePtr&, const std::string&, Ice::Int, const IceInternal::Address&, Ice::Int, - const std::string&, bool); - EndpointI(const InstancePtr&); - EndpointI(const InstancePtr&, Ice::InputStream*); + EndpointI(const InstancePtr&, const IceInternal::EndpointIPtr&); + + virtual void streamWriteImpl(Ice::OutputStream*) const; virtual Ice::EndpointInfoPtr getInfo() const; - virtual Ice::EndpointInfoPtr getWSInfo(const std::string&) const; + virtual Ice::Short type() const; + virtual const std::string& protocol() const; virtual Ice::Int timeout() const; virtual IceInternal::EndpointIPtr timeout(Ice::Int) const; + virtual const std::string& connectionId() const; + virtual IceInternal::EndpointIPtr connectionId(const ::std::string&) const; virtual bool compress() const; virtual IceInternal::EndpointIPtr compress(bool) const; virtual bool datagram() const; + virtual bool secure() const; virtual IceInternal::TransceiverPtr transceiver() const; + virtual void connectors_async(Ice::EndpointSelectionType, const IceInternal::EndpointI_connectorsPtr&) const; virtual IceInternal::AcceptorPtr acceptor(const std::string&) const; + + virtual std::vector<IceInternal::EndpointIPtr> expand() const; + virtual bool equivalent(const IceInternal::EndpointIPtr&) const; + virtual ::Ice::Int hash() const; virtual std::string options() const; + EndpointIPtr endpoint(const IceInternal::EndpointIPtr&) const; + #ifdef ICE_CPP11_MAPPING virtual bool operator==(const Ice::Endpoint&) const; virtual bool operator<(const Ice::Endpoint&) const; @@ -51,29 +60,17 @@ public: virtual bool operator<(const Ice::LocalObject&) const; #endif - virtual EndpointIPtr endpoint(const AcceptorIPtr&) const; - - using IceInternal::IPEndpointI::connectionId; - protected: - virtual void streamWriteImpl(Ice::OutputStream*) const; - virtual void hashInit(Ice::Int&) const; - virtual void fillEndpointInfo(Ice::IPEndpointInfo*) const; virtual bool checkOption(const std::string&, const std::string&, const std::string&); - virtual IceInternal::ConnectorPtr createConnector(const IceInternal::Address&, - const IceInternal::NetworkProxyPtr&) const; - virtual IceInternal::IPEndpointIPtr createEndpoint(const std::string&, int, const std::string&) const; - private: // // All members are const, because endpoints are immutable. // const InstancePtr _instance; - const Ice::Int _timeout; - const bool _compress; + const IceInternal::EndpointIPtr _delegate; }; class EndpointFactoryI : public IceInternal::EndpointFactory @@ -88,14 +85,16 @@ public: virtual IceInternal::EndpointIPtr read(Ice::InputStream*) const; virtual void destroy(); - virtual IceInternal::EndpointFactoryPtr clone(const IceInternal::ProtocolInstancePtr&) const; + virtual IceInternal::EndpointFactoryPtr clone(const IceInternal::ProtocolInstancePtr&, + const IceInternal::EndpointFactoryPtr&) const; private: - EndpointFactoryI(const InstancePtr&); + EndpointFactoryI(const InstancePtr&, const IceInternal::EndpointFactoryPtr&); friend class PluginI; InstancePtr _instance; + const IceInternal::EndpointFactoryPtr _delegate; }; } diff --git a/cpp/src/IceSSL/Instance.cpp b/cpp/src/IceSSL/Instance.cpp index b7f9ce3fdf4..e37ab14a967 100644 --- a/cpp/src/IceSSL/Instance.cpp +++ b/cpp/src/IceSSL/Instance.cpp @@ -7,13 +7,8 @@ // // ********************************************************************** -#include <IceUtil/Config.h> -#ifdef _WIN32 -# include <winsock2.h> -#endif #include <IceSSL/Instance.h> #include <IceSSL/SSLEngine.h> -#include <Ice/Properties.h> using namespace std; using namespace Ice; diff --git a/cpp/src/IceSSL/Instance.h b/cpp/src/IceSSL/Instance.h index 6a4514de52b..d9a25482eb0 100644 --- a/cpp/src/IceSSL/Instance.h +++ b/cpp/src/IceSSL/Instance.h @@ -10,8 +10,8 @@ #ifndef ICE_SSL_INSTANCE_H #define ICE_SSL_INSTANCE_H -#include <IceSSL/InstanceF.h> #include <Ice/ProtocolInstance.h> +#include <IceSSL/InstanceF.h> #include <IceSSL/SSLEngineF.h> namespace IceSSL @@ -24,12 +24,12 @@ public: Instance(const SSLEnginePtr&, Ice::Short, const std::string&); virtual ~Instance(); - SSLEnginePtr + SSLEnginePtr engine() const { return _engine; } - + bool initialized() const; private: diff --git a/cpp/src/IceSSL/Makefile.mk b/cpp/src/IceSSL/Makefile.mk index 3a6988f4879..0e2e3d00e94 100644 --- a/cpp/src/IceSSL/Makefile.mk +++ b/cpp/src/IceSSL/Makefile.mk @@ -11,10 +11,7 @@ $(project)_libraries := IceSSL IceSSL_targetdir := $(libdir) IceSSL_dependencies := Ice -IceSSL_cppflags := -DICESSL_API_EXPORTS -IceSSL_sliceflags := --include-dir IceSSL --dll-export ICESSL_API - -IceSSL[iphoneos]_excludes := $(wildcard $(addprefix $(currentdir)/,*.cpp)) -IceSSL[iphonesimulator]_excludes = $(IceSSL[iphoneos]_excludes) +IceSSL_cppflags := -DICE_SSL_API_EXPORTS +IceSSL_sliceflags := --include-dir IceSSL --dll-export ICE_SSL_API projects += $(project) diff --git a/cpp/src/IceSSL/OpenSSLTransceiverI.cpp b/cpp/src/IceSSL/OpenSSLTransceiverI.cpp index 2178c292ea0..de7fbb3ade6 100644 --- a/cpp/src/IceSSL/OpenSSLTransceiverI.cpp +++ b/cpp/src/IceSSL/OpenSSLTransceiverI.cpp @@ -79,16 +79,20 @@ IceSSL_opensslVerifyCallback(int ok, X509_STORE_CTX* ctx) IceInternal::NativeInfoPtr IceSSL::TransceiverI::getNativeInfo() { - return _stream; + return _delegate->getNativeInfo(); } IceInternal::SocketOperation 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; } if(!_ssl) @@ -96,7 +100,9 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B // // This static_cast is necessary due to 64bit windows. There SOCKET is a non-int type. // - BIO* bio = BIO_new_socket(static_cast<int>(_stream->fd()), 0); + SOCKET fd = _delegate->getNativeInfo()->fd(); + assert(fd != INVALID_SOCKET); // Underlying transport must be SOCKET based. + BIO* bio = BIO_new_socket(static_cast<int>(fd), 0); if(!bio) { SecurityException ex(__FILE__, __LINE__); @@ -231,15 +237,9 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B } case SSL_ERROR_SSL: { - IceInternal::Address remoteAddr; - string desc = "<not available>"; - if(IceInternal::fdToRemoteAddress(_stream->fd(), remoteAddr)) - { - desc = IceInternal::addrToString(remoteAddr); - } ostringstream ostr; ostr << "SSL error occurred for new " << (_incoming ? "incoming" : "outgoing") - << " connection:\nremote address = " << desc << "\n" << _engine->sslErrors(); + << " connection:\nremote address = " << _delegate->toString() << "\n" << _engine->sslErrors(); ProtocolException ex(__FILE__, __LINE__); ex.reason = ostr.str(); throw ex; @@ -278,12 +278,7 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B { _verified = true; } - -#ifdef ICE_CPP11_MAPPING - _engine->verifyPeer(_stream->fd(), _host, dynamic_pointer_cast<NativeConnectionInfo>(getInfo())); -#else - _engine->verifyPeer(_stream->fd(), _host, NativeConnectionInfoPtr::dynamicCast(getInfo())); -#endif + _engine->verifyPeer(_host, ICE_DYNAMIC_CAST(NativeConnectionInfo, getInfo()), toString()); if(_engine->securityTraceLevel() >= 1) { @@ -342,15 +337,15 @@ IceSSL::TransceiverI::close() _ssl = 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()) @@ -450,9 +445,9 @@ IceSSL::TransceiverI::write(IceInternal::Buffer& buf) IceInternal::SocketOperation IceSSL::TransceiverI::read(IceInternal::Buffer& buf) { - if(!_stream->isConnected()) + if(!_connected) { - return _stream->read(buf); + return _delegate->read(buf); } // @@ -466,7 +461,7 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf) return IceInternal::SocketOperationNone; } - _stream->ready(IceInternal::SocketOperationRead, false); + _delegate->getNativeInfo()->ready(IceInternal::SocketOperationRead, false); // // It's impossible for packetSize to be more than an Int. @@ -560,7 +555,7 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf) // // Check if there's still buffered data to read, set the read ready status. // - _stream->ready(IceInternal::SocketOperationRead, SSL_pending(_ssl) > 0); + _delegate->getNativeInfo()->ready(IceInternal::SocketOperationRead, SSL_pending(_ssl) > 0); return IceInternal::SocketOperationNone; } @@ -574,7 +569,7 @@ IceSSL::TransceiverI::protocol() const string IceSSL::TransceiverI::toString() const { - return _stream->toString(); + return _delegate->toString(); } string @@ -587,16 +582,19 @@ Ice::ConnectionInfoPtr IceSSL::TransceiverI::getInfo() const { NativeConnectionInfoPtr info = ICE_MAKE_SHARED(NativeConnectionInfo); - fillConnectionInfo(info, info->nativeCerts); - return info; -} - -Ice::ConnectionInfoPtr -IceSSL::TransceiverI::getWSInfo(const Ice::HeaderDict& headers) const -{ - WSSNativeConnectionInfoPtr info = ICE_MAKE_SHARED(WSSNativeConnectionInfo); - fillConnectionInfo(info, info->nativeCerts); - info->headers = headers; + info->underlying = _delegate->getInfo(); + info->incoming = _incoming; + info->adapterName = _adapterName; + info->verified = _verified; + info->nativeCerts = _nativeCerts; + for(vector<CertificatePtr>::const_iterator p = _nativeCerts.begin(); p != _nativeCerts.end(); ++p) + { + info->certs.push_back((*p)->encode()); + } + if(_ssl != 0) + { + info->cipher = SSL_get_cipher_name(_ssl); // Nothing needs to be free'd. + } return info; } @@ -608,7 +606,7 @@ IceSSL::TransceiverI::checkSendSize(const IceInternal::Buffer&) void IceSSL::TransceiverI::setBufferSize(int rcvSize, int sndSize) { - _stream->setBufferSize(rcvSize, sndSize); + _delegate->setBufferSize(rcvSize, sndSize); } int @@ -656,14 +654,15 @@ IceSSL::TransceiverI::verifyCallback(int ok, X509_STORE_CTX* c) return 1; } -IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance, const IceInternal::StreamSocketPtr& stream, +IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance, const IceInternal::TransceiverPtr& delegate, const string& hostOrAdapterName, bool incoming) : _instance(instance), _engine(OpenSSLEnginePtr::dynamicCast(instance->engine())), _host(incoming ? "" : hostOrAdapterName), _adapterName(incoming ? hostOrAdapterName : ""), _incoming(incoming), - _stream(stream), + _delegate(delegate), + _connected(false), _verified(false), _ssl(0) { @@ -673,30 +672,4 @@ 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()); - } - info->adapterName = _adapterName; - info->incoming = _incoming; - info->verified = _verified; - nativeCerts = _nativeCerts; - for(vector<CertificatePtr>::const_iterator p = _nativeCerts.begin(); p != _nativeCerts.end(); ++p) - { - info->certs.push_back((*p)->encode()); - } - if(_ssl != 0) - { - info->cipher = SSL_get_cipher_name(_ssl); // Nothing needs to be free'd. - } - info->adapterName = _adapterName; - info->incoming = _incoming; -} - #endif diff --git a/cpp/src/IceSSL/OpenSSLTransceiverI.h b/cpp/src/IceSSL/OpenSSLTransceiverI.h index 8451db86b69..58459e804b9 100644 --- a/cpp/src/IceSSL/OpenSSLTransceiverI.h +++ b/cpp/src/IceSSL/OpenSSLTransceiverI.h @@ -32,7 +32,7 @@ namespace IceSSL class ConnectorI; class AcceptorI; -class TransceiverI : public IceInternal::Transceiver, public IceInternal::WSTransceiverDelegate +class TransceiverI : public IceInternal::Transceiver { public: @@ -51,7 +51,6 @@ public: virtual std::string toString() const; virtual std::string toDetailedString() const; virtual Ice::ConnectionInfoPtr getInfo() const; - virtual Ice::ConnectionInfoPtr getWSInfo(const Ice::HeaderDict&) const; virtual void checkSendSize(const IceInternal::Buffer&); virtual void setBufferSize(int rcvSize, int sndSize); @@ -59,11 +58,9 @@ public: private: - TransceiverI(const InstancePtr&, const IceInternal::StreamSocketPtr&, const std::string&, bool); + TransceiverI(const InstancePtr&, const IceInternal::TransceiverPtr&, const std::string&, bool); virtual ~TransceiverI(); - void fillConnectionInfo(const ConnectionInfoPtr&, std::vector<CertificatePtr>&) const; - friend class ConnectorI; friend class AcceptorI; @@ -72,7 +69,8 @@ private: const std::string _host; const std::string _adapterName; const bool _incoming; - const IceInternal::StreamSocketPtr _stream; + const IceInternal::TransceiverPtr _delegate; + bool _connected; bool _verified; std::vector<CertificatePtr> _nativeCerts; diff --git a/cpp/src/IceSSL/PluginI.cpp b/cpp/src/IceSSL/PluginI.cpp index 7e9fb283783..cd6bbab1f53 100644..100755 --- a/cpp/src/IceSSL/PluginI.cpp +++ b/cpp/src/IceSSL/PluginI.cpp @@ -15,6 +15,7 @@ #include <Ice/ProtocolPluginFacade.h> #include <Ice/ProtocolInstance.h> #include <Ice/LocalException.h> +#include <Ice/RegisterPlugins.h> using namespace std; using namespace Ice; @@ -23,17 +24,12 @@ using namespace IceSSL; // // Plug-in factory function. // -extern "C" -{ - -ICE_SSL_API Ice::Plugin* +extern "C" ICE_SSL_API Ice::Plugin* createIceSSL(const CommunicatorPtr& communicator, const string& /*name*/, const StringSeq& /*args*/) { return new PluginI(communicator); } -} - namespace Ice { @@ -46,6 +42,15 @@ registerIceSSL(bool loadOnInitialize) } // +// Objective-C function to allow Objective-C programs to register plugin. +// +extern "C" ICE_SSL_API void +ICEregisterIceSSL(bool loadOnInitialize) +{ + Ice::registerIceSSL(loadOnInitialize); +} + +// // Plugin implementation. // IceSSL::PluginI::PluginI(const Ice::CommunicatorPtr& com) @@ -54,6 +59,8 @@ IceSSL::PluginI::PluginI(const Ice::CommunicatorPtr& com) _engine = new SecureTransportEngine(com); #elif defined(ICE_USE_SCHANNEL) _engine = new SChannelEngine(com); +#elif defined(ICE_OS_WINRT) + _engine = new WinRTEngine(com); #else _engine = new OpenSSLEngine(com); #endif @@ -63,8 +70,31 @@ IceSSL::PluginI::PluginI(const Ice::CommunicatorPtr& com) // than in initialize, because the communicator may need to // interpret proxies before the plug-in is fully initialized. // - IceInternal::EndpointFactoryPtr sslFactory = new EndpointFactoryI(new Instance(_engine, EndpointType, "ssl")); - IceInternal::getProtocolPluginFacade(com)->addEndpointFactory(sslFactory); + IceInternal::ProtocolPluginFacadePtr pluginFacade = IceInternal::getProtocolPluginFacade(com); + + // SSL based on TCP + IceInternal::EndpointFactoryPtr tcp = pluginFacade->getEndpointFactory(TCPEndpointType); + if(tcp) + { + InstancePtr instance = new Instance(_engine, SSLEndpointType, "ssl"); + pluginFacade->addEndpointFactory(new EndpointFactoryI(instance, tcp->clone(instance, 0))); + } + + // SSL based on Bluetooth + IceInternal::EndpointFactoryPtr bluetooth = pluginFacade->getEndpointFactory(BTEndpointType); + if(bluetooth) + { + InstancePtr instance = new Instance(_engine, BTSEndpointType, "bts"); + pluginFacade->addEndpointFactory(new EndpointFactoryI(instance, bluetooth->clone(instance, 0))); + } + + // SSL based on iAP + IceInternal::EndpointFactoryPtr iap = pluginFacade->getEndpointFactory(iAPEndpointType); + if(iap) + { + InstancePtr instance = new Instance(_engine, iAPSEndpointType, "iaps"); + pluginFacade->addEndpointFactory(new EndpointFactoryI(instance, iap->clone(instance, 0))); + } } void diff --git a/cpp/src/IceSSL/PluginI.h b/cpp/src/IceSSL/PluginI.h index e0c5a48120b..ea0cf344ab4 100644 --- a/cpp/src/IceSSL/PluginI.h +++ b/cpp/src/IceSSL/PluginI.h @@ -46,6 +46,8 @@ private: SecureTransportEnginePtr _engine; #elif defined(ICE_USE_SCHANNEL) SChannelEnginePtr _engine; +#elif defined(ICE_OS_WINRT) + WinRTEnginePtr _engine; #else OpenSSLEnginePtr _engine; #endif diff --git a/cpp/src/IceSSL/RFC2253.cpp b/cpp/src/IceSSL/RFC2253.cpp index 7b46682f3c2..e4c57add13a 100644 --- a/cpp/src/IceSSL/RFC2253.cpp +++ b/cpp/src/IceSSL/RFC2253.cpp @@ -271,7 +271,7 @@ parseAttributeType(const string& data, size_t& pos) // // Here we must also check for "oid." and "OID." before parsing // according to the ALPHA KEYCHAR* rule. - // + // // First the OID case. // if(IceUtilInternal::isDigit(data[pos]) || @@ -318,7 +318,7 @@ parseAttributeType(const string& data, size_t& pos) result += data[pos]; ++pos; // 1* KEYCHAR - while(pos < data.size() && + while(pos < data.size() && (IceUtilInternal::isAlpha(data[pos]) || IceUtilInternal::isDigit(data[pos]) || data[pos] == '-')) { result += data[pos]; @@ -448,7 +448,7 @@ parsePair(const string& data, size_t& pos) } return parseHexPair(data, pos, false); } - + // // RFC 2253 // hexpair = hexchar hexchar diff --git a/cpp/src/IceSSL/SChannelTransceiverI.cpp b/cpp/src/IceSSL/SChannelTransceiverI.cpp index b5eca20d632..d7555d545a9 100644 --- a/cpp/src/IceSSL/SChannelTransceiverI.cpp +++ b/cpp/src/IceSSL/SChannelTransceiverI.cpp @@ -208,7 +208,7 @@ getSecBufferWithType(const SecBufferDesc& desc, ULONG bufferType) IceInternal::NativeInfoPtr IceSSL::TransceiverI::getNativeInfo() { - return _stream; + return _delegate->getNativeInfo(); } IceInternal::SocketOperation @@ -624,13 +624,17 @@ IceSSL::TransceiverI::encryptMessage(IceInternal::Buffer& buffer) IceInternal::SocketOperation IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::Buffer& writeBuffer) { - IceInternal::SocketOperation op = _stream->connect(readBuffer, writeBuffer); - if(op != IceInternal::SocketOperationNone) + if(_state == StateNotInitialized) { - return op; + IceInternal::SocketOperation op = _delegate->initialize(readBuffer, writeBuffer); + if(op != IceInternal::SocketOperationNone) + { + return op; + } + _state = StateHandshakeNotStarted; } - op = sslHandshake(); + IceInternal::SocketOperation op = sslHandshake(); if(op != IceInternal::SocketOperationNone) { return op; @@ -715,7 +719,7 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B } } - _engine->verifyPeer(_stream->fd(), _host, ICE_DYNAMIC_CAST(NativeConnectionInfo, getInfo())); + _engine->verifyPeer(_host, ICE_DYNAMIC_CAST(NativeConnectionInfo, getInfo()), toString()); _state = StateHandshakeComplete; if(_instance->engine()->securityTraceLevel() >= 1) @@ -746,8 +750,8 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B } out << toString(); } - _stream->ready(IceInternal::SocketOperationRead, - !_readUnprocessed.b.empty() || _readBuffer.i != _readBuffer.b.begin()); + _delegate->getNativeInfo()->ready(IceInternal::SocketOperationRead, + !_readUnprocessed.b.empty() || _readBuffer.i != _readBuffer.b.begin()); return IceInternal::SocketOperationNone; } @@ -778,7 +782,7 @@ IceSSL::TransceiverI::close() _credentialsInitialized = false; } - _stream->close(); + _delegate->close(); // // Clear the buffers now instead of waiting for destruction. @@ -791,9 +795,9 @@ IceSSL::TransceiverI::close() IceInternal::SocketOperation IceSSL::TransceiverI::write(IceInternal::Buffer& buf) { - if(!_stream->isConnected()) + if(_state == StateNotInitialized) { - return _stream->write(buf); + return _delegate->write(buf); } if(buf.i == buf.b.end()) @@ -826,9 +830,9 @@ IceSSL::TransceiverI::write(IceInternal::Buffer& buf) IceInternal::SocketOperation IceSSL::TransceiverI::read(IceInternal::Buffer& buf) { - if(!_stream->isConnected()) + if(_state == StateNotInitialized) { - return _stream->read(buf); + return _delegate->read(buf); } if(buf.i == buf.b.end()) @@ -837,7 +841,7 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf) } assert(_state == StateHandshakeComplete); - _stream->ready(IceInternal::SocketOperationRead, false); + _delegate->getNativeInfo()->ready(IceInternal::SocketOperationRead, false); while(buf.i != buf.b.end()) { if(_readUnprocessed.b.empty() && _readBuffer.i == _readBuffer.b.begin() && !readRaw(_readBuffer)) @@ -857,8 +861,8 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf) buf.i += decrypted; } - _stream->ready(IceInternal::SocketOperationRead, - !_readUnprocessed.b.empty() || _readBuffer.i != _readBuffer.b.begin()); + _delegate->getNativeInfo()->ready(IceInternal::SocketOperationRead, + !_readUnprocessed.b.empty() || _readBuffer.i != _readBuffer.b.begin()); return IceInternal::SocketOperationNone; } @@ -867,9 +871,9 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf) bool IceSSL::TransceiverI::startWrite(IceInternal::Buffer& buffer) { - if(!_stream->isConnected()) + if(_state == StateNotInitialized) { - return _stream->startWrite(buffer); + return _delegate->startWrite(buffer); } if(_state == StateHandshakeComplete && _bufferedW == 0) @@ -878,19 +882,19 @@ IceSSL::TransceiverI::startWrite(IceInternal::Buffer& buffer) _bufferedW = encryptMessage(buffer); } - return _stream->startWrite(_writeBuffer); + return _delegate->startWrite(_writeBuffer) && _bufferedW == (buffer.b.end() - buffer.i); } void IceSSL::TransceiverI::finishWrite(IceInternal::Buffer& buf) { - if(!_stream->isConnected()) + if(_state == StateNotInitialized) { - _stream->finishWrite(buf); + _delegate->finishWrite(buf); return; } - _stream->finishWrite(_writeBuffer); + _delegate->finishWrite(_writeBuffer); if(_writeBuffer.i != _writeBuffer.b.end()) { return; // We're not finished yet with writing the write buffer. @@ -906,36 +910,36 @@ IceSSL::TransceiverI::finishWrite(IceInternal::Buffer& buf) void IceSSL::TransceiverI::startRead(IceInternal::Buffer& buffer) { - if(!_stream->isConnected()) + if(_state == StateNotInitialized) { - _stream->startRead(buffer); + _delegate->startRead(buffer); return; } - _stream->startRead(_readBuffer); + _delegate->startRead(_readBuffer); } void IceSSL::TransceiverI::finishRead(IceInternal::Buffer& buf) { - if(!_stream->isConnected()) + if(_state == StateNotInitialized) { - _stream->finishRead(buf); + _delegate->finishRead(buf); return; } - _stream->finishRead(_readBuffer); + _delegate->finishRead(_readBuffer); if(_state == StateHandshakeComplete) { size_t decrypted = decryptMessage(buf); if(decrypted > 0) { buf.i += decrypted; - _stream->ready(IceInternal::SocketOperationRead, - !_readUnprocessed.b.empty() || _readBuffer.i != _readBuffer.b.begin()); + _delegate->getNativeInfo()->ready(IceInternal::SocketOperationRead, + !_readUnprocessed.b.empty() || _readBuffer.i != _readBuffer.b.begin()); } else { - _stream->ready(IceInternal::SocketOperationRead, false); + _delegate->getNativeInfo()->ready(IceInternal::SocketOperationRead, false); } } } @@ -950,7 +954,7 @@ IceSSL::TransceiverI::protocol() const string IceSSL::TransceiverI::toString() const { - return _stream->toString(); + return _delegate->toString(); } string @@ -963,65 +967,10 @@ Ice::ConnectionInfoPtr IceSSL::TransceiverI::getInfo() const { NativeConnectionInfoPtr info = ICE_MAKE_SHARED(NativeConnectionInfo); - fillConnectionInfo(info, info->nativeCerts); - return info; -} - -Ice::ConnectionInfoPtr -IceSSL::TransceiverI::getWSInfo(const Ice::HeaderDict& headers) const -{ - WSSNativeConnectionInfoPtr info = ICE_MAKE_SHARED(WSSNativeConnectionInfo); - fillConnectionInfo(info, info->nativeCerts); - info->headers = headers; - return info; -} - -void -IceSSL::TransceiverI::checkSendSize(const IceInternal::Buffer&) -{ -} - -void -IceSSL::TransceiverI::setBufferSize(int rcvSize, int sndSize) -{ - _stream->setBufferSize(rcvSize, sndSize); -} - -IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance, - const IceInternal::StreamSocketPtr& stream, - const string& hostOrAdapterName, - bool incoming) : - _instance(instance), - _engine(SChannelEnginePtr::dynamicCast(instance->engine())), - _host(incoming ? "" : hostOrAdapterName), - _adapterName(incoming ? hostOrAdapterName : ""), - _incoming(incoming), - _stream(stream), - _state(StateHandshakeNotStarted), - _bufferedW(0), - _sslInitialized(false), - _credentialsInitialized(false), - _verified(false) -{ -} - -IceSSL::TransceiverI::~TransceiverI() -{ -} - -void -IceSSL::TransceiverI::fillConnectionInfo(const ConnectionInfoPtr& info, 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()); - } - + info->underlying = _delegate->getInfo(); + info->incoming = _incoming; + info->adapterName = _adapterName; info->verified = _verified; - if(_sslInitialized) { CtxtHandle* ssl = const_cast<CtxtHandle*>(&_ssl); @@ -1056,7 +1005,7 @@ IceSSL::TransceiverI::fillConnectionInfo(const ConnectionInfoPtr& info, vector<C } CertificatePtr certificate = ICE_MAKE_SHARED(Certificate, cc); - nativeCerts.push_back(certificate); + info->nativeCerts.push_back(certificate); info->certs.push_back(certificate->encode()); } CertFreeCertificateChain(certChain); @@ -1080,24 +1029,53 @@ IceSSL::TransceiverI::fillConnectionInfo(const ConnectionInfoPtr& info, vector<C IceUtilInternal::lastErrorToString()); } } + return info; +} - info->adapterName = _adapterName; - info->incoming = _incoming; +void +IceSSL::TransceiverI::checkSendSize(const IceInternal::Buffer&) +{ +} + +void +IceSSL::TransceiverI::setBufferSize(int rcvSize, int sndSize) +{ + _delegate->setBufferSize(rcvSize, sndSize); +} + +IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance, + const IceInternal::TransceiverPtr& delegate, + const string& hostOrAdapterName, + bool incoming) : + _instance(instance), + _engine(SChannelEnginePtr::dynamicCast(instance->engine())), + _host(incoming ? "" : hostOrAdapterName), + _adapterName(incoming ? hostOrAdapterName : ""), + _incoming(incoming), + _delegate(delegate), + _state(StateNotInitialized), + _bufferedW(0), + _sslInitialized(false), + _credentialsInitialized(false), + _verified(false) +{ +} +IceSSL::TransceiverI::~TransceiverI() +{ } bool IceSSL::TransceiverI::writeRaw(IceInternal::Buffer& buf) { - ssize_t ret = _stream->write(reinterpret_cast<const char*>(&*buf.i), buf.b.end() - buf.i); - buf.i += ret; + _delegate->write(buf); return buf.i == buf.b.end(); } bool IceSSL::TransceiverI::readRaw(IceInternal::Buffer& buf) { - ssize_t ret = _stream->read(reinterpret_cast<char*>(&*buf.i), buf.b.end() - buf.i); - buf.i += ret; - return ret > 0; + IceInternal::Buffer::Container::iterator p = buf.i; + _delegate->read(buf); + return buf.i != p; } #endif diff --git a/cpp/src/IceSSL/SChannelTransceiverI.h b/cpp/src/IceSSL/SChannelTransceiverI.h index b9d96b47eea..dc9d8030b61 100644 --- a/cpp/src/IceSSL/SChannelTransceiverI.h +++ b/cpp/src/IceSSL/SChannelTransceiverI.h @@ -43,7 +43,7 @@ namespace IceSSL class ConnectorI; class AcceptorI; -class TransceiverI : public IceInternal::Transceiver, public IceInternal::WSTransceiverDelegate +class TransceiverI : public IceInternal::Transceiver { public: @@ -68,17 +68,14 @@ public: virtual std::string toString() const; virtual std::string toDetailedString() const; virtual Ice::ConnectionInfoPtr getInfo() const; - virtual Ice::ConnectionInfoPtr getWSInfo(const Ice::HeaderDict&) const; virtual void checkSendSize(const IceInternal::Buffer&); virtual void setBufferSize(int rcvSize, int sndSize); private: - TransceiverI(const InstancePtr&, const IceInternal::StreamSocketPtr&, const std::string&, bool); + TransceiverI(const InstancePtr&, const IceInternal::TransceiverPtr&, const std::string&, bool); virtual ~TransceiverI(); - void fillConnectionInfo(const ConnectionInfoPtr&, std::vector<CertificatePtr>&) const; - IceInternal::SocketOperation sslHandshake(); size_t decryptMessage(IceInternal::Buffer&); @@ -92,6 +89,7 @@ private: enum State { + StateNotInitialized, StateHandshakeNotStarted, StateHandshakeReadContinue, StateHandshakeWriteContinue, @@ -103,7 +101,7 @@ private: const std::string _host; const std::string _adapterName; const bool _incoming; - const IceInternal::StreamSocketPtr _stream; + const IceInternal::TransceiverPtr _delegate; State _state; // diff --git a/cpp/src/IceSSL/SSLEngine.cpp b/cpp/src/IceSSL/SSLEngine.cpp index 31bc4d54e3d..ed286df2b5b 100644 --- a/cpp/src/IceSSL/SSLEngine.cpp +++ b/cpp/src/IceSSL/SSLEngine.cpp @@ -115,23 +115,24 @@ IceSSL::SSLEngine::initialize() // VerifyPeer determines whether certificate validation failures abort a connection. // _verifyPeer = properties->getPropertyAsIntWithDefault(propPrefix + "VerifyPeer", 2); - + if(_verifyPeer < 0 || _verifyPeer > 2) { PluginInitializationException ex(__FILE__, __LINE__); ex.reason = "IceSSL: invalid value for " + propPrefix + "VerifyPeer"; throw ex; } - + _securityTraceLevel = properties->getPropertyAsInt("IceSSL.Trace.Security"); _securityTraceCategory = "Security"; } void -IceSSL::SSLEngine::verifyPeer(SOCKET fd, const string& address, const NativeConnectionInfoPtr& info) +IceSSL::SSLEngine::verifyPeer(const string& address, const NativeConnectionInfoPtr& info, const string& desc) { const CertificateVerifierPtr verifier = getCertificateVerifier(); - + +#if !defined(ICE_USE_SECURE_TRANSPORT_IOS) // // For an outgoing connection, we compare the proxy address (if any) against // fields in the server's certificate (if any). @@ -248,6 +249,7 @@ IceSSL::SSLEngine::verifyPeer(SOCKET fd, const string& address, const NativeConn } } } +#endif if(_verifyDepthMax > 0 && static_cast<int>(info->certs.size()) > _verifyDepthMax) { @@ -258,19 +260,19 @@ IceSSL::SSLEngine::verifyPeer(SOCKET fd, const string& address, const NativeConn string msg = ostr.str(); if(_securityTraceLevel >= 1) { - _logger->trace(_securityTraceCategory, msg + "\n" + IceInternal::fdToString(fd)); + _logger->trace(_securityTraceCategory, msg + "\n" + desc); } SecurityException ex(__FILE__, __LINE__); ex.reason = msg; throw ex; } - if(!_trustManager->verify(info)) + if(!_trustManager->verify(info, desc)) { string msg = string(info->incoming ? "incoming" : "outgoing") + " connection rejected by trust manager"; if(_securityTraceLevel >= 1) { - _logger->trace(_securityTraceCategory, msg + "\n" + IceInternal::fdToString(fd)); + _logger->trace(_securityTraceCategory, msg + "\n" + desc); } SecurityException ex(__FILE__, __LINE__); ex.reason = msg; @@ -282,7 +284,7 @@ IceSSL::SSLEngine::verifyPeer(SOCKET fd, const string& address, const NativeConn string msg = string(info->incoming ? "incoming" : "outgoing") + " connection rejected by certificate verifier"; if(_securityTraceLevel >= 1) { - _logger->trace(_securityTraceCategory, msg + "\n" + IceInternal::fdToString(fd)); + _logger->trace(_securityTraceCategory, msg + "\n" + desc); } SecurityException ex(__FILE__, __LINE__); ex.reason = msg; diff --git a/cpp/src/IceSSL/SSLEngine.h b/cpp/src/IceSSL/SSLEngine.h index 08b79e85bd5..25748c71c78 100644 --- a/cpp/src/IceSSL/SSLEngine.h +++ b/cpp/src/IceSSL/SSLEngine.h @@ -22,6 +22,7 @@ #if defined(ICE_USE_SECURE_TRANSPORT) # include <Security/Security.h> +# include <Security/SecureTransport.h> #elif defined(ICE_USE_SCHANNEL) // @@ -72,7 +73,7 @@ public: // // Verify peer certificate // - void verifyPeer(SOCKET, const std::string&, const NativeConnectionInfoPtr&); + void verifyPeer(const std::string&, const NativeConnectionInfoPtr&, const std::string&); CertificateVerifierPtr getCertificateVerifier() const; PasswordPromptPtr getPasswordPrompt() const; @@ -80,6 +81,7 @@ public: std::string getPassword() const; void setPassword(const std::string& password); + bool getCheckCertName() const { return _checkCertName; } int getVerifyPeer() const { return _verifyPeer; } int securityTraceLevel() const { return _securityTraceLevel; } std::string securityTraceCategory() const { return _securityTraceCategory; } @@ -120,7 +122,6 @@ public: private: void parseCiphers(const std::string&); - SecKeychainRef openKeychain(); bool _initialized; UniqueRef<CFArrayRef> _certificateAuthorities; @@ -131,8 +132,9 @@ private: std::string _defaultDir; +#if TARGET_OS_IPHONE==0 std::vector<char> _dhParams; - +#endif std::vector<SSLCipherSuite> _ciphers; IceUtil::Mutex _mutex; }; @@ -179,6 +181,7 @@ private: # endif #endif + class SChannelEngine : public SSLEngine { public: @@ -219,7 +222,22 @@ private: HCERTCHAINENGINE _chainEngine; std::vector<ALG_ID> _ciphers; }; + +#elif defined(ICE_OS_WINRT) + +class WinRTEngine : public SSLEngine +{ +public: + + WinRTEngine(const Ice::CommunicatorPtr&); + + virtual void initialize(); + virtual bool initialized() const; + virtual void destroy(); +}; + #else // OpenSSL + class OpenSSLEngine : public SSLEngine { public: diff --git a/cpp/src/IceSSL/SSLEngineF.h b/cpp/src/IceSSL/SSLEngineF.h index 6d9c7a1e284..61656a11d2a 100644 --- a/cpp/src/IceSSL/SSLEngineF.h +++ b/cpp/src/IceSSL/SSLEngineF.h @@ -19,20 +19,24 @@ namespace IceSSL { class SSLEngine; -ICE_SSL_API IceUtil::Shared* upCast(IceSSL::SSLEngine*); +ICE_SSL_API IceUtil::Shared* upCast(SSLEngine*); typedef IceInternal::Handle<SSLEngine> SSLEnginePtr; #if defined(ICE_USE_SECURE_TRANSPORT) class SecureTransportEngine; -ICE_SSL_API IceUtil::Shared* upCast(IceSSL::SecureTransportEngine*); +ICE_SSL_API IceUtil::Shared* upCast(SecureTransportEngine*); typedef IceInternal::Handle<SecureTransportEngine> SecureTransportEnginePtr; #elif defined(ICE_USE_SCHANNEL) class SChannelEngine; -ICE_SSL_API IceUtil::Shared* upCast(IceSSL::SChannelEngine*); +ICE_SSL_API IceUtil::Shared* upCast(SChannelEngine*); typedef IceInternal::Handle<SChannelEngine> SChannelEnginePtr; +#elif defined(ICE_OS_WINRT) +class WinRTEngine; +ICE_SSL_API IceUtil::Shared* upCast(WinRTEngine*); +typedef IceInternal::Handle<WinRTEngine> WinRTEnginePtr; #else // OpenSSL class OpenSSLEngine; -ICE_SSL_API IceUtil::Shared* upCast(IceSSL::OpenSSLEngine*); +ICE_SSL_API IceUtil::Shared* upCast(OpenSSLEngine*); typedef IceInternal::Handle<OpenSSLEngine> OpenSSLEnginePtr; #endif diff --git a/cpp/src/IceSSL/SecureTransportEngine.cpp b/cpp/src/IceSSL/SecureTransportEngine.cpp index 00cb59d4c83..1876477794c 100644 --- a/cpp/src/IceSSL/SecureTransportEngine.cpp +++ b/cpp/src/IceSSL/SecureTransportEngine.cpp @@ -858,6 +858,9 @@ IceSSL::SecureTransportEngine::initialize() string certFile = properties->getProperty("IceSSL.CertFile"); string keyFile = properties->getProperty("IceSSL.KeyFile"); string findCert = properties->getProperty("IceSSL.FindCert"); + string keychain = properties->getProperty("IceSSL.Keychain"); + string keychainPassword = properties->getProperty("IceSSL.KeychainPassword"); + if(!certFile.empty()) { vector<string> files; @@ -903,10 +906,10 @@ IceSSL::SecureTransportEngine::initialize() keyFile = resolved; } - UniqueRef<SecKeychainRef> kc(openKeychain()); try { - _chain.reset(loadCertificateChain(file, keyFile, kc.get(), password, passwordPrompt, passwordRetryMax)); + _chain.reset(loadCertificateChain(file, keyFile, keychain, keychainPassword, password, passwordPrompt, + passwordRetryMax)); break; } catch(const CertificateReadException& ce) @@ -924,57 +927,13 @@ IceSSL::SecureTransportEngine::initialize() } else if(!findCert.empty()) { - UniqueRef<SecKeychainRef> kc(openKeychain()); - UniqueRef<SecCertificateRef> cert(findCertificate(kc.get(), findCert)); - - // - // Retrieve the certificate chain - // - UniqueRef<SecPolicyRef> policy(SecPolicyCreateSSL(true, 0)); - SecTrustRef trust = 0; - OSStatus err = SecTrustCreateWithCertificates((CFArrayRef)cert.get(), policy.get(), &trust); - if(err || !trust) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: error creating trust object" + - (err ? ":\n" + errorToString(err) : "")); - } - UniqueRef<SecTrustRef> v(trust); - - SecTrustResultType trustResult; - if((err = SecTrustEvaluate(trust, &trustResult))) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: error evaluating trust:\n" + errorToString(err)); - } - - int chainLength = SecTrustGetCertificateCount(trust); - CFMutableArrayRef items = CFArrayCreateMutable(kCFAllocatorDefault, chainLength, &kCFTypeArrayCallBacks); - for(int i = 0; i < chainLength; ++i) - { - CFArrayAppendValue(items, SecTrustGetCertificateAtIndex(trust, i)); - } - - // - // Replace the first certificate in the chain with the - // identity. - // - SecIdentityRef identity; - err = SecIdentityCreateWithCertificate(kc.get(), cert.get(), &identity); - if(err != noErr) - { - ostringstream os; - os << "IceSSL: couldn't create identity for certificate found in the keychain:\n" << errorToString(err); - throw PluginInitializationException(__FILE__, __LINE__, os.str()); - } - CFArraySetValueAtIndex(items, 0, identity); - CFRelease(identity); - _chain.reset(items); + _chain.reset(findCertificateChain(keychain, keychainPassword, findCert)); } // // DiffieHellmanParams in DER format. // +#if defined(ICE_USE_SECURE_TRANSPORT_MACOS) string dhFile = properties->getProperty("IceSSL.DHParams"); if(!dhFile.empty()) { @@ -986,6 +945,7 @@ IceSSL::SecureTransportEngine::initialize() readFile(resolved, _dhParams); } +#endif // // Establish the cipher list. @@ -1086,6 +1046,7 @@ IceSSL::SecureTransportEngine::newContext(bool incoming) } } +#if defined(ICE_USE_SECURE_TRANSPORT_MACOS) if(!_dhParams.empty()) { if((err = SSLSetDiffieHellmanParams(ssl, &_dhParams[0], _dhParams.size()))) @@ -1094,6 +1055,7 @@ IceSSL::SecureTransportEngine::newContext(bool incoming) "IceSSL: unable to create the trust object:\n" + errorToString(err)); } } +#endif } if(_chain && (err = SSLSetCertificate(ssl, _chain.get()))) @@ -1318,92 +1280,5 @@ IceSSL::SecureTransportEngine::parseCiphers(const string& ciphers) } } -SecKeychainRef -SecureTransportEngine::openKeychain() -{ - const PropertiesPtr properties = communicator()->getProperties(); - - // - // Open the application KeyChain or create it if the keychain doesn't exists - // - string keychainPath = properties->getProperty("IceSSL.Keychain"); - string keychainPassword = properties->getProperty("IceSSL.KeychainPassword"); - - SecKeychainRef keychain = 0; - OSStatus err = 0; - if(keychainPath.empty()) - { - if((err = SecKeychainCopyDefault(&keychain))) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: unable to retrieve default keychain:\n" + errorToString(err)); - } - } - else - { - // - // KeyChain path is relative to the current working directory. - // - if(!IceUtilInternal::isAbsolutePath(keychainPath)) - { - string cwd; - if(IceUtilInternal::getcwd(cwd) == 0) - { - keychainPath = string(cwd) + '/' + keychainPath; - } - } - - if((err = SecKeychainOpen(keychainPath.c_str(), &keychain))) - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: unable to open keychain: `" + - keychainPath + "'\n" + errorToString(err)); - } - } - - UniqueRef<SecKeychainRef> k(keychain); - - SecKeychainStatus status; - err = SecKeychainGetStatus(keychain, &status); - if(err == noErr) - { - const char* pass = keychainPassword.empty() ? 0 : keychainPassword.c_str(); - if((err = SecKeychainUnlock(keychain, keychainPassword.size(), pass, pass != 0))) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: unable to unlock keychain:\n" + errorToString(err)); - } - } - else if(err == errSecNoSuchKeychain) - { - const char* pass = keychainPassword.empty() ? 0 : keychainPassword.c_str(); - if((err = SecKeychainCreate(keychainPath.c_str(), keychainPassword.size(), pass, pass == 0, 0, &keychain))) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: unable to create keychain:\n" + errorToString(err)); - } - k.reset(keychain); - } - else - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: unable to open keychain:\n" + errorToString(err)); - } - - // - // Set keychain settings to avoid keychain lock. - // - SecKeychainSettings settings; - settings.version = SEC_KEYCHAIN_SETTINGS_VERS1; - settings.lockOnSleep = FALSE; - settings.useLockInterval = FALSE; - settings.lockInterval = INT_MAX; - if((err = SecKeychainSetSettings(keychain, &settings))) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: error setting keychain settings:\n" + errorToString(err)); - } - - return k.release(); -} #endif diff --git a/cpp/src/IceSSL/SecureTransportTransceiverI.cpp b/cpp/src/IceSSL/SecureTransportTransceiverI.cpp index b043ef19713..f407e008913 100644 --- a/cpp/src/IceSSL/SecureTransportTransceiverI.cpp +++ b/cpp/src/IceSSL/SecureTransportTransceiverI.cpp @@ -96,7 +96,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 InstancePtr& instance, + const string& host) { OSStatus err = noErr; SecTrustResultType trustResult = kSecTrustResultOtherError; @@ -115,6 +116,28 @@ 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))); + CFArrayRef policies; + if((err = SecTrustCopyPolicies(trust, &policies))) + { + throw SecurityException(__FILE__, __LINE__, "IceSSL: handshake failure:\n" + errorToString(err)); + } + UniqueRef<CFMutableArrayRef> newPolicies(CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, policies)); + CFRelease(policies); + 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,18 +194,29 @@ 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) { - 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) { @@ -237,7 +271,7 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B } if(err == noErr) { - _verified = checkTrustResult(_trust, _engine, _instance); + _verified = checkTrustResult(_trust, _engine, _instance, _host); continue; // Call SSLHandshake to resume the handsake. } // Let it fall through, this will raise a SecurityException with the SSLCopyPeerTrust error. @@ -247,18 +281,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, ICE_DYNAMIC_CAST(NativeConnectionInfo, getInfo())); + _engine->verifyPeer(_host, ICE_DYNAMIC_CAST(NativeConnectionInfo, getInfo()), toString()); if(_instance->engine()->securityTraceLevel() >= 1) { @@ -317,15 +345,15 @@ IceSSL::TransceiverI::close() _ssl = 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()) @@ -402,9 +430,9 @@ IceSSL::TransceiverI::write(IceInternal::Buffer& buf) IceInternal::SocketOperation 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()) @@ -412,7 +440,7 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf) return IceInternal::SocketOperationNone; } - _stream->ready(IceInternal::SocketOperationRead, false); + _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()) @@ -471,7 +499,7 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf) errno = err; throw SocketException(__FILE__, __LINE__, IceInternal::getSocketErrno()); } - _stream->ready(IceInternal::SocketOperationRead, buffered > 0); + _delegate->getNativeInfo()->ready(IceInternal::SocketOperationRead, buffered > 0); return IceInternal::SocketOperationNone; } @@ -484,7 +512,7 @@ IceSSL::TransceiverI::protocol() const string IceSSL::TransceiverI::toString() const { - return _stream->toString(); + return _delegate->toString(); } string @@ -497,16 +525,30 @@ Ice::ConnectionInfoPtr IceSSL::TransceiverI::getInfo() const { NativeConnectionInfoPtr info = ICE_MAKE_SHARED(NativeConnectionInfo); - fillConnectionInfo(info, info->nativeCerts); - return info; -} + info->underlying = _delegate->getInfo(); + info->incoming = _incoming; + info->adapterName = _adapterName; + if(_ssl) + { + for(int i = 0, count = SecTrustGetCertificateCount(_trust); i < count; ++i) + { + SecCertificateRef cert = SecTrustGetCertificateAtIndex(_trust, i); + CFRetain(cert); -Ice::ConnectionInfoPtr -IceSSL::TransceiverI::getWSInfo(const Ice::HeaderDict& headers) const -{ - WSSNativeConnectionInfoPtr info = ICE_MAKE_SHARED(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, &cipher); + info->cipher = _engine->getCipherName(cipher); + info->verified = _verified; + } + else + { + info->verified = false; + } return info; } @@ -518,11 +560,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, + const IceInternal::TransceiverPtr& delegate, const string& hostOrAdapterName, bool incoming) : _instance(instance), @@ -530,61 +572,19 @@ IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance, _host(incoming ? "" : hostOrAdapterName), _adapterName(incoming ? hostOrAdapterName : ""), _incoming(incoming), - _stream(stream), + _delegate(delegate), _ssl(0), _trust(0), + _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 = ICE_MAKE_SHARED(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 { @@ -592,13 +592,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&) { @@ -623,13 +625,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&) { diff --git a/cpp/src/IceSSL/SecureTransportTransceiverI.h b/cpp/src/IceSSL/SecureTransportTransceiverI.h index 68b0a677783..71a2a6c5f34 100644 --- a/cpp/src/IceSSL/SecureTransportTransceiverI.h +++ b/cpp/src/IceSSL/SecureTransportTransceiverI.h @@ -17,12 +17,11 @@ #include <Ice/Transceiver.h> #include <Ice/Network.h> -#include <Ice/StreamSocket.h> -#include <Ice/WSTransceiver.h> #ifdef ICE_USE_SECURE_TRANSPORT #include <Security/Security.h> +#include <Security/SecureTransport.h> #include <CoreFoundation/CoreFoundation.h> namespace IceSSL @@ -31,7 +30,7 @@ namespace IceSSL class ConnectorI; class AcceptorI; -class TransceiverI : public IceInternal::Transceiver, public IceInternal::WSTransceiverDelegate +class TransceiverI : public IceInternal::Transceiver { public: @@ -51,7 +50,6 @@ public: virtual std::string toString() const; virtual std::string toDetailedString() const; virtual Ice::ConnectionInfoPtr getInfo() const; - virtual Ice::ConnectionInfoPtr getWSInfo(const Ice::HeaderDict&) const; virtual void checkSendSize(const IceInternal::Buffer&); virtual void setBufferSize(int rcvSize, int sndSize); @@ -60,11 +58,9 @@ public: private: - TransceiverI(const InstancePtr&, const IceInternal::StreamSocketPtr&, const std::string&, bool); + TransceiverI(const InstancePtr&, const IceInternal::TransceiverPtr&, const std::string&, bool); virtual ~TransceiverI(); - void fillConnectionInfo(const ConnectionInfoPtr&, std::vector<CertificatePtr>&) const; - friend class ConnectorI; friend class AcceptorI; @@ -73,10 +69,11 @@ private: const std::string _host; const std::string _adapterName; const bool _incoming; - const IceInternal::StreamSocketPtr _stream; + const IceInternal::TransceiverPtr _delegate; SSLContextRef _ssl; SecTrustRef _trust; + bool _connected; bool _verified; size_t _buffered; diff --git a/cpp/src/IceSSL/TrustManager.cpp b/cpp/src/IceSSL/TrustManager.cpp index 0e60abb5a82..31b42291db3 100644 --- a/cpp/src/IceSSL/TrustManager.cpp +++ b/cpp/src/IceSSL/TrustManager.cpp @@ -62,7 +62,7 @@ TrustManager::TrustManager(const Ice::CommunicatorPtr& communicator) : } bool -TrustManager::verify(const NativeConnectionInfoPtr& info) +TrustManager::verify(const NativeConnectionInfoPtr& info, const std::string& desc) { list<list<DistinguishedName> > reject, accept; @@ -139,19 +139,14 @@ TrustManager::verify(const NativeConnectionInfoPtr& info) Ice::Trace trace(_communicator->getLogger(), "Security"); if(info->incoming) { - trace << "trust manager evaluating client:\n" - << "subject = " << string(subject) << '\n' - << "adapter = " << info->adapterName << '\n' - << "local addr = " << info->localAddress << ":" << info->localPort << '\n' - << "remote addr = " << info->remoteAddress << ":" << info->remotePort; + trace << "trust manager evaluating client:\n" << "subject = " << string(subject) << '\n' + << "adapter = " << info->adapterName << '\n'; } else { - trace << "trust manager evaluating server:\n" - << "subject = " << string(subject) << '\n' - << "local addr = " << info->localAddress << ":" << info->localPort << '\n' - << "remote addr = " << info->remoteAddress << ":" << info->remotePort; + trace << "trust manager evaluating server:\n" << "subject = " << string(subject) << '\n'; } + trace << desc; } // diff --git a/cpp/src/IceSSL/TrustManager.h b/cpp/src/IceSSL/TrustManager.h index a03c5d2a694..a99363baf05 100644 --- a/cpp/src/IceSSL/TrustManager.h +++ b/cpp/src/IceSSL/TrustManager.h @@ -25,7 +25,7 @@ public: TrustManager(const Ice::CommunicatorPtr&); - bool verify(const NativeConnectionInfoPtr&); + bool verify(const NativeConnectionInfoPtr&, const std::string&); private: diff --git a/cpp/src/IceSSL/Util.cpp b/cpp/src/IceSSL/Util.cpp index b55ca494233..9a5f6bce50e 100644..100755 --- a/cpp/src/IceSSL/Util.cpp +++ b/cpp/src/IceSSL/Util.cpp @@ -8,7 +8,7 @@ // ********************************************************************** #include <IceUtil/Config.h> -#ifdef _WIN32 +#if defined(_WIN32) && !defined(ICE_OS_WINRT) # include <winsock2.h> #endif @@ -16,6 +16,7 @@ #include <IceUtil/FileUtil.h> #include <IceUtil/StringUtil.h> +#include <Ice/Base64.h> #include <Ice/LocalException.h> #include <Ice/Network.h> #include <Ice/Object.h> @@ -33,30 +34,7 @@ using namespace Ice; using namespace IceUtil; using namespace IceSSL; -void -IceSSL::readFile(const string& file, vector<char>& buffer) -{ - IceUtilInternal::ifstream is(file, ios::in | ios::binary); - if(!is.good()) - { - throw CertificateReadException(__FILE__, __LINE__, "error opening file " + file); - } - - is.seekg(0, is.end); - buffer.resize(static_cast<int>(is.tellg())); - is.seekg(0, is.beg); - - if(!buffer.empty()) - { - is.read(&buffer[0], buffer.size()); - if(!is.good()) - { - throw CertificateReadException(__FILE__, __LINE__, "error reading file " + file); - } - } -} - -#ifndef ICE_USE_OPENSSL +#if !defined(ICE_USE_OPENSSL) namespace { @@ -423,12 +401,14 @@ IceSSL::errorToString(OSStatus status) { ostringstream os; os << "(error: " << status; +#if defined(ICE_USE_SECURE_TRANSPORT_MACOS) CFStringRef s = SecCopyErrorMessageString(status, 0); if(s) { os << " description: " << fromCFString(s); CFRelease(s); } +#endif os << ")"; return os.str(); } @@ -448,6 +428,7 @@ IceSSL::fromCFString(CFStringRef v) return s; } +#if defined(ICE_USE_SECURE_TRANSPORT_MACOS) CFDictionaryRef IceSSL::getCertificateProperty(SecCertificateRef cert, CFTypeRef key) { @@ -471,10 +452,36 @@ IceSSL::getCertificateProperty(SecCertificateRef cert, CFTypeRef key) CFRelease(values); return property; } +#endif namespace { +CFDataRef +readCertFile(const string& file) +{ + IceUtilInternal::ifstream is(file, ios::in | ios::binary); + if(!is.good()) + { + throw CertificateReadException(__FILE__, __LINE__, "error opening file " + file); + } + + is.seekg(0, is.end); + size_t size = is.tellg(); + is.seekg(0, is.beg); + + CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, size); + CFDataSetLength(data, size); + is.read(reinterpret_cast<char*>(CFDataGetMutableBytePtr(data)), size); + if(!is.good()) + { + CFRelease(data); + throw CertificateReadException(__FILE__, __LINE__, "error reading file " + file); + } + return data; +} + +#if defined(ICE_USE_SECURE_TRANSPORT_MACOS) // // Check the certificate basic constraints to check if the certificate is marked as a CA. // @@ -506,12 +513,7 @@ CFArrayRef loadKeychainItems(const string& file, SecExternalItemType type, SecKeychainRef keychain, const string& passphrase, const PasswordPromptPtr& prompt, int retryMax) { - vector<char> buffer; - readFile(file, buffer); - UniqueRef<CFDataRef> data(CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, - reinterpret_cast<const UInt8*>(&buffer[0]), - buffer.size(), - kCFAllocatorNull)); + UniqueRef<CFDataRef> data(readCertFile(file)); SecItemImportExportKeyParameters params; memset(¶ms, 0, sizeof(params)); @@ -591,14 +593,93 @@ loadKeychainItems(const string& file, SecExternalItemType type, SecKeychainRef k return items; } +SecKeychainRef +openKeychain(const std::string& path, const std::string& keychainPassword) +{ + string keychainPath = path; + SecKeychainRef keychain = 0; + OSStatus err = 0; + if(keychainPath.empty()) + { + if((err = SecKeychainCopyDefault(&keychain))) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: unable to retrieve default keychain:\n" + errorToString(err)); + } + } + else + { + // + // KeyChain path is relative to the current working directory. + // + if(!IceUtilInternal::isAbsolutePath(keychainPath)) + { + string cwd; + if(IceUtilInternal::getcwd(cwd) == 0) + { + keychainPath = string(cwd) + '/' + keychainPath; + } + } + + if((err = SecKeychainOpen(keychainPath.c_str(), &keychain))) + { + throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: unable to open keychain: `" + + keychainPath + "'\n" + errorToString(err)); + } + } + + UniqueRef<SecKeychainRef> k(keychain); + + SecKeychainStatus status; + err = SecKeychainGetStatus(keychain, &status); + if(err == noErr) + { + const char* pass = keychainPassword.empty() ? 0 : keychainPassword.c_str(); + if((err = SecKeychainUnlock(keychain, keychainPassword.size(), pass, pass != 0))) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: unable to unlock keychain:\n" + errorToString(err)); + } + } + else if(err == errSecNoSuchKeychain) + { + const char* pass = keychainPassword.empty() ? 0 : keychainPassword.c_str(); + if((err = SecKeychainCreate(keychainPath.c_str(), keychainPassword.size(), pass, pass == 0, 0, &keychain))) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: unable to create keychain:\n" + errorToString(err)); + } + k.reset(keychain); + } + else + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: unable to open keychain:\n" + errorToString(err)); + } + + // + // Set keychain settings to avoid keychain lock. + // + SecKeychainSettings settings; + settings.version = SEC_KEYCHAIN_SETTINGS_VERS1; + settings.lockOnSleep = FALSE; + settings.useLockInterval = FALSE; + settings.lockInterval = INT_MAX; + if((err = SecKeychainSetSettings(keychain, &settings))) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: error setting keychain settings:\n" + errorToString(err)); + } + + return k.release(); } // // Imports a certificate private key and optionally add it to a keychain. // SecIdentityRef -IceSSL::loadPrivateKey(const string& file, SecCertificateRef cert, SecKeychainRef keychain, const string& password, - const PasswordPromptPtr& prompt, int retryMax) +loadPrivateKey(const string& file, SecCertificateRef cert, SecKeychainRef keychain, const string& password, + const PasswordPromptPtr& prompt, int retryMax) { // // Check if we already imported the certificate @@ -751,17 +832,139 @@ IceSSL::loadPrivateKey(const string& file, SecCertificateRef cert, SecKeychainRe } return identity; } +#else + +CFArrayRef +loadCerts(const string& file) +{ + UniqueRef<CFMutableArrayRef> certs(CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks)); + if(file.find(".pem") != string::npos) + { + vector<char> buffer; + readFile(file, buffer); + string strbuf(buffer.begin(), buffer.end()); + string::size_type size, startpos, endpos = 0; + bool first = true; + while(true) + { + startpos = strbuf.find("-----BEGIN CERTIFICATE-----", endpos); + if(startpos != string::npos) + { + startpos += sizeof("-----BEGIN CERTIFICATE-----"); + endpos = strbuf.find("-----END CERTIFICATE-----", startpos); + if(endpos == string::npos) + { + InitializationException ex(__FILE__, __LINE__); + ex.reason = "IceSSL: certificate " + file + " is not a valid PEM-encoded certificate"; + throw ex; + } + size = endpos - startpos; + } + else if(first) + { + startpos = 0; + endpos = string::npos; + size = strbuf.size(); + } + else + { + break; + } + + vector<unsigned char> data(IceInternal::Base64::decode(string(&buffer[startpos], size))); + UniqueRef<CFDataRef> certdata(CFDataCreate(kCFAllocatorDefault, &data[0], data.size())); + SecCertificateRef cert = SecCertificateCreateWithData(0, certdata.get()); + if(!cert) + { + InitializationException ex(__FILE__, __LINE__); + ex.reason = "IceSSL: certificate " + file + " is not a valid PEM-encoded certificate"; + throw ex; + } + CFArrayAppendValue(certs.get(), cert); + CFRelease(cert); + first = false; + } + } + else + { + UniqueRef<CFDataRef> data(readCertFile(file)); + SecCertificateRef cert = SecCertificateCreateWithData(0, data.get()); + if(!cert) + { + InitializationException ex(__FILE__, __LINE__); + ex.reason = "IceSSL: certificate " + file + " is not a valid DER-encoded certificate"; + throw ex; + } + CFArrayAppendValue(certs.get(), cert); + CFRelease(cert); + } + return certs.release(); +} +#endif + +} // // Imports a certificate (it might contain an identity or certificate depending on the format). // CFArrayRef -IceSSL::loadCertificateChain(const string& file, const string& keyFile, SecKeychainRef keychain, - const string& password, const PasswordPromptPtr& prompt, int retryMax) +IceSSL::loadCertificateChain(const string& file, const string& keyFile, const std::string& keychainPath, + const string& keychainPassword, const string& password, const PasswordPromptPtr& prompt, + int retryMax) { +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) + UniqueRef<CFDataRef> cert(readCertFile(file)); + + UniqueRef<CFMutableDictionaryRef> settings(CFDictionaryCreateMutable(0, 1, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + CFArrayRef items = 0; + OSStatus err; + if(password.empty() && prompt) + { + int count = 0; + do + { + UniqueRef<CFStringRef> pass(toCFString(prompt->getPassword())); + CFDictionarySetValue(settings.get(), kSecImportExportPassphrase, pass.get()); + err = SecPKCS12Import(cert.get(), settings.get(), &items); + ++count; + } + while(err == errSecAuthFailed && count < retryMax); + } + else + { + UniqueRef<CFStringRef> pass(toCFString(password)); + CFDictionarySetValue(settings.get(), kSecImportExportPassphrase, pass.get()); + err = SecPKCS12Import(cert.get(), settings.get(), &items); + } + if(err != noErr) + { + ostringstream os; + os << "IceSSL: unable to import certificate from file " << file << " (error = " << err << ")"; + throw InitializationException(__FILE__, __LINE__, os.str()); + } + + UniqueRef<CFArrayRef> itemsHolder(items);; + for(int i = 0; i < CFArrayGetCount(items); ++i) + { + CFDictionaryRef dict = (CFDictionaryRef)CFArrayGetValueAtIndex(items, i); + SecIdentityRef identity = (SecIdentityRef)CFDictionaryGetValue(dict, kSecImportItemIdentity); + if(identity) + { + CFArrayRef certs = (CFArrayRef)CFDictionaryGetValue(dict, kSecImportItemCertChain); + CFMutableArrayRef a = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, certs); + CFArraySetValueAtIndex(a, 0, identity); + return a; + } + } + ostringstream os; + os << "IceSSL: couldn't find identity in file " << file; + throw InitializationException(__FILE__, __LINE__, os.str()); +#else + UniqueRef<SecKeychainRef> keychain(openKeychain(keychainPath, keychainPassword)); if(keyFile.empty()) { - return loadKeychainItems(file, kSecItemTypeUnknown, keychain, password, prompt, retryMax); + return loadKeychainItems(file, kSecItemTypeUnknown, keychain.get(), password, prompt, retryMax); } else { @@ -783,26 +986,37 @@ IceSSL::loadCertificateChain(const string& file, const string& keyFile, SecKeych // add the certificate/key to the keychain if they aren't // already present in the keychain. // - UniqueRef<SecIdentityRef> identity(loadPrivateKey(keyFile, cert, keychain, password, prompt, retryMax)); + UniqueRef<SecIdentityRef> identity(loadPrivateKey(keyFile, cert, keychain.get(), password, prompt, retryMax)); CFMutableArrayRef a = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, items.get()); CFArraySetValueAtIndex(a, 0, identity.get()); return a; } +#endif } SecCertificateRef IceSSL::loadCertificate(const string& file) { - CFArrayRef items = loadKeychainItems(file, kSecItemTypeCertificate, 0, "", 0, 0); - SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(items, 0); +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) + UniqueRef<CFArrayRef> certs(loadCerts(file)); + assert(CFArrayGetCount(certs.get()) > 0); + SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs.get(), 0); + CFRetain(cert); + return cert; +#else + UniqueRef<CFArrayRef> items(loadKeychainItems(file, kSecItemTypeCertificate, 0, "", 0, 0)); + SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(items.get(), 0); CFRetain(cert); - CFRelease(items); return cert; +#endif } CFArrayRef IceSSL::loadCACertificates(const string& file) { +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) + return loadCerts(file); +#else UniqueRef<CFArrayRef> items(loadKeychainItems(file, kSecItemTypeCertificate, 0, "", 0, 0)); CFMutableArrayRef certificateAuthorities = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); int count = CFArrayGetCount(items.get()); @@ -816,10 +1030,11 @@ IceSSL::loadCACertificates(const string& file) } } return certificateAuthorities; +#endif } -SecCertificateRef -IceSSL::findCertificate(SecKeychainRef keychain, const string& value) +CFArrayRef +IceSSL::findCertificateChain(const std::string& keychainPath, const std::string& keychainPassword, const string& value) { // // Search the keychain using key:value pairs. The following keys are supported: @@ -836,17 +1051,20 @@ IceSSL::findCertificate(SecKeychainRef keychain, const string& value) &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); - const void* values[] = { keychain }; +#if defined(ICE_USE_SECURE_TRANSPORT_MACOS) + UniqueRef<SecKeychainRef> keychain(openKeychain(keychainPath, keychainPassword)); + const void* values[] = { keychain.get() }; UniqueRef<CFArrayRef> searchList(CFArrayCreate(kCFAllocatorDefault, values, 1, &kCFTypeArrayCallBacks)); - - CFDictionarySetValue(query.get(), kSecMatchLimit, kSecMatchLimitOne); CFDictionarySetValue(query.get(), kSecMatchSearchList, searchList.get()); +#endif + CFDictionarySetValue(query.get(), kSecMatchLimit, kSecMatchLimitOne); CFDictionarySetValue(query.get(), kSecClass, kSecClassCertificate); CFDictionarySetValue(query.get(), kSecReturnRef, kCFBooleanTrue); CFDictionarySetValue(query.get(), kSecMatchCaseInsensitive, kCFBooleanTrue); size_t start = 0; size_t pos; + bool valid = false; while((pos = value.find(':', start)) != string::npos) { string field = IceUtilInternal::toUpper(IceUtilInternal::trim(value.substr(start, pos - start))); @@ -906,6 +1124,7 @@ IceSSL::findCertificate(SecKeychainRef keychain, const string& value) { UniqueRef<CFStringRef> v(toCFString(arg)); CFDictionarySetValue(query.get(), field == "LABEL" ? kSecAttrLabel : kSecMatchSubjectContains, v.get()); + valid = true; } else if(field == "SUBJECTKEYID" || field == "SERIAL") { @@ -917,10 +1136,11 @@ IceSSL::findCertificate(SecKeychainRef keychain, const string& value) UniqueRef<CFDataRef> v(CFDataCreate(kCFAllocatorDefault, &buffer[0], buffer.size())); CFDictionarySetValue(query.get(), field == "SUBJECTKEYID" ? kSecAttrSubjectKeyID : kSecAttrSerialNumber, v.get()); + valid = true; } } - if(CFDictionaryGetCount(query.get()) == 5) + if(!valid) { throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: invalid value `" + value + "'"); } @@ -932,7 +1152,92 @@ IceSSL::findCertificate(SecKeychainRef keychain, const string& value) throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: find certificate `" + value + "' failed:\n" + errorToString(err)); } - return cert; + + UniqueRef<SecCertificateRef> certHolder(cert); + + // + // Retrieve the certificate chain + // + UniqueRef<SecPolicyRef> policy(SecPolicyCreateSSL(true, 0)); + SecTrustRef trust = 0; + err = SecTrustCreateWithCertificates((CFArrayRef)cert, policy.get(), &trust); + if(err || !trust) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: error creating trust object" + + (err ? ":\n" + errorToString(err) : "")); + } + UniqueRef<SecTrustRef> v(trust); + + SecTrustResultType trustResult; + if((err = SecTrustEvaluate(trust, &trustResult))) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: error evaluating trust:\n" + errorToString(err)); + } + + int chainLength = SecTrustGetCertificateCount(trust); + CFMutableArrayRef items = CFArrayCreateMutable(kCFAllocatorDefault, chainLength, &kCFTypeArrayCallBacks); + UniqueRef<CFMutableArrayRef> itemsHolder(items); + for(int i = 0; i < chainLength; ++i) + { + CFArrayAppendValue(items, SecTrustGetCertificateAtIndex(trust, i)); + } + + // + // Replace the first certificate in the chain with the + // identity. + // + SecIdentityRef identity; +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) + + // + // SecIdentityCreateWithCertificate isn't supported on iOS so we lookup the identity + // using the certicate label. If the user added the identity with SecItemAdd the + // identity has the same label as the certificate. + // + query.reset(CFDictionaryCreateMutable(0, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + CFDictionarySetValue(query.get(), kSecClass, kSecClassCertificate); + CFDictionarySetValue(query.get(), kSecValueRef, cert); + CFDictionarySetValue(query.get(), kSecReturnAttributes, kCFBooleanTrue); + CFDictionaryRef attributes; + err = SecItemCopyMatching(query.get(), (CFTypeRef*)&attributes); + if(err != noErr) + { + ostringstream os; + os << "IceSSL: couldn't create identity for certificate found in the keychain:\n" << errorToString(err); + throw PluginInitializationException(__FILE__, __LINE__, os.str()); + } + UniqueRef<CFDictionaryRef> attributesHolder(attributes); + + // Now lookup the identity with the label + query.reset(CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + CFDictionarySetValue(query.get(), kSecMatchLimit, kSecMatchLimitOne); + CFDictionarySetValue(query.get(), kSecClass, kSecClassIdentity); + CFDictionarySetValue(query.get(), kSecAttrLabel, (CFDataRef)CFDictionaryGetValue(attributes, kSecAttrLabel)); + CFDictionarySetValue(query.get(), kSecReturnRef, kCFBooleanTrue); + err = SecItemCopyMatching(query.get(), (CFTypeRef*)&identity); + if(err == noErr) + { + SecCertificateRef cert2 = NULL; + if((err = SecIdentityCopyCertificate(identity, &cert2)) == noErr) + { + err = CFEqual(cert2, cert) ? noErr : errSecItemNotFound; + CFRelease(cert2); + } + } +#else + err = SecIdentityCreateWithCertificate(keychain.get(), cert, &identity); +#endif + if(err != noErr) + { + ostringstream os; + os << "IceSSL: couldn't create identity for certificate found in the keychain:\n" << errorToString(err); + throw PluginInitializationException(__FILE__, __LINE__, os.str()); + } + CFArraySetValueAtIndex(items, 0, identity); + CFRelease(identity); + return itemsHolder.release(); } #elif defined(ICE_USE_SCHANNEL) @@ -1195,9 +1500,55 @@ IceSSL::findCertificates(const string& location, const string& name, const strin } #endif +void +IceSSL::readFile(const string& file, vector<char>& buffer) +{ + IceUtilInternal::ifstream is(file, ios::in | ios::binary); + if(!is.good()) + { + throw CertificateReadException(__FILE__, __LINE__, "error opening file " + file); + } + + is.seekg(0, is.end); + buffer.resize(static_cast<int>(is.tellg())); + is.seekg(0, is.beg); + + if(!buffer.empty()) + { + is.read(&buffer[0], buffer.size()); + if(!is.good()) + { + throw CertificateReadException(__FILE__, __LINE__, "error reading file " + file); + } + } +} + bool IceSSL::checkPath(const string& path, const string& defaultDir, bool dir, string& resolved) { +#if defined(ICE_USE_SECURE_TRANSPORT_IOS) + CFURLRef url = 0; + CFBundleRef bundle = CFBundleGetMainBundle(); + if(bundle) + { + CFStringRef resourceName = toCFString(path); + CFStringRef subDirName = toCFString(defaultDir); + url = CFBundleCopyResourceURL(bundle, resourceName, 0, subDirName); + CFRelease(resourceName); + CFRelease(subDirName); + + UInt8 filePath[PATH_MAX]; + if(CFURLGetFileSystemRepresentation(url, true, filePath, sizeof(filePath))) + { + string tmp = string(reinterpret_cast<char*>(filePath)); + if((dir && IceUtilInternal::directoryExists(tmp)) || (!dir && IceUtilInternal::fileExists(tmp))) + { + resolved = tmp; + return true; + } + } + } +#endif if(IceUtilInternal::isAbsolutePath(path)) { if((dir && IceUtilInternal::directoryExists(path)) || (!dir && IceUtilInternal::fileExists(path))) diff --git a/cpp/src/IceSSL/Util.h b/cpp/src/IceSSL/Util.h index 855e0ac71b8..3e98050ee35 100644 --- a/cpp/src/IceSSL/Util.h +++ b/cpp/src/IceSSL/Util.h @@ -150,27 +150,23 @@ toCFString(const std::string& s) std::string errorToString(CFErrorRef); std::string errorToString(OSStatus); +#if !defined(__APPLE__) || TARGET_OS_IPHONE == 0 // // Retrieve a certificate property // CFDictionaryRef getCertificateProperty(SecCertificateRef, CFTypeRef); - -// -// Read a private key from an file and associate it to the given certificate. -// -SecIdentityRef loadPrivateKey(const std::string&, SecCertificateRef, SecKeychainRef, const std::string&, - const PasswordPromptPtr&, int); +#endif // // Read certificate from a file. // -CFArrayRef loadCertificateChain(const std::string&, const std::string&, SecKeychainRef, const std::string&, - const PasswordPromptPtr&, int); +CFArrayRef loadCertificateChain(const std::string&, const std::string&, const std::string&, const std::string&, + const std::string&, const PasswordPromptPtr&, int); SecCertificateRef loadCertificate(const std::string&); CFArrayRef loadCACertificates(const std::string&); -SecCertificateRef findCertificate(SecKeychainRef, const std::string&); +CFArrayRef findCertificateChain(const std::string&, const std::string&, const std::string&); #elif defined(ICE_USE_SCHANNEL) std::vector<PCCERT_CONTEXT> diff --git a/cpp/src/IceSSL/WinRTEngine.cpp b/cpp/src/IceSSL/WinRTEngine.cpp new file mode 100755 index 00000000000..7eb59f922a7 --- /dev/null +++ b/cpp/src/IceSSL/WinRTEngine.cpp @@ -0,0 +1,43 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <IceSSL/Config.h> + +#ifdef ICE_OS_WINRT + +#include <IceSSL/SSLEngine.h> +#include <IceUtil/Shared.h> + +IceUtil::Shared* IceSSL::upCast(IceSSL::WinRTEngine* p) { return p; } + +using namespace IceSSL; + +WinRTEngine::WinRTEngine(const Ice::CommunicatorPtr& communicator) : SSLEngine(communicator) +{ + +} + +void +WinRTEngine::initialize() +{ +} + +bool +WinRTEngine::initialized() const +{ + return true; +} + +void +WinRTEngine::destroy() +{ +} + +#endif + diff --git a/cpp/src/IceSSL/WinRTTransceiverI.cpp b/cpp/src/IceSSL/WinRTTransceiverI.cpp new file mode 100755 index 00000000000..be0d632eaf8 --- /dev/null +++ b/cpp/src/IceSSL/WinRTTransceiverI.cpp @@ -0,0 +1,199 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <IceSSL/Config.h> + +#ifdef ICE_OS_WINRT + +#include <IceSSL/WinRTTransceiverI.h> +#include <IceSSL/Instance.h> +#include <IceSSL/SSLEngine.h> + +using namespace std; +using namespace Ice; +using namespace IceSSL; + +using namespace Platform; +using namespace Windows::Networking; +using namespace Windows::Networking::Sockets; + +IceInternal::NativeInfoPtr +IceSSL::TransceiverI::getNativeInfo() +{ + return _delegate->getNativeInfo(); +} + +IceInternal::SocketOperation +IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::Buffer& writeBuffer) +{ + if(!_connected) + { + IceInternal::SocketOperation status = _delegate->initialize(readBuffer, writeBuffer); + if(status != IceInternal::SocketOperationNone) + { + return status; + } + _connected = true; + + // + // Continue connecting, this will call startWrite/finishWrite to upgrade the stream + // to SSL. + // + return IceInternal::SocketOperationConnect; + } + else if(!_upgraded) + { + _upgraded = true; + } + return IceInternal::SocketOperationNone; +} + +IceInternal::SocketOperation +#ifdef ICE_CPP11_MAPPING +IceSSL::TransceiverI::closing(bool initiator, exception_ptr ex) +#else +IceSSL::TransceiverI::closing(bool initiator, const Ice::LocalException& ex) +#endif +{ + return _delegate->closing(initiator, ex); +} + +void +IceSSL::TransceiverI::close() +{ + _delegate->close(); +} + +IceInternal::SocketOperation +IceSSL::TransceiverI::write(IceInternal::Buffer& buf) +{ + return _delegate->write(buf); +} + +IceInternal::SocketOperation +IceSSL::TransceiverI::read(IceInternal::Buffer& buf) +{ + return _delegate->read(buf); +} + +bool +IceSSL::TransceiverI::startWrite(IceInternal::Buffer& buf) +{ + if(_connected && !_upgraded) + { + StreamSocket^ stream = safe_cast<StreamSocket^>(_delegate->getNativeInfo()->fd()); + HostName^ host = ref new HostName(ref new String(IceUtil::stringToWstring(_host).c_str())); + try + { + Windows::Foundation::IAsyncAction^ action = stream->UpgradeToSslAsync(SocketProtectionLevel::Tls12, host); + getNativeInfo()->queueAction(IceInternal::SocketOperationWrite, action); + } + catch(Platform::Exception^ ex) + { + IceInternal::checkErrorCode(__FILE__, __LINE__, ex->HResult); + } + return true; + } + return _delegate->startWrite(buf); +} + +void +IceSSL::TransceiverI::finishWrite(IceInternal::Buffer& buf) +{ + if(_connected && !_upgraded) + { + IceInternal::AsyncInfo* asyncInfo = getNativeInfo()->getAsyncInfo(IceInternal::SocketOperationWrite); + if(asyncInfo->count == SOCKET_ERROR) + { + IceInternal::checkErrorCode(__FILE__, __LINE__, asyncInfo->error); + } + return; + } + _delegate->finishWrite(buf); +} + +void +IceSSL::TransceiverI::startRead(IceInternal::Buffer& buf) +{ + _delegate->startRead(buf); +} + +void +IceSSL::TransceiverI::finishRead(IceInternal::Buffer& buf) +{ + _delegate->finishRead(buf); +} + +string +IceSSL::TransceiverI::protocol() const +{ + return _instance->protocol(); +} + +string +IceSSL::TransceiverI::toString() const +{ + return _delegate->toString(); +} + +string +IceSSL::TransceiverI::toDetailedString() const +{ + return toString(); +} + +Ice::ConnectionInfoPtr +IceSSL::TransceiverI::getInfo() const +{ + NativeConnectionInfoPtr info = ICE_MAKE_SHARED(NativeConnectionInfo); + StreamSocket^ stream = safe_cast<StreamSocket^>(_delegate->getNativeInfo()->fd()); + info->nativeCerts.push_back(ICE_MAKE_SHARED(Certificate, stream->Information->ServerCertificate)); + info->certs.push_back(info->nativeCerts.back()->encode()); + for(auto iter = stream->Information->ServerIntermediateCertificates->First(); iter->HasCurrent; iter->MoveNext()) + { + info->nativeCerts.push_back(ICE_MAKE_SHARED(Certificate, iter->Current)); + info->certs.push_back(info->nativeCerts.back()->encode()); + } + info->adapterName = _adapterName; + info->incoming = _incoming; + info->underlying = _delegate->getInfo(); + return info; +} + +void +IceSSL::TransceiverI::checkSendSize(const IceInternal::Buffer&) +{ +} + +void +IceSSL::TransceiverI::setBufferSize(int rcvSize, int sndSize) +{ + _delegate->setBufferSize(rcvSize, sndSize); +} + +IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance, + const IceInternal::TransceiverPtr& delegate, + const string& hostOrAdapterName, + bool incoming) : + _instance(instance), + _engine(WinRTEnginePtr::dynamicCast(instance->engine())), + _host(incoming ? "" : hostOrAdapterName), + _adapterName(incoming ? hostOrAdapterName : ""), + _incoming(incoming), + _delegate(delegate), + _connected(false), + _upgraded(false) +{ +} + +IceSSL::TransceiverI::~TransceiverI() +{ +} + +#endif diff --git a/cpp/src/IceSSL/WinRTTransceiverI.h b/cpp/src/IceSSL/WinRTTransceiverI.h new file mode 100755 index 00000000000..d3994eb359a --- /dev/null +++ b/cpp/src/IceSSL/WinRTTransceiverI.h @@ -0,0 +1,81 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef ICE_SSL_WINRT_TRANSCEIVER_I_H +#define ICE_SSL_WINRT_TRANSCEIVER_I_H + +#include <IceSSL/Config.h> + +#ifdef ICE_OS_WINRT + +#include <IceSSL/InstanceF.h> +#include <IceSSL/SSLEngineF.h> +#include <IceSSL/Plugin.h> + +#include <Ice/Transceiver.h> +#include <Ice/Network.h> + +namespace IceSSL +{ + +class ConnectorI; +class AcceptorI; + +class TransceiverI : public IceInternal::Transceiver +{ +public: + + virtual IceInternal::NativeInfoPtr getNativeInfo(); + + virtual IceInternal::SocketOperation initialize(IceInternal::Buffer&, IceInternal::Buffer&); +#ifdef ICE_CPP11_MAPPING + virtual IceInternal::SocketOperation closing(bool, std::exception_ptr); +#else + virtual IceInternal::SocketOperation closing(bool, const Ice::LocalException&); +#endif + virtual void close(); + virtual IceInternal::SocketOperation write(IceInternal::Buffer&); + virtual IceInternal::SocketOperation read(IceInternal::Buffer&); + virtual bool startWrite(IceInternal::Buffer&); + virtual void finishWrite(IceInternal::Buffer&); + virtual void startRead(IceInternal::Buffer&); + virtual void finishRead(IceInternal::Buffer&); + + virtual std::string protocol() const; + virtual std::string toString() const; + virtual std::string toDetailedString() const; + virtual Ice::ConnectionInfoPtr getInfo() const; + virtual void checkSendSize(const IceInternal::Buffer&); + virtual void setBufferSize(int rcvSize, int sndSize); + +private: + + TransceiverI(const InstancePtr&, const IceInternal::TransceiverPtr&, const std::string&, bool); + virtual ~TransceiverI(); + + friend class ConnectorI; + friend class AcceptorI; + + const InstancePtr _instance; + const WinRTEnginePtr _engine; + const std::string _host; + const std::string _adapterName; + const bool _incoming; + const IceInternal::TransceiverPtr _delegate; + + bool _connected; + bool _upgraded; +}; +typedef IceUtil::Handle<TransceiverI> TransceiverIPtr; + +} + +#endif + +#endif diff --git a/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj b/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj index 2b35204da8a..6b376e66034 100644 --- a/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj +++ b/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj @@ -136,10 +136,18 @@ <IceBuilder Include="..\..\..\..\..\slice\IceSSL\EndpointInfo.ice" /> </ItemGroup> <ItemGroup> - <ClCompile Include="..\..\uwp\AcceptorI.cpp" /> - <ClCompile Include="..\..\uwp\ConnectorI.cpp" /> - <ClCompile Include="..\..\uwp\EndpointI.cpp" /> - <ClCompile Include="..\..\uwp\TransceiverI.cpp" /> + <ClCompile Include="..\..\AcceptorI.cpp" /> + <ClCompile Include="..\..\Certificate.cpp" /> + <ClCompile Include="..\..\ConnectorI.cpp" /> + <ClCompile Include="..\..\EndpointI.cpp" /> + <ClCompile Include="..\..\Instance.cpp" /> + <ClCompile Include="..\..\PluginI.cpp" /> + <ClCompile Include="..\..\RFC2253.cpp" /> + <ClCompile Include="..\..\SSLEngine.cpp" /> + <ClCompile Include="..\..\TrustManager.cpp" /> + <ClCompile Include="..\..\Util.cpp" /> + <ClCompile Include="..\..\WinRTEngine.cpp" /> + <ClCompile Include="..\..\WinRTTransceiverI.cpp" /> <ClCompile Include="ARM\Debug\ConnectionInfo.cpp"> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> diff --git a/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj.filters b/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj.filters index 7d141e0bffd..17f262f778e 100644 --- a/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj.filters +++ b/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj.filters @@ -75,18 +75,6 @@ </IceBuilder> </ItemGroup> <ItemGroup> - <ClCompile Include="..\..\uwp\AcceptorI.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="..\..\uwp\ConnectorI.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="..\..\uwp\EndpointI.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="..\..\uwp\TransceiverI.cpp"> - <Filter>Source Files</Filter> - </ClCompile> <ClCompile Include="Win32\Debug\ConnectionInfo.cpp"> <Filter>Source Files\Win32\Debug</Filter> </ClCompile> @@ -123,6 +111,40 @@ <ClCompile Include="x64\Release\EndpointInfo.cpp"> <Filter>Source Files\x64\Release</Filter> </ClCompile> + <ClCompile Include="..\..\ConnectorI.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\AcceptorI.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\EndpointI.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\Instance.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\SSLEngine.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\TrustManager.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\WinRTTransceiverI.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\PluginI.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\Certificate.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\Util.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\WinRTEngine.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\RFC2253.cpp" /> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\uwp\AcceptorI.h"> |