HTTPCLIENT-1097 BrowserCompatHostnameVerifier and StrictHostnameVerifier should handle wildcards in SSL certificates better.

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1130531 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Sebastian Bazley 2011-06-02 13:08:15 +00:00
parent 4acba49325
commit a41eccec14
3 changed files with 20 additions and 18 deletions

View File

@ -1,5 +1,8 @@
Changes since 4.1.1 Changes since 4.1.1
* [HTTPCLIENT-1097] BrowserCompatHostnameVerifier and StrictHostnameVerifier should handle wildcards in SSL certificates better.
Contributed by Sebastian Bazley <sebb at apache.org>
* [HTTPCLIENT-1092] If ClientPNames.VIRTUAL_HOST does not provide the port, derive it from the current request. * [HTTPCLIENT-1092] If ClientPNames.VIRTUAL_HOST does not provide the port, derive it from the current request.
Contributed by Sebastian Bazley <sebb at apache.org> Contributed by Sebastian Bazley <sebb at apache.org>

View File

@ -197,13 +197,21 @@ public abstract class AbstractVerifier implements X509HostnameVerifier {
// The CN better have at least two dots if it wants wildcard // The CN better have at least two dots if it wants wildcard
// action. It also can't be [*.co.uk] or [*.co.jp] or // action. It also can't be [*.co.uk] or [*.co.jp] or
// [*.org.uk], etc... // [*.org.uk], etc...
boolean doWildcard = cn.startsWith("*.") && String parts[] = cn.split("\\.");
cn.lastIndexOf('.') >= 0 && boolean doWildcard = parts.length >= 3 &&
parts[0].endsWith("*") &&
acceptableCountryWildcard(cn) && acceptableCountryWildcard(cn) &&
!isIPAddress(host); !isIPAddress(host);
if(doWildcard) { if(doWildcard) {
if (parts[0].length() > 1) { // e.g. server*
String prefix = parts[0].substring(0, parts.length-2); // e.g. server
String suffix = cn.substring(parts[0].length()); // skip wildcard part from cn
String hostSuffix = hostName.substring(prefix.length()); // skip wildcard part from host
match = hostName.startsWith(prefix) && hostSuffix.endsWith(suffix);
} else {
match = hostName.endsWith(cn.substring(1)); match = hostName.endsWith(cn.substring(1));
}
if(match && strictWithSubDomains) { if(match && strictWithSubDomains) {
// If we're in strict mode, then [*.foo.com] is not // If we're in strict mode, then [*.foo.com] is not
// allowed to match [a.b.foo.com] // allowed to match [a.b.foo.com]
@ -222,18 +230,11 @@ public abstract class AbstractVerifier implements X509HostnameVerifier {
} }
public static boolean acceptableCountryWildcard(String cn) { public static boolean acceptableCountryWildcard(String cn) {
int cnLen = cn.length(); String parts[] = cn.split("\\.");
if(cnLen >= 7 && cnLen <= 9) { if (parts.length != 3 || parts[2].length() != 2) {
// Look for the '.' in the 3rd-last position: return true; // it's not an attempt to wildcard a 2TLD within a country code
if(cn.charAt(cnLen - 3) == '.') {
// Trim off the [*.] and the [.XX].
String s = cn.substring(2, cnLen - 3);
// And test against the sorted array of bad 2lds:
int x = Arrays.binarySearch(BAD_COUNTRY_2LDS, s);
return x < 0;
} }
} return Arrays.binarySearch(BAD_COUNTRY_2LDS, parts[1]) < 0;
return true;
} }
public static String[] getCNs(X509Certificate cert) { public static String[] getCNs(X509Certificate cert) {

View File

@ -36,7 +36,6 @@ import java.util.Arrays;
import javax.net.ssl.SSLException; import javax.net.ssl.SSLException;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
/** /**
@ -301,7 +300,6 @@ public class TestHostnameVerifier {
} }
@Test @Test
@Ignore("not yet implemented")
public void HTTPCLIENT_1097() { public void HTTPCLIENT_1097() {
String cns[]; String cns[];
String alt[] = {}; String alt[] = {};
@ -312,8 +310,8 @@ public class TestHostnameVerifier {
checkMatching(bhv, "a.b.c", cns, alt, false); // OK checkMatching(bhv, "a.b.c", cns, alt, false); // OK
checkMatching(shv, "a.b.c", cns, alt, false); // OK checkMatching(shv, "a.b.c", cns, alt, false); // OK
checkMatching(bhv, "s.a.b.c", cns, alt, false); // OK checkMatching(bhv, "a.a.b.c", cns, alt, false); // OK
checkMatching(shv, "s.a.b.c", cns, alt, true); // subdomain not 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*.co.uk", false); // 2 character TLD, invalid 2TLD
checkWildcard("s*.gov.uk", false); // 2 character TLD, invalid 2TLD checkWildcard("s*.gov.uk", false); // 2 character TLD, invalid 2TLD