Index: java/org/apache/catalina/valves/LocalStrings.properties =================================================================== --- java/org/apache/catalina/valves/LocalStrings.properties (revision 1080687) +++ java/org/apache/catalina/valves/LocalStrings.properties (working copy) @@ -44,6 +44,8 @@ # Remote IP valve remoteIpValve.syntax=Invalid regular expressions [{0}] provided. +sslValve.invalidProvider=The SSL provider specified on the connector associated with this request of [{0}] is invalid. The certificate data could not be processed. + # HTTP status reports http.100=The client may continue ({0}). http.101=The server is switching protocols according to the "Upgrade" header ({0}). Index: java/org/apache/catalina/valves/SSLValve.java =================================================================== --- java/org/apache/catalina/valves/SSLValve.java (revision 1080687) +++ java/org/apache/catalina/valves/SSLValve.java (working copy) @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.ByteArrayInputStream; +import java.security.NoSuchProviderException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; @@ -28,7 +29,8 @@ import org.apache.catalina.valves.ValveBase; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; -import org.apache.catalina.util.StringManager; +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; /* * Valve to fill the SSL informations in the request @@ -46,8 +48,10 @@ * @version $Id$ */ -public class SSLValve - extends ValveBase { +public class SSLValve extends ValveBase { + + private static final Log log = LogFactory.getLog(SSLValve.class); + /* private static final String info = "SSLValve/1.0"; @@ -87,14 +91,25 @@ // ByteArrayInputStream bais = new ByteArrayInputStream(strcerts.getBytes("UTF-8")); ByteArrayInputStream bais = new ByteArrayInputStream(strcerts.getBytes()); X509Certificate jsseCerts[] = null; + String providerName = (String) request.getConnector().getProperty( + "clientCertProvider"); try { - CertificateFactory cf = CertificateFactory.getInstance("X.509"); + CertificateFactory cf; + if (providerName == null) { + cf = CertificateFactory.getInstance("X.509"); + } else { + cf = CertificateFactory.getInstance("X.509", providerName); + } X509Certificate cert = (X509Certificate) cf.generateCertificate(bais); jsseCerts = new X509Certificate[1]; jsseCerts[0] = cert; } catch (java.security.cert.CertificateException e) { System.out.println("SSLValve failed " + strcerts); System.out.println("SSLValve failed " + e); + } catch (NoSuchProviderException e) { + log.error(sm.getString( + "sslValve.invalidProvider", providerName), e); + } request.setAttribute("javax.servlet.request.X509Certificate", jsseCerts); } Index: java/org/apache/coyote/ajp/AjpAprProcessor.java =================================================================== --- java/org/apache/coyote/ajp/AjpAprProcessor.java (revision 1080687) +++ java/org/apache/coyote/ajp/AjpAprProcessor.java (working copy) @@ -22,6 +22,7 @@ import java.io.InterruptedIOException; import java.net.InetAddress; import java.nio.ByteBuffer; +import java.security.NoSuchProviderException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; @@ -334,6 +335,20 @@ public void setRequiredSecret(String requiredSecret) { this.requiredSecret = requiredSecret; } + /** + * When client certificate information is presented in a form other than + * instances of {@link java.security.cert.X509Certificate} it needs to be + * converted before it can be used and this property controls which JSSE + * provider is used to perform the conversion. For example it is used with + * the AJP connectors, the HTTP APR connector and with the + * {@link org.apache.catalina.valves.SSLValve}. If not specified, the + * default provider will be used. + */ + protected String clientCertProvider = null; + public String getClientCertProvider() { return clientCertProvider; } + public void setClientCertProvider(String s) { this.clientCertProvider = s; } + + // --------------------------------------------------------- Public Methods @@ -555,8 +570,13 @@ certData.getLength()); // Fill the elements. try { - CertificateFactory cf = - CertificateFactory.getInstance("X.509"); + CertificateFactory cf; + if (clientCertProvider == null) { + cf = CertificateFactory.getInstance("X.509"); + } else { + cf = CertificateFactory.getInstance("X.509", + clientCertProvider); + } while(bais.available() > 0) { X509Certificate cert = (X509Certificate) cf.generateCertificate(bais); @@ -573,6 +593,9 @@ } catch (java.security.cert.CertificateException e) { log.error(sm.getString("ajpprocessor.certs.fail"), e); return; + } catch (NoSuchProviderException e) { + log.error(sm.getString("ajpprocessor.certs.fail"), e); + return; } request.setAttribute(AprEndpoint.CERTIFICATE_KEY, jsseCerts); } Index: java/org/apache/coyote/ajp/AjpAprProtocol.java =================================================================== --- java/org/apache/coyote/ajp/AjpAprProtocol.java (revision 1080687) +++ java/org/apache/coyote/ajp/AjpAprProtocol.java (working copy) @@ -315,6 +315,21 @@ public void setPollerSize(int pollerSize) { endpoint.setPollerSize(pollerSize); } public int getPollerSize() { return endpoint.getPollerSize(); } + + /** + * When client certificate information is presented in a form other than + * instances of {@link java.security.cert.X509Certificate} it needs to be + * converted before it can be used and this property controls which JSSE + * provider is used to perform the conversion. For example it is used with + * the AJP connectors, the HTTP APR connector and with the + * {@link org.apache.catalina.valves.SSLValve}. If not specified, the + * default provider will be used. + */ + protected String clientCertProvider = null; + public String getClientCertProvider() { return clientCertProvider; } + public void setClientCertProvider(String s) { this.clientCertProvider = s; } + + // -------------------------------------- AjpConnectionHandler Inner Class @@ -421,6 +436,7 @@ processor.setAdapter(proto.adapter); processor.setTomcatAuthentication(proto.tomcatAuthentication); processor.setRequiredSecret(proto.requiredSecret); + processor.setClientCertProvider(proto.getClientCertProvider()); register(processor); return processor; } Index: java/org/apache/coyote/ajp/AjpProcessor.java =================================================================== --- java/org/apache/coyote/ajp/AjpProcessor.java (revision 1080687) +++ java/org/apache/coyote/ajp/AjpProcessor.java (working copy) @@ -24,6 +24,7 @@ import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; +import java.security.NoSuchProviderException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; @@ -344,6 +345,20 @@ public void setKeepAliveTimeout(int timeout) { keepAliveTimeout = timeout; } + /** + * When client certificate information is presented in a form other than + * instances of {@link java.security.cert.X509Certificate} it needs to be + * converted before it can be used and this property controls which JSSE + * provider is used to perform the conversion. For example it is used with + * the AJP connectors, the HTTP APR connector and with the + * {@link org.apache.catalina.valves.SSLValve}. If not specified, the + * default provider will be used. + */ + protected String clientCertProvider = null; + public String getClientCertProvider() { return clientCertProvider; } + public void setClientCertProvider(String s) { this.clientCertProvider = s; } + + // --------------------------------------------------------- Public Methods @@ -560,8 +575,13 @@ certData.getLength()); // Fill the elements. try { - CertificateFactory cf = - CertificateFactory.getInstance("X.509"); + CertificateFactory cf; + if (clientCertProvider == null) { + cf = CertificateFactory.getInstance("X.509"); + } else { + cf = CertificateFactory.getInstance("X.509", + clientCertProvider); + } while(bais.available() > 0) { X509Certificate cert = (X509Certificate) cf.generateCertificate(bais); @@ -578,6 +598,9 @@ } catch (java.security.cert.CertificateException e) { log.error(sm.getString("ajpprocessor.certs.fail"), e); return; + } catch (NoSuchProviderException e) { + log.error(sm.getString("ajpprocessor.certs.fail"), e); + return; } request.setAttribute(JIoEndpoint.CERTIFICATE_KEY, jsseCerts); } Index: java/org/apache/coyote/ajp/AjpProtocol.java =================================================================== --- java/org/apache/coyote/ajp/AjpProtocol.java (revision 1080687) +++ java/org/apache/coyote/ajp/AjpProtocol.java (working copy) @@ -308,6 +308,20 @@ public void setKeepAliveTimeout(int timeout) { keepAliveTimeout = timeout; } + /** + * When client certificate information is presented in a form other than + * instances of {@link java.security.cert.X509Certificate} it needs to be + * converted before it can be used and this property controls which JSSE + * provider is used to perform the conversion. For example it is used with + * the AJP connectors, the HTTP APR connector and with the + * {@link org.apache.catalina.valves.SSLValve}. If not specified, the + * default provider will be used. + */ + protected String clientCertProvider = null; + public String getClientCertProvider() { return clientCertProvider; } + public void setClientCertProvider(String s) { this.clientCertProvider = s; } + + // -------------------------------------- AjpConnectionHandler Inner Class @@ -407,6 +421,7 @@ processor.setTomcatAuthentication(proto.tomcatAuthentication); processor.setRequiredSecret(proto.requiredSecret); processor.setKeepAliveTimeout(proto.keepAliveTimeout); + processor.setClientCertProvider(proto.getClientCertProvider()); register(processor); return processor; } Index: java/org/apache/coyote/http11/Http11AprProcessor.java =================================================================== --- java/org/apache/coyote/http11/Http11AprProcessor.java (revision 1080687) +++ java/org/apache/coyote/http11/Http11AprProcessor.java (working copy) @@ -320,8 +320,21 @@ protected String server = null; + /** + * When client certificate information is presented in a form other than + * instances of {@link java.security.cert.X509Certificate} it needs to be + * converted before it can be used and this property controls which JSSE + * provider is used to perform the conversion. For example it is used with + * the AJP connectors, the HTTP APR connector and with the + * {@link org.apache.catalina.valves.SSLValve}. If not specified, the + * default provider will be used. + */ + protected String clientCertProvider = null; + // ------------------------------------------------------------- Properties + public String getClientCertProvider() { return clientCertProvider; } + public void setClientCertProvider(String s) { this.clientCertProvider = s; } /** * Return compression level. @@ -1151,7 +1164,13 @@ X509Certificate[] certs = null; if (clientCert != null && certLength > -1) { certs = new X509Certificate[certLength + 1]; - CertificateFactory cf = CertificateFactory.getInstance("X.509"); + CertificateFactory cf; + if (clientCertProvider == null) { + cf = CertificateFactory.getInstance("X.509"); + } else { + cf = CertificateFactory.getInstance("X.509", + clientCertProvider); + } certs[0] = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(clientCert)); for (int i = 0; i < certLength; i++) { byte[] data = SSLSocket.getInfoB(socket, SSL.SSL_INFO_CLIENT_CERT_CHAIN + i); Index: java/org/apache/coyote/http11/Http11AprProtocol.java =================================================================== --- java/org/apache/coyote/http11/Http11AprProtocol.java (revision 1080687) +++ java/org/apache/coyote/http11/Http11AprProtocol.java (working copy) @@ -470,7 +470,22 @@ */ public int getSSLVerifyDepth() { return endpoint.getSSLVerifyDepth(); } public void setSSLVerifyDepth(int SSLVerifyDepth) { endpoint.setSSLVerifyDepth(SSLVerifyDepth); } + + /** + * When client certificate information is presented in a form other than + * instances of {@link java.security.cert.X509Certificate} it needs to be + * converted before it can be used and this property controls which JSSE + * provider is used to perform the conversion. For example it is used with + * the AJP connectors, the HTTP APR connector and with the + * {@link org.apache.catalina.valves.SSLValve}. If not specified, the + * default provider will be used. + */ + protected String clientCertProvider = null; + public String getClientCertProvider() { return clientCertProvider; } + public void setClientCertProvider(String s) { this.clientCertProvider = s; } + + // -------------------- Connection handler -------------------- static class Http11ConnectionHandler implements Handler { @@ -628,6 +643,7 @@ processor.setSocketBuffer(proto.socketBuffer); processor.setMaxSavePostSize(proto.maxSavePostSize); processor.setServer(proto.server); + processor.setClientCertProvider(proto.getClientCertProvider()); register(processor); return processor; } Index: java/org/apache/coyote/http11/Http11NioProtocol.java =================================================================== --- java/org/apache/coyote/http11/Http11NioProtocol.java (revision 1080687) +++ java/org/apache/coyote/http11/Http11NioProtocol.java (working copy) @@ -582,8 +582,20 @@ public boolean getSSLEnabled() { return ep.isSSLEnabled(); } public void setSSLEnabled(boolean SSLEnabled) { ep.setSSLEnabled(SSLEnabled); } - + /** + * When client certificate information is presented in a form other than + * instances of {@link java.security.cert.X509Certificate} it needs to be + * converted before it can be used and this property controls which JSSE + * provider is used to perform the conversion. For example it is used with + * the AJP connectors, the HTTP APR connector and with the + * {@link org.apache.catalina.valves.SSLValve}. If not specified, the + * default provider will be used. + */ + protected String clientCertProvider = null; + public String getClientCertProvider() { return clientCertProvider; } + public void setClientCertProvider(String s) { this.clientCertProvider = s; } + // -------------------- Connection handler -------------------- static class Http11ConnectionHandler implements Handler { Index: java/org/apache/coyote/http11/Http11Protocol.java =================================================================== --- java/org/apache/coyote/http11/Http11Protocol.java (revision 1080687) +++ java/org/apache/coyote/http11/Http11Protocol.java (working copy) @@ -518,6 +518,20 @@ setAttribute("keyAlias", keyAlias); } + /** + * When client certificate information is presented in a form other than + * instances of {@link java.security.cert.X509Certificate} it needs to be + * converted before it can be used and this property controls which JSSE + * provider is used to perform the conversion. For example it is used with + * the AJP connectors, the HTTP APR connector and with the + * {@link org.apache.catalina.valves.SSLValve}. If not specified, the + * default provider will be used. + */ + protected String clientCertProvider = null; + public String getClientCertProvider() { return clientCertProvider; } + public void setClientCertProvider(String s) { this.clientCertProvider = s; } + + // ----------------------------------- Http11ConnectionHandler Inner Class protected static class Http11ConnectionHandler implements Handler { Index: webapps/docs/config/ajp.xml =================================================================== --- webapps/docs/config/ajp.xml (revision 1080687) +++ webapps/docs/config/ajp.xml (working copy) @@ -248,6 +248,17 @@ (i.e. buffering disabled)

+ +

When client certificate information is presented in a form other than + instances of java.security.cert.X509Certificate it needs to + be converted before it can be used and this property controls which JSSE + provider is used to perform the conversion. For example it is used with + the AJP connectors, the HTTP APR connector and + with the + org.apache.catalina.valves.SSLValve.If not specified, the default + provider will be used.

+
+

The number of milliseconds this Connector will wait, after accepting a connection, for the request URI line to be Index: webapps/docs/config/http.xml =================================================================== --- webapps/docs/config/http.xml (revision 1080687) +++ webapps/docs/config/http.xml (working copy) @@ -694,6 +694,17 @@ SSL HowTo for an example.

+ +

When client certificate information is presented in a form other than + instances of java.security.cert.X509Certificate it needs to + be converted before it can be used and this property controls which JSSE + provider is used to perform the conversion. For example it is used with + the AJP connectors, the HTTP APR connector and + with the + org.apache.catalina.valves.SSLValve. If not specified, the default + provider will be used.

+
+

The pathname of the keystore file where you have stored the server certificate to be loaded. By default, the pathname is