calls to functions deprecated in OpenSSL 1.1 replaced with compatible ones
[public/netxms.git] / src / server / core / main.cpp
index 8a8c2c5..9378d9b 100644 (file)
@@ -1,6 +1,6 @@
 /*
 ** NetXMS - Network Management System
-** Copyright (C) 2003-2016 Raden Solutions
+** Copyright (C) 2003-2017 Raden Solutions
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -67,12 +67,16 @@ extern Queue g_dciCacheLoaderQueue;
 void InitClientListeners();
 void InitMobileDeviceListeners();
 void InitCertificates();
+bool LoadServerCertificate(RSA **serverKey);
 void InitUsers();
 void CleanupUsers();
 void LoadPerfDataStorageDrivers();
 void ImportLocalConfiguration();
 void RegisterPredictionEngines();
 void ExecuteStartupScripts();
+void CloseAgentTunnels();
+void StopDataCollection();
+void StopObjectMaintenanceThreads();
 
 void ExecuteScheduledScript(const ScheduledTaskParameters *param);
 void MaintenanceModeEnter(const ScheduledTaskParameters *params);
@@ -102,10 +106,8 @@ THREAD_RESULT THREAD_CALL NodePoller(void *);
 THREAD_RESULT THREAD_CALL PollManager(void *);
 THREAD_RESULT THREAD_CALL EventProcessor(void *);
 THREAD_RESULT THREAD_CALL WatchdogThread(void *);
-THREAD_RESULT THREAD_CALL ClientListener(void *);
-THREAD_RESULT THREAD_CALL ClientListenerIPv6(void *);
-THREAD_RESULT THREAD_CALL MobileDeviceListener(void *);
-THREAD_RESULT THREAD_CALL MobileDeviceListenerIPv6(void *);
+THREAD_RESULT THREAD_CALL ClientListenerThread(void *);
+THREAD_RESULT THREAD_CALL MobileDeviceListenerThread(void *);
 THREAD_RESULT THREAD_CALL ISCListener(void *);
 THREAD_RESULT THREAD_CALL LocalAdminListener(void *);
 THREAD_RESULT THREAD_CALL SNMPTrapReceiver(void *);
@@ -113,6 +115,7 @@ THREAD_RESULT THREAD_CALL BeaconPoller(void *);
 THREAD_RESULT THREAD_CALL JobManagerThread(void *);
 THREAD_RESULT THREAD_CALL UptimeCalculator(void *);
 THREAD_RESULT THREAD_CALL ReportingServerConnector(void *);
+THREAD_RESULT THREAD_CALL TunnelListenerThread(void *arg);
 
 /**
  * Global variables
@@ -156,6 +159,7 @@ DB_DRIVER g_dbDriver = NULL;
 ThreadPool NXCORE_EXPORTABLE *g_mainThreadPool = NULL;
 INT16 g_defaultAgentCacheMode = AGENT_CACHE_OFF;
 InetAddressList g_peerNodeAddrList;
+Condition g_dbPasswordReady(true);
 
 /**
  * Static data
@@ -163,6 +167,7 @@ InetAddressList g_peerNodeAddrList;
 static CONDITION m_condShutdown = INVALID_CONDITION_HANDLE;
 static THREAD m_thPollManager = INVALID_THREAD_HANDLE;
 static THREAD m_thSyncer = INVALID_THREAD_HANDLE;
+static THREAD s_tunnelListenerThread = INVALID_THREAD_HANDLE;
 static int m_nShutdownReason = SHUTDOWN_DEFAULT;
 static StringSet s_components;
 
@@ -374,70 +379,86 @@ static void LoadGlobalConfig()
 /**
  * Initialize cryptografic functions
  */
-static BOOL InitCryptografy()
+static bool InitCryptografy()
 {
 #ifdef _WITH_ENCRYPTION
-       BOOL bResult = FALSE;
+       bool success = false;
 
    if (!InitCryptoLib(ConfigReadULong(_T("AllowedCiphers"), 0x7F)))
                return FALSE;
    nxlog_debug(4, _T("Supported ciphers: %s"), (const TCHAR *)NXCPGetSupportedCiphersAsText());
 
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+   OPENSSL_init_ssl(0, NULL);
+#else
    SSL_library_init();
    SSL_load_error_strings();
+#endif
 
-   TCHAR szKeyFile[MAX_PATH];
-       _tcscpy(szKeyFile, g_netxmsdDataDir);
-       _tcscat(szKeyFile, DFILE_KEYS);
-       g_pServerKey = LoadRSAKeys(szKeyFile);
-       if (g_pServerKey == NULL)
-       {
-          nxlog_debug(1, _T("Generating RSA key pair..."));
-               g_pServerKey = RSA_generate_key(NETXMS_RSA_KEYLEN, 17, NULL, 0);
-               if (g_pServerKey != NULL)
-               {
-                       int fd = _topen(szKeyFile, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, 0600);
-                       if (fd != -1)
-                       {
-                               UINT32 dwLen = i2d_RSAPublicKey(g_pServerKey, NULL);
-                               dwLen += i2d_RSAPrivateKey(g_pServerKey, NULL);
-                               BYTE *pKeyBuffer = (BYTE *)malloc(dwLen);
-
-                               BYTE *pBufPos = pKeyBuffer;
-                               i2d_RSAPublicKey(g_pServerKey, &pBufPos);
-                               i2d_RSAPrivateKey(g_pServerKey, &pBufPos);
-                               _write(fd, &dwLen, sizeof(UINT32));
-                               _write(fd, pKeyBuffer, dwLen);
-
-                          BYTE hash[SHA1_DIGEST_SIZE];
-                               CalculateSHA1Hash(pKeyBuffer, dwLen, hash);
-                               _write(fd, hash, SHA1_DIGEST_SIZE);
-
-                               _close(fd);
-                               free(pKeyBuffer);
-                               bResult = TRUE;
-                       }
+   if (LoadServerCertificate(&g_pServerKey))
+   {
+      nxlog_debug(1, _T("Server certificate loaded"));
+   }
+   if (g_pServerKey != NULL)
+   {
+      nxlog_debug(1, _T("Using server certificate key"));
+      success = true;
+   }
+   else
+   {
+      TCHAR szKeyFile[MAX_PATH];
+      _tcscpy(szKeyFile, g_netxmsdDataDir);
+      _tcscat(szKeyFile, DFILE_KEYS);
+      g_pServerKey = LoadRSAKeys(szKeyFile);
+      if (g_pServerKey == NULL)
+      {
+         nxlog_debug(1, _T("Generating RSA key pair..."));
+         g_pServerKey = RSAGenerateKey(NETXMS_RSA_KEYLEN);
+         if (g_pServerKey != NULL)
+         {
+            int fd = _topen(szKeyFile, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, 0600);
+            if (fd != -1)
+            {
+               UINT32 dwLen = i2d_RSAPublicKey(g_pServerKey, NULL);
+               dwLen += i2d_RSAPrivateKey(g_pServerKey, NULL);
+               BYTE *pKeyBuffer = (BYTE *)malloc(dwLen);
+
+               BYTE *pBufPos = pKeyBuffer;
+               i2d_RSAPublicKey(g_pServerKey, &pBufPos);
+               i2d_RSAPrivateKey(g_pServerKey, &pBufPos);
+               _write(fd, &dwLen, sizeof(UINT32));
+               _write(fd, pKeyBuffer, dwLen);
+
+               BYTE hash[SHA1_DIGEST_SIZE];
+               CalculateSHA1Hash(pKeyBuffer, dwLen, hash);
+               _write(fd, hash, SHA1_DIGEST_SIZE);
+
+               _close(fd);
+               free(pKeyBuffer);
+               success = true;
+            }
+            else
+            {
+               nxlog_debug(0, _T("Failed to open %s for writing"), szKeyFile);
+            }
+         }
          else
          {
-            nxlog_debug(0, _T("Failed to open %s for writing"), szKeyFile);
+            nxlog_debug(0, _T("Failed to generate RSA key"));
          }
-               }
+      }
       else
       {
-         nxlog_debug(0, _T("Failed to generate RSA key"));
+         success = true;
       }
-       }
-       else
-       {
-               bResult = TRUE;
-       }
+   }
 
        int iPolicy = ConfigReadInt(_T("DefaultEncryptionPolicy"), 1);
        if ((iPolicy < 0) || (iPolicy > 3))
                iPolicy = 1;
        SetAgentDEP(iPolicy);
 
-       return bResult;
+       return success;
 #else
        return TRUE;
 #endif
@@ -589,6 +610,19 @@ static void OracleSessionInitCallback(DB_HANDLE hdb)
 }
 
 /**
+ * Get database password
+ */
+static void GetDatabasePassword()
+{
+   if (_tcscmp(g_szDbPassword, _T("?")))
+      return;
+
+   nxlog_write(MSG_WAITING_FOR_DB_PASSWORD, NXLOG_INFO, NULL);
+   g_dbPasswordReady.wait(INFINITE);
+   nxlog_debug(1, _T("Database password received"));
+}
+
+/**
  * Server initialization
  */
 BOOL NXCORE_EXPORTABLE Initialize()
@@ -610,9 +644,9 @@ BOOL NXCORE_EXPORTABLE Initialize()
                    ((g_flags & AF_DAEMON) ? 0 : NXLOG_PRINT_TO_STDOUT),
                    _T("LIBNXSRV.DLL"),
 #ifdef _WIN32
-                                      0, NULL, MSG_DEBUG))
+                                      0, NULL, MSG_DEBUG, MSG_DEBUG_TAG, MSG_OTHER))
 #else
-                                      g_dwNumMessages, g_szMessages, MSG_DEBUG))
+                                      g_dwNumMessages, g_szMessages, MSG_DEBUG, MSG_DEBUG_TAG, MSG_OTHER))
 #endif
    {
                _ftprintf(stderr, _T("FATAL ERROR: Cannot open log file\n"));
@@ -674,6 +708,13 @@ BOOL NXCORE_EXPORTABLE Initialize()
        if (g_dbDriver == NULL)
                return FALSE;
 
+   // Start local administrative interface listener if required
+   if (g_flags & AF_ENABLE_LOCAL_CONSOLE)
+      ThreadCreate(LocalAdminListener, 0, NULL);
+
+       // Wait for database password if needed
+       GetDatabasePassword();
+
        // Connect to database
        DB_HANDLE hdbBootstrap = NULL;
        TCHAR errorText[DBDRV_MAX_ERROR_TEXT];
@@ -692,10 +733,17 @@ BOOL NXCORE_EXPORTABLE Initialize()
        nxlog_debug(1, _T("Successfully connected to database %s@%s"), g_szDbName, g_szDbServer);
 
        // Check database schema version
-       int schemaVersion = DBGetSchemaVersion(hdbBootstrap);
-       if (schemaVersion != DB_FORMAT_VERSION)
+       INT32 schemaVersionMajor, schemaVersionMinor;
+       if (!DBGetSchemaVersion(hdbBootstrap, &schemaVersionMajor, &schemaVersionMinor))
+       {
+          nxlog_write(MSG_UNABLE_TO_GET_DB_SCHEMA_VERSION, NXLOG_ERROR, NULL);
+      DBDisconnect(hdbBootstrap);
+      return FALSE;
+       }
+
+       if ((schemaVersionMajor != DB_SCHEMA_VERSION_MAJOR) || (schemaVersionMinor != DB_SCHEMA_VERSION_MINOR))
        {
-               nxlog_write(MSG_WRONG_DB_VERSION, EVENTLOG_ERROR_TYPE, "dd", schemaVersion, DB_FORMAT_VERSION);
+               nxlog_write(MSG_WRONG_DB_SCHEMA_VERSION, NXLOG_ERROR, "dddd", schemaVersionMajor, schemaVersionMinor, DB_SCHEMA_VERSION_MAJOR, DB_SCHEMA_VERSION_MINOR);
                DBDisconnect(hdbBootstrap);
                return FALSE;
        }
@@ -722,7 +770,10 @@ BOOL NXCORE_EXPORTABLE Initialize()
 
    UINT32 lrt = ConfigReadULong(_T("LongRunningQueryThreshold"), 0);
    if (lrt != 0)
+   {
       DBSetLongRunningThreshold(lrt);
+      nxlog_write_generic(NXLOG_INFO, _T("Long running query threshold set at %d milliseconds"), lrt);
+   }
 
    MetaDataPreLoad();
 
@@ -741,7 +792,7 @@ BOOL NXCORE_EXPORTABLE Initialize()
       _sntprintf(buffer, 256, UINT64X_FMT(_T("016")), g_serverId);
                MetaDataWriteStr(_T("ServerID"), buffer);
        }
-       nxlog_debug(1, _T("Server ID ") UINT64X_FMT(_T("016")), g_serverId);
+       nxlog_write_generic(NXLOG_INFO, _T("Server ID ") UINT64X_FMT(_T("016")), g_serverId);
 
        // Initialize locks
 retry_db_lock:
@@ -879,8 +930,7 @@ retry_db_lock:
 
        // Initialize data collection subsystem
    LoadPerfDataStorageDrivers();
-       if (!InitDataCollector())
-               return FALSE;
+       InitDataCollector();
 
        InitLogAccess();
        FileUploadJob::init();
@@ -921,10 +971,6 @@ retry_db_lock:
        // Start database _T("lazy") write thread
        StartDBWriter();
 
-       // Start local administartive interface listener if required
-       if (ConfigReadInt(_T("EnableAdminInterface"), 1))
-               ThreadCreate(LocalAdminListener, 0, NULL);
-
        // Start beacon host poller
        ThreadCreate(BeaconPoller, 0, NULL);
 
@@ -955,17 +1001,14 @@ retry_db_lock:
       RemoveScheduledTaskByHandlerId(ALARM_SUMMARY_EMAIL_TASK_ID);
 
        // Allow clients to connect
-       ThreadCreate(ClientListener, 0, NULL);
-#ifdef WITH_IPV6
-       ThreadCreate(ClientListenerIPv6, 0, NULL);
-#endif
+       ThreadCreate(ClientListenerThread, 0, NULL);
 
        // Allow mobile devices to connect
        InitMobileDeviceListeners();
-       ThreadCreate(MobileDeviceListener, 0, NULL);
-#ifdef WITH_IPV6
-       ThreadCreate(MobileDeviceListenerIPv6, 0, NULL);
-#endif
+       ThreadCreate(MobileDeviceListenerThread, 0, NULL);
+
+       // Agent tunnels
+   s_tunnelListenerThread = ThreadCreateEx(TunnelListenerThread, 0, NULL);
 
        // Start uptime calculator for SLM
        ThreadCreate(UptimeCalculator, 0, NULL);
@@ -1033,6 +1076,9 @@ void NXCORE_EXPORTABLE Shutdown()
        // Wait for critical threads
        ThreadJoin(m_thPollManager);
        ThreadJoin(m_thSyncer);
+       ThreadJoin(s_tunnelListenerThread);
+
+       CloseAgentTunnels();
 
        // Call shutdown functions for the modules
    // CALL_ALL_MODULES cannot be used here because it checks for shutdown flag
@@ -1042,8 +1088,11 @@ void NXCORE_EXPORTABLE Shutdown()
                        g_pModuleList[i].pfShutdown();
        }
 
+   StopDataCollection();
+   StopObjectMaintenanceThreads();
+
    DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
-       SaveObjects(hdb, INVALID_INDEX);
+       SaveObjects(hdb, INVALID_INDEX, true);
        nxlog_debug(2, _T("All objects saved to database"));
        SaveUsers(hdb, INVALID_INDEX);
        nxlog_debug(2, _T("All users saved to database"));
@@ -1074,8 +1123,6 @@ void NXCORE_EXPORTABLE Shutdown()
    MsgWaitQueue::shutdown();
    WatchdogShutdown();
 
-       delete g_pScriptLibrary;
-
        nxlog_debug(1, _T("Server shutdown complete"));
        nxlog_close();
 
@@ -1104,7 +1151,7 @@ void NXCORE_EXPORTABLE FastShutdown()
        ConditionSet(m_condShutdown);
 
        DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
-       SaveObjects(hdb, INVALID_INDEX);
+       SaveObjects(hdb, INVALID_INDEX, true);
        DbgPrintf(2, _T("All objects saved to database"));
        SaveUsers(hdb, INVALID_INDEX);
        DbgPrintf(2, _T("All users saved to database"));