From fe4d6b1f8ee49c858ca2644851377ba2402d9509 Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Thu, 25 Jul 2013 13:21:03 +0000
Subject: [PATCH] OPENDJ-948 (CR-1873) unauthorized disclosure of directory contents 

---
 opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendDeleteOperation.java |  133 ++++++++++++++++++++++++++-----------------
 1 files changed, 80 insertions(+), 53 deletions(-)

diff --git a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendDeleteOperation.java b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendDeleteOperation.java
index d28ac4b..9f09437 100644
--- a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendDeleteOperation.java
+++ b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendDeleteOperation.java
@@ -144,31 +144,38 @@
     // Check for a request to cancel this operation.
     checkIfCanceled(false);
 
-    BooleanHolder executePostOpPlugins = new BooleanHolder(false);
-    processDelete(executePostOpPlugins);
-
-    // Invoke the post-operation or post-synchronization delete plugins.
-    PluginConfigManager pluginConfigManager =
-        DirectoryServer.getPluginConfigManager();
-    if (isSynchronizationOperation())
+    try
     {
-      if (getResultCode() == ResultCode.SUCCESS)
+      BooleanHolder executePostOpPlugins = new BooleanHolder(false);
+      processDelete(executePostOpPlugins);
+
+      // Invoke the post-operation or post-synchronization delete plugins.
+      PluginConfigManager pluginConfigManager =
+          DirectoryServer.getPluginConfigManager();
+      if (isSynchronizationOperation())
       {
-        pluginConfigManager.invokePostSynchronizationDeletePlugins(this);
+        if (getResultCode() == ResultCode.SUCCESS)
+        {
+          pluginConfigManager.invokePostSynchronizationDeletePlugins(this);
+        }
+      }
+      else if (executePostOpPlugins.value)
+      {
+        PluginResult.PostOperation postOpResult =
+            pluginConfigManager.invokePostOperationDeletePlugins(this);
+        if (!postOpResult.continueProcessing())
+        {
+          setResultCode(postOpResult.getResultCode());
+          appendErrorMessage(postOpResult.getErrorMessage());
+          setMatchedDN(postOpResult.getMatchedDN());
+          setReferralURLs(postOpResult.getReferralURLs());
+          return;
+        }
       }
     }
-    else if (executePostOpPlugins.value)
+    finally
     {
-      PluginResult.PostOperation postOpResult =
-          pluginConfigManager.invokePostOperationDeletePlugins(this);
-      if (!postOpResult.continueProcessing())
-      {
-        setResultCode(postOpResult.getResultCode());
-        appendErrorMessage(postOpResult.getErrorMessage());
-        setMatchedDN(postOpResult.getMatchedDN());
-        setReferralURLs(postOpResult.getReferralURLs());
-        return;
-      }
+      LocalBackendWorkflowElement.filterNonDisclosableMatchedDN(this);
     }
 
     // Register a post-response call-back which will notify persistent
@@ -227,16 +234,16 @@
 
     // Grab a write lock on the entry.
     final Lock entryLock = LockManager.lockWrite(entryDN);
-    if (entryLock == null)
-    {
-      setResultCode(ResultCode.BUSY);
-      appendErrorMessage(ERR_DELETE_CANNOT_LOCK_ENTRY.get(String
-          .valueOf(entryDN)));
-      return;
-    }
 
     try
     {
+      if (entryLock == null)
+      {
+        setResultCodeAndMessageNoInfoDisclosure(entry, ResultCode.BUSY,
+            ERR_DELETE_CANNOT_LOCK_ENTRY.get(String.valueOf(entryDN)));
+        return;
+      }
+
       // Get the entry to delete. If it doesn't exist, then fail.
       entry = backend.getEntry(entryDN);
       if (entry == null)
@@ -272,9 +279,10 @@
         if (!AccessControlConfigManager.getInstance().getAccessControlHandler()
             .isAllowed(this))
         {
-          setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-          appendErrorMessage(ERR_DELETE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS
-              .get(String.valueOf(entryDN)));
+          setResultCodeAndMessageNoInfoDisclosure(entry,
+              ResultCode.INSUFFICIENT_ACCESS_RIGHTS,
+              ERR_DELETE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS.get(String
+                  .valueOf(entryDN)));
           return;
         }
       }
@@ -322,17 +330,17 @@
         switch (DirectoryServer.getWritabilityMode())
         {
         case DISABLED:
-          setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-          appendErrorMessage(ERR_DELETE_SERVER_READONLY.get(String
-              .valueOf(entryDN)));
+          setResultCodeAndMessageNoInfoDisclosure(entry,
+              ResultCode.UNWILLING_TO_PERFORM,
+              ERR_DELETE_SERVER_READONLY.get(String.valueOf(entryDN)));
           return;
 
         case INTERNAL_ONLY:
           if (!(isInternalOperation() || isSynchronizationOperation()))
           {
-            setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-            appendErrorMessage(ERR_DELETE_SERVER_READONLY.get(String
-                .valueOf(entryDN)));
+            setResultCodeAndMessageNoInfoDisclosure(entry,
+                ResultCode.UNWILLING_TO_PERFORM,
+                ERR_DELETE_SERVER_READONLY.get(String.valueOf(entryDN)));
             return;
           }
         }
@@ -340,17 +348,17 @@
         switch (backend.getWritabilityMode())
         {
         case DISABLED:
-          setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-          appendErrorMessage(ERR_DELETE_BACKEND_READONLY.get(String
-              .valueOf(entryDN)));
+          setResultCodeAndMessageNoInfoDisclosure(entry,
+              ResultCode.UNWILLING_TO_PERFORM,
+              ERR_DELETE_BACKEND_READONLY.get(String.valueOf(entryDN)));
           return;
 
         case INTERNAL_ONLY:
           if (!(isInternalOperation() || isSynchronizationOperation()))
           {
-            setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-            appendErrorMessage(ERR_DELETE_BACKEND_READONLY.get(String
-                .valueOf(entryDN)));
+            setResultCodeAndMessageNoInfoDisclosure(entry,
+                ResultCode.UNWILLING_TO_PERFORM,
+                ERR_DELETE_BACKEND_READONLY.get(String.valueOf(entryDN)));
             return;
           }
         }
@@ -368,9 +376,10 @@
         {
           if (dn.isDescendantOf(entryDN))
           {
-            setResultCode(ResultCode.NOT_ALLOWED_ON_NONLEAF);
-            appendErrorMessage(ERR_DELETE_HAS_SUB_BACKEND.get(String
-                .valueOf(entryDN), String.valueOf(dn)));
+            setResultCodeAndMessageNoInfoDisclosure(entry,
+                ResultCode.NOT_ALLOWED_ON_NONLEAF,
+                ERR_DELETE_HAS_SUB_BACKEND.get(String.valueOf(entryDN),
+                    String.valueOf(dn)));
             return;
           }
         }
@@ -407,15 +416,33 @@
       }
 
       setResponseData(de);
-      return;
     }
     finally
     {
-      LockManager.unlock(entryDN, entryLock);
+      if (entryLock != null)
+      {
+        LockManager.unlock(entryDN, entryLock);
+      }
       processSynchPostOperationPlugins();
     }
   }
 
+  private DirectoryException newDirectoryException(Entry entry,
+      ResultCode resultCode, Message message) throws DirectoryException
+  {
+    return LocalBackendWorkflowElement.newDirectoryException(this, entry, null,
+        resultCode, message, ResultCode.NO_SUCH_OBJECT,
+        ERR_DELETE_NO_SUCH_ENTRY.get(String.valueOf(entryDN)));
+  }
+
+  private void setResultCodeAndMessageNoInfoDisclosure(Entry entry,
+      ResultCode resultCode, Message message) throws DirectoryException
+  {
+    LocalBackendWorkflowElement.setResultCodeAndMessageNoInfoDisclosure(this,
+        entry, null, resultCode, message, ResultCode.NO_SUCH_OBJECT,
+        ERR_DELETE_NO_SUCH_ENTRY.get(String.valueOf(entryDN)));
+  }
+
   private DN findMatchedDN(DN entryDN)
   {
     try
@@ -480,7 +507,7 @@
               TRACER.debugCaught(DebugLogLevel.ERROR, de);
             }
 
-            throw new DirectoryException(de.getResultCode(),
+            throw newDirectoryException(entry, de.getResultCode(),
                            ERR_DELETE_CANNOT_PROCESS_ASSERTION_FILTER.get(
                                 String.valueOf(entryDN),
                                 de.getMessageObject()));
@@ -500,7 +527,7 @@
           {
             if (!filter.matchesEntry(entry))
             {
-              throw new DirectoryException(ResultCode.ASSERTION_FAILED,
+              throw newDirectoryException(entry, ResultCode.ASSERTION_FAILED,
                   ERR_DELETE_ASSERTION_FAILED.get(String
                       .valueOf(entryDN)));
             }
@@ -517,7 +544,7 @@
               TRACER.debugCaught(DebugLogLevel.ERROR, de);
             }
 
-            throw new DirectoryException(de.getResultCode(),
+            throw newDirectoryException(entry, de.getResultCode(),
                            ERR_DELETE_CANNOT_PROCESS_ASSERTION_FILTER.get(
                                 String.valueOf(entryDN),
                                 de.getMessageObject()));
@@ -591,7 +618,7 @@
         {
           if ((backend == null) || (! backend.supportsControl(oid)))
           {
-            throw new DirectoryException(
+            throw newDirectoryException(entry,
                            ResultCode.UNAVAILABLE_CRITICAL_EXTENSION,
                            ERR_DELETE_UNSUPPORTED_CRITICAL_CONTROL.get(
                                 String.valueOf(entryDN), oid));
@@ -617,8 +644,8 @@
               SynchronizationProviderResult result =
                   provider.handleConflictResolution(this);
               if (! result.continueProcessing()) {
-                  setResultCode(result.getResultCode());
-                  appendErrorMessage(result.getErrorMessage());
+                  setResultCodeAndMessageNoInfoDisclosure(entry,
+                      result.getResultCode(), result.getErrorMessage());
                   setMatchedDN(result.getMatchedDN());
                   setReferralURLs(result.getReferralURLs());
                   returnVal = false;

--
Gitblit v1.10.0