From a6ffa6f49ae5d4c3311eb5ffdd74dc3a8d6c4f40 Mon Sep 17 00:00:00 2001
From: dugan <dugan@localhost>
Date: Thu, 14 Jun 2007 19:12:52 +0000
Subject: [PATCH] Add support for '+' all attributes description in targetattrs expression, with missing files from previous commit. See issue 1779 for more info.
---
opends/src/server/org/opends/server/authorization/dseecompat/Aci.java | 52 +++
opends/src/server/org/opends/server/authorization/dseecompat/AciTargets.java | 59 +++-
opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java | 89 +++++--
opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java | 41 ++-
opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/TargetAttrTestCase.java | 162 +++++++++++++
opends/src/server/org/opends/server/authorization/dseecompat/TargetAttr.java | 203 +++++++++-------
opends/src/server/org/opends/server/authorization/dseecompat/AciTargetMatchContext.java | 48 +++
opends/src/server/org/opends/server/messages/AciMessages.java | 35 --
8 files changed, 498 insertions(+), 191 deletions(-)
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/Aci.java b/opends/src/server/org/opends/server/authorization/dseecompat/Aci.java
index 6f5b75b..46ef3db 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/Aci.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/Aci.java
@@ -110,11 +110,12 @@
/**
* Regular expression that graciously matches an attribute type name. Must
* begin with an ASCII letter or digit, and contain only ASCII letters,
- * digit characters, hyphens, semi-colons and underscores.
- * They are case insensitive.
+ * digit characters, hyphens, semi-colons and underscores. It also allows
+ * the special shorthand characters "*" for all user attributes and "+" for
+ * all operational attributes.
*/
public static final String ATTR_NAME =
- "((?i)[a-z\\d]{1}[[a-z]\\d-_.;]*(?-i))";
+ "((?i)[a-z\\d]{1}[[a-z]\\d-_.;]*(?-i)|\\*{1}|\\+{1})";
/**
* Regular expression matching a LDAP URL.
@@ -150,8 +151,16 @@
/**
* Regular expression the matches "*".
*/
- public static final String ALL_ATTRS_WILD_CARD = ZERO_OR_MORE_WHITESPACE +
- "\\*" + ZERO_OR_MORE_WHITESPACE;
+ public static final String ALL_USER_ATTRS_WILD_CARD =
+ ZERO_OR_MORE_WHITESPACE +
+ "\\*" + ZERO_OR_MORE_WHITESPACE;
+
+ /**
+ * Regular expression the matches "+".
+ */
+ public static final String ALL_OP_ATTRS_WILD_CARD =
+ ZERO_OR_MORE_WHITESPACE +
+ "\\+" + ZERO_OR_MORE_WHITESPACE;
/**
* ACI_ADD is used to set the container rights for a LDAP add operation.
@@ -265,15 +274,38 @@
* evaluation if the flag is ACI_ATTR_STAR_MATCHED (all attributes match)
* and the attribute type is not operational.
*/
- public static final int ACI_ATTR_STAR_MATCHED = 0x0008;
+ public static final int ACI_USER_ATTR_STAR_MATCHED = 0x0008;
/**
- * ACI_FOUND_ATTR_RULE is the flag set when the evaluation reason of a
+ * ACI_FOUND_USER_ATTR_RULE is the flag set when the evaluation reason of a
* AciHandler.maysend ACI_READ access evaluation was the result of an
- * ACI targetattr specific attribute expression
- * (targetattr="some attribute type") target match.
+ * ACI targetattr specific user attribute expression
+ * (targetattr="some user attribute type") target match.
*/
- public static final int ACI_FOUND_ATTR_RULE = 0x0010;
+ public static final int ACI_FOUND_USER_ATTR_RULE = 0x0010;
+
+ /**
+ * ACI_OP_ATTR_PLUS_MATCHED is the flag set when the evaluation reason of a
+ * AciHandler.maysend ACI_READ access evaluation was the result of an
+ * ACI targetattr all operational attributes expression (targetattr="+")
+ * target match. For this flag to be set, there must be only one
+ * ACI matching.
+ *
+ * This flag and ACI_FOUND_OP_ATTR_RULE are used in the
+ * AciHandler.filterEntry.accessAllowedAttrs method to skip access
+ * evaluation if the flag is ACI_OP_ATTR_PLUS_MATCHED (all operational
+ * attributes match) and the attribute type is operational.
+ */
+
+ public static final int ACI_OP_ATTR_PLUS_MATCHED = 0x0004;
+
+ /**
+ * ACI_FOUND_OP_ATTR_RULE is the flag set when the evaluation reason of a
+ * AciHandler.maysend ACI_READ access evaluation was the result of an
+ * ACI targetattr specific operational attribute expression
+ * (targetattr="some operational attribute type") target match.
+ */
+ public static final int ACI_FOUND_OP_ATTR_RULE = 0x0020;
/**
* ACI_NULL is used to set the container rights to all zeros. Used
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java
index ff7da54..c2126da 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java
@@ -280,12 +280,20 @@
this.authzid=getEffectiveRightsControl.getAuthzDN();
this.specificAttrs=getEffectiveRightsControl.getAttributes();
}
- //If the ACI evaluated because of an Targetattr="*", then the
+ //If an ACI evaluated because of an Targetattr="*", then the
//AciHandler.maySend method signaled this via adding this attachment
//string.
- String allAttrs=(String)operation.getAttachment(ALL_ATTRS_MATCHED);
- if(allAttrs != null)
- evalAllAttributes = ACI_ATTR_STAR_MATCHED;
+ String allUserAttrs=
+ (String)operation.getAttachment(ALL_USER_ATTRS_MATCHED);
+ if(allUserAttrs != null)
+ evalAllAttributes |= ACI_USER_ATTR_STAR_MATCHED;
+ //If an ACI evaluated because of an Targetattr="+", then the
+ //AciHandler.maySend method signaled this via adding this attachment
+ //string.
+ String allOpAttrs=(String)operation.getAttachment(ALL_OP_ATTRS_MATCHED);
+ if(allOpAttrs != null)
+ evalAllAttributes |= ACI_OP_ATTR_PLUS_MATCHED;
+
//The AciHandler.maySend method also adds the full attribute version of
//the resource entry in this attachment.
fullEntry=(Entry)operation.getAttachment(ALL_ATTRS_RESOURCE_ENTRY);
@@ -823,43 +831,74 @@
/**
* {@inheritDoc}
*/
- public void setACIEvalAttributesRule(int v) {
+ public void setEvalUserAttributes(int v) {
if(operation instanceof SearchOperation && (rights == ACI_READ)) {
- if(v == ACI_FOUND_ATTR_RULE) {
- evalAllAttributes |= ACI_FOUND_ATTR_RULE;
- evalAllAttributes &= ~ACI_ATTR_STAR_MATCHED;
+ if(v == ACI_FOUND_USER_ATTR_RULE) {
+ evalAllAttributes |= ACI_FOUND_USER_ATTR_RULE;
+ evalAllAttributes &= ~ACI_USER_ATTR_STAR_MATCHED;
} else
- evalAllAttributes |= Aci.ACI_ATTR_STAR_MATCHED;
+ evalAllAttributes |= ACI_USER_ATTR_STAR_MATCHED;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setEvalOpAttributes(int v) {
+ if(operation instanceof SearchOperation && (rights == ACI_READ)) {
+ if(v == ACI_FOUND_OP_ATTR_RULE) {
+ evalAllAttributes |= ACI_FOUND_OP_ATTR_RULE;
+ evalAllAttributes &= ~ACI_OP_ATTR_PLUS_MATCHED;
+ } else
+ evalAllAttributes |= ACI_OP_ATTR_PLUS_MATCHED;
}
}
/**
* {@inheritDoc}
*/
- public boolean hasACIEvalAttributes() {
- return (evalAllAttributes & ACI_FOUND_ATTR_RULE) == ACI_FOUND_ATTR_RULE;
- }
-
-
- /**
- * Return true if the evaluating ACI either contained a targetattr all
- * attributes rule matched only.
- *
- * @return True if the above condition was seen.
- **/
- public boolean hasACIAllAttributes() {
- return (evalAllAttributes & ACI_ATTR_STAR_MATCHED) == ACI_ATTR_STAR_MATCHED;
+ public boolean hasEvalUserAttributes() {
+ return (evalAllAttributes & ACI_FOUND_USER_ATTR_RULE) ==
+ ACI_FOUND_USER_ATTR_RULE;
}
/**
* {@inheritDoc}
*/
- public void clearACIEvalAttributesRule(int v) {
+ public boolean hasEvalOpAttributes() {
+ return (evalAllAttributes & ACI_FOUND_OP_ATTR_RULE) ==
+ ACI_FOUND_OP_ATTR_RULE;
+ }
+
+ /**
+ * Return true if the evaluating ACI contained a targetattr all
+ * user attributes rule match.
+ *
+ * @return True if the above condition was seen.
+ **/
+ public boolean hasAllUserAttributes() {
+ return (evalAllAttributes & ACI_USER_ATTR_STAR_MATCHED) ==
+ ACI_USER_ATTR_STAR_MATCHED;
+ }
+
+ /**
+ * Return true if the evaluating ACI contained a targetattr all
+ * operational attributes rule match.
+ *
+ * @return True if the above condition was seen.
+ **/
+ public boolean hasAllOpAttributes() {
+ return (evalAllAttributes & ACI_OP_ATTR_PLUS_MATCHED) ==
+ ACI_OP_ATTR_PLUS_MATCHED;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void clearEvalAttributes(int v) {
if(v == 0)
evalAllAttributes=0;
else
evalAllAttributes &= ~v;
}
-
-
}
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
index 134262c..e934089 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
@@ -98,10 +98,16 @@
public static String ALL_ATTRS_RESOURCE_ENTRY = "allAttrsResourceEntry";
/**
- * String used to indicate that the evaluating ACI had a all attributes
+ * String used to indicate that the evaluating ACI had a all user attributes
* targetattr match (targetattr="*").
*/
- public static String ALL_ATTRS_MATCHED = "allAttrsMatched";
+ public static String ALL_USER_ATTRS_MATCHED = "allUserAttrsMatched";
+
+ /**
+ * String used to indicate that the evaluating ACI had a all operational
+ * attributes targetattr match (targetattr="+").
+ */
+ public static String ALL_OP_ATTRS_MATCHED = "allOpAttrsMatched";
/**
* This constructor instantiates the ACI handler class that performs the
@@ -603,17 +609,18 @@
*/
private SearchResultEntry
accessAllowedAttrs(AciLDAPOperationContainer container) {
- Entry e=container.getResourceEntry();
- List<AttributeType> typeList=getAllAttrs(e);
- for(AttributeType attrType : typeList) {
- if(container.hasACIAllAttributes() && !attrType.isOperational())
- continue;
- container.setCurrentAttributeType(attrType);
- if(!accessAllowed(container)) {
- e.removeAttribute(attrType);
+ Entry e=container.getResourceEntry();
+ List<AttributeType> typeList=getAllAttrs(e);
+ for(AttributeType attrType : typeList) {
+ if(container.hasAllUserAttributes() && !attrType.isOperational())
+ continue;
+ if(container.hasAllOpAttributes() && attrType.isOperational())
+ continue;
+ container.setCurrentAttributeType(attrType);
+ if(!accessAllowed(container))
+ e.removeAttribute(attrType);
}
- }
- return container.getSearchResultEntry();
+ return container.getSearchResultEntry();
}
/**
@@ -916,12 +923,16 @@
ret=false;
}
if (ret) {
- operationContainer.clearACIEvalAttributesRule(ACI_NULL);
+ operationContainer.clearEvalAttributes(ACI_NULL);
operationContainer.setRights(ACI_READ);
ret=accessAllowedEntry(operationContainer);
if(ret) {
- if(!operationContainer.hasACIEvalAttributes())
- operation.setAttachment(ALL_ATTRS_MATCHED, ALL_ATTRS_MATCHED);
+ if(!operationContainer.hasEvalUserAttributes())
+ operation.setAttachment(ALL_USER_ATTRS_MATCHED,
+ ALL_USER_ATTRS_MATCHED);
+ if(!operationContainer.hasEvalOpAttributes())
+ operation.setAttachment(ALL_OP_ATTRS_MATCHED,
+ ALL_OP_ATTRS_MATCHED);
}
}
}
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciTargetMatchContext.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciTargetMatchContext.java
index d6fb958..33f4db1 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciTargetMatchContext.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciTargetMatchContext.java
@@ -168,38 +168,64 @@
/**
* This method toggles a mask that indicates that access checking of
- * individual non-operational attributes may or may not be skipped depending
- * on if there is a single ACI containing a targetattr all attributes rule
- * (targetattr="*").
+ * individual user attributes may or may not be skipped depending
+ * on if there is a single ACI containing a targetattr all user
+ * attributes rule (targetattr="*").
*
- * The only case where individual non-operational attribute access checking
+ * The only case where individual user attribute access checking
* can be skipped, is when a single ACI matched using a targetattr
- * all attributes rule.
+ * all user attributes rule and the attribute type being check is not
+ * operational.
*
* @param v The mask to this value.
*/
- void setACIEvalAttributesRule(int v);
+ void setEvalUserAttributes(int v);
+
+ /**
+ * This method toggles a mask that indicates that access checking of
+ * individual operational attributes may or may not be skipped depending
+ * on if there is a single ACI containing a targetattr all operational
+ * attributes rule (targetattr="+").
+ *
+ * The only case where individual operational attribute access checking
+ * can be skipped, is when a single ACI matched using a targetattr
+ * all operational attributes rule and the attribute type being check is
+ * operational.
+ *
+ * @param v The mask to this value.
+ */
+ void setEvalOpAttributes(int v);
/**
* Return true if the evaluating ACI either contained an explicitly defined
- * attribute type in a targeattr target rule or both a targetattr all
- * attributes rule matched and a explictly defined targetattr target rule
+ * user attribute type in a targeattr target rule or both a targetattr all
+ * user attributes rule matched and a explictly defined targetattr target rule
* matched.
*
* @return True if the above condition was seen.
*/
- boolean hasACIEvalAttributes();
+ boolean hasEvalUserAttributes();
+
+ /**
+ * Return true if the evaluating ACI either contained an explicitly defined
+ * operational attribute type in a targeattr target rule or both a targetattr
+ * all operational attributes rule matched and a explictly defined targetattr
+ * target rule matched.
+ *
+ * @return True if the above condition was seen.
+ */
+ boolean hasEvalOpAttributes();
/**
* Used to clear the mask used to detect if access checking needs to be
- * performed on individual non-operational attributes types. The specified
+ * performed on individual attributes types. The specified
* value is cleared from the mask or if the value equals 0 the mask is
* completely cleared.
*
* @param v The flag to clear or 0 to set the mask to 0.
*/
- public void clearACIEvalAttributesRule(int v);
+ public void clearEvalAttributes(int v);
}
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciTargets.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciTargets.java
index dc13132..41e58a0 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciTargets.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciTargets.java
@@ -412,21 +412,8 @@
int rights=targetMatchCtx.getRights();
boolean isFirstAttr=targetMatchCtx.isFirstAttribute();
if((a != null) && (targets.getTargetAttr() != null)) {
- ret=TargetAttr.isApplicable(a,targets.getTargetAttr());
- targetMatchCtx.clearACIEvalAttributesRule(ACI_ATTR_STAR_MATCHED);
- /*
- If a explicitly defined targetattr's match rule has not
- been seen (~ACI_FOUND_ATTR_RULE) and the current attribute type
- is applicable because of a targetattr all attributes rule match,
- set a flag to indicate this situation (ACI_ATTR_STAR_MATCHED).
- Else the attributes is applicable because it is operational or
- not a targetattr's all attribute match.
- */
- if(ret && targets.getTargetAttr().isAllAttributes() &&
- !targetMatchCtx.hasACIEvalAttributes())
- targetMatchCtx.setACIEvalAttributesRule(ACI_ATTR_STAR_MATCHED);
- else
- targetMatchCtx.setACIEvalAttributesRule(ACI_FOUND_ATTR_RULE);
+ ret=TargetAttr.isApplicable(a,targets.getTargetAttr());
+ setEvalAttributes(targetMatchCtx,targets,ret);
} else if((a != null) || (targets.getTargetAttr() != null)) {
if((aci.hasRights(skipRights)) &&
(skipRightsHasRights(rights)))
@@ -563,4 +550,46 @@
}
return ret;
}
+
+
+ /**
+ * The method is used to try and determine if a targetAttr expression that
+ * is applicable has a '*' (or '+' operational attributes) token or if it
+ * was applicable because of a specific attribute type declared in the
+ * targetattrs expression (i.e., targetattrs=cn).
+ *
+ *
+ * @param ctx The ctx to check against.
+ * @param targets The targets part of the ACI.
+ * @param ret The is true if the ACI has already been evaluated to be
+ * applicable.
+ */
+ private static
+ void setEvalAttributes(AciTargetMatchContext ctx, AciTargets targets,
+ boolean ret) {
+ ctx.clearEvalAttributes(ACI_USER_ATTR_STAR_MATCHED);
+ ctx.clearEvalAttributes(ACI_OP_ATTR_PLUS_MATCHED);
+ /*
+ If an applicable targetattr's match rule has not
+ been seen (~ACI_FOUND_OP_ATTR_RULE or ~ACI_FOUND_USER_ATTR_RULE) and
+ the current attribute type is applicable because of a targetattr all
+ user (or operational) attributes rule match,
+ set a flag to indicate this situation (ACI_USER_ATTR_STAR_MATCHED or
+ ACI_OP_ATTR_PLUS_MATCHED). This check also catches the following case
+ where the match was by a specific attribute type (either user or
+ operational) and the other attribute type has an all attribute token.
+ For example, the expression is: (targetattrs="cn || +) and the current
+ attribute type is cn.
+ */
+ if(ret && targets.getTargetAttr().isAllUserAttributes() &&
+ !ctx.hasEvalUserAttributes())
+ ctx.setEvalUserAttributes(ACI_USER_ATTR_STAR_MATCHED);
+ else
+ ctx.setEvalUserAttributes(ACI_FOUND_USER_ATTR_RULE);
+ if(ret && targets.getTargetAttr().isAllOpAttributes() &&
+ !ctx.hasEvalOpAttributes())
+ ctx.setEvalOpAttributes(ACI_OP_ATTR_PLUS_MATCHED);
+ else
+ ctx.setEvalOpAttributes(ACI_FOUND_OP_ATTR_RULE);
+ }
}
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/TargetAttr.java b/opends/src/server/org/opends/server/authorization/dseecompat/TargetAttr.java
index 9b2afff..c28633e 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/TargetAttr.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/TargetAttr.java
@@ -45,9 +45,14 @@
private EnumTargetOperator operator = EnumTargetOperator.EQUALITY;
/*
- * Flags that is set if all attributes pattern seen "*".
+ * Flags that is set if all user attributes pattern seen "*".
*/
- private boolean allAttributes = false ;
+ private boolean allUserAttributes = false ;
+
+ /*
+ * Flags that is set if all operational attributes pattern seen "+".
+ */
+ private boolean allOpAttributes = false ;
/*
* HashSet of the attribute types parsed by the constructor.
@@ -73,18 +78,21 @@
* @param operator The operation enumeration of the targetattr
* expression (=, !=).
* @param attrString A string representing the attributes specified in
- * the targetattr expression (ie, dn || cn).
+ * the targetattr expression (ie, dn || +).
* @throws AciException If the attrs string is invalid.
*/
private TargetAttr(EnumTargetOperator operator, String attrString)
throws AciException {
this.operator = operator;
if (attrString != null) {
- if (Pattern.matches(ALL_ATTRS_WILD_CARD, attrString) ){
- allAttributes = true ;
- } else {
+ if (Pattern.matches(ALL_USER_ATTRS_WILD_CARD, attrString) )
+ allUserAttributes = true ;
+ else if (Pattern.matches(ALL_OP_ATTRS_WILD_CARD, attrString) )
+ allOpAttributes = true ;
+ else {
if (Pattern.matches(ZERO_OR_MORE_WHITESPACE, attrString)){
- allAttributes = false;
+ allUserAttributes = false;
+ allOpAttributes=false;
} else {
if (Pattern.matches(attrListRegex, attrString)) {
// Remove the spaces in the attr string and
@@ -95,25 +103,9 @@
attrString.replaceAll(ZERO_OR_MORE_WHITESPACE, "");
String[] attributeArray=
separatorPattern.split(attrString);
- //Add each element of array to attributes HashSet
- //after converting it to AttributeType.
- arrayToAttributeTypes(attributeArray);
- //Must be either all operational attrs or all user attrs,
- //but not both.
- if(!opAttributes.isEmpty() && !attributes.isEmpty()) {
- int msgID =
- MSGID_ACI_TARGETATTR_INVALID_OP_USER_ATTR;
- String message = getMessage(msgID, attrString);
- throw new AciException(msgID, message);
- }
- //Inequality not allowed with operational attrs.
- if(!opAttributes.isEmpty() &&
- operator.equals(EnumTargetOperator.NOT_EQUALITY)) {
- int msgID =
- MSGID_ACI_TARGATTR_INVALID_OP_ATTR_INEQUALITY;
- String message = getMessage(msgID, attrString);
- throw new AciException(msgID, message);
- }
+ //Add each element of array to appropriate HashSet
+ //after conversion to AttributeType.
+ arrayToAttributeTypes(attributeArray, attrString);
} else {
int msgID =
MSGID_ACI_SYNTAX_INVALID_TARGETATTRKEYWORD_EXPRESSION;
@@ -126,23 +118,47 @@
}
/**
- * Converts each element of an array of attribute type strings
- * to attribute types and adds them to either the attributes HashSet or
- * the operational attributes HashSet if they are operational.
+ * Converts each element of an array of attribute strings
+ * to attribute types and adds them to either the user attributes HashSet or
+ * the operational attributes HashSet. Also, scan for the shorthand tokens
+ * "*" for all user attributes and "+" for all operational attributes.
+ *
* @param attributeArray The array of attribute type strings.
+ * @param attrStr String used in error message if an Aci Exception
+ * is thrown.
+ * @throws AciException If the one of the attribute checks fails.
*/
- private void arrayToAttributeTypes(String[] attributeArray) {
+ private void arrayToAttributeTypes(String[] attributeArray, String attrStr)
+ throws AciException {
for (int i=0, n=attributeArray.length; i < n; i++) {
String attribute=attributeArray[i].toLowerCase();
- AttributeType attributeType;
- if((attributeType =
- DirectoryServer.getAttributeType(attribute)) == null)
- attributeType =
- DirectoryServer.getDefaultAttributeType(attribute);
- if(attributeType.isOperational())
- opAttributes.add(attributeType);
- else
- attributes.add(attributeType);
+ if(attribute.equals("*")) {
+ if(!allUserAttributes)
+ allUserAttributes=true;
+ else {
+ int msgID = MSGID_ACI_TARGETATTR_INVALID_ATTR_TOKEN;
+ String message = getMessage(msgID, attrStr);
+ throw new AciException(msgID, message);
+ }
+ } else if(attribute.equals("+")) {
+ if(!allOpAttributes)
+ allOpAttributes=true;
+ else {
+ int msgID = MSGID_ACI_TARGETATTR_INVALID_ATTR_TOKEN;
+ String message = getMessage(msgID, attrStr);
+ throw new AciException(msgID, message);
+ }
+ } else {
+ AttributeType attributeType;
+ if((attributeType =
+ DirectoryServer.getAttributeType(attribute)) == null)
+ attributeType =
+ DirectoryServer.getDefaultAttributeType(attribute);
+ if(attributeType.isOperational())
+ opAttributes.add(attributeType);
+ else
+ attributes.add(attributeType);
+ }
}
}
@@ -159,8 +175,18 @@
* targetattr="*" or targetattr != "*".
* @return True if all attributes was seen.
*/
- public boolean isAllAttributes() {
- return allAttributes;
+ public boolean isAllUserAttributes() {
+ return allUserAttributes;
+ }
+
+
+ /**
+ * This flag is set if the parsing code saw:
+ * targetattr="+" or targetattr != "+".
+ * @return True if all attributes was seen.
+ */
+ public boolean isAllOpAttributes() {
+ return allOpAttributes;
}
/**
@@ -195,67 +221,64 @@
}
/**
- * Perform two checks to see if a specified attribute type is applicable.
- * First, check the targetAttr's isAllAttributes() boolean. The
- * isAllAttributes boolean is set true when the string:
+ * Performs test to see if the specified is applicable to the specified
+ * TargetAttr. First a check if the TargetAttr parsing code saw an
+ * expression like:
*
- * targetattrs="*"
+ * (targetattrs="+ || *), (targetattrs != "* || +)
*
- * is seen when an ACI is parsed. This boolean only applies to
- * non-operational attribute types. If the attribute type being evaluated
- * and the isAllAttributes is true, then the evaluation will return false
- * because operational attributes must be explicity defined.
+ * where both shorthand tokens where parsed. IF so then the attribute type
+ * matches automatically (or not matches if NOT_EQUALITY).
*
- * If the isAllAttributes boolean is true (and the attribute is
- * non-operational), the second check is skipped and the TargetAttr's
- * operator is checked to see if the method should return false
- * (NOT_EQUALITY) instead of true.
+ * If there isn't a match, then the method evalAttrType is called to further
+ * evaluate the attribute type and targetAttr combination.
*
- * If the isAllAttributes boolean is false, then the attribute type is
- * checked to see if it is operational. If it is, then the operational
- * HashSet is searched to see if it contains the operational attribute
- * type. If it is found then true is returned, else false is returned
- * if it isn't found. The NOT_EQUALITY operator is invalid for operational
- * attribute types and is not checked.
- *
- * If the attribute is not operational, then the TargeAttr's user
- * attribute type HashSet is searched to see if it contains the
- * specified attribute type. That result could be negated depending
- * on if the TargetAttr's operator is NOT_EQUALITY.
*
* @param a The attribute type to evaluate.
* @param targetAttr The ACI's TargetAttr class to evaluate against.
* @return The boolean result of the above tests and application
* TargetAttr's operator value applied to the test result.
*/
+
public static boolean isApplicable(AttributeType a,
TargetAttr targetAttr) {
- boolean ret;
- if(targetAttr.isAllAttributes()) {
- //If it is an operational attribute, then access is denied for all
- //attributes wild-card. Operational attributes must be
- // explicitly defined and cannot be negated.
- if(a.isOperational()) {
- ret=false;
+ boolean ret;
+ if(targetAttr.isAllUserAttributes() && targetAttr.isAllOpAttributes()) {
+ ret =
+ !targetAttr.getOperator().equals(EnumTargetOperator.NOT_EQUALITY);
} else
- ret =
- !targetAttr.getOperator().equals(EnumTargetOperator.NOT_EQUALITY);
- } else {
- ret=false;
- HashSet<AttributeType> attributes=targetAttr.getAttributes();
- HashSet<AttributeType> opAttributes=targetAttr.getOpAttributes();
- //Check if the attribute is operational, if so check the
- //operation HashSet.
- if(a.isOperational()) {
- if(opAttributes.contains(a))
- ret=true;
- } else {
- if(attributes.contains(a))
- ret=true;
- if(targetAttr.getOperator().equals(EnumTargetOperator.NOT_EQUALITY))
- ret = !ret;
- }
- }
- return ret;
+ ret=evalAttrType(a, targetAttr);
+
+ return ret;
+ }
+
+ /**
+ * First check is to see if the attribute type is operational. If so then
+ * a match is true if the allOpAttributes boolean is true or if the
+ * attribute type is found in the operational attributes HashSet.
+ *
+ * Second check is similar to above, except the user attributes boolean
+ * and HashSet is examined. Both results can be negated if the expression
+ * operator is NOT_EQUALITT).
+ *
+ * @param a The attribute type to evaluate.
+ * @param targetAttr The targetAttr to apply to the attribute type.
+ * @return True if the attribute type is applicable to the targetAttr.
+ */
+ private static
+ boolean evalAttrType(AttributeType a, TargetAttr targetAttr) {
+ boolean ret=false;
+ if(a.isOperational()) {
+ if(targetAttr.isAllOpAttributes() ||
+ targetAttr.opAttributes.contains(a))
+ ret=true;
+ } else {
+ if(targetAttr.isAllUserAttributes() ||
+ targetAttr.attributes.contains(a))
+ ret=true;
+ }
+ if(targetAttr.getOperator().equals(EnumTargetOperator.NOT_EQUALITY))
+ ret = !ret;
+ return ret;
}
}
diff --git a/opends/src/server/org/opends/server/messages/AciMessages.java b/opends/src/server/org/opends/server/messages/AciMessages.java
index 722a2e0..811b377 100644
--- a/opends/src/server/org/opends/server/messages/AciMessages.java
+++ b/opends/src/server/org/opends/server/messages/AciMessages.java
@@ -740,22 +740,15 @@
public static final int MSGID_ACI_NOT_VALID_DN =
CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 73;
- /**
- * The message ID for the message that will be used if a targetattr
- * keyword expression contains both operational and user attribute
- * types. This takes one argument, which is the targetattr expression string.
- */
- public static final int MSGID_ACI_TARGETATTR_INVALID_OP_USER_ATTR =
- CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 74;
-
/**
* The message ID for the message that will be used if a targetattr
- * keyword expression performs both an inequality operation using
- * operational attribute types. This takes one argument, which is the
- * targetattr expression string.
+ * keyword expression contains an error when a each token in an targetattr
+ * expression was parsed. This takes one argument, which is the expression
+ * string that caused the error.
*/
- public static final int MSGID_ACI_TARGATTR_INVALID_OP_ATTR_INEQUALITY =
- CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 75;
+ public static final int MSGID_ACI_TARGETATTR_INVALID_ATTR_TOKEN =
+ CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 74;
+
/**
* The message ID for the message that will be used if a roledn
@@ -763,7 +756,7 @@
* This takes one argument, which is the roledn expression string.
*/
public static final int MSGID_ACI_SYNTAX_ROLEDN_NOT_SUPPORTED =
- CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 76;
+ CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 75;
/**
* The message ID for the message that will be used if there are ACI decode
@@ -772,7 +765,7 @@
* exception.
*/
public static final int MSGID_ACI_SERVER_DECODE_FAILED =
- CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 77;
+ CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 76;
/**
@@ -781,7 +774,7 @@
* causing the server is being put in lockdown mode. The takes no arguments.
*/
public static final int MSGID_ACI_ENTER_LOCKDOWN_MODE =
- CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 78;
+ CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 77;
/**
@@ -1206,17 +1199,11 @@
"Selfwrite check skipped because an attribute \"%s\" with a " +
"distinguished name syntax was not a valid DN");
- registerMessage(MSGID_ACI_TARGETATTR_INVALID_OP_USER_ATTR,
+ registerMessage(MSGID_ACI_TARGETATTR_INVALID_ATTR_TOKEN,
"The provided Access Control Instruction (ACI) " +
"targetattr expression value \"%s\" is invalid because" +
- " the expression contains both operational attribute types" +
- " and user attribute types");
+ " the expression contains invalid or duplicate tokens");
- registerMessage(MSGID_ACI_TARGATTR_INVALID_OP_ATTR_INEQUALITY,
- "The provided Access Control Instruction (ACI) " +
- "targetattr expression value \"%s\" is invalid because" +
- " the expression performs an inequality operation using " +
- "operational attribute types");
registerMessage(MSGID_ACI_SYNTAX_ROLEDN_NOT_SUPPORTED,
"The provided Access Control Instruction (ACI) expression " +
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/TargetAttrTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/TargetAttrTestCase.java
index fe96c12..cfc978b 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/TargetAttrTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/TargetAttrTestCase.java
@@ -44,9 +44,46 @@
private static final String user3="uid=user.3,ou=People,o=test";
public static final String aciFilter = "(aci=*)";
+
+ private static final
+ String starAciAttrs = "(targetattr=\"* || aci\")" +
+ "(version 3.0;acl \"read/search all user, aci op\";" +
+ "allow (search, read) " +
+ "userattr=\"l#Austin\";)";
+
+ private static final
+ String ocOpAttrs = "(targetattr=\"objectclass || +\")" +
+ "(version 3.0;acl \"read/search all op, oc user\";" +
+ "allow (search, read) " +
+ "userattr=\"l#Austin\";)";
+
+ private static final
+ String OpSrchAttrs = "(targetattr=\"sn || uid || +\")" +
+ "(version 3.0;acl \"read/search all op, sn uid user\";" +
+ "allow (search, read) " +
+ "userattr=\"l#Austin\";)";
+
+ private static final
+ String allAttrs = "(targetattr=\"* || +\")" +
+ "(version 3.0;acl \"read/search all user and all op lattr\";" +
+ "allow (search, read) " +
+ "userattr=\"l#Austin\";)";
+
+ private static final
+ String allOpAttrAci1 = "(targetattr=\"+\")" +
+ "(version 3.0;acl \"read/search all op attr\";" +
+ "allow (search, read) " +
+ "userattr!=\"l#New York\";)";
+
+ private static final
+ String notAllOpAttrAci1 = "(targetattr!=\"+\")" +
+ "(version 3.0;acl \"read/search not all op attr\";" +
+ "allow (search, read) " +
+ "userattr!=\"l#New York\";)";
+
private static final
String userAttrAci = "(targetattr=\"*\")" +
- "(version 3.0;acl \"read/search userattr\";" +
+ "(version 3.0;acl \"read/search all userattr\";" +
"allow (search, read) " +
"userattr=\"l#Austin\";)";
@@ -164,6 +201,129 @@
deleteAttrFromEntry(user1, "aci");
}
+ /**
+ * Test targetattr shorthand behavior, all attrs both user and operational.
+ * See comments.
+ *
+ * @throws Exception If a test result is unexpected.
+ */
+ @Test()
+ public void testTargetAttrAllAttr() throws Exception {
+ //Add aci with: (targetattr = "+ || *")
+ String aciLdif=makeAddAciLdif("aci", user1, allAttrs);
+ modEntries(aciLdif, DIR_MGR_DN, PWD);
+ String userResults =
+ LDAPSearchParams(user3, PWD, null, null, null,
+ user1, filter, opAttrList);
+ Assert.assertFalse(userResults.equals(""));
+ HashMap<String, String> attrMap=getAttrMap(userResults);
+ //All should be returned.
+ Assert.assertTrue(attrMap.containsKey("aci"));
+ Assert.assertTrue(attrMap.containsKey("sn"));
+ Assert.assertTrue(attrMap.containsKey("uid"));
+ deleteAttrFromEntry(user1, "aci");
+ }
+
+
+ /**
+ * Test targetattr shorthand behavior, userattr and plus sign (all op attrs).
+ * See comments.
+ *
+ * @throws Exception If a test result is unexpected.
+ */
+ @Test()
+ public void testTargetAttrOpPlusAttr() throws Exception {
+ //Add aci with: (targetattr = "objectclass|| +")
+ String aciLdif=makeAddAciLdif("aci", user1, ocOpAttrs);
+ modEntries(aciLdif, DIR_MGR_DN, PWD);
+ String userResults =
+ LDAPSearchParams(user3, PWD, null, null, null,
+ user1, filter, opAttrList);
+ Assert.assertFalse(userResults.equals(""));
+ HashMap<String, String> attrMap=getAttrMap(userResults);
+ //Only aci should be returned.
+ Assert.assertTrue(attrMap.containsKey("aci"));
+ Assert.assertFalse(attrMap.containsKey("sn"));
+ Assert.assertFalse(attrMap.containsKey("uid"));
+ deleteAttrFromEntry(user1, "aci");
+ }
+
+
+ /**
+ * Test targetattr shorthand behavior, star (all user attr) or aci attr.
+ * See comments.
+ *
+ * @throws Exception If a test result is unexpected.
+ */
+ @Test()
+ public void testTargetAttrUserStarAttr() throws Exception {
+ //Add aci with: (targetattr = "*|| aci")
+ String aciLdif=makeAddAciLdif("aci", user1, starAciAttrs);
+ modEntries(aciLdif, DIR_MGR_DN, PWD);
+ String userResults =
+ LDAPSearchParams(user3, PWD, null, null, null,
+ user1, filter, opAttrList);
+ Assert.assertFalse(userResults.equals(""));
+ HashMap<String, String> attrMap=getAttrMap(userResults);
+ //All should be returned.
+ Assert.assertTrue(attrMap.containsKey("aci"));
+ Assert.assertTrue(attrMap.containsKey("sn"));
+ Assert.assertTrue(attrMap.containsKey("uid"));
+ deleteAttrFromEntry(user1, "aci");
+ }
+
+ /**
+ * Test targetattr shorthand behavior using '+' in expression and an
+ * operational attribute in the filter. The second test is two ACIs one
+ * with targetattr='+' and the other with targetattr='*'.
+ *
+ * @throws Exception If test result is unexpected.
+ */
+ @Test()
+ public void testTargetAttrSrchShorthand() throws Exception {
+ //Aci: (targetattrs="sn || uid || +) and search with an
+ //operational attr (aci).
+ String aciLdif=makeAddAciLdif("aci", user1, OpSrchAttrs);
+ modEntries(aciLdif, DIR_MGR_DN, PWD);
+ String userResults =
+ LDAPSearchParams(user3, PWD, null, null, null,
+ user1, aciFilter, opAttrList);
+ Assert.assertFalse(userResults.equals(""));
+ HashMap<String, String> attrMap=getAttrMap(userResults);
+ //All should be returned.
+ Assert.assertTrue(attrMap.containsKey("aci"));
+ Assert.assertTrue(attrMap.containsKey("sn"));
+ Assert.assertTrue(attrMap.containsKey("uid"));
+ deleteAttrFromEntry(user1, "aci");
+ //Add two ACIs, one with '+' and the other with '*'.
+ String aciLdif1=makeAddAciLdif("aci", user1, allOpAttrAci1, userAttrAci);
+ modEntries(aciLdif1, DIR_MGR_DN, PWD);
+ String userResults1 =
+ LDAPSearchParams(user3, PWD, null, null, null,
+ user1, aciFilter, opAttrList);
+ Assert.assertFalse(userResults1.equals(""));
+ HashMap<String, String> attrMap1=getAttrMap(userResults1);
+ //All should be returned.
+ Assert.assertTrue(attrMap1.containsKey("aci"));
+ Assert.assertTrue(attrMap1.containsKey("sn"));
+ Assert.assertTrue(attrMap1.containsKey("uid"));
+ deleteAttrFromEntry(user1, "aci");
+ //Add two ACIs, one with '+' and the other with '*'.
+ String aciLdif2=makeAddAciLdif("aci", user1, notAllOpAttrAci1, userAttrAci);
+ modEntries(aciLdif2, DIR_MGR_DN, PWD);
+ String userResults2 =
+ LDAPSearchParams(user3, PWD, null, null, null,
+ user1, filter, opAttrList);
+ Assert.assertFalse(userResults2.equals(""));
+ HashMap<String, String> attrMap2=getAttrMap(userResults2);
+ //Only non-operation should be returned.
+ Assert.assertFalse(attrMap2.containsKey("aci"));
+ Assert.assertTrue(attrMap2.containsKey("sn"));
+ Assert.assertTrue(attrMap2.containsKey("uid"));
+ deleteAttrFromEntry(user1, "aci");
+ }
+
+
private void
checkAttributeVal(HashMap<String, String> attrMap, String attr,
String val) throws Exception {
--
Gitblit v1.10.0