diff options
Diffstat (limited to 'cpp')
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(¶ms, 0, sizeof(params)); - params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; - - UniqueRef<CFArrayRef> items; - OSStatus err = SecItemImport(data.get(), 0, &format, &type, 0, ¶ms, 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(¶ms, 0, sizeof(params)); + params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; + + UniqueRef<CFArrayRef> items; + OSStatus err = SecItemImport(data.get(), 0, &format, &type, 0, ¶ms, 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(¶ms, 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, ¶ms, 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, ¶ms, 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(¶ms, 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, ¶ms, 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, ¶ms, 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 &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 &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 &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 &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 |