summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cs/demo/Glacier2/callback/config.client2
-rw-r--r--cs/demo/Glacier2/chat/config.client2
-rw-r--r--cs/demo/Ice/callback/config.client2
-rw-r--r--cs/demo/Ice/callback/config.server2
-rw-r--r--cs/demo/Ice/context/config.client2
-rw-r--r--cs/demo/Ice/context/config.server2
-rw-r--r--cs/demo/Ice/hello/config.client2
-rw-r--r--cs/demo/Ice/hello/config.server2
-rw-r--r--cs/demo/Ice/properties/config.client2
-rw-r--r--cs/demo/Ice/properties/config.server2
-rw-r--r--cs/demo/Ice/wpf/config.client2
-rw-r--r--cs/demo/IceBox/hello/config.client2
-rw-r--r--cs/demo/IceBox/hello/config.service2
-rw-r--r--cs/demo/IceDiscovery/hello/config.client2
-rw-r--r--cs/demo/IceDiscovery/hello/config.server2
-rw-r--r--cs/demo/IceDiscovery/replication/config.server2
-rw-r--r--cs/src/IceSSL/Plugin.cs13
-rw-r--r--cs/src/IceSSL/PluginI.cs5
-rw-r--r--cs/src/IceSSL/SSLEngine.cs57
-rw-r--r--cs/src/IceSSL/TransceiverI.cs53
-rw-r--r--cs/test/IceSSL/configuration/AllTests.cs39
-rwxr-xr-xscripts/TestUtil.py9
22 files changed, 181 insertions, 27 deletions
diff --git a/cs/demo/Glacier2/callback/config.client b/cs/demo/Glacier2/callback/config.client
index 1a982d96d65..cea66b0f5ec 100644
--- a/cs/demo/Glacier2/callback/config.client
+++ b/cs/demo/Glacier2/callback/config.client
@@ -50,6 +50,6 @@ Callback.Proxy=callback:tcp -h localhost -p 10000
#
Ice.Plugin.IceSSL=IceSSL:IceSSL.PluginFactory
IceSSL.DefaultDir=../../../../certs
-IceSSL.ImportCert.CurrentUser.Root=cacert.pem
+IceSSL.CertAuthFile=cacert.pem
IceSSL.CertFile=c_rsa1024.pfx
IceSSL.Password=password
diff --git a/cs/demo/Glacier2/chat/config.client b/cs/demo/Glacier2/chat/config.client
index 256104a5b3b..26898af4187 100644
--- a/cs/demo/Glacier2/chat/config.client
+++ b/cs/demo/Glacier2/chat/config.client
@@ -34,7 +34,7 @@
#
Ice.Plugin.IceSSL=IceSSL:IceSSL.PluginFactory
IceSSL.DefaultDir=../../../../certs
-IceSSL.ImportCert.CurrentUser.Root=cacert.pem
+IceSSL.CertAuthFile=cacert.pem
IceSSL.CertFile=c_rsa1024.pfx
IceSSL.Password=password
diff --git a/cs/demo/Ice/callback/config.client b/cs/demo/Ice/callback/config.client
index e95aeb23d31..ed214518a3a 100644
--- a/cs/demo/Ice/callback/config.client
+++ b/cs/demo/Ice/callback/config.client
@@ -47,6 +47,6 @@ Ice.Warn.Connections=1
#
Ice.Plugin.IceSSL=IceSSL:IceSSL.PluginFactory
IceSSL.DefaultDir=../../../../certs
-IceSSL.ImportCert.CurrentUser.Root=cacert.pem
+IceSSL.CertAuthFile=cacert.pem
IceSSL.CertFile=c_rsa1024.pfx
IceSSL.Password=password
diff --git a/cs/demo/Ice/callback/config.server b/cs/demo/Ice/callback/config.server
index b4e19652669..4dff589efa6 100644
--- a/cs/demo/Ice/callback/config.server
+++ b/cs/demo/Ice/callback/config.server
@@ -41,6 +41,6 @@ Ice.Warn.Connections=1
#
Ice.Plugin.IceSSL=IceSSL:IceSSL.PluginFactory
IceSSL.DefaultDir=../../../../certs
-IceSSL.ImportCert.CurrentUser.Root=cacert.pem
+IceSSL.CertAuthFile=cacert.pem
IceSSL.CertFile=s_rsa1024.pfx
IceSSL.Password=password
diff --git a/cs/demo/Ice/context/config.client b/cs/demo/Ice/context/config.client
index b1546086745..d1b4911105b 100644
--- a/cs/demo/Ice/context/config.client
+++ b/cs/demo/Ice/context/config.client
@@ -45,6 +45,6 @@ Ice.Warn.Connections=1
#
Ice.Plugin.IceSSL=IceSSL:IceSSL.PluginFactory
IceSSL.DefaultDir=../../../../certs
-IceSSL.ImportCert.CurrentUser.Root=cacert.pem
+IceSSL.CertAuthFile=cacert.pem
IceSSL.CertFile=c_rsa1024.pfx
IceSSL.Password=password
diff --git a/cs/demo/Ice/context/config.server b/cs/demo/Ice/context/config.server
index 306d4ec7874..7a97fa5217c 100644
--- a/cs/demo/Ice/context/config.server
+++ b/cs/demo/Ice/context/config.server
@@ -41,6 +41,6 @@ Ice.Warn.Connections=1
#
Ice.Plugin.IceSSL=IceSSL:IceSSL.PluginFactory
IceSSL.DefaultDir=../../../../certs
-IceSSL.ImportCert.CurrentUser.Root=cacert.pem
+IceSSL.CertAuthFile=cacert.pem
IceSSL.CertFile=s_rsa1024.pfx
IceSSL.Password=password
diff --git a/cs/demo/Ice/hello/config.client b/cs/demo/Ice/hello/config.client
index 95624d417e4..0838d3143d4 100644
--- a/cs/demo/Ice/hello/config.client
+++ b/cs/demo/Ice/hello/config.client
@@ -50,7 +50,7 @@ Ice.Warn.Connections=1
#
Ice.Plugin.IceSSL=IceSSL:IceSSL.PluginFactory
IceSSL.DefaultDir=../../../../certs
-IceSSL.ImportCert.CurrentUser.Root=cacert.pem
+IceSSL.CertAuthFile=cacert.pem
IceSSL.CertFile=c_rsa1024.pfx
IceSSL.Password=password
diff --git a/cs/demo/Ice/hello/config.server b/cs/demo/Ice/hello/config.server
index d88b411e680..136e14b3155 100644
--- a/cs/demo/Ice/hello/config.server
+++ b/cs/demo/Ice/hello/config.server
@@ -51,7 +51,7 @@ Ice.Warn.Connections=1
#
Ice.Plugin.IceSSL=IceSSL:IceSSL.PluginFactory
IceSSL.DefaultDir=../../../../certs
-IceSSL.ImportCert.CurrentUser.Root=cacert.pem
+IceSSL.CertAuthFile=cacert.pem
IceSSL.CertFile=s_rsa1024.pfx
IceSSL.Password=password
diff --git a/cs/demo/Ice/properties/config.client b/cs/demo/Ice/properties/config.client
index 76f2f4de50b..9f99baffbab 100644
--- a/cs/demo/Ice/properties/config.client
+++ b/cs/demo/Ice/properties/config.client
@@ -46,6 +46,6 @@ Ice.Warn.Connections=1
#
Ice.Plugin.IceSSL=IceSSL:IceSSL.PluginFactory
IceSSL.DefaultDir=../../../../certs
-IceSSL.ImportCert.CurrentUser.Root=cacert.pem
+IceSSL.CertAuthFile=cacert.pem
IceSSL.CertFile=c_rsa1024.pfx
IceSSL.Password=password
diff --git a/cs/demo/Ice/properties/config.server b/cs/demo/Ice/properties/config.server
index 31c7b0431d3..2cf04d54a6c 100644
--- a/cs/demo/Ice/properties/config.server
+++ b/cs/demo/Ice/properties/config.server
@@ -56,6 +56,6 @@ Ice.Warn.Connections=1
#
Ice.Plugin.IceSSL=IceSSL:IceSSL.PluginFactory
IceSSL.DefaultDir=../../../../certs
-IceSSL.ImportCert.CurrentUser.Root=cacert.pem
+IceSSL.CertAuthFile=cacert.pem
IceSSL.CertFile=s_rsa1024.pfx
IceSSL.Password=password
diff --git a/cs/demo/Ice/wpf/config.client b/cs/demo/Ice/wpf/config.client
index 70c719e2483..885224063d3 100644
--- a/cs/demo/Ice/wpf/config.client
+++ b/cs/demo/Ice/wpf/config.client
@@ -40,6 +40,6 @@ Ice.Warn.Connections=1
#
Ice.Plugin.IceSSL=IceSSL:IceSSL.PluginFactory
IceSSL.DefaultDir=../../../../certs
-IceSSL.ImportCert.CurrentUser.Root=cacert.pem
+IceSSL.CertAuthFile=cacert.pem
IceSSL.CertFile=c_rsa1024.pfx
IceSSL.Password=password
diff --git a/cs/demo/IceBox/hello/config.client b/cs/demo/IceBox/hello/config.client
index 438876b7bb9..5dead60547c 100644
--- a/cs/demo/IceBox/hello/config.client
+++ b/cs/demo/IceBox/hello/config.client
@@ -32,6 +32,6 @@ Ice.Warn.Connections=1
#
Ice.Plugin.IceSSL=IceSSL:IceSSL.PluginFactory
IceSSL.DefaultDir=../../../../certs
-IceSSL.ImportCert.CurrentUser.Root=cacert.pem
+IceSSL.CertAuthFile=cacert.pem
IceSSL.CertFile=c_rsa1024.pfx
IceSSL.Password=password
diff --git a/cs/demo/IceBox/hello/config.service b/cs/demo/IceBox/hello/config.service
index 51765a037de..fc5155105b6 100644
--- a/cs/demo/IceBox/hello/config.service
+++ b/cs/demo/IceBox/hello/config.service
@@ -32,6 +32,6 @@ Ice.Warn.Connections=1
#
Ice.Plugin.IceSSL="IceSSL,Version=3.5.1.0":IceSSL.PluginFactory
IceSSL.DefaultDir=../../../../certs
-IceSSL.ImportCert.CurrentUser.Root=cacert.pem
+IceSSL.CertAuthFile=cacert.pem
IceSSL.CertFile=s_rsa1024.pfx
IceSSL.Password=password
diff --git a/cs/demo/IceDiscovery/hello/config.client b/cs/demo/IceDiscovery/hello/config.client
index 879b4c378c6..561842811a9 100644
--- a/cs/demo/IceDiscovery/hello/config.client
+++ b/cs/demo/IceDiscovery/hello/config.client
@@ -44,7 +44,7 @@ Ice.Trace.Locator=1
#
Ice.Plugin.IceSSL=IceSSL:IceSSL.PluginFactory
IceSSL.DefaultDir=../../../../certs
-IceSSL.ImportCert.CurrentUser.Root=cacert.pem
+IceSSL.CertAuthFile=cacert.pem
IceSSL.CertFile=c_rsa1024.pfx
IceSSL.Password=password
diff --git a/cs/demo/IceDiscovery/hello/config.server b/cs/demo/IceDiscovery/hello/config.server
index 72d439f5275..d9978797d61 100644
--- a/cs/demo/IceDiscovery/hello/config.server
+++ b/cs/demo/IceDiscovery/hello/config.server
@@ -52,7 +52,7 @@ Ice.Plugin.IceDiscovery=IceDiscovery:IceDiscovery.PluginFactory
#
Ice.Plugin.IceSSL=IceSSL:IceSSL.PluginFactory
IceSSL.DefaultDir=../../../../certs
-IceSSL.ImportCert.CurrentUser.Root=cacert.pem
+IceSSL.CertAuthFile=cacert.pem
IceSSL.CertFile=c_rsa1024.pfx
IceSSL.Password=password
diff --git a/cs/demo/IceDiscovery/replication/config.server b/cs/demo/IceDiscovery/replication/config.server
index 72d439f5275..d9978797d61 100644
--- a/cs/demo/IceDiscovery/replication/config.server
+++ b/cs/demo/IceDiscovery/replication/config.server
@@ -52,7 +52,7 @@ Ice.Plugin.IceDiscovery=IceDiscovery:IceDiscovery.PluginFactory
#
Ice.Plugin.IceSSL=IceSSL:IceSSL.PluginFactory
IceSSL.DefaultDir=../../../../certs
-IceSSL.ImportCert.CurrentUser.Root=cacert.pem
+IceSSL.CertAuthFile=cacert.pem
IceSSL.CertFile=c_rsa1024.pfx
IceSSL.Password=password
diff --git a/cs/src/IceSSL/Plugin.cs b/cs/src/IceSSL/Plugin.cs
index 12906320f85..77abae5bbed 100644
--- a/cs/src/IceSSL/Plugin.cs
+++ b/cs/src/IceSSL/Plugin.cs
@@ -56,6 +56,19 @@ namespace IceSSL
abstract public void initialize();
/// <summary>
+ /// Specify the certificate authorities certificates to use
+ /// when validating SSL peer certificates. This must be done
+ /// before the plug-in is initialized; therefore, the application
+ /// must define the property Ice.InitPlugins=0, set the certificates,
+ /// and finally invoke initializePlugins on the PluginManager.
+ /// When the application supplies its own certificate authorities
+ /// certificates, the plug-in skips its normal property-based
+ /// configuration.
+ /// </summary>
+ /// <param name="certs">The certificate authorities certificates to use.</param>
+ abstract public void setCACertificates(X509Certificate2Collection certs);
+
+ /// <summary>
/// Specify the certificates to use for SSL connections. This
/// must be done before the plug-in is initialized; therefore,
/// the application must define the property Ice.InitPlugins=0,
diff --git a/cs/src/IceSSL/PluginI.cs b/cs/src/IceSSL/PluginI.cs
index 03fc8fca1b0..96cc476f8e1 100644
--- a/cs/src/IceSSL/PluginI.cs
+++ b/cs/src/IceSSL/PluginI.cs
@@ -57,6 +57,11 @@ namespace IceSSL
{
}
+ public override void setCACertificates(X509Certificate2Collection certs)
+ {
+ _engine.setCACertificates(certs);
+ }
+
public override void setCertificates(X509Certificate2Collection certs)
{
_engine.setCertificates(certs);
diff --git a/cs/src/IceSSL/SSLEngine.cs b/cs/src/IceSSL/SSLEngine.cs
index f75acee4959..1b27ffe1565 100644
--- a/cs/src/IceSSL/SSLEngine.cs
+++ b/cs/src/IceSSL/SSLEngine.cs
@@ -56,6 +56,13 @@ namespace IceSSL
keySet = "DefaultKeySet";
}
+ _certStore = properties.getPropertyWithDefault(prefix + "CertStore", "CurrentUser");
+ if(_certStore != "CurrentUser" && _certStore != "LocalMachine")
+ {
+ _logger.warning("Invalid IceSSL.CertStore value `" + _certStore + "' adjusted to `CurrentUser'");
+ _certStore = "CurrentUser";
+ }
+
X509KeyStorageFlags keyStorageFlags = X509KeyStorageFlags.DefaultKeySet;
if(keySet.Equals("UserKeySet"))
{
@@ -272,9 +279,57 @@ namespace IceSSL
}
}
+ if(_caCerts == null)
+ {
+ string certAuthFile = properties.getProperty(prefix + "CertAuthFile");
+ if(certAuthFile.Length > 0)
+ {
+ if(!checkPath(ref certAuthFile))
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: CA certificate file not found: " + certAuthFile;
+ throw e;
+ }
+
+ _caCerts = new X509Certificate2Collection();
+ try
+ {
+ _caCerts.Add(new X509Certificate2(certAuthFile));
+ }
+ catch(CryptographicException ex)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException(ex);
+ e.reason = "IceSSL: error while attempting to load CA certificate from " + certAuthFile;
+ throw e;
+ }
+ }
+ }
+
_initialized = true;
}
+ internal string certStore()
+ {
+ return _certStore;
+ }
+
+ internal X509Certificate2Collection caCerts()
+ {
+ return _caCerts;
+ }
+
+ internal void setCACertificates(X509Certificate2Collection caCerts)
+ {
+ if(_initialized)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: plug-in is already initialized";
+ throw e;
+ }
+
+ _caCerts = caCerts;
+ }
+
internal void setCertificates(X509Certificate2Collection certs)
{
if(_initialized)
@@ -1126,6 +1181,8 @@ namespace IceSSL
private int _verifyDepthMax;
private int _checkCRL;
private X509Certificate2Collection _certs;
+ private string _certStore;
+ private X509Certificate2Collection _caCerts;
private CertificateVerifier _verifier;
private PasswordCallback _passwordCallback;
private TrustManager _trustManager;
diff --git a/cs/src/IceSSL/TransceiverI.cs b/cs/src/IceSSL/TransceiverI.cs
index 27a5e6e2159..5d7e4f38aa6 100644
--- a/cs/src/IceSSL/TransceiverI.cs
+++ b/cs/src/IceSSL/TransceiverI.cs
@@ -502,6 +502,27 @@ namespace IceSSL
{
_verifyPeer = 0;
}
+
+ X509Certificate2Collection caCerts = _instance.engine().caCerts();
+ if(caCerts != null)
+ {
+ _chainEngine = new X509Chain(_instance.engine().certStore() == "LocalMachine");
+ //
+ // We need to set this flag to be able to use a certificate authority from the extra
+ // store.
+ //
+ _chainEngine.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
+
+ if(_instance.checkCRL() == 0)
+ {
+ _chainEngine.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
+ }
+
+ foreach(X509Certificate2 cert in caCerts)
+ {
+ _chainEngine.ChainPolicy.ExtraStore.Add(cert);
+ }
+ }
}
private NativeConnectionInfo getNativeConnectionInfo()
@@ -681,9 +702,24 @@ namespace IceSSL
}
}
- private bool validationCallback(object sender, X509Certificate certificate, X509Chain chain,
- SslPolicyErrors sslPolicyErrors)
+ private bool validationCallback(object sender, X509Certificate certificate, X509Chain chainEngine,
+ SslPolicyErrors policyErrors)
{
+
+ SslPolicyErrors sslPolicyErrors = policyErrors;
+ bool valid = false;
+ if(_chainEngine != null && certificate != null)
+ {
+ sslPolicyErrors = SslPolicyErrors.None;
+ valid = _chainEngine.Build(new X509Certificate2(certificate));
+ if(_chainEngine.ChainStatus.Length > 0)
+ {
+ sslPolicyErrors = SslPolicyErrors.RemoteCertificateChainErrors;
+ }
+ }
+
+ X509Chain chain = _chainEngine == null ? chainEngine : _chainEngine;
+
//
// The certificate chain is not available via SslStream, and it is destroyed
// after this callback returns, so we keep a reference to each of the
@@ -748,13 +784,17 @@ namespace IceSSL
int errorCount = chain.ChainStatus.Length;
foreach(X509ChainStatus status in chain.ChainStatus)
{
- if((certificate.Subject == certificate.Issuer) &&
- (status.Status == X509ChainStatusFlags.UntrustedRoot))
+ if(status.Status == X509ChainStatusFlags.UntrustedRoot && _chainEngine != null && valid)
{
//
- // Untrusted root for self-signed certificate is OK.
+ // Untrusted root is OK when using our custom chain engine if
+ // the CA certificate is present in the chain policy extra store.
//
- --errorCount;
+ X509ChainElement e = chain.ChainElements[chain.ChainElements.Count - 1];
+ if(_chainEngine.ChainPolicy.ExtraStore.Contains(e.Certificate))
+ {
+ --errorCount;
+ }
}
else if(status.Status == X509ChainStatusFlags.Revoked)
{
@@ -862,6 +902,7 @@ namespace IceSSL
private IceInternal.AsyncCallback _readCallback;
private IceInternal.AsyncCallback _writeCallback;
private X509Certificate2[] _chain;
+ private X509Chain _chainEngine;
private const int StateNeedConnect = 0;
private const int StateConnectPending = 1;
diff --git a/cs/test/IceSSL/configuration/AllTests.cs b/cs/test/IceSSL/configuration/AllTests.cs
index 886534ca7d7..5ee37b3a67e 100644
--- a/cs/test/IceSSL/configuration/AllTests.cs
+++ b/cs/test/IceSSL/configuration/AllTests.cs
@@ -194,6 +194,45 @@ public class AllTests
store.Remove(caCert1);
comm.destroy();
}
+
+ {
+ //
+ // Supply our own CA certificate.
+ //
+ X509Certificate2 cert = new X509Certificate2(defaultDir + "/cacert1.pem");
+ X509Certificate2Collection coll = new X509Certificate2Collection();
+ coll.Add(cert);
+ Ice.InitializationData initData = createClientProps(defaultProperties, testDir, defaultHost);
+ initData.properties.setProperty("Ice.InitPlugins", "0");
+ initData.properties.setProperty("IceSSL.CertFile", defaultDir + "/c_rsa_nopass_ca1.pfx");
+ initData.properties.setProperty("IceSSL.Password", "password");
+ Ice.Communicator comm = Ice.Util.initialize(ref args, initData);
+ Ice.PluginManager pm = comm.getPluginManager();
+ IceSSL.Plugin plugin = (IceSSL.Plugin)pm.getPlugin("IceSSL");
+ test(plugin != null);
+ plugin.setCACertificates(coll);
+ pm.initializePlugins();
+ Ice.ObjectPrx obj = comm.stringToProxy(factoryRef);
+ test(obj != null);
+ Test.ServerFactoryPrx fact = Test.ServerFactoryPrxHelper.checkedCast(obj);
+ Dictionary<string, string> d = createServerProps(defaultProperties, testDir, defaultHost);
+ d["IceSSL.CertFile"] = defaultDir + "/s_rsa_nopass_ca1.pfx";
+ d["IceSSL.CertAuthFile"] = defaultDir + "/cacert1.pem";
+ d["IceSSL.Password"] = "password";
+ d["IceSSL.VerifyPeer"] = "2";
+ Test.ServerPrx server = fact.createServer(d);
+ try
+ {
+ server.ice_ping();
+ }
+ catch(Ice.LocalException ex)
+ {
+ Console.WriteLine(ex.ToString());
+ test(false);
+ }
+ fact.destroyServer(server);
+ comm.destroy();
+ }
Console.Out.WriteLine("ok");
Console.Out.Write("testing certificate verification... ");
diff --git a/scripts/TestUtil.py b/scripts/TestUtil.py
index b3f4751945f..55044f19089 100755
--- a/scripts/TestUtil.py
+++ b/scripts/TestUtil.py
@@ -699,12 +699,11 @@ sslConfigTree = {
"colloc" : " --IceSSL.Keystore=client.jks"
},
"cs" : {
- "plugin" : " --Ice.Plugin.IceSSL=%(icesslcs)s:IceSSL.PluginFactory " +
- " --IceSSL.Password=password --IceSSL.DefaultDir=%(certsdir)s --IceSSL.VerifyPeer=%(verifyPeer)s",
+ "plugin" : " --Ice.Plugin.IceSSL=%(icesslcs)s:IceSSL.PluginFactory --IceSSL.CertAuthFile=cacert.pem " +
+ "--IceSSL.Password=password --IceSSL.DefaultDir=%(certsdir)s --IceSSL.VerifyPeer=%(verifyPeer)s",
"client" : " --IceSSL.CertFile=c_rsa1024.pfx --IceSSL.CheckCertName=0",
- "server" : " --IceSSL.CertFile=s_rsa1024.pfx --IceSSL.ImportCert.CurrentUser.Root=cacert.pem",
- "colloc" : " --IceSSL.CertFile=c_rsa1024.pfx --IceSSL.ImportCert.CurrentUser.Root=cacert.pem " +
- "--IceSSL.CheckCertName=0"
+ "server" : " --IceSSL.CertFile=s_rsa1024.pfx",
+ "colloc" : " --IceSSL.CertFile=c_rsa1024.pfx --IceSSL.CheckCertName=0"
},
}