These changes are mostly related to restructuring the regular
expression patterns to make them more readable by defining constants.
The other changes included are:
- support the "targattrfilters" target keyword
- make the "search" right behave correctly
- fix a bug in the way we evaluate multiple permission bind rule pairs
- the targetattr wild-card "*" will now not return operational
attributes; operational attributes now need to be explicitly defined
in the targetattr rule to grant access
1 files added
42 files modified
| | |
| | | * The Aci class represents ACI strings. |
| | | */ |
| | | public class Aci { |
| | | |
| | | /* |
| | | * The body of the ACI is the version, name and permission-bind rule |
| | | * pairs. |
| | |
| | | */ |
| | | public static final String supportedVersion="3.0"; |
| | | |
| | | /* |
| | | * String representation of the ACI used. |
| | | */ |
| | | private String aciString; |
| | | |
| | | /* |
| | |
| | | */ |
| | | 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. |
| | |
| | | isApplicable(Aci aci, AciTargetMatchContext matchCtx) { |
| | | return AciTargets.isTargetApplicable(aci, matchCtx) && |
| | | AciTargets.isTargetFilterApplicable(aci, matchCtx) && |
| | | AciTargets.isTargAttrFiltersApplicable(aci, matchCtx) && |
| | | AciTargets.isTargetAttrApplicable(aci, matchCtx); |
| | | } |
| | | |
| | |
| | | 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; |
| | |
| | | */ |
| | | 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 |
| | |
| | | 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); |
| | |
| | | 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 |
| | |
| | | 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; |
| | | } |
| | |
| | | */ |
| | | private Operation operation; |
| | | |
| | | /* |
| | | * True if a targattrfilters match was found. |
| | | */ |
| | | private boolean targAttrFiltersMatch=false; |
| | | |
| | | /** |
| | | * This constructor is used by all currently supported LDAP operations. |
| | | * |
| | |
| | | public void setRights(int rights) { |
| | | this.rights=rights; |
| | | } |
| | | |
| | | /** |
| | | * Gets the hostname of the remote client. |
| | | * @return Cannonical hostname of remote client. |
| | |
| | | } |
| | | |
| | | /** |
| | | * 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() { |
| | |
| | | } |
| | | |
| | | /** |
| | | * 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; |
| | |
| | | */ |
| | | 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; |
| | | |
| | | /** |
| | |
| | | |
| | | 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; |
| | |
| | | */ |
| | | 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. |
| | |
| | | } |
| | | |
| | | /** |
| | | * 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 |
| | |
| | | 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 |
| | |
| | | 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; |
| | | } |
| | | |
| | | /* |
| | |
| | | */ |
| | | 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. |
| | |
| | | * 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. |
| | | */ |
| | |
| | | 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. |
| | | */ |
| | |
| | | } |
| | | attrs.add("aci"); |
| | | } |
| | | |
| | | /** |
| | | * Save the list created by the AciHandler routine. |
| | | * @param aciList The list object created and loaded by the handler. |
| | |
| | | /** |
| | | * 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; |
| | | |
| | | /** |
| | |
| | | |
| | | /** |
| | | * 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; |
| | | |
| | | /** |
| | |
| | | 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. |
| | |
| | | "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, |
| | |
| | | " 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 \"!=\"."); |
| | |
| | | "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" + |
| | |
| | | "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( |
| | |
| | | "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."); |
| | | |
| | | |
| | | } |
| | | } |
| | |
| | | */ |
| | | 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(); |
| | |
| | | * checked on. |
| | | */ |
| | | public interface AciTargetMatchContext { |
| | | |
| | | /** |
| | | * Set the deny ACI list. |
| | | * @param denyList The deny ACI list. |
| | |
| | | * @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(); |
| | | } |
| | | |
| | | |
| | |
| | | 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; |
| | |
| | | * 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 + ")*"; |
| | | |
| | |
| | | * 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 |
| | |
| | | * @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; |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | |
| | | 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); |
| | | } |
| | |
| | | { |
| | | // 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); |
| | | } |
| | |
| | | } |
| | | 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); |
| | | } |
| | | |
| | | /* |
| | |
| | | } |
| | | |
| | | /** |
| | | * 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 |
| | |
| | | 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 |
| | |
| | | * @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; |
| | | } |
| | | |
| | |
| | | * 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; |
| | | |
| | | /** |
| | |
| | | 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; |
| | |
| | | * 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 |
| | |
| | | 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; |
| | |
| | | */ |
| | | 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. |
| | |
| | | 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); |
| | |
| | | */ |
| | | 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; |
| | | |
| | | /** |
| | |
| | | * types (allow, deny). |
| | | */ |
| | | public enum EnumAccessType { |
| | | |
| | | /** |
| | | * Allow access type. |
| | | */ |
| | |
| | | */ |
| | | DENY ("deny"); |
| | | |
| | | /* |
| | | * The access type string. |
| | | */ |
| | | private final String accessType; |
| | | |
| | | /** |
| | |
| | | * 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. |
| | |
| | | */ |
| | | AUTHMETHOD_NOMATCH ("nomatch"); |
| | | |
| | | /** |
| | | /* |
| | | * The name of the authmethod. |
| | | */ |
| | | public String authmethod = null; |
| | | private String authmethod = null; |
| | | |
| | | /** |
| | | * Creates a new enumeration type for this authmethod. |
| | |
| | | * keyword types. |
| | | */ |
| | | public enum EnumBindRuleKeyword { |
| | | |
| | | /** |
| | | * The enumeration type when the bind rule has specified keyword of |
| | | * userdn. |
| | |
| | | * authmethod. |
| | | */ |
| | | AUTHMETHOD ("authmethod"); |
| | | /** |
| | | |
| | | /* |
| | | * The keyword name. |
| | | */ |
| | | public final String keyword; |
| | | private final String keyword; |
| | | |
| | | /** |
| | | * Creates a new enumeration type for the specified keyword. |
| | |
| | | * 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 |
| | | * "=". |
| | |
| | | */ |
| | | GREATER_OR_EQUAL_BINDRULE_TYPE (">="); |
| | | |
| | | /** |
| | | /* |
| | | * The bind rule type name. |
| | | */ |
| | | private final String type; |
| | |
| | | * 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". |
| | |
| | | */ |
| | | NOT_BOOLEAN_TYPE ("not"); |
| | | |
| | | /** |
| | | /* |
| | | * The bind rule boolean type name. |
| | | */ |
| | | private final String booleanType; |
| | |
| | | * 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". |
| | |
| | | */ |
| | | DAY_SUNDAY ("sun"); |
| | | |
| | | /** |
| | | /* |
| | | * The bind rule dayofweek type name. |
| | | */ |
| | | private String day = null; |
| | |
| | | * the bind rule evaluation methods. |
| | | */ |
| | | public enum EnumEvalResult { |
| | | |
| | | /** |
| | | * This enumeration is returned when the result of the evaluation is TRUE. |
| | | */ |
| | |
| | | */ |
| | | |
| | | package org.opends.server.authorization.dseecompat; |
| | | import static org.opends.server.authorization.dseecompat.Aci.*; |
| | | |
| | | /** |
| | | * This class provides an enumeration of the allowed rights. |
| | |
| | | */ |
| | | ADDWRITE ("addwrite"); |
| | | |
| | | /** |
| | | /* |
| | | * The name of the right. |
| | | */ |
| | | private final String right; |
| | |
| | | * @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; |
| | |
| | | * This class provides an enumeration of the valid ACI target keywords. |
| | | */ |
| | | public enum EnumTargetKeyword { |
| | | |
| | | /** |
| | | * This enumeration is returned when the target keyword is |
| | | * "target". |
| | |
| | | * "targattrfilters". |
| | | */ |
| | | KEYWORD_TARGATTRFILTERS ("targattrfilters"); |
| | | |
| | | /* |
| | | * TODO Add support for the targattrfilters keyword. |
| | | */ |
| | | /** |
| | | * The target keyword name. |
| | | */ |
| | | private final String keyword; |
| | |
| | | * This class provides an enumeration of the valid ACI target operators. |
| | | */ |
| | | public enum EnumTargetOperator { |
| | | |
| | | /** |
| | | * This enumeration is returned when the target operator is "=". |
| | | */ |
| | |
| | | */ |
| | | NOT_EQUALITY ("!="); |
| | | |
| | | /** |
| | | /* |
| | | * The target operator name. |
| | | */ |
| | | private final String operator; |
| | |
| | | * 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. |
| | |
| | | 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; |
| | |
| | | */ |
| | | 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. |
| | |
| | | */ |
| | | 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 { |
| | |
| | | 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; |
| | |
| | | /** |
| | | * 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 |
| | |
| | | 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. |
| | |
| | | */ |
| | | 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); |
| | |
| | | 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; |
| | | |
| | |
| | | * 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; |
| | | |
| | | |
| | |
| | | //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. |
| | |
| | | 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 = |
| | |
| | | */ |
| | | public class PermBindRulePair { |
| | | |
| | | /* |
| | | * The Bind Rule part. |
| | | */ |
| | | private BindRule bindRule; |
| | | |
| | | /* |
| | | * The permission part. |
| | | */ |
| | | private Permission perm=null; |
| | | |
| | | /** |
| | |
| | | |
| | | 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; |
| | | |
| | | /** |
| | |
| | | * 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 |
| | |
| | | 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; |
| | |
| | | */ |
| | | 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 |
| | |
| | | * @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); |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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; |
| | | } |
| | | } |
| | |
| | | |
| | | 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; |
| | | } |
| | | |
| | | } |
| | |
| | | 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; |
| | |
| | | */ |
| | | 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. |
| | |
| | | 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); |
| | |
| | | } |
| | | |
| | | /* |
| | | * 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. |
| | |
| | | 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; |
| | |
| | | * 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. |
| | |
| | | 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 |
| | |
| | | } else { |
| | | int msgID = |
| | | MSGID_ACI_SYNTAX_INVALID_TARGETATTRKEYWORD_EXPRESSION; |
| | | String message = getMessage(msgID, operator); |
| | | String message = getMessage(msgID, attrString); |
| | | throw new AciException(msgID, message); |
| | | } |
| | | } |
| | |
| | | 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. |
| | |
| | | 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(); |
| | |
| | | * |
| | | */ |
| | | 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. |
| | |
| | | * 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; |
| | | |
| | | /** |
| | |
| | | * 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 |
| | |
| | | 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); |
| | | } |
| | |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | |
| | | */ |
| | | 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. |
| | |
| | | * 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. |
| | | */ |
| | |
| | | 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\""; |
| | |
| | | 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\";)"; |
| | | |
| | |
| | | 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); |
| | |
| | | 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); |
| | |
| | | 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); |
| | |
| | | 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); |
| | |
| | | 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); |
| | | |
| | | |
| | | // ----------------------------------------------------------------------------- |
| | |
| | | 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. |
| | |
| | | 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), |
| | |
| | | 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, |
| | |
| | | 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. |
| | |
| | | // 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> |
| | | }; |
| | |
| | | // 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) ? |
| | |
| | | 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 += "="; |
| | | } |
| | |
| | | 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 + ";"); |
| | | } |
| | | } |