summaryrefslogtreecommitdiff
path: root/java/broker-plugins/access-control/src/main/java/org/apache/qpid
diff options
context:
space:
mode:
Diffstat (limited to 'java/broker-plugins/access-control/src/main/java/org/apache/qpid')
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AbstractConfiguration.java7
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclAction.java102
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclRulePredicates.java102
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Action.java114
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ClientAction.java88
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ConfigurationFile.java12
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java184
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java44
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java113
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/AccessControlFirewallException.java47
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/FirewallRule.java26
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/FirewallRuleFactory.java (renamed from java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlActivator.java)30
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/HostnameFirewallRule.java156
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/InetNetwork.java177
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRule.java117
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/logging/AccessControl_logmessages.properties2
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java83
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java (renamed from java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java)96
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java59
19 files changed, 1152 insertions, 407 deletions
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AbstractConfiguration.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AbstractConfiguration.java
index f04dd38aca..f87374ac80 100644
--- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AbstractConfiguration.java
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AbstractConfiguration.java
@@ -22,13 +22,8 @@ package org.apache.qpid.server.security.access.config;
import java.io.File;
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.log4j.Logger;
-
public abstract class AbstractConfiguration implements ConfigurationFile
{
- private static final Logger _logger = Logger.getLogger(ConfigurationFile.class);
-
private File _file;
private RuleSet _config;
@@ -42,7 +37,7 @@ public abstract class AbstractConfiguration implements ConfigurationFile
return _file;
}
- public RuleSet load() throws ConfigurationException
+ public RuleSet load()
{
_config = new RuleSet();
return _config;
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclAction.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclAction.java
new file mode 100644
index 0000000000..e4bf21a082
--- /dev/null
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclAction.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.server.security.access.config;
+
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+import org.apache.qpid.server.security.access.ObjectProperties;
+import org.apache.qpid.server.security.access.ObjectType;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.access.firewall.FirewallRule;
+
+public class AclAction
+{
+ private Action _action;
+ private FirewallRule _firewallRule;
+
+ public AclAction(Operation operation, ObjectType object, AclRulePredicates predicates)
+ {
+ _action = new Action(operation, object, predicates.getObjectProperties());
+ _firewallRule = predicates.getFirewallRule();
+ }
+
+ public AclAction(Operation operation)
+ {
+ _action = new Action(operation);
+ }
+
+ public AclAction(Operation operation, ObjectType object, ObjectProperties properties)
+ {
+ _action = new Action(operation, object, properties);
+ }
+
+ public FirewallRule getFirewallRule()
+ {
+ return _firewallRule;
+ }
+
+ public Action getAction()
+ {
+ return _action;
+ }
+
+ public boolean isAllowed()
+ {
+ return _action.isAllowed();
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return new HashCodeBuilder()
+ .append(_action)
+ .append(_firewallRule).toHashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (obj == this)
+ {
+ return true;
+ }
+ if (obj.getClass() != getClass())
+ {
+ return false;
+ }
+ AclAction rhs = (AclAction) obj;
+ return new EqualsBuilder()
+ .append(_action, rhs._action)
+ .append(_firewallRule, rhs._firewallRule).isEquals();
+ }
+
+ @Override
+ public String toString()
+ {
+ return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
+ .append(_action)
+ .append(_firewallRule).toString();
+ }
+}
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclRulePredicates.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclRulePredicates.java
new file mode 100644
index 0000000000..45af85be6c
--- /dev/null
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclRulePredicates.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.server.security.access.config;
+
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.security.access.ObjectProperties;
+import org.apache.qpid.server.security.access.ObjectProperties.Property;
+import org.apache.qpid.server.security.access.firewall.FirewallRule;
+import org.apache.qpid.server.security.access.firewall.FirewallRuleFactory;
+
+/**
+ * Represents the predicates on an ACL rule by combining predicates relating to the object being operated on
+ * (e.g. name=foo) with firewall rules.
+ */
+public class AclRulePredicates
+{
+ private static final Logger _logger = Logger.getLogger(AclRulePredicates.class);
+
+ private static final String SEPARATOR = ",";
+
+ private ObjectProperties _properties = new ObjectProperties();
+
+ private FirewallRule _firewallRule;
+
+ private FirewallRuleFactory _firewallRuleFactory = new FirewallRuleFactory();
+
+ public void parse(String key, String value)
+ {
+ ObjectProperties.Property property = ObjectProperties.Property.parse(key);
+
+ if(property == Property.FROM_HOSTNAME)
+ {
+ checkFirewallRuleNotAlreadyDefined(key, value);
+ _firewallRule = _firewallRuleFactory.createForHostname(value.split(SEPARATOR));
+ }
+ else if(property == Property.FROM_NETWORK)
+ {
+ checkFirewallRuleNotAlreadyDefined(key, value);
+ _firewallRule = _firewallRuleFactory.createForNetwork(value.split(SEPARATOR));
+ }
+ else
+ {
+ _properties.put(property, value);
+ }
+
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Parsed " + property + " with value " + value);
+ }
+ }
+
+ private void checkFirewallRuleNotAlreadyDefined(String key, String value)
+ {
+ if(_firewallRule != null)
+ {
+ throw new IllegalStateException(
+ "Cannot parse " + key + "=" + value
+ + " because firewall rule " + _firewallRule + " has already been defined");
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
+ .append(_properties)
+ .append(_firewallRule).toString();
+ }
+
+ public FirewallRule getFirewallRule()
+ {
+ return _firewallRule;
+ }
+
+ public ObjectProperties getObjectProperties()
+ {
+ return _properties;
+ }
+
+ void setFirewallRuleFactory(FirewallRuleFactory firewallRuleFactory)
+ {
+ _firewallRuleFactory = firewallRuleFactory;
+ }
+}
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Action.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Action.java
index b887d1e079..4fff0bebf5 100644
--- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Action.java
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Action.java
@@ -20,8 +20,6 @@
*/
package org.apache.qpid.server.security.access.config;
-import java.util.Comparator;
-
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
@@ -32,7 +30,7 @@ import org.apache.qpid.server.security.access.Operation;
/**
* An access control v2 rule action.
- *
+ *
* An action consists of an {@link Operation} on an {@link ObjectType} with certain properties, stored in a {@link java.util.Map}.
* The operation and object should be an allowable combination, based on the {@link ObjectType#isAllowed(Operation)}
* method of the object, which is exposed as the {@link #isAllowed()} method here. The internal {@link #propertiesMatch(Map)}
@@ -45,104 +43,96 @@ import org.apache.qpid.server.security.access.Operation;
*/
public class Action
{
- private Operation _operation;
- private ObjectType _object;
- private ObjectProperties _properties;
-
+ private final Operation _operation;
+ private final ObjectType _object;
+ private final ObjectProperties _properties;
+
public Action(Operation operation)
{
this(operation, ObjectType.ALL);
}
-
+
public Action(Operation operation, ObjectType object, String name)
{
this(operation, object, new ObjectProperties(name));
}
-
+
public Action(Operation operation, ObjectType object)
{
this(operation, object, ObjectProperties.EMPTY);
}
-
+
public Action(Operation operation, ObjectType object, ObjectProperties properties)
{
- setOperation(operation);
- setObjectType(object);
- setProperties(properties);
+ _operation = operation;
+ _object = object;
+ _properties = properties;
}
-
+
public Operation getOperation()
{
return _operation;
}
- public void setOperation(Operation operation)
- {
- _operation = operation;
- }
-
public ObjectType getObjectType()
{
return _object;
}
- public void setObjectType(ObjectType object)
- {
- _object = object;
- }
-
public ObjectProperties getProperties()
{
return _properties;
}
-
- public void setProperties(ObjectProperties properties)
- {
- _properties = properties;
- }
-
+
public boolean isAllowed()
{
return _object.isAllowed(_operation);
}
- /** @see Comparable#compareTo(Object) */
public boolean matches(Action a)
{
- return ((Operation.ALL == a.getOperation() || getOperation() == a.getOperation())
- && (ObjectType.ALL == a.getObjectType() || getObjectType() == a.getObjectType())
- && _properties.matches(a.getProperties()));
+ if (!operationsMatch(a))
+ {
+ return false;
+ }
+
+ if (!objectTypesMatch(a))
+ {
+ return false;
+ }
+
+ if (!propertiesMatch(a))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean operationsMatch(Action a)
+ {
+ return Operation.ALL == a.getOperation() || getOperation() == a.getOperation();
}
- /**
- * An ordering based on specificity
- *
- * @see Comparator#compare(Object, Object)
- */
- public class Specificity implements Comparator<Action>
+ private boolean objectTypesMatch(Action a)
{
- public int compare(Action a, Action b)
+ return ObjectType.ALL == a.getObjectType() || getObjectType() == a.getObjectType();
+ }
+
+ private boolean propertiesMatch(Action a)
+ {
+ boolean propertiesMatch = false;
+ if (_properties != null)
+ {
+ propertiesMatch = _properties.matches(a.getProperties());
+ }
+ else if (a.getProperties() == null)
{
- if (a.getOperation() == Operation.ALL && b.getOperation() != Operation.ALL)
- {
- return 1; // B is more specific
- }
- else if (b.getOperation() == Operation.ALL && a.getOperation() != Operation.ALL)
- {
- return 1; // A is more specific
- }
- else if (a.getOperation() == b.getOperation())
- {
- return 1; // b is more specific
- }
- else // Different operations
- {
- return a.getOperation().compareTo(b.getOperation()); // Arbitrary
- }
+ propertiesMatch = true;
}
+ return propertiesMatch;
}
- /** @see Object#equals(Object) */
@Override
public boolean equals(Object o)
{
@@ -151,26 +141,24 @@ public class Action
return false;
}
Action a = (Action) o;
-
+
return new EqualsBuilder()
.append(_operation, a.getOperation())
.append(_object, a.getObjectType())
- .appendSuper(_properties.equals(a.getProperties()))
+ .append(_properties, a.getProperties())
.isEquals();
}
- /** @see Object#hashCode() */
@Override
public int hashCode()
{
return new HashCodeBuilder()
.append(_operation)
- .append(_operation)
+ .append(_object)
.append(_properties)
.toHashCode();
}
- /** @see Object#toString() */
@Override
public String toString()
{
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ClientAction.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ClientAction.java
new file mode 100644
index 0000000000..fed20a56c8
--- /dev/null
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ClientAction.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.server.security.access.config;
+
+import java.net.InetAddress;
+
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+import org.apache.qpid.server.security.access.ObjectProperties;
+import org.apache.qpid.server.security.access.ObjectType;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.access.firewall.FirewallRule;
+
+/**
+ * I represent an {@link Action} taken by a client from a known address. The address is used to
+ * determine if I match an {@link AclAction}, which may contain firewall rules.
+ */
+public class ClientAction
+{
+ private Action _clientAction;
+
+ public ClientAction(Action clientAction)
+ {
+ _clientAction = clientAction;
+ }
+
+ public ClientAction(Operation operation, ObjectType objectType, ObjectProperties properties)
+ {
+ _clientAction = new Action(operation, objectType, properties);
+ }
+
+ public boolean matches(AclAction ruleAction, InetAddress addressOfClient)
+ {
+ return _clientAction.matches(ruleAction.getAction())
+ && addressOfClientMatches(ruleAction, addressOfClient);
+ }
+
+ private boolean addressOfClientMatches(AclAction ruleAction, InetAddress addressOfClient)
+ {
+ FirewallRule firewallRule = ruleAction.getFirewallRule();
+ if(firewallRule == null || addressOfClient == null)
+ {
+ return true;
+ }
+ else
+ {
+ return firewallRule.matches(addressOfClient);
+ }
+ }
+
+ public Operation getOperation()
+ {
+ return _clientAction.getOperation();
+ }
+
+ public ObjectType getObjectType()
+ {
+ return _clientAction.getObjectType();
+ }
+
+ public ObjectProperties getProperties()
+ {
+ return _clientAction.getProperties();
+ }
+
+ @Override
+ public String toString()
+ {
+ return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
+ .append(_clientAction).toString();
+ }
+}
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ConfigurationFile.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ConfigurationFile.java
index 8b1a00259b..966c32e24e 100644
--- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ConfigurationFile.java
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ConfigurationFile.java
@@ -22,7 +22,7 @@ package org.apache.qpid.server.security.access.config;
import java.io.File;
-import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
public interface ConfigurationFile
{
@@ -33,19 +33,17 @@ public interface ConfigurationFile
/**
* Load this configuration file's contents into a {@link RuleSet}.
- *
- * @throws ConfigurationException if the configuration file has errors.
+ * @throws IllegalConfigurationException if the configuration file has errors.
* @throws IllegalArgumentException if individual tokens cannot be parsed.
*/
- RuleSet load() throws ConfigurationException;
+ RuleSet load() throws IllegalConfigurationException;
/**
* Reload this configuration file's contents.
- *
- * @throws ConfigurationException if the configuration file has errors.
+ * @throws IllegalConfigurationException if the configuration file has errors.
* @throws IllegalArgumentException if individual tokens cannot be parsed.
*/
- RuleSet reload() throws ConfigurationException;
+ RuleSet reload() throws IllegalConfigurationException;
RuleSet getConfiguration();
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java
index 9a08eb6499..ab309c54ce 100644
--- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java
@@ -1,5 +1,5 @@
/*
- *
+ *
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -7,16 +7,16 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
- *
+ *
*/
package org.apache.qpid.server.security.access.config;
@@ -32,55 +32,65 @@ import java.util.List;
import java.util.Map;
import java.util.Stack;
-import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.lang.StringUtils;
-import org.apache.qpid.server.security.access.ObjectProperties;
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.security.access.ObjectType;
import org.apache.qpid.server.security.access.Operation;
import org.apache.qpid.server.security.access.Permission;
public class PlainConfiguration extends AbstractConfiguration
{
+ private static final Logger _logger = Logger.getLogger(PlainConfiguration.class);
+
public static final Character COMMENT = '#';
public static final Character CONTINUATION = '\\';
- public static final String GROUP = "group";
public static final String ACL = "acl";
public static final String CONFIG = "config";
- public static final String UNRECOGNISED_INITIAL_MSG = "Unrecognised initial token '%s' at line %d";
- public static final String NOT_ENOUGH_TOKENS_MSG = "Not enough tokens at line %d";
- public static final String NUMBER_NOT_ALLOWED_MSG = "Number not allowed before '%s' at line %d";
- public static final String CANNOT_LOAD_MSG = "Cannot load config file %s";
- public static final String PREMATURE_CONTINUATION_MSG = "Premature continuation character at line %d";
- public static final String PREMATURE_EOF_MSG = "Premature end of file reached at line %d";
- public static final String PARSE_TOKEN_FAILED_MSG = "Failed to parse token at line %d";
- public static final String CONFIG_NOT_FOUND_MSG = "Cannot find config file %s";
- public static final String NOT_ENOUGH_GROUP_MSG = "Not enough data for a group at line %d";
- public static final String NOT_ENOUGH_ACL_MSG = "Not enough data for an acl at line %d";
- public static final String NOT_ENOUGH_CONFIG_MSG = "Not enough data for config at line %d";
- public static final String BAD_ACL_RULE_NUMBER_MSG = "Invalid rule number at line %d";
- public static final String PROPERTY_KEY_ONLY_MSG = "Incomplete property (key only) at line %d";
- public static final String PROPERTY_NO_EQUALS_MSG = "Incomplete property (no equals) at line %d";
- public static final String PROPERTY_NO_VALUE_MSG = "Incomplete property (no value) at line %d";
-
+ static final String UNRECOGNISED_INITIAL_MSG = "Unrecognised initial token '%s' at line %d";
+ static final String NOT_ENOUGH_TOKENS_MSG = "Not enough tokens at line %d";
+ static final String NUMBER_NOT_ALLOWED_MSG = "Number not allowed before '%s' at line %d";
+ static final String CANNOT_LOAD_MSG = "Cannot load config file %s";
+ static final String CANNOT_CLOSE_MSG = "Cannot close config file %s";
+ static final String PREMATURE_CONTINUATION_MSG = "Premature continuation character at line %d";
+ static final String PREMATURE_EOF_MSG = "Premature end of file reached at line %d";
+ static final String PARSE_TOKEN_FAILED_MSG = "Failed to parse token at line %d";
+ static final String CONFIG_NOT_FOUND_MSG = "Cannot find config file %s";
+ static final String NOT_ENOUGH_ACL_MSG = "Not enough data for an acl at line %d";
+ static final String NOT_ENOUGH_CONFIG_MSG = "Not enough data for config at line %d";
+ static final String BAD_ACL_RULE_NUMBER_MSG = "Invalid rule number at line %d";
+ static final String PROPERTY_KEY_ONLY_MSG = "Incomplete property (key only) at line %d";
+ static final String PROPERTY_NO_EQUALS_MSG = "Incomplete property (no equals) at line %d";
+ static final String PROPERTY_NO_VALUE_MSG = "Incomplete property (no value) at line %d";
+
private StreamTokenizer _st;
public PlainConfiguration(File file)
{
super(file);
}
-
+
@Override
- public RuleSet load() throws ConfigurationException
+ public RuleSet load()
{
RuleSet ruleSet = super.load();
-
+
+ File file = getFile();
+ FileReader fileReader = null;
+
try
{
- _st = new StreamTokenizer(new BufferedReader(new FileReader(getFile())));
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("About to load ACL file " + file);
+ }
+
+ fileReader = new FileReader(file);
+ _st = new StreamTokenizer(new BufferedReader(fileReader));
_st.resetSyntax(); // setup the tokenizer
-
+
_st.commentChar(COMMENT); // single line comments
_st.eolIsSignificant(true); // return EOL as a token
_st.ordinaryChar('='); // equals is a token
@@ -97,7 +107,7 @@ public class PlainConfiguration extends AbstractConfiguration
_st.wordChars('*', '*'); // star
_st.wordChars('@', '@'); // at
_st.wordChars(':', ':'); // colon
-
+
// parse the acl file lines
Stack<String> stack = new Stack<String>();
int current;
@@ -111,21 +121,21 @@ public class PlainConfiguration extends AbstractConfiguration
{
break; // blank line
}
-
+
// pull out the first token from the bottom of the stack and check arguments exist
String first = stack.firstElement();
stack.removeElementAt(0);
if (stack.isEmpty())
{
- throw new ConfigurationException(String.format(NOT_ENOUGH_TOKENS_MSG, getLine()));
+ throw new IllegalConfigurationException(String.format(NOT_ENOUGH_TOKENS_MSG, getLine()));
}
-
+
// check for and parse optional initial number for ACL lines
Integer number = null;
if (StringUtils.isNumeric(first))
{
// set the acl number and get the next element
- number = Integer.valueOf(first);
+ number = Integer.valueOf(first);
first = stack.firstElement();
stack.removeElementAt(0);
}
@@ -136,9 +146,9 @@ public class PlainConfiguration extends AbstractConfiguration
}
else if (number == null)
{
- if (StringUtils.equalsIgnoreCase(GROUP, first))
+ if(StringUtils.equalsIgnoreCase("GROUP", first))
{
- parseGroup(stack);
+ throw new IllegalConfigurationException(String.format("GROUP keyword not supported. Groups should defined via a Group Provider, not in the ACL file.", getLine()));
}
else if (StringUtils.equalsIgnoreCase(CONFIG, first))
{
@@ -146,14 +156,14 @@ public class PlainConfiguration extends AbstractConfiguration
}
else
{
- throw new ConfigurationException(String.format(UNRECOGNISED_INITIAL_MSG, first, getLine()));
+ throw new IllegalConfigurationException(String.format(UNRECOGNISED_INITIAL_MSG, first, getLine()));
}
}
else
{
- throw new ConfigurationException(String.format(NUMBER_NOT_ALLOWED_MSG, first, getLine()));
+ throw new IllegalConfigurationException(String.format(NUMBER_NOT_ALLOWED_MSG, first, getLine()));
}
-
+
// reset stack, start next line
stack.clear();
break;
@@ -171,9 +181,9 @@ public class PlainConfiguration extends AbstractConfiguration
{
break; // continue reading next line
}
-
+
// invalid location for continuation character (add one to line beacuse we ate the EOL)
- throw new ConfigurationException(String.format(PREMATURE_CONTINUATION_MSG, getLine() + 1));
+ throw new IllegalConfigurationException(String.format(PREMATURE_CONTINUATION_MSG, getLine() + 1));
}
else if (_st.ttype == '\'' || _st.ttype == '"')
{
@@ -185,54 +195,59 @@ public class PlainConfiguration extends AbstractConfiguration
}
}
} while (current != StreamTokenizer.TT_EOF);
-
+
if (!stack.isEmpty())
{
- throw new ConfigurationException(String.format(PREMATURE_EOF_MSG, getLine()));
+ throw new IllegalConfigurationException(String.format(PREMATURE_EOF_MSG, getLine()));
}
}
catch (IllegalArgumentException iae)
{
- throw new ConfigurationException(String.format(PARSE_TOKEN_FAILED_MSG, getLine()), iae);
+ throw new IllegalConfigurationException(String.format(PARSE_TOKEN_FAILED_MSG, getLine()), iae);
}
catch (FileNotFoundException fnfe)
{
- throw new ConfigurationException(String.format(CONFIG_NOT_FOUND_MSG, getFile().getName()), fnfe);
+ throw new IllegalConfigurationException(String.format(CONFIG_NOT_FOUND_MSG, file.getName()), fnfe);
}
catch (IOException ioe)
{
- throw new ConfigurationException(String.format(CANNOT_LOAD_MSG, getFile().getName()), ioe);
+ throw new IllegalConfigurationException(String.format(CANNOT_LOAD_MSG, file.getName()), ioe);
}
-
- return ruleSet;
- }
-
- private void parseGroup(List<String> args) throws ConfigurationException
- {
- if (args.size() < 2)
+ finally
{
- throw new ConfigurationException(String.format(NOT_ENOUGH_GROUP_MSG, getLine()));
+ if(fileReader != null)
+ {
+ try
+ {
+ fileReader.close();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalConfigurationException(String.format(CANNOT_CLOSE_MSG, file.getName()), e);
+ }
+ }
}
-
- getConfiguration().addGroup(args.get(0), args.subList(1, args.size()));
+
+
+ return ruleSet;
}
-
- private void parseAcl(Integer number, List<String> args) throws ConfigurationException
+
+ private void parseAcl(Integer number, List<String> args)
{
if (args.size() < 3)
{
- throw new ConfigurationException(String.format(NOT_ENOUGH_ACL_MSG, getLine()));
+ throw new IllegalConfigurationException(String.format(NOT_ENOUGH_ACL_MSG, getLine()));
}
Permission permission = Permission.parse(args.get(0));
String identity = args.get(1);
Operation operation = Operation.parse(args.get(2));
-
+
if (number != null && !getConfiguration().isValidNumber(number))
{
- throw new ConfigurationException(String.format(BAD_ACL_RULE_NUMBER_MSG, getLine()));
+ throw new IllegalConfigurationException(String.format(BAD_ACL_RULE_NUMBER_MSG, getLine()));
}
-
+
if (args.size() == 3)
{
getConfiguration().grant(number, identity, permission, operation);
@@ -240,55 +255,52 @@ public class PlainConfiguration extends AbstractConfiguration
else
{
ObjectType object = ObjectType.parse(args.get(3));
- ObjectProperties properties = toObjectProperties(args.subList(4, args.size()));
+ AclRulePredicates predicates = toRulePredicates(args.subList(4, args.size()));
- getConfiguration().grant(number, identity, permission, operation, object, properties);
+ getConfiguration().grant(number, identity, permission, operation, object, predicates);
}
}
-
- private void parseConfig(List<String> args) throws ConfigurationException
+
+ private void parseConfig(List<String> args)
{
if (args.size() < 3)
{
- throw new ConfigurationException(String.format(NOT_ENOUGH_CONFIG_MSG, getLine()));
+ throw new IllegalConfigurationException(String.format(NOT_ENOUGH_CONFIG_MSG, getLine()));
}
Map<String, Boolean> properties = toPluginProperties(args);
-
+
getConfiguration().configure(properties);
}
-
- /** Converts a {@link List} of "name", "=", "value" tokens into a {@link Map}. */
- protected ObjectProperties toObjectProperties(List<String> args) throws ConfigurationException
+
+ private AclRulePredicates toRulePredicates(List<String> args)
{
- ObjectProperties properties = new ObjectProperties();
+ AclRulePredicates predicates = new AclRulePredicates();
Iterator<String> i = args.iterator();
while (i.hasNext())
{
String key = i.next();
if (!i.hasNext())
{
- throw new ConfigurationException(String.format(PROPERTY_KEY_ONLY_MSG, getLine()));
+ throw new IllegalConfigurationException(String.format(PROPERTY_KEY_ONLY_MSG, getLine()));
}
if (!"=".equals(i.next()))
{
- throw new ConfigurationException(String.format(PROPERTY_NO_EQUALS_MSG, getLine()));
+ throw new IllegalConfigurationException(String.format(PROPERTY_NO_EQUALS_MSG, getLine()));
}
if (!i.hasNext())
{
- throw new ConfigurationException(String.format(PROPERTY_NO_VALUE_MSG, getLine()));
+ throw new IllegalConfigurationException(String.format(PROPERTY_NO_VALUE_MSG, getLine()));
}
String value = i.next();
-
- // parse property key
- ObjectProperties.Property property = ObjectProperties.Property.parse(key);
- properties.put(property, value);
+
+ predicates.parse(key, value);
}
- return properties;
+ return predicates;
}
-
+
/** Converts a {@link List} of "name", "=", "value" tokens into a {@link Map}. */
- protected Map<String, Boolean> toPluginProperties(List<String> args) throws ConfigurationException
+ protected Map<String, Boolean> toPluginProperties(List<String> args)
{
Map<String, Boolean> properties = new HashMap<String, Boolean>();
Iterator<String> i = args.iterator();
@@ -297,24 +309,24 @@ public class PlainConfiguration extends AbstractConfiguration
String key = i.next().toLowerCase();
if (!i.hasNext())
{
- throw new ConfigurationException(String.format(PROPERTY_KEY_ONLY_MSG, getLine()));
+ throw new IllegalConfigurationException(String.format(PROPERTY_KEY_ONLY_MSG, getLine()));
}
if (!"=".equals(i.next()))
{
- throw new ConfigurationException(String.format(PROPERTY_NO_EQUALS_MSG, getLine()));
+ throw new IllegalConfigurationException(String.format(PROPERTY_NO_EQUALS_MSG, getLine()));
}
if (!i.hasNext())
{
- throw new ConfigurationException(String.format(PROPERTY_NO_VALUE_MSG, getLine()));
+ throw new IllegalConfigurationException(String.format(PROPERTY_NO_VALUE_MSG, getLine()));
}
-
+
// parse property value and save
Boolean value = Boolean.valueOf(i.next());
properties.put(key, value);
}
return properties;
}
-
+
protected int getLine()
{
return _st.lineno() - 1;
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java
index 15d6b67192..cef9a8696b 100644
--- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java
@@ -29,7 +29,7 @@ import org.apache.qpid.server.security.access.Permission;
/**
* An access control v2 rule.
- *
+ *
* A rule consists of {@link Permission} for a particular identity to perform an {@link Action}. The identity
* may be either a user or a group.
*/
@@ -37,41 +37,41 @@ public class Rule implements Comparable<Rule>
{
/** String indicating all identitied. */
public static final String ALL = "all";
-
+
private Integer _number;
private Boolean _enabled = Boolean.TRUE;
private String _identity;
- private Action _action;
+ private AclAction _action;
private Permission _permission;
-
- public Rule(Integer number, String identity, Action action, Permission permission)
+
+ public Rule(Integer number, String identity, AclAction action, Permission permission)
{
setNumber(number);
setIdentity(identity);
setAction(action);
setPermission(permission);
}
-
- public Rule(String identity, Action action, Permission permission)
+
+ public Rule(String identity, AclAction action, Permission permission)
{
this(null, identity, action, permission);
}
-
+
public boolean isEnabled()
{
return _enabled;
}
-
+
public void setEnabled(boolean enabled)
{
_enabled = enabled;
}
-
+
public void enable()
{
_enabled = Boolean.TRUE;
}
-
+
public void disable()
{
_enabled = Boolean.FALSE;
@@ -96,13 +96,18 @@ public class Rule implements Comparable<Rule>
{
_identity = identity;
}
-
+
public Action getAction()
{
+ return _action.getAction();
+ }
+
+ public AclAction getAclAction()
+ {
return _action;
}
- public void setAction(Action action)
+ public void setAction(AclAction action)
{
_action = action;
}
@@ -117,7 +122,7 @@ public class Rule implements Comparable<Rule>
_permission = permission;
}
- /** @see Comparable#compareTo(Object) */
+ @Override
public int compareTo(Rule r)
{
return new CompareToBuilder()
@@ -127,7 +132,6 @@ public class Rule implements Comparable<Rule>
.toComparison();
}
- /** @see Object#equals(Object) */
@Override
public boolean equals(Object o)
{
@@ -136,33 +140,31 @@ public class Rule implements Comparable<Rule>
return false;
}
Rule r = (Rule) o;
-
+
return new EqualsBuilder()
.append(getIdentity(), r.getIdentity())
- .append(getAction(), r.getAction())
+ .append(getAclAction(), r.getAclAction())
.append(getPermission(), r.getPermission())
.isEquals();
}
- /** @see Object#hashCode() */
@Override
public int hashCode()
{
return new HashCodeBuilder()
.append(getIdentity())
- .append(getAction())
+ .append(getAclAction())
.append(getPermission())
.toHashCode();
}
- /** @see Object#toString() */
@Override
public String toString()
{
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
.append("#", getNumber())
.append("identity", getIdentity())
- .append("action", getAction())
+ .append("action", getAclAction())
.append("permission", getPermission())
.append("enabled", isEnabled())
.toString();
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java
index 815df99f80..e61370fced 100644
--- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java
@@ -18,8 +18,8 @@
*/
package org.apache.qpid.server.security.access.config;
+import java.net.InetAddress;
import java.security.Principal;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
@@ -54,7 +54,7 @@ import org.apache.qpid.server.security.access.logging.AccessControlMessages;
*/
public class RuleSet
{
- public static final Logger _logger = Logger.getLogger(RuleSet.class);
+ private static final Logger _logger = Logger.getLogger(RuleSet.class);
private static final String AT = "@";
private static final String SLASH = "/";
@@ -66,7 +66,6 @@ public class RuleSet
private static final Integer _increment = 10;
- private final Map<String, List<String>> _aclGroups = new HashMap<String, List<String>>();
private final SortedMap<Integer, Rule> _rules = new TreeMap<Integer, Rule>();
private final Map<Subject, Map<Operation, Map<ObjectType, List<Rule>>>> _cache =
new WeakHashMap<Subject, Map<Operation, Map<ObjectType, List<Rule>>>>();
@@ -79,14 +78,13 @@ public class RuleSet
}
/**
- * Clear the contents, including acl groups, rules and configuration.
+ * Clear the contents, including acl rules and configuration.
*/
public void clear()
{
_rules.clear();
_cache.clear();
_config.clear();
- _aclGroups.clear();
}
public int getRuleCount()
@@ -157,21 +155,27 @@ public class RuleSet
public void grant(Integer number, String identity, Permission permission, Operation operation)
{
- Action action = new Action(operation);
+ AclAction action = new AclAction(operation);
addRule(number, identity, permission, action);
}
public void grant(Integer number, String identity, Permission permission, Operation operation, ObjectType object, ObjectProperties properties)
{
- Action action = new Action(operation, object, properties);
+ AclAction action = new AclAction(operation, object, properties);
addRule(number, identity, permission, action);
}
- public boolean ruleExists(String identity, Action action)
+ public void grant(Integer number, String identity, Permission permission, Operation operation, ObjectType object, AclRulePredicates predicates)
+ {
+ AclAction aclAction = new AclAction(operation, object, predicates);
+ addRule(number, identity, permission, aclAction);
+ }
+
+ public boolean ruleExists(String identity, AclAction action)
{
for (Rule rule : _rules.values())
{
- if (rule.getIdentity().equals(identity) && rule.getAction().equals(action))
+ if (rule.getIdentity().equals(identity) && rule.getAclAction().equals(action))
{
return true;
}
@@ -179,8 +183,7 @@ public class RuleSet
return false;
}
- // TODO make this work when group membership is not known at file parse time
- public void addRule(Integer number, String identity, Permission permission, Action action)
+ public void addRule(Integer number, String identity, Permission permission, AclAction action)
{
_cache.clear();
@@ -222,53 +225,6 @@ public class RuleSet
_rules.get(Integer.valueOf(ruleNumber)).disable();
}
- public boolean addGroup(String group, List<String> constituents)
- {
- _cache.clear();
-
- if (_aclGroups.containsKey(group))
- {
- // cannot redefine
- return false;
- }
- else
- {
- _aclGroups.put(group, new ArrayList<String>());
- }
-
- for (String name : constituents)
- {
- if (name.equalsIgnoreCase(group))
- {
- // recursive definition
- return false;
- }
-
- if (!checkName(name))
- {
- // invalid name
- return false;
- }
-
- if (_aclGroups.containsKey(name))
- {
- // is a group
- _aclGroups.get(group).addAll(_aclGroups.get(name));
- }
- else
- {
- // is a user
- if (!isvalidUserName(name))
- {
- // invalid username
- return false;
- }
- _aclGroups.get(group).add(name);
- }
- }
- return true;
- }
-
/** Return true if the name is well-formed (contains legal characters). */
protected boolean checkName(String name)
{
@@ -312,11 +268,15 @@ public class RuleSet
return true;
}
- // CPP broker authorise function prototype
- // virtual bool authorise(const std::string& id, const Action& action, const ObjectType& objType,
- // const std::string& name, std::map<Property, std::string>* params=0)
-
- // Possibly add a String name paramater?
+ /**
+ * Checks for the case when the client's address is not known.
+ *
+ * @see #check(Subject, Operation, ObjectType, ObjectProperties, InetAddress)
+ */
+ public Result check(Subject subject, Operation operation, ObjectType objectType, ObjectProperties properties)
+ {
+ return check(subject, operation, objectType, properties, null);
+ }
/**
* Check the authorisation granted to a particular identity for an operation on an object type with
@@ -327,10 +287,9 @@ public class RuleSet
* the first match found, or denies access if there are no matching rules. Normally, it would be expected
* to have a default deny or allow rule at the end of an access configuration however.
*/
- public Result check(Subject subject, Operation operation, ObjectType objectType, ObjectProperties properties)
+ public Result check(Subject subject, Operation operation, ObjectType objectType, ObjectProperties properties, InetAddress addressOfClient)
{
- // Create the action to check
- Action action = new Action(operation, objectType, properties);
+ ClientAction action = new ClientAction(operation, objectType, properties);
if(_logger.isDebugEnabled())
{
@@ -349,27 +308,31 @@ public class RuleSet
}
// Iterate through a filtered set of rules dealing with this identity and operation
- for (Rule current : rules)
+ for (Rule rule : rules)
{
if(_logger.isDebugEnabled())
{
- _logger.debug("Checking against rule: " + current);
+ _logger.debug("Checking against rule: " + rule);
}
- // Check if action matches
- if (action.matches(current.getAction()))
+
+ if (action.matches(rule.getAclAction(), addressOfClient))
{
- Permission permission = current.getPermission();
+ Permission permission = rule.getPermission();
switch (permission)
{
case ALLOW_LOG:
CurrentActor.get().message(AccessControlMessages.ALLOWED(
- action.getOperation().toString(), action.getObjectType().toString(), action.getProperties().toString()));
+ action.getOperation().toString(),
+ action.getObjectType().toString(),
+ action.getProperties().toString()));
case ALLOW:
return Result.ALLOWED;
case DENY_LOG:
CurrentActor.get().message(AccessControlMessages.DENIED(
- action.getOperation().toString(), action.getObjectType().toString(), action.getProperties().toString()));
+ action.getOperation().toString(),
+ action.getObjectType().toString(),
+ action.getProperties().toString()));
case DENY:
return Result.DENIED;
}
@@ -446,8 +409,7 @@ public class RuleSet
{
final Principal principal = iterator.next();
- if (rule.getIdentity().equalsIgnoreCase(principal.getName())
- || (_aclGroups.containsKey(rule.getIdentity()) && _aclGroups.get(rule.getIdentity()).contains(principal.getName())))
+ if (rule.getIdentity().equalsIgnoreCase(principal.getName()))
{
return true;
}
@@ -476,5 +438,4 @@ public class RuleSet
}
return objects;
}
-
}
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/AccessControlFirewallException.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/AccessControlFirewallException.java
new file mode 100644
index 0000000000..d08a052efd
--- /dev/null
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/AccessControlFirewallException.java
@@ -0,0 +1,47 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.security.access.firewall;
+
+public class AccessControlFirewallException extends RuntimeException
+{
+ /** serialVersionUID */
+ private static final long serialVersionUID = 4526157149690917805L;
+
+ public AccessControlFirewallException()
+ {
+ super();
+ }
+
+ public AccessControlFirewallException(String message)
+ {
+ super(message);
+ }
+
+ public AccessControlFirewallException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public AccessControlFirewallException(Throwable cause)
+ {
+ super(cause);
+ }
+} \ No newline at end of file
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/FirewallRule.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/FirewallRule.java
new file mode 100644
index 0000000000..482a795693
--- /dev/null
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/FirewallRule.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.server.security.access.firewall;
+
+import java.net.InetAddress;
+
+public interface FirewallRule
+{
+ boolean matches(InetAddress addressOfClient);
+}
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlActivator.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/FirewallRuleFactory.java
index 7c83446cf1..64be26c209 100644
--- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlActivator.java
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/FirewallRuleFactory.java
@@ -1,5 +1,4 @@
/*
- *
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -7,35 +6,28 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
- *
*/
-package org.apache.qpid.server.security.access.plugins;
+package org.apache.qpid.server.security.access.firewall;
-import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
-import org.apache.qpid.server.security.SecurityPluginActivator;
-import org.apache.qpid.server.security.SecurityPluginFactory;
-
-/**
- * The OSGi {@link org.osgi.framework.BundleActivator} for {@link AccessControl}.
- */
-public class AccessControlActivator extends SecurityPluginActivator
+public class FirewallRuleFactory
{
- public SecurityPluginFactory getFactory()
- {
- return AccessControl.FACTORY;
- }
+ public FirewallRule createForHostname(String[] hostnames)
+ {
+ return new HostnameFirewallRule(hostnames);
+ }
- public ConfigurationPluginFactory getConfigurationFactory()
+ public FirewallRule createForNetwork(String[] networks)
{
- return AccessControlConfiguration.FACTORY;
+ return new NetworkFirewallRule(networks);
}
+
}
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/HostnameFirewallRule.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/HostnameFirewallRule.java
new file mode 100644
index 0000000000..fb13426fbb
--- /dev/null
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/HostnameFirewallRule.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.server.security.access.firewall;
+
+import java.net.InetAddress;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+import org.apache.log4j.Logger;
+
+public class HostnameFirewallRule implements FirewallRule
+{
+ private static final Logger _logger = Logger.getLogger(HostnameFirewallRule.class);
+
+ private static final long DNS_TIMEOUT = 30000;
+ private static final ExecutorService DNS_LOOKUP = Executors.newCachedThreadPool();
+
+ private Pattern[] _hostnamePatterns;
+ private String[] _hostnames;
+
+ public HostnameFirewallRule(String... hostnames)
+ {
+ _hostnames = hostnames;
+
+ int i = 0;
+ _hostnamePatterns = new Pattern[hostnames.length];
+ for (String hostname : hostnames)
+ {
+ _hostnamePatterns[i++] = Pattern.compile(hostname);
+ }
+
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Created " + this);
+ }
+ }
+
+ @Override
+ public boolean matches(InetAddress remote)
+ {
+ String hostname = getHostname(remote);
+ if (hostname == null)
+ {
+ throw new AccessControlFirewallException("DNS lookup failed for address " + remote);
+ }
+ for (Pattern pattern : _hostnamePatterns)
+ {
+ boolean hostnameMatches = pattern.matcher(hostname).matches();
+
+ if (hostnameMatches)
+ {
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Hostname " + hostname + " matches rule " + pattern.toString());
+ }
+ return true;
+ }
+ }
+
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Hostname " + hostname + " matches no configured hostname patterns");
+ }
+
+ return false;
+ }
+
+
+ /**
+ * @param remote
+ * the InetAddress to look up
+ * @return the hostname, null if not found, takes longer than
+ * {@value #DNS_LOOKUP} to find or otherwise fails
+ */
+ private String getHostname(final InetAddress remote) throws AccessControlFirewallException
+ {
+ FutureTask<String> lookup = new FutureTask<String>(new Callable<String>()
+ {
+ public String call()
+ {
+ return remote.getCanonicalHostName();
+ }
+ });
+ DNS_LOOKUP.execute(lookup);
+
+ try
+ {
+ return lookup.get(DNS_TIMEOUT, TimeUnit.MILLISECONDS);
+ }
+ catch (Exception e)
+ {
+ _logger.warn("Unable to look up hostname from address " + remote, e);
+ return null;
+ }
+ finally
+ {
+ lookup.cancel(true);
+ }
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return new HashCodeBuilder().append(_hostnames).toHashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (obj == this)
+ {
+ return true;
+ }
+ if (obj.getClass() != getClass())
+ {
+ return false;
+ }
+ HostnameFirewallRule rhs = (HostnameFirewallRule) obj;
+ return new EqualsBuilder().append(_hostnames, rhs._hostnames).isEquals();
+ }
+
+ @Override
+ public String toString()
+ {
+ return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
+ .append(_hostnames).toString();
+ }
+}
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/InetNetwork.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/InetNetwork.java
new file mode 100644
index 0000000000..2e979b38f1
--- /dev/null
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/InetNetwork.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.server.security.access.firewall;
+
+import java.net.InetAddress;
+
+class InetNetwork
+{
+ /*
+ * Implements network masking, and is compatible with RFC 1518 and
+ * RFC 1519, which describe CIDR: Classless Inter-Domain Routing.
+ */
+
+ private InetAddress network;
+ private InetAddress netmask;
+
+ public InetNetwork(InetAddress ip, InetAddress netmask)
+ {
+ this.network = maskIP(ip, netmask);
+ this.netmask = netmask;
+ }
+
+ public boolean contains(final String name) throws java.net.UnknownHostException
+ {
+ return network.equals(maskIP(InetAddress.getByName(name), netmask));
+ }
+
+ public boolean contains(final InetAddress ip)
+ {
+ return network.equals(maskIP(ip, netmask));
+ }
+
+ @Override
+ public String toString()
+ {
+ return network.getHostAddress() + "/" + netmask.getHostAddress();
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return maskIP(network, netmask).hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ return (obj != null) &&
+ (obj instanceof InetNetwork) &&
+ ((InetNetwork)obj).network.equals(network) &&
+ ((InetNetwork)obj).netmask.equals(netmask);
+ }
+
+ public static InetNetwork getFromString(String netspec) throws java.net.UnknownHostException
+ {
+ if (netspec.endsWith("*"))
+ {
+ netspec = normalizeFromAsterisk(netspec);
+ }
+ else
+ {
+ int iSlash = netspec.indexOf('/');
+ if (iSlash == -1)
+ {
+ netspec += "/255.255.255.255";
+ }
+ else if (netspec.indexOf('.', iSlash) == -1)
+ {
+ netspec = normalizeFromCIDR(netspec);
+ }
+ }
+
+ return new InetNetwork(
+ InetAddress.getByName(netspec.substring(0, netspec.indexOf('/'))),
+ InetAddress.getByName(netspec.substring(netspec.indexOf('/') + 1)));
+ }
+
+ public static InetAddress maskIP(final byte[] ip, final byte[] mask)
+ {
+ try
+ {
+ return getByAddress(
+ new byte[]
+ {
+ (byte) (mask[0] & ip[0]),
+ (byte) (mask[1] & ip[1]),
+ (byte) (mask[2] & ip[2]),
+ (byte) (mask[3] & ip[3])
+ }
+ );
+ }
+ catch (Exception _)
+ {
+ return null;
+ }
+ }
+
+ public static InetAddress maskIP(final InetAddress ip, final InetAddress mask)
+ {
+ return maskIP(ip.getAddress(), mask.getAddress());
+ }
+
+ /*
+ * This converts from an uncommon "wildcard" CIDR format
+ * to "address + mask" format:
+ *
+ * * => 000.000.000.0/000.000.000.0
+ * xxx.* => xxx.000.000.0/255.000.000.0
+ * xxx.xxx.* => xxx.xxx.000.0/255.255.000.0
+ * xxx.xxx.xxx.* => xxx.xxx.xxx.0/255.255.255.0
+ */
+ static private String normalizeFromAsterisk(final String netspec)
+ {
+ String[] masks = { "0.0.0.0/0.0.0.0", "0.0.0/255.0.0.0", "0.0/255.255.0.0", "0/255.255.255.0" };
+ char[] srcb = netspec.toCharArray();
+ int octets = 0;
+ for (int i = 1; i < netspec.length(); i++)
+ {
+ if (srcb[i] == '.')
+ {
+ octets++;
+ }
+ }
+ return (octets == 0) ? masks[0] : netspec.substring(0, netspec.length() -1 ).concat(masks[octets]);
+ }
+
+ /*
+ * RFC 1518, 1519 - Classless Inter-Domain Routing (CIDR)
+ * This converts from "prefix + prefix-length" format to
+ * "address + mask" format, e.g. from xxx.xxx.xxx.xxx/yy
+ * to xxx.xxx.xxx.xxx/yyy.yyy.yyy.yyy.
+ */
+ static private String normalizeFromCIDR(final String netspec)
+ {
+ final int bits = 32 - Integer.parseInt(netspec.substring(netspec.indexOf('/')+1));
+ final int mask = (bits == 32) ? 0 : 0xFFFFFFFF - ((1 << bits)-1);
+
+ return netspec.substring(0, netspec.indexOf('/') + 1) +
+ Integer.toString(mask >> 24 & 0xFF, 10) + "." +
+ Integer.toString(mask >> 16 & 0xFF, 10) + "." +
+ Integer.toString(mask >> 8 & 0xFF, 10) + "." +
+ Integer.toString(mask >> 0 & 0xFF, 10);
+ }
+
+ private static InetAddress getByAddress(byte[] ip) throws java.net.UnknownHostException
+ {
+ InetAddress addr = InetAddress.getByAddress(ip);
+
+ if (addr == null) {
+ addr = InetAddress.getByName
+ (
+ Integer.toString(ip[0] & 0xFF, 10) + "." +
+ Integer.toString(ip[1] & 0xFF, 10) + "." +
+ Integer.toString(ip[2] & 0xFF, 10) + "." +
+ Integer.toString(ip[3] & 0xFF, 10)
+ );
+ }
+
+ return addr;
+ }
+} \ No newline at end of file
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRule.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRule.java
new file mode 100644
index 0000000000..ad619a0e0b
--- /dev/null
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRule.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.server.security.access.firewall;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+import org.apache.log4j.Logger;
+
+public class NetworkFirewallRule implements FirewallRule
+{
+ private static final Logger _logger = Logger.getLogger(NetworkFirewallRule.class);
+
+ private List<InetNetwork> _networks;
+
+ public NetworkFirewallRule(String... networks)
+ {
+ _networks = new ArrayList<InetNetwork>();
+ for (int i = 0; i < networks.length; i++)
+ {
+ String network = networks[i];
+ try
+ {
+ InetNetwork inetNetwork = InetNetwork.getFromString(network);
+ if (!_networks.contains(inetNetwork))
+ {
+ _networks.add(inetNetwork);
+ }
+ }
+ catch (java.net.UnknownHostException uhe)
+ {
+ _logger.error("Cannot resolve address: " + network, uhe);
+ }
+ }
+
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Created " + this);
+ }
+ }
+
+ @Override
+ public boolean matches(InetAddress ip)
+ {
+ for (InetNetwork network : _networks)
+ {
+ if (network.contains(ip))
+ {
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Client address " + ip + " matches configured network " + network);
+ }
+ return true;
+ }
+ }
+
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Client address " + ip + " does not match any configured networks");
+ }
+
+ return false;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return new HashCodeBuilder().append(_networks).toHashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (obj == this)
+ {
+ return true;
+ }
+ if (obj.getClass() != getClass())
+ {
+ return false;
+ }
+ NetworkFirewallRule rhs = (NetworkFirewallRule) obj;
+ return new EqualsBuilder().append(_networks, rhs._networks).isEquals();
+ }
+
+ @Override
+ public String toString()
+ {
+ return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
+ .append(_networks).toString();
+ }
+}
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/logging/AccessControl_logmessages.properties b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/logging/AccessControl_logmessages.properties
index bf80df3722..2a5eb7b3be 100644
--- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/logging/AccessControl_logmessages.properties
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/logging/AccessControl_logmessages.properties
@@ -25,4 +25,4 @@
ALLOWED = ACL-1001 : Allowed : {0} {1} {2}
# 'deny-log' rule message
-DENIED = ACL-1002 : Denied : {0} {1} {2} \ No newline at end of file
+DENIED = ACL-1002 : Denied : {0} {1} {2}
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java
deleted file mode 100644
index c4db6db820..0000000000
--- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.security.access.plugins;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.List;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
-import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
-import org.apache.qpid.server.security.access.config.ConfigurationFile;
-import org.apache.qpid.server.security.access.config.PlainConfiguration;
-import org.apache.qpid.server.security.access.config.RuleSet;
-
-public class AccessControlConfiguration extends ConfigurationPlugin
-{
- public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory()
- {
- public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException
- {
- ConfigurationPlugin instance = new AccessControlConfiguration();
- instance.setConfiguration(path, config);
- return instance;
- }
-
- public List<String> getParentPaths()
- {
- return Arrays.asList("security.acl", "virtualhosts.virtualhost.security.acl");
- }
- };
-
- private RuleSet _ruleSet;
-
- public String[] getElementsProcessed()
- {
- return new String[] { "" };
- }
-
- public String getFileName()
- {
- return getConfig().getString("");
- }
-
- public void validateConfiguration() throws ConfigurationException
- {
- String filename = getFileName();
- if (filename == null)
- {
- throw new ConfigurationException("No ACL file name specified");
- }
-
- File aclFile = new File(filename);
-
- ConfigurationFile configFile = new PlainConfiguration(aclFile);
- _ruleSet = configFile.load();
- }
-
- public RuleSet getRuleSet()
- {
- return _ruleSet;
- }
-
-}
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java
index d8a5bd4085..6f7885da94 100644
--- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java
@@ -20,56 +20,47 @@
*/
package org.apache.qpid.server.security.access.plugins;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.io.File;
+
import javax.security.auth.Subject;
import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.lang.ObjectUtils;
import org.apache.log4j.Logger;
-import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
-import org.apache.qpid.server.security.AbstractPlugin;
import org.apache.qpid.server.security.Result;
import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.server.security.SecurityPluginFactory;
+import org.apache.qpid.server.security.AccessControl;
import org.apache.qpid.server.security.access.ObjectProperties;
import org.apache.qpid.server.security.access.ObjectType;
import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.access.config.ConfigurationFile;
+import org.apache.qpid.server.security.access.config.PlainConfiguration;
import org.apache.qpid.server.security.access.config.RuleSet;
-/**
- * This access control plugin implements version two plain text access control.
- */
-public class AccessControl extends AbstractPlugin
+public class DefaultAccessControl implements AccessControl
{
- public static final Logger _logger = Logger.getLogger(AccessControl.class);
-
+ private static final Logger _logger = Logger.getLogger(DefaultAccessControl.class);
+
private RuleSet _ruleSet;
-
- public static final SecurityPluginFactory<AccessControl> FACTORY = new SecurityPluginFactory<AccessControl>()
- {
- public Class<AccessControl> getPluginClass()
- {
- return AccessControl.class;
- }
- public String getPluginName()
+ public DefaultAccessControl(String fileName)
+ {
+ if (_logger.isDebugEnabled())
{
- return AccessControl.class.getName();
+ _logger.debug("Creating AccessControl instance using file: " + fileName);
}
+ File aclFile = new File(fileName);
- public AccessControl newInstance(ConfigurationPlugin config) throws ConfigurationException
- {
- AccessControlConfiguration configuration = config.getConfiguration(AccessControlConfiguration.class.getName());
-
- // If there is no configuration for this plugin then don't load it.
- if (configuration == null)
- {
- return null;
- }
+ ConfigurationFile configFile = new PlainConfiguration(aclFile);
+ _ruleSet = configFile.load();
+ }
- AccessControl plugin = new AccessControl();
- plugin.configure(configuration);
- return plugin;
- }
- };
+ DefaultAccessControl(RuleSet rs) throws ConfigurationException
+ {
+ _ruleSet = rs;
+ }
public Result getDefault()
{
@@ -82,11 +73,18 @@ public class AccessControl extends AbstractPlugin
* Delegate to the {@link #authorise(Operation, ObjectType, ObjectProperties)} method, with
* the operation set to ACCESS and no object properties.
*/
- public Result access(ObjectType objectType, Object instance)
+ public Result access(ObjectType objectType, Object inetSocketAddress)
{
- return authorise(Operation.ACCESS, objectType, ObjectProperties.EMPTY);
+ InetAddress addressOfClient = null;
+
+ if(inetSocketAddress != null)
+ {
+ addressOfClient = ((InetSocketAddress) inetSocketAddress).getAddress();
+ }
+
+ return authoriseFromAddress(Operation.ACCESS, objectType, ObjectProperties.EMPTY, addressOfClient);
}
-
+
/**
* Check if an operation is authorised by asking the configuration object about the access
* control rules granted to the current thread's {@link Subject}. If there is no current
@@ -94,23 +92,31 @@ public class AccessControl extends AbstractPlugin
*/
public Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties)
{
+ return authoriseFromAddress(operation, objectType, properties, null);
+ }
+
+ public Result authoriseFromAddress(Operation operation, ObjectType objectType, ObjectProperties properties, InetAddress addressOfClient)
+ {
final Subject subject = SecurityManager.getThreadSubject();
// Abstain if there is no subject/principal associated with this thread
if (subject == null || subject.getPrincipals().size() == 0)
{
return Result.ABSTAIN;
}
-
- _logger.debug("Checking " + operation + " " + objectType);
- return _ruleSet.check(subject, operation, objectType, properties);
- }
- public void configure(ConfigurationPlugin config)
- {
- super.configure(config);
-
- AccessControlConfiguration accessConfig = (AccessControlConfiguration) getConfig();
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Checking " + operation + " " + objectType + " " + ObjectUtils.defaultIfNull(addressOfClient, ""));
+ }
- _ruleSet = accessConfig.getRuleSet();
+ try
+ {
+ return _ruleSet.check(subject, operation, objectType, properties, addressOfClient);
+ }
+ catch(Exception e)
+ {
+ _logger.error("Unable to check " + operation + " " + objectType + " " + ObjectUtils.defaultIfNull(addressOfClient, ""), e);
+ return Result.DENIED;
+ }
}
}
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java
new file mode 100644
index 0000000000..a3d7823caf
--- /dev/null
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java
@@ -0,0 +1,59 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.security.access.plugins;
+
+import java.io.File;
+import java.util.Map;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.plugin.AccessControlFactory;
+import org.apache.qpid.server.security.AccessControl;
+
+public class DefaultAccessControlFactory implements AccessControlFactory
+{
+ public static final String ATTRIBUTE_ACL_FILE = "aclFile";
+
+ public AccessControl createInstance(Map<String, Object> aclConfiguration)
+ {
+ if (aclConfiguration != null)
+ {
+ Object aclFile = aclConfiguration.get(ATTRIBUTE_ACL_FILE);
+ if (aclFile != null)
+ {
+ if (aclFile instanceof String)
+ {
+ String aclPath = (String) aclFile;
+ if (!new File(aclPath).exists())
+ {
+ throw new IllegalConfigurationException("ACL file '" + aclPath + "' is not found");
+ }
+ return new DefaultAccessControl(aclPath);
+ }
+ else
+ {
+ throw new IllegalConfigurationException("Expected '" + ATTRIBUTE_ACL_FILE + "' attribute value of type String but was " + aclFile.getClass()
+ + ": " + aclFile);
+ }
+ }
+ }
+ return null;
+ }
+}