/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.communication.transport.jms.activemq.internal; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.jms.Connection; import org.apache.activemq.broker.BrokerPlugin; import org.apache.activemq.broker.BrokerPluginSupport; import org.apache.activemq.broker.ConnectionContext; import org.apache.activemq.command.ActiveMQDestination; import org.apache.activemq.command.ConnectionInfo; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import de.rcenvironment.core.communication.common.CommunicationException; import de.rcenvironment.core.communication.configuration.ConnectionFilter; /** * A custom ActiveMQ {@link BrokerPlugin} to allow or deny incoming JMS {@link Connection}s. * * @author Robert Mischke */ public class ActiveMQConnectionFilterPlugin extends BrokerPluginSupport { private static final Pattern VM_CONNECTION_PATTERN = Pattern.compile("vm://.+#\\d+"); private static final Pattern TCP_CONNECTION_PATTERN = Pattern.compile("tcp://(\\d{1,3}.\\d{1,3}.\\d{1,3}.\\d{1,3}):\\d{1,5}"); private final Log log = LogFactory.getLog(getClass()); private volatile ConnectionFilter filter = null; // will cause an exception if queried before setting @Override public void addConnection(ConnectionContext context, ConnectionInfo info) throws Exception { // note that the "IP" in the method name is misleading; this actually returns the connection URL - misc_ro String clientUrl = info.getClientIp(); if (VM_CONNECTION_PATTERN.matcher(clientUrl).matches()) { // allow all in-JVM connections log.debug("Accepting in-JVM JMS broker connection " + clientUrl); } else { // attempt to match IPv4 connection URL Matcher m = TCP_CONNECTION_PATTERN.matcher(clientUrl); if (!m.matches()) { throw new CommunicationException("Connection refused: Malformed client URL (not a numeric IPv4 address): " + clientUrl); } String ipPart = m.group(1); // if matched, check the IP against the provided filter try { boolean accepted = filter.isIpAllowedToConnect(ipPart); if (accepted) { log.debug("Accepting TCP JMS connection from " + ipPart); } else { log.error("Refusing TCP JMS connection from " + ipPart); throw new CommunicationException("Connection from " + ipPart + " refused by IP filter"); } } catch (RuntimeException e) { throw new IllegalStateException("Error while checking filter for incoming IP " + ipPart, e); } } super.addConnection(context, info); } // overridden to suppress warnings caused by superclass - misc_ro @Override @SuppressWarnings({ "unchecked", "rawtypes" }) public Set getDestinations(ActiveMQDestination destination) { return super.getDestinations(destination); } public void setFilter(ConnectionFilter filter) { this.filter = filter; } }