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

Valery Kharseko
9 hours ago 83db1555233d219fe0d8642a16ef64fc127ada54
Fix java/local-temp-file-or-directory-information-disclosure CodeQL alerts by using NIO temp file APIs (#763)
13 files modified
1 files added
182 ■■■■ changed files
opendj-embedded/src/main/java/org/openidentityplatform/opendj/embedded/EmbeddedOpenDJ.java 37 ●●●● patch | view | raw | blame | history
opendj-embedded/src/test/java/org/openidentityplatform/opendj/embedded/EmbeddedOpenDJTest.java 11 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ControlPanelLauncher.java 5 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/NewBaseDNPanel.java 4 ●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/quicksetup/TempLogFile.java 4 ●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/InstallerHelper.java 4 ●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/admin/doc/ConfigGuideGeneration.java 17 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeImporter.java 3 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/schema/SchemaFilesWriter.java 16 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/LDAPAuthenticationHandler.java 4 ●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/dsreplication/ReplicationCliMain.java 4 ●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/status/StatusCli.java 4 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/util/SetupUtils.java 4 ●●● patch | view | raw | blame | history
opendj-server-legacy/src/test/java/org/opends/server/util/SetupUtilsTestCase.java 65 ●●●●● patch | view | raw | blame | history
opendj-embedded/src/main/java/org/openidentityplatform/opendj/embedded/EmbeddedOpenDJ.java
@@ -11,7 +11,7 @@
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2024 3A Systems LLC.
 * Copyright 2024-2026 3A Systems LLC.
 */
package org.openidentityplatform.opendj.embedded;
@@ -60,6 +60,9 @@
    final Config config;
    private final File instanceDirectory;
    private final File rootDirectory;
    public EmbeddedOpenDJ() {
        this(new Config());
    }
@@ -69,13 +72,18 @@
        logger.info("Create embedded OpenDJ instance: {}", config);
        this.config = config;
        File tempDirectory = new File(System.getProperty("java.io.tmpdir"));
        File rootDirectory = new File(tempDirectory, "opendj");
        File instanceDirectory = null;
        try {
            if(rootDirectory.exists()) {
                FileUtils.deleteDirectory(rootDirectory);
            }
            // Create a fresh per-instance parent directory, only accessible by the
            // current user, instead of the fixed shared {java.io.tmpdir}/opendj
            // directory. The server root inside it must be named "opendj" because
            // setup from an archive requires the server root directory to match the
            // root directory contained in the archive. The whole directory is
            // deleted on close().
            instanceDirectory = Files.createTempDirectory("opendj").toFile();
            File rootDirectory = new File(instanceDirectory, "opendj");
            rootDirectory.mkdir();
            logger.info("OpenDJ server root: {}", rootDirectory);
            File configDirectory = new File(rootDirectory, "config");
            File schemaDirectory = new File(configDirectory, "schema");
@@ -109,13 +117,25 @@
            copyFilesFromJar(schemaFiles, JAR_SCHEMA_DIRECTORY, schemaDirectory);
            this.instanceDirectory = instanceDirectory;
            this.rootDirectory = rootDirectory;
        }catch (Exception e) {
            logger.error("Error initializing OpenDJ");
            FileUtils.deleteQuietly(instanceDirectory);
            throw new RuntimeException(e);
        }
        Runtime.getRuntime().addShutdownHook(new Thread(this::close));
    }
    /**
     * Returns the server root directory of this embedded instance.
     *
     * @return the server root directory
     */
    public File getServerRootDirectory() {
        return rootDirectory;
    }
    @Override
    public void run() {
        try {
@@ -145,13 +165,16 @@
    @Override
    public void close()  {
        if (server.isRunning())
        if (server.isRunning()) {
            try {
                logger.info("Shutting down OpenDJ ...");
                server.stop(this.getClass().getName(), LocalizableMessage.raw("Stopped after receiving Control-C"));
            }catch (Throwable e) {
                logger.error("Error stopping OpenDJ", e);
            }
        }
        // close() is also registered as a shutdown hook, so deletion must stay idempotent
        FileUtils.deleteQuietly(instanceDirectory);
    }
    private void copyFilesFromJar(List<String> jarFiles, String jarDirectory, File outputDirectory) throws IOException{
opendj-embedded/src/test/java/org/openidentityplatform/opendj/embedded/EmbeddedOpenDJTest.java
@@ -11,7 +11,7 @@
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2024 3A Systems LLC.
 * Copyright 2024-2026 3A Systems LLC.
 */
package org.openidentityplatform.opendj.embedded;
@@ -54,6 +54,9 @@
        embeddedOpenDJ.run();
        assertTrue(embeddedOpenDJ.isRunning());
        File serverRoot = embeddedOpenDJ.getServerRootDirectory();
        assertTrue(serverRoot.isDirectory());
        //import ldif data from an input stream
        URI resUri = getClass().getClassLoader().getResource("opendj/data.ldif").toURI();
        byte[] bytes = Files.readAllBytes(Paths.get(resUri));
@@ -83,5 +86,9 @@
        //stop OpenDJ
        embeddedOpenDJ.close();
        assertFalse(embeddedOpenDJ.isRunning());
        //the per-instance temporary directory is deleted on close
        assertFalse(serverRoot.exists());
        assertFalse(serverRoot.getParentFile().exists());
    }
}
}
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ControlPanelLauncher.java
@@ -13,6 +13,7 @@
 *
 * Copyright 2008-2010 Sun Microsystems, Inc.
 * Portions Copyright 2011-2016 ForgeRock AS.
 * Portions Copyright 2026 3A Systems, LLC.
 */
package org.opends.guitools.controlpanel;
@@ -21,8 +22,8 @@
import static org.opends.messages.AdminToolMessages.*;
import static org.opends.messages.ToolMessages.*;
import java.io.File;
import java.io.PrintStream;
import java.nio.file.Files;
import javax.swing.SwingUtilities;
@@ -64,7 +65,7 @@
  {
    try {
      ControlPanelLog.initLogFileHandler(
          File.createTempFile(LOG_FILE_PREFIX, LOG_FILE_SUFFIX));
          Files.createTempFile(LOG_FILE_PREFIX, LOG_FILE_SUFFIX).toFile());
    } catch (Throwable t) {
      System.err.println("Unable to initialize log");
      t.printStackTrace();
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/NewBaseDNPanel.java
@@ -13,6 +13,7 @@
 *
 * Copyright 2008-2009 Sun Microsystems, Inc.
 * Portions Copyright 2011-2016 ForgeRock AS.
 * Portions Copyright 2026 3A Systems, LLC.
 */
package org.opends.guitools.controlpanel.ui;
@@ -28,6 +29,7 @@
import java.awt.event.ItemListener;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -1239,7 +1241,7 @@
      final TemplateFile generator = new TemplateFile(resourceDir.getAbsolutePath(), new Random(0));
      generator.parse(templateFile.getAbsolutePath(), Collections.<LocalizableMessage>emptyList());
      final File tempFile = File.createTempFile("opendj-control-panel", ".ldif");
      final File tempFile = Files.createTempFile("opendj-control-panel", ".ldif").toFile();
      tempFile.deleteOnExit();
      final String generatedLdifFilePath = tempFile.getAbsolutePath();
opendj-server-legacy/src/main/java/org/opends/quicksetup/TempLogFile.java
@@ -13,12 +13,14 @@
 *
 * Copyright 2008-2010 Sun Microsystems, Inc.
 * Portions Copyright 2011-2016 ForgeRock AS.
 * Portions Copyright 2026 3A Systems, LLC.
 */
package org.opends.quicksetup;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Date;
import java.text.DateFormat;
@@ -51,7 +53,7 @@
  {
    try
    {
      return new TempLogFile(File.createTempFile(prefix, ".log"));
      return new TempLogFile(Files.createTempFile(prefix, ".log").toFile());
    }
    catch (final IOException e)
    {
opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/InstallerHelper.java
@@ -13,6 +13,7 @@
 *
 * Copyright 2006-2010 Sun Microsystems, Inc.
 * Portions Copyright 2011-2016 ForgeRock AS.
 * Portions Copyright 2026 3A Systems, LLC.
 */
package org.opends.quicksetup.installer;
@@ -33,6 +34,7 @@
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
@@ -272,7 +274,7 @@
    File ldifFile;
    try
    {
      ldifFile = File.createTempFile("opendj-base-entry", ".ldif");
      ldifFile = Files.createTempFile("opendj-base-entry", ".ldif").toFile();
      ldifFile.deleteOnExit();
    } catch (IOException ioe)
    {
opendj-server-legacy/src/main/java/org/opends/server/admin/doc/ConfigGuideGeneration.java
@@ -19,6 +19,7 @@
import java.io.File;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
@@ -98,7 +99,7 @@
   *
   * Properties:
   * GenerationDir - The directory where the doc is generated
   *              (default is /var/tmp/[CONFIG_GUIDE_DIR&gt;])
   *              (default is a fresh temporary directory, printed on startup)
   * LdapMapping - Presence means that the LDAP mapping section is to be
   *               generated (default is no)
   * OpenDJWiki - The URL of the OpenDJ Wiki
@@ -112,14 +113,14 @@
  public static void main(String[] args) {
    Properties properties = System.getProperties();
    generationDir = properties.getProperty("GenerationDir");
    if (generationDir == null) {
      // Default dir is prefixed by the system-dependent default temporary dir
      generationDir = System.getProperty("java.io.tmpdir") + File.separator +
        CONFIG_GUIDE_DIR;
    }
    // Create new dir if necessary
    try {
      new File(generationDir).mkdir();
      if (generationDir == null) {
        // Default dir is a fresh temporary dir, only accessible by the current user
        generationDir = Files.createTempDirectory(CONFIG_GUIDE_DIR).toString();
      } else {
        // Create new dir if necessary
        new File(generationDir).mkdir();
      }
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(1);
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeImporter.java
@@ -38,6 +38,7 @@
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.file.Files;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
@@ -425,7 +426,7 @@
    private File exportBranches(List<DN> includeBranches, List<DN> excludeBranches) throws Exception
    {
      final File migrationFile = File.createTempFile("import-migration-", ".ldif");
      final File migrationFile = Files.createTempFile("import-migration-", ".ldif").toFile();
      final LDIFExportConfig exportConfig =
          new LDIFExportConfig(migrationFile.getAbsolutePath(), ExistingFileBehavior.OVERWRITE);
      exportConfig.setIncludeBranches(includeBranches);
opendj-server-legacy/src/main/java/org/opends/server/schema/SchemaFilesWriter.java
@@ -13,6 +13,7 @@
 *
 * Copyright 2006-2010 Sun Microsystems, Inc.
 * Portions Copyright 2011-2016 ForgeRock AS.
 * Portions Copyright 2026 3A Systems, LLC.
 */
package org.opends.server.schema;
@@ -40,6 +41,7 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.PosixFilePermission;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
@@ -725,7 +727,7 @@
    }
    // Create a temporary file to which we can write the schema entry.
    File tempFile = File.createTempFile(schemaFile, "temp");
    File tempFile = Files.createTempFile(schemaFile, "temp").toFile();
    LDIFExportConfig exportConfig =
         new LDIFExportConfig(tempFile.getAbsolutePath(),
                              ExistingFileBehavior.OVERWRITE);
@@ -1064,11 +1066,23 @@
    // files.  If this fails, then try to restore the originals.
    try
    {
      boolean posixSupported = schemaInstanceDir.toPath().getFileSystem()
          .supportedFileAttributeViews().contains("posix");
      for (int i=0; i < installedFileList.size(); i++)
      {
        File installedFile = installedFileList.get(i);
        File tempFile      = tempFileList.get(i);
        // The temporary file was created with owner-only permissions and Files.copy
        // propagates the source permissions, so preserve the permissions of the
        // previously installed schema file.
        Set<PosixFilePermission> previousPermissions = posixSupported && installedFile.exists()
            ? Files.getPosixFilePermissions(installedFile.toPath())
            : null;
        Files.copy(tempFile.toPath(), installedFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
        if (previousPermissions != null)
        {
          Files.setPosixFilePermissions(installedFile.toPath(), previousPermissions);
        }
      }
    }
    catch (Exception e)
opendj-server-legacy/src/main/java/org/opends/server/tools/LDAPAuthenticationHandler.java
@@ -13,6 +13,7 @@
 *
 * Copyright 2006-2009 Sun Microsystems, Inc.
 * Portions Copyright 2012-2016 ForgeRock AS.
 * Portions Copyright 2026 3A Systems, LLC.
 */
package org.opends.server.tools;
@@ -28,6 +29,7 @@
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.security.PrivilegedExceptionAction;
import java.security.SecureRandom;
@@ -1892,7 +1894,7 @@
    String configFileName;
    try
    {
      File tempFile = File.createTempFile("login", "conf");
      File tempFile = Files.createTempFile("login", "conf").toFile();
      configFileName = tempFile.getAbsolutePath();
      tempFile.deleteOnExit();
      try (BufferedWriter w = new BufferedWriter(new FileWriter(tempFile, false))) {
opendj-server-legacy/src/main/java/org/opends/server/tools/dsreplication/ReplicationCliMain.java
@@ -14,6 +14,7 @@
 * Copyright 2007-2010 Sun Microsystems, Inc.
 * Portions Copyright 2011-2016 ForgeRock AS.
 * Portions Copyright 2012 profiq s.r.o.
 * Portions Copyright 2026 3A Systems, LLC.
 */
package org.opends.server.tools.dsreplication;
@@ -46,6 +47,7 @@
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -364,7 +366,7 @@
    try
    {
      ControlPanelLog.initLogFileHandler(
          File.createTempFile(LOG_FILE_PREFIX, LOG_FILE_SUFFIX));
          Files.createTempFile(LOG_FILE_PREFIX, LOG_FILE_SUFFIX).toFile());
    } catch (Throwable t) {
      System.err.println("Unable to initialize log");
      t.printStackTrace();
opendj-server-legacy/src/main/java/org/opends/server/tools/status/StatusCli.java
@@ -29,10 +29,10 @@
import static org.opends.messages.QuickSetupMessages.INFO_NOT_AVAILABLE_LABEL;
import static org.opends.messages.ToolMessages.*;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.file.Files;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
@@ -166,7 +166,7 @@
    try {
      ControlPanelLog.initLogFileHandler(
              File.createTempFile(LOG_FILE_PREFIX, LOG_FILE_SUFFIX));
              Files.createTempFile(LOG_FILE_PREFIX, LOG_FILE_SUFFIX).toFile());
      ControlPanelLog.initPackage("org.opends.server.tools.status");
    } catch (Throwable t) {
      System.err.println("Unable to initialize log");
opendj-server-legacy/src/main/java/org/opends/server/util/SetupUtils.java
@@ -13,6 +13,7 @@
 *
 * Copyright 2006-2010 Sun Microsystems, Inc.
 * Portions Copyright 2011-2016 ForgeRock AS.
 * Portions Copyright 2026 3A Systems, LLC.
 */
package org.opends.server.util;
@@ -27,6 +28,7 @@
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.file.Files;
import java.security.KeyStoreException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
@@ -149,7 +151,7 @@
      int numEntries)
         throws IOException
  {
    File templateFile = File.createTempFile("opendj-install", ".template");
    File templateFile = Files.createTempFile("opendj-install", ".template").toFile();
    templateFile.deleteOnExit();
    LinkedList<String> lines = new LinkedList<>();
opendj-server-legacy/src/test/java/org/opends/server/util/SetupUtilsTestCase.java
New file
@@ -0,0 +1,65 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions copyright [year] [name of copyright owner]".
 *
 * Copyright 2026 3A Systems, LLC.
 */
package org.opends.server.util;
import static org.testng.Assert.assertEquals;
import java.io.File;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
import org.testng.SkipException;
import org.testng.annotations.Test;
/**
 * A set of test cases for the SetupUtils class.
 */
public class SetupUtilsTestCase extends UtilTestCase
{
  /**
   * Tests that temporary files are created readable and writable only by the
   * owner on POSIX file systems.
   *
   * @throws Exception
   *           If an unexpected problem occurs.
   */
  @Test
  public void testCreateTemplateFileIsOwnerAccessOnly() throws Exception
  {
    if (!FileSystems.getDefault().supportedFileAttributeViews().contains("posix"))
    {
      throw new SkipException("POSIX file permissions are not supported on this platform");
    }
    File templateFile = SetupUtils.createTemplateFile(
        Collections.singleton("dc=example,dc=com"), 1);
    try
    {
      Set<PosixFilePermission> permissions =
          Files.getPosixFilePermissions(templateFile.toPath());
      assertEquals(permissions,
          EnumSet.of(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE));
    }
    finally
    {
      templateFile.delete();
    }
  }
}