michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: package org.mozilla.gecko.sync.net; michael@0: michael@0: import java.io.IOException; michael@0: import java.net.Socket; michael@0: michael@0: import javax.net.ssl.SSLContext; michael@0: import javax.net.ssl.SSLSocket; michael@0: michael@0: import org.mozilla.gecko.background.common.log.Logger; michael@0: michael@0: import ch.boye.httpclientandroidlib.conn.ssl.SSLSocketFactory; michael@0: import ch.boye.httpclientandroidlib.params.HttpParams; michael@0: michael@0: public class TLSSocketFactory extends SSLSocketFactory { michael@0: private static final String LOG_TAG = "TLSSocketFactory"; michael@0: private static final String[] DEFAULT_CIPHER_SUITES = new String[] { michael@0: "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", michael@0: "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", michael@0: "SSL_RSA_WITH_RC4_128_SHA", // "RC4_SHA" michael@0: }; michael@0: private static final String[] DEFAULT_PROTOCOLS = new String[] { michael@0: "SSLv3", michael@0: "TLSv1" michael@0: }; michael@0: michael@0: // Guarded by `this`. michael@0: private static String[] cipherSuites = DEFAULT_CIPHER_SUITES; michael@0: michael@0: public TLSSocketFactory(SSLContext sslContext) { michael@0: super(sslContext); michael@0: } michael@0: michael@0: /** michael@0: * Attempt to specify the cipher suites to use for a connection. If michael@0: * setting fails (as it will on Android 2.2, because the wrong names michael@0: * are in use to specify ciphers), attempt to set the defaults. michael@0: * michael@0: * We store the list of cipher suites in `cipherSuites`, which michael@0: * avoids this fallback handling having to be executed more than once. michael@0: * michael@0: * This method is synchronized to ensure correct use of that member. michael@0: * michael@0: * See Bug 717691 for more details. michael@0: * michael@0: * @param socket michael@0: * The SSLSocket on which to operate. michael@0: */ michael@0: public static synchronized void setEnabledCipherSuites(SSLSocket socket) { michael@0: try { michael@0: socket.setEnabledCipherSuites(cipherSuites); michael@0: } catch (IllegalArgumentException e) { michael@0: cipherSuites = socket.getSupportedCipherSuites(); michael@0: Logger.warn(LOG_TAG, "Setting enabled cipher suites failed: " + e.getMessage()); michael@0: Logger.warn(LOG_TAG, "Using " + cipherSuites.length + " supported suites."); michael@0: socket.setEnabledCipherSuites(cipherSuites); michael@0: } michael@0: } michael@0: michael@0: @Override michael@0: public Socket createSocket(HttpParams params) throws IOException { michael@0: SSLSocket socket = (SSLSocket) super.createSocket(params); michael@0: socket.setEnabledProtocols(DEFAULT_PROTOCOLS); michael@0: setEnabledCipherSuites(socket); michael@0: return socket; michael@0: } michael@0: }