112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo/*
212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/ssl/SSLSocketFactory.java $
312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * $Revision: 659194 $
412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * $Date: 2008-05-22 11:33:47 -0700 (Thu, 22 May 2008) $
512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *
612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * ====================================================================
712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * Licensed to the Apache Software Foundation (ASF) under one
812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * or more contributor license agreements.  See the NOTICE file
912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * distributed with this work for additional information
1012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * regarding copyright ownership.  The ASF licenses this file
1112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * to you under the Apache License, Version 2.0 (the
1212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * "License"); you may not use this file except in compliance
1312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * with the License.  You may obtain a copy of the License at
1412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *
1512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *   http://www.apache.org/licenses/LICENSE-2.0
1612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *
1712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * Unless required by applicable law or agreed to in writing,
1812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * software distributed under the License is distributed on an
1912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
2012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * KIND, either express or implied.  See the License for the
2112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * specific language governing permissions and limitations
2212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * under the License.
2312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * ====================================================================
2412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *
2512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * This software consists of voluntary contributions made by many
2612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * individuals on behalf of the Apache Software Foundation.  For more
2712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * information on the Apache Software Foundation, please see
2812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * <http://www.apache.org/>.
2912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *
3012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * This class was copied from org.apache.http.conn.ssl, because it didn't have a suitable
3112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * constructor.
3212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo */
3312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
3412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalopackage com.android.emailcommon.utility;
3512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
3612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport org.apache.http.conn.scheme.HostNameResolver;
3712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport org.apache.http.conn.scheme.LayeredSocketFactory;
3812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport org.apache.http.conn.ssl.AllowAllHostnameVerifier;
3912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
4012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport org.apache.http.conn.ssl.StrictHostnameVerifier;
4112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport org.apache.http.conn.ssl.X509HostnameVerifier;
4212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport org.apache.http.params.HttpConnectionParams;
4312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport org.apache.http.params.HttpParams;
4412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
4512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport javax.net.ssl.HttpsURLConnection;
4612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport javax.net.ssl.KeyManager;
4712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport javax.net.ssl.KeyManagerFactory;
4812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport javax.net.ssl.SSLContext;
4912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport javax.net.ssl.SSLSocket;
5012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport javax.net.ssl.TrustManager;
5112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport javax.net.ssl.TrustManagerFactory;
5212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport java.io.IOException;
5312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport java.net.InetAddress;
5412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport java.net.InetSocketAddress;
5512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport java.net.Socket;
5612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport java.net.UnknownHostException;
5712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport java.security.KeyManagementException;
5812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport java.security.KeyStore;
5912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport java.security.KeyStoreException;
6012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport java.security.NoSuchAlgorithmException;
6112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport java.security.SecureRandom;
6212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komaloimport java.security.UnrecoverableKeyException;
6312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
6412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo/**
6512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * Layered socket factory for TLS/SSL connections, based on JSSE.
6612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *.
6712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * <p>
6812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * SSLSocketFactory can be used to validate the identity of the HTTPS
6912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * server against a list of trusted certificates and to authenticate to
7012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * the HTTPS server using a private key.
7112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * </p>
7212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *
7312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * <p>
7412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * SSLSocketFactory will enable server authentication when supplied with
7512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * a {@link KeyStore truststore} file containg one or several trusted
7612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * certificates. The client secure socket will reject the connection during
7712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * the SSL session handshake if the target HTTPS server attempts to
7812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * authenticate itself with a non-trusted certificate.
7912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * </p>
8012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *
8112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * <p>
8212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * Use JDK keytool utility to import a trusted certificate and generate a truststore file:
8312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *    <pre>
8412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *     keytool -import -alias "my server cert" -file server.crt -keystore my.truststore
8512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *    </pre>
8612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * </p>
8712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *
8812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * <p>
8912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * SSLSocketFactory will enable client authentication when supplied with
9012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * a {@link KeyStore keystore} file containg a private key/public certificate
9112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * pair. The client secure socket will use the private key to authenticate
9212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * itself to the target HTTPS server during the SSL session handshake if
9312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * requested to do so by the server.
9412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * The target HTTPS server will in its turn verify the certificate presented
9512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * by the client in order to establish client's authenticity
9612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * </p>
9712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *
9812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * <p>
9912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * Use the following sequence of actions to generate a keystore file
10012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * </p>
10112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *   <ul>
10212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *     <li>
10312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      <p>
10412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      Use JDK keytool utility to generate a new key
10512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      <pre>keytool -genkey -v -alias "my client key" -validity 365 -keystore my.keystore</pre>
10612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      For simplicity use the same password for the key as that of the keystore
10712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      </p>
10812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *     </li>
10912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *     <li>
11012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      <p>
11112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      Issue a certificate signing request (CSR)
11212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      <pre>keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore</pre>
11312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *     </p>
11412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *     </li>
11512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *     <li>
11612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      <p>
11712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      Send the certificate request to the trusted Certificate Authority for signature.
11812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      One may choose to act as her own CA and sign the certificate request using a PKI
11912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      tool, such as OpenSSL.
12012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      </p>
12112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *     </li>
12212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *     <li>
12312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      <p>
12412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *       Import the trusted CA root certificate
12512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *       <pre>keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore</pre>
12612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      </p>
12712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *     </li>
12812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *     <li>
12912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      <p>
13012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *       Import the PKCS#7 file containg the complete certificate chain
13112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *       <pre>keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore</pre>
13212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      </p>
13312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *     </li>
13412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *     <li>
13512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      <p>
13612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *       Verify the content the resultant keystore file
13712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *       <pre>keytool -list -v -keystore my.keystore</pre>
13812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *      </p>
13912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *     </li>
14012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo *   </ul>
14112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
14212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo * @author Julius Davies
14312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo */
14412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
14512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalopublic class SSLSocketFactory implements LayeredSocketFactory {
14612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
14712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public static final String TLS   = "TLS";
14812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public static final String SSL   = "SSL";
14912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public static final String SSLV2 = "SSLv2";
15012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
15112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public static final X509HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER
15212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        = new AllowAllHostnameVerifier();
15312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
15412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public static final X509HostnameVerifier BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
15512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        = new BrowserCompatHostnameVerifier();
15612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
15712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public static final X509HostnameVerifier STRICT_HOSTNAME_VERIFIER
15812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        = new StrictHostnameVerifier();
15912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    /**
16012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     * The factory using the default JVM settings for secure connections.
16112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     */
16212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    private static final SSLSocketFactory DEFAULT_FACTORY = new SSLSocketFactory();
16312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
16412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    /**
16512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     * Gets an singleton instance of the SSLProtocolSocketFactory.
16612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     * @return a SSLProtocolSocketFactory
16712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     */
16812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public static SSLSocketFactory getSocketFactory() {
16912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        return DEFAULT_FACTORY;
17012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    }
17112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
17212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    private final SSLContext sslcontext;
17312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    private final javax.net.ssl.SSLSocketFactory socketfactory;
17412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    private final HostNameResolver nameResolver;
17512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    private X509HostnameVerifier hostnameVerifier = BROWSER_COMPATIBLE_HOSTNAME_VERIFIER;
17612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
17712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public SSLSocketFactory(
17812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        String algorithm,
17912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        final KeyStore keystore,
18012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        final String keystorePassword,
18112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        final KeyStore truststore,
18212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        final SecureRandom random,
18312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        final HostNameResolver nameResolver)
18412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException
18512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    {
18612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        super();
18712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        if (algorithm == null) {
18812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            algorithm = TLS;
18912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        }
19012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        KeyManager[] keymanagers = null;
19112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        if (keystore != null) {
19212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            keymanagers = createKeyManagers(keystore, keystorePassword);
19312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        }
19412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        TrustManager[] trustmanagers = null;
19512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        if (truststore != null) {
19612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            trustmanagers = createTrustManagers(truststore);
19712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        }
19812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        sslcontext = SSLContext.getInstance(algorithm);
19912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        sslcontext.init(keymanagers, trustmanagers, random);
20012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        socketfactory = sslcontext.getSocketFactory();
20112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        this.nameResolver = nameResolver;
20212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    }
20312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
20412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public SSLSocketFactory(
20512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            final KeyStore keystore,
20612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            final String keystorePassword,
20712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            final KeyStore truststore)
20812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException
20912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    {
21012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        this(TLS, keystore, keystorePassword, truststore, null, null);
21112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    }
21212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
21312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public SSLSocketFactory(final KeyStore keystore, final String keystorePassword)
21412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException
21512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    {
21612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        this(TLS, keystore, keystorePassword, null, null, null);
21712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    }
21812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
21912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public SSLSocketFactory(final KeyStore truststore)
22012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException
22112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    {
22212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        this(TLS, null, null, truststore, null, null);
22312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    }
22412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
22512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    /**
22612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     * Constructs an HttpClient SSLSocketFactory backed by the given JSSE
22712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     * SSLSocketFactory.
22812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     */
22912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public SSLSocketFactory(javax.net.ssl.SSLSocketFactory socketfactory) {
23012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        super();
23112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        sslcontext = null;
23212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        this.socketfactory = socketfactory;
23312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        nameResolver = null;
23412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    }
23512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
23612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    /**
23712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     * Creates the default SSL socket factory.
23812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     * This constructor is used exclusively to instantiate the factory for
23912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     * {@link #getSocketFactory getSocketFactory}.
24012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     */
24112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    private SSLSocketFactory() {
24212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        super();
24312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        sslcontext = null;
24412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        socketfactory = HttpsURLConnection.getDefaultSSLSocketFactory();
24512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        nameResolver = null;
24612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    }
24712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
24812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    private static KeyManager[] createKeyManagers(final KeyStore keystore, final String password)
24912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
25012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        if (keystore == null) {
25112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            throw new IllegalArgumentException("Keystore may not be null");
25212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        }
25312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(
25412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            KeyManagerFactory.getDefaultAlgorithm());
25512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        kmfactory.init(keystore, password != null ? password.toCharArray(): null);
25612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        return kmfactory.getKeyManagers();
25712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    }
25812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
25912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    private static TrustManager[] createTrustManagers(final KeyStore keystore)
26012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        throws KeyStoreException, NoSuchAlgorithmException {
26112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        if (keystore == null) {
26212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            throw new IllegalArgumentException("Keystore may not be null");
26312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        }
26412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(
26512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            TrustManagerFactory.getDefaultAlgorithm());
26612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        tmfactory.init(keystore);
26712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        return tmfactory.getTrustManagers();
26812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    }
26912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
27012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
27112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    // non-javadoc, see interface org.apache.http.conn.SocketFactory
27212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public Socket createSocket()
27312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        throws IOException {
27412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
27512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        // the cast makes sure that the factory is working as expected
27612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        return socketfactory.createSocket();
27712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    }
27812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
27912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
28012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    // non-javadoc, see interface org.apache.http.conn.SocketFactory
28112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public Socket connectSocket(
28212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        final Socket sock,
28312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        final String host,
28412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        final int port,
28512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        final InetAddress localAddress,
28612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        int localPort,
28712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        final HttpParams params
28812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    ) throws IOException {
28912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
29012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        if (host == null) {
29112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            throw new IllegalArgumentException("Target host may not be null.");
29212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        }
29312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        if (params == null) {
29412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            throw new IllegalArgumentException("Parameters may not be null.");
29512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        }
29612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
29712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        SSLSocket sslsock = (SSLSocket)
29812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            ((sock != null) ? sock : createSocket());
29912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
30012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        if ((localAddress != null) || (localPort > 0)) {
30112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
30212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            // we need to bind explicitly
30312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            if (localPort < 0)
30412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo                localPort = 0; // indicates "any"
30512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
30612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            InetSocketAddress isa =
30712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo                new InetSocketAddress(localAddress, localPort);
30812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            sslsock.bind(isa);
30912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        }
31012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
31112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
31212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        int soTimeout = HttpConnectionParams.getSoTimeout(params);
31312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
31412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        InetSocketAddress remoteAddress;
31512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        if (nameResolver != null) {
31612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            remoteAddress = new InetSocketAddress(nameResolver.resolve(host), port);
31712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        } else {
31812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            remoteAddress = new InetSocketAddress(host, port);
31912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        }
32012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
32112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        sslsock.connect(remoteAddress, connTimeout);
32212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
32312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        sslsock.setSoTimeout(soTimeout);
32412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        try {
32512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            hostnameVerifier.verify(host, sslsock);
32612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            // verifyHostName() didn't blowup - good!
32712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        } catch (IOException iox) {
32812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            // close the socket before re-throwing the exception
32912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            try { sslsock.close(); } catch (Exception x) { /*ignore*/ }
33012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            throw iox;
33112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        }
33212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
33312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        return sslsock;
33412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    }
33512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
33612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
33712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    /**
33812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     * Checks whether a socket connection is secure.
33912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     * This factory creates TLS/SSL socket connections
34012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     * which, by default, are considered secure.
34112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     * <br/>
34212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     * Derived classes may override this method to perform
34312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     * runtime checks, for example based on the cypher suite.
34412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     *
34512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     * @param sock      the connected socket
34612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     *
34712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     * @return  <code>true</code>
34812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     *
34912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     * @throws IllegalArgumentException if the argument is invalid
35012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo     */
35112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public boolean isSecure(Socket sock)
35212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        throws IllegalArgumentException {
35312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
35412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        if (sock == null) {
35512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            throw new IllegalArgumentException("Socket may not be null.");
35612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        }
35712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        // This instanceof check is in line with createSocket() above.
35812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        if (!(sock instanceof SSLSocket)) {
35912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            throw new IllegalArgumentException
36012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo                ("Socket not created by this factory.");
36112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        }
36212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        // This check is performed last since it calls the argument object.
36312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        if (sock.isClosed()) {
36412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            throw new IllegalArgumentException("Socket is closed.");
36512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        }
36612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
36712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        return true;
36812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
36912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    } // isSecure
37012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
37112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
37212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    // non-javadoc, see interface LayeredSocketFactory
37312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public Socket createSocket(
37412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        final Socket socket,
37512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        final String host,
37612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        final int port,
37712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        final boolean autoClose
37812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    ) throws IOException, UnknownHostException {
37912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        SSLSocket sslSocket = (SSLSocket) socketfactory.createSocket(
38012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo              socket,
38112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo              host,
38212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo              port,
38312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo              autoClose
38412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        );
38512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        hostnameVerifier.verify(host, sslSocket);
38612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        // verifyHostName() didn't blowup - good!
38712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        return sslSocket;
38812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    }
38912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
39012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public void setHostnameVerifier(X509HostnameVerifier hostnameVerifier) {
39112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        if ( hostnameVerifier == null ) {
39212a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo            throw new IllegalArgumentException("Hostname verifier may not be null");
39312a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        }
39412a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        this.hostnameVerifier = hostnameVerifier;
39512a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    }
39612a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
39712a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    public X509HostnameVerifier getHostnameVerifier() {
39812a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo        return hostnameVerifier;
39912a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo    }
40012a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo
40112a3e3e4b91ebab1ac4538d9f7a336b9e05dce0eBen Komalo}
402