opendj-sdk/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 opendj-sdk/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; } } opendj-sdk/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); } } } opendj-sdk/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); } opendj-sdk/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); } } opendj-sdk/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; } } opendj-sdk/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 " + opendj-sdk/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 {