[HTTPCLIENT-1316] Certificate verification rejects IPv6 addresses which are not String-equal.
git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1442829 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
4a021ce33a
commit
d7afb22c13
|
@ -1,6 +1,9 @@
|
||||||
Changes since 4.3 ALPHA1
|
Changes since 4.3 ALPHA1
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
* [HTTPCLIENT-1316] Certificate verification rejects IPv6 addresses which are not String-equal.
|
||||||
|
Contributed Sebastian Bazley <sebb at apache.org>.
|
||||||
|
|
||||||
* [HTTPCLIENT-1307] Future based asynchronous request execution.
|
* [HTTPCLIENT-1307] Future based asynchronous request execution.
|
||||||
Contributed by Jilles van Gurp <jilles at jillesvangurp.com>
|
Contributed by Jilles van Gurp <jilles at jillesvangurp.com>
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,8 @@ package org.apache.http.conn.ssl;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
import java.security.cert.CertificateParsingException;
|
import java.security.cert.CertificateParsingException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
@ -44,6 +46,8 @@ import javax.net.ssl.SSLException;
|
||||||
import javax.net.ssl.SSLSession;
|
import javax.net.ssl.SSLSession;
|
||||||
import javax.net.ssl.SSLSocket;
|
import javax.net.ssl.SSLSocket;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.apache.http.annotation.Immutable;
|
import org.apache.http.annotation.Immutable;
|
||||||
import org.apache.http.conn.util.InetAddressUtils;
|
import org.apache.http.conn.util.InetAddressUtils;
|
||||||
|
|
||||||
|
@ -75,6 +79,8 @@ public abstract class AbstractVerifier implements X509HostnameVerifier {
|
||||||
Arrays.sort(BAD_COUNTRY_2LDS);
|
Arrays.sort(BAD_COUNTRY_2LDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final Log log = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
public AbstractVerifier() {
|
public AbstractVerifier() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
@ -177,7 +183,7 @@ public abstract class AbstractVerifier implements X509HostnameVerifier {
|
||||||
|
|
||||||
// We're can be case-insensitive when comparing the host we used to
|
// We're can be case-insensitive when comparing the host we used to
|
||||||
// establish the socket to the hostname in the certificate.
|
// establish the socket to the hostname in the certificate.
|
||||||
final String hostName = host.trim().toLowerCase(Locale.US);
|
final String hostName = normaliseIPv6Address(host.trim().toLowerCase(Locale.US));
|
||||||
boolean match = false;
|
boolean match = false;
|
||||||
for(final Iterator<String> it = names.iterator(); it.hasNext();) {
|
for(final Iterator<String> it = names.iterator(); it.hasNext();) {
|
||||||
// Don't trim the CN, though!
|
// Don't trim the CN, though!
|
||||||
|
@ -216,7 +222,7 @@ public abstract class AbstractVerifier implements X509HostnameVerifier {
|
||||||
match = countDots(hostName) == countDots(cn);
|
match = countDots(hostName) == countDots(cn);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match = hostName.equals(cn);
|
match = hostName.equals(normaliseIPv6Address(cn));
|
||||||
}
|
}
|
||||||
if(match) {
|
if(match) {
|
||||||
break;
|
break;
|
||||||
|
@ -361,4 +367,19 @@ public abstract class AbstractVerifier implements X509HostnameVerifier {
|
||||||
InetAddressUtils.isIPv6Address(hostname));
|
InetAddressUtils.isIPv6Address(hostname));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if hostname is IPv6, and if so, convert to standard format.
|
||||||
|
*/
|
||||||
|
private String normaliseIPv6Address(final String hostname) {
|
||||||
|
if (hostname == null || !InetAddressUtils.isIPv6Address(hostname)) {
|
||||||
|
return hostname;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
InetAddress inetAddress = InetAddress.getByName(hostname);
|
||||||
|
return inetAddress.getHostAddress();
|
||||||
|
} catch (UnknownHostException uhe) { // Should not happen, because we check for IPv6 address above
|
||||||
|
log.error("Unexpected error converting "+hostname, uhe);
|
||||||
|
return hostname;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -301,6 +301,22 @@ public class TestHostnameVerifier {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
// Check compressed IPv6 hostname matching
|
||||||
|
public void testHTTPCLIENT_1316() throws Exception{
|
||||||
|
String cns[] = {"2001:0db8:aaaa:bbbb:cccc:0:0:0001"};
|
||||||
|
String alt[] = {};
|
||||||
|
final X509HostnameVerifier bhv = new BrowserCompatHostnameVerifier();
|
||||||
|
final X509HostnameVerifier shv = new StrictHostnameVerifier();
|
||||||
|
checkMatching(bhv, "2001:0db8:aaaa:bbbb:cccc:0:0:0001", cns, alt, false);
|
||||||
|
checkMatching(shv, "2001:0db8:aaaa:bbbb:cccc:0:0:0001", cns, alt, false);
|
||||||
|
checkMatching(bhv, "2001:0db8:aaaa:bbbb:cccc::1", cns, alt, false);
|
||||||
|
checkMatching(shv, "2001:0db8:aaaa:bbbb:cccc::1", cns, alt, false);
|
||||||
|
checkMatching(bhv, "2001:0db8:aaaa:bbbb:cccc::10", cns, alt, true);
|
||||||
|
checkMatching(shv, "2001:0db8:aaaa:bbbb:cccc::10", cns, alt, true);
|
||||||
|
// TODO need some more samples
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHTTPCLIENT_1097() {
|
public void testHTTPCLIENT_1097() {
|
||||||
String cns[];
|
String cns[];
|
||||||
|
|
Loading…
Reference in New Issue