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/05/29 15:18:13 UTC
[tomcat] branch master updated: Implement more of the SSL env
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
The following commit(s) were added to refs/heads/master by this push:
new d381b0b Implement more of the SSL env
d381b0b is described below
commit d381b0b84a168681944e202a63a294766a11926d
Author: remm <re...@apache.org>
AuthorDate: Fri May 29 17:17:51 2020 +0200
Implement more of the SSL env
With a test case to see the result. The rest seems difficult to
implement.
---
.../catalina/valves/rewrite/ResolverImpl.java | 68 +++++++++--
.../apache/tomcat/util/net/TestResolverSSL.java | 134 +++++++++++++++++++++
2 files changed, 189 insertions(+), 13 deletions(-)
diff --git a/java/org/apache/catalina/valves/rewrite/ResolverImpl.java b/java/org/apache/catalina/valves/rewrite/ResolverImpl.java
index ea44acc..51566f0 100644
--- a/java/org/apache/catalina/valves/rewrite/ResolverImpl.java
+++ b/java/org/apache/catalina/valves/rewrite/ResolverImpl.java
@@ -18,15 +18,21 @@ package org.apache.catalina.valves.rewrite;
import java.io.IOException;
import java.nio.charset.Charset;
+import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.Calendar;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.apache.catalina.WebResource;
import org.apache.catalina.WebResourceRoot;
import org.apache.catalina.connector.Request;
+import org.apache.tomcat.util.codec.binary.Base64;
import org.apache.tomcat.util.http.FastHttpDateFormat;
import org.apache.tomcat.util.net.SSLSupport;
+import org.apache.tomcat.util.net.openssl.ciphers.Cipher;
+import org.apache.tomcat.util.net.openssl.ciphers.EncryptionLevel;
+import org.apache.tomcat.util.net.openssl.ciphers.OpenSSLCipherConfigurationParser;
public class ResolverImpl extends Resolver {
@@ -139,20 +145,39 @@ public class ResolverImpl extends Resolver {
public String resolveSsl(String key) {
SSLSupport sslSupport = (SSLSupport) request.getAttribute(SSLSupport.SESSION_MGR);
try {
- // FIXME SSL_SESSION_RESUMED
- // FIXME SSL_SECURE_RENEG
- // FIXME SSL_CIPHER_EXPORT
- // FIXME SSL_CIPHER_ALGKEYSIZE
- // FIXME SSL_COMPRESS_METHOD
+ // FIXME SSL_SESSION_RESUMED in SSLHostConfig
+ // FIXME SSL_SECURE_RENEG in SSLHostConfig
+ // FIXME SSL_COMPRESS_METHOD in SSLHostConfig
+ // FIXME SSL_TLS_SNI from handshake
// FIXME SSL_SRP_USER
// FIXME SSL_SRP_USERINFO
- // FIXME SSL_TLS_SNI
- if (key.equals("SSL_PROTOCOL")) {
+ if (key.equals("HTTPS")) {
+ return String.valueOf(sslSupport != null);
+ } else if (key.equals("SSL_PROTOCOL")) {
return sslSupport.getProtocol();
} else if (key.equals("SSL_SESSION_ID")) {
return sslSupport.getSessionId();
} else if (key.equals("SSL_CIPHER")) {
return sslSupport.getCipherSuite();
+ } else if (key.equals("SSL_CIPHER_EXPORT")) {
+ String cipherSuite = sslSupport.getCipherSuite();
+ Set<Cipher> cipherList = OpenSSLCipherConfigurationParser.parse(cipherSuite);
+ if (cipherList.size() == 1) {
+ Cipher cipher = cipherList.iterator().next();
+ if (cipher.getLevel().equals(EncryptionLevel.EXP40)
+ || cipher.getLevel().equals(EncryptionLevel.EXP56)) {
+ return "true";
+ } else {
+ return "false";
+ }
+ }
+ } else if (key.equals("SSL_CIPHER_ALGKEYSIZE")) {
+ String cipherSuite = sslSupport.getCipherSuite();
+ Set<Cipher> cipherList = OpenSSLCipherConfigurationParser.parse(cipherSuite);
+ if (cipherList.size() == 1) {
+ Cipher cipher = cipherList.iterator().next();
+ return String.valueOf(cipher.getAlg_bits());
+ }
} else if (key.equals("SSL_CIPHER_USEKEYSIZE")) {
return sslSupport.getKeySize().toString();
} else if (key.startsWith("SSL_CLIENT_")) {
@@ -166,9 +191,9 @@ public class ResolverImpl extends Resolver {
key = key.substring("SAN_OTHER_msUPN_".length());
// FIXME return certificates[0].getSubjectAlternativeNames()
} else if (key.equals("CERT_RFC4523_CEA")) {
- // FIXME return certificates[0];
+ // FIXME return certificates[0]
} else if (key.equals("VERIFY")) {
- // FIXME return certificates[0];
+ // FIXME return verification state
}
}
} else if (key.startsWith("SSL_SERVER_")) {
@@ -199,7 +224,7 @@ public class ResolverImpl extends Resolver {
return certificates[0].getSubjectDN().getName();
} else if (key.startsWith("S_DN_")) {
key = key.substring("S_DN_".length());
- // FIXME return certificates[0].getSubjectX500Principal().?;
+ // FIXME would need access to X500Name from X500Principal
} else if (key.startsWith("SAN_Email_")) {
key = key.substring("SAN_Email_".length());
// FIXME return certificates[0].getSubjectAlternativeNames()
@@ -210,7 +235,7 @@ public class ResolverImpl extends Resolver {
return certificates[0].getIssuerDN().getName();
} else if (key.startsWith("I_DN_")) {
key = key.substring("I_DN_".length());
- // FIXME return certificates[0].getIssuerX500Principal().?;
+ // FIXME would need access to X500Name from X500Principal
} else if (key.equals("V_START")) {
return String.valueOf(certificates[0].getNotBefore().getTime());
} else if (key.equals("V_END")) {
@@ -227,14 +252,31 @@ public class ResolverImpl extends Resolver {
} else if (key.equals("A_KEY")) {
return certificates[0].getPublicKey().getAlgorithm();
} else if (key.equals("CERT")) {
- // FIXME return certificates[0] to pem
+ try {
+ return toPEM(certificates[0]);
+ } catch (CertificateEncodingException e) {
+ }
} else if (key.startsWith("CERT_CHAIN_")) {
key = key.substring("CERT_CHAIN_".length());
- // FIXME return certificates[n] to pem
+ try {
+ return toPEM(certificates[Integer.parseInt(key)]);
+ } catch (NumberFormatException | CertificateEncodingException e) {
+ // Ignore
+ }
}
return null;
}
+ private String toPEM(X509Certificate certificate) throws CertificateEncodingException {
+ StringBuilder result = new StringBuilder();
+ result.append("-----BEGIN CERTIFICATE-----");
+ result.append(System.lineSeparator());
+ Base64 b64 = new Base64(64);
+ result.append(b64.encodeAsString(certificate.getEncoded()));
+ result.append("-----END CERTIFICATE-----");
+ return result.toString();
+ }
+
@Override
public String resolveHttp(String key) {
String header = request.getHeader(key);
diff --git a/test/org/apache/tomcat/util/net/TestResolverSSL.java b/test/org/apache/tomcat/util/net/TestResolverSSL.java
new file mode 100644
index 0000000..d58c3bc
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/TestResolverSSL.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.net;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import jakarta.servlet.ServletException;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.catalina.valves.ValveBase;
+import org.apache.catalina.valves.rewrite.Resolver;
+import org.apache.catalina.valves.rewrite.ResolverImpl;
+import org.apache.tomcat.util.buf.ByteChunk;
+
+public class TestResolverSSL extends TomcatBaseTest {
+
+ @Test
+ public void testSslEnv() throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+ Container root = tomcat.getHost().findChild("");
+ root.getPipeline().addValve(new ResolverTestValve());
+
+ tomcat.start();
+ ByteChunk res = getUrl("https://localhost:" + getPort() + "/protected");
+ // Just look a bit at the result
+ System.out.println(res.toString());
+ Assert.assertTrue(res.toString().indexOf("OK") > 0);
+ }
+
+ // List from https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#envvars
+ private static final String[] keys = {
+ "HTTPS",
+ "SSL_PROTOCOL",
+ "SSL_SESSION_ID",
+ "SSL_SESSION_RESUMED",
+ "SSL_SECURE_RENEG",
+ "SSL_CIPHER",
+ "SSL_CIPHER_EXPORT",
+ "SSL_CIPHER_USEKEYSIZE",
+ "SSL_CIPHER_ALGKEYSIZE",
+ "SSL_COMPRESS_METHOD",
+ "SSL_VERSION_INTERFACE",
+ "SSL_VERSION_LIBRARY",
+ "SSL_CLIENT_M_VERSION",
+ "SSL_CLIENT_M_SERIAL",
+ "SSL_CLIENT_S_DN",
+ "SSL_CLIENT_S_DN_CN", // CN component
+ "SSL_CLIENT_S_DN_O", // O component
+ "SSL_CLIENT_S_DN_C", // C component
+ "SSL_CLIENT_SAN_Email_n", // FXIME: n
+ "SSL_CLIENT_SAN_DNS_n", // FXIME: n
+ "SSL_CLIENT_SAN_OTHER_msUPN_n", // FXIME: n
+ "SSL_CLIENT_I_DN",
+ "SSL_CLIENT_I_DN_x509", // FXIME: x509
+ "SSL_CLIENT_V_START",
+ "SSL_CLIENT_V_END",
+ "SSL_CLIENT_V_REMAIN",
+ "SSL_CLIENT_A_SIG",
+ "SSL_CLIENT_A_KEY",
+ "SSL_CLIENT_CERT",
+ "SSL_CLIENT_CERT_CHAIN_0",
+ "SSL_CLIENT_CERT_RFC4523_CEA",
+ "SSL_CLIENT_VERIFY",
+ "SSL_SERVER_M_VERSION",
+ "SSL_SERVER_M_SERIAL",
+ "SSL_SERVER_S_DN",
+ "SSL_SERVER_SAN_Email_n", // FXIME: n
+ "SSL_SERVER_SAN_DNS_n", // FXIME: n
+ "SSL_SERVER_SAN_OTHER_dnsSRV_n", // FXIME: n
+ "SSL_SERVER_S_DN_CN", // CN component
+ "SSL_SERVER_S_DN_O", // O component
+ "SSL_SERVER_S_DN_C", // C component
+ "SSL_SERVER_I_DN",
+ "SSL_SERVER_I_DN_x509", // FXIME: x509
+ "SSL_SERVER_V_START",
+ "SSL_SERVER_V_END",
+ "SSL_SERVER_A_SIG",
+ "SSL_SERVER_A_KEY",
+ "SSL_SERVER_CERT",
+ "SSL_SRP_USER",
+ "SSL_SRP_USERINFO",
+ "SSL_TLS_SNI" };
+
+ public class ResolverTestValve extends ValveBase {
+
+ @Override
+ public void invoke(Request request, Response response)
+ throws IOException, ServletException {
+ PrintWriter writer = response.getWriter();
+ Resolver resolver = new ResolverImpl(request);
+ for (String key : keys) {
+ resolve(key, resolver, writer);
+ }
+ writer.println("OK");
+ }
+
+ private void resolve(String key, Resolver resolver, PrintWriter writer) {
+ writer.println("[" + key + "] " + resolver.resolveSsl(key));
+ }
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ Tomcat tomcat = getTomcatInstance();
+
+ TesterSupport.configureClientCertContext(tomcat);
+
+ TesterSupport.configureClientSsl();
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org