['PluginCveCveTicket', 'addEvents']]; // Add in database synchronization $PLUGIN_HOOKS['plugin_datainjection_populate']['cve'] = ['PluginCveCve' => 'plugin_datainjection_populate_cve']; // Menu entry - Add to "Tools" menu only $PLUGIN_HOOKS['menu_toadd']['cve'] = [ 'tools' => 'PluginCveCveMenu' ]; // Dashboard widgets $PLUGIN_HOOKS['dashboard_cards']['cve'] = 'plugin_cve_dashboard_cards'; // Cron tasks registration CronTask::register('PluginCveCveSource', 'SyncCVESources', 6 * HOUR_TIMESTAMP, ['mode' => CronTask::MODE_EXTERNAL]); CronTask::register('PluginCveCve', 'CleanOldCVEs', 7 * DAY_TIMESTAMP, ['mode' => CronTask::MODE_EXTERNAL]); CronTask::register('PluginCveCveInventory', 'AnalyzeInventory', 12 * HOUR_TIMESTAMP, ['mode' => CronTask::MODE_EXTERNAL]); // Item events (hooks) $PLUGIN_HOOKS['item_add']['cve'] = ['Ticket' => 'plugin_cve_item_add_ticket']; $PLUGIN_HOOKS['item_update']['cve'] = ['Ticket' => 'plugin_cve_item_update_ticket']; $PLUGIN_HOOKS['pre_item_purge']['cve'] = ['Ticket' => 'plugin_cve_pre_item_purge_ticket']; // Software inventory hook $PLUGIN_HOOKS['item_add']['cve']['Software'] = 'plugin_cve_item_add_software'; $PLUGIN_HOOKS['item_add']['cve']['SoftwareVersion'] = 'plugin_cve_item_add_softwareversion'; return true; } /** * Handler for software addition * * @param Software $software Software that was added */ function plugin_cve_item_add_software(Software $software) { // Schedule a vulnerability analysis when new software is added $task = new CronTask(); if ($task->getFromDBbyName('PluginCveCveInventory', 'AnalyzeInventory')) { $task->update([ 'id' => $task->fields['id'], 'state' => CronTask::STATE_WAITING ]); } } /** * Handler for software version addition * * @param SoftwareVersion $version Software version that was added */ function plugin_cve_item_add_softwareversion(SoftwareVersion $version) { // Schedule a vulnerability analysis when new software version is added $task = new CronTask(); if ($task->getFromDBbyName('PluginCveCveInventory', 'AnalyzeInventory')) { $task->update([ 'id' => $task->fields['id'], 'state' => CronTask::STATE_WAITING ]); } } /** * Plugin version information * * @return array Plugin version info */ function plugin_version_cve() { return [ 'name' => __('Vulnérabilité', 'cve'), 'version' => PLUGIN_CVE_VERSION, 'author' => 'Tips-Of-Mine', 'license' => 'GPL v3+', 'homepage' => 'https://github.com/tips-of-mine/GLPI-Plugin-CVE-Prototype', 'requirements' => [ 'glpi' => [ 'min' => PLUGIN_CVE_MIN_GLPI, 'max' => PLUGIN_CVE_MAX_GLPI, 'dev' => false ], 'php' => [ 'min' => '7.4', 'max' => '8.2', 'required' => true ] ] ]; } /** * Plugin initialization check * * @return boolean */ function plugin_cve_check_prerequisites() { // Check GLPI version if (version_compare(GLPI_VERSION, PLUGIN_CVE_MIN_GLPI, 'lt') || version_compare(GLPI_VERSION, PLUGIN_CVE_MAX_GLPI, 'gt')) { echo "This plugin requires GLPI >= " . PLUGIN_CVE_MIN_GLPI . " and GLPI <= " . PLUGIN_CVE_MAX_GLPI; return false; } // Check curl extension if (!extension_loaded('curl')) { echo "This plugin requires the PHP cURL extension"; return false; } return true; } /** * Plugin check config * * @return boolean */ function plugin_cve_check_config() { return true; } /** * Plugin installation process * * @return boolean */ function plugin_cve_install() { global $DB; $migration = new Migration(PLUGIN_CVE_VERSION); // Install core tables PluginCveCve::install($migration); PluginCveCveSource::install($migration); PluginCveCveRule::install($migration); PluginCveCveTicket::install($migration); PluginCveCveInventory::install($migration); PluginCveCveAlert::install($migration); // Create default notification templates // This would be implemented here... $migration->executeMigration(); // Schedule the initial CVE data download as a background task $task = new CronTask(); // Check if the synchronization task is already registered $taskId = $task->find(['itemtype' => 'PluginCveCveSource', 'name' => 'SyncCVESources']); if (count($taskId) == 0) { // Register the task if it doesn't exist $taskId = $task->add([ 'itemtype' => 'PluginCveCveSource', 'name' => 'SyncCVESources', 'frequency' => 6 * HOUR_TIMESTAMP, 'param' => null, 'state' => CronTask::STATE_WAITING, 'mode' => CronTask::MODE_EXTERNAL, 'allowmode' => CronTask::MODE_EXTERNAL, 'hourmin' => 0, 'hourmax' => 24, 'logs_lifetime' => 30, 'date_creation' => $_SESSION['glpi_currenttime'], 'comment' => 'Synchronize CVE data from external sources' ]); } else { $taskData = array_shift($taskId); $taskId = $taskData['id']; } // Register the inventory analysis task $inventoryTaskId = $task->find(['itemtype' => 'PluginCveCveInventory', 'name' => 'AnalyzeInventory']); if (count($inventoryTaskId) == 0) { // Register the task if it doesn't exist $inventoryTaskId = $task->add([ 'itemtype' => 'PluginCveCveInventory', 'name' => 'AnalyzeInventory', 'frequency' => 12 * HOUR_TIMESTAMP, 'param' => null, 'state' => CronTask::STATE_WAITING, 'mode' => CronTask::MODE_EXTERNAL, 'allowmode' => CronTask::MODE_EXTERNAL, 'hourmin' => 0, 'hourmax' => 24, 'logs_lifetime' => 30, 'date_creation' => $_SESSION['glpi_currenttime'], 'comment' => 'Analyze software inventory for vulnerabilities' ]); } else { $taskData = array_shift($inventoryTaskId); $inventoryTaskId = $taskData['id']; } // Force run the task immediately to download initial CVE data if ($taskId > 0) { // Log the action Toolbox::logInFile('cve_plugin', 'Initial CVE data synchronization scheduled'); // Queue the task for immediate execution $task->getFromDB($taskId); $task->update([ 'id' => $taskId, 'state' => CronTask::STATE_WAITING ]); // Start background sync process via AJAX or CLI $syncUrl = Plugin::getWebDir('cve') . '/ajax/sync_now.php'; // Use asynchronous curl request to start the sync process plugin_cve_async_request($syncUrl); } // Schedule initial software inventory analysis if ($inventoryTaskId > 0) { // Log the action Toolbox::logInFile('cve_plugin', 'Initial software vulnerability analysis scheduled'); // Queue the task for immediate execution after CVE data is synchronized $task->getFromDB($inventoryTaskId); $task->update([ 'id' => $inventoryTaskId, 'state' => CronTask::STATE_WAITING ]); } return true; } /** * Make an asynchronous HTTP request * * @param string $url URL to request * @return boolean Success */ function plugin_cve_async_request($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 1); curl_setopt($ch, CURLOPT_NOSIGNAL, 1); // Add security token to the request $params = [ '_glpi_csrf_token' => Session::getNewCSRFToken() ]; curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params)); curl_exec($ch); curl_close($ch); return true; } /** * Plugin uninstallation process * * @return boolean */ function plugin_cve_uninstall() { global $DB; $migration = new Migration(PLUGIN_CVE_VERSION); // Remove cron tasks $crontask = new CronTask(); $crontask->deleteByCriteria(['itemtype' => 'PluginCveCveSource', 'name' => 'SyncCVESources']); $crontask->deleteByCriteria(['itemtype' => 'PluginCveCve', 'name' => 'CleanOldCVEs']); $crontask->deleteByCriteria(['itemtype' => 'PluginCveCveInventory', 'name' => 'AnalyzeInventory']); // Uninstall core tables PluginCveCve::uninstall($migration); PluginCveCveSource::uninstall($migration); PluginCveCveRule::uninstall($migration); PluginCveCveTicket::uninstall($migration); PluginCveCveInventory::uninstall($migration); PluginCveCveAlert::uninstall($migration); // Remove user preferences $query = "DELETE FROM `glpi_configs` WHERE `context` = 'plugin:cve'"; $DB->query($query); $migration->executeMigration(); return true; } /** * Define dropdown relations * * @return array */ function plugin_cve_getDatabaseRelations() { $plugin = new Plugin(); if ($plugin->isActivated('cve')) { return [ "glpi_entities" => [ "glpi_plugin_cve_cves" => "entities_id", "glpi_plugin_cve_alerts" => "entities_id" ], "glpi_tickets" => [ "glpi_plugin_cve_tickets" => "tickets_id", "glpi_plugin_cve_alerts" => "tickets_id" ], "glpi_softwares" => [ "glpi_plugin_cve_alerts" => "softwares_id" ], "glpi_softwareversions" => [ "glpi_plugin_cve_alerts" => "softwareversions_id" ] ]; } return []; } /** * Define database table relations * * @return array */ function plugin_cve_getTablesNames() { $plugin = new Plugin(); $tables = []; if ($plugin->isActivated('cve')) { $tables = [ 'glpi_plugin_cve_cves', 'glpi_plugin_cve_sources', 'glpi_plugin_cve_rules', 'glpi_plugin_cve_tickets', 'glpi_plugin_cve_alerts' ]; } return $tables; } /** * Display a nice message when activated */ function plugin_cve_postinit() { global $PLUGIN_HOOKS; // Add nice message when activated for the first time if (isset($_GET['activate']) && $_GET['activate'] === 'cve') { Html::displayTitle(__('Plugin activated successfully!', 'cve'), __('CVE Management plugin has been activated.', 'cve') . '
' . __('Initial CVE data is being synchronized in the background.', 'cve') . '
' . __('Software inventory will be analyzed for vulnerabilities automatically.', 'cve') . '
' . __('You can now configure the data sources and rules.', 'cve')); } }