mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

boli
15.54.2006 da7c2116996d26d22b3eca9f20cb497791dbb857
This uses the new FilePermission framework to set permissions on the
directory holding the database files. The new config attribute
ds-cfg-backend-mode is optional and by default has a value of 700. The
permissions are set on backend initialization as well as on the fly via
LDAP. The server will make sure the file permissions will allow owner
access before setting. Any exceptions encountered while setting the
attribute will result in non fatal errors which are logged. However, any
configuration exceptions will keep the backend from starting.

Fix for issue 50
7 files modified
177 ■■■■■ changed files
opends/resource/config/config.ldif 1 ●●●● patch | view | raw | blame | history
opends/resource/schema/02-config.ldif 6 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/backends/jeb/BackendImpl.java 50 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/backends/jeb/Config.java 62 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/config/ConfigConstants.java 9 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/messages/ConfigMessages.java 40 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/messages/JebMessages.java 9 ●●●●● patch | view | raw | blame | history
opends/resource/config/config.ldif
@@ -103,6 +103,7 @@
ds-cfg-backend-writability-mode: enabled
ds-cfg-backend-base-dn: dc=example,dc=com
ds-cfg-backend-directory: db
ds-cfg-backend-mode: 700
ds-cfg-backend-index-entry-limit: 4000
ds-cfg-backend-subtree-delete-size-limit: 100000
ds-cfg-backend-preload-time-limit: 0 seconds
opends/resource/schema/02-config.ldif
@@ -981,6 +981,9 @@
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.286 NAME 'ds-rlim-lookthrough-limit'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE USAGE directoryOperation
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.287 NAME 'ds-cfg-backend-mode'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
  NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL
  MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled )
@@ -1007,7 +1010,8 @@
  ds-cfg-backend-import-temp-directory $ ds-cfg-backend-import-buffer-size $
  ds-cfg-backend-import-queue-size $ ds-cfg-backend-import-thread-count $
  ds-cfg-backend-entries-compressed $ ds-cfg-backend-deadlock-retry-limit $
  ds-cfg-backend-import-pass-size ) X-ORIGIN 'OpenDS Directory Server' )
  ds-cfg-backend-import-pass-size $ ds-cfg-backend-mode )
  X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.7 NAME 'ds-cfg-je-database'
  SUP top STRUCTURAL MAY ( cn $ ds-cfg-database-cache-percent $
  ds-cfg-database-cache-size $ ds-cfg-database-txn-no-sync $
opends/src/server/org/opends/server/backends/jeb/BackendImpl.java
@@ -79,6 +79,7 @@
import org.opends.server.types.LDIFExportConfig;
import org.opends.server.types.RestoreConfig;
import org.opends.server.types.ResultCode;
import org.opends.server.types.FilePermission;
import org.opends.server.monitors.DatabaseEnvironmentMonitor;
import org.opends.server.util.LDIFException;
import org.opends.server.loggers.Debug;
@@ -121,6 +122,12 @@
  private File backendDirectory;
  /**
   * The permissions mode for the directory containing persistent storage for
   * the backend.
   */
  private FilePermission backendPermission;
  /**
   * The base DNs contained in this backend.
   */
  private ConcurrentHashMap<DN, EntryContainer> baseDNs;
@@ -374,6 +381,24 @@
                                        message);
    }
    // Get the backend database directory permissions and apply
    try
    {
      backendPermission = config.getBackendPermission();
      if(!FilePermission.setPermissions(backendDirectory, backendPermission))
      {
        throw new Exception();
      }
    }
    catch(Exception e)
    {
      // Log an warning that the permissions were not set.
      int msgID = MSGID_JEB_SET_PERMISSIONS_FAILED;
      String message = getMessage(msgID, backendDirectory.getPath());
      logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_WARNING,
               message, msgID);
    }
    // FIXME: Currently assuming every base DN is also a suffix.
    for (DN dn : baseDNs)
    {
@@ -1577,6 +1602,31 @@
        }
      }
      // Check for changes to the database directory permissions
      FilePermission oldPermission = config.getBackendPermission();
      FilePermission newPermission = newConfig.getBackendPermission();
      if(!FilePermission.toUNIXMode(oldPermission).equals(
          FilePermission.toUNIXMode(newPermission)))
      {
        try
        {
          if(!FilePermission.setPermissions(newConfig.getBackendDirectory(),
              newPermission))
          {
            throw new Exception();
          }
        }
        catch(Exception e)
        {
          // Log an warning that the permissions were not set.
          int msgID = MSGID_JEB_SET_PERMISSIONS_FAILED;
          String message = getMessage(msgID, backendDirectory.getPath());
          logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_WARNING,
                   message, msgID);
        }
      }
      // Check if any JE non-mutable properties were changed.
      EnvironmentConfig oldEnvConfig = config.getEnvironmentConfig();
      EnvironmentConfig newEnvConfig = newConfig.getEnvironmentConfig();
opends/src/server/org/opends/server/backends/jeb/Config.java
@@ -29,7 +29,14 @@
import static org.opends.server.messages.MessageHandler.getMessage;
import static org.opends.server.messages.ConfigMessages.
     MSGID_CONFIG_DESCRIPTION_BACKEND_DIRECTORY;
import static org.opends.server.messages.ConfigMessages.
     MSGID_CONFIG_DESCRIPTION_BACKEND_MODE;
import static org.opends.server.messages.ConfigMessages.
    MSGID_CONFIG_BACKEND_MODE_INVALID;
import static org.opends.server.messages.ConfigMessages.
    MSGID_CONFIG_BACKEND_INSANE_MODE;
import static org.opends.server.config.ConfigConstants.ATTR_BACKEND_DIRECTORY;
import static org.opends.server.config.ConfigConstants.ATTR_BACKEND_MODE;
import static org.opends.server.messages.ConfigMessages.
     MSGID_CONFIG_BACKEND_NO_DIRECTORY;
import static org.opends.server.messages.JebMessages.*;
@@ -52,6 +59,7 @@
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
import org.opends.server.types.RDN;
import org.opends.server.types.FilePermission;
import com.sleepycat.je.EnvironmentConfig;
import java.util.HashMap;
@@ -240,6 +248,12 @@
  private File backendDirectory = null;
  /**
   * The backend directory permission mode. By default, owner has read, write
   * and execute permissions on the database directory.
   */
  private FilePermission backendPermission = new FilePermission(0700);
  /**
   * Number of times we should retry database transactions that get aborted
   * due to deadlock.
   */
@@ -343,6 +357,44 @@
    }
    backendDirectory = getFileForPath(backendDirectoryAttr.activeValue());
    // ds-cfg-backend-mode
    // Optional, single-valued config attribute requiring admin action on change
    msg = getMessage(MSGID_CONFIG_DESCRIPTION_BACKEND_MODE);
    stub =
        new StringConfigAttribute(ATTR_BACKEND_MODE, msg, false,false, true);
    StringConfigAttribute backendModeAttr = (StringConfigAttribute)
         configEntry.getConfigAttribute(stub);
    if (backendModeAttr != null)
    {
      FilePermission newBackendPermission;
      try
      {
        newBackendPermission = FilePermission.decodeUNIXMode(
            backendModeAttr.activeValue());
      }
      catch(Exception e)
      {
        int msgID = MSGID_CONFIG_BACKEND_MODE_INVALID;
        String message = getMessage(msgID, configEntry.getDN().toString());
        throw new ConfigException(msgID, message);
      }
      //Make sure the mode will allow the server itself access to
      //the database
      if(!newBackendPermission.isOwnerWritable() ||
           !newBackendPermission.isOwnerReadable() ||
           !newBackendPermission.isOwnerExecutable())
      {
        int msgID = MSGID_CONFIG_BACKEND_INSANE_MODE;
        String message = getMessage(msgID);
        throw new ConfigException(msgID, message);
      }
      else
      {
        backendPermission = newBackendPermission;
      }
    }
    // ds-cfg-backendIndexEntryLimit
    // Optional, single-valued config attribute requiring admin action on change
    msg = getMessage(MSGID_CONFIG_DESCRIPTION_BACKEND_INDEX_ENTRY_LIMIT);
@@ -723,6 +775,16 @@
  }
  /**
   * Get the backend directory file permission mode.
   *
   * @return An FilePermission representing the directory permissions
   */
  public FilePermission getBackendPermission()
  {
     return backendPermission;
  }
  /**
   * Get the set of base DNs.
   *
   * @return An array of base DNs.
opends/src/server/org/opends/server/config/ConfigConstants.java
@@ -3288,6 +3288,15 @@
  /**
   * The name of the attribute which configures the file permission mode
   * for the database direction.
   */
  public static final String ATTR_BACKEND_MODE =
      ConfigConstants.NAME_PREFIX_CFG + "backend-mode";
  /**
   * The name of the file (with no path information) that will be used as the
   * backing file for holding the tasks defined in the Directory Server.
   */
opends/src/server/org/opends/server/messages/ConfigMessages.java
@@ -6125,6 +6125,34 @@
  /**
   * The message ID used to describe the attribute which configure the
   * file permissions mode for the database directory.
   */
  public static final int MSGID_CONFIG_DESCRIPTION_BACKEND_MODE =
      CATEGORY_MASK_CONFIG | SEVERITY_MASK_INFORMATIONAL | 566;
  /**
   * The message ID for the message that will be used if the backend directory
   * file permission mode atrribute is not a valid UNIX mode.
   */
  public static final int MSGID_CONFIG_BACKEND_MODE_INVALID =
      CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 567;
  /**
   * The message ID of an error indicating that the file permissions for the
   * database directory will result in an inaccessable database. The orginal or
   * default value will be used instead
   */
  public static final int MSGID_CONFIG_BACKEND_INSANE_MODE =
      CATEGORY_MASK_JEB | SEVERITY_MASK_SEVERE_WARNING | 568;
  /**
   * Associates a set of generic messages with the message IDs defined in this
   * class.
   */
@@ -8881,6 +8909,18 @@
                    " (It should be a positive integer value specifying " +
                    "the lookthrough limit to use, or a value of 0 or -1 to " +
                    "indicate that no limit should be enforced):  %s.");
    registerMessage(MSGID_CONFIG_DESCRIPTION_BACKEND_MODE,
                    "The permissions used for the directory containing the " +
                    "backend database files");
    registerMessage(MSGID_CONFIG_BACKEND_MODE_INVALID,
                   "Configuration entry %s does not contain a valid value " +
                   "for configuration attribute " + ATTR_BACKEND_MODE +
                   " (It should be an UNIX permission mode in three-digit " +
                   "octal notation.)");
    registerMessage(MSGID_CONFIG_BACKEND_INSANE_MODE,
                   "Unable to set the requested file permissions to the " +
                   "backend database directory. The requested permissions " +
                   "will result in an inaccessable database.");
  }
}
opends/src/server/org/opends/server/messages/JebMessages.java
@@ -1241,6 +1241,12 @@
  /**
   * The message ID of an error indicating that the file permissions for the
   * database directory was not set.
   */
  public static final int MSGID_JEB_SET_PERMISSIONS_FAILED =
      CATEGORY_MASK_JEB | SEVERITY_MASK_SEVERE_WARNING | 128;
  /**
   * Associates a set of generic messages with the message IDs defined in this
@@ -1734,5 +1740,8 @@
    registerMessage(MSGID_JEB_LOOKTHROUGH_LIMIT_EXCEEDED,
                    "This search operation has checked the maximum of %d " +
                    "entries for matches.");
    registerMessage(MSGID_JEB_SET_PERMISSIONS_FAILED,
                    "Unable to set file permissions for the backend database " +
                    "directory %s.");
  }
}