Home » apache-tomcat-6.0.26-src » org.apache » tomcat » util » net » jsse » [javadoc | source]

    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   
   18   package org.apache.tomcat.util.net.jsse;
   19   
   20   import java.io.File;
   21   import java.io.FileInputStream;
   22   import java.io.FileNotFoundException;
   23   import java.io.IOException;
   24   import java.io.InputStream;
   25   import java.net.InetAddress;
   26   import java.net.ServerSocket;
   27   import java.net.Socket;
   28   import java.net.SocketException;
   29   import java.security.KeyStore;
   30   import java.security.SecureRandom;
   31   import java.security.cert.CRL;
   32   import java.security.cert.CRLException;
   33   import java.security.cert.CertPathParameters;
   34   import java.security.cert.CertStore;
   35   import java.security.cert.CertStoreParameters;
   36   import java.security.cert.CertificateException;
   37   import java.security.cert.CertificateFactory;
   38   import java.security.cert.CollectionCertStoreParameters;
   39   import java.security.cert.PKIXBuilderParameters;
   40   import java.security.cert.X509CertSelector;
   41   import java.util.Collection;
   42   import java.util.Vector;
   43   
   44   import javax.net.ssl.CertPathTrustManagerParameters;
   45   import javax.net.ssl.KeyManager;
   46   import javax.net.ssl.KeyManagerFactory;
   47   import javax.net.ssl.ManagerFactoryParameters;
   48   import javax.net.ssl.SSLContext;
   49   import javax.net.ssl.SSLException;
   50   import javax.net.ssl.SSLServerSocket;
   51   import javax.net.ssl.SSLServerSocketFactory;
   52   import javax.net.ssl.SSLSessionContext;
   53   import javax.net.ssl.SSLSocket;
   54   import javax.net.ssl.TrustManager;
   55   import javax.net.ssl.TrustManagerFactory;
   56   import javax.net.ssl.X509KeyManager;
   57   
   58   import org.apache.tomcat.util.res.StringManager;
   59   
   60   /*
   61     1. Make the JSSE's jars available, either as an installed
   62        extension (copy them into jre/lib/ext) or by adding
   63        them to the Tomcat classpath.
   64     2. keytool -genkey -alias tomcat -keyalg RSA
   65        Use "changeit" as password ( this is the default we use )
   66    */
   67   
   68   /**
   69    * SSL server socket factory. It _requires_ a valid RSA key and
   70    * JSSE. 
   71    *
   72    * @author Harish Prabandham
   73    * @author Costin Manolache
   74    * @author Stefan Freyr Stefansson
   75    * @author EKR -- renamed to JSSESocketFactory
   76    * @author Jan Luehe
   77    * @author Bill Barker
   78    */
   79   public class JSSESocketFactory
   80       extends org.apache.tomcat.util.net.ServerSocketFactory {
   81   
   82       private static StringManager sm =
   83           StringManager.getManager("org.apache.tomcat.util.net.jsse.res");
   84   
   85       // defaults
   86       static String defaultProtocol = "TLS";
   87       static boolean defaultClientAuth = false;
   88       static String defaultKeystoreType = "JKS";
   89       private static final String defaultKeystoreFile
   90           = System.getProperty("user.home") + "/.keystore";
   91       private static final String defaultKeyPass = "changeit";
   92       private static final int defaultSessionCacheSize = 0;
   93       private static final int defaultSessionTimeout = 86400;
   94       
   95       static org.apache.juli.logging.Log log =
   96           org.apache.juli.logging.LogFactory.getLog(JSSESocketFactory.class);
   97   
   98       protected boolean initialized;
   99       protected String clientAuth = "false";
  100       protected SSLServerSocketFactory sslProxy = null;
  101       protected String[] enabledCiphers;
  102       protected boolean allowUnsafeLegacyRenegotiation = false;
  103   
  104       /**
  105        * Flag to state that we require client authentication.
  106        */
  107       protected boolean requireClientAuth = false;
  108   
  109       /**
  110        * Flag to state that we would like client authentication.
  111        */
  112       protected boolean wantClientAuth    = false;
  113   
  114   
  115       public JSSESocketFactory () {
  116       }
  117   
  118       public ServerSocket createSocket (int port)
  119           throws IOException
  120       {
  121           if (!initialized) init();
  122           ServerSocket socket = sslProxy.createServerSocket(port);
  123           initServerSocket(socket);
  124           return socket;
  125       }
  126       
  127       public ServerSocket createSocket (int port, int backlog)
  128           throws IOException
  129       {
  130           if (!initialized) init();
  131           ServerSocket socket = sslProxy.createServerSocket(port, backlog);
  132           initServerSocket(socket);
  133           return socket;
  134       }
  135       
  136       public ServerSocket createSocket (int port, int backlog,
  137                                         InetAddress ifAddress)
  138           throws IOException
  139       {   
  140           if (!initialized) init();
  141           ServerSocket socket = sslProxy.createServerSocket(port, backlog,
  142                                                             ifAddress);
  143           initServerSocket(socket);
  144           return socket;
  145       }
  146       
  147       public Socket acceptSocket(ServerSocket socket)
  148           throws IOException
  149       {
  150           SSLSocket asock = null;
  151           try {
  152                asock = (SSLSocket)socket.accept();
  153                configureClientAuth(asock);
  154           } catch (SSLException e){
  155             throw new SocketException("SSL handshake error" + e.toString());
  156           }
  157           return asock;
  158       }
  159       
  160       public void handshake(Socket sock) throws IOException {
  161           ((SSLSocket)sock).startHandshake();
  162           
  163           if (!allowUnsafeLegacyRenegotiation) {
  164               // Prevent futher handshakes by removing all cipher suites
  165               ((SSLSocket) sock).setEnabledCipherSuites(new String[0]);
  166           }
  167       }
  168   
  169       /*
  170        * Determines the SSL cipher suites to be enabled.
  171        *
  172        * @param requestedCiphers Comma-separated list of requested ciphers
  173        * @param supportedCiphers Array of supported ciphers
  174        *
  175        * @return Array of SSL cipher suites to be enabled, or null if none of the
  176        * requested ciphers are supported
  177        */
  178       protected String[] getEnabledCiphers(String requestedCiphers,
  179                                            String[] supportedCiphers) {
  180   
  181           String[] enabledCiphers = null;
  182   
  183           if (requestedCiphers != null) {
  184               Vector vec = null;
  185               String cipher = requestedCiphers;
  186               int index = requestedCiphers.indexOf(',');
  187               if (index != -1) {
  188                   int fromIndex = 0;
  189                   while (index != -1) {
  190                       cipher = requestedCiphers.substring(fromIndex, index).trim();
  191                       if (cipher.length() > 0) {
  192                           /*
  193                            * Check to see if the requested cipher is among the
  194                            * supported ciphers, i.e., may be enabled
  195                            */
  196                           for (int i=0; supportedCiphers != null
  197                                        && i<supportedCiphers.length; i++) {
  198                               if (supportedCiphers[i].equals(cipher)) {
  199                                   if (vec == null) {
  200                                       vec = new Vector();
  201                                   }
  202                                   vec.addElement(cipher);
  203                                   break;
  204                               }
  205                           }
  206                       }
  207                       fromIndex = index+1;
  208                       index = requestedCiphers.indexOf(',', fromIndex);
  209                   } // while
  210                   cipher = requestedCiphers.substring(fromIndex);
  211               }
  212   
  213               if (cipher != null) {
  214                   cipher = cipher.trim();
  215                   if (cipher.length() > 0) {
  216                       /*
  217                        * Check to see if the requested cipher is among the
  218                        * supported ciphers, i.e., may be enabled
  219                        */
  220                       for (int i=0; supportedCiphers != null
  221                                    && i<supportedCiphers.length; i++) {
  222                           if (supportedCiphers[i].equals(cipher)) {
  223                               if (vec == null) {
  224                                   vec = new Vector();
  225                               }
  226                               vec.addElement(cipher);
  227                               break;
  228                           }
  229                       }
  230                   }
  231               }           
  232   
  233               if (vec != null) {
  234                   enabledCiphers = new String[vec.size()];
  235                   vec.copyInto(enabledCiphers);
  236               }
  237           } else {
  238               enabledCiphers = sslProxy.getDefaultCipherSuites();
  239           }
  240   
  241           return enabledCiphers;
  242       }
  243        
  244       /*
  245        * Gets the SSL server's keystore password.
  246        */
  247       protected String getKeystorePassword() {
  248           String keyPass = (String)attributes.get("keypass");
  249           if (keyPass == null) {
  250               keyPass = defaultKeyPass;
  251           }
  252           String keystorePass = (String)attributes.get("keystorePass");
  253           if (keystorePass == null) {
  254               keystorePass = keyPass;
  255           }
  256           return keystorePass;
  257       }
  258   
  259       /*
  260        * Gets the SSL server's keystore.
  261        */
  262       protected KeyStore getKeystore(String type, String provider, String pass)
  263               throws IOException {
  264   
  265           String keystoreFile = (String)attributes.get("keystore");
  266           if (keystoreFile == null)
  267               keystoreFile = defaultKeystoreFile;
  268   
  269           return getStore(type, provider, keystoreFile, pass);
  270       }
  271   
  272       /*
  273        * Gets the SSL server's truststore.
  274        */
  275       protected KeyStore getTrustStore(String keystoreType,
  276               String keystoreProvider) throws IOException {
  277           KeyStore trustStore = null;
  278   
  279           String truststoreFile = (String)attributes.get("truststoreFile");
  280           if(truststoreFile == null) {
  281               truststoreFile = System.getProperty("javax.net.ssl.trustStore");
  282           }
  283           if(log.isDebugEnabled()) {
  284               log.debug("Truststore = " + truststoreFile);
  285           }
  286           String truststorePassword = (String)attributes.get("truststorePass");
  287           if( truststorePassword == null) {
  288               truststorePassword = System.getProperty("javax.net.ssl.trustStorePassword");
  289           }
  290           if( truststorePassword == null ) {
  291               truststorePassword = getKeystorePassword();
  292           }
  293           if(log.isDebugEnabled()) {
  294               log.debug("TrustPass = " + truststorePassword);
  295           }
  296           String truststoreType = (String)attributes.get("truststoreType");
  297           if( truststoreType == null) {
  298               truststoreType = System.getProperty("javax.net.ssl.trustStoreType");
  299           }
  300           if(truststoreType == null) {
  301               truststoreType = keystoreType;
  302           }
  303           if(log.isDebugEnabled()) {
  304               log.debug("trustType = " + truststoreType);
  305           }
  306           String truststoreProvider =
  307               (String)attributes.get("truststoreProvider");
  308           if( truststoreProvider == null) {
  309               truststoreProvider =
  310                   System.getProperty("javax.net.ssl.trustStoreProvider");
  311           }
  312           if (truststoreProvider == null) {
  313               truststoreProvider = keystoreProvider;
  314           }
  315           if(log.isDebugEnabled()) {
  316               log.debug("trustProvider = " + truststoreProvider);
  317           }
  318   
  319           if (truststoreFile != null && truststorePassword != null){
  320               trustStore = getStore(truststoreType, truststoreProvider,
  321                       truststoreFile, truststorePassword);
  322           }
  323   
  324           return trustStore;
  325       }
  326   
  327       /*
  328        * Gets the key- or truststore with the specified type, path, and password.
  329        */
  330       private KeyStore getStore(String type, String provider, String path,
  331               String pass) throws IOException {
  332   
  333           KeyStore ks = null;
  334           InputStream istream = null;
  335           try {
  336               if (provider == null) {
  337                   ks = KeyStore.getInstance(type);
  338               } else {
  339                   ks = KeyStore.getInstance(type, provider);
  340               }
  341               if(!("PKCS11".equalsIgnoreCase(type) || "".equalsIgnoreCase(path))) {
  342                   File keyStoreFile = new File(path);
  343                   if (!keyStoreFile.isAbsolute()) {
  344                       keyStoreFile = new File(System.getProperty("catalina.base"),
  345                                               path);
  346                   }
  347                   istream = new FileInputStream(keyStoreFile);
  348               }
  349   
  350               ks.load(istream, pass.toCharArray());
  351           } catch (FileNotFoundException fnfe) {
  352               log.error(sm.getString("jsse.keystore_load_failed", type, path,
  353                       fnfe.getMessage()), fnfe);
  354               throw fnfe;
  355           } catch (IOException ioe) {
  356               log.error(sm.getString("jsse.keystore_load_failed", type, path,
  357                       ioe.getMessage()), ioe);
  358               throw ioe;      
  359           } catch(Exception ex) {
  360               String msg = sm.getString("jsse.keystore_load_failed", type, path,
  361                       ex.getMessage());
  362               log.error(msg, ex);
  363               throw new IOException(msg);
  364           } finally {
  365               if (istream != null) {
  366                   try {
  367                       istream.close();
  368                   } catch (IOException ioe) {
  369                       // Do nothing
  370                   }
  371               }
  372           }
  373   
  374           return ks;
  375       }
  376   
  377       /**
  378        * Reads the keystore and initializes the SSL socket factory.
  379        */
  380       void init() throws IOException {
  381           try {
  382   
  383               String clientAuthStr = (String) attributes.get("clientauth");
  384               if("true".equalsIgnoreCase(clientAuthStr) ||
  385                  "yes".equalsIgnoreCase(clientAuthStr)) {
  386                   requireClientAuth = true;
  387               } else if("want".equalsIgnoreCase(clientAuthStr)) {
  388                   wantClientAuth = true;
  389               }
  390   
  391               // SSL protocol variant (e.g., TLS, SSL v3, etc.)
  392               String protocol = (String) attributes.get("protocol");
  393               if (protocol == null) {
  394                   protocol = defaultProtocol;
  395               }
  396   
  397               // Certificate encoding algorithm (e.g., SunX509)
  398               String algorithm = (String) attributes.get("algorithm");
  399               if (algorithm == null) {
  400                   algorithm = KeyManagerFactory.getDefaultAlgorithm();;
  401               }
  402   
  403               String keystoreType = (String) attributes.get("keystoreType");
  404               if (keystoreType == null) {
  405                   keystoreType = defaultKeystoreType;
  406               }
  407   
  408               String keystoreProvider =
  409                   (String) attributes.get("keystoreProvider");
  410   
  411               String trustAlgorithm =
  412                   (String)attributes.get("truststoreAlgorithm");
  413               if( trustAlgorithm == null ) {
  414                   trustAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
  415               }
  416   
  417               // Create and init SSLContext
  418               SSLContext context = SSLContext.getInstance(protocol); 
  419               context.init(getKeyManagers(keystoreType, keystoreProvider,
  420                                    algorithm,
  421                                    (String) attributes.get("keyAlias")),
  422                            getTrustManagers(keystoreType, keystoreProvider,
  423                                    trustAlgorithm),
  424                            new SecureRandom());
  425   
  426               // Configure SSL session cache
  427               int sessionCacheSize;
  428               if (attributes.get("sessionCacheSize") != null) {
  429                   sessionCacheSize = Integer.parseInt(
  430                           (String)attributes.get("sessionCacheSize"));
  431               } else {
  432                   sessionCacheSize = defaultSessionCacheSize;
  433               }
  434               int sessionCacheTimeout;
  435               if (attributes.get("sessionCacheTimeout") != null) {
  436                   sessionCacheTimeout = Integer.parseInt(
  437                           (String)attributes.get("sessionCacheTimeout"));
  438               } else {
  439                   sessionCacheTimeout = defaultSessionTimeout;
  440               }
  441               SSLSessionContext sessionContext =
  442                   context.getServerSessionContext();
  443               if (sessionContext != null) {
  444                   sessionContext.setSessionCacheSize(sessionCacheSize);
  445                   sessionContext.setSessionTimeout(sessionCacheTimeout);
  446               }
  447   
  448               // create proxy
  449               sslProxy = context.getServerSocketFactory();
  450   
  451               // Determine which cipher suites to enable
  452               String requestedCiphers = (String)attributes.get("ciphers");
  453               enabledCiphers = getEnabledCiphers(requestedCiphers,
  454                                                  sslProxy.getSupportedCipherSuites());
  455   
  456               allowUnsafeLegacyRenegotiation =
  457                   "true".equals(attributes.get("allowUnsafeLegacyRenegotiation"));
  458               
  459               // Check the SSL config is OK
  460               checkConfig();
  461   
  462           } catch(Exception e) {
  463               if( e instanceof IOException )
  464                   throw (IOException)e;
  465               throw new IOException(e.getMessage());
  466           }
  467       }
  468   
  469       /**
  470        * Gets the initialized key managers.
  471        */
  472       protected KeyManager[] getKeyManagers(String keystoreType,
  473                                             String keystoreProvider,
  474                                             String algorithm,
  475                                             String keyAlias)
  476                   throws Exception {
  477   
  478           KeyManager[] kms = null;
  479   
  480           String keystorePass = getKeystorePassword();
  481   
  482           KeyStore ks = getKeystore(keystoreType, keystoreProvider, keystorePass);
  483           if (keyAlias != null && !ks.isKeyEntry(keyAlias)) {
  484               throw new IOException(sm.getString("jsse.alias_no_key_entry", keyAlias));
  485           }
  486   
  487           KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
  488           kmf.init(ks, keystorePass.toCharArray());
  489   
  490           kms = kmf.getKeyManagers();
  491           if (keyAlias != null) {
  492               if (JSSESocketFactory.defaultKeystoreType.equals(keystoreType)) {
  493                   keyAlias = keyAlias.toLowerCase();
  494               }
  495               for(int i=0; i<kms.length; i++) {
  496                   kms[i] = new JSSEKeyManager((X509KeyManager)kms[i], keyAlias);
  497               }
  498           }
  499   
  500           return kms;
  501       }
  502   
  503       /**
  504        * Gets the intialized trust managers.
  505        */
  506       protected TrustManager[] getTrustManagers(String keystoreType,
  507               String keystoreProvider, String algorithm)
  508           throws Exception {
  509           String crlf = (String) attributes.get("crlFile");
  510           
  511           TrustManager[] tms = null;
  512           
  513           KeyStore trustStore = getTrustStore(keystoreType, keystoreProvider);
  514           if (trustStore != null) {
  515               if (crlf == null) {
  516                   TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
  517                   tmf.init(trustStore);
  518                   tms = tmf.getTrustManagers();
  519               } else {
  520                   TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
  521                   CertPathParameters params = getParameters(algorithm, crlf, trustStore);
  522                   ManagerFactoryParameters mfp = new CertPathTrustManagerParameters(params);
  523                   tmf.init(mfp);
  524                   tms = tmf.getTrustManagers();
  525               }
  526           }
  527           
  528           return tms;
  529       }
  530       
  531       /**
  532        * Return the initialization parameters for the TrustManager.
  533        * Currently, only the default <code>PKIX</code> is supported.
  534        * 
  535        * @param algorithm The algorithm to get parameters for.
  536        * @param crlf The path to the CRL file.
  537        * @param trustStore The configured TrustStore.
  538        * @return The parameters including the CRLs and TrustStore.
  539        */
  540       protected CertPathParameters getParameters(String algorithm, 
  541                                                   String crlf, 
  542                                                   KeyStore trustStore)
  543           throws Exception {
  544           CertPathParameters params = null;
  545           if("PKIX".equalsIgnoreCase(algorithm)) {
  546               PKIXBuilderParameters xparams = new PKIXBuilderParameters(trustStore, 
  547                                                                        new X509CertSelector());
  548               Collection crls = getCRLs(crlf);
  549               CertStoreParameters csp = new CollectionCertStoreParameters(crls);
  550               CertStore store = CertStore.getInstance("Collection", csp);
  551               xparams.addCertStore(store);
  552               xparams.setRevocationEnabled(true);
  553               String trustLength = (String)attributes.get("trustMaxCertLength");
  554               if(trustLength != null) {
  555                   try {
  556                       xparams.setMaxPathLength(Integer.parseInt(trustLength));
  557                   } catch(Exception ex) {
  558                       log.warn("Bad maxCertLength: "+trustLength);
  559                   }
  560               }
  561   
  562               params = xparams;
  563           } else {
  564               throw new CRLException("CRLs not supported for type: "+algorithm);
  565           }
  566           return params;
  567       }
  568   
  569   
  570       /**
  571        * Load the collection of CRLs.
  572        * 
  573        */
  574       protected Collection<? extends CRL> getCRLs(String crlf) 
  575           throws IOException, CRLException, CertificateException {
  576   
  577           File crlFile = new File(crlf);
  578           if( !crlFile.isAbsolute() ) {
  579               crlFile = new File(System.getProperty("catalina.base"), crlf);
  580           }
  581           Collection<? extends CRL> crls = null;
  582           InputStream is = null;
  583           try {
  584               CertificateFactory cf = CertificateFactory.getInstance("X.509");
  585               is = new FileInputStream(crlFile);
  586               crls = cf.generateCRLs(is);
  587           } catch(IOException iex) {
  588               throw iex;
  589           } catch(CRLException crle) {
  590               throw crle;
  591           } catch(CertificateException ce) {
  592               throw ce;
  593           } finally { 
  594               if(is != null) {
  595                   try{
  596                       is.close();
  597                   } catch(Exception ex) {
  598                   }
  599               }
  600           }
  601           return crls;
  602       }
  603   
  604       /**
  605        * Set the SSL protocol variants to be enabled.
  606        * @param socket the SSLServerSocket.
  607        * @param protocols the protocols to use.
  608        */
  609       protected void setEnabledProtocols(SSLServerSocket socket, String []protocols){
  610           if (protocols != null) {
  611               socket.setEnabledProtocols(protocols);
  612           }
  613       }
  614   
  615       /**
  616        * Determines the SSL protocol variants to be enabled.
  617        *
  618        * @param socket The socket to get supported list from.
  619        * @param requestedProtocols Comma-separated list of requested SSL
  620        * protocol variants
  621        *
  622        * @return Array of SSL protocol variants to be enabled, or null if none of
  623        * the requested protocol variants are supported
  624        */
  625       protected String[] getEnabledProtocols(SSLServerSocket socket,
  626                                              String requestedProtocols){
  627           String[] supportedProtocols = socket.getSupportedProtocols();
  628   
  629           String[] enabledProtocols = null;
  630   
  631           if (requestedProtocols != null) {
  632               Vector vec = null;
  633               String protocol = requestedProtocols;
  634               int index = requestedProtocols.indexOf(',');
  635               if (index != -1) {
  636                   int fromIndex = 0;
  637                   while (index != -1) {
  638                       protocol = requestedProtocols.substring(fromIndex, index).trim();
  639                       if (protocol.length() > 0) {
  640                           /*
  641                            * Check to see if the requested protocol is among the
  642                            * supported protocols, i.e., may be enabled
  643                            */
  644                           for (int i=0; supportedProtocols != null
  645                                        && i<supportedProtocols.length; i++) {
  646                               if (supportedProtocols[i].equals(protocol)) {
  647                                   if (vec == null) {
  648                                       vec = new Vector();
  649                                   }
  650                                   vec.addElement(protocol);
  651                                   break;
  652                               }
  653                           }
  654                       }
  655                       fromIndex = index+1;
  656                       index = requestedProtocols.indexOf(',', fromIndex);
  657                   } // while
  658                   protocol = requestedProtocols.substring(fromIndex);
  659               }
  660   
  661               if (protocol != null) {
  662                   protocol = protocol.trim();
  663                   if (protocol.length() > 0) {
  664                       /*
  665                        * Check to see if the requested protocol is among the
  666                        * supported protocols, i.e., may be enabled
  667                        */
  668                       for (int i=0; supportedProtocols != null
  669                                    && i<supportedProtocols.length; i++) {
  670                           if (supportedProtocols[i].equals(protocol)) {
  671                               if (vec == null) {
  672                                   vec = new Vector();
  673                               }
  674                               vec.addElement(protocol);
  675                               break;
  676                           }
  677                       }
  678                   }
  679               }           
  680   
  681               if (vec != null) {
  682                   enabledProtocols = new String[vec.size()];
  683                   vec.copyInto(enabledProtocols);
  684               }
  685           }
  686   
  687           return enabledProtocols;
  688       }
  689   
  690       /**
  691        * Configure Client authentication for this version of JSSE.  The
  692        * JSSE included in Java 1.4 supports the 'want' value.  Prior
  693        * versions of JSSE will treat 'want' as 'false'.
  694        * @param socket the SSLServerSocket
  695        */
  696       protected void configureClientAuth(SSLServerSocket socket){
  697           if (wantClientAuth){
  698               socket.setWantClientAuth(wantClientAuth);
  699           } else {
  700               socket.setNeedClientAuth(requireClientAuth);
  701           }
  702       }
  703   
  704       /**
  705        * Configure Client authentication for this version of JSSE.  The
  706        * JSSE included in Java 1.4 supports the 'want' value.  Prior
  707        * versions of JSSE will treat 'want' as 'false'.
  708        * @param socket the SSLSocket
  709        */
  710       protected void configureClientAuth(SSLSocket socket){
  711           // Per JavaDocs: SSLSockets returned from 
  712           // SSLServerSocket.accept() inherit this setting.
  713       }
  714       
  715       /**
  716        * Configures the given SSL server socket with the requested cipher suites,
  717        * protocol versions, and need for client authentication
  718        */
  719       private void initServerSocket(ServerSocket ssocket) {
  720   
  721           SSLServerSocket socket = (SSLServerSocket) ssocket;
  722   
  723           if (enabledCiphers != null) {
  724               socket.setEnabledCipherSuites(enabledCiphers);
  725           }
  726   
  727           String requestedProtocols = (String) attributes.get("protocols");
  728           setEnabledProtocols(socket, getEnabledProtocols(socket, 
  729                                                            requestedProtocols));
  730   
  731           // we don't know if client auth is needed -
  732           // after parsing the request we may re-handshake
  733           configureClientAuth(socket);
  734       }
  735   
  736       /**
  737        * Checks that the certificate is compatible with the enabled cipher suites.
  738        * If we don't check now, the JIoEndpoint can enter a nasty logging loop.
  739        * See bug 45528.
  740        */
  741       private void checkConfig() throws IOException {
  742           // Create an unbound server socket
  743           ServerSocket socket = sslProxy.createServerSocket();
  744           initServerSocket(socket);
  745   
  746           try {
  747               // Set the timeout to 1ms as all we care about is if it throws an
  748               // SSLException on accept. 
  749               socket.setSoTimeout(1);
  750   
  751               socket.accept();
  752               // Will never get here - no client can connect to an unbound port
  753           } catch (SSLException ssle) {
  754               // SSL configuration is invalid. Possibly cert doesn't match ciphers
  755               IOException ioe = new IOException(sm.getString(
  756                       "jsse.invalid_ssl_conf", ssle.getMessage()));
  757               ioe.initCause(ssle);
  758               throw ioe;
  759           } catch (Exception e) {
  760               /*
  761                * Possible ways of getting here
  762                * socket.accept() throws a SecurityException
  763                * socket.setSoTimeout() throws a SocketException
  764                * socket.accept() throws some other exception (after a JDK change)
  765                *      In these cases the test won't work so carry on - essentially
  766                *      the behaviour before this patch
  767                * socket.accept() throws a SocketTimeoutException
  768                *      In this case all is well so carry on
  769                */
  770           } finally {
  771               // Should be open here but just in case
  772               if (!socket.isClosed()) {
  773                   socket.close();
  774               }
  775           }
  776           
  777       }
  778   }

Home » apache-tomcat-6.0.26-src » org.apache » tomcat » util » net » jsse » [javadoc | source]