8157667: sun/security/x509/URICertStore/ExtensionsWithLDAP.java has to be updated due to JDK-8134577

Resolving hosts by proxy instead of name service

Reviewed-by: mullan
This commit is contained in:
John Jiang 2016-07-07 01:31:31 -07:00 committed by Hamlin Li
parent aec121f999
commit 0eca75cd93
5 changed files with 134 additions and 58 deletions

@ -285,8 +285,6 @@ sun/security/krb5/auto/HttpNegotiateServer.java 8038079 generic-
sun/security/tools/keytool/autotest.sh 8130302 generic-all sun/security/tools/keytool/autotest.sh 8130302 generic-all
sun/security/x509/URICertStore/ExtensionsWithLDAP.java 8134577 generic-all
############################################################################ ############################################################################
# jdk_sound # jdk_sound

@ -0,0 +1 @@
127.0.0.1 ldap.host.for.aia

@ -0,0 +1 @@
127.0.0.1 ldap.host.for.crldp

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,33 +23,34 @@
* questions. * questions.
*/ */
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.StringBufferInputStream; import java.net.InetSocketAddress;
import java.net.InetAddress; import java.net.Socket;
import java.net.UnknownHostException; import java.nio.file.Path;
import java.security.cert.CertificateException; import java.nio.file.Paths;
import java.security.cert.CertificateFactory;
import java.security.cert.CertPath; import java.security.cert.CertPath;
import java.security.cert.CertPathValidator; import java.security.cert.CertPathValidator;
import java.security.cert.CertPathValidatorException; import java.security.cert.CertPathValidatorException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.PKIXParameters; import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor; import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer;
/* /*
* @test * @test
* @bug 8134708 * @bug 8134708
* @summary Check if LDAP resources from CRLDP and AIA extensions can be loaded * @summary Check if LDAP resources from CRLDP and AIA extensions can be loaded
* @run main/othervm ExtensionsWithLDAP * @run main/othervm ExtensionsWithLDAP CRLDP ldap.host.for.crldp
* @run main/othervm ExtensionsWithLDAP AIA ldap.host.for.aia
*/ */
public class ExtensionsWithLDAP { public class ExtensionsWithLDAP {
@ -125,29 +126,18 @@ public class ExtensionsWithLDAP {
+ "hnxn9+e0Ah+t8dS5EKfn44w5bI5PCu2bqxs6RCTxNjcY\n" + "hnxn9+e0Ah+t8dS5EKfn44w5bI5PCu2bqxs6RCTxNjcY\n"
+ "-----END CERTIFICATE-----"; + "-----END CERTIFICATE-----";
private static final String LDAP_HOST_CRLDP = "ldap.host.for.crldp";
private static final String LDAP_HOST_AIA = "ldap.host.for.aia";
// a date within the certificates validity period
static final Date validationDate;
static {
try {
validationDate = DateFormat.getDateInstance(
DateFormat.MEDIUM, Locale.US).parse("Sep 02, 2015");
} catch (ParseException e) {
throw new RuntimeException("Couldn't parse date", e);
}
}
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
String extension = args[0];
String targetHost = args[1];
// enable CRLDP and AIA extensions // enable CRLDP and AIA extensions
System.setProperty("com.sun.security.enableCRLDP", "true"); System.setProperty("com.sun.security.enableCRLDP", "true");
System.setProperty("com.sun.security.enableAIAcaIssuers", "true"); System.setProperty("com.sun.security.enableAIAcaIssuers", "true");
// register a local name service Path hostsFilePath = Paths.get(System.getProperty("test.src", ".")
String hostsFileName = System.getProperty("test.src", ".") + "/ExtensionsWithLDAPHosts"; + File.separator + extension);
System.setProperty("jdk.net.hosts.file", hostsFileName); System.setProperty("jdk.net.hosts.file",
hostsFilePath.toFile().getAbsolutePath());
X509Certificate trustedCert = loadCertificate(CA_CERT); X509Certificate trustedCert = loadCertificate(CA_CERT);
X509Certificate eeCert = loadCertificate(EE_CERT); X509Certificate eeCert = loadCertificate(EE_CERT);
@ -158,31 +148,29 @@ public class ExtensionsWithLDAP {
CertPath cp = (CertPath) CertificateFactory.getInstance("X509") CertPath cp = (CertPath) CertificateFactory.getInstance("X509")
.generateCertPath(Arrays.asList(eeCert)); .generateCertPath(Arrays.asList(eeCert));
PKIXParameters params = new PKIXParameters(trustedCertsSet); // CertPath validator should try to parse CRLDP and AIA extensions,
params.setDate(validationDate); // and load CRLs/certs which they point to.
// If proxy server catches requests for resolving host names
// certpath validator should try to parse CRLDP and AIA extensions, // which extensions contain, then it means that CertPath validator
// and load CRLs/certs which they point to // tried to load CRLs/certs which they point to.
// if a local name service catched requests for resolving host names List<String> hosts = new ArrayList<>();
// which extensions contain, then it means that certpath validator Consumer<Socket> socketConsumer = (Socket socket) -> {
// tried to load CRLs/certs which they point to InetSocketAddress remoteAddress
try { = (InetSocketAddress) socket.getRemoteSocketAddress();
CertPathValidator.getInstance("PKIX").validate(cp, params); hosts.add(remoteAddress.getHostName());
};
try (SocksProxy proxy = SocksProxy.startProxy(socketConsumer)) {
CertPathValidator.getInstance("PKIX").validate(cp,
new PKIXParameters(trustedCertsSet));
throw new RuntimeException("CertPathValidatorException not thrown"); throw new RuntimeException("CertPathValidatorException not thrown");
} catch (CertPathValidatorException cpve) { } catch (CertPathValidatorException cpve) {
System.out.println("Expected exception: " + cpve); System.out.println("Expected exception: " + cpve);
} }
// check if it tried to resolve a host name from CRLDP extension if (!hosts.contains(targetHost)) {
if (!LocalNameService.requestedHosts.contains(LDAP_HOST_CRLDP)) {
throw new RuntimeException( throw new RuntimeException(
"A hostname from CRLDP extension not requested"); String.format("The %s from %s extension is not requested",
} targetHost, extension));
// check if it tried to resolve a host name from AIA extension
if (!LocalNameService.requestedHosts.contains(LDAP_HOST_AIA)) {
throw new RuntimeException(
"A hostname from AIA extension not requested");
} }
System.out.println("Test passed"); System.out.println("Test passed");
@ -192,15 +180,9 @@ public class ExtensionsWithLDAP {
public static X509Certificate loadCertificate(String s) public static X509Certificate loadCertificate(String s)
throws IOException, CertificateException { throws IOException, CertificateException {
try (StringBufferInputStream is = new StringBufferInputStream(s)) { try (ByteArrayInputStream is = new ByteArrayInputStream(s.getBytes())) {
return (X509Certificate) CertificateFactory.getInstance("X509") return (X509Certificate) CertificateFactory.getInstance("X509")
.generateCertificate(is); .generateCertificate(is);
} }
} }
}
// a local name service which log requested host names
public static class LocalNameService {
static final List<String> requestedHosts = new ArrayList<>();
}
}

@ -0,0 +1,94 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Objects;
import java.util.function.Consumer;
import javax.net.ServerSocketFactory;
/*
* A simple socks4 proxy for traveling socket.
*/
class SocksProxy implements Runnable, AutoCloseable {
private ServerSocket server;
private Consumer<Socket> socketConsumer;
private SocksProxy(ServerSocket server, Consumer<Socket> socketConsumer) {
this.server = server;
this.socketConsumer = socketConsumer;
}
static SocksProxy startProxy(Consumer<Socket> socketConsumer)
throws IOException {
Objects.requireNonNull(socketConsumer, "socketConsumer cannot be null");
ServerSocket server
= ServerSocketFactory.getDefault().createServerSocket(0);
System.setProperty("socksProxyHost", "127.0.0.1");
System.setProperty("socksProxyPort",
String.valueOf(server.getLocalPort()));
System.setProperty("socksProxyVersion", "4");
SocksProxy proxy = new SocksProxy(server, socketConsumer);
Thread proxyThread = new Thread(proxy, "Proxy");
proxyThread.setDaemon(true);
proxyThread.start();
return proxy;
}
@Override
public void run() {
while (!server.isClosed()) {
try(Socket socket = server.accept()) {
System.out.println("Server: accepted connection");
if (socketConsumer != null) {
socketConsumer.accept(socket);
}
} catch (IOException e) {
if (!server.isClosed()) {
throw new RuntimeException(
"Server: accept connection failed", e);
} else {
System.out.println("Server is closed.");
}
}
}
}
@Override
public void close() throws Exception {
if (!server.isClosed()) {
server.close();
}
}
int getPort() {
return server.getLocalPort();
}
}