Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protocol error between Android and Python using SSL

This question has been asked, in various flavors, several times. Unfortunately, none of the answers have yielded a solution for me.

I am attempting to connect to a python web server (code to follow) using the https protocol, with client side authentication included. When I connect via a python client that I wrote for testing, I have no problems. Fast forward, I am now trying to connect from an Android device (code to follow again) and am getting a

javax.net.ssl.SSLProtocolException

I have a self signed CA, which has issued two certificates. One for the client and one for the server.

I removed the passphrase from the server private key using:

openssl rsa -in serverKey.pem -out serverKey.pem

and issued a request using openssl from the linux command line.

For the client I issued a request, created the certificate and then used keytool with the BouncyCastle provider to import the CA into a trust store and the client certificate into a key store (I realize they are the same format, it just helps me to keep them separated if I refer to them by different names).

Relevant server code:

class ReuseHTTPServer(BaseHTTPServer.HTTPServer):
    def __init__(self, address, handler):
        BaseHTTPServer.HTTPServer.__init__(self, address, handler)

        self.address = address

        ssl_socket = ssl.wrap_socket(socket.socket(self.address_family,
                                                   self.socket_type),
                                     keyfile = KEY_PATH,
                                     certfile = CERTIFICATE_PATH,
                                     server_side = True,
                                     cert_reqs = ssl.CERT_REQUIRED,
                                     ssl_version = ssl.PROTOCOL_SSLv23,
                                     ca_certs = CA_PATH)
        s = self.socket.getsockname()

        print "serving:", s[0], "on port:", s[1]

        self.socket = ssl_socket

        self.server_bind()
        self.server_activate()

    def server_bind(self):
        BaseHTTPServer.HTTPServer.server_bind(self)

Android client code:

//add bouncy castle to the list of security providers
Security.insertProviderAt(new BouncyCastleProvider(), 1);

//load the trusted CA
KeyStore trusted = KeyStore.getInstance("BKS");
InputStream in = getResources().openRawResource(R.raw.mobilecastore);
trusted.load(in, "password".toCharArray());
in.close();
TrustManagerFactory trust_factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trust_factory.init(trusted);

//load the client keystore
KeyStore client = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream client_in = getResources().openRawResource(R.raw.client);
client.load(client_in, "password2".toCharArray());
client_in.close();
KeyManagerFactory key_factory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

key_factory.init(client, "password2".toCharArray());

SSLContext ssl_context = SSLContext.getInstance("SSL"); 
ssl_context.init(key_factory.getKeyManagers(), trust_factory.getTrustManagers(), null);

URL url = new URL("https", IP, 60000, "/cgi-bin/www_sel_jf");
connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(ssl_context.getSocketFactory());
connection.setDoInput(true);
connection.setRequestMethod("GET");
connection.connect();

The error:

12-31 07:23:37.917: W/System.err(3666): javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0x16bab18: Failure in SSL library, usually a protocol error
12-31 07:23:37.917: W/System.err(3666): error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure (external/openssl/ssl/s3_pkt.c:1234 0x16bf980:0x00000003)
12-31 07:23:37.917: W/System.err(3666):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:460)
12-31 07:23:37.917: W/System.err(3666):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:257)
12-31 07:23:37.917: W/System.err(3666):     at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:210)
12-31 07:23:37.917: W/System.err(3666):     at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:477)
12-31 07:23:37.917: W/System.err(3666):     at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:441)
12-31 07:23:37.917: W/System.err(3666):     at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282)
12-31 07:23:37.917: W/System.err(3666):     at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232)
12-31 07:23:37.917: W/System.err(3666):     at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80)
12-31 07:23:37.917: W/System.err(3666):     at libcore.net.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:164)
12-31 07:23:37.917: W/System.err(3666):     at com.dsndata.sds2mobile.status.activities.ServerJobs$RetrieveJobNames.doInBackground(ServerJobs.java:143)
12-31 07:23:37.917: W/System.err(3666):     at com.dsndata.sds2mobile.status.activities.ServerJobs$RetrieveJobNames.doInBackground(ServerJobs.java:1)
12-31 07:23:37.917: W/System.err(3666):     at android.os.AsyncTask$2.call(AsyncTask.java:264)
12-31 07:23:37.925: W/System.err(3666):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
12-31 07:23:37.925: W/System.err(3666):     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
12-31 07:23:37.925: W/System.err(3666):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
12-31 07:23:37.925: W/System.err(3666):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
12-31 07:23:37.925: W/System.err(3666):     at java.lang.Thread.run(Thread.java:856)
12-31 07:23:37.925: W/System.err(3666): Caused by: javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0x16bab18: Failure in SSL library, usually a protocol error
12-31 07:23:37.925: W/System.err(3666): error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure (external/openssl/ssl/s3_pkt.c:1234 0x16bf980:0x00000003)
12-31 07:23:37.925: W/System.err(3666):     at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
12-31 07:23:37.925: W/System.err(3666):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:410)
12-31 07:23:37.925: W/System.err(3666):     ... 16 more
12-31 07:23:37.925: W/System.err(3666): javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0x16bab18: Failure in SSL library, usually a protocol error
12-31 07:23:37.925: W/System.err(3666): error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure (external/openssl/ssl/s3_pkt.c:1234 0x16bf980:0x00000003)
12-31 07:23:37.925: W/System.err(3666):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:460)
12-31 07:23:37.925: W/System.err(3666):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:257)
12-31 07:23:37.925: W/System.err(3666):     at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:210)
12-31 07:23:37.925: W/System.err(3666):     at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:477)
12-31 07:23:37.925: W/System.err(3666):     at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:441)
12-31 07:23:37.925: W/System.err(3666):     at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282)
12-31 07:23:37.925: W/System.err(3666):     at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232)
12-31 07:23:37.925: W/System.err(3666):     at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80)
12-31 07:23:37.925: W/System.err(3666):     at libcore.net.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:164)
12-31 07:23:37.925: W/System.err(3666):     at com.dsndata.sds2mobile.status.activities.ServerJobs$RetrieveJobNames.doInBackground(ServerJobs.java:143)
12-31 07:23:37.932: W/System.err(3666):     at com.dsndata.sds2mobile.status.activities.ServerJobs$RetrieveJobNames.doInBackground(ServerJobs.java:1)
12-31 07:23:37.932: W/System.err(3666):     at android.os.AsyncTask$2.call(AsyncTask.java:264)
12-31 07:23:37.932: W/System.err(3666):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
12-31 07:23:37.932: W/System.err(3666):     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
12-31 07:23:37.932: W/System.err(3666):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
12-31 07:23:37.932: W/System.err(3666):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
12-31 07:23:37.932: W/System.err(3666):     at java.lang.Thread.run(Thread.java:856)
12-31 07:23:37.932: W/System.err(3666): Caused by: javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0x16bab18: Failure in SSL library, usually a protocol error
12-31 07:23:37.932: W/System.err(3666): error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure (external/openssl/ssl/s3_pkt.c:1234 0x16bf980:0x00000003)
12-31 07:23:37.932: W/System.err(3666):     at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
12-31 07:23:37.932: W/System.err(3666):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:410)
12-31 07:23:37.932: W/System.err(3666):     ... 16 more

It should be noted that I am using the javax.net.ssl library and not the apache one.

EDIT: The python server is hosted on a Windows machine. Is there any extra configuration that needs to be taken into account for ssl on a Windows port?

EDIT: Yes, there is something that needs to be done to allow SSL on a windows port. Switched to port 443 (designated for SSL traffic) and am making (slow) progress.

EDIT: I am now able to track the request using Wireshark (I am learning a lot for this problem!) and Wireshark is telling me that there is a 405 error. Which in SSL means that the certificate format is not recognized. The python server is using PEM certificates (the only format allowed according to python docs) and the certificates imported into the keystore on the Android device are DER (to my knowledge the only format accepted by BKS).

Any help would be greatly appreciated.

like image 840
Lunchbox Avatar asked Jul 11 '26 07:07

Lunchbox


2 Answers

This can be a SSL/TLS version or algorithms mismatch error. Your server uses SSL v.2-3, while this is quite old and TLS 1.0-1.2 should be used. The best way to debug this is to run Wireshark, and see which client and server's SSL/TLS handshake packets are sent and when connection is dropped.

like image 179
Nickolay Olshevsky Avatar answered Jul 14 '26 02:07

Nickolay Olshevsky


After learning how to read the packets, it turns out that the issue was with my certificates. The common name was not matched to the URL.

like image 37
Lunchbox Avatar answered Jul 14 '26 01:07

Lunchbox