I have written an Android application using SMACK 4.3.4. Everything has been working great until today, when I started getting connection errors.
I am using a public, online XMPP server for my testing (chatserver.space). I have not to this point had to do anything with certificates. It all "just worked". So clearly there is some default certificate somewhere that has expired (see the Caused by: java.security.cert.CertPathValidatorException: timestamp check failed
portion of the stacktrace below), I just don't understand where it is and what I need to do to bump the date properly.
Here is the code from my app (standard SMACK connection stuff):
public void connect() throws Exception {
Timber.d("Lifecycle: XMPPConnectionMgr connect() attempted HOST: %s, PORT: %d, DOMAIN: %s", XMPP_HOST, XMPP_PORT, XMPP_DOMAIN);
if (xmppConnection == null) {
XMPPTCPConnectionConfiguration.Builder connConfigBuilder = XMPPTCPConnectionConfiguration.builder();
try {
connConfigBuilder
.setHost(XMPP_HOST) // Name of your Host
.setPort(XMPP_PORT) // Your Port for accepting c2s connection
.setXmppDomain(XMPP_DOMAIN)
.setSecurityMode(XMPPTCPConnectionConfiguration.SecurityMode.required);
xmppConnection = new XMPPTCPConnection(connConfigBuilder.build());
xmppConnection.addConnectionListener(this);
Set<String> blacklist = SASLAuthentication.getBlacklistedSASLMechanisms();
Timber.d("Lifecycle: Blacklist contents: %s", blacklist.toString());
Map<String,String> registered = SASLAuthentication.getRegisterdSASLMechanisms();
Timber.d("Lifecycle: registered SASLAuthentication mechanisms: %s", registered.toString());
} catch (XmppStringprepException e) {
Timber.d("XMPPConnectionMgr could not connect to XMPP Server: %s", e.getMessage());
throw new Exception(String.format(InTouch.getInstance().getApplicationContext().getString(R.string.exception_communications_connection),
e.getMessage()));
}
}
try {
if ( !xmppConnection.isConnected() ) {
xmppConnection.connect();
}
} catch (SmackException e) {
Timber.d("XMPPConnectionMgr got Exception trying to connect to XMPP Server: %s", e.getMessage());
throw new Exception(String.format(InTouch.getInstance().getApplicationContext().getString(R.string.exception_communications_connection),
e.getMessage()));
} catch (IOException e) {
Timber.d("XMPPConnectionMgr got IOException trying to connect to XMPP Server: %s", e.getMessage());
throw new Exception(String.format(InTouch.getInstance().getApplicationContext().getString(R.string.exception_communications_connection),
e.getMessage()));
} catch (XMPPException e) {
Timber.d("XMPPConnectionMgr got Exception trying to connect to XMPP Server: %s", e.getMessage());
throw new Exception(String.format(InTouch.getInstance().getApplicationContext().getString(R.string.exception_communications_connection),
e.getMessage()));
} catch (InterruptedException e) {
Timber.d("XMPPConnectionMgr got InterruptedException trying to connect to XMPP Server: %s", e.getMessage());
throw new Exception(String.format(InTouch.getInstance().getApplicationContext().getString(R.string.exception_communications_connection),
e.getMessage()));
}
}
The full stack trace is as follows:
2019-07-22 21:01:46.942 1511-1929/com.reddragon.intouch W/AbstractXMPPConnection: Connection XMPPTCPConnection[not-authenticated] (0) closed with error
javax.net.ssl.SSLHandshakeException: Chain validation failed
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:361)
at com.android.org.conscrypt.OpenSSLSocketImpl.waitForHandshake(OpenSSLSocketImpl.java:690)
at com.android.org.conscrypt.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:652)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnection.java:703)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:853)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$2000(XMPPTCPConnection.java:155)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:1171)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$1000(XMPPTCPConnection.java:1092)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:1112)
at java.lang.Thread.run(Thread.java:764)
Caused by: java.security.cert.CertificateException: Chain validation failed
at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:788)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:612)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:633)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:678)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:499)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:422)
at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:343)
at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:88)
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:203)
at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:607)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
at com.android.org.conscrypt.OpenSSLSocketImpl.waitForHandshake(OpenSSLSocketImpl.java:690)
at com.android.org.conscrypt.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:652)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnection.java:703)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:853)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$2000(XMPPTCPConnection.java:155)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:1171)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$1000(XMPPTCPConnection.java:1092)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:1112)
at java.lang.Thread.run(Thread.java:764)
Caused by: java.security.cert.CertPathValidatorException: timestamp check failed
at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:133)
at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:225)
at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:143)
at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:79)
at com.android.org.conscrypt.DelegatingCertPathValidator.engineValidate(DelegatingCertPathValidator.java:44)
at java.security.cert.CertPathValidator.validate(CertPathValidator.java:301)
at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:784)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:612)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:633)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:678)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:499)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:422)
at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:343)
at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:88)
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:203)
at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:607)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
at com.android.org.conscrypt.OpenSSLSocketImpl.waitForHandshake(OpenSSLSocketImpl.java:690)
at com.android.org.conscrypt.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:652)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnection.java:703)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:853)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$2000(XMPPTCPConnection.java:155)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:1171)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$1000(XMPPTCPConnection.java:1092)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:1112)
at java.lang.Thread.run(Thread.java:764)
Caused by: java.security.cert.CertificateExpiredException: Certificate expired at Mon Jul 22 12:04:58 MDT 2019 (compared to Mon Jul 22 21:01:46 MDT 2019)
at com.android.org.conscrypt.OpenSSLX509Certificate.checkValidity(OpenSSLX509Certificate.java:244)
at sun.security.provider.certpath.BasicChecker.verifyTimestamp(BasicChecker.java:194)
at sun.security.provider.certpath.BasicChecker.check(BasicChecker.java:144)
at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:125)
at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:225)
at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:143)
at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:79)
at com.android.org.conscrypt.DelegatingCertPathValidator.engineValidate(DelegatingCertPathValidator.java:44)
at java.security.cert.CertPathValidator.validate(CertPathValidator.java:301)
at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:784)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:612)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:633)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:678)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:499)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:422)
at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:343)
at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:88)
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:203)
at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:607)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
at com.android.org.conscrypt.OpenSSLSocketImpl.waitForHandshake(OpenSSLSocketImpl.java:690)
at com.android.org.conscrypt.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:652)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnection.java:703)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:853)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$2000(XMPPTCPConnection.java:155)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:1171)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$1000(XMPPTCPConnection.java:1092)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:1112)
at java.lang.Thread.run(Thread.java:764)
Looking at the output of openssl
:
wojtek@atlantiscity.local ~ $ openssl s_client -connect xmpp.chatserver.space:5222 -xmpphost chatserver.space < /dev/null -starttls xmpp | openssl x509 -noout -dates
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = chatserver.space
verify return:1
poll error
notBefore=Jul 22 06:45:13 2019 GMT
notAfter=Oct 20 06:45:13 2019 GMT
It looks like they just renewed their certificate, so most likely you were served outdated certificate from the server (as would CertPathValidatorException: timestamp check failed
indicate). Unfortunately you can't do anything in this case - server owner has to update the certificate on the server.
You could circumvent certificate verification but *THIS IS VERY, HIGHLY DISCOURAGED* (thus I won't go into details how to do it)