[jboss-cvs] JBossAS SVN: r69795 - in trunk/messaging/src: main/org/jboss/jms/server/jbosssx and 1 other directory.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Feb 12 08:17:45 EST 2008


Author: anil.saldhana at jboss.com
Date: 2008-02-12 08:17:45 -0500 (Tue, 12 Feb 2008)
New Revision: 69795

Added:
   trunk/messaging/src/main/org/jboss/jms/server/jbosssx/JBossASSecurityMetadataStore.java
   trunk/messaging/src/main/org/jboss/jms/server/jbosssx/JBossASSecurityMetadataStoreMBean.java
   trunk/messaging/src/main/org/jboss/jms/server/jbosssx/SecurityActions.java
Modified:
   trunk/messaging/src/etc/deploy/common/messaging-service.xml
Log:
JBAS-5230: SecurityMetaDataStore implementation for AS integration

Modified: trunk/messaging/src/etc/deploy/common/messaging-service.xml
===================================================================
--- trunk/messaging/src/etc/deploy/common/messaging-service.xml	2008-02-12 13:07:14 UTC (rev 69794)
+++ trunk/messaging/src/etc/deploy/common/messaging-service.xml	2008-02-12 13:17:45 UTC (rev 69795)
@@ -7,7 +7,7 @@
  -->
 
 <server>
-     <mbean code="org.jboss.jms.server.security.SecurityMetadataStore"
+     <mbean code="org.jboss.jms.server.jbosssx.JBossASSecurityMetadataStore"
           name="jboss.messaging:service=SecurityStore">
           
           <attribute name="DefaultSecurityConfig">

Added: trunk/messaging/src/main/org/jboss/jms/server/jbosssx/JBossASSecurityMetadataStore.java
===================================================================
--- trunk/messaging/src/main/org/jboss/jms/server/jbosssx/JBossASSecurityMetadataStore.java	                        (rev 0)
+++ trunk/messaging/src/main/org/jboss/jms/server/jbosssx/JBossASSecurityMetadataStore.java	2008-02-12 13:17:45 UTC (rev 69795)
@@ -0,0 +1,320 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * 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.jms.server.jbosssx;
+
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jms.JMSSecurityException;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.security.auth.Subject;
+
+import org.jboss.jms.server.SecurityStore;
+import org.jboss.jms.server.security.CheckType;
+import org.jboss.jms.server.security.SecurityMetadata;
+import org.jboss.logging.Logger;
+import org.jboss.security.AuthenticationManager;
+import org.jboss.security.RealmMapping;
+import org.jboss.security.SimplePrincipal;
+import org.jboss.security.SubjectSecurityManager;
+import org.w3c.dom.Element;
+
+/**
+ * A security metadate store for JMS. Stores security information for destinations and delegates
+ * authentication and authorization to a JaasSecurityManager.
+ *
+ * @author Peter Antman
+ * @author <a href="mailto:Scott.Stark at jboss.org">Scott Stark</a>
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @author <a href="mailto:ovidiu at feodorov.com">Ovidiu Feodorov</a>
+ * @version $Revision$
+ *
+ * $Id$
+ */
+public class JBossASSecurityMetadataStore implements SecurityStore, JBossASSecurityMetadataStoreMBean
+{
+   // Constants -----------------------------------------------------
+   
+   private static final Logger log = Logger.getLogger(JBossASSecurityMetadataStore.class);
+   
+   public static final String DEFAULT_SUCKER_USER_PASSWORD = "CHANGE ME!!";
+   
+   // Attributes ----------------------------------------------------
+   
+   private boolean trace = log.isTraceEnabled();
+   
+   private Map queueSecurityConf;
+   private Map topicSecurityConf;
+
+   private AuthenticationManager authenticationManager;
+   private RealmMapping realmMapping;
+   
+   private Element defaultSecurityConfig;
+   private String securityDomain = "java:/jaas/messaging";
+      
+   private String suckerPassword;
+
+   // Static --------------------------------------------------------
+   
+   // Constructors --------------------------------------------------
+
+   public JBossASSecurityMetadataStore()
+   {
+      queueSecurityConf = new HashMap();
+      topicSecurityConf = new HashMap();
+   }
+
+   // SecurityManager implementation --------------------------------
+
+   public SecurityMetadata getSecurityMetadata(boolean isQueue, String destName)
+   {
+      SecurityMetadata m = (SecurityMetadata)
+         (isQueue ? queueSecurityConf.get(destName) : topicSecurityConf.get(destName));
+
+      if (m == null)
+      {
+         // No SecurityMetadata was configured for the destination, apply the default
+         if (defaultSecurityConfig != null)
+         {
+            log.debug("No SecurityMetadadata was available for " + destName + ", using default security config");
+            try
+            {
+               m = new SecurityMetadata(defaultSecurityConfig);
+            }
+            catch (Exception e)
+            {
+               log.warn("Unable to apply default security for destName, using guest " + destName, e);
+               m = new SecurityMetadata();
+            }
+         }
+         else
+         {
+            // default to guest
+            log.warn("No SecurityMetadadata was available for " + destName + ", adding guest");
+            m = new SecurityMetadata();
+         }
+
+         // don't cache it! this way the callers will be able to take advantage of default security
+         // configuration updates
+         // securityConf.put(destName, m);
+      }
+      return m;
+   }
+
+   public void setSecurityConfig(boolean isQueue, String destName, Element conf) throws Exception
+   {
+      if (trace) { log.trace("adding security configuration for " + (isQueue ? "queue " : "topic ") + destName); }
+      
+      if (conf == null)
+      {
+      	clearSecurityConfig(isQueue, destName);
+      }
+      else
+      {	
+	      SecurityMetadata m = new SecurityMetadata(conf);
+	
+	      if (isQueue)
+	      {
+	         queueSecurityConf.put(destName, m);
+	      }
+	      else
+	      {
+	         topicSecurityConf.put(destName, m);
+	      }
+      }
+   }
+
+   public void clearSecurityConfig(boolean isQueue, String name) throws Exception
+   {
+      if (trace) { log.trace("clearing security configuration for " + (isQueue ? "queue " : "topic ") + name); }
+
+      if (isQueue)
+      {
+         queueSecurityConf.remove(name);
+      }
+      else
+      {
+         topicSecurityConf.remove(name);
+      }
+   }
+   
+   public Subject authenticate(String user, String password) throws JMSSecurityException
+   {
+      if (trace) { log.trace("authenticating user " + user); }
+      
+      SimplePrincipal principal = new SimplePrincipal(user);
+      char[] passwordChars = null;
+      if (password != null)
+      {
+         passwordChars = password.toCharArray();
+      }
+
+      Subject subject = new Subject();
+      
+      boolean authenticated = false;
+      
+      if (SUCKER_USER.equals(user))
+      {
+      	if (trace) { log.trace("Authenticating sucker user"); }
+      	
+      	checkDefaultSuckerPassword(password);
+      	
+      	// The special user SUCKER_USER is used for creating internal connections that suck messages between nodes
+      	
+      	authenticated = suckerPassword.equals(password);
+      }
+      else
+      {
+      	authenticated = authenticationManager.isValid(principal, passwordChars, subject);
+      }
+
+      if (authenticated)
+      {
+         // Warning! This "taints" thread local. Make sure you pop it off the stack as soon as
+         //          you're done with it.
+         SecurityActions.pushSubjectContext(principal, passwordChars, subject, 
+               authenticationManager.getSecurityDomain());
+         return subject;
+      }
+      else
+      {
+         throw new JMSSecurityException("User " + user + " is NOT authenticated");
+      }
+   }
+
+   public boolean authorize(String user, Set rolePrincipals, CheckType checkType)
+   {
+      if (trace) { log.trace("authorizing user " + user + " for role(s) " + rolePrincipals.toString()); }
+      
+      if (SUCKER_USER.equals(user))
+      {
+      	//The special user SUCKER_USER is used for creating internal connections that suck messages between nodes
+      	//It has automatic read/write access to all destinations
+      	return (checkType.equals(CheckType.READ) || checkType.equals(CheckType.WRITE));
+      }
+
+      Principal principal = user == null ? null : new SimplePrincipal(user);
+	
+      boolean hasRole = realmMapping.doesUserHaveRole(principal, rolePrincipals);
+
+      if (trace) { log.trace("user " + user + (hasRole ? " is " : " is NOT ") + "authorized"); }
+
+      return hasRole;     
+   }
+   
+   // Public --------------------------------------------------------
+   
+   public void setSuckerPassword(String password)
+   {   	   	
+   	checkDefaultSuckerPassword(password);
+   	   	
+   	this.suckerPassword = password;
+   }
+   
+   public void start() throws NamingException
+   {
+      if (trace) { log.trace("initializing SecurityMetadataStore"); }
+
+      // Get the JBoss security manager from JNDI
+      InitialContext ic = new InitialContext();
+
+      try
+      {
+         Object mgr = ic.lookup(securityDomain);
+
+         log.debug("JaasSecurityManager is " + mgr);
+
+         authenticationManager = (AuthenticationManager)mgr;
+         realmMapping = (RealmMapping)mgr;
+
+         log.trace("SecurityMetadataStore initialized");
+      }
+      catch (NamingException e)
+      {
+         // Apparently there is no security context, try adding java:/jaas
+         log.warn("Failed to lookup securityDomain " + securityDomain, e);
+
+         if (!securityDomain.startsWith("java:/jaas/"))
+         {
+            authenticationManager =
+               (SubjectSecurityManager)ic.lookup("java:/jaas/" + securityDomain);
+         }
+         else
+         {
+            throw e;
+         }
+      }
+      finally
+      {
+         ic.close();
+      }
+   }
+
+   public void stop() throws Exception
+   {
+   }
+
+   public String getSecurityDomain()
+   {
+      return this.securityDomain;
+   }
+
+   public void setSecurityDomain(String securityDomain)
+   {
+      this.securityDomain = securityDomain;
+   }
+
+   public Element getDefaultSecurityConfig()
+   {
+      return this.defaultSecurityConfig;
+   }
+
+   public void setDefaultSecurityConfig(Element conf) throws Exception
+   {
+      // Force a parse
+      new SecurityMetadata(conf);
+      defaultSecurityConfig = conf;
+   }
+
+   // Protected -----------------------------------------------------
+
+   // Package Private -----------------------------------------------
+
+   // Private -------------------------------------------------------
+   
+   private void checkDefaultSuckerPassword(String password)
+   {
+   	// Sanity check
+   	if (DEFAULT_SUCKER_USER_PASSWORD.equals(password))
+   	{
+   		log.warn("WARNING! POTENTIAL SECURITY RISK. It has been detected that the MessageSucker component " +
+   				   "which sucks messages from one node to another has not had its password changed from the installation default. " +
+   				   "Please see the JBoss Messaging user guide for instructions on how to do this.");
+   	}
+   }
+
+   // Inner class ---------------------------------------------------      
+
+}

Added: trunk/messaging/src/main/org/jboss/jms/server/jbosssx/JBossASSecurityMetadataStoreMBean.java
===================================================================
--- trunk/messaging/src/main/org/jboss/jms/server/jbosssx/JBossASSecurityMetadataStoreMBean.java	                        (rev 0)
+++ trunk/messaging/src/main/org/jboss/jms/server/jbosssx/JBossASSecurityMetadataStoreMBean.java	2008-02-12 13:17:45 UTC (rev 69795)
@@ -0,0 +1,80 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * 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.jms.server.jbosssx;
+
+import java.security.Principal;
+import java.util.Set;
+
+import javax.jms.JMSSecurityException;
+import javax.security.auth.Subject;
+
+import org.jboss.jms.server.security.CheckType;
+import org.jboss.jms.server.security.SecurityMetadata;
+import org.w3c.dom.Element;
+
+/**
+ * The SecurityMetadataStore mbean interface
+ * 
+ * @author Scott.Stark at jboss.org
+ * @version $Revision$
+ */
+public interface JBossASSecurityMetadataStoreMBean
+{
+   public String getSecurityDomain();
+   public void setSecurityDomain(String securityDomain);
+   public void setDefaultSecurityConfig(Element conf) throws Exception;
+   public Element getDefaultSecurityConfig();
+
+   public void setSuckerPassword(String password);
+   public void start() throws Exception;
+   public void stop() throws Exception;
+   /**
+    * @return the security meta-data for the given destination.
+    */
+   SecurityMetadata getSecurityMetadata(boolean isQueue, String destName);
+
+   void setSecurityConfig(boolean isQueue, String destName, Element conf) throws Exception;
+   
+   void clearSecurityConfig(boolean isQueue, String name) throws Exception;
+
+   /**
+    * Authenticate the specified user with the given password. Implementations are most likely to
+    * delegates to a JBoss AuthenticationManager.
+    *
+    * Successful authentication will place a new SubjectContext on thread local, which will be used
+    * in the authorization process. However, we need to make sure we clean up thread local
+    * immediately after we used the information, otherwise some other people security my be screwed
+    * up, on account of thread local security stack being corrupted.
+    *
+    * @throws JMSSecurityException if the user is not authenticated
+    */
+   Subject authenticate(String user, String password) throws JMSSecurityException;
+
+   /**
+    * Authorize that the subject has at least one of the specified roles. Implementations are most
+    * likely to delegates to a JBoss AuthenticationManager.
+    *
+    * @param rolePrincipals - The set of roles allowed to read/write/create the destination.
+    * @return true if the subject is authorized, or false if not.
+    */
+   boolean authorize(String user, Set<Principal> rolePrincipals, CheckType checkType);
+}
\ No newline at end of file

Added: trunk/messaging/src/main/org/jboss/jms/server/jbosssx/SecurityActions.java
===================================================================
--- trunk/messaging/src/main/org/jboss/jms/server/jbosssx/SecurityActions.java	                        (rev 0)
+++ trunk/messaging/src/main/org/jboss/jms/server/jbosssx/SecurityActions.java	2008-02-12 13:17:45 UTC (rev 69795)
@@ -0,0 +1,124 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2007, JBoss Inc., and individual contributors as indicated
+  * 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.jms.server.jbosssx;
+ 
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+
+import org.jboss.security.SecurityContext;
+import org.jboss.security.SecurityContextFactory;
+import org.jboss.security.plugins.SecurityContextAssociation;
+
+
+/** A collection of privileged actions for this package
+* @author Scott.Stark at jboss.org
+* @author <a href="mailto:alex at jboss.org">Alexey Loubyansky</a>
+* @author <a her="mailto:tim.fox at jboss.com">Tim Fox</a>
+* @version $Revison: 1.0$
+*/
+class SecurityActions
+{
+  interface PrincipalInfoAction
+  {
+     PrincipalInfoAction PRIVILEGED = new PrincipalInfoAction()
+     {
+        public void push(final Principal principal, final Object credential,
+           final Subject subject, final String domain)
+        {
+           AccessController.doPrivileged(
+              new PrivilegedAction<Object>()
+              {
+                 public Object run()
+                 {
+                    try
+                    {
+                       SecurityContext sc = SecurityContextFactory.createSecurityContext(domain);
+                       SecurityContextAssociation.setSecurityContext(sc);
+                       sc.getUtil().createSubjectInfo(principal, credential, subject);
+                    }
+                    catch (Exception e)
+                    {
+                      throw new RuntimeException(e);
+                    }
+                    return null;
+                 }
+              }
+           );
+        } 
+        public void pop()
+        {
+           AccessController.doPrivileged(
+              new PrivilegedAction<Object>()
+              {
+                 public Object run()
+                 {
+                    SecurityContextAssociation.clearSecurityContext(); 
+                    return null;
+                 }
+              }
+           );
+        }
+     };
+
+     PrincipalInfoAction NON_PRIVILEGED = new PrincipalInfoAction()
+     {
+        public void push(Principal principal, Object credential, Subject subject, String domain)
+        {
+           //ToDo: Get the correct security domain name
+           try
+           {
+              SecurityContext sc = SecurityContextFactory.createSecurityContext(domain);
+              SecurityContextAssociation.setSecurityContext(sc);
+              sc.getUtil().createSubjectInfo(principal, credential, subject);
+           }
+           catch (Exception e)
+           {
+             throw new RuntimeException(e);
+           }
+        }
+         
+        public void pop()
+        {
+           SecurityContextAssociation.clearSecurityContext();
+        }
+     };
+
+     void push(Principal principal, Object credential, Subject subject, String domain);
+     void pop();
+  }
+
+  static void pushSubjectContext(Principal principal, Object credential,
+     Subject subject, String domain)
+  {
+     if(System.getSecurityManager() == null)
+     {
+        PrincipalInfoAction.NON_PRIVILEGED.push(principal, credential, subject, domain);
+     }
+     else
+     {
+        PrincipalInfoAction.PRIVILEGED.push(principal, credential, subject, domain);
+     }
+  }
+ }
\ No newline at end of file




More information about the jboss-cvs-commits mailing list