summaryrefslogtreecommitdiff
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-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
5 files changed, 488 insertions, 528 deletions
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