From b4201ac0dae295d63110d97f5f3c411d450e142d Mon Sep 17 00:00:00 2001
From: boli <boli@localhost>
Date: Wed, 02 May 2007 00:34:04 +0000
Subject: [PATCH] Added privileges support for unindexed searches. Fixed issue where id2subtree and id2children indexes were not used when they should be. Added test cases for the unindexed search privilege.
---
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java | 32 +++----
opendj-sdk/opends/src/server/org/opends/server/messages/JebMessages.java | 11 ++
opendj-sdk/opends/resource/config/config.ldif | 1
opendj-sdk/opends/src/server/org/opends/server/types/Privilege.java | 13 +++
opendj-sdk/opends/tests/unit-tests-testng/resource/config-changes.ldif | 40 ++++++++++
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java | 2
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java | 112 ++++++++++++++++++++++++++++
7 files changed, 191 insertions(+), 20 deletions(-)
diff --git a/opendj-sdk/opends/resource/config/config.ldif b/opendj-sdk/opends/resource/config/config.ldif
index 9f4ec56..6fa3c52 100644
--- a/opendj-sdk/opends/resource/config/config.ldif
+++ b/opendj-sdk/opends/resource/config/config.ldif
@@ -1235,6 +1235,7 @@
ds-cfg-default-root-privilege-name: update-schema
ds-cfg-default-root-privilege-name: privilege-change
ds-cfg-default-root-privilege-name: index-rebuild
+ds-cfg-default-root-privilege-name: unindexed-search
dn: cn=Directory Manager,cn=Root DNs,cn=config
objectClass: top
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
index 18eb18b..64bd468 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
@@ -31,6 +31,7 @@
import org.opends.server.api.AttributeSyntax;
import org.opends.server.api.Backend;
import org.opends.server.api.EntryCache;
+import org.opends.server.api.ClientConnection;
import org.opends.server.core.AddOperation;
import org.opends.server.core.DeleteOperation;
import org.opends.server.core.DirectoryServer;
@@ -43,22 +44,7 @@
import org.opends.server.controls.ServerSideSortRequestControl;
import org.opends.server.controls.ServerSideSortResponseControl;
import org.opends.server.controls.VLVRequestControl;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.AttributeType;
-import org.opends.server.types.AttributeValue;
-import org.opends.server.types.CancelledOperationException;
-import org.opends.server.types.Control;
-import org.opends.server.types.DebugLogLevel;
-import org.opends.server.types.DirectoryException;
-import org.opends.server.types.DN;
-import org.opends.server.types.Entry;
-import org.opends.server.types.LDAPException;
-import org.opends.server.types.LockType;
-import org.opends.server.types.Modification;
-import org.opends.server.types.Operation;
-import org.opends.server.types.RDN;
-import org.opends.server.types.ResultCode;
-import org.opends.server.types.SearchScope;
+import org.opends.server.types.*;
import org.opends.server.util.StaticUtils;
import org.opends.server.util.ServerConstants;
@@ -720,8 +706,7 @@
// Evaluate the search scope against the id2children and id2subtree indexes.
boolean candidatesAreInScope = false;
- if (entryIDList.isDefined() &&
- entryIDList.size() > IndexFilter.FILTER_CANDIDATE_THRESHOLD)
+ if (entryIDList.size() > IndexFilter.FILTER_CANDIDATE_THRESHOLD)
{
// Read the ID from dn2id.
EntryID baseID = dn2id.get(null, baseDN);
@@ -820,6 +805,17 @@
}
else
{
+ ClientConnection clientConnection =
+ searchOperation.getClientConnection();
+ if(! clientConnection.hasPrivilege(Privilege.UNINDEXED_SEARCH,
+ searchOperation))
+ {
+ int msgID = MSGID_JEB_SEARCH_UNINDEXED_INSUFFICIENT_PRIVILEGES;
+ String message = getMessage(msgID);
+ throw new DirectoryException(ResultCode.INSUFFICIENT_ACCESS_RIGHTS,
+ message, msgID);
+ }
+
if (sortRequest != null)
{
// FIXME -- Add support for sorting unindexed searches using indexes
diff --git a/opendj-sdk/opends/src/server/org/opends/server/messages/JebMessages.java b/opendj-sdk/opends/src/server/org/opends/server/messages/JebMessages.java
index 4c68e21..037ddaa 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/messages/JebMessages.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/messages/JebMessages.java
@@ -1143,6 +1143,14 @@
CATEGORY_MASK_JEB | SEVERITY_MASK_MILD_ERROR | 144;
/**
+ * The message ID of an error indicating that unindexed searches are not
+ * allowed without the unindexed search prilvilege. This does not take
+ * any arguments.
+ */
+ public static final int MSGID_JEB_SEARCH_UNINDEXED_INSUFFICIENT_PRIVILEGES =
+ CATEGORY_MASK_JEB | SEVERITY_MASK_MILD_ERROR | 145;
+
+ /**
* Associates a set of generic messages with the message IDs defined in this
* class.
*/
@@ -1467,5 +1475,8 @@
"Unable to prcess the virtual list view request because " +
"no entry was found in the result set with a sort value " +
"greater than or equal to the provided assertion value");
+ registerMessage(MSGID_JEB_SEARCH_UNINDEXED_INSUFFICIENT_PRIVILEGES,
+ "You do not have sufficient privileges to perform an " +
+ "unindexed search");
}
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/types/Privilege.java b/opendj-sdk/opends/src/server/org/opends/server/types/Privilege.java
index 4b9dc7d..06cbb2a 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/types/Privilege.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/types/Privilege.java
@@ -214,7 +214,15 @@
* The privilege that provides the ability to rebuild one or more
* indexes in a backend that supports indexing.
*/
- INDEX_REBUILD("index-rebuild");
+ INDEX_REBUILD("index-rebuild"),
+
+
+
+ /**
+ * The privilege that provides the ability to perform an unindexed
+ * search in the JE backend.
+ */
+ UNINDEXED_SEARCH("unindexed-search");
@@ -274,6 +282,7 @@
PRIV_MAP.put("update-schema", UPDATE_SCHEMA);
PRIV_MAP.put("privilege-change", PRIVILEGE_CHANGE);
PRIV_MAP.put("index-rebuild", INDEX_REBUILD);
+ PRIV_MAP.put("unindexed-search", UNINDEXED_SEARCH);
PRIV_NAMES.add("bypass-acl");
PRIV_NAMES.add("modify-acl");
@@ -297,6 +306,7 @@
PRIV_NAMES.add("update-schema");
PRIV_NAMES.add("privilege-change");
PRIV_NAMES.add("index-rebuild");
+ PRIV_NAMES.add("unindexed-search");
DEFAULT_ROOT_PRIV_SET.add(BYPASS_ACL);
DEFAULT_ROOT_PRIV_SET.add(MODIFY_ACL);
@@ -315,6 +325,7 @@
DEFAULT_ROOT_PRIV_SET.add(UPDATE_SCHEMA);
DEFAULT_ROOT_PRIV_SET.add(PRIVILEGE_CHANGE);
DEFAULT_ROOT_PRIV_SET.add(INDEX_REBUILD);
+ DEFAULT_ROOT_PRIV_SET.add(UNINDEXED_SEARCH);
}
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 dbd4763..df6788f 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
@@ -338,6 +338,46 @@
replace: ds-cfg-override-severity
ds-cfg-override-severity: EXCEPTION=INFO
+dn: ds-cfg-backend-id=unindexedRoot,cn=Backends,cn=config
+changetype: add
+objectClass: top
+objectClass: ds-cfg-backend
+objectClass: ds-cfg-je-backend
+ds-cfg-backend-enabled: true
+ds-cfg-backend-class: org.opends.server.backends.jeb.BackendImpl
+ds-cfg-backend-id: unindexedRoot
+ds-cfg-backend-writability-mode: enabled
+ds-cfg-backend-base-dn: dc=unindexed,dc=jeb
+ds-cfg-backend-directory: db_unindexed
+ds-cfg-backend-mode: 700
+ds-cfg-backend-index-entry-limit: 1
+ds-cfg-backend-subtree-delete-size-limit: 100000
+ds-cfg-backend-preload-time-limit: 0 seconds
+ds-cfg-backend-import-temp-directory: importTmp
+ds-cfg-backend-import-buffer-size: 256 megabytes
+ds-cfg-backend-import-queue-size: 100
+ds-cfg-backend-import-pass-size: 0
+ds-cfg-backend-import-thread-count: 8
+ds-cfg-backend-entries-compressed: false
+ds-cfg-backend-deadlock-retry-limit: 10
+
+dn: cn=Index,ds-cfg-backend-id=unindexedRoot,cn=Backends,cn=config
+changetype: add
+objectClass: top
+objectClass: ds-cfg-branch
+cn: Index
+
+dn: ds-cfg-index-attribute=mail,cn=Index,ds-cfg-backend-id=unindexedRoot,cn=Backends,cn=config
+changetype: add
+objectClass: top
+objectClass: ds-cfg-je-index
+ds-cfg-index-attribute: mail
+ds-cfg-index-type: presence
+ds-cfg-index-type: equality
+ds-cfg-index-type: substring
+ds-cfg-index-type: ordering
+ds-cfg-index-type: approximate
+
dn: ds-cfg-backend-id=rebuildRoot,cn=Backends,cn=config
changetype: add
objectClass: top
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java
index eecfbf9..6c13eb8 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java
@@ -190,7 +190,7 @@
//db_rebuild is the third jeb backend used by the jeb rebuild test cases
String[] subDirectories = { "bak", "bin", "changelogDb", "classes",
"config", "db", "db_verify", "ldif", "lib",
- "locks", "logs", "db_rebuild",
+ "locks", "logs", "db_rebuild", "db_unindexed",
"db_index_test" };
for (String s : subDirectories)
{
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java
index 9e1b04b..1f6f3f5 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java
@@ -40,6 +40,7 @@
import org.testng.annotations.Test;
import org.opends.server.TestCaseUtils;
+import static org.opends.server.util.StaticUtils.createEntry;
import org.opends.server.backends.task.Task;
import org.opends.server.backends.task.TaskBackend;
import org.opends.server.backends.task.TaskState;
@@ -134,6 +135,8 @@
"ds-privilege-name: -ldif-export",
"ds-privilege-name: -backend-backup",
"ds-privilege-name: -backend-restore",
+ "ds-privilege-name: -index-rebuild",
+ "ds-privilege-name: -unindexed-search",
"",
"dn: cn=Proxy Root,cn=Root DNs,cn=config",
"objectClass: top",
@@ -168,6 +171,8 @@
"ds-privilege-name: backend-restore",
"ds-privilege-name: proxied-auth",
"ds-privilege-name: bypass-acl",
+ "ds-privilege-name: index-rebuild",
+ "ds-privilege-name: unindexed-search",
"ds-pwp-password-policy-dn: cn=Clear UserPassword Policy," +
"cn=Password Policies,cn=config",
"",
@@ -250,6 +255,30 @@
connections[i] = connList.get(i);
successful[i] = successList.get(i);
}
+
+ TestCaseUtils.addEntries(
+ "dn: dc=unindexed,dc=jeb",
+ "objectClass: top",
+ "objectClass: domain",
+ "",
+ "dn: cn=test1 user,dc=unindexed,dc=jeb",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "cn: test1 user",
+ "givenName: user",
+ "sn: test1",
+ "",
+ "dn: cn=test2 user,dc=unindexed,dc=jeb",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "cn: test2 user",
+ "givenName: user",
+ "sn: test2"
+ );
}
@@ -333,6 +362,43 @@
}
}
+ /**
+ * Tests to ensure that unindexed search operations properly respect the
+ * UNINDEXED_SEARCH privilege.
+ *
+ * @param conn The client connection to use to perform the search operation.
+ *
+ * @param hasPrivilege Indicates whether the authenticated user is expected
+ * to have the UNINDEXED_SEARCH privilege and therefore
+ * the search should succeed.
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testdata")
+ public void testUnindexedSearch(InternalClientConnection conn,
+ boolean hasPrivilege)
+ throws Exception
+ {
+ assertEquals(conn.hasPrivilege(Privilege.UNINDEXED_SEARCH, null), hasPrivilege);
+
+ for(DN dn : DirectoryServer.getBaseDNs().keySet())
+ {
+ System.out.println(dn.toString());
+ }
+
+ InternalSearchOperation searchOperation =
+ conn.processSearch(DN.decode("dc=unindexed,dc=jeb"), SearchScope.WHOLE_SUBTREE,
+ SearchFilter.createFilterFromString("(sn=test*)"));
+ if (hasPrivilege)
+ {
+ assertEquals(searchOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+ else
+ {
+ assertEquals(searchOperation.getResultCode(),
+ ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
+ }
+ }
+
/**
@@ -1016,6 +1082,52 @@
}
}
+ /**
+ * Test to ensure that attempts to rebuild indexes will property respect
+ * the INDEX_REBUILD privilege.
+ *
+ * @param conn The client connection to use to perform the rebuild.
+ * @param hasPrivilege Indicates weather the authenticated user is
+ * expected to have the INDEX_REBUILD privilege
+ * and therefore the rebuild should succeed.
+ * @throws Exception if an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testdata", groups = { "slow" })
+ public void testRebuildIndex(InternalClientConnection conn,
+ boolean hasPrivilege)
+ throws Exception
+ {
+ assertEquals(conn.hasPrivilege(Privilege.INDEX_REBUILD, null), hasPrivilege);
+
+ Entry taskEntry = TestCaseUtils.makeEntry(
+ "dn: ds-task-id=" + UUID.randomUUID() + ",cn=Scheduled Tasks,cn=Tasks",
+ "objectclass: top",
+ "objectclass: ds-task",
+ "objectclass: ds-task-rebuild",
+ "ds-task-class-name: org.opends.server.tasks.RebuildTask",
+ "ds-task-rebuild-base-dn: dc=example,dc=com",
+ "ds-task-rebuild-index: cn");
+
+ AddOperation addOperation =
+ conn.processAdd(taskEntry.getDN(), taskEntry.getObjectClasses(),
+ taskEntry.getUserAttributes(),
+ taskEntry.getOperationalAttributes());
+
+ if (hasPrivilege)
+ {
+ assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
+
+ Task task = getCompletedTask(taskEntry.getDN());
+ assertNotNull(task);
+ assertTrue(TaskState.isSuccessful(task.getTaskState()));
+ }
+ else
+ {
+ assertEquals(addOperation.getResultCode(),
+ ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
+ }
+ }
+
/**
--
Gitblit v1.10.0