package org.jboss.mq.security;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.JMSSecurityException;
import javax.jms.InvalidDestinationException;
import javax.jms.TemporaryQueue;
import javax.jms.TemporaryTopic;
import org.jboss.mq.ConnectionToken;
import org.jboss.mq.SpyMessage;
import org.jboss.mq.SpyDestination;
import org.jboss.mq.SpyTopic;
import org.jboss.mq.DurableSubscriptionID;
import org.jboss.mq.Subscription;
import org.jboss.mq.TransactionRequest;
import org.jboss.mq.server.JMSServerInterceptorSupport;
public class ServerSecurityInterceptor extends JMSServerInterceptorSupport
{
SecurityManager manager;
private HashMap tempDests = new HashMap();
public ServerSecurityInterceptor(SecurityManager manager)
{
super();
this.manager = manager;
}
public String authenticate(String name, String password) throws JMSException
{
log.trace("Autenticating user " + name + "/" + password);
return manager.authenticate(name, password);
}
public void connectionClosing(ConnectionToken dc) throws JMSException
{
super.connectionClosing(dc);
manager.logout(dc);
removeTemporaryDestinations(dc);
}
public SpyMessage[] browse(ConnectionToken dc, Destination dest, String selector) throws JMSException
{
if (log.isTraceEnabled())
log.trace("Checking browse authorize on " + dc + " dest=" + dest);
if (!authorizeRead(dc, ((SpyDestination) dest).getName()))
throw new JMSSecurityException("Connection not authorized to browse to destination: " + dest);
return super.browse(dc, dest, selector);
}
public SpyMessage receive(ConnectionToken dc, int subscriberId, long wait) throws JMSException
{
if (log.isTraceEnabled())
log.trace("Checking receive authorize on " + dc + " subId=" + subscriberId);
Subscription sub = super.getSubscription(dc, subscriberId);
String destName = sub.destination.getName();
if (!authorizeRead(dc, destName))
throw new JMSSecurityException("Connection not authorized to receive from destination: " + destName);
return super.receive(dc, subscriberId, wait);
}
public void subscribe(org.jboss.mq.ConnectionToken dc, org.jboss.mq.Subscription sub) throws JMSException
{
if (log.isTraceEnabled())
log.trace("Checking subscribe authorize on " + dc + " sub=" + sub);
if (sub == null)
throw new JMSException("The subscription is not allowed to be null");
else if (sub.destination == null)
throw new InvalidDestinationException("Destination is not allowed to be null");
SpyDestination dest = sub.destination;
String destName = dest.getName();
if (dest instanceof SpyTopic)
{
DurableSubscriptionID id = ((SpyTopic) dest).getDurableSubscriptionID();
if (id != null)
{
if (!authorizeCreate(dc, destName))
throw new JMSSecurityException("Connection not authorized to do durable subscription on topic: "
+ destName);
}
}
if (!authorizeRead(dc, destName))
throw new JMSSecurityException("Connection not authorized to subscribe to destination: " + destName);
super.subscribe(dc, sub);
}
public void addMessage(ConnectionToken dc, SpyMessage message) throws JMSException
{
String dest = ((SpyDestination) message.getJMSDestination()).getName();
if (!authorizeWrite(dc, dest))
throw new JMSSecurityException("Connection not authorized to addMessages to destination: " + dest);
super.addMessage(dc, message);
}
public void transact(ConnectionToken dc, TransactionRequest t) throws JMSException
{
if (t.messages != null)
{
if (t.messages.length == 1)
{
String dest = ((SpyDestination) t.messages[0].getJMSDestination()).getName();
if (authorizeWrite(dc, dest) == false)
throw new JMSSecurityException("Connection not authorized to addMessages to destination: " + dest);
}
else if (t.messages.length > 0)
{
HashSet destinations = new HashSet();
for (int i = 0; i < t.messages.length; ++i)
destinations.add(((SpyDestination) t.messages[i].getJMSDestination()).getName());
for (Iterator i = destinations.iterator(); i.hasNext();)
{
String destinationName = (String) i.next();
if (authorizeWrite(dc, destinationName) == false)
throw new JMSSecurityException("Connection not authorized to addMessages to destination: " + destinationName);
}
}
}
super.transact(dc, t);
}
public void destroySubscription(ConnectionToken dc, DurableSubscriptionID id) throws JMSException
{
SpyTopic t = super.getDurableTopic(id);
if (t == null)
throw new InvalidDestinationException("No durable topic found for subscription " + id.getSubscriptionName());
if (!authorizeCreate(dc, t.getName()))
throw new JMSSecurityException("Connection not authorized to unsubscribe from subscription: " + t.getName());
super.destroySubscription(dc, id);
}
public TemporaryTopic getTemporaryTopic(ConnectionToken dc) throws JMSException
{
TemporaryTopic result = super.getTemporaryTopic(dc);
addTemporaryDestination(dc, result);
return result;
}
public TemporaryQueue getTemporaryQueue(ConnectionToken dc) throws JMSException
{
TemporaryQueue result = super.getTemporaryQueue(dc);
addTemporaryDestination(dc, result);
return result;
}
public void deleteTemporaryDestination(ConnectionToken dc, SpyDestination destination) throws JMSException
{
removeTemporaryDestination(dc, destination);
super.deleteTemporaryDestination(dc, destination);
}
public boolean authorizeRead(ConnectionToken dc, String destination) throws JMSException
{
SecurityMetadata m = manager.getSecurityMetadata(destination);
if (m == null)
{
log.warn("No security configuration avaliable for " + destination);
return false; }
Set readPrincipals = m.getReadPrincipals();
if (manager.authorize(dc, readPrincipals))
return true;
else
return false;
}
public boolean authorizeWrite(ConnectionToken dc, String destination) throws JMSException
{
SecurityMetadata m = manager.getSecurityMetadata(destination);
if (m == null)
{
log.warn("No security configuration avaliable for " + destination);
return false; }
Set writePrincipals = m.getWritePrincipals();
if (manager.authorize(dc, writePrincipals))
return true;
else
return false;
}
public boolean authorizeCreate(ConnectionToken dc, String destination) throws JMSException
{
SecurityMetadata m = manager.getSecurityMetadata(destination);
if (m == null)
{
log.warn("No security configuration avaliable for " + destination);
return false; }
Set createPrincipals = m.getCreatePrincipals();
if (manager.authorize(dc, createPrincipals))
return true;
else
return false;
}
public void addTemporaryDestination(ConnectionToken dc, Destination destination)
{
synchronized (tempDests)
{
HashSet set = (HashSet) tempDests.get(dc);
if (set == null)
{
set = new HashSet();
tempDests.put(dc, set);
}
set.add(destination);
}
}
public void removeTemporaryDestination(ConnectionToken dc, SpyDestination destination)
{
synchronized (tempDests)
{
HashSet set = (HashSet) tempDests.get(dc);
if (set == null)
return;
set.remove(destination);
}
try
{
manager.removeDestination(destination.getName());
}
catch (Exception e)
{
log.warn("Unable to remove temporary destination " + destination, e);
}
}
public void removeTemporaryDestinations(ConnectionToken dc)
{
synchronized (tempDests)
{
HashSet set = (HashSet) tempDests.remove(dc);
if (set == null)
return;
for (Iterator iterator = set.iterator(); iterator.hasNext();)
{
SpyDestination destination = (SpyDestination) iterator.next();
try
{
manager.removeDestination(destination.getName());
}
catch (Exception e)
{
log.warn("Unable to remove temporary destination " + destination, e);
}
}
}
}
}