ACI UCDetector and AutoRefactor code cleanup
| | |
| | | import org.forgerock.opendj.ldap.ByteSequence; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | |
| | | /** |
| | | * The Aci class represents ACI strings. |
| | | */ |
| | | /** The Aci class represents ACI strings. */ |
| | | public class Aci implements Comparable<Aci> |
| | | { |
| | | |
| | | /** |
| | | * The body of the ACI is the version, name and permission-bind rule |
| | | * pairs. |
| | | */ |
| | | private AciBody body; |
| | | |
| | | /** |
| | | * The ACI targets. |
| | | */ |
| | | private AciTargets targets; |
| | | |
| | | /** |
| | | * Version that we support. |
| | | */ |
| | | /** Version that we support. */ |
| | | public static final String supportedVersion="3.0"; |
| | | |
| | | /** |
| | | * String representation of the ACI used. |
| | | */ |
| | | private String aciString; |
| | | |
| | | /** |
| | | * The DN of the entry containing this ACI. |
| | | */ |
| | | /** The body of the ACI is the version, name and permission-bind rule pairs. */ |
| | | private final AciBody body; |
| | | /** The ACI targets. */ |
| | | private final AciTargets targets; |
| | | /** String representation of the ACI used. */ |
| | | private final String aciString; |
| | | /** The DN of the entry containing this ACI. */ |
| | | private final DN dn; |
| | | |
| | | /** |
| | | * Regular expression matching a word group. |
| | | */ |
| | | /** 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 word group at the start of a pattern. */ |
| | | static final String WORD_GROUP_START_PATTERN = "^" + WORD_GROUP; |
| | | |
| | | /** |
| | | * Regular expression matching a white space. |
| | | */ |
| | | /** 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. |
| | | */ |
| | | /** 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. |
| | | */ |
| | | /** Regular expression matching a white space at the end of a pattern. */ |
| | | private static final String ZERO_OR_MORE_WHITESPACE_END_PATTERN = |
| | | ZERO_OR_MORE_WHITESPACE + "$"; |
| | | |
| | | /** |
| | | * Regular expression matching a ACL statement separator. |
| | | */ |
| | | /** 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. |
| | | */ |
| | | /** This regular expression is used to do a quick syntax check when an ACI is being decoded. */ |
| | | private static final String aciRegex = |
| | | 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, |
| | |
| | | * the special shorthand characters "*" for all user attributes and "+" for |
| | | * all operational attributes. |
| | | */ |
| | | public static final String ATTR_NAME = |
| | | static final String ATTR_NAME = |
| | | "((?i)[a-z\\d]{1}[[a-z]\\d-_.]*(?-i)|\\*{1}|\\+{1})"; |
| | | |
| | | /** |
| | | * Regular expression matching a LDAP URL. |
| | | */ |
| | | /** Regular expression matching a LDAP URL. */ |
| | | public static final String LDAP_URL = ZERO_OR_MORE_WHITESPACE + |
| | | "(ldap:///[^\\|]+)"; |
| | | |
| | | /** |
| | | * String used to check for NULL ldap URL. |
| | | */ |
| | | /** String used to check for NULL ldap URL. */ |
| | | public static final String NULL_LDAP_URL = "ldap:///"; |
| | | |
| | | /** |
| | | * Regular expression used to match token that joins expressions (||). |
| | | */ |
| | | public static final String LOGICAL_OR = "\\|\\|"; |
| | | /** Regular expression used to match token that joins expressions (||). */ |
| | | static final String LOGICAL_OR = "\\|\\|"; |
| | | /** Regular expression used to match an open parenthesis. */ |
| | | static final String OPEN_PAREN = "\\("; |
| | | /** Regular expression used to match a closed parenthesis. */ |
| | | static final String CLOSED_PAREN = "\\)"; |
| | | /** Regular expression used to match a single equal sign. */ |
| | | static final String EQUAL_SIGN = "={1}"; |
| | | |
| | | /** |
| | | * 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 "*". |
| | | */ |
| | | /** Regular expression the matches "*". */ |
| | | public static final String ALL_USER_ATTRS_WILD_CARD = |
| | | ZERO_OR_MORE_WHITESPACE + |
| | | "\\*" + ZERO_OR_MORE_WHITESPACE; |
| | | |
| | | /** |
| | | * Regular expression the matches "+". |
| | | */ |
| | | /** Regular expression the matches "+". */ |
| | | public static final String ALL_OP_ATTRS_WILD_CARD = |
| | | ZERO_OR_MORE_WHITESPACE + |
| | | "\\+" + ZERO_OR_MORE_WHITESPACE; |
| | | |
| | | /** |
| | | * Regular expression used to do quick check of OID string. |
| | | */ |
| | | /** Regular expression used to do quick check of OID string. */ |
| | | private static final String OID_NAME = "[\\d.\\*]*"; |
| | | |
| | | /** |
| | | * Regular expression that matches one or more OID_NAME's separated by |
| | | * the "||" token. |
| | | */ |
| | | /** Regular expression that matches one or more OID_NAME's separated by the "||" token. */ |
| | | private static final String oidListRegex = ZERO_OR_MORE_WHITESPACE + |
| | | OID_NAME + ZERO_OR_MORE_WHITESPACE + "(" + |
| | | LOGICAL_OR + ZERO_OR_MORE_WHITESPACE + OID_NAME + |
| | | ZERO_OR_MORE_WHITESPACE + ")*"; |
| | | |
| | | /** |
| | | * ACI_ADD is used to set the container rights for a LDAP add operation. |
| | | */ |
| | | /** ACI_ADD is used to set the container rights for a LDAP add operation. */ |
| | | public static final int ACI_ADD = 0x0020; |
| | | |
| | | /** |
| | | * ACI_DELETE is used to set the container rights for a LDAP |
| | | * delete operation. |
| | | */ |
| | | public static final int ACI_DELETE = 0x0010; |
| | | |
| | | /** |
| | | * 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 = 0x0001; |
| | | |
| | | /** |
| | | * ACI_SEARCH is used to set the container rights a LDAP search operation. |
| | | */ |
| | | public static final int ACI_SEARCH = 0x0002; |
| | | |
| | | /** |
| | | * ACI_SELF is used for the SELFWRITE right. |
| | | */ |
| | | /** ACI_DELETE is used to set the container rights for a LDAP delete operation. */ |
| | | static final int ACI_DELETE = 0x0010; |
| | | /** ACI_READ is used to set the container rights for a LDAP search operation. */ |
| | | static final int ACI_READ = 0x0004; |
| | | /** ACI_WRITE is used to set the container rights for a LDAP modify operation. */ |
| | | static final int ACI_WRITE = 0x0008; |
| | | /** ACI_COMPARE is used to set the container rights for a LDAP compare operation. */ |
| | | static final int ACI_COMPARE = 0x0001; |
| | | /** ACI_SEARCH is used to set the container rights a LDAP search operation. */ |
| | | static final int ACI_SEARCH = 0x0002; |
| | | /** ACI_SELF is used for the SELFWRITE right. */ |
| | | 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. |
| | | */ |
| | | static final int ACI_ALL = 0x007F; |
| | | /** ACI_PROXY is used for the PROXY right. */ |
| | | public static final int ACI_PROXY = 0x0080; |
| | | |
| | | /** |
| | | * ACI_IMPORT is used to set the container rights for a LDAP |
| | | * modify dn operation. |
| | | */ |
| | | public static final int ACI_IMPORT = 0x0100; |
| | | |
| | | /** |
| | | * ACI_EXPORT is used to set the container rights for a LDAP |
| | | * modify dn operation. |
| | | */ |
| | | 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. |
| | | */ |
| | | /** ACI_IMPORT is used to set the container rights for a LDAP modify dn operation. */ |
| | | static final int ACI_IMPORT = 0x0100; |
| | | /** ACI_EXPORT is used to set the container rights for a LDAP modify dn operation. */ |
| | | static final int ACI_EXPORT = 0x0200; |
| | | /** ACI_WRITE_ADD is used by the LDAP modify operation. */ |
| | | 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; |
| | | |
| | | /** |
| | | * ACI_SKIP_PROXY_CHECK is used to bypass the proxy access check. |
| | | */ |
| | | /** ACI_SKIP_PROXY_CHECK is used to bypass the proxy access check. */ |
| | | public static final int ACI_SKIP_PROXY_CHECK = 0x400000; |
| | | |
| | | /** |
| | |
| | | * The TARGATTRFILTERS_ADD flag would be set during ACI parsing in the |
| | | * TargAttrFilters class. |
| | | */ |
| | | public static final int TARGATTRFILTERS_ADD = 0x1000; |
| | | static final int TARGATTRFILTERS_ADD = 0x1000; |
| | | |
| | | /** |
| | | * TARGATTRFILTER_DELETE is used to specify that a |
| | |
| | | * The TARGATTRFILTERS_DELETE flag would be set during ACI parsing in the |
| | | * TargAttrFilters class. |
| | | */ |
| | | public static final int TARGATTRFILTERS_DELETE = 0x2000; |
| | | static final int TARGATTRFILTERS_DELETE = 0x2000; |
| | | |
| | | /** |
| | | * Used by the control evaluation access check. |
| | | */ |
| | | public static final int ACI_CONTROL = 0x4000; |
| | | /** Used by the control evaluation access check. */ |
| | | static final int ACI_CONTROL = 0x4000; |
| | | |
| | | /** |
| | | * Used by the extended operation access check. |
| | | */ |
| | | /** Used by the extended operation access check. */ |
| | | public static final int ACI_EXT_OP = 0x8000; |
| | | |
| | | /** |
| | |
| | | * evaluation if the flag is ACI_ATTR_STAR_MATCHED (all attributes match) |
| | | * and the attribute type is not operational. |
| | | */ |
| | | public static final int ACI_USER_ATTR_STAR_MATCHED = 0x0008; |
| | | static final int ACI_USER_ATTR_STAR_MATCHED = 0x0008; |
| | | |
| | | /** |
| | | * ACI_FOUND_USER_ATTR_RULE is the flag set when the evaluation reason of a |
| | |
| | | * ACI targetattr specific user attribute expression |
| | | * (targetattr="some user attribute type") target match. |
| | | */ |
| | | public static final int ACI_FOUND_USER_ATTR_RULE = 0x0010; |
| | | static final int ACI_FOUND_USER_ATTR_RULE = 0x0010; |
| | | |
| | | /** |
| | | * ACI_OP_ATTR_PLUS_MATCHED is the flag set when the evaluation reason of a |
| | |
| | | * evaluation if the flag is ACI_OP_ATTR_PLUS_MATCHED (all operational |
| | | * attributes match) and the attribute type is operational. |
| | | */ |
| | | public static final int ACI_OP_ATTR_PLUS_MATCHED = 0x0004; |
| | | static final int ACI_OP_ATTR_PLUS_MATCHED = 0x0004; |
| | | |
| | | /** |
| | | * ACI_FOUND_OP_ATTR_RULE is the flag set when the evaluation reason of a |
| | |
| | | * ACI targetattr specific operational attribute expression |
| | | * (targetattr="some operational attribute type") target match. |
| | | */ |
| | | public static final int ACI_FOUND_OP_ATTR_RULE = 0x0020; |
| | | static final int ACI_FOUND_OP_ATTR_RULE = 0x0020; |
| | | |
| | | /** |
| | | * ACI_NULL is used to set the container rights to all zeros. Used |
| | | * by LDAP modify. |
| | | */ |
| | | public static final int ACI_NULL = 0x0000; |
| | | /** ACI_NULL is used to set the container rights to all zeros. Used by LDAP modify. */ |
| | | static final int ACI_NULL = 0x0000; |
| | | |
| | | /** |
| | | * Construct a new Aci from the provided arguments. |
| | |
| | | //Perform a quick pattern check against the string to catch any |
| | | //obvious syntax errors. |
| | | if (!Pattern.matches(aciRegex, input)) { |
| | | LocalizableMessage message = WARN_ACI_SYNTAX_GENERAL_PARSE_FAILED.get(input); |
| | | throw new AciException(message); |
| | | throw new AciException(WARN_ACI_SYNTAX_GENERAL_PARSE_FAILED.get(input)); |
| | | } |
| | | //Decode the body first. |
| | | AciBody body=AciBody.decode(input); |
| | |
| | | return this.body.getName(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Decode an OIDs expression string. |
| | | * |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008-2009 Sun Microsystems, Inc. |
| | | * Portions Copyright 2012-2015 ForgeRock AS. |
| | | * Portions Copyright 2012-2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | |
| | | * version, name, and permission-bind rule pairs. |
| | | */ |
| | | public class AciBody { |
| | | |
| | | /** |
| | | * Regular expression group position for the version string. |
| | | */ |
| | | /** Regular expression group position for the version string. */ |
| | | private static final int VERSION = 1; |
| | | |
| | | /** |
| | | * Regular expression group position for the name string. |
| | | */ |
| | | /** Regular expression group position for the name string. */ |
| | | private static final int NAME = 2; |
| | | |
| | | /** |
| | | * Regular expression group position for the permission string. |
| | | */ |
| | | /** Regular expression group position for the permission string. */ |
| | | private static final int PERM = 1; |
| | | |
| | | /** |
| | | * Regular expression group position for the rights string. |
| | | */ |
| | | /** Regular expression group position for the rights string. */ |
| | | private static final int RIGHTS = 2; |
| | | |
| | | /** |
| | | * Regular expression group position for the bindrule string. |
| | | */ |
| | | /** 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; |
| | | /** Index into the ACI string where the ACI body starts. */ |
| | | private final int startPos; |
| | | /** The name of the ACI, currently not used but parsed. */ |
| | | private final String name; |
| | | /** The version of the ACi, current not used but parsed and checked for 3.0. */ |
| | | private final String version; |
| | | |
| | | /** |
| | | * The name of the ACI, currently not used but parsed. |
| | | */ |
| | | private String name; |
| | | |
| | | /** |
| | | * The version of the ACi, current not used but parsed and checked for 3.0. |
| | | */ |
| | | private String version; |
| | | |
| | | /** |
| | | * This structure represents a permission-bind rule pairs. There can be |
| | | * several of these. |
| | | */ |
| | | private List<PermBindRulePair> permBindRulePairs; |
| | | /** This structure represents a permission-bind rule pairs. There can be several of these. */ |
| | | private final List<PermBindRulePair> permBindRulePairs; |
| | | |
| | | /** |
| | | * Regular expression used to match the access type group (allow, deny) and |
| | |
| | | ZERO_OR_MORE_WHITESPACE + permissionRegex + |
| | | ZERO_OR_MORE_WHITESPACE + bindRuleRegex; |
| | | |
| | | /** |
| | | * Regular expression used to match the version value (digit.digit). |
| | | */ |
| | | /** Regular expression used to match the version value (digit.digit). */ |
| | | private static final String versionRegex = "(\\d\\.\\d)"; |
| | | |
| | | /** |
| | | * Regular expression used to match the version token. Case insensitive. |
| | | */ |
| | | /** 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. |
| | | */ |
| | | /** Regular expression used to match the acl token. Case insensitive. */ |
| | | private static final String aclToken = "(?i)acl(?-i)"; |
| | | |
| | | /** |
| | | * Regular expression used to match the body of an ACI. This pattern is |
| | | * a general verification check. |
| | | */ |
| | | public static final String bodyRegx = |
| | | static final String bodyRegx = |
| | | "\\(" + ZERO_OR_MORE_WHITESPACE + versionToken + |
| | | ZERO_OR_MORE_WHITESPACE + versionRegex + |
| | | ACI_STATEMENT_SEPARATOR + aclToken + ZERO_OR_MORE_WHITESPACE + |
| | |
| | | Pattern bodyPattern1 = Pattern.compile("\\G" + actionRegex); |
| | | Matcher bodyMatcher1 = bodyPattern1.matcher(input); |
| | | |
| | | /* |
| | | * The may be many permission-bind rule pairs. |
| | | */ |
| | | /* The may be many permission-bind rule pairs. */ |
| | | int lastIndex = -1; |
| | | while(bodyMatcher1.find()) { |
| | | String perm=bodyMatcher1.group(PERM); |
| | |
| | | return this.name; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Mainly used because geteffectiverights adds flags to the rights that aren't |
| | | * needed in the actual evaluation of the ACI. This routine returns only the |
| | |
| | | return version; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String toString() |
| | | { |
| | |
| | | * The buffer into which a string representation of this object |
| | | * should be appended. |
| | | */ |
| | | public final void toString(StringBuilder buffer) |
| | | private final void toString(StringBuilder buffer) |
| | | { |
| | | buffer.append("(version ").append(this.version); |
| | | buffer.append("; acl \"").append(this.name).append("\"; "); |
| | | for (PermBindRulePair pair : this.permBindRulePairs) |
| | | { |
| | | buffer.append(pair); |
| | | pair.toString(buffer); |
| | | } |
| | | } |
| | | } |
| | |
| | | import org.opends.server.types.Attributes; |
| | | import org.opends.server.types.Entry; |
| | | |
| | | /** |
| | | * This class implements the dseecompat geteffectiverights evaluation. |
| | | */ |
| | | /** This class implements the dseecompat geteffectiverights evaluation. */ |
| | | public class AciEffectiveRights { |
| | | |
| | | /** |
| | | * Value used when a aclRights attribute was seen in the search operation |
| | | * attribute set. |
| | | */ |
| | | /** Value used when a aclRights attribute was seen in the search operation attribute set. */ |
| | | private static final int ACL_RIGHTS = 0x001; |
| | | |
| | | /** |
| | | * Value used when a aclRightsInfo attribute was seen in the search operation |
| | | * attribute set. |
| | | */ |
| | | /** Value used when a aclRightsInfo attribute was seen in the search operation attribute set. */ |
| | | private static final int ACL_RIGHTS_INFO = 0x002; |
| | | |
| | | /** |
| | |
| | | /**The distinguishedName string. */ |
| | | private static final String dnAttrStr = "distinguishedname"; |
| | | |
| | | /** |
| | | * String used to fill in the summary status field when access was allowed. |
| | | */ |
| | | private static String ALLOWED="access allowed"; |
| | | |
| | | /** |
| | | * String used to fill in the summary status field when access was not |
| | | * allowed. |
| | | */ |
| | | private static String NOT_ALLOWED="access not allowed"; |
| | | /** String used to fill in the summary status field when access was allowed. */ |
| | | private static final String ALLOWED = "access allowed"; |
| | | /** String used to fill in the summary status field when access was not allowed. */ |
| | | private static final String NOT_ALLOWED = "access not allowed"; |
| | | |
| | | /** Evaluated as anonymous user. Used to fill in summary field. */ |
| | | private static String anonymous="anonymous"; |
| | | private static final String anonymous = "anonymous"; |
| | | |
| | | /** Format used to build the summary string. */ |
| | | private static String summaryFormatStr = |
| | | private static final String summaryFormatStr = |
| | | "acl_summary(%s): %s(%s) on entry/attr(%s, %s) to (%s)" + |
| | | " (not proxied) ( reason: %s %s)"; |
| | | |
| | |
| | | * Strings below represent access denied or allowed evaluation reasons. Used |
| | | * to fill in the summary status field. Access evaluated an allow ACI. |
| | | */ |
| | | private static String EVALUATED_ALLOW="evaluated allow"; |
| | | |
| | | private static final String EVALUATED_ALLOW = "evaluated allow"; |
| | | /** Access evaluated a deny ACI. */ |
| | | private static String EVALUATED_DENY="evaluated deny"; |
| | | |
| | | private static final String EVALUATED_DENY = "evaluated deny"; |
| | | /** Access evaluated deny because there were no allow ACIs. */ |
| | | private static String NO_ALLOWS="no acis matched the resource"; |
| | | |
| | | private static final String NO_ALLOWS = "no acis matched the resource"; |
| | | /** Access evaluated deny because no allow or deny ACIs evaluated. */ |
| | | private static String NO_ALLOWS_MATCHED="no acis matched the subject"; |
| | | |
| | | private static final String NO_ALLOWS_MATCHED = "no acis matched the subject"; |
| | | /** Access evaluated allow because the clientDN has bypass-acl privileges. */ |
| | | private static String SKIP_ACI="user has bypass-acl privileges"; |
| | | private static final String SKIP_ACI = "user has bypass-acl privileges"; |
| | | |
| | | //TODO add support for the modify-acl privilege? |
| | | |
| | |
| | | addEntryLevelRights(container, handler, attrMask, e, skipCheck); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Perform the attributeLevel rights evaluation on a list of specified |
| | | * attribute types. Each attribute has an access check done for the following |
| | |
| | | container.setCurrentAttributeType(null); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Perform the attributeLevel write rights evaluation. The issue here is that |
| | | * an ACI could contain a targattrfilters keyword that matches the attribute |
| | |
| | | return resString.toString(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Check that access is allowed on the aclRights and/or aclRightsInfo |
| | | * attribute types. |
| | |
| | | return retRight && retInfo; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Add aclRightsInfo attributeLevel information to the entry. This is the |
| | | * summary string built from the last access check. |
| | |
| | | void addAttrLevelRightsInfo(AciLDAPOperationContainer container, int mask, |
| | | AttributeType aType, Entry retEntry, |
| | | String rightStr) { |
| | | |
| | | //Check if the aclRightsInfo attribute was requested. |
| | | if(hasAttrMask(mask,ACL_RIGHTS_INFO)) { |
| | | //Build the attribute type. |
| | |
| | | void addEntryLevelRightsInfo(AciLDAPOperationContainer container, int mask, |
| | | Entry retEntry, |
| | | String rightStr) { |
| | | |
| | | //Check if the aclRightsInfo attribute was requested. |
| | | if(hasAttrMask(mask,ACL_RIGHTS_INFO)) { |
| | | String typeStr = aclRightsInfoEntryLogsStr + ";" + rightStr; |
| | |
| | | return (mask & rightsAttr) != 0; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Create the summary string used in the aclRightsInfo log string. |
| | | * |
| | |
| | | * String used to indicate that the evaluating ACI had a all |
| | | * operational attributes targetattr match (targetattr="+"). |
| | | */ |
| | | public static final String ALL_OP_ATTRS_MATCHED = "allOpAttrsMatched"; |
| | | static final String ALL_OP_ATTRS_MATCHED = "allOpAttrsMatched"; |
| | | |
| | | /** |
| | | * String used to indicate that the evaluating ACI had a all user |
| | | * attributes targetattr match (targetattr="*"). |
| | | */ |
| | | public static final String ALL_USER_ATTRS_MATCHED = "allUserAttrsMatched"; |
| | | static final String ALL_USER_ATTRS_MATCHED = "allUserAttrsMatched"; |
| | | |
| | | /** |
| | | * String used to save the original authorization entry in an |
| | | * operation attachment if a proxied authorization control was seen. |
| | | */ |
| | | public static final String ORIG_AUTH_ENTRY = "origAuthorizationEntry"; |
| | | static final String ORIG_AUTH_ENTRY = "origAuthorizationEntry"; |
| | | |
| | | /** Attribute type corresponding to "aci" attribute. */ |
| | | static AttributeType aciType; |
| | |
| | | new ReentrantReadWriteLock(); |
| | | |
| | | /** The configuration DN used to compare against the global ACI entry DN. */ |
| | | private DN configDN; |
| | | private final DN configDN; |
| | | |
| | | /** |
| | | * Constructor to create an ACI list to cache ACI attribute types. |
| | |
| | | baseDN=parentDN; |
| | | } |
| | | } |
| | | return candidates; |
| | | } |
| | | finally |
| | | { |
| | | lock.readLock().unlock(); |
| | | } |
| | | |
| | | return candidates; |
| | | } |
| | | |
| | | /** |
| | |
| | | public int addAci(List<? extends Entry> entries, |
| | | LinkedList<LocalizableMessage> failedACIMsgs) |
| | | { |
| | | int validAcis=0; |
| | | |
| | | lock.writeLock().lock(); |
| | | try |
| | | { |
| | | int validAcis = 0; |
| | | for (Entry entry : entries) { |
| | | DN dn=entry.getName(); |
| | | List<Attribute> attributeList = |
| | |
| | | validAcis += addAciAttributeList(aciList, dn, configDN, |
| | | attributeList, failedACIMsgs); |
| | | } |
| | | return validAcis; |
| | | } |
| | | finally |
| | | { |
| | | lock.writeLock().unlock(); |
| | | } |
| | | |
| | | return validAcis; |
| | | } |
| | | |
| | | /** |
| | |
| | | public int addAci(Entry entry, boolean hasAci, |
| | | boolean hasGlobalAci, |
| | | List<LocalizableMessage> failedACIMsgs) { |
| | | int validAcis=0; |
| | | |
| | | lock.writeLock().lock(); |
| | | try |
| | | { |
| | | int validAcis = 0; |
| | | //Process global "ds-cfg-global-aci" attribute type. The oldentry |
| | | //DN is checked to verify it is equal to the config DN. If not those |
| | | //attributes are skipped. |
| | |
| | | validAcis += addAciAttributeList(aciList, entry.getName(), configDN, |
| | | attributeList, failedACIMsgs); |
| | | } |
| | | return validAcis; |
| | | } |
| | | finally |
| | | { |
| | | lock.writeLock().unlock(); |
| | | } |
| | | |
| | | return validAcis; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public boolean removeAci(Entry entry, boolean hasAci, |
| | | boolean hasGlobalAci) { |
| | | DN entryDN = entry.getName(); |
| | | |
| | | lock.writeLock().lock(); |
| | | try |
| | | { |
| | | DN entryDN = entry.getName(); |
| | | if (hasGlobalAci && entryDN.equals(configDN) && |
| | | aciList.remove(DN.rootDN()) == null) |
| | | { |
| | |
| | | { |
| | | return aciList.removeSubtree(entryDN, null); |
| | | } |
| | | return true; |
| | | } |
| | | finally |
| | | { |
| | | lock.writeLock().unlock(); |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | /** The configuration DN. */ |
| | | private DN configurationDN; |
| | | private final DN configurationDN; |
| | | |
| | | /** True if the server is in lockdown mode. */ |
| | | private boolean inLockDownMode; |
| | | |
| | | /** The AciList caches the ACIs. */ |
| | | private AciList aciList; |
| | | private final AciList aciList; |
| | | |
| | | /** Search filter used in context search for "aci" attribute types. */ |
| | | private static SearchFilter aciFilter; |
| | | static |
| | | private final static SearchFilter aciFilter = buildAciFilter(); |
| | | private static SearchFilter buildAciFilter() |
| | | { |
| | | // Set up the filter used to search private and public contexts. |
| | | try |
| | | { |
| | | aciFilter = SearchFilter.createFilterFromString("(aci=*)"); |
| | | return SearchFilter.createFilterFromString("(aci=*)"); |
| | | } |
| | | catch (DirectoryException ex) |
| | | { |
| | | // TODO should never happen, error message? |
| | | return null; |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} In this case, the server will search the backend to |
| | | * find all aci attribute type values that it may contain and add them |
| | | * to the ACI list. |
| | | * {@inheritDoc} |
| | | * <p> |
| | | * In this case, the server will search the backend to find all aci attribute type values |
| | | * that it may contain and add them to the ACI list. |
| | | */ |
| | | @Override |
| | | public void performBackendPreInitializationProcessing(Backend<?> backend) |
| | |
| | | * @param failedACIMsgs |
| | | * List of exception messages from failed ACI decodes. |
| | | */ |
| | | public void logMsgsSetLockDownMode(LinkedList<LocalizableMessage> failedACIMsgs) |
| | | private void logMsgsSetLockDownMode(LinkedList<LocalizableMessage> failedACIMsgs) |
| | | { |
| | | for (LocalizableMessage msg : failedACIMsgs) |
| | | { |
| | |
| | | */ |
| | | public class AciTargets { |
| | | /** ACI syntax has a target keyword. */ |
| | | private Target target; |
| | | private final Target target; |
| | | /** ACI syntax has a targetscope keyword. */ |
| | | private SearchScope targetScope = SearchScope.WHOLE_SUBTREE; |
| | | private final SearchScope targetScope; |
| | | /** ACI syntax has a targetattr keyword. */ |
| | | private TargetAttr targetAttr; |
| | | private final TargetAttr targetAttr; |
| | | /** ACI syntax has a targetfilter keyword. */ |
| | | private TargetFilter targetFilter; |
| | | private final TargetFilter targetFilter; |
| | | /** ACI syntax has a targattrtfilters keyword. */ |
| | | private TargAttrFilters targAttrFilters; |
| | | private final TargAttrFilters targAttrFilters; |
| | | /** The ACI syntax has a targetcontrol keyword. */ |
| | | private TargetControl targetControl; |
| | | private final TargetControl targetControl; |
| | | /** The ACI syntax has a extop keyword. */ |
| | | private ExtOp extOp; |
| | | private final ExtOp extOp; |
| | | |
| | | /** The number of regular expression group positions in a valid ACI target expression. */ |
| | | private static final int targetElementCount = 3; |
| | |
| | | * Regular expression used to match one or more target rules. The pattern is |
| | | * part of a general ACI verification. |
| | | */ |
| | | public static final String targetsRegex = "(" + targetRegex + ")*"; |
| | | static final String targetsRegex = "(" + targetRegex + ")*"; |
| | | |
| | | /** |
| | | * Rights that are skipped for certain target evaluations. |
| | |
| | | * @return True if the one or more of the specified rights are in the |
| | | * skiprights rights mask. |
| | | */ |
| | | public static boolean skipRightsHasRights(int rights) { |
| | | private static boolean skipRightsHasRights(int rights) { |
| | | //geteffectiverights sets this flag, turn it off before evaluating. |
| | | int tmpRights=rights & ~ACI_SKIP_PROXY_CHECK; |
| | | return (skipRights & tmpRights) == tmpRights; |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2013-2015 ForgeRock AS. |
| | | * Portions Copyright 2013-2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | | import static org.opends.messages.AccessControlMessages.*; |
| | | |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.opends.server.core.DirectoryServer; |
| | | |
| | | /** |
| | | * The AuthMethod class represents an authmethod bind rule keyword expression. |
| | | */ |
| | | /** The AuthMethod class represents an authmethod bind rule keyword expression. */ |
| | | public class AuthMethod implements KeywordBindRule { |
| | | |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | |
| | | /** |
| | | * Enumeration representing the authentication method. |
| | | */ |
| | | private EnumAuthMethod authMethod; |
| | | |
| | | /** |
| | | * The SASL mechanism if the authentication method is SASL. |
| | | */ |
| | | private String saslMech; |
| | | |
| | | /** |
| | | * Enumeration representing the bind rule operation type. |
| | | */ |
| | | private EnumBindRuleType type; |
| | | /** Enumeration representing the authentication method. */ |
| | | private final EnumAuthMethod authMethod; |
| | | /** The SASL mechanism if the authentication method is SASL. */ |
| | | private final String saslMech; |
| | | /** Enumeration representing the bind rule operation type. */ |
| | | private final EnumBindRuleType type; |
| | | |
| | | /** |
| | | * Create a class representing an authmethod bind rule keyword from the |
| | |
| | | public static KeywordBindRule decode(String expr, EnumBindRuleType type) |
| | | throws AciException { |
| | | String lowerExpr = expr.toLowerCase(); |
| | | if (lowerExpr.equals("none")) |
| | | if ("none".equals(lowerExpr)) |
| | | { |
| | | return new AuthMethod(EnumAuthMethod.AUTHMETHOD_NONE, null, type); |
| | | } |
| | | else if (lowerExpr.equals("simple")) |
| | | else if ("simple".equals(lowerExpr)) |
| | | { |
| | | return new AuthMethod(EnumAuthMethod.AUTHMETHOD_SIMPLE, null, type); |
| | | } |
| | | else if (lowerExpr.equals("ssl")) |
| | | else if ("ssl".equals(lowerExpr)) |
| | | { |
| | | return new AuthMethod(EnumAuthMethod.AUTHMETHOD_SSL, "EXTERNAL", type); |
| | | } |
| | |
| | | return new AuthMethod(EnumAuthMethod.AUTHMETHOD_SASL, saslMech, type); |
| | | } |
| | | |
| | | LocalizableMessage message = WARN_ACI_SYNTAX_INVALID_AUTHMETHOD_EXPRESSION.get(expr); |
| | | throw new AciException(message); |
| | | throw new AciException(WARN_ACI_SYNTAX_INVALID_AUTHMETHOD_EXPRESSION.get(expr)); |
| | | } |
| | | |
| | | /** |
| | |
| | | return matched.getRet(type, false); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String toString() |
| | | { |
| | |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public final void toString(StringBuilder buffer) |
| | | { |
| | | buffer.append(super.toString()); |
| | | } |
| | | |
| | | } |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2013-2015 ForgeRock AS. |
| | | * Portions Copyright 2013-2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | |
| | | import static org.opends.server.authorization.dseecompat.Aci.*; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.regex.Matcher; |
| | | import java.util.regex.Pattern; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | |
| | | /** |
| | | * This class represents a single bind rule of an ACI permission-bind rule pair. |
| | | */ |
| | | /** This class represents a single bind rule of an ACI permission-bind rule pair. */ |
| | | public class BindRule { |
| | | |
| | | /** This hash table holds the keyword bind rule mapping. */ |
| | | private final HashMap<String, KeywordBindRule> keywordRuleMap = new HashMap<>(); |
| | | private final Map<String, KeywordBindRule> keywordRuleMap = new HashMap<>(); |
| | | |
| | | /** True is a boolean "not" was seen. */ |
| | | private boolean negate; |
| | | |
| | | /** Complex bind rules have left and right values. */ |
| | | private BindRule left; |
| | | private BindRule right; |
| | | private final BindRule left; |
| | | private final BindRule right; |
| | | |
| | | /** Enumeration of the boolean type of the complex bind rule ("and" or "or"). */ |
| | | private EnumBooleanTypes booleanType; |
| | | private final EnumBooleanTypes booleanType; |
| | | /** The keyword of a simple bind rule. */ |
| | | private EnumBindRuleKeyword keyword; |
| | | private final EnumBindRuleKeyword keyword; |
| | | |
| | | /** Regular expression group position of a bind rule keyword. */ |
| | | private static final int keywordPos = 1; |
| | |
| | | private BindRule(EnumBindRuleKeyword keyword, KeywordBindRule rule) { |
| | | this.keyword=keyword; |
| | | this.keywordRuleMap.put(keyword.toString(), rule); |
| | | this.booleanType = null; |
| | | this.left = null; |
| | | this.right = null; |
| | | } |
| | | |
| | | |
| | | /* |
| | | * TODO Verify that this handles the NOT boolean properly by |
| | | * creating a unit test. |
| | |
| | | * @param booleanType The boolean type enumeration ("and" or "or"). |
| | | */ |
| | | private BindRule(BindRule left, BindRule right, EnumBooleanTypes booleanType) { |
| | | this.keyword = null; |
| | | this.booleanType = booleanType; |
| | | this.left = left; |
| | | this.right = right; |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Parses a simple bind rule using the regular expression matcher. |
| | | * @param bindruleMatcher A regular expression matcher holding |
| | |
| | | return EnumEvalResult.negateIfNeeded(ret, negate); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String toString() { |
| | | final StringBuilder sb = new StringBuilder(); |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2013-2015 ForgeRock AS. |
| | | * Portions Copyright 2013-2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | |
| | | /** |
| | | * This class implements the dns bind rule keyword. |
| | | */ |
| | | /** This class implements the dns bind rule keyword. */ |
| | | public class DNS implements KeywordBindRule { |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | /** List of patterns to match against. */ |
| | | private List<String> patterns; |
| | | |
| | | private final List<String> patterns; |
| | | /** The enumeration representing the bind rule type of the DNS rule. */ |
| | | private EnumBindRuleType type; |
| | | private final EnumBindRuleType type; |
| | | |
| | | /** 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 + |
| | |
| | | String hn=valueMatcher.group(valuePos); |
| | | String[] hnArray=hn.split("\\.", -1); |
| | | for(int i=1, n=hnArray.length; i < n; i++) { |
| | | if(hnArray[i].equals("*")) { |
| | | if ("*".equals(hnArray[i])) { |
| | | LocalizableMessage message = |
| | | WARN_ACI_SYNTAX_INVALID_DNS_WILDCARD.get(expr); |
| | | throw new AciException(message); |
| | |
| | | String canonicalName = addr.getCanonicalHostName(); |
| | | if (! hn.equalsIgnoreCase(canonicalName)) |
| | | { |
| | | if (hn.equalsIgnoreCase("localhost") |
| | | if ("localhost".equalsIgnoreCase(hn) |
| | | && !dns.contains(canonicalName)) |
| | | { |
| | | dns.add(canonicalName); |
| | |
| | | * @return True if the remote hostname matches the pattern. |
| | | */ |
| | | boolean evalHostName(String[] remoteHostName, String[] pat) { |
| | | boolean wildCard=pat[0].equals("*"); |
| | | boolean wildCard = "*".equals(pat[0]); |
| | | //Check if there is a single wild-card. |
| | | if(pat.length == 1 && wildCard) { |
| | | return true; |
| | |
| | | return true; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String toString() { |
| | | final StringBuilder sb = new StringBuilder(); |
| | |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public final void toString(StringBuilder buffer) { |
| | | buffer.append(super.toString()); |
| | | } |
| | | |
| | | } |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2013-2015 ForgeRock AS. |
| | | * Portions Copyright 2013-2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | |
| | | /** |
| | | * This class implements the dayofweek bind rule keyword. |
| | | */ |
| | | /** This class implements the dayofweek bind rule keyword. */ |
| | | public class DayOfWeek implements KeywordBindRule { |
| | | |
| | | /** List containing the enumeration of the day of the week. */ |
| | | private List<EnumDayOfWeek> days; |
| | | |
| | | private final List<EnumDayOfWeek> days; |
| | | /** Enumeration representing the bind rule operation type. */ |
| | | private EnumBindRuleType type; |
| | | private final EnumBindRuleType type; |
| | | |
| | | /** |
| | | * Create a class representing a dayofweek bind rule keyword. |
| | |
| | | return matched.getRet(type, false); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String toString() |
| | | { |
| | |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public final void toString(StringBuilder buffer) |
| | | { |
| | | buffer.append(super.toString()); |
| | | } |
| | | |
| | | } |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2015 ForgeRock AS. |
| | | * Portions Copyright 2015-2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | | /** |
| | | * This class provides an enumeration of the two access types (allow, deny). |
| | | */ |
| | | public enum EnumAccessType { |
| | | |
| | | /** This class provides an enumeration of the two access types (allow, deny). */ |
| | | enum EnumAccessType { |
| | | /** Allow access type. */ |
| | | ALLOW ("allow"), |
| | | /** Deny access type. */ |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2015 ForgeRock AS. |
| | | * Portions Copyright 2015-2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | /** This class provides an enumeration of the allowed authmethod types. */ |
| | | enum EnumAuthMethod { |
| | | /** The enumeration type when the bind rule has specified authentication of none. */ |
| | | AUTHMETHOD_NONE ("none"), |
| | | |
| | | /** |
| | | * The enumeration type when the bind rule has specified authentication of |
| | | * simple. |
| | | */ |
| | | /** The enumeration type when the bind rule has specified authentication of simple. */ |
| | | AUTHMETHOD_SIMPLE ("simple"), |
| | | |
| | | /** |
| | | * The enumeration type when the bind rule has specified authentication of |
| | | * ssl client auth. |
| | | */ |
| | | /** The enumeration type when the bind rule has specified authentication of ssl client auth. */ |
| | | AUTHMETHOD_SSL ("ssl"), |
| | | |
| | | /** |
| | | * The enumeration type when the bind rule has specified authentication of |
| | | * a sasl mechanism. |
| | | */ |
| | | /** The enumeration type when the bind rule has specified authentication of a sasl mechanism. */ |
| | | AUTHMETHOD_SASL ("sasl"); |
| | | |
| | | /** |
| | |
| | | */ |
| | | EnumAuthMethod (String authmethod){ |
| | | } |
| | | |
| | | } |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2015 ForgeRock AS. |
| | | * Portions Copyright 2015-2016 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | | /** |
| | | * This class provides an enumeration of the allowed bind rule |
| | | * keyword types. |
| | | */ |
| | | public enum EnumBindRuleKeyword { |
| | | |
| | | /** |
| | | * The enumeration type when the bind rule has specified keyword of |
| | | * userdn. |
| | | */ |
| | | /** This class provides an enumeration of the allowed bind rule keyword types. */ |
| | | enum EnumBindRuleKeyword { |
| | | /** The enumeration type when the bind rule has specified keyword of userdn. */ |
| | | USERDN ("userdn"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified keyword of |
| | | * groupdn. |
| | | */ |
| | | /** The enumeration type when the bind rule has specified keyword of groupdn. */ |
| | | GROUPDN ("groupdn"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified keyword of |
| | | * roledn. |
| | | */ |
| | | /** The enumeration type when the bind rule has specified keyword of roledn. */ |
| | | ROLEDN ("roledn"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified keyword of |
| | | * ip. |
| | | */ |
| | | /** The enumeration type when the bind rule has specified keyword of ip. */ |
| | | IP ("ip"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified keyword of |
| | | * dns. |
| | | */ |
| | | /** The enumeration type when the bind rule has specified keyword of dns. */ |
| | | DNS ("dns"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified keyword of |
| | | * dayofweek. |
| | | */ |
| | | /** The enumeration type when the bind rule has specified keyword of dayofweek. */ |
| | | DAYOFWEEK ("dayofweek"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified keyword of |
| | | * timeofday. |
| | | */ |
| | | /** The enumeration type when the bind rule has specified keyword of timeofday. */ |
| | | TIMEOFDAY ("timeofday"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified keyword of |
| | | * userattr. |
| | | */ |
| | | /** The enumeration type when the bind rule has specified keyword of userattr. */ |
| | | USERATTR ("userattr"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified keyword of |
| | | * authmethod. |
| | | */ |
| | | /** The enumeration type when the bind rule has specified keyword of authmethod. */ |
| | | AUTHMETHOD ("authmethod"), |
| | | /** The enumeration type when the bind rule has specified keyword of ssf. */ |
| | | SSF("ssf"); |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2013 ForgeRock AS. |
| | | * Portions Copyright 2013-2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | | /** |
| | | * 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 |
| | | * "=". |
| | | */ |
| | | /** This class provides an enumeration of the allowed bind rule types. */ |
| | | enum EnumBindRuleType { |
| | | /** The enumeration type when the bind rule has specified type of "=". */ |
| | | EQUAL_BINDRULE_TYPE ("="), |
| | | /** |
| | | * The enumeration type when the bind rule has specified type of |
| | | * "!=". |
| | | */ |
| | | /** The enumeration type when the bind rule has specified type of "!=". */ |
| | | NOT_EQUAL_BINDRULE_TYPE ("!="), |
| | | /** |
| | | * The enumeration type when the bind rule has specified type of |
| | | * "<". |
| | | */ |
| | | /** The enumeration type when the bind rule has specified type of "<". */ |
| | | LESS_BINDRULE_TYPE ("<"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified type of |
| | | * "<=". |
| | | */ |
| | | /** The enumeration type when the bind rule has specified type of "<=". */ |
| | | LESS_OR_EQUAL_BINDRULE_TYPE ("<="), |
| | | /** |
| | | * The enumeration type when the bind rule has specified type of |
| | | * >". |
| | | */ |
| | | /** The enumeration type when the bind rule has specified type of >". */ |
| | | GREATER_BINDRULE_TYPE (">"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified type of |
| | | * ">=". |
| | | */ |
| | | /** The enumeration type when the bind rule has specified type of ">=". */ |
| | | GREATER_OR_EQUAL_BINDRULE_TYPE (">="); |
| | | |
| | | /** The bind rule type name. */ |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2015 ForgeRock AS. |
| | | * Portions Copyright 2015-2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | | /** |
| | | * This class provides an enumeration of the allowed bind rule boolean types. |
| | | */ |
| | | public enum EnumBooleanTypes { |
| | | |
| | | /** |
| | | * The enumeration type when the bind rule has specified boolean type of |
| | | * "AND". |
| | | */ |
| | | /** This class provides an enumeration of the allowed bind rule boolean types. */ |
| | | enum EnumBooleanTypes { |
| | | /** The enumeration type when the bind rule has specified boolean type of "AND". */ |
| | | AND_BOOLEAN_TYPE ("and"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified boolean type of |
| | | * "OR". |
| | | */ |
| | | /** The enumeration type when the bind rule has specified boolean type of "OR". */ |
| | | OR_BOOLEAN_TYPE ("or"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified boolean type of |
| | | * "NOT". |
| | | */ |
| | | /** The enumeration type when the bind rule has specified boolean type of "NOT". */ |
| | | NOT_BOOLEAN_TYPE ("not"); |
| | | |
| | | /** The bind rule boolean type name. */ |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2015 ForgeRock AS. |
| | | * Portions Copyright 2015-2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | | import java.util.Calendar; |
| | | |
| | | /** |
| | | * 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". |
| | | */ |
| | | /** This class provides an enumeration of the allowed dayofweek types. */ |
| | | enum EnumDayOfWeek { |
| | | /** The enumeration type when the bind rule has specified dayofweek type of "mon". */ |
| | | DAY_MONDAY ("mon"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified dayofweek type of |
| | | * "tue" . |
| | | */ |
| | | /** The enumeration type when the bind rule has specified dayofweek type of "tue" . */ |
| | | DAY_TUESDAY ("tue"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified dayofweek type of |
| | | * "wed". |
| | | */ |
| | | /** The enumeration type when the bind rule has specified dayofweek type of "wed". */ |
| | | DAY_WEDNESDAY ("wed"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified dayofweek type of |
| | | * "thu". |
| | | */ |
| | | /** The enumeration type when the bind rule has specified dayofweek type of "thu". */ |
| | | DAY_THURSDAY ("thu"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified dayofweek type of |
| | | * "fri". |
| | | */ |
| | | /** The enumeration type when the bind rule has specified dayofweek type of "fri". */ |
| | | DAY_FRIDAY ("fri"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified dayofweek type of |
| | | * "sat". |
| | | */ |
| | | /** The enumeration type when the bind rule has specified dayofweek type of "sat". */ |
| | | DAY_SATURDAY ("sat"), |
| | | /** |
| | | * The enumeration type when the bind rule has specified dayofweek type of |
| | | * "sun". |
| | | */ |
| | | /** The enumeration type when the bind rule has specified dayofweek type of "sun". */ |
| | | DAY_SUNDAY ("sun"); |
| | | |
| | | /** The bind rule dayofweek type name. */ |
| | | private String day = null; |
| | | private final String day; |
| | | |
| | | /** |
| | | * Creates a new enumeration type for the specified bind rule dayofweek |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2015 ForgeRock AS. |
| | | * Portions Copyright 2015-2016 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | | /** |
| | | * This class provides an enumeration of the valid ACI target keywords. |
| | | */ |
| | | public enum EnumTargetKeyword { |
| | | |
| | | /** |
| | | * This enumeration is returned when the target keyword is |
| | | * "target". |
| | | */ |
| | | /** This class provides an enumeration of the valid ACI target keywords. */ |
| | | enum EnumTargetKeyword { |
| | | /** This enumeration is returned when the target keyword is "target". */ |
| | | KEYWORD_TARGET ("target"), |
| | | /** |
| | | * This enumeration is returned when the target keyword is |
| | | * "targetattr". |
| | | */ |
| | | /** This enumeration is returned when the target keyword is "targetattr". */ |
| | | KEYWORD_TARGETATTR ("targetattr"), |
| | | /** |
| | | * This enumeration is returned when the target keyword is |
| | | * "targetscope". |
| | | */ |
| | | /** This enumeration is returned when the target keyword is "targetscope". */ |
| | | KEYWORD_TARGETSCOPE ("targetscope"), |
| | | /** |
| | | * This enumeration is returned when the target keyword is |
| | | * "targetfilter". |
| | | */ |
| | | /** This enumeration is returned when the target keyword is "targetfilter". */ |
| | | KEYWORD_TARGETFILTER ("targetfilter"), |
| | | /** |
| | | * This enumeration is returned when the target keyword is |
| | | * "targattrfilters". |
| | | */ |
| | | /** This enumeration is returned when the target keyword is "targattrfilters". */ |
| | | KEYWORD_TARGATTRFILTERS ("targattrfilters"), |
| | | /** |
| | | * This enumeration is returned when the target keyword is |
| | | * "targetcontrol". |
| | | */ |
| | | /** This enumeration is returned when the target keyword is "targetcontrol". */ |
| | | KEYWORD_TARGETCONTROL ("targetcontrol"), |
| | | /** |
| | | * This enumeration is returned when the target keyword is |
| | | * "extop". |
| | | */ |
| | | /** This enumeration is returned when the target keyword is "extop". */ |
| | | KEYWORD_EXTOP ("extop"); |
| | | |
| | | /** The target keyword name. */ |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | | |
| | | /** |
| | | * Enumeration that represents the type an "userdn" keyword DN can have. |
| | | * The issues is the syntax allows invalid URLs such as "ldap:///anyone" |
| | |
| | | * ignored in the UserDN.evaluate() method for types such as: ALL, PARENT, |
| | | * SELF and ANYONE. |
| | | */ |
| | | public enum EnumUserDNType { |
| | | |
| | | enum EnumUserDNType { |
| | | /** |
| | | * The enumeration type when the "userdn" URL contains only a DN (no |
| | | * filter or scope) and that DN has no pattern. |
| | |
| | | * filter or scope) and that DN has a substring pattern. |
| | | */ |
| | | DNPATTERN(1), |
| | | /** |
| | | * The enumeration type when the "userdn" URL has the value of: |
| | | * "ldap:///all". |
| | | */ |
| | | /** The enumeration type when the "userdn" URL has the value of: "ldap:///all". */ |
| | | ALL(2), |
| | | /** |
| | | * The enumeration type when the "userdn" URL has the value of: |
| | | * "ldap:///parent". |
| | | */ |
| | | /** The enumeration type when the "userdn" URL has the value of: "ldap:///parent". */ |
| | | PARENT(3), |
| | | /** |
| | | * The enumeration type when the "userdn" URL has the value of: |
| | | * "ldap:///self". |
| | | */ |
| | | /** The enumeration type when the "userdn" URL has the value of: "ldap:///self". */ |
| | | SELF(4), |
| | | /** |
| | | * The enumeration type when the "userdn" URL has the value of: |
| | | * "ldap:///anyone". |
| | | */ |
| | | /** The enumeration type when the "userdn" URL has the value of: "ldap:///anyone". */ |
| | | ANYONE(5), |
| | | /** |
| | | * The enumeration type when the "userdn" URL is contains a DN (suffix), |
| | | * a scope and a filter. |
| | | */ |
| | | /** The enumeration type when the "userdn" URL is contains a DN (suffix), a scope and a filter. */ |
| | | URL(6); |
| | | |
| | | /** |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2013-2015 ForgeRock AS. |
| | | * Portions Copyright 2013-2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | | import static org.opends.messages.AccessControlMessages.*; |
| | | |
| | | import java.util.HashSet; |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * This class represents an ACI's extop keyword rule. |
| | | */ |
| | | /** This class represents an ACI's extop keyword rule. */ |
| | | public class ExtOp { |
| | | |
| | | /** |
| | | * HashSet of OID strings parsed from the decode. |
| | | */ |
| | | private Set<String> extOpOIDs = new HashSet<>(); |
| | | |
| | | /** |
| | | * Enumeration representing the extop operator. |
| | | */ |
| | | private EnumTargetOperator op = EnumTargetOperator.EQUALITY; |
| | | /** Set of OID strings parsed from the decode. */ |
| | | private final Set<String> extOpOIDs; |
| | | /** Enumeration representing the extop operator. */ |
| | | private final EnumTargetOperator op; |
| | | |
| | | /** |
| | | * Creates a class that can be used to evaluate a extop rule. |
| | |
| | | { |
| | | return false; |
| | | } |
| | | boolean ret = false; |
| | | for(String oid : extOpOIDs) |
| | | boolean ret = isApplicable(matchCtx.getExtOpOID()); |
| | | if (EnumTargetOperator.NOT_EQUALITY.equals(op)) |
| | | { |
| | | if(oid.equals("*") || matchCtx.getExtOpOID().equals(oid)) { |
| | | ret=true; |
| | | break; |
| | | } |
| | | } |
| | | if(op.equals(EnumTargetOperator.NOT_EQUALITY)) |
| | | { |
| | | ret = !ret; |
| | | return !ret; |
| | | } |
| | | return ret; |
| | | } |
| | | |
| | | private boolean isApplicable(String matchOID) |
| | | { |
| | | for(String oid : extOpOIDs) |
| | | { |
| | | if ("*".equals(oid) || matchOID.equals(oid)) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | } |
| | |
| | | import org.forgerock.i18n.LocalizedIllegalArgumentException; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.forgerock.opendj.ldap.schema.AttributeType; |
| | | import org.opends.server.api.Group; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.core.GroupManager; |
| | | import org.forgerock.opendj.ldap.schema.AttributeType; |
| | | import org.opends.server.types.*; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.LDAPURL; |
| | | |
| | | /** |
| | | * This class implements the groupdn bind rule keyword. |
| | | */ |
| | | public class GroupDN implements KeywordBindRule { |
| | | /** This class implements the groupdn bind rule keyword. */ |
| | | class GroupDN implements KeywordBindRule { |
| | | |
| | | /** List of group DNs. */ |
| | | private List<DN> groupDNs; |
| | | |
| | | private final List<DN> groupDNs; |
| | | /** Enumeration representing the groupdn operator type. */ |
| | | private EnumBindRuleType type; |
| | | private final EnumBindRuleType type; |
| | | |
| | | /** |
| | | * Regular expression matching one or more LDAP URLs separated by |
| | | * "||". |
| | | */ |
| | | public static final String LDAP_URLS = LDAP_URL + |
| | | /** Regular expression matching one or more LDAP URLs separated by "||". */ |
| | | private static final String LDAP_URLS = LDAP_URL + |
| | | ZERO_OR_MORE_WHITESPACE + "(" + LOGICAL_OR + |
| | | ZERO_OR_MORE_WHITESPACE + LDAP_URL + ")*"; |
| | | |
| | |
| | | * then the groupDN can be anywhere in the DIT. |
| | | * @return Enumeration evaluation result. |
| | | */ |
| | | public static EnumEvalResult evaluate (Entry e, AciEvalContext evalCtx, |
| | | public static boolean evaluate (Entry e, AciEvalContext evalCtx, |
| | | AttributeType attributeType, |
| | | DN suffixDN) { |
| | | EnumEvalResult matched= EnumEvalResult.FALSE; |
| | | List<Attribute> attrs = e.getAttribute(attributeType); |
| | | for(ByteString v : attrs.get(0)) { |
| | | try { |
| | |
| | | } |
| | | Group<?> group = getGroupManager().getGroupInstance(groupDN); |
| | | if(group != null && evalCtx.isMemberOf(group)) { |
| | | matched=EnumEvalResult.TRUE; |
| | | break; |
| | | return true; |
| | | } |
| | | } catch (LocalizedIllegalArgumentException ignored) { |
| | | break; |
| | | } |
| | | } |
| | | return matched; |
| | | return false; |
| | | } |
| | | |
| | | private static GroupManager getGroupManager() { |
| | | return DirectoryServer.getGroupManager(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String toString() { |
| | | final StringBuilder sb = new StringBuilder(); |
| | |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public final void toString(StringBuilder buffer) { |
| | | buffer.append(super.toString()); |
| | | } |
| | | |
| | | } |
| | |
| | | Pattern.compile("((?i)[\\.{1}[a-f]\\d:\\+{1}\\*/{1}\\t\\[{1}\\]{1}]+(?-i))"); |
| | | |
| | | /** List of the pattern classes, one for each address decoded from the bind rule. */ |
| | | private List<PatternIP> patternIPList; |
| | | private final List<PatternIP> patternIPList; |
| | | /** The type of the bind rule (!= or =). */ |
| | | private EnumBindRuleType type; |
| | | private final EnumBindRuleType type; |
| | | |
| | | /** |
| | | * Create a class representing the IP bind rule expressions for this ACI. |
| | |
| | | * Multiple-Whole-RDN: A double wildcard may be used to match one or more |
| | | * RDN components: |
| | | * uid=bjensen,**,dc=example,dc=com |
| | | * |
| | | */ |
| | | public class PatternDN |
| | | { |
| | |
| | | private List<PatternRDN[]> subAnyElements; |
| | | private PatternRDN[] subFinal; |
| | | |
| | | |
| | | /** |
| | | * When there is no initial sequence, this is used to distinguish between |
| | | * the case where we have a suffix pattern (zero or more RDN components |
| | |
| | | */ |
| | | private boolean isSuffix; |
| | | |
| | | |
| | | /** |
| | | * Create a DN pattern that does not include any Multiple-Whole-RDN wildcards. |
| | | * @param equality The sequence of RDN patterns making up the DN pattern. |
| | |
| | | this.equality = equality; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Create a DN pattern that includes Multiple-Whole-RDN wildcards. |
| | | * @param subInitial The sequence of RDN patterns appearing at the |
| | |
| | | this.subFinal = subFinal; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Determine whether a given DN matches this pattern. |
| | | * @param dn The DN to be matched. |
| | |
| | | } |
| | | pos++; |
| | | } |
| | | else |
| | | { |
| | | if (!isSuffix) |
| | | else if (!isSuffix) |
| | | { |
| | | pos++; |
| | | } |
| | | } |
| | | |
| | | |
| | | if (subAnyElements != null && ! subAnyElements.isEmpty()) |
| | | { |
| | |
| | | boolean match = false; |
| | | for (; pos < end; pos++) |
| | | { |
| | | if (element[0].matchesRDN(dn.rdn(pos))) |
| | | { |
| | | if (subMatch(dn, pos, element, anyLength)) |
| | | if (element[0].matchesRDN(dn.rdn(pos)) |
| | | && subMatch(dn, pos, element, anyLength)) |
| | | { |
| | | match = true; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!match) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | if (subFinal != null) |
| | | { |
| | | int finalLength = subFinal.length; |
| | |
| | | return patternDN; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Create a new DN pattern matcher from a pattern string. |
| | | * @param dnString The DN pattern string. |
| | |
| | | return new PatternDN(); |
| | | } |
| | | |
| | | |
| | | // Iterate through the DN string. The first thing to do is to get |
| | | // rid of any leading spaces. |
| | | int pos = 0; |
| | |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // If we are at the end of the DN string, then that must mean |
| | | // that the attribute value was empty. This will probably never |
| | | // happen in a real-world environment, but technically isn't |
| | |
| | | break; |
| | | } |
| | | |
| | | |
| | | // Parse the value for this RDN component. |
| | | List<ByteString> parsedValue = new ArrayList<>(); |
| | | pos = parseValuePattern(dnString, pos, parsedValue); |
| | | |
| | | |
| | | // Create the new RDN with the provided information. |
| | | PatternRDN rdn = new PatternRDN(name, parsedValue, dnString); |
| | | |
| | | |
| | | // Skip over any spaces that might be after the attribute value. |
| | | while (pos < length && ((c = dnString.charAt(pos)) == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // Most likely, we will be at either the end of the RDN |
| | | // component or the end of the DN. If so, then handle that appropriately. |
| | | if (pos >= length) |
| | |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, message); |
| | | } |
| | | |
| | | |
| | | // If we have gotten here, then this must be a multi-valued RDN. |
| | | // In that case, parse the remaining attribute/value pairs and |
| | | // add them to the RDN that we've already created. |
| | |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // Parse the attribute name from the DN string. |
| | | attributeName = new StringBuilder(); |
| | | pos = parseAttributePattern(dnString, pos, attributeName); |
| | | |
| | | |
| | | // Make sure that we're not at the end of the DN string |
| | | // because that would be invalid. |
| | | if (pos >= length) |
| | |
| | | ERR_ATTR_SYNTAX_DN_END_WITH_ATTR_NAME.get(dnString, attributeName)); |
| | | } |
| | | |
| | | |
| | | name = attributeName.toString(); |
| | | |
| | | // Skip over any spaces between the attribute name and its |
| | |
| | | c = dnString.charAt(pos); |
| | | } |
| | | |
| | | |
| | | // The next character must be an equal sign. If it is not, |
| | | // then that's an error. |
| | | if (c == '=') |
| | |
| | | throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, message); |
| | | } |
| | | |
| | | |
| | | // Skip over any spaces after the equal sign. |
| | | while (pos < length && ((c = dnString.charAt(pos)) == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // If we are at the end of the DN string, then that must mean |
| | | // that the attribute value was empty. This will probably |
| | | // never happen in a real-world environment, but technically |
| | |
| | | break; |
| | | } |
| | | |
| | | |
| | | // Parse the value for this RDN component. |
| | | parsedValue = new ArrayList<>(); |
| | | pos = parseValuePattern(dnString, pos, parsedValue); |
| | | |
| | | |
| | | // Create the new RDN with the provided information. |
| | | rdn.addValue(name, parsedValue, dnString); |
| | | |
| | | |
| | | // Skip over any spaces that might be after the attribute value. |
| | | while (pos < length && ((c = dnString.charAt(pos)) == ' ')) |
| | | { |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // Most likely, we will be at either the end of the RDN |
| | | // component or the end of the DN. If so, then handle that appropriately. |
| | | if (pos >= length) |
| | |
| | | return new PatternDN(subInitial, subAnyElements, subFinal); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Parses an attribute name pattern from the provided DN pattern string |
| | | * starting at the specified location. |
| | |
| | | * valid attribute name pattern from the |
| | | * provided DN pattern string. |
| | | */ |
| | | static int parseAttributePattern(String dnString, int pos, |
| | | private static int parseAttributePattern(String dnString, int pos, |
| | | StringBuilder attributeName) |
| | | throws DirectoryException |
| | | { |
| | | int length = dnString.length(); |
| | | |
| | | |
| | | // Skip over any leading spaces. |
| | | if (pos < length) |
| | | { |
| | |
| | | endOfName = true; |
| | | break; |
| | | |
| | | |
| | | case '!': |
| | | case '"': |
| | | case '#': |
| | |
| | | // character immediately following it. |
| | | throw illegalCharacter(dnString, pos, c); |
| | | |
| | | |
| | | case '*': |
| | | // Wildcard character. |
| | | attributeName.append(c); |
| | |
| | | case '+': |
| | | throw illegalCharacter(dnString, pos, c); |
| | | |
| | | |
| | | case ',': |
| | | // This should denote the end of the attribute name. |
| | | endOfName = true; |
| | |
| | | attributeName.append(c); |
| | | break; |
| | | |
| | | |
| | | case '.': |
| | | // The period could be allowed if the attribute name is |
| | | // actually expressed as an OID. We'll accept it for now, |
| | |
| | | checkForOID = true; |
| | | break; |
| | | |
| | | |
| | | case '/': |
| | | throw illegalCharacter(dnString, pos, c); |
| | | |
| | | |
| | | case '0': |
| | | case '1': |
| | | case '2': |
| | |
| | | attributeName.append(c); |
| | | break; |
| | | |
| | | |
| | | case ':': |
| | | throw illegalCharacter(dnString, pos, c); |
| | | |
| | | |
| | | case ';': // NOTE: attribute options are not allowed in a DN. |
| | | // This should denote the end of the attribute name. |
| | | endOfName = true; |
| | |
| | | case '<': |
| | | throw illegalCharacter(dnString, pos, c); |
| | | |
| | | |
| | | case '=': |
| | | // This should denote the end of the attribute name. |
| | | endOfName = true; |
| | | break; |
| | | |
| | | |
| | | case '>': |
| | | case '?': |
| | | case '@': |
| | | throw illegalCharacter(dnString, pos, c); |
| | | |
| | | |
| | | case 'A': |
| | | case 'B': |
| | | case 'C': |
| | |
| | | attributeName.append(c); |
| | | break; |
| | | |
| | | |
| | | case '[': |
| | | case '\\': |
| | | case ']': |
| | | case '^': |
| | | throw illegalCharacter(dnString, pos, c); |
| | | |
| | | |
| | | case '_': |
| | | attributeName.append(c); |
| | | break; |
| | | |
| | | |
| | | case '`': |
| | | throw illegalCharacter(dnString, pos, c); |
| | | |
| | | |
| | | case 'a': |
| | | case 'b': |
| | | case 'c': |
| | |
| | | attributeName.append(c); |
| | | break; |
| | | |
| | | |
| | | default: |
| | | // This is not allowed in an attribute name or any character |
| | | // immediately following it. |
| | | throw illegalCharacter(dnString, pos, c); |
| | | } |
| | | |
| | | |
| | | if (endOfName) |
| | | { |
| | | break; |
| | |
| | | pos++; |
| | | } |
| | | |
| | | |
| | | // We should now have the full attribute name. However, we may |
| | | // still need to perform some validation, particularly if the |
| | | // name contains a period or starts with a digit. It must also |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | if (validOID && attributeName.charAt(nameLength-1) == '.') |
| | | { |
| | | validOID = false; |
| | |
| | | ERR_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR.get(dnString, c, pos)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Parses the attribute value pattern from the provided DN pattern |
| | | * string starting at the specified location. The value is split up |
| | |
| | | return pos; |
| | | } |
| | | |
| | | |
| | | // Look at the first character. If it is an octothorpe (#), then |
| | | // that means that the value should be a hex string. |
| | | char c = dnString.charAt(pos++); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // The rest of the value must be a multiple of two hex |
| | | // characters. The end of the value may be designated by the |
| | | // end of the DN, a comma or semicolon, or a space. |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // At this point, we should have a valid hex string. Convert it |
| | | // to a byte array and set that as the value of the provided |
| | | // octet string. |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // If the first character is a quotation mark, then the value |
| | | // should continue until the corresponding closing quotation mark. |
| | | else if (c == '"') |
| | |
| | | return pos; |
| | | } |
| | | |
| | | |
| | | // Otherwise, use general parsing to find the end of the value. |
| | | else |
| | | { |
| | |
| | | valueString.append(c); |
| | | } |
| | | |
| | | |
| | | // Keep reading until we find an unescaped comma or plus sign or the end of the DN. |
| | | while (true) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Strip off any unescaped spaces that may be at the end of the |
| | | // value. |
| | | if (pos > 2 && dnString.charAt(pos-1) == ' ' && |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | attributeValues.add(ByteString.valueOfUtf8(valueString)); |
| | | return pos; |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Decodes a hexadecimal string from the provided |
| | | * <CODE>hexChars</CODE> buffer, converts it to a byte array, and |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014-2015 ForgeRock AS. |
| | | * Portions Copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | |
| | | |
| | | package org.opends.server.authorization.dseecompat; |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | |
| | | import static org.opends.messages.AccessControlMessages.*; |
| | | import java.util.BitSet; |
| | | import java.util.HashMap; |
| | | |
| | | import java.net.Inet6Address; |
| | | import java.net.InetAddress; |
| | | import java.net.UnknownHostException; |
| | | import java.net.Inet6Address; |
| | | import java.util.BitSet; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | |
| | | /** |
| | | * A class representing a single IP address parsed from a IP bind rule |
| | |
| | | * using the information parsed from the IP bind rule expression. |
| | | */ |
| | | public class PatternIP { |
| | | |
| | | /** |
| | | * Enumeration that represents if the pattern is IPv5 or |
| | | * IPv4. |
| | | */ |
| | | enum IPType { |
| | | /** Enumeration that represents if the pattern is IPv5 or IPv4. */ |
| | | private enum IPType { |
| | | IPv4, IPv6 |
| | | } |
| | | |
| | | /** The IP address type (v6 or v4). */ |
| | | private IPType ipType; |
| | | private final IPType ipType; |
| | | |
| | | /** IPv4 sizes of addresses and prefixes. */ |
| | | private static int IN4ADDRSZ = 4; |
| | | private static int IPV4MAXPREFIX = 32; |
| | | private static final int IN4ADDRSZ = 4; |
| | | private static final int IPV4MAXPREFIX = 32; |
| | | |
| | | /** IPv6 sizes of addresses and prefixes. */ |
| | | private static int IN6ADDRSZ = 16; |
| | | private static int IPV6MAXPREFIX = 128; |
| | | private static final int IN6ADDRSZ = 16; |
| | | private static final int IPV6MAXPREFIX = 128; |
| | | |
| | | /** |
| | | Byte arrays used to match the remote IP address. The ruleAddrByte array |
| | |
| | | rulePrefixBytes array contains the bytes of the cidr prefix or netmask |
| | | representation. |
| | | */ |
| | | private byte[] ruleAddrBytes, rulePrefixBytes; |
| | | private final byte[] ruleAddrBytes, rulePrefixBytes; |
| | | |
| | | /** |
| | | Bit set that holds the wild-card information of processed IPv4 addresses. |
| | | */ |
| | | private BitSet wildCardBitSet; |
| | | /** Bit set that holds the wild-card information of processed IPv4 addresses. */ |
| | | private final BitSet wildCardBitSet; |
| | | |
| | | /** Hash map of valid netmask strings. Used in parsing netmask values. */ |
| | | private static HashMap<String,String> validNetMasks = new HashMap<>(); |
| | | |
| | | /** Map of valid netmask strings. Used in parsing netmask values. */ |
| | | private static final Map<String, String> validNetMasks = new HashMap<>(); |
| | | /** Initialize valid netmask hash map. */ |
| | | static { |
| | | initNetMask( |
| | |
| | | private static int |
| | | getPrefixValue(IPType ipType, int numParts, String expr, String prefixStr) |
| | | throws AciException { |
| | | |
| | | int prefix = IPV4MAXPREFIX; |
| | | int maxPrefix= IPV4MAXPREFIX; |
| | | if(ipType == IPType.IPv6) { |
| | |
| | | } |
| | | //Must be between 0 to maxprefix. |
| | | if(prefix < 0 || prefix > maxPrefix) { |
| | | LocalizableMessage message = |
| | | WARN_ACI_SYNTAX_INVALID_PREFIX_VALUE.get(expr); |
| | | throw new AciException(message); |
| | | } |
| | | } catch(NumberFormatException nfex) { |
| | | LocalizableMessage msg = WARN_ACI_SYNTAX_PREFIX_NOT_NUMERIC.get(expr); |
| | | throw new AciException(msg); |
| | | throw new AciException(WARN_ACI_SYNTAX_INVALID_PREFIX_VALUE.get(expr)); |
| | | } |
| | | return prefix; |
| | | } catch(NumberFormatException nfex) { |
| | | throw new AciException(WARN_ACI_SYNTAX_PREFIX_NOT_NUMERIC.get(expr)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | /** Indicate whether the RDN contains a wildcard in any of its attribute types. */ |
| | | private boolean hasTypeWildcard; |
| | | private final boolean hasTypeWildcard; |
| | | /** The set of attribute type patterns. */ |
| | | private String[] typePatterns; |
| | | /** |
| | |
| | | * a list of one element A. The value "*A*" is represented as a list |
| | | * of three elements "", A and "". |
| | | */ |
| | | private List<List<ByteString>> valuePatterns; |
| | | private final List<List<ByteString>> valuePatterns; |
| | | |
| | | /** |
| | | * Create a new RDN pattern composed of a single attribute-value pair. |
| | |
| | | } |
| | | hasTypeWildcard = true; |
| | | } |
| | | else |
| | | { |
| | | hasTypeWildcard = false; |
| | | } |
| | | |
| | | typePatterns = new String[] { type }; |
| | | valuePatterns = newArrayList(valuePattern); |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2013-2015 ForgeRock AS. |
| | | * Portions Copyright 2013-2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | | /** |
| | | * A class representing a permission-bind rule pair. There can be multiple |
| | | * of these in an ACI. |
| | | */ |
| | | /** A class representing a permission-bind rule pair. There can be multiple of these in an ACI. */ |
| | | public class PermBindRulePair { |
| | | |
| | | /** The Bind Rule part. */ |
| | | private BindRule bindRule; |
| | | |
| | | private final BindRule bindRule; |
| | | /** The permission part. */ |
| | | private Permission perm; |
| | | private final Permission perm; |
| | | |
| | | /** |
| | | * This constructor calls the permission and bind rule decodes |
| | |
| | | return perm.hasRights(right); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String toString() { |
| | | final StringBuilder sb = new StringBuilder(); |
| | |
| | | * The buffer into which a string representation of this object |
| | | * should be appended. |
| | | */ |
| | | public final void toString(StringBuilder buffer) { |
| | | final void toString(StringBuilder buffer) { |
| | | if (this.perm != null) { |
| | | this.perm.toString(buffer); |
| | | } |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2013-2015 ForgeRock AS. |
| | | * Portions Copyright 2013-2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | |
| | | */ |
| | | public class Permission { |
| | | |
| | | /** |
| | | * The access type (allow,deny) corresponding to the ACI permission value. |
| | | */ |
| | | private EnumAccessType accessType; |
| | | |
| | | /** |
| | | * The rights (search, add, delete, ...) corresponding to the ACI rights |
| | | * value. |
| | | */ |
| | | private int rights; |
| | | |
| | | /** |
| | | * Regular expression token representing the separator. |
| | | */ |
| | | /** Regular expression token representing the separator. */ |
| | | private static final String separatorToken = ","; |
| | | |
| | | /** |
| | | * Regular expression used to match the ACI rights string. |
| | | */ |
| | | /** 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 + ")*"; |
| | | |
| | | /** The access type (allow,deny) corresponding to the ACI permission value. */ |
| | | private final EnumAccessType accessType; |
| | | /** The rights (search, add, delete, ...) corresponding to the ACI rights value. */ |
| | | private int rights; |
| | | |
| | | /** |
| | | * Constructor creating a class representing a permission part of an bind |
| | | * rule. |
| | |
| | | return (this.rights & rights) != 0; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String toString() { |
| | | final StringBuilder sb = new StringBuilder(); |
| | |
| | | Set<EnumRight> enumRights = EnumRight.getEnumRight(rights); |
| | | if (enumRights != null) { |
| | | buffer.append("("); |
| | | for (Iterator<EnumRight> iter = enumRights.iterator(); iter |
| | | .hasNext();) { |
| | | for (Iterator<EnumRight> iter = enumRights.iterator(); iter.hasNext();) { |
| | | buffer.append(iter.next().getRight()); |
| | | if (iter.hasNext()) { |
| | | buffer.append(","); |
| | |
| | | |
| | | /** The class represents the ssf keyword in a bind rule.SSF stands for security strength factor. */ |
| | | public class SSF implements KeywordBindRule { |
| | | /** Enumeration representing the bind rule operation type. */ |
| | | private EnumBindRuleType type; |
| | | |
| | | private static final int MAX_KEY_BITS=1024; |
| | | private int ssf; |
| | | |
| | | /** Enumeration representing the bind rule operation type. */ |
| | | private final EnumBindRuleType type; |
| | | private final int ssf; |
| | | |
| | | private SSF(int ssf, EnumBindRuleType type) { |
| | | this.ssf = ssf; |
| | |
| | | throw new AciException(message); |
| | | } |
| | | if (valueAsInt <= 0 || valueAsInt > MAX_KEY_BITS) { |
| | | LocalizableMessage message = WARN_ACI_SYNTAX_INVALID_SSF_RANGE.get(expr); |
| | | throw new AciException(message); |
| | | throw new AciException(WARN_ACI_SYNTAX_INVALID_SSF_RANGE.get(expr)); |
| | | } |
| | | return new SSF(valueAsInt, type); |
| | | } |
| | |
| | | */ |
| | | @Override |
| | | public EnumEvalResult evaluate(AciEvalContext evalCtx) { |
| | | int currentSSF = evalCtx.getCurrentSSF(); |
| | | EnumEvalResult matched = getMatched(currentSSF); |
| | | EnumEvalResult matched = getMatched(evalCtx.getCurrentSSF()); |
| | | return matched.getRet(type, false); |
| | | } |
| | | |
| | | private EnumEvalResult getMatched(int currentSSF) { |
| | | return getMatched0(currentSSF) ? EnumEvalResult.TRUE : EnumEvalResult.FALSE; |
| | | } |
| | | |
| | | private boolean getMatched0(int currentSSF) |
| | | { |
| | | switch (type) { |
| | | case EQUAL_BINDRULE_TYPE: |
| | | case NOT_EQUAL_BINDRULE_TYPE: |
| | | if (currentSSF == ssf) { |
| | | return EnumEvalResult.TRUE; |
| | | } |
| | | break; |
| | | |
| | | return currentSSF == ssf; |
| | | case LESS_OR_EQUAL_BINDRULE_TYPE: |
| | | if (currentSSF <= ssf) { |
| | | return EnumEvalResult.TRUE; |
| | | } |
| | | break; |
| | | |
| | | return currentSSF <= ssf; |
| | | case LESS_BINDRULE_TYPE: |
| | | if (currentSSF < ssf) { |
| | | return EnumEvalResult.TRUE; |
| | | } |
| | | break; |
| | | |
| | | return currentSSF < ssf; |
| | | case GREATER_OR_EQUAL_BINDRULE_TYPE: |
| | | if (currentSSF >= ssf) { |
| | | return EnumEvalResult.TRUE; |
| | | } |
| | | break; |
| | | |
| | | return currentSSF >= ssf; |
| | | case GREATER_BINDRULE_TYPE: |
| | | if (currentSSF > ssf) { |
| | | return EnumEvalResult.TRUE; |
| | | return currentSSF > ssf; |
| | | default: |
| | | return false; |
| | | } |
| | | } |
| | | return EnumEvalResult.FALSE; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() |
| | |
| | | import java.util.regex.Pattern; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.forgerock.opendj.ldap.schema.AttributeType; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.SearchFilter; |
| | | |
| | |
| | | * |
| | | * "Op=attr1:F1 [(&& attr2:F2)*] |
| | | */ |
| | | public class TargAttrFilterList { |
| | | |
| | | /** |
| | | * The mask corresponding to the operation of this list (add or del). |
| | | */ |
| | | private int mask; |
| | | |
| | | class TargAttrFilterList |
| | | { |
| | | /** The mask corresponding to the operation of this list (add or del). */ |
| | | private final int mask; |
| | | /** |
| | | * 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; |
| | | private final 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 group count. */ |
| | | private static final int expectedGroupCount = 2; |
| | | /** Regular expression attribute group position. */ |
| | | private static final int attributePos = 1; |
| | | /** Regular expression filter group position. */ |
| | | private static final int filterPos = 2; |
| | | |
| | | /** |
| | | * Regular expression used to match a filter list including the strange "and" |
| | |
| | | private static final String filterListSeperator = |
| | | ZERO_OR_MORE_WHITESPACE + "&&" + ZERO_OR_MORE_WHITESPACE; |
| | | |
| | | /** |
| | | * Regular expression used to match an attribute filter pair. |
| | | */ |
| | | /** 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})"; |
| | |
| | | * @param attrFilterList The list map containing the attribute type |
| | | * filter mappings. |
| | | */ |
| | | public TargAttrFilterList(int mask, |
| | | private TargAttrFilterList(int mask, |
| | | LinkedHashMap<AttributeType, SearchFilter> attrFilterList) { |
| | | this.mask=mask; |
| | | this.attrFilterList=attrFilterList; |
| | |
| | | * filter list. |
| | | * @throws AciException If the expression string contains errors. |
| | | */ |
| | | public static TargAttrFilterList decode(int mask, String expression) |
| | | throws AciException { |
| | | static TargAttrFilterList decode(int mask, String expression) throws AciException { |
| | | LinkedHashMap<AttributeType, SearchFilter> attrFilterList = new LinkedHashMap<>(); |
| | | String[] subExpressions=expression.split(filterListSeperator, -1); |
| | | //Iterate over each sub-expression, parse and add them to the list |
| | |
| | | * @param mask The mask to check for. |
| | | * @return True if the mask matches the specified value. |
| | | */ |
| | | public boolean hasMask(int mask) { |
| | | 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() { |
| | | public LinkedHashMap<AttributeType, SearchFilter> getAttributeTypeFilterList() { |
| | | return attrFilterList; |
| | | } |
| | | } |
| | |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.SearchFilter; |
| | | |
| | | /** |
| | | * The TargAttrFilters class represents a targattrfilters rule of an ACI. |
| | | */ |
| | | /** The TargAttrFilters class represents a targattrfilters rule of an ACI. */ |
| | | public class TargAttrFilters { |
| | | |
| | | /** |
| | | * A valid targattrfilters rule may have two TargFilterlist parts -- the |
| | | * first one is required. |
| | | */ |
| | | /** A valid targattrfilters rule may have two TargFilterlist parts -- the first one is required. */ |
| | | private final TargAttrFilterList firstFilterList; |
| | | private TargAttrFilterList secondFilterList; |
| | | private final TargAttrFilterList secondFilterList; |
| | | |
| | | /** |
| | | * Regular expression group position for the first operation value. |
| | | */ |
| | | /** 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. |
| | | */ |
| | | /** 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). |
| | | */ |
| | | /** 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 check for valid expression separator. |
| | | */ |
| | | /** Regular expression used to check for valid expression separator. */ |
| | | private static final Pattern secondOpSeparator = Pattern.compile("\\)" + ZERO_OR_MORE_WHITESPACE + ","); |
| | | |
| | | /** |
| | |
| | | * Regular expression used to group the remainder of a partially parsed |
| | | * rule. Any character one or more times. |
| | | */ |
| | | private final static String restOfExpression = "(.+)"; |
| | | private static final String restOfExpression = "(.+)"; |
| | | |
| | | /** |
| | | * Regular expression used to match the first operation keyword and the |
| | | * rest of the expression. |
| | | */ |
| | | private final static String keywordFullPattern = firstOp + restOfExpression; |
| | | /** Regular expression used to match the first operation keyword and the rest of the expression. */ |
| | | private static final String keywordFullPattern = firstOp + restOfExpression; |
| | | |
| | | /** |
| | | * The enumeration representing the operation. |
| | | */ |
| | | /** The enumeration representing the operation. */ |
| | | private final EnumTargetOperator op; |
| | | |
| | | /** |
| | |
| | | * @param secondFilterList The second filter list class parsed from the |
| | | * rule. This one is optional. |
| | | */ |
| | | public TargAttrFilters(EnumTargetOperator op, |
| | | private TargAttrFilters(EnumTargetOperator op, |
| | | TargAttrFilterList firstFilterList, |
| | | TargAttrFilterList secondFilterList ) { |
| | | this.op=op; |
| | |
| | | //Add the second filter list mask to the mask. |
| | | operationMask |= secondFilterList.getMask(); |
| | | this.secondFilterList=secondFilterList; |
| | | } else { |
| | | this.secondFilterList = null; |
| | | } |
| | | } |
| | | |
| | |
| | | get(expression); |
| | | throw new AciException(message); |
| | | } |
| | | /* |
| | | * Check that there are not too many filter lists. There can only |
| | | * be either one or two. |
| | | */ |
| | | /* Check that there are not too many filter lists. There can only be either one or two. */ |
| | | String[] filterLists = secondOp.split(subExpression, -1); |
| | | if(filterLists.length > 2) { |
| | | throw new AciException(WARN_ACI_SYNTAX_INVALID_TARGATTRFILTERS_MAX_FILTER_LISTS.get(expression)); |
| | |
| | | * @return The mask corresponding to the operation string. |
| | | */ |
| | | private static int getMask(String op) { |
| | | if(op.equals("add")) |
| | | if ("add".equals(op)) |
| | | { |
| | | return TARGATTRFILTERS_ADD; |
| | | } |
| | |
| | | * @return A TargAttrFilterList matching both the rights of the target |
| | | * match context and the mask of the TargFilterAttrList. May return null. |
| | | */ |
| | | public TargAttrFilterList |
| | | private TargAttrFilterList |
| | | getTargAttrFilterList(AciTargetMatchContext matchCtx) { |
| | | int mask=ACI_NULL; |
| | | //Set up the wanted mask by evaluating both the target match |
| | |
| | | public boolean hasMask(int mask) { |
| | | return (this.operationMask & mask) != 0; |
| | | } |
| | | |
| | | } |
| | |
| | | import static org.opends.messages.AccessControlMessages.*; |
| | | import static org.opends.server.authorization.dseecompat.Aci.*; |
| | | |
| | | /** |
| | | * A class representing an ACI target keyword. |
| | | */ |
| | | /** A class representing an ACI target keyword. */ |
| | | public class Target |
| | | { |
| | | /** |
| | | * Enumeration representing the target operator. |
| | | */ |
| | | private EnumTargetOperator operator = EnumTargetOperator.EQUALITY; |
| | | |
| | | /** |
| | | * True if the URL contained a DN wild-card pattern. |
| | | */ |
| | | private boolean isPattern; |
| | | |
| | | /** |
| | | * The target DN from the URL or null if it was a wild-card pattern. |
| | | */ |
| | | private DN urlDN; |
| | | |
| | | /** |
| | | * The pattern matcher for a wild-card pattern or null if the URL |
| | | * contained an ordinary DN. |
| | | */ |
| | | private PatternDN patternDN; |
| | | /** Enumeration representing the target operator. */ |
| | | private final EnumTargetOperator operator; |
| | | /** True if the URL contained a DN wild-card pattern. */ |
| | | private final boolean isPattern; |
| | | /** The target DN from the URL or null if it was a wild-card pattern. */ |
| | | private final DN urlDN; |
| | | /** The pattern matcher for a wild-card pattern or null if the URL contained an ordinary DN. */ |
| | | private final PatternDN patternDN; |
| | | |
| | | /* |
| | | * TODO Save aciDN parameter and use it in matchesPattern re-write. |
| | |
| | | * it can be used in the matchesPattern() method? The DN should only be |
| | | * considered a potential match if it is at or below the entry containing |
| | | * the ACI. |
| | | * |
| | | */ |
| | | /** |
| | | * This constructor parses the target string. |
| | |
| | | if (targetURL.getRawBaseDN().contains("*")) { |
| | | this.isPattern=true; |
| | | patternDN = PatternDN.decodeSuffix(targetURL.getRawBaseDN()); |
| | | urlDN = null; |
| | | } else { |
| | | this.isPattern = false; |
| | | patternDN = null; |
| | | urlDN=targetURL.getBaseDN(); |
| | | if(!urlDN.isSubordinateOrEqualTo(aciDN)) { |
| | | throw new AciException(WARN_ACI_SYNTAX_TARGET_DN_NOT_DESCENDENTOF.get(urlDN, aciDN)); |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2013-2015 ForgeRock AS. |
| | | * Portions Copyright 2013-2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | | import static org.opends.messages.AccessControlMessages.*; |
| | | |
| | | import java.util.HashSet; |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * This class represents an ACI's targetcontrol keyword. |
| | | */ |
| | | /** This class represents an ACI's targetcontrol keyword. */ |
| | | public class TargetControl { |
| | | |
| | | /** HashSet of OID strings parsed from the decode. */ |
| | | private Set<String> controlOIDS = new HashSet<>(); |
| | | private final Set<String> controlOIDS; |
| | | /** Enumeration representing the targetcontrol operator. */ |
| | | private EnumTargetOperator op = EnumTargetOperator.EQUALITY; |
| | | private final EnumTargetOperator op; |
| | | |
| | | /** |
| | | * Creates a class that can be used to evaluate a targetcontrol. |
| | |
| | | { |
| | | return false; |
| | | } |
| | | boolean ret = false; |
| | | for(String oid : controlOIDS) |
| | | boolean ret = isApplicable(matchCtx.getControlOID()); |
| | | if (EnumTargetOperator.NOT_EQUALITY.equals(op)) |
| | | { |
| | | if(oid.equals("*") || matchCtx.getControlOID().equals(oid)) { |
| | | ret=true; |
| | | break; |
| | | } |
| | | } |
| | | if(op.equals(EnumTargetOperator.NOT_EQUALITY)) |
| | | { |
| | | ret = !ret; |
| | | return !ret; |
| | | } |
| | | return ret; |
| | | } |
| | | |
| | | private boolean isApplicable(String matchControlOID) |
| | | { |
| | | for (String oid : controlOIDS) |
| | | { |
| | | if (oid.equals("*") || matchControlOID.equals(oid)) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | } |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014-2015 ForgeRock AS. |
| | | * Portions Copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | |
| | | import static org.opends.messages.AccessControlMessages.*; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.SearchFilter; |
| | | |
| | | /** |
| | | * This class represents a targetfilter keyword of an aci. |
| | | */ |
| | | /** This class represents a targetfilter keyword of an aci. */ |
| | | public class TargetFilter { |
| | | |
| | | /** Enumeration representing the targetfilter operation. */ |
| | | private EnumTargetOperator op = EnumTargetOperator.EQUALITY; |
| | | |
| | | private final EnumTargetOperator op; |
| | | /** Filter parsed from the ACI used to match the resource entry. */ |
| | | private SearchFilter filter; |
| | | private final SearchFilter filter; |
| | | |
| | | /** |
| | | * Class representing a targetfilter keyword. |
| | |
| | | filter = SearchFilter.createFilterFromString(expr); |
| | | } catch (DirectoryException ex) { |
| | | LocalizableMessage message = |
| | | WARN_ACI_SYNTAX_INVALID_TARGETFILTERKEYWORD_EXPRESSION. |
| | | get(expr); |
| | | WARN_ACI_SYNTAX_INVALID_TARGETFILTERKEYWORD_EXPRESSION.get(expr); |
| | | throw new AciException(message); |
| | | } |
| | | return new TargetFilter(op, filter); |
| | |
| | | * @return True if the target filter matched the context. |
| | | */ |
| | | public boolean isApplicable(AciTargetMatchContext matchCtx) { |
| | | boolean ret; |
| | | ret=matchesFilter(matchCtx.getResourceEntry()); |
| | | boolean ret = matchesFilter(matchCtx.getResourceEntry()); |
| | | if(op.equals(EnumTargetOperator.NOT_EQUALITY)) |
| | | { |
| | | ret = !ret; |
| | | return !ret; |
| | | } |
| | | return ret; |
| | | } |
| | |
| | | * @return True if the filter matches the entry. |
| | | */ |
| | | private boolean matchesFilter(Entry e) { |
| | | boolean ret; |
| | | try { |
| | | ret=filter.matchesEntry(e); |
| | | return filter.matchesEntry(e); |
| | | } catch (DirectoryException ex) { |
| | | //TODO information message? |
| | | return false; |
| | | } |
| | | return ret; |
| | | } |
| | | } |
| | |
| | | * Portions Copyright 2013-2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | | import static org.opends.messages.AccessControlMessages.*; |
| | | |
| | | import java.util.regex.Pattern; |
| | |
| | | private static final Pattern timeofdayRegex = Pattern.compile("[0-2]\\d[0-5]\\d"); |
| | | |
| | | /** Enumeration representing the bind rule operation type. */ |
| | | private EnumBindRuleType type; |
| | | |
| | | private final EnumBindRuleType type; |
| | | /** Holds the time value parsed from the ACI. */ |
| | | private int timeRef; |
| | | private final int timeRef; |
| | | |
| | | /** |
| | | * Constructor to create a timeofday keyword class. |
| | |
| | | * Evaluates the timeofday bind rule using the evaluation context |
| | | * passed into the method. |
| | | * @param evalCtx The evaluation context to use for the evaluation. |
| | | * @return An enumeration result representing the result of the |
| | | * evaluation. |
| | | * @return An enumeration result representing the result of the evaluation. |
| | | */ |
| | | @Override |
| | | public EnumEvalResult evaluate(AciEvalContext evalCtx) { |
| | | EnumEvalResult matched=EnumEvalResult.FALSE; |
| | | EnumEvalResult matched = evaluate() ? EnumEvalResult.TRUE : EnumEvalResult.FALSE; |
| | | return matched.getRet(type, false); |
| | | } |
| | | |
| | | private boolean evaluate() { |
| | | int currentTime=TimeThread.getHourAndMinute(); |
| | | //check the type |
| | | switch (type) { |
| | | case EQUAL_BINDRULE_TYPE: |
| | | case NOT_EQUAL_BINDRULE_TYPE: |
| | | if (currentTime != timeRef) |
| | | { |
| | | matched=EnumEvalResult.TRUE; |
| | | } |
| | | break; |
| | | |
| | | return currentTime != timeRef; |
| | | case LESS_OR_EQUAL_BINDRULE_TYPE: |
| | | if (currentTime <= timeRef) |
| | | { |
| | | matched=EnumEvalResult.TRUE; |
| | | } |
| | | break; |
| | | |
| | | return currentTime <= timeRef; |
| | | case LESS_BINDRULE_TYPE: |
| | | if (currentTime < timeRef) |
| | | { |
| | | matched=EnumEvalResult.TRUE; |
| | | } |
| | | break; |
| | | |
| | | return currentTime < timeRef; |
| | | case GREATER_OR_EQUAL_BINDRULE_TYPE: |
| | | if (currentTime >= timeRef) |
| | | { |
| | | matched=EnumEvalResult.TRUE; |
| | | } |
| | | break; |
| | | |
| | | return currentTime >= timeRef; |
| | | case GREATER_BINDRULE_TYPE: |
| | | if (currentTime > timeRef) |
| | | { |
| | | matched=EnumEvalResult.TRUE; |
| | | return currentTime > timeRef; |
| | | default: |
| | | return false; |
| | | } |
| | | } |
| | | return matched.getRet(type, false); |
| | | } |
| | | |
| | | @Override |
| | | public String toString() |
| | |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | | import static org.opends.messages.AccessControlMessages.*; |
| | | import static org.opends.server.protocols.internal.InternalClientConnection.*; |
| | | import static org.opends.server.protocols.internal.Requests.*; |
| | | |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | |
| | |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.forgerock.opendj.ldap.SearchScope; |
| | | import org.forgerock.opendj.ldap.schema.AttributeType; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.protocols.internal.InternalSearchOperation; |
| | | import org.opends.server.protocols.internal.SearchRequest; |
| | | import org.forgerock.opendj.ldap.schema.AttributeType; |
| | | import org.opends.server.types.*; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.LDAPURL; |
| | | import org.opends.server.types.SearchResultEntry; |
| | | |
| | | import static org.opends.messages.AccessControlMessages.*; |
| | | import static org.opends.server.protocols.internal.InternalClientConnection.*; |
| | | import static org.opends.server.protocols.internal.Requests.*; |
| | | |
| | | /* |
| | | * TODO Evaluate making this class more efficient. |
| | | * |
| | | * This class isn't as efficient as it could be. For example, the evalVAL() |
| | | * method should be able to use cached versions of the attribute type and |
| | | * filter. The evalURL() and evalDN() methods should also be able to use a |
| | | * cached version of the attribute type. |
| | | */ |
| | | /** |
| | | * This class implements the userattr bind rule keyword. |
| | | * <p> |
| | | * TODO Evaluate making this class more efficient. |
| | | *<p> |
| | | * This class isn't as efficient as it could be. For example, the {@link #evalVAL(AciEvalContext)} |
| | | * method should be able to use cached versions of the attribute type and filter. |
| | | * The {@link #evalURL(AciEvalContext)} and {@link #evalDNKeywords(AciEvalContext)} |
| | | * methods should also be able to use a cached version of the attribute type. |
| | | */ |
| | | public class UserAttr implements KeywordBindRule { |
| | | |
| | | /** |
| | | * This enumeration is the various types the userattr can have after |
| | | * the "#" token. |
| | | */ |
| | | /** This enumeration is the various types the userattr can have after the "#" token. */ |
| | | private enum UserAttrType { |
| | | USERDN, GROUPDN, ROLEDN, URL, VALUE; |
| | | |
| | |
| | | * Used to create an attribute type that can compare the value below in |
| | | * an entry returned from an internal search. |
| | | */ |
| | | private String attrStr; |
| | | |
| | | private final String attrStr; |
| | | /** |
| | | * 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; |
| | | |
| | | private final String attrVal; |
| | | /** Contains the type of the userattr, one of the above enumerations. */ |
| | | private UserAttrType userAttrType; |
| | | |
| | | private final UserAttrType userAttrType; |
| | | /** An enumeration representing the bind rule type. */ |
| | | private EnumBindRuleType type; |
| | | |
| | | private final EnumBindRuleType type; |
| | | /** The class used to hold the parent inheritance information. */ |
| | | private ParentInheritance parentInheritance; |
| | | private final ParentInheritance parentInheritance; |
| | | |
| | | /** |
| | | * Create an non-USERDN/GROUPDN instance of the userattr keyword class. |
| | |
| | | this.attrVal=attrVal; |
| | | this.userAttrType=userAttrType; |
| | | this.type=type; |
| | | this.parentInheritance = null; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | private UserAttr(UserAttrType userAttrType, EnumBindRuleType type, |
| | | ParentInheritance parentInheritance) { |
| | | this.attrStr = null; |
| | | this.attrVal = null; |
| | | this.userAttrType=userAttrType; |
| | | this.type=type; |
| | | this.parentInheritance=parentInheritance; |
| | |
| | | */ |
| | | @Override |
| | | public EnumEvalResult evaluate(AciEvalContext evalCtx) { |
| | | EnumEvalResult matched; |
| | | //The working resource entry might be filtered and not have an |
| | | //attribute type that is needed to perform these evaluations. The |
| | | //evalCtx has a copy of the non-filtered entry, switch to it for these |
| | |
| | | switch(userAttrType) { |
| | | case ROLEDN: |
| | | case GROUPDN: |
| | | case USERDN: { |
| | | matched=evalDNKeywords(evalCtx); |
| | | break; |
| | | } |
| | | case URL: { |
| | | matched=evalURL(evalCtx); |
| | | break; |
| | | } |
| | | case USERDN: |
| | | return evalDNKeywords(evalCtx); |
| | | case URL: |
| | | return evalURL(evalCtx); |
| | | default: |
| | | matched=evalVAL(evalCtx); |
| | | return evalVAL(evalCtx); |
| | | } |
| | | return matched; |
| | | } |
| | | |
| | | /** Evaluate a VALUE userattr type. Look in client entry for an |
| | |
| | | * @return An enumeration containing a result of the USERDN evaluation. |
| | | */ |
| | | private EnumEvalResult evalDNKeywords(AciEvalContext evalCtx) { |
| | | EnumEvalResult matched= EnumEvalResult.FALSE; |
| | | boolean undefined=false, stop=false; |
| | | boolean matched = false; |
| | | boolean undefined = false; |
| | | int numLevels=parentInheritance.getNumLevels(); |
| | | int[] levels=parentInheritance.getLevels(); |
| | | AttributeType attrType=parentInheritance.getAttributeType(); |
| | | DN baseDN=parentInheritance.getBaseDN(); |
| | | Entry resourceEntry = evalCtx.getResourceEntry(); |
| | | if(baseDN != null) { |
| | | if (evalCtx.getResourceEntry().hasAttribute(attrType)) { |
| | | matched=GroupDN.evaluate(evalCtx.getResourceEntry(), |
| | | evalCtx,attrType, baseDN); |
| | | } |
| | | matched = resourceEntry.hasAttribute(attrType) && GroupDN.evaluate(resourceEntry, evalCtx,attrType, baseDN); |
| | | } else { |
| | | for(int i=0;(i < numLevels && !stop); i++ ) { |
| | | for (int i = 0; i < numLevels; i++) { |
| | | //The ROLEDN keyword will always enter this statement. The others |
| | | //might. For the add operation, the resource itself (level 0) |
| | | //must never be allowed to give access. |
| | | if(levels[i] == 0) { |
| | | if(evalCtx.isAddOperation()) { |
| | | undefined=true; |
| | | } else if (evalCtx.getResourceEntry().hasAttribute(attrType)) { |
| | | matched = |
| | | evalEntryAttr(evalCtx.getResourceEntry(), |
| | | evalCtx,attrType); |
| | | if(matched.equals(EnumEvalResult.TRUE)) { |
| | | stop=true; |
| | | } |
| | | } else if (resourceEntry.hasAttribute(attrType) |
| | | && evalEntryAttr(resourceEntry, evalCtx, attrType)) { |
| | | matched = true; |
| | | break; |
| | | } |
| | | } else { |
| | | DN pDN = getDNParentLevel(levels[i], evalCtx.getResourceDN()); |
| | | DN pDN = evalCtx.getResourceDN().parent(levels[i]); |
| | | if(pDN == null) { |
| | | continue; |
| | | } |
| | |
| | | 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 (e.hasAttribute(attrType) && evalEntryAttr(e, evalCtx, attrType)) { |
| | | matched = true; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | EnumEvalResult res = matched ? EnumEvalResult.TRUE : EnumEvalResult.FALSE; |
| | | return res.getRet(type, undefined); |
| | | } |
| | | return matched.getRet(type, undefined); |
| | | } |
| | | |
| | | /** |
| | | * This method returns a parent DN based on the level. Not very |
| | | * sophisticated but it works. |
| | | * @param l The level. |
| | | * @param dn The DN to get the parent of. |
| | | * @return Parent DN based on the level or null if the level is greater |
| | | * than the rdn count. |
| | | */ |
| | | private DN getDNParentLevel(int l, DN dn) { |
| | | int rdns=dn.size(); |
| | | if(l > rdns) { |
| | | return null; |
| | | } |
| | | DN theDN=dn; |
| | | for(int i=0; i < l;i++) { |
| | | theDN=theDN.parent(); |
| | | } |
| | | return theDN; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * This method evaluates the user attribute type and calls the correct |
| | | * evalaution method. The three user attribute types that can be selected |
| | | * evaluation method. The three user attribute types that can be selected |
| | | * are USERDN or GROUPDN. |
| | | * |
| | | * @param e The entry to use in the evaluation. |
| | |
| | | * @param attributeType The attribute type to use in the evaluation. |
| | | * @return The result of the evaluation routine. |
| | | */ |
| | | private EnumEvalResult evalEntryAttr(Entry e, AciEvalContext evalCtx, |
| | | AttributeType attributeType) { |
| | | EnumEvalResult result=EnumEvalResult.FALSE; |
| | | private boolean evalEntryAttr(Entry e, AciEvalContext evalCtx, AttributeType attributeType) { |
| | | switch (userAttrType) { |
| | | case USERDN: { |
| | | result=UserDN.evaluate(e, evalCtx.getClientDN(), |
| | | attributeType); |
| | | break; |
| | | case USERDN: |
| | | return UserDN.evaluate(e, evalCtx.getClientDN(), attributeType); |
| | | case GROUPDN: |
| | | return GroupDN.evaluate(e, evalCtx, attributeType, null); |
| | | default: |
| | | return false; |
| | | } |
| | | case GROUPDN: { |
| | | result=GroupDN.evaluate(e, evalCtx, attributeType, null); |
| | | break; |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String toString() |
| | | { |
| | |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public final void toString(StringBuilder buffer) |
| | | { |
| | | buffer.append(super.toString()); |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | /** This class represents the userdn keyword in a bind rule. */ |
| | | public class UserDN implements KeywordBindRule { |
| | | |
| | | /** A dummy URL for invalid URLs such as: all, parent, anyone, self. */ |
| | | private static final String URL_STR = "ldap:///"; |
| | | |
| | | /** This list holds a list of objects representing a EnumUserDNType URL mapping. */ |
| | | private List<UserDNTypeURL> urlList; |
| | | private final List<UserDNTypeURL> urlList; |
| | | /** Enumeration of the userdn operation type. */ |
| | | private EnumBindRuleType type; |
| | | private final EnumBindRuleType type; |
| | | |
| | | /** |
| | | * Constructor that creates the userdn class. It also sets up an attribute |
| | |
| | | */ |
| | | public static KeywordBindRule decode(String expression, |
| | | EnumBindRuleType type) throws AciException { |
| | | |
| | | String[] vals=expression.split("[|][|]"); |
| | | List<UserDNTypeURL> urlList = new LinkedList<>(); |
| | | for (String val : vals) |
| | |
| | | * @return The user DN type of the URL. |
| | | */ |
| | | private static EnumUserDNType getType(StringBuilder bldr) { |
| | | EnumUserDNType type; |
| | | String str=bldr.toString(); |
| | | |
| | | if (str.contains("?")) { |
| | | type = EnumUserDNType.URL; |
| | | return EnumUserDNType.URL; |
| | | } else if(str.equalsIgnoreCase("ldap:///self")) { |
| | | type = EnumUserDNType.SELF; |
| | | bldr.replace(0, bldr.length(), URL_STR); |
| | | return EnumUserDNType.SELF; |
| | | } else if(str.equalsIgnoreCase("ldap:///anyone")) { |
| | | type = EnumUserDNType.ANYONE; |
| | | bldr.replace(0, bldr.length(), URL_STR); |
| | | return EnumUserDNType.ANYONE; |
| | | } else if(str.equalsIgnoreCase("ldap:///parent")) { |
| | | type = EnumUserDNType.PARENT; |
| | | bldr.replace(0, bldr.length(), URL_STR); |
| | | return EnumUserDNType.PARENT; |
| | | } else if(str.equalsIgnoreCase("ldap:///all")) { |
| | | type = EnumUserDNType.ALL; |
| | | bldr.replace(0, bldr.length(), URL_STR); |
| | | return EnumUserDNType.ALL; |
| | | } else if (str.contains("*")) { |
| | | type = EnumUserDNType.DNPATTERN; |
| | | return EnumUserDNType.DNPATTERN; |
| | | } else { |
| | | type = EnumUserDNType.DN; |
| | | return EnumUserDNType.DN; |
| | | } |
| | | return type; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | private EnumEvalResult evalNonAnonymous(AciEvalContext evalCtx, |
| | | UserDNTypeURL dnTypeURL) { |
| | | return evalNonAnonymous0(evalCtx, dnTypeURL) ? EnumEvalResult.TRUE : EnumEvalResult.FALSE; |
| | | } |
| | | |
| | | private boolean evalNonAnonymous0(AciEvalContext evalCtx, |
| | | UserDNTypeURL dnTypeURL) { |
| | | DN clientDN=evalCtx.getClientDN(); |
| | | DN resDN=evalCtx.getResourceDN(); |
| | | EnumEvalResult matched = EnumEvalResult.FALSE; |
| | | EnumUserDNType type=dnTypeURL.getUserDNType(); |
| | | LDAPURL url=dnTypeURL.getURL(); |
| | | switch (type) { |
| | | case URL: |
| | | { |
| | | matched = evalURL(evalCtx, url); |
| | | break; |
| | | } |
| | | return evalURL0(evalCtx, url); |
| | | case ANYONE: |
| | | { |
| | | matched = EnumEvalResult.TRUE; |
| | | break; |
| | | } |
| | | case SELF: |
| | | { |
| | | if (clientDN.equals(resDN)) |
| | | { |
| | | matched = EnumEvalResult.TRUE; |
| | | } |
| | | break; |
| | | } |
| | | case PARENT: |
| | | { |
| | | DN parentDN = resDN.parent(); |
| | | if (parentDN != null && parentDN.equals(clientDN)) |
| | | { |
| | | matched = EnumEvalResult.TRUE; |
| | | } |
| | | break; |
| | | } |
| | | case ALL: |
| | | { |
| | | matched = EnumEvalResult.TRUE; |
| | | break; |
| | | } |
| | | return true; |
| | | case SELF: |
| | | return clientDN.equals(resDN); |
| | | case PARENT: |
| | | DN parentDN = resDN.parent(); |
| | | return parentDN != null && parentDN.equals(clientDN); |
| | | case DNPATTERN: |
| | | { |
| | | matched = evalDNPattern(evalCtx, url); |
| | | break; |
| | | } |
| | | return evalDNPattern(evalCtx, url); |
| | | case DN: |
| | | return evalDN(clientDN, url); |
| | | default: |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | private boolean evalDN(DN clientDN, LDAPURL url) |
| | | { |
| | | try |
| | | { |
| | | DN dn = url.getBaseDN(); |
| | | if (clientDN.equals(dn)) |
| | | { |
| | | matched = EnumEvalResult.TRUE; |
| | | return true; |
| | | } |
| | | else { |
| | | |
| | | //This code handles the case where a root dn entry does |
| | | //not have bypass-acl privilege and the ACI bind rule |
| | | //userdn DN possible is an alternate root DN. |
| | | DN actualDN=DirectoryServer.getActualRootBindDN(dn); |
| | | DN clientActualDN= |
| | | DirectoryServer.getActualRootBindDN(clientDN); |
| | | DN clientActualDN = DirectoryServer.getActualRootBindDN(clientDN); |
| | | if(actualDN != null) |
| | | { |
| | | dn=actualDN; |
| | |
| | | { |
| | | clientDN=clientActualDN; |
| | | } |
| | | if(clientDN.equals(dn)) |
| | | { |
| | | matched=EnumEvalResult.TRUE; |
| | | } |
| | | } |
| | | return clientDN.equals(dn); |
| | | } catch (DirectoryException ex) { |
| | | //TODO add message |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | return matched; |
| | | } |
| | | |
| | | /** |
| | | * This method evaluates a DN pattern userdn expression. |
| | |
| | | * @param url The LDAP URL containing the pattern. |
| | | * @return An enumeration evaluation result. |
| | | */ |
| | | private EnumEvalResult evalDNPattern(AciEvalContext evalCtx, LDAPURL url) { |
| | | private boolean evalDNPattern(AciEvalContext evalCtx, LDAPURL url) { |
| | | PatternDN pattern; |
| | | try { |
| | | pattern = PatternDN.decode(url.getRawBaseDN()); |
| | | } catch (DirectoryException ex) { |
| | | return EnumEvalResult.FALSE; |
| | | return false; |
| | | } |
| | | |
| | | return pattern.matchesDN(evalCtx.getClientDN()) ? |
| | | EnumEvalResult.TRUE : EnumEvalResult.FALSE; |
| | | return pattern.matchesDN(evalCtx.getClientDN()); |
| | | } |
| | | |
| | | |
| | |
| | | * @return An enumeration of the evaluation result. |
| | | */ |
| | | public static EnumEvalResult evalURL(AciEvalContext evalCtx, LDAPURL url) { |
| | | EnumEvalResult ret=EnumEvalResult.FALSE; |
| | | return evalURL0(evalCtx, url) ? EnumEvalResult.TRUE : EnumEvalResult.FALSE; |
| | | } |
| | | |
| | | private static boolean evalURL0(AciEvalContext evalCtx, LDAPURL url) { |
| | | DN urlDN; |
| | | SearchFilter filter; |
| | | try { |
| | | urlDN=url.getBaseDN(); |
| | | filter=url.getFilter(); |
| | | } catch (DirectoryException ex) { |
| | | return EnumEvalResult.FALSE; |
| | | return false; |
| | | } |
| | | SearchScope scope=url.getScope(); |
| | | if(scope == SearchScope.WHOLE_SUBTREE) { |
| | | if(!evalCtx.getClientDN().isSubordinateOrEqualTo(urlDN)) |
| | | { |
| | | return EnumEvalResult.FALSE; |
| | | return false; |
| | | } |
| | | } else if(scope == SearchScope.SINGLE_LEVEL) { |
| | | DN parent=evalCtx.getClientDN().parent(); |
| | | if(parent != null && !parent.equals(urlDN)) |
| | | { |
| | | return EnumEvalResult.FALSE; |
| | | return false; |
| | | } |
| | | } else if(scope == SearchScope.SUBORDINATES) { |
| | | DN userDN = evalCtx.getClientDN(); |
| | | if (userDN.size() <= urlDN.size() || |
| | | !userDN.isSubordinateOrEqualTo(urlDN)) { |
| | | return EnumEvalResult.FALSE; |
| | | return false; |
| | | } |
| | | } else { |
| | | if(!evalCtx.getClientDN().equals(urlDN)) |
| | | { |
| | | return EnumEvalResult.FALSE; |
| | | return false; |
| | | } |
| | | } |
| | | try { |
| | | if(filter.matchesEntry(evalCtx.getClientEntry())) |
| | | { |
| | | ret=EnumEvalResult.TRUE; |
| | | } |
| | | return (filter.matchesEntry(evalCtx.getClientEntry())); |
| | | } catch (DirectoryException ex) { |
| | | return EnumEvalResult.FALSE; |
| | | return false; |
| | | } |
| | | return ret; |
| | | } |
| | | |
| | | /* |
| | |
| | | * @param attrType The attribute type from the bind rule. |
| | | * @return An enumeration with the result. |
| | | */ |
| | | public static EnumEvalResult evaluate(Entry e, DN clientDN, |
| | | public static boolean evaluate(Entry e, DN clientDN, |
| | | AttributeType attrType) { |
| | | List<Attribute> attrs = e.getAttribute(attrType); |
| | | for(ByteString v : attrs.get(0)) { |
| | | try { |
| | | DN dn = DN.valueOf(v.toString()); |
| | | if(dn.equals(clientDN)) { |
| | | return EnumEvalResult.TRUE; |
| | | return true; |
| | | } |
| | | } catch (LocalizedIllegalArgumentException ignored) { |
| | | break; |
| | | } |
| | | } |
| | | return EnumEvalResult.FALSE; |
| | | return false; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String toString() { |
| | | final StringBuilder sb = new StringBuilder(); |
| | |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public final void toString(StringBuilder buffer) { |
| | | buffer.append("userdn"); |
| | |
| | | buffer.append("\""); |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2015 ForgeRock AS. |
| | | * Portions Copyright 2015-2016 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.authorization.dseecompat; |
| | | |
| | |
| | | public class UserDNTypeURL { |
| | | |
| | | /** The DN type of the URL. */ |
| | | private EnumUserDNType dnType; |
| | | |
| | | private final EnumUserDNType dnType; |
| | | /** The URL value. Maybe a dummy value for types such as ANYONE or SELF. */ |
| | | private LDAPURL url; |
| | | private final LDAPURL url; |
| | | |
| | | /** |
| | | * Create a class representing the "userdn" URL decoded by the |