From 91fdf0048df4c43fe3b7412ccb7f862eab5f7669 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Wed, 02 Feb 2011 20:45:14 +0000
Subject: [PATCH] Fix issue OPENDJ-24: Fix OpenDS issue 4583: during a search op, ACI with targetfilter and targetattrs gets evaluated wrongly https://bugster.forgerock.org/jira/browse/OPENDJ-24
---
opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java | 117 -----
opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java | 170 +++++++
opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyDNOperation.java | 118 -----
opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java | 63 --
opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendCompareOperation.java | 2
opends/src/server/org/opends/server/api/AccessControlHandler.java | 63 +-
opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java | 155 ++----
opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java | 72 --
opends/src/server/org/opends/server/core/SearchOperationBasis.java | 32
opends/src/server/org/opends/server/core/DefaultAccessControlHandler.java | 33 -
opends/src/server/org/opends/server/authorization/dseecompat/AciEvalContext.java | 28 -
opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java | 44 -
opends/src/server/org/opends/server/authorization/dseecompat/UserAttr.java | 44 -
opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTests.java | 2
opends/src/server/org/opends/server/authorization/dseecompat/AciEffectiveRights.java | 300 +++++++------
opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendDeleteOperation.java | 63 --
16 files changed, 500 insertions(+), 806 deletions(-)
diff --git a/opends/src/server/org/opends/server/api/AccessControlHandler.java b/opends/src/server/org/opends/server/api/AccessControlHandler.java
index 6f5f534..b5f3b82 100644
--- a/opends/src/server/org/opends/server/api/AccessControlHandler.java
+++ b/opends/src/server/org/opends/server/api/AccessControlHandler.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2006-2009 Sun Microsystems, Inc.
+ * Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.api;
@@ -347,36 +348,18 @@
* the client. Implementations <b>must not under any
* circumstances</b> modify the search entry in any way.
*
- * @param searchOperation
- * The search operation with which the provided entry is
- * associated.
- * @param searchEntry
- * The search result entry for which to make the
- * determination.
+ * @param operation
+ * The operation currently being processed (this will
+ * usually be a search, but may be other types of operation
+ * when pre/post read controls are used).
+ * @param unfilteredEntry
+ * The result entry before any attribute filtering.
* @return {@code true} if the access control configuration allows
* the entry to be returned to the client, or {@code false}
* if not.
*/
- public abstract boolean maySend(SearchOperation searchOperation,
- SearchResultEntry searchEntry);
-
-
-
- /**
- * Filter the contents of the provided entry such that it no longer
- * contains any attributes or values that the client is not
- * permitted to access.
- *
- * @param searchOperation
- * The search operation with which the provided entry is
- * associated.
- * @param searchEntry
- * The search result entry to be filtered.
- * @return Returns the entry with filtered attributes and values
- * removed.
- */
- public abstract SearchResultEntry filterEntry(
- SearchOperation searchOperation, SearchResultEntry searchEntry);
+ public abstract boolean maySend(Operation operation,
+ SearchResultEntry unfilteredEntry);
@@ -386,15 +369,18 @@
* permitted to access.
*
* @param operation
- * The operation with which the provided entry is
- * associated.
- * @param entry
- * The entry to be filtered.
- * @return Returns the entry with filtered attributes and values
- * removed.
+ * The operation currently being processed (this will
+ * usually be a search, but may be other types of operation
+ * when pre/post read controls are used).
+ * @param unfilteredEntry
+ * The result entry before any attribute filtering.
+ * @param filteredEntry
+ * The partially filtered result entry being returned to
+ * the client.
*/
- public abstract SearchResultEntry filterEntry(
- Operation operation, Entry entry);
+ public abstract void filterEntry(Operation operation,
+ SearchResultEntry unfilteredEntry,
+ SearchResultEntry filteredEntry);
@@ -404,8 +390,8 @@
*
* @param dn
* A DN that can be used in the access determination.
- * @param searchOperation
- * The search operation with which the provided reference
+ * @param operation
+ * The operation with which the provided reference
* is associated.
* @param searchReference
* The search result reference for which to make the
@@ -414,9 +400,8 @@
* the reference to be returned to the client, or {@code
* false} if not.
*/
- public abstract boolean maySend(DN dn,
- SearchOperation searchOperation,
- SearchResultReference searchReference);
+ public abstract boolean maySend(DN dn, Operation operation,
+ SearchResultReference searchReference);
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java
index d12f2bf..2bb31ce 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2008 Sun Microsystems, Inc.
+ * Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.authorization.dseecompat;
@@ -103,13 +104,6 @@
private Entry resourceEntry;
/*
- * Saves the resource entry. Used in geteffectiverights evaluation to
- * restore the current resource entry state after a read right was
- * evaluated.
- */
- private final Entry saveResourceEntry;
-
- /*
* The client connection information.
*/
private final ClientConnection clientConnection;
@@ -187,12 +181,6 @@
private List<AttributeType> specificAttrs=null;
/*
- * The entry with all of its attributes available. Used in
- * geteffectiverights read entry level evaluation.
- */
- private Entry fullEntry=null;
-
- /*
* Table of ACIs that have targattrfilter keywords that matched. Used
* in geteffectiverights attributeLevel write evaluation.
*/
@@ -278,26 +266,29 @@
if(origAuthorizationEntry != null)
this.proxiedAuthorization=true;
this.authorizationEntry=operation.getAuthorizationEntry();
+
//The ACI_READ right at constructor time can only be the result of the
//AciHandler.filterEntry method. This method processes the
//geteffectiverights control, so it needs to check for it. There are
//two other checks done, because the resource entry passed to that method
//is filtered (it may not contain enough attribute information
//to evaluate correctly). See the the comments below.
- if(operation instanceof SearchOperation && (rights == ACI_READ)) {
+ if (rights == ACI_READ) {
//Checks if a geteffectiverights control was sent and
//sets up the structures needed.
GetEffectiveRightsRequestControl getEffectiveRightsControl =
(GetEffectiveRightsRequestControl)
operation.getAttachment(OID_GET_EFFECTIVE_RIGHTS);
- if(getEffectiveRightsControl != null) {
- hasGetEffectiveRightsControl=true;
- if(getEffectiveRightsControl.getAuthzDN() == null)
- this.authzid=getClientDN();
- else
- this.authzid=getEffectiveRightsControl.getAuthzDN();
- this.specificAttrs=getEffectiveRightsControl.getAttributes();
+ if (getEffectiveRightsControl != null
+ && operation instanceof SearchOperation)
+ {
+ hasGetEffectiveRightsControl = true;
+ if (getEffectiveRightsControl.getAuthzDN() == null)
+ this.authzid = getClientDN();
+ else this.authzid = getEffectiveRightsControl.getAuthzDN();
+ this.specificAttrs = getEffectiveRightsControl.getAttributes();
}
+
//If an ACI evaluated because of an Targetattr="*", then the
//AciHandler.maySend method signaled this via adding this attachment
//string.
@@ -311,16 +302,11 @@
String allOpAttrs=(String)operation.getAttachment(ALL_OP_ATTRS_MATCHED);
if(allOpAttrs != null)
evalAllAttributes |= ACI_OP_ATTR_PLUS_MATCHED;
+ }
- //The AciHandler.maySend method also adds the full attribute version of
- //the resource entry in this attachment.
- fullEntry=(Entry)operation.getAttachment(ALL_ATTRS_RESOURCE_ENTRY);
- } else
- fullEntry=this.resourceEntry;
//Reference the current authorization entry, so it can be put back
//if an access proxy check was performed.
this.saveAuthorizationEntry=this.authorizationEntry;
- this.saveResourceEntry=this.resourceEntry;
this.rightsMask = rights;
}
@@ -341,7 +327,6 @@
this.authInfo = authInfo;
this.authorizationEntry = authInfo.getAuthorizationEntry();
this.saveAuthorizationEntry=this.authorizationEntry;
- this.saveResourceEntry=this.resourceEntry;
this.rightsMask = rights;
}
/**
@@ -419,28 +404,6 @@
return this.specificAttrs;
}
- /**
- * During the geteffectiverights entrylevel read evaluation, an entry with all
- * of the attributes used in the AciHandler's maysend method evaluation is
- * needed to perform the evaluation over again. This entry was saved
- * in the operation's attachment mechanism when the container was created
- * during the SearchOperation read evaluation.
- *
- * This method is used to replace the current resource entry with that saved
- * entry to perform the entrylevel read evaluation described above and to
- * switch back to the current resource entry when needed.
- *
- * @param val Specifies if the saved entry should be used or not. True if it
- * should be used, false if the original resource entry should be used.
- *
- */
- public void useFullResourceEntry(boolean val) {
- if(val)
- resourceEntry=fullEntry;
- else
- resourceEntry=saveResourceEntry;
- }
-
/**
* {@inheritDoc}
*/
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciEffectiveRights.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciEffectiveRights.java
index 45296a1..a09880c 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciEffectiveRights.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciEffectiveRights.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2008 Sun Microsystems, Inc.
+ * Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.authorization.dseecompat;
@@ -186,123 +187,148 @@
* @param e The entry to add the rights attributes to.
* @param skipCheck True if ACI evaluation was skipped because bypass-acl
* privilege was found.
- * @return A SearchResultEntry with geteffectiverights information possibly
- * added to it.
*/
- public static SearchResultEntry
- addRightsToEntry(AciHandler handler, LinkedHashSet<String> searchAttributes,
- AciLDAPOperationContainer container,SearchResultEntry e,
- boolean skipCheck) {
- List<AttributeType> nonRightsAttrs = new LinkedList<AttributeType>();
- int attrMask=ACI_NULL;
- if(aclRights == null)
- aclRights =
- DirectoryServer.getAttributeType(aclRightsAttrStr.toLowerCase());
- if(aclRightsInfo == null)
- aclRightsInfo =
- DirectoryServer.getAttributeType(aclRightsInfoAttrStr.toLowerCase());
- if(dnAttributeType == null)
+ public static void addRightsToEntry(AciHandler handler,
+ LinkedHashSet<String> searchAttributes,
+ AciLDAPOperationContainer container, final Entry e,
+ boolean skipCheck)
+ {
+ if (aclRights == null)
+ {
+ aclRights = DirectoryServer.getAttributeType(aclRightsAttrStr
+ .toLowerCase());
+ }
+
+ if (aclRightsInfo == null)
+ {
+ aclRightsInfo = DirectoryServer.getAttributeType(aclRightsInfoAttrStr
+ .toLowerCase());
+ }
+
+ if (dnAttributeType == null)
+ {
dnAttributeType = DirectoryServer.getAttributeType(dnAttrStr);
- //Check if the attributes aclRights and aclRightsInfo were requested and
- //add attributes less those two attributes to a new list of attribute types.
- for(String a : searchAttributes) {
- if(a.equalsIgnoreCase(aclRightsAttrStr))
+ }
+
+ // Check if the attributes aclRights and aclRightsInfo were requested and
+ // add attributes less those two attributes to a new list of attribute
+ // types.
+ List<AttributeType> nonRightsAttrs = new LinkedList<AttributeType>();
+ int attrMask = ACI_NULL;
+ for (String a : searchAttributes)
+ {
+ if (a.equalsIgnoreCase(aclRightsAttrStr))
+ {
attrMask |= ACL_RIGHTS;
- else if(a.equalsIgnoreCase(aclRightsInfoAttrStr))
+ }
+ else if (a.equalsIgnoreCase(aclRightsInfoAttrStr))
+ {
attrMask |= ACL_RIGHTS_INFO;
- else {
- //Check for shorthands for user attributes "*" or operational "+".
- if(a.equals("*")) {
- //Add objectclass.
- AttributeType ocType =
- DirectoryServer.getObjectClassAttributeType();
- nonRightsAttrs.add(ocType);
- nonRightsAttrs.addAll(e.getUserAttributes().keySet());
- } else if (a.equals("+"))
- nonRightsAttrs.addAll(e.getOperationalAttributes().keySet());
- else {
- AttributeType attrType;
- if((attrType =
- DirectoryServer.getAttributeType(a.toLowerCase())) == null)
- attrType =
- DirectoryServer.getDefaultAttributeType(a.toLowerCase());
- nonRightsAttrs.add(attrType);
- }
+ }
+ else
+ {
+ // Check for shorthands for user attributes "*" or operational "+".
+ if (a.equals("*"))
+ {
+ // Add objectclass.
+ AttributeType ocType = DirectoryServer.getObjectClassAttributeType();
+ nonRightsAttrs.add(ocType);
+ nonRightsAttrs.addAll(e.getUserAttributes().keySet());
+ }
+ else if (a.equals("+"))
+ {
+ nonRightsAttrs.addAll(e.getOperationalAttributes().keySet());
+ }
+ else
+ {
+ AttributeType attrType = DirectoryServer.getAttributeType(a
+ .toLowerCase());
+ if (attrType == null)
+ attrType = DirectoryServer.getDefaultAttributeType(a.toLowerCase());
+ nonRightsAttrs.add(attrType);
+ }
}
}
- //If the special geteffectiverights attributes were not found or
- //the user does not have both bypass-acl privs and is not allowed to
- //perform rights evalation -- return the entry unchanged.
- if(attrMask == ACI_NULL ||
- (!skipCheck && !rightsAccessAllowed(container,handler,attrMask)))
- return e;
- //From here on out, geteffectiverights evaluation is being performed and the
- //container will be manipulated. First set the flag that geteffectiverights
- //evaluation's underway and to use the authZid for authorizationDN (they
- //might be the same).
+
+ // If the special geteffectiverights attributes were not found or
+ // the user does not have both bypass-acl privs and is not allowed to
+ // perform rights evalation -- return the entry unchanged.
+ if (attrMask == ACI_NULL
+ || (!skipCheck && !rightsAccessAllowed(container, handler, attrMask)))
+ {
+ return;
+ }
+
+ // From here on out, geteffectiverights evaluation is being performed and
+ // the container will be manipulated. First set the flag that
+ // geteffectiverights evaluation's underway and to use the authZid for
+ // authorizationDN (they might be the same).
container.setGetEffectiveRightsEval();
container.useAuthzid(true);
- //If no attributes were requested return only entryLevel rights, else
- //return attributeLevel rights and entryLevel rights. Always try and
- //return the specific attribute rights if they exist.
- if(nonRightsAttrs.isEmpty()) {
- e=addAttributeLevelRights(container,handler,attrMask,e,
- container.getSpecificAttributes(), skipCheck, true);
- e=addEntryLevelRights(container,handler,attrMask,e, skipCheck);
- } else {
- e=addAttributeLevelRights(container,handler,attrMask,e,
- nonRightsAttrs, skipCheck, false);
- e=addAttributeLevelRights(container,handler,attrMask,e,
- container.getSpecificAttributes(), skipCheck, true);
- e=addEntryLevelRights(container,handler,attrMask,e,skipCheck);
+
+ // If no attributes were requested return only entryLevel rights, else
+ // return attributeLevel rights and entryLevel rights. Always try and
+ // return the specific attribute rights if they exist.
+ if (nonRightsAttrs.isEmpty())
+ {
+ addAttributeLevelRights(container, handler, attrMask, e,
+ container.getSpecificAttributes(), skipCheck, true);
+ addEntryLevelRights(container, handler, attrMask, e, skipCheck);
}
- return e;
+ else
+ {
+ addAttributeLevelRights(container, handler, attrMask, e, nonRightsAttrs,
+ skipCheck, false);
+ addAttributeLevelRights(container, handler, attrMask, e,
+ container.getSpecificAttributes(), skipCheck, true);
+ addEntryLevelRights(container, handler, attrMask, e, skipCheck);
+ }
}
+
/**
* Perform the attributeLevel rights evaluation on a list of specified
* attribute types. Each attribute has an access check done for the following
* rights: search, read, compare, add, delete, proxy, selfwrite_add,
- * selfwrite_delete and write.
+ * selfwrite_delete and write. The special rights, selfwrite_add and
+ * selfwrite_delete, use the authZid as the attribute value to evaluate
+ * against the attribute type being evaluated. The selfwrite_add performs the
+ * access check using the ACI_WRITE_ADD right and selfwrite_delete uses
+ * ACI_WRITE_ADD right. The write right is made complicated by the
+ * targattrfilters keyword, which might depend on an unknown value of an
+ * attribute type. For this case a dummy attribute value is used to try and
+ * determine if a "?" needs to be placed in the rights string. The special
+ * flag ACI_SKIP_PROXY_CHECK is always set, so that proxy evaluation is
+ * bypassed in the Aci Handler's accessAllowed method.
*
- * The special rights, selfwrite_add and selfwrite_delete, use the authZid as
- * the attribute value to evaluate against the attribute type being
- * evaluated. The selfwrite_add performs the access check using the
- * ACI_WRITE_ADD right and selfwrite_delete uses ACI_WRITE_ADD right.
- *
- * The write right is made complicated by the targattrfilters keyword, which
- * might depend on an unknown value of an attribute type. For this case a
- * dummy attribute value is used to try and determine if a "?" needs to be
- * placed in the rights string.
- *
- * The special flag ACI_SKIP_PROXY_CHECK is always set, so that proxy
- * evaluation is bypassed in the Aci Handler's accessAllowed method.
- *
- * @param container The LDAP operation container to use in the evaluations.
- * @param handler The Aci Handler to use in the access evaluations.
- * @param mask Mask specifing what rights attribute processing to perform
- * (aclRights or aclRightsInfo or both).
- * @param retEntry The entry to return.
- * @param attrList The list of attribute types to iterate over.
- * @param skipCheck True if ACI evaluation was skipped because bypass-acl
- * privilege was found.
- * @param specificAttr True if this evaluation is result of specific
- * attributes sent in the request.
- * @return A SearchResultEntry with geteffectiverights attribute level
- * information added to it.
+ * @param container
+ * The LDAP operation container to use in the evaluations.
+ * @param handler
+ * The Aci Handler to use in the access evaluations.
+ * @param mask
+ * Mask specifing what rights attribute processing to perform
+ * (aclRights or aclRightsInfo or both).
+ * @param retEntry
+ * The entry to return.
+ * @param attrList
+ * The list of attribute types to iterate over.
+ * @param skipCheck
+ * True if ACI evaluation was skipped because bypass-acl privilege
+ * was found.
+ * @param specificAttr
+ * True if this evaluation is result of specific attributes sent in
+ * the request.
*/
- private static
- SearchResultEntry addAttributeLevelRights(AciLDAPOperationContainer container,
- AciHandler handler, int mask,
- SearchResultEntry retEntry,
- List<AttributeType> attrList,
- boolean skipCheck,
- boolean specificAttr) {
+ private static void addAttributeLevelRights(
+ AciLDAPOperationContainer container, AciHandler handler, int mask,
+ final Entry retEntry, List<AttributeType> attrList,
+ boolean skipCheck, boolean specificAttr)
+ {
- //The attribute list might be null.
- if(attrList == null)
- return retEntry;
+ // The attribute list might be null.
+ if (attrList == null) return;
+
for(AttributeType a : attrList) {
StringBuilder evalInfo=new StringBuilder();
container.setCurrentAttributeType(a);
@@ -371,33 +397,34 @@
}
container.setCurrentAttributeValue(null);
container.setCurrentAttributeType(null);
- return retEntry;
}
+
+
/**
* Perform the attributeLevel write rights evaluation. The issue here is that
* an ACI could contain a targattrfilters keyword that matches the attribute
- * being evaluated.
+ * being evaluated. There is no way of knowing if the filter part of the
+ * targattrfilter would be successful or not. So if the ACI that allowed
+ * access, has an targattrfilter keyword, a "?" is used as the result of the
+ * write (depends on attribute value). If the allow ACI doesn't contain a
+ * targattrfilters keyword than a "1" is added. If the ACI denies then a "0"
+ * is added. If the skipCheck flag is true, then a 1 is used for the write
+ * access, since the client DN has bypass privs.
*
- * There is no way of knowing if the filter part of the targattrfilter would
- * be successful or not. So if the ACI that allowed access, has an
- * targattrfilter keyword, a "?" is used as the result of the write (depends
- * on attribute value).
- *
- * If the allow ACI doesn't contain a targattrfilters keyword than a
- * "1" is added. If the ACI denies then a "0" is added. If the skipCheck flag
- * is true, then a 1 is used for the write access, since the client DN has
- * bypass privs.
- *
- * @param container The LDAP operation container to use in the evaluations.
- * @param handler The Aci Handler to use in the access evaluations.
- * @param skipCheck True if ACI evaluation was skipped because bypass-acl
- * privilege was found.
+ * @param container
+ * The LDAP operation container to use in the evaluations.
+ * @param handler
+ * The Aci Handler to use in the access evaluations.
+ * @param skipCheck
+ * True if ACI evaluation was skipped because bypass-acl privilege
+ * was found.
* @return A string representing the rights information.
*/
- private static
- String attributeLevelWriteRights(AciLDAPOperationContainer container,
- AciHandler handler, boolean skipCheck){
+ private static String attributeLevelWriteRights(
+ AciLDAPOperationContainer container, AciHandler handler,
+ boolean skipCheck)
+ {
boolean addRet=false, delRet=false;
StringBuilder resString=new StringBuilder();
//If the user has bypass-acl privs and the authzid is equal to the
@@ -443,27 +470,31 @@
return resString.toString();
}
+
+
/**
* Perform entryLevel rights evaluation. The rights string is added to the
* entry if the aclRights attribute was seen in the search's requested
* attribute set.
*
- * @param container The LDAP operation container to use in the evaluations.
- * @param handler The Aci Handler to use in the access evaluations.
- * @param mask Mask specifing what rights attribute processing to perform
- * (aclRights or aclRightsInfo or both).
- * @param retEntry The entry to return.
- * @param skipCheck True if ACI evaluation was skipped because bypass-acl
- * privilege was found.
- * @return A SearchResultEntry with geteffectiverights entryLevel rights
- * information added to it.
+ * @param container
+ * The LDAP operation container to use in the evaluations.
+ * @param handler
+ * The Aci Handler to use in the access evaluations.
+ * @param mask
+ * Mask specifing what rights attribute processing to perform
+ * (aclRights or aclRightsInfo or both).
+ * @param retEntry
+ * The entry to return.
+ * @param skipCheck
+ * True if ACI evaluation was skipped because bypass-acl privilege
+ * was found.
*/
- private static SearchResultEntry
- addEntryLevelRights(AciLDAPOperationContainer container,
- AciHandler handler,
- int mask, SearchResultEntry retEntry,
- boolean skipCheck) {
+ private static void addEntryLevelRights(AciLDAPOperationContainer container,
+ AciHandler handler, int mask, final Entry retEntry,
+ boolean skipCheck)
+ {
//Perform access evaluations for rights: add, delete, read, write, proxy.
StringBuilder evalInfo=new StringBuilder();
container.setCurrentAttributeType(null);
@@ -479,13 +510,11 @@
container.setCurrentAttributeType(null);
//The read right needs the entry with the full set of attributes. This was
//saved in the Aci Handlers maysend method.
- container.useFullResourceEntry(true);
container.setRights(ACI_READ | ACI_SKIP_PROXY_CHECK);
evalInfo.append(rightsString(container, handler, skipCheck, "read"));
addEntryLevelRightsInfo(container, mask, retEntry, "read");
evalInfo.append(',');
//Switch back to the entry from the Aci Handler's filterentry method.
- container.useFullResourceEntry(false);
container.setCurrentAttributeType(null);
container.setRights(ACI_WRITE| ACI_SKIP_PROXY_CHECK);
evalInfo.append(rightsString(container, handler, skipCheck, "write"));
@@ -502,7 +531,6 @@
.toString());
retEntry.addAttribute(attr,null);
}
- return retEntry;
}
/**
@@ -593,7 +621,7 @@
*/
private static
void addAttrLevelRightsInfo(AciLDAPOperationContainer container, int mask,
- AttributeType aType, SearchResultEntry retEntry,
+ AttributeType aType, Entry retEntry,
String rightStr) {
//Check if the aclRightsInfo attribute was requested.
@@ -625,7 +653,7 @@
*/
private static
void addEntryLevelRightsInfo(AciLDAPOperationContainer container, int mask,
- SearchResultEntry retEntry,
+ Entry retEntry,
String rightStr) {
//Check if the aclRightsInfo attribute was requested.
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciEvalContext.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciEvalContext.java
index 50ae0dd..fc62e3d 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciEvalContext.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciEvalContext.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2008-2010 Sun Microsystems, Inc.
+ * Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.authorization.dseecompat;
@@ -303,30 +304,13 @@
public String rightToString();
/**
- * Return the name of the ACI that last matched a targattrfilters rule. Used
- * in geteffectiverights control evaluation.
- *
- * @return The name of the ACI that last matched a targattrfilters rule.
- */
+ * Return the name of the ACI that last matched a targattrfilters rule. Used
+ * in geteffectiverights control evaluation.
+ *
+ * @return The name of the ACI that last matched a targattrfilters rule.
+ */
public String getTargAttrFiltersAciName();
- /**
- * The full entry with all of the attributes was saved
- * in the operation's attachment mechanism when the container was created
- * during the SearchOperation read evaluation. Some operations need the full
- * entry and not the filtered entry to perform their evaluations, because they
- * might depend attribute types and values filtered out.
- *
- * This method is used to replace the current resource entry with that saved
- * entry and back.
- *
- * @param val Specifies if the saved entry should be used or not. {@code true}
- * if it should be used, {@code false} if the original resource entry should
- * be used.
- *
- */
- public void useFullResourceEntry(boolean val);
-
/**
* Return the current SSF (Security Strength Factor) of the underlying
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
index f2130db..ccae97b 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2008-2010 Sun Microsystems, Inc.
+ * Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.authorization.dseecompat;
@@ -94,15 +95,6 @@
AccessControlHandler<DseeCompatAccessControlHandlerCfg>
{
/**
- * String used to save a resource entry containing all the attributes
- * in the SearchOperation attachment list. This is only used during
- * geteffectiverights read right processing when all of an entry'ss
- * attributes need to examined.
- */
- public static final String ALL_ATTRS_RESOURCE_ENTRY =
- "allAttrsResourceEntry";
-
- /**
* String used to indicate that the evaluating ACI had a all
* operational attributes targetattr match (targetattr="+").
*/
@@ -234,46 +226,29 @@
* {@inheritDoc}
*/
@Override
- public SearchResultEntry filterEntry(SearchOperation operation,
- SearchResultEntry entry)
+ public void filterEntry(Operation operation,
+ SearchResultEntry unfilteredEntry, SearchResultEntry filteredEntry)
{
AciLDAPOperationContainer operationContainer =
- new AciLDAPOperationContainer(operation, (ACI_READ), entry);
+ new AciLDAPOperationContainer(operation, (ACI_READ), unfilteredEntry);
+
// Proxy access check has already been done for this entry in the
// maySend method, set the seen flag to true to bypass any proxy
// check.
operationContainer.setSeenEntry(true);
- SearchResultEntry returnEntry;
+
boolean skipCheck = skipAccessCheck(operation);
if (!skipCheck)
{
- returnEntry = accessAllowedAttrs(operationContainer);
+ filterEntry(operationContainer, filteredEntry);
}
- else
- {
- returnEntry = entry;
- }
+
if (operationContainer.hasGetEffectiveRightsControl())
{
- returnEntry =
- AciEffectiveRights.addRightsToEntry(this, operation
- .getAttributes(), operationContainer, returnEntry,
- skipCheck);
+ AciEffectiveRights.addRightsToEntry(this,
+ ((SearchOperation) operation).getAttributes(), operationContainer,
+ filteredEntry, skipCheck);
}
- return returnEntry;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public SearchResultEntry filterEntry(Operation operation, Entry entry)
- {
- AciLDAPOperationContainer operationContainer =
- new AciLDAPOperationContainer(operation, (ACI_READ), entry);
- return accessAllowedAttrs(operationContainer);
}
@@ -595,7 +570,7 @@
* {@inheritDoc}
*/
@Override
- public boolean maySend(DN dn, SearchOperation operation,
+ public boolean maySend(DN dn, Operation operation,
SearchResultReference reference)
{
boolean ret;
@@ -625,57 +600,55 @@
/**
- * Checks access on a search operation.
- *
- * @param operation
- * The search operation class containing information to check
- * the access on.
- * @param entry
- * The entry to evaluate access.
- * @return True if access is allowed.
+ * {@inheritDoc}
*/
@Override
- public boolean maySend(SearchOperation operation,
- SearchResultEntry entry)
+ public boolean maySend(Operation operation, SearchResultEntry entry)
{
+ if (skipAccessCheck(operation))
+ {
+ return true;
+ }
+
AciLDAPOperationContainer operationContainer =
- new AciLDAPOperationContainer(operation, (ACI_SEARCH), entry);
- boolean ret;
- if (!(ret = skipAccessCheck(operation)))
+ new AciLDAPOperationContainer(operation, (ACI_SEARCH), entry);
+
+ // Pre/post read controls are associated with other types of operation.
+ if (operation instanceof SearchOperation)
{
try
{
- ret = testFilter(operationContainer, operation.getFilter());
+ if (!testFilter(operationContainer,
+ ((SearchOperation) operation).getFilter()))
+ {
+ return false;
+ }
}
catch (DirectoryException ex)
{
- ret = false;
- }
- if (ret)
- {
- operationContainer.clearEvalAttributes(ACI_NULL);
- operationContainer.setRights(ACI_READ);
- ret = accessAllowedEntry(operationContainer);
- if (ret)
- {
- if (!operationContainer.hasEvalUserAttributes())
- {
- operation.setAttachment(ALL_USER_ATTRS_MATCHED,
- ALL_USER_ATTRS_MATCHED);
- }
- if (!operationContainer.hasEvalOpAttributes())
- {
- operation.setAttachment(ALL_OP_ATTRS_MATCHED,
- ALL_OP_ATTRS_MATCHED);
- }
- }
+ return false;
}
}
- // Save a copy of the full resource entry for possible
- // userattr bind rule or geteffectiveright's evaluations in the
- // filterEnty method.
- operation.setAttachment(ALL_ATTRS_RESOURCE_ENTRY, entry);
- return ret;
+
+ operationContainer.clearEvalAttributes(ACI_NULL);
+ operationContainer.setRights(ACI_READ);
+
+ if (!accessAllowedEntry(operationContainer))
+ {
+ return false;
+ }
+
+ if (!operationContainer.hasEvalUserAttributes())
+ {
+ operation.setAttachment(ALL_USER_ATTRS_MATCHED, ALL_USER_ATTRS_MATCHED);
+ }
+
+ if (!operationContainer.hasEvalOpAttributes())
+ {
+ operation.setAttachment(ALL_OP_ATTRS_MATCHED, ALL_OP_ATTRS_MATCHED);
+ }
+
+ return true;
}
@@ -855,23 +828,21 @@
/**
- * 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.
+ * 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.
- * @return The entry to send back to the client, minus any attribute
- * types that failed access check.
+ * 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 SearchResultEntry accessAllowedAttrs(
- AciLDAPOperationContainer container)
+ private void filterEntry(AciLDAPOperationContainer container,
+ Entry filteredEntry)
{
- Entry e = container.getResourceEntry();
- List<AttributeType> typeList = getAllAttrs(e);
+ List<AttributeType> typeList = getAllAttrs(filteredEntry);
for (AttributeType attrType : typeList)
{
if (container.hasAllUserAttributes() && !attrType.isOperational())
@@ -885,10 +856,9 @@
container.setCurrentAttributeType(attrType);
if (!accessAllowed(container))
{
- e.removeAttribute(attrType);
+ filteredEntry.removeAttribute(attrType);
}
}
- return container.getSearchResultEntry();
}
@@ -914,7 +884,8 @@
{
Entry resourceEntry = container.getResourceEntry();
DN dn = resourceEntry.getDN();
- List<Modification> modifications = container.getModifications();
+ List<Modification> modifications = operation.getModifications();
+
for (Modification m : modifications)
{
Attribute modAttr = m.getAttribute();
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java
index 5840077..45b1454 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java
@@ -23,11 +23,11 @@
*
*
* Copyright 2008-2009 Sun Microsystems, Inc.
+ * Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.authorization.dseecompat;
-import java.util.List;
import org.opends.server.core.*;
import org.opends.server.types.*;
import org.opends.server.workflowelement.localbackend.*;
@@ -39,17 +39,6 @@
*/
public class AciLDAPOperationContainer extends AciContainer {
- /*
- * The entry to be returned if this is a LDAP search.
- */
- private SearchResultEntry searchEntry;
-
- /*
- * The list of modifications if this operation is a LDAP
- * modify.
- */
- private List<Modification> modifications;
-
/**
* Constructor interface for all currently supported LDAP operations.
* @param operation The compare operation to evaluate.
@@ -60,7 +49,6 @@
int rights, Entry entry)
{
super(operation, rights, entry);
- this.searchEntry = new SearchResultEntry(entry);
}
@@ -149,7 +137,6 @@
int rights)
{
super(operation, rights, operation.getCurrentEntry());
- this.modifications=operation.getModifications();
}
/**
@@ -163,33 +150,4 @@
Entry entry) {
super(operation, rights, entry);
}
-
- /**
- * Constructor interface for the LDAP search operation.
- * @param operation The search operation.
- * @param rights The rights of a search operation.
- * @param entry The entry to be evaluated for this search.
- */
- public AciLDAPOperationContainer(SearchOperation operation,
- int rights,
- SearchResultEntry entry)
- {
- super(operation, rights, entry);
- this.searchEntry = entry;
- }
-
- /**
- * Retrieve the search result entry of the search operation.
- * @return The search result entry.
- */
- public SearchResultEntry getSearchResultEntry() {
- return this.searchEntry;
- }
-
- /** Retrieve the list of modifications if this is a LDAP modify.
- * @return The list of LDAP modifications to made on the resource entry.
- */
- public List<Modification> getModifications() {
- return modifications;
- }
}
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/UserAttr.java b/opends/src/server/org/opends/server/authorization/dseecompat/UserAttr.java
index c496469..bf1173c 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/UserAttr.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/UserAttr.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2008 Sun Microsystems, Inc.
+ * Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.authorization.dseecompat;
@@ -174,29 +175,26 @@
* @return An enumeration containing the result of the evaluation.
*/
public EnumEvalResult evaluate(AciEvalContext evalCtx) {
- EnumEvalResult matched;
- //The working resource entry might be filtered and not have an
- //attribute type that is needed to perform these evaluations. The
- //evalCtx has a copy of the non-filtered entry, switch to it for these
- //evaluations.
- evalCtx.useFullResourceEntry(true);
- switch(userAttrType) {
- case ROLEDN:
- case GROUPDN:
- case USERDN: {
- matched=evalDNKeywords(evalCtx);
- break;
- }
- case URL: {
- matched=evalURL(evalCtx);
- break;
- }
- default:
- matched=evalVAL(evalCtx);
- }
- //Switch back to the working resource entry.
- evalCtx.useFullResourceEntry(false);
- return matched;
+ EnumEvalResult matched;
+ //The working resource entry might be filtered and not have an
+ //attribute type that is needed to perform these evaluations. The
+ //evalCtx has a copy of the non-filtered entry, switch to it for these
+ //evaluations.
+ switch(userAttrType) {
+ case ROLEDN:
+ case GROUPDN:
+ case USERDN: {
+ matched=evalDNKeywords(evalCtx);
+ break;
+ }
+ case URL: {
+ matched=evalURL(evalCtx);
+ break;
+ }
+ default:
+ matched=evalVAL(evalCtx);
+ }
+ return matched;
}
/** Evaluate a VALUE userattr type. Look in client entry for an
diff --git a/opends/src/server/org/opends/server/core/DefaultAccessControlHandler.java b/opends/src/server/org/opends/server/core/DefaultAccessControlHandler.java
index c5c888a..40ebc16 100644
--- a/opends/src/server/org/opends/server/core/DefaultAccessControlHandler.java
+++ b/opends/src/server/org/opends/server/core/DefaultAccessControlHandler.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2006-2009 Sun Microsystems, Inc.
+ * Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.core;
@@ -48,13 +49,6 @@
extends AccessControlHandler<AccessControlHandlerCfg>
{
/**
- * The single handler instance.
- */
- private static DefaultAccessControlHandler instance = null;
-
-
-
- /**
* Create a new default access control handler.
*/
public DefaultAccessControlHandler()
@@ -204,22 +198,21 @@
* {@inheritDoc}
*/
@Override
- public boolean maySend(SearchOperation searchOperation,
- SearchResultEntry searchEntry)
+ public boolean maySend(Operation operation, SearchResultEntry unfilteredEntry)
{
return true;
}
+
/**
* {@inheritDoc}
*/
@Override
- public SearchResultEntry filterEntry(SearchOperation searchOperation,
- SearchResultEntry searchEntry)
+ public void filterEntry(Operation operation,
+ SearchResultEntry unfilteredEntry, SearchResultEntry filteredEntry)
{
- // No implementation required.
- return searchEntry;
+ return;
}
@@ -228,19 +221,7 @@
* {@inheritDoc}
*/
@Override
- public SearchResultEntry filterEntry(Operation operation, Entry entry)
- {
- // No implementation required.
- return new SearchResultEntry(entry);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean maySend(DN dn, SearchOperation searchOperation,
+ public boolean maySend(DN dn, Operation operation,
SearchResultReference searchReference)
{
return true;
diff --git a/opends/src/server/org/opends/server/core/SearchOperationBasis.java b/opends/src/server/org/opends/server/core/SearchOperationBasis.java
index 715c3fb..ace7465 100644
--- a/opends/src/server/org/opends/server/core/SearchOperationBasis.java
+++ b/opends/src/server/org/opends/server/core/SearchOperationBasis.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2006-2010 Sun Microsystems, Inc.
+ * Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.core;
@@ -691,12 +692,13 @@
}
// Check to see if the entry can be read by the client.
+ SearchResultEntry unfilteredSearchEntry = new SearchResultEntry(entry,
+ controls);
if (evaluateAci)
{
- SearchResultEntry tmpSearchEntry = new SearchResultEntry(entry,
- controls);
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().maySend(this, tmpSearchEntry) == false) {
+ if (AccessControlConfigManager.getInstance().getAccessControlHandler()
+ .maySend(this, unfilteredSearchEntry) == false)
+ {
return true;
}
}
@@ -705,7 +707,7 @@
// of requested attributes.
// NOTE: that this copy will include the objectClass attribute.
- Entry entryToReturn =
+ Entry filteredEntry =
entry.filterEntry(getAttributes(), typesOnly,
isVirtualAttributesOnly(), isRealAttributesOnly());
@@ -721,7 +723,7 @@
// dealt with later.
AttributeType attrType = DirectoryServer.getObjectClassAttributeType();
Iterator<String> ocIterator =
- entryToReturn.getObjectClasses().values().iterator();
+ filteredEntry.getObjectClasses().values().iterator();
while (ocIterator.hasNext())
{
String ocName = ocIterator.next();
@@ -735,7 +737,7 @@
// Next, the set of user attributes (incl. objectClass attribute).
- for (Map.Entry<AttributeType, List<Attribute>> e : entryToReturn
+ for (Map.Entry<AttributeType, List<Attribute>> e : filteredEntry
.getUserAttributes().entrySet())
{
AttributeType t = e.getKey();
@@ -762,7 +764,7 @@
// Then the set of operational attributes.
- for (Map.Entry<AttributeType, List<Attribute>> e : entryToReturn
+ for (Map.Entry<AttributeType, List<Attribute>> e : filteredEntry
.getOperationalAttributes().entrySet())
{
AttributeType t = e.getKey();
@@ -790,8 +792,8 @@
// Convert the provided entry to a search result entry.
- SearchResultEntry searchEntry = new SearchResultEntry(entryToReturn,
- controls);
+ SearchResultEntry filteredSearchEntry = new SearchResultEntry(
+ filteredEntry, controls);
// Strip out any attributes that the client does not have access to.
@@ -799,24 +801,24 @@
// values that the client is not permitted to see.
if (evaluateAci)
{
- searchEntry = AccessControlConfigManager.getInstance()
- .getAccessControlHandler().filterEntry(this, searchEntry);
+ AccessControlConfigManager.getInstance().getAccessControlHandler()
+ .filterEntry(this, unfilteredSearchEntry, filteredSearchEntry);
}
// Invoke any search entry plugins that may be registered with the server.
PluginResult.IntermediateResponse pluginResult =
DirectoryServer.getPluginConfigManager().
- invokeSearchResultEntryPlugins(this, searchEntry);
+ invokeSearchResultEntryPlugins(this, filteredSearchEntry);
// Send the entry to the client.
if (pluginResult.sendResponse())
{
// Log the entry sent to the client.
- logSearchResultEntry(this, searchEntry);
+ logSearchResultEntry(this, filteredSearchEntry);
try
{
- sendSearchEntry(searchEntry);
+ sendSearchEntry(filteredSearchEntry);
incrementEntriesSent();
}
diff --git a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java
index 8214122..3ca1ef8 100644
--- a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java
+++ b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2008-2010 Sun Microsystems, Inc.
+ * Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.workflowelement.localbackend;
@@ -55,7 +56,6 @@
import org.opends.server.api.plugin.PluginResult;
import org.opends.server.controls.LDAPAssertionRequestControl;
import org.opends.server.controls.LDAPPostReadRequestControl;
-import org.opends.server.controls.LDAPPostReadResponseControl;
import org.opends.server.controls.PasswordPolicyErrorType;
import org.opends.server.controls.PasswordPolicyResponseControl;
import org.opends.server.controls.ProxiedAuthV1Control;
@@ -263,7 +263,7 @@
// Invoke any conflict resolution processing that might be needed by the
// synchronization provider.
- for (SynchronizationProvider provider :
+ for (SynchronizationProvider<?> provider :
DirectoryServer.getSynchronizationProviders())
{
try
@@ -643,7 +643,7 @@
}
else
{
- for (SynchronizationProvider provider :
+ for (SynchronizationProvider<?> provider :
DirectoryServer.getSynchronizationProviders())
{
try
@@ -676,11 +676,8 @@
backend.addEntry(entry, this);
}
- if (postReadRequest != null)
- {
- addPostReadResponse();
- }
-
+ LocalBackendWorkflowElement.addPostReadResponse(this,
+ postReadRequest, entry);
if (! noOp)
{
@@ -700,7 +697,7 @@
}
finally
{
- for (SynchronizationProvider provider :
+ for (SynchronizationProvider<?> provider :
DirectoryServer.getSynchronizationProviders())
{
try
@@ -1204,7 +1201,7 @@
// Encode the password.
if (passwordPolicy.usesAuthPasswordSyntax())
{
- for (PasswordStorageScheme s : defaultStorageSchemes)
+ for (PasswordStorageScheme<?> s : defaultStorageSchemes)
{
ByteString encodedValue = s.encodeAuthPassword(value);
builder.add(AttributeValues.create(
@@ -1213,7 +1210,7 @@
}
else
{
- for (PasswordStorageScheme s : defaultStorageSchemes)
+ for (PasswordStorageScheme<?> s : defaultStorageSchemes)
{
ByteString encodedValue = s.encodePasswordWithScheme(value);
builder.add(AttributeValues.create(
@@ -1609,58 +1606,5 @@
}
}
}
-
-
-
- /**
- * Adds the post-read response control to the response.
- */
- protected void addPostReadResponse()
- {
- Entry addedEntry = entry.duplicate(true);
-
- if (! postReadRequest.allowsAttribute(
- DirectoryServer.getObjectClassAttributeType()))
- {
- addedEntry.removeAttribute(DirectoryServer.getObjectClassAttributeType());
- }
-
- if (! postReadRequest.returnAllUserAttributes())
- {
- Iterator<AttributeType> iterator =
- addedEntry.getUserAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! postReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- if (! postReadRequest.returnAllOperationalAttributes())
- {
- Iterator<AttributeType> iterator =
- addedEntry.getOperationalAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! postReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- // Check access controls on the entry and strip out
- // any not allowed attributes.
- SearchResultEntry searchEntry =
- AccessControlConfigManager.getInstance().
- getAccessControlHandler().filterEntry(this, addedEntry);
- LDAPPostReadResponseControl responseControl =
- new LDAPPostReadResponseControl(searchEntry);
- addResponseControl(responseControl);
- }
}
diff --git a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendCompareOperation.java b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendCompareOperation.java
index 1c42ff6..b37d0ae 100644
--- a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendCompareOperation.java
+++ b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendCompareOperation.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2008-2009 Sun Microsystems, Inc.
+ * Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.workflowelement.localbackend;
@@ -52,7 +53,6 @@
import static org.opends.messages.CoreMessages.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.util.ServerConstants.*;
-import static org.opends.server.util.StaticUtils.*;
diff --git a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendDeleteOperation.java b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendDeleteOperation.java
index c33d77f..d15fd66 100644
--- a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendDeleteOperation.java
+++ b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendDeleteOperation.java
@@ -23,12 +23,12 @@
*
*
* Copyright 2008-2009 Sun Microsystems, Inc.
+ * Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.workflowelement.localbackend;
-import java.util.Iterator;
import java.util.List;
import java.util.concurrent.locks.Lock;
@@ -46,7 +46,6 @@
import org.opends.server.core.PersistentSearch;
import org.opends.server.core.PluginConfigManager;
import org.opends.server.loggers.debug.DebugTracer;
-import org.opends.server.types.AttributeType;
import org.opends.server.types.CanceledOperationException;
import org.opends.server.types.Control;
import org.opends.server.types.DebugLogLevel;
@@ -57,7 +56,6 @@
import org.opends.server.types.Privilege;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchFilter;
-import org.opends.server.types.SearchResultEntry;
import org.opends.server.types.SynchronizationProviderResult;
import org.opends.server.types.operation.PostOperationDeleteOperation;
import org.opends.server.types.operation.PostResponseDeleteOperation;
@@ -410,7 +408,8 @@
}
- processPreReadControl();
+ LocalBackendWorkflowElement.addPreReadResponse(this,
+ preReadRequest, entry);
if (! noOp)
@@ -662,62 +661,6 @@
/**
- * Performs any processing needed for the LDAP pre-read control.
- */
- protected void processPreReadControl()
- {
- if (preReadRequest != null)
- {
- Entry entryCopy = entry.duplicate(true);
-
- if (! preReadRequest.allowsAttribute(
- DirectoryServer.getObjectClassAttributeType()))
- {
- entryCopy.removeAttribute(
- DirectoryServer.getObjectClassAttributeType());
- }
-
- if (! preReadRequest.returnAllUserAttributes())
- {
- Iterator<AttributeType> iterator =
- entryCopy.getUserAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! preReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- if (! preReadRequest.returnAllOperationalAttributes())
- {
- Iterator<AttributeType> iterator =
- entryCopy.getOperationalAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! preReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- // Check access controls on the entry and strip out
- // any not allowed attributes.
- SearchResultEntry searchEntry =
- AccessControlConfigManager.getInstance().
- getAccessControlHandler().filterEntry(this, entryCopy);
- LDAPPreReadResponseControl responseControl =
- new LDAPPreReadResponseControl(preReadRequest.isCritical(),
- searchEntry);
- addResponseControl(responseControl);
- }
- }
-
- /**
* Handle conflict resolution.
* @return {@code true} if processing should continue for the operation, or
* {@code false} if not.
diff --git a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyDNOperation.java b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyDNOperation.java
index 2be70b8..4fb55d9 100644
--- a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyDNOperation.java
+++ b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyDNOperation.java
@@ -23,12 +23,12 @@
*
*
* Copyright 2008-2010 Sun Microsystems, Inc.
+ * Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.workflowelement.localbackend;
-import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Lock;
@@ -42,9 +42,7 @@
import org.opends.server.api.plugin.PluginResult;
import org.opends.server.controls.LDAPAssertionRequestControl;
import org.opends.server.controls.LDAPPostReadRequestControl;
-import org.opends.server.controls.LDAPPostReadResponseControl;
import org.opends.server.controls.LDAPPreReadRequestControl;
-import org.opends.server.controls.LDAPPreReadResponseControl;
import org.opends.server.controls.ProxiedAuthV1Control;
import org.opends.server.controls.ProxiedAuthV2Control;
import org.opends.server.core.AccessControlConfigManager;
@@ -71,7 +69,6 @@
import org.opends.server.types.RDN;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchFilter;
-import org.opends.server.types.SearchResultEntry;
import org.opends.server.types.SynchronizationProviderResult;
import org.opends.server.types.operation.PostOperationModifyDNOperation;
import org.opends.server.types.operation.PostResponseModifyDNOperation;
@@ -631,7 +628,10 @@
// Attach the pre-read and/or post-read controls to the response if
// appropriate.
- processReadEntryControls();
+ LocalBackendWorkflowElement.addPreReadResponse(this,
+ preReadRequest, currentEntry);
+ LocalBackendWorkflowElement.addPostReadResponse(this,
+ postReadRequest, newEntry);
if (! noOp)
@@ -1077,114 +1077,6 @@
/**
- * Performs any necessary processing to create the pre-read and/or post-read
- * response controls and attach them to the response.
- */
- protected void processReadEntryControls()
- {
- if (preReadRequest != null)
- {
- Entry entry = currentEntry.duplicate(true);
-
- if (! preReadRequest.allowsAttribute(
- DirectoryServer.getObjectClassAttributeType()))
- {
- entry.removeAttribute(
- DirectoryServer.getObjectClassAttributeType());
- }
-
- if (! preReadRequest.returnAllUserAttributes())
- {
- Iterator<AttributeType> iterator =
- entry.getUserAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! preReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- if (! preReadRequest.returnAllOperationalAttributes())
- {
- Iterator<AttributeType> iterator =
- entry.getOperationalAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! preReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- // Check access controls on the entry and strip out
- // any not allowed attributes.
- SearchResultEntry searchEntry =
- AccessControlConfigManager.getInstance().
- getAccessControlHandler().filterEntry(this, entry);
- LDAPPreReadResponseControl responseControl =
- new LDAPPreReadResponseControl(preReadRequest.isCritical(),
- searchEntry);
-
- addResponseControl(responseControl);
- }
-
- if (postReadRequest != null)
- {
- Entry entry = newEntry.duplicate(true);
-
- if (! postReadRequest.allowsAttribute(
- DirectoryServer.getObjectClassAttributeType()))
- {
- entry.removeAttribute(
- DirectoryServer.getObjectClassAttributeType());
- }
-
- if (! postReadRequest.returnAllUserAttributes())
- {
- Iterator<AttributeType> iterator =
- entry.getUserAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! postReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- if (! postReadRequest.returnAllOperationalAttributes())
- {
- Iterator<AttributeType> iterator =
- entry.getOperationalAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! postReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- // Check access controls on the entry and strip out
- // any not allowed attributes.
- SearchResultEntry searchEntry =
- AccessControlConfigManager.getInstance().
- getAccessControlHandler().filterEntry(this, entry);
- LDAPPostReadResponseControl responseControl =
- new LDAPPostReadResponseControl(searchEntry);
-
- addResponseControl(responseControl);
- }
- }
-
- /**
* Handle conflict resolution.
* @return {@code true} if processing should continue for the operation, or
* {@code false} if not.
diff --git a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
index c011803..d92813e 100644
--- a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
+++ b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
@@ -23,6 +23,7 @@
*
*
* Copyright 2008-2009 Sun Microsystems, Inc.
+ * Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.workflowelement.localbackend;
@@ -52,9 +53,7 @@
import org.opends.server.api.plugin.PluginResult;
import org.opends.server.controls.LDAPAssertionRequestControl;
import org.opends.server.controls.LDAPPostReadRequestControl;
-import org.opends.server.controls.LDAPPostReadResponseControl;
import org.opends.server.controls.LDAPPreReadRequestControl;
-import org.opends.server.controls.LDAPPreReadResponseControl;
import org.opends.server.controls.PasswordPolicyErrorType;
import org.opends.server.controls.PasswordPolicyResponseControl;
import org.opends.server.controls.ProxiedAuthV1Control;
@@ -652,7 +651,10 @@
// Handle any processing that may be needed for the pre-read and/or
// post-read controls.
- handleReadEntryProcessing();
+ LocalBackendWorkflowElement.addPreReadResponse(this,
+ preReadRequest, currentEntry);
+ LocalBackendWorkflowElement.addPostReadResponse(this,
+ postReadRequest, modifiedEntry);
if (! noOp)
@@ -2108,115 +2110,6 @@
/**
- * Handles any processing that is required for the LDAP pre-read and/or
- * post-read controls.
- */
- protected void handleReadEntryProcessing()
- {
- if (preReadRequest != null)
- {
- Entry entry = currentEntry.duplicate(true);
-
- if (! preReadRequest.allowsAttribute(
- DirectoryServer.getObjectClassAttributeType()))
- {
- entry.removeAttribute(
- DirectoryServer.getObjectClassAttributeType());
- }
-
- if (! preReadRequest.returnAllUserAttributes())
- {
- Iterator<AttributeType> iterator =
- entry.getUserAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! preReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- if (! preReadRequest.returnAllOperationalAttributes())
- {
- Iterator<AttributeType> iterator =
- entry.getOperationalAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! preReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- // Check access controls on the entry and strip out
- // any not allowed attributes.
- SearchResultEntry searchEntry =
- AccessControlConfigManager.getInstance().
- getAccessControlHandler().filterEntry(this, entry);
- LDAPPreReadResponseControl responseControl =
- new LDAPPreReadResponseControl(preReadRequest.isCritical(),
- searchEntry);
- getResponseControls().add(responseControl);
- }
-
- if (postReadRequest != null)
- {
- Entry entry = modifiedEntry.duplicate(true);
-
- if (! postReadRequest.allowsAttribute(
- DirectoryServer.getObjectClassAttributeType()))
- {
- entry.removeAttribute(
- DirectoryServer.getObjectClassAttributeType());
- }
-
- if (! postReadRequest.returnAllUserAttributes())
- {
- Iterator<AttributeType> iterator =
- entry.getUserAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! postReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- if (! postReadRequest.returnAllOperationalAttributes())
- {
- Iterator<AttributeType> iterator =
- entry.getOperationalAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! postReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- // Check access controls on the entry and strip out
- // any not allowed attributes.
- SearchResultEntry searchEntry =
- AccessControlConfigManager.getInstance().
- getAccessControlHandler().filterEntry(this, entry);
- LDAPPostReadResponseControl responseControl =
- new LDAPPostReadResponseControl(searchEntry);
-
- getResponseControls().add(responseControl);
- }
- }
-
-
-
- /**
* Handle conflict resolution.
* @return {@code true} if processing should continue for the operation, or
* {@code false} if not.
diff --git a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
index 6c5d318..def6b50 100644
--- a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
+++ b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
@@ -23,12 +23,14 @@
*
*
* Copyright 2008-2010 Sun Microsystems, Inc.
+ * Portions Copyright 2011 ForgeRock AS
*/
package org.opends.server.workflowelement.localbackend;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import java.util.TreeMap;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -41,15 +43,11 @@
import org.opends.server.admin.std.server.RootCfg;
import org.opends.server.api.Backend;
import org.opends.server.config.ConfigException;
-import org.opends.server.core.AddOperation;
-import org.opends.server.core.BindOperation;
-import org.opends.server.core.CompareOperation;
-import org.opends.server.core.DeleteOperation;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.ModifyDNOperation;
-import org.opends.server.core.ModifyOperation;
-import org.opends.server.core.PersistentSearch;
-import org.opends.server.core.SearchOperation;
+import org.opends.server.controls.LDAPPostReadRequestControl;
+import org.opends.server.controls.LDAPPostReadResponseControl;
+import org.opends.server.controls.LDAPPreReadRequestControl;
+import org.opends.server.controls.LDAPPreReadResponseControl;
+import org.opends.server.core.*;
import org.opends.server.types.*;
import org.opends.server.workflowelement.LeafWorkflowElement;
@@ -326,6 +324,160 @@
/**
+ * Adds the post-read response control to the response if requested.
+ *
+ * @param operation
+ * The update operation.
+ * @param postReadRequest
+ * The request control, if present.
+ * @param entry
+ * The post-update entry.
+ */
+ static void addPostReadResponse(final Operation operation,
+ final LDAPPostReadRequestControl postReadRequest, final Entry entry)
+ {
+ if (postReadRequest == null)
+ {
+ return;
+ }
+
+ // Even though the associated update succeeded, we should still check
+ // whether or not we should return the entry.
+ final SearchResultEntry unfilteredEntry =
+ new SearchResultEntry(entry, null);
+ if (AccessControlConfigManager.getInstance().getAccessControlHandler()
+ .maySend(operation, unfilteredEntry) == false)
+ {
+ return;
+ }
+
+ final SearchResultEntry filteredEntry = new SearchResultEntry(
+ entry.duplicate(true), null);
+
+ if (!postReadRequest.allowsAttribute(DirectoryServer
+ .getObjectClassAttributeType()))
+ {
+ filteredEntry.removeAttribute(DirectoryServer
+ .getObjectClassAttributeType());
+ }
+
+ if (!postReadRequest.returnAllUserAttributes())
+ {
+ Iterator<AttributeType> iterator = filteredEntry.getUserAttributes()
+ .keySet().iterator();
+ while (iterator.hasNext())
+ {
+ final AttributeType attrType = iterator.next();
+ if (!postReadRequest.allowsAttribute(attrType))
+ {
+ iterator.remove();
+ }
+ }
+ }
+
+ if (!postReadRequest.returnAllOperationalAttributes())
+ {
+ final Iterator<AttributeType> iterator = filteredEntry
+ .getOperationalAttributes().keySet().iterator();
+ while (iterator.hasNext())
+ {
+ AttributeType attrType = iterator.next();
+ if (!postReadRequest.allowsAttribute(attrType))
+ {
+ iterator.remove();
+ }
+ }
+ }
+
+ // Strip out any attributes which access control denies access to.
+ AccessControlConfigManager.getInstance().getAccessControlHandler()
+ .filterEntry(operation, unfilteredEntry, filteredEntry);
+
+ final LDAPPostReadResponseControl responseControl =
+ new LDAPPostReadResponseControl(filteredEntry);
+ operation.addResponseControl(responseControl);
+ }
+
+
+
+ /**
+ * Adds the pre-read response control to the response if requested.
+ *
+ * @param operation
+ * The update operation.
+ * @param preReadRequest
+ * The request control, if present.
+ * @param entry
+ * The pre-update entry.
+ */
+ static void addPreReadResponse(final Operation operation,
+ final LDAPPreReadRequestControl preReadRequest, final Entry entry)
+ {
+ if (preReadRequest == null)
+ {
+ return;
+ }
+
+ // Even though the associated update succeeded, we should still check
+ // whether or not we should return the entry.
+ final SearchResultEntry unfilteredEntry =
+ new SearchResultEntry(entry, null);
+ if (AccessControlConfigManager.getInstance().getAccessControlHandler()
+ .maySend(operation, unfilteredEntry) == false)
+ {
+ return;
+ }
+
+ final SearchResultEntry filteredEntry = new SearchResultEntry(
+ entry.duplicate(true), null);
+
+ if (!preReadRequest.allowsAttribute(DirectoryServer
+ .getObjectClassAttributeType()))
+ {
+ filteredEntry.removeAttribute(DirectoryServer
+ .getObjectClassAttributeType());
+ }
+
+ if (!preReadRequest.returnAllUserAttributes())
+ {
+ Iterator<AttributeType> iterator = filteredEntry.getUserAttributes()
+ .keySet().iterator();
+ while (iterator.hasNext())
+ {
+ final AttributeType attrType = iterator.next();
+ if (!preReadRequest.allowsAttribute(attrType))
+ {
+ iterator.remove();
+ }
+ }
+ }
+
+ if (!preReadRequest.returnAllOperationalAttributes())
+ {
+ final Iterator<AttributeType> iterator = filteredEntry
+ .getOperationalAttributes().keySet().iterator();
+ while (iterator.hasNext())
+ {
+ AttributeType attrType = iterator.next();
+ if (!preReadRequest.allowsAttribute(attrType))
+ {
+ iterator.remove();
+ }
+ }
+ }
+
+ // Strip out any attributes which access control denies access to.
+ AccessControlConfigManager.getInstance().getAccessControlHandler()
+ .filterEntry(operation, unfilteredEntry, filteredEntry);
+
+ final LDAPPreReadResponseControl responseControl =
+ new LDAPPreReadResponseControl(filteredEntry);
+ operation.addResponseControl(responseControl);
+ }
+
+
+
+ /**
* Registers a local backend with the server.
*
* @param localBackend the local backend to register with the server
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTests.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTests.java
index 0ed63aa..818bc54 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTests.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTests.java
@@ -2081,7 +2081,7 @@
* @throws Exception
* If an unexpected exception occurred.
*/
- @Test(enabled=false)
+ @Test
public void testSearchTargetFilterAndAttributes() throws Exception
{
addEntries(BASIC_LDIF__GROUP_SEARCH_TESTS, DIR_MGR_DN, DIR_MGR_PW);
--
Gitblit v1.10.0