[jboss-cvs] JBoss Messaging SVN: r5889 - in trunk: tests/src/org/jboss/messaging/tests/unit/core/security/impl and 1 other directory.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Wed Feb 18 05:21:15 EST 2009


Author: jmesnil
Date: 2009-02-18 05:21:15 -0500 (Wed, 18 Feb 2009)
New Revision: 5889

Added:
   trunk/src/main/org/jboss/messaging/integration/security/JAASSecurityManager.java
   trunk/tests/src/org/jboss/messaging/tests/unit/core/security/impl/JAASSecurityManagerTest.java
Log:
JBMESSAGING-1326: JAASSecurityManager

* added a JAASSecurityManager (using only JAAS API) 

Added: trunk/src/main/org/jboss/messaging/integration/security/JAASSecurityManager.java
===================================================================
--- trunk/src/main/org/jboss/messaging/integration/security/JAASSecurityManager.java	                        (rev 0)
+++ trunk/src/main/org/jboss/messaging/integration/security/JAASSecurityManager.java	2009-02-18 10:21:15 UTC (rev 5889)
@@ -0,0 +1,285 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.messaging.integration.security;
+
+import static org.jboss.messaging.core.security.CheckType.CREATE;
+import static org.jboss.messaging.core.security.CheckType.READ;
+import static org.jboss.messaging.core.security.CheckType.WRITE;
+
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.jboss.messaging.core.logging.Logger;
+import org.jboss.messaging.core.security.CheckType;
+import org.jboss.messaging.core.security.JBMSecurityManager;
+import org.jboss.messaging.core.security.Role;
+import org.jboss.messaging.core.server.MessagingComponent;
+
+/**
+ * This implementation delegates to the JAAS security interfaces.
+ * 
+ * @author <a href="ataylor at redhat.com">Andy Taylor</a>
+ * @author <a href="tim.fox at jboss.com">Tim Fox</a>
+ * @author <a href="jmesnil at redhat.com">Jeff Mesnil</a>
+ * @author <a href="on at ibis.odessa.ua">Oleg Nitz</a>
+ * @author Scott.Stark at jboss.org
+ */
+public class JAASSecurityManager implements JBMSecurityManager, MessagingComponent
+{
+   private static final Logger log = Logger.getLogger(JAASSecurityManager.class);
+
+   // Static --------------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   private boolean trace = log.isTraceEnabled();
+
+   private String configurationName;
+
+   private boolean started;
+
+   private CallbackHandler callbackHandler;
+
+   private Configuration config;
+
+   // JBMSecurityManager implementation -----------------------------
+
+   public boolean validateUser(final String user, final String password)
+   {
+      try
+      {
+         getAuthenticatedSubject(user, password);
+         return true;
+      }
+      catch (LoginException e1)
+      {
+         return false;
+      }
+   }
+
+   public boolean validateUserAndRole(final String user,
+                                      final String password,
+                                      final Set<Role> roles,
+                                      final CheckType checkType)
+   {
+      Subject localSubject = null;
+      try
+      {
+         localSubject = getAuthenticatedSubject(user, password);
+      }
+      catch (LoginException e1)
+      {
+         return false;
+      }
+
+      boolean authenticated = true;
+
+      if (localSubject != null)
+      {
+         Set<Principal> rolePrincipals = getRolePrincipals(checkType, roles);
+
+         // authenticated = realmMapping.doesUserHaveRole(principal, rolePrincipals);
+
+         boolean hasRole = false;
+         // check that the caller is authenticated to the current thread
+
+         // Check the caller's roles
+         Group subjectRoles = getSubjectRoles(localSubject);
+         if (subjectRoles != null)
+         {
+            Iterator<Principal> iter = rolePrincipals.iterator();
+            while (!hasRole && iter.hasNext())
+            {
+               Principal role = iter.next();
+               hasRole = subjectRoles.isMember(role);
+            }
+         }
+
+         authenticated = hasRole;
+
+         if (trace)
+         {
+            log.trace("user " + user + (authenticated ? " is " : " is NOT ") + "authorized");
+         }
+      }
+      return authenticated;
+   }
+
+   // MessagingComponent implementation -----------------------------
+
+   /**
+    * lifecycle method, needs to be called
+    *
+    * @throws Exception
+    */
+   public synchronized void start() throws Exception
+   {
+      if (started)
+      {
+         return;
+      }
+
+      started = true;
+   }
+
+   public synchronized void stop()
+   {
+      if (!started)
+      {
+         return;
+      }
+      started = false;
+   }
+
+   public synchronized boolean isStarted()
+   {
+      return started;
+   }
+
+   private Subject getAuthenticatedSubject(final String user, final String password) throws LoginException
+   {
+      SimplePrincipal principal = user == null ? null : new SimplePrincipal(user);
+
+      char[] passwordChars = null;
+
+      if (password != null)
+      {
+         passwordChars = password.toCharArray();
+      }
+
+      Subject subject = new Subject();
+
+      subject.getPrincipals().add(principal);
+      subject.getPrivateCredentials().add(passwordChars);
+
+      LoginContext lc = new LoginContext(configurationName, subject, callbackHandler, config);
+      lc.login();
+      return lc.getSubject();
+   }
+
+   private Group getSubjectRoles(Subject subject)
+   {
+      Set<Group> subjectGroups = subject.getPrincipals(Group.class);
+      Iterator<Group> iter = subjectGroups.iterator();
+      Group roles = null;
+      while (iter.hasNext())
+      {
+         Group grp = iter.next();
+         String name = grp.getName();
+         if (name.equals("Roles"))
+         {
+            roles = grp;
+         }
+      }
+      return roles;
+   }
+
+   private Set<Principal> getRolePrincipals(final CheckType checkType, final Set<Role> roles)
+   {
+      Set<Principal> principals = new HashSet<Principal>();
+      for (Role role : roles)
+      {
+         if ((checkType.equals(CREATE) && role.isCheckType(CREATE))
+          || (checkType.equals(WRITE) && role.isCheckType(WRITE))
+          || (checkType.equals(READ) && role.isCheckType(READ)))
+         {
+            principals.add(new SimplePrincipal(role.getName()));
+         }
+      }
+      return principals;
+   }
+
+   // Public --------------------------------------------------------
+
+   public void setConfigurationName(String configurationName)
+   {
+      this.configurationName = configurationName;
+   }
+
+   public void setCallbackHandler(CallbackHandler handler)
+   {
+      this.callbackHandler = handler;
+   }
+
+   public void setConfiguration(Configuration config)
+   {
+      this.config = config;
+   }
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+   public static class SimplePrincipal implements Principal, java.io.Serializable
+   {
+      private static final long serialVersionUID = 1L;
+
+      private String name;
+
+      public SimplePrincipal(String name)
+      {
+         this.name = name;
+      }
+
+      /** Compare this SimplePrincipal's name against another Principal
+      @return true if name equals another.getName();
+       */
+      public boolean equals(Object another)
+      {
+         if (!(another instanceof Principal))
+            return false;
+         String anotherName = ((Principal)another).getName();
+         boolean equals = false;
+         if (name == null)
+            equals = anotherName == null;
+         else
+            equals = name.equals(anotherName);
+         return equals;
+      }
+
+      public int hashCode()
+      {
+         return (name == null ? 0 : name.hashCode());
+      }
+
+      public String toString()
+      {
+         return name;
+      }
+
+      public String getName()
+      {
+         return name;
+      }
+   }
+
+}

Added: trunk/tests/src/org/jboss/messaging/tests/unit/core/security/impl/JAASSecurityManagerTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/core/security/impl/JAASSecurityManagerTest.java	                        (rev 0)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/core/security/impl/JAASSecurityManagerTest.java	2009-02-18 10:21:15 UTC (rev 5889)
@@ -0,0 +1,198 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.messaging.tests.unit.core.security.impl;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+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.UnsupportedCallbackException;
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
+import javax.security.auth.spi.LoginModule;
+
+import junit.framework.TestCase;
+
+import org.jboss.messaging.core.security.CheckType;
+import org.jboss.messaging.core.security.Role;
+import org.jboss.messaging.integration.security.JAASSecurityManager;
+import org.jboss.security.SimpleGroup;
+
+/**
+ * tests the JAASSecurityManager
+ *
+ *@author <a href="jmesnil at redhat.com">Jeff Mesnil</a>
+ */
+public class JAASSecurityManagerTest extends TestCase
+{
+   private JAASSecurityManager securityManager;
+
+   private static final String USER = "user";
+   private static final String PASSWORD = "password";
+   private static final String INVALID_PASSWORD = "invalidPassword";   
+   private static final String ROLE = "role";
+   private static final String INVALID_ROLE = "invalidRole";
+   
+   protected void setUp() throws Exception
+   {
+      securityManager = new JAASSecurityManager();
+      
+      final String domainName = SimpleLogingModule.class.getName();
+      // pass the correct user/pass and a role as options to the login module
+      final Map<String, String> options = new HashMap<String, String>();
+      options.put("user", USER);
+      options.put("pass", PASSWORD);
+      options.put("role", ROLE);
+
+      securityManager.setConfigurationName(domainName);
+      securityManager.setCallbackHandler(new CallbackHandler()
+      {
+         public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
+         {
+            // empty callback, auth info are directly passed as options to the login module
+         }
+      });
+      securityManager.setConfiguration(new SimpleConfiguration(domainName, options));
+      
+   }
+
+   protected void tearDown() throws Exception
+   {
+      securityManager = null;
+   }
+
+   public void testValidatingUser()
+   {
+      assertTrue(securityManager.validateUser(USER, PASSWORD));
+      assertFalse(securityManager.validateUser(USER, INVALID_PASSWORD));
+   }
+
+   public void testValidatingUserAndRole()
+   {
+      Set<Role> roles = new HashSet<Role>();
+      roles.add(new Role(ROLE, true, true, true));
+
+      assertTrue(securityManager.validateUserAndRole(USER, PASSWORD, roles, CheckType.CREATE));
+
+      roles.clear();
+      roles.add(new Role(INVALID_ROLE, true, true, true));
+      assertFalse(securityManager.validateUserAndRole(USER, PASSWORD, roles, CheckType.CREATE));
+   }
+
+   public static class SimpleLogingModule implements LoginModule
+   {
+
+      private Map<String, ?> options;
+
+      private Subject subject;
+
+      public SimpleLogingModule()
+      {
+      }
+
+      public boolean abort() throws LoginException
+      {
+         return true;
+      }
+
+      public boolean commit() throws LoginException
+      {
+         return true;
+      }
+
+      public void initialize(Subject subject,
+                             CallbackHandler callbackHandler,
+                             Map<String, ?> sharedState,
+                             Map<String, ?> options)
+      {
+         this.subject = subject;
+         this.options = options;
+      }
+
+      public boolean login() throws LoginException
+      {
+         Iterator<char[]> iterator = subject.getPrivateCredentials(char[].class).iterator();
+         char[] passwordChars = iterator.next();
+         String password = new String(passwordChars);
+         Iterator<Principal> iterator2 = subject.getPrincipals().iterator();
+         String user = iterator2.next().getName();
+
+         boolean authenticated = user.equals(options.get("user")) && password.equals(options.get("pass"));
+         
+         if (authenticated)
+         {
+            Group roles = new SimpleGroup("Roles");
+            roles.addMember(new JAASSecurityManager.SimplePrincipal((String)options.get("role")));
+            subject.getPrincipals().add(roles);
+         }
+         return authenticated;
+
+      }
+      
+      public Subject getSubject()
+      {
+         return subject;
+      }
+
+      public boolean logout() throws LoginException
+      {
+         return true;
+      }
+   }
+
+   public static class SimpleConfiguration extends Configuration
+   {
+      private Map<String, ?> options;
+      private String loginModuleName;
+
+      public SimpleConfiguration(String loginModuleName, Map<String, ?> options)
+      {
+         this.loginModuleName = loginModuleName;
+         this.options = options;
+      }
+
+      @Override
+      public AppConfigurationEntry[] getAppConfigurationEntry(String name)
+      {
+         AppConfigurationEntry entry = new AppConfigurationEntry(loginModuleName,
+                                                                 LoginModuleControlFlag.REQUIRED,
+                                                                 options);
+         return new AppConfigurationEntry[] { entry };
+      }
+
+      @Override
+      public void refresh()
+      {
+      }
+   }
+}




More information about the jboss-cvs-commits mailing list