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

ludovicp
07.59.2010 9f443811d6c86db26eb474a61df7021f98c32c78
Add support for MS AD Permissive Modify Control (Issue/Enhancement #4238)
4 files modified
80 ■■■■ changed files
opends/src/server/org/opends/server/core/DirectoryServer.java 1 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/types/Entry.java 43 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/util/ServerConstants.java 6 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java 30 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -2712,6 +2712,7 @@
    supportedControls.add(OID_MATCHED_VALUES);
    supportedControls.add(OID_LDAP_SUBENTRIES);
    supportedControls.add(OID_PASSWORD_POLICY_CONTROL);
    supportedControls.add(OID_PERMISSIVE_MODIFY_CONTROL);
    supportedControls.add(OID_REAL_ATTRS_ONLY);
    supportedControls.add(OID_VIRTUAL_ATTRS_ONLY);
    supportedControls.add(OID_ACCOUNT_USABLE_CONTROL);
opends/src/server/org/opends/server/types/Entry.java
@@ -1781,14 +1781,17 @@
   * checking will be performed.
   *
   * @param  mod  The modification to apply to this entry.
   *
   * @param  relaxConstraints indicates if the modification constraints are
   *                          relaxed to match the ones of a set (add existing
   *                          value and delete absent value do not fail)
   *
   * @throws  DirectoryException  If a problem occurs while attempting
   *                              to apply the modification.  Note
   *                              that even if a problem occurs, then
   *                              the entry may have been altered in
   *                              some way.
   */
  public void applyModification(Modification mod)
  public void applyModification(Modification mod, boolean relaxConstraints)
         throws DirectoryException
  {
    Attribute     a = mod.getAttribute();
@@ -1816,11 +1819,14 @@
          {
            if (objectClasses.containsKey(oc))
            {
              Message message =
              if (!relaxConstraints)
              {
                Message message =
                  ERR_ENTRY_DUPLICATE_VALUES.get(a.getName());
              throw new DirectoryException(
                throw new DirectoryException(
                             ResultCode.ATTRIBUTE_OR_VALUE_EXISTS,
                             message);
              }
            }
            else
            {
@@ -1835,10 +1841,13 @@
          {
            if (objectClasses.remove(oc) == null)
            {
              Message message =
              if (! relaxConstraints)
              {
                Message message =
                  ERR_ENTRY_NO_SUCH_VALUE.get(a.getName());
              throw new DirectoryException(
                throw new DirectoryException(
                             ResultCode.NO_SUCH_ATTRIBUTE, message);
              }
            }
          }
          objectClassAttribute = null;
@@ -1871,7 +1880,7 @@
        LinkedList<AttributeValue> duplicateValues =
             new LinkedList<AttributeValue>();
        addAttribute(a, duplicateValues);
        if (! duplicateValues.isEmpty())
        if ((! duplicateValues.isEmpty()) && (! relaxConstraints))
        {
          Message message =
              ERR_ENTRY_DUPLICATE_VALUES.get(a.getName());
@@ -1885,7 +1894,7 @@
        LinkedList<AttributeValue> missingValues =
             new LinkedList<AttributeValue>();
        removeAttribute(a, missingValues);
        if (! missingValues.isEmpty())
        if ((! missingValues.isEmpty()) && (! relaxConstraints))
        {
          Message message = ERR_ENTRY_NO_SUCH_VALUE.get(a.getName());
          throw new DirectoryException(ResultCode.NO_SUCH_ATTRIBUTE,
@@ -1909,7 +1918,23 @@
    }
  }
  /**
   * Applies the provided modification to this entry.  No schema
   * checking will be performed.
   *
   * @param  mod  The modification to apply to this entry.
   *
   * @throws  DirectoryException  If a problem occurs while attempting
   *                              to apply the modification.  Note
   *                              that even if a problem occurs, then
   *                              the entry may have been altered in
   *                              some way.
   */
  public void applyModification(Modification mod)
         throws DirectoryException
  {
      applyModification(mod, false);
  }
  /**
   * Applies all of the provided modifications to this entry.
opends/src/server/org/opends/server/util/ServerConstants.java
@@ -2275,6 +2275,12 @@
       "2.16.840.1.113730.3.4.2";
  /**
   * The OID for the Permissive Modify control, defined and used by MSAD
   */
  public static final String OID_PERMISSIVE_MODIFY_CONTROL =
      "1.2.840.113556.1.4.1413";
  /**
   * The OID for the server-side sort request control.
opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
@@ -120,6 +120,11 @@
  protected boolean noOp;
  /**
   * Indicates whether the request included the Permissive Modify control.
   */
  protected boolean permissiveModify = false;
  /**
   * Indicates whether this modify operation includees a password change.
   */
  protected boolean passwordChanged;
@@ -287,7 +292,7 @@
  public void addModification(Modification modification)
    throws DirectoryException
  {
    modifiedEntry.applyModification(modification);
    modifiedEntry.applyModification(modification, permissiveModify);
    super.addModification(modification);
  }
@@ -839,6 +844,10 @@
        {
          noOp = true;
        }
        else if (oid.equals(OID_PERMISSIVE_MODIFY_CONTROL))
        {
          permissiveModify = true;
        }
        else if (oid.equals(OID_LDAP_READENTRY_PREREAD))
        {
          preReadRequest =
@@ -1496,7 +1505,7 @@
    LinkedList<AttributeValue> duplicateValues =
      new LinkedList<AttributeValue>();
    modifiedEntry.addAttribute(attr, duplicateValues);
    if (!duplicateValues.isEmpty())
    if (!duplicateValues.isEmpty() && !permissiveModify)
    {
      StringBuilder buffer = new StringBuilder();
      Iterator<AttributeValue> iterator = duplicateValues.iterator();
@@ -1604,18 +1613,21 @@
      }
      else
      {
        StringBuilder buffer = new StringBuilder();
        Iterator<AttributeValue> iterator = missingValues.iterator();
        buffer.append(iterator.next().getValue().toString());
        while (iterator.hasNext())
        if (! permissiveModify)
        {
          buffer.append(", ");
          StringBuilder buffer = new StringBuilder();
          Iterator<AttributeValue> iterator = missingValues.iterator();
          buffer.append(iterator.next().getValue().toString());
        }
          while (iterator.hasNext())
          {
            buffer.append(", ");
            buffer.append(iterator.next().getValue().toString());
          }
        throw new DirectoryException(ResultCode.NO_SUCH_ATTRIBUTE,
          throw new DirectoryException(ResultCode.NO_SUCH_ATTRIBUTE,
                       ERR_MODIFY_DELETE_MISSING_VALUES.get(
                            String.valueOf(entryDN), attr.getName(), buffer));
        }
      }
    }
    else