From c09124d6ae9060ea52a6d8bc284140f8ab95fbe9 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Thu, 03 May 2007 03:56:41 +0000
Subject: [PATCH] Implement support for config file change detection, which can detect external edits to the server configuration (e.g., manually updating the file in a text editor) with the server online.  If the server detects that the configuration file has been externally modified when it needs to rewrite it to apply a change coming in through protocol, then it will attempt to copy the manually-edited file off to the side and will generate an administrative alert and write a log message to let administrators know what happened.

---
 opends/src/server/org/opends/server/extensions/ConfigFileHandler.java |   73 ++++++++++++++++++++++++++++++++++++
 1 files changed, 73 insertions(+), 0 deletions(-)

diff --git a/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java b/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
index b6f1a2c..156a272 100644
--- a/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
+++ b/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
@@ -1928,6 +1928,75 @@
     // FIXME -- This needs support for encryption.
 
 
+    // Calculate an archive for the current server configuration file and see if
+    // it matches what we expect.  If not, then the file has been manually
+    // edited with the server online which is a bad thing.  In that case, we'll
+    // copy the current config off to the side before writing the new config
+    // so that the manual changes don't get lost but also don't get applied.
+    // Also, send an admin alert notifying administrators about the problem.
+    try
+    {
+      byte[] currentDigest = calculateConfigDigest();
+      if (! Arrays.equals(configurationDigest, currentDigest))
+      {
+        File existingCfg   = new File(configFile);
+        File newConfigFile = new File(existingCfg.getParent(),
+                                      "config.manualedit-" +
+                                           TimeThread.getGMTTime() + ".ldif");
+        int counter = 2;
+        while (newConfigFile.exists())
+        {
+          newConfigFile = new File(newConfigFile.getAbsolutePath() + "." +
+                                   counter++);
+        }
+
+        FileInputStream  inputStream  = new FileInputStream(existingCfg);
+        FileOutputStream outputStream = new FileOutputStream(newConfigFile);
+        byte[] buffer = new byte[8192];
+        while (true)
+        {
+          int bytesRead = inputStream.read(buffer);
+          if (bytesRead < 0)
+          {
+            break;
+          }
+
+          outputStream.write(buffer, 0, bytesRead);
+        }
+
+        inputStream.close();
+        outputStream.close();
+
+        int    msgID   = MSGID_CONFIG_MANUAL_CHANGES_DETECTED;
+        String message = getMessage(msgID, configFile,
+                                    newConfigFile.getAbsolutePath());
+
+        logError(ErrorLogCategory.CONFIGURATION,
+                 ErrorLogSeverity.SEVERE_WARNING, message, msgID);
+
+        DirectoryServer.sendAlertNotification(this,
+             ALERT_TYPE_MANUAL_CONFIG_EDIT_HANDLED, msgID, message);
+      }
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      int    msgID   = MSGID_CONFIG_MANUAL_CHANGES_LOST;
+      String message = getMessage(msgID, configFile,
+                                  stackTraceToSingleLineString(e));
+
+      logError(ErrorLogCategory.CONFIGURATION,
+               ErrorLogSeverity.SEVERE_ERROR, message, msgID);
+
+      DirectoryServer.sendAlertNotification(this,
+           ALERT_TYPE_MANUAL_CONFIG_EDIT_HANDLED, msgID, message);
+    }
+
+
     // Write the new configuration to a temporary file.
     String tempConfig = configFile + ".tmp";
     try
@@ -3391,6 +3460,10 @@
 
     alerts.put(ALERT_TYPE_CANNOT_WRITE_CONFIGURATION,
                ALERT_DESCRIPTION_CANNOT_WRITE_CONFIGURATION);
+    alerts.put(ALERT_TYPE_MANUAL_CONFIG_EDIT_HANDLED,
+               ALERT_DESCRIPTION_MANUAL_CONFIG_EDIT_HANDLED);
+    alerts.put(ALERT_TYPE_MANUAL_CONFIG_EDIT_LOST,
+               ALERT_DESCRIPTION_MANUAL_CONFIG_EDIT_LOST);
 
     return alerts;
   }

--
Gitblit v1.10.0