mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-20 15:25:27 +00:00
8170282: Enable ALPN parameters to be supplied during the TLS handshake
Reviewed-by: wetmore, xuelei
This commit is contained in:
parent
98cc34711b
commit
bd0a13fa21
@ -27,6 +27,8 @@ package javax.net.ssl;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ReadOnlyBufferException;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
|
||||
/**
|
||||
@ -1332,4 +1334,89 @@ public abstract class SSLEngine {
|
||||
public String getHandshakeApplicationProtocol() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback function that selects an application protocol
|
||||
* value for a SSL/TLS/DTLS handshake.
|
||||
* The function overrides any values set using
|
||||
* {@link SSLParameters#setApplicationProtocols
|
||||
* SSLParameters.setApplicationProtocols} and it supports the following
|
||||
* type parameters:
|
||||
* <blockquote>
|
||||
* <dl>
|
||||
* <dt> {@code SSLEngine}
|
||||
* <dd> The function's first argument allows the current {@code SSLEngine}
|
||||
* to be inspected, including the handshake session and configuration
|
||||
* settings.
|
||||
* <dt> {@code List<String>}
|
||||
* <dd> The function's second argument lists the application protocol names
|
||||
* advertised by the TLS peer.
|
||||
* <dt> {@code String}
|
||||
* <dd> The function's result is an application protocol name, or null to
|
||||
* indicate that none of the advertised names are acceptable.
|
||||
* If the return value is null (no value chosen) or is a value that
|
||||
* was not advertised by the peer, the underlying protocol will
|
||||
* determine what action to take. (For example, ALPN will send a
|
||||
* "no_application_protocol" alert and terminate the connection.)
|
||||
* </dl>
|
||||
* </blockquote>
|
||||
*
|
||||
* For example, the following call registers a callback function that
|
||||
* examines the TLS handshake parameters and selects an application protocol
|
||||
* name:
|
||||
* <pre>{@code
|
||||
* serverEngine.setHandshakeApplicationProtocolSelector(
|
||||
* (serverEngine, clientProtocols) -> {
|
||||
* SSLSession session = serverEngine.getHandshakeSession();
|
||||
* return chooseApplicationProtocol(
|
||||
* serverEngine,
|
||||
* clientProtocols,
|
||||
* session.getProtocol(),
|
||||
* session.getCipherSuite());
|
||||
* });
|
||||
* }</pre>
|
||||
*
|
||||
* @apiNote
|
||||
* This method should be called by TLS server applications before the TLS
|
||||
* handshake begins. Also, this {@code SSLEngine} should be configured with
|
||||
* parameters that are compatible with the application protocol selected by
|
||||
* the callback function. For example, enabling a poor choice of cipher
|
||||
* suites could result in no suitable application protocol.
|
||||
* See {@link SSLParameters}.
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this class throws
|
||||
* {@code UnsupportedOperationException} and performs no other action.
|
||||
*
|
||||
* @param selector the callback function, or null to disable the callback
|
||||
* functionality.
|
||||
* @throws UnsupportedOperationException if the underlying provider
|
||||
* does not implement the operation.
|
||||
* @since 9
|
||||
*/
|
||||
public void setHandshakeApplicationProtocolSelector(
|
||||
BiFunction<SSLEngine, List<String>, String> selector) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the callback function that selects an application protocol
|
||||
* value during a SSL/TLS/DTLS handshake.
|
||||
* See {@link #setHandshakeApplicationProtocolSelector
|
||||
* setHandshakeApplicationProtocolSelector}
|
||||
* for the function's type parameters.
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this class throws
|
||||
* {@code UnsupportedOperationException} and performs no other action.
|
||||
*
|
||||
* @return the callback function, or null if none has been set.
|
||||
* @throws UnsupportedOperationException if the underlying provider
|
||||
* does not implement the operation.
|
||||
* @since 9
|
||||
*/
|
||||
public BiFunction<SSLEngine, List<String>, String>
|
||||
getHandshakeApplicationProtocolSelector() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,8 @@ package javax.net.ssl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* This class extends <code>Socket</code>s and provides secure
|
||||
@ -742,4 +744,89 @@ public abstract class SSLSocket extends Socket
|
||||
public String getHandshakeApplicationProtocol() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers a callback function that selects an application protocol
|
||||
* value for a SSL/TLS/DTLS handshake.
|
||||
* The function overrides any values set using
|
||||
* {@link SSLParameters#setApplicationProtocols
|
||||
* SSLParameters.setApplicationProtocols} and it supports the following
|
||||
* type parameters:
|
||||
* <blockquote>
|
||||
* <dl>
|
||||
* <dt> {@code SSLSocket}
|
||||
* <dd> The function's first argument allows the current {@code SSLSocket}
|
||||
* to be inspected, including the handshake session and configuration
|
||||
* settings.
|
||||
* <dt> {@code List<String>}
|
||||
* <dd> The function's second argument lists the application protocol names
|
||||
* advertised by the TLS peer.
|
||||
* <dt> {@code String}
|
||||
* <dd> The function's result is an application protocol name, or null to
|
||||
* indicate that none of the advertised names are acceptable.
|
||||
* If the return value is null (no value chosen) or is a value that
|
||||
* was not advertised by the peer, the underlying protocol will
|
||||
* determine what action to take. (For example, ALPN will send a
|
||||
* "no_application_protocol" alert and terminate the connection.)
|
||||
* </dl>
|
||||
* </blockquote>
|
||||
*
|
||||
* For example, the following call registers a callback function that
|
||||
* examines the TLS handshake parameters and selects an application protocol
|
||||
* name:
|
||||
* <pre>{@code
|
||||
* serverSocket.setHandshakeApplicationProtocolSelector(
|
||||
* (serverSocket, clientProtocols) -> {
|
||||
* SSLSession session = serverSocket.getHandshakeSession();
|
||||
* return chooseApplicationProtocol(
|
||||
* serverSocket,
|
||||
* clientProtocols,
|
||||
* session.getProtocol(),
|
||||
* session.getCipherSuite());
|
||||
* });
|
||||
* }</pre>
|
||||
*
|
||||
* @apiNote
|
||||
* This method should be called by TLS server applications before the TLS
|
||||
* handshake begins. Also, this {@code SSLSocket} should be configured with
|
||||
* parameters that are compatible with the application protocol selected by
|
||||
* the callback function. For example, enabling a poor choice of cipher
|
||||
* suites could result in no suitable application protocol.
|
||||
* See {@link SSLParameters}.
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this class throws
|
||||
* {@code UnsupportedOperationException} and performs no other action.
|
||||
*
|
||||
* @param selector the callback function, or null to de-register.
|
||||
* @throws UnsupportedOperationException if the underlying provider
|
||||
* does not implement the operation.
|
||||
* @since 9
|
||||
*/
|
||||
public void setHandshakeApplicationProtocolSelector(
|
||||
BiFunction<SSLSocket, List<String>, String> selector) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the callback function that selects an application protocol
|
||||
* value during a SSL/TLS/DTLS handshake.
|
||||
* See {@link #setHandshakeApplicationProtocolSelector
|
||||
* setHandshakeApplicationProtocolSelector}
|
||||
* for the function's type parameters.
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this class throws
|
||||
* {@code UnsupportedOperationException} and performs no other action.
|
||||
*
|
||||
* @return the callback function, or null if none has been set.
|
||||
* @throws UnsupportedOperationException if the underlying provider
|
||||
* does not implement the operation.
|
||||
* @since 9
|
||||
*/
|
||||
public BiFunction<SSLSocket, List<String>, String>
|
||||
getHandshakeApplicationProtocolSelector() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,6 +36,7 @@ import java.security.AlgorithmConstraints;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.*;
|
||||
@ -122,6 +123,14 @@ abstract class Handshaker {
|
||||
// Negotiated ALPN value
|
||||
String applicationProtocol = null;
|
||||
|
||||
// Application protocol callback function (for SSLEngine)
|
||||
BiFunction<SSLEngine,List<String>,String>
|
||||
appProtocolSelectorSSLEngine = null;
|
||||
|
||||
// Application protocol callback function (for SSLSocket)
|
||||
BiFunction<SSLSocket,List<String>,String>
|
||||
appProtocolSelectorSSLSocket = null;
|
||||
|
||||
// The maximum expected network packet size for SSL/TLS/DTLS records.
|
||||
int maximumPacketSize = 0;
|
||||
|
||||
@ -500,6 +509,22 @@ abstract class Handshaker {
|
||||
return applicationProtocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Application Protocol selector function for SSLEngine.
|
||||
*/
|
||||
void setApplicationProtocolSelectorSSLEngine(
|
||||
BiFunction<SSLEngine,List<String>,String> selector) {
|
||||
this.appProtocolSelectorSSLEngine = selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Application Protocol selector function for SSLSocket.
|
||||
*/
|
||||
void setApplicationProtocolSelectorSSLSocket(
|
||||
BiFunction<SSLSocket,List<String>,String> selector) {
|
||||
this.appProtocolSelectorSSLSocket = selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cipher suites preference.
|
||||
*/
|
||||
|
||||
@ -27,8 +27,9 @@ package sun.security.ssl;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.*;
|
||||
import java.util.*;
|
||||
import java.security.*;
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
|
||||
@ -206,6 +207,10 @@ public final class SSLEngineImpl extends SSLEngine {
|
||||
// The value under negotiation will be obtained from handshaker.
|
||||
String applicationProtocol = null;
|
||||
|
||||
// Callback function that selects the application protocol value during
|
||||
// the SSL/TLS handshake.
|
||||
BiFunction<SSLEngine, List<String>, String> applicationProtocolSelector;
|
||||
|
||||
// Have we been told whether we're client or server?
|
||||
private boolean serverModeSet = false;
|
||||
private boolean roleIsServer;
|
||||
@ -442,6 +447,8 @@ public final class SSLEngineImpl extends SSLEngine {
|
||||
handshaker.setEnabledCipherSuites(enabledCipherSuites);
|
||||
handshaker.setEnableSessionCreation(enableSessionCreation);
|
||||
handshaker.setApplicationProtocols(applicationProtocols);
|
||||
handshaker.setApplicationProtocolSelectorSSLEngine(
|
||||
applicationProtocolSelector);
|
||||
|
||||
outputRecord.initHandshaker();
|
||||
}
|
||||
@ -2264,6 +2271,21 @@ public final class SSLEngineImpl extends SSLEngine {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setHandshakeApplicationProtocolSelector(
|
||||
BiFunction<SSLEngine, List<String>, String> selector) {
|
||||
applicationProtocolSelector = selector;
|
||||
if ((handshaker != null) && !handshaker.activated()) {
|
||||
handshaker.setApplicationProtocolSelectorSSLEngine(selector);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized BiFunction<SSLEngine, List<String>, String>
|
||||
getHandshakeApplicationProtocolSelector() {
|
||||
return this.applicationProtocolSelector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a printable representation of this end of the connection.
|
||||
*/
|
||||
|
||||
@ -37,6 +37,7 @@ import java.security.AlgorithmConstraints;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.net.ssl.*;
|
||||
@ -223,6 +224,10 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||
// The value under negotiation will be obtained from handshaker.
|
||||
String applicationProtocol = null;
|
||||
|
||||
// Callback function that selects the application protocol value during
|
||||
// the SSL/TLS handshake.
|
||||
BiFunction<SSLSocket, List<String>, String> applicationProtocolSelector;
|
||||
|
||||
/*
|
||||
* READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
|
||||
* IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
|
||||
@ -1370,6 +1375,8 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||
handshaker.setEnabledCipherSuites(enabledCipherSuites);
|
||||
handshaker.setEnableSessionCreation(enableSessionCreation);
|
||||
handshaker.setApplicationProtocols(applicationProtocols);
|
||||
handshaker.setApplicationProtocolSelectorSSLSocket(
|
||||
applicationProtocolSelector);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2658,6 +2665,21 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setHandshakeApplicationProtocolSelector(
|
||||
BiFunction<SSLSocket, List<String>, String> selector) {
|
||||
applicationProtocolSelector = selector;
|
||||
if ((handshaker != null) && !handshaker.activated()) {
|
||||
handshaker.setApplicationProtocolSelectorSSLSocket(selector);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized BiFunction<SSLSocket, List<String>, String>
|
||||
getHandshakeApplicationProtocolSelector() {
|
||||
return this.applicationProtocolSelector;
|
||||
}
|
||||
|
||||
//
|
||||
// We allocate a separate thread to deliver handshake completion
|
||||
// events. This ensures that the notifications don't block the
|
||||
|
||||
@ -34,6 +34,7 @@ import java.security.cert.*;
|
||||
import java.security.interfaces.*;
|
||||
import java.security.spec.ECParameterSpec;
|
||||
import java.math.BigInteger;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.net.ssl.*;
|
||||
@ -532,31 +533,39 @@ final class ServerHandshaker extends Handshaker {
|
||||
ALPNExtension clientHelloALPN = (ALPNExtension)
|
||||
mesg.extensions.get(ExtensionType.EXT_ALPN);
|
||||
|
||||
if ((clientHelloALPN != null) && (localApl.length > 0)) {
|
||||
// Use the application protocol callback when provided.
|
||||
// Otherwise use the local list of application protocols.
|
||||
boolean hasAPCallback =
|
||||
((engine != null && appProtocolSelectorSSLEngine != null) ||
|
||||
(conn != null && appProtocolSelectorSSLSocket != null));
|
||||
|
||||
// Intersect the requested and the locally supported,
|
||||
// and save for later.
|
||||
String negotiatedValue = null;
|
||||
List<String> protocols = clientHelloALPN.getPeerAPs();
|
||||
if (!hasAPCallback) {
|
||||
if ((clientHelloALPN != null) && (localApl.length > 0)) {
|
||||
|
||||
// Use server preference order
|
||||
for (String ap : localApl) {
|
||||
if (protocols.contains(ap)) {
|
||||
negotiatedValue = ap;
|
||||
break;
|
||||
// Intersect the requested and the locally supported,
|
||||
// and save for later.
|
||||
String negotiatedValue = null;
|
||||
List<String> protocols = clientHelloALPN.getPeerAPs();
|
||||
|
||||
// Use server preference order
|
||||
for (String ap : localApl) {
|
||||
if (protocols.contains(ap)) {
|
||||
negotiatedValue = ap;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (negotiatedValue == null) {
|
||||
fatalSE(Alerts.alert_no_application_protocol,
|
||||
new SSLHandshakeException(
|
||||
"No matching ALPN values"));
|
||||
}
|
||||
applicationProtocol = negotiatedValue;
|
||||
if (negotiatedValue == null) {
|
||||
fatalSE(Alerts.alert_no_application_protocol,
|
||||
new SSLHandshakeException(
|
||||
"No matching ALPN values"));
|
||||
}
|
||||
applicationProtocol = negotiatedValue;
|
||||
|
||||
} else {
|
||||
applicationProtocol = "";
|
||||
}
|
||||
} else {
|
||||
applicationProtocol = "";
|
||||
}
|
||||
} // Otherwise, applicationProtocol will be set by the callback.
|
||||
|
||||
session = null; // forget about the current session
|
||||
//
|
||||
@ -892,8 +901,36 @@ final class ServerHandshaker extends Handshaker {
|
||||
}
|
||||
|
||||
// Prepare the ALPN response
|
||||
if (applicationProtocol != null && !applicationProtocol.isEmpty()) {
|
||||
m1.extensions.add(new ALPNExtension(applicationProtocol));
|
||||
if (clientHelloALPN != null) {
|
||||
List<String> peerAPs = clientHelloALPN.getPeerAPs();
|
||||
|
||||
// check for a callback function
|
||||
if (hasAPCallback) {
|
||||
if (conn != null) {
|
||||
applicationProtocol =
|
||||
appProtocolSelectorSSLSocket.apply(conn, peerAPs);
|
||||
} else {
|
||||
applicationProtocol =
|
||||
appProtocolSelectorSSLEngine.apply(engine, peerAPs);
|
||||
}
|
||||
}
|
||||
|
||||
// check for no-match and that the selected name was also proposed
|
||||
// by the TLS peer
|
||||
if (applicationProtocol == null ||
|
||||
(!applicationProtocol.isEmpty() &&
|
||||
!peerAPs.contains(applicationProtocol))) {
|
||||
|
||||
fatalSE(Alerts.alert_no_application_protocol,
|
||||
new SSLHandshakeException(
|
||||
"No matching ALPN values"));
|
||||
|
||||
} else if (!applicationProtocol.isEmpty()) {
|
||||
m1.extensions.add(new ALPNExtension(applicationProtocol));
|
||||
}
|
||||
} else {
|
||||
// Nothing was negotiated, returned at end of the handshake
|
||||
applicationProtocol = "";
|
||||
}
|
||||
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
|
||||
@ -34,15 +34,17 @@ public class MyX509ExtendedKeyManager extends X509ExtendedKeyManager {
|
||||
static final String ERROR = "ERROR";
|
||||
X509ExtendedKeyManager akm;
|
||||
String expectedAP;
|
||||
boolean doCheck = true;
|
||||
|
||||
MyX509ExtendedKeyManager(X509ExtendedKeyManager akm) {
|
||||
this.akm = akm;
|
||||
}
|
||||
|
||||
public MyX509ExtendedKeyManager(
|
||||
X509ExtendedKeyManager akm, String expectedAP) {
|
||||
X509ExtendedKeyManager akm, String expectedAP, boolean doCheck) {
|
||||
this.akm = akm;
|
||||
this.expectedAP = expectedAP;
|
||||
this.doCheck = doCheck;
|
||||
|
||||
}
|
||||
|
||||
@ -104,6 +106,12 @@ public class MyX509ExtendedKeyManager extends X509ExtendedKeyManager {
|
||||
|
||||
private void checkALPN(String ap) {
|
||||
|
||||
if (!doCheck) {
|
||||
System.out.println("Skipping KeyManager checks " +
|
||||
"because a callback has been registered");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ERROR.equals(expectedAP)) {
|
||||
throw new RuntimeException("Should not reach here");
|
||||
}
|
||||
|
||||
@ -26,23 +26,53 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8051498 8145849
|
||||
* @bug 8051498 8145849 8170282
|
||||
* @summary JEP 244: TLS Application-Layer Protocol Negotiation Extension
|
||||
* @compile MyX509ExtendedKeyManager.java
|
||||
* @run main/othervm SSLEngineAlpnTest h2 h2 h2
|
||||
* @run main/othervm SSLEngineAlpnTest h2 h2,http/1.1 h2
|
||||
* @run main/othervm SSLEngineAlpnTest h2,http/1.1 h2,http/1.1 h2
|
||||
* @run main/othervm SSLEngineAlpnTest http/1.1,h2 h2,http/1.1 http/1.1
|
||||
* @run main/othervm SSLEngineAlpnTest h4,h3,h2 h1,h2 h2
|
||||
* @run main/othervm SSLEngineAlpnTest EMPTY h2,http/1.1 NONE
|
||||
* @run main/othervm SSLEngineAlpnTest h2 EMPTY NONE
|
||||
* @run main/othervm SSLEngineAlpnTest H2 h2 ERROR
|
||||
* @run main/othervm SSLEngineAlpnTest h2 http/1.1 ERROR
|
||||
*
|
||||
* @run main/othervm SSLEngineAlpnTest h2 UNUSED h2 h2
|
||||
* @run main/othervm SSLEngineAlpnTest h2 UNUSED h2,http/1.1 h2
|
||||
* @run main/othervm SSLEngineAlpnTest h2,http/1.1 UNUSED h2,http/1.1 h2
|
||||
* @run main/othervm SSLEngineAlpnTest http/1.1,h2 UNUSED h2,http/1.1 http/1.1
|
||||
* @run main/othervm SSLEngineAlpnTest h4,h3,h2 UNUSED h1,h2 h2
|
||||
* @run main/othervm SSLEngineAlpnTest EMPTY UNUSED h2,http/1.1 NONE
|
||||
* @run main/othervm SSLEngineAlpnTest h2 UNUSED EMPTY NONE
|
||||
* @run main/othervm SSLEngineAlpnTest H2 UNUSED h2 ERROR
|
||||
* @run main/othervm SSLEngineAlpnTest h2 UNUSED http/1.1 ERROR
|
||||
*
|
||||
* @run main/othervm SSLEngineAlpnTest UNUSED h2 h2 h2
|
||||
* @run main/othervm SSLEngineAlpnTest UNUSED h2 h2,http/1.1 h2
|
||||
* @run main/othervm SSLEngineAlpnTest UNUSED h2 http/1.1,h2 h2
|
||||
* @run main/othervm SSLEngineAlpnTest UNUSED http/1.1 h2,http/1.1 http/1.1
|
||||
* @run main/othervm SSLEngineAlpnTest UNUSED EMPTY h2,http/1.1 NONE
|
||||
* @run main/othervm SSLEngineAlpnTest UNUSED h2 EMPTY NONE
|
||||
* @run main/othervm SSLEngineAlpnTest UNUSED H2 h2 ERROR
|
||||
* @run main/othervm SSLEngineAlpnTest UNUSED h2 http/1.1 ERROR
|
||||
*
|
||||
* @run main/othervm SSLEngineAlpnTest h2 h2 h2 h2
|
||||
* @run main/othervm SSLEngineAlpnTest H2 h2 h2,http/1.1 h2
|
||||
* @run main/othervm SSLEngineAlpnTest h2,http/1.1 http/1.1 h2,http/1.1 http/1.1
|
||||
* @run main/othervm SSLEngineAlpnTest http/1.1,h2 h2 h2,http/1.1 h2
|
||||
* @run main/othervm SSLEngineAlpnTest EMPTY h2 h2 h2
|
||||
* @run main/othervm SSLEngineAlpnTest h2,http/1.1 EMPTY http/1.1 NONE
|
||||
* @run main/othervm SSLEngineAlpnTest h2,http/1.1 h2 EMPTY NONE
|
||||
* @run main/othervm SSLEngineAlpnTest UNUSED UNUSED http/1.1,h2 NONE
|
||||
* @run main/othervm SSLEngineAlpnTest h2 h2 http/1.1 ERROR
|
||||
* @run main/othervm SSLEngineAlpnTest h2,http/1.1 H2 http/1.1 ERROR
|
||||
*/
|
||||
/**
|
||||
* A simple SSLEngine-based client/server that demonstrates the proposed API
|
||||
* changes for JEP 244 in support of the TLS ALPN extension (RFC 7301).
|
||||
*
|
||||
* Usage:
|
||||
* java SSLEngineAlpnTest <server-APs> <callback-AP> <client-APs> <result>
|
||||
*
|
||||
* where:
|
||||
* EMPTY indicates that ALPN is disabled
|
||||
* UNUSED indicates that no ALPN values are supplied (server-side only)
|
||||
* ERROR indicates that an exception is expected
|
||||
* NONE indicates that no ALPN is expected
|
||||
*
|
||||
* This example is based on our standard SSLEngineTemplate.
|
||||
*
|
||||
* The immediate consumer of ALPN will be HTTP/2 (RFC 7540), aka H2. The H2 IETF
|
||||
@ -98,6 +128,7 @@ import javax.net.ssl.SSLEngineResult.*;
|
||||
import java.io.*;
|
||||
import java.security.*;
|
||||
import java.nio.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class SSLEngineAlpnTest {
|
||||
|
||||
@ -117,6 +148,9 @@ public class SSLEngineAlpnTest {
|
||||
*/
|
||||
private static final boolean debug = false;
|
||||
|
||||
private static boolean hasServerAPs; // whether server APs are present
|
||||
private static boolean hasCallback; // whether a callback is present
|
||||
|
||||
private final SSLContext sslc;
|
||||
|
||||
private SSLEngine clientEngine; // client Engine
|
||||
@ -157,17 +191,21 @@ public class SSLEngineAlpnTest {
|
||||
if (debug) {
|
||||
System.setProperty("javax.net.debug", "all");
|
||||
}
|
||||
System.out.println("Test args: " + Arrays.toString(args));
|
||||
|
||||
// Validate parameters
|
||||
if (args.length != 3) {
|
||||
if (args.length != 4) {
|
||||
throw new Exception("Invalid number of test parameters");
|
||||
}
|
||||
|
||||
SSLEngineAlpnTest test = new SSLEngineAlpnTest(args[2]);
|
||||
hasServerAPs = !args[0].equals("UNUSED"); // are server APs being used?
|
||||
hasCallback = !args[1].equals("UNUSED"); // is callback being used?
|
||||
|
||||
SSLEngineAlpnTest test = new SSLEngineAlpnTest(args[3]);
|
||||
try {
|
||||
test.runTest(convert(args[0]), convert(args[1]), args[2]);
|
||||
test.runTest(convert(args[0]), args[1], convert(args[2]), args[3]);
|
||||
} catch (SSLHandshakeException she) {
|
||||
if (args[2].equals("ERROR")) {
|
||||
if (args[3].equals("ERROR")) {
|
||||
System.out.println("Caught the expected exception: " + she);
|
||||
} else {
|
||||
throw she;
|
||||
@ -199,7 +237,8 @@ public class SSLEngineAlpnTest {
|
||||
}
|
||||
|
||||
kms = new KeyManager[] { new MyX509ExtendedKeyManager(
|
||||
(X509ExtendedKeyManager) kms[0], expectedAP) };
|
||||
(X509ExtendedKeyManager) kms[0], expectedAP,
|
||||
!hasCallback && hasServerAPs) };
|
||||
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
|
||||
tmf.init(ts);
|
||||
@ -215,12 +254,15 @@ public class SSLEngineAlpnTest {
|
||||
* Convert a comma-separated list into an array of strings.
|
||||
*/
|
||||
private static String[] convert(String list) {
|
||||
String[] strings = null;
|
||||
if (list.equals("UNUSED")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (list.equals("EMPTY")) {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
String[] strings;
|
||||
if (list.indexOf(',') > 0) {
|
||||
strings = list.split(",");
|
||||
} else {
|
||||
@ -247,12 +289,12 @@ public class SSLEngineAlpnTest {
|
||||
* One could easily separate these phases into separate
|
||||
* sections of code.
|
||||
*/
|
||||
private void runTest(String[] serverAPs, String[] clientAPs,
|
||||
String expectedAP) throws Exception {
|
||||
private void runTest(String[] serverAPs, String callbackAP,
|
||||
String[] clientAPs, String expectedAP) throws Exception {
|
||||
|
||||
boolean dataDone = false;
|
||||
|
||||
createSSLEngines(serverAPs, clientAPs);
|
||||
createSSLEngines(serverAPs, callbackAP, clientAPs);
|
||||
createBuffers();
|
||||
|
||||
SSLEngineResult clientResult; // results from client's last operation
|
||||
@ -364,8 +406,8 @@ public class SSLEngineAlpnTest {
|
||||
* Using the SSLContext created during object creation,
|
||||
* create/configure the SSLEngines we'll use for this test.
|
||||
*/
|
||||
private void createSSLEngines(String[] serverAPs, String[] clientAPs)
|
||||
throws Exception {
|
||||
private void createSSLEngines(String[] serverAPs, String callbackAP,
|
||||
String[] clientAPs) throws Exception {
|
||||
/*
|
||||
* Configure the serverEngine to act as a server in the SSL/TLS
|
||||
* handshake. Also, require SSL client authentication.
|
||||
@ -385,18 +427,42 @@ public class SSLEngineAlpnTest {
|
||||
*/
|
||||
String[] suites = sslp.getCipherSuites();
|
||||
sslp.setCipherSuites(suites);
|
||||
sslp.setApplicationProtocols(serverAPs);
|
||||
if (serverAPs != null) {
|
||||
sslp.setApplicationProtocols(serverAPs);
|
||||
}
|
||||
sslp.setUseCipherSuitesOrder(true); // Set server side order
|
||||
|
||||
serverEngine.setSSLParameters(sslp);
|
||||
|
||||
// check that no callback has been registered
|
||||
if (serverEngine.getHandshakeApplicationProtocolSelector() != null) {
|
||||
throw new Exception("getHandshakeApplicationProtocolSelector() " +
|
||||
"should return null");
|
||||
}
|
||||
|
||||
if (hasCallback) {
|
||||
serverEngine.setHandshakeApplicationProtocolSelector(
|
||||
(sslEngine, clientProtocols) -> {
|
||||
return callbackAP.equals("EMPTY") ? "" : callbackAP;
|
||||
});
|
||||
|
||||
// check that the callback can be retrieved
|
||||
if (serverEngine.getHandshakeApplicationProtocolSelector()
|
||||
== null) {
|
||||
throw new Exception("getHandshakeApplicationProtocolSelector()"
|
||||
+ " should return non-null");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Similar to above, but using client mode instead.
|
||||
*/
|
||||
clientEngine = sslc.createSSLEngine("client", 80);
|
||||
clientEngine.setUseClientMode(true);
|
||||
sslp = clientEngine.getSSLParameters();
|
||||
sslp.setApplicationProtocols(clientAPs);
|
||||
if (clientAPs != null) {
|
||||
sslp.setApplicationProtocols(clientAPs);
|
||||
}
|
||||
clientEngine.setSSLParameters(sslp);
|
||||
|
||||
if ((clientEngine.getHandshakeApplicationProtocol() != null) ||
|
||||
|
||||
@ -26,22 +26,61 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8051498 8145849 8158978
|
||||
* @bug 8051498 8145849 8158978 8170282
|
||||
* @summary JEP 244: TLS Application-Layer Protocol Negotiation Extension
|
||||
* @compile MyX509ExtendedKeyManager.java
|
||||
* @run main/othervm SSLServerSocketAlpnTest h2 h2 h2
|
||||
* @run main/othervm SSLServerSocketAlpnTest h2 h2,http/1.1 h2
|
||||
* @run main/othervm SSLServerSocketAlpnTest h2,http/1.1 h2,http/1.1 h2
|
||||
* @run main/othervm SSLServerSocketAlpnTest http/1.1,h2 h2,http/1.1 http/1.1
|
||||
* @run main/othervm SSLServerSocketAlpnTest h4,h3,h2 h1,h2 h2
|
||||
* @run main/othervm SSLServerSocketAlpnTest EMPTY h2,http/1.1 NONE
|
||||
* @run main/othervm SSLServerSocketAlpnTest h2 EMPTY NONE
|
||||
* @run main/othervm SSLServerSocketAlpnTest H2 h2 ERROR
|
||||
* @run main/othervm SSLServerSocketAlpnTest h2 http/1.1 ERROR
|
||||
*
|
||||
* @run main/othervm SSLServerSocketAlpnTest h2 UNUSED h2 h2
|
||||
* @run main/othervm SSLServerSocketAlpnTest h2 UNUSED h2,http/1.1 h2
|
||||
* @run main/othervm SSLServerSocketAlpnTest h2,http/1.1 UNUSED h2,http/1.1 h2
|
||||
* @run main/othervm SSLServerSocketAlpnTest http/1.1,h2 UNUSED h2,http/1.1 http/1.1
|
||||
* @run main/othervm SSLServerSocketAlpnTest h4,h3,h2 UNUSED h1,h2 h2
|
||||
* @run main/othervm SSLServerSocketAlpnTest EMPTY UNUSED h2,http/1.1 NONE
|
||||
* @run main/othervm SSLServerSocketAlpnTest h2 UNUSED EMPTY NONE
|
||||
* @run main/othervm SSLServerSocketAlpnTest H2 UNUSED h2 ERROR
|
||||
* @run main/othervm SSLServerSocketAlpnTest h2 UNUSED http/1.1 ERROR
|
||||
*
|
||||
* @run main/othervm SSLServerSocketAlpnTest UNUSED h2 h2 h2
|
||||
* @run main/othervm SSLServerSocketAlpnTest UNUSED h2 h2,http/1.1 h2
|
||||
* @run main/othervm SSLServerSocketAlpnTest UNUSED h2 http/1.1,h2 h2
|
||||
* @run main/othervm SSLServerSocketAlpnTest UNUSED http/1.1 h2,http/1.1 http/1.1
|
||||
* @run main/othervm SSLServerSocketAlpnTest UNUSED EMPTY h2,http/1.1 NONE
|
||||
* @run main/othervm SSLServerSocketAlpnTest UNUSED h2 EMPTY NONE
|
||||
* @run main/othervm SSLServerSocketAlpnTest UNUSED H2 h2 ERROR
|
||||
* @run main/othervm SSLServerSocketAlpnTest UNUSED h2 http/1.1 ERROR
|
||||
*
|
||||
* @run main/othervm SSLServerSocketAlpnTest h2 h2 h2 h2
|
||||
* @run main/othervm SSLServerSocketAlpnTest H2 h2 h2,http/1.1 h2
|
||||
* @run main/othervm SSLServerSocketAlpnTest h2,http/1.1 http/1.1 h2,http/1.1 http/1.1
|
||||
* @run main/othervm SSLServerSocketAlpnTest http/1.1,h2 h2 h2,http/1.1 h2
|
||||
* @run main/othervm SSLServerSocketAlpnTest EMPTY h2 h2 h2
|
||||
* @run main/othervm SSLServerSocketAlpnTest h2,http/1.1 EMPTY http/1.1 NONE
|
||||
* @run main/othervm SSLServerSocketAlpnTest h2,http/1.1 h2 EMPTY NONE
|
||||
* @run main/othervm SSLServerSocketAlpnTest UNUSED UNUSED http/1.1,h2 NONE
|
||||
* @run main/othervm SSLServerSocketAlpnTest h2 h2 http/1.1 ERROR
|
||||
* @run main/othervm SSLServerSocketAlpnTest h2,http/1.1 H2 http/1.1 ERROR
|
||||
*
|
||||
* @author Brad Wetmore
|
||||
*/
|
||||
/**
|
||||
* A simple SSLSocket-based client/server that demonstrates the proposed API
|
||||
* changes for JEP 244 in support of the TLS ALPN extension (RFC 7301).
|
||||
*
|
||||
* Usage:
|
||||
* java SSLServerSocketAlpnTest
|
||||
* <server-APs> <callback-AP> <client-APs> <result>
|
||||
*
|
||||
* where:
|
||||
* EMPTY indicates that ALPN is disabled
|
||||
* UNUSED indicates that no ALPN values are supplied (server-side only)
|
||||
* ERROR indicates that an exception is expected
|
||||
* NONE indicates that no ALPN is expected
|
||||
*
|
||||
* This example is based on our standard SSLSocketTemplate.
|
||||
*/
|
||||
import java.io.*;
|
||||
import java.security.KeyStore;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
|
||||
@ -73,6 +112,9 @@ public class SSLServerSocketAlpnTest {
|
||||
static String trustFilename = System.getProperty("test.src", ".") + "/"
|
||||
+ pathToStores + "/" + trustStoreFile;
|
||||
|
||||
private static boolean hasServerAPs; // whether server APs are present
|
||||
private static boolean hasCallback; // whether a callback is present
|
||||
|
||||
/*
|
||||
* SSLContext
|
||||
*/
|
||||
@ -89,6 +131,7 @@ public class SSLServerSocketAlpnTest {
|
||||
static boolean debug = false;
|
||||
|
||||
static String[] serverAPs;
|
||||
static String callbackAP;
|
||||
static String[] clientAPs;
|
||||
static String expectedAP;
|
||||
|
||||
@ -129,7 +172,9 @@ public class SSLServerSocketAlpnTest {
|
||||
sslp.setUseCipherSuitesOrder(true); // Set server side order
|
||||
|
||||
// Set the ALPN selection.
|
||||
sslp.setApplicationProtocols(serverAPs);
|
||||
if (serverAPs != null) {
|
||||
sslp.setApplicationProtocols(serverAPs);
|
||||
}
|
||||
sslServerSocket.setSSLParameters(sslp);
|
||||
|
||||
serverPort = sslServerSocket.getLocalPort();
|
||||
@ -146,6 +191,25 @@ public class SSLServerSocketAlpnTest {
|
||||
+ "return null before the handshake starts");
|
||||
}
|
||||
|
||||
// check that no callback has been registered
|
||||
if (sslSocket.getHandshakeApplicationProtocolSelector() != null) {
|
||||
throw new Exception("getHandshakeApplicationProtocolSelector() " +
|
||||
"should return null");
|
||||
}
|
||||
|
||||
if (hasCallback) {
|
||||
sslSocket.setHandshakeApplicationProtocolSelector(
|
||||
(serverSocket, clientProtocols) -> {
|
||||
return callbackAP.equals("EMPTY") ? "" : callbackAP;
|
||||
});
|
||||
|
||||
// check that the callback can be retrieved
|
||||
if (sslSocket.getHandshakeApplicationProtocolSelector() == null) {
|
||||
throw new Exception("getHandshakeApplicationProtocolSelector()"
|
||||
+ " should return non-null");
|
||||
}
|
||||
}
|
||||
|
||||
sslSocket.startHandshake();
|
||||
|
||||
if (sslSocket.getHandshakeApplicationProtocol() != null) {
|
||||
@ -276,14 +340,19 @@ public class SSLServerSocketAlpnTest {
|
||||
if (debug) {
|
||||
System.setProperty("javax.net.debug", "all");
|
||||
}
|
||||
System.out.println("Test args: " + Arrays.toString(args));
|
||||
|
||||
// Validate parameters
|
||||
if (args.length != 3) {
|
||||
if (args.length != 4) {
|
||||
throw new Exception("Invalid number of test parameters");
|
||||
}
|
||||
serverAPs = convert(args[0]);
|
||||
clientAPs = convert(args[1]);
|
||||
expectedAP = args[2];
|
||||
callbackAP = args[1];
|
||||
clientAPs = convert(args[2]);
|
||||
expectedAP = args[3];
|
||||
|
||||
hasServerAPs = !args[0].equals("UNUSED"); // are server APs being used?
|
||||
hasCallback = !callbackAP.equals("UNUSED"); // is callback being used?
|
||||
|
||||
/*
|
||||
* Start the tests.
|
||||
@ -291,7 +360,7 @@ public class SSLServerSocketAlpnTest {
|
||||
try {
|
||||
new SSLServerSocketAlpnTest();
|
||||
} catch (SSLHandshakeException she) {
|
||||
if (args[2].equals("ERROR")) {
|
||||
if (args[3].equals("ERROR")) {
|
||||
System.out.println("Caught the expected exception: " + she);
|
||||
} else {
|
||||
throw she;
|
||||
@ -322,7 +391,8 @@ public class SSLServerSocketAlpnTest {
|
||||
}
|
||||
|
||||
kms = new KeyManager[] { new MyX509ExtendedKeyManager(
|
||||
(X509ExtendedKeyManager) kms[0], expectedAP) };
|
||||
(X509ExtendedKeyManager) kms[0], expectedAP,
|
||||
!hasCallback && hasServerAPs) };
|
||||
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
|
||||
tmf.init(trustKS);
|
||||
@ -338,12 +408,15 @@ public class SSLServerSocketAlpnTest {
|
||||
* Convert a comma-separated list into an array of strings.
|
||||
*/
|
||||
private static String[] convert(String list) {
|
||||
String[] strings;
|
||||
if (list.equals("UNUSED")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (list.equals("EMPTY")) {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
String[] strings;
|
||||
if (list.indexOf(',') > 0) {
|
||||
strings = list.split(",");
|
||||
} else {
|
||||
|
||||
@ -26,22 +26,60 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8051498 8145849
|
||||
* @bug 8051498 8145849 8170282
|
||||
* @summary JEP 244: TLS Application-Layer Protocol Negotiation Extension
|
||||
* @compile MyX509ExtendedKeyManager.java
|
||||
* @run main/othervm SSLSocketAlpnTest h2 h2 h2
|
||||
* @run main/othervm SSLSocketAlpnTest h2 h2,http/1.1 h2
|
||||
* @run main/othervm SSLSocketAlpnTest h2,http/1.1 h2,http/1.1 h2
|
||||
* @run main/othervm SSLSocketAlpnTest http/1.1,h2 h2,http/1.1 http/1.1
|
||||
* @run main/othervm SSLSocketAlpnTest h4,h3,h2 h1,h2 h2
|
||||
* @run main/othervm SSLSocketAlpnTest EMPTY h2,http/1.1 NONE
|
||||
* @run main/othervm SSLSocketAlpnTest h2 EMPTY NONE
|
||||
* @run main/othervm SSLSocketAlpnTest H2 h2 ERROR
|
||||
* @run main/othervm SSLSocketAlpnTest h2 http/1.1 ERROR
|
||||
*
|
||||
* @run main/othervm SSLSocketAlpnTest h2 UNUSED h2 h2
|
||||
* @run main/othervm SSLSocketAlpnTest h2 UNUSED h2,http/1.1 h2
|
||||
* @run main/othervm SSLSocketAlpnTest h2,http/1.1 UNUSED h2,http/1.1 h2
|
||||
* @run main/othervm SSLSocketAlpnTest http/1.1,h2 UNUSED h2,http/1.1 http/1.1
|
||||
* @run main/othervm SSLSocketAlpnTest h4,h3,h2 UNUSED h1,h2 h2
|
||||
* @run main/othervm SSLSocketAlpnTest EMPTY UNUSED h2,http/1.1 NONE
|
||||
* @run main/othervm SSLSocketAlpnTest h2 UNUSED EMPTY NONE
|
||||
* @run main/othervm SSLSocketAlpnTest H2 UNUSED h2 ERROR
|
||||
* @run main/othervm SSLSocketAlpnTest h2 UNUSED http/1.1 ERROR
|
||||
*
|
||||
* @run main/othervm SSLSocketAlpnTest UNUSED h2 h2 h2
|
||||
* @run main/othervm SSLSocketAlpnTest UNUSED h2 h2,http/1.1 h2
|
||||
* @run main/othervm SSLSocketAlpnTest UNUSED h2 http/1.1,h2 h2
|
||||
* @run main/othervm SSLSocketAlpnTest UNUSED http/1.1 h2,http/1.1 http/1.1
|
||||
* @run main/othervm SSLSocketAlpnTest UNUSED EMPTY h2,http/1.1 NONE
|
||||
* @run main/othervm SSLSocketAlpnTest UNUSED h2 EMPTY NONE
|
||||
* @run main/othervm SSLSocketAlpnTest UNUSED H2 h2 ERROR
|
||||
* @run main/othervm SSLSocketAlpnTest UNUSED h2 http/1.1 ERROR
|
||||
*
|
||||
* @run main/othervm SSLSocketAlpnTest h2 h2 h2 h2
|
||||
* @run main/othervm SSLSocketAlpnTest H2 h2 h2,http/1.1 h2
|
||||
* @run main/othervm SSLSocketAlpnTest h2,http/1.1 http/1.1 h2,http/1.1 http/1.1
|
||||
* @run main/othervm SSLSocketAlpnTest http/1.1,h2 h2 h2,http/1.1 h2
|
||||
* @run main/othervm SSLSocketAlpnTest EMPTY h2 h2 h2
|
||||
* @run main/othervm SSLSocketAlpnTest h2,http/1.1 EMPTY http/1.1 NONE
|
||||
* @run main/othervm SSLSocketAlpnTest h2,http/1.1 h2 EMPTY NONE
|
||||
* @run main/othervm SSLSocketAlpnTest UNUSED UNUSED http/1.1,h2 NONE
|
||||
* @run main/othervm SSLSocketAlpnTest h2 h2 http/1.1 ERROR
|
||||
* @run main/othervm SSLSocketAlpnTest h2,http/1.1 H2 http/1.1 ERROR
|
||||
*
|
||||
* @author Brad Wetmore
|
||||
*/
|
||||
/**
|
||||
* A simple SSLSocket-based client/server that demonstrates the proposed API
|
||||
* changes for JEP 244 in support of the TLS ALPN extension (RFC 7301).
|
||||
*
|
||||
* Usage:
|
||||
* java SSLSocketAlpnTest <server-APs> <callback-AP> <client-APs> <result>
|
||||
*
|
||||
* where:
|
||||
* EMPTY indicates that ALPN is disabled
|
||||
* UNUSED indicates that no ALPN values are supplied (server-side only)
|
||||
* ERROR indicates that an exception is expected
|
||||
* NONE indicates that no ALPN is expected
|
||||
*
|
||||
* This example is based on our standard SSLSocketTemplate.
|
||||
*/
|
||||
import java.io.*;
|
||||
import java.security.KeyStore;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
|
||||
@ -73,6 +111,9 @@ public class SSLSocketAlpnTest {
|
||||
static String trustFilename = System.getProperty("test.src", ".") + "/"
|
||||
+ pathToStores + "/" + trustStoreFile;
|
||||
|
||||
private static boolean hasServerAPs; // whether server APs are present
|
||||
private static boolean hasCallback; // whether a callback is present
|
||||
|
||||
/*
|
||||
* SSLContext
|
||||
*/
|
||||
@ -89,6 +130,7 @@ public class SSLSocketAlpnTest {
|
||||
static boolean debug = false;
|
||||
|
||||
static String[] serverAPs;
|
||||
static String callbackAP;
|
||||
static String[] clientAPs;
|
||||
static String expectedAP;
|
||||
|
||||
@ -136,7 +178,9 @@ public class SSLSocketAlpnTest {
|
||||
sslp.setUseCipherSuitesOrder(true); // Set server side order
|
||||
|
||||
// Set the ALPN selection.
|
||||
sslp.setApplicationProtocols(serverAPs);
|
||||
if (serverAPs != null) {
|
||||
sslp.setApplicationProtocols(serverAPs);
|
||||
}
|
||||
sslSocket.setSSLParameters(sslp);
|
||||
|
||||
if (sslSocket.getHandshakeApplicationProtocol() != null) {
|
||||
@ -144,6 +188,24 @@ public class SSLSocketAlpnTest {
|
||||
+ "return null before the handshake starts");
|
||||
}
|
||||
|
||||
// check that no callback has been registered
|
||||
if (sslSocket.getHandshakeApplicationProtocolSelector() != null) {
|
||||
throw new Exception("getHandshakeApplicationProtocolSelector() " +
|
||||
"should return null");
|
||||
}
|
||||
|
||||
if (hasCallback) {
|
||||
sslSocket.setHandshakeApplicationProtocolSelector(
|
||||
(serverSocket, clientProtocols) -> {
|
||||
return callbackAP.equals("EMPTY") ? "" : callbackAP;
|
||||
});
|
||||
|
||||
// check that the callback can be retrieved
|
||||
if (sslSocket.getHandshakeApplicationProtocolSelector() == null) {
|
||||
throw new Exception("getHandshakeApplicationProtocolSelector()" + " should return non-null");
|
||||
}
|
||||
}
|
||||
|
||||
sslSocket.startHandshake();
|
||||
|
||||
if (sslSocket.getHandshakeApplicationProtocol() != null) {
|
||||
@ -274,14 +336,19 @@ public class SSLSocketAlpnTest {
|
||||
if (debug) {
|
||||
System.setProperty("javax.net.debug", "all");
|
||||
}
|
||||
System.out.println("Test args: " + Arrays.toString(args));
|
||||
|
||||
// Validate parameters
|
||||
if (args.length != 3) {
|
||||
if (args.length != 4) {
|
||||
throw new Exception("Invalid number of test parameters");
|
||||
}
|
||||
serverAPs = convert(args[0]);
|
||||
clientAPs = convert(args[1]);
|
||||
expectedAP = args[2];
|
||||
callbackAP = args[1];
|
||||
clientAPs = convert(args[2]);
|
||||
expectedAP = args[3];
|
||||
|
||||
hasServerAPs = !args[0].equals("UNUSED"); // are server APs being used?
|
||||
hasCallback = !callbackAP.equals("UNUSED"); // is callback being used?
|
||||
|
||||
/*
|
||||
* Start the tests.
|
||||
@ -289,7 +356,7 @@ public class SSLSocketAlpnTest {
|
||||
try {
|
||||
new SSLSocketAlpnTest();
|
||||
} catch (SSLHandshakeException she) {
|
||||
if (args[2].equals("ERROR")) {
|
||||
if (args[3].equals("ERROR")) {
|
||||
System.out.println("Caught the expected exception: " + she);
|
||||
} else {
|
||||
throw she;
|
||||
@ -320,7 +387,8 @@ public class SSLSocketAlpnTest {
|
||||
}
|
||||
|
||||
kms = new KeyManager[] { new MyX509ExtendedKeyManager(
|
||||
(X509ExtendedKeyManager) kms[0], expectedAP) };
|
||||
(X509ExtendedKeyManager) kms[0], expectedAP,
|
||||
!hasCallback && hasServerAPs) };
|
||||
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
|
||||
tmf.init(trustKS);
|
||||
@ -336,12 +404,15 @@ public class SSLSocketAlpnTest {
|
||||
* Convert a comma-separated list into an array of strings.
|
||||
*/
|
||||
private static String[] convert(String list) {
|
||||
String[] strings;
|
||||
if (list.equals("UNUSED")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (list.equals("EMPTY")) {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
String[] strings;
|
||||
if (list.indexOf(',') > 0) {
|
||||
strings = list.split(",");
|
||||
} else {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user