Save This Page
Home » apache-tomcat-6.0.16-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.ByteArrayInputStream;
   21   import java.io.IOException;
   22   import java.io.InputStream;
   23   import java.net.SocketException;
   24   import java.security.cert.Certificate;
   25   import java.security.cert.CertificateFactory;
   26   
   27   import javax.net.ssl.HandshakeCompletedEvent;
   28   import javax.net.ssl.HandshakeCompletedListener;
   29   import javax.net.ssl.SSLException;
   30   import javax.net.ssl.SSLSession;
   31   import javax.net.ssl.SSLSocket;
   32   import javax.security.cert.X509Certificate;
   33   
   34   import org.apache.tomcat.util.net.SSLSupport;
   35   
   36   /** JSSESupport
   37   
   38      Concrete implementation class for JSSE
   39      Support classes.
   40   
   41      This will only work with JDK 1.2 and up since it
   42      depends on JDK 1.2's certificate support
   43   
   44      @author EKR
   45      @author Craig R. McClanahan
   46      @author Filip Hanik
   47      Parts cribbed from JSSECertCompat       
   48      Parts cribbed from CertificatesValve
   49   */
   50   
   51   class JSSESupport implements SSLSupport {
   52       
   53       private static org.apache.juli.logging.Log log =
   54           org.apache.juli.logging.LogFactory.getLog(JSSESupport.class);
   55   
   56       protected SSLSocket ssl;
   57       protected SSLSession session;
   58   
   59       Listener listener = new Listener();
   60   
   61       JSSESupport(SSLSocket sock){
   62           ssl=sock;
   63           session = sock.getSession();
   64           sock.addHandshakeCompletedListener(listener);
   65       }
   66       
   67       JSSESupport(SSLSession session) {
   68           this.session = session;
   69       }
   70   
   71       public String getCipherSuite() throws IOException {
   72           // Look up the current SSLSession
   73           if (session == null)
   74               return null;
   75           return session.getCipherSuite();
   76       }
   77   
   78       public Object[] getPeerCertificateChain() 
   79           throws IOException {
   80           return getPeerCertificateChain(false);
   81       }
   82   
   83       protected java.security.cert.X509Certificate [] getX509Certificates(SSLSession session) 
   84           throws IOException {
   85           Certificate [] certs=null;
   86           try {
   87               certs = session.getPeerCertificates();
   88           } catch( Throwable t ) {
   89               log.debug("Error getting client certs",t);
   90               return null;
   91           }
   92           if( certs==null ) return null;
   93           
   94           java.security.cert.X509Certificate [] x509Certs = 
   95               new java.security.cert.X509Certificate[certs.length];
   96           for(int i=0; i < certs.length; i++) {
   97               if (certs[i] instanceof java.security.cert.X509Certificate ) {
   98                   // always currently true with the JSSE 1.1.x
   99                   x509Certs[i] = (java.security.cert.X509Certificate) certs[i];
  100               } else {
  101                   try {
  102                       byte [] buffer = certs[i].getEncoded();
  103                       CertificateFactory cf =
  104                           CertificateFactory.getInstance("X.509");
  105                       ByteArrayInputStream stream =
  106                           new ByteArrayInputStream(buffer);
  107                       x509Certs[i] = (java.security.cert.X509Certificate) cf.generateCertificate(stream);
  108                   } catch(Exception ex) { 
  109                       log.info("Error translating cert " + certs[i], ex);
  110                       return null;
  111                   }
  112               }
  113               if(log.isTraceEnabled())
  114                   log.trace("Cert #" + i + " = " + x509Certs[i]);
  115           }
  116           if(x509Certs.length < 1)
  117               return null;
  118           return x509Certs;
  119       }
  120   
  121       public Object[] getPeerCertificateChain(boolean force)
  122           throws IOException {
  123           // Look up the current SSLSession
  124           if (session == null)
  125               return null;
  126   
  127           // Convert JSSE's certificate format to the ones we need
  128   	X509Certificate [] jsseCerts = null;
  129   	try {
  130   	    jsseCerts = session.getPeerCertificateChain();
  131   	} catch(Exception bex) {
  132   	    // ignore.
  133   	}
  134   	if (jsseCerts == null)
  135   	    jsseCerts = new X509Certificate[0];
  136   	if(jsseCerts.length <= 0 && force) {
  137   	    session.invalidate();
  138   	    handShake();
  139   	    session = ssl.getSession();
  140   	}
  141           return getX509Certificates(session);
  142       }
  143   
  144       protected void handShake() throws IOException {
  145           if( ssl.getWantClientAuth() ) {
  146               log.debug("No client cert sent for want");
  147           } else {
  148               ssl.setNeedClientAuth(true);
  149           }
  150   
  151           InputStream in = ssl.getInputStream();
  152           int oldTimeout = ssl.getSoTimeout();
  153           ssl.setSoTimeout(1000);
  154           byte[] b = new byte[0];
  155           listener.reset();
  156           ssl.startHandshake();
  157           int maxTries = 60; // 60 * 1000 = example 1 minute time out
  158           for (int i = 0; i < maxTries; i++) {
  159           if(log.isTraceEnabled())
  160               log.trace("Reading for try #" +i);
  161               try {
  162                   int x = in.read(b);
  163               } catch(SSLException sslex) {
  164                   log.info("SSL Error getting client Certs",sslex);
  165                   throw sslex;
  166               } catch (IOException e) {
  167                   // ignore - presumably the timeout
  168               }
  169               if (listener.completed) {
  170                   break;
  171               }
  172           }
  173           ssl.setSoTimeout(oldTimeout);
  174           if (listener.completed == false) {
  175               throw new SocketException("SSL Cert handshake timeout");
  176           }
  177   
  178       }
  179   
  180       /**
  181        * Copied from <code>org.apache.catalina.valves.CertificateValve</code>
  182        */
  183       public Integer getKeySize() 
  184           throws IOException {
  185           // Look up the current SSLSession
  186           SSLSupport.CipherData c_aux[]=ciphers;
  187           if (session == null)
  188               return null;
  189           Integer keySize = (Integer) session.getValue(KEY_SIZE_KEY);
  190           if (keySize == null) {
  191               int size = 0;
  192               String cipherSuite = session.getCipherSuite();
  193               for (int i = 0; i < c_aux.length; i++) {
  194                   if (cipherSuite.indexOf(c_aux[i].phrase) >= 0) {
  195                       size = c_aux[i].keySize;
  196                       break;
  197                   }
  198               }
  199               keySize = new Integer(size);
  200               session.putValue(KEY_SIZE_KEY, keySize);
  201           }
  202           return keySize;
  203       }
  204   
  205       public String getSessionId()
  206           throws IOException {
  207           // Look up the current SSLSession
  208           if (session == null)
  209               return null;
  210           // Expose ssl_session (getId)
  211           byte [] ssl_session = session.getId();
  212           if ( ssl_session == null) 
  213               return null;
  214           StringBuffer buf=new StringBuffer("");
  215           for(int x=0; x<ssl_session.length; x++) {
  216               String digit=Integer.toHexString((int)ssl_session[x]);
  217               if (digit.length()<2) buf.append('0');
  218               if (digit.length()>2) digit=digit.substring(digit.length()-2);
  219               buf.append(digit);
  220           }
  221           return buf.toString();
  222       }
  223   
  224   
  225       private static class Listener implements HandshakeCompletedListener {
  226           volatile boolean completed = false;
  227           public void handshakeCompleted(HandshakeCompletedEvent event) {
  228               completed = true;
  229           }
  230           void reset() {
  231               completed = false;
  232           }
  233       }
  234   
  235   }
  236   

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » tomcat » util » net » jsse » [javadoc | source]