Added: 
tomcat/sandbox/tomcat-lite/coyote-nio/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
URL: 
http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/coyote-nio/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java?rev=640855&view=auto
==============================================================================
--- 
tomcat/sandbox/tomcat-lite/coyote-nio/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
 (added)
+++ 
tomcat/sandbox/tomcat-lite/coyote-nio/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
 Tue Mar 25 08:23:12 2008
@@ -0,0 +1,670 @@
+/*
+ *  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.apache.tomcat.util.net.jsse;
+
+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.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.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSocket;
+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
+    extends org.apache.tomcat.util.net.ServerSocketFactory {
+
+    private static StringManager sm =
+        StringManager.getManager("org.apache.tomcat.util.net.jsse.res");
+
+    // defaults
+    static String defaultProtocol = "TLS";
+    static boolean defaultClientAuth = false;
+    static String defaultKeystoreType = "JKS";
+    private static final String defaultKeystoreFile
+        = System.getProperty("user.home") + "/.keystore";
+    private static final String defaultKeyPass = "changeit";
+    static org.apache.juli.logging.Log log =
+        org.apache.juli.logging.LogFactory.getLog(JSSESocketFactory.class);
+
+    protected boolean initialized;
+    protected String clientAuth = "false";
+    protected SSLServerSocketFactory sslProxy = null;
+    protected String[] enabledCiphers;
+
+    /**
+     * 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 () {
+    }
+
+    public ServerSocket createSocket (int port)
+        throws IOException
+    {
+        if (!initialized) init();
+        ServerSocket socket = sslProxy.createServerSocket(port);
+        initServerSocket(socket);
+        return socket;
+    }
+    
+    public ServerSocket createSocket (int port, int backlog)
+        throws IOException
+    {
+        if (!initialized) init();
+        ServerSocket socket = sslProxy.createServerSocket(port, backlog);
+        initServerSocket(socket);
+        return socket;
+    }
+    
+    public ServerSocket createSocket (int port, int backlog,
+                                      InetAddress ifAddress)
+        throws IOException
+    {   
+        if (!initialized) init();
+        ServerSocket socket = sslProxy.createServerSocket(port, backlog,
+                                                          ifAddress);
+        initServerSocket(socket);
+        return socket;
+    }
+    
+    public Socket acceptSocket(ServerSocket socket)
+        throws IOException
+    {
+        SSLSocket asock = null;
+        try {
+             asock = (SSLSocket)socket.accept();
+             configureClientAuth(asock);
+        } catch (SSLException e){
+          throw new SocketException("SSL handshake error" + e.toString());
+        }
+        return asock;
+    }
+
+    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 password.
+     */
+    protected String getKeystorePassword() {
+        String keyPass = (String)attributes.get("keypass");
+        if (keyPass == null) {
+            keyPass = defaultKeyPass;
+        }
+        String keystorePass = (String)attributes.get("keystorePass");
+        if (keystorePass == null) {
+            keystorePass = keyPass;
+        }
+        return keystorePass;
+    }
+
+    /*
+     * Gets the SSL server's keystore.
+     */
+    protected KeyStore getKeystore(String type, String pass)
+            throws IOException {
+
+        String keystoreFile = (String)attributes.get("keystore");
+        if (keystoreFile == null)
+            keystoreFile = defaultKeystoreFile;
+
+        return getStore(type, keystoreFile, pass);
+    }
+
+    /*
+     * Gets the SSL server's truststore.
+     */
+    protected KeyStore getTrustStore(String keystoreType) throws IOException {
+        KeyStore trustStore = null;
+
+        String trustStoreFile = (String)attributes.get("truststoreFile");
+        if(trustStoreFile == null) {
+            trustStoreFile = System.getProperty("javax.net.ssl.trustStore");
+        }
+        if(log.isDebugEnabled()) {
+            log.debug("Truststore = " + trustStoreFile);
+        }
+        String trustStorePassword = (String)attributes.get("truststorePass");
+        if( trustStorePassword == null) {
+            trustStorePassword = 
System.getProperty("javax.net.ssl.trustStorePassword");
+        }
+        if( trustStorePassword == null ) {
+            trustStorePassword = getKeystorePassword();
+        }
+        if(log.isDebugEnabled()) {
+            log.debug("TrustPass = " + trustStorePassword);
+        }
+        String truststoreType = (String)attributes.get("truststoreType");
+        if( truststoreType == null) {
+            truststoreType = 
System.getProperty("javax.net.ssl.trustStoreType");
+        }
+        if(truststoreType == null) {
+            truststoreType = keystoreType;
+        }
+        if(log.isDebugEnabled()) {
+            log.debug("trustType = " + truststoreType);
+        }
+        if (trustStoreFile != null && trustStorePassword != null){
+            trustStore = getStore(truststoreType, trustStoreFile,
+                                  trustStorePassword);
+        }
+
+        return trustStore;
+    }
+
+    /*
+     * Gets the key- or truststore with the specified type, path, and password.
+     */
+    private KeyStore getStore(String type, String path, String pass)
+            throws IOException {
+
+        KeyStore ks = null;
+        InputStream istream = null;
+        try {
+            ks = KeyStore.getInstance(type);
+            if(! "PKCS11".equalsIgnoreCase(type) ) {
+                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) {
+            throw fnfe;
+        } catch (IOException ioe) {
+            throw ioe;      
+        } catch(Exception ex) {
+            log.error("Exception trying to load keystore " +path,ex);
+            throw new IOException("Exception trying to load keystore " +
+                                  path + ": " + ex.getMessage() );
+        } 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;
+            }
+
+            // SSL protocol variant (e.g., TLS, SSL v3, etc.)
+            String protocol = (String) attributes.get("protocol");
+            if (protocol == null) {
+                protocol = defaultProtocol;
+            }
+
+            // Certificate encoding algorithm (e.g., SunX509)
+            String algorithm = (String) attributes.get("algorithm");
+            if (algorithm == null) {
+                algorithm = KeyManagerFactory.getDefaultAlgorithm();;
+            }
+
+            String keystoreType = (String) attributes.get("keystoreType");
+            if (keystoreType == null) {
+                keystoreType = defaultKeystoreType;
+            }
+
+        String trustAlgorithm = (String)attributes.get("truststoreAlgorithm");
+        if( trustAlgorithm == null ) {
+            trustAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
+        }
+            // Create and init SSLContext
+            SSLContext context = SSLContext.getInstance(protocol); 
+            context.init(getKeyManagers(keystoreType, algorithm,
+                                        (String) attributes.get("keyAlias")),
+                         getTrustManagers(keystoreType, trustAlgorithm),
+                         new SecureRandom());
+
+            // create proxy
+            sslProxy = context.getServerSocketFactory();
+
+            // Determine which cipher suites to enable
+            String requestedCiphers = (String)attributes.get("ciphers");
+            enabledCiphers = getEnabledCiphers(requestedCiphers,
+                                               
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 algorithm,
+                                          String keyAlias)
+                throws Exception {
+
+        KeyManager[] kms = null;
+
+        String keystorePass = getKeystorePassword();
+
+        KeyStore ks = getKeystore(keystoreType, keystorePass);
+        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, keystorePass.toCharArray());
+
+        kms = kmf.getKeyManagers();
+        if (keyAlias != null) {
+            if (JSSESocketFactory.defaultKeystoreType.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 
algorithm)
+        throws Exception {
+        String crlf = (String) attributes.get("crlFile");
+        
+        TrustManager[] tms = null;
+        
+        String truststoreType = (String) attributes.get("truststoreType");
+        if (truststoreType == null) {
+            truststoreType = keystoreType;
+        }
+        KeyStore trustStore = getTrustStore(truststoreType);
+        if (trustStore != null) {
+            if (crlf == null) {
+                TrustManagerFactory tmf = 
TrustManagerFactory.getInstance(algorithm);
+                tmf.init(trustStore);
+                tms = tmf.getTrustManagers();
+            } else {
+                TrustManagerFactory tmf = 
TrustManagerFactory.getInstance(algorithm);
+                CertPathParameters params = getParameters(algorithm, crlf, 
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);
+            String trustLength = (String)attributes.get("trustMaxCertLength");
+            if(trustLength != null) {
+                try {
+                    xparams.setMaxPathLength(Integer.parseInt(trustLength));
+                } catch(Exception ex) {
+                    log.warn("Bad maxCertLength: "+trustLength);
+                }
+            }
+
+            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(SSLServerSocket 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(SSLServerSocket 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;
+    }
+
+    /**
+     * Configure Client authentication for this version of JSSE.  The
+     * JSSE included in Java 1.4 supports the 'want' value.  Prior
+     * versions of JSSE will treat 'want' as 'false'.
+     * @param socket the SSLServerSocket
+     */
+    protected void configureClientAuth(SSLServerSocket socket){
+        if (wantClientAuth){
+            socket.setWantClientAuth(wantClientAuth);
+        } else {
+            socket.setNeedClientAuth(requireClientAuth);
+        }
+    }
+
+    /**
+     * Configure Client authentication for this version of JSSE.  The
+     * JSSE included in Java 1.4 supports the 'want' value.  Prior
+     * versions of JSSE will treat 'want' as 'false'.
+     * @param socket the SSLSocket
+     */
+    protected void configureClientAuth(SSLSocket socket){
+        // Per JavaDocs: SSLSockets returned from 
+        // SSLServerSocket.accept() inherit this setting.
+    }
+    
+    /**
+     * Configures the given SSL server socket with the requested cipher suites,
+     * protocol versions, and need for client authentication
+     */
+    private void initServerSocket(ServerSocket ssocket) {
+
+        SSLServerSocket socket = (SSLServerSocket) ssocket;
+
+        if (enabledCiphers != null) {
+            socket.setEnabledCipherSuites(enabledCiphers);
+        }
+
+        String requestedProtocols = (String) attributes.get("protocols");
+        setEnabledProtocols(socket, getEnabledProtocols(socket, 
+                                                         requestedProtocols));
+
+        // we don't know if client auth is needed -
+        // after parsing the request we may re-handshake
+        configureClientAuth(socket);
+    }
+
+}

Added: 
tomcat/sandbox/tomcat-lite/coyote-nio/org/apache/tomcat/util/net/jsse/JSSESupport.java
URL: 
http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/coyote-nio/org/apache/tomcat/util/net/jsse/JSSESupport.java?rev=640855&view=auto
==============================================================================
--- 
tomcat/sandbox/tomcat-lite/coyote-nio/org/apache/tomcat/util/net/jsse/JSSESupport.java
 (added)
+++ 
tomcat/sandbox/tomcat-lite/coyote-nio/org/apache/tomcat/util/net/jsse/JSSESupport.java
 Tue Mar 25 08:23:12 2008
@@ -0,0 +1,236 @@
+/*
+ *  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.apache.tomcat.util.net.jsse;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.SocketException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+
+import javax.net.ssl.HandshakeCompletedEvent;
+import javax.net.ssl.HandshakeCompletedListener;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.security.cert.X509Certificate;
+
+import org.apache.tomcat.util.net.SSLSupport;
+
+/** JSSESupport
+
+   Concrete implementation class for JSSE
+   Support classes.
+
+   This will only work with JDK 1.2 and up since it
+   depends on JDK 1.2's certificate support
+
+   @author EKR
+   @author Craig R. McClanahan
+   @author Filip Hanik
+   Parts cribbed from JSSECertCompat       
+   Parts cribbed from CertificatesValve
+*/
+
+class JSSESupport implements SSLSupport {
+    
+    private static org.apache.juli.logging.Log log =
+        org.apache.juli.logging.LogFactory.getLog(JSSESupport.class);
+
+    protected SSLSocket ssl;
+    protected SSLSession session;
+
+    Listener listener = new Listener();
+
+    JSSESupport(SSLSocket sock){
+        ssl=sock;
+        session = sock.getSession();
+        sock.addHandshakeCompletedListener(listener);
+    }
+    
+    JSSESupport(SSLSession session) {
+        this.session = session;
+    }
+
+    public String getCipherSuite() throws IOException {
+        // Look up the current SSLSession
+        if (session == null)
+            return null;
+        return session.getCipherSuite();
+    }
+
+    public Object[] getPeerCertificateChain() 
+        throws IOException {
+        return getPeerCertificateChain(false);
+    }
+
+    protected java.security.cert.X509Certificate [] 
getX509Certificates(SSLSession session) 
+        throws IOException {
+        Certificate [] certs=null;
+        try {
+            certs = session.getPeerCertificates();
+        } catch( Throwable t ) {
+            log.debug("Error getting client certs",t);
+            return null;
+        }
+        if( certs==null ) return null;
+        
+        java.security.cert.X509Certificate [] x509Certs = 
+            new java.security.cert.X509Certificate[certs.length];
+        for(int i=0; i < certs.length; i++) {
+            if (certs[i] instanceof java.security.cert.X509Certificate ) {
+                // always currently true with the JSSE 1.1.x
+                x509Certs[i] = (java.security.cert.X509Certificate) certs[i];
+            } else {
+                try {
+                    byte [] buffer = certs[i].getEncoded();
+                    CertificateFactory cf =
+                        CertificateFactory.getInstance("X.509");
+                    ByteArrayInputStream stream =
+                        new ByteArrayInputStream(buffer);
+                    x509Certs[i] = (java.security.cert.X509Certificate) 
cf.generateCertificate(stream);
+                } catch(Exception ex) { 
+                    log.info("Error translating cert " + certs[i], ex);
+                    return null;
+                }
+            }
+            if(log.isTraceEnabled())
+                log.trace("Cert #" + i + " = " + x509Certs[i]);
+        }
+        if(x509Certs.length < 1)
+            return null;
+        return x509Certs;
+    }
+
+    public Object[] getPeerCertificateChain(boolean force)
+        throws IOException {
+        // Look up the current SSLSession
+        if (session == null)
+            return null;
+
+        // Convert JSSE's certificate format to the ones we need
+       X509Certificate [] jsseCerts = null;
+       try {
+           jsseCerts = session.getPeerCertificateChain();
+       } catch(Exception bex) {
+           // ignore.
+       }
+       if (jsseCerts == null)
+           jsseCerts = new X509Certificate[0];
+       if(jsseCerts.length <= 0 && force) {
+           session.invalidate();
+           handShake();
+           session = ssl.getSession();
+       }
+        return getX509Certificates(session);
+    }
+
+    protected void handShake() throws IOException {
+        if( ssl.getWantClientAuth() ) {
+            log.debug("No client cert sent for want");
+        } else {
+            ssl.setNeedClientAuth(true);
+        }
+
+        InputStream in = ssl.getInputStream();
+        int oldTimeout = ssl.getSoTimeout();
+        ssl.setSoTimeout(1000);
+        byte[] b = new byte[0];
+        listener.reset();
+        ssl.startHandshake();
+        int maxTries = 60; // 60 * 1000 = example 1 minute time out
+        for (int i = 0; i < maxTries; i++) {
+        if(log.isTraceEnabled())
+            log.trace("Reading for try #" +i);
+            try {
+                int x = in.read(b);
+            } catch(SSLException sslex) {
+                log.info("SSL Error getting client Certs",sslex);
+                throw sslex;
+            } catch (IOException e) {
+                // ignore - presumably the timeout
+            }
+            if (listener.completed) {
+                break;
+            }
+        }
+        ssl.setSoTimeout(oldTimeout);
+        if (listener.completed == false) {
+            throw new SocketException("SSL Cert handshake timeout");
+        }
+
+    }
+
+    /**
+     * Copied from <code>org.apache.catalina.valves.CertificateValve</code>
+     */
+    public Integer getKeySize() 
+        throws IOException {
+        // Look up the current SSLSession
+        SSLSupport.CipherData c_aux[]=ciphers;
+        if (session == null)
+            return null;
+        Integer keySize = (Integer) session.getValue(KEY_SIZE_KEY);
+        if (keySize == null) {
+            int size = 0;
+            String cipherSuite = session.getCipherSuite();
+            for (int i = 0; i < c_aux.length; i++) {
+                if (cipherSuite.indexOf(c_aux[i].phrase) >= 0) {
+                    size = c_aux[i].keySize;
+                    break;
+                }
+            }
+            keySize = new Integer(size);
+            session.putValue(KEY_SIZE_KEY, keySize);
+        }
+        return keySize;
+    }
+
+    public String getSessionId()
+        throws IOException {
+        // Look up the current SSLSession
+        if (session == null)
+            return null;
+        // Expose ssl_session (getId)
+        byte [] ssl_session = session.getId();
+        if ( ssl_session == null) 
+            return null;
+        StringBuffer buf=new StringBuffer("");
+        for(int x=0; x<ssl_session.length; x++) {
+            String digit=Integer.toHexString((int)ssl_session[x]);
+            if (digit.length()<2) buf.append('0');
+            if (digit.length()>2) digit=digit.substring(digit.length()-2);
+            buf.append(digit);
+        }
+        return buf.toString();
+    }
+
+
+    private static class Listener implements HandshakeCompletedListener {
+        volatile boolean completed = false;
+        public void handshakeCompleted(HandshakeCompletedEvent event) {
+            completed = true;
+        }
+        void reset() {
+            completed = false;
+        }
+    }
+
+}
+



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to