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

Ludovic Poitou
20.37.2011 439a48e88a9891e3e3e813ca06bfbcbf54bcb140
Fix issue OPENDJ-237: Password modification by deleting the value and adding a new one fails with unwilling to perform (would result in multiple password in the entry).
Make sure we update the passwords counters when deleting values.
Unit-tests added to make sure we do not have regressions in the future
2 files modified
223 ■■■■■ changed files
opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java 32 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/core/ModifyOperationTestCase.java 191 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
@@ -1323,6 +1323,12 @@
    // encoded forms.
    Attribute pwAttr = m.getAttribute();
    AttributeBuilder builder = new AttributeBuilder(pwAttr, true);
    if (pwAttr.isEmpty())
    {
      // Removing all current password values.
      numPasswords = 0;
    }
    for (AttributeValue v : pwAttr)
    {
      if (pwPolicyState.passwordIsPreEncoded(v.getValue()))
@@ -1335,7 +1341,31 @@
        }
        else
        {
          builder.add(v);
          // We still need to check if the pre-encoded password matches
          // an existing value, to decrease the number of passwords.
          List<Attribute> attrList = currentEntry.getAttribute(pwAttr
              .getAttributeType());
          if ((attrList == null) || (attrList.isEmpty()))
          {
            throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
                ERR_MODIFY_NO_EXISTING_VALUES.get());
          }
          boolean found = false;
          for (Attribute attr : attrList)
          {
            for (AttributeValue av : attr)
            {
              if (av.equals(v))
              {
                builder.add(v);
                found = true;
              }
            }
          }
          if (found)
          {
            numPasswords--;
          }
        }
      }
      else
opends/tests/unit-tests-testng/src/server/org/opends/server/core/ModifyOperationTestCase.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2006-2011 Sun Microsystems, Inc.
 *      Portions Copyright 2011 ForgeRock AS
 */
package org.opends.server.core;
@@ -4776,6 +4777,196 @@
    assertTrue(modifyOperation.getResultCode() == ResultCode.SUCCESS);
    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.
   *
   * @param  baseDN  The base DN for the test backend.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "baseDNs")
  public void testModifyDelAddPasswordAttribute(String baseDN)
         throws Exception
  {
    TestCaseUtils.clearJEBackend(true,"userRoot",baseDN);
     Entry entry = TestCaseUtils.makeEntry(
         "dn: uid=testPassword01.user," + baseDN,
         "objectClass: top",
         "objectClass: person",
         "objectClass: organizationalPerson",
         "objectClass: inetOrgPerson",
         "uid: test.user",
         "givenName: Test",
         "sn: User",
         "cn: Test User",
         "displayName: Test User",
         "userPassword: password");
    InternalClientConnection conn =
         InternalClientConnection.getRootConnection();
    AddOperation addOperation =
         conn.processAdd(entry.getDN(), entry.getObjectClasses(),
                         entry.getUserAttributes(),
                         entry.getOperationalAttributes());
    assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
    String path = TestCaseUtils.createTempFile(
         "dn: uid=testPassword01.user," + baseDN,
         "changetype: modify",
         "delete: userPassword",
         "-",
         "add: userPassword",
         "userPassword: aNewPassword");
    String[] args =
    {
      "-h", "127.0.0.1",
      "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
      "-D", "cn=Directory Manager",
      "-w", "password",
      "-f", path
    };
    assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
  }
   /**
   * Tests a modify operation that attempts change the user password doing
   * a delete of a clear text value followed of an add of a new value.
   *
   * @param  baseDN  The base DN for the test backend.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "baseDNs")
  public void testModifyDelOneAddOnePasswordAttribute(String baseDN)
         throws Exception
  {
    TestCaseUtils.clearJEBackend(true,"userRoot",baseDN);
     Entry entry = TestCaseUtils.makeEntry(
         "dn: uid=testPassword02.user," + baseDN,
         "objectClass: top",
         "objectClass: person",
         "objectClass: organizationalPerson",
         "objectClass: inetOrgPerson",
         "uid: test.user",
         "givenName: Test",
         "sn: User",
         "cn: Test User",
         "displayName: Test User",
         "userPassword: password");
    InternalClientConnection conn =
         InternalClientConnection.getRootConnection();
    AddOperation addOperation =
         conn.processAdd(entry.getDN(), entry.getObjectClasses(),
                         entry.getUserAttributes(),
                         entry.getOperationalAttributes());
    assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
    String path = TestCaseUtils.createTempFile(
         "dn: uid=testPassword02.user," + baseDN,
         "changetype: modify",
         "delete: userPassword",
         "userPassword: password",
         "-",
         "add: userPassword",
         "userPassword: aNewPassword");
    String[] args =
    {
      "-h", "127.0.0.1",
      "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
      "-D", "cn=Directory Manager",
      "-w", "password",
      "-f", path
    };
    assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
  }
   /**
   * Tests a modify operation that attempts change the user password doing
   * a delete of an encrypted value followed of an add of a new value.
   *
   * @param  baseDN  The base DN for the test backend.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "baseDNs")
  public void testModifyDelEncryptedAddOnePasswordAttribute(String baseDN)
         throws Exception
  {
    TestCaseUtils.clearJEBackend(true,"userRoot",baseDN);
     Entry entry = TestCaseUtils.makeEntry(
         "dn: uid=testPassword03.user," + baseDN,
         "objectClass: top",
         "objectClass: person",
         "objectClass: organizationalPerson",
         "objectClass: inetOrgPerson",
         "uid: test.user",
         "givenName: Test",
         "sn: User",
         "cn: Test User",
         "displayName: Test User",
         "userPassword: password");
    InternalClientConnection conn =
         InternalClientConnection.getRootConnection();
    AddOperation addOperation =
         conn.processAdd(entry.getDN(), entry.getObjectClasses(),
                         entry.getUserAttributes(),
                         entry.getOperationalAttributes());
    assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
    Entry e = DirectoryServer.getEntry(
            DN.decode("uid=testPassword03.user," + baseDN));
    List<Attribute> attrList =
         e.getAttribute(DirectoryServer.getAttributeType("userpassword", true));
    assertNotNull(attrList);
    String passwd = null;
    for (Attribute a : attrList)
    {
      for (AttributeValue v : a)
      {
        passwd = v.toString();
      }
    }
    assertNotNull(passwd);
    String path = TestCaseUtils.createTempFile(
         "dn: uid=testPassword03.user," + baseDN,
         "changetype: modify",
         "delete: userPassword",
         "userPassword: " + passwd,
         "-",
         "add: userPassword",
         "userPassword: aNewPassword");
    String[] args =
    {
      "-h", "127.0.0.1",
      "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
      "-D", "cn=Directory Manager",
      "-w", "password",
      "-f", path
    };
    assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
  }
}