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

dugan
16.59.2007 09b2bb485c8939161985e4542ec791b695e88ed9
Fix userattr bind rule GROUPDN keyword when using a  url search failure . Issue 1596.
6 files modified
169 ■■■■■ changed files
opends/src/server/org/opends/server/authorization/dseecompat/GroupDN.java 8 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/ParentInheritance.java 55 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/UserAttr.java 17 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/messages/AciMessages.java 47 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTestCase.java 3 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/TargetAttrTestCase.java 39 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/GroupDN.java
@@ -143,16 +143,22 @@
     * @param evalCtx  The evaluation context to use in the evaluation.
     * @param attributeType The attribute type of the entry to use to get the
     * values for the groupd DNs.
     * @param suffixDN The suffix that the groupDN must be under. If it's null,
     *                 then the groupDN can be anywhere in the DIT.
     * @return Enumeration evaluation result.
     */
    public static EnumEvalResult evaluate (Entry e, AciEvalContext evalCtx,
                                           AttributeType attributeType) {
                                           AttributeType attributeType,
                                           DN suffixDN) {
        EnumEvalResult matched= EnumEvalResult.FALSE;
        List<Attribute> attrs = e.getAttribute(attributeType);
        LinkedHashSet<AttributeValue> vals = attrs.get(0).getValues();
        for(AttributeValue v : vals) {
            try {
                DN groupDN=DN.decode(v.getStringValue());
                if(suffixDN != null &&
                   !groupDN.isDescendantOf(suffixDN))
                        continue;
                Group group = groupManager.getGroupInstance(groupDN);
                if((group != null) && (evalCtx.isMemberOf(group))) {
                    matched=EnumEvalResult.TRUE;
opends/src/server/org/opends/server/authorization/dseecompat/ParentInheritance.java
@@ -31,11 +31,15 @@
import static org.opends.server.authorization.dseecompat.Aci.*;
import static org.opends.server.messages.MessageHandler.getMessage;
import java.util.StringTokenizer;
import java.util.LinkedHashSet;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
import org.opends.server.types.LDAPURL;
import org.opends.server.types.DirectoryException;
/**
 * This class is used by USERDN and GROUPDN userattr types
@@ -75,6 +79,13 @@
     */
    private String attrTypeStr;
    /*
     * The base DN of a URL parsed from the rule. Used to make sure groupdn
     * are under this suffix. Originally a way to search all nested groups
     * under this suffix, so the behavior is slightly different.
     */
    private DN baseDN=null;
    /**
     * Construct a class from the inheritance pattern. The skipParsing boolean
@@ -181,12 +192,35 @@
                }
            }
        } else {
            if((this.attributeType =
                DirectoryServer.getAttributeType(pattern)) == null)
                this.attributeType =
                    DirectoryServer.getDefaultAttributeType(pattern);
            numLevels=1;
            levels[0]=0;
          attrTypeStr=pattern;
          if(pattern.startsWith(NULL_LDAP_URL)) {
            try {
              LDAPURL url=LDAPURL.decode(pattern, true);
              LinkedHashSet<String>attrs=url.getAttributes();
              if(attrs.size() != 1) {
                int msgID = MSGID_ACI_SYNTAX_INVALID_USERATTR_ATTR_URL;
                String message = getMessage(msgID, pattern);
                throw new AciException(msgID, pattern);
              }
              baseDN=url.getBaseDN();
              if(baseDN.isNullDN()){
                int msgID = MSGID_ACI_SYNTAX_INVALID_USERATTR_BASEDN_URL;
                String message = getMessage(msgID, pattern);
                throw new AciException(msgID, message);
              }
              attrTypeStr=attrs.iterator().next();
            } catch (DirectoryException ex) {
              int msgID = MSGID_ACI_SYNTAX_INVALID_USERATTR_URL;
              String message = getMessage(msgID, ex.getErrorMessage());
              throw new AciException(msgID, message);
            }
          }
          if((this.attributeType =
                  DirectoryServer.getAttributeType(attrTypeStr)) == null)
            this.attributeType =
                    DirectoryServer.getDefaultAttributeType(attrTypeStr);
          numLevels=1;
          levels[0]=0;
        }
    }
@@ -221,5 +255,14 @@
    public String getAttrTypeStr() {
        return attrTypeStr;
    }
  /**
   * Return the DN that groupdn must be under.
   *
   * @return DN that groupdn must be under.
   */
  public DN getBaseDN() {
      return baseDN;
    }
}
opends/src/server/org/opends/server/authorization/dseecompat/UserAttr.java
@@ -323,6 +323,12 @@
        int numLevels=parentInheritance.getNumLevels();
        int[] levels=parentInheritance.getLevels();
        AttributeType attrType=parentInheritance.getAttributeType();
        DN baseDN=parentInheritance.getBaseDN();
        if(baseDN != null) {
            if (evalCtx.getResourceEntry().hasAttribute(attrType))
                matched=GroupDN.evaluate(evalCtx.getResourceEntry(),
                        evalCtx,attrType, baseDN);
        } else {
        for(int i=0;((i < numLevels) && !stop); i++ ) {
            //The ROLEDN keyword will always enter this statement. The others
            //might. For the add operation, the resource itself (level 0)
@@ -332,9 +338,9 @@
                    undefined=true;
                } else if (evalCtx.getResourceEntry().hasAttribute(attrType)) {
                    matched =
                        evalEntryAttr(evalCtx.getResourceEntry(),
                                evalCtx,attrType);
                   if(matched.equals(EnumEvalResult.TRUE))
                            evalEntryAttr(evalCtx.getResourceEntry(),
                                    evalCtx,attrType);
                    if(matched.equals(EnumEvalResult.TRUE))
                        stop=true;
                }
            } else {
@@ -362,7 +368,8 @@
                }
            }
        }
        return matched.getRet(type, undefined);
    }
    return matched.getRet(type, undefined);
    }
    /**
@@ -405,7 +412,7 @@
                break;
            }
            case GROUPDN: {
                result=GroupDN.evaluate(e, evalCtx, attributeType);
                result=GroupDN.evaluate(e, evalCtx, attributeType, null);
                break;
            }
        }
opends/src/server/org/opends/server/messages/AciMessages.java
@@ -778,6 +778,35 @@
    /**
     * The message ID for the message that will be used if an "aci" attribute
     * type value parse failed because a bind rule userattr LDAP URL failed
     * to decode.  This takes one argument the message from the LDAP
     * URL decode DirectoryException.
     */
    public static final int MSGID_ACI_SYNTAX_INVALID_USERATTR_URL =
        CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 78;
    /**
     * The message ID for the message that will be used if an "aci" attribute
     * type value parse failed because a bind rule userattr LDAP URL contained
     * a null base DN.  This takes one argument the ldap URL from the bind rule
     * expression.
     */
    public static final int MSGID_ACI_SYNTAX_INVALID_USERATTR_BASEDN_URL =
        CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 79;
    /**
     * The message ID for the message that will be used if an "aci" attribute
     * type value parse failed because a bind rule userattr LDAP URL attribute
     * field either contained more than one attribute or the field was null.
     * This takes one argument the ldap URL from the bind rule expression.
     */
    public static final int MSGID_ACI_SYNTAX_INVALID_USERATTR_ATTR_URL =
        CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 80;
    /**
     * Associates a set of generic messages with the message IDs defined in
     * this class.
     */
@@ -1220,5 +1249,23 @@
                "invalid ACIs rules were detected either when the server " +
                "was started or during a backend initialization");
        registerMessage(MSGID_ACI_SYNTAX_INVALID_USERATTR_URL,
                "The provided Access Control Instruction (ACI) bind rule " +
                "userattr expression value failed to URL decode for " +
                "the following reason: %s");
        registerMessage(MSGID_ACI_SYNTAX_INVALID_USERATTR_BASEDN_URL,
                "The provided Access Control Instruction (ACI) bind rule " +
                "userattr expression value failed to parse because the " +
                "ldap URL \"%s\" contains an empty base DN");
        registerMessage(MSGID_ACI_SYNTAX_INVALID_USERATTR_ATTR_URL,
                "The provided Access Control Instruction (ACI) bind rule " +
                "userattr expression value failed to parse because the " +
                "attribute field of the ldap URL \"%s\" either contains more " +
                "than one description or the field is empty");
    }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTestCase.java
@@ -211,7 +211,7 @@
            "objectclass: top",
            "objectclass: groupOfNames",
            "cn: group",
            "member: uid=user.1,ou=People,o=test",
            "member: uid=user.3,ou=People,o=test",
            "",
            "dn: uid=superuser,ou=admins,o=test",
            "objectClass: top",
@@ -246,6 +246,7 @@
            "sn: 1",
            "cn: User1",
            "l: Austin",
            "manager: cn=group,ou=People,o=test",
            "userPassword: password",
            "",
            "dn: uid=user.2,ou=People,o=test",
opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/TargetAttrTestCase.java
@@ -46,6 +46,19 @@
  private static final
  String grpAttrAci = "(targetattr=\"*\")" +
        "(version 3.0; acl \"user attr URL example\"; " +
        "allow (search,read) " +
        "userattr=\"ldap:///ou=People,o=test?manager#GROUPDN\";)";
  private static final
  String grp1AttrAci = "(targetattr=\"*\")" +
        "(version 3.0; acl \"user attr1 URL example\"; " +
        "allow (search,read) " +
        "userattr=\"ldap:///ou=People1,o=test?manager#GROUPDN\";)";
  private static final
  String starAciAttrs = "(targetattr=\"* || aci\")" +
          "(version 3.0;acl \"read/search all user, aci op\";" +
          "allow (search, read) " +
@@ -323,6 +336,32 @@
    deleteAttrFromEntry(user1, "aci");
  }
  /**
   * Test two scenerios with userattr LDAP URL and groupdn keyword.
   *
   * @throws Exception Exception If test result is unexpected.
   */
  @Test()
  public void testTargetAttrGrpDN() throws Exception {
    String aciLdif=makeAddAciLdif("aci", user1, grpAttrAci);
    modEntries(aciLdif, DIR_MGR_DN, PWD);
    String userResults =
            LDAPSearchParams(user3, PWD, null, null, null,
                    user1, filter, attrList);
    Assert.assertFalse(userResults.equals(""));
    HashMap<String, String> attrMap=getAttrMap(userResults);
    Assert.assertTrue(attrMap.containsKey("l"));
    Assert.assertTrue(attrMap.containsKey("sn"));
    Assert.assertTrue(attrMap.containsKey("uid"));
    deleteAttrFromEntry(user1, "aci");
    String aciLdif1=makeAddAciLdif("aci", user1, grp1AttrAci);
    modEntries(aciLdif1, DIR_MGR_DN, PWD);
    String userResults1 =
            LDAPSearchParams(user3, PWD, null, null, null,
                    user1, filter, attrList);
    //This search should return nothing since the URL has a bogus DN.
    Assert.assertTrue(userResults1.equals(""));
  }
  private void
  checkAttributeVal(HashMap<String, String> attrMap, String attr,