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:21:44 UTC

[tomcat] branch 9.0.x updated (1fffbd9 -> 13d40ae)

This is an automated email from the ASF dual-hosted git repository.

remm pushed a change to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git.


    from 1fffbd9  Make enums public
     new 567492f  WIP for more TLS env resolution
     new 67c77a6  Implement more of the SSL env
     new 13d40ae  Javax package

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../catalina/valves/rewrite/ResolverImpl.java      | 149 +++++++++++++++++++--
 .../apache/tomcat/util/net/TestResolverSSL.java    | 134 ++++++++++++++++++
 2 files changed, 273 insertions(+), 10 deletions(-)
 create mode 100644 test/org/apache/tomcat/util/net/TestResolverSSL.java


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 01/03: WIP for more TLS env resolution

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

remm pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 567492f2c0f346737724ebbc7d410050dc699bc4
Author: remm <re...@apache.org>
AuthorDate: Thu May 28 16:28:19 2020 +0200

    WIP for more TLS env resolution
    
    Make explicit each missing env value, to help eventual documenting.
---
 .../catalina/valves/rewrite/ResolverImpl.java      | 107 +++++++++++++++++++--
 1 file changed, 97 insertions(+), 10 deletions(-)

diff --git a/java/org/apache/catalina/valves/rewrite/ResolverImpl.java b/java/org/apache/catalina/valves/rewrite/ResolverImpl.java
index 1ae6600..ea44acc 100644
--- a/java/org/apache/catalina/valves/rewrite/ResolverImpl.java
+++ b/java/org/apache/catalina/valves/rewrite/ResolverImpl.java
@@ -16,10 +16,12 @@
  */
 package org.apache.catalina.valves.rewrite;
 
+import java.io.IOException;
 import java.nio.charset.Charset;
+import java.security.cert.X509Certificate;
 import java.util.Calendar;
+import java.util.concurrent.TimeUnit;
 
-import org.apache.catalina.Globals;
 import org.apache.catalina.WebResource;
 import org.apache.catalina.WebResourceRoot;
 import org.apache.catalina.connector.Request;
@@ -135,16 +137,101 @@ public class ResolverImpl extends Resolver {
 
     @Override
     public String resolveSsl(String key) {
-        if (key.equals("SSL_PROTOCOL")) {
-            return String.valueOf(request.getAttribute(SSLSupport.PROTOCOL_VERSION_KEY));
-        } else if (key.equals("SSL_SESSION_ID")) {
-            return String.valueOf(request.getAttribute(Globals.SSL_SESSION_ID_ATTR));
-        } else if (key.equals("SSL_CIPHER")) {
-            return String.valueOf(request.getAttribute(Globals.CIPHER_SUITE_ATTR));
-        } else if (key.equals("SSL_CIPHER_USEKEYSIZE")) {
-            return String.valueOf(request.getAttribute(Globals.KEY_SIZE_ATTR));
+        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_SRP_USER
+            // FIXME SSL_SRP_USERINFO
+            // FIXME SSL_TLS_SNI
+            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_USEKEYSIZE")) {
+                return sslSupport.getKeySize().toString();
+            } else if (key.startsWith("SSL_CLIENT_")) {
+                X509Certificate[] certificates = sslSupport.getPeerCertificateChain();
+                if (certificates != null && certificates.length > 0) {
+                    key = key.substring("SSL_CLIENT_".length());
+                    String result = resolveSslCertificates(key, certificates);
+                    if (result != null) {
+                        return result;
+                    } else if (key.startsWith("SAN_OTHER_msUPN_")) {
+                        key = key.substring("SAN_OTHER_msUPN_".length());
+                        // FIXME return certificates[0].getSubjectAlternativeNames()
+                    } else if (key.equals("CERT_RFC4523_CEA")) {
+                        // FIXME return certificates[0];
+                    } else if (key.equals("VERIFY")) {
+                        // FIXME return certificates[0];
+                    }
+                }
+            } else if (key.startsWith("SSL_SERVER_")) {
+                X509Certificate[] certificates = sslSupport.getLocalCertificateChain();
+                if (certificates != null && certificates.length > 0) {
+                    key = key.substring("SSL_SERVER_".length());
+                    String result = resolveSslCertificates(key, certificates);
+                    if (result != null) {
+                        return result;
+                    } else if (key.startsWith("SAN_OTHER_dnsSRV_")) {
+                        key = key.substring("SAN_OTHER_dnsSRV_".length());
+                        // FIXME return certificates[0].getSubjectAlternativeNames()
+                    }
+                }
+            }
+        } catch (IOException e) {
+            // TLS access error
+        }
+        return null;
+    }
+
+    private String resolveSslCertificates(String key, X509Certificate[] certificates) {
+        if (key.equals("M_VERSION")) {
+            return String.valueOf(certificates[0].getVersion());
+        } else if (key.equals("M_SERIAL")) {
+            return certificates[0].getSerialNumber().toString();
+        } else if (key.equals("S_DN")) {
+            return certificates[0].getSubjectDN().getName();
+        } else if (key.startsWith("S_DN_")) {
+            key = key.substring("S_DN_".length());
+            // FIXME return certificates[0].getSubjectX500Principal().?;
+        } else if (key.startsWith("SAN_Email_")) {
+            key = key.substring("SAN_Email_".length());
+            // FIXME return certificates[0].getSubjectAlternativeNames()
+        } else if (key.startsWith("SAN_DNS_")) {
+            key = key.substring("SAN_DNS_".length());
+            // FIXME return certificates[0].getSubjectAlternativeNames()
+        } else if (key.equals("I_DN")) {
+            return certificates[0].getIssuerDN().getName();
+        } else if (key.startsWith("I_DN_")) {
+            key = key.substring("I_DN_".length());
+            // FIXME return certificates[0].getIssuerX500Principal().?;
+        } else if (key.equals("V_START")) {
+            return String.valueOf(certificates[0].getNotBefore().getTime());
+        } else if (key.equals("V_END")) {
+            return String.valueOf(certificates[0].getNotAfter().getTime());
+        } else if (key.equals("V_REMAIN")) {
+            long remain = certificates[0].getNotAfter().getTime() - System.currentTimeMillis();
+            if (remain < 0) {
+                remain = 0L;
+            }
+            // Return remaining days
+            return String.valueOf(TimeUnit.MILLISECONDS.toDays(remain));
+        } else if (key.equals("A_SIG")) {
+            return certificates[0].getSigAlgName();
+        } else if (key.equals("A_KEY")) {
+            return certificates[0].getPublicKey().getAlgorithm();
+        } else if (key.equals("CERT")) {
+            // FIXME return certificates[0] to pem
+        } else if (key.startsWith("CERT_CHAIN_")) {
+            key = key.substring("CERT_CHAIN_".length());
+            // FIXME return certificates[n] to pem
         }
-        // FIXME: Implement other SSL environment variables when possible
         return null;
     }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 02/03: Implement more of the SSL env

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

remm pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 67c77a65c581376b755d8dac4f127c5f3aa1cc47
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


[tomcat] 03/03: Javax package

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

remm pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 13d40ae5156a539a71fa842840ccc9b1569107b9
Author: remm <re...@apache.org>
AuthorDate: Fri May 29 17:21:25 2020 +0200

    Javax package
---
 test/org/apache/tomcat/util/net/TestResolverSSL.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/org/apache/tomcat/util/net/TestResolverSSL.java b/test/org/apache/tomcat/util/net/TestResolverSSL.java
index d58c3bc..984e261 100644
--- a/test/org/apache/tomcat/util/net/TestResolverSSL.java
+++ b/test/org/apache/tomcat/util/net/TestResolverSSL.java
@@ -19,7 +19,7 @@ package org.apache.tomcat.util.net;
 import java.io.IOException;
 import java.io.PrintWriter;
 
-import jakarta.servlet.ServletException;
+import javax.servlet.ServletException;
 
 import org.junit.Assert;
 import org.junit.Test;


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org