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 =
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) {
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);
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.
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
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;
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")) {
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());
+ }
+ }
}
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;
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;
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
+ }
+ }
}
</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>
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