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

Valery Kharseko
yesterday bc07627ecf743de52900fb82e6779eb625a37627
Fix all cpp/ CodeQL code-scanning alerts in Windows build-tools (#757)
5 files modified
315 ■■■■■ changed files
opendj-server-legacy/src/build-tools/windows/common.c 67 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/build-tools/windows/common.h 10 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/build-tools/windows/service.c 215 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/build-tools/windows/service.h 5 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/build-tools/windows/winlauncher.c 18 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/build-tools/windows/common.c
@@ -13,10 +13,12 @@
 *
 * Copyright 2008-2010 Sun Microsystems, Inc.
 * Portions Copyright 2013 ForgeRock AS.
 * Portions Copyright 2026 3A Systems, LLC.
 */
#include "common.h"
#include "service.h"
#include <direct.h>
#include <errno.h>
#include <fcntl.h>
#include <io.h>
@@ -112,7 +114,7 @@
    debug("createBatchFileChildProcess: the batch file path is too long.");
    return FALSE;
  }
  sprintf(command, "/c %s", batchFile);
  _snprintf(command, COMMAND_SIZE, "/c %s", batchFile);
  debug("createBatchFileChildProcess: Attempting to create child process '%s' background=%d.",
      command,
      background);
@@ -259,7 +261,7 @@
  char * logFile;
  FILE *fp;
    time_t rawtime;
  struct tm * timeinfo;
  struct tm timeinfo;
  char formattedTime[100];
  
  if (noMessageLogged)
@@ -272,8 +274,8 @@
  // Time-stamp
  time(&rawtime);
  timeinfo = localtime(&rawtime);
  strftime(formattedTime, 100, "%Y/%m/%d %H:%M:%S", timeinfo);
  localtime_s(&timeinfo, &rawtime);
  strftime(formattedTime, 100, "%Y/%m/%d %H:%M:%S", &timeinfo);
  
  logFile = getDebugLogFileName();
  deleteIfLargerThan(logFile, MAX_DEBUG_LOG_SIZE);
@@ -310,16 +312,13 @@
  char execName [MAX_PATH];
  char * lastSlash;
  char logpath[MAX_PATH];
  char * temp;
  FILE *file;
  if (logFile != NULL)
  if (logFile != NULL)
  {
    return logFile;
  }
  temp = getenv("TEMP");
  // Get the name of the executable.
  // Get the name of the executable.
  GetModuleFileName (
    NULL,
    execName,
@@ -339,18 +338,36 @@
  strcpy(logpath, execName); 
  strcat(logpath, "\\logs\\"); 
  
  // If the log folder doesn's exist in the instance path
  // If the log folder doesn't exist in the instance path
  // we create the log file in the temp directory.
  if (isExistingDirectory(logpath))
  if (isExistingDirectory(logpath))
  {
    sprintf(path, "%s\\logs\\%s", execName, DEBUG_LOG_NAME);
  } else {
    strcat(temp, "\\logs\\");
    mkdir(temp);
    strcat(temp, DEBUG_LOG_NAME);
    file = fopen(temp,"a+");
    fclose(file);
    sprintf(path, "%s", temp);
    _snprintf(path, MAX_PATH, "%s\\logs\\%s", execName, DEBUG_LOG_NAME);
    path[MAX_PATH - 1] = '\0';
  }
  else
  {
    // Fall back to the OS temp directory.  Use GetTempPath (a trusted OS API
    // that resolves the TMP/TEMP/USERPROFILE locations) rather than
    // getenv("TEMP"), whose buffer must not be extended in place.
    char tempDir[MAX_PATH];
    DWORD tempLen = GetTempPath(MAX_PATH, tempDir);
    if ((tempLen > 0) && (tempLen < MAX_PATH))
    {
      // GetTempPath returns a path that already ends with a backslash.
      char tempLogDir[MAX_PATH];
      _snprintf(tempLogDir, MAX_PATH, "%slogs\\", tempDir);
      tempLogDir[MAX_PATH - 1] = '\0';
      _mkdir(tempLogDir);
      _snprintf(path, MAX_PATH, "%s%s", tempLogDir, DEBUG_LOG_NAME);
      path[MAX_PATH - 1] = '\0';
    }
    else
    {
      // Could not determine a temp directory: fall back to the log file name.
      _snprintf(path, MAX_PATH, "%s", DEBUG_LOG_NAME);
      path[MAX_PATH - 1] = '\0';
    }
  }
  logFile = _strdup(path);
@@ -415,6 +432,14 @@
{
  DWORD str = GetFileAttributes(fileName);
  return (str != INVALID_FILE_ATTRIBUTES &&
  return (str != INVALID_FILE_ATTRIBUTES &&
         (str & FILE_ATTRIBUTE_DIRECTORY));
}
// ---------------------------------------------------------------
// See common.h for the contract of this function.
// ---------------------------------------------------------------
BOOL isSafePath(const char* path)
{
  return (path != NULL) && (strstr(path, "..") == NULL);
}
opendj-server-legacy/src/build-tools/windows/common.h
@@ -12,8 +12,12 @@
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2008-2010 Sun Microsystems, Inc.
 * Portions Copyright 2026 3A Systems, LLC.
 */
#ifndef OPENDJ_WINDOWS_COMMON_H
#define OPENDJ_WINDOWS_COMMON_H
// Just some functions and constants to be used by winlauncher.c
// and service.c
@@ -32,3 +36,9 @@
void updateDebugFlag(char* argv[], int argc);
BOOL waitForProcess(PROCESS_INFORMATION* procInfo, DWORD waitTime,
  DWORD* exitCode);
// Returns TRUE if the given path is non-NULL and does not contain a
// parent-directory reference ("..") that could be used for path traversal.
BOOL isSafePath(const char* path);
#endif // OPENDJ_WINDOWS_COMMON_H
opendj-server-legacy/src/build-tools/windows/service.c
@@ -190,7 +190,7 @@
  // Check whether the Registry Key is already created,
  // If so don't create a new one.
  sprintf (subkey, EVENT_LOG_KEY, serviceName);
  _snprintf (subkey, MAX_REGISTRY_KEY, EVENT_LOG_KEY, serviceName);
  result = RegOpenKeyEx(
  HKEY_LOCAL_MACHINE,
  subkey,
@@ -292,7 +292,7 @@
  // Set the number of categories: 1 (OPENDJ)
  if (success)
  {
    long result = RegSetValueEx(
    result = RegSetValueEx(
    hkey,                    // subkey handle
    "CategoryCount",         // value name
    0,                       // must be zero
@@ -346,7 +346,7 @@
  // Check whether the Registry Key is already created,
  // If so don't create a new one.
  sprintf (subkey, EVENT_LOG_KEY, serviceName);
  _snprintf (subkey, MAX_REGISTRY_KEY, EVENT_LOG_KEY, serviceName);
  result = RegOpenKeyEx(
  HKEY_LOCAL_MACHINE,
  subkey,
@@ -390,7 +390,10 @@
  char subkey [MAX_SERVICE_NAME];
  debug("Registering the Event Log for service '%s'.", serviceName);
  sprintf (subkey, serviceName);
  // _snprintf does not null-terminate on truncation (MSVC), so terminate
  // explicitly: serviceName ultimately derives from argv and is unbounded.
  _snprintf (subkey, MAX_SERVICE_NAME, "%s", serviceName);
  subkey[MAX_SERVICE_NAME - 1] = '\0';
  eventLog = RegisterEventSource(
  NULL,      // local host
@@ -427,11 +430,11 @@
  {
    debug("Determining if the server is running.");
  }
  if (strlen(relativePath)+strlen(_instanceDir)+1 < MAX_PATH)
  if (isSafePath(_instanceDir) && strlen(relativePath)+strlen(_instanceDir)+1 < MAX_PATH)
  {
    int fd;
    sprintf(lockFile, "%s%s", _instanceDir, relativePath);
    _snprintf(lockFile, MAX_PATH, "%s%s", _instanceDir, relativePath);
    if (mustDebug)
    {
      debug(
@@ -517,7 +520,7 @@
  if (strlen(relativePath)+strlen(_instanceDir)+1 < COMMAND_SIZE)
  {
  sprintf(command, "\"%s%s\" --windowsNetStart", _instanceDir, relativePath);
  _snprintf(command, COMMAND_SIZE, "\"%s%s\" --windowsNetStart", _instanceDir, relativePath);
    debug("doStartApplication: Launching batch file: %s", command);
    createOk = createBatchFileChildProcess(command, FALSE, &procInfo);
@@ -709,7 +712,7 @@
  debug("doStopApplication");
  if (strlen(relativePath)+strlen(_instanceDir)+1 < COMMAND_SIZE)
  {
    sprintf(command, "\"%s%s\" --windowsNetStop", _instanceDir, relativePath);
    _snprintf(command, COMMAND_SIZE, "\"%s%s\" --windowsNetStop", _instanceDir, relativePath);
    // launch the command
    if (spawn(command, FALSE) != -1)
@@ -808,7 +811,7 @@
      if ((strlen(fileName) + strlen(" start ") + strlen(_instanceDir) +
          2 * strlen("\"\"")) < COMMAND_SIZE)
      {
        sprintf(serviceBinPath, "\"%s\" start \"%s\"", fileName,
        _snprintf(serviceBinPath, COMMAND_SIZE, "\"%s\" start \"%s\"", fileName,
        _instanceDir);
      }
      else
@@ -873,7 +876,7 @@
              // This function assumes that there are at least
              // MAX_SERVICE_NAME (256) characters reserved in
              // servicename.
              sprintf(serviceName, curService.serviceName);
              _snprintf(serviceName, MAX_SERVICE_NAME, "%s", curService.serviceName);
              returnValue = SERVICE_RETURN_OK;
            }
            else
@@ -1061,11 +1064,11 @@
  ServiceReturnCode code;
  // a checkpoint value indicate the progress of an operation
  DWORD checkPoint = CHECKPOINT_FIRST_VALUE;
  SERVICE_STATUS_HANDLE serviceStatusHandle;
  // static so its address does not escape the stack when stored in the
  // global _serviceStatusHandle; there is only one service per process.
  static SERVICE_STATUS_HANDLE serviceStatusHandle;
  BOOL running;
  // __debugbreak();
  debug("serviceMain");
  code = createServiceBinPath(cmdToRun);
@@ -1133,16 +1136,12 @@
  if (!running && code == SERVICE_RETURN_OK)
  {
    WORD argCount = 1;
    const char *argc[] = {_instanceDir};
    const char *logArgs[] = {_instanceDir};
    code = doStartApplication(_serviceStatusHandle, &checkPoint);
    switch (code)
    if (code != SERVICE_RETURN_OK)
    {
      case SERVICE_RETURN_OK:
      // start is ok: do nothing for the moment.
      break;
      default:
      // start failed
      debugError("serviceMain: doStartApplication() failed");
      code = SERVICE_RETURN_ERROR;
      _serviceCurStatus = SERVICE_STOPPED;
@@ -1156,7 +1155,7 @@
      reportLogEvent(
        EVENTLOG_ERROR_TYPE,
        WIN_EVENT_ID_SERVER_START_FAILED,
        argCount, argc
        argCount, logArgs
      );
    }
  }
@@ -1222,7 +1221,7 @@
      if (!updatedRunningStatus)
      {
        WORD argCount = 1;
            const char *argc[] = {_instanceDir};
            const char *logArgs[] = {_instanceDir};
            updateServiceStatus (
               _serviceCurStatus,
               NO_ERROR,
@@ -1234,7 +1233,7 @@
             reportLogEvent(
               EVENTLOG_SUCCESS,
               WIN_EVENT_ID_SERVER_STARTED,
               argCount, argc
               argCount, logArgs
             );
       updatedRunningStatus = TRUE;
      }
@@ -1269,7 +1268,7 @@
                  (state == SERVICE_STOP_PENDING))))
            {
              WORD argCount = 1;
              const char *argc[] = {_instanceDir};
              const char *logArgs[] = {_instanceDir};
              _serviceCurStatus = SERVICE_STOPPED;
              debug("checking in serviceMain serviceHandler: service stopped with error.");
@@ -1283,7 +1282,7 @@
              reportLogEvent(
                EVENTLOG_ERROR_TYPE,
                WIN_EVENT_ID_SERVER_STOPPED_OUTSIDE_SCM,
                argCount, argc);
                argCount, logArgs);
            }
            break;
          }
@@ -1324,6 +1323,68 @@
}  // doTerminateService
// ----------------------------------------------------
// Stops the service from within the service handler.  Shared by the
// SERVICE_CONTROL_STOP and SERVICE_CONTROL_SHUTDOWN control codes.
// ----------------------------------------------------
static void stopServiceFromHandler(void)
{
  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();
  if (code == SERVICE_RETURN_OK)
  {
    WORD argCount = 1;
    const char *logArgs[] = {_instanceDir};
    _serviceCurStatus = SERVICE_STOPPED;
    updateServiceStatus (
    _serviceCurStatus,
    NO_ERROR,
    0,
    CHECKPOINT_NO_ONGOING_OPERATION,
    TIMEOUT_NONE,
    _serviceStatusHandle
    );
    // again, let's ignore the above status and
    // notify serviceMain that service has stopped
    doTerminateService (_terminationEvent);
    reportLogEvent(
    EVENTLOG_SUCCESS,
    WIN_EVENT_ID_SERVER_STOP,
    argCount, logArgs
    );
  }
  else
  {
    WORD argCount = 1;
    const char *logArgs[] = {_instanceDir};
    debug("serviceHandler: The server could not be stopped.");
    // We could not stop the server
    reportLogEvent(
    EVENTLOG_ERROR_TYPE,
    WIN_EVENT_ID_SERVER_STOP_FAILED,
    argCount, logArgs
    );
  }
}  // stopServiceFromHandler
// ----------------------------------------------------
// This function is the handler of the service. It is processing the
// commands send by the SCM. Commands can be: STOP, PAUSE, CONTINUE,
// SHUTDOWN and INTERROGATE.
@@ -1333,7 +1394,6 @@
void serviceHandler(DWORD controlCode)
{
  ServiceReturnCode code;
  DWORD checkpoint;
  BOOL running;
  debug("serviceHandler called with controlCode=%d.", controlCode);
  switch (controlCode)
@@ -1343,60 +1403,9 @@
    // -> no break here
      debug("serviceHandler: shutdown");
    case SERVICE_CONTROL_STOP:
    {
      // 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();
      if (code == SERVICE_RETURN_OK)
      {
        WORD argCount = 1;
        const char *argc[] = {_instanceDir};
        _serviceCurStatus = SERVICE_STOPPED;
        updateServiceStatus (
        _serviceCurStatus,
        NO_ERROR,
        0,
        CHECKPOINT_NO_ONGOING_OPERATION,
        TIMEOUT_NONE,
        _serviceStatusHandle
        );
        // again, let's ignore the above status and
        // notify serviceMain that service has stopped
        doTerminateService (_terminationEvent);
        reportLogEvent(
        EVENTLOG_SUCCESS,
        WIN_EVENT_ID_SERVER_STOP,
        argCount, argc
        );
      }
      else
      {
        WORD argCount = 1;
        const char *argc[] = {_instanceDir};
    debug("serviceHandler: The server could not be stopped.");
        // We could not stop the server
        reportLogEvent(
        EVENTLOG_ERROR_TYPE,
        WIN_EVENT_ID_SERVER_STOP_FAILED,
        argCount, argc
        );
      }
      // update service status to STOP_PENDING and stop the application
      stopServiceFromHandler();
      break;
    }
    // Request to pause the service
@@ -1526,7 +1535,7 @@
      {
        if (strlen(serviceConfig->lpBinaryPathName) < COMMAND_SIZE)
        {
          sprintf(binPathName, serviceConfig->lpBinaryPathName);
          _snprintf(binPathName, COMMAND_SIZE, "%s", serviceConfig->lpBinaryPathName);
          returnValue = SERVICE_RETURN_OK;
        }
        else
@@ -1543,11 +1552,8 @@
    }
  }
  // free buffers
  if (serviceConfig != NULL)
  {
    free(serviceConfig);
  }
  // free buffers (free(NULL) is a safe no-op, so no guard is needed)
  free(serviceConfig);
  return returnValue;
} // getBinaryPathName
@@ -1618,12 +1624,12 @@
        if (! svcStatusOk)
        {
          DWORD lastError = GetLastError();
          if (lastError != ERROR_MORE_DATA)
          DWORD innerLastError = GetLastError();
          if (innerLastError != ERROR_MORE_DATA)
          {
            returnValue = SERVICE_RETURN_ERROR;
            debug("getServiceList: second try generic error. Code [%d]",
                lastError);
                innerLastError);
          }
          else
          {
@@ -1690,8 +1696,10 @@
  if (scm != NULL)
  {
    CloseServiceHandle (scm);
    // free the result buffer
    if (lpServiceData != NULL)
    // free the result buffer, but only if it was heap-allocated: it still
    // points to the stack-based serviceData when the first EnumServicesStatus
    // call succeeded without needing a larger buffer.
    if (lpServiceData != &serviceData)
    {
      free (lpServiceData);
    }
@@ -1780,12 +1788,15 @@
  {
    if (i == 1)
    {
      sprintf(serviceName, baseName);
      _snprintf(serviceName, MAX_SERVICE_NAME, "%s", baseName);
    }
    else
    {
      sprintf(serviceName, "%s-%d", baseName, i);
      _snprintf(serviceName, MAX_SERVICE_NAME, "%s-%d", baseName, i);
    }
    // _snprintf does not null-terminate on truncation (MSVC), and baseName
    // (== argv[3]) is unbounded, so terminate explicitly.
    serviceName[MAX_SERVICE_NAME - 1] = '\0';
    nameInUseResult = serviceNameInUse(serviceName);
@@ -1930,11 +1941,8 @@
    CloseServiceHandle (scm);
  }
  // free names
  if (serviceName != NULL)
  {
    free (serviceName);
  }
  // free names (free(NULL) is a safe no-op, so no guard is needed)
  free (serviceName);
  debug("createServiceInScm returning %d.", returnValue);
@@ -1970,7 +1978,7 @@
    serviceName,
    SERVICE_ALL_ACCESS | DELETE
    );
    debug("After opening service myService=%d.", myService);
    debug("After opening service myService=%p.", (void*)myService);
    if (myService == NULL)
    {
      debugError("Failed to open the service '%s'. Last error = %d",
@@ -2176,7 +2184,7 @@
    {
      // There is a valid serviceName for the command to run, so
      // OpenDJ is registered as a service.
      fprintf(stdout, serviceName);
      fprintf(stdout, "%s", serviceName);
      returnCode = 0;
      debug("Service '%s' is enabled.", serviceName);
    }
@@ -2375,6 +2383,13 @@
// ---------------------------------------------------------------
// Entry point for the opendj_service executable.  Dispatches to the
// requested subcommand (create, state, remove, start, isrunning or
// cleanup); each operates on the OpenDJ instance directory (or the
// service name, for cleanup) given as the following argument.
// Returns 0 on success and a non-zero value otherwise.
// ---------------------------------------------------------------
int main(int argc, char* argv[])
{
  char* subcommand;
@@ -2388,8 +2403,6 @@
      debug("  argv[%d] = '%s'", i, argv[i]);
  }
  // __debugbreak();
  if (argc <= 1)
  {
    fprintf(stdout,
opendj-server-legacy/src/build-tools/windows/service.h
@@ -16,6 +16,9 @@
 * Portions Copyright 2026 3A Systems, LLC.
 */
#ifndef OPENDJ_WINDOWS_SERVICE_H
#define OPENDJ_WINDOWS_SERVICE_H
#include "common.h"
#include <errno.h>
#include <fcntl.h>
@@ -100,3 +103,5 @@
void serviceHandler(DWORD controlCode);
BOOL getServiceStatus(char *serviceName, LPDWORD returnState);
#endif // OPENDJ_WINDOWS_SERVICE_H
opendj-server-legacy/src/build-tools/windows/winlauncher.c
@@ -12,6 +12,7 @@
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 * Portions Copyright 2026 3A Systems, LLC.
 */
#include "winlauncher.h"
@@ -29,9 +30,14 @@
  debug("Attempting to get the PID file for instanceDir='%s'", instanceDir);
  if ((strlen(relativePath) + strlen(instanceDir)) < maxSize)
  if (!isSafePath(instanceDir))
  {
    sprintf(pidFile, "%s\\logs\\server.pid", instanceDir);
    debugError("Unable to get the PID file name because the instance dir is not a safe path.");
    returnValue = FALSE;
  }
  else if ((strlen(relativePath) + strlen(instanceDir)) < maxSize)
  {
    _snprintf(pidFile, maxSize, "%s\\logs\\server.pid", instanceDir);
    returnValue = TRUE;
    debug("PID file name is '%s'.", pidFile);
  }
@@ -283,7 +289,7 @@
    {
      if (curCmdInd + strlen(" ") < maxSize)
      {
        sprintf (&command[curCmdInd], " ");
        _snprintf (&command[curCmdInd], maxSize - curCmdInd, " ");
        curCmdInd = strlen(command);
      }
      else
@@ -314,7 +320,7 @@
        if (curCmdInd + strlen("\"\"") + strlen(curarg) < maxSize)
        {
          // no begining quote and white space inside => add quotes
          sprintf (&command[curCmdInd], "\"%s\"", curarg);
          _snprintf (&command[curCmdInd], maxSize - curCmdInd, "\"%s\"", curarg);
          curCmdInd = strlen (command);
        }
        else
@@ -327,7 +333,7 @@
        if (curCmdInd + strlen(curarg) < maxSize)
        {
          // no white space or quotes detected, keep the arg as is
          sprintf (&command[curCmdInd], "%s", curarg);
          _snprintf (&command[curCmdInd], maxSize - curCmdInd, "%s", curarg);
          curCmdInd = strlen (command);
        }
        else
@@ -339,7 +345,7 @@
    } else {
      if (curCmdInd + strlen("\"\"") < maxSize)
      {
        sprintf (&command[curCmdInd], "\"\"");
        _snprintf (&command[curCmdInd], maxSize - curCmdInd, "\"\"");
        curCmdInd = strlen (command);
      }
      else