JBossWeb SVN: r657 - in trunk: webapps/docs and 1 other directory.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-06-04 15:57:54 -0400 (Wed, 04 Jun 2008)
New Revision: 657
Added:
trunk/java/org/jboss/web/cluster/JSSEKeyManager.java
trunk/java/org/jboss/web/cluster/JSSESocketFactory.java
Modified:
trunk/java/org/jboss/web/cluster/ClusterListener.java
trunk/webapps/docs/changelog.xml
Log:
- Add SSL utility code (not used yet).
Modified: trunk/java/org/jboss/web/cluster/ClusterListener.java
===================================================================
--- trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-06-04 19:55:55 UTC (rev 656)
+++ trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-06-04 19:57:54 UTC (rev 657)
@@ -37,6 +37,11 @@
import java.util.StringTokenizer;
import javax.management.ObjectName;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManagerFactory;
import org.apache.catalina.Container;
import org.apache.catalina.ContainerEvent;
@@ -106,6 +111,12 @@
protected Proxy[] proxies = null;
+ /**
+ * Socket factory.
+ */
+
+
+
// ------------------------------------------------------------- Properties
@@ -236,7 +247,135 @@
public int getMaxAttempts() { return maxAttempts; }
public void setMaxAttempts(int maxAttempts) { this.maxAttempts = maxAttempts; }
+
+ /**
+ * SSL client cert usage to connect to the proxy.
+ */
+ protected boolean ssl = false;
+ public boolean isSsl() { return ssl; }
+ public void setSsl(boolean ssl) { this.ssl = ssl; }
+
+ /**
+ * SSL ciphers.
+ */
+ protected String sslCiphers = null;
+ public String getSslCiphers() { return sslCiphers; }
+ public void setSslCiphers(String sslCiphers) { this.sslCiphers = sslCiphers; }
+
+
+ /**
+ * SSL protocol.
+ */
+ protected String sslProtocol = "TLS";
+ public String getSslProtocol() { return sslProtocol; }
+ public void setSslProtocol(String sslProtocol) { this.sslProtocol = sslProtocol; }
+
+
+ /**
+ * Certificate encoding algorithm.
+ */
+ protected String sslCertificateEncodingAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
+ public String getSslCertificateEncodingAlgorithm() { return sslCertificateEncodingAlgorithm; }
+ public void setSslCertificateEncodingAlgorithm(String sslCertificateEncodingAlgorithm) { this.sslCertificateEncodingAlgorithm = sslCertificateEncodingAlgorithm; }
+
+
+ /**
+ * SSL keystore.
+ */
+ protected String sslKeyStore = System.getProperty("user.home") + "/.keystore";
+ public String getSslKeyStore() { return sslKeyStore; }
+ public void setSslKeyStore(String sslKeyStore) { this.sslKeyStore = sslKeyStore; }
+
+
+ /**
+ * SSL keystore password.
+ */
+ protected String sslKeyStorePass = "changeit";
+ public String getSslKeyStorePass() { return sslKeyStorePass; }
+ public void setSslKeyStorePass(String sslKeyStorePass) { this.sslKeyStorePass = sslKeyStorePass; }
+
+
+ /**
+ * Keystore type.
+ */
+ protected String sslKeyStoreType = "JKS";
+ public String getSslKeyStoreType() { return sslKeyStoreType; }
+ public void setSslKeyStoreType(String sslKeyStoreType) { this.sslKeyStoreType = sslKeyStoreType; }
+
+
+ /**
+ * Keystore provider.
+ */
+ protected String sslKeyStoreProvider = null;
+ public String getSslKeyStoreProvider() { return sslKeyStoreProvider; }
+ public void setSslKeyStoreProvider(String sslKeyStoreProvider) { this.sslKeyStoreProvider = sslKeyStoreProvider; }
+
+
+ /**
+ * Truststore algorithm.
+ */
+ protected String sslTrustAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
+ public String getSslTrustAlgorithm() { return sslTrustAlgorithm; }
+ public void setSslTrustAlgorithm(String sslTrustAlgorithm) { this.sslTrustAlgorithm = sslTrustAlgorithm; }
+
+
+ /**
+ * Key alias.
+ */
+ protected String sslKeyAlias = null;
+ public String getSslKeyAlias() { return sslKeyAlias; }
+ public void setSslKeyAlias(String sslKeyAlias) { this.sslKeyAlias = sslKeyAlias; }
+
+
+ /**
+ * Certificate revocation list.
+ */
+ protected String sslCrlFile = null;
+ public String getSslCrlFile() { return sslCrlFile; }
+ public void setSslCrlFile(String sslCrlFile) { this.sslCrlFile = sslCrlFile; }
+
+
+ /**
+ * Trust max certificate length.
+ */
+ protected int sslTrustMaxCertLength = 5;
+ public int getSslTrustMaxCertLength() { return sslTrustMaxCertLength; }
+ public void setSslTrustMaxCertLength(int sslTrustMaxCertLength) { this.sslTrustMaxCertLength = sslTrustMaxCertLength; }
+
+
+ /**
+ * Trust store file.
+ */
+ protected String sslTrustStore = System.getProperty("javax.net.ssl.trustStore");
+ public String getSslTrustStore() { return sslTrustStore; }
+ public void setSslTrustStore(String sslTrustStore) { this.sslTrustStore = sslTrustStore; }
+
+
+ /**
+ * Trust store password.
+ */
+ protected String sslTrustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword");
+ public String getSslTrustStorePassword() { return sslTrustStorePassword; }
+ public void setSslTrustStorePassword(String sslTrustStorePassword) { this.sslTrustStorePassword = sslTrustStorePassword; }
+
+
+ /**
+ * Trust store type.
+ */
+ protected String sslTrustStoreType = System.getProperty("javax.net.ssl.trustStoreType");
+ public String getSslTrustStoreType() { return sslTrustStoreType; }
+ public void setSslTrustStoreType(String sslTrustStoreType) { this.sslTrustStoreType = sslTrustStoreType; }
+
+
+ /**
+ * Trust store provider.
+ */
+ protected String sslTrustStoreProvider = System.getProperty("javax.net.ssl.trustStoreProvider");
+ public String getSslTrustStoreProvider() { return sslTrustStoreProvider; }
+ public void setSslTrustStoreProvider(String sslTrustStoreProvider) { this.sslTrustStoreProvider = sslTrustStoreProvider; }
+
+
// ---------------------------------------------- LifecycleListener Methods
@@ -328,6 +467,7 @@
proxies = proxyList.toArray(new Proxy[0]);
}
+ sslInit();
startServer((Server) source, -1);
} else {
return;
@@ -1074,15 +1214,32 @@
/**
+ * SSL init.
+ */
+ protected void sslInit() {
+ }
+
+
+ /**
* Return a connection to the proxy.
*/
protected Socket getConnection(int i)
throws IOException {
// FIXME: Add SSL (using a client cert)
- if (proxies[i].address == null) {
- return new Socket(InetAddress.getLocalHost(), proxies[i].port);
+ if (!ssl) {
+ if (proxies[i].address == null) {
+ return new Socket(InetAddress.getLocalHost(), proxies[i].port);
+ } else {
+ return new Socket(proxies[i].address, proxies[i].port);
+ }
} else {
- return new Socket(proxies[i].address, proxies[i].port);
+ if (proxies[i].address == null) {
+ return SSLSocketFactory.getDefault()
+ .createSocket(InetAddress.getLocalHost(), proxies[i].port);
+ } else {
+ return SSLSocketFactory.getDefault()
+ .createSocket(proxies[i].address, proxies[i].port);
+ }
}
}
Added: trunk/java/org/jboss/web/cluster/JSSEKeyManager.java
===================================================================
--- trunk/java/org/jboss/web/cluster/JSSEKeyManager.java (rev 0)
+++ trunk/java/org/jboss/web/cluster/JSSEKeyManager.java 2008-06-04 19:57:54 UTC (rev 657)
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jboss.web.cluster;
+
+import java.net.Socket;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.X509KeyManager;
+
+/**
+ * X509KeyManager which allows selection of a specific keypair and certificate
+ * chain (identified by their keystore alias name) to be used by the server to
+ * authenticate itself to SSL clients.
+ *
+ * @author Jan Luehe
+ */
+public final class JSSEKeyManager implements X509KeyManager {
+
+ private X509KeyManager delegate;
+ private String serverKeyAlias;
+
+ /**
+ * Constructor.
+ *
+ * @param mgr The X509KeyManager used as a delegate
+ * @param serverKeyAlias The alias name of the server's keypair and
+ * supporting certificate chain
+ */
+ public JSSEKeyManager(X509KeyManager mgr, String serverKeyAlias) {
+ this.delegate = mgr;
+ this.serverKeyAlias = serverKeyAlias;
+ }
+
+ /**
+ * Choose an alias to authenticate the client side of a secure socket,
+ * given the public key type and the list of certificate issuer authorities
+ * recognized by the peer (if any).
+ *
+ * @param keyType The key algorithm type name(s), ordered with the
+ * most-preferred key type first
+ * @param issuers The list of acceptable CA issuer subject names, or null
+ * if it does not matter which issuers are used
+ * @param socket The socket to be used for this connection. This parameter
+ * can be null, in which case this method will return the most generic
+ * alias to use
+ *
+ * @return The alias name for the desired key, or null if there are no
+ * matches
+ */
+ public String chooseClientAlias(String[] keyType, Principal[] issuers,
+ Socket socket) {
+ return delegate.chooseClientAlias(keyType, issuers, socket);
+ }
+
+ /**
+ * Returns this key manager's server key alias that was provided in the
+ * constructor.
+ *
+ * @param keyType The key algorithm type name (ignored)
+ * @param issuers The list of acceptable CA issuer subject names, or null
+ * if it does not matter which issuers are used (ignored)
+ * @param socket The socket to be used for this connection. This parameter
+ * can be null, in which case this method will return the most generic
+ * alias to use (ignored)
+ *
+ * @return Alias name for the desired key
+ */
+ public String chooseServerAlias(String keyType, Principal[] issuers,
+ Socket socket) {
+ return serverKeyAlias;
+ }
+
+ /**
+ * Returns the certificate chain associated with the given alias.
+ *
+ * @param alias The alias name
+ *
+ * @return Certificate chain (ordered with the user's certificate first
+ * and the root certificate authority last), or null if the alias can't be
+ * found
+ */
+ public X509Certificate[] getCertificateChain(String alias) {
+ return delegate.getCertificateChain(alias);
+ }
+
+ /**
+ * Get the matching aliases for authenticating the client side of a secure
+ * socket, given the public key type and the list of certificate issuer
+ * authorities recognized by the peer (if any).
+ *
+ * @param keyType The key algorithm type name
+ * @param issuers The list of acceptable CA issuer subject names, or null
+ * if it does not matter which issuers are used
+ *
+ * @return Array of the matching alias names, or null if there were no
+ * matches
+ */
+ public String[] getClientAliases(String keyType, Principal[] issuers) {
+ return delegate.getClientAliases(keyType, issuers);
+ }
+
+ /**
+ * Get the matching aliases for authenticating the server side of a secure
+ * socket, given the public key type and the list of certificate issuer
+ * authorities recognized by the peer (if any).
+ *
+ * @param keyType The key algorithm type name
+ * @param issuers The list of acceptable CA issuer subject names, or null
+ * if it does not matter which issuers are used
+ *
+ * @return Array of the matching alias names, or null if there were no
+ * matches
+ */
+ public String[] getServerAliases(String keyType, Principal[] issuers) {
+ return delegate.getServerAliases(keyType, issuers);
+ }
+
+ /**
+ * Returns the key associated with the given alias.
+ *
+ * @param alias The alias name
+ *
+ * @return The requested key, or null if the alias can't be found
+ */
+ public PrivateKey getPrivateKey(String alias) {
+ return delegate.getPrivateKey(alias);
+ }
+}
Added: trunk/java/org/jboss/web/cluster/JSSESocketFactory.java
===================================================================
--- trunk/java/org/jboss/web/cluster/JSSESocketFactory.java (rev 0)
+++ trunk/java/org/jboss/web/cluster/JSSESocketFactory.java 2008-06-04 19:57:54 UTC (rev 657)
@@ -0,0 +1,550 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jboss.web.cluster;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+import java.security.cert.CRL;
+import java.security.cert.CRLException;
+import java.security.cert.CertPathParameters;
+import java.security.cert.CertStore;
+import java.security.cert.CertStoreParameters;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CollectionCertStoreParameters;
+import java.security.cert.PKIXBuilderParameters;
+import java.security.cert.X509CertSelector;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Vector;
+
+import javax.net.ssl.CertPathTrustManagerParameters;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.ManagerFactoryParameters;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509KeyManager;
+
+import org.apache.tomcat.util.res.StringManager;
+
+/*
+ 1. Make the JSSE's jars available, either as an installed
+ extension (copy them into jre/lib/ext) or by adding
+ them to the Tomcat classpath.
+ 2. keytool -genkey -alias tomcat -keyalg RSA
+ Use "changeit" as password ( this is the default we use )
+ */
+
+/**
+ * SSL server socket factory. It _requires_ a valid RSA key and
+ * JSSE.
+ *
+ * @author Harish Prabandham
+ * @author Costin Manolache
+ * @author Stefan Freyr Stefansson
+ * @author EKR -- renamed to JSSESocketFactory
+ * @author Jan Luehe
+ * @author Bill Barker
+ */
+public class JSSESocketFactory {
+
+ private static StringManager sm =
+ StringManager.getManager("org.apache.tomcat.util.net.jsse.res");
+
+ static org.jboss.logging.Logger log =
+ org.jboss.logging.Logger.getLogger(JSSESocketFactory.class);
+
+ protected boolean initialized;
+ //protected String clientAuth = "false";
+ protected SSLSocketFactory sslProxy = null;
+ protected String[] enabledCiphers;
+ protected ClusterListener listener = null;
+
+ /**
+ * Flag to state that we require client authentication.
+ */
+ //protected boolean requireClientAuth = false;
+
+ /**
+ * Flag to state that we would like client authentication.
+ */
+ //protected boolean wantClientAuth = false;
+
+
+ public JSSESocketFactory (ClusterListener listener) {
+ this.listener = listener;
+ }
+
+ public Socket createSocket (InetAddress ifAddress, int port)
+ throws IOException
+ {
+ if (!initialized) init();
+ Socket socket = sslProxy.createSocket(ifAddress, port);
+ initSocket(socket);
+ return socket;
+ }
+
+ public void handshake(Socket sock) throws IOException {
+ ((SSLSocket)sock).startHandshake();
+ }
+
+ /*
+ * Determines the SSL cipher suites to be enabled.
+ *
+ * @param requestedCiphers Comma-separated list of requested ciphers
+ * @param supportedCiphers Array of supported ciphers
+ *
+ * @return Array of SSL cipher suites to be enabled, or null if none of the
+ * requested ciphers are supported
+ */
+ protected String[] getEnabledCiphers(String requestedCiphers,
+ String[] supportedCiphers) {
+
+ String[] enabledCiphers = null;
+
+ if (requestedCiphers != null) {
+ Vector vec = null;
+ String cipher = requestedCiphers;
+ int index = requestedCiphers.indexOf(',');
+ if (index != -1) {
+ int fromIndex = 0;
+ while (index != -1) {
+ cipher = requestedCiphers.substring(fromIndex, index).trim();
+ if (cipher.length() > 0) {
+ /*
+ * Check to see if the requested cipher is among the
+ * supported ciphers, i.e., may be enabled
+ */
+ for (int i=0; supportedCiphers != null
+ && i<supportedCiphers.length; i++) {
+ if (supportedCiphers[i].equals(cipher)) {
+ if (vec == null) {
+ vec = new Vector();
+ }
+ vec.addElement(cipher);
+ break;
+ }
+ }
+ }
+ fromIndex = index+1;
+ index = requestedCiphers.indexOf(',', fromIndex);
+ } // while
+ cipher = requestedCiphers.substring(fromIndex);
+ }
+
+ if (cipher != null) {
+ cipher = cipher.trim();
+ if (cipher.length() > 0) {
+ /*
+ * Check to see if the requested cipher is among the
+ * supported ciphers, i.e., may be enabled
+ */
+ for (int i=0; supportedCiphers != null
+ && i<supportedCiphers.length; i++) {
+ if (supportedCiphers[i].equals(cipher)) {
+ if (vec == null) {
+ vec = new Vector();
+ }
+ vec.addElement(cipher);
+ break;
+ }
+ }
+ }
+ }
+
+ if (vec != null) {
+ enabledCiphers = new String[vec.size()];
+ vec.copyInto(enabledCiphers);
+ }
+ } else {
+ enabledCiphers = sslProxy.getDefaultCipherSuites();
+ }
+
+ return enabledCiphers;
+ }
+
+ /*
+ * Gets the SSL server's keystore.
+ */
+ protected KeyStore getKeystore(String type, String provider, String pass)
+ throws IOException {
+ return getStore(type, provider, listener.getSslKeyStore(), pass);
+ }
+
+ /*
+ * Gets the SSL server's truststore.
+ */
+ protected KeyStore getTrustStore(String keystoreType,
+ String keystoreProvider) throws IOException {
+ KeyStore trustStore = null;
+
+ String truststorePassword = listener.getSslTrustStorePassword();
+ if( truststorePassword == null ) {
+ truststorePassword = listener.getSslKeyStorePass();
+ }
+ String truststoreType = listener.getSslTrustStoreType();
+ if(truststoreType == null) {
+ truststoreType = keystoreType;
+ }
+ String truststoreProvider = listener.getSslTrustStoreProvider();
+ if (truststoreProvider == null) {
+ truststoreProvider = keystoreProvider;
+ }
+
+ if (listener.getSslTrustStore() != null && truststorePassword != null){
+ trustStore = getStore(truststoreType, truststoreProvider,
+ listener.getSslTrustStore(), truststorePassword);
+ }
+
+ return trustStore;
+ }
+
+ /*
+ * Gets the key- or truststore with the specified type, path, and password.
+ */
+ private KeyStore getStore(String type, String provider, String path,
+ String pass) throws IOException {
+
+ KeyStore ks = null;
+ InputStream istream = null;
+ try {
+ if (provider == null) {
+ ks = KeyStore.getInstance(type);
+ } else {
+ ks = KeyStore.getInstance(type, provider);
+ }
+ if(!("PKCS11".equalsIgnoreCase(type) || "".equalsIgnoreCase(path))) {
+ File keyStoreFile = new File(path);
+ if (!keyStoreFile.isAbsolute()) {
+ keyStoreFile = new File(System.getProperty("catalina.base"),
+ path);
+ }
+ istream = new FileInputStream(keyStoreFile);
+ }
+
+ ks.load(istream, pass.toCharArray());
+ } catch (FileNotFoundException fnfe) {
+ log.error(sm.getString("jsse.keystore_load_failed", type, path,
+ fnfe.getMessage()), fnfe);
+ throw fnfe;
+ } catch (IOException ioe) {
+ log.error(sm.getString("jsse.keystore_load_failed", type, path,
+ ioe.getMessage()), ioe);
+ throw ioe;
+ } catch(Exception ex) {
+ String msg = sm.getString("jsse.keystore_load_failed", type, path,
+ ex.getMessage());
+ log.error(msg, ex);
+ throw new IOException(msg);
+ } finally {
+ if (istream != null) {
+ try {
+ istream.close();
+ } catch (IOException ioe) {
+ // Do nothing
+ }
+ }
+ }
+
+ return ks;
+ }
+
+ /**
+ * Reads the keystore and initializes the SSL socket factory.
+ */
+ void init() throws IOException {
+ try {
+
+ /**
+ String clientAuthStr = (String) attributes.get("clientauth");
+ if("true".equalsIgnoreCase(clientAuthStr) ||
+ "yes".equalsIgnoreCase(clientAuthStr)) {
+ requireClientAuth = true;
+ } else if("want".equalsIgnoreCase(clientAuthStr)) {
+ wantClientAuth = true;
+ }*/
+
+ // Create and init SSLContext
+ SSLContext context = SSLContext.getInstance(listener.getSslProtocol());
+ context.init(getKeyManagers(listener.getSslKeyStoreType(),
+ listener.getSslKeyStoreProvider(),
+ listener.getSslCertificateEncodingAlgorithm(),
+ listener.getSslKeyAlias()),
+ getTrustManagers(listener.getSslKeyStoreType(), listener.getSslKeyStoreProvider(),
+ listener.getSslTrustAlgorithm()),
+ new SecureRandom());
+
+ // create proxy
+ sslProxy = context.getSocketFactory();
+
+ // Determine which cipher suites to enable
+ enabledCiphers = getEnabledCiphers(listener.getSslCiphers(),
+ sslProxy.getSupportedCipherSuites());
+
+ } catch(Exception e) {
+ if( e instanceof IOException )
+ throw (IOException)e;
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ /**
+ * Gets the initialized key managers.
+ */
+ protected KeyManager[] getKeyManagers(String keystoreType,
+ String keystoreProvider,
+ String algorithm,
+ String keyAlias)
+ throws Exception {
+
+ KeyManager[] kms = null;
+
+ KeyStore ks = getKeystore(keystoreType, keystoreProvider, listener.getSslKeyStorePass());
+ if (keyAlias != null && !ks.isKeyEntry(keyAlias)) {
+ throw new IOException(sm.getString("jsse.alias_no_key_entry", keyAlias));
+ }
+
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
+ kmf.init(ks, listener.getSslKeyStorePass().toCharArray());
+
+ kms = kmf.getKeyManagers();
+ if (keyAlias != null) {
+ if ("JKS".equals(keystoreType)) {
+ keyAlias = keyAlias.toLowerCase();
+ }
+ for(int i=0; i<kms.length; i++) {
+ kms[i] = new JSSEKeyManager((X509KeyManager)kms[i], keyAlias);
+ }
+ }
+
+ return kms;
+ }
+
+ /**
+ * Gets the intialized trust managers.
+ */
+ protected TrustManager[] getTrustManagers(String keystoreType,
+ String keystoreProvider, String algorithm)
+ throws Exception {
+ TrustManager[] tms = null;
+
+ KeyStore trustStore = getTrustStore(keystoreType, keystoreProvider);
+ if (trustStore != null) {
+ if (listener.getSslCrlFile() == null) {
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
+ tmf.init(trustStore);
+ tms = tmf.getTrustManagers();
+ } else {
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
+ CertPathParameters params = getParameters(algorithm, listener.getSslCrlFile(), trustStore);
+ ManagerFactoryParameters mfp = new CertPathTrustManagerParameters(params);
+ tmf.init(mfp);
+ tms = tmf.getTrustManagers();
+ }
+ }
+
+ return tms;
+ }
+
+ /**
+ * Return the initialization parameters for the TrustManager.
+ * Currently, only the default <code>PKIX</code> is supported.
+ *
+ * @param algorithm The algorithm to get parameters for.
+ * @param crlf The path to the CRL file.
+ * @param trustStore The configured TrustStore.
+ * @return The parameters including the CRLs and TrustStore.
+ */
+ protected CertPathParameters getParameters(String algorithm,
+ String crlf,
+ KeyStore trustStore)
+ throws Exception {
+ CertPathParameters params = null;
+ if("PKIX".equalsIgnoreCase(algorithm)) {
+ PKIXBuilderParameters xparams = new PKIXBuilderParameters(trustStore,
+ new X509CertSelector());
+ Collection crls = getCRLs(crlf);
+ CertStoreParameters csp = new CollectionCertStoreParameters(crls);
+ CertStore store = CertStore.getInstance("Collection", csp);
+ xparams.addCertStore(store);
+ xparams.setRevocationEnabled(true);
+ xparams.setMaxPathLength(listener.getSslTrustMaxCertLength());
+
+ params = xparams;
+ } else {
+ throw new CRLException("CRLs not supported for type: "+algorithm);
+ }
+ return params;
+ }
+
+
+ /**
+ * Load the collection of CRLs.
+ *
+ */
+ protected Collection<? extends CRL> getCRLs(String crlf)
+ throws IOException, CRLException, CertificateException {
+
+ File crlFile = new File(crlf);
+ if( !crlFile.isAbsolute() ) {
+ crlFile = new File(System.getProperty("catalina.base"), crlf);
+ }
+ Collection<? extends CRL> crls = null;
+ InputStream is = null;
+ try {
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ is = new FileInputStream(crlFile);
+ crls = cf.generateCRLs(is);
+ } catch(IOException iex) {
+ throw iex;
+ } catch(CRLException crle) {
+ throw crle;
+ } catch(CertificateException ce) {
+ throw ce;
+ } finally {
+ if(is != null) {
+ try{
+ is.close();
+ } catch(Exception ex) {
+ }
+ }
+ }
+ return crls;
+ }
+
+ /**
+ * Set the SSL protocol variants to be enabled.
+ * @param socket the SSLServerSocket.
+ * @param protocols the protocols to use.
+ */
+ protected void setEnabledProtocols(SSLSocket socket, String []protocols){
+ if (protocols != null) {
+ socket.setEnabledProtocols(protocols);
+ }
+ }
+
+ /**
+ * Determines the SSL protocol variants to be enabled.
+ *
+ * @param socket The socket to get supported list from.
+ * @param requestedProtocols Comma-separated list of requested SSL
+ * protocol variants
+ *
+ * @return Array of SSL protocol variants to be enabled, or null if none of
+ * the requested protocol variants are supported
+ */
+ protected String[] getEnabledProtocols(SSLSocket socket,
+ String requestedProtocols){
+ String[] supportedProtocols = socket.getSupportedProtocols();
+
+ String[] enabledProtocols = null;
+
+ if (requestedProtocols != null) {
+ Vector vec = null;
+ String protocol = requestedProtocols;
+ int index = requestedProtocols.indexOf(',');
+ if (index != -1) {
+ int fromIndex = 0;
+ while (index != -1) {
+ protocol = requestedProtocols.substring(fromIndex, index).trim();
+ if (protocol.length() > 0) {
+ /*
+ * Check to see if the requested protocol is among the
+ * supported protocols, i.e., may be enabled
+ */
+ for (int i=0; supportedProtocols != null
+ && i<supportedProtocols.length; i++) {
+ if (supportedProtocols[i].equals(protocol)) {
+ if (vec == null) {
+ vec = new Vector();
+ }
+ vec.addElement(protocol);
+ break;
+ }
+ }
+ }
+ fromIndex = index+1;
+ index = requestedProtocols.indexOf(',', fromIndex);
+ } // while
+ protocol = requestedProtocols.substring(fromIndex);
+ }
+
+ if (protocol != null) {
+ protocol = protocol.trim();
+ if (protocol.length() > 0) {
+ /*
+ * Check to see if the requested protocol is among the
+ * supported protocols, i.e., may be enabled
+ */
+ for (int i=0; supportedProtocols != null
+ && i<supportedProtocols.length; i++) {
+ if (supportedProtocols[i].equals(protocol)) {
+ if (vec == null) {
+ vec = new Vector();
+ }
+ vec.addElement(protocol);
+ break;
+ }
+ }
+ }
+ }
+
+ if (vec != null) {
+ enabledProtocols = new String[vec.size()];
+ vec.copyInto(enabledProtocols);
+ }
+ }
+
+ return enabledProtocols;
+ }
+
+ /**
+ * Configures the given SSL server socket with the requested cipher suites,
+ * protocol versions, and need for client authentication
+ */
+ private void initSocket(Socket ssocket) {
+
+ SSLSocket socket = (SSLSocket) ssocket;
+
+ if (enabledCiphers != null) {
+ socket.setEnabledCipherSuites(enabledCiphers);
+ }
+
+ setEnabledProtocols(socket, getEnabledProtocols(socket,
+ listener.getSslProtocol()));
+
+ // we don't know if client auth is needed -
+ // after parsing the request we may re-handshake
+ //configureClientAuth(socket);
+ }
+
+}
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2008-06-04 19:55:55 UTC (rev 656)
+++ trunk/webapps/docs/changelog.xml 2008-06-04 19:57:54 UTC (rev 657)
@@ -44,6 +44,19 @@
<update>
Add all CONFIG parameters to the cluster listener as fields. (remm)
</update>
+ <fix>
+ <bug>43683</bug>: If the context is reloaded, the classloader will have changed so need to reset it. (markt)
+ </fix>
+ <fix>
+ <bug>45101</bug>: Format dates for header value from DirContextURLConnection using HTTP format.
+ Patch provided by Chris Hubick. (markt)
+ </fix>
+ <fix>
+ Avoid overriding existing system properties. (remm)
+ </fix>
+ <update>
+ Add security to ClusterListener using SSL client certificate. (remm)
+ </update>
</changelog>
</subsection>
<subsection name="Coyote">
17 years, 3 months
JBossWeb SVN: r656 - in trunk/java/org/apache/catalina: startup and 1 other directory.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-06-04 15:55:55 -0400 (Wed, 04 Jun 2008)
New Revision: 656
Modified:
trunk/java/org/apache/catalina/manager/host/HTMLHostManagerServlet.java
trunk/java/org/apache/catalina/startup/CatalinaProperties.java
Log:
- Port: Very minor XSS problem.
- Don't override system properties.
Modified: trunk/java/org/apache/catalina/manager/host/HTMLHostManagerServlet.java
===================================================================
--- trunk/java/org/apache/catalina/manager/host/HTMLHostManagerServlet.java 2008-06-02 11:49:30 UTC (rev 655)
+++ trunk/java/org/apache/catalina/manager/host/HTMLHostManagerServlet.java 2008-06-04 19:55:55 UTC (rev 656)
@@ -21,6 +21,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.Map;
@@ -292,17 +293,17 @@
args = new Object[7];
args[0] = response.encodeURL
(request.getContextPath() +
- "/html/start?name=" + hostName);
+ "/html/start?name=" + URLEncoder.encode(hostName, "UTF-8"));
args[1] = hostsStart;
args[2] = response.encodeURL
(request.getContextPath() +
- "/html/stop?name=" + hostName);
+ "/html/stop?name=" + URLEncoder.encode(hostName, "UTF-8"));
args[3] = hostsStop;
args[4] = response.encodeURL
(request.getContextPath() +
- "/html/remove?name=" + hostName);
+ "/html/remove?name=" + URLEncoder.encode(hostName, "UTF-8"));
args[5] = hostsRemove;
- args[6] = hostName;
+ args[6] = RequestUtil.filter(hostName);
if (host == this.host) {
writer.print(MessageFormat.format(
MANAGER_HOST_ROW_BUTTON_SECTION, args));
Modified: trunk/java/org/apache/catalina/startup/CatalinaProperties.java
===================================================================
--- trunk/java/org/apache/catalina/startup/CatalinaProperties.java 2008-06-02 11:49:30 UTC (rev 655)
+++ trunk/java/org/apache/catalina/startup/CatalinaProperties.java 2008-06-04 19:55:55 UTC (rev 656)
@@ -136,7 +136,7 @@
while (enumeration.hasMoreElements()) {
String name = (String) enumeration.nextElement();
String value = properties.getProperty(name);
- if (value != null) {
+ if (value != null && (System.getProperty(name) == null)) {
System.setProperty(name, value);
}
}
17 years, 3 months
JBossWeb SVN: r655 - trunk/java/org/jboss/web/cluster.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-06-02 07:49:30 -0400 (Mon, 02 Jun 2008)
New Revision: 655
Modified:
trunk/java/org/jboss/web/cluster/ClusterListener.java
Log:
- Fix problem with reset leading to adding lifecycle listeners
every time it is called (this was a side effect of
add/removeContext).
Modified: trunk/java/org/jboss/web/cluster/ClusterListener.java
===================================================================
--- trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-05-30 19:22:27 UTC (rev 654)
+++ trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-06-02 11:49:30 UTC (rev 655)
@@ -256,6 +256,7 @@
if (type.equals(Container.ADD_CHILD_EVENT)) {
if (container instanceof Host) {
// Deploying a webapp
+ ((Lifecycle) child).addLifecycleListener(this);
addContext((Context) child, -1);
} else if (container instanceof Engine) {
// Deploying a host
@@ -264,6 +265,7 @@
} else if (type.equals(Container.REMOVE_CHILD_EVENT)) {
if (container instanceof Host) {
// Undeploying a webapp
+ ((Lifecycle) child).removeLifecycleListener(this);
removeContext((Context) child, -1);
} else if (container instanceof Engine) {
// Undeploying a host
@@ -536,6 +538,7 @@
children[j].addContainerListener(this);
Container[] children2 = children[j].findChildren();
for (int k = 0; k < children2.length; k++) {
+ ((Lifecycle) children2[k]).addLifecycleListener(this);
addContext((Context) children2[k], pos);
}
}
@@ -568,6 +571,7 @@
children[j].removeContainerListener(this);
Container[] children2 = children[j].findChildren();
for (int k = 0; k < children2.length; k++) {
+ ((Lifecycle) children2[k]).removeLifecycleListener(this);
removeContext((Context) children2[k], pos);
}
}
@@ -739,8 +743,6 @@
log.debug(sm.getString("clusterListener.context.enable", context.getPath(), context.getParent().getName(), ((StandardContext) context).getState()));
}
- ((Lifecycle) context).addLifecycleListener(this);
-
HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put("JVMRoute", getJvmRoute(context));
parameters.put("Context", ("".equals(context.getPath())) ? "/" : context.getPath());
@@ -763,8 +765,6 @@
log.debug(sm.getString("clusterListener.context.disable", context.getPath(), context.getParent().getName(), ((StandardContext) context).getState()));
}
- ((Lifecycle) context).removeLifecycleListener(this);
-
HashMap<String, String> parameters = new HashMap<String, String>();
String jvmRoute = getJvmRoute(context);
// JVMRoute can be null here if nothing was ever initialized
@@ -970,7 +970,6 @@
String requestLine = command + " " + ((wildcard) ? "*" : proxyURL) + " HTTP/1.0";
int contentLength = body.getLength();
- System.out.println("Body: " + new String(body.getBuffer(), body.getStart(), body.getLength()));
writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
writer.write(requestLine);
writer.write("\r\n");
17 years, 3 months