Author: markt
Date: Wed Dec 13 11:17:04 2017
New Revision: 1817999

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

Added:
    tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorTrustedCerts.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/connectorCerts.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=1817999&r1=1817998&r2=1817999&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/manager/HTMLManagerServlet.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/manager/HTMLManagerServlet.java Wed 
Dec 13 11:17:04 2017
@@ -86,6 +86,7 @@ public final class HTMLManagerServlet ex
     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";
+    static final String connectorTrustedCertsJspPath = 
"/WEB-INF/jsp/connectorTrustedCerts.jsp";
 
     private boolean showProxySessions = false;
 
@@ -140,7 +141,9 @@ public final class HTMLManagerServlet ex
         } else if (command.equals("/sslConnectorCiphers")) {
             sslConnectorCiphers(request, response);
         } else if (command.equals("/sslConnectorCerts")) {
-            sslConnectorHostCerts(request, response);
+            sslConnectorCerts(request, response);
+        } else if (command.equals("/sslConnectorTrustedCerts")) {
+            sslConnectorTrustedCerts(request, response);
         } else if (command.equals("/upload") || command.equals("/deploy") ||
                 command.equals("/reload") || command.equals("/undeploy") ||
                 command.equals("/expire") || command.equals("/start") ||
@@ -538,7 +541,7 @@ public final class HTMLManagerServlet ex
         writer.print(MessageFormat.format(UPLOAD_SECTION, args));
 
         // Diagnostics section
-        args = new Object[12];
+        args = new Object[15];
         args[0] = smClient.getString("htmlManagerServlet.diagnosticsTitle");
         args[1] = smClient.getString("htmlManagerServlet.diagnosticsLeak");
         args[2] = response.encodeURL(
@@ -554,6 +557,10 @@ public final class HTMLManagerServlet ex
                 request.getContextPath() + "/html/sslConnectorCerts");
         args[10] = 
smClient.getString("htmlManagerServlet.diagnosticsSslConnectorCertsButton");
         args[11] = 
smClient.getString("htmlManagerServlet.diagnosticsSslConnectorCertsText");
+        args[12] = response.encodeURL(
+                request.getContextPath() + "/html/sslConnectorTrustedCerts");
+        args[13] = 
smClient.getString("htmlManagerServlet.diagnosticsSslConnectorTrustedCertsButton");
+        args[14] = 
smClient.getString("htmlManagerServlet.diagnosticsSslConnectorTrustedCertsText");
         writer.print(MessageFormat.format(DIAGNOSTICS_SECTION, args));
 
         // Server Header Section
@@ -735,7 +742,7 @@ public final class HTMLManagerServlet ex
     }
 
 
-    protected void sslConnectorHostCerts(HttpServletRequest request,
+    protected void sslConnectorCerts(HttpServletRequest request,
             HttpServletResponse response) throws ServletException, IOException 
{
         request.setAttribute("certList", getConnectorCerts());
         getServletContext().getRequestDispatcher(
@@ -743,6 +750,14 @@ public final class HTMLManagerServlet ex
     }
 
 
+    protected void sslConnectorTrustedCerts(HttpServletRequest request,
+            HttpServletResponse response) throws ServletException, IOException 
{
+        request.setAttribute("trustedCertList", getConnectorTrustedCerts());
+        getServletContext().getRequestDispatcher(
+                connectorTrustedCertsJspPath).forward(request, response);
+    }
+
+
     /**
      * @see javax.servlet.Servlet#getServletInfo()
      */
@@ -1365,11 +1380,24 @@ public final class HTMLManagerServlet ex
         "</form>\n" +
         "</td>\n" +
         "</tr>\n" +
+
+        "<tr>\n" +
+        " <td colspan=\"2\">\n" +
+        "<form method=\"post\" action=\"{12}\">\n" +
+        "<table cellspacing=\"0\" cellpadding=\"3\">\n" +
+        "<tr>\n" +
+        " <td class=\"row-left\">\n" +
+        "  <input type=\"submit\" value=\"{13}\">\n" +
+        " </td>\n" +
+        " <td class=\"row-left\">\n" +
+        "  <small>{14}</small>\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=1817999&r1=1817998&r2=1817999&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/manager/LocalStrings.properties 
(original)
+++ tomcat/trunk/java/org/apache/catalina/manager/LocalStrings.properties Wed 
Dec 13 11:17:04 2017
@@ -53,6 +53,8 @@ htmlManagerServlet.diagnosticsSslConnect
 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.diagnosticsSslConnectorTrustedCertsButton=Trusted 
Certificates
+htmlManagerServlet.diagnosticsSslConnectorTrustedCertsText=List the configured 
TLS virtual hosts and the trusted certificates for each
 htmlManagerServlet.diagnosticsTitle=Diagnostics
 htmlManagerServlet.findleaksList=\
   The following web applications were stopped (reloaded, undeployed), but 
their\n\
@@ -118,6 +120,7 @@ managerServlet.stopped=OK - Stopped appl
 managerServlet.storeConfig.invalidMBean=FAIL - Unable to find the StoreConfig 
Mbean. [{0}] is not a valid name for an MBean.
 managerServlet.storeConfig.noMBean=FAIL - No StoreConfig MBean registered at 
[{0}]. Registration is typically performed by the StoreConfigLifecycleListener.
 managerServlet.threaddump=OK - JVM thread dump
+managerServlet.trustedCertsNotConfigured=No trusted certificates are 
configured for this virtual host
 managerServlet.undeployed=OK - Undeployed application at context path [{0}]
 managerServlet.unknownCommand=FAIL - Unknown command [{0}]
 managerServlet.vminfo=OK - VM info

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=1817999&r1=1817998&r2=1817999&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/manager/ManagerServlet.java (original)
+++ tomcat/trunk/java/org/apache/catalina/manager/ManagerServlet.java Wed Dec 
13 11:17:04 2017
@@ -1761,4 +1761,40 @@ public class ManagerServlet extends Http
         return result;
     }
 
+
+    protected Map<String,List<String>> getConnectorTrustedCerts() {
+        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) {
+                    String name = connector.toString() + "-" + 
sslHostConfig.getHostName();
+                    List<String> certList = new ArrayList<>();
+                    SSLContext sslContext =
+                            
sslHostConfig.getCertificates().iterator().next().getSslContext();
+                    X509Certificate[] certs = sslContext.getAcceptedIssuers();
+                    if (certs == null) {
+                        
certList.add(sm.getString("managerServlet.certsNotAvailable"));
+                    } else if (certs.length == 0) {
+                        
certList.add(sm.getString("managerServlet.trustedCertsNotConfigured"));
+                    } 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=1817999&r1=1817998&r2=1817999&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 
11:17:04 2017
@@ -49,4 +49,6 @@ public interface SSLContext {
     public SSLParameters getSupportedSSLParameters();
 
     public X509Certificate[] getCertificateChain(String alias);
+
+    public X509Certificate[] getAcceptedIssuers();
 }

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=1817999&r1=1817998&r2=1817999&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 11:17:04 2017
@@ -21,6 +21,8 @@ import java.security.KeyManagementExcept
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
 import java.security.cert.X509Certificate;
+import java.util.HashSet;
+import java.util.Set;
 
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLEngine;
@@ -29,6 +31,7 @@ import javax.net.ssl.SSLServerSocketFact
 import javax.net.ssl.SSLSessionContext;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509KeyManager;
+import javax.net.ssl.X509TrustManager;
 
 import org.apache.tomcat.util.net.SSLContext;
 
@@ -36,6 +39,7 @@ class JSSESSLContext implements SSLConte
 
     private javax.net.ssl.SSLContext context;
     private KeyManager[] kms;
+    private TrustManager[] tms;
 
     JSSESSLContext(String protocol) throws NoSuchAlgorithmException {
         context = javax.net.ssl.SSLContext.getInstance(protocol);
@@ -45,6 +49,7 @@ class JSSESSLContext implements SSLConte
     public void init(KeyManager[] kms, TrustManager[] tms, SecureRandom sr)
             throws KeyManagementException {
         this.kms = kms;
+        this.tms = tms;
         context.init(kms, tms, sr);
     }
 
@@ -84,4 +89,22 @@ class JSSESSLContext implements SSLConte
         }
         return result;
     }
+
+    @Override
+    public X509Certificate[] getAcceptedIssuers() {
+        Set<X509Certificate> certs = new HashSet<>();
+        if (tms != null) {
+            for (TrustManager tm : tms) {
+                if (tm instanceof X509TrustManager) {
+                    X509Certificate[] accepted = ((X509TrustManager) 
tm).getAcceptedIssuers();
+                    if (accepted != null) {
+                        for (X509Certificate c : accepted) {
+                            certs.add(c);
+                        }
+                    }
+                }
+            }
+        }
+        return certs.toArray(new X509Certificate[certs.size()]);
+    }
 }

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=1817999&r1=1817998&r2=1817999&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 11:17:04 2017
@@ -69,6 +69,7 @@ public class OpenSSLContext implements o
     private final SSLHostConfigCertificate certificate;
     private OpenSSLSessionContext sessionContext;
     private X509KeyManager x509KeyManager;
+    private X509TrustManager x509TrustManager;
 
     private final List<String> negotiableProtocols;
 
@@ -326,13 +327,13 @@ public class OpenSSLContext implements o
 
             if (tms != null) {
                 // Client certificate verification based on custom trust 
managers
-                final X509TrustManager manager = chooseTrustManager(tms);
+                x509TrustManager = chooseTrustManager(tms);
                 SSLContext.setCertVerifyCallback(ctx, new 
CertificateVerifier() {
                     @Override
                     public boolean verify(long ssl, byte[][] chain, String 
auth) {
                         X509Certificate[] peerCerts = certificates(chain);
                         try {
-                            manager.checkClientTrusted(peerCerts, auth);
+                            x509TrustManager.checkClientTrusted(peerCerts, 
auth);
                             return true;
                         } catch (Exception e) {
                             
log.debug(sm.getString("openssl.certificateVerificationFailed"), e);
@@ -344,7 +345,7 @@ public class OpenSSLContext implements o
                 // certificate issuers, so that their subjects can be presented
                 // by the server during the handshake to allow the client 
choosing
                 // an acceptable certificate
-                for (X509Certificate caCert : manager.getAcceptedIssuers()) {
+                for (X509Certificate caCert : 
x509TrustManager.getAcceptedIssuers()) {
                     SSLContext.addClientCACertificateRaw(ctx, 
caCert.getEncoded());
                     if (log.isDebugEnabled())
                         log.debug(sm.getString("openssl.addedClientCaCert", 
caCert.toString()));
@@ -516,19 +517,31 @@ 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);
+        X509Certificate[] chain = null;
+        if (x509KeyManager != null) {
+            if (alias == null) {
+                alias = "tomcat";
+            }
             chain = x509KeyManager.getCertificateChain(alias);
+            if (chain == null) {
+                alias = findAlias(x509KeyManager, certificate);
+                chain = x509KeyManager.getCertificateChain(alias);
+            }
         }
 
         return chain;
     }
 
     @Override
+    public X509Certificate[] getAcceptedIssuers() {
+        X509Certificate[] acceptedCerts = null;
+        if (x509TrustManager != null) {
+            acceptedCerts = x509TrustManager.getAcceptedIssuers();
+        }
+        return acceptedCerts;
+    }
+
+    @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=1817999&r1=1817998&r2=1817999&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Wed Dec 13 11:17:04 2017
@@ -92,9 +92,9 @@
       </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.
+        the currently in use certificate chain and list of trusted certificates
+        for all virtual hosts configured using the JSSE style (keystore) TLS
+        configuration via the Manager web application.
       </add>
     </changelog>
   </subsection>

Modified: 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=1817999&r1=1817998&r2=1817999&view=diff
==============================================================================
--- tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorCerts.jsp (original)
+++ tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorCerts.jsp Wed Dec 13 
11:17:04 2017
@@ -37,7 +37,7 @@
     <title>Configured certificate chains per Connector</title>
 </head>
 <body>
-<h1>Configured ciphers per Connector</h1>
+<h1>Configured certificate chains per Connector</h1>
 
 <table border="1" cellpadding="2" cellspacing="2" width="100%">
     <thead>

Added: tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorTrustedCerts.jsp
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorTrustedCerts.jsp?rev=1817999&view=auto
==============================================================================
--- tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorTrustedCerts.jsp (added)
+++ tomcat/trunk/webapps/manager/WEB-INF/jsp/connectorTrustedCerts.jsp Wed Dec 
13 11:17:04 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>> trustedCertList = (Map<String,List<String>>) 
request.getAttribute("trustedCertList");
+%>
+<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>Trusted certificates per Connector</title>
+</head>
+<body>
+<h1>Trusted certificates per Connector</h1>
+
+<table border="1" cellpadding="2" cellspacing="2" width="100%">
+    <thead>
+        <tr>
+            <th>Connector / TLS Virtual Host</th>
+            <th>Trusted Certificates</th>
+        </tr>
+    </thead>
+    <tbody>
+        <%
+        for (Map.Entry<String, List<String>> entry : 
trustedCertList.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/connectorTrustedCerts.jsp
------------------------------------------------------------------------------
    svn:eol-style = native



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

Reply via email to