mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Jean-Noel Rouvignac
03.03.2013 56e752193bfb90d11cfe73c35a24e576b9b18c87
First stab at having debuggable ACIs.


AciBodyTest.java: ADDED

KeywordBindRule.java:
Added toString(StringBuilder).

*.java:
Fixed a lot of javadocs and made a lot of instance members private.
Added toString() and toString(StringBuilder) to most classes, with AciBody, BindRule, PermBindRulePair, Permission, UserDN having a proper implementation.

EnumBindRuleType.java:
Added getType().

EnumRight.java:
Added getRight(), getEnumRight() and hasRights()
1 files added
20 files modified
1028 ■■■■■ changed files
opends/src/server/org/opends/server/authorization/dseecompat/AciBody.java 78 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java 154 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/AciList.java 33 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/AuthMethod.java 32 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/BindRule.java 84 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/DNS.java 52 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/DayOfWeek.java 43 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/EnumBindRuleType.java 16 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/EnumRight.java 66 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/GroupDN.java 52 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/IP.java 35 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/KeywordBindRule.java 11 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/PermBindRulePair.java 36 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/Permission.java 55 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/SSF.java 27 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/TargAttrFilterList.java 38 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/TargAttrFilters.java 36 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/TimeOfDay.java 29 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/UserAttr.java 45 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/UserDN.java 48 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciBodyTest.java 58 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/AciBody.java
@@ -23,83 +23,82 @@
 *
 *
 *      Copyright 2008-2009 Sun Microsystems, Inc.
 *      Portions copyright 2012 ForgeRock AS.
 *      Portions copyright 2012-2013 ForgeRock AS.
 */
package org.opends.server.authorization.dseecompat;
import org.opends.messages.Message;
import static org.opends.messages.AccessControlMessages.*;
import static org.opends.server.authorization.dseecompat.Aci.*;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.opends.messages.Message;
/**
 * This class represents the body of an ACI. The body of the ACI is the
 * version, name, and permission-bind rule pairs.
 */
public class AciBody {
    /*
    /**
     * Regular expression group position for the version string.
     */
    private static final int VERSION = 1;
    /*
    /**
     * Regular expression group position for the name string.
     */
    private static final int NAME = 2;
    /*
    /**
     * Regular expression group position for the permission string.
     */
    private static final int PERM = 1;
    /*
    /**
     * Regular expression group position for the rights string.
     */
    private static final int RIGHTS = 2;
    /*
    /**
     * Regular expression group position for the bindrule string.
     */
    private static final int BINDRULE = 3;
    /*
    /**
     * Index into the ACI string where the ACI body starts.
     */
    private int startPos=0;
    /*
    /**
    * The name of the ACI, currently not used but parsed.
    */
    private String name = null;
    /*
    * The version of the ACi, current not used but parsed and checked
    * for 3.0.
    /**
     * The version of the ACi, current not used but parsed and checked for 3.0.
    */
    private String version = null;
    /*
     This structure represents a permission-bind rule pairs. There can be
     several of these.
    /**
     * This structure represents a permission-bind rule pairs. There can be
     * several of these.
    */
    private List<PermBindRulePair> permBindRulePairs;
    /*
    /**
     * Regular expression used to match the access type group (allow, deny) and
     * the rights group "(read, write, ...)". The last pattern looks for a group
     * surrounded by parenthesis. The group must contain at least one
     * non-paren character.
     */
    private static final
    String permissionRegex =
    private static final String permissionRegex =
               WORD_GROUP + ZERO_OR_MORE_WHITESPACE + "\\(([^()]+)\\)";
    /*
    /**
     * Regular expression that matches a bind rule group at a coarse level. It
     * matches any character one or more times, a single quotation and
     * an optional right parenthesis.
@@ -107,7 +106,7 @@
    private static final String bindRuleRegex =
            "(.+?\"[)]*)" + ACI_STATEMENT_SEPARATOR;
    /*
    /**
     * Regular expression used to match the actions of the ACI. The actions
     * are permissions and matching bind rules.
     */
@@ -115,17 +114,17 @@
            ZERO_OR_MORE_WHITESPACE + permissionRegex +
            ZERO_OR_MORE_WHITESPACE + bindRuleRegex;
    /*
    /**
     * Regular expression used to match the version value (digit.digit).
     */
    private static final String versionRegex = "(\\d\\.\\d)";
    /*
    /**
     * Regular expression used to match the version token. Case insensitive.
     */
    private static final String versionToken = "(?i)version(?-i)";
    /*
    /**
     * Regular expression used to match the acl token. Case insensitive.
     */
    private static final String aclToken = "(?i)acl(?-i)";
@@ -141,7 +140,7 @@
        "\"([^\"]*)\"" + ACI_STATEMENT_SEPARATOR + actionRegex +
        ZERO_OR_MORE_WHITESPACE  + "\\)";
    /*
    /**
     * Regular expression used to match the header of the ACI body. The
     * header is version and acl name.
     */
@@ -260,7 +259,7 @@
     *
     * @return The permission-bind rule pairs.
     */
    private List<PermBindRulePair> getPermBindRulePairs() {
    List<PermBindRulePair> getPermBindRulePairs() {
        return permBindRulePairs;
    }
@@ -374,4 +373,31 @@
  public String getVersion () {
    return version;
  }
  /** {@inheritDoc} */
  @Override
  public String toString()
  {
    final StringBuilder sb = new StringBuilder();
    toString(sb);
    return sb.toString();
  }
  /**
   * Appends a string representation of this object to the provided buffer.
   *
   * @param buffer
   *          The buffer into which a string representation of this object
   *          should be appended.
   */
  public 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);
    }
  }
}
opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java
@@ -23,28 +23,27 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2011 ForgeRock AS
 *      Portions Copyright 2011-2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
import org.opends.server.protocols.ldap.LDAPClientConnection;
import org.opends.server.types.*;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.Group;
import org.opends.server.core.AddOperationBasis;
import org.opends.server.core.SearchOperation;
import org.opends.server.types.Operation;
import java.net.InetAddress;
import java.security.cert.Certificate;
import java.util.LinkedList;
import java.util.List;
import java.util.HashMap;
import static org.opends.server.authorization.dseecompat.Aci.*;
import static org.opends.server.authorization.dseecompat.AciHandler.*;
import static org.opends.server.util.ServerConstants.*;
import java.net.InetAddress;
import java.security.cert.Certificate;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.Group;
import org.opends.server.controls.GetEffectiveRightsRequestControl;
import static org.opends.server.util.ServerConstants.OID_GET_EFFECTIVE_RIGHTS;
import org.opends.server.core.AddOperation;
import org.opends.server.core.SearchOperation;
import org.opends.server.protocols.ldap.LDAPClientConnection;
import org.opends.server.types.*;
/**
 *  The AciContainer class contains all of the needed information to perform
@@ -55,70 +54,70 @@
public abstract class AciContainer
implements AciTargetMatchContext, AciEvalContext {
    /*
    /**
     * The allow and deny lists.
     */
    private LinkedList<Aci> denyList, allowList;
    /*
    /**
     * The attribute type in the resource entry currently being evaluated.
     */
    private AttributeType attributeType;
    /*
    /**
     * The attribute type value in the resource entry currently being
     * evaluated.
     */
    private AttributeValue attributeValue;
    /*
    /**
     * True if this is the first attribute type in the resource entry being
     * evaluated.
     */
    private boolean isFirst = false;
    /*
    /**
     * True if an entry test rule was seen during target matching of an ACI
     * entry. A entry test rule is an ACI with targetattrs target keyword.
     */
    private boolean isEntryTestRule = false;
    /*
    /**
     * True if the evaluation of an ACI is from the deny list.
     */
    private boolean isDenyEval;
    /*
    /**
     * True if the evaluation is a result of an LDAP add operation.
     */
    private boolean isAddOp=false;
    /*
    /**
     * The right mask to use in the evaluation of the LDAP operation.
     */
    private int rightsMask;
    /*
    /**
     * The entry being evaluated (resource entry).
     */
    private Entry resourceEntry;
    /*
    /**
     * The client connection information.
     */
    private final ClientConnection clientConnection;
    /*
    /**
     * The operation being evaluated.
     */
    private final Operation operation;
    /*
    /**
     * True if a targattrfilters match was found.
     */
    private boolean targAttrFiltersMatch=false;
    /*
    /**
     * The authorization entry currently being evaluated. If proxied
     * authorization is being used and the handler is doing a proxy access
     * check, then this entry will switched to the original authorization entry
@@ -128,24 +127,24 @@
     */
    private Entry authorizationEntry;
    /*
    /**
     * Used to save the current authorization entry when the authorization
     * entry is switched during a proxy access check.
     */
    private final Entry saveAuthorizationEntry;
    /*
    /**
     * This entry is only used if proxied authorization is being used.  It is
     * the original authorization entry before the proxied authorization change.
     */
    private Entry origAuthorizationEntry=null;
    /*
    /**
     * True if proxied authorization is being used.
     */
    private boolean proxiedAuthorization=false;
    /*
    /**
     * Used by proxied authorization processing. True if the entry has already
     * been processed by an access proxy check. Some operations might perform
     * several access checks on the same entry (modify DN), this
@@ -153,88 +152,88 @@
     */
    private boolean seenEntry=false;
    /*
    /**
     *  True if geteffectiverights evaluation is in progress.
     */
    private boolean isGetEffectiveRightsEval=false;
     /*
    /**
     *  True if the operation has a geteffectiverights control.
     */
    private boolean hasGetEffectiveRightsControl=false;
    /*
    /**
     * The geteffectiverights authzID in DN format.
     */
    private DN authzid=null;
    /*
    /**
     * True if the authZid should be used as the client DN, only used in
     * geteffectiverights evaluation.
     */
    private boolean useAuthzid=false;
    /*
    /**
     * The list of specific attributes to get rights for, in addition to
     * any attributes requested in the search.
     */
    private List<AttributeType> specificAttrs=null;
    /*
    /**
     * Table of ACIs that have targattrfilter keywords that matched. Used
     * in geteffectiverights attributeLevel write evaluation.
     */
    private final HashMap<Aci,Aci> targAttrFilterAcis=new HashMap<Aci, Aci>();
    /*
    /**
     * The name of a ACI that decided an evaluation and contained a
     * targattrfilter keyword. Used in geteffectiverights attributeLevel
     * write evaluation.
     */
    private String targAttrFiltersAciName=null;
    /*
    /**
     * Value that is used to store the allow/deny result of a deciding ACI
     * containing a targattrfilter keyword.  Used in geteffectiverights
     * attributeLevel write evaluation.
     */
    private int targAttrMatch=0;
    /*
    /**
     * The ACI that decided the last evaluation. Used in geteffectiverights
     * loginfo processing.
     */
    private Aci decidingAci=null;
    /*
    /**
     * The reason the last evaluation decision was made. Used both
     * in geteffectiverights loginfo processing and attributeLevel write
     * evaluation.
     */
    private EnumEvalReason evalReason=null;
    /*
    /**
     * A summary string holding the last evaluation information in textual
     * format. Used in geteffectiverights loginfo processing.
     */
    private String summaryString=null;
   /*
   /**
    * Flag used to determine if ACI all attributes target matched.
    */
    private int evalAllAttributes=0;
   /*
   /**
    * String used to hold a control OID string.
    */
    private String controlOID;
   /*
   /**
    * String used to hold an extended operation OID string.
    */
    private String extOpOID;
    /*
    /**
     * AuthenticationInfo class to use.
     */
    private AuthenticationInfo authInfo;
@@ -255,16 +254,14 @@
      this.resourceEntry=entry;
      this.operation=operation;
      this.clientConnection=operation.getClientConnection();
      if(operation instanceof AddOperationBasis)
          this.isAddOp=true;
      this.isAddOp = operation instanceof AddOperation;
      this.authInfo = clientConnection.getAuthenticationInfo();
      //If the proxied authorization control was processed, then the operation
      //will contain an attachment containing the original authorization entry.
      this.origAuthorizationEntry =
                      (Entry) operation.getAttachment(ORIG_AUTH_ENTRY);
      if(origAuthorizationEntry != null)
         this.proxiedAuthorization=true;
      this.proxiedAuthorization = origAuthorizationEntry != null;
      this.authorizationEntry=operation.getAuthorizationEntry();
      //The ACI_READ right at constructor time can only be the result of the
@@ -353,6 +350,7 @@
  /**
   * {@inheritDoc}
   */
    @Override
    public boolean isProxiedAuthorization() {
         return this.proxiedAuthorization;
    }
@@ -360,6 +358,7 @@
  /**
   * {@inheritDoc}
   */
    @Override
    public boolean isGetEffectiveRightsEval() {
        return this.isGetEffectiveRightsEval;
    }
@@ -407,6 +406,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public void addTargAttrFiltersMatchAci(Aci aci) {
      this.targAttrFilterAcis.put(aci, aci);
    }
@@ -414,6 +414,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public boolean hasTargAttrFiltersMatchAci(Aci aci) {
      return this.targAttrFilterAcis.containsKey(aci);
    }
@@ -421,6 +422,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public boolean isTargAttrFilterMatchAciEmpty() {
       return this.targAttrFilterAcis.isEmpty();
    }
@@ -443,6 +445,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public void setTargAttrFiltersAciName(String name) {
      this.targAttrFiltersAciName=name;
    }
@@ -450,6 +453,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public String getTargAttrFiltersAciName() {
      return this.targAttrFiltersAciName;
    }
@@ -457,6 +461,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public void setTargAttrFiltersMatchOp(int flag) {
      this.targAttrMatch |= flag;
    }
@@ -464,6 +469,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public boolean hasTargAttrFiltersMatchOp(int flag) {
       return (this.targAttrMatch & flag) != 0;
    }
@@ -471,6 +477,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public void setDecidingAci(Aci aci) {
      this.decidingAci=aci;
    }
@@ -478,6 +485,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public String getDecidingAciName() {
      if(this.decidingAci != null)
         return this.decidingAci.getName();
@@ -487,6 +495,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public void setEvalReason(EnumEvalReason reason) {
      this.evalReason=reason;
    }
@@ -494,6 +503,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public EnumEvalReason getEvalReason() {
      return this.evalReason;
    }
@@ -501,6 +511,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public void setEvalSummary(String summary) {
      this.summaryString=summary;
    }
@@ -508,6 +519,7 @@
   /**
    * {@inheritDoc}
    */
     @Override
     public String getEvalSummary() {
      return this.summaryString;
    }
@@ -540,6 +552,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public void setDenyList(LinkedList<Aci> denys) {
        denyList=denys;
    }
@@ -547,6 +560,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public void setAllowList(LinkedList<Aci> allows) {
        allowList=allows;
    }
@@ -554,6 +568,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public AttributeType getCurrentAttributeType() {
        return attributeType;
    }
@@ -561,6 +576,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public AttributeValue getCurrentAttributeValue() {
        return attributeValue;
    }
@@ -568,6 +584,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public void setCurrentAttributeType(AttributeType type) {
        attributeType=type;
    }
@@ -575,6 +592,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public void setCurrentAttributeValue(AttributeValue value) {
        attributeValue=value;
    }
@@ -582,6 +600,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public boolean isFirstAttribute() {
        return isFirst;
    }
@@ -589,6 +608,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public void setIsFirstAttribute(boolean val) {
        isFirst=val;
    }
@@ -596,6 +616,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public boolean hasEntryTestRule() {
        return isEntryTestRule;
    }
@@ -603,6 +624,7 @@
   /**
    * {@inheritDoc}
    */
   @Override
   public void setEntryTestRule(boolean val) {
        isEntryTestRule=val;
    }
@@ -610,6 +632,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public Entry getResourceEntry() {
        return resourceEntry;
    }
@@ -617,6 +640,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public Entry getClientEntry() {
      return this.authorizationEntry;
    }
@@ -624,6 +648,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public LinkedList<Aci> getDenyList() {
        return denyList;
     }
@@ -631,6 +656,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public LinkedList<Aci> getAllowList() {
       return allowList;
    }
@@ -638,6 +664,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public boolean isDenyEval() {
        return isDenyEval;
    }
@@ -645,6 +672,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public boolean isAnonymousUser() {
        return !authInfo.isAuthenticated();
    }
@@ -652,6 +680,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public void setDenyEval(boolean val) {
        isDenyEval = val;
    }
@@ -659,6 +688,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public DN getClientDN() {
      if(this.useAuthzid)
        return this.authzid;
@@ -672,6 +702,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public DN getResourceDN() {
        return resourceEntry.getDN();
    }
@@ -679,6 +710,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public boolean hasRights(int rights) {
       return (this.rightsMask & rights) != 0;
    }
@@ -686,6 +718,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public int getRights() {
        return this.rightsMask;
    }
@@ -693,6 +726,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public void setRights(int rights) {
         this.rightsMask=rights;
    }
@@ -700,6 +734,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public String getHostName() {
        return clientConnection.getRemoteAddress().getCanonicalHostName();
    }
@@ -707,6 +742,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public InetAddress getRemoteAddress() {
        return clientConnection.getRemoteAddress();
    }
@@ -714,6 +750,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public boolean isAddOperation() {
        return isAddOp;
    }
@@ -721,6 +758,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public void setTargAttrFiltersMatch(boolean v) {
        this.targAttrFiltersMatch=v;
    }
@@ -728,6 +766,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public boolean getTargAttrFiltersMatch() {
        return targAttrFiltersMatch;
    }
@@ -735,6 +774,7 @@
    /**
    * {@inheritDoc}
    */
    @Override
    public String getControlOID() {
      return controlOID;
    }
@@ -742,6 +782,7 @@
   /**
    * {@inheritDoc}
    */
    @Override
    public String getExtOpOID() {
      return extOpOID;
    }
@@ -768,6 +809,7 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public EnumEvalResult hasAuthenticationMethod(EnumAuthMethod authMethod,
                                                  String saslMech) {
      EnumEvalResult matched=EnumEvalResult.FALSE;
@@ -822,6 +864,7 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isMemberOf(Group<?> group) {
        boolean ret;
        try {
@@ -844,6 +887,7 @@
  /**
   * {@inheritDoc}
   */
    @Override
    public String rightToString() {
      if(hasRights(ACI_SEARCH))
        return "search";
@@ -872,6 +916,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public  void setEvalUserAttributes(int v) {
    if(operation instanceof SearchOperation && (rightsMask == ACI_READ)) {
      if(v == ACI_FOUND_USER_ATTR_RULE) {
@@ -885,6 +930,7 @@
     /**
   * {@inheritDoc}
   */
  @Override
  public  void setEvalOpAttributes(int v) {
    if(operation instanceof SearchOperation && (rightsMask == ACI_READ)) {
      if(v == ACI_FOUND_OP_ATTR_RULE) {
@@ -898,6 +944,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public boolean hasEvalUserAttributes() {
    return (evalAllAttributes & ACI_FOUND_USER_ATTR_RULE) ==
            ACI_FOUND_USER_ATTR_RULE;
@@ -906,6 +953,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public boolean hasEvalOpAttributes() {
    return (evalAllAttributes & ACI_FOUND_OP_ATTR_RULE) ==
            ACI_FOUND_OP_ATTR_RULE;
@@ -936,6 +984,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public void clearEvalAttributes(int v) {
    if(v == 0)
      evalAllAttributes=0;
@@ -946,6 +995,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public int getCurrentSSF() {
      return clientConnection.getSSF();
  }
opends/src/server/org/opends/server/authorization/dseecompat/AciList.java
@@ -23,43 +23,42 @@
 *
 *
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
import org.opends.messages.Message;
import org.opends.server.api.Backend;
import static org.opends.server.authorization.dseecompat.AciHandler.*;
import static org.opends.server.loggers.ErrorLogger.logError;
import static org.opends.messages.AccessControlMessages.*;
import org.opends.server.api.DITCacheMap;
import org.opends.server.types.*;
import static org.opends.server.authorization.dseecompat.AciHandler.*;
import static org.opends.server.loggers.ErrorLogger.*;
import java.util.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.opends.messages.Message;
import org.opends.server.api.Backend;
import org.opends.server.api.DITCacheMap;
import org.opends.server.types.*;
/**
 * The AciList class performs caching of the ACI attribute values
 * using the entry DN as the key.
 */
public class AciList {
  /*
  /**
   * A map containing all the ACIs.
   * We use the copy-on-write technique to avoid locking when reading.
   */
  private volatile DITCacheMap<List<Aci>> aciList =
       new DITCacheMap<List<Aci>>();
  /*
  /**
   * Lock to protect internal data structures.
   */
  private final ReentrantReadWriteLock lock =
          new ReentrantReadWriteLock();
  /*
  * The configuration DN used to compare against the global ACI entry DN.
  */
  /** The configuration DN used to compare against the global ACI entry DN. */
  private DN configDN;
  /**
@@ -102,14 +101,12 @@
              AciTargets targets = aci.getTargets();
              //If there is a target, evaluate it to see if this ACI should
              //be included in the candidate set.
              if (targets != null) {
                boolean ret = AciTargets.isTargetApplicable(aci, targets,
                        entryDN);
                if (ret) {
              if (targets != null
                  && AciTargets.isTargetApplicable(aci, targets, entryDN))
              {
                  candidates.add(aci);  //Add this ACI to the candidates.
                }
              }
            }
          } else {
            candidates.addAll(acis);
          }
@@ -414,7 +411,7 @@
  /**
   * Rename all ACIs under the specified old DN to the new DN. A simple
   * interation over the entire list is performed.
   * interaction over the entire list is performed.
   * @param oldDN The DN of the original entry that was moved.
   * @param newDN The DN of the new entry.
   */
opends/src/server/org/opends/server/authorization/dseecompat/AuthMethod.java
@@ -23,23 +23,21 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
import org.opends.messages.Message;
import static org.opends.messages.AccessControlMessages.*;
import static org.opends.server.loggers.ErrorLogger.*;
import org.opends.messages.Message;
import org.opends.server.core.DirectoryServer;
import static org.opends.server.loggers.ErrorLogger.logError;
/**
 * The AuthMethod class represents an authmethod bind rule keyword expression.
 */
public class AuthMethod implements KeywordBindRule {
    /*
    /**
     * Enumeration representing the authentication method.
     */
    private EnumAuthMethod authMethod=null;
@@ -49,7 +47,7 @@
     */
    private String saslMech = null;
    /*
    /**
     * Enumeration representing the bind rule operation type.
     */
    private EnumBindRuleType type=null;
@@ -110,9 +108,27 @@
     * @param evalCtx  An evaluation context to use.
     * @return  An enumeration evaluation result.
     */
    @Override
    public EnumEvalResult evaluate(AciEvalContext evalCtx) {
        EnumEvalResult matched =
             evalCtx.hasAuthenticationMethod(authMethod, saslMech);
        return matched.getRet(type, false);
    }
    /** {@inheritDoc} */
    @Override
    public String toString()
    {
      final StringBuilder sb = new StringBuilder();
      toString(sb);
      return sb.toString();
    }
    /** {@inheritDoc} */
    @Override
    public final void toString(StringBuilder buffer)
    {
      buffer.append(super.toString());
    }
}
opends/src/server/org/opends/server/authorization/dseecompat/BindRule.java
@@ -23,16 +23,18 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
import org.opends.messages.Message;
import static org.opends.messages.AccessControlMessages.*;
import static org.opends.server.authorization.dseecompat.Aci.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.opends.messages.Message;
/**
 * This class represents a single bind rule of an ACI permission-bind rule
@@ -40,78 +42,58 @@
 */
public class BindRule {
    /*
     * This hash table holds the keyword bind rule mapping.
     */
    private HashMap<String, KeywordBindRule> keywordRuleMap =
    /** This hash table holds the keyword bind rule mapping. */
    private final HashMap<String, KeywordBindRule> keywordRuleMap =
                                    new HashMap<String, KeywordBindRule>();
    /*
     * True is a boolean "not" was seen.
     */
    /** True is a boolean "not" was seen. */
    private boolean negate=false;
    /*
     * Complex bind rules have left and right values.
     */
    /** Complex bind rules have left and right values. */
    private BindRule left = null;
    private BindRule right = null;
    /*
    /**
     * Enumeration of the boolean type of the complex bind rule ("and" or "or").
     */
    private EnumBooleanTypes booleanType = null;
    /*
     * The keyword of a simple bind rule.
     */
    /** The keyword of a simple bind rule. */
    private EnumBindRuleKeyword keyword = null;
    /*
     * Regular expression group position of a bind rule keyword.
     */
    /** Regular expression group position of a bind rule keyword. */
    private static final int keywordPos = 1;
    /*
     * Regular expression group position of a bind rule operation.
     */
    /** Regular expression group position of a bind rule operation. */
    private static final int opPos = 2;
    /*
     * Regular expression group position of a bind rule expression.
     */
    /** Regular expression group position of a bind rule expression. */
    private static final int expressionPos = 3;
    /*
    /**
     * Regular expression group position of the remainder part of an operand.
     */
    private static final int remainingOperandPos = 1;
    /*
     * Regular expression group position of the remainder of the bind rule.
     */
    /** Regular expression group position of the remainder of the bind rule. */
    private static final int remainingBindrulePos = 2;
    /*
     * Regular expression for valid bind rule operator group.
     */
    /** Regular expression for valid bind rule operator group. */
    private static final String opRegGroup = "([!=<>]+)";
    /*
    /**
     * Regular expression for the expression part of a partially parsed
     * bind rule.
     */
    private static final String expressionRegex =
                                  "\"([^\"]+)\"" + ZERO_OR_MORE_WHITESPACE;
    /*
     * Regular expression for a single bind rule.
     */
    /** Regular expression for a single bind rule. */
    private static final String bindruleRegex =
        WORD_GROUP_START_PATTERN + ZERO_OR_MORE_WHITESPACE +
        opRegGroup + ZERO_OR_MORE_WHITESPACE + expressionRegex;
    /*
    /**
     * Regular expression of the remainder part of a partially parsed bind rule.
     */
    private static final String remainingBindruleRegex =
@@ -588,4 +570,28 @@
            ret=evalComplex(left.evaluate(evalCtx),right.evaluate(evalCtx));
        return EnumEvalResult.negateIfNeeded(ret, negate);
    }
    /** {@inheritDoc} */
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        toString(sb);
        return sb.toString();
    }
    /**
     * Appends a string representation of this object to the provided buffer.
     *
     * @param buffer
     *          The buffer into which a string representation of this object
     *          should be appended.
     */
    public final void toString(StringBuilder buffer) {
        if (this.keywordRuleMap != null) {
            for (KeywordBindRule rule : this.keywordRuleMap.values()) {
                rule.toString(buffer);
                buffer.append(";");
            }
        }
    }
}
opends/src/server/org/opends/server/authorization/dseecompat/DNS.java
@@ -23,54 +23,46 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
import org.opends.messages.Message;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.messages.AccessControlMessages.*;
import static org.opends.server.authorization.dseecompat.Aci.*;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.util.StaticUtils.*;
import org.opends.server.loggers.debug.DebugTracer;
import java.net.InetAddress;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.opends.messages.Message;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.types.DebugLogLevel;
/**
 * This class implements the dns bind rule keyword.
 */
public class DNS implements KeywordBindRule {
  /**
   * The tracer object for the debug logger.
   */
  private static final DebugTracer TRACER = getTracer();
    /** List of patterns to match against. */
    private List<String> patterns = null;
    /*
     * List of patterns to match against.
     */
    LinkedList<String> patterns=null;
    /*
     * The enumeration representing the bind rule type of the DNS rule.
     */
    /** The enumeration representing the bind rule type of the DNS rule. */
    private EnumBindRuleType type=null;
    /*
     *  Regular expression group used to match a dns rule.
     */
    /** 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.
     */
    /** Regular expression group used to match one or more DNS values. */
    private static final String valuesRegExGroup =
            valueRegex + ZERO_OR_MORE_WHITESPACE +
            "(," +  ZERO_OR_MORE_WHITESPACE  +  valueRegex  +  ")*";
@@ -80,7 +72,7 @@
     * @param patterns List of dns patterns to match against.
     * @param type An enumeration representing the bind rule type.
     */
    DNS(LinkedList<String> patterns, EnumBindRuleType type) {
    DNS(List<String> patterns, EnumBindRuleType type) {
        this.patterns=patterns;
        this.type=type;
    }
@@ -100,7 +92,7 @@
            Message message = WARN_ACI_SYNTAX_INVALID_DNS_EXPRESSION.get(expr);
            throw new AciException(message);
        }
        LinkedList<String>dns=new LinkedList<String>();
        List<String> dns = new LinkedList<String>();
        int valuePos = 1;
        Pattern valuePattern = Pattern.compile(valueRegex);
        Matcher valueMatcher = valuePattern.matcher(expr);
@@ -181,6 +173,7 @@
     * @param evalCtx  An evaluation context to use in the evaluation.
     * @return An enumeration evaluation result.
     */
    @Override
    public EnumEvalResult evaluate(AciEvalContext evalCtx) {
        EnumEvalResult matched=EnumEvalResult.FALSE;
        String[] remoteHost = evalCtx.getHostName().split("\\.", -1);
@@ -226,4 +219,19 @@
                return false;
      return true;
    }
    /** {@inheritDoc} */
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        toString(sb);
        return sb.toString();
    }
    /** {@inheritDoc} */
    @Override
    public final void toString(StringBuilder buffer) {
        buffer.append(super.toString());
    }
}
opends/src/server/org/opends/server/authorization/dseecompat/DayOfWeek.java
@@ -23,29 +23,28 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
import org.opends.messages.Message;
import static org.opends.messages.AccessControlMessages.*;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.LinkedList;
import java.util.List;
import org.opends.messages.Message;
/**
 * This class implements the dayofweek bind rule keyword.
 */
public class DayOfWeek  implements KeywordBindRule {
    /*
     * List containing the enumeration of the day of the week.
     */
    LinkedList<EnumDayOfWeek> days=null;
    /** List containing the enumeration of the day of the week. */
    private List<EnumDayOfWeek> days = null;
    /*
     * Enumeration representing the bind rule operation type.
     */
    /** Enumeration representing the bind rule operation type. */
    private EnumBindRuleType type=null;
    /**
@@ -53,7 +52,7 @@
     * @param days  A list of day of the week enumerations.
     * @param type An enumeration representing the bind rule type.
     */
    private DayOfWeek(LinkedList<EnumDayOfWeek> days, EnumBindRuleType type) {
    private DayOfWeek(List<EnumDayOfWeek> days, EnumBindRuleType type) {
        this.days=days;
        this.type=type;
    }
@@ -69,11 +68,11 @@
    public static KeywordBindRule decode(String expr, EnumBindRuleType type)
    throws AciException
    {
        LinkedList<EnumDayOfWeek>days=new LinkedList<EnumDayOfWeek>();
        List<EnumDayOfWeek> days = new LinkedList<EnumDayOfWeek>();
        String[] dayArray=expr.split(",", -1);
        for(int i=0, m=dayArray.length; i < m; i++)
        for (String element : dayArray)
        {
          EnumDayOfWeek day=EnumDayOfWeek.createDayOfWeek(dayArray[i]);
          EnumDayOfWeek day=EnumDayOfWeek.createDayOfWeek(element);
          if (day == null)
          {
              Message message = WARN_ACI_SYNTAX_INVALID_DAYOFWEEK.get(expr);
@@ -90,6 +89,7 @@
     * @param evalCtx  An evaluation context to use in the evaluation.
     * @return An enumeration evaluation result.
     */
    @Override
    public EnumEvalResult evaluate(AciEvalContext evalCtx) {
        EnumEvalResult matched=EnumEvalResult.FALSE;
        GregorianCalendar calendar = new GregorianCalendar();
@@ -99,4 +99,21 @@
            matched=EnumEvalResult.TRUE;
        return matched.getRet(type, false);
    }
    /** {@inheritDoc} */
    @Override
    public String toString()
    {
      final StringBuilder sb = new StringBuilder();
      toString(sb);
      return sb.toString();
    }
    /** {@inheritDoc} */
    @Override
    public final void toString(StringBuilder buffer)
    {
      buffer.append(super.toString());
    }
}
opends/src/server/org/opends/server/authorization/dseecompat/EnumBindRuleType.java
@@ -23,8 +23,8 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
/**
@@ -63,9 +63,7 @@
     */
    GREATER_OR_EQUAL_BINDRULE_TYPE  (">=");
    /*
     * The bind rule type name.
     */
    /** The bind rule type name. */
    private final String type;
    /**
@@ -77,6 +75,16 @@
    }
    /**
     * Returns the comparison operator corresponding to this EnumBindRuleType.
     *
     * @return the string representing the comparison operator
     */
    public String getType()
    {
      return type;
    }
    /**
     * Checks to see if the type string is equal to the enumeration type
     * name.
     * @param type  The type name to check equality for.
opends/src/server/org/opends/server/authorization/dseecompat/EnumRight.java
@@ -23,11 +23,15 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
import static org.opends.server.authorization.dseecompat.Aci.*;
import java.util.EnumSet;
import java.util.Set;
/**
 * This class provides an enumeration of the allowed rights.
 */
@@ -89,7 +93,7 @@
     */
    ADDWRITE    ("addwrite");
    /*
    /**
     * The name of the right.
     */
    private final String right;
@@ -103,6 +107,15 @@
    }
    /**
     * Returns the string representation of the right.
     *
     * @return the string representation of the right
     */
    public String getRight() {
        return right;
    }
    /**
     * Checks if the enumeration is equal to the right name.
     * @param right The name of the right to check.
     * @return  True if the right is equal to the enumeration's.
@@ -171,4 +184,53 @@
        }
        return mask;
    }
    /**
     * Return the EnumRight corresponding to the provided rightsMask.
     *
     * @param rightsMask
     *          the rights mask for which to return the corresponding EnumRight
     * @return EnumRight corresponding to the provided rightsMask.
     */
    public static Set<EnumRight> getEnumRight(int rightsMask) {
        if (hasRights(rightsMask, ACI_ALL))
            return EnumSet.of(ALL);
        final EnumSet<EnumRight> results = EnumSet.noneOf(EnumRight.class);
        if (hasRights(rightsMask, ACI_READ))
            results.add(READ);
        if (hasRights(rightsMask, ACI_WRITE))
            results.add(WRITE);
        if (hasRights(rightsMask, ACI_ADD))
            results.add(ADD);
        if (hasRights(rightsMask, ACI_DELETE))
            results.add(DELETE);
        if (hasRights(rightsMask, ACI_SEARCH))
            results.add(SEARCH);
        if (hasRights(rightsMask, ACI_COMPARE))
            results.add(COMPARE);
        if (hasRights(rightsMask, ACI_EXPORT))
            results.add(EXPORT);
        if (hasRights(rightsMask, ACI_IMPORT))
            results.add(IMPORT);
        if (hasRights(rightsMask, ACI_PROXY))
            results.add(PROXY);
        if (hasRights(rightsMask, ACI_SELF))
            results.add(SELFWRITE);
        return results;
    }
    /**
     * Checks if the provided rights mask has the specified rights.
     *
     * @param rightsMask
     *          The rights mask to look into.
     * @param rights
     *          The rights to check for.
     * @return true if the rights mask has the specified rights, false
     *           otherwise.
     */
    public static boolean hasRights(int rightsMask, int rights) {
        return (rightsMask & rights) == rights;
    }
}
opends/src/server/org/opends/server/authorization/dseecompat/GroupDN.java
@@ -23,37 +23,33 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
import org.opends.messages.Message;
import static org.opends.messages.AccessControlMessages.*;
import static org.opends.server.authorization.dseecompat.Aci.*;
import org.opends.server.types.*;
import org.opends.server.api.Group;
import org.opends.server.core.GroupManager;
import org.opends.server.core.DirectoryServer;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.opends.messages.Message;
import org.opends.server.api.Group;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.GroupManager;
import org.opends.server.types.*;
/**
 * This class implements the groupdn bind rule keyword.
 */
public class GroupDN implements KeywordBindRule {
    /*
     * List of group DNs.
     */
    LinkedList<DN> groupDNs=null;
    /** List of group DNs. */
    private List<DN> groupDNs = null;
    /*
     * Enumeration representing the groupdn operator type.
     */
    /** Enumeration representing the groupdn operator type. */
    private EnumBindRuleType type=null;
    /**
@@ -69,7 +65,7 @@
     * @param type An enumeration representing the bind rule type.
     * @param groupDNs A list of the dns representing groups.
     */
    private GroupDN(EnumBindRuleType type, LinkedList<DN> groupDNs ) {
    private GroupDN(EnumBindRuleType type, List<DN> groupDNs ) {
        this.groupDNs=groupDNs;
        this.type=type;
    }
@@ -89,7 +85,7 @@
                WARN_ACI_SYNTAX_INVALID_GROUPDN_EXPRESSION.get(expr);
            throw new AciException(message);
        }
        LinkedList<DN>groupDNs=new LinkedList<DN>();
        List<DN> groupDNs = new LinkedList<DN>();
        int ldapURLPos = 1;
        Pattern ldapURLPattern = Pattern.compile(LDAP_URL);
        Matcher ldapURLMatcher = ldapURLPattern.matcher(expr);
@@ -115,14 +111,15 @@
     * @param evalCtx  An evaluation context to use  in the evaluation.
     * @return  Enumeration evaluation result.
     */
    @Override
    public EnumEvalResult evaluate(AciEvalContext evalCtx) {
        EnumEvalResult matched = EnumEvalResult.FALSE;
       Iterator<DN> it=groupDNs.iterator();
        for(; it.hasNext() && matched != EnumEvalResult.TRUE;) {
            DN  groupDN=it.next();
        for (DN groupDN : groupDNs) {
            Group<?> group = getGroupManager().getGroupInstance(groupDN);
            if((group != null) && (evalCtx.isMemberOf(group)))
            if((group != null) && (evalCtx.isMemberOf(group))) {
               matched = EnumEvalResult.TRUE;
               break;
            }
        }
        return matched.getRet(type, false);
    }
@@ -167,4 +164,19 @@
    private static GroupManager getGroupManager() {
        return DirectoryServer.getGroupManager();
    }
    /** {@inheritDoc} */
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        toString(sb);
        return sb.toString();
    }
    /** {@inheritDoc} */
    @Override
    public final void toString(StringBuilder buffer) {
        buffer.append(super.toString());
    }
}
opends/src/server/org/opends/server/authorization/dseecompat/IP.java
@@ -23,8 +23,8 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
import org.opends.messages.Message;
@@ -41,23 +41,21 @@
 */
public class IP implements KeywordBindRule {
    /*
      Regular expression used to do a quick check on the characters in a
      bind rule address. These are all of the valid characters that may
      appear in an bind rule address part.
    /**
     * Regular expression used to do a quick check on the characters in a
     * bind rule address. These are all of the valid characters that may
     * appear in an bind rule address part.
    */
    private  static final String ipRegEx =
            "((?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.
    /**
     * List of the pattern classes, one for each address decoded from the bind
     * rule.
    */
    private List<PatternIP> patternIPList=null;
    /*
      The type of the bind rule (!= or =).
     */
    /** The type of the bind rule (!= or =). */
    private EnumBindRuleType type=null;
    /**
@@ -129,4 +127,19 @@
        }
        return matched.getRet(type, false);
    }
    /** {@inheritDoc} */
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        toString(sb);
        return sb.toString();
    }
    /** {@inheritDoc} */
    @Override
    public final void toString(StringBuilder buffer) {
        buffer.append(super.toString());
    }
}
opends/src/server/org/opends/server/authorization/dseecompat/KeywordBindRule.java
@@ -23,8 +23,8 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
/**
@@ -41,4 +41,13 @@
     * @return An enumeration evaluation result.
     */
    public EnumEvalResult evaluate(AciEvalContext evalCtx);
    /**
     * Appends a string representation of this object to the provided buffer.
     *
     * @param buffer
     *          The buffer into which a string representation of this object
     *          should be appended.
     */
    void toString(StringBuilder buffer);
}
opends/src/server/org/opends/server/authorization/dseecompat/PermBindRulePair.java
@@ -23,8 +23,8 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
/**
@@ -33,14 +33,10 @@
 */
public class PermBindRulePair {
    /*
     * The Bind Rule part.
     */
    /** The Bind Rule part. */
    private BindRule bindRule;
    /*
     * The permission part.
     */
    /** The permission part. */
    private Permission perm=null;
    /**
@@ -97,4 +93,30 @@
    public boolean hasRights(int right) {
        return perm.hasRights(right);
    }
    /** {@inheritDoc} */
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        toString(sb);
        return sb.toString();
    }
    /**
     * Appends a string representation of this object to the provided buffer.
     *
     * @param buffer
     *          The buffer into which a string representation of this object
     *          should be appended.
     */
    public final void toString(StringBuilder buffer) {
        if (this.perm != null) {
            this.perm.toString(buffer);
        }
        buffer.append(" ");
        if (this.bindRule != null) {
            this.bindRule.toString(buffer);
        }
        buffer.append(")"); // not sure why, but we need this extra parenthesis
    }
}
opends/src/server/org/opends/server/authorization/dseecompat/Permission.java
@@ -23,38 +23,41 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
import org.opends.messages.Message;
import static org.opends.messages.AccessControlMessages.*;
import static org.opends.server.authorization.dseecompat.Aci.*;
import java.util.Iterator;
import java.util.Set;
import java.util.regex.Pattern;
import org.opends.messages.Message;
/**
 * A class representing the permissions of an bind rule. The permissions
 * of an ACI look like deny(search, write).
 */
public class Permission {
    /*
    /**
     *  The access type (allow,deny) corresponding to the ACI permission value.
     */
    private EnumAccessType accessType = null;
    /*
    /**
     * The rights (search, add, delete, ...) corresponding to the ACI rights
     * value.
     */
    private int rights;
    /*
    /**
     * Regular expression token representing the separator.
     */
    private static final String separatorToken = ",";
    /*
    /**
     * Regular expression used to match the ACI rights string.
     */
    private static final String rightsRegex = ZERO_OR_MORE_WHITESPACE +
@@ -108,8 +111,7 @@
     * rule.
     * @throws AciException  If the accesstype or rights strings are invalid.
     */
    public static
    Permission decode (String accessType, String rights)
    public static Permission decode (String accessType, String rights)
    throws AciException {
        return new Permission(accessType, rights);
    }
@@ -132,4 +134,39 @@
    public boolean hasRights(int rights) {
        return (this.rights & rights) != 0;
    }
    /** {@inheritDoc} */
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        toString(sb);
        return sb.toString();
    }
    /**
     * Appends a string representation of this object to the provided buffer.
     *
     * @param buffer
     *          The buffer into which a string representation of this object
     *          should be appended.
     */
    public final void toString(StringBuilder buffer) {
        if (this.accessType != null) {
            buffer.append(accessType.toString().toLowerCase());
            Set<EnumRight> enumRights = EnumRight.getEnumRight(rights);
            if (enumRights != null) {
                buffer.append("(");
                for (Iterator<EnumRight> iter = enumRights.iterator(); iter
                        .hasNext();) {
                    buffer.append(iter.next().getRight());
                    if (iter.hasNext()) {
                        buffer.append(",");
                    }
                }
                buffer.append(")");
            } else {
                buffer.append("(all)");
            }
        }
    }
}
opends/src/server/org/opends/server/authorization/dseecompat/SSF.java
@@ -23,8 +23,8 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
import org.opends.messages.Message;
@@ -33,13 +33,10 @@
/**
 * 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.
     */
    /** Enumeration representing the bind rule operation type. */
    private EnumBindRuleType type=null;
    private static final int MAX_KEY_BITS=1024;
@@ -58,8 +55,7 @@
     * @return A SSF instance.
     * @throws AciException If the SSF instance cannot be created.
     */
    static SSF
    decode(String expr, EnumBindRuleType type) throws AciException  {
    static SSF decode(String expr, EnumBindRuleType type) throws AciException {
        int valueAsInt = 0;
        try {
            valueAsInt = Integer.parseInt(expr);
@@ -113,4 +109,21 @@
        }
        return matched.getRet(type, false);
    }
    /** {@inheritDoc} */
    @Override
    public String toString()
    {
        final StringBuilder sb = new StringBuilder();
        toString(sb);
        return sb.toString();
    }
    /** {@inheritDoc} */
    @Override
    public final void toString(StringBuilder buffer)
    {
        buffer.append(super.toString());
    }
}
opends/src/server/org/opends/server/authorization/dseecompat/TargAttrFilterList.java
@@ -23,20 +23,22 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
import org.opends.messages.Message;
import org.opends.server.types.AttributeType;
import org.opends.server.types.SearchFilter;
import org.opends.server.types.DirectoryException;
import org.opends.server.core.DirectoryServer;
import static org.opends.messages.AccessControlMessages.*;
import static org.opends.server.authorization.dseecompat.Aci.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.LinkedHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.opends.messages.Message;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.SearchFilter;
/**
 * The TargAttrFilterList class represents an targattrfilters list. A
@@ -46,40 +48,40 @@
 */
public class TargAttrFilterList {
    /*
     * The mask coresponding to the operation of this list (add or del).
  /**
   * The mask corresponding to the operation of this list (add or del).
     */
    private int mask=0;
    /*
  /**
     * ListHashMap keyed by the attribute type and mapping to the corresponding
     * search filter. LinkedHashMap is used so everything is in order.
     */
    private LinkedHashMap<AttributeType, SearchFilter> attrFilterList;
    /*
  /**
     * Regular expression group count.
     */
    private static int expectedGroupCount=2;
    /*
  /**
     * Regular expression attribute group position.
     */
    private static int attributePos=1;
    /*
  /**
     * Regular expression filter group position.
     */
    private static int filterPos=2;
    /*
     * Regular expression used to match a filter list including the strange
     * "and" token used to join the multiple attribute type filter pairs.
  /**
   * Regular expression used to match a filter list including the strange "and"
   * token used to join the multiple attribute type filter pairs.
     */
    private static final String filterListSeperator =
              ZERO_OR_MORE_WHITESPACE  + "&&" + ZERO_OR_MORE_WHITESPACE;
    /*
  /**
     * Regular expression used to match an attribute filter pair.
     */
    private static final String attributeFilter=
opends/src/server/org/opends/server/authorization/dseecompat/TargAttrFilters.java
@@ -23,51 +23,51 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
import org.opends.messages.Message;
import static org.opends.messages.AccessControlMessages.*;
import static org.opends.server.authorization.dseecompat.Aci.*;
import org.opends.server.types.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.opends.messages.Message;
import org.opends.server.types.*;
/**
 * 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.
     */
    TargAttrFilterList firstFilterList=null;
    TargAttrFilterList secondFilterList=null;
    private TargAttrFilterList firstFilterList = null;
    private TargAttrFilterList secondFilterList = null;
    /*
    /**
     * Regular expression group position for the first operation value.
     */
    private static final int firstOpPos = 1;
    /*
    /**
     * Regular expression group position for the rest of an partially parsed
     * rule.
     */
    private static final int restOfExpressionPos=2;
    /*
    /**
     * Regular expression used to match the operation group (either add or del).
     */
    private static final String ADD_OR_DEL_KEYWORD_GROUP = "(add|del)";
    /*
    /**
     * Regular expression used to check for valid expression separator.
     */
    private static final
    String secondOpSeparator="\\)" +  ZERO_OR_MORE_WHITESPACE + ",";
@@ -80,31 +80,31 @@
            "[,]{1}" + ZERO_OR_MORE_WHITESPACE + "del|add" +
            ZERO_OR_MORE_WHITESPACE + EQUAL_SIGN + ZERO_OR_MORE_WHITESPACE;
    /*
    /**
     * Regular expression used to match the first targFilterList, it must exist
     * or an exception is thrown.
     */
    private static final String firstOp = "^" + ADD_OR_DEL_KEYWORD_GROUP +
            ZERO_OR_MORE_WHITESPACE + EQUAL_SIGN + ZERO_OR_MORE_WHITESPACE;
    /*
    /**
     * Regular expression used to group the remainder of a partially parsed
     * rule.  Any character one or more times.
     */
    private static String restOfExpression = "(.+)";
    /*
    /**
     * Regular expression used to match the first operation keyword and the
     * rest of the expression.
     */
    private static String keywordFullPattern = firstOp + restOfExpression;
    /*
    /**
     * The enumeration representing the operation.
     */
    EnumTargetOperator op;
    /*
    /**
     * A mask used to denote if the rule has add, del or both operations in the
     * composite TargFilterList parts.
     */
opends/src/server/org/opends/server/authorization/dseecompat/TimeOfDay.java
@@ -23,8 +23,8 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
import org.opends.messages.Message;
@@ -37,19 +37,15 @@
 */
public class TimeOfDay implements KeywordBindRule {
    /*
    /**
     * Regular expression matching a valid timeofday rule value (0-2359).
     */
    private static final String timeofdayRegex = "[0-2]\\d[0-5]\\d";
    /*
     *  Enumeration representing the bind rule operation type.
     */
    /** Enumeration representing the bind rule operation type. */
    private EnumBindRuleType type=null;
    /*
     * Holds the time value parsed from the ACI.
     */
    /** Holds the time value parsed from the ACI. */
    private int timeRef;
    /**
@@ -143,4 +139,21 @@
        }
        return matched.getRet(type, false);
    }
    /** {@inheritDoc} */
    @Override
    public String toString()
    {
        final StringBuilder sb = new StringBuilder();
        toString(sb);
        return sb.toString();
    }
    /** {@inheritDoc} */
    @Override
    public final void toString(StringBuilder buffer)
    {
        buffer.append(super.toString());
    }
}
opends/src/server/org/opends/server/authorization/dseecompat/UserAttr.java
@@ -23,20 +23,22 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2011 ForgeRock AS
 *      Portions Copyright 2011-2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
import org.opends.messages.Message;
import static org.opends.messages.AccessControlMessages.*;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import org.opends.messages.Message;
import org.opends.server.core.DirectoryServer;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.types.*;
/*
 * TODO Evaluate making this class more efficient.
 *
@@ -58,36 +60,28 @@
        USERDN, GROUPDN, ROLEDN, URL, VALUE
    }
    /*
     * Filter used in  internal search.
     */
    /** Filter used internal search. */
    private static SearchFilter filter;
    /*
    /**
     * Used to create an attribute type that can compare the value below in
     * an entry returned from an internal search.
     */
    private  String attrStr=null;
    /*
    /**
     * Used to compare a attribute value returned from a search against this
     * value which might have been defined in the ACI userattr rule.
     */
    private  String attrVal=null;
    /*
     * Contains the type of the userattr, one of the above enumerations.
     */
    /** Contains the type of the userattr, one of the above enumerations. */
    private UserAttrType userAttrType=null;
    /*
     * An enumeration representing the bind rule type.
     */
    /** An enumeration representing the bind rule type. */
    private EnumBindRuleType type=null;
    /*
     * The class used to hold the parent inheritance information.
     */
    /** The class used to hold the parent inheritance information. */
    private ParentInheritance parentInheritance=null;
    static {
@@ -174,6 +168,7 @@
     * userattr expression.
     * @return  An enumeration containing the result of the evaluation.
     */
    @Override
    public EnumEvalResult evaluate(AciEvalContext evalCtx) {
      EnumEvalResult matched;
      //The working resource entry might be filtered and not have an
@@ -416,4 +411,20 @@
        return result;
    }
    /** {@inheritDoc} */
    @Override
    public String toString()
    {
        final StringBuilder sb = new StringBuilder();
        toString(sb);
        return sb.toString();
    }
    /** {@inheritDoc} */
    @Override
    public final void toString(StringBuilder buffer)
    {
        buffer.append(super.toString());
    }
}
opends/src/server/org/opends/server/authorization/dseecompat/UserDN.java
@@ -23,34 +23,37 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
import org.opends.messages.Message;
import static org.opends.messages.AccessControlMessages.*;
import java.util.*;
import org.opends.server.types.*;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.opends.messages.Message;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.*;
/**
 * 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 String urlStr="ldap:///";
    /*
    /**
     * This list holds a list of objects representing a EnumUserDNType
     * URL mapping.
     */
    private List<UserDNTypeURL> urlList=null;
    /*
     * Enumeration of the userdn operation type.
     */
    /** Enumeration of the userdn operation type. */
    private EnumBindRuleType type=null;
    /**
@@ -78,9 +81,9 @@
        String[] vals=expression.split("[|][|]");
        List<UserDNTypeURL> urlList = new LinkedList<UserDNTypeURL>();
         for(int i=0, m=vals.length; i < m; i++)
        for (String val : vals)
        {
            StringBuilder value = new StringBuilder(vals[i].trim());
            StringBuilder value = new StringBuilder(val.trim());
           /*
            * TODO Evaluate using a wild-card in the dn portion of LDAP url.
            * The current implementation (DS6) does not treat a "*"
@@ -174,6 +177,7 @@
     * @return  An evaluation result enumeration containing the result
     * of the evaluation.
     */
    @Override
    public EnumEvalResult evaluate(AciEvalContext evalCtx) {
        EnumEvalResult matched = EnumEvalResult.FALSE;
        boolean undefined=false;
@@ -372,4 +376,26 @@
        }
        return matched;
    }
    /** {@inheritDoc} */
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        toString(sb);
        return sb.toString();
    }
    /** {@inheritDoc} */
    @Override
    public final void toString(StringBuilder buffer) {
        buffer.append("userdn");
        buffer.append(this.type.getType());
        for (UserDNTypeURL url : this.urlList) {
            buffer.append("\"");
            buffer.append(urlStr);
            buffer.append(url.getUserDNType().toString().toLowerCase());
            buffer.append("\"");
        }
    }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciBodyTest.java
New file
@@ -0,0 +1,58 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Copyright 2013 ForgeRock AS
 */
package org.opends.server.authorization.dseecompat;
import static org.assertj.core.api.Assertions.*;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@SuppressWarnings("javadoc")
public class AciBodyTest extends AciTestCase
{
  @DataProvider(name = "validAcis")
  public Object[][] getValidAcis()
  {
    return new Object[][] {
      { "(version 3.0; acl \"Anonymous extended operation access\"; deny(all) userdn=\"ldap:///anyone\";)" },
      { "(version 3.0; acl \"Anonymous extended operation access\"; allow(read) userdn=\"ldap:///anyone\";)" },
      { "(version 3.0; acl \"Self entry modification\"; allow(write) userdn=\"ldap:///self\";)" },
      { "(version 3.0; acl \"Self entry read\"; allow(read,search,compare) userdn=\"ldap:///self\";)" },
      { "(version 3.0; acl \"Anonymous read access\"; allow(read,search,compare) userdn=\"ldap:///anyone\";)" },
      { "(version 3.0; acl \"Anonymous control access\"; allow(read) userdn=\"ldap:///anyone\";)" },
      { "(version 3.0; acl \"Authenticated users control access\"; allow(read) userdn=\"ldap:///all\";)" }, };
  }
  @Test(dataProvider = "validAcis")
  public void decodeValidAci(String aci) throws Exception
  {
    AciBody aciBody = AciBody.decode(aci);
    assertThat(aciBody.toString()).isEqualTo(aci);
    assertThat(aciBody.getPermBindRulePairs()).hasSize(1);
  }
}