[HTTPCLIENT-1410: Browser compatible hostname verifier no longer rejects *.co.<countrycode>, *.gov.<countrycode>, *.info.<countrycode>, etc as invalid

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1528744 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2013-10-03 08:25:58 +00:00
parent 75937296d9
commit fea3c55520
4 changed files with 29 additions and 30 deletions

View File

@ -1,6 +1,10 @@
Changes since 4.3
-------------------
* [HTTPCLIENT-1410] Browser compatible hostname verifier no longer rejects
*.co.<countrycode>, *.gov.<countrycode>, *.info.<countrycode>, etc as invalid.
Contributed by Oleg Kalnichevski <olegk at apache.org>
* Ensure X509HostnameVerifier is never null.
Contributed by Oleg Kalnichevski <olegk at apache.org>

View File

@ -201,10 +201,9 @@ public abstract class AbstractVerifier implements X509HostnameVerifier {
// action. It also can't be [*.co.uk] or [*.co.jp] or
// [*.org.uk], etc...
final String parts[] = cn.split("\\.");
final boolean doWildcard = parts.length >= 3 &&
parts[0].endsWith("*") &&
acceptableCountryWildcard(cn) &&
!isIPAddress(host);
final boolean doWildcard =
parts.length >= 3 && parts[0].endsWith("*") &&
validCountryWildcard(cn) && !isIPAddress(host);
if(doWildcard) {
final String firstpart = parts[0];
@ -233,6 +232,10 @@ public abstract class AbstractVerifier implements X509HostnameVerifier {
}
}
/**
* @deprecated (4.3.1) should not be a part of public APIs.
*/
@Deprecated
public static boolean acceptableCountryWildcard(final String cn) {
final String parts[] = cn.split("\\.");
if (parts.length != 3 || parts[2].length() != 2) {
@ -241,6 +244,14 @@ public abstract class AbstractVerifier implements X509HostnameVerifier {
return Arrays.binarySearch(BAD_COUNTRY_2LDS, parts[1]) < 0;
}
boolean validCountryWildcard(final String cn) {
final String parts[] = cn.split("\\.");
if (parts.length != 3 || parts[2].length() != 2) {
return true; // it's not an attempt to wildcard a 2TLD within a country code
}
return Arrays.binarySearch(BAD_COUNTRY_2LDS, parts[1]) < 0;
}
public static String[] getCNs(final X509Certificate cert) {
final LinkedList<String> cnList = new LinkedList<String>();
/*

View File

@ -54,6 +54,11 @@ public class BrowserCompatHostnameVerifier extends AbstractVerifier {
verify(host, cns, subjectAlts, false);
}
@Override
boolean validCountryWildcard(final String cn) {
return true;
}
@Override
public final String toString() {
return "BROWSER_COMPATIBLE";

View File

@ -150,9 +150,9 @@ public class TestHostnameVerifier {
// using "*.co.jp".
DEFAULT.verify("*.co.jp", x509);
STRICT.verify("*.co.jp", x509);
exceptionPlease(DEFAULT, "foo.co.jp", x509);
DEFAULT.verify("foo.co.jp", x509);
exceptionPlease(STRICT, "foo.co.jp", x509);
exceptionPlease(DEFAULT, "\u82b1\u5b50.co.jp", x509);
DEFAULT.verify("\u82b1\u5b50.co.jp", x509);
exceptionPlease(STRICT, "\u82b1\u5b50.co.jp", x509);
in = new ByteArrayInputStream(CertificatesToPlayWith.X509_WILD_FOO_BAR_HANAKO);
@ -285,10 +285,10 @@ public class TestHostnameVerifier {
checkMatching(shv, "s.a.b.c", cns, alt, true); // subdomain not OK
alt = new String []{"*.gov.uk"};
checkMatching(bhv, "a.gov.uk", cns, alt, true); // Bad 2TLD
checkMatching(bhv, "a.gov.uk", cns, alt, false); // OK
checkMatching(shv, "a.gov.uk", cns, alt, true); // Bad 2TLD
checkMatching(bhv, "s.a.gov.uk", cns, alt, true); // Bad 2TLD
checkMatching(bhv, "s.a.gov.uk", cns, alt, false); // OK
checkMatching(shv, "s.a.gov.uk", cns, alt, true); // Bad 2TLD/no subdomain allowed
alt = new String []{"*.gov.com"};
@ -299,7 +299,7 @@ public class TestHostnameVerifier {
checkMatching(shv, "s.a.gov.com", cns, alt, true); // no subdomain allowed
cns = new String []{"a*.gov.uk"}; // 2TLD check applies to wildcards
checkMatching(bhv, "a.gov.uk", cns, alt, true); // Bad 2TLD
checkMatching(bhv, "a.gov.uk", cns, alt, false); // OK
checkMatching(shv, "a.gov.uk", cns, alt, true); // Bad 2TLD
checkMatching(bhv, "s.a.gov.uk", cns, alt, true); // Bad 2TLD
@ -336,10 +336,6 @@ public class TestHostnameVerifier {
checkMatching(bhv, "a.a.b.c", cns, alt, false); // OK
checkMatching(shv, "a.a.b.c", cns, alt, true); // subdomain not OK
checkWildcard("s*.co.uk", false); // 2 character TLD, invalid 2TLD
checkWildcard("s*.gov.uk", false); // 2 character TLD, invalid 2TLD
checkWildcard("s*.gouv.uk", false); // 2 character TLD, invalid 2TLD
}
@Test
@ -353,23 +349,6 @@ public class TestHostnameVerifier {
checkMatching(shv, "mail.a.b.c.com", cns, alt, false); // OK
}
// Helper
private void checkWildcard(final String host, final boolean isOK) {
Assert.assertTrue(host+" should be "+isOK, isOK==AbstractVerifier.acceptableCountryWildcard(host));
}
@Test
// Various checks of 2TLDs
public void testAcceptableCountryWildcards() {
checkWildcard("*.co.org", true); // Not a 2 character TLD
checkWildcard("s*.co.org", true); // Not a 2 character TLD
checkWildcard("*.co.uk", false); // 2 character TLD, invalid 2TLD
checkWildcard("*.gov.uk", false); // 2 character TLD, invalid 2TLD
checkWildcard("*.gouv.uk", false); // 2 character TLD, invalid 2TLD
checkWildcard("*.a.co.uk", true); // 2 character TLD, invalid 2TLD, but using subdomain
checkWildcard("s*.a.co.uk", true); // 2 character TLD, invalid 2TLD, but using subdomain
}
public void testGetCNs() {
final Principal principal = Mockito.mock(Principal.class);
final X509Certificate cert = Mockito.mock(X509Certificate.class);