FileDocCategorySizeDatePackage
JSSESocketFactory.javaAPI DocApache Tomcat 6.0.1424705Fri Jul 20 04:20:36 BST 2007org.apache.tomcat.util.net.jsse

JSSESocketFactory

public class JSSESocketFactory extends org.apache.tomcat.util.net.ServerSocketFactory
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

Fields Summary
private static org.apache.tomcat.util.res.StringManager
sm
static String
defaultProtocol
static boolean
defaultClientAuth
static String
defaultKeystoreType
private static final String
defaultKeystoreFile
private static final String
defaultKeyPass
static org.apache.juli.logging.Log
log
protected boolean
initialized
protected String
clientAuth
protected SSLServerSocketFactory
sslProxy
protected String[]
enabledCiphers
protected boolean
requireClientAuth
Flag to state that we require client authentication.
protected boolean
wantClientAuth
Flag to state that we would like client authentication.
Constructors Summary
public JSSESocketFactory()



       
    
Methods Summary
public java.net.SocketacceptSocket(java.net.ServerSocket socket)

        SSLSocket asock = null;
        try {
             asock = (SSLSocket)socket.accept();
             configureClientAuth(asock);
        } catch (SSLException e){
          throw new SocketException("SSL handshake error" + e.toString());
        }
        return asock;
    
protected voidconfigureClientAuth(javax.net.ssl.SSLServerSocket socket)
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

        if (wantClientAuth){
            socket.setWantClientAuth(wantClientAuth);
        } else {
            socket.setNeedClientAuth(requireClientAuth);
        }
    
protected voidconfigureClientAuth(javax.net.ssl.SSLSocket socket)
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

        // Per JavaDocs: SSLSockets returned from 
        // SSLServerSocket.accept() inherit this setting.
    
public java.net.ServerSocketcreateSocket(int port)

        if (!initialized) init();
        ServerSocket socket = sslProxy.createServerSocket(port);
        initServerSocket(socket);
        return socket;
    
public java.net.ServerSocketcreateSocket(int port, int backlog)

        if (!initialized) init();
        ServerSocket socket = sslProxy.createServerSocket(port, backlog);
        initServerSocket(socket);
        return socket;
    
public java.net.ServerSocketcreateSocket(int port, int backlog, java.net.InetAddress ifAddress)

   
        if (!initialized) init();
        ServerSocket socket = sslProxy.createServerSocket(port, backlog,
                                                          ifAddress);
        initServerSocket(socket);
        return socket;
    
protected java.util.CollectiongetCRLs(java.lang.String crlf)
Load the collection of CRLs.


        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;
    
protected java.lang.String[]getEnabledCiphers(java.lang.String requestedCiphers, java.lang.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;
    
protected java.lang.String[]getEnabledProtocols(javax.net.ssl.SSLServerSocket socket, java.lang.String requestedProtocols)
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

        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;
    
protected javax.net.ssl.KeyManager[]getKeyManagers(java.lang.String keystoreType, java.lang.String algorithm, java.lang.String keyAlias)
Gets the initialized key managers.


        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;
    
protected java.security.KeyStoregetKeystore(java.lang.String type, java.lang.String pass)


        String keystoreFile = (String)attributes.get("keystore");
        if (keystoreFile == null)
            keystoreFile = defaultKeystoreFile;

        return getStore(type, keystoreFile, pass);
    
protected java.lang.StringgetKeystorePassword()

        String keyPass = (String)attributes.get("keypass");
        if (keyPass == null) {
            keyPass = defaultKeyPass;
        }
        String keystorePass = (String)attributes.get("keystorePass");
        if (keystorePass == null) {
            keystorePass = keyPass;
        }
        return keystorePass;
    
protected java.security.cert.CertPathParametersgetParameters(java.lang.String algorithm, java.lang.String crlf, java.security.KeyStore trustStore)
Return the initialization parameters for the TrustManager. Currently, only the default PKIX 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.

        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;
    
private java.security.KeyStoregetStore(java.lang.String type, java.lang.String path, java.lang.String pass)


        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;
    
protected javax.net.ssl.TrustManager[]getTrustManagers(java.lang.String keystoreType, java.lang.String algorithm)
Gets the intialized trust managers.

        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;
    
protected java.security.KeyStoregetTrustStore(java.lang.String keystoreType)

        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 = keystoreType;
        }
        if(log.isDebugEnabled()) {
            log.debug("trustType = " + truststoreType);
        }
        if (trustStoreFile != null && trustStorePassword != null){
            trustStore = getStore(truststoreType, trustStoreFile,
                                  trustStorePassword);
        }

        return trustStore;
    
public voidhandshake(java.net.Socket sock)

        ((SSLSocket)sock).startHandshake();
    
voidinit()
Reads the keystore and initializes the SSL socket factory.

        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());
        }
    
private voidinitServerSocket(java.net.ServerSocket ssocket)
Configures the given SSL server socket with the requested cipher suites, protocol versions, and need for client authentication


        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);
    
protected voidsetEnabledProtocols(javax.net.ssl.SSLServerSocket socket, java.lang.String[] protocols)
Set the SSL protocol variants to be enabled.

param
socket the SSLServerSocket.
param
protocols the protocols to use.

        if (protocols != null) {
            socket.setEnabledProtocols(protocols);
        }