8170329: New SSLSocket testing template

Reviewed-by: asmotrak, mullan
This commit is contained in:
Xue-Lei Andrew Fan 2016-12-09 17:21:50 +00:00
parent 0a549bfea5
commit 7f4cb73e6d
5 changed files with 918 additions and 744 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 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
@ -34,6 +34,7 @@ import java.security.cert.*;
import javax.security.auth.x500.X500Principal;
import sun.security.x509.X509CertImpl;
import sun.security.x509.KeyIdentifier;
import sun.security.x509.NetscapeCertTypeExtension;
import sun.security.util.DerValue;
import sun.security.util.DerInputStream;
@ -386,8 +387,21 @@ public final class SimpleValidator extends Validator {
X500Principal issuer = cert.getIssuerX500Principal();
List<X509Certificate> list = trustedX500Principals.get(issuer);
if (list != null) {
X509Certificate trustedCert = list.iterator().next();
c.add(trustedCert);
X509Certificate matchedCert = list.get(0);
X509CertImpl certImpl = X509CertImpl.toImpl(cert);
KeyIdentifier akid = certImpl.getAuthKeyId();
if (akid != null) {
for (X509Certificate sup : list) {
// Look for a best match issuer.
X509CertImpl supCert = X509CertImpl.toImpl(sup);
if (akid.equals(supCert.getSubjectKeyId())) {
matchedCert = sup;
break;
}
}
}
c.add(matchedCert);
return c.toArray(CHAIN0);
}

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,11 @@
* questions.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/*
* @test
* @bug 4323990 4413069 8160838
@ -29,19 +34,25 @@
* @modules java.base/sun.net.www
* @library /javax/net/ssl/templates
* @run main/othervm ProxyAuthTest fail
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=Basic ProxyAuthTest fail
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=Basic, ProxyAuthTest fail
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=BAsIc ProxyAuthTest fail
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=Basic,Digest ProxyAuthTest fail
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=Unknown,bAsIc ProxyAuthTest fail
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes= ProxyAuthTest succeed
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=Digest,NTLM,Negotiate ProxyAuthTest succeed
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=UNKNOWN,notKnown ProxyAuthTest succeed
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=Basic
* ProxyAuthTest fail
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=Basic,
* ProxyAuthTest fail
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=BAsIc
* ProxyAuthTest fail
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=Basic,Digest
* ProxyAuthTest fail
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=Unknown,bAsIc
* ProxyAuthTest fail
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=
* ProxyAuthTest succeed
* @run main/othervm
* -Djdk.http.auth.tunneling.disabledSchemes=Digest,NTLM,Negotiate
* ProxyAuthTest succeed
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=UNKNOWN,notKnown
* ProxyAuthTest succeed
*/
// No way to reserve and restore java.lang.Authenticator, as well as read-once
// system properties, so this tests needs to run in othervm mode.
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
@ -54,6 +65,8 @@ import java.net.URL;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLContext;
import static java.nio.charset.StandardCharsets.US_ASCII;
/*
@ -64,13 +77,128 @@ import static java.nio.charset.StandardCharsets.US_ASCII;
*/
public class ProxyAuthTest extends SSLSocketTemplate {
private static boolean expectSuccess;
/*
* Where do we find the keystores?
* Run the test case.
*/
static String pathToStores = "../../../../../../javax/net/ssl/etc";
static String keyStoreFile = "keystore";
static String trustStoreFile = "truststore";
static String passwd = "passphrase";
public static void main(String[] args) throws Exception {
// Get the customized arguments.
parseArguments(args);
(new ProxyAuthTest()).run();
}
@Override
protected boolean isCustomizeClientConnection() {
return true;
}
@Override
protected void runServerApplication(SSLSocket socket) throws Exception {
String response = "Proxy authentication for tunneling succeeded ..";
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
try {
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
// read the request
readRequest(in);
// retrieve bytecodes
byte[] bytecodes = response.getBytes(US_ASCII);
// send bytecodes in response (assumes HTTP/1.0 or later)
out.writeBytes("HTTP/1.0 200 OK\r\n");
out.writeBytes("Content-Length: " + bytecodes.length + "\r\n");
out.writeBytes("Content-Type: text/html\r\n\r\n");
out.write(bytecodes);
out.flush();
} catch (IOException e) {
// write out error response
out.writeBytes("HTTP/1.0 400 " + e.getMessage() + "\r\n");
out.writeBytes("Content-Type: text/html\r\n\r\n");
out.flush();
}
}
@Override
protected void runClientApplication(int serverPort) throws Exception {
/*
* Set the default SSLSocketFactory.
*/
SSLContext context = createClientSSLContext();
HttpsURLConnection.setDefaultSSLSocketFactory(
context.getSocketFactory());
/*
* setup up a proxy with authentication information
*/
ProxyTunnelServer ps = setupProxy();
/*
* we want to avoid URLspoofCheck failures in cases where the cert
* DN name does not match the hostname in the URL.
*/
HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier());
InetSocketAddress paddr =
new InetSocketAddress("localhost", ps.getPort());
Proxy proxy = new Proxy(Proxy.Type.HTTP, paddr);
URL url = new URL(
"https://" + "localhost:" + serverPort + "/index.html");
BufferedReader in = null;
HttpsURLConnection uc = (HttpsURLConnection) url.openConnection(proxy);
try {
in = new BufferedReader(new InputStreamReader(uc.getInputStream()));
String inputLine;
System.out.print("Client recieved from the server: ");
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
}
if (!expectSuccess) {
throw new RuntimeException(
"Expected exception/failure to connect, but succeeded.");
}
} catch (IOException e) {
if (expectSuccess) {
System.out.println("Client side failed: " + e.getMessage());
throw e;
}
// Assert that the error stream is not accessible from the failed
// tunnel setup.
if (uc.getErrorStream() != null) {
throw new RuntimeException("Unexpected error stream.");
}
if (!e.getMessage().contains("Unable to tunnel through proxy") ||
!e.getMessage().contains("407")) {
throw new RuntimeException(
"Expected exception about cannot tunnel, " +
"407, etc, but got", e);
} else {
// Informative
System.out.println(
"Caught expected exception: " + e.getMessage());
}
} finally {
if (in != null) {
in.close();
}
}
}
private static void parseArguments(String[] args) {
if (args[0].equals("succeed")) {
expectSuccess = true;
} else {
expectSuccess = false;
}
}
/**
* read the response, don't care for the syntax of the request-line
@ -88,143 +216,7 @@ public class ProxyAuthTest extends SSLSocketTemplate {
(line.charAt(0) != '\r') && (line.charAt(0) != '\n'));
}
/*
* Main method to create the server and the client
*/
public static void main(String args[]) throws Exception {
boolean expectSuccess;
expectSuccess = args[0].equals("succeed");
String keyFilename =
TEST_SRC + "/" + pathToStores + "/" + keyStoreFile;
String trustFilename =
TEST_SRC + "/" + pathToStores + "/" + trustStoreFile;
setup(keyFilename, trustFilename, passwd);
new SSLSocketTemplate()
.setServerApplication((socket, test) -> {
DataOutputStream out = new DataOutputStream(
socket.getOutputStream());
try {
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
// read the request
readRequest(in);
// retrieve bytecodes
byte[] bytecodes =
"Proxy authentication for tunneling succeeded .."
.getBytes(US_ASCII);
// send bytecodes in response (assumes HTTP/1.0 or later)
out.writeBytes("HTTP/1.0 200 OK\r\n");
out.writeBytes("Content-Length: " + bytecodes.length +
"\r\n");
out.writeBytes("Content-Type: text/html\r\n\r\n");
out.write(bytecodes);
out.flush();
} catch (IOException e) {
// write out error response
out.writeBytes("HTTP/1.0 400 " + e.getMessage() + "\r\n");
out.writeBytes("Content-Type: text/html\r\n\r\n");
out.flush();
}
})
.setClientPeer(test -> {
try {
doClientSide(test);
if (!expectSuccess) {
throw new RuntimeException("Expected exception/failure "
+ "to connect, but succeeded.");
}
} catch (IOException e) {
if (expectSuccess) {
System.out.println("Client side failed: "
+ e.getMessage());
throw e;
}
if (! (e.getMessage().contains(
"Unable to tunnel through proxy") &&
e.getMessage().contains("407")) ) {
throw new RuntimeException(
"Expected exception about cannot tunnel, "
+ "407, etc, but got", e);
} else {
// Informative
System.out.println("Caught expected exception: "
+ e.getMessage());
}
}
})
.runTest();
}
static void doClientSide(SSLSocketTemplate test) throws IOException {
// Wait for server to get started.
//
// The server side takes care of the issue if the server cannot
// get started in 90 seconds. The client side would just ignore
// the test case if the serer is not ready.
try {
if (!test.waitForServerSignal()) {
System.out.print("The server is not ready yet in 90 seconds. "
+ "Ignore in client side.");
return;
}
} catch (InterruptedException e) {
System.out.print("InterruptedException occured. "
+ "Ignore in client side.");
return;
}
/*
* setup up a proxy with authentication information
*/
ProxyTunnelServer ps = setupProxy();
/*
* we want to avoid URLspoofCheck failures in cases where the cert
* DN name does not match the hostname in the URL.
*/
HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier());
InetSocketAddress paddr = new InetSocketAddress(
"localhost", ps.getPort());
Proxy proxy = new Proxy(Proxy.Type.HTTP, paddr);
URL url = new URL("https://" + "localhost:" + test.getServerPort()
+ "/index.html");
// Signal the server, the client is ready to communicate.
test.signalClientReady();
HttpsURLConnection uc = (HttpsURLConnection) url.openConnection(proxy);
try (BufferedReader in = new BufferedReader(
new InputStreamReader(uc.getInputStream()))) {
String inputLine;
System.out.print("Client recieved from the server: ");
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
}
} catch (IOException e) {
// Assert that the error stream is not accessible from the failed
// tunnel setup.
if (uc.getErrorStream() != null) {
throw new RuntimeException("Unexpected error stream.");
}
throw e;
}
}
static class NameVerifier implements HostnameVerifier {
private static class NameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
@ -232,8 +224,9 @@ public class ProxyAuthTest extends SSLSocketTemplate {
}
}
static ProxyTunnelServer setupProxy() throws IOException {
private static ProxyTunnelServer setupProxy() throws IOException {
ProxyTunnelServer pserver = new ProxyTunnelServer();
/*
* register a system wide authenticator and setup the proxy for
* authentication
@ -248,7 +241,7 @@ public class ProxyAuthTest extends SSLSocketTemplate {
return pserver;
}
public static class TestAuthenticator extends Authenticator {
private static class TestAuthenticator extends Authenticator {
@Override
public PasswordAuthentication getPasswordAuthentication() {

View File

@ -21,86 +21,109 @@
* questions.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/*
* @test
* @bug 4328195
* @summary Need to include the alternate subject DN for certs,
* https should check for this
* @library /javax/net/ssl/templates
* @run main/othervm ServerIdentityTest dnsstore
* @run main/othervm ServerIdentityTest ipstore
*
* SunJSSE does not support dynamic system properties, no way to re-use
* system properties in samevm/agentvm mode.
* @run main/othervm ServerIdentityTest dnsstore localhost
* @run main/othervm ServerIdentityTest ipstore 127.0.0.1
*
* @author Yingxian Wang
*/
import java.io.InputStream;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyStore;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
public class ServerIdentityTest extends SSLSocketTemplate {
public final class ServerIdentityTest extends SSLSocketTemplate {
private static final String PASSWORD = "changeit";
private static String keystore;
private static String hostname;
private static SSLContext context;
/*
* Run the test case.
*/
public static void main(String[] args) throws Exception {
final String keystore = args[0];
String keystoreFilename = TEST_SRC + "/" + keystore;
// Get the customized arguments.
initialize(args);
setup(keystoreFilename, keystoreFilename, PASSWORD);
(new ServerIdentityTest()).run();
}
SSLContext context = SSLContext.getInstance("SSL");
@Override
protected boolean isCustomizeClientConnection() {
return true;
}
KeyManager[] kms = new KeyManager[1];
KeyStore ks = loadJksKeyStore(keystoreFilename, PASSWORD);
KeyManager km = new MyKeyManager(ks, PASSWORD.toCharArray());
kms[0] = km;
context.init(kms, null, null);
@Override
protected void runServerApplication(SSLSocket socket) throws Exception {
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream()));
bw.write("HTTP/1.1 200 OK\r\n\r\n\r\n");
bw.flush();
socket.getSession().invalidate();
}
@Override
protected void runClientApplication(int serverPort) throws Exception {
URL url = new URL(
"https://" + hostname + ":" + serverPort + "/index.html");
HttpURLConnection urlc = null;
InputStream is = null;
try {
urlc = (HttpURLConnection)url.openConnection();
is = urlc.getInputStream();
} finally {
if (is != null) {
is.close();
}
if (urlc != null) {
urlc.disconnect();
}
}
}
@Override
protected SSLContext createServerSSLContext() throws Exception {
return context;
}
@Override
protected SSLContext createClientSSLContext() throws Exception {
return context;
}
private static void initialize(String[] args) throws Exception {
keystore = args[0];
hostname = args[1];
String password = "changeit";
String keyFilename =
System.getProperty("test.src", ".") + "/" + keystore;
String trustFilename =
System.getProperty("test.src", ".") + "/" + keystore;
System.setProperty("javax.net.ssl.keyStore", keyFilename);
System.setProperty("javax.net.ssl.keyStorePassword", password);
System.setProperty("javax.net.ssl.trustStore", trustFilename);
System.setProperty("javax.net.ssl.trustStorePassword", password);
context = SSLContext.getDefault();
HttpsURLConnection.setDefaultSSLSocketFactory(
context.getSocketFactory());
/*
* Start the test.
*/
System.out.println("Testing " + keystore);
new SSLSocketTemplate()
.setSSLContext(context)
.setServerApplication((socket, test) -> {
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream()));
bw.write("HTTP/1.1 200 OK\r\n\r\n\r\n");
bw.flush();
Thread.sleep(2000);
socket.getSession().invalidate();
print("Server application is done");
})
.setClientPeer((test) -> {
boolean serverIsReady = test.waitForServerSignal();
if (!serverIsReady) {
print(
"The server is not ready, ignore on client side.");
return;
}
// Signal the server, the client is ready to communicate.
test.signalClientReady();
String host = keystore.equals("ipstore")
? "127.0.0.1" : "localhost";
URL url = new URL("https://" + host + ":" + test.getServerPort()
+ "/index.html");
((HttpURLConnection) url.openConnection())
.getInputStream().close();
print("Client is done");
}).runTest();
}
}

View File

@ -31,115 +31,57 @@
* @bug 4392475
* @library /javax/net/ssl/templates
* @summary Calling setWantClientAuth(true) disables anonymous suites
* @run main/othervm/timeout=180 AnonCipherWithWantClientAuth
* @run main/othervm AnonCipherWithWantClientAuth
*/
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Security;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
public class AnonCipherWithWantClientAuth extends SSLSocketTemplate {
/*
* Where do we find the keystores?
* Run the test case.
*/
static String pathToStores = "../../../../javax/net/ssl/etc";
static String keyStoreFile = "keystore";
static String trustStoreFile = "truststore";
static String passwd = "passphrase";
public static void main(String[] args) throws Exception {
// reset the security property to make sure that the algorithms
// and keys used in this test are not disabled.
Security.setProperty("jdk.tls.disabledAlgorithms", "");
Security.setProperty("jdk.certpath.disabledAlgorithms", "");
String keyFilename =
System.getProperty("test.src", "./") + "/" + pathToStores +
"/" + keyStoreFile;
String trustFilename =
System.getProperty("test.src", "./") + "/" + pathToStores +
"/" + trustStoreFile;
setup(keyFilename, trustFilename, passwd);
(new AnonCipherWithWantClientAuth()).run();
}
new SSLSocketTemplate()
.setServerPeer(test -> {
SSLServerSocketFactory sslssf =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket sslServerSocket =
(SSLServerSocket) sslssf.createServerSocket(FREE_PORT);
test.setServerPort(sslServerSocket.getLocalPort());
print("Server is listening on port "
+ test.getServerPort());
@Override
protected void runServerApplication(SSLSocket socket) throws Exception {
String ciphers[] = {
"SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA" };
socket.setEnabledCipherSuites(ciphers);
socket.setWantClientAuth(true);
String ciphers[] = {
"SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA" };
sslServerSocket.setEnabledCipherSuites(ciphers);
sslServerSocket.setWantClientAuth(true);
InputStream sslIS = socket.getInputStream();
OutputStream sslOS = socket.getOutputStream();
// Signal the client, the server is ready to accept connection.
test.signalServerReady();
sslIS.read();
sslOS.write(85);
sslOS.flush();
}
// Try to accept a connection in 30 seconds.
SSLSocket sslSocket = accept(sslServerSocket);
if (sslSocket == null) {
// Ignore the test case if no connection within 30 seconds.
print("No incoming client connection in 30 seconds."
+ " Ignore in server side.");
return;
}
print("Server accepted connection");
@Override
protected void runClientApplication(SSLSocket socket) throws Exception {
String ciphers[] = {
"SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DH_anon_EXPORT_WITH_RC4_40_MD5" };
socket.setEnabledCipherSuites(ciphers);
socket.setUseClientMode(true);
// handle the connection
try {
// Is it the expected client connection?
//
// Naughty test cases or third party routines may try to
// connection to this server port unintentionally. In
// order to mitigate the impact of unexpected client
// connections and avoid intermittent failure, it should
// be checked that the accepted connection is really linked
// to the expected client.
boolean clientIsReady = test.waitForClientSignal();
InputStream sslIS = socket.getInputStream();
OutputStream sslOS = socket.getOutputStream();
if (clientIsReady) {
// Run the application in server side.
print("Run server application");
InputStream sslIS = sslSocket.getInputStream();
OutputStream sslOS = sslSocket.getOutputStream();
sslIS.read();
sslOS.write(85);
sslOS.flush();
} else {
System.out.println(
"The client is not the expected one or timeout. "
+ "Ignore in server side.");
}
} finally {
sslSocket.close();
sslServerSocket.close();
}
})
.setClientApplication((socket, test) -> {
String ciphers[] = {
"SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DH_anon_EXPORT_WITH_RC4_40_MD5" };
socket.setEnabledCipherSuites(ciphers);
socket.setUseClientMode(true);
InputStream sslIS = socket.getInputStream();
OutputStream sslOS = socket.getOutputStream();
sslOS.write(280);
sslOS.flush();
sslIS.read();
})
.runTest();
sslOS.write(280);
sslOS.flush();
sslIS.read();
}
}