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

12 files modified
580 ■■■■ changed files
.github/workflows/build.yml 19 ●●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/ldap/AddressMask.java 5 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/java/org/forgerock/opendj/ldap/AddressMaskTestCase.java 14 ●●●● patch | view | raw | blame | history
opendj-server-legacy/pom.xml 16 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/resource/bin/stop-ds.bat 10 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/build-tools/windows/service.c 348 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/build-tools/windows/service.h 1 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/build-tools/windows/winlauncher.c 145 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/build-tools/windows/winlauncher.h 5 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/cassandra/Storage.java 6 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java 7 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/snmp/src/org/opends/server/snmp/SNMPMonitor.java 4 ●●●● patch | view | raw | blame | history
.github/workflows/build.yml
@@ -287,6 +287,21 @@
    - name: Test on Windows
      if: runner.os == 'Windows'
      run:   |
        # Verify a stop took effect before moving on: wait until the server
        # releases the exclusive byte-range lock it holds on locks\server.lock.
        # The explicit Lock(0, 1) probe is required: a byte-range lock does not
        # prevent opening the file, so a bare Open() would always succeed.
        function Wait-ServerStopped($lockFile) {
          $lockFile = Join-Path $PWD $lockFile
          for ($i = 0; $i -lt 30; $i++) {
            if (-not (Test-Path $lockFile)) { return }
            try {
              $fs = [System.IO.File]::Open($lockFile, 'Open', 'ReadWrite', 'ReadWrite')
              try { $fs.Lock(0, 1); $fs.Unlock(0, 1); return } finally { $fs.Close() }
            } catch { Start-Sleep -Seconds 2 }
          }
          throw "The server still holds the lock on ${lockFile}: the stop did not take effect"
        }
        set OPENDJ_JAVA_ARGS="-server -Xmx512m"
        opendj-server-legacy\target\package\opendj\setup.bat -h localhost -p 1389 --ldapsPort 1636 --adminConnectorPort 4444 --enableStartTLS --generateSelfSignedCertificate --rootUserDN "cn=Directory Manager" --rootUserPassword password --baseDN dc=example,dc=com --sampleData 5000 --cli --acceptLicense --no-prompt
        opendj-server-legacy\target\package\opendj\bat\status.bat --hostname localhost --bindDN "cn=Directory Manager" --bindPassword password --trustAll
@@ -325,6 +340,8 @@
        opendj-server-legacy\target\package\opendj\bat\dsconfig.bat create-backend --hostname localhost --port 4444 --bindDN "cn=Directory Manager" --bindPassword password --backend-name=example2 --type je --set=base-dn:dc=example2,dc=com --set=enabled:true --no-prompt --trustAll
        opendj-server-legacy\target\package\opendj\bat\makeldif.bat -o test.ldif -c suffix=dc=example2,dc=com opendj-server-legacy\target\package\opendj\config\MakeLDIF\example.template
        opendj-server-legacy\target\package\opendj\bat\stop-ds.bat
        if ($LASTEXITCODE -ne 0) { throw "stop-ds.bat failed with exit code $LASTEXITCODE" }
        Wait-ServerStopped 'opendj-server-legacy\target\package\opendj\locks\server.lock'
        echo "4.9.9.0" > opendj-server-legacy\target\package\opendj\config\buildinfo
        opendj-server-legacy\target\package\opendj\upgrade.bat
        opendj-server-legacy\target\package\opendj\bat\import-ldif.bat --offline --ldifFile test.ldif --backendID=example2
@@ -333,6 +350,8 @@
        opendj-server-legacy\target\package\opendj\bat\rebuild-index.bat --bindDN "cn=Directory Manager" --bindPassword password --baseDN "dc=example2,dc=com" --rebuildAll --trustAll
        opendj-server-legacy\target\package\opendj\bat\ldapsearch.bat --hostname localhost --port 1636 --bindDN "cn=Directory Manager" --bindPassword password --useSsl --trustAll --baseDN "dc=example2,dc=com" --searchScope sub "(uid=user.*)" dn | find /c '"dn:"' | findstr "10000"
        opendj-server-legacy\target\package\opendj\bat\stop-ds.bat
        if ($LASTEXITCODE -ne 0) { throw "stop-ds.bat failed with exit code $LASTEXITCODE" }
        Wait-ServerStopped 'opendj-server-legacy\target\package\opendj\locks\server.lock'
        opendj-server-legacy\target\package\opendj\bat\windows-service.bat --enableService
        net start "OpenDJ Server"
        if ($LASTEXITCODE -ne 0) { throw "net start 'OpenDJ Server' failed with exit code $LASTEXITCODE" }
opendj-core/src/main/java/org/forgerock/opendj/ldap/AddressMask.java
@@ -13,6 +13,7 @@
 *
 * Copyright 2006-2009 Sun Microsystems, Inc.
 * Portions copyright 2011-2014 ForgeRock AS.
 * Portions Copyright 2026 3A Systems, LLC.
 */
package org.forgerock.opendj.ldap;
@@ -328,7 +329,7 @@
     */
    private void processHost(final String rule) {
        // Note that '*' is valid in host rule
        final String[] s = rule.split("^[0-9a-zA-z-.*]+");
        final String[] s = rule.split("^[0-9a-zA-Z_.*-]+");
        if (s.length > 0) {
            throw genericDecodeError();
        }
@@ -346,7 +347,7 @@
     */
    private void processHostPattern(final String rule) {
        // quick check for invalid chars like " "
        final String[] s = rule.split("^[0-9a-zA-z-.]+");
        final String[] s = rule.split("^[0-9a-zA-Z_.-]+");
        if (s.length > 0) {
            throw genericDecodeError();
        }
opendj-core/src/test/java/org/forgerock/opendj/ldap/AddressMaskTestCase.java
@@ -13,6 +13,7 @@
 *
 * Copyright 2006-2008 Sun Microsystems, Inc.
 * Portions copyright 2011-2015 ForgeRock AS.
 * Portions Copyright 2026 3A Systems, LLC.
 */
package org.forgerock.opendj.ldap;
@@ -38,7 +39,9 @@
    public Object[][] validData() {
        return new Object[][] { { "129.34.55.67" }, { "129.*.78.55" }, { ".central.sun.com" },
            { "foo.central.sun.com" }, { "foo.*.sun.*" }, { "128.*.*.*" }, { "129.45.23.67/22" },
            { "128.33.23.21/32" }, { "*.*.*.*" }, { "129.45.67.34/0" }, { "foo.com" }, { "foo" } };
            { "128.33.23.21/32" }, { "*.*.*.*" }, { "129.45.67.34/0" }, { "foo.com" }, { "foo" },
            // Underscores appear in real deployments and stay accepted.
            { "my_host.example.com" }, { ".my_domain.com" } };
    }
    @DataProvider(name = "invalidRules")
@@ -47,7 +50,14 @@
            { "129.56.78.90/2000" }, { "677.777.AG.BC" }, { "/34" }, { "234.12.12.*/31" },
            { "234.12.12.90/" }, { "129.34.56.78/-100" }, { "129" }, { "129.34.-90.67" },
            { "129.**.56.67" }, { "foo bar.com" }, { "12foo.example.com" }, { "123.45." },
            { ".central.sun day.com" }, { "129.34.45.45/4/3/" } };
            { ".central.sun day.com" }, { "129.34.45.45/4/3/" },
            /*
             * The characters between 'Z' and 'a' used to slip through the host and host
             * pattern validators, which spelled the letter range as A-z instead of A-Z.
             */
            { "foo[bar.com" }, { "foo\\bar.com" }, { "foo]bar.com" }, { "foo^bar.com" },
            { "foo`bar.com" }, { ".foo[bar.com" }, { ".foo\\bar.com" }, { ".foo]bar.com" },
            { ".foo^bar.com" }, { ".foo`bar.com" } };
    }
    @DataProvider(name = "toStringRule")
opendj-server-legacy/pom.xml
@@ -31,20 +31,6 @@
  </description>
  <inceptionYear>2010</inceptionYear>
  <repositories>
    <repository>
      <id>oracle-repository</id>
      <name>Oracle Maven Repository</name>
      <url>http://download.oracle.com/maven</url>
      <releases>
        <enabled>true</enabled>
      </releases>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>
  <properties>
    <!-- General server-wide properties -->
    <docgen.dir>${project.build.directory}/docgen</docgen.dir>
@@ -265,7 +251,7 @@
    <dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <version>42.7.11</version>
      <version>42.7.12</version>
    </dependency>
    <dependency>
      <groupId>org.testng</groupId>
opendj-server-legacy/resource/bin/stop-ds.bat
@@ -14,6 +14,7 @@
rem
rem Copyright 2006-2010 Sun Microsystems, Inc.
rem Portions Copyright 2011-2014 ForgeRock AS.
rem Portions Copyright 2026 3A Systems, LLC.
setlocal
@@ -93,12 +94,19 @@
:stopUsingSystemCall
echo %SCRIPT%: stop using system call >> %LOG%
"%INSTALL_ROOT%\lib\winlauncher.exe" stop "%INSTANCE_ROOT%"
if not %errorlevel% == 0 (
  echo %SCRIPT%: winlauncher stop failed with error %errorlevel% >> %LOG%
  exit /B %errorlevel%
)
goto end
:restartUsingSystemCall
echo %SCRIPT%: restart using system call >> %LOG%
"%INSTALL_ROOT%\lib\winlauncher.exe" stop "%INSTANCE_ROOT%"
if not %errorlevel% == 0 goto end
if not %errorlevel% == 0 (
  echo %SCRIPT%: winlauncher stop failed with error %errorlevel% >> %LOG%
  exit /B %errorlevel%
)
goto startUsingSystemCall
:stopUsingProtocol
opendj-server-legacy/src/build-tools/windows/service.c
@@ -24,6 +24,13 @@
char *_instanceDir = NULL;
HANDLE _eventLog = NULL;
char * _logFile = NULL;
// The root of the server instance (where logs\server.pid and
// locks\server.lock live).  _instanceDir is the install root the
// service was created with; on split install/instance layouts the
// instance root differs and is resolved from the install root's
// instance.loc file.  Resolved by getInstanceRoot(), normally once
// from setInstanceDir(), and released by freeInstanceDir().
static char *_instanceRoot = NULL;
// ----------------------------------------------------
// Register a service handler to the service control dispatcher.
@@ -417,6 +424,113 @@
}
// ----------------------------------------------------
// Returns the root of the server instance whose files the service
// must probe.  The launching scripts (_script-util.bat) resolve it
// from the install root's instance.loc file when that file exists
// (split install/instance layouts), resolving a relative content
// against the install root, and fall back to the install root
// itself.  This function performs the same resolution.  The result is
// cached, except when instance.loc exists but its content cannot be
// resolved yet (getCanonicalDirectoryPath requires the directory to
// exist, e.g. an instance on a volume that is not mounted yet):
// caching the install root then would make isServerRunning() probe
// the wrong locks\server.lock for the lifetime of the process, so
// that case is reported to the event log and retried on the next
// call, probing the install root only for the current call.
// ----------------------------------------------------
static char* getInstanceRoot(void)
{
  char locFile[MAX_PATH];
  FILE *f;
  char *resolved = NULL;
  BOOL unresolvable = FALSE;
  if (_instanceRoot != NULL)
  {
    return _instanceRoot;
  }
  if (isSafePath(_instanceDir)
      && (strlen(_instanceDir) + strlen("\\instance.loc") + 1 < MAX_PATH))
  {
    _snprintf(locFile, MAX_PATH, "%s\\instance.loc", _instanceDir);
    f = fopen(locFile, "r");
    if (f != NULL)
    {
      char line[MAX_PATH];
      if (fgets(line, MAX_PATH, f) != NULL)
      {
        size_t len = strlen(line);
        while ((len > 0)
            && ((line[len - 1] == '\n') || (line[len - 1] == '\r')
                || (line[len - 1] == ' ') || (line[len - 1] == '\t')))
        {
          line[--len] = '\0';
        }
        if (len > 0)
        {
          char joined[2 * MAX_PATH];
          BOOL isAbsolute = ((len >= 2) && (line[1] == ':'))
              || ((line[0] == '\\') && (line[1] == '\\'));
          if (isAbsolute)
          {
            _snprintf(joined, sizeof(joined), "%s", line);
          }
          else
          {
            _snprintf(joined, sizeof(joined), "%s\\%s", _instanceDir, line);
          }
          resolved = getCanonicalDirectoryPath(joined);
          if (resolved == NULL)
          {
            unresolvable = TRUE;
            debugError("Could not resolve the instance root '%s' read from '%s'.",
                joined, locFile);
          }
          else
          {
            debug("Instance root resolved from '%s': '%s'.", locFile, resolved);
          }
        }
      }
      fclose(f);
    }
  }
  if (unresolvable)
  {
    static volatile LONG alreadyReported = 0;
    if (InterlockedCompareExchange(&alreadyReported, 1, 0) == 0)
    {
      char msg[2 * MAX_PATH];
      const char *logArgs[1];
      _snprintf(msg, sizeof(msg),
          "Could not resolve the OpenDJ instance root from '%s'; probing the install root '%s' until the instance root becomes available.",
          locFile, _instanceDir);
      msg[sizeof(msg) - 1] = '\0';
      logArgs[0] = msg;
      if (!reportLogEvent(EVENTLOG_WARNING_TYPE, WIN_EVENT_ID_DEBUG, 1, logArgs))
      {
        // The event log is not registered yet (command-line paths and the
        // eager call from setInstanceDir): let a later call report it.
        InterlockedExchange(&alreadyReported, 0);
      }
    }
    return _instanceDir;
  }
  if (resolved == NULL)
  {
    // No usable instance.loc: the install root is the instance root.
    _instanceRoot = _instanceDir;
  }
  else if (InterlockedCompareExchangePointer((PVOID*)&_instanceRoot, resolved,
      NULL) != NULL)
  {
    // A concurrent first call published its copy: keep that one.
    free(resolved);
  }
  return _instanceRoot;
}  // getInstanceRoot
// ----------------------------------------------------
// Check if the server is running or not.
// The functions returns SERVICE_RETURN_OK if we could determine if
// the server is running or not and false otherwise.
@@ -426,15 +540,16 @@
  ServiceReturnCode returnValue;
  char* relativePath = "\\locks\\server.lock";
  char lockFile[MAX_PATH];
  char* instanceRoot = getInstanceRoot();
  if (mustDebug)
  {
    debug("Determining if the server is running.");
  }
  if (isSafePath(_instanceDir) && strlen(relativePath)+strlen(_instanceDir)+1 < MAX_PATH)
  if (isSafePath(instanceRoot) && strlen(relativePath)+strlen(instanceRoot)+1 < MAX_PATH)
  {
    int fd;
    _snprintf(lockFile, MAX_PATH, "%s%s", _instanceDir, relativePath);
    _snprintf(lockFile, MAX_PATH, "%s%s", instanceRoot, relativePath);
    if (mustDebug)
    {
      debug(
@@ -698,22 +813,40 @@
// ----------------------------------------------------
// Stop the application using stop-ds.bat
// Stop the application by invoking winlauncher.exe stop directly.
// The stop used to go through stop-ds.bat --windowsNetStop, but on
// that path two java processes are launched only to end up in the
// very same winlauncher.exe stop call, keeping the SCM waiting for
// tens of seconds before the stop even begins.
// While the stop is in progress the SERVICE_STOP_PENDING status is
// re-reported with an incrementing checkPoint through
// serviceStatusHandle, as doStartApplication does for the start
// (both parameters may be NULL when no reporting is wanted).
// The functions returns SERVICE_RETURN_OK if we could stop the server
// and SERVICE_RETURN_ERROR otherwise.
// ----------------------------------------------------
ServiceReturnCode doStopApplication()
ServiceReturnCode doStopApplication(SERVICE_STATUS_HANDLE *serviceStatusHandle, DWORD *checkPoint)
{
  ServiceReturnCode returnValue;
  // init out params
  char* relativePath = "\\bat\\stop-ds.bat";
  char* relativePath = "\\lib\\winlauncher.exe";
  char command[COMMAND_SIZE];
  // winlauncher.exe lives under the install root, but the directory it
  // operates on (logs\server.pid, locks\server.lock) is the instance root.
  char* instanceRoot = getInstanceRoot();
  debug("doStopApplication");
  if (strlen(relativePath)+strlen(_instanceDir)+1 < COMMAND_SIZE)
  if (strlen(relativePath) + strlen(_instanceDir) + strlen(instanceRoot)
      + strlen("\"\" stop \"\\.\"") + 1 < COMMAND_SIZE)
  {
    _snprintf(command, COMMAND_SIZE, "\"%s%s\" --windowsNetStop", _instanceDir, relativePath);
    // The trailing "\." protects the closing quote from a root that ends
    // with a backslash (which the command line parser would treat as an
    // escape); winlauncher.exe removes it again when canonicalizing the path.
    _snprintf(command, COMMAND_SIZE, "\"%s%s\" stop \"%s\\.\"", _instanceDir, relativePath, instanceRoot);
    // The stop no longer goes through stop-ds.bat, so this debug log is
    // the only file trace of the stop: record the command unconditionally.
    debug("doStopApplication: launching '%s'.", command);
    // launch the command
    if (spawn(command, FALSE) != -1)
    {
@@ -723,12 +856,15 @@
      debug("doStopApplication: the spawn of the process worked.");
      // Wait to be able to launch the java process in order it to free the lock
      // on the file.
      Sleep(3000);
      Sleep(1000);
      while ((nTries > 0) && running)
      {
        nTries--;
        if (serviceStatusHandle != NULL && checkPoint != NULL)
        {
          updateServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, 0,
              (*checkPoint)++, 10000, serviceStatusHandle);
        }
        if (isServerRunning(&running, TRUE) != SERVICE_RETURN_OK)
        {
          break;
@@ -939,10 +1075,10 @@
  // elaborate the commands supported by the service:
  // - STOP        customer has performed a stop-ds (or NET STOP)
  // - SHUTDOWN    the system is rebooting
  // - INTERROGATE service controler can interrogate the service
  // - No need to support PAUSE/CONTINUE
  //
  // Note: INTERROGATE *must* be supported by the service handler
  // Note: INTERROGATE has no SERVICE_ACCEPT_ bit: it is always accepted
  // and *must* be supported by the service handler
  DWORD controls;
  SERVICE_STATUS serviceStatus;
  BOOL success;
@@ -961,8 +1097,7 @@
  {
    controls =
    SERVICE_ACCEPT_STOP
    | SERVICE_ACCEPT_SHUTDOWN
    | SERVICE_CONTROL_INTERROGATE;
    | SERVICE_ACCEPT_SHUTDOWN;
  }
  // fill in the status structure
@@ -1196,19 +1331,24 @@
      else
      {
        running = FALSE;
        // Wait on the termination event rather than sleeping: a completed
        // stop signals it through doTerminateService, so the process can
        // exit right away instead of after the next poll plus its
        // confirmation retries - the window in which a following start
        // fails with ERROR_SERVICE_ALREADY_RUNNING.
        if (updatedRunningStatus)
        {
          Sleep(5000);
          returnValue = WaitForSingleObject (_terminationEvent, 5000);
        }
        else
        {
          returnValue = WaitForSingleObject (_terminationEvent,
                                           refreshPeriodSeconds * 1000);
          if (returnValue == WAIT_OBJECT_0)
          {
            debug("The application has exited.");
            break;
          }
        }
        if (returnValue == WAIT_OBJECT_0)
        {
          debug("The application has exited.");
          break;
        }
        code = isServerRunning(&running, FALSE);
        if (code != SERVICE_RETURN_OK)
@@ -1322,31 +1462,25 @@
}  // doTerminateService
// Set to 1 while a stop is in progress so that repeated STOP/SHUTDOWN
// controls do not start a second stop, and the checkpoint counter the
// ongoing stop reports SERVICE_STOP_PENDING progress with.
static volatile LONG _stopInProgress = 0;
static DWORD _stopCheckpoint = CHECKPOINT_FIRST_VALUE;
// ----------------------------------------------------
// Stops the service from within the service handler.  Shared by the
// SERVICE_CONTROL_STOP and SERVICE_CONTROL_SHUTDOWN control codes.
// Performs the actual stop of the service: stops the application and
// reports the final service status.  Runs on the worker thread spawned
// by stopServiceFromHandler for SERVICE_CONTROL_STOP and synchronously
// for SERVICE_CONTROL_SHUTDOWN.
// ----------------------------------------------------
static void stopServiceFromHandler(void)
static void stopService(BOOL duringShutdown)
{
  ServiceReturnCode code;
  DWORD checkpoint;
  // update service status to STOP_PENDING
  debug("serviceHandler: stop");
  _serviceCurStatus = SERVICE_STOP_PENDING;
  checkpoint = CHECKPOINT_FIRST_VALUE;
  updateServiceStatus (
  _serviceCurStatus,
  NO_ERROR,
  0,
  checkpoint++,
  TIMEOUT_STOP_SERVICE,
  _serviceStatusHandle
  );
  // let's try to stop the application whatever may be the status above
  // (best effort mode)
  code = doStopApplication();
  code = doStopApplication(_serviceStatusHandle, &_stopCheckpoint);
  if (code == SERVICE_RETURN_OK)
  {
    WORD argCount = 1;
@@ -1375,13 +1509,94 @@
    WORD argCount = 1;
    const char *logArgs[] = {_instanceDir};
    debug("serviceHandler: The server could not be stopped.");
    // We could not stop the server
    // We could not stop the server.  Leaving the service in
    // SERVICE_STOP_PENDING forever would make the SCM refuse any further
    // stop or delete request, so report a final state: RUNNING for a
    // regular stop; during a system shutdown the process is about to be
    // terminated anyway, so report STOPPED and let serviceMain return.
    _serviceCurStatus = duringShutdown ? SERVICE_STOPPED : SERVICE_RUNNING;
    updateServiceStatus (
    _serviceCurStatus,
    NO_ERROR,
    0,
    CHECKPOINT_NO_ONGOING_OPERATION,
    TIMEOUT_NONE,
    _serviceStatusHandle
    );
    if (duringShutdown)
    {
      doTerminateService (_terminationEvent);
    }
    reportLogEvent(
    EVENTLOG_ERROR_TYPE,
    WIN_EVENT_ID_SERVER_STOP_FAILED,
    argCount, logArgs
    );
  }
  InterlockedExchange(&_stopInProgress, 0);
}  // stopService
// ----------------------------------------------------
// Thread procedure running stopService for SERVICE_CONTROL_STOP.
// ----------------------------------------------------
static DWORD WINAPI stopServiceWorker(LPVOID lpParam)
{
  (void)lpParam;
  stopService(FALSE);
  return 0;
}  // stopServiceWorker
// ----------------------------------------------------
// Stops the service from within the service handler.  Shared by the
// SERVICE_CONTROL_STOP and SERVICE_CONTROL_SHUTDOWN control codes.
// Reports SERVICE_STOP_PENDING and hands the actual stop over to a
// worker thread: the handler must return quickly (the SCM cuts off
// ControlService callers after 30 seconds) while a legitimate stop
// can take longer.  During a system shutdown the stop stays
// synchronous: returning from the handler early would only invite the
// system to terminate the process sooner.
// ----------------------------------------------------
static void stopServiceFromHandler(BOOL duringShutdown)
{
  if (InterlockedCompareExchange(&_stopInProgress, 1, 0) != 0)
  {
    // The ongoing stop keeps reporting progress and will set the final
    // status: nothing to do for this control request.
    debug("serviceHandler: a stop is already in progress.");
    return;
  }
  // update service status to STOP_PENDING
  debug("serviceHandler: stop");
  _serviceCurStatus = SERVICE_STOP_PENDING;
  _stopCheckpoint = CHECKPOINT_FIRST_VALUE;
  updateServiceStatus (
  _serviceCurStatus,
  NO_ERROR,
  0,
  _stopCheckpoint++,
  TIMEOUT_STOP_SERVICE,
  _serviceStatusHandle
  );
  if (duringShutdown)
  {
    stopService(TRUE);
  }
  else
  {
    HANDLE stopThread = CreateThread(NULL, 0, stopServiceWorker, NULL, 0, NULL);
    if (stopThread == NULL)
    {
      debugError("Failed to create the stop thread.  Last error = %d.  Stopping synchronously.",
          GetLastError());
      stopService(FALSE);
    }
    else
    {
      CloseHandle(stopThread);
    }
  }
}  // stopServiceFromHandler
// ----------------------------------------------------
@@ -1399,12 +1614,15 @@
  switch (controlCode)
  {
    case SERVICE_CONTROL_SHUTDOWN:
    // If system is shuting down then stop the service
    // -> no break here
      // The system is shutting down: stop the service synchronously
      debug("serviceHandler: shutdown");
      stopServiceFromHandler(TRUE);
      break;
    case SERVICE_CONTROL_STOP:
      // update service status to STOP_PENDING and stop the application
      stopServiceFromHandler();
      // from a worker thread
      stopServiceFromHandler(FALSE);
      break;
@@ -2032,7 +2250,39 @@
      }
      else
      {
        Sleep (500);
        // Wait until the service actually reaches SERVICE_STOPPED so that
        // DeleteService below performs a clean delete instead of merely
        // marking a still-running service for deletion.  The budget must
        // exceed the stop worker's own (~61 s); a return to SERVICE_RUNNING
        // means the stop failed and waiting further is pointless.
        int nTries = 90;
        while ((nTries > 0) && (serviceStatus.dwCurrentState != SERVICE_STOPPED)
            && (serviceStatus.dwCurrentState != SERVICE_RUNNING))
        {
          nTries--;
          Sleep (1000);
          if (!QueryServiceStatus (myService, &serviceStatus))
          {
            break;
          }
        }
        if (serviceStatus.dwCurrentState == SERVICE_RUNNING)
        {
          // The stop worker reports SERVICE_RUNNING when the stop failed:
          // deleting the service now would merely mark a still-running
          // service for deletion and report success while the server keeps
          // running with no service registration left to retry with.
          debugError(
              "The service '%s' is still running after the stop request: not deleting it.",
              serviceName);
          returnValue = SERVICE_RETURN_ERROR;
        }
        else if (serviceStatus.dwCurrentState != SERVICE_STOPPED)
        {
          debugError(
              "The service '%s' did not reach SERVICE_STOPPED (state=%d): DeleteService will only mark it for deletion.",
              serviceName, serviceStatus.dwCurrentState);
        }
      }
    }
  }
@@ -2396,14 +2646,24 @@
    fprintf(stdout, "The instance dir '%s' is not valid.\n", dir);
    return FALSE;
  }
  // Resolve the instance root before serviceMain's monitor loop and the
  // stop worker can race on the lazy initialization, and so the resolved
  // root appears in the debug log at startup.
  getInstanceRoot();
  return TRUE;
}
// ---------------------------------------------------------------
// Frees the _instanceDir global variable allocated by setInstanceDir.
// Frees the _instanceDir and _instanceRoot global variables allocated
// by setInstanceDir/getInstanceRoot.
// ---------------------------------------------------------------
static void freeInstanceDir()
{
  if ((_instanceRoot != NULL) && (_instanceRoot != _instanceDir))
  {
    free(_instanceRoot);
  }
  _instanceRoot = NULL;
  free(_instanceDir);
  _instanceDir = NULL;
}
opendj-server-legacy/src/build-tools/windows/service.h
@@ -100,6 +100,7 @@
   SERVICE_STATUS_HANDLE *serviceStatusHandle
   );
ServiceReturnCode doStartApplication(SERVICE_STATUS_HANDLE *serviceStatusHandle, DWORD *checkPoint);
ServiceReturnCode doStopApplication(SERVICE_STATUS_HANDLE *serviceStatusHandle, DWORD *checkPoint);
void serviceHandler(DWORD controlCode);
BOOL getServiceStatus(char *serviceName, LPDWORD returnState);
opendj-server-legacy/src/build-tools/windows/winlauncher.c
@@ -122,21 +122,26 @@
  char pidFile[PATH_SIZE];
  FILE *f;
  char buf[BUF_SIZE];
  int read;
  size_t nRead;
  debug("Attempting to get the PID for the server rooted at '%s'.", instanceDir);
  if (getPidFile(instanceDir, pidFile, PATH_SIZE))
  {
    if ((f = fopen(pidFile, "r")) != NULL)
    {
      read = fread(buf, 1, sizeof(buf),f);
      debug("Read '%s' from the PID file '%s'.", buf, pidFile);
    }
    if (f != NULL)
    {
      nRead = fread(buf, 1, sizeof(buf) - 1, f);
      fclose(f);
      returnValue = (int)strtol(buf, (char **)NULL, 10);
      buf[nRead] = '\0';
      if (nRead > 0)
      {
        debug("Read '%s' from the PID file '%s'.", buf, pidFile);
        returnValue = (int)strtol(buf, (char **)NULL, 10);
      }
      else
      {
        debugError("The PID file '%s' is empty.", pidFile);
        returnValue = 0;
      }
    }
    else
    {
@@ -177,9 +182,20 @@
  if (procHandle == NULL)
  {
    debug("The process with pid=%d has already terminated.", pid);
    // process already dead
    processDead = TRUE;
    DWORD lastError = GetLastError();
    if (lastError == ERROR_INVALID_PARAMETER)
    {
      // no process with this pid exists: it has already terminated
      debug("The process with pid=%d has already terminated.", pid);
      processDead = TRUE;
    }
    else
    {
      // Access denied or any other error: the process may well still be
      // running, so it must not be reported as stopped.
      debugError("Failed to open the process (pid=%d) lastError=%d.", pid, lastError);
      processDead = FALSE;
    }
  }
  else
  {
@@ -246,7 +262,7 @@
    // immediately.
    if ((fopen_s(&f, pidFile, "w") == 0) && (f != NULL))
    {
      fprintf(f, "%d", pid);
      fprintf(f, "%d\n", pid);
      fclose (f);
      returnValue = TRUE;
      debug("Successfully put pid=%d in the pid file '%s'.", pid, pidFile);
@@ -427,6 +443,74 @@
// ----------------------------------------------------
// Waits until the exclusive lock that the server holds on
// locks\server.lock has been released, which is the definitive sign
// that the server process is gone (the pid in the pid file may be
// stale and belong to another process, so the outcome of killProcess
// alone is not proof that the server was stopped).
// Only a lock conflict (EACCES) is proof that the server still runs:
// like isServerRunning in service.c, a lock file that cannot be opened
// or an unexpected locking error is not treated as a running server.
// Returns TRUE if the server no longer holds the lock (or holding it
// cannot be proven) and FALSE if the lock conflict persists after the
// bounded retries.
// ----------------------------------------------------
BOOL waitForLockRelease(const char* instanceDir)
{
  char lockFile[PATH_SIZE];
  char* relativePath = "\\locks\\server.lock";
  int nTries = 30;
  if (!isSafePath(instanceDir)
    || (strlen(relativePath) + strlen(instanceDir)) >= PATH_SIZE)
  {
    debugError("Unable to get the lock file name for instanceDir='%s'.", instanceDir);
    return FALSE;
  }
  _snprintf(lockFile, PATH_SIZE, "%s%s", instanceDir, relativePath);
  while (nTries > 0)
  {
    int fd;
    int lockingError;
    if (!fileExists(lockFile))
    {
      debug("Lock file '%s' does not exist, so the server is stopped.", lockFile);
      return TRUE;
    }
    fd = _open(lockFile, _O_RDWR);
    if (fd == -1)
    {
      debug("Could not open the lock file '%s' (errno=%d), so the server is considered stopped.",
        lockFile, errno);
      return TRUE;
    }
    if (_locking(fd, LK_NBLCK, 1) != -1)
    {
      _locking(fd, LK_UNLCK, 1);
      _close(fd);
      debug("Acquired the lock on '%s', so the server is stopped.", lockFile);
      return TRUE;
    }
    lockingError = errno;
    _close(fd);
    if (lockingError != EACCES)
    {
      debugError("Unexpected error locking '%s': %d", lockFile, lockingError);
      return TRUE;
    }
    nTries--;
    debug("The server still holds the lock on '%s'.  Sleeping for 1 second and will try %d more time(s).",
      lockFile, nTries);
    Sleep(1000);
  }
  debugError("The server did not release the lock on '%s'.", lockFile);
  return FALSE;
} // waitForLockRelease
// ----------------------------------------------------
// Function called when we want to stop the server.
// This code is called by the stop-ds.bat batch file to stop the server
// in windows.
@@ -443,13 +527,14 @@
// sets the pid file to be deleted on the exit of the process
// the file is not always deleted.
//
// Returns 0 if the instance could be stopped using the
// pid stored in a file of the server installation and
// -1 otherwise.
// Returns 0 if the server no longer holds the server lock (the process
// found in the pid file, if any, was killed and the lock was released)
// and -1 otherwise.
// ----------------------------------------------------
int stop(const char* instanceDir)
{
  int returnCode = -1;
  BOOL mayHaveStopped = FALSE;
  int childPid;
@@ -459,15 +544,33 @@
  if (childPid != 0)
  {
    if (killProcess(childPid))
    {
      returnCode = 0;
      deletePidFile(instanceDir);
    }
    mayHaveStopped = killProcess(childPid);
  }
  else
  {
    debug("Could not stop the server running at root '%s' because the pid could not be located.", instanceDir);
    // The pid file is typically missing because the server has already
    // stopped (or is stopping right now): the lock probe below gives the
    // definitive answer.
    debug("Could not locate the pid of the server running at root '%s': relying on the server lock alone.", instanceDir);
    mayHaveStopped = TRUE;
  }
  if (mayHaveStopped)
  {
    if (waitForLockRelease(instanceDir))
    {
      returnCode = 0;
      if (childPid != 0)
      {
        deletePidFile(instanceDir);
      }
    }
    else
    {
      char * msg = "The server at '%s' is still running: it did not release the server lock.\n";
      debugError(msg, instanceDir);
      fprintf(stderr, msg, instanceDir);
    }
  }
  return returnCode;
opendj-server-legacy/src/build-tools/windows/winlauncher.h
@@ -12,11 +12,16 @@
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 * Portions Copyright 2026 3A Systems, LLC.
 */
#include "common.h"
#include <errno.h>
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/locking.h>
#include <sys/stat.h>
#include <process.h>
opendj-server-legacy/src/main/java/org/opends/server/backends/cassandra/Storage.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 2023-2024 3A Systems, LLC.
 * Copyright 2023-2026 3A Systems, LLC.
 */
package org.opends.server.backends.cassandra;
@@ -147,11 +147,11 @@
    }
    String getKeyspaceName() {
        return "\""+System.getProperty("keyspace",config.getDBDirectory()).replaceAll("[^a-zA-z0-9_]", "_")+"\"";
        return "\""+System.getProperty("keyspace",config.getDBDirectory()).replaceAll("[^a-zA-Z0-9_]", "_")+"\"";
    }
    
    String getTableName() {
        return getKeyspaceName()+".\""+config.getBackendId().replaceAll("[^a-zA-z0-9_]", "_")+"\"";
        return getKeyspaceName()+".\""+config.getBackendId().replaceAll("[^a-zA-Z0-9_]", "_")+"\"";
    }
    
    @Override
opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.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;
@@ -1291,10 +1292,12 @@
   */
  private static String getAlternativeCipher()
  {
    // Only OAEP variants belong here: RSA with PKCS#1 v1.5 padding is vulnerable to
    // Bleichenbacher-style padding oracle attacks and must not be used to wrap the
    // CryptoManager secret keys.
    final String[] preferredAlternativeCiphers =
    {
        "RSA/ECB/OAEPWITHSHA1ANDMGF1PADDING",
        "RSA/ECB/PKCS1Padding"
        "RSA/ECB/OAEPWITHSHA1ANDMGF1PADDING"
    };
    for (final String cipher : preferredAlternativeCiphers)
    {
opendj-server-legacy/src/snmp/src/org/opends/server/snmp/SNMPMonitor.java
@@ -13,7 +13,7 @@
 *
 * Copyright 2008 Sun Microsystems, Inc.
 * Portions Copyright 2012-2014 ForgeRock AS.
 * Portions Copyright 2024 3A Systems, LLC.
 * Portions Copyright 2024-2026 3A Systems, LLC.
 */
package org.opends.server.snmp;
@@ -426,7 +426,7 @@
   */
  private static long pow(long x, long y)
  {
    int j = 1;
    long j = 1;
    long k = x;
    if (y == 0)
    {