[jboss-cvs] JBoss Messaging SVN: r7989 - in branches/Branch_1_4: integration/AS5/src/main and 12 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Mon Mar 29 23:05:40 EDT 2010


Author: gaohoward
Date: 2010-03-29 23:05:37 -0400 (Mon, 29 Mar 2010)
New Revision: 7989

Added:
   branches/Branch_1_4/integration/AS5/src/main/
   branches/Branch_1_4/integration/AS5/src/main/org/
   branches/Branch_1_4/integration/AS5/src/main/org/jboss/
   branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/
   branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/
   branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/container/
   branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/container/SecurityActions.java
   branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/container/SecurityAspect.java
   branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/endpoint/
   branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/endpoint/SecurityActions.java
   branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/endpoint/ServerConnectionFactoryEndpoint.java
   branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/security/
   branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/security/SecurityActions.java
   branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/security/SecurityMetadataStore.java
   branches/Branch_1_4/integration/EAP4/src/main/org/jboss/jms/server/security/
   branches/Branch_1_4/integration/EAP4/src/main/org/jboss/jms/server/security/SecurityActions.java
   branches/Branch_1_4/integration/EAP4/src/main/org/jboss/jms/server/security/SecurityMetadataStore.java
   branches/Branch_1_4/integration/EAP5/src/main/org/jboss/jms/server/security/
   branches/Branch_1_4/integration/EAP5/src/main/org/jboss/jms/server/security/SecurityActions.java
   branches/Branch_1_4/integration/EAP5/src/main/org/jboss/jms/server/security/SecurityMetadataStore.java
Modified:
   branches/Branch_1_4/tests/src/org/jboss/test/thirdparty/jbosssx/SecurityAssociationTest.java
Log:
JBMESSAGING-1787


Added: branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/container/SecurityActions.java
===================================================================
--- branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/container/SecurityActions.java	                        (rev 0)
+++ branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/container/SecurityActions.java	2010-03-30 03:05:37 UTC (rev 7989)
@@ -0,0 +1,67 @@
+/*
+  * 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.container;
+
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+
+import org.jboss.security.SecurityAssociation;
+import org.jboss.security.SecurityContext;
+import org.jboss.security.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 href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @author <a href="mailto:anil.saldhana at jboss.com">anil saldhana</a>
+ * @author <a href="mailto:hgao at redhat.com">Howard Gao</a>
+ * @version $Revison: 1.0$
+ */
+class SecurityActions
+{
+   
+   static SecurityContext getSecurityContext()
+   {
+      return  AccessController.doPrivileged(new PrivilegedAction<SecurityContext>(){
+
+         public SecurityContext run()
+         {
+            return SecurityContextAssociation.getSecurityContext();
+         }});
+   }
+   
+   static void setSecurityContext(final SecurityContext sc)
+   {
+      AccessController.doPrivileged(new PrivilegedAction<Object>(){
+
+         public Object run()
+         {
+            SecurityContextAssociation.setSecurityContext(sc);
+            return null;
+         }});
+   }
+
+}

Added: branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/container/SecurityAspect.java
===================================================================
--- branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/container/SecurityAspect.java	                        (rev 0)
+++ branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/container/SecurityAspect.java	2010-03-30 03:05:37 UTC (rev 7989)
@@ -0,0 +1,352 @@
+/*
+  * 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.container;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.jms.Destination;
+import javax.jms.JMSSecurityException;
+import javax.jms.Message;
+
+import org.jboss.aop.joinpoint.Invocation;
+import org.jboss.aop.joinpoint.MethodInvocation;
+import org.jboss.jms.destination.JBossDestination;
+import org.jboss.jms.message.JBossMessage;
+import org.jboss.jms.server.SecurityStore;
+import org.jboss.jms.server.endpoint.ServerConnectionEndpoint;
+import org.jboss.jms.server.endpoint.ServerConsumerEndpoint;
+import org.jboss.jms.server.endpoint.ServerSessionEndpoint;
+import org.jboss.jms.server.endpoint.advised.ConnectionAdvised;
+import org.jboss.jms.server.endpoint.advised.ConsumerAdvised;
+import org.jboss.jms.server.endpoint.advised.SessionAdvised;
+import org.jboss.jms.server.security.CheckType;
+import org.jboss.jms.server.security.SecurityMetadata;
+import org.jboss.jms.tx.ClientTransaction;
+import org.jboss.jms.tx.TransactionRequest;
+import org.jboss.logging.Logger; 
+import org.jboss.security.SecurityContext;
+
+/**
+ * This aspect enforces the JBossMessaging JMS security policy.
+ * 
+ * This aspect is PER_INSTANCE
+ * 
+ * For performance reasons we cache access rights in the interceptor for a maximum of
+ * INVALIDATION_INTERVAL milliseconds.
+ * This is because we don't want to do a full authentication and authorization on every send,
+ * for example, since this will drastically reduce performance.
+ * This means any changes to security data won't be reflected until INVALIDATION_INTERVAL
+ * milliseconds later.
+ * 
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @author <a href="mailto:ovidiu at feodorov.com">Ovidiu Feodorov</a>
+ * @version <tt>$Revision 1.1 $</tt>
+ *
+ * $Id: SecurityAspect.java 3147 2007-09-27 19:12:12Z anil.saldhana at jboss.com $
+ */
+public class SecurityAspect
+{
+   // Constants -----------------------------------------------------
+
+   private static final Logger log = Logger.getLogger(SecurityAspect.class);
+
+   // Static --------------------------------------------------------
+   
+   // Attributes ----------------------------------------------------
+   
+   private boolean trace = log.isTraceEnabled();
+   
+   private Set readCache;
+   
+   private Set writeCache;
+   
+   private Set createCache;
+   
+   //TODO Make this configurable
+   private static final long INVALIDATION_INTERVAL = 15000;
+   
+   private long lastCheck;
+      
+   // Constructors --------------------------------------------------
+   
+   // Public --------------------------------------------------------
+   public SecurityAspect()
+   {
+      readCache = new HashSet();
+      
+      writeCache = new HashSet();
+      
+      createCache = new HashSet();
+   }
+   
+   public Object handleCreateConsumerDelegate(Invocation invocation) throws Throwable
+   {
+      MethodInvocation mi = (MethodInvocation)invocation;
+      
+      // read permission required on the destination
+      Destination dest = (Destination)mi.getArguments()[0];
+      
+      SessionAdvised del = (SessionAdvised)invocation.getTargetObject();
+      ServerSessionEndpoint sess = (ServerSessionEndpoint)del.getEndpoint();
+      
+      check(dest, CheckType.READ, sess.getConnectionEndpoint());
+      
+      // if creating a durable subscription then need create permission
+      
+      String subscriptionName = (String)mi.getArguments()[3];
+      if (subscriptionName != null)
+      {
+         // durable
+         check(dest, CheckType.CREATE, sess.getConnectionEndpoint());
+      }
+      
+      return invocation.invokeNext();
+   }   
+   
+   public Object handleCreateBrowserDelegate(Invocation invocation) throws Throwable
+   {
+      // read permission required on the destination
+      
+      MethodInvocation mi = (MethodInvocation)invocation;
+      
+      Destination dest = (Destination)mi.getArguments()[0];
+      
+      SessionAdvised del = (SessionAdvised)invocation.getTargetObject();
+      ServerSessionEndpoint sess = (ServerSessionEndpoint)del.getEndpoint();
+                  
+      check(dest, CheckType.READ, sess.getConnectionEndpoint());
+      
+      return invocation.invokeNext();
+   }
+   
+   public Object handleSend(Invocation invocation) throws Throwable
+   {
+      // anonymous producer - if destination is not null then write permissions required
+      
+      MethodInvocation mi = (MethodInvocation)invocation;
+      
+      Message m = (Message)mi.getArguments()[0];
+      Destination dest = m.getJMSDestination();
+
+      SessionAdvised del = (SessionAdvised)invocation.getTargetObject();
+      ServerSessionEndpoint se = (ServerSessionEndpoint)del.getEndpoint();
+      ServerConnectionEndpoint ce = se.getConnectionEndpoint();
+                        
+      check(dest, CheckType.WRITE, ce);
+            
+      return invocation.invokeNext();
+   }
+
+
+   // An aspect over ConnectionAdvised
+   public Object handleSendTransaction(Invocation invocation) throws Throwable
+   {
+      ConnectionAdvised del = (ConnectionAdvised)invocation.getTargetObject();
+      ServerConnectionEndpoint ce = (ServerConnectionEndpoint)del.getEndpoint();
+
+      MethodInvocation mi = (MethodInvocation)invocation;
+
+      TransactionRequest t = (TransactionRequest)mi.getArguments()[0];
+
+      ClientTransaction txState = t.getState();
+
+      if (txState != null)
+      {
+         // distinct list of destinations...
+         HashSet destinations = new HashSet();
+
+         for (Iterator i = txState.getSessionStates().iterator(); i.hasNext(); )
+         {
+            ClientTransaction.SessionTxState sessionState = (ClientTransaction.SessionTxState)i.next();
+            for (Iterator j = sessionState.getMsgs().iterator(); j.hasNext(); )
+            {
+               JBossMessage message = (JBossMessage)j.next();
+               destinations.add(message.getJMSDestination());
+            }
+         }
+         for (Iterator iterDestinations = destinations.iterator();iterDestinations.hasNext();)
+         {
+            Destination destination = (Destination) iterDestinations.next();
+            check(destination, CheckType.WRITE, ce);
+         }
+
+      }
+
+      return invocation.invokeNext();
+   }
+
+
+   
+   protected void checkConsumerAccess(Invocation invocation) throws Throwable
+   {
+      ConsumerAdvised del = (ConsumerAdvised)invocation.getTargetObject();
+      ServerConsumerEndpoint cons = (ServerConsumerEndpoint)del.getEndpoint();
+      ServerConnectionEndpoint conn = cons.getSessionEndpoint().getConnectionEndpoint();
+      JBossDestination dest = cons.getDestination();
+      
+      check(dest, CheckType.READ, conn);
+   }
+   
+   // Package protected ---------------------------------------------
+   
+   // Protected -----------------------------------------------------
+   
+   // Private -------------------------------------------------------
+         
+   private boolean checkCached(Destination dest, CheckType checkType)
+   {
+      long now = System.currentTimeMillis();
+      
+      boolean granted = false;
+      
+      if (now - lastCheck > INVALIDATION_INTERVAL)
+      {
+         readCache.clear();
+         
+         writeCache.clear();
+         
+         createCache.clear();         
+      }
+      else
+      {         
+         switch (checkType.type)
+         {
+            case CheckType.TYPE_READ:
+            {
+               granted = readCache.contains(dest);
+               break;
+            }
+            case CheckType.TYPE_WRITE:
+            {
+               granted = writeCache.contains(dest);
+               break;
+            }
+            case CheckType.TYPE_CREATE:
+            {
+               granted = createCache.contains(dest);
+               break;
+            }
+            default:
+            {
+               throw new IllegalArgumentException("Invalid checkType:" + checkType);
+            }
+         }
+      }
+      
+      lastCheck = now;
+      
+      return granted;
+   }
+   
+   private void check(Destination dest, CheckType checkType, ServerConnectionEndpoint conn)
+      throws JMSSecurityException
+   {
+      JBossDestination jbd = (JBossDestination)dest;
+
+      if (jbd.isTemporary())
+      {
+         if (trace) { log.trace("skipping permission check on temporary destination " + dest); }
+         return;
+      }
+
+      if (trace) { log.trace("checking access permissions to " + dest); }
+      
+      if (checkCached(dest, checkType))
+      {
+         // OK
+         return;
+      }
+
+      boolean isQueue = jbd.isQueue();
+      String name = jbd.getName();
+
+      SecurityStore sm = conn.getSecurityManager();
+      SecurityMetadata securityMetadata = sm.getSecurityMetadata(isQueue, name);
+
+      if (securityMetadata == null)
+      {
+         throw new JMSSecurityException("No security configuration avaliable for " + name);
+      }
+
+      // Authenticate. Need to save current SecurityContext
+      SecurityContext previousSCtx = SecurityActions.getSecurityContext();
+      
+      sm.authenticate(conn.getUsername(), conn.getPassword());
+
+      // Authorize
+      Set principals = checkType == CheckType.READ ? securityMetadata.getReadPrincipals() :
+                       checkType == CheckType.WRITE ? securityMetadata.getWritePrincipals() :
+                       securityMetadata.getCreatePrincipals();
+      try
+      {
+         if (!sm.authorize(conn.getUsername(), principals, checkType))
+         {
+            String msg = "User: " + conn.getUsername() +
+               " is not authorized to " +
+               (checkType == CheckType.READ ? "read from" :
+                  checkType == CheckType.WRITE ? "write to" : "create durable sub on") +
+               " destination " + name;
+
+            throw new JMSSecurityException(msg);
+         }
+      }
+      finally
+      {
+         // Restore previous SecurityContext
+         SecurityActions.setSecurityContext(previousSCtx);
+      }
+
+      // if we get here we're granted, add to the cache
+      
+      switch (checkType.type)
+      {
+         case CheckType.TYPE_READ:
+         {
+            readCache.add(dest);
+            break;
+         }
+         case CheckType.TYPE_WRITE:
+         {
+            writeCache.add(dest);
+            break;
+         }
+         case CheckType.TYPE_CREATE:
+         {
+            createCache.add(dest);
+            break;
+         }
+         default:
+         {
+            throw new IllegalArgumentException("Invalid checkType:" + checkType);
+         }
+      }      
+   }
+   
+   // Inner classes -------------------------------------------------
+  
+}
+
+
+
+

Added: branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/endpoint/SecurityActions.java
===================================================================
--- branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/endpoint/SecurityActions.java	                        (rev 0)
+++ branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/endpoint/SecurityActions.java	2010-03-30 03:05:37 UTC (rev 7989)
@@ -0,0 +1,123 @@
+/*
+  * 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.endpoint;
+
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+
+import org.jboss.security.SecurityAssociation;
+import org.jboss.security.SecurityContext;
+import org.jboss.security.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 tim.fox at jboss.com
+ * @author anil.saldhana at jboss.com
+ * @author <a href="mailto:hgao at redhat.com">Howard Gao</a>
+ * @version $Revison: 1.0$
+ */
+class SecurityActions
+{
+   
+   static SecurityContext getSecurityContext()
+   {
+      return  AccessController.doPrivileged(new PrivilegedAction<SecurityContext>(){
+
+         public SecurityContext run()
+         {
+            return SecurityContextAssociation.getSecurityContext();
+         }});
+   }
+   
+   static void setSecurityContext(final SecurityContext sc)
+   {
+      AccessController.doPrivileged(new PrivilegedAction<Object>(){
+
+         public Object run()
+         {
+            SecurityContextAssociation.setSecurityContext(sc);
+            return null;
+         }});
+   }
+
+
+   static ClassLoader getTCL()
+   {
+      if (System.getSecurityManager() == null)
+      {
+         return Thread.currentThread().getContextClassLoader();
+      }
+      else
+      {
+         return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>()
+         {
+            public ClassLoader run()
+            {
+               return Thread.currentThread().getContextClassLoader();
+            }
+         });
+      }
+   }
+
+   static ClassLoader getClassLoader(final Class<?> clazz)
+   {
+      if (System.getSecurityManager() == null)
+      {
+         return clazz.getClassLoader();
+      }
+      else
+      {
+         return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>()
+         {
+            public ClassLoader run()
+            {
+               return clazz.getClassLoader();
+            }
+         });
+      }
+
+   }
+
+   static void setTCL(final ClassLoader tcl)
+   {
+      if (System.getSecurityManager() == null)
+      {
+         Thread.currentThread().setContextClassLoader(tcl);
+      }
+      else
+      {
+         AccessController.doPrivileged(new PrivilegedAction<Object>()
+         {
+            public Object run()
+            {
+               Thread.currentThread().setContextClassLoader(tcl);
+               return null;
+            }
+         });
+      }
+   }
+
+}

Added: branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/endpoint/ServerConnectionFactoryEndpoint.java
===================================================================
--- branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/endpoint/ServerConnectionFactoryEndpoint.java	                        (rev 0)
+++ branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/endpoint/ServerConnectionFactoryEndpoint.java	2010-03-30 03:05:37 UTC (rev 7989)
@@ -0,0 +1,418 @@
+/*
+  * 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.endpoint;
+
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jms.JMSException;
+
+import org.jboss.aop.AspectManager;
+import org.jboss.jms.client.delegate.ClientConnectionDelegate;
+import org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate;
+import org.jboss.jms.delegate.ConnectionFactoryEndpoint;
+import org.jboss.jms.delegate.CreateConnectionResult;
+import org.jboss.jms.delegate.TopologyResult;
+import org.jboss.jms.server.ServerPeer;
+import org.jboss.jms.server.connectionfactory.JNDIBindings;
+import org.jboss.jms.server.endpoint.advised.ConnectionAdvised;
+import org.jboss.jms.wireformat.ConnectionFactoryUpdate;
+import org.jboss.jms.wireformat.Dispatcher;
+import org.jboss.logging.Logger;
+import org.jboss.messaging.util.ConcurrentHashSet;
+import org.jboss.messaging.util.ExceptionUtil;
+import org.jboss.remoting.callback.Callback;
+import org.jboss.remoting.callback.InvokerCallbackHandler;
+import org.jboss.remoting.callback.ServerInvokerCallbackHandler;
+import org.jboss.security.SecurityContext;
+
+/**
+ * Concrete implementation of ConnectionFactoryEndpoint
+ *
+ * @author <a href="mailto:ovidiu at feodorov.com">Ovidiu Feodorov</a>
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 5366 $</tt>
+ *
+ * $Id: ServerConnectionFactoryEndpoint.java 5366 2008-11-14 21:46:28Z clebert.suconic at jboss.com $
+ */
+public class ServerConnectionFactoryEndpoint implements ConnectionFactoryEndpoint
+{
+   // Constants ------------------------------------------------------------------------------------
+
+   private static final Logger log = Logger.getLogger(ServerConnectionFactoryEndpoint.class);
+
+   // Static ---------------------------------------------------------------------------------------
+
+   // Attributes -----------------------------------------------------------------------------------
+
+   private ServerPeer serverPeer;
+
+   private String clientID;
+
+   private String uniqueName;
+
+   private String id;
+
+   private JNDIBindings jndiBindings;
+
+   private int prefetchSize;
+
+   private int defaultTempQueueFullSize;
+
+   private int defaultTempQueuePageSize;
+
+   private int defaultTempQueueDownCacheSize;
+
+   private int dupsOKBatchSize;
+   
+   private boolean supportsFailover;
+   
+   private boolean slowConsumers;
+
+   /** Cluster Topology on ClusteredConnectionFactories
+       Information to failover to other connections on clients **/
+   private ClientConnectionFactoryDelegate[] delegates;
+
+   /** Cluster Topology on ClusteredConnectionFactories
+       Information to failover to other connections on clients **/
+   private Map failoverMap;
+
+   private Set<InvokerCallbackHandler> handlers = new ConcurrentHashSet<InvokerCallbackHandler>();
+   
+
+   // Constructors ---------------------------------------------------------------------------------
+
+   /**
+    * @param jndiBindings - names under which the corresponding JBossConnectionFactory is bound in
+    *        JNDI.
+    */
+   public ServerConnectionFactoryEndpoint(String uniqueName, String id, ServerPeer serverPeer,
+                                          String defaultClientID,
+                                          JNDIBindings jndiBindings,
+                                          int preFetchSize,
+                                          boolean slowConsumers,
+                                          int defaultTempQueueFullSize,
+                                          int defaultTempQueuePageSize,
+                                          int defaultTempQueueDownCacheSize,
+                                          int dupsOKBatchSize,
+                                          boolean supportsFailover)
+   {
+      this.uniqueName = uniqueName;
+      this.serverPeer = serverPeer;
+      this.clientID = defaultClientID;
+      this.id = id;
+      this.jndiBindings = jndiBindings;
+      this.prefetchSize = preFetchSize;
+      this.defaultTempQueueFullSize = defaultTempQueueFullSize;
+      this.defaultTempQueuePageSize = defaultTempQueuePageSize;
+      this.defaultTempQueueDownCacheSize = defaultTempQueueDownCacheSize;
+      this.dupsOKBatchSize = dupsOKBatchSize;
+      this.supportsFailover = supportsFailover;
+      this.slowConsumers = slowConsumers;
+      if (slowConsumers)
+      {
+         this.prefetchSize = 1;
+      }
+   }
+
+   // ConnectionFactoryDelegate implementation -----------------------------------------------------
+
+   public CreateConnectionResult createConnectionDelegate(String username,
+                                                         String password,
+                                                         int failedNodeID)
+                                                        
+      throws JMSException      
+   {
+      //This is never called directly
+      throw new IllegalStateException("createConnectionDelegate should never be called directly");
+   }
+   
+   /**
+    * @param failedNodeID - zero or positive values mean connection creation attempt is result of
+    *        failover. -1 are ignored (mean regular connection creation attempt).
+    */
+   public CreateConnectionResult createConnectionDelegate(String username,
+                                                          String password,
+                                                          int failedNodeID,
+                                                          String remotingSessionID,
+                                                          String clientVMID,
+                                                          byte versionToUse,
+                                                          ServerInvokerCallbackHandler callbackHandler)
+      throws JMSException      
+   {
+      try
+      {
+         if (failedNodeID == -1)
+         {
+            // Just a standard createConnection
+            ClientConnectionDelegate cd =
+               createConnectionDelegateInternal(username, password, failedNodeID,
+                                                remotingSessionID, clientVMID,
+                                                versionToUse,
+                                                callbackHandler);
+            return new CreateConnectionResult(cd);
+         }
+         else
+         {
+            log.trace(this + " received client-side failover request. Creating failover "+
+               "connection to replace connection to failed node " + failedNodeID);
+
+            // Wait for server side failover to complete
+            int failoverNodeID = serverPeer.getFailoverWaiter().waitForFailover(failedNodeID);
+            
+            if (failoverNodeID == -1 || failoverNodeID != serverPeer.getServerPeerID())
+            {
+               log.trace(this + " realized that we are on the wrong node or no failover has occured");
+               return new CreateConnectionResult(failoverNodeID);
+            }
+            else
+            {
+               log.trace(this + " received notification that server-side failover completed, " +
+                  "creating connection delegate ...");
+               ClientConnectionDelegate cd =
+                  createConnectionDelegateInternal(username, password, failedNodeID,
+                                                   remotingSessionID, clientVMID,
+                                                   versionToUse,
+                                                   callbackHandler);
+               return new CreateConnectionResult(cd);
+            }
+         }
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMSInvocation(t, this + " createFailoverConnectionDelegate");
+      }
+      
+   }
+
+   /**
+    * @param failedNodeID - zero or positive values mean connection creation attempt is result of
+    *        failover. Negative values are ignored (mean regular connection creation attempt).
+    */
+   private ClientConnectionDelegate
+      createConnectionDelegateInternal(final String username,
+                                       final String password,
+                                       final int failedNodeID,
+                                       final String remotingSessionID, final String clientVMID,
+                                       final byte versionToUse,
+                                       final ServerInvokerCallbackHandler callbackHandler)
+      throws Exception
+   {
+      log.trace("creating a new connection for user " + username);
+
+      // Authenticate. Need to save current SecurityContext
+      SecurityContext previousSCtx = SecurityActions.getSecurityContext();
+
+      if (System.getSecurityManager() == null)
+      {
+         serverPeer.getSecurityManager().authenticate(username, password);
+      }
+      else
+      {
+         try
+         {
+            AccessController.doPrivileged(new PrivilegedExceptionAction<Object>()
+                                          {
+                                             public Object run() throws Exception
+                                             {
+                                                serverPeer.getSecurityManager().authenticate(username, password);
+                                                return null;
+                                             }
+                                          });
+         }
+         catch (PrivilegedActionException pe)
+         {
+            throw pe.getException();
+         }
+      }
+
+      // Restore previous SecurityContext
+      SecurityActions.setSecurityContext(previousSCtx);
+
+      String clientIDUsed = clientID;
+
+      // see if there is a preconfigured client id for the user
+      if (username != null)
+      {
+         String preconfClientID =
+            serverPeer.getJmsUserManagerInstance().getPreConfiguredClientID(username);
+
+         if (preconfClientID != null)
+         {
+            clientIDUsed = preconfClientID;
+         }                  
+      }
+
+      // create the corresponding "server-side" connection endpoint and register it with the
+      // server peer's ClientManager
+      ServerConnectionEndpoint endpoint =
+         new ServerConnectionEndpoint(serverPeer, clientIDUsed, username, password, prefetchSize,
+                                      defaultTempQueueFullSize, defaultTempQueuePageSize,
+                                      defaultTempQueueDownCacheSize, failedNodeID, this,
+                                      remotingSessionID, clientVMID, versionToUse,
+                                      callbackHandler, dupsOKBatchSize);
+
+      String connectionID = endpoint.getConnectionID();
+
+      ConnectionAdvised connAdvised;
+      
+      // Need to synchronized to prevent a deadlock
+      // See http://jira.jboss.com/jira/browse/JBMESSAGING-797
+      synchronized (AspectManager.instance())
+      {       
+         connAdvised = new ConnectionAdvised(endpoint);
+      }
+      
+      Dispatcher.instance.registerTarget(connectionID, connAdvised);
+
+      log.trace("created and registered " + endpoint);
+
+      // Need to synchronized to prevent a deadlock
+      // See http://jira.jboss.com/jira/browse/JBMESSAGING-797
+      synchronized (AspectManager.instance())
+      {         
+         return new ClientConnectionDelegate(connectionID, serverPeer.getServerPeerID());
+      }
+   }
+      
+   public byte[] getClientAOPStack() throws JMSException
+   {
+      try
+      {
+         return serverPeer.getClientAOPStack();
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMSInvocation(t, this + " getClientAOPStack");
+      }
+   }
+
+   public void addCallback(String VMID, String remotingSessionID,
+                             InvokerCallbackHandler callbackHandler) throws JMSException
+   {
+      log.debug("Adding callbackHandler on ConnectionFactory");
+      
+      handlers.add(callbackHandler);
+      
+      serverPeer.getConnectionManager().registerConnectionFactoryCallback(VMID, remotingSessionID, callbackHandler);
+   }
+
+   public void removeCallback(String VMID, String remotingSessionID,
+                              ServerInvokerCallbackHandler callbackHandler) throws JMSException
+   {
+      log.debug("Removing callbackHandler on ConnectionFactory");
+      
+      handlers.remove(callbackHandler);
+      
+      serverPeer.getConnectionManager().unregisterConnectionFactoryCallback(VMID, remotingSessionID);
+   }
+
+   public TopologyResult getTopology() throws JMSException
+   {
+      return new TopologyResult(uniqueName, delegates, failoverMap);
+   }
+         
+   public void removeCallbackhandler(InvokerCallbackHandler handler)
+   {
+      handlers.remove(handler);
+   }
+   
+   // Public ---------------------------------------------------------------------------------------
+   
+   public String getID()
+   {
+      return id;
+   }
+
+   public JNDIBindings getJNDIBindings()
+   {
+      return jndiBindings;
+   }
+
+   public ServerPeer getServerPeer()
+   {
+      return serverPeer;
+   }
+
+   /**
+    * Sends a cluster view update message to its associated ClusteredConnectionFactories.
+    *
+    * Observation: It is placed here, because if we decide to lock the ServerEndpoint while we send
+    *              updates, we would need the method here to perform WriteLocks on objects.
+    */
+   public void updateClusteredClients(ClientConnectionFactoryDelegate[] delegates, Map failoverMap)
+      throws Exception
+   {
+      updateTopology(delegates, failoverMap);
+ 
+      log.debug("updateClusteredClients being called!!! clientFactoriesToUpdate.size = " + handlers.size());
+
+      ConnectionFactoryUpdate message =
+         new ConnectionFactoryUpdate(uniqueName, delegates, failoverMap);
+
+      Callback callback = new Callback(message);
+
+      for (InvokerCallbackHandler o: handlers)
+      {
+         log.debug("Updating CF on callback " + o);
+         ((ServerInvokerCallbackHandler)o).handleCallbackOneway(callback);
+      }
+   }
+
+   public void updateTopology(ClientConnectionFactoryDelegate[] delegates, Map failoverMap)
+   {
+      this.delegates = delegates;
+      this.failoverMap = failoverMap;
+   }
+   
+   public boolean isSlowConsumers()
+   {
+      return slowConsumers;
+   }
+
+   public String toString()
+   {
+      return "ConnectionFactoryEndpoint[" + id + "]";
+   }
+   
+   /** Method used for tests and validations only */
+   public Set getCallbackHandlers()
+   {
+      return java.util.Collections.unmodifiableSet(handlers);
+   }
+
+   // Package protected ----------------------------------------------------------------------------
+   
+   boolean isSupportsFailover()
+   {
+      return supportsFailover;
+   }
+   
+   // Protected ------------------------------------------------------------------------------------
+   
+   // Private --------------------------------------------------------------------------------------
+   
+   // Inner classes --------------------------------------------------------------------------------
+}

Added: branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/security/SecurityActions.java
===================================================================
--- branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/security/SecurityActions.java	                        (rev 0)
+++ branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/security/SecurityActions.java	2010-03-30 03:05:37 UTC (rev 7989)
@@ -0,0 +1,164 @@
+/*
+  * 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.security;
+
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+
+import javax.security.auth.Subject;
+
+import org.jboss.security.SecurityAssociation;
+import org.jboss.security.SecurityContext;
+import org.jboss.security.SecurityContextAssociation;
+import org.jboss.security.SecurityContextFactory;
+import org.jboss.security.SimplePrincipal;
+import org.jboss.security.plugins.JBossSecurityContext;
+
+
+/** 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
+{
+   
+   static SecurityContext getSecurityContext()
+   {
+      return  AccessController.doPrivileged(new PrivilegedAction<SecurityContext>(){
+
+         public SecurityContext run()
+         {
+            return SecurityContextAssociation.getSecurityContext();
+         }});
+   }
+   
+   static void setSecurityContext(final SecurityContext sc)
+   {
+      AccessController.doPrivileged(new PrivilegedAction<Object>(){
+
+         public Object run()
+         {
+            SecurityContextAssociation.setSecurityContext(sc);
+            return null;
+         }});
+   }
+
+   interface PrincipalInfoAction
+   {
+      PrincipalInfoAction PRIVILEGED = new PrincipalInfoAction()
+      {
+         public void push(final Principal principal, final Object credential,
+            final Subject subject)
+         {
+            AccessController.doPrivileged(
+               new PrivilegedAction()
+               {
+                  public Object run()
+                  {
+                     SecurityAssociation.pushSubjectContext(subject, principal, credential);
+                     return null;
+                  }
+               }
+            );
+         }
+         public void dup()
+         {
+            AccessController.doPrivileged(
+               new PrivilegedAction()
+               {
+                  public Object run()
+                  {
+                     SecurityAssociation.dupSubjectContext();
+                     return null;
+                  }
+               }
+            );
+         }
+         public void pop()
+         {
+            AccessController.doPrivileged(
+               new PrivilegedAction()
+               {
+                  public Object run()
+                  {
+                     SecurityAssociation.popSubjectContext();
+                     return null;
+                  }
+               }
+            );
+         }
+      };
+
+      PrincipalInfoAction NON_PRIVILEGED = new PrincipalInfoAction()
+      {
+         public void push(Principal principal, Object credential, Subject subject)
+         {
+            SecurityAssociation.pushSubjectContext(subject, principal, credential);
+         }
+         public void dup()
+         {
+            SecurityAssociation.dupSubjectContext();
+         }
+         public void pop()
+         {
+            SecurityAssociation.popSubjectContext();
+         }
+      };
+
+      void push(Principal principal, Object credential, Subject subject);
+      void dup();
+      void pop();
+   }
+
+   static void pushSubjectContext(Principal principal, Object credential,
+      Subject subject)
+   {
+      if(System.getSecurityManager() == null)
+      {
+         PrincipalInfoAction.NON_PRIVILEGED.push(principal, credential, subject);
+      }
+      else
+      {
+         PrincipalInfoAction.PRIVILEGED.push(principal, credential, subject);
+      }
+   }
+
+   public static void setSecurityContext(final SimplePrincipal principal, 
+                                         final char[] passwordChars, 
+                                         final Subject subject, 
+                                         final String secDom) throws Exception
+   {
+      AccessController.doPrivileged(new PrivilegedExceptionAction<Object>(){
+
+         public Object run() throws Exception
+         {
+            SecurityContext context = SecurityContextFactory.createSecurityContext(principal, passwordChars, subject, secDom);
+            SecurityContextAssociation.setSecurityContext(context);
+            return null;
+         }});
+   }
+
+}

Added: branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/security/SecurityMetadataStore.java
===================================================================
--- branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/security/SecurityMetadataStore.java	                        (rev 0)
+++ branches/Branch_1_4/integration/AS5/src/main/org/jboss/jms/server/security/SecurityMetadataStore.java	2010-03-30 03:05:37 UTC (rev 7989)
@@ -0,0 +1,325 @@
+/*
+  * 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.security;
+
+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.logging.Logger;
+import org.jboss.security.AuthenticationManager;
+import org.jboss.security.RealmMapping;
+import org.jboss.security.SecurityAssociation;
+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: 4986 $
+ *
+ * $Id: SecurityMetadataStore.java 4986 2008-09-18 22:11:43Z clebert.suconic at jboss.com $
+ */
+public class SecurityMetadataStore implements SecurityStore, SecurityMetadataStoreMBean
+{
+   // Constants -----------------------------------------------------
+   
+   private static final Logger log = Logger.getLogger(SecurityMetadataStore.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 SecurityMetadataStore()
+   {
+      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.
+         try
+         {
+            SecurityActions.setSecurityContext(principal, passwordChars, subject, this.getSecurityDomain());
+         }
+         catch (Exception e)
+         {
+            throw new JMSSecurityException("Failed to set SecurityContext");
+         }
+         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: branches/Branch_1_4/integration/EAP4/src/main/org/jboss/jms/server/security/SecurityActions.java
===================================================================
--- branches/Branch_1_4/integration/EAP4/src/main/org/jboss/jms/server/security/SecurityActions.java	                        (rev 0)
+++ branches/Branch_1_4/integration/EAP4/src/main/org/jboss/jms/server/security/SecurityActions.java	2010-03-30 03:05:37 UTC (rev 7989)
@@ -0,0 +1,120 @@
+/*
+  * 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.security;
+
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+
+import org.jboss.security.SecurityAssociation;
+
+
+/** 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)
+         {
+            AccessController.doPrivileged(
+               new PrivilegedAction()
+               {
+                  public Object run()
+                  {
+                     SecurityAssociation.pushSubjectContext(subject, principal, credential);
+                     return null;
+                  }
+               }
+            );
+         }
+         public void dup()
+         {
+            AccessController.doPrivileged(
+               new PrivilegedAction()
+               {
+                  public Object run()
+                  {
+                     SecurityAssociation.dupSubjectContext();
+                     return null;
+                  }
+               }
+            );
+         }
+         public void pop()
+         {
+            AccessController.doPrivileged(
+               new PrivilegedAction()
+               {
+                  public Object run()
+                  {
+                     SecurityAssociation.popSubjectContext();
+                     return null;
+                  }
+               }
+            );
+         }
+      };
+
+      PrincipalInfoAction NON_PRIVILEGED = new PrincipalInfoAction()
+      {
+         public void push(Principal principal, Object credential, Subject subject)
+         {
+            SecurityAssociation.pushSubjectContext(subject, principal, credential);
+         }
+         public void dup()
+         {
+            SecurityAssociation.dupSubjectContext();
+         }
+         public void pop()
+         {
+            SecurityAssociation.popSubjectContext();
+         }
+      };
+
+      void push(Principal principal, Object credential, Subject subject);
+      void dup();
+      void pop();
+   }
+
+   static void pushSubjectContext(Principal principal, Object credential,
+      Subject subject)
+   {
+      if(System.getSecurityManager() == null)
+      {
+         PrincipalInfoAction.NON_PRIVILEGED.push(principal, credential, subject);
+      }
+      else
+      {
+         PrincipalInfoAction.PRIVILEGED.push(principal, credential, subject);
+      }
+   }
+  }

Added: branches/Branch_1_4/integration/EAP4/src/main/org/jboss/jms/server/security/SecurityMetadataStore.java
===================================================================
--- branches/Branch_1_4/integration/EAP4/src/main/org/jboss/jms/server/security/SecurityMetadataStore.java	                        (rev 0)
+++ branches/Branch_1_4/integration/EAP4/src/main/org/jboss/jms/server/security/SecurityMetadataStore.java	2010-03-30 03:05:37 UTC (rev 7989)
@@ -0,0 +1,317 @@
+/*
+  * 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.security;
+
+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.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: 4986 $
+ *
+ * $Id: SecurityMetadataStore.java 4986 2008-09-18 22:11:43Z clebert.suconic at jboss.com $
+ */
+public class SecurityMetadataStore implements SecurityStore, SecurityMetadataStoreMBean
+{
+   // Constants -----------------------------------------------------
+   
+   private static final Logger log = Logger.getLogger(SecurityMetadataStore.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 SecurityMetadataStore()
+   {
+      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);
+         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: branches/Branch_1_4/integration/EAP5/src/main/org/jboss/jms/server/security/SecurityActions.java
===================================================================
--- branches/Branch_1_4/integration/EAP5/src/main/org/jboss/jms/server/security/SecurityActions.java	                        (rev 0)
+++ branches/Branch_1_4/integration/EAP5/src/main/org/jboss/jms/server/security/SecurityActions.java	2010-03-30 03:05:37 UTC (rev 7989)
@@ -0,0 +1,164 @@
+/*
+  * 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.security;
+
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+
+import javax.security.auth.Subject;
+
+import org.jboss.security.SecurityAssociation;
+import org.jboss.security.SecurityContext;
+import org.jboss.security.SecurityContextAssociation;
+import org.jboss.security.SecurityContextFactory;
+import org.jboss.security.SimplePrincipal;
+import org.jboss.security.plugins.JBossSecurityContext;
+
+
+/** 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
+{
+   
+   static SecurityContext getSecurityContext()
+   {
+      return  AccessController.doPrivileged(new PrivilegedAction<SecurityContext>(){
+
+         public SecurityContext run()
+         {
+            return SecurityContextAssociation.getSecurityContext();
+         }});
+   }
+   
+   static void setSecurityContext(final SecurityContext sc)
+   {
+      AccessController.doPrivileged(new PrivilegedAction<Object>(){
+
+         public Object run()
+         {
+            SecurityContextAssociation.setSecurityContext(sc);
+            return null;
+         }});
+   }
+
+   interface PrincipalInfoAction
+   {
+      PrincipalInfoAction PRIVILEGED = new PrincipalInfoAction()
+      {
+         public void push(final Principal principal, final Object credential,
+            final Subject subject)
+         {
+            AccessController.doPrivileged(
+               new PrivilegedAction()
+               {
+                  public Object run()
+                  {
+                     SecurityAssociation.pushSubjectContext(subject, principal, credential);
+                     return null;
+                  }
+               }
+            );
+         }
+         public void dup()
+         {
+            AccessController.doPrivileged(
+               new PrivilegedAction()
+               {
+                  public Object run()
+                  {
+                     SecurityAssociation.dupSubjectContext();
+                     return null;
+                  }
+               }
+            );
+         }
+         public void pop()
+         {
+            AccessController.doPrivileged(
+               new PrivilegedAction()
+               {
+                  public Object run()
+                  {
+                     SecurityAssociation.popSubjectContext();
+                     return null;
+                  }
+               }
+            );
+         }
+      };
+
+      PrincipalInfoAction NON_PRIVILEGED = new PrincipalInfoAction()
+      {
+         public void push(Principal principal, Object credential, Subject subject)
+         {
+            SecurityAssociation.pushSubjectContext(subject, principal, credential);
+         }
+         public void dup()
+         {
+            SecurityAssociation.dupSubjectContext();
+         }
+         public void pop()
+         {
+            SecurityAssociation.popSubjectContext();
+         }
+      };
+
+      void push(Principal principal, Object credential, Subject subject);
+      void dup();
+      void pop();
+   }
+
+   static void pushSubjectContext(Principal principal, Object credential,
+      Subject subject)
+   {
+      if(System.getSecurityManager() == null)
+      {
+         PrincipalInfoAction.NON_PRIVILEGED.push(principal, credential, subject);
+      }
+      else
+      {
+         PrincipalInfoAction.PRIVILEGED.push(principal, credential, subject);
+      }
+   }
+
+   public static void setSecurityContext(final SimplePrincipal principal, 
+                                         final char[] passwordChars, 
+                                         final Subject subject, 
+                                         final String secDom) throws Exception
+   {
+      AccessController.doPrivileged(new PrivilegedExceptionAction<Object>(){
+
+         public Object run() throws Exception
+         {
+            SecurityContext context = SecurityContextFactory.createSecurityContext(principal, passwordChars, subject, secDom);
+            SecurityContextAssociation.setSecurityContext(context);
+            return null;
+         }});
+   }
+
+}

Added: branches/Branch_1_4/integration/EAP5/src/main/org/jboss/jms/server/security/SecurityMetadataStore.java
===================================================================
--- branches/Branch_1_4/integration/EAP5/src/main/org/jboss/jms/server/security/SecurityMetadataStore.java	                        (rev 0)
+++ branches/Branch_1_4/integration/EAP5/src/main/org/jboss/jms/server/security/SecurityMetadataStore.java	2010-03-30 03:05:37 UTC (rev 7989)
@@ -0,0 +1,325 @@
+/*
+  * 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.security;
+
+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.logging.Logger;
+import org.jboss.security.AuthenticationManager;
+import org.jboss.security.RealmMapping;
+import org.jboss.security.SecurityAssociation;
+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: 4986 $
+ *
+ * $Id: SecurityMetadataStore.java 4986 2008-09-18 22:11:43Z clebert.suconic at jboss.com $
+ */
+public class SecurityMetadataStore implements SecurityStore, SecurityMetadataStoreMBean
+{
+   // Constants -----------------------------------------------------
+   
+   private static final Logger log = Logger.getLogger(SecurityMetadataStore.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 SecurityMetadataStore()
+   {
+      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.
+         try
+         {
+            SecurityActions.setSecurityContext(principal, passwordChars, subject, this.getSecurityDomain());
+         }
+         catch (Exception e)
+         {
+            throw new JMSSecurityException("Failed to set SecurityContext");
+         }
+         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 ---------------------------------------------------      
+
+}

Modified: branches/Branch_1_4/tests/src/org/jboss/test/thirdparty/jbosssx/SecurityAssociationTest.java
===================================================================
--- branches/Branch_1_4/tests/src/org/jboss/test/thirdparty/jbosssx/SecurityAssociationTest.java	2010-03-30 02:41:51 UTC (rev 7988)
+++ branches/Branch_1_4/tests/src/org/jboss/test/thirdparty/jbosssx/SecurityAssociationTest.java	2010-03-30 03:05:37 UTC (rev 7989)
@@ -84,6 +84,7 @@
          new Subject(false, principals, Collections.EMPTY_SET, Collections.EMPTY_SET);
       Principal nebuchadrezzar = new SimplePrincipal("nebuchadrezzar");
 
+      SecurityAssociation.setServer();
       SecurityAssociation.pushSubjectContext(subject, nebuchadrezzar, "xexe");
 
       Connection conn = null;




More information about the jboss-cvs-commits mailing list