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

Matthew Swift
03.49.2012 226d60b39eb76ed0ca5c956e9722c14927a8ede2
opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
@@ -23,7 +23,7 @@
 *
 *
 *      Copyright 2008-2011 Sun Microsystems, Inc.
 *      Portions Copyright 2011 ForgeRock AS
 *      Portions Copyright 2011-2012 ForgeRock AS
 */
package org.opends.server.workflowelement.localbackend;
@@ -1098,18 +1098,32 @@
      {
        if (!isSynchronizationOperation())
        {
          // If the attribute contains any options, then reject it.  Passwords
          // will not be allowed to have options.
          // Skipped for internal operations.
          // If the attribute contains any options and new values are going to
          // be added, then reject it. Passwords will not be allowed to have
          // options. Skipped for internal operations.
          if (!isInternalOperation())
          {
            if (a.hasOptions())
            {
              throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
                  ERR_MODIFY_PASSWORDS_CANNOT_HAVE_OPTIONS.get());
              switch (m.getModificationType())
              {
              case REPLACE:
                if (!a.isEmpty())
                {
                  throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
                      ERR_MODIFY_PASSWORDS_CANNOT_HAVE_OPTIONS.get());
                }
                // Allow delete operations to clean up after import.
                break;
              case ADD:
                throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
                    ERR_MODIFY_PASSWORDS_CANNOT_HAVE_OPTIONS.get());
              default:
                // Allow delete operations to clean up after import.
                break;
              }
            }
            // If it's a self change, then see if that's allowed.
            if (selfChange
                && (!pwPolicyState.getAuthenticationPolicy()
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/ModifyOperationTestCase.java
@@ -64,6 +64,7 @@
import static org.testng.Assert.*;
import static org.opends.server.TestCaseUtils.TEST_BACKEND_ID;
import static org.opends.server.protocols.ldap.LDAPConstants.*;
@@ -4778,7 +4779,7 @@
    retrieveSuccessfulOperationElements(modifyOperation);
  }
    /**
  /**
   * Tests a modify operation that attempts change the user password doing
   * a delete of all values followed of an add of a new value.
   *
@@ -4968,7 +4969,168 @@
    assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
  }
  /**
   * Tests that it is possible to delete userPassword attributes which have
   * options. Options are not allowed for passwords, but we should allow users
   * to clean them up, for example, after an import of legacy data.
   *
   * @throws Exception
   *           If an unexpected problem occurs.
   */
  @Test
  public void testModifyDelPasswordAttributeWithOption()
      throws Exception
  {
    // @formatter:off
    TestCaseUtils.initializeTestBackend(true);
    Entry e = TestCaseUtils.makeEntry(
        "dn: cn=Test User,o=test",
        "objectClass: top",
        "objectClass: person",
        "sn: User",
        "cn: Test User",
        "userPassword: password",
        "userPassword;deleted: oldpassword");
    Backend backend = DirectoryServer.getBackend(TEST_BACKEND_ID);
    backend.addEntry(e, null); // Don't use add operation.
    // Constraint violation.
    assertEquals(TestCaseUtils.applyModifications(false,
        "dn: cn=Test User,o=test",
        "changetype: modify",
        "delete: userPassword;deleted",
        "-"
    ), 0);
    // @formatter:on
    e = DirectoryServer.getEntry(DN.decode("cn=Test User,o=test"));
    List<Attribute> attrList = e.getAttribute("userpassword");
    assertNotNull(attrList);
    assertEquals(attrList.size(), 1);
    assertFalse(attrList.get(0).hasOptions());
    assertEquals(attrList.get(0).size(), 1);
  }
  /**
   * Tests that it is possible to delete userPassword attributes using an empty
   * replace which have options. Options are not allowed for passwords, but we
   * should allow users to clean them up, for example, after an import of legacy
   * data.
   *
   * @throws Exception
   *           If an unexpected problem occurs.
   */
  @Test
  public void testModifyReplaceEmptyPasswordAttributeWithOption()
      throws Exception
  {
    // @formatter:off
    TestCaseUtils.initializeTestBackend(true);
    Entry e = TestCaseUtils.makeEntry(
        "dn: cn=Test User,o=test",
        "objectClass: top",
        "objectClass: person",
        "sn: User",
        "cn: Test User",
        "userPassword: password",
        "userPassword;deleted: oldpassword");
    Backend backend = DirectoryServer.getBackend(TEST_BACKEND_ID);
    backend.addEntry(e, null); // Don't use add operation.
    // Constraint violation.
    assertEquals(TestCaseUtils.applyModifications(false,
        "dn: cn=Test User,o=test",
        "changetype: modify",
        "replace: userPassword;deleted",
        "-"
    ), 0);
    // @formatter:on
    e = DirectoryServer.getEntry(DN.decode("cn=Test User,o=test"));
    List<Attribute> attrList = e.getAttribute("userpassword");
    assertNotNull(attrList);
    assertEquals(attrList.size(), 1);
    assertFalse(attrList.get(0).hasOptions());
    assertEquals(attrList.get(0).size(), 1);
  }
  /**
   * Tests that it is not possible to add userPassword attributes which have
   * options. Options are not allowed for passwords.
   *
   * @throws Exception
   *           If an unexpected problem occurs.
   */
  @Test
  public void testModifyAddPasswordAttributeWithOption()
      throws Exception
  {
    // @formatter:off
    TestCaseUtils.initializeTestBackend(true);
    TestCaseUtils.addEntry(
        "dn: cn=Test User,o=test",
        "objectClass: top",
        "objectClass: person",
        "sn: User",
        "cn: Test User",
        "userPassword: password");
    // Constraint violation.
    assertEquals(TestCaseUtils.applyModifications(false,
        "dn: cn=Test User,o=test",
        "changetype: modify",
        "add: userPassword;added",
        "userPassword;added: newpassword",
        "-"
    ), 19);
    // @formatter:on
    Entry e = DirectoryServer.getEntry(DN.decode("cn=Test User,o=test"));
    List<Attribute> attrList = e.getAttribute("userpassword");
    assertNotNull(attrList);
    assertEquals(attrList.size(), 1);
    assertFalse(attrList.get(0).hasOptions());
    assertEquals(attrList.get(0).size(), 1);
  }
  /**
   * Tests that it is not possible to add userPassword attributes which have
   * options. Options are not allowed for passwords.
   *
   * @throws Exception
   *           If an unexpected problem occurs.
   */
  @Test
  public void testModifyReplaceWithValuesPasswordAttributeWithOption()
      throws Exception
  {
    // @formatter:off
    TestCaseUtils.initializeTestBackend(true);
    TestCaseUtils.addEntry(
        "dn: cn=Test User,o=test",
        "objectClass: top",
        "objectClass: person",
        "sn: User",
        "cn: Test User",
        "userPassword: password");
    // Constraint violation.
    assertEquals(TestCaseUtils.applyModifications(false,
        "dn: cn=Test User,o=test",
        "changetype: modify",
        "replace: userPassword;added",
        "userPassword;added: newpassword",
        "-"
    ), 19);
    // @formatter:on
    Entry e = DirectoryServer.getEntry(DN.decode("cn=Test User,o=test"));
    List<Attribute> attrList = e.getAttribute("userpassword");
    assertNotNull(attrList);
    assertEquals(attrList.size(), 1);
    assertFalse(attrList.get(0).hasOptions());
    assertEquals(attrList.get(0).size(), 1);
  }
  /**
   * Tests that the binary option is automatically added to modifications if it