Author: markt
Date: Wed Dec 13 10:42:15 2017
New Revision: 1817997

URL: http://svn.apache.org/viewvc?rev=1817997&view=rev
Log:
Partial fix for https://bz.apache.org/bugzilla/show_bug.cgi?id=61566
Certificate chains are now exposed for virtual hosts configured using a Java 
key store.

Added:
    tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorCerts.jsp   (with props)
Modified:
    tomcat/trunk/java/org/apache/catalina/manager/HTMLManagerServlet.java
    tomcat/trunk/java/org/apache/catalina/manager/LocalStrings.properties
    tomcat/trunk/java/org/apache/catalina/manager/ManagerServlet.java
    tomcat/trunk/java/org/apache/tomcat/util/net/SSLContext.java
    tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSESSLContext.java
    tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java
    tomcat/trunk/webapps/docs/changelog.xml
    tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorCiphers.jsp

Modified: tomcat/trunk/java/org/apache/catalina/manager/HTMLManagerServlet.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/manager/HTMLManagerServlet.java?rev=1817997&r1=1817996&r2=1817997&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/manager/HTMLManagerServlet.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/manager/HTMLManagerServlet.java Wed 
Dec 13 10:42:15 2017
@@ -85,6 +85,7 @@ public final class HTMLManagerServlet ex
     static final String sessionsListJspPath = "/WEB-INF/jsp/sessionsList.jsp";
     static final String sessionDetailJspPath = 
"/WEB-INF/jsp/sessionDetail.jsp";
     static final String connectorCiphersJspPath = 
"/WEB-INF/jsp/connectorCiphers.jsp";
+    static final String connectorCertsJspPath = 
"/WEB-INF/jsp/connectorCerts.jsp";
 
     private boolean showProxySessions = false;
 
@@ -138,6 +139,8 @@ public final class HTMLManagerServlet ex
             }
         } else if (command.equals("/sslConnectorCiphers")) {
             sslConnectorCiphers(request, response);
+        } else if (command.equals("/sslConnectorCerts")) {
+            sslConnectorHostCerts(request, response);
         } else if (command.equals("/upload") || command.equals("/deploy") ||
                 command.equals("/reload") || command.equals("/undeploy") ||
                 command.equals("/expire") || command.equals("/start") ||
@@ -535,7 +538,7 @@ public final class HTMLManagerServlet ex
         writer.print(MessageFormat.format(UPLOAD_SECTION, args));
 
         // Diagnostics section
-        args = new Object[9];
+        args = new Object[12];
         args[0] = smClient.getString("htmlManagerServlet.diagnosticsTitle");
         args[1] = smClient.getString("htmlManagerServlet.diagnosticsLeak");
         args[2] = response.encodeURL(
@@ -547,6 +550,10 @@ public final class HTMLManagerServlet ex
                 request.getContextPath() + "/html/sslConnectorCiphers");
         args[7] = 
smClient.getString("htmlManagerServlet.diagnosticsSslConnectorCipherButton");
         args[8] = 
smClient.getString("htmlManagerServlet.diagnosticsSslConnectorCipherText");
+        args[9] = response.encodeURL(
+                request.getContextPath() + "/html/sslConnectorCerts");
+        args[10] = 
smClient.getString("htmlManagerServlet.diagnosticsSslConnectorCertsButton");
+        args[11] = 
smClient.getString("htmlManagerServlet.diagnosticsSslConnectorCertsText");
         writer.print(MessageFormat.format(DIAGNOSTICS_SECTION, args));
 
         // Server Header Section
@@ -727,6 +734,15 @@ public final class HTMLManagerServlet ex
                 connectorCiphersJspPath).forward(request, response);
     }
 
+
+    protected void sslConnectorHostCerts(HttpServletRequest request,
+            HttpServletResponse response) throws ServletException, IOException 
{
+        request.setAttribute("certList", getConnectorCerts());
+        getServletContext().getRequestDispatcher(
+                connectorCertsJspPath).forward(request, response);
+    }
+
+
     /**
      * @see javax.servlet.Servlet#getServletInfo()
      */
@@ -1292,6 +1308,7 @@ public final class HTMLManagerServlet ex
         "<tr>\n" +
         " <td colspan=\"2\" class=\"title\">{0}</td>\n" +
         "</tr>\n" +
+
         "<tr>\n" +
         " <td colspan=\"2\" class=\"header-left\"><small>{1}</small></td>\n" +
         "</tr>\n" +
@@ -1311,6 +1328,7 @@ public final class HTMLManagerServlet ex
         "</form>\n" +
         "</td>\n" +
         "</tr>\n" +
+
         "<tr>\n" +
         " <td colspan=\"2\" class=\"header-left\"><small>{5}</small></td>\n" +
         "</tr>\n" +
@@ -1330,6 +1348,28 @@ public final class HTMLManagerServlet ex
         "</form>\n" +
         "</td>\n" +
         "</tr>\n" +
+
+        "<tr>\n" +
+        " <td colspan=\"2\">\n" +
+        "<form method=\"post\" action=\"{9}\">\n" +
+        "<table cellspacing=\"0\" cellpadding=\"3\">\n" +
+        "<tr>\n" +
+        " <td class=\"row-left\">\n" +
+        "  <input type=\"submit\" value=\"{10}\">\n" +
+        " </td>\n" +
+        " <td class=\"row-left\">\n" +
+        "  <small>{11}</small>\n" +
+        " </td>\n" +
+        "</tr>\n" +
+        "</table>\n" +
+        "</form>\n" +
+        "</td>\n" +
+        "</tr>\n" +
+        "</table>\n" +
+        "</form>\n" +
+
+        "</td>\n" +
+        "</tr>\n" +
         "</table>\n" +
         "<br>";
 }

Modified: tomcat/trunk/java/org/apache/catalina/manager/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/manager/LocalStrings.properties?rev=1817997&r1=1817996&r2=1817997&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/manager/LocalStrings.properties 
(original)
+++ tomcat/trunk/java/org/apache/catalina/manager/LocalStrings.properties Wed 
Dec 13 10:42:15 2017
@@ -48,9 +48,11 @@ htmlManagerServlet.deployWar=WAR or Dire
 htmlManagerServlet.diagnosticsLeak=Check to see if a web application has 
caused a memory leak on stop, reload or undeploy
 htmlManagerServlet.diagnosticsLeakButton=Find leaks
 htmlManagerServlet.diagnosticsLeakWarning=This diagnostic check will trigger a 
full garbage collection. Use it with extreme caution on production systems.
-htmlManagerServlet.diagnosticsSsl=SSL connector configuration diagnostics
-htmlManagerServlet.diagnosticsSslConnectorCipherButton=Connector ciphers
-htmlManagerServlet.diagnosticsSslConnectorCipherText=List the configured 
ciphers for each connector
+htmlManagerServlet.diagnosticsSsl=TLS connector configuration diagnostics
+htmlManagerServlet.diagnosticsSslConnectorCipherButton=Ciphers
+htmlManagerServlet.diagnosticsSslConnectorCipherText=List the configured TLS 
virtual hosts and the ciphers for each
+htmlManagerServlet.diagnosticsSslConnectorCertsButton=Certificates
+htmlManagerServlet.diagnosticsSslConnectorCertsText=List the configured TLS 
virtual hosts and the certificate chain for each
 htmlManagerServlet.diagnosticsTitle=Diagnostics
 htmlManagerServlet.findleaksList=\
   The following web applications were stopped (reloaded, undeployed), but 
their\n\
@@ -72,6 +74,7 @@ htmlManagerServlet.serverTitle=Server In
 htmlManagerServlet.serverVersion=Tomcat Version
 htmlManagerServlet.title=Tomcat Web Application Manager
 managerServlet.alreadyContext=FAIL - Application already exists at path [{0}]
+managerServlet.certsNotAvailable=Certificate information cannot be obtained 
from this connector at runtime
 managerServlet.deleteFail=FAIL - Unable to delete [{0}]. The continued 
presence of this file may cause problems.
 managerServlet.deployed=OK - Deployed application at context path [{0}]
 managerServlet.deployFailed=FAIL - Failed to deploy application at context 
path [{0}]

Modified: tomcat/trunk/java/org/apache/catalina/manager/ManagerServlet.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/manager/ManagerServlet.java?rev=1817997&r1=1817996&r2=1817997&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/manager/ManagerServlet.java (original)
+++ tomcat/trunk/java/org/apache/catalina/manager/ManagerServlet.java Wed Dec 
13 10:42:15 2017
@@ -22,6 +22,8 @@ import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Enumeration;
@@ -30,6 +32,7 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Set;
 
 import javax.management.MBeanServer;
 import javax.management.MalformedObjectNameException;
@@ -62,7 +65,9 @@ import org.apache.catalina.util.ServerIn
 import org.apache.tomcat.util.Diagnostics;
 import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.modeler.Registry;
+import org.apache.tomcat.util.net.SSLContext;
 import org.apache.tomcat.util.net.SSLHostConfig;
+import org.apache.tomcat.util.net.SSLHostConfigCertificate;
 import org.apache.tomcat.util.res.StringManager;
 import org.apache.tomcat.util.security.Escape;
 
@@ -1712,4 +1717,48 @@ public class ManagerServlet extends Http
         }
         return result;
     }
+
+
+    protected Map<String,List<String>> getConnectorCerts() {
+        Map<String,List<String>> result = new HashMap<>();
+
+        Engine e = (Engine) host.getParent();
+        Service s = e.getService();
+        Connector connectors[] = s.findConnectors();
+        for (Connector connector : connectors) {
+            if (Boolean.TRUE.equals(connector.getProperty("SSLEnabled"))) {
+                SSLHostConfig[] sslHostConfigs = 
connector.getProtocolHandler().findSslHostConfigs();
+                for (SSLHostConfig sslHostConfig : sslHostConfigs) {
+                    Set<SSLHostConfigCertificate> sslHostConfigCerts =
+                            sslHostConfig.getCertificates();
+                    for (SSLHostConfigCertificate sslHostConfigCert : 
sslHostConfigCerts) {
+                        String name = connector.toString() + "-" + 
sslHostConfig.getHostName() +
+                                "-" + sslHostConfigCert.getType();
+                        List<String> certList = new ArrayList<>();
+                        SSLContext sslContext = 
sslHostConfigCert.getSslContext();
+                        String alias = 
sslHostConfigCert.getCertificateKeyAlias();
+                        if (alias == null) {
+                            alias = "tomcat";
+                        }
+                        X509Certificate[] certs = 
sslContext.getCertificateChain(alias);
+                        if (certs == null) {
+                            
certList.add(sm.getString("managerServlet.certsNotAvailable"));
+                        } else {
+                            for (Certificate cert : certs) {
+                                certList.add(cert.toString());
+                            }
+                        }
+                        result.put(name, certList);
+                    }
+                }
+            } else {
+                List<String> certList = new ArrayList<>(1);
+                certList.add(sm.getString("managerServlet.notSslConnector"));
+                result.put(connector.toString(), certList);
+            }
+        }
+
+        return result;
+    }
+
 }

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SSLContext.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SSLContext.java?rev=1817997&r1=1817996&r2=1817997&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SSLContext.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SSLContext.java Wed Dec 13 
10:42:15 2017
@@ -19,6 +19,7 @@ package org.apache.tomcat.util.net;
 
 import java.security.KeyManagementException;
 import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
 
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLEngine;
@@ -47,4 +48,5 @@ public interface SSLContext {
 
     public SSLParameters getSupportedSSLParameters();
 
+    public X509Certificate[] getCertificateChain(String alias);
 }

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSESSLContext.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSESSLContext.java?rev=1817997&r1=1817996&r2=1817997&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSESSLContext.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSESSLContext.java Wed 
Dec 13 10:42:15 2017
@@ -20,6 +20,7 @@ package org.apache.tomcat.util.net.jsse;
 import java.security.KeyManagementException;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
 
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLEngine;
@@ -27,12 +28,15 @@ import javax.net.ssl.SSLParameters;
 import javax.net.ssl.SSLServerSocketFactory;
 import javax.net.ssl.SSLSessionContext;
 import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509KeyManager;
 
 import org.apache.tomcat.util.net.SSLContext;
 
 class JSSESSLContext implements SSLContext {
 
     private javax.net.ssl.SSLContext context;
+    private KeyManager[] kms;
+
     JSSESSLContext(String protocol) throws NoSuchAlgorithmException {
         context = javax.net.ssl.SSLContext.getInstance(protocol);
     }
@@ -40,6 +44,7 @@ class JSSESSLContext implements SSLConte
     @Override
     public void init(KeyManager[] kms, TrustManager[] tms, SecureRandom sr)
             throws KeyManagementException {
+        this.kms = kms;
         context.init(kms, tms, sr);
     }
 
@@ -67,4 +72,16 @@ class JSSESSLContext implements SSLConte
         return context.getSupportedSSLParameters();
     }
 
+    @Override
+    public X509Certificate[] getCertificateChain(String alias) {
+        X509Certificate[] result = null;
+        if (kms != null) {
+            for (int i = 0; i < kms.length && result == null; i++) {
+                if (kms[i] instanceof X509KeyManager) {
+                    result = ((X509KeyManager) 
kms[i]).getCertificateChain(alias);
+                }
+            }
+        }
+        return result;
+    }
 }

Modified: 
tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java?rev=1817997&r1=1817996&r2=1817997&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java 
Wed Dec 13 10:42:15 2017
@@ -68,6 +68,7 @@ public class OpenSSLContext implements o
     private final SSLHostConfig sslHostConfig;
     private final SSLHostConfigCertificate certificate;
     private OpenSSLSessionContext sessionContext;
+    private X509KeyManager x509KeyManager;
 
     private final List<String> negotiableProtocols;
 
@@ -286,17 +287,17 @@ public class OpenSSLContext implements o
                         SSLHostConfig.adjustRelativePath(
                                 
sslHostConfig.getCertificateRevocationListPath()));
             } else {
-                X509KeyManager keyManager = chooseKeyManager(kms);
+                x509KeyManager = chooseKeyManager(kms);
                 String alias = certificate.getCertificateKeyAlias();
                 if (alias == null) {
                     alias = "tomcat";
                 }
-                X509Certificate[] chain = 
keyManager.getCertificateChain(alias);
+                X509Certificate[] chain = 
x509KeyManager.getCertificateChain(alias);
                 if (chain == null) {
-                    alias = findAlias(keyManager, certificate);
-                    chain = keyManager.getCertificateChain(alias);
+                    alias = findAlias(x509KeyManager, certificate);
+                    chain = x509KeyManager.getCertificateChain(alias);
                 }
-                PrivateKey key = keyManager.getPrivateKey(alias);
+                PrivateKey key = x509KeyManager.getPrivateKey(alias);
                 StringBuilder sb = new StringBuilder(BEGIN_KEY);
                 sb.append(Base64.getMimeEncoder(64, new byte[] 
{'\n'}).encodeToString(key.getEncoded()));
                 sb.append(END_KEY);
@@ -514,6 +515,20 @@ public class OpenSSLContext implements o
     }
 
     @Override
+    public X509Certificate[] getCertificateChain(String alias) {
+        if (alias == null) {
+            alias = "tomcat";
+        }
+        X509Certificate[] chain = x509KeyManager.getCertificateChain(alias);
+        if (chain == null) {
+            alias = findAlias(x509KeyManager, certificate);
+            chain = x509KeyManager.getCertificateChain(alias);
+        }
+
+        return chain;
+    }
+
+    @Override
     protected void finalize() throws Throwable {
         /*
          * When an SSLHostConfig is replaced at runtime, it is not possible to

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1817997&r1=1817996&r2=1817997&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Wed Dec 13 10:42:15 2017
@@ -90,6 +90,12 @@
         MBean documentation so users have a reference to use when constructing
         mbeans-descriptiors.xml files for custom components. (markt)
       </add>
+      <add>
+        <bug>61566</bug>: Provide a partial fix for this issue. The fix exposes
+        the currently in use certificate chain for all virtual hosts configured
+        using the JSSE style (keystore) TLS configuration via the Manager web
+        application.
+      </add>
     </changelog>
   </subsection>
   <subsection name="Other">

Added: tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorCerts.jsp
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorCerts.jsp?rev=1817997&view=auto
==============================================================================
--- tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorCerts.jsp (added)
+++ tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorCerts.jsp Wed Dec 13 
10:42:15 2017
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<%--
+ 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.
+--%>
+<%@page session="false" contentType="text/html; charset=ISO-8859-1" %>
+<%@page import="java.util.Map" %>
+<%@page import="java.util.Map.Entry" %>
+<%@page import="java.util.List" %>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>
+
+<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en">
+<% Map<String,List<String>> certList = (Map<String,List<String>>) 
request.getAttribute("certList");
+%>
+<head>
+    <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"/>
+    <meta http-equiv="pragma" content="no-cache"/><!-- HTTP 1.0 -->
+    <meta http-equiv="cache-control" content="no-cache,must-revalidate"/><!-- 
HTTP 1.1 -->
+    <meta http-equiv="expires" content="0"/><!-- 0 is an invalid value and 
should be treated as 'now' -->
+    <meta http-equiv="content-language" content="en"/>
+    <meta name="copyright" content="copyright 2005-2017 the Apache Software 
Foundation"/>
+    <meta name="robots" content="noindex,nofollow,noarchive"/>
+    <title>Configured certificate chains per Connector</title>
+</head>
+<body>
+<h1>Configured ciphers per Connector</h1>
+
+<table border="1" cellpadding="2" cellspacing="2" width="100%">
+    <thead>
+        <tr>
+            <th>Connector / TLS Virtual Host / Certificate type</th>
+            <th>Certificate chain</th>
+        </tr>
+    </thead>
+    <tbody>
+        <%
+        for (Map.Entry<String, List<String>> entry : certList.entrySet()) {
+        %>
+        <tr>
+            <td><%=entry.getKey()%></td>
+            <td>
+            <%
+            for (String cert : entry.getValue()) {
+            %>
+                <pre><%=cert%></pre>
+            <%
+            }
+            %>
+            </td>
+        </tr>
+        <%
+        }
+        %>
+    </tbody>
+</table>
+
+<form method="get" action="<%=request.getContextPath()%>/html">
+  <p style="text-align: center;">
+    <input type="submit" value="Return to main page" />
+  </p>
+</form>
+
+<%--div style="display: none;">
+<p>
+    <a href="http://validator.w3.org/check?uri=referer";><img
+        src="http://www.w3.org/Icons/valid-html401";
+        alt="Valid HTML 4.01!" height="31" width="88"></a>
+    <a href="http://validator.w3.org/check?uri=referer";><img
+        src="http://www.w3.org/Icons/valid-xhtml10";
+        alt="Valid XHTML 1.0!" height="31" width="88" /></a>
+    <a href="http://validator.w3.org/check?uri=referer";><img
+        src="http://www.w3.org/Icons/valid-xhtml11";
+        alt="Valid XHTML 1.1!" height="31" width="88" /></a>
+</p>
+</div--%>
+
+</body>
+</html>

Propchange: tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorCerts.jsp
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorCiphers.jsp
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorCiphers.jsp?rev=1817997&r1=1817996&r2=1817997&view=diff
==============================================================================
--- tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorCiphers.jsp (original)
+++ tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorCiphers.jsp Wed Dec 13 
10:42:15 2017
@@ -42,7 +42,7 @@
 <table border="1" cellpadding="2" cellspacing="2" width="100%">
     <thead>
         <tr>
-            <th>Connector</th>
+            <th>Connector / TLS Virtual Host</th>
             <th>Enabled Ciphers</th>
         </tr>
     </thead>



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to