User: stark   
  Date: 01/03/05 01:53:36

  Added:       src/main/org/jboss/security/plugins/samples
                        DatabaseServerLoginModule.java
                        IdentityLoginModule.java JaasServerLoginModule.java
                        RolesLoginModule.java SimpleServerLoginModule.java
  Log:
  Initial version of the JBossSX module
  
  Revision  Changes    Path
  1.1                  
jbosssx/src/main/org/jboss/security/plugins/samples/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.plugins.samples;
  
  
  import java.util.Map;
  import java.util.Set;
  import java.util.Arrays;
  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.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;
  
      /**
       * 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");
      }
  
      /**
       * Method to authenticate a Subject (phase 1).
       */
      public boolean login() throws LoginException {
          Callback[] callbacks = new Callback[2];
          char[] password;
          char[] tmpPassword;
          InitialContext initial;
          DataSource ds;
          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");
                  }
                  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");
                  }
                  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) {
              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 {
                      conn.close();
                  } 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;
      }
  
      public boolean logout() throws LoginException {
          return true;
      }
  }
  
  
  
  1.1                  
jbosssx/src/main/org/jboss/security/plugins/samples/IdentityLoginModule.java
  
  Index: IdentityLoginModule.java
  ===================================================================
  
  package org.jboss.security.plugins.samples;
  
  import java.util.Map;
  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.SimplePrincipal;
  
  /** 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.SimplePrincipal
  
  @author [EMAIL PROTECTED]
  @version $Revision: 1.1 $
  */
  public class IdentityLoginModule implements LoginModule
  {
      String principal;
      Subject subject;
      Map sharedState;
  
      /** Creates new IdentityLoginModule */
      public IdentityLoginModule()
      {
      }
     
      public void initialize(Subject subject, CallbackHandler handler, Map 
sharedState, Map options)
      {
          this.subject = subject;
          this.sharedState = sharedState;
          principal = (String) options.get("principal");
          if( principal == null )
              principal = "guest";
      }
  
      public boolean login() throws LoginException
      {
          subject.getPrincipals().add(new SimplePrincipal(principal));
          // Put the username into the sharedState map
          sharedState.put("javax.security.auth.login.name", principal);
          return true;
      }
  
      public boolean commit() throws LoginException
      {
          return true;
      }
  
      public boolean abort() throws LoginException
      {
          return true;
      }
  
      public boolean logout() throws LoginException
      {
          return true;
      }
  }
  
  
  
  1.1                  
jbosssx/src/main/org/jboss/security/plugins/samples/JaasServerLoginModule.java
  
  Index: JaasServerLoginModule.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.util.*;
  import java.io.*;
  
  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.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>
   */
  public class JaasServerLoginModule extends AbstractServerLoginModule
  {
    // 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();
      }
  
      // Polymorphic, used by the abstract base class.
      protected Enumeration getUsersRoles()
      {
        String roles = _roles.getProperty(getUsername());
        return (roles == null ? null : new StringTokenizer(roles, ","));
      }
      protected String getUsersPassword()
      {
          return _users.getProperty(getUsername(), null);
      }
  
  // utility methods
      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;
      }
  }
  
  
  
  
  
  
  
  1.1                  
jbosssx/src/main/org/jboss/security/plugins/samples/RolesLoginModule.java
  
  Index: RolesLoginModule.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.io.InputStream;
  import java.security.acl.Group;
  import java.util.Map;
  import java.util.Properties;
  import java.util.Set;
  import java.util.StringTokenizer;
  
  import javax.security.auth.Subject;
  import javax.security.auth.callback.CallbackHandler;
  import javax.security.auth.callback.Callback;
  import javax.security.auth.login.LoginException;
  import javax.security.auth.spi.LoginModule;
  
  import org.jboss.security.SimpleGroup;
  import org.jboss.security.SimplePrincipal;
  
  /** A role mapping LoginModule. This module loads a roles.properties
  file from the classpath and creates role mappings for a username
  by creating Groups for any username.Roles and username.CallerPrincipal
  entries found in the roles.properties file. The Groups are added
  to the Subject Principals set. This module must be combined with
  a module that does the authentication and passes the username via
  the sharedMap as the javax.security.auth.login.name property.
  
  
  @author [EMAIL PROTECTED]
  @version $Revision: 1.1 $
  */
  public class RolesLoginModule implements LoginModule
  {
      private Subject subject;
      private Map sharedState;
      private Properties roles;
      private Group userRoles;
      private Group callerPrincipal;
  
      public RolesLoginModule()
      {
      }
  
  // --- Begin LoginModule interface methods
      /**
       * Initialize this LoginModule.
       */
      public void initialize(Subject subject, CallbackHandler callbackHandler, Map 
sharedState, Map options)
      {
          this.subject = subject;
          this.sharedState = sharedState;
      }
  
      /** Load the roles.properties file
       */
      public boolean login() throws LoginException
      {
          loadRoles();
          return true;
      }
  
      public boolean commit()
      {
          // Get the username from the shared state
          String username = (String) sharedState.get("javax.security.auth.login.name");
          boolean committed = false;
  
          if( username != null )
          {
              committed = true;
              Set principals = subject.getPrincipals();
              // Get the username.Roles for the 'Roles' group
              String key = username + ".Roles";
              userRoles = createGroup(key, "Roles");
              principals.add(userRoles);
  
              // Get the username.CallerPrincipal for the 'CallerPrincipal' group
              key = username + ".CallerPrincipal";
              callerPrincipal = createGroup(key, "CallerPrincipal");
              principals.add(callerPrincipal);
          }
          return committed;
      }
  
      public boolean abort()
      {
          roles = null;
          userRoles = null;
          callerPrincipal = null;
          return true;
      }
  
      public boolean logout()
      {
          Set principals = subject.getPrincipals();
          principals.remove(userRoles);
          principals.remove(callerPrincipal);
  
          return true;
      }
  // --- End LoginModule interface methods
  
      private Group createGroup(String key, String name)
      {
          String value = roles.getProperty(key);
          Group group = new SimpleGroup(name);
          if( value != null )
          {
              StringTokenizer tokenizer = new StringTokenizer(value, ",");
              while( tokenizer.hasMoreTokens() )
              {
                  String token = tokenizer.nextToken();
                  SimplePrincipal p = new SimplePrincipal(token);
                  group.addMember(p);
              }
          }
          return group;
      }
  
      /** Load the roles.properties from the current thread class loader.
       */
      private void loadRoles() throws LoginException
      {
          ClassLoader loader = Thread.currentThread().getContextClassLoader();
          InputStream is = loader.getResourceAsStream("roles.properties");
          if( is == null )
              throw new LoginException("Failed to find roles.properties resource");
          roles = new Properties();
          try
          {
              roles.load(is);
          }
          catch(IOException e)
          {
              throw new LoginException("Failed to load roles.properties, 
ioe="+e.getMessage());
          }
      }
  
  }
  
  
  
  1.1                  
jbosssx/src/main/org/jboss/security/plugins/samples/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.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 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;
      }
  
      /**
       * 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");
          }
          if (_password != null && !(new String(_password)).equals(_username)) {
              throw new FailedLoginException("Password Incorrect");
          }
          return true;
      }
            
      /**
       * 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).
       */
      public boolean abort() throws LoginException {
          _username = null;
          if (_password != null) {
              for (int i = 0; i < _password.length; i++)
              _password[i] = ' ';
              _password = null;
          }
          return true;
      }
  
      public boolean logout() throws LoginException {
          return true;
      }
  }
  
  
  

Reply via email to