|
29 | 29 | import java.util.List; |
30 | 30 | import java.util.Locale; |
31 | 31 | import java.util.regex.Pattern; |
| 32 | +import java.nio.charset.StandardCharsets; |
32 | 33 | import javax.net.ssl.HostnameVerifier; |
33 | 34 | import javax.net.ssl.SSLException; |
34 | 35 | import javax.net.ssl.SSLSession; |
@@ -63,6 +64,9 @@ private OkHostnameVerifier() { |
63 | 64 |
|
64 | 65 | @Override |
65 | 66 | public boolean verify(String host, SSLSession session) { |
| 67 | + if (!isAscii(host)) { |
| 68 | + return false; |
| 69 | + } |
66 | 70 | try { |
67 | 71 | Certificate[] certificates = session.getPeerCertificates(); |
68 | 72 | return verify(host, (X509Certificate) certificates[0]); |
@@ -98,7 +102,7 @@ private boolean verifyIpAddress(String ipAddress, X509Certificate certificate) { |
98 | 102 | * Returns true if {@code certificate} matches {@code hostName}. |
99 | 103 | */ |
100 | 104 | private boolean verifyHostName(String hostName, X509Certificate certificate) { |
101 | | - hostName = hostName.toLowerCase(Locale.US); |
| 105 | + hostName = asciiToLowercase(hostName); |
102 | 106 | boolean hasDns = false; |
103 | 107 | List<String> altNames = getSubjectAltNames(certificate, ALT_DNS_NAME); |
104 | 108 | for (int i = 0, size = altNames.size(); i < size; i++) { |
@@ -254,4 +258,22 @@ private boolean verifyHostName(String hostName, String pattern) { |
254 | 258 | // hostName matches pattern |
255 | 259 | return true; |
256 | 260 | } |
| 261 | + |
| 262 | + /** |
| 263 | + * Normalize the input to lowercase, if it is an ASCII string. |
| 264 | + * Avoid unicode characters like \u1E0E from returning lowercased ascii |
| 265 | + * that could match real hostnames. |
| 266 | + */ |
| 267 | + private static String asciiToLowercase(String input) { |
| 268 | + if (isAscii(input)) { |
| 269 | + return input.toLowerCase(Locale.US); |
| 270 | + } else { |
| 271 | + return input; |
| 272 | + } |
| 273 | + } |
| 274 | + |
| 275 | + private static boolean isAscii(String input) { |
| 276 | + // Only ASCII characters are 1 byte in UTF-8. |
| 277 | + return input.getBytes(StandardCharsets.UTF_8).length == input.length(); |
| 278 | + } |
257 | 279 | } |
0 commit comments