User: oleg    
  Date: 00/10/16 11:00:19

  Added:       src/main/org/jboss/security ClientLoginModule.java
                        JaasSecurityManager.java
                        JaasSecurityManagerService.java
                        JaasSecurityManagerServiceMBean.java
                        SimpleServerLoginModule.java
  Log:
  JAAS-based security is initiated
  
  Revision  Changes    Path
  1.1                  jboss/src/main/org/jboss/security/ClientLoginModule.java
  
  Index: ClientLoginModule.java
  ===================================================================
  /*
   * jBoss, the OpenSource EJB server
   *
   * Distributable under GPL license.
   * See terms of license at gnu.org.
   */
   
  package org.jboss.security;
  
  
  import java.util.Map;
  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.spi.LoginModule;
  import org.jboss.system.SecurityAssociation;
  import org.jboss.system.SimplePrincipal;
  
  
  public class ClientLoginModule 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");
          }
          return true;
      }
            
      /**
       * Method to commit the authentication process (phase 2).
       */
      public boolean commit() throws LoginException {
          SecurityAssociation.setPrincipal(new SimplePrincipal(_username));
          SecurityAssociation.setCredential(_password);
          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;
      }
  }
  
  
  
  1.1                  jboss/src/main/org/jboss/security/JaasSecurityManager.java
  
  Index: JaasSecurityManager.java
  ===================================================================
  /*
   * jBoss, the OpenSource EJB server
   *
   * Distributable under GPL license.
   * See terms of license at gnu.org.
   */
   
  package org.jboss.security;
  
  import java.io.File;
  import java.net.URL;
  import java.rmi.server.UnicastRemoteObject;
  import java.rmi.RemoteException;
  import java.rmi.ServerException;
  import java.util.Set;
  import java.util.HashMap;
  import java.util.Arrays;
  import java.util.Iterator;
  
  import java.security.Principal;
  import javax.security.auth.Subject;
  import javax.security.auth.login.LoginContext;
  import javax.security.auth.callback.CallbackHandler;
  import javax.security.auth.callback.Callback;
  import javax.security.auth.callback.NameCallback;
  import javax.security.auth.callback.PasswordCallback;
  import javax.security.auth.callback.UnsupportedCallbackException;
  
  import javax.naming.InitialContext;
  import javax.naming.Context;
  import javax.naming.Reference;
  import javax.naming.Name;
  import javax.naming.spi.ObjectFactory;
  
  import javax.management.MBeanServer;
  import javax.management.ObjectName;
  
  import javax.transaction.TransactionManager;
  
  import org.jboss.logging.Log;
  import org.jboss.util.ServiceMBeanSupport;
  
  import org.jboss.system.EJBSecurityManager;
  import org.jboss.system.RealmMapping;
  
  /**
   * The EJBSecurityManager is responsible for validating credentials
   * associated with principals. Right now it is a "demo" that just
   * ensures name == credential
   *      
   * @see EJBSecurityManager
   * @author <a href="[EMAIL PROTECTED]">Oleg Nitz</a>
   */
  public class JaasSecurityManager implements EJBSecurityManager, RealmMapping {
      
      /**
       * Security manager name.
       */
      private final String _smName;
      
      /**
       * Maps an original principal to authenticated client credential, aka password.
       * Should be a time or size limited cache for better scalability.
       * This is a master cache, when a principal is removed from this cache,
       * the related entries from all other caches should be removed too.
       */
      private final HashMap _passwords = new HashMap();
  
      /**
       * Maps original principal to principal for the bean.
       */
      private final HashMap _principals = new HashMap();
      
      /**
       * Maps original principal to Set of roles for the bean.
       */
      private final HashMap _roles = new HashMap();
  
      /**
       * @param smName The name of the security manager
       */
      public JaasSecurityManager(String smName) {
          _smName = smName;
      }
      
      public boolean isValid(Principal principal, Object credential) {
          char[] authenticated;
  
          authenticated = (char[]) _passwords.get(principal);
          if (authenticated == null) {
              return authenticate(_smName, principal, credential);
          } else  {
              return (credential instanceof char[]) &&
                      Arrays.equals(authenticated, (char[]) credential);
          }
      }
      
      public Principal getPrincipal(Principal principal) {
          Principal result;
          result = (Principal) _principals.get(principal);
          if (result == null) {
              if (authenticate(_smName, principal, null)) {
                  result = (Principal) _principals.get(principal);
              }
          }
          return result;
      }
  
      public boolean doesUserHaveRole(Principal principal, Set roleNames)
      {
          Set roles;
          Iterator it;
  
          if (roleNames == null)
              return true;
          roles = (Set) _roles.get(principal);
          if (roles == null) {
              if (!authenticate(_smName, principal, null)) {
                  return false;
              }
          } 
          it = roleNames.iterator();
          while (it.hasNext()) {
              if (roles.contains(it.next())) {
                  return true;
              }
          }
          return false;
      }
      
      
      /**
       * @param bean The bean name
       * @param userName The user name
       * @param password The password
       * @return false on failure, true on success.
       */
      private boolean authenticate(String beanName, Principal principal, Object 
credential) {
          LoginContext lc;
          Subject subj;
          final String userName = principal.getName();
          final char[] password = (char[]) credential;
          Iterator it;
          Principal beanPrincipal;
  
          try {
              lc = new LoginContext(beanName, new CallbackHandler() {
                  public void handle(Callback[] callbacks) throws 
UnsupportedCallbackException {
                      for (int i = 0; i < callbacks.length; i++) {
                          if (callbacks[i] instanceof NameCallback) {
                              ((NameCallback) callbacks[i]).setName(userName);
                          } else if (callbacks[i] instanceof PasswordCallback) {
                              ((PasswordCallback) callbacks[i]).setPassword(password);
                          } else {
                              throw new UnsupportedCallbackException(callbacks[i], 
"Unrecognized Callback");
                          }
                      }
                  }
              });
              lc.login();
              _passwords.put(principal, password);
              subj = lc.getSubject();
              beanPrincipal = principal;
              it = subj.getPrincipals().iterator();
              if (it.hasNext()) {
                  beanPrincipal = (Principal) it.next();
              }
              _principals.put(principal, beanPrincipal);
              _roles.put(principal, subj.getPublicCredentials());
              return true;
          } catch (Exception ex) {
              return false;
          } 
      }    
  }
  
  
  
  
  1.1                  
jboss/src/main/org/jboss/security/JaasSecurityManagerService.java
  
  Index: JaasSecurityManagerService.java
  ===================================================================
  /*
   * jBoss, the OpenSource EJB server
   *
   * Distributable under GPL license.
   * See terms of license at gnu.org.
   */
   
  package org.jboss.security;
  
  import java.io.File;
  import java.net.URL;
  import java.rmi.server.UnicastRemoteObject;
  import java.rmi.RemoteException;
  import java.rmi.ServerException;
  import java.util.Hashtable;
  import java.util.ArrayList;
  import java.util.Iterator;
  
  import javax.naming.InitialContext;
  import javax.naming.Context;
  import javax.naming.Reference;
  import javax.naming.Name;
  import javax.naming.spi.ObjectFactory;
  import javax.naming.CommunicationException;
  
  import javax.management.MBeanServer;
  import javax.management.ObjectName;
  
  import javax.security.auth.login.Configuration;
  
  import org.jboss.logging.Log;
  import org.jboss.util.ServiceMBeanSupport;
  
  import org.jboss.system.EJBSecurityManager;
  
  /**
   *   This is a JMX service which manages the EJBSecurityManager.
   *    The service creates it and binds a Reference to it into JNDI.
   *    The EJBSecurityManager is responsible for validating credentials
   *    associated with principals.
   *      
   *   @see EJBSecurityManager
   *   @author <a href="[EMAIL PROTECTED]">Oleg Nitz</a>
   */
  public class JaasSecurityManagerService
          extends ServiceMBeanSupport
          implements JaasSecurityManagerServiceMBean, ObjectFactory {
  
      private static String JNDI_NAME = "jaas";
      
      private static String JNDI_SM_CONTEXT_NAME = "jaas.sm";
  
      MBeanServer server;
          
      // smJndiNames and smContext must be static: they are used by
      // ObjectFactory instances
      private static ArrayList smJndiNames = new ArrayList();
  
      private static Context smContext;
  
      public String getName() {
          return "JAAS Security Manager";
      }
     
      protected ObjectName getObjectName(MBeanServer server, ObjectName name)
              throws javax.management.MalformedObjectNameException {
          this.server = server;
          return new ObjectName(OBJECT_NAME);
      }
      
      protected void initService() throws Exception {
          InitialContext ic = new InitialContext();
  
          // Bind reference to SM in JNDI
          Reference ref = new Reference(JaasSecurityManager.class.getName(), 
getClass().getName(), null);
          ic.bind(JNDI_NAME, ref);
          if (smContext == null) {
              smContext = ic.createSubcontext(JNDI_SM_CONTEXT_NAME);
          }
      }
      
      protected void startService()
              throws Exception {
      }
     
      protected void stopService() {
          InitialContext ic;
          try {
              ic = new InitialContext();
              // Remove all SMs from JNDI
              if (smContext != null) {
                  for (Iterator it = smJndiNames.iterator(); it.hasNext(); ) {
                      smContext.unbind((String) it.next());
                      it.remove();
                  }
                  ic.destroySubcontext(JNDI_SM_CONTEXT_NAME);
                  smContext = null;
              }
              ic.unbind(JNDI_NAME);
          } catch (CommunicationException e) {
              // Do nothing, the naming services is already stopped   
          } catch (Exception e) {
              log.exception(e);
          }
      }
      
      // ObjectFactory implementation ----------------------------------
      public Object getObjectInstance(Object obj,
                                      Name name,
                                      Context nameCtx,
                                      Hashtable environment)
              throws Exception {
          String smName = name.get(name.size() - 1);
  
          if (!smJndiNames.contains(smName)) {
              smContext.bind(smName, new JaasSecurityManager(smName));
              smJndiNames.add(smName);
          }
          return smContext;
      }
  }
  
  
  
  
  1.1                  
jboss/src/main/org/jboss/security/JaasSecurityManagerServiceMBean.java
  
  Index: JaasSecurityManagerServiceMBean.java
  ===================================================================
  /*
   * jBoss, the OpenSource EJB server
   *
   * Distributable under GPL license.
   * See terms of license at gnu.org.
   */
  
  package org.jboss.security;
  
  public interface JaasSecurityManagerServiceMBean
      extends org.jboss.util.ServiceMBean
  {
     // Constants -----------------------------------------------------
     public static final String OBJECT_NAME = ":service=JaasSecurityManager";
      
     // Public --------------------------------------------------------
  }
  
  
  
  1.1                  jboss/src/main/org/jboss/security/SimpleServerLoginModule.java
  
  Index: SimpleServerLoginModule.java
  ===================================================================
  /*
   * jBoss, the OpenSource EJB server
   *
   * Distributable under GPL license.
   * See terms of license at gnu.org.
   */
   
  package org.jboss.security;
  
  
  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;
  import org.jboss.system.SecurityAssociation;
  import org.jboss.system.SimplePrincipal;
  
  
  /**
   * 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