You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by sc...@apache.org on 2012/03/08 18:34:53 UTC

svn commit: r1298479 - in /tomcat/tc7.0.x/trunk: java/org/apache/catalina/realm/ webapps/docs/ webapps/docs/config/

Author: schultz
Date: Thu Mar  8 17:34:53 2012
New Revision: 1298479

URL: http://svn.apache.org/viewvc?rev=1298479&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/tc7.0.x/trunk/java/org/apache/catalina/realm/X509SubjectDnRetriever.java
      - copied unchanged from r1298476, tomcat/trunk/java/org/apache/catalina/realm/X509SubjectDnRetriever.java
    tomcat/tc7.0.x/trunk/java/org/apache/catalina/realm/X509UsernameRetriever.java
      - copied unchanged from r1298476, tomcat/trunk/java/org/apache/catalina/realm/X509UsernameRetriever.java
Modified:
    tomcat/tc7.0.x/trunk/java/org/apache/catalina/realm/LocalStrings.properties
    tomcat/tc7.0.x/trunk/java/org/apache/catalina/realm/RealmBase.java
    tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml
    tomcat/tc7.0.x/trunk/webapps/docs/config/realm.xml

Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/realm/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/realm/LocalStrings.properties?rev=1298479&r1=1298478&r2=1298479&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/realm/LocalStrings.properties (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/realm/LocalStrings.properties Thu Mar  8 17:34:53 2012
@@ -76,6 +76,11 @@ realmBase.authenticateFailure=Username {
 realmBase.authenticateSuccess=Username {0} successfully authenticated
 realmBase.gssNameFail=Failed to extract name from established GSSContext
 userDatabaseRealm.authenticateError=Login configuration error authenticating username {0}
+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}
 userDatabaseRealm.noEngine=No Engine component found in container hierarchy

Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/realm/RealmBase.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/realm/RealmBase.java?rev=1298479&r1=1298478&r2=1298479&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/realm/RealmBase.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/realm/RealmBase.java Thu Mar  8 17:34:53 2012
@@ -148,6 +148,11 @@ public abstract class RealmBase extends 
 
     
     /**
+     * The object that will extract user names from X509 client certificates.
+     */
+    protected X509UsernameRetriever x509UsernameRetriever;
+
+    /**
      * The all role mode.
      */
     protected AllRolesMode allRolesMode = AllRolesMode.STRICT_MODE;
@@ -288,6 +293,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;
@@ -1056,6 +1084,8 @@ public abstract class RealmBase extends 
         if (container != null) {
             this.containerLog = container.getLogger();
         }
+        
+        x509UsernameRetriever = createUsernameRetriever(x509UsernameRetrieverClassName);
     }
         
     /**
@@ -1213,7 +1243,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));
     }
     
 
@@ -1413,4 +1448,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);
+        }
+    }
 }

Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1298479&r1=1298478&r2=1298479&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Thu Mar  8 17:34:53 2012
@@ -68,6 +68,11 @@
         during an asynchronous request on a container thread. (markt)
       </fix>
       <fix>
+        <bug>52500</bug>: Added configurable mechanism to retrieve user names
+        from X509 client certificates. Based on a patch provided by
+        Michael Furman. (schultz)
+      </fix>fix>
+      <fix>
         <bug>52719</bug>: Fix a theoretical resource leak in the JAR validation
         that checks for non-permitted classes in web application JARs. (markt)
       </fix>

Modified: tomcat/tc7.0.x/trunk/webapps/docs/config/realm.xml
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/config/realm.xml?rev=1298479&r1=1298478&r2=1298479&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/config/realm.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/config/realm.xml Thu Mar  8 17:34:53 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: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org