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

coulbeck
06.30.2007 67daa4057a090d2c2ed891699c4726b1bf3d08cb
Implement access control checking for the modify increment operation.  The same checks are made for increment as would be made for a replace.  However, the access control handler needs to have the modified entry available so the access control handler is called later in the modify operation after the modified entry has been set.  This change has been discussed with Mike and Neil.
2 files modified
133 ■■■■ changed files
opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java 91 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperation.java 42 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
@@ -40,7 +40,6 @@
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
import org.opends.server.types.Modification;
import org.opends.server.types.ModificationType;
import org.opends.server.types.Privilege;
import org.opends.server.types.SearchResultEntry;
import org.opends.server.types.SearchResultReference;
@@ -166,14 +165,6 @@
            aciType = DirectoryServer.getDefaultAttributeType("aci");
    }
    /*
     * TODO
     * The internal search performed by the searchAcis method will require
     * a presence index on the aci attribute for any database of any significant
     * size.  We should probably consider making this index present by default,
     * because if they aren't using the DSEE-compatible implementation then
     * they probably won't have any instances of the aci attribute.
     */
    /**
     * Checks to see if a LDAP modification is allowed access.
     *
@@ -184,7 +175,7 @@
     * @return  True if access is allowed.
     */
    private boolean aciCheckMods(AciLDAPOperationContainer container,
                                 Operation operation,
                                 ModifyOperation operation,
                                 boolean skipAccessCheck) {
        Entry resourceEntry=container.getResourceEntry();
        DN dn=resourceEntry.getDN();
@@ -193,50 +184,68 @@
            Attribute modAttr=m.getAttribute();
            AttributeType modType=modAttr.getAttributeType();
            switch(m.getModificationType()) {
            /*
             * TODO Increment modification type needs to be handled.
             */
                case DELETE:
                case REPLACE:
                {
                    /*
                        Check if we have rights to delete all values of
                        an attribute type in the resource entry.
                    */
                    if(resourceEntry.hasAttribute(modType)) {
                        container.setCurrentAttributeType(modType);
                        List<Attribute> attrList =
                            resourceEntry.getAttribute(modType,null);
                        for (Attribute a : attrList) {
                            for (AttributeValue v : a.getValues()) {
                                container.setCurrentAttributeValue(v);
                                container.setRights(ACI_WRITE_DELETE);
                                if(!skipAccessCheck &&
                                   !accessAllowed(container))
                                    return false;
                            }
                        }
              case DELETE:
              case REPLACE:
              case INCREMENT:
              {
                /*
                 * Check if we have rights to delete all values of
                 * an attribute type in the resource entry.
                 */
                if(resourceEntry.hasAttribute(modType)) {
                  container.setCurrentAttributeType(modType);
                  List<Attribute> attrList =
                       resourceEntry.getAttribute(modType,modAttr.getOptions());
                  for (Attribute a : attrList) {
                    for (AttributeValue v : a.getValues()) {
                      container.setCurrentAttributeValue(v);
                      container.setRights(ACI_WRITE_DELETE);
                      if(!skipAccessCheck &&
                           !accessAllowed(container))
                        return false;
                    }
                  }
                }
              }
            }
            if(modAttr.hasValue()) {
               boolean checkPrivileges=true;
               for(AttributeValue v : modAttr.getValues()) {
                   container.setCurrentAttributeType(modType);
                   container.setCurrentAttributeValue(v);
                   if((m.getModificationType() == ModificationType.ADD) ||
                      (m.getModificationType() == ModificationType.REPLACE)) {
                   switch (m.getModificationType())
                   {
                     case ADD:
                     case REPLACE:
                       container.setCurrentAttributeValue(v);
                       container.setRights(ACI_WRITE_ADD);
                       if(!skipAccessCheck && !accessAllowed(container))
                           return false;
                   } else if(m.getModificationType()
                           == ModificationType.DELETE) {
                       break;
                     case DELETE:
                       container.setCurrentAttributeValue(v);
                       container.setRights(ACI_WRITE_DELETE);
                       if(!skipAccessCheck && !accessAllowed(container))
                           return false;
                   } else {
                     if(!skipAccessCheck)
                       return false;
                       break;
                     case INCREMENT:
                       Entry modifiedEntry = operation.getModifiedEntry();
                       List<Attribute> modifiedAttrs =
                            modifiedEntry.getAttribute(modType,
                                                       modAttr.getOptions());
                       if (modifiedAttrs != null)
                       {
                         for (Attribute attr : modifiedAttrs)
                         {
                           for (AttributeValue val : attr.getValues())
                           {
                             container.setCurrentAttributeValue(val);
                             container.setRights(ACI_WRITE_ADD);
                             if(!skipAccessCheck && !accessAllowed(container))
                                 return false;
                           }
                         }
                       }
                       break;
                   }
                   /*
                    Check if the modification type has an "aci" attribute type.
opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperation.java
@@ -1164,26 +1164,6 @@
        }
        // Check to see if the client has permission to perform the
        // modify.
        // FIXME: for now assume that this will check all permission
        // pertinent to the operation. This includes proxy authorization
        // and any other controls specified.
        // FIXME: earlier checks to see if the entry already exists may
        // have already exposed sensitive information to the client.
        if (AccessControlConfigManager.getInstance()
            .getAccessControlHandler().isAllowed(this) == false) {
          setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
          int msgID = MSGID_MODIFY_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
          appendErrorMessage(getMessage(msgID, String.valueOf(entryDN)));
          skipPostOperation = true;
          break modifyProcessing;
        }
        // Get the password policy state object for the entry that can be used
        // to perform any appropriate password policy processing.  Also, see if
        // the entry is being updated by the end user or an administrator.
@@ -2374,6 +2354,28 @@
        }
        // Check to see if the client has permission to perform the
        // modify.
        // The access control check is not made any earlier because the
        // handler needs access to the modified entry.
        // FIXME: for now assume that this will check all permission
        // pertinent to the operation. This includes proxy authorization
        // and any other controls specified.
        // FIXME: earlier checks to see if the entry already exists may
        // have already exposed sensitive information to the client.
        if (AccessControlConfigManager.getInstance()
            .getAccessControlHandler().isAllowed(this) == false) {
          setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
          int msgID = MSGID_MODIFY_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
          appendErrorMessage(getMessage(msgID, String.valueOf(entryDN)));
          skipPostOperation = true;
          break modifyProcessing;
        }
        // Make sure that the new entry is valid per the server schema.
        if (DirectoryServer.checkSchema())
        {