TLS v1.2 and KSoap2

1,091 views
Skip to first unread message

Nick Ellis

unread,
Aug 4, 2015, 1:02:08 PM8/4/15
to ksoap2-android
Hello,

I'm currently using KSoap2 for my app, and the webserver it uses is transitioning to only use the TLS v1.2 protocol. My app supports APIs 16+, and the documentation states that TLS v1.2 is not enabled by default on APIs 16-19.

My question is how do I expose the connection so that I can enable TLS v1.2 on it? Has anybody found a good way? Looks like I can cast the service connection as a HttpsURLConnection and then set the socket factory, but that seems like a terrible way to do it.

HttpsURLConnection httpsConn = (HttpsURLConnection) androidHttpTransport.getServiceConnection();

httpsConn.setSSLSocketFactory( /*SET SSL SOCKET FACTORY HERE*/);


Thanks,
-Nick



Manfred Moser

unread,
Aug 6, 2015, 1:51:52 AM8/6/15
to ksoap2-...@googlegroups.com
This sort of approach might work although it will depend on the underlying device and if the lower level TLS 1.2 support is present. 

The same idea can be used to override security setup in terms of certficate trust and has been used in various apps successfully. 

I am not sure if anybody has a more details sample for TLS1.2 support. 

ksoap2-android only sits on top of the platform provided http stack and does not reinvent or add anything on top.

A nice approach for getting the http related setup improved might be to use okhttp but I am not aware of anybody having done that.

manfred

--
You received this message because you are subscribed to the Google Groups "ksoap2-android" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ksoap2-androi...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Roxanne Bayaborda

unread,
Oct 23, 2015, 7:25:58 AM10/23/15
to ksoap2-android
Hi Sir,

May I ask if you found out the solution to your problem because we have the same problem. Please help me. Thanks

Nick Ellis

unread,
Oct 23, 2015, 1:26:31 PM10/23/15
to ksoap2-android
Hi Roxanne,

With some help from Manfred we were able to figure it out.

Remember that this will only work for Android API 16+. TLS v1.2 is only supported on these APIs.

You'll need to do two things. You'll need to override the SSLSocketFactory class, and you'll need to make your own HttpsTransportSE from KSoap2. This answer might seem overly complicated, but its done this way for a reason. At first I tried using a socket factory created from a SSL context, which I thought would work. Looked something like this:

SSLContext context = SSLContext.getInstance("TLSv1.2");
context.init(null, null, null);
tls12Factory = context.getSocketFactory();

This factory will produce sockets that actually have 2 protocols enabled, "SSLv3" and "TLSv1.2". Then for some reason my connection was using the "SSLv3" connection even though it wasn't supported by the server (see SO: http://stackoverflow.com/questions/16531807/android-client-server-on-tls-v1-2).

1) Overriding the SSLSocketFactory class
I've attached Tls12OnlySocket.java for reference. I'm just going to highlight the important parts in this. Basically its just writing your own socket factory to use your own sockets that only allow the "TLSv1.2" protocol.

private Tls12OnlySocket(SSLSocket delegate) {
    super(delegate);
    delegate.setEnabledProtocols(new String[]{"TLSv1.2"});
}

@Override
public void setEnabledProtocols(String[] protocols) {}

In the Tls12OnlySocket constructor you should set the enabled protocols as "TLSv1.2". The ones created from SSLContext.getInstance("TLSv1.2") factory will have "SSLv3" enabled as well which we don't want. I also overrode the setEnabledProtocols to do nothing, so that the socket will only ever use "TLSv1.2" no matter what.

Then in the socket factory, whenever a createSocket() method is called return your Tls12OnlySocket if the socket is a SSLSocket. For example:

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

    private Socket strippedProtocolSocket(Socket socket) {
        if (socket instanceof SSLSocket) {
            socket = new Tls12OnlySocket((SSLSocket) socket);
        }
        return socket;
    }

2) HttpsTransportSE class for TLS 1.2

Whenever your transport class requests a service connection, be sure that it is using your socket factory. Shown below:

public class HttpsTls12TransportSE extends HttpsTransportSE
{
    public HttpsTls12TransportSE(String host, int port, String file, int timeout) {
        super(host, port, file, timeout);
    }
    
    @Override
    public ServiceConnection getServiceConnection() throws IOException
    {
        ServiceConnection serviceConnection =
                new HttpsServiceConnectionSEIgnoringConnectionClose(host, port, file, timeout);
        serviceConnection.setRequestProperty("Connection", "keep-alive");

        SSLSocketFactory factory = new Tls12SocketFactory();
        ((HttpsServiceConnectionSE)serviceConnection).setSSLSocketFactory(factory);

        return serviceConnection;
    }

}

And that should do it!
Tls12SocketFactory.java

Roxanne Bayaborda

unread,
Oct 24, 2015, 1:18:08 AM10/24/15
to ksoap2-android
Thank you very much to all of you. It will be a great help for us.

Roxanne Bayaborda

unread,
Oct 24, 2015, 1:35:44 AM10/24/15
to ksoap2-android
Hi sir,

Follow up question, do i still need to configure the webconfig of webservice because we are trying to call the web method it returns an error. Please see below. I am now using the WCf webservice. Im confused where is the cause of an error. We successfully applied the what was you've given to us. THANKS IN ADVANCE. :)


ERROR FROM APP:

10-24 13:24:32.255: W/System.err(32367): java.net.SocketTimeoutException: Read timed out
10-24 13:24:32.315: W/System.err(32367): at com.android.org.conscrypt.NativeCrypto.SSL_read(Native Method)
10-24 13:24:32.315: W/System.err(32367): at com.android.org.conscrypt.OpenSSLSocketImpl$SSLInputStream.read(OpenSSLSocketImpl.java:690)
10-24 13:24:32.315: W/System.err(32367): at java.io.InputStream.read(InputStream.java:162)
10-24 13:24:32.315: W/System.err(32367): at java.io.BufferedInputStream.fillbuf(BufferedInputStream.java:142)
10-24 13:24:32.315: W/System.err(32367): at java.io.BufferedInputStream.read(BufferedInputStream.java:227)
10-24 13:24:32.315: W/System.err(32367): at com.android.okhttp.internal.Util.readAsciiLine(Util.java:316)
10-24 13:24:32.315: W/System.err(32367): at com.android.okhttp.internal.http.RawHeaders.fromBytes(RawHeaders.java:308)
10-24 13:24:32.315: W/System.err(32367): at com.android.okhttp.internal.http.HttpTransport.readResponseHeaders(HttpTransport.java:135)
10-24 13:24:32.315: W/System.err(32367): at com.android.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:644)
10-24 13:24:32.315: W/System.err(32367): at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:347)
10-24 13:24:32.315: W/System.err(32367): at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296)
10-24 13:24:32.315: W/System.err(32367): at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:503)
10-24 13:24:32.315: W/System.err(32367): at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:136)
10-24 13:24:32.315: W/System.err(32367): at org.ksoap2.transport.HttpsServiceConnectionSE.getResponseCode(HttpsServiceConnectionSE.java:107)
10-24 13:24:32.325: W/System.err(32367): at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:192)
10-24 13:24:32.325: W/System.err(32367): at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:118)
10-24 13:24:32.325: W/System.err(32367): at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:113)
10-24 13:24:32.325: W/System.err(32367): at com.smart.paymaya.CallSoapActivate.doInBackground(CallSoapActivate.java:164)
10-24 13:24:32.325: W/System.err(32367): at com.smart.paymaya.CallSoapActivate.doInBackground(CallSoapActivate.java:1)
10-24 13:24:32.335: W/System.err(32367): at android.os.AsyncTask$2.call(AsyncTask.java:288)
10-24 13:24:32.335: W/System.err(32367): at java.util.concurrent.FutureTask.run(FutureTask.java:237)
10-24 13:24:32.335: W/System.err(32367): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
10-24 13:24:32.335: W/System.err(32367): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
10-24 13:24:32.335: W/System.err(32367): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
10-24 13:24:32.335: W/System.err(32367): at java.lang.Thread.run(Thread.java:841)

Roxanne Bayaborda

unread,
Oct 24, 2015, 1:35:49 AM10/24/15
to ksoap2-android

Federico Villafañes

unread,
Dec 15, 2020, 4:45:28 PM12/15/20
to ksoap2-android
Hi Roxane,

Do you was able of solving the 'read timed out' exception? I have the same issue after implementing the fixes indicated by Nick Hellis.

Thanks!
Federico
Reply all
Reply to author
Forward
0 new messages