User: starksm 
  Date: 01/07/09 01:49:37

  Modified:    src/main/org/jboss/security/plugins Tag: Branch_2_4
                        JaasSecurityManager.java
  Log:
  Add support for authenticating anonymous users(username, password == null)
  at the UsernamePasswordLoginModule level and update JaasSecurityManager to
  provide a callerPrincipal for the case of a null principal.
  
  Revision  Changes    Path
  No                   revision
  
  
  No                   revision
  
  
  1.7.2.1   +472 -446  
jbosssx/src/main/org/jboss/security/plugins/JaasSecurityManager.java
  
  Index: JaasSecurityManager.java
  ===================================================================
  RCS file: 
/cvsroot/jboss/jbosssx/src/main/org/jboss/security/plugins/JaasSecurityManager.java,v
  retrieving revision 1.7
  retrieving revision 1.7.2.1
  diff -u -r1.7 -r1.7.2.1
  --- JaasSecurityManager.java  2001/06/15 08:26:02     1.7
  +++ JaasSecurityManager.java  2001/07/09 08:49:37     1.7.2.1
  @@ -1,446 +1,472 @@
  -/*
  - * JBoss, the OpenSource EJB server
  - *
  - * Distributable under LGPL license.
  - * See terms of license at gnu.org.
  - */
  -package org.jboss.security.plugins;
  -
  -import java.io.IOException;
  -import java.util.Arrays;
  -import java.util.Enumeration;
  -import java.util.Iterator;
  -import java.util.Set;
  -
  -import java.security.AccessController;
  -import java.security.Principal;
  -import java.security.acl.Group;
  -import javax.naming.InitialContext;
  -import javax.naming.NamingException;
  -import javax.security.auth.Policy;
  -import javax.security.auth.Subject;
  -import javax.security.auth.login.LoginContext;
  -import javax.security.auth.login.LoginException;
  -import javax.security.auth.callback.CallbackHandler;
  -import javax.security.auth.callback.Callback;
  -import javax.security.auth.callback.NameCallback;
  -import javax.security.auth.callback.PasswordCallback;
  -import javax.security.auth.callback.UnsupportedCallbackException;
  -
  -import org.jboss.security.AppPolicy;
  -import org.jboss.security.AuthenticationInfo;
  -import org.jboss.security.EJBSecurityManager;
  -import org.jboss.security.RealmMapping;
  -import org.jboss.security.SecurityAssociation;
  -import org.jboss.security.SecurityPolicy;
  -import org.jboss.security.SimplePrincipal;
  -import org.jboss.security.SubjectSecurityManager;
  -import org.jboss.security.auth.callback.SecurityAssociationHandler;
  -import org.jboss.util.CachePolicy;
  -import org.jboss.util.TimedCachePolicy;
  -
  -/** The JaasSecurityManager is responsible both for authenticating credentials
  -associated with principals and for role mapping. This implementation relies
  -on the JAAS LoginContext/LoginModules associated with the security
  -domain name associated with the class for authentication,
  -and the context JAAS Subject object for role mapping.
  -
  -@see #isValid(Principal, Object)
  -@see #Principal getPrincipal(Principal)
  -@see #doesUserHaveRole(Principal, Set)
  -
  -@author <a href="[EMAIL PROTECTED]">Oleg Nitz</a>
  -@author [EMAIL PROTECTED]
  -@version $Revision: 1.7 $
  -*/
  -public class JaasSecurityManager implements SubjectSecurityManager, RealmMapping
  -{
  -    /** The authentication cache object.
  -     */
  -    public static class DomainInfo
  -    {
  -        Subject subject;
  -        Object credential;
  -        Principal callerPrincipal;
  -        Group roles;
  -    }
  -
  -    /** The current authenticate()d subject.
  -     */
  -    private static ThreadLocal activeSubject = new ThreadLocal();
  -    /** The name of the domain this instance is securing. It is used as
  -        the appName into the SecurityPolicy.
  -     */
  -    private String securityDomain;
  -    /** A cache of DomainInfo objects keyd by Principal.
  -     */
  -    private CachePolicy domainCache;
  -    /** The custom JAAS policy. This may be null if a custom
  -        policy is not being used.
  -     */
  -    private SecurityPolicy securityPolicy;
  -    /** Used in the absence of a SecurityPolicy specific CallbackHandler
  -        to pass credential info to the LoginModule associated with the
  -        securityDomain name.
  -     */
  -    private SecurityAssociationHandler handler = new SecurityAssociationHandler();
  -
  -    /** Get the currently authenticated Subject in securityDomain.
  -    @return The Subject for securityDomain if one exists, false otherwise.
  -    */
  -    public static Subject getActiveSubject(String securityDomain)
  -    {
  -        Subject subject = null;
  -        try
  -        {
  -            InitialContext ctx = new InitialContext();
  -            String jsmName = "jaas:/"+securityDomain;
  -            JaasSecurityManager jsm = (JaasSecurityManager) ctx.lookup(jsmName);
  -            subject = jsm.getActiveSubject();
  -        }
  -        catch(NamingException e)
  -        {
  -        }
  -        return subject;
  -    }
  -    /** Create a LoginContext for the currently authenticated Subject in
  -     securityDomain.
  -    */
  -    public static LoginContext getActiveSubjectLoginContext(String securityDomain, 
CallbackHandler handler)
  -        throws LoginException
  -    {
  -        LoginContext lc = null;
  -        Subject subject = getActiveSubject(securityDomain);
  -        if( subject == null )
  -            throw new LoginException("No active subject found in securityDomain: 
"+securityDomain);
  -
  -        if( handler != null )
  -            lc = new LoginContext(securityDomain, subject, handler);
  -        else
  -            lc = new LoginContext(securityDomain, subject);
  -
  -        return lc;
  -    }
  -
  -    /** Creates a default JaasSecurityManager for with a securityDomain
  -     name of 'other'.
  -    */
  -    public JaasSecurityManager()
  -    {
  -        this("other");
  -    }
  -    /** Creates a JaasSecurityManager for with a securityDomain
  -     name of that given by the 'securityDomain' argument.
  -    @param securityDomain.
  -    */
  -    public JaasSecurityManager(String securityDomain)
  -    {
  -        this.securityDomain = securityDomain;
  -        try
  -        {   // Try to get the SecurityPolicy from the JAAS Policy class
  -            securityPolicy = (SecurityPolicy) Policy.getPolicy();
  -        }
  -        catch(ClassCastException e)
  -        {  // The installed Policy is not a SecurityPolicy
  -        }
  -    }
  -
  -    /** The domainCache is typically a shared object that is populated
  -        by the login code(LoginModule, etc.) and read by this class in the
  -        isValid() method.
  -    @see #isValid(Principal, Object)
  -    */
  -    public void setCachePolicy(CachePolicy domainCache)
  -    {
  -        this.domainCache = domainCache;
  -    }
  -
  -    public void flushCache()
  -    {
  -        if( domainCache != null )
  -            domainCache.flush();
  -    }
  -
  -    public void setSecurityPolicyName(String jndiName) throws NamingException
  -    {
  -        InitialContext ctx = new InitialContext();
  -        securityPolicy = (SecurityPolicy) ctx.lookup(jndiName);
  -    }
  -
  -    /** Get the name of the security domain associated with this security mgr.
  -        @return Name of the security manager security domain.
  -     */
  -    public String getSecurityDomain()
  -    {
  -        return securityDomain;
  -    }
  -    /** Get the currently authenticated Subject. This is a thread local
  -        property shared across all JaasSecurityManager instances.
  -        @return The Subject authenticated in the current thread if one
  -        exists, null otherwise.
  -     */
  -    public Subject getActiveSubject()
  -    {
  -        return (Subject) activeSubject.get();
  -    }
  -
  -    /** Validate that the given credential is correct for principal. This first
  -     will check the current CachePolicy object if one exists to see if the
  -     user's cached credentials match the given credential. If there is no
  -     credential cache or the cache information is invalid or does not match,
  -     the user is authenticated against the JAAS login modules configured for
  -     the security domain.
  -    @param principal, the security domain principal attempting access
  -    @param credential, the proof of identity offered by the principal
  -    @return true if the principal was authenticated, false otherwise.
  -     */
  -    public boolean isValid(Principal principal, Object credential)
  -    {
  -        // Check the cache first
  -        DomainInfo cacheInfo = null;
  -        if( domainCache != null )
  -            cacheInfo = (DomainInfo) domainCache.get(principal);
  -
  -        boolean isValid = false;
  -        if( cacheInfo != null )
  -            isValid = validateCache(cacheInfo, credential);
  -        if( isValid == false )
  -            isValid = authenticate(principal, credential);
  -        return isValid;
  -    }
  -
  -    /** Map the argument principal from the deployment environment principal
  -        to the developer environment. This is called by the EJB context
  -        getCallerPrincipal() to return the Principal as described by
  -        the EJB developer domain.
  -    @return a Principal object that is valid in the deployment environment
  -        if one exists. If no Subject exists or the Subject has no principals
  -        then the argument principal is returned.
  -     */
  -    public Principal getPrincipal(Principal principal)
  -    {
  -        Principal result = principal;
  -        if( domainCache != null )
  -        {
  -            // Get the CallerPrincipal group member
  -            DomainInfo info = (DomainInfo) domainCache.get(principal);
  -            if( info != null )
  -                result = info.callerPrincipal;
  -            // If the mapping did not have a callerPrincipal just use principal
  -            if( result == null )
  -                result = principal;  
  -        }
  -
  -        return result;
  -    }
  -
  -    /** Does the current Subject have a role(a Principal) that equates to one
  -        of the role names. This method obtains the Group named 'Roles' from
  -        the principal set of the currently authenticated Subject and then
  -        creates a SimplePrincipal for each name in roleNames. If the role is
  -        a member of the Roles group, then the user has the role.
  -    @param principal, ignored. The current authenticated Subject determines
  -        the active user and assigned user roles.
  -    @param rolePrincipals, a Set of Principals for the roles to check.
  -
  -    @see java.security.acl.Group;
  -    @see Subject#getPrincipals()
  -    */
  -    public boolean doesUserHaveRole(Principal principal, Set rolePrincipals)
  -    {
  -        boolean hasRole = false;
  -        Subject subject = getActiveSubject();
  -        if( subject != null )
  -        {
  -            DomainInfo info = null;
  -            if( domainCache != null )
  -                info = (DomainInfo) domainCache.get(principal);
  -
  -            Group roles = null;
  -            if( info != null )
  -                roles = info.roles;
  -            if( roles != null )
  -            {
  -                Iterator iter = rolePrincipals.iterator();
  -                while( hasRole == false && iter.hasNext() )
  -                {
  -                    Principal role = (Principal) iter.next();
  -                    hasRole = roles.isMember(role);
  -                }
  -            }
  -        }
  -        return hasRole;
  -    }
  -
  -    /** Validates operational environment Principal against the specified
  -        application domain role.
  -    @param principal, the caller principal as known in the operation environment.
  -    @param role, the application domain role that the principal is to be validated 
against.
  -    @return true if the principal has the role, false otherwise.
  -     */
  -    public boolean doesUserHaveRole(Principal principal, Principal role)
  -    {
  -        boolean hasRole = false;
  -        Subject subject = getActiveSubject();
  -        if( subject != null )
  -        {
  -            DomainInfo info = null;
  -            if( domainCache != null )
  -                info = (DomainInfo) domainCache.get(principal);
  -
  -            Group roles = null;
  -            if( info != null )
  -                roles = info.roles;
  -            if( roles != null )
  -            {
  -                hasRole = roles.isMember(role);
  -            }
  -        }
  -        return hasRole;
  -    }
  -
  -    /** Currently this simply calls defaultLogin() to do a JAAS login using the
  -     security domain name as the login module configuration name.
  -
  -     * @param principal, the user id to authenticate
  -     * @param credential, an opaque credential.
  -     * @return false on failure, true on success.
  -     */
  -    private boolean authenticate(Principal principal, Object credential)
  -    {
  -        LoginContext lc = null;
  -        Subject subject = null;
  -        boolean authenticated = false;
  -
  -        try
  -        {
  -            // Clear any current subject
  -            activeSubject.set(null);
  -            // Get the AppPolicy login info. Not implemented yet.
  -            AppPolicy policy = null;
  -            subject = defaultLogin(principal, credential);
  -
  -            // Set the current subject if login was successful
  -            if( subject != null )
  -            {
  -                activeSubject.set(subject);
  -                authenticated = true;
  -                // Build the Subject based DomainInfo cache value
  -                updateCache(subject, principal, credential);
  -            }
  -        }
  -        catch(LoginException e)
  -        {
  -            e.printStackTrace();
  -        }
  -
  -        return authenticated;
  -    }
  -
  -    /** Pass the security info to the login modules configured for
  -        this security domain using our SecurityAssociationHandler.
  -     @return The authenticated Subject if successful.
  -     @exception LoginException throw if login fails for any reason.
  -     */
  -    private Subject defaultLogin(Principal principal, Object credential)
  -        throws LoginException
  -    {
  -        // We use our internal CallbackHandler to provide the security info
  -        handler.setSecurityInfo(principal, credential);
  -        Subject subject = new Subject();
  -        LoginContext lc = new LoginContext(securityDomain, subject, handler);
  -        lc.login();
  -        return subject;
  -    }
  -
  -    /** Validate the cache credential value against the provided credential
  -     */
  -    private boolean validateCache(DomainInfo info, Object credential)
  -    {
  -        Object subjectCredential = info.credential;
  -        boolean isValid = false;
  -        if( subjectCredential.getClass().isAssignableFrom(credential.getClass()) == 
false )
  -            return false;
  -
  -        if( subjectCredential instanceof Comparable )
  -        {
  -            Comparable c = (Comparable) subjectCredential;
  -            isValid = c.compareTo(credential) == 0;
  -        }
  -        else if( subjectCredential instanceof char[] )
  -        {
  -            char[] a1 = (char[]) subjectCredential;
  -            char[] a2 = (char[]) credential;
  -            isValid = Arrays.equals(a1, a2);
  -        }
  -        else if( subjectCredential instanceof byte[] )
  -        {
  -            byte[] a1 = (byte[]) subjectCredential;
  -            byte[] a2 = (byte[]) credential;
  -            isValid = Arrays.equals(a1, a2);
  -        }
  -        else
  -        {
  -            isValid = subjectCredential.equals(credential);
  -        }
  -
  -        if( isValid )
  -        {
  -            activeSubject.set(info.subject);
  -        }
  -
  -        return isValid;
  -    }
  -
  -    private void updateCache(Subject subject, Principal principal, Object 
credential)
  -    {
  -        DomainInfo info = new DomainInfo();
  -        info.subject = subject;
  -        info.credential = credential;
  -
  -        /* If we don't have a cache policy create a default timed cache
  -         that has an 1800 sec lifetime, is thread-safe, and a resolution
  -         of 60 seconds.
  -         */
  -        if( domainCache == null )
  -        {
  -            domainCache = new TimedCachePolicy(1800, true, 60);
  -            try
  -            {
  -                domainCache.init();
  -                domainCache.start();
  -            }
  -            catch(Exception e)
  -            {
  -                e.printStackTrace();
  -            }
  -        }
  -
  -        /* Get the Subject callerPrincipal by looking for a Group called
  -           'CallerPrincipal' and roles by looking for a Group called 'Roles'
  -        */
  -        Set subjectGroups = subject.getPrincipals(Group.class);
  -        Iterator iter = subjectGroups.iterator();
  -        while( iter.hasNext() )
  -        {
  -            Group grp = (Group) iter.next();
  -            String name = grp.getName();
  -            if( name.equals("CallerPrincipal") )
  -            {
  -                Enumeration members = grp.members();
  -                if( members.hasMoreElements() )
  -                    info.callerPrincipal = (Principal) members.nextElement();
  -            }
  -            else if( name.equals("Roles") )
  -                info.roles = grp;
  -        }
  -
  -        /* If the user already exists another login is active. Currently
  -           only one is allowed so remove the old and insert the new.
  -        */
  -        if( domainCache.peek(principal) != null )
  -            domainCache.remove(principal);
  -        domainCache.insert(principal, info);
  -    }
  -
  -}
  +/*
  + * JBoss, the OpenSource EJB server
  + *
  + * Distributable under LGPL license.
  + * See terms of license at gnu.org.
  + */
  +package org.jboss.security.plugins;
  +
  +import java.io.IOException;
  +import java.util.Arrays;
  +import java.util.Enumeration;
  +import java.util.Iterator;
  +import java.util.Set;
  +
  +import java.security.AccessController;
  +import java.security.Principal;
  +import java.security.acl.Group;
  +import javax.naming.InitialContext;
  +import javax.naming.NamingException;
  +import javax.security.auth.Policy;
  +import javax.security.auth.Subject;
  +import javax.security.auth.login.LoginContext;
  +import javax.security.auth.login.LoginException;
  +import javax.security.auth.callback.CallbackHandler;
  +import javax.security.auth.callback.Callback;
  +import javax.security.auth.callback.NameCallback;
  +import javax.security.auth.callback.PasswordCallback;
  +import javax.security.auth.callback.UnsupportedCallbackException;
  +
  +import org.jboss.security.AppPolicy;
  +import org.jboss.security.AuthenticationInfo;
  +import org.jboss.security.EJBSecurityManager;
  +import org.jboss.security.RealmMapping;
  +import org.jboss.security.SecurityAssociation;
  +import org.jboss.security.SecurityPolicy;
  +import org.jboss.security.SimplePrincipal;
  +import org.jboss.security.SubjectSecurityManager;
  +import org.jboss.security.auth.callback.SecurityAssociationHandler;
  +import org.jboss.util.CachePolicy;
  +import org.jboss.util.TimedCachePolicy;
  +
  +/** The JaasSecurityManager is responsible both for authenticating credentials
  +associated with principals and for role mapping. This implementation relies
  +on the JAAS LoginContext/LoginModules associated with the security
  +domain name associated with the class for authentication,
  +and the context JAAS Subject object for role mapping.
  +
  +@see #isValid(Principal, Object)
  +@see #Principal getPrincipal(Principal)
  +@see #doesUserHaveRole(Principal, Set)
  +
  +@author <a href="[EMAIL PROTECTED]">Oleg Nitz</a>
  +@author [EMAIL PROTECTED]
  +@version $Revision: 1.7.2.1 $
  +*/
  +public class JaasSecurityManager implements SubjectSecurityManager, RealmMapping
  +{
  +    /** The authentication cache object.
  +     */
  +    public static class DomainInfo
  +    {
  +        Subject subject;
  +        Object credential;
  +        Principal callerPrincipal;
  +        Group roles;
  +    }
  +
  +    /** The current authenticate()d subject.
  +     */
  +    private static ThreadLocal activeSubject = new ThreadLocal();
  +    /** The name of the domain this instance is securing. It is used as
  +        the appName into the SecurityPolicy.
  +     */
  +    private String securityDomain;
  +    /** A cache of DomainInfo objects keyd by Principal.
  +     */
  +    private CachePolicy domainCache;
  +    /** The custom JAAS policy. This may be null if a custom
  +        policy is not being used.
  +     */
  +    private SecurityPolicy securityPolicy;
  +    /** Used in the absence of a SecurityPolicy specific CallbackHandler
  +        to pass credential info to the LoginModule associated with the
  +        securityDomain name.
  +     */
  +    private SecurityAssociationHandler handler = new SecurityAssociationHandler();
  +
  +    /** Get the currently authenticated Subject in securityDomain.
  +    @return The Subject for securityDomain if one exists, false otherwise.
  +    */
  +    public static Subject getActiveSubject(String securityDomain)
  +    {
  +        Subject subject = null;
  +        try
  +        {
  +            InitialContext ctx = new InitialContext();
  +            String jsmName = "jaas:/"+securityDomain;
  +            JaasSecurityManager jsm = (JaasSecurityManager) ctx.lookup(jsmName);
  +            subject = jsm.getActiveSubject();
  +        }
  +        catch(NamingException e)
  +        {
  +        }
  +        return subject;
  +    }
  +    /** Create a LoginContext for the currently authenticated Subject in
  +     securityDomain.
  +    */
  +    public static LoginContext getActiveSubjectLoginContext(String securityDomain, 
CallbackHandler handler)
  +        throws LoginException
  +    {
  +        LoginContext lc = null;
  +        Subject subject = getActiveSubject(securityDomain);
  +        if( subject == null )
  +            throw new LoginException("No active subject found in securityDomain: 
"+securityDomain);
  +
  +        if( handler != null )
  +            lc = new LoginContext(securityDomain, subject, handler);
  +        else
  +            lc = new LoginContext(securityDomain, subject);
  +
  +        return lc;
  +    }
  +
  +    /** Creates a default JaasSecurityManager for with a securityDomain
  +     name of 'other'.
  +    */
  +    public JaasSecurityManager()
  +    {
  +        this("other");
  +    }
  +    /** Creates a JaasSecurityManager for with a securityDomain
  +     name of that given by the 'securityDomain' argument.
  +    @param securityDomain.
  +    */
  +    public JaasSecurityManager(String securityDomain)
  +    {
  +        this.securityDomain = securityDomain;
  +        try
  +        {   // Try to get the SecurityPolicy from the JAAS Policy class
  +            securityPolicy = (SecurityPolicy) Policy.getPolicy();
  +        }
  +        catch(ClassCastException e)
  +        {  // The installed Policy is not a SecurityPolicy
  +        }
  +    }
  +
  +    /** The domainCache is typically a shared object that is populated
  +        by the login code(LoginModule, etc.) and read by this class in the
  +        isValid() method.
  +    @see #isValid(Principal, Object)
  +    */
  +    public void setCachePolicy(CachePolicy domainCache)
  +    {
  +        this.domainCache = domainCache;
  +    }
  +
  +    public void flushCache()
  +    {
  +        if( domainCache != null )
  +            domainCache.flush();
  +    }
  +
  +    public void setSecurityPolicyName(String jndiName) throws NamingException
  +    {
  +        InitialContext ctx = new InitialContext();
  +        securityPolicy = (SecurityPolicy) ctx.lookup(jndiName);
  +    }
  +
  +    /** Get the name of the security domain associated with this security mgr.
  +        @return Name of the security manager security domain.
  +     */
  +    public String getSecurityDomain()
  +    {
  +        return securityDomain;
  +    }
  +    /** Get the currently authenticated Subject. This is a thread local
  +        property shared across all JaasSecurityManager instances.
  +        @return The Subject authenticated in the current thread if one
  +        exists, null otherwise.
  +     */
  +    public Subject getActiveSubject()
  +    {
  +        return (Subject) activeSubject.get();
  +    }
  +
  +    /** Validate that the given credential is correct for principal. This first
  +     will check the current CachePolicy object if one exists to see if the
  +     user's cached credentials match the given credential. If there is no
  +     credential cache or the cache information is invalid or does not match,
  +     the user is authenticated against the JAAS login modules configured for
  +     the security domain.
  +    @param principal, the security domain principal attempting access
  +    @param credential, the proof of identity offered by the principal
  +    @return true if the principal was authenticated, false otherwise.
  +     */
  +    public boolean isValid(Principal principal, Object credential)
  +    {
  +        // Check the cache first
  +        DomainInfo cacheInfo = null;
  +        if( domainCache != null )
  +            cacheInfo = (DomainInfo) domainCache.get(principal);
  +
  +        boolean isValid = false;
  +        if( cacheInfo != null )
  +            isValid = validateCache(cacheInfo, credential);
  +        if( isValid == false )
  +            isValid = authenticate(principal, credential);
  +        return isValid;
  +    }
  +
  +    /** Map the argument principal from the deployment environment principal
  +        to the developer environment. This is called by the EJB context
  +        getCallerPrincipal() to return the Principal as described by
  +        the EJB developer domain.
  +    @return a Principal object that is valid in the deployment environment
  +        if one exists. If no Subject exists or the Subject has no principals
  +        then the argument principal is returned.
  +     */
  +    public Principal getPrincipal(Principal principal)
  +    {
  +        Principal result = principal;
  +        if( domainCache != null )
  +        {
  +            // Get the CallerPrincipal group member
  +            DomainInfo info = (DomainInfo) domainCache.get(principal);
  +            if( info != null )
  +                result = info.callerPrincipal;
  +            // If the mapping did not have a callerPrincipal just use principal
  +            if( result == null )
  +                result = principal;  
  +        }
  +
  +        return result;
  +    }
  +
  +    /** Does the current Subject have a role(a Principal) that equates to one
  +        of the role names. This method obtains the Group named 'Roles' from
  +        the principal set of the currently authenticated Subject and then
  +        creates a SimplePrincipal for each name in roleNames. If the role is
  +        a member of the Roles group, then the user has the role.
  +    @param principal, ignored. The current authenticated Subject determines
  +        the active user and assigned user roles.
  +    @param rolePrincipals, a Set of Principals for the roles to check.
  +
  +    @see java.security.acl.Group;
  +    @see Subject#getPrincipals()
  +    */
  +    public boolean doesUserHaveRole(Principal principal, Set rolePrincipals)
  +    {
  +        boolean hasRole = false;
  +        Subject subject = getActiveSubject();
  +        if( subject != null )
  +        {
  +            DomainInfo info = null;
  +            if( domainCache != null )
  +                info = (DomainInfo) domainCache.get(principal);
  +
  +            Group roles = null;
  +            if( info != null )
  +                roles = info.roles;
  +            if( roles != null )
  +            {
  +                Iterator iter = rolePrincipals.iterator();
  +                while( hasRole == false && iter.hasNext() )
  +                {
  +                    Principal role = (Principal) iter.next();
  +                    hasRole = roles.isMember(role);
  +                }
  +            }
  +        }
  +        return hasRole;
  +    }
  +
  +    /** Validates operational environment Principal against the specified
  +        application domain role.
  +    @param principal, the caller principal as known in the operation environment.
  +    @param role, the application domain role that the principal is to be validated 
against.
  +    @return true if the principal has the role, false otherwise.
  +     */
  +    public boolean doesUserHaveRole(Principal principal, Principal role)
  +    {
  +        boolean hasRole = false;
  +        Subject subject = getActiveSubject();
  +        if( subject != null )
  +        {
  +            DomainInfo info = null;
  +            if( domainCache != null )
  +                info = (DomainInfo) domainCache.get(principal);
  +
  +            Group roles = null;
  +            if( info != null )
  +                roles = info.roles;
  +            if( roles != null )
  +            {
  +                hasRole = roles.isMember(role);
  +            }
  +        }
  +        return hasRole;
  +    }
  +
  +    /** Currently this simply calls defaultLogin() to do a JAAS login using the
  +     security domain name as the login module configuration name.
  +
  +     * @param principal, the user id to authenticate
  +     * @param credential, an opaque credential.
  +     * @return false on failure, true on success.
  +     */
  +    private boolean authenticate(Principal principal, Object credential)
  +    {
  +        LoginContext lc = null;
  +        Subject subject = null;
  +        boolean authenticated = false;
  +
  +        try
  +        {
  +            // Clear any current subject
  +            activeSubject.set(null);
  +            // Get the AppPolicy login info. Not implemented yet.
  +            AppPolicy policy = null;
  +            subject = defaultLogin(principal, credential);
  +
  +            // Set the current subject if login was successful
  +            if( subject != null )
  +            {
  +                activeSubject.set(subject);
  +                authenticated = true;
  +                // Build the Subject based DomainInfo cache value
  +                updateCache(subject, principal, credential);
  +            }
  +        }
  +        catch(LoginException e)
  +        {
  +            e.printStackTrace();
  +        }
  +
  +        return authenticated;
  +    }
  +
  +    /** Pass the security info to the login modules configured for
  +        this security domain using our SecurityAssociationHandler.
  +     @return The authenticated Subject if successful.
  +     @exception LoginException throw if login fails for any reason.
  +     */
  +    private Subject defaultLogin(Principal principal, Object credential)
  +        throws LoginException
  +    {
  +        // We use our internal CallbackHandler to provide the security info
  +        handler.setSecurityInfo(principal, credential);
  +        Subject subject = new Subject();
  +        LoginContext lc = new LoginContext(securityDomain, subject, handler);
  +        lc.login();
  +        return subject;
  +    }
  +
  +    /** Validate the cache credential value against the provided credential
  +     */
  +    private boolean validateCache(DomainInfo info, Object credential)
  +    {
  +        Object subjectCredential = info.credential;
  +        boolean isValid = false;
  +        // Check for a null credential as can be the case for an anonymou user
  +        if( credential == null )
  +        {
  +           // Subject credential must also be null
  +           isValid = subjectCredential == null;
  +        }
  +        if( isValid == true )
  +           return true;
  +
  +        if( subjectCredential.getClass().isAssignableFrom(credential.getClass()) == 
false )
  +            return false;
  +
  +        if( subjectCredential instanceof Comparable )
  +        {
  +            Comparable c = (Comparable) subjectCredential;
  +            isValid = c.compareTo(credential) == 0;
  +        }
  +        else if( subjectCredential instanceof char[] )
  +        {
  +            char[] a1 = (char[]) subjectCredential;
  +            char[] a2 = (char[]) credential;
  +            isValid = Arrays.equals(a1, a2);
  +        }
  +        else if( subjectCredential instanceof byte[] )
  +        {
  +            byte[] a1 = (byte[]) subjectCredential;
  +            byte[] a2 = (byte[]) credential;
  +            isValid = Arrays.equals(a1, a2);
  +        }
  +        else
  +        {
  +            isValid = subjectCredential.equals(credential);
  +        }
  +
  +        if( isValid )
  +        {
  +            activeSubject.set(info.subject);
  +        }
  +
  +        return isValid;
  +    }
  +
  +    private void updateCache(Subject subject, Principal principal, Object 
credential)
  +    {
  +        DomainInfo info = new DomainInfo();
  +        info.subject = subject;
  +        info.credential = credential;
  +
  +        /* If we don't have a cache policy create a default timed cache
  +         that has an 1800 sec lifetime, is thread-safe, and a resolution
  +         of 60 seconds.
  +         */
  +        if( domainCache == null )
  +        {
  +            domainCache = new TimedCachePolicy(1800, true, 60);
  +            try
  +            {
  +                domainCache.init();
  +                domainCache.start();
  +            }
  +            catch(Exception e)
  +            {
  +                e.printStackTrace();
  +            }
  +        }
  +
  +        /* Get the Subject callerPrincipal by looking for a Group called
  +           'CallerPrincipal' and roles by looking for a Group called 'Roles'
  +        */
  +        Set subjectGroups = subject.getPrincipals(Group.class);
  +        Iterator iter = subjectGroups.iterator();
  +        while( iter.hasNext() )
  +        {
  +            Group grp = (Group) iter.next();
  +            String name = grp.getName();
  +            if( name.equals("CallerPrincipal") )
  +            {
  +                Enumeration members = grp.members();
  +                if( members.hasMoreElements() )
  +                    info.callerPrincipal = (Principal) members.nextElement();
  +            }
  +            else if( name.equals("Roles") )
  +                info.roles = grp;
  +        }
  +
  +        /* Handle null principals with no callerPrincipal. This is an indication
  +           of an user that has not provided any authentication info, but
  +           has been authenticated by the domain login module stack. Here we look
  +           for the first non-Group Principal and use that.
  +        */
  +        if( principal == null && info.callerPrincipal == null )
  +        {
  +           Set subjectPrincipals = subject.getPrincipals(Principal.class);
  +           iter = subjectPrincipals.iterator();
  +           while( iter.hasNext() )
  +           {
  +               Principal p = (Principal) iter.next();
  +               if( (p instanceof Group) == false )
  +                  info.callerPrincipal = p;
  +           }
  +        }
  +
  +        /* If the user already exists another login is active. Currently
  +           only one is allowed so remove the old and insert the new.
  +        */
  +        if( domainCache.peek(principal) != null )
  +            domainCache.remove(principal);
  +        domainCache.insert(principal, info);
  +    }
  +
  +}
  
  
  

_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to