summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2015-04-28 19:27:04 +0200
committerBenoit Foucher <benoit@zeroc.com>2015-04-28 19:27:04 +0200
commite6e102cc642e78cf9da55645c82f5bfe6eacb76d (patch)
treeab5861ee9ad2a909fa0dc8f25b1b12e0dd1d6527
parentFixed ICE-6443 and other SSL fixes (diff)
downloadice-e6e102cc642e78cf9da55645c82f5bfe6eacb76d.tar.bz2
ice-e6e102cc642e78cf9da55645c82f5bfe6eacb76d.tar.xz
ice-e6e102cc642e78cf9da55645c82f5bfe6eacb76d.zip
Fixed previous commit which was incomplete
-rw-r--r--CHANGELOG-3.6.md16
-rw-r--r--config/PropertyNames.xml10
-rw-r--r--cpp/include/IceSSL/Plugin.h41
-rw-r--r--cpp/src/Ice/EndpointI.h32
-rw-r--r--cpp/src/Ice/OpaqueEndpointI.cpp9
-rw-r--r--cpp/src/Ice/PropertyNames.cpp12
-rw-r--r--cpp/src/Ice/PropertyNames.h2
-rw-r--r--cpp/src/Ice/TcpEndpointI.cpp40
-rw-r--r--cpp/src/Ice/TcpEndpointI.h4
-rw-r--r--cpp/src/Ice/TcpTransceiver.cpp28
-rw-r--r--cpp/src/Ice/TcpTransceiver.h6
-rw-r--r--cpp/src/Ice/UdpEndpointI.cpp33
-rw-r--r--cpp/src/Ice/WSEndpoint.cpp37
-rw-r--r--cpp/src/Ice/WSEndpoint.h11
-rw-r--r--cpp/src/Ice/WSTransceiver.cpp13
-rw-r--r--cpp/src/Ice/WSTransceiver.h11
-rw-r--r--cpp/src/Ice/winrt/StreamEndpointI.cpp67
-rw-r--r--cpp/src/Ice/winrt/StreamEndpointI.h4
-rw-r--r--cpp/src/Ice/winrt/StreamTransceiver.cpp32
-rw-r--r--cpp/src/Ice/winrt/StreamTransceiver.h6
-rw-r--r--cpp/src/IceSSL/EndpointI.cpp40
-rw-r--r--cpp/src/IceSSL/EndpointI.h4
-rw-r--r--cpp/src/IceSSL/OpenSSLEngine.cpp22
-rw-r--r--cpp/src/IceSSL/OpenSSLTransceiverI.cpp110
-rw-r--r--cpp/src/IceSSL/OpenSSLTransceiverI.h10
-rw-r--r--cpp/src/IceSSL/SChannelEngine.cpp111
-rw-r--r--cpp/src/IceSSL/SChannelTransceiverI.cpp23
-rw-r--r--cpp/src/IceSSL/SChannelTransceiverI.h6
-rw-r--r--cpp/src/IceSSL/SecureTransportEngine.cpp11
-rw-r--r--cpp/src/IceSSL/SecureTransportTransceiverI.cpp23
-rw-r--r--cpp/src/IceSSL/SecureTransportTransceiverI.h6
-rw-r--r--cpp/test/Ice/info/AllTests.cpp27
-rw-r--r--cpp/test/Ice/info/TestI.cpp9
-rwxr-xr-xcpp/test/IceSSL/certs/makecerts.py6
-rw-r--r--cpp/test/IceSSL/configuration/AllTests.cpp347
-rwxr-xr-xcpp/test/IceSSL/configuration/run.py6
-rw-r--r--csharp/src/Ice/PropertyNames.cs13
-rw-r--r--csharp/src/Ice/TcpEndpointI.cs35
-rw-r--r--csharp/src/Ice/TcpTransceiver.cs38
-rw-r--r--csharp/src/Ice/WSEndpoint.cs15
-rw-r--r--csharp/src/Ice/WSTransceiver.cs21
-rw-r--r--csharp/src/IceSSL/EndpointI.cs38
-rw-r--r--csharp/src/IceSSL/SSLEngine.cs63
-rw-r--r--csharp/src/IceSSL/TransceiverI.cs184
-rw-r--r--csharp/src/IceSSL/Util.cs14
-rw-r--r--csharp/test/Ice/info/AllTests.cs21
-rw-r--r--csharp/test/Ice/info/Makefile.mak2
-rw-r--r--csharp/test/Ice/info/TestI.cs9
-rwxr-xr-xcsharp/test/IceSSL/certs/makecerts.py8
-rw-r--r--csharp/test/IceSSL/configuration/AllTests.cs499
-rw-r--r--java/src/Ice/src/main/java/IceInternal/PropertyNames.java13
-rw-r--r--java/src/Ice/src/main/java/IceInternal/TcpEndpointI.java64
-rw-r--r--java/src/Ice/src/main/java/IceInternal/TcpTransceiver.java48
-rw-r--r--java/src/Ice/src/main/java/IceInternal/WSEndpoint.java25
-rw-r--r--java/src/Ice/src/main/java/IceInternal/WSTransceiver.java12
-rw-r--r--java/src/Ice/src/main/java/IceSSL/EndpointI.java64
-rw-r--r--java/src/Ice/src/main/java/IceSSL/SSLEngine.java81
-rw-r--r--java/src/Ice/src/main/java/IceSSL/TransceiverI.java28
-rw-r--r--java/test/src/main/java/test/Ice/info/AllTests.java21
-rw-r--r--java/test/src/main/java/test/Ice/info/TestI.java9
-rw-r--r--java/test/src/main/java/test/IceSSL/configuration/AllTests.java45
-rw-r--r--js/src/Ice/PropertyNames.js3
-rw-r--r--js/src/Ice/WSEndpoint.js5
-rw-r--r--js/src/Ice/browser/WSTransceiver.js5
-rw-r--r--js/src/Ice/sources.json3
-rw-r--r--js/test/Ice/proxy/Client.js37
-rw-r--r--python/modules/IcePy/ConnectionInfo.cpp1
-rwxr-xr-xscripts/Expect.py5
-rwxr-xr-xscripts/TestUtil.py12
-rw-r--r--slice/Ice/Connection.ice5
-rw-r--r--slice/Ice/Endpoint.ice2
-rw-r--r--slice/IceSSL/ConnectionInfo.ice11
-rw-r--r--slice/IceSSL/EndpointInfo.ice15
73 files changed, 1715 insertions, 934 deletions
diff --git a/CHANGELOG-3.6.md b/CHANGELOG-3.6.md
index c908d8de793..a2f8c5d272b 100644
--- a/CHANGELOG-3.6.md
+++ b/CHANGELOG-3.6.md
@@ -19,11 +19,23 @@ These are the changes since Ice 3.5.1.
## General Changes
-- The default value of the IceSSL.VerifyDepthMax property is now 3 (it was previously 2). This allows certificate chains of 3 certificates (e.g: a Peer, CA and Root certificate chain).
+- Added `IceSSL::WSSConnectionInfo` local Slice class to provide information on a WSS connection. This class extends the `IceSSL::ConnectionInfo` class. The `IceSSL::WSSNativeConnectionInfo` was also added to provide the language mapping specific certificates associated with the SSL connection.
+
+- Added `IceSSL::WSSEndpointInfo` local Slice class to provide WSS endpoint information. This class extends the `IceSSL::EndpointInfo` class.
+
+- Updated `Ice::WSEndpointInfo` to extend `Ice::TCPEndpointInfo` and `Ice::WSConnectionInfo` to extend `Ice::TCPConnectionInfo`
+
+- IceSSL now supports using the platform Root Certificate Authorities to validate remote certificates. The use of the platform Root CAs can be enabled with the `IceSSL.UsePlatformCAs` property. The platform Root CAs are only checked if `Ice.CAs` is not set.
+
+- The `IceSSL.CertAuthFile` and `IceSSL.CertAuthDir` properties have been deprecated. You should now use the `Ice.CAs` property to configure the path of the PEM file containing the Root Certificate Authorities or the path of a directory containing the certificates (OpenSSL only).
+
+- The `IceSSL.KeyFile` property has been deprecated. You should instead use `Ice.CertFile` and PKCS12 files to configure the IceSSL identity.
+
+- The default value of the `IceSSL.VerifyDepthMax` property is now 3 (it was previously 2). This allows certificate chains of 3 certificates (e.g: a Peer, CA and Root certificate chain).
- The certificate chain provided in the `IceSSL::ConnectionInfo` should now always include the root certificate if the chain could successfully be verified.
-- Added `verified` member to the `IceSSL::ConnectionInfo` class. This member indicates whether or not the peer certificate was successfully verified. This member is useful for clients which set IceSSL.VerifyPeer=0 to check if the server certificate could be verified or not. For server connections, the member should always be `true` since servers always reject invalid client certificates.
+- Added `verified` member to the `IceSSL::ConnectionInfo` class. This member indicates whether or not the peer certificate was successfully verified. This member is useful for clients which set `IceSSL.VerifyPeer=0` to check if the server certificate could be verified or not. For server connections, the member should always be `true` since servers always reject invalid client certificates.
- The Ice distribution now supports the Objective-C mapping on OS X.
diff --git a/config/PropertyNames.xml b/config/PropertyNames.xml
index c7992e322e6..2432f3bc19f 100644
--- a/config/PropertyNames.xml
+++ b/config/PropertyNames.xml
@@ -560,8 +560,9 @@ generated from the section label.
<section name="IceSSL">
<property name="Alias" />
- <property name="CertAuthDir" />
- <property name="CertAuthFile" />
+ <property name="CAs"/>
+ <property name="CertAuthDir" deprecated="true"/>
+ <property name="CertAuthFile" deprecated="true"/>
<property name="CertStore" />
<property name="CertFile" />
<property name="CertVerifier" />
@@ -573,10 +574,10 @@ generated from the section label.
<property name="DHParams" />
<property name="EntropyDaemon" />
<property name="FindCert" />
- <property name="FindCert.[any]" />
+ <property name="FindCert.[any]" deprecated="true"/>
<property name="ImportCert.[any]" deprecated="true"/>
<property name="InitOpenSSL" />
- <property name="KeyFile" />
+ <property name="KeyFile" deprecated="true"/>
<property name="KeySet"/>
<property name="Keychain"/>
<property name="KeychainPassword"/>
@@ -599,6 +600,7 @@ generated from the section label.
<property name="Truststore" />
<property name="TruststorePassword" />
<property name="TruststoreType" />
+ <property name="UsePlatformCAs" />
<property name="VerifyDepthMax" />
<property name="VerifyPeer" />
</section>
diff --git a/cpp/include/IceSSL/Plugin.h b/cpp/include/IceSSL/Plugin.h
index 5a7e7ea86cc..367fd73c5dd 100644
--- a/cpp/include/IceSSL/Plugin.h
+++ b/cpp/include/IceSSL/Plugin.h
@@ -55,14 +55,14 @@
#ifdef ICE_USE_OPENSSL
//
-// Pointer to an opaque SSL session context object. ssl_ctx_st is the
+// 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;
//
-// Pointer to an opaque certificate object. X509_st is the OpenSSL
+// Pointer to an opaque certificate object. X509_st is the OpenSSL
// type that represents a certificate.
//
typedef struct x509_st* X509CertificateRef;
@@ -185,7 +185,7 @@ class ICE_SSL_API PublicKey : public IceUtil::Shared
public:
~PublicKey();
-
+
//
// Retrieve the native public key value wrapped by this object.
//
@@ -202,7 +202,7 @@ private:
CertificatePtr _cert;
KeyRef _key;
-
+
};
typedef IceUtil::Handle<PublicKey> PublicKeyPtr;
@@ -282,7 +282,7 @@ class ICE_SSL_API Certificate : public IceUtil::Shared
public:
//
- // Construct a certificate using a native certificate.
+ // Construct a certificate using a native certificate.
//
// The Certificate class assumes ownership of the given native
// certificate.
@@ -321,7 +321,7 @@ public:
// 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
@@ -331,10 +331,10 @@ public:
// 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")
+ ICE_DEPRECATED_API("verify(const PublicKeyPtr&) is deprecated, use verify(const CertificatePtr&) instead")
bool verify(const PublicKeyPtr&) const;
#endif
-
+
//
// Return a string encoding of the certificate in PEM format.
// Raises CertificateEncodingException if an error occurs.
@@ -433,7 +433,7 @@ public:
//
// Retrieve the native X509 certificate value wrapped by this
- // object.
+ // object.
//
// The returned reference is only valid for the lifetime of this
// object. With SecureTransport you can increment the reference
@@ -470,6 +470,23 @@ public:
typedef IceUtil::Handle<NativeConnectionInfo> NativeConnectionInfoPtr;
//
+// WSSNativeConnectionInfo is an extension of IceSSL::WSSConnectionInfo
+// that provides access to native certificates.
+//
+class ICE_SSL_API WSSNativeConnectionInfo : public WSSConnectionInfo
+{
+public:
+
+ //
+ // The certificate chain. This may be empty if the peer did not
+ // supply a certificate. The peer's certificate (if any) is the
+ // first one in the chain.
+ //
+ std::vector<CertificatePtr> nativeCerts;
+};
+typedef IceUtil::Handle<WSSNativeConnectionInfo> WSSNativeConnectionInfoPtr;
+
+//
// An application can customize the certificate verification process
// by implementing the CertificateVerifier interface.
//
@@ -528,7 +545,7 @@ public:
// the plug-in is initialized.
//
virtual void setPasswordPrompt(const PasswordPromptPtr&) = 0;
-
+
#ifdef ICE_USE_OPENSSL
//
// Establish the OpenSSL context. This must be done before the
@@ -539,7 +556,7 @@ public:
// 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;
@@ -548,7 +565,7 @@ public:
// 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;
+ virtual SSL_CTX* getContext() = 0;
#endif
};
typedef IceUtil::Handle<Plugin> PluginPtr;
diff --git a/cpp/src/Ice/EndpointI.h b/cpp/src/Ice/EndpointI.h
index 8c9eb5fa055..df41372bd82 100644
--- a/cpp/src/Ice/EndpointI.h
+++ b/cpp/src/Ice/EndpointI.h
@@ -160,6 +160,38 @@ inline bool operator<(const EndpointI& l, const EndpointI& r)
return static_cast<const ::Ice::LocalObject&>(l) < static_cast<const ::Ice::LocalObject&>(r);
}
+template<typename T> class InfoI : public T
+{
+public:
+
+ InfoI(const EndpointIPtr& endpoint) : _endpoint(endpoint)
+ {
+ }
+
+ virtual Ice::Short
+ type() const
+ {
+ return _endpoint->type();
+ }
+
+ virtual bool
+ datagram() const
+ {
+ return _endpoint->datagram();
+ }
+
+ virtual bool
+ secure() const
+ {
+ return _endpoint->secure();
+ }
+
+private:
+
+ const EndpointIPtr _endpoint;
+};
+
+
}
#endif
diff --git a/cpp/src/Ice/OpaqueEndpointI.cpp b/cpp/src/Ice/OpaqueEndpointI.cpp
index e2f478c7231..c061eb0acfa 100644
--- a/cpp/src/Ice/OpaqueEndpointI.cpp
+++ b/cpp/src/Ice/OpaqueEndpointI.cpp
@@ -56,11 +56,11 @@ IceInternal::OpaqueEndpointI::OpaqueEndpointI(Short type, BasicStream* s) : _typ
namespace
{
-class InfoI : public Ice::OpaqueEndpointInfo
+class OpaqueEndpointInfoI : public Ice::OpaqueEndpointInfo
{
public:
- InfoI(Ice::Short type, const Ice::EncodingVersion& rawEncoding, const Ice::ByteSeq& rawByes);
+ OpaqueEndpointInfoI(Ice::Short type, const Ice::EncodingVersion& rawEncoding, const Ice::ByteSeq& rawByes);
virtual Ice::Short
type() const
@@ -89,7 +89,8 @@ private:
//
// COMPILERFIX: inlining this constructor causes crashes with gcc 4.0.1.
//
-InfoI::InfoI(Ice::Short type, const Ice::EncodingVersion& rawEncoding, const Ice::ByteSeq& rawBytes) :
+OpaqueEndpointInfoI::OpaqueEndpointInfoI(Ice::Short type, const Ice::EncodingVersion& rawEncoding,
+ const Ice::ByteSeq& rawBytes) :
Ice::OpaqueEndpointInfo(-1, false, rawEncoding, rawBytes),
_type(type)
{
@@ -106,7 +107,7 @@ IceInternal::OpaqueEndpointI::streamWrite(BasicStream* s) const
Ice::EndpointInfoPtr
IceInternal::OpaqueEndpointI::getInfo() const
{
- return new InfoI(_type, _rawEncoding, _rawBytes);
+ return new OpaqueEndpointInfoI(_type, _rawEncoding, _rawBytes);
}
Short
diff --git a/cpp/src/Ice/PropertyNames.cpp b/cpp/src/Ice/PropertyNames.cpp
index 95cf61169a8..11b035d47df 100644
--- a/cpp/src/Ice/PropertyNames.cpp
+++ b/cpp/src/Ice/PropertyNames.cpp
@@ -6,7 +6,7 @@
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
-// Generated by makeprops.py from file ./config/PropertyNames.xml, Thu Mar 19 17:54:51 2015
+// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Apr 28 17:34:50 2015
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -998,8 +998,9 @@ const IceInternal::PropertyArray
const IceInternal::Property IceSSLPropsData[] =
{
IceInternal::Property("IceSSL.Alias", false, 0),
- IceInternal::Property("IceSSL.CertAuthDir", false, 0),
- IceInternal::Property("IceSSL.CertAuthFile", false, 0),
+ IceInternal::Property("IceSSL.CAs", false, 0),
+ IceInternal::Property("IceSSL.CertAuthDir", true, 0),
+ IceInternal::Property("IceSSL.CertAuthFile", true, 0),
IceInternal::Property("IceSSL.CertStore", false, 0),
IceInternal::Property("IceSSL.CertFile", false, 0),
IceInternal::Property("IceSSL.CertVerifier", false, 0),
@@ -1011,10 +1012,10 @@ const IceInternal::Property IceSSLPropsData[] =
IceInternal::Property("IceSSL.DHParams", false, 0),
IceInternal::Property("IceSSL.EntropyDaemon", false, 0),
IceInternal::Property("IceSSL.FindCert", false, 0),
- IceInternal::Property("IceSSL.FindCert.*", false, 0),
+ IceInternal::Property("IceSSL.FindCert.*", true, 0),
IceInternal::Property("IceSSL.ImportCert.*", true, 0),
IceInternal::Property("IceSSL.InitOpenSSL", false, 0),
- IceInternal::Property("IceSSL.KeyFile", false, 0),
+ IceInternal::Property("IceSSL.KeyFile", true, 0),
IceInternal::Property("IceSSL.KeySet", false, 0),
IceInternal::Property("IceSSL.Keychain", false, 0),
IceInternal::Property("IceSSL.KeychainPassword", false, 0),
@@ -1037,6 +1038,7 @@ const IceInternal::Property IceSSLPropsData[] =
IceInternal::Property("IceSSL.Truststore", false, 0),
IceInternal::Property("IceSSL.TruststorePassword", false, 0),
IceInternal::Property("IceSSL.TruststoreType", false, 0),
+ IceInternal::Property("IceSSL.UsePlatformCAs", false, 0),
IceInternal::Property("IceSSL.VerifyDepthMax", false, 0),
IceInternal::Property("IceSSL.VerifyPeer", false, 0),
};
diff --git a/cpp/src/Ice/PropertyNames.h b/cpp/src/Ice/PropertyNames.h
index 28b47265af6..cf92a38d43f 100644
--- a/cpp/src/Ice/PropertyNames.h
+++ b/cpp/src/Ice/PropertyNames.h
@@ -6,7 +6,7 @@
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
-// Generated by makeprops.py from file ./config/PropertyNames.xml, Thu Mar 19 17:54:51 2015
+// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Apr 28 17:34:50 2015
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
diff --git a/cpp/src/Ice/TcpEndpointI.cpp b/cpp/src/Ice/TcpEndpointI.cpp
index 606a442e94a..5e744c394bb 100644
--- a/cpp/src/Ice/TcpEndpointI.cpp
+++ b/cpp/src/Ice/TcpEndpointI.cpp
@@ -62,39 +62,17 @@ IceInternal::TcpEndpointI::TcpEndpointI(const ProtocolInstancePtr& instance, Bas
EndpointInfoPtr
IceInternal::TcpEndpointI::getInfo() const
{
- class InfoI : public Ice::TCPEndpointInfo
- {
- public:
-
- InfoI(const EndpointIPtr& endpoint) : _endpoint(endpoint)
- {
- }
-
- virtual Ice::Short
- type() const
- {
- return _endpoint->type();
- }
-
- virtual bool
- datagram() const
- {
- return _endpoint->datagram();
- }
-
- virtual bool
- secure() const
- {
- return _endpoint->secure();
- }
-
- private:
-
- const EndpointIPtr _endpoint;
- };
+ TCPEndpointInfoPtr info = new InfoI<Ice::TCPEndpointInfo>(const_cast<TcpEndpointI*>(this));
+ fillEndpointInfo(info.get());
+ return info;
+}
- TCPEndpointInfoPtr info = new InfoI(const_cast<TcpEndpointI*>(this));
+EndpointInfoPtr
+IceInternal::TcpEndpointI::getWSInfo(const string& resource) const
+{
+ WSEndpointInfoPtr info = new InfoI<Ice::WSEndpointInfo>(const_cast<TcpEndpointI*>(this));
fillEndpointInfo(info.get());
+ info->resource = resource;
return info;
}
diff --git a/cpp/src/Ice/TcpEndpointI.h b/cpp/src/Ice/TcpEndpointI.h
index 2525d940168..d29498fc181 100644
--- a/cpp/src/Ice/TcpEndpointI.h
+++ b/cpp/src/Ice/TcpEndpointI.h
@@ -14,11 +14,12 @@
#include <Ice/IPEndpointI.h>
#include <Ice/EndpointFactory.h>
#include <Ice/Network.h> // for IceIternal::Address
+#include <Ice/WSEndpoint.h>
namespace IceInternal
{
-class TcpEndpointI : public IPEndpointI
+class TcpEndpointI : public IPEndpointI, public WSEndpointDelegate
{
public:
@@ -28,6 +29,7 @@ public:
TcpEndpointI(const ProtocolInstancePtr&, BasicStream*);
virtual Ice::EndpointInfoPtr getInfo() const;
+ virtual Ice::EndpointInfoPtr getWSInfo(const std::string&) const;
virtual Ice::Int timeout() const;
virtual EndpointIPtr timeout(Ice::Int) const;
diff --git a/cpp/src/Ice/TcpTransceiver.cpp b/cpp/src/Ice/TcpTransceiver.cpp
index ee022c639e9..4fa6d0bce2d 100644
--- a/cpp/src/Ice/TcpTransceiver.cpp
+++ b/cpp/src/Ice/TcpTransceiver.cpp
@@ -105,13 +105,17 @@ IceInternal::TcpTransceiver::toDetailedString() const
Ice::ConnectionInfoPtr
IceInternal::TcpTransceiver::getInfo() const
{
- Ice::TCPConnectionInfoPtr info = new Ice::TCPConnectionInfo();
- fdToAddressAndPort(_stream->fd(), info->localAddress, info->localPort, info->remoteAddress, info->remotePort);
- if(_stream->fd() != INVALID_SOCKET)
- {
- info->rcvSize = getRecvBufferSize(_stream->fd());
- info->sndSize = getSendBufferSize(_stream->fd());
- }
+ TCPConnectionInfoPtr info = new TCPConnectionInfo();
+ fillConnectionInfo(info);
+ return info;
+}
+
+Ice::ConnectionInfoPtr
+IceInternal::TcpTransceiver::getWSInfo(const Ice::HeaderDict& headers) const
+{
+ WSConnectionInfoPtr info = new WSConnectionInfo();
+ fillConnectionInfo(info);
+ info->headers = headers;
return info;
}
@@ -136,3 +140,13 @@ IceInternal::TcpTransceiver::~TcpTransceiver()
{
}
+void
+IceInternal::TcpTransceiver::fillConnectionInfo(const TCPConnectionInfoPtr& info) const
+{
+ fdToAddressAndPort(_stream->fd(), info->localAddress, info->localPort, info->remoteAddress, info->remotePort);
+ if(_stream->fd() != INVALID_SOCKET)
+ {
+ info->rcvSize = getRecvBufferSize(_stream->fd());
+ info->sndSize = getSendBufferSize(_stream->fd());
+ }
+}
diff --git a/cpp/src/Ice/TcpTransceiver.h b/cpp/src/Ice/TcpTransceiver.h
index ee6c57214d9..16845238ae4 100644
--- a/cpp/src/Ice/TcpTransceiver.h
+++ b/cpp/src/Ice/TcpTransceiver.h
@@ -14,6 +14,7 @@
#include <Ice/Transceiver.h>
#include <Ice/Network.h>
#include <Ice/StreamSocket.h>
+#include <Ice/WSTransceiver.h>
namespace IceInternal
{
@@ -21,7 +22,7 @@ namespace IceInternal
class TcpConnector;
class TcpAcceptor;
-class TcpTransceiver : public Transceiver
+class TcpTransceiver : public Transceiver, public WSTransceiverDelegate
{
public:
@@ -42,6 +43,7 @@ public:
virtual std::string toString() const;
virtual std::string toDetailedString() const;
virtual Ice::ConnectionInfoPtr getInfo() const;
+ virtual Ice::ConnectionInfoPtr getWSInfo(const Ice::HeaderDict&) const;
virtual void checkSendSize(const Buffer&);
virtual void setBufferSize(int rcvSize, int sndSize);
@@ -50,6 +52,8 @@ private:
TcpTransceiver(const ProtocolInstancePtr&, const StreamSocketPtr&);
virtual ~TcpTransceiver();
+ void fillConnectionInfo(const Ice::TCPConnectionInfoPtr&) const;
+
friend class TcpConnector;
friend class TcpAcceptor;
diff --git a/cpp/src/Ice/UdpEndpointI.cpp b/cpp/src/Ice/UdpEndpointI.cpp
index 6b0584fb2ba..019ff02a368 100644
--- a/cpp/src/Ice/UdpEndpointI.cpp
+++ b/cpp/src/Ice/UdpEndpointI.cpp
@@ -76,38 +76,7 @@ IceInternal::UdpEndpointI::UdpEndpointI(const ProtocolInstancePtr& instance, Bas
EndpointInfoPtr
IceInternal::UdpEndpointI::getInfo() const
{
- class InfoI : public Ice::UDPEndpointInfo
- {
- public:
-
- InfoI(const EndpointIPtr& endpoint) : _endpoint(endpoint)
- {
- }
-
- virtual Ice::Short
- type() const
- {
- return _endpoint->type();
- }
-
- virtual bool
- datagram() const
- {
- return _endpoint->datagram();
- }
-
- virtual bool
- secure() const
- {
- return _endpoint->secure();
- }
-
- private:
-
- const EndpointIPtr _endpoint;
- };
-
- Ice::UDPEndpointInfoPtr info = new InfoI(const_cast<UdpEndpointI*>(this));
+ Ice::UDPEndpointInfoPtr info = new InfoI<Ice::UDPEndpointInfo>(const_cast<UdpEndpointI*>(this));
fillEndpointInfo(info.get());
return info;
}
diff --git a/cpp/src/Ice/WSEndpoint.cpp b/cpp/src/Ice/WSEndpoint.cpp
index 54acdef77c4..d23b952b6b5 100644
--- a/cpp/src/Ice/WSEndpoint.cpp
+++ b/cpp/src/Ice/WSEndpoint.cpp
@@ -47,41 +47,8 @@ IceInternal::WSEndpoint::WSEndpoint(const ProtocolInstancePtr& instance, const E
Ice::EndpointInfoPtr
IceInternal::WSEndpoint::getInfo() const
{
- class InfoI : public WSEndpointInfo
- {
- public:
-
- InfoI(const EndpointIPtr& e) : _endpoint(e)
- {
- }
-
- virtual Short
- type() const
- {
- return _endpoint->type();
- }
-
- virtual bool
- datagram() const
- {
- return _endpoint->datagram();
- }
-
- virtual bool
- secure() const
- {
- return _endpoint->secure();
- }
-
- private:
-
- const EndpointIPtr _endpoint;
- };
-
- WSEndpointInfoPtr info = new InfoI(const_cast<WSEndpoint*>(this));
- _delegate->fillEndpointInfo(info.get());
- info->resource = _resource;
- return info;
+ assert(dynamic_cast<WSEndpointDelegate*>(_delegate.get()));
+ return dynamic_cast<WSEndpointDelegate*>(_delegate.get())->getWSInfo(_resource);
}
Ice::Short
diff --git a/cpp/src/Ice/WSEndpoint.h b/cpp/src/Ice/WSEndpoint.h
index 255bcf6cc1b..6fb08211a84 100644
--- a/cpp/src/Ice/WSEndpoint.h
+++ b/cpp/src/Ice/WSEndpoint.h
@@ -20,6 +20,17 @@
namespace IceInternal
{
+//
+// Delegate interface implemented by TcpEndpoint or IceSSL::Endpoint or any endpoint that WS can
+// delegate to.
+//
+class ICE_API WSEndpointDelegate : virtual public IceUtil::Shared
+{
+public:
+
+ virtual Ice::EndpointInfoPtr getWSInfo(const std::string&) const = 0;
+};
+
class WSEndpoint : public EndpointI
{
public:
diff --git a/cpp/src/Ice/WSTransceiver.cpp b/cpp/src/Ice/WSTransceiver.cpp
index d476b52a67e..08764fbc267 100644
--- a/cpp/src/Ice/WSTransceiver.cpp
+++ b/cpp/src/Ice/WSTransceiver.cpp
@@ -803,17 +803,8 @@ IceInternal::WSTransceiver::toDetailedString() const
Ice::ConnectionInfoPtr
IceInternal::WSTransceiver::getInfo() const
{
- IPConnectionInfoPtr di = IPConnectionInfoPtr::dynamicCast(_delegate->getInfo());
- assert(di);
- WSConnectionInfoPtr info = new WSConnectionInfo();
- info->localAddress = di->localAddress;
- info->localPort = di->localPort;
- info->remoteAddress = di->remoteAddress;
- info->remotePort = di->remotePort;
- info->rcvSize = di->rcvSize;
- info->sndSize = di->sndSize;
- info->headers = _parser->getHeaders();
- return info;
+ assert(dynamic_cast<WSTransceiverDelegate*>(_delegate.get()));
+ return dynamic_cast<WSTransceiverDelegate*>(_delegate.get())->getWSInfo(_parser->getHeaders());
}
void
diff --git a/cpp/src/Ice/WSTransceiver.h b/cpp/src/Ice/WSTransceiver.h
index 2273f51a683..c3d8d760e22 100644
--- a/cpp/src/Ice/WSTransceiver.h
+++ b/cpp/src/Ice/WSTransceiver.h
@@ -24,6 +24,17 @@ namespace IceInternal
class ConnectorI;
class AcceptorI;
+//
+// Delegate interface implemented by TcpTransceiver or IceSSL::Transceiver or any transport that WS can
+// delegate to.
+//
+class ICE_API WSTransceiverDelegate : virtual public IceUtil::Shared
+{
+public:
+
+ virtual Ice::ConnectionInfoPtr getWSInfo(const Ice::HeaderDict&) const = 0;
+};
+
class WSTransceiver : public Transceiver
{
public:
diff --git a/cpp/src/Ice/winrt/StreamEndpointI.cpp b/cpp/src/Ice/winrt/StreamEndpointI.cpp
index 60aca535bdd..bdd3dc0295d 100644
--- a/cpp/src/Ice/winrt/StreamEndpointI.cpp
+++ b/cpp/src/Ice/winrt/StreamEndpointI.cpp
@@ -44,43 +44,6 @@ createIceSSL(const CommunicatorPtr& com, const string&, const StringSeq&)
}
-namespace
-{
-
-template<class T> class InfoI : public T
-{
-public:
-
- InfoI(const ProtocolInstancePtr& instance, Ice::Int to, bool comp, const string& host, Ice::Int port) :
- T(to, comp, host, port, ""), _instance(instance)
- {
- }
-
- virtual Ice::Short
- type() const
- {
- return _instance->type();
- }
-
- virtual bool
- datagram() const
- {
- return false;
- }
-
- virtual bool
- secure() const
- {
- return _instance->secure();
- }
-
-private:
-
- ProtocolInstancePtr _instance;
-};
-
-}
-
IceUtil::Shared* IceInternal::upCast(StreamEndpointI* p) { return p; }
IceInternal::StreamEndpointI::StreamEndpointI(const ProtocolInstancePtr& instance, const string& ho, Int po, Int ti,
@@ -110,14 +73,37 @@ IceInternal::StreamEndpointI::StreamEndpointI(const ProtocolInstancePtr& instanc
EndpointInfoPtr
IceInternal::StreamEndpointI::getInfo() const
{
+ IPEndpointInfoPtr info;
+ if(_instance->secure())
+ {
+ info = new InfoI<IceSSL::EndpointInfo>(const_cast<StreamEndpointI*>(this));
+ }
+ else
+ {
+ info = new InfoI<Ice::TCPEndpointInfo>(const_cast<StreamEndpointI*>(this));
+ }
+ fillEndpointInfo(info.get());
+ return info;
+}
+
+EndpointInfoPtr
+IceInternal::StreamEndpointI::getWSInfo(const string& resource) const
+{
+ IPEndpointInfoPtr info;
if(_instance->secure())
{
- return new InfoI<IceSSL::EndpointInfo>(_instance, _timeout, _compress, _host, _port);
+ IceSSL::WSSEndpointInfoPtr i = new InfoI<IceSSL::WSSEndpointInfo>(const_cast<StreamEndpointI*>(this));
+ i->resource = resource;
+ info = i;
}
else
{
- return new InfoI<Ice::TCPEndpointInfo>(_instance, _timeout, _compress, _host, _port);
+ Ice::WSEndpointInfoPtr i = new InfoI<Ice::WSEndpointInfo>(const_cast<StreamEndpointI*>(this));
+ i->resource = resource;
+ info = i;
}
+ fillEndpointInfo(info.get());
+ return info;
}
Int
@@ -180,8 +166,7 @@ IceInternal::StreamEndpointI::datagram() const
bool
IceInternal::StreamEndpointI::secure() const
{
- return _instance->type() == IceSSL::EndpointType ||
- _instance->type() == WSSEndpointType;
+ return _instance->type() == IceSSL::EndpointType || _instance->type() == WSSEndpointType;
}
TransceiverPtr
diff --git a/cpp/src/Ice/winrt/StreamEndpointI.h b/cpp/src/Ice/winrt/StreamEndpointI.h
index 8e77b2d1397..d3f9f1bbe66 100644
--- a/cpp/src/Ice/winrt/StreamEndpointI.h
+++ b/cpp/src/Ice/winrt/StreamEndpointI.h
@@ -13,13 +13,14 @@
#include <IceUtil/Config.h>
#include <Ice/IPEndpointI.h>
#include <Ice/EndpointFactory.h>
+#include <Ice/WSEndpoint.h>
#include <Ice/Network.h> // for IceIternal::Address
#include <Ice/winrt/StreamF.h>
namespace IceInternal
{
-class StreamEndpointI : public IPEndpointI
+class StreamEndpointI : public IPEndpointI, WSEndpointDelegate
{
public:
@@ -28,6 +29,7 @@ public:
StreamEndpointI(const ProtocolInstancePtr&, BasicStream*);
virtual Ice::EndpointInfoPtr getInfo() const;
+ virtual Ice::EndpointInfoPtr getWSInfo(const std::string&) const;
virtual Ice::Int timeout() const;
virtual EndpointIPtr timeout(Ice::Int) const;
diff --git a/cpp/src/Ice/winrt/StreamTransceiver.cpp b/cpp/src/Ice/winrt/StreamTransceiver.cpp
index 3c4a30f8cc6..7cf9946ed9c 100644
--- a/cpp/src/Ice/winrt/StreamTransceiver.cpp
+++ b/cpp/src/Ice/winrt/StreamTransceiver.cpp
@@ -302,12 +302,29 @@ IceInternal::StreamTransceiver::getInfo() const
{
info = new Ice::TCPConnectionInfo();
}
- fdToAddressAndPort(_fd, info->localAddress, info->localPort, info->remoteAddress, info->remotePort);
- info->rcvSize = getRecvBufferSize(_fd);
- info->sndSize = getSendBufferSize(_fd);
+ fillConnectionInfo(info);
return info;
}
+Ice::ConnectionInfoPtr
+IceInternal::StreamTransceiver::getWSInfo(const Ice::HeaderDict& headers) const
+{
+ if(_instance->secure())
+ {
+ IceSSL::WSSConnectionInfoPtr info = new IceSSL::WSSConnectionInfo();
+ fillConnectionInfo(info);
+ info->headers = headers;
+ return info;
+ }
+ else
+ {
+ Ice::WSConnectionInfoPtr info = new Ice::WSConnectionInfo();
+ fillConnectionInfo(info);
+ info->headers = headers;
+ return info;
+ }
+}
+
void
IceInternal::StreamTransceiver::checkSendSize(const Buffer&)
{
@@ -387,3 +404,12 @@ IceInternal::StreamTransceiver::checkIfErrorOrCompleted(SocketOperation op, IAsy
return true; // Prevent compiler warning.
}
}
+
+void
+IceInternal::StreamTransceiver::fillConnectionInfo(const Ice::IPConnectionInfoPtr& info) const
+{
+ fdToAddressAndPort(_fd, info->localAddress, info->localPort, info->remoteAddress, info->remotePort);
+ info->rcvSize = getRecvBufferSize(_fd);
+ info->sndSize = getSendBufferSize(_fd);
+}
+
diff --git a/cpp/src/Ice/winrt/StreamTransceiver.h b/cpp/src/Ice/winrt/StreamTransceiver.h
index 4a32cfd10e8..6d7effd8e49 100644
--- a/cpp/src/Ice/winrt/StreamTransceiver.h
+++ b/cpp/src/Ice/winrt/StreamTransceiver.h
@@ -13,6 +13,7 @@
#include <Ice/ProtocolInstanceF.h>
#include <Ice/Transceiver.h>
#include <Ice/Network.h>
+#include <Ice/WSTransceiver.h>
namespace IceInternal
{
@@ -20,7 +21,7 @@ namespace IceInternal
class StreamConnector;
class StreamAcceptor;
-class StreamTransceiver : public Transceiver, public NativeInfo
+class StreamTransceiver : public Transceiver, public NativeInfo, public WSTransceiverDelegate
{
enum State
{
@@ -49,6 +50,7 @@ public:
virtual std::string toString() const;
virtual std::string toDetailedString() const;
virtual Ice::ConnectionInfoPtr getInfo() const;
+ virtual Ice::ConnectionInfoPtr getWSInfo(const Ice::HeaderDict&) const;
virtual void checkSendSize(const Buffer&);
virtual void setBufferSize(int rcvSize, int sndSize);
@@ -58,8 +60,8 @@ private:
virtual ~StreamTransceiver();
void connect(const Address&);
-
bool checkIfErrorOrCompleted(SocketOperation, Windows::Foundation::IAsyncInfo^, int = 0);
+ void fillConnectionInfo(const Ice::IPConnectionInfoPtr&) const;
friend class StreamConnector;
friend class StreamAcceptor;
diff --git a/cpp/src/IceSSL/EndpointI.cpp b/cpp/src/IceSSL/EndpointI.cpp
index 124c63dc645..6893db0e117 100644
--- a/cpp/src/IceSSL/EndpointI.cpp
+++ b/cpp/src/IceSSL/EndpointI.cpp
@@ -53,39 +53,17 @@ IceSSL::EndpointI::EndpointI(const InstancePtr& instance, IceInternal::BasicStre
Ice::EndpointInfoPtr
IceSSL::EndpointI::getInfo() const
{
- class InfoI : public EndpointInfo
- {
- public:
-
- InfoI(const IceInternal::EndpointIPtr& endpoint) : _endpoint(endpoint)
- {
- }
-
- virtual Ice::Short
- type() const
- {
- return _endpoint->type();
- }
-
- virtual bool
- datagram() const
- {
- return _endpoint->datagram();
- }
-
- virtual bool
- secure() const
- {
- return _endpoint->secure();
- }
-
- private:
-
- const IceInternal::EndpointIPtr _endpoint;
- };
+ EndpointInfoPtr info = new IceInternal::InfoI<EndpointInfo>(const_cast<EndpointI*>(this));
+ fillEndpointInfo(info.get());
+ return info;
+}
- IPEndpointInfoPtr info = new InfoI(const_cast<EndpointI*>(this));
+Ice::EndpointInfoPtr
+IceSSL::EndpointI::getWSInfo(const string& resource) const
+{
+ WSSEndpointInfoPtr info = new IceInternal::InfoI<WSSEndpointInfo>(const_cast<EndpointI*>(this));
fillEndpointInfo(info.get());
+ info->resource = resource;
return info;
}
diff --git a/cpp/src/IceSSL/EndpointI.h b/cpp/src/IceSSL/EndpointI.h
index b3a154a6ad4..74f04d1665a 100644
--- a/cpp/src/IceSSL/EndpointI.h
+++ b/cpp/src/IceSSL/EndpointI.h
@@ -12,6 +12,7 @@
#include <Ice/IPEndpointI.h>
#include <Ice/EndpointFactory.h>
+#include <Ice/WSEndpoint.h>
#include <IceSSL/InstanceF.h>
#include <IceSSL/EndpointInfo.h>
#include <Ice/Network.h>
@@ -19,7 +20,7 @@
namespace IceSSL
{
-class EndpointI : public IceInternal::IPEndpointI
+class EndpointI : public IceInternal::IPEndpointI, public IceInternal::WSEndpointDelegate
{
public:
@@ -29,6 +30,7 @@ public:
EndpointI(const InstancePtr&, IceInternal::BasicStream*);
virtual Ice::EndpointInfoPtr getInfo() const;
+ virtual Ice::EndpointInfoPtr getWSInfo(const std::string&) const;
virtual Ice::Int timeout() const;
virtual IceInternal::EndpointIPtr timeout(Ice::Int) const;
diff --git a/cpp/src/IceSSL/OpenSSLEngine.cpp b/cpp/src/IceSSL/OpenSSLEngine.cpp
index c47e19eb99f..cc617008547 100644
--- a/cpp/src/IceSSL/OpenSSLEngine.cpp
+++ b/cpp/src/IceSSL/OpenSSLEngine.cpp
@@ -395,8 +395,22 @@ OpenSSLEngine::initialize()
// Establish the location of CA certificates.
//
{
- string caFile = properties->getProperty(propPrefix + "CertAuthFile");
- string caDir = properties->getPropertyWithDefault(propPrefix + "CertAuthDir", defaultDir);
+ string caFile = properties->getProperty(propPrefix + "CAs");
+ string caDir;
+ if(!caFile.empty())
+ {
+ if(!checkPath(caFile, defaultDir, false) && checkPath(caFile, defaultDir, true))
+ {
+ caDir = caFile;
+ caFile = "";
+ }
+ }
+ else
+ {
+ // Deprecated properties
+ caFile = properties->getProperty(propPrefix + "CertAuthFile");
+ caDir = properties->getProperty(propPrefix + "CertAuthDir");
+ }
const char* file = 0;
const char* dir = 0;
if(!caFile.empty())
@@ -452,6 +466,10 @@ OpenSSLEngine::initialize()
throw PluginInitializationException(__FILE__, __LINE__, msg);
}
}
+ else if(properties->getPropertyAsInt("IceSSL.UsePlatformCAs") > 0)
+ {
+ SSL_CTX_set_default_verify_paths(_ctx);
+ }
}
//
diff --git a/cpp/src/IceSSL/OpenSSLTransceiverI.cpp b/cpp/src/IceSSL/OpenSSLTransceiverI.cpp
index bed46b3b8b4..2b40c62a4b6 100644
--- a/cpp/src/IceSSL/OpenSSLTransceiverI.cpp
+++ b/cpp/src/IceSSL/OpenSSLTransceiverI.cpp
@@ -276,11 +276,12 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
throw ex;
}
}
- else if(_info)
+ else
{
- _info->verified = true;
+ _verified = true;
}
- _engine->verifyPeer(_stream->fd(), _host, getNativeConnectionInfo());
+
+ _engine->verifyPeer(_stream->fd(), _host, NativeConnectionInfoPtr::dynamicCast(getInfo()));
if(_engine->securityTraceLevel() >= 1)
{
@@ -573,7 +574,18 @@ IceSSL::TransceiverI::toDetailedString() const
Ice::ConnectionInfoPtr
IceSSL::TransceiverI::getInfo() const
{
- return getNativeConnectionInfo();
+ NativeConnectionInfoPtr info = new NativeConnectionInfo();
+ fillConnectionInfo(info, info->nativeCerts);
+ return info;
+}
+
+Ice::ConnectionInfoPtr
+IceSSL::TransceiverI::getWSInfo(const Ice::HeaderDict& headers) const
+{
+ WSSNativeConnectionInfoPtr info = new WSSNativeConnectionInfo();
+ fillConnectionInfo(info, info->nativeCerts);
+ info->headers = headers;
+ return info;
}
void
@@ -609,17 +621,18 @@ IceSSL::TransceiverI::verifyCallback(int ok, X509_STORE_CTX* c)
}
//
- // Initialize the native connection info with the verified
- // certificate chain. SSL_get_peer_cert_chain doesn't return the
- // verified chain, it returns the chain sent by the peer.
+ // Initialize the native certs with the verified certificate chain. SSL_get_peer_cert_chain
+ // doesn't return the verified chain, it returns the chain sent by the peer.
//
- try
- {
- _info = initNativeConnectionInfo(c);
- }
- catch(const Ice::Exception&)
+ STACK_OF(X509)* chain = X509_STORE_CTX_get1_chain(c);
+ if(chain != 0)
{
- // Ignore
+ _nativeCerts.clear();
+ for(int i = 0; i < sk_X509_num(chain); ++i)
+ {
+ _nativeCerts.push_back(new Certificate(X509_dup(sk_X509_value(chain, i))));
+ }
+ sk_X509_pop_free(chain, X509_free);
}
//
@@ -639,6 +652,7 @@ IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance, const IceInterna
_adapterName(incoming ? hostOrAdapterName : ""),
_incoming(incoming),
_stream(stream),
+ _verified(false),
_ssl(0)
{
}
@@ -647,20 +661,9 @@ IceSSL::TransceiverI::~TransceiverI()
{
}
-NativeConnectionInfoPtr
-IceSSL::TransceiverI::getNativeConnectionInfo() const
-{
- if(!_info)
- {
- return initNativeConnectionInfo(0);
- }
- return _info;
-}
-
-NativeConnectionInfoPtr
-IceSSL::TransceiverI::initNativeConnectionInfo(X509_STORE_CTX* ctx) const
+void
+IceSSL::TransceiverI::fillConnectionInfo(const ConnectionInfoPtr& info, std::vector<CertificatePtr>& nativeCerts) const
{
- NativeConnectionInfoPtr info = new NativeConnectionInfo();
IceInternal::fdToAddressAndPort(_stream->fd(), info->localAddress, info->localPort, info->remoteAddress,
info->remotePort);
if(_stream->fd() != INVALID_SOCKET)
@@ -670,57 +673,11 @@ IceSSL::TransceiverI::initNativeConnectionInfo(X509_STORE_CTX* ctx) const
}
info->adapterName = _adapterName;
info->incoming = _incoming;
- info->verified = false;
-
- STACK_OF(X509)* chain = 0;
- if(ctx)
- {
- //
- // This is called from the verify callback where OpenSSL provides the verified
- // certificate chain.
- //
- chain = X509_STORE_CTX_get1_chain(ctx);
- }
-
- if(chain == 0 && _ssl != 0)
- {
- //
- // On the client side, SSL_get_peer_cert_chain returns the entire chain of certs.
- // On the server side, the peer certificate must be obtained separately.
- //
- // Since we have no clear idea whether the connection is server or client side,
- // the peer certificate is obtained separately and compared against the first
- // certificate in the chain. If they are not the same, it is added to the chain.
- //
- X509* cert = SSL_get_peer_certificate(_ssl);
- chain = SSL_get_peer_cert_chain(_ssl);
- if(cert != 0 && (chain == 0 || sk_X509_num(chain) == 0 || cert != sk_X509_value(chain, 0)))
- {
- CertificatePtr certificate = new Certificate(cert);
- info->nativeCerts.push_back(certificate);
- info->certs.push_back(certificate->encode());
- }
- else
- {
- X509_free(cert);
- }
- }
-
- if(chain != 0)
+ info->verified = _verified;
+ nativeCerts = _nativeCerts;
+ for(vector<CertificatePtr>::const_iterator p = _nativeCerts.begin(); p != _nativeCerts.end(); ++p)
{
- for(int i = 0; i < sk_X509_num(chain); ++i)
- {
- //
- // Duplicate the certificate since the stack comes straight from the SSL connection.
- //
- CertificatePtr certificate = new Certificate(X509_dup(sk_X509_value(chain, i)));
- info->nativeCerts.push_back(certificate);
- info->certs.push_back(certificate->encode());
- }
- if(ctx)
- {
- sk_X509_pop_free(chain, X509_free);
- }
+ info->certs.push_back((*p)->encode());
}
if(_ssl != 0)
{
@@ -728,7 +685,6 @@ IceSSL::TransceiverI::initNativeConnectionInfo(X509_STORE_CTX* ctx) const
}
info->adapterName = _adapterName;
info->incoming = _incoming;
- return info;
}
#endif
diff --git a/cpp/src/IceSSL/OpenSSLTransceiverI.h b/cpp/src/IceSSL/OpenSSLTransceiverI.h
index 85fa55d4548..a64e932a0f5 100644
--- a/cpp/src/IceSSL/OpenSSLTransceiverI.h
+++ b/cpp/src/IceSSL/OpenSSLTransceiverI.h
@@ -19,6 +19,7 @@
#include <Ice/Transceiver.h>
#include <Ice/Network.h>
#include <Ice/StreamSocket.h>
+#include <Ice/WSTransceiver.h>
#ifdef ICE_USE_OPENSSL
@@ -31,7 +32,7 @@ namespace IceSSL
class ConnectorI;
class AcceptorI;
-class TransceiverI : public IceInternal::Transceiver
+class TransceiverI : public IceInternal::Transceiver, public IceInternal::WSTransceiverDelegate
{
public:
@@ -46,6 +47,7 @@ public:
virtual std::string toString() const;
virtual std::string toDetailedString() const;
virtual Ice::ConnectionInfoPtr getInfo() const;
+ virtual Ice::ConnectionInfoPtr getWSInfo(const Ice::HeaderDict&) const;
virtual void checkSendSize(const IceInternal::Buffer&);
virtual void setBufferSize(int rcvSize, int sndSize);
@@ -56,8 +58,7 @@ private:
TransceiverI(const InstancePtr&, const IceInternal::StreamSocketPtr&, const std::string&, bool);
virtual ~TransceiverI();
- virtual NativeConnectionInfoPtr getNativeConnectionInfo() const;
- NativeConnectionInfoPtr initNativeConnectionInfo(X509_STORE_CTX*) const;
+ void fillConnectionInfo(const ConnectionInfoPtr&, std::vector<CertificatePtr>&) const;
friend class ConnectorI;
friend class AcceptorI;
@@ -68,7 +69,8 @@ private:
const std::string _adapterName;
const bool _incoming;
const IceInternal::StreamSocketPtr _stream;
- NativeConnectionInfoPtr _info;
+ bool _verified;
+ std::vector<CertificatePtr> _nativeCerts;
SSL* _ssl;
};
diff --git a/cpp/src/IceSSL/SChannelEngine.cpp b/cpp/src/IceSSL/SChannelEngine.cpp
index efb3b099ce3..ddc47619373 100644
--- a/cpp/src/IceSSL/SChannelEngine.cpp
+++ b/cpp/src/IceSSL/SChannelEngine.cpp
@@ -56,7 +56,7 @@ struct CertChainEngineConfig
# endif
void
-addCertificateToStore(const string& file, HCERTSTORE store, PCCERT_CONTEXT* cert = 0)
+addCertificatesToStore(const string& file, HCERTSTORE store, PCCERT_CONTEXT* cert = 0)
{
vector<char> buffer;
readFile(file, buffer);
@@ -65,29 +65,50 @@ addCertificateToStore(const string& file, HCERTSTORE store, PCCERT_CONTEXT* cert
throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: certificate file is empty:\n" + file);
}
- vector<BYTE> outBuffer;
- outBuffer.resize(buffer.size());
- DWORD outLength = static_cast<DWORD>(outBuffer.size());
-
- if(!CryptStringToBinary(&buffer[0], static_cast<DWORD>(buffer.size()), CRYPT_STRING_BASE64HEADER,
- &outBuffer[0], &outLength, 0, 0))
+ string strbuf(buffer.begin(), buffer.end());
+ string::size_type size, startpos, endpos = 0;
+ bool first = true;
+ while(true)
{
- //
- // Base64 data should always be bigger than binary
- //
- assert(GetLastError() != ERROR_MORE_DATA);
- throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: error decoding certificate:\n" + lastErrorToString());
- }
+ startpos = strbuf.find("-----BEGIN CERTIFICATE-----", endpos);
+ if(startpos != string::npos)
+ {
+ endpos = strbuf.find("-----END CERTIFICATE-----", startpos);
+ size = endpos - startpos + sizeof("-----END CERTIFICATE-----");
+ }
+ else if(first)
+ {
+ startpos = 0;
+ endpos = string::npos;
+ size = strbuf.size();
+ }
+ else
+ {
+ break;
+ }
- if(!CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &outBuffer[0],
- outLength, CERT_STORE_ADD_NEW, cert))
- {
- if(GetLastError() != static_cast<DWORD>(CRYPT_E_EXISTS))
+ vector<BYTE> outBuffer;
+ outBuffer.resize(size);
+ DWORD outLength = static_cast<DWORD>(outBuffer.size());
+ if(!CryptStringToBinary(&buffer[startpos], static_cast<DWORD>(size), CRYPT_STRING_ANY, &outBuffer[0],
+ &outLength, 0, 0))
{
+ assert(GetLastError() != ERROR_MORE_DATA); // Base64 data should always be bigger than binary
throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: error decoding certificate:\n" + lastErrorToString());
+ "IceSSL: error decoding certificate:\n" + lastErrorToString());
+ }
+
+ if(!CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &outBuffer[0],
+ outLength, CERT_STORE_ADD_NEW, first ? cert : 0))
+ {
+ if(GetLastError() != static_cast<DWORD>(CRYPT_E_EXISTS))
+ {
+ throw PluginInitializationException(__FILE__, __LINE__,
+ "IceSSL: error decoding certificate:\n" + lastErrorToString());
+ }
}
+
+ first = false;
}
}
@@ -244,8 +265,12 @@ SChannelEngine::initialize()
//
// Create trusted CA store with contents of CertAuthFile
//
- string caFile = properties->getProperty(prefix + "CertAuthFile");
- if(!caFile.empty())
+ string caFile = properties->getProperty(prefix + "CAs");
+ if(caFile.empty())
+ {
+ caFile = properties->getProperty(prefix + "CertAuthFile");
+ }
+ if(!caFile.empty() || properties->getPropertyAsInt("IceSSL.UsePlatformCAs") <= 0)
{
_rootStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 0, 0);
if(!_rootStore)
@@ -253,15 +278,20 @@ SChannelEngine::initialize()
throw PluginInitializationException(__FILE__, __LINE__,
"IceSSL: error creating in memory certificate store:\n" + lastErrorToString());
}
-
+ }
+ if(!caFile.empty())
+ {
if(!checkPath(caFile, defaultDir, false))
{
throw PluginInitializationException(__FILE__, __LINE__,
"IceSSL: CA certificate file not found:\n" + caFile);
}
- addCertificateToStore(caFile, _rootStore);
+ addCertificatesToStore(caFile, _rootStore);
+ }
+ if(_rootStore)
+ {
//
// Create a chain engine that uses our Trusted Root Store
//
@@ -410,26 +440,8 @@ SChannelEngine::initialize()
"IceSSL: certificate error:\n" + lastErrorToString());
}
- //
- // If we found a certificate, add it to a new memory store. We
- // can't use directly the certificate context from the PFX
- // store: while it works for certificates without
- // intermediates, it doesn't if the certificate has
- // intermediates, the intermediates certificates aren't being
- // sent.
- //
- HCERTSTORE newStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 0, 0);
- PCCERT_CONTEXT newCert;
- if(!CertAddCertificateContextToStore(newStore, cert, CERT_STORE_ADD_ALWAYS, &newCert))
- {
- CertCloseStore(newStore, 0);
- throw PluginInitializationException(__FILE__, __LINE__,
- "IceSSL: certificate error:\n" + lastErrorToString());
- }
- _certs.push_back(newCert);
- _stores.push_back(newStore);
- CertFreeCertificateContext(cert);
- CertCloseStore(store, 0);
+ _certs.push_back(cert);
+ _stores.push_back(store);
continue;
}
@@ -560,7 +572,7 @@ SChannelEngine::initialize()
"store:\n" + lastErrorToString());
}
- addCertificateToStore(certFile, store, &cert);
+ addCertificatesToStore(certFile, store, &cert);
//
// Associate key & certificate
@@ -705,6 +717,17 @@ SChannelEngine::newCredentialsHandle(bool incoming)
// the root certificate either way.
//
cred.dwFlags = SCH_CRED_NO_SYSTEM_MAPPER;
+
+ //
+ // There's no way to prevent SChannel from sending "CA names" to the
+ // client. Recent Windows versions don't CA names but older ones do
+ // send all the trusted root CA names. We provide the root store to
+ // ensure that for these older Windows versions, we also include the
+ // CA names of your trusted roots. IceSSL for Java will only send a
+ // client certificate if the client certificate CA matches one of the
+ // CA names sent by the server.
+ //
+ cred.hRootStore = _rootStore;
}
else
{
diff --git a/cpp/src/IceSSL/SChannelTransceiverI.cpp b/cpp/src/IceSSL/SChannelTransceiverI.cpp
index 74d9d840ed2..126a966f6b3 100644
--- a/cpp/src/IceSSL/SChannelTransceiverI.cpp
+++ b/cpp/src/IceSSL/SChannelTransceiverI.cpp
@@ -715,7 +715,7 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
}
}
- _engine->verifyPeer(_stream->fd(), _host, getNativeConnectionInfo());
+ _engine->verifyPeer(_stream->fd(), _host, NativeConnectionInfoPtr::dynamicCast(getInfo()));
_state = StateHandshakeComplete;
if(_instance->engine()->securityTraceLevel() >= 1)
@@ -948,7 +948,18 @@ IceSSL::TransceiverI::toDetailedString() const
Ice::ConnectionInfoPtr
IceSSL::TransceiverI::getInfo() const
{
- return getNativeConnectionInfo();
+ NativeConnectionInfoPtr info = new NativeConnectionInfo();
+ fillConnectionInfo(info, info->nativeCerts);
+ return info;
+}
+
+Ice::ConnectionInfoPtr
+IceSSL::TransceiverI::getWSInfo(const Ice::HeaderDict& headers) const
+{
+ WSSNativeConnectionInfoPtr info = new WSSNativeConnectionInfo();
+ fillConnectionInfo(info, info->nativeCerts);
+ info->headers = headers;
+ return info;
}
void
@@ -984,10 +995,9 @@ IceSSL::TransceiverI::~TransceiverI()
{
}
-NativeConnectionInfoPtr
-IceSSL::TransceiverI::getNativeConnectionInfo() const
+void
+IceSSL::TransceiverI::fillConnectionInfo(const ConnectionInfoPtr& info, vector<CertificatePtr>& nativeCerts) const
{
- NativeConnectionInfoPtr info = new NativeConnectionInfo();
IceInternal::fdToAddressAndPort(_stream->fd(), info->localAddress, info->localPort, info->remoteAddress,
info->remotePort);
if(_stream->fd() != INVALID_SOCKET)
@@ -1032,7 +1042,7 @@ IceSSL::TransceiverI::getNativeConnectionInfo() const
}
CertificatePtr certificate = new Certificate(cc);
- info->nativeCerts.push_back(certificate);
+ nativeCerts.push_back(certificate);
info->certs.push_back(certificate->encode());
}
CertFreeCertificateChain(certChain);
@@ -1059,7 +1069,6 @@ IceSSL::TransceiverI::getNativeConnectionInfo() const
info->adapterName = _adapterName;
info->incoming = _incoming;
- return info;
}
bool
diff --git a/cpp/src/IceSSL/SChannelTransceiverI.h b/cpp/src/IceSSL/SChannelTransceiverI.h
index a029cf596bf..f60d54ff6d6 100644
--- a/cpp/src/IceSSL/SChannelTransceiverI.h
+++ b/cpp/src/IceSSL/SChannelTransceiverI.h
@@ -19,6 +19,7 @@
#include <Ice/Network.h>
#include <Ice/Buffer.h>
#include <Ice/StreamSocket.h>
+#include <Ice/WSTransceiver.h>
#ifdef ICE_USE_SCHANNEL
@@ -42,7 +43,7 @@ namespace IceSSL
class ConnectorI;
class AcceptorI;
-class TransceiverI : public IceInternal::Transceiver
+class TransceiverI : public IceInternal::Transceiver, public IceInternal::WSTransceiverDelegate
{
public:
@@ -63,6 +64,7 @@ public:
virtual std::string toString() const;
virtual std::string toDetailedString() const;
virtual Ice::ConnectionInfoPtr getInfo() const;
+ virtual Ice::ConnectionInfoPtr getWSInfo(const Ice::HeaderDict&) const;
virtual void checkSendSize(const IceInternal::Buffer&);
virtual void setBufferSize(int rcvSize, int sndSize);
@@ -71,7 +73,7 @@ private:
TransceiverI(const InstancePtr&, const IceInternal::StreamSocketPtr&, const std::string&, bool);
virtual ~TransceiverI();
- virtual NativeConnectionInfoPtr getNativeConnectionInfo() const;
+ void fillConnectionInfo(const ConnectionInfoPtr&, std::vector<CertificatePtr>&) const;
IceInternal::SocketOperation sslHandshake();
diff --git a/cpp/src/IceSSL/SecureTransportEngine.cpp b/cpp/src/IceSSL/SecureTransportEngine.cpp
index 9264bf252aa..a7102f64279 100644
--- a/cpp/src/IceSSL/SecureTransportEngine.cpp
+++ b/cpp/src/IceSSL/SecureTransportEngine.cpp
@@ -905,7 +905,11 @@ IceSSL::SecureTransportEngine::initialize()
//
try
{
- string caFile = properties->getProperty("IceSSL.CertAuthFile");
+ string caFile = properties->getProperty("IceSSL.CAs");
+ if(caFile.empty())
+ {
+ caFile = properties->getProperty("IceSSL.CertAuthFile");
+ }
if(!caFile.empty())
{
if(!checkPath(caFile, defaultDir, false))
@@ -915,6 +919,11 @@ IceSSL::SecureTransportEngine::initialize()
}
_certificateAuthorities = loadCACertificates(caFile);
}
+ else if(properties->getPropertyAsInt("IceSSL.UsePlatformCAs") <= 0)
+ {
+ // Setup an empty list of Root CAs to not use the system root CAs.
+ _certificateAuthorities = CFArrayCreate(0, 0, 0, 0);
+ }
}
catch(const CertificateReadException& ce)
{
diff --git a/cpp/src/IceSSL/SecureTransportTransceiverI.cpp b/cpp/src/IceSSL/SecureTransportTransceiverI.cpp
index 3ff588cd9e2..211a4ca3fe8 100644
--- a/cpp/src/IceSSL/SecureTransportTransceiverI.cpp
+++ b/cpp/src/IceSSL/SecureTransportTransceiverI.cpp
@@ -258,7 +258,7 @@ IceSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::B
<< "remote address = " << desc << "\n" << errorToString(err);
throw ProtocolException(__FILE__, __LINE__, os.str());
}
- _engine->verifyPeer(_stream->fd(), _host, getNativeConnectionInfo());
+ _engine->verifyPeer(_stream->fd(), _host, NativeConnectionInfoPtr::dynamicCast(getInfo()));
if(_instance->engine()->securityTraceLevel() >= 1)
{
@@ -485,7 +485,18 @@ IceSSL::TransceiverI::toDetailedString() const
Ice::ConnectionInfoPtr
IceSSL::TransceiverI::getInfo() const
{
- return getNativeConnectionInfo();
+ NativeConnectionInfoPtr info = new NativeConnectionInfo();
+ fillConnectionInfo(info, info->nativeCerts);
+ return info;
+}
+
+Ice::ConnectionInfoPtr
+IceSSL::TransceiverI::getWSInfo(const Ice::HeaderDict& headers) const
+{
+ WSSNativeConnectionInfoPtr info = new WSSNativeConnectionInfo();
+ fillConnectionInfo(info, info->nativeCerts);
+ info->headers = headers;
+ return info;
}
void
@@ -526,10 +537,9 @@ IceSSL::TransceiverI::~TransceiverI()
{
}
-NativeConnectionInfoPtr
-IceSSL::TransceiverI::getNativeConnectionInfo() const
+void
+IceSSL::TransceiverI::fillConnectionInfo(const ConnectionInfoPtr& info, std::vector<CertificatePtr>& nativeCerts) const
{
- NativeConnectionInfoPtr info = new NativeConnectionInfo();
IceInternal::fdToAddressAndPort(_stream->fd(), info->localAddress, info->localPort, info->remoteAddress,
info->remotePort);
if(_stream->fd() != INVALID_SOCKET)
@@ -546,7 +556,7 @@ IceSSL::TransceiverI::getNativeConnectionInfo() const
CFRetain(cert);
CertificatePtr certificate = new Certificate(cert);
- info->nativeCerts.push_back(certificate);
+ nativeCerts.push_back(certificate);
info->certs.push_back(certificate->encode());
}
@@ -562,7 +572,6 @@ IceSSL::TransceiverI::getNativeConnectionInfo() const
info->adapterName = _adapterName;
info->incoming = _incoming;
- return info;
}
OSStatus
diff --git a/cpp/src/IceSSL/SecureTransportTransceiverI.h b/cpp/src/IceSSL/SecureTransportTransceiverI.h
index aaf232c4032..c81ee7aaef1 100644
--- a/cpp/src/IceSSL/SecureTransportTransceiverI.h
+++ b/cpp/src/IceSSL/SecureTransportTransceiverI.h
@@ -18,6 +18,7 @@
#include <Ice/Transceiver.h>
#include <Ice/Network.h>
#include <Ice/StreamSocket.h>
+#include <Ice/WSTransceiver.h>
#ifdef ICE_USE_SECURE_TRANSPORT
@@ -30,7 +31,7 @@ namespace IceSSL
class ConnectorI;
class AcceptorI;
-class TransceiverI : public IceInternal::Transceiver
+class TransceiverI : public IceInternal::Transceiver, public IceInternal::WSTransceiverDelegate
{
public:
@@ -46,6 +47,7 @@ public:
virtual std::string toString() const;
virtual std::string toDetailedString() const;
virtual Ice::ConnectionInfoPtr getInfo() const;
+ virtual Ice::ConnectionInfoPtr getWSInfo(const Ice::HeaderDict&) const;
virtual void checkSendSize(const IceInternal::Buffer&);
virtual void setBufferSize(int rcvSize, int sndSize);
@@ -57,7 +59,7 @@ private:
TransceiverI(const InstancePtr&, const IceInternal::StreamSocketPtr&, const std::string&, bool);
virtual ~TransceiverI();
- virtual NativeConnectionInfoPtr getNativeConnectionInfo() const;
+ void fillConnectionInfo(const ConnectionInfoPtr&, std::vector<CertificatePtr>&) const;
friend class ConnectorI;
friend class AcceptorI;
diff --git a/cpp/test/Ice/info/AllTests.cpp b/cpp/test/Ice/info/AllTests.cpp
index 80a3bd258de..f8094effbae 100644
--- a/cpp/test/Ice/info/AllTests.cpp
+++ b/cpp/test/Ice/info/AllTests.cpp
@@ -44,7 +44,7 @@ allTests(const Ice::CommunicatorPtr& communicator)
test((ipEndpoint->type() == Ice::TCPEndpointType && Ice::TCPEndpointInfoPtr::dynamicCast(ipEndpoint)) ||
(ipEndpoint->type() == IceSSL::EndpointType && IceSSL::EndpointInfoPtr::dynamicCast(ipEndpoint)) ||
(ipEndpoint->type() == Ice::WSEndpointType && Ice::WSEndpointInfoPtr::dynamicCast(ipEndpoint)) ||
- (ipEndpoint->type() == Ice::WSSEndpointType && Ice::WSEndpointInfoPtr::dynamicCast(ipEndpoint)));
+ (ipEndpoint->type() == Ice::WSSEndpointType && IceSSL::WSSEndpointInfoPtr::dynamicCast(ipEndpoint)));
Ice::UDPEndpointInfoPtr udpEndpoint = Ice::UDPEndpointInfoPtr::dynamicCast(endps[1]->getInfo());
test(udpEndpoint);
@@ -184,13 +184,26 @@ allTests(const Ice::CommunicatorPtr& communicator)
if(base->ice_getConnection()->type() == "ws" || base->ice_getConnection()->type() == "wss")
{
- Ice::WSConnectionInfoPtr wsinfo = Ice::WSConnectionInfoPtr::dynamicCast(info);
- test(wsinfo);
+ Ice::HeaderDict headers;
- test(wsinfo->headers["Upgrade"] == "websocket");
- test(wsinfo->headers["Connection"] == "Upgrade");
- test(wsinfo->headers["Sec-WebSocket-Protocol"] == "ice.zeroc.com");
- test(wsinfo->headers.find("Sec-WebSocket-Accept") != wsinfo->headers.end());
+ Ice::WSConnectionInfoPtr wsinfo = Ice::WSConnectionInfoPtr::dynamicCast(info);
+ if(wsinfo)
+ {
+ headers = wsinfo->headers;
+ }
+
+ IceSSL::WSSConnectionInfoPtr wssinfo = IceSSL::WSSConnectionInfoPtr::dynamicCast(info);
+ if(wssinfo)
+ {
+ headers = wssinfo->headers;
+ test(wssinfo->verified);
+ test(!wssinfo->certs.empty());
+ }
+
+ test(headers["Upgrade"] == "websocket");
+ test(headers["Connection"] == "Upgrade");
+ test(headers["Sec-WebSocket-Protocol"] == "ice.zeroc.com");
+ test(headers.find("Sec-WebSocket-Accept") != headers.end());
test(ctx["ws.Upgrade"] == "websocket");
test(ctx["ws.Connection"] == "Upgrade");
diff --git a/cpp/test/Ice/info/TestI.cpp b/cpp/test/Ice/info/TestI.cpp
index ba63bf96744..11588b29294 100644
--- a/cpp/test/Ice/info/TestI.cpp
+++ b/cpp/test/Ice/info/TestI.cpp
@@ -84,5 +84,14 @@ TestI::getConnectionInfoAsContext(const Ice::Current& c)
}
}
+ IceSSL::WSSConnectionInfoPtr wssinfo = IceSSL::WSSConnectionInfoPtr::dynamicCast(info);
+ if(wssinfo)
+ {
+ for(Ice::HeaderDict::const_iterator p = wssinfo->headers.begin(); p != wssinfo->headers.end(); ++p)
+ {
+ ctx["ws." + p->first] = p->second;
+ }
+ }
+
return ctx;
}
diff --git a/cpp/test/IceSSL/certs/makecerts.py b/cpp/test/IceSSL/certs/makecerts.py
index 3c241767a1c..57bfdfcfeba 100755
--- a/cpp/test/IceSSL/certs/makecerts.py
+++ b/cpp/test/IceSSL/certs/makecerts.py
@@ -74,6 +74,12 @@ dsaca = IceCertUtils.OpenSSLCertificateFactory(home=ca1.home, keyalg="dsa", keys
#
if force or not os.path.exists("cacert1.pem"): ca1.getCA().save("cacert1.pem")
if force or not os.path.exists("cacert2.pem"): ca2.getCA().save("cacert2.pem")
+if force or not os.path.exists("cacert1.der"): ca1.getCA().save("cacert1.der")
+if force or not os.path.exists("cacerts.pem"):
+ pem = ""
+ with open("cacert1.pem", "r") as f: pem += f.read()
+ with open("cacert2.pem", "r") as f: pem += f.read()
+ with open("cacerts.pem", "w") as f: f.write(pem);
# Also export the ca2 self-signed certificate, it's used by the tests to test self-signed certificates
if force or not os.path.exists("cacert2_pub.pem"): ca2.getCA().save("cacert2_pub.pem")
diff --git a/cpp/test/IceSSL/configuration/AllTests.cpp b/cpp/test/IceSSL/configuration/AllTests.cpp
index 448eb075a0f..4a51b3416f1 100644
--- a/cpp/test/IceSSL/configuration/AllTests.cpp
+++ b/cpp/test/IceSSL/configuration/AllTests.cpp
@@ -39,43 +39,113 @@ readFile(const string& file, vector<char>& buffer)
}
#ifdef ICE_USE_SCHANNEL
-void
-findCertsCleanup(HCERTSTORE store, const vector<HCERTSTORE>& stores, const vector<PCCERT_CONTEXT>& certs)
+class ImportCerts
{
- for(vector<PCCERT_CONTEXT>::const_iterator i = certs.begin(); i != certs.end(); ++i)
- {
- PCCERT_CONTEXT cert = *i;
-
+public:
- DWORD size = 0;
+ ImportCerts(const string& defaultDir, const char* certificates[])
+ {
//
- // Retrieve the certificate CERT_KEY_PROV_INFO_PROP_ID property, we use the CRYPT_KEY_PROV_INFO
- // data to then remove the key set associated with the certificate.
+ // First we need to import some certificates in the user store.
//
- if(CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0, &size))
+ _store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
+ test(_store);
+
+ for(int i = 0; certificates[i] != 0; ++i)
{
- vector<char> buf(size);
- if(CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, &buf[0], &size))
+ vector<char> buffer;
+ readFile(defaultDir + certificates[i], buffer);
+
+ CRYPT_DATA_BLOB p12Blob;
+ p12Blob.cbData = static_cast<DWORD>(buffer.size());
+ p12Blob.pbData = reinterpret_cast<BYTE*>(&buffer[0]);
+
+ HCERTSTORE p12 = PFXImportCertStore(&p12Blob, L"password", CRYPT_USER_KEYSET);
+ _stores.push_back(p12);
+
+ PCCERT_CONTEXT next = 0;
+ PCCERT_CONTEXT newCert = 0;
+ do
{
- CRYPT_KEY_PROV_INFO* keyProvInfo = reinterpret_cast<CRYPT_KEY_PROV_INFO*>(&buf[0]);
- HCRYPTPROV cryptProv = 0;
- if(CryptAcquireContextW(&cryptProv, keyProvInfo->pwszContainerName, keyProvInfo->pwszProvName,
- keyProvInfo->dwProvType, 0))
+ if((next = CertFindCertificateInStore(p12, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
+ CERT_FIND_ANY, 0, next)))
{
- CryptAcquireContextW(&cryptProv, keyProvInfo->pwszContainerName, keyProvInfo->pwszProvName,
- keyProvInfo->dwProvType, CRYPT_DELETEKEYSET);
+ if(CertAddCertificateContextToStore(_store, next, CERT_STORE_ADD_ALWAYS, &newCert))
+ {
+ _certs.push_back(newCert);
+ }
+ }
+ }
+ while(next);
+ }
+ }
+
+ ~ImportCerts()
+ {
+ cleanup();
+ }
+
+ void cleanup()
+ {
+ for(vector<PCCERT_CONTEXT>::const_iterator i = _certs.begin(); i != _certs.end(); ++i)
+ {
+ PCCERT_CONTEXT cert = *i;
+
+ // Retrieve the certificate CERT_KEY_PROV_INFO_PROP_ID property, we use the CRYPT_KEY_PROV_INFO
+ // data to then remove the key set associated with the certificate.
+ //
+ DWORD size = 0;
+ if(CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0, &size))
+ {
+ vector<char> buf(size);
+ if(CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, &buf[0], &size))
+ {
+ CRYPT_KEY_PROV_INFO* keyProvInfo = reinterpret_cast<CRYPT_KEY_PROV_INFO*>(&buf[0]);
+ HCRYPTPROV cryptProv = 0;
+ if(CryptAcquireContextW(&cryptProv, keyProvInfo->pwszContainerName, keyProvInfo->pwszProvName,
+ keyProvInfo->dwProvType, 0))
+ {
+ CryptAcquireContextW(&cryptProv, keyProvInfo->pwszContainerName, keyProvInfo->pwszProvName,
+ keyProvInfo->dwProvType, CRYPT_DELETEKEYSET);
+ }
}
}
CertDeleteCertificateFromStore(cert);
}
+ _certs.clear();
+ for(vector<HCERTSTORE>::const_iterator i = _stores.begin(); i != _stores.end(); ++i)
+ {
+ CertCloseStore(*i, 0);
+ }
+ _stores.clear();
+ if(_store)
+ {
+ CertCloseStore(_store, 0);
+ _store = 0;
+ }
+ }
+
+private:
+
+ HCERTSTORE _store;
+ vector<HCERTSTORE> _stores;
+ vector<PCCERT_CONTEXT> _certs;
+};
+#else
+class ImportCerts
+{
+public:
+ ImportCerts(const string& defaultDir, const char* certificates[])
+ {
+ // Nothing to do.
}
- for(vector<HCERTSTORE>::const_iterator i = stores.begin(); i != stores.end(); ++i)
+
+ void cleanup()
{
- CertCloseStore(*i, 0);
}
-}
+};
#endif
class PasswordPromptI : public IceSSL::PasswordPrompt
@@ -240,7 +310,10 @@ createServerProps(const Ice::PropertiesPtr& defaultProps, const string& defaultD
{
Test::Properties result;
result["Ice.Plugin.IceSSL"] = "IceSSL:createIceSSL";
- result["IceSSL.DefaultDir"] = defaultDir;
+ if(!defaultDir.empty())
+ {
+ result["IceSSL.DefaultDir"] = defaultDir;
+ }
if(!defaultProps->getProperty("Ice.IPv6").empty())
{
result["Ice.IPv6"] = defaultProps->getProperty("Ice.IPv6");
@@ -273,28 +346,22 @@ createServerProps(const Ice::PropertiesPtr& defaultProps, const string& defaultD
// If no CA is specified, we don't set IceSSL.DefaultDir since
// with OpenSSL the CAs might still be found.
//
- string pfx;
- if(ca.empty())
- {
- d = createServerProps(defaultProps, "", defaultHost, p12);
- pfx = defaultDir + "/";
- }
- else
+ d = createServerProps(defaultProps, defaultDir, defaultHost, p12);
+ if(!ca.empty())
{
- d = createServerProps(defaultProps, defaultDir, defaultHost, p12);
- d["IceSSL.CertAuthFile"] = ca + ".pem";
+ d["IceSSL.CAs"] = ca + ".pem";
}
if(!cert.empty())
{
if(p12)
{
- d["IceSSL.CertFile"] = pfx + cert + ".p12";
+ d["IceSSL.CertFile"] = cert + ".p12";
}
else
{
- d["IceSSL.CertFile"] = pfx + cert + "_pub.pem";
- d["IceSSL.KeyFile"] = pfx + cert + "_priv.pem";
+ d["IceSSL.CertFile"] = cert + "_pub.pem";
+ d["IceSSL.KeyFile"] = cert + "_priv.pem";
}
}
return d;
@@ -306,32 +373,22 @@ createClientProps(const Ice::PropertiesPtr& defaultProps, const string& defaultD
{
Ice::PropertiesPtr properties;
- //
- // If no CA is specified, we don't set IceSSL.DefaultDir since
- // with OpenSSL the CAs might still be found.
- //
- string pfx;
- if(ca.empty())
+ properties = createClientProps(defaultProps, defaultDir, defaultHost, p12);
+ if(!ca.empty())
{
- properties = createClientProps(defaultProps, "", defaultHost, p12);
- pfx = defaultDir + "/";
- }
- else
- {
- properties = createClientProps(defaultProps, defaultDir, defaultHost, p12);
- properties->setProperty("IceSSL.CertAuthFile", ca + ".pem");
+ properties->setProperty("IceSSL.CAs", ca + ".pem");
}
if(!cert.empty())
{
if(p12)
{
- properties->setProperty("IceSSL.CertFile", pfx + cert + ".p12");
+ properties->setProperty("IceSSL.CertFile", cert + ".p12");
}
else
{
- properties->setProperty("IceSSL.CertFile", pfx + cert + "_pub.pem");
- properties->setProperty("IceSSL.KeyFile", pfx + cert + "_priv.pem");
+ properties->setProperty("IceSSL.CertFile", cert + "_pub.pem");
+ properties->setProperty("IceSSL.KeyFile", cert + "_priv.pem");
}
}
return properties;
@@ -456,8 +513,9 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
server->noCert();
test(!IceSSL::ConnectionInfoPtr::dynamicCast(server->ice_getConnection()->getInfo())->verified);
}
- catch(const LocalException&)
+ catch(const LocalException& ex)
{
+ cerr << ex << endl;
test(false);
}
fact->destroyServer(server);
@@ -821,6 +879,9 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
cout << "testing certificate chains... " << flush;
{
+ const char* certificates[] = {"/s_rsa_cai2.p12", 0};
+ ImportCerts import(defaultDir, certificates);
+
InitializationData initData;
initData.properties = createClientProps(defaultProps, defaultDir, defaultHost, p12, "", "");
initData.properties->setProperty("IceSSL.VerifyPeer", "0");
@@ -843,9 +904,9 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
test(info->nativeCerts.size() == 1);
test(!info->verified);
}
- catch(const Ice::LocalException& ex)
+ catch(const Ice::LocalException&)
{
- cerr << ex << endl;
+ import.cleanup();
test(false);
}
fact->destroyServer(server);
@@ -870,6 +931,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
catch(const Ice::LocalException& ex)
{
cerr << ex << endl;
+ import.cleanup();
test(false);
}
fact->destroyServer(server);
@@ -897,6 +959,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
catch(const Ice::LocalException& ex)
{
cerr << ex << endl;
+ import.cleanup();
test(false);
}
fact->destroyServer(server);
@@ -926,6 +989,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
catch(const Ice::LocalException& ex)
{
cerr << ex << endl;
+ import.cleanup();
test(false);
}
fact->destroyServer(server);
@@ -950,6 +1014,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
try
{
IceSSL::NativeConnectionInfoPtr::dynamicCast(server->ice_getConnection()->getInfo());
+ import.cleanup();
test(false);
}
catch(const Ice::SecurityException&)
@@ -959,6 +1024,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
catch(const Ice::LocalException& ex)
{
cerr << ex << endl;
+ import.cleanup();
test(false);
}
fact->destroyServer(server);
@@ -988,6 +1054,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
}
catch(const Ice::LocalException&)
{
+ import.cleanup();
test(false);
}
fact->destroyServer(server);
@@ -1000,6 +1067,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
try
{
IceSSL::NativeConnectionInfoPtr::dynamicCast(server->ice_getConnection()->getInfo());
+ import.cleanup();
test(false);
}
catch(const Ice::SecurityException&)
@@ -1033,6 +1101,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
}
catch(const Ice::LocalException&)
{
+ import.cleanup();
test(false);
}
fact->destroyServer(server);
@@ -1058,6 +1127,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
try
{
server->ice_getConnection();
+ import.cleanup();
test(false);
}
catch(const Ice::ProtocolException&)
@@ -1070,6 +1140,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
}
catch(const Ice::LocalException&)
{
+ import.cleanup();
test(false);
}
fact->destroyServer(server);
@@ -1086,12 +1157,14 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
}
catch(const Ice::LocalException&)
{
+ import.cleanup();
test(false);
}
fact->destroyServer(server);
}
comm->destroy();
+ import.cleanup();
}
cout << "ok" << endl;
@@ -1538,17 +1611,17 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
cout << "testing CA certificate directory... " << flush;
{
//
- // Don't specify CertAuthFile explicitly; we let OpenSSL find the CA
+ // Don't specify CAs explicitly; we let OpenSSL find the CA
// certificate in the default directory.
//
InitializationData initData;
initData.properties = createClientProps(defaultProps, defaultDir, defaultHost, p12, "c_rsa_ca1", "");
- initData.properties->setProperty("IceSSL.DefaultDir", defaultDir);
+ initData.properties->setProperty("IceSSL.CAs", defaultDir);
CommunicatorPtr comm = initialize(initData);
Test::ServerFactoryPrx fact = Test::ServerFactoryPrx::checkedCast(comm->stringToProxy(factoryRef));
test(fact);
Test::Properties d = createServerProps(defaultProps, defaultDir, defaultHost, p12, "s_rsa_ca1", "");
- d["IceSSL.DefaultDir"] = defaultDir;
+ d["IceSSL.CAs"] = defaultDir;
Test::ServerPrx server = fact->createServer(d);
try
{
@@ -1565,6 +1638,56 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
cout << "ok" << endl;
#endif
+ cout << "testing multiple CA certificates... " << flush;
+ {
+ InitializationData initData;
+ initData.properties = createClientProps(defaultProps, defaultDir, defaultHost, p12, "c_rsa_ca1", "cacerts");
+ CommunicatorPtr comm = initialize(initData);
+ Test::ServerFactoryPrx fact = Test::ServerFactoryPrx::checkedCast(comm->stringToProxy(factoryRef));
+ test(fact);
+ Test::Properties d = createServerProps(defaultProps, defaultDir, defaultHost, p12, "s_rsa_ca2", "cacerts");
+ d["IceSSL.VerifyPeer"] = "2";
+ Test::ServerPrx server = fact->createServer(d);
+ try
+ {
+ server->ice_ping();
+ }
+ catch(const Ice::LocalException&)
+ {
+ test(false);
+ }
+ fact->destroyServer(server);
+ comm->destroy();
+ }
+ cout << "ok" << endl;
+
+#ifndef ICE_USE_OPENSSL
+ cout << "testing DER CA certificate... " << flush;
+ {
+ InitializationData initData;
+ initData.properties = createClientProps(defaultProps, defaultDir, defaultHost, p12, "c_rsa_ca1", "");
+ initData.properties->setProperty("IceSSL.CAs", "cacert1.der");
+ CommunicatorPtr comm = initialize(initData);
+ Test::ServerFactoryPrx fact = Test::ServerFactoryPrx::checkedCast(comm->stringToProxy(factoryRef));
+ test(fact);
+ Test::Properties d = createServerProps(defaultProps, defaultDir, defaultHost, p12, "s_rsa_ca1", "");
+ d["IceSSL.VerifyPeer"] = "2";
+ d["IceSSL.CAs"] = "cacert1.der";
+ Test::ServerPrx server = fact->createServer(d);
+ try
+ {
+ server->ice_ping();
+ }
+ catch(const Ice::LocalException&)
+ {
+ test(false);
+ }
+ fact->destroyServer(server);
+ comm->destroy();
+ }
+ cout << "ok" << endl;
+#endif
+
//
// SChannel doesn't support PEM Password protected certificates certificates
//
@@ -2806,7 +2929,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
{
#if defined(ICE_USE_SCHANNEL)
- cerr << "testing IceSSL.FindCert... " << flush;
+ cout << "testing IceSSL.FindCert... " << flush;
const char* clientFindCertProperties[] =
{
"SUBJECTDN:'CN=Client, OU=Ice, O=\"ZeroC, Inc.\", L=Jupiter, S=Florida, C=US, E=info@zeroc.com'",
@@ -2842,50 +2965,13 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
};
const char* certificates[] = {"/s_rsa_ca1.p12", "/c_rsa_ca1.p12", 0};
-
- //
- // First we need to import some certificates in the user store.
- //
- HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
- test(store);
-
- vector<HCERTSTORE> stores;
- vector<PCCERT_CONTEXT> certs;
-
- for(int i = 0; certificates[i] != 0; ++i)
- {
- vector<char> buffer;
- readFile(defaultDir + certificates[i], buffer);
-
- CRYPT_DATA_BLOB p12Blob;
- p12Blob.cbData = static_cast<DWORD>(buffer.size());
- p12Blob.pbData = reinterpret_cast<BYTE*>(&buffer[0]);
-
- HCERTSTORE p12 = PFXImportCertStore(&p12Blob, L"password", CRYPT_USER_KEYSET);
-
- PCCERT_CONTEXT next = 0;
- PCCERT_CONTEXT newCert = 0;
- do
- {
- if((next = CertFindCertificateInStore(p12, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
- CERT_FIND_ANY, 0, next)))
- {
- if(CertAddCertificateContextToStore(store, next, CERT_STORE_ADD_ALWAYS, &newCert))
- {
- certs.push_back(newCert);
- }
- }
- }
- while(next);
-
- stores.push_back(p12);
- }
+ ImportCerts import(defaultDir, certificates);
for(int i = 0; clientFindCertProperties[i] != 0; i++)
{
InitializationData initData;
initData.properties = createClientProps(defaultProps, defaultDir, defaultHost, p12);
- initData.properties->setProperty("IceSSL.CertAuthFile", "cacert1.pem");
+ initData.properties->setProperty("IceSSL.CAs", "cacert1.pem");
initData.properties->setProperty("IceSSL.FindCert.CurrentUser.My", clientFindCertProperties[i]);
//
// Use TrustOnly to ensure the peer has pick the expected certificate.
@@ -2897,7 +2983,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
Test::ServerFactoryPrx fact = Test::ServerFactoryPrx::checkedCast(comm->stringToProxy(factoryRef));
test(fact);
Test::Properties d = createServerProps(defaultProps, defaultDir, defaultHost, p12, "s_rsa_ca1", "cacert1");
- d["IceSSL.CertAuthFile"] = "cacert1.pem";
+ d["IceSSL.CAs"] = "cacert1.pem";
d["IceSSL.FindCert.CurrentUser.My"] = serverFindCertProperties[i];
//
// Use TrustOnly to ensure the peer has pick the expected certificate.
@@ -2912,7 +2998,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
catch(const LocalException& ex)
{
cerr << ex << endl;
- findCertsCleanup(store, stores, certs);
+ import.cleanup();
test(false);
}
fact->destroyServer(server);
@@ -2926,12 +3012,12 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
{
InitializationData initData;
initData.properties = createClientProps(defaultProps, defaultDir, defaultHost, p12);
- initData.properties->setProperty("IceSSL.CertAuthFile", "cacert1.pem");
+ initData.properties->setProperty("IceSSL.CAs", "cacert1.pem");
initData.properties->setProperty("IceSSL.FindCert.CurrentUser.My", failFindCertProperties[i]);
try
{
CommunicatorPtr comm = initialize(initData);
- findCertsCleanup(store, stores, certs);
+ import.cleanup();
test(false);
}
catch(const PluginInitializationException&)
@@ -2941,12 +3027,12 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
catch(const Ice::LocalException& ex)
{
cerr << ex << endl;
- findCertsCleanup(store, stores, certs);
+ import.cleanup();
test(false);
}
}
- findCertsCleanup(store, stores, certs);
+ import.cleanup();
//
// These must fail because we have already remove the certificates.
@@ -2955,7 +3041,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
{
InitializationData initData;
initData.properties = createClientProps(defaultProps, defaultDir, defaultHost, p12);
- initData.properties->setProperty("IceSSL.CertAuthFile", "cacert1.pem");
+ initData.properties->setProperty("IceSSL.CAs", "cacert1.pem");
initData.properties->setProperty("IceSSL.FindCert.CurrentUser.My", clientFindCertProperties[i]);
try
{
@@ -2972,9 +3058,9 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
test(false);
}
}
- cerr << "ok" << endl;
+ cout << "ok" << endl;
#elif defined(ICE_USE_SECURE_TRANSPORT)
- cerr << "testing IceSSL.FindCert... " << flush;
+ cout << "testing IceSSL.FindCert... " << flush;
const char* clientFindCertProperties[] =
{
"SUBJECT:Client",
@@ -3012,7 +3098,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
{
InitializationData initData;
initData.properties = createClientProps(defaultProps, defaultDir, defaultHost, p12);
- initData.properties->setProperty("IceSSL.CertAuthFile", "cacert1.pem");
+ initData.properties->setProperty("IceSSL.CAs", "cacert1.pem");
initData.properties->setProperty("IceSSL.Keychain", "../certs/Find.keychain");
initData.properties->setProperty("IceSSL.KeychainPassword", "password");
initData.properties->setProperty("IceSSL.FindCert", clientFindCertProperties[i]);
@@ -3026,7 +3112,7 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
Test::ServerFactoryPrx fact = Test::ServerFactoryPrx::checkedCast(comm->stringToProxy(factoryRef));
test(fact);
Test::Properties d = createServerProps(defaultProps, defaultDir, defaultHost, p12);
- d["IceSSL.CertAuthFile"] = "cacert1.pem";
+ d["IceSSL.CAs"] = "cacert1.pem";
d["IceSSL.Keychain"] = "../certs/Find.keychain";
d["IceSSL.KeychainPassword"] = "password";
d["IceSSL.FindCert"] = serverFindCertProperties[i];
@@ -3071,10 +3157,55 @@ allTests(const CommunicatorPtr& communicator, const string& testDir, bool p12, b
test(false);
}
}
- cerr << "ok" << endl;
+ cout << "ok" << endl;
#endif
}
+ cout << "testing system CAs... " << flush;
+ {
+ InitializationData initData;
+ initData.properties = createClientProps(defaultProps, "", defaultHost, false);
+ initData.properties->setProperty("IceSSL.VerifyDepthMax", "4");
+ initData.properties->setProperty("Ice.Override.Timeout", "5000"); // 5s timeout
+ CommunicatorPtr comm = initialize(initData);
+ Ice::ObjectPrx p = comm->stringToProxy("dummy:wss -h demo.zeroc.com -p 5064");
+ try
+ {
+ p->ice_ping();
+ test(false);
+ }
+ catch(const Ice::SecurityException&)
+ {
+ // Expected, by default we don't check for system CAs.
+ }
+ catch(const Ice::LocalException& ex)
+ {
+ cerr << "warning: unable to connect to demo.zeroc.com to check system CA:\n" << ex << endl;
+ }
+ comm->destroy();
+
+ initData.properties = createClientProps(defaultProps, "", defaultHost, false);
+ initData.properties->setProperty("IceSSL.VerifyDepthMax", "4");
+ initData.properties->setProperty("Ice.Override.Timeout", "5000"); // 5s timeout
+ initData.properties->setProperty("IceSSL.UsePlatformCAs", "1");
+ comm = initialize(initData);
+ p = comm->stringToProxy("dummy:wss -h demo.zeroc.com -p 5064");
+
+ IceSSL::WSSConnectionInfoPtr info;
+ try
+ {
+ info = IceSSL::WSSConnectionInfoPtr::dynamicCast(p->ice_getConnection()->getInfo());
+ test(info->verified);
+ }
+ catch(const Ice::LocalException& ex)
+ {
+ cerr << ex << endl;
+ test(false);
+ }
+ comm->destroy();
+ }
+ cout << "ok" << endl;
+
if(shutdown)
{
factory->shutdown();
diff --git a/cpp/test/IceSSL/configuration/run.py b/cpp/test/IceSSL/configuration/run.py
index 58c6b79a9e6..e877d3bf802 100755
--- a/cpp/test/IceSSL/configuration/run.py
+++ b/cpp/test/IceSSL/configuration/run.py
@@ -8,7 +8,7 @@
#
# **********************************************************************
-import os, sys, atexit
+import os, sys, atexit, re
path = [ ".", "..", "../..", "../../..", "../../../.." ]
head = os.path.dirname(sys.argv[0])
@@ -20,6 +20,10 @@ if len(path) == 0:
sys.path.append(os.path.join(path[0], "scripts"))
import TestUtil
+# Filter-out the deprecated property warnings
+TestUtil.clientTraceFilters = [ lambda x: re.sub("-! .* warning: deprecated property: IceSSL.KeyFile\n", "", x) ]
+TestUtil.serverTraceFilters = [ lambda x: re.sub("-! .* warning: deprecated property: IceSSL.KeyFile\n", "", x) ]
+
certsPath = os.path.abspath(os.path.join(os.getcwd(), "..", "certs"))
keychainPath = os.path.abspath(os.path.join(certsPath, "Find.keychain"))
diff --git a/csharp/src/Ice/PropertyNames.cs b/csharp/src/Ice/PropertyNames.cs
index 279d5cb0ff2..cd2190d1f47 100644
--- a/csharp/src/Ice/PropertyNames.cs
+++ b/csharp/src/Ice/PropertyNames.cs
@@ -6,7 +6,7 @@
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
-// Generated by makeprops.py from file ../config/PropertyNames.xml, Tue Dec 9 12:08:30 2014
+// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Apr 28 17:34:50 2015
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -188,6 +188,7 @@ namespace IceInternal
new Property(@"^Ice\.Warn\.UnusedProperties$", false, null),
new Property(@"^Ice\.CacheMessageBuffers$", false, null),
new Property(@"^Ice\.ThreadInterruptSafe$", false, null),
+ new Property(@"^Ice\.Voip$", false, null),
null
};
@@ -969,8 +970,9 @@ namespace IceInternal
public static Property[] IceSSLProps =
{
new Property(@"^IceSSL\.Alias$", false, null),
- new Property(@"^IceSSL\.CertAuthDir$", false, null),
- new Property(@"^IceSSL\.CertAuthFile$", false, null),
+ new Property(@"^IceSSL\.CAs$", false, null),
+ new Property(@"^IceSSL\.CertAuthDir$", true, null),
+ new Property(@"^IceSSL\.CertAuthFile$", true, null),
new Property(@"^IceSSL\.CertStore$", false, null),
new Property(@"^IceSSL\.CertFile$", false, null),
new Property(@"^IceSSL\.CertVerifier$", false, null),
@@ -982,10 +984,10 @@ namespace IceInternal
new Property(@"^IceSSL\.DHParams$", false, null),
new Property(@"^IceSSL\.EntropyDaemon$", false, null),
new Property(@"^IceSSL\.FindCert$", false, null),
- new Property(@"^IceSSL\.FindCert\.[^\s]+$", false, null),
+ new Property(@"^IceSSL\.FindCert\.[^\s]+$", true, null),
new Property(@"^IceSSL\.ImportCert\.[^\s]+$", true, null),
new Property(@"^IceSSL\.InitOpenSSL$", false, null),
- new Property(@"^IceSSL\.KeyFile$", false, null),
+ new Property(@"^IceSSL\.KeyFile$", true, null),
new Property(@"^IceSSL\.KeySet$", false, null),
new Property(@"^IceSSL\.Keychain$", false, null),
new Property(@"^IceSSL\.KeychainPassword$", false, null),
@@ -1008,6 +1010,7 @@ namespace IceInternal
new Property(@"^IceSSL\.Truststore$", false, null),
new Property(@"^IceSSL\.TruststorePassword$", false, null),
new Property(@"^IceSSL\.TruststoreType$", false, null),
+ new Property(@"^IceSSL\.UsePlatformCAs$", false, null),
new Property(@"^IceSSL\.VerifyDepthMax$", false, null),
new Property(@"^IceSSL\.VerifyPeer$", false, null),
null
diff --git a/csharp/src/Ice/TcpEndpointI.cs b/csharp/src/Ice/TcpEndpointI.cs
index fcfa84ab0c3..71b0e498230 100644
--- a/csharp/src/Ice/TcpEndpointI.cs
+++ b/csharp/src/Ice/TcpEndpointI.cs
@@ -15,7 +15,7 @@ namespace IceInternal
using System;
using System.Globalization;
- sealed class TcpEndpointI : IPEndpointI
+ sealed class TcpEndpointI : IPEndpointI, WSEndpointDelegate
{
public TcpEndpointI(ProtocolInstance instance, string ho, int po, EndPoint sourceAddr, int ti, string conId,
bool co) :
@@ -71,6 +71,39 @@ namespace IceInternal
return info;
}
+ private sealed class WSInfoI : Ice.WSEndpointInfo
+ {
+ public WSInfoI(IPEndpointI e)
+ {
+ _endpoint = e;
+ }
+
+ public override short type()
+ {
+ return _endpoint.type();
+ }
+
+ public override bool datagram()
+ {
+ return _endpoint.datagram();
+ }
+
+ public override bool secure()
+ {
+ return _endpoint.secure();
+ }
+
+ private IPEndpointI _endpoint;
+ }
+
+ public Ice.EndpointInfo getWSInfo(string resource)
+ {
+ WSInfoI info = new WSInfoI(this);
+ fillEndpointInfo(info);
+ info.resource = resource;
+ return info;
+ }
+
public override int timeout()
{
return _timeout;
diff --git a/csharp/src/Ice/TcpTransceiver.cs b/csharp/src/Ice/TcpTransceiver.cs
index 11f7fd49578..c434f1f33db 100644
--- a/csharp/src/Ice/TcpTransceiver.cs
+++ b/csharp/src/Ice/TcpTransceiver.cs
@@ -12,10 +12,11 @@ namespace IceInternal
using System;
using System.ComponentModel;
using System.Diagnostics;
+ using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
- sealed class TcpTransceiver : Transceiver
+ sealed class TcpTransceiver : Transceiver, WSTransceiverDelegate
{
public Socket fd()
{
@@ -88,17 +89,15 @@ namespace IceInternal
public Ice.ConnectionInfo getInfo()
{
Ice.TCPConnectionInfo info = new Ice.TCPConnectionInfo();
- if(_stream.fd() != null)
- {
- EndPoint localEndpoint = Network.getLocalAddress(_stream.fd());
- info.localAddress = Network.endpointAddressToString(localEndpoint);
- info.localPort = Network.endpointPort(localEndpoint);
- EndPoint remoteEndpoint = Network.getRemoteAddress(_stream.fd());
- info.remoteAddress = Network.endpointAddressToString(remoteEndpoint);
- info.remotePort = Network.endpointPort(remoteEndpoint);
- info.rcvSize = Network.getRecvBufferSize(_stream.fd());
- info.sndSize = Network.getSendBufferSize(_stream.fd());
- }
+ fillConnectionInfo(info);
+ return info;
+ }
+
+ public Ice.ConnectionInfo getWSInfo(Dictionary<string, string> headers)
+ {
+ Ice.WSConnectionInfo info = new Ice.WSConnectionInfo();
+ fillConnectionInfo(info);
+ info.headers = headers;
return info;
}
@@ -130,6 +129,21 @@ namespace IceInternal
_stream = stream;
}
+ private void fillConnectionInfo(Ice.TCPConnectionInfo info)
+ {
+ if(_stream.fd() != null)
+ {
+ EndPoint localEndpoint = Network.getLocalAddress(_stream.fd());
+ info.localAddress = Network.endpointAddressToString(localEndpoint);
+ info.localPort = Network.endpointPort(localEndpoint);
+ EndPoint remoteEndpoint = Network.getRemoteAddress(_stream.fd());
+ info.remoteAddress = Network.endpointAddressToString(remoteEndpoint);
+ info.remotePort = Network.endpointPort(remoteEndpoint);
+ info.rcvSize = Network.getRecvBufferSize(_stream.fd());
+ info.sndSize = Network.getSendBufferSize(_stream.fd());
+ }
+ }
+
private readonly ProtocolInstance _instance;
private readonly StreamSocket _stream;
}
diff --git a/csharp/src/Ice/WSEndpoint.cs b/csharp/src/Ice/WSEndpoint.cs
index 27f7816d5e9..5d0660726c8 100644
--- a/csharp/src/Ice/WSEndpoint.cs
+++ b/csharp/src/Ice/WSEndpoint.cs
@@ -14,6 +14,15 @@ namespace IceInternal
using System.Collections.Generic;
using System.Globalization;
+ //
+ // Delegate interface implemented by TcpEndpoint or IceSSL.EndpointI or any endpoint that WS can
+ // delegate to.
+ //
+ public interface WSEndpointDelegate
+ {
+ Ice.EndpointInfo getWSInfo(string resource);
+ };
+
sealed class WSEndpoint : EndpointI
{
internal WSEndpoint(ProtocolInstance instance, EndpointI del, string res)
@@ -71,10 +80,8 @@ namespace IceInternal
public override Ice.EndpointInfo getInfo()
{
- InfoI info = new InfoI(this);
- _delegate.fillEndpointInfo(info);
- info.resource = _resource;
- return info;
+ Debug.Assert(_delegate is WSEndpointDelegate);
+ return ((WSEndpointDelegate)_delegate).getWSInfo(_resource);
}
public override short type()
diff --git a/csharp/src/Ice/WSTransceiver.cs b/csharp/src/Ice/WSTransceiver.cs
index 7218027bdc2..98dd6f8fdae 100644
--- a/csharp/src/Ice/WSTransceiver.cs
+++ b/csharp/src/Ice/WSTransceiver.cs
@@ -16,6 +16,15 @@ namespace IceInternal
using System.Security.Cryptography;
using System.Text;
+ //
+ // Delegate interface implemented by TcpTransceiver or IceSSL.TransceiverI or any endpoint that WS can
+ // delegate to.
+ //
+ public interface WSTransceiverDelegate
+ {
+ Ice.ConnectionInfo getWSInfo(Dictionary<string, string> headers);
+ };
+
sealed class WSTransceiver : Transceiver
{
public Socket fd()
@@ -629,16 +638,8 @@ namespace IceInternal
public Ice.ConnectionInfo getInfo()
{
- Ice.IPConnectionInfo di = (Ice.IPConnectionInfo)_delegate.getInfo();
- Ice.WSConnectionInfo info = new Ice.WSConnectionInfo();
- info.localAddress = di.localAddress;
- info.localPort = di.localPort;
- info.remoteAddress = di.remoteAddress;
- info.remotePort = di.remotePort;
- info.rcvSize = di.rcvSize;
- info.sndSize = di.sndSize;
- info.headers = _parser.getHeaders();
- return info;
+ Debug.Assert(_delegate is WSTransceiverDelegate);
+ return ((WSTransceiverDelegate)_delegate).getWSInfo(_parser.getHeaders());
}
public void checkSendSize(Buffer buf)
diff --git a/csharp/src/IceSSL/EndpointI.cs b/csharp/src/IceSSL/EndpointI.cs
index edc04dd09d9..8c02bad421a 100644
--- a/csharp/src/IceSSL/EndpointI.cs
+++ b/csharp/src/IceSSL/EndpointI.cs
@@ -15,7 +15,7 @@ namespace IceSSL
using System.Net;
using System.Globalization;
- sealed class EndpointI : IceInternal.IPEndpointI
+ sealed class EndpointI : IceInternal.IPEndpointI, IceInternal.WSEndpointDelegate
{
internal EndpointI(Instance instance, string ho, int po, EndPoint sourceAddr, int ti, string conId, bool co) :
base(instance, ho, po, sourceAddr, conId)
@@ -76,6 +76,42 @@ namespace IceSSL
return info;
}
+ private sealed class WSSInfoI : IceSSL.WSSEndpointInfo
+ {
+ public WSSInfoI(EndpointI e)
+ {
+ _endpoint = e;
+ }
+
+ override public short type()
+ {
+ return _endpoint.type();
+ }
+
+ override public bool datagram()
+ {
+ return _endpoint.datagram();
+ }
+
+ override public bool secure()
+ {
+ return _endpoint.secure();
+ }
+
+ private EndpointI _endpoint;
+ }
+
+ //
+ // Return the endpoint information.
+ //
+ public Ice.EndpointInfo getWSInfo(string resource)
+ {
+ WSSInfoI info = new WSSInfoI(this);
+ fillEndpointInfo(info);
+ info.resource = resource;
+ return info;
+ }
+
//
// Return the timeout for the endpoint in milliseconds. 0 means
// non-blocking, -1 means no timeout.
diff --git a/csharp/src/IceSSL/SSLEngine.cs b/csharp/src/IceSSL/SSLEngine.cs
index c0ae3a79c04..7a0180d3fcf 100644
--- a/csharp/src/IceSSL/SSLEngine.cs
+++ b/csharp/src/IceSSL/SSLEngine.cs
@@ -305,7 +305,15 @@ namespace IceSSL
if(_caCerts == null)
{
- string certAuthFile = properties.getProperty(prefix + "CertAuthFile");
+ string certAuthFile = properties.getProperty(prefix + "CAs");
+ if(certAuthFile.Length == 0)
+ {
+ certAuthFile = properties.getProperty(prefix + "CertAuthFile");
+ }
+ if(certAuthFile.Length > 0 || properties.getPropertyAsInt(prefix + "UsePlatformCAs") <= 0)
+ {
+ _caCerts = new X509Certificate2Collection();
+ }
if(certAuthFile.Length > 0)
{
if(!checkPath(ref certAuthFile))
@@ -315,12 +323,59 @@ namespace IceSSL
throw e;
}
- _caCerts = new X509Certificate2Collection();
try
{
- _caCerts.Add(new X509Certificate2(certAuthFile));
+ using(System.IO.FileStream fs = System.IO.File.OpenRead(certAuthFile))
+ {
+ byte[] data = new byte[fs.Length];
+ fs.Read(data, 0, data.Length);
+
+ string strbuf = "";
+ try
+ {
+ strbuf = System.Text.Encoding.UTF8.GetString(data);
+ }
+ catch(Exception)
+ {
+ // Ignore
+ }
+
+ if(strbuf.Length == data.Length)
+ {
+ int size, startpos, endpos = 0;
+ bool first = true;
+ while(true)
+ {
+ startpos = strbuf.IndexOf("-----BEGIN CERTIFICATE-----", endpos);
+ if(startpos != -1)
+ {
+ endpos = strbuf.IndexOf("-----END CERTIFICATE-----", startpos);
+ size = endpos - startpos + "-----END CERTIFICATE-----".Length;
+ }
+ else if(first)
+ {
+ startpos = 0;
+ endpos = strbuf.Length;
+ size = strbuf.Length;
+ }
+ else
+ {
+ break;
+ }
+
+ byte[] cert = new byte[size];
+ System.Buffer.BlockCopy(data, startpos, cert, 0, size);
+ _caCerts.Import(cert);
+ first = false;
+ }
+ }
+ else
+ {
+ _caCerts.Import(data);
+ }
+ }
}
- catch(CryptographicException ex)
+ catch(Exception ex)
{
Ice.PluginInitializationException e = new Ice.PluginInitializationException(ex);
e.reason = "IceSSL: error while attempting to load CA certificate from " + certAuthFile;
diff --git a/csharp/src/IceSSL/TransceiverI.cs b/csharp/src/IceSSL/TransceiverI.cs
index 96eec4be71b..85ec68d0e4f 100644
--- a/csharp/src/IceSSL/TransceiverI.cs
+++ b/csharp/src/IceSSL/TransceiverI.cs
@@ -22,7 +22,7 @@ namespace IceSSL
using System.Threading;
using System.Text;
- sealed class TransceiverI : IceInternal.Transceiver
+ sealed class TransceiverI : IceInternal.Transceiver, IceInternal.WSTransceiverDelegate
{
public Socket fd()
{
@@ -49,7 +49,7 @@ namespace IceSSL
Debug.Assert(_sslStream.IsAuthenticated);
_authenticated = true;
- _instance.verifyPeer(getNativeConnectionInfo(), _stream.fd(), _host);
+ _instance.verifyPeer((NativeConnectionInfo)getInfo(), _stream.fd(), _host);
if(_instance.securityTraceLevel() >= 1)
{
@@ -302,7 +302,17 @@ namespace IceSSL
public Ice.ConnectionInfo getInfo()
{
- return getNativeConnectionInfo();
+ NativeConnectionInfo info = new NativeConnectionInfo();
+ info.nativeCerts = fillConnectionInfo(info);
+ return info;
+ }
+
+ public Ice.ConnectionInfo getWSInfo(Dictionary<string, string> headers)
+ {
+ WSSNativeConnectionInfo info = new WSSNativeConnectionInfo();
+ info.nativeCerts = fillConnectionInfo(info);
+ info.headers = headers;
+ return info;
}
public void checkSendSize(IceInternal.Buffer buf)
@@ -367,9 +377,9 @@ namespace IceSSL
}
}
- private NativeConnectionInfo getNativeConnectionInfo()
+ private X509Certificate2[] fillConnectionInfo(ConnectionInfo info)
{
- IceSSL.NativeConnectionInfo info = new IceSSL.NativeConnectionInfo();
+ X509Certificate2[] nativeCerts = null;
if(_stream.fd() != null)
{
IPEndPoint localEndpoint = (IPEndPoint)IceInternal.Network.getLocalAddress(_stream.fd());
@@ -392,19 +402,19 @@ namespace IceSSL
info.cipher = _sslStream.CipherAlgorithm.ToString();
if(_chain.ChainElements != null && _chain.ChainElements.Count > 0)
{
- info.nativeCerts = new X509Certificate2[_chain.ChainElements.Count];
+ nativeCerts = new X509Certificate2[_chain.ChainElements.Count];
for(int i = 0; i < _chain.ChainElements.Count; ++i)
{
- info.nativeCerts[i] = _chain.ChainElements[i].Certificate;
+ nativeCerts[i] = _chain.ChainElements[i].Certificate;
}
}
#endif
List<string> certs = new List<string>();
#if !UNITY
- if(info.nativeCerts != null)
+ if(nativeCerts != null)
{
- foreach(X509Certificate2 cert in info.nativeCerts)
+ foreach(X509Certificate2 cert in nativeCerts)
{
StringBuilder s = new StringBuilder();
s.Append("-----BEGIN CERTIFICATE-----\n");
@@ -419,7 +429,7 @@ namespace IceSSL
}
info.adapterName = _adapterName;
info.incoming = _incoming;
- return info;
+ return nativeCerts;
}
private bool startAuthenticate(IceInternal.AsyncCallback callback, object state)
@@ -571,19 +581,44 @@ namespace IceSSL
SslPolicyErrors policyErrors)
{
#if !UNITY
- SslPolicyErrors sslPolicyErrors = policyErrors;
+ string message = "";
+ int errors = (int)policyErrors;
if(certificate != null)
{
- sslPolicyErrors = SslPolicyErrors.None;
- _verified = _chain.Build(new X509Certificate2(certificate));
- if(_chain.ChainStatus.Length > 0)
+ _chain.Build(new X509Certificate2(certificate));
+ if(_chain.ChainStatus != null && _chain.ChainStatus.Length > 0)
+ {
+ errors = (int)SslPolicyErrors.RemoteCertificateChainErrors;
+ }
+ else if(_instance.engine().caCerts() != null)
+ {
+ X509ChainElement e = _chain.ChainElements[_chain.ChainElements.Count - 1];
+ if(!_chain.ChainPolicy.ExtraStore.Contains(e.Certificate))
+ {
+ if(_verifyPeer > 0)
+ {
+ message = message + "\npuntrusted root certificate";
+ }
+ else
+ {
+ message = message + "\nuntrusted root certificate (ignored)";
+ _verified = false;
+ }
+ errors = (int)SslPolicyErrors.RemoteCertificateChainErrors;
+ }
+ else
+ {
+ _verified = true;
+ return true;
+ }
+ }
+ else
{
- sslPolicyErrors = SslPolicyErrors.RemoteCertificateChainErrors;
+ _verified = true;
+ return true;
}
}
- string message = "";
- int errors = (int)sslPolicyErrors;
if((errors & (int)SslPolicyErrors.RemoteCertificateNotAvailable) > 0)
{
//
@@ -618,81 +653,87 @@ namespace IceSSL
}
- if((errors & (int)SslPolicyErrors.RemoteCertificateChainErrors) > 0)
+ if((errors & (int)SslPolicyErrors.RemoteCertificateChainErrors) > 0 &&
+ _chain.ChainStatus != null && _chain.ChainStatus.Length > 0)
{
- if(_chain.ChainStatus != null)
+ int errorCount = 0;
+ foreach(X509ChainStatus status in _chain.ChainStatus)
{
- int errorCount = _chain.ChainStatus.Length;
- foreach(X509ChainStatus status in _chain.ChainStatus)
+ if(status.Status == X509ChainStatusFlags.UntrustedRoot && _instance.engine().caCerts() != null)
{
- if(status.Status == X509ChainStatusFlags.UntrustedRoot &&
- _instance.engine().caCerts() != null && _verified)
+ //
+ // Untrusted root is OK when using our custom chain engine if
+ // the CA certificate is present in the chain policy extra store.
+ //
+ X509ChainElement e = _chain.ChainElements[_chain.ChainElements.Count - 1];
+ if(!_chain.ChainPolicy.ExtraStore.Contains(e.Certificate))
{
- //
- // Untrusted root is OK when using our custom chain engine if
- // the CA certificate is present in the chain policy extra store.
- //
- X509ChainElement e = _chain.ChainElements[_chain.ChainElements.Count - 1];
- if(_chain.ChainPolicy.ExtraStore.Contains(e.Certificate))
- {
- --errorCount;
- }
- }
- else if(status.Status == X509ChainStatusFlags.Revoked)
- {
- if(_instance.checkCRL() > 0)
+ if(_verifyPeer > 0)
{
- message = message + "\ncertificate revoked";
+ message = message + "\npuntrusted root certificate";
+ ++errorCount;
}
else
{
- message = message + "\ncertificate revoked (ignored)";
- --errorCount;
+ message = message + "\nuntrusted root certificate (ignored)";
}
}
- else if(status.Status == X509ChainStatusFlags.RevocationStatusUnknown)
+ else
{
- //
- // If a certificate's revocation status cannot be determined, the strictest
- // policy is to reject the connection.
- //
- if(_instance.checkCRL() > 1)
- {
- message = message + "\ncertificate revocation status unknown";
- }
- else
- {
- message = message + "\ncertificate revocation status unknown (ignored)";
- --errorCount;
- }
+ _verified = true;
}
- else if(status.Status == X509ChainStatusFlags.PartialChain)
+ }
+ else if(status.Status == X509ChainStatusFlags.Revoked)
+ {
+ if(_instance.checkCRL() > 0)
{
- if(_verifyPeer > 0)
- {
- message = message + "\npartial certificate chain";
- }
- else
- {
- message = message + "\npartial certificate chain (ignored)";
- --errorCount;
- }
+ message = message + "\ncertificate revoked";
+ ++errorCount;
}
- else if(status.Status == X509ChainStatusFlags.NoError)
+ else
{
- --errorCount;
+ message = message + "\ncertificate revoked (ignored)";
+ }
+ }
+ else if(status.Status == X509ChainStatusFlags.RevocationStatusUnknown)
+ {
+ //
+ // If a certificate's revocation status cannot be determined, the strictest
+ // policy is to reject the connection.
+ //
+ if(_instance.checkCRL() > 1)
+ {
+ message = message + "\ncertificate revocation status unknown";
+ ++errorCount;
}
else
{
- message = message + "\ncertificate chain error: " + status.Status.ToString();
+ message = message + "\ncertificate revocation status unknown (ignored)";
}
}
-
- if(errorCount == 0)
+ else if(status.Status == X509ChainStatusFlags.PartialChain)
+ {
+ if(_verifyPeer > 0)
+ {
+ message = message + "\npartial certificate chain";
+ ++errorCount;
+ }
+ else
+ {
+ message = message + "\npartial certificate chain (ignored)";
+ }
+ }
+ else if(status.Status != X509ChainStatusFlags.NoError)
{
- errors ^= (int)SslPolicyErrors.RemoteCertificateChainErrors;
+ message = message + "\ncertificate chain error: " + status.Status.ToString();
+ ++errorCount;
}
}
+
+ if(errorCount == 0)
+ {
+ errors ^= (int)SslPolicyErrors.RemoteCertificateChainErrors;
+ }
}
if(errors > 0)
@@ -714,11 +755,10 @@ namespace IceSSL
}
else if(message.Length > 0 && _instance.securityTraceLevel() >= 1)
{
- _instance.logger().trace(_instance.securityTraceCategory(), "SSL certificate validation status:" +
- message);
+ _instance.logger().trace(_instance.securityTraceCategory(),
+ "SSL certificate validation status:" + message);
}
#endif
-
return true;
}
diff --git a/csharp/src/IceSSL/Util.cs b/csharp/src/IceSSL/Util.cs
index 9fa6b8d0142..0dd847fcb10 100644
--- a/csharp/src/IceSSL/Util.cs
+++ b/csharp/src/IceSSL/Util.cs
@@ -28,6 +28,20 @@ namespace IceSSL
public System.Security.Cryptography.X509Certificates.X509Certificate2[] nativeCerts;
}
+ /// <summary>
+ /// This class provides information about a connection to applications
+ /// that require information about a peer.
+ /// </summary>
+ public sealed class WSSNativeConnectionInfo : WSSConnectionInfo
+ {
+ /// <summary>
+ /// The certificate chain. This may be null if the peer did not
+ /// supply a certificate. The peer's certificate (if any) is the
+ /// first one in the chain.
+ /// </summary>
+ public System.Security.Cryptography.X509Certificates.X509Certificate2[] nativeCerts;
+ }
+
public sealed class Util
{
public static X509Certificate2 createCertificate(string certPEM)
diff --git a/csharp/test/Ice/info/AllTests.cs b/csharp/test/Ice/info/AllTests.cs
index 87019626c24..f2b3a21f714 100644
--- a/csharp/test/Ice/info/AllTests.cs
+++ b/csharp/test/Ice/info/AllTests.cs
@@ -69,7 +69,7 @@ public class AllTests : TestCommon.TestApp
test(ipEndpoint.type() == Ice.TCPEndpointType.value && ipEndpoint is Ice.TCPEndpointInfo ||
ipEndpoint.type() == IceSSL.EndpointType.value && ipEndpoint is IceSSL.EndpointInfo ||
ipEndpoint.type() == Ice.WSEndpointType.value && ipEndpoint is Ice.WSEndpointInfo ||
- ipEndpoint.type() == Ice.WSSEndpointType.value && ipEndpoint is Ice.WSEndpointInfo);
+ ipEndpoint.type() == Ice.WSSEndpointType.value && ipEndpoint is IceSSL.WSSEndpointInfo);
#endif
Ice.UDPEndpointInfo udpEndpoint = (Ice.UDPEndpointInfo)endps[1].getInfo();
@@ -209,12 +209,19 @@ public class AllTests : TestCommon.TestApp
if(@base.ice_getConnection().type().Equals("ws") || @base.ice_getConnection().type().Equals("wss"))
{
- test(info is Ice.WSConnectionInfo);
- Ice.WSConnectionInfo wsinfo = (Ice.WSConnectionInfo)info;
- test(wsinfo.headers["Upgrade"].Equals("websocket"));
- test(wsinfo.headers["Connection"].Equals("Upgrade"));
- test(wsinfo.headers["Sec-WebSocket-Protocol"].Equals("ice.zeroc.com"));
- test(wsinfo.headers["Sec-WebSocket-Accept"] != null);
+ Dictionary<string, string> headers;
+ if(info is Ice.WSConnectionInfo)
+ {
+ headers = ((Ice.WSConnectionInfo)info).headers;
+ }
+ else
+ {
+ headers = ((IceSSL.WSSConnectionInfo)info).headers;
+ }
+ test(headers["Upgrade"].Equals("websocket"));
+ test(headers["Connection"].Equals("Upgrade"));
+ test(headers["Sec-WebSocket-Protocol"].Equals("ice.zeroc.com"));
+ test(headers["Sec-WebSocket-Accept"] != null);
test(ctx["ws.Upgrade"].Equals("websocket"));
test(ctx["ws.Connection"].Equals("Upgrade"));
diff --git a/csharp/test/Ice/info/Makefile.mak b/csharp/test/Ice/info/Makefile.mak
index b6dd92ff24f..49377776519 100644
--- a/csharp/test/Ice/info/Makefile.mak
+++ b/csharp/test/Ice/info/Makefile.mak
@@ -30,4 +30,4 @@ client.exe: $(C_SRCS) $(GEN_SRCS)
$(MCS) $(MCSFLAGS) -out:$@ -r:"$(refdir)\Ice.dll" -r:"$(refdir)\IceSSL.dll" $(C_SRCS) $(GEN_SRCS)
server.exe: $(S_SRCS) $(GEN_SRCS)
- $(MCS) $(MCSFLAGS) -out:$@ -r:"$(refdir)\Ice.dll" $(S_SRCS) $(GEN_SRCS)
+ $(MCS) $(MCSFLAGS) -out:$@ -r:"$(refdir)\Ice.dll" -r:"$(refdir)\IceSSL.dll" $(S_SRCS) $(GEN_SRCS)
diff --git a/csharp/test/Ice/info/TestI.cs b/csharp/test/Ice/info/TestI.cs
index 3e15e9fecc1..d84e4bd64e0 100644
--- a/csharp/test/Ice/info/TestI.cs
+++ b/csharp/test/Ice/info/TestI.cs
@@ -63,6 +63,15 @@ public class TestI : TestIntfDisp_
}
}
+ if(info is IceSSL.WSSConnectionInfo)
+ {
+ IceSSL.WSSConnectionInfo wssinfo = (IceSSL.WSSConnectionInfo)info;
+ foreach(KeyValuePair<string, string> e in wssinfo.headers)
+ {
+ ctx["ws." + e.Key] = e.Value;
+ }
+ }
+
return ctx;
}
}
diff --git a/csharp/test/IceSSL/certs/makecerts.py b/csharp/test/IceSSL/certs/makecerts.py
index 4e413e7a926..73a18296d47 100755
--- a/csharp/test/IceSSL/certs/makecerts.py
+++ b/csharp/test/IceSSL/certs/makecerts.py
@@ -66,6 +66,12 @@ cai2 = cai1.getIntermediateFactory("intermediate1")
if force or not os.path.exists("cacert1.pem"): ca1.getCA().save("cacert1.pem")
if force or not os.path.exists("cacert2.pem"): ca2.getCA().save("cacert2.pem")
+if force or not os.path.exists("cacert1.der"): ca1.getCA().save("cacert1.der")
+if force or not os.path.exists("cacerts.pem"):
+ pem = ""
+ with open("cacert1.pem", "r") as f: pem += f.read()
+ with open("cacert2.pem", "r") as f: pem += f.read()
+ with open("cacerts.pem", "w") as f: f.write(pem);
certs = [
(ca1, "s_rsa_ca1", None, {}),
@@ -88,7 +94,7 @@ certs = [
for (ca, alias, path, args) in certs:
if not path: path = alias
cert = ca.get(alias)
- if force or not os.path.exists(path + ".p12"):
+ if force or not os.path.exists(path + ".p12"):
cert.save(path + ".p12", **args)
# Also export the ca2 self-signed certificate, it's used by the tests to test self-signed certificates
diff --git a/csharp/test/IceSSL/configuration/AllTests.cs b/csharp/test/IceSSL/configuration/AllTests.cs
index cd890b61f86..d81617df54c 100644
--- a/csharp/test/IceSSL/configuration/AllTests.cs
+++ b/csharp/test/IceSSL/configuration/AllTests.cs
@@ -89,7 +89,7 @@ public class AllTests
}
if(ca.Length > 0)
{
- d["IceSSL.CertAuthFile"] = ca + ".pem";
+ d["IceSSL.CAs"] = ca + ".pem";
}
d["IceSSL.Password"] = "password";
return d;
@@ -105,7 +105,7 @@ public class AllTests
}
if(ca.Length > 0)
{
- initData.properties.setProperty("IceSSL.CertAuthFile", ca + ".pem");
+ initData.properties.setProperty("IceSSL.CAs", ca + ".pem");
}
initData.properties.setProperty("IceSSL.Password", "password");
return initData;
@@ -208,7 +208,7 @@ public class AllTests
coll.Add(cert);
initData = createClientProps(defaultProperties, defaultDir, defaultHost);
initData.properties.setProperty("Ice.InitPlugins", "0");
- initData.properties.setProperty("IceSSL.CertAuthFile", caCert1File);
+ initData.properties.setProperty("IceSSL.CAs", caCert1File);
Ice.Communicator comm = Ice.Util.initialize(ref args, initData);
Ice.PluginManager pm = comm.getPluginManager();
IceSSL.Plugin plugin = (IceSSL.Plugin)pm.getPlugin("IceSSL");
@@ -289,7 +289,7 @@ public class AllTests
test(!((IceSSL.ConnectionInfo)server.ice_getConnection().getInfo()).verified);
}
catch(Ice.LocalException ex)
- {
+ {
Console.WriteLine(ex.ToString());
test(false);
}
@@ -314,7 +314,7 @@ public class AllTests
test(((IceSSL.ConnectionInfo)server.ice_getConnection().getInfo()).verified);
}
catch(Ice.LocalException ex)
- {
+ {
Console.WriteLine(ex.ToString());
test(false);
}
@@ -336,7 +336,7 @@ public class AllTests
server.noCert();
}
catch(Ice.LocalException)
- {
+ {
test(false);
}
fact.destroyServer(server);
@@ -652,260 +652,278 @@ public class AllTests
Console.Out.Write("testing certificate chains... ");
Console.Out.Flush();
{
- IceSSL.NativeConnectionInfo info;
-
- initData = createClientProps(defaultProperties, defaultDir, defaultHost, "", "");
- initData.properties.setProperty("IceSSL.VerifyPeer", "0");
- Ice.Communicator comm = Ice.Util.initialize(initData);
-
- Test.ServerFactoryPrx fact = Test.ServerFactoryPrxHelper.checkedCast(comm.stringToProxy(factoryRef));
- test(fact != null);
-
- //
- // The client can't verify the server certificate but it should
- // still provide it. "s_rsa_ca1" doesn't include the root so the
- // cert size should be 1.
- //
- d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_ca1", "");
- d["IceSSL.VerifyPeer"] = "0";
- Test.ServerPrx server = fact.createServer(d);
- try
- {
- info = (IceSSL.NativeConnectionInfo)server.ice_getConnection().getInfo();
- test(info.nativeCerts.Length == 1);
- test(!info.verified);
- }
- catch(Ice.LocalException)
- {
- test(false);
- }
- fact.destroyServer(server);
-
- //
- // Setting the CA for the server shouldn't change anything, it
- // shouldn't modify the cert chain sent to the client.
- //
- d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_ca1", "cacert1");
- d["IceSSL.VerifyPeer"] = "0";
- server = fact.createServer(d);
- try
- {
- info = (IceSSL.NativeConnectionInfo)server.ice_getConnection().getInfo();
- test(info.nativeCerts.Length == 1);
- test(!info.verified);
- }
- catch(Ice.LocalException)
+ X509Store certStore = new X509Store("My", StoreLocation.CurrentUser);
+ certStore.Open(OpenFlags.ReadWrite);
+ X509Certificate2Collection certs = new X509Certificate2Collection();
+ certs.Import(defaultDir + "/s_rsa_cai2.p12", "password", X509KeyStorageFlags.DefaultKeySet);
+ foreach(X509Certificate2 cert in certs)
{
- test(false);
+ certStore.Add(cert);
}
- fact.destroyServer(server);
-
- //
- // The client can't verify the server certificate but should
- // still provide it. "s_rsa_wroot_ca1" includes the root so
- // the cert size should be 2.
- //
- d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_wroot_ca1", "");
- d["IceSSL.VerifyPeer"] = "0";;
- server = fact.createServer(d);
try
{
- info = (IceSSL.NativeConnectionInfo)server.ice_getConnection().getInfo();
- test(info.nativeCerts.Length == 1); // Like the SChannel transport, .NET never sends the root.
- }
- catch(Ice.LocalException)
- {
- test(false);
- }
- fact.destroyServer(server);
- comm.destroy();
+ IceSSL.NativeConnectionInfo info;
- //
- // Now the client verifies the server certificate
- //
- initData = createClientProps(defaultProperties, defaultDir, defaultHost, "", "cacert1");
- initData.properties.setProperty("IceSSL.VerifyPeer", "1");
- comm = Ice.Util.initialize(initData);
+ initData = createClientProps(defaultProperties, defaultDir, defaultHost, "", "");
+ initData.properties.setProperty("IceSSL.VerifyPeer", "0");
+ Ice.Communicator comm = Ice.Util.initialize(initData);
- fact = Test.ServerFactoryPrxHelper.checkedCast(comm.stringToProxy(factoryRef));
- test(fact != null);
+ Test.ServerFactoryPrx fact = Test.ServerFactoryPrxHelper.checkedCast(comm.stringToProxy(factoryRef));
+ test(fact != null);
- {
+ //
+ // The client can't verify the server certificate but it should
+ // still provide it. "s_rsa_ca1" doesn't include the root so the
+ // cert size should be 1.
+ //
d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_ca1", "");
- d["IceSSL.VerifyPeer"] = "0";;
- server = fact.createServer(d);
+ d["IceSSL.VerifyPeer"] = "0";
+ Test.ServerPrx server = fact.createServer(d);
try
{
info = (IceSSL.NativeConnectionInfo)server.ice_getConnection().getInfo();
- test(info.nativeCerts.Length == 2);
- test(info.verified);
+ test(info.nativeCerts.Length == 1);
+ test(!info.verified);
}
catch(Ice.LocalException)
{
test(false);
}
fact.destroyServer(server);
- }
-
- //
- // Try certificate with one intermediate and VerifyDepthMax=2
- //
- initData = createClientProps(defaultProperties, defaultDir, defaultHost, "", "cacert1");
- initData.properties.setProperty("IceSSL.VerifyPeer", "1");
- initData.properties.setProperty("IceSSL.VerifyDepthMax", "2");
- comm = Ice.Util.initialize(initData);
- fact = Test.ServerFactoryPrxHelper.checkedCast(comm.stringToProxy(factoryRef));
- test(fact != null);
-
- {
- d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_cai1", "");
- d["IceSSL.VerifyPeer"] = "0";;
+ //
+ // Setting the CA for the server shouldn't change anything, it
+ // shouldn't modify the cert chain sent to the client.
+ //
+ d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_ca1", "cacert1");
+ d["IceSSL.VerifyPeer"] = "0";
server = fact.createServer(d);
try
{
- server.ice_getConnection().getInfo();
- test(false);
- }
- catch(Ice.SecurityException)
- {
- // Chain length too long
+ info = (IceSSL.NativeConnectionInfo)server.ice_getConnection().getInfo();
+ test(info.nativeCerts.Length == 1);
+ test(!info.verified);
}
catch(Ice.LocalException)
{
test(false);
}
fact.destroyServer(server);
- }
- comm.destroy();
-
- //
- // Set VerifyDepthMax to 3 (the default)
- //
- initData = createClientProps(defaultProperties, defaultDir, defaultHost, "", "cacert1");
- initData.properties.setProperty("IceSSL.VerifyPeer", "1");
- //initData.properties.setProperty("IceSSL.VerifyDepthMax", "3");
- comm = Ice.Util.initialize(initData);
- fact = Test.ServerFactoryPrxHelper.checkedCast(comm.stringToProxy(factoryRef));
- test(fact != null);
-
- {
- d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_cai1", "");
+ //
+ // The client can't verify the server certificate but should
+ // still provide it. "s_rsa_wroot_ca1" includes the root so
+ // the cert size should be 2.
+ //
+ d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_wroot_ca1", "");
d["IceSSL.VerifyPeer"] = "0";;
server = fact.createServer(d);
try
{
info = (IceSSL.NativeConnectionInfo)server.ice_getConnection().getInfo();
- test(info.nativeCerts.Length == 3);
- test(info.verified);
+ test(info.nativeCerts.Length == 1); // Like the SChannel transport, .NET never sends the root.
}
catch(Ice.LocalException)
{
test(false);
}
fact.destroyServer(server);
- }
+ comm.destroy();
+
+ //
+ // Now the client verifies the server certificate
+ //
+ initData = createClientProps(defaultProperties, defaultDir, defaultHost, "", "cacert1");
+ initData.properties.setProperty("IceSSL.VerifyPeer", "1");
+ comm = Ice.Util.initialize(initData);
+
+ fact = Test.ServerFactoryPrxHelper.checkedCast(comm.stringToProxy(factoryRef));
+ test(fact != null);
- {
- d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_cai2", "");
- d["IceSSL.VerifyPeer"] = "0";;
- server = fact.createServer(d);
- try
{
- server.ice_getConnection().getInfo();
- test(false);
+ d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_ca1", "");
+ d["IceSSL.VerifyPeer"] = "0";;
+ server = fact.createServer(d);
+ try
+ {
+ info = (IceSSL.NativeConnectionInfo)server.ice_getConnection().getInfo();
+ test(info.nativeCerts.Length == 2);
+ test(info.verified);
+ }
+ catch(Ice.LocalException)
+ {
+ test(false);
+ }
+ fact.destroyServer(server);
}
- catch(Ice.SecurityException)
+
+ //
+ // Try certificate with one intermediate and VerifyDepthMax=2
+ //
+ initData = createClientProps(defaultProperties, defaultDir, defaultHost, "", "cacert1");
+ initData.properties.setProperty("IceSSL.VerifyPeer", "1");
+ initData.properties.setProperty("IceSSL.VerifyDepthMax", "2");
+ comm = Ice.Util.initialize(initData);
+
+ fact = Test.ServerFactoryPrxHelper.checkedCast(comm.stringToProxy(factoryRef));
+ test(fact != null);
+
{
- // Chain length too long
+ d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_cai1", "");
+ d["IceSSL.VerifyPeer"] = "0";;
+ server = fact.createServer(d);
+ try
+ {
+ server.ice_getConnection().getInfo();
+ test(false);
+ }
+ catch(Ice.SecurityException)
+ {
+ // Chain length too long
+ }
+ catch(Ice.LocalException)
+ {
+ test(false);
+ }
+ fact.destroyServer(server);
}
- fact.destroyServer(server);
- }
- comm.destroy();
+ comm.destroy();
- //
- // Increase VerifyDepthMax to 4
- //
- initData = createClientProps(defaultProperties, defaultDir, defaultHost, "", "cacert1");
- initData.properties.setProperty("IceSSL.VerifyPeer", "1");
- initData.properties.setProperty("IceSSL.VerifyDepthMax", "4");
- comm = Ice.Util.initialize(initData);
+ //
+ // Set VerifyDepthMax to 3 (the default)
+ //
+ initData = createClientProps(defaultProperties, defaultDir, defaultHost, "", "cacert1");
+ initData.properties.setProperty("IceSSL.VerifyPeer", "1");
+ //initData.properties.setProperty("IceSSL.VerifyDepthMax", "3");
+ comm = Ice.Util.initialize(initData);
- fact = Test.ServerFactoryPrxHelper.checkedCast(comm.stringToProxy(factoryRef));
- test(fact != null);
+ fact = Test.ServerFactoryPrxHelper.checkedCast(comm.stringToProxy(factoryRef));
+ test(fact != null);
- {
- d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_cai2", "");
- d["IceSSL.VerifyPeer"] = "0";;
- server = fact.createServer(d);
- try
{
- info = (IceSSL.NativeConnectionInfo)server.ice_getConnection().getInfo();
- test(info.nativeCerts.Length == 4);
- test(info.verified);
+ d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_cai1", "");
+ d["IceSSL.VerifyPeer"] = "0";;
+ server = fact.createServer(d);
+ try
+ {
+ info = (IceSSL.NativeConnectionInfo)server.ice_getConnection().getInfo();
+ test(info.nativeCerts.Length == 3);
+ test(info.verified);
+ }
+ catch(Ice.LocalException)
+ {
+ test(false);
+ }
+ fact.destroyServer(server);
}
- catch(Ice.LocalException)
+
{
- test(false);
+ d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_cai2", "");
+ d["IceSSL.VerifyPeer"] = "0";;
+ server = fact.createServer(d);
+ try
+ {
+ server.ice_getConnection().getInfo();
+ test(false);
+ }
+ catch(Ice.SecurityException)
+ {
+ // Chain length too long
+ }
+ fact.destroyServer(server);
}
- fact.destroyServer(server);
- }
-
- comm.destroy();
+ comm.destroy();
- //
- // Increase VerifyDepthMax to 4
- //
- initData = createClientProps(defaultProperties, defaultDir, defaultHost, "c_rsa_cai2", "cacert1");
- initData.properties.setProperty("IceSSL.VerifyPeer", "1");
- initData.properties.setProperty("IceSSL.VerifyDepthMax", "4");
- comm = Ice.Util.initialize(initData);
+ //
+ // Increase VerifyDepthMax to 4
+ //
+ initData = createClientProps(defaultProperties, defaultDir, defaultHost, "", "cacert1");
+ initData.properties.setProperty("IceSSL.VerifyPeer", "1");
+ initData.properties.setProperty("IceSSL.VerifyDepthMax", "4");
+ comm = Ice.Util.initialize(initData);
- fact = Test.ServerFactoryPrxHelper.checkedCast(comm.stringToProxy(factoryRef));
- test(fact != null);
+ fact = Test.ServerFactoryPrxHelper.checkedCast(comm.stringToProxy(factoryRef));
+ test(fact != null);
- {
- d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_cai2", "cacert1");
- d["IceSSL.VerifyPeer"] = "2";
- server = fact.createServer(d);
- try
{
- server.ice_getConnection();
- test(false);
- }
- catch(Ice.ProtocolException)
- {
- // Expected
+ d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_cai2", "");
+ d["IceSSL.VerifyPeer"] = "0";;
+ server = fact.createServer(d);
+ try
+ {
+ info = (IceSSL.NativeConnectionInfo)server.ice_getConnection().getInfo();
+ test(info.nativeCerts.Length == 4);
+ test(info.verified);
+ }
+ catch(Ice.LocalException)
+ {
+ test(false);
+ }
+ fact.destroyServer(server);
}
- catch(Ice.ConnectionLostException)
+
+ comm.destroy();
+
+ //
+ // Increase VerifyDepthMax to 4
+ //
+ initData = createClientProps(defaultProperties, defaultDir, defaultHost, "c_rsa_cai2", "cacert1");
+ initData.properties.setProperty("IceSSL.VerifyPeer", "1");
+ initData.properties.setProperty("IceSSL.VerifyDepthMax", "4");
+ comm = Ice.Util.initialize(initData);
+
+ fact = Test.ServerFactoryPrxHelper.checkedCast(comm.stringToProxy(factoryRef));
+ test(fact != null);
+
{
- // Expected
+ d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_cai2", "cacert1");
+ d["IceSSL.VerifyPeer"] = "2";
+ server = fact.createServer(d);
+ try
+ {
+ server.ice_getConnection();
+ test(false);
+ }
+ catch(Ice.ProtocolException)
+ {
+ // Expected
+ }
+ catch(Ice.ConnectionLostException)
+ {
+ // Expected
+ }
+ catch(Ice.LocalException)
+ {
+ test(false);
+ }
+ fact.destroyServer(server);
}
- catch(Ice.LocalException)
+
{
- test(false);
+ d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_cai2", "cacert1");
+ d["IceSSL.VerifyPeer"] = "2";
+ d["IceSSL.VerifyDepthMax"] = "4";
+ server = fact.createServer(d);
+ try
+ {
+ server.ice_getConnection();
+ }
+ catch(Ice.LocalException)
+ {
+ test(false);
+ }
+ fact.destroyServer(server);
}
- fact.destroyServer(server);
- }
+ comm.destroy();
+ }
+ finally
{
- d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_cai2", "cacert1");
- d["IceSSL.VerifyPeer"] = "2";
- d["IceSSL.VerifyDepthMax"] = "4";
- server = fact.createServer(d);
- try
- {
- server.ice_getConnection();
- }
- catch(Ice.LocalException)
+ foreach(X509Certificate2 cert in certs)
{
- test(false);
+ certStore.Remove(cert);
}
- fact.destroyServer(server);
}
-
- comm.destroy();
}
Console.Out.WriteLine("ok");
@@ -1210,6 +1228,55 @@ public class AllTests
}
Console.Out.WriteLine("ok");
}
+
+ Console.Out.Write("testing multiple CA certificates... ");
+ Console.Out.Flush();
+ {
+ initData = createClientProps(defaultProperties, defaultDir, defaultHost, "c_rsa_ca1", "cacerts");
+ Ice.Communicator comm = Ice.Util.initialize(initData);
+ Test.ServerFactoryPrx fact = Test.ServerFactoryPrxHelper.checkedCast(comm.stringToProxy(factoryRef));
+ test(fact != null);
+ d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_ca2", "cacerts");
+ d["IceSSL.VerifyPeer"] = "2";
+ Test.ServerPrx server = fact.createServer(d);
+ try
+ {
+ server.ice_ping();
+ }
+ catch(Ice.LocalException)
+ {
+ test(false);
+ }
+ fact.destroyServer(server);
+ comm.destroy();
+ }
+ Console.Out.WriteLine("ok");
+
+ Console.Out.Write("testing DER CA certificate... ");
+ Console.Out.Flush();
+ {
+ initData = createClientProps(defaultProperties, defaultDir, defaultHost, "c_rsa_ca1", "");
+ initData.properties.setProperty("IceSSL.CAs", "cacert1.der");
+ Ice.Communicator comm = Ice.Util.initialize(initData);
+ Test.ServerFactoryPrx fact = Test.ServerFactoryPrxHelper.checkedCast(comm.stringToProxy(factoryRef));
+ test(fact != null);
+ d = createServerProps(defaultProperties, defaultDir, defaultHost, "s_rsa_ca1", "");
+ d["IceSSL.VerifyPeer"] = "2";
+ d["IceSSL.CAs"] = "cacert1.der";
+ Test.ServerPrx server = fact.createServer(d);
+ try
+ {
+ server.ice_ping();
+ }
+ catch(Ice.LocalException)
+ {
+ test(false);
+ }
+ fact.destroyServer(server);
+ comm.destroy();
+ }
+ Console.Out.WriteLine("ok");
+
Console.Out.Write("testing passwords... ");
Console.Out.Flush();
{
@@ -2165,6 +2232,48 @@ public class AllTests
}
}
Console.Out.WriteLine("ok");
+
+ Console.Out.Write("testing system CAs... ");
+ Console.Out.Flush();
+ {
+ initData = createClientProps(defaultProperties, defaultDir, defaultHost);
+ initData.properties.setProperty("IceSSL.VerifyDepthMax", "4");
+ initData.properties.setProperty("Ice.Override.Timeout", "5000"); // 5s timeout
+ Ice.Communicator comm = Ice.Util.initialize(initData);
+ Ice.ObjectPrx p = comm.stringToProxy("dummy:wss -h demo.zeroc.com -p 5064");
+ try
+ {
+ p.ice_ping();
+ test(false);
+ }
+ catch(Ice.SecurityException)
+ {
+ // Expected, by default we don't check for system CAs.
+ }
+ catch(Ice.LocalException)
+ {
+ test(false);
+ }
+
+ initData = createClientProps(defaultProperties, defaultDir, defaultHost);
+ initData.properties.setProperty("IceSSL.VerifyDepthMax", "4");
+ initData.properties.setProperty("Ice.Override.Timeout", "5000"); // 5s timeout
+ initData.properties.setProperty("IceSSL.UsePlatformCAs", "1");
+ comm = Ice.Util.initialize(initData);
+ p = comm.stringToProxy("dummy:wss -h demo.zeroc.com -p 5064");
+ IceSSL.WSSConnectionInfo info;
+ try
+ {
+ info = (IceSSL.WSSConnectionInfo)p.ice_getConnection().getInfo();
+ test(info.verified);
+ }
+ catch(Ice.LocalException)
+ {
+ test(false);
+ }
+ comm.destroy();
+ }
+ Console.Out.WriteLine("ok");
}
finally
{
diff --git a/java/src/Ice/src/main/java/IceInternal/PropertyNames.java b/java/src/Ice/src/main/java/IceInternal/PropertyNames.java
index d3660b21946..54868a2488f 100644
--- a/java/src/Ice/src/main/java/IceInternal/PropertyNames.java
+++ b/java/src/Ice/src/main/java/IceInternal/PropertyNames.java
@@ -6,7 +6,7 @@
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
-// Generated by makeprops.py from file ../config/PropertyNames.xml, Tue Dec 9 12:08:30 2014
+// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Apr 28 17:34:50 2015
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -188,6 +188,7 @@ public final class PropertyNames
new Property("Ice\\.Warn\\.UnusedProperties", false, null),
new Property("Ice\\.CacheMessageBuffers", false, null),
new Property("Ice\\.ThreadInterruptSafe", false, null),
+ new Property("Ice\\.Voip", false, null),
null
};
@@ -969,8 +970,9 @@ public final class PropertyNames
public static final Property IceSSLProps[] =
{
new Property("IceSSL\\.Alias", false, null),
- new Property("IceSSL\\.CertAuthDir", false, null),
- new Property("IceSSL\\.CertAuthFile", false, null),
+ new Property("IceSSL\\.CAs", false, null),
+ new Property("IceSSL\\.CertAuthDir", true, null),
+ new Property("IceSSL\\.CertAuthFile", true, null),
new Property("IceSSL\\.CertStore", false, null),
new Property("IceSSL\\.CertFile", false, null),
new Property("IceSSL\\.CertVerifier", false, null),
@@ -982,10 +984,10 @@ public final class PropertyNames
new Property("IceSSL\\.DHParams", false, null),
new Property("IceSSL\\.EntropyDaemon", false, null),
new Property("IceSSL\\.FindCert", false, null),
- new Property("IceSSL\\.FindCert\\.[^\\s]+", false, null),
+ new Property("IceSSL\\.FindCert\\.[^\\s]+", true, null),
new Property("IceSSL\\.ImportCert\\.[^\\s]+", true, null),
new Property("IceSSL\\.InitOpenSSL", false, null),
- new Property("IceSSL\\.KeyFile", false, null),
+ new Property("IceSSL\\.KeyFile", true, null),
new Property("IceSSL\\.KeySet", false, null),
new Property("IceSSL\\.Keychain", false, null),
new Property("IceSSL\\.KeychainPassword", false, null),
@@ -1008,6 +1010,7 @@ public final class PropertyNames
new Property("IceSSL\\.Truststore", false, null),
new Property("IceSSL\\.TruststorePassword", false, null),
new Property("IceSSL\\.TruststoreType", false, null),
+ new Property("IceSSL\\.UsePlatformCAs", false, null),
new Property("IceSSL\\.VerifyDepthMax", false, null),
new Property("IceSSL\\.VerifyPeer", false, null),
null
diff --git a/java/src/Ice/src/main/java/IceInternal/TcpEndpointI.java b/java/src/Ice/src/main/java/IceInternal/TcpEndpointI.java
index be274252438..a4547612335 100644
--- a/java/src/Ice/src/main/java/IceInternal/TcpEndpointI.java
+++ b/java/src/Ice/src/main/java/IceInternal/TcpEndpointI.java
@@ -9,7 +9,7 @@
package IceInternal;
-final class TcpEndpointI extends IPEndpointI
+final class TcpEndpointI extends IPEndpointI implements WSEndpointDelegate
{
public TcpEndpointI(ProtocolInstance instance, String ho, int po, java.net.InetSocketAddress sourceAddr, int ti,
String conId, boolean co)
@@ -40,27 +40,57 @@ final class TcpEndpointI extends IPEndpointI
public Ice.EndpointInfo getInfo()
{
Ice.TCPEndpointInfo info = new Ice.TCPEndpointInfo()
+ {
+ @Override
+ public short type()
{
- @Override
- public short type()
- {
- return TcpEndpointI.this.type();
- }
+ return TcpEndpointI.this.type();
+ }
- @Override
- public boolean datagram()
- {
- return TcpEndpointI.this.datagram();
- }
+ @Override
+ public boolean datagram()
+ {
+ return TcpEndpointI.this.datagram();
+ }
- @Override
- public boolean secure()
- {
- return TcpEndpointI.this.secure();
- }
- };
+ @Override
+ public boolean secure()
+ {
+ return TcpEndpointI.this.secure();
+ }
+ };
+ fillEndpointInfo(info);
+ return info;
+ }
+
+ //
+ // Return the WebSocket endpoint information.
+ //
+ @Override
+ public Ice.EndpointInfo getWSInfo(String resource)
+ {
+ Ice.WSEndpointInfo info = new Ice.WSEndpointInfo()
+ {
+ @Override
+ public short type()
+ {
+ return TcpEndpointI.this.type();
+ }
+ @Override
+ public boolean datagram()
+ {
+ return TcpEndpointI.this.datagram();
+ }
+
+ @Override
+ public boolean secure()
+ {
+ return TcpEndpointI.this.secure();
+ }
+ };
fillEndpointInfo(info);
+ info.resource = resource;
return info;
}
diff --git a/java/src/Ice/src/main/java/IceInternal/TcpTransceiver.java b/java/src/Ice/src/main/java/IceInternal/TcpTransceiver.java
index 997ddc09d8c..94a5717b02d 100644
--- a/java/src/Ice/src/main/java/IceInternal/TcpTransceiver.java
+++ b/java/src/Ice/src/main/java/IceInternal/TcpTransceiver.java
@@ -9,7 +9,7 @@
package IceInternal;
-final class TcpTransceiver implements Transceiver
+final class TcpTransceiver implements Transceiver, WSTransceiverDelegate
{
@Override
public java.nio.channels.SelectableChannel fd()
@@ -79,22 +79,16 @@ final class TcpTransceiver implements Transceiver
public Ice.ConnectionInfo getInfo()
{
Ice.TCPConnectionInfo info = new Ice.TCPConnectionInfo();
- if(_stream.fd() != null)
- {
- java.net.Socket socket = _stream.fd().socket();
- info.localAddress = socket.getLocalAddress().getHostAddress();
- info.localPort = socket.getLocalPort();
- if(socket.getInetAddress() != null)
- {
- info.remoteAddress = socket.getInetAddress().getHostAddress();
- info.remotePort = socket.getPort();
- }
- if(!socket.isClosed())
- {
- info.rcvSize = Network.getRecvBufferSize(_stream.fd());
- info.sndSize = Network.getSendBufferSize(_stream.fd());
- }
- }
+ fillConnectionInfo(info);
+ return info;
+ }
+
+ @Override
+ public Ice.ConnectionInfo getWSInfo(java.util.Map<String, String> headers)
+ {
+ Ice.WSConnectionInfo info = new Ice.WSConnectionInfo();
+ fillConnectionInfo(info);
+ info.headers = headers; // Provided header is a copy so no need to clone here.
return info;
}
@@ -115,6 +109,26 @@ final class TcpTransceiver implements Transceiver
_stream = stream;
}
+ private void fillConnectionInfo(Ice.IPConnectionInfo info)
+ {
+ if(_stream.fd() != null)
+ {
+ java.net.Socket socket = _stream.fd().socket();
+ info.localAddress = socket.getLocalAddress().getHostAddress();
+ info.localPort = socket.getLocalPort();
+ if(socket.getInetAddress() != null)
+ {
+ info.remoteAddress = socket.getInetAddress().getHostAddress();
+ info.remotePort = socket.getPort();
+ }
+ if(!socket.isClosed())
+ {
+ info.rcvSize = Network.getRecvBufferSize(_stream.fd());
+ info.sndSize = Network.getSendBufferSize(_stream.fd());
+ }
+ }
+ }
+
final private ProtocolInstance _instance;
final private StreamSocket _stream;
}
diff --git a/java/src/Ice/src/main/java/IceInternal/WSEndpoint.java b/java/src/Ice/src/main/java/IceInternal/WSEndpoint.java
index 7716771e919..dd64dbfb8af 100644
--- a/java/src/Ice/src/main/java/IceInternal/WSEndpoint.java
+++ b/java/src/Ice/src/main/java/IceInternal/WSEndpoint.java
@@ -41,29 +41,8 @@ final class WSEndpoint extends IceInternal.EndpointI
@Override
public Ice.EndpointInfo getInfo()
{
- Ice.WSEndpointInfo info = new Ice.WSEndpointInfo()
- {
- @Override
- public short type()
- {
- return WSEndpoint.this.type();
- }
-
- @Override
- public boolean datagram()
- {
- return WSEndpoint.this.datagram();
- }
-
- @Override
- public boolean secure()
- {
- return WSEndpoint.this.secure();
- }
- };
- _delegate.fillEndpointInfo(info);
- info.resource = _resource;
- return info;
+ assert(_delegate instanceof WSEndpointDelegate);
+ return ((WSEndpointDelegate)_delegate).getWSInfo(_resource);
}
@Override
diff --git a/java/src/Ice/src/main/java/IceInternal/WSTransceiver.java b/java/src/Ice/src/main/java/IceInternal/WSTransceiver.java
index fa8e1279fb2..d4ceb98f777 100644
--- a/java/src/Ice/src/main/java/IceInternal/WSTransceiver.java
+++ b/java/src/Ice/src/main/java/IceInternal/WSTransceiver.java
@@ -478,16 +478,8 @@ final class WSTransceiver implements Transceiver
@Override
public Ice.ConnectionInfo getInfo()
{
- Ice.IPConnectionInfo di = (Ice.IPConnectionInfo)_delegate.getInfo();
- Ice.WSConnectionInfo info = new Ice.WSConnectionInfo();
- info.localAddress = di.localAddress;
- info.localPort = di.localPort;
- info.remoteAddress = di.remoteAddress;
- info.remotePort = di.remotePort;
- info.rcvSize = di.rcvSize;
- info.sndSize = di.sndSize;
- info.headers = _parser.getHeaders();
- return info;
+ assert(_delegate instanceof WSTransceiverDelegate);
+ return ((WSTransceiverDelegate)_delegate).getWSInfo(_parser.getHeaders());
}
@Override
diff --git a/java/src/Ice/src/main/java/IceSSL/EndpointI.java b/java/src/Ice/src/main/java/IceSSL/EndpointI.java
index 8a922bf4e0d..266d59ce306 100644
--- a/java/src/Ice/src/main/java/IceSSL/EndpointI.java
+++ b/java/src/Ice/src/main/java/IceSSL/EndpointI.java
@@ -9,7 +9,7 @@
package IceSSL;
-final class EndpointI extends IceInternal.IPEndpointI
+final class EndpointI extends IceInternal.IPEndpointI implements IceInternal.WSEndpointDelegate
{
public EndpointI(Instance instance, String ho, int po, java.net.InetSocketAddress sourceAddr, int ti, String conId,
boolean co)
@@ -43,27 +43,57 @@ final class EndpointI extends IceInternal.IPEndpointI
public Ice.EndpointInfo getInfo()
{
Ice.IPEndpointInfo info = new IceSSL.EndpointInfo()
+ {
+ @Override
+ public short type()
{
- @Override
- public short type()
- {
- return EndpointI.this.type();
- }
+ return EndpointI.this.type();
+ }
- @Override
- public boolean datagram()
- {
- return EndpointI.this.datagram();
- }
+ @Override
+ public boolean datagram()
+ {
+ return EndpointI.this.datagram();
+ }
- @Override
- public boolean secure()
- {
- return EndpointI.this.secure();
- }
- };
+ @Override
+ public boolean secure()
+ {
+ return EndpointI.this.secure();
+ }
+ };
+ fillEndpointInfo(info);
+ return info;
+ }
+
+ //
+ // Return the secure WebSocket endpoint information.
+ //
+ @Override
+ public Ice.EndpointInfo getWSInfo(String resource)
+ {
+ IceSSL.WSSEndpointInfo info = new IceSSL.WSSEndpointInfo()
+ {
+ @Override
+ public short type()
+ {
+ return EndpointI.this.type();
+ }
+ @Override
+ public boolean datagram()
+ {
+ return EndpointI.this.datagram();
+ }
+
+ @Override
+ public boolean secure()
+ {
+ return EndpointI.this.secure();
+ }
+ };
fillEndpointInfo(info);
+ info.resource = resource;
return info;
}
diff --git a/java/src/Ice/src/main/java/IceSSL/SSLEngine.java b/java/src/Ice/src/main/java/IceSSL/SSLEngine.java
index bacb4a9cf26..daf4efdbc12 100644
--- a/java/src/Ice/src/main/java/IceSSL/SSLEngine.java
+++ b/java/src/Ice/src/main/java/IceSSL/SSLEngine.java
@@ -507,20 +507,70 @@ class SSLEngine
}
}
}
- else
- {
- ts = keys;
- }
//
- // Collect the trust managers.
+ // Collect the trust managers. Use IceSSL.Truststore if
+ // specified, otherwise use the Java root CAs if
+ // Ice.Use.PlatformCAs is enabled. If none of these are enabled,
+ // use the keystore or a dummy trust manager which rejects any
+ // certificate.
//
javax.net.ssl.TrustManager[] trustManagers = null;
{
String algorithm = javax.net.ssl.TrustManagerFactory.getDefaultAlgorithm();
javax.net.ssl.TrustManagerFactory tmf = javax.net.ssl.TrustManagerFactory.getInstance(algorithm);
- tmf.init(ts);
- trustManagers = tmf.getTrustManagers();
+ java.security.KeyStore trustStore = null;
+ if(ts != null)
+ {
+ trustStore = ts;
+ }
+ else if(properties.getPropertyAsInt("IceSSL.UsePlatformCAs") <= 0)
+ {
+ if(keys != null)
+ {
+ trustStore = keys;
+ }
+ else
+ {
+ trustManagers = new javax.net.ssl.TrustManager[]
+ {
+ new javax.net.ssl.X509TrustManager()
+ {
+ @Override
+ public void
+ checkClientTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException
+ {
+ throw new CertificateException("no trust anchors");
+ }
+
+ @Override
+ public void
+ checkServerTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException
+ {
+ throw new CertificateException("no trust anchors");
+ }
+
+ @Override
+ public X509Certificate[]
+ getAcceptedIssuers()
+ {
+ return new X509Certificate[0];
+ }
+ }
+ };
+ }
+ }
+ else
+ {
+ trustStore = null;
+ }
+ if(trustManagers == null)
+ {
+ tmf.init(trustStore);
+ trustManagers = tmf.getTrustManagers();
+ }
assert(trustManagers != null);
}
@@ -537,11 +587,17 @@ class SSLEngine
X509Certificate[] certs = ((javax.net.ssl.X509TrustManager)tm).getAcceptedIssuers();
for(X509Certificate cert : certs)
{
- anchors.add(new TrustAnchor(cert, null));
+ if(cert.getBasicConstraints() >= 0) // Only add CAs
+ {
+ anchors.add(new TrustAnchor(cert, null));
+ }
}
}
- _validatorParams = new PKIXParameters(anchors);
- _validatorParams.setRevocationEnabled(false);
+ if(!anchors.isEmpty())
+ {
+ _validatorParams = new PKIXParameters(anchors);
+ _validatorParams.setRevocationEnabled(false);
+ }
//
// Wrap each trust manager.
@@ -575,6 +631,11 @@ class SSLEngine
Certificate[] getVerifiedCertificateChain(Certificate[] chain)
{
+ if(_validatorParams == null)
+ {
+ return null; // Couldn't validate the given certificate chain.
+ }
+
List<Certificate> certs = new ArrayList<Certificate>(java.util.Arrays.asList(chain));
try
{
diff --git a/java/src/Ice/src/main/java/IceSSL/TransceiverI.java b/java/src/Ice/src/main/java/IceSSL/TransceiverI.java
index c9de921c8f4..89828ffa495 100644
--- a/java/src/Ice/src/main/java/IceSSL/TransceiverI.java
+++ b/java/src/Ice/src/main/java/IceSSL/TransceiverI.java
@@ -13,7 +13,7 @@ import java.nio.*;
import javax.net.ssl.*;
import javax.net.ssl.SSLEngineResult.*;
-final class TransceiverI implements IceInternal.Transceiver
+final class TransceiverI implements IceInternal.Transceiver, IceInternal.WSTransceiverDelegate
{
@Override
public java.nio.channels.SelectableChannel fd()
@@ -39,7 +39,7 @@ final class TransceiverI implements IceInternal.Transceiver
//
// Additional verification.
//
- _instance.verifyPeer(getNativeConnectionInfo(), _stream.fd(), _host);
+ _instance.verifyPeer((NativeConnectionInfo)getInfo(), _stream.fd(), _host);
if(_instance.securityTraceLevel() >= 1)
{
@@ -233,7 +233,18 @@ final class TransceiverI implements IceInternal.Transceiver
@Override
public Ice.ConnectionInfo getInfo()
{
- return getNativeConnectionInfo();
+ NativeConnectionInfo info = new NativeConnectionInfo();
+ info.nativeCerts = fillConnectionInfo(info);
+ return info;
+ }
+
+ @Override
+ public Ice.ConnectionInfo getWSInfo(java.util.Map<String, String> headers)
+ {
+ WSSNativeConnectionInfo info = new WSSNativeConnectionInfo();
+ info.nativeCerts = fillConnectionInfo(info);
+ info.headers = headers; // Provided header is a copy so no need to clone here.
+ return info;
}
@Override
@@ -267,12 +278,12 @@ final class TransceiverI implements IceInternal.Transceiver
}
}
- private NativeConnectionInfo getNativeConnectionInfo()
+ private java.security.cert.Certificate[] fillConnectionInfo(ConnectionInfo info)
{
//
// This can only be called on an open transceiver.
//
- NativeConnectionInfo info = new NativeConnectionInfo();
+ java.security.cert.Certificate[] nativeCerts = null;
if(_stream.fd() != null)
{
java.net.Socket socket = _stream.fd().socket();
@@ -305,10 +316,9 @@ final class TransceiverI implements IceInternal.Transceiver
java.security.cert.Certificate[] pcerts = session.getPeerCertificates();
java.security.cert.Certificate[] vcerts = _instance.engine().getVerifiedCertificateChain(pcerts);
info.verified = vcerts != null;
- info.nativeCerts = vcerts != null ? vcerts : pcerts;
-
+ nativeCerts = vcerts != null ? vcerts : pcerts;
java.util.ArrayList<String> certs = new java.util.ArrayList<String>();
- for(java.security.cert.Certificate c : info.nativeCerts)
+ for(java.security.cert.Certificate c : nativeCerts)
{
StringBuilder s = new StringBuilder("-----BEGIN CERTIFICATE-----\n");
s.append(IceUtilInternal.Base64.encode(c.getEncoded()));
@@ -327,7 +337,7 @@ final class TransceiverI implements IceInternal.Transceiver
}
info.adapterName = _adapterName;
info.incoming = _incoming;
- return info;
+ return nativeCerts;
}
private int handshakeNonBlocking()
diff --git a/java/test/src/main/java/test/Ice/info/AllTests.java b/java/test/src/main/java/test/Ice/info/AllTests.java
index f3059ac59c4..ce135750bb4 100644
--- a/java/test/src/main/java/test/Ice/info/AllTests.java
+++ b/java/test/src/main/java/test/Ice/info/AllTests.java
@@ -53,7 +53,7 @@ public class AllTests
test(ipEndpoint.type() == Ice.TCPEndpointType.value && ipEndpoint instanceof Ice.TCPEndpointInfo ||
ipEndpoint.type() == IceSSL.EndpointType.value && ipEndpoint instanceof IceSSL.EndpointInfo ||
ipEndpoint.type() == Ice.WSEndpointType.value && ipEndpoint instanceof Ice.WSEndpointInfo ||
- ipEndpoint.type() == Ice.WSSEndpointType.value && ipEndpoint instanceof Ice.WSEndpointInfo);
+ ipEndpoint.type() == Ice.WSSEndpointType.value && ipEndpoint instanceof IceSSL.WSSEndpointInfo);
Ice.UDPEndpointInfo udpEndpoint = (Ice.UDPEndpointInfo)endps[1].getInfo();
test(udpEndpoint.host.equals("udphost"));
@@ -175,12 +175,19 @@ public class AllTests
if(base.ice_getConnection().type().equals("ws") || base.ice_getConnection().type().equals("wss"))
{
- test(info instanceof Ice.WSConnectionInfo);
- Ice.WSConnectionInfo wsinfo = (Ice.WSConnectionInfo)info;
- test(wsinfo.headers.get("Upgrade").equals("websocket"));
- test(wsinfo.headers.get("Connection").equals("Upgrade"));
- test(wsinfo.headers.get("Sec-WebSocket-Protocol").equals("ice.zeroc.com"));
- test(wsinfo.headers.get("Sec-WebSocket-Accept") != null);
+ java.util.Map<String, String> headers;
+ if(info instanceof Ice.WSConnectionInfo)
+ {
+ headers = ((Ice.WSConnectionInfo)info).headers;
+ }
+ else
+ {
+ headers = ((IceSSL.WSSConnectionInfo)info).headers;
+ }
+ test(headers.get("Upgrade").equals("websocket"));
+ test(headers.get("Connection").equals("Upgrade"));
+ test(headers.get("Sec-WebSocket-Protocol").equals("ice.zeroc.com"));
+ test(headers.get("Sec-WebSocket-Accept") != null);
test(ctx.get("ws.Upgrade").equals("websocket"));
test(ctx.get("ws.Connection").equals("Upgrade"));
diff --git a/java/test/src/main/java/test/Ice/info/TestI.java b/java/test/src/main/java/test/Ice/info/TestI.java
index 6a149c6d53f..d90cf8ed75d 100644
--- a/java/test/src/main/java/test/Ice/info/TestI.java
+++ b/java/test/src/main/java/test/Ice/info/TestI.java
@@ -70,6 +70,15 @@ public class TestI extends _TestIntfDisp
}
}
+ if(info instanceof IceSSL.WSSConnectionInfo)
+ {
+ IceSSL.WSSConnectionInfo wssinfo = (IceSSL.WSSConnectionInfo)info;
+ for(java.util.Map.Entry<String, String> e : wssinfo.headers.entrySet())
+ {
+ ctx.put("ws." + e.getKey(), e.getValue());
+ }
+ }
+
return ctx;
}
}
diff --git a/java/test/src/main/java/test/IceSSL/configuration/AllTests.java b/java/test/src/main/java/test/IceSSL/configuration/AllTests.java
index f53beb315f5..ae632d80947 100644
--- a/java/test/src/main/java/test/IceSSL/configuration/AllTests.java
+++ b/java/test/src/main/java/test/IceSSL/configuration/AllTests.java
@@ -204,6 +204,7 @@ public class AllTests
}
catch(Ice.LocalException ex)
{
+ ex.printStackTrace();
test(false);
}
fact.destroyServer(server);
@@ -682,7 +683,7 @@ public class AllTests
}
fact.destroyServer(server);
}
-
+
comm.destroy();
//
@@ -2224,6 +2225,48 @@ public class AllTests
}
out.println("ok");
+ out.print("testing system CAs... ");
+ out.flush();
+ {
+ initData = createClientProps(defaultProperties, defaultDir, defaultHost);
+ initData.properties.setProperty("IceSSL.VerifyDepthMax", "4");
+ initData.properties.setProperty("Ice.Override.Timeout", "5000"); // 5s timeout
+ Ice.Communicator comm = Ice.Util.initialize(initData);
+ Ice.ObjectPrx p = comm.stringToProxy("dummy:wss -h demo.zeroc.com -p 5064");
+ try
+ {
+ p.ice_ping();
+ test(false);
+ }
+ catch(Ice.SecurityException ex)
+ {
+ // Expected, by default we don't check for system CAs.
+ }
+ catch(Ice.LocalException ex)
+ {
+ test(false);
+ }
+
+ initData = createClientProps(defaultProperties, defaultDir, defaultHost);
+ initData.properties.setProperty("IceSSL.VerifyDepthMax", "4");
+ initData.properties.setProperty("Ice.Override.Timeout", "5000"); // 5s timeout
+ initData.properties.setProperty("IceSSL.UsePlatformCAs", "1");
+ comm = Ice.Util.initialize(initData);
+ p = comm.stringToProxy("dummy:wss -h demo.zeroc.com -p 5064");
+ IceSSL.WSSConnectionInfo info;
+ try
+ {
+ info = (IceSSL.WSSConnectionInfo)p.ice_getConnection().getInfo();
+ test(info.verified);
+ }
+ catch(Ice.LocalException ex)
+ {
+ test(false);
+ }
+ comm.destroy();
+ }
+ out.println("ok");
+
return factory;
}
}
diff --git a/js/src/Ice/PropertyNames.js b/js/src/Ice/PropertyNames.js
index 49b3c928d1f..4b1fe5b144a 100644
--- a/js/src/Ice/PropertyNames.js
+++ b/js/src/Ice/PropertyNames.js
@@ -6,7 +6,7 @@
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
-// Generated by makeprops.py from file ../config/PropertyNames.xml, Tue Dec 9 12:08:30 2014
+// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Apr 28 17:34:50 2015
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -189,6 +189,7 @@ PropertyNames.IceProps =
new Property("/^Ice\.Warn\.UnusedProperties/", false, null),
new Property("/^Ice\.CacheMessageBuffers/", false, null),
new Property("/^Ice\.ThreadInterruptSafe/", false, null),
+ new Property("/^Ice\.Voip/", false, null),
];
/* jshint +W044*/
diff --git a/js/src/Ice/WSEndpoint.js b/js/src/Ice/WSEndpoint.js
index 6ccc3dcaf40..42160ed4a05 100644
--- a/js/src/Ice/WSEndpoint.js
+++ b/js/src/Ice/WSEndpoint.js
@@ -16,7 +16,8 @@ Ice.__M.require(module,
"../Ice/StringUtil",
"../Ice/EndpointI",
"../Ice/LocalException",
- "../Ice/WSTransceiver"
+ "../Ice/WSTransceiver",
+ "../Ice/EndpointInfo"
]);
var HashUtil = Ice.HashUtil;
@@ -33,7 +34,7 @@ var WSEndpoint = Class(EndpointI, {
},
getInfo: function()
{
- var info = new Ice.WSEndpointInfo();
+ var info = this._delegate.secure() ? new IceSSL.WSSEndpointInfo() : new Ice.WSEndpointInfo();
info.resource = this._resource;
this._delegate.fillEndpointInfo(info);
return info;
diff --git a/js/src/Ice/browser/WSTransceiver.js b/js/src/Ice/browser/WSTransceiver.js
index e0a16ed45cb..9cea74acd92 100644
--- a/js/src/Ice/browser/WSTransceiver.js
+++ b/js/src/Ice/browser/WSTransceiver.js
@@ -18,7 +18,8 @@ Ice.__M.require(module,
"../Ice/Connection",
"../Ice/Exception",
"../Ice/LocalException",
- "../Ice/Timer"
+ "../Ice/Timer",
+ "../Ice/ConnectionInfo"
]);
var Debug = Ice.Debug;
@@ -284,7 +285,7 @@ var WSTransceiver = Ice.Class({
getInfo: function()
{
Debug.assert(this._fd !== null);
- var info = new Ice.WSConnectionInfo();
+ var info = this._secure ? new IceSSL.WSSConnectionInfo() : new Ice.WSConnectionInfo();
//
// The WebSocket API doens't provide this info
diff --git a/js/src/Ice/sources.json b/js/src/Ice/sources.json
index 953d085b91e..751d4c7cbff 100644
--- a/js/src/Ice/sources.json
+++ b/js/src/Ice/sources.json
@@ -20,7 +20,8 @@
"Ice/Router.ice",
"Ice/SliceChecksumDict.ice",
"Ice/Version.ice",
- "IceSSL/EndpointInfo.ice"],
+ "IceSSL/EndpointInfo.ice",
+ "IceSSL/ConnectionInfo.ice"],
"common": [
"ACM.js",
diff --git a/js/test/Ice/proxy/Client.js b/js/test/Ice/proxy/Client.js
index 38bdd4d2310..d31c1f9b1b1 100644
--- a/js/test/Ice/proxy/Client.js
+++ b/js/test/Ice/proxy/Client.js
@@ -10,6 +10,7 @@
(function(module, require, exports)
{
var Ice = require("ice").Ice;
+ var IceSSL = require("ice").IceSSL;
var Test = require("Test").Test;
var Promise = Ice.Promise;
@@ -916,7 +917,7 @@
}
var p1, pstr;
-
+
// Legal TCP endpoint expressed as opaque endpoint
p1 = communicator.stringToProxy("test -e 1.1:opaque -e 1.0 -t 1 -v CTEyNy4wLjAuMeouAAAQJwAAAA==");
pstr = communicator.proxyToString(p1);
@@ -1019,6 +1020,40 @@
).then(
function()
{
+ var p = communicator.stringToProxy("test:default -p 12010");
+ if(defaultProtocol === "tcp")
+ {
+ test(p.ice_getEndpoints()[0].getInfo() instanceof Ice.TCPEndpointInfo);
+ }
+ else if(defaultProtocol === "ws")
+ {
+ test(p.ice_getEndpoints()[0].getInfo() instanceof Ice.WSEndpointInfo);
+ }
+ else if(defaultProtocol === "wss")
+ {
+ test(p.ice_getEndpoints()[0].getInfo() instanceof IceSSL.WSSEndpointInfo);
+ }
+ return p.ice_getConnection()
+ }
+ ).then(
+ function(con)
+ {
+ if(defaultProtocol === "tcp")
+ {
+ test(con.getInfo() instanceof Ice.TCPConnectionInfo);
+ }
+ else if(defaultProtocol === "ws")
+ {
+ test(con.getInfo() instanceof Ice.WSConnectionInfo);
+ }
+ else if(defaultProtocol === "wss")
+ {
+ test(con.getInfo() instanceof IceSSL.WSSConnectionInfo);
+ }
+ }
+ ).then(
+ function()
+ {
out.writeLine("ok");
var derived = Test.MyDerivedClassPrx.uncheckedCast(communicator.stringToProxy("test:default -p 12010"));
return derived.shutdown();
diff --git a/python/modules/IcePy/ConnectionInfo.cpp b/python/modules/IcePy/ConnectionInfo.cpp
index 2381bb303ba..455d8a8296b 100644
--- a/python/modules/IcePy/ConnectionInfo.cpp
+++ b/python/modules/IcePy/ConnectionInfo.cpp
@@ -14,7 +14,6 @@
#include <EndpointInfo.h>
#include <Util.h>
#include <Ice/Object.h>
-
using namespace std;
using namespace IcePy;
diff --git a/scripts/Expect.py b/scripts/Expect.py
index cc92aff163e..c367b5b63a9 100755
--- a/scripts/Expect.py
+++ b/scripts/Expect.py
@@ -18,6 +18,7 @@ import sys
import threading
import time
import traceback
+import types
__all__ = ["Expect", "EOF", "TIMEOUT" ]
@@ -133,7 +134,9 @@ class reader(threading.Thread):
content = self._tbuf.getvalue()
suppress = False
for p in self._tracesuppress:
- if p.search(content):
+ if isinstance(p, types.LambdaType) or isinstance(p, types.FunctionType):
+ content = p(content)
+ elif p.search(content):
suppress = True
break
if not suppress:
diff --git a/scripts/TestUtil.py b/scripts/TestUtil.py
index 2a7003c6ce0..1109cedfde7 100755
--- a/scripts/TestUtil.py
+++ b/scripts/TestUtil.py
@@ -25,7 +25,8 @@ global x86
x86 = False # Binary distribution is 32-bit
cpp11 = False # Binary distribution is c++11
extraArgs = []
-
+clientTraceFilters = []
+serverTraceFilters = []
# Default java loader
@@ -867,7 +868,7 @@ class InvalidSelectorString(Exception):
sslConfigTree = {
"cpp" : {
"plugin" : " --Ice.Plugin.IceSSL=IceSSL:createIceSSL --IceSSL.Password=password " +
- "--IceSSL.DefaultDir=%(certsdir)s --IceSSL.CertAuthFile=cacert.pem --IceSSL.VerifyPeer=%(verifyPeer)s",
+ "--IceSSL.DefaultDir=%(certsdir)s --IceSSL.CAs=cacert.pem --IceSSL.VerifyPeer=%(verifyPeer)s",
"client" : " --IceSSL.CertFile=client.p12",
"server" : " --IceSSL.CertFile=server.p12",
"colloc" : " --IceSSL.CertFile=client.p12"
@@ -880,7 +881,7 @@ sslConfigTree = {
"colloc" : " --IceSSL.Keystore=client.jks"
},
"csharp" : {
- "plugin" : " --Ice.Plugin.IceSSL=%(icesslcs)s:IceSSL.PluginFactory --IceSSL.CertAuthFile=cacert.pem " +
+ "plugin" : " --Ice.Plugin.IceSSL=%(icesslcs)s:IceSSL.PluginFactory --IceSSL.CAs=cacert.pem " +
"--IceSSL.Password=password --IceSSL.DefaultDir=%(certsdir)s --IceSSL.VerifyPeer=%(verifyPeer)s",
"client" : " --IceSSL.CertFile=client.p12 --IceSSL.CheckCertName=0",
"server" : " --IceSSL.CertFile=server.p12",
@@ -1261,7 +1262,7 @@ def spawn(cmd, cwd=None):
def spawnClient(cmd, env=None, cwd=None, echo=True, startReader=True, lang=None):
client = _spawn(cmd, env, cwd, startReader=startReader, lang=lang)
if echo:
- client.trace()
+ client.trace(clientTraceFilters)
return client
def spawnServer(cmd, env=None, cwd=None, count=1, adapter=None, echo=True, lang=None, mx=False, timeout=60):
@@ -1278,7 +1279,7 @@ def spawnServer(cmd, env=None, cwd=None, count=1, adapter=None, echo=True, lang=
server.expect("[^\n]+ ready\n", timeout = timeout)
count = count - 1
if echo:
- server.trace([re.compile("[^\n]+ ready")])
+ server.trace([re.compile("[^\n]+ ready")] + serverTraceFilters)
return server
import subprocess
@@ -1821,6 +1822,7 @@ def getTestEnv(lang, testdir):
if iceHome:
addClasspath(os.path.join(getIceDir("java", testdir), "lib", "db.jar"), env)
elif thirdPartyHome:
+ suffix = ""
if x64:
suffix = "x64"
else:
diff --git a/slice/Ice/Connection.ice b/slice/Ice/Connection.ice
index bc8db075af4..773ff20c335 100644
--- a/slice/Ice/Connection.ice
+++ b/slice/Ice/Connection.ice
@@ -22,8 +22,7 @@ module Ice
/**
*
- * Base class providing access to the connection details.
- *
+ * Base class providing access to the connection details. *
**/
local class ConnectionInfo
{
@@ -343,7 +342,7 @@ dictionary<string, string> HeaderDict;
* Provides access to the connection details of a WebSocket connection
*
**/
-local class WSConnectionInfo extends IPConnectionInfo
+local class WSConnectionInfo extends TCPConnectionInfo
{
/** The headers from the HTTP upgrade request. */
HeaderDict headers;
diff --git a/slice/Ice/Endpoint.ice b/slice/Ice/Endpoint.ice
index 4796b97b6f5..4b5dc03e21d 100644
--- a/slice/Ice/Endpoint.ice
+++ b/slice/Ice/Endpoint.ice
@@ -196,7 +196,7 @@ local class UDPEndpointInfo extends IPEndpointInfo
* Provides access to a WebSocket endpoint information.
*
**/
-local class WSEndpointInfo extends IPEndpointInfo
+local class WSEndpointInfo extends TCPEndpointInfo
{
/**
*
diff --git a/slice/IceSSL/ConnectionInfo.ice b/slice/IceSSL/ConnectionInfo.ice
index a0dd0b13b1f..fcc1c24597d 100644
--- a/slice/IceSSL/ConnectionInfo.ice
+++ b/slice/IceSSL/ConnectionInfo.ice
@@ -34,5 +34,16 @@ local class ConnectionInfo extends Ice::IPConnectionInfo
bool verified;
};
+/**
+ *
+ * Provides access to the connection details of a secure WebSocket connection
+ *
+ **/
+local class WSSConnectionInfo extends ConnectionInfo
+{
+ /** The headers from the HTTP upgrade request. */
+ Ice::HeaderDict headers;
+};
+
};
diff --git a/slice/IceSSL/EndpointInfo.ice b/slice/IceSSL/EndpointInfo.ice
index 330f6aa5e47..5b1e7c823d2 100644
--- a/slice/IceSSL/EndpointInfo.ice
+++ b/slice/IceSSL/EndpointInfo.ice
@@ -40,5 +40,20 @@ local class EndpointInfo extends Ice::IPEndpointInfo
{
};
+/**
+ *
+ * Provides access to a secure WebSocket endpoint information.
+ *
+ **/
+local class WSSEndpointInfo extends EndpointInfo
+{
+ /**
+ *
+ * The URI configured with the endpoint.
+ *
+ **/
+ string resource;
+};
+
};