Smack DNSSEC / DANE Security experimental features

aTalk has implemented DNSSEC and DANE based on Smack experimental features. So far both features seem to be working with no error (no much log messages feedback to positively confirm this). However what I observed was that there seem to be little or no error exception thrown when there were errors occur during DNSSED/DANE authentication process.

When I enabled both DNSSEC/DANE on atalk.org, the following error message was logged by miniDNS. However this is no propagated up to the app level, everything lie silent until response timeout. aTalk shows user the error message as “Encounter problem during XMPPConnection: No response received within reply timeout. Timeout was 10000ms (~10s). While waiting for establishing TLS”.

Also from the error message printed if I interpret correctly, it seems that DANE is asking/checking TLS certificate based on atalk.org service name instead of the overridden server atalk.sytes.net address.

I am also not sure if DANE will revert to user in case of untrusted TLS certificate for user action.

I also tried the same setting on 5222.de / opendialogue.de account, both DNSSEC/DANE authenticated work with no error message.

05-26 08:42:39.197 4499-12149/org.atalk.android W/aTalk: [38599] de.measite.minidns.AbstractDNSClient.query() Response from /192.168.1.254 asked for _5222._tcp.atalk.org.	IN	TLSA with error code: SERVER_FAIL.
    DNSMessage(35572 QUERY SERVER_FAIL resp[qr=1] rd ra cd)
    [Q: _5222._tcp.atalk.org.	IN	TLSA]
    [X: EDNS: version: 0, flags: do; udp: 4096]

Occasionally aTalk also encountered problem with the following messages. For the second error if happen persistently; I inserted a break point after returning from populateHostAddresses() in XMPPTCPCOnnection#ConnectUsingConfiguration(), and allow it to continue after break point is triggered. then the authentication is successful.

Any advice?

`05-24 18:09:03.500 21309-25882/org.atalk.android W/aTalk: [35634] de.measite.minidns.AbstractDNSClient.query() The DNS server /192.168.1.254 returned a response without the "recursion available" (RA) flag set. This likely indicates a misconfiguration because the server is not suitable for DNS resolution`

and

05-24 16:44:49.144 6439-19290/org.atalk.android I/aTalk: [35433] impl.protocol.jabber.ProtocolProviderServiceJabberImpl.connectAndLogin().1035 Starting XMPP Connection...: 5222.de:5222
05-24 16:44:49.888 6439-19290/org.atalk.android E/aTalk: [35433] util.account.LoginManager.run().318 Failed to register protocol provider. 
    java.lang.IllegalArgumentException: Invalid input to toASCII: ��X��?��h����g��;�xmpp��������� ��Ճ�I�����������������������
        at java.net.IDN.toASCII(IDN.java:112)
        at java.net.IDN.toASCII(IDN.java:134)
        at de.measite.minidns.idna.DefaultIdnaTransformator.toASCII(DefaultIdnaTransformator.java:19)
        at de.measite.minidns.idna.MiniDnsIdna.toASCII(MiniDnsIdna.java:18)
        at de.measite.minidns.DNSName.<init>(DNSName.java:85)
        at de.measite.minidns.DNSName.<init>(DNSName.java:80)
        at de.measite.minidns.DNSName.parse(DNSName.java:325)
        at de.measite.minidns.DNSName.parse(DNSName.java:321)
        at de.measite.minidns.DNSName.parse(DNSName.java:321)
        at de.measite.minidns.DNSName.parse(DNSName.java:282)
        at de.measite.minidns.Record.parse(Record.java:336)
        at de.measite.minidns.DNSMessage.<init>(DNSMessage.java:414)
        at de.measite.minidns.source.NetworkDataSource.queryUdp(NetworkDataSource.java:73)
        at de.measite.minidns.source.NetworkDataSource.query(NetworkDataSource.java:39)
        at de.measite.minidns.AbstractDNSClient.query(AbstractDNSClient.java:175)
        at de.measite.minidns.AbstractDNSClient.query(AbstractDNSClient.java:261)
        at de.measite.minidns.DNSClient.query(DNSClient.java:161)
        at de.measite.minidns.iterative.ReliableDNSClient.query(ReliableDNSClient.java:96)
        at de.measite.minidns.AbstractDNSClient.query(AbstractDNSClient.java:145)
        at de.measite.minidns.dnssec.DNSSECClient.queryDnssec(DNSSECClient.java:93)
        at de.measite.minidns.hla.DnssecResolverApi.resolve(DnssecResolverApi.java:65)
        at de.measite.minidns.hla.ResolverApi.resolve(ResolverApi.java:40)
        at de.measite.minidns.hla.ResolverApi.resolve(ResolverApi.java:34)
        at org.jivesoftware.smack.util.dns.minidns.MiniDnsResolver.lookupSRVRecords0(MiniDnsResolver.java:72)
        at org.jivesoftware.smack.util.dns.DNSResolver.lookupSRVRecords(DNSResolver.java:51)
        at org.jivesoftware.smack.util.DNSUtil.resolveDomain(DNSUtil.java:189)
        at org.jivesoftware.smack.util.DNSUtil.resolveXMPPServiceDomain(DNSUtil.java:137)
        at org.jivesoftware.smack.AbstractXMPPConnection.populateHostAddresses(AbstractXMPPConnection.java:626)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectUsingConfiguration(XMPPTCPConnection.java:558)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectInternal(XMPPTCPConnection.java:902)
        at org.jivesoftware.smack.AbstractXMPPConnection.connect(AbstractXMPPConnection.java:383)
        at net.java.sip.communicator.impl.protocol.jabber.ProtocolProviderServiceJabberImpl.connectAndLogin(ProtocolProviderServiceJabberImpl.java:1037)
        at net.java.sip.communicator.impl.protocol.jabber.ProtocolProviderServiceJabberImpl.initializeConnectAndLogin(ProtocolProviderServiceJabberImpl.java:780)
        at net.java.sip.communicator.impl.protocol.jabber.ProtocolProviderServiceJabberImpl.register(ProtocolProviderServiceJabberImpl.java:635)
        at net.java.sip.communicator.util.account.LoginManager$RegisterProvider.run(LoginManager.java:313)
     Caused by: A prohibited code point was found in the input. line:  0. preContext:  . postContext: ��x��?��h����g��;�xmpp��������� ��ճ�i�����������������������
    
        at android.icu.text.StringPrep.prepare(StringPrep.java:524)
        at android.icu.impl.IDNA2003.convertToASCII(IDNA2003.java:180)
        at android.icu.impl.IDNA2003.convertIDNToASCII(IDNA2003.java:277)
        at android.icu.text.IDNA.convertIDNToASCII(IDNA.java:654)
        at java.net.IDN.toASCII(IDN.java:110)
        at java.net.IDN.toASCII(IDN.java:134) 
        at de.measite.minidns.idna.DefaultIdnaTransformator.toASCII(DefaultIdnaTransformator.java:19) 
        at de.measite.minidns.idna.MiniDnsIdna.toASCII(MiniDnsIdna.java:18) 
        at de.measite.minidns.DNSName.<init>(DNSName.java:85) 
        at de.measite.minidns.DNSName.<init>(DNSName.java:80) 
        at de.measite.minidns.DNSName.parse(DNSName.java:325)

When I enabled DNSSEC and DANE on aTalk, android throws the following error i.e.

Domain specific configurations require that hostname aware checkServerTrusted(X509Certificate[], String, String)

I was unable to find much information online, but seems that this function is required and being called by android NetworkSecurityTrustManager method below. Any advice?

    /**
     * Hostname aware version of {@link #checkServerTrusted(X509Certificate[], String)}.
     * This interface is used by conscrypt and android.net.http.X509TrustManagerExtensions do not
     * modify without modifying those callers.
     */
    public List<X509Certificate> checkServerTrusted(X509Certificate[] certs, String authType,
            String host) throws CertificateException {
        List<X509Certificate> trustedChain = mDelegate.checkServerTrusted(certs, authType, host);
        checkPins(trustedChain);
        return trustedChain;
    }
05-28 13:54:07.596 14877-17452/org.atalk.android W/aTalk: [41279] org.jivesoftware.smack.AbstractXMPPConnection.callConnectionClosedOnErrorListener() Connection XMPPTCPConnection[not-authenticated] (3) closed with error
    java.security.cert.CertificateException: Domain specific configurations require that hostname aware checkServerTrusted(X509Certificate[], String, String) is used
        at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:111)
        at de.measite.minidns.dane.ExpectingTrustManager.checkServerTrusted(ExpectingTrustManager.java:58)
        at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:207)
        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:658)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:807)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$1200(XMPPTCPConnection.java:151)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:1071)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$300(XMPPTCPConnection.java:1000)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:1016)
        at java.lang.Thread.run(Thread.java:764)

I have found the problem for

CertificateException:
Domain specific configurations require that hostname aware checkServerTrusted(X509Certificate[], String, String) is used

With reference to the following links. Although the Network Security Configuration allows app to specify trusted custom domains/services certificates in android#networkSecurityConfig, RootTrustManager#checkServerTrusted() however is not happy when it finds that there are pre-configured trusted domains being specified when called with checkCertTrusted(chain, authType);
hence it throws the CertificateException without checking.

To support custom domain-config with self-signed certificates, the apk must use
checkServerTrusted(X509Certificate[] certs, String authType, String hostname) from the CertificateException error message. However this requires X509ExtendedTrustManager and is available only in android API-24 and above. Hence aTalk has to drop this.

https://www.javatips.net/api/org.skife.config.configsource

====================================
Following are the new observation after the above fix. With the DNSSEC enabled, is that any way to hook in aTalk own TrustManager so it handles and catches all the checkServerTrust exceptions for actions?

With aTalk self-signed certificate and DNSSEC enabled, android displays log message and throws the following exception. It is propagated up to app.

org.atalk.android E/Conscrypt: ------------------Untrusted chain: ----------------------

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

However when both DNSSEC and DANE are enabled, the same error message is shown in log, but this is not propagated to app, until response timeout

org.atalk.android E/Conscrypt: ------------------Untrusted chain: ----------------------

Any advice?
FYI: have included DNSSEC and DANE (experimental) in aTalk version 1.3.1 release (20180530)