Skip to content

Commit 2c31053

Browse files
committed
Add test.
Fix host as well.
1 parent accc382 commit 2c31053

File tree

2 files changed

+100
-19
lines changed

2 files changed

+100
-19
lines changed

httpclient5/src/main/java/org/apache/hc/client5/http/ssl/DefaultHostnameVerifier.java

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -230,43 +230,51 @@ private static boolean matchIdentity(final String host, final String identity,
230230
final DomainType domainType,
231231
final boolean strict) {
232232

233-
final String unicodeIdentity;
233+
final String normalizedHost;
234+
final String normalizedIdentity;
234235
try {
235-
unicodeIdentity = IDN.toUnicode(identity);
236+
normalizedHost = IDN.toUnicode(host);
237+
normalizedIdentity = IDN.toUnicode(identity);
236238
} catch (final IllegalArgumentException e) {
237239
return false;
238240
}
239241

240242
// Public suffix check on the Unicode identity
241-
if (publicSuffixMatcher != null && host.contains(".")) {
242-
if (publicSuffixMatcher.getDomainRoot(unicodeIdentity, domainType) == null) {
243+
if (publicSuffixMatcher != null && normalizedHost.contains(".")) {
244+
if (publicSuffixMatcher.getDomainRoot(normalizedIdentity, domainType) == null) {
243245
return false;
244246
}
245247
}
246248

247-
// Handle wildcard in the Unicode identity
248-
final int asteriskIdx = unicodeIdentity.indexOf('*');
249+
// RFC 2818, 3.1. Server Identity
250+
// "...Names may contain the wildcard
251+
// character * which is considered to match any single domain name
252+
// component or component fragment..."
253+
// Based on this statement presuming only singular wildcard is legal
254+
final int asteriskIdx = normalizedIdentity.indexOf('*');
249255
if (asteriskIdx != -1) {
250-
final String prefix = unicodeIdentity.substring(0, asteriskIdx);
251-
final String suffix = unicodeIdentity.substring(asteriskIdx + 1);
256+
final String prefix = normalizedIdentity.substring(0, asteriskIdx);
257+
final String suffix = normalizedIdentity.substring(asteriskIdx + 1);
252258

253-
if (!prefix.isEmpty() && !host.startsWith(prefix)) {
259+
if (!prefix.isEmpty() && !normalizedHost.startsWith(prefix)) {
254260
return false;
255261
}
256-
if (!suffix.isEmpty() && !host.endsWith(suffix)) {
262+
if (!suffix.isEmpty() && !normalizedHost.endsWith(suffix)) {
257263
return false;
258264
}
259-
260-
// Additional sanity checks on the wildcard portion
265+
// Additional sanity checks on content selected by wildcard can be done here
261266
if (strict) {
262-
final String remainder = host.substring(prefix.length(), host.length() - suffix.length());
267+
final String remainder = normalizedHost.substring(
268+
prefix.length(),
269+
normalizedHost.length() - suffix.length()
270+
);
263271
return !remainder.contains(".");
264272
}
265273
return true;
266274
}
267275

268276
// Direct Unicode comparison
269-
return host.equalsIgnoreCase(unicodeIdentity);
277+
return normalizedHost.equalsIgnoreCase(normalizedIdentity);
270278
}
271279

272280
static boolean matchIdentity(final String host, final String identity,

httpclient5/src/test/java/org/apache/hc/client5/http/ssl/TestDefaultHostnameVerifier.java

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -473,21 +473,94 @@ void testMatchDNSName() throws Exception {
473473
}
474474

475475
@Test
476-
void testMatchIdentityWithIDN() {
477-
final String unicodeHost = "поиск-слов.рф";
478-
final String punycodeHost = "xn----dtbqigoecuc.xn--p1ai";
476+
void testMatchIdentity() {
477+
// Test 1: IDN matching punycode
478+
final String unicodeHost1 = "поиск-слов.рф";
479+
final String punycodeHost1 = "xn----dtbqigoecuc.xn--p1ai";
479480

480481
// These should now match, thanks to IDN.toASCII():
481482
Assertions.assertTrue(
482-
DefaultHostnameVerifier.matchIdentity(unicodeHost, punycodeHost),
483+
DefaultHostnameVerifier.matchIdentity(unicodeHost1, punycodeHost1),
483484
"Expected the Unicode host and its punycode to match"
484485
);
485486

486487
// ‘example.com’ vs. an unrelated punycode domain should fail:
487488
Assertions.assertFalse(
488-
DefaultHostnameVerifier.matchIdentity("example.com", punycodeHost),
489+
DefaultHostnameVerifier.matchIdentity("example.com", punycodeHost1),
489490
"Expected mismatch between example.com and xn----dtbqigoecuc.xn--p1ai"
490491
);
492+
493+
// Test 2: Unicode host and Unicode identity
494+
final String unicodeHost2 = "пример.рф";
495+
final String unicodeIdentity2 = "пример.рф";
496+
Assertions.assertTrue(
497+
DefaultHostnameVerifier.matchIdentity(unicodeHost2, unicodeIdentity2),
498+
"Expected Unicode host and Unicode identity to match"
499+
);
500+
501+
// Test 3: Punycode host and Unicode identity
502+
final String punycodeHost2 = "xn--e1afmkfd.xn--p1ai";
503+
final String unicodeIdentity3 = "пример.рф";
504+
Assertions.assertTrue(
505+
DefaultHostnameVerifier.matchIdentity(punycodeHost2, unicodeIdentity3),
506+
"Expected punycode host and Unicode identity to match"
507+
);
508+
509+
// Test 4: Unicode host and Punycode identity
510+
final String unicodeHost3 = "пример.рф";
511+
final String punycodeIdentity3 = "xn--e1afmkfd.xn--p1ai";
512+
Assertions.assertTrue(
513+
DefaultHostnameVerifier.matchIdentity(unicodeHost3, punycodeIdentity3),
514+
"Expected Unicode host and punycode identity to match"
515+
);
516+
517+
// Test 5: Wildcard matching in the left-most label
518+
final String unicodeHost4 = "sub.пример.рф";
519+
final String unicodeIdentity4 = "*.пример.рф";
520+
Assertions.assertTrue(
521+
DefaultHostnameVerifier.matchIdentity(unicodeHost4, unicodeIdentity4),
522+
"Expected wildcard to match subdomain"
523+
);
524+
525+
// Test 6: Invalid host
526+
final String invalidHost = "invalid_host";
527+
final String unicodeIdentity5 = "пример.рф";
528+
Assertions.assertFalse(
529+
DefaultHostnameVerifier.matchIdentity(invalidHost, unicodeIdentity5),
530+
"Expected invalid host to not match"
531+
);
532+
533+
// Test 7: Invalid identity
534+
final String unicodeHost4b = "пример.рф";
535+
final String invalidIdentity = "xn--invalid-punycode";
536+
Assertions.assertFalse(
537+
DefaultHostnameVerifier.matchIdentity(unicodeHost4b, invalidIdentity),
538+
"Expected invalid identity to not match"
539+
);
540+
541+
// Test 8: Mixed case comparison
542+
final String unicodeHost5 = "ПрИмеР.рф";
543+
final String unicodeIdentity6 = "пример.рф";
544+
Assertions.assertTrue(
545+
DefaultHostnameVerifier.matchIdentity(unicodeHost5, unicodeIdentity6),
546+
"Expected case-insensitive Unicode comparison to match"
547+
);
548+
549+
// Test 9: Wildcard with punycode host
550+
final String punycodeHost3 = "xn--a-7h.xn--e1afmkfd.xn--p1ai";
551+
final String unicodeIdentity7 = "*.пример.рф";
552+
Assertions.assertTrue(
553+
DefaultHostnameVerifier.matchIdentity(punycodeHost3, unicodeIdentity7),
554+
"Expected wildcard to match punycode-encoded host"
555+
);
556+
557+
// Test 10: Wildcard in the middle label (per RFC 2818, should match)
558+
final String unicodeHost6 = "sub.пример.рф";
559+
final String unicodeIdentity8 = "sub.*.рф";
560+
Assertions.assertTrue(
561+
DefaultHostnameVerifier.matchIdentity(unicodeHost6, unicodeIdentity8),
562+
"Expected wildcard in the middle label to match"
563+
);
491564
}
492565

493566
}

0 commit comments

Comments
 (0)