Smack 4.4.0-alpha library uses serviceName instead of FQDN DomainName when requesting TLS certificate from ejabberd server

When aTalk v2.3.1 release upgraded to use smack-4.4.0-alpha5 library, it is found that aTalk client login to server failed when the sever-overridden option is enabled e.g. swordfish@atalk.org where atalk.org is the client virtual host service running on host with FQDN atalk.sytes.net (server-overridden). This problem seems to happen on all smack-4.4.0 alpha releases, but reveal as login failure only in smack-4.4.0-alpha5 due to ------------------Untrusted chain: ----------------------. Actually this problem also happen in aTalk v2.3.0 release with alpha3 library, but smack ignores and proceed as normal to have a successful login.

This problem also happen in smack 4.2.3 which has already been fixed. Please see:
a. Smack 4.2.3 always uses HostName instead of DomainName when requesting TLS certificate from ejabberd server
b. Smack uses hostname instead of XMPP service name for SNI

Previously, aTalk only need to add config.setHost(FQDN) to compliment the solution.

From the smack alpha5 source. config.getXMPPServiceDomain() always refers to the service name.
I did a quick verification to confirm the observation by using config.setXmppDomain(FQDN);
This seems to “resolve” the problem; but believe this is not the right approach.

Any advice on solution?

========= aTalk debug log =============
2020-07-22 23:24:21.982 8686-8943/org.atalk.android D/SMACK: SENT (0): 
    <stream:stream xmlns='jabber:client' to='atalk.org' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' xml:lang='en'>
2020-07-22 23:24:21.997 8686-8944/org.atalk.android D/SMACK: RECV (0): ?xml version='1.0'?>
    <stream:stream id='3652220486897623538' version='1.0' xml:lang='en' xmlns:stream='http://etherx.jabber.org/streams' from='atalk.org' xmlns='jabber:client'>
2020-07-22 23:24:22.003 8686-8944/org.atalk.android D/SMACK: RECV (0): 
    <stream:features>
      <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>
        <required/>
      </starttls>
    </stream:features>
2020-07-22 23:24:22.008 8686-8943/org.atalk.android D/SMACK: SENT (0): 
    <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
2020-07-22 23:24:22.015 8686-8944/org.atalk.android D/SMACK: RECV (0): 
    <proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
2020-07-22 23:24:22.215 8686-8944/org.atalk.android E/CONSCRYPT: ------------------Untrusted chain: ----------------------
2020-07-22 23:24:22.215 8686-8944/org.atalk.android E/CONSCRYPT: == Chain0 == 
     Version:   3
2020-07-22 23:24:22.216 8686-8944/org.atalk.android E/CONSCRYPT:  Serial Number:   fac884d4c609a3d1
2020-07-22 23:24:22.217 8686-8944/org.atalk.android E/CONSCRYPT:  SubjectDN:   CN=atalk.org
2020-07-22 23:24:22.217 8686-8944/org.atalk.android E/CONSCRYPT:  IssuerDN:   CN=atalk.org
2020-07-22 23:24:22.278 8686-8944/org.atalk.android E/CONSCRYPT:  Get not before:   Sat Dec 26 09:07:16 GMT+08:00 2015
2020-07-22 23:24:22.289 8686-8944/org.atalk.android E/CONSCRYPT:  Get not after:   Tue Dec 23 09:07:16 GMT+08:00 2025
2020-07-22 23:24:22.289 8686-8944/org.atalk.android E/CONSCRYPT:  Sig ALG name:   SHA256WITHRSA
2020-07-22 23:24:22.298 8686-8944/org.atalk.android E/CONSCRYPT:  Signature:   4b17767fb81d53486c05e8d3fe140bc9d33699aef9c9fb6e5aaf87dec6e48b2184bb7a13692c2b813a33b1c1fdc8dd504466a92585aee513a074bf990a128ceca2681e1d33f5b677712dc1fe94048b172d50a3ee1710fb7513934682bbea4275ea50575280f4716e86b9f2d0614dd645d3f169d551ba4a5d77423ea9b91df93e733184d0b82a537bdcc36b25d6430a52bf3c90f17bd95dcc6eeb62c140f181e9ab9f7caf16a129e57e538d9d07f2d78d84089c1c345616115bde6de8742b985b771f63763bd4bc95d5e31bd8932836cdc1cfa76e76b7c0b9c55583795997eca6e4ba0b2cfce8dc94d11331cb3cc50eb8320bc1af9be606834ac57fe49ac17ebc
2020-07-22 23:24:22.442 8686-8944/org.atalk.android E/CONSCRYPT:  Public key:
     
     30 82 01 22 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03
     82 01 0f 00 30 82 01 0a 02 82 01 01 00 e1 ed fc 01 59 35 a0
     0e 59 d1 7a 4c f7 77 66 af 0d fb b3 9f 2d 49 75 7f b7 02 3b
     dc 26 2b 98 21 48 f1 dc 8a 9c e5 f7 86 59 aa ac 23 a3 ee ff
     d4 95 28 20 63 24 32 df 2f 2f 14 22 92 e7 dc 5d d1 23 8b b5
     b9 29 a9 94 20 b5 8b 5c 81 91 42 17 b8 bf e5 9e 97 ca 95 60
     0e 2a aa 67 b9 cc ed 84 7a 3c d1 2c 60 30 02 e0 c2 94 76 75
     d7 f2 26 10 87 2e a8 9a 98 ff 3a da c3 65 08 b2 ab 35 22 9c
     8c ff 83 0c ba 3d ec d4 21 6c b1 b4 5b 94 3a 28 d8 a0 e2 9b
     16 66 fc 01 00 85 92 db 77 2e 0e 96 85 27 4d b8 39 e3 8e 18
     4f ef cb 0e 88 09 b1 38 6a 3e 27 d6 68 ec 98 82 2d 4b 93 cc
     9f 50 78 47 c1 1d 7b dd 68 ad 83 15 33 1c e3 f7 34 99 fb fe
     09 2e 72 9d 59 c7 32 81 c4 f6 1f 44 db e8 57 ad 75 5a 26 7f
     34 a6 a1 45 92 1c b9 33 d2 9d 50 7f 41 45 86 6c 10 61 c4 d6
     7c fb 8f a6 31 37 71 5d ef 02 03 01 00 01
2020-07-22 23:24:22.460 8686-8944/org.atalk.android I/aTalk: [149676] org.jivesoftware.smack.AbstractXMPPConnection.notifyConnectionError() Connection was already disconnected when attempting to handle javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
    javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:239)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.waitForHandshake(ConscryptFileDescriptorSocket.java:510)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.getInputStream(ConscryptFileDescriptorSocket.java:473)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnection.java:676)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:714)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$1400(XMPPTCPConnection.java:130)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:972)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$700(XMPPTCPConnection.java:898)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:921)
        at java.lang.Thread.run(Thread.java:919)
     Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:688)
        at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:557)
        at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:513)
        at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:432)
        at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:360)
        at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
        at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:89)
        at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:224)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.verifyCertificateChain(ConscryptFileDescriptorSocket.java:430)
        at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
        at com.android.org.conscrypt.NativeSsl.doHandshake(NativeSsl.java:387)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:234)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.waitForHandshake(ConscryptFileDescriptorSocket.java:510) 
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.getInputStream(ConscryptFileDescriptorSocket.java:473) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnection.java:676) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:714) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$1400(XMPPTCPConnection.java:130) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:972) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$700(XMPPTCPConnection.java:898) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:921) 
        at java.lang.Thread.run(Thread.java:919) 
     Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:688) 
        at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:557) 
        at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:513) 
        at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:432) 
        at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:360) 
        at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94) 
        at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:89) 
        at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:224) 
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.verifyCertificateChain(ConscryptFileDescriptorSocket.java:430) 
        at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) 
        at com.android.org.conscrypt.NativeSsl.doHandshake(NativeSsl.java:387) 
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:234) 
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.waitForHandshake(ConscryptFileDescriptorSocket.java:510) 
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.getInputStream(ConscryptFileDescriptorSocket.java:473) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnection.java:676) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:714) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$1400(XMPPTCPConnection.java:130) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:972) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$700(XMPPTCPConnection.java:898) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:921) 
        at java.lang.Thread.run(Thread.java:919)

How does the server certificate look like?

How does the server certificate look like?
See attached

x509_cert.html (4.7 KB)

More info added:
Actually the unsuccessful login was reported by aTalk user using aTalk v2.3.1 (smack-4.4.0-alpha5):
the user account fails to connect to the Openfire server in the new version 2.3.1 #158

Below is the debug log for aTalk v2.3.0. Actually the
-----------------Untrusted chain: ----------------------
also occurred; however smack proceed to login and is successful.

I am not sure how far back the problem has started, ad for which smack version; after the fixed was introduced since smack v4.2.3.

=========== aTalk v2.3.0 (smack 4.4.0-alpha3) debug log ============
2020-07-22 23:14:11.896 1281-1437/org.atalk.android D/SMACK: RECV (0): ?xml version='1.0'?>
    <stream:stream id='4799655983325539208' version='1.0' xml:lang='en' xmlns:stream='http://etherx.jabber.org/streams' from='atalk.org' xmlns='jabber:client'>
    <stream:features>
      <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>
        <required/>
      </starttls>
    </stream:features>
2020-07-22 23:14:11.906 1281-1436/org.atalk.android D/SMACK: SENT (0): 
    <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
2020-07-22 23:14:11.922 1281-1437/org.atalk.android D/SMACK: RECV (0): 
    <proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
2020-07-22 23:14:11.935 1281-1437/org.atalk.android D/libmdf: libmdf v2.9.0.0 On 64bit PLATFORM
2020-07-22 23:14:12.179 1281-1437/org.atalk.android E/CONSCRYPT: ------------------Untrusted chain: ----------------------
2020-07-22 23:14:12.179 1281-1437/org.atalk.android E/CONSCRYPT: == Chain0 == 
     Version:   3
2020-07-22 23:14:12.179 1281-1437/org.atalk.android E/CONSCRYPT:  Serial Number:   fac884d4c609a3d1
2020-07-22 23:14:12.180 1281-1437/org.atalk.android E/CONSCRYPT:  SubjectDN:   CN=atalk.org
2020-07-22 23:14:12.181 1281-1437/org.atalk.android E/CONSCRYPT:  IssuerDN:   CN=atalk.org
2020-07-22 23:14:12.253 1281-1437/org.atalk.android E/CONSCRYPT:  Get not before:   Sat Dec 26 09:07:16 GMT+08:00 2015
2020-07-22 23:14:12.264 1281-1437/org.atalk.android E/CONSCRYPT:  Get not after:   Tue Dec 23 09:07:16 GMT+08:00 2025
2020-07-22 23:14:12.264 1281-1437/org.atalk.android E/CONSCRYPT:  Sig ALG name:   SHA256WITHRSA
2020-07-22 23:14:12.272 1281-1437/org.atalk.android E/CONSCRYPT:  Signature:   4b17767fb81d53486c05e8d3fe140bc9d33699aef9c9fb6e5aaf87dec6e48b2184bb7a13692c2b813a33b1c1fdc8dd504466a92585aee513a074bf990a128ceca2681e1d33f5b677712dc1fe94048b172d50a3ee1710fb7513934682bbea4275ea50575280f4716e86b9f2d0614dd645d3f169d551ba4a5d77423ea9b91df93e733184d0b82a537bdcc36b25d6430a52bf3c90f17bd95dcc6eeb62c140f181e9ab9f7caf16a129e57e538d9d07f2d78d84089c1c345616115bde6de8742b985b771f63763bd4bc95d5e31bd8932836cdc1cfa76e76b7c0b9c55583795997eca6e4ba0b2cfce8dc94d11331cb3cc50eb8320bc1af9be606834ac57fe49ac17ebc
2020-07-22 23:14:12.385 1281-1437/org.atalk.android E/CONSCRYPT:  Public key:
     
     30 82 01 22 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03
     82 01 0f 00 30 82 01 0a 02 82 01 01 00 e1 ed fc 01 59 35 a0
     0e 59 d1 7a 4c f7 77 66 af 0d fb b3 9f 2d 49 75 7f b7 02 3b
     dc 26 2b 98 21 48 f1 dc 8a 9c e5 f7 86 59 aa ac 23 a3 ee ff
     d4 95 28 20 63 24 32 df 2f 2f 14 22 92 e7 dc 5d d1 23 8b b5
     b9 29 a9 94 20 b5 8b 5c 81 91 42 17 b8 bf e5 9e 97 ca 95 60
     0e 2a aa 67 b9 cc ed 84 7a 3c d1 2c 60 30 02 e0 c2 94 76 75
     d7 f2 26 10 87 2e a8 9a 98 ff 3a da c3 65 08 b2 ab 35 22 9c
     8c ff 83 0c ba 3d ec d4 21 6c b1 b4 5b 94 3a 28 d8 a0 e2 9b
     16 66 fc 01 00 85 92 db 77 2e 0e 96 85 27 4d b8 39 e3 8e 18
     4f ef cb 0e 88 09 b1 38 6a 3e 27 d6 68 ec 98 82 2d 4b 93 cc
     9f 50 78 47 c1 1d 7b dd 68 ad 83 15 33 1c e3 f7 34 99 fb fe
     09 2e 72 9d 59 c7 32 81 c4 f6 1f 44 db e8 57 ad 75 5a 26 7f
     34 a6 a1 45 92 1c b9 33 d2 9d 50 7f 41 45 86 6c 10 61 c4 d6
     7c fb 8f a6 31 37 71 5d ef 02 03 01 00 01
2020-07-22 23:14:12.426 1281-1436/org.atalk.android D/SMACK: SENT (0): 
    <stream:stream xmlns='jabber:client' to='atalk.org' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' xml:lang='en'>
2020-07-22 23:14:12.437 1281-1437/org.atalk.android D/SMACK: RECV (0): ?xml version='1.0'?>
    <stream:stream id='14985251048368901923' version='1.0' xml:lang='en' xmlns:stream='http://etherx.jabber.org/streams' from='atalk.org' xmlns='jabber:client'>
2020-07-22 23:14:12.445 1281-1437/org.atalk.android D/SMACK: RECV (0): 
    <stream:features>
      <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
        <mechanism>
          EXTERNAL
        </mechanism>
        <mechanism>
          PLAIN
        </mechanism>
        <mechanism>
          SCRAM-SHA-1
        </mechanism>
        <mechanism>
          X-OAUTH2
        </mechanism>
      </mechanisms>
      <register xmlns='http://jabber.org/features/iq-register'/>
    </stream:features>
2020-07-22 23:14:12.818 1281-1436/org.atalk.android D/SMACK: SENT (0): 
    <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='SCRAM-SHA-1'>
      bixhPXN3b3JkZmlzaEBhdGFsay5vcmcsbj1zd29yZGZpc2gscj1gMXNeQ0gmKStmYiJNKCUhK15AIWhYe2JSaTxeT0ckPQ==
    </auth>
2020-07-22 23:14:12.872 1281-1437/org.atalk.android D/SMACK: RECV (0): 
    <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
      cj1gMXNeQ0gmKStmYiJNKCUhK15AIWhYe2JSaTxeT0ckPVhOUCt5a1dVTEFjdjlPQkZOQmtkRVE9PSxzPTVXVENHSnk1dk1FUWJpNmZWRVJ1S0E9PSxpPTQwOTY=
    </challenge>
2020-07-22 23:14:13.655 1281-1436/org.atalk.android D/SMACK: SENT (0): 
    <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
      Yz1iaXhoUFhOM2IzSmtabWx6YUVCaGRHRnNheTV2Y21jcyxyPWAxc15DSCYpK2ZiIk0oJSErXkAhaFh7YlJpPF5PRyQ9WE5QK3lrV1VMQWN2OU9CRk5Ca2RFUT09LHA9dVRlMVBUdVoyaW4rN3hxblV2UGtuRytFQ3JFPQ==
    </response>
2020-07-22 23:14:13.686 1281-1437/org.atalk.android D/SMACK: RECV (0): 
    <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
      dj1wMFU5MTlUZUFtZHJ4RTk4Y2xoaUlXdldETEE9
    </success>

Actually atalk.org is only a virtual host without any public IP; ejabberd server supports virtual host ‘atalk.org’ xmpp service. The ejabberd server is running on the physical host atalk.sytes.net with a valid FQDN.

atalk.sytes.net has a public ip and its certificate is provided by let’s encrypt; the certificate for atalk.org is only a self-signed certificate, hence result to Untrusted chain.

My thinking is that certificate validation should be performed on the physical connected device i.e. atalk.sytes.net. Unless smack enforces the certificate validation is on each service resides on the host, then the observation it is a normal behavior.

Actually ejaberd gives warning on self-signed certificates:

14:20:52.222 [warning] Invalid certificate in /usr/local/etc/ejabberd/ssl_cert/atalk.org.pem: at line 29: self-signed certificate
14:20:52.224 [warning] No certificate found matching 'upload.atalk.sytes.net': strictly configured clients or servers will reject connections with this host; obtain a certificate for this (sub)domain from any trusted CA such as Let's Encrypt (www.letsencrypt.org)
14:20:52.224 [warning] No certificate found matching 'conference.atalk.sytes.net': strictly configured clients or servers will reject connections with this host; obtain a certificate for this (sub)domain from any trusted CA such as Let's Encrypt (www.letsencrypt.org)
14:20:52.224 [warning] No certificate found matching 'pubsub.atalk.org': strictly configured clients or servers will reject connections with this host; obtain a certificate for this (sub)domain from any trusted CA such as Let's Encrypt (www.letsencrypt.org)
14:20:52.224 [warning] No certificate found matching 'proxy.atalk.sytes.net': strictly configured clients or servers will reject connections with this host; obtain a certificate for this (sub)domain from any trusted CA such as Let's Encrypt (www.letsencrypt.org)
14:20:52.224 [warning] No certificate found matching 'pubsub.atalk.sytes.net': strictly configured clients or servers will reject connections with this host; obtain a certificate for this (sub)domain from any trusted CA such as Let's Encrypt (www.letsencrypt.org)
14:20:52.224 [warning] No certificate found matching 'proxy.atalk.org': strictly configured clients or servers will reject connections with this host; obtain a certificate for this (sub)domain from any trusted CA such as Let's Encrypt (www.letsencrypt.org)
14:20:52.225 [warning] No certificate found matching 'conference.atalk.org': strictly configured clients or servers will reject connections with this host; obtain a certificate for this (sub)domain from any trusted CA such as Let's Encrypt (www.letsencrypt.org)
14:20:52.225 [warning] No certificate found matching 'upload.atalk.org': strictly configured clients or servers will reject connections with this host; obtain a certificate for this (sub)domain from any trusted CA such as Let's Encrypt (www.letsencrypt.org)

No, this would allow anyone to impersonate the XMPP service for atalk.org and hence render verification meaningless. But it is a common misconception when it comes to certificate verification.

You want to certificate that has atalk.org SRV-ID. See also RFC 6120 - Extensible Messaging and Presence Protocol (XMPP): Core

Yes, actually I was also thinking my early comment is not correct.
aTalk has already implemented SRV-ID. So I did a re-check on aTalk v2.3.0 and v2.3.1.

On aTalk v2.3.0 (smack-4.4.0-alpha3), it will pop-up a prompt requesting user to verify and accept if a self-signed certificate is detected, as shown in the snapshot below.

However in aTalk v2.3.1 (smack 4.4.0-alpah5), under the same test condition, there is no such prompt. Seems like calback for user certificate verification is not triggered.

There was no change in aTalk source in this area between v2.3.0 and v2.3.1; so the problem seems to be smack new implementation in alpha5. Any advice?

image

Follow the trail from the prompt backwards, i.e., what triggers the appearance of the prompt. Look how it is wired with Smack internals (since the prompt is caused by something within the SSLContext’s certification verification routine). The determine what make it work with -alpha3, and what is missing in -alpha5.

I was hoping you can give a quick solution, as I saw that there is some major changes in the ConnecitonConfiguration. I will do the debug and update you. FYI:

aTalk has the following implementation using custom SSLContext for SSL connection.

            CertificateService cvs = getCertificateVerificationService();
            if (cvs != null) {
                try {
                    X509TrustManager sslTrustManager = getTrustManager(cvs, serviceName);
                    SSLContext sslContext = loginStrategy.createSslContext(cvs, sslTrustManager);
                    SslContextFactory sslContextFactory = () -> sslContext;

                    config.setSslContextFactory(sslContextFactory);
                    config.setAuthzid(mAccountID.getBareJid().asEntityBareJidIfPossible());

                } catch (GeneralSecurityException e) {
                    Timber.e(e, "Error creating custom trust manager");
                    // StanzaError stanzaError = StanzaError.getBuilder(Condition.service_unavailable).build();
                    throw new ATalkXmppException("Security-Exception: Creating custom TrustManager", e);
                }
            }

where sslTrustManager implements X509TrustManager to catch the CertificateException to show the user prompt.

        /**
         * Check whether a certificate is trusted, if not ask user whether he trusts it.
         *
         * @param chain the certificate chain.
         * @param authType authentication type like: RSA.
         * @throws CertificateException not trusted.
         */
        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException
        {
            abortConnecting = true;
            try {
                tm.checkServerTrusted(chain, authType);
            } catch (CertificateException e) {
                // notify in a separate thread to avoid a deadlock when a reg state listener
                // accesses a synchronized XMPPConnection method (like getRoster)
                new Thread(() -> fireRegistrationStateChanged(getRegistrationState(),
                        RegistrationState.UNREGISTERED, RegistrationStateChangeEvent.REASON_USER_REQUEST,
                        "Not trusted certificate")).start();
                throw e;
            }

            if (abortConnecting) {
                // connect hasn't finished we will continue normally
                abortConnecting = false;
            }
            else {
                // in this situation connect method has finished and it was disconnected so we
                // wont to connect. register.connect in new thread so we can release the current
                // connecting thread, otherwise this blocks jabber
                new Thread(() -> reRegister(SecurityAuthority.CONNECTION_FAILED, null)).start();
            }
        }

Problem resolved.
Under smack-4.4.0-alpha5, it is also required to

config.setCustomX509TrustManager(sslTrustManager);

in additional to:

config.setSslContextFactory(sslContextFactory);

even the sslTrustManager is already passed in sslContextFactory

           CertificateService cvs = getCertificateVerificationService();
            if (cvs != null) {
                try {
                    X509TrustManager sslTrustManager = getTrustManager(cvs, serviceName);
                    SSLContext sslContext = loginStrategy.createSslContext(cvs, sslTrustManager);
                    SslContextFactory sslContextFactory = () -> sslContext;

                    config.setSslContextFactory(sslContextFactory);
                    config.setCustomX509TrustManager(sslTrustManager);
                    config.setAuthzid(mAccountID.getBareJid().asEntityBareJidIfPossible());

                } catch (GeneralSecurityException e) {
                    Timber.e(e, "Error creating custom trust manager");
                    // StanzaError stanzaError = StanzaError.getBuilder(Condition.service_unavailable).build();
                    throw new ATalkXmppException("Security-Exception: Creating custom TrustManager", e);
                }
            }

Factories are expected to manufactor new instances every time their factory method is called (createSslContext()). Possible that it does not make any difference in your case, but what you really want is

SslContextFactory sslContextFactory = () -> return loginStrategy.createSslContext(cvs, sslTrustManager);

I tried your recommendation, it is not working. What I see in smack 4.4.0-alpha5 release, there is a change in getSmackTlsContext() where customX509TrustManager is one of the pass-in parameters, and it get included in the list of TrustManager. So doing

config.setCustomX509TrustManager(sslTrustManager);

may be is the safer thing to do for future aTalk releases (even for alpha3 release).

  smackTlsContext = getSmackTlsContext(builder.dnssecMode, builder.sslContextFactory,
            builder.customX509TrustManager, builder.keystoreType, builder.keystorePath,
            builder.callbackHandler, builder.pkcs11Library);

From the below two debug logs for aTalk v2.3.0 (smack-4.4.0-alpha3) and aTalk v2.3.1 (smack-4.4.0-alpha5); it is found that there is a change in the CertificateException order. In v2.3.0, aTalk is given the chance to handle the CertificateException i.e. HostTrustManager.checkServerTrusted(), but not in v2.3.1; smack handles the CertificateException instead.

============ aTalk debug log (smack 4.4.0-alpha3) ============ 

2020-07-24 07:48:54.540 28555-28835/org.atalk.android E/(ProtocolProviderServiceJabberImpl.java:2763)#checkServerTrusted: java.lang.Exception: TSL Certificate Invalid
        at net.java.sip.communicator.impl.protocol.jabber.ProtocolProviderServiceJabberImpl$HostTrustManager.checkServerTrusted(ProtocolProviderServiceJabberImpl.java:2763)
        at net.java.sip.communicator.impl.protocol.jabber.ProtocolProviderServiceJabberImpl$HostTrustManager.checkServerTrusted(ProtocolProviderServiceJabberImpl.java:2733)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.org.conscrypt.Platform.checkTrusted(Platform.java:196)
        at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:225)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.verifyCertificateChain(ConscryptFileDescriptorSocket.java:430)
        at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
        at com.android.org.conscrypt.NativeSsl.doHandshake(NativeSsl.java:387)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:234)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.waitForHandshake(ConscryptFileDescriptorSocket.java:510)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.getInputStream(ConscryptFileDescriptorSocket.java:473)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnection.java:671)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:715)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$1200(XMPPTCPConnection.java:136)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:969)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$300(XMPPTCPConnection.java:893)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:913)
        at java.lang.Thread.run(Thread.java:919)
2020-07-24 07:48:54.676 28555-28835/org.atalk.android E/CONSCRYPT: ------------------Untrusted chain: ----------------------
2020-07-24 07:48:54.676 28555-28835/org.atalk.android E/CONSCRYPT: == Chain0 == 
     Version:   3
2020-07-24 07:48:54.676 28555-28835/org.atalk.android E/CONSCRYPT:  Serial Number:   fac884d4c609a3d1
2020-07-24 07:48:54.677 28555-28835/org.atalk.android E/CONSCRYPT:  SubjectDN:   CN=atalk.org
2020-07-24 07:48:54.678 28555-28835/org.atalk.android E/CONSCRYPT:  IssuerDN:   CN=atalk.org
2020-07-24 07:48:54.775 28555-28835/org.atalk.android E/CONSCRYPT:  Get not before:   Sat Dec 26 09:07:16 GMT+08:00 2015
2020-07-24 07:48:54.785 28555-28574/org.atalk.android W/System: A resource failed to call close. 
2020-07-24 07:48:54.800 28555-28835/org.atalk.android E/CONSCRYPT:  Get not after:   Tue Dec 23 09:07:16 GMT+08:00 2025
2020-07-24 07:48:54.800 28555-28835/org.atalk.android E/CONSCRYPT:  Sig ALG name:   SHA256WITHRSA
2020-07-24 07:48:54.820 28555-28835/org.atalk.android E/CONSCRYPT:  Signature:   4b17767fb81d53486c05e8d3fe140bc9d33699aef9c9fb6e5aaf87dec6e48b2184bb7a13692c2b813a33b1c1fdc8dd504466a92585aee513a074bf990a128ceca2681e1d33f5b677712dc1fe94048b172d50a3ee1710fb7513934682bbea4275ea50575280f4716e86b9f2d0614dd645d3f169d551ba4a5d77423ea9b91df93e733184d0b82a537bdcc36b25d6430a52bf3c90f17bd95dcc6eeb62c140f181e9ab9f7caf16a129e57e538d9d07f2d78d84089c1c345616115bde6de8742b985b771f63763bd4bc95d5e31bd8932836cdc1cfa76e76b7c0b9c55583795997eca6e4ba0b2cfce8dc94d11331cb3cc50eb8320bc1af9be606834ac57fe49ac17ebc
2020-07-24 07:48:54.918 28555-28835/org.atalk.android E/CONSCRYPT:  Public key:
     
     30 82 01 22 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03
     82 01 0f 00 30 82 01 0a 02 82 01 01 00 e1 ed fc 01 59 35 a0
     0e 59 d1 7a 4c f7 77 66 af 0d fb b3 9f 2d 49 75 7f b7 02 3b
     dc 26 2b 98 21 48 f1 dc 8a 9c e5 f7 86 59 aa ac 23 a3 ee ff
     d4 95 28 20 63 24 32 df 2f 2f 14 22 92 e7 dc 5d d1 23 8b b5
     b9 29 a9 94 20 b5 8b 5c 81 91 42 17 b8 bf e5 9e 97 ca 95 60
     0e 2a aa 67 b9 cc ed 84 7a 3c d1 2c 60 30 02 e0 c2 94 76 75
     d7 f2 26 10 87 2e a8 9a 98 ff 3a da c3 65 08 b2 ab 35 22 9c
     8c ff 83 0c ba 3d ec d4 21 6c b1 b4 5b 94 3a 28 d8 a0 e2 9b
     16 66 fc 01 00 85 92 db 77 2e 0e 96 85 27 4d b8 39 e3 8e 18
     4f ef cb 0e 88 09 b1 38 6a 3e 27 d6 68 ec 98 82 2d 4b 93 cc
     9f 50 78 47 c1 1d 7b dd 68 ad 83 15 33 1c e3 f7 34 99 fb fe
     09 2e 72 9d 59 c7 32 81 c4 f6 1f 44 db e8 57 ad 75 5a 26 7f
     34 a6 a1 45 92 1c b9 33 d2 9d 50 7f 41 45 86 6c 10 61 c4 d6
     7c fb 8f a6 31 37 71 5d ef 02 03 01 00 01

============ aTalk debug log (smack 4.4.0-alpha5) ============ 
2020-07-24 08:06:25.817 388-739/org.atalk.android E/CONSCRYPT: ------------------Untrusted chain: ----------------------
2020-07-24 08:06:25.818 388-739/org.atalk.android E/CONSCRYPT: == Chain0 == 
     Version:   3
2020-07-24 08:06:25.818 388-739/org.atalk.android E/CONSCRYPT:  Serial Number:   fac884d4c609a3d1
2020-07-24 08:06:25.819 388-739/org.atalk.android E/CONSCRYPT:  SubjectDN:   CN=atalk.org
2020-07-24 08:06:25.819 388-739/org.atalk.android E/CONSCRYPT:  IssuerDN:   CN=atalk.org
2020-07-24 08:06:25.885 388-739/org.atalk.android E/CONSCRYPT:  Get not before:   Sat Dec 26 09:07:16 GMT+08:00 2015
2020-07-24 08:06:25.896 388-739/org.atalk.android E/CONSCRYPT:  Get not after:   Tue Dec 23 09:07:16 GMT+08:00 2025
2020-07-24 08:06:25.896 388-739/org.atalk.android E/CONSCRYPT:  Sig ALG name:   SHA256WITHRSA
2020-07-24 08:06:25.905 388-739/org.atalk.android E/CONSCRYPT:  Signature:   4b17767fb81d53486c05e8d3fe140bc9d33699aef9c9fb6e5aaf87dec6e48b2184bb7a13692c2b813a33b1c1fdc8dd504466a92585aee513a074bf990a128ceca2681e1d33f5b677712dc1fe94048b172d50a3ee1710fb7513934682bbea4275ea50575280f4716e86b9f2d0614dd645d3f169d551ba4a5d77423ea9b91df93e733184d0b82a537bdcc36b25d6430a52bf3c90f17bd95dcc6eeb62c140f181e9ab9f7caf16a129e57e538d9d07f2d78d84089c1c345616115bde6de8742b985b771f63763bd4bc95d5e31bd8932836cdc1cfa76e76b7c0b9c55583795997eca6e4ba0b2cfce8dc94d11331cb3cc50eb8320bc1af9be606834ac57fe49ac17ebc
2020-07-24 08:06:25.999 388-739/org.atalk.android E/CONSCRYPT:  Public key:
     
     30 82 01 22 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03
     82 01 0f 00 30 82 01 0a 02 82 01 01 00 e1 ed fc 01 59 35 a0
     0e 59 d1 7a 4c f7 77 66 af 0d fb b3 9f 2d 49 75 7f b7 02 3b
     dc 26 2b 98 21 48 f1 dc 8a 9c e5 f7 86 59 aa ac 23 a3 ee ff
     d4 95 28 20 63 24 32 df 2f 2f 14 22 92 e7 dc 5d d1 23 8b b5
     b9 29 a9 94 20 b5 8b 5c 81 91 42 17 b8 bf e5 9e 97 ca 95 60
     0e 2a aa 67 b9 cc ed 84 7a 3c d1 2c 60 30 02 e0 c2 94 76 75
     d7 f2 26 10 87 2e a8 9a 98 ff 3a da c3 65 08 b2 ab 35 22 9c
     8c ff 83 0c ba 3d ec d4 21 6c b1 b4 5b 94 3a 28 d8 a0 e2 9b
     16 66 fc 01 00 85 92 db 77 2e 0e 96 85 27 4d b8 39 e3 8e 18
     4f ef cb 0e 88 09 b1 38 6a 3e 27 d6 68 ec 98 82 2d 4b 93 cc
     9f 50 78 47 c1 1d 7b dd 68 ad 83 15 33 1c e3 f7 34 99 fb fe
     09 2e 72 9d 59 c7 32 81 c4 f6 1f 44 db e8 57 ad 75 5a 26 7f
     34 a6 a1 45 92 1c b9 33 d2 9d 50 7f 41 45 86 6c 10 61 c4 d6
     7c fb 8f a6 31 37 71 5d ef 02 03 01 00 01
2020-07-24 08:06:26.016 388-739/org.atalk.android I/aTalk: [158601] org.jivesoftware.smack.AbstractXMPPConnection.notifyConnectionError() Connection was already disconnected when attempting to handle javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
    javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:239)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.waitForHandshake(ConscryptFileDescriptorSocket.java:510)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.getInputStream(ConscryptFileDescriptorSocket.java:473)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnection.java:676)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:714)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$1400(XMPPTCPConnection.java:130)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:972)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$700(XMPPTCPConnection.java:898)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:921)
        at java.lang.Thread.run(Thread.java:919)
     Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:688)
        at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:557)
        at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:513)
        at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:432)
        at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:360)
        at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
        at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:89)
        at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:224)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.verifyCertificateChain(ConscryptFileDescriptorSocket.java:430)
        at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
        at com.android.org.conscrypt.NativeSsl.doHandshake(NativeSsl.java:387)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:234)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.waitForHandshake(ConscryptFileDescriptorSocket.java:510) 
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.getInputStream(ConscryptFileDescriptorSocket.java:473) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnection.java:676) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:714) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$1400(XMPPTCPConnection.java:130) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:972) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$700(XMPPTCPConnection.java:898) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:921) 
        at java.lang.Thread.run(Thread.java:919) 
     Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:688) 
        at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:557) 
        at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:513) 
        at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:432) 
        at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:360) 
        at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94) 
        at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:89) 
        at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:224) 
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.verifyCertificateChain(ConscryptFileDescriptorSocket.java:430) 
        at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) 
        at com.android.org.conscrypt.NativeSsl.doHandshake(NativeSsl.java:387) 
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:234) 
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.waitForHandshake(ConscryptFileDescriptorSocket.java:510) 
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.getInputStream(ConscryptFileDescriptorSocket.java:473) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnection.java:676) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:714) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$1400(XMPPTCPConnection.java:130) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:972) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$700(XMPPTCPConnection.java:898) 
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:921) 
        at java.lang.Thread.run(Thread.java:919)

Maybe I did not make myself clear. Sorry about that. What I suggested is that you create a new SSLContext instance every time the factory method is called, while still setting a custom trust manager via config.setCustomX509TrustManager(sslTrustManager);.

Thanks for the clarification. However I am not sure why there is a need to perform the below statement whenever the SslContextFactory.createSslContext() is called. Need you to enlighten me. as I see this is a new change in smack-4.4.0-alpha5.

SslContextFactory sslContextFactory = () → return loginStrategy.createSslContext(cvs, sslTrustManager);

What I see from aTalk source is that

SSLContext sslContext = loginStrategy.createSslContext(cvs, sslTrustManager);

will actually resolve to getSSLContext() below for password login strategy; which should return a reference instance, and remains unchanged for the same SSL connection.

Note: loginStrategy.createSslContext(cvs, sslTrustManager) will get a new instance when there is a change in the XMPP Connection.

    public SSLContext getSSLContext(X509TrustManager trustManager)
            throws GeneralSecurityException
    {
        try {
            KeyStore ks = KeyStore.getInstance(System.getProperty("javax.net.ssl.keyStoreType",
                    KeyStore.getDefaultType()));
            KeyManagerFactory kmFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

            String keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword");
            if (System.getProperty("javax.net.ssl.keyStore") != null) {
                ks.load(new FileInputStream(System.getProperty("javax.net.ssl.keyStore")), null);
            }
            else {
                ks.load(null, null);
            }
            kmFactory.init(ks, keyStorePassword == null ? null : keyStorePassword.toCharArray());
            return getSSLContext(kmFactory.getKeyManagers(), trustManager);
        } catch (Exception e) {
            throw new GeneralSecurityException("Cannot init SSLContext", e);
        }
    }

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.