View Javadoc

    1   // ========================================================================
    2   // Copyright 2000-2005 Mort Bay Consulting Pty. Ltd.
    3   // ------------------------------------------------------------------------
    4   // Licensed under the Apache License, Version 2.0 (the "License");
    5   // you may not use this file except in compliance with the License.
    6   // You may obtain a copy of the License at
    7   // http://www.apache.org/licenses/LICENSE-2.0
    8   // Unless required by applicable law or agreed to in writing, software
    9   // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  // ========================================================================
    14
    15  package org.mortbay.jetty.security;
    16
    17  import java.io.ByteArrayInputStream;
    18  import java.io.File;
    19  import java.io.IOException;
    20  import java.io.InputStream;
    21  import java.net.InetAddress;
    22  import java.net.ServerSocket;
    23  import java.net.Socket;
    24  import java.net.SocketAddress;
    25  import java.security.KeyStore;
    26  import java.security.SecureRandom;
    27  import java.security.Security;
    28  import java.security.cert.X509Certificate;
    29  import java.util.ArrayList;
    30  import java.util.Arrays;
    31  import java.util.Iterator;
    32  import java.util.List;
    33
    34  import javax.net.ssl.HandshakeCompletedEvent;
    35  import javax.net.ssl.HandshakeCompletedListener;
    36  import javax.net.ssl.KeyManager;
    37  import javax.net.ssl.KeyManagerFactory;
    38  import javax.net.ssl.SSLContext;
    39  import javax.net.ssl.SSLException;
    40  import javax.net.ssl.SSLPeerUnverifiedException;
    41  import javax.net.ssl.SSLServerSocket;
    42  import javax.net.ssl.SSLServerSocketFactory;
    43  import javax.net.ssl.SSLSession;
    44  import javax.net.ssl.SSLSocket;
    45  import javax.net.ssl.TrustManager;
    46  import javax.net.ssl.TrustManagerFactory;
    47
    48  import org.mortbay.io.EndPoint;
    49  import org.mortbay.io.bio.SocketEndPoint;
    50  import org.mortbay.jetty.HttpSchemes;
    51  import org.mortbay.jetty.Request;
    52  import org.mortbay.jetty.bio.SocketConnector;
    53  import org.mortbay.log.Log;
    54  import org.mortbay.resource.Resource;
    55
    56  /* ------------------------------------------------------------ */
    57  /**
    58   * JSSE Socket Listener.
    59   *
    60   * This specialization of HttpListener is an abstract listener that can be used as the basis for a
    61   * specific JSSE listener.
    62   *
    63   * This is heavily based on the work from Court Demas, which in turn is based on the work from Forge
    64   * Research.
    65   *
    66   * @author Greg Wilkins (gregw@mortbay.com)
    67   * @author Court Demas (court@kiwiconsulting.com)
    68   * @author Forge Research Pty Ltd ACN 003 491 576
    69   * @author Jan Hlavat�
    70   */
    71  public class SslSocketConnector extends SocketConnector
    72  {
    73      /**
    74       * The name of the SSLSession attribute that will contain any cached information.
    75       */
    76      static final String CACHED_INFO_ATTR = CachedInfo.class.getName();
    77
    78      /** Default value for the keystore location path. */
    79      public static final String DEFAULT_KEYSTORE = System.getProperty("user.home") + File.separator
    80              + ".keystore";
    81
    82      /** String name of key password property. */
    83      public static final String KEYPASSWORD_PROPERTY = "jetty.ssl.keypassword";
    84
    85      /** String name of keystore password property. */
    86      public static final String PASSWORD_PROPERTY = "jetty.ssl.password";
    87
    88      /**
    89       * Return the chain of X509 certificates used to negotiate the SSL Session.
    90       * <p>
    91       * Note: in order to do this we must convert a javax.security.cert.X509Certificate[], as used by
    92       * JSSE to a java.security.cert.X509Certificate[],as required by the Servlet specs.
    93       *
    94       * @param sslSession the javax.net.ssl.SSLSession to use as the source of the cert chain.
    95       * @return the chain of java.security.cert.X509Certificates used to negotiate the SSL
    96       *         connection. <br>
    97       *         Will be null if the chain is missing or empty.
    98       */
    99      private static X509Certificate[] getCertChain(SSLSession sslSession)
    100     {
    101         try
    102         {
    103             javax.security.cert.X509Certificate javaxCerts[] = sslSession.getPeerCertificateChain();
    104             if (javaxCerts == null || javaxCerts.length == 0)
    105                 return null;
    106
    107             int length = javaxCerts.length;
    108             X509Certificate[] javaCerts = new X509Certificate[length];
    109
    110             java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory.getInstance("X.509");
    111             for (int i = 0; i < length; i++)
    112             {
    113                 byte bytes[] = javaxCerts[i].getEncoded();
    114                 ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
    115                 javaCerts[i] = (X509Certificate) cf.generateCertificate(stream);
    116             }
    117
    118             return javaCerts;
    119         }
    120         catch (SSLPeerUnverifiedException pue)
    121         {
    122             return null;
    123         }
    124         catch (Exception e)
    125         {
    126             Log.warn(Log.EXCEPTION, e);
    127             return null;
    128         }
    129     }
    130
    131
    132     /** Default value for the cipher Suites. */
    133     private String _excludeCipherSuites[] = null;
    134
    135     /** Default value for the keystore location path. */
    136     private String _keystore=DEFAULT_KEYSTORE ;
    137     private String _keystoreType = "JKS"; // type of the key store
    138
    139     /** Set to true if we require client certificate authentication. */
    140     private boolean _needClientAuth = false;
    141     private transient Password _password;
    142     private transient Password _keyPassword;
    143     private transient Password _trustPassword;
    144     private String _protocol= "TLS";
    145     private String _provider;
    146     private String _secureRandomAlgorithm; // cert algorithm
    147     private String _sslKeyManagerFactoryAlgorithm = (Security.getProperty("ssl.KeyManagerFactory.algorithm")==null?"SunX509":Security.getProperty("ssl.KeyManagerFactory.algorithm")); // cert algorithm
    148     private String _sslTrustManagerFactoryAlgorithm = (Security.getProperty("ssl.TrustManagerFactory.algorithm")==null?"SunX509":Security.getProperty("ssl.TrustManagerFactory.algorithm")); // cert algorithm
    149
    150     private String _truststore;
    151     private String _truststoreType = "JKS"; // type of the key store
    152
    153     /** Set to true if we would like client certificate authentication. */
    154     private boolean _wantClientAuth = false;
    155     private int _handshakeTimeout = 0; //0 means use maxIdleTime
    156
    157     private boolean _allowRenegotiate =false;
    158
    159     /* ------------------------------------------------------------ */
    160     /**
    161      * Constructor.
    162      */
    163     public SslSocketConnector()
    164     {
    165         super();
    166     }
    167
    168
    169     /* ------------------------------------------------------------ */
    170     /**
    171      * @return True if SSL re-negotiation is allowed (default false)
    172      */
    173     public boolean isAllowRenegotiate()
    174     {
    175         return _allowRenegotiate;
    176     }
    177
    178     /* ------------------------------------------------------------ */
    179     /**
    180      * Set if SSL re-negotiation is allowed. CVE-2009-3555 discovered
    181      * a vulnerability in SSL/TLS with re-negotiation.  If your JVM
    182      * does not have CVE-2009-3555 fixed, then re-negotiation should
    183      * not be allowed.
    184      * @param allowRenegotiate true if re-negotiation is allowed (default false)
    185      */
    186     public void setAllowRenegotiate(boolean allowRenegotiate)
    187     {
    188         _allowRenegotiate = allowRenegotiate;
    189     }
    190
    191     /* ------------------------------------------------------------ */
    192     public void accept(int acceptorID)
    193         throws IOException, InterruptedException
    194     {
    195         try
    196         {
    197             Socket socket = _serverSocket.accept();
    198             configure(socket);
    199
    200             Connection connection=new SslConnection(socket);
    201             connection.dispatch();
    202         }
    203         catch(SSLException e)
    204         {
    205             Log.warn(e);
    206             try
    207             {
    208                 stop();
    209             }
    210             catch(Exception e2)
    211             {
    212                 Log.warn(e2);
    213                 throw new IllegalStateException(e2.getMessage());
    214             }
    215         }
    216     }
    217
    218     /* ------------------------------------------------------------ */
    219     protected void configure(Socket socket)
    220         throws IOException
    221     {
    222         super.configure(socket);
    223     }
    224
    225     /* ------------------------------------------------------------ */
    226     protected SSLServerSocketFactory createFactory()
    227         throws Exception
    228     {
    229         if (_truststore==null)
    230         {
    231             _truststore=_keystore;
    232             _truststoreType=_keystoreType;
    233         }
    234
    235         KeyManager[] keyManagers = null;
    236         InputStream keystoreInputStream = null;
    237         KeyStore keyStore = null;
    238         try
    239         {
    240 			if (_keystore != null)
    241 			{
    242 				keystoreInputStream = Resource.newResource(_keystore).getInputStream();
    243 			}
    244
    245 			keyStore = KeyStore.getInstance(_keystoreType);
    246 			keyStore.load(keystoreInputStream, _password == null ? null : _password.toString().toCharArray());
    247 		}
    248         finally
    249 		{
    250 			if (keystoreInputStream != null)
    251 			{
    252 				keystoreInputStream.close();
    253 			}
    254 		}
    255
    256         KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(_sslKeyManagerFactoryAlgorithm);
    257         keyManagerFactory.init(keyStore,_keyPassword==null?null:_keyPassword.toString().toCharArray());
    258         keyManagers = keyManagerFactory.getKeyManagers();
    259
    260         TrustManager[] trustManagers = null;
    261         InputStream truststoreInputStream = null;
    262         KeyStore trustStore = null;
    263
    264 		try
    265 		{
    266 			if (_truststore != null)
    267 			{
    268 				truststoreInputStream = Resource.newResource(_truststore).getInputStream();
    269 			}
    270 			trustStore = KeyStore.getInstance(_truststoreType);
    271 			trustStore.load(truststoreInputStream, _trustPassword == null ? null : _trustPassword.toString().toCharArray());
    272 		}
    273 		finally
    274 		{
    275 			if (truststoreInputStream != null)
    276 			{
    277 				truststoreInputStream.close();
    278 			}
    279 		}
    280
    281         TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_sslTrustManagerFactoryAlgorithm);
    282         trustManagerFactory.init(trustStore);
    283         trustManagers = trustManagerFactory.getTrustManagers();
    284
    285
    286         SecureRandom secureRandom = _secureRandomAlgorithm==null?null:SecureRandom.getInstance(_secureRandomAlgorithm);
    287
    288         SSLContext context = _provider==null?SSLContext.getInstance(_protocol):SSLContext.getInstance(_protocol, _provider);
    289
    290         context.init(keyManagers, trustManagers, secureRandom);
    291
    292         return context.getServerSocketFactory();
    293     }
    294
    295     /* ------------------------------------------------------------ */
    296     /**
    297      * Allow the Listener a chance to customise the request. before the server does its stuff. <br>
    298      * This allows the required attributes to be set for SSL requests. <br>
    299      * The requirements of the Servlet specs are:
    300      * <ul>
    301      * <li> an attribute named "javax.servlet.request.cipher_suite" of type String.</li>
    302      * <li> an attribute named "javax.servlet.request.key_size" of type Integer.</li>
    303      * <li> an attribute named "javax.servlet.request.X509Certificate" of type
    304      * java.security.cert.X509Certificate[]. This is an array of objects of type X509Certificate,
    305      * the order of this array is defined as being in ascending order of trust. The first
    306      * certificate in the chain is the one set by the client, the next is the one used to
    307      * authenticate the first, and so on. </li>
    308      * </ul>
    309      *
    310      * @param endpoint The Socket the request arrived on.
    311      *        This should be a {@link SocketEndPoint} wrapping a {@link SSLSocket}.
    312      * @param request HttpRequest to be customised.
    313      */
    314     public void customize(EndPoint endpoint, Request request)
    315         throws IOException
    316     {
    317         super.customize(endpoint, request);
    318         request.setScheme(HttpSchemes.HTTPS);
    319
    320         SocketEndPoint socket_end_point = (SocketEndPoint)endpoint;
    321         SSLSocket sslSocket = (SSLSocket)socket_end_point.getTransport();
    322
    323         try
    324         {
    325             SSLSession sslSession = sslSocket.getSession();
    326             String cipherSuite = sslSession.getCipherSuite();
    327             Integer keySize;
    328             X509Certificate[] certs;
    329
    330             CachedInfo cachedInfo = (CachedInfo) sslSession.getValue(CACHED_INFO_ATTR);
    331             if (cachedInfo != null)
    332             {
    333                 keySize = cachedInfo.getKeySize();
    334                 certs = cachedInfo.getCerts();
    335             }
    336             else
    337             {
    338                 keySize = new Integer(ServletSSL.deduceKeyLength(cipherSuite));
    339                 certs = getCertChain(sslSession);
    340                 cachedInfo = new CachedInfo(keySize, certs);
    341                 sslSession.putValue(CACHED_INFO_ATTR, cachedInfo);
    342             }
    343
    344             if (certs != null)
    345                 request.setAttribute("javax.servlet.request.X509Certificate", certs);
    346             else if (_needClientAuth) // Sanity check
    347                 throw new IllegalStateException("no client auth");
    348
    349             request.setAttribute("javax.servlet.request.cipher_suite", cipherSuite);
    350             request.setAttribute("javax.servlet.request.key_size", keySize);
    351         }
    352         catch (Exception e)
    353         {
    354             Log.warn(Log.EXCEPTION, e);
    355         }
    356     }
    357
    358     /* ------------------------------------------------------------ */
    359     public String[] getExcludeCipherSuites() {
    360         return _excludeCipherSuites;
    361     }
    362
    363     /* ------------------------------------------------------------ */
    364     public String getKeystore()
    365     {
    366         return _keystore;
    367     }
    368
    369     /* ------------------------------------------------------------ */
    370     public String getKeystoreType()
    371     {
    372         return (_keystoreType);
    373     }
    374
    375     /* ------------------------------------------------------------ */
    376     public boolean getNeedClientAuth()
    377     {
    378         return _needClientAuth;
    379     }
    380
    381     /* ------------------------------------------------------------ */
    382     public String getProtocol()
    383     {
    384         return _protocol;
    385     }
    386
    387     /* ------------------------------------------------------------ */
    388     public String getProvider() {
    389 	return _provider;
    390     }
    391
    392     /* ------------------------------------------------------------ */
    393     public String getSecureRandomAlgorithm()
    394     {
    395         return (this._secureRandomAlgorithm);
    396     }
    397
    398     /* ------------------------------------------------------------ */
    399     public String getSslKeyManagerFactoryAlgorithm()
    400     {
    401         return (this._sslKeyManagerFactoryAlgorithm);
    402     }
    403
    404     /* ------------------------------------------------------------ */
    405     public String getSslTrustManagerFactoryAlgorithm()
    406     {
    407         return (this._sslTrustManagerFactoryAlgorithm);
    408     }
    409
    410     /* ------------------------------------------------------------ */
    411     public String getTruststore()
    412     {
    413         return _truststore;
    414     }
    415
    416     /* ------------------------------------------------------------ */
    417     public String getTruststoreType()
    418     {
    419         return _truststoreType;
    420     }
    421
    422     /* ------------------------------------------------------------ */
    423     public boolean getWantClientAuth()
    424     {
    425         return _wantClientAuth;
    426     }
    427
    428     /* ------------------------------------------------------------ */
    429     /**
    430      * By default, we're confidential, given we speak SSL. But, if we've been told about an
    431      * confidential port, and said port is not our port, then we're not. This allows separation of
    432      * listeners providing INTEGRAL versus CONFIDENTIAL constraints, such as one SSL listener
    433      * configured to require client certs providing CONFIDENTIAL, whereas another SSL listener not
    434      * requiring client certs providing mere INTEGRAL constraints.
    435      */
    436     public boolean isConfidential(Request request)
    437     {
    438         final int confidentialPort = getConfidentialPort();
    439         return confidentialPort == 0 || confidentialPort == request.getServerPort();
    440     }
    441
    442     /* ------------------------------------------------------------ */
    443     /**
    444      * By default, we're integral, given we speak SSL. But, if we've been told about an integral
    445      * port, and said port is not our port, then we're not. This allows separation of listeners
    446      * providing INTEGRAL versus CONFIDENTIAL constraints, such as one SSL listener configured to
    447      * require client certs providing CONFIDENTIAL, whereas another SSL listener not requiring
    448      * client certs providing mere INTEGRAL constraints.
    449      */
    450     public boolean isIntegral(Request request)
    451     {
    452         final int integralPort = getIntegralPort();
    453         return integralPort == 0 || integralPort == request.getServerPort();
    454     }
    455
    456     /* ------------------------------------------------------------ */
    457     /**
    458      * @param addr The {@link SocketAddress address} that this server should listen on
    459      * @param backlog See {@link ServerSocket#bind(java.net.SocketAddress, int)}
    460      * @return A new {@link ServerSocket socket object} bound to the supplied address with all other
    461      * settings as per the current configuration of this connector.
    462      * @see #setWantClientAuth
    463      * @see #setNeedClientAuth
    464      * @see #setCipherSuites
    465      * @exception IOException
    466      */
    467
    468     /* ------------------------------------------------------------ */
    469     protected ServerSocket newServerSocket(String host, int port,int backlog) throws IOException
    470     {
    471         SSLServerSocketFactory factory = null;
    472         SSLServerSocket socket = null;
    473
    474         try
    475         {
    476             factory = createFactory();
    477
    478             socket = (SSLServerSocket) (host==null?
    479                             factory.createServerSocket(port,backlog):
    480                             factory.createServerSocket(port,backlog,InetAddress.getByName(host)));
    481
    482             if (_wantClientAuth)
    483                 socket.setWantClientAuth(_wantClientAuth);
    484             if (_needClientAuth)
    485                 socket.setNeedClientAuth(_needClientAuth);
    486
    487             if (_excludeCipherSuites != null && _excludeCipherSuites.length >0)
    488             {
    489                 List excludedCSList = Arrays.asList(_excludeCipherSuites);
    490                 String[] enabledCipherSuites = socket.getEnabledCipherSuites();
    491             	List enabledCSList = new ArrayList(Arrays.asList(enabledCipherSuites));
    492             	Iterator exIter = excludedCSList.iterator();
    493
    494                 while (exIter.hasNext())
    495             	{
    496             	    String cipherName = (String)exIter.next();
    497                     if (enabledCSList.contains(cipherName))
    498                     {
    499                         enabledCSList.remove(cipherName);
    500                     }
    501             	}
    502                 enabledCipherSuites = (String[])enabledCSList.toArray(new String[enabledCSList.size()]);
    503
    504                 socket.setEnabledCipherSuites(enabledCipherSuites);
    505             }
    506
    507         }
    508         catch (IOException e)
    509         {
    510             throw e;
    511         }
    512         catch (Exception e)
    513         {
    514             Log.warn(e.toString());
    515             Log.debug(e);
    516             throw new IOException("!JsseListener: " + e);
    517         }
    518         return socket;
    519     }
    520
    521     /* ------------------------------------------------------------ */
    522     /**
    523      * @author Tony Jiang
    524      */
    525     public void setExcludeCipherSuites(String[] cipherSuites) {
    526         this._excludeCipherSuites = cipherSuites;
    527     }
    528
    529     /* ------------------------------------------------------------ */
    530     public void setKeyPassword(String password)
    531     {
    532         _keyPassword = Password.getPassword(KEYPASSWORD_PROPERTY,password,null);
    533     }
    534
    535     /* ------------------------------------------------------------ */
    536     /**
    537      * @param keystore The resource path to the keystore, or null for built in keystores.
    538      */
    539     public void setKeystore(String keystore)
    540     {
    541         _keystore = keystore;
    542     }
    543
    544     /* ------------------------------------------------------------ */
    545     public void setKeystoreType(String keystoreType)
    546     {
    547         _keystoreType = keystoreType;
    548     }
    549
    550     /* ------------------------------------------------------------ */
    551     /**
    552      * Set the value of the needClientAuth property
    553      *
    554      * @param needClientAuth true iff we require client certificate authentication.
    555      */
    556     public void setNeedClientAuth(boolean needClientAuth)
    557     {
    558         _needClientAuth = needClientAuth;
    559     }
    560
    561     /* ------------------------------------------------------------ */
    562     public void setPassword(String password)
    563     {
    564         _password = Password.getPassword(PASSWORD_PROPERTY,password,null);
    565     }
    566
    567     /* ------------------------------------------------------------ */
    568     public void setTrustPassword(String password)
    569     {
    570         _trustPassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
    571     }
    572
    573     /* ------------------------------------------------------------ */
    574     public void setProtocol(String protocol)
    575     {
    576         _protocol = protocol;
    577     }
    578
    579     /* ------------------------------------------------------------ */
    580     public void setProvider(String _provider) {
    581 	this._provider = _provider;
    582     }
    583
    584     /* ------------------------------------------------------------ */
    585     public void setSecureRandomAlgorithm(String algorithm)
    586     {
    587         this._secureRandomAlgorithm = algorithm;
    588     }
    589
    590     /* ------------------------------------------------------------ */
    591     public void setSslKeyManagerFactoryAlgorithm(String algorithm)
    592     {
    593         this._sslKeyManagerFactoryAlgorithm = algorithm;
    594     }
    595
    596     /* ------------------------------------------------------------ */
    597     public void setSslTrustManagerFactoryAlgorithm(String algorithm)
    598     {
    599         this._sslTrustManagerFactoryAlgorithm = algorithm;
    600     }
    601
    602
    603     public void setTruststore(String truststore)
    604     {
    605         _truststore = truststore;
    606     }
    607
    608
    609     public void setTruststoreType(String truststoreType)
    610     {
    611         _truststoreType = truststoreType;
    612     }
    613
    614     /* ------------------------------------------------------------ */
    615     /**
    616      * Set the value of the _wantClientAuth property. This property is used when
    617      * {@link #newServerSocket(SocketAddress, int) opening server sockets}.
    618      *
    619      * @param wantClientAuth true iff we want client certificate authentication.
    620      * @see SSLServerSocket#setWantClientAuth
    621      */
    622     public void setWantClientAuth(boolean wantClientAuth)
    623     {
    624         _wantClientAuth = wantClientAuth;
    625     }
    626
    627     /**
    628      * Set the time in milliseconds for so_timeout during ssl handshaking
    629      * @param msec a non-zero value will be used to set so_timeout during
    630      * ssl handshakes. A zero value means the maxIdleTime is used instead.
    631      */
    632     public void setHandshakeTimeout (int msec)
    633     {
    634         _handshakeTimeout = msec;
    635     }
    636
    637
    638     public int getHandshakeTimeout ()
    639     {
    640         return _handshakeTimeout;
    641     }
    642     /**
    643      * Simple bundle of information that is cached in the SSLSession. Stores the effective keySize
    644      * and the client certificate chain.
    645      */
    646     private class CachedInfo
    647     {
    648         private X509Certificate[] _certs;
    649         private Integer _keySize;
    650
    651         CachedInfo(Integer keySize, X509Certificate[] certs)
    652         {
    653             this._keySize = keySize;
    654             this._certs = certs;
    655         }
    656
    657         X509Certificate[] getCerts()
    658         {
    659             return _certs;
    660         }
    661
    662         Integer getKeySize()
    663         {
    664             return _keySize;
    665         }
    666     }
    667
    668
    669     public class SslConnection extends Connection
    670     {
    671         public SslConnection(Socket socket) throws IOException
    672         {
    673             super(socket);
    674         }
    675
    676         public void shutdownOutput() throws IOException
    677         {
    678 			close();
    679 		}
    680
    681 		public void run()
    682         {
    683             try
    684             {
    685                 int handshakeTimeout = getHandshakeTimeout();
    686                 int oldTimeout = _socket.getSoTimeout();
    687                 if (handshakeTimeout > 0)
    688                     _socket.setSoTimeout(handshakeTimeout);
    689
    690                 final SSLSocket ssl=(SSLSocket)_socket;
    691                 ssl.addHandshakeCompletedListener(new HandshakeCompletedListener()
    692                 {
    693                     boolean handshook=false;
    694                     public void handshakeCompleted(HandshakeCompletedEvent event)
    695                     {
    696                         if (handshook)
    697                         {
    698                             if (!_allowRenegotiate)
    699                             {
    700                                 Log.warn("SSL renegotiate denied: "+ssl);
    701                                 try{ssl.close();}catch(IOException e){Log.warn(e);}
    702                             }
    703                         }
    704                         else
    705                             handshook=true;
    706                     }
    707                 });
    708                 ssl.startHandshake();
    709
    710                 if (handshakeTimeout>0)
    711                     _socket.setSoTimeout(oldTimeout);
    712
    713                 super.run();
    714             }
    715             catch (SSLException e)
    716             {
    717                 Log.warn(e);
    718                 try{close();}
    719                 catch(IOException e2){Log.ignore(e2);}
    720             }
    721             catch (IOException e)
    722             {
    723                 Log.debug(e);
    724                 try{close();}
    725                 catch(IOException e2){Log.ignore(e2);}
    726             }
    727         }
    728     }
    729
    730 }