# 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}).
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.security.NoSuchProviderException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import org.apache.catalina.Globals;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
/**
* When using mod_proxy_http, the client SSL information is not included in the
*/
public class SSLValve extends ValveBase {
+ private static final Log log = LogFactory.getLog(SSLValve.class);
+
//------------------------------------------------------ Constructor
public SSLValve() {
// 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(Globals.CERTIFICATES_ATTR, jsseCerts);
}
}
+ /**
+ * 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; }
+
+
// ---------------------- Properties that are passed through to the EndPoint
@Override
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.InetAddress;
+import java.security.NoSuchProviderException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.concurrent.Executor;
}
+ /**
+ * 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
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);
} catch (java.security.cert.CertificateException e) {
getLog().error(sm.getString("ajpprocessor.certs.fail"), e);
return;
+ } catch (NoSuchProviderException e) {
+ getLog().error(sm.getString("ajpprocessor.certs.fail"), e);
+ return;
}
request.setAttribute(SSLSupport.CERTIFICATE_KEY, jsseCerts);
}
processor.setAdapter(proto.adapter);
processor.setTomcatAuthentication(proto.tomcatAuthentication);
processor.setRequiredSecret(proto.requiredSecret);
+ processor.setClientCertProvider(proto.getClientCertProvider());
register(processor);
return processor;
}
processor.setTomcatAuthentication(proto.tomcatAuthentication);
processor.setRequiredSecret(proto.requiredSecret);
processor.setKeepAliveTimeout(proto.getKeepAliveTimeout());
+ processor.setClientCertProvider(proto.getClientCertProvider());
register(processor);
return processor;
}
return endpoint;
}
+
+ /**
+ * 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
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(socketRef, SSL.SSL_INFO_CLIENT_CERT_CHAIN + i);
processor.setSocketBuffer(proto.getSocketBuffer());
processor.setMaxSavePostSize(proto.getMaxSavePostSize());
processor.setServer(proto.getServer());
+ processor.setClientCertProvider(proto.getClientCertProvider());
register(processor);
return processor;
}
</fix>
</changelog>
</subsection>
+ <subsection name="Coyote">
+ <changelog>
+ <add>
+ <bug>50887</bug>: Add support for configuring the JSSE provider used to
+ convert client certificates. Based on a patch by pknopp. (markt)
+ </add>
+ </changelog>
+ </subsection>
<subsection name="Other">
<changelog>
<update>
interface.</p>
</attribute>
+ <attribute name="clientCertProvider" required="false">
+ <p>When client certificate information is presented in a form other than
+ instances of <code>java.security.cert.X509Certificate</code> 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 <a href="http.html">HTTP APR connector</a> and
+ with the <a href="valve.html#SSL_Authenticator_Valve">
+ org.apache.catalina.valves.SSLValve</a>.If not specified, the default
+ provider will be used.</p>
+ </attribute>
+
<attribute name="connectionLinger" required="false">
<p>The number of milliseconds during which the sockets used by this
<strong>Connector</strong> will linger when they are closed.
constraint that uses <code>CLIENT-CERT</code> authentication.</p>
</attribute>
+ <attribute name="clientCertProvider" required="false">
+ <p>When client certificate information is presented in a form other than
+ instances of <code>java.security.cert.X509Certificate</code> 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 <a href="ajp.html">AJP connectors</a>, the HTTP APR connector and
+ with the <a href="valve.html#SSL_Authenticator_Valve">
+ org.apache.catalina.valves.SSLValve</a>. If not specified, the default
+ provider will be used.</p>
+ </attribute>
+
<attribute name="crlFile" required="false">
<p>The certificate revocation list to be used to verify client
certificates. If not defined, client certificates will not be checked