summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp')
-rw-r--r--cpp/src/Ice/msbuild/iceuwp++11/iceuwp++11.vcxproj.filters9
-rwxr-xr-xcpp/src/IceSSL/Certificate.cpp94
-rw-r--r--cpp/src/IceSSL/SSLEngine.cpp24
-rw-r--r--cpp/src/IceSSL/SSLEngine.h18
-rwxr-xr-xcpp/src/IceSSL/Util.cpp135
-rw-r--r--cpp/src/IceSSL/Util.h3
-rwxr-xr-xcpp/src/IceSSL/WinRTEngine.cpp37
-rwxr-xr-xcpp/src/IceSSL/WinRTTransceiverI.cpp182
-rwxr-xr-xcpp/src/IceSSL/WinRTTransceiverI.h2
-rw-r--r--cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj4
-rw-r--r--cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj.filters16
11 files changed, 479 insertions, 45 deletions
diff --git a/cpp/src/Ice/msbuild/iceuwp++11/iceuwp++11.vcxproj.filters b/cpp/src/Ice/msbuild/iceuwp++11/iceuwp++11.vcxproj.filters
index 5a48cd6767d..84cf9cc5098 100644
--- a/cpp/src/Ice/msbuild/iceuwp++11/iceuwp++11.vcxproj.filters
+++ b/cpp/src/Ice/msbuild/iceuwp++11/iceuwp++11.vcxproj.filters
@@ -1087,7 +1087,6 @@
<ClCompile Include="..\..\Timer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\..\TcpEndpointI.cpp" />
<ClCompile Include="..\..\TcpAcceptor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -1100,6 +1099,12 @@
<ClCompile Include="..\..\StreamSocket.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\TcpEndpointI.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\WindowsStringConverter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<IceBuilder Include="..\..\..\..\..\slice\Ice\BuiltinSequences.ice">
@@ -1924,4 +1929,4 @@
<Filter>Header Files\x64\Release</Filter>
</ClInclude>
</ItemGroup>
-</Project>
+</Project> \ No newline at end of file
diff --git a/cpp/src/IceSSL/Certificate.cpp b/cpp/src/IceSSL/Certificate.cpp
index 8ecfd8c0dc0..3f4eb05bed9 100755
--- a/cpp/src/IceSSL/Certificate.cpp
+++ b/cpp/src/IceSSL/Certificate.cpp
@@ -28,6 +28,9 @@
# pragma GCC diagnostic ignored "-Wold-style-cast"
#elif defined(ICE_USE_SECURE_TRANSPORT)
# include <Security/Security.h>
+#elif defined(ICE_OS_WINRT)
+# include <ppltasks.h>
+# include <nserror.h>
#endif
#ifdef __SUNPRO_CC
@@ -49,6 +52,15 @@ using namespace std;
using namespace Ice;
using namespace IceSSL;
+#ifdef ICE_OS_WINRT
+using namespace concurrency;
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Storage;
+using namespace Windows::Storage::Streams;
+using namespace Windows::Security::Cryptography;
+#endif
+
#if defined(ICE_USE_SECURE_TRANSPORT) || defined(ICE_USE_SCHANNEL)
//
@@ -599,19 +611,19 @@ 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())
+ for(auto iter = subAltNames->EmailName->First(); iter->HasCurrent; iter->MoveNext())
{
altNames.push_back(make_pair(AltNameEmail, wstringToString(iter->Current->Data())));
}
- for (auto iter = subAltNames->DnsName->First(); iter->HasCurrent; iter->MoveNext())
+ for(auto iter = subAltNames->DnsName->First(); iter->HasCurrent; iter->MoveNext())
{
altNames.push_back(make_pair(AltNameDNS, wstringToString(iter->Current->Data())));
}
- for (auto iter = subAltNames->Url->First(); iter->HasCurrent; iter->MoveNext())
+ for(auto iter = subAltNames->Url->First(); iter->HasCurrent; iter->MoveNext())
{
altNames.push_back(make_pair(AltNameURL, wstringToString(iter->Current->Data())));
}
- for (auto iter = subAltNames->IPAddress->First(); iter->HasCurrent; iter->MoveNext())
+ for(auto iter = subAltNames->IPAddress->First(); iter->HasCurrent; iter->MoveNext())
{
altNames.push_back(make_pair(AltNAmeIP, wstringToString(iter->Current->Data())));
}
@@ -1035,7 +1047,7 @@ Certificate::Certificate(X509CertificateRef cert) : _cert(cert)
throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Invalid certificate reference");
}
-#ifdef ICE_USE_SCHANNEL
+#if defined(ICE_USE_SCHANNEL)
_certInfo = 0;
try
{
@@ -1055,9 +1067,7 @@ Certificate::Certificate(X509CertificateRef cert) : _cert(cert)
_cert = 0;
throw;
}
-#endif
-
-#if defined(ICE_USE_SECURE_TRANSPORT_IOS)
+#elif defined(ICE_USE_SECURE_TRANSPORT_IOS)
_subject = NULL;
_issuer = NULL;
#endif
@@ -1125,8 +1135,39 @@ Certificate::load(const string& file)
BIO_free(cert);
return ICE_MAKE_SHARED(Certificate, x);
#elif defined(ICE_OS_WINRT)
- // TODO
- return ICE_NULLPTR;
+ promise<shared_ptr<Certificate>> result;
+ create_task(StorageFile::GetFileFromApplicationUriAsync(
+ ref new Uri(ref new String(stringToWstring(file).c_str())))).then([](StorageFile^ file)
+ {
+ return FileIO::ReadBufferAsync(file);
+ },
+ task_continuation_context::use_arbitrary()).then([&result, &file](task<IBuffer^> previous)
+ {
+ try
+ {
+ result.set_value(make_shared<Certificate>(ref new Certificates::Certificate(previous.get())));
+ }
+ catch(Platform::Exception^ ex)
+ {
+ try
+ {
+ if(HRESULT_CODE(ex->HResult) == ERROR_FILE_NOT_FOUND)
+ {
+ throw CertificateReadException(__FILE__, __LINE__, "certificate file not found:\n" + file);
+ }
+ else
+ {
+ throw Ice::SyscallException(__FILE__, __LINE__, ex->HResult);
+ }
+ }
+ catch(...)
+ {
+ result.set_exception(current_exception());
+ }
+ }
+ },
+ task_continuation_context::use_arbitrary());
+ return result.get_future().get();
#else
# error "Unknown platform"
#endif
@@ -1198,8 +1239,25 @@ Certificate::decode(const string& encoding)
BIO_free(cert);
return ICE_MAKE_SHARED(Certificate, x);
#elif defined(ICE_OS_WINRT)
- // TODO
- return ICE_NULLPTR;
+ 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)));
+ auto writer = ref new DataWriter();
+ writer->WriteBytes(Platform::ArrayReference<unsigned char>(&data[0], data.size()));
+ return make_shared<Certificate>(ref new Certificates::Certificate(writer->DetachBuffer()));
#else
# error "Unknown platform"
#endif
@@ -1461,7 +1519,7 @@ Certificate::encode() const
#elif defined(ICE_OS_WINRT)
auto reader = Windows::Storage::Streams::DataReader::FromBuffer(_cert->GetCertificateBlob());
std::vector<unsigned char> data(reader->UnconsumedBufferLength);
- if (!data.empty())
+ if(!data.empty())
{
reader->ReadBytes(Platform::ArrayReference<unsigned char>(&data[0], static_cast<unsigned int>(data.size())));
}
@@ -1646,9 +1704,9 @@ Certificate::getSubjectDN() const
}
else
{
- string s = "CN=";
- s += fromCFString(UniqueRef<CFStringRef>(SecCertificateCopySubjectSummary(_cert)).get());
- return DistinguishedName(s);
+ ostringstream os;
+ os << "CN=" << fromCFString(UniqueRef<CFStringRef>(SecCertificateCopySubjectSummary(_cert)).get());
+ return DistinguishedName(os.str());
}
#elif defined(ICE_USE_SECURE_TRANSPORT_MACOS)
return getX509Name(_cert, kSecOIDX509V1SubjectName);
@@ -1657,7 +1715,9 @@ Certificate::getSubjectDN() const
#elif defined(ICE_USE_OPENSSL)
return DistinguishedName(RFC2253::parseStrict(convertX509NameToString(X509_get_subject_name(_cert))));
#elif defined(ICE_OS_WINRT)
- return DistinguishedName(wstringToString(_cert->Subject->Data()));
+ ostringstream os;
+ os << "CN=" << wstringToString(_cert->Subject->Data());
+ return DistinguishedName(os.str());
#else
# error "Unknown platform"
#endif
diff --git a/cpp/src/IceSSL/SSLEngine.cpp b/cpp/src/IceSSL/SSLEngine.cpp
index ed286df2b5b..4f8f927495f 100644
--- a/cpp/src/IceSSL/SSLEngine.cpp
+++ b/cpp/src/IceSSL/SSLEngine.cpp
@@ -291,3 +291,27 @@ IceSSL::SSLEngine::verifyPeer(const string& address, const NativeConnectionInfoP
throw ex;
}
}
+
+bool
+IceSSL::SSLEngine::getCheckCertName() const
+{
+ return _checkCertName;
+}
+
+int
+IceSSL::SSLEngine::getVerifyPeer() const
+{
+ return _verifyPeer;
+}
+
+int
+IceSSL::SSLEngine::securityTraceLevel() const
+{
+ return _securityTraceLevel;
+}
+
+std::string
+IceSSL::SSLEngine::securityTraceCategory() const
+{
+ return _securityTraceCategory;
+}
diff --git a/cpp/src/IceSSL/SSLEngine.h b/cpp/src/IceSSL/SSLEngine.h
index 25748c71c78..c8b84fcd31b 100644
--- a/cpp/src/IceSSL/SSLEngine.h
+++ b/cpp/src/IceSSL/SSLEngine.h
@@ -40,6 +40,8 @@
# include <sspi.h>
# include <schannel.h>
# undef SECURITY_WIN32
+#elif defined(ICE_OS_WINRT)
+# include <mutex>
#endif
namespace IceSSL
@@ -81,10 +83,10 @@ 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; }
+ bool getCheckCertName() const;
+ int getVerifyPeer() const;
+ int securityTraceLevel() const;
+ std::string securityTraceCategory() const;
private:
@@ -234,6 +236,13 @@ public:
virtual void initialize();
virtual bool initialized() const;
virtual void destroy();
+ virtual std::shared_ptr<Certificate> certificate();
+
+private:
+
+ std::shared_ptr<Certificate> _certificate;
+ bool _initialized;
+ std::mutex _mutex;
};
#else // OpenSSL
@@ -263,7 +272,6 @@ private:
enum Protocols { SSLv3 = 0x01, TLSv1_0 = 0x02, TLSv1_1 = 0x04, TLSv1_2 = 0x08 };
int parseProtocols(const Ice::StringSeq&) const;
-
bool _initialized;
SSL_CTX* _ctx;
std::string _defaultDir;
diff --git a/cpp/src/IceSSL/Util.cpp b/cpp/src/IceSSL/Util.cpp
index 5b592797842..67a81e09740 100755
--- a/cpp/src/IceSSL/Util.cpp
+++ b/cpp/src/IceSSL/Util.cpp
@@ -23,6 +23,11 @@
#include <Ice/StringConverter.h>
#include <fstream>
+#ifdef ICE_OS_WINRT
+# include <ppltasks.h>
+#endif
+using namespace IceUtilInternal;
+
#ifdef ICE_USE_OPENSSL
# include <openssl/err.h>
//
@@ -36,6 +41,17 @@ using namespace Ice;
using namespace IceUtil;
using namespace IceSSL;
+#ifdef ICE_OS_WINRT
+using namespace concurrency;
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::Storage;
+using namespace Windows::Storage::Streams;
+using namespace Windows::Security::Cryptography;
+using namespace Windows::Security::Cryptography::Core;
+using namespace Windows::Security::Cryptography::Certificates;
+#endif
#ifdef ICE_CPP11_MAPPING
IceSSL::CertificateVerifier::CertificateVerifier(std::function<bool(const std::shared_ptr<NativeConnectionInfo>&)> v) :
@@ -1677,6 +1693,125 @@ IceSSL::findCertificates(const string& location, const string& name, const strin
}
return certs;
}
+#elif defined (ICE_OS_WINRT)
+IVectorView<Certificates::Certificate^>^
+IceSSL::findCertificates(const string& name, const string& value)
+{
+ CertificateQuery^ query = ref new CertificateQuery();
+ query->StoreName = ref new String(stringToWstring(name).c_str());
+ query->IncludeDuplicates = true;
+
+ if(value != "*")
+ {
+ if(value.find(':', 0) == string::npos)
+ {
+ throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: no key in `" + value + "'");
+ }
+ size_t start = 0;
+ size_t pos;
+ while((pos = value.find(':', start)) != string::npos)
+ {
+ string field = IceUtilInternal::toUpper(IceUtilInternal::trim(value.substr(start, pos - start)));
+ if(field != "ISSUER" && field != "THUMBPRINT" && field != "FRIENDLYNAME")
+ {
+ throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: unknown key in `" + value + "'");
+ }
+
+ start = pos + 1;
+ while(start < value.size() && (value[start] == ' ' || value[start] == '\t'))
+ {
+ ++start;
+ }
+
+ if(start == value.size())
+ {
+ throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: missing argument in `" + value + "'");
+ }
+
+ string arg;
+ if(value[start] == '"' || value[start] == '\'')
+ {
+ size_t end = start;
+ ++end;
+ while(end < value.size())
+ {
+ if(value[end] == value[start] && value[end - 1] != '\\')
+ {
+ break;
+ }
+ ++end;
+ }
+ if(end == value.size() || value[end] != value[start])
+ {
+ throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: unmatched quote in `" + value + "'");
+ }
+ ++start;
+ arg = value.substr(start, end - start);
+ start = end + 1;
+ }
+ else
+ {
+ size_t end = value.find_first_of(" \t", start);
+ if(end == string::npos)
+ {
+ arg = value.substr(start);
+ start = value.size();
+ }
+ else
+ {
+ arg = value.substr(start, end - start);
+ start = end + 1;
+ }
+ }
+
+ if(field == "ISSUER")
+ {
+ query->IssuerName = ref new String(stringToWstring(arg).c_str());
+ }
+ else if(field == "FRIENDLYNAME")
+ {
+ query->FriendlyName = ref new String(stringToWstring(arg).c_str());
+ }
+ else if(field == "THUMBPRINT")
+ {
+ vector<BYTE> buffer;
+ if(!parseBytes(arg, buffer))
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: invalid `IceSSL.FindCert' property: can't decode the value");
+ }
+ query->Thumbprint = ref new Array<unsigned char>(&buffer[0], static_cast<unsigned int>(buffer.size()));
+ }
+ }
+ }
+
+ std::promise<IVectorView<Certificates::Certificate^>^> p;
+ HRESULT error = 0;
+ create_task(CertificateStores::FindAllAsync(query)).then(
+ [&](task<IVectorView<Certificates::Certificate^>^> previous)
+ {
+ try
+ {
+ p.set_value(previous.get());
+ }
+ catch(Platform::Exception^ err)
+ {
+ try
+ {
+ Ice::SyscallException ex(__FILE__, __LINE__);
+ ex.error = err->HResult;
+ throw ex;
+ }
+ catch(...)
+ {
+ p.set_exception(current_exception());
+ }
+ }
+ },
+ task_continuation_context::use_arbitrary());
+
+ return p.get_future().get();
+}
#endif
void
diff --git a/cpp/src/IceSSL/Util.h b/cpp/src/IceSSL/Util.h
index 1ff3b12aab5..59ff813a1a8 100644
--- a/cpp/src/IceSSL/Util.h
+++ b/cpp/src/IceSSL/Util.h
@@ -202,6 +202,9 @@ CFArrayRef findCertificateChain(const std::string&, const std::string&, const st
#elif defined(ICE_USE_SCHANNEL)
std::vector<PCCERT_CONTEXT>
findCertificates(const std::string&, const std::string&, const std::string&, std::vector<HCERTSTORE>&);
+#elif defined(ICE_OS_WINRT)
+Windows::Foundation::Collections::IVectorView<Windows::Security::Cryptography::Certificates::Certificate^>^
+findCertificates(const std::string&, const std::string&);
#endif
//
diff --git a/cpp/src/IceSSL/WinRTEngine.cpp b/cpp/src/IceSSL/WinRTEngine.cpp
index a6dc675c581..651fd2ace53 100755
--- a/cpp/src/IceSSL/WinRTEngine.cpp
+++ b/cpp/src/IceSSL/WinRTEngine.cpp
@@ -12,26 +12,59 @@
#ifdef ICE_OS_WINRT
#include <IceSSL/SSLEngine.h>
+#include <Ice/Communicator.h>
+#include <Ice/Properties.h>
#include <IceUtil/Shared.h>
+#include <string>
+
IceUtil::Shared* IceSSL::upCast(IceSSL::WinRTEngine* p) { return p; }
+using namespace std;
using namespace IceSSL;
WinRTEngine::WinRTEngine(const Ice::CommunicatorPtr& communicator) : SSLEngine(communicator)
{
-
}
void
WinRTEngine::initialize()
{
+ lock_guard<mutex> lock(_mutex);
+ if(_initialized)
+ {
+ return;
+ }
+
+ SSLEngine::initialize();
+
+ const auto properties = communicator()->getProperties();
+
+ //
+ // Load client certificate
+ //
+ string findCert = properties->getProperty("IceSSL.FindCert");
+ if(!findCert.empty())
+ {
+ auto certs = findCertificates(properties->getPropertyWithDefault("IceSSL.CertStore", "My"), findCert);
+ if(certs->Size > 0)
+ {
+ _certificate = make_shared<IceSSL::Certificate>(certs->GetAt(0));
+ }
+ }
+ _initialized = true;
}
bool
WinRTEngine::initialized() const
{
- return true;
+ return _initialized;
+}
+
+shared_ptr<Certificate>
+WinRTEngine::certificate()
+{
+ return _certificate;
}
void
diff --git a/cpp/src/IceSSL/WinRTTransceiverI.cpp b/cpp/src/IceSSL/WinRTTransceiverI.cpp
index d9bca2912a9..6aad729e957 100755
--- a/cpp/src/IceSSL/WinRTTransceiverI.cpp
+++ b/cpp/src/IceSSL/WinRTTransceiverI.cpp
@@ -14,14 +14,94 @@
#include <IceSSL/WinRTTransceiverI.h>
#include <IceSSL/Instance.h>
#include <IceSSL/SSLEngine.h>
+#include <Ice/Logger.h>
+#include <ppltasks.h>
using namespace std;
using namespace Ice;
using namespace IceSSL;
+using namespace concurrency;
using namespace Platform;
using namespace Windows::Networking;
using namespace Windows::Networking::Sockets;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::Security::Cryptography::Certificates;
+
+namespace
+{
+
+std::string
+validationResultToString(ChainValidationResult result)
+{
+ switch (result)
+ {
+ case ChainValidationResult::Success:
+ {
+ return "The certificate chain was verified.";
+ }
+ case ChainValidationResult::Untrusted:
+ {
+ return "A certificate in the chain is not trusted.";
+ }
+ case ChainValidationResult::Revoked:
+ {
+ return "A certificate in the chain has been revoked.";
+ }
+ case ChainValidationResult::Expired:
+ {
+ return "A certificate in the chain has expired.";
+ }
+ case ChainValidationResult::IncompleteChain:
+ {
+ return "The certificate chain is missing one or more certificates.";
+ }
+ case ChainValidationResult::InvalidSignature:
+ {
+ return "The signature of a certificate in the chain cannot be verified.";
+ }
+ case ChainValidationResult::WrongUsage:
+ {
+ return "A certificate in the chain is being used for a purpose other than one specified by its CA.";
+ }
+ case ChainValidationResult::InvalidName:
+ {
+ return "A certificate in the chain has a name that is not valid. The name is either not included in "
+ "the permitted list or is explicitly excluded.";
+ }
+ case ChainValidationResult::InvalidCertificateAuthorityPolicy:
+ {
+ return "A certificate in the chain has a policy that is not valid.";
+ }
+ case ChainValidationResult::BasicConstraintsError:
+ {
+ return "The basic constraint extension of a certificate in the chain has not been observed.";
+ }
+ case ChainValidationResult::UnknownCriticalExtension:
+ {
+ return "A certificate in the chain contains an unknown extension that is marked \"critical\".";
+ }
+ case ChainValidationResult::RevocationInformationMissing:
+ {
+ return "No installed or registered DLL was found to verify revocation.";
+ }
+ case ChainValidationResult::RevocationFailure:
+ {
+ return "Unable to connect to the revocation server.";
+ }
+ case ChainValidationResult::OtherErrors:
+ {
+ return "An unexpected error occurred while validating the certificate chain.";
+ }
+ default:
+ {
+ assert(false);
+ return "";
+ }
+ }
+}
+
+}
IceInternal::NativeInfoPtr
IceSSL::TransceiverI::getNativeInfo()
@@ -50,6 +130,89 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
else if(!_upgraded)
{
_upgraded = true;
+ try
+ {
+ auto fd = safe_cast<StreamSocket^>(_delegate->getNativeInfo()->fd());
+ if (fd->Information->ServerCertificate)
+ {
+ //
+ // Build the certificate chain
+ //
+ auto params = ref new ChainBuildingParameters();
+ params->AuthorityInformationAccessEnabled = false;
+ params->CurrentTimeValidationEnabled = true;
+ params->NetworkRetrievalEnabled = false;
+ params->RevocationCheckEnabled = false;
+
+ promise<CertificateChain^> p;
+
+ create_task(fd->Information->ServerCertificate->BuildChainAsync(
+ fd->Information->ServerIntermediateCertificates, params)).then(
+ [&](task<CertificateChain^> previous)
+ {
+ try
+ {
+ p.set_value(previous.get());
+ }
+ catch (Platform::Exception^ ex)
+ {
+ try
+ {
+ throw SyscallException(__FILE__, __LINE__, ex->HResult);
+ }
+ catch(...)
+ {
+ p.set_exception(current_exception());
+ }
+ }
+ });
+
+ _chain = p.get_future().get();
+
+ ChainValidationResult result = _chain->Validate();
+ //
+ // Ignore InvalidName errors here SSLEngine::verifyPeer already checks that
+ // using IceSSL.CheckCertName settings.
+ //
+ if(result != ChainValidationResult::InvalidName && result != ChainValidationResult::Success)
+ {
+ if(_engine->getVerifyPeer() == 0)
+ {
+ if(_instance->traceLevel() >= 1)
+ {
+ _instance->logger()->trace(_instance->traceCategory(),
+ "IceSSL: ignoring certificate verification failure\n" +
+ validationResultToString(result));
+ }
+ }
+ else
+ {
+ throw SecurityException(__FILE__, __LINE__,
+ "IceSSL: certificate validation error:\n" + validationResultToString(result));
+ }
+ }
+ else
+ {
+ _verified = true;
+ }
+ }
+ else if((!_incoming && _engine->getVerifyPeer() > 0) || (_incoming && _engine->getVerifyPeer() == 2))
+ {
+ //
+ // Clients require server certificate if VerifyPeer > 0 and servers require client
+ // certificate if VerifyPeer == 2
+ //
+ throw SecurityException(__FILE__, __LINE__, "IceSSL: certificate required");
+ }
+
+ _engine->verifyPeer(_host, dynamic_pointer_cast<IceSSL::NativeConnectionInfo>(getInfo()), toString());
+ }
+ catch(Platform::Exception^ ex)
+ {
+ ostringstream os;
+ os << "IceSSL: certificate verification failure:\n" << wstringToString(ex->Message->Data());
+ throw SecurityException(__FILE__, __LINE__, os.str());
+ }
}
return IceInternal::SocketOperationNone;
}
@@ -85,6 +248,18 @@ IceSSL::TransceiverI::startWrite(IceInternal::Buffer& buf)
{
StreamSocket^ stream = safe_cast<StreamSocket^>(_delegate->getNativeInfo()->fd());
HostName^ host = ref new HostName(ref new String(IceUtil::stringToWstring(_host).c_str()));
+
+ //
+ // We ignre SSL invalid name errors at this point, the certificate name will be later verify
+ // by SSLEngine veryPeer implementation.
+ //
+ stream->Control->IgnorableServerCertificateErrors->Append(ChainValidationResult::InvalidName);
+
+ if(_engine->certificate())
+ {
+ stream->Control->ClientCertificate = _engine->certificate()->getCert();
+ }
+
try
{
Windows::Foundation::IAsyncAction^ action = stream->UpgradeToSslAsync(SocketProtectionLevel::Tls12, host);
@@ -151,11 +326,13 @@ IceSSL::TransceiverI::getInfo() const
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())
+ auto certs = _chain ? _chain->GetCertificates(true) : stream->Information->ServerIntermediateCertificates;
+ for(auto iter = certs->First(); iter->HasCurrent; iter->MoveNext())
{
info->nativeCerts.push_back(ICE_MAKE_SHARED(Certificate, iter->Current));
info->certs.push_back(info->nativeCerts.back()->encode());
}
+ info->verified = _verified;
info->adapterName = _adapterName;
info->incoming = _incoming;
info->underlying = _delegate->getInfo();
@@ -184,7 +361,8 @@ IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance,
_incoming(incoming),
_delegate(delegate),
_connected(false),
- _upgraded(false)
+ _upgraded(false),
+ _verified(false)
{
}
diff --git a/cpp/src/IceSSL/WinRTTransceiverI.h b/cpp/src/IceSSL/WinRTTransceiverI.h
index 29d285175a6..71429198022 100755
--- a/cpp/src/IceSSL/WinRTTransceiverI.h
+++ b/cpp/src/IceSSL/WinRTTransceiverI.h
@@ -67,6 +67,8 @@ private:
bool _connected;
bool _upgraded;
+ bool _verified;
+ Windows::Security::Cryptography::Certificates::CertificateChain^ _chain;
};
typedef IceUtil::Handle<TransceiverI> TransceiverIPtr;
diff --git a/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj b/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj
index 6b376e66034..8e4a2dd18fb 100644
--- a/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj
+++ b/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj
@@ -318,10 +318,6 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</ExcludedFromBuild>
</ClInclude>
- <ClInclude Include="..\..\uwp\AcceptorI.h" />
- <ClInclude Include="..\..\uwp\ConnectorI.h" />
- <ClInclude Include="..\..\uwp\EndpointI.h" />
- <ClInclude Include="..\..\uwp\TransceiverI.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="$(IceBuilderCppTargets)" Condition="Exists('$(IceBuilderCppTargets)')" />
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 17f262f778e..e3eed3add57 100644
--- a/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj.filters
+++ b/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj.filters
@@ -144,21 +144,11 @@
<ClCompile Include="..\..\WinRTEngine.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\..\RFC2253.cpp" />
+ <ClCompile Include="..\..\RFC2253.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
- <ClInclude Include="..\..\uwp\AcceptorI.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\..\uwp\ConnectorI.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\..\uwp\EndpointI.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\..\uwp\TransceiverI.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="..\..\..\..\include\generated\uwp\Win32\Debug\IceSSL\ConnectionInfo.h">
<Filter>Header Files\Win32\Debug</Filter>
</ClInclude>