Last active
January 30, 2016 06:17
-
-
Save longbai/fa72b6c5f2648131f14d to your computer and use it in GitHub Desktop.
android loopj ssl sni ref http://blog.dev001.net/post/67082904181/android-using-sni-and-tlsv12-with-apache
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class TlsSniSocketFactory extends MySSLSocketFactory { | |
private static final String TAG = "davdroid.SNISocketFactory"; | |
final static HostnameVerifier hostnameVerifier = new StrictHostnameVerifier(); | |
// Plain TCP/IP (layer below TLS) | |
@Override | |
public Socket connectSocket(Socket s, String host, int port, InetAddress localAddress, int localPort, HttpParams params) throws IOException { | |
// 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(TAG, "Setting SNI hostname"); | |
this.setHostname(ssl, host); | |
} 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, host.getHostName()); | |
} catch (Exception e) { | |
Log.w(TAG, "SNI not useable", e); | |
} | |
} | |
// copy super implements to here | |
} | |
@Override | |
public Socket createSocket() throws IOException { | |
return super.createSocket(); | |
} | |
@Override | |
public boolean isSecure(Socket s) throws IllegalArgumentException { | |
if (s instanceof SSLSocket) | |
return ((SSLSocket)s).isConnected(); | |
return false; | |
} | |
// TLS layer | |
@Override | |
public Socket createSocket(Socket plainSocket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { | |
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(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(TAG, "Setting SNI hostname"); | |
sslSocketFactory.setHostname(ssl, host); | |
} 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, host.getHostName()); | |
} catch (Exception e) { | |
Log.w(TAG, "SNI not useable", e); | |
} | |
} | |
// verify hostname and certificate | |
SSLSession session = ssl.getSession(); | |
if (!hostnameVerifier.verify(host, session)) | |
throw new SSLPeerUnverifiedException("Cannot verify hostname: " + host); | |
Log.i(TAG, "Established " + session.getProtocol() + " connection with " + session.getPeerHost() + | |
" using " + session.getCipherSuite()); | |
return ssl; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment