From 2d0aba220afc66dcb50fcd2639df306a25f639ea Mon Sep 17 00:00:00 2001
From: dugan <dugan@localhost>
Date: Wed, 02 May 2007 02:02:04 +0000
Subject: [PATCH] Add ACI support for Get Effective Rights control. Issue #87.
---
opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java | 125 +++++++++++++++++++++++++++++++++++------
1 files changed, 105 insertions(+), 20 deletions(-)
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 2d15fbb..86a5462 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
@@ -43,6 +43,7 @@
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.protocols.internal.InternalClientConnection;
import static org.opends.server.schema.SchemaConstants.*;
+import static org.opends.server.util.ServerConstants.OID_GET_EFFECTIVE_RIGHTS;
import java.util.*;
import java.util.concurrent.locks.Lock;
@@ -75,6 +76,14 @@
*/
public static String ORIG_AUTH_ENTRY="origAuthorizationEntry";
+ /**
+ * 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 String ALL_ATTRS_RESOURCE_ENTRY = "allAttrsResourceEntry";
+
/**
* This constructor instantiates the ACI handler class that performs the
* main processing for the dseecompat ACI package. It does the following
@@ -352,28 +361,71 @@
*/
private boolean testApplicableLists(AciEvalContext evalCtx) {
EnumEvalResult res=EnumEvalResult.FALSE;
- //First check deny lists
+ evalCtx.setEvalReason(EnumEvalReason.NO_REASON);
LinkedList<Aci>denys=evalCtx.getDenyList();
+ LinkedList<Aci>allows=evalCtx.getAllowList();
+ //If allows list is empty and not doing geteffectiverights return
+ //false.
+ if(allows.isEmpty() && !(evalCtx.isGetEffectiveRightsEval() &&
+ !evalCtx.hasRights(ACI_SELF) &&
+ evalCtx.isTargAttrFilterMatchAciEmpty())) {
+ evalCtx.setEvalReason(EnumEvalReason.NO_ALLOW_ACIS);
+ evalCtx.setDecidingAci(null);
+ return false;
+ }
evalCtx.setDenyEval(true);
for(Aci denyAci : denys) {
res=Aci.evaluate(evalCtx, denyAci);
//Failure could be returned if a system limit is hit or
//search fails
- if((res.equals(EnumEvalResult.FAIL) ||
- (res.equals(EnumEvalResult.TRUE)))) {
- return false;
+ if(res.equals(EnumEvalResult.FAIL)) {
+ evalCtx.setEvalReason(EnumEvalReason.EVALUATED_DENY_ACI);
+ evalCtx.setDecidingAci(denyAci);
+ return false;
+ } else if (res.equals(EnumEvalResult.TRUE)) {
+ if(evalCtx.isGetEffectiveRightsEval() &&
+ !evalCtx.hasRights(ACI_SELF) &&
+ !evalCtx.isTargAttrFilterMatchAciEmpty()) {
+ //Iterate to next only if deny ACI contains a targattrfilters
+ //keyword.
+ if(AciEffectiveRights.setTargAttrAci(evalCtx, denyAci, true))
+ continue;
+ evalCtx.setEvalReason(EnumEvalReason.EVALUATED_DENY_ACI);
+ evalCtx.setDecidingAci(denyAci);
+ return false;
+ } else {
+ evalCtx.setEvalReason(EnumEvalReason.EVALUATED_DENY_ACI);
+ evalCtx.setDecidingAci(denyAci);
+ return false;
+ }
}
}
//Now check the allows -- flip the deny flag to false first.
evalCtx.setDenyEval(false);
- LinkedList<Aci>allows=evalCtx.getAllowList();
for(Aci allowAci : allows) {
- res=Aci.evaluate(evalCtx, allowAci);
- if(res.equals(EnumEvalResult.TRUE)) {
- break;
- }
+ res=Aci.evaluate(evalCtx, allowAci);
+ if(res.equals(EnumEvalResult.TRUE)) {
+ if(evalCtx.isGetEffectiveRightsEval() &&
+ !evalCtx.hasRights(ACI_SELF) &&
+ !evalCtx.isTargAttrFilterMatchAciEmpty()) {
+ //Iterate to next only if deny ACI contains a targattrfilters
+ //keyword.
+ if(AciEffectiveRights.setTargAttrAci(evalCtx, allowAci, false))
+ continue;
+ evalCtx.setEvalReason(EnumEvalReason.EVALUATED_ALLOW_ACI);
+ evalCtx.setDecidingAci(allowAci);
+ return true;
+ } else {
+ evalCtx.setEvalReason(EnumEvalReason.EVALUATED_ALLOW_ACI);
+ evalCtx.setDecidingAci(allowAci);
+ return true;
+ }
+ }
}
- return res.getBoolVal();
+ //Nothing matched fall through.
+ evalCtx.setEvalReason(EnumEvalReason.NO_MATCHED_ALLOWS_ACIS);
+ evalCtx.setDecidingAci(null);
+ return false;
}
/**
@@ -397,6 +449,8 @@
allows.add(aci);
}
}
+ if(targetMatchCtx.getTargAttrFiltersMatch())
+ targetMatchCtx.setTargAttrFiltersMatch(false);
}
targetMatchCtx.setAllowList(allows);
targetMatchCtx.setDenyList(denys);
@@ -425,7 +479,7 @@
*
* @return True if access is allowed.
*/
- private boolean accessAllowed(AciContainer container)
+ boolean accessAllowed(AciContainer container)
{
DN dn = container.getResourceEntry().getDN();
//For ACI_WRITE_ADD and ACI_WRITE_DELETE set the ACI_WRITE
@@ -439,9 +493,9 @@
if((container.getCurrentAttributeValue() != null) &&
(container.hasRights(ACI_WRITE)) &&
(isAttributeDN(container.getCurrentAttributeType()))) {
+ String DNString=null;
try {
- String DNString =
- container.getCurrentAttributeValue().getStringValue();
+ DNString = container.getCurrentAttributeValue().getStringValue();
DN tmpDN = DN.decode(DNString);
//Have a valid DN, compare to clientDN to see if the ACI_SELF
//right should be set.
@@ -449,7 +503,11 @@
container.setRights(container.getRights() | ACI_SELF);
}
} catch (DirectoryException ex) {
- return false;
+ //Log a message and keep going.
+ int msgID = MSGID_ACI_NOT_VALID_DN;
+ String message = getMessage(msgID, DNString);
+ logError(ErrorLogCategory.ACCESS_CONTROL,
+ ErrorLogSeverity.INFORMATIONAL, message, msgID);
}
}
@@ -458,8 +516,9 @@
//only do a proxy check if the right is not set to ACI_PROXY and the
//proxied authorization control has been decoded.
if(!container.hasSeenEntry()) {
- if(!container.hasRights(ACI_PROXY) &&
- container.isProxiedAuthorization()) {
+ if(container.isProxiedAuthorization() &&
+ !container.hasRights(ACI_PROXY) &&
+ !container.hasRights(ACI_SKIP_PROXY_CHECK)) {
int currentRights=container.getRights();
//Save the current rights so they can be put back if on success.
container.setRights(ACI_PROXY);
@@ -488,9 +547,13 @@
*/
createApplicableList(candidates,container);
/*
- * Lastly, evaluate the applicable list.
+ * Evaluate the applicable list.
*/
- return(testApplicableLists(container));
+ boolean ret=testApplicableLists(container);
+ //Build summary string if doing geteffectiverights eval.
+ if(container.isGetEffectiveRightsEval())
+ AciEffectiveRights.createSummary(container, ret, "main");
+ return ret;
}
/**
@@ -578,7 +641,7 @@
*
* @return True if access is allowed.
*/
- private boolean accessAllowedEntry(AciLDAPOperationContainer container) {
+ boolean accessAllowedEntry(AciLDAPOperationContainer container) {
boolean ret=false;
//set flag that specifies this is the first attribute evaluated
//in the entry
@@ -816,6 +879,8 @@
ret=accessAllowedEntry(operationContainer);
}
}
+ if(ret && operation.getAttachment(OID_GET_EFFECTIVE_RIGHTS) != null)
+ operation.setAttachment(ALL_ATTRS_RESOURCE_ENTRY, entry );
return ret;
}
@@ -844,10 +909,17 @@
//method, set the seen flag to true to bypass any proxy check.
operationContainer.setSeenEntry(true);
SearchResultEntry returnEntry;
- if(!skipAccessCheck(operation)) {
+ boolean skipCheck=skipAccessCheck(operation);
+ if(!skipCheck) {
returnEntry=accessAllowedAttrs(operationContainer);
} else
returnEntry=entry;
+ if(operationContainer.hasGetEffectiveRightsControl()) {
+ returnEntry =
+ AciEffectiveRights.addRightsToEntry(this, operation.getAttributes(),
+ operationContainer, returnEntry,
+ skipCheck);
+ }
return returnEntry;
}
@@ -1009,6 +1081,19 @@
return true;
}
+ /**
+ * Called when a geteffectiverights request control was decoded. Currently
+ * used to save the control in the specified operation's attachment list.
+ * Eventually will be used to check access to the actual control.
+ * @param operation The operation to save the attachment to.
+ * @param c The request control to save.
+ * @return True if the control is allowed access.
+ */
+ public boolean isGetEffectiveRightsAllowed(Operation operation, Control c) {
+ operation.setAttachment(OID_GET_EFFECTIVE_RIGHTS, c);
+ return true;
+ }
+
//Not planned to be implemented methods.
/**
--
Gitblit v1.10.0