User: starksm 
  Date: 01/04/10 19:04:21

  Added:       src/main/org/jboss/security/auth/spi
                        AbstractServerLoginModule.java
                        DatabaseServerLoginModule.java
                        IdentityLoginModule.java LdapLoginModule.java
                        SimpleServerLoginModule.java
                        UsernamePasswordLoginModule.java
                        UsersRolesLoginModule.java
  Log:
  Clean up the package structure.
  
  Revision  Changes    Path
  1.1                  
jbosssx/src/main/org/jboss/security/auth/spi/AbstractServerLoginModule.java
  
  Index: AbstractServerLoginModule.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.security.auth.spi;
  
  import java.util.*;
  import java.io.*;
  
  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.NestableGroup;
  import org.jboss.security.SimpleGroup;
  
  /** This class implements the common functionality required for a JAAS
  server side LoginModule and implements the JBossSX standard Subject usage
  pattern of storing identities and roles. Subclass this module to create your
  own custom LoginModule and override the getRoles() and getIdentity()
  methods.
  
  You may also wish to override
      public void initialize(Subject subject, CallbackHandler callbackHandler, Map 
sharedState, Map options)
  
  In which case the first line of your initialize() method should be:
      super.initialize(subject, callbackHandler, sharedState, options);
  You may also wish to override
      public boolean login() throws LoginException
  In which case the last line of your login() method should be
      return super.login();
  
  @author <a href="[EMAIL PROTECTED]">Edward Kenworthy</a>, 12th Dec 
2000
  @author [EMAIL PROTECTED]
  @version $Revision: 1.1 $
  */
  public abstract class AbstractServerLoginModule implements LoginModule
  {
      protected Subject subject;
      protected CallbackHandler callbackHandler;
      protected Map sharedState;
      protected Map options;
  
      /** Flag indicating if the shared credential should be used */
      protected boolean useFirstPass;
  
  //--- Begin LoginModule interface methods
      /** Initialize the login module. This stores the subject, callbackHandler
          and sharedState and options for the login session.
      @param options,
          @option 
          @option password-stacking: if true, the login identity will be taken from the
          javax.security.auth.login.name value of the sharedState map, and
          the proof of identity from the javax.security.auth.login.password
          value sharedState map.
      */
      public void initialize(Subject subject, CallbackHandler callbackHandler, Map 
sharedState, Map options)
      {
          this.subject = subject;
          this.callbackHandler = callbackHandler;
          this.sharedState = sharedState;
          this.options = options;
  
          /* Check for password sharing options. Any non-null value for
              password_stacking sets useFirstPass as this module has no way to
              validate any shared password.
           */
          String passwordStacking = (String) options.get("password-stacking");
          if( passwordStacking != null && 
passwordStacking.equalsIgnoreCase("useFirstPass") )
                useFirstPass = true;
      }
  
      /** Looks for javax.security.auth.login.name and 
javax.security.auth.login.password
          values in the sharedState map if the useFirstPass option was true and returns
          true if they exist. If they do not or are null this method returns false.
      */
      public boolean login() throws LoginException
      {
          // If useFirstPass is true, look for the shared password
          if( useFirstPass == true )
          {
              try
              {
                  Object identity = sharedState.get("javax.security.auth.login.name");
                  Object credential = 
sharedState.get("javax.security.auth.login.password");
                  if( identity != null && credential != null )
                        return true;
                  // Else, fall through and perform the login
              }
              catch(Exception e)
              {   // Dump the exception and continue
                  e.printStackTrace();
              }
          }
  
          return false;
      }
  
      /** Method to commit the authentication process (phase 2).
          It adds the getIdentity() value to the subject getPrincipals() Set.
          It also adds the members of each Group returned by getRoleSets()
          to the subject getPrincipals() Set.
  
       @see javax.security.auth.Subject;
       @see java.security.acl.Group;
       @return true always.
      */
      public boolean commit() throws LoginException
      {
          Set principals = subject.getPrincipals();
          Principal identity = getIdentity();
          principals.add(identity);
          Group[] roleSets = getRoleSets();
          for(int g = 0; g < roleSets.length; g ++)
          {
              Group group = roleSets[g];
              String name = group.getName();
              Group subjectGroup = createGroup(name, principals);
              if( subjectGroup instanceof NestableGroup )
              {
                  /* A NestableGroup only allows Groups to be added to it so we
                   need to add a SimpleGroup to subjectRoles to contain the roles
                  */
                  SimpleGroup tmp = new SimpleGroup("Roles");
                  subjectGroup.addMember(tmp);
                  subjectGroup = tmp;
              }
              // Copy the group members to the Subject group
              Enumeration members = group.members();
              while( members.hasMoreElements() )
              {
                  Principal role = (Principal) members.nextElement();
                  subjectGroup.addMember(role);
              }
          }
          return true;
      }
  
      /** Method to abort the authentication process (phase 2).
      @return true alaways
      */
      public boolean abort() throws LoginException
      {
          return true;
      }
  
      /** Remove the user identity and roles added to the Subject during commit.
      @return true always.
      */
        public boolean logout() throws LoginException
        {
          // Remove the user identity
          Principal identity = getIdentity();
          Set principals = subject.getPrincipals();
                principals.remove(identity);
          // Remove any added Groups...
                return true;
        }
  //--- End LoginModule interface methods
  
  // --- Protected methods
  
      /** Overriden by subclasses to return the Principal that corresponds to
       the user primary identity.
      */
      abstract protected Principal getIdentity();
      /** 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 
      */
      abstract protected Group[] getRoleSets() throws LoginException;
  
      protected boolean getUseFirstPass()
      {
          return useFirstPass;
      }
  
      /** Find or create a Group with the given name. Subclasses should use this
      method to locate the 'Roles' group or create additional types of groups.
      @return A named Group from the principals set.
      */
      protected Group createGroup(String name, Set principals)
      {
          Group roles = null;
          Iterator iter = principals.iterator();
          while( iter.hasNext() )
          {
              Object next = iter.next();
              if( (next instanceof Group) == false )
                  continue;
              Group grp = (Group) next;
              if( grp.getName().equals(name) )
              {
                  roles = grp;
                  break;
              }
          }
          // If we did not find a group create one
          if( roles == null )
          {
              roles = new NestableGroup(name);
              principals.add(roles);
          }
          return roles;
      }
  }
  
  
  
  1.1                  
jbosssx/src/main/org/jboss/security/auth/spi/DatabaseServerLoginModule.java
  
  Index: DatabaseServerLoginModule.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.security.auth.spi;
  
  import java.security.acl.Group;
  import java.util.Enumeration;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.Set;
  import java.util.Vector;
  import java.sql.Connection;
  import java.sql.PreparedStatement;
  import java.sql.ResultSet;
  import java.sql.SQLException;
  import javax.naming.InitialContext;
  import javax.naming.NamingException;
  import javax.sql.DataSource;
  import javax.security.auth.Subject;
  import javax.security.auth.callback.CallbackHandler;
  import javax.security.auth.login.LoginException;
  import javax.security.auth.login.FailedLoginException;
  
  import org.jboss.security.SimpleGroup;
  import org.jboss.security.SimplePrincipal;
  import org.jboss.security.auth.spi.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.1 $
  */
  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)
      {
          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();
      }
  
       /** 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
       */
      protected String getUsersPassword() throws LoginException
      {
          String username = getUsername();
          String password = null;
          Connection conn = null;
  
          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();
                  }
                  catch (Exception 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());
          }
          finally
          {
              if( conn != null )
              {
                  try
                  {
                      conn.close();
                  }
                  catch (Exception ex)
                  {
                  }
              }
          }
  
          Group[] roleSets = new Group[setsMap.size()];
          setsMap.values().toArray(roleSets);
          return roleSets;
      }
  
      /** 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.1                  
jbosssx/src/main/org/jboss/security/auth/spi/IdentityLoginModule.java
  
  Index: IdentityLoginModule.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.security.auth.spi;
  
  import java.security.Principal;
  import java.security.acl.Group;
  import java.util.ArrayList;
  import java.util.Map;
  import java.util.StringTokenizer;
  import javax.security.auth.Subject;
  import javax.security.auth.callback.CallbackHandler;
  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.auth.spi.AbstractServerLoginModule;
  
  /** A simple login module that simply associates the principal specified
  in the module options with any subject authenticated against the module.
  The type of Principal class used is org.jboss.security.SimplePrincipal.
  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.1 $
  */
  public class IdentityLoginModule extends AbstractServerLoginModule
  {
      private String principalName;
      private String roleNames;
  
      /** Creates new IdentityLoginModule */
      public IdentityLoginModule()
      {
      }
     
      public void initialize(Subject subject, CallbackHandler handler, Map 
sharedState, Map options)
      {
          super.initialize(subject, handler, sharedState, options);
          principalName = (String) options.get("principal");
          if( principalName == null )
              principalName = "guest";
          roleNames = (String) options.get("roles");
      }
  
      public boolean login() throws LoginException
      {
          if( super.login() == true )
              return true;
  
          Principal principal = new SimplePrincipal(principalName);
          subject.getPrincipals().add(principal);
          // Put the principal into the sharedState map
          sharedState.put("javax.security.auth.login.name", principal);
          return true;
      }
  
      protected Principal getIdentity()
      {
          Principal principal = new SimplePrincipal(principalName);
          return principal;
      }
      protected Group[] getRoleSets() throws LoginException
      {
          SimpleGroup roles = new SimpleGroup("Roles");
          Group[] roleSets = {roles};
          if( roleNames != null )
          {
              StringTokenizer tokenizer = new StringTokenizer(roleNames, ",");
              while( tokenizer.hasMoreTokens() )
              {
                  String roleName = tokenizer.nextToken();
                  roles.addMember(new SimplePrincipal(roleName));
              }
          }
          return roleSets;
      }
  }
  
  
  
  1.1                  
jbosssx/src/main/org/jboss/security/auth/spi/LdapLoginModule.java
  
  Index: LdapLoginModule.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.security.auth.spi;
  
  import java.security.Principal;
  import java.security.acl.Group;
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.Map.Entry;
  import java.util.Properties;
  import javax.naming.Context;
  import javax.naming.NamingEnumeration;
  import javax.naming.NamingException;
  import javax.naming.directory.Attribute;
  import javax.naming.directory.Attributes;
  import javax.naming.directory.BasicAttributes;
  import javax.naming.directory.SearchResult;
  import javax.naming.ldap.InitialLdapContext;
  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.FailedLoginException;
  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.auth.callback.ObjectCallback;
  import org.jboss.security.auth.spi.AbstractServerLoginModule;
  
  /** An implementation of LoginModule that authenticates against an LDAP server
  using JNDI based on the configuration properties.
  
  The LoginModule options include whatever options your LDAP JNDI provider
  support. Examples of standard property names are:
  Context.INITIAL_CONTEXT_FACTORY = "java.naming.factory.initial"
  Context.SECURITY_PROTOCOL = "java.naming.security.protocol"
  Context.PROVIDER_URL = "java.naming.provider.url"
  Context.SECURITY_AUTHENTICATION = "java.naming.security.authentication"
  
  The Context.SECURITY_PRINCIPAL is set to the distinguished name of the user
  as obtained by the callback handler and the Context.SECURITY_CREDENTIALS
  property is either set to the String password or Object credential depending
  on the useObjectCredential option.
  
  Additional module properties include:
  principalDNPrefix, principalDNSuffix : A prefix and suffix to add to the
      username when forming the user distiguished name. This is useful if you
      prompt a user for a username and you don't want them to have to enter the
      fully distinguished name. Using this property and principalDNSuffix the
      userDN will be formed as:
  <code>String userDN = principalDNPrefix + username + principalDNSuffix;</code>
  
  useObjectCredential : indicates that the credential should be obtained as
  an opaque Object using the org.jboss.security.plugins.ObjectCallback type
  of Callback rather than as a char[] password using a JAAS PasswordCallback.
  
  rolesCtxDN : The distinguished name to the context to search for user roles.
  roleAttributeName : The name of the attribute that contains the user roles
  uidAttributeName : The name of the attribute that in the object containing
   the user roles that corresponds to the userid. This is used to locate the
   user roles.
  
  A sample login config:
   testLdap {
      org.jboss.security.plugins.samples.LdapLoginModule required
          java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
          principalDNPrefix=uid=
          uidAttributeID=userid
          roleAttributeID=rolenames
          principalDNSuffix=,ou=People,o=displayscape.com
          rolesCtxDN=ou=Users,cn=Project1,ou=Projects,o=displayscape.com
          java.naming.provider.url=ldap://siren-int/
          java.naming.security.authentication=simple
   };
  
  @author [EMAIL PROTECTED]
  @version $Revision: 1.1 $
  */
  public class LdapLoginModule extends AbstractServerLoginModule
  {
      private static final String USE_OBJECT_CREDENTIAL_OPT = "useObjectCredential";
      private static final String PRINCIPAL_DN_PREFIX_OPT = "principalDNPrefix";
      private static final String PRINCIPAL_DN_SUFFIX_OPT = "principalDNSuffix";
      private static final String ROLES_CTX_DN_OPT = "rolesCtxDN";
      private static final String UID_ATTRIBUTE_ID_OPT = "uidAttributeID";
      private static final String ROLE_ATTRIBUTE_ID_OPT = "roleAttributeID";
  
      public LdapLoginModule()
      {
      }
  
        private transient String username;
        private transient Object credential;
      private transient SimpleGroup userRoles = new SimpleGroup("Roles");
  
        public boolean login() throws javax.security.auth.login.LoginException
        {
                System.out.println("LdapLoginModule.login");
                if( super.login() == true )
          {
              // Use the shared username and password
              Object identity = sharedState.get("javax.security.auth.login.name");
              credential = sharedState.get("javax.security.auth.login.password");
              username = identity.toString();
          }
          else
          {
              // Use the callbackHander to get username and password
              getUsernamePassword();
          }
  
                // Validate the user & password by creating an LDAP initial context.
                try
                {
                        createLdapInitContext();
                }
                catch(NamingException e)
                {
                        throw new FailedLoginException(e.toString(true));
                }
                catch(Throwable t)
                {
                        throw new FailedLoginException("Unexpected failure: 
"+t.getMessage());
                }
                return true;
        }
        
      protected Principal getIdentity()
      {
          return new SimplePrincipal(username);
      }
      protected Group[] getRoleSets() throws LoginException
      {
          Group[] roleSets = {userRoles};
          return roleSets;
      }
  
      private void getUsernamePassword() throws LoginException
      {
          if( callbackHandler == null )
                        throw new LoginException("Error: no CallbackHandler 
available");
  
                NameCallback ncallback = new NameCallback("LdapLoginModule username: 
");
                PasswordCallback pcallback = new PasswordCallback("LdapLoginModule 
password: ", false);
          ObjectCallback ocallback = new ObjectCallback("LdapLoginModule credential: 
");
                try
                {
              Object useObjectCred = options.get(USE_OBJECT_CREDENTIAL_OPT);
              if( useObjectCred == null || 
Boolean.valueOf(useObjectCred.toString()).booleanValue() == false )
              {
                  Callback[] callbacks = {ncallback, pcallback};
                  callbackHandler.handle(callbacks);
                  char[] tmpPassword = pcallback.getPassword();
                  credential = new String(tmpPassword);
                  pcallback.clearPassword();
              }
              else
              {
                  Callback[] callbacks = {ncallback, ocallback};
                  callbackHandler.handle(callbacks);
                  credential = ocallback.getCredential();
              }
                        username = ncallback.getName();
                }
                catch(java.io.IOException ioe)
                {
                        throw new LoginException(ioe.toString());
                }
                catch(UnsupportedCallbackException uce)
                {
                        throw new LoginException("Error: " + 
uce.getCallback().toString());
                }
      }
  
        private void createLdapInitContext() throws NamingException
        {
                Properties env = new Properties();
          // Map all option into the JNDI InitialLdapContext env
          Iterator iter = options.entrySet().iterator();
          while( iter.hasNext() )
          {
              Entry entry = (Entry) iter.next();
              env.put(entry.getKey(), entry.getValue());
          }
  
          // Set defaults for key values if they are missing
                String factoryName = env.getProperty(Context.INITIAL_CONTEXT_FACTORY);
                if( factoryName == null )
          {
                        factoryName = "com.sun.jndi.ldap.LdapCtxFactory";
              env.setProperty(Context.INITIAL_CONTEXT_FACTORY, factoryName);
          }
          String authType = env.getProperty(Context.SECURITY_AUTHENTICATION);
          if( authType == null )
              env.setProperty(Context.SECURITY_AUTHENTICATION, "simple");
                String protocol = env.getProperty(Context.SECURITY_PROTOCOL);
                String providerURL = (String) options.get(Context.PROVIDER_URL);
                if( providerURL == null )
                        providerURL = "ldap://localhost:" + ((protocol != null && 
protocol.equals("ssl")) ? "389" : "636");
                String principalDNPrefix = (String) 
options.get(PRINCIPAL_DN_PREFIX_OPT);
                if( principalDNPrefix == null )
                        principalDNPrefix="";
                String principalDNSuffix = (String) 
options.get(PRINCIPAL_DN_SUFFIX_OPT);
                if( principalDNSuffix == null )
                        principalDNSuffix="";
                String userDN = principalDNPrefix + username + principalDNSuffix;
                env.setProperty(Context.PROVIDER_URL, providerURL);
                env.setProperty(Context.SECURITY_PRINCIPAL, userDN);
                env.put(Context.SECURITY_CREDENTIALS, credential);
                System.out.println("Logging into LDAP server, env="+env);
                InitialLdapContext ctx = new InitialLdapContext(env, null);
                System.out.println("Logged into LDAP server, "+ctx);
          // Query the user's roles...
          String rolesCtxDN = (String) options.get(ROLES_CTX_DN_OPT);
          if( rolesCtxDN != null )
          {
              String uidAttrName = (String) options.get(UID_ATTRIBUTE_ID_OPT);
              if( uidAttrName == null )
                  uidAttrName = "uid";
              String roleAttrName = (String) options.get(ROLE_ATTRIBUTE_ID_OPT);
              if( roleAttrName == null )
                  roleAttrName = "roles";
              BasicAttributes matchAttrs = new BasicAttributes(true); 
              matchAttrs.put(uidAttrName, username);
              String[] roleAttr = {roleAttrName};
              try
              {
                  NamingEnumeration answer = ctx.search(rolesCtxDN, matchAttrs, 
roleAttr);
                  while( answer.hasMore() )
                  {
                      SearchResult sr = (SearchResult) answer.next();
                      Attributes attrs = sr.getAttributes();
                      Attribute roles = attrs.get(roleAttrName);
                      for(int r = 0; r < roles.size(); r ++)
                      {
                          Object value = roles.get(r);
                          String roleName = value.toString();
                          userRoles.addMember(new SimplePrincipal(roleName));
                      }
                  }
              }
              catch(NamingException e)
              {
              }
          }
          // Close the context to release the connection
                ctx.close();
        }
  }
  
  
  
  1.1                  
jbosssx/src/main/org/jboss/security/auth/spi/SimpleServerLoginModule.java
  
  Index: SimpleServerLoginModule.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.security.auth.spi;
  
  import java.security.Principal;
  import java.security.acl.Group;
  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.auth.spi.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.1 $
  */
  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;
      }
  
      protected boolean validatePassword(String inputPassword, String expectedPassword)
      {
          boolean isValid = false;
          if( inputPassword == null )
          {
              guestOnly = true;
              isValid = true;
              user = new SimplePrincipal("guest");
          }
          else
          {
              isValid = inputPassword.equals(expectedPassword);
          }
          return isValid;
      }
  
      /** 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
      {
          Group[] roleSets = {new SimpleGroup("Roles")};
          if( guestOnly == false )
              roleSets[0].addMember(new SimplePrincipal("user"));
          roleSets[0].addMember(new SimplePrincipal("guest"));
          return roleSets;
      }
  
      /** 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/auth/spi/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.auth.spi;
  
  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.auth.spi.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;
  
  }
  
  
  
  1.1                  
jbosssx/src/main/org/jboss/security/auth/spi/UsersRolesLoginModule.java
  
  Index: UsersRolesLoginModule.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.security.auth.spi;
  
  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;
  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.auth.spi.UsernamePasswordLoginModule;
  
  /** 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 UsersRolesLoginModule extends UsernamePasswordLoginModule
  {
    // users+passwords, users+roles
      private Properties _users;   // You might think these should be static. The only 
problem with
      private Properties _roles;   // static attributes is they are shared across the 
VM. So I chose safety
                                   // over performance.
  
      /**
       * Initialize this LoginModule.
       */
      public void initialize(Subject subject, CallbackHandler callbackHandler, Map 
sharedState, Map options)
      {
          super.initialize(subject, callbackHandler, sharedState, options);
          try
          {
  // Load the properties file that contains the list of users and passwords
            LoadUsers();
            LoadRoles();
          }
          catch (Exception e)
          {
            System.out.print("[JAASSecurity] PANIC! Couldn't load users/passwords/role 
files.\n");
            e.printStackTrace();
  // Note that although this exception isn't passed on, _users or _roles will be null
  // so that any call to login will throw a LoginException.
          }
      }
  
      /**
       * Method to authenticate a Subject (phase 1).
       *
       * Most of the changes from the original SimpleServerLoginModule
       * are made in this method. They are:
       * users and passwords read from users.properties file
       * users and roles read from roles.properties file
       *
       * I've also removed the notion of a guest login. If you want to provide 'guest'
       * access to your beans then simply disable security on them.
       *
       */
      public boolean login() throws LoginException
      {
          if (_users == null || _roles == null)
          {
            throw new LoginException("Missing _users or _roles properties file.");
          }
  
          return super.login();
      }
  
      /** 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
      {
          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()
      {
          return _users.getProperty(getUsername(), null);
      }
  
  // 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");
      }
  
      private void LoadRoles() throws IOException
      {
        _roles = LoadProperties("roles.properties");
      }
  
      /**
      * Loads the given properties file and returns a Properties object containing the
      * key,value pairs in that file.
      * The properties files should be in the class path.
      */
      private Properties LoadProperties(String propertiesName) throws IOException
      {
        Properties bundle = null;
        InputStream is 
=Thread.currentThread().getContextClassLoader().getResource(propertiesName).openStream();
  
        if (null != is)
        {
           bundle = new Properties();
           bundle.load(is);
        }
        else
        {
           throw new IOException("Properties file " + propertiesName + " not found");
        }
        return bundle;
      }
  }
  
  
  

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

Reply via email to