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,8 +400,7 @@ * the reference to be returned to the client, or {@code * false} if not. */ public abstract boolean maySend(DN dn, SearchOperation searchOperation, public abstract boolean maySend(DN dn, Operation operation, SearchResultReference searchReference); 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) { if (getEffectiveRightsControl != null && operation instanceof SearchOperation) { hasGetEffectiveRightsControl=true; if(getEffectiveRightsControl.getAuthzDN() == null) this.authzid=getClientDN(); else this.authzid=getEffectiveRightsControl.getAuthzDN(); 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; } /** @@ -420,28 +405,6 @@ } /** * 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} */ public void addTargAttrFiltersMatchAci(Aci aci) { 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) { 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. 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) 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) { for (String a : searchAttributes) { if(a.equalsIgnoreCase(aclRightsAttrStr)) { attrMask |= ACL_RIGHTS; } else if(a.equalsIgnoreCase(aclRightsInfoAttrStr)) { attrMask |= ACL_RIGHTS_INFO; else { } else { //Check for shorthands for user attributes "*" or operational "+". if(a.equals("*")) { if (a.equals("*")) { //Add objectclass. AttributeType ocType = DirectoryServer.getObjectClassAttributeType(); AttributeType ocType = DirectoryServer.getObjectClassAttributeType(); nonRightsAttrs.add(ocType); nonRightsAttrs.addAll(e.getUserAttributes().keySet()); } else if (a.equals("+")) } else if (a.equals("+")) { nonRightsAttrs.addAll(e.getOperationalAttributes().keySet()); else { AttributeType attrType; if((attrType = DirectoryServer.getAttributeType(a.toLowerCase())) == null) attrType = DirectoryServer.getDefaultAttributeType(a.toLowerCase()); } 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 (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, if (nonRightsAttrs.isEmpty()) { 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, addEntryLevelRights(container, handler, attrMask, e, skipCheck); } else { addAttributeLevelRights(container, handler, attrMask, e, nonRightsAttrs, skipCheck, false); addAttributeLevelRights(container, handler, attrMask, e, container.getSpecificAttributes(), skipCheck, true); e=addEntryLevelRights(container,handler,attrMask,e,skipCheck); addEntryLevelRights(container, handler, attrMask, e, skipCheck); } return e; } /** * 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 * @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 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; 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 * @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 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. 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; @@ -310,23 +311,6 @@ */ 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 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))) // 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; return false; } if (ret) { } operationContainer.clearEvalAttributes(ACI_NULL); operationContainer.setRights(ACI_READ); ret = accessAllowedEntry(operationContainer); if (ret) if (!accessAllowedEntry(operationContainer)) { return false; } if (!operationContainer.hasEvalUserAttributes()) { operation.setAttachment(ALL_USER_ATTRS_MATCHED, ALL_USER_ATTRS_MATCHED); operation.setAttachment(ALL_USER_ATTRS_MATCHED, ALL_USER_ATTRS_MATCHED); } if (!operationContainer.hasEvalOpAttributes()) { operation.setAttachment(ALL_OP_ATTRS_MATCHED, ALL_OP_ATTRS_MATCHED); operation.setAttachment(ALL_OP_ATTRS_MATCHED, ALL_OP_ATTRS_MATCHED); } } } } // 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; 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(); 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; } } 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; @@ -179,7 +180,6 @@ //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: @@ -194,8 +194,6 @@ default: matched=evalVAL(evalCtx); } //Switch back to the working resource entry. evalCtx.useFullResourceEntry(false); return matched; } 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; 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(); } 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); } } 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.*; 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. 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. 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. 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 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);