Author: kkolinko
Date: Sat Jun  2 21:06:49 2012
New Revision: 1345575

URL: http://svn.apache.org/viewvc?rev=1345575&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=52500
Add configurable mechanism to retrieve user names from X509 client certificates.
It is backport of r1298476 with clean-ups (r1298542, r1298577, r1298590, 
r1298592).

Note (a small difference wrt 7.0):
RealmBase.init() cannot throw a LifecycleException, so I am just logging an 
error
when there is configuration error with X509UsernameRetrieverClassName property.

Added:
    
tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/X509SubjectDnRetriever.java
      - copied, changed from r1345563, 
tomcat/trunk/java/org/apache/catalina/realm/X509SubjectDnRetriever.java
    
tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/X509UsernameRetriever.java
      - copied unchanged from r1345563, 
tomcat/trunk/java/org/apache/catalina/realm/X509UsernameRetriever.java
Modified:
    tomcat/tc6.0.x/trunk/STATUS.txt
    tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/LocalStrings.properties
    tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/RealmBase.java
    tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml
    tomcat/tc6.0.x/trunk/webapps/docs/config/realm.xml

Modified: tomcat/tc6.0.x/trunk/STATUS.txt
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/STATUS.txt?rev=1345575&r1=1345574&r2=1345575&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/STATUS.txt (original)
+++ tomcat/tc6.0.x/trunk/STATUS.txt Sat Jun  2 21:06:49 2012
@@ -79,19 +79,6 @@ PATCHES PROPOSED TO BACKPORT:
   -0: markt - https://issues.apache.org/bugzilla/show_bug.cgi?id=52579#c8
   -1: 
 
-* Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=52500
-  Add configurable mechanism to retrieve user names from X509 client 
certificates.
-  trunk patch: http://svn.apache.org/viewvc?view=revision&revision=r1298476
-  additional clean-up patches (good for markt?):
-     http://svn.apache.org/viewvc?view=revision&revision=r1298542
-     http://svn.apache.org/viewvc?view=revision&revision=r1298577
-     http://svn.apache.org/viewvc?view=revision&revision=r1298590
-     http://svn.apache.org/viewvc?view=revision&revision=r1298592
-  +1: schultz, fhanik
-  +1: markt if clean-up is also applied
-  +1: kkolinko: with clean-ups (r1298542, r1298577, r1298590, r1298592)
-  -1:
-
 * Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=52723
   Correct theoretical resource leak in StandardManager
   http://svn.apache.org/viewvc?rev=1299036&view=rev

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/LocalStrings.properties?rev=1345575&r1=1345574&r2=1345575&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/LocalStrings.properties 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/LocalStrings.properties 
Sat Jun  2 21:06:49 2012
@@ -75,6 +75,11 @@ realmBase.notAuthenticated=Configuration
 realmBase.notStarted=This Realm has not yet been started
 realmBase.authenticateFailure=Username {0} NOT successfully authenticated
 realmBase.authenticateSuccess=Username {0} successfully authenticated
+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.authenticateError=Login configuration error authenticating 
username {0}
 userDatabaseRealm.lookup=Exception looking up UserDatabase under key {0}
 userDatabaseRealm.noDatabase=No UserDatabase component found under key {0}

Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/RealmBase.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/RealmBase.java?rev=1345575&r1=1345574&r2=1345575&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/RealmBase.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/RealmBase.java Sat Jun  
2 21:06:49 2012
@@ -154,7 +154,17 @@ public abstract class RealmBase
      */
     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.
      */
@@ -278,6 +288,28 @@ public abstract class RealmBase
 
     }
 
+    /**
+     * 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
+     * X509UsernameRetriever.
+     *
+     * @param className The name of the class that will be used to extract 
user names
+     *                  from X509 client certificates.
+     * @see X509UsernameRetriever
+     */
+    public void setX509UsernameRetrieverClassName(String className) {
+        this.x509UsernameRetrieverClassName = className;
+    }
 
     // --------------------------------------------------------- Public Methods
 
@@ -1213,9 +1245,14 @@ public abstract class RealmBase
      * 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));
     }
-    
+
 
     /**
      * Return the Principal associated with the given user name.
@@ -1359,7 +1396,14 @@ public abstract class RealmBase
         if (container != null) {
             this.containerLog = container.getLogger();
         }
-        
+
+        try {
+            x509UsernameRetriever =
+                    createUsernameRetriever(x509UsernameRetrieverClassName);
+        } catch (LifecycleException ex) {
+            log.error(ex.getMessage(), ex);
+        }
+
         initialized=true;
         if( container== null ) {
             ObjectName parent=null;
@@ -1460,4 +1504,23 @@ public abstract class RealmBase
         }
     }
 
+    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 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);
+        }
+    }
 }

Copied: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/X509SubjectDnRetriever.java 
(from r1345563, 
tomcat/trunk/java/org/apache/catalina/realm/X509SubjectDnRetriever.java)
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/X509SubjectDnRetriever.java?p2=tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/X509SubjectDnRetriever.java&p1=tomcat/trunk/java/org/apache/catalina/realm/X509SubjectDnRetriever.java&r1=1345563&r2=1345575&rev=1345575&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/realm/X509SubjectDnRetriever.java 
(original)
+++ 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/X509SubjectDnRetriever.java 
Sat Jun  2 21:06:49 2012
@@ -24,7 +24,6 @@ import java.security.cert.X509Certificat
  */
 public class X509SubjectDnRetriever implements X509UsernameRetriever {
 
-    @Override
     public String getUsername(X509Certificate clientCert) {
         return clientCert.getSubjectDN().getName();
     }

Modified: tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml?rev=1345575&r1=1345574&r2=1345575&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Sat Jun  2 21:06:49 2012
@@ -109,6 +109,11 @@
         <code>org.apache.catalina.filters</code> package so that it is
         available for all web applications. (kkolinko)
       </add>
+      <add>
+        <bug>52500</bug>: Added configurable mechanism to retrieve user names
+        from X509 client certificates. Based on a patch provided by
+        Michael Furman. (schultz/kkolinko)
+      </add>
       <fix>
         <bug>52719</bug>: Fix a theoretical resource leak in the JAR validation
         that checks for non-permitted classes in web application JARs. (markt)

Modified: tomcat/tc6.0.x/trunk/webapps/docs/config/realm.xml
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/config/realm.xml?rev=1345575&r1=1345574&r2=1345575&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/webapps/docs/config/realm.xml (original)
+++ tomcat/tc6.0.x/trunk/webapps/docs/config/realm.xml Sat Jun  2 21:06:49 2012
@@ -182,6 +182,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
@@ -276,6 +284,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">
@@ -518,6 +534,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
@@ -554,6 +578,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
@@ -605,6 +637,14 @@
         default value is <code>conf/tomcat-users.xml</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
@@ -696,6 +736,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: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to