Android custom socket obtained from OpenSSLSocketImpl (not SSLSocket)

Sorry this is such a long question, but it gets somewhat involved. Thanks for reading.

I have a custom socket factory and a socket class (Android 5.0) that I developed to do some specific tasks that I need to do at this level. Here is my socket factory and socket (I leave many methods for brevity):

public class CustomSocketFactory extends SSLSocketFactory {
private final SSLSocketFactory delegate;

public CustomSocketFactory(SSLSocketFactory delegate) {
    this.delegate = delegate;
}

private Socket createCustomSocket(Socket socket) {
    if (socket instanceof SSLSocket) {
        socket = new CustomSocket((SSLSocket) socket);
    }
    return socket;
}

@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
    return createCustomSocket(delegate.createSocket(s, host, port, autoClose));
}

@Override
public Socket createSocket(String host, int port) throws IOException {
    return createCustomSocket(delegate.createSocket(host, port));
}


private class CustomSocket extends SSLSocket {

    protected final SSLSocket delegate;

    private CustomSocket(SSLSocket delegate) {
        this.delegate = delegate;
    }

      

I am using this factory like this:

  private void doCustomSocketFactoryWithHttpUrlConnection() {

    try {
        String uri = "https://alice.sni.velox.ch";

        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, null, null);
        CustomSocketFactory customSocketFactory = new CustomSocketFactory(context.getSocketFactory());
        HttpsURLConnection.setDefaultSSLSocketFactory(customSocketFactory);

        URL url = new URL(uri);
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

        Log.d(TAG, "HTTP Response Code: " + conn.getResponseCode());

    } catch (Exception e) {
        Log.d(TAG, e.getLocalizedMessage());
    }

}

      

This works as expected, except when I am on a site that uses Server Name , such as alice.sni.velox.ch . In this case, the site is complaining (and I confirm with Wireshark) that SNI TLS headers are not being sent by my application.

Take out your own factory socket and dispatched headers.

Digging further, I found this code in the okhttp Platform.java class (the okhttp classes are used internally by HttpsURLConnection).

@Override public void enableTlsExtensions(SSLSocket socket, String uriHost) {
     super.enableTlsExtensions(socket, uriHost);
     if (!openSslSocketClass.isInstance(socket)) return;
     try {
       setUseSessionTickets.invoke(socket, true);
       setHostname.invoke(socket, uriHost);
     } catch (InvocationTargetException e) {
// snip
}

      

The openSSLSocketClass is configured as follows:

Class<?> openSslSocketClass =    Class.forName("com.android.org.conscrypt.OpenSSLSocketImpl");

      

So this code allows SNI and session to be used, but only if the socket extends OpenSSLSocketImpl.

Back to my custom socket, in the debugger I can see that the socket class passed to the constructor is: com.android.org.conscrypt.OpenSSLSocketImplWrapper (which extends OpenSSLSocketImpl).

So I'm missing the SNI and session ticket functionality because my socket extends java.net.ssl.SSLSocket (not OpenSSLSocketImpl).

The best solution that comes to mind is to just extend MyScanSocket OpenSSLSocketImpl and add the required delegation methods, but I can't see how to import OpenSSLSocketImpl. It doesn't seem to be in the standard Android libraries. Android documentation only discusses SSLSocket and doesn't say anything about OpenSSLSocketImpl.

Is there a way to have my CustomSocket class extend from OpenSSLSocketImpl that I am missing?

I realize that I can use reflection to call these methods in "delegation" in my CustomSocket class, but I am worried about the reliability of this in all cases and where / when for these calls. Also, if they keep adding new features to the OpenSSLSocketImpl class in newer versions of Android using a similar method, I would skip those features too.

Thanks for reading all the way!

+3


source to share


2 answers


It depends on what functionality you need to implement in your CustomSocket, but you can do the following:



  • make CustomSocket a Socket extension (no SSL)
  • in your factory socket, create a simple custom socket then wrap the SSL socket around it delegate.createSocket(s, host, port, autoClose)

  • returns the result delegate

    , it will be of typecom.android.org.conscrypt.OpenSSLSocketImplWrapper

0


source


Well, maybe I'm not that helpful to you, but you can try setting up a different client like jersey client or apache http client, especially since Android's native HTTP clients are too old and should be replaced.



-1


source







All Articles