/** * Performs an access check against all of the attributes of an entry. The attributes that fail * access are removed from the entry. This method performs the processing needed for the * filterEntry method processing. * * @param container The search or compare container which has all of the information needed to * filter the attributes for this entry. * @param filteredEntry The partially filtered search result entry being returned to the client. */ private void filterEntry(AciLDAPOperationContainer container, Entry filteredEntry) { List<AttributeType> typeList = getAllAttrs(filteredEntry); for (AttributeType attrType : typeList) { if (container.hasAllUserAttributes() && !attrType.isOperational()) { continue; } if (container.hasAllOpAttributes() && attrType.isOperational()) { continue; } container.setCurrentAttributeType(attrType); if (!accessAllowed(container)) { filteredEntry.removeAttribute(attrType); } } }
/** * Check if the specified attribute type is a DN by checking if its syntax OID is equal to the DN * syntax OID. * * @param attribute The attribute type to check. * @return True if the attribute type syntax OID is equal to a DN syntax OID. */ private boolean isAttributeDN(AttributeType attribute) { return (attribute.getSyntaxOID().equals(SYNTAX_DN_OID)); }
/** * Checks to see if a LDAP modification is allowed access. * * @param container The structure containing the LDAP modifications * @param operation The operation to check modify privileges on. operation to check and the * evaluation context to apply the check against. * @param skipAccessCheck True if access checking should be skipped. * @return True if access is allowed. * @throws DirectoryException If a modified ACI could not be decoded. */ private boolean aciCheckMods( AciLDAPOperationContainer container, LocalBackendModifyOperation operation, boolean skipAccessCheck) throws DirectoryException { Entry resourceEntry = container.getResourceEntry(); DN dn = resourceEntry.getDN(); List<Modification> modifications = operation.getModifications(); for (Modification m : modifications) { Attribute modAttr = m.getAttribute(); AttributeType modAttrType = modAttr.getAttributeType(); if (modAttrType.equals(aciType)) { /* * Check that the operation has modify privileges if it contains * an "aci" attribute type. */ if (!operation.getClientConnection().hasPrivilege(Privilege.MODIFY_ACL, operation)) { Message message = INFO_ACI_MODIFY_FAILED_PRIVILEGE.get( String.valueOf(container.getResourceDN()), String.valueOf(container.getClientDN())); logError(message); return false; } } // This access check handles the case where all attributes of this // type are being replaced or deleted. If only a subset is being // deleted than this access check is skipped. ModificationType modType = m.getModificationType(); if (((modType == ModificationType.DELETE) && modAttr.isEmpty()) || ((modType == ModificationType.REPLACE) || (modType == ModificationType.INCREMENT))) { /* * Check if we have rights to delete all values of an attribute * type in the resource entry. */ if (resourceEntry.hasAttribute(modAttrType)) { container.setCurrentAttributeType(modAttrType); List<Attribute> attrList = resourceEntry.getAttribute(modAttrType, modAttr.getOptions()); if (attrList != null) { for (Attribute a : attrList) { for (AttributeValue v : a) { container.setCurrentAttributeValue(v); container.setRights(ACI_WRITE_DELETE); if (!skipAccessCheck && !accessAllowed(container)) { return false; } } } } } } if (!modAttr.isEmpty()) { for (AttributeValue v : modAttr) { container.setCurrentAttributeType(modAttrType); switch (m.getModificationType()) { case ADD: case REPLACE: container.setCurrentAttributeValue(v); container.setRights(ACI_WRITE_ADD); if (!skipAccessCheck && !accessAllowed(container)) { return false; } break; case DELETE: container.setCurrentAttributeValue(v); container.setRights(ACI_WRITE_DELETE); if (!skipAccessCheck && !accessAllowed(container)) { return false; } break; case INCREMENT: Entry modifiedEntry = operation.getModifiedEntry(); List<Attribute> modifiedAttrs = modifiedEntry.getAttribute(modAttrType, modAttr.getOptions()); if (modifiedAttrs != null) { for (Attribute attr : modifiedAttrs) { for (AttributeValue val : attr) { 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. * If so, check the syntax of that attribute value. Fail the * the operation if the syntax check fails. */ if (modAttrType.equals(aciType) || modAttrType.equals(globalAciType)) { try { // A global ACI needs a NULL DN, not the DN of the // modification. if (modAttrType.equals(globalAciType)) { dn = DN.nullDN(); } Aci.decode(v.getValue(), dn); } catch (AciException ex) { Message message = WARN_ACI_MODIFY_FAILED_DECODE.get(String.valueOf(dn), ex.getMessage()); throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message); } } } } } return true; }