1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.client5.http.ssl;
29
30 import java.io.ByteArrayInputStream;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.InputStreamReader;
34 import java.nio.charset.StandardCharsets;
35 import java.security.cert.CertificateFactory;
36 import java.security.cert.X509Certificate;
37 import java.util.Arrays;
38 import java.util.Collections;
39 import java.util.List;
40
41 import javax.net.ssl.SSLException;
42
43 import org.apache.hc.client5.http.psl.PublicSuffixList;
44 import org.apache.hc.client5.http.psl.PublicSuffixListParser;
45 import org.apache.hc.client5.http.psl.PublicSuffixMatcher;
46 import org.apache.hc.client5.http.utils.DnsUtils;
47 import org.junit.jupiter.api.Assertions;
48 import org.junit.jupiter.api.BeforeEach;
49 import org.junit.jupiter.api.Test;
50
51
52
53
54 class TestDefaultHostnameVerifier {
55
56 private DefaultHostnameVerifier impl;
57 private PublicSuffixMatcher publicSuffixMatcher;
58
59 private static final String PUBLIC_SUFFIX_MATCHER_SOURCE_FILE = "suffixlistmatcher.txt";
60
61 @BeforeEach
62 void setup() throws IOException {
63 impl = new DefaultHostnameVerifier();
64
65
66 final ClassLoader classLoader = getClass().getClassLoader();
67 final InputStream in = classLoader.getResourceAsStream(PUBLIC_SUFFIX_MATCHER_SOURCE_FILE);
68 Assertions.assertNotNull(in);
69 final List<PublicSuffixList> lists = PublicSuffixListParser.INSTANCE.parseByType(
70 new InputStreamReader(in, StandardCharsets.UTF_8));
71 publicSuffixMatcher = new PublicSuffixMatcher(lists);
72 }
73
74 @Test
75 void testVerify() throws Exception {
76 final CertificateFactory cf = CertificateFactory.getInstance("X.509");
77 InputStream in;
78 X509Certificate x509;
79 in = new ByteArrayInputStream(CertificatesToPlayWith.X509_FOO);
80 x509 = (X509Certificate) cf.generateCertificate(in);
81
82 impl.verify("foo.com", x509);
83 exceptionPlease(impl, "a.foo.com", x509);
84 exceptionPlease(impl, "bar.com", x509);
85
86 in = new ByteArrayInputStream(CertificatesToPlayWith.X509_HANAKO);
87 x509 = (X509Certificate) cf.generateCertificate(in);
88 impl.verify("\u82b1\u5b50.co.jp", x509);
89 exceptionPlease(impl, "a.\u82b1\u5b50.co.jp", x509);
90
91 in = new ByteArrayInputStream(CertificatesToPlayWith.X509_FOO_BAR);
92 x509 = (X509Certificate) cf.generateCertificate(in);
93 exceptionPlease(impl, "foo.com", x509);
94 exceptionPlease(impl, "a.foo.com", x509);
95 impl.verify("bar.com", x509);
96 exceptionPlease(impl, "a.bar.com", x509);
97
98 in = new ByteArrayInputStream(CertificatesToPlayWith.X509_FOO_BAR_HANAKO);
99 x509 = (X509Certificate) cf.generateCertificate(in);
100 exceptionPlease(impl, "foo.com", x509);
101 exceptionPlease(impl, "a.foo.com", x509);
102 impl.verify("bar.com", x509);
103 exceptionPlease(impl, "a.bar.com", x509);
104
105
106
107
108
109
110
111 exceptionPlease(impl, "a.\u82b1\u5b50.co.jp", x509);
112
113 in = new ByteArrayInputStream(CertificatesToPlayWith.X509_NO_CNS_FOO);
114 x509 = (X509Certificate) cf.generateCertificate(in);
115 impl.verify("foo.com", x509);
116 exceptionPlease(impl, "a.foo.com", x509);
117
118 in = new ByteArrayInputStream(CertificatesToPlayWith.X509_NO_CNS_FOO);
119 x509 = (X509Certificate) cf.generateCertificate(in);
120 impl.verify("foo.com", x509);
121 exceptionPlease(impl, "a.foo.com", x509);
122
123 in = new ByteArrayInputStream(CertificatesToPlayWith.X509_THREE_CNS_FOO_BAR_HANAKO);
124 x509 = (X509Certificate) cf.generateCertificate(in);
125 exceptionPlease(impl, "foo.com", x509);
126 exceptionPlease(impl, "a.foo.com", x509);
127 exceptionPlease(impl, "bar.com", x509);
128 exceptionPlease(impl, "a.bar.com", x509);
129 impl.verify("\u82b1\u5b50.co.jp", x509);
130 exceptionPlease(impl, "a.\u82b1\u5b50.co.jp", x509);
131
132 in = new ByteArrayInputStream(CertificatesToPlayWith.X509_WILD_FOO);
133 x509 = (X509Certificate) cf.generateCertificate(in);
134 exceptionPlease(impl, "foo.com", x509);
135 impl.verify("www.foo.com", x509);
136 impl.verify("\u82b1\u5b50.foo.com", x509);
137 exceptionPlease(impl, "a.b.foo.com", x509);
138
139 in = new ByteArrayInputStream(CertificatesToPlayWith.X509_WILD_CO_JP);
140 x509 = (X509Certificate) cf.generateCertificate(in);
141
142
143 impl.verify("*.co.jp", x509);
144 impl.verify("foo.co.jp", x509);
145 impl.verify("\u82b1\u5b50.co.jp", x509);
146
147 in = new ByteArrayInputStream(CertificatesToPlayWith.X509_WILD_FOO_BAR_HANAKO);
148 x509 = (X509Certificate) cf.generateCertificate(in);
149
150 exceptionPlease(impl, "foo.com", x509);
151 exceptionPlease(impl, "www.foo.com", x509);
152 exceptionPlease(impl, "\u82b1\u5b50.foo.com", x509);
153 exceptionPlease(impl, "a.b.foo.com", x509);
154
155 exceptionPlease(impl, "bar.com", x509);
156 impl.verify("www.bar.com", x509);
157 impl.verify("\u82b1\u5b50.bar.com", x509);
158 exceptionPlease(impl, "a.b.bar.com", x509);
159
160 in = new ByteArrayInputStream(CertificatesToPlayWith.X509_MULTIPLE_VALUE_AVA);
161 x509 = (X509Certificate) cf.generateCertificate(in);
162 impl.verify("repository.infonotary.com", x509);
163
164 in = new ByteArrayInputStream(CertificatesToPlayWith.S_GOOGLE_COM);
165 x509 = (X509Certificate) cf.generateCertificate(in);
166 impl.verify("*.google.com", x509);
167
168 in = new ByteArrayInputStream(CertificatesToPlayWith.S_GOOGLE_COM);
169 x509 = (X509Certificate) cf.generateCertificate(in);
170 impl.verify("*.Google.com", x509);
171
172 in = new ByteArrayInputStream(CertificatesToPlayWith.IP_1_1_1_1);
173 x509 = (X509Certificate) cf.generateCertificate(in);
174 impl.verify("1.1.1.1", x509);
175 impl.verify("dummy-value.com", x509);
176
177 exceptionPlease(impl, "1.1.1.2", x509);
178 exceptionPlease(impl, "not-the-cn.com", x509);
179
180 in = new ByteArrayInputStream(CertificatesToPlayWith.EMAIL_ALT_SUBJECT_NAME);
181 x509 = (X509Certificate) cf.generateCertificate(in);
182 impl.verify("www.company.com", x509);
183 }
184
185 @Test
186 void testSubjectAlt() throws Exception {
187 final CertificateFactory cf = CertificateFactory.getInstance("X.509");
188 final InputStream in = new ByteArrayInputStream(CertificatesToPlayWith.X509_MULTIPLE_SUBJECT_ALT);
189 final X509Certificate x509 = (X509Certificate) cf.generateCertificate(in);
190
191 Assertions.assertEquals("CN=localhost, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=CH",
192 x509.getSubjectDN().getName());
193
194 impl.verify("localhost.localdomain", x509);
195 impl.verify("127.0.0.1", x509);
196
197 Assertions.assertThrows(SSLException.class, () -> impl.verify("localhost", x509));
198 Assertions.assertThrows(SSLException.class, () -> impl.verify("local.host", x509));
199 Assertions.assertThrows(SSLException.class, () -> impl.verify("127.0.0.2", x509));
200 }
201
202 public void exceptionPlease(final DefaultHostnameVerifier hv, final String host,
203 final X509Certificate x509) {
204 Assertions.assertThrows(SSLException.class, () -> hv.verify(host, x509));
205 }
206
207 @Test
208 void testParseFQDN() {
209 Assertions.assertEquals(Arrays.asList("blah"),
210 DefaultHostnameVerifier.parseFQDN("blah"));
211 Assertions.assertEquals(Arrays.asList("blah", "blah"),
212 DefaultHostnameVerifier.parseFQDN("blah.blah"));
213 Assertions.assertEquals(Arrays.asList("blah", "blah", "blah"),
214 DefaultHostnameVerifier.parseFQDN("blah.blah.blah"));
215 Assertions.assertEquals(Arrays.asList("", "", "blah", ""),
216 DefaultHostnameVerifier.parseFQDN(".blah.."));
217 Assertions.assertEquals(Arrays.asList(""),
218 DefaultHostnameVerifier.parseFQDN(""));
219 Assertions.assertEquals(Arrays.asList("", ""),
220 DefaultHostnameVerifier.parseFQDN("."));
221 Assertions.assertEquals(Arrays.asList("com", "domain", "host"),
222 DefaultHostnameVerifier.parseFQDN("host.domain.com"));
223 }
224
225 @Test
226 void testDomainRootMatching() {
227 Assertions.assertFalse(DefaultHostnameVerifier.matchDomainRoot("a.b.c", null));
228 Assertions.assertTrue(DefaultHostnameVerifier.matchDomainRoot("a.b.c", "a.b.c"));
229 Assertions.assertFalse(DefaultHostnameVerifier.matchDomainRoot("aa.b.c", "a.b.c"));
230 Assertions.assertFalse(DefaultHostnameVerifier.matchDomainRoot("a.b.c", "aa.b.c"));
231 Assertions.assertTrue(DefaultHostnameVerifier.matchDomainRoot("a.a.b.c", "a.b.c"));
232 }
233
234 static boolean matchIdentity(final String host, final String identity,
235 final PublicSuffixMatcher publicSuffixMatcher, final boolean strict) {
236 return DefaultHostnameVerifier.matchIdentity(
237 DnsUtils.normalizeUnicode(host),
238 DnsUtils.normalizeUnicode(identity),
239 publicSuffixMatcher, strict);
240 }
241
242 static boolean matchIdentity(final String host, final String identity,
243 final PublicSuffixMatcher publicSuffixMatcher) {
244 return matchIdentity(host, identity, publicSuffixMatcher, false);
245 }
246
247 static boolean matchIdentity(final String host, final String identity) {
248 return matchIdentity(host, identity, null, false);
249 }
250
251 static boolean matchIdentityStrict(final String host, final String identity,
252 final PublicSuffixMatcher publicSuffixMatcher) {
253 return matchIdentity(host, identity, publicSuffixMatcher, true);
254 }
255
256 static boolean matchIdentityStrict(final String host, final String identity) {
257 return matchIdentity(host, identity, null, true);
258 }
259
260 @Test
261 void testIdentityMatching() {
262
263 Assertions.assertTrue(matchIdentity("a.b.c", "*.b.c"));
264 Assertions.assertTrue(matchIdentityStrict("a.b.c", "*.b.c"));
265
266 Assertions.assertTrue(matchIdentity("s.a.b.c", "*.b.c"));
267 Assertions.assertFalse(matchIdentityStrict("s.a.b.c", "*.b.c"));
268
269 Assertions.assertTrue(matchIdentity("a.gov.uk", "*.gov.uk", publicSuffixMatcher));
270 Assertions.assertTrue(matchIdentityStrict("a.gov.uk", "*.gov.uk", publicSuffixMatcher));
271
272 Assertions.assertTrue(matchIdentity("s.a.gov.uk", "*.a.gov.uk", publicSuffixMatcher));
273 Assertions.assertTrue(matchIdentityStrict("s.a.gov.uk", "*.a.gov.uk", publicSuffixMatcher));
274
275 Assertions.assertTrue(matchIdentity("s.a.gov.uk", "*.gov.uk", publicSuffixMatcher));
276 Assertions.assertFalse(matchIdentityStrict("s.a.gov.uk", "*.gov.uk", publicSuffixMatcher));
277
278 Assertions.assertTrue(matchIdentity("a.gov.com", "*.gov.com", publicSuffixMatcher));
279 Assertions.assertTrue(matchIdentityStrict("a.gov.com", "*.gov.com", publicSuffixMatcher));
280
281 Assertions.assertTrue(matchIdentity("s.a.gov.com", "*.gov.com", publicSuffixMatcher));
282 Assertions.assertFalse(matchIdentityStrict("s.a.gov.com", "*.gov.com", publicSuffixMatcher));
283
284 Assertions.assertTrue(matchIdentity("a.gov.uk", "a*.gov.uk", publicSuffixMatcher));
285 Assertions.assertTrue(matchIdentityStrict("a.gov.uk", "a*.gov.uk", publicSuffixMatcher));
286
287 Assertions.assertFalse(matchIdentity("s.a.gov.uk", "a*.gov.uk", publicSuffixMatcher));
288 Assertions.assertFalse(matchIdentityStrict("s.a.gov.uk", "a*.gov.uk", publicSuffixMatcher));
289
290 Assertions.assertFalse(matchIdentity("a.b.c", "*.b.*"));
291 Assertions.assertFalse(matchIdentityStrict("a.b.c", "*.b.*"));
292
293 Assertions.assertFalse(matchIdentity("a.b.c", "*.*.c"));
294 Assertions.assertFalse(matchIdentityStrict("a.b.c", "*.*.c"));
295
296 Assertions.assertTrue(matchIdentity("a.b.xxx.uk", "a.b.xxx.uk", publicSuffixMatcher));
297 Assertions.assertTrue(matchIdentityStrict("a.b.xxx.uk", "a.b.xxx.uk", publicSuffixMatcher));
298
299 Assertions.assertTrue(matchIdentity("a.b.xxx.uk", "*.b.xxx.uk", publicSuffixMatcher));
300 Assertions.assertTrue(matchIdentityStrict("a.b.xxx.uk", "*.b.xxx.uk", publicSuffixMatcher));
301
302 Assertions.assertTrue(matchIdentity("b.xxx.uk", "b.xxx.uk", publicSuffixMatcher));
303 Assertions.assertTrue(matchIdentityStrict("b.xxx.uk", "b.xxx.uk", publicSuffixMatcher));
304
305 Assertions.assertTrue(matchIdentity("b.xxx.uk", "*.xxx.uk", publicSuffixMatcher));
306 Assertions.assertTrue(matchIdentityStrict("b.xxx.uk", "*.xxx.uk", publicSuffixMatcher));
307 }
308
309 @Test
310 void testHTTPCLIENT_1097() {
311 Assertions.assertTrue(matchIdentity("a.b.c", "a*.b.c"));
312 Assertions.assertTrue(matchIdentityStrict("a.b.c", "a*.b.c"));
313
314 Assertions.assertTrue(matchIdentity("a.a.b.c", "a*.b.c"));
315 Assertions.assertFalse(matchIdentityStrict("a.a.b.c", "a*.b.c"));
316 }
317
318 @Test
319 void testHTTPCLIENT_1255() {
320 Assertions.assertTrue(matchIdentity("mail.a.b.c.com", "m*.a.b.c.com"));
321 Assertions.assertTrue(matchIdentityStrict("mail.a.b.c.com", "m*.a.b.c.com"));
322 }
323
324 @Test
325 void testHTTPCLIENT_1997() {
326 String domain;
327
328 domain = "dev.b.cloud.a";
329 Assertions.assertTrue(matchIdentity("service.apps." + domain, "*.apps." + domain));
330 Assertions.assertTrue(matchIdentityStrict("service.apps." + domain, "*.apps." + domain));
331 Assertions.assertTrue(matchIdentity("service.apps." + domain, "*.apps." + domain, publicSuffixMatcher));
332 Assertions.assertTrue(matchIdentityStrict("service.apps." + domain, "*.apps." + domain, publicSuffixMatcher));
333
334
335 domain = "dev.b.cloud.com";
336 Assertions.assertTrue(matchIdentity("service.apps." + domain, "*.apps." + domain));
337 Assertions.assertTrue(matchIdentityStrict("service.apps." + domain, "*.apps." + domain));
338 Assertions.assertTrue(matchIdentity("service.apps." + domain, "*.apps." + domain, publicSuffixMatcher));
339 Assertions.assertTrue(matchIdentityStrict("service.apps." + domain, "*.apps." + domain, publicSuffixMatcher));
340
341
342 domain = "dev.b.cloud.lan";
343 Assertions.assertTrue(matchIdentity("service.apps." + domain, "*.apps." + domain));
344 Assertions.assertTrue(matchIdentityStrict("service.apps." + domain, "*.apps." + domain));
345 Assertions.assertTrue(matchIdentity("service.apps." + domain, "*.apps." + domain, publicSuffixMatcher));
346 Assertions.assertTrue(matchIdentityStrict("service.apps." + domain, "*.apps." + domain, publicSuffixMatcher));
347 }
348
349 @Test
350 void testHTTPCLIENT_1316() throws Exception{
351 final String host1 = "2001:0db8:aaaa:bbbb:cccc:0:0:0001";
352 DefaultHostnameVerifier.matchIPv6Address(host1, Collections.singletonList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc:0:0:0001")));
353 DefaultHostnameVerifier.matchIPv6Address(host1, Collections.singletonList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc::1")));
354 Assertions.assertThrows(SSLException.class, () ->
355 DefaultHostnameVerifier.matchIPv6Address(host1, Collections.singletonList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc::10"))));
356 final String host2 = "2001:0db8:aaaa:bbbb:cccc::1";
357 DefaultHostnameVerifier.matchIPv6Address(host2, Collections.singletonList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc:0:0:0001")));
358 DefaultHostnameVerifier.matchIPv6Address(host2, Collections.singletonList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc::1")));
359 Assertions.assertThrows(SSLException.class, () ->
360 DefaultHostnameVerifier.matchIPv6Address(host2, Collections.singletonList(SubjectName.IP("2001:0db8:aaaa:bbbb:cccc::10"))));
361 }
362
363 @Test
364 void testHTTPCLIENT_2149() throws Exception {
365 final CertificateFactory cf = CertificateFactory.getInstance("X.509");
366 final InputStream in = new ByteArrayInputStream(CertificatesToPlayWith.SUBJECT_ALT_IP_ONLY);
367 final X509Certificate x509 = (X509Certificate) cf.generateCertificate(in);
368
369 Assertions.assertEquals("CN=www.foo.com", x509.getSubjectDN().getName());
370
371 impl.verify("127.0.0.1", x509);
372 impl.verify("www.foo.com", x509);
373
374 exceptionPlease(impl, "127.0.0.2", x509);
375 exceptionPlease(impl, "www.bar.com", x509);
376 }
377
378 @Test
379 void testExtractCN() throws Exception {
380 Assertions.assertEquals("blah", DefaultHostnameVerifier.extractCN("cn=blah, ou=blah, o=blah"));
381 Assertions.assertEquals("blah", DefaultHostnameVerifier.extractCN("cn=blah, cn=yada, cn=booh"));
382 Assertions.assertEquals("blah", DefaultHostnameVerifier.extractCN("c = pampa , cn = blah , ou = blah , o = blah"));
383 Assertions.assertEquals("blah", DefaultHostnameVerifier.extractCN("cn=\"blah\", ou=blah, o=blah"));
384 Assertions.assertEquals("blah blah", DefaultHostnameVerifier.extractCN("cn=\"blah blah\", ou=blah, o=blah"));
385 Assertions.assertEquals("blah, blah", DefaultHostnameVerifier.extractCN("cn=\"blah, blah\", ou=blah, o=blah"));
386 Assertions.assertEquals("blah, blah", DefaultHostnameVerifier.extractCN("cn=blah\\, blah, ou=blah, o=blah"));
387 Assertions.assertEquals("blah", DefaultHostnameVerifier.extractCN("c = cn=uuh, cn=blah, ou=blah, o=blah"));
388 Assertions.assertThrows(SSLException.class, () ->
389 DefaultHostnameVerifier.extractCN("blah,blah"));
390 Assertions.assertThrows(SSLException.class, () ->
391 DefaultHostnameVerifier.extractCN("cn,o=blah"));
392 }
393
394 @Test
395 void testMatchDNSName() throws Exception {
396 DefaultHostnameVerifier.matchDNSName(
397 "host.domain.com",
398 Collections.singletonList(SubjectName.DNS("*.domain.com")),
399 publicSuffixMatcher);
400 DefaultHostnameVerifier.matchDNSName(
401 "host.xx",
402 Collections.singletonList(SubjectName.DNS("*.xx")),
403 publicSuffixMatcher);
404 DefaultHostnameVerifier.matchDNSName(
405 "host.appspot.com",
406 Collections.singletonList(SubjectName.DNS("*.appspot.com")),
407 publicSuffixMatcher);
408 DefaultHostnameVerifier.matchDNSName(
409 "demo-s3-bucket.s3.eu-central-1.amazonaws.com",
410 Collections.singletonList(SubjectName.DNS("*.s3.eu-central-1.amazonaws.com")),
411 publicSuffixMatcher);
412 DefaultHostnameVerifier.matchDNSName(
413 "hostname-workspace-1.local",
414 Collections.singletonList(SubjectName.DNS("hostname-workspace-1.local")),
415 publicSuffixMatcher);
416
417 Assertions.assertThrows(SSLException.class, () ->
418 DefaultHostnameVerifier.matchDNSName(
419 "host.domain.com",
420 Collections.singletonList(SubjectName.DNS("some.other.com")),
421 publicSuffixMatcher));
422
423 DefaultHostnameVerifier.matchDNSName(
424 "host.ec2.compute-1.amazonaws.com",
425 Collections.singletonList(SubjectName.DNS("host.ec2.compute-1.amazonaws.com")),
426 publicSuffixMatcher);
427 DefaultHostnameVerifier.matchDNSName(
428 "host.ec2.compute-1.amazonaws.com",
429 Collections.singletonList(SubjectName.DNS("*.ec2.compute-1.amazonaws.com")),
430 publicSuffixMatcher);
431 Assertions.assertThrows(SSLException.class, () ->
432 DefaultHostnameVerifier.matchDNSName(
433 "compute-1.amazonaws.com",
434 Collections.singletonList(SubjectName.DNS("*.compute-1.amazonaws.com")),
435 publicSuffixMatcher));
436 DefaultHostnameVerifier.matchDNSName(
437 "ec2.compute-1.amazonaws.com",
438 Collections.singletonList(SubjectName.DNS("*.compute-1.amazonaws.com")),
439 publicSuffixMatcher);
440 }
441
442 @Test
443 void testMatchIdentity() {
444
445 final String unicodeHost1 = "поиск-слов.рф";
446 final String punycodeHost1 = "xn----dtbqigoecuc.xn--p1ai";
447
448
449 Assertions.assertTrue(matchIdentity(unicodeHost1, punycodeHost1),
450 "Expected the Unicode host and its punycode to match"
451 );
452
453
454 Assertions.assertFalse(
455 matchIdentity("example.com", punycodeHost1),
456 "Expected mismatch between example.com and xn----dtbqigoecuc.xn--p1ai"
457 );
458
459
460 final String unicodeHost2 = "пример.рф";
461 final String unicodeIdentity2 = "пример.рф";
462 Assertions.assertTrue(matchIdentity(unicodeHost2, unicodeIdentity2),
463 "Expected Unicode host and Unicode identity to match"
464 );
465
466
467 final String unicodeHost3 = "пример.рф";
468 final String punycodeIdentity3 = "xn--e1afmkfd.xn--p1ai";
469 Assertions.assertTrue(matchIdentity(unicodeHost3, punycodeIdentity3),
470 "Expected Unicode host and punycode identity to match"
471 );
472
473
474 final String unicodeHost4 = "sub.пример.рф";
475 final String unicodeIdentity4 = "*.пример.рф";
476 Assertions.assertTrue(matchIdentity(unicodeHost4, unicodeIdentity4),
477 "Expected wildcard to match subdomain"
478 );
479
480
481 final String invalidHost = "invalid_host";
482 final String unicodeIdentity5 = "пример.рф";
483 Assertions.assertFalse(
484 matchIdentity(invalidHost, unicodeIdentity5),
485 "Expected invalid host to not match"
486 );
487
488
489 final String unicodeHost4b = "пример.рф";
490 final String invalidIdentity = "xn--invalid-punycode";
491 Assertions.assertFalse(
492 matchIdentity(unicodeHost4b, invalidIdentity),
493 "Expected invalid identity to not match"
494 );
495
496
497 final String unicodeHost5 = "ПрИмеР.рф";
498 final String unicodeIdentity6 = "пример.рф";
499 Assertions.assertTrue(matchIdentity(unicodeHost5, unicodeIdentity6),
500 "Expected case-insensitive Unicode comparison to match"
501 );
502
503
504
505 final String unicodeHost6 = "sub.пример.рф";
506 final String unicodeIdentity8 = "sub.*.рф";
507 Assertions.assertTrue(matchIdentity(unicodeHost6, unicodeIdentity8),
508 "Expected wildcard in the middle label to match"
509 );
510 }
511
512 }