From 14c5f3996a46c1281cb133de439f25492c97530a Mon Sep 17 00:00:00 2001
From: dugan <dugan@localhost>
Date: Wed, 07 Mar 2007 14:56:34 +0000
Subject: [PATCH] These changes are mostly related to restructuring the regular expression patterns to make them more readable by defining constants.
---
opends/src/server/org/opends/server/authorization/dseecompat/AciException.java | 4
opends/src/server/org/opends/server/authorization/dseecompat/IpCriteria.java | 13
opends/src/server/org/opends/server/authorization/dseecompat/TimeOfDay.java | 12
opends/src/server/org/opends/server/authorization/dseecompat/TargAttrFilters.java | 354 ++++++++
opends/src/server/org/opends/server/authorization/dseecompat/UserDNTypeURL.java | 4
opends/src/server/org/opends/server/authorization/dseecompat/AciListenerManager.java | 11
opends/src/server/org/opends/server/authorization/dseecompat/TargetAttr.java | 50
opends/src/server/org/opends/server/authorization/dseecompat/AciProvider.java | 6
opends/src/server/org/opends/server/authorization/dseecompat/PermBindRulePair.java | 7
opends/src/server/org/opends/server/authorization/dseecompat/EnumTargetKeyword.java | 5
opends/src/server/org/opends/server/authorization/dseecompat/AciTargets.java | 179 +++-
opends/src/server/org/opends/server/authorization/dseecompat/UserDN.java | 13
opends/src/server/org/opends/server/authorization/dseecompat/EnumBooleanTypes.java | 3
opends/src/server/org/opends/server/authorization/dseecompat/AciBody.java | 168 +++-
opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTests.java | 145 ++-
opends/src/server/org/opends/server/authorization/dseecompat/EnumRight.java | 27
opends/src/server/org/opends/server/authorization/dseecompat/DayOfWeek.java | 7
opends/src/server/org/opends/server/authorization/dseecompat/Aci.java | 187 ++++
opends/src/server/org/opends/server/authorization/dseecompat/AciMessages.java | 170 ++++
opends/src/server/org/opends/server/authorization/dseecompat/ParentInheritance.java | 60 +
opends/src/server/org/opends/server/authorization/dseecompat/EnumDayOfWeek.java | 3
opends/src/server/org/opends/server/authorization/dseecompat/EnumTargetOperator.java | 3
opends/src/server/org/opends/server/authorization/dseecompat/TargetFilter.java | 10
opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java | 37
opends/src/server/org/opends/server/authorization/dseecompat/EnumBindRuleType.java | 3
opends/src/server/org/opends/server/authorization/dseecompat/EnumAuthMethod.java | 5
opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java | 153 +--
opends/src/server/org/opends/server/authorization/dseecompat/EnumEvalResult.java | 1
opends/src/server/org/opends/server/authorization/dseecompat/EnumAccessType.java | 4
opends/src/server/org/opends/server/authorization/dseecompat/TargAttrFilterList.java | 221 +++++
opends/src/server/org/opends/server/authorization/dseecompat/EnumUserDNType.java | 1
opends/src/server/org/opends/server/authorization/dseecompat/AciTargetMatchContext.java | 14
opends/src/server/org/opends/server/authorization/dseecompat/AciList.java | 3
opends/src/server/org/opends/server/authorization/dseecompat/BindRule.java | 69 +
opends/src/server/org/opends/server/authorization/dseecompat/Permission.java | 25
opends/src/server/org/opends/server/authorization/dseecompat/Target.java | 41
opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java | 5
opends/src/server/org/opends/server/authorization/dseecompat/EnumBindRuleKeyword.java | 6
opends/src/server/org/opends/server/authorization/dseecompat/DNS.java | 24
opends/src/server/org/opends/server/authorization/dseecompat/UserAttr.java | 111 +-
opends/src/server/org/opends/server/authorization/dseecompat/AuthMethod.java | 8
opends/src/server/org/opends/server/authorization/dseecompat/GroupDN.java | 28
opends/src/server/org/opends/server/authorization/dseecompat/RoleDN.java | 31
43 files changed, 1,781 insertions(+), 450 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 e881dd8..e29445b 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/Aci.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/Aci.java
@@ -37,6 +37,7 @@
* The Aci class represents ACI strings.
*/
public class Aci {
+
/*
* The body of the ACI is the version, name and permission-bind rule
* pairs.
@@ -53,6 +54,9 @@
*/
public static final String supportedVersion="3.0";
+ /*
+ * String representation of the ACI used.
+ */
private String aciString;
/*
@@ -60,13 +64,191 @@
*/
private DN dn;
+ /**
+ * Regular expression matching a word group.
+ */
+ public static final String WORD_GROUP="(\\w+)";
+
+ /**
+ * Regular expression matching a word group at the start of a
+ * pattern.
+ */
+ public static final String WORD_GROUP_START_PATTERN = "^" + WORD_GROUP;
+
+ /**
+ * Regular expression matching a white space.
+ */
+ public static final String ZERO_OR_MORE_WHITESPACE="\\s*";
+
+ /**
+ * Regular expression matching a white space at the start of a pattern.
+ */
+ public static final String ZERO_OR_MORE_WHITESPACE_START_PATTERN =
+ "^" + ZERO_OR_MORE_WHITESPACE ;
+
+ /**
+ * Regular expression matching a white space at the end of a pattern.
+ */
+ public static final String ZERO_OR_MORE_WHITESPACE_END_PATTERN =
+ ZERO_OR_MORE_WHITESPACE + "$";
+
+ /**
+ * Regular expression matching a ACL statement separator.
+ */
+ public static final String ACI_STATEMENT_SEPARATOR =
+ ZERO_OR_MORE_WHITESPACE + ";" + ZERO_OR_MORE_WHITESPACE;
+
/*
* This regular expression is used to do a quick syntax check
* when an ACI is being decoded.
*/
private static final String aciRegex =
- "^\\s*" + AciTargets.targetsRegex + "\\s*"+
- AciBody.bodyRegx + "\\s*$";
+ ZERO_OR_MORE_WHITESPACE_START_PATTERN + AciTargets.targetsRegex +
+ ZERO_OR_MORE_WHITESPACE + AciBody.bodyRegx +
+ ZERO_OR_MORE_WHITESPACE_END_PATTERN;
+
+ /**
+ * 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.
+ */
+ public static final String ATTR_NAME =
+ "((?i)[a-z\\d]{1}[[a-z]\\d-_.;]*(?-i))";
+
+ /**
+ * Regular expression matching a LDAP URL.
+ */
+ public static final String LDAP_URL = ZERO_OR_MORE_WHITESPACE +
+ "(ldap:///[^\\|]+)";
+
+ /**
+ * Regular expression used to match token that joins expressions (||).
+ */
+ public static final String LOGICAL_OR = "\\|\\|";
+
+ /**
+ * Regular expression used to match an open parenthesis.
+ */
+ public static final String OPEN_PAREN = "\\(";
+
+ /**
+ * Regular expression used to match a closed parenthesis.
+ */
+ public static final String CLOSED_PAREN = "\\)";
+
+ /**
+ * Regular expression used to match a single equal sign.
+ */
+ public static final String EQUAL_SIGN = "={1}";
+
+ /**
+ * Regular expression the matches "*".
+ */
+ public static final String ALL_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.
+ */
+ public static final int ACI_ADD = 0x0001;
+
+ /**
+ * ACI_DELETE is used to set the container rights for a LDAP
+ * delete operation.
+ */
+ public static final int ACI_DELETE = 0x0002;
+
+ /**
+ * ACI_READ is used to set the container rights for a LDAP
+ * search operation.
+ */
+ public static final int ACI_READ = 0x0004;
+
+ /**
+ * ACI_WRITE is used to set the container rights for a LDAP
+ * modify operation.
+ */
+ public static final int ACI_WRITE = 0x0008;
+
+ /**
+ * ACI_COMPARE is used to set the container rights for a LDAP
+ * compare operation.
+ */
+ public static final int ACI_COMPARE = 0x0010;
+
+ /**
+ * ACI_SEARCH is used to set the container rights a LDAP search operation.
+ */
+ public static final int ACI_SEARCH = 0x0020;
+
+ /**
+ * ACI_SELF is used for the SELFWRITE right. Currently not implemented.
+ */
+ public static final int ACI_SELF = 0x0040;
+
+ /**
+ * ACI_ALL is used to as a mask for all of the above. These
+ * six below are not masked by the ACI_ALL.
+ */
+ public static final int ACI_ALL = 0x007F;
+
+ /**
+ * ACI_PROXY is used for the PROXY right. Currently not used.
+ */
+ public static final int ACI_PROXY = 0x0080;
+
+ /**
+ * ACI_IMPORT is used to set the container rights for a LDAP
+ * modify dn operation. Currently not used.
+ */
+ public static final int ACI_IMPORT = 0x0100;
+
+ /**
+ * ACI_EXPORT is used to set the container rights for a LDAP
+ * modify dn operation. Currently not used.
+ */
+ public static final int ACI_EXPORT = 0x0200;
+
+ /**
+ * ACI_WRITE_ADD is used by the LDAP modify operation.
+ */
+ public static final int ACI_WRITE_ADD = 0x800;
+
+ /**
+ * ACI_WRITE_DELETE is used by the LDAP modify operation.
+ */
+ public static final int ACI_WRITE_DELETE = 0x400;
+
+ /**
+ * TARGATTRFILTER_ADD is used to specify that a
+ * targattrfilters ADD operation was seen in the ACI. For example,
+ * given an ACI with:
+ *
+ * (targattrfilters="add=mail:(mail=*@example.com)")
+ *
+ * The TARGATTRFILTERS_ADD flag would be set during ACI parsing in the
+ * TargAttrFilters class.
+ */
+ public static final int TARGATTRFILTERS_ADD = 0x1000;
+
+ /**
+ * TARGATTRFILTER_DELETE is used to specify that a
+ * targattrfilters DELETE operation was seen in the ACI. For example,
+ * given an ACI with:
+ *
+ * (targattrfilters="del=mail:(mail=*@example.com)")
+ *
+ * The TARGATTRFILTERS_DELETE flag would be set during ACI parsing in the
+ * TargAttrFilters class.
+ */
+ public static final int TARGATTRFILTERS_DELETE = 0x2000;
+
+ /**
+ * ACI_NULL is used to set the container rights to all zeros. Used
+ * by LDAP modify.
+ */
+ public static final int ACI_NULL = 0x0000;
/**
* Construct a new Aci from the provided arguments.
@@ -158,6 +340,7 @@
isApplicable(Aci aci, AciTargetMatchContext matchCtx) {
return AciTargets.isTargetApplicable(aci, matchCtx) &&
AciTargets.isTargetFilterApplicable(aci, matchCtx) &&
+ AciTargets.isTargAttrFiltersApplicable(aci, matchCtx) &&
AciTargets.isTargetAttrApplicable(aci, matchCtx);
}
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciBody.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciBody.java
index dd0c1e5..c5119e5 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciBody.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciBody.java
@@ -28,6 +28,7 @@
package org.opends.server.authorization.dseecompat;
import static org.opends.server.authorization.dseecompat.AciMessages.*;
+import static org.opends.server.authorization.dseecompat.Aci.*;
import static org.opends.server.messages.MessageHandler.getMessage;
import java.util.ArrayList;
import java.util.List;
@@ -40,57 +41,120 @@
*/
public class AciBody {
+ /*
+ * Regular expression group position for the version string.
+ */
private static final int VERSION = 1;
+
+ /*
+ * Regular expression group position for the namr string.
+ */
private static final int NAME = 2;
+
+ /*
+ * Regular expression group position for the permission string.
+ */
private static final int PERM = 1;
+
+ /*
+ * Regular expression group position for the rights string.
+ */
private static final int RIGHTS = 2;
+
+ /*
+ * Regular expression group position for the bindrule string.
+ */
private static final int BINDRULE = 3;
+
+ /*
+ * Index into the ACI string where the ACI body starts.
+ */
private int startPos=0;
+
/*
- * The name of the ACI, currently not used but parsed.
- */
+ * The name of the ACI, currently not used but parsed.
+ */
private String name = null;
+
/*
- * The version of the ACi, current not used but parsed and checked
- * for 3.0.
- */
+ * The version of the ACi, current not used but parsed and checked
+ * for 3.0.
+ */
private String version = null;
+
/*
This structure represents a permission-bind rule pairs. There can be
several of these.
*/
private List<PermBindRulePair> permBindRulePairs;
+
/*
- * TODO Define constants for these regular expressions to make them more
- * readable.
- * The regular expressions would probably be a lot easier
- * to understand if you defined a number of constants for the
- * individual components and then concatenated them. For example,
- * "\\s*" could be defined in a constant named ZERO_OR_MORE_SPACES.
- * This would also help make it easier to understand which parentheses
- * were part of the regex and which were part of the ACI syntax.
+ * Regular expression used to match the access type group (allow, deny) and
+ * the rights group "(read, write, ...)". The last pattern looks for a group
+ * surrounded by parenthesis. The group must contain at least one
+ * non-paren character.
*/
- private static final String permissionRegex = "(\\w+)\\s*\\(([^()]+)\\)";
- private static final String bindRuleRegex = "(.+?\"[)]*)\\s*;";
+ private static final
+ String permissionRegex =
+ WORD_GROUP + ZERO_OR_MORE_WHITESPACE + "\\(([^()]+)\\)";
+
+ /*
+ * Regular expression that matches a bind rule group at a coarse level. It
+ * matches any character one or more times, a single quotation and
+ * an optional right parenthesis.
+ */
+ private static final String bindRuleRegex =
+ "(.+?\"[)]*)" + ACI_STATEMENT_SEPARATOR;
+
+ /*
+ * Regular expression used to match the actions of the ACI. The actions
+ * are permissions and matching bind rules.
+ */
private static final String actionRegex =
- "\\s*" + permissionRegex + "\\s*" + bindRuleRegex;
+ ZERO_OR_MORE_WHITESPACE + permissionRegex +
+ ZERO_OR_MORE_WHITESPACE + bindRuleRegex;
+
+ /*
+ * Regular expression used to match the version value (digit.digit).
+ */
private static final String versionRegex = "(\\d\\.\\d)";
- private static final String versionToken = "(?i)version";
- private static final String aclToken = "(?i)acl";
+
+ /*
+ * Regular expression used to match the version token. Case insensitive.
+ */
+ private static final String versionToken = "(?i)version(?-i)";
+
+ /*
+ * Regular expression used to match the acl token. Case insensitive.
+ */
+ private static final String aclToken = "(?i)acl(?-i)";
+
/**
- * Regular expression used to parse the body of an ACI.
+ * Regular expression used to match the body of an ACI. This pattern is
+ * a general verification check.
*/
public static final String bodyRegx =
- "\\(\\s*" + versionToken + "\\s*"
- + versionRegex + "\\s*;\\s*" + aclToken + "\\s*\"(.*)\"\\s*;\\s*"
- + actionRegex + "\\s*\\)";
- /**
- * Regular expression used to parse the header of the ACI body. The
+ "\\(" + ZERO_OR_MORE_WHITESPACE + versionToken +
+ ZERO_OR_MORE_WHITESPACE + versionRegex +
+ ACI_STATEMENT_SEPARATOR + aclToken + ZERO_OR_MORE_WHITESPACE +
+ "\"(.*)\"" + ACI_STATEMENT_SEPARATOR + actionRegex +
+ ZERO_OR_MORE_WHITESPACE + "\\)";
+
+ public static final String bodyRegx1 =
+ "\\("+ Aci.ZERO_OR_MORE_WHITESPACE + versionToken +
+ Aci.ZERO_OR_MORE_WHITESPACE + versionRegex +
+ Aci.ACI_STATEMENT_SEPARATOR + aclToken + Aci.ZERO_OR_MORE_WHITESPACE +
+ "\"(.*)\"" + Aci.ACI_STATEMENT_SEPARATOR + actionRegex +
+ Aci.ZERO_OR_MORE_WHITESPACE + "\\)";
+ /*
+ * Regular expression used to match the header of the ACI body. The
* header is version and acl name.
*/
- public static final String header =
- "\\(\\s*" + versionToken + "\\s*"
- + versionRegex + "\\s*;\\s*" + aclToken + "\\s*\"(.*?)\"\\s*;";
+ private static final String header =
+ OPEN_PAREN + ZERO_OR_MORE_WHITESPACE + versionToken +
+ ZERO_OR_MORE_WHITESPACE +
+ versionRegex + ACI_STATEMENT_SEPARATOR + aclToken +
+ ZERO_OR_MORE_WHITESPACE + "\"(.*?)\"" + ACI_STATEMENT_SEPARATOR;
/**
* Construct an ACI body from the specified version, name and
@@ -128,7 +192,7 @@
if(bodyMatcher.find()) {
startPos=bodyMatcher.start();
version = bodyMatcher.group(VERSION);
- if (!version.equalsIgnoreCase(Aci.supportedVersion)) {
+ if (!version.equalsIgnoreCase(supportedVersion)) {
int msgID = MSGID_ACI_SYNTAX_INVAILD_VERSION;
String message = getMessage(msgID, version);
throw new AciException(msgID, message);
@@ -203,9 +267,6 @@
return startPos;
}
- //TODO Evaluate adding support for the "absolute" deny access
- // type precedence operator.
-
/**
* Performs an evaluation of the permission-bind rule pairs
* using the evaluation context. The method walks down
@@ -226,29 +287,32 @@
EnumEvalResult res=EnumEvalResult.FALSE;
List<PermBindRulePair>pairs=getPermBindRulePairs();
for(PermBindRulePair p : pairs) {
+ if(evalCtx.isDenyEval() &&
+ (p.hasAccessType(EnumAccessType.ALLOW)))
+ continue;
if(!p.hasRights(evalCtx.getRights()))
continue;
- res=p.getBindRule().evaluate(evalCtx);
- // The evaluation result could be FAIL. Stop processing and return
- //FAIL. Maybe an internal search failed.
- if((res != EnumEvalResult.TRUE) &&
- (res != EnumEvalResult.FALSE)) {
- res=EnumEvalResult.FAIL;
- break;
- //If the access type is DENY and the pair evaluated to TRUE,
- //then stop processing and return TRUE. A deny pair
- //succeeded.
- } else if((p.hasAccessType(EnumAccessType.DENY)) &&
- (res == EnumEvalResult.TRUE)) {
- res=EnumEvalResult.TRUE;
- break;
- //An allow access type evaluated TRUE, stop processing
- //and return TRUE.
- } else if((p.hasAccessType(EnumAccessType.ALLOW) &&
- (res == EnumEvalResult.TRUE))) {
- res=EnumEvalResult.TRUE;
- break;
- }
+ res=p.getBindRule().evaluate(evalCtx);
+ // The evaluation result could be FAIL. Stop processing and return
+ //FAIL. Maybe an internal search failed.
+ if((res != EnumEvalResult.TRUE) &&
+ (res != EnumEvalResult.FALSE)) {
+ res=EnumEvalResult.FAIL;
+ break;
+ //If the access type is DENY and the pair evaluated to TRUE,
+ //then stop processing and return TRUE. A deny pair
+ //succeeded.
+ } else if((p.hasAccessType(EnumAccessType.DENY)) &&
+ (res == EnumEvalResult.TRUE)) {
+ res=EnumEvalResult.TRUE;
+ break;
+ //An allow access type evaluated TRUE, stop processing
+ //and return TRUE.
+ } else if((p.hasAccessType(EnumAccessType.ALLOW) &&
+ (res == EnumEvalResult.TRUE))) {
+ res=EnumEvalResult.TRUE;
+ break;
+ }
}
return res;
}
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 0a32315..498f52a 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java
@@ -104,6 +104,11 @@
*/
private Operation operation;
+ /*
+ * True if a targattrfilters match was found.
+ */
+ private boolean targAttrFiltersMatch=false;
+
/**
* This constructor is used by all currently supported LDAP operations.
*
@@ -305,6 +310,7 @@
public void setRights(int rights) {
this.rights=rights;
}
+
/**
* Gets the hostname of the remote client.
* @return Cannonical hostname of remote client.
@@ -322,7 +328,7 @@
}
/**
- * Return true if this is an add operation.
+ * Return true if the current operation is a LDAP add operation.
* @return True if this is an add operation.
*/
public boolean isAddOperation() {
@@ -330,13 +336,32 @@
}
/**
- * Tries to determine the authentication information from the connection
- * class. The checks are for simple and SASL, anything else is not a
- * match. If the bind rule needs the SSL client flag then that needs
- * to be set. This code is used by the authmethod bind rule keyword.
+ * Set to true if the ACI had a targattrfilter rule that matched.
+ * @param v The value to use.
+ */
+ public void setTargAttrFiltersMatch(boolean v) {
+ this.targAttrFiltersMatch=v;
+ }
+
+ /**
+ * Return the value of the targAttrFiltersMatch variable. This is set to
+ * true if the ACI had a targattrfilter rule that matched.
+ * @return True if the ACI had a targattrfilter rule that matched.
+ */
+ public boolean getTargAttrFiltersMatch() {
+ return targAttrFiltersMatch;
+ }
+
+ /**
+ * Try to determine the authentication information from the current
+ * client connection. The checks are for simple and SASL, anything else
+ * is not a match. If the bind rule requires any SSL client authentication
+ * information then the "wantSSL" flag should be set. This code is used by
+ * the authmethod bind rule keyword.
+ *
* @param wantSSL True if the bind rule needs the ssl client auth check.
* @return Return an enumeration containing the authentication method
- * for this connection.
+ * type for this client connection.
*/
public EnumAuthMethod getAuthenticationMethod(boolean wantSSL) {
EnumAuthMethod method=EnumAuthMethod.AUTHMETHOD_NOMATCH;
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciException.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciException.java
index 49e4e5e..924a960 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciException.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciException.java
@@ -45,7 +45,9 @@
*/
private static final long serialVersionUID = -2763328522960628853L;
- // The unique message ID for the associated message.
+ /*
+ * The unique message ID for the associated message.
+ */
private int messageID;
/**
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 2ccd972..6341904 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
@@ -29,20 +29,11 @@
import org.opends.server.api.AccessControlHandler;
import static org.opends.server.authorization.dseecompat.AciMessages.*;
+import static org.opends.server.authorization.dseecompat.Aci.*;
import org.opends.server.core.*;
import static org.opends.server.loggers.Error.logError;
import static org.opends.server.messages.MessageHandler.getMessage;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.AttributeType;
-import org.opends.server.types.AttributeValue;
-import org.opends.server.types.DN;
-import org.opends.server.types.Entry;
-import org.opends.server.types.ErrorLogCategory;
-import org.opends.server.types.ErrorLogSeverity;
-import org.opends.server.types.Modification;
-import org.opends.server.types.Privilege;
-import org.opends.server.types.SearchResultEntry;
-import org.opends.server.types.SearchResultReference;
+import org.opends.server.types.*;
import static org.opends.server.util.StaticUtils.toLowerCase;
import java.util.LinkedList;
import java.util.List;
@@ -54,87 +45,6 @@
*/
public class AciHandler extends AccessControlHandler
{
-
-
- /**
- * ACI_ADD is used to set the container rights for a LDAP add operation.
- */
- public static final int ACI_ADD = 0x0001;
-
- /**
- * ACI_DELETE is used to set the container rights for a LDAP
- * delete operation.
- */
- public static final int ACI_DELETE = 0x0002;
-
- /**
- * ACI_READ is used to set the container rights for a LDAP
- * search operation.
- */
- public static final int ACI_READ = 0x0004;
-
- /**
- * ACI_WRITE is used to set the container rights for a LDAP
- * modify operation.
- */
- public static final int ACI_WRITE = 0x0008;
-
- /**
- * ACI_COMPARE is used to set the container rights for a LDAP
- * compare operation.
- */
- public static final int ACI_COMPARE = 0x0010;
-
- /**
- * ACI_SEARCH is used to set the container rights a LDAP search operation.
- */
- public static final int ACI_SEARCH = 0x0020;
-
- /**
- * ACI_SELF is used for the SELFWRITE right. Currently not implemented.
- */
- public static final int ACI_SELF = 0x0040;
-
- /**
- * ACI_ALL is used to as a mask for all of the above. These
- * six below are not masked by the ACI_ALL.
- */
- public static final int ACI_ALL = 0x007F;
-
- /**
- * ACI_PROXY is used for the PROXY right. Currently not implemented.
- */
- public static final int ACI_PROXY = 0x0080;
-
- /**
- * ACI_IMPORT is used to set the container rights for a LDAP
- * modify dn operation. Currently not implemented.
- */
- public static final int ACI_IMPORT = 0x0100;
-
- /**
- * ACI_EXPORT is used to set the container rights for a LDAP
- * modify dn operation. Currently not implemented.
- */
- public static final int ACI_EXPORT = 0x0200;
-
- /**
- * ACI_WRITE_ADD and ACI_WRITE_DELETE are used by the LDAP modify
- * operation. They currently don't have much value; but will be needed
- * once the targetattrfilters target and modify dn are implemented.
- */
- public static final int ACI_WRITE_ADD = 0x800;
- /**
- * See above.
- */
- public static final int ACI_WRITE_DELETE = 0x400;
-
- /**
- * ACI_NULL is used to set the container rights to all zeros. Used
- * by LDAP modify.
- */
- public static final int ACI_NULL = 0x0000;
-
/*
* The list that holds that ACIs keyed by the DN of the entry
* holding the ACI.
@@ -511,6 +421,39 @@
}
/**
+ * Test the attribute types of the search filter for access. This method
+ * supports the search right.
+ *
+ * @param container The container used in the access evaluation.
+ * @param filter The filter to check access on.
+ * @return True if all attribute types in the filter have access.
+ */
+ private boolean
+ testFilter(AciLDAPOperationContainer container, SearchFilter filter) {
+ boolean ret=true;
+ switch (filter.getFilterType()) {
+ case AND:
+ case OR: {
+ for (SearchFilter f : filter.getFilterComponents())
+ if(!testFilter(container, f))
+ return false ;
+ break;
+ }
+ case NOT: {
+ SearchFilter f = filter.getNotComponent();
+ ret=!testFilter(container, f);
+ break;
+ }
+ default: {
+ AttributeType attrType=filter.getAttributeType();
+ container.setCurrentAttributeType(attrType);
+ ret=accessAllowed(container);
+ }
+ }
+ return ret;
+ }
+
+ /**
* Evaluate an entry to be added to see if it has any "aci"
* attribute type. If it does, examines each "aci" attribute type
* value for syntax errors. All of the "aci" attribute type values
@@ -657,19 +600,6 @@
skipAccessCheck(operation));
}
-
- /*
- * TODO Add access testing of the filter against the entry. This was
- * brought up in the first code review.
- *
- * The static block that creates the arrays of EnumRight objects needs to
- * be documented to explain what they are. Also, I still disagree with
- * the interpretation that the READ right is all that is necessary to
- * perform either search or compare operations. That definitely goes
- * against the documentation, which states that READ applies only to
- * the search operation, and that users must have both SEARCH and READ
- * in order to access the results.
- */
/**
* Checks access on a search operation.
* @param operation The search operation class containing information to
@@ -681,9 +611,16 @@
maySend(SearchOperation operation, SearchResultEntry entry) {
AciLDAPOperationContainer operationContainer =
new AciLDAPOperationContainer(operation,
- (ACI_READ | ACI_SEARCH), entry);
- return skipAccessCheck(operation) ||
- accessAllowedEntry(operationContainer);
+ (ACI_SEARCH), entry);
+ boolean ret;
+ if(!(ret=skipAccessCheck(operation))) {
+ ret=testFilter(operationContainer, operation.getFilter());
+ if (ret) {
+ operationContainer.setRights(ACI_READ);
+ ret=accessAllowedEntry(operationContainer);
+ }
+ }
+ return ret;
}
/*
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java
index 126eeb0..30b9560 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java
@@ -44,16 +44,17 @@
*/
public class AciLDAPOperationContainer extends AciContainer {
- /**
+ /*
* The entry to be returned if this is a LDAP search.
*/
private SearchResultEntry searchEntry;
- /**
+ /*
* The list of modifications if this operation is a LDAP
* modify.
*/
private List<Modification> modifications;
+
/**
* Constructor interface for the compare operation.
* @param operation The compare operation to evaluate.
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciList.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciList.java
index de2c477..90cfdfe 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciList.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciList.java
@@ -49,7 +49,8 @@
* using the entry DN as the key.
*/
public class AciList {
- /**
+
+ /*
* A map containing all the ACIs.
* We use the copy-on-write technique to avoid locking when reading.
*/
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciListenerManager.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciListenerManager.java
index f8f1eb5..3690dee 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciListenerManager.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciListenerManager.java
@@ -54,13 +54,17 @@
public class AciListenerManager
implements ChangeNotificationListener, BackendInitializationListener {
-
+ /*
+ * The AciList caches the ACIs.
+ */
private AciList aciList;
- /*
+
+ /*
* Search filter used in context search for "aci" attribute types.
*/
private static SearchFilter aciFilter;
- /**
+
+ /*
* The aci attribute type is operational so we need to specify it to be
* returned.
*/
@@ -77,6 +81,7 @@
}
attrs.add("aci");
}
+
/**
* Save the list created by the AciHandler routine.
* @param aciList The list object created and loaded by the handler.
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciMessages.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciMessages.java
index db9aa81..d75ac45 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciMessages.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciMessages.java
@@ -364,10 +364,10 @@
/**
* The message ID for the message that will be used if an "aci" attribute
* type value failed parsing because of an invalid target keyword operator.
- * This takes one argument, which is the target keyword operator string
- * parsed from the "aci" attribute type value string.
+ * This takes two arguments, which are the target keyword operator string
+ * parsed from the "aci" attribute type value string and the keyword string.
*/
- public static final int MSGID_ACI_SYNTAX_INVALID_TARGET_OPERATOR =
+ public static final int MSGID_ACI_SYNTAX_INVALID_TARGET_NOT_OPERATOR =
CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 35;
/**
@@ -392,11 +392,11 @@
/**
* The message ID for the message that will be used if an "aci" attribute
- * type value failed parsing because of an invalid targetscope keyword
- * operator. This takes one argument, which is the targetscope keyword
+ * type value failed parsing because of an invalid target keyword
+ * operator. This takes one argument, which is the target keyword
* operator string parsed from the "aci" attribute type value string.
*/
- public static final int MSGID_ACI_SYNTAX_INVALID_TARGETSCOPE_OPERATOR =
+ public static final int MSGID_ACI_SYNTAX_INVALID_TARGETS_OPERATOR =
CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 38;
/**
@@ -528,6 +528,88 @@
public static
final int MSGID_ACI_SYNTAX_INVALID_USERATTR_ROLEDN_INHERITANCE_PATTERN =
CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 51;
+
+ /**
+ * The message ID for the message that will be used if an "aci" attribute
+ * type value parse failed because a targattrfilters keyword expression
+ * did not parse because the operation was invalid. This takes two
+ * arguments, which are the targattrfilters expression parsed from the ACI
+ * and a message further clarifying the error.
+ */
+ public static
+ final int MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_OPERATION =
+ CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 52;
+
+ /**
+ * The message ID for the message that will be used if an "aci" attribute
+ * type value parse failed because a targattrfiltesr keyword expression
+ * did not parse. This takes one argument, which is the targattrfilters
+ * expression parsed from the ACI.
+ */
+ public static
+ final int MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_EXPRESSION =
+ CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 53;
+
+ /**
+ * The message ID for the message that will be used if an "aci" attribute
+ * type value parse failed because the operation tokens targattrfilters
+ * in the expresssion are the same. This takes one argument, which is
+ * the targattrfilters expression parsed from the ACI.
+ */
+ public static
+ final int MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_OPS_MATCH =
+ CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 54;
+
+ /**
+ * The message ID for the message that will be used if an "aci" attribute
+ * type value parse failed because the there are two many targattrfilters
+ * filter list statements in the ACI. This takes one argument, which is
+ * the targattrfilters expression parsed from the ACI.
+ */
+ public static
+ final int MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_MAX_FILTER_LISTS =
+ CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 55;
+
+ /**
+ * The message ID for the message that will be used if an "aci" attribute
+ * type value parse failed because the targattrfilters expression statement
+ * is in the wrong format. This takes one argument, which is
+ * the targattrfilters expression parsed from the ACI.
+ */
+ public static
+ final int MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_FILTER_LIST_FORMAT =
+ CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 56;
+
+ /**
+ * The message ID for the message that will be used if an "aci" attribute
+ * type value parse failed because one or more targattrfilters filter
+ * statements are invalid. This takes two arguments, which are
+ * the targattrfilters expression parsed from the ACI and an error
+ * message from the createFilterFromString method.
+ */
+ public static
+ final int MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_FILTER_LISTS_FILTER =
+ CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 57;
+
+ /**
+ * The message ID for the message that will be used if an "aci" attribute
+ * type value parse failed because one or more targattrfilters filter
+ * statements contain invalid attribute type names. This takes one
+ * argument, which is the targattrfilters expression parsed from the ACI.
+ */
+ public static final
+ int MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_FILTER_LISTS_ATTR_FILTER =
+ CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 58;
+
+ /**
+ * The message ID for the message that will be used if an "aci" attribute
+ * type name is invalid. This takes one
+ * argument, which is the attribute type name parsed from the ACI.
+ */
+ public static final
+ int MSGID_ACI_SYNTAX_INVALID_ATTRIBUTE_TYPE_NAME =
+ CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 59;
+
/**
* Associates a set of generic messages with the message IDs defined in
* this class.
@@ -559,7 +641,7 @@
"The provided Access Control Instruction (ACI) rights " +
"keyword values \"%s\" are invalid. The valid rights " +
"keyword values are one or more of the following: read, " +
- "write, add, delete, search, compare or the single value" +
+ "write, add, delete, search, compare or the single value " +
"all.");
registerMessage(MSGID_ACI_SYNTAX_BIND_RULE_MISSING_CLOSE_PAREN,
@@ -733,7 +815,7 @@
" value is one of the following: target, targetscope, " +
"targetfilter, targetattr or targetattrfilters.");
- registerMessage(MSGID_ACI_SYNTAX_INVALID_TARGET_OPERATOR,
+ registerMessage(MSGID_ACI_SYNTAX_INVALID_TARGETS_OPERATOR,
"The provided Access Control Instruction (ACI) target " +
"keyword operator value \"%s\" is invalid. A valid target" +
"keyword operator value is either '=' or \"!=\".");
@@ -747,10 +829,10 @@
"target keyword value \"%s\" was seen multiple times in" +
" the ACI \"%s\".");
- registerMessage(MSGID_ACI_SYNTAX_INVALID_TARGETSCOPE_OPERATOR,
- "The provided Access Control Instruction (ACI) targetscope" +
- " keyword operator value \"%s\" is invalid. The only valid" +
- "targetscope operator value is '='.");
+ registerMessage(MSGID_ACI_SYNTAX_INVALID_TARGET_NOT_OPERATOR,
+ "The provided Access Control Instruction (ACI) target" +
+ " operator value \"%s\" is invalid. The only valid" +
+ "target operator value for the \"%s\" keyword is '='.");
registerMessage(MSGID_ACI_SYNTAX_INVALID_TARGETSCOPE_EXPRESSION,
"The provided Access Control Instruction (ACI) targetscope" +
@@ -775,7 +857,7 @@
"The provided Access Control Instruction (ACI) " +
"targetattr expression value \"%s\" is invalid. A valid " +
"targetattr keyword expression value requires one or more " +
- "attribute type values in the following format: " +
+ "valid attribute type names in the following format: " +
"attribute1 [|| attribute1] ... [|| attributen].");
registerMessage(
@@ -823,5 +905,67 @@
"userattr expression inheritance pattern value " +
"\"%s\" is invalid for the roledn keyword because it starts " +
"with the string \"parent[\".");
+
+ registerMessage(MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_OPERATION,
+ "The provided Access Control Instruction (ACI) " +
+ "targattrfilter expression value " +
+ "%s is invalid because %s.");
+
+ registerMessage(MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_EXPRESSION,
+ "The provided Access Control Instruction (ACI) " +
+ "targattrfilter expression value " +
+ "%s is invalid because it is not in the correct format." +
+ "A valid targattrsfilters expression value must be in " +
+ "the following format: "+
+ "\"add=attr1: F1 && attr2: F2 ... && attrn: Fn" +
+ ",del= attr1: F1 && attr2: F2 ... && attrn: Fn\"");
+
+ registerMessage(MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_OPS_MATCH,
+ "The provided Access Control Instruction (ACI) " +
+ "targattrfilter expression value " +
+ "%s is invalid because the both operation tokens " +
+ "match in the two filter lists.");
+
+ registerMessage(
+ MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_MAX_FILTER_LISTS,
+ "The provided Access Control Instruction (ACI) " +
+ "targattrfilters expression value " +
+ "%s is invalid because there are more than two" +
+ "filter list statements.");
+
+ registerMessage(
+ MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_FILTER_LIST_FORMAT,
+ "The provided Access Control Instruction (ACI) " +
+ "targattrfilters expression value " +
+ "%s is invalid because the provided filter list string " +
+ "is in the wrong format. A valid targattrfilters filter " +
+ "list must be in the following format: " +
+ "add=attr1: F1 && attr2: F2 ... && attrn: Fn .");
+
+ registerMessage(
+ MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_FILTER_LISTS_FILTER,
+ "The provided Access Control Instruction (ACI) " +
+ "targattrfilters expression value " +
+ "%s is invalid because the one or more of the specified" +
+ "filters are invalid for the following reason: " +
+ "%s.");
+
+ registerMessage(
+ MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_FILTER_LISTS_ATTR_FILTER,
+ "The provided Access Control Instruction (ACI) " +
+ "targattrfilters expression value " +
+ "%s is invalid because the one or more of the specified" +
+ "filters are invalid because of non-matching attribute" +
+ "type names in the filter.");
+
+ registerMessage(
+ MSGID_ACI_SYNTAX_INVALID_ATTRIBUTE_TYPE_NAME,
+ "The provided Access Control Instruction (ACI) " +
+ "attribute name value " +
+ "%s is invalid. A valid attribute type name must begin " +
+ "with an ASCII letter and must contain only ASCII letters," +
+ "digits or the \"-\" character.");
+
+
}
}
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciProvider.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciProvider.java
index 105f224..be0478b 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciProvider.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciProvider.java
@@ -38,11 +38,13 @@
*/
public class AciProvider implements AccessControlProvider {
-
+ /*
+ * The AciHandler does all the work in this package.
+ */
private static AciHandler instance = null;
/**
- * Create an aci provider. This doesn't do much.
+ * Create an aci provider.
*/
public AciProvider() {
super();
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 833309d..7fdb608 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciTargetMatchContext.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciTargetMatchContext.java
@@ -41,6 +41,7 @@
* checked on.
*/
public interface AciTargetMatchContext {
+
/**
* Set the deny ACI list.
* @param denyList The deny ACI list.
@@ -129,6 +130,19 @@
* @param rights The rights to set the container's rights to.
*/
public void setRights(int rights);
+
+ /**
+ * Set to true if the ACI had a targattrfilter rule that matched.
+ * @param v The value to use.
+ */
+ public void setTargAttrFiltersMatch(boolean v);
+
+ /**
+ * Return the value of the targAttrFiltersMatch variable. This is set to
+ * true if the ACI had a targattrfilter rule that matched.
+ * @return True if the ACI had a targattrfilter rule that matched.
+ */
+ public boolean getTargAttrFiltersMatch();
}
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 f21ac6e..8c90b10 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciTargets.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciTargets.java
@@ -28,6 +28,7 @@
package org.opends.server.authorization.dseecompat;
import static org.opends.server.authorization.dseecompat.AciMessages.*;
+import static org.opends.server.authorization.dseecompat.Aci.*;
import static org.opends.server.messages.MessageHandler.getMessage;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
@@ -40,47 +41,75 @@
* of an ACI before the ACI body and specifies the entry, attributes, or set
* of entries and attributes which the ACI controls access.
*
- * The four supported ACI target keywords currently
- * supported are: target, targetattr, targetscope and targetfilter.
- * Missing is support for targetattrfilters.
+ * The five supported ACI target keywords are: target, targetattr,
+ * targetscope, targetfilter and targattrfilters.
*/
public class AciTargets {
+
/*
* ACI syntax has a target keyword.
*/
private Target target = null ;
+
/*
* ACI syntax has a targetscope keyword.
*/
private SearchScope targetScope = SearchScope.WHOLE_SUBTREE;
+
/*
* ACI syntax has a targetattr keyword.
*/
private TargetAttr targetAttr = null ;
+
/*
* ACI syntax has a targetfilter keyword.
*/
private TargetFilter targetFilter=null;
- private TargAttrFilters targAttrFilters=null;
/*
- * These are used in the regular expression parsing.
+ * ACI syntax has a targattrtfilters keyword.
+ */
+ private TargAttrFilters targAttrFilters=null;
+
+ /*
+ * The number of regular expression group positions in a valid ACI target
+ * expression.
*/
private static final int targetElementCount = 3;
- private static final int targetKeywordPos = 1;
- private static final int targetOperatorPos = 2;
- private static final int targetExpressionPos = 3;
+
/*
- * TODO Make the regular expression strings below easier to
- * understand.
- *
- * The same note earlier about making regex values easier to
- * understand applies to this class as well.
+ * Regular expression group position of a target keyword.
+ */
+ private static final int targetKeywordPos = 1;
+
+ /*
+ * Regular expression group position of a target operator enumeration.
+ */
+ private static final int targetOperatorPos = 2;
+
+ /*
+ * Regular expression group position of a target expression statement.
+ */
+ private static final int targetExpressionPos = 3;
+
+ /*
+ * Regular expression used to match a single target rule.
*/
private static final String targetRegex =
- "\\(\\s*(\\w+)\\s*(!?=)\\s*\"([^\"]+)\"\\s*\\)\\s*";
+ OPEN_PAREN + ZERO_OR_MORE_WHITESPACE + WORD_GROUP +
+ ZERO_OR_MORE_WHITESPACE + "(!?=)" + ZERO_OR_MORE_WHITESPACE +
+ "\"([^\"]+)\"" + ZERO_OR_MORE_WHITESPACE + CLOSED_PAREN +
+ ZERO_OR_MORE_WHITESPACE;
+
+ private static final String targetRegex1 =
+ "\\(" + Aci.ZERO_OR_MORE_WHITESPACE + Aci.WORD_GROUP +
+ Aci.ZERO_OR_MORE_WHITESPACE + "(!?=)" + Aci.ZERO_OR_MORE_WHITESPACE +
+ "\"([^\"]+)\"" + Aci.ZERO_OR_MORE_WHITESPACE + "\\)" +
+ Aci.ZERO_OR_MORE_WHITESPACE;
+
/**
- * Regular expression used in target matching.
+ * Regular expression used to match one or more target rules. The patern is
+ * part of a general ACI verification.
*/
public static final String targetsRegex = "(" + targetRegex + ")*";
@@ -106,8 +135,7 @@
* for this ACI.
*/
- private static final int skipRights =
- (AciHandler.ACI_ADD | AciHandler.ACI_DELETE | AciHandler.ACI_PROXY);
+ private static final int skipRights = (ACI_ADD | ACI_DELETE | ACI_PROXY);
/**
* Creates an ACI target from the specified arguments. All of these
@@ -116,14 +144,17 @@
* @param targetAttr The ACI targetattr keyword if any.
* @param targetFilter The ACI targetfilter keyword if any.
* @param targetScope The ACI targetscope keyword if any.
+ * @param targAttrFilters The ACI targAttrFilters keyword if any.
*/
private AciTargets(Target targetEntry, TargetAttr targetAttr,
TargetFilter targetFilter,
- SearchScope targetScope) {
+ SearchScope targetScope,
+ TargAttrFilters targAttrFilters) {
this.target=targetEntry;
this.targetAttr=targetAttr;
this.targetScope=targetScope;
this.targetFilter=targetFilter;
+ this.targAttrFilters=targAttrFilters;
}
/**
@@ -162,6 +193,14 @@
}
/**
+ * Return the class representing the ACI targattrfilters keyword. May be
+ * null.
+ * @return The targattrfilters information.
+ */
+ public TargAttrFilters getTargAttrFilters() {
+ return targAttrFilters;
+ }
+ /**
* Decode an ACI's target part of the syntax from the string provided.
* @param input String representing an ACI target part of syntax.
* @param dn The DN of the entry containing the ACI.
@@ -197,7 +236,7 @@
EnumTargetOperator targetOperator =
EnumTargetOperator.createOperator(operator);
if (targetOperator == null) {
- int msgID = MSGID_ACI_SYNTAX_INVALID_TARGET_OPERATOR;
+ int msgID = MSGID_ACI_SYNTAX_INVALID_TARGETS_OPERATOR;
String message = getMessage(msgID, operator);
throw new AciException(msgID, message);
}
@@ -238,7 +277,7 @@
{
// Check the operator for the targetscope is EQUALITY
if (targetOperator == EnumTargetOperator.NOT_EQUALITY) {
- int msgID = MSGID_ACI_SYNTAX_INVALID_TARGETSCOPE_OPERATOR;
+ int msgID = MSGID_ACI_SYNTAX_INVALID_TARGET_NOT_OPERATOR;
String message = getMessage(msgID, operator);
throw new AciException(msgID, message);
}
@@ -253,31 +292,39 @@
}
else {
int msgID =
- MSGID_ACI_SYNTAX_INVALID_TARGET_DUPLICATE_KEYWORDS;
+ MSGID_ACI_SYNTAX_INVALID_TARGET_DUPLICATE_KEYWORDS;
String message =
- getMessage(msgID, "targetfilter", input);
+ getMessage(msgID, "targetfilter", input);
throw new AciException(msgID, message);
}
break;
}
- case KEYWORD_TARGATTRFILTERS:
- {
- if (targAttrFilters == null){
- targAttrFilters = TargAttrFilters.decode(targetOperator,
- expression);
- }
- else {
+ case KEYWORD_TARGATTRFILTERS:
+ {
+ if (targAttrFilters == null){
+ // Check the operator for the targattrfilters is EQUALITY
+ if (targetOperator == EnumTargetOperator.NOT_EQUALITY) {
int msgID =
- MSGID_ACI_SYNTAX_INVALID_TARGET_DUPLICATE_KEYWORDS;
- String message =
- getMessage(msgID, "targattrfilters", input);
+ MSGID_ACI_SYNTAX_INVALID_TARGET_NOT_OPERATOR;
+ String message = getMessage(msgID, operator);
throw new AciException(msgID, message);
}
- break;
+ targAttrFilters = TargAttrFilters.decode(targetOperator,
+ expression);
}
+ else {
+ int msgID =
+ MSGID_ACI_SYNTAX_INVALID_TARGET_DUPLICATE_KEYWORDS;
+ String message =
+ getMessage(msgID, "targattrfilters", input);
+ throw new AciException(msgID, message);
+ }
+ break;
+ }
}
}
- return new AciTargets(target, targetAttr, targetFilter, targetScope);
+ return new AciTargets(target, targetAttr, targetFilter,
+ targetScope, targAttrFilters);
}
/*
@@ -308,7 +355,7 @@
}
/**
- * Checks an ACI's targetfilter information against an target match
+ * Checks an ACI's targetfilter information against a target match
* context.
* @param aci The ACI to try an match the targetfilter of.
* @param matchCtx The target match context containing information needed
@@ -324,6 +371,32 @@
return ret;
}
+ /**
+ * Check an ACI's targattrfilters against a target match context.
+ * @param aci The ACI to match the targattrfilters against.
+ * @param matchCtx The target match context containing the information
+ * needed to perform the target match.
+ * @return True if the targattrfilters matched the target context.
+ */
+ public static boolean isTargAttrFiltersApplicable(Aci aci,
+ AciTargetMatchContext matchCtx) {
+ boolean ret=true;
+ TargAttrFilters targAttrFilters=aci.getTargets().getTargAttrFilters();
+ if(targAttrFilters != null) {
+ if((matchCtx.hasRights(ACI_ADD) &&
+ targAttrFilters.hasMask(TARGATTRFILTERS_ADD)) ||
+ (matchCtx.hasRights(ACI_DELETE) &&
+ targAttrFilters.hasMask(TARGATTRFILTERS_DELETE)))
+ ret=targAttrFilters.isApplicableAddDel(matchCtx);
+ else if((matchCtx.hasRights(ACI_WRITE_ADD) &&
+ targAttrFilters.hasMask(TARGATTRFILTERS_ADD)) ||
+ (matchCtx.hasRights(ACI_WRITE_DELETE) &&
+ targAttrFilters.hasMask(TARGATTRFILTERS_DELETE)))
+ ret=targAttrFilters.isApplicableMod(matchCtx);
+ }
+ return ret;
+ }
+
/*
* TODO Evaluate making this method more efficient.
* The isTargetAttrApplicable method looks a lot less efficient than it
@@ -338,26 +411,28 @@
* @return True if the targetattr matched the target context.
*/
public static boolean isTargetAttrApplicable(Aci aci,
- AciTargetMatchContext targetMatchCtx) {
+ AciTargetMatchContext targetMatchCtx) {
boolean ret=true;
- AciTargets targets=aci.getTargets();
- AttributeType a=targetMatchCtx.getCurrentAttributeType();
- int rights=targetMatchCtx.getRights();
- boolean isFirstAttr=targetMatchCtx.isFirstAttribute();
- if((a != null) && (targets.getTargetAttr() != null)) {
- ret=TargetAttr.isApplicable(a, targets.getTargetAttr());
- } else if((a != null) || (targets.getTargetAttr() != null)) {
- if((aci.hasRights(skipRights)) && (skipRightsHasRights(rights))) {
- ret=true;
- } else if ((targets.getTargetAttr() != null) &&
- (a == null) && (aci.hasRights(AciHandler.ACI_WRITE))) {
- ret = true;
- } else {
- ret = false;
+ if(!targetMatchCtx.getTargAttrFiltersMatch()) {
+ AciTargets targets=aci.getTargets();
+ AttributeType a=targetMatchCtx.getCurrentAttributeType();
+ int rights=targetMatchCtx.getRights();
+ boolean isFirstAttr=targetMatchCtx.isFirstAttribute();
+ if((a != null) && (targets.getTargetAttr() != null))
+ ret=TargetAttr.isApplicable(a, targets.getTargetAttr());
+ else if((a != null) || (targets.getTargetAttr() != null)) {
+ if((aci.hasRights(skipRights)) &&
+ (skipRightsHasRights(rights)))
+ ret=true;
+ else if ((targets.getTargetAttr() != null) &&
+ (a == null) && (aci.hasRights(ACI_WRITE)))
+ ret = true;
+ else
+ ret = false;
}
+ if((isFirstAttr) && (aci.getTargets().getTargetAttr() == null))
+ targetMatchCtx.setEntryTestRule(true);
}
- if((isFirstAttr) && (aci.getTargets().getTargetAttr() == null))
- targetMatchCtx.setEntryTestRule(true);
return ret;
}
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AuthMethod.java b/opends/src/server/org/opends/server/authorization/dseecompat/AuthMethod.java
index 9c58c50..5adc0ec 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AuthMethod.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AuthMethod.java
@@ -34,7 +34,15 @@
* The AuthMethod class represents an authmethod bind rule keyword expression.
*/
public class AuthMethod implements KeywordBindRule {
+
+ /*
+ * Enumeration representing the authentication method.
+ */
private EnumAuthMethod authMethod=null;
+
+ /*
+ * Enumeration representing the bind rule operation type.
+ */
private EnumBindRuleType type=null;
/**
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/BindRule.java b/opends/src/server/org/opends/server/authorization/dseecompat/BindRule.java
index 5d6a79e..011e3e1 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/BindRule.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/BindRule.java
@@ -28,6 +28,7 @@
package org.opends.server.authorization.dseecompat;
import static org.opends.server.authorization.dseecompat.AciMessages.*;
+import static org.opends.server.authorization.dseecompat.Aci.*;
import static org.opends.server.messages.MessageHandler.getMessage;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
@@ -38,38 +39,84 @@
* pair.
*/
public class BindRule {
+
/*
* This hash table holds the keyword bind rule mapping.
*/
private HashMap<String, KeywordBindRule> keywordRuleMap =
new HashMap<String, KeywordBindRule>();
- //True is a boolean "not" was seen.
+ /*
+ * True is a boolean "not" was seen.
+ */
private boolean negate=false;
- //Complex bind rules have left and right values.
+ /*
+ * Complex bind rules have left and right values.
+ */
private BindRule left = null;
private BindRule right = null;
- //Enumeration of the boolean type of the complex bind rule ("and" or "or").
+ /*
+ * Enumeration of the boolean type of the complex bind rule ("and" or "or").
+ */
private EnumBooleanTypes booleanType = null;
- //The keyword of a simple bind rule.
+ /*
+ * The keyword of a simple bind rule.
+ */
private EnumBindRuleKeyword keyword = null;
- //Regular expression stuff that needs to be made clearer.
+ /*
+ * Regular expression group position of a bind rule keyword.
+ */
private static final int keywordPos = 1;
+
+ /*
+ * Regular expression group position of a bind rule operation.
+ */
private static final int opPos = 2;
+
+ /*
+ * Regular expression group position of a bind rule expression.
+ */
private static final int expressionPos = 3;
- private static final String keywordRegex = "^(\\w+)";
- private static final String opRegex = "([!=<>]+)";
- private static final String expressionRegex = "\"([^\"]+)\"\\s*";
- private static final String bindruleRegex =
- keywordRegex + "\\s*" + opRegex + "\\s*" + expressionRegex;
+
+ /*
+ * Regular expression group position of the remainder part of an operand.
+ */
private static final int remainingOperandPos = 1;
+
+ /*
+ * Regular expression group position of the remainder of the bind rule.
+ */
private static final int remainingBindrulePos = 2;
+
+ /*
+ * Regular expression for valid bind rule operator group.
+ */
+ private static final String opRegGroup = "([!=<>]+)";
+
+ /*
+ * Regular expression for the expression part of a partially parsed
+ * bind rule.
+ */
+ private static final String expressionRegex =
+ "\"([^\"]+)\"" + ZERO_OR_MORE_WHITESPACE;
+
+ /*
+ * Regular expression for a single bind rule.
+ */
+ private static final String bindruleRegex =
+ WORD_GROUP_START_PATTERN + ZERO_OR_MORE_WHITESPACE +
+ opRegGroup + ZERO_OR_MORE_WHITESPACE + expressionRegex;
+
+ /*
+ * Regular expression of the remainder part of a partially parsed bind rule.
+ */
private static final String remainingBindruleRegex =
- "^\\s*(\\w+)\\s*(.*)$";
+ ZERO_OR_MORE_WHITESPACE_START_PATTERN + WORD_GROUP +
+ ZERO_OR_MORE_WHITESPACE + "(.*)$";
/**
* Constructor that takes an keyword enumeration and corresponding
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/DNS.java b/opends/src/server/org/opends/server/authorization/dseecompat/DNS.java
index ba97b91..9bb3171 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/DNS.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/DNS.java
@@ -28,6 +28,7 @@
package org.opends.server.authorization.dseecompat;
import static org.opends.server.authorization.dseecompat.AciMessages.*;
+import static org.opends.server.authorization.dseecompat.Aci.*;
import static org.opends.server.messages.MessageHandler.getMessage;
import java.util.LinkedList;
import java.util.regex.Matcher;
@@ -38,9 +39,28 @@
*/
public class DNS implements KeywordBindRule {
+ /*
+ * List of patterns to match against.
+ */
LinkedList<String> patterns=null;
+
+ /*
+ * The enumeration representing the bind rule type of the DNS rule.
+ */
private EnumBindRuleType type=null;
+ /*
+ * Regular expression group used to match a dns rule.
+ */
+ private static final String valueRegex = "([a-zA-Z0-9\\.\\-\\*]+)";
+
+ /*
+ * Regular expression group used to match one or more DNS values.
+ */
+ private static final String valuesRegExGroup =
+ valueRegex + ZERO_OR_MORE_WHITESPACE +
+ "(," + ZERO_OR_MORE_WHITESPACE + valueRegex + ")*";
+
/**
* Create a class representing a dns bind rule keyword.
* @param patterns List of dns patterns to match against.
@@ -62,9 +82,7 @@
public static DNS decode(String expr, EnumBindRuleType type)
throws AciException
{
- String valueRegex = "([a-zA-Z0-9\\.\\-\\*]+)";
- String valuesRegex = valueRegex + "\\s*(,\\s*" + valueRegex + ")*";
- if (!Pattern.matches(valuesRegex, expr)) {
+ if (!Pattern.matches(valuesRegExGroup, expr)) {
int msgID = MSGID_ACI_SYNTAX_INVALID_DNS_EXPRESSION;
String message = getMessage(msgID, expr);
throw new AciException(msgID, message);
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/DayOfWeek.java b/opends/src/server/org/opends/server/authorization/dseecompat/DayOfWeek.java
index f2af1ee..1e5cdf6 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/DayOfWeek.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/DayOfWeek.java
@@ -38,7 +38,14 @@
*/
public class DayOfWeek implements KeywordBindRule {
+ /*
+ * List containing the enumeration of the day of the week.
+ */
LinkedList<EnumDayOfWeek> days=null;
+
+ /*
+ * Enumeration representing the bind rule operation type.
+ */
private EnumBindRuleType type=null;
/**
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/EnumAccessType.java b/opends/src/server/org/opends/server/authorization/dseecompat/EnumAccessType.java
index 3a20a35..fcccc44 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/EnumAccessType.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/EnumAccessType.java
@@ -32,6 +32,7 @@
* types (allow, deny).
*/
public enum EnumAccessType {
+
/**
* Allow access type.
*/
@@ -41,6 +42,9 @@
*/
DENY ("deny");
+ /*
+ * The access type string.
+ */
private final String accessType;
/**
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/EnumAuthMethod.java b/opends/src/server/org/opends/server/authorization/dseecompat/EnumAuthMethod.java
index 1f12a12..7f3fe72 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/EnumAuthMethod.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/EnumAuthMethod.java
@@ -41,6 +41,7 @@
* This class provides an enumeration of the allowed authmethod types.
*/
public enum EnumAuthMethod {
+
/**
* The enumeration type when the bind rule has specified authentication of
* none.
@@ -76,10 +77,10 @@
*/
AUTHMETHOD_NOMATCH ("nomatch");
- /**
+ /*
* The name of the authmethod.
*/
- public String authmethod = null;
+ private String authmethod = null;
/**
* Creates a new enumeration type for this authmethod.
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/EnumBindRuleKeyword.java b/opends/src/server/org/opends/server/authorization/dseecompat/EnumBindRuleKeyword.java
index cfea957..d0ce121 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/EnumBindRuleKeyword.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/EnumBindRuleKeyword.java
@@ -32,6 +32,7 @@
* keyword types.
*/
public enum EnumBindRuleKeyword {
+
/**
* The enumeration type when the bind rule has specified keyword of
* userdn.
@@ -77,10 +78,11 @@
* authmethod.
*/
AUTHMETHOD ("authmethod");
- /**
+
+ /*
* The keyword name.
*/
- public final String keyword;
+ private final String keyword;
/**
* Creates a new enumeration type for the specified keyword.
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/EnumBindRuleType.java b/opends/src/server/org/opends/server/authorization/dseecompat/EnumBindRuleType.java
index 3e0a91d..f780ff3 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/EnumBindRuleType.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/EnumBindRuleType.java
@@ -31,6 +31,7 @@
* This class provides an enumeration of the allowed bind rule types.
*/
public enum EnumBindRuleType {
+
/**
* The enumeration type when the bind rule has specified type of
* "=".
@@ -62,7 +63,7 @@
*/
GREATER_OR_EQUAL_BINDRULE_TYPE (">=");
- /**
+ /*
* The bind rule type name.
*/
private final String type;
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/EnumBooleanTypes.java b/opends/src/server/org/opends/server/authorization/dseecompat/EnumBooleanTypes.java
index cd81820..3c8b370 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/EnumBooleanTypes.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/EnumBooleanTypes.java
@@ -31,6 +31,7 @@
* This class provides an enumeration of the allowed bind rule booelan types.
*/
public enum EnumBooleanTypes {
+
/**
* The enumeration type when the bind rule has specified boolean type of
* "AND".
@@ -47,7 +48,7 @@
*/
NOT_BOOLEAN_TYPE ("not");
- /**
+ /*
* The bind rule boolean type name.
*/
private final String booleanType;
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/EnumDayOfWeek.java b/opends/src/server/org/opends/server/authorization/dseecompat/EnumDayOfWeek.java
index bd00a8d..6112488 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/EnumDayOfWeek.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/EnumDayOfWeek.java
@@ -33,6 +33,7 @@
* This class provides an enumeration of the allowed dayofweek types.
*/
public enum EnumDayOfWeek {
+
/**
* The enumeration type when the bind rule has specified dayofweek type of
* "mon".
@@ -69,7 +70,7 @@
*/
DAY_SUNDAY ("sun");
- /**
+ /*
* The bind rule dayofweek type name.
*/
private String day = null;
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/EnumEvalResult.java b/opends/src/server/org/opends/server/authorization/dseecompat/EnumEvalResult.java
index b63581e..bc372a3 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/EnumEvalResult.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/EnumEvalResult.java
@@ -32,6 +32,7 @@
* the bind rule evaluation methods.
*/
public enum EnumEvalResult {
+
/**
* This enumeration is returned when the result of the evaluation is TRUE.
*/
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/EnumRight.java b/opends/src/server/org/opends/server/authorization/dseecompat/EnumRight.java
index 11a4e4a..b93fecf 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/EnumRight.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/EnumRight.java
@@ -26,6 +26,7 @@
*/
package org.opends.server.authorization.dseecompat;
+import static org.opends.server.authorization.dseecompat.Aci.*;
/**
* This class provides an enumeration of the allowed rights.
@@ -88,7 +89,7 @@
*/
ADDWRITE ("addwrite");
- /**
+ /*
* The name of the right.
*/
private final String right;
@@ -132,40 +133,40 @@
* @return The bit mask associated with the right.
*/
public static int getMask(EnumRight right) {
- int mask=AciHandler.ACI_NULL;
+ int mask=ACI_NULL;
switch(right) {
case READ:
- mask=AciHandler.ACI_READ;
+ mask=ACI_READ;
break;
case WRITE:
- mask=AciHandler.ACI_WRITE;
+ mask=ACI_WRITE;
break;
case ADD:
- mask=AciHandler.ACI_ADD;
+ mask=ACI_ADD;
break;
case DELETE:
- mask=AciHandler.ACI_DELETE;
+ mask=ACI_DELETE;
break;
case SEARCH:
- mask=AciHandler.ACI_SEARCH;
+ mask=ACI_SEARCH;
break;
case COMPARE:
- mask=AciHandler.ACI_COMPARE;
+ mask=ACI_COMPARE;
break;
case ALL:
- mask=AciHandler.ACI_ALL;
+ mask=ACI_ALL;
break;
case EXPORT:
- mask=AciHandler.ACI_EXPORT;
+ mask=ACI_EXPORT;
break;
case IMPORT:
- mask=AciHandler.ACI_IMPORT;
+ mask=ACI_IMPORT;
break;
case PROXY:
- mask=AciHandler.ACI_PROXY;
+ mask=ACI_PROXY;
break;
case SELFWRITE:
- mask=AciHandler.ACI_SELF;
+ mask=ACI_SELF;
break;
}
return mask;
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/EnumTargetKeyword.java b/opends/src/server/org/opends/server/authorization/dseecompat/EnumTargetKeyword.java
index 9ef3b00..e58fe0b 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/EnumTargetKeyword.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/EnumTargetKeyword.java
@@ -31,6 +31,7 @@
* This class provides an enumeration of the valid ACI target keywords.
*/
public enum EnumTargetKeyword {
+
/**
* This enumeration is returned when the target keyword is
* "target".
@@ -56,10 +57,8 @@
* "targattrfilters".
*/
KEYWORD_TARGATTRFILTERS ("targattrfilters");
+
/*
- * TODO Add support for the targattrfilters keyword.
- */
- /**
* The target keyword name.
*/
private final String keyword;
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/EnumTargetOperator.java b/opends/src/server/org/opends/server/authorization/dseecompat/EnumTargetOperator.java
index 72f22e7..204a885 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/EnumTargetOperator.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/EnumTargetOperator.java
@@ -31,6 +31,7 @@
* This class provides an enumeration of the valid ACI target operators.
*/
public enum EnumTargetOperator {
+
/**
* This enumeration is returned when the target operator is "=".
*/
@@ -40,7 +41,7 @@
*/
NOT_EQUALITY ("!=");
- /**
+ /*
* The target operator name.
*/
private final String operator;
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/EnumUserDNType.java b/opends/src/server/org/opends/server/authorization/dseecompat/EnumUserDNType.java
index 9e943c3..868541b 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/EnumUserDNType.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/EnumUserDNType.java
@@ -40,6 +40,7 @@
* SELF and ANYONE.
*/
public enum EnumUserDNType {
+
/**
* The enumeration type when the "userdn" URL contains only a DN (no
* filter or scope) and that DN has no pattern.
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/GroupDN.java b/opends/src/server/org/opends/server/authorization/dseecompat/GroupDN.java
index 78aac73..b188b17 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/GroupDN.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/GroupDN.java
@@ -28,6 +28,7 @@
package org.opends.server.authorization.dseecompat;
import static org.opends.server.authorization.dseecompat.AciMessages.*;
+import static org.opends.server.authorization.dseecompat.Aci.*;
import static org.opends.server.messages.MessageHandler.getMessage;
import org.opends.server.types.*;
import org.opends.server.api.Group;
@@ -46,10 +47,28 @@
*/
public class GroupDN implements KeywordBindRule {
+ /*
+ * List of group DNs.
+ */
LinkedList<DN> groupDNs=null;
+
+ /*
+ * Enumeration representing the groupdn operator type.
+ */
private EnumBindRuleType type=null;
+
+ /*
+ * Group manager needed for group API.
+ */
private static GroupManager groupManager =
- DirectoryServer.getGroupManager();
+ DirectoryServer.getGroupManager();
+ /**
+ * Regular expression matching one or more LDAP URLs separated by
+ * "||".
+ */
+ public static final String LDAP_URLS = LDAP_URL +
+ ZERO_OR_MORE_WHITESPACE + "(" + LOGICAL_OR +
+ ZERO_OR_MORE_WHITESPACE + LDAP_URL + ")*";
/**
* Create a class representing a groupdn bind rule keyword.
@@ -71,17 +90,14 @@
*/
public static KeywordBindRule decode(String expr, EnumBindRuleType type)
throws AciException {
- String ldapURLRegex = "\\s*(ldap:///[^\\|]+)";
- String ldapURLSRegex =
- ldapURLRegex + "\\s*(\\|\\|\\s*" + ldapURLRegex + ")*";
- if (!Pattern.matches(ldapURLSRegex, expr)) {
+ if (!Pattern.matches(LDAP_URLS, expr)) {
int msgID = MSGID_ACI_SYNTAX_INVALID_GROUPDN_EXPRESSION;
String message = getMessage(msgID, expr);
throw new AciException(msgID, message);
}
LinkedList<DN>groupDNs=new LinkedList<DN>();
int ldapURLPos = 1;
- Pattern ldapURLPattern = Pattern.compile(ldapURLRegex);
+ Pattern ldapURLPattern = Pattern.compile(LDAP_URL);
Matcher ldapURLMatcher = ldapURLPattern.matcher(expr);
while (ldapURLMatcher.find()) {
try {
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/IpCriteria.java b/opends/src/server/org/opends/server/authorization/dseecompat/IpCriteria.java
index a81048b..19199b0 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/IpCriteria.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/IpCriteria.java
@@ -28,6 +28,7 @@
package org.opends.server.authorization.dseecompat;
import static org.opends.server.authorization.dseecompat.AciMessages.*;
+import static org.opends.server.authorization.dseecompat.Aci.*;
import static org.opends.server.messages.MessageHandler.getMessage;
import java.net.Inet6Address;
import java.net.InetAddress;
@@ -39,8 +40,7 @@
/**
* This class represents a ip bind rule keyword.
*/
-public class IpCriteria implements KeywordBindRule
-{
+public class IpCriteria implements KeywordBindRule {
private EnumBindRuleType type=null;
// private token to express that any address is accepted
@@ -50,6 +50,13 @@
private IpBitsNetworkCriteria[] ipBitsCriteria = null;
private IpMaskNetworkCriteria[] ipMaskCriteria = null;
+ private static final String valueRegex =
+ "([^," + ZERO_OR_MORE_WHITESPACE + "]+)";
+
+ private static final String valuesRegex =
+ valueRegex + ZERO_OR_MORE_WHITESPACE + "(," +
+ ZERO_OR_MORE_WHITESPACE + valueRegex + ")*";
+
/*
* TODO Verifiy IpCriteria constructor adheres to DS 5.2 ip keyword
* syntax.
@@ -245,8 +252,6 @@
*/
public static KeywordBindRule decode(String expr, EnumBindRuleType type)
throws AciException {
- String valueRegex = "([^,\\s]+)";
- String valuesRegex = valueRegex + "\\s*(,\\s*" + valueRegex + ")*";
if (!Pattern.matches(valuesRegex, expr)) {
int msgID = MSGID_ACI_SYNTAX_INVALID_IP_EXPRESSION;
String message = getMessage(msgID, expr);
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/ParentInheritance.java b/opends/src/server/org/opends/server/authorization/dseecompat/ParentInheritance.java
index 17e341d..eb151ea 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/ParentInheritance.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/ParentInheritance.java
@@ -28,8 +28,12 @@
package org.opends.server.authorization.dseecompat;
import static org.opends.server.authorization.dseecompat.AciMessages.*;
+import static org.opends.server.authorization.dseecompat.Aci.*;
import static org.opends.server.messages.MessageHandler.getMessage;
import java.util.StringTokenizer;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.AttributeType;
@@ -38,14 +42,31 @@
* to determine what parent inheritance checks to make.
*/
public class ParentInheritance {
+
/*
* The maximum number of parent inheritance levels supported.
- *
*/
private static final int MAX_LEVELS=10;
+
+ /*
+ * Pattern to match for parent inheritance.
+ */
private String parentPat="parent[";
+
+ /*
+ * Array used to hold the level information. Each slot corresponds to a
+ * level parsed from the rule.
+ */
private int[] levels=new int[MAX_LEVELS];
+
+ /*
+ * The number of levels parsed.
+ */
private int numLevels;
+
+ /*
+ * The attribute type parsed from the rule.
+ */
private AttributeType attributeType;
@@ -66,21 +87,29 @@
//The "parent[" pattern is invalid for ROLEDN user attr keyword.
if(pattern.startsWith(parentPat)) {
int msgID =
- MSGID_ACI_SYNTAX_INVALID_USERATTR_ROLEDN_INHERITANCE_PATTERN;
+ MSGID_ACI_SYNTAX_INVALID_USERATTR_ROLEDN_INHERITANCE_PATTERN;
String message = getMessage(msgID, pattern);
throw new AciException(msgID, message);
} else {
pattern=pattern.trim();
- if((this.attributeType =
- DirectoryServer.getAttributeType(pattern)) == null)
- this.attributeType =
- DirectoryServer.getDefaultAttributeType(pattern);
- numLevels=1;
- levels[0]=0;
+ Pattern pattern1=Pattern.compile(ATTR_NAME);
+ Matcher matcher=pattern1.matcher(pattern);
+ //Check if valid attribute type name.
+ if(!matcher.find() || matcher.groupCount() != 1) {
+ int msgID =
+ MSGID_ACI_SYNTAX_INVALID_ATTRIBUTE_TYPE_NAME;
+ String message = getMessage(msgID, pattern);
+ throw new AciException(msgID, message);
+ }
+ if((this.attributeType =
+ DirectoryServer.getAttributeType(pattern)) == null)
+ this.attributeType =
+ DirectoryServer.getDefaultAttributeType(pattern);
+ numLevels=1;
+ levels[0]=0;
}
- } else
- parse(pattern);
- }
+ } else parse(pattern);
+}
/**
* Performs all parsing of the specified pattern string.
@@ -108,6 +137,15 @@
String message = getMessage(msgID, pattern);
throw new AciException(msgID, message);
}
+ Pattern pattern1=Pattern.compile(ATTR_NAME);
+ Matcher matcher=pattern1.matcher(toks[1]);
+ //Check if valid attribute type name.
+ if(!matcher.find() || matcher.groupCount() != 1) {
+ int msgID =
+ MSGID_ACI_SYNTAX_INVALID_ATTRIBUTE_TYPE_NAME;
+ String message = getMessage(msgID, toks[1]);
+ throw new AciException(msgID, message);
+ }
if((this.attributeType =
DirectoryServer.getAttributeType(toks[1])) == null)
this.attributeType =
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/PermBindRulePair.java b/opends/src/server/org/opends/server/authorization/dseecompat/PermBindRulePair.java
index c64976f..11a9362 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/PermBindRulePair.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/PermBindRulePair.java
@@ -33,7 +33,14 @@
*/
public class PermBindRulePair {
+ /*
+ * The Bind Rule part.
+ */
private BindRule bindRule;
+
+ /*
+ * The permission part.
+ */
private Permission perm=null;
/**
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/Permission.java b/opends/src/server/org/opends/server/authorization/dseecompat/Permission.java
index 2e013c7..f258fca 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/Permission.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/Permission.java
@@ -29,6 +29,7 @@
import static org.opends.server.messages.MessageHandler.getMessage;
import static org.opends.server.authorization.dseecompat.AciMessages.*;
+import static org.opends.server.authorization.dseecompat.Aci.*;
import java.util.regex.Pattern;
/**
@@ -36,12 +37,30 @@
* of an ACI look like deny(search, write).
*/
public class Permission {
- //the access type (allow,deny)
+
+ /*
+ * The access type (allow,deny) corresponding to the ACI permission value.
+ */
private EnumAccessType accessType = null;
+
+ /*
+ * The rights (search, add, delete, ...) corresponding to the ACI rights
+ * value.
+ */
private int rights;
+
+ /*
+ * Regular expression token representing the separator.
+ */
private static final String separatorToken = ",";
- private static final String rightsRegex =
- "\\s*(\\w+)\\s*(,\\s*(\\w+)\\s*)*";
+
+ /*
+ * Regular expression used to match the ACI rights string.
+ */
+ private static final String rightsRegex = ZERO_OR_MORE_WHITESPACE +
+ WORD_GROUP + ZERO_OR_MORE_WHITESPACE +
+ "(," + ZERO_OR_MORE_WHITESPACE + WORD_GROUP +
+ ZERO_OR_MORE_WHITESPACE + ")*";
/**
* Constructor creating a class representing a permission part of an bind
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/RoleDN.java b/opends/src/server/org/opends/server/authorization/dseecompat/RoleDN.java
index a3ec83e..26a53f9 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/RoleDN.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/RoleDN.java
@@ -28,6 +28,7 @@
package org.opends.server.authorization.dseecompat;
import static org.opends.server.authorization.dseecompat.AciMessages.*;
+import static org.opends.server.authorization.dseecompat.Aci.*;
import static org.opends.server.messages.MessageHandler.getMessage;
import org.opends.server.types.*;
import org.opends.server.api.Group;
@@ -47,10 +48,21 @@
*/
public class RoleDN implements KeywordBindRule {
+ /*
+ * List of DNs parsed from the ACI bind rule.
+ */
LinkedList<DN> roleDNs=null;
+
+ /*
+ * The bind rule type of the RoleDN statement.
+ */
private EnumBindRuleType type=null;
+
+ /*
+ * Group manager needed by the class.
+ */
private static GroupManager groupManager =
- DirectoryServer.getGroupManager();
+ DirectoryServer.getGroupManager();
/**
* Constructor creating a class representing a roledn keyword of a bind
@@ -72,31 +84,26 @@
* @throws AciException If the expression is invalid.
*/
public static KeywordBindRule decode(String expr, EnumBindRuleType type)
- throws AciException {
- String ldapURLRegex = "\\s*(ldap:///[^\\|]+)";
- String ldapURLSRegex =
- ldapURLRegex + "\\s*(\\|\\|\\s*" + ldapURLRegex + ")*";
- if (!Pattern.matches(ldapURLSRegex, expr)) {
+ throws AciException {
+ if (!Pattern.matches(GroupDN.LDAP_URLS, expr)) {
int msgID = MSGID_ACI_SYNTAX_INVALID_ROLEDN_EXPRESSION;
String message = getMessage(msgID, expr);
throw new AciException(msgID, message);
}
LinkedList<DN>roleDNs=new LinkedList<DN>();
int ldapURLPos = 1;
- Pattern ldapURLPattern = Pattern.compile(ldapURLRegex);
+ Pattern ldapURLPattern = Pattern.compile(LDAP_URL);
Matcher ldapURLMatcher = ldapURLPattern.matcher(expr);
while (ldapURLMatcher.find()) {
- String val = ldapURLMatcher.group(ldapURLPos);
- val = val.trim();
- DN dn;
+ String value = ldapURLMatcher.group(ldapURLPos).trim();
try {
- dn=DN.decode(val);
+ DN dn=LDAPURL.decode(value, true).getBaseDN();
+ roleDNs.add(dn);
} catch (DirectoryException ex) {
int msgID = MSGID_ACI_SYNTAX_INVALID_ROLEDN_URL;
String message = getMessage(msgID, ex.getErrorMessage());
throw new AciException(msgID, message);
}
- roleDNs.add(dn);
}
return new RoleDN(type, roleDNs);
}
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/TargAttrFilterList.java b/opends/src/server/org/opends/server/authorization/dseecompat/TargAttrFilterList.java
new file mode 100644
index 0000000..80bacba
--- /dev/null
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/TargAttrFilterList.java
@@ -0,0 +1,221 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.authorization.dseecompat;
+
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.SearchFilter;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.core.DirectoryServer;
+import static org.opends.server.authorization.dseecompat.AciMessages.*;
+import static org.opends.server.authorization.dseecompat.Aci.*;
+import static org.opends.server.messages.MessageHandler.getMessage;
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.util.LinkedHashMap;
+
+/**
+ * The TargAttrFilterList class represents an targattrfilters list. A
+ * targattrfilters list looks like:
+ *
+ * "Op=attr1:F1 [(&& attr2:F2)*]
+ */
+public class TargAttrFilterList {
+
+ /*
+ * The mask coresponding to the operation of this list (add or del).
+ */
+ private int mask=0;
+
+ /*
+ * ListHashMap keyed by the attribute type and mapping to the corresponding
+ * search filter. LinkedHashMap is used so everything is in order.
+ */
+ private LinkedHashMap<AttributeType, SearchFilter> attrFilterList;
+
+ /*
+ * Regular expression group count.
+ */
+ private static int expectedGroupCount=2;
+
+ /*
+ * Regular expression attribute group position.
+ */
+ private static int attributePos=1;
+
+ /*
+ * Regular expression filter group position.
+ */
+ private static int filterPos=2;
+
+ /*
+ * Regular expression used to match a filter list including the strange
+ * "and" token used to join the multiple attribute type filter pairs.
+ */
+ private static final String filterListSeperator =
+ ZERO_OR_MORE_WHITESPACE + "&&" + ZERO_OR_MORE_WHITESPACE;
+
+ /*
+ * Regular expression used to match an attribute filter pair.
+ */
+ private static final String attributeFilter=
+ ATTR_NAME + ZERO_OR_MORE_WHITESPACE + ":{1}" +
+ ZERO_OR_MORE_WHITESPACE + "(\\({1}.*\\){1})";
+
+ /**
+ * Construct a class representing an targattrfilters filter list.
+ * @param mask The mask representing the operation.
+ * @param attrFilterList The list map containing the attribute type
+ * filter mappings.
+ */
+ public TargAttrFilterList(int mask,
+ LinkedHashMap<AttributeType, SearchFilter> attrFilterList) {
+ this.mask=mask;
+ this.attrFilterList=attrFilterList;
+ }
+
+ /**
+ * Decode an TargAttrFilterList from the specified expression string.
+ * @param mask The mask representing the operation.
+ * @param expression The expression string to decode.
+ * @return A TargAttrFilterList class representing the targattrfilters
+ * filter list.
+ * @throws AciException If the expression string contains errors.
+ */
+ public static TargAttrFilterList decode(int mask, String expression)
+ throws AciException {
+ LinkedHashMap<AttributeType, SearchFilter> attrFilterList =
+ new LinkedHashMap<AttributeType, SearchFilter>();
+ String[] subExpressions=expression.split(filterListSeperator, -1);
+ //Iterate over each sub-expression, parse and add them to the list
+ //if there are no errors.
+ for(String subs : subExpressions) {
+ Pattern pattern=Pattern.compile(attributeFilter);
+ Matcher matcher=pattern.matcher(subs);
+ //Match the attribute:filter pair part of the expression
+ if(!matcher.find() || matcher.groupCount() != expectedGroupCount) {
+ int msgID =
+ MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_FILTER_LIST_FORMAT;
+ String message = getMessage(msgID, expression);
+ throw new AciException(msgID, message);
+ }
+ String attributeName=matcher.group(attributePos).toLowerCase();
+ //Strip off any options, so it will match the filter option
+ //handling.
+ int semicolon = attributeName.indexOf(';');
+ if (semicolon != -1)
+ attributeName=attributeName.substring(0, semicolon);
+ String filterString=matcher.group(filterPos);
+ AttributeType attributeType;
+ if((attributeType =
+ DirectoryServer.getAttributeType(attributeName)) == null)
+ attributeType =
+ DirectoryServer.getDefaultAttributeType(attributeName);
+ SearchFilter filter;
+ //Check if it is a valid filter and add it to the list map if ok.
+ try {
+ filter = SearchFilter.createFilterFromString(filterString);
+ attrFilterList.put(attributeType, filter);
+ } catch (DirectoryException ex) {
+ String er=ex.getErrorMessage();
+ int msgID =
+ MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_FILTER_LISTS_FILTER;
+ String message = getMessage(msgID, filterString, er);
+ throw new AciException(msgID, message);
+ }
+ //Verify the filter components. This check assures that each
+ //attribute type in the filter matches the provided attribute
+ //type.
+ verifyFilterComponents(filter, attributeType);
+ }
+ return new TargAttrFilterList(mask, attrFilterList);
+ }
+
+ /**
+ * Verify the filter component attribute types by assuring that each
+ * attribute type in the filter matches the specified attribute type.
+ * @param filter The filter to verify.
+ * @param type The attribute type to use in the verification.
+ * @throws AciException If the filter contains an attribute type not
+ * specified.
+ */
+ private static void verifyFilterComponents(SearchFilter filter,
+ AttributeType type)
+ throws AciException {
+ switch (filter.getFilterType()) {
+ case AND:
+ case OR: {
+ for (SearchFilter f : filter.getFilterComponents()) {
+ verifyFilterComponents(f, type);
+ }
+ break;
+ }
+ case NOT: {
+ SearchFilter f = filter.getNotComponent();
+ verifyFilterComponents(f, type);
+ break;
+ }
+ default: {
+ AttributeType attrType=filter.getAttributeType();
+ if(!attrType.equals(type)) {
+ int msgID =
+ MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_FILTER_LISTS_ATTR_FILTER;
+ String message = getMessage(msgID, filter.toString());
+ throw new AciException(msgID, message);
+ }
+ }
+ }
+ }
+
+ /**
+ * Return the mask of this TargAttrFilterList.
+ * @return The mask value.
+ */
+ public int getMask() {
+ return this.mask;
+ }
+
+ /**
+ * Check if the mask value of this TargAttrFilterList class contains the
+ * specified mask value.
+ * @param mask The mask to check for.
+ * @return True if the mask matches the specified value.
+ */
+ public boolean hasMask(int mask) {
+ return (this.mask & mask) != 0;
+ }
+
+ /**
+ * Return the list map holding the attribute type to filter mappings.
+ * @return The list map.
+ */
+ public
+ LinkedHashMap<AttributeType, SearchFilter> getAttributeTypeFilterList() {
+ return attrFilterList;
+ }
+}
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/TargAttrFilters.java b/opends/src/server/org/opends/server/authorization/dseecompat/TargAttrFilters.java
index cba42bc..6265e65 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/TargAttrFilters.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/TargAttrFilters.java
@@ -27,29 +27,355 @@
package org.opends.server.authorization.dseecompat;
+import static org.opends.server.authorization.dseecompat.AciMessages.*;
+import static org.opends.server.authorization.dseecompat.Aci.*;
+import static org.opends.server.messages.MessageHandler.getMessage;
+import org.opends.server.types.*;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.util.*;
+
/**
- * Placeholder. This class is partially complete. The TargAttrFilters class
- * will represent an targAttrFitlers rule.
+ * The TargAttrFilters class represents a targattrfilters rule of an ACI.
*/
public class TargAttrFilters {
- /**
- * Represents an targAttrFilters rule.
+ /*
+ * A valid targattrfilters rule may have two TargFilterlist parts -- the
+ * first one is required.
*/
- public TargAttrFilters() {
+ TargAttrFilterList firstFilterList=null;
+ TargAttrFilterList secondFilterList=null;
+ /*
+ * Regular expression group position for the first operation value.
+ */
+ private static final int firstOpPos = 1;
+
+ /*
+ * Regular expression group position for the rest of an partially parsed
+ * rule.
+ */
+ private static final int restOfExpressionPos=2;
+
+ /*
+ * Regular expression used to match the operation group (either add or del).
+ */
+ private static final String ADD_OR_DEL_KEYWORD_GROUP = "(add|del)";
+
+ /**
+ * Regular expression used to match the second operation of the filter list.
+ * If the first was "add" this must be "del", if the first was "del" this
+ * must be "add".
+ */
+ public static final String secondOp =
+ "[,]{1}" + ZERO_OR_MORE_WHITESPACE + "del|add" +
+ ZERO_OR_MORE_WHITESPACE + EQUAL_SIGN + ZERO_OR_MORE_WHITESPACE;
+
+ /*
+ * Regular expression used to match the first targFilterList, it must exist
+ * or an exception is thrown.
+ */
+ private static final String firstOp = "^" + ADD_OR_DEL_KEYWORD_GROUP +
+ ZERO_OR_MORE_WHITESPACE + EQUAL_SIGN + ZERO_OR_MORE_WHITESPACE;
+
+ /*
+ * Regular expression used to group the remainder of a partially parsed
+ * rule. Any character one or more times.
+ */
+ private static String restOfExpression = "(.+)";
+
+ /*
+ * Regular expression used to match the first operation keyword and the
+ * rest of the expression.
+ */
+ private static String keywordFullPattern = firstOp + restOfExpression;
+
+ /*
+ * The enumeration representing the operation.
+ */
+ EnumTargetOperator op;
+
+ /*
+ * A mask used to denote if the rule has add, del or both operations in the
+ * composite TargFilterList parts.
+ */
+ private int operationMask;
+
+ /**
+ * Represents an targatterfilters keyword rule.
+ * @param op The enumeration representing the operation type.
+ *
+ * @param firstFilterList The first filter list class parsed from the rule.
+ * This one is required.
+ *
+ * @param secondFilterList The second filter list class parsed from the
+ * rule. This one is optional.
+ */
+ public TargAttrFilters(EnumTargetOperator op,
+ TargAttrFilterList firstFilterList,
+ TargAttrFilterList secondFilterList ) {
+ this.op=op;
+ this.firstFilterList=firstFilterList;
+ operationMask=firstFilterList.getMask();
+ if(secondFilterList != null) {
+ //Add the second filter list mask to the mask.
+ operationMask |= secondFilterList.getMask();
+ this.secondFilterList=secondFilterList;
+ }
}
/**
- * Decode an string representing a targattrfilters keyword.
- * @param operator The operator of the rule.
- * @param expression The string parsed from the ACI representing the
- * targattrfilters rule.
- * @return An object representing an targattrfilters rule.
- * @throws AciException if the expression string cannot be parsed.
+ * Decode an targattrfilter rule.
+ * @param type The enumeration representing the type of this rule. Defaults
+ * to equality for this target.
+ *
+ * @param expression The string expression to be decoded.
+ * @return A TargAttrFilters class representing the decode expression.
+ * @throws AciException If the expression string contains errors and
+ * cannot be decoded.
*/
- public static TargAttrFilters decode(EnumTargetOperator operator,
- String expression) throws AciException {
- return new TargAttrFilters();
+ public static TargAttrFilters decode(EnumTargetOperator type,
+ String expression) throws AciException {
+ Pattern fullPattern=Pattern.compile(keywordFullPattern);
+ Matcher matcher = fullPattern.matcher(expression);
+ //First match for overall correctness and to get the first operation.
+ if(!matcher.find()) {
+ int msgID = MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_EXPRESSION;
+ String message = getMessage(msgID, expression);
+ throw new AciException(msgID, message);
+ }
+ String firstOp=matcher.group(firstOpPos);
+ String subExpression=matcher.group(restOfExpressionPos);
+ //This pattern is built dynamically and is used to see if the operations
+ //in the two filter list parts (if the second exists) are equal. See
+ //comment below.
+ String opPattern=
+ "[,]{1}" + ZERO_OR_MORE_WHITESPACE +
+ firstOp + ZERO_OR_MORE_WHITESPACE + EQUAL_SIGN +
+ ZERO_OR_MORE_WHITESPACE;
+ String[] temp=subExpression.split(opPattern);
+ /**
+ * Check that the initial list operation is not equal to the second.
+ * For example: Matcher find
+ *
+ * "add:cn:(cn=foo), add:cn:(cn=bar)"
+ *
+ * This is invalid.
+ */
+ if(temp.length > 1) {
+ int msgID =
+ MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_OPS_MATCH;
+ String message = getMessage(msgID, expression);
+ throw new AciException(msgID, message);
+ }
+ /**
+ * Check that there are not too many filter lists. There can only
+ * be either one or two.
+ */
+ String[] filterLists=
+ subExpression.split(secondOp, -1);
+ if(filterLists.length > 2) {
+ int msgID =
+ MSGID_ACI_SYNTAX_INVALID_TARGATTRFILTERS_MAX_FILTER_LISTS;
+ String message = getMessage(msgID, expression);
+ throw new AciException(msgID, message);
+ }
+ TargAttrFilterList firstFilterList =
+ TargAttrFilterList.decode(getMask(firstOp), filterLists[0]);
+ TargAttrFilterList secondFilterList=null;
+ //Handle the second filter list if there is one.
+ if(filterLists.length == 2) {
+ String temp2= filterLists[1].substring(1,filterLists[1].length());
+ //Assume the first op is an "add" so this has to be a "del".
+ String secondOp="del";
+ //If the first op is a "del", the second has to be an "add".
+ if(getMask(firstOp) == TARGATTRFILTERS_DELETE)
+ secondOp="add";
+ secondFilterList =
+ TargAttrFilterList.decode(getMask(secondOp), temp2);
+ }
+ return new TargAttrFilters(type, firstFilterList, secondFilterList);
}
+
+ /**
+ * Return the mask corrsponding to the specified string.
+ * @param op The op string.
+ * @return The mask corresponding to the operation string.
+ */
+ private static int getMask(String op) {
+ if(op.equals("add"))
+ return TARGATTRFILTERS_ADD;
+ else
+ return TARGATTRFILTERS_DELETE;
+ }
+
+ /**
+ * Gets the TargFilterList corresponding to the mask value.
+ * @param matchCtx The target match context containing the rights to
+ * match against.
+ * @return A TargAttrFilterList matching both the rights of the target
+ * match context and the mask of the TargFilterAttrList. May return null.
+ */
+ public TargAttrFilterList
+ getTargAttrFilterList(AciTargetMatchContext matchCtx) {
+ TargAttrFilterList filterList=null;
+ int mask=ACI_NULL;
+ //Set up the wanted mask by evaluating both the target match
+ //context's rights and the mask.
+ if(matchCtx.hasRights(ACI_ADD) &&
+ hasMask(TARGATTRFILTERS_ADD))
+ mask=TARGATTRFILTERS_ADD;
+ else if(matchCtx.hasRights(ACI_DELETE) &&
+ hasMask(TARGATTRFILTERS_DELETE))
+ mask=TARGATTRFILTERS_DELETE;
+ //Check the first list first, it always has to be there. If it doesn't
+ //match then check the second if it exists.
+ if(firstFilterList.hasMask(mask))
+ filterList=firstFilterList;
+ else if((secondFilterList != null) &&
+ secondFilterList.hasMask(mask))
+ filterList=secondFilterList;
+ return filterList;
+ }
+
+ /**
+ * Check if this TargAttrFilters object is applicable to the target
+ * specified match context. This check is only used for the LDAP modify
+ * operation.
+ * @param matchCtx The target match context containing the information
+ * needed to match.
+ * @return True if this TargAttrFitlers object is applicable to this
+ * target match context.
+ */
+ public boolean isApplicableMod(AciTargetMatchContext matchCtx) {
+ //Get the targFitlerList corresponding to this context's rights.
+ TargAttrFilterList attrFilterList=getTargAttrFilterList(matchCtx);
+ //If the list is empty return true and go on to the targattr check
+ //in AciTargets.isApplicable().
+ if(attrFilterList == null)
+ return true;
+ LinkedHashMap<AttributeType, SearchFilter> filterList =
+ attrFilterList.getAttributeTypeFilterList();
+ boolean attrMatched=true;
+ AttributeType attrType=matchCtx.getCurrentAttributeType();
+ //If the filter list contains the current attribute type; check
+ //the attribute types value(s) against the corresponding filter.
+ // If the filter list does not contain the attribute type skip the
+ // attribute type.
+ if((attrType != null) && (filterList.containsKey(attrType))) {
+ AttributeValue value=matchCtx.getCurrentAttributeValue();
+ SearchFilter filter = filterList.get(attrType);
+ attrMatched=matchFilterAttributeValue(attrType, value, filter);
+ //This flag causes any targattr checks to be bypassed in AciTargets.
+ if(attrMatched)
+ matchCtx.setTargAttrFiltersMatch(true);
+ if(op.equals(EnumTargetOperator.NOT_EQUALITY))
+ attrMatched = !attrMatched;
+ }
+ return attrMatched;
+ }
+
+ /**
+ * Check if this TargAttrFilters object is applicable to the specified
+ * target match context. This check is only used for either LDAP add or
+ * delete operations.
+ * @param matchCtx The target match context containing the information
+ * needed to match.
+ * @return True if this TargAttrFilters object is applicable to this
+ * target match context.
+ */
+ public boolean isApplicableAddDel(AciTargetMatchContext matchCtx) {
+ TargAttrFilterList attrFilterList=getTargAttrFilterList(matchCtx);
+ //List didn't match current operation return true.
+ if(attrFilterList == null)
+ return true;
+ LinkedHashMap<AttributeType, SearchFilter> filterList =
+ attrFilterList.getAttributeTypeFilterList();
+ Iterator<AttributeType> iterator=filterList.keySet().iterator();
+ boolean attrMatched=true;
+ //Get the resource entry.
+ Entry resEntry=matchCtx.getResourceEntry();
+ //Iterate through each attribute type in the filter list checking
+ //the resource entry to see if it has that attribute type. If not
+ //go to the next attribute type. If it is found, then check the entries
+ //attribute type values against the filter.
+ for(;iterator.hasNext() && attrMatched;) {
+ AttributeType attrType=iterator.next();
+ SearchFilter f=filterList.get(attrType);
+ //Found a match in the entry, iterate over each attribute
+ //type in the entry and check its values agaist the filter.
+ if(resEntry.hasAttribute(attrType)) {
+ ListIterator<Attribute> attrIterator=
+ resEntry.getAttribute(attrType).listIterator();
+ for(;attrIterator.hasNext() && attrMatched;) {
+ Attribute a=attrIterator.next();
+ attrMatched=matchFilterAttributeValues(a, attrType, f);
+ }
+ }
+ }
+ if(op.equals(EnumTargetOperator.NOT_EQUALITY))
+ attrMatched = !attrMatched;
+ return attrMatched;
+ }
+
+ /**
+ * Iterate over each attribute type attribute and compare the values
+ * against the provided filter.
+ * @param a The attribute from the resource entry.
+ * @param attrType The attribute type currently working on.
+ * @param filter The filter to evaluate the values against.
+ * @return True if all of the values matched the filter.
+ */
+ private boolean matchFilterAttributeValues(Attribute a,
+ AttributeType attrType,
+ SearchFilter filter) {
+ boolean filterMatch=true;
+ Iterator<AttributeValue> valIterator = a.getValues().iterator();
+ //Iterate through each value and apply the filter against it.
+ for(; valIterator.hasNext() && filterMatch;) {
+ AttributeValue value=valIterator.next();
+ filterMatch=matchFilterAttributeValue(attrType, value, filter);
+ }
+ return filterMatch;
+ }
+
+ /**
+ * Matches an specified attribute value against a specified filter. A dummy
+ * entry is created with only a single attribute containing the value The
+ * filter is applied against that entry.
+ *
+ * @param attrType The attribute type currently being evaluated.
+ * @param value The value to match the filter against.
+ * @param filter The filter to match.
+ * @return True if the value matches the filter.
+ */
+ private boolean matchFilterAttributeValue(AttributeType attrType,
+ AttributeValue value,
+ SearchFilter filter) {
+ boolean filterMatch;
+ LinkedHashSet<AttributeValue> values =
+ new LinkedHashSet<AttributeValue>();
+ values.add(new AttributeValue(attrType, value.getValue()));
+ Attribute attr =
+ new Attribute(attrType, attrType.toString(), values);
+ Entry e = new Entry(DN.nullDN(), null, null, null);
+ e.addAttribute(attr, new ArrayList<AttributeValue>());
+ try {
+ filterMatch=filter.matchesEntry(e);
+ } catch(DirectoryException ex) {
+ filterMatch=false;
+ }
+ return filterMatch;
+ }
+
+ /**
+ * Return true if the TargAttrFilters mask contains the specified mask.
+ * @param mask The mask to check for.
+ * @return True if the mask matches.
+ */
+ public boolean hasMask(int mask) {
+ return (this.operationMask & mask) != 0;
+ }
+
}
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/Target.java b/opends/src/server/org/opends/server/authorization/dseecompat/Target.java
index fa02d7b..a7f0300 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/Target.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/Target.java
@@ -28,6 +28,7 @@
package org.opends.server.authorization.dseecompat;
import static org.opends.server.authorization.dseecompat.AciMessages.*;
+import static org.opends.server.authorization.dseecompat.Aci.*;
import static org.opends.server.messages.MessageHandler.getMessage;
import java.util.ArrayList;
import java.util.LinkedHashSet;
@@ -47,13 +48,37 @@
*/
public class Target
{
+ /*
+ * Enumeration representing the target operator.
+ */
private EnumTargetOperator operator = EnumTargetOperator.EQUALITY;
- private LDAPURL targetURL = null;
- private DN urlDN=null;
- private boolean isPattern=false;
- private SearchFilter filter=null;
- private AttributeType targetType;
+ /*
+ * The target URL.
+ */
+ private LDAPURL targetURL = null;
+
+ /*
+ * The DN of the above URL.
+ */
+ private DN urlDN=null;
+
+ /*
+ * True of a wild-card pattern was seen.
+ */
+ private boolean isPattern=false;
+
+ /*
+ * Filter used to apply to an dummy entry when a wild-card pattern is
+ * used.
+ */
+ private SearchFilter filter=null;
+
+ /*
+ * Attribute type that is used to create the pattern attribute.
+ * See matchesPattern method.
+ */
+ private AttributeType targetType;
/*
* TODO Save aciDN parameter and use it in matchesPattern re-write.
@@ -89,8 +114,7 @@
throws AciException {
this.operator = operator;
try {
- String ldapURLRegex = "\\s*(ldap:///[^\\|]+)";
- if (!Pattern.matches(ldapURLRegex, target)) {
+ if (!Pattern.matches(LDAP_URL, target)) {
int msgID = MSGID_ACI_SYNTAX_INVALID_TARGETKEYWORD_EXPRESSION;
String message = getMessage(msgID, target);
throw new AciException(msgID, message);
@@ -163,7 +187,8 @@
}
/*
- * TODO Evaluate re-writing this method.
+ * TODO Evaluate re-writing this method. Evaluate if we want to dis-allow
+ * wild-card matching in the suffix part of the dn.
*
* The matchesPattern() method really needs to be rewritten. It's using a
* very inefficient and very error-prone method to make the determination.
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 e4f23dc..bd17665 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/TargetAttr.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/TargetAttr.java
@@ -28,6 +28,7 @@
package org.opends.server.authorization.dseecompat;
import static org.opends.server.authorization.dseecompat.AciMessages.*;
+import static org.opends.server.authorization.dseecompat.Aci.*;
import static org.opends.server.messages.MessageHandler.getMessage;
import java.util.HashSet;
import java.util.regex.Pattern;
@@ -38,18 +39,29 @@
* A class representing an ACI's targetattr keyword.
*/
public class TargetAttr {
+ /*
+ * Enumeration representing the targetattr operator.
+ */
private EnumTargetOperator operator = EnumTargetOperator.EQUALITY;
+
+ /*
+ * Flags that is set if all attributes pattern seen "*".
+ */
private boolean allAttributes = false ;
+
/*
* HashSet of the attribute types parsed by the constructor.
*/
private HashSet<AttributeType> attributes = new HashSet<AttributeType>();
- //private String[] attributes = new String[0];
- private static final String allAttrsRegex = "\\s*\\*\\s*";
- private static final String noAttrsRegex = "\\s*";
- private static final String separatorToken = "\\|\\|";
- private static final String attrListRegex =
- "\\s*(\\w+)\\s*(" + separatorToken + "\\s*(\\w+)\\s*)*";
+
+ /*
+ * Regular expression that matches one or more ATTR_NAME's separated by
+ * the "||" token.
+ */
+ private static final String attrListRegex = ZERO_OR_MORE_WHITESPACE +
+ ATTR_NAME + ZERO_OR_MORE_WHITESPACE + "(" +
+ LOGICAL_OR + ZERO_OR_MORE_WHITESPACE + ATTR_NAME +
+ ZERO_OR_MORE_WHITESPACE + ")*";
/**
* Constructor creating a class representing a targetattr keyword of an ACI.
@@ -63,18 +75,19 @@
throws AciException {
this.operator = operator;
if (attrString != null) {
- if (Pattern.matches(allAttrsRegex, attrString) ){
+ if (Pattern.matches(ALL_ATTRS_WILD_CARD, attrString) ){
allAttributes = true ;
} else {
- if (Pattern.matches(noAttrsRegex, attrString)){
+ if (Pattern.matches(ZERO_OR_MORE_WHITESPACE, attrString)){
allAttributes = false;
} else {
if (Pattern.matches(attrListRegex, attrString)) {
// Remove the spaces in the attr string and
// split the list.
Pattern separatorPattern =
- Pattern.compile(separatorToken);
- attrString=attrString.replaceAll("\\s", "");
+ Pattern.compile(LOGICAL_OR);
+ attrString=
+ attrString.replaceAll(ZERO_OR_MORE_WHITESPACE, "");
String[] attributeArray=
separatorPattern.split(attrString);
//Add each element of array to attributes HashSet
@@ -83,7 +96,7 @@
} else {
int msgID =
MSGID_ACI_SYNTAX_INVALID_TARGETATTRKEYWORD_EXPRESSION;
- String message = getMessage(msgID, operator);
+ String message = getMessage(msgID, attrString);
throw new AciException(msgID, message);
}
}
@@ -101,12 +114,13 @@
String attribute=attributeArray[i].toLowerCase();
AttributeType attributeType;
if((attributeType =
- DirectoryServer.getAttributeType(attribute)) == null)
+ DirectoryServer.getAttributeType(attribute)) == null)
attributeType =
- DirectoryServer.getDefaultAttributeType(attribute);
+ DirectoryServer.getDefaultAttributeType(attribute);
attributes.add(attributeType);
}
}
+
/**
* Returns the operator enumeration of the targetattr expression.
* @return The operator enumeration.
@@ -172,8 +186,14 @@
TargetAttr targetAttr) {
boolean ret;
if(targetAttr.isAllAttributes()) {
- ret =
- !targetAttr.getOperator().equals(EnumTargetOperator.NOT_EQUALITY);
+ //If it is an operational attribute, then access is denied for all
+ //attributes wild-card. Operational attributes must be
+ // explicitly defined.
+ if(a.isOperational()) {
+ ret=false;
+ } else
+ ret =
+ !targetAttr.getOperator().equals(EnumTargetOperator.NOT_EQUALITY);
} else {
ret=false;
HashSet<AttributeType> attributes=targetAttr.getAttributes();
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/TargetFilter.java b/opends/src/server/org/opends/server/authorization/dseecompat/TargetFilter.java
index 743d85c..80734df 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/TargetFilter.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/TargetFilter.java
@@ -38,10 +38,18 @@
*
*/
public class TargetFilter {
+
+ /*
+ * Enumeration representing the targetfilter operation.
+ */
private EnumTargetOperator op = EnumTargetOperator.EQUALITY;
+
+ /*
+ * Filter parsed from the ACI used to match the resource entry.
+ */
private SearchFilter filter;
- /**
+ /*
* Class representing a targetfilter keyword.
* @param op The operation of the targetfilter expression (=, !=)
* @param filter The filter itself.
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/TimeOfDay.java b/opends/src/server/org/opends/server/authorization/dseecompat/TimeOfDay.java
index c42c193..7863fc9 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/TimeOfDay.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/TimeOfDay.java
@@ -36,8 +36,20 @@
* This class represents the timeofday keyword in a bind rule.
*/
public class TimeOfDay implements KeywordBindRule {
+
+ /*
+ * Regular expression matching a valid timeofday rule value (0-2359).
+ */
private static final String timeofdayRegex = "[0-2]\\d[0-5]\\d";
+
+ /*
+ * Enumeration representing the bind rule operation type.
+ */
private EnumBindRuleType type=null;
+
+ /*
+ * Holds the time value parsed from the ACI.
+ */
private int timeRef;
/**
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/UserAttr.java b/opends/src/server/org/opends/server/authorization/dseecompat/UserAttr.java
index 2f65e25..f1462cf 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/UserAttr.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/UserAttr.java
@@ -48,20 +48,58 @@
* This class implements the userattr bind rule keyword.
*/
public class UserAttr implements KeywordBindRule {
+
/**
* This enumeration is the various types the userattr can have after
* the "#" token.
*/
- enum UserAttrType {
+ private enum UserAttrType {
USERDN, GROUPDN, ROLEDN, URL, VALUE
}
- private static String f="objectclass=*";
+
+ /*
+ * Filter used in internal search.
+ */
+ private static SearchFilter filter;
+
+ /*
+ * Used to create an attribute type that can compare the value below in
+ * an entry returned from an internal search.
+ */
private String attrStr=null;
+
+ /*
+ * Used to compare a attribute value returned from a search against this
+ * value which might have been defined in the ACI userattr rule.
+ */
private String attrVal=null;
+
+ /*
+ * Contains the type of the userattr, one of the above enumerations.
+ */
private UserAttrType userAttrType=null;
+
+ /*
+ * An enumeration representing the bind rule type.
+ */
private EnumBindRuleType type=null;
+
+ /*
+ * The class used to hold the parent inheritance information.
+ */
private ParentInheritance parentInheritance=null;
+ static {
+ /*
+ * Set up the filter used to search private and public contexts.
+ */
+ try {
+ filter=SearchFilter.createFilterFromString("(objectclass=*)");
+ } catch (DirectoryException ex) {
+ //TODO should never happen, error message?
+ }
+ }
+
/**
* Create an non-USERDN/GROUPDN instance of the userattr keyword class.
* @param attrStr The attribute name in string form. Kept in string form
@@ -174,27 +212,22 @@
AttributeType attrType;
if((attrType = DirectoryServer.getAttributeType(attrStr)) == null)
attrType = DirectoryServer.getDefaultAttributeType(attrStr);
- try {
- InternalClientConnection conn =
+ InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- InternalSearchOperation op =
- conn.processSearch(evalCtx.getClientDN(),
- SearchScope.BASE_OBJECT,
- DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
- SearchFilter.createFilterFromString(f), null);
- LinkedList<SearchResultEntry> result = op.getSearchEntries();
- if (!result.isEmpty()) {
- AttributeValue val=new AttributeValue(attrType, attrVal);
- SearchResultEntry resultEntry = result.getFirst();
- if(resultEntry.hasValue(attrType, null, val)) {
- Entry e=evalCtx.getResourceEntry();
- if(e.hasValue(attrType, null, val))
- matched=EnumEvalResult.TRUE;
- }
+ InternalSearchOperation op =
+ conn.processSearch(evalCtx.getClientDN(),
+ SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ filter, null);
+ LinkedList<SearchResultEntry> result = op.getSearchEntries();
+ if (!result.isEmpty()) {
+ AttributeValue val=new AttributeValue(attrType, attrVal);
+ SearchResultEntry resultEntry = result.getFirst();
+ if(resultEntry.hasValue(attrType, null, val)) {
+ Entry e=evalCtx.getResourceEntry();
+ if(e.hasValue(attrType, null, val))
+ matched=EnumEvalResult.TRUE;
}
- } catch (DirectoryException ex) {
- undefined = true;
- matched = EnumEvalResult.ERR;
}
return matched.getRet(type, undefined);
}
@@ -305,31 +338,25 @@
stop=true;
}
} else {
- try {
- DN pDN=
+ DN pDN=
getDNParentLevel(levels[i], evalCtx.getResourceDN());
- if(pDN == null)
- continue;
- InternalClientConnection conn =
+ if(pDN == null)
+ continue;
+ InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- InternalSearchOperation op = conn.processSearch(pDN,
- SearchScope.BASE_OBJECT,
- DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
- SearchFilter.createFilterFromString(f), null);
- LinkedList<SearchResultEntry> result =
+ InternalSearchOperation op = conn.processSearch(pDN,
+ SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ filter, null);
+ LinkedList<SearchResultEntry> result =
op.getSearchEntries();
- if (!result.isEmpty()) {
- Entry e = result.getFirst();
- if (e.hasAttribute(attrType)) {
- matched = evalEntryAttr(e, evalCtx, attrType);
- if(matched.equals(EnumEvalResult.TRUE))
- stop=true;
- }
+ if (!result.isEmpty()) {
+ Entry e = result.getFirst();
+ if (e.hasAttribute(attrType)) {
+ matched = evalEntryAttr(e, evalCtx, attrType);
+ if(matched.equals(EnumEvalResult.TRUE))
+ stop=true;
}
- } catch (DirectoryException ex) {
- undefined=true;
- stop=true;
- matched=EnumEvalResult.ERR;
}
}
}
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/UserDN.java b/opends/src/server/org/opends/server/authorization/dseecompat/UserDN.java
index 2154c3c..4ec5643 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/UserDN.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/UserDN.java
@@ -43,13 +43,22 @@
*/
private static String urlStr="ldap:///";
- /**
+ /*
* This list holds a list of objects representing a EnumUserDNType
* URL mapping.
*/
- List<UserDNTypeURL> urlList=null;
+ private List<UserDNTypeURL> urlList=null;
+
+ /*
+ * Enumeration of the userdn operation type.
+ */
private EnumBindRuleType type=null;
+
+ /*
+ * Used to evaluate a userdn that has a pattern (wild-card).
+ */
private AttributeType userDNAttrType;
+
/**
* Constructor that creates the userdn class. It also sets up an attribute
* type ("userdn") needed for wild-card matching.
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/UserDNTypeURL.java b/opends/src/server/org/opends/server/authorization/dseecompat/UserDNTypeURL.java
index 9cedaab..849da6e 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/UserDNTypeURL.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/UserDNTypeURL.java
@@ -33,10 +33,12 @@
* of a "userdn" URL decoded by the UserDN.decode() method.
*/
public class UserDNTypeURL {
- /**
+
+ /*
* The DN type of the URL.
*/
private EnumUserDNType dnType;
+
/*
* The URL value. Maybe a dummy value for types such as ANYONE or SELF.
*/
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTests.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTests.java
index e8d6958..5418bf1 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTests.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTests.java
@@ -227,8 +227,24 @@
private static final String BIND_RULE_GROUPDN_1 = "groupdn=\"ldap:///cn=SomeGroup,dc=example,dc=com\"";
private static final String BIND_RULE_GROUPDN_2 = "groupdn=\"ldap:///cn=SomeGroup,dc=example,dc=com || ldap:///cn=SomeOtherGroup,dc=example,dc=com\"";
private static final String BIND_RULE_GROUPDN_3 = "groupdn=\"ldap:///cn=SomeGroup,dc=example,dc=com || ldap:///cn=SomeOtherGroup,dc=example,dc=com || ldap:///cn=SomeThirdGroup,dc=example,dc=com\"";
+ private static final String BIND_RULE_ROLEDN_1 = "roledn=\"ldap:///cn=SomeGroup,dc=example,dc=com\"";
+ private static final String BIND_RULE_ROLEDN_2 = "roledn=\"ldap:///cn=SomeGroup,dc=example,dc=com || ldap:///cn=SomeOtherGroup,dc=example,dc=com\"";
+ private static final String BIND_RULE_ROLEDN_3 = "roledn=\"ldap:///cn=SomeGroup,dc=example,dc=com || ldap:///cn=SomeOtherGroup,dc=example,dc=com || ldap:///cn=SomeThirdGroup,dc=example,dc=com\"";
+
private static final String BIND_RULE_USERDN_FILTER = "userdn=\"ldap:///dc=example,dc=com??one?(|(ou=eng)(ou=acct))\"";
+ //bind rule user attr ACIs
+ private static final String BIND_RULE_USERATTR_USERDN = "userattr=\"manager#USERDN\"";
+ private static final String BIND_RULE_USERATTR_USERDN_1 = "userattr=\"ldap:///dc=example,dc=com?owner#USERDN\"";
+ private static final String BIND_RULE_USERATTR_URL = "userattr=\"cn#LDAPURL\"";
+ private static final String BIND_RULE_USERATTR_GROUPDN = "userattr=\"manager#GROUPDN\"";
+ private static final String BIND_RULE_USERATTR_GROUPDN_1 = "userattr=\"ldap:///dc=example,dc=com?owner#GROUPDN\"";
+ private static final String BIND_RULE_USERATTR_ROLEDN = "userattr=\"manager#ROLEDN\"";
+ private static final String BIND_RULE_USERATTR_ROLEDN_1 = "userattr=\"ldap:///dc=example,dc=com?owner#ROLEDN\"";
+ private static final String BIND_RULE_USERATTR_USERDN_INHERITANCE = "userattr=\"parent[0,1,2].cn#USERDN\"";
+ private static final String BIND_RULE_USERATTR_GROUPDN_INHERITANCE = "userattr=\"parent[0,1,2].cn#GROUPDN\"";
+ private static final String BIND_RULE_USERATTR_VALUE = "userattr=\"manager#a manager\"";
+
private static final String BIND_RULE_INVALID_DAY = "dayofweek=\"sumday\"";
private static final String BIND_RULE_ONLY_AT_NOON = "timeofday=\"1200\"";
@@ -237,6 +253,21 @@
private static final String BIND_RULE_NOON_AND_AFTER = "timeofday>=\"1200\"";
private static final String BIND_RULE_BEFORE_NOON = "timeofday<\"1200\"";
private static final String BIND_RULE_NOON_AND_BEFORE = "timeofday<=\"1200\"";
+ //targattrfilters
+ private static final String TARG_ATTR_FILTERS = "add=cn:(!(cn=superAdmin))";
+ private static final String TARG_ATTR_FILTERS_1 = "add=cn:(!(cn=superAdmin)) && telephoneNumber:(telephoneNumber=123*)";
+ private static final String TARG_ATTR_FILTERS_2 = "add=cn:(!(cn=superAdmin)), del=sn:(!(sn=nonSuperAdmin))";
+ private static final String TARG_ATTR_FILTERS_4 = "del=cn:(&(cn=foo)(cn=f*)) && sn:(sn=joe*)";
+ private static final String TARG_ATTR_FILTERS_5 = TARG_ATTR_FILTERS_1 + "," + TARG_ATTR_FILTERS_4 ;
+ //targattrfilters invalids
+ private static final String TARG_ATTR_FILTERS_INVALID_FILTER = "del=cn:(&(cnfoo)(cn=f*)) && sn:(snjoe*)";
+ private static final String TARG_ATTR_FILTERS_BAD_OP = "delete=cn:(&(cn=foo)(cn=f*)) && sn:(sn=joe*)";
+ private static final String TARG_ATTR_FILTERS_BAD_OP_MATCH = TARG_ATTR_FILTERS_1 + "," + TARG_ATTR_FILTERS_1 ;
+ private static final String TARG_ATTR_FILTERS_BAD_FILTER_ATTR = "del=cn:(&(cn=foo)(cn=f*)) && sn:(cn=joe*)";
+ private static final String TARG_ATTR_FILTERS_BAD_FORMAT = "delete=cn;(&(cn=foo)(cn=f*)) && sn:(sn=joe*)";
+ private static final String TARG_ATTR_FILTERS_TOO_MANY_LISTS = TARG_ATTR_FILTERS_1 + "," + TARG_ATTR_FILTERS_4 + "," + TARG_ATTR_FILTERS_1;
+ private static final String TARG_ATTR_FILTERS_BAD_TOK = "delete=cn:(&(cn=foo)(cn=f*)) && sn:(sn=joe*) || pager:(pager=123-*)";
+ private static final String TARG_ATTR_FILTERS_ATTR_TYPE_NAME = "del=cn:(&(cn=foo)(cn=f*)) && 1sn_;:(1sn_;=joe*)";
private static final String SELF_MODIFY_ACI = "aci: (targetattr=\"*\")(version 3.0; acl \"self modify\";allow(all) userdn=\"userdn=\"ldap:///self\";)";
@@ -250,7 +281,7 @@
buildAciValue("name", "allow all to anyone", "targetattr", "*", "allow(all)", BIND_RULE_USERDN_ANYONE);
private static final String ALLOW_SEARCH_TO_ADMIN =
- buildAciValue("name", "allow search to admin", "targetattr", "*", "allow(search)", BIND_RULE_USERDN_ADMIN);
+ buildAciValue("name", "allow search to admin", "targetattr", "*", "allow(search, read)", BIND_RULE_USERDN_ADMIN);
private static final String DENY_ALL_TO_ALL =
buildAciValue("name", "deny all", "targetattr", "*", "deny(all)", BIND_RULE_USERDN_ALL);
@@ -262,7 +293,7 @@
buildAciValue("name", "deny search", "targetattr", "*", "deny(search)", BIND_RULE_USERDN_ALL);
private static final String ALLOW_SEARCH_TO_ALL =
- buildAciValue("name", "allow search", "targetattr", "*", "allow(search)", BIND_RULE_USERDN_ALL);
+ buildAciValue("name", "allow search", "targetattr", "*", "allow(search, read)", BIND_RULE_USERDN_ALL);
private static final String ALLOW_READ_TO_ALL =
buildAciValue("name", "allow read", "targetattr", "*", "allow(read)", BIND_RULE_USERDN_ALL);
@@ -289,7 +320,7 @@
buildAciValue("name", "allow all to non ou person", "targetattr", "*", "targetfilter!=", "(|(objectclass=organizationalunit)(objectclass=person))", "allow(all)", BIND_RULE_USERDN_ALL);
private static final String ALLOW_WRITE_DELETE_SEARCH_TO_ALL =
- buildAciValue("name", "allow write, delete, and search,", "targetattr", "*", "allow(write, delete, search)", BIND_RULE_USERDN_ALL);
+ buildAciValue("name", "allow write, delete, and search,", "targetattr", "*", "allow(write, delete, search, read)", BIND_RULE_USERDN_ALL);
private static final String DENY_WRITE_DELETE_READ_TO_ALL =
buildAciValue("name", "deny write delete read to all", "targetattr", "*", "deny(write, delete, read)", BIND_RULE_USERDN_ALL);
@@ -307,7 +338,7 @@
buildAciValue("name", "deny read to users with 'admin' in their cn", "targetattr", "*", "deny(read)", BIND_RULE_USERDN_ALL_CN_ADMINS);
private static final String ALLOW_SEARCH_TO_CN_ADMINS =
- buildAciValue("name", "allow search to users with 'admin' in their cn", "targetattr", "*", "allow(search)", BIND_RULE_USERDN_ALL_CN_ADMINS);
+ buildAciValue("name", "allow search to users with 'admin' in their cn", "targetattr", "*", "allow(search, read)", BIND_RULE_USERDN_ALL_CN_ADMINS);
private static final String DENY_READ_TO_TOP_LEVEL_CN_ADMINS =
buildAciValue("name", "deny read to users with 'admin' in their cn", "targetattr", "*", "deny(read)", BIND_RULE_USERDN_TOP_LEVEL_CN_ADMINS);
@@ -386,19 +417,19 @@
buildAciValue("name", "allow not admin", "targetattr", "*", "allow(all)", BIND_RULE_USERDN_NOT_ADMIN);
private static final String ALLOW_SEARCH_TO_LOCALHOST =
- buildAciValue("name", "allow search to localhost", "targetattr", "*", "allow(search)", BIND_RULE_IP_LOCALHOST);
+ buildAciValue("name", "allow search to localhost", "targetattr", "*", "allow(search, read)", BIND_RULE_IP_LOCALHOST);
private static final String ALLOW_SEARCH_REALATTRS_TO_LOCALHOST =
- buildAciValue("name", "allow search to localhost", "targetattr!=", "bogusAttr", "allow(search)", BIND_RULE_IP_LOCALHOST);
+ buildAciValue("name", "allow search to localhost", "targetattr!=", "bogusAttr", "allow(search, read)", BIND_RULE_IP_LOCALHOST);
private static final String ALLOW_SEARCH_OUR_ATTRS_TO_ADMIN =
- buildAciValue("name", "allow search to our attributes to admin", "targetattr", "objectclass||ou||cn||sn||givenname", "target", LDAP_URL_OU_INNER, "allow(search)", BIND_RULE_USERDN_ADMIN);
+ buildAciValue("name", "allow search to our attributes to admin", "targetattr", "objectclass||ou||cn||sn||givenname", "target", LDAP_URL_OU_INNER, "allow(search, read)", BIND_RULE_USERDN_ADMIN);
private static final String ALLOW_SEARCH_TARGET_INNER_TO_LOCALHOST =
- buildAciValue("name", "allow search inner to localhost", "targetattr", "*", "target", LDAP_URL_OU_INNER, "allow(search)", BIND_RULE_IP_LOCALHOST);
+ buildAciValue("name", "allow search inner to localhost", "targetattr", "*", "target", LDAP_URL_OU_INNER, "allow(search, read)", BIND_RULE_IP_LOCALHOST);
private static final String ALLOW_SEARCH_OU_AND_PERSON_TO_SIMPLE =
- buildAciValue("name", "allow search ou and person to localhost", "targetattr", "*", "targetfilter", "(|(objectclass=organizationalunit)(objectclass=person))", "allow(search)", BIND_RULE_AUTHMETHOD_SIMPLE);
+ buildAciValue("name", "allow search ou and person to localhost", "targetattr", "*", "targetfilter", "(|(objectclass=organizationalunit)(objectclass=person))", "allow(search, read)", BIND_RULE_AUTHMETHOD_SIMPLE);
// -----------------------------------------------------------------------------
@@ -461,6 +492,13 @@
buildAciValue("name", "w/ 1 targetattr", "targetattr", "cn", "allow (write)", BIND_RULE_USERDN_SELF),
buildAciValue("name", "w/ 2 targetattr", "targetattr", "cn || sn", "allow (write)", BIND_RULE_USERDN_SELF),
buildAciValue("name", "w/ 3 targetattr", "targetattr", "cn || sn || uid", "allow (write)", BIND_RULE_USERDN_SELF),
+ //These are four are OpenDS specific attr names
+ buildAciValue("name", "opends targetattr", "targetattr", "1-digitinfirst", "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "opendstargetattr", "targetattr", "this_has_underscores", "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "locality targetattr", "targetattr", "locality;lang-fr-ca", "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "oid targetattr", "targetattr", " 2.16.840.1.113730.3.3.2.18.1.4", "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "complicated targetattr", "targetattr", "1ocal_ity;lang-fr-ca", "allow (write)", BIND_RULE_USERDN_SELF),
+
buildAciValue("name", "w/ * targetattr", "targetattr", "*", "allow (write)", BIND_RULE_USERDN_SELF),
buildAciValue("name", "w/ non-existing attr", "targetattr", "notanattr", "allow (write)", BIND_RULE_USERDN_SELF), // DS 5.2p4 accepts this so we should too.
buildAciValue("name", "w/ non-existing attr", "targetattr", "cn || notanattr", "allow (write)", BIND_RULE_USERDN_SELF), // DS 5.2p4 accepts this so we should too.
@@ -481,20 +519,16 @@
buildAciValue("name", "w/ 1 !targetattr", "targetattr!=", "cn", "allow (write)", BIND_RULE_USERDN_SELF),
buildAciValue("name", "w/ 2 !targetattr", "targetattr!=", "cn || sn", "allow (write)", BIND_RULE_USERDN_SELF),
buildAciValue("name", "w/ targetfilter", "targetfilter!=", "(sn=admin)", "allow (write)", BIND_RULE_USERDN_SELF),
-// </PASSES>
-
-// <FAILS>
-// These aren't supported yet. We should open an issue.
-// buildAciValue("name", "w/ targetattrfilters", "targetattrfilters", "add=cn:(!(cn=superAdmin))", "allow (write)", BIND_RULE_USERDN_SELF),
-// buildAciValue("name", "w/ targetattrfilters", "targetattrfilters", "add=cn:(!(cn=superAdmin)) && telephoneNumber:(telephoneNumber=123*)", "allow (write)", BIND_RULE_USERDN_SELF),
-// </FAILS>
-
-// <PASSES>
+ buildAciValue("name", "w/ targattrfilters", "targattrfilters=", TARG_ATTR_FILTERS, "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "w/ targattrfilters", "targattrfilters=", TARG_ATTR_FILTERS_1 , "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "w/ targattrfilters", "targattrfilters=", TARG_ATTR_FILTERS_2 , "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "w/ targattrfilters", "targattrfilters=", TARG_ATTR_FILTERS_5 , "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "bad_ATTR_TYPE_NAME", "targattrfilters",TARG_ATTR_FILTERS_ATTR_TYPE_NAME, "allow (write)", BIND_RULE_USERDN_SELF),
buildAciValue("name", "read", "targetattr", "*", "allow (read)", BIND_RULE_USERDN_SELF),
buildAciValue("name", "write", "targetattr", "*", "allow (write)", BIND_RULE_USERDN_SELF),
buildAciValue("name", "add", "targetattr", "*", "allow (add)", BIND_RULE_USERDN_SELF),
buildAciValue("name", "delete", "targetattr", "*", "allow (delete)", BIND_RULE_USERDN_SELF),
- buildAciValue("name", "search", "targetattr", "*", "allow (search)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "search", "targetattr", "*", "allow (search, read)", BIND_RULE_USERDN_SELF),
buildAciValue("name", "compare", "targetattr", "*", "allow (compare)", BIND_RULE_USERDN_SELF),
buildAciValue("name", "selfwrite", "targetattr", "*", "allow (selfwrite)", BIND_RULE_USERDN_SELF),
buildAciValue("name", "all", "targetattr", "*", "allow (all)", BIND_RULE_USERDN_SELF),
@@ -518,16 +552,22 @@
buildAciValue("name", "read anyone", "targetattr", "*", "allow (read)", BIND_RULE_USERDN_ANYONE),
buildAciValue("name", "read filter", "targetattr", "*", "allow (read)", BIND_RULE_USERDN_FILTER),
buildAciValue("name", "read parent", "targetattr", "*", "allow (read)", BIND_RULE_USERDN_PARENT),
-// <FAIL>
-// These aren't supported yet. We should open an issue.
-// buildAciValue("name", "read group dn 1", "targetattr", "*", "allow (read)", BIND_RULE_GROUPDN_1),
-// buildAciValue("name", "read group dn 2", "targetattr", "*", "allow (read)", BIND_RULE_GROUPDN_2),
-// buildAciValue("name", "read group dn 3", "targetattr", "*", "allow (read)", BIND_RULE_GROUPDN_3),
-// </FAIL>
- buildAciValue("name", "userattr", "targetattr", "*", "allow (read)", "userattr=\"manager#USERDN\""),
- buildAciValue("name", "userattr", "targetattr", "*", "allow (read)", "userattr=\"ldap:///dc=example,dc=com?owner#USERDN\""),
- buildAciValue("name", "userattr", "targetattr", "*", "allow (read)", "userattr=\"cn#LDAPURL\""),
-
+ buildAciValue("name", "read group dn 1", "targetattr", "*", "allow (read)", BIND_RULE_GROUPDN_1),
+ buildAciValue("name", "read group dn 2", "targetattr", "*", "allow (read)", BIND_RULE_GROUPDN_2),
+ buildAciValue("name", "read group dn 3", "targetattr", "*", "allow (read)", BIND_RULE_GROUPDN_3),
+ buildAciValue("name", "read group dn 1", "targetattr", "*", "allow (read)", BIND_RULE_ROLEDN_1),
+ buildAciValue("name", "read group dn 2", "targetattr", "*", "allow (read)", BIND_RULE_ROLEDN_2),
+ buildAciValue("name", "read group dn 3", "targetattr", "*", "allow (read)", BIND_RULE_ROLEDN_3),
+ buildAciValue("name", "userattr", "targetattr", "*", "allow (read)", BIND_RULE_USERATTR_USERDN),
+ buildAciValue("name", "userattr", "targetattr", "*", "allow (read)", BIND_RULE_USERATTR_USERDN_1),
+ buildAciValue("name", "userattr", "targetattr", "*", "allow (read)", BIND_RULE_USERATTR_URL),
+ buildAciValue("name", "userattr", "targetattr", "*", "allow (read)", BIND_RULE_USERATTR_GROUPDN),
+ buildAciValue("name", "userattr", "targetattr", "*", "allow (read)", BIND_RULE_USERATTR_GROUPDN_1),
+ buildAciValue("name", "userattr", "targetattr", "*", "allow (read)", BIND_RULE_USERATTR_ROLEDN),
+ buildAciValue("name", "userattr", "targetattr", "*", "allow (read)", BIND_RULE_USERATTR_ROLEDN_1),
+ buildAciValue("name", "userattr", "targetattr", "*", "allow (read)", BIND_RULE_USERATTR_USERDN_INHERITANCE),
+ buildAciValue("name", "userattr", "targetattr", "*", "allow (read)", BIND_RULE_USERATTR_GROUPDN_INHERITANCE),
+ buildAciValue("name", "userattr", "targetattr", "*", "allow (read)", BIND_RULE_USERATTR_VALUE),
// BUG! These work with DS 5.2p4, but not with OpenDS.
// <FAIL>
// DENY_ALL_TO_LOCALHOST_SUBNET,
@@ -559,12 +599,6 @@
DENY_ALL_TO_ADMIN_AND_LOCALHOST_OR_SSL,
ALLOW_ALL_NOT_ADMIN
-
-// <FAIL>
-// These aren't supported yet. We should open an issue.
-// buildAciValue("name", "userattr 1", "targetattr", "*", "allow (read)", "userattr=\"owner#GROUPDN\""),
-// buildAciValue("name", "userattr 1", "targetattr", "*", "allow (read)", "userattr=\"ldap:///dc=example,dc=com?owner#GROUPDN\""),
-// </FAIL>
// </PASSES>
// TODO: bind rules for 'ip', 'dns', 'dayofweek', 'timeofday', 'authmethod'
// TODO: combinations of these things, including multiple bind rules.
@@ -575,20 +609,29 @@
// Test each feature in isolation.
// <PASSES>
"aci: ",
- buildAciValue("allow (write)", BIND_RULE_USERDN_SELF), // No name
- buildAciValue("name", "invalid", "target", "ldap:///", "allow (write)", BIND_RULE_USERDN_SELF),
- buildAciValue("name", "invalid", "target", "ldap:///not a DN", "allow (write)", BIND_RULE_USERDN_SELF),
- buildAciValue("name", "invalid", "target", "ldap:///cn=", "allow (write)", BIND_RULE_USERDN_SELF),
- buildAciValue("name", "invalid", "targetattr", "", "allow (write)", BIND_RULE_USERDN_SELF),
- buildAciValue("name", "invalid", "targetattr", "not an attr", "allow (write)", BIND_RULE_USERDN_SELF),
- buildAciValue("name", "invalid", "targetattr", "cn ||", "allow (write)", BIND_RULE_USERDN_SELF),
- buildAciValue("name", "invalid", "targetattr", "not/an/attr", "allow (write)", BIND_RULE_USERDN_SELF),
- buildAciValue("name", "invalid", "targetattr", "cn", "allow (write)", BIND_RULE_INVALID_DAY),
+ buildAciValue("allow (write)", BIND_RULE_USERDN_SELF), // No name
+ buildAciValue("name", "invalid", "target", "ldap:///", "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "invalid", "target", "ldap:///not a DN", "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "invalid", "target", "ldap:///cn=", "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "invalid", "targetattr", "", "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "invalid", "targetattr", "not an attr", "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "invalid", "targetattr", "cn ||", "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "invalid", "targetattr", "not/an/attr", "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "invalid", "targetattr", "cn", "allow (write)", BIND_RULE_INVALID_DAY),
+ buildAciValue("name", "bad_filters", "targetattrfilters",TARG_ATTR_FILTERS_INVALID_FILTER, "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "bad_op", "targetattrfilters",TARG_ATTR_FILTERS_BAD_OP, "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "bad_op_match", "targetattrfilters",TARG_ATTR_FILTERS_BAD_OP_MATCH, "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "bad_filter_attr", "targetattrfilters",TARG_ATTR_FILTERS_BAD_FILTER_ATTR, "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "bad_format", "targetattrfilters",TARG_ATTR_FILTERS_BAD_FORMAT, "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "too_many_lists", "targetattrfilters",TARG_ATTR_FILTERS_TOO_MANY_LISTS, "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "bad_tok", "targetattrfilters",TARG_ATTR_FILTERS_BAD_TOK, "allow (write)", BIND_RULE_USERDN_SELF),
-// <FAIL>
-// Attributes can't have '_' right?, but DS 5.2p4 accepts this, so should we?
-// buildAciValue("name", "invalid", "targetattr", "not_an_attr", "allow (write)", BIND_RULE_USERDN_SELF),
-// </FAIL>
+
+ buildAciValue("name", "bad targetScope", "targetScope", "sub_tree", "allow (write)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "bad right", "targetattr", "*", "allow (read, write, add, delete, search, compare, selfwrite, all, foo)", BIND_RULE_USERDN_SELF),
+ buildAciValue("name", "bad access type", "targetattr", "*", "allows (read, write, add, delete, search, compare, selfwrite, all)", BIND_RULE_USERDN_SELF),
+ //no name
+ buildAciValue("targetattr", "*", "allows (read, write, add, delete, search, compare, selfwrite, all)", BIND_RULE_USERDN_SELF),
// </PASSES>
};
@@ -1392,7 +1435,7 @@
// Ignoring whitespace the diff should be empty.
Assert.assertTrue(diffFromExpected.replaceAll("\\s", "").length() == 0);
} catch (Throwable e) {
- System.err.println(
+ System.err.println(
"Started with dit:\n" +
params._initialDitLdif +
((params._aciLdif.length() == 0) ?
@@ -1429,7 +1472,7 @@
String aciField = aciFields[i];
String aciValue = aciFields[i+1];
- if (aciField.startsWith("target")) {
+ if (aciField.startsWith("targ")) {
if (!aciField.endsWith("=")) { // We allow = or more importantly != to be included with the target
aciField += "=";
}
@@ -1456,7 +1499,7 @@
String permission = aciFields[i];
String bindRule = aciFields[i+1];
- if (!permission.startsWith("target") && !permission.equals("name")) {
+ if (!permission.startsWith("targ") && !permission.equals("name")) {
aci.append(EOL + " " + permission + " " + bindRule + ";");
}
}
--
Gitblit v1.10.0