logging and code clean up in XmppDomainVerifier

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/crypto/XmppDomainVerifier.java | 37 
1 file changed, 24 insertions(+), 13 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/crypto/XmppDomainVerifier.java ๐Ÿ”—

@@ -2,6 +2,8 @@ package eu.siacs.conversations.crypto;
 
 import android.util.Log;
 import android.util.Pair;
+import androidx.annotation.NonNull;
+import com.google.common.base.CharMatcher;
 import com.google.common.base.MoreObjects;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
@@ -12,6 +14,7 @@ import java.security.cert.CertificateParsingException;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
 import javax.net.ssl.SSLPeerUnverifiedException;
@@ -36,18 +39,18 @@ public class XmppDomainVerifier {
     private static final String XMPP_ADDR = "1.3.6.1.5.5.7.8.5";
 
     private static List<String> getCommonNames(final X509Certificate certificate) {
-        List<String> domains = new ArrayList<>();
+        final var domains = new ImmutableList.Builder<String>();
         try {
-            X500Name x500name = new JcaX509CertificateHolder(certificate).getSubject();
-            RDN[] rdns = x500name.getRDNs(BCStyle.CN);
-            for (int i = 0; i < rdns.length; ++i) {
+            final var x500name = new JcaX509CertificateHolder(certificate).getSubject();
+            final RDN[] nameRDNs = x500name.getRDNs(BCStyle.CN);
+            for (int i = 0; i < nameRDNs.length; ++i) {
                 domains.add(
                         IETFUtils.valueToString(
                                 x500name.getRDNs(BCStyle.CN)[i].getFirst().getValue()));
             }
-            return domains;
-        } catch (CertificateEncodingException e) {
-            return domains;
+            return domains.build();
+        } catch (final CertificateEncodingException e) {
+            return Collections.emptyList();
         }
     }
 
@@ -75,17 +78,24 @@ public class XmppDomainVerifier {
         }
     }
 
-    public static boolean matchDomain(final String needle, final List<String> haystack) {
-        for (final String entry : haystack) {
-            if (entry.startsWith("*.")) {
+    public static boolean matchDomain(final String domain, final List<String> certificateDomains) {
+        for (final String certificateDomain : certificateDomains) {
+            if (certificateDomain.startsWith("*.")) {
                 // https://www.rfc-editor.org/rfc/rfc6125#section-6.4.3
                 // wild cards can only be in the left most label and donโ€™t match '.'
-                final int i = needle.indexOf('.');
-                if (i != -1 && needle.substring(i).equalsIgnoreCase(entry.substring(1))) {
+                final var wildcardEntry = certificateDomain.substring(1);
+                if (CharMatcher.is('.').countIn(wildcardEntry) < 2) {
+                    Log.w(LOGTAG, "not enough labels in wildcard certificate");
+                    break;
+                }
+                final int position = domain.indexOf('.');
+                if (position != -1 && domain.substring(position).equalsIgnoreCase(wildcardEntry)) {
+                    Log.d(LOGTAG, "domain " + domain + " matched " + certificateDomain);
                     return true;
                 }
             } else {
-                if (entry.equalsIgnoreCase(needle)) {
+                if (certificateDomain.equalsIgnoreCase(domain)) {
+                    Log.d(LOGTAG, "domain " + domain + " matched " + certificateDomain);
                     return true;
                 }
             }
@@ -184,6 +194,7 @@ public class XmppDomainVerifier {
             return all.build();
         }
 
+        @NonNull
         @Override
         public String toString() {
             return MoreObjects.toStringHelper(this)