From 28aa10cfe44287f9135e0b3b988e148e29cb56ce Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Fri, 20 Apr 2018 20:16:57 +0200
Subject: [PATCH] Correct an issue with DNS validation of wildcard certificates

---
 .../ssl/BrowserCompatibleHostnameVerifier.kt  | 27 ++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/app/src/main/java/de/kuschku/quasseldroid/ssl/BrowserCompatibleHostnameVerifier.kt b/app/src/main/java/de/kuschku/quasseldroid/ssl/BrowserCompatibleHostnameVerifier.kt
index cbb6affbf..022a97f8c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ssl/BrowserCompatibleHostnameVerifier.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ssl/BrowserCompatibleHostnameVerifier.kt
@@ -15,9 +15,30 @@ class BrowserCompatibleHostnameVerifier : HostnameVerifier {
   }
 
   private fun matches(name: String, host: String): Boolean {
-    val normalizedName = IDN.toASCII(name).trimEnd('.')
-    val normalizedHost = IDN.toASCII(host).trimEnd('.')
-    return normalizedName.equals(normalizedHost, ignoreCase = true)
+    // First we normalize both by removing trailing dots (absolute DNS names), splitting into DNS
+    // labels, and punycoding all unicode parts.
+    val normalizedName = name.trimEnd('.').split('.').map(IDN::toASCII)
+    val normalizedHost = host.trimEnd('.').split('.').map(IDN::toASCII)
+
+    // Only if both have the same number of DNS labels they can match
+    if (normalizedHost.size != normalizedName.size) return false
+
+    // Hosts with size of zero are invalid
+    if (normalizedHost.isEmpty()) return false
+
+    val both = normalizedName.zip(normalizedHost)
+
+    // The first label has to either match exactly, or be *
+    if (!both.take(1).all { (target, actual) ->
+        target.equals(actual, ignoreCase = true) || target == "*"
+      }) return false
+
+    // All other labels have to match exactly.
+    if (!both.drop(1).all { (target, actual) ->
+        target.equals(actual, ignoreCase = true)
+      }) return false
+
+    return true
   }
 
   private fun hostnames(certificate: X509Certificate): Sequence<String> =
-- 
GitLab