summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
authorJose <jose@zeroc.com>2017-03-16 16:11:24 +0100
committerJose <jose@zeroc.com>2017-03-16 16:11:24 +0100
commitc6f4057a8975e2312d82f22af59f2069d2b5e8ab (patch)
tree1312f2c5798821dd8b4c583f30983542d9528790 /cpp
parentRemoved C# Ice.BatchRequestInterceptor (ICE-7662) (diff)
downloadice-c6f4057a8975e2312d82f22af59f2069d2b5e8ab.tar.bz2
ice-c6f4057a8975e2312d82f22af59f2069d2b5e8ab.tar.xz
ice-c6f4057a8975e2312d82f22af59f2069d2b5e8ab.zip
Fixed (ICE-7621) - Refactor IceSSL API to support multiple implementations
Diffstat (limited to 'cpp')
-rw-r--r--cpp/include/IceSSL/Config.h23
-rw-r--r--cpp/include/IceSSL/IceSSL.h13
-rw-r--r--cpp/include/IceSSL/OpenSSL.h115
-rw-r--r--cpp/include/IceSSL/Plugin.h340
-rw-r--r--cpp/include/IceSSL/SChannel.h66
-rw-r--r--cpp/include/IceSSL/SecureTransport.h66
-rw-r--r--cpp/include/IceSSL/UWP.h58
-rw-r--r--cpp/include/IceUtil/PushDisableWarnings.h2
-rw-r--r--cpp/msbuild/ice.nuget.targets6
-rw-r--r--cpp/msbuild/ice.openssl.test.sln94
-rw-r--r--cpp/msbuild/ice.proj56
-rw-r--r--cpp/msbuild/ice.v140.sln28
-rw-r--r--cpp/src/IceSSL/AcceptorI.cpp9
-rw-r--r--cpp/src/IceSSL/AcceptorI.h2
-rwxr-xr-xcpp/src/IceSSL/Certificate.cpp2076
-rw-r--r--cpp/src/IceSSL/CertificateI.cpp284
-rw-r--r--cpp/src/IceSSL/CertificateI.h69
-rw-r--r--cpp/src/IceSSL/ConnectorI.cpp8
-rw-r--r--cpp/src/IceSSL/ConnectorI.h2
-rw-r--r--cpp/src/IceSSL/IceSSLOpenSSL.rc33
-rw-r--r--cpp/src/IceSSL/Instance.h2
-rw-r--r--cpp/src/IceSSL/InstanceF.h8
-rw-r--r--cpp/src/IceSSL/Makefile.mk16
-rw-r--r--cpp/src/IceSSL/OpenSSLCertificateI.cpp572
-rw-r--r--cpp/src/IceSSL/OpenSSLEngine.cpp132
-rw-r--r--cpp/src/IceSSL/OpenSSLEngine.h64
-rw-r--r--cpp/src/IceSSL/OpenSSLEngineF.h32
-rw-r--r--cpp/src/IceSSL/OpenSSLPluginI.cpp130
-rw-r--r--cpp/src/IceSSL/OpenSSLTransceiverI.cpp318
-rw-r--r--cpp/src/IceSSL/OpenSSLTransceiverI.h42
-rw-r--r--cpp/src/IceSSL/OpenSSLUtil.cpp463
-rw-r--r--cpp/src/IceSSL/OpenSSLUtil.h63
-rwxr-xr-xcpp/src/IceSSL/PluginI.cpp117
-rw-r--r--cpp/src/IceSSL/PluginI.h26
-rw-r--r--cpp/src/IceSSL/RFC2253.cpp10
-rw-r--r--cpp/src/IceSSL/RFC2253.h8
-rw-r--r--cpp/src/IceSSL/SChannelCertificateI.cpp569
-rw-r--r--cpp/src/IceSSL/SChannelEngine.cpp309
-rw-r--r--cpp/src/IceSSL/SChannelEngine.h124
-rw-r--r--cpp/src/IceSSL/SChannelEngineF.h32
-rw-r--r--cpp/src/IceSSL/SChannelPluginI.cpp92
-rw-r--r--cpp/src/IceSSL/SChannelTransceiverI.cpp56
-rw-r--r--cpp/src/IceSSL/SChannelTransceiverI.h19
-rw-r--r--cpp/src/IceSSL/SSLEngine.cpp22
-rw-r--r--cpp/src/IceSSL/SSLEngine.h226
-rw-r--r--cpp/src/IceSSL/SSLEngineF.h19
-rw-r--r--cpp/src/IceSSL/SecureTransportCertificateI.cpp858
-rw-r--r--cpp/src/IceSSL/SecureTransportEngine.cpp66
-rw-r--r--cpp/src/IceSSL/SecureTransportEngine.h60
-rw-r--r--cpp/src/IceSSL/SecureTransportEngineF.h31
-rw-r--r--cpp/src/IceSSL/SecureTransportPluginI.cpp94
-rw-r--r--cpp/src/IceSSL/SecureTransportTransceiverI.cpp74
-rw-r--r--cpp/src/IceSSL/SecureTransportTransceiverI.h17
-rw-r--r--cpp/src/IceSSL/SecureTransportUtil.cpp855
-rw-r--r--cpp/src/IceSSL/SecureTransportUtil.h47
-rw-r--r--cpp/src/IceSSL/UWPCertificateI.cpp271
-rw-r--r--cpp/src/IceSSL/UWPEngine.cpp300
-rw-r--r--cpp/src/IceSSL/UWPEngine.h46
-rw-r--r--cpp/src/IceSSL/UWPEngineF.h31
-rw-r--r--cpp/src/IceSSL/UWPPluginI.cpp94
-rw-r--r--cpp/src/IceSSL/UWPTransceiverI.cpp49
-rw-r--r--cpp/src/IceSSL/UWPTransceiverI.h20
-rwxr-xr-xcpp/src/IceSSL/Util.cpp1815
-rw-r--r--cpp/src/IceSSL/Util.h115
-rw-r--r--cpp/src/IceSSL/msbuild/icessl++11/icessl++11.vcxproj6
-rw-r--r--cpp/src/IceSSL/msbuild/icessl++11/icessl++11.vcxproj.filters12
-rw-r--r--cpp/src/IceSSL/msbuild/icessl/icessl.vcxproj6
-rw-r--r--cpp/src/IceSSL/msbuild/icessl/icessl.vcxproj.filters12
-rw-r--r--cpp/src/IceSSL/msbuild/icesslopenssl++11/icesslopenssl++11.vcxproj128
-rw-r--r--cpp/src/IceSSL/msbuild/icesslopenssl++11/icesslopenssl++11.vcxproj.filters96
-rw-r--r--cpp/src/IceSSL/msbuild/icesslopenssl++11/packages.config4
-rw-r--r--cpp/src/IceSSL/msbuild/icesslopenssl/icesslopenssl.vcxproj133
-rw-r--r--cpp/src/IceSSL/msbuild/icesslopenssl/icesslopenssl.vcxproj.filters96
-rw-r--r--cpp/src/IceSSL/msbuild/icesslopenssl/packages.config4
-rw-r--r--cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj7
-rw-r--r--cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj.filters15
-rw-r--r--cpp/test/IceSSL/configuration/AllTests.cpp82
-rw-r--r--cpp/test/IceSSL/configuration/Client.cpp6
-rw-r--r--cpp/test/IceSSL/configuration/Server.cpp4
-rw-r--r--cpp/test/IceSSL/configuration/msbuild/clientopenssl/clientopenssl.vcxproj358
-rw-r--r--cpp/test/IceSSL/configuration/msbuild/clientopenssl/clientopenssl.vcxproj.filters141
-rw-r--r--cpp/test/IceSSL/configuration/msbuild/clientopenssl/packages.config6
-rw-r--r--cpp/test/IceSSL/configuration/msbuild/serveropenssl/packages.config6
-rw-r--r--cpp/test/IceSSL/configuration/msbuild/serveropenssl/serveropenssl.vcxproj350
-rw-r--r--cpp/test/IceSSL/configuration/msbuild/serveropenssl/serveropenssl.vcxproj.filters144
85 files changed, 8313 insertions, 4967 deletions
diff --git a/cpp/include/IceSSL/Config.h b/cpp/include/IceSSL/Config.h
index d6d31fc5cef..9305f9b3784 100644
--- a/cpp/include/IceSSL/Config.h
+++ b/cpp/include/IceSSL/Config.h
@@ -15,27 +15,12 @@
//
// Automatically link IceSSL[D|++11|++11D].lib with Visual C++
//
-#if !defined(ICE_BUILDING_ICE_SSL) && defined(ICESSL_API_EXPORTS)
-# define ICE_BUILDING_ICE_SSL
+#if !defined(ICE_BUILDING_ICESSL) && defined(ICESSL_API_EXPORTS)
+# define ICE_BUILDING_ICESSL
#endif
-#if defined(_MSC_VER) && !defined(ICE_BUILDING_ICE_SSL)
-# pragma comment(lib, ICE_LIBNAME("IceSSL"))
-#endif
-
-#if defined(__APPLE__)
-# define ICE_USE_SECURE_TRANSPORT 1
-#if defined(__APPLE__) && TARGET_OS_IPHONE != 0
-# define ICE_USE_SECURE_TRANSPORT_IOS 1
-#else
-# define ICE_USE_SECURE_TRANSPORT_MACOS 1
-#endif
-#elif defined(_WIN32)
-# if !defined(ICE_OS_UWP)
-# define ICE_USE_SCHANNEL 1
-# endif
-#else
-# define ICE_USE_OPENSSL 1
+#if defined(_MSC_VER) && !defined(ICE_BUILDING_ICESSL)
+# pragma comment(lib, ICE_LIBNAME("IceSSL"))
#endif
#endif
diff --git a/cpp/include/IceSSL/IceSSL.h b/cpp/include/IceSSL/IceSSL.h
index 87882208554..4052921c511 100644
--- a/cpp/include/IceSSL/IceSSL.h
+++ b/cpp/include/IceSSL/IceSSL.h
@@ -13,6 +13,19 @@
#include <IceUtil/PushDisableWarnings.h>
#include <Ice/Config.h>
#include <IceSSL/Plugin.h>
+
+#if defined(_WIN32)
+# if defined(ICE_OS_UWP)
+# include <IceSSL/UWP.h>
+# else
+# include <IceSSL/SChannel.h>
+# endif
+#elif defined(__APPLE__)
+# include <IceSSL/SecureTransport.h>
+#else
+# include <IceSSL/OpenSSL.h>
+#endif
+
#include <IceSSL/EndpointInfo.h>
#include <IceSSL/ConnectionInfo.h>
#include <IceUtil/PopDisableWarnings.h>
diff --git a/cpp/include/IceSSL/OpenSSL.h b/cpp/include/IceSSL/OpenSSL.h
new file mode 100644
index 00000000000..4f2d8c333a8
--- /dev/null
+++ b/cpp/include/IceSSL/OpenSSL.h
@@ -0,0 +1,115 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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 ICESSL_OPENSSL_H
+#define ICESSL_OPENSSL_H
+
+#include <IceSSL/Plugin.h>
+
+#include <openssl/x509v3.h>
+#include <openssl/pem.h>
+
+//
+// Automatically link IceSSLOpenSSL[D|++11|++11D].lib with Visual C++
+//
+#if defined(_MSC_VER)
+# if !defined(ICE_BUILDING_ICESSL_OPENSSL) && defined(ICESSL_OPENSSL_API_EXPORTS)
+# define ICE_BUILDING_ICESSL_OPENSSL
+# endif
+
+# if !defined(ICE_BUILDING_ICESSL_OPENSSL)
+# pragma comment(lib, ICE_LIBNAME("IceSSLOpenSSL"))
+# endif
+#endif
+
+#ifndef ICESSL_OPENSSL_API
+# if defined(ICE_STATIC_LIBS)
+# define ICESSL_OPENSSL_API /**/
+# elif defined(ICESSL_OPENSSL_API_EXPORTS)
+# define ICESSL_OPENSSL_API ICE_DECLSPEC_EXPORT
+# else
+# define ICESSL_OPENSSL_API ICE_DECLSPEC_IMPORT
+# endif
+#endif
+
+namespace IceSSL
+{
+
+namespace OpenSSL
+{
+
+class Certificate;
+ICE_DEFINE_PTR(CertificatePtr, Certificate);
+
+class ICESSL_OPENSSL_API Certificate : public virtual IceSSL::Certificate
+{
+public:
+
+ //
+ // Construct a certificate using a native certificate.
+ //
+ // The Certificate class assumes ownership of the given native
+ // certificate.
+ //
+ static CertificatePtr create(x509_st*);
+
+ //
+ // Load the certificate from a file. The certificate must use the
+ // PEM encoding format. Raises CertificateReadException if the
+ // file cannot be read.
+ //
+ static CertificatePtr load(const std::string&);
+
+ //
+ // Decode a certificate from a string that uses the PEM encoding
+ // format. Raises CertificateEncodingException if an error
+ // occurs.
+ //
+ static CertificatePtr decode(const std::string&);
+
+ //
+ // Retrieve the native X509 certificate value wrapped by this
+ // object.
+ //
+ // The returned reference is only valid for the lifetime of this
+ // object. you can increment it with X509_dup.
+ //
+ virtual x509_st* getCert() const = 0;
+};
+
+class ICESSL_OPENSSL_API Plugin : public virtual IceSSL::Plugin
+{
+public:
+ //
+ // Establish the OpenSSL context. This must be done before the
+ // plug-in is initialized, therefore the application must define
+ // the property Ice.InitPlugins=0, set the context, and finally
+ // invoke initializePlugins on the PluginManager.
+ //
+ // When the application supplies its own OpenSSL context, the
+ // plug-in ignores configuration properties related to certificates,
+ // keys, and passwords.
+ //
+ // Note that the plugin assumes ownership of the given context.
+ //
+ virtual void setContext(SSL_CTX*) = 0;
+
+ //
+ // Obtain the SSL context. Use caution when modifying this value.
+ // Changes made to this value have no effect on existing connections.
+ //
+ virtual SSL_CTX* getContext() = 0;
+
+};
+
+} // OpenSSL namespace end
+
+} // IceSSL namespace end
+
+#endif
diff --git a/cpp/include/IceSSL/Plugin.h b/cpp/include/IceSSL/Plugin.h
index 6731f60b76d..8e3d2f44f5b 100644
--- a/cpp/include/IceSSL/Plugin.h
+++ b/cpp/include/IceSSL/Plugin.h
@@ -11,7 +11,6 @@
#define ICESSL_PLUGIN_H
#include <Ice/Plugin.h>
-#include <Ice/UniqueRef.h>
#include <IceSSL/Config.h>
#include <IceSSL/ConnectionInfo.h>
@@ -24,22 +23,6 @@
#include <vector>
#include <list>
-// For struct sockaddr_storage
-#ifdef _WIN32
-#ifndef ICE_OS_UWP
-# include <winsock2.h>
-#endif
-#else
-# include <sys/socket.h>
-#endif
-
-#if defined(ICE_USE_SECURE_TRANSPORT)
-# include <CoreFoundation/CFError.h>
-# include <Security/Security.h>
-#elif defined(ICE_USE_SCHANNEL)
-# include <wincrypt.h>
-#endif
-
#ifndef ICESSL_API
# if defined(ICE_STATIC_LIBS)
# define ICESSL_API /**/
@@ -50,38 +33,6 @@
# endif
#endif
-#ifdef ICE_USE_OPENSSL
-
-//
-// Pointer to an opaque SSL session context object. ssl_ctx_st is the
-// OpenSSL type that holds configuration settings for all SSL
-// connections.
-//
-typedef struct ssl_ctx_st SSL_CTX;
-typedef struct X509_name_st X509NAME;
-
-typedef struct X509_extension_st* X509ExtensionRef;
-typedef struct x509_st* X509CertificateRef;
-typedef struct evp_pkey_st* KeyRef;
-
-#elif defined(ICE_USE_SECURE_TRANSPORT)
-
-typedef SecCertificateRef X509CertificateRef;
-typedef SecKeyRef KeyRef;
-
-#elif defined(ICE_USE_SCHANNEL)
-
-typedef CERT_EXTENSION X509ExtensionRef;
-typedef CERT_SIGNED_CONTENT_INFO* X509CertificateRef;
-typedef CERT_PUBLIC_KEY_INFO* KeyRef;
-
-#elif defined(ICE_OS_UWP)
-
-typedef Windows::Security::Cryptography::Certificates::Certificate^ X509CertificateRef;
-typedef Windows::Security::Cryptography::Core::CryptographicKey^ KeyRef;
-
-#endif
-
namespace IceSSL
{
@@ -116,9 +67,6 @@ class ICESSL_API CertificateEncodingException : public IceUtil::ExceptionHelper<
public:
CertificateEncodingException(const char*, int, const std::string&);
-#ifdef ICE_USE_SECURE_TRANSPORT
- CertificateEncodingException(const char*, int, CFErrorRef);
-#endif
#ifndef ICE_CPP11_COMPILER
virtual ~CertificateEncodingException() throw();
#endif
@@ -158,50 +106,6 @@ private:
};
//
-// Forward declaration.
-//
-class Certificate;
-ICE_DEFINE_PTR(CertificatePtr, Certificate);
-
-//
-// A representation of a PublicKey.
-//
-class ICESSL_API PublicKey
-#ifndef ICE_CPP11_MAPPING
- : public virtual IceUtil::Shared
-#endif
-{
-public:
-
- PublicKey(const CertificatePtr&, KeyRef);
-
-#ifdef ICE_USE_OPENSSL
- ~PublicKey();
-#endif
- //
- // Retrieve the native public key value wrapped by this object.
- //
- // The returned reference is only valid for the lifetime of this
- // object. With SecureTransport you can increment the reference
- // count of the returned object with CFRetain.
- //
- KeyRef key() const;
-
-private:
-
- friend class Certificate;
-
- CertificatePtr _cert;
-#ifdef __APPLE__
- IceInternal::UniqueRef<KeyRef> _key;
-#else
- KeyRef _key;
-#endif
-
-};
-ICE_DEFINE_PTR(PublicKeyPtr, PublicKey);
-
-//
// This class represents a DistinguishedName, similar to the Java
// type X500Principal and the .NET type X500DistinguishedName.
//
@@ -217,17 +121,6 @@ class ICESSL_API DistinguishedName
{
public:
-#ifdef ICE_USE_OPENSSL
- //
- // Create a DistinguishedName using an OpenSSL value.
- //
- explicit DistinguishedName(X509NAME*);
-#endif
-
-#if defined(__APPLE__) && TARGET_OS_IPHONE != 0
- explicit DistinguishedName(CFDataRef);
-#endif
-
//
// Create a DistinguishedName from a string encoded using
// the rules in RFC2253.
@@ -264,9 +157,11 @@ public:
//
operator std::string() const;
-private:
+protected:
- void unescape();
+ void unescape();
+
+private:
std::list<std::pair<std::string, std::string> > _rdns;
std::list<std::pair<std::string, std::string> > _unescaped;
@@ -296,12 +191,8 @@ operator!=(const DistinguishedName& lhs, const DistinguishedName& rhs)
return !(lhs == rhs);
}
-#if defined(ICE_USE_OPENSSL) || defined(ICE_USE_SCHANNEL)
//
-// This class is a wrapper around a native certificate extension.
-//
-// X509 extension wrapper is only implemented with OpenSSL and SChannel
-// other engines lacks the required APIs to implement this feature.
+// This class represents an X509 Certificate extension.
//
class ICESSL_API X509Extension
#ifndef ICE_CPP11_MAPPING
@@ -310,35 +201,21 @@ class ICESSL_API X509Extension
{
public:
- //
- // Construct a X509 extension using a native extension.
- //
- X509Extension(X509ExtensionRef, const std::string&, const CertificatePtr&);
- ~X509Extension();
-
- bool isCritical() const;
- std::string getOID() const;
- std::vector<Ice::Byte> getData() const;
-
-private:
-
- X509ExtensionRef _extension;
- std::string _oid;
- //
- // We want to keep the certificate that contains the extension alive
- // for the lifetime of the extension.
- //
- CertificatePtr _cert;
+ virtual bool isCritical() const = 0;
+ virtual std::string getOID() const = 0;
+ virtual std::vector<Ice::Byte> getData() const = 0;
};
ICE_DEFINE_PTR(X509ExtensionPtr, X509Extension);
-#endif
//
// This convenience class is a wrapper around a native certificate.
// The interface is inspired by java.security.cert.X509Certificate.
//
+
+class Certificate;
+ICE_DEFINE_PTR(CertificatePtr, Certificate);
+
class ICESSL_API Certificate :
- public IceUtil::Mutex,
#ifdef ICE_CPP11_MAPPING
public std::enable_shared_from_this<Certificate>
#else
@@ -348,133 +225,77 @@ class ICESSL_API Certificate :
public:
//
- // Construct a certificate using a native certificate.
- //
- // The Certificate class assumes ownership of the given native
- //
- // certificate.
- explicit Certificate(X509CertificateRef);
- ~Certificate();
-
- //
- // Load the certificate from a file. The certificate must use the
- // PEM encoding format. Raises CertificateReadException if the
- // file cannot be read.
- //
- static CertificatePtr load(const std::string&);
-
- //
- // Decode a certificate from a string that uses the PEM encoding
- // format. Raises CertificateEncodingException if an error
- // occurs.
- //
- static CertificatePtr decode(const std::string&);
-
- //
// Compare the certificates for equality using the
// native certificate comparison method.
//
- bool operator==(const Certificate&) const;
- bool operator!=(const Certificate&) const;
+ virtual bool operator==(const Certificate&) const = 0;
+ virtual bool operator!=(const Certificate&) const = 0;
//
// Authority key identifier
//
- std::vector<Ice::Byte> getAuthorityKeyIdentifier() const;
+ virtual std::vector<Ice::Byte> getAuthorityKeyIdentifier() const = 0;
//
// Subject key identifier
//
- std::vector<Ice::Byte> getSubjectKeyIdentifier() const;
-
- //
- // Get the certificate's public key.
- //
- PublicKeyPtr getPublicKey() const;
+ virtual std::vector<Ice::Byte> getSubjectKeyIdentifier() const = 0;
//
// Verify that this certificate was signed by the given certificate
// public key. Returns true if signed, false otherwise.
//
- bool verify(const CertificatePtr&) const;
-
-#ifdef ICE_USE_OPENSSL
- //
- // Verify that this certificate was signed by the given public
- // key. Returns true if signed, false otherwise.
- //
- // This method was deprecated for consistency with some SSL
- // engines that require a certificate and not just a public key to
- // verify the certificate signature.
- //
- ICE_DEPRECATED_API("verify(const PublicKeyPtr&) is deprecated, use verify(const CertificatePtr&) instead")
- bool verify(const PublicKeyPtr&) const;
-#endif
+ virtual bool verify(const CertificatePtr&) const = 0;
//
// Return a string encoding of the certificate in PEM format.
// Raises CertificateEncodingException if an error occurs.
//
- std::string encode() const;
-
-#if !defined(__APPLE__) || TARGET_OS_IPHONE == 0
+ virtual std::string encode() const = 0;
//
// Checks that the certificate is currently valid, that is, the current
// date falls between the validity period given in the certificate.
//
- bool checkValidity() const;
+ virtual bool checkValidity() const = 0;
//
// Checks that the certificate is valid at the given time.
//
-# ifdef ICE_CPP11_MAPPING
- bool checkValidity(const std::chrono::system_clock::time_point&) const;
-# else
- bool checkValidity(const IceUtil::Time&) const;
-# endif
+#ifdef ICE_CPP11_MAPPING
+ virtual bool checkValidity(const std::chrono::system_clock::time_point&) const = 0;
+#else
+ virtual bool checkValidity(const IceUtil::Time&) const = 0;
+#endif
//
// Get the not-after validity time.
//
-# ifdef ICE_CPP11_MAPPING
- std::chrono::system_clock::time_point getNotAfter() const;
-# else
- IceUtil::Time getNotAfter() const;
-# endif
+#ifdef ICE_CPP11_MAPPING
+ virtual std::chrono::system_clock::time_point getNotAfter() const = 0;
+#else
+ virtual IceUtil::Time getNotAfter() const = 0;
+#endif
//
// Get the not-before validity time.
//
-# ifdef ICE_CPP11_MAPPING
- std::chrono::system_clock::time_point getNotBefore() const;
-# else
- IceUtil::Time getNotBefore() const;
-# endif
-
+#ifdef ICE_CPP11_MAPPING
+ virtual std::chrono::system_clock::time_point getNotBefore() const = 0;
+#else
+ virtual IceUtil::Time getNotBefore() const = 0;
#endif
//
// Get the serial number. This is an arbitrarily large number.
//
- std::string getSerialNumber() const;
-
- //
- // Get the signature algorithm name used to sign the certificate.
- //
- //std::string getSigAlgName() const;
-
- //
- // Get the signature algorithm OID string from the certificate.
- //
- //std::string getSigAlgOID() const;
+ virtual std::string getSerialNumber() const = 0;
//
// Get the issuer's distinguished name (DN).
//
- DistinguishedName getIssuerDN() const;
+ virtual DistinguishedName getIssuerDN() const = 0;
-#if !defined(__APPLE__) || TARGET_OS_IPHONE == 0
//
// Get the values in the issuer's alternative names extension.
//
@@ -501,86 +322,54 @@ public:
// The remainder of the data will result in an empty string. Use the raw
// X509* certificate to obtain these values.
//
- std::vector<std::pair<int, std::string> > getIssuerAlternativeNames();
-#endif
+ virtual std::vector<std::pair<int, std::string> > getIssuerAlternativeNames() const = 0;
//
// Get the subject's distinguished name (DN).
//
- DistinguishedName getSubjectDN() const;
+ virtual DistinguishedName getSubjectDN() const = 0;
-#if !defined(__APPLE__) || TARGET_OS_IPHONE == 0
//
// See the comment for getIssuerAlternativeNames.
//
- std::vector<std::pair<int, std::string> > getSubjectAlternativeNames();
-#endif
+ virtual std::vector<std::pair<int, std::string> > getSubjectAlternativeNames() const = 0;
//
// Retrieve the certificate version number.
//
- int getVersion() const;
+ virtual int getVersion() const = 0;
//
// Stringify the certificate. This is a human readable version of
// the certificate, not a DER or PEM encoding.
//
- std::string toString() const;
+ virtual std::string toString() const = 0;
//
- // Retrieve the native X509 certificate value wrapped by this
- // object.
- //
- // The returned reference is only valid for the lifetime of this
- // object. With SecureTransport you can increment the reference
- // count of the returned object with CFRetain. With OpenSSL, you
- // can increment it with X509_dup. With SChannel, the returned
- // reference is a pointer to a struct.
- //
- X509CertificateRef getCert() const;
-
-#if defined(ICE_USE_OPENSSL) || defined(ICE_USE_SCHANNEL)
- //
// Return a list with the X509v3 extensions contained in the
// certificate.
//
- std::vector<X509ExtensionPtr> getX509Extensions() const;
+ virtual std::vector<X509ExtensionPtr> getX509Extensions() const = 0;
//
// Return the extension with the given OID or null if the certificate
// does not contain a extension with the given OID.
//
- X509ExtensionPtr getX509Extension(const std::string&) const;
-#endif
+ virtual X509ExtensionPtr getX509Extension(const std::string&) const = 0;
-private:
-
//
- // Lazzy initialization of the extensions
+ // Load the certificate from a file. The certificate must use the
+ // PEM encoding format. Raises CertificateReadException if the
+ // file cannot be read.
//
- void loadX509Extensions() const;
-
-#if defined(__APPLE__)
- IceInternal::UniqueRef<X509CertificateRef> _cert;
-#else
- X509CertificateRef _cert;
-#endif
-
-#ifdef ICE_USE_SCHANNEL
- CERT_INFO* _certInfo;
-#endif
-
-#if defined(__APPLE__) && TARGET_OS_IPHONE != 0
- void initializeAttributes() const;
- mutable IceInternal::UniqueRef<CFDataRef> _subject;
- mutable IceInternal::UniqueRef<CFDataRef> _issuer;
- mutable std::string _serial;
- mutable int _version;
-#endif
+ static CertificatePtr load(const std::string&);
-#if defined(ICE_USE_OPENSSL) || defined(ICE_USE_SCHANNEL)
- mutable std::vector<X509ExtensionPtr> _extensions;
-#endif
+ //
+ // Decode a certificate from a string that uses the PEM encoding
+ // format. Raises CertificateEncodingException if an error
+ // occurs.
+ //
+ static CertificatePtr decode(const std::string&);
};
//
@@ -654,7 +443,6 @@ public:
typedef IceUtil::Handle<PasswordPrompt> PasswordPromptPtr;
#endif
-
class ICESSL_API Plugin : public Ice::Plugin
{
public:
@@ -684,27 +472,19 @@ public:
virtual void setPasswordPrompt(const PasswordPromptPtr&) = 0;
#endif
-#ifdef ICE_USE_OPENSSL
- //
- // Establish the OpenSSL context. This must be done before the
- // plug-in is initialized, therefore the application must define
- // the property Ice.InitPlugins=0, set the context, and finally
- // invoke initializePlugins on the PluginManager.
- //
- // When the application supplies its own OpenSSL context, the
- // plug-in ignores configuration properties related to certificates,
- // keys, and passwords.
//
- // Note that the plugin assumes ownership of the given context.
+ // Load the certificate from a file. The certificate must use the
+ // PEM encoding format. Raises CertificateReadException if the
+ // file cannot be read.
//
- virtual void setContext(SSL_CTX*) = 0;
+ virtual CertificatePtr load(const std::string&) const = 0;
//
- // Obtain the SSL context. Use caution when modifying this value.
- // Changes made to this value have no effect on existing connections.
+ // Decode a certificate from a string that uses the PEM encoding
+ // format. Raises CertificateEncodingException if an error
+ // occurs.
//
- virtual SSL_CTX* getContext() = 0;
-#endif
+ virtual CertificatePtr decode(const std::string&) const = 0;
};
ICE_DEFINE_PTR(PluginPtr, Plugin);
diff --git a/cpp/include/IceSSL/SChannel.h b/cpp/include/IceSSL/SChannel.h
new file mode 100644
index 00000000000..9ff60700ea7
--- /dev/null
+++ b/cpp/include/IceSSL/SChannel.h
@@ -0,0 +1,66 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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 ICESSL_SCHANNEL_H
+#define ICESSL_SCHANNEL_H
+
+#include <IceSSL/Plugin.h>
+
+#include <wincrypt.h>
+
+namespace IceSSL
+{
+
+namespace SChannel
+{
+
+class Certificate;
+ICE_DEFINE_PTR(CertificatePtr, Certificate);
+
+class ICESSL_API Certificate : public virtual IceSSL::Certificate
+{
+public:
+
+ //
+ // Construct a certificate using a native certificate.
+ //
+ // The Certificate class assumes ownership of the given native
+ // certificate.
+ //
+ static CertificatePtr create(CERT_SIGNED_CONTENT_INFO*);
+
+ //
+ // Load the certificate from a file. The certificate must use the
+ // PEM encoding format. Raises CertificateReadException if the
+ // file cannot be read.
+ //
+ static CertificatePtr load(const std::string&);
+
+ //
+ // Decode a certificate from a string that uses the PEM encoding
+ // format. Raises CertificateEncodingException if an error
+ // occurs.
+ //
+ static CertificatePtr decode(const std::string&);
+
+ //
+ // Retrieve the native X509 certificate value wrapped by this
+ // object.
+ //
+ // The returned reference is only valid for the lifetime of this
+ // object. The returned reference is a pointer to a struct.
+ //
+ virtual CERT_SIGNED_CONTENT_INFO* getCert() const = 0;
+};
+
+} // SChannel namespace end
+
+} // IceSSL namespace end
+
+#endif
diff --git a/cpp/include/IceSSL/SecureTransport.h b/cpp/include/IceSSL/SecureTransport.h
new file mode 100644
index 00000000000..9be2d30868c
--- /dev/null
+++ b/cpp/include/IceSSL/SecureTransport.h
@@ -0,0 +1,66 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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 ICESSL_SECURE_TRANSPORT_H
+#define ICESSL_SECURE_TRANSPORT_H
+
+#include <IceSSL/Plugin.h>
+#include <Security/Security.h>
+
+namespace IceSSL
+{
+
+namespace SecureTransport
+{
+
+class Certificate;
+ICE_DEFINE_PTR(CertificatePtr, Certificate);
+
+class ICESSL_API Certificate : public virtual IceSSL::Certificate
+{
+public:
+
+ //
+ // Construct a certificate using a native certificate.
+ //
+ // The Certificate class assumes ownership of the given native
+ // certificate.
+ //
+ static CertificatePtr create(SecCertificateRef);
+
+ //
+ // Load the certificate from a file. The certificate must use the
+ // PEM encoding format. Raises CertificateReadException if the
+ // file cannot be read.
+ //
+ static CertificatePtr load(const std::string&);
+
+ //
+ // Decode a certificate from a string that uses the PEM encoding
+ // format. Raises CertificateEncodingException if an error
+ // occurs.
+ //
+ static CertificatePtr decode(const std::string&);
+
+ //
+ // Retrieve the native X509 certificate value wrapped by this
+ // object.
+ //
+ // The returned reference is only valid for the lifetime of this
+ // object. You can increment the reference count of the returned
+ // object with CFRetain.
+ //
+ virtual SecCertificateRef getCert() const = 0;
+};
+
+} // SecureTransport namespace end
+
+} // IceSSL namespace end
+
+#endif
diff --git a/cpp/include/IceSSL/UWP.h b/cpp/include/IceSSL/UWP.h
new file mode 100644
index 00000000000..e131ade6c5b
--- /dev/null
+++ b/cpp/include/IceSSL/UWP.h
@@ -0,0 +1,58 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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 ICESSL_UWP_H
+#define ICESSL_UWP_H
+
+#include <IceSSL/Plugin.h>
+
+namespace IceSSL
+{
+
+namespace UWP
+{
+
+class Certificate;
+ICE_DEFINE_PTR(CertificatePtr, Certificate);
+
+class ICESSL_API Certificate : public virtual IceSSL::Certificate
+{
+public:
+
+ //
+ // Construct a certificate using a native certificate.
+ //
+ static CertificatePtr create(Windows::Security::Cryptography::Certificates::Certificate^);
+
+ //
+ // Load the certificate from a file. The certificate must use the
+ // PEM encoding format. Raises CertificateReadException if the
+ // file cannot be read.
+ //
+ static CertificatePtr load(const std::string&);
+
+ //
+ // Decode a certificate from a string that uses the PEM encoding
+ // format. Raises CertificateEncodingException if an error
+ // occurs.
+ //
+ static CertificatePtr decode(const std::string&);
+
+ //
+ // Retrieve the native X509 certificate value wrapped by this
+ // object.
+ //
+ virtual Windows::Security::Cryptography::Certificates::Certificate^ getCert() const = 0;
+};
+
+} // UWP namespace end
+
+} // IceSSL namespace end
+
+#endif
diff --git a/cpp/include/IceUtil/PushDisableWarnings.h b/cpp/include/IceUtil/PushDisableWarnings.h
index 4dcff0ae560..7268eeea46a 100644
--- a/cpp/include/IceUtil/PushDisableWarnings.h
+++ b/cpp/include/IceUtil/PushDisableWarnings.h
@@ -17,7 +17,7 @@
# pragma warning(disable:4512) // ... assignment operator could not be generated
# if _MSC_VER >= 1900
-# pragma warning(disable:4275) // non dll-interface class ... used as base for dll-interface class ...
+# pragma warning(disable:4275) // non dll-interface class ... used as base for dll-interface class ...
# endif
#elif defined(__clang__)
diff --git a/cpp/msbuild/ice.nuget.targets b/cpp/msbuild/ice.nuget.targets
index 8b4bd2313df..c5be8216e01 100644
--- a/cpp/msbuild/ice.nuget.targets
+++ b/cpp/msbuild/ice.nuget.targets
@@ -7,10 +7,12 @@
<!-- Dynamic libraries and import libraries -->
<ItemGroup>
<Libraries Include="$(Ice_SrcRootDir)bin\$(Platform)\$(Configuration)\*.dll"
- Exclude="$(Ice_SrcRootDir)bin\$(Platform)\$(Configuration)\glacier2cryptpermissionsverifier*d.dll"/>
+ Exclude="$(Ice_SrcRootDir)bin\$(Platform)\$(Configuration)\glacier2cryptpermissionsverifier*d.dll;
+ $(Ice_SrcRootDir)bin\$(Platform)\$(Configuration)\icesslopenssl*.dll"/>
<ImportLibraries Include="$(Ice_SrcRootDir)lib\$(Platform)\$(Configuration)\*.lib"
- Exclude="$(Ice_SrcRootDir)lib\$(Platform)\$(Configuration)\glacier2cryptpermissionsverifier*;
+ Exclude="$(Ice_SrcRootDir)lib\$(Platform)\$(Configuration)\glacier2cryptpermissionsverifier*.lib;
+ $(Ice_SrcRootDir)lib\$(Platform)\$(Configuration)\icesslopenssl*.lib;
$(Ice_SrcRootDir)lib\$(Platform)\$(Configuration)\*uwp++11*.lib"/>
</ItemGroup>
diff --git a/cpp/msbuild/ice.openssl.test.sln b/cpp/msbuild/ice.openssl.test.sln
new file mode 100644
index 00000000000..fb0d6ecf5e6
--- /dev/null
+++ b/cpp/msbuild/ice.openssl.test.sln
@@ -0,0 +1,94 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26228.4
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{2D52604F-E2AD-4586-BBD7-BD13536C702C}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testcommon", "..\test\Common\msbuild\testcommon.vcxproj", "{C7223CC8-0AAA-470B-ACB3-12B9DE75525C}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "IceSSL", "IceSSL", "{8DC4FC60-61F2-4D58-8DB1-615460DEF993}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "configuration", "configuration", "{2557CF58-4848-4D0A-8D42-E0F7C7158A6B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "clientopenssl", "..\test\IceSSL\configuration\msbuild\clientopenssl\clientopenssl.vcxproj", "{34135D29-7ABF-416E-80A9-4077BD6A126F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C} = {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "serveropenssl", "..\test\IceSSL\configuration\msbuild\serveropenssl\serveropenssl.vcxproj", "{1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}"
+ ProjectSection(ProjectDependencies) = postProject
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C} = {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Cpp11-Debug|Win32 = Cpp11-Debug|Win32
+ Cpp11-Debug|x64 = Cpp11-Debug|x64
+ Cpp11-Release|Win32 = Cpp11-Release|Win32
+ Cpp11-Release|x64 = Cpp11-Release|x64
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}.Cpp11-Debug|Win32.ActiveCfg = Cpp11-Debug|Win32
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}.Cpp11-Debug|Win32.Build.0 = Cpp11-Debug|Win32
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}.Cpp11-Debug|x64.ActiveCfg = Cpp11-Debug|x64
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}.Cpp11-Debug|x64.Build.0 = Cpp11-Debug|x64
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}.Cpp11-Release|Win32.ActiveCfg = Cpp11-Release|Win32
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}.Cpp11-Release|Win32.Build.0 = Cpp11-Release|Win32
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}.Cpp11-Release|x64.ActiveCfg = Cpp11-Release|x64
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}.Cpp11-Release|x64.Build.0 = Cpp11-Release|x64
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}.Debug|Win32.Build.0 = Debug|Win32
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}.Debug|x64.ActiveCfg = Debug|x64
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}.Debug|x64.Build.0 = Debug|x64
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}.Release|Win32.ActiveCfg = Release|Win32
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}.Release|Win32.Build.0 = Release|Win32
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}.Release|x64.ActiveCfg = Release|x64
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C}.Release|x64.Build.0 = Release|x64
+ {34135D29-7ABF-416E-80A9-4077BD6A126F}.Cpp11-Debug|Win32.ActiveCfg = Cpp11-Debug|Win32
+ {34135D29-7ABF-416E-80A9-4077BD6A126F}.Cpp11-Debug|Win32.Build.0 = Cpp11-Debug|Win32
+ {34135D29-7ABF-416E-80A9-4077BD6A126F}.Cpp11-Debug|x64.ActiveCfg = Cpp11-Debug|x64
+ {34135D29-7ABF-416E-80A9-4077BD6A126F}.Cpp11-Debug|x64.Build.0 = Cpp11-Debug|x64
+ {34135D29-7ABF-416E-80A9-4077BD6A126F}.Cpp11-Release|Win32.ActiveCfg = Cpp11-Release|Win32
+ {34135D29-7ABF-416E-80A9-4077BD6A126F}.Cpp11-Release|Win32.Build.0 = Cpp11-Release|Win32
+ {34135D29-7ABF-416E-80A9-4077BD6A126F}.Cpp11-Release|x64.ActiveCfg = Cpp11-Release|x64
+ {34135D29-7ABF-416E-80A9-4077BD6A126F}.Cpp11-Release|x64.Build.0 = Cpp11-Release|x64
+ {34135D29-7ABF-416E-80A9-4077BD6A126F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {34135D29-7ABF-416E-80A9-4077BD6A126F}.Debug|Win32.Build.0 = Debug|Win32
+ {34135D29-7ABF-416E-80A9-4077BD6A126F}.Debug|x64.ActiveCfg = Debug|x64
+ {34135D29-7ABF-416E-80A9-4077BD6A126F}.Debug|x64.Build.0 = Debug|x64
+ {34135D29-7ABF-416E-80A9-4077BD6A126F}.Release|Win32.ActiveCfg = Release|Win32
+ {34135D29-7ABF-416E-80A9-4077BD6A126F}.Release|Win32.Build.0 = Release|Win32
+ {34135D29-7ABF-416E-80A9-4077BD6A126F}.Release|x64.ActiveCfg = Release|x64
+ {34135D29-7ABF-416E-80A9-4077BD6A126F}.Release|x64.Build.0 = Release|x64
+ {1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}.Cpp11-Debug|Win32.ActiveCfg = Cpp11-Debug|Win32
+ {1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}.Cpp11-Debug|Win32.Build.0 = Cpp11-Debug|Win32
+ {1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}.Cpp11-Debug|x64.ActiveCfg = Cpp11-Debug|x64
+ {1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}.Cpp11-Debug|x64.Build.0 = Cpp11-Debug|x64
+ {1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}.Cpp11-Release|Win32.ActiveCfg = Cpp11-Release|Win32
+ {1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}.Cpp11-Release|Win32.Build.0 = Cpp11-Release|Win32
+ {1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}.Cpp11-Release|x64.ActiveCfg = Cpp11-Release|x64
+ {1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}.Cpp11-Release|x64.Build.0 = Cpp11-Release|x64
+ {1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}.Debug|Win32.ActiveCfg = Debug|Win32
+ {1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}.Debug|Win32.Build.0 = Debug|Win32
+ {1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}.Debug|x64.ActiveCfg = Debug|x64
+ {1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}.Debug|x64.Build.0 = Debug|x64
+ {1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}.Release|Win32.ActiveCfg = Release|Win32
+ {1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}.Release|Win32.Build.0 = Release|Win32
+ {1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}.Release|x64.ActiveCfg = Release|x64
+ {1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {C7223CC8-0AAA-470B-ACB3-12B9DE75525C} = {2D52604F-E2AD-4586-BBD7-BD13536C702C}
+ {2557CF58-4848-4D0A-8D42-E0F7C7158A6B} = {8DC4FC60-61F2-4D58-8DB1-615460DEF993}
+ {34135D29-7ABF-416E-80A9-4077BD6A126F} = {2557CF58-4848-4D0A-8D42-E0F7C7158A6B}
+ {1A83DE5F-3401-4D5D-B9FE-A930D5B15F39} = {2557CF58-4848-4D0A-8D42-E0F7C7158A6B}
+ EndGlobalSection
+EndGlobal
diff --git a/cpp/msbuild/ice.proj b/cpp/msbuild/ice.proj
index be78891034b..c859244c94a 100644
--- a/cpp/msbuild/ice.proj
+++ b/cpp/msbuild/ice.proj
@@ -28,6 +28,7 @@
<Target Name="TestNugetRestore" DependsOnTargets="GetNuget" Condition="'$(ICE_BIN_DIST)' == 'all'">
<Exec Command="$(NugetExe) restore $(MSBuildThisFileDirectory)ice.test.sln"/>
+ <Exec Command="$(NugetExe) restore $(MSBuildThisFileDirectory)ice.openssl.test.sln"/>
</Target>
<Target Name="UWPTestNugetRestore" DependsOnTargets="GetNuget" Condition="'$(ICE_BIN_DIST)' == 'all'">
@@ -68,7 +69,6 @@
<UWPDistSolution Include="ice.uwp.sln">
<Properties>Configuration=Debug;Platform=x64</Properties>
</UWPDistSolution>
-
<UWPDistSolution Include="ice.uwp.sln">
<Properties>Configuration=Release;Platform=Win32</Properties>
</UWPDistSolution>
@@ -109,6 +109,38 @@
</TestSolution>
</ItemGroup>
+ <!-- OpenSSL C++ test configurations (C++98 mapping) -->
+ <ItemGroup Condition="'$(ICE_BIN_DIST)' != 'all' and '$(DefaultPlatformToolset)' == 'v140'">
+ <TestSolution Include="ice.openssl.test.sln">
+ <Properties>Configuration=Debug;Platform=Win32</Properties>
+ </TestSolution>
+ <TestSolution Include="ice.openssl.test.sln">
+ <Properties>Configuration=Debug;Platform=x64</Properties>
+ </TestSolution>
+ <TestSolution Include="ice.openssl.test.sln">
+ <Properties>Configuration=Release;Platform=Win32</Properties>
+ </TestSolution>
+ <TestSolution Include="ice.openssl.test.sln">
+ <Properties>Configuration=Release;Platform=x64</Properties>
+ </TestSolution>
+ </ItemGroup>
+
+ <!-- OpenSSL C++ test configurations (C++11 mapping) -->
+ <ItemGroup Condition="'$(ICE_BIN_DIST)' != 'all' and '$(DefaultPlatformToolset)' == 'v140'">
+ <TestSolution Include="ice.openssl.test.sln">
+ <Properties>Configuration=Cpp11-Debug;Platform=Win32</Properties>
+ </TestSolution>
+ <TestSolution Include="ice.openssl.test.sln">
+ <Properties>Configuration=Cpp11-Debug;Platform=x64</Properties>
+ </TestSolution>
+ <TestSolution Include="ice.openssl.test.sln">
+ <Properties>Configuration=Cpp11-Release;Platform=Win32</Properties>
+ </TestSolution>
+ <TestSolution Include="ice.openssl.test.sln">
+ <Properties>Configuration=Cpp11-Release;Platform=x64</Properties>
+ </TestSolution>
+ </ItemGroup>
+
<!-- Ice for UWP test configurations -->
<ItemGroup>
<UWPTestSolution Include="ice.testuwp.sln">
@@ -144,6 +176,17 @@
</TestSolution>
</ItemGroup>
+ <!-- OpenSSL test builds -->
+ <ItemGroup Condition="'$(ICE_BIN_DIST)' != 'all' and '$(DefaultPlatformToolset)' == 'v140'">
+ <OpenSSLTestSolution Include="ice.openssl.test.sln">
+ <Properties>Configuration=$(Configuration);Platform=$(Platform)</Properties>
+ </OpenSSLTestSolution>
+
+ <OpenSSLTestSolution Include="ice.openssl.test.sln">
+ <Properties>Configuration=Cpp11-$(Configuration);Platform=$(Platform)</Properties>
+ </OpenSSLTestSolution>
+ </ItemGroup>
+
<ItemGroup Condition="'$(UWPCompiler)' == 'yes'">
<UWPDistSolution Include="ice.uwp.sln">
<Properties>Configuration=$(Configuration);Platform=$(Platform)</Properties>
@@ -179,11 +222,22 @@
<MSBuild Projects="@(TestSolution)"
BuildInParallel="true"
Properties="%(Properties)" />
+
+ <!-- Build OpenSSL tests only with v140 source distribution builds -->
+ <MSBuild Projects="@(OpenSSLTestSolution)"
+ BuildInParallel="true"
+ Properties="%(Properties)"
+ Condition="'$(ICE_BIN_DIST)' != 'all' and '$(DefaultPlatformToolset)' == 'v140'" />
</Target>
<!-- Clean test solution -->
<Target Name="Clean" DependsOnTargets="CleanDist">
<MSBuild Projects="@(TestSolution)" BuildInParallel="true" Targets="Clean" Properties="%(Properties)" />
+ <MSBuild Projects="@(OpenSSLTestSolution)"
+ BuildInParallel="true"
+ Targets="Clean"
+ Properties="%(Properties)"
+ Condition="'$(ICE_BIN_DIST)' != 'all' and '$(DefaultPlatformToolset)' == 'v140'" />
</Target>
<!-- Create nuget packages -->
diff --git a/cpp/msbuild/ice.v140.sln b/cpp/msbuild/ice.v140.sln
index 66c558d4fad..827303b965b 100644
--- a/cpp/msbuild/ice.v140.sln
+++ b/cpp/msbuild/ice.v140.sln
@@ -267,6 +267,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "icebridge", "..\src\IceBrid
{6485EC94-6B47-428D-B42D-AAA11F08DB59} = {6485EC94-6B47-428D-B42D-AAA11F08DB59}
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "icesslopenssl", "..\src\IceSSL\msbuild\icesslopenssl\icesslopenssl.vcxproj", "{0D08F6B8-39C0-413B-84CE-D73230BCC740}"
+ ProjectSection(ProjectDependencies) = postProject
+ {72FA68A9-49B6-4AB6-94AE-34BB03770A51} = {72FA68A9-49B6-4AB6-94AE-34BB03770A51}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "icesslopenssl++11", "..\src\IceSSL\msbuild\icesslopenssl++11\icesslopenssl++11.vcxproj", "{D0DC2305-37FE-4D03-BE05-AC8912678DC8}"
+ ProjectSection(ProjectDependencies) = postProject
+ {5923B17D-2873-4245-87A7-FB8F4BE12501} = {5923B17D-2873-4245-87A7-FB8F4BE12501}
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -635,6 +645,22 @@ Global
{1D6E8807-7C28-421F-B49E-BCB482FCB21D}.Release|Win32.Build.0 = Release|Win32
{1D6E8807-7C28-421F-B49E-BCB482FCB21D}.Release|x64.ActiveCfg = Release|x64
{1D6E8807-7C28-421F-B49E-BCB482FCB21D}.Release|x64.Build.0 = Release|x64
+ {0D08F6B8-39C0-413B-84CE-D73230BCC740}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0D08F6B8-39C0-413B-84CE-D73230BCC740}.Debug|Win32.Build.0 = Debug|Win32
+ {0D08F6B8-39C0-413B-84CE-D73230BCC740}.Debug|x64.ActiveCfg = Debug|x64
+ {0D08F6B8-39C0-413B-84CE-D73230BCC740}.Debug|x64.Build.0 = Debug|x64
+ {0D08F6B8-39C0-413B-84CE-D73230BCC740}.Release|Win32.ActiveCfg = Release|Win32
+ {0D08F6B8-39C0-413B-84CE-D73230BCC740}.Release|Win32.Build.0 = Release|Win32
+ {0D08F6B8-39C0-413B-84CE-D73230BCC740}.Release|x64.ActiveCfg = Release|x64
+ {0D08F6B8-39C0-413B-84CE-D73230BCC740}.Release|x64.Build.0 = Release|x64
+ {D0DC2305-37FE-4D03-BE05-AC8912678DC8}.Debug|Win32.ActiveCfg = Debug|Win32
+ {D0DC2305-37FE-4D03-BE05-AC8912678DC8}.Debug|Win32.Build.0 = Debug|Win32
+ {D0DC2305-37FE-4D03-BE05-AC8912678DC8}.Debug|x64.ActiveCfg = Debug|x64
+ {D0DC2305-37FE-4D03-BE05-AC8912678DC8}.Debug|x64.Build.0 = Debug|x64
+ {D0DC2305-37FE-4D03-BE05-AC8912678DC8}.Release|Win32.ActiveCfg = Release|Win32
+ {D0DC2305-37FE-4D03-BE05-AC8912678DC8}.Release|Win32.Build.0 = Release|Win32
+ {D0DC2305-37FE-4D03-BE05-AC8912678DC8}.Release|x64.ActiveCfg = Release|x64
+ {D0DC2305-37FE-4D03-BE05-AC8912678DC8}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -685,5 +711,7 @@ Global
{541CF1D6-95FD-4499-AB02-75CCCEE660B0} = {2DC2B270-B7AE-48CF-8FB0-41A55A9747E9}
{369524F4-D374-44F4-BCFD-408934595701} = {2DC2B270-B7AE-48CF-8FB0-41A55A9747E9}
{1D6E8807-7C28-421F-B49E-BCB482FCB21D} = {2DC2B270-B7AE-48CF-8FB0-41A55A9747E9}
+ {0D08F6B8-39C0-413B-84CE-D73230BCC740} = {2DC2B270-B7AE-48CF-8FB0-41A55A9747E9}
+ {D0DC2305-37FE-4D03-BE05-AC8912678DC8} = {F48CC091-6F26-4EC8-A2FB-485975E7C908}
EndGlobalSection
EndGlobal
diff --git a/cpp/src/IceSSL/AcceptorI.cpp b/cpp/src/IceSSL/AcceptorI.cpp
index 3e262519590..ccb8b65a143 100644
--- a/cpp/src/IceSSL/AcceptorI.cpp
+++ b/cpp/src/IceSSL/AcceptorI.cpp
@@ -10,12 +10,7 @@
#include <IceSSL/AcceptorI.h>
#include <IceSSL/EndpointI.h>
#include <IceSSL/Instance.h>
-
-
-#include <IceSSL/OpenSSLTransceiverI.h>
-#include <IceSSL/SecureTransportTransceiverI.h>
-#include <IceSSL/SChannelTransceiverI.h>
-#include <IceSSL/UWPTransceiverI.h>
+#include <IceSSL/SSLEngine.h>
#include <IceSSL/Util.h>
@@ -83,7 +78,7 @@ IceSSL::AcceptorI::accept()
throw ex;
}
- return new TransceiverI(_instance, _delegate->accept(), _adapterName, true);
+ return _instance->engine()->createTransceiver(_instance, _delegate->accept(), _adapterName, true);
}
string
diff --git a/cpp/src/IceSSL/AcceptorI.h b/cpp/src/IceSSL/AcceptorI.h
index 0e068324201..9e29b9bdf5f 100644
--- a/cpp/src/IceSSL/AcceptorI.h
+++ b/cpp/src/IceSSL/AcceptorI.h
@@ -54,4 +54,4 @@ private:
}
-#endif
+#endif // IceSSL namespace end
diff --git a/cpp/src/IceSSL/Certificate.cpp b/cpp/src/IceSSL/Certificate.cpp
deleted file mode 100755
index a5808186d97..00000000000
--- a/cpp/src/IceSSL/Certificate.cpp
+++ /dev/null
@@ -1,2076 +0,0 @@
-// **********************************************************************
-//
-// Copyright (c) 2003-2017 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 <IceUtil/DisableWarnings.h>
-#include <IceUtil/Mutex.h>
-#include <IceUtil/MutexPtrLock.h>
-#include <IceUtil/StringUtil.h>
-#include <IceSSL/Plugin.h>
-#include <IceSSL/Util.h>
-#include <IceSSL/RFC2253.h>
-#include <Ice/Object.h>
-#include <Ice/Base64.h>
-#include <Ice/StringConverter.h>
-#include <IceUtil/Time.h>
-
-#if defined(ICE_USE_OPENSSL)
-# include <openssl/x509v3.h>
-# include <openssl/pem.h>
-//
-// Avoid old style cast warnings from OpenSSL macros
-//
-# pragma GCC diagnostic ignored "-Wold-style-cast"
-#elif defined(ICE_USE_SECURE_TRANSPORT)
-# include <Security/Security.h>
-#elif defined(ICE_OS_UWP)
-# include <ppltasks.h>
-# include <nserror.h>
-#endif
-
-#ifdef __SUNPRO_CC
-
-//
-// The call to sk_GENERAL_NAME_pop_free fails to compile if we don't
-// remove the extern "C" vs non extern "C" check with the macro below:
-//
-
-extern "C" typedef void (*FreeFunc)(void*);
-
-#undef CHECKED_SK_FREE_FUNC
-#define CHECKED_SK_FREE_FUNC(type, p) \
- (FreeFunc) (p)
-
-#endif
-
-using namespace std;
-using namespace Ice;
-using namespace IceInternal;
-using namespace IceSSL;
-
-#ifdef ICE_OS_UWP
-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)
-
-//
-// Map a certificate OID to its alias
-//
-struct CertificateOID
-{
- const char* name;
- const char* alias;
-};
-
-const CertificateOID certificateOIDS[] =
-{
- {"2.5.4.3", "CN"},
- {"2.5.4.4", "SN"},
- {"2.5.4.5", "DeviceSerialNumber"},
- {"2.5.4.6", "C"},
- {"2.5.4.7", "L"},
- {"2.5.4.8", "ST"},
- {"2.5.4.9", "STREET"},
- {"2.5.4.10", "O"},
- {"2.5.4.11", "OU"},
- {"2.5.4.12", "T"},
- {"2.5.4.42", "G"},
- {"2.5.4.43", "I"},
- {"1.2.840.113549.1.9.8", "unstructuredAddress"},
- {"1.2.840.113549.1.9.2", "unstructuredName"},
- {"1.2.840.113549.1.9.1", "emailAddress"},
- {"0.9.2342.19200300.100.1.25", "DC"}
-};
-const int certificateOIDSSize = sizeof(certificateOIDS) / sizeof(CertificateOID);
-
-#endif
-
-#if defined(ICE_USE_SECURE_TRANSPORT)
-
-string
-certificateOIDAlias(const string& name)
-{
- for(int i = 0; i < certificateOIDSSize; ++i)
- {
- const CertificateOID* certificateOID = &certificateOIDS[i];
- assert(certificateOID);
- if(name == certificateOID->name)
- {
- return certificateOID->alias;
- }
- }
- return name;
-}
-
-string
-escapeX509Name(const string& name)
-{
- ostringstream os;
- for(string::const_iterator i = name.begin(); i != name.end(); ++i)
- {
- switch(*i)
- {
- case ',':
- case '=':
- case '+':
- case '<':
- case '>':
- case '#':
- case ';':
- {
- os << '\\';
- }
- default:
- {
- break;
- }
- }
- os << *i;
- }
- 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)
-{
- assert(key == kSecOIDX509V1IssuerName || key == kSecOIDX509V1SubjectName);
- list<pair<string, string> > rdnPairs;
- UniqueRef<CFDictionaryRef> property(getCertificateProperty(cert, key));
- if(property)
- {
- CFArrayRef dn = static_cast<CFArrayRef>(CFDictionaryGetValue(property.get(), kSecPropertyKeyValue));
- int size = CFArrayGetCount(dn);
- for(int i = 0; i < size; ++i)
- {
- CFDictionaryRef dict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(dn, i));
- rdnPairs.push_front(make_pair(
- certificateOIDAlias(
- fromCFString((static_cast<CFStringRef>(CFDictionaryGetValue(dict, kSecPropertyKeyLabel))))),
- escapeX509Name(
- fromCFString(static_cast<CFStringRef>(CFDictionaryGetValue(dict, kSecPropertyKeyValue))))));
- }
- }
- return DistinguishedName(rdnPairs);
-}
-
-vector<pair<int, string> >
-getX509AltName(SecCertificateRef cert, CFTypeRef key)
-{
- assert(key == kSecOIDIssuerAltName || key == kSecOIDSubjectAltName);
- UniqueRef<CFDictionaryRef> property(getCertificateProperty(cert, key));
-
- vector<pair<int, string> > pairs;
- if(property)
- {
- CFArrayRef names = static_cast<CFArrayRef>(CFDictionaryGetValue(property.get(), kSecPropertyKeyValue));
- int size = CFArrayGetCount(names);
-
- for(int i = 0; i < size; ++i)
- {
- CFDictionaryRef dict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(names, i));
-
- int type = certificateAlternativeNameType(
- fromCFString(static_cast<CFStringRef>(CFDictionaryGetValue(dict, kSecPropertyKeyLabel))));
- if(type != -1)
- {
- CFStringRef v = static_cast<CFStringRef>(CFDictionaryGetValue(dict, kSecPropertyKeyValue));
- CFStringRef t = static_cast<CFStringRef>(CFDictionaryGetValue(dict, kSecPropertyKeyType));
- if(CFEqual(t, kSecPropertyTypeString) || CFEqual(t, kSecPropertyTypeTitle))
- {
- pairs.push_back(make_pair(type, fromCFString(v)));
- }
- else if(CFEqual(t, kSecPropertyTypeURL))
- {
- pairs.push_back(make_pair(type, fromCFString(CFURLGetString((CFURLRef)v))));
- }
- else if(CFEqual(t, kSecPropertyTypeSection))
- {
- CFArrayRef section = (CFArrayRef)v;
- ostringstream os;
- for(int i = 0, count = CFArrayGetCount(section); i < count;)
- {
- CFDictionaryRef d = (CFDictionaryRef)CFArrayGetValueAtIndex(section, i);
-
- CFStringRef sectionLabel = static_cast<CFStringRef>(CFDictionaryGetValue(d, kSecPropertyKeyLabel));
- CFStringRef sectionValue = static_cast<CFStringRef>(CFDictionaryGetValue(d, kSecPropertyKeyValue));
-
- os << certificateOIDAlias(fromCFString(sectionLabel)) << "=" << fromCFString(sectionValue);
- if(++i < count)
- {
- os << ",";
- }
- }
- pairs.push_back(make_pair(type, os.str()));
- }
- }
- }
- }
- return pairs;
-}
-
-#ifdef ICE_CPP11_MAPPING
-chrono::system_clock::time_point
-#else
-IceUtil::Time
-#endif
-getX509Date(SecCertificateRef cert, CFTypeRef key)
-{
- assert(key == kSecOIDX509V1ValidityNotAfter || key == kSecOIDX509V1ValidityNotBefore);
- UniqueRef<CFDictionaryRef> property(getCertificateProperty(cert, key));
- CFAbsoluteTime seconds = 0;
- if(property)
- {
- CFNumberRef date = static_cast<CFNumberRef>(CFDictionaryGetValue(property.get(), kSecPropertyKeyValue));
- CFNumberGetValue(date, kCFNumberDoubleType, &seconds);
- }
-
- IceUtil::Time time = IceUtil::Time::secondsDouble(kCFAbsoluteTimeIntervalSince1970 + seconds);
-
-#ifdef ICE_CPP11_MAPPING
- return chrono::system_clock::time_point(chrono::microseconds(time.toMicroSeconds()));
-#else
- return time;
-#endif
-}
-
-string
-getX509String(SecCertificateRef cert, CFTypeRef key)
-{
- assert(key == kSecOIDX509V1SerialNumber || key == kSecOIDX509V1Version);
- UniqueRef<CFDictionaryRef> property(getCertificateProperty(cert, key));
- return property ?
- fromCFString(static_cast<CFStringRef>(CFDictionaryGetValue(property.get(), kSecPropertyKeyValue))) : "";
-}
-
-#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_UWP)
-
-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)
-{
- DWORD outLength = length;
- vector<BYTE> outBuffer;
- outBuffer.resize(outLength);
-
- if(!CryptStringToBinary(buffer, length, CRYPT_STRING_BASE64HEADER, &outBuffer[0], &outLength, 0, 0))
- {
- //
- // Base64 data should always be bigger than binary
- //
- assert(GetLastError() != ERROR_MORE_DATA);
- throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
- }
-
- DWORD decodedLeng = 0;
- if(!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_CERT, &outBuffer[0], outLength, CRYPT_DECODE_ALLOC_FLAG, 0,
- cert, &decodedLeng))
- {
- throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
- }
-}
-
-void
-loadCertificate(PCERT_SIGNED_CONTENT_INFO* cert, const string& file)
-{
- vector<char> buffer;
- readFile(file, buffer);
- if(buffer.empty())
- {
- throw CertificateReadException(__FILE__, __LINE__, "certificate file " + file + " is empty");
- }
- loadCertificate(cert, &buffer[0], static_cast<DWORD>(buffer.size()));
-}
-
-#ifdef ICE_CPP11_MAPPING
-chrono::system_clock::time_point
-#else
-IceUtil::Time
-#endif
-filetimeToTime(FILETIME ftime)
-{
- Ice::Long value = 0;
- DWORD* dest = reinterpret_cast<DWORD*>(&value);
- *dest++ = ftime.dwLowDateTime;
- *dest = ftime.dwHighDateTime;
-
- IceUtil::Time time = IceUtil::Time::milliSeconds((value / TICKS_PER_MSECOND) - MSECS_TO_EPOCH);
-
-#ifdef ICE_CPP11_MAPPING
- return chrono::system_clock::time_point(chrono::microseconds(time.toMicroSeconds()));
-#else
- return time;
-#endif
-
-}
-
-string
-certNameToString(CERT_NAME_BLOB* name)
-{
- assert(name);
- DWORD length = 0;
- if(!(length = CertNameToStr(X509_ASN_ENCODING, name, CERT_OID_NAME_STR|CERT_NAME_STR_REVERSE_FLAG, 0, 0)))
- {
- throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
- }
-
- vector<char> buffer(length);
- if(!CertNameToStr(X509_ASN_ENCODING, name, CERT_OID_NAME_STR|CERT_NAME_STR_REVERSE_FLAG, &buffer[0], length))
- {
- throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
- }
-
- string s(&buffer[0]);
- for(int i = 0; i < certificateOIDSSize; ++i)
- {
- const CertificateOID* certificateOID = &certificateOIDS[i];
- assert(certificateOID);
- const string name = string(certificateOID->name) + "=";
- const string alias = string(certificateOID->alias) + "=";
- size_t pos = 0;
- while((pos = s.find(name, pos)) != string::npos)
- {
- s.replace(pos, name.size(), alias);
- }
- }
- return s;
-}
-
-vector<pair<int, string> >
-certificateAltNames(CERT_INFO* certInfo, LPCSTR altNameOID)
-{
- vector<pair<int, string> > altNames;
-
- PCERT_EXTENSION extension = CertFindExtension(altNameOID, certInfo->cExtension, certInfo->rgExtension);
- if(extension)
- {
- CERT_ALT_NAME_INFO* altName;
- DWORD length = 0;
- if(!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_ALTERNATE_NAME, extension->Value.pbData,
- extension->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, 0, &altName, &length))
- {
- throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
- }
-
- for(DWORD i = 0; i < altName->cAltEntry; ++i)
- {
- CERT_ALT_NAME_ENTRY* entry = &altName->rgAltEntry[i];
-
- switch(entry->dwAltNameChoice)
- {
- case CERT_ALT_NAME_RFC822_NAME:
- {
- altNames.push_back(make_pair(AltNameEmail, wstringToString(entry->pwszRfc822Name)));
- break;
- }
- case CERT_ALT_NAME_DNS_NAME:
- {
- altNames.push_back(make_pair(AltNameDNS, wstringToString(entry->pwszDNSName)));
- break;
- }
- case CERT_ALT_NAME_DIRECTORY_NAME:
- {
- altNames.push_back(make_pair(AltNameDirectory, certNameToString(&entry->DirectoryName)));
- break;
- }
- case CERT_ALT_NAME_URL:
- {
- altNames.push_back(make_pair(AltNameURL, wstringToString(entry->pwszURL)));
- break;
- }
- case CERT_ALT_NAME_IP_ADDRESS:
- {
- if(entry->IPAddress.cbData == 4)
- {
- //
- // IPv4 address
- //
- ostringstream os;
- Byte* src = reinterpret_cast<Byte*>(entry->IPAddress.pbData);
- for(int j = 0; j < 4;)
- {
- int value = 0;
- Byte* dest = reinterpret_cast<Byte*>(&value);
- *dest = *src++;
- os << value;
- if(++j < 4)
- {
- os << ".";
- }
- }
- altNames.push_back(make_pair(AltNAmeIP, os.str()));
- }
- //
- // TODO IPv6 Address support.
- //
- break;
- }
- default:
- {
- // Not supported
- break;
- }
- }
- }
- LocalFree(altName);
- }
- return altNames;
-}
-#else
-
-vector<pair<int, string> >
-certificateAltNames(Windows::Security::Cryptography::Certificates::SubjectAlternativeNameInfo^ subAltNames)
-{
- vector<pair<int, string> > altNames;
- if(subAltNames)
- {
- 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())
- {
- altNames.push_back(make_pair(AltNameDNS, wstringToString(iter->Current->Data())));
- }
- 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())
- {
- altNames.push_back(make_pair(AltNAmeIP, wstringToString(iter->Current->Data())));
- }
- }
- return altNames;
-}
-#endif
-
-#endif
-
-CertificateReadException::CertificateReadException(const char* file, int line, const string& r) :
- ExceptionHelper<CertificateReadException>(file, line),
- reason(r)
-{
-}
-
-#ifndef ICE_CPP11_COMPILER
-CertificateReadException::~CertificateReadException() throw()
-{
-}
-#endif
-
-string
-CertificateReadException::ice_id() const
-{
- return "::IceSSL::CertificateReadException";
-}
-
-#ifndef ICE_CPP11_MAPPING
-CertificateReadException*
-CertificateReadException::ice_clone() const
-{
- return new CertificateReadException(*this);
-}
-#endif
-
-#ifdef ICE_USE_SECURE_TRANSPORT
-CertificateEncodingException::CertificateEncodingException(const char* file, int line, CFErrorRef err) :
- ExceptionHelper<CertificateEncodingException>(file, line)
-{
- assert(err);
- reason = "certificate error:\n" + errorToString(err);
-}
-#endif
-
-CertificateEncodingException::CertificateEncodingException(const char* file, int line, const string& r) :
- ExceptionHelper<CertificateEncodingException>(file, line),
- reason(r)
-{
-}
-
-#ifndef ICE_CPP11_COMPILER
-CertificateEncodingException::~CertificateEncodingException() throw()
-{
-}
-#endif
-
-string
-CertificateEncodingException::ice_id() const
-{
- return "::IceSSL::CertificateEncodingException";
-}
-
-#ifndef ICE_CPP11_MAPPING
-CertificateEncodingException*
-CertificateEncodingException::ice_clone() const
-{
- return new CertificateEncodingException(*this);
-}
-#endif
-
-#ifdef ICE_USE_OPENSSL
-
-namespace
-{
-
-IceUtil::Mutex* mut = 0;
-
-class Init
-{
-public:
-
- Init()
- {
- mut = new IceUtil::Mutex;
- }
-
- ~Init()
- {
- delete mut;
- mut = 0;
- }
-};
-
-Init init;
-
-}
-
-#ifdef ICE_CPP11_MAPPING
-chrono::system_clock::time_point
-#else
-static IceUtil::Time
-#endif
-ASMUtcTimeToTime(const ASN1_UTCTIME* s)
-{
- struct tm tm;
- int offset;
-
- memset(&tm, '\0', sizeof tm);
-
-# define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
- tm.tm_year = g2(s->data);
- if(tm.tm_year < 50)
- tm.tm_year += 100;
- tm.tm_mon = g2(s->data + 2) - 1;
- tm.tm_mday = g2(s->data + 4);
- tm.tm_hour = g2(s->data + 6);
- tm.tm_min = g2(s->data + 8);
- tm.tm_sec = g2(s->data + 10);
- if(s->data[12] == 'Z')
- {
- offset = 0;
- }
- else
- {
- offset = g2(s->data + 13) * 60 + g2(s->data + 15);
- if(s->data[12] == '-')
- {
- offset = -offset;
- }
- }
-# undef g2
-
- //
- // If timegm was on all systems this code could be
- // return IceUtil::Time::seconds(timegm(&tm) - offset*60);
- //
- // Windows doesn't support the re-entrant _r versions.
- //
- time_t tzone;
- {
- IceUtilInternal::MutexPtrLock<IceUtil::Mutex> sync(mut);
- time_t now = time(0);
- tzone = mktime(localtime(&now)) - mktime(gmtime(&now));
- }
-
- IceUtil::Time time = IceUtil::Time::seconds(mktime(&tm) - offset * 60 + tzone);
-
-#ifdef ICE_CPP11_MAPPING
- return chrono::system_clock::time_point(chrono::microseconds(time.toMicroSeconds()));
-#else
- return time;
-#endif
-}
-
-static string
-convertX509NameToString(X509_NAME* name)
-{
- BIO* out = BIO_new(BIO_s_mem());
- X509_NAME_print_ex(out, name, 0, XN_FLAG_RFC2253);
- BUF_MEM* p;
- BIO_get_mem_ptr(out, &p);
- string result = string(p->data, p->length);
- BIO_free(out);
- return result;
-}
-
-static vector<pair<int, string> >
-convertGeneralNames(GENERAL_NAMES* gens)
-{
- vector<pair<int, string> > alt;
- if(gens == 0)
- {
- return alt;
- }
- for(int i = 0; i < sk_GENERAL_NAME_num(gens); ++i)
- {
- GENERAL_NAME* gen = sk_GENERAL_NAME_value(gens, i);
- pair<int, string> p;
- p.first = gen->type;
- switch(gen->type)
- {
- case GEN_EMAIL:
- {
- ASN1_IA5STRING* str = gen->d.rfc822Name;
- if(str && str->type == V_ASN1_IA5STRING && str->data && str->length > 0)
- {
- p.second = string(reinterpret_cast<const char*>(str->data), str->length);
- }
- break;
- }
- case GEN_DNS:
- {
- ASN1_IA5STRING* str = gen->d.dNSName;
- if(str && str->type == V_ASN1_IA5STRING && str->data && str->length > 0)
- {
- p.second = string(reinterpret_cast<const char*>(str->data), str->length);
- }
- break;
- }
- case GEN_DIRNAME:
- {
- p.second = convertX509NameToString(gen->d.directoryName);
- break;
- }
- case GEN_URI:
- {
- ASN1_IA5STRING* str = gen->d.uniformResourceIdentifier;
- if(str && str->type == V_ASN1_IA5STRING && str->data && str->length > 0)
- {
- p.second = string(reinterpret_cast<const char*>(str->data), str->length);
- }
- break;
- }
- case GEN_IPADD:
- {
- ASN1_OCTET_STRING* addr = gen->d.iPAddress;
- // TODO: Support IPv6 someday.
- if(addr && addr->type == V_ASN1_OCTET_STRING && addr->data && addr->length == 4)
- {
- ostringstream ostr;
- for(int j = 0; j < 4; ++j)
- {
- if(j > 0)
- {
- ostr << '.';
- }
- ostr << static_cast<int>(addr->data[j]);
- }
- p.second = ostr.str();
- }
- break;
- }
- case GEN_OTHERNAME:
- case GEN_EDIPARTY:
- case GEN_X400:
- case GEN_RID:
- {
- //
- // TODO: These types are not supported. If the user wants
- // them, they have to get at the certificate data. Another
- // alternative is to DER encode the data (as the Java
- // certificate does).
- //
- break;
- }
- }
- alt.push_back(p);
- }
- sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
- return alt;
-}
-#endif
-
-ParseException::ParseException(const char* file, int line, const string& r) :
- ExceptionHelper<ParseException>(file, line),
- reason(r)
-{
-}
-
-#ifndef ICE_CPP11_COMPILER
-ParseException::~ParseException() throw()
-{
-}
-#endif
-
-string
-ParseException::ice_id() const
-{
- return "::IceSSL::ParseException";
-}
-
-#ifndef ICE_CPP11_MAPPING
-ParseException*
-ParseException::ice_clone() const
-{
- return new ParseException(*this);
-}
-#endif
-
-#ifdef ICE_USE_OPENSSL
-DistinguishedName::DistinguishedName(X509NAME* name) : _rdns(RFC2253::parseStrict(convertX509NameToString(name)))
-{
- unescape();
-}
-#endif
-
-#if defined(ICE_USE_SECURE_TRANSPORT_IOS)
-DistinguishedName::DistinguishedName(CFDataRef data) : _rdns(ASN1Parser(data).parse())
-{
- unescape();
-}
-#endif
-
-DistinguishedName::DistinguishedName(const string& dn) : _rdns(RFC2253::parseStrict(dn))
-{
- unescape();
-}
-
-DistinguishedName::DistinguishedName(const list<pair<string, string> >& rdns) : _rdns(rdns)
-{
- unescape();
-}
-
-namespace IceSSL
-{
-
-bool
-operator==(const DistinguishedName& lhs, const DistinguishedName& rhs)
-{
- return lhs._unescaped == rhs._unescaped;
-}
-
-bool
-operator<(const DistinguishedName& lhs, const DistinguishedName& rhs)
-{
- return lhs._unescaped == rhs._unescaped;
-}
-
-}
-
-bool
-DistinguishedName::match(const DistinguishedName& other) const
-{
- for(list< pair<string, string> >::const_iterator p = other._unescaped.begin(); p != other._unescaped.end(); ++p)
- {
- bool found = false;
- for(list< pair<string, string> >::const_iterator q = _unescaped.begin(); q != _unescaped.end(); ++q)
- {
- if(p->first == q->first)
- {
- found = true;
- if(p->second != q->second)
- {
- return false;
- }
- }
- }
- if(!found)
- {
- return false;
- }
- }
- return true;
-}
-
-bool
-DistinguishedName::match(const string& other) const
-{
- return match(DistinguishedName(other));
-}
-
-//
-// This always produces the same output as the input DN -- the type of
-// escaping is not changed.
-//
-DistinguishedName::operator string() const
-{
- ostringstream os;
- bool first = true;
- for(list< pair<string, string> >::const_iterator p = _rdns.begin(); p != _rdns.end(); ++p)
- {
- if(!first)
- {
- os << ",";
- }
- first = false;
- os << p->first << "=" << p->second;
- }
- return os.str();
-}
-
-void
-DistinguishedName::unescape()
-{
- for(list< pair<string, string> >::const_iterator q = _rdns.begin(); q != _rdns.end(); ++q)
- {
- pair<string, string> rdn = *q;
- rdn.second = RFC2253::unescape(rdn.second);
- _unescaped.push_back(rdn);
- }
-}
-
-PublicKey::PublicKey(const CertificatePtr& cert, KeyRef key) :
- _cert(cert),
- _key(key)
-{
- if(!_key)
- {
- throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Invalid key reference");
- }
-}
-
-//
-// With SecureTransport the key is UniqueRef and will be automatically released.
-// With SChannel the key is owned by the certificate and there is no need
-// for release it.
-//
-#ifdef ICE_USE_OPENSSL
-PublicKey::~PublicKey()
-{
- if(_key)
- {
- EVP_PKEY_free(_key);
- }
-}
-#endif
-
-KeyRef
-PublicKey::key() const
-{
-#ifdef __APPLE__
- return _key.get();
-#else
- return _key;
-#endif
-}
-
-#if defined(ICE_USE_OPENSSL) || defined(ICE_USE_SCHANNEL)
-
-X509Extension::X509Extension(X509ExtensionRef extension, const string& oid, const CertificatePtr& cert) :
- _extension(extension),
- _oid(oid),
- _cert(cert)
-{
-}
-
-X509Extension::~X509Extension()
-{
-}
-
-bool
-X509Extension::isCritical() const
-{
-#if defined(ICE_USE_OPENSSL)
- return X509_EXTENSION_get_critical(_extension) == 1;
-#elif defined(ICE_USE_SCHANNEL)
- return _extension.fCritical;
-#endif
-}
-
-string
-X509Extension::getOID() const
-{
- return _oid;
-}
-
-vector<Ice::Byte>
-X509Extension::getData() const
-{
- vector<Ice::Byte> data;
-#if defined(ICE_USE_OPENSSL)
- ASN1_OCTET_STRING* buffer = X509_EXTENSION_get_data(_extension);
- assert(buffer);
- data.resize(buffer->length);
- memcpy(&data[0], buffer->data, buffer->length);
-#elif defined(ICE_USE_SCHANNEL)
- data.resize(_extension.Value.cbData);
- memcpy(&data[0], _extension.Value.pbData, _extension.Value.cbData);
-#endif
- return data;
-}
-
-#endif
-
-//
-// The caller is responsible for incrementing the reference count.
-//
-Certificate::Certificate(X509CertificateRef cert) : _cert(cert)
-{
- if(!_cert)
- {
- throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Invalid certificate reference");
- }
-
-#if defined(ICE_USE_SCHANNEL)
- _certInfo = 0;
- try
- {
- //
- // Decode certificate info
- //
- DWORD length = 0;
- if(!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, _cert->ToBeSigned.pbData,
- _cert->ToBeSigned.cbData, CRYPT_DECODE_ALLOC_FLAG, 0, &_certInfo, &length))
- {
- throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
- }
- }
- catch(...)
- {
- LocalFree(_cert);
- _cert = 0;
- throw;
- }
-#endif
-}
-
-#if defined(ICE_USE_OPENSSL) || defined(ICE_USE_SCHANNEL)
-
-void
-Certificate::loadX509Extensions() const
-{
- IceUtil::Mutex::Lock sync(*this);
- if(_extensions.empty())
- {
-#if defined(ICE_USE_SCHANNEL)
- for(size_t i = 0; i < _certInfo->cExtension; ++i)
- {
- CERT_EXTENSION ext = _certInfo->rgExtension[i];
- _extensions.push_back(ICE_MAKE_SHARED(X509Extension, ext, ext.pszObjId, ICE_SHARED_FROM_CONST_THIS(Certificate)));
- }
-#elif defined(ICE_USE_OPENSSL)
- int sz = X509_get_ext_count(_cert);
- for(int i = 0; i < sz; i++)
- {
- X509_EXTENSION* ext = X509_get_ext(_cert, i);
- ASN1_OBJECT* obj = X509_EXTENSION_get_object(ext);
- string oid;
- //
- // According to OBJ_obj2txt doc a buffer of length 80 should be more than enough to
- // handle any OID encountered in practice.
- //
- int len = 80;
- oid.resize(len);
- len = OBJ_obj2txt(&oid[0], len, obj, 1);
- oid.resize(len);
- _extensions.push_back(ICE_MAKE_SHARED(X509Extension, ext, oid, ICE_SHARED_FROM_CONST_THIS(Certificate)));
- }
-#endif
- }
-}
-
-vector<X509ExtensionPtr>
-Certificate::getX509Extensions() const
-{
- loadX509Extensions(); // Lazzy initialize the extensions
- return _extensions;
-}
-
-X509ExtensionPtr
-Certificate::getX509Extension(const string& oid) const
-{
- loadX509Extensions(); // Lazzy initialize the extensions
- X509ExtensionPtr ext;
- for(vector<X509ExtensionPtr>::const_iterator i = _extensions.begin(); i != _extensions.end(); ++i)
- {
- if((*i)->getOID() == oid)
- {
- ext = *i;
- break;
- }
- }
- return ext;
-}
-#endif
-
-Certificate::~Certificate()
-{
- if(_cert)
- {
-#if defined(ICE_USE_SCHANNEL)
- LocalFree(_cert);
- if(_certInfo)
- {
- LocalFree(_certInfo);
- }
-#elif defined(ICE_USE_OPENSSL)
- X509_free(_cert);
-#endif
- }
-}
-
-CertificatePtr
-Certificate::load(const string& file)
-{
-#if defined(ICE_USE_SECURE_TRANSPORT)
- 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);
-#elif defined(ICE_USE_OPENSSL)
- BIO *cert = BIO_new(BIO_s_file());
- if(BIO_read_filename(cert, file.c_str()) <= 0)
- {
- BIO_free(cert);
- throw CertificateReadException(__FILE__, __LINE__, "error opening file");
- }
-
- X509CertificateRef x = PEM_read_bio_X509_AUX(cert, ICE_NULLPTR, ICE_NULLPTR, ICE_NULLPTR);
- if(x == ICE_NULLPTR)
- {
- BIO_free(cert);
- throw CertificateReadException(__FILE__, __LINE__, "error reading file:\n" + getSslErrors(false));
- }
- BIO_free(cert);
- return ICE_MAKE_SHARED(Certificate, x);
-#elif defined(ICE_OS_UWP)
- try
- {
- auto uri = ref new Uri(ref new String(stringToWstring(file).c_str()));
- auto file = create_task(StorageFile::GetFileFromApplicationUriAsync(uri)).get();
- auto buffer = create_task(FileIO::ReadTextAsync(file)).get();
- return Certificate::decode(wstringToString(buffer->Data()));
- }
- catch(Platform::Exception^ ex)
- {
- if(HRESULT_CODE(ex->HResult) == ERROR_FILE_NOT_FOUND)
- {
- throw CertificateReadException(__FILE__, __LINE__, "error opening file :" + file);
- }
- else
- {
- throw Ice::SyscallException(__FILE__, __LINE__, ex->HResult);
- }
- }
-#else
-# error "Unknown platform"
-#endif
-}
-
-CertificatePtr
-Certificate::decode(const string& encoding)
-{
-#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)
- UniqueRef<CFDataRef> data(
- CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
- reinterpret_cast<const UInt8*>(encoding.c_str()),
- encoding.size(), kCFAllocatorNull));
-
- SecExternalFormat format = kSecFormatUnknown;
- SecExternalItemType type = kSecItemTypeCertificate;
-
- SecItemImportExportKeyParameters params;
- memset(&params, 0, sizeof(params));
- params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
-
- UniqueRef<CFArrayRef> items;
- OSStatus err = SecItemImport(data.get(), 0, &format, &type, 0, &params, 0, &items.get());
- if(err)
- {
- throw CertificateEncodingException(__FILE__, __LINE__, errorToString(err));
- }
-
- UniqueRef<SecKeychainItemRef> item;
- item.retain(static_cast<SecKeychainItemRef>(const_cast<void*>(CFArrayGetValueAtIndex(items.get(), 0))));
- assert(SecCertificateGetTypeID() == CFGetTypeID(item.get()));
- return ICE_MAKE_SHARED(Certificate, reinterpret_cast<SecCertificateRef>(item.release()));
-#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);
-#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, ICE_NULLPTR, ICE_NULLPTR, ICE_NULLPTR);
- if(x == ICE_NULLPTR)
- {
- BIO_free(cert);
- throw CertificateEncodingException(__FILE__, __LINE__, getSslErrors(false));
- }
- BIO_free(cert);
- return ICE_MAKE_SHARED(Certificate, x);
-#elif defined(ICE_OS_UWP)
- 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], static_cast<unsigned int>(data.size())));
- return make_shared<Certificate>(ref new Certificates::Certificate(writer->DetachBuffer()));
-#else
-# error "Unknown platform"
-#endif
-}
-
-bool
-Certificate::operator==(const Certificate& other) const
-{
-#if defined(ICE_USE_SECURE_TRANSPORT)
- return CFEqual(_cert.get(), other._cert.get());
-#elif defined(ICE_USE_SCHANNEL)
- return CertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, _certInfo, other._certInfo);
-#elif defined(ICE_USE_OPENSSL)
- return X509_cmp(_cert, other._cert) == 0;
-#elif defined(ICE_OS_UWP)
- return CryptographicBuffer::Compare(_cert->GetCertificateBlob(), other._cert->GetCertificateBlob());
-#else
-# error "Unknown platform"
-#endif
-}
-
-bool
-Certificate::operator!=(const Certificate& other) const
-{
- return !operator==(other);
-}
-
-vector<Ice::Byte>
-Certificate::getAuthorityKeyIdentifier() const
-{
- vector<Ice::Byte> keyid;
-#if defined(ICE_USE_SECURE_TRANSPORT_IOS)
- // Not supported
-#elif defined(ICE_USE_SECURE_TRANSPORT_MACOS)
- UniqueRef<CFDictionaryRef> property(getCertificateProperty(_cert.get(), kSecOIDAuthorityKeyIdentifier));
- if(property)
- {
- CFTypeRef type = 0;
- CFTypeRef value;
- if(CFDictionaryGetValueIfPresent(property.get(), kSecPropertyKeyType, &type))
- {
- if(CFEqual(type, kSecPropertyTypeSection))
- {
- if(CFDictionaryGetValueIfPresent(property.get(), kSecPropertyKeyValue, &value))
- {
- if(CFArrayGetCount(static_cast<CFArrayRef>(value)) >= 0)
- {
- value = CFArrayGetValueAtIndex(static_cast<CFArrayRef>(value), 1);
- type = CFDictionaryGetValue(static_cast<CFDictionaryRef>(value), kSecPropertyKeyType);
- }
- }
- }
-
- if(CFEqual(type, kSecPropertyTypeData))
- {
- CFDataRef data = static_cast<CFDataRef>(
- CFDictionaryGetValue(static_cast<CFDictionaryRef>(value), kSecPropertyKeyValue));
- keyid.resize(CFDataGetLength(data));
- memcpy(&keyid[0], CFDataGetBytePtr(data), CFDataGetLength(data));
- }
- }
- }
-#elif defined(ICE_USE_SCHANNEL)
- PCERT_EXTENSION extension = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER2, _certInfo->cExtension,
- _certInfo->rgExtension);
- if(extension)
- {
- CERT_AUTHORITY_KEY_ID2_INFO* decoded;
- DWORD length = 0;
- if(!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_AUTHORITY_KEY_ID2, extension->Value.pbData,
- extension->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, 0, &decoded, &length))
- {
- throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
- }
-
- if(decoded->KeyId.pbData && decoded->KeyId.cbData)
- {
- keyid.resize(decoded->KeyId.cbData);
- memcpy(&keyid[0], decoded->KeyId.pbData, decoded->KeyId.cbData);
- LocalFree(decoded);
- }
- }
-#elif defined(ICE_USE_OPENSSL)
- int index = X509_get_ext_by_NID(_cert, NID_authority_key_identifier, -1);
- if(index >= 0)
- {
- X509_EXTENSION* ext = X509_get_ext(_cert, index);
- if(ext)
- {
- AUTHORITY_KEYID* decoded = (AUTHORITY_KEYID*)X509V3_EXT_d2i(ext);
- if(!decoded)
- {
- throw CertificateEncodingException(__FILE__, __LINE__, "the extension could not be decoded");
- }
- keyid.resize(decoded->keyid->length);
- memcpy(&keyid[0], decoded->keyid->data, decoded->keyid->length);
- AUTHORITY_KEYID_free(decoded);
- }
- }
-#elif defined(ICE_OS_UWP)
- // Not supported
-#else
-# error "Unknown platform"
-#endif
- return keyid;
-}
-
-vector<Ice::Byte>
-Certificate::getSubjectKeyIdentifier() const
-{
- vector<Ice::Byte> keyid;
-#if defined(ICE_USE_SECURE_TRANSPORT_IOS)
- // Not supported
-#elif defined(ICE_USE_SECURE_TRANSPORT_MACOS)
- UniqueRef<CFDictionaryRef> property(getCertificateProperty(_cert.get(), kSecOIDSubjectKeyIdentifier));
- if(property)
- {
- CFTypeRef type = 0;
- CFTypeRef value;
- if(CFDictionaryGetValueIfPresent(property.get(), kSecPropertyKeyType, &type))
- {
- if(CFEqual(type, kSecPropertyTypeSection))
- {
- if(CFDictionaryGetValueIfPresent(property.get(), kSecPropertyKeyValue, &value))
- {
- if(CFArrayGetCount(static_cast<CFArrayRef>(value)) >= 0)
- {
- value = CFArrayGetValueAtIndex(static_cast<CFArrayRef>(value), 1);
- type = CFDictionaryGetValue(static_cast<CFDictionaryRef>(value), kSecPropertyKeyType);
- }
- }
- }
-
- if(CFEqual(type, kSecPropertyTypeData))
- {
- CFDataRef data = static_cast<CFDataRef>(
- CFDictionaryGetValue(static_cast<CFDictionaryRef>(value), kSecPropertyKeyValue));
- keyid.resize(CFDataGetLength(data));
- memcpy(&keyid[0], CFDataGetBytePtr(data), CFDataGetLength(data));
- }
- }
- }
-#elif defined(ICE_USE_SCHANNEL)
- PCERT_EXTENSION extension = CertFindExtension(szOID_SUBJECT_KEY_IDENTIFIER, _certInfo->cExtension,
- _certInfo->rgExtension);
- if(extension)
- {
- CRYPT_DATA_BLOB* decoded;
- DWORD length = 0;
- if(!CryptDecodeObjectEx(X509_ASN_ENCODING, szOID_SUBJECT_KEY_IDENTIFIER, extension->Value.pbData,
- extension->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, 0, &decoded, &length))
- {
- throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
- }
-
- if(decoded->pbData && decoded->cbData)
- {
- keyid.resize(decoded->cbData);
- memcpy(&keyid[0], decoded->pbData, decoded->cbData);
- LocalFree(decoded);
- }
- }
-#elif defined(ICE_USE_OPENSSL)
- int index = X509_get_ext_by_NID(_cert, NID_subject_key_identifier, -1);
- if(index >= 0)
- {
- X509_EXTENSION* ext = X509_get_ext(_cert, index);
- if(ext)
- {
- ASN1_OCTET_STRING* decoded = static_cast<ASN1_OCTET_STRING*>(X509V3_EXT_d2i(ext));
- if(!decoded)
- {
- throw CertificateEncodingException(__FILE__, __LINE__, "the extension could not be decoded");
- }
- keyid.resize(decoded->length);
- memcpy(&keyid[0], decoded->data, decoded->length);
- ASN1_OCTET_STRING_free(decoded);
- }
- }
-#elif defined(ICE_OS_UWP)
- // Not supported
-#else
-# error "Unknown platform"
-#endif
- return keyid;
-}
-
-PublicKeyPtr
-Certificate::getPublicKey() const
-{
-#if defined(ICE_USE_SECURE_TRANSPORT_IOS)
- return ICE_NULLPTR; // Not supported
-#elif defined(ICE_USE_SECURE_TRANSPORT_MACOS)
- UniqueRef<SecKeyRef> key;
- OSStatus err = SecCertificateCopyPublicKey(_cert.get(), &key.get());
- if(err)
- {
- throw CertificateEncodingException(__FILE__, __LINE__, errorToString(err));
- }
- return ICE_MAKE_SHARED(PublicKey, ICE_SHARED_FROM_CONST_THIS(Certificate), key.release());
-#elif defined(ICE_USE_SCHANNEL)
- return ICE_MAKE_SHARED(PublicKey, ICE_SHARED_FROM_CONST_THIS(Certificate), &_certInfo->SubjectPublicKeyInfo);
-#elif defined(ICE_USE_OPENSSL)
- return ICE_MAKE_SHARED(PublicKey, ICE_SHARED_FROM_CONST_THIS(Certificate), X509_get_pubkey(_cert));
-#elif defined(ICE_OS_UWP)
- return ICE_NULLPTR; // Not supported
-#else
-# error "Unknown platform"
-#endif
-}
-
-bool
-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 checking a certificate against itself
- // SecTrustEvaluate always returns it is valid.
- //
- bool valid = false;
-
-# if defined(ICE_USE_SECURE_TRANSPORT_IOS)
- initializeAttributes();
- cert->initializeAttributes();
- valid = CFEqual(_issuer.get(), cert->_subject.get());
-# else
- UniqueRef<CFErrorRef> error;
- UniqueRef<CFDataRef> issuer(SecCertificateCopyNormalizedIssuerContent(_cert.get(), &error.get()));
- if(error)
- {
- throw CertificateEncodingException(__FILE__, __LINE__, error.get());
- }
- UniqueRef<CFDataRef> subject(SecCertificateCopyNormalizedSubjectContent(cert->getCert(), &error.get()));
- if(error)
- {
- throw CertificateEncodingException(__FILE__, __LINE__, error.get());
- }
-
- //
- // The certificate issuer must match the CA subject.
- //
- valid = CFEqual(issuer.get(), subject.get());
-# endif
- if(valid)
- {
- UniqueRef<SecPolicyRef> policy(SecPolicyCreateBasicX509());
- UniqueRef<SecTrustRef> trust;
- OSStatus err = 0;;
- if((err = SecTrustCreateWithCertificates(_cert.get(), policy.get(), &trust.get())))
- {
- throw CertificateEncodingException(__FILE__, __LINE__, errorToString(err));
- }
-
- SecCertificateRef certs[1] = { cert->getCert() };
- UniqueRef<CFArrayRef> anchorCertificates(
- CFArrayCreate(kCFAllocatorDefault, (const void**)&certs, 1, &kCFTypeArrayCallBacks));
- if((err = SecTrustSetAnchorCertificates(trust.get(), anchorCertificates.get())))
- {
- throw CertificateEncodingException(__FILE__, __LINE__, errorToString(err));
- }
-
- SecTrustResultType trustResult = kSecTrustResultInvalid;
- if((err = SecTrustEvaluate(trust.get(), &trustResult)))
- {
- throw CertificateEncodingException(__FILE__, __LINE__, errorToString(err));
- }
-
- valid = trustResult == kSecTrustResultUnspecified;
- }
- return valid;
-#elif defined(ICE_USE_SCHANNEL)
- BYTE* buffer = 0;
- DWORD length = 0;
- if(!CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, _cert, CRYPT_ENCODE_ALLOC_FLAG , 0, &buffer, &length))
- {
- throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
- }
-
- bool result = CryptVerifyCertificateSignature(0, X509_ASN_ENCODING, buffer, length, cert->getPublicKey()->key());
- LocalFree(buffer);
- return result;
-#elif defined(ICE_USE_OPENSSL)
- return X509_verify(_cert, cert->getPublicKey()->key()) > 0;
-#elif defined(ICE_OS_UWP)
- return false;
-#else
-# error "Unknown platform"
-#endif
-}
-
-#ifdef ICE_USE_OPENSSL
-bool
-Certificate::verify(const PublicKeyPtr& key) const
-{
- return X509_verify(_cert, key->key()) > 0;
-}
-#endif
-
-string
-Certificate::encode() const
-{
-#if defined(ICE_USE_SECURE_TRANSPORT_IOS)
- UniqueRef<CFDataRef> cert(SecCertificateCopyData(_cert.get()));
- vector<unsigned char> data(CFDataGetBytePtr(cert.get()), CFDataGetBytePtr(cert.get()) + CFDataGetLength(cert.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)
- UniqueRef<CFDataRef> exported;
- OSStatus err = SecItemExport(_cert.get(), kSecFormatPEMSequence, kSecItemPemArmour, 0, &exported.get());
- if(err != noErr)
- {
- throw CertificateEncodingException(__FILE__, __LINE__, errorToString(err));
- }
- return string(reinterpret_cast<const char*>(CFDataGetBytePtr(exported.get())), CFDataGetLength(exported.get()));
-#elif defined(ICE_USE_SCHANNEL)
- string s;
- DWORD length = 0;
- BYTE* buffer = 0;
- try
- {
- if(!CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, _cert, CRYPT_ENCODE_ALLOC_FLAG , 0, &buffer, &length))
- {
- throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
- }
-
- DWORD encodedLength = 0;
- if(!CryptBinaryToString(buffer, length, CRYPT_STRING_BASE64HEADER | CRYPT_STRING_NOCR, 0, &encodedLength))
- {
- throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
- }
-
- std::vector<char> encoded;
- encoded.resize(encodedLength);
- if(!CryptBinaryToString(buffer, length, CRYPT_STRING_BASE64HEADER | CRYPT_STRING_NOCR, &encoded[0],
- &encodedLength))
- {
- throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
- }
- LocalFree(buffer);
- buffer = 0;
- s.assign(&encoded[0]);
- }
- catch(...)
- {
- if(buffer)
- {
- LocalFree(buffer);
- }
- throw;
- }
- return s;
-#elif defined(ICE_USE_OPENSSL)
- BIO* out = BIO_new(BIO_s_mem());
- int i = PEM_write_bio_X509_AUX(out, _cert);
- if(i <= 0)
- {
- BIO_free(out);
- throw CertificateEncodingException(__FILE__, __LINE__, getSslErrors(false));
- }
- BUF_MEM* p;
- BIO_get_mem_ptr(out, &p);
- string result = string(p->data, p->length);
- BIO_free(out);
- return result;
-#elif defined(ICE_OS_UWP)
- 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], static_cast<unsigned int>(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
-{
-#ifdef ICE_CPP11_MAPPING
- auto now = chrono::system_clock::now();
-#else
- IceUtil::Time now = IceUtil::Time::now();
-#endif
- return now > getNotBefore() && now <= getNotAfter();
-}
-
-bool
-#ifdef ICE_CPP11_MAPPING
-Certificate::checkValidity(const chrono::system_clock::time_point& now) const
-#else
-Certificate::checkValidity(const IceUtil::Time& now) const
-#endif
-{
- return now > getNotBefore() && now <= getNotAfter();
-}
-
-#ifdef ICE_CPP11_MAPPING
-chrono::system_clock::time_point
-#else
-IceUtil::Time
-#endif
-Certificate::getNotAfter() const
-{
-#if defined(ICE_USE_SECURE_TRANSPORT)
- return getX509Date(_cert.get(), kSecOIDX509V1ValidityNotAfter);
-#elif defined(ICE_USE_SCHANNEL)
- return filetimeToTime(_certInfo->NotAfter);
-#elif defined(ICE_USE_OPENSSL)
- return ASMUtcTimeToTime(X509_get_notAfter(_cert));
-#elif defined(ICE_OS_UWP)
- // Convert 100ns time from January 1, 1601 to ms from January 1, 1970
- IceUtil::Time time = IceUtil::Time::milliSeconds(_cert->ValidTo.UniversalTime / TICKS_PER_MSECOND - MSECS_TO_EPOCH);
-# ifdef ICE_CPP11_MAPPING
- return chrono::system_clock::time_point(chrono::microseconds(time.toMicroSeconds()));
-# else
- return time;
-# endif
-
-#else
-# error "Unknown platform"
-#endif
-}
-
-#ifdef ICE_CPP11_MAPPING
-chrono::system_clock::time_point
-#else
-IceUtil::Time
-#endif
-Certificate::getNotBefore() const
-{
-#if defined(ICE_USE_SECURE_TRANSPORT)
- return getX509Date(_cert.get(), kSecOIDX509V1ValidityNotBefore);
-#elif defined(ICE_USE_SCHANNEL)
- return filetimeToTime(_certInfo->NotBefore);
-#elif defined(ICE_USE_OPENSSL)
- return ASMUtcTimeToTime(X509_get_notBefore(_cert));
-#elif defined(ICE_OS_UWP)
- // Convert 100ns time from January 1, 1601 to ms from January 1, 1970
- IceUtil::Time time = IceUtil::Time::milliSeconds(_cert->ValidFrom.UniversalTime / TICKS_PER_MSECOND - MSECS_TO_EPOCH);
-# ifdef ICE_CPP11_MAPPING
- return chrono::system_clock::time_point(chrono::microseconds(time.toMicroSeconds()));
-# else
- return time;
-# endif
-
-#else
-# error "Unknown platform"
-#endif
-}
-
-#endif
-
-string
-Certificate::getSerialNumber() const
-{
-#if defined(ICE_USE_SECURE_TRANSPORT_IOS)
- initializeAttributes();
- return _serial;
-#elif defined(ICE_USE_SECURE_TRANSPORT_MACOS)
- return getX509String(_cert.get(), kSecOIDX509V1SerialNumber);
-#elif defined(ICE_USE_SCHANNEL)
- ostringstream os;
- for(int i = _certInfo->SerialNumber.cbData - 1; i >= 0; --i)
- {
- unsigned char c = _certInfo->SerialNumber.pbData[i];
- os.fill('0');
- os.width(2);
- os << hex << static_cast<int>(c);
- if(i)
- {
- os << ' ';
- }
- }
- return IceUtilInternal::toUpper(os.str());
-#elif defined(ICE_USE_OPENSSL)
- BIGNUM* bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(_cert), 0);
- char* dec = BN_bn2dec(bn);
- string result = dec;
- OPENSSL_free(dec);
- BN_free(bn);
-
- return result;
-#elif defined(ICE_OS_UWP)
- 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
-}
-
-DistinguishedName
-Certificate::getIssuerDN() const
-{
-#if defined(ICE_USE_SECURE_TRANSPORT_IOS)
- initializeAttributes();
- return _issuer ? DistinguishedName(_issuer.get()) : DistinguishedName("");
-#elif defined(ICE_USE_SECURE_TRANSPORT_MACOS)
- return getX509Name(_cert.get(), kSecOIDX509V1IssuerName);
-#elif defined(ICE_USE_SCHANNEL)
- return DistinguishedName(certNameToString(&_certInfo->Issuer));
-#elif defined(ICE_USE_OPENSSL)
- return DistinguishedName(RFC2253::parseStrict(convertX509NameToString(X509_get_issuer_name(_cert))));
-#elif defined(ICE_OS_UWP)
- ostringstream os;
- os << "CN=" << wstringToString(_cert->Issuer->Data());
- return DistinguishedName(os.str());
-#else
-# error "Unknown platform"
-#endif
-}
-
-#if !defined(ICE_USE_SECURE_TRANSPORT_IOS)
-vector<pair<int, string> >
-Certificate::getIssuerAlternativeNames()
-{
-#if defined(ICE_USE_SECURE_TRANSPORT)
- return getX509AltName(_cert.get(), kSecOIDIssuerAltName);
-#elif defined(ICE_USE_SCHANNEL)
- return certificateAltNames(_certInfo, szOID_ISSUER_ALT_NAME2);
-#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_UWP)
- return vector<pair<int, string> >(); // Not supported
-#else
-# error "Unknown platform"
-#endif
-}
-#endif
-
-DistinguishedName
-Certificate::getSubjectDN() const
-{
-#if defined(ICE_USE_SECURE_TRANSPORT_IOS)
- initializeAttributes();
- if(_subject)
- {
- return DistinguishedName(_subject.get());
- }
- else
- {
- UniqueRef<CFStringRef> subjectSummary(SecCertificateCopySubjectSummary(_cert.get()));
- return DistinguishedName("CN=" + fromCFString(subjectSummary.get()));
- }
-#elif defined(ICE_USE_SECURE_TRANSPORT_MACOS)
- return getX509Name(_cert.get(), kSecOIDX509V1SubjectName);
-#elif defined(ICE_USE_SCHANNEL)
- return DistinguishedName(certNameToString(&_certInfo->Subject));
-#elif defined(ICE_USE_OPENSSL)
- return DistinguishedName(RFC2253::parseStrict(convertX509NameToString(X509_get_subject_name(_cert))));
-#elif defined(ICE_OS_UWP)
- ostringstream os;
- os << "CN=" << wstringToString(_cert->Subject->Data());
- return DistinguishedName(os.str());
-#else
-# error "Unknown platform"
-#endif
-}
-
-#if !defined(ICE_USE_SECURE_TRANSPORT_IOS)
-vector<pair<int, string> >
-Certificate::getSubjectAlternativeNames()
-{
-#if defined(ICE_USE_SECURE_TRANSPORT)
- return getX509AltName(_cert.get(), kSecOIDSubjectAltName);
-#elif defined(ICE_USE_SCHANNEL)
- return certificateAltNames(_certInfo, szOID_SUBJECT_ALT_NAME2);
-#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_UWP)
- return certificateAltNames(_cert->SubjectAlternativeName);
-#else
-# error "Unknown platform"
-#endif
-}
-#endif
-
-int
-Certificate::getVersion() const
-{
-#if defined(ICE_USE_SECURE_TRANSPORT_IOS)
- initializeAttributes();
- return _version;
-#elif defined(ICE_USE_SECURE_TRANSPORT_MACOS)
- return atoi(getX509String(_cert.get(), kSecOIDX509V1Version).c_str()) - 1;
-#elif defined(ICE_USE_SCHANNEL)
- return _certInfo->dwVersion;
-#elif defined(ICE_USE_OPENSSL)
- return static_cast<int>(X509_get_version(_cert));
-#elif defined(ICE_OS_UWP)
- return -1; // Not supported
-#else
-# error "Unknown platform"
-#endif
-}
-
-string
-Certificate::toString() const
-{
- ostringstream os;
- os << "serial: " << getSerialNumber() << "\n";
- os << "issuer: " << string(getIssuerDN()) << "\n";
- os << "subject: " << string(getSubjectDN()) << "\n";
-#if !defined(ICE_USE_SECURE_TRANSPORT_IOS)
-
-# ifdef ICE_CPP11_MAPPING
- // Precision is only seconds here, which is probably fine
- os << "notBefore: " << IceUtil::Time::seconds(chrono::system_clock::to_time_t(getNotBefore())).toDateTime() << "\n";
- os << "notAfter: " << IceUtil::Time::seconds(chrono::system_clock::to_time_t(getNotAfter())).toDateTime();
-# else
- os << "notBefore: " << getNotBefore().toDateTime() << "\n";
- os << "notAfter: " << getNotAfter().toDateTime();
-# endif
-
-#endif
- return os.str();
-}
-
-X509CertificateRef
-Certificate::getCert() const
-{
-#ifdef __APPLE__
- return _cert.get();
-#else
- return _cert;
-#endif
-}
-
-#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
-{
- //
- // 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);
-
- if(_subject)
- {
- return;
- }
-
- UniqueRef<CFMutableDictionaryRef> query(
- CFDictionaryCreateMutable(0, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
- CFDictionarySetValue(query.get(), kSecValueRef, _cert.get());
- CFDictionarySetValue(query.get(), kSecReturnAttributes, kCFBooleanTrue);
-
- UniqueRef<CFDictionaryRef> attributes(0);
- OSStatus err;
- if((err = SecItemAdd(query.get(), reinterpret_cast<CFTypeRef*>(&attributes.get()))) == errSecDuplicateItem)
- {
- CFDictionarySetValue(query.get(), kSecClass, kSecClassCertificate);
- err = SecItemCopyMatching(query.get(), reinterpret_cast<CFTypeRef*>(&attributes.get()));
- }
- else
- {
- query.reset(CFDictionaryCreateMutable(0, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
- CFDictionarySetValue(query.get(), kSecClass, kSecClassCertificate);
- CFDictionarySetValue(query.get(), kSecValueRef, _cert.get());
- err = SecItemDelete(query.get());
- }
-
- if(err != noErr)
- {
- _subject.reset(0);
- _issuer.reset(0);
- throw CertificateEncodingException(__FILE__, __LINE__, errorToString(err));
- }
-
- _subject.retain(static_cast<CFDataRef>(CFDictionaryGetValue(attributes.get(), kSecAttrSubject)));
- _issuer.retain(static_cast<CFDataRef>(CFDictionaryGetValue(attributes.get(), kSecAttrIssuer)));
- CFDataRef serial = static_cast<CFDataRef>(CFDictionaryGetValue(attributes.get(), 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 = static_cast<CFNumberRef>(CFDictionaryGetValue(attributes.get(), kSecAttrCertificateType));
- if(!CFNumberGetValue(version, kCFNumberIntType, &_version))
- {
- _version = -1;
- }
-}
-#endif
diff --git a/cpp/src/IceSSL/CertificateI.cpp b/cpp/src/IceSSL/CertificateI.cpp
new file mode 100644
index 00000000000..fb7969b75f4
--- /dev/null
+++ b/cpp/src/IceSSL/CertificateI.cpp
@@ -0,0 +1,284 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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 <IceUtil/DisableWarnings.h>
+#include <IceUtil/Mutex.h>
+#include <IceUtil/MutexPtrLock.h>
+#include <IceUtil/StringUtil.h>
+#include <IceSSL/Plugin.h>
+#include <IceSSL/Util.h>
+#include <IceSSL/RFC2253.h>
+#include <IceSSL/CertificateI.h>
+#include <Ice/Object.h>
+#include <Ice/Base64.h>
+#include <Ice/StringConverter.h>
+#include <IceUtil/Time.h>
+
+
+using namespace std;
+using namespace Ice;
+using namespace IceInternal;
+using namespace IceSSL;
+
+//
+// Map a certificate OID to its alias
+//
+const CertificateOID IceSSL::certificateOIDS[] =
+{
+ {"2.5.4.3", "CN"},
+ {"2.5.4.4", "SN"},
+ {"2.5.4.5", "DeviceSerialNumber"},
+ {"2.5.4.6", "C"},
+ {"2.5.4.7", "L"},
+ {"2.5.4.8", "ST"},
+ {"2.5.4.9", "STREET"},
+ {"2.5.4.10", "O"},
+ {"2.5.4.11", "OU"},
+ {"2.5.4.12", "T"},
+ {"2.5.4.42", "G"},
+ {"2.5.4.43", "I"},
+ {"1.2.840.113549.1.9.8", "unstructuredAddress"},
+ {"1.2.840.113549.1.9.2", "unstructuredName"},
+ {"1.2.840.113549.1.9.1", "emailAddress"},
+ {"0.9.2342.19200300.100.1.25", "DC"}
+};
+const int IceSSL::certificateOIDSSize = sizeof(IceSSL::certificateOIDS) / sizeof(CertificateOID);
+
+CertificateReadException::CertificateReadException(const char* file, int line, const string& r) :
+ ExceptionHelper<CertificateReadException>(file, line),
+ reason(r)
+{
+}
+
+#ifndef ICE_CPP11_COMPILER
+CertificateReadException::~CertificateReadException() throw()
+{
+}
+#endif
+
+string
+CertificateReadException::ice_id() const
+{
+ return "::IceSSL::CertificateReadException";
+}
+
+#ifndef ICE_CPP11_MAPPING
+CertificateReadException*
+CertificateReadException::ice_clone() const
+{
+ return new CertificateReadException(*this);
+}
+#endif
+
+CertificateEncodingException::CertificateEncodingException(const char* file, int line, const string& r) :
+ ExceptionHelper<CertificateEncodingException>(file, line),
+ reason(r)
+{
+}
+
+#ifndef ICE_CPP11_COMPILER
+CertificateEncodingException::~CertificateEncodingException() throw()
+{
+}
+#endif
+
+string
+CertificateEncodingException::ice_id() const
+{
+ return "::IceSSL::CertificateEncodingException";
+}
+
+#ifndef ICE_CPP11_MAPPING
+CertificateEncodingException*
+CertificateEncodingException::ice_clone() const
+{
+ return new CertificateEncodingException(*this);
+}
+#endif
+
+ParseException::ParseException(const char* file, int line, const string& r) :
+ ExceptionHelper<ParseException>(file, line),
+ reason(r)
+{
+}
+
+#ifndef ICE_CPP11_COMPILER
+ParseException::~ParseException() throw()
+{
+}
+#endif
+
+string
+ParseException::ice_id() const
+{
+ return "::IceSSL::ParseException";
+}
+
+#ifndef ICE_CPP11_MAPPING
+ParseException*
+ParseException::ice_clone() const
+{
+ return new ParseException(*this);
+}
+#endif
+
+DistinguishedName::DistinguishedName(const string& dn) : _rdns(RFC2253::parseStrict(dn))
+{
+ unescape();
+}
+
+DistinguishedName::DistinguishedName(const list<pair<string, string> >& rdns) : _rdns(rdns)
+{
+ unescape();
+}
+
+namespace IceSSL
+{
+
+bool
+operator==(const DistinguishedName& lhs, const DistinguishedName& rhs)
+{
+ return lhs._unescaped == rhs._unescaped;
+}
+
+bool
+operator<(const DistinguishedName& lhs, const DistinguishedName& rhs)
+{
+ return lhs._unescaped < rhs._unescaped;
+}
+
+}
+
+bool
+DistinguishedName::match(const DistinguishedName& other) const
+{
+ for(list< pair<string, string> >::const_iterator p = other._unescaped.begin(); p != other._unescaped.end(); ++p)
+ {
+ bool found = false;
+ for(list< pair<string, string> >::const_iterator q = _unescaped.begin(); q != _unescaped.end(); ++q)
+ {
+ if(p->first == q->first)
+ {
+ found = true;
+ if(p->second != q->second)
+ {
+ return false;
+ }
+ }
+ }
+ if(!found)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool
+DistinguishedName::match(const string& other) const
+{
+ return match(DistinguishedName(other));
+}
+
+//
+// This always produces the same output as the input DN -- the type of
+// escaping is not changed.
+//
+DistinguishedName::operator string() const
+{
+ ostringstream os;
+ bool first = true;
+ for(list< pair<string, string> >::const_iterator p = _rdns.begin(); p != _rdns.end(); ++p)
+ {
+ if(!first)
+ {
+ os << ",";
+ }
+ first = false;
+ os << p->first << "=" << p->second;
+ }
+ return os.str();
+}
+
+void
+DistinguishedName::unescape()
+{
+ for(list< pair<string, string> >::const_iterator q = _rdns.begin(); q != _rdns.end(); ++q)
+ {
+ pair<string, string> rdn = *q;
+ rdn.second = RFC2253::unescape(rdn.second);
+ _unescaped.push_back(rdn);
+ }
+}
+
+bool
+CertificateI::operator!=(const IceSSL::Certificate& other) const
+{
+ return !operator==(other);
+}
+
+vector<X509ExtensionPtr>
+CertificateI::getX509Extensions() const
+{
+ loadX509Extensions(); // Lazzy initialize the extensions
+ return _extensions;
+}
+
+X509ExtensionPtr
+CertificateI::getX509Extension(const string& oid) const
+{
+ loadX509Extensions(); // Lazzy initialize the extensions
+ X509ExtensionPtr ext;
+ for(vector<X509ExtensionPtr>::const_iterator i = _extensions.begin(); i != _extensions.end(); ++i)
+ {
+ if((*i)->getOID() == oid)
+ {
+ ext = *i;
+ break;
+ }
+ }
+ return ext;
+}
+
+void
+CertificateI::loadX509Extensions() const
+{
+ throw FeatureNotSupportedException(__FILE__, __LINE__);
+}
+
+bool
+CertificateI::checkValidity() const
+{
+# ifdef ICE_CPP11_MAPPING
+ auto now = chrono::system_clock::now();
+# else
+ IceUtil::Time now = IceUtil::Time::now();
+# endif
+ return now > getNotBefore() && now <= getNotAfter();
+}
+
+bool
+# ifdef ICE_CPP11_MAPPING
+CertificateI::checkValidity(const chrono::system_clock::time_point& now) const
+# else
+CertificateI::checkValidity(const IceUtil::Time& now) const
+# endif
+{
+ return now > getNotBefore() && now <= getNotAfter();
+}
+
+string
+CertificateI::toString() const
+{
+ ostringstream os;
+ os << "serial: " << getSerialNumber() << "\n";
+ os << "issuer: " << string(getIssuerDN()) << "\n";
+ os << "subject: " << string(getSubjectDN()) << "\n";
+ return os.str();
+}
diff --git a/cpp/src/IceSSL/CertificateI.h b/cpp/src/IceSSL/CertificateI.h
new file mode 100644
index 00000000000..4420806182c
--- /dev/null
+++ b/cpp/src/IceSSL/CertificateI.h
@@ -0,0 +1,69 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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 ICESSL_CERTIFICATE_I_H
+#define ICESSL_CERTIFICATE_I_H
+
+#include <IceSSL/Plugin.h>
+
+#include <vector>
+#include <string>
+
+namespace IceSSL
+{
+
+//
+// Map a certificate OID to its alias
+//
+struct ICESSL_API CertificateOID
+{
+ const char* name;
+ const char* alias;
+};
+
+extern const ICESSL_API CertificateOID certificateOIDS[];
+extern const ICESSL_API int certificateOIDSSize;
+
+//
+// Certificate common implementation
+//
+class ICESSL_API CertificateI : public virtual IceSSL::Certificate
+{
+public:
+
+ virtual bool operator!=(const IceSSL::Certificate&) const;
+
+ virtual std::vector<X509ExtensionPtr> getX509Extensions() const;
+ virtual X509ExtensionPtr getX509Extension(const std::string&) const;
+
+ virtual bool checkValidity() const;
+# ifdef ICE_CPP11_MAPPING
+ virtual bool checkValidity(const std::chrono::system_clock::time_point& now) const;
+# else
+ virtual bool checkValidity(const IceUtil::Time& now) const;
+# endif
+
+ virtual std::string toString() const;
+
+protected:
+
+ //
+ // Implementations that support retrieving X509 extensions must
+ // reimplement this method to lazzy initialize the extensions
+ // list.
+ //
+ // The default implementation just throw FeatureNotSupportedException
+ //
+ virtual void loadX509Extensions() const;
+ mutable std::vector<X509ExtensionPtr> _extensions;
+};
+
+} // IceSSL namespace end
+
+#endif
diff --git a/cpp/src/IceSSL/ConnectorI.cpp b/cpp/src/IceSSL/ConnectorI.cpp
index 019a1a4e08c..cce51d27217 100644
--- a/cpp/src/IceSSL/ConnectorI.cpp
+++ b/cpp/src/IceSSL/ConnectorI.cpp
@@ -10,13 +10,9 @@
#include <IceSSL/ConnectorI.h>
#include <IceSSL/Instance.h>
-#include <IceSSL/OpenSSLTransceiverI.h>
-#include <IceSSL/SecureTransportTransceiverI.h>
-#include <IceSSL/SChannelTransceiverI.h>
-#include <IceSSL/UWPTransceiverI.h>
-
#include <IceSSL/EndpointI.h>
#include <IceSSL/Util.h>
+#include <IceSSL/SSLEngine.h>
#include <Ice/Communicator.h>
#include <Ice/LocalException.h>
#include <Ice/StreamSocket.h>
@@ -40,7 +36,7 @@ IceSSL::ConnectorI::connect()
throw ex;
}
- return new TransceiverI(_instance, _delegate->connect(), _host, false);
+ return _instance->engine()->createTransceiver(_instance, _delegate->connect(), _host, false);
}
Short
diff --git a/cpp/src/IceSSL/ConnectorI.h b/cpp/src/IceSSL/ConnectorI.h
index bfb909cc09f..9820887de68 100644
--- a/cpp/src/IceSSL/ConnectorI.h
+++ b/cpp/src/IceSSL/ConnectorI.h
@@ -44,6 +44,6 @@ private:
const std::string _host;
};
-}
+} // IceSSL namespace end
#endif
diff --git a/cpp/src/IceSSL/IceSSLOpenSSL.rc b/cpp/src/IceSSL/IceSSLOpenSSL.rc
new file mode 100644
index 00000000000..8fb8b420357
--- /dev/null
+++ b/cpp/src/IceSSL/IceSSLOpenSSL.rc
@@ -0,0 +1,33 @@
+#include<IceUtil/ResourceConfig.h>
+
+#define ICE_INTERNALNAME ICE_LIBNAME("icesslopenssl") "\0"
+#define ICE_ORIGINALFILENAME ICE_LIBNAME("icesslopenssl") ".dll\0"
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION ICE_VERSION
+PRODUCTVERSION ICE_VERSION
+FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+FILEOS VOS_NT_WINDOWS32
+FILETYPE VFT_DLL
+FILESUBTYPE VFT2_UNKNOWN
+FILEFLAGS VER_DEBUG
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "CompanyName", ICE_COMPANY_NAME
+ VALUE "FileDescription", "IceSSL OpenSSL C++ Plug-in\0"
+ VALUE "FileVersion", ICE_STRING_VERSION
+ VALUE "InternalName", ICE_INTERNALNAME
+ VALUE "LegalCopyright", ICE_COPYRIGHT
+ VALUE "OriginalFilename", ICE_ORIGINALFILENAME
+ VALUE "ProductName", ICE_PRODUCT_NAME
+ VALUE "ProductVersion", ICE_STRING_VERSION
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
diff --git a/cpp/src/IceSSL/Instance.h b/cpp/src/IceSSL/Instance.h
index ab82106ee40..3cb34f42675 100644
--- a/cpp/src/IceSSL/Instance.h
+++ b/cpp/src/IceSSL/Instance.h
@@ -17,7 +17,7 @@
namespace IceSSL
{
-class Instance : public IceInternal::ProtocolInstance
+class ICESSL_API Instance : public IceInternal::ProtocolInstance
{
public:
diff --git a/cpp/src/IceSSL/InstanceF.h b/cpp/src/IceSSL/InstanceF.h
index f3b825e43e1..b0a9b49192e 100644
--- a/cpp/src/IceSSL/InstanceF.h
+++ b/cpp/src/IceSSL/InstanceF.h
@@ -11,26 +11,26 @@
#define ICESSL_INSTANCE_F_H
#include <IceUtil/Shared.h>
-
#include <Ice/Handle.h>
+#include <IceSSL/Plugin.h>
namespace IceSSL
{
class Instance;
-IceUtil::Shared* upCast(Instance*);
+ICESSL_API IceUtil::Shared* upCast(Instance*);
typedef IceInternal::Handle<Instance> InstancePtr;
class EndpointI;
#ifdef ICE_CPP11_MAPPING
typedef ::std::shared_ptr<EndpointI> EndpointIPtr;
#else
-IceUtil::Shared* upCast(EndpointI*);
+ICESSL_API IceUtil::Shared* upCast(EndpointI*);
typedef IceInternal::Handle<EndpointI> EndpointIPtr;
#endif
class AcceptorI;
-IceUtil::Shared* upCast(AcceptorI*);
+ICESSL_API IceUtil::Shared* upCast(AcceptorI*);
typedef IceInternal::Handle<AcceptorI> AcceptorIPtr;
}
diff --git a/cpp/src/IceSSL/Makefile.mk b/cpp/src/IceSSL/Makefile.mk
index aa9b9c0dfd7..da98ab6c2b3 100644
--- a/cpp/src/IceSSL/Makefile.mk
+++ b/cpp/src/IceSSL/Makefile.mk
@@ -11,7 +11,21 @@ $(project)_libraries := IceSSL
IceSSL_targetdir := $(libdir)
IceSSL_dependencies := Ice
-IceSSL_cppflags := -DICESSL_API_EXPORTS
+IceSSL_cppflags := -DICESSL_API_EXPORTS
IceSSL_sliceflags := --include-dir IceSSL
+#
+# Exclude sources that are not build with the default
+# implementation.
+#
+IceSSL_excludes += $(wildcard src/IceSSL/SChannel*.cpp)
+IceSSL_excludes += $(wildcard src/IceSSL/UWP*.cpp)
+
+ifeq ($(os),Darwin)
+IceSSL_excludes += $(wildcard src/IceSSL/OpenSSL*.cpp)
+else
+IceSSL_cppflags += -DICESSL_OPENSSL_API_EXPORTS
+IceSSL_excludes += $(wildcard src/IceSSL/SecureTransport*.cpp)
+endif
+
projects += $(project)
diff --git a/cpp/src/IceSSL/OpenSSLCertificateI.cpp b/cpp/src/IceSSL/OpenSSLCertificateI.cpp
new file mode 100644
index 00000000000..bbee2fdd0ca
--- /dev/null
+++ b/cpp/src/IceSSL/OpenSSLCertificateI.cpp
@@ -0,0 +1,572 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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/Plugin.h>
+#include <IceSSL/OpenSSL.h>
+#include <IceSSL/CertificateI.h>
+#include <IceSSL/OpenSSLUtil.h>
+#include <IceSSL/RFC2253.h>
+
+#include <IceUtil/Mutex.h>
+#include <IceUtil/MutexPtrLock.h>
+
+#include <openssl/x509v3.h>
+#include <openssl/pem.h>
+
+using namespace IceSSL;
+using namespace std;
+
+//
+// Avoid old style cast warnings from OpenSSL macros
+//
+#if defined(__GNUC__)
+# pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+#ifdef __SUNPRO_CC
+
+//
+// The call to sk_GENERAL_NAME_pop_free fails to compile if we don't
+// remove the extern "C" vs non extern "C" check with the macro below:
+//
+
+extern "C" typedef void (*FreeFunc)(void*);
+
+#undef CHECKED_SK_FREE_FUNC
+#define CHECKED_SK_FREE_FUNC(type, p) \
+ (FreeFunc) (p)
+
+#endif
+
+namespace
+{
+
+static string
+convertX509NameToString(X509_name_st* name)
+{
+ BIO* out = BIO_new(BIO_s_mem());
+ X509_NAME_print_ex(out, name, 0, XN_FLAG_RFC2253);
+ BUF_MEM* p;
+ BIO_get_mem_ptr(out, &p);
+ string result = string(p->data, p->length);
+ BIO_free(out);
+ return result;
+}
+
+static vector<pair<int, string> >
+convertGeneralNames(GENERAL_NAMES* gens)
+{
+ vector<pair<int, string> > alt;
+ if (gens == 0)
+ {
+ return alt;
+ }
+ for (int i = 0; i < sk_GENERAL_NAME_num(gens); ++i)
+ {
+ GENERAL_NAME* gen = sk_GENERAL_NAME_value(gens, i);
+ pair<int, string> p;
+ p.first = gen->type;
+ switch (gen->type)
+ {
+ case GEN_EMAIL:
+ {
+ ASN1_IA5STRING* str = gen->d.rfc822Name;
+ if (str && str->type == V_ASN1_IA5STRING && str->data && str->length > 0)
+ {
+ p.second = string(reinterpret_cast<const char*>(str->data), str->length);
+ }
+ break;
+ }
+ case GEN_DNS:
+ {
+ ASN1_IA5STRING* str = gen->d.dNSName;
+ if (str && str->type == V_ASN1_IA5STRING && str->data && str->length > 0)
+ {
+ p.second = string(reinterpret_cast<const char*>(str->data), str->length);
+ }
+ break;
+ }
+ case GEN_DIRNAME:
+ {
+ p.second = convertX509NameToString(gen->d.directoryName);
+ break;
+ }
+ case GEN_URI:
+ {
+ ASN1_IA5STRING* str = gen->d.uniformResourceIdentifier;
+ if (str && str->type == V_ASN1_IA5STRING && str->data && str->length > 0)
+ {
+ p.second = string(reinterpret_cast<const char*>(str->data), str->length);
+ }
+ break;
+ }
+ case GEN_IPADD:
+ {
+ ASN1_OCTET_STRING* addr = gen->d.iPAddress;
+ // TODO: Support IPv6 someday.
+ if (addr && addr->type == V_ASN1_OCTET_STRING && addr->data && addr->length == 4)
+ {
+ ostringstream ostr;
+ for (int j = 0; j < 4; ++j)
+ {
+ if (j > 0)
+ {
+ ostr << '.';
+ }
+ ostr << static_cast<int>(addr->data[j]);
+ }
+ p.second = ostr.str();
+ }
+ break;
+ }
+ case GEN_OTHERNAME:
+ case GEN_EDIPARTY:
+ case GEN_X400:
+ case GEN_RID:
+ {
+ //
+ // TODO: These types are not supported. If the user wants
+ // them, they have to get at the certificate data. Another
+ // alternative is to DER encode the data (as the Java
+ // certificate does).
+ //
+ break;
+ }
+ }
+ alt.push_back(p);
+ }
+ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+ return alt;
+}
+
+class DistinguishedNameI : public IceSSL::DistinguishedName
+{
+public:
+
+ DistinguishedNameI(X509_name_st* name) :
+ IceSSL::DistinguishedName(IceSSL::RFC2253::parseStrict(convertX509NameToString(name)))
+ {
+ unescape();
+ }
+
+};
+
+IceUtil::Mutex* mut = 0;
+
+class Init
+{
+public:
+
+ Init()
+ {
+ mut = new IceUtil::Mutex;
+ }
+
+ ~Init()
+ {
+ delete mut;
+ mut = 0;
+ }
+};
+
+Init init;
+
+#ifdef ICE_CPP11_MAPPING
+chrono::system_clock::time_point
+#else
+static IceUtil::Time
+#endif
+ASMUtcTimeToTime(const ASN1_UTCTIME* s)
+{
+ struct tm tm;
+ int offset;
+
+ memset(&tm, '\0', sizeof tm);
+
+# define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
+ tm.tm_year = g2(s->data);
+ if(tm.tm_year < 50)
+ {
+ tm.tm_year += 100;
+ }
+ tm.tm_mon = g2(s->data + 2) - 1;
+ tm.tm_mday = g2(s->data + 4);
+ tm.tm_hour = g2(s->data + 6);
+ tm.tm_min = g2(s->data + 8);
+ tm.tm_sec = g2(s->data + 10);
+ if(s->data[12] == 'Z')
+ {
+ offset = 0;
+ }
+ else
+ {
+ offset = g2(s->data + 13) * 60 + g2(s->data + 15);
+ if(s->data[12] == '-')
+ {
+ offset = -offset;
+ }
+ }
+# undef g2
+
+ //
+ // If timegm was on all systems this code could be
+ // return IceUtil::Time::seconds(timegm(&tm) - offset*60);
+ //
+ // Windows doesn't support the re-entrant _r versions.
+ //
+#if defined(_MSC_VER)
+# pragma warning(disable:4996) // localtime is depercated
+#endif
+ time_t tzone;
+ {
+ IceUtilInternal::MutexPtrLock<IceUtil::Mutex> sync(mut);
+ time_t now = time(0);
+ tzone = mktime(localtime(&now)) - mktime(gmtime(&now));
+ }
+#if defined(_MSC_VER)
+# pragma warning(default:4996) // localtime is depercated
+#endif
+
+ IceUtil::Time time = IceUtil::Time::seconds(mktime(&tm) - offset * 60 + tzone);
+
+#ifdef ICE_CPP11_MAPPING
+ return chrono::system_clock::time_point(chrono::microseconds(time.toMicroSeconds()));
+#else
+ return time;
+#endif
+}
+
+class OpenSSLX509ExtensionI : public IceSSL::X509Extension
+{
+
+public:
+
+ OpenSSLX509ExtensionI(struct X509_extension_st*, const string&, const IceSSL::OpenSSL::CertificatePtr&);
+ virtual bool isCritical() const;
+ virtual string getOID() const;
+ virtual vector<Ice::Byte> getData() const;
+
+private:
+
+ struct X509_extension_st* _extension;
+ string _oid;
+ IceSSL::OpenSSL::CertificatePtr _cert;
+};
+
+class OpenSSLCertificateI : public IceSSL::OpenSSL::Certificate,
+ public CertificateI,
+ public IceUtil::Mutex
+{
+public:
+
+ OpenSSLCertificateI(x509_st*);
+ ~OpenSSLCertificateI();
+
+ virtual bool operator==(const IceSSL::Certificate&) const;
+
+ virtual vector<Ice::Byte> getAuthorityKeyIdentifier() const;
+ virtual vector<Ice::Byte> getSubjectKeyIdentifier() const;
+ virtual bool verify(const IceSSL::CertificatePtr&) const;
+ virtual string encode() const;
+
+# ifdef ICE_CPP11_MAPPING
+ virtual chrono::system_clock::time_point getNotAfter() const;
+ virtual chrono::system_clock::time_point getNotBefore() const;
+# else
+ virtual IceUtil::Time getNotAfter() const;
+ virtual IceUtil::Time getNotBefore() const;
+# endif
+ virtual string getSerialNumber() const;
+ virtual IceSSL::DistinguishedName getIssuerDN() const;
+ virtual vector<pair<int, string> > getIssuerAlternativeNames() const;
+ virtual IceSSL::DistinguishedName getSubjectDN() const;
+ virtual vector<pair<int, string> > getSubjectAlternativeNames() const;
+ virtual int getVersion() const;
+ virtual x509_st* getCert() const;
+
+protected:
+
+ virtual void loadX509Extensions() const;
+
+private:
+
+ x509_st* _cert;
+};
+
+} // end anonymous namespace
+
+OpenSSLX509ExtensionI::OpenSSLX509ExtensionI(struct X509_extension_st* extension, const string& oid,
+ const IceSSL::OpenSSL::CertificatePtr& cert) :
+ _extension(extension),
+ _oid(oid),
+ _cert(cert)
+{
+}
+
+bool
+OpenSSLX509ExtensionI::isCritical() const
+{
+ return X509_EXTENSION_get_critical(_extension) == 1;
+}
+
+string
+OpenSSLX509ExtensionI::getOID() const
+{
+ return _oid;
+}
+
+vector<Ice::Byte>
+OpenSSLX509ExtensionI::getData() const
+{
+ vector<Ice::Byte> data;
+ ASN1_OCTET_STRING* buffer = X509_EXTENSION_get_data(_extension);
+ assert(buffer);
+ data.resize(buffer->length);
+ memcpy(&data[0], buffer->data, buffer->length);
+ return data;
+}
+
+//
+// The caller is responsible for incrementing the reference count.
+//
+OpenSSLCertificateI::OpenSSLCertificateI(x509_st* cert) : _cert(cert)
+{
+ if(!_cert)
+ {
+ throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Invalid certificate reference");
+ }
+}
+
+OpenSSLCertificateI::~OpenSSLCertificateI()
+{
+ if(_cert)
+ {
+ X509_free(_cert);
+ }
+}
+
+bool
+OpenSSLCertificateI::operator==(const IceSSL::Certificate& r) const
+{
+ const OpenSSLCertificateI* p = dynamic_cast<const OpenSSLCertificateI*>(&r);
+ if(!p)
+ {
+ return false;
+ }
+
+ return X509_cmp(_cert, p->_cert) == 0;
+}
+
+vector<Ice::Byte>
+OpenSSLCertificateI::getAuthorityKeyIdentifier() const
+{
+ vector<Ice::Byte> keyid;
+ int index = X509_get_ext_by_NID(_cert, NID_authority_key_identifier, -1);
+ if(index >= 0)
+ {
+ X509_EXTENSION* ext = X509_get_ext(_cert, index);
+ if(ext)
+ {
+ AUTHORITY_KEYID* decoded = (AUTHORITY_KEYID*)X509V3_EXT_d2i(ext);
+ if(!decoded)
+ {
+ throw IceSSL::CertificateEncodingException(__FILE__, __LINE__, "the extension could not be decoded");
+ }
+ keyid.resize(decoded->keyid->length);
+ memcpy(&keyid[0], decoded->keyid->data, decoded->keyid->length);
+ AUTHORITY_KEYID_free(decoded);
+ }
+ }
+ return keyid;
+}
+
+vector<Ice::Byte>
+OpenSSLCertificateI::getSubjectKeyIdentifier() const
+{
+ vector<Ice::Byte> keyid;
+ int index = X509_get_ext_by_NID(_cert, NID_subject_key_identifier, -1);
+ if(index >= 0)
+ {
+ X509_EXTENSION* ext = X509_get_ext(_cert, index);
+ if(ext)
+ {
+ ASN1_OCTET_STRING* decoded = static_cast<ASN1_OCTET_STRING*>(X509V3_EXT_d2i(ext));
+ if(!decoded)
+ {
+ throw IceSSL::CertificateEncodingException(__FILE__, __LINE__, "the extension could not be decoded");
+ }
+ keyid.resize(decoded->length);
+ memcpy(&keyid[0], decoded->data, decoded->length);
+ ASN1_OCTET_STRING_free(decoded);
+ }
+ }
+ return keyid;
+}
+
+bool
+OpenSSLCertificateI::verify(const IceSSL::CertificatePtr& cert) const
+{
+ OpenSSLCertificateI* c = dynamic_cast<OpenSSLCertificateI*>(cert.get());
+ if(c)
+ {
+ return X509_verify(_cert, X509_get_pubkey(c->_cert)) > 0;
+ }
+ return false;
+}
+
+string
+OpenSSLCertificateI::encode() const
+{
+ BIO* out = BIO_new(BIO_s_mem());
+ int i = PEM_write_bio_X509_AUX(out, _cert);
+ if(i <= 0)
+ {
+ BIO_free(out);
+ throw IceSSL::CertificateEncodingException(__FILE__, __LINE__, IceSSL::OpenSSL::getSslErrors(false));
+ }
+ BUF_MEM* p;
+ BIO_get_mem_ptr(out, &p);
+ string result = string(p->data, p->length);
+ BIO_free(out);
+ return result;
+}
+
+# ifdef ICE_CPP11_MAPPING
+chrono::system_clock::time_point
+# else
+IceUtil::Time
+# endif
+OpenSSLCertificateI::getNotAfter() const
+{
+ return ASMUtcTimeToTime(X509_get_notAfter(_cert));
+}
+
+# ifdef ICE_CPP11_MAPPING
+chrono::system_clock::time_point
+# else
+IceUtil::Time
+# endif
+OpenSSLCertificateI::getNotBefore() const
+{
+ return ASMUtcTimeToTime(X509_get_notBefore(_cert));
+}
+
+string
+OpenSSLCertificateI::getSerialNumber() const
+{
+ BIGNUM* bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(_cert), 0);
+ char* dec = BN_bn2dec(bn);
+ string result = dec;
+ OPENSSL_free(dec);
+ BN_free(bn);
+ return result;
+}
+
+IceSSL::DistinguishedName
+OpenSSLCertificateI::getIssuerDN() const
+{
+ return IceSSL::DistinguishedName(IceSSL::RFC2253::parseStrict(convertX509NameToString(X509_get_issuer_name(_cert))));
+}
+
+vector<pair<int, string> >
+OpenSSLCertificateI::getIssuerAlternativeNames() const
+{
+ return convertGeneralNames(reinterpret_cast<GENERAL_NAMES*>(X509_get_ext_d2i(_cert, NID_issuer_alt_name, 0, 0)));
+}
+
+IceSSL::DistinguishedName
+OpenSSLCertificateI::getSubjectDN() const
+{
+ return IceSSL::DistinguishedName(IceSSL::RFC2253::parseStrict(convertX509NameToString(X509_get_subject_name(_cert))));
+}
+
+vector<pair<int, string> >
+OpenSSLCertificateI::getSubjectAlternativeNames() const
+{
+ return convertGeneralNames(reinterpret_cast<GENERAL_NAMES*>(X509_get_ext_d2i(_cert, NID_subject_alt_name, 0, 0)));
+}
+
+int
+OpenSSLCertificateI::getVersion() const
+{
+ return static_cast<int>(X509_get_version(_cert));
+}
+
+x509_st*
+OpenSSLCertificateI::getCert() const
+{
+ return _cert;
+}
+
+void
+OpenSSLCertificateI::loadX509Extensions() const
+{
+ IceUtil::Mutex::Lock sync(*this);
+ if(_extensions.empty())
+ {
+ int sz = X509_get_ext_count(_cert);
+ for(int i = 0; i < sz; i++)
+ {
+ X509_EXTENSION* ext = X509_get_ext(_cert, i);
+ ASN1_OBJECT* obj = X509_EXTENSION_get_object(ext);
+ string oid;
+ //
+ // According to OBJ_obj2txt doc a buffer of length 80 should be more than enough to
+ // handle any OID encountered in practice.
+ //
+ int len = 80;
+ oid.resize(len);
+ len = OBJ_obj2txt(&oid[0], len, obj, 1);
+ oid.resize(len);
+ _extensions.push_back(ICE_DYNAMIC_CAST(IceSSL::X509Extension,
+ ICE_MAKE_SHARED(OpenSSLX509ExtensionI, ext, oid,
+ ICE_DYNAMIC_CAST(IceSSL::OpenSSL::Certificate, ICE_SHARED_FROM_CONST_THIS(OpenSSLCertificateI)))));
+ }
+ }
+}
+
+IceSSL::OpenSSL::CertificatePtr
+IceSSL::OpenSSL::Certificate::create(x509_st* cert)
+{
+ return ICE_MAKE_SHARED(OpenSSLCertificateI, cert);
+}
+
+IceSSL::OpenSSL::CertificatePtr
+IceSSL::OpenSSL::Certificate::load(const std::string& file)
+{
+ BIO* cert = BIO_new(BIO_s_file());
+ if(BIO_read_filename(cert, file.c_str()) <= 0)
+ {
+ BIO_free(cert);
+ throw CertificateReadException(__FILE__, __LINE__, "error opening file");
+ }
+
+ x509_st* x = PEM_read_bio_X509_AUX(cert, ICE_NULLPTR, ICE_NULLPTR, ICE_NULLPTR);
+ if(x == ICE_NULLPTR)
+ {
+ BIO_free(cert);
+ throw CertificateReadException(__FILE__, __LINE__, "error reading file:\n" + getSslErrors(false));
+ }
+ BIO_free(cert);
+ return ICE_MAKE_SHARED(OpenSSLCertificateI, x);
+}
+
+IceSSL::OpenSSL::CertificatePtr
+IceSSL::OpenSSL::Certificate::decode(const std::string& encoding)
+{
+ BIO *cert = BIO_new_mem_buf(static_cast<void*>(const_cast<char*>(&encoding[0])), static_cast<int>(encoding.size()));
+ x509_st* x = PEM_read_bio_X509_AUX(cert, ICE_NULLPTR, ICE_NULLPTR, ICE_NULLPTR);
+ if(x == ICE_NULLPTR)
+ {
+ BIO_free(cert);
+ throw CertificateEncodingException(__FILE__, __LINE__, getSslErrors(false));
+ }
+ BIO_free(cert);
+ return ICE_MAKE_SHARED(OpenSSLCertificateI, x);
+}
diff --git a/cpp/src/IceSSL/OpenSSLEngine.cpp b/cpp/src/IceSSL/OpenSSLEngine.cpp
index 884271deade..950f334484b 100644
--- a/cpp/src/IceSSL/OpenSSLEngine.cpp
+++ b/cpp/src/IceSSL/OpenSSLEngine.cpp
@@ -9,7 +9,9 @@
#include <IceSSL/Config.h>
-#include <IceSSL/SSLEngine.h>
+#include <IceSSL/OpenSSLEngineF.h>
+#include <IceSSL/OpenSSLEngine.h>
+#include <IceSSL/OpenSSLTransceiverI.h>
#include <IceSSL/Util.h>
#include <IceSSL/TrustManager.h>
@@ -24,8 +26,6 @@
#include <IceUtil/MutexPtrLock.h>
#include <IceUtil/FileUtil.h>
-#ifdef ICE_USE_OPENSSL
-
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
@@ -37,6 +37,7 @@ using namespace IceSSL;
namespace
{
+
IceUtil::Mutex* staticMutex = 0;
int instanceCount = 0;
bool initOpenSSL = false;
@@ -93,23 +94,25 @@ IceSSL_opensslThreadIdCallback()
# error "Unknown platform"
# endif
}
+
#endif
int
IceSSL_opensslPasswordCallback(char* buf, int size, int flag, void* userData)
{
- OpenSSLEngine* p = reinterpret_cast<OpenSSLEngine*>(userData);
+ OpenSSL::SSLEngine* p = reinterpret_cast<OpenSSL::SSLEngine*>(userData);
+ assert(p);
string passwd = p->password(flag == 1);
int sz = static_cast<int>(passwd.size());
if(sz > size)
{
sz = size - 1;
}
-# if defined(_WIN32)
+#if defined(_WIN32)
strncpy_s(buf, size, passwd.c_str(), sz);
-# else
+#else
strncpy(buf, passwd.c_str(), sz);
-# endif
+#endif
buf[sz] = '\0';
for(string::iterator i = passwd.begin(); i != passwd.end(); ++i)
@@ -120,7 +123,7 @@ IceSSL_opensslPasswordCallback(char* buf, int size, int flag, void* userData)
return sz;
}
-# ifndef OPENSSL_NO_DH
+#ifndef OPENSSL_NO_DH
DH*
IceSSL_opensslDHCallback(SSL* ssl, int /*isExport*/, int keyLength)
{
@@ -129,10 +132,10 @@ IceSSL_opensslDHCallback(SSL* ssl, int /*isExport*/, int keyLength)
# else
SSL_CTX* ctx = ssl->ctx;
# endif
- OpenSSLEngine* p = reinterpret_cast<OpenSSLEngine*>(SSL_CTX_get_ex_data(ctx, 0));
+ OpenSSL::SSLEngine* p = reinterpret_cast<OpenSSL::SSLEngine*>(SSL_CTX_get_ex_data(ctx, 0));
return p->dhParams(keyLength);
}
-# endif
+#endif
}
@@ -188,11 +191,14 @@ passwordError()
}
-IceUtil::Shared* IceSSL::upCast(IceSSL::OpenSSLEngine* p) { return p; }
+IceUtil::Shared*
+OpenSSL::upCast(OpenSSL::SSLEngine* p)
+{
+ return p;
+}
-OpenSSLEngine::OpenSSLEngine(const CommunicatorPtr& communicator) :
- SSLEngine(communicator),
- _initialized(false),
+OpenSSL::SSLEngine::SSLEngine(const CommunicatorPtr& communicator) :
+ IceSSL::SSLEngine(communicator),
_ctx(0)
{
__setNoDelete(true);
@@ -292,7 +298,7 @@ OpenSSLEngine::OpenSSLEngine(const CommunicatorPtr& communicator) :
}
}
}
-# if !defined (_WIN32) && !defined (OPENSSL_NO_EGD)
+#if !defined (_WIN32) && !defined (OPENSSL_NO_EGD)
//
// The Entropy Gathering Daemon (EGD) is not available on Windows.
// The file should be a Unix domain socket for the daemon.
@@ -306,7 +312,7 @@ OpenSSLEngine::OpenSSLEngine(const CommunicatorPtr& communicator) :
"IceSSL: EGD failure using file " + entropyDaemon);
}
}
-# endif
+#endif
if(!RAND_status())
{
getLogger()->warning("IceSSL: insufficient data to initialize PRNG");
@@ -318,18 +324,18 @@ OpenSSLEngine::OpenSSLEngine(const CommunicatorPtr& communicator) :
{
getLogger()->warning("IceSSL: ignoring IceSSL.Random because OpenSSL initialization is disabled");
}
-# ifndef _WIN32
+#ifndef _WIN32
else if(!properties->getProperty("IceSSL.EntropyDaemon").empty())
{
getLogger()->warning("IceSSL: ignoring IceSSL.EntropyDaemon because OpenSSL initialization is disabled");
}
-# endif
+#endif
}
}
__setNoDelete(false);
}
-OpenSSLEngine::~OpenSSLEngine()
+OpenSSL::SSLEngine::~SSLEngine()
{
//
// OpenSSL 1.1.0 remove the need for library initialization and cleanup.
@@ -360,15 +366,8 @@ OpenSSLEngine::~OpenSSLEngine()
#endif
}
-bool
-OpenSSLEngine::initialized() const
-{
- IceUtil::Mutex::Lock lock(_mutex);
- return _initialized;
-}
-
void
-OpenSSLEngine::initialize()
+OpenSSL::SSLEngine::initialize()
{
IceUtil::Mutex::Lock lock(_mutex);
if(_initialized)
@@ -378,7 +377,7 @@ OpenSSLEngine::initialize()
try
{
- SSLEngine::initialize();
+ IceSSL::SSLEngine::initialize();
const string propPrefix = "IceSSL.";
PropertiesPtr properties = communicator()->getProperties();
@@ -549,18 +548,12 @@ OpenSSLEngine::initialize()
// First we try to load the certificate using PKCS12 format if that fails
// we fallback to PEM format.
//
- FILE* f = fopen(file.c_str(), "rb");
- if(!f)
- {
- throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: unable to load certificate chain from file " + file + "\n" +
- IceUtilInternal::lastErrorToString());
- }
-
+ vector<char> buffer;
+ readFile(file, buffer);
int success = 0;
- PKCS12* p12 = d2i_PKCS12_fp(f, 0);
- fclose(f);
+ const unsigned char* b = const_cast<const unsigned char*>(reinterpret_cast<unsigned char*>(&buffer[0]));
+ PKCS12* p12 = d2i_PKCS12(0, &b, static_cast<long>(buffer.size()));
if(p12)
{
EVP_PKEY* key = 0;
@@ -766,11 +759,11 @@ OpenSSLEngine::initialize()
// Diffie Hellman configuration.
//
{
-# ifndef OPENSSL_NO_DH
+#ifndef OPENSSL_NO_DH
_dhParams = new DHParams;
SSL_CTX_set_options(_ctx, SSL_OP_SINGLE_DH_USE);
SSL_CTX_set_tmp_dh_callback(_ctx, IceSSL_opensslDHCallback);
-# endif
+#endif
//
// Properties have the following form:
//
@@ -780,9 +773,9 @@ OpenSSLEngine::initialize()
PropertyDict d = properties->getPropertiesForPrefix(dhPrefix);
if(!d.empty())
{
-# ifdef OPENSSL_NO_DH
+#ifdef OPENSSL_NO_DH
getLogger()->warning("IceSSL: OpenSSL is not configured for Diffie Hellman");
-# else
+#else
for(PropertyDict::iterator p = d.begin(); p != d.end(); ++p)
{
string s = p->first.substr(dhPrefix.size());
@@ -804,7 +797,7 @@ OpenSSLEngine::initialize()
}
}
}
-# endif
+#endif
}
}
@@ -886,7 +879,7 @@ OpenSSLEngine::initialize()
}
void
-OpenSSLEngine::context(SSL_CTX* context)
+OpenSSL::SSLEngine::context(SSL_CTX* context)
{
if(initialized())
{
@@ -898,19 +891,19 @@ OpenSSLEngine::context(SSL_CTX* context)
}
SSL_CTX*
-OpenSSLEngine::context() const
+OpenSSL::SSLEngine::context() const
{
return _ctx;
}
string
-OpenSSLEngine::sslErrors() const
+OpenSSL::SSLEngine::sslErrors() const
{
return getSslErrors(securityTraceLevel() >= 1);
}
void
-OpenSSLEngine::destroy()
+OpenSSL::SSLEngine::destroy()
{
if(_ctx)
{
@@ -918,16 +911,38 @@ OpenSSLEngine::destroy()
}
}
-# ifndef OPENSSL_NO_DH
+void
+OpenSSL::SSLEngine::verifyPeer(const string& address, const NativeConnectionInfoPtr& info, const string& desc)
+{
+#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10002000L
+ //
+ // Peer hostname verification is new in OpenSSL 1.0.2 for older versions
+ // we use IceSSL build in hostname verification.
+ //
+ verifyPeerCertName(address, info);
+#endif
+ IceSSL::SSLEngine::verifyPeer(address, info, desc);
+}
+
+IceInternal::TransceiverPtr
+OpenSSL::SSLEngine::createTransceiver(const InstancePtr& instance,
+ const IceInternal::TransceiverPtr& delegate,
+ const string& hostOrAdapterName,
+ bool incoming)
+{
+ return new OpenSSL::TransceiverI(instance, delegate, hostOrAdapterName, incoming);
+}
+
+#ifndef OPENSSL_NO_DH
DH*
-OpenSSLEngine::dhParams(int keyLength)
+OpenSSL::SSLEngine::dhParams(int keyLength)
{
return _dhParams->get(keyLength);
}
-# endif
+#endif
int
-OpenSSLEngine::parseProtocols(const StringSeq& protocols) const
+OpenSSL::SSLEngine::parseProtocols(const StringSeq& protocols) const
{
int v = 0;
@@ -960,7 +975,7 @@ OpenSSLEngine::parseProtocols(const StringSeq& protocols) const
}
SSL_METHOD*
-OpenSSLEngine::getMethod(int /*protocols*/)
+OpenSSL::SSLEngine::getMethod(int /*protocols*/)
{
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
SSL_METHOD* meth = const_cast<SSL_METHOD*>(TLS_method());
@@ -984,7 +999,7 @@ OpenSSLEngine::getMethod(int /*protocols*/)
}
void
-OpenSSLEngine::setOptions(int protocols)
+OpenSSL::SSLEngine::setOptions(int protocols)
{
long opts = SSL_OP_NO_SSLv2; // SSLv2 is not supported.
if(!(protocols & SSLv3))
@@ -995,7 +1010,7 @@ OpenSSLEngine::setOptions(int protocols)
{
opts |= SSL_OP_NO_TLSv1;
}
-# ifdef SSL_OP_NO_TLSv1_1
+#ifdef SSL_OP_NO_TLSv1_1
if(!(protocols & TLSv1_1))
{
opts |= SSL_OP_NO_TLSv1_1;
@@ -1007,14 +1022,13 @@ OpenSSLEngine::setOptions(int protocols)
opts |= 0x10000000L; // New value of SSL_OP_NO_TLSv1_1.
}
}
-# endif
-# ifdef SSL_OP_NO_TLSv1_2
+#endif
+
+#ifdef SSL_OP_NO_TLSv1_2
if(!(protocols & TLSv1_2))
{
opts |= SSL_OP_NO_TLSv1_2;
}
-# endif
+#endif
SSL_CTX_set_options(_ctx, opts);
}
-
-#endif // ICESSL_USE_OPENSSL
diff --git a/cpp/src/IceSSL/OpenSSLEngine.h b/cpp/src/IceSSL/OpenSSLEngine.h
new file mode 100644
index 00000000000..5fc92c930c8
--- /dev/null
+++ b/cpp/src/IceSSL/OpenSSLEngine.h
@@ -0,0 +1,64 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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 ICESSL_OPENSSL_ENGINE_H
+#define ICESSL_OPENSSL_ENGINE_H
+
+#include <IceSSL/SSLEngine.h>
+#include <IceSSL/InstanceF.h>
+#include <IceSSL/OpenSSLUtil.h>
+
+#include <Ice/BuiltinSequences.h>
+
+namespace IceSSL
+{
+
+namespace OpenSSL
+{
+
+class SSLEngine : public IceSSL::SSLEngine
+{
+public:
+
+ SSLEngine(const Ice::CommunicatorPtr&);
+ ~SSLEngine();
+
+ virtual void initialize();
+ virtual void destroy();
+ virtual void verifyPeer(const std::string&, const IceSSL::NativeConnectionInfoPtr&, const std::string&);
+ virtual IceInternal::TransceiverPtr
+ createTransceiver(const IceSSL::InstancePtr&, const IceInternal::TransceiverPtr&, const std::string&, bool);
+
+#ifndef OPENSSL_NO_DH
+ DH* dhParams(int);
+#endif
+
+ SSL_CTX* context() const;
+ void context(SSL_CTX*);
+ std::string sslErrors() const;
+
+private:
+
+ SSL_METHOD* getMethod(int);
+ void setOptions(int);
+ enum Protocols { SSLv3 = 0x01, TLSv1_0 = 0x02, TLSv1_1 = 0x04, TLSv1_2 = 0x08 };
+ int parseProtocols(const Ice::StringSeq&) const;
+
+ SSL_CTX* _ctx;
+
+#ifndef OPENSSL_NO_DH
+ IceSSL::OpenSSL::DHParamsPtr _dhParams;
+#endif
+};
+
+} // OpenSSL namespace end
+
+} // IceSSL namespace endif
+
+#endif
diff --git a/cpp/src/IceSSL/OpenSSLEngineF.h b/cpp/src/IceSSL/OpenSSLEngineF.h
new file mode 100644
index 00000000000..260f6954945
--- /dev/null
+++ b/cpp/src/IceSSL/OpenSSLEngineF.h
@@ -0,0 +1,32 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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 ICESSL_OPENSSL_ENGINE_F_H
+#define ICESSL_OPENSSL_ENGINE_F_H
+
+#include <IceUtil/Shared.h>
+#include <Ice/Handle.h>
+
+#include <IceSSL/OpenSSL.h>
+
+namespace IceSSL
+{
+
+namespace OpenSSL
+{
+
+class SSLEngine;
+ICESSL_OPENSSL_API IceUtil::Shared* upCast(SSLEngine*);
+typedef IceInternal::Handle<SSLEngine> SSLEnginePtr;
+
+} // OpenSSL namespace end
+
+} // IceSSL namespace end
+
+#endif
diff --git a/cpp/src/IceSSL/OpenSSLPluginI.cpp b/cpp/src/IceSSL/OpenSSLPluginI.cpp
new file mode 100644
index 00000000000..7328dfbf41d
--- /dev/null
+++ b/cpp/src/IceSSL/OpenSSLPluginI.cpp
@@ -0,0 +1,130 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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/PluginI.h>
+#include <IceSSL/OpenSSL.h>
+#include <IceSSL/OpenSSLEngine.h>
+
+#include <Ice/Initialize.h>
+
+using namespace std;
+
+namespace
+{
+
+class PluginI : public IceSSL::PluginI,
+ public IceSSL::OpenSSL::Plugin
+{
+public:
+
+ PluginI(const Ice::CommunicatorPtr&);
+
+ virtual string getEngineName() const;
+ virtual Ice::Long getEngineVersion() const;
+ virtual IceSSL::CertificatePtr create(x509_st*) const;
+ virtual IceSSL::CertificatePtr load(const std::string&) const;
+ virtual IceSSL::CertificatePtr decode(const std::string&) const;
+ virtual void setContext(SSL_CTX*);
+ virtual SSL_CTX* getContext();
+};
+
+} // anonymous namespace end
+
+//
+// Plugin implementation.
+//
+PluginI::PluginI(const Ice::CommunicatorPtr& com) :
+ IceSSL::PluginI(com, new IceSSL::OpenSSL::SSLEngine(com))
+{
+}
+
+string
+PluginI::getEngineName() const
+{
+ ostringstream os;
+ os << "OpenSSLEngine@" << SSLeay_version(SSLEAY_VERSION);
+ return os.str();
+}
+
+Ice::Long
+PluginI::getEngineVersion() const
+{
+ return SSLeay();
+}
+
+IceSSL::CertificatePtr
+PluginI::create(x509_st* cert) const
+{
+ return IceSSL::OpenSSL::Certificate::create(cert);
+}
+
+IceSSL::CertificatePtr
+PluginI::load(const std::string& file) const
+{
+ return IceSSL::OpenSSL::Certificate::load(file);
+}
+
+IceSSL::CertificatePtr
+PluginI::decode(const std::string& encoding) const
+{
+ return IceSSL::OpenSSL::Certificate::load(encoding);
+}
+
+void
+PluginI::setContext(SSL_CTX* context)
+{
+ IceSSL::OpenSSL::SSLEngine* engine = dynamic_cast<IceSSL::OpenSSL::SSLEngine*>(_engine.get());
+ assert(engine);
+ engine->context(context);
+}
+
+SSL_CTX*
+PluginI::getContext()
+{
+ IceSSL::OpenSSL::SSLEngine* engine = dynamic_cast<IceSSL::OpenSSL::SSLEngine*>(_engine.get());
+ assert(engine);
+ return engine->context();
+}
+
+#ifdef _WIN32
+//
+// Plug-in factory function.
+//
+extern "C" ICESSL_OPENSSL_API Ice::Plugin*
+createIceSSLOpenSSL(const Ice::CommunicatorPtr& communicator, const string& /*name*/, const Ice::StringSeq& /*args*/)
+{
+ return new PluginI(communicator);
+}
+
+#else
+
+extern "C" ICESSL_API Ice::Plugin*
+createIceSSL(const Ice::CommunicatorPtr& communicator, const string& /*name*/, const Ice::StringSeq& /*args*/)
+{
+ return new PluginI(communicator);
+}
+
+//
+// The following functions are defined only when OpenSSL is the default
+// implementation. In Windows the default implementation is always
+// SChannel.
+//
+IceSSL::CertificatePtr
+IceSSL::Certificate::load(const std::string& file)
+{
+ return IceSSL::OpenSSL::Certificate::load(file);
+}
+
+IceSSL::CertificatePtr
+IceSSL::Certificate::decode(const std::string& encoding)
+{
+ return IceSSL::OpenSSL::Certificate::decode(encoding);
+}
+
+#endif
diff --git a/cpp/src/IceSSL/OpenSSLTransceiverI.cpp b/cpp/src/IceSSL/OpenSSLTransceiverI.cpp
index 0f8359f3638..ee10d229f81 100644
--- a/cpp/src/IceSSL/OpenSSLTransceiverI.cpp
+++ b/cpp/src/IceSSL/OpenSSLTransceiverI.cpp
@@ -8,6 +8,7 @@
// **********************************************************************
#include <IceSSL/OpenSSLTransceiverI.h>
+#include <IceSSL/OpenSSLEngine.h>
#include <IceUtil/Mutex.h>
#include <IceUtil/MutexPtrLock.h>
@@ -22,8 +23,7 @@
#include <Ice/LocalException.h>
#include <Ice/Network.h>
-#ifdef ICE_USE_OPENSSL
-
+#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/bio.h>
@@ -32,7 +32,7 @@ using namespace Ice;
using namespace IceSSL;
//
-// BUGFIX: an openssl bug that affects OpensSSL < 1.0.0k
+// BUGFIX: an openssl bug that affects OpenSSL < 1.0.0k
// could cause a deadlock when decoding public keys.
//
// See: http://cvs.openssl.org/chngview?cn=22569
@@ -71,20 +71,20 @@ int
IceSSL_opensslVerifyCallback(int ok, X509_STORE_CTX* ctx)
{
SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
- TransceiverI* p = reinterpret_cast<TransceiverI*>(SSL_get_ex_data(ssl, 0));
+ OpenSSL::TransceiverI* p = reinterpret_cast<OpenSSL::TransceiverI*>(SSL_get_ex_data(ssl, 0));
return p->verifyCallback(ok, ctx);
}
}
IceInternal::NativeInfoPtr
-IceSSL::TransceiverI::getNativeInfo()
+OpenSSL::TransceiverI::getNativeInfo()
{
return _delegate->getNativeInfo();
}
IceInternal::SocketOperation
-IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::Buffer& writeBuffer)
+OpenSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::Buffer& writeBuffer)
{
if(!_connected)
{
@@ -108,7 +108,23 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
return IceInternal::SocketOperationRead;
}
+#ifdef ICE_USE_IOCP
+ _maxSendPacketSize = std::max(512, IceInternal::getSendBufferSize(fd));
+ _maxRecvPacketSize = std::max(512, IceInternal::getRecvBufferSize(fd));
+ BIO* bio;
+ _sentBytes = 0;
+ if(!BIO_new_bio_pair(&bio, _maxSendPacketSize, &_iocpBio, _maxRecvPacketSize))
+ {
+ bio = 0;
+ _iocpBio = 0;
+ }
+#else
+ //
+ // This static_cast is necessary due to 64bit windows. There SOCKET is a non-int type.
+ //
BIO* bio = BIO_new_socket(static_cast<int>(fd), 0);
+#endif
+
if(!bio)
{
SecurityException ex(__FILE__, __LINE__);
@@ -120,6 +136,10 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
if(!_ssl)
{
BIO_free(bio);
+#ifdef ICE_USE_IOCP
+ BIO_free(_iocpBio);
+ _iocpBio = 0;
+#endif
SecurityException ex(__FILE__, __LINE__);
ex.reason = "openssl failure";
throw ex;
@@ -182,7 +202,7 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
//
//
- // BUGFIX: an openssl bug that affects OpensSSL < 1.0.0k
+ // BUGFIX: an openssl bug that affects OpenSSL < 1.0.0k
// could cause a deadlock when decoding public keys.
//
// See: http://cvs.openssl.org/chngview?cn=22569
@@ -196,6 +216,18 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x100000bfL && !defined(LIBRESSL_VERSION_NUMBER)
sync.release();
#endif
+
+#ifdef ICE_USE_IOCP
+ if(BIO_ctrl_pending(_iocpBio))
+ {
+ if(!send())
+ {
+ return IceInternal::SocketOperationWrite;
+ }
+ continue;
+ }
+#endif
+
if(ret <= 0)
{
switch(SSL_get_error(_ssl, ret))
@@ -213,14 +245,27 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
}
case SSL_ERROR_WANT_READ:
{
+#ifdef ICE_USE_IOCP
+ if(receive())
+ {
+ continue;
+ }
+#endif
return IceInternal::SocketOperationRead;
}
case SSL_ERROR_WANT_WRITE:
{
+#ifdef ICE_USE_IOCP
+ if(send())
+ {
+ continue;
+ }
+#endif
return IceInternal::SocketOperationWrite;
}
case SSL_ERROR_SYSCALL:
{
+#ifndef ICE_USE_IOCP
if(IceInternal::interrupted())
{
break;
@@ -246,12 +291,10 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
ex.error = IceInternal::getSocketErrno();
throw ex;
}
- else
- {
- SocketException ex(__FILE__, __LINE__);
- ex.error = IceInternal::getSocketErrno();
- throw ex;
- }
+#endif
+ SocketException ex(__FILE__, __LINE__);
+ ex.error = IceInternal::getSocketErrno();
+ throw ex;
}
case SSL_ERROR_SSL:
{
@@ -327,7 +370,7 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
}
IceInternal::SocketOperation
-IceSSL::TransceiverI::closing(bool initiator, const Ice::LocalException&)
+OpenSSL::TransceiverI::closing(bool initiator, const Ice::LocalException&)
{
// If we are initiating the connection closure, wait for the peer
// to close the TCP/IP connection. Otherwise, close immediately.
@@ -335,7 +378,7 @@ IceSSL::TransceiverI::closing(bool initiator, const Ice::LocalException&)
}
void
-IceSSL::TransceiverI::close()
+OpenSSL::TransceiverI::close()
{
if(_ssl)
{
@@ -353,17 +396,35 @@ IceSSL::TransceiverI::close()
_ssl = 0;
}
+#ifdef ICE_USE_IOCP
+ if(_iocpBio)
+ {
+ BIO_free(_iocpBio);
+ _iocpBio = 0;
+ }
+#endif
+
_delegate->close();
}
IceInternal::SocketOperation
-IceSSL::TransceiverI::write(IceInternal::Buffer& buf)
+OpenSSL::TransceiverI::write(IceInternal::Buffer& buf)
{
if(!_connected)
{
return _delegate->write(buf);
}
+#ifdef ICE_USE_IOCP
+ if(_writeBuffer.i != _writeBuffer.b.end())
+ {
+ if(!send())
+ {
+ return IceInternal::SocketOperationWrite;
+ }
+ }
+#endif
+
if(buf.i == buf.b.end())
{
return IceInternal::SocketOperationNone;
@@ -372,11 +433,37 @@ IceSSL::TransceiverI::write(IceInternal::Buffer& buf)
//
// It's impossible for packetSize to be more than an Int.
//
- int packetSize = static_cast<int>(buf.b.end() - buf.i);
+ int packetSize =
+#ifdef ICE_USE_IOCP
+ std::min(static_cast<int>(_maxSendPacketSize), static_cast<int>(buf.b.end() - buf.i));
+#else
+ static_cast<int>(buf.b.end() - buf.i);
+#endif
while(buf.i != buf.b.end())
{
ERR_clear_error(); // Clear any spurious errors.
+#ifdef ICE_USE_IOCP
+ int ret;
+ if(_sentBytes)
+ {
+ ret = _sentBytes;
+ _sentBytes = 0;
+ }
+ else
+ {
+ ret = SSL_write(_ssl, reinterpret_cast<const void*>(&*buf.i), packetSize);
+ if(ret > 0)
+ {
+ if(!send())
+ {
+ _sentBytes = ret;
+ return IceInternal::SocketOperationWrite;
+ }
+ }
+ }
+#else
int ret = SSL_write(_ssl, reinterpret_cast<const void*>(&*buf.i), packetSize);
+#endif
if(ret <= 0)
{
switch(SSL_get_error(_ssl, ret))
@@ -397,10 +484,18 @@ IceSSL::TransceiverI::write(IceInternal::Buffer& buf)
}
case SSL_ERROR_WANT_WRITE:
{
+#ifdef ICE_USE_IOCP
+ if(send())
+ {
+ continue;
+ }
+#endif
return IceInternal::SocketOperationWrite;
}
case SSL_ERROR_SYSCALL:
{
+#ifndef ICE_USE_IOCP
+
if(IceInternal::interrupted())
{
continue;
@@ -417,7 +512,7 @@ IceSSL::TransceiverI::write(IceInternal::Buffer& buf)
assert(SSL_want_write(_ssl));
return IceInternal::SocketOperationWrite;
}
-
+#endif
if(IceInternal::connectionLost() || IceInternal::getSocketErrno() == 0)
{
ConnectionLostException ex(__FILE__, __LINE__);
@@ -447,18 +542,27 @@ IceSSL::TransceiverI::write(IceInternal::Buffer& buf)
packetSize = static_cast<int>(buf.b.end() - buf.i);
}
}
-
return IceInternal::SocketOperationNone;
}
IceInternal::SocketOperation
-IceSSL::TransceiverI::read(IceInternal::Buffer& buf)
+OpenSSL::TransceiverI::read(IceInternal::Buffer& buf)
{
if(!_connected)
{
return _delegate->read(buf);
}
+#ifdef ICE_USE_IOCP
+ if(_readBuffer.i != _readBuffer.b.end())
+ {
+ if(!receive())
+ {
+ return IceInternal::SocketOperationRead;
+ }
+ }
+#endif
+
//
// Note: We assume that OpenSSL doesn't read more SSL records than
// necessary to fill the requested data and that the sender sends
@@ -497,6 +601,12 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf)
}
case SSL_ERROR_WANT_READ:
{
+#ifdef ICE_USE_IOCP
+ if(receive())
+ {
+ continue;
+ }
+#endif
return IceInternal::SocketOperationRead;
}
case SSL_ERROR_WANT_WRITE:
@@ -506,6 +616,7 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf)
}
case SSL_ERROR_SYSCALL:
{
+#ifndef ICE_USE_IOCP
if(IceInternal::interrupted())
{
continue;
@@ -522,7 +633,7 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf)
assert(SSL_want_read(_ssl));
return IceInternal::SocketOperationRead;
}
-
+#endif
if(IceInternal::connectionLost() || IceInternal::getSocketErrno() == 0)
{
ConnectionLostException ex(__FILE__, __LINE__);
@@ -561,26 +672,108 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf)
return IceInternal::SocketOperationNone;
}
+#ifdef ICE_USE_IOCP
+
+bool
+OpenSSL::TransceiverI::startWrite(IceInternal::Buffer& buffer)
+{
+ if(!_connected)
+ {
+ return _delegate->startWrite(buffer);
+ }
+
+ assert(!_writeBuffer.b.empty() && _writeBuffer.i != _writeBuffer.b.end());
+ return _delegate->startWrite(_writeBuffer) && buffer.i == buffer.b.end();
+}
+
+void
+OpenSSL::TransceiverI::finishWrite(IceInternal::Buffer& buffer)
+{
+ if(!_connected)
+ {
+ _delegate->finishWrite(buffer);
+ return;
+ }
+
+ _delegate->finishWrite(_writeBuffer);
+}
+
+void
+OpenSSL::TransceiverI::startRead(IceInternal::Buffer& buffer)
+{
+ if(!_connected)
+ {
+ _delegate->startRead(buffer);
+ return;
+ }
+
+ if(_readBuffer.i == _readBuffer.b.end())
+ {
+ assert(!buffer.b.empty() && buffer.i != buffer.b.end());
+ assert(!BIO_ctrl_get_read_request(_iocpBio));
+
+ ERR_clear_error(); // Clear any spurious errors.
+#ifndef NDEBUG
+ int ret =
+#endif
+ SSL_read(_ssl, reinterpret_cast<void*>(&*buffer.i), static_cast<int>(buffer.b.end() - buffer.i));
+ assert(ret <= 0 && SSL_get_error(_ssl, ret) == SSL_ERROR_WANT_READ);
+
+ assert(BIO_ctrl_get_read_request(_iocpBio));
+ _readBuffer.b.resize(BIO_ctrl_get_read_request(_iocpBio));
+ _readBuffer.i = _readBuffer.b.begin();
+ }
+
+ assert(!_readBuffer.b.empty() && _readBuffer.i != _readBuffer.b.end());
+
+ _delegate->startRead(_readBuffer);
+}
+
+void
+OpenSSL::TransceiverI::finishRead(IceInternal::Buffer& buffer)
+{
+ if(!_connected)
+ {
+ _delegate->finishRead(buffer);
+ return;
+ }
+
+ _delegate->finishRead(_readBuffer);
+ if(_iocpBio && _readBuffer.i == _readBuffer.b.end())
+ {
+ assert(_readBuffer.i == _readBuffer.b.end());
+ int n = BIO_write(_iocpBio, _readBuffer.b.begin(), static_cast<int>(_readBuffer.b.size()));
+ if(n < 0) // Expected if the transceiver was closed.
+ {
+ SecurityException ex(__FILE__, __LINE__);
+ ex.reason = "SSL bio write failed";
+ throw ex;
+ }
+ assert(n == static_cast<int>(_readBuffer.b.size()));
+ }
+}
+#endif
+
string
-IceSSL::TransceiverI::protocol() const
+OpenSSL::TransceiverI::protocol() const
{
return _instance->protocol();
}
string
-IceSSL::TransceiverI::toString() const
+OpenSSL::TransceiverI::toString() const
{
return _delegate->toString();
}
string
-IceSSL::TransceiverI::toDetailedString() const
+OpenSSL::TransceiverI::toDetailedString() const
{
return toString();
}
Ice::ConnectionInfoPtr
-IceSSL::TransceiverI::getInfo() const
+OpenSSL::TransceiverI::getInfo() const
{
NativeConnectionInfoPtr info = ICE_MAKE_SHARED(NativeConnectionInfo);
info->underlying = _delegate->getInfo();
@@ -594,18 +787,18 @@ IceSSL::TransceiverI::getInfo() const
}
void
-IceSSL::TransceiverI::checkSendSize(const IceInternal::Buffer&)
+OpenSSL::TransceiverI::checkSendSize(const IceInternal::Buffer&)
{
}
void
-IceSSL::TransceiverI::setBufferSize(int rcvSize, int sndSize)
+OpenSSL::TransceiverI::setBufferSize(int rcvSize, int sndSize)
{
_delegate->setBufferSize(rcvSize, sndSize);
}
int
-IceSSL::TransceiverI::verifyCallback(int ok, X509_STORE_CTX* c)
+OpenSSL::TransceiverI::verifyCallback(int ok, X509_STORE_CTX* c)
{
if(!ok && _engine->securityTraceLevel() >= 1)
{
@@ -636,7 +829,7 @@ IceSSL::TransceiverI::verifyCallback(int ok, X509_STORE_CTX* c)
_certs.clear();
for(int i = 0; i < sk_X509_num(chain); ++i)
{
- CertificatePtr cert = ICE_MAKE_SHARED(Certificate, X509_dup(sk_X509_value(chain, i)));
+ CertificatePtr cert = OpenSSL::Certificate::create(X509_dup(sk_X509_value(chain, i)));
_nativeCerts.push_back(cert);
_certs.push_back(cert->encode());
}
@@ -652,10 +845,12 @@ IceSSL::TransceiverI::verifyCallback(int ok, X509_STORE_CTX* c)
return 1;
}
-IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance, const IceInternal::TransceiverPtr& delegate,
- const string& hostOrAdapterName, bool incoming) :
+OpenSSL::TransceiverI::TransceiverI(const InstancePtr& instance,
+ const IceInternal::TransceiverPtr& delegate,
+ const string& hostOrAdapterName,
+ bool incoming) :
_instance(instance),
- _engine(OpenSSLEnginePtr::dynamicCast(instance->engine())),
+ _engine(OpenSSL::SSLEnginePtr::dynamicCast(instance->engine())),
_host(incoming ? "" : hostOrAdapterName),
_adapterName(incoming ? hostOrAdapterName : ""),
_incoming(incoming),
@@ -663,11 +858,68 @@ IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance, const IceInterna
_connected(false),
_verified(false),
_ssl(0)
+#ifdef ICE_USE_IOCP
+ , _iocpBio(0),
+ _sentBytes(0),
+ _maxSendPacketSize(0),
+ _maxRecvPacketSize(0)
+#endif
{
}
-IceSSL::TransceiverI::~TransceiverI()
+OpenSSL::TransceiverI::~TransceiverI()
{
}
+#ifdef ICE_USE_IOCP
+bool
+OpenSSL::TransceiverI::receive()
+{
+ if(_readBuffer.i == _readBuffer.b.end())
+ {
+ assert(BIO_ctrl_get_read_request(_iocpBio));
+ _readBuffer.b.resize(BIO_ctrl_get_read_request(_iocpBio));
+ _readBuffer.i = _readBuffer.b.begin();
+ }
+
+ while(_readBuffer.i != _readBuffer.b.end())
+ {
+ if(_delegate->read(_readBuffer) != IceInternal::SocketOperationNone)
+ {
+ return false;
+ }
+ }
+
+ assert(_readBuffer.i == _readBuffer.b.end());
+
+#ifndef NDEBUG
+ int n =
+#endif
+ BIO_write(_iocpBio, &_readBuffer.b[0], static_cast<int>(_readBuffer.b.end() - _readBuffer.b.begin()));
+
+ assert(n == static_cast<int>(_readBuffer.b.end() - _readBuffer.b.begin()));
+
+ return true;
+}
+
+bool
+OpenSSL::TransceiverI::send()
+{
+ if(_writeBuffer.i == _writeBuffer.b.end())
+ {
+ assert(BIO_ctrl_pending(_iocpBio));
+ _writeBuffer.b.resize( BIO_ctrl_pending(_iocpBio));
+ _writeBuffer.i = _writeBuffer.b.begin();
+ BIO_read(_iocpBio, _writeBuffer.i, static_cast<int>(_writeBuffer.b.size()));
+ }
+
+ if(_writeBuffer.i != _writeBuffer.b.end())
+ {
+ if(_delegate->write(_writeBuffer) != IceInternal::SocketOperationNone)
+ {
+ return false;
+ }
+ }
+ return _writeBuffer.i == _writeBuffer.b.end();
+}
#endif
diff --git a/cpp/src/IceSSL/OpenSSLTransceiverI.h b/cpp/src/IceSSL/OpenSSLTransceiverI.h
index 7db90508be8..0bda6849b91 100644
--- a/cpp/src/IceSSL/OpenSSLTransceiverI.h
+++ b/cpp/src/IceSSL/OpenSSLTransceiverI.h
@@ -7,30 +7,28 @@
//
// **********************************************************************
-#ifndef ICESSL_TRANSCEIVER_I_H
-#define ICESSL_TRANSCEIVER_I_H
+#ifndef ICESSL_OPENSSL_TRANSCEIVER_I_H
+#define ICESSL_OPENSSL_TRANSCEIVER_I_H
#include <IceSSL/Config.h>
#include <IceSSL/Util.h>
#include <IceSSL/InstanceF.h>
#include <IceSSL/Plugin.h>
-#include <IceSSL/SSLEngineF.h>
+#include <IceSSL/OpenSSLEngineF.h>
#include <Ice/Transceiver.h>
#include <Ice/Network.h>
#include <Ice/StreamSocket.h>
#include <Ice/WSTransceiver.h>
-#ifdef ICE_USE_OPENSSL
-
typedef struct ssl_st SSL;
typedef struct bio_st BIO;
namespace IceSSL
{
-class ConnectorI;
-class AcceptorI;
+namespace OpenSSL
+{
class TransceiverI : public IceInternal::Transceiver
{
@@ -43,6 +41,12 @@ public:
virtual void close();
virtual IceInternal::SocketOperation write(IceInternal::Buffer&);
virtual IceInternal::SocketOperation read(IceInternal::Buffer&);
+#ifdef ICE_USE_IOCP
+ virtual bool startWrite(IceInternal::Buffer&);
+ virtual void finishWrite(IceInternal::Buffer&);
+ virtual void startRead(IceInternal::Buffer&);
+ virtual void finishRead(IceInternal::Buffer&);
+#endif
virtual std::string protocol() const;
virtual std::string toString() const;
virtual std::string toDetailedString() const;
@@ -57,11 +61,15 @@ private:
TransceiverI(const InstancePtr&, const IceInternal::TransceiverPtr&, const std::string&, bool);
virtual ~TransceiverI();
- friend class ConnectorI;
- friend class AcceptorI;
+#ifdef ICE_USE_IOCP
+ bool receive();
+ bool send();
+#endif
+
+ friend class IceSSL::OpenSSL::SSLEngine;
const InstancePtr _instance;
- const OpenSSLEnginePtr _engine;
+ const IceSSL::OpenSSL::SSLEnginePtr _engine;
const std::string _host;
const std::string _adapterName;
const bool _incoming;
@@ -70,14 +78,22 @@ private:
std::string _cipher;
std::vector<std::string> _certs;
bool _verified;
- std::vector<CertificatePtr> _nativeCerts;
+ std::vector<IceSSL::CertificatePtr> _nativeCerts;
SSL* _ssl;
+#ifdef ICE_USE_IOCP
+ BIO* _iocpBio;
+ IceInternal::Buffer _writeBuffer;
+ IceInternal::Buffer _readBuffer;
+ int _sentBytes;
+ size_t _maxSendPacketSize;
+ size_t _maxRecvPacketSize;
+#endif
};
typedef IceUtil::Handle<TransceiverI> TransceiverIPtr;
-}
+} // OpenSSL namespace end
-#endif
+} // IceSSL namespace end
#endif
diff --git a/cpp/src/IceSSL/OpenSSLUtil.cpp b/cpp/src/IceSSL/OpenSSLUtil.cpp
new file mode 100644
index 00000000000..fa9acdfab7a
--- /dev/null
+++ b/cpp/src/IceSSL/OpenSSLUtil.cpp
@@ -0,0 +1,463 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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/OpenSSLUtil.h>
+
+#include <openssl/err.h>
+//
+// Avoid old style cast warnings from OpenSSL macros
+//
+#if defined(__GNUC__)
+# pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+using namespace std;
+
+namespace
+{
+
+#ifndef OPENSSL_NO_DH
+# if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+
+// The following arrays are predefined Diffie Hellman group parameters.
+// These are known strong primes, distributed with the OpenSSL library
+// in the files dh512.pem, dh1024.pem, dh2048.pem and dh4096.pem.
+// They are not keys themselves, but the basis for generating DH keys
+// on the fly.
+
+static DH*
+convertDH(unsigned char* p, int plen, unsigned char* g, int glen)
+{
+ assert(p != 0);
+ assert(g != 0);
+
+ DH* dh = DH_new();
+
+ if(dh != 0)
+ {
+ dh->p = BN_bin2bn(p, plen, 0);
+ dh->g = BN_bin2bn(g, glen, 0);
+
+ if((dh->p == 0) || (dh->g == 0))
+ {
+ DH_free(dh);
+ dh = 0;
+ }
+ }
+ return dh;
+}
+
+unsigned char dh512_p[] =
+{
+ 0xF5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40,0x18,0x11,0x8D,0x7C,
+ 0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03,0x19,0xC8,0x07,0x29,
+ 0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB,0xD0,0x0A,0x50,0x9B,
+ 0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D,0x41,0x9F,0x9C,0x7C,
+ 0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB,0xA2,0x5E,0xC3,0x55,
+ 0xE9,0x2A,0x05,0x5F,
+};
+
+unsigned char dh512_g[] = { 0x02 };
+
+unsigned char dh1024_p[] =
+{
+ 0xF4,0x88,0xFD,0x58,0x4E,0x49,0xDB,0xCD,0x20,0xB4,0x9D,0xE4,
+ 0x91,0x07,0x36,0x6B,0x33,0x6C,0x38,0x0D,0x45,0x1D,0x0F,0x7C,
+ 0x88,0xB3,0x1C,0x7C,0x5B,0x2D,0x8E,0xF6,0xF3,0xC9,0x23,0xC0,
+ 0x43,0xF0,0xA5,0x5B,0x18,0x8D,0x8E,0xBB,0x55,0x8C,0xB8,0x5D,
+ 0x38,0xD3,0x34,0xFD,0x7C,0x17,0x57,0x43,0xA3,0x1D,0x18,0x6C,
+ 0xDE,0x33,0x21,0x2C,0xB5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40,
+ 0x18,0x11,0x8D,0x7C,0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03,
+ 0x19,0xC8,0x07,0x29,0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB,
+ 0xD0,0x0A,0x50,0x9B,0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D,
+ 0x41,0x9F,0x9C,0x7C,0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB,
+ 0xA2,0x5E,0xC3,0x55,0xE9,0x2F,0x78,0xC7,
+};
+
+unsigned char dh1024_g[] = { 0x02 };
+
+unsigned char dh2048_p[] =
+{
+ 0xF6,0x42,0x57,0xB7,0x08,0x7F,0x08,0x17,0x72,0xA2,0xBA,0xD6,
+ 0xA9,0x42,0xF3,0x05,0xE8,0xF9,0x53,0x11,0x39,0x4F,0xB6,0xF1,
+ 0x6E,0xB9,0x4B,0x38,0x20,0xDA,0x01,0xA7,0x56,0xA3,0x14,0xE9,
+ 0x8F,0x40,0x55,0xF3,0xD0,0x07,0xC6,0xCB,0x43,0xA9,0x94,0xAD,
+ 0xF7,0x4C,0x64,0x86,0x49,0xF8,0x0C,0x83,0xBD,0x65,0xE9,0x17,
+ 0xD4,0xA1,0xD3,0x50,0xF8,0xF5,0x59,0x5F,0xDC,0x76,0x52,0x4F,
+ 0x3D,0x3D,0x8D,0xDB,0xCE,0x99,0xE1,0x57,0x92,0x59,0xCD,0xFD,
+ 0xB8,0xAE,0x74,0x4F,0xC5,0xFC,0x76,0xBC,0x83,0xC5,0x47,0x30,
+ 0x61,0xCE,0x7C,0xC9,0x66,0xFF,0x15,0xF9,0xBB,0xFD,0x91,0x5E,
+ 0xC7,0x01,0xAA,0xD3,0x5B,0x9E,0x8D,0xA0,0xA5,0x72,0x3A,0xD4,
+ 0x1A,0xF0,0xBF,0x46,0x00,0x58,0x2B,0xE5,0xF4,0x88,0xFD,0x58,
+ 0x4E,0x49,0xDB,0xCD,0x20,0xB4,0x9D,0xE4,0x91,0x07,0x36,0x6B,
+ 0x33,0x6C,0x38,0x0D,0x45,0x1D,0x0F,0x7C,0x88,0xB3,0x1C,0x7C,
+ 0x5B,0x2D,0x8E,0xF6,0xF3,0xC9,0x23,0xC0,0x43,0xF0,0xA5,0x5B,
+ 0x18,0x8D,0x8E,0xBB,0x55,0x8C,0xB8,0x5D,0x38,0xD3,0x34,0xFD,
+ 0x7C,0x17,0x57,0x43,0xA3,0x1D,0x18,0x6C,0xDE,0x33,0x21,0x2C,
+ 0xB5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40,0x18,0x11,0x8D,0x7C,
+ 0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03,0x19,0xC8,0x07,0x29,
+ 0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB,0xD0,0x0A,0x50,0x9B,
+ 0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D,0x41,0x9F,0x9C,0x7C,
+ 0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB,0xA2,0x5E,0xC3,0x55,
+ 0xE9,0x32,0x0B,0x3B,
+};
+
+unsigned char dh2048_g[] = { 0x02 };
+
+unsigned char dh4096_p[] =
+{
+ 0xFA,0x14,0x72,0x52,0xC1,0x4D,0xE1,0x5A,0x49,0xD4,0xEF,0x09,
+ 0x2D,0xC0,0xA8,0xFD,0x55,0xAB,0xD7,0xD9,0x37,0x04,0x28,0x09,
+ 0xE2,0xE9,0x3E,0x77,0xE2,0xA1,0x7A,0x18,0xDD,0x46,0xA3,0x43,
+ 0x37,0x23,0x90,0x97,0xF3,0x0E,0xC9,0x03,0x50,0x7D,0x65,0xCF,
+ 0x78,0x62,0xA6,0x3A,0x62,0x22,0x83,0xA1,0x2F,0xFE,0x79,0xBA,
+ 0x35,0xFF,0x59,0xD8,0x1D,0x61,0xDD,0x1E,0x21,0x13,0x17,0xFE,
+ 0xCD,0x38,0x87,0x9E,0xF5,0x4F,0x79,0x10,0x61,0x8D,0xD4,0x22,
+ 0xF3,0x5A,0xED,0x5D,0xEA,0x21,0xE9,0x33,0x6B,0x48,0x12,0x0A,
+ 0x20,0x77,0xD4,0x25,0x60,0x61,0xDE,0xF6,0xB4,0x4F,0x1C,0x63,
+ 0x40,0x8B,0x3A,0x21,0x93,0x8B,0x79,0x53,0x51,0x2C,0xCA,0xB3,
+ 0x7B,0x29,0x56,0xA8,0xC7,0xF8,0xF4,0x7B,0x08,0x5E,0xA6,0xDC,
+ 0xA2,0x45,0x12,0x56,0xDD,0x41,0x92,0xF2,0xDD,0x5B,0x8F,0x23,
+ 0xF0,0xF3,0xEF,0xE4,0x3B,0x0A,0x44,0xDD,0xED,0x96,0x84,0xF1,
+ 0xA8,0x32,0x46,0xA3,0xDB,0x4A,0xBE,0x3D,0x45,0xBA,0x4E,0xF8,
+ 0x03,0xE5,0xDD,0x6B,0x59,0x0D,0x84,0x1E,0xCA,0x16,0x5A,0x8C,
+ 0xC8,0xDF,0x7C,0x54,0x44,0xC4,0x27,0xA7,0x3B,0x2A,0x97,0xCE,
+ 0xA3,0x7D,0x26,0x9C,0xAD,0xF4,0xC2,0xAC,0x37,0x4B,0xC3,0xAD,
+ 0x68,0x84,0x7F,0x99,0xA6,0x17,0xEF,0x6B,0x46,0x3A,0x7A,0x36,
+ 0x7A,0x11,0x43,0x92,0xAD,0xE9,0x9C,0xFB,0x44,0x6C,0x3D,0x82,
+ 0x49,0xCC,0x5C,0x6A,0x52,0x42,0xF8,0x42,0xFB,0x44,0xF9,0x39,
+ 0x73,0xFB,0x60,0x79,0x3B,0xC2,0x9E,0x0B,0xDC,0xD4,0xA6,0x67,
+ 0xF7,0x66,0x3F,0xFC,0x42,0x3B,0x1B,0xDB,0x4F,0x66,0xDC,0xA5,
+ 0x8F,0x66,0xF9,0xEA,0xC1,0xED,0x31,0xFB,0x48,0xA1,0x82,0x7D,
+ 0xF8,0xE0,0xCC,0xB1,0xC7,0x03,0xE4,0xF8,0xB3,0xFE,0xB7,0xA3,
+ 0x13,0x73,0xA6,0x7B,0xC1,0x0E,0x39,0xC7,0x94,0x48,0x26,0x00,
+ 0x85,0x79,0xFC,0x6F,0x7A,0xAF,0xC5,0x52,0x35,0x75,0xD7,0x75,
+ 0xA4,0x40,0xFA,0x14,0x74,0x61,0x16,0xF2,0xEB,0x67,0x11,0x6F,
+ 0x04,0x43,0x3D,0x11,0x14,0x4C,0xA7,0x94,0x2A,0x39,0xA1,0xC9,
+ 0x90,0xCF,0x83,0xC6,0xFF,0x02,0x8F,0xA3,0x2A,0xAC,0x26,0xDF,
+ 0x0B,0x8B,0xBE,0x64,0x4A,0xF1,0xA1,0xDC,0xEE,0xBA,0xC8,0x03,
+ 0x82,0xF6,0x62,0x2C,0x5D,0xB6,0xBB,0x13,0x19,0x6E,0x86,0xC5,
+ 0x5B,0x2B,0x5E,0x3A,0xF3,0xB3,0x28,0x6B,0x70,0x71,0x3A,0x8E,
+ 0xFF,0x5C,0x15,0xE6,0x02,0xA4,0xCE,0xED,0x59,0x56,0xCC,0x15,
+ 0x51,0x07,0x79,0x1A,0x0F,0x25,0x26,0x27,0x30,0xA9,0x15,0xB2,
+ 0xC8,0xD4,0x5C,0xCC,0x30,0xE8,0x1B,0xD8,0xD5,0x0F,0x19,0xA8,
+ 0x80,0xA4,0xC7,0x01,0xAA,0x8B,0xBA,0x53,0xBB,0x47,0xC2,0x1F,
+ 0x6B,0x54,0xB0,0x17,0x60,0xED,0x79,0x21,0x95,0xB6,0x05,0x84,
+ 0x37,0xC8,0x03,0xA4,0xDD,0xD1,0x06,0x69,0x8F,0x4C,0x39,0xE0,
+ 0xC8,0x5D,0x83,0x1D,0xBE,0x6A,0x9A,0x99,0xF3,0x9F,0x0B,0x45,
+ 0x29,0xD4,0xCB,0x29,0x66,0xEE,0x1E,0x7E,0x3D,0xD7,0x13,0x4E,
+ 0xDB,0x90,0x90,0x58,0xCB,0x5E,0x9B,0xCD,0x2E,0x2B,0x0F,0xA9,
+ 0x4E,0x78,0xAC,0x05,0x11,0x7F,0xE3,0x9E,0x27,0xD4,0x99,0xE1,
+ 0xB9,0xBD,0x78,0xE1,0x84,0x41,0xA0,0xDF,
+};
+
+unsigned char dh4096_g[] = { 0x02 };
+
+# else
+//
+// With OpenSSL 1.1.0 is no longer possible to acess the DH p and g
+// data members to set the DH params. We still use the same default
+// parameters but they were converted to DER format using
+// i2d_DHparams and can be restored using d2i_DHparams
+
+static DH*
+convertDH(const unsigned char* buf, int len)
+{
+ return d2i_DHparams(0, &buf, len);
+}
+
+unsigned char dh512[] =
+{
+ 0x30,0x46,0x02,0x41,0x00,0xF5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,
+ 0x40,0x18,0x11,0x8D,0x7C,0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,
+ 0x03,0x19,0xC8,0x07,0x29,0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,
+ 0xAB,0xD0,0x0A,0x50,0x9B,0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,
+ 0x5D,0x41,0x9F,0x9C,0x7C,0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,
+ 0xAB,0xA2,0x5E,0xC3,0x55,0xE9,0x2A,0x05,0x5F,0x02,0x01,0x02,
+};
+
+unsigned char dh1024[] =
+{
+ 0x30,0x81,0x87,0x02,0x81,0x81,0x00,0xF4,0x88,0xFD,0x58,0x4E,
+ 0x49,0xDB,0xCD,0x20,0xB4,0x9D,0xE4,0x91,0x07,0x36,0x6B,0x33,
+ 0x6C,0x38,0x0D,0x45,0x1D,0x0F,0x7C,0x88,0xB3,0x1C,0x7C,0x5B,
+ 0x2D,0x8E,0xF6,0xF3,0xC9,0x23,0xC0,0x43,0xF0,0xA5,0x5B,0x18,
+ 0x8D,0x8E,0xBB,0x55,0x8C,0xB8,0x5D,0x38,0xD3,0x34,0xFD,0x7C,
+ 0x17,0x57,0x43,0xA3,0x1D,0x18,0x6C,0xDE,0x33,0x21,0x2C,0xB5,
+ 0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40,0x18,0x11,0x8D,0x7C,0x84,
+ 0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03,0x19,0xC8,0x07,0x29,0x7A,
+ 0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB,0xD0,0x0A,0x50,0x9B,0x02,
+ 0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D,0x41,0x9F,0x9C,0x7C,0xBD,
+ 0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB,0xA2,0x5E,0xC3,0x55,0xE9,
+ 0x2F,0x78,0xC7,0x02,0x01,0x02,
+};
+
+unsigned char dh2048[] =
+{
+ 0x30,0x82,0x01,0x08,0x02,0x82,0x01,0x01,0x00,0xF6,0x42,0x57,
+ 0xB7,0x08,0x7F,0x08,0x17,0x72,0xA2,0xBA,0xD6,0xA9,0x42,0xF3,
+ 0x05,0xE8,0xF9,0x53,0x11,0x39,0x4F,0xB6,0xF1,0x6E,0xB9,0x4B,
+ 0x38,0x20,0xDA,0x01,0xA7,0x56,0xA3,0x14,0xE9,0x8F,0x40,0x55,
+ 0xF3,0xD0,0x07,0xC6,0xCB,0x43,0xA9,0x94,0xAD,0xF7,0x4C,0x64,
+ 0x86,0x49,0xF8,0x0C,0x83,0xBD,0x65,0xE9,0x17,0xD4,0xA1,0xD3,
+ 0x50,0xF8,0xF5,0x59,0x5F,0xDC,0x76,0x52,0x4F,0x3D,0x3D,0x8D,
+ 0xDB,0xCE,0x99,0xE1,0x57,0x92,0x59,0xCD,0xFD,0xB8,0xAE,0x74,
+ 0x4F,0xC5,0xFC,0x76,0xBC,0x83,0xC5,0x47,0x30,0x61,0xCE,0x7C,
+ 0xC9,0x66,0xFF,0x15,0xF9,0xBB,0xFD,0x91,0x5E,0xC7,0x01,0xAA,
+ 0xD3,0x5B,0x9E,0x8D,0xA0,0xA5,0x72,0x3A,0xD4,0x1A,0xF0,0xBF,
+ 0x46,0x00,0x58,0x2B,0xE5,0xF4,0x88,0xFD,0x58,0x4E,0x49,0xDB,
+ 0xCD,0x20,0xB4,0x9D,0xE4,0x91,0x07,0x36,0x6B,0x33,0x6C,0x38,
+ 0x0D,0x45,0x1D,0x0F,0x7C,0x88,0xB3,0x1C,0x7C,0x5B,0x2D,0x8E,
+ 0xF6,0xF3,0xC9,0x23,0xC0,0x43,0xF0,0xA5,0x5B,0x18,0x8D,0x8E,
+ 0xBB,0x55,0x8C,0xB8,0x5D,0x38,0xD3,0x34,0xFD,0x7C,0x17,0x57,
+ 0x43,0xA3,0x1D,0x18,0x6C,0xDE,0x33,0x21,0x2C,0xB5,0x2A,0xFF,
+ 0x3C,0xE1,0xB1,0x29,0x40,0x18,0x11,0x8D,0x7C,0x84,0xA7,0x0A,
+ 0x72,0xD6,0x86,0xC4,0x03,0x19,0xC8,0x07,0x29,0x7A,0xCA,0x95,
+ 0x0C,0xD9,0x96,0x9F,0xAB,0xD0,0x0A,0x50,0x9B,0x02,0x46,0xD3,
+ 0x08,0x3D,0x66,0xA4,0x5D,0x41,0x9F,0x9C,0x7C,0xBD,0x89,0x4B,
+ 0x22,0x19,0x26,0xBA,0xAB,0xA2,0x5E,0xC3,0x55,0xE9,0x32,0x0B,
+ 0x3B,0x02,0x01,0x02,
+};
+
+unsigned char dh4096[] =
+{
+ 0x30,0x82,0x02,0x08,0x02,0x82,0x02,0x01,0x00,0xFA,0x14,0x72,
+ 0x52,0xC1,0x4D,0xE1,0x5A,0x49,0xD4,0xEF,0x09,0x2D,0xC0,0xA8,
+ 0xFD,0x55,0xAB,0xD7,0xD9,0x37,0x04,0x28,0x09,0xE2,0xE9,0x3E,
+ 0x77,0xE2,0xA1,0x7A,0x18,0xDD,0x46,0xA3,0x43,0x37,0x23,0x90,
+ 0x97,0xF3,0x0E,0xC9,0x03,0x50,0x7D,0x65,0xCF,0x78,0x62,0xA6,
+ 0x3A,0x62,0x22,0x83,0xA1,0x2F,0xFE,0x79,0xBA,0x35,0xFF,0x59,
+ 0xD8,0x1D,0x61,0xDD,0x1E,0x21,0x13,0x17,0xFE,0xCD,0x38,0x87,
+ 0x9E,0xF5,0x4F,0x79,0x10,0x61,0x8D,0xD4,0x22,0xF3,0x5A,0xED,
+ 0x5D,0xEA,0x21,0xE9,0x33,0x6B,0x48,0x12,0x0A,0x20,0x77,0xD4,
+ 0x25,0x60,0x61,0xDE,0xF6,0xB4,0x4F,0x1C,0x63,0x40,0x8B,0x3A,
+ 0x21,0x93,0x8B,0x79,0x53,0x51,0x2C,0xCA,0xB3,0x7B,0x29,0x56,
+ 0xA8,0xC7,0xF8,0xF4,0x7B,0x08,0x5E,0xA6,0xDC,0xA2,0x45,0x12,
+ 0x56,0xDD,0x41,0x92,0xF2,0xDD,0x5B,0x8F,0x23,0xF0,0xF3,0xEF,
+ 0xE4,0x3B,0x0A,0x44,0xDD,0xED,0x96,0x84,0xF1,0xA8,0x32,0x46,
+ 0xA3,0xDB,0x4A,0xBE,0x3D,0x45,0xBA,0x4E,0xF8,0x03,0xE5,0xDD,
+ 0x6B,0x59,0x0D,0x84,0x1E,0xCA,0x16,0x5A,0x8C,0xC8,0xDF,0x7C,
+ 0x54,0x44,0xC4,0x27,0xA7,0x3B,0x2A,0x97,0xCE,0xA3,0x7D,0x26,
+ 0x9C,0xAD,0xF4,0xC2,0xAC,0x37,0x4B,0xC3,0xAD,0x68,0x84,0x7F,
+ 0x99,0xA6,0x17,0xEF,0x6B,0x46,0x3A,0x7A,0x36,0x7A,0x11,0x43,
+ 0x92,0xAD,0xE9,0x9C,0xFB,0x44,0x6C,0x3D,0x82,0x49,0xCC,0x5C,
+ 0x6A,0x52,0x42,0xF8,0x42,0xFB,0x44,0xF9,0x39,0x73,0xFB,0x60,
+ 0x79,0x3B,0xC2,0x9E,0x0B,0xDC,0xD4,0xA6,0x67,0xF7,0x66,0x3F,
+ 0xFC,0x42,0x3B,0x1B,0xDB,0x4F,0x66,0xDC,0xA5,0x8F,0x66,0xF9,
+ 0xEA,0xC1,0xED,0x31,0xFB,0x48,0xA1,0x82,0x7D,0xF8,0xE0,0xCC,
+ 0xB1,0xC7,0x03,0xE4,0xF8,0xB3,0xFE,0xB7,0xA3,0x13,0x73,0xA6,
+ 0x7B,0xC1,0x0E,0x39,0xC7,0x94,0x48,0x26,0x00,0x85,0x79,0xFC,
+ 0x6F,0x7A,0xAF,0xC5,0x52,0x35,0x75,0xD7,0x75,0xA4,0x40,0xFA,
+ 0x14,0x74,0x61,0x16,0xF2,0xEB,0x67,0x11,0x6F,0x04,0x43,0x3D,
+ 0x11,0x14,0x4C,0xA7,0x94,0x2A,0x39,0xA1,0xC9,0x90,0xCF,0x83,
+ 0xC6,0xFF,0x02,0x8F,0xA3,0x2A,0xAC,0x26,0xDF,0x0B,0x8B,0xBE,
+ 0x64,0x4A,0xF1,0xA1,0xDC,0xEE,0xBA,0xC8,0x03,0x82,0xF6,0x62,
+ 0x2C,0x5D,0xB6,0xBB,0x13,0x19,0x6E,0x86,0xC5,0x5B,0x2B,0x5E,
+ 0x3A,0xF3,0xB3,0x28,0x6B,0x70,0x71,0x3A,0x8E,0xFF,0x5C,0x15,
+ 0xE6,0x02,0xA4,0xCE,0xED,0x59,0x56,0xCC,0x15,0x51,0x07,0x79,
+ 0x1A,0x0F,0x25,0x26,0x27,0x30,0xA9,0x15,0xB2,0xC8,0xD4,0x5C,
+ 0xCC,0x30,0xE8,0x1B,0xD8,0xD5,0x0F,0x19,0xA8,0x80,0xA4,0xC7,
+ 0x01,0xAA,0x8B,0xBA,0x53,0xBB,0x47,0xC2,0x1F,0x6B,0x54,0xB0,
+ 0x17,0x60,0xED,0x79,0x21,0x95,0xB6,0x05,0x84,0x37,0xC8,0x03,
+ 0xA4,0xDD,0xD1,0x06,0x69,0x8F,0x4C,0x39,0xE0,0xC8,0x5D,0x83,
+ 0x1D,0xBE,0x6A,0x9A,0x99,0xF3,0x9F,0x0B,0x45,0x29,0xD4,0xCB,
+ 0x29,0x66,0xEE,0x1E,0x7E,0x3D,0xD7,0x13,0x4E,0xDB,0x90,0x90,
+ 0x58,0xCB,0x5E,0x9B,0xCD,0x2E,0x2B,0x0F,0xA9,0x4E,0x78,0xAC,
+ 0x05,0x11,0x7F,0xE3,0x9E,0x27,0xD4,0x99,0xE1,0xB9,0xBD,0x78,
+ 0xE1,0x84,0x41,0xA0,0xDF,0x02,0x01,0x02,
+};
+# endif
+
+}
+
+IceSSL::OpenSSL::DHParams::DHParams() :
+ _dh512(0), _dh1024(0), _dh2048(0), _dh4096(0)
+{
+}
+
+IceSSL::OpenSSL::DHParams::~DHParams()
+{
+ for(ParamList::iterator p = _params.begin(); p != _params.end(); ++p)
+ {
+ DH_free(p->second);
+ }
+ DH_free(_dh512);
+ DH_free(_dh1024);
+ DH_free(_dh2048);
+ DH_free(_dh4096);
+}
+
+bool
+IceSSL::OpenSSL::DHParams::add(int keyLength, const string& file)
+{
+ BIO* bio = BIO_new(BIO_s_file());
+ if(BIO_read_filename(bio, file.c_str()) <= 0)
+ {
+ BIO_free(bio);
+ return false;
+ }
+ DH* dh = PEM_read_bio_DHparams(bio, 0, 0, 0);
+ BIO_free(bio);
+ if(!dh)
+ {
+ return false;
+ }
+ ParamList::iterator p = _params.begin();
+ while(p != _params.end() && keyLength > p->first)
+ {
+ ++p;
+ }
+ _params.insert(p, KeyParamPair(keyLength, dh));
+ return true;
+}
+
+DH*
+IceSSL::OpenSSL::DHParams::get(int keyLength)
+{
+ //
+ // First check the set of parameters specified by the user.
+ // Return the first set whose key length is at least keyLength.
+ //
+ for(ParamList::iterator p = _params.begin(); p != _params.end(); ++p)
+ {
+ if(p->first >= keyLength)
+ {
+ return p->second;
+ }
+ }
+
+ //
+ // No match found. Use one of the predefined parameter sets instead.
+ //
+ IceUtil::Mutex::Lock sync(*this);
+# if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+ if(keyLength >= 4096)
+ {
+ if(!_dh4096)
+ {
+ _dh4096 = convertDH(dh4096, (int) sizeof(dh4096));
+ }
+ return _dh4096;
+ }
+ else if(keyLength >= 2048)
+ {
+ if(!_dh2048)
+ {
+ _dh2048 = convertDH(dh2048, (int) sizeof(dh2048));
+ }
+ return _dh2048;
+ }
+ else if(keyLength >= 1024)
+ {
+ if(!_dh1024)
+ {
+ _dh1024 = convertDH(dh1024, (int) sizeof(dh1024));
+ }
+ return _dh1024;
+ }
+ else
+ {
+ if(!_dh512)
+ {
+ _dh512 = convertDH(dh512, (int) sizeof(dh512));
+ }
+ return _dh512;
+ }
+# else
+ if(keyLength >= 4096)
+ {
+ if(!_dh4096)
+ {
+ _dh4096 = convertDH(dh4096_p, (int) sizeof(dh4096_p), dh4096_g, (int) sizeof(dh4096_g));
+ }
+ return _dh4096;
+ }
+ else if(keyLength >= 2048)
+ {
+ if(!_dh2048)
+ {
+ _dh2048 = convertDH(dh2048_p, (int) sizeof(dh2048_p), dh2048_g, (int) sizeof(dh2048_g));
+ }
+ return _dh2048;
+ }
+ else if(keyLength >= 1024)
+ {
+ if(!_dh1024)
+ {
+ _dh1024 = convertDH(dh1024_p, (int) sizeof(dh1024_p), dh1024_g, (int) sizeof(dh1024_g));
+ }
+ return _dh1024;
+ }
+ else
+ {
+ if(!_dh512)
+ {
+ _dh512 = convertDH(dh512_p, (int) sizeof(dh512_p), dh512_g, (int) sizeof(dh512_g));
+ }
+ return _dh512;
+ }
+# endif
+}
+
+#endif
+
+string
+IceSSL::OpenSSL::getSslErrors(bool verbose)
+{
+ ostringstream ostr;
+
+ const char* file;
+ const char* data;
+ int line;
+ int flags;
+ unsigned long err;
+ int count = 0;
+ while((err = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0)
+ {
+ if(count > 0)
+ {
+ ostr << endl;
+ }
+
+ if(verbose)
+ {
+ if(count > 0)
+ {
+ ostr << endl;
+ }
+
+ char buf[200];
+ ERR_error_string_n(err, buf, sizeof(buf));
+
+ ostr << "error # = " << err << endl;
+ ostr << "message = " << buf << endl;
+ ostr << "location = " << file << ", " << line;
+ if(flags & ERR_TXT_STRING)
+ {
+ ostr << endl;
+ ostr << "data = " << data;
+ }
+ }
+ else
+ {
+ const char* reason = ERR_reason_error_string(err);
+ ostr << (reason == ICE_NULLPTR ? "unknown reason" : reason);
+ if(flags & ERR_TXT_STRING)
+ {
+ ostr << ": " << data;
+ }
+ }
+
+ ++count;
+ }
+
+ ERR_clear_error();
+
+ return ostr.str();
+}
diff --git a/cpp/src/IceSSL/OpenSSLUtil.h b/cpp/src/IceSSL/OpenSSLUtil.h
new file mode 100644
index 00000000000..6edf4d11009
--- /dev/null
+++ b/cpp/src/IceSSL/OpenSSLUtil.h
@@ -0,0 +1,63 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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 ICESSL_OPENSSL_UTIL_I_H
+#define ICESSL_OPENSSL_UTIL_I_H
+
+#include <IceUtil/Shared.h>
+#include <IceUtil/Mutex.h>
+#include <IceUtil/Handle.h>
+
+#include <openssl/ssl.h>
+
+#include <list>
+
+namespace IceSSL
+{
+
+namespace OpenSSL
+{
+
+#ifndef OPENSSL_NO_DH
+
+class DHParams : public IceUtil::Shared, public IceUtil::Mutex
+{
+public:
+
+ DHParams();
+ ~DHParams();
+
+ bool add(int, const std::string&);
+ DH* get(int);
+
+private:
+
+ typedef std::pair<int, DH*> KeyParamPair;
+ typedef std::list<KeyParamPair> ParamList;
+ ParamList _params;
+
+ DH* _dh512;
+ DH* _dh1024;
+ DH* _dh2048;
+ DH* _dh4096;
+};
+typedef IceUtil::Handle<DHParams> DHParamsPtr;
+
+#endif
+
+//
+// Accumulate the OpenSSL error stack into a string.
+//
+std::string getSslErrors(bool);
+
+} // OpenSSL namespace end
+
+} // IceSSL namespace end
+
+#endif
diff --git a/cpp/src/IceSSL/PluginI.cpp b/cpp/src/IceSSL/PluginI.cpp
index 1dcb535cce8..4e3cd01680a 100755
--- a/cpp/src/IceSSL/PluginI.cpp
+++ b/cpp/src/IceSSL/PluginI.cpp
@@ -21,40 +21,20 @@ using namespace std;
using namespace Ice;
using namespace IceSSL;
-//
-// Plug-in factory function.
-//
-extern "C" ICESSL_API Ice::Plugin*
-createIceSSL(const CommunicatorPtr& communicator, const string& /*name*/, const StringSeq& /*args*/)
-{
- return new PluginI(communicator);
-}
-
-namespace Ice
-{
-
-ICESSL_API void
-registerIceSSL(bool loadOnInitialize)
-{
- Ice::registerPluginFactory("IceSSL", createIceSSL, loadOnInitialize);
-}
-
-}
-
#ifndef ICE_CPP11_MAPPING
-IceSSL::CertificateVerifier::~CertificateVerifier()
+CertificateVerifier::~CertificateVerifier()
{
// Out of line to avoid weak vtable
}
-IceSSL::PasswordPrompt::~PasswordPrompt()
+PasswordPrompt::~PasswordPrompt()
{
// Out of line to avoid weak vtable
}
#endif
-IceSSL::NativeConnectionInfo::~NativeConnectionInfo()
+NativeConnectionInfo::~NativeConnectionInfo()
{
// Out of line to avoid weak vtable
}
@@ -65,29 +45,11 @@ IceSSL::Plugin::~Plugin()
}
//
-// Objective-C function to allow Objective-C programs to register plugin.
-//
-extern "C" ICESSL_API void
-ICEregisterIceSSL(bool loadOnInitialize)
-{
- Ice::registerIceSSL(loadOnInitialize);
-}
-
-//
// Plugin implementation.
//
-IceSSL::PluginI::PluginI(const Ice::CommunicatorPtr& com)
+PluginI::PluginI(const Ice::CommunicatorPtr& com, const SSLEnginePtr& engine) :
+ _engine(engine)
{
-#if defined(ICE_USE_SECURE_TRANSPORT)
- _engine = new SecureTransportEngine(com);
-#elif defined(ICE_USE_SCHANNEL)
- _engine = new SChannelEngine(com);
-#elif defined(ICE_OS_UWP)
- _engine = new UWPEngine(com);
-#else
- _engine = new OpenSSLEngine(com);
-#endif
-
//
// Register the endpoint factory. We have to do this now, rather
// than in initialize, because the communicator may need to
@@ -121,47 +83,21 @@ IceSSL::PluginI::PluginI(const Ice::CommunicatorPtr& com)
}
void
-IceSSL::PluginI::initialize()
+PluginI::initialize()
{
_engine->initialize();
}
void
-IceSSL::PluginI::destroy()
+PluginI::destroy()
{
_engine->destroy();
_engine = 0;
}
-string
-IceSSL::PluginI::getEngineName() const
-{
-#if defined(ICE_USE_SECURE_TRANSPORT)
- return "SecureTransportEngine";
-#elif defined(ICE_USE_SCHANNEL)
- return "SChannelEngine";
-#elif defined(ICE_OS_UWP)
- return "UWPEngine";
-#else
- ostringstream os;
- os << "OpenSSLEngine@" << SSLeay_version(SSLEAY_VERSION);
- return os.str();
-#endif
-}
-
-Ice::Long
-IceSSL::PluginI::getEngineVersion() const
-{
-#if defined(ICE_USE_OPENSSL)
- return SSLeay();
-#else
- return 0;
-#endif
-}
-
#ifdef ICE_CPP11_MAPPING
void
-IceSSL::PluginI::setCertificateVerifier(std::function<bool(const std::shared_ptr<NativeConnectionInfo>&)> verifier)
+PluginI::setCertificateVerifier(std::function<bool(const std::shared_ptr<NativeConnectionInfo>&)> verifier)
{
if(verifier)
{
@@ -174,7 +110,7 @@ IceSSL::PluginI::setCertificateVerifier(std::function<bool(const std::shared_ptr
}
#else
void
-IceSSL::PluginI::setCertificateVerifier(const CertificateVerifierPtr& verifier)
+PluginI::setCertificateVerifier(const CertificateVerifierPtr& verifier)
{
_engine->setCertificateVerifier(verifier);
}
@@ -182,7 +118,7 @@ IceSSL::PluginI::setCertificateVerifier(const CertificateVerifierPtr& verifier)
#ifdef ICE_CPP11_MAPPING
void
-IceSSL::PluginI::setPasswordPrompt(std::function<std::string()> prompt)
+PluginI::setPasswordPrompt(std::function<std::string()> prompt)
{
if(prompt)
{
@@ -195,22 +131,37 @@ IceSSL::PluginI::setPasswordPrompt(std::function<std::string()> prompt)
}
#else
void
-IceSSL::PluginI::setPasswordPrompt(const PasswordPromptPtr& prompt)
+PluginI::setPasswordPrompt(const PasswordPromptPtr& prompt)
{
_engine->setPasswordPrompt(prompt);
}
#endif
-#ifdef ICE_USE_OPENSSL
-void
-IceSSL::PluginI::setContext(SSL_CTX* context)
+extern "C"
+{
+
+ICESSL_API Ice::Plugin*
+createIceSSL(const CommunicatorPtr&, const string&, const StringSeq&);
+
+}
+
+namespace Ice
{
- _engine->context(context);
+
+ICESSL_API void
+registerIceSSL(bool loadOnInitialize)
+{
+ Ice::registerPluginFactory("IceSSL", createIceSSL, loadOnInitialize);
+}
+
}
-SSL_CTX*
-IceSSL::PluginI::getContext()
+//
+// Objective-C function to allow Objective-C programs to register plugin.
+//
+extern "C" ICESSL_API void
+ICEregisterIceSSL(bool loadOnInitialize)
{
- return _engine->context();
+ Ice::registerIceSSL(loadOnInitialize);
}
-#endif
+
diff --git a/cpp/src/IceSSL/PluginI.h b/cpp/src/IceSSL/PluginI.h
index 71d35b3a566..3cb9a14b024 100644
--- a/cpp/src/IceSSL/PluginI.h
+++ b/cpp/src/IceSSL/PluginI.h
@@ -17,19 +17,16 @@
namespace IceSSL
{
-class PluginI : public IceSSL::Plugin
+class ICESSL_API PluginI : public virtual IceSSL::Plugin
{
public:
- PluginI(const Ice::CommunicatorPtr&);
-
+ PluginI(const Ice::CommunicatorPtr&, const IceSSL::SSLEnginePtr&);
//
// From Ice::Plugin.
//
virtual void initialize();
virtual void destroy();
- virtual std::string getEngineName() const;
- virtual Ice::Long getEngineVersion() const;
//
// From IceSSL::Plugin.
@@ -42,22 +39,11 @@ public:
virtual void setPasswordPrompt(const PasswordPromptPtr&);
#endif
-#ifdef ICE_USE_OPENSSL
- virtual void setContext(SSL_CTX*);
- virtual SSL_CTX* getContext();
-#endif
-
-private:
+ virtual CertificatePtr load(const std::string&) const = 0;
+ virtual CertificatePtr decode(const std::string&) const = 0;
+protected:
-#if defined(ICE_USE_SECURE_TRANSPORT)
- SecureTransportEnginePtr _engine;
-#elif defined(ICE_USE_SCHANNEL)
- SChannelEnginePtr _engine;
-#elif defined(ICE_OS_UWP)
- UWPEnginePtr _engine;
-#else
- OpenSSLEnginePtr _engine;
-#endif
+ SSLEnginePtr _engine;
};
}
diff --git a/cpp/src/IceSSL/RFC2253.cpp b/cpp/src/IceSSL/RFC2253.cpp
index 7d14e26a3af..d5ede7cb6ba 100644
--- a/cpp/src/IceSSL/RFC2253.cpp
+++ b/cpp/src/IceSSL/RFC2253.cpp
@@ -37,8 +37,8 @@ static string parsePair(const string&, size_t&);
static string parseHexPair(const string&, size_t&, bool);
static void eatWhite(const string&, size_t&);
-IceSSL::RFC2253::RDNEntrySeq
-IceSSL::RFC2253::parse(const string& data)
+RFC2253::RDNEntrySeq
+RFC2253::parse(const string& data)
{
RDNEntrySeq results;
RDNEntry current;
@@ -82,8 +82,8 @@ IceSSL::RFC2253::parse(const string& data)
return results;
}
-IceSSL::RFC2253::RDNSeq
-IceSSL::RFC2253::parseStrict(const string& data)
+RFC2253::RDNSeq
+RFC2253::parseStrict(const string& data)
{
RDNSeq results;
size_t pos = 0;
@@ -104,7 +104,7 @@ IceSSL::RFC2253::parseStrict(const string& data)
}
string
-IceSSL::RFC2253::unescape(const string& data)
+RFC2253::unescape(const string& data)
{
if(data.size() == 0)
{
diff --git a/cpp/src/IceSSL/RFC2253.h b/cpp/src/IceSSL/RFC2253.h
index b29b60e618d..e642af16a88 100644
--- a/cpp/src/IceSSL/RFC2253.h
+++ b/cpp/src/IceSSL/RFC2253.h
@@ -33,7 +33,7 @@ namespace RFC2253
typedef std::list< std::pair<std::string, std::string> > RDNSeq;
-struct RDNEntry
+struct ICESSL_API RDNEntry
{
RDNSeq rdn;
bool negate;
@@ -46,7 +46,7 @@ typedef std::list<RDNEntry> RDNEntrySeq;
// The function returns a list of RDNEntry structures. Any failure in
// parsing results in a ParseException being thrown.
//
-RDNEntrySeq parse(const std::string&);
+ICESSL_API RDNEntrySeq parse(const std::string&);
//
// RDNs are separated with ',' and ';'.
@@ -54,12 +54,12 @@ RDNEntrySeq parse(const std::string&);
// This function returns a list of RDN pairs. Any failure in parsing
// results in a ParseException being thrown.
//
-RDNSeq parseStrict(const std::string&);
+ICESSL_API RDNSeq parseStrict(const std::string&);
//
// Unescape the string.
//
-std::string unescape(const std::string&);
+ICESSL_API std::string unescape(const std::string&);
}
}
diff --git a/cpp/src/IceSSL/SChannelCertificateI.cpp b/cpp/src/IceSSL/SChannelCertificateI.cpp
new file mode 100644
index 00000000000..e9aff0aa4b0
--- /dev/null
+++ b/cpp/src/IceSSL/SChannelCertificateI.cpp
@@ -0,0 +1,569 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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/Plugin.h>
+#include <IceSSL/SChannel.h>
+#include <IceSSL/CertificateI.h>
+#include <IceSSL/Util.h>
+#include <Ice/StringUtil.h>
+#include <Ice/StringConverter.h>
+
+#include <wincrypt.h>
+
+#include <string>
+#include <vector>
+
+using namespace std;
+using namespace Ice;
+using namespace IceSSL;
+
+namespace
+{
+
+class SCHannelX509ExtensionI : public X509Extension
+{
+
+public:
+
+ SCHannelX509ExtensionI(CERT_EXTENSION , const string&, const SChannel::CertificatePtr&);
+ virtual bool isCritical() const;
+ virtual string getOID() const;
+ virtual vector<Ice::Byte> getData() const;
+
+private:
+
+ CERT_EXTENSION _extension;
+ string _oid;
+ //
+ // We want to keep the certificate that contains the extension alive
+ // for the lifetime of the extension.
+ //
+ SChannel::CertificatePtr _cert;
+};
+
+class SChannelCertificateI : public SChannel::Certificate,
+ public CertificateI,
+ public IceUtil::Mutex
+{
+public:
+
+ SChannelCertificateI(CERT_SIGNED_CONTENT_INFO*);
+ ~SChannelCertificateI();
+
+ virtual bool operator==(const IceSSL::Certificate&) const;
+
+ virtual vector<Ice::Byte> getAuthorityKeyIdentifier() const;
+ virtual vector<Ice::Byte> getSubjectKeyIdentifier() const;
+ virtual bool verify(const CertificatePtr&) const;
+ virtual string encode() const;
+
+#ifdef ICE_CPP11_MAPPING
+ virtual chrono::system_clock::time_point getNotAfter() const;
+ virtual chrono::system_clock::time_point getNotBefore() const;
+#else
+ virtual IceUtil::Time getNotAfter() const;
+ virtual IceUtil::Time getNotBefore() const;
+#endif
+ virtual string getSerialNumber() const;
+ virtual DistinguishedName getIssuerDN() const;
+ virtual vector<pair<int, string> > getIssuerAlternativeNames() const;
+ virtual DistinguishedName getSubjectDN() const;
+ virtual vector<pair<int, string> > getSubjectAlternativeNames() const;
+ virtual int getVersion() const;
+ virtual CERT_SIGNED_CONTENT_INFO* getCert() const;
+
+protected:
+
+ virtual void loadX509Extensions() const;
+
+private:
+
+ CERT_SIGNED_CONTENT_INFO* _cert;
+ CERT_INFO* _certInfo;
+};
+
+const Ice::Long TICKS_PER_MSECOND = 10000LL;
+const Ice::Long MSECS_TO_EPOCH = 11644473600000LL;
+
+void
+loadCertificate(PCERT_SIGNED_CONTENT_INFO* cert, const char* buffer, DWORD length)
+{
+ DWORD outLength = length;
+ vector<BYTE> outBuffer;
+ outBuffer.resize(outLength);
+
+ if(!CryptStringToBinary(buffer, length, CRYPT_STRING_BASE64HEADER, &outBuffer[0], &outLength, 0, 0))
+ {
+ //
+ // Base64 data should always be bigger than binary
+ //
+ assert(GetLastError() != ERROR_MORE_DATA);
+ throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
+ }
+
+ DWORD decodedLeng = 0;
+ if(!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_CERT, &outBuffer[0], outLength, CRYPT_DECODE_ALLOC_FLAG, 0,
+ cert, &decodedLeng))
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
+ }
+}
+
+void
+loadCertificate(PCERT_SIGNED_CONTENT_INFO* cert, const string& file)
+{
+ vector<char> buffer;
+ readFile(file, buffer);
+ if(buffer.empty())
+ {
+ throw CertificateReadException(__FILE__, __LINE__, "certificate file " + file + " is empty");
+ }
+ loadCertificate(cert, &buffer[0], static_cast<DWORD>(buffer.size()));
+}
+
+# ifdef ICE_CPP11_MAPPING
+chrono::system_clock::time_point
+# else
+IceUtil::Time
+# endif
+filetimeToTime(FILETIME ftime)
+{
+ Ice::Long value = 0;
+ DWORD* dest = reinterpret_cast<DWORD*>(&value);
+ *dest++ = ftime.dwLowDateTime;
+ *dest = ftime.dwHighDateTime;
+
+ IceUtil::Time time = IceUtil::Time::milliSeconds((value / TICKS_PER_MSECOND) - MSECS_TO_EPOCH);
+
+# ifdef ICE_CPP11_MAPPING
+ return chrono::system_clock::time_point(chrono::microseconds(time.toMicroSeconds()));
+# else
+ return time;
+# endif
+}
+
+string
+certNameToString(CERT_NAME_BLOB* name)
+{
+ assert(name);
+ DWORD length = 0;
+ if(!(length = CertNameToStr(X509_ASN_ENCODING, name, CERT_OID_NAME_STR|CERT_NAME_STR_REVERSE_FLAG, 0, 0)))
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
+ }
+
+ vector<char> buffer(length);
+ if(!CertNameToStr(X509_ASN_ENCODING, name, CERT_OID_NAME_STR|CERT_NAME_STR_REVERSE_FLAG, &buffer[0], length))
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
+ }
+
+ string s(&buffer[0]);
+ for(int i = 0; i < certificateOIDSSize; ++i)
+ {
+ const CertificateOID* certificateOID = &certificateOIDS[i];
+ assert(certificateOID);
+ const string name = string(certificateOID->name) + "=";
+ const string alias = string(certificateOID->alias) + "=";
+ size_t pos = 0;
+ while((pos = s.find(name, pos)) != string::npos)
+ {
+ s.replace(pos, name.size(), alias);
+ }
+ }
+ return s;
+}
+
+vector<pair<int, string> >
+certificateAltNames(CERT_INFO* certInfo, LPCSTR altNameOID)
+{
+ vector<pair<int, string> > altNames;
+
+ PCERT_EXTENSION extension = CertFindExtension(altNameOID, certInfo->cExtension, certInfo->rgExtension);
+ if(extension)
+ {
+ CERT_ALT_NAME_INFO* altName;
+ DWORD length = 0;
+ if(!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_ALTERNATE_NAME, extension->Value.pbData,
+ extension->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, 0, &altName, &length))
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
+ }
+
+ for(DWORD i = 0; i < altName->cAltEntry; ++i)
+ {
+ CERT_ALT_NAME_ENTRY* entry = &altName->rgAltEntry[i];
+
+ switch(entry->dwAltNameChoice)
+ {
+ case CERT_ALT_NAME_RFC822_NAME:
+ {
+ altNames.push_back(make_pair(AltNameEmail, Ice::wstringToString(entry->pwszRfc822Name)));
+ break;
+ }
+ case CERT_ALT_NAME_DNS_NAME:
+ {
+ altNames.push_back(make_pair(AltNameDNS, Ice::wstringToString(entry->pwszDNSName)));
+ break;
+ }
+ case CERT_ALT_NAME_DIRECTORY_NAME:
+ {
+ altNames.push_back(make_pair(AltNameDirectory, certNameToString(&entry->DirectoryName)));
+ break;
+ }
+ case CERT_ALT_NAME_URL:
+ {
+ altNames.push_back(make_pair(AltNameURL, Ice::wstringToString(entry->pwszURL)));
+ break;
+ }
+ case CERT_ALT_NAME_IP_ADDRESS:
+ {
+ if(entry->IPAddress.cbData == 4)
+ {
+ //
+ // IPv4 address
+ //
+ ostringstream os;
+ Byte* src = reinterpret_cast<Byte*>(entry->IPAddress.pbData);
+ for(int j = 0; j < 4;)
+ {
+ int value = 0;
+ Byte* dest = reinterpret_cast<Byte*>(&value);
+ *dest = *src++;
+ os << value;
+ if(++j < 4)
+ {
+ os << ".";
+ }
+ }
+ altNames.push_back(make_pair(AltNAmeIP, os.str()));
+ }
+ //
+ // TODO IPv6 Address support.
+ //
+ break;
+ }
+ default:
+ {
+ // Not supported
+ break;
+ }
+ }
+ }
+ LocalFree(altName);
+ }
+ return altNames;
+}
+
+} // End anonymous namespace
+
+SCHannelX509ExtensionI::SCHannelX509ExtensionI(CERT_EXTENSION extension, const string& oid, const SChannel::CertificatePtr& cert) :
+ _extension(extension),
+ _oid(oid),
+ _cert(cert)
+{
+}
+
+bool
+SCHannelX509ExtensionI::isCritical() const
+{
+ return _extension.fCritical != 0;
+}
+
+string
+SCHannelX509ExtensionI::getOID() const
+{
+ return _oid;
+}
+
+vector<Ice::Byte>
+SCHannelX509ExtensionI::getData() const
+{
+ vector<Ice::Byte> data;
+ data.resize(_extension.Value.cbData);
+ memcpy(&data[0], _extension.Value.pbData, _extension.Value.cbData);
+ return data;
+}
+
+SChannelCertificateI::SChannelCertificateI(CERT_SIGNED_CONTENT_INFO* cert) :
+ _cert(cert),
+ _certInfo(0)
+{
+ if(!_cert)
+ {
+ throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Invalid certificate reference");
+ }
+
+ try
+ {
+ //
+ // Decode certificate info
+ //
+ DWORD length = 0;
+ if(!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, _cert->ToBeSigned.pbData,
+ _cert->ToBeSigned.cbData, CRYPT_DECODE_ALLOC_FLAG, 0, &_certInfo, &length))
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
+ }
+ }
+ catch(...)
+ {
+ LocalFree(_cert);
+ _cert = 0;
+ throw;
+ }
+}
+
+SChannelCertificateI::~SChannelCertificateI()
+{
+ if(_cert)
+ {
+ LocalFree(_cert);
+ if(_certInfo)
+ {
+ LocalFree(_certInfo);
+ }
+ }
+}
+
+bool
+SChannelCertificateI::operator==(const IceSSL::Certificate& r) const
+{
+ const SChannelCertificateI* p = dynamic_cast<const SChannelCertificateI*>(&r);
+ if(!p)
+ {
+ return false;
+ }
+
+ return CertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, _certInfo, p->_certInfo) != 0;
+}
+
+vector<Ice::Byte>
+SChannelCertificateI::getAuthorityKeyIdentifier() const
+{
+ vector<Ice::Byte> keyid;
+ PCERT_EXTENSION extension = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER2, _certInfo->cExtension,
+ _certInfo->rgExtension);
+ if(extension)
+ {
+ CERT_AUTHORITY_KEY_ID2_INFO* decoded;
+ DWORD length = 0;
+ if(!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_AUTHORITY_KEY_ID2, extension->Value.pbData,
+ extension->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, 0, &decoded, &length))
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
+ }
+
+ if(decoded->KeyId.pbData && decoded->KeyId.cbData)
+ {
+ keyid.resize(decoded->KeyId.cbData);
+ memcpy(&keyid[0], decoded->KeyId.pbData, decoded->KeyId.cbData);
+ LocalFree(decoded);
+ }
+ }
+ return keyid;
+}
+
+vector<Ice::Byte>
+SChannelCertificateI::getSubjectKeyIdentifier() const
+{
+ vector<Ice::Byte> keyid;
+ PCERT_EXTENSION extension = CertFindExtension(szOID_SUBJECT_KEY_IDENTIFIER, _certInfo->cExtension,
+ _certInfo->rgExtension);
+ if(extension)
+ {
+ CRYPT_DATA_BLOB* decoded;
+ DWORD length = 0;
+ if(!CryptDecodeObjectEx(X509_ASN_ENCODING, szOID_SUBJECT_KEY_IDENTIFIER, extension->Value.pbData,
+ extension->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, 0, &decoded, &length))
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
+ }
+
+ if(decoded->pbData && decoded->cbData)
+ {
+ keyid.resize(decoded->cbData);
+ memcpy(&keyid[0], decoded->pbData, decoded->cbData);
+ LocalFree(decoded);
+ }
+ }
+ return keyid;
+}
+
+bool
+SChannelCertificateI::verify(const CertificatePtr& cert) const
+{
+ bool result = false;
+ SChannelCertificateI* c = dynamic_cast<SChannelCertificateI*>(cert.get());
+ if(c)
+ {
+ BYTE* buffer = 0;
+ DWORD length = 0;
+ if(!CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, _cert, CRYPT_ENCODE_ALLOC_FLAG , 0, &buffer, &length))
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
+ }
+ result = CryptVerifyCertificateSignature(0, X509_ASN_ENCODING, buffer, length, &c->_certInfo->SubjectPublicKeyInfo) != 0;
+ LocalFree(buffer);
+ }
+ return result;
+}
+
+string
+SChannelCertificateI::encode() const
+{
+ string s;
+ DWORD length = 0;
+ BYTE* buffer = 0;
+ try
+ {
+ if(!CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, _cert, CRYPT_ENCODE_ALLOC_FLAG , 0, &buffer, &length))
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
+ }
+
+ DWORD encodedLength = 0;
+ if(!CryptBinaryToString(buffer, length, CRYPT_STRING_BASE64HEADER | CRYPT_STRING_NOCR, 0, &encodedLength))
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
+ }
+
+ std::vector<char> encoded;
+ encoded.resize(encodedLength);
+ if(!CryptBinaryToString(buffer, length, CRYPT_STRING_BASE64HEADER | CRYPT_STRING_NOCR, &encoded[0],
+ &encodedLength))
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());
+ }
+ LocalFree(buffer);
+ buffer = 0;
+ s.assign(&encoded[0]);
+ }
+ catch(...)
+ {
+ if(buffer)
+ {
+ LocalFree(buffer);
+ }
+ throw;
+ }
+ return s;
+}
+
+# ifdef ICE_CPP11_MAPPING
+chrono::system_clock::time_point
+# else
+IceUtil::Time
+# endif
+SChannelCertificateI::getNotAfter() const
+{
+ return filetimeToTime(_certInfo->NotAfter);
+}
+
+# ifdef ICE_CPP11_MAPPING
+chrono::system_clock::time_point
+# else
+IceUtil::Time
+# endif
+SChannelCertificateI::getNotBefore() const
+{
+ return filetimeToTime(_certInfo->NotBefore);
+}
+
+string
+SChannelCertificateI::getSerialNumber() const
+{
+ ostringstream os;
+ for(int i = _certInfo->SerialNumber.cbData - 1; i >= 0; --i)
+ {
+ unsigned char c = _certInfo->SerialNumber.pbData[i];
+ os.fill('0');
+ os.width(2);
+ os << hex << static_cast<int>(c);
+ if(i)
+ {
+ os << ' ';
+ }
+ }
+ return IceUtilInternal::toUpper(os.str());
+}
+
+DistinguishedName
+SChannelCertificateI::getIssuerDN() const
+{
+ return DistinguishedName(certNameToString(&_certInfo->Issuer));
+}
+
+vector<pair<int, string> >
+SChannelCertificateI::getIssuerAlternativeNames() const
+{
+ return certificateAltNames(_certInfo, szOID_ISSUER_ALT_NAME2);
+}
+
+DistinguishedName
+SChannelCertificateI::getSubjectDN() const
+{
+ return DistinguishedName(certNameToString(&_certInfo->Subject));
+}
+
+vector<pair<int, string> >
+SChannelCertificateI::getSubjectAlternativeNames() const
+{
+ return certificateAltNames(_certInfo, szOID_SUBJECT_ALT_NAME2);
+}
+
+int
+SChannelCertificateI::getVersion() const
+{
+ return _certInfo->dwVersion;
+}
+
+CERT_SIGNED_CONTENT_INFO*
+SChannelCertificateI::getCert() const
+{
+ return _cert;
+}
+
+void
+SChannelCertificateI::loadX509Extensions() const
+{
+ IceUtil::Mutex::Lock sync(*this);
+ if(_extensions.empty())
+ {
+ for(size_t i = 0; i < _certInfo->cExtension; ++i)
+ {
+ CERT_EXTENSION ext = _certInfo->rgExtension[i];
+ _extensions.push_back(ICE_DYNAMIC_CAST(X509Extension,
+ ICE_MAKE_SHARED(SCHannelX509ExtensionI, ext, ext.pszObjId,
+ ICE_DYNAMIC_CAST(SChannel::Certificate, ICE_SHARED_FROM_CONST_THIS(SChannelCertificateI)))));
+ }
+ }
+}
+
+SChannel::CertificatePtr
+SChannel::Certificate::create(CERT_SIGNED_CONTENT_INFO* cert)
+{
+ return ICE_MAKE_SHARED(SChannelCertificateI, cert);
+}
+
+SChannel::CertificatePtr
+SChannel::Certificate::load(const std::string& file)
+{
+ CERT_SIGNED_CONTENT_INFO* cert;
+ loadCertificate(&cert, file);
+ return ICE_MAKE_SHARED(SChannelCertificateI, cert);
+}
+
+SChannel::CertificatePtr
+SChannel::Certificate::decode(const std::string& encoding)
+{
+ CERT_SIGNED_CONTENT_INFO* cert;
+ loadCertificate(&cert, encoding.c_str(), static_cast<DWORD>(encoding.size()));
+ return ICE_MAKE_SHARED(SChannelCertificateI, cert);
+}
diff --git a/cpp/src/IceSSL/SChannelEngine.cpp b/cpp/src/IceSSL/SChannelEngine.cpp
index 37bd41b2ff0..25c62a81ff0 100644
--- a/cpp/src/IceSSL/SChannelEngine.cpp
+++ b/cpp/src/IceSSL/SChannelEngine.cpp
@@ -7,8 +7,10 @@
//
// **********************************************************************
-#include <IceSSL/SSLEngine.h>
+#include <IceSSL/SChannelEngine.h>
+#include <IceSSL/SChannelTransceiverI.h>
#include <IceSSL/Plugin.h>
+#include <IceSSL/Util.h>
#include <Ice/LocalException.h>
#include <Ice/Logger.h>
@@ -19,19 +21,275 @@
#include <IceUtil/FileUtil.h>
#include <Ice/UUID.h>
+#include <wincrypt.h>
+
using namespace std;
using namespace Ice;
using namespace IceUtil;
using namespace IceUtilInternal;
using namespace IceSSL;
-#ifdef ICE_USE_SCHANNEL
-
-Shared* IceSSL::upCast(IceSSL::SChannelEngine* p) { return p; }
+Shared* SChannel::upCast(SChannel::SSLEngine* p)
+{
+ return p;
+}
namespace
{
+void
+addMatchingCertificates(HCERTSTORE source, HCERTSTORE target, DWORD findType, const void* findParam)
+{
+ PCCERT_CONTEXT next = 0;
+ do
+ {
+ if((next = CertFindCertificateInStore(source, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
+ findType, findParam, next)))
+ {
+ if(!CertAddCertificateContextToStore(target, next, CERT_STORE_ADD_ALWAYS, 0))
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: error adding certificate to store:\n" + IceUtilInternal::lastErrorToString());
+ }
+ }
+ }
+ while(next);
+}
+
+vector<PCCERT_CONTEXT>
+findCertificates(const string& location, const string& name, const string& value, vector<HCERTSTORE>& stores)
+{
+ DWORD storeLoc;
+ if(location == "CurrentUser")
+ {
+ storeLoc = CERT_SYSTEM_STORE_CURRENT_USER;
+ }
+ else
+ {
+ storeLoc = CERT_SYSTEM_STORE_LOCAL_MACHINE;
+ }
+
+ HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, storeLoc, Ice::stringToWstring(name).c_str());
+ if(!store)
+ {
+ throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: failed to open certificate store `" + name +
+ "':\n" + IceUtilInternal::lastErrorToString());
+ }
+
+ //
+ // Start with all of the certificates in the collection and filter as necessary.
+ //
+ // - If the value is "*", return all certificates.
+ // - Otherwise, search using key:value pairs. The following keys are supported:
+ //
+ // Issuer
+ // IssuerDN
+ // Serial
+ // Subject
+ // SubjectDN
+ // SubjectKeyId
+ // Thumbprint
+ //
+ // A value must be enclosed in single or double quotes if it contains whitespace.
+ //
+ HCERTSTORE tmpStore = 0;
+ try
+ {
+ 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 != "SUBJECT" && field != "SUBJECTDN" && field != "ISSUER" && field != "ISSUERDN" &&
+ field != "THUMBPRINT" && field != "SUBJECTKEYID" && field != "SERIAL")
+ {
+ 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;
+ }
+ }
+
+ tmpStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 0, 0);
+ if(!tmpStore)
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: error adding certificate to store:\n" + IceUtilInternal::lastErrorToString());
+ }
+
+ if(field == "SUBJECT" || field == "ISSUER")
+ {
+ const wstring argW = Ice::stringToWstring(arg);
+ DWORD findType = field == "SUBJECT" ? CERT_FIND_SUBJECT_STR : CERT_FIND_ISSUER_STR;
+ addMatchingCertificates(store, tmpStore, findType, argW.c_str());
+ }
+ else if(field == "SUBJECTDN" || field == "ISSUERDN")
+ {
+ const wstring argW = Ice::stringToWstring(arg);
+ DWORD flags[] = {
+ CERT_OID_NAME_STR,
+ CERT_OID_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
+ CERT_OID_NAME_STR | CERT_NAME_STR_FORCE_UTF8_DIR_STR_FLAG,
+ CERT_OID_NAME_STR | CERT_NAME_STR_FORCE_UTF8_DIR_STR_FLAG | CERT_NAME_STR_REVERSE_FLAG
+ };
+ for(size_t i = 0; i < sizeof(flags) / sizeof(DWORD); ++i)
+ {
+ DWORD length = 0;
+ if(!CertStrToNameW(X509_ASN_ENCODING, argW.c_str(), flags[i], 0, 0, &length, 0))
+ {
+ throw PluginInitializationException(
+ __FILE__, __LINE__,
+ "IceSSL: invalid value `" + value + "' for `IceSSL.FindCert' property:\n" +
+ IceUtilInternal::lastErrorToString());
+ }
+
+ vector<BYTE> buffer(length);
+ if(!CertStrToNameW(X509_ASN_ENCODING, argW.c_str(), flags[i], 0, &buffer[0], &length, 0))
+ {
+ throw PluginInitializationException(
+ __FILE__, __LINE__,
+ "IceSSL: invalid value `" + value + "' for `IceSSL.FindCert' property:\n" +
+ IceUtilInternal::lastErrorToString());
+ }
+
+ CERT_NAME_BLOB name = { length, &buffer[0] };
+
+ DWORD findType = field == "SUBJECTDN" ? CERT_FIND_SUBJECT_NAME : CERT_FIND_ISSUER_NAME;
+ addMatchingCertificates(store, tmpStore, findType, &name);
+ }
+ }
+ else if(field == "THUMBPRINT" || field == "SUBJECTKEYID")
+ {
+ vector<BYTE> buffer;
+ if(!parseBytes(arg, buffer))
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: invalid `IceSSL.FindCert' property: can't decode the value");
+ }
+
+ CRYPT_HASH_BLOB hash = { static_cast<DWORD>(buffer.size()), &buffer[0] };
+ DWORD findType = field == "THUMBPRINT" ? CERT_FIND_HASH : CERT_FIND_KEY_IDENTIFIER;
+ addMatchingCertificates(store, tmpStore, findType, &hash);
+ }
+ else if(field == "SERIAL")
+ {
+ vector<BYTE> buffer;
+ if(!parseBytes(arg, buffer))
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: invalid value `" + value + "' for `IceSSL.FindCert' property");
+ }
+
+ CRYPT_INTEGER_BLOB serial = { static_cast<DWORD>(buffer.size()), &buffer[0] };
+ PCCERT_CONTEXT next = 0;
+ do
+ {
+ if((next = CertFindCertificateInStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
+ CERT_FIND_ANY, 0, next)))
+ {
+ if(CertCompareIntegerBlob(&serial, &next->pCertInfo->SerialNumber))
+ {
+ if(!CertAddCertificateContextToStore(tmpStore, next, CERT_STORE_ADD_ALWAYS, 0))
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: error adding certificate to store:\n" +
+ IceUtilInternal::lastErrorToString());
+ }
+ }
+ }
+ }
+ while(next);
+ }
+ CertCloseStore(store, 0);
+ store = tmpStore;
+ }
+ }
+ }
+ catch(...)
+ {
+ if(store && store != tmpStore)
+ {
+ CertCloseStore(store, 0);
+ }
+
+ if(tmpStore)
+ {
+ CertCloseStore(tmpStore, 0);
+ tmpStore = 0;
+ }
+ throw;
+ }
+
+ vector<PCCERT_CONTEXT> certs;
+ if(store)
+ {
+ PCCERT_CONTEXT next = 0;
+ do
+ {
+ if((next = CertFindCertificateInStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, 0,
+ next)))
+ {
+ certs.push_back(next);
+ }
+ }
+ while(next);
+ stores.push_back(store);
+ }
+ return certs;
+}
+
+
#if defined(__MINGW32__) || (defined(_MSC_VER) && (_MSC_VER <= 1500))
//
// CERT_CHAIN_ENGINE_CONFIG struct in mingw headers doesn't include
@@ -187,16 +445,15 @@ algorithmId(const string& name)
}
-SChannelEngine::SChannelEngine(const CommunicatorPtr& communicator) :
- SSLEngine(communicator),
- _initialized(false),
+SChannel::SSLEngine::SSLEngine(const CommunicatorPtr& communicator) :
+ IceSSL::SSLEngine(communicator),
_rootStore(0),
_chainEngine(0)
{
}
void
-SChannelEngine::initialize()
+SChannel::SSLEngine::initialize()
{
Mutex::Lock lock(_mutex);
if(_initialized)
@@ -204,7 +461,7 @@ SChannelEngine::initialize()
return;
}
- SSLEngine::initialize();
+ IceSSL::SSLEngine::initialize();
const string prefix = "IceSSL.";
const PropertiesPtr properties = communicator()->getProperties();
@@ -643,7 +900,7 @@ SChannelEngine::initialize()
}
string
-SChannelEngine::getCipherName(ALG_ID cipher) const
+SChannel::SSLEngine::getCipherName(ALG_ID cipher) const
{
switch(cipher)
{
@@ -678,15 +935,8 @@ SChannelEngine::getCipherName(ALG_ID cipher) const
}
}
-bool
-SChannelEngine::initialized() const
-{
- Mutex::Lock lock(_mutex);
- return _initialized;
-}
-
CredHandle
-SChannelEngine::newCredentialsHandle(bool incoming)
+SChannel::SSLEngine::newCredentialsHandle(bool incoming)
{
SCHANNEL_CRED cred;
memset(&cred, 0, sizeof(cred));
@@ -745,13 +995,13 @@ SChannelEngine::newCredentialsHandle(bool incoming)
}
HCERTCHAINENGINE
-SChannelEngine::chainEngine() const
+SChannel::SSLEngine::chainEngine() const
{
return _chainEngine;
}
void
-SChannelEngine::parseCiphers(const std::string& ciphers)
+SChannel::SSLEngine::parseCiphers(const std::string& ciphers)
{
vector<string> tokens;
splitString(ciphers, " \t", tokens);
@@ -766,7 +1016,7 @@ SChannelEngine::parseCiphers(const std::string& ciphers)
}
void
-SChannelEngine::destroy()
+SChannel::SSLEngine::destroy()
{
if(_chainEngine && _chainEngine != HCCE_CURRENT_USER && _chainEngine != HCCE_LOCAL_MACHINE)
{
@@ -809,4 +1059,19 @@ SChannelEngine::destroy()
CertCloseStore(*i, 0);
}
}
-#endif
+
+void
+SChannel::SSLEngine::verifyPeer(const string& address, const NativeConnectionInfoPtr& info, const string& desc)
+{
+ verifyPeerCertName(address, info);
+ IceSSL::SSLEngine::verifyPeer(address, info, desc);
+}
+
+IceInternal::TransceiverPtr
+SChannel::SSLEngine::createTransceiver(const InstancePtr& instance,
+ const IceInternal::TransceiverPtr& delegate,
+ const string& hostOrAdapterName,
+ bool incoming)
+{
+ return new SChannel::TransceiverI(instance, delegate, hostOrAdapterName, incoming);
+}
diff --git a/cpp/src/IceSSL/SChannelEngine.h b/cpp/src/IceSSL/SChannelEngine.h
new file mode 100644
index 00000000000..f62ff654677
--- /dev/null
+++ b/cpp/src/IceSSL/SChannelEngine.h
@@ -0,0 +1,124 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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 ICESSL_SCHANNEL_ENGINE_H
+#define ICESSL_SCHANNEL_ENGINE_H
+
+#include <IceSSL/SSLEngine.h>
+#include <IceSSL/SChannelEngineF.h>
+
+//
+// SECURITY_WIN32 or SECURITY_KERNEL, must be defined before including security.h
+// indicating who is compiling the code.
+//
+# ifdef SECURITY_WIN32
+# undef SECURITY_WIN32
+# endif
+# ifdef SECURITY_KERNEL
+# undef SECURITY_KERNEL
+# endif
+# define SECURITY_WIN32 1
+# include <security.h>
+# include <sspi.h>
+# include <schannel.h>
+# undef SECURITY_WIN32
+
+#if defined(__MINGW32__) || (defined(_MSC_VER) && (_MSC_VER <= 1500))
+
+//
+// Add some definitions missing from MinGW headers.
+//
+
+# ifndef CERT_TRUST_IS_EXPLICIT_DISTRUST
+# define CERT_TRUST_IS_EXPLICIT_DISTRUST 0x04000000
+# endif
+
+# ifndef CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT
+# define CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT 0x08000000
+# endif
+
+# ifndef SECBUFFER_ALERT
+# define SECBUFFER_ALERT 17
+# endif
+
+# ifndef SCH_SEND_ROOT_CERT
+# define SCH_SEND_ROOT_CERT 0x00040000
+# endif
+
+# ifndef SP_PROT_TLS1_1_SERVER
+# define SP_PROT_TLS1_1_SERVER 0x00000100
+# endif
+
+# ifndef SP_PROT_TLS1_1_CLIENT
+# define SP_PROT_TLS1_1_CLIENT 0x00000200
+# endif
+
+# ifndef SP_PROT_TLS1_2_SERVER
+# define SP_PROT_TLS1_2_SERVER 0x00000400
+# endif
+
+# ifndef SP_PROT_TLS1_2_CLIENT
+# define SP_PROT_TLS1_2_CLIENT 0x00000800
+# endif
+
+#endif
+
+namespace IceSSL
+{
+
+namespace SChannel
+{
+
+class SSLEngine : public IceSSL::SSLEngine
+{
+public:
+
+ SSLEngine(const Ice::CommunicatorPtr&);
+
+ //
+ // Setup the engine.
+ //
+ virtual void initialize();
+
+ virtual IceInternal::TransceiverPtr
+ createTransceiver(const InstancePtr&, const IceInternal::TransceiverPtr&, const std::string&, bool);
+
+ //
+ // Destroy the engine.
+ //
+ virtual void destroy();
+
+ virtual void verifyPeer(const std::string&, const NativeConnectionInfoPtr&, const std::string&);
+
+ std::string getCipherName(ALG_ID) const;
+
+ CredHandle newCredentialsHandle(bool);
+
+ HCERTCHAINENGINE chainEngine() const;
+
+private:
+
+ void parseCiphers(const std::string&);
+
+ std::vector<PCCERT_CONTEXT> _allCerts;
+ std::vector<PCCERT_CONTEXT> _importedCerts;
+ DWORD _protocols;
+
+ std::vector<HCERTSTORE> _stores;
+ HCERTSTORE _rootStore;
+
+ HCERTCHAINENGINE _chainEngine;
+ std::vector<ALG_ID> _ciphers;
+};
+
+}
+
+}
+
+#endif
diff --git a/cpp/src/IceSSL/SChannelEngineF.h b/cpp/src/IceSSL/SChannelEngineF.h
new file mode 100644
index 00000000000..68be2d28fa0
--- /dev/null
+++ b/cpp/src/IceSSL/SChannelEngineF.h
@@ -0,0 +1,32 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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 ICESSL_SCHANNEL_ENGINE_F_H
+#define ICESSL_SCHANNEL_ENGINE_F_H
+
+#include <IceUtil/Shared.h>
+#include <Ice/Handle.h>
+
+#include <IceSSL/SChannel.h>
+
+namespace IceSSL
+{
+
+namespace SChannel
+{
+
+class SSLEngine;
+ICESSL_API IceUtil::Shared* upCast(SSLEngine*);
+typedef IceInternal::Handle<SSLEngine> SSLEnginePtr;
+
+}
+
+}
+
+#endif
diff --git a/cpp/src/IceSSL/SChannelPluginI.cpp b/cpp/src/IceSSL/SChannelPluginI.cpp
new file mode 100644
index 00000000000..59cb2d11d1e
--- /dev/null
+++ b/cpp/src/IceSSL/SChannelPluginI.cpp
@@ -0,0 +1,92 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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/PluginI.h>
+#include <IceSSL/SChannelEngine.h>
+
+#include <Ice/Initialize.h>
+
+using namespace std;
+
+namespace
+{
+
+class PluginI : public IceSSL::PluginI
+{
+public:
+
+ PluginI(const Ice::CommunicatorPtr&);
+
+ virtual string getEngineName() const;
+ virtual Ice::Long getEngineVersion() const;
+ virtual IceSSL::CertificatePtr create(CERT_SIGNED_CONTENT_INFO*) const;
+ virtual IceSSL::CertificatePtr load(const std::string&) const;
+ virtual IceSSL::CertificatePtr decode(const std::string&) const;
+};
+
+} // anonymous namespace end
+
+//
+// Plugin implementation.
+//
+PluginI::PluginI(const Ice::CommunicatorPtr& com) :
+ IceSSL::PluginI(com, new IceSSL::SChannel::SSLEngine(com))
+{
+}
+
+string
+PluginI::getEngineName() const
+{
+ return "SChannelEngine";
+}
+
+Ice::Long
+PluginI::getEngineVersion() const
+{
+ return 0;
+}
+
+IceSSL::CertificatePtr
+PluginI::create(CERT_SIGNED_CONTENT_INFO* cert) const
+{
+ return IceSSL::SChannel::Certificate::create(cert);
+}
+
+IceSSL::CertificatePtr
+PluginI::load(const std::string& file) const
+{
+ return IceSSL::SChannel::Certificate::load(file);
+}
+
+IceSSL::CertificatePtr
+PluginI::decode(const std::string& encoding) const
+{
+ return IceSSL::SChannel::Certificate::load(encoding);
+}
+
+//
+// Plug-in factory function.
+//
+extern "C" ICESSL_API Ice::Plugin*
+createIceSSL(const Ice::CommunicatorPtr& communicator, const string& /*name*/, const Ice::StringSeq& /*args*/)
+{
+ return new PluginI(communicator);
+}
+
+IceSSL::CertificatePtr
+IceSSL::Certificate::load(const std::string& file)
+{
+ return IceSSL::SChannel::Certificate::load(file);
+}
+
+IceSSL::CertificatePtr
+IceSSL::Certificate::decode(const std::string& encoding)
+{
+ return IceSSL::SChannel::Certificate::decode(encoding);
+}
diff --git a/cpp/src/IceSSL/SChannelTransceiverI.cpp b/cpp/src/IceSSL/SChannelTransceiverI.cpp
index 8c9ab78d393..caae4dc7fe0 100644
--- a/cpp/src/IceSSL/SChannelTransceiverI.cpp
+++ b/cpp/src/IceSSL/SChannelTransceiverI.cpp
@@ -13,15 +13,13 @@
#include <IceSSL/ConnectionInfo.h>
#include <IceSSL/Instance.h>
-#include <IceSSL/SSLEngine.h>
+#include <IceSSL/SChannelEngine.h>
#include <IceSSL/Util.h>
#include <Ice/Communicator.h>
#include <Ice/LoggerUtil.h>
#include <Ice/Buffer.h>
#include <Ice/LocalException.h>
-#ifdef ICE_USE_SCHANNEL
-
using namespace std;
using namespace Ice;
using namespace IceSSL;
@@ -206,13 +204,13 @@ getSecBufferWithType(const SecBufferDesc& desc, ULONG bufferType)
}
IceInternal::NativeInfoPtr
-IceSSL::TransceiverI::getNativeInfo()
+SChannel::TransceiverI::getNativeInfo()
{
return _delegate->getNativeInfo();
}
IceInternal::SocketOperation
-IceSSL::TransceiverI::sslHandshake()
+SChannel::TransceiverI::sslHandshake()
{
DWORD flags = ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT | ASC_REQ_CONFIDENTIALITY | ASC_REQ_ALLOCATE_MEMORY |
ASC_REQ_STREAM;
@@ -477,7 +475,7 @@ IceSSL::TransceiverI::sslHandshake()
// data before it can decrypt the complete message.
//
size_t
-IceSSL::TransceiverI::decryptMessage(IceInternal::Buffer& buffer)
+SChannel::TransceiverI::decryptMessage(IceInternal::Buffer& buffer)
{
assert(_readBuffer.i != _readBuffer.b.begin() || !_readUnprocessed.b.empty());
@@ -582,7 +580,7 @@ IceSSL::TransceiverI::decryptMessage(IceInternal::Buffer& buffer)
// number of bytes is less than the message size, the function must be called again.
//
size_t
-IceSSL::TransceiverI::encryptMessage(IceInternal::Buffer& buffer)
+SChannel::TransceiverI::encryptMessage(IceInternal::Buffer& buffer)
{
//
// Limit the message size to cbMaximumMessage which is the maximun size data that can be
@@ -622,7 +620,7 @@ IceSSL::TransceiverI::encryptMessage(IceInternal::Buffer& buffer)
}
IceInternal::SocketOperation
-IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::Buffer& writeBuffer)
+SChannel::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::Buffer& writeBuffer)
{
if(_state == StateNotInitialized)
{
@@ -703,7 +701,7 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
IceUtilInternal::lastErrorToString());
}
- CertificatePtr certificate = ICE_MAKE_SHARED(Certificate, cc);
+ CertificatePtr certificate = SChannel::Certificate::create(cc);
_nativeCerts.push_back(certificate);
_certs.push_back(certificate->encode());
}
@@ -787,7 +785,7 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
}
IceInternal::SocketOperation
-IceSSL::TransceiverI::closing(bool initiator, const Ice::LocalException&)
+SChannel::TransceiverI::closing(bool initiator, const Ice::LocalException&)
{
// If we are initiating the connection closure, wait for the peer
// to close the TCP/IP connection. Otherwise, close immediately.
@@ -795,7 +793,7 @@ IceSSL::TransceiverI::closing(bool initiator, const Ice::LocalException&)
}
void
-IceSSL::TransceiverI::close()
+SChannel::TransceiverI::close()
{
if(_sslInitialized)
{
@@ -820,7 +818,7 @@ IceSSL::TransceiverI::close()
}
IceInternal::SocketOperation
-IceSSL::TransceiverI::write(IceInternal::Buffer& buf)
+SChannel::TransceiverI::write(IceInternal::Buffer& buf)
{
if(_state == StateNotInitialized)
{
@@ -855,7 +853,7 @@ IceSSL::TransceiverI::write(IceInternal::Buffer& buf)
}
IceInternal::SocketOperation
-IceSSL::TransceiverI::read(IceInternal::Buffer& buf)
+SChannel::TransceiverI::read(IceInternal::Buffer& buf)
{
if(_state == StateNotInitialized)
{
@@ -896,7 +894,7 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf)
#ifdef ICE_USE_IOCP
bool
-IceSSL::TransceiverI::startWrite(IceInternal::Buffer& buffer)
+SChannel::TransceiverI::startWrite(IceInternal::Buffer& buffer)
{
if(_state == StateNotInitialized)
{
@@ -913,7 +911,7 @@ IceSSL::TransceiverI::startWrite(IceInternal::Buffer& buffer)
}
void
-IceSSL::TransceiverI::finishWrite(IceInternal::Buffer& buf)
+SChannel::TransceiverI::finishWrite(IceInternal::Buffer& buf)
{
if(_state == StateNotInitialized)
{
@@ -935,7 +933,7 @@ IceSSL::TransceiverI::finishWrite(IceInternal::Buffer& buf)
}
void
-IceSSL::TransceiverI::startRead(IceInternal::Buffer& buffer)
+SChannel::TransceiverI::startRead(IceInternal::Buffer& buffer)
{
if(_state == StateNotInitialized)
{
@@ -946,7 +944,7 @@ IceSSL::TransceiverI::startRead(IceInternal::Buffer& buffer)
}
void
-IceSSL::TransceiverI::finishRead(IceInternal::Buffer& buf)
+SChannel::TransceiverI::finishRead(IceInternal::Buffer& buf)
{
if(_state == StateNotInitialized)
{
@@ -973,25 +971,25 @@ IceSSL::TransceiverI::finishRead(IceInternal::Buffer& buf)
#endif
string
-IceSSL::TransceiverI::protocol() const
+SChannel::TransceiverI::protocol() const
{
return _instance->protocol();
}
string
-IceSSL::TransceiverI::toString() const
+SChannel::TransceiverI::toString() const
{
return _delegate->toString();
}
string
-IceSSL::TransceiverI::toDetailedString() const
+SChannel::TransceiverI::toDetailedString() const
{
return toString();
}
Ice::ConnectionInfoPtr
-IceSSL::TransceiverI::getInfo() const
+SChannel::TransceiverI::getInfo() const
{
NativeConnectionInfoPtr info = ICE_MAKE_SHARED(NativeConnectionInfo);
info->underlying = _delegate->getInfo();
@@ -1005,22 +1003,22 @@ IceSSL::TransceiverI::getInfo() const
}
void
-IceSSL::TransceiverI::checkSendSize(const IceInternal::Buffer&)
+SChannel::TransceiverI::checkSendSize(const IceInternal::Buffer&)
{
}
void
-IceSSL::TransceiverI::setBufferSize(int rcvSize, int sndSize)
+SChannel::TransceiverI::setBufferSize(int rcvSize, int sndSize)
{
_delegate->setBufferSize(rcvSize, sndSize);
}
-IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance,
+SChannel::TransceiverI::TransceiverI(const InstancePtr& instance,
const IceInternal::TransceiverPtr& delegate,
const string& hostOrAdapterName,
bool incoming) :
_instance(instance),
- _engine(SChannelEnginePtr::dynamicCast(instance->engine())),
+ _engine(SChannel::SSLEnginePtr::dynamicCast(instance->engine())),
_host(incoming ? "" : hostOrAdapterName),
_adapterName(incoming ? hostOrAdapterName : ""),
_incoming(incoming),
@@ -1032,22 +1030,22 @@ IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance,
_verified(false)
{
}
-IceSSL::TransceiverI::~TransceiverI()
+
+SChannel::TransceiverI::~TransceiverI()
{
}
bool
-IceSSL::TransceiverI::writeRaw(IceInternal::Buffer& buf)
+SChannel::TransceiverI::writeRaw(IceInternal::Buffer& buf)
{
_delegate->write(buf);
return buf.i == buf.b.end();
}
bool
-IceSSL::TransceiverI::readRaw(IceInternal::Buffer& buf)
+SChannel::TransceiverI::readRaw(IceInternal::Buffer& buf)
{
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 b35dad2260e..2f05011a873 100644
--- a/cpp/src/IceSSL/SChannelTransceiverI.h
+++ b/cpp/src/IceSSL/SChannelTransceiverI.h
@@ -13,7 +13,7 @@
#include <IceSSL/Config.h>
#include <IceSSL/InstanceF.h>
#include <IceSSL/Plugin.h>
-#include <IceSSL/SSLEngineF.h>
+#include <IceSSL/SChannelEngineF.h>
#include <Ice/Transceiver.h>
#include <Ice/Network.h>
@@ -21,8 +21,6 @@
#include <Ice/StreamSocket.h>
#include <Ice/WSTransceiver.h>
-#ifdef ICE_USE_SCHANNEL
-
#ifdef SECURITY_WIN32
# undef SECURITY_WIN32
#endif
@@ -40,8 +38,8 @@
namespace IceSSL
{
-class ConnectorI;
-class AcceptorI;
+namespace SChannel
+{
class TransceiverI : public IceInternal::Transceiver
{
@@ -80,8 +78,7 @@ private:
bool writeRaw(IceInternal::Buffer&);
bool readRaw(IceInternal::Buffer&);
- friend class ConnectorI;
- friend class AcceptorI;
+ friend class IceSSL::SChannel::SSLEngine;
enum State
{
@@ -93,7 +90,7 @@ private:
};
const InstancePtr _instance;
- const SChannelEnginePtr _engine;
+ const IceSSL::SChannel::SSLEnginePtr _engine;
const std::string _host;
const std::string _adapterName;
const bool _incoming;
@@ -124,12 +121,12 @@ private:
std::string _cipher;
std::vector<std::string> _certs;
bool _verified;
- std::vector<CertificatePtr> _nativeCerts;
+ std::vector<IceSSL::CertificatePtr> _nativeCerts;
};
typedef IceUtil::Handle<TransceiverI> TransceiverIPtr;
-}
+} // SChannel namespace end
-#endif
+} // IceSSL namespace end
#endif
diff --git a/cpp/src/IceSSL/SSLEngine.cpp b/cpp/src/IceSSL/SSLEngine.cpp
index 355b8fad16f..81f36d38948 100644
--- a/cpp/src/IceSSL/SSLEngine.cpp
+++ b/cpp/src/IceSSL/SSLEngine.cpp
@@ -22,11 +22,13 @@
using namespace std;
using namespace Ice;
+using namespace IceUtil;
using namespace IceSSL;
IceUtil::Shared* IceSSL::upCast(IceSSL::SSLEngine* p) { return p; }
IceSSL::SSLEngine::SSLEngine(const Ice::CommunicatorPtr& communicator) :
+ _initialized(false),
_communicator(communicator),
_logger(communicator->getLogger()),
_trustManager(new TrustManager(communicator))
@@ -80,6 +82,13 @@ IceSSL::SSLEngine::password(bool /*encrypting*/)
}
}
+bool
+IceSSL::SSLEngine::initialized() const
+{
+ Mutex::Lock lock(_mutex);
+ return _initialized;
+}
+
string
IceSSL::SSLEngine::getPassword() const
{
@@ -128,13 +137,8 @@ IceSSL::SSLEngine::initialize()
}
void
-IceSSL::SSLEngine::verifyPeer(const string& address, const NativeConnectionInfoPtr& info, const string& desc)
+IceSSL::SSLEngine::verifyPeerCertName(const string& address, const NativeConnectionInfoPtr& info)
{
- const CertificateVerifierPtr verifier = getCertificateVerifier();
-
-#if defined(ICE_USE_SCHANNEL) || \
- (defined(ICE_USE_OPENSSL) && defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10002000L)
-
//
// For an outgoing connection, we compare the proxy address (if any) against
// fields in the server's certificate (if any).
@@ -219,8 +223,12 @@ IceSSL::SSLEngine::verifyPeer(const string& address, const NativeConnectionInfoP
}
}
}
-#endif
+}
+void
+IceSSL::SSLEngine::verifyPeer(const string& address, const NativeConnectionInfoPtr& info, const string& desc)
+{
+ const CertificateVerifierPtr verifier = getCertificateVerifier();
if(_verifyDepthMax > 0 && static_cast<int>(info->certs.size()) > _verifyDepthMax)
{
ostringstream ostr;
diff --git a/cpp/src/IceSSL/SSLEngine.h b/cpp/src/IceSSL/SSLEngine.h
index 30d88e123a4..422f0c17648 100644
--- a/cpp/src/IceSSL/SSLEngine.h
+++ b/cpp/src/IceSSL/SSLEngine.h
@@ -14,41 +14,17 @@
#include <IceSSL/Util.h>
#include <IceSSL/SSLEngineF.h>
#include <IceSSL/TrustManagerF.h>
+#include <IceSSL/InstanceF.h>
#include <IceUtil/Shared.h>
-#include <IceUtil/Mutex.h>
#include <Ice/CommunicatorF.h>
#include <Ice/Network.h>
-#include <Ice/UniqueRef.h>
-
-#if defined(ICE_USE_SECURE_TRANSPORT)
-# include <Security/Security.h>
-# include <Security/SecureTransport.h>
-#elif defined(ICE_USE_SCHANNEL)
-
-//
-// SECURITY_WIN32 or SECURITY_KERNEL, must be defined before including security.h
-// indicating who is compiling the code.
-//
-# ifdef SECURITY_WIN32
-# undef SECURITY_WIN32
-# endif
-# ifdef SECURITY_KERNEL
-# undef SECURITY_KERNEL
-# endif
-# define SECURITY_WIN32 1
-# include <security.h>
-# include <sspi.h>
-# include <schannel.h>
-# undef SECURITY_WIN32
-#elif defined(ICE_OS_UWP)
-# include <mutex>
-#endif
+#include <Ice/TransceiverF.h>
namespace IceSSL
{
-class SSLEngine : public IceUtil::Shared
+class ICESSL_API SSLEngine : public IceUtil::Shared
{
public:
@@ -66,7 +42,7 @@ public:
//
virtual void initialize() = 0;
- virtual bool initialized() const = 0;
+ virtual bool initialized() const;
//
// Destroy the engine.
@@ -74,9 +50,16 @@ public:
virtual void destroy() = 0;
//
+ // Create a transceiver using the engine specific implementation
+ //
+ virtual IceInternal::TransceiverPtr
+ createTransceiver(const InstancePtr&, const IceInternal::TransceiverPtr&, const std::string&, bool) = 0;
+
+ //
// Verify peer certificate
//
- void verifyPeer(const std::string&, const NativeConnectionInfoPtr&, const std::string&);
+ virtual void verifyPeer(const std::string&, const NativeConnectionInfoPtr&, const std::string&);
+ void verifyPeerCertName(const std::string&, const NativeConnectionInfoPtr&);
CertificateVerifierPtr getCertificateVerifier() const;
PasswordPromptPtr getPasswordPrompt() const;
@@ -89,6 +72,11 @@ public:
int securityTraceLevel() const;
std::string securityTraceCategory() const;
+protected:
+
+ bool _initialized;
+ IceUtil::Mutex _mutex;
+
private:
const Ice::CommunicatorPtr _communicator;
@@ -106,186 +94,6 @@ private:
std::string _securityTraceCategory;
};
-#if defined(ICE_USE_SECURE_TRANSPORT)
-
-class SecureTransportEngine : public SSLEngine
-{
-public:
-
- SecureTransportEngine(const Ice::CommunicatorPtr&);
-
- virtual void initialize();
- virtual bool initialized() const;
- virtual void destroy();
-
- SSLContextRef newContext(bool);
- CFArrayRef getCertificateAuthorities() const;
- std::string getCipherName(SSLCipherSuite) const;
-
-private:
-
- void parseCiphers(const std::string&);
-
- bool _initialized;
- IceInternal::UniqueRef<CFArrayRef> _certificateAuthorities;
- IceInternal::UniqueRef<CFArrayRef> _chain;
-
- SSLProtocol _protocolVersionMax;
- SSLProtocol _protocolVersionMin;
-
- std::string _defaultDir;
-
-#if TARGET_OS_IPHONE==0
- std::vector<char> _dhParams;
-#endif
- std::vector<SSLCipherSuite> _ciphers;
- IceUtil::Mutex _mutex;
-};
-
-#elif defined(ICE_USE_SCHANNEL)
-
-
-#if defined(__MINGW32__) || (defined(_MSC_VER) && (_MSC_VER <= 1500))
-
-//
-// Add some definitions missing from MinGW headers.
-//
-
-# ifndef CERT_TRUST_IS_EXPLICIT_DISTRUST
-# define CERT_TRUST_IS_EXPLICIT_DISTRUST 0x04000000
-# endif
-
-# ifndef CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT
-# define CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT 0x08000000
-# endif
-
-# ifndef SECBUFFER_ALERT
-# define SECBUFFER_ALERT 17
-# endif
-
-# ifndef SCH_SEND_ROOT_CERT
-# define SCH_SEND_ROOT_CERT 0x00040000
-# endif
-
-# ifndef SP_PROT_TLS1_1_SERVER
-# define SP_PROT_TLS1_1_SERVER 0x00000100
-# endif
-
-# ifndef SP_PROT_TLS1_1_CLIENT
-# define SP_PROT_TLS1_1_CLIENT 0x00000200
-# endif
-
-# ifndef SP_PROT_TLS1_2_SERVER
-# define SP_PROT_TLS1_2_SERVER 0x00000400
-# endif
-
-# ifndef SP_PROT_TLS1_2_CLIENT
-# define SP_PROT_TLS1_2_CLIENT 0x00000800
-# endif
-
-#endif
-
-class SChannelEngine : public SSLEngine
-{
-public:
-
- SChannelEngine(const Ice::CommunicatorPtr&);
-
- //
- // Setup the engine.
- //
- virtual void initialize();
-
- virtual bool initialized() const;
-
- //
- // Destroy the engine.
- //
- virtual void destroy();
-
- std::string getCipherName(ALG_ID) const;
-
- CredHandle newCredentialsHandle(bool);
-
- HCERTCHAINENGINE chainEngine() const;
-
-private:
-
- void parseCiphers(const std::string&);
-
- bool _initialized;
- std::vector<PCCERT_CONTEXT> _allCerts;
- std::vector<PCCERT_CONTEXT> _importedCerts;
- DWORD _protocols;
- IceUtil::Mutex _mutex;
-
- std::vector<HCERTSTORE> _stores;
- HCERTSTORE _rootStore;
-
- HCERTCHAINENGINE _chainEngine;
- std::vector<ALG_ID> _ciphers;
-};
-
-#elif defined(ICE_OS_UWP)
-
-class UWPEngine : public SSLEngine
-{
-public:
-
- UWPEngine(const Ice::CommunicatorPtr&);
-
- virtual void initialize();
- virtual bool initialized() const;
- virtual void destroy();
- //virtual std::shared_ptr<Certificate> ca();
- virtual std::shared_ptr<Certificate> certificate();
-
-private:
-
- //std::shared_ptr<Certificate> _ca;
- std::shared_ptr<Certificate> _certificate;
- bool _initialized;
- std::mutex _mutex;
-};
-
-#else // OpenSSL
-
-class OpenSSLEngine : public SSLEngine
-{
-public:
-
- OpenSSLEngine(const Ice::CommunicatorPtr&);
- ~OpenSSLEngine();
-
- virtual void initialize();
- virtual bool initialized() const;
- virtual void destroy();
-
-# ifndef OPENSSL_NO_DH
- DH* dhParams(int);
-# endif
- SSL_CTX* context() const;
- void context(SSL_CTX*);
- std::string sslErrors() const;
-
-private:
-
- SSL_METHOD* getMethod(int);
- void setOptions(int);
- 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;
-
-# ifndef OPENSSL_NO_DH
- DHParamsPtr _dhParams;
-# endif
- IceUtil::Mutex _mutex;
-};
-#endif
-
}
#endif
diff --git a/cpp/src/IceSSL/SSLEngineF.h b/cpp/src/IceSSL/SSLEngineF.h
index 55e1a385a03..525c54fbe94 100644
--- a/cpp/src/IceSSL/SSLEngineF.h
+++ b/cpp/src/IceSSL/SSLEngineF.h
@@ -12,7 +12,6 @@
#include <IceUtil/Shared.h>
#include <Ice/Handle.h>
-
#include <IceSSL/Plugin.h>
namespace IceSSL
@@ -22,24 +21,6 @@ class SSLEngine;
ICESSL_API IceUtil::Shared* upCast(SSLEngine*);
typedef IceInternal::Handle<SSLEngine> SSLEnginePtr;
-#if defined(ICE_USE_SECURE_TRANSPORT)
-class SecureTransportEngine;
-ICESSL_API IceUtil::Shared* upCast(SecureTransportEngine*);
-typedef IceInternal::Handle<SecureTransportEngine> SecureTransportEnginePtr;
-#elif defined(ICE_USE_SCHANNEL)
-class SChannelEngine;
-ICESSL_API IceUtil::Shared* upCast(SChannelEngine*);
-typedef IceInternal::Handle<SChannelEngine> SChannelEnginePtr;
-#elif defined(ICE_OS_UWP)
-class UWPEngine;
-ICESSL_API IceUtil::Shared* upCast(UWPEngine*);
-typedef IceInternal::Handle<UWPEngine> UWPEnginePtr;
-#else // OpenSSL
-class OpenSSLEngine;
-ICESSL_API IceUtil::Shared* upCast(OpenSSLEngine*);
-typedef IceInternal::Handle<OpenSSLEngine> OpenSSLEnginePtr;
-#endif
-
}
#endif
diff --git a/cpp/src/IceSSL/SecureTransportCertificateI.cpp b/cpp/src/IceSSL/SecureTransportCertificateI.cpp
new file mode 100644
index 00000000000..f988de667a5
--- /dev/null
+++ b/cpp/src/IceSSL/SecureTransportCertificateI.cpp
@@ -0,0 +1,858 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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/Plugin.h>
+#include <IceSSL/SecureTransport.h>
+#include <IceSSL/CertificateI.h>
+#include <IceSSL/SecureTransportUtil.h>
+#include <IceSSL/RFC2253.h>
+
+#include <Ice/UniqueRef.h>
+#include <Ice/Base64.h>
+
+#include <IceUtil/MutexPtrLock.h>
+
+#include <Security/Security.h>
+
+using namespace Ice;
+using namespace IceInternal;
+using namespace IceSSL;
+using namespace IceSSL::SecureTransport;
+
+using namespace std;
+
+namespace
+{
+
+string
+certificateOIDAlias(const string& name)
+{
+ for(int i = 0; i < certificateOIDSSize; ++i)
+ {
+ const CertificateOID* certificateOID = &certificateOIDS[i];
+ assert(certificateOID);
+ if(name == certificateOID->name)
+ {
+ return certificateOID->alias;
+ }
+ }
+ return name;
+}
+
+string
+escapeX509Name(const string& name)
+{
+ ostringstream os;
+ for(string::const_iterator i = name.begin(); i != name.end(); ++i)
+ {
+ switch(*i)
+ {
+ case ',':
+ case '=':
+ case '+':
+ case '<':
+ case '>':
+ case '#':
+ case ';':
+ {
+ os << '\\';
+ }
+ default:
+ {
+ break;
+ }
+ }
+ os << *i;
+ }
+ return os.str();
+}
+
+#ifdef ICE_USE_SECURE_TRANSPORT_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
+
+
+class SecureTransportCertificateI : public IceSSL::SecureTransport::Certificate,
+ public IceSSL::CertificateI
+{
+public:
+
+ SecureTransportCertificateI(SecCertificateRef);
+
+ virtual bool operator==(const IceSSL::Certificate&) const;
+
+ virtual vector<Ice::Byte> getAuthorityKeyIdentifier() const;
+ virtual vector<Ice::Byte> getSubjectKeyIdentifier() const;
+ virtual bool verify(const IceSSL::CertificatePtr&) const;
+ virtual string encode() const;
+
+#ifdef ICE_CPP11_MAPPING
+ virtual chrono::system_clock::time_point getNotAfter() const;
+ virtual chrono::system_clock::time_point getNotBefore() const;
+#else
+ virtual IceUtil::Time getNotAfter() const;
+ virtual IceUtil::Time getNotBefore() const;
+#endif
+
+ virtual string getSerialNumber() const;
+ virtual DistinguishedName getIssuerDN() const;
+ virtual vector<pair<int, string> > getIssuerAlternativeNames() const;
+ virtual DistinguishedName getSubjectDN() const;
+ virtual vector<pair<int, string> > getSubjectAlternativeNames() const;
+ virtual int getVersion() const;
+ virtual SecCertificateRef getCert() const;
+
+private:
+
+ IceInternal::UniqueRef<SecCertificateRef> _cert;
+
+#ifdef ICE_USE_SECURE_TRANSPORT_IOS
+ void initializeAttributes() const;
+
+ mutable IceInternal::UniqueRef<CFDataRef> _subject;
+ mutable IceInternal::UniqueRef<CFDataRef> _issuer;
+ mutable std::string _serial;
+ mutable int _version;
+#endif
+};
+
+#ifndef 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)
+{
+ assert(key == kSecOIDX509V1IssuerName || key == kSecOIDX509V1SubjectName);
+ list<pair<string, string> > rdnPairs;
+ UniqueRef<CFDictionaryRef> property(getCertificateProperty(cert, key));
+ if(property)
+ {
+ CFArrayRef dn = static_cast<CFArrayRef>(CFDictionaryGetValue(property.get(), kSecPropertyKeyValue));
+ int size = CFArrayGetCount(dn);
+ for(int i = 0; i < size; ++i)
+ {
+ CFDictionaryRef dict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(dn, i));
+ rdnPairs.push_front(make_pair(
+ certificateOIDAlias(
+ fromCFString((static_cast<CFStringRef>(CFDictionaryGetValue(dict, kSecPropertyKeyLabel))))),
+ escapeX509Name(
+ fromCFString(static_cast<CFStringRef>(CFDictionaryGetValue(dict, kSecPropertyKeyValue))))));
+ }
+ }
+ return DistinguishedName(rdnPairs);
+}
+
+vector<pair<int, string> >
+getX509AltName(SecCertificateRef cert, CFTypeRef key)
+{
+ assert(key == kSecOIDIssuerAltName || key == kSecOIDSubjectAltName);
+ UniqueRef<CFDictionaryRef> property(getCertificateProperty(cert, key));
+
+ vector<pair<int, string> > pairs;
+ if(property)
+ {
+ CFArrayRef names = static_cast<CFArrayRef>(CFDictionaryGetValue(property.get(), kSecPropertyKeyValue));
+ int size = CFArrayGetCount(names);
+
+ for(int i = 0; i < size; ++i)
+ {
+ CFDictionaryRef dict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(names, i));
+
+ int type = certificateAlternativeNameType(
+ fromCFString(static_cast<CFStringRef>(CFDictionaryGetValue(dict, kSecPropertyKeyLabel))));
+ if(type != -1)
+ {
+ CFStringRef v = static_cast<CFStringRef>(CFDictionaryGetValue(dict, kSecPropertyKeyValue));
+ CFStringRef t = static_cast<CFStringRef>(CFDictionaryGetValue(dict, kSecPropertyKeyType));
+ if(CFEqual(t, kSecPropertyTypeString) || CFEqual(t, kSecPropertyTypeTitle))
+ {
+ pairs.push_back(make_pair(type, fromCFString(v)));
+ }
+ else if(CFEqual(t, kSecPropertyTypeURL))
+ {
+ pairs.push_back(make_pair(type, fromCFString(CFURLGetString((CFURLRef)v))));
+ }
+ else if(CFEqual(t, kSecPropertyTypeSection))
+ {
+ CFArrayRef section = (CFArrayRef)v;
+ ostringstream os;
+ for(int i = 0, count = CFArrayGetCount(section); i < count;)
+ {
+ CFDictionaryRef d = (CFDictionaryRef)CFArrayGetValueAtIndex(section, i);
+
+ CFStringRef sectionLabel = static_cast<CFStringRef>(CFDictionaryGetValue(d, kSecPropertyKeyLabel));
+ CFStringRef sectionValue = static_cast<CFStringRef>(CFDictionaryGetValue(d, kSecPropertyKeyValue));
+
+ os << certificateOIDAlias(fromCFString(sectionLabel)) << "=" << fromCFString(sectionValue);
+ if(++i < count)
+ {
+ os << ",";
+ }
+ }
+ pairs.push_back(make_pair(type, os.str()));
+ }
+ }
+ }
+ }
+ return pairs;
+}
+
+#ifdef ICE_CPP11_MAPPING
+chrono::system_clock::time_point
+#else
+IceUtil::Time
+#endif
+getX509Date(SecCertificateRef cert, CFTypeRef key)
+{
+ assert(key == kSecOIDX509V1ValidityNotAfter || key == kSecOIDX509V1ValidityNotBefore);
+ UniqueRef<CFDictionaryRef> property(getCertificateProperty(cert, key));
+ CFAbsoluteTime seconds = 0;
+ if(property)
+ {
+ CFNumberRef date = static_cast<CFNumberRef>(CFDictionaryGetValue(property.get(), kSecPropertyKeyValue));
+ CFNumberGetValue(date, kCFNumberDoubleType, &seconds);
+ }
+
+ IceUtil::Time time = IceUtil::Time::secondsDouble(kCFAbsoluteTimeIntervalSince1970 + seconds);
+
+#ifdef ICE_CPP11_MAPPING
+ return chrono::system_clock::time_point(chrono::microseconds(time.toMicroSeconds()));
+#else
+ return time;
+#endif
+}
+
+string
+getX509String(SecCertificateRef cert, CFTypeRef key)
+{
+ assert(key == kSecOIDX509V1SerialNumber || key == kSecOIDX509V1Version);
+ UniqueRef<CFDictionaryRef> property(getCertificateProperty(cert, key));
+ return property ?
+ fromCFString(static_cast<CFStringRef>(CFDictionaryGetValue(property.get(), kSecPropertyKeyValue))) : "";
+}
+#endif
+
+} // end anonymous namespace
+
+SecureTransportCertificateI::SecureTransportCertificateI(SecCertificateRef cert) : _cert(cert)
+{
+ if(!_cert)
+ {
+ throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Invalid certificate reference");
+ }
+}
+
+bool
+SecureTransportCertificateI::operator==(const IceSSL::Certificate& r) const
+{
+ const SecureTransportCertificateI* p = dynamic_cast<const SecureTransportCertificateI*>(&r);
+ if(!p)
+ {
+ return false;
+ }
+ return CFEqual(_cert.get(), p->_cert.get());
+}
+
+vector<Ice::Byte>
+SecureTransportCertificateI::getAuthorityKeyIdentifier() const
+{
+#ifdef ICE_USE_SECURE_TRANSPORT_IOS
+ throw Ice::FeatureNotSupportedException(__FILE__, __LINE__);
+#else // MacOS
+ vector<Ice::Byte> keyid;
+
+ UniqueRef<CFDictionaryRef> property(getCertificateProperty(_cert.get(), kSecOIDAuthorityKeyIdentifier));
+ if(property)
+ {
+ CFTypeRef type = 0;
+ CFTypeRef value;
+ if(CFDictionaryGetValueIfPresent(property.get(), kSecPropertyKeyType, &type))
+ {
+ if(CFEqual(type, kSecPropertyTypeSection))
+ {
+ if(CFDictionaryGetValueIfPresent(property.get(), kSecPropertyKeyValue, &value))
+ {
+ if(CFArrayGetCount(static_cast<CFArrayRef>(value)) >= 0)
+ {
+ value = CFArrayGetValueAtIndex(static_cast<CFArrayRef>(value), 1);
+ type = CFDictionaryGetValue(static_cast<CFDictionaryRef>(value), kSecPropertyKeyType);
+ }
+ }
+ }
+
+ if(CFEqual(type, kSecPropertyTypeData))
+ {
+ CFDataRef data = static_cast<CFDataRef>(
+ CFDictionaryGetValue(static_cast<CFDictionaryRef>(value), kSecPropertyKeyValue));
+ keyid.resize(CFDataGetLength(data));
+ memcpy(&keyid[0], CFDataGetBytePtr(data), CFDataGetLength(data));
+ }
+ }
+ }
+ return keyid;
+#endif
+}
+
+vector<Ice::Byte>
+SecureTransportCertificateI::getSubjectKeyIdentifier() const
+{
+#ifdef ICE_USE_SECURE_TRANSPORT_IOS
+ throw Ice::FeatureNotSupportedException(__FILE__, __LINE__);
+#else // MacOS
+ vector<Ice::Byte> keyid;
+ UniqueRef<CFDictionaryRef> property(getCertificateProperty(_cert.get(), kSecOIDSubjectKeyIdentifier));
+ if(property)
+ {
+ CFTypeRef type = 0;
+ CFTypeRef value;
+ if(CFDictionaryGetValueIfPresent(property.get(), kSecPropertyKeyType, &type))
+ {
+ if(CFEqual(type, kSecPropertyTypeSection))
+ {
+ if(CFDictionaryGetValueIfPresent(property.get(), kSecPropertyKeyValue, &value))
+ {
+ if(CFArrayGetCount(static_cast<CFArrayRef>(value)) >= 0)
+ {
+ value = CFArrayGetValueAtIndex(static_cast<CFArrayRef>(value), 1);
+ type = CFDictionaryGetValue(static_cast<CFDictionaryRef>(value), kSecPropertyKeyType);
+ }
+ }
+ }
+
+ if(CFEqual(type, kSecPropertyTypeData))
+ {
+ CFDataRef data = static_cast<CFDataRef>(
+ CFDictionaryGetValue(static_cast<CFDictionaryRef>(value), kSecPropertyKeyValue));
+ keyid.resize(CFDataGetLength(data));
+ memcpy(&keyid[0], CFDataGetBytePtr(data), CFDataGetLength(data));
+ }
+ }
+ }
+ return keyid;
+#endif
+}
+
+bool
+SecureTransportCertificateI::verify(const IceSSL::CertificatePtr& cert) const
+{
+ bool valid = false;
+ SecureTransportCertificateI* c = dynamic_cast<SecureTransportCertificateI*>(cert.get());
+ if(c)
+ {
+ //
+ // 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.
+ //
+#ifdef ICE_USE_SECURE_TRANSPORT_IOS
+ initializeAttributes();
+ c->initializeAttributes();
+ valid = CFEqual(_issuer.get(), c->_subject.get());
+#else // MacOS
+ UniqueRef<CFErrorRef> error;
+ UniqueRef<CFDataRef> issuer(SecCertificateCopyNormalizedIssuerContent(_cert.get(), &error.get()));
+ if(error)
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, "certificate error:\n" + sslErrorToString(error.get()));
+ }
+ UniqueRef<CFDataRef> subject(SecCertificateCopyNormalizedSubjectContent(c->getCert(), &error.get()));
+ if(error)
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, "certificate error:\n" + sslErrorToString(error.get()));
+ }
+
+ //
+ // The certificate issuer must match the CA subject.
+ //
+ valid = CFEqual(issuer.get(), subject.get());
+#endif
+ if(valid)
+ {
+ UniqueRef<SecPolicyRef> policy(SecPolicyCreateBasicX509());
+ UniqueRef<SecTrustRef> trust;
+ OSStatus err = 0;;
+ if((err = SecTrustCreateWithCertificates(_cert.get(), policy.get(), &trust.get())))
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, sslErrorToString(err));
+ }
+
+ SecCertificateRef certs[1] = { c->getCert() };
+ UniqueRef<CFArrayRef> anchorCertificates(
+ CFArrayCreate(kCFAllocatorDefault, (const void**)&certs, 1, &kCFTypeArrayCallBacks));
+ if((err = SecTrustSetAnchorCertificates(trust.get(), anchorCertificates.get())))
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, sslErrorToString(err));
+ }
+
+ SecTrustResultType trustResult = kSecTrustResultInvalid;
+ if((err = SecTrustEvaluate(trust.get(), &trustResult)))
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, sslErrorToString(err));
+ }
+
+ valid = trustResult == kSecTrustResultUnspecified;
+ }
+ }
+ return valid;
+}
+
+string
+SecureTransportCertificateI::encode() const
+{
+#ifdef ICE_USE_SECURE_TRANSPORT_IOS
+ UniqueRef<CFDataRef> cert(SecCertificateCopyData(_cert.get()));
+ vector<unsigned char> data(CFDataGetBytePtr(cert.get()), CFDataGetBytePtr(cert.get()) + CFDataGetLength(cert.get()));
+ ostringstream os;
+ os << "-----BEGIN CERTIFICATE-----\n";
+ os << IceInternal::Base64::encode(data);
+ os << "-----END CERTIFICATE-----\n";
+ return os.str();
+#else // MacOS
+ UniqueRef<CFDataRef> exported;
+ OSStatus err = SecItemExport(_cert.get(), kSecFormatPEMSequence, kSecItemPemArmour, 0, &exported.get());
+ if(err != noErr)
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, sslErrorToString(err));
+ }
+ return string(reinterpret_cast<const char*>(CFDataGetBytePtr(exported.get())), CFDataGetLength(exported.get()));
+#endif
+}
+
+#ifdef ICE_CPP11_MAPPING
+chrono::system_clock::time_point
+#else
+IceUtil::Time
+#endif
+SecureTransportCertificateI::getNotAfter() const
+{
+#ifdef ICE_USE_SECURE_TRANSPORT_IOS
+ throw Ice::FeatureNotSupportedException(__FILE__, __LINE__);
+#else // MacOS
+ return getX509Date(_cert.get(), kSecOIDX509V1ValidityNotAfter);
+#endif
+}
+
+#ifdef ICE_CPP11_MAPPING
+chrono::system_clock::time_point
+#else
+IceUtil::Time
+#endif
+SecureTransportCertificateI::getNotBefore() const
+{
+#ifdef ICE_USE_SECURE_TRANSPORT_IOS
+ throw Ice::FeatureNotSupportedException(__FILE__, __LINE__);
+#else // MacOS
+ return getX509Date(_cert.get(), kSecOIDX509V1ValidityNotBefore);
+#endif
+}
+
+string
+SecureTransportCertificateI::getSerialNumber() const
+{
+#ifdef ICE_USE_SECURE_TRANSPORT_IOS
+ initializeAttributes();
+ return _serial;
+#else // MacOS
+ return getX509String(_cert.get(), kSecOIDX509V1SerialNumber);
+#endif
+}
+
+DistinguishedName
+SecureTransportCertificateI::getIssuerDN() const
+{
+#ifdef ICE_USE_SECURE_TRANSPORT_IOS
+ initializeAttributes();
+ return _issuer ? DistinguishedName(ASN1Parser(_issuer.get()).parse()) : DistinguishedName("");
+#else // MacOS
+ return getX509Name(_cert.get(), kSecOIDX509V1IssuerName);
+#endif
+}
+
+vector<pair<int, string> >
+SecureTransportCertificateI::getIssuerAlternativeNames() const
+{
+#if defined(ICE_USE_SECURE_TRANSPORT_IOS)
+ throw FeatureNotSupportedException(__FILE__, __LINE__);
+#else // MacOS
+ return getX509AltName(_cert.get(), kSecOIDIssuerAltName);
+#endif
+}
+
+DistinguishedName
+SecureTransportCertificateI::getSubjectDN() const
+{
+#ifdef ICE_USE_SECURE_TRANSPORT_IOS
+ initializeAttributes();
+ if(_subject)
+ {
+ return DistinguishedName(ASN1Parser(_subject.get()).parse());
+ }
+ else
+ {
+ UniqueRef<CFStringRef> subjectSummary(SecCertificateCopySubjectSummary(_cert.get()));
+ return DistinguishedName("CN=" + fromCFString(subjectSummary.get()));
+ }
+#else // MacOS
+ return getX509Name(_cert.get(), kSecOIDX509V1SubjectName);
+#endif
+}
+
+vector<pair<int, string> >
+SecureTransportCertificateI::getSubjectAlternativeNames() const
+{
+#ifdef ICE_USE_SECURE_TRANSPORT_IOS
+ throw FeatureNotSupportedException(__FILE__, __LINE__);
+#else // MacOS
+ return getX509AltName(_cert.get(), kSecOIDSubjectAltName);
+#endif
+}
+
+int
+SecureTransportCertificateI::getVersion() const
+{
+#ifdef ICE_USE_SECURE_TRANSPORT_IOS
+ initializeAttributes();
+ return _version;
+#else // MacOS
+ return atoi(getX509String(_cert.get(), kSecOIDX509V1Version).c_str()) - 1;
+#endif
+}
+
+SecCertificateRef
+SecureTransportCertificateI::getCert() const
+{
+ return _cert.get();
+}
+
+#ifdef ICE_USE_SECURE_TRANSPORT_IOS
+
+IceUtil::Mutex* globalMutex = 0;
+
+class Init
+{
+public:
+
+ Init()
+ {
+ globalMutex = new IceUtil::Mutex;
+ }
+
+ ~Init()
+ {
+ delete globalMutex;
+ globalMutex = 0;
+ }
+};
+
+Init init;
+
+void
+SecureTransportCertificateI::initializeAttributes() const
+{
+ //
+ // 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);
+
+ if(_subject)
+ {
+ return;
+ }
+
+ UniqueRef<CFMutableDictionaryRef> query(
+ CFDictionaryCreateMutable(0, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ CFDictionarySetValue(query.get(), kSecValueRef, _cert.get());
+ CFDictionarySetValue(query.get(), kSecReturnAttributes, kCFBooleanTrue);
+
+ UniqueRef<CFDictionaryRef> attributes(0);
+ OSStatus err;
+ if((err = SecItemAdd(query.get(), reinterpret_cast<CFTypeRef*>(&attributes.get()))) == errSecDuplicateItem)
+ {
+ CFDictionarySetValue(query.get(), kSecClass, kSecClassCertificate);
+ err = SecItemCopyMatching(query.get(), reinterpret_cast<CFTypeRef*>(&attributes.get()));
+ }
+ else
+ {
+ query.reset(CFDictionaryCreateMutable(0, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ CFDictionarySetValue(query.get(), kSecClass, kSecClassCertificate);
+ CFDictionarySetValue(query.get(), kSecValueRef, _cert.get());
+ err = SecItemDelete(query.get());
+ }
+
+ if(err != noErr)
+ {
+ _subject.reset(0);
+ _issuer.reset(0);
+ throw CertificateEncodingException(__FILE__, __LINE__, sslErrorToString(err));
+ }
+
+ _subject.retain(static_cast<CFDataRef>(CFDictionaryGetValue(attributes.get(), kSecAttrSubject)));
+ _issuer.retain(static_cast<CFDataRef>(CFDictionaryGetValue(attributes.get(), kSecAttrIssuer)));
+ CFDataRef serial = static_cast<CFDataRef>(CFDictionaryGetValue(attributes.get(), 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 = static_cast<CFNumberRef>(CFDictionaryGetValue(attributes.get(), kSecAttrCertificateType));
+ if(!CFNumberGetValue(version, kCFNumberIntType, &_version))
+ {
+ _version = -1;
+ }
+}
+#endif
+
+IceSSL::SecureTransport::CertificatePtr
+IceSSL::SecureTransport::Certificate::create(SecCertificateRef cert)
+{
+ return ICE_MAKE_SHARED(SecureTransportCertificateI, cert);
+}
+
+IceSSL::SecureTransport::CertificatePtr
+IceSSL::SecureTransport::Certificate::load(const std::string& file)
+{
+ string resolved;
+ if(checkPath(file, "", false, resolved))
+ {
+ return ICE_MAKE_SHARED(SecureTransportCertificateI, loadCertificate(resolved));
+ }
+ else
+ {
+ throw CertificateReadException(__FILE__, __LINE__, "error opening file " + file);
+ }
+}
+
+IceSSL::SecureTransport::CertificatePtr
+IceSSL::SecureTransport::Certificate::decode(const std::string& encoding)
+{
+#ifdef 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(SecureTransportCertificateI, cert);
+#else // MacOS
+ UniqueRef<CFDataRef> data(
+ CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
+ reinterpret_cast<const UInt8*>(encoding.c_str()),
+ encoding.size(), kCFAllocatorNull));
+
+ SecExternalFormat format = kSecFormatUnknown;
+ SecExternalItemType type = kSecItemTypeCertificate;
+
+ SecItemImportExportKeyParameters params;
+ memset(&params, 0, sizeof(params));
+ params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
+
+ UniqueRef<CFArrayRef> items;
+ OSStatus err = SecItemImport(data.get(), 0, &format, &type, 0, &params, 0, &items.get());
+ if(err)
+ {
+ throw CertificateEncodingException(__FILE__, __LINE__, sslErrorToString(err));
+ }
+
+ UniqueRef<SecKeychainItemRef> item;
+ item.retain(static_cast<SecKeychainItemRef>(const_cast<void*>(CFArrayGetValueAtIndex(items.get(), 0))));
+ assert(SecCertificateGetTypeID() == CFGetTypeID(item.get()));
+ return ICE_MAKE_SHARED(SecureTransportCertificateI, reinterpret_cast<SecCertificateRef>(item.release()));
+#endif
+}
diff --git a/cpp/src/IceSSL/SecureTransportEngine.cpp b/cpp/src/IceSSL/SecureTransportEngine.cpp
index 03664becba8..307b82ea62e 100644
--- a/cpp/src/IceSSL/SecureTransportEngine.cpp
+++ b/cpp/src/IceSSL/SecureTransportEngine.cpp
@@ -9,6 +9,9 @@
#include <IceSSL/Config.h>
+#include <IceSSL/SecureTransportEngineF.h>
+#include <IceSSL/SecureTransportEngine.h>
+
#include <IceUtil/FileUtil.h>
#include <IceUtil/StringUtil.h>
#include <IceUtil/MutexPtrLock.h>
@@ -20,12 +23,11 @@
#include <Ice/LoggerUtil.h>
#include <IceSSL/SecureTransportTransceiverI.h>
+#include <IceSSL/SecureTransportUtil.h>
#include <IceSSL/Plugin.h>
#include <IceSSL/SSLEngine.h>
#include <IceSSL/Util.h>
-#ifdef ICE_USE_SECURE_TRANSPORT
-
#include <regex.h>
using namespace std;
@@ -33,6 +35,7 @@ using namespace IceUtil;
using namespace Ice;
using namespace IceInternal;
using namespace IceSSL;
+using namespace IceSSL::SecureTransport;
namespace
{
@@ -780,11 +783,14 @@ parseProtocol(const string& p)
}
-IceUtil::Shared* IceSSL::upCast(IceSSL::SecureTransportEngine* p) { return p; }
+IceUtil::Shared*
+IceSSL::SecureTransport::upCast(IceSSL::SecureTransport::SSLEngine* p)
+{
+ return p;
+}
-IceSSL::SecureTransportEngine::SecureTransportEngine(const Ice::CommunicatorPtr& communicator) :
- SSLEngine(communicator),
- _initialized(false),
+IceSSL::SecureTransport::SSLEngine::SSLEngine(const Ice::CommunicatorPtr& communicator) :
+ IceSSL::SSLEngine(communicator),
_certificateAuthorities(0),
_chain(0),
_protocolVersionMax(kSSLProtocolUnknown),
@@ -792,18 +798,11 @@ IceSSL::SecureTransportEngine::SecureTransportEngine(const Ice::CommunicatorPtr&
{
}
-bool
-IceSSL::SecureTransportEngine::initialized() const
-{
- IceUtil::Mutex::Lock lock(_mutex);
- return _initialized;
-}
-
//
// Setup the engine.
//
void
-IceSSL::SecureTransportEngine::initialize()
+IceSSL::SecureTransport::SSLEngine::initialize()
{
IceUtil::Mutex::Lock lock(_mutex);
if(_initialized)
@@ -811,7 +810,7 @@ IceSSL::SecureTransportEngine::initialize()
return;
}
- SSLEngine::initialize();
+ IceSSL::SSLEngine::initialize();
const PropertiesPtr properties = communicator()->getProperties();
@@ -1007,12 +1006,22 @@ IceSSL::SecureTransportEngine::initialize()
// Destroy the engine.
//
void
-IceSSL::SecureTransportEngine::destroy()
+IceSSL::SecureTransport::SSLEngine::destroy()
+{
+}
+
+IceInternal::TransceiverPtr
+IceSSL::SecureTransport::SSLEngine::createTransceiver(const InstancePtr& instance,
+ const IceInternal::TransceiverPtr& delegate,
+ const string& hostOrAdapterName,
+ bool incoming)
{
+ return new IceSSL::SecureTransport::TransceiverI(instance, delegate, hostOrAdapterName, incoming);
}
+
SSLContextRef
-IceSSL::SecureTransportEngine::newContext(bool incoming)
+IceSSL::SecureTransport::SSLEngine::newContext(bool incoming)
{
SSLContextRef ssl = SSLCreateContext(kCFAllocatorDefault, incoming ? kSSLServerSide : kSSLClientSide,
kSSLStreamType);
@@ -1054,7 +1063,7 @@ IceSSL::SecureTransportEngine::newContext(bool incoming)
if((err = SSLSetDiffieHellmanParams(ssl, &_dhParams[0], _dhParams.size())))
{
throw SecurityException(__FILE__, __LINE__,
- "IceSSL: unable to create the trust object:\n" + errorToString(err));
+ "IceSSL: unable to create the trust object:\n" + sslErrorToString(err));
}
}
#endif
@@ -1063,14 +1072,14 @@ IceSSL::SecureTransportEngine::newContext(bool incoming)
if(_chain && (err = SSLSetCertificate(ssl, _chain.get())))
{
throw SecurityException(__FILE__, __LINE__,
- "IceSSL: error while setting the SSL context certificate:\n" + errorToString(err));
+ "IceSSL: error while setting the SSL context certificate:\n" + sslErrorToString(err));
}
if(!_ciphers.empty())
{
if((err = SSLSetEnabledCiphers(ssl, &_ciphers[0], _ciphers.size())))
{
- throw SecurityException(__FILE__, __LINE__, "IceSSL: error while setting ciphers:\n" + errorToString(err));
+ throw SecurityException(__FILE__, __LINE__, "IceSSL: error while setting ciphers:\n" + sslErrorToString(err));
}
}
@@ -1078,7 +1087,7 @@ IceSSL::SecureTransportEngine::newContext(bool incoming)
kSSLSessionOptionBreakOnServerAuth,
true)))
{
- throw SecurityException(__FILE__, __LINE__, "IceSSL: error while setting SSL option:\n" + errorToString(err));
+ throw SecurityException(__FILE__, __LINE__, "IceSSL: error while setting SSL option:\n" + sslErrorToString(err));
}
if(_protocolVersionMax != kSSLProtocolUnknown)
@@ -1086,7 +1095,7 @@ IceSSL::SecureTransportEngine::newContext(bool incoming)
if((err = SSLSetProtocolVersionMax(ssl, _protocolVersionMax)))
{
throw SecurityException(__FILE__, __LINE__,
- "IceSSL: error while setting SSL protocol version max:\n" + errorToString(err));
+ "IceSSL: error while setting SSL protocol version max:\n" + sslErrorToString(err));
}
}
@@ -1095,7 +1104,7 @@ IceSSL::SecureTransportEngine::newContext(bool incoming)
if((err = SSLSetProtocolVersionMin(ssl, _protocolVersionMin)))
{
throw SecurityException(__FILE__, __LINE__,
- "IceSSL: error while setting SSL protocol version min:\n" + errorToString(err));
+ "IceSSL: error while setting SSL protocol version min:\n" + sslErrorToString(err));
}
}
@@ -1103,19 +1112,19 @@ IceSSL::SecureTransportEngine::newContext(bool incoming)
}
CFArrayRef
-IceSSL::SecureTransportEngine::getCertificateAuthorities() const
+IceSSL::SecureTransport::SSLEngine::getCertificateAuthorities() const
{
return _certificateAuthorities.get();
}
string
-IceSSL::SecureTransportEngine::getCipherName(SSLCipherSuite cipher) const
+IceSSL::SecureTransport::SSLEngine::getCipherName(SSLCipherSuite cipher) const
{
return CiphersHelper::cipherName(cipher);
}
void
-IceSSL::SecureTransportEngine::parseCiphers(const string& ciphers)
+IceSSL::SecureTransport::SSLEngine::parseCiphers(const string& ciphers)
{
vector<string> tokens;
vector<CipherExpression> cipherExpressions;
@@ -1204,7 +1213,7 @@ IceSSL::SecureTransportEngine::parseCiphers(const string& ciphers)
if(err)
{
throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: unable to get supported ciphers list:\n" + errorToString(err));
+ "IceSSL: unable to get supported ciphers list:\n" + sslErrorToString(err));
}
vector<SSLCipherSuite> enabled;
@@ -1280,6 +1289,3 @@ IceSSL::SecureTransportEngine::parseCiphers(const string& ciphers)
"\nThe result cipher list does not contain any entries");
}
}
-
-
-#endif
diff --git a/cpp/src/IceSSL/SecureTransportEngine.h b/cpp/src/IceSSL/SecureTransportEngine.h
new file mode 100644
index 00000000000..21960de78dc
--- /dev/null
+++ b/cpp/src/IceSSL/SecureTransportEngine.h
@@ -0,0 +1,60 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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 ICESSL_SECURE_TRANSPORT_ENGINE_H
+#define ICESSL_SECURE_TRANSPORT_ENGINE_H
+
+#include <IceSSL/SSLEngine.h>
+#include <Ice/UniqueRef.h>
+
+#include <Security/Security.h>
+#include <Security/SecureTransport.h>
+
+namespace IceSSL
+{
+
+namespace SecureTransport
+{
+
+class SSLEngine : public IceSSL::SSLEngine
+{
+public:
+
+ SSLEngine(const Ice::CommunicatorPtr&);
+
+ virtual void initialize();
+ virtual void destroy();
+ virtual IceInternal::TransceiverPtr
+ createTransceiver(const InstancePtr&, const IceInternal::TransceiverPtr&, const std::string&, bool);
+
+ SSLContextRef newContext(bool);
+ CFArrayRef getCertificateAuthorities() const;
+ std::string getCipherName(SSLCipherSuite) const;
+
+private:
+
+ void parseCiphers(const std::string&);
+
+ IceInternal::UniqueRef<CFArrayRef> _certificateAuthorities;
+ IceInternal::UniqueRef<CFArrayRef> _chain;
+
+ SSLProtocol _protocolVersionMax;
+ SSLProtocol _protocolVersionMin;
+
+#if TARGET_OS_IPHONE==0
+ std::vector<char> _dhParams;
+#endif
+ std::vector<SSLCipherSuite> _ciphers;
+};
+
+} // SecureTransport namespace end
+
+} // IceSSL namespace end
+
+#endif
diff --git a/cpp/src/IceSSL/SecureTransportEngineF.h b/cpp/src/IceSSL/SecureTransportEngineF.h
new file mode 100644
index 00000000000..e75a041635b
--- /dev/null
+++ b/cpp/src/IceSSL/SecureTransportEngineF.h
@@ -0,0 +1,31 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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 ICESSL_SECURE_TRANSPORT_ENGINE_F_H
+#define ICESSL_SECURE_TRANSPORT_ENGINE_F_H
+
+#include <IceSSL/Plugin.h>
+#include <IceUtil/Shared.h>
+#include <Ice/Handle.h>
+
+namespace IceSSL
+{
+
+namespace SecureTransport
+{
+
+class SSLEngine;
+ICESSL_API IceUtil::Shared* upCast(SSLEngine*);
+typedef IceInternal::Handle<SSLEngine> SSLEnginePtr;
+
+}
+
+}
+
+#endif
diff --git a/cpp/src/IceSSL/SecureTransportPluginI.cpp b/cpp/src/IceSSL/SecureTransportPluginI.cpp
new file mode 100644
index 00000000000..3d11563b521
--- /dev/null
+++ b/cpp/src/IceSSL/SecureTransportPluginI.cpp
@@ -0,0 +1,94 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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/PluginI.h>
+#include <IceSSL/SecureTransport.h>
+#include <IceSSL/SecureTransportEngine.h>
+
+#include <Ice/Initialize.h>
+
+using namespace Ice;
+using namespace std;
+
+namespace
+{
+
+class PluginI : public IceSSL::PluginI
+{
+public:
+
+ PluginI(const Ice::CommunicatorPtr&);
+
+ virtual string getEngineName() const;
+ virtual Ice::Long getEngineVersion() const;
+ virtual IceSSL::CertificatePtr create(SecCertificateRef) const;
+ virtual IceSSL::CertificatePtr load(const std::string&) const;
+ virtual IceSSL::CertificatePtr decode(const std::string&) const;
+};
+
+} // anonymous namespace end
+
+//
+// Plugin implementation.
+//
+PluginI::PluginI(const Ice::CommunicatorPtr& com) :
+ IceSSL::PluginI(com, new IceSSL::SecureTransport::SSLEngine(com))
+{
+}
+
+string
+PluginI::getEngineName() const
+{
+ return "SecureTransport";
+}
+
+Ice::Long
+PluginI::getEngineVersion() const
+{
+ return 0;
+}
+
+IceSSL::CertificatePtr
+PluginI::create(SecCertificateRef cert) const
+{
+ return IceSSL::SecureTransport::Certificate::create(cert);
+}
+
+IceSSL::CertificatePtr
+PluginI::load(const std::string& file) const
+{
+ return IceSSL::SecureTransport::Certificate::load(file);
+}
+
+IceSSL::CertificatePtr
+PluginI::decode(const std::string& encoding) const
+{
+ return IceSSL::SecureTransport::Certificate::load(encoding);
+}
+
+//
+// Plug-in factory function.
+//
+extern "C" ICESSL_API Ice::Plugin*
+createIceSSL(const Ice::CommunicatorPtr& communicator, const string& /*name*/, const Ice::StringSeq& /*args*/)
+{
+ return new PluginI(communicator);
+}
+
+IceSSL::CertificatePtr
+IceSSL::Certificate::load(const std::string& file)
+{
+ return IceSSL::SecureTransport::Certificate::load(file);
+}
+
+IceSSL::CertificatePtr
+IceSSL::Certificate::decode(const std::string& encoding)
+{
+ return IceSSL::SecureTransport::Certificate::decode(encoding);
+}
diff --git a/cpp/src/IceSSL/SecureTransportTransceiverI.cpp b/cpp/src/IceSSL/SecureTransportTransceiverI.cpp
index 123d5a09a22..2cbd7fe0bd9 100644
--- a/cpp/src/IceSSL/SecureTransportTransceiverI.cpp
+++ b/cpp/src/IceSSL/SecureTransportTransceiverI.cpp
@@ -9,17 +9,17 @@
#include <IceSSL/SecureTransportTransceiverI.h>
#include <IceSSL/Instance.h>
-#include <IceSSL/SSLEngine.h>
+#include <IceSSL/SecureTransportEngine.h>
+#include <IceSSL/SecureTransportUtil.h>
#include <Ice/LoggerUtil.h>
#include <Ice/LocalException.h>
-#ifdef ICE_USE_SECURE_TRANSPORT
-
using namespace std;
using namespace Ice;
using namespace IceInternal;
using namespace IceSSL;
+using namespace IceSSL::SecureTransport;
namespace
{
@@ -97,7 +97,9 @@ socketRead(SSLConnectionRef connection, void* data, size_t* length)
}
bool
-checkTrustResult(SecTrustRef trust, const SecureTransportEnginePtr& engine, const IceSSL::InstancePtr& instance,
+checkTrustResult(SecTrustRef trust,
+ const IceSSL::SecureTransport::SSLEnginePtr& engine,
+ const IceSSL::InstancePtr& instance,
const string& host)
{
OSStatus err = noErr;
@@ -106,7 +108,7 @@ checkTrustResult(SecTrustRef trust, const SecureTransportEnginePtr& engine, cons
{
if((err = SecTrustSetAnchorCertificates(trust, engine->getCertificateAuthorities())))
{
- throw SecurityException(__FILE__, __LINE__, "IceSSL: handshake failure:\n" + errorToString(err));
+ throw SecurityException(__FILE__, __LINE__, "IceSSL: handshake failure:\n" + sslErrorToString(err));
}
//
@@ -114,7 +116,7 @@ checkTrustResult(SecTrustRef trust, const SecureTransportEnginePtr& engine, cons
//
if((err = SecTrustSetNetworkFetchAllowed(trust, false)))
{
- throw SecurityException(__FILE__, __LINE__, "IceSSL: handshake failure:\n" + errorToString(err));
+ throw SecurityException(__FILE__, __LINE__, "IceSSL: handshake failure:\n" + sslErrorToString(err));
}
//
@@ -126,13 +128,13 @@ checkTrustResult(SecTrustRef trust, const SecureTransportEnginePtr& engine, cons
UniqueRef<CFArrayRef> policies;
if((err = SecTrustCopyPolicies(trust, &policies.get())))
{
- throw SecurityException(__FILE__, __LINE__, "IceSSL: handshake failure:\n" + errorToString(err));
+ throw SecurityException(__FILE__, __LINE__, "IceSSL: handshake failure:\n" + sslErrorToString(err));
}
UniqueRef<CFMutableArrayRef> newPolicies(CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, policies.get()));
CFArrayAppendValue(newPolicies.get(), policy.release());
if((err = SecTrustSetPolicies(trust, newPolicies.release())))
{
- throw SecurityException(__FILE__, __LINE__, "IceSSL: handshake failure:\n" + errorToString(err));
+ throw SecurityException(__FILE__, __LINE__, "IceSSL: handshake failure:\n" + sslErrorToString(err));
}
}
@@ -141,7 +143,7 @@ checkTrustResult(SecTrustRef trust, const SecureTransportEnginePtr& engine, cons
//
if((err = SecTrustEvaluate(trust, &trustResult)))
{
- throw SecurityException(__FILE__, __LINE__, "IceSSL: handshake failure:\n" + errorToString(err));
+ throw SecurityException(__FILE__, __LINE__, "IceSSL: handshake failure:\n" + sslErrorToString(err));
}
}
@@ -190,13 +192,13 @@ checkTrustResult(SecTrustRef trust, const SecureTransportEnginePtr& engine, cons
}
IceInternal::NativeInfoPtr
-IceSSL::TransceiverI::getNativeInfo()
+IceSSL::SecureTransport::TransceiverI::getNativeInfo()
{
return _delegate->getNativeInfo();
}
IceInternal::SocketOperation
-IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::Buffer& writeBuffer)
+IceSSL::SecureTransport::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::Buffer& writeBuffer)
{
if(!_connected)
{
@@ -225,13 +227,13 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
if((err = SSLSetIOFuncs(_ssl.get(), socketRead, socketWrite)))
{
throw SecurityException(__FILE__, __LINE__, "IceSSL: setting IO functions failed\n" +
- errorToString(err));
+ sslErrorToString(err));
}
if((err = SSLSetConnection(_ssl.get(), reinterpret_cast<SSLConnectionRef>(this))))
{
throw SecurityException(__FILE__, __LINE__, "IceSSL: setting SSL connection failed\n" +
- errorToString(err));
+ sslErrorToString(err));
}
}
@@ -279,7 +281,7 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
ostringstream os;
os << "IceSSL: ssl error occurred for new " << (_incoming ? "incoming" : "outgoing") << " connection:\n"
- << _delegate->toString() << "\n" << errorToString(err);
+ << _delegate->toString() << "\n" << sslErrorToString(err);
throw ProtocolException(__FILE__, __LINE__, os.str());
}
@@ -288,7 +290,7 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
SecCertificateRef cert = SecTrustGetCertificateAtIndex(_trust.get(), i);
CFRetain(cert);
- CertificatePtr certificate = ICE_MAKE_SHARED(Certificate, cert);
+ CertificatePtr certificate = IceSSL::SecureTransport::Certificate::create(cert);
_nativeCerts.push_back(certificate);
_certs.push_back(certificate->encode());
}
@@ -330,7 +332,7 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
}
IceInternal::SocketOperation
-IceSSL::TransceiverI::closing(bool initiator, const Ice::LocalException&)
+IceSSL::SecureTransport::TransceiverI::closing(bool initiator, const Ice::LocalException&)
{
// If we are initiating the connection closure, wait for the peer
// to close the TCP/IP connection. Otherwise, close immediately.
@@ -338,7 +340,7 @@ IceSSL::TransceiverI::closing(bool initiator, const Ice::LocalException&)
}
void
-IceSSL::TransceiverI::close()
+IceSSL::SecureTransport::TransceiverI::close()
{
_trust.reset(0);
if(_ssl)
@@ -351,7 +353,7 @@ IceSSL::TransceiverI::close()
}
IceInternal::SocketOperation
-IceSSL::TransceiverI::write(IceInternal::Buffer& buf)
+IceSSL::SecureTransport::TransceiverI::write(IceInternal::Buffer& buf)
{
if(!_connected)
{
@@ -396,7 +398,7 @@ IceSSL::TransceiverI::write(IceInternal::Buffer& buf)
//
if(err <= -9800 && err >= -9849)
{
- throw ProtocolException(__FILE__, __LINE__, "IceSSL: error during write:\n" + errorToString(err));
+ throw ProtocolException(__FILE__, __LINE__, "IceSSL: error during write:\n" + sslErrorToString(err));
}
errno = err;
@@ -430,7 +432,7 @@ IceSSL::TransceiverI::write(IceInternal::Buffer& buf)
}
IceInternal::SocketOperation
-IceSSL::TransceiverI::read(IceInternal::Buffer& buf)
+IceSSL::SecureTransport::TransceiverI::read(IceInternal::Buffer& buf)
{
if(!_connected)
{
@@ -469,7 +471,7 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf)
//
if(err <= -9800 && err >= -9849)
{
- throw ProtocolException(__FILE__, __LINE__, "IceSSL: error during read:\n" + errorToString(err));
+ throw ProtocolException(__FILE__, __LINE__, "IceSSL: error during read:\n" + sslErrorToString(err));
}
errno = err;
@@ -506,25 +508,25 @@ IceSSL::TransceiverI::read(IceInternal::Buffer& buf)
}
string
-IceSSL::TransceiverI::protocol() const
+IceSSL::SecureTransport::TransceiverI::protocol() const
{
return _instance->protocol();
}
string
-IceSSL::TransceiverI::toString() const
+IceSSL::SecureTransport::TransceiverI::toString() const
{
return _delegate->toString();
}
string
-IceSSL::TransceiverI::toDetailedString() const
+IceSSL::SecureTransport::TransceiverI::toDetailedString() const
{
return toString();
}
Ice::ConnectionInfoPtr
-IceSSL::TransceiverI::getInfo() const
+IceSSL::SecureTransport::TransceiverI::getInfo() const
{
NativeConnectionInfoPtr info = ICE_MAKE_SHARED(NativeConnectionInfo);
info->underlying = _delegate->getInfo();
@@ -538,22 +540,22 @@ IceSSL::TransceiverI::getInfo() const
}
void
-IceSSL::TransceiverI::checkSendSize(const IceInternal::Buffer&)
+IceSSL::SecureTransport::TransceiverI::checkSendSize(const IceInternal::Buffer&)
{
}
void
-IceSSL::TransceiverI::setBufferSize(int rcvSize, int sndSize)
+IceSSL::SecureTransport::TransceiverI::setBufferSize(int rcvSize, int sndSize)
{
_delegate->setBufferSize(rcvSize, sndSize);
}
-IceSSL::TransceiverI::TransceiverI(const IceSSL::InstancePtr& instance,
- const IceInternal::TransceiverPtr& delegate,
- const string& hostOrAdapterName,
- bool incoming) :
+IceSSL::SecureTransport::TransceiverI::TransceiverI(const IceSSL::InstancePtr& instance,
+ const IceInternal::TransceiverPtr& delegate,
+ const string& hostOrAdapterName,
+ bool incoming) :
_instance(instance),
- _engine(SecureTransportEnginePtr::dynamicCast(instance->engine())),
+ _engine(IceSSL::SecureTransport::SSLEnginePtr::dynamicCast(instance->engine())),
_host(incoming ? "" : hostOrAdapterName),
_adapterName(incoming ? hostOrAdapterName : ""),
_incoming(incoming),
@@ -564,12 +566,12 @@ IceSSL::TransceiverI::TransceiverI(const IceSSL::InstancePtr& instance,
{
}
-IceSSL::TransceiverI::~TransceiverI()
+IceSSL::SecureTransport::TransceiverI::~TransceiverI()
{
}
OSStatus
-IceSSL::TransceiverI::writeRaw(const char* data, size_t* length) const
+IceSSL::SecureTransport::TransceiverI::writeRaw(const char* data, size_t* length) const
{
_flags &= ~SSLWantWrite;
@@ -602,7 +604,7 @@ IceSSL::TransceiverI::writeRaw(const char* data, size_t* length) const
}
OSStatus
-IceSSL::TransceiverI::readRaw(char* data, size_t* length) const
+IceSSL::SecureTransport::TransceiverI::readRaw(char* data, size_t* length) const
{
_flags &= ~SSLWantRead;
@@ -633,5 +635,3 @@ IceSSL::TransceiverI::readRaw(char* data, size_t* length) const
}
return noErr;
}
-
-#endif
diff --git a/cpp/src/IceSSL/SecureTransportTransceiverI.h b/cpp/src/IceSSL/SecureTransportTransceiverI.h
index 3053faab3e9..a73771eabc7 100644
--- a/cpp/src/IceSSL/SecureTransportTransceiverI.h
+++ b/cpp/src/IceSSL/SecureTransportTransceiverI.h
@@ -12,15 +12,13 @@
#include <IceSSL/Config.h>
#include <IceSSL/InstanceF.h>
-#include <IceSSL/SSLEngineF.h>
+#include <IceSSL/SecureTransportEngineF.h>
#include <IceSSL/Plugin.h>
#include <Ice/Transceiver.h>
#include <Ice/UniqueRef.h>
#include <Ice/Network.h>
-#ifdef ICE_USE_SECURE_TRANSPORT
-
#include <Security/Security.h>
#include <Security/SecureTransport.h>
#include <CoreFoundation/CoreFoundation.h>
@@ -28,8 +26,8 @@
namespace IceSSL
{
-class ConnectorI;
-class AcceptorI;
+namespace SecureTransport
+{
class TransceiverI : public IceInternal::Transceiver
{
@@ -58,11 +56,10 @@ private:
TransceiverI(const InstancePtr&, const IceInternal::TransceiverPtr&, const std::string&, bool);
virtual ~TransceiverI();
- friend class ConnectorI;
- friend class AcceptorI;
+ friend class IceSSL::SecureTransport::SSLEngine;
const InstancePtr _instance;
- const SecureTransportEnginePtr _engine;
+ const SSLEnginePtr _engine;
const std::string _host;
const std::string _adapterName;
const bool _incoming;
@@ -89,8 +86,8 @@ private:
};
typedef IceUtil::Handle<TransceiverI> TransceiverIPtr;
-}
+} // SecureTransport namespace end
-#endif
+} // IceSSL namespace end
#endif
diff --git a/cpp/src/IceSSL/SecureTransportUtil.cpp b/cpp/src/IceSSL/SecureTransportUtil.cpp
new file mode 100644
index 00000000000..1108560cd8b
--- /dev/null
+++ b/cpp/src/IceSSL/SecureTransportUtil.cpp
@@ -0,0 +1,855 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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/SecureTransportUtil.h>
+#include <IceSSL/Plugin.h>
+
+#include <Ice/Base64.h>
+#include <Ice/UniqueRef.h>
+
+#include <IceUtil/FileUtil.h>
+#include <IceUtil/StringUtil.h>
+
+#include <fstream>
+
+#include <Security/Security.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+using namespace Ice;
+using namespace IceInternal;
+using namespace IceSSL;
+using namespace IceSSL::SecureTransport;
+using namespace std;
+
+
+namespace
+{
+
+CFMutableDataRef
+readCertFile(const string& file)
+{
+ ifstream is(IceUtilInternal::streamFilename(file).c_str(), 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);
+
+ UniqueRef<CFMutableDataRef> data(CFDataCreateMutable(kCFAllocatorDefault, size));
+ CFDataSetLength(data.get(), size);
+ is.read(reinterpret_cast<char*>(CFDataGetMutableBytePtr(data.get())), size);
+ if(!is.good())
+ {
+ throw CertificateReadException(__FILE__, __LINE__, "error reading file " + file);
+ }
+ return data.release();
+}
+
+}
+
+string
+IceSSL::SecureTransport::sslErrorToString(CFErrorRef err)
+{
+ ostringstream os;
+ if(err)
+ {
+ UniqueRef<CFStringRef> s(CFErrorCopyDescription(err));
+ os << "(error: " << CFErrorGetCode(err) << " description: " << fromCFString(s.get()) << ")";
+ }
+ return os.str();
+}
+
+string
+IceSSL::SecureTransport::sslErrorToString(OSStatus status)
+{
+ ostringstream os;
+ os << "(error: " << status;
+#if defined(ICE_USE_SECURE_TRANSPORT_MACOS)
+ UniqueRef<CFStringRef> s(SecCopyErrorMessageString(status, 0));
+ if(s)
+ {
+ os << " description: " << fromCFString(s.get());
+ }
+#endif
+ os << ")";
+ return os.str();
+}
+
+#if defined(ICE_USE_SECURE_TRANSPORT_MACOS)
+CFDictionaryRef
+IceSSL::SecureTransport::getCertificateProperty(SecCertificateRef cert, CFTypeRef key)
+{
+ UniqueRef<CFDictionaryRef> property;
+ UniqueRef<CFArrayRef> keys(CFArrayCreate(ICE_NULLPTR, &key , 1, &kCFTypeArrayCallBacks));
+ UniqueRef<CFErrorRef> err;
+ UniqueRef<CFDictionaryRef> values(SecCertificateCopyValues(cert, keys.get(), &err.get()));
+ if(err)
+ {
+ ostringstream os;
+ os << "IceSSL: error getting property for certificate:\n" << sslErrorToString(err);
+ throw CertificateReadException(__FILE__, __LINE__, os.str());
+ }
+
+ assert(values);
+ property.retain(static_cast<CFDictionaryRef>(CFDictionaryGetValue(values.get(), key)));
+ return property.release();
+}
+
+namespace
+{
+
+//
+// Check the certificate basic constraints to check if the certificate is marked as a CA.
+//
+bool
+isCA(SecCertificateRef cert)
+{
+ UniqueRef<CFDictionaryRef> property(getCertificateProperty(cert, kSecOIDBasicConstraints));
+ if(property)
+ {
+ CFArrayRef propertyValues = static_cast<CFArrayRef>(CFDictionaryGetValue(property.get(), kSecPropertyKeyValue));
+ for(int i = 0, size = CFArrayGetCount(propertyValues); i < size; ++i)
+ {
+ CFDictionaryRef dict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(propertyValues, i));
+ CFStringRef label = static_cast<CFStringRef>(CFDictionaryGetValue(dict, kSecPropertyKeyLabel));
+ if(CFEqual(label, CFSTR("Certificate Authority")))
+ {
+ return CFEqual(static_cast<CFStringRef>(CFDictionaryGetValue(dict, kSecPropertyKeyValue)), CFSTR("Yes"));
+ }
+ }
+ }
+ return false;
+}
+
+//
+// Load keychain items (Certificates or Private Keys) from a file. On return items param contain
+// the list of items, the caller must release it.
+//
+CFArrayRef
+loadKeychainItems(const string& file, SecExternalItemType type, SecKeychainRef keychain, const string& passphrase,
+ const PasswordPromptPtr& prompt, int retryMax)
+{
+ UniqueRef<CFMutableDataRef> data(readCertFile(file));
+
+ SecItemImportExportKeyParameters params;
+ memset(&params, 0, sizeof(params));
+ params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
+ params.flags |= kSecKeyNoAccessControl;
+ if(!passphrase.empty())
+ {
+ params.passphrase = toCFString(passphrase);
+ }
+
+ UniqueRef<CFArrayRef> items;
+ SecExternalItemType importType = type;
+ SecExternalFormat format = type == kSecItemTypeUnknown ? kSecFormatPKCS12 : kSecFormatUnknown;
+ UniqueRef<CFStringRef> path(toCFString(file));
+ OSStatus err = SecItemImport(data.get(), path.get(), &format, &importType, 0, &params, keychain, &items.get());
+
+ //
+ // If passphrase failure and no password was configured, we obtain
+ // the password from the given prompt or configure the import to
+ // prompt the user with an alert dialog.
+ //
+ UniqueRef<CFStringRef> passphraseHolder;
+ UniqueRef<CFStringRef> alertPromptHolder;
+ if(passphrase.empty() &&
+ (err == errSecPassphraseRequired || err == errSecInvalidData || err == errSecPkcs12VerifyFailure))
+ {
+ if(!prompt)
+ {
+ params.flags |= kSecKeySecurePassphrase;
+ ostringstream os;
+ os << "Enter the password for\n" << file;
+ alertPromptHolder.reset(toCFString(os.str()));
+ params.alertPrompt = alertPromptHolder.get();
+ }
+
+ int count = 0;
+ while((err == errSecPassphraseRequired || err == errSecInvalidData || err == errSecPkcs12VerifyFailure) &&
+ count < retryMax)
+ {
+ if(prompt)
+ {
+ passphraseHolder.reset(toCFString(prompt->getPassword()));
+ params.passphrase = passphraseHolder.get();
+ }
+ err = SecItemImport(data.get(), path.get(), &format, &importType, 0, &params, keychain, &items.get());
+ ++count;
+ }
+ }
+
+ if(err != noErr)
+ {
+ ostringstream os;
+ os << "IceSSL: error reading " << (type == kSecItemTypePrivateKey ? "private key" : "certificate");
+ os << " `" << file << "':\n" << sslErrorToString(err);
+ throw CertificateReadException(__FILE__, __LINE__, os.str());
+ }
+
+ if(type != kSecItemTypeUnknown && importType != kSecItemTypeAggregate && importType != type)
+ {
+ ostringstream os;
+ os << "IceSSL: error reading " << (type == kSecItemTypePrivateKey ? "private key" : "certificate");
+ os << " `" << file << "' doesn't contain the expected item";
+ throw CertificateReadException(__FILE__, __LINE__, os.str());
+ }
+
+ return items.release();
+}
+
+SecKeychainRef
+openKeychain(const std::string& path, const std::string& keychainPassword)
+{
+ string keychainPath = path;
+ UniqueRef<SecKeychainRef> keychain;
+ OSStatus err = 0;
+ if(keychainPath.empty())
+ {
+ if((err = SecKeychainCopyDefault(&keychain.get())))
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: unable to retrieve default keychain:\n" + sslErrorToString(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.get())))
+ {
+ throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: unable to open keychain: `" +
+ keychainPath + "'\n" + sslErrorToString(err));
+ }
+ }
+
+ SecKeychainStatus status;
+ err = SecKeychainGetStatus(keychain.get(), &status);
+ if(err == noErr)
+ {
+ const char* pass = keychainPassword.empty() ? 0 : keychainPassword.c_str();
+ if((err = SecKeychainUnlock(keychain.get(), keychainPassword.size(), pass, pass != 0)))
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: unable to unlock keychain:\n" + sslErrorToString(err));
+ }
+ }
+ else if(err == errSecNoSuchKeychain)
+ {
+ const char* pass = keychainPassword.empty() ? 0 : keychainPassword.c_str();
+ keychain.reset(0);
+ if((err = SecKeychainCreate(keychainPath.c_str(), keychainPassword.size(), pass, pass == 0, 0, &keychain.get())))
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: unable to create keychain:\n" + sslErrorToString(err));
+ }
+ }
+ else
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: unable to open keychain:\n" + sslErrorToString(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.get(), &settings)))
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: error setting keychain settings:\n" + sslErrorToString(err));
+ }
+
+ return keychain.release();
+}
+
+//
+// Imports a certificate private key and optionally add it to a keychain.
+//
+SecIdentityRef
+loadPrivateKey(const string& file, SecCertificateRef cert, SecKeychainRef keychain, const string& password,
+ const PasswordPromptPtr& prompt, int retryMax)
+{
+ //
+ // Check if we already imported the certificate
+ //
+ UniqueRef<CFDataRef> hash;
+ UniqueRef<CFDictionaryRef> subjectKeyProperty(getCertificateProperty(cert, kSecOIDSubjectKeyIdentifier));
+ if(subjectKeyProperty)
+ {
+ CFArrayRef values = static_cast<CFArrayRef>(CFDictionaryGetValue(subjectKeyProperty.get(),
+ kSecPropertyKeyValue));
+ for(int i = 0; i < CFArrayGetCount(values); ++i)
+ {
+ CFDictionaryRef dict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(values, i));
+ if(CFEqual(CFDictionaryGetValue(dict, kSecPropertyKeyLabel), CFSTR("Key Identifier")))
+ {
+ hash.retain(static_cast<CFDataRef>(CFDictionaryGetValue(dict, kSecPropertyKeyValue)));
+ break;
+ }
+ }
+ }
+
+ const void* values[] = { keychain };
+ UniqueRef<CFArrayRef> searchList(CFArrayCreate(kCFAllocatorDefault, values, 1, &kCFTypeArrayCallBacks));
+
+ UniqueRef<CFMutableDictionaryRef> query(CFDictionaryCreateMutable(0,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ CFDictionarySetValue(query.get(), kSecClass, kSecClassCertificate);
+ CFDictionarySetValue(query.get(), kSecMatchLimit, kSecMatchLimitOne);
+ CFDictionarySetValue(query.get(), kSecMatchSearchList, searchList.get());
+ CFDictionarySetValue(query.get(), kSecAttrSubjectKeyID, hash.get());
+ CFDictionarySetValue(query.get(), kSecReturnRef, kCFBooleanTrue);
+
+ UniqueRef<CFTypeRef> value(0);
+ OSStatus err = SecItemCopyMatching(query.get(), &value.get());
+ UniqueRef<SecCertificateRef> item(static_cast<SecCertificateRef>(const_cast<void*>(value.release())));
+ if(err == noErr)
+ {
+ //
+ // If the certificate has already been imported, create the
+ // identity. The key should also have been imported.
+ //
+ UniqueRef<SecIdentityRef> identity;
+ err = SecIdentityCreateWithCertificate(keychain, item.get(), &identity.get());
+ if(err != noErr)
+ {
+ ostringstream os;
+ os << "IceSSL: error creating certificate identity:\n" << sslErrorToString(err);
+ throw CertificateReadException(__FILE__, __LINE__, os.str());
+ }
+ return identity.release();
+ }
+ else if(err != errSecItemNotFound)
+ {
+ ostringstream os;
+ os << "IceSSL: error searching for keychain items:\n" << sslErrorToString(err);
+ throw CertificateReadException(__FILE__, __LINE__, os.str());
+ }
+
+ //
+ // If the certificate isn't already in the keychain, load the
+ // private key into the keychain and add the certificate.
+ //
+ UniqueRef<CFArrayRef> items(loadKeychainItems(file, kSecItemTypePrivateKey, keychain, password, prompt, retryMax));
+ int count = CFArrayGetCount(items.get());
+ UniqueRef<SecKeyRef> key;
+ for(int i = 0; i < count; ++i)
+ {
+ SecKeychainItemRef item =
+ static_cast<SecKeychainItemRef>(const_cast<void*>(CFArrayGetValueAtIndex(items.get(), 0)));
+ if(SecKeyGetTypeID() == CFGetTypeID(item))
+ {
+ key.retain(reinterpret_cast<SecKeyRef>(item));
+ break;
+ }
+ }
+ if(!key)
+ {
+ throw CertificateReadException(__FILE__, __LINE__, "IceSSL: no key in file `" + file + "'");
+ }
+
+ //
+ // Add the certificate to the keychain
+ //
+ query.reset(CFDictionaryCreateMutable(kCFAllocatorDefault,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ CFDictionarySetValue(query.get(), kSecUseKeychain, keychain);
+ CFDictionarySetValue(query.get(), kSecClass, kSecClassCertificate);
+ CFDictionarySetValue(query.get(), kSecValueRef, cert);
+ CFDictionarySetValue(query.get(), kSecReturnRef, kCFBooleanTrue);
+
+ value.reset(0);
+ err = SecItemAdd(query.get(), static_cast<CFTypeRef*>(&value.get()));
+ UniqueRef<CFArrayRef> added(static_cast<CFArrayRef>(value.release()));
+ if(err != noErr)
+ {
+ ostringstream os;
+ os << "IceSSL: failure adding certificate to keychain\n" << sslErrorToString(err);
+ throw CertificateReadException(__FILE__, __LINE__, os.str());
+ }
+ item.retain(static_cast<SecCertificateRef>(const_cast<void*>(CFArrayGetValueAtIndex(added.get(), 0))));
+
+ //
+ // Create the association between the private key and the certificate,
+ // kSecKeyLabel attribute should match the subject key identifier.
+ //
+ vector<SecKeychainAttribute> attributes;
+ if(hash)
+ {
+ SecKeychainAttribute attr;
+ attr.tag = kSecKeyLabel;
+ attr.data = const_cast<UInt8*>(CFDataGetBytePtr(hash.get()));
+ attr.length = CFDataGetLength(hash.get());
+ attributes.push_back(attr);
+ }
+
+ //
+ // kSecKeyPrintName attribute correspond to the keychain display
+ // name.
+ //
+ string label;
+ UniqueRef<CFStringRef> commonName(0);
+ if(SecCertificateCopyCommonName(item.get(), &commonName.get()) == noErr)
+ {
+ label = fromCFString(commonName.get());
+ SecKeychainAttribute attr;
+ attr.tag = kSecKeyPrintName;
+ attr.data = const_cast<char*>(label.c_str());
+ attr.length = label.size();
+ attributes.push_back(attr);
+ }
+
+ SecKeychainAttributeList attrs;
+ attrs.attr = &attributes[0];
+ attrs.count = attributes.size();
+ SecKeychainItemModifyAttributesAndData(reinterpret_cast<SecKeychainItemRef>(key.get()), &attrs, 0, 0);
+
+ UniqueRef<SecIdentityRef> identity;
+ err = SecIdentityCreateWithCertificate(keychain, item.get(), &identity.get());
+ if(err != noErr)
+ {
+ ostringstream os;
+ os << "IceSSL: error creating certificate identity:\n" << sslErrorToString(err);
+ throw CertificateReadException(__FILE__, __LINE__, os.str());
+ }
+ return identity.release();
+}
+
+} // anonymous namespace end
+
+#else
+
+namespace
+{
+
+CFArrayRef
+loadCerts(const string& file)
+{
+ UniqueRef<CFArrayRef> 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()));
+ UniqueRef<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(const_cast<CFMutableArrayRef>(certs.get()), cert.get());
+ first = false;
+ }
+ }
+ else
+ {
+ UniqueRef<CFDataRef> data(readCertFile(file));
+ UniqueRef<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(const_cast<CFMutableArrayRef>(certs.get()), cert.get());
+ }
+ return certs.release();
+}
+
+}
+
+#endif
+
+//
+// Imports a certificate (it might contain an identity or certificate depending on the format).
+//
+CFArrayRef
+IceSSL::SecureTransport::loadCertificateChain(const string& file,
+ const string& keyFile,
+ const std::string& keychainPath,
+ const string& keychainPassword,
+ const string& password,
+ const PasswordPromptPtr& prompt,
+ int retryMax)
+{
+ UniqueRef<CFArrayRef> chain;
+#if defined(ICE_USE_SECURE_TRANSPORT_IOS)
+ UniqueRef<CFDataRef> cert(readCertFile(file));
+
+ UniqueRef<CFMutableDictionaryRef> settings(CFDictionaryCreateMutable(0,
+ 1,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+ UniqueRef<CFArrayRef> items;
+ OSStatus err;
+ int count = 0;
+ do
+ {
+ UniqueRef<CFStringRef> pass(toCFString(password.empty() && prompt ? prompt->getPassword() : password));
+ CFDictionarySetValue(settings.get(), kSecImportExportPassphrase, pass.get());
+ err = SecPKCS12Import(cert.get(), settings.get(), &items.get());
+ ++count;
+ }
+ while(password.empty() && prompt && err == errSecAuthFailed && count < retryMax);
+
+ if(err != noErr)
+ {
+ ostringstream os;
+ os << "IceSSL: unable to import certificate from file " << file << " (error = " << err << ")";
+ throw InitializationException(__FILE__, __LINE__, os.str());
+ }
+
+ for(int i = 0; i < CFArrayGetCount(items.get()); ++i)
+ {
+ CFDictionaryRef dict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(items.get(), i));
+ SecIdentityRef identity = static_cast<SecIdentityRef>(
+ const_cast<void*>(CFDictionaryGetValue(dict, kSecImportItemIdentity)));
+ if(identity)
+ {
+ CFArrayRef certs = static_cast<CFArrayRef>(CFDictionaryGetValue(dict, kSecImportItemCertChain));
+ chain.reset(CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, certs));
+ CFArraySetValueAtIndex(const_cast<CFMutableArrayRef>(chain.get()), 0, identity);
+ }
+ }
+
+ if(!chain)
+ {
+ 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())
+ {
+ chain.reset(loadKeychainItems(file, kSecItemTypeUnknown, keychain.get(), password, prompt, retryMax));
+ }
+ else
+ {
+ //
+ // Load the certificate, don't load into the keychain as it
+ // might already have been imported.
+ //
+ UniqueRef<CFArrayRef> items(loadKeychainItems(file, kSecItemTypeCertificate, 0, password, prompt, retryMax));
+ SecCertificateRef cert =
+ static_cast<SecCertificateRef>(const_cast<void*>(CFArrayGetValueAtIndex(items.get(), 0)));
+ if(SecCertificateGetTypeID() != CFGetTypeID(cert))
+ {
+ ostringstream os;
+ os << "IceSSL: couldn't find certificate in `" << file << "'";
+ throw CertificateReadException(__FILE__, __LINE__, os.str());
+ }
+
+ //
+ // Load the private key for the given certificate. This will
+ // add the certificate/key to the keychain if they aren't
+ // already present in the keychain.
+ //
+ UniqueRef<SecIdentityRef> identity(loadPrivateKey(keyFile, cert, keychain.get(), password, prompt, retryMax));
+ chain.reset(CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, items.get()));
+ CFArraySetValueAtIndex(const_cast<CFMutableArrayRef>(chain.get()), 0, identity.get());
+ }
+#endif
+ return chain.release();
+}
+
+SecCertificateRef
+IceSSL::SecureTransport::loadCertificate(const string& file)
+{
+ UniqueRef<SecCertificateRef> cert;
+#if defined(ICE_USE_SECURE_TRANSPORT_IOS)
+ UniqueRef<CFArrayRef> certs(loadCerts(file));
+ assert(CFArrayGetCount(certs.get()) > 0);
+ cert.retain((SecCertificateRef)CFArrayGetValueAtIndex(certs.get(), 0));
+#else
+ UniqueRef<CFArrayRef> items(loadKeychainItems(file, kSecItemTypeCertificate, 0, "", 0, 0));
+ cert.retain((SecCertificateRef)CFArrayGetValueAtIndex(items.get(), 0));
+#endif
+ return cert.release();
+}
+
+CFArrayRef
+IceSSL::SecureTransport::loadCACertificates(const string& file)
+{
+#if defined(ICE_USE_SECURE_TRANSPORT_IOS)
+ return loadCerts(file);
+#else
+ UniqueRef<CFArrayRef> items(loadKeychainItems(file, kSecItemTypeCertificate, 0, "", 0, 0));
+ UniqueRef<CFArrayRef> certificateAuthorities(CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
+ int count = CFArrayGetCount(items.get());
+ for(CFIndex i = 0; i < count; ++i)
+ {
+ SecCertificateRef cert =
+ static_cast<SecCertificateRef>(const_cast<void*>(CFArrayGetValueAtIndex(items.get(), i)));
+ assert(SecCertificateGetTypeID() == CFGetTypeID(cert));
+ if(isCA(cert))
+ {
+ CFArrayAppendValue(const_cast<CFMutableArrayRef>(certificateAuthorities.get()), cert);
+ }
+ }
+ return certificateAuthorities.release();
+#endif
+}
+
+CFArrayRef
+IceSSL::SecureTransport::findCertificateChain(const std::string& keychainPath,
+ const std::string& keychainPassword,
+ const string& value)
+{
+ //
+ // Search the keychain using key:value pairs. The following keys are supported:
+ //
+ // Label
+ // Serial
+ // Subject
+ // SubjectKeyId
+ //
+ // A value must be enclosed in single or double quotes if it contains whitespace.
+ //
+ UniqueRef<CFMutableDictionaryRef> query(CFDictionaryCreateMutable(0,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+#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(), 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)));
+ string arg;
+ if(field != "LABEL" && field != "SERIAL" && field != "SUBJECT" && field != "SUBJECTKEYID")
+ {
+ 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 + "'");
+ }
+
+ 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 == "SUBJECT" || field == "LABEL")
+ {
+ UniqueRef<CFStringRef> v(toCFString(arg));
+ CFDictionarySetValue(query.get(), field == "LABEL" ? kSecAttrLabel : kSecMatchSubjectContains, v.get());
+ valid = true;
+ }
+ else if(field == "SUBJECTKEYID" || field == "SERIAL")
+ {
+ vector<unsigned char> buffer;
+ if(!parseBytes(arg, buffer))
+ {
+ throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: invalid value `" + value + "'");
+ }
+ UniqueRef<CFDataRef> v(CFDataCreate(kCFAllocatorDefault, &buffer[0], buffer.size()));
+ CFDictionarySetValue(query.get(), field == "SUBJECTKEYID" ? kSecAttrSubjectKeyID : kSecAttrSerialNumber,
+ v.get());
+ valid = true;
+ }
+ }
+
+ if(!valid)
+ {
+ throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: invalid value `" + value + "'");
+ }
+
+ UniqueRef<SecCertificateRef> cert;
+ OSStatus err = SecItemCopyMatching(query.get(), (CFTypeRef*)&cert.get());
+ if(err != noErr)
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: find certificate `" + value + "' failed:\n" + sslErrorToString(err));
+ }
+
+ //
+ // Retrieve the certificate chain
+ //
+ UniqueRef<SecPolicyRef> policy(SecPolicyCreateSSL(true, 0));
+ UniqueRef<SecTrustRef> trust;
+ err = SecTrustCreateWithCertificates(reinterpret_cast<CFArrayRef>(cert.get()), policy.get(), &trust.get());
+ if(err || !trust)
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: error creating trust object" +
+ (err ? ":\n" + sslErrorToString(err) : ""));
+ }
+
+ SecTrustResultType trustResult;
+ if((err = SecTrustEvaluate(trust.get(), &trustResult)))
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: error evaluating trust:\n" + sslErrorToString(err));
+ }
+
+ int chainLength = SecTrustGetCertificateCount(trust.get());
+ UniqueRef<CFArrayRef> items(CFArrayCreateMutable(kCFAllocatorDefault, chainLength, &kCFTypeArrayCallBacks));
+ for(int i = 0; i < chainLength; ++i)
+ {
+ CFArrayAppendValue(const_cast<CFMutableArrayRef>(items.get()), SecTrustGetCertificateAtIndex(trust.get(), i));
+ }
+
+ //
+ // Replace the first certificate in the chain with the
+ // identity.
+ //
+ UniqueRef<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.get());
+ CFDictionarySetValue(query.get(), kSecReturnAttributes, kCFBooleanTrue);
+ UniqueRef<CFDictionaryRef> attributes;
+ err = SecItemCopyMatching(query.get(), reinterpret_cast<CFTypeRef*>(&attributes.get()));
+ if(err != noErr)
+ {
+ ostringstream os;
+ os << "IceSSL: couldn't create identity for certificate found in the keychain:\n" << sslErrorToString(err);
+ throw PluginInitializationException(__FILE__, __LINE__, os.str());
+ }
+
+ // 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.get(), kSecAttrLabel));
+ CFDictionarySetValue(query.get(), kSecReturnRef, kCFBooleanTrue);
+ err = SecItemCopyMatching(query.get(), (CFTypeRef*)&identity.get());
+ if(err == noErr)
+ {
+ UniqueRef<SecCertificateRef> cert2;
+ if((err = SecIdentityCopyCertificate(identity.get(), &cert2.get())) == noErr)
+ {
+ err = CFEqual(cert2.get(), cert.get()) ? noErr : errSecItemNotFound;
+ }
+ }
+#else
+ err = SecIdentityCreateWithCertificate(keychain.get(), cert.get(), &identity.get());
+#endif
+ if(err != noErr)
+ {
+ ostringstream os;
+ os << "IceSSL: couldn't create identity for certificate found in the keychain:\n" << sslErrorToString(err);
+ throw PluginInitializationException(__FILE__, __LINE__, os.str());
+ }
+ CFArraySetValueAtIndex(const_cast<CFMutableArrayRef>(items.get()), 0, identity.get());
+ return items.release();
+}
diff --git a/cpp/src/IceSSL/SecureTransportUtil.h b/cpp/src/IceSSL/SecureTransportUtil.h
new file mode 100644
index 00000000000..e508a41776d
--- /dev/null
+++ b/cpp/src/IceSSL/SecureTransportUtil.h
@@ -0,0 +1,47 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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 ICESSL_SECURE_TRANSPORT_UTIL_H
+#define ICESSL_SECURE_TRANSPORT_UTIL_H
+
+#include <IceSSL/SecureTransport.h>
+#include <IceSSL/Util.h>
+
+namespace IceSSL
+{
+
+namespace SecureTransport
+{
+
+std::string sslErrorToString(CFErrorRef);
+std::string sslErrorToString(OSStatus);
+
+# if defined(ICE_USE_SECURE_TRANSPORT_MACOS)
+//
+// Retrieve a certificate property
+//
+CFDictionaryRef getCertificateProperty(SecCertificateRef, CFTypeRef);
+# endif
+
+//
+// Read certificate from a file.
+//
+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&);
+CFArrayRef findCertificateChain(const std::string&, const std::string&, const std::string&);
+
+
+} // SecureTransport namespace end
+
+} // IceSSL namespace end
+
+#endif
diff --git a/cpp/src/IceSSL/UWPCertificateI.cpp b/cpp/src/IceSSL/UWPCertificateI.cpp
new file mode 100644
index 00000000000..e0d26fe159b
--- /dev/null
+++ b/cpp/src/IceSSL/UWPCertificateI.cpp
@@ -0,0 +1,271 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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.
+//
+// **********************************************************************
+
+//
+// UWP Certificate implementation
+//
+
+#include <IceSSL/UWP.h>
+#include <IceSSL/CertificateI.h>
+#include <IceSSL/Util.h>
+
+#include <Ice/LocalException.h>
+#include <Ice/StringConverter.h>
+#include <Ice/Base64.h>
+#include <Ice/StringUtil.h>
+
+#include <ppltasks.h>
+#include <nserror.h>
+
+using namespace concurrency;
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Storage;
+using namespace Windows::Storage::Streams;
+using namespace Windows::Security::Cryptography;
+
+using namespace Ice;
+using namespace IceSSL;
+
+using namespace std;
+
+namespace
+{
+
+class UWPCertificateI : public UWP::Certificate,
+ public CertificateI
+{
+public:
+
+ UWPCertificateI(Windows::Security::Cryptography::Certificates::Certificate^);
+
+ virtual bool operator==(const IceSSL::Certificate&) const;
+
+ virtual vector<Ice::Byte> getAuthorityKeyIdentifier() const;
+ virtual vector<Ice::Byte> getSubjectKeyIdentifier() const;
+ virtual bool verify(const CertificatePtr&) const;
+ virtual string encode() const;
+
+ virtual chrono::system_clock::time_point getNotAfter() const;
+ virtual chrono::system_clock::time_point getNotBefore() const;
+ virtual string getSerialNumber() const;
+ virtual DistinguishedName getIssuerDN() const;
+ virtual vector<pair<int, string> > getIssuerAlternativeNames() const;
+ virtual DistinguishedName getSubjectDN() const;
+ virtual vector<pair<int, string> > getSubjectAlternativeNames() const;
+ virtual int getVersion() const;
+ virtual Windows::Security::Cryptography::Certificates::Certificate^ getCert() const;
+
+private:
+
+ Windows::Security::Cryptography::Certificates::Certificate^ _cert;
+};
+
+const Ice::Long TICKS_PER_MSECOND = 10000LL;
+const Ice::Long MSECS_TO_EPOCH = 11644473600000LL;
+
+vector<pair<int, string> >
+certificateAltNames(Windows::Security::Cryptography::Certificates::SubjectAlternativeNameInfo^ subAltNames)
+{
+ vector<pair<int, string> > altNames;
+ if(subAltNames)
+ {
+ 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())
+ {
+ altNames.push_back(make_pair(AltNameDNS, wstringToString(iter->Current->Data())));
+ }
+ 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())
+ {
+ altNames.push_back(make_pair(AltNAmeIP, wstringToString(iter->Current->Data())));
+ }
+ }
+ return altNames;
+}
+
+} // end anonymous namespace
+
+UWPCertificateI::UWPCertificateI(Windows::Security::Cryptography::Certificates::Certificate^ cert) : _cert(cert)
+{
+ if(!_cert)
+ {
+ throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Invalid certificate reference");
+ }
+}
+
+bool
+UWPCertificateI::operator==(const IceSSL::Certificate& r) const
+{
+ const UWPCertificateI* p = dynamic_cast<const UWPCertificateI*>(&r);
+ if(!p)
+ {
+ return false;
+ }
+
+ return CryptographicBuffer::Compare(_cert->GetCertificateBlob(), p->_cert->GetCertificateBlob());
+}
+
+vector<Ice::Byte>
+UWPCertificateI::getAuthorityKeyIdentifier() const
+{
+ throw FeatureNotSupportedException(__FILE__, __LINE__);
+}
+
+vector<Ice::Byte>
+UWPCertificateI::getSubjectKeyIdentifier() const
+{
+ throw FeatureNotSupportedException(__FILE__, __LINE__);
+}
+
+bool
+UWPCertificateI::verify(const CertificatePtr&) const
+{
+ throw FeatureNotSupportedException(__FILE__, __LINE__);
+}
+
+string
+UWPCertificateI::encode() const
+{
+ 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], static_cast<unsigned int>(data.size())));
+ }
+ ostringstream os;
+ os << "-----BEGIN CERTIFICATE-----\n";
+ os << IceInternal::Base64::encode(data);
+ os << "-----END CERTIFICATE-----\n";
+ return os.str();
+}
+
+chrono::system_clock::time_point
+UWPCertificateI::getNotAfter() const
+{
+ // Convert 100ns time from January 1, 1601 to ms from January 1, 1970
+ return chrono::system_clock::time_point(
+ chrono::milliseconds(_cert->ValidTo.UniversalTime / TICKS_PER_MSECOND - MSECS_TO_EPOCH));
+}
+
+chrono::system_clock::time_point
+UWPCertificateI::getNotBefore() const
+{
+ // Convert 100ns time from January 1, 1601 to ms from January 1, 1970
+ return chrono::system_clock::time_point(
+ chrono::milliseconds(_cert->ValidFrom.UniversalTime / TICKS_PER_MSECOND - MSECS_TO_EPOCH));
+}
+
+string
+UWPCertificateI::getSerialNumber() const
+{
+ 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());
+}
+
+DistinguishedName
+UWPCertificateI::getIssuerDN() const
+{
+ return DistinguishedName("CN=" + wstringToString(_cert->Issuer->Data()));
+}
+
+vector<pair<int, string> >
+UWPCertificateI::getIssuerAlternativeNames() const
+{
+ throw FeatureNotSupportedException(__FILE__, __LINE__);
+}
+
+DistinguishedName
+UWPCertificateI::getSubjectDN() const
+{
+ return DistinguishedName("CN=" + wstringToString(_cert->Subject->Data()));
+}
+
+vector<pair<int, string> >
+UWPCertificateI::getSubjectAlternativeNames() const
+{
+ return certificateAltNames(_cert->SubjectAlternativeName);
+}
+
+int
+UWPCertificateI::getVersion() const
+{
+ throw FeatureNotSupportedException(__FILE__, __LINE__);
+}
+
+Windows::Security::Cryptography::Certificates::Certificate^
+UWPCertificateI::getCert() const
+{
+ return _cert;
+}
+
+UWP::CertificatePtr
+UWP::Certificate::create(Windows::Security::Cryptography::Certificates::Certificate^ cert)
+{
+ return ICE_MAKE_SHARED(UWPCertificateI, cert);
+}
+
+UWP::CertificatePtr
+UWP::Certificate::load(const std::string& file)
+{
+ try
+ {
+ auto uri = ref new Uri(ref new String(stringToWstring(file).c_str()));
+ auto file = create_task(StorageFile::GetFileFromApplicationUriAsync(uri)).get();
+ auto buffer = create_task(FileIO::ReadTextAsync(file)).get();
+ return UWP::Certificate::decode(wstringToString(buffer->Data()));
+ }
+ catch(Platform::Exception^ ex)
+ {
+ if(HRESULT_CODE(ex->HResult) == ERROR_FILE_NOT_FOUND)
+ {
+ throw CertificateReadException(__FILE__, __LINE__, "error opening file :" + file);
+ }
+ else
+ {
+ throw Ice::SyscallException(__FILE__, __LINE__, ex->HResult);
+ }
+ }
+}
+
+UWP::CertificatePtr
+UWP::Certificate::decode(const std::string& encoding)
+{
+ 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], static_cast<unsigned int>(data.size())));
+ return make_shared<UWPCertificateI>(ref new Certificates::Certificate(writer->DetachBuffer()));
+}
diff --git a/cpp/src/IceSSL/UWPEngine.cpp b/cpp/src/IceSSL/UWPEngine.cpp
index aadade9bf93..97fcbda9b1f 100644
--- a/cpp/src/IceSSL/UWPEngine.cpp
+++ b/cpp/src/IceSSL/UWPEngine.cpp
@@ -9,47 +9,283 @@
#include <IceSSL/Config.h>
-#ifdef ICE_OS_UWP
+#include <IceSSL/UWPEngineF.h>
+#include <IceSSL/UWPEngine.h>
+#include <IceSSL/UWPTransceiverI.h>
+#include <IceSSL/Util.h>
-#include <IceSSL/SSLEngine.h>
#include <Ice/Communicator.h>
+#include <Ice/StringConverter.h>
+#include <Ice/StringUtil.h>
#include <Ice/Properties.h>
+#include <Ice/Network.h>
#include <IceUtil/Shared.h>
#include <string>
-IceUtil::Shared* IceSSL::upCast(IceSSL::UWPEngine* p) { return p; }
-
using namespace std;
+using namespace Ice;
+using namespace IceUtil;
using namespace IceSSL;
-UWPEngine::UWPEngine(const Ice::CommunicatorPtr& communicator) : SSLEngine(communicator)
+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;
+
+IceUtil::Shared* UWP::upCast(UWP::SSLEngine* p) { return p; }
+
+namespace
+{
+
+//
+// Find a certificate in the Application Personal certificate store
+// with the given friendly name. Returns the matching certificate or
+// nullptr if none is found.
+//
+Certificates::Certificate^
+findPersonalCertificate(String^ friendlyName)
+{
+ CertificateQuery^ query = ref new CertificateQuery();
+ query->IncludeDuplicates = true;
+ query->IncludeExpiredCertificates = true;
+ query->FriendlyName = friendlyName;
+ query->StoreName = StandardCertificateStoreNames::Personal;
+
+ try
+ {
+ auto certificates = IceInternal::runSync(CertificateStores::FindAllAsync(query));
+ return certificates->Size > 0 ? certificates->GetAt(0) : nullptr;
+ }
+ catch(Platform::Exception^ ex)
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: certificate error:\n" + wstringToString(ex->Message->Data()));
+ }
+}
+
+//
+// Import a certificate in the Application Personal certificate store
+// with the given friendly name. Returns true if there was a password
+// error and false otherwise. If the import fails because a different
+// error PluginInitializationException exception is throw.
+//
+bool
+importPfxData(String^ friendlyName, String^ data, String^ password)
+{
+ try
+ {
+ IceInternal::runSync(CertificateEnrollmentManager::ImportPfxDataAsync(
+ data,
+ password,
+ ExportOption::NotExportable,
+ KeyProtectionLevel::NoConsent,
+ InstallOptions::None,
+ friendlyName));
+ return false; // The import succcess
+ }
+ catch(Platform::Exception^ ex)
+ {
+ if(HRESULT_CODE(ex->HResult) == ERROR_DECRYPTION_FAILED)
+ {
+ return true; // Password error
+ }
+ else
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: certificate error:\n" + wstringToString(ex->Message->Data()));
+ }
+ }
+}
+
+Certificates::Certificate^
+importPersonalCertificate(const string& file, function<string ()> password, bool passwordPrompt,
+ int passwordRetryMax)
+{
+ auto uri = ref new Uri(ref new String(stringToWstring(file).c_str()));
+ try
+ {
+ auto file = IceInternal::runSync(StorageFile::GetFileFromApplicationUriAsync(uri));
+ auto buffer = IceInternal::runSync(FileIO::ReadBufferAsync(file));
+
+ //
+ // Create a hash of the certificate to use as a friendly name, this will allow us
+ // to uniquely identify the certificate in the store.
+ //
+ auto hasher = HashAlgorithmProvider::OpenAlgorithm(HashAlgorithmNames::Sha1);
+ auto hash = hasher->CreateHash();
+
+ hash->Append(buffer);
+ String^ friendlyName = CryptographicBuffer::EncodeToBase64String(hash->GetValueAndReset());
+
+ //
+ // If the certificate is already in the store we avoid importing it.
+ //
+ Certificates::Certificate^ cert = findPersonalCertificate(friendlyName);
+ if(cert)
+ {
+ return cert;
+ }
+ else
+ {
+ String^ data = CryptographicBuffer::EncodeToBase64String(buffer);
+ int count = 0;
+ bool passwordErr = false;
+ do
+ {
+ passwordErr = importPfxData(friendlyName, data,
+ ref new String(stringToWstring(password()).c_str()));
+ }
+ while(passwordPrompt && passwordErr && ++count < passwordRetryMax);
+ if(passwordErr)
+ {
+ throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: error decoding certificate");
+ }
+ return findPersonalCertificate(friendlyName);
+ }
+ }
+ catch(Platform::Exception^ ex)
+ {
+ if(HRESULT_CODE(ex->HResult) == ERROR_FILE_NOT_FOUND)
+ {
+ throw PluginInitializationException(__FILE__, __LINE__, "certificate file not found:\n" + file);
+ }
+ else
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: certificate error:\n" + wstringToString(ex->Message->Data()));
+ }
+ }
+}
+
+IVectorView<Certificates::Certificate^>^
+findCertificates(const string& name, const string& value)
+{
+ CertificateQuery^ query = ref new CertificateQuery();
+ query->StoreName = ref new String(stringToWstring(name).c_str());
+ query->IncludeDuplicates = true;
+ query->IncludeExpiredCertificates = 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()));
+ }
+ }
+ }
+
+ try
+ {
+ return IceInternal::runSync(CertificateStores::FindAllAsync(query));
+ }
+ catch(Platform::Exception^ ex)
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: certificate error:\n" + wstringToString(ex->Message->Data()));
+ }
+}
+
+} // anonymous namespace end
+
+UWP::SSLEngine::SSLEngine(const Ice::CommunicatorPtr& communicator) : IceSSL::SSLEngine(communicator)
{
}
void
-UWPEngine::initialize()
+UWP::SSLEngine::initialize()
{
- lock_guard<mutex> lock(_mutex);
+ Mutex::Lock lock(_mutex);
if(_initialized)
{
return;
}
- SSLEngine::initialize();
+ IceSSL::SSLEngine::initialize();
const auto properties = communicator()->getProperties();
//
- // Load CAs
- //
- //string ca = properties->getProperty("IceSSL.CAs");
- //if(!ca.empty())
- //{
- // _ca = Certificate::load(ca);
- //}
-
- //
// Load client certificate
//
const int passwordRetryMax = properties->getPropertyAsIntWithDefault("IceSSL.PasswordRetryMax", 3);
@@ -59,14 +295,14 @@ UWPEngine::initialize()
string findCert = properties->getProperty("IceSSL.FindCert");
if(!certFile.empty())
{
- _certificate = make_shared<IceSSL::Certificate>(importPersonalCertificate(
+ _certificate = dynamic_pointer_cast<UWP::Certificate>(UWP::Certificate::create(importPersonalCertificate(
certFile,
[this]()
{
return password(false);
},
getPasswordPrompt() != nullptr,
- passwordRetryMax));
+ passwordRetryMax)));
}
else if(!findCert.empty())
{
@@ -75,33 +311,33 @@ UWPEngine::initialize()
{
throw Ice::PluginInitializationException(__FILE__, __LINE__, "IceSSL: no certificates found");
}
- _certificate = make_shared<IceSSL::Certificate>(certs->GetAt(0));
+ _certificate = dynamic_pointer_cast<UWP::Certificate>(UWP::Certificate::create(certs->GetAt(0)));
}
_initialized = true;
}
bool
-UWPEngine::initialized() const
+UWP::SSLEngine::initialized() const
{
return _initialized;
}
-//shared_ptr<Certificate>
-//UWPEngine::ca()
-//{
-// return _ca;
-//}
-
-shared_ptr<Certificate>
-UWPEngine::certificate()
+shared_ptr<UWP::Certificate>
+UWP::SSLEngine::certificate()
{
return _certificate;
}
void
-UWPEngine::destroy()
+UWP::SSLEngine::destroy()
{
}
-#endif
-
+IceInternal::TransceiverPtr
+UWP::SSLEngine::createTransceiver(const InstancePtr& instance,
+ const IceInternal::TransceiverPtr& delegate,
+ const string& hostOrAdapterName,
+ bool incoming)
+{
+ return new UWP::TransceiverI(instance, delegate, hostOrAdapterName, incoming);
+}
diff --git a/cpp/src/IceSSL/UWPEngine.h b/cpp/src/IceSSL/UWPEngine.h
new file mode 100644
index 00000000000..e5df7c8c3ef
--- /dev/null
+++ b/cpp/src/IceSSL/UWPEngine.h
@@ -0,0 +1,46 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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 ICESSL_UWP_ENGINE_H
+#define ICESSL_UWP_ENGINE_H
+
+#include <IceSSL/SSLEngine.h>
+#include <IceSSL/UWP.h>
+
+#include <mutex>
+
+namespace IceSSL
+{
+
+namespace UWP
+{
+
+class SSLEngine : public IceSSL::SSLEngine
+{
+public:
+
+ SSLEngine(const Ice::CommunicatorPtr&);
+
+ virtual void initialize();
+ virtual bool initialized() const;
+ virtual void destroy();
+ virtual IceInternal::TransceiverPtr
+ createTransceiver(const InstancePtr&, const IceInternal::TransceiverPtr&, const std::string&, bool);
+ virtual std::shared_ptr<IceSSL::UWP::Certificate> certificate();
+
+private:
+
+ std::shared_ptr<IceSSL::UWP::Certificate> _certificate;
+};
+
+} // UWP namespace end
+
+} // IceSSL namespace end
+
+#endif
diff --git a/cpp/src/IceSSL/UWPEngineF.h b/cpp/src/IceSSL/UWPEngineF.h
new file mode 100644
index 00000000000..666caa5f718
--- /dev/null
+++ b/cpp/src/IceSSL/UWPEngineF.h
@@ -0,0 +1,31 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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 ICESSL_UWP_ENGINE_F_H
+#define ICESSL_UWP_ENGINE_F_H
+
+#include <IceUtil/Shared.h>
+#include <Ice/Handle.h>
+#include <IceSSL/UWP.h>
+
+namespace IceSSL
+{
+
+namespace UWP
+{
+
+class SSLEngine;
+ICESSL_API IceUtil::Shared* upCast(SSLEngine*);
+typedef IceInternal::Handle<SSLEngine> SSLEnginePtr;
+
+}
+
+}
+
+#endif
diff --git a/cpp/src/IceSSL/UWPPluginI.cpp b/cpp/src/IceSSL/UWPPluginI.cpp
new file mode 100644
index 00000000000..3590c89ae4a
--- /dev/null
+++ b/cpp/src/IceSSL/UWPPluginI.cpp
@@ -0,0 +1,94 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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/PluginI.h>
+#include <IceSSL/UWPEngine.h>
+
+#include <Ice/Initialize.h>
+
+using namespace std;
+
+namespace
+{
+
+class PluginI : public IceSSL::PluginI
+{
+public:
+
+ PluginI(const Ice::CommunicatorPtr&);
+ //
+ // Construct a certificate using a native certificate.
+ //
+ virtual string getEngineName() const;
+ virtual Ice::Long getEngineVersion() const;
+ virtual IceSSL::CertificatePtr create(Windows::Security::Cryptography::Certificates::Certificate^) const;
+ virtual IceSSL::CertificatePtr load(const std::string&) const;
+ virtual IceSSL::CertificatePtr decode(const std::string&) const;
+};
+
+} // anonymous namespace end
+
+//
+// Plugin implementation.
+//
+PluginI::PluginI(const Ice::CommunicatorPtr& com) :
+ IceSSL::PluginI(com, new IceSSL::UWP::SSLEngine(com))
+{
+}
+
+IceSSL::CertificatePtr
+PluginI::create(Windows::Security::Cryptography::Certificates::Certificate^ cert) const
+{
+ return IceSSL::UWP::Certificate::create(cert);
+}
+
+IceSSL::CertificatePtr
+PluginI::load(const std::string& file) const
+{
+ return IceSSL::UWP::Certificate::load(file);
+}
+
+IceSSL::CertificatePtr
+PluginI::decode(const std::string& encoding) const
+{
+ return IceSSL::UWP::Certificate::decode(encoding);
+}
+
+string
+PluginI::getEngineName() const
+{
+ return "UWPEngine";
+}
+
+Ice::Long
+PluginI::getEngineVersion() const
+{
+ return 0;
+}
+
+//
+// Plug-in factory function.
+//
+extern "C" ICESSL_API Ice::Plugin*
+createIceSSL(const Ice::CommunicatorPtr& communicator, const string& /*name*/, const Ice::StringSeq& /*args*/)
+{
+ return new PluginI(communicator);
+}
+
+IceSSL::CertificatePtr
+IceSSL::Certificate::load(const std::string& file)
+{
+ return IceSSL::UWP::Certificate::load(file);
+}
+
+IceSSL::CertificatePtr
+IceSSL::Certificate::decode(const std::string& encoding)
+{
+ return IceSSL::UWP::Certificate::decode(encoding);
+} \ No newline at end of file
diff --git a/cpp/src/IceSSL/UWPTransceiverI.cpp b/cpp/src/IceSSL/UWPTransceiverI.cpp
index 27b8c76502d..b2b1b3f1992 100644
--- a/cpp/src/IceSSL/UWPTransceiverI.cpp
+++ b/cpp/src/IceSSL/UWPTransceiverI.cpp
@@ -8,12 +8,9 @@
// **********************************************************************
#include <IceSSL/Config.h>
-
-#ifdef ICE_OS_UWP
-
#include <IceSSL/UWPTransceiverI.h>
#include <IceSSL/Instance.h>
-#include <IceSSL/SSLEngine.h>
+#include <IceSSL/UWPEngine.h>
#include <Ice/Logger.h>
#include <ppltasks.h>
@@ -104,13 +101,13 @@ validationResultToString(ChainValidationResult result)
}
IceInternal::NativeInfoPtr
-IceSSL::TransceiverI::getNativeInfo()
+UWP::TransceiverI::getNativeInfo()
{
return _delegate->getNativeInfo();
}
IceInternal::SocketOperation
-IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::Buffer& writeBuffer)
+UWP::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::Buffer& writeBuffer)
{
if(!_connected)
{
@@ -199,7 +196,7 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
auto certs = _chain->GetCertificates(true);
for(auto iter = certs->First(); iter->HasCurrent; iter->MoveNext())
{
- auto cert = ICE_MAKE_SHARED(Certificate, iter->Current);
+ auto cert = UWP::Certificate::create(iter->Current);
_nativeCerts.push_back(cert);
_certs.push_back(cert->encode());
}
@@ -218,31 +215,31 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
}
IceInternal::SocketOperation
-IceSSL::TransceiverI::closing(bool initiator, const Ice::LocalException& ex)
+UWP::TransceiverI::closing(bool initiator, const Ice::LocalException& ex)
{
return _delegate->closing(initiator, ex);
}
void
-IceSSL::TransceiverI::close()
+UWP::TransceiverI::close()
{
_delegate->close();
}
IceInternal::SocketOperation
-IceSSL::TransceiverI::write(IceInternal::Buffer& buf)
+UWP::TransceiverI::write(IceInternal::Buffer& buf)
{
return _delegate->write(buf);
}
IceInternal::SocketOperation
-IceSSL::TransceiverI::read(IceInternal::Buffer& buf)
+UWP::TransceiverI::read(IceInternal::Buffer& buf)
{
return _delegate->read(buf);
}
bool
-IceSSL::TransceiverI::startWrite(IceInternal::Buffer& buf)
+UWP::TransceiverI::startWrite(IceInternal::Buffer& buf)
{
if(_connected && !_upgraded)
{
@@ -251,7 +248,7 @@ IceSSL::TransceiverI::startWrite(IceInternal::Buffer& buf)
//
// We ignore SSL Certificate errors at this point, the certificate chain will be validated
- // when the chain is constructed in IceSSL::Transceiver::initialize
+ // when the chain is constructed in Transceiver::initialize
//
stream->Control->IgnorableServerCertificateErrors->Append(ChainValidationResult::Expired);
stream->Control->IgnorableServerCertificateErrors->Append(ChainValidationResult::IncompleteChain);
@@ -287,7 +284,7 @@ IceSSL::TransceiverI::startWrite(IceInternal::Buffer& buf)
}
void
-IceSSL::TransceiverI::finishWrite(IceInternal::Buffer& buf)
+UWP::TransceiverI::finishWrite(IceInternal::Buffer& buf)
{
if(_connected && !_upgraded)
{
@@ -318,37 +315,37 @@ IceSSL::TransceiverI::finishWrite(IceInternal::Buffer& buf)
}
void
-IceSSL::TransceiverI::startRead(IceInternal::Buffer& buf)
+UWP::TransceiverI::startRead(IceInternal::Buffer& buf)
{
_delegate->startRead(buf);
}
void
-IceSSL::TransceiverI::finishRead(IceInternal::Buffer& buf)
+UWP::TransceiverI::finishRead(IceInternal::Buffer& buf)
{
_delegate->finishRead(buf);
}
string
-IceSSL::TransceiverI::protocol() const
+UWP::TransceiverI::protocol() const
{
return _instance->protocol();
}
string
-IceSSL::TransceiverI::toString() const
+UWP::TransceiverI::toString() const
{
return _delegate->toString();
}
string
-IceSSL::TransceiverI::toDetailedString() const
+UWP::TransceiverI::toDetailedString() const
{
return toString();
}
Ice::ConnectionInfoPtr
-IceSSL::TransceiverI::getInfo() const
+UWP::TransceiverI::getInfo() const
{
NativeConnectionInfoPtr info = ICE_MAKE_SHARED(NativeConnectionInfo);
info->verified = _verified;
@@ -361,22 +358,22 @@ IceSSL::TransceiverI::getInfo() const
}
void
-IceSSL::TransceiverI::checkSendSize(const IceInternal::Buffer&)
+UWP::TransceiverI::checkSendSize(const IceInternal::Buffer&)
{
}
void
-IceSSL::TransceiverI::setBufferSize(int rcvSize, int sndSize)
+UWP::TransceiverI::setBufferSize(int rcvSize, int sndSize)
{
_delegate->setBufferSize(rcvSize, sndSize);
}
-IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance,
+UWP::TransceiverI::TransceiverI(const InstancePtr& instance,
const IceInternal::TransceiverPtr& delegate,
const string& hostOrAdapterName,
bool incoming) :
_instance(instance),
- _engine(UWPEnginePtr::dynamicCast(instance->engine())),
+ _engine(UWP::SSLEnginePtr::dynamicCast(instance->engine())),
_host(incoming ? "" : hostOrAdapterName),
_adapterName(incoming ? hostOrAdapterName : ""),
_incoming(incoming),
@@ -387,8 +384,6 @@ IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance,
{
}
-IceSSL::TransceiverI::~TransceiverI()
+UWP::TransceiverI::~TransceiverI()
{
}
-
-#endif
diff --git a/cpp/src/IceSSL/UWPTransceiverI.h b/cpp/src/IceSSL/UWPTransceiverI.h
index e94aee18e67..fc9ab74ced9 100644
--- a/cpp/src/IceSSL/UWPTransceiverI.h
+++ b/cpp/src/IceSSL/UWPTransceiverI.h
@@ -11,11 +11,8 @@
#define ICESSL_UWP_TRANSCEIVER_I_H
#include <IceSSL/Config.h>
-
-#ifdef ICE_OS_UWP
-
#include <IceSSL/InstanceF.h>
-#include <IceSSL/SSLEngineF.h>
+#include <IceSSL/UWPEngineF.h>
#include <IceSSL/Plugin.h>
#include <Ice/Transceiver.h>
@@ -24,8 +21,8 @@
namespace IceSSL
{
-class ConnectorI;
-class AcceptorI;
+namespace UWP
+{
class TransceiverI : public IceInternal::Transceiver
{
@@ -55,11 +52,10 @@ private:
TransceiverI(const InstancePtr&, const IceInternal::TransceiverPtr&, const std::string&, bool);
virtual ~TransceiverI();
- friend class ConnectorI;
- friend class AcceptorI;
+ friend class SSLEngine;
const InstancePtr _instance;
- const UWPEnginePtr _engine;
+ const SSLEnginePtr _engine;
const std::string _host;
const std::string _adapterName;
const bool _incoming;
@@ -69,13 +65,13 @@ private:
bool _upgraded;
std::vector<std::string> _certs;
bool _verified;
- std::vector<CertificatePtr> _nativeCerts;
+ std::vector<IceSSL::CertificatePtr> _nativeCerts;
Windows::Security::Cryptography::Certificates::CertificateChain^ _chain;
};
typedef IceUtil::Handle<TransceiverI> TransceiverIPtr;
-}
+} // UWP namespace end
-#endif
+} // IceSSL namespace end
#endif
diff --git a/cpp/src/IceSSL/Util.cpp b/cpp/src/IceSSL/Util.cpp
index 52cd3c5144c..08f97a0c6fb 100755
--- a/cpp/src/IceSSL/Util.cpp
+++ b/cpp/src/IceSSL/Util.cpp
@@ -21,15 +21,9 @@
#include <Ice/Network.h>
#include <Ice/Object.h>
#include <Ice/StringConverter.h>
-#include <fstream>
+#include <Ice/UniqueRef.h>
-#ifdef ICE_USE_OPENSSL
-# include <openssl/err.h>
-//
-// Avoid old style cast warnings from OpenSSL macros
-//
-# pragma GCC diagnostic ignored "-Wold-style-cast"
-#endif
+#include <fstream>
using namespace std;
using namespace Ice;
@@ -37,16 +31,23 @@ using namespace IceInternal;
using namespace IceUtil;
using namespace IceSSL;
-#ifdef ICE_OS_UWP
-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;
+#if defined(__APPLE__)
+
+std::string
+IceSSL::fromCFString(CFStringRef v)
+{
+ string s;
+ if(v)
+ {
+ CFIndex size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(v), kCFStringEncodingUTF8);
+ vector<char> buffer;
+ buffer.resize(size + 1);
+ CFStringGetCString(v, &buffer[0], buffer.size(), kCFStringEncodingUTF8);
+ s.assign(&buffer[0]);
+ }
+ return s;
+}
+
#endif
#ifdef ICE_CPP11_MAPPING
@@ -73,14 +74,8 @@ IceSSL::PasswordPrompt::getPassword()
}
#endif
-
-#if !defined(ICE_USE_OPENSSL)
-
-namespace
-{
-
bool
-parseBytes(const string& arg, vector<unsigned char>& buffer)
+IceSSL::parseBytes(const string& arg, vector<unsigned char>& buffer)
{
string v = IceUtilInternal::toUpper(arg);
@@ -118,1776 +113,6 @@ parseBytes(const string& arg, vector<unsigned char>& buffer)
return true;
}
-}
-
-#endif
-
-#if defined(ICE_USE_OPENSSL)
-
-namespace
-{
-
-# ifndef OPENSSL_NO_DH
-# if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
-
-// The following arrays are predefined Diffie Hellman group parameters.
-// These are known strong primes, distributed with the OpenSSL library
-// in the files dh512.pem, dh1024.pem, dh2048.pem and dh4096.pem.
-// They are not keys themselves, but the basis for generating DH keys
-// on the fly.
-
-unsigned char dh512_p[] =
-{
- 0xF5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40,0x18,0x11,0x8D,0x7C,
- 0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03,0x19,0xC8,0x07,0x29,
- 0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB,0xD0,0x0A,0x50,0x9B,
- 0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D,0x41,0x9F,0x9C,0x7C,
- 0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB,0xA2,0x5E,0xC3,0x55,
- 0xE9,0x2A,0x05,0x5F,
-};
-
-unsigned char dh512_g[] = { 0x02 };
-
-unsigned char dh1024_p[] =
-{
- 0xF4,0x88,0xFD,0x58,0x4E,0x49,0xDB,0xCD,0x20,0xB4,0x9D,0xE4,
- 0x91,0x07,0x36,0x6B,0x33,0x6C,0x38,0x0D,0x45,0x1D,0x0F,0x7C,
- 0x88,0xB3,0x1C,0x7C,0x5B,0x2D,0x8E,0xF6,0xF3,0xC9,0x23,0xC0,
- 0x43,0xF0,0xA5,0x5B,0x18,0x8D,0x8E,0xBB,0x55,0x8C,0xB8,0x5D,
- 0x38,0xD3,0x34,0xFD,0x7C,0x17,0x57,0x43,0xA3,0x1D,0x18,0x6C,
- 0xDE,0x33,0x21,0x2C,0xB5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40,
- 0x18,0x11,0x8D,0x7C,0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03,
- 0x19,0xC8,0x07,0x29,0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB,
- 0xD0,0x0A,0x50,0x9B,0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D,
- 0x41,0x9F,0x9C,0x7C,0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB,
- 0xA2,0x5E,0xC3,0x55,0xE9,0x2F,0x78,0xC7,
-};
-
-unsigned char dh1024_g[] = { 0x02 };
-
-unsigned char dh2048_p[] =
-{
- 0xF6,0x42,0x57,0xB7,0x08,0x7F,0x08,0x17,0x72,0xA2,0xBA,0xD6,
- 0xA9,0x42,0xF3,0x05,0xE8,0xF9,0x53,0x11,0x39,0x4F,0xB6,0xF1,
- 0x6E,0xB9,0x4B,0x38,0x20,0xDA,0x01,0xA7,0x56,0xA3,0x14,0xE9,
- 0x8F,0x40,0x55,0xF3,0xD0,0x07,0xC6,0xCB,0x43,0xA9,0x94,0xAD,
- 0xF7,0x4C,0x64,0x86,0x49,0xF8,0x0C,0x83,0xBD,0x65,0xE9,0x17,
- 0xD4,0xA1,0xD3,0x50,0xF8,0xF5,0x59,0x5F,0xDC,0x76,0x52,0x4F,
- 0x3D,0x3D,0x8D,0xDB,0xCE,0x99,0xE1,0x57,0x92,0x59,0xCD,0xFD,
- 0xB8,0xAE,0x74,0x4F,0xC5,0xFC,0x76,0xBC,0x83,0xC5,0x47,0x30,
- 0x61,0xCE,0x7C,0xC9,0x66,0xFF,0x15,0xF9,0xBB,0xFD,0x91,0x5E,
- 0xC7,0x01,0xAA,0xD3,0x5B,0x9E,0x8D,0xA0,0xA5,0x72,0x3A,0xD4,
- 0x1A,0xF0,0xBF,0x46,0x00,0x58,0x2B,0xE5,0xF4,0x88,0xFD,0x58,
- 0x4E,0x49,0xDB,0xCD,0x20,0xB4,0x9D,0xE4,0x91,0x07,0x36,0x6B,
- 0x33,0x6C,0x38,0x0D,0x45,0x1D,0x0F,0x7C,0x88,0xB3,0x1C,0x7C,
- 0x5B,0x2D,0x8E,0xF6,0xF3,0xC9,0x23,0xC0,0x43,0xF0,0xA5,0x5B,
- 0x18,0x8D,0x8E,0xBB,0x55,0x8C,0xB8,0x5D,0x38,0xD3,0x34,0xFD,
- 0x7C,0x17,0x57,0x43,0xA3,0x1D,0x18,0x6C,0xDE,0x33,0x21,0x2C,
- 0xB5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40,0x18,0x11,0x8D,0x7C,
- 0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03,0x19,0xC8,0x07,0x29,
- 0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB,0xD0,0x0A,0x50,0x9B,
- 0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D,0x41,0x9F,0x9C,0x7C,
- 0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB,0xA2,0x5E,0xC3,0x55,
- 0xE9,0x32,0x0B,0x3B,
-};
-
-unsigned char dh2048_g[] = { 0x02 };
-
-unsigned char dh4096_p[] =
-{
- 0xFA,0x14,0x72,0x52,0xC1,0x4D,0xE1,0x5A,0x49,0xD4,0xEF,0x09,
- 0x2D,0xC0,0xA8,0xFD,0x55,0xAB,0xD7,0xD9,0x37,0x04,0x28,0x09,
- 0xE2,0xE9,0x3E,0x77,0xE2,0xA1,0x7A,0x18,0xDD,0x46,0xA3,0x43,
- 0x37,0x23,0x90,0x97,0xF3,0x0E,0xC9,0x03,0x50,0x7D,0x65,0xCF,
- 0x78,0x62,0xA6,0x3A,0x62,0x22,0x83,0xA1,0x2F,0xFE,0x79,0xBA,
- 0x35,0xFF,0x59,0xD8,0x1D,0x61,0xDD,0x1E,0x21,0x13,0x17,0xFE,
- 0xCD,0x38,0x87,0x9E,0xF5,0x4F,0x79,0x10,0x61,0x8D,0xD4,0x22,
- 0xF3,0x5A,0xED,0x5D,0xEA,0x21,0xE9,0x33,0x6B,0x48,0x12,0x0A,
- 0x20,0x77,0xD4,0x25,0x60,0x61,0xDE,0xF6,0xB4,0x4F,0x1C,0x63,
- 0x40,0x8B,0x3A,0x21,0x93,0x8B,0x79,0x53,0x51,0x2C,0xCA,0xB3,
- 0x7B,0x29,0x56,0xA8,0xC7,0xF8,0xF4,0x7B,0x08,0x5E,0xA6,0xDC,
- 0xA2,0x45,0x12,0x56,0xDD,0x41,0x92,0xF2,0xDD,0x5B,0x8F,0x23,
- 0xF0,0xF3,0xEF,0xE4,0x3B,0x0A,0x44,0xDD,0xED,0x96,0x84,0xF1,
- 0xA8,0x32,0x46,0xA3,0xDB,0x4A,0xBE,0x3D,0x45,0xBA,0x4E,0xF8,
- 0x03,0xE5,0xDD,0x6B,0x59,0x0D,0x84,0x1E,0xCA,0x16,0x5A,0x8C,
- 0xC8,0xDF,0x7C,0x54,0x44,0xC4,0x27,0xA7,0x3B,0x2A,0x97,0xCE,
- 0xA3,0x7D,0x26,0x9C,0xAD,0xF4,0xC2,0xAC,0x37,0x4B,0xC3,0xAD,
- 0x68,0x84,0x7F,0x99,0xA6,0x17,0xEF,0x6B,0x46,0x3A,0x7A,0x36,
- 0x7A,0x11,0x43,0x92,0xAD,0xE9,0x9C,0xFB,0x44,0x6C,0x3D,0x82,
- 0x49,0xCC,0x5C,0x6A,0x52,0x42,0xF8,0x42,0xFB,0x44,0xF9,0x39,
- 0x73,0xFB,0x60,0x79,0x3B,0xC2,0x9E,0x0B,0xDC,0xD4,0xA6,0x67,
- 0xF7,0x66,0x3F,0xFC,0x42,0x3B,0x1B,0xDB,0x4F,0x66,0xDC,0xA5,
- 0x8F,0x66,0xF9,0xEA,0xC1,0xED,0x31,0xFB,0x48,0xA1,0x82,0x7D,
- 0xF8,0xE0,0xCC,0xB1,0xC7,0x03,0xE4,0xF8,0xB3,0xFE,0xB7,0xA3,
- 0x13,0x73,0xA6,0x7B,0xC1,0x0E,0x39,0xC7,0x94,0x48,0x26,0x00,
- 0x85,0x79,0xFC,0x6F,0x7A,0xAF,0xC5,0x52,0x35,0x75,0xD7,0x75,
- 0xA4,0x40,0xFA,0x14,0x74,0x61,0x16,0xF2,0xEB,0x67,0x11,0x6F,
- 0x04,0x43,0x3D,0x11,0x14,0x4C,0xA7,0x94,0x2A,0x39,0xA1,0xC9,
- 0x90,0xCF,0x83,0xC6,0xFF,0x02,0x8F,0xA3,0x2A,0xAC,0x26,0xDF,
- 0x0B,0x8B,0xBE,0x64,0x4A,0xF1,0xA1,0xDC,0xEE,0xBA,0xC8,0x03,
- 0x82,0xF6,0x62,0x2C,0x5D,0xB6,0xBB,0x13,0x19,0x6E,0x86,0xC5,
- 0x5B,0x2B,0x5E,0x3A,0xF3,0xB3,0x28,0x6B,0x70,0x71,0x3A,0x8E,
- 0xFF,0x5C,0x15,0xE6,0x02,0xA4,0xCE,0xED,0x59,0x56,0xCC,0x15,
- 0x51,0x07,0x79,0x1A,0x0F,0x25,0x26,0x27,0x30,0xA9,0x15,0xB2,
- 0xC8,0xD4,0x5C,0xCC,0x30,0xE8,0x1B,0xD8,0xD5,0x0F,0x19,0xA8,
- 0x80,0xA4,0xC7,0x01,0xAA,0x8B,0xBA,0x53,0xBB,0x47,0xC2,0x1F,
- 0x6B,0x54,0xB0,0x17,0x60,0xED,0x79,0x21,0x95,0xB6,0x05,0x84,
- 0x37,0xC8,0x03,0xA4,0xDD,0xD1,0x06,0x69,0x8F,0x4C,0x39,0xE0,
- 0xC8,0x5D,0x83,0x1D,0xBE,0x6A,0x9A,0x99,0xF3,0x9F,0x0B,0x45,
- 0x29,0xD4,0xCB,0x29,0x66,0xEE,0x1E,0x7E,0x3D,0xD7,0x13,0x4E,
- 0xDB,0x90,0x90,0x58,0xCB,0x5E,0x9B,0xCD,0x2E,0x2B,0x0F,0xA9,
- 0x4E,0x78,0xAC,0x05,0x11,0x7F,0xE3,0x9E,0x27,0xD4,0x99,0xE1,
- 0xB9,0xBD,0x78,0xE1,0x84,0x41,0xA0,0xDF,
-};
-
-unsigned char dh4096_g[] = { 0x02 };
-
-# else
-//
-// With OpenSSL 1.1.0 is no longer possible to acess the DH p and g
-// data members to set the DH params. We still use the same default
-// parameters but they were converted to DER format using
-// i2d_DHparams and can be restored using d2i_DHparams
-
-unsigned char dh512[] =
-{
- 0x30,0x46,0x02,0x41,0x00,0xF5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,
- 0x40,0x18,0x11,0x8D,0x7C,0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,
- 0x03,0x19,0xC8,0x07,0x29,0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,
- 0xAB,0xD0,0x0A,0x50,0x9B,0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,
- 0x5D,0x41,0x9F,0x9C,0x7C,0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,
- 0xAB,0xA2,0x5E,0xC3,0x55,0xE9,0x2A,0x05,0x5F,0x02,0x01,0x02,
-};
-
-unsigned char dh1024[] =
-{
- 0x30,0x81,0x87,0x02,0x81,0x81,0x00,0xF4,0x88,0xFD,0x58,0x4E,
- 0x49,0xDB,0xCD,0x20,0xB4,0x9D,0xE4,0x91,0x07,0x36,0x6B,0x33,
- 0x6C,0x38,0x0D,0x45,0x1D,0x0F,0x7C,0x88,0xB3,0x1C,0x7C,0x5B,
- 0x2D,0x8E,0xF6,0xF3,0xC9,0x23,0xC0,0x43,0xF0,0xA5,0x5B,0x18,
- 0x8D,0x8E,0xBB,0x55,0x8C,0xB8,0x5D,0x38,0xD3,0x34,0xFD,0x7C,
- 0x17,0x57,0x43,0xA3,0x1D,0x18,0x6C,0xDE,0x33,0x21,0x2C,0xB5,
- 0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40,0x18,0x11,0x8D,0x7C,0x84,
- 0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03,0x19,0xC8,0x07,0x29,0x7A,
- 0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB,0xD0,0x0A,0x50,0x9B,0x02,
- 0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D,0x41,0x9F,0x9C,0x7C,0xBD,
- 0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB,0xA2,0x5E,0xC3,0x55,0xE9,
- 0x2F,0x78,0xC7,0x02,0x01,0x02,
-};
-
-unsigned char dh2048[] =
-{
- 0x30,0x82,0x01,0x08,0x02,0x82,0x01,0x01,0x00,0xF6,0x42,0x57,
- 0xB7,0x08,0x7F,0x08,0x17,0x72,0xA2,0xBA,0xD6,0xA9,0x42,0xF3,
- 0x05,0xE8,0xF9,0x53,0x11,0x39,0x4F,0xB6,0xF1,0x6E,0xB9,0x4B,
- 0x38,0x20,0xDA,0x01,0xA7,0x56,0xA3,0x14,0xE9,0x8F,0x40,0x55,
- 0xF3,0xD0,0x07,0xC6,0xCB,0x43,0xA9,0x94,0xAD,0xF7,0x4C,0x64,
- 0x86,0x49,0xF8,0x0C,0x83,0xBD,0x65,0xE9,0x17,0xD4,0xA1,0xD3,
- 0x50,0xF8,0xF5,0x59,0x5F,0xDC,0x76,0x52,0x4F,0x3D,0x3D,0x8D,
- 0xDB,0xCE,0x99,0xE1,0x57,0x92,0x59,0xCD,0xFD,0xB8,0xAE,0x74,
- 0x4F,0xC5,0xFC,0x76,0xBC,0x83,0xC5,0x47,0x30,0x61,0xCE,0x7C,
- 0xC9,0x66,0xFF,0x15,0xF9,0xBB,0xFD,0x91,0x5E,0xC7,0x01,0xAA,
- 0xD3,0x5B,0x9E,0x8D,0xA0,0xA5,0x72,0x3A,0xD4,0x1A,0xF0,0xBF,
- 0x46,0x00,0x58,0x2B,0xE5,0xF4,0x88,0xFD,0x58,0x4E,0x49,0xDB,
- 0xCD,0x20,0xB4,0x9D,0xE4,0x91,0x07,0x36,0x6B,0x33,0x6C,0x38,
- 0x0D,0x45,0x1D,0x0F,0x7C,0x88,0xB3,0x1C,0x7C,0x5B,0x2D,0x8E,
- 0xF6,0xF3,0xC9,0x23,0xC0,0x43,0xF0,0xA5,0x5B,0x18,0x8D,0x8E,
- 0xBB,0x55,0x8C,0xB8,0x5D,0x38,0xD3,0x34,0xFD,0x7C,0x17,0x57,
- 0x43,0xA3,0x1D,0x18,0x6C,0xDE,0x33,0x21,0x2C,0xB5,0x2A,0xFF,
- 0x3C,0xE1,0xB1,0x29,0x40,0x18,0x11,0x8D,0x7C,0x84,0xA7,0x0A,
- 0x72,0xD6,0x86,0xC4,0x03,0x19,0xC8,0x07,0x29,0x7A,0xCA,0x95,
- 0x0C,0xD9,0x96,0x9F,0xAB,0xD0,0x0A,0x50,0x9B,0x02,0x46,0xD3,
- 0x08,0x3D,0x66,0xA4,0x5D,0x41,0x9F,0x9C,0x7C,0xBD,0x89,0x4B,
- 0x22,0x19,0x26,0xBA,0xAB,0xA2,0x5E,0xC3,0x55,0xE9,0x32,0x0B,
- 0x3B,0x02,0x01,0x02,
-};
-
-unsigned char dh4096[] =
-{
- 0x30,0x82,0x02,0x08,0x02,0x82,0x02,0x01,0x00,0xFA,0x14,0x72,
- 0x52,0xC1,0x4D,0xE1,0x5A,0x49,0xD4,0xEF,0x09,0x2D,0xC0,0xA8,
- 0xFD,0x55,0xAB,0xD7,0xD9,0x37,0x04,0x28,0x09,0xE2,0xE9,0x3E,
- 0x77,0xE2,0xA1,0x7A,0x18,0xDD,0x46,0xA3,0x43,0x37,0x23,0x90,
- 0x97,0xF3,0x0E,0xC9,0x03,0x50,0x7D,0x65,0xCF,0x78,0x62,0xA6,
- 0x3A,0x62,0x22,0x83,0xA1,0x2F,0xFE,0x79,0xBA,0x35,0xFF,0x59,
- 0xD8,0x1D,0x61,0xDD,0x1E,0x21,0x13,0x17,0xFE,0xCD,0x38,0x87,
- 0x9E,0xF5,0x4F,0x79,0x10,0x61,0x8D,0xD4,0x22,0xF3,0x5A,0xED,
- 0x5D,0xEA,0x21,0xE9,0x33,0x6B,0x48,0x12,0x0A,0x20,0x77,0xD4,
- 0x25,0x60,0x61,0xDE,0xF6,0xB4,0x4F,0x1C,0x63,0x40,0x8B,0x3A,
- 0x21,0x93,0x8B,0x79,0x53,0x51,0x2C,0xCA,0xB3,0x7B,0x29,0x56,
- 0xA8,0xC7,0xF8,0xF4,0x7B,0x08,0x5E,0xA6,0xDC,0xA2,0x45,0x12,
- 0x56,0xDD,0x41,0x92,0xF2,0xDD,0x5B,0x8F,0x23,0xF0,0xF3,0xEF,
- 0xE4,0x3B,0x0A,0x44,0xDD,0xED,0x96,0x84,0xF1,0xA8,0x32,0x46,
- 0xA3,0xDB,0x4A,0xBE,0x3D,0x45,0xBA,0x4E,0xF8,0x03,0xE5,0xDD,
- 0x6B,0x59,0x0D,0x84,0x1E,0xCA,0x16,0x5A,0x8C,0xC8,0xDF,0x7C,
- 0x54,0x44,0xC4,0x27,0xA7,0x3B,0x2A,0x97,0xCE,0xA3,0x7D,0x26,
- 0x9C,0xAD,0xF4,0xC2,0xAC,0x37,0x4B,0xC3,0xAD,0x68,0x84,0x7F,
- 0x99,0xA6,0x17,0xEF,0x6B,0x46,0x3A,0x7A,0x36,0x7A,0x11,0x43,
- 0x92,0xAD,0xE9,0x9C,0xFB,0x44,0x6C,0x3D,0x82,0x49,0xCC,0x5C,
- 0x6A,0x52,0x42,0xF8,0x42,0xFB,0x44,0xF9,0x39,0x73,0xFB,0x60,
- 0x79,0x3B,0xC2,0x9E,0x0B,0xDC,0xD4,0xA6,0x67,0xF7,0x66,0x3F,
- 0xFC,0x42,0x3B,0x1B,0xDB,0x4F,0x66,0xDC,0xA5,0x8F,0x66,0xF9,
- 0xEA,0xC1,0xED,0x31,0xFB,0x48,0xA1,0x82,0x7D,0xF8,0xE0,0xCC,
- 0xB1,0xC7,0x03,0xE4,0xF8,0xB3,0xFE,0xB7,0xA3,0x13,0x73,0xA6,
- 0x7B,0xC1,0x0E,0x39,0xC7,0x94,0x48,0x26,0x00,0x85,0x79,0xFC,
- 0x6F,0x7A,0xAF,0xC5,0x52,0x35,0x75,0xD7,0x75,0xA4,0x40,0xFA,
- 0x14,0x74,0x61,0x16,0xF2,0xEB,0x67,0x11,0x6F,0x04,0x43,0x3D,
- 0x11,0x14,0x4C,0xA7,0x94,0x2A,0x39,0xA1,0xC9,0x90,0xCF,0x83,
- 0xC6,0xFF,0x02,0x8F,0xA3,0x2A,0xAC,0x26,0xDF,0x0B,0x8B,0xBE,
- 0x64,0x4A,0xF1,0xA1,0xDC,0xEE,0xBA,0xC8,0x03,0x82,0xF6,0x62,
- 0x2C,0x5D,0xB6,0xBB,0x13,0x19,0x6E,0x86,0xC5,0x5B,0x2B,0x5E,
- 0x3A,0xF3,0xB3,0x28,0x6B,0x70,0x71,0x3A,0x8E,0xFF,0x5C,0x15,
- 0xE6,0x02,0xA4,0xCE,0xED,0x59,0x56,0xCC,0x15,0x51,0x07,0x79,
- 0x1A,0x0F,0x25,0x26,0x27,0x30,0xA9,0x15,0xB2,0xC8,0xD4,0x5C,
- 0xCC,0x30,0xE8,0x1B,0xD8,0xD5,0x0F,0x19,0xA8,0x80,0xA4,0xC7,
- 0x01,0xAA,0x8B,0xBA,0x53,0xBB,0x47,0xC2,0x1F,0x6B,0x54,0xB0,
- 0x17,0x60,0xED,0x79,0x21,0x95,0xB6,0x05,0x84,0x37,0xC8,0x03,
- 0xA4,0xDD,0xD1,0x06,0x69,0x8F,0x4C,0x39,0xE0,0xC8,0x5D,0x83,
- 0x1D,0xBE,0x6A,0x9A,0x99,0xF3,0x9F,0x0B,0x45,0x29,0xD4,0xCB,
- 0x29,0x66,0xEE,0x1E,0x7E,0x3D,0xD7,0x13,0x4E,0xDB,0x90,0x90,
- 0x58,0xCB,0x5E,0x9B,0xCD,0x2E,0x2B,0x0F,0xA9,0x4E,0x78,0xAC,
- 0x05,0x11,0x7F,0xE3,0x9E,0x27,0xD4,0x99,0xE1,0xB9,0xBD,0x78,
- 0xE1,0x84,0x41,0xA0,0xDF,0x02,0x01,0x02,
-};
-# endif
-
-}
-
-//
-// Convert a predefined parameter set into a DH value.
-//
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
-static DH*
-convertDH(const unsigned char* buf, int len)
-{
- return d2i_DHparams(0, &buf, len);
-}
-# else
-static DH*
-convertDH(unsigned char* p, int plen, unsigned char* g, int glen)
-{
- assert(p != 0);
- assert(g != 0);
-
- DH* dh = DH_new();
-
- if(dh != 0)
- {
- dh->p = BN_bin2bn(p, plen, 0);
- dh->g = BN_bin2bn(g, glen, 0);
-
- if((dh->p == 0) || (dh->g == 0))
- {
- DH_free(dh);
- dh = 0;
- }
- }
- return dh;
-}
-# endif
-
-IceSSL::DHParams::DHParams() :
- _dh512(0), _dh1024(0), _dh2048(0), _dh4096(0)
-{
-}
-
-IceSSL::DHParams::~DHParams()
-{
- for(ParamList::iterator p = _params.begin(); p != _params.end(); ++p)
- {
- DH_free(p->second);
- }
- DH_free(_dh512);
- DH_free(_dh1024);
- DH_free(_dh2048);
- DH_free(_dh4096);
-}
-
-bool
-IceSSL::DHParams::add(int keyLength, const string& file)
-{
- BIO* bio = BIO_new(BIO_s_file());
- if(BIO_read_filename(bio, file.c_str()) <= 0)
- {
- BIO_free(bio);
- return false;
- }
- DH* dh = PEM_read_bio_DHparams(bio, 0, 0, 0);
- BIO_free(bio);
- if(!dh)
- {
- return false;
- }
- ParamList::iterator p = _params.begin();
- while(p != _params.end() && keyLength > p->first)
- {
- ++p;
- }
- _params.insert(p, KeyParamPair(keyLength, dh));
- return true;
-}
-
-DH*
-IceSSL::DHParams::get(int keyLength)
-{
- //
- // First check the set of parameters specified by the user.
- // Return the first set whose key length is at least keyLength.
- //
- for(ParamList::iterator p = _params.begin(); p != _params.end(); ++p)
- {
- if(p->first >= keyLength)
- {
- return p->second;
- }
- }
-
- //
- // No match found. Use one of the predefined parameter sets instead.
- //
- IceUtil::Mutex::Lock sync(*this);
-# if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
- if(keyLength >= 4096)
- {
- if(!_dh4096)
- {
- _dh4096 = convertDH(dh4096, (int) sizeof(dh4096));
- }
- return _dh4096;
- }
- else if(keyLength >= 2048)
- {
- if(!_dh2048)
- {
- _dh2048 = convertDH(dh2048, (int) sizeof(dh2048));
- }
- return _dh2048;
- }
- else if(keyLength >= 1024)
- {
- if(!_dh1024)
- {
- _dh1024 = convertDH(dh1024, (int) sizeof(dh1024));
- }
- return _dh1024;
- }
- else
- {
- if(!_dh512)
- {
- _dh512 = convertDH(dh512, (int) sizeof(dh512));
- }
- return _dh512;
- }
-# else
- if(keyLength >= 4096)
- {
- if(!_dh4096)
- {
- _dh4096 = convertDH(dh4096_p, (int) sizeof(dh4096_p), dh4096_g, (int) sizeof(dh4096_g));
- }
- return _dh4096;
- }
- else if(keyLength >= 2048)
- {
- if(!_dh2048)
- {
- _dh2048 = convertDH(dh2048_p, (int) sizeof(dh2048_p), dh2048_g, (int) sizeof(dh2048_g));
- }
- return _dh2048;
- }
- else if(keyLength >= 1024)
- {
- if(!_dh1024)
- {
- _dh1024 = convertDH(dh1024_p, (int) sizeof(dh1024_p), dh1024_g, (int) sizeof(dh1024_g));
- }
- return _dh1024;
- }
- else
- {
- if(!_dh512)
- {
- _dh512 = convertDH(dh512_p, (int) sizeof(dh512_p), dh512_g, (int) sizeof(dh512_g));
- }
- return _dh512;
- }
-# endif
-}
-
-# endif
-
-string
-IceSSL::getSslErrors(bool verbose)
-{
- ostringstream ostr;
-
- const char* file;
- const char* data;
- int line;
- int flags;
- unsigned long err;
- int count = 0;
- while((err = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0)
- {
- if(count > 0)
- {
- ostr << endl;
- }
-
- if(verbose)
- {
- if(count > 0)
- {
- ostr << endl;
- }
-
- char buf[200];
- ERR_error_string_n(err, buf, sizeof(buf));
-
- ostr << "error # = " << err << endl;
- ostr << "message = " << buf << endl;
- ostr << "location = " << file << ", " << line;
- if(flags & ERR_TXT_STRING)
- {
- ostr << endl;
- ostr << "data = " << data;
- }
- }
- else
- {
- const char* reason = ERR_reason_error_string(err);
- ostr << (reason == ICE_NULLPTR ? "unknown reason" : reason);
- if(flags & ERR_TXT_STRING)
- {
- ostr << ": " << data;
- }
- }
-
- ++count;
- }
-
- ERR_clear_error();
-
- return ostr.str();
-}
-
-#elif defined(ICE_USE_SECURE_TRANSPORT)
-
-string
-IceSSL::errorToString(CFErrorRef err)
-{
- ostringstream os;
- if(err)
- {
- UniqueRef<CFStringRef> s(CFErrorCopyDescription(err));
- os << "(error: " << CFErrorGetCode(err) << " description: " << fromCFString(s.get()) << ")";
- }
- return os.str();
-}
-
-string
-IceSSL::errorToString(OSStatus status)
-{
- ostringstream os;
- os << "(error: " << status;
-#if defined(ICE_USE_SECURE_TRANSPORT_MACOS)
- UniqueRef<CFStringRef> s(SecCopyErrorMessageString(status, 0));
- if(s)
- {
- os << " description: " << fromCFString(s.get());
- }
-#endif
- os << ")";
- return os.str();
-}
-
-std::string
-IceSSL::fromCFString(CFStringRef v)
-{
- string s;
- if(v)
- {
- CFIndex size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(v), kCFStringEncodingUTF8);
- vector<char> buffer;
- buffer.resize(size + 1);
- CFStringGetCString(v, &buffer[0], buffer.size(), kCFStringEncodingUTF8);
- s.assign(&buffer[0]);
- }
- return s;
-}
-
-#if defined(ICE_USE_SECURE_TRANSPORT_MACOS)
-CFDictionaryRef
-IceSSL::getCertificateProperty(SecCertificateRef cert, CFTypeRef key)
-{
- UniqueRef<CFDictionaryRef> property;
- UniqueRef<CFArrayRef> keys(CFArrayCreate(ICE_NULLPTR, &key , 1, &kCFTypeArrayCallBacks));
- UniqueRef<CFErrorRef> err;
- UniqueRef<CFDictionaryRef> values(SecCertificateCopyValues(cert, keys.get(), &err.get()));
- if(err)
- {
- ostringstream os;
- os << "IceSSL: error getting property for certificate:\n" << errorToString(err);
- throw CertificateReadException(__FILE__, __LINE__, os.str());
- }
-
- assert(values);
- property.retain(static_cast<CFDictionaryRef>(CFDictionaryGetValue(values.get(), key)));
- return property.release();
-}
-#endif
-
-namespace
-{
-
-CFMutableDataRef
-readCertFile(const string& file)
-{
- ifstream is(IceUtilInternal::streamFilename(file).c_str(), 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);
-
- UniqueRef<CFMutableDataRef> data(CFDataCreateMutable(kCFAllocatorDefault, size));
- CFDataSetLength(data.get(), size);
- is.read(reinterpret_cast<char*>(CFDataGetMutableBytePtr(data.get())), size);
- if(!is.good())
- {
- throw CertificateReadException(__FILE__, __LINE__, "error reading file " + file);
- }
- return data.release();
-}
-
-#if defined(ICE_USE_SECURE_TRANSPORT_MACOS)
-//
-// Check the certificate basic constraints to check if the certificate is marked as a CA.
-//
-bool
-isCA(SecCertificateRef cert)
-{
- UniqueRef<CFDictionaryRef> property(getCertificateProperty(cert, kSecOIDBasicConstraints));
- if(property)
- {
- CFArrayRef propertyValues = static_cast<CFArrayRef>(CFDictionaryGetValue(property.get(), kSecPropertyKeyValue));
- for(int i = 0, size = CFArrayGetCount(propertyValues); i < size; ++i)
- {
- CFDictionaryRef dict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(propertyValues, i));
- CFStringRef label = static_cast<CFStringRef>(CFDictionaryGetValue(dict, kSecPropertyKeyLabel));
- if(CFEqual(label, CFSTR("Certificate Authority")))
- {
- return CFEqual(static_cast<CFStringRef>(CFDictionaryGetValue(dict, kSecPropertyKeyValue)), CFSTR("Yes"));
- }
- }
- }
- return false;
-}
-
-//
-// Load keychain items (Certificates or Private Keys) from a file. On return items param contain
-// the list of items, the caller must release it.
-//
-CFArrayRef
-loadKeychainItems(const string& file, SecExternalItemType type, SecKeychainRef keychain, const string& passphrase,
- const PasswordPromptPtr& prompt, int retryMax)
-{
- UniqueRef<CFMutableDataRef> data(readCertFile(file));
-
- SecItemImportExportKeyParameters params;
- memset(&params, 0, sizeof(params));
- params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
- params.flags |= kSecKeyNoAccessControl;
- if(!passphrase.empty())
- {
- params.passphrase = toCFString(passphrase);
- }
-
- UniqueRef<CFArrayRef> items;
- SecExternalItemType importType = type;
- SecExternalFormat format = type == kSecItemTypeUnknown ? kSecFormatPKCS12 : kSecFormatUnknown;
- UniqueRef<CFStringRef> path(toCFString(file));
- OSStatus err = SecItemImport(data.get(), path.get(), &format, &importType, 0, &params, keychain, &items.get());
-
- //
- // If passphrase failure and no password was configured, we obtain
- // the password from the given prompt or configure the import to
- // prompt the user with an alert dialog.
- //
- UniqueRef<CFStringRef> passphraseHolder;
- UniqueRef<CFStringRef> alertPromptHolder;
- if(passphrase.empty() &&
- (err == errSecPassphraseRequired || err == errSecInvalidData || err == errSecPkcs12VerifyFailure))
- {
- if(!prompt)
- {
- params.flags |= kSecKeySecurePassphrase;
- ostringstream os;
- os << "Enter the password for\n" << file;
- alertPromptHolder.reset(toCFString(os.str()));
- params.alertPrompt = alertPromptHolder.get();
- }
-
- int count = 0;
- while((err == errSecPassphraseRequired || err == errSecInvalidData || err == errSecPkcs12VerifyFailure) &&
- count < retryMax)
- {
- if(prompt)
- {
- passphraseHolder.reset(toCFString(prompt->getPassword()));
- params.passphrase = passphraseHolder.get();
- }
- err = SecItemImport(data.get(), path.get(), &format, &importType, 0, &params, keychain, &items.get());
- ++count;
- }
- }
-
- if(err != noErr)
- {
- ostringstream os;
- os << "IceSSL: error reading " << (type == kSecItemTypePrivateKey ? "private key" : "certificate");
- os << " `" << file << "':\n" << errorToString(err);
- throw CertificateReadException(__FILE__, __LINE__, os.str());
- }
-
- if(type != kSecItemTypeUnknown && importType != kSecItemTypeAggregate && importType != type)
- {
- ostringstream os;
- os << "IceSSL: error reading " << (type == kSecItemTypePrivateKey ? "private key" : "certificate");
- os << " `" << file << "' doesn't contain the expected item";
- throw CertificateReadException(__FILE__, __LINE__, os.str());
- }
-
- return items.release();
-}
-
-SecKeychainRef
-openKeychain(const std::string& path, const std::string& keychainPassword)
-{
- string keychainPath = path;
- UniqueRef<SecKeychainRef> keychain;
- OSStatus err = 0;
- if(keychainPath.empty())
- {
- if((err = SecKeychainCopyDefault(&keychain.get())))
- {
- 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.get())))
- {
- throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: unable to open keychain: `" +
- keychainPath + "'\n" + errorToString(err));
- }
- }
-
- SecKeychainStatus status;
- err = SecKeychainGetStatus(keychain.get(), &status);
- if(err == noErr)
- {
- const char* pass = keychainPassword.empty() ? 0 : keychainPassword.c_str();
- if((err = SecKeychainUnlock(keychain.get(), 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();
- keychain.reset(0);
- if((err = SecKeychainCreate(keychainPath.c_str(), keychainPassword.size(), pass, pass == 0, 0, &keychain.get())))
- {
- throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: unable to create keychain:\n" + errorToString(err));
- }
- }
- 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.get(), &settings)))
- {
- throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: error setting keychain settings:\n" + errorToString(err));
- }
-
- return keychain.release();
-}
-
-//
-// Imports a certificate private key and optionally add it to a keychain.
-//
-SecIdentityRef
-loadPrivateKey(const string& file, SecCertificateRef cert, SecKeychainRef keychain, const string& password,
- const PasswordPromptPtr& prompt, int retryMax)
-{
- //
- // Check if we already imported the certificate
- //
- UniqueRef<CFDataRef> hash;
- UniqueRef<CFDictionaryRef> subjectKeyProperty(getCertificateProperty(cert, kSecOIDSubjectKeyIdentifier));
- if(subjectKeyProperty)
- {
- CFArrayRef values = static_cast<CFArrayRef>(CFDictionaryGetValue(subjectKeyProperty.get(),
- kSecPropertyKeyValue));
- for(int i = 0; i < CFArrayGetCount(values); ++i)
- {
- CFDictionaryRef dict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(values, i));
- if(CFEqual(CFDictionaryGetValue(dict, kSecPropertyKeyLabel), CFSTR("Key Identifier")))
- {
- hash.retain(static_cast<CFDataRef>(CFDictionaryGetValue(dict, kSecPropertyKeyValue)));
- break;
- }
- }
- }
-
- const void* values[] = { keychain };
- UniqueRef<CFArrayRef> searchList(CFArrayCreate(kCFAllocatorDefault, values, 1, &kCFTypeArrayCallBacks));
-
- UniqueRef<CFMutableDictionaryRef> query(CFDictionaryCreateMutable(0,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
-
- CFDictionarySetValue(query.get(), kSecClass, kSecClassCertificate);
- CFDictionarySetValue(query.get(), kSecMatchLimit, kSecMatchLimitOne);
- CFDictionarySetValue(query.get(), kSecMatchSearchList, searchList.get());
- CFDictionarySetValue(query.get(), kSecAttrSubjectKeyID, hash.get());
- CFDictionarySetValue(query.get(), kSecReturnRef, kCFBooleanTrue);
-
- UniqueRef<CFTypeRef> value(0);
- OSStatus err = SecItemCopyMatching(query.get(), &value.get());
- UniqueRef<SecCertificateRef> item(static_cast<SecCertificateRef>(const_cast<void*>(value.release())));
- if(err == noErr)
- {
- //
- // If the certificate has already been imported, create the
- // identity. The key should also have been imported.
- //
- UniqueRef<SecIdentityRef> identity;
- err = SecIdentityCreateWithCertificate(keychain, item.get(), &identity.get());
- if(err != noErr)
- {
- ostringstream os;
- os << "IceSSL: error creating certificate identity:\n" << errorToString(err);
- throw CertificateReadException(__FILE__, __LINE__, os.str());
- }
- return identity.release();
- }
- else if(err != errSecItemNotFound)
- {
- ostringstream os;
- os << "IceSSL: error searching for keychain items:\n" << errorToString(err);
- throw CertificateReadException(__FILE__, __LINE__, os.str());
- }
-
- //
- // If the certificate isn't already in the keychain, load the
- // private key into the keychain and add the certificate.
- //
- UniqueRef<CFArrayRef> items(loadKeychainItems(file, kSecItemTypePrivateKey, keychain, password, prompt, retryMax));
- int count = CFArrayGetCount(items.get());
- UniqueRef<SecKeyRef> key;
- for(int i = 0; i < count; ++i)
- {
- SecKeychainItemRef item =
- static_cast<SecKeychainItemRef>(const_cast<void*>(CFArrayGetValueAtIndex(items.get(), 0)));
- if(SecKeyGetTypeID() == CFGetTypeID(item))
- {
- key.retain(reinterpret_cast<SecKeyRef>(item));
- break;
- }
- }
- if(!key)
- {
- throw CertificateReadException(__FILE__, __LINE__, "IceSSL: no key in file `" + file + "'");
- }
-
- //
- // Add the certificate to the keychain
- //
- query.reset(CFDictionaryCreateMutable(kCFAllocatorDefault,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
-
- CFDictionarySetValue(query.get(), kSecUseKeychain, keychain);
- CFDictionarySetValue(query.get(), kSecClass, kSecClassCertificate);
- CFDictionarySetValue(query.get(), kSecValueRef, cert);
- CFDictionarySetValue(query.get(), kSecReturnRef, kCFBooleanTrue);
-
- value.reset(0);
- err = SecItemAdd(query.get(), static_cast<CFTypeRef*>(&value.get()));
- UniqueRef<CFArrayRef> added(static_cast<CFArrayRef>(value.release()));
- if(err != noErr)
- {
- ostringstream os;
- os << "IceSSL: failure adding certificate to keychain\n" << errorToString(err);
- throw CertificateReadException(__FILE__, __LINE__, os.str());
- }
- item.retain(static_cast<SecCertificateRef>(const_cast<void*>(CFArrayGetValueAtIndex(added.get(), 0))));
-
- //
- // Create the association between the private key and the certificate,
- // kSecKeyLabel attribute should match the subject key identifier.
- //
- vector<SecKeychainAttribute> attributes;
- if(hash)
- {
- SecKeychainAttribute attr;
- attr.tag = kSecKeyLabel;
- attr.data = const_cast<UInt8*>(CFDataGetBytePtr(hash.get()));
- attr.length = CFDataGetLength(hash.get());
- attributes.push_back(attr);
- }
-
- //
- // kSecKeyPrintName attribute correspond to the keychain display
- // name.
- //
- string label;
- UniqueRef<CFStringRef> commonName(0);
- if(SecCertificateCopyCommonName(item.get(), &commonName.get()) == noErr)
- {
- label = fromCFString(commonName.get());
- SecKeychainAttribute attr;
- attr.tag = kSecKeyPrintName;
- attr.data = const_cast<char*>(label.c_str());
- attr.length = label.size();
- attributes.push_back(attr);
- }
-
- SecKeychainAttributeList attrs;
- attrs.attr = &attributes[0];
- attrs.count = attributes.size();
- SecKeychainItemModifyAttributesAndData(reinterpret_cast<SecKeychainItemRef>(key.get()), &attrs, 0, 0);
-
- UniqueRef<SecIdentityRef> identity;
- err = SecIdentityCreateWithCertificate(keychain, item.get(), &identity.get());
- if(err != noErr)
- {
- ostringstream os;
- os << "IceSSL: error creating certificate identity:\n" << errorToString(err);
- throw CertificateReadException(__FILE__, __LINE__, os.str());
- }
- return identity.release();
-}
-#else
-
-CFArrayRef
-loadCerts(const string& file)
-{
- UniqueRef<CFArrayRef> 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()));
- UniqueRef<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(const_cast<CFMutableArrayRef>(certs.get()), cert.get());
- first = false;
- }
- }
- else
- {
- UniqueRef<CFDataRef> data(readCertFile(file));
- UniqueRef<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(const_cast<CFMutableArrayRef>(certs.get()), cert.get());
- }
- 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, const std::string& keychainPath,
- const string& keychainPassword, const string& password, const PasswordPromptPtr& prompt,
- int retryMax)
-{
- UniqueRef<CFArrayRef> chain;
-#if defined(ICE_USE_SECURE_TRANSPORT_IOS)
- UniqueRef<CFDataRef> cert(readCertFile(file));
-
- UniqueRef<CFMutableDictionaryRef> settings(CFDictionaryCreateMutable(0,
- 1,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
- UniqueRef<CFArrayRef> items;
- OSStatus err;
- int count = 0;
- do
- {
- UniqueRef<CFStringRef> pass(toCFString(password.empty() && prompt ? prompt->getPassword() : password));
- CFDictionarySetValue(settings.get(), kSecImportExportPassphrase, pass.get());
- err = SecPKCS12Import(cert.get(), settings.get(), &items.get());
- ++count;
- }
- while(password.empty() && prompt && err == errSecAuthFailed && count < retryMax);
-
- if(err != noErr)
- {
- ostringstream os;
- os << "IceSSL: unable to import certificate from file " << file << " (error = " << err << ")";
- throw InitializationException(__FILE__, __LINE__, os.str());
- }
-
- for(int i = 0; i < CFArrayGetCount(items.get()); ++i)
- {
- CFDictionaryRef dict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(items.get(), i));
- SecIdentityRef identity = static_cast<SecIdentityRef>(
- const_cast<void*>(CFDictionaryGetValue(dict, kSecImportItemIdentity)));
- if(identity)
- {
- CFArrayRef certs = static_cast<CFArrayRef>(CFDictionaryGetValue(dict, kSecImportItemCertChain));
- chain.reset(CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, certs));
- CFArraySetValueAtIndex(const_cast<CFMutableArrayRef>(chain.get()), 0, identity);
- }
- }
-
- if(!chain)
- {
- 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())
- {
- chain.reset(loadKeychainItems(file, kSecItemTypeUnknown, keychain.get(), password, prompt, retryMax));
- }
- else
- {
- //
- // Load the certificate, don't load into the keychain as it
- // might already have been imported.
- //
- UniqueRef<CFArrayRef> items(loadKeychainItems(file, kSecItemTypeCertificate, 0, password, prompt, retryMax));
- SecCertificateRef cert =
- static_cast<SecCertificateRef>(const_cast<void*>(CFArrayGetValueAtIndex(items.get(), 0)));
- if(SecCertificateGetTypeID() != CFGetTypeID(cert))
- {
- ostringstream os;
- os << "IceSSL: couldn't find certificate in `" << file << "'";
- throw CertificateReadException(__FILE__, __LINE__, os.str());
- }
-
- //
- // Load the private key for the given certificate. This will
- // add the certificate/key to the keychain if they aren't
- // already present in the keychain.
- //
- UniqueRef<SecIdentityRef> identity(loadPrivateKey(keyFile, cert, keychain.get(), password, prompt, retryMax));
- chain.reset(CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, items.get()));
- CFArraySetValueAtIndex(const_cast<CFMutableArrayRef>(chain.get()), 0, identity.get());
- }
-#endif
- return chain.release();
-}
-
-SecCertificateRef
-IceSSL::loadCertificate(const string& file)
-{
- UniqueRef<SecCertificateRef> cert;
-#if defined(ICE_USE_SECURE_TRANSPORT_IOS)
- UniqueRef<CFArrayRef> certs(loadCerts(file));
- assert(CFArrayGetCount(certs.get()) > 0);
- cert.retain((SecCertificateRef)CFArrayGetValueAtIndex(certs.get(), 0));
-#else
- UniqueRef<CFArrayRef> items(loadKeychainItems(file, kSecItemTypeCertificate, 0, "", 0, 0));
- cert.retain((SecCertificateRef)CFArrayGetValueAtIndex(items.get(), 0));
-#endif
- return cert.release();
-}
-
-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));
- UniqueRef<CFArrayRef> certificateAuthorities(CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
- int count = CFArrayGetCount(items.get());
- for(CFIndex i = 0; i < count; ++i)
- {
- SecCertificateRef cert =
- static_cast<SecCertificateRef>(const_cast<void*>(CFArrayGetValueAtIndex(items.get(), i)));
- assert(SecCertificateGetTypeID() == CFGetTypeID(cert));
- if(isCA(cert))
- {
- CFArrayAppendValue(const_cast<CFMutableArrayRef>(certificateAuthorities.get()), cert);
- }
- }
- return certificateAuthorities.release();
-#endif
-}
-
-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:
- //
- // Label
- // Serial
- // Subject
- // SubjectKeyId
- //
- // A value must be enclosed in single or double quotes if it contains whitespace.
- //
- UniqueRef<CFMutableDictionaryRef> query(CFDictionaryCreateMutable(0,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
-
-#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(), 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)));
- string arg;
- if(field != "LABEL" && field != "SERIAL" && field != "SUBJECT" && field != "SUBJECTKEYID")
- {
- 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 + "'");
- }
-
- 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 == "SUBJECT" || field == "LABEL")
- {
- UniqueRef<CFStringRef> v(toCFString(arg));
- CFDictionarySetValue(query.get(), field == "LABEL" ? kSecAttrLabel : kSecMatchSubjectContains, v.get());
- valid = true;
- }
- else if(field == "SUBJECTKEYID" || field == "SERIAL")
- {
- vector<unsigned char> buffer;
- if(!parseBytes(arg, buffer))
- {
- throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: invalid value `" + value + "'");
- }
- UniqueRef<CFDataRef> v(CFDataCreate(kCFAllocatorDefault, &buffer[0], buffer.size()));
- CFDictionarySetValue(query.get(), field == "SUBJECTKEYID" ? kSecAttrSubjectKeyID : kSecAttrSerialNumber,
- v.get());
- valid = true;
- }
- }
-
- if(!valid)
- {
- throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: invalid value `" + value + "'");
- }
-
- UniqueRef<SecCertificateRef> cert;
- OSStatus err = SecItemCopyMatching(query.get(), (CFTypeRef*)&cert.get());
- if(err != noErr)
- {
- throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: find certificate `" + value + "' failed:\n" + errorToString(err));
- }
-
- //
- // Retrieve the certificate chain
- //
- UniqueRef<SecPolicyRef> policy(SecPolicyCreateSSL(true, 0));
- UniqueRef<SecTrustRef> trust;
- err = SecTrustCreateWithCertificates(reinterpret_cast<CFArrayRef>(cert.get()), policy.get(), &trust.get());
- if(err || !trust)
- {
- throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: error creating trust object" +
- (err ? ":\n" + errorToString(err) : ""));
- }
-
- SecTrustResultType trustResult;
- if((err = SecTrustEvaluate(trust.get(), &trustResult)))
- {
- throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: error evaluating trust:\n" + errorToString(err));
- }
-
- int chainLength = SecTrustGetCertificateCount(trust.get());
- UniqueRef<CFArrayRef> items(CFArrayCreateMutable(kCFAllocatorDefault, chainLength, &kCFTypeArrayCallBacks));
- for(int i = 0; i < chainLength; ++i)
- {
- CFArrayAppendValue(const_cast<CFMutableArrayRef>(items.get()), SecTrustGetCertificateAtIndex(trust.get(), i));
- }
-
- //
- // Replace the first certificate in the chain with the
- // identity.
- //
- UniqueRef<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.get());
- CFDictionarySetValue(query.get(), kSecReturnAttributes, kCFBooleanTrue);
- UniqueRef<CFDictionaryRef> attributes;
- err = SecItemCopyMatching(query.get(), reinterpret_cast<CFTypeRef*>(&attributes.get()));
- 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());
- }
-
- // 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.get(), kSecAttrLabel));
- CFDictionarySetValue(query.get(), kSecReturnRef, kCFBooleanTrue);
- err = SecItemCopyMatching(query.get(), (CFTypeRef*)&identity.get());
- if(err == noErr)
- {
- UniqueRef<SecCertificateRef> cert2;
- if((err = SecIdentityCopyCertificate(identity.get(), &cert2.get())) == noErr)
- {
- err = CFEqual(cert2.get(), cert.get()) ? noErr : errSecItemNotFound;
- }
- }
-#else
- err = SecIdentityCreateWithCertificate(keychain.get(), cert.get(), &identity.get());
-#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(const_cast<CFMutableArrayRef>(items.get()), 0, identity.get());
- return items.release();
-}
-
-#elif defined(ICE_USE_SCHANNEL)
-
-namespace
-{
-
-void
-addMatchingCertificates(HCERTSTORE source, HCERTSTORE target, DWORD findType, const void* findParam)
-{
- PCCERT_CONTEXT next = 0;
- do
- {
- if((next = CertFindCertificateInStore(source, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
- findType, findParam, next)))
- {
- if(!CertAddCertificateContextToStore(target, next, CERT_STORE_ADD_ALWAYS, 0))
- {
- throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: error adding certificate to store:\n" + IceUtilInternal::lastErrorToString());
- }
- }
- }
- while(next);
-}
-
-}
-
-vector<PCCERT_CONTEXT>
-IceSSL::findCertificates(const string& location, const string& name, const string& value, vector<HCERTSTORE>& stores)
-{
- DWORD storeLoc;
- if(location == "CurrentUser")
- {
- storeLoc = CERT_SYSTEM_STORE_CURRENT_USER;
- }
- else
- {
- storeLoc = CERT_SYSTEM_STORE_LOCAL_MACHINE;
- }
-
- HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, storeLoc, Ice::stringToWstring(name).c_str());
- if(!store)
- {
- throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: failed to open certificate store `" + name +
- "':\n" + IceUtilInternal::lastErrorToString());
- }
-
- //
- // Start with all of the certificates in the collection and filter as necessary.
- //
- // - If the value is "*", return all certificates.
- // - Otherwise, search using key:value pairs. The following keys are supported:
- //
- // Issuer
- // IssuerDN
- // Serial
- // Subject
- // SubjectDN
- // SubjectKeyId
- // Thumbprint
- //
- // A value must be enclosed in single or double quotes if it contains whitespace.
- //
- HCERTSTORE tmpStore = 0;
- try
- {
- 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 != "SUBJECT" && field != "SUBJECTDN" && field != "ISSUER" && field != "ISSUERDN" &&
- field != "THUMBPRINT" && field != "SUBJECTKEYID" && field != "SERIAL")
- {
- 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;
- }
- }
-
- tmpStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 0, 0);
- if(!tmpStore)
- {
- throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: error adding certificate to store:\n" + IceUtilInternal::lastErrorToString());
- }
-
- if(field == "SUBJECT" || field == "ISSUER")
- {
- const wstring argW = Ice::stringToWstring(arg);
- DWORD findType = field == "SUBJECT" ? CERT_FIND_SUBJECT_STR : CERT_FIND_ISSUER_STR;
- addMatchingCertificates(store, tmpStore, findType, argW.c_str());
- }
- else if(field == "SUBJECTDN" || field == "ISSUERDN")
- {
- const wstring argW = Ice::stringToWstring(arg);
- DWORD flags[] = {
- CERT_OID_NAME_STR,
- CERT_OID_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
- CERT_OID_NAME_STR | CERT_NAME_STR_FORCE_UTF8_DIR_STR_FLAG,
- CERT_OID_NAME_STR | CERT_NAME_STR_FORCE_UTF8_DIR_STR_FLAG | CERT_NAME_STR_REVERSE_FLAG
- };
- for(size_t i = 0; i < sizeof(flags) / sizeof(DWORD); ++i)
- {
- DWORD length = 0;
- if(!CertStrToNameW(X509_ASN_ENCODING, argW.c_str(), flags[i], 0, 0, &length, 0))
- {
- throw PluginInitializationException(
- __FILE__, __LINE__,
- "IceSSL: invalid value `" + value + "' for `IceSSL.FindCert' property:\n" +
- IceUtilInternal::lastErrorToString());
- }
-
- vector<BYTE> buffer(length);
- if(!CertStrToNameW(X509_ASN_ENCODING, argW.c_str(), flags[i], 0, &buffer[0], &length, 0))
- {
- throw PluginInitializationException(
- __FILE__, __LINE__,
- "IceSSL: invalid value `" + value + "' for `IceSSL.FindCert' property:\n" +
- IceUtilInternal::lastErrorToString());
- }
-
- CERT_NAME_BLOB name = { length, &buffer[0] };
-
- DWORD findType = field == "SUBJECTDN" ? CERT_FIND_SUBJECT_NAME : CERT_FIND_ISSUER_NAME;
- addMatchingCertificates(store, tmpStore, findType, &name);
- }
- }
- else if(field == "THUMBPRINT" || field == "SUBJECTKEYID")
- {
- vector<BYTE> buffer;
- if(!parseBytes(arg, buffer))
- {
- throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: invalid `IceSSL.FindCert' property: can't decode the value");
- }
-
- CRYPT_HASH_BLOB hash = { static_cast<DWORD>(buffer.size()), &buffer[0] };
- DWORD findType = field == "THUMBPRINT" ? CERT_FIND_HASH : CERT_FIND_KEY_IDENTIFIER;
- addMatchingCertificates(store, tmpStore, findType, &hash);
- }
- else if(field == "SERIAL")
- {
- vector<BYTE> buffer;
- if(!parseBytes(arg, buffer))
- {
- throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: invalid value `" + value + "' for `IceSSL.FindCert' property");
- }
-
- CRYPT_INTEGER_BLOB serial = { static_cast<DWORD>(buffer.size()), &buffer[0] };
- PCCERT_CONTEXT next = 0;
- do
- {
- if((next = CertFindCertificateInStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
- CERT_FIND_ANY, 0, next)))
- {
- if(CertCompareIntegerBlob(&serial, &next->pCertInfo->SerialNumber))
- {
- if(!CertAddCertificateContextToStore(tmpStore, next, CERT_STORE_ADD_ALWAYS, 0))
- {
- throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: error adding certificate to store:\n" +
- IceUtilInternal::lastErrorToString());
- }
- }
- }
- }
- while(next);
- }
- CertCloseStore(store, 0);
- store = tmpStore;
- }
- }
- }
- catch(...)
- {
- if(store && store != tmpStore)
- {
- CertCloseStore(store, 0);
- }
-
- if(tmpStore)
- {
- CertCloseStore(tmpStore, 0);
- tmpStore = 0;
- }
- throw;
- }
-
- vector<PCCERT_CONTEXT> certs;
- if(store)
- {
- PCCERT_CONTEXT next = 0;
- do
- {
- if((next = CertFindCertificateInStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, 0,
- next)))
- {
- certs.push_back(next);
- }
- }
- while(next);
- stores.push_back(store);
- }
- return certs;
-}
-#elif defined (ICE_OS_UWP)
-
-namespace
-{
-
-//
-// Find a certificate in the Application Personal certificate store
-// with the given friendly name. Returns the matching certificate or
-// nullptr if none is found.
-//
-Certificates::Certificate^
-findPersonalCertificate(String^ friendlyName)
-{
- CertificateQuery^ query = ref new CertificateQuery();
- query->IncludeDuplicates = true;
- query->IncludeExpiredCertificates = true;
- query->FriendlyName = friendlyName;
- query->StoreName = StandardCertificateStoreNames::Personal;
-
- try
- {
- auto certificates = IceInternal::runSync(CertificateStores::FindAllAsync(query));
- return certificates->Size > 0 ? certificates->GetAt(0) : nullptr;
- }
- catch(Platform::Exception^ ex)
- {
- throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: certificate error:\n" + wstringToString(ex->Message->Data()));
- }
-}
-
-//
-// Import a certificate in the Application Personal certificate store
-// with the given friendly name. Returns true if there was a password
-// error and false otherwise. If the import fails because a different
-// error PluginInitializationException exception is throw.
-//
-bool
-importPfxData(String^ friendlyName, String^ data, String^ password)
-{
- try
- {
- IceInternal::runSync(CertificateEnrollmentManager::ImportPfxDataAsync(
- data,
- password,
- ExportOption::NotExportable,
- KeyProtectionLevel::NoConsent,
- InstallOptions::None,
- friendlyName));
- return false; // The import succcess
- }
- catch(Platform::Exception^ ex)
- {
- if(HRESULT_CODE(ex->HResult) == ERROR_DECRYPTION_FAILED)
- {
- return true; // Password error
- }
- else
- {
- throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: certificate error:\n" + wstringToString(ex->Message->Data()));
- }
- }
-}
-
-}
-
-Certificates::Certificate^
-IceSSL::importPersonalCertificate(const string& file, function<string ()> password, bool passwordPrompt,
- int passwordRetryMax)
-{
- auto uri = ref new Uri(ref new String(stringToWstring(file).c_str()));
- try
- {
- auto file = IceInternal::runSync(StorageFile::GetFileFromApplicationUriAsync(uri));
- auto buffer = IceInternal::runSync(FileIO::ReadBufferAsync(file));
-
- //
- // Create a hash of the certificate to use as a friendly name, this will allow us
- // to uniquely identify the certificate in the store.
- //
- auto hasher = HashAlgorithmProvider::OpenAlgorithm(HashAlgorithmNames::Sha1);
- auto hash = hasher->CreateHash();
-
- hash->Append(buffer);
- String^ friendlyName = CryptographicBuffer::EncodeToBase64String(hash->GetValueAndReset());
-
- //
- // If the certificate is already in the store we avoid importing it.
- //
- Certificates::Certificate^ cert = findPersonalCertificate(friendlyName);
- if(cert)
- {
- return cert;
- }
- else
- {
- String^ data = CryptographicBuffer::EncodeToBase64String(buffer);
- int count = 0;
- bool passwordErr = false;
- do
- {
- passwordErr = importPfxData(friendlyName, data,
- ref new String(stringToWstring(password()).c_str()));
- }
- while(passwordPrompt && passwordErr && ++count < passwordRetryMax);
- if(passwordErr)
- {
- throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: error decoding certificate");
- }
- return findPersonalCertificate(friendlyName);
- }
- }
- catch(Platform::Exception^ ex)
- {
- if(HRESULT_CODE(ex->HResult) == ERROR_FILE_NOT_FOUND)
- {
- throw PluginInitializationException(__FILE__, __LINE__, "certificate file not found:\n" + file);
- }
- else
- {
- throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: certificate error:\n" + wstringToString(ex->Message->Data()));
- }
- }
-}
-
-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;
- query->IncludeExpiredCertificates = 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()));
- }
- }
- }
-
- try
- {
- return IceInternal::runSync(CertificateStores::FindAllAsync(query));
- }
- catch(Platform::Exception^ ex)
- {
- throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: certificate error:\n" + wstringToString(ex->Message->Data()));
- }
-}
-#endif
-
void
IceSSL::readFile(const string& file, vector<char>& buffer)
{
diff --git a/cpp/src/IceSSL/Util.h b/cpp/src/IceSSL/Util.h
index c1bf6138819..ac9697a990e 100644
--- a/cpp/src/IceSSL/Util.h
+++ b/cpp/src/IceSSL/Util.h
@@ -13,29 +13,38 @@
#include <IceUtil/Mutex.h>
#include <IceUtil/Shared.h>
#include <IceUtil/Handle.h>
-
-#include <Ice/UniqueRef.h>
-
#include <IceSSL/Plugin.h>
-#if defined(ICE_USE_OPENSSL)
-# include <openssl/ssl.h>
-# include <list>
-#elif defined(ICE_USE_SECURE_TRANSPORT)
-# include <Security/Security.h>
+#if defined(__APPLE__)
# include <CoreFoundation/CoreFoundation.h>
-#elif defined(ICE_USE_SCHANNEL)
-# include <wincrypt.h>
+# if TARGET_OS_IPHONE != 0
+# define ICE_USE_SECURE_TRANSPORT_IOS 1
+# else
+# define ICE_USE_SECURE_TRANSPORT_MACOS 1
+# endif
#endif
namespace IceSSL
{
+#if defined(__APPLE__)
+//
+// Helper functions to use by Secure Transport.
+//
+std::string fromCFString(CFStringRef);
+
+inline CFStringRef
+toCFString(const std::string& s)
+{
+ return CFStringCreateWithCString(ICE_NULLPTR, s.c_str(), kCFStringEncodingUTF8);
+}
+#endif
+
#ifdef ICE_CPP11_MAPPING
//
// Adapts the C++11 functions to C++98-like callbacks
//
-class CertificateVerifier
+class ICESSL_API CertificateVerifier
{
public:
@@ -48,7 +57,7 @@ private:
};
using CertificateVerifierPtr = std::shared_ptr<CertificateVerifier>;
-class PasswordPrompt
+class ICESSL_API PasswordPrompt
{
public:
@@ -77,92 +86,18 @@ const int AltNameURL = 6;
const int AltNAmeIP = 7;
//const AltNameObjectIdentifier = 8;
-#ifdef ICE_USE_OPENSSL
-
-# ifndef OPENSSL_NO_DH
-class DHParams : public IceUtil::Shared, public IceUtil::Mutex
-{
-public:
-
- DHParams();
- ~DHParams();
-
- bool add(int, const std::string&);
- DH* get(int);
-
-private:
-
- typedef std::pair<int, DH*> KeyParamPair;
- typedef std::list<KeyParamPair> ParamList;
- ParamList _params;
-
- DH* _dh512;
- DH* _dh1024;
- DH* _dh2048;
- DH* _dh4096;
-};
-typedef IceUtil::Handle<DHParams> DHParamsPtr;
-# endif
-
-//
-// Accumulate the OpenSSL error stack into a string.
-//
-std::string getSslErrors(bool);
-
-#elif defined(ICE_USE_SECURE_TRANSPORT)
-//
-// Helper functions to use by Secure Transport.
-//
-
-std::string fromCFString(CFStringRef);
-
-inline CFStringRef
-toCFString(const std::string& s)
-{
- return CFStringCreateWithCString(ICE_NULLPTR, s.c_str(), kCFStringEncodingUTF8);
-}
-
-std::string errorToString(CFErrorRef);
-std::string errorToString(OSStatus);
-
-# if defined(ICE_USE_SECURE_TRANSPORT_MACOS)
-//
-// Retrieve a certificate property
-//
-CFDictionaryRef getCertificateProperty(SecCertificateRef, CFTypeRef);
-# endif
-
-//
-// Read certificate from a file.
-//
-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&);
-CFArrayRef findCertificateChain(const std::string&, const std::string&, const std::string&);
-
-#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_UWP)
-Windows::Security::Cryptography::Certificates::Certificate^
-importPersonalCertificate(const std::string&, std::function<std::string()>, bool, int);
-
-Windows::Foundation::Collections::IVectorView<Windows::Security::Cryptography::Certificates::Certificate^>^
-findCertificates(const std::string&, const std::string&);
-#endif
-
//
// Read a file into memory buffer.
//
-void readFile(const std::string&, std::vector<char>&);
+ICESSL_API void readFile(const std::string&, std::vector<char>&);
//
// Determine if a file or directory exists, with an optional default
// directory.
//
-bool checkPath(const std::string&, const std::string&, bool, std::string&);
+ICESSL_API bool checkPath(const std::string&, const std::string&, bool, std::string&);
+
+ICESSL_API bool parseBytes(const std::string&, std::vector<unsigned char>&);
}
diff --git a/cpp/src/IceSSL/msbuild/icessl++11/icessl++11.vcxproj b/cpp/src/IceSSL/msbuild/icessl++11/icessl++11.vcxproj
index acd8cd82542..78eda48ca78 100644
--- a/cpp/src/IceSSL/msbuild/icessl++11/icessl++11.vcxproj
+++ b/cpp/src/IceSSL/msbuild/icessl++11/icessl++11.vcxproj
@@ -110,13 +110,15 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\AcceptorI.cpp" />
- <ClCompile Include="..\..\Certificate.cpp" />
+ <ClCompile Include="..\..\CertificateI.cpp" />
<ClCompile Include="..\..\ConnectorI.cpp" />
<ClCompile Include="..\..\EndpointI.cpp" />
<ClCompile Include="..\..\Instance.cpp" />
<ClCompile Include="..\..\PluginI.cpp" />
<ClCompile Include="..\..\RFC2253.cpp" />
+ <ClCompile Include="..\..\SChannelCertificateI.cpp" />
<ClCompile Include="..\..\SChannelEngine.cpp" />
+ <ClCompile Include="..\..\SChannelPluginI.cpp" />
<ClCompile Include="..\..\SChannelTransceiverI.cpp" />
<ClCompile Include="..\..\SSLEngine.cpp" />
<ClCompile Include="..\..\TrustManager.cpp" />
@@ -213,6 +215,8 @@
<ClInclude Include="..\..\InstanceF.h" />
<ClInclude Include="..\..\PluginI.h" />
<ClInclude Include="..\..\RFC2253.h" />
+ <ClInclude Include="..\..\SChannelEngine.h" />
+ <ClInclude Include="..\..\SChannelEngineF.h" />
<ClInclude Include="..\..\SChannelTransceiverI.h" />
<ClInclude Include="..\..\SSLEngine.h" />
<ClInclude Include="..\..\SSLEngineF.h" />
diff --git a/cpp/src/IceSSL/msbuild/icessl++11/icessl++11.vcxproj.filters b/cpp/src/IceSSL/msbuild/icessl++11/icessl++11.vcxproj.filters
index b57a4914467..c988a7c0d72 100644
--- a/cpp/src/IceSSL/msbuild/icessl++11/icessl++11.vcxproj.filters
+++ b/cpp/src/IceSSL/msbuild/icessl++11/icessl++11.vcxproj.filters
@@ -128,6 +128,12 @@
<ClCompile Include="x64\Release\EndpointInfo.cpp">
<Filter>Source Files\x64\Release</Filter>
</ClCompile>
+ <ClCompile Include="..\..\SChannelCertificate.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\SChannelPluginI.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\Util.h">
@@ -202,5 +208,11 @@
<ClInclude Include="..\..\..\..\include\generated\cpp11\x64\Release\IceSSL\EndpointInfo.h">
<Filter>Header Files\x64\Release</Filter>
</ClInclude>
+ <ClInclude Include="..\..\SChannelEngine.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\SChannelEngineF.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/cpp/src/IceSSL/msbuild/icessl/icessl.vcxproj b/cpp/src/IceSSL/msbuild/icessl/icessl.vcxproj
index 4400a310637..837279671e5 100644
--- a/cpp/src/IceSSL/msbuild/icessl/icessl.vcxproj
+++ b/cpp/src/IceSSL/msbuild/icessl/icessl.vcxproj
@@ -115,13 +115,15 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\AcceptorI.cpp" />
- <ClCompile Include="..\..\Certificate.cpp" />
+ <ClCompile Include="..\..\CertificateI.cpp" />
<ClCompile Include="..\..\ConnectorI.cpp" />
<ClCompile Include="..\..\EndpointI.cpp" />
<ClCompile Include="..\..\Instance.cpp" />
<ClCompile Include="..\..\PluginI.cpp" />
<ClCompile Include="..\..\RFC2253.cpp" />
+ <ClCompile Include="..\..\SChannelCertificateI.cpp" />
<ClCompile Include="..\..\SChannelEngine.cpp" />
+ <ClCompile Include="..\..\SChannelPluginI.cpp" />
<ClCompile Include="..\..\SChannelTransceiverI.cpp" />
<ClCompile Include="..\..\SSLEngine.cpp" />
<ClCompile Include="..\..\TrustManager.cpp" />
@@ -212,12 +214,14 @@
<ClInclude Include="..\..\..\..\include\IceSSL\IceSSL.h" />
<ClInclude Include="..\..\..\..\include\IceSSL\Plugin.h" />
<ClInclude Include="..\..\AcceptorI.h" />
+ <ClInclude Include="..\..\CertificateI.h" />
<ClInclude Include="..\..\ConnectorI.h" />
<ClInclude Include="..\..\EndpointI.h" />
<ClInclude Include="..\..\Instance.h" />
<ClInclude Include="..\..\InstanceF.h" />
<ClInclude Include="..\..\PluginI.h" />
<ClInclude Include="..\..\RFC2253.h" />
+ <ClInclude Include="..\..\SChannelEngine.h" />
<ClInclude Include="..\..\SChannelTransceiverI.h" />
<ClInclude Include="..\..\SSLEngine.h" />
<ClInclude Include="..\..\SSLEngineF.h" />
diff --git a/cpp/src/IceSSL/msbuild/icessl/icessl.vcxproj.filters b/cpp/src/IceSSL/msbuild/icessl/icessl.vcxproj.filters
index 1365285ff1d..c82244834e8 100644
--- a/cpp/src/IceSSL/msbuild/icessl/icessl.vcxproj.filters
+++ b/cpp/src/IceSSL/msbuild/icessl/icessl.vcxproj.filters
@@ -128,6 +128,12 @@
<ClCompile Include="x64\Release\EndpointInfo.cpp">
<Filter>Source Files\x64\Release</Filter>
</ClCompile>
+ <ClCompile Include="..\..\SChannelCertificate.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\SChannelPluginI.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\Util.h">
@@ -202,5 +208,11 @@
<ClInclude Include="..\..\..\..\include\generated\cpp98\x64\Release\IceSSL\EndpointInfo.h">
<Filter>Header Files\x64\Release</Filter>
</ClInclude>
+ <ClInclude Include="..\..\SChannelEngine.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\Certificate.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/cpp/src/IceSSL/msbuild/icesslopenssl++11/icesslopenssl++11.vcxproj b/cpp/src/IceSSL/msbuild/icesslopenssl++11/icesslopenssl++11.vcxproj
new file mode 100644
index 00000000000..4b431b29580
--- /dev/null
+++ b/cpp/src/IceSSL/msbuild/icesslopenssl++11/icesslopenssl++11.vcxproj
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{D0DC2305-37FE-4D03-BE05-AC8912678DC8}</ProjectGuid>
+ <IceBuilderInstallDir>$([MSBuild]::GetRegistryValue('HKEY_CURRENT_USER\SOFTWARE\ZeroC\IceBuilder', 'InstallDir.$(VisualStudioVersion)'))</IceBuilderInstallDir>
+ <IceBuilderCppProps>$(IceBuilderInstallDir)\Resources\IceBuilder.Cpp.props</IceBuilderCppProps>
+ <IceBuilderCppTargets>$(IceBuilderInstallDir)\Resources\IceBuilder.Cpp.targets</IceBuilderCppTargets>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <Import Project="$(MSBuildThisFileDirectory)\..\..\..\..\msbuild\ice.cpp11.props" />
+ <Import Project="$(IceBuilderCppProps)" Condition="Exists('$(IceBuilderCppProps)')" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="IceBuilder">
+ <IceBuilderHeaderOutputDir>$(Ice_SrcRootDir)\include\generated\cpp11\$(Platform)\$(Configuration)\IceSSL\</IceBuilderHeaderOutputDir>
+ <IceBuilderBaseDirectoryForGeneratedInclude>IceSSL</IceBuilderBaseDirectoryForGeneratedInclude>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>ICESSL_OPENSSL_API_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>ICESSL_OPENSSL_API_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>ICESSL_OPENSSL_API_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>ICESSL_OPENSSL_API_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\..\IceSSLOpenSSL.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\OpenSSLCertificateI.cpp" />
+ <ClCompile Include="..\..\OpenSSLEngine.cpp" />
+ <ClCompile Include="..\..\OpenSSLPluginI.cpp" />
+ <ClCompile Include="..\..\OpenSSLTransceiverI.cpp" />
+ <ClCompile Include="..\..\OpenSSLUtil.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\OpenSSLEngine.h" />
+ <ClInclude Include="..\..\OpenSSLEngineF.h" />
+ <ClInclude Include="..\..\OpenSSLTransceiverI.h" />
+ <ClInclude Include="..\..\OpenSSLUtil.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <Import Project="$(IceBuilderCppTargets)" Condition="Exists('$(IceBuilderCppTargets)')" />
+ <ImportGroup Label="ExtensionTargets">
+ <Import Project="..\..\..\..\msbuild\packages\openssl.v140.1.0.2.1\build\native\openssl.v140.targets" Condition="Exists('..\..\..\..\msbuild\packages\openssl.v140.1.0.2.1\build\native\openssl.v140.targets')" />
+ </ImportGroup>
+ <Import Project="$(MSBuildThisFileDirectory)..\..\..\..\..\config\ice.sign.targets" />
+ <Target Name="EnsureIceBuilderImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project requires the Ice Builder for Visual Studio extension. Use "Tools &amp;gt; Extensions and Updates" to install it. For more information, see https://visualstudiogallery.msdn.microsoft.com/1a64e701-63f2-4740-8004-290e6c682ce0.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(IceBuilderCppProps)')" Text="$(ErrorText)" />
+ </Target>
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('..\..\..\..\msbuild\packages\openssl.v140.1.0.2.1\build\native\openssl.v140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\msbuild\packages\openssl.v140.1.0.2.1\build\native\openssl.v140.targets'))" />
+ </Target>
+</Project> \ No newline at end of file
diff --git a/cpp/src/IceSSL/msbuild/icesslopenssl++11/icesslopenssl++11.vcxproj.filters b/cpp/src/IceSSL/msbuild/icesslopenssl++11/icesslopenssl++11.vcxproj.filters
new file mode 100644
index 00000000000..aa9d1871ef4
--- /dev/null
+++ b/cpp/src/IceSSL/msbuild/icesslopenssl++11/icesslopenssl++11.vcxproj.filters
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{4d9f616e-1934-41a2-8ba4-83b5113d1ee9}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{dc46ba85-888a-44c6-a892-02ca81802a4f}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{7f20c422-9df1-492a-8b6f-5dd7f3188a7a}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Slice Files">
+ <UniqueIdentifier>{9007c33c-0c7e-42bb-8400-baae022a4a6d}</UniqueIdentifier>
+ <Extensions>ice</Extensions>
+ </Filter>
+ <Filter Include="Source Files\Win32">
+ <UniqueIdentifier>{e9fe80ae-1aff-4267-84d9-1f75b1b573a6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Win32\Debug">
+ <UniqueIdentifier>{0f9d0820-dd66-4cea-a839-576ef894e6da}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Win32">
+ <UniqueIdentifier>{85447365-08ad-4445-93c9-5b2d697c26d3}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Win32\Debug">
+ <UniqueIdentifier>{3970e819-06e0-4ff0-90ae-36e4d3e2599e}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\x64">
+ <UniqueIdentifier>{e29283e2-0bcc-4737-ba65-4d7818277667}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\x64\Debug">
+ <UniqueIdentifier>{37734e94-4269-46ce-a869-b343baada79c}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\x64">
+ <UniqueIdentifier>{799ccbb8-b61f-49d0-ab9b-c35577f4fc90}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\x64\Debug">
+ <UniqueIdentifier>{919084ad-57a8-4656-8e9c-7e297ade0cba}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Win32\Release">
+ <UniqueIdentifier>{a9faf6cb-dac5-4226-b78f-e8d540941d95}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Win32\Release">
+ <UniqueIdentifier>{5b553fdf-f103-40de-901e-e625bbac9df6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\x64\Release">
+ <UniqueIdentifier>{4a704c57-97d4-44e6-a7fe-54071c38a0d1}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\x64\Release">
+ <UniqueIdentifier>{d5c1d6b6-0241-4fb2-8d58-451aee18ef20}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\..\IceSSL.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\OpenSSLCertificateI.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\OpenSSLEngine.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\OpenSSLPluginI.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\OpenSSLTransceiverI.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\OpenSSLUtil.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\OpenSSLEngine.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\OpenSSLEngineF.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\OpenSSLTransceiverI.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\OpenSSLUtil.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/cpp/src/IceSSL/msbuild/icesslopenssl++11/packages.config b/cpp/src/IceSSL/msbuild/icesslopenssl++11/packages.config
new file mode 100644
index 00000000000..1e1ce645625
--- /dev/null
+++ b/cpp/src/IceSSL/msbuild/icesslopenssl++11/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="openssl.v140" version="1.0.2.1" targetFramework="native" />
+</packages> \ No newline at end of file
diff --git a/cpp/src/IceSSL/msbuild/icesslopenssl/icesslopenssl.vcxproj b/cpp/src/IceSSL/msbuild/icesslopenssl/icesslopenssl.vcxproj
new file mode 100644
index 00000000000..a5767a3a18c
--- /dev/null
+++ b/cpp/src/IceSSL/msbuild/icesslopenssl/icesslopenssl.vcxproj
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{0D08F6B8-39C0-413B-84CE-D73230BCC740}</ProjectGuid>
+ <IceBuilderInstallDir>$([MSBuild]::GetRegistryValue('HKEY_CURRENT_USER\SOFTWARE\ZeroC\IceBuilder', 'InstallDir.$(VisualStudioVersion)'))</IceBuilderInstallDir>
+ <IceBuilderCppProps>$(IceBuilderInstallDir)\Resources\IceBuilder.Cpp.props</IceBuilderCppProps>
+ <IceBuilderCppTargets>$(IceBuilderInstallDir)\Resources\IceBuilder.Cpp.targets</IceBuilderCppTargets>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <Import Project="$(MSBuildThisFileDirectory)\..\..\..\..\msbuild\ice.cpp98.props" />
+ <Import Project="$(IceBuilderCppProps)" Condition="Exists('$(IceBuilderCppProps)')" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <PropertyGroup Label="IceBuilder">
+ <IceBuilderHeaderOutputDir>$(Ice_SrcRootDir)\include\generated\cpp98\$(Platform)\$(Configuration)\IceSSL\</IceBuilderHeaderOutputDir>
+ <IceBuilderBaseDirectoryForGeneratedInclude>IceSSL</IceBuilderBaseDirectoryForGeneratedInclude>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>ICESSL_OPENSSL_API_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>ICESSL_OPENSSL_API_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>ICESSL_OPENSSL_API_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>ICESSL_OPENSSL_API_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\..\IceSSLOpenSSL.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\OpenSSLCertificateI.cpp" />
+ <ClCompile Include="..\..\OpenSSLEngine.cpp" />
+ <ClCompile Include="..\..\OpenSSLPluginI.cpp" />
+ <ClCompile Include="..\..\OpenSSLTransceiverI.cpp" />
+ <ClCompile Include="..\..\OpenSSLUtil.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\OpenSSLEngine.h" />
+ <ClInclude Include="..\..\OpenSSLEngineF.h" />
+ <ClInclude Include="..\..\OpenSSLTransceiverI.h" />
+ <ClInclude Include="..\..\OpenSSLUtil.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <Import Project="$(IceBuilderCppTargets)" Condition="Exists('$(IceBuilderCppTargets)')" />
+ <ImportGroup Label="ExtensionTargets">
+ <Import Project="..\..\..\..\msbuild\packages\openssl.v140.1.0.2.1\build\native\openssl.v140.targets" Condition="Exists('..\..\..\..\msbuild\packages\openssl.v140.1.0.2.1\build\native\openssl.v140.targets')" />
+ </ImportGroup>
+ <Import Project="$(MSBuildThisFileDirectory)..\..\..\..\..\config\ice.sign.targets" />
+ <Target Name="EnsureIceBuilderImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project requires the Ice Builder for Visual Studio extension. Use "Tools &amp;gt; Extensions and Updates" to install it. For more information, see https://visualstudiogallery.msdn.microsoft.com/1a64e701-63f2-4740-8004-290e6c682ce0.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(IceBuilderCppProps)')" Text="$(ErrorText)" />
+ </Target>
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('..\..\..\..\msbuild\packages\openssl.v140.1.0.2.1\build\native\openssl.v140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\msbuild\packages\openssl.v140.1.0.2.1\build\native\openssl.v140.targets'))" />
+ </Target>
+</Project> \ No newline at end of file
diff --git a/cpp/src/IceSSL/msbuild/icesslopenssl/icesslopenssl.vcxproj.filters b/cpp/src/IceSSL/msbuild/icesslopenssl/icesslopenssl.vcxproj.filters
new file mode 100644
index 00000000000..ada1ef4134a
--- /dev/null
+++ b/cpp/src/IceSSL/msbuild/icesslopenssl/icesslopenssl.vcxproj.filters
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Slice Files">
+ <UniqueIdentifier>{0255b63a-660b-4a1c-805f-0abe632c5677}</UniqueIdentifier>
+ <Extensions>ice</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{956d2580-1d49-4b49-a059-988288782db2}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{e83d242d-b1ea-4c9c-b23c-e89105597587}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{448e5844-aa20-4e5e-8876-57eb2a5cbe2f}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="Source Files\Win32">
+ <UniqueIdentifier>{8fbefc16-ee09-44ab-b2b4-d752bd5377ea}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Win32\Debug">
+ <UniqueIdentifier>{9ad49193-c783-4a96-a912-221addf43f04}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Win32">
+ <UniqueIdentifier>{0feba132-cf9d-4d8f-b4d6-20001d1d8ae6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Win32\Debug">
+ <UniqueIdentifier>{c0691be0-ad4d-45b0-9b58-ff51634b7abe}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\x64">
+ <UniqueIdentifier>{c9a4873d-7104-447e-a4c6-393349a8ff39}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\x64\Debug">
+ <UniqueIdentifier>{e34f5387-2c17-4311-b257-1344b9008865}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\x64">
+ <UniqueIdentifier>{c662649c-a902-4c7e-8616-ea54f436eb45}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\x64\Debug">
+ <UniqueIdentifier>{9ff83beb-868b-4a94-9b0e-3afc3bab37d6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Win32\Release">
+ <UniqueIdentifier>{2a739cdd-800d-4fb5-b656-2e647b26bd3f}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Win32\Release">
+ <UniqueIdentifier>{bf287f75-264e-406d-a75e-b19d15f4a387}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\x64\Release">
+ <UniqueIdentifier>{2d055007-bfcb-4301-8c18-3c394e9d2b71}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\x64\Release">
+ <UniqueIdentifier>{d89224e9-0392-47b3-9a1a-f4b0b186ab08}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\..\IceSSL.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\OpenSSLCertificate.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\OpenSSLEngine.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\OpenSSLPlugin.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\OpenSSLTransceiverI.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\OpenSSLUtil.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\OpenSSLUtil.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\OpenSSLTransceiverI.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\OpenSSLEngineF.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\OpenSSLEngine.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/cpp/src/IceSSL/msbuild/icesslopenssl/packages.config b/cpp/src/IceSSL/msbuild/icesslopenssl/packages.config
new file mode 100644
index 00000000000..1e1ce645625
--- /dev/null
+++ b/cpp/src/IceSSL/msbuild/icesslopenssl/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="openssl.v140" version="1.0.2.1" targetFramework="native" />
+</packages> \ No newline at end of file
diff --git a/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj b/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj
index a9062dbd402..d40f69335ba 100644
--- a/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj
+++ b/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj
@@ -138,7 +138,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\AcceptorI.cpp" />
- <ClCompile Include="..\..\Certificate.cpp" />
+ <ClCompile Include="..\..\CertificateI.cpp" />
<ClCompile Include="..\..\ConnectorI.cpp" />
<ClCompile Include="..\..\EndpointI.cpp" />
<ClCompile Include="..\..\Instance.cpp" />
@@ -147,7 +147,9 @@
<ClCompile Include="..\..\SSLEngine.cpp" />
<ClCompile Include="..\..\TrustManager.cpp" />
<ClCompile Include="..\..\Util.cpp" />
+ <ClCompile Include="..\..\UWPCertificateI.cpp" />
<ClCompile Include="..\..\UWPEngine.cpp" />
+ <ClCompile Include="..\..\UWPPluginI.cpp" />
<ClCompile Include="..\..\UWPTransceiverI.cpp" />
<ClCompile Include="ARM\Debug\ConnectionInfo.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
@@ -319,6 +321,9 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</ExcludedFromBuild>
</ClInclude>
+ <ClInclude Include="..\..\UWPEngine.h" />
+ <ClInclude Include="..\..\UWPEngineF.h" />
+ <ClInclude Include="..\..\UWPTransceiverI.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 2540bd3e82d..88967825a06 100644
--- a/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj.filters
+++ b/cpp/src/IceSSL/msbuild/icessluwp++11/icessluwp++11.vcxproj.filters
@@ -147,6 +147,12 @@
<ClCompile Include="..\..\RFC2253.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\UWPCertificate.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\UWPPluginI.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\..\include\generated\uwp\Win32\Debug\IceSSL\ConnectionInfo.h">
@@ -185,5 +191,14 @@
<ClInclude Include="..\..\..\..\include\generated\uwp\x64\Release\IceSSL\EndpointInfo.h">
<Filter>Header Files\x64\Release</Filter>
</ClInclude>
+ <ClInclude Include="..\..\UWPEngine.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\UWPEngineF.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\UWPTransceiverI.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/cpp/test/IceSSL/configuration/AllTests.cpp b/cpp/test/IceSSL/configuration/AllTests.cpp
index ec063c94c16..ad8338888e9 100644
--- a/cpp/test/IceSSL/configuration/AllTests.cpp
+++ b/cpp/test/IceSSL/configuration/AllTests.cpp
@@ -8,16 +8,17 @@
// **********************************************************************
#include <Ice/Ice.h>
-#include <IceSSL/Plugin.h>
+#include <IceSSL/IceSSL.h>
#include <TestCommon.h>
#include <Test.h>
#include <fstream>
#include <algorithm>
+#include <Ice/UniqueRef.h>
#if defined(__APPLE__)
# include <sys/sysctl.h>
# if TARGET_OS_IPHONE != 0
-# include <IceSSL/Util.h> // For loadCertificateChain
+# include <IceSSL/SecureTransportUtil.h> // For loadCertificateChain
# endif
#elif defined(ICE_OS_UWP)
# include <ppltasks.h>
@@ -38,6 +39,25 @@ using namespace Windows::Security::Cryptography::Certificates;
# define ICE_TARGET_EQUAL_TO(A,B) A == B
#endif
+#if defined(__APPLE__)
+# define ICE_USE_SECURE_TRANSPORT 1
+#if defined(__APPLE__) && TARGET_OS_IPHONE != 0
+# define ICE_USE_SECURE_TRANSPORT_IOS 1
+#else
+# define ICE_USE_SECURE_TRANSPORT_MACOS 1
+#endif
+#elif defined(_WIN32)
+# if !defined(ICE_OS_UWP) && !defined(ICE_USE_OPENSSL)
+# define ICE_USE_SCHANNEL 1
+# endif
+#else
+# define ICE_USE_OPENSSL 1
+#endif
+
+#if defined(_WIN32) && defined(ICE_USE_OPENSSL)
+# include <IceSSL/OpenSSL.h>
+#endif
+
using namespace std;
using namespace Ice;
@@ -89,7 +109,7 @@ readFile(const string& file, vector<char>& buffer)
bool
importCaCertificate(const string& friendlyName, const string& file)
{
- auto cert = IceSSL::Certificate::load(file)->getCert();
+ auto cert = IceSSL::UWP::Certificate::load(file)->getCert();
cert->FriendlyName = ref new String(stringToWstring(friendlyName).c_str());
CertificateStores::TrustedRootCertificationAuthorities->Add(cert);
return true;
@@ -304,7 +324,7 @@ public:
string resolved;
if(IceSSL::checkPath(certificates[i], defaultDir, false, resolved))
{
- IceInternal::UniqueRef<CFArrayRef> certs(IceSSL::loadCertificateChain(resolved, "", "", "", "password", 0, 0));
+ IceInternal::UniqueRef<CFArrayRef> certs(IceSSL::SecureTransport::loadCertificateChain(resolved, "", "", "", "password", 0, 0));
SecIdentityRef identity = static_cast<SecIdentityRef>(const_cast<void*>(CFArrayGetValueAtIndex(certs.get(), 0)));
CFRetain(identity);
_identities.push_back(identity);
@@ -525,7 +545,9 @@ createClientProps(const Ice::PropertiesPtr& defaultProps, bool p12)
//
// Don't set the plugin property, the client registered the plugin with registerIceSSL.
//
- //result->setProperty("Ice.Plugin.IceSSL", "IceSSL:createIceSSL");
+#if defined(_WIN32) && defined(ICE_USE_OPENSSL)
+ result->setProperty("Ice.Plugin.IceSSL", "IceSSLOpenSSL:createIceSSLOpenSSL");
+#endif
result->setProperty("IceSSL.DefaultDir", defaultProps->getProperty("IceSSL.DefaultDir"));
result->setProperty("Ice.Default.Host", defaultProps->getProperty("Ice.Default.Host"));
if(!defaultProps->getProperty("Ice.IPv6").empty())
@@ -536,8 +558,8 @@ createClientProps(const Ice::PropertiesPtr& defaultProps, bool p12)
{
result->setProperty("IceSSL.Password", "password");
}
-// result->setProperty("IceSSL.Trace.Security", "1");
-// result->setProperty("Ice.Trace.Network", "1");
+ //result->setProperty("IceSSL.Trace.Security", "1");
+ //result->setProperty("Ice.Trace.Network", "3");
#ifdef ICE_USE_SECURE_TRANSPORT
ostringstream keychainName;
keychainName << "../certs/keychain/client" << keychainN++ << ".keychain";
@@ -552,7 +574,11 @@ static Test::Properties
createServerProps(const Ice::PropertiesPtr& defaultProps, bool p12)
{
Test::Properties result;
+#if defined(_WIN32) && defined(ICE_USE_OPENSSL)
+ result["Ice.Plugin.IceSSL"] = "IceSSLOpenSSL:createIceSSLOpenSSL";
+#else
result["Ice.Plugin.IceSSL"] = "IceSSL:createIceSSL";
+#endif
result["IceSSL.DefaultDir"] = defaultProps->getProperty("IceSSL.DefaultDir");
result["Ice.Default.Host"] = defaultProps->getProperty("Ice.Default.Host");
if(!defaultProps->getProperty("Ice.IPv6").empty())
@@ -563,8 +589,8 @@ createServerProps(const Ice::PropertiesPtr& defaultProps, bool p12)
{
result["IceSSL.Password"] = "password";
}
-// result["Ice.Trace.Network"] = "1";
-// result["IceSSL.Trace.Security"] = "1";
+ //result["Ice.Trace.Network"] = "3";
+ //result["IceSSL.Trace.Security"] = "1";
#ifdef ICE_USE_SECURE_TRANSPORT
ostringstream keychainName;
keychainName << "../certs/keychain/server" << keychainN << ".keychain";
@@ -781,8 +807,9 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12)
{
server->ice_ping();
}
- catch(const LocalException&)
+ catch(const LocalException& ex)
{
+ cerr << ex << endl;
test(false);
}
fact->destroyServer(server);
@@ -908,13 +935,17 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12)
server = fact->createServer(d);
try
{
-#ifdef ICE_OS_UWP
+#if defined(ICE_OS_UWP)
IceSSL::CertificatePtr clientCert = IceSSL::Certificate::load("ms-appx:///c_rsa_ca1_pub.pem");
Ice::Context ctx;
ctx["uwp"] = "1";
server->checkCert(clientCert->getSubjectDN(), clientCert->getIssuerDN(), ctx);
#else
+# if defined(_WIN32) && defined(ICE_USE_OPENSSL)
+ IceSSL::CertificatePtr clientCert = IceSSL::OpenSSL::Certificate::load(defaultDir + "/c_rsa_ca1_pub.pem");
+# else
IceSSL::CertificatePtr clientCert = IceSSL::Certificate::load(defaultDir + "/c_rsa_ca1_pub.pem");
+# endif
server->checkCert(clientCert->getSubjectDN(), clientCert->getIssuerDN());
#endif
@@ -925,12 +956,17 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12)
//
// Validate some aspects of the Certificate class.
//
-#ifdef ICE_OS_UWP
+#if defined(ICE_OS_UWP)
IceSSL::CertificatePtr serverCert = IceSSL::Certificate::load("ms-appx:///s_rsa_ca1_pub.pem");
#else
+# if defined(_WIN32) && defined(ICE_USE_OPENSSL)
+ IceSSL::CertificatePtr serverCert = IceSSL::OpenSSL::Certificate::load(defaultDir + "/s_rsa_ca1_pub.pem");
+ test(ICE_TARGET_EQUAL_TO(IceSSL::OpenSSL::Certificate::decode(serverCert->encode()), serverCert));
+# else
IceSSL::CertificatePtr serverCert = IceSSL::Certificate::load(defaultDir + "/s_rsa_ca1_pub.pem");
-#endif
test(ICE_TARGET_EQUAL_TO(IceSSL::Certificate::decode(serverCert->encode()), serverCert));
+# endif
+#endif
test(ICE_TARGET_EQUAL_TO(serverCert, serverCert));
#if !defined(__APPLE__) || TARGET_OS_IPHONE == 0
test(serverCert->checkValidity());
@@ -942,12 +978,17 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12)
# endif
#endif
-#ifdef ICE_OS_UWP
+#if defined(ICE_OS_UWP)
IceSSL::CertificatePtr caCert = IceSSL::Certificate::load("ms-appx:///cacert1.pem");
IceSSL::CertificatePtr caCert2 = IceSSL::Certificate::load("ms-appx:///cacert2.pem");
#else
+# if defined(_WIN32) && defined(ICE_USE_OPENSSL)
+ IceSSL::CertificatePtr caCert = IceSSL::OpenSSL::Certificate::load(defaultDir + "/cacert1.pem");
+ IceSSL::CertificatePtr caCert2 = IceSSL::OpenSSL::Certificate::load(defaultDir + "/cacert2.pem");
+# else
IceSSL::CertificatePtr caCert = IceSSL::Certificate::load(defaultDir + "/cacert1.pem");
IceSSL::CertificatePtr caCert2 = IceSSL::Certificate::load(defaultDir + "/cacert2.pem");
+# endif
#endif
test(ICE_TARGET_EQUAL_TO(caCert, caCert));
#if !defined(__APPLE__) || TARGET_OS_IPHONE == 0
@@ -1019,13 +1060,17 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12)
server = fact->createServer(d);
try
{
-#ifdef ICE_OS_UWP
+#if defined(ICE_OS_UWP)
IceSSL::CertificatePtr clientCert = IceSSL::Certificate::load("ms-appx:///c_rsa_ca1_pub.pem");
Ice::Context ctx;
ctx["uwp"] = "1";
server->checkCert(clientCert->getSubjectDN(), clientCert->getIssuerDN(), ctx);
#else
+# if defined(_WIN32) && defined(ICE_USE_OPENSSL)
+ IceSSL::CertificatePtr clientCert = IceSSL::OpenSSL::Certificate::load(defaultDir + "/c_rsa_ca1_pub.pem");
+# else
IceSSL::CertificatePtr clientCert = IceSSL::Certificate::load(defaultDir + "/c_rsa_ca1_pub.pem");
+# endif
server->checkCert(clientCert->getSubjectDN(), clientCert->getIssuerDN());
#endif
}
@@ -4079,10 +4124,13 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12)
#endif
}
-#if !defined(_AIX) && !defined(ICE_OS_UWP)
+#if !defined(_AIX) && !defined(ICE_OS_UWP) && !(defined(_WIN32) && defined(ICE_USE_OPENSSL))
+ //
// On AIX 6.1, the default root certificates don't validate demo.zeroc.com
// UWP application manifest is not configure to use system CAs and IceSSL.UsePlatformCAs
- // is not supported with UWP
+ // is not supported with UWP.
+ // On Windows with OpenSSL there isn't any system CAs
+ //
cout << "testing system CAs... " << flush;
{
{
diff --git a/cpp/test/IceSSL/configuration/Client.cpp b/cpp/test/IceSSL/configuration/Client.cpp
index 931e45955da..1e416a55e57 100644
--- a/cpp/test/IceSSL/configuration/Client.cpp
+++ b/cpp/test/IceSSL/configuration/Client.cpp
@@ -12,6 +12,10 @@
#include <TestCommon.h>
#include <Test.h>
+#if defined(ICE_USE_OPENSSL)
+# include <IceSSL/OpenSSL.h>
+#endif
+
DEFINE_TEST("client")
using namespace std;
@@ -65,7 +69,9 @@ main(int argc, char* argv[])
// don't set Ice.Plugin.IceSSL to ensure the plugin is registered without
// the property setting.
//
+#if !defined(ICE_USE_OPENSSL)
Ice::registerIceSSL();
+#endif
int status;
Ice::CommunicatorPtr communicator;
diff --git a/cpp/test/IceSSL/configuration/Server.cpp b/cpp/test/IceSSL/configuration/Server.cpp
index d5d37876202..b8308cd89ba 100644
--- a/cpp/test/IceSSL/configuration/Server.cpp
+++ b/cpp/test/IceSSL/configuration/Server.cpp
@@ -11,6 +11,10 @@
#include <TestI.h>
#include <TestCommon.h>
+#if defined(ICE_USE_OPENSSL)
+# include <IceSSL/OpenSSL.h>
+#endif
+
DEFINE_TEST("server")
using namespace std;
diff --git a/cpp/test/IceSSL/configuration/msbuild/clientopenssl/clientopenssl.vcxproj b/cpp/test/IceSSL/configuration/msbuild/clientopenssl/clientopenssl.vcxproj
new file mode 100644
index 00000000000..b2619bef670
--- /dev/null
+++ b/cpp/test/IceSSL/configuration/msbuild/clientopenssl/clientopenssl.vcxproj
@@ -0,0 +1,358 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="..\..\..\..\..\msbuild\packages\zeroc.ice.v120.3.7.0-beta0\build\native\zeroc.ice.v120.props" Condition="Exists('..\..\..\..\..\msbuild\packages\zeroc.ice.v120.3.7.0-beta0\build\native\zeroc.ice.v120.props') and '$(ICE_BIN_DIST)' == 'all'" />
+ <Import Project="..\..\..\..\..\msbuild\packages\zeroc.ice.v140.3.7.0-beta0\build\native\zeroc.ice.v140.props" Condition="Exists('..\..\..\..\..\msbuild\packages\zeroc.ice.v140.3.7.0-beta0\build\native\zeroc.ice.v140.props') and '$(ICE_BIN_DIST)' == 'all'" />
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Cpp11-Debug|Win32">
+ <Configuration>Cpp11-Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Cpp11-Debug|x64">
+ <Configuration>Cpp11-Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Cpp11-Release|Win32">
+ <Configuration>Cpp11-Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Cpp11-Release|x64">
+ <Configuration>Cpp11-Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{34135D29-7ABF-416E-80A9-4077BD6A126F}</ProjectGuid>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ <IceBuilderInstallDir>$([MSBuild]::GetRegistryValue('HKEY_CURRENT_USER\SOFTWARE\ZeroC\IceBuilder', 'InstallDir.$(VisualStudioVersion)'))</IceBuilderInstallDir>
+ <IceBuilderCppProps>$(IceBuilderInstallDir)\Resources\IceBuilder.Cpp.props</IceBuilderCppProps>
+ <IceBuilderCppTargets>$(IceBuilderInstallDir)\Resources\IceBuilder.Cpp.targets</IceBuilderCppTargets>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <Import Project="$(MSBuildThisFileDirectory)\..\..\..\..\..\msbuild\ice.test.props" />
+ <Import Project="$(IceBuilderCppProps)" Condition="Exists('$(IceBuilderCppProps)')" />
+ <ImportGroup Label="ExtensionSettings">
+ <Import Project="..\..\..\..\..\msbuild\packages\zeroc.ice.v140.3.7.0-beta0\build\native\zeroc.ice.v140.targets" Condition="Exists('..\..\..\..\..\msbuild\packages\zeroc.ice.v140.3.7.0-beta0\build\native\zeroc.ice.v140.targets') and '$(ICE_BIN_DIST)' == 'all'" />
+ <Import Project="..\..\..\..\..\msbuild\packages\zeroc.ice.v120.3.7.0-beta0\build\native\zeroc.ice.v120.targets" Condition="Exists('..\..\..\..\..\msbuild\packages\zeroc.ice.v120.3.7.0-beta0\build\native\zeroc.ice.v120.targets') and '$(ICE_BIN_DIST)' == 'all'" />
+ <Import Project="..\..\..\..\..\msbuild\packages\openssl.v140.1.0.2.1\build\native\openssl.v140.targets" Condition="Exists('..\..\..\..\..\msbuild\packages\openssl.v140.1.0.2.1\build\native\openssl.v140.targets')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">
+ <Link>
+ <AdditionalDependencies>advapi32.lib;crypt32.lib</AdditionalDependencies>
+ </Link>
+ <ClCompile>
+ <PreprocessorDefinitions>ICE_USE_OPENSSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Link>
+ <AdditionalDependencies>advapi32.lib;crypt32.lib</AdditionalDependencies>
+ </Link>
+ <ClCompile>
+ <PreprocessorDefinitions>ICE_USE_OPENSSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Link>
+ <AdditionalDependencies>advapi32.lib;crypt32.lib</AdditionalDependencies>
+ </Link>
+ <ClCompile>
+ <PreprocessorDefinitions>ICE_USE_OPENSSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">
+ <Link>
+ <AdditionalDependencies>advapi32.lib;crypt32.lib</AdditionalDependencies>
+ </Link>
+ <ClCompile>
+ <PreprocessorDefinitions>ICE_USE_OPENSSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">
+ <Link>
+ <AdditionalDependencies>advapi32.lib;crypt32.lib</AdditionalDependencies>
+ </Link>
+ <ClCompile>
+ <PreprocessorDefinitions>ICE_USE_OPENSSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Link>
+ <AdditionalDependencies>advapi32.lib;crypt32.lib</AdditionalDependencies>
+ </Link>
+ <ClCompile>
+ <PreprocessorDefinitions>ICE_USE_OPENSSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Link>
+ <AdditionalDependencies>advapi32.lib;crypt32.lib</AdditionalDependencies>
+ </Link>
+ <ClCompile>
+ <PreprocessorDefinitions>ICE_USE_OPENSSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">
+ <Link>
+ <AdditionalDependencies>advapi32.lib;crypt32.lib</AdditionalDependencies>
+ </Link>
+ <ClCompile>
+ <PreprocessorDefinitions>ICE_USE_OPENSSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <IceBuilder Include="..\..\Test.ice" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\AllTests.cpp" />
+ <ClCompile Include="..\..\Client.cpp" />
+ <ClCompile Include="Win32\Cpp11-Debug\Test.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="Win32\Cpp11-Release\Test.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="Win32\Debug\Test.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="Win32\Release\Test.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="x64\Cpp11-Debug\Test.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="x64\Cpp11-Release\Test.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="x64\Debug\Test.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="x64\Release\Test.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="Win32\Cpp11-Debug\Test.h">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClInclude>
+ <ClInclude Include="Win32\Cpp11-Release\Test.h">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ </ClInclude>
+ <ClInclude Include="Win32\Debug\Test.h">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClInclude>
+ <ClInclude Include="Win32\Release\Test.h">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClInclude>
+ <ClInclude Include="x64\Cpp11-Debug\Test.h">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClInclude>
+ <ClInclude Include="x64\Cpp11-Release\Test.h">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClInclude>
+ <ClInclude Include="x64\Debug\Test.h">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClInclude>
+ <ClInclude Include="x64\Release\Test.h">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <Import Project="$(IceBuilderCppTargets)" Condition="Exists('$(IceBuilderCppTargets)')" />
+ <Target Name="EnsureIceBuilderImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project requires the Ice Builder for Visual Studio extension. Use "Tools &amp;gt; Extensions and Updates" to install it. For more information, see https://visualstudiogallery.msdn.microsoft.com/1a64e701-63f2-4740-8004-290e6c682ce0.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(IceBuilderCppProps)')" Text="$(ErrorText)" />
+ </Target>
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('..\..\..\..\..\msbuild\packages\zeroc.ice.v140.3.7.0-beta0\build\native\zeroc.ice.v140.props') and '$(ICE_BIN_DIST)' == 'all'" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\..\msbuild\packages\zeroc.ice.v140.3.7.0-beta0\build\native\zeroc.ice.v140.props'))" />
+ <Error Condition="!Exists('..\..\..\..\..\msbuild\packages\zeroc.ice.v140.3.7.0-beta0\build\native\zeroc.ice.v140.targets') and '$(ICE_BIN_DIST)' == 'all'" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\..\msbuild\packages\zeroc.ice.v140.3.7.0-beta0\build\native\zeroc.ice.v140.targets'))" />
+ <Error Condition="!Exists('..\..\..\..\..\msbuild\packages\zeroc.ice.v120.3.7.0-beta0\build\native\zeroc.ice.v120.props') and '$(ICE_BIN_DIST)' == 'all'" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\..\msbuild\packages\zeroc.ice.v120.3.7.0-beta0\build\native\zeroc.ice.v120.props'))" />
+ <Error Condition="!Exists('..\..\..\..\..\msbuild\packages\zeroc.ice.v120.3.7.0-beta0\build\native\zeroc.ice.v120.targets') and '$(ICE_BIN_DIST)' == 'all'" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\..\msbuild\packages\zeroc.ice.v120.3.7.0-beta0\build\native\zeroc.ice.v120.targets'))" />
+ <Error Condition="!Exists('..\..\..\..\..\msbuild\packages\openssl.v140.1.0.2.1\build\native\openssl.v140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\..\msbuild\packages\openssl.v140.1.0.2.1\build\native\openssl.v140.targets'))" />
+ </Target>
+</Project> \ No newline at end of file
diff --git a/cpp/test/IceSSL/configuration/msbuild/clientopenssl/clientopenssl.vcxproj.filters b/cpp/test/IceSSL/configuration/msbuild/clientopenssl/clientopenssl.vcxproj.filters
new file mode 100644
index 00000000000..93cc54f49f8
--- /dev/null
+++ b/cpp/test/IceSSL/configuration/msbuild/clientopenssl/clientopenssl.vcxproj.filters
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="..\..\AllTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\Client.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="x64\Cpp11-Debug\Test.cpp">
+ <Filter>Source Files\x64\Cpp11-Debug</Filter>
+ </ClCompile>
+ <ClCompile Include="Win32\Cpp11-Debug\Test.cpp">
+ <Filter>Source Files\Win32\Cpp11-Debug</Filter>
+ </ClCompile>
+ <ClCompile Include="x64\Debug\Test.cpp">
+ <Filter>Source Files\x64\Debug</Filter>
+ </ClCompile>
+ <ClCompile Include="Win32\Debug\Test.cpp">
+ <Filter>Source Files\Win32\Debug</Filter>
+ </ClCompile>
+ <ClCompile Include="x64\Release\Test.cpp">
+ <Filter>Source Files\x64\Release</Filter>
+ </ClCompile>
+ <ClCompile Include="Win32\Release\Test.cpp">
+ <Filter>Source Files\Win32\Release</Filter>
+ </ClCompile>
+ <ClCompile Include="x64\Cpp11-Release\Test.cpp">
+ <Filter>Source Files\x64\Cpp11-Release</Filter>
+ </ClCompile>
+ <ClCompile Include="Win32\Cpp11-Release\Test.cpp">
+ <Filter>Source Files\Win32\Cpp11-Release</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Slice Files">
+ <UniqueIdentifier>{08bcf4bb-8da2-42d3-a2e4-4e48275b80d0}</UniqueIdentifier>
+ <Extensions>ice</Extensions>
+ </Filter>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{1f195fdb-30ae-41ba-9fc9-760d564bff78}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{caa10804-d3fd-4300-afcd-38f17bad5b69}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\x64">
+ <UniqueIdentifier>{cff6ff58-cfc7-4ff9-8b6e-983c9eadeeea}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\x64\Cpp11-Debug">
+ <UniqueIdentifier>{05fca7b1-4694-4d7b-9e96-8664b9eec0a3}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\x64">
+ <UniqueIdentifier>{b527d98a-2399-4c39-8963-1619d21e27cc}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\x64\Cpp11-Debug">
+ <UniqueIdentifier>{73aff73a-c87e-4d36-b247-d537cc2fd804}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Win32">
+ <UniqueIdentifier>{9dce4a10-5e39-41c2-9125-d537fcaf0562}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Win32\Cpp11-Debug">
+ <UniqueIdentifier>{c58a9746-f268-45f5-99d7-5fdb64a04407}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Win32">
+ <UniqueIdentifier>{7f2c40d1-5e97-4d10-9d0a-16905ab8ad76}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Win32\Cpp11-Debug">
+ <UniqueIdentifier>{22596883-4550-49c4-a5e0-ed146a3e68a5}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\x64\Debug">
+ <UniqueIdentifier>{50206de0-b08c-445c-9e80-58c39cc5278f}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\x64\Debug">
+ <UniqueIdentifier>{592034df-71c8-4fe2-a3dd-1b0683b74287}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Win32\Debug">
+ <UniqueIdentifier>{4648dae2-7d22-4cdd-b1cc-be2621e6bae6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Win32\Debug">
+ <UniqueIdentifier>{04269c9d-f32a-40b9-937d-f44b065331d4}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\x64\Release">
+ <UniqueIdentifier>{506cfce3-3fb6-4bbb-b397-72bc6feff9c6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\x64\Release">
+ <UniqueIdentifier>{37ab9376-8d7d-42b9-aaf3-bcab54ab0688}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Win32\Release">
+ <UniqueIdentifier>{c8295b1f-a0c2-4a59-bfeb-da9bd3b79cd3}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Win32\Release">
+ <UniqueIdentifier>{39ff1ead-1815-4af9-a2cd-457b6f0ed399}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\x64\Cpp11-Release">
+ <UniqueIdentifier>{8f5b4b04-166a-4057-8707-5c93822b5e02}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\x64\Cpp11-Release">
+ <UniqueIdentifier>{9c340360-3907-426f-b200-8b0040d45fa3}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Win32\Cpp11-Release">
+ <UniqueIdentifier>{4a70479b-9ee2-4d91-808b-14bb9b741b27}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Win32\Cpp11-Release">
+ <UniqueIdentifier>{eab6f860-7cf3-4cee-8810-216df2924251}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <IceBuilder Include="..\..\Test.ice">
+ <Filter>Slice Files</Filter>
+ </IceBuilder>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="x64\Cpp11-Debug\Test.h">
+ <Filter>Header Files\x64\Cpp11-Debug</Filter>
+ </ClInclude>
+ <ClInclude Include="Win32\Cpp11-Debug\Test.h">
+ <Filter>Header Files\Win32\Cpp11-Debug</Filter>
+ </ClInclude>
+ <ClInclude Include="x64\Debug\Test.h">
+ <Filter>Header Files\x64\Debug</Filter>
+ </ClInclude>
+ <ClInclude Include="Win32\Debug\Test.h">
+ <Filter>Header Files\Win32\Debug</Filter>
+ </ClInclude>
+ <ClInclude Include="x64\Release\Test.h">
+ <Filter>Header Files\x64\Release</Filter>
+ </ClInclude>
+ <ClInclude Include="Win32\Release\Test.h">
+ <Filter>Header Files\Win32\Release</Filter>
+ </ClInclude>
+ <ClInclude Include="x64\Cpp11-Release\Test.h">
+ <Filter>Header Files\x64\Cpp11-Release</Filter>
+ </ClInclude>
+ <ClInclude Include="Win32\Cpp11-Release\Test.h">
+ <Filter>Header Files\Win32\Cpp11-Release</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/cpp/test/IceSSL/configuration/msbuild/clientopenssl/packages.config b/cpp/test/IceSSL/configuration/msbuild/clientopenssl/packages.config
new file mode 100644
index 00000000000..b1c0af1a1b6
--- /dev/null
+++ b/cpp/test/IceSSL/configuration/msbuild/clientopenssl/packages.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="openssl.v140" version="1.0.2.1" targetFramework="native" />
+ <package id="zeroc.ice.v120" version="3.7.0-beta0" targetFramework="native" />
+ <package id="zeroc.ice.v140" version="3.7.0-beta0" targetFramework="native" />
+</packages> \ No newline at end of file
diff --git a/cpp/test/IceSSL/configuration/msbuild/serveropenssl/packages.config b/cpp/test/IceSSL/configuration/msbuild/serveropenssl/packages.config
new file mode 100644
index 00000000000..b1c0af1a1b6
--- /dev/null
+++ b/cpp/test/IceSSL/configuration/msbuild/serveropenssl/packages.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="openssl.v140" version="1.0.2.1" targetFramework="native" />
+ <package id="zeroc.ice.v120" version="3.7.0-beta0" targetFramework="native" />
+ <package id="zeroc.ice.v140" version="3.7.0-beta0" targetFramework="native" />
+</packages> \ No newline at end of file
diff --git a/cpp/test/IceSSL/configuration/msbuild/serveropenssl/serveropenssl.vcxproj b/cpp/test/IceSSL/configuration/msbuild/serveropenssl/serveropenssl.vcxproj
new file mode 100644
index 00000000000..9da8bf24423
--- /dev/null
+++ b/cpp/test/IceSSL/configuration/msbuild/serveropenssl/serveropenssl.vcxproj
@@ -0,0 +1,350 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="..\..\..\..\..\msbuild\packages\zeroc.ice.v120.3.7.0-beta0\build\native\zeroc.ice.v120.props" Condition="Exists('..\..\..\..\..\msbuild\packages\zeroc.ice.v120.3.7.0-beta0\build\native\zeroc.ice.v120.props') and '$(ICE_BIN_DIST)' == 'all'" />
+ <Import Project="..\..\..\..\..\msbuild\packages\zeroc.ice.v140.3.7.0-beta0\build\native\zeroc.ice.v140.props" Condition="Exists('..\..\..\..\..\msbuild\packages\zeroc.ice.v140.3.7.0-beta0\build\native\zeroc.ice.v140.props') and '$(ICE_BIN_DIST)' == 'all'" />
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Cpp11-Debug|Win32">
+ <Configuration>Cpp11-Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Cpp11-Debug|x64">
+ <Configuration>Cpp11-Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Cpp11-Release|Win32">
+ <Configuration>Cpp11-Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Cpp11-Release|x64">
+ <Configuration>Cpp11-Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{1A83DE5F-3401-4D5D-B9FE-A930D5B15F39}</ProjectGuid>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ <IceBuilderInstallDir>$([MSBuild]::GetRegistryValue('HKEY_CURRENT_USER\SOFTWARE\ZeroC\IceBuilder', 'InstallDir.$(VisualStudioVersion)'))</IceBuilderInstallDir>
+ <IceBuilderCppProps>$(IceBuilderInstallDir)\Resources\IceBuilder.Cpp.props</IceBuilderCppProps>
+ <IceBuilderCppTargets>$(IceBuilderInstallDir)\Resources\IceBuilder.Cpp.targets</IceBuilderCppTargets>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <Import Project="$(MSBuildThisFileDirectory)\..\..\..\..\..\msbuild\ice.test.props" />
+ <Import Project="$(IceBuilderCppProps)" Condition="Exists('$(IceBuilderCppProps)')" />
+ <ImportGroup Label="ExtensionSettings">
+ <Import Project="..\..\..\..\..\msbuild\packages\zeroc.ice.v140.3.7.0-beta0\build\native\zeroc.ice.v140.targets" Condition="Exists('..\..\..\..\..\msbuild\packages\zeroc.ice.v140.3.7.0-beta0\build\native\zeroc.ice.v140.targets') and '$(ICE_BIN_DIST)' == 'all'" />
+ <Import Project="..\..\..\..\..\msbuild\packages\zeroc.ice.v120.3.7.0-beta0\build\native\zeroc.ice.v120.targets" Condition="Exists('..\..\..\..\..\msbuild\packages\zeroc.ice.v120.3.7.0-beta0\build\native\zeroc.ice.v120.targets') and '$(ICE_BIN_DIST)' == 'all'" />
+ <Import Project="..\..\..\..\..\msbuild\packages\openssl.v140.1.0.2.1\build\native\openssl.v140.targets" Condition="Exists('..\..\..\..\..\msbuild\packages\openssl.v140.1.0.2.1\build\native\openssl.v140.targets')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>ICE_USE_OPENSSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies />
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>ICE_USE_OPENSSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>ICE_USE_OPENSSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link />
+ <Link />
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>ICE_USE_OPENSSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>ICE_USE_OPENSSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>ICE_USE_OPENSSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>ICE_USE_OPENSSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link />
+ <Link />
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>ICE_USE_OPENSSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <IceBuilder Include="..\..\Test.ice" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\Server.cpp" />
+ <ClCompile Include="..\..\TestI.cpp" />
+ <ClCompile Include="Win32\Cpp11-Debug\Test.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="Win32\Cpp11-Release\Test.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="Win32\Debug\Test.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="Win32\Release\Test.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="x64\Cpp11-Debug\Test.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="x64\Cpp11-Release\Test.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="x64\Debug\Test.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ <ClCompile Include="x64\Release\Test.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\TestI.h" />
+ <ClInclude Include="Win32\Cpp11-Debug\Test.h">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClInclude>
+ <ClInclude Include="Win32\Cpp11-Release\Test.h">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ </ClInclude>
+ <ClInclude Include="Win32\Debug\Test.h">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClInclude>
+ <ClInclude Include="Win32\Release\Test.h">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClInclude>
+ <ClInclude Include="x64\Cpp11-Debug\Test.h">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClInclude>
+ <ClInclude Include="x64\Cpp11-Release\Test.h">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClInclude>
+ <ClInclude Include="x64\Debug\Test.h">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClInclude>
+ <ClInclude Include="x64\Release\Test.h">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Cpp11-Release|Win32'">true</ExcludedFromBuild>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <PropertyGroup Label="UserMacros" />
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <Import Project="$(IceBuilderCppTargets)" Condition="Exists('$(IceBuilderCppTargets)')" />
+ <Target Name="EnsureIceBuilderImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project requires the Ice Builder for Visual Studio extension. Use "Tools &amp;gt; Extensions and Updates" to install it. For more information, see https://visualstudiogallery.msdn.microsoft.com/1a64e701-63f2-4740-8004-290e6c682ce0.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(IceBuilderCppProps)')" Text="$(ErrorText)" />
+ </Target>
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('..\..\..\..\..\msbuild\packages\zeroc.ice.v140.3.7.0-beta0\build\native\zeroc.ice.v140.props') and '$(ICE_BIN_DIST)' == 'all'" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\..\msbuild\packages\zeroc.ice.v140.3.7.0-beta0\build\native\zeroc.ice.v140.props'))" />
+ <Error Condition="!Exists('..\..\..\..\..\msbuild\packages\zeroc.ice.v140.3.7.0-beta0\build\native\zeroc.ice.v140.targets') and '$(ICE_BIN_DIST)' == 'all'" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\..\msbuild\packages\zeroc.ice.v140.3.7.0-beta0\build\native\zeroc.ice.v140.targets'))" />
+ <Error Condition="!Exists('..\..\..\..\..\msbuild\packages\zeroc.ice.v120.3.7.0-beta0\build\native\zeroc.ice.v120.props') and '$(ICE_BIN_DIST)' == 'all'" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\..\msbuild\packages\zeroc.ice.v120.3.7.0-beta0\build\native\zeroc.ice.v120.props'))" />
+ <Error Condition="!Exists('..\..\..\..\..\msbuild\packages\zeroc.ice.v120.3.7.0-beta0\build\native\zeroc.ice.v120.targets') and '$(ICE_BIN_DIST)' == 'all'" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\..\msbuild\packages\zeroc.ice.v120.3.7.0-beta0\build\native\zeroc.ice.v120.targets'))" />
+ <Error Condition="!Exists('..\..\..\..\..\msbuild\packages\openssl.v140.1.0.2.1\build\native\openssl.v140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\..\msbuild\packages\openssl.v140.1.0.2.1\build\native\openssl.v140.targets'))" />
+ </Target>
+</Project> \ No newline at end of file
diff --git a/cpp/test/IceSSL/configuration/msbuild/serveropenssl/serveropenssl.vcxproj.filters b/cpp/test/IceSSL/configuration/msbuild/serveropenssl/serveropenssl.vcxproj.filters
new file mode 100644
index 00000000000..281d36c06b1
--- /dev/null
+++ b/cpp/test/IceSSL/configuration/msbuild/serveropenssl/serveropenssl.vcxproj.filters
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="..\..\Server.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\TestI.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="x64\Cpp11-Debug\Test.cpp">
+ <Filter>Source Files\x64\Cpp11-Debug</Filter>
+ </ClCompile>
+ <ClCompile Include="Win32\Cpp11-Debug\Test.cpp">
+ <Filter>Source Files\Win32\Cpp11-Debug</Filter>
+ </ClCompile>
+ <ClCompile Include="x64\Debug\Test.cpp">
+ <Filter>Source Files\x64\Debug</Filter>
+ </ClCompile>
+ <ClCompile Include="Win32\Debug\Test.cpp">
+ <Filter>Source Files\Win32\Debug</Filter>
+ </ClCompile>
+ <ClCompile Include="x64\Release\Test.cpp">
+ <Filter>Source Files\x64\Release</Filter>
+ </ClCompile>
+ <ClCompile Include="Win32\Release\Test.cpp">
+ <Filter>Source Files\Win32\Release</Filter>
+ </ClCompile>
+ <ClCompile Include="x64\Cpp11-Release\Test.cpp">
+ <Filter>Source Files\x64\Cpp11-Release</Filter>
+ </ClCompile>
+ <ClCompile Include="Win32\Cpp11-Release\Test.cpp">
+ <Filter>Source Files\Win32\Cpp11-Release</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{00922b8a-f9c7-4876-87dc-7e1d5239cb67}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Slice Files">
+ <UniqueIdentifier>{632a0f02-496e-48af-b566-685d2b84964d}</UniqueIdentifier>
+ <Extensions>ice</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{f493b829-501f-4bb7-812e-55f66f4fea51}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\x64">
+ <UniqueIdentifier>{d25424dc-4b3f-4dec-a83a-54d4de89fefe}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\x64\Cpp11-Debug">
+ <UniqueIdentifier>{625e8b26-8c7b-48e0-b61f-207f02235717}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\x64">
+ <UniqueIdentifier>{b2c4157f-5d2d-45fb-b193-c6d7da06190a}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\x64\Cpp11-Debug">
+ <UniqueIdentifier>{4f5279cd-c658-4c6c-9ec3-a0152caf0ed5}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Win32">
+ <UniqueIdentifier>{b35ef6e1-7178-4b4e-a992-0ba588b047fd}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Win32\Cpp11-Debug">
+ <UniqueIdentifier>{7b307652-09f7-45b2-885f-50ae92266efd}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Win32">
+ <UniqueIdentifier>{9caa42de-c763-47d9-9f4d-e3ae67b23a9d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Win32\Cpp11-Debug">
+ <UniqueIdentifier>{fcb3f373-d502-4e32-a1d5-ef5b918367c9}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\x64\Debug">
+ <UniqueIdentifier>{f31275fe-6cc1-47c6-bdfd-74984e2ea306}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\x64\Debug">
+ <UniqueIdentifier>{069e1eb3-2e20-47c2-89a3-083203109449}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Win32\Debug">
+ <UniqueIdentifier>{250998b2-ec62-41fe-b480-87aecbef67e6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Win32\Debug">
+ <UniqueIdentifier>{b575266a-2948-4ee0-8bd0-cede3812b41c}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\x64\Release">
+ <UniqueIdentifier>{89df9379-399c-4bfc-9d60-f371b41f3936}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\x64\Release">
+ <UniqueIdentifier>{1c318068-a0ce-4ce7-9544-b19709fa509d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Win32\Release">
+ <UniqueIdentifier>{a3c4f295-3c3b-4774-83be-211a3cb1a990}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Win32\Release">
+ <UniqueIdentifier>{f5e99acb-dae1-4563-8086-882077ef946f}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\x64\Cpp11-Release">
+ <UniqueIdentifier>{8cea6720-831d-44c3-a1e8-92451ae1ac45}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\x64\Cpp11-Release">
+ <UniqueIdentifier>{82198e5b-4c69-4d86-b991-cd322047f1e1}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Win32\Cpp11-Release">
+ <UniqueIdentifier>{883e8b6c-c487-4e4f-90f3-e37b7d095867}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Win32\Cpp11-Release">
+ <UniqueIdentifier>{1cd2596f-cf38-4e5a-a94f-246cc35987df}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <IceBuilder Include="..\..\Test.ice">
+ <Filter>Slice Files</Filter>
+ </IceBuilder>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\TestI.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="x64\Cpp11-Debug\Test.h">
+ <Filter>Header Files\x64\Cpp11-Debug</Filter>
+ </ClInclude>
+ <ClInclude Include="Win32\Cpp11-Debug\Test.h">
+ <Filter>Header Files\Win32\Cpp11-Debug</Filter>
+ </ClInclude>
+ <ClInclude Include="x64\Debug\Test.h">
+ <Filter>Header Files\x64\Debug</Filter>
+ </ClInclude>
+ <ClInclude Include="Win32\Debug\Test.h">
+ <Filter>Header Files\Win32\Debug</Filter>
+ </ClInclude>
+ <ClInclude Include="x64\Release\Test.h">
+ <Filter>Header Files\x64\Release</Filter>
+ </ClInclude>
+ <ClInclude Include="Win32\Release\Test.h">
+ <Filter>Header Files\Win32\Release</Filter>
+ </ClInclude>
+ <ClInclude Include="x64\Cpp11-Release\Test.h">
+ <Filter>Header Files\x64\Cpp11-Release</Filter>
+ </ClInclude>
+ <ClInclude Include="Win32\Cpp11-Release\Test.h">
+ <Filter>Header Files\Win32\Cpp11-Release</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+</Project> \ No newline at end of file