From 9164f1e6812b662cec97576a1c7468f4285bd0b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= Date: Mon, 12 Sep 2022 12:41:09 +0200 Subject: [PATCH 1/3] IP Allow control --- .../godmode/users/configure_user.php | 151 ++++++++++++------ pandora_console/index.php | 25 +++ pandora_console/operation/users/user_edit.php | 53 ++++-- 3 files changed, 171 insertions(+), 58 deletions(-) diff --git a/pandora_console/godmode/users/configure_user.php b/pandora_console/godmode/users/configure_user.php index 3ed36f8737..2609c7f23c 100644 --- a/pandora_console/godmode/users/configure_user.php +++ b/pandora_console/godmode/users/configure_user.php @@ -1,17 +1,32 @@ $tag) { - if (empty($tag)) { + if (empty($tag) === true) { unset($tags[$k]); } } @@ -826,7 +852,7 @@ if (!users_is_admin() && $config['id_user'] != $id && !$new_user) { ); $result = db_get_all_rows_sql($sql); - if ($result == false && $user_info['is_admin'] == false) { + if ((bool) $result === false && (bool) $user_info['is_admin'] === false) { db_pandora_audit( AUDIT_LOG_ACL_VIOLATION, 'Trying to access User Management' @@ -837,12 +863,13 @@ if (!users_is_admin() && $config['id_user'] != $id && !$new_user) { } } -if (defined('METACONSOLE')) { - if ($id) { - echo '
'.__('Update User').'
'; - } else { - echo '
'.__('Create User').'
'; - } +if (is_metaconsole() === true) { + html_print_div( + [ + 'class' => 'user_form_title', + 'content' => ((bool) $id === true) ? __('Update User') : __('Create User'), + ] + ); } if (!$new_user) { @@ -1030,6 +1057,26 @@ $comments .= html_print_textarea( true ); +$allowedIP = '

'; +$allowedIP .= __('Login allowed IP list').' '; +$allowedIP .= ui_print_help_tip(__('Add the source IPs that will allow console access. Each IP must be separated only by comma. * allows all.'), true).' '; +$allowedIP .= html_print_checkbox_switch( + 'allowed_ip_active', + 0, + $user_info['allowed_ip_active'], + true +); +$allowedIP .= '

'; +$allowedIP .= html_print_textarea( + 'allowed_ip_list', + 2, + 65, + $user_info['allowed_ip_list'], + (((bool) $view_mode === true) ? 'readonly="readonly"' : ''), + true +); + + // If we want to create a new user, skins displayed are the skins of the creator's group. If we want to update, skins displayed are the skins of the modified user. $own_info = get_user_info($config['id_user']); if ($own_info['is_admin'] || check_acl($config['id_user'], 0, 'PM')) { @@ -1046,8 +1093,8 @@ if ($new_user) { $id_usr = $id; } -if (!$meta) { - // User only can change skins if has more than one group +if ((bool) $meta === false) { + // User only can change skins if has more than one group. if (count($usr_groups) > 1) { if ($isFunctionSkins !== ENTERPRISE_NOT_HOOK) { $skin = '

'.__('Skin').'

'; @@ -1056,7 +1103,7 @@ if (!$meta) { } } -if ($meta) { +if ((bool) $meta === true) { $array_filters = get_filters_custom_fields_view(0, true); $search_custom_fields_view = '

'.__('Search custom field view').' '.ui_print_help_tip(__('Load by default the selected view in custom field view'), true).'

'; @@ -1413,6 +1460,20 @@ echo '
'.$comments.'
'; + +html_print_div( + [ + 'class' => 'user_edit_third_row white_box', + 'content' => html_print_div( + [ + 'class' => 'edit_user_allowed_ip', + 'content' => $allowedIP, + ], + true + ), + ] +); + if (!empty($ehorus)) { echo '
'.$ehorus.'
'; } diff --git a/pandora_console/index.php b/pandora_console/index.php index ad0e37c505..555da9f05a 100755 --- a/pandora_console/index.php +++ b/pandora_console/index.php @@ -299,6 +299,31 @@ if (isset($config['id_user']) === false) { // Since now, only the $pass variable are needed. unset($_GET['pass'], $_POST['pass'], $_REQUEST['pass']); + // IP allowed check. + $user_info = users_get_user_by_id($nick); + if ((bool) $user_info['allowed_ip_active'] === true) { + $userIP = $_SERVER['REMOTE_ADDR']; + if ((strpos($user_info['allowed_ip_list'], '*') !== false || strpos($user_info['allowed_ip_list'], $userIP) !== false) === false) { + $config['auth_error'] = 'IP not allowed'; + $login_failed = true; + include_once 'general/login_page.php'; + db_pandora_audit( + AUDIT_LOG_USER_REGISTRATION, + sprintf( + 'IP %s not allowed for user %s', + $userIP, + $nick + ), + $userIP + ); + while (ob_get_length() > 0) { + ob_end_flush(); + } + + exit(''); + } + } + // If the auth_code exists, we assume the user has come from // double authorization page. if (isset($_POST['auth_code']) === true) { diff --git a/pandora_console/operation/users/user_edit.php b/pandora_console/operation/users/user_edit.php index c9c875f4f4..a42fe2e8bc 100644 --- a/pandora_console/operation/users/user_edit.php +++ b/pandora_console/operation/users/user_edit.php @@ -14,7 +14,7 @@ * |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______| * * ============================================================================ - * Copyright (c) 2005-2021 Artica Soluciones Tecnologicas + * Copyright (c) 2005-2022 Artica Soluciones Tecnologicas * Please see http://pandorafms.org for full contribution list * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -75,6 +75,9 @@ if (isset($_GET['modified']) && !$view_mode) { $upd_info['email'] = get_parameter_post('email', ''); $upd_info['phone'] = get_parameter_post('phone', ''); $upd_info['comments'] = get_parameter_post('comments', ''); + $upd_info['allowed_ip_active'] = ((int) get_parameter_switch('allowed_ip_active', -1) === 0); + $upd_info['allowed_ip_list'] = io_safe_input(strip_tags(io_safe_output((string) get_parameter('allowed_ip_list')))); + $upd_info['comments'] = get_parameter_post('comments', ''); $upd_info['language'] = get_parameter_post('language', $user_info['language']); $upd_info['timezone'] = get_parameter_post('timezone', ''); $upd_info['id_skin'] = get_parameter('skin', $user_info['id_skin']); @@ -111,14 +114,14 @@ if (isset($_GET['modified']) && !$view_mode) { $section = io_safe_output($upd_info['section']); - if (($section == 'Event list') || ($section == 'Group view') - || ($section == 'Alert detail') || ($section == 'Tactical view') - || ($section == 'Default') + if (($section === 'Event list') || ($section === 'Group view') + || ($section === 'Alert detail') || ($section === 'Tactical view') + || ($section === 'Default') ) { $upd_info['data_section'] = ''; - } else if ($section == 'Dashboard') { + } else if ($section === 'Dashboard') { $upd_info['data_section'] = $dashboard; - } else if ($section == 'Visual console') { + } else if ($section === 'Visual console') { $upd_info['data_section'] = $visual_console; } @@ -168,13 +171,13 @@ if (isset($_GET['modified']) && !$view_mode) { // (no changes in data) SQL function returns 0 (FALSE), but is not an error, // just no change. Previous error message could be confussing to the user. if ($return) { - if (!empty($password_new) && !empty($password_confirm)) { + if (empty($password_new) === false && empty($password_confirm) === false) { $success_msg = __('Password successfully updated'); } // If info is valid then proceed with update. - if ((filter_var($upd_info['email'], FILTER_VALIDATE_EMAIL) || $upd_info['email'] == '') - && (preg_match('/^[0-9- ]+$/D', $upd_info['phone']) || $upd_info['phone'] == '') + if ((filter_var($upd_info['email'], FILTER_VALIDATE_EMAIL) || empty($upd_info['email']) === true) + && (preg_match('/^[0-9- ]+$/D', $upd_info['phone']) || empty($upd_info['phone']) === true) ) { $return_update_user = update_user($id, $upd_info); @@ -183,7 +186,7 @@ if (isset($_GET['modified']) && !$view_mode) { } else if ($return_update_user == true) { $success_msg = __('User info successfully updated'); } else { - if (!empty($password_new) && !empty($password_confirm)) { + if (empty($password_new) === false && empty($password_confirm) === false) { $success_msg = __('Password successfully updated'); } else if ($upd_info['id_skin'] !== $user_info['id_skin']) { $success_msg = __('Skin successfully updated'); @@ -614,6 +617,26 @@ $comments .= html_print_textarea( ); $comments .= html_print_input_hidden('quick_language_change', 1, true); +$allowedIP = '

'; +$allowedIP .= __('Login allowed IP list').' '; +$allowedIP .= ui_print_help_tip(__('Add the source IPs that will allow console access. Each IP must be separated only by comma. * allows all.'), true).' '; +$allowedIP .= html_print_checkbox_switch( + 'allowed_ip_active', + 0, + $user_info['allowed_ip_active'], + true +); +$allowedIP .= '

'; +$allowedIP .= html_print_textarea( + 'allowed_ip_list', + 2, + 65, + $user_info['allowed_ip_list'], + ($view_mode ? 'readonly="readonly"' : ''), + true +); + + foreach ($timezones as $timezone_name => $tz) { if ($timezone_name == 'America/Montreal') { @@ -655,7 +678,7 @@ if (is_metaconsole()) { -if (!is_metaconsole()) { +if (is_metaconsole() === false) { echo '
@@ -664,10 +687,14 @@ if (!is_metaconsole()) { } echo '
-
+
'.$comments.'
-
+ + +
+
'.$allowedIP.'
+
'; if ($config['ehorus_enabled'] && $config['ehorus_user_level_conf']) { From 9cdb8788ff530f3167ec32eabbaa871415ab7ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= Date: Mon, 12 Sep 2022 12:41:33 +0200 Subject: [PATCH 2/3] DB Files for IP Allow control --- pandora_console/extras/mr/57.sql | 3 +++ pandora_console/pandoradb.sql | 2 ++ 2 files changed, 5 insertions(+) diff --git a/pandora_console/extras/mr/57.sql b/pandora_console/extras/mr/57.sql index 93493913a6..e77a356fdb 100644 --- a/pandora_console/extras/mr/57.sql +++ b/pandora_console/extras/mr/57.sql @@ -3,6 +3,9 @@ START TRANSACTION; ALTER TABLE `tplanned_downtime` ADD COLUMN `cron_interval_from` VARCHAR(100) DEFAULT ''; ALTER TABLE `tplanned_downtime` ADD COLUMN `cron_interval_to` VARCHAR(100) DEFAULT ''; +ALTER TABLE `tusuario` ADD COLUMN `allowed_ip_active` TINYINT DEFAULT 0; +ALTER TABLE `tusuario` ADD COLUMN `allowed_ip_list` TEXT; + SET @id_config := (SELECT id_config FROM tconfig WHERE `token` = 'metaconsole_node_id' AND `value` IS NOT NULL ORDER BY id_config DESC LIMIT 1); DELETE FROM tconfig WHERE `token` = 'metaconsole_node_id' AND (id_config < @id_config OR `value` IS NULL); diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index c3b21084a1..e9127154dd 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -1306,6 +1306,8 @@ CREATE TABLE IF NOT EXISTS `tusuario` ( `ehorus_user_level_enabled` TINYINT, `integria_user_level_user` VARCHAR(60), `integria_user_level_pass` VARCHAR(45), + `allowed_ip_active` TINYINT UNSIGNED DEFAULT 0, + `allowed_ip_list` TEXT, CONSTRAINT `fk_filter_id` FOREIGN KEY (`id_filter`) REFERENCES tevent_filter (`id_filter`) ON DELETE SET NULL, UNIQUE KEY `id_user` (`id_user`) ) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; From 51a2da89c936eb58db39c116e609e817fc4135ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= Date: Mon, 12 Sep 2022 18:29:58 +0200 Subject: [PATCH 3/3] Fixed control for IP Ranges --- pandora_console/include/functions_users.php | 49 +++++++++++++++++++++ pandora_console/index.php | 11 ++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/pandora_console/include/functions_users.php b/pandora_console/include/functions_users.php index f4e6e25be8..966fc5446a 100755 --- a/pandora_console/include/functions_users.php +++ b/pandora_console/include/functions_users.php @@ -877,3 +877,52 @@ function users_get_users_group_by_group($id_group) return $users; } + + +/** + * Check if IP is in range. Check wildcard `*`, single IP and IP ranges. + * + * @param array $arrayIP List of IPs. + * @param string $userIP IP for determine if is in the list. + * + * @return boolean True if IP is in range. + */ +function checkIPInRange( + array $arrayIP, + string $userIP='' +) { + $output = false; + + if (empty($userIP) === true) { + $userIP = $_SERVER['REMOTE_ADDR']; + } + + if (empty($arrayIP) === false) { + foreach ($arrayIP as $ip) { + if ($ip === '*') { + // The list has wildcard, this accept all IPs. + $output = true; + break; + } else if ($ip === $userIP) { + $output = true; + break; + } else if (preg_match('/([0-2]?[0-9]{1,2})[.]([0-2]?[0-9]{1,2})[.]([0-2]?[0-9]{0,2})[.](0){1}/', $ip) > 0) { + $rangeArrayIP = explode('.', $ip); + $userArrayIP = explode('.', $userIP); + foreach ($rangeArrayIP as $position => $segmentIP) { + if ($segmentIP === $userArrayIP[$position]) { + $output = true; + } else if ((string) $segmentIP === '0') { + break 2; + } else { + $output = false; + } + } + } else { + $output = false; + } + } + } + + return $output; +} diff --git a/pandora_console/index.php b/pandora_console/index.php index 555da9f05a..df1f7e9ae7 100755 --- a/pandora_console/index.php +++ b/pandora_console/index.php @@ -303,7 +303,16 @@ if (isset($config['id_user']) === false) { $user_info = users_get_user_by_id($nick); if ((bool) $user_info['allowed_ip_active'] === true) { $userIP = $_SERVER['REMOTE_ADDR']; - if ((strpos($user_info['allowed_ip_list'], '*') !== false || strpos($user_info['allowed_ip_list'], $userIP) !== false) === false) { + $allowedIP = false; + $arrayIP = explode(',', $user_info['allowed_ip_list']); + // By default, if the IP definition is no correct, allows all. + if (empty($arrayIP) === true) { + $allowedIP = true; + } else { + $allowedIP = checkIPInRange($arrayIP, $userIP); + } + + if ($allowedIP === false) { $config['auth_error'] = 'IP not allowed'; $login_failed = true; include_once 'general/login_page.php';