You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2020/07/03 09:18:03 UTC
[tomcat] 01/02: Revert "Direct use of the ALPN API"
This is an automated email from the ASF dual-hosted git repository.
remm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 35d84487fd10bfd6f2a00494078a5e3eef1b1830
Author: remm <re...@apache.org>
AuthorDate: Fri Jul 3 11:16:24 2020 +0200
Revert "Direct use of the ALPN API"
This reverts commit 7763877a98e5c74bb579b64f31e938fea17290a5.
---
java/org/apache/tomcat/util/compat/JreCompat.java | 69 ++++++++++++++++++++++
.../tomcat/util/compat/LocalStrings.properties | 3 +
.../tomcat/util/net/AbstractJsseEndpoint.java | 20 ++++++-
.../apache/tomcat/util/net/SSLImplementation.java | 1 +
java/org/apache/tomcat/util/net/SSLUtil.java | 12 ++++
.../apache/tomcat/util/net/SecureNio2Channel.java | 9 ++-
.../apache/tomcat/util/net/SecureNioChannel.java | 9 ++-
.../tomcat/util/net/jsse/JSSEImplementation.java | 5 ++
.../tomcat/util/net/openssl/OpenSSLEngine.java | 5 +-
.../util/net/openssl/OpenSSLImplementation.java | 5 ++
10 files changed, 131 insertions(+), 7 deletions(-)
diff --git a/java/org/apache/tomcat/util/compat/JreCompat.java b/java/org/apache/tomcat/util/compat/JreCompat.java
index 2f0268f..8275e60 100644
--- a/java/org/apache/tomcat/util/compat/JreCompat.java
+++ b/java/org/apache/tomcat/util/compat/JreCompat.java
@@ -19,11 +19,18 @@ package org.apache.tomcat.util.compat;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLConnection;
import java.util.Deque;
import java.util.jar.JarFile;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLParameters;
+
+import org.apache.tomcat.util.res.StringManager;
+
/**
* This is the base implementation class for JRE compatibility and provides an
* implementation based on Java 8. Sub-classes may extend this class and provide
@@ -37,6 +44,10 @@ public class JreCompat {
private static final boolean graalAvailable;
private static final boolean jre11Available;
private static final boolean jre9Available;
+ private static final StringManager sm = StringManager.getManager(JreCompat.class);
+
+ protected static final Method setApplicationProtocolsMethod;
+ protected static final Method getApplicationProtocolMethod;
static {
// This is Tomcat 9 with a minimum Java version of Java 8.
@@ -55,6 +66,17 @@ public class JreCompat {
jre9Available = false;
}
jre11Available = instance.jarFileRuntimeMajorVersion() >= 11;
+
+ Method m1 = null;
+ Method m2 = null;
+ try {
+ m1 = SSLParameters.class.getMethod("setApplicationProtocols", String[].class);
+ m2 = SSLEngine.class.getMethod("getApplicationProtocol");
+ } catch (ReflectiveOperationException | IllegalArgumentException e) {
+ // Only the newest Java 8 have the ALPN API, so ignore
+ }
+ setApplicationProtocolsMethod = m1;
+ getApplicationProtocolMethod = m2;
}
@@ -68,6 +90,11 @@ public class JreCompat {
}
+ public static boolean isAlpnSupported() {
+ return setApplicationProtocolsMethod != null && getApplicationProtocolMethod != null;
+ }
+
+
public static boolean isJre9Available() {
return jre9Available;
}
@@ -96,6 +123,48 @@ public class JreCompat {
/**
+ * Set the application protocols the server will accept for ALPN
+ *
+ * @param sslParameters The SSL parameters for a connection
+ * @param protocols The application protocols to be allowed for that
+ * connection
+ */
+ public void setApplicationProtocols(SSLParameters sslParameters, String[] protocols) {
+ if (setApplicationProtocolsMethod != null) {
+ try {
+ setApplicationProtocolsMethod.invoke(sslParameters, (Object) protocols);
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ throw new UnsupportedOperationException(e);
+ }
+ } else {
+ throw new UnsupportedOperationException(sm.getString("jreCompat.noApplicationProtocols"));
+ }
+ }
+
+
+ /**
+ * Get the application protocol that has been negotiated for connection
+ * associated with the given SSLEngine.
+ *
+ * @param sslEngine The SSLEngine for which to obtain the negotiated
+ * protocol
+ *
+ * @return The name of the negotiated protocol
+ */
+ public String getApplicationProtocol(SSLEngine sslEngine) {
+ if (getApplicationProtocolMethod != null) {
+ try {
+ return (String) getApplicationProtocolMethod.invoke(sslEngine);
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ throw new UnsupportedOperationException(e);
+ }
+ } else {
+ throw new UnsupportedOperationException(sm.getString("jreCompat.noApplicationProtocol"));
+ }
+ }
+
+
+ /**
* Disables caching for JAR URL connections. For Java 8 and earlier, this also disables
* caching for ALL URL connections.
*
diff --git a/java/org/apache/tomcat/util/compat/LocalStrings.properties b/java/org/apache/tomcat/util/compat/LocalStrings.properties
index 34ffd70..891782c 100644
--- a/java/org/apache/tomcat/util/compat/LocalStrings.properties
+++ b/java/org/apache/tomcat/util/compat/LocalStrings.properties
@@ -16,3 +16,6 @@
jre9Compat.invalidModuleUri=The module URI provided [{0}] could not be converted to a URL for the JarScanner to process
jre9Compat.javaPre9=Class not found so assuming code is running on a pre-Java 9 JVM
jre9Compat.unexpected=Failed to create references to Java 9 classes and methods
+
+jreCompat.noApplicationProtocol=Java Runtime does not support SSLEngine.getApplicationProtocol(). You must use Java 9 to use this feature.
+jreCompat.noApplicationProtocols=Java Runtime does not support SSLParameters.setApplicationProtocols(). You must use Java 9 to use this feature.
diff --git a/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java b/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java
index 1488393..925e91d 100644
--- a/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java
+++ b/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java
@@ -28,6 +28,7 @@ import java.util.Set;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLParameters;
+import org.apache.tomcat.util.compat.JreCompat;
import org.apache.tomcat.util.net.openssl.ciphers.Cipher;
public abstract class AbstractJsseEndpoint<S,U> extends AbstractEndpoint<S,U> {
@@ -122,7 +123,7 @@ public abstract class AbstractJsseEndpoint<S,U> extends AbstractEndpoint<S,U> {
SSLParameters sslParameters = engine.getSSLParameters();
sslParameters.setUseCipherSuitesOrder(sslHostConfig.getHonorCipherOrder());
- if (clientRequestedApplicationProtocols != null
+ if (JreCompat.isAlpnSupported() && clientRequestedApplicationProtocols != null
&& clientRequestedApplicationProtocols.size() > 0
&& negotiableProtocols.size() > 0) {
// Only try to negotiate if both client and server have at least
@@ -133,7 +134,7 @@ public abstract class AbstractJsseEndpoint<S,U> extends AbstractEndpoint<S,U> {
commonProtocols.retainAll(clientRequestedApplicationProtocols);
if (commonProtocols.size() > 0) {
String[] commonProtocolsArray = commonProtocols.toArray(new String[0]);
- sslParameters.setApplicationProtocols(commonProtocolsArray);
+ JreCompat.getInstance().setApplicationProtocols(sslParameters, commonProtocolsArray);
}
}
switch (sslHostConfig.getCertificateVerification()) {
@@ -192,7 +193,20 @@ public abstract class AbstractJsseEndpoint<S,U> extends AbstractEndpoint<S,U> {
@Override
public boolean isAlpnSupported() {
// ALPN requires TLS so if TLS is not enabled, ALPN cannot be supported
- return isSSLEnabled();
+ if (!isSSLEnabled()) {
+ return false;
+ }
+
+ // Depends on the SSLImplementation.
+ SSLImplementation sslImplementation;
+ try {
+ sslImplementation = SSLImplementation.getInstance(getSslImplementationName());
+ } catch (ClassNotFoundException e) {
+ // Ignore the exception. It will be logged when trying to start the
+ // end point.
+ return false;
+ }
+ return sslImplementation.isAlpnSupported();
}
diff --git a/java/org/apache/tomcat/util/net/SSLImplementation.java b/java/org/apache/tomcat/util/net/SSLImplementation.java
index fb11b82..43ccbe5 100644
--- a/java/org/apache/tomcat/util/net/SSLImplementation.java
+++ b/java/org/apache/tomcat/util/net/SSLImplementation.java
@@ -68,4 +68,5 @@ public abstract class SSLImplementation {
public abstract SSLUtil getSSLUtil(SSLHostConfigCertificate certificate);
+ public abstract boolean isAlpnSupported();
}
diff --git a/java/org/apache/tomcat/util/net/SSLUtil.java b/java/org/apache/tomcat/util/net/SSLUtil.java
index 4ba3504..c65f7a2 100644
--- a/java/org/apache/tomcat/util/net/SSLUtil.java
+++ b/java/org/apache/tomcat/util/net/SSLUtil.java
@@ -67,4 +67,16 @@ public interface SSLUtil {
*/
public String[] getEnabledCiphers() throws IllegalArgumentException;
+ /**
+ * Optional interface that can be implemented by
+ * {@link javax.net.ssl.SSLEngine}s to indicate that they support ALPN and
+ * can provided the protocol agreed with the client.
+ */
+ public interface ProtocolInfo {
+ /**
+ * ALPN information.
+ * @return the protocol selected using ALPN
+ */
+ public String getNegotiatedProtocol();
+ }
}
diff --git a/java/org/apache/tomcat/util/net/SecureNio2Channel.java b/java/org/apache/tomcat/util/net/SecureNio2Channel.java
index 3db1038..394837c 100644
--- a/java/org/apache/tomcat/util/net/SecureNio2Channel.java
+++ b/java/org/apache/tomcat/util/net/SecureNio2Channel.java
@@ -38,6 +38,7 @@ import javax.net.ssl.SSLException;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.buf.ByteBufferUtils;
+import org.apache.tomcat.util.compat.JreCompat;
import org.apache.tomcat.util.net.TLSClientHelloExtractor.ExtractorResult;
import org.apache.tomcat.util.net.openssl.ciphers.Cipher;
import org.apache.tomcat.util.res.StringManager;
@@ -241,7 +242,13 @@ public class SecureNio2Channel extends Nio2Channel {
}
case FINISHED: {
if (endpoint.hasNegotiableProtocols()) {
- socketWrapper.setNegotiatedProtocol(sslEngine.getApplicationProtocol());
+ if (sslEngine instanceof SSLUtil.ProtocolInfo) {
+ socketWrapper.setNegotiatedProtocol(
+ ((SSLUtil.ProtocolInfo) sslEngine).getNegotiatedProtocol());
+ } else if (JreCompat.isAlpnSupported()) {
+ socketWrapper.setNegotiatedProtocol(
+ JreCompat.getInstance().getApplicationProtocol(sslEngine));
+ }
}
//we are complete if we have delivered the last package
handshakeComplete = !netOutBuffer.hasRemaining();
diff --git a/java/org/apache/tomcat/util/net/SecureNioChannel.java b/java/org/apache/tomcat/util/net/SecureNioChannel.java
index ef0a33e..a176675 100644
--- a/java/org/apache/tomcat/util/net/SecureNioChannel.java
+++ b/java/org/apache/tomcat/util/net/SecureNioChannel.java
@@ -35,6 +35,7 @@ import javax.net.ssl.SSLException;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.buf.ByteBufferUtils;
+import org.apache.tomcat.util.compat.JreCompat;
import org.apache.tomcat.util.net.NioEndpoint.NioSocketWrapper;
import org.apache.tomcat.util.net.TLSClientHelloExtractor.ExtractorResult;
import org.apache.tomcat.util.net.openssl.ciphers.Cipher;
@@ -166,7 +167,13 @@ public class SecureNioChannel extends NioChannel {
throw new IOException(sm.getString("channel.nio.ssl.notHandshaking"));
case FINISHED:
if (endpoint.hasNegotiableProtocols()) {
- socketWrapper.setNegotiatedProtocol(sslEngine.getApplicationProtocol());
+ if (sslEngine instanceof SSLUtil.ProtocolInfo) {
+ socketWrapper.setNegotiatedProtocol(
+ ((SSLUtil.ProtocolInfo) sslEngine).getNegotiatedProtocol());
+ } else if (JreCompat.isAlpnSupported()) {
+ socketWrapper.setNegotiatedProtocol(
+ JreCompat.getInstance().getApplicationProtocol(sslEngine));
+ }
}
//we are complete if we have delivered the last package
handshakeComplete = !netOutBuffer.hasRemaining();
diff --git a/java/org/apache/tomcat/util/net/jsse/JSSEImplementation.java b/java/org/apache/tomcat/util/net/jsse/JSSEImplementation.java
index 4fa54be..1c1eae8 100644
--- a/java/org/apache/tomcat/util/net/jsse/JSSEImplementation.java
+++ b/java/org/apache/tomcat/util/net/jsse/JSSEImplementation.java
@@ -18,6 +18,7 @@ package org.apache.tomcat.util.net.jsse;
import javax.net.ssl.SSLSession;
+import org.apache.tomcat.util.compat.JreCompat;
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
import org.apache.tomcat.util.net.SSLImplementation;
import org.apache.tomcat.util.net.SSLSupport;
@@ -49,4 +50,8 @@ public class JSSEImplementation extends SSLImplementation {
return new JSSEUtil(certificate);
}
+ @Override
+ public boolean isAlpnSupported() {
+ return JreCompat.isAlpnSupported();
+ }
}
diff --git a/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java b/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java
index 16f1451..058ee71 100644
--- a/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java
+++ b/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java
@@ -46,6 +46,7 @@ import org.apache.tomcat.jni.SSL;
import org.apache.tomcat.jni.SSLContext;
import org.apache.tomcat.util.buf.ByteBufferUtils;
import org.apache.tomcat.util.net.Constants;
+import org.apache.tomcat.util.net.SSLUtil;
import org.apache.tomcat.util.net.openssl.ciphers.OpenSSLCipherConfigurationParser;
import org.apache.tomcat.util.res.StringManager;
@@ -54,7 +55,7 @@ import org.apache.tomcat.util.res.StringManager;
* <a href="https://www.openssl.org/docs/crypto/BIO_s_bio.html#EXAMPLE">OpenSSL
* BIO abstractions</a>.
*/
-public final class OpenSSLEngine extends SSLEngine {
+public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolInfo {
private static final Log logger = LogFactory.getLog(OpenSSLEngine.class);
private static final StringManager sm = StringManager.getManager(OpenSSLEngine.class);
@@ -208,7 +209,7 @@ public final class OpenSSLEngine extends SSLEngine {
}
@Override
- public String getApplicationProtocol() {
+ public String getNegotiatedProtocol() {
return selectedProtocol;
}
diff --git a/java/org/apache/tomcat/util/net/openssl/OpenSSLImplementation.java b/java/org/apache/tomcat/util/net/openssl/OpenSSLImplementation.java
index 6f2c3bf..94b4bf2 100644
--- a/java/org/apache/tomcat/util/net/openssl/OpenSSLImplementation.java
+++ b/java/org/apache/tomcat/util/net/openssl/OpenSSLImplementation.java
@@ -36,4 +36,9 @@ public class OpenSSLImplementation extends SSLImplementation {
return new OpenSSLUtil(certificate);
}
+ @Override
+ public boolean isAlpnSupported() {
+ // OpenSSL supported ALPN
+ return true;
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org