From 4b01c44954d8be6ea19e1f43832c51ce56575a3d Mon Sep 17 00:00:00 2001
From: Gaetan Boismal <gaetan.boismal@forgerock.com>
Date: Mon, 23 Jun 2014 12:49:04 +0000
Subject: [PATCH] OPENDJ-1351 (CR-3814) Require a privilege needed for searching cn=changelog * config.ldiff ** Add the 'changelog-read' value to the 'ds-default-root-privilege-name' multi-valued attribute * GlobalConfiguration.xml RootDNConfiguration.xml ADSContext.java Privilege.java RootPrivilegeChangeListener.java ** Add the 'changelog-read' privilege where is was needed * GlobalCfgDefn.properties RootDNCfgDefn.properties ** Add 'changelog-read' privilege definition * replication.properties replication_fr.properties ** Add messages to prevent user that he needs to have the 'changelog-read' privilege if he wants to search on changelog * ECLSearchOperation.java ** Add a check to verify that the current connection has the 'changelog-read' privilege before starting the changelog search * ExternalChangeLogTest.java ** Unit test which ensure that is not possible to perform a changelog search without the 'changelog-read' privilege 

---
 opendj-sdk/opendj3-server-dev/src/admin/messages/GlobalCfgDefn.properties                                                        |    1 
 opendj-sdk/opendj3-server-dev/src/admin/messages/RootDNCfgDefn.properties                                                        |    1 
 opendj-sdk/opendj3-server-dev/src/ads/org/opends/admin/ads/ADSContext.java                                                       |    1 
 opendj-sdk/opendj3-server-dev/resource/config/config.ldif                                                                        |    1 
 opendj-sdk/opendj3-server-dev/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml                                 |    8 ++
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/types/Privilege.java                                                  |   13 +++
 opendj-sdk/opendj3-server-dev/src/admin/defn/org/opends/server/admin/std/RootDNConfiguration.xml                                 |    8 ++
 opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ExternalChangeLogTest.java |   25 ++++++++
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/core/RootPrivilegeChangeListener.java                                 |   76 -------------------------
 opendj-sdk/opendj3-server-dev/src/messages/messages/replication_fr.properties                                                    |    1 
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java             |    7 ++
 opendj-sdk/opendj3-server-dev/src/messages/messages/replication.properties                                                       |    2 
 12 files changed, 64 insertions(+), 80 deletions(-)

diff --git a/opendj-sdk/opendj3-server-dev/resource/config/config.ldif b/opendj-sdk/opendj3-server-dev/resource/config/config.ldif
index e743d63..08ee1e0 100644
--- a/opendj-sdk/opendj3-server-dev/resource/config/config.ldif
+++ b/opendj-sdk/opendj3-server-dev/resource/config/config.ldif
@@ -1956,6 +1956,7 @@
 ds-cfg-default-root-privilege-name: privilege-change
 ds-cfg-default-root-privilege-name: unindexed-search
 ds-cfg-default-root-privilege-name: subentry-write
+ds-cfg-default-root-privilege-name: changelog-read
 
 dn: cn=Directory Manager,cn=Root DNs,cn=config
 objectClass: top
diff --git a/opendj-sdk/opendj3-server-dev/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml b/opendj-sdk/opendj3-server-dev/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml
index 5638e80..e009e71 100644
--- a/opendj-sdk/opendj3-server-dev/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml
+++ b/opendj-sdk/opendj3-server-dev/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml
@@ -23,7 +23,7 @@
   !
   !
   !      Copyright 2007-2010 Sun Microsystems, Inc.
-  !      Portions Copyright 2011-2012 ForgeRock AS
+  !      Portions Copyright 2011-2014 ForgeRock AS
   ! -->
 <adm:managed-object name="global" plural-name="globals"
   package="org.opends.server.admin.std"
@@ -681,6 +681,12 @@
             operations.
           </adm:synopsis>
         </adm:value>
+        <adm:value name="changelog-read">
+          <adm:synopsis>
+            The privilege that provides the ability to perform read
+            operations on the changelog
+          </adm:synopsis>
+        </adm:value>
       </adm:enumeration>
     </adm:syntax>
     <adm:profile name="ldap">
diff --git a/opendj-sdk/opendj3-server-dev/src/admin/defn/org/opends/server/admin/std/RootDNConfiguration.xml b/opendj-sdk/opendj3-server-dev/src/admin/defn/org/opends/server/admin/std/RootDNConfiguration.xml
index 8657a5b..4e880f1 100644
--- a/opendj-sdk/opendj3-server-dev/src/admin/defn/org/opends/server/admin/std/RootDNConfiguration.xml
+++ b/opendj-sdk/opendj3-server-dev/src/admin/defn/org/opends/server/admin/std/RootDNConfiguration.xml
@@ -23,7 +23,7 @@
   !
   !
   !      Copyright 2007-2010 Sun Microsystems, Inc.
-  !      Portions Copyright 2011 ForgeRock AS
+  !      Portions Copyright 2014 ForgeRock AS
   ! -->
 <adm:managed-object name="root-dn" plural-name="root-dns"
   package="org.opends.server.admin.std"
@@ -77,6 +77,7 @@
         <adm:value>privilege-change</adm:value>
         <adm:value>unindexed-search</adm:value>
         <adm:value>subentry-write</adm:value>
+        <adm:value>changelog-read</adm:value>
       </adm:defined>
     </adm:default-behavior>
     <adm:syntax>
@@ -217,6 +218,11 @@
             operations.
           </adm:synopsis>
         </adm:value>
+        <adm:value name="changelog-read">
+          <adm:synopsis>
+            Allows the user to perform read operations on the changelog
+          </adm:synopsis>
+        </adm:value>
       </adm:enumeration>
     </adm:syntax>
     <adm:profile name="ldap">
diff --git a/opendj-sdk/opendj3-server-dev/src/admin/messages/GlobalCfgDefn.properties b/opendj-sdk/opendj3-server-dev/src/admin/messages/GlobalCfgDefn.properties
index 4d326f8..948cb4d 100644
--- a/opendj-sdk/opendj3-server-dev/src/admin/messages/GlobalCfgDefn.properties
+++ b/opendj-sdk/opendj3-server-dev/src/admin/messages/GlobalCfgDefn.properties
@@ -20,6 +20,7 @@
 property.disabled-privilege.syntax.enumeration.value.bypass-acl.synopsis=Allows the associated user to bypass access control checks performed by the server.
 property.disabled-privilege.syntax.enumeration.value.bypass-lockdown.synopsis=Allows the associated user to bypass server lockdown mode.
 property.disabled-privilege.syntax.enumeration.value.cancel-request.synopsis=Allows the user to cancel operations in progress on other client connections.
+property.disabled-privilege.syntax.enumeration.value.changelog-read.synopsis=The privilege that provides the ability to perform read operations on the changelog
 property.disabled-privilege.syntax.enumeration.value.config-read.synopsis=Allows the associated user to read the server configuration.
 property.disabled-privilege.syntax.enumeration.value.config-write.synopsis=Allows the associated user to update the server configuration. The config-read privilege is also required.
 property.disabled-privilege.syntax.enumeration.value.data-sync.synopsis=Allows the user to participate in data synchronization.
diff --git a/opendj-sdk/opendj3-server-dev/src/admin/messages/RootDNCfgDefn.properties b/opendj-sdk/opendj3-server-dev/src/admin/messages/RootDNCfgDefn.properties
index e105636..2509b77 100644
--- a/opendj-sdk/opendj3-server-dev/src/admin/messages/RootDNCfgDefn.properties
+++ b/opendj-sdk/opendj3-server-dev/src/admin/messages/RootDNCfgDefn.properties
@@ -7,6 +7,7 @@
 property.default-root-privilege-name.syntax.enumeration.value.bypass-acl.synopsis=Allows the associated user to bypass access control checks performed by the server.
 property.default-root-privilege-name.syntax.enumeration.value.bypass-lockdown.synopsis=Allows the associated user to bypass server lockdown mode.
 property.default-root-privilege-name.syntax.enumeration.value.cancel-request.synopsis=Allows the user to cancel operations in progress on other client connections.
+property.default-root-privilege-name.syntax.enumeration.value.changelog-read.synopsis=Allows the user to perform read operations on the changelog
 property.default-root-privilege-name.syntax.enumeration.value.config-read.synopsis=Allows the associated user to read the server configuration.
 property.default-root-privilege-name.syntax.enumeration.value.config-write.synopsis=Allows the associated user to update the server configuration. The config-read privilege is also required.
 property.default-root-privilege-name.syntax.enumeration.value.data-sync.synopsis=Allows the user to participate in data synchronization.
diff --git a/opendj-sdk/opendj3-server-dev/src/ads/org/opends/admin/ads/ADSContext.java b/opendj-sdk/opendj3-server-dev/src/ads/org/opends/admin/ads/ADSContext.java
index 716a285..1592a1f 100644
--- a/opendj-sdk/opendj3-server-dev/src/ads/org/opends/admin/ads/ADSContext.java
+++ b/opendj-sdk/opendj3-server-dev/src/ads/org/opends/admin/ads/ADSContext.java
@@ -1718,6 +1718,7 @@
     privilege.add("privilege-change");
     privilege.add("unindexed-search");
     privilege.add("subentry-write");
+    privilege.add("changelog-read");
     return privilege;
   }
 
diff --git a/opendj-sdk/opendj3-server-dev/src/messages/messages/replication.properties b/opendj-sdk/opendj3-server-dev/src/messages/messages/replication.properties
index 377d2c5..ff8836a 100644
--- a/opendj-sdk/opendj3-server-dev/src/messages/messages/replication.properties
+++ b/opendj-sdk/opendj3-server-dev/src/messages/messages/replication.properties
@@ -531,3 +531,5 @@
  change %s to replicaDB %s %s because: %s
 ERR_COULD_NOT_ADD_CHANGE_TO_SHUTTING_DOWN_REPLICA_DB_240=Could not add \
  change %s to replicaDB %s %s because flushing thread is shutting down
+NOTE_SEARCH_CHANGELOG_INSUFFICIENT_PRIVILEGES_285=You do not have sufficient privileges to \
+ perform a search request on cn=changelog
\ No newline at end of file
diff --git a/opendj-sdk/opendj3-server-dev/src/messages/messages/replication_fr.properties b/opendj-sdk/opendj3-server-dev/src/messages/messages/replication_fr.properties
index bf032e0..fe36cdf 100644
--- a/opendj-sdk/opendj3-server-dev/src/messages/messages/replication_fr.properties
+++ b/opendj-sdk/opendj3-server-dev/src/messages/messages/replication_fr.properties
@@ -188,3 +188,4 @@
 ERR_RSQUEUE_DIFFERENT_MSGS_WITH_SAME_CN_201=Traitement de deux modifications diff\u00e9rentes ayant le m\u00eame param\u00e8tre changeNumber=%s. Pr\u00e9c\u00e9dent msg=<%s>, Nouveau msg=<%s>
 ERR_COULD_NOT_SOLVE_CONFLICT_202=Une erreur est survenue lors de la tentative de r\u00e9solution d'un conflit avec le DN\u00a0: %s ERREUR : %s
 NOTE_ECL_LOOKTHROUGH_LIMIT_EXCEEDED_238=Cette op\u00e9ration de recherche a v\u00e9rifi\u00e9 le maximum d'entr\u00e9es %d \u00e0 des fins de correspondance
+NOTE_SEARCH_CHANGELOG_INSUFFICIENT_PRIVILEGES_285=Vous ne disposez pas du privil\u00e8ge de lecture sur cn=changelog
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/core/RootPrivilegeChangeListener.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/core/RootPrivilegeChangeListener.java
index b32a5e6..dec2b08 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/core/RootPrivilegeChangeListener.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/core/RootPrivilegeChangeListener.java
@@ -117,81 +117,7 @@
     HashSet<Privilege> privSet = new HashSet<Privilege>(configPrivSet.size());
     for (RootDNCfgDefn.DefaultRootPrivilegeName p : configPrivSet)
     {
-      switch (p)
-      {
-        case BYPASS_LOCKDOWN:
-          privSet.add(Privilege.BYPASS_LOCKDOWN);
-          break;
-        case BYPASS_ACL:
-          privSet.add(Privilege.BYPASS_ACL);
-          break;
-        case MODIFY_ACL:
-          privSet.add(Privilege.MODIFY_ACL);
-          break;
-        case CONFIG_READ:
-          privSet.add(Privilege.CONFIG_READ);
-          break;
-        case CONFIG_WRITE:
-          privSet.add(Privilege.CONFIG_WRITE);
-          break;
-        case JMX_READ:
-          privSet.add(Privilege.JMX_READ);
-          break;
-        case JMX_WRITE:
-          privSet.add(Privilege.JMX_WRITE);
-          break;
-        case JMX_NOTIFY:
-          privSet.add(Privilege.JMX_NOTIFY);
-          break;
-        case LDIF_IMPORT:
-          privSet.add(Privilege.LDIF_IMPORT);
-          break;
-        case LDIF_EXPORT:
-          privSet.add(Privilege.LDIF_EXPORT);
-          break;
-        case BACKEND_BACKUP:
-          privSet.add(Privilege.BACKEND_BACKUP);
-          break;
-        case BACKEND_RESTORE:
-          privSet.add(Privilege.BACKEND_RESTORE);
-          break;
-        case SERVER_LOCKDOWN:
-          privSet.add(Privilege.SERVER_LOCKDOWN);
-          break;
-        case SERVER_SHUTDOWN:
-          privSet.add(Privilege.SERVER_SHUTDOWN);
-          break;
-        case SERVER_RESTART:
-          privSet.add(Privilege.SERVER_RESTART);
-          break;
-        case PROXIED_AUTH:
-          privSet.add(Privilege.PROXIED_AUTH);
-          break;
-        case DISCONNECT_CLIENT:
-          privSet.add(Privilege.DISCONNECT_CLIENT);
-          break;
-        case CANCEL_REQUEST:
-          privSet.add(Privilege.CANCEL_REQUEST);
-          break;
-        case PASSWORD_RESET:
-          privSet.add(Privilege.PASSWORD_RESET);
-          break;
-        case DATA_SYNC:
-          privSet.add(Privilege.DATA_SYNC);
-          break;
-        case UPDATE_SCHEMA:
-          privSet.add(Privilege.UPDATE_SCHEMA);
-          break;
-        case PRIVILEGE_CHANGE:
-          privSet.add(Privilege.PRIVILEGE_CHANGE);
-          break;
-        case UNINDEXED_SEARCH:
-          privSet.add(Privilege.UNINDEXED_SEARCH);
-          break;
-        case SUBENTRY_WRITE:
-          privSet.add(Privilege.SUBENTRY_WRITE);
-          break;
-      }
+        privSet.add(Privilege.privilegeForName(p.toString()));
     }
 
     defaultRootPrivileges = privSet;
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/types/Privilege.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/types/Privilege.java
index 9438aae..477bd71 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/types/Privilege.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/types/Privilege.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2008-2010 Sun Microsystems, Inc.
- *      Portions Copyright 2013 ForgeRock AS
+ *      Portions Copyright 2014 ForgeRock AS
  */
 package org.opends.server.types;
 
@@ -229,7 +229,15 @@
    * The privilege that provides the ability to perform write
    * operations on LDAP subentries.
    */
-  SUBENTRY_WRITE("subentry-write");
+  SUBENTRY_WRITE("subentry-write"),
+
+
+
+  /**
+   * The privilege that provides the ability to perform read
+   * operations on the changelog.
+   */
+  CHANGELOG_READ("changelog-read");
 
 
 
@@ -282,6 +290,7 @@
     DEFAULT_ROOT_PRIV_SET.add(PRIVILEGE_CHANGE);
     DEFAULT_ROOT_PRIV_SET.add(UNINDEXED_SEARCH);
     DEFAULT_ROOT_PRIV_SET.add(SUBENTRY_WRITE);
+    DEFAULT_ROOT_PRIV_SET.add(CHANGELOG_READ);
   }
 
 
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java
index 0a1b9a0..ad76a71 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java
@@ -208,6 +208,13 @@
       replicationServer  = wfe.getReplicationServer();
       clientConnection   = getClientConnection();
 
+      if (!clientConnection.hasPrivilege(Privilege.CHANGELOG_READ, this))
+      {
+        setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
+        appendErrorMessage(NOTE_SEARCH_CHANGELOG_INSUFFICIENT_PRIVILEGES.get());
+        return;
+      }
+
       final StartECLSessionMsg startECLSessionMsg = new StartECLSessionMsg();
 
       // Set default behavior as "from change number".
diff --git a/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ExternalChangeLogTest.java b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ExternalChangeLogTest.java
index a3613c7..3cf9e53 100644
--- a/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ExternalChangeLogTest.java
+++ b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ExternalChangeLogTest.java
@@ -49,6 +49,7 @@
 import org.opends.server.controls.PersistentSearchControl;
 import org.opends.server.core.*;
 import org.opends.server.plugins.InvocationCounterPlugin;
+import org.opends.server.protocols.internal.InternalClientConnection;
 import org.opends.server.protocols.internal.InternalSearchOperation;
 import org.opends.server.protocols.ldap.*;
 import org.opends.server.replication.ReplicationTestCase;
@@ -397,7 +398,29 @@
     // TODO: test with optimization when code done.
     ECLFilterOnReplicationCSN(csn);
   }
-
+  
+  //Verifies that is not possible to read the changelog without the changelog-read privilege
+  @Test(enabled=true, dependsOnMethods = { "ECLReplicationServerTest"})
+  public void ECLChangelogReadPrivilegeTest() throws Exception
+  {  
+     InternalClientConnection conn =
+           new InternalClientConnection(new AuthenticationInfo());
+     InternalSearchOperation ico = conn.processSearch(
+          "cn=changelog",
+          SearchScope.WHOLE_SUBTREE,
+          DereferenceAliasesPolicy.NEVER,
+          0, // Size limit
+          0, // Time limit
+          false, // Types only
+          "(objectclass=*)",
+          ALL_ATTRIBUTES,
+          NO_CONTROL,
+          null);
+     
+     assertEquals(ico.getResultCode(), ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
+     assertEquals(ico.getErrorMessage().toMessage(), NOTE_SEARCH_CHANGELOG_INSUFFICIENT_PRIVILEGES.get());
+  }
+  
   private void ECLIsNotASupportedSuffix() throws Exception
   {
     ECLCompatTestLimits(0,0, false);

--
Gitblit v1.10.0