Author: markt
Date: Thu Mar 31 19:33:04 2011
New Revision: 1087416

URL: http://svn.apache.org/viewvc?rev=1087416&view=rev
Log:
SPNEGO support part 2
Expose the users delegated credentials through a request attribute so 
applications can make use of it

Modified:
    tomcat/trunk/java/org/apache/catalina/Globals.java
    tomcat/trunk/java/org/apache/catalina/Realm.java
    tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java
    tomcat/trunk/java/org/apache/catalina/connector/Request.java
    tomcat/trunk/java/org/apache/catalina/realm/CombinedRealm.java
    tomcat/trunk/java/org/apache/catalina/realm/GenericPrincipal.java
    tomcat/trunk/java/org/apache/catalina/realm/LocalStrings.properties
    tomcat/trunk/java/org/apache/catalina/realm/LockOutRealm.java
    tomcat/trunk/java/org/apache/catalina/realm/RealmBase.java
    tomcat/trunk/java/org/apache/catalina/session/StandardSession.java
    tomcat/trunk/webapps/docs/config/valve.xml

Modified: tomcat/trunk/java/org/apache/catalina/Globals.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Globals.java?rev=1087416&r1=1087415&r2=1087416&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/Globals.java (original)
+++ tomcat/trunk/java/org/apache/catalina/Globals.java Thu Mar 31 19:33:04 2011
@@ -151,6 +151,10 @@ public final class Globals {
         "javax.security.auth.subject";
 
     
+    public static final String GSS_CREDENTIAL_ATTR =
+        "org.apache.catalina.realm.GSS_CREDENTIAL";
+
+
     /**
      * The master flag which controls strict servlet specification 
      * compliance.

Modified: tomcat/trunk/java/org/apache/catalina/Realm.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Realm.java?rev=1087416&r1=1087415&r2=1087416&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/Realm.java (original)
+++ tomcat/trunk/java/org/apache/catalina/Realm.java Thu Mar 31 19:33:04 2011
@@ -111,9 +111,11 @@ public interface Realm {
      * Return the Principal associated with the specified chain of X509
      * client certificates.  If there is none, return <code>null</code>.
      *
-     * @param certs The gssContext processed by the {@link Authenticator}.
+     * @param gssContext The gssContext processed by the {@link Authenticator}.
+     * @param storeCreds Should the realm attempt to store the delegated
+     *                   credentials in the returned Principal?
      */
-    public Principal authenticate(GSSContext gssContext);
+    public Principal authenticate(GSSContext gssContext, boolean storeCreds);
     
     
     /**

Modified: 
tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java?rev=1087416&r1=1087415&r2=1087416&view=diff
==============================================================================
--- 
tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java 
(original)
+++ 
tomcat/trunk/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java 
Thu Mar 31 19:33:04 2011
@@ -77,6 +77,15 @@ public class SpnegoAuthenticator extends
         this.loginConfigName = loginConfigName;
     }
 
+    private boolean storeDelegatedCredentials = true;
+    public boolean isStoreDelegatedCredentials() {
+        return storeDelegatedCredentials;
+    }
+    public void setStoreDelegatedCredentials(
+            boolean storeDelegatedCredentials) {
+        this.storeDelegatedCredentials = storeDelegatedCredentials;
+    }
+
 
     @Override
     protected String getAuthMethod() {
@@ -229,7 +238,8 @@ public class SpnegoAuthenticator extends
                 return false;
             }
 
-            principal = context.getRealm().authenticate(gssContext);
+            principal = context.getRealm().authenticate(gssContext,
+                    storeDelegatedCredentials);
         } catch (GSSException e) {
             if (log.isDebugEnabled()) {
                 
log.debug(sm.getString("spnegoAuthenticator.ticketValidateFail",

Modified: tomcat/trunk/java/org/apache/catalina/connector/Request.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/Request.java?rev=1087416&r1=1087415&r2=1087416&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/Request.java (original)
+++ tomcat/trunk/java/org/apache/catalina/connector/Request.java Thu Mar 31 
19:33:04 2011
@@ -923,6 +923,13 @@ public class Request
             return asyncSupported;
         }
 
+        if (name.equals(Globals.GSS_CREDENTIAL_ATTR)) {
+            if (userPrincipal instanceof GenericPrincipal) {
+                return ((GenericPrincipal) userPrincipal).getGssCredential();
+            }
+            return null;
+        }
+
         Object attr=attributes.get(name);
 
         if(attr!=null)

Modified: tomcat/trunk/java/org/apache/catalina/realm/CombinedRealm.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/realm/CombinedRealm.java?rev=1087416&r1=1087415&r2=1087416&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/realm/CombinedRealm.java (original)
+++ tomcat/trunk/java/org/apache/catalina/realm/CombinedRealm.java Thu Mar 31 
19:33:04 2011
@@ -271,7 +271,7 @@ public class CombinedRealm extends Realm
      * {@inheritDoc}
      */
     @Override
-    public Principal authenticate(GSSContext gssContext) {
+    public Principal authenticate(GSSContext gssContext, boolean storeCreds) {
         if (gssContext.isEstablished()) {
             Principal authenticatedUser = null;
             String username = null;
@@ -292,7 +292,7 @@ public class CombinedRealm extends Realm
                             username, realm.getInfo()));
                 }
 
-                authenticatedUser = realm.authenticate(gssContext);
+                authenticatedUser = realm.authenticate(gssContext, storeCreds);
 
                 if (authenticatedUser == null) {
                     if (log.isDebugEnabled()) {

Modified: tomcat/trunk/java/org/apache/catalina/realm/GenericPrincipal.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/realm/GenericPrincipal.java?rev=1087416&r1=1087415&r2=1087416&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/realm/GenericPrincipal.java (original)
+++ tomcat/trunk/java/org/apache/catalina/realm/GenericPrincipal.java Thu Mar 
31 19:33:04 2011
@@ -25,6 +25,8 @@ import java.util.List;
 
 import javax.security.auth.login.LoginContext;
 
+import org.ietf.jgss.GSSCredential;
+
 
 /**
  * Generic implementation of <strong>java.security.Principal</strong> that
@@ -98,6 +100,26 @@ public class GenericPrincipal implements
      */
     public GenericPrincipal(String name, String password, List<String> roles,
             Principal userPrincipal, LoginContext loginContext) {
+        this(name, password, roles, userPrincipal, loginContext, null);
+    }
+    
+    /**
+     * Construct a new Principal, associated with the specified Realm, for the
+     * specified username and password, with the specified role names
+     * (as Strings).
+     *
+     * @param name The username of the user represented by this Principal
+     * @param password Credentials used to authenticate this user
+     * @param roles List of roles (must be Strings) possessed by this user
+     * @param userPrincipal - the principal to be returned from the request 
+     *        getUserPrincipal call if not null; if null, this will be returned
+     * @param loginContext  - If provided, this will be used to log out the 
user
+     *        at the appropriate time
+     * @param gssCredential - If provided, the user&apos;s delegated 
credentials
+     */
+    public GenericPrincipal(String name, String password, List<String> roles,
+            Principal userPrincipal, LoginContext loginContext,
+            GSSCredential gssCredential) {
         super();
         this.name = name;
         this.password = password;
@@ -109,6 +131,7 @@ public class GenericPrincipal implements
                 Arrays.sort(this.roles);
         }
         this.loginContext = loginContext;
+        this.gssCredential = gssCredential;
     }
 
 
@@ -167,6 +190,19 @@ public class GenericPrincipal implements
      */
     protected LoginContext loginContext = null;
 
+
+    /**
+     * The user&apos;s delegated credentials.
+     */
+    protected GSSCredential gssCredential = null;
+
+    public GSSCredential getGssCredential() {
+        return this.gssCredential;
+    }
+    protected void setGssCredential(GSSCredential gssCredential) {
+        this.gssCredential = gssCredential;
+    }
+
     // --------------------------------------------------------- Public Methods
 
 

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=1087416&r1=1087415&r2=1087416&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/realm/LocalStrings.properties 
(original)
+++ tomcat/trunk/java/org/apache/catalina/realm/LocalStrings.properties Thu Mar 
31 19:33:04 2011
@@ -65,6 +65,7 @@ memoryRealm.readXml=Exception while read
 memoryRealm.xmlFeatureEncoding=Exception configuring digester to permit java 
encoding names in XML files. Only IANA encoding names will be supported.
 realmBase.algorithm=Invalid message digest algorithm {0} specified
 realmBase.alreadyStarted=This Realm has already been started
+realmBase.delegatedCredentialFail=Unable to obtain delegated credentials for 
user [{0}
 realmBase.digest=Error digesting user credentials
 realmBase.forbidden=Access to the requested resource has been denied
 realmBase.hasRoleFailure=Username {0} does NOT have role {1}

Modified: tomcat/trunk/java/org/apache/catalina/realm/LockOutRealm.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/realm/LockOutRealm.java?rev=1087416&r1=1087415&r2=1087416&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/realm/LockOutRealm.java (original)
+++ tomcat/trunk/java/org/apache/catalina/realm/LockOutRealm.java Thu Mar 31 
19:33:04 2011
@@ -225,7 +225,7 @@ public class LockOutRealm extends Combin
      * {@inheritDoc}
      */
     @Override
-    public Principal authenticate(GSSContext gssContext) {
+    public Principal authenticate(GSSContext gssContext, boolean storeCreds) {
         if (gssContext.isEstablished()) {
             String username = null;
             GSSName name = null;
@@ -246,7 +246,8 @@ public class LockOutRealm extends Combin
                 return null;
             }
 
-            Principal authenticatedUser = super.authenticate(gssContext);
+            Principal authenticatedUser =
+                    super.authenticate(gssContext, storeCreds);
             
             if (authenticatedUser == null) {
                 registerAuthFailure(username);

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=1087416&r1=1087415&r2=1087416&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/realm/RealmBase.java (original)
+++ tomcat/trunk/java/org/apache/catalina/realm/RealmBase.java Thu Mar 31 
19:33:04 2011
@@ -55,6 +55,7 @@ import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.res.StringManager;
 import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSCredential;
 import org.ietf.jgss.GSSException;
 import org.ietf.jgss.GSSName;
 
@@ -424,7 +425,7 @@ public abstract class RealmBase extends 
      * {@inheritDoc}
      */
     @Override
-    public Principal authenticate(GSSContext gssContext) {
+    public Principal authenticate(GSSContext gssContext, boolean storeCred) {
         if (gssContext.isEstablished()) {
             GSSName name = null;
             try {
@@ -434,7 +435,20 @@ public abstract class RealmBase extends 
             }
             
             if (name!= null) {
-                return getPrincipal(name.toString());
+                GSSCredential gssCredential = null;
+                if (storeCred && gssContext.getCredDelegState()) {
+                    try {
+                        gssCredential = gssContext.getDelegCred();
+                    } catch (GSSException e) {
+                        e.printStackTrace();
+                        if (log.isDebugEnabled()) {
+                            log.debug(sm.getString(
+                                    "realmBase.delegatedCredentialFail", name),
+                                    e);
+                        }
+                    }
+                }
+                return getPrincipal(name.toString(), gssCredential);
             }
         }
         
@@ -785,7 +799,7 @@ public abstract class RealmBase extends 
             if (roles.length == 0 && !constraint.getAllRoles()) {
                 if(constraint.getAuthConstraint()) {
                     if( log.isDebugEnabled() )
-                        log.debug("No roles ");
+                        log.debug("No role)s ");
                     status = false; // No listed roles means no access at all
                     denyfromall = true;
                     break;
@@ -1181,6 +1195,17 @@ public abstract class RealmBase extends 
     protected abstract Principal getPrincipal(String username);
 
 
+    protected Principal getPrincipal(String username,
+            GSSCredential gssCredential) {
+        Principal p = getPrincipal(username);
+        
+        if (p instanceof GenericPrincipal) {
+            ((GenericPrincipal) p).setGssCredential(gssCredential);
+        }
+        
+        return p;
+    }
+
     /**
      * Return the Server object that is the ultimate parent for the container
      * with which this Realm is associated. If the server cannot be found (eg

Modified: tomcat/trunk/java/org/apache/catalina/session/StandardSession.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/session/StandardSession.java?rev=1087416&r1=1087415&r2=1087416&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/session/StandardSession.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/session/StandardSession.java Thu Mar 
31 19:33:04 2011
@@ -176,7 +176,8 @@ public class StandardSession implements 
      * Set of attribute names which are not allowed to be persisted.
      */
     protected static final String[] excludedAttributes = {
-        Globals.SUBJECT_ATTR
+        Globals.SUBJECT_ATTR,
+        Globals.GSS_CREDENTIAL_ATTR
     };
 
 

Modified: tomcat/trunk/webapps/docs/config/valve.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/valve.xml?rev=1087416&r1=1087415&r2=1087416&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/valve.xml (original)
+++ tomcat/trunk/webapps/docs/config/valve.xml Thu Mar 31 19:33:04 2011
@@ -891,6 +891,15 @@
         specified, the platform default provider will be used.</p>
       </attribute>
 
+      <attribute name="storeDelegatedCredentials" required="false">
+        <p>Controls if the user&apos; delegated credentials will be stored in
+        the user Principal. If available, the delegated credentials will be
+        available to applications (e.g. for onward authentication to external
+        services) via the <code>org.apache.catalina.realm.GSS_CREDENTIAL</code>
+        request attribute.If not set, the default value of <code>true</code>
+        will be used.</p>
+      </attribute>
+
     </attributes>
 
   </subsection>



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

Reply via email to