Author: markt
Date: Sun Mar  6 09:33:26 2011
New Revision: 1078436

URL: http://svn.apache.org/viewvc?rev=1078436&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=48208
Add custom trust manager support

Modified:
    tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
    
tomcat/trunk/java/org/apache/tomcat/util/net/jsse/res/LocalStrings.properties
    tomcat/trunk/test/org/apache/tomcat/util/net/TestCustomSsl.java
    tomcat/trunk/test/org/apache/tomcat/util/net/TesterSupport.java
    tomcat/trunk/webapps/docs/changelog.xml
    tomcat/trunk/webapps/docs/config/http.xml

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java?rev=1078436&r1=1078435&r2=1078436&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java Sun Mar  
6 09:33:26 2011
@@ -679,9 +679,13 @@ public abstract class AbstractEndpoint {
     private String truststoreFile = 
System.getProperty("javax.net.ssl.trustStore");
     public String getTruststoreFile() {return truststoreFile;}
     public void setTruststoreFile(String s) {
-        String file = adjustRelativePath(s,
-                System.getProperty(Constants.CATALINA_BASE_PROP));
-        this.truststoreFile = file;
+        if (s == null) {
+            this.truststoreFile = null;
+        } else {
+            String file = adjustRelativePath(s,
+                    System.getProperty(Constants.CATALINA_BASE_PROP));
+            this.truststoreFile = file;
+        }
     }
 
     private String truststorePass =
@@ -710,6 +714,12 @@ public abstract class AbstractEndpoint {
         this.truststoreAlgorithm = truststoreAlgorithm;
     }
 
+    private String trustManagerClassName = null;
+    public String getTrustManagerClassName() {return trustManagerClassName;}
+    public void setTrustManagerClassName(String trustManagerClassName) {
+        this.trustManagerClassName = trustManagerClassName;
+    }
+
     private String crlFile = null;
     public String getCrlFile() {return crlFile;}
     public void setCrlFile(String crlFile) {

Modified: 
tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java?rev=1078436&r1=1078435&r2=1078436&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java 
Sun Mar  6 09:33:26 2011
@@ -569,12 +569,12 @@ public class JSSESocketFactory implement
         TrustManager[] tms = null;
         
         KeyStore trustStore = getTrustStore(keystoreType, keystoreProvider);
-        if (trustStore != null) {
+        if (trustStore != null || endpoint.getTrustManagerClassName() != null) 
{
             if (crlf == null) {
                 TrustManagerFactory tmf =
                     TrustManagerFactory.getInstance(algorithm);
                 tmf.init(trustStore);
-                tms = tmf.getTrustManagers();
+                tms = getTrustManagers(tmf);
             } else {
                 TrustManagerFactory tmf =
                     TrustManagerFactory.getInstance(algorithm);
@@ -583,13 +583,42 @@ public class JSSESocketFactory implement
                 ManagerFactoryParameters mfp =
                     new CertPathTrustManagerParameters(params);
                 tmf.init(mfp);
-                tms = tmf.getTrustManagers();
+                tms = getTrustManagers(tmf);
             }
         }
         
         return tms;
     }
-    
+
+    /**
+     * Gets the TrustManagers either from Connector's
+     * <code>trustManagerClassName</code> attribute (if set) else from the
+     * {@link TrustManagerFactory}.
+     * @return The TrustManagers to use for this connector.
+     * @throws NoSuchAlgorithmException 
+     * @throws ClassNotFoundException 
+     * @throws IllegalAccessException 
+     * @throws InstantiationException 
+    */
+   protected TrustManager[] getTrustManagers(TrustManagerFactory tmf)
+           throws NoSuchAlgorithmException, ClassNotFoundException,
+           InstantiationException, IllegalAccessException {
+
+       String className = endpoint.getTrustManagerClassName();
+       if(className != null && className.length() > 0) {
+            ClassLoader classLoader = getClass().getClassLoader();
+            Class<?> clazz = classLoader.loadClass(className);
+            if(!(TrustManager.class.isAssignableFrom(clazz))){
+               throw new InstantiationException(sm.getString(
+                       "jsse.invalidTrustManagerClassName", className));
+            }
+            Object trustManagerObject = clazz.newInstance();
+            TrustManager trustManager = (TrustManager) trustManagerObject;
+            return new TrustManager[]{ trustManager };
+        }      
+       return tmf.getTrustManagers();
+   }
+
     /**
      * Return the initialization parameters for the TrustManager.
      * Currently, only the default <code>PKIX</code> is supported.

Modified: 
tomcat/trunk/java/org/apache/tomcat/util/net/jsse/res/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/jsse/res/LocalStrings.properties?rev=1078436&r1=1078435&r2=1078436&view=diff
==============================================================================
--- 
tomcat/trunk/java/org/apache/tomcat/util/net/jsse/res/LocalStrings.properties 
(original)
+++ 
tomcat/trunk/java/org/apache/tomcat/util/net/jsse/res/LocalStrings.properties 
Sun Mar  6 09:33:26 2011
@@ -16,4 +16,5 @@
 jsse.alias_no_key_entry=Alias name {0} does not identify a key entry
 jsse.keystore_load_failed=Failed to load keystore type {0} with path {1} due 
to {2}
 jsse.invalid_ssl_conf=SSL configuration is invalid due to {0}
-jsse.invalid_truststore_password=The provided trust store password could not 
be used to unlock and/or validate the trust store. Retrying to access the trust 
store with a null password which will skip validation.
\ No newline at end of file
+jsse.invalid_truststore_password=The provided trust store password could not 
be used to unlock and/or validate the trust store. Retrying to access the trust 
store with a null password which will skip validation.
+jsse.invalidTrustManagerClassName=The trustManagerClassName provided [{0}] 
does not implement javax.net.ssl.TrustManager 
\ No newline at end of file

Modified: tomcat/trunk/test/org/apache/tomcat/util/net/TestCustomSsl.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/net/TestCustomSsl.java?rev=1078436&r1=1078435&r2=1078436&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/util/net/TestCustomSsl.java (original)
+++ tomcat/trunk/test/org/apache/tomcat/util/net/TestCustomSsl.java Sun Mar  6 
09:33:26 2011
@@ -17,12 +17,15 @@
 package org.apache.tomcat.util.net;
 
 import java.io.File;
+import java.net.SocketException;
 
-import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLHandshakeException;
 
 import org.apache.catalina.connector.Connector;
 import org.apache.catalina.startup.Tomcat;
 import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.coyote.ProtocolHandler;
+import org.apache.coyote.http11.AbstractHttp11JsseProtocol;
 import org.apache.tomcat.util.buf.ByteChunk;
 import org.apache.tomcat.util.net.jsse.TesterBug50640SslImpl;
 
@@ -35,16 +38,8 @@ public class TestCustomSsl extends Tomca
 
     public void testCustomSslImplementation() throws Exception {
 
-        try {
-            SSLContext sc = SSLContext.getInstance("SSL");
-            sc.init(null, TesterSupport.getTrustManagers(),
-                    new java.security.SecureRandom());
-            javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(
-                    sc.getSocketFactory());
-        } catch (Exception e) {
-            e.printStackTrace();
-        } 
-        
+        TesterSupport.configureClientSsl();
+
         Tomcat tomcat = getTomcatInstance();
         Connector connector = tomcat.getConnector();
         if (connector.getProtocolHandlerClassName().contains("Apr")) {
@@ -76,4 +71,70 @@ public class TestCustomSsl extends Tomca
         assertTrue(res.toString().indexOf("<h1>Hello World!</h1>") > 0);
     }
 
+    public void testCustomTrustManager1() throws Exception {
+        doTestCustomTrustManager(false);
+    }
+    
+    public void testCustomTrustManager2() throws Exception {
+        doTestCustomTrustManager(true);
+    }
+    
+    private void doTestCustomTrustManager(boolean serverTrustAll)
+            throws Exception {
+        
+        if (!TesterSupport.RFC_5746_SUPPORTED) {
+            // Make sure SSL renegotiation is not disabled in the JVM
+            System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", 
"true");
+        }
+
+        Tomcat tomcat = getTomcatInstance();
+
+        if (!TesterSupport.isRenegotiationSupported(getTomcatInstance())) {
+            return;
+        }
+
+        TesterSupport.configureClientCertContext(tomcat);
+        
+        // Override the defaults
+        ProtocolHandler handler = tomcat.getConnector().getProtocolHandler();
+        if (handler instanceof AbstractHttp11JsseProtocol) {
+            ((AbstractHttp11JsseProtocol) handler).setTruststoreFile(null);
+        } else {
+            // Unexpected
+            fail("Unexpected handler type");
+        }
+        if (serverTrustAll) {
+            tomcat.getConnector().setAttribute("trustManagerClassName",
+                    "org.apache.tomcat.util.net.TesterSupport$TrustAllCerts");
+        }
+        
+        // Start Tomcat
+        tomcat.start();
+        
+        TesterSupport.configureClientSsl();
+
+        // Unprotected resource
+        ByteChunk res =
+                getUrl("https://localhost:"; + getPort() + "/unprotected");
+        assertEquals("OK", res.toString());
+        
+        // Protected resource
+        res.recycle();
+        int rc = -1;
+        try {
+            rc = getUrl("https://localhost:"; + getPort() + "/protected", res,
+                null, null);
+        } catch (SocketException expected1) {
+            // Ignore
+        } catch (SSLHandshakeException expected2) {
+            // Ignore
+        }
+        if (serverTrustAll) {
+            assertEquals(200, rc);
+            assertEquals("OK", res.toString());
+        } else {
+            assertTrue(rc != 200);
+            assertEquals("", res.toString());
+        }
+    }
 }

Modified: tomcat/trunk/test/org/apache/tomcat/util/net/TesterSupport.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/net/TesterSupport.java?rev=1078436&r1=1078435&r2=1078436&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/util/net/TesterSupport.java (original)
+++ tomcat/trunk/test/org/apache/tomcat/util/net/TesterSupport.java Sun Mar  6 
09:33:26 2011
@@ -24,6 +24,7 @@ import java.security.KeyManagementExcept
 import java.security.KeyStore;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
 
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
@@ -31,6 +32,7 @@ import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLServerSocketFactory;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
@@ -226,4 +228,24 @@ public final class TesterSupport {
                 resp.getWriter().print("CONTENT-MISMATCH-" + read);
         }
     }
+    
+    public static class TrustAllCerts implements X509TrustManager {
+        
+        @Override
+        public X509Certificate[] getAcceptedIssuers() {
+            return new X509Certificate[0];
+        }
+        
+        @Override
+        public void checkClientTrusted(X509Certificate[] certs,
+                String authType) {
+            // NOOP - Trust everything
+        }
+        
+        @Override
+        public void checkServerTrusted(X509Certificate[] certs,
+                String authType) {
+            // NOOP - Trust everything
+        }
+    }
 }

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1078436&r1=1078435&r2=1078436&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Sun Mar  6 09:33:26 2011
@@ -51,6 +51,14 @@
       </fix>
     </changelog>
   </subsection>
+  <subsection name="Coyote">
+    <changelog>
+      <add>
+        <bug>48208</bug>: Allow the configuration of a custom trust manager for
+        use in CLIENT-CERT authentication. (markt)
+      </add>
+    </changelog>
+  </subsection>
   <subsection name="Jasper">
     <changelog>
       <fix>

Modified: tomcat/trunk/webapps/docs/config/http.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/http.xml?rev=1078436&r1=1078435&r2=1078436&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/http.xml (original)
+++ tomcat/trunk/webapps/docs/config/http.xml Sun Mar  6 09:33:26 2011
@@ -967,6 +967,14 @@
       the default is "<code>TLS</code>".</p>
     </attribute>
 
+    <attribute name="trustManagerClassName" required="false">
+      <p>The name of a custom trust manager class to use to validate client
+      certificates. The class must have a zero argument constructor and must
+      also implement <code>javax.net.ssl.X509TrustManager</code>. If this
+      attribute is set, the trust store attributes may be ignored.
+      </p>
+    </attribute>
+    
     <attribute name="trustMaxCertLength" required="false">
       <p>The maximum number of intermediate certificates that will be allowed
       when validating client certificates. If not specified, the default value



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

Reply via email to