mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-10 10:28:37 +00:00
8145849: ALPN: getHandshakeApplicationProtocol() always return null
Reviewed-by: wetmore, vinnie
This commit is contained in:
parent
717c4699a8
commit
751dd7f031
@ -2211,7 +2211,7 @@ public final class SSLEngineImpl extends SSLEngine {
|
||||
|
||||
@Override
|
||||
public synchronized String getHandshakeApplicationProtocol() {
|
||||
if ((handshaker != null) && !handshaker.started()) {
|
||||
if ((handshaker != null) && handshaker.started()) {
|
||||
return handshaker.getHandshakeApplicationProtocol();
|
||||
}
|
||||
return null;
|
||||
|
||||
@ -2598,7 +2598,7 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||
|
||||
@Override
|
||||
public synchronized String getHandshakeApplicationProtocol() {
|
||||
if ((handshaker != null) && !handshaker.started()) {
|
||||
if ((handshaker != null) && handshaker.started()) {
|
||||
return handshaker.getHandshakeApplicationProtocol();
|
||||
}
|
||||
return null;
|
||||
|
||||
130
jdk/test/javax/net/ssl/ALPN/MyX509ExtendedKeyManager.java
Normal file
130
jdk/test/javax/net/ssl/ALPN/MyX509ExtendedKeyManager.java
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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.net.Socket;
|
||||
import java.security.Principal;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.X509ExtendedKeyManager;
|
||||
|
||||
public class MyX509ExtendedKeyManager extends X509ExtendedKeyManager {
|
||||
|
||||
static final String ERROR = "ERROR";
|
||||
X509ExtendedKeyManager akm;
|
||||
String expectedAP;
|
||||
|
||||
MyX509ExtendedKeyManager(X509ExtendedKeyManager akm) {
|
||||
this.akm = akm;
|
||||
}
|
||||
|
||||
public MyX509ExtendedKeyManager(
|
||||
X509ExtendedKeyManager akm, String expectedAP) {
|
||||
this.akm = akm;
|
||||
this.expectedAP = expectedAP;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getClientAliases(String keyType, Principal[] issuers) {
|
||||
return akm.getClientAliases(keyType, issuers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String chooseClientAlias(String[] keyType, Principal[] issuers,
|
||||
Socket socket) {
|
||||
String nap = ((SSLSocket) socket).getHandshakeApplicationProtocol();
|
||||
checkALPN(nap);
|
||||
|
||||
return akm.chooseClientAlias(keyType, issuers, socket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getServerAliases(String keyType, Principal[] issuers) {
|
||||
return akm.getServerAliases(keyType, issuers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String chooseServerAlias(String keyType, Principal[] issuers,
|
||||
Socket socket) {
|
||||
String nap = ((SSLSocket) socket).getHandshakeApplicationProtocol();
|
||||
checkALPN(nap);
|
||||
|
||||
return akm.chooseServerAlias(keyType, issuers, socket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getCertificateChain(String alias) {
|
||||
return akm.getCertificateChain(alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrivateKey getPrivateKey(String alias) {
|
||||
return akm.getPrivateKey(alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String chooseEngineClientAlias(String[] keyType, Principal[] issuers,
|
||||
SSLEngine engine) {
|
||||
String nap = engine.getHandshakeApplicationProtocol();
|
||||
checkALPN(nap);
|
||||
|
||||
return akm.chooseEngineClientAlias(keyType, issuers, engine);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String chooseEngineServerAlias(String keyType, Principal[] issuers,
|
||||
SSLEngine engine) {
|
||||
String nap = engine.getHandshakeApplicationProtocol();
|
||||
checkALPN(nap);
|
||||
|
||||
return akm.chooseEngineServerAlias(keyType, issuers, engine);
|
||||
}
|
||||
|
||||
private void checkALPN(String ap) {
|
||||
|
||||
if (ERROR.equals(expectedAP)) {
|
||||
throw new RuntimeException("Should not reach here");
|
||||
}
|
||||
|
||||
System.out.println("Expected ALPN value: " + expectedAP
|
||||
+ " Got: " + ap);
|
||||
|
||||
if (ap == null) {
|
||||
throw new RuntimeException(
|
||||
"ALPN should be negotiated, but null was received");
|
||||
}
|
||||
if (expectedAP.equals("NONE")) {
|
||||
if (!ap.isEmpty()) {
|
||||
throw new RuntimeException("Expected no ALPN value");
|
||||
} else {
|
||||
System.out.println("No ALPN value negotiated, as expected");
|
||||
}
|
||||
} else if (!expectedAP.equals(ap)) {
|
||||
throw new RuntimeException(expectedAP
|
||||
+ " ALPN value not available on negotiated connection");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 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
|
||||
@ -26,8 +26,9 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8051498
|
||||
* @bug 8051498 8145849
|
||||
* @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
|
||||
@ -162,7 +163,7 @@ public class SSLEngineAlpnTest {
|
||||
throw new Exception("Invalid number of test parameters");
|
||||
}
|
||||
|
||||
SSLEngineAlpnTest test = new SSLEngineAlpnTest();
|
||||
SSLEngineAlpnTest test = new SSLEngineAlpnTest(args[2]);
|
||||
try {
|
||||
test.runTest(convert(args[0]), convert(args[1]), args[2]);
|
||||
} catch (SSLHandshakeException she) {
|
||||
@ -179,7 +180,7 @@ public class SSLEngineAlpnTest {
|
||||
/*
|
||||
* Create an initialized SSLContext to use for these tests.
|
||||
*/
|
||||
public SSLEngineAlpnTest() throws Exception {
|
||||
public SSLEngineAlpnTest(String expectedAP) throws Exception {
|
||||
|
||||
KeyStore ks = KeyStore.getInstance("JKS");
|
||||
KeyStore ts = KeyStore.getInstance("JKS");
|
||||
@ -192,12 +193,20 @@ public class SSLEngineAlpnTest {
|
||||
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
|
||||
kmf.init(ks, passphrase);
|
||||
|
||||
KeyManager [] kms = kmf.getKeyManagers();
|
||||
if (!(kms[0] instanceof X509ExtendedKeyManager)) {
|
||||
throw new Exception("kms[0] not X509ExtendedKeyManager");
|
||||
}
|
||||
|
||||
kms = new KeyManager[] { new MyX509ExtendedKeyManager(
|
||||
(X509ExtendedKeyManager) kms[0], expectedAP) };
|
||||
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
|
||||
tmf.init(ts);
|
||||
|
||||
SSLContext sslCtx = SSLContext.getInstance("TLS");
|
||||
|
||||
sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
||||
sslCtx.init(kms, tmf.getTrustManagers(), null);
|
||||
|
||||
sslc = sslCtx;
|
||||
}
|
||||
@ -327,6 +336,11 @@ public class SSLEngineAlpnTest {
|
||||
return;
|
||||
}
|
||||
|
||||
if (engine.getHandshakeApplicationProtocol() != null) {
|
||||
throw new Exception ("getHandshakeApplicationProtocol() should "
|
||||
+ "return null after the handshake is completed");
|
||||
}
|
||||
|
||||
String ap = engine.getApplicationProtocol();
|
||||
System.out.println("Application Protocol: \"" + ap + "\"");
|
||||
|
||||
@ -384,6 +398,12 @@ public class SSLEngineAlpnTest {
|
||||
sslp = clientEngine.getSSLParameters();
|
||||
sslp.setApplicationProtocols(clientAPs);
|
||||
clientEngine.setSSLParameters(sslp);
|
||||
|
||||
if ((clientEngine.getHandshakeApplicationProtocol() != null) ||
|
||||
(serverEngine.getHandshakeApplicationProtocol() != null)) {
|
||||
throw new Exception ("getHandshakeApplicationProtocol() should "
|
||||
+ "return null before the handshake starts");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 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
|
||||
@ -26,8 +26,9 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8051498
|
||||
* @bug 8051498 8145849
|
||||
* @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
|
||||
@ -40,6 +41,8 @@
|
||||
* @author Brad Wetmore
|
||||
*/
|
||||
import java.io.*;
|
||||
import java.security.KeyStore;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
|
||||
public class SSLSocketAlpnTest {
|
||||
@ -65,6 +68,16 @@ public class SSLSocketAlpnTest {
|
||||
static String trustStoreFile = "truststore";
|
||||
static String passwd = "passphrase";
|
||||
|
||||
static String keyFilename = System.getProperty("test.src", ".") + "/"
|
||||
+ pathToStores + "/" + keyStoreFile;
|
||||
static String trustFilename = System.getProperty("test.src", ".") + "/"
|
||||
+ pathToStores + "/" + trustStoreFile;
|
||||
|
||||
/*
|
||||
* SSLContext
|
||||
*/
|
||||
SSLContext mySSLContext = null;
|
||||
|
||||
/*
|
||||
* Is the server ready to serve?
|
||||
*/
|
||||
@ -82,7 +95,7 @@ public class SSLSocketAlpnTest {
|
||||
/*
|
||||
* If the client or server is doing some kind of object creation
|
||||
* that the other side depends on, and that thread prematurely
|
||||
* exits, you may experience a hang. The test harness will
|
||||
* exits, you may experience a hang. The test harness will
|
||||
* terminate all hung threads after its timeout has expired,
|
||||
* currently 3 minutes by default, but you might try to be
|
||||
* smart about it....
|
||||
@ -95,10 +108,11 @@ public class SSLSocketAlpnTest {
|
||||
* to avoid infinite hangs.
|
||||
*/
|
||||
void doServerSide() throws Exception {
|
||||
SSLServerSocketFactory sslssf
|
||||
= (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
|
||||
SSLServerSocketFactory sslssf = mySSLContext.getServerSocketFactory();
|
||||
SSLServerSocket sslServerSocket
|
||||
= (SSLServerSocket) sslssf.createServerSocket(serverPort);
|
||||
// for both client/server to call into X509KM
|
||||
sslServerSocket.setNeedClientAuth(true);
|
||||
|
||||
serverPort = sslServerSocket.getLocalPort();
|
||||
|
||||
@ -119,20 +133,30 @@ public class SSLSocketAlpnTest {
|
||||
*/
|
||||
String[] suites = sslp.getCipherSuites();
|
||||
sslp.setCipherSuites(suites);
|
||||
sslp.setUseCipherSuitesOrder(true); // Set server side order
|
||||
sslp.setUseCipherSuitesOrder(true); // Set server side order
|
||||
|
||||
// Set the ALPN selection.
|
||||
sslp.setApplicationProtocols(serverAPs);
|
||||
sslSocket.setSSLParameters(sslp);
|
||||
|
||||
if (sslSocket.getHandshakeApplicationProtocol() != null) {
|
||||
throw new Exception ("getHandshakeApplicationProtocol() should "
|
||||
+ "return null before the handshake starts");
|
||||
}
|
||||
|
||||
sslSocket.startHandshake();
|
||||
|
||||
if (sslSocket.getHandshakeApplicationProtocol() != null) {
|
||||
throw new Exception ("getHandshakeApplicationProtocol() should "
|
||||
+ "return null after the handshake is completed");
|
||||
}
|
||||
|
||||
String ap = sslSocket.getApplicationProtocol();
|
||||
System.out.println("Application Protocol: \"" + ap + "\"");
|
||||
|
||||
if (ap == null) {
|
||||
throw new Exception(
|
||||
"Handshake was completed but null was received");
|
||||
"Handshake was completed but null was received");
|
||||
}
|
||||
if (expectedAP.equals("NONE")) {
|
||||
if (!ap.isEmpty()) {
|
||||
@ -141,8 +165,8 @@ public class SSLSocketAlpnTest {
|
||||
System.out.println("No ALPN value negotiated, as expected");
|
||||
}
|
||||
} else if (!expectedAP.equals(ap)) {
|
||||
throw new Exception(expectedAP +
|
||||
" ALPN value not available on negotiated connection");
|
||||
throw new Exception(expectedAP
|
||||
+ " ALPN value not available on negotiated connection");
|
||||
}
|
||||
|
||||
InputStream sslIS = sslSocket.getInputStream();
|
||||
@ -170,8 +194,7 @@ public class SSLSocketAlpnTest {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
|
||||
SSLSocketFactory sslsf
|
||||
= (SSLSocketFactory) SSLSocketFactory.getDefault();
|
||||
SSLSocketFactory sslsf = mySSLContext.getSocketFactory();
|
||||
SSLSocket sslSocket
|
||||
= (SSLSocket) sslsf.createSocket("localhost", serverPort);
|
||||
|
||||
@ -185,28 +208,35 @@ public class SSLSocketAlpnTest {
|
||||
*/
|
||||
String[] suites = sslp.getCipherSuites();
|
||||
sslp.setCipherSuites(suites);
|
||||
sslp.setUseCipherSuitesOrder(true); // Set server side order
|
||||
sslp.setUseCipherSuitesOrder(true); // Set server side order
|
||||
|
||||
// Set the ALPN selection.
|
||||
sslp.setApplicationProtocols(clientAPs);
|
||||
sslSocket.setSSLParameters(sslp);
|
||||
|
||||
if (sslSocket.getHandshakeApplicationProtocol() != null) {
|
||||
throw new Exception ("getHandshakeApplicationProtocol() should "
|
||||
+ "return null before the handshake starts");
|
||||
}
|
||||
|
||||
sslSocket.startHandshake();
|
||||
|
||||
if (sslSocket.getHandshakeApplicationProtocol() != null) {
|
||||
throw new Exception ("getHandshakeApplicationProtocol() should "
|
||||
+ "return null after the handshake is completed");
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that the resulting connection meets our defined ALPN
|
||||
* criteria. If we were connecting to a non-JSSE implementation,
|
||||
* the server might have negotiated something we shouldn't accept.
|
||||
*
|
||||
* We were expecting H2 from server, let's make sure the
|
||||
* conditions match.
|
||||
*/
|
||||
String ap = sslSocket.getApplicationProtocol();
|
||||
System.out.println("Application Protocol: \"" + ap + "\"");
|
||||
|
||||
if (ap == null) {
|
||||
throw new Exception(
|
||||
"Handshake was completed but null was received");
|
||||
"Handshake was completed but null was received");
|
||||
}
|
||||
if (expectedAP.equals("NONE")) {
|
||||
if (!ap.isEmpty()) {
|
||||
@ -215,8 +245,8 @@ public class SSLSocketAlpnTest {
|
||||
System.out.println("No ALPN value negotiated, as expected");
|
||||
}
|
||||
} else if (!expectedAP.equals(ap)) {
|
||||
throw new Exception(expectedAP +
|
||||
" ALPN value not available on negotiated connection");
|
||||
throw new Exception(expectedAP
|
||||
+ " ALPN value not available on negotiated connection");
|
||||
}
|
||||
|
||||
InputStream sslIS = sslSocket.getInputStream();
|
||||
@ -240,17 +270,6 @@ public class SSLSocketAlpnTest {
|
||||
volatile Exception clientException = null;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String keyFilename
|
||||
= System.getProperty("test.src", ".") + "/" + pathToStores
|
||||
+ "/" + keyStoreFile;
|
||||
String trustFilename
|
||||
= System.getProperty("test.src", ".") + "/" + pathToStores
|
||||
+ "/" + trustStoreFile;
|
||||
|
||||
System.setProperty("javax.net.ssl.keyStore", keyFilename);
|
||||
System.setProperty("javax.net.ssl.keyStorePassword", passwd);
|
||||
System.setProperty("javax.net.ssl.trustStore", trustFilename);
|
||||
System.setProperty("javax.net.ssl.trustStorePassword", passwd);
|
||||
|
||||
if (debug) {
|
||||
System.setProperty("javax.net.debug", "all");
|
||||
@ -280,6 +299,39 @@ public class SSLSocketAlpnTest {
|
||||
System.out.println("Test Passed.");
|
||||
}
|
||||
|
||||
SSLContext getSSLContext(String keyFilename, String trustFilename)
|
||||
throws Exception {
|
||||
SSLContext ctx = SSLContext.getInstance("TLS");
|
||||
|
||||
// Keystores
|
||||
KeyStore keyKS = KeyStore.getInstance("JKS");
|
||||
keyKS.load(new FileInputStream(keyFilename), passwd.toCharArray());
|
||||
|
||||
KeyStore trustKS = KeyStore.getInstance("JKS");
|
||||
trustKS.load(new FileInputStream(trustFilename), passwd.toCharArray());
|
||||
|
||||
// Generate KeyManager and TrustManager
|
||||
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
|
||||
kmf.init(keyKS, passwd.toCharArray());
|
||||
|
||||
KeyManager[] kms = kmf.getKeyManagers();
|
||||
if (!(kms[0] instanceof X509ExtendedKeyManager)) {
|
||||
throw new Exception("kms[0] not X509ExtendedKeyManager");
|
||||
}
|
||||
|
||||
kms = new KeyManager[] { new MyX509ExtendedKeyManager(
|
||||
(X509ExtendedKeyManager) kms[0], expectedAP) };
|
||||
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
|
||||
tmf.init(trustKS);
|
||||
TrustManager[] tms = tmf.getTrustManagers();
|
||||
|
||||
// initial SSLContext
|
||||
ctx.init(kms, tms, null);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a comma-separated list into an array of strings.
|
||||
*/
|
||||
@ -309,6 +361,7 @@ public class SSLSocketAlpnTest {
|
||||
*/
|
||||
SSLSocketAlpnTest() throws Exception {
|
||||
Exception startException = null;
|
||||
mySSLContext = getSSLContext(keyFilename, trustFilename);
|
||||
try {
|
||||
if (separateServerThread) {
|
||||
startServer(true);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user