Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TLS: HostnameUnverifiedException in WebSocket.connectAsynchronously() #126

Open
or-else opened this issue Sep 18, 2017 · 5 comments
Open

Comments

@or-else
Copy link

or-else commented Sep 18, 2017

Android SDK version 25 in Android emulator.

I keep getting HostnameUnverifiedException thrown from SocketConnector.verifyHostname(SSLSocket socket, String hostname) at SocketConnector.java line 171 because OkHostnameVerifier.verify(String host, SSLSession session) returns false in SocketConnector.java line 164. That in turn happens because Certificate[] certificates = session.getPeerCertificates(); in OkHostnameVerifier.java line 64 throws javax.net.ssl.SSLPeerUnverifiedException: No peer certificate.

The culprit I believe is the call
SSLSession session = socket.getSession(); in SocketConnector.java line 161
Before the call the socket is connected:
Socket[address=api.tinode.co/104.196.16.37,port=443,localPort=54910]
during the call it gets closed:
Socket[unconnected] and the session is returned as com.android.org.conscrypt.SSLNullSession which obviously knows nothing about the host name.

The connection is created with the default socketFactory:

private static WebSocketFactory sWSFactory = new WebSocketFactory();
...
WebSocket ws = sWSFactory.createSocket(mEndpoint, CONNECTION_TIMEOUT); ws.addHeader(...);
ws.addListener(...);
...
ws.connectAsynchronously();

See full source here:
https://github.com/tinode/android-example/blob/devel/tinodesdk/src/main/java/co/tinode/tinodesdk/Connection.java

The host is secured with a Letsencrypt certificate which seems to be perfectly fine:
https://www.ssllabs.com/ssltest/analyze.html?d=api.tinode.co
It works fine in the browser in the same Android emulator. The websocket also works fine without the SSL.

What's going on? Is this a known issue?

Btw, because verifyHostname throws a custom HostnameUnverifiedException instead of re-throwing javax.net.ssl.SSLPeerUnverifiedException, it loses the stack trace and makes it a lot harder to debug the problem. For instance, instead of just posting the stack trace I have to write it up like this. What's the value in replacing SSLPeerUnverifiedException with a custom one?

@or-else
Copy link
Author

or-else commented Sep 18, 2017

OK, I figured it out. This is the same bug as #106

Golang's Letsencrypt implementation requires client to support SNI. Android's socket.getSession() starts handshake implicitly but does not expose exceptions if the handshake fails, just silently closes the socket (https://issuetracker.google.com/issues/37046928). The handshake fails because the server closes the connection because the client sends blank ServerName in ClientHello. And that happens because SNI is not supported as correctly pointed out in the #106

Any chance to have #106 fixed any time soon?

@or-else
Copy link
Author

or-else commented Sep 19, 2017

Beside the solution in PR #109 , another option is to add another method to WsSocketFactory which would take Socket is one of the parameters, like this:

https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLSocketFactory.html#createSocket(java.net.Socket,%20java.lang.String,%20int,%20boolean)

public abstract Socket createSocket(Socket s,
                  String host,
                  int port,
                  boolean autoClose)
                             throws IOException

This way I could provide my own properly configured socket.

This issue is a show stopper for me. Please talk to me. Let me know if this can be addressed any time soon.

@or-else
Copy link
Author

or-else commented Sep 19, 2017

@dajnz
Copy link

dajnz commented Jun 22, 2019

@or-else have you switched to any other library which can work properly with WSS websockets and Let's Encrypt certificates on back-end?

@or-else
Copy link
Author

or-else commented Jun 23, 2019

Yes, I've switched to https://github.com/TooTallNate/Java-WebSocket/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants