summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Spruiell <mes@zeroc.com>2006-04-26 17:04:31 +0000
committerMark Spruiell <mes@zeroc.com>2006-04-26 17:04:31 +0000
commit4b7ac6e8197a8e9e729d69fd04b75f327953943f (patch)
treeeb07dc7faa9d7a1b6c09df90b796e8785d1284bb
parentmore fixes for two-stage initialization (diff)
downloadice-4b7ac6e8197a8e9e729d69fd04b75f327953943f.tar.bz2
ice-4b7ac6e8197a8e9e729d69fd04b75f327953943f.tar.xz
ice-4b7ac6e8197a8e9e729d69fd04b75f327953943f.zip
refactoring to remove Context
-rwxr-xr-xcs/src/IceSSL/AcceptorI.cs19
-rwxr-xr-xcs/src/IceSSL/ConnectorI.cs15
-rwxr-xr-xcs/src/IceSSL/Context.cs351
-rwxr-xr-xcs/src/IceSSL/IceSSL.csproj1
-rw-r--r--cs/src/IceSSL/Instance.cs374
-rw-r--r--java/src/IceSSL/AcceptorI.java23
-rw-r--r--java/src/IceSSL/ConnectorI.java19
-rw-r--r--java/src/IceSSL/Context.java474
-rw-r--r--java/src/IceSSL/Instance.java496
-rw-r--r--java/src/IceSSL/PluginI.java4
10 files changed, 855 insertions, 921 deletions
diff --git a/cs/src/IceSSL/AcceptorI.cs b/cs/src/IceSSL/AcceptorI.cs
index f8b4afc1d2e..a9326885429 100755
--- a/cs/src/IceSSL/AcceptorI.cs
+++ b/cs/src/IceSSL/AcceptorI.cs
@@ -71,7 +71,12 @@ namespace IceSSL
//
// The plugin may not be fully initialized.
//
- Context ctx = instance_.context();
+ if(!instance_.initialized())
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: plugin is not initialized";
+ throw ex;
+ }
Socket fd = IceInternal.Network.doAccept(fd_, timeout);
IceInternal.Network.setBlock(fd, true); // SSL requires a blocking socket.
@@ -95,7 +100,7 @@ namespace IceSSL
//
// Get the certificate collection and select the first one.
//
- X509Certificate2Collection certs = ctx.certs();
+ X509Certificate2Collection certs = instance_.certs();
X509Certificate2 cert = null;
if(certs.Count > 0)
{
@@ -108,9 +113,9 @@ namespace IceSSL
AuthInfo info = new AuthInfo();
info.stream = stream;
info.done = false;
- IAsyncResult ar = stream.BeginAuthenticateAsServer(cert, ctx.verifyPeer() > 1, ctx.protocols(),
- ctx.checkCRL(), new AsyncCallback(authCallback),
- info);
+ IAsyncResult ar = stream.BeginAuthenticateAsServer(cert, instance_.verifyPeer() > 1,
+ instance_.protocols(), instance_.checkCRL(),
+ new AsyncCallback(authCallback), info);
lock(info)
{
if(!info.done)
@@ -237,7 +242,7 @@ namespace IceSSL
//
// .NET requires that a certificate be supplied.
//
- X509Certificate2Collection certs = instance.context().certs();
+ X509Certificate2Collection certs = instance.certs();
if(certs.Count == 0)
{
Ice.SecurityException ex = new Ice.SecurityException();
@@ -314,7 +319,7 @@ namespace IceSSL
int errors = (int)sslPolicyErrors;
if((errors & (int)SslPolicyErrors.RemoteCertificateNotAvailable) > 0)
{
- if(instance_.context().verifyPeer() > 1)
+ if(instance_.verifyPeer() > 1)
{
if(instance_.securityTraceLevel() >= 1)
{
diff --git a/cs/src/IceSSL/ConnectorI.cs b/cs/src/IceSSL/ConnectorI.cs
index aa81fcad001..cdcb8a92092 100755
--- a/cs/src/IceSSL/ConnectorI.cs
+++ b/cs/src/IceSSL/ConnectorI.cs
@@ -25,7 +25,12 @@ namespace IceSSL
//
// The plugin may not be fully initialized.
//
- Context ctx = instance_.context();
+ if(!instance_.initialized())
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: plugin is not initialized";
+ throw ex;
+ }
if(instance_.networkTraceLevel() >= 2)
{
@@ -53,9 +58,9 @@ namespace IceSSL
AuthInfo info = new AuthInfo();
info.stream = stream;
info.done = false;
- IAsyncResult ar = stream.BeginAuthenticateAsClient(host_, ctx.certs(), ctx.protocols(),
- ctx.checkCRL(), new AsyncCallback(authCallback),
- info);
+ IAsyncResult ar = stream.BeginAuthenticateAsClient(host_, instance_.certs(), instance_.protocols(),
+ instance_.checkCRL(),
+ new AsyncCallback(authCallback), info);
lock(info)
{
if(!info.done)
@@ -196,7 +201,7 @@ namespace IceSSL
int errors = (int)sslPolicyErrors;
if((errors & (int)SslPolicyErrors.RemoteCertificateNameMismatch) > 0)
{
- if(!instance_.context().checkCertName())
+ if(!instance_.checkCertName())
{
errors ^= (int)SslPolicyErrors.RemoteCertificateNameMismatch;
message = message + "\nremote certificate name mismatch (ignored)";
diff --git a/cs/src/IceSSL/Context.cs b/cs/src/IceSSL/Context.cs
deleted file mode 100755
index 8c936d68cc8..00000000000
--- a/cs/src/IceSSL/Context.cs
+++ /dev/null
@@ -1,351 +0,0 @@
-// **********************************************************************
-//
-// Copyright (c) 2003-2006 ZeroC, Inc. All rights reserved.
-//
-// This copy of Ice is licensed to you under the terms described in the
-// ICE_LICENSE file included in this distribution.
-//
-// **********************************************************************
-
-namespace IceSSL
-{
- using System;
- using System.Collections;
- using System.IO;
- using System.Security.Authentication;
- using System.Security.Cryptography;
- using System.Security.Cryptography.X509Certificates;
-
- internal class Context
- {
- internal Context(Instance instance, X509Certificate2Collection certs)
- {
- instance_ = instance;
- logger_ = instance.communicator().getLogger();
-
- const string prefix = "IceSSL.";
- Ice.Properties properties = instance.communicator().getProperties();
-
- //
- // If the user doesn't supply a certificate collection, we need to examine
- // the property settings.
- //
- certs_ = certs;
- if(certs_ == null)
- {
- //
- // If IceSSL.CertFile is defined, load a certificate from a file and
- // add it to the collection.
- //
- // TODO: tracing?
- certs_ = new X509Certificate2Collection();
- string certFile = properties.getProperty(prefix + "CertFile");
- string password = properties.getProperty(prefix + "Password");
- if(certFile.Length > 0)
- {
- if(!instance_.checkPath(ref certFile))
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: certificate file not found: " + certFile;
- throw e;
- }
- try
- {
- X509Certificate2 cert = new X509Certificate2(certFile, password);
- certs_.Add(cert);
- }
- catch(CryptographicException ex)
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException(ex);
- e.reason = "IceSSL: error while attempting to load certificate from " + certFile;
- throw e;
- }
- }
-
- //
- // If IceSSL.FindCert.* properties are defined, add the selected certificates
- // to the collection.
- //
- // TODO: tracing?
- const string findPrefix = prefix + "FindCert.";
- Ice.PropertyDict certProps = properties.getPropertiesForPrefix(findPrefix);
- if(certProps.Count > 0)
- {
- foreach(DictionaryEntry entry in certProps)
- {
- string name = (string)entry.Key;
- string val = (string)entry.Value;
- if(val.Length > 0)
- {
- string storeSpec = name.Substring(findPrefix.Length);
- X509Certificate2Collection coll = findCertificates(name, storeSpec, val);
- certs_.AddRange(coll);
- }
- }
- if(certs_.Count == 0)
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: no client certificates found";
- throw e;
- }
- }
- }
-
- //
- // Determine whether a certificate is required from the peer.
- //
- verifyPeer_ = properties.getPropertyAsIntWithDefault(prefix + "VerifyPeer", 2);
-
- //
- // Select protocols.
- //
- protocols_ = parseProtocols(prefix + "Protocols");
-
- //
- // CheckCRL determines whether the certificate revocation list is checked.
- //
- checkCRL_ = properties.getPropertyAsIntWithDefault(prefix + "CheckCRL", 0) > 0;
-
- //
- // CheckCertName determines whether we compare the name in a peer's
- // certificate against its hostname.
- //
- checkCertName_ = properties.getPropertyAsIntWithDefault(prefix + "CheckCertName", 0) > 0;
- }
-
- internal X509Certificate2Collection certs()
- {
- return certs_;
- }
-
- internal int verifyPeer()
- {
- return verifyPeer_;
- }
-
- internal SslProtocols protocols()
- {
- return protocols_;
- }
-
- internal bool checkCRL()
- {
- return checkCRL_;
- }
-
- internal bool checkCertName()
- {
- return checkCertName_;
- }
-
- private SslProtocols parseProtocols(string property)
- {
- SslProtocols result = SslProtocols.Default;
- string val = instance_.communicator().getProperties().getProperty(property);
- if(val.Length > 0)
- {
- char[] delim = new char[] {',', ' '};
- string[] arr = val.Split(delim, StringSplitOptions.RemoveEmptyEntries);
- if(arr.Length > 0)
- {
- result = 0;
- for(int i = 0; i < arr.Length; ++i)
- {
- string s = arr[i].ToLower();
- if(s.Equals("ssl3") || s.Equals("sslv3"))
- {
- result |= SslProtocols.Ssl3;
- }
- else if(s.Equals("tls") || s.Equals("tls1") || s.Equals("tlsv1"))
- {
- result |= SslProtocols.Tls;
- }
- else
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: unrecognized protocol `" + s + "'";
- throw e;
- }
- }
- }
- }
- return result;
- }
-
- private X509Certificate2Collection findCertificates(string prop, string storeSpec, string value)
- {
- StoreLocation storeLoc = 0;
- StoreName storeName = 0;
- string storeNameStr = null;
- instance_.parseStore(prop, storeSpec, ref storeLoc, ref storeName, ref storeNameStr);
-
- //
- // Open the X509 certificate store.
- //
- X509Store store = null;
- try
- {
- if(storeNameStr != null)
- {
- store = new X509Store(storeNameStr, storeLoc);
- }
- else
- {
- store = new X509Store(storeName, storeLoc);
- }
- store.Open(OpenFlags.ReadOnly);
- }
- catch(Exception ex)
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException(ex);
- e.reason = "IceSSL: failure while opening store specified by " + prop;
- throw e;
- }
-
- //
- // Start with all of the certificates in the collection and filter as necessary.
- //
- // - If the value is "*", return all certificates.
- // - Otherwise, search using key:value pairs. The following keys are supported:
- //
- // Issuer
- // IssuerDN
- // Serial
- // Subject
- // SubjectDN
- // SubjectKeyId
- // Thumbprint
- //
- // A value must be enclosed in single or double quotes if it contains whitespace.
- //
- X509Certificate2Collection result = new X509Certificate2Collection();
- result.AddRange(store.Certificates);
- try
- {
- if(value != "*")
- {
- int start = 0;
- int pos;
- while((pos = value.IndexOf(':', start)) != -1)
- {
- //
- // Parse the X509FindType.
- //
- string field = value.Substring(start, pos - start).Trim().ToLower();
- X509FindType findType;
- if(field.Equals("subject"))
- {
- findType = X509FindType.FindBySubjectName;
- }
- else if(field.Equals("subjectdn"))
- {
- findType = X509FindType.FindBySubjectDistinguishedName;
- }
- else if(field.Equals("issuer"))
- {
- findType = X509FindType.FindByIssuerName;
- }
- else if(field.Equals("issuerdn"))
- {
- findType = X509FindType.FindByIssuerDistinguishedName;
- }
- else if(field.Equals("thumbprint"))
- {
- findType = X509FindType.FindByThumbprint;
- }
- else if(field.Equals("subjectkeyid"))
- {
- findType = X509FindType.FindBySubjectKeyIdentifier;
- }
- else if(field.Equals("serial"))
- {
- findType = X509FindType.FindBySerialNumber;
- }
- else
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: unknown key in `" + value + "'";
- throw e;
- }
-
- //
- // Parse the argument.
- //
- start = pos + 1;
- while(start < value.Length && (value[start] == ' ' || value[start] == '\t'))
- {
- ++start;
- }
- if(start == value.Length)
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: missing argument in `" + value + "'";
- throw e;
- }
-
- string arg;
- if(value[start] == '"' || value[start] == '\'')
- {
- int end = start;
- ++end;
- while(end < value.Length)
- {
- if(value[end] == value[start] && value[end - 1] != '\\')
- {
- break;
- }
- ++end;
- }
- if(end == value.Length || value[end] != value[start])
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: unmatched quote in `" + value + "'";
- throw e;
- }
- ++start;
- arg = value.Substring(start, end - start);
- start = end + 1;
- }
- else
- {
- char[] ws = new char[] { ' ', '\t' };
- int end = value.IndexOfAny(ws, start);
- if(end == -1)
- {
- arg = value.Substring(start);
- start = value.Length;
- }
- else
- {
- arg = value.Substring(start, end - start);
- start = end + 1;
- }
- }
-
- //
- // Execute the query.
- //
- // TODO: allow user to specify a value for validOnly?
- //
- bool validOnly = false;
- result = result.Find(findType, arg, validOnly);
- }
- }
- }
- finally
- {
- store.Close();
- }
-
- return result;
- }
-
- private Instance instance_;
- private Ice.Logger logger_;
- private X509Certificate2Collection certs_;
- private int verifyPeer_;
- private SslProtocols protocols_;
- private bool checkCRL_;
- private bool checkCertName_;
- }
-}
diff --git a/cs/src/IceSSL/IceSSL.csproj b/cs/src/IceSSL/IceSSL.csproj
index 65770e0c830..a9dc0410e4f 100755
--- a/cs/src/IceSSL/IceSSL.csproj
+++ b/cs/src/IceSSL/IceSSL.csproj
@@ -56,7 +56,6 @@
<ItemGroup>
<Compile Include="AcceptorI.cs" />
<Compile Include="ConnectorI.cs" />
- <Compile Include="Context.cs" />
<Compile Include="EndpointI.cs" />
<Compile Include="Instance.cs" />
<Compile Include="Plugin.cs" />
diff --git a/cs/src/IceSSL/Instance.cs b/cs/src/IceSSL/Instance.cs
index 290943b9f00..5241045f5a0 100644
--- a/cs/src/IceSSL/Instance.cs
+++ b/cs/src/IceSSL/Instance.cs
@@ -12,28 +12,48 @@ namespace IceSSL
using System;
using System.Collections;
using System.IO;
+ using System.Security.Authentication;
+ using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
internal class Instance
{
internal Instance(Ice.Communicator communicator)
{
- Ice.Properties properties = communicator.getProperties();
-
+ logger_ = communicator.getLogger();
facade_ = Ice.Util.getProtocolPluginFacade(communicator);
- securityTraceLevel_ = properties.getPropertyAsIntWithDefault("IceSSL.Trace.Security", 0);
+ securityTraceLevel_ = communicator.getProperties().getPropertyAsIntWithDefault("IceSSL.Trace.Security", 0);
securityTraceCategory_ = "Security";
+ initialized_ = false;
+
+ //
+ // Register the endpoint factory. We have to do this now, rather than
+ // in initialize, because the communicator may need to interpret
+ // proxies before the plugin is fully initialized.
+ //
+ facade_.addEndpointFactory(new EndpointFactoryI(this));
+ }
+
+ internal void initialize()
+ {
+ if(initialized_)
+ {
+ return;
+ }
+
+ const string prefix = "IceSSL.";
+ Ice.Properties properties = communicator().getProperties();
//
// Check for a default directory. We look in this directory for
// files mentioned in the configuration.
//
- defaultDir_ = properties.getProperty("IceSSL.DefaultDir");
+ defaultDir_ = properties.getProperty(prefix + "DefaultDir");
//
// Process IceSSL.ImportCert.* properties.
//
- Ice.PropertyDict certs = properties.getPropertiesForPrefix("IceSSL.ImportCert.");
+ Ice.PropertyDict certs = properties.getPropertiesForPrefix(prefix + "ImportCert.");
foreach(DictionaryEntry entry in certs)
{
string name = (string)entry.Key;
@@ -45,26 +65,96 @@ namespace IceSSL
}
//
- // Register the endpoint factory. We have to do this now, rather than
- // in initialize, because the communicator may need to interpret
- // proxies before the plugin is fully initialized.
+ // Select protocols.
//
- facade_.addEndpointFactory(new EndpointFactoryI(this));
- }
+ protocols_ = parseProtocols(prefix + "Protocols");
- internal void initialize()
- {
- if(context_ != null)
+ //
+ // CheckCertName determines whether we compare the name in a peer's
+ // certificate against its hostname.
+ //
+ checkCertName_ = properties.getPropertyAsIntWithDefault(prefix + "CheckCertName", 0) > 0;
+
+ //
+ // Determine whether a certificate is required from the peer.
+ //
+ verifyPeer_ = properties.getPropertyAsIntWithDefault(prefix + "VerifyPeer", 2);
+
+ //
+ // CheckCRL determines whether the certificate revocation list is checked.
+ //
+ checkCRL_ = properties.getPropertyAsIntWithDefault(prefix + "CheckCRL", 0) > 0;
+
+ //
+ // If the user hasn't supplied a certificate collection, we need to examine
+ // the property settings.
+ //
+ if(certs_ == null)
{
- return;
+ //
+ // If IceSSL.CertFile is defined, load a certificate from a file and
+ // add it to the collection.
+ //
+ // TODO: tracing?
+ certs_ = new X509Certificate2Collection();
+ string certFile = properties.getProperty(prefix + "CertFile");
+ string password = properties.getProperty(prefix + "Password");
+ if(certFile.Length > 0)
+ {
+ if(!checkPath(ref certFile))
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: certificate file not found: " + certFile;
+ throw e;
+ }
+ try
+ {
+ X509Certificate2 cert = new X509Certificate2(certFile, password);
+ certs_.Add(cert);
+ }
+ catch(CryptographicException ex)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException(ex);
+ e.reason = "IceSSL: error while attempting to load certificate from " + certFile;
+ throw e;
+ }
+ }
+
+ //
+ // If IceSSL.FindCert.* properties are defined, add the selected certificates
+ // to the collection.
+ //
+ // TODO: tracing?
+ const string findPrefix = prefix + "FindCert.";
+ Ice.PropertyDict certProps = properties.getPropertiesForPrefix(findPrefix);
+ if(certProps.Count > 0)
+ {
+ foreach(DictionaryEntry entry in certProps)
+ {
+ string name = (string)entry.Key;
+ string val = (string)entry.Value;
+ if(val.Length > 0)
+ {
+ string storeSpec = name.Substring(findPrefix.Length);
+ X509Certificate2Collection coll = findCertificates(name, storeSpec, val);
+ certs_.AddRange(coll);
+ }
+ }
+ if(certs_.Count == 0)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: no client certificates found";
+ throw e;
+ }
+ }
}
- context_ = new Context(this, certs_);
+ initialized_ = true;
}
internal void setCertificates(X509Certificate2Collection certs)
{
- if(context_ != null)
+ if(initialized_)
{
Ice.PluginInitializationException e = new Ice.PluginInitializationException();
e.reason = "IceSSL: plugin is already initialized";
@@ -109,20 +199,39 @@ namespace IceSSL
return securityTraceCategory_;
}
- internal Context context()
+ internal CertificateVerifier certificateVerifier()
{
- if(context_ == null)
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: plugin is not fully initialized";
- throw e;
- }
- return context_;
+ return verifier_;
}
- internal CertificateVerifier certificateVerifier()
+ internal bool initialized()
{
- return verifier_;
+ return initialized_;
+ }
+
+ internal X509Certificate2Collection certs()
+ {
+ return certs_;
+ }
+
+ internal int verifyPeer()
+ {
+ return verifyPeer_;
+ }
+
+ internal SslProtocols protocols()
+ {
+ return protocols_;
+ }
+
+ internal bool checkCRL()
+ {
+ return checkCRL_;
+ }
+
+ internal bool checkCertName()
+ {
+ return checkCertName_;
}
internal void traceStream(System.Net.Security.SslStream stream, string connInfo)
@@ -196,7 +305,7 @@ namespace IceSSL
}
}
- internal bool checkPath(ref string path)
+ private bool checkPath(ref string path)
{
if(File.Exists(path))
{
@@ -375,12 +484,219 @@ namespace IceSSL
return (string[])l.ToArray(typeof(string));
}
+ private SslProtocols parseProtocols(string property)
+ {
+ SslProtocols result = SslProtocols.Default;
+ string val = communicator().getProperties().getProperty(property);
+ if(val.Length > 0)
+ {
+ char[] delim = new char[] {',', ' '};
+ string[] arr = val.Split(delim, StringSplitOptions.RemoveEmptyEntries);
+ if(arr.Length > 0)
+ {
+ result = 0;
+ for(int i = 0; i < arr.Length; ++i)
+ {
+ string s = arr[i].ToLower();
+ if(s.Equals("ssl3") || s.Equals("sslv3"))
+ {
+ result |= SslProtocols.Ssl3;
+ }
+ else if(s.Equals("tls") || s.Equals("tls1") || s.Equals("tlsv1"))
+ {
+ result |= SslProtocols.Tls;
+ }
+ else
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: unrecognized protocol `" + s + "'";
+ throw e;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ private X509Certificate2Collection findCertificates(string prop, string storeSpec, string value)
+ {
+ StoreLocation storeLoc = 0;
+ StoreName storeName = 0;
+ string storeNameStr = null;
+ parseStore(prop, storeSpec, ref storeLoc, ref storeName, ref storeNameStr);
+
+ //
+ // Open the X509 certificate store.
+ //
+ X509Store store = null;
+ try
+ {
+ if(storeNameStr != null)
+ {
+ store = new X509Store(storeNameStr, storeLoc);
+ }
+ else
+ {
+ store = new X509Store(storeName, storeLoc);
+ }
+ store.Open(OpenFlags.ReadOnly);
+ }
+ catch(Exception ex)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException(ex);
+ e.reason = "IceSSL: failure while opening store specified by " + prop;
+ throw e;
+ }
+
+ //
+ // Start with all of the certificates in the collection and filter as necessary.
+ //
+ // - If the value is "*", return all certificates.
+ // - Otherwise, search using key:value pairs. The following keys are supported:
+ //
+ // Issuer
+ // IssuerDN
+ // Serial
+ // Subject
+ // SubjectDN
+ // SubjectKeyId
+ // Thumbprint
+ //
+ // A value must be enclosed in single or double quotes if it contains whitespace.
+ //
+ X509Certificate2Collection result = new X509Certificate2Collection();
+ result.AddRange(store.Certificates);
+ try
+ {
+ if(value != "*")
+ {
+ int start = 0;
+ int pos;
+ while((pos = value.IndexOf(':', start)) != -1)
+ {
+ //
+ // Parse the X509FindType.
+ //
+ string field = value.Substring(start, pos - start).Trim().ToLower();
+ X509FindType findType;
+ if(field.Equals("subject"))
+ {
+ findType = X509FindType.FindBySubjectName;
+ }
+ else if(field.Equals("subjectdn"))
+ {
+ findType = X509FindType.FindBySubjectDistinguishedName;
+ }
+ else if(field.Equals("issuer"))
+ {
+ findType = X509FindType.FindByIssuerName;
+ }
+ else if(field.Equals("issuerdn"))
+ {
+ findType = X509FindType.FindByIssuerDistinguishedName;
+ }
+ else if(field.Equals("thumbprint"))
+ {
+ findType = X509FindType.FindByThumbprint;
+ }
+ else if(field.Equals("subjectkeyid"))
+ {
+ findType = X509FindType.FindBySubjectKeyIdentifier;
+ }
+ else if(field.Equals("serial"))
+ {
+ findType = X509FindType.FindBySerialNumber;
+ }
+ else
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: unknown key in `" + value + "'";
+ throw e;
+ }
+
+ //
+ // Parse the argument.
+ //
+ start = pos + 1;
+ while(start < value.Length && (value[start] == ' ' || value[start] == '\t'))
+ {
+ ++start;
+ }
+ if(start == value.Length)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: missing argument in `" + value + "'";
+ throw e;
+ }
+
+ string arg;
+ if(value[start] == '"' || value[start] == '\'')
+ {
+ int end = start;
+ ++end;
+ while(end < value.Length)
+ {
+ if(value[end] == value[start] && value[end - 1] != '\\')
+ {
+ break;
+ }
+ ++end;
+ }
+ if(end == value.Length || value[end] != value[start])
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: unmatched quote in `" + value + "'";
+ throw e;
+ }
+ ++start;
+ arg = value.Substring(start, end - start);
+ start = end + 1;
+ }
+ else
+ {
+ char[] ws = new char[] { ' ', '\t' };
+ int end = value.IndexOfAny(ws, start);
+ if(end == -1)
+ {
+ arg = value.Substring(start);
+ start = value.Length;
+ }
+ else
+ {
+ arg = value.Substring(start, end - start);
+ start = end + 1;
+ }
+ }
+
+ //
+ // Execute the query.
+ //
+ // TODO: allow user to specify a value for validOnly?
+ //
+ bool validOnly = false;
+ result = result.Find(findType, arg, validOnly);
+ }
+ }
+ }
+ finally
+ {
+ store.Close();
+ }
+
+ return result;
+ }
+
+ private Ice.Logger logger_;
private IceInternal.ProtocolPluginFacade facade_;
private int securityTraceLevel_;
private string securityTraceCategory_;
- private Context context_;
- private CertificateVerifier verifier_;
+ private bool initialized_;
private string defaultDir_;
+ private SslProtocols protocols_;
+ private bool checkCertName_;
+ private int verifyPeer_;
+ private bool checkCRL_;
private X509Certificate2Collection certs_;
+ private CertificateVerifier verifier_;
}
}
diff --git a/java/src/IceSSL/AcceptorI.java b/java/src/IceSSL/AcceptorI.java
index ea0e0f102a6..b7fb65d05e7 100644
--- a/java/src/IceSSL/AcceptorI.java
+++ b/java/src/IceSSL/AcceptorI.java
@@ -60,6 +60,16 @@ class AcceptorI implements IceInternal.Acceptor
public IceInternal.Transceiver
accept(int timeout)
{
+ //
+ // The plugin may not be fully initialized.
+ //
+ if(!_instance.initialized())
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: plugin is not initialized";
+ throw ex;
+ }
+
javax.net.ssl.SSLSocket fd = null;
try
{
@@ -120,7 +130,7 @@ class AcceptorI implements IceInternal.Acceptor
}
}
- if(!_ctx.verifyPeer(fd, "", true))
+ if(!_instance.verifyPeer(fd, "", true))
{
try
{
@@ -226,7 +236,7 @@ class AcceptorI implements IceInternal.Acceptor
if(_instance.securityTraceLevel() > 0)
{
- _ctx.traceConnection(fd, true);
+ _instance.traceConnection(fd, true);
}
return new TransceiverI(_instance, fd);
@@ -272,7 +282,6 @@ class AcceptorI implements IceInternal.Acceptor
AcceptorI(Instance instance, String host, int port)
{
_instance = instance;
- _ctx = instance.context();
_logger = instance.communicator().getLogger();
_backlog = 0;
@@ -283,7 +292,7 @@ class AcceptorI implements IceInternal.Acceptor
try
{
- javax.net.ssl.SSLServerSocketFactory factory = _ctx.sslContext().getServerSocketFactory();
+ javax.net.ssl.SSLServerSocketFactory factory = _instance.context().getServerSocketFactory();
_addr = new java.net.InetSocketAddress(host, port);
if(_instance.networkTraceLevel() >= 2)
{
@@ -310,7 +319,8 @@ class AcceptorI implements IceInternal.Acceptor
_fd.setNeedClientAuth(true);
}
- String[] cipherSuites = _ctx.filterCiphers(_fd.getSupportedCipherSuites(), _fd.getEnabledCipherSuites());
+ String[] cipherSuites =
+ _instance.filterCiphers(_fd.getSupportedCipherSuites(), _fd.getEnabledCipherSuites());
try
{
_fd.setEnabledCipherSuites(cipherSuites);
@@ -333,7 +343,7 @@ class AcceptorI implements IceInternal.Acceptor
_logger.trace(_instance.securityTraceCategory(), s.toString());
}
- String[] protocols = _ctx.getProtocols();
+ String[] protocols = _instance.protocols();
if(protocols != null)
{
try
@@ -445,7 +455,6 @@ class AcceptorI implements IceInternal.Acceptor
}
private Instance _instance;
- private Context _ctx;
private Ice.Logger _logger;
private javax.net.ssl.SSLServerSocket _fd;
private int _backlog;
diff --git a/java/src/IceSSL/ConnectorI.java b/java/src/IceSSL/ConnectorI.java
index cf197e1eb95..d7e8796f601 100644
--- a/java/src/IceSSL/ConnectorI.java
+++ b/java/src/IceSSL/ConnectorI.java
@@ -17,7 +17,12 @@ final class ConnectorI implements IceInternal.Connector
//
// The plugin may not be fully initialized.
//
- Context ctx = _instance.context();
+ if(!_instance.initialized())
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: plugin is not initialized";
+ throw ex;
+ }
if(_instance.networkTraceLevel() >= 2)
{
@@ -33,7 +38,7 @@ final class ConnectorI implements IceInternal.Connector
//
if(timeout >= 0)
{
- ConnectThread ct = new ConnectThread(ctx.sslContext(), _addr);
+ ConnectThread ct = new ConnectThread(_instance.context(), _addr);
ct.start();
fd = ct.getFd(timeout == 0 ? 1 : timeout);
if(fd == null)
@@ -43,13 +48,13 @@ final class ConnectorI implements IceInternal.Connector
}
else
{
- javax.net.SocketFactory factory = ctx.sslContext().getSocketFactory();
+ javax.net.SocketFactory factory = _instance.context().getSocketFactory();
fd = (javax.net.ssl.SSLSocket)factory.createSocket(_addr.getAddress(), _addr.getPort());
}
fd.setUseClientMode(true);
- String[] cipherSuites = ctx.filterCiphers(fd.getSupportedCipherSuites(), fd.getEnabledCipherSuites());
+ String[] cipherSuites = _instance.filterCiphers(fd.getSupportedCipherSuites(), fd.getEnabledCipherSuites());
try
{
fd.setEnabledCipherSuites(cipherSuites);
@@ -72,7 +77,7 @@ final class ConnectorI implements IceInternal.Connector
_logger.trace(_instance.securityTraceCategory(), s.toString());
}
- String[] protocols = ctx.getProtocols();
+ String[] protocols = _instance.protocols();
if(protocols != null)
{
try
@@ -125,7 +130,7 @@ final class ConnectorI implements IceInternal.Connector
}
}
- if(!ctx.verifyPeer(fd, _host, false))
+ if(!_instance.verifyPeer(fd, _host, false))
{
Ice.SecurityException ex = new Ice.SecurityException();
ex.reason = "IceSSL: outgoing connection rejected by certificate verifier";
@@ -217,7 +222,7 @@ final class ConnectorI implements IceInternal.Connector
if(_instance.securityTraceLevel() > 0)
{
- ctx.traceConnection(fd, false);
+ _instance.traceConnection(fd, false);
}
return new TransceiverI(_instance, fd);
diff --git a/java/src/IceSSL/Context.java b/java/src/IceSSL/Context.java
deleted file mode 100644
index 1eaa2f881a2..00000000000
--- a/java/src/IceSSL/Context.java
+++ /dev/null
@@ -1,474 +0,0 @@
-// **********************************************************************
-//
-// Copyright (c) 2003-2006 ZeroC, Inc. All rights reserved.
-//
-// This copy of Ice is licensed to you under the terms described in the
-// ICE_LICENSE file included in this distribution.
-//
-// **********************************************************************
-
-package IceSSL;
-
-class Context
-{
- Context(Instance instance, javax.net.ssl.SSLContext context, java.security.SecureRandom rand)
- throws java.security.GeneralSecurityException
- {
- _instance = instance;
- _logger = instance.communicator().getLogger();
-
- final String prefix = "IceSSL.";
- Ice.Properties properties = instance.communicator().getProperties();
- String ciphers = properties.getProperty(prefix + "Ciphers");
-
- if(ciphers.length() > 0)
- {
- parseCiphers(ciphers);
- }
-
- //
- // If the user doesn't supply an SSLContext, we need to create one based
- // on property settings.
- //
- _ctx = context;
- if(_ctx == null)
- {
- //
- // Check for a default directory. We look in this directory for
- // files mentioned in the configuration.
- //
- _defaultDir = properties.getProperty(prefix + "DefaultDir");
-
- //
- // The keystore holds private keys and associated certificates.
- //
- Ice.StringHolder keystorePath = new Ice.StringHolder(properties.getProperty(prefix + "Keystore"));
-
- //
- // The password for the keys.
- //
- final String password = properties.getProperty(prefix + "Password");
-
- //
- // The password for the keystore.
- //
- final String keystorePassword = properties.getProperty(prefix + "KeystorePassword");
-
- //
- // The default keystore type value is "JKS", but it can also be "PKCS12".
- //
- final String defaultType = java.security.KeyStore.getDefaultType();
- final String keystoreType = properties.getPropertyWithDefault(prefix + "KeystoreType", defaultType);
-
- //
- // The alias of the key to use in authentication.
- //
- final String alias = properties.getProperty(prefix + "Alias");
-
- //
- // The truststore holds the certificates of trusted CAs.
- //
- Ice.StringHolder truststorePath = new Ice.StringHolder(properties.getProperty(prefix + "Truststore"));
-
- //
- // The password for the truststore.
- //
- final String truststorePassword = properties.getProperty(prefix + "TruststorePassword");
-
- //
- // The truststore type defaults to "JKS", but it can also be "PKCS12".
- //
- String truststoreType =
- properties.getPropertyWithDefault(prefix + "TruststoreType", java.security.KeyStore.getDefaultType());
-
- //
- // Parse the enabled protocols.
- //
- String protocols = properties.getProperty(prefix + "Protocols");
- if(protocols.length() > 0)
- {
- java.util.ArrayList l = new java.util.ArrayList();
- String[] arr = protocols.split("[ \t,]+");
- for(int i = 0; i < arr.length; ++i)
- {
- String s = arr[i].toLowerCase();
- if(s.equals("ssl3") || s.equals("sslv3"))
- {
- l.add("SSLv3");
- }
- else if(s.equals("tls") || s.equals("tls1") || s.equals("tlsv1"))
- {
- l.add("TLSv1");
- }
- else
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: unrecognized protocol `" + arr[i] + "'";
- throw e;
- }
- }
- _protocols = new String[l.size()];
- l.toArray(_protocols);
- }
-
- //
- // Collect the key managers.
- //
- javax.net.ssl.KeyManager[] keyManagers = null;
- if(keystorePath.value.length() > 0)
- {
- if(!checkPath(keystorePath, false))
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: keystore file not found:\n" + keystorePath.value;
- throw e;
- }
- java.security.KeyStore keys = java.security.KeyStore.getInstance(keystoreType);
- try
- {
- char[] passwordChars = null;
- if(keystorePassword.length() > 0)
- {
- passwordChars = keystorePassword.toCharArray();
- }
-
- java.io.BufferedInputStream bis =
- new java.io.BufferedInputStream(new java.io.FileInputStream(keystorePath.value));
- keys.load(bis, passwordChars);
- }
- catch(java.io.IOException ex)
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: unable to load keystore:\n" + keystorePath.value;
- e.initCause(ex);
- throw e;
- }
-
- String algorithm = javax.net.ssl.KeyManagerFactory.getDefaultAlgorithm();
- javax.net.ssl.KeyManagerFactory kmf = javax.net.ssl.KeyManagerFactory.getInstance(algorithm);
- kmf.init(keys, password.toCharArray());
- keyManagers = kmf.getKeyManagers();
-
- //
- // If the user selected a specific alias, we need to wrap the key managers
- // in order to return the desired alias.
- //
- if(alias.length() > 0)
- {
- if(!keys.isKeyEntry(alias))
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: keystore does not contain an entry with alias `" + alias + "'";
- throw e;
- }
-
- for(int i = 0; i < keyManagers.length; ++i)
- {
- keyManagers[i] = new KeyManagerI((javax.net.ssl.X509KeyManager)keyManagers[i], alias);
- }
- }
- }
-
- //
- // Collect the trust managers.
- //
- javax.net.ssl.TrustManager[] trustManagers = null;
- if(truststorePath.value.length() > 0)
- {
- if(!checkPath(truststorePath, false))
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: truststore file not found:\n" + truststorePath.value;
- throw e;
- }
- java.security.KeyStore ts = java.security.KeyStore.getInstance(truststoreType);
- try
- {
- char[] passwordChars = null;
- if(truststorePassword.length() > 0)
- {
- passwordChars = truststorePassword.toCharArray();
- }
-
- java.io.BufferedInputStream bis =
- new java.io.BufferedInputStream(new java.io.FileInputStream(truststorePath.value));
- ts.load(bis, passwordChars);
- }
- catch(java.io.IOException ex)
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: unable to load truststore:\n" + truststorePath.value;
- e.initCause(ex);
- throw e;
- }
-
- String algorithm = javax.net.ssl.TrustManagerFactory.getDefaultAlgorithm();
- javax.net.ssl.TrustManagerFactory tmf = javax.net.ssl.TrustManagerFactory.getInstance(algorithm);
- tmf.init(ts);
- trustManagers = tmf.getTrustManagers();
- }
-
- //
- // Initialize the SSL context.
- //
- _ctx = javax.net.ssl.SSLContext.getInstance("SSL");
- _ctx.init(keyManagers, trustManagers, rand);
- }
- }
-
- javax.net.ssl.SSLContext
- sslContext()
- {
- return _ctx;
- }
-
- String[]
- filterCiphers(String[] supportedCiphers, String[] defaultCiphers)
- {
- java.util.LinkedList result = new java.util.LinkedList();
- if(_allCiphers)
- {
- for(int i = 0; i < supportedCiphers.length; ++i)
- {
- result.add(supportedCiphers[i]);
- }
- }
- else if(!_noCiphers)
- {
- for(int i = 0; i < defaultCiphers.length; ++i)
- {
- result.add(defaultCiphers[i]);
- }
- }
-
- if(_ciphers != null)
- {
- for(int i = 0; i < _ciphers.length; ++i)
- {
- CipherExpression ce = (CipherExpression)_ciphers[i];
- if(ce.not)
- {
- java.util.Iterator e = result.iterator();
- while(e.hasNext())
- {
- String cipher = (String)e.next();
- if(ce.cipher != null)
- {
- if(ce.cipher.equals(cipher))
- {
- e.remove();
- }
- }
- else
- {
- assert(ce.re != null);
- java.util.regex.Matcher m = ce.re.matcher(cipher);
- if(m.find())
- {
- e.remove();
- }
- }
- }
- }
- else
- {
- if(ce.cipher != null)
- {
- result.add(0, ce.cipher);
- }
- else
- {
- assert(ce.re != null);
- for(int j = 0; j < supportedCiphers.length; ++j)
- {
- java.util.regex.Matcher m = ce.re.matcher(supportedCiphers[j]);
- if(m.find())
- {
- result.add(0, supportedCiphers[j]);
- }
- }
- }
- }
- }
- }
-
- String[] arr = new String[result.size()];
- result.toArray(arr);
- return arr;
- }
-
- String[]
- getProtocols()
- {
- return _protocols;
- }
-
- void
- traceConnection(javax.net.ssl.SSLSocket fd, boolean incoming)
- {
- javax.net.ssl.SSLSession session = fd.getSession();
- String msg = "SSL summary for " + (incoming ? "incoming" : "outgoing") + " connection\n" +
- "cipher = " + session.getCipherSuite() + "\n" +
- "protocol = " + session.getProtocol() + "\n" +
- IceInternal.Network.fdToString(fd);
- _logger.trace(_instance.securityTraceCategory(), msg);
- }
-
- boolean
- verifyPeer(javax.net.ssl.SSLSocket fd, String host, boolean incoming)
- {
- CertificateVerifier verifier = _instance.certificateVerifier();
- if(verifier != null)
- {
- VerifyInfo info = new VerifyInfo();
- info.incoming = incoming;
- try
- {
- info.certs = fd.getSession().getPeerCertificates();
- }
- catch(javax.net.ssl.SSLPeerUnverifiedException ex)
- {
- // No peer certificates.
- }
- info.socket = fd;
- info.address = host;
- if(!verifier.verify(info))
- {
- if(_instance.securityTraceLevel() > 0)
- {
- _logger.trace(_instance.securityTraceCategory(),
- (incoming ? "incoming" : "outgoing") +
- " connection rejected by certificate verifier\n" +
- IceInternal.Network.fdToString(fd));
- }
- return false;
- }
- }
-
- return true;
- }
-
- private void
- parseCiphers(String ciphers)
- {
- java.util.ArrayList cipherList = new java.util.ArrayList();
- String[] expr = ciphers.split("[ \t]+");
- for(int i = 0; i < expr.length; ++i)
- {
- if(expr[i].equals("ALL"))
- {
- if(i != 0)
- {
- Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
- ex.reason = "IceSSL: `ALL' must be first in cipher list `" + ciphers + "'";
- throw ex;
- }
- _allCiphers = true;
- }
- else if(expr[i].equals("NONE"))
- {
- if(i != 0)
- {
- Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
- ex.reason = "IceSSL: `NONE' must be first in cipher list `" + ciphers + "'";
- throw ex;
- }
- _noCiphers = true;
- }
- else
- {
- CipherExpression ce = new CipherExpression();
- String exp = expr[i];
- if(exp.charAt(0) == '!')
- {
- ce.not = true;
- if(exp.length() > 1)
- {
- exp = exp.substring(1);
- }
- else
- {
- Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
- ex.reason = "IceSSL: invalid cipher expression `" + exp + "'";
- throw ex;
- }
- }
-
- if(exp.charAt(0) == '(')
- {
- if(!exp.endsWith(")"))
- {
- Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
- ex.reason = "IceSSL: invalid cipher expression `" + exp + "'";
- throw ex;
- }
-
- try
- {
- ce.re = java.util.regex.Pattern.compile(exp.substring(1, exp.length() - 2));
- }
- catch(java.util.regex.PatternSyntaxException ex)
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: invalid cipher expression `" + exp + "'";
- e.initCause(ex);
- throw e;
- }
- }
- else
- {
- ce.cipher = exp;
- }
-
- cipherList.add(ce);
- }
- }
- _ciphers = new CipherExpression[cipherList.size()];
- cipherList.toArray(_ciphers);
- }
-
- private boolean
- checkPath(Ice.StringHolder path, boolean dir)
- {
- //
- // Check if file exists. If not, try prepending the default
- // directory and check again. If the file is found, the
- // string argument is modified and true is returned. Otherwise
- // false is returned.
- //
- java.io.File f = new java.io.File(path.value);
- if(f.exists())
- {
- return dir ? f.isDirectory() : f.isFile();
- }
-
- if(_defaultDir.length() > 0)
- {
- String s = _defaultDir + java.io.File.separator + path.value;
- f = new java.io.File(s);
- if(f.exists() && ((!dir && f.isFile()) || (dir && f.isDirectory())))
- {
- path.value = s;
- return true;
- }
- }
-
- return false;
- }
-
- private static class CipherExpression
- {
- boolean not;
- String cipher;
- java.util.regex.Pattern re;
- }
-
- private Instance _instance;
- private Ice.Logger _logger;
- private String _defaultDir;
- private CipherExpression[] _ciphers;
- private boolean _allCiphers;
- private boolean _noCiphers;
- private String[] _protocols;
- private javax.net.ssl.SSLContext _ctx;
-}
diff --git a/java/src/IceSSL/Instance.java b/java/src/IceSSL/Instance.java
index 59ae5ed7afa..ea6ab3308e8 100644
--- a/java/src/IceSSL/Instance.java
+++ b/java/src/IceSSL/Instance.java
@@ -13,9 +13,11 @@ class Instance
{
Instance(Ice.Communicator communicator)
{
+ _logger = communicator.getLogger();
_facade = Ice.Util.getProtocolPluginFacade(communicator);
_securityTraceLevel = communicator.getProperties().getPropertyAsIntWithDefault("IceSSL.Trace.Security", 0);
_securityTraceCategory = "Security";
+ _initialized = false;
//
// Register the endpoint factory. We have to do this now, rather than
@@ -28,69 +30,252 @@ class Instance
void
initialize()
{
- if(_context != null)
+ if(_initialized)
{
return;
}
+ final String prefix = "IceSSL.";
+ Ice.Properties properties = communicator().getProperties();
+
//
- // If we have to initialize an SSLContext, we'll need a SecureRandom object.
+ // Parse the cipher list.
//
- java.security.SecureRandom rand = null;
- if(_ctx == null)
+ String ciphers = properties.getProperty(prefix + "Ciphers");
+ if(ciphers.length() > 0)
+ {
+ parseCiphers(ciphers);
+ }
+
+ //
+ // Select protocols.
+ //
+ String protocols = properties.getProperty(prefix + "Protocols");
+ if(protocols.length() > 0)
+ {
+ java.util.ArrayList l = new java.util.ArrayList();
+ String[] arr = protocols.split("[ \t,]+");
+ for(int i = 0; i < arr.length; ++i)
+ {
+ String s = arr[i].toLowerCase();
+ if(s.equals("ssl3") || s.equals("sslv3"))
+ {
+ l.add("SSLv3");
+ }
+ else if(s.equals("tls") || s.equals("tls1") || s.equals("tlsv1"))
+ {
+ l.add("TLSv1");
+ }
+ else
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: unrecognized protocol `" + arr[i] + "'";
+ throw e;
+ }
+ }
+ _protocols = new String[l.size()];
+ l.toArray(_protocols);
+ }
+
+ //
+ // If the user doesn't supply an SSLContext, we need to create one based
+ // on property settings.
+ //
+ if(_context == null)
{
try
{
- rand = java.security.SecureRandom.getInstance("SHA1PRNG");
+ //
+ // We need a SecureRandom object.
+ //
+ java.security.SecureRandom rand = java.security.SecureRandom.getInstance("SHA1PRNG");
//
// We call nextInt() in order to force the object to perform any time-consuming
// initialization tasks now.
//
rand.nextInt();
+
+ //
+ // Check for a default directory. We look in this directory for
+ // files mentioned in the configuration.
+ //
+ _defaultDir = properties.getProperty(prefix + "DefaultDir");
+
+ //
+ // The keystore holds private keys and associated certificates.
+ //
+ Ice.StringHolder keystorePath = new Ice.StringHolder(properties.getProperty(prefix + "Keystore"));
+
+ //
+ // The password for the keys.
+ //
+ final String password = properties.getProperty(prefix + "Password");
+
+ //
+ // The password for the keystore.
+ //
+ final String keystorePassword = properties.getProperty(prefix + "KeystorePassword");
+
+ //
+ // The default keystore type value is "JKS", but it can also be "PKCS12".
+ //
+ final String defaultType = java.security.KeyStore.getDefaultType();
+ final String keystoreType = properties.getPropertyWithDefault(prefix + "KeystoreType", defaultType);
+
+ //
+ // The alias of the key to use in authentication.
+ //
+ final String alias = properties.getProperty(prefix + "Alias");
+
+ //
+ // The truststore holds the certificates of trusted CAs.
+ //
+ Ice.StringHolder truststorePath = new Ice.StringHolder(properties.getProperty(prefix + "Truststore"));
+
+ //
+ // The password for the truststore.
+ //
+ final String truststorePassword = properties.getProperty(prefix + "TruststorePassword");
+
+ //
+ // The truststore type defaults to "JKS", but it can also be "PKCS12".
+ //
+ String truststoreType = properties.getPropertyWithDefault(prefix + "TruststoreType",
+ java.security.KeyStore.getDefaultType());
+
+ //
+ // Collect the key managers.
+ //
+ javax.net.ssl.KeyManager[] keyManagers = null;
+ if(keystorePath.value.length() > 0)
+ {
+ if(!checkPath(keystorePath, false))
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: keystore file not found:\n" + keystorePath.value;
+ throw e;
+ }
+ java.security.KeyStore keys = java.security.KeyStore.getInstance(keystoreType);
+ try
+ {
+ char[] passwordChars = null;
+ if(keystorePassword.length() > 0)
+ {
+ passwordChars = keystorePassword.toCharArray();
+ }
+
+ java.io.BufferedInputStream bis =
+ new java.io.BufferedInputStream(new java.io.FileInputStream(keystorePath.value));
+ keys.load(bis, passwordChars);
+ }
+ catch(java.io.IOException ex)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: unable to load keystore:\n" + keystorePath.value;
+ e.initCause(ex);
+ throw e;
+ }
+
+ String algorithm = javax.net.ssl.KeyManagerFactory.getDefaultAlgorithm();
+ javax.net.ssl.KeyManagerFactory kmf = javax.net.ssl.KeyManagerFactory.getInstance(algorithm);
+ kmf.init(keys, password.toCharArray());
+ keyManagers = kmf.getKeyManagers();
+
+ //
+ // If the user selected a specific alias, we need to wrap the key managers
+ // in order to return the desired alias.
+ //
+ if(alias.length() > 0)
+ {
+ if(!keys.isKeyEntry(alias))
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: keystore does not contain an entry with alias `" + alias + "'";
+ throw e;
+ }
+
+ for(int i = 0; i < keyManagers.length; ++i)
+ {
+ keyManagers[i] = new KeyManagerI((javax.net.ssl.X509KeyManager)keyManagers[i], alias);
+ }
+ }
+ }
+
+ //
+ // Collect the trust managers.
+ //
+ javax.net.ssl.TrustManager[] trustManagers = null;
+ if(truststorePath.value.length() > 0)
+ {
+ if(!checkPath(truststorePath, false))
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: truststore file not found:\n" + truststorePath.value;
+ throw e;
+ }
+ java.security.KeyStore ts = java.security.KeyStore.getInstance(truststoreType);
+ try
+ {
+ char[] passwordChars = null;
+ if(truststorePassword.length() > 0)
+ {
+ passwordChars = truststorePassword.toCharArray();
+ }
+
+ java.io.BufferedInputStream bis =
+ new java.io.BufferedInputStream(new java.io.FileInputStream(truststorePath.value));
+ ts.load(bis, passwordChars);
+ }
+ catch(java.io.IOException ex)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: unable to load truststore:\n" + truststorePath.value;
+ e.initCause(ex);
+ throw e;
+ }
+
+ String algorithm = javax.net.ssl.TrustManagerFactory.getDefaultAlgorithm();
+ javax.net.ssl.TrustManagerFactory tmf = javax.net.ssl.TrustManagerFactory.getInstance(algorithm);
+ tmf.init(ts);
+ trustManagers = tmf.getTrustManagers();
+ }
+
+ //
+ // Initialize the SSL context.
+ //
+ _context = javax.net.ssl.SSLContext.getInstance("SSL");
+ _context.init(keyManagers, trustManagers, rand);
}
catch(java.security.GeneralSecurityException ex)
{
Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: unable to initialize secure PRNG";
+ e.reason = "IceSSL: unable to initialize context";
e.initCause(ex);
throw e;
}
}
- //
- // Create the context.
- //
- try
- {
- _context = new Context(this, _ctx, rand);
- }
- catch(java.security.GeneralSecurityException ex)
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: unable to initialize context";
- e.initCause(ex);
- throw e;
- }
+ _initialized = true;
}
void
- setContext(javax.net.ssl.SSLContext context)
+ context(javax.net.ssl.SSLContext context)
{
- if(_context != null)
+ if(_initialized)
{
Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
ex.reason = "IceSSL: plugin is already initialized";
throw ex;
}
- _ctx = context;
+ _context = context;
}
javax.net.ssl.SSLContext
- getContext()
+ context()
{
- return _ctx;
+ return _context;
}
void
@@ -135,28 +320,263 @@ class Instance
return _securityTraceCategory;
}
- Context
- context()
+ boolean
+ initialized()
{
- if(_context == null)
+ return _initialized;
+ }
+
+ String[]
+ filterCiphers(String[] supportedCiphers, String[] defaultCiphers)
+ {
+ java.util.LinkedList result = new java.util.LinkedList();
+ if(_allCiphers)
{
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: plugin is not fully initialized";
- throw e;
+ for(int i = 0; i < supportedCiphers.length; ++i)
+ {
+ result.add(supportedCiphers[i]);
+ }
}
- return _context;
+ else if(!_noCiphers)
+ {
+ for(int i = 0; i < defaultCiphers.length; ++i)
+ {
+ result.add(defaultCiphers[i]);
+ }
+ }
+
+ if(_ciphers != null)
+ {
+ for(int i = 0; i < _ciphers.length; ++i)
+ {
+ CipherExpression ce = (CipherExpression)_ciphers[i];
+ if(ce.not)
+ {
+ java.util.Iterator e = result.iterator();
+ while(e.hasNext())
+ {
+ String cipher = (String)e.next();
+ if(ce.cipher != null)
+ {
+ if(ce.cipher.equals(cipher))
+ {
+ e.remove();
+ }
+ }
+ else
+ {
+ assert(ce.re != null);
+ java.util.regex.Matcher m = ce.re.matcher(cipher);
+ if(m.find())
+ {
+ e.remove();
+ }
+ }
+ }
+ }
+ else
+ {
+ if(ce.cipher != null)
+ {
+ result.add(0, ce.cipher);
+ }
+ else
+ {
+ assert(ce.re != null);
+ for(int j = 0; j < supportedCiphers.length; ++j)
+ {
+ java.util.regex.Matcher m = ce.re.matcher(supportedCiphers[j]);
+ if(m.find())
+ {
+ result.add(0, supportedCiphers[j]);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ String[] arr = new String[result.size()];
+ result.toArray(arr);
+ return arr;
+ }
+
+ String[]
+ protocols()
+ {
+ return _protocols;
+ }
+
+ void
+ traceConnection(javax.net.ssl.SSLSocket fd, boolean incoming)
+ {
+ javax.net.ssl.SSLSession session = fd.getSession();
+ String msg = "SSL summary for " + (incoming ? "incoming" : "outgoing") + " connection\n" +
+ "cipher = " + session.getCipherSuite() + "\n" +
+ "protocol = " + session.getProtocol() + "\n" +
+ IceInternal.Network.fdToString(fd);
+ _logger.trace(_securityTraceCategory, msg);
+ }
+
+ boolean
+ verifyPeer(javax.net.ssl.SSLSocket fd, String host, boolean incoming)
+ {
+ CertificateVerifier verifier = _verifier;
+ if(verifier != null)
+ {
+ VerifyInfo info = new VerifyInfo();
+ info.incoming = incoming;
+ try
+ {
+ info.certs = fd.getSession().getPeerCertificates();
+ }
+ catch(javax.net.ssl.SSLPeerUnverifiedException ex)
+ {
+ // No peer certificates.
+ }
+ info.socket = fd;
+ info.address = host;
+ if(!verifier.verify(info))
+ {
+ if(_securityTraceLevel > 0)
+ {
+ _logger.trace(_securityTraceCategory,
+ (incoming ? "incoming" : "outgoing") +
+ " connection rejected by certificate verifier\n" +
+ IceInternal.Network.fdToString(fd));
+ }
+ return false;
+ }
+ }
+
+ return true;
}
- CertificateVerifier
- certificateVerifier()
- {
- return _verifier;
+ private void
+ parseCiphers(String ciphers)
+ {
+ java.util.ArrayList cipherList = new java.util.ArrayList();
+ String[] expr = ciphers.split("[ \t]+");
+ for(int i = 0; i < expr.length; ++i)
+ {
+ if(expr[i].equals("ALL"))
+ {
+ if(i != 0)
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: `ALL' must be first in cipher list `" + ciphers + "'";
+ throw ex;
+ }
+ _allCiphers = true;
+ }
+ else if(expr[i].equals("NONE"))
+ {
+ if(i != 0)
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: `NONE' must be first in cipher list `" + ciphers + "'";
+ throw ex;
+ }
+ _noCiphers = true;
+ }
+ else
+ {
+ CipherExpression ce = new CipherExpression();
+ String exp = expr[i];
+ if(exp.charAt(0) == '!')
+ {
+ ce.not = true;
+ if(exp.length() > 1)
+ {
+ exp = exp.substring(1);
+ }
+ else
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: invalid cipher expression `" + exp + "'";
+ throw ex;
+ }
+ }
+
+ if(exp.charAt(0) == '(')
+ {
+ if(!exp.endsWith(")"))
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: invalid cipher expression `" + exp + "'";
+ throw ex;
+ }
+
+ try
+ {
+ ce.re = java.util.regex.Pattern.compile(exp.substring(1, exp.length() - 2));
+ }
+ catch(java.util.regex.PatternSyntaxException ex)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: invalid cipher expression `" + exp + "'";
+ e.initCause(ex);
+ throw e;
+ }
+ }
+ else
+ {
+ ce.cipher = exp;
+ }
+
+ cipherList.add(ce);
+ }
+ }
+ _ciphers = new CipherExpression[cipherList.size()];
+ cipherList.toArray(_ciphers);
+ }
+
+ private boolean
+ checkPath(Ice.StringHolder path, boolean dir)
+ {
+ //
+ // Check if file exists. If not, try prepending the default
+ // directory and check again. If the file is found, the
+ // string argument is modified and true is returned. Otherwise
+ // false is returned.
+ //
+ java.io.File f = new java.io.File(path.value);
+ if(f.exists())
+ {
+ return dir ? f.isDirectory() : f.isFile();
+ }
+
+ if(_defaultDir.length() > 0)
+ {
+ String s = _defaultDir + java.io.File.separator + path.value;
+ f = new java.io.File(s);
+ if(f.exists() && ((!dir && f.isFile()) || (dir && f.isDirectory())))
+ {
+ path.value = s;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private static class CipherExpression
+ {
+ boolean not;
+ String cipher;
+ java.util.regex.Pattern re;
}
+ private Ice.Logger _logger;
private IceInternal.ProtocolPluginFacade _facade;
private int _securityTraceLevel;
private String _securityTraceCategory;
- private Context _context;
+ private boolean _initialized;
+ private javax.net.ssl.SSLContext _context;
+ private String _defaultDir;
+ private CipherExpression[] _ciphers;
+ private boolean _allCiphers;
+ private boolean _noCiphers;
+ private String[] _protocols;
private CertificateVerifier _verifier;
- private javax.net.ssl.SSLContext _ctx;
}
diff --git a/java/src/IceSSL/PluginI.java b/java/src/IceSSL/PluginI.java
index 838322ec034..61cdb6e07b3 100644
--- a/java/src/IceSSL/PluginI.java
+++ b/java/src/IceSSL/PluginI.java
@@ -31,13 +31,13 @@ class PluginI extends Ice.LocalObjectImpl implements Plugin
public void
setContext(javax.net.ssl.SSLContext context)
{
- _instance.setContext(context);
+ _instance.context(context);
}
public javax.net.ssl.SSLContext
getContext()
{
- return _instance.getContext();
+ return _instance.context();
}
public void