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

Chris Ridd
01.29.2015 fe19ac2d6f1b978356b29e81901b91ae7a09daf9
OPENDJ-2312 Check rightsMask for all operations in setEval{User,Op}Attributes

During a modify operation, we need to evaluate the readability of the returned
attributes. The clauses removed from AciContainer were preventing that and
allowing anything to be returned.

Some new unit tests are added.
3 files modified
145 ■■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciContainer.java 4 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/test/java/org/opends/server/authorization/dseecompat/AciTestCase.java 57 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/test/java/org/opends/server/authorization/dseecompat/TargetAttrTestCase.java 84 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciContainer.java
@@ -805,7 +805,7 @@
  /** {@inheritDoc} */
  @Override
  public  void setEvalUserAttributes(int v) {
    if(operation instanceof SearchOperation && rightsMask == ACI_READ) {
    if(rightsMask == ACI_READ) {
      if(v == ACI_FOUND_USER_ATTR_RULE) {
        evalAllAttributes |= ACI_FOUND_USER_ATTR_RULE;
        evalAllAttributes &= ~ACI_USER_ATTR_STAR_MATCHED;
@@ -820,7 +820,7 @@
  /** {@inheritDoc} */
  @Override
  public  void setEvalOpAttributes(int v) {
    if(operation instanceof SearchOperation && rightsMask == ACI_READ) {
    if(rightsMask == ACI_READ) {
      if(v == ACI_FOUND_OP_ATTR_RULE) {
        evalAllAttributes |= ACI_FOUND_OP_ATTR_RULE;
        evalAllAttributes &= ~ACI_OP_ATTR_PLUS_MATCHED;
opendj-server-legacy/src/test/java/org/opends/server/authorization/dseecompat/AciTestCase.java
@@ -199,6 +199,47 @@
    return oStream.toString();
  }
  /**
   * Perform a modify operation, and request attributes via a preRead control.
   *
   * @param bindDn        The user to authenticate as.
   * @param bindPassword  The user's credentials.
   * @param ldif          The modification to make.
   * @param attributes    A space-separated list of attributes to return.
   *
   * @return  The output of the command.
   *
   * @throws Exception  If an unexpected problem occurred.
   */
  protected String preReadModify(String bindDn, String bindPassword,
                                 String ldif, String attributes) throws Exception
  {
    File tempFile = getTemporaryLdifFile();
    TestCaseUtils.writeFile(tempFile, ldif);
    ArrayList<String> argList=new ArrayList<>(20);
    argList.add("-h");
    argList.add("127.0.0.1");
    argList.add("-p");
    argList.add(String.valueOf(TestCaseUtils.getServerLdapPort()));
    argList.add("-D");
    argList.add(bindDn);
    argList.add("-w");
    argList.add(bindPassword);
    if (attributes != null) {
      argList.add("--preReadAttributes");
      argList.add(attributes);
    }
    argList.add("-f");
    argList.add(tempFile.getAbsolutePath());
    String[] args = new String[argList.size()];
    oStream.reset();
    int retVal =LDAPModify.mainModify(argList.toArray(args), false, oStream, oStream);
    Assert.assertEquals(retVal, 0, "Returned error: " + oStream);
    return oStream.toString();
  }
  protected String LDAPSearchCtrl(String bindDn, String bindPassword,
                            String proxyDN, String controlStr,
                            String base, String filter, String attr) {
@@ -719,8 +760,21 @@
  protected Map<String, String> getAttrMap(String resultString)
  {
    return getAttrMap(resultString, false);
  }
  /**
   * Parse a tool output for an LDIF record, returning the attributes in a Map.
   *
   * @param resultString The entire output from the operation
   * @param stripHeader  Set to {@code true} if data before the LDIF needs to be ignored
   * @return  A map of attribute-values
   */
  protected Map<String, String> getAttrMap(String resultString, boolean stripHeader)
  {
    StringReader r=new StringReader(resultString);
    BufferedReader br=new BufferedReader(r);
    boolean stripping = stripHeader;
    Map<String, String> attrMap = new HashMap<>();
    try {
      while(true) {
@@ -729,8 +783,11 @@
        {
          break;
        }
        if (stripping) {
        if(s.startsWith("dn:"))
        {
            stripping = false;
          }
          continue;
        }
        String[] a=s.split(": ");
opendj-server-legacy/src/test/java/org/opends/server/authorization/dseecompat/TargetAttrTestCase.java
@@ -122,9 +122,42 @@
          "allow (search, read) " +
          "userattr=\"l#Austin\";)";
  private static final
  String controlAci = "(targetcontrol=\"1.3.6.1.1.13.1\")" +
          "(version 3.0;acl \"use pre-read control\";" +
          "allow (read) " +
          "userdn=\"ldap:///anyone\";)";
  private static final String user3ForbiddenUserAttr = "sn";
  private static final String user3ForbiddenOperationalAttr = "createTimestamp";
  private static final String user3AllowedUserAttr = "uid";
  private static final String user3AllowedOperationalAttr = "ds-privilege-name";
  private static final String user3WritableAttr = "description";
    private static final
  String selfWriteAci = "(targetattr=\"" + user3WritableAttr + "\")" +
          "(version 3.0;acl \"self write description\";" +
          "allow (write) " +
          "userdn=\"ldap:///self\";)";
  private static final
  String selfDenyAttrReadAci = "(targetattr=\"" + user3ForbiddenUserAttr + "||" +
          user3ForbiddenOperationalAttr + "\")" +
          "(version 3.0;acl \"self deny attribute reads\";" +
          "deny (read,search) " +
          "userdn=\"ldap:///self\";)";
  private static final
  String selfReadAllAttrsAci = "(targetattr=\"*||+\")" +
          "(version 3.0; acl \"self read/search all attributes\";" +
          "allow (read,search) " +
          "userdn=\"ldap:///self\";)";
  @BeforeClass
  public void setupClass() throws Exception {
    deleteAttrFromAdminEntry(ACCESS_HANDLER_DN, ATTR_AUTHZ_GLOBAL_ACI);
    String aciLdif3 = makeAddLDIF(ATTR_AUTHZ_GLOBAL_ACI, ACCESS_HANDLER_DN, controlAci, selfWriteAci);
    LDIFModify(aciLdif3, DIR_MGR_DN, PWD);
    addEntries("o=test");
  }
@@ -217,6 +250,57 @@
  }
  /**
   * Test targetattr behaviour with modify and pre-read controls
   *
   * @throws Exception  If a test result is unexpected.
   */
  @Test
  public void testTargetAttrPreRead() throws Exception {
    String aciLdif=makeAddLDIF("aci", user3,
            controlAci, selfWriteAci, selfDenyAttrReadAci, selfReadAllAttrsAci);
    LDIFModify(aciLdif, DIR_MGR_DN, PWD);
    // sanity check that search does not return the forbidden attributes
    String searchResults =
            LDAPSearchParams(user3, PWD, null, null, null, user3, filter, "+ *");
    assertNotEquals(searchResults, "");
    Map<String, String> attrMap = getAttrMap(searchResults);
    assertFalse(attrMap.containsKey(user3ForbiddenUserAttr));
    assertFalse(attrMap.containsKey(user3ForbiddenOperationalAttr));
    assertTrue(attrMap.containsKey(user3AllowedUserAttr));
    // check we can't pre-read the forbidden user attribute
    String modifyLdif1 = makeAddLDIF(user3WritableAttr, user3, "don't care 1");
    String modifyResults1 = preReadModify(user3, PWD, modifyLdif1, user3ForbiddenUserAttr);
    assertNotEquals(modifyResults1, "");
    Map<String, String> modifyMap1 = getAttrMap(modifyResults1, true);
    assertFalse(modifyMap1.containsKey(user3ForbiddenUserAttr));
    // check we can't pre-read the forbidden operational attribute
    String modifyLdif2 = makeAddLDIF(user3WritableAttr, user3, "don't care 2");
    String modifyResults2 = preReadModify(user3, PWD, modifyLdif2, user3ForbiddenOperationalAttr);
    assertNotEquals(modifyResults2, "");
    Map<String, String> modifyMap2 = getAttrMap(modifyResults2, true);
    assertFalse(modifyMap2.containsKey(user3ForbiddenOperationalAttr));
    // check we can pre-read the allowed user attribute
    String modifyLdif3 = makeAddLDIF(user3WritableAttr, user3, "don't care 3");
    String modifyResults3 = preReadModify(user3, PWD, modifyLdif3, user3AllowedUserAttr);
    assertNotEquals(modifyResults3, "");
    Map<String, String> modifyMap3 = getAttrMap(modifyResults3, true);
    assertTrue(modifyMap3.containsKey(user3AllowedUserAttr));
    // check we can pre-read the allowed operational attribute
    String modifyLdif4 = makeAddLDIF(user3WritableAttr, user3, "don't care 4");
    String modifyResults4 = preReadModify(user3, PWD, modifyLdif4, user3AllowedOperationalAttr);
    assertNotEquals(modifyResults4, "");
    Map<String, String> modifyMap4 = getAttrMap(modifyResults4, true);
    assertTrue(modifyMap4.containsKey(user3AllowedOperationalAttr));
    deleteAttrFromEntry(user3, "aci");
  }
  /**
   * Test targetattr shorthand behavior, all attrs both user and operational.
   * See comments.
   *