From 4a8a0657929658916db8bd2586cbfb1a85532431 Mon Sep 17 00:00:00 2001
From: markt
Date: Sun, 13 Mar 2011 14:01:34 +0000
Subject: [PATCH] Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=50887
Add support for configuring the JSSE provider used to convert client
certificates. Based on a patch by pknopp.
git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1081117 13f79535-47bb-0310-9956-ffa450edef68
---
.../apache/catalina/valves/LocalStrings.properties | 2 ++
java/org/apache/catalina/valves/SSLValve.java | 17 +++++++++++++-
.../org/apache/coyote/AbstractProtocolHandler.java | 14 ++++++++++++
.../apache/coyote/ajp/AbstractAjpProcessor.java | 26 ++++++++++++++++++++--
java/org/apache/coyote/ajp/AjpAprProtocol.java | 1 +
java/org/apache/coyote/ajp/AjpProtocol.java | 1 +
.../apache/coyote/http11/Http11AprProcessor.java | 23 ++++++++++++++++++-
.../apache/coyote/http11/Http11AprProtocol.java | 1 +
webapps/docs/changelog.xml | 8 +++++++
webapps/docs/config/ajp.xml | 11 +++++++++
webapps/docs/config/http.xml | 11 +++++++++
11 files changed, 111 insertions(+), 4 deletions(-)
diff --git a/java/org/apache/catalina/valves/LocalStrings.properties b/java/org/apache/catalina/valves/LocalStrings.properties
index dbb51865f..7317e632e 100644
--- a/java/org/apache/catalina/valves/LocalStrings.properties
+++ b/java/org/apache/catalina/valves/LocalStrings.properties
@@ -41,6 +41,8 @@ errorReportValve.rootCauseInLogs=The full stack trace of the root cause is avail
# 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}).
diff --git a/java/org/apache/catalina/valves/SSLValve.java b/java/org/apache/catalina/valves/SSLValve.java
index e8d145345..c02322099 100644
--- a/java/org/apache/catalina/valves/SSLValve.java
+++ b/java/org/apache/catalina/valves/SSLValve.java
@@ -19,6 +19,7 @@ package org.apache.catalina.valves;
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.security.NoSuchProviderException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
@@ -27,6 +28,8 @@ import javax.servlet.ServletException;
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
@@ -59,6 +62,8 @@ import org.apache.catalina.connector.Response;
*/
public class SSLValve extends ValveBase {
+ private static final Log log = LogFactory.getLog(SSLValve.class);
+
//------------------------------------------------------ Constructor
public SSLValve() {
@@ -91,14 +96,24 @@ public class SSLValve extends ValveBase {
// 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);
}
diff --git a/java/org/apache/coyote/AbstractProtocolHandler.java b/java/org/apache/coyote/AbstractProtocolHandler.java
index 5d0fa561b..c5284908e 100644
--- a/java/org/apache/coyote/AbstractProtocolHandler.java
+++ b/java/org/apache/coyote/AbstractProtocolHandler.java
@@ -109,6 +109,20 @@ public abstract class AbstractProtocolHandler implements ProtocolHandler,
}
+ /**
+ * 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
diff --git a/java/org/apache/coyote/ajp/AbstractAjpProcessor.java b/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
index 7c3fdc9f7..7e5b86e4d 100644
--- a/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
+++ b/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
@@ -20,6 +20,7 @@ package org.apache.coyote.ajp;
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;
@@ -205,6 +206,19 @@ public abstract class AbstractAjpProcessor implements ActionHook, Processor {
}
+ /**
+ * 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
@@ -294,8 +308,13 @@ public abstract class AbstractAjpProcessor implements ActionHook, Processor {
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);
@@ -312,6 +331,9 @@ public abstract class AbstractAjpProcessor implements ActionHook, Processor {
} 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);
}
diff --git a/java/org/apache/coyote/ajp/AjpAprProtocol.java b/java/org/apache/coyote/ajp/AjpAprProtocol.java
index 30a526994..2d862d9a4 100644
--- a/java/org/apache/coyote/ajp/AjpAprProtocol.java
+++ b/java/org/apache/coyote/ajp/AjpAprProtocol.java
@@ -266,6 +266,7 @@ public class AjpAprProtocol extends AbstractAjpProtocol {
processor.setAdapter(proto.adapter);
processor.setTomcatAuthentication(proto.tomcatAuthentication);
processor.setRequiredSecret(proto.requiredSecret);
+ processor.setClientCertProvider(proto.getClientCertProvider());
register(processor);
return processor;
}
diff --git a/java/org/apache/coyote/ajp/AjpProtocol.java b/java/org/apache/coyote/ajp/AjpProtocol.java
index d5fd00efb..95dcafd03 100644
--- a/java/org/apache/coyote/ajp/AjpProtocol.java
+++ b/java/org/apache/coyote/ajp/AjpProtocol.java
@@ -221,6 +221,7 @@ public class AjpProtocol extends AbstractAjpProtocol {
processor.setTomcatAuthentication(proto.tomcatAuthentication);
processor.setRequiredSecret(proto.requiredSecret);
processor.setKeepAliveTimeout(proto.getKeepAliveTimeout());
+ processor.setClientCertProvider(proto.getClientCertProvider());
register(processor);
return processor;
}
diff --git a/java/org/apache/coyote/http11/Http11AprProcessor.java b/java/org/apache/coyote/http11/Http11AprProcessor.java
index 3eca711bd..0471e97aa 100644
--- a/java/org/apache/coyote/http11/Http11AprProcessor.java
+++ b/java/org/apache/coyote/http11/Http11AprProcessor.java
@@ -139,6 +139,21 @@ public class Http11AprProcessor extends AbstractHttp11Processor {
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
@@ -531,7 +546,13 @@ public class Http11AprProcessor extends AbstractHttp11Processor {
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);
diff --git a/java/org/apache/coyote/http11/Http11AprProtocol.java b/java/org/apache/coyote/http11/Http11AprProtocol.java
index 83591917f..1581fd18e 100644
--- a/java/org/apache/coyote/http11/Http11AprProtocol.java
+++ b/java/org/apache/coyote/http11/Http11AprProtocol.java
@@ -418,6 +418,7 @@ public class Http11AprProtocol extends AbstractHttp11Protocol {
processor.setSocketBuffer(proto.getSocketBuffer());
processor.setMaxSavePostSize(proto.getMaxSavePostSize());
processor.setServer(proto.getServer());
+ processor.setClientCertProvider(proto.getClientCertProvider());
register(processor);
return processor;
}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 211c49b9d..48a5b1d56 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -56,6 +56,14 @@
+
+
+
+ 50887: Add support for configuring the JSSE provider used to
+ convert client certificates. Based on a patch by pknopp. (markt)
+
+
+
diff --git a/webapps/docs/config/ajp.xml b/webapps/docs/config/ajp.xml
index c5cb35bbd..4a11231a6 100644
--- a/webapps/docs/config/ajp.xml
+++ b/webapps/docs/config/ajp.xml
@@ -268,6 +268,17 @@
interface.
+
+ 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 during which the sockets used by this
Connector will linger when they are closed.
diff --git a/webapps/docs/config/http.xml b/webapps/docs/config/http.xml
index 9902b177a..534ed4ce0 100644
--- a/webapps/docs/config/http.xml
+++ b/webapps/docs/config/http.xml
@@ -893,6 +893,17 @@
constraint that uses CLIENT-CERT authentication.
+
+ 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 certificate revocation list to be used to verify client
certificates. If not defined, client certificates will not be checked
--
2.11.0