You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2008/08/14 00:50:41 UTC

svn commit: r685720 - in /tomcat/tc6.0.x/trunk: ./ STATUS.txt java/org/apache/catalina/realm/JAASCallbackHandler.java java/org/apache/catalina/realm/JAASMemoryLoginModule.java java/org/apache/catalina/realm/JAASRealm.java webapps/docs/changelog.xml

Author: markt
Date: Wed Aug 13 15:50:40 2008
New Revision: 685720

URL: http://svn.apache.org/viewvc?rev=685720&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=45576
Add support for DIGEST to the JAASRealm

Modified:
    tomcat/tc6.0.x/trunk/   (props changed)
    tomcat/tc6.0.x/trunk/STATUS.txt
    tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/JAASCallbackHandler.java
    tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/JAASMemoryLoginModule.java
    tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/JAASRealm.java
    tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml

Propchange: tomcat/tc6.0.x/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Aug 13 15:50:40 2008
@@ -1 +1 @@
-/tomcat/trunk:673796,673820,683982,684001,684081
+/tomcat/trunk:673796,673820,683982,684001,684081,684234

Modified: tomcat/tc6.0.x/trunk/STATUS.txt
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/STATUS.txt?rev=685720&r1=685719&r2=685720&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/STATUS.txt (original)
+++ tomcat/tc6.0.x/trunk/STATUS.txt Wed Aug 13 15:50:40 2008
@@ -71,12 +71,6 @@
    0: remm (looks risky, very minor problem)
   -1: 
 
-* Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=45576
-  Add support for DIGEST to the JAASRealm
-  http://svn.apache.org/viewvc?rev=684234&view=rev
-  +1: markt, funkman, remm (the two people using digest could be interested)
-  -1: 
-
 * Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=41407
   Add support for CLIENT-CERT to the JASSRealm. Builds on DIGEST patch above.
   http://svn.apache.org/viewvc?rev=684270&view=rev

Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/JAASCallbackHandler.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/JAASCallbackHandler.java?rev=685720&r1=685719&r2=685720&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/JAASCallbackHandler.java (original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/JAASCallbackHandler.java Wed Aug 13 15:50:40 2008
@@ -24,6 +24,7 @@
 import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.callback.NameCallback;
 import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextInputCallback;
 import javax.security.auth.callback.UnsupportedCallbackException;
 
 import org.apache.catalina.util.StringManager;
@@ -75,6 +76,33 @@
         }
     }
 
+    
+    /**
+     * Construct a callback handler for DIGEST authentication.
+     *
+     * @param realm     Our associated JAASRealm instance
+     * @param username  Username to be authenticated with
+     * @param password  Password to be authenticated with
+     * @param nonce     Server generated nonce
+     * @param nc        Nonce count
+     * @param cnonce    Client generated nonce
+     * @param qop       Quality of protection aplied to the message
+     * @param realmName Realm name
+     * @param md5a2     Second MD5 digest used to calculate the digest
+     *                      MD5(Method + ":" + uri)
+     */
+    public JAASCallbackHandler(JAASRealm realm, String username,
+                               String password, String nonce, String nc,
+                               String cnonce, String qop, String realmName,
+                               String md5a2) {
+        this(realm, username, password);
+        this.nonce = nonce;
+        this.nc = nc;
+        this.cnonce = cnonce;
+        this.qop = qop;
+        this.realmName = realmName;
+        this.md5a2 = md5a2;
+    }
 
     // ----------------------------------------------------- Instance Variables
 
@@ -101,14 +129,46 @@
      */
     protected String username = null;
 
+    /**
+     * Server generated nonce.
+     */
+    protected String nonce = null;
+    
+    /**
+     * Nonce count.
+     */
+    protected String nc = null;
+    
+    /**
+     * Client generated nonce.
+     */
+    protected String cnonce = null;
+
+    /**
+     * Quality of protection aplied to the message.
+     */
+    protected String qop;
+
+    /**
+     * Realm name.
+     */
+    protected String realmName;
+
+    /**
+     * Second MD5 digest.
+     */
+    protected String md5a2;
+
 
     // --------------------------------------------------------- Public Methods
 
 
     /**
      * Retrieve the information requested in the provided <code>Callbacks</code>.
-     * This implementation only recognizes <code>NameCallback</code> and
-     * <code>PasswordCallback</code> instances.
+     * This implementation only recognizes {@link NameCallback},
+     * {@link PasswordCallback} and {@link TextInputCallback}.
+     * {@link TextInputCallback} is ued to pass the various additional
+     * parameters required for DIGEST authentication. 
      *
      * @param callbacks The set of <code>Callback</code>s to be processed
      *
@@ -134,6 +194,23 @@
                 }
                 ((PasswordCallback) callbacks[i]).setPassword
                     (passwordcontents);
+            } else if (callbacks[i] instanceof TextInputCallback) {
+                TextInputCallback cb = ((TextInputCallback) callbacks[i]);
+                if (cb.getPrompt().equals("nonce")) {
+                    cb.setText(nonce);
+                } else if (cb.getPrompt().equals("nc")) {
+                    cb.setText(nc);
+                } else if (cb.getPrompt().equals("cnonce")) {
+                    cb.setText(cnonce);
+                } else if (cb.getPrompt().equals("qop")) {
+                    cb.setText(qop);
+                } else if (cb.getPrompt().equals("realmName")) {
+                    cb.setText(realmName);
+                } else if (cb.getPrompt().equals("md5a2")) {
+                    cb.setText(md5a2);
+                } else {
+                    throw new UnsupportedCallbackException(callbacks[i]);
+                }
             } else {
                 throw new UnsupportedCallbackException(callbacks[i]);
             }

Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/JAASMemoryLoginModule.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/JAASMemoryLoginModule.java?rev=685720&r1=685719&r2=685720&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/JAASMemoryLoginModule.java (original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/JAASMemoryLoginModule.java Wed Aug 13 15:50:40 2008
@@ -31,6 +31,7 @@
 import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.callback.NameCallback;
 import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextInputCallback;
 import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.security.auth.login.FailedLoginException;
 import javax.security.auth.login.LoginException;
@@ -309,18 +310,37 @@
         // Set up our CallbackHandler requests
         if (callbackHandler == null)
             throw new LoginException("No CallbackHandler specified");
-        Callback callbacks[] = new Callback[2];
+        Callback callbacks[] = new Callback[8];
         callbacks[0] = new NameCallback("Username: ");
         callbacks[1] = new PasswordCallback("Password: ", false);
+        callbacks[2] = new TextInputCallback("nonce");
+        callbacks[3] = new TextInputCallback("nc");
+        callbacks[4] = new TextInputCallback("cnonce");
+        callbacks[5] = new TextInputCallback("qop");
+        callbacks[6] = new TextInputCallback("realmName");
+        callbacks[7] = new TextInputCallback("md5a2");
 
         // Interact with the user to retrieve the username and password
         String username = null;
         String password = null;
+        String nonce = null;
+        String nc = null;
+        String cnonce = null;
+        String qop = null;
+        String realmName = null;
+        String md5a2 = null;
+
         try {
             callbackHandler.handle(callbacks);
             username = ((NameCallback) callbacks[0]).getName();
             password =
                 new String(((PasswordCallback) callbacks[1]).getPassword());
+            nonce = ((TextInputCallback) callbacks[2]).getText();
+            nc = ((TextInputCallback) callbacks[3]).getText();
+            cnonce = ((TextInputCallback) callbacks[4]).getText();
+            qop = ((TextInputCallback) callbacks[5]).getText();
+            realmName = ((TextInputCallback) callbacks[6]).getText();
+            md5a2 = ((TextInputCallback) callbacks[7]).getText();
         } catch (IOException e) {
             throw new LoginException(e.toString());
         } catch (UnsupportedCallbackException e) {
@@ -328,7 +348,14 @@
         }
 
         // Validate the username and password we have received
-        principal = super.authenticate(username, password);
+        if (md5a2 == null) {
+            // Not using DIGEST
+            principal = super.authenticate(username, password);
+        } else {
+            // Must be using DIGEST
+            principal = super.authenticate(username, password, nonce, nc,
+                    cnonce, qop, realmName, md5a2);
+        }
 
         log.debug("login " + username + " " + principal);
 

Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/JAASRealm.java
URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/JAASRealm.java?rev=685720&r1=685719&r2=685720&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/JAASRealm.java (original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/realm/JAASRealm.java Wed Aug 13 15:50:40 2008
@@ -25,6 +25,7 @@
 import java.util.List;
 
 import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.login.AccountExpiredException;
 import javax.security.auth.login.CredentialExpiredException;
 import javax.security.auth.login.FailedLoginException;
@@ -310,19 +311,53 @@
 
 
     /**
-     * Return the <code>Principal</code> associated with the specified username and
-     * credentials, if there is one; otherwise return <code>null</code>.
-     *
-     * If there are any errors with the JDBC connection, executing
-     * the query or anything we return null (don't authenticate). This
-     * event is also logged, and the connection will be closed so that
-     * a subsequent request will automatically re-open it.
+     * Return the <code>Principal</code> associated with the specified username
+     * and credentials, if there is one; otherwise return <code>null</code>.
      *
      * @param username Username of the <code>Principal</code> to look up
      * @param credentials Password or other credentials to use in
      *  authenticating this username
      */
     public Principal authenticate(String username, String credentials) {
+        return authenticate(username,
+                new JAASCallbackHandler(this, username, credentials));
+    }
+     
+
+    /**
+     * Return the <code>Principal</code> associated with the specified username
+     * and digest, if there is one; otherwise return <code>null</code>.
+     *
+     * @param username      Username of the <code>Principal</code> to look up
+     * @param clientDigest  Digest to use in authenticating this username
+     * @param nonce         Server generated nonce
+     * @param nc            Nonce count
+     * @param cnonce        Client generated nonce
+     * @param qop           Quality of protection aplied to the message
+     * @param realmName     Realm name
+     * @param md5a2         Second MD5 digest used to calculate the digest
+     *                          MD5(Method + ":" + uri)
+     */
+    public Principal authenticate(String username, String clientDigest,
+            String nonce, String nc, String cnonce, String qop,
+            String realmName, String md5a2) {
+        return authenticate(username,
+                new JAASCallbackHandler(this, username, clientDigest, nonce,
+                        nc, cnonce, qop, realmName, md5a2));
+    }
+
+
+    // -------------------------------------------------------- Package Methods
+
+
+    // ------------------------------------------------------ Protected Methods
+
+
+    /**
+     * Perform the actual JAAS authentication
+     */
+    protected Principal authenticate(String username,
+            CallbackHandler callbackHandler) {
 
         // Establish a LoginContext to use for authentication
         try {
@@ -342,9 +377,7 @@
         }
 
         try {
-            loginContext = new LoginContext
-                (appName, new JAASCallbackHandler(this, username,
-                                                  credentials));
+            loginContext = new LoginContext(appName, callbackHandler);
         } catch (Throwable e) {
             log.error(sm.getString("jaasRealm.unexpectedError"), e);
             return (null);
@@ -406,13 +439,6 @@
             return null;
         }
     }
-     
-
-    // -------------------------------------------------------- Package Methods
-
-
-    // ------------------------------------------------------ Protected Methods
-
 
     /**
      * Return a short name for this <code>Realm</code> implementation.
@@ -425,7 +451,9 @@
 
 
     /**
-     * Return the password associated with the given principal's user name.
+     * Return the password associated with the given principal's user name. This
+     * always returns null as the JAASRealm has no way of obtaining this
+     * information.
      */
     protected String getPassword(String username) {
 

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=685720&r1=685719&r2=685720&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Wed Aug 13 15:50:40 2008
@@ -39,6 +39,9 @@
         <bug>45453</bug>: Remove potential race condition in JDBC Realm.
         Based on a patch by Santtu Hyrkk. (markt)
       </fix>
+      <add>
+        <bug>45576</bug>: Add DIGEST support to the JAAS Realm. (markt)
+      </add>
       <fix>
         <bug>45585</bug>: Allow Tomcat to start if using
         <code>$CATALINA_BASE</code> but not JULI. Patch based on a suggestion by



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org