User: starksm 
  Date: 01/03/28 18:27:13

  Modified:    src/main/org/jboss/security/plugins/samples
                        DatabaseServerLoginModule.java
                        IdentityLoginModule.java JaasServerLoginModule.java
                        LdapLoginModule.java RolesLoginModule.java
                        SimpleServerLoginModule.java
  Added:       src/main/org/jboss/security/plugins/samples
                        UsernamePasswordLoginModule.java
  Log:
  Updated sample modules to subclass AbstractServerLoginModule to ensure
  consistent behaviore. Add role mapping to DatabaseServerLoginModule.
  
  Revision  Changes    Path
  1.2       +160 -125  
jbosssx/src/main/org/jboss/security/plugins/samples/DatabaseServerLoginModule.java
  
  Index: DatabaseServerLoginModule.java
  ===================================================================
  RCS file: 
/cvsroot/jboss/jbosssx/src/main/org/jboss/security/plugins/samples/DatabaseServerLoginModule.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DatabaseServerLoginModule.java    2001/03/05 09:53:35     1.1
  +++ DatabaseServerLoginModule.java    2001/03/29 02:27:12     1.2
  @@ -4,13 +4,14 @@
    * Distributable under LGPL license.
    * See terms of license at gnu.org.
    */
  - 
   package org.jboss.security.plugins.samples;
   
  -
  +import java.security.acl.Group;
  +import java.util.Enumeration;
  +import java.util.HashMap;
   import java.util.Map;
   import java.util.Set;
  -import java.util.Arrays;
  +import java.util.Vector;
   import java.sql.Connection;
   import java.sql.PreparedStatement;
   import java.sql.ResultSet;
  @@ -19,150 +20,184 @@
   import javax.naming.NamingException;
   import javax.sql.DataSource;
   import javax.security.auth.Subject;
  -import javax.security.auth.callback.Callback;
   import javax.security.auth.callback.CallbackHandler;
  -import javax.security.auth.callback.NameCallback;
  -import javax.security.auth.callback.PasswordCallback;
  -import javax.security.auth.callback.UnsupportedCallbackException;
   import javax.security.auth.login.LoginException;
   import javax.security.auth.login.FailedLoginException;
  -import javax.security.auth.spi.LoginModule;
   
  -public class DatabaseServerLoginModule implements LoginModule {
  -    private String _db;
  -    private String _table;
  -    private String _nameCol;
  -    private String _pswCol;
  -    private Subject _subject;
  -    private CallbackHandler _callbackHandler;
  -    private String _username;
  +import org.jboss.security.SimpleGroup;
  +import org.jboss.security.SimplePrincipal;
  +import org.jboss.security.plugins.samples.UsernamePasswordLoginModule;
  +
  +/** A JDBC based login module that supports authentication and role mapping.
  +It is based on two logical tables:
  +
  + Principals(PrincipalID text, Password text)
  + Roles(PrincipalID text, Role text, RoleGroup text)
  +
  +LoginModule options:
  +dsJndiName: The name of the DataSource of the database containing the Principals, 
Roles tables
  +principalsQuery: The prepared statement query equivalent to:
  +    "select Password from Principals where PrincipalID=?"
  +rolesQuery: The prepared statement query equivalent to:
  +    "select Role, RoleGroup from Roles where PrincipalID=?"
  +
  +@author <a href="[EMAIL PROTECTED]">Oleg Nitz</a>
  +@author [EMAIL PROTECTED]
  +@version $Revision: 1.2 $
  +*/
  +public class DatabaseServerLoginModule extends UsernamePasswordLoginModule
  +{
  +    private String dsJndiName;
  +    private String principalsQuery = "select Password from Principals where 
PrincipalID=?";
  +    private String rolesQuery = "select Role, RoleGroup from Roles where 
PrincipalID=?";
   
       /**
        * Initialize this LoginModule.
        */
  -    public void initialize(Subject subject, CallbackHandler callbackHandler,
  -            Map sharedState, Map options) {
  -        _subject = subject;
  -        _callbackHandler = callbackHandler;
  -        _db = (String) options.get("db");
  -        _table = (String) options.get("table");
  -        _nameCol = (String) options.get("name");
  -        _pswCol = (String) options.get("password");
  +    public void initialize(Subject subject, CallbackHandler callbackHandler, Map 
sharedState, Map options)
  +    {
  +        super.initialize(subject, callbackHandler, sharedState, options);
  +        dsJndiName = (String) options.get("dsJndiName");
  +        Object tmp = options.get("principalsQuery");
  +        if( tmp != null )
  +            principalsQuery = tmp.toString();
  +        tmp = options.get("rolesQuery");
  +        if( tmp != null )
  +            rolesQuery = tmp.toString();
       }
   
  -    /**
  -     * Method to authenticate a Subject (phase 1).
  +     /** Get the expected password for the current username available via
  +     * the getUsername() method. This is called from within the login()
  +     * method after the CallbackHandler has returned the username and
  +     * candidate password.
  +     * @return the valid password String
        */
  -    public boolean login() throws LoginException {
  -        Callback[] callbacks = new Callback[2];
  -        char[] password;
  -        char[] tmpPassword;
  -        InitialContext initial;
  -        DataSource ds;
  +    protected String getUsersPassword() throws LoginException
  +    {
  +        String username = getUsername();
  +        String password = null;
           Connection conn = null;
  -        PreparedStatement ps;
  -        ResultSet rs;
  -        Object psw;
  -        boolean ok;
  -      
  -        try {
  -            // prompt for a username and password
  -            if (_callbackHandler == null) {
  -                throw new LoginException("Error: no CallbackHandler available " +
  -                                         "to garner authentication information from 
the user");
  -            }
   
  -            callbacks[0] = new NameCallback("User name: ", "guest");
  -            callbacks[1] = new PasswordCallback("Password: ", false);
  -            _callbackHandler.handle(callbacks);
  -            _username = ((NameCallback)callbacks[0]).getName();
  -            tmpPassword = ((PasswordCallback)callbacks[1]).getPassword();
  -            if (tmpPassword == null) {
  -                password = null;
  -            } else {
  -                password = new char[tmpPassword.length];
  -                System.arraycopy(tmpPassword, 0, password, 0, tmpPassword.length);
  -                ((PasswordCallback)callbacks[1]).clearPassword();
  -            }
  -
  -            // password authorization
  -            if (_pswCol != null) {
  -                initial = new InitialContext();
  -                ds = (DataSource) initial.lookup( _db );
  -                conn = ds.getConnection();
  -                ps = conn.prepareStatement("SELECT " + _pswCol + " FROM " + _table +
  -                                           " WHERE " + _nameCol + "=?");
  -                ps.setString(1, _username);
  -                rs = ps.executeQuery();
  -                if (!rs.next()) {
  -                    throw new FailedLoginException("Incorrect user name");
  +        try
  +        {
  +            InitialContext ctx = new InitialContext();
  +            DataSource ds = (DataSource) ctx.lookup(dsJndiName);
  +            conn = ds.getConnection();
  +            // Get the password
  +            PreparedStatement ps = conn.prepareStatement(principalsQuery);
  +            ps.setString(1, username);
  +            ResultSet rs = ps.executeQuery();
  +            if( rs.next() == false )
  +                throw new FailedLoginException("No matching username found in 
Principals");
  +
  +            password = rs.getString(1);
  +            password = convertRawPassword(password);
  +            ps.close();
  +            rs.close();
  +        }
  +        catch(NamingException ex)
  +        {
  +            throw new LoginException(ex.toString(true));
  +        }
  +        catch(SQLException ex)
  +        {
  +            ex.printStackTrace();
  +            throw new LoginException(ex.toString());
  +        }
  +        finally
  +        {
  +            if( conn != null )
  +            {
  +                try
  +                {
  +                    conn.close();
                   }
  -                psw = rs.getObject(1);
  -                if (password == null || psw == null) {
  -                    ok = (password == psw);
  -                } else if (psw instanceof byte[]) {
  -                    byte[] bpsw;
  -                    int len;
  -                    char[] cpsw;
  -                    bpsw = (byte[]) psw;
  -                    // trim zero bytes
  -                    for (len = bpsw.length; len>0; len--) {
  -                        if (bpsw[len - 1] != 0) {
  -                            break;
  -                        }
  -                    }
  -                    cpsw = new char[len];
  -                    for (int i = 0; i < len; i++) {
  -                        cpsw[i] = (char) bpsw[i];
  -                    }
  -                    ok = Arrays.equals(password, cpsw);
  -                } else if (psw instanceof String) {
  -                    // trim spaces
  -                    ok = (new String(password)).equals(((String) psw).trim());
  -                } else {
  -                    throw new LoginException("Unsupported SQL type of password 
column");
  +                catch (Exception ex)
  +                {
                   }
  -                if (!ok) {
  -                    throw new FailedLoginException("Incorrect password");
  -                }                        
               }
  -        } catch (NamingException ex) {
  -            throw new LoginException(ex.toString());
  -        } catch (java.io.IOException ex) {
  -            throw new LoginException(ex.toString());
  -        } catch (SQLException ex) {
  +        }
  +        return password;
  +    }
  +
  +    /** Overriden by subclasses to return the Groups that correspond to the
  +        to the role sets assigned to the user. Subclasses should create at
  +        least a Group named "Roles" that contains the roles assigned to the user.
  +        A second common group is "CallerPrincipal" that provides the application
  +        identity of the user rather than the security domain identity.
  +    @return Group[] containing the sets of roles 
  +    */
  +    protected Group[] getRoleSets() throws LoginException
  +    {
  +        String username = getUsername();
  +        Connection conn = null;
  +        HashMap setsMap = new HashMap();
  +
  +        try
  +        {
  +            InitialContext ctx = new InitialContext();
  +            DataSource ds = (DataSource) ctx.lookup(dsJndiName);
  +            conn = ds.getConnection();
  +            // Get the users role names
  +            PreparedStatement ps = conn.prepareStatement(rolesQuery);
  +            ps.setString(1, username);
  +            ResultSet rs = ps.executeQuery();
  +            if( rs.next() == false )
  +                throw new FailedLoginException("No matching username found in 
Roles");
  +
  +            do
  +            {
  +                String name = rs.getString(1);
  +                String groupName = rs.getString(2);
  +                if( groupName == null || groupName.length() == 0 )
  +                    groupName = "Roles";
  +                Group group = (Group) setsMap.get(groupName);
  +                if( group == null )
  +                {
  +                    group = new SimpleGroup(groupName);
  +                    setsMap.put(groupName, group);
  +                }
  +                group.addMember(new SimplePrincipal(name));
  +            } while( rs.next() );
  +            ps.close();
  +            rs.close();
  +        }
  +        catch(NamingException ex)
  +        {
  +            throw new LoginException(ex.toString(true));
  +        }
  +        catch(SQLException ex)
  +        {
  +            ex.printStackTrace();
               throw new LoginException(ex.toString());
  -        } catch (UnsupportedCallbackException uce) {
  -            throw new LoginException("Error: " + uce.getCallback().toString() +
  -                    " not available to garner authentication information " +
  -                    "from the user");
  -        } finally {
  -            if (conn != null) {
  -                try {
  +        }
  +        finally
  +        {
  +            if( conn != null )
  +            {
  +                try
  +                {
                       conn.close();
  -                } catch (Exception ex) {
                   }
  +                catch (Exception ex)
  +                {
  +                }
               }
           }
  -        return true;
  -    }
  -          
  -    /**
  -     * Method to commit the authentication process (phase 2).
  -     */
  -    public boolean commit() throws LoginException {
  -        return true;
  -    }    
  -          
  -    /**
  -     * Method to abort the authentication process (phase 2).
  -     */
  -    public boolean abort() throws LoginException {
  -        _username = null;
  -        return true;
  +
  +        Group[] roleSets = new Group[setsMap.size()];
  +        setsMap.values().toArray(roleSets);
  +        return roleSets;
       }
   
  -    public boolean logout() throws LoginException {
  -        return true;
  +    /** A hook to allow subclasses to convert a password from the database
  +        into a plain text string or whatever form is used for matching against
  +        the user input. It is called from within the getUsersPassword() method.
  +    @param rawPassword, the password as obtained from the database
  +    @return the argument rawPassword
  +    */
  +    protected String convertRawPassword(String rawPassword)
  +    {
  +        return rawPassword;
       }
   }
  
  
  
  1.3       +9 -8      
jbosssx/src/main/org/jboss/security/plugins/samples/IdentityLoginModule.java
  
  Index: IdentityLoginModule.java
  ===================================================================
  RCS file: 
/cvsroot/jboss/jbosssx/src/main/org/jboss/security/plugins/samples/IdentityLoginModule.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- IdentityLoginModule.java  2001/03/22 09:40:03     1.2
  +++ IdentityLoginModule.java  2001/03/29 02:27:12     1.3
  @@ -2,6 +2,7 @@
   package org.jboss.security.plugins.samples;
   
   import java.security.Principal;
  +import java.security.acl.Group;
   import java.util.ArrayList;
   import java.util.Map;
   import java.util.StringTokenizer;
  @@ -10,6 +11,7 @@
   import javax.security.auth.login.LoginException;
   import javax.security.auth.spi.LoginModule;
   
  +import org.jboss.security.SimpleGroup;
   import org.jboss.security.SimplePrincipal;
   import org.jboss.security.plugins.AbstractServerLoginModule;
   
  @@ -19,10 +21,11 @@
   If no principal option is specified a principal with the name of 'guest'
   is used.
   
  +@see org.jboss.security.SimpleGroup
   @see org.jboss.security.SimplePrincipal
   
   @author [EMAIL PROTECTED]
  -@version $Revision: 1.2 $
  +@version $Revision: 1.3 $
   */
   public class IdentityLoginModule extends AbstractServerLoginModule
   {
  @@ -60,21 +63,19 @@
           Principal principal = new SimplePrincipal(principalName);
           return principal;
       }
  -    protected Principal[] getRoles()
  +    protected Group[] getRoleSets() throws LoginException
       {
  -        Principal[] roles = null;
  +        SimpleGroup roles = new SimpleGroup("Roles");
  +        Group[] roleSets = {roles};
           if( roleNames != null )
           {
  -            ArrayList tmp = new ArrayList();
               StringTokenizer tokenizer = new StringTokenizer(roleNames, ",");
               while( tokenizer.hasMoreTokens() )
               {
                   String roleName = tokenizer.nextToken();
  -                tmp.add(new SimplePrincipal(roleName));
  +                roles.addMember(new SimplePrincipal(roleName));
               }
  -            roles = new Principal[tmp.size()];
  -            tmp.toArray(roles);
           }
  -        return roles;
  +        return roleSets;
       }
   }
  
  
  
  1.3       +82 -31    
jbosssx/src/main/org/jboss/security/plugins/samples/JaasServerLoginModule.java
  
  Index: JaasServerLoginModule.java
  ===================================================================
  RCS file: 
/cvsroot/jboss/jbosssx/src/main/org/jboss/security/plugins/samples/JaasServerLoginModule.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- JaasServerLoginModule.java        2001/03/22 09:40:03     1.2
  +++ JaasServerLoginModule.java        2001/03/29 02:27:12     1.3
  @@ -10,6 +10,7 @@
   import java.util.*;
   import java.io.*;
   
  +import java.security.acl.Group;
   import javax.security.auth.Subject;
   import javax.security.auth.callback.Callback;
   import javax.security.auth.callback.CallbackHandler;
  @@ -19,31 +20,41 @@
   import javax.security.auth.login.LoginException;
   import javax.security.auth.login.FailedLoginException;
   import javax.security.auth.spi.LoginModule;
  -import org.jboss.security.plugins.AbstractServerLoginModule;
   
  +import org.jboss.security.SimpleGroup;
  +import org.jboss.security.SimplePrincipal;
  +import org.jboss.security.plugins.AbstractServerLoginModule;
   
  -/**
  - * JaasServerLoginModule
  - * written by: Edward Kenworthy 12th Dec 2000
  - *
  - * An example of a realistic ServerLoginModule that can be used when using JAAS
  - * security with jBoss. I took SimpleServerLoginModule, written by Oleg Nitz and 
extended
  - * the functionality.
  - *
  - * It uses two properties files:
  - *        users.properties, which holds users (key) and their password (value).
  - *        roles.properties which holds users (key) and a list of their roles as csv 
(value).
  - *
  - * Obviously using properties files means it will struggle with very large numbers 
of users and
  - * also as it reads the properties file in at initialisation it will be insensitive 
to subsequent
  - * password changes. It does have the advantage of being realistic in its 
functionality.
  - *
  - * The other major change I have made is to pull out an abstract class 
(AbstractServerLoginModule)
  - * so that if you want to implement a more scalable way of looking up users and 
passwords and roles then you can
  - * do so without having to start from scratch.
  - *
  - * @author <a href="[EMAIL PROTECTED]">Edward Kenworthy</a>
  - */
  +/** A simple properties file based login module that consults two Java Properties
  +formatted text files for username to password("users.properties") and
  +username to roles("roles.properties") mapping. The properties files are loaded
  +during initialization using the thread context class loader. This means that
  +these files can be placed into the J2EE deployment jar or the JBoss config
  +directory.
  +
  +The users.properties file uses a format:
  +    username1=password1
  +    username2=password2
  +    ...
  +
  +to define all valid usernames and their corresponding passwords.
  +
  +The roles.properties file uses a format:
  +    username1=role1,role2,...
  +    username1.RoleGroup1=role3,role4,...
  +    username2=role1,role3,...
  +
  +to define the sets of roles for valid usernames. The "username.XXX" form of
  +property name is used to assign the username roles to a particular named
  +group of roles where the XXX portion of the property name is the group name.
  +The "username=..." form is an abbreviation for "username.Roles=...".
  +The following are therefore equivalent:
  +    jduke=TheDuke,AnimatedCharacter
  +    jduke.Roles=TheDuke,AnimatedCharacter
  +
  +@author <a href="[EMAIL PROTECTED]">Edward Kenworthy</a>, 12th Dec 
2000
  +@author [EMAIL PROTECTED]
  +*/
   public class JaasServerLoginModule extends UsernamePasswordLoginModule
   {
     // users+passwords, users+roles
  @@ -94,11 +105,44 @@
           return super.login();
       }
   
  -    // Polymorphic, used by the abstract base class.
  -    protected Enumeration getUsersRoles()
  +    /** Create the set of roles the user belongs to by parsing the roles.properties
  +        data for username=role1,role2,... and username.XXX=role1,role2,...
  +        patterns.
  +    @return Group[] containing the sets of roles 
  +    */
  +    protected Group[] getRoleSets() throws LoginException
       {
  -      String roles = _roles.getProperty(getUsername());
  -      return (roles == null ? null : new StringTokenizer(roles, ","));
  +        Enumeration users = _roles.propertyNames();
  +        SimpleGroup rolesGroup = new SimpleGroup("Roles");
  +        ArrayList groups = new ArrayList();
  +        groups.add(rolesGroup);
  +        while( users.hasMoreElements() )
  +        {
  +            String user = (String) users.nextElement();
  +            String value = _roles.getProperty(user);
  +            // Check for username.RoleGroup pattern
  +            int index = user.indexOf('.');
  +            if( index > 0 )
  +            {
  +                String groupName = user.substring(index+1);
  +                if( groupName.equals("Roles") )
  +                    parseGroupMembers(rolesGroup, value);
  +                else
  +                {
  +                    SimpleGroup group = new SimpleGroup(groupName);
  +                    parseGroupMembers(rolesGroup, value);
  +                    groups.add(group);
  +                }
  +            }
  +            else
  +            {
  +                // Place these roles into the Default "Roles" group
  +                parseGroupMembers(rolesGroup, value);
  +            }
  +        }
  +        Group[] roleSets = new Group[groups.size()];
  +        groups.toArray(roleSets);
  +        return roleSets;
       }
       protected String getUsersPassword()
       {
  @@ -106,6 +150,17 @@
       }
   
   // utility methods
  +    private void parseGroupMembers(Group group, String value)
  +    {
  +        StringTokenizer tokenizer = new StringTokenizer(value, ",");
  +        while( tokenizer.hasMoreTokens() )
  +        {
  +            String token = tokenizer.nextToken();
  +            SimplePrincipal p = new SimplePrincipal(token);
  +            group.addMember(p);
  +        }
  +    }
  +
       private void LoadUsers() throws IOException
       {
         _users = LoadProperties("users.properties");
  @@ -138,7 +193,3 @@
         return bundle;
       }
   }
  -
  -
  -
  -
  
  
  
  1.2       +8 -9      
jbosssx/src/main/org/jboss/security/plugins/samples/LdapLoginModule.java
  
  Index: LdapLoginModule.java
  ===================================================================
  RCS file: 
/cvsroot/jboss/jbosssx/src/main/org/jboss/security/plugins/samples/LdapLoginModule.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- LdapLoginModule.java      2001/03/22 09:40:03     1.1
  +++ LdapLoginModule.java      2001/03/29 02:27:12     1.2
  @@ -7,6 +7,7 @@
   package org.jboss.security.plugins.samples;
   
   import java.security.Principal;
  +import java.security.acl.Group;
   import java.util.ArrayList;
   import java.util.Iterator;
   import java.util.Map;
  @@ -30,6 +31,7 @@
   import javax.security.auth.login.LoginException;
   import javax.security.auth.spi.LoginModule;
   
  +import org.jboss.security.SimpleGroup;
   import org.jboss.security.SimplePrincipal;
   import org.jboss.security.plugins.AbstractServerLoginModule;
   import org.jboss.security.plugins.ObjectCallback;
  @@ -81,7 +83,7 @@
    };
   
   @author [EMAIL PROTECTED]
  -@version $Revision: 1.1 $
  +@version $Revision: 1.2 $
   */
   public class LdapLoginModule extends AbstractServerLoginModule
   {
  @@ -98,7 +100,7 @@
   
        private transient String username;
        private transient Object credential;
  -    private transient Principal[] userRoles;
  +    private transient SimpleGroup userRoles = new SimpleGroup("Roles");
   
        public boolean login() throws javax.security.auth.login.LoginException
        {
  @@ -136,9 +138,10 @@
       {
           return new SimplePrincipal(username);
       }
  -    protected Principal[] getRoles()
  +    protected Group[] getRoleSets() throws LoginException
       {
  -        return userRoles;
  +        Group[] roleSets = {userRoles};
  +        return roleSets;
       }
   
       private void getUsernamePassword() throws LoginException
  @@ -232,10 +235,8 @@
               try
               {
                   NamingEnumeration answer = ctx.search(rolesCtxDN, matchAttrs, 
roleAttr);
  -                ArrayList tmp = new ArrayList();
                   while( answer.hasMore() )
                   {
  -                    System.out.println("Roles:");
                       SearchResult sr = (SearchResult) answer.next();
                       Attributes attrs = sr.getAttributes();
                       Attribute roles = attrs.get(roleAttrName);
  @@ -243,11 +244,9 @@
                       {
                           Object value = roles.get(r);
                           String roleName = value.toString();
  -                        tmp.add(new SimplePrincipal(roleName));
  +                        userRoles.addMember(new SimplePrincipal(roleName));
                       }
                   }
  -                userRoles = new Principal[tmp.size()];
  -                tmp.toArray(userRoles);
               }
               catch(NamingException e)
               {
  
  
  
  1.3       +2 -1      
jbosssx/src/main/org/jboss/security/plugins/samples/RolesLoginModule.java
  
  Index: RolesLoginModule.java
  ===================================================================
  RCS file: 
/cvsroot/jboss/jbosssx/src/main/org/jboss/security/plugins/samples/RolesLoginModule.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- RolesLoginModule.java     2001/03/06 08:35:29     1.2
  +++ RolesLoginModule.java     2001/03/29 02:27:12     1.3
  @@ -33,9 +33,10 @@
   a module that does the authentication and passes the username via
   the sharedMap as the javax.security.auth.login.name property.
   
  +@deprecated See the JaasServerLoginModule which has incorporated this behavior.
   
   @author [EMAIL PROTECTED]
  -@version $Revision: 1.2 $
  +@version $Revision: 1.3 $
   */
   public class RolesLoginModule implements LoginModule
   {
  
  
  
  1.2       +65 -89    
jbosssx/src/main/org/jboss/security/plugins/samples/SimpleServerLoginModule.java
  
  Index: SimpleServerLoginModule.java
  ===================================================================
  RCS file: 
/cvsroot/jboss/jbosssx/src/main/org/jboss/security/plugins/samples/SimpleServerLoginModule.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SimpleServerLoginModule.java      2001/03/05 09:53:35     1.1
  +++ SimpleServerLoginModule.java      2001/03/29 02:27:13     1.2
  @@ -4,107 +4,83 @@
    * Distributable under LGPL license.
    * See terms of license at gnu.org.
    */
  -
   package org.jboss.security.plugins.samples;
  -
   
  -import java.util.Map;
  -import java.util.Set;
  -import javax.security.auth.Subject;
  -import javax.security.auth.callback.Callback;
  -import javax.security.auth.callback.CallbackHandler;
  -import javax.security.auth.callback.NameCallback;
  -import javax.security.auth.callback.PasswordCallback;
  -import javax.security.auth.callback.UnsupportedCallbackException;
  +import java.security.Principal;
  +import java.security.acl.Group;
   import javax.security.auth.login.LoginException;
  -import javax.security.auth.login.FailedLoginException;
   import javax.security.auth.spi.LoginModule;
  -
   
  -/**
  - * This server login module implements the following simple algorithm:
  - *   if password is null, authenticate the user and assign the "guest" role
  - *   else if password is equal to the user name, assign both "user" and "guest" 
roles
  - *   else don't authenticate.
  - */
  -public class SimpleServerLoginModule implements LoginModule {
  -    private Subject _subject;
  -    private CallbackHandler _callbackHandler;
  -
  -    // username and password
  -    private String _username;
  -    private char[] _password;
  -
  -    /**
  -     * Initialize this LoginModule.
  -     */
  -    public void initialize(Subject subject, CallbackHandler callbackHandler,
  -            Map sharedState, Map options) {
  -        _subject = subject;
  -        _callbackHandler = callbackHandler;
  +import org.jboss.security.SimpleGroup;
  +import org.jboss.security.SimplePrincipal;
  +import org.jboss.security.plugins.samples.UsernamePasswordLoginModule;
  +
  +/** A simple server login module useful to quick setup of security for testing
  +purposes. It implements the following simple algorithm:
  +    - if password is null, authenticate the user and assign an identity of guest
  +        and a role of "guest".
  +    - else if password is equal to the user name, assign an identity equal to
  +        the username and both "user" and "guest" roles
  +    - else authentication fails.
  +
  +@author <a href="[EMAIL PROTECTED]">Oleg Nitz</a>
  +@author [EMAIL PROTECTED]
  +@version $Revision: 1.2 $
  +*/
  +public class SimpleServerLoginModule extends UsernamePasswordLoginModule
  +{
  +    private SimplePrincipal user;
  +    private boolean guestOnly;
  +
  +    protected Principal getIdentity()
  +    {
  +        Principal principal = user;
  +        if( principal == null )
  +            principal = super.getIdentity();
  +        return principal;
       }
   
  -    /**
  -     * Method to authenticate a Subject (phase 1).
  -     */
  -    public boolean login() throws LoginException {
  -        Callback[] callbacks = new Callback[2];
  -        
  -        // prompt for a username and password
  -        if (_callbackHandler == null)
  -            throw new LoginException("Error: no CallbackHandler available " +
  -                "to garner authentication information from the user");
  -
  -        callbacks[0] = new NameCallback("User name: ", "guest");
  -        callbacks[1] = new PasswordCallback("Password: ", false);
  -        try {
  -            _callbackHandler.handle(callbacks);
  -            _username = ((NameCallback)callbacks[0]).getName();
  -            char[] tmpPassword = ((PasswordCallback)callbacks[1]).getPassword();
  -            if (tmpPassword != null) {
  -                _password = new char[tmpPassword.length];
  -                System.arraycopy(tmpPassword, 0, _password, 0, tmpPassword.length);
  -                ((PasswordCallback)callbacks[1]).clearPassword();
  -            }
  -        } catch (java.io.IOException ioe) {
  -            throw new LoginException(ioe.toString());
  -        } catch (UnsupportedCallbackException uce) {
  -            throw new LoginException("Error: " + uce.getCallback().toString() +
  -                    " not available to garner authentication information " +
  -                    "from the user");
  +    protected boolean validatePassword(String inputPassword, String 
expectedPassword)
  +    {
  +        boolean isValid = false;
  +        if( inputPassword == null )
  +        {
  +            guestOnly = true;
  +            isValid = true;
  +            user = new SimplePrincipal("guest");
           }
  -        if (_password != null && !(new String(_password)).equals(_username)) {
  -            throw new FailedLoginException("Password Incorrect");
  +        else
  +        {
  +            isValid = inputPassword.equals(expectedPassword);
           }
  -        return true;
  +        return isValid;
       }
  -          
  -    /**
  -     * Method to commit the authentication process (phase 2).
  -     */
  -    public boolean commit() throws LoginException {
  -        Set roles = _subject.getPublicCredentials();
  -        roles.add("guest");
  -        if (_password != null) {
  -            roles.add("user");
  -        }
  -        return true;
  -    }    
  -          
  -    /**
  -     * Method to abort the authentication process (phase 2).
  +
  +    /** Overriden by subclasses to return the Groups that correspond to the
  +     * to the role sets assigned to the user. Subclasses should create at
  +     * least a Group named "Roles" that contains the roles assigned to the user.
  +     * A second common group is "CallerPrincipal" that provides the application
  +     * identity of the user rather than the security domain identity.
  +     * @return Group[] containing the sets of roles 
        */
  -    public boolean abort() throws LoginException {
  -        _username = null;
  -        if (_password != null) {
  -            for (int i = 0; i < _password.length; i++)
  -            _password[i] = ' ';
  -            _password = null;
  -        }
  -        return true;
  +    protected Group[] getRoleSets() throws LoginException
  +    {
  +        Group[] roleSets = {new SimpleGroup("Roles")};
  +        if( guestOnly == false )
  +            roleSets[0].addMember(new SimplePrincipal("user"));
  +        roleSets[0].addMember(new SimplePrincipal("guest"));
  +        return roleSets;
       }
   
  -    public boolean logout() throws LoginException {
  -        return true;
  +    /** Get the expected password for the current username available via
  +     * the getUsername() method. This is called from within the login()
  +     * method after the CallbackHandler has returned the username and
  +     * candidate password.
  +     * @return the value of getUsername()
  +     */
  +    protected String getUsersPassword() throws LoginException
  +    {
  +        return getUsername();
       }
  +
   }
  
  
  
  1.1                  
jbosssx/src/main/org/jboss/security/plugins/samples/UsernamePasswordLoginModule.java
  
  Index: UsernamePasswordLoginModule.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.security.plugins.samples;
  
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.Enumeration;
  import java.security.Principal;
  import java.security.acl.Group;
  import javax.security.auth.Subject;
  import javax.security.auth.callback.Callback;
  import javax.security.auth.callback.CallbackHandler;
  import javax.security.auth.callback.NameCallback;
  import javax.security.auth.callback.PasswordCallback;
  import javax.security.auth.callback.UnsupportedCallbackException;
  import javax.security.auth.login.LoginException;
  import javax.security.auth.login.FailedLoginException;
  import javax.security.auth.spi.LoginModule;
  
  import org.jboss.security.SimpleGroup;
  import org.jboss.security.SimplePrincipal;
  import org.jboss.security.plugins.AbstractServerLoginModule;
  
  
  /** An abstract subclass of AbstractServerLoginModule that imposes a
  an identity == String username, credentials == String password view on
  the login process. Subclasses override the getUsersPassword()
  and getUsersRoles() methods to return the expected password and roles
  for the user.
  
  @see #getUsername()
  @see #getUsersPassword()
  @see #getUsersRoles()
  
  @author [EMAIL PROTECTED]
  @version $Revision: 1.1 $
  */
  public abstract class UsernamePasswordLoginModule extends AbstractServerLoginModule
  {
      /** The login identity */
      private Principal identity;
      /** The proof of login identity */
      private char[] credential;
  
      /**
       */
      public boolean login() throws LoginException
      {
          // See if shared credentials exist
          if( super.login() == true )
          {
              // Setup our view of the user
              Object username = sharedState.get("javax.security.auth.login.name");
              if( username instanceof Principal )
                  identity = (Principal) username;
              else
              {
                  String name = username.toString();
                  identity = new SimplePrincipal(name);
              }
              Object password = sharedState.get("javax.security.auth.login.password");
              if( password instanceof char[] )
                  credential = (char[]) password;
              else
              {
                  String tmp = password.toString();
                  credential = tmp.toCharArray();
              }
              return true;
          }
  
          String[] info = getUsernameAndPassword();
          String username = info[0];
          String password = info[1];
          identity = new SimplePrincipal(username);
  
          // Validate the password supplied by the subclass
          String expectedPassword = getUsersPassword();
          if( validatePassword(password, expectedPassword) == false )
          {
              System.out.println("[JAASSecurity] Bad password.");
              throw new FailedLoginException("Password Incorrect/Password Required");
          }
          System.out.print("[JAASSecurity] User '" + username + "' authenticated.\n");
  
          if( getUseFirstPass() == true )
          {    // Add the username and password to the shared state map
               sharedState.put("javax.security.auth.login.name", identity);
               sharedState.put("javax.security.auth.login.password", credential);
          }
          return true;
      }
  
      protected Principal getIdentity()
      {
          return identity;
      }
  
      protected Object getCredentials()
      {
          return credential;
      }
      protected String getUsername()
      {
          return getIdentity().getName();
      }
  
      /** Called by login() to acquire the username and password strings for
          authentication. This method does no validation of either.
      @return String[], [0] = username, [1] = password
      @exception LoginException thrown if CallbackHandler is not set or fails.
      */
      protected String[] getUsernameAndPassword() throws LoginException
      {
          String[] info = {null, null};
          // prompt for a username and password
          if( callbackHandler == null )
          {
              throw new LoginException("Error: no CallbackHandler available " +
                                   "to garner authentication information from the 
user");
          }
          NameCallback nc = new NameCallback("User name: ", "guest");
          PasswordCallback pc = new PasswordCallback("Password: ", false);
          Callback[] callbacks = {nc, pc};
          String username = null;
          String password = null;
          try
          {
              callbackHandler.handle(callbacks);
              username = nc.getName();
              char[] tmpPassword = pc.getPassword();
              if( tmpPassword != null )
              {
                  credential = new char[tmpPassword.length];
                  System.arraycopy(tmpPassword, 0, credential, 0, tmpPassword.length);
                  pc.clearPassword();
              }
              password = new String(credential);
          }
          catch(java.io.IOException ioe)
          {
              throw new LoginException(ioe.toString());
          }
          catch(UnsupportedCallbackException uce)
          {
              throw new LoginException("CallbackHandler does not support: " + 
uce.getCallback());
          }
          info[0] = username;
          info[1] = password;
          return info;
      }
  
      /** A hook that allows subclasses to change the validation of the input
          password against the expected password. This version checks that
          neither inputPassword or expectedPassword are null that that
          inputPassword.equals(expectedPassword) is true;
      @return true if the inputPassword is valid, false otherwise.
      */
      protected boolean validatePassword(String inputPassword, String expectedPassword)
      {
          if( inputPassword == null || expectedPassword == null )
              return false;
          return inputPassword.equals(expectedPassword);
      }
  
      /** Get the expected password for the current username available via
          the getUsername() method. This is called from within the login()
          method after the CallbackHandler has returned the username and
          candidate password.
      @return the valid password String
      */
      abstract protected String getUsersPassword() throws LoginException;
  
  }
  
  
  

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

Reply via email to