From 3f02855a9202d146ec2e87a7568180caec938235 Mon Sep 17 00:00:00 2001
From: dugan <dugan@localhost>
Date: Wed, 25 Jul 2007 23:12:49 +0000
Subject: [PATCH] Add new ACI keyword "extop" that can be used to enforce access based on the OID of an extended operation. For example, a new global access extended operation rule is also being added:
---
opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/EnumTargetKeyword.java | 7
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/TargetAttrTestCase.java | 5
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/GetEffectiveRightsTestCase.java | 3
opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/ExtOp.java | 104 +++++++
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AlternateRootDN.java | 10
opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/Aci.java | 64 +++
opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java | 33 +
opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java | 30 +
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTests.java | 29 +
opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciTargets.java | 116 ++++++--
opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/TargetControl.java | 2
opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciTargetMatchContext.java | 21 +
opendj-sdk/opends/resource/config/config.ldif | 1
opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java | 26 +
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/ExtOpTestCase.java | 240 +++++++++++++++++
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/IPTestCase.java | 1
opendj-sdk/opends/tests/unit-tests-testng/resource/config-changes.ldif | 6
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/TargetControlTestCase.java | 61 +++
opendj-sdk/opends/src/server/org/opends/server/messages/AciMessages.java | 17 +
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTestCase.java | 38 ++
20 files changed, 719 insertions(+), 95 deletions(-)
diff --git a/opendj-sdk/opends/resource/config/config.ldif b/opendj-sdk/opends/resource/config/config.ldif
index f864c53..d3d2df8 100644
--- a/opendj-sdk/opends/resource/config/config.ldif
+++ b/opendj-sdk/opends/resource/config/config.ldif
@@ -51,6 +51,7 @@
objectClass: top
objectClass: ds-cfg-access-control-handler
objectClass: ds-cfg-dseecompat-access-control-handler
+ds-cfg-global-aci: (extop="1.3.6.1.4.1.26027.1.6.1 || 1.3.6.1.4.1.4203.1.11.1 || 1.3.6.1.4.1.1466.20037 || 1.3.6.1.4.1.4203.1.11.3") (version 3.0; acl "Anonymous extended operation access"; allow(read) userdn="ldap:///anyone";)
ds-cfg-global-aci: (targetcontrol="2.16.840.1.113730.3.4.2 || 2.16.840.1.113730.3.4.17 || 2.16.840.1.113730.3.4.19 || 1.3.6.1.4.1.4203.1.10.2") (version 3.0; acl "Anonymous control access"; allow(read) userdn="ldap:///anyone";)
ds-cfg-global-aci: (targetattr!="userPassword||authPassword")(version 3.0; acl "Anonymous read access"; allow (read,search,compare) userdn="ldap:///anyone";)
ds-cfg-global-aci: (targetattr="*")(version 3.0; acl "Self entry modification"; allow (write) userdn="ldap:///self";)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/Aci.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/Aci.java
index d1ace9d..4af0b45 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/Aci.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/Aci.java
@@ -282,6 +282,16 @@
public static final int TARGATTRFILTERS_DELETE = 0x2000;
/**
+ * Used by the control evaluation access check.
+ */
+ public static final int ACI_CONTROL = 0x4000;
+
+ /**
+ * Used by the extended operation access check.
+ */
+ public static final int ACI_EXT_OP = 0x8000;
+
+ /**
* ACI_ATTR_STAR_MATCHED is the flag set when the evaluation reason of a
* AciHandler.maysend ACI_READ access evaluation was the result of an
* ACI targetattr all attributes expression (targetattr="*") target match.
@@ -400,15 +410,40 @@
/**
* Test if the given ACI is applicable using the target match information
- * provided. The ACI target can have four keywords at this time:
+ * provided. The ACI target can have seven keywords at this time:
+ *
+ * These two base decision on the resource entry DN:
*
* 1. target - checked in isTargetApplicable.
* 2. targetscope - checked in isTargetApplicable.
+ *
+ * These three base decision on resource entry attributes:
+ *
* 3. targetfilter - checked in isTargetFilterApplicable.
* 4. targetattr - checked in isTargetAttrApplicable.
+ * 5. targattrfilters - checked in isTargAttrFiltersApplicable.
*
- * One and two are checked for match first. If they return true, then
- * three is checked. Lastly four is checked.
+ * These two base decisions on a resource entry built by the ACI handler
+ * that only contains a DN:
+ * 6. targetcontrol - check in isTargetControlApplicable.
+ * 7. extop - check in isExtOpApplicable.
+ *
+ * Six and seven are specific to the check being done: targetcontrol when a
+ * control is being evaluated and extop when an extended operation is
+ * evaluated. None of the attribute based keywords should be checked
+ * when a control or extended op is being evaluated, because one
+ * of those attribute keywords rule might incorrectly make an ACI
+ * applicable that shouldn't be. This can happen by erroneously basing
+ * their decision on the ACI handler generated stub resource entry. For
+ * example, a "(targetattr != userpassword)" rule would match the generated
+ * stub resource entry, even though a control or extended op might be
+ * denied.
+ *
+ * What is allowed is the target and targetscope keywords, since the DN is
+ * known, so they are checked along with the correct method for the access
+ * check (isTargetControlApplicable for control and
+ * isTExtOpApplicable for extended operations). See comments in code
+ * where these checks are done.
*
* @param aci The ACI to test.
* @param matchCtx The target matching context containing all the info
@@ -417,20 +452,27 @@
*/
public static boolean
isApplicable(Aci aci, AciTargetMatchContext matchCtx) {
- int ctxRights=matchCtx.getRights();
- //First check if the ACI and context have similar rights.
+ if(matchCtx.hasRights(ACI_EXT_OP)) {
+ //Extended operation is being evaluated.
+ return AciTargets.isTargetApplicable(aci, matchCtx) &&
+ AciTargets.isExtOpApplicable(aci, matchCtx);
+ } else if(matchCtx.hasRights(ACI_CONTROL)) {
+ //Control is being evaluated.
+ return AciTargets.isTargetApplicable(aci, matchCtx) &&
+ AciTargets.isTargetControlApplicable(aci, matchCtx);
+ } else {
+ int ctxRights = matchCtx.getRights();
+ //First check if the ACI and context have similar rights.
if(!aci.hasRights(ctxRights)) {
- //TODO This check might be able to be removed further testing
- // is needed.
- if(!(aci.hasRights(ACI_SEARCH| ACI_READ) &&
- matchCtx.hasRights(ACI_SEARCH | ACI_READ)))
- return false;
+ if(!(aci.hasRights(ACI_SEARCH| ACI_READ) &&
+ matchCtx.hasRights(ACI_SEARCH | ACI_READ)))
+ return false;
}
return AciTargets.isTargetApplicable(aci, matchCtx) &&
- AciTargets.isTargetControlApplicable(aci, matchCtx) &&
AciTargets.isTargetFilterApplicable(aci, matchCtx) &&
AciTargets.isTargAttrFiltersApplicable(aci, matchCtx) &&
AciTargets.isTargetAttrApplicable(aci, matchCtx);
+ }
}
/**
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java
index 54fd4dc..217b3c6 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java
@@ -237,10 +237,15 @@
private int evalAllAttributes=0;
/*
- * String used to hold a control OID string.
- */
+ * String used to hold a control OID string.
+ */
private String controlOID;
+ /*
+ * String used to hold an extended operation OID string.
+ */
+ private String extOpOID;
+
/**
* This constructor is used by all currently supported LDAP operations.
*
@@ -743,6 +748,13 @@
return controlOID;
}
+ /**
+ * {@inheritDoc}
+ */
+ public String getExtOpOID() {
+ return extOpOID;
+ }
+
/**
* Set the the controlOID value to the specified oid string.
*
@@ -752,6 +764,16 @@
this.controlOID=oid;
}
+
+ /**
+ * Set the extended operation OID value to the specified oid string.
+ *
+ * @param oid The extended operation oid string.
+ */
+ protected void setExtOpOID(String oid) {
+ this.extOpOID=oid;
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
index e0969f0..77c3ba1 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
@@ -1195,7 +1195,8 @@
if(!(ret=skipAccessCheck(op))) {
Entry e = new Entry(entryDN, null, null, null);
AciLDAPOperationContainer operationContainer =
- new AciLDAPOperationContainer(op, e, control.getOID());
+ new AciLDAPOperationContainer(op, e, control,
+ (ACI_READ | ACI_CONTROL));
ret=accessAllowed(operationContainer);
}
if(control.getOID().equals(OID_PROXIED_AUTH_V2) ||
@@ -1218,6 +1219,27 @@
return ret;
}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isAllowed(ExtendedOperation operation) {
+ boolean ret;
+ if(!(ret=skipAccessCheck(operation))) {
+ Entry e = new Entry(operation.getAuthorizationDN(), null, null, null);
+ AciLDAPOperationContainer operationContainer =
+ new AciLDAPOperationContainer(operation, e, (ACI_READ | ACI_EXT_OP));
+ ret=accessAllowed(operationContainer);
+ }
+ if(operation.getRequestOID().equals(OID_PROXIED_AUTH_V2) ||
+ operation.getRequestOID().equals(OID_PROXIED_AUTH_V1))
+ operation.
+ setAttachment(ORIG_AUTH_ENTRY, operation.getAuthorizationEntry());
+ return ret;
+ }
+
+
//Not planned to be implemented methods.
/**
@@ -1243,15 +1265,6 @@
* {@inheritDoc}
*/
@Override
- public boolean isAllowed(ExtendedOperation extendedOperation) {
- //Not planned to be implemented.
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
public boolean isAllowed(LocalBackendSearchOperation searchOperation) {
//Not planned to be implemented.
return true;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java
index a417b61..b5a6398 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java
@@ -32,7 +32,6 @@
import org.opends.server.core.*;
import org.opends.server.types.*;
import org.opends.server.workflowelement.localbackend.*;
-import static org.opends.server.authorization.dseecompat.Aci.ACI_READ;
/**
* The AciLDAPOperationContainer is an AciContainer
@@ -64,15 +63,30 @@
}
/**
- * Constructor interface for control evaluation.
+ * Constructor interface for evaluation of a control.
*
- * @param operation The operation to evaluate.
- * @param e An entry built especially for control evaluation.
- * @param oid The control's oid string.
+ * @param operation The operation to use in the evaluation.
+ * @param e An entry built especially for evaluation.
+ * @param c The control to evaluate.
+ * @param rights The rights of a control.
*/
- public AciLDAPOperationContainer(Operation operation, Entry e, String oid) {
- super(operation, (ACI_READ), e );
- setControlOID(oid);
+ public AciLDAPOperationContainer(Operation operation, Entry e, Control c,
+ int rights) {
+ super(operation, rights, e );
+ setControlOID(c.getOID());
+ }
+
+ /**
+ * Constructor interface for evaluation of the extended operation.
+ *
+ * @param operation The extended operation to evaluate.
+ * @param e An entry built especially for evaluation.
+ * @param rights The rights of a extended operation.
+ */
+ public AciLDAPOperationContainer(ExtendedOperation operation, Entry e,
+ int rights) {
+ super(operation, rights, e );
+ setExtOpOID(operation.getRequestOID());
}
/**
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciTargetMatchContext.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciTargetMatchContext.java
index d0a5f1c..420be0f 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciTargetMatchContext.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciTargetMatchContext.java
@@ -118,12 +118,21 @@
*/
public int getRights();
- /**
- * Return the oid string of the control being evaluated.
- *
- * @return The oid string of the control being evaluated.
- */
- public String getControlOID();
+ /**
+ * Return the OID (Object Identifier) string of the control being evaluated.
+ *
+ * @return The OID string of the control being evaluated.
+ */
+ public String getControlOID();
+
+
+ /**
+ * Return The OID (Object Identifier) string of the extended operation being
+ * evaluated.
+ *
+ * @return The OID string of the extended operation being evaluated.
+ */
+ public String getExtOpOID();
/**
* Checks if the container's rights has the specified rights.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciTargets.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciTargets.java
index e55aca6..94eb6d4 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciTargets.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciTargets.java
@@ -41,8 +41,8 @@
* of an ACI before the ACI body and specifies the entry, attributes, or set
* of entries and attributes which the ACI controls access.
*
- * The five supported ACI target keywords are: target, targetattr,
- * targetscope, targetfilter and targattrfilters.
+ * The supported ACI target keywords are: target, targetattr,
+ * targetscope, targetfilter, targattrfilters, targetcontrol and extop.
*/
public class AciTargets {
@@ -76,6 +76,11 @@
*/
private TargetControl targetControl=null;
+ /**
+ * The ACI syntax has a extop keyword.
+ */
+ private ExtOp extOp=null;
+
/*
* The number of regular expression group positions in a valid ACI target
* expression.
@@ -138,25 +143,29 @@
/**
* Creates an ACI target from the specified arguments. All of these
- * may be null -- the ACI has no targets an will use defaults.
- * @param targetEntry The ACI target keyword if any.
- * @param targetAttr The ACI targetattr keyword if any.
- * @param targetFilter The ACI targetfilter keyword if any.
- * @param targetScope The ACI targetscope keyword if any.
- * @param targAttrFilters The ACI targAttrFilters keyword if any.
- * @param targetControl The ACI targetControl keyword if any.
+ * may be null. If the ACI has no targets defaults will be used.
+ *
+ * @param targetEntry The ACI target keyword class.
+ * @param targetAttr The ACI targetattr keyword class.
+ * @param targetFilter The ACI targetfilter keyword class.
+ * @param targetScope The ACI targetscope keyword class.
+ * @param targAttrFilters The ACI targAttrFilters keyword class.
+ * @param targetControl The ACI targetControl keyword class.
+ * @param extOp The ACI extop keyword class.
*/
private AciTargets(Target targetEntry, TargetAttr targetAttr,
TargetFilter targetFilter,
SearchScope targetScope,
TargAttrFilters targAttrFilters,
- TargetControl targetControl) {
+ TargetControl targetControl,
+ ExtOp extOp) {
this.target=targetEntry;
this.targetAttr=targetAttr;
this.targetScope=targetScope;
this.targetFilter=targetFilter;
this.targAttrFilters=targAttrFilters;
this.targetControl=targetControl;
+ this.extOp=extOp;
}
/**
@@ -212,6 +221,16 @@
return targetControl;
}
+
+ /**
+ * Return the class representing the ACI extop keyword. May be
+ * null.
+ * @return The extop information.
+ */
+ public ExtOp getExtOp() {
+ return extOp;
+ }
+
/**
* Decode an ACI's target part of the syntax from the string provided.
* @param input String representing an ACI target part of syntax.
@@ -226,6 +245,7 @@
TargetFilter targetFilter=null;
TargAttrFilters targAttrFilters=null;
TargetControl targetControl=null;
+ ExtOp extOp=null;
SearchScope targetScope=SearchScope.WHOLE_SUBTREE;
Pattern targetPattern = Pattern.compile(targetRegex);
Matcher targetMatcher = targetPattern.matcher(input);
@@ -273,19 +293,34 @@
}
case KEYWORD_TARGETCONTROL:
{
- if (targetControl == null){
- targetControl =
- TargetControl.decode(targetOperator, expression);
- }
- else
- {
- int msgID =
+ if (targetControl == null){
+ targetControl =
+ TargetControl.decode(targetOperator, expression);
+ }
+ else
+ {
+ int msgID =
MSGID_ACI_SYNTAX_INVALID_TARGET_DUPLICATE_KEYWORDS;
- String message =
+ String message =
getMessage(msgID, "targetcontrol", input);
- throw new AciException(msgID, message);
- }
- break;
+ throw new AciException(msgID, message);
+ }
+ break;
+ }
+ case KEYWORD_EXTOP:
+ {
+ if (extOp == null){
+ extOp = ExtOp.decode(targetOperator, expression);
+ }
+ else
+ {
+ int msgID =
+ MSGID_ACI_SYNTAX_INVALID_TARGET_DUPLICATE_KEYWORDS;
+ String message =
+ getMessage(msgID, "extop", input);
+ throw new AciException(msgID, message);
+ }
+ break;
}
case KEYWORD_TARGETATTR:
{
@@ -353,7 +388,8 @@
}
}
return new AciTargets(target, targetAttr, targetFilter,
- targetScope, targAttrFilters, targetControl);
+ targetScope, targAttrFilters, targetControl,
+ extOp);
}
/**
@@ -383,12 +419,12 @@
}
/**
- * Checks an ACI's targetfilter information against a target match
+ * Checks an ACI's targetfilter rule information against a target match
* context.
* @param aci The ACI to try an match the targetfilter of.
* @param matchCtx The target match context containing information needed
* to perform a target match.
- * @return True if the targetfilter matched the target context.
+ * @return True if the targetfilter rule matched the target context.
*/
public static boolean isTargetFilterApplicable(Aci aci,
AciTargetMatchContext matchCtx) {
@@ -400,16 +436,16 @@
}
/**
- * Check an ACI's targetcontrol against a target match context.
+ * Check an ACI's targetcontrol rule against a target match context.
*
* @param aci The ACI to match the targetcontrol against.
* @param matchCtx The target match context containing the information
* needed to perform the target match.
- * @return True if the targetcontrol matched the target context.
+ * @return True if the targetcontrol rule matched the target context.
*/
public static boolean isTargetControlApplicable(Aci aci,
AciTargetMatchContext matchCtx) {
- boolean ret=true;
+ boolean ret=false;
TargetControl targetControl=aci.getTargets().getTargetControl();
if(targetControl != null)
ret=targetControl.isApplicable(matchCtx);
@@ -417,11 +453,30 @@
}
/**
- * Check an ACI's targattrfilters against a target match context.
+ * Check an ACI's extop rule against a target match context.
+ *
+ * @param aci The ACI to match the extop rule against.
+ * @param matchCtx The target match context containing the information
+ * needed to perform the target match.
+ * @return True if the extop rule matched the target context.
+ */
+ public static boolean isExtOpApplicable(Aci aci,
+ AciTargetMatchContext matchCtx) {
+ boolean ret=false;
+ ExtOp extOp=aci.getTargets().getExtOp();
+ if(extOp != null)
+ ret=extOp.isApplicable(matchCtx);
+ return ret;
+ }
+
+
+ /**
+ * Check an ACI's targattrfilters rule against a target match context.
+ *
* @param aci The ACI to match the targattrfilters against.
* @param matchCtx The target match context containing the information
* needed to perform the target match.
- * @return True if the targattrfilters matched the target context.
+ * @return True if the targattrfilters rule matched the target context.
*/
public static boolean isTargAttrFiltersApplicable(Aci aci,
AciTargetMatchContext matchCtx) {
@@ -449,8 +504,9 @@
* of method calls over local variables.
*/
/**
- * Checks an provided ACI's targetattr information against a target match
+ * Checks an provided ACI's targetattr rule against a target match
* context.
+ *
* @param aci The ACI to evaluate.
* @param targetMatchCtx The target match context to check the ACI against.
* @return True if the targetattr matched the target context.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/EnumTargetKeyword.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/EnumTargetKeyword.java
index e22c5fd..1f69075 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/EnumTargetKeyword.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/EnumTargetKeyword.java
@@ -61,7 +61,12 @@
* This enumeration is returned when the target keyword is
* "targetcontrol".
*/
- KEYWORD_TARGETCONTROL ("targetcontrol");
+ KEYWORD_TARGETCONTROL ("targetcontrol"),
+ /**
+ * This enumeration is returned when the target keyword is
+ * "extop".
+ */
+ KEYWORD_EXTOP ("extop");
/*
* The target keyword name.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/ExtOp.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/ExtOp.java
new file mode 100644
index 0000000..a1c4498
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/ExtOp.java
@@ -0,0 +1,104 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.authorization.dseecompat;
+
+import static org.opends.server.messages.AciMessages.*;
+
+import java.util.HashSet;
+
+
+/**
+ * This class represents an ACI's extop keyword rule.
+ */
+
+public class ExtOp {
+
+
+ /*
+ * HashSet of OID strings parsed from the decode.
+ */
+ private HashSet<String> extOpOIDs = new HashSet<String>();
+
+ /*
+ * Enumeration representing the extop operator.
+ */
+
+ private EnumTargetOperator op = EnumTargetOperator.EQUALITY;
+
+ /**
+ * Creates a class that can be used to evaluate a extop rule.
+ *
+ * @param op The operator of the extop expression (=, !=).
+ * @param extOpOIDs Set of extended operation OIDS to use in the evaluation
+ * (wild-card '*' allowed).
+ */
+ private ExtOp(EnumTargetOperator op, HashSet<String> extOpOIDs) {
+ this.extOpOIDs=extOpOIDs;
+ this.op=op;
+ }
+
+
+ /**
+ * Decode an extop expression string.
+ *
+ * @param operator An enumeration representing the operator type.
+ * @param expr A string representing the extop expression.
+ * @return A class representing the extop expression that can be
+ * used to evaluate an ACI.
+ *
+ * @throws AciException If the specified expression string is invalid.
+ */
+ public static ExtOp decode(EnumTargetOperator operator, String expr)
+ throws AciException {
+ HashSet<String> extOpOIDs =
+ Aci.decodeOID(expr,MSGID_ACI_SYNTAX_INVALID_TARGEXTOP_EXPRESSION);
+ return new ExtOp(operator, extOpOIDs);
+ }
+
+ /**
+ * Check if a extop is applicable based on the provided target match
+ * context.
+ *
+ * @param matchCtx The target match context to use in the check.
+ * @return True if the extop is applicable based on the context.
+ */
+ public boolean isApplicable(AciTargetMatchContext matchCtx) {
+ if(matchCtx.getExtOpOID() == null)
+ return false;
+ boolean ret = false;
+ for(String oid : extOpOIDs)
+ if(oid.equals("*") || matchCtx.getExtOpOID().equals(oid)) {
+ ret=true;
+ break;
+ }
+ if(op.equals(EnumTargetOperator.NOT_EQUALITY))
+ ret = !ret;
+ return ret;
+ }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/TargetControl.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/TargetControl.java
index 9510888..dbda4cd 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/TargetControl.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/TargetControl.java
@@ -51,7 +51,7 @@
/**
* Creates a class that can be used to evaluate a targetcontrol.
*
- * @param op The operator of the targetfilter expression (=, !=).
+ * @param op The operator of the targetcontrol expression (=, !=).
* @param controlOIDS Set of control OIDS to use in the evaluation (may
* contain wild-card '*').
*/
diff --git a/opendj-sdk/opends/src/server/org/opends/server/messages/AciMessages.java b/opendj-sdk/opends/src/server/org/opends/server/messages/AciMessages.java
index da777e4..71d0cc9 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/messages/AciMessages.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/messages/AciMessages.java
@@ -954,6 +954,16 @@
MSGID_ACI_SYNTAX_DECODE_EFFECTIVERIGHTS_FAIL =
CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 94;
+ /**
+ * The message ID for the message that will be used if an "aci" attribute
+ * type value parse failed because an extop keyword expression
+ * did not parse. This takes one argument, which is the extop
+ * expression from the ACI.
+ */
+
+ public static final int MSGID_ACI_SYNTAX_INVALID_TARGEXTOP_EXPRESSION =
+ CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 95;
+
/**
* Associates a set of generic messages with the message IDs defined in
* this class.
@@ -1501,5 +1511,12 @@
" geteffectiverights control could not be" +
" decoded because of the following reason: \"%s\"");
+ registerMessage(MSGID_ACI_SYNTAX_INVALID_TARGEXTOP_EXPRESSION,
+ "The provided Access Control Instruction (ACI) " +
+ "extop expression value \"%s\" is invalid. A valid " +
+ "extop keyword expression value requires one or more " +
+ "valid extended operation request OID strings in the following" +
+ " format: oid [|| oid1] ... [|| oidn]");
+
}
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/resource/config-changes.ldif b/opendj-sdk/opends/tests/unit-tests-testng/resource/config-changes.ldif
index c5678d5..b70ad9f 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/resource/config-changes.ldif
+++ b/opendj-sdk/opends/tests/unit-tests-testng/resource/config-changes.ldif
@@ -32,6 +32,12 @@
replace: ds-cfg-trust-manager-provider-dn
ds-cfg-trust-manager-provider-dn: cn=JKS,cn=Trust Manager Providers,cn=config
+dn: cn=Access Control Handler,cn=config
+changeType: modify
+add: ds-cfg-global-aci
+ds-cfg-global-aci: (targetcontrol="*") (version 3.0; acl "Anonymous control access"; allow(read) userdn="ldap:///anyone";)
+ds-cfg-global-aci: (extop="*") (version 3.0; acl "Anonymous extended op access"; allow(read) userdn="ldap:///anyone";)
+
dn: cn=JMX Connection Handler,cn=Connection Handlers,cn=config
changeType: modify
replace: ds-cfg-listen-port
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTestCase.java
index c588e5c..1244306 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTestCase.java
@@ -85,7 +85,12 @@
protected final static String G_CONTROL =
"(targetcontrol = \"*\")" +
- "(version 3.0; acl \"Control\"; " +
+ "(version 3.0; acl \"Anonymous control access\"; " +
+ "allow (read) userdn=\"ldap:///anyone\";)";
+
+ protected final static String E_EXTEND_OP =
+ "(extop = \"*\")" +
+ "(version 3.0; acl \"Anonymous extend op access\"; " +
"allow (read) userdn=\"ldap:///anyone\";)";
private static final ByteArrayOutputStream oStream = new ByteArrayOutputStream();
@@ -483,10 +488,35 @@
"uid: user.3",
"givenName: User 3",
"sn: 3",
- "mail: user.3@test",
- "description: user.3 description",
"cn: User 3",
- "l: Austin",
+ "l: Austin",
+ "userPassword: password",
+ "ds-privilege-name: proxied-auth",
+ "",
+ "dn: uid=user.4,ou=People,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: user.4",
+ "givenName: User 4",
+ "sn: 4",
+ "cn: User 4",
+ "l: ft worth",
+ "userPassword: password",
+ "",
+ "dn: uid=user.5,ou=People,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: user.5",
+ "givenName: User 5",
+ "sn: 5",
+ "mail: user.5@test",
+ "description: user.5 description",
+ "cn: User 5",
+ "l: waco",
"userPassword: password",
"ds-privilege-name: proxied-auth");
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTests.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTests.java
index 6c2f536..4be19c9 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTests.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AciTests.java
@@ -1069,26 +1069,38 @@
"allow(write)", BIND_RULE_USERDN_SELF);
private static final String GLOBAL_SCHEMA_ACI =
- buildGlobalAciValue("name", "User-Visible Schema Operational Attributes",
+ buildGlobalAciValue("name",
+ "User-Visible Schema Operational Attributes",
"target", "ldap:///cn=schema", "targetscope", "base",
"targetattr",
- "attributeTypes||dITContentRules||dITStructureRules||ldapSyntaxes||matchingRules||matchingRuleUse||nameForms||objectClasses",
+ "attributeTypes||dITContentRules||dITStructureRules||" +
+ "ldapSyntaxes||matchingRules||matchingRuleUse||nameForms||" +
+ "objectClasses",
"allow(read, search, compare)", BIND_RULE_USERDN_ANYONE);
private static final String GLOBAL_DSE_ACI = buildGlobalAciValue(
"name","User-Visible Root DSE Operational Attributes",
"target", "ldap:///", "targetscope", "base",
"targetattr",
- "namingContexts||supportedAuthPasswordSchemes||supportedControl||supportedExtension||supportedFeatures||supportedSASLMechanisms||vendorName||vendorVersion",
+ "namingContexts||supportedAuthPasswordSchemes||supportedControl||" +
+ "supportedExtension||supportedFeatures||supportedSASLMechanisms||" +
+ "vendorName||vendorVersion",
"allow(read, search, compare)",BIND_RULE_USERDN_ANYONE);
private static final String GLOBAL_USER_OP_ATTRS_ACI = buildGlobalAciValue(
"name", "User-Visible Operational Attributes", "targetattr",
- "createTimestamp||creatorsName||modifiersName||modifyTimestamp||entryDN||entryUUID||subschemaSubentry",
+ "createTimestamp||creatorsName||modifiersName||modifyTimestamp||" +
+ "entryDN||entryUUID||subschemaSubentry",
"allow(read, search, compare)", BIND_RULE_USERDN_ANYONE);
private static final String GLOBAL_CONTROL_ACI = buildGlobalAciValue(
- "name", "Control", "targetcontrol", "*",
+ "name", "Anonymous control access", "targetcontrol",
+ "*",
+ "allow(read)", BIND_RULE_USERDN_ANYONE);
+
+ private static final String GLOBAL_EXT_OP_ACI = buildGlobalAciValue(
+ "name", "Anonymous extend op access", "extop",
+ "*",
"allow(read)", BIND_RULE_USERDN_ANYONE);
private static final String GLOBAL_DEFAULT_ACIS =
@@ -1096,7 +1108,7 @@
GLOBAL_ANONYMOUS_READ_ACI,
GLOBAL_SELF_WRITE_ACI, GLOBAL_SCHEMA_ACI,
GLOBAL_DSE_ACI, GLOBAL_USER_OP_ATTRS_ACI,
- GLOBAL_CONTROL_ACI);
+ GLOBAL_CONTROL_ACI, GLOBAL_EXT_OP_ACI);
//ACI used to test LDAP compare.
private static final
@@ -2065,7 +2077,7 @@
String aciField = aciFields[i];
String aciValue = aciFields[i+1];
- if (aciField.startsWith("targ")) {
+ if (aciField.startsWith("targ") || aciField.equals("extop")) {
if (!aciField.endsWith("=")) { // We allow = or more importantly != to be included with the target
aciField += "=";
}
@@ -2092,7 +2104,8 @@
String permission = aciFields[i];
String bindRule = aciFields[i+1];
- if (!permission.startsWith("targ") && !permission.equals("name")) {
+ if (!permission.startsWith("targ") && !permission.equals("extop") &&
+ !permission.equals("name")) {
aci.append(EOL + " " + permission + " " + bindRule + ";");
}
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AlternateRootDN.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AlternateRootDN.java
index b6e40c1..dbf633d 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AlternateRootDN.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/AlternateRootDN.java
@@ -33,6 +33,7 @@
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeMethod;
import org.testng.Assert;
import org.opends.server.TestCaseUtils;
import static org.opends.server.config.ConfigConstants.*;
@@ -78,11 +79,18 @@
@AfterClass
public void tearDown() throws Exception {
String aciLdif=makeAddLDIF(ATTR_AUTHZ_GLOBAL_ACI, ACCESS_HANDLER_DN,
- G_READ_ACI, G_SELF_MOD, G_SCHEMA, G_DSE, G_USER_OPS, G_CONTROL);
+ G_READ_ACI, G_SELF_MOD, G_SCHEMA, G_DSE, G_USER_OPS, G_CONTROL,
+ E_EXTEND_OP);
LDIFModify(aciLdif, DIR_MGR_DN, PWD);
}
+ @BeforeMethod
+ public void clearBackend() throws Exception {
+ deleteAttrFromEntry(user1, "aci");
+ deleteAttrFromEntry(ACCESS_HANDLER_DN, ATTR_AUTHZ_GLOBAL_ACI);
+ }
+
/**
* This test uses an ACI allowing access to the userPassword attribute, based
* on one of the alternate bind DNs of a root entry. The root entry does not
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/ExtOpTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/ExtOpTestCase.java
new file mode 100644
index 0000000..3843231
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/ExtOpTestCase.java
@@ -0,0 +1,240 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.authorization.dseecompat;
+
+import org.testng.annotations.*;
+import org.testng.annotations.Test;
+import org.opends.server.TestCaseUtils;
+import org.opends.server.protocols.ldap.LDAPResultCode;
+import static org.opends.server.util.ServerConstants.*;
+import static org.opends.server.config.ConfigConstants.*;
+
+/**
+ * Unit test to test the extop ACI keyword.
+ */
+
+public class ExtOpTestCase extends AciTestCase {
+
+ private static final String superUser="uid=superuser,ou=admins,o=test";
+ private static final String level5User="uid=user.5,ou=People,o=test";
+ private static final String level4User="uid=user.4,ou=People,o=test";
+ private static final String level3User="uid=user.3,ou=People,o=test";
+ private static final String level2User="uid=user.2,ou=People,o=test";
+ private static final String level1User="uid=user.1,ou=People,o=test";
+ private static final String newPWD="newPWD";
+ private static final String peopleBase="ou=People,o=test";
+ private static final String adminBase="ou=Admins,o=test";
+
+ //Allow either reportauthzID or passwordpolicy controls. Used in the
+ //bind tests.
+ private static final
+ String pwdControls =
+ "(targetcontrol=\"" + OID_AUTHZID_REQUEST + "||" +
+ OID_PASSWORD_POLICY_CONTROL + "\")" +
+ "(version 3.0; acl \"control\";" +
+ "allow(read) userdn=\"ldap:///" + "anyone" + "\";)";
+
+
+ //Allow only password modify extended op.
+ private static final
+ String extOp =
+ "(extop=\"" + OID_PASSWORD_MODIFY_REQUEST + "\")" +
+ "(version 3.0; acl \"extended op\";" +
+ "allow(read) userdn=\"ldap:///" + "anyone" + "\";)";
+
+
+ //Allow all extended ops based on extop = *.
+ private static final
+ String extOpWC =
+ "(extop=\"" + "*" + "\")" +
+ "(version 3.0; acl \"extended op WC\";" +
+ "allow(read) userdn=\"ldap:///" + "anyone" + "\";)";
+
+
+ //Dis-allow all extended ops based on extop != *"
+ private static final
+ String extOpNotWC =
+ "(extop!=\"" + "*" + "\")" +
+ "(version 3.0; acl \"extended op no wc\";" +
+ "allow(read) userdn=\"ldap:///" + "anyone" + "\";)";
+
+
+ //Allow all attributes to be modified - so the password can be changed.
+ private static final
+ String ALLOW_ALL = "(targetattr=\"*\")" +
+ "(version 3.0;acl \"all access\";" +
+ "allow (all) " +
+ "userdn=\"ldap:///self\";)";
+
+ //Allow pwd modify to people branch.
+ private static final
+ String extOpPeople = "(extop=\"" +
+ OID_PASSWORD_MODIFY_REQUEST + "\")" +
+ "(target=\"ldap:///" + peopleBase + "\")" +
+ "(version 3.0; acl \"extended op\";" +
+ "allow(read) userdn=\"ldap:///" + "anyone" + "\";)";
+
+ //Dis-allow pwd modify to admin branch.
+ private static final
+ String extOpAdmin =
+ "(extop!=\"" + OID_PASSWORD_MODIFY_REQUEST + "\")" +
+ "(target=\"ldap:///" + adminBase + "\")" +
+ "(version 3.0; acl \"extended op\";" +
+ "allow(read) userdn=\"ldap:///" + "anyone" + "\";)";
+
+ //Test for side effect -- targetattr rule gives access to denied extended
+ //op.
+ private static final
+ String complicated =
+ "(extop = \"1.2.3.4\")" +
+ "(targetattr != \"userpassword\")" +
+ "(version 3.0; acl \"extended op\";" +
+ "allow(all) userdn=\"ldap:///" + "anyone" + "\";)";
+
+ @BeforeClass
+ public void setupClass() throws Exception {
+ TestCaseUtils.startServer();
+ deleteAttrFromEntry(ACCESS_HANDLER_DN, ATTR_AUTHZ_GLOBAL_ACI);
+ addEntries();
+ }
+
+ @AfterClass
+ public void tearDown() throws Exception {
+ String aciLdif=makeAddLDIF(ATTR_AUTHZ_GLOBAL_ACI, ACCESS_HANDLER_DN,
+ G_READ_ACI, G_SELF_MOD, G_SCHEMA, G_DSE, G_USER_OPS, G_CONTROL,
+ E_EXTEND_OP);
+ LDIFModify(aciLdif, DIR_MGR_DN, PWD);
+ }
+
+ @BeforeMethod
+ public void clearBackend() throws Exception {
+ deleteAttrFromEntry(peopleBase, "aci");
+ deleteAttrFromEntry(adminBase, "aci");
+ deleteAttrFromEntry(ACCESS_HANDLER_DN, ATTR_AUTHZ_GLOBAL_ACI);
+ }
+
+ /**
+ * Test access to extended op using wildcard.
+ *
+ * @throws Exception If an unexpected result is returned.
+ */
+ @Test()
+ public void testExtendOpPwdWC() throws Exception {
+ String pwdLdifs =
+ makeAddLDIF("aci", peopleBase, pwdControls, extOpWC, ALLOW_ALL);
+ LDIFModify(pwdLdifs, DIR_MGR_DN, PWD);
+ String pwdLdifs1 =
+ makeAddLDIF("aci", adminBase, pwdControls, ALLOW_ALL);
+ LDIFModify(pwdLdifs1, DIR_MGR_DN, PWD);
+ //Pass the people branch has access to all extended op using wild-card.
+ pwdModify(level1User, PWD, newPWD, null, null, 0);
+ //Fail the admin branch has no access to the extended op.
+ pwdModify(superUser, PWD, newPWD, null, null,
+ LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS);
+ deleteAttrFromEntry(peopleBase, "aci");
+ deleteAttrFromEntry(adminBase, "aci");
+ }
+
+ /**
+ * Test denied access to extended operation based on a extop rule
+ * deny all using a wild-card.
+ *
+ * @throws Exception If an unexpected result is returned.
+ */
+ @Test()
+ public void testExtendOpPwdNotWC() throws Exception {
+ String pwdLdifs =
+ makeAddLDIF("aci", peopleBase, pwdControls, extOpNotWC, ALLOW_ALL);
+ LDIFModify(pwdLdifs, DIR_MGR_DN, PWD);
+ pwdModify(level5User, PWD, newPWD, null, null,
+ LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS);
+ deleteAttrFromEntry(peopleBase, "aci");
+ }
+
+
+ /**
+ * Test access to extended op using one ACI to allow access to the
+ * extended op and another ACI to allow the pwd change..
+ *
+ * @throws Exception If an unexpected result is returned.
+ */
+ @Test()
+ public void testExtendOpPwd() throws Exception {
+ String pwdLdifs =
+ makeAddLDIF("aci", peopleBase, pwdControls, extOp, ALLOW_ALL);
+ LDIFModify(pwdLdifs, DIR_MGR_DN, PWD);
+ pwdModify(level3User, PWD, newPWD, null, null, 0);
+ deleteAttrFromEntry(peopleBase, "aci");
+ }
+
+ /**
+ * Test access to disallowed extended op based on a targetattr rule allowing
+ * access.
+ *
+ * @throws Exception If an unexpected result is returned.
+ */
+
+ @Test()
+ public void testTargetattrSideEffect() throws Exception {
+ String pwdLdifs =
+ makeAddLDIF("aci", peopleBase, complicated);
+ LDIFModify(pwdLdifs, DIR_MGR_DN, PWD);
+ //Fail because pwd not an allowed extended operation.
+ pwdModify(level4User, PWD, newPWD, null, null,
+ LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS);
+ deleteAttrFromEntry(peopleBase, "aci");
+ }
+
+ /**
+ * Test access to pwd changes using global ACIs with target statements giving
+ * access to different parts of the DIT.
+ *
+ * @throws Exception If an unexpected result is returned.
+ */
+ public void testGlobalTargets() throws Exception {
+ String globalControlAcis=
+ makeAddLDIF(ATTR_AUTHZ_GLOBAL_ACI, ACCESS_HANDLER_DN,
+ extOpAdmin, extOpPeople);
+ LDIFModify(globalControlAcis, DIR_MGR_DN, PWD);
+ String pwdLdifs =
+ makeAddLDIF("aci", peopleBase, pwdControls, ALLOW_ALL);
+ LDIFModify(pwdLdifs, DIR_MGR_DN, PWD);
+ String pwdLdifs1 =
+ makeAddLDIF("aci", adminBase, pwdControls, ALLOW_ALL);
+ LDIFModify(pwdLdifs1, DIR_MGR_DN, PWD);
+ //Succeed because ACI gives access to people branch.
+ pwdModify(level2User, PWD, newPWD, null, null, 0);
+ //Fail because ACI doesn't give access to admin branch.
+ pwdModify(superUser, PWD, newPWD, null, null,
+ LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS);
+ deleteAttrFromEntry(peopleBase, "aci");
+ deleteAttrFromEntry(adminBase, "aci");
+ deleteAttrFromEntry(ACCESS_HANDLER_DN, ATTR_AUTHZ_GLOBAL_ACI);
+ }
+
+}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/GetEffectiveRightsTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/GetEffectiveRightsTestCase.java
index 73cd2dd..c7fa970 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/GetEffectiveRightsTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/GetEffectiveRightsTestCase.java
@@ -171,7 +171,8 @@
@AfterClass
public void tearDown() throws Exception {
String aciLdif=makeAddLDIF(ATTR_AUTHZ_GLOBAL_ACI, ACCESS_HANDLER_DN,
- G_READ_ACI, G_SELF_MOD, G_SCHEMA, G_DSE, G_USER_OPS, G_CONTROL);
+ G_READ_ACI, G_SELF_MOD, G_SCHEMA, G_DSE, G_USER_OPS, G_CONTROL,
+ E_EXTEND_OP);
LDIFModify(aciLdif, DIR_MGR_DN, PWD);
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/IPTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/IPTestCase.java
index e61aa96..235c65c 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/IPTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/IPTestCase.java
@@ -28,7 +28,6 @@
package org.opends.server.authorization.dseecompat;
-import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.testng.annotations.DataProvider;
import java.net.InetAddress;
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/TargetAttrTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/TargetAttrTestCase.java
index e8969e4..73c6a75 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/TargetAttrTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/TargetAttrTestCase.java
@@ -30,6 +30,7 @@
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeMethod;
import org.testng.Assert;
import org.opends.server.TestCaseUtils;
import static org.opends.server.config.ConfigConstants.*;
@@ -129,11 +130,11 @@
@AfterClass
public void tearDown() throws Exception {
String aciLdif=makeAddLDIF(ATTR_AUTHZ_GLOBAL_ACI, ACCESS_HANDLER_DN,
- G_READ_ACI, G_SELF_MOD, G_SCHEMA, G_DSE, G_USER_OPS, G_CONTROL);
+ G_READ_ACI, G_SELF_MOD, G_SCHEMA, G_DSE, G_USER_OPS, G_CONTROL,
+ E_EXTEND_OP);
LDIFModify(aciLdif, DIR_MGR_DN, PWD);
}
-
/**
* Test targetattr behavior using userattr bind rule.
*
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/TargetControlTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/TargetControlTestCase.java
index 81e47c4..2ff7888 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/TargetControlTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/TargetControlTestCase.java
@@ -30,8 +30,7 @@
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.AfterClass;
+import org.testng.annotations.*;
import org.opends.server.TestCaseUtils;
import org.opends.server.protocols.ldap.LDAPResultCode;
import static org.opends.server.util.ServerConstants.*;
@@ -44,6 +43,7 @@
private static final String superUser="uid=superuser,ou=admins,o=test";
private static final String level3User="uid=user.3,ou=People,o=test";
+ private static final String level4User="uid=user.4,ou=People,o=test";
private static final String newPWD="newPWD";
@@ -55,8 +55,8 @@
private static final String peopleBase="ou=People,o=test";
private static final String adminBase="ou=Admins,o=test";
- private static final String newPeopleDN="uid=user.4," + peopleBase;
- private static final String newAdminDN="uid=user.4," + adminBase;
+ private static final String newPeopleDN="uid=user.6," + peopleBase;
+ private static final String newAdminDN="uid=user.6," + adminBase;
@BeforeClass
@@ -69,10 +69,19 @@
@AfterClass
public void tearDown() throws Exception {
String aciLdif=makeAddLDIF(ATTR_AUTHZ_GLOBAL_ACI, ACCESS_HANDLER_DN,
- G_READ_ACI, G_SELF_MOD, G_SCHEMA, G_DSE, G_USER_OPS, G_CONTROL);
+ G_READ_ACI, G_SELF_MOD, G_SCHEMA, G_DSE, G_USER_OPS, G_CONTROL,
+ E_EXTEND_OP);
LDIFModify(aciLdif, DIR_MGR_DN, PWD);
}
+
+ @BeforeMethod
+ public void clearBackend() throws Exception {
+ deleteAttrFromEntry(peopleBase, "aci");
+ deleteAttrFromEntry(base, "aci");
+ deleteAttrFromEntry(ACCESS_HANDLER_DN, ATTR_AUTHZ_GLOBAL_ACI);
+ }
+
private static final String[] newEntry = new String[] {
"objectClass: top",
"objectClass: person",
@@ -166,6 +175,21 @@
"(version 3.0; acl \"control\";" +
"allow(read) userdn=\"ldap:///" + "anyone" + "\";)";
+ //Allow all to extended op.
+ private static final
+ String extOpAll =
+ "(extop=\"" + "*" + "\")" +
+ "(version 3.0; acl \"control\";" +
+ "allow(read) userdn=\"ldap:///" + "anyone" + "\";)";
+
+ //Only allow access to the password policy control. Used to test if the
+ //targetattr rule will give access erroneously.
+ private static final
+ String complicated =
+ "(targetcontrol=\"" + OID_PASSWORD_POLICY_CONTROL + "\")" +
+ "(targetattr != \"userpassword\")" +
+ "(version 3.0; acl \"control\";" +
+ "allow(all) userdn=\"ldap:///" + "anyone" + "\";)";
/**
* Test valid targetcontrol statements.
@@ -202,14 +226,34 @@
}
/**
+ * Test access to disallowed control based on a targetattr rule allowing
+ * access.
+ *
+ * @throws Exception If an unexpected result is returned.
+ */
+
+ @Test()
+ public void testTargetattrSideEffect() throws Exception {
+ String pwdLdifs =
+ makeAddLDIF("aci", peopleBase, complicated);
+ LDIFModify(pwdLdifs, DIR_MGR_DN, PWD);
+ String noOpCtrlStr=OID_LDAP_NOOP_OPENLDAP_ASSIGNED + ":true";
+ //This should fail beacause this ACI only allows acces to the
+ //password policy control.
+ pwdModify(level4User, PWD, newPWD, noOpCtrlStr, null,
+ LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS);
+ deleteAttrFromEntry(peopleBase, "aci");
+ }
+
+ /**
* Test access to extended op controls (no-op and userPasswordPolicy).
*
* @throws Exception If an unexpected result is returned.
*/
- @Test()
+ @Test()
public void testExtendOpControls() throws Exception {
String pwdLdifs =
- makeAddLDIF("aci", peopleBase, extOpControls, ALLOW_ALL);
+ makeAddLDIF("aci", peopleBase, extOpControls, extOpAll, ALLOW_ALL);
LDIFModify(pwdLdifs, DIR_MGR_DN, PWD);
String noOpCtrlStr=OID_LDAP_NOOP_OPENLDAP_ASSIGNED + ":true";
//This pwd change should return no-op since the no-op control is
@@ -228,7 +272,7 @@
*
* @throws Exception If an unexpected result is returned.
*/
- @Test()
+ @Test()
public void testBindControl() throws Exception {
String pwdLdifs =
makeAddLDIF("aci", peopleBase, pwdControls, ALLOW_ALL);
@@ -292,7 +336,6 @@
deleteAttrFromEntry(ACCESS_HANDLER_DN, ATTR_AUTHZ_GLOBAL_ACI);
}
-
/**
* Test wildcard access. First test "targetcontrol != *"
* expression. Should all be access denied. Remove that ACI and add
--
Gitblit v1.10.0