Author: schultz
Date: Thu Mar 8 17:22:29 2012
New Revision: 1298476
URL: http://svn.apache.org/viewvc?rev=1298476&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=52500
Added configurable mechanism to retrieve user names from X509 client
certificates. Based on a patch provided by Michael Furman.
Added:
tomcat/trunk/java/org/apache/catalina/realm/X509SubjectDnRetriever.java
tomcat/trunk/java/org/apache/catalina/realm/X509UsernameRetriever.java
Modified:
tomcat/trunk/java/org/apache/catalina/realm/LocalStrings.properties
tomcat/trunk/java/org/apache/catalina/realm/RealmBase.java
tomcat/trunk/webapps/docs/config/realm.xml
Modified: tomcat/trunk/java/org/apache/catalina/realm/LocalStrings.properties
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/realm/LocalStrings.properties?rev=1298476&r1=1298475&r2=1298476&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/realm/LocalStrings.properties
(original)
+++ tomcat/trunk/java/org/apache/catalina/realm/LocalStrings.properties Thu Mar
8 17:22:29 2012
@@ -60,6 +60,11 @@ realmBase.hasRoleSuccess=Username {0} ha
realmBase.authenticateFailure=Username {0} NOT successfully authenticated
realmBase.authenticateSuccess=Username {0} successfully authenticated
realmBase.gssNameFail=Failed to extract name from established GSSContext
+realmBase.gotX509Username=Got user name from X509 certificate: {0}
+realmBase.createUsernameRetriever.ClassCastException=Class {0} is not an
X509UsernameRetriever.
+realmBase.createUsernameRetriever.ClassNotFoundException=Cannot find class {0}.
+realmBase.createUsernameRetriever.InstantiationException=Cannot create object
of type {0}.
+realmBase.createUsernameRetriever.IllegalAccessException=Cannot create object
of type {0}.
userDatabaseRealm.lookup=Exception looking up UserDatabase under key {0}
userDatabaseRealm.noDatabase=No UserDatabase component found under key {0}
dataSourceRealm.authenticateFailure=Username {0} NOT successfully authenticated
Modified: tomcat/trunk/java/org/apache/catalina/realm/RealmBase.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/realm/RealmBase.java?rev=1298476&r1=1298475&r2=1298476&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/realm/RealmBase.java (original)
+++ tomcat/trunk/java/org/apache/catalina/realm/RealmBase.java Thu Mar 8
17:22:29 2012
@@ -136,6 +136,16 @@ public abstract class RealmBase extends
*/
protected boolean validate = true;
+ /**
+ * The name of the class to use for retrieving user names from X509
+ * certificates.
+ */
+ protected String x509UsernameRetrieverClassName;
+
+ /**
+ * The object that will extract user names from X509 client certificates.
+ */
+ protected X509UsernameRetriever x509UsernameRetriever;
/**
* The all role mode.
@@ -266,6 +276,29 @@ public abstract class RealmBase extends
}
+ /**
+ * Gets the name of the class that will be used to extract user names
+ * from X509 client certificates.
+ * @return The name of the class that will be used to extract user names
+ * from X509 client certificates.
+ */
+ public String getX509UsernameRetrieverClassName()
+ {
+ return x509UsernameRetrieverClassName;
+ }
+
+ /**
+ * Sets the name of the class that will be used to extract user names
+ * from X509 client certificates. The class must implement
+ * {@see X509UsernameRetriever}.
+ *
+ * @param className The name of the class that will be used to extract
user names
+ * from X509 client certificates.
+ */
+ public void setX509UsernameRetrieverClassName(String className)
+ {
+ this.x509UsernameRetrieverClassName = className;
+ }
public boolean isStripRealmForGss() {
return stripRealmForGss;
@@ -1034,6 +1067,8 @@ public abstract class RealmBase extends
if (container != null) {
this.containerLog = container.getLogger();
}
+
+ x509UsernameRetriever =
createUsernameRetriever(x509UsernameRetrieverClassName);
}
/**
@@ -1191,7 +1226,12 @@ public abstract class RealmBase extends
* Return the Principal associated with the given certificate.
*/
protected Principal getPrincipal(X509Certificate usercert) {
- return(getPrincipal(usercert.getSubjectDN().getName()));
+ String username = x509UsernameRetriever.getUsername(usercert);
+
+ if(log.isDebugEnabled())
+ log.debug(sm.getString("realmBase.gotX509Username", username));
+
+ return(getPrincipal(username));
}
@@ -1391,4 +1431,23 @@ public abstract class RealmBase extends
}
}
+ private static X509UsernameRetriever createUsernameRetriever(String
className)
+ throws LifecycleException {
+ if(null == className || "".equals(className.trim()))
+ return new X509SubjectDnRetriever();
+
+ try {
+ @SuppressWarnings("unchecked")
+ Class<? extends X509UsernameRetriever> clazz = (Class<? extends
X509UsernameRetriever>)Class.forName(className);
+ return (X509UsernameRetriever)clazz.newInstance();
+ } catch (ClassNotFoundException e) {
+ throw new
LifecycleException(sm.getString("realmBase.createUsernameRetriever.ClassNotFoundException",
className), e);
+ } catch (InstantiationException e) {
+ throw new
LifecycleException(sm.getString("realmBase.createUsernameRetriever.InstantiationException",
className), e);
+ } catch (IllegalAccessException e) {
+ throw new
LifecycleException(sm.getString("realmBase.createUsernameRetriever.IllegalAccessException",
className), e);
+ } catch (ClassCastException e) {
+ throw new
LifecycleException(sm.getString("realmBase.createUsernameRetriever.ClassCastException",
className), e);
+ }
+ }
}
Added: tomcat/trunk/java/org/apache/catalina/realm/X509SubjectDnRetriever.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/realm/X509SubjectDnRetriever.java?rev=1298476&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/realm/X509SubjectDnRetriever.java
(added)
+++ tomcat/trunk/java/org/apache/catalina/realm/X509SubjectDnRetriever.java Thu
Mar 8 17:22:29 2012
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.realm;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * An X509UsernameRetriever that returns a certificate's entire
+ * SubjectDN as the username.
+ */
+public class X509SubjectDnRetriever
+ implements X509UsernameRetriever {
+ public String getUsername(X509Certificate clientCert) {
+ return clientCert.getSubjectDN().getName();
+ }
+}
Added: tomcat/trunk/java/org/apache/catalina/realm/X509UsernameRetriever.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/realm/X509UsernameRetriever.java?rev=1298476&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/realm/X509UsernameRetriever.java
(added)
+++ tomcat/trunk/java/org/apache/catalina/realm/X509UsernameRetriever.java Thu
Mar 8 17:22:29 2012
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.realm;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * Provides an interface for retrieving a user name from an X509Certificate.
+ */
+public interface X509UsernameRetriever {
+ /**
+ * Gets a user name from an X509Certificate.
+ *
+ * @param cert The certificate containing the user name.
+ * @return An appropriate user name obtained from one or more fields
+ * in the certificate.
+ */
+ public String getUsername(X509Certificate clientCert);
+}
Modified: tomcat/trunk/webapps/docs/config/realm.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/realm.xml?rev=1298476&r1=1298475&r2=1298476&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/realm.xml (original)
+++ tomcat/trunk/webapps/docs/config/realm.xml Thu Mar 8 17:22:29 2012
@@ -188,6 +188,14 @@
attributes.</p>
</attribute>
+ <attribute name="X509UsernameRetrieverClassName" required="false">
+ <p>When using X509 client certificates, this specifies the class name
+ that will be used to retrieve the user name from the certificate.
+ The class must implement the
+ <code>org.apache.catalina.realm.X509UsernameRetriever</code>
+ interface. The default is to use the certificate's SubjectDN
+ as the username.</p>
+ </attribute>
</attributes>
<p>See the <a href="../realm-howto.html">Container-Managed Security
Guide</a> for more
@@ -288,6 +296,14 @@
attributes.</p>
</attribute>
+ <attribute name="X509UsernameRetrieverClassName" required="false">
+ <p>When using X509 client certificates, this specifies the class name
+ that will be used to retrieve the user name from the certificate.
+ The class must implement the
+ <code>org.apache.catalina.realm.X509UsernameRetriever</code>
+ interface. The default is to use the certificate's SubjectDN
+ as the username.</p>
+ </attribute>
</attributes>
<p>See the <a href="../realm-howto.html#DataSourceRealm">
@@ -575,6 +591,14 @@
expression.</p>
</attribute>
+ <attribute name="X509UsernameRetrieverClassName" required="false">
+ <p>When using X509 client certificates, this specifies the class name
+ that will be used to retrieve the user name from the certificate.
+ The class must implement the
+ <code>org.apache.catalina.realm.X509UsernameRetriever</code>
+ interface. The default is to use the certificate's SubjectDN
+ as the username.</p>
+ </attribute>
</attributes>
<p>See the <a href="../realm-howto.html">Container-Managed Security
Guide</a> for more
@@ -611,6 +635,14 @@
and role information.</p>
</attribute>
+ <attribute name="X509UsernameRetrieverClassName" required="false">
+ <p>When using X509 client certificates, this specifies the class name
+ that will be used to retrieve the user name from the certificate.
+ The class must implement the
+ <code>org.apache.catalina.realm.X509UsernameRetriever</code>
+ interface. The default is to use the certificate's SubjectDN
+ as the username.</p>
+ </attribute>
</attributes>
<p>See the
@@ -668,6 +700,14 @@
name. If not specified, the default is <code>true</code>.</p>
</attribute>
+ <attribute name="X509UsernameRetrieverClassName" required="false">
+ <p>When using X509 client certificates, this specifies the class name
+ that will be used to retrieve the user name from the certificate.
+ The class must implement the
+ <code>org.apache.catalina.realm.X509UsernameRetriever</code>
+ interface. The default is to use the certificate's SubjectDN
+ as the username.</p>
+ </attribute>
</attributes>
<p>The XML document referenced by the <code>pathname</code> attribute must
@@ -765,6 +805,14 @@
<code>false</code>.</p>
</attribute>
+ <attribute name="X509UsernameRetrieverClassName" required="false">
+ <p>When using X509 client certificates, this specifies the class name
+ that will be used to retrieve the user name from the certificate.
+ The class must implement the
+ <code>org.apache.catalina.realm.X509UsernameRetriever</code>
+ interface. The default is to use the certificate's SubjectDN
+ as the username.</p>
+ </attribute>
</attributes>
<p>See the <a href="../realm-howto.html">Container-Managed Security
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]