/** * Attempts to get a new socket connection to the given host within the given time limit. * * <p>To circumvent the limitations of older JREs that do not support connect timeout a controller * thread is executed. The controller thread attempts to create a new socket within the given * limit of time. If socket constructor does not return until the timeout expires, the controller * terminates and throws an {@link ConnectTimeoutException} * * @param host the host name/IP * @param port the port on the host * @param localAddress the local host name/IP to bind the socket to * @param localPort the port on the local machine * @param params {@link HttpConnectionParams Http connection parameters} * @return Socket a new socket * @throws IOException if an I/O error occurs while creating the socket * @throws UnknownHostException if the IP address of the host cannot be determined */ @Override public Socket createSocket( final String host, final int port, final InetAddress localAddress, final int localPort, final HttpConnectionParams params) throws IOException, UnknownHostException, ConnectTimeoutException { if (params == null) { throw new IllegalArgumentException("Parameters may not be null"); } int timeout = params.getConnectionTimeout(); SocketFactory socketfactory = getSSLContext().getSocketFactory(); if (timeout == 0) { Socket socket = socketfactory.createSocket(host, port, localAddress, localPort); if (socket instanceof SSLSocket) { ((SSLSocket) socket) .setEnabledProtocols( SSLUtils.getSupportedProtocols(((SSLSocket) socket).getEnabledProtocols())); } return socket; } else { Socket socket = socketfactory.createSocket(); if (socket instanceof SSLSocket) { ((SSLSocket) socket) .setEnabledProtocols( SSLUtils.getSupportedProtocols(((SSLSocket) socket).getEnabledProtocols())); } SocketAddress localaddr = new InetSocketAddress(localAddress, localPort); SocketAddress remoteaddr = new InetSocketAddress(host, port); socket.bind(localaddr); socket.connect(remoteaddr, timeout); return socket; } }
@Override public Socket createSocket( final String host, final int port, final InetAddress localAddress, final int localPort, final HttpConnectionParams params) throws IOException, UnknownHostException, ConnectTimeoutException { final int timeout = params.getConnectionTimeout(); if (timeout == 0) { Socket socket = createSocket(host, port, localAddress, localPort); if (socket instanceof SSLSocket) { ((SSLSocket) socket) .setEnabledProtocols( SSLUtils.getSupportedProtocols(((SSLSocket) socket).getEnabledProtocols())); } return socket; } else { final Socket s = ssf.createSocket(); if (s instanceof SSLSocket) { ((SSLSocket) s) .setEnabledProtocols( SSLUtils.getSupportedProtocols(((SSLSocket) s).getEnabledProtocols())); } s.bind(new InetSocketAddress(localAddress, localPort)); s.connect(new InetSocketAddress(host, port), timeout); return s; } }
/** * Configure the TLS connection to use {@code tlsVersion}. We also bundle certain extensions with * certain versions. In particular, we enable Server Name Indication (SNI) and Next Protocol * Negotiation (NPN) with TLSv1 on platforms that support them. */ public void configureTls(SSLSocket socket, String uriHost, String tlsVersion) { // We don't call setEnabledProtocols("TLSv1") on the assumption that that's // the default. TODO: confirm this and support more TLS versions. if (tlsVersion.equals("SSLv3")) { socket.setEnabledProtocols(new String[] {"SSLv3"}); } }
@Override public Socket createSocket(InetAddress inetaddress, int i, InetAddress inetaddress1, int j) throws IOException { SSLSocket result = (SSLSocket) factory.createSocket(inetaddress, i, inetaddress1, j); result.setEnabledProtocols(new String[] {"SSLv3"}); return result; }
@Override public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { SSLCertificateSocketFactory sslSocketFactory = (SSLCertificateSocketFactory) SSLCertificateSocketFactory.getDefault(0); SSLSocket ssl = (SSLSocket) sslSocketFactory.createSocket(InetAddress.getByName(host), port); // enable TLSv1.1/1.2 if available // (see https://github.com/rfc2822/davdroid/issues/229) ssl.setEnabledProtocols(ssl.getSupportedProtocols()); // set up SNI before the handshake if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { Log.i("SNISocketFactory", "Setting SNI hostname"); sslSocketFactory.setHostname(ssl, host); } else { Log.d( "SNISocketFactory", "No documented SNI support on Android <4.2, trying with reflection"); try { java.lang.reflect.Method setHostnameMethod = ssl.getClass().getMethod("setHostname", String.class); setHostnameMethod.invoke(ssl, host); } catch (Exception e) { Log.w("SNISocketFactory", "SNI not useable", e); } } return ssl; }
/** * SSL/TLS negotiation. Acquires an SSL socket of a control connection and carries out handshake * processing. * * @throws IOException If server negotiation fails */ protected void sslNegotiation() throws IOException { plainSocket = _socket_; initSslContext(); SSLSocketFactory ssf = context.getSocketFactory(); String ip = _socket_.getInetAddress().getHostAddress(); int port = _socket_.getPort(); SSLSocket socket = (SSLSocket) ssf.createSocket(_socket_, ip, port, false); socket.setEnableSessionCreation(isCreation); socket.setUseClientMode(isClientMode); // server mode if (!isClientMode) { socket.setNeedClientAuth(isNeedClientAuth); socket.setWantClientAuth(isWantClientAuth); } if (protocols != null) { socket.setEnabledProtocols(protocols); } if (suites != null) { socket.setEnabledCipherSuites(suites); } socket.startHandshake(); _socket_ = socket; _controlInput_ = new BufferedReader(new InputStreamReader(socket.getInputStream(), getControlEncoding())); _controlOutput_ = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), getControlEncoding())); }
/** * Returns a socket of the data connection. Wrapped as an {@link SSLSocket}, which carries out * handshake processing. * * @param command The textual representation of the FTP command to send. * @param arg The arguments to the FTP command. If this parameter is set to null, then the command * is sent with no arguments. * @return corresponding to the established data connection. Null is returned if an FTP protocol * error is reported at any point during the establishment and initialization of the * connection. * @throws IOException If there is any problem with the connection. * @see FTPClient#_openDataConnection_(int, String) * @since 3.2 */ @Override protected Socket _openDataConnection_(String command, String arg) throws IOException { Socket socket = super._openDataConnection_(command, arg); _prepareDataSocket_(socket); if (socket instanceof SSLSocket) { SSLSocket sslSocket = (SSLSocket) socket; sslSocket.setUseClientMode(isClientMode); sslSocket.setEnableSessionCreation(isCreation); // server mode if (!isClientMode) { sslSocket.setNeedClientAuth(isNeedClientAuth); sslSocket.setWantClientAuth(isWantClientAuth); } if (suites != null) { sslSocket.setEnabledCipherSuites(suites); } if (protocols != null) { sslSocket.setEnabledProtocols(protocols); } sslSocket.startHandshake(); } return socket; }
/* * Define the client side of the test. * * If the server prematurely exits, serverReady will be set to true * to avoid infinite hangs. */ void doClientSide() throws Exception { /* * Wait for server to get started. */ while (!serverReady) { Thread.sleep(50); } SSLSocketFactory sslsf = (SSLSocketFactory) SSLSocketFactory.getDefault(); SSLSocket sslSocket = (SSLSocket) sslsf.createSocket("localhost", serverPort); // enable TLSv1.1 only sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"}); // enable a block cipher sslSocket.setEnabledCipherSuites(new String[] {"TLS_RSA_WITH_AES_128_CBC_SHA"}); InputStream sslIS = sslSocket.getInputStream(); OutputStream sslOS = sslSocket.getOutputStream(); sslOS.write('B'); sslOS.flush(); sslIS.read(); sslSocket.close(); }
private void connect() throws IOException { Socket tmp = null; try { tmp = socketFactory.createSocket(); tmp.setTcpNoDelay(tcpNoDelay); if (sendBuffer > 0) tmp.setSendBufferSize(sendBuffer); tmp.bind(bindaddr); if (tmp instanceof SSLSocket) { SSLSocket sslsock = (SSLSocket) tmp; sslsock.setEnabledProtocols(new String[] {tlsProtocol}); sslsock.setEnabledCipherSuites(tlsCiphers); } tmp.connect(addr, tcpConnectTimeout); if (tmp instanceof SSLSocket) { SSLSocket sslsock = (SSLSocket) tmp; sslsock.startHandshake(); } sockout = new BufferedOutputStream(tmp.getOutputStream()); sock = tmp; tmp = null; } finally { if (tmp != null) try { tmp.close(); } catch (Exception ignore) { } } }
private static void hardenSocket(SSLSocket sock) { if (ENABLED_CIPHERS != null) { sock.setEnabledCipherSuites(ENABLED_CIPHERS); } if (ENABLED_PROTOCOLS != null) { sock.setEnabledProtocols(ENABLED_PROTOCOLS); } }
/** * Updates the provided socket to apply the appropriate set of enabled SSL protocols. This will * only have any effect for sockets that are instances of {@code javax.net.ssl.SSLSocket}, but it * is safe to call for any kind of {@code java.net.Socket}. This should be called before * attempting any communication over the socket, as * * @param socket The socket on which to apply the configured set of enabled SSL protocols. * @param protocols The set of protocols that should be enabled for the socket, if available. * @throws IOException If {@link #getEnabledSSLProtocols} returns a non-empty set but none of the * values in that set are supported by the socket. */ static void applyEnabledSSLProtocols(final Socket socket, final Set<String> protocols) throws IOException { if ((socket == null) || (!(socket instanceof SSLSocket)) || protocols.isEmpty()) { return; } final Set<String> lowerProtocols = new HashSet<String>(protocols.size()); for (final String s : protocols) { lowerProtocols.add(StaticUtils.toLowerCase(s)); } final SSLSocket sslSocket = (SSLSocket) socket; final String[] supportedProtocols = sslSocket.getSupportedProtocols(); final ArrayList<String> enabledList = new ArrayList<String>(supportedProtocols.length); for (final String supportedProtocol : supportedProtocols) { if (lowerProtocols.contains(StaticUtils.toLowerCase(supportedProtocol))) { enabledList.add(supportedProtocol); } } if (enabledList.isEmpty()) { final StringBuilder enabledBuffer = new StringBuilder(); final Iterator<String> enabledIterator = protocols.iterator(); while (enabledIterator.hasNext()) { enabledBuffer.append('\''); enabledBuffer.append(enabledIterator.next()); enabledBuffer.append('\''); if (enabledIterator.hasNext()) { enabledBuffer.append(", "); } } final StringBuilder supportedBuffer = new StringBuilder(); for (int i = 0; i < supportedProtocols.length; i++) { if (i > 0) { supportedBuffer.append(", "); } supportedBuffer.append('\''); supportedBuffer.append(supportedProtocols[i]); supportedBuffer.append('\''); } throw new IOException( ERR_NO_ENABLED_SSL_PROTOCOLS_AVAILABLE_FOR_SOCKET.get( enabledBuffer.toString(), supportedBuffer.toString(), PROPERTY_ENABLED_SSL_PROTOCOLS, SSLUtil.class.getName() + ".setEnabledSSLProtocols")); } else { final String[] enabledArray = new String[enabledList.size()]; sslSocket.setEnabledProtocols(enabledList.toArray(enabledArray)); } }
/** @see ProtocolSocketFactory#createSocket(java.lang.String,int) */ @Override public Socket createSocket(String host, int port) throws IOException, UnknownHostException { Socket socket = (Socket) getSSLContext().getSocketFactory().createSocket(host, port); if (socket instanceof SSLSocket) { ((SSLSocket) socket) .setEnabledProtocols( SSLUtils.getSupportedProtocols(((SSLSocket) socket).getEnabledProtocols())); } return socket; }
/** Applies this spec to {@code sslSocket}. */ void apply(SSLSocket sslSocket, boolean isFallback) { ConnectionSpec specToApply = supportedSpec(sslSocket, isFallback); if (specToApply.tlsVersions != null) { sslSocket.setEnabledProtocols(specToApply.tlsVersions); } if (specToApply.cipherSuites != null) { sslSocket.setEnabledCipherSuites(specToApply.cipherSuites); } }
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { Socket s = getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose); if (s instanceof SSLSocket) { ((SSLSocket) s) .setEnabledProtocols( SSLUtils.getSupportedProtocols(((SSLSocket) s).getEnabledProtocols())); } return s; }
public void afterConnect() throws IOException, UnknownHostException { if (!isCachedConnection()) { SSLSocket s = null; SSLSocketFactory factory; factory = sslSocketFactory; try { if (!(serverSocket instanceof SSLSocket)) { s = (SSLSocket) factory.createSocket(serverSocket, host, port, true); } else { s = (SSLSocket) serverSocket; } } catch (IOException ex) { // If we fail to connect through the tunnel, try it // locally, as a last resort. If this doesn't work, // throw the original exception. try { s = (SSLSocket) factory.createSocket(host, port); } catch (IOException ignored) { throw ex; } } SSLSocketFactoryImpl.checkCreate(s); // // Force handshaking, so that we get any authentication. // Register a handshake callback so our session state tracks any // later session renegotiations. // String[] protocols = getProtocols(); String[] ciphers = getCipherSuites(); if (protocols != null) s.setEnabledProtocols(protocols); if (ciphers != null) s.setEnabledCipherSuites(ciphers); s.addHandshakeCompletedListener(this); s.startHandshake(); session = s.getSession(); // change the serverSocket and serverOutput serverSocket = s; try { serverOutput = new PrintStream( new BufferedOutputStream(serverSocket.getOutputStream()), false, encoding); } catch (UnsupportedEncodingException e) { throw new InternalError(encoding + " encoding not found"); } // check URL spoofing checkURLSpoofing(hv); } else { // if we are reusing a cached https session, // we don't need to do handshaking etc. But we do need to // set the ssl session session = ((SSLSocket) serverSocket).getSession(); } }
/** Creates a new TlsSocket */ public TlsSocket createTlsSocket(String host, int port) throws java.io .IOException { // SSLSocket ssl_socket=(SSLSocket)ssl_factory.createSocket(host,port); // return new TlsSocket(ssl_socket); SSLSocket ssl_socket = (SSLSocket) ssl_factory.createSocket(); if (!client_mode) ssl_socket.setUseClientMode(false); if (enabled_protocols != null) ssl_socket.setEnabledProtocols(enabled_protocols); ssl_socket.connect(new java.net.InetSocketAddress(host, port)); return new TlsSocket(ssl_socket); }
@Override public Socket createSocket( final Socket socket, final String host, final int port, final boolean autoClose) throws IOException, UnknownHostException { Socket s = ssf.createSocket(socket, host, port, autoClose); if (s instanceof SSLSocket) { ((SSLSocket) s) .setEnabledProtocols( SSLUtils.getSupportedProtocols(((SSLSocket) s).getEnabledProtocols())); } return s; }
@Override public Socket createSocket( final String address, final int port, final InetAddress localAddress, final int localPort) throws IOException, UnknownHostException { Socket socket = ssf.createSocket(address, port, localAddress, localPort); if (socket instanceof SSLSocket) { ((SSLSocket) socket) .setEnabledProtocols( SSLUtils.getSupportedProtocols(((SSLSocket) socket).getEnabledProtocols())); } return socket; }
private void initialize() { try { SSLContext sslContext = SSLContext.getInstance(protocols[0]); sslContext.init(keyManagers, trustManagers, null); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); socket = (SSLSocket) socketFactory.createSocket(getRemoteInetAddress(), getAuthPort()); socket.setReuseAddress(true); socket.setSoTimeout(getSocketTimeout() * 1000); socket.setEnabledProtocols(protocols); if (getAcctPort() != getAuthPort()) { socketAcct = (SSLSocket) socketFactory.createSocket(getRemoteInetAddress(), getAcctPort()); socketAcct.setReuseAddress(true); socketAcct.setSoTimeout(getSocketTimeout() * 1000); socketAcct.setEnabledProtocols(protocols); } } catch (Exception e) { e.printStackTrace(); } }
@Override public Socket createSocket(Socket plainSocket, String host, int port, boolean autoClose) throws IOException { String peerHost = this.conn.getRequestProperty("Host"); if (peerHost == null) peerHost = host; Log.i(TAG, "customized createSocket. host: " + peerHost); InetAddress address = plainSocket.getInetAddress(); if (autoClose) { // we don't need the plainSocket plainSocket.close(); } // create and connect SSL socket, but don't do hostname/certificate verification yet SSLCertificateSocketFactory sslSocketFactory = (SSLCertificateSocketFactory) SSLCertificateSocketFactory.getDefault(0); SSLSocket ssl = (SSLSocket) sslSocketFactory.createSocket(address, port); // enable TLSv1.1/1.2 if available ssl.setEnabledProtocols(ssl.getSupportedProtocols()); // set up SNI before the handshake if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { Log.i(TAG, "Setting SNI hostname"); sslSocketFactory.setHostname(ssl, peerHost); } else { Log.d(TAG, "No documented SNI support on Android <4.2, trying with reflection"); try { java.lang.reflect.Method setHostnameMethod = ssl.getClass().getMethod("setHostname", String.class); setHostnameMethod.invoke(ssl, peerHost); } catch (Exception e) { Log.w(TAG, "SNI not useable", e); } } // verify hostname and certificate SSLSession session = ssl.getSession(); if (!hostnameVerifier.verify(peerHost, session)) throw new SSLPeerUnverifiedException("Cannot verify hostname: " + peerHost); Log.i( TAG, "Established " + session.getProtocol() + " connection with " + session.getPeerHost() + " using " + session.getCipherSuite()); return ssl; }
/* */ public Socket createSocket(String paramString, int paramInt) /* */ throws IOException /* */ { /* 117 */ SocketFactory localSocketFactory = getDefaultClientSocketFactory(); /* */ /* 120 */ SSLSocket localSSLSocket = (SSLSocket) localSocketFactory.createSocket(paramString, paramInt); /* */ /* 124 */ String str = System.getProperty("javax.rmi.ssl.client.enabledCipherSuites"); /* */ /* 126 */ if (str != null) { /* 127 */ localObject = new StringTokenizer(str, ","); /* 128 */ int i = ((StringTokenizer) localObject).countTokens(); /* 129 */ String[] arrayOfString1 = new String[i]; /* 130 */ for (int k = 0; k < i; k++) /* 131 */ arrayOfString1[k] = ((StringTokenizer) localObject).nextToken(); /* */ try /* */ { /* 134 */ localSSLSocket.setEnabledCipherSuites(arrayOfString1); /* */ } catch (IllegalArgumentException localIllegalArgumentException1) { /* 136 */ throw ((IOException) new IOException(localIllegalArgumentException1.getMessage()) .initCause(localIllegalArgumentException1)); /* */ } /* */ /* */ } /* */ /* 142 */ Object localObject = System.getProperty("javax.rmi.ssl.client.enabledProtocols"); /* */ /* 144 */ if (localObject != null) { /* 145 */ StringTokenizer localStringTokenizer = new StringTokenizer((String) localObject, ","); /* 146 */ int j = localStringTokenizer.countTokens(); /* 147 */ String[] arrayOfString2 = new String[j]; /* 148 */ for (int m = 0; m < j; m++) /* 149 */ arrayOfString2[m] = localStringTokenizer.nextToken(); /* */ try /* */ { /* 152 */ localSSLSocket.setEnabledProtocols(arrayOfString2); /* */ } catch (IllegalArgumentException localIllegalArgumentException2) { /* 154 */ throw ((IOException) new IOException(localIllegalArgumentException2.getMessage()) .initCause(localIllegalArgumentException2)); /* */ } /* */ /* */ } /* */ /* 160 */ return localSSLSocket; /* */ }
public SSLSocket clientNoHandshake(String hostName, int hostPort, boolean useClientCert) throws IOException { SSLSocket socket = null; // SSL Strong Cipher Hack // SSL Strong Cipher Hack if (useClientCert) { socket = (SSLSocket) clientSSLSockCertFactory.createSocket(hostName, hostPort); } else { socket = (SSLSocket) clientSSLSockFactory.createSocket(hostName, hostPort); } socket.setEnabledProtocols(new String[] {"SSLv3"}); socket.setEnabledCipherSuites(new String[] {"SSL_RSA_WITH_DES_CBC_SHA"}); return socket; }
/** * Create an {@code SSLSocket} and perform the SSL handshake (performing certificate validation. * * @param sslSocketFactory Source of new {@code SSLSocket} instances. * @param tlsTolerant If true, assume server can handle common TLS extensions and SSL deflate * compression. If false, use an SSL3 only fallback mode without compression. */ public void setupSecureSocket(SSLSocketFactory sslSocketFactory, boolean tlsTolerant) throws IOException { // create the wrapper over connected socket unverifiedSocket = (SSLSocket) sslSocketFactory.createSocket( socket, address.uriHost, address.uriPort, true /* autoClose */); // tlsTolerant mimics Chrome's behavior if (tlsTolerant && unverifiedSocket instanceof OpenSSLSocketImpl) { OpenSSLSocketImpl openSslSocket = (OpenSSLSocketImpl) unverifiedSocket; openSslSocket.setEnabledCompressionMethods(new String[] {"ZLIB"}); openSslSocket.setUseSessionTickets(true); openSslSocket.setHostname(address.socketHost); // use SSLSocketFactory default enabled protocols } else { unverifiedSocket.setEnabledProtocols(new String[] {"SSLv3"}); } // force handshake, which can throw unverifiedSocket.startHandshake(); }
public void supportTlsIntolerantServer(SSLSocket socket) { String fallbackScsv = "TLS_FALLBACK_SCSV"; boolean socketSupportsFallbackScsv = false; String[] supportedCipherSuites = socket.getSupportedCipherSuites(); for (int i = supportedCipherSuites.length - 1; i >= 0; i--) { if ("TLS_FALLBACK_SCSV".equals(supportedCipherSuites[i])) { socketSupportsFallbackScsv = true; break; } } if (socketSupportsFallbackScsv) { String[] enabledCipherSuites = socket.getEnabledCipherSuites(); String[] newEnabledCipherSuites = new String[(enabledCipherSuites.length + 1)]; System.arraycopy( enabledCipherSuites, 0, newEnabledCipherSuites, 0, enabledCipherSuites.length); newEnabledCipherSuites[newEnabledCipherSuites.length - 1] = "TLS_FALLBACK_SCSV"; socket.setEnabledCipherSuites(newEnabledCipherSuites); } socket.setEnabledProtocols(new String[] {"SSLv3"}); }
/** {@inheritDoc} Used to enforce the preferred TLS protocol during SSL handshake. */ @Override protected final void prepareSocket(final SSLSocket socket) { String[] supported = socket.getSupportedProtocols(); String[] enabled = socket.getEnabledProtocols(); if (LOG.isDebugEnabled()) { LOG.debug( "socket.getSupportedProtocols(): " + Arrays.toString(supported) + ", socket.getEnabledProtocols(): " + Arrays.toString(enabled)); } List<String> target = new ArrayList<String>(); if (supported != null) { // Append the preferred protocols in descending order of preference // but only do so if the protocols are supported TLSProtocol[] values = TLSProtocol.values(); for (int i = 0; i < values.length; i++) { final String pname = values[i].getProtocolName(); if (existsIn(pname, supported)) { target.add(pname); } } } if (enabled != null) { // Append the rest of the already enabled protocols to the end // if not already included in the list for (String pname : enabled) { if (!target.contains(pname)) { target.add(pname); } } } if (target.size() > 0) { String[] enabling = target.toArray(new String[target.size()]); socket.setEnabledProtocols(enabling); if (LOG.isDebugEnabled()) { LOG.debug("TLS protocol enabled for SSL handshake: " + Arrays.toString(enabling)); } } }
@Test public void tls_defaultCiphers_withFallbackIndicator() throws Exception { ConnectionSpec tlsSpec = new ConnectionSpec.Builder(true) .tlsVersions(TlsVersion.TLS_1_2) .supportsTlsExtensions(false) .build(); SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); socket.setEnabledCipherSuites( new String[] { CipherSuite.TLS_RSA_WITH_RC4_128_MD5.javaName, CipherSuite.TLS_RSA_WITH_RC4_128_SHA.javaName, }); socket.setEnabledProtocols( new String[] { TlsVersion.TLS_1_2.javaName, TlsVersion.TLS_1_1.javaName, }); Route route = new Route( HTTPS_ADDRESS, PROXY, INET_SOCKET_ADDRESS, tlsSpec, true /* shouldSendTlsFallbackIndicator */); tlsSpec.apply(socket, route); assertEquals(createSet(TlsVersion.TLS_1_2.javaName), createSet(socket.getEnabledProtocols())); Set<String> expectedCipherSet = createSet( CipherSuite.TLS_RSA_WITH_RC4_128_MD5.javaName, CipherSuite.TLS_RSA_WITH_RC4_128_SHA.javaName); if (Arrays.asList(socket.getSupportedCipherSuites()).contains("TLS_FALLBACK_SCSV")) { expectedCipherSet.add("TLS_FALLBACK_SCSV"); } assertEquals(expectedCipherSet, expectedCipherSet); }
@SuppressLint("NewApi") private Socket enableSNI(SSLSocket ssl, String host) throws SSLPeerUnverifiedException { // enable TLSv1.1/1.2 if available // (see https://github.com/rfc2822/davdroid/issues/229) ssl.setEnabledProtocols(ssl.getSupportedProtocols()); // set up SNI before the handshake if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { AppLog.i(T.API, "Setting SNI hostname"); mFactory.setHostname(ssl, host); } else { AppLog.i(T.API, "No documented SNI support on Android <4.2, trying with reflection"); try { java.lang.reflect.Method setHostnameMethod = ssl.getClass().getMethod("setHostname", String.class); setHostnameMethod.invoke(ssl, host); } catch (Exception e) { AppLog.e(T.API, "SNI not useable", e); } } // verify hostname and certificate SSLSession session = ssl.getSession(); if (!mHostnameVerifier.verify(host, session)) { throw new SSLPeerUnverifiedException("Cannot verify hostname: " + host); } AppLog.i( T.API, "Established " + session.getProtocol() + " connection with " + session.getPeerHost() + " using " + session.getCipherSuite()); return ssl; }
/** * Prepares a TLS/SSL connection socket by: - setting reasonable TLS protocol versions - setting * reasonable cipher suites (if required) * * @param socket unconnected SSLSocket to prepare */ private void setTlsParameters(SSLSocket socket) { // Android 5.0+ (API level21) provides reasonable default settings // but it still allows SSLv3 // https://developer.android.com/about/versions/android-5.0-changes.html#ssl /* set reasonable protocol versions */ // - enable all supported protocols (enables TLSv1.1 and TLSv1.2 on Android <5.0) // - remove all SSL versions (especially SSLv3) because they're insecure now final List<String> protocols = new LinkedList<String>(); for (String protocol : socket.getSupportedProtocols()) { if (!protocol.toUpperCase().contains("SSL")) { protocols.add(protocol); } } Log.v(TAG, "Setting allowed TLS protocols: " + TextUtils.join(", ", protocols)); socket.setEnabledProtocols(protocols.toArray(new String[protocols.size()])); /* set reasonable cipher suites */ if (Build.VERSION.SDK_INT < VERSION_CODES_LOLLIPOP) { // choose secure cipher suites final List<String> availableCiphers = Arrays.asList(socket.getSupportedCipherSuites()); // preferred ciphers = allowed Ciphers \ availableCiphers final Set<String> preferredCiphers = new HashSet<String>(ALLOWED_CIPHERS); preferredCiphers.retainAll(availableCiphers); // add enabled ciphers to preferred ciphers // for maximum security, preferred ciphers should *replace* enabled ciphers, // but for the security level of ACRA, disabling of insecure // ciphers should be a server-side task preferredCiphers.addAll(Arrays.asList(socket.getEnabledCipherSuites())); Log.v(TAG, "Setting allowed TLS ciphers: " + TextUtils.join(", ", preferredCiphers)); socket.setEnabledCipherSuites(preferredCiphers.toArray(new String[preferredCiphers.size()])); } }
/** * SSL/TLS negotiation. Acquires an SSL socket of a connection and carries out handshake * processing. * * @throws java.io.IOException If server negotiation fails. */ private void performSSLNegotiation() throws IOException { initSSLContext(); SSLSocketFactory ssf = context.getSocketFactory(); String ip = getRemoteAddress().getHostAddress(); int port = getRemotePort(); SSLSocket socket = (SSLSocket) ssf.createSocket(_socket_, ip, port, true); socket.setEnableSessionCreation(true); socket.setUseClientMode(true); if (protocols != null) { socket.setEnabledProtocols(protocols); } if (suites != null) { socket.setEnabledCipherSuites(suites); } socket.startHandshake(); _socket_ = socket; _input_ = socket.getInputStream(); _output_ = socket.getOutputStream(); _reader = new CRLFLineReader(new InputStreamReader(_input_, encoding)); _writer = new BufferedWriter(new OutputStreamWriter(_output_, encoding)); }
public Socket createSocket() throws IOException { SSLSocket socket = (SSLSocket) factory.createSocket(); socket.setEnabledProtocols(new String[] {protocol}); return socket; }