@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; }
private static void printSocketInfo(SSLSocket s) { LOGGER.info("Socket class: " + s.getClass()); LOGGER.info(" Remote address = " + s.getInetAddress().toString()); LOGGER.info(" Remote port = " + s.getPort()); LOGGER.info(" Local socket address = " + s.getLocalSocketAddress().toString()); LOGGER.info(" Local address = " + s.getLocalAddress().toString()); LOGGER.info(" Local port = " + s.getLocalPort()); LOGGER.info(" Need client authentication = " + s.getNeedClientAuth()); SSLSession ss = s.getSession(); LOGGER.info(" Cipher suite = " + ss.getCipherSuite()); LOGGER.info(" Protocol = " + ss.getProtocol()); }
@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; }
@TargetApi(VERSION_CODES_JELLY_BEAN_MR1) private void setSniHostname(SSLSocket socket, String hostName) { // set SNI host name if (Build.VERSION.SDK_INT >= VERSION_CODES_JELLY_BEAN_MR1) { Log.d(TAG, "Using documented SNI with host name " + hostName); sslSocketFactory.setHostname(socket, hostName); } else { Log.d( TAG, "No documented SNI support on Android <4.2, trying reflection method with host name " + hostName); try { final Method setHostnameMethod = socket.getClass().getMethod("setHostname", String.class); setHostnameMethod.invoke(socket, hostName); } catch (Exception e) { Log.w(TAG, "SNI not usable", e); } } }
@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; }