1<?php 2/* 3 +-------------------------------------------------------------------------+ 4 | Copyright (C) 2004-2021 The Cacti Group | 5 | | 6 | This program is free software; you can redistribute it and/or | 7 | modify it under the terms of the GNU General Public License | 8 | as published by the Free Software Foundation; either version 2 | 9 | of the License, or (at your option) any later version. | 10 | | 11 | This program is distributed in the hope that it will be useful, | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | GNU General Public License for more details. | 15 +-------------------------------------------------------------------------+ 16 | Cacti: The Complete RRDtool-based Graphing Solution | 17 +-------------------------------------------------------------------------+ 18 | This code is designed, written, and maintained by the Cacti Group. See | 19 | about.php and/or the AUTHORS file for specific developer information. | 20 +-------------------------------------------------------------------------+ 21 | http://www.cacti.net/ | 22 +-------------------------------------------------------------------------+ 23*/ 24 25/* 26 !!! IMPORTANT !!! 27 28 The following defaults are not to be altered. Please refer to 29 include/config.php for user configurable settings. 30 31*/ 32 33/* load cacti version from file */ 34$cacti_version_file = dirname(__FILE__) . '/cacti_version'; 35 36if (! file_exists($cacti_version_file)) { 37 die ('ERROR: failed to find cacti version file'); 38} 39 40$cacti_version = file_get_contents($cacti_version_file, false); 41if ($cacti_version === false) { 42 die ('ERROR: failed to load cacti version file'); 43} 44$cacti_version = trim($cacti_version); 45 46/* define cacti version */ 47define('CACTI_VERSION', $cacti_version); 48#define('CACTI_VERSION_BETA', 1); 49 50/* define if cacti is in CLI mode */ 51define('CACTI_CLI', (php_sapi_name() == 'cli')); 52if (defined('CACTI_CLI_ONLY') && !CACTI_CLI) { 53 die('<br><strong>This script is only meant to run at the command line.</strong>'); 54} 55 56// define documentation table of contents 57define('CACTI_DOCUMENTATION_TOC', 'docs/Table-of-Contents.html'); 58 59/* Default database settings*/ 60$database_type = 'mysql'; 61$database_default = 'cacti'; 62$database_hostname = 'localhost'; 63$database_username = 'cactiuser'; 64$database_password = 'cactiuser'; 65$database_port = '3306'; 66$database_retries = 2; 67 68$database_ssl = false; 69$database_ssl_key = ''; 70$database_ssl_cert = ''; 71$database_ssl_ca = ''; 72$database_persist = true; 73 74/* Default session name - Session name must contain alpha characters */ 75$cacti_session_name = 'Cacti'; 76 77/* define default url path */ 78$url_path = '/cacti/'; 79 80/* disable log rotation setting */ 81$disable_log_rotation = false; 82 83$config = array(); 84 85/* Include configuration, or use the defaults */ 86if (file_exists(dirname(__FILE__) . '/config.php')) { 87 if (!is_readable(dirname(__FILE__) . '/config.php')) { 88 die('Configuration file include/config.php is present, but unreadable.' . PHP_EOL); 89 } 90 include(dirname(__FILE__) . '/config.php'); 91} 92 93if (isset($config['cacti_version'])) { 94 die('Invalid include/config.php file detected.' . PHP_EOL); 95 exit; 96} 97 98/* Set the poller_id */ 99if (isset($poller_id)) { 100 $config['poller_id'] = $poller_id; 101} else { 102 $config['poller_id'] = 1; 103} 104 105$db_var_defaults = array( 106 'database_type' => 'mysql', 107 'database_default' => NULL, 108 'database_hostname' => NULL, 109 'database_username' => NULL, 110 'database_password' => NULL, 111 'database_port' => '3306', 112 'database_retries' => 2, 113 'database_ssl' => false, 114 'database_ssl_key' => '', 115 'database_ssl_cert' => '', 116 'database_ssl_ca' => '', 117); 118 119$db_var_prefixes = array(''); 120if ($config['poller_id'] > 1 || isset($rdatabase_hostname)) { 121 $db_var_prefixes[] = 'r'; 122} 123 124$db_missing_vars = ''; 125foreach ($db_var_prefixes as $db_var_prefix) { 126 foreach ($db_var_defaults as $db_var_name => $db_var_default) { 127 $db_var_full = $db_var_prefix . $db_var_name; 128 if (!isset($$db_var_full)) { 129 if ($db_var_default !== NULL) { 130 $$db_var_full = $db_var_default; 131 } else { 132 $db_missing_vars .= (($db_missing_vars == '') ? 'missing ' : ', ') . $db_var_full; 133 } 134 } 135 } 136} 137 138if (!empty($db_missing_vars)) { 139 die("config.php is $db_missing_vars" . PHP_EOL); 140} 141 142if (empty($url_path)) { 143 /* define default url path */ 144 $url_path = '/'; 145} 146 147/* set the local for international users */ 148setlocale(LC_CTYPE, 'en_US.UTF-8'); 149 150/* Files that do not need http header information - Command line scripts */ 151$no_http_header_files = array( 152 'add_device.php', 153 'add_graphs.php', 154 'add_perms.php', 155 'add_tree.php', 156 'boost_rrdupdate.php', 157 'cmd.php', 158 'cmd_realtime.php', 159 'copy_user.php', 160 'host_update_template.php', 161 'poller_automation.php', 162 'poller_boost.php', 163 'poller_commands.php', 164 'poller_dsstats.php', 165 'poller_export.php', 166 'poller_graphs_reapply_names.php', 167 'poller_maintenance.php', 168 'poller_output_empty.php', 169 'poller.php', 170 'poller_realtime.php', 171 'poller_recovery.php', 172 'poller_reindex_hosts.php', 173 'poller_reports.php', 174 'poller_spikekill.php', 175 'query_host_cpu.php', 176 'query_host_partitions.php', 177 'rebuild_poller_cache.php', 178 'repair_database.php', 179 'script_server.php', 180 'snmpagent_mibcachechild.php', 181 'snmpagent_mibcache.php', 182 'snmpagent_persist.php', 183 'sql.php', 184 'ss_host_cpu.php', 185 'ss_host_disk.php', 186 'ss_sql.php', 187 'structure_rra_paths.php', 188); 189 190$colors = array(); 191 192/* this should be auto-detected, set it manually if needed */ 193$config['cacti_server_os'] = (strstr(PHP_OS, 'WIN')) ? 'win32' : 'unix'; 194 195if (!empty($path_csrf_secret)) { 196 $config['path_csrf_secret'] = $path_csrf_secret; 197} 198 199/* built-in snmp support */ 200if (isset($php_snmp_support) && !$php_snmp_support) { 201 $config['php_snmp_support'] = false; 202} else { 203 $config['php_snmp_support'] = class_exists('SNMP'); 204} 205 206/* PHP binary location */ 207if (isset($php_path)) { 208 $config['php_path'] = $php_path; 209} 210 211/* Set various debug fields */ 212$config['DEBUG_READ_CONFIG_OPTION'] = defined('DEBUG_READ_CONFIG_OPTION'); 213$config['DEBUG_READ_CONFIG_OPTION_DB_OPEN'] = defined('DEBUG_READ_CONFIG_OPTION_DB_OPEN'); 214$config['DEBUG_SQL_CMD'] = defined('DEBUG_SQL_CMD'); 215$config['DEBUG_SQL_FLOW'] = defined('DEBUG_SQL_FLOW'); 216 217/* check for an empty database port */ 218if (empty($database_port)) { 219 $database_port = '3306'; 220} 221 222/* set URL path */ 223if (!isset($url_path)) { 224 $url_path = ''; 225} 226$config['url_path'] = $url_path; 227define('URL_PATH', $url_path); 228 229/* used for includes */ 230if ($config['cacti_server_os'] == 'win32') { 231 $config['base_path'] = str_replace("\\", "/", substr(dirname(__FILE__),0,-8)); 232 $config['library_path'] = $config['base_path'] . '/lib'; 233} else { 234 $config['base_path'] = preg_replace("/(.*)[\/]include/", "\\1", dirname(__FILE__)); 235 $config['library_path'] = preg_replace("/(.*[\/])include/", "\\1lib", dirname(__FILE__)); 236} 237$config['include_path'] = dirname(__FILE__); 238$config['rra_path'] = '/var/db/cacti/rra'; 239 240/* for multiple pollers, we need to know this location */ 241if (!isset($scripts_path)) { 242 $config['scripts_path'] = $config['base_path'] . '/scripts'; 243} else { 244 $config['scripts_path'] = $scripts_path; 245} 246 247if (!isset($resource_path)) { 248 $config['resource_path'] = $config['base_path'] . '/resource'; 249} else { 250 $config['resource_path'] = $resource_path; 251} 252 253if (isset($input_whitelist)) { 254 $config['input_whitelist'] = $input_whitelist; 255} 256 257/* include base modules */ 258include_once($config['library_path'] . '/database.php'); 259include_once($config['library_path'] . '/functions.php'); 260include_once($config['include_path'] . '/global_constants.php'); 261include_once($config['library_path'] . '/html.php'); 262include_once($config['library_path'] . '/html_utility.php'); 263include_once($config['library_path'] . '/html_validate.php'); 264 265$filename = get_current_page(); 266 267$config['is_web'] = !defined('CACTI_CLI_ONLY'); 268if ((isset($no_http_headers) && $no_http_headers == true) || in_array($filename, $no_http_header_files, true)) { 269 $config['is_web'] = false; 270} 271 272/* set poller mode */ 273global $local_db_cnn_id, $remote_db_cnn_id; 274 275$config['connection'] = 'online'; 276 277if ($config['poller_id'] > 1 || isset($rdatabase_hostname)) { 278 $local_db_cnn_id = db_connect_real($database_hostname, $database_username, $database_password, $database_default, $database_type, $database_port, $database_retries, $database_ssl, $database_ssl_key, $database_ssl_cert, $database_ssl_ca); 279 280 if (!isset($rdatabase_retries)) $rdatabase_retries = 2; 281 if (!isset($rdatabase_ssl)) $rdatabase_ssl = false; 282 if (!isset($rdatabase_ssl_key)) $rdatabase_ssl_key = false; 283 if (!isset($rdatabase_ssl_cert)) $rdatabase_ssl_cert = false; 284 if (!isset($rdatabase_ssl_ca)) $rdatabase_ssl_ca = false; 285 286 // Check for recovery 287 if (is_object($local_db_cnn_id)) { 288 $boost_records = db_fetch_cell('SELECT COUNT(*) 289 FROM poller_output_boost', '', true, $local_db_cnn_id); 290 291 if ($boost_records > 0) { 292 $config['connection'] = 'recovery'; 293 } 294 } 295 296 /* gather the existing cactidb version */ 297 $config['cacti_db_version'] = db_fetch_cell('SELECT cacti FROM version LIMIT 1', false, $local_db_cnn_id); 298 299 // We are a remote poller also try to connect to the remote database 300 $remote_db_cnn_id = db_connect_real($rdatabase_hostname, $rdatabase_username, $rdatabase_password, $rdatabase_default, $rdatabase_type, $rdatabase_port, $database_retries, $rdatabase_ssl, $rdatabase_ssl_key, $rdatabase_ssl_cert, $rdatabase_ssl_ca); 301 302 if ($config['is_web'] && is_object($remote_db_cnn_id) && 303 $config['connection'] != 'recovery' && 304 $config['cacti_db_version'] != 'new_install') { 305 306 // Connection worked, so now override the default settings so that it will always utilize the remote connection 307 $database_default = $rdatabase_default; 308 $database_hostname = $rdatabase_hostname; 309 $database_username = $rdatabase_username; 310 $database_password = $rdatabase_password; 311 $database_port = $rdatabase_port; 312 $database_ssl = $rdatabase_ssl; 313 $database_ssl_key = $rdatabase_ssl_key; 314 $database_ssl_cert = $rdatabase_ssl_cert; 315 $database_ssl_ca = $rdatabase_ssl_ca; 316 } elseif (is_object($remote_db_cnn_id)) { 317 if ($config['connection'] != 'recovery') { 318 $config['connection'] = 'online'; 319 } 320 } else { 321 $config['connection'] = 'offline'; 322 } 323} else { 324 if (!isset($database_ssl)) $database_ssl = false; 325 if (!isset($database_ssl_key)) $database_ssl_key = false; 326 if (!isset($database_ssl_cert)) $database_ssl_cert = false; 327 if (!isset($database_ssl_ca)) $database_ssl_ca = false; 328 329 if (!db_connect_real($database_hostname, $database_username, $database_password, $database_default, $database_type, $database_port, $database_retries, $database_ssl, $database_ssl_key, $database_ssl_cert, $database_ssl_ca)) { 330 $ps = $config['is_web'] ? '<p>' : ''; 331 $sp = $config['is_web'] ? '</p>' : PHP_EOL; 332 $ul = $config['is_web'] ? '<ul>' : PHP_EOL; 333 $li = $config['is_web'] ? '<li>' : PHP_EOL . ' - '; 334 $lu = $config['is_web'] ? '</ul>' : ''; 335 $il = $config['is_web'] ? '</li>' : ''; 336 print $ps . 'FATAL: Connection to Cacti database failed. Please ensure: ' . $ul; 337 print $li . 'the PHP MySQL module is installed and enabled.' . $il; 338 print $li . 'the database is running.' . $il; 339 print $li . 'the credentials in config.php are valid.' . $il; 340 print $lu . $sp; 341 if (isset($_REQUEST['display_db_errors']) & !empty($config['DATABASE_ERROR'])) { 342 print $ps . 'The following database errors occurred: ' . $ul; 343 foreach ($config['DATABASE_ERROR'] as $e) { 344 print $li . $e['Code'] . ': ' . $e['Error'] . $il; 345 } 346 print $lu . $sp; 347 } 348 exit; 349 } else { 350 /* gather the existing cactidb version */ 351 $config['cacti_db_version'] = db_fetch_cell('SELECT cacti FROM version LIMIT 1'); 352 } 353} 354 355/* check cacti log is available */ 356$log_filename = cacti_log_file(); 357if (!is_resource_writable($log_filename)) { 358 die('System log file is not available for writing, please enable write access' . PHP_EOL . 'Log: ' . $log_filename . PHP_EOL); 359} 360 361if ($config['poller_id'] > 1) { 362 $timezone = db_fetch_cell_prepared('SELECT timezone 363 FROM poller 364 WHERE id = ?', 365 array($config['poller_id'])); 366 367 if ($timezone != '') { 368 db_execute_prepared('SET time_zone = ?', array($timezone)); 369 } 370} 371 372if (isset($cacti_db_session) && $cacti_db_session && db_table_exists('sessions')) { 373 include(dirname(__FILE__) . '/session.php'); 374} else { 375 $cacti_db_session = false; 376} 377 378if (!defined('IN_CACTI_INSTALL')) { 379 set_error_handler('CactiErrorHandler'); 380 register_shutdown_function('CactiShutdownHandler'); 381} 382 383/* verify the cacti database is initialized before moving past here */ 384db_cacti_initialized($config['is_web']); 385 386if ($config['is_web']) { 387 if (read_config_option('force_https') == 'on') { 388 if (!isset($_SERVER['HTTPS']) && isset($_SERVER['HTTP_HOST']) && isset($_SERVER['REQUEST_URI'])) { 389 header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . PHP_EOL . PHP_EOL); 390 exit; 391 } 392 } 393 394 /* set the maximum post size */ 395 ini_set('post_max_size', '8M'); 396 397 /* add additional cookie directives */ 398 ini_set('session.cookie_httponly', true); 399 ini_set('session.cookie_path', $config['url_path']); 400 ini_set('session.use_strict_mode', true); 401 402 $options = array( 403 'cookie_httponly' => true, 404 'cookie_path' => $config['url_path'], 405 'use_strict_mode' => true 406 ); 407 408 if (isset($cacti_cookie_domain) && $cacti_cookie_domain != '') { 409 ini_set('session.cookie_domain', $cacti_cookie_domain); 410 $options['cookie_domain'] = $cacti_cookie_domain; 411 } 412 413 // SameSite php7.3+ behavior 414 if (version_compare(PHP_VERSION, '7.3', '>=')) { 415 ini_set('session.cookie_samesite', 'Strict'); 416 $options['cookie_samesite'] = 'Strict'; 417 } 418 419 if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') { 420 ini_set('session.cookie_secure', true); 421 $options['cookie_secure'] = true; 422 } 423 424 $config['cookie_options'] = $options; 425 $config['cacti_session_name'] = $cacti_session_name; 426 427 /* we don't want these pages cached */ 428 header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); 429 header('X-Frame-Options: SAMEORIGIN'); 430 431 /* increased web hardening */ 432 $script_policy = read_config_option('content_security_policy_script'); 433 if ($script_policy == 'unsafe-eval') { 434 $script_policy = "'$script_policy'"; 435 } else { 436 $script_policy = ''; 437 } 438 $alternates = html_escape(read_config_option('content_security_alternate_sources')); 439 440 header("Content-Security-Policy: default-src *; img-src 'self' $alternates data: blob:; style-src 'self' 'unsafe-inline' $alternates; script-src 'self' $script_policy 'unsafe-inline' $alternates; frame-ancestors 'self'; worker-src 'self' $alternates;"); 441 442 /* prevent IE from silently rejects cookies sent from third party sites. */ 443 header('P3P: CP="CAO PSA OUR"'); 444 header('Cache-Control: no-store, no-cache, must-revalidate'); 445 header('Cache-Control: max-age=31536000'); 446 447 cacti_session_start(); 448 449 /* we never run with magic quotes on */ 450 if (version_compare(PHP_VERSION, '5.4', '<=')) { 451 if (get_magic_quotes_gpc()) { 452 $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST); 453 foreach ($process as $key => $val) { 454 foreach ($val as $k => $v) { 455 unset($process[$key][$k]); 456 if (is_array($v)) { 457 $process[$key][stripslashes($k)] = $v; 458 $process[] = &$process[$key][stripslashes($k)]; 459 } else { 460 $process[$key][stripslashes($k)] = stripslashes($v); 461 } 462 } 463 } 464 unset($process); 465 } 466 } 467 468 /* make sure to start only only Cacti session at a time */ 469 if (!isset($_SESSION['cacti_cwd'])) { 470 $_SESSION['cacti_cwd'] = $config['base_path']; 471 } else { 472 if ($_SESSION['cacti_cwd'] != $config['base_path']) { 473 cacti_session_destroy(); 474 } 475 } 476 477 /* Sanitize the http referer */ 478 if (isset($_SERVER['HTTP_REFERER'])) { 479 $_SERVER['HTTP_REFERER'] = sanitize_uri($_SERVER['HTTP_REFERER']); 480 } 481} 482 483/* emulate 'register_globals' = 'off' if turned on */ 484if ((bool)ini_get('register_globals')) { 485 $not_unset = array('_GET', '_POST', '_COOKIE', '_SERVER', '_SESSION', '_ENV', '_FILES', 'database_type', 'database_default', 'database_hostname', 'database_username', 'database_password', 'config', 'colors'); 486 487 /* Not only will array_merge give a warning if a parameter is not an array, it will 488 * actually fail. So we check if HTTP_SESSION_VARS has been initialised. */ 489 if (!isset($_SESSION)) { 490 $_SESSION = array(); 491 } 492 493 /* Merge all into one extremely huge array; unset this later */ 494 $input = array_merge($_GET, $_POST, $_COOKIE, $_SERVER, $_SESSION, $_ENV, $_FILES); 495 496 unset($input['input']); 497 unset($input['not_unset']); 498 499 foreach ($input as $var => $val) { 500 if (!in_array($var, $not_unset)) { 501 unset($$var); 502 } 503 } 504 505 unset($input); 506} 507 508define('CACTI_DATE_TIME_FORMAT', date_time_format()); 509 510include_once($config['include_path'] . '/global_languages.php'); 511include_once($config['library_path'] . '/auth.php'); 512include_once($config['library_path'] . '/plugins.php'); 513include_once($config['include_path'] . '/plugins.php'); 514include_once($config['include_path'] . '/global_arrays.php'); 515include_once($config['include_path'] . '/global_settings.php'); 516include_once($config['include_path'] . '/global_form.php'); 517include_once($config['library_path'] . '/html_form.php'); 518include_once($config['library_path'] . '/html_filter.php'); 519include_once($config['library_path'] . '/variables.php'); 520include_once($config['library_path'] . '/mib_cache.php'); 521include_once($config['library_path'] . '/poller.php'); 522include_once($config['library_path'] . '/snmpagent.php'); 523include_once($config['library_path'] . '/aggregate.php'); 524include_once($config['library_path'] . '/api_automation.php'); 525include_once($config['include_path'] . '/csrf.php'); 526 527if ($config['is_web']) { 528 if (isset_request_var('newtheme')) { 529 unset($_SESSION['selected_theme']); 530 } 531 532 if (isset_request_var('csrf_timeout')) { 533 raise_message('csrf_ptimeout'); 534 } 535 536 /* check for save actions using GET */ 537 if (isset_request_var('action')) { 538 $action = get_nfilter_request_var('action'); 539 540 $bad_actions = array('save', 'update_data', 'changepassword'); 541 542 foreach($bad_actions as $bad) { 543 if ($action == $bad && !isset($_POST['__csrf_magic'])) { 544 cacti_log('WARNING: Attempt to use GET method for POST operations from IP ' . get_client_addr(), false, 'WEBUI'); 545 exit; 546 } 547 } 548 } 549 550 if (isset($_COOKIE['CactiTimeZone'])) { 551 $gmt_offset = $_COOKIE['CactiTimeZone']; 552 553 cacti_time_zone_set($gmt_offset); 554 } 555} 556 557api_plugin_hook('config_insert'); 558 559/* set config cacti_version for plugins */ 560$config['cacti_version'] = CACTI_VERSION;; 561 562