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'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'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' 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