This is an automated email from the ASF dual-hosted git repository. remm pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 7c5f05d9542f77e6d4a9c04d46c64188844c4026 Author: remm <r...@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 b9749e0..005c301 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-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org