0) { $secret = hash('sha512', $token, false); cacti_cookie_session_logout(); db_execute_prepared('DELETE FROM user_auth_cache WHERE user_id = ? AND token = ?', array($user_id, $secret)); } } } /** * set_auth_cookie - sets a users security token * * @param (array) user is the user_auth row for the user * * @return (bool) True if token set worked, otherwise false */ function set_auth_cookie($user) { global $config; if (db_table_exists('user_auth_cache')) { clear_auth_cookie(); $nssecret = md5($_SERVER['REQUEST_TIME'] . mt_rand(10000,10000000)) . md5(get_client_addr()); $secret = hash('sha512', $nssecret, false); db_execute_prepared('REPLACE INTO user_auth_cache (user_id, hostname, last_update, token) VALUES (?, ?, NOW(), ?);', array($user['id'], get_client_addr(), $secret)); cacti_cookie_session_set($user['id'], $user['realm'], $nssecret); } } /** * check_auth_cookie - clears a users security token * * @return (int) The user of the session cookie, otherwise false */ function check_auth_cookie() { if (isset($_COOKIE['cacti_remembers']) && read_config_option('auth_cache_enabled') == 'on' && db_table_exists('user_auth_cache')) { $parts = explode(',', $_COOKIE['cacti_remembers']); if (cacti_sizeof($parts) == 2) { $user_id = $parts[0]; $realm_id = -1; $token = $parts[1]; } else { $user_id = $parts[0]; $realm_id = $parts[1]; $token = $parts[2]; } // Legacy support which leaked usernames if (!is_numeric($user_id)) { $user_id = db_fetch_cell_prepared('SELECT id FROM user_auth WHERE username = ?', array($user_id)); } if ($user_id > 0 && $user_id != get_guest_account()) { if ($realm_id == -1) { $user_info = db_fetch_row_prepared('SELECT id, realm, username FROM user_auth WHERE id = ?', array($user_id)); } else { $user_info = db_fetch_row_prepared('SELECT id, realm, username FROM user_auth WHERE id = ? AND realm = ?', array($user_id, $realm_id)); } if (cacti_sizeof($user_info)) { $secret = hash('sha512', $token, false); $found = db_fetch_cell_prepared('SELECT user_id FROM user_auth_cache WHERE user_id = ? AND token = ?', array($user_info['id'], $secret) ); if (empty($found)) { return false; } else { set_auth_cookie($user_info); cacti_log("LOGIN: User '" . $user_info['username'] . "' Authenticated via Authentication Cookie", false, 'AUTH'); db_execute_prepared('INSERT IGNORE INTO user_log (username, user_id, result, ip, time) VALUES (?, ?, 2, ?, NOW())', array($user_info['username'], $user_info['id'], get_client_addr()) ); return $user_info['id']; } } } } return false; } /** * is_template_account - given a username or user_id test if this is a template account * Template accounts could be accounts used for the administrative email, for both * the guest and template accounts, or a user that is specified by a plugin as a * template account. * * @param (int|string) user_id is either the user_id or a username * * @return (bool) true if template account, false otherwise */ function is_template_account($user_id) { if (!is_numeric($user_id)) { $user_id = db_fetch_cell_prepared('SELECT id FROM user_auth WHERE username = ?', array($user_id)); } if (empty($user_id)) { return false; } if (read_config_option('admin_user') == $user_id) { return true; } elseif (read_config_option('guest_user') == $user_id) { return true; } elseif (read_config_option('user_template') == $user_id) { return true; } else { $domain_template = db_fetch_cell_prepared('SELECT COUNT(*) FROM user_domains WHERE user_id = ?', array($user_id)); if ($domain_template > 0) { return true; } else { $plugin_template = get_template_account($user_id); if ($plugin_template == $user_id) { return true; } } } return false; } /** * get_basic_auth_username - If basic auth is used, return the valid username * * @return (string) the new username, or false if one was not passed */ function get_basic_auth_username() { if (isset($_SERVER['PHP_AUTH_USER'])) { $username = str_replace("\\", "\\\\", $_SERVER['PHP_AUTH_USER']); } elseif (isset($_SERVER['REMOTE_USER'])) { $username = str_replace("\\", "\\\\", $_SERVER['REMOTE_USER']); } elseif (isset($_SERVER['REDIRECT_REMOTE_USER'])) { $username = str_replace("\\", "\\\\", $_SERVER['REDIRECT_REMOTE_USER']); } elseif (isset($_SERVER['HTTP_PHP_AUTH_USER'])) { $username = str_replace("\\", "\\\\", $_SERVER['HTTP_PHP_AUTH_USER']); } elseif (isset($_SERVER['HTTP_REMOTE_USER'])) { $username = str_replace("\\", "\\\\", $_SERVER['HTTP_REMOTE_USER']); } elseif (isset($_SERVER['HTTP_REDIRECT_REMOTE_USER'])) { $username = str_replace("\\", "\\\\", $_SERVER['HTTP_REDIRECT_REMOTE_USER']); } else { $username = false; } if ($username !== false) { if (strpos($username, '@') !== false) { $upart = explode('@', $username); $username = $upart[0]; } /* Handle mapping basic accounts to shortform accounts. * Format of map file is CSV: basic,shortform */ $mapfile = read_config_option('path_basic_mapfile'); if ($mapfile != '' && file_exists($mapfile) && is_readable($mapfile)) { $records = file($mapfile); $found = false; if (cacti_sizeof($records)) { foreach($records as $r) { list($basic, $shortform) = str_getcsv($r); if (trim($basic) == $username) { $username = trim($shortform); $found = true; break; } } } if (!$found) { cacti_log("WARNING: Username $username not found in basic mapfile.", false, 'AUTH'); } } } return $username; } /** * user_copy - copies user account * * @param (string) $template_user - username of the user account that should be used as the template * @param (string) $new_user - new username of the account to be created/overwritten * @param (int) $template_realm - new realm of the account * @param (int) $new_realm - new realm of the account to be created, overwrite not affected, but is used for lookup * @param (bool) $overwrite - Allow overwrite of existing user, preserves username, fullname, password and realm * @param (array) $data_override - Array of user_auth field and values to override on the new user * * @return (int|bool) the new users id, or false on no copy */ function user_copy($template_user, $new_user, $template_realm = 0, $new_realm = 0, $overwrite = false, $data_override = array()) { /* ================= input validation ================= */ input_validate_input_number($template_realm); input_validate_input_number($new_realm); /* ==================================================== */ /* Check get template users array */ $user_auth = db_fetch_row_prepared('SELECT * FROM user_auth WHERE username = ? AND realm = ?', array($template_user, $template_realm)); if (!cacti_sizeof($user_auth)) { return false; } $template_id = $user_auth['id']; /* Create update/insert for new/existing user */ $user_exist = db_fetch_row_prepared('SELECT * FROM user_auth WHERE username = ? AND realm = ?', array($new_user, $new_realm)); if (cacti_sizeof($user_exist)) { if ($overwrite) { /* Overwrite existing user */ $user_auth['id'] = $user_exist['id']; $user_auth['username'] = $user_exist['username']; $user_auth['password'] = $user_exist['password']; $user_auth['realm'] = $user_exist['realm']; $user_auth['full_name'] = $user_exist['full_name']; $user_auth['email_address'] = $user_exist['email_address']; $user_auth['must_change_password'] = $user_exist['must_change_password']; $user_auth['enabled'] = $user_exist['enabled']; } else { /* User already exists, duplicate users are bad */ raise_message(19); return false; } } else { /* new user */ $user_auth['id'] = 0; $user_auth['username'] = $new_user; $user_auth['enabled'] = 'on'; $user_auth['password'] = mt_rand(100000, 10000000); $user_auth['email_address'] = ''; $user_auth['realm'] = $new_realm; } /* Update data_override fields */ if (is_array($data_override)) { foreach ($data_override as $field => $value) { if (isset($user_auth[$field]) && $field != 'id' && $field != 'username') { $user_auth[$field] = $value; } } } /* Save the user */ $new_id = sql_save($user_auth, 'user_auth'); /* Create/Update permissions and settings */ if (cacti_sizeof($user_exist) && $overwrite) { db_execute_prepared('DELETE FROM user_auth_perms WHERE user_id = ?', array($user_exist['id'])); db_execute_prepared('DELETE FROM user_auth_realm WHERE user_id = ?', array($user_exist['id'])); db_execute_prepared('DELETE FROM settings_user WHERE user_id = ?', array($user_exist['id'])); db_execute_prepared('DELETE FROM settings_tree WHERE user_id = ?', array($user_exist['id'])); } $user_auth_perms = db_fetch_assoc_prepared('SELECT * FROM user_auth_perms WHERE user_id = ?', array($template_id)); if (cacti_sizeof($user_auth_perms)) { foreach ($user_auth_perms as $row) { $row['user_id'] = $new_id; sql_save($row, 'user_auth_perms', array('user_id', 'item_id', 'type'), false); } } $user_auth_realm = db_fetch_assoc_prepared('SELECT * FROM user_auth_realm WHERE user_id = ?', array($template_id)); if (cacti_sizeof($user_auth_realm)) { foreach ($user_auth_realm as $row) { $row['user_id'] = $new_id; sql_save($row, 'user_auth_realm', array('realm_id', 'user_id'), false); } } $settings_user = db_fetch_assoc_prepared('SELECT * FROM settings_user WHERE user_id = ?', array($template_id)); if (cacti_sizeof($settings_user)) { foreach ($settings_user as $row) { $row['user_id'] = $new_id; sql_save($row, 'settings_user', array('user_id', 'name'), false); } } $settings_tree = db_fetch_assoc_prepared('SELECT * FROM settings_tree WHERE user_id = ?', array($template_id)); if (cacti_sizeof($settings_tree)) { foreach ($settings_tree as $row) { $row['user_id'] = $new_id; sql_save($row, 'settings_tree', array('user_id', 'graph_tree_item_id'), false); } } /* apply group permissions for the user */ $groups = db_fetch_assoc_prepared('SELECT group_id FROM user_auth_group_members WHERE user_id = ?', array($template_id)); if (cacti_sizeof($groups)) { foreach($groups as $g) { $sql[] = '(' . $new_id . ', ' . $g['group_id'] . ')'; } db_execute('INSERT IGNORE INTO user_auth_group_members (user_id, group_id) VALUES ' . implode(',', $sql)); } api_plugin_hook_function('copy_user', array('template_id' => $template_id, 'new_id' => $new_id)); return $new_id; } /** * user_remove - remove a user account * * @param (int) $user_id - Id os the user account to remove * * @return (void) */ function user_remove($user_id) { /* ================= input validation ================= */ input_validate_input_number($user_id); /* ==================================================== */ /* check for guest or template user */ $username = db_fetch_cell_prepared('SELECT username FROM user_auth WHERE id = ?', array($user_id)); if ($username != get_nfilter_request_var('username')) { if (is_template_account($user_id)) { raise_message(21); return; } if ($user_id === get_guest_account()) { raise_message(21); return; } } db_execute_prepared('DELETE FROM user_auth WHERE id = ?', array($user_id)); db_execute_prepared('DELETE FROM user_auth_realm WHERE user_id = ?', array($user_id)); db_execute_prepared('DELETE FROM user_auth_cache WHERE user_id = ?', array($user_id)); db_execute_prepared('DELETE FROM user_auth_perms WHERE user_id = ?', array($user_id)); db_execute_prepared('DELETE FROM user_auth_row_cache WHERE user_id = ?', array($user_id)); db_execute_prepared('DELETE FROM user_auth_group_members WHERE user_id = ?', array($user_id)); db_execute_prepared('DELETE FROM settings_user WHERE user_id = ?', array($user_id)); db_execute_prepared('DELETE FROM settings_tree WHERE user_id = ?', array($user_id)); db_execute_prepared('DELETE FROM sessions WHERE user_id = ?', array($user_id)); api_plugin_hook_function('user_remove', $user_id); } /** * user_disable - disable a user account * * @param (int) $user_id - Id of the user account to disable * * @return (void) */ function user_disable($user_id) { /* ================= input validation ================= */ input_validate_input_number($user_id); /* ==================================================== */ db_execute_prepared("UPDATE user_auth SET enabled = '' WHERE id = ?", array($user_id)); reset_user_perms($user_id); } /** * user_enable - enable a user account * * @param (int) $user_id - Id of the user account to enable * * @return (void) */ function user_enable($user_id) { /* ================= input validation ================= */ input_validate_input_number($user_id); /* ==================================================== */ db_execute_prepared("UPDATE user_auth SET enabled = 'on' WHERE id = ?", array($user_id)); reset_user_perms($user_id); } /** * get_auth_realms - return a list of system user authentication realms * * @param (bool) $login - If true, we also set the local login realm * * @return (array) Array of login realms */ function get_auth_realms($login = false) { if (read_config_option('auth_method') == 4) { $drealms = db_fetch_assoc('SELECT domain_id, domain_name FROM user_domains WHERE enabled="on" ORDER BY domain_name'); if (cacti_sizeof($drealms)) { if ($login) { $new_realms['0'] = array( 'name' => __('Local'), 'selected' => false ); foreach($drealms as $realm) { $new_realms[1000+$realm['domain_id']] = array( 'name' => $realm['domain_name'], 'selected' => false ); } $default_realm = db_fetch_cell('SELECT domain_id FROM user_domains WHERE defdomain=1 AND enabled="on"'); if (!empty($default_realm)) { $new_realms[1000+$default_realm]['selected'] = true; } else { $new_realms['0']['selected'] = true; } } else { $new_realms['0'] = __('Local'); foreach($drealms as $realm) { $new_realms[1000+$realm['domain_id']] = $realm['domain_name']; } } return $new_realms; } } return array( '0' => __('Local'), '3' => __('LDAP'), '2' => __('Web Basic') ); } /** * is_graph_allowed - determines whether the current user is allowed to view a certain graph * * @param (int) $local_graph_id - the ID of the graph to check permissions for * * @return (bool) whether the current user is allowed the view the specified graph or not */ function is_graph_allowed($local_graph_id, $user_id = 0) { $rows = 0; get_allowed_graphs('', '', '', $rows, $user_id, $local_graph_id); return ($rows > 0); } /** * auth_check_perms - A helper function to checking Tree permissions * * @param (array) A set of tree objects * @param (int) $policy - The policy to check * * @return (bool) true if there is access else false */ function auth_check_perms($objects, $policy) { $objectSize = cacti_sizeof($objects); /* policy == allow AND matches = DENY */ if ($objectSize && $policy == 1) { return false; /* policy == deny AND matches = ALLOW */ } elseif ($objectSize && $policy == 2) { return true; /* policy == allow AND no matches = ALLOW */ } elseif (!$objectSize && $policy == 1) { return true; /* policy == deny AND no matches = DENY */ } elseif (!$objectSize && $policy == 2) { return false; } } /** * auth_augment_roles - A helper function to extend Cacti roles with additional realms * or to add a new role. * * @param (string) $role_name - The role to extend or add * @param (array) $files - The filenames to add to the role * * @return (void) */ function auth_augment_roles($role_name, $files) { global $user_auth_roles, $user_auth_realm_filenames; foreach($files as $file) { if (array_search($file, $user_auth_realm_filenames, true) !== false) { if (array_search($user_auth_realm_filenames[$file], $user_auth_roles[$role_name], true) === false) { $user_auth_roles[$role_name][] = $user_auth_realm_filenames[$file]; } } else { if (isset($_SESSION['sess_auth_names'][$file])) { $realm_id = $_SESSION['sess_auth_names'][$file]; } else { $realm_id = db_fetch_cell_prepared('SELECT id+100 AS realm FROM plugin_realms WHERE file = ? OR file LIKE ? OR file LIKE ? OR file LIKE ?', array( $file, $file . ',%', '%,' . $file . ',%', '%,' . $file ) ); if ($realm_id > 0) { $_SESSION['sess_auth_names'][$file] = $realm_id; } } if (!empty($realm_id)) { if (!isset($user_auth_roles[$role_name])) { $user_auth_roles[$role_name][] = $realm_id; } elseif (array_search($realm_id, $user_auth_roles[$role_name]) === false) { $user_auth_roles[$role_name][] = $realm_id; } } } } } /** * auth_augment_roles_byname - A helper function to extend Cacti roles with additional realms * or to add a new role. * * @param (string) $role_name - The role to extend or add * @param (string) $auth_name - The name that must be mapped * * @return (void) */ function auth_augment_roles_byname($role_name, $auth_name) { global $user_auth_roles, $user_auth_realm_filenames; if (isset($_SESSION['sess_auth_names'][$auth_name])) { $realm_id = $_SESSION['sess_auth_names'][$auth_name]; } else { $realm_id = db_fetch_cell_prepared('SELECT id+100 AS realm FROM plugin_realms WHERE display = ?', array($auth_name)); if ($realm_id > 0) { $_SESSION['sess_auth_names'][$auth_name] = $realm_id; } } if (!empty($realm_id)) { if (!isset($user_auth_roles[$role_name])) { $user_auth_roles[$role_name][] = $realm_id; } elseif (array_search($realm_id, $user_auth_roles[$role_name]) === false) { $user_auth_roles[$role_name][] = $realm_id; } } } /** * is_tree_allowed - determines whether the current user is allowed to view a certain graph tree * * @param (int) $tree_id the ID of the graph tree to check permissions for * @param (int) If checking a user, specify the user_id otherwise for the current user leave blank * * @return (bool) whether the current user is allowed the view the specified graph tree or not */ function is_tree_allowed($tree_id, $user_id = 0) { if ($user_id == -1) { return true; } if (isset($_SESSION['sess_tree_perms'][$tree_id])) { return $_SESSION['sess_tree_perms'][$tree_id]; } if (read_config_option('auth_method') != 0) { if ($user_id == 0) { if (isset($_SESSION['sess_user_id'])) { $user_id = $_SESSION['sess_user_id']; } else { $_SESSION['sess_tree_perms'][$tree_id] = false; return false; } } $policy = db_fetch_cell_prepared('SELECT policy_trees FROM user_auth WHERE id = ?', array($user_id)); $trees = db_fetch_assoc_prepared('SELECT user_id FROM user_auth_perms WHERE user_id = ? AND type = 2 AND item_id = ?', array($user_id, $tree_id)); if (auth_check_perms($trees, $policy)) { $_SESSION['sess_tree_perms'][$tree_id] = true; return true; } /* check for group perms */ $groups = db_fetch_assoc_prepared("SELECT uag.policy_trees FROM user_auth_group AS uag INNER JOIN user_auth_group_members AS uagm ON uag.id = uagm.group_id WHERE uag.enabled = 'on' AND uagm.user_id = ?", array($user_id)); if (!cacti_sizeof($groups)) { $_SESSION['sess_tree_perms'][$tree_id] = false; return false; } foreach ($groups as $g) { if (auth_check_perms($trees, $g['policy_trees'])) { $_SESSION['sess_tree_perms'][$tree_id] = true; return true; } } /* check for group trees */ $gtrees = db_fetch_assoc_prepared("SELECT uagm.user_id FROM user_auth_group AS uag INNER JOIN user_auth_group_members AS uagm ON uag.id = uagm.group_id INNER JOIN user_auth_group_perms as uagp ON uagp.group_id = uag.id WHERE uag.enabled = 'on' AND uagm.user_id = ? AND uagp.item_id = ?", array($user_id, $tree_id)); foreach ($groups as $g) { if (auth_check_perms($gtrees, $g['policy_trees'])) { $_SESSION['sess_tree_perms'][$tree_id] = true; return true; } } $_SESSION['sess_tree_perms'][$tree_id] = false; return false; } else { $_SESSION['sess_tree_perms'][$tree_id] = true; return true; } } /** * is_device_allowed - determines whether the current user is allowed to view a certain device * * @param (int) $device_id - the ID of the device to check permissions for * @param (int) If checking a user, specify the user_id otherwise for the current user leave blank * * @return (bool) whether the current user is allowed the view the specified device or not */ function is_device_allowed($device_id, $user_id = 0) { $total_rows = -2; get_allowed_devices('', '', '', $total_rows, $user_id, $device_id); return ($total_rows > 0); } /** * is_graph_template_allowed - determines whether the current user is allowed to view a certain graph template * * @param (int) $graph_template_id - The ID of the graph template to check permissions for * @param (int) If checking a user, specify the user_id otherwise for the current user leave blank * * @return (bool) whether the current user is allowed the view the specified graph template or not */ function is_graph_template_allowed($graph_template_id, $user = 0) { $total_rows = -2; get_allowed_graph_templates('', '', '', $total_rows, $user, $graph_template_id); return ($total_rows > 0); } /** * is_view_allowed - Returns a true or false as to whether or not a specific view type is allowed * View options include 'show_tree', 'show_list', 'show_preview', 'graph_settings' * * @param (string) $view - the view to check for permissions on * * @return (bool) True if allowed, else false */ function is_view_allowed($view = 'show_tree') { if (read_config_option('auth_method') != 0) { if (!isset($_SESSION['sess_user_id'])) { return false; } if (db_table_exists('user_auth_group')) { $values = array_rekey( db_fetch_assoc_prepared("SELECT DISTINCT $view FROM user_auth_group AS uag INNER JOIN user_auth_group_members AS uagm ON uag.id = uagm.user_id WHERE uag.enabled = 'on' AND uagm.user_id = ?", array($_SESSION['sess_user_id']) ), $view, $view ); if (isset($values[3])) { return false; } elseif (isset($values['on'])) { return true; } elseif (isset($values[2])) { return true; } } $value = db_fetch_cell_prepared("SELECT $view FROM user_auth WHERE id = ?", array($_SESSION['sess_user_id']) ); return ($value == 'on'); } else { return true; } } /** * is_tree_branch_empty - Given a tree id and a branch id, check if it's empty * * @param (int) $tree_id - The Cacti Tree id * @param (int) $parent - The Cacti Tree branch id * * @return (bool) True if empty, else false */ function is_tree_branch_empty($tree_id, $parent = 0) { $graphs = array_rekey( db_fetch_assoc_prepared('SELECT local_graph_id FROM graph_tree_items WHERE graph_tree_id = ? AND local_graph_id > 0 AND parent = ?', array($tree_id, $parent) ), 'local_graph_id', 'local_graph_id' ); $simple_perms = get_simple_graph_perms($_SESSION['sess_user_id']); if (cacti_sizeof($graphs) && ($simple_perms || cacti_sizeof(get_allowed_graphs('gl.id IN(' . implode(',', $graphs) . ')'))) > 0) { return false; } $hosts = array_rekey( db_fetch_assoc_prepared('SELECT host_id FROM graph_tree_items WHERE graph_tree_id = ? AND host_id > 0 AND parent = ?', array($tree_id, $parent) ), 'host_id', 'host_id' ); $sites = array_rekey( db_fetch_assoc_prepared('SELECT site_id FROM graph_tree_items WHERE graph_tree_id = ? AND site_id > 0 AND parent = ?', array($tree_id, $parent) ), 'site_id', 'site_id' ); if (!cacti_sizeof($sites)) { if (cacti_sizeof($hosts) && cacti_sizeof(get_allowed_devices('h.id IN(' . implode(',', $hosts) . ')'), 'description', '', -1) > 0) { return false; } } else { $site_hosts = array(); foreach($sites as $site) { $site_hosts += array_rekey( db_fetch_assoc_prepared('SELECT id FROM host WHERE site_id = ?', array($site) ), 'id', 'id' ); } if (cacti_sizeof($site_hosts) && cacti_sizeof(get_allowed_devices('h.id IN(' . implode(',', $site_hosts) . ')'), 'description', '', -1) > 0) { return false; } } $branches = db_fetch_assoc_prepared('SELECT id, graph_tree_id FROM graph_tree_items WHERE graph_tree_id = ? AND parent = ? AND local_graph_id = 0 AND host_id = 0', array($tree_id, $parent)); if (cacti_sizeof($branches)) { foreach($branches as $b) { if (!is_tree_branch_empty($b['graph_tree_id'], $b['id'])) { return false; } } } return true; } /** * is_realm_allowed - Given a realm and a user, check their permissions if the * admin changed a users settings, setup the case to redirect by clearing * session variables so that when an admin makes a change, the user does not * have to login again to receive them. * * @param (int) $realm The realm to check * @param (int|bool) $check_user The either false or the user id to check * * @return (bool) True if allowed, otherwise false */ function is_realm_allowed($realm, $check_user = false) { global $config; /* list all realms that this user has access to */ if (read_config_option('auth_method') != 0) { /* if we are only checking another users permission, don't check cache */ if ($check_user == false) { /* user is not set, no permissions */ if (!isset($_SESSION['sess_user_id'])) { return false; } /* check to see if the admin invalidated a permission */ if (!is_user_perms_valid($_SESSION['sess_user_id'])) { if (db_table_exists('user_auth_cache')) { $enabled = db_fetch_cell_prepared('SELECT enabled FROM user_auth WHERE id = ?', array($_SESSION['sess_user_id'])); if ($enabled == '' && get_guest_account() !== $_SESSION['sess_user_id']) { db_execute_prepared('DELETE FROM user_auth_cache WHERE user_id = ?', array($_SESSION['sess_user_id'])); kill_session_var('sess_user_id'); kill_session_var('sess_user_realms'); kill_session_var('sess_user_config_array'); kill_session_var('sess_config_array'); kill_session_var('sess_auth_names'); kill_session_var('sess_tree_perms'); kill_session_var('sess_simple_perms'); kill_session_var('sess_simple_template_perms'); print 'cactiLoginSuspend'; exit; } else { kill_session_var('sess_user_realms'); kill_session_var('sess_user_config_array'); kill_session_var('sess_config_array'); kill_session_var('sess_auth_names'); kill_session_var('sess_tree_perms'); kill_session_var('sess_simple_perms'); kill_session_var('sess_simple_template_perms'); } print 'cactiRedirect'; exit; } else { kill_session_var('sess_user_realms'); kill_session_var('sess_user_config_array'); kill_session_var('sess_config_array'); kill_session_var('sess_auth_names'); kill_session_var('sess_tree_perms'); kill_session_var('sess_simple_perms'); kill_session_var('sess_simple_template_perms'); } } /* if the permission is already valid, the session variable will be set */ if (isset($_SESSION['sess_user_realms'][$realm])) { return $_SESSION['sess_user_realms'][$realm]; } $user_id = $_SESSION['sess_user_id']; } else { $user_id = $check_user; } /** * check the permissions from the table, should only happen once per login * of after a permission change by the administrator. */ if (read_config_option('auth_method') != 0) { if (cacti_version_compare($config['cacti_db_version'], '1.0.0', '>=')) { $user_realm = db_fetch_cell_prepared("SELECT realm_id FROM user_auth_realm WHERE user_id = ? AND realm_id = ? UNION SELECT realm_id FROM user_auth_group_realm AS uagr INNER JOIN user_auth_group AS uag ON uag.id = uagr.group_id INNER JOIN user_auth_group_members AS uagm ON uag.id = uagm.group_id WHERE uag.enabled = 'on' AND uagr.realm_id = ? AND uagm.user_id = ?", array($user_id, $realm, $realm, $user_id)); } else { $user_realm = db_fetch_cell_prepared('SELECT realm_id FROM user_auth_realm WHERE user_id = ? AND realm_id = ?', array($user_id, $realm)); } if (!empty($user_realm)) { if ($check_user == false) { $_SESSION['sess_user_realms'][$realm] = true; } else { return true; } } else { if ($check_user == false) { $_SESSION['sess_user_realms'][$realm] = false; } else { return false; } } } else { if ($check_user == false) { $_SESSION['sess_user_realms'][$realm] = true; } else { return true; } } } else { if ($check_user == false) { $_SESSION['sess_user_realms'][$realm] = true; } else { return true; } } return $_SESSION['sess_user_realms'][$realm]; } /** * get_allowed_tree_level - Get the permitted tree branch data available to the user * * @param (int) The tree id to check * @param (int) The branch id, 0 is the root of the tree * @param (bool) Tells the function that the user is editing * @param (int) The user id to check for permissions. if 0 then check the current user * * @return (array) An array of Tree branch items that a re allowed (graphs, devices) */ function get_allowed_tree_level($tree_id, $parent_id, $editing = false, $user_id = 0) { if (!auth_valid_user($user_id)) { return array(); } $items = db_fetch_assoc_prepared('SELECT gti.id, gti.title, gti.host_id, gti.site_id, gti.local_graph_id, gti.host_grouping_type, h.description AS hostname, s.name AS sitename FROM graph_tree_items AS gti INNER JOIN graph_tree AS gt ON gt.id = gti.graph_tree_id LEFT JOIN host AS h ON h.id = gti.host_id LEFT JOIN sites AS s ON s.id = gti.site_id WHERE gti.graph_tree_id = ? AND gti.parent = ? ORDER BY gti.position ASC', array($tree_id, $parent_id)); if (!$editing) { $i = 0; if (cacti_sizeof($items)) { foreach($items as $item) { if ($item['host_id'] > 0) { if (!is_device_allowed($item['host_id'], $user_id)) { unset($items[$i]); } } elseif($item['local_graph_id'] > 0) { if (!is_graph_allowed($item['local_graph_id'], $user_id)) { unset($items[$i]); } } $i++; } } } return $items; } /** * get_allowed_tree_content - A function that gathers items and statistics of those items * that are permitted on the tree specified * * @param (int) The tree id to check * @param (int) The branch id, 0 is the root of the tree * @param (string) The Tree SQL where when searching for specific content * @param (string) The SQL Order clause to use for the sorting of items * @param (int) The limit on items to return. If empty or -1, return all items * @param (int) The number of rows found, to be returned to the caller * @param (int) If checking a user, specify the user_id otherwise for the current user leave blank * * @return (array) An array of Tree branch items that a re allowed (graphs, devices) */ function get_allowed_tree_content($tree_id, $parent = 0, $sql_where = '', $sql_order = '', $sql_limit = '', &$total_rows = 0, $user_id = 0) { if (!auth_valid_user($user_id)) { return array(); } if ($sql_limit != '' && $sql_limit != -1) { $sql_limit = "LIMIT $sql_limit"; } else { $sql_limit = ''; } if (!is_numeric($tree_id)) { return array(); } if (!is_numeric($parent)) { return array(); } if ($sql_order != '') { $sql_order = "ORDER BY $sql_order"; } if ($sql_where != '') { $sql_where = "WHERE gti.local_graph_id=0 AND gti.parent=$parent AND gti.graph_tree_id=$tree_id AND (" . $sql_where . ')'; } else { $sql_where = "WHERE gti.local_graph_id=0 AND gti.parent=$parent AND gti.graph_tree_id=$tree_id"; } $trees = array_rekey( get_allowed_trees(false, false, '', '', '', $total_rows, $user_id), 'id', 'name' ); if ($tree_id > 0) { if (cacti_sizeof($trees)) { $sql_where .= ' AND gt.id IN (' . implode(', ', array_keys($trees)) . ')'; } $hierarchy = db_fetch_assoc("SELECT gti.graph_tree_id AS tree_id, gti.id, gti.title, gti.host_id, gti.site_id, gti.local_graph_id, gti.host_grouping_type, h.description AS hostname, s.name AS sitename FROM graph_tree_items AS gti INNER JOIN graph_tree AS gt ON gt.id = gti.graph_tree_id LEFT JOIN host AS h ON h.id = gti.host_id LEFT JOIN sites AS s ON gti.site_id=s.id $sql_where ORDER BY gti.position"); } elseif (cacti_sizeof($trees)) { $hierarchy = db_fetch_assoc("SELECT gt.id AS tree_id, '0' AS id, gt.name AS title, '0' AS host_id, '0' AS site_id, '0' AS local_graph_id, '1' AS host_grouping_type, '' AS hostname, '' AS sitename FROM graph_tree AS gt WHERE enabled='on' AND gt.id IN (" . implode(', ', array_keys($trees)) . ") ORDER BY gt.sequence"); } if (read_config_option('auth_method') != 0) { $new_hierarchy = array(); if (cacti_sizeof($hierarchy)) { foreach($hierarchy as $h) { if ($h['host_id'] > 0) { if (is_device_allowed($h['host_id'])) { $new_hierarchy[] = $h; } } elseif ($h['id'] == 0) { if (!is_tree_branch_empty($h['tree_id'], $h['id'])) { if (is_tree_allowed($h['tree_id'])) { $new_hierarchy[] = $h; } } } elseif ($h['site_id'] > 0) { $new_hierarchy[] = $h; } elseif (!is_tree_branch_empty($h['tree_id'], $h['id'])) { $new_hierarchy[] = $h; } } } return $new_hierarchy; } else { return $hierarchy; } } /** * get_policies - Searches both the users and the users groups and returns a policy * array to be used for determining object permissions. * * @param (int) If checking a user, specify the user_id otherwise for the current user leave blank * * @return (array) An array of policy objects comprising the users permissions */ function get_policies($user_id) { /* get policies for all user groups */ $policies = db_fetch_assoc_prepared("SELECT uag.id, 'group' AS type, uag.name, uag.policy_graphs, uag.policy_hosts, uag.policy_graph_templates, uag.policy_trees FROM user_auth_group AS uag INNER JOIN user_auth_group_members AS uagm ON uag.id = uagm.group_id WHERE uag.enabled = 'on' AND uagm.user_id = ?", array($user_id)); /* get policies for the user */ $policies[] = db_fetch_row_prepared("SELECT id, 'user' AS type, 'user' AS name, policy_graphs, policy_hosts, policy_graph_templates, policy_trees FROM user_auth WHERE id = ?", array($user_id)); return $policies; } /** * get_allowed_tree_header_graphs - Returns the graphs that are permitted at the branch/leaf id specified * * @param (int) The tree id to check * @param (int) The branch id, 0 is the root of the tree * @param (string) The Tree SQL where when searching for specific content * @param (string) The SQL Order clause to use for the sorting of items * @param (int) The limit on items to return. If empty or -1, return all items * @param (int) The number of rows found, to be returned to the caller * @param (int) If checking a user, specify the user_id otherwise for the current user leave blank * * @return (array) Array of tree header graphs to display */ function get_allowed_tree_header_graphs($tree_id, $leaf_id = 0, $sql_where = '', $sql_order = 'gti.position', $sql_limit = '', &$total_rows = 0, $user_id = 0) { if (!auth_valid_user($user_id)) { return array(); } if (!is_numeric($tree_id)) { return array(); } if (!is_numeric($leaf_id)) { return array(); } if ($sql_limit != '' && $sql_limit != -1) { $sql_limit = "LIMIT $sql_limit"; } else { $sql_limit = ''; } if ($sql_order != '') { $sql_order = "ORDER BY $sql_order"; } if ($sql_where != '') { $sql_where = " AND ($sql_where)"; } $sql_where = "WHERE (gti.graph_tree_id=$tree_id AND gti.parent=$leaf_id)" . $sql_where; if (read_user_setting('hide_disabled') == 'on') { $sql_where .= ($sql_where != '' ? ' AND ':'') . '(h.disabled = "" OR h.disabled IS NULL)'; } if ($user_id == -1) { $auth_method = 0; } else { $auth_method = read_config_option('auth_method'); } if ($auth_method > 0 && $user_id == 0) { if (isset($_SESSION['sess_user_id'])) { $user_id = $_SESSION['sess_user_id']; } else { return array(); } } $graph_auth_method = read_config_option('graph_auth_method'); /* get policies for all groups and user */ $policies = get_policies($user_id); if ($auth_method != 0) { $sql_where = get_policy_where($graph_auth_method, $policies, $sql_where); } $graphs = db_fetch_assoc("SELECT gti.id, gti.title, gtg.local_graph_id, h.description, gt.name AS template_name, gtg.title_cache, gtg.width, gtg.height, gl.snmp_index, gl.snmp_query_id FROM graph_templates_graph AS gtg INNER JOIN graph_local AS gl ON gl.id = gtg.local_graph_id INNER JOIN graph_tree_items AS gti ON gti.local_graph_id = gl.id LEFT JOIN graph_templates AS gt ON gt.id = gl.graph_template_id LEFT JOIN host AS h ON h.id = gl.host_id $sql_where $sql_order $sql_limit"); $sql = "SELECT COUNT(*) FROM graph_templates_graph AS gtg INNER JOIN graph_local AS gl ON gl.id=gtg.local_graph_id INNER JOIN graph_tree_items AS gti ON gti.local_graph_id=gl.id LEFT JOIN graph_templates AS gt ON gt.id=gl.graph_template_id LEFT JOIN host AS h ON h.id=gl.host_id $sql_where"; $total_rows = get_total_row_data($user_id, $sql, array(), 'graph'); return $graphs; } /** * get_allowed_graphs - Returns the graphs that are permitted by the user. Used for table displays * where users will view the graphs that they are permitted to access * * @param (string) The SQL where when searching for specific content * @param (string) The SQL Order clause to use for the sorting of graphs * @param (int) The limit on items to return. If empty or -1, return all items * @param (int) The number of rows found, to be returned to the caller * @param (int) If checking a user, specify the user_id otherwise for the current user leave blank * @param (int) If just searching for if a single graph is permitted, the id of that graph * * @return (array) Array of allowed graphs */ function get_allowed_graphs($sql_where = '', $sql_order = 'gtg.title_cache', $sql_limit = '', &$total_rows = 0, $user_id = 0, $graph_id = 0) { if (!auth_valid_user($user_id)) { return array(); } if ($sql_limit != '') { $sql_limit = "LIMIT $sql_limit"; } else { $sql_limit = ''; } if ($sql_order != '') { $sql_order = "ORDER BY $sql_order"; } if ($graph_id > 0) { $sql_where .= ($sql_where != '' ? ' AND ' : ' ') . " gl.id = $graph_id"; } if (read_user_setting('hide_disabled') == 'on') { $sql_where .= ($sql_where != '' ? ' AND ':'') . '(h.disabled = "" OR h.disabled IS NULL)'; } if ($sql_where != '') { $sql_where = "WHERE ((h.id > 0 AND h.deleted = '') OR h.id IS NULL) AND $sql_where"; } else { $sql_where = "WHERE ((h.id > 0 AND h.deleted = '') OR h.id IS NULL)"; } if ($user_id == -1) { $auth_method = 0; } else { $auth_method = read_config_option('auth_method'); } if ($auth_method > 0 && $user_id == 0) { if (isset($_SESSION['sess_user_id'])) { $user_id = $_SESSION['sess_user_id']; } else { return array(); } } /* see if permissions are simple */ $simple_perms = get_simple_graph_perms($user_id); /* in case we need to review get the graph_auth_method */ $graph_auth_method = read_config_option('graph_auth_method'); /* get policies for all groups and user */ $policies = get_policies($user_id); if (!$simple_perms && $auth_method != 0) { $sql_where = get_policy_where($graph_auth_method, $policies, $sql_where); } $graphs = db_fetch_assoc("SELECT gtg.local_graph_id, h.description, gt.name AS template_name, gtg.title_cache, gtg.width, gtg.height, gl.snmp_index, gl.snmp_query_id, IF(gl.graph_template_id=0, 0, IF(gl.snmp_query_id=0, 2, 1)) AS graph_source FROM graph_templates_graph AS gtg INNER JOIN graph_local AS gl ON gl.id=gtg.local_graph_id LEFT JOIN graph_templates AS gt ON gt.id=gl.graph_template_id LEFT JOIN host AS h ON h.id=gl.host_id $sql_where $sql_order $sql_limit"); $sql = "SELECT COUNT(*) FROM graph_templates_graph AS gtg INNER JOIN graph_local AS gl ON gl.id=gtg.local_graph_id LEFT JOIN graph_templates AS gt ON gt.id=gl.graph_template_id LEFT JOIN host AS h ON h.id=gl.host_id $sql_where"; if ($graph_id == 0) { $total_rows = get_total_row_data($user_id, $sql, array(), 'graph'); } else { $total_rows = db_fetch_cell($sql); } return $graphs; } /** * get_allowed_aggregate_graphs - Returns the aggregate graphs that are permitted by the user. * Used for table displays where users will view the graphs that they are permitted to access * * @param (string) The SQL where when searching for specific content * @param (string) The SQL Order clause to use for the sorting of graphs * @param (int) The limit on items to return. If empty or -1, return all items * @param (int) The number of rows found, to be returned to the caller * @param (int) If checking a user, specify the user_id otherwise for the current user leave blank * @param (int) If just searching for if a single graph is permitted, the id of that graph * * @return (array) Array of allowed graphs */ function get_allowed_aggregate_graphs($sql_where = '', $sql_order = 'gtg.title_cache', $sql_limit = '', &$total_rows = 0, $user_id = 0, $graph_id = 0) { if (!auth_valid_user($user_id)) { return array(); } if ($sql_limit != '' && $sql_limit != -1) { $sql_limit = "LIMIT $sql_limit"; } else { $sql_limit = ''; } if ($sql_order != '') { $sql_order = "ORDER BY $sql_order"; } if ($graph_id > 0) { $sql_where .= ($sql_where != '' ? ' AND ' : ' ') . " gl.id = $graph_id"; } if (read_user_setting('hide_disabled') == 'on') { $sql_where .= ($sql_where != '' ? ' AND ':'') . '(h.disabled = "" OR h.disabled IS NULL)'; } if ($sql_where != '') { $sql_where = "WHERE ((h.id > 0 AND h.deleted = '') OR h.id IS NULL) AND $sql_where"; } else { $sql_where = "WHERE ((h.id > 0 AND h.deleted = '') OR h.id IS NULL)"; } if ($user_id == -1) { $auth_method = 0; } else { $auth_method = read_config_option('auth_method'); } if ($auth_method > 0 && $user_id == 0) { if (isset($_SESSION['sess_user_id'])) { $user_id = $_SESSION['sess_user_id']; } else { return array(); } } /* see if permissions are simple */ $simple_perms = get_simple_graph_perms($user_id); /* in case we need to review get the graph_auth_method */ $graph_auth_method = read_config_option('graph_auth_method'); /* get policies for all groups and user */ $policies = get_policies($user_id); if (!$simple_perms && $auth_method != 0) { $sql_where = get_policy_where($graph_auth_method, $policies, $sql_where); } $graphs = db_fetch_assoc("SELECT gtg.local_graph_id, '' AS description, gt.name AS template_name, gtg.title_cache, gtg.width, gtg.height, gl.snmp_index, gl.snmp_query_id FROM graph_templates_graph AS gtg INNER JOIN ( SELECT ag.local_graph_id AS id, gl.host_id, gl.graph_template_id, gl.snmp_query_id, gl.snmp_query_graph_id, gl.snmp_index FROM aggregate_graphs AS ag INNER JOIN aggregate_graphs_items AS agi ON ag.id=agi.aggregate_graph_id INNER JOIN graph_local AS gl ON gl.id=agi.local_graph_id ) AS gl ON gl.id=gtg.local_graph_id LEFT JOIN graph_templates AS gt ON gt.id=gl.graph_template_id LEFT JOIN host AS h ON h.id=gl.host_id $sql_where GROUP BY gtg.local_graph_id $sql_order $sql_limit"); $sql = "SELECT COUNT(DISTINCT gl.id) FROM graph_templates_graph AS gtg INNER JOIN ( SELECT ag.local_graph_id AS id, gl.host_id, gl.graph_template_id, gl.snmp_query_id, gl.snmp_query_graph_id, gl.snmp_index FROM aggregate_graphs AS ag INNER JOIN aggregate_graphs_items AS agi ON ag.id=agi.aggregate_graph_id INNER JOIN graph_local AS gl ON gl.id=agi.local_graph_id ) AS gl ON gl.id=gtg.local_graph_id LEFT JOIN graph_templates AS gt ON gt.id=gl.graph_template_id LEFT JOIN host AS h ON h.id=gl.host_id $sql_where"; $total_rows = get_total_row_data($user_id, $sql, array(), 'aggregate_graph'); return $graphs; } /** * get_simple_device_perms - Returns a boolean true or false if the user has full access to * all devices in the system. This function is used to shortcut complex queries that may * take multiple seconds to return an answer. * * @param (int) The user id to check for permissions for * * @return (bool) True if simple permissions are in place, otherwise false */ function get_simple_device_perms($user) { $policy_hosts = db_fetch_cell_prepared('SELECT policy_hosts FROM user_auth WHERE id = ?', array($user)); $perm_count = db_fetch_cell_prepared('SELECT COUNT(*) FROM user_auth_perms WHERE user_id = ? AND type = 2', array($user)); if ($policy_hosts == 1 && $perm_count == 0) { return true; } else { $policies = db_fetch_assoc_prepared('SELECT policy_hosts, COUNT(*) AS exceptions FROM user_auth_group AS uag INNER JOIN user_auth_group_perms AS uagp ON uag.id = uagp.group_id INNER JOIN user_auth_group_members AS uagm ON uagm.group_id = uag.id WHERE uagp.type = 2 AND uagm.user_id = ? GROUP BY uag.id', array($user)); if (cacti_sizeof($policies)) { foreach($policies as $p) { if ($p['policy_hosts'] == 1 && $p['exceptions'] == 0) { return true; } } } return false; } } /** * get_simple_graph_perms - Returns a boolean true or false if the user has full access to * all graphs in the system. This function is used to shortcut complex queries that may * take multiple seconds to return an answer. * * @param (int) The user id to check for permissions for * * @return (bool) True if simple permissions are in place, otherwise false */ function get_simple_graph_perms($user_id) { if (isset($_SESSION['sess_simple_perms'])) { return $_SESSION['sess_simple_perms']; } $policy_graphs = db_fetch_cell_prepared('SELECT policy_graphs FROM user_auth WHERE id = ?', array($user_id)); $perm_count = db_fetch_cell_prepared('SELECT COUNT(*) FROM user_auth_perms WHERE user_id = ? AND type = 1', array($user_id)); if ($policy_graphs == 1 && $perm_count == 0) { $_SESSION['sess_simple_perms'] = true; return true; } else { $policies = db_fetch_assoc_prepared('SELECT policy_graphs, COUNT(*) AS exceptions FROM user_auth_group AS uag INNER JOIN user_auth_group_perms AS uagp ON uag.id = uagp.group_id INNER JOIN user_auth_group_members AS uagm ON uagm.group_id = uag.id WHERE uagp.type = 1 AND uagm.user_id = ? GROUP BY uag.id', array($user_id)); if (cacti_sizeof($policies)) { foreach($policies as $p) { if ($p['policy_graphs'] == 1 && $p['exceptions'] == 0) { $_SESSION['sess_simple_perms'] = true; return true; } } } $_SESSION['sess_simple_perms'] = false; return false; } } /** * get_simple_graph_template_perms - Returns a boolean true or false if the user has full access to * all graphs templates in the system. This function is used to shortcut complex queries that may * take multiple seconds to return an answer. * * @param (int) The user id to check for permissions for * * @return (bool) True if simple permissions are in place, otherwise false */ function get_simple_graph_template_perms($user_id) { if (isset($_SESSION['sess_simple_template_perms'])) { return $_SESSION['sess_simple_template_perms']; } $policy_graph_templates = db_fetch_cell_prepared('SELECT policy_graph_templates FROM user_auth WHERE id = ?', array($user_id)); $perm_count = db_fetch_cell_prepared('SELECT COUNT(*) FROM user_auth_perms WHERE user_id = ? AND type = 4', array($user_id)); if ($policy_graph_templates == 1 && $perm_count == 0) { $_SESSION['sess_simple_template_perms'] = true; return true; } else { $policies = db_fetch_assoc_prepared('SELECT policy_graph_templates, COUNT(*) AS exceptions FROM user_auth_group AS uag INNER JOIN user_auth_group_perms AS uagp ON uag.id = uagp.group_id INNER JOIN user_auth_group_members AS uagm ON uagm.group_id = uag.id WHERE uagp.type = 4 AND uagm.user_id = ? GROUP BY uag.id', array($user_id)); if (cacti_sizeof($policies)) { foreach($policies as $p) { if ($p['policy_graph_templates'] == 1 && $p['exceptions'] == 0) { $_SESSION['sess_simple_template_perms'] = true; return true; } } } $_SESSION['sess_simple_template_perms'] = false; return false; } } /** * get_allowed_graph_templates - returns the list of Graph Templates that the user is allowed * To access. This function is generally intended for both listbox and table displays. * * @param (string) The SQL where when searching for specific content * @param (string) The SQL Order clause to use for the sorting of graphs * @param (int) The limit on items to return. If empty or -1, return all items * @param (int) The number of rows found, to be returned to the caller * @param (int) If checking a user, specify the user_id otherwise for the current user leave blank * @param (int) If just searching for if a single graph template is permitted, the id of that graph template * * @return (array) An array of permitted Graph Templates */ function get_allowed_graph_templates($sql_where = '', $sql_order = 'gt.name', $sql_limit = '', &$total_rows = 0, $user_id = 0, $graph_template_id = 0) { if (!auth_valid_user($user_id)) { return array(); } if ($user_id == 0) { if (isset($_SESSION['sess_user_id'])) { $user_id = $_SESSION['sess_user_id']; } else { return array(); } } // For timing $start = microtime(true); $init_rows = $total_rows; $templates = array(); if ($sql_limit != '' && $sql_limit != -1) { $sql_limit = "LIMIT $sql_limit"; } else { $sql_limit = ''; } if ($sql_order != '') { $sql_order = "ORDER BY $sql_order"; } if ($graph_template_id > 0) { $sql_where .= ($sql_where != '' ? ' AND ' : ' ') . "(gl.graph_template_id = $graph_template_id)"; } $sql_where = 'WHERE ' . ($sql_where != '' ? $sql_where . ' AND ':' ') . '(gt.id IS NOT NULL) '; if ($user_id == -1) { $auth_method = 0; } else { $auth_method = read_config_option('auth_method'); } if ($auth_method > 0 && $user_id == 0) { if (isset($_SESSION['sess_user_id'])) { $user_id = $_SESSION['sess_user_id']; } else { return array(); } } /* see if permissions are simple */ $simple_perms = get_simple_graph_perms($user_id); /* in case we need to review get the graph_auth_method */ $graph_auth_method = read_config_option('graph_auth_method'); /* get policies for all groups and user */ $policies = get_policies($user_id); /* short circuit if we don't have a user */ if ($auth_method > 0 && $user_id == 0) { return array(); } if (!$simple_perms && $auth_method != 0) { $sql_where = get_policy_where($graph_auth_method, $policies, $sql_where); } if ($total_rows != -2) { $templates = db_fetch_assoc("SELECT gt.id, gt.name, COUNT(*) AS graphs FROM graph_local AS gl LEFT JOIN graph_templates AS gt ON gt.id = gl.graph_template_id LEFT JOIN host AS h ON h.id = gl.host_id $sql_where GROUP BY gl.graph_template_id $sql_order $sql_limit"); } if ($total_rows >= 0 || $total_rows == -2) { $sql = "SELECT COUNT(DISTINCT gl.graph_template_id) AS id FROM graph_local AS gl LEFT JOIN graph_templates AS gt ON gt.id = gl.graph_template_id LEFT JOIN host AS h ON h.id = gl.host_id $sql_where"; if ($graph_template_id == 0) { $total_rows = get_total_row_data($user_id, $sql, array(), 'graph'); } else { $total_rows = db_fetch_cell($sql); } } // For timing $end = microtime(true); cacti_log(sprintf('The Get Templates total time was %4.2f', $end - $start), false, 'AUTH', POLLER_VERBOSITY_DEBUG); if ($templates === false) { $templates = array(); } return $templates; } /** * get_policy_join_select - Parse the policies in order to visually display user permissions * * @param (array) $policies The list of user and group policies. Will be reversed to * show user permissions first. * * @return (array) Array containing both $sql_select and $sql_join */ function get_policy_join_select($policies) { $sql_join = ''; $sql_select = ''; $i = 1; $j = 1; foreach($policies as $p) { $sql_join .= "LEFT JOIN (SELECT * FROM user_auth_" . ($p['type'] == 'user' ? '' : 'group_') . "perms WHERE " . $p['type'] . '_id = ' . $p['id'] . ") AS uap$j ON (gl.id = uap$j.item_id AND uap$j.type = 1) "; $sql_select .= ($sql_select != '' ? ', ' : '') . "uap$j." . $p['type'] . "_id AS graph$i"; $j++; $sql_join .= 'LEFT JOIN (SELECT * FROM user_auth_' . ($p['type'] == 'user' ? '' : 'group_') . "perms WHERE " . $p['type'] . '_id = ' . $p['id'] . ") AS uap$j ON (gl.host_id = uap$j.item_id AND uap$j.type = 3) "; $sql_select .= ($sql_select != '' ? ', ' : '') . "uap$j." . $p['type'] . "_id AS device$i"; $j++; $sql_join .= 'LEFT JOIN (SELECT * FROM user_auth_' . ($p['type'] == 'user' ? '' : 'group_') . "perms WHERE " . $p['type'] . '_id = ' . $p['id'] . ") AS uap$j ON (gl.graph_template_id = uap$j.item_id AND uap$j.type = 4) "; $sql_select .= ($sql_select != '' ? ', ' : '') . "uap$j." . $p['type'] . "_id AS template$i"; $j++; $i++; } return array('sql_select' => $sql_select, 'sql_join' => $sql_join); } /** * get_policy_where - Parse the policies in order to downselect matching graphs * without the use of the SQL Having clause which is very inefficient * * @param (int) $graph_auth_method - The graph auth method: permissive, restrictive, device, graph_template * @param (array) $policies - The list of user and group policies. Will be reversed to * @param (string) $sql_where - The SQL where filter provided by the calling function. * * @return (string) - Updated sql_where value */ function get_policy_where($graph_auth_method, $policies, $sql_where) { if ($graph_auth_method == 1) { // Policy Rows include // id, type (group|user), policy_graphs, policy_hosts, policy_graph_templates // Table user_auth_perms has user_id, item_id, type // Types can be: // 1 - Graph // 2 - Trees // 3 - Device // 4 - Graph Template // Policies are // 1 - Default Allow, all exceptions are denied // 2 - Default Deny, all exceptions are allowed // Permissive means access to the graph, or access to either the host or template $sql_where .= ($sql_where != '' ? ' AND (':'WHERE ('); foreach($policies as $index => $p) { $sql_where .= ($index > 0 ? ' OR (':'('); if ($p['type'] == 'user') { if ($p['policy_graphs'] == 1) { $sql_where .= 'gl.id NOT IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 1)'; } else { $sql_where .= 'gl.id IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 1)'; } $sql_where .= ' OR '; if ($p['policy_hosts'] == 1) { $sql_where .= 'h.id NOT IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 3)'; } else { $sql_where .= 'h.id IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 3)'; } $sql_where .= ' OR '; if ($p['policy_graph_templates'] == 1) { $sql_where .= 'gl.graph_template_id NOT IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 4)'; } else { $sql_where .= 'gl.graph_template_id IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 4)'; } } else { if ($p['policy_graphs'] == 1) { $sql_where .= 'gl.id NOT IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 1)'; } else { $sql_where .= 'gl.id IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 1)'; } $sql_where .= ' OR '; if ($p['policy_hosts'] == 1) { $sql_where .= 'h.id NOT IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 3)'; } else { $sql_where .= 'h.id IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 3)'; } $sql_where .= ' OR '; if ($p['policy_graph_templates'] == 1) { $sql_where .= 'gl.graph_template_id NOT IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 4)'; } else { $sql_where .= 'gl.graph_template_id IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 4)'; } } $sql_where .= ')'; } $sql_where .= ')'; } elseif ($graph_auth_method == 2) { // Policy Rows include // id, type (group|user), policy_graphs, policy_hosts, policy_graph_templates // Table user_auth_perms has user_id, item_id, type // Types can be: // 1 - Graph // 2 - Trees // 3 - Device // 4 - Graph Template // Policies are // 1 - Default Allow, all exceptions are denied // 2 - Default Deny, all exceptions are allowed // Restrictive means access to the graph, or access to both the host and template $sql_where .= ($sql_where != '' ? ' AND (':'WHERE ('); foreach($policies as $index => $p) { $sql_where .= ($index == 0 ? '((':' OR (('); if ($p['type'] == 'user') { if ($p['policy_graphs'] == 1) { $sql_where .= 'gl.id NOT IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 1)'; } else { $sql_where .= 'gl.id IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 1)'; } $sql_where .= ') OR ('; if ($p['policy_hosts'] == 1) { $sql_where .= 'h.id NOT IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 3)'; } else { $sql_where .= 'h.id IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 3)'; } $sql_where .= ' AND '; if ($p['policy_graph_templates'] == 1) { $sql_where .= ' gl.graph_template_id NOT IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 4)'; } else { $sql_where .= ' gl.graph_template_id IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 4)'; } $sql_where .= ')'; } else { if ($p['policy_graphs'] == 1) { $sql_where .= 'gl.id NOT IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 1)'; } else { $sql_where .= 'gl.id IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 1)'; } $sql_where .= ') OR ('; if ($p['policy_hosts'] == 1) { $sql_where .= 'h.id NOT IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 3)'; } else { $sql_where .= 'h.id IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 3)'; } $sql_where .= ' AND '; if ($p['policy_graph_templates'] == 1) { $sql_where .= 'gl.graph_template_id NOT IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 4)'; } else { $sql_where .= 'gl.graph_template_id IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 4)'; } $sql_where .= ')'; } $sql_where .= ')'; } $sql_where .= ')'; } elseif ($graph_auth_method == 3) { // Policy Rows include // id, type (group|user), policy_graphs, policy_hosts, policy_graph_templates // Table user_auth_perms has user_id, item_id, type // Types can be: // 1 - Graph // 2 - Trees // 3 - Device // 4 - Graph Template // Policies are // 1 - Default Allow, all exceptions are denied // 2 - Default Deny, all exceptions are allowed $sql_where .= ($sql_where != '' ? ' AND (':'WHERE ('); foreach($policies as $index => $p) { $sql_where .= ($index == 0 ? '((' : ') OR (('); if ($p['type'] == 'user') { if ($p['policy_graphs'] == 1) { $sql_where .= 'gl.id NOT IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 1)'; } else { $sql_where .= 'gl.id IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 1)'; } $sql_where .= ') OR ('; if ($p['policy_hosts'] == 1) { $sql_where .= 'h.id NOT IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 3)'; } else { $sql_where .= 'h.id IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 3)'; } } else { if ($p['policy_graphs'] == 1) { $sql_where .= 'gl.id NOT IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 1)'; } else { $sql_where .= 'gl.id IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 1)'; } $sql_where .= ') OR ('; if ($p['policy_hosts'] == 1) { $sql_where .= 'h.id NOT IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 3)'; } else { $sql_where .= 'h.id IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 3)'; } } $sql_where .= ')'; } $sql_where .= '))'; } elseif ($graph_auth_method == 4) { // Policy Rows include // id, type (group|user), policy_graphs, policy_hosts, policy_graph_templates // Table user_auth_perms has user_id, item_id, type // Types can be: // 1 - Graph // 2 - Trees // 3 - Device // 4 - Graph Template // Policies are // 1 - Default Allow, all exceptions are denied // 2 - Default Deny, all exceptions are allowed $sql_where .= ($sql_where != '' ? ' AND (':'WHERE ('); foreach($policies as $index => $p) { $sql_where .= ($index == 0 ? '((' : ') OR (('); if ($p['type'] == 'user') { if ($p['policy_graphs'] == 1) { $sql_where .= 'gl.id NOT IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 1)'; } else { $sql_where .= 'gl.id IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 1)'; } $sql_where .= ') OR ('; if ($p['policy_graph_templates'] == 1) { $sql_where .= 'gl.graph_template_id NOT IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 4)'; } else { $sql_where .= 'gl.graph_template_id IN (SELECT item_id FROM user_auth_perms WHERE user_id = ' . $p['id'] . ' AND type = 4)'; } } else { if ($p['policy_graphs'] == 1) { $sql_where .= 'gl.id NOT IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 1)'; } else { $sql_where .= 'gl.id IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 1)'; } $sql_where .= ') OR ('; if ($p['policy_graph_templates'] == 1) { $sql_where .= 'gl.graph_template_id NOT IN (SELECT item_id FROM user_auth_group_perms WHERE group_id = ' . $p['id'] . ' AND type = 4)'; } else { $sql_where .= 'gl.graph_template_id IN (SELECT item_id FROM user_auth_group_perms WHERE group_id =' . $p['id'] . ' AND type = 4)'; } } $sql_where .= ')'; } $sql_where .= '))'; } return $sql_where; } /** * get_permission_string - get the effective permission string for the graph in question. The * logic for this is somewhat complex, but understandable. First, the $graph object will include * three columns generally graphX, deviceX, and templateX for each of the user or groups in the collection. * The way we assign a restrictive or permissive value is based upon the graph permission setting * in Cacti, but also whether or not the default access for the object type is either 'Allow' or 'Deny'. * * - If the 'default access' for the object type is 'Deny', then a numeric value in userX means * the user has permission to an object. * - If the default access for the object is 'Allow', then a numeric * value in userX means that the object is blocked. * * Again, each of the graphX, deviceX, and templateX will always come in three's. They equate to: * * - graphX - The user does or does not have permission to the Graph at the Graph Level * - deviceX - The user does or does not have permission to the Graph at the Device Level * - templateX - The user does or does not have permission to the Graph at the Graph Template Level * * Then, the effective permission are calculated by the Graph Permission Model in Cacti. They are * * - Permissive - If the user has access to the Graph, the Device, or Graph Template, then the * user will have access to the Graph. * * - Restrictive - If the user has access to the Graph, or both the Device and Graph Template, * then the user will have access to the Graph * * - Device - If the user has access to the Graph, or the Device, then the user will have * access to the Graph * * - Graph Template - If the user has access to the Graph, or the Graph Template, then the user * will have access to the Graph. * * This function will apply this logic, and then respond to the user a 'Granted' or 'Restricted' * column value, and a Tooltip, that shows how the permissions were evaluated. In other words * why was the user either permitted to or denied access to the Graph. */ function get_permission_string(&$graph, &$policies) { $grantStr = ''; $rejectStr = ''; $reasonStr = ''; $drejectStr = ''; // Methods: // 1 - Permissive // 2 - Restrictive // 3 - Device // 4 - Graph Template $method = read_config_option('graph_auth_method'); if ($graph['disabled'] == 'on' && read_user_setting('hide_disabled', false, false, get_request_var('user_id'))) { $drejectStr .= __esc('Device:(Hide Disabled)'); } // Policies: // 1 - Default Allow All - Numeric means blocked // 2 - Default Deny All - Numeric means allowed $i = 1; foreach($policies as $p) { $allowed = 0; $rejected = 0; // Perform the Graph Check first // If a user has access at the Graph Access, they always get Access if ($p['policy_graphs'] == 1) { // Default is to allow if (empty($graph["graph$i"])) { // Allow the access at the level $grantStr .= ($grantStr != '' ? ', ':'') . __esc('Graph:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); } else { $rejectStr .= ($rejectStr != '' ? ', ':'') . __esc('Graph:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); $rejected++; } } else { // Default is to Deny if (!empty($graph["graph$i"])) { $grantStr .= ($grantStr != '' ? ', ':'') . __esc('Graph:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); } else { $rejectStr .= ($rejectStr != '' ? ', ':'') . __esc('Graph:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); $rejected++; } } /** * Now we check at the Device and Graph Template Level. Here the permission get a bit more dicey, so we will * Use case logic to make it read more simply. */ switch($method) { case 1: // Permissive if ($p['policy_hosts'] == 1) { if (empty($graph["device$i"])) { $grantStr .= ($grantStr != '' ? ', ':'') . __esc('Device:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); } else { $rejected++; } } else { if (!empty($graph["device$i"])) { $grantStr = $grantStr . ($grantStr != '' ? ', ':'') . __esc('Device:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); } else { $rejected++; } } if ($p['policy_graph_templates'] == 1) { if (empty($graph["template$i"])) { $grantStr .= ($grantStr != '' ? ', ':'') . __esc('Template:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); } else { $rejected++; } } else { if (!empty($graph["template$i"])) { $grantStr .= ($grantStr != '' ? ', ':'') . __esc('Template:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); } else { $rejected++; } } if ($rejected == 3) { $rejectStr .= ($rejectStr != '' ? ', ':'') . __esc('Graph+Device+Template:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); } break; case 2: // Restrictive $allowed = 0; $rejected = 0; if ($p['policy_hosts'] == 1) { if (empty($graph["device$i"])) { $allowed++; } else { $rejected++; } } else { if (!empty($graph["device$i"])) { $allowed++; } else { $rejected++; } } if ($p['policy_graph_templates'] == 1) { if (empty($graph["template$i"])) { $allowed++; } else { $rejected++; } } else { if (!empty($graph["template$i"])) { $rejected++; } else { $allowed++; } } if ($allowed == 2) { $grantStr = $grantStr . ($grantStr != '' ? ', ':'') . __esc('Device+Template:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); } else { $rejectStr = $rejectStr . ($rejectStr != '' ? ', ':'') . __esc('Device+Template:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); } break; case 3: // Device if ($p['policy_hosts'] == 1) { if (empty($graph["device$i"])) { $grantStr = $grantStr . ($grantStr != '' ? ', ':'') . __esc('Device:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); } else { $rejectStr = $rejectStr . ($rejectStr != '' ? ', ':'') . __esc('Device:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); } } else { if (!empty($graph["device$i"])) { $grantStr = $grantStr . ($grantStr != '' ? ', ':'') . __esc('Device:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); } else { $rejectStr = $rejectStr . ($rejectStr != '' ? ', ':'') . __esc('Device:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); } } break; case 4: // Graph Template if ($p['policy_graph_templates'] == 1) { if (empty($graph["template$i"])) { $grantStr = $grantStr . ($grantStr != '' ? ', ':'') . __esc('Template:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); } else { $rejectStr = $rejectStr . ($rejectStr != '' ? ', ':'') . __esc('Template:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); } } else { if (!empty($graph["template$i"])) { $grantStr = $grantStr . ($grantStr != '' ? ', ':'') . __esc('Template:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); } else { $rejectStr = $rejectStr . ($rejectStr != '' ? ', ':'') . __esc('Template:(%s%s)', ucfirst($p['type']), ($p['type'] != 'user' ? '/' . $p['name']:'')); } } break; } $i++; } $permStr = ''; if ($drejectStr != '') { $reasonStr .= ($reasonStr != '' ? ', ':'') . __esc('Restricted By: ') . $drejectStr; } if ($grantStr != '') { $reasonStr .= ($reasonStr != '' ? ', ':'') . __esc('Granted By: ') . trim($grantStr, ','); if ($rejectStr != '') { $reasonStr .= ', ' . __esc('Restricted By: ') . trim($rejectStr, ','); } if ($drejectStr == '') { $permStr = "" . __('Granted') . ''; } else { $permStr = "" . __('Restricted') . ''; } } elseif ($rejectStr != '') { $reasonStr .= ($reasonStr != '' ? ', ':'') . __esc('Restricted By: ') . trim($rejectStr, ','); $permStr = "" . __('Restricted') . ''; } else { $permStr = __('Unknown'); } return $permStr; } /** * get_allowed_trees - returns the list of Trees that the user is allowed * To access. This function is generally intended for both listbox and table displays as * well as to build out the tree for a user. * * @param (bool) Is the Tree in Edit mode or not * @param (bool) Return either the SQL used to get the values or the values * @param (string) The SQL Order clause to use for the sorting of graphs * @param (int) The limit on items to return. If empty or -1, return all items * @param (int) The number of rows found, to be returned to the caller * @param (int) If checking a user, specify the user_id otherwise for the current user leave blank * @param (int) If just searching for if a single graph template is permitted, the id of that graph template * * @return (string|array) An array of permitted Trees or the SQL to gather them */ function get_allowed_trees($edit = false, $return_sql = false, $sql_where = '', $sql_order = 'name', $sql_limit = '', &$total_rows = 0, $user_id = 0) { if (!auth_valid_user($user_id)) { return array(); } if ($sql_limit != '' && $sql_limit != -1) { $sql_limit = "LIMIT $sql_limit"; } else { $sql_limit = ''; } if ($sql_order != '') { $sql_order = "ORDER BY $sql_order"; } if ($user_id == -1) { $auth_method = 0; } else { $auth_method = read_config_option('auth_method'); } if ($auth_method != 0) { if ($user_id == 0) { if (isset($_SESSION['sess_user_id'])) { $user_id = $_SESSION['sess_user_id']; } else { return array(); } } /* get policies for all groups and user */ $policies = db_fetch_assoc_prepared("SELECT uag.id, 'group' AS type, policy_trees FROM user_auth_group AS uag INNER JOIN user_auth_group_members AS uagm ON uag.id = uagm.group_id WHERE uag.enabled = 'on' AND uagm.user_id = ?", array($user_id)); $policies[] = db_fetch_row_prepared("SELECT id, 'user' as type, policy_trees FROM user_auth WHERE id = ?", array($user_id)); $i = 0; $sql_join = ''; $sql_where1 = ''; foreach($policies as $policy) { if ($policy['policy_trees'] == '1') { $sql_where1 .= ($sql_where1 != '' ? ' OR':'') . " uap$i." . $policy['type'] . "_id IS NULL"; } elseif ($policy['policy_trees'] == '2') { $sql_where1 .= ($sql_where1 != '' ? ' OR':'') . " uap$i." . $policy['type'] . "_id IS NOT NULL"; } $sql_join .= 'LEFT JOIN user_auth_' . ($policy['type'] == 'group' ? 'group_':'') . "perms AS uap$i ON (gt.id=uap$i.item_id AND uap$i.type=2 AND uap$i." . $policy['type'] . '_id=' . $policy['id'] . ') '; $i++; } if ($sql_where != '') { $sql_where = 'WHERE ' . ($edit == false ? '(gt.enabled="on") AND ':'') . '(' . $sql_where . ') AND (' . $sql_where1 . ')'; } else { $sql_where = 'WHERE ' . ($edit == false ? '(gt.enabled="on") AND ':'') . '(gt.enabled="on") AND (' . $sql_where1 . ')'; } $sql = "SELECT id, name FROM graph_tree AS gt $sql_join $sql_where $sql_order $sql_limit"; if ($return_sql) { return $sql; } else { $trees = db_fetch_assoc($sql); $sql = "SELECT COUNT(gt.id) FROM graph_tree AS gt $sql_join $sql_where"; $total_rows = get_total_row_data($user_id, $sql, array(), 'tree'); } } else { if ($sql_where != '') { $sql_where = "WHERE enabled='on' AND $sql_where"; } else { $sql_where = "WHERE enabled='on'"; } if ($return_sql) { return "SELECT id, name FROM graph_tree $sql_where $sql_order"; } else { $trees = db_fetch_assoc("SELECT id, name FROM graph_tree AS gt $sql_where $sql_order"); $sql = "SELECT COUNT(*) FROM graph_tree AS gt $sql_where"; $total_rows = get_total_row_data($user_id, $sql, array(), 'tree'); } } return $trees; } /** * get_allowed_branches - returns the list of Tree branches that the user is allowed * To access. This function is generally intended for both listbox and table displays as * well as to build out the tree for a user. * * @param (bool) Is the Tree in Edit mode or not * @param (string) The SQL Where used to get the values or the values * @param (string) The SQL Order clause to use for the sorting of branches * @param (int) The limit on items to return. If empty or -1, return all items * @param (int) The number of rows found, to be returned to the caller * @param (int) If checking a user, specify the user_id otherwise for the current user leave blank * * @return (array) An array of permitted Tree branches */ function get_allowed_branches($sql_where = '', $sql_order = 'name', $sql_limit = '', &$total_rows = 0, $user_id = 0) { if (!auth_valid_user($user_id)) { return array(); } if ($sql_limit != '' && $sql_limit != -1) { $sql_limit = "LIMIT $sql_limit"; } else { $sql_limit = ''; } if ($sql_order != '') { $sql_order = "ORDER BY $sql_order"; } // suppress total rows $total_rows = -1; if ($user_id == -1) { $auth_method = 0; } else { $auth_method = read_config_option('auth_method'); } if ($auth_method > 0 && $user_id == 0) { if (isset($_SESSION['sess_user_id'])) { $user_id = $_SESSION['sess_user_id']; } else { return array(); } } $simple_perms = get_simple_device_perms($user_id); /* get policies for all groups and user */ $policies = get_policies($user_id); $sql_hosts_where = ''; if (!$simple_perms) { $hosts = get_allowed_devices('', 'description', '', $total_rows); if (cacti_sizeof($hosts)) { $hosts = array_rekey($hosts, 'id', 'description'); } $tree_hosts = db_fetch_assoc("SELECT DISTINCT h.id, h.description FROM graph_tree_items AS gti INNER JOIN graph_tree AS gt ON gti.graph_tree_id = gt.id INNER JOIN host AS h ON gti.host_id = h.id WHERE gti.host_id > 0 AND $sql_where", false); if (cacti_sizeof($tree_hosts)) { $tree_hosts = array_rekey($tree_hosts, 'id', 'description'); } $hosts = array_intersect_key($hosts, $tree_hosts); if (cacti_sizeof($hosts) > 0) { $sql_hosts_where = 'AND h.id IN (' . implode(',', array_keys($hosts)) . ')'; } } if ($auth_method != 0) { $i = 0; $sql_join = ''; $sql_where1 = ''; foreach($policies as $policy) { if ($policy['policy_trees'] == '1') { $sql_where1 .= ($sql_where1 != '' ? ' OR':'') . " uap$i." . $policy['type'] . "_id IS NULL"; } elseif ($policy['policy_trees'] == '2') { $sql_where1 .= ($sql_where1 != '' ? ' OR':'') . " uap$i." . $policy['type'] . "_id IS NOT NULL"; } $sql_join .= 'LEFT JOIN user_auth_' . ($policy['type'] == 'group' ? 'group_':'') . "perms AS uap$i ON (gt.id=uap$i.item_id AND uap$i.type=2 AND uap$i." . $policy['type'] . '_id=' . $policy['id'] . ') '; $i++; } if ($sql_where != '') { $sql_where = 'WHERE gt.enabled="on" AND (' . $sql_where . ')' . ($sql_where1 != '' ? ' AND (' . $sql_where1 . ')':''); } elseif ($sql_where1 != '') { $sql_where = 'WHERE gt.enabled="on" AND (' . $sql_where1 . ')'; } $sql = "(SELECT gti.id, CONCAT('". __('Branch:') . " ', gti.title) AS name FROM graph_tree AS gt INNER JOIN graph_tree_items AS gti ON gti.graph_tree_id = gt.id AND gti.host_id = 0 AND gti.local_graph_id=0 $sql_join $sql_where ) UNION ( SELECT gti.id, CONCAT('" . __('Device:') . " ', h.description) AS name FROM graph_tree AS gt INNER JOIN graph_tree_items AS gti ON gti.graph_tree_id = gt.id INNER JOIN host AS h ON h.id=gti.host_id $sql_hosts_where $sql_join $sql_where ) $sql_order $sql_limit"; $branches = db_fetch_assoc($sql); $sql = 'SELECT COUNT(*) FROM (' . $sql . ') AS rower'; $total_rows = get_total_row_data($user_id, $sql, array(), 'branch'); } else { if ($sql_where != '') { $sql_where = "WHERE gt.enabled='on' AND h.disabled='' AND ((h.id > 0 AND h.deleted = '') OR h.id IS NULL) AND $sql_where"; } else { $sql_where = "WHERE gt.enabled='on' AND h.disabled='on' AND ((h.id > 0 AND h.deleted = '') OR h.id IS NULL)"; } $sql = "( SELECT gti.id, CONCAT('". __('Branch:') . " ', gti.title) AS name FROM graph_tree AS gt INNER JOIN graph_tree_items AS gti ON gti.graph_tree_id = gt.id AND gti.host_id=0 AND gti.local_graph_id=0 $sql_where ) UNION ( SELECT gti.id, CONCAT('" . __('Device:') . " ', h.description) AS name FROM graph_tree AS gt INNER JOIN graph_tree_items AS gti ON gti.graph_tree_id = gt.id INNER JOIN host AS h ON h.id=gti.host_id $sql_join $sql_where ) $sql_order $sql_limit"; $branches = db_fetch_assoc($sql); $sql = 'SELECT COUNT(*) FROM (' . $sql . ') AS rower'; $total_rows = get_total_row_data($user_id, $sql, array(), 'branch'); } return $branches; } /** * get_allowed_devices - returns the list of devices that the user is allowed * To access. This function is generally intended for both listbox and table displays as * well as other tasks. * * @param (string) The SQL Where used to get the values or the values * @param (string) The SQL Order clause to use for the sorting of devices * @param (int) The limit on items to return. If empty or -1, return all items * @param (int) The number of rows found, to be returned to the caller * @param (int) If checking a user, specify the user_id otherwise for the current user leave blank * * @return (array) An array of permitted devices */ function get_allowed_devices($sql_where = '', $sql_order = 'description', $sql_limit = '', &$total_rows = 0, $user_id = 0, $device_id = 0) { if (!auth_valid_user($user_id)) { return array(); } if ($user_id == -1) { $auth_method = 0; } else { $auth_method = read_config_option('auth_method'); } if ($auth_method > 0 && $user_id == 0) { if (isset($_SESSION['sess_user_id'])) { $user_id = $_SESSION['sess_user_id']; } else { return array(); } } $simple_perms = get_simple_device_perms($user_id); $init_rows = $total_rows; $host_list = array(); if ($sql_limit != '' && $sql_limit != -1) { $sql_limit = "LIMIT $sql_limit"; } else { $sql_limit = ''; } if ($sql_order != '') { $sql_order = "ORDER BY $sql_order"; } if (read_user_setting('hide_disabled') == 'on') { $sql_where .= ($sql_where != '' ? ' AND ':'') . '(h.disabled = "" OR h.disabled IS NULL)'; } if ($sql_where != '') { $sql_where = "WHERE ((h.id > 0 AND h.deleted = '') OR h.id IS NULL) AND $sql_where"; } else { $sql_where = "WHERE ((h.id > 0 AND h.deleted = '') OR h.id IS NULL) "; } if ($device_id > 0) { $sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . " h.id = $device_id"; } $graph_auth_method = read_config_option('graph_auth_method'); /* get policies for all groups and user */ $policies = get_policies($user_id); if (!$simple_perms && $auth_method != 0) { $sql_where = get_policy_where($graph_auth_method, $policies, $sql_where); } if ($total_rows != -2) { $host_list = db_fetch_assoc("SELECT h1.* FROM host AS h1 INNER JOIN ( SELECT DISTINCT id FROM ( SELECT h.id FROM host AS h LEFT JOIN graph_local AS gl ON h.id=gl.host_id LEFT JOIN graph_templates AS gt ON gt.id=gl.graph_template_id LEFT JOIN host_template AS ht ON h.host_template_id=ht.id $sql_where ) AS rs1 ) AS rs2 ON rs2.id=h1.id $sql_order $sql_limit"); } if ($total_rows >= 0 || $total_rows == -2) { $sql = "SELECT COUNT(DISTINCT id) FROM ( SELECT h.id FROM host AS h LEFT JOIN graph_local AS gl ON h.id=gl.host_id LEFT JOIN graph_templates AS gt ON gt.id=gl.graph_template_id LEFT JOIN host_template AS ht ON h.host_template_id=ht.id $sql_where ) AS rower"; if ($device_id == 0) { $total_rows = get_total_row_data($user_id, $sql, array(), 'device'); } else { $total_rows = db_fetch_cell($sql); } } return $host_list; } /** * get_allowed_sites - returns the list of sites that the user is allowed * To access. This function is generally intended for both listbox and table displays as * well as other tasks. * * @param (string) The SQL Where used to get the values or the values * @param (string) The SQL Order clause to use for the sorting of devices * @param (int) The limit on items to return. If empty or -1, return all items * @param (int) The number of rows found, to be returned to the caller * @param (int) If checking a user, specify the user_id otherwise for the current user leave blank * @param (int) If checking a single site, specify the site_id * * @return (array) An array of permitted sites */ function get_allowed_sites($sql_where = '', $sql_order = 'name', $sql_limit = '', &$total_rows = 0, $user_id = 0, $site_id = 0) { if (!auth_valid_user($user_id)) { return array(); } if ($sql_limit != '' && $sql_limit != -1) { $sql_limit = "LIMIT $sql_limit"; } else { $sql_limit = ''; } if ($sql_order != '') { $sql_order = "ORDER BY $sql_order"; } if ($sql_where != '') { $sql_where = "WHERE $sql_where"; } if ($site_id > 0) { $sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . " s.id=$site_id"; } if ($user_id == -1) { $auth_method = 0; } else { $auth_method = read_config_option('auth_method'); } if (isset($_SESSION['sess_user_id']) && $user_id == 0) { $user_id = $_SESSION['sess_user_id']; } elseif ($auth_method > 0) { return array(); } $sites = db_fetch_assoc("SELECT s.id, s.name FROM sites AS s INNER JOIN host AS h ON s.id=h.site_id $sql_where GROUP BY s.id $sql_order $sql_limit"); $sql = "SELECT COUNT(DISTINCT s.id) FROM sites AS s INNER JOIN host AS h ON s.id=h.site_id $sql_where"; $total_rows = get_total_row_data($user_id, $sql, array(), 'site_device'); return $sites; } /** * get_allowed_site_devices - returns the list of devices in a site that the user is allowed * To access. This function is generally intended for both listbox and table displays as * well as other tasks. * * @param (int) The site id for the site * @param (string) The SQL Where used to get the values or the values * @param (string) The SQL Order clause to use for the sorting of devices * @param (int) The limit on items to return. If empty or -1, return all items * @param (int) The number of rows found, to be returned to the caller * @param (int) If checking a user, specify the user_id otherwise for the current user leave blank * * @return (array) An array of permitted site devices */ function get_allowed_site_devices($site_id, $sql_where = '', $sql_order = 'description', $sql_limit = '', &$total_rows = 0, $user_id = 0) { if (!auth_valid_user($user_id)) { return array(); } if ($user_id == -1) { $auth_method = 0; } else { $auth_method = read_config_option('auth_method'); } if ($auth_method > 0 && $user_id == 0) { if (isset($_SESSION['sess_user_id'])) { $user_id = $_SESSION['sess_user_id']; } else { return array(); } } $simple_perms = get_simple_device_perms($user_id); $policies = get_policies($user_id); $graph_auth_method = read_config_option('graph_auth_method'); if ($sql_limit != '' && $sql_limit != -1) { $sql_limit = "LIMIT $sql_limit"; } else { $sql_limit = ''; } if ($sql_order != '') { $sql_order = "ORDER BY $sql_order"; } if (read_user_setting('hide_disabled') == 'on') { $sql_where .= ($sql_where != '' ? ' AND ':'') . '(h.disabled = "" OR h.disabled IS NULL)'; } if ($sql_where != '') { $sql_where = "WHERE ((h.id > 0 AND h.deleted = '') OR h.id IS NULL) AND $sql_where"; } else { $sql_where = "WHERE ((h.id > 0 AND h.deleted = '') OR h.id IS NULL) "; } if ($site_id > 0) { $sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . " h.site_id=$site_id"; } if ($auth_method != 0 && !$simple_perms) { $sql_where = get_policy_where($graph_auth_method, $policies, $sql_where); } $host_list = db_fetch_assoc("SELECT h1.*, ht.name AS host_template_name FROM host AS h1 LEFT JOIN host_template AS ht ON h1.host_template_id=ht.id INNER JOIN ( SELECT DISTINCT id FROM ( SELECT h.id FROM host AS h LEFT JOIN graph_local AS gl ON h.id=gl.host_id LEFT JOIN graph_templates_graph AS gtg ON gl.id=gtg.local_graph_id LEFT JOIN graph_templates AS gt ON gt.id=gl.graph_template_id LEFT JOIN host_template AS ht ON h.host_template_id=ht.id $sql_where ) AS rs1 ) AS rs2 ON rs2.id=h1.id $sql_order $sql_limit"); $sql = "SELECT COUNT(DISTINCT id) FROM ( SELECT h.id FROM host AS h LEFT JOIN graph_local AS gl ON h.id=gl.host_id LEFT JOIN graph_templates_graph AS gtg ON gl.id=gtg.local_graph_id LEFT JOIN graph_templates AS gt ON gt.id=gl.graph_template_id LEFT JOIN host_template AS ht ON h.host_template_id=ht.id $sql_where ) AS rower"; $total_rows = get_total_row_data($user_id, $sql, array(), 'site_device'); return $host_list; } /** * get_allowed_graph_templates_normalized - returns the list of graph templates aligned with the * To be able to differentiate between Graph Templates based on a non-data query data input mode * and those related to data queries. * * @param (string) The SQL Where used to get the values or the values * @param (string) The SQL Order clause to use for the sorting of devices * @param (int) The limit on items to return. If empty or -1, return all items * @param (int) The number of rows found, to be returned to the caller * @param (int) If checking a user, specify the user_id otherwise for the current user leave blank * @param (int) If checking a single graph template, specify the graph_template_id * * @return (array) An array of permitted and normalized graph templates */ function get_allowed_graph_templates_normalized($sql_where = '', $sql_order = 'name', $sql_limit = '', &$total_rows = 0, $user_id = 0, $graph_template_id = 0) { if (!auth_valid_user($user_id)) { return array(); } $templates = array_rekey(get_allowed_graph_templates($sql_where, $sql_order, $sql_limit, $total_rows, $user_id, $graph_template_id), 'id', 'name'); if (!cacti_sizeof($templates)) { return array(); } if ($sql_where != '') { $sql_where = ' WHERE (' . $sql_where . ') AND gl.graph_template_id IN(' . implode(', ', array_keys($templates)) . ') AND (gl.snmp_query_graph_id=0 OR sqg.name IS NOT NULL) AND (gt.name IS NOT NULL)'; } else { $sql_where = ' WHERE gl.graph_template_id IN(' . implode(', ', array_keys($templates)) . ') AND (gl.snmp_query_graph_id=0 OR sqg.name IS NOT NULL) AND (gt.name IS NOT NULL)'; } if ($sql_limit != '' && $sql_limit != -1) { $sql_limit = "LIMIT $sql_limit"; } else { $sql_limit = ''; } if ($sql_order != '') { $sql_order = "ORDER BY $sql_order"; } $templates = db_fetch_assoc("SELECT IF(snmp_query_graph_id=0, CONCAT('cg_',gl.graph_template_id), CONCAT('dq_', gl.snmp_query_graph_id)) AS id, IF(snmp_query_graph_id=0, gt.name, CONCAT(gt.name, ' [', sqg.name, ']')) AS name FROM graph_local AS gl LEFT JOIN graph_templates AS gt ON gt.id=gl.graph_template_id LEFT JOIN snmp_query_graph AS sqg ON gl.snmp_query_graph_id=sqg.id AND gl.graph_template_id=sqg.graph_template_id $sql_where GROUP BY id, name $sql_order $sql_limit"); return $templates; } /** * auth_valid_user - Returns true or false depending on if the user is valid for the system * users with an id of 0 or -1 are special cases. All non-zero users should be found in the * user_auth table. * * @param int A valid or invalid user. * * @return bool True is valid otherwise false */ function auth_valid_user($user_id) { static $users = array(); // perform a check if the user exists if ($user_id > 0) { if (isset($users[$user_id]) && $users[$user_id] == true) { return true; } elseif (isset($users[$user_id])) { return false; } else { $exists = db_fetch_cell_prepared('SELECT id FROM user_auth WHERE id = ?', array($user_id)); if (empty($exists)) { cacti_log(sprintf('ERROR: Invalid Cacti User ID %d is being used in a permission that does not exist', $user_id), false, 'AUTH'); cacti_debug_backtrace('Invalid User Accound'); $users[$user_id] = false; return false; } $users[$user_id] = true; } } return true; } /** * get_total_row_data - returns the total rows based upon a set of criteria * * This function will hash the $sql, and then search for the total * row counter based upon that criteria and if it finds a unexpired * match for that data, it will return the row count in the table * otherwise, it will execute the SQL and return the data. * * @param (int) The user id making the request * @param (string) The sql to be executed, either prepared or otherwise * @param (array) In the case of a prepared statement the * @param (string) The user defined class of data * @param (int) The timeout for the Class if not controlled by Cacti * * @return (array) an array containing a list of hosts */ function get_total_row_data($user_id, $sql, $sql_params = array(), $class = '', $timeout = 86400) { $execute = true; $now_time = time(); if (cacti_sizeof($sql_params)) { $nsql = str_replace('?', "'%s'", $sql); $nsql = vsprintf($nsql, $sql_params); $hash = md5($nsql); } else { $hash = md5($sql); } $row_data = db_fetch_row_prepared('SELECT total_rows, UNIX_TIMESTAMP(time) AS time FROM user_auth_row_cache WHERE user_id = ? AND class = ? AND hash = ?', array($user_id, $class, $hash)); $cached = false; if (cacti_sizeof($row_data)) { $cached = true; $last_time = read_config_option('time_last_change_' . $class); if (!empty($last_time)) { if ($row_data['time'] >= $last_time) { return $row_data['total_rows']; } } elseif ($now_time - $row_data['time'] < $timeout) { return $row_data['total_rows']; } } if (cacti_sizeof($sql_params)) { $rows = db_fetch_cell($sql, $sql_params); } else { $rows = db_fetch_cell($sql); } if ($user_id > 0) { db_execute_prepared('REPLACE INTO user_auth_row_cache (user_id, class, hash, total_rows, time) VALUES (?, ?, ?, ?, FROM_UNIXTIME(?))', array($user_id, $class, $hash, $rows, $now_time)); } return $rows; } /** * get_host_array - returns a list of hosts taking permissions into account if necessary * * @return (array) an array containing a list of hosts */ function get_host_array() { $total_rows = -1; $hosts = get_allowed_devices('', 'description', '', $total_rows); foreach($hosts as $host) { $return_devices[] = strip_domain($host['description']) . ' (' . strip_domain($host['hostname']) . ')'; } return $return_devices; } /** * get_allowed_ajax_hosts - returns a list of hosts in a way that can be easily read through * a callback, in JSON. The 'term' request variable will include an optional search term. * * @param (bool) Include the 'Any' item as the first in the list @ @param (bool) Include the 'None' item as the first or second in the list * @param (string) SQL Where expression to use to gather the hosts in addition to the 'term' * request variable. * * @return (string) A json array of matching devices upto a limit specified in the system * settings */ function get_allowed_ajax_hosts($include_any = true, $include_none = true, $sql_where = '') { $user_id = $_SESSION['sess_user_id']; if (!auth_valid_user($user_id)) { return array(); } $return = array(); $term = get_filter_request_var('term', FILTER_CALLBACK, array('options' => 'sanitize_search_string')); if ($term != '') { $sql_where .= ($sql_where != '' ? ' AND ' : '') . '(hostname LIKE ' . db_qstr("%$term%") . ' OR description LIKE ' . db_qstr("%$term%") . ' OR notes LIKE ' . db_qstr("%$term%") . ')'; } if (get_request_var('term') == '') { if ($include_any) { $return[] = array('label' => __('Any'), 'value' => 'Any', 'id' => '-1'); } if ($include_none) { $return[] = array('label' => __('None'), 'value' => 'None', 'id' => '0'); } } $total_rows = -1; $hosts = get_allowed_devices($sql_where, 'description', read_config_option('autocomplete_rows'), $total_rows); if (cacti_sizeof($hosts)) { foreach($hosts as $host) { $return[] = array('label' => html_escape(strip_domain($host['description'])), 'value' => html_escape($host['description']), 'id' => $host['id']); } } print json_encode($return); } /** * get_allowed_ajax_graph_templates - returns a list of graph_template in a way that can be easily * read through a callback, in JSON. The 'term' request variable will include an optional search term. * * @param (bool) Include the 'Any' item as the first in the list @ @param (bool) Include the 'None' item as the first or second in the list * @param (string) SQL Where expression to use to gather the graph templates in addition to the 'term' * request variable. * * @return (string) A json array of matching graph templates upto a limit specified in the system * settings */ function get_allowed_ajax_graph_templates($include_any = true, $include_none = true, $sql_where = '') { $user_id = $_SESSION['sess_user_id']; if (!auth_valid_user($user_id)) { return array(); } $return = array(); $term = get_filter_request_var('term', FILTER_CALLBACK, array('options' => 'sanitize_search_string')); if ($term != '') { $sql_where .= ($sql_where != '' ? ' AND ' : '') . 'name LIKE ' . db_qstr("%$term%"); } if (get_request_var('term') == '') { if ($include_any) { $return[] = array('label' => __('Any'), 'value' => 'Any', 'id' => '-1'); } if ($include_none) { $return[] = array('label' => __('None'), 'value' => 'None', 'id' => '0'); } } $total_rows = -1; $templates = get_allowed_graph_templates($sql_where, 'gt.name', read_config_option('autocomplete_rows'), $total_rows); if (cacti_sizeof($templates)) { foreach($templates as $template) { $return[] = array('label' => html_escape($template['name']), 'value' => html_escape($template['name']), 'id' => $template['id']); } } print json_encode($return); } /** * get_allowed_ajax_graph_items - returns a list of graph items in a way that can be easily * read through a callback, in JSON. The 'term' request variable will include an optional search term. * @ @param (bool) Include the 'None' item as the first item in the list * @param (string) SQL Where expression to use to gather the hosts in addition to the 'term' * request variable. * * @return (string) A json array of matching graph items upto a limit specified in the system * settings */ function get_allowed_ajax_graph_items($include_none = true, $sql_where = '') { $user_id = $_SESSION['sess_user_id']; if (!auth_valid_user($user_id)) { return array(); } $return = array(); $term = get_filter_request_var('term', FILTER_CALLBACK, array('options' => 'sanitize_search_string')); if ($term != '') { $sql_where .= ($sql_where != '' ? ' AND ' : '') . 'name_cache LIKE ' . db_qstr("%$term%") . ' OR data_source_name LIKE ' . db_qstr("%$term%"); } if (get_request_var('term') == '') { if ($include_none) { $return[] = array('label' => __('None'), 'value' => 'None', 'id' => '0'); } } $graph_items = get_allowed_graph_items($sql_where, 'name_cache', read_config_option('autocomplete_rows')); if (cacti_sizeof($graph_items)) { foreach($graph_items as $gi) { $return[] = array('label' => html_escape($gi['name']), 'value' => html_escape($gi['name']), 'id' => $gi['id']); } } print json_encode($return); } /** * get_allowed_ajax_graph - returns a list of allowed graphs in a way that can be easily * read through a callback, in JSON. The 'term' request variable will include an optional search term. * * @param (string) SQL Where expression to use to gather the graphs in addition to the 'term' * request variable. * * @return (string) A json array of matching graphs upto a limit specified in the system * settings */ function get_allowed_ajax_graphs($sql_where = '') { $user_id = $_SESSION['sess_user_id']; if (!auth_valid_user($user_id)) { return array(); } $return = array(); $term = get_filter_request_var('term', FILTER_CALLBACK, array('options' => 'sanitize_search_string')); if ($term != '') { $sql_where .= ($sql_where != '' ? ' AND ' : '') . 'title_cache LIKE ' . db_qstr("%$term%"); } $total_rows = -1; $graphs = get_allowed_graphs($sql_where, 'gtg.title_cache', read_config_option('autocomplete_rows'), $total_rows); if (cacti_sizeof($graphs)) { foreach($graphs as $graph) { $return[] = array('label' => html_escape($graph['title_cache']), 'value' => html_escape($graph['title_cache']), 'id' => $graph['local_graph_id']); } } print json_encode($return); } /** * get_allowed_graph_items - returns a array of allowed graph items in a way that can be easily * use in a table or list. * * @param (string) The SQL Where expression to use to gather the graph items * @param (string) The SQL Order clause to use for the sorting of devices * @param (int) The limit on items to return. If empty or -1, return all items * @param (int) The number of rows found, to be returned to the caller * @param (int) If checking a user, specify the user_id otherwise for the current user leave blank * * @return (array) An array of permitted graph items */ function get_allowed_graph_items($sql_where, $sql_order = 'name', $sql_limit = 20, $user_id = 0) { if (!auth_valid_user($user_id)) { return array(); } $return = array(); if ($user_id == 0 && isset($_SESSION['sess_user_id'])) { $user_id = $_SESSION['sess_user_id']; } if ($sql_where != '') { $sql_where = 'WHERE ' . $sql_where; } if ($sql_limit != '' && $sql_limit != -1) { $sql_limit = 'LIMIT ' . $sql_limit; } else { $sql_limit = ''; } if ($sql_order != '') { $sql_order = "ORDER BY $sql_order"; } $items = db_fetch_assoc("SELECT CONCAT_WS('', dtd.name_cache,' (', dtr.data_source_name, ')') as name, dtr.id, dl.host_id FROM data_local AS dl INNER JOIN data_template_data AS dtd ON dtd.local_data_id=dl.id INNER JOIN data_template_rrd AS dtr ON dtr.local_data_id=dl.id LEFT JOIN host AS h ON dl.host_id=h.id $sql_where $sql_order $sql_limit"); if (cacti_sizeof($items)) { foreach($items as $i) { if (is_device_allowed($i['host_id'], $user_id)) { $return[] = array('id' => $i['id'], 'name' => $i['name']); } } } return $return; } /** * auth_get_username - returns the login username for the user attempting to login * * @return (string) the username attempting to login */ function auth_get_username() { $auth_method = read_config_option('auth_method'); if ($auth_method == 2) { $username = get_basic_auth_username(); /* Get the Web Basic Auth username and set action so we login right away */ set_request_var('action', 'login'); } elseif (get_nfilter_request_var('action') == 'login') { $username = get_nfilter_request_var('login_username'); } else { $username = ''; } $username = sanitize_search_string($username); return $username; } /** * auth_checkclear_lockout - checks the lockout status of a user and unlocks if necessary * * @param (string) $username The username of the user to check * @param (int) $realm The realm of the user to check * * @return (void) */ function auth_checkclear_lockout($username, $realm) { // Unlock the user account if timing permits $secPassLockFailed = read_config_option('secpass_lockfailed'); if ($secPassLockFailed > 0) { $max = intval($secPassLockFailed); if ($max > 0) { $user = db_fetch_row_prepared("SELECT id, username, lastfail, failed_attempts, `locked`, password FROM user_auth WHERE username = ? AND realm = ? AND enabled = 'on'", array($username, $realm)); if (cacti_sizeof($user)) { $unlock = intval(read_config_option('secpass_unlocktime')); if ($unlock > 1440) { $unlock = 1440; } $secs_unlock = $unlock * 60; $secs_fail = time() - $user['lastfail']; cacti_log('DEBUG: User \'' . $username . '\' secs_fail = ' . $secs_fail . ', secs_unlock = ' . $secs_unlock, false, 'AUTH', POLLER_VERBOSITY_DEBUG); if ($unlock > 0 && ($secs_fail > $secs_unlock)) { db_execute_prepared("UPDATE user_auth SET lastfail = 0, failed_attempts = 0, `locked` = '' WHERE username = ? AND realm = ? AND enabled = 'on'", array($username, $realm)); } } } } } /** * auth_process_lockout_check - checks to see if the user is locked out of their account * if there is an error, the globals error and error_msg will be set to notify the caller * that a lockout is present and not to proceed with login. * * @param (string) $username - The name of the user account * @param (int) $realm - The logging realm for the user * * @return (bool) True if locked out, otherwise false */ function auth_process_lockout_check($username, $realm) { global $error, $error_msg; // Mark failed login attempts $secPassLockFailed = read_config_option('secpass_lockfailed'); if ($secPassLockFailed > 0) { $max = intval($secPassLockFailed); if ($max > 0) { $user = db_fetch_row_prepared("SELECT id, username, lastfail, failed_attempts, `locked`, password FROM user_auth WHERE username = ? AND realm = ? AND enabled = 'on'", array($username, $realm)); if (cacti_sizeof($user)) { if ($user['locked'] == 'on') { $error = true; $error_msg = __('Your account has been locked. Please contact your Administrator.'); return true; } } } } return false; } /** * auth_process_lockout - called when a user login attempt fails to increment or lockout the user * if there is an error, the globals error and error_msg will be set to notify the caller * that a lockout is present and not to proceed with login. * * @param (string) $username - The name of the user account * @param (int) $realm - The logging realm for the user * * @return (void) */ function auth_process_lockout($username, $realm) { global $error, $error_msg; // Mark failed login attempts $secPassLockFailed = read_config_option('secpass_lockfailed'); if ($secPassLockFailed > 0) { $max = intval($secPassLockFailed); if ($max > 0) { $user = db_fetch_row_prepared("SELECT id, username, enabled, lastfail, failed_attempts, `locked`, password FROM user_auth WHERE username = ? AND realm = ?", array($username, $realm)); if (cacti_sizeof($user)) { if ($user['enabled'] == '') { cacti_log("LOGIN FAILED: Local Login Failed for user '" . $username . "' from IP Address '" . get_client_addr() . "'. User account Disabled.", false, 'AUTH'); $error = true; $error_msg = __('Access Denied! Login Disabled.'); } $failed = intval($user['failed_attempts']) + 1; cacti_log('LOGIN FAILED: User \'' . $username . '\' failed authentication, incrementing lockout (' . $failed . ' of ' . $max . ')', false, 'AUTH', POLLER_VERBOSITY_LOW); if ($failed >= $max) { db_execute_prepared("UPDATE user_auth SET `locked` = 'on' WHERE username = ? AND realm = ? AND enabled = 'on'", array($username, $realm)); $user['locked'] = 'on'; } $user['lastfail'] = time(); db_execute_prepared("UPDATE user_auth SET lastfail = ?, failed_attempts = ? WHERE username = ? AND realm = ? AND enabled = 'on'", array($user['lastfail'], $failed, $username, $realm)); // Log the invalid password attempt db_execute_prepared('INSERT IGNORE INTO user_log (username, user_id, result, ip, time) VALUES (?, ?, 0, ?, NOW())', array($username, isset($user['id']) ? $user['id']:0, get_client_addr())); if ($user['locked'] == 'on') { cacti_log("LOGIN FAILED: Local Login Failed for user '" . $username . "' from IP Address '" . get_client_addr() . "'. Account is locked out.", false, 'AUTH'); $error = true; $error_msg = __('Your account has been locked. Please contact your Administrator.'); } else { cacti_log("LOGIN FAILED: Local Login Failed for user '" . $username . "' from IP Address '" . get_client_addr() . "'.", false, 'AUTH'); /* error */ $error = true; $error_msg = __('Access Denied! Login Failed.'); } } else { cacti_log("LOGIN FAILED: Local Login Failed to find user '" . $username . "' from IP Address '" . get_client_addr() . "'.", false, 'AUTH'); $error = true; $error_msg = __('Access Denied! Login Failed.'); } } } } /** * basic_auth_login_process - login a basic auth account or generate an error * if there is an error, the globals error and error_msg will be set to notify the caller * that a lockout is present and not to proceed with login. This function will also * exit and return html to the display to notify the user of critical errors. * * @param (string) $username The user to process * * @return (array|void) $user The valid user, an empty array if the user must be created * or void in the case of an exit condition */ function basic_auth_login_process($username) { global $error, $error_msg; if (empty($username)) { cacti_log('ERROR: No username passed with Web Basic Authentication enabled.', false, 'AUTH'); auth_display_custom_error_message(__('Web Basic Authentication configured, but no username was passed from the web server. Please make sure you have authentication enabled on the web server.')); exit; } /* Locate user in database */ $user = db_fetch_row_prepared('SELECT * FROM user_auth WHERE username = ? AND realm = 2', array($username)); if (!$user && get_template_account($username) == 0 && get_guest_account() === 0) { $error = true; $error_msg = __esc('%s authenticated by Web Server, but both Template and Guest Users are not defined in Cacti.', $username); cacti_log("LOGIN FAILED: User '" . $username . "' authenticated by Web Server, but both Template and Guest Users are not defined in Cacti. Exiting.", false, 'AUTH'); auth_display_custom_error_message($error_msg); exit; } return $user; } /** * local_auth_login_process - login a local account or generate an error * if there is an error, the globals error and error_msg will be set to notify the caller * that error and not to proceed with login. * * @param (string) $username - The user to process * * @return (array) $user - The valid user information, or empty array if user must be created */ function local_auth_login_process($username) { $user = array(); if (!api_plugin_hook_function('login_process', false)) { $user = secpass_login_process($username); /** * If the password needs to be rehashed for security purposes, * do that now. */ $stored_pass = db_fetch_cell_prepared('SELECT password FROM user_auth WHERE username = ? AND realm = 0', array($username)); if ($stored_pass != '') { $password = get_nfilter_request_var('login_password'); $valid = compat_password_verify($password, $stored_pass); cacti_log("DEBUG: User '" . $username . "' password for rehash is " . ($valid ? '':'in') . 'valid', false, 'AUTH', POLLER_VERBOSITY_DEBUG); if ($valid) { $user = db_fetch_row_prepared('SELECT * FROM user_auth WHERE username = ? AND realm = 0', array($username)); if (compat_password_needs_rehash($stored_pass, PASSWORD_DEFAULT)) { $password = compat_password_hash($password, PASSWORD_DEFAULT); db_check_password_length(); db_execute_prepared('UPDATE user_auth SET password = ? WHERE username = ?', array($password, $username)); } } } } return $user; } /** * ldap_login_process - login to an LDAP account or generate an error * if there is an error, the globals error and error_msg will be set to notify the caller * that error and not to proceed with login. * * @param (string) $username - The user to process * * @return (array) $user - The valid user information, or empty array if user must be created */ function ldap_login_process($username) { global $error, $error_msg; $password = get_nfilter_request_var('login_password'); if ($username == '') { $error = true; $error_msg = __('Access Denied! Login Failed.'); cacti_log('LOGIN FAILED: Empty LDAP Username provided', false, 'AUTH'); return array(); } auth_checkclear_lockout($username, 3); if (auth_process_lockout_check($username, 3)) { return array(); } $user = array(); $realm = 3; if ($password != '') { /* get user DN */ $ldap_dn_search_response = cacti_ldap_search_dn($username); if ($ldap_dn_search_response['error_num'] == '0') { $ldap_dn = $ldap_dn_search_response['dn']; } else { /* error searching */ $error = true; $error_msg = __('Access Denied! LDAP Search Error: %s', $ldap_dn_search_response['error_text']); cacti_log('LOGIN FAILED: LDAP Error: ' . $ldap_dn_search_response['error_text'], false, 'AUTH'); } if (!$error) { /* auth user with LDAP */ $ldap_auth_response = cacti_ldap_auth($username, $password, $ldap_dn); if ($ldap_auth_response['error_num'] == '0') { /* Locate user in database */ cacti_log("LOGIN: LDAP User '" . $username . "' Authenticated", false, 'AUTH'); $user = db_fetch_row_prepared('SELECT * FROM user_auth WHERE username = ? AND realm = ?', array($username, $realm)); } else { /* error */ $error = true; $error_msg = __('Access Denied! LDAP Error: %s', $ldap_auth_response['error_text']); cacti_log('LOGIN FAILED: LDAP Error: ' . $ldap_auth_response['error_text'], false, 'AUTH'); if ($ldap_auth_response['error_num'] == 1) { auth_process_lockout($username, $realm); } } } } else { /* error */ $error = true; $error_msg = __('Access Denied! No password provided by user.'); cacti_log(sprintf('LOGIN FAILED: LDAP No password provided for user %s', $username), false, 'AUTH'); auth_process_lockout($username, $realm); } return $user; } /** * domains_login_process - login to an LDAP domain account or generate an error * if there is an error, the globals error and error_msg will be set to notify the caller * that error and not to proceed with login. * * @param (string) $username - The user to process * * @return (array) $user - The valid user information, or empty array if user must be created */ function domains_login_process($username) { global $realm, $error, $error_msg; $realm = get_nfilter_request_var('realm'); $password = get_nfilter_request_var('login_password'); if ($username == '') { $error = true; $error_msg = __('Access Denied! Login Failed.'); cacti_log('LOGIN FAILED: Empty Domains Username provided', false, 'AUTH'); return array(); } auth_checkclear_lockout($username, $realm); if (auth_process_lockout_check($username, $realm)) { return array(); } $user = array(); if ($realm > 3 && $password != '') { /* get user DN */ $ldap_dn_search_response = domains_ldap_search_dn($username, $realm); if ($ldap_dn_search_response['error_num'] == '0') { $ldap_dn = $ldap_dn_search_response['dn']; } else { /* error searching */ $error = true; $error_msg = __('LDAP Search Error: %s', $ldap_dn_search_response['error_text']); cacti_log('LOGIN FAILED: LDAP Error: ' . $ldap_dn_search_response['error_text'], false, 'AUTH'); } if (!$error) { /* auth user with LDAP */ $ldap_auth_response = domains_ldap_auth($username, $password, $ldap_dn, $realm); if ($ldap_auth_response['error_num'] == '0') { /* User ok */ $domain_name = db_fetch_cell_prepared('SELECT domain_name FROM user_domains WHERE domain_id = ?', array($realm-1000)); /* Locate user in database */ cacti_log("LOGIN: LDAP User '$username' Authenticated from Domain '$domain_name'", false, 'AUTH'); $user = db_fetch_row_prepared('SELECT * FROM user_auth WHERE username = ? AND realm = ?', array($username, $realm)); /* Create user from template if requested */ $template_user = db_fetch_cell_prepared('SELECT user_id FROM user_domains WHERE domain_id = ?', array($realm-1000)); $template_username = db_fetch_cell_prepared('SELECT username FROM user_auth WHERE id = ?', array($template_user)); if (!cacti_sizeof($user) && $template_user > 0 && $username != '') { cacti_log("NOTE: User '" . $username . "' does not exist, copying template user", false, 'AUTH'); /* check that template user exists */ $user_template = db_fetch_row_prepared('SELECT * FROM user_auth WHERE id = ?', array($template_user)); if (cacti_sizeof($user_template)) { /* template user found */ $cn_full_name = db_fetch_cell_prepared('SELECT cn_full_name FROM user_domains_ldap WHERE domain_id = ?', array($realm-1000)); $cn_email = db_fetch_cell_prepared('SELECT cn_email FROM user_domains_ldap WHERE domain_id = ?', array($realm-1000)); if ($cn_full_name != '' || $cn_email != '') { $ldap_cn_search_response = cacti_ldap_search_cn($username, array($cn_full_name, $cn_email)); if (isset($ldap_cn_search_response['cn'])) { $data_override = array(); if (array_key_exists($cn_full_name, $ldap_cn_search_response['cn'])) { $data_override['full_name'] = $ldap_cn_search_response['cn'][$cn_full_name]; } else { $data_override['full_name'] = ''; } if (array_key_exists($cn_email, $ldap_cn_search_response['cn'])) { $data_override['email_address'] = $ldap_cn_search_response['cn'][$cn_email]; } else { $data_override['email_address'] = ''; } user_copy($user_template['username'], $username, 0, $realm, false, $data_override); } else { cacti_log('LOGIN: fields not found ' . $ldap_cn_search_response[0] . 'code: ' . $ldap_cn_search_response['error_num'], false, 'AUTH'); user_copy($user_template['username'], $username, 0, $realm); } } else { user_copy($user_template['username'], $username, 0, $realm); } /* requery newly created user */ $user = db_fetch_row_prepared('SELECT * FROM user_auth WHERE username = ? AND realm = ?', array($username, $realm)); } else { /* error */ $error = true; $error_msg = __('Access Denied! Template user id %s does not exist. Please contact your Administrator.', $template_user); cacti_log("LOGIN FAILED: Template user id '" . $template_user . "' does not exist.", false, 'AUTH'); } } } else { /* error */ $error = true; $error_msg = __('Access Denied! LDAP Error: %s', $ldap_auth_response['error_text']); cacti_log('LOGIN FAILED: LDAP Error: ' . $ldap_auth_response['error_text'], false, 'AUTH'); if ($ldap_auth_response['error_text'] == 1) { auth_lockout_process($username, $realm); } } } } elseif ($password == '') { /* error */ $error = true; $error_msg = __('Access Denied! No password provided by user.'); cacti_log(sprintf('LOGIN FAILED: LDAP No password provided for user %s', $username), false, 'AUTH'); auth_process_lockout($username, $realm); } return $user; } /** * domains_ldap_auth - authentications a LDAP domain login * * @param (string) $username - The user to process * @param (string) $password - The users password * @param (string) $dn - The domain name * @param (int) $realm - The LDAP Realm number * * @return (array) $response - The ldap response of false on a general error */ function domains_ldap_auth($username, $password = '', $dn = '', $realm = 0) { $ldap = new Ldap; if (!empty($username)) $ldap->username = $username; if (!empty($password)) $ldap->password = $password; $ldap->dn = $dn; $ld = db_fetch_row_prepared('SELECT * FROM user_domains_ldap WHERE domain_id = ?', array($realm-1000)); if (cacti_sizeof($ld)) { if (empty($dn) && !empty($ld['dn'])) { $ldap->dn = $ld['dn']; } if (!empty($ld['server'])) $ldap->host = $ld['server']; if (!empty($ld['port'])) $ldap->port = $ld['port']; if (!empty($ld['port_ssl'])) $ldap->port_ssl = $ld['port_ssl']; if (!empty($ld['proto_version'])) $ldap->version = $ld['proto_version']; if (!empty($ld['encryption'])) $ldap->encryption = $ld['encryption']; if (!empty($ld['referrals'])) $ldap->referrals = $ld['referrals']; if (!empty($ld['mode'])) $ldap->mode = $ld['mode']; if (!empty($ld['search_base'])) $ldap->search_base = $ld['search_base']; if (!empty($ld['search_filter'])) $ldap->search_filter = $ld['search_filter']; if (!empty($ld['specific_dn'])) $ldap->specific_dn = $ld['specific_dn']; if (!empty($ld['specific_password'])) $ldap->specific_password = $ld['specific_password']; if ($ld['group_require'] == 'on') { $ldap->group_require = true; } else { $ldap->group_require = false; } if (!empty($ld['group_dn'])) $ldap->group_dn = $ld['group_dn']; if (!empty($ld['group_attrib'])) $ldap->group_attrib = $ld['group_attrib']; if (!empty($ld['group_member_type'])) $ldap->group_member_type = $ld['group_member_type']; /* If the server list is a space delimited set of servers * process each server until you get a bind, or fail */ $ldap_servers = preg_split('/\s+/', $ldap->host); foreach($ldap_servers as $ldap_server) { $ldap->host = $ldap_server; $response = $ldap->Authenticate(); if ($response['error_num'] == 0) { return $response; } } return $response; } else { return false; } } /** * domains_ldap_search_dn - searches the user dn for existence * * @param (string) $username - The user to process * @param (int) $realm - The LDAP Realm number * * @return (array) $response - The ldap response, or false on general error */ function domains_ldap_search_dn($username, $realm) { $ldap = new Ldap; if (!empty($username)) $ldap->username = $username; $ld = db_fetch_row_prepared('SELECT * FROM user_domains_ldap WHERE domain_id = ?', array($realm-1000)); if (cacti_sizeof($ld)) { if (!empty($ld['dn'])) $ldap->dn = $ld['dn']; if (!empty($ld['server'])) $ldap->host = $ld['server']; if (!empty($ld['port'])) $ldap->port = $ld['port']; if (!empty($ld['port_ssl'])) $ldap->port_ssl = $ld['port_ssl']; if (!empty($ld['proto_version'])) $ldap->version = $ld['proto_version']; if (!empty($ld['encryption'])) $ldap->encryption = $ld['encryption']; if (!empty($ld['referrals'])) $ldap->referrals = $ld['referrals']; if (!empty($ld['mode'])) $ldap->mode = $ld['mode']; if (!empty($ld['search_base'])) $ldap->search_base = $ld['search_base']; if (!empty($ld['search_filter'])) $ldap->search_filter = $ld['search_filter']; if (!empty($ld['specific_dn'])) $ldap->specific_dn = $ld['specific_dn']; if (!empty($ld['specific_password'])) $ldap->specific_password = $ld['specific_password']; if ($ld['group_require'] == 'on') { $ldap->group_require = true; } else { $ldap->group_require = false; } if (!empty($ld['group_dn'])) $ldap->group_dn = $ld['group_dn']; if (!empty($ld['group_attrib'])) $ldap->group_attrib = $ld['group_attrib']; if (!empty($ld['group_member_type'])) $ldap->group_member_type = $ld['group_member_type']; /* If the server list is a space delimited set of servers * process each server until you get a bind, or fail */ $ldap_servers = preg_split('/\s+/', $ldap->host); foreach($ldap_servers as $ldap_server) { $ldap->host = $ldap_server; $response = $ldap->Search(); if ($response['error_num'] == 0) { return $response; } } return $response; } else { return false; } } /** * secpass_login_process - process a local login checking for triggers * such as those that would force a password check and take the appropriate action. * if there is an error, the globals error and error_msg will be set to notify the caller * that error and not to proceed with login. * * @param (string) $username - The user to process * * @return (array) $user - The login user or an empty array if the user does not exist */ function secpass_login_process($username) { global $error, $error_msg; $password = get_nfilter_request_var('login_password'); if ($username == '') { $error = true; $error_msg = __('Access Denied! Login Failed.'); cacti_log('LOGIN FAILED: Empty Local Username provided', false, 'AUTH'); return array(); } auth_checkclear_lockout($username, 0); if (auth_process_lockout_check($username, 0)) { return array(); } if (db_column_exists('user_auth', 'lastfail')) { $user = db_fetch_row_prepared("SELECT id, username, lastfail, failed_attempts, `locked`, enabled, password FROM user_auth WHERE username = ? AND realm = 0", array($username)); } else { $user = db_fetch_row_prepared("SELECT id, username, password, enabled FROM user_auth WHERE username = ? AND realm = 0", array($username)); } if (cacti_sizeof($user)) { if ($user['enabled'] != 'on') { $error = true; $error_msg = __('Access Denied! Login Failed.'); cacti_log(sprintf('LOGIN FAILED: User %s, account disabled.', $username), false, 'AUTH'); return array(); } if (trim($password) == '') { /* error */ $error = true; $error_msg = __('Access Denied! No password provided by user.'); cacti_log(sprintf('LOGIN FAILED: No password provided for user %s', $username), false, 'AUTH'); $valid_pass = false; } else { $valid_pass = compat_password_verify($password, $user['password']); } cacti_log('DEBUG: User \'' . $username . '\' valid password = ' . $valid_pass, false, 'AUTH', POLLER_VERBOSITY_DEBUG); if (!$valid_pass) { auth_process_lockout($username, 0); if (!$error) { $error = true; $error_msg = __('Access Denied! Login failed.'); } return array(); } } else { /* error */ $error = true; $error_msg = __('Access Denied! Login Failed.'); cacti_log(sprintf('LOGIN FAILED: Invalid user %s specified.', $username), false, 'AUTH'); } /** * Check if old password doesn't meet specifications and must be changed * This only applies to local logins where we store the actual hashed * password. */ if (read_config_option('secpass_forceold') == 'on') { $message = secpass_check_pass($password); if ($message != 'ok') { db_execute_prepared("UPDATE user_auth SET must_change_password = 'on' WHERE username = ? AND realm = 0 AND enabled = 'on'", array($username)); $error_msg = __('Your Cacti administrator has forced complex passwords for logins and your current Cacti password does not match the new requirements. Therefore, you must change your password now.'); raise_message('forced_password', $error_msg, MESSAGE_LEVEL_INFO); header('Location: auth_changepassword.php?header=false'); exit; } } // Set the last Login time if (read_config_option('secpass_expireaccount') > 0) { db_execute_prepared("UPDATE user_auth SET lastlogin = ? WHERE username = ? AND realm = 0 AND enabled = 'on'", array(time(), $username)); } return $user; } /** * secpass_check_pass - Validate a given password for various password rules * * @param (string) $password - The user password * * @return (string) Either 'ok', or an error message to present to the user */ function secpass_check_pass($password) { $minlen = read_config_option('secpass_minlen'); if (strlen($password) < $minlen) { return __('Password must be at least %d characters!', $minlen); } if (read_config_option('secpass_reqnum') == 'on' && str_replace(array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'), '', $password) == $password ) { return __('Your password must contain at least 1 numerical character!'); } if (read_config_option('secpass_reqmixcase') == 'on' && strtolower($password) == $password) { return __('Your password must contain a mix of lower case and upper case characters!'); } if (read_config_option('secpass_reqspec') == 'on' && str_replace(array('~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '+', '=', '[', '{', ']', '}', ';', ':', '<', ',', '.', '>', '?', '|', '/', '\\'), '', $password) == $password ) { return __('Your password must contain at least 1 special character!'); } return 'ok'; } /** * secpass_check_history - Checks for password reuse for local accounts * * @param (int) $id - The user id to check * @param (string) $password - The user password * * @return (bool) True if the user password provided meets history rules */ function secpass_check_history($id, $password) { $history = intval(read_config_option('secpass_history')); if ($history > 0) { $user = db_fetch_row_prepared("SELECT password, password_history FROM user_auth WHERE id = ? AND realm = 0 AND enabled = 'on'", array($id)); if (compat_password_verify($password, $user['password'])) { return false; } $passes = explode('|', $user['password_history']); // Double check this incase the password history setting was changed while (cacti_count($passes) > $history) { array_shift($passes); } if (!empty($passes)) { foreach ($passes as $hash) { if (compat_password_verify($password, $hash)) { return false; } } } } return true; } /** * rsa_check_keypair - Checks that Cacti ras_public_key is present. If not * it will insert the information into the Cacti database. * * @return (void) */ function rsa_check_keypair() { global $config; set_include_path($config['include_path'] . '/vendor/phpseclib/'); include('Crypt/Base.php'); include('Math/BigInteger.php'); include('Crypt/Hash.php'); include('Crypt/RSA.php'); include('Crypt/Rijndael.php'); include('Crypt/AES.php'); $public_key = read_config_option('rsa_public_key'); if(!$public_key) { $rsa = new phpseclib\Crypt\RSA(); $keys = $rsa->createKey(2048); $rsa->loadKey($keys['publickey']); $fingerprint = $rsa->getPublicKeyFingerprint(); db_execute_prepared("INSERT INTO settings (`name`, `value`) VALUES ('rsa_public_key', '" . $keys['publickey'] . "'), ('rsa_private_key', '" . $keys['privatekey'] . "'), ('rsa_fingerprint', '" . $fingerprint . "')" ); } } /** * reset_group_perms - sets a flag for all users of a group logged in that their perms * need to be reloaded from the database * * @param (int) $group_id - the id of the group to check * * @return (void) */ function reset_group_perms($group_id) { $users = array_rekey(db_fetch_assoc_prepared('SELECT user_id FROM user_auth_group_members WHERE group_id = ?', array($group_id)), 'user_id', 'user_id'); if (cacti_sizeof($users)) { db_execute('UPDATE user_auth SET reset_perms=FLOOR(RAND() * 4294967295) + 1 WHERE id IN (' . implode(',', $users) . ')'); } } /** * reset_user_perms - sets a flag for all users logged in as this user that their perms * need to be reloaded from the database * * @param (int) $user_id - the id of the current user * * @return (void) */ function reset_user_perms($user_id) { db_execute_prepared('UPDATE user_auth SET reset_perms=FLOOR(RAND() * 4294967295) + 1 WHERE id = ?', array($user_id)); if ($user_id == $_SESSION['sess_user_id']) { kill_session_var('sess_user_realms'); kill_session_var('sess_user_config_array'); kill_session_var('sess_config_array'); kill_session_var('sess_auth_names'); } } /** * is_user_perms_valid - checks to see if the admin has changed users permissions * * @param (int) $user_id - the id of the current user * * @return (bool) true if still valid, false otherwise */ function is_user_perms_valid($user_id) { global $config; static $valid = null; static $key = null; if ($valid === null && cacti_version_compare($config['cacti_db_version'], '1.0.0', '>=')) { $key = db_fetch_cell_prepared('SELECT reset_perms FROM user_auth WHERE id = ?', array($user_id)); } if (isset($_SESSION['sess_user_perms_key'])) { if ($key != $_SESSION['sess_user_perms_key']) { $valid = false; } else { $valid = true; } } else { $valid = true; } $_SESSION['sess_user_perms_key'] = $key; return $valid; } /** * compat_password_verify - if the secure function exists, verify against that * first. If that checks fails or does not exist, check against older md5 * version * * @param (string) $password - password to verify * @param (string) $hash - current password hash * * @return (bool) true if password hash matches, false otherwise */ function compat_password_verify($password, $hash) { if (function_exists('password_verify')) { if (password_verify($password, $hash)) { return true; } } $md5 = md5($password); return ($md5 == $hash); } /** * compat_password_hash - if the secure function exists, hash using that. * If that does not exist, hash older md5 function instead * * @param (string) $password - password to hash * @param (string) $algo - algorithm to use (PASSWORD_DEFAULT) * * @return (bool) true if password hash matches, false otherwise */ function compat_password_hash($password, $algo, $options = array()) { if (function_exists('password_hash')) { // Check if options array has anything, only pass when required return (cacti_sizeof($options) > 0) ? password_hash($password, $algo, $options) : password_hash($password, $algo); } return md5($password); } /** * compat_password_needs_rehash - if the secure function exists, check hash * using that. If that does not exist, return false as md5 doesn't need a * rehash * * @param (string) $password - password to hash * @param (string) $algo - algorithm to use (PASSWORD_DEFAULT) * * @return (bool) true if password hash needs changing, false otherwise */ function compat_password_needs_rehash($password, $algo, $options = array()) { if (function_exists('password_needs_rehash')) { // Check if options array has anything, only pass when required return (cacti_sizeof($options) > 0) ? password_needs_rehash($password, $algo, $options) : password_needs_rehash($password, $algo); } return true; } /** * auth_user_has_access - Verify that the user account has some access to cacti * * @param (int) $user - The user id of the account to check * * @return (bool) True if the user has access false otherwise */ function auth_user_has_access($user) { $access = false; // See if they have access to any realms $realms = db_fetch_cell_prepared('SELECT COUNT(*) FROM user_auth_realm WHERE user_id = ?', array($user['id'])); if ($realms > 0) { return true; } // See if they have general graph access as a guest account if (read_config_option('guest_user') > 0) { if ($user['show_tree'] == 'on' || $user['show_list'] == 'on' || $user['show_preview'] == 'on') { return true; } } // See if they have access to any group realms $user_groups = db_fetch_assoc_prepared('SELECT * FROM user_auth_group_members WHERE user_id = ?', array($user['id'])); if (cacti_sizeof($user_groups)) { foreach($user_groups as $g) { $realms = db_fetch_cell_prepared('SELECT COUNT(*) FROM user_auth_group_realm WHERE group_id = ?', array($g['group_id'])); if ($realms > 0) { return true; } // See if they have general graph access as a guest account if (read_config_option('guest_user') > 0) { if ($g['show_tree'] == 'on' || $g['show_list'] == 'on' || $g['show_preview'] == 'on') { return true; } } } } return false; } /** * auth_display_custom_error_message - displays a custom error message to the browser that looks like * the pre-defined error messages * * @param (string) $message - the actual text of the error message to display * * @return (void) */ function auth_display_custom_error_message($message) { global $config; $auth_method = read_config_option('auth_method'); if ($auth_method == 2) { $custom_message = read_config_option('basic_auth_fail_message'); } else { $custom_message = ''; } /* kill the session */ cacti_cookie_logout(); /* print error */ print ''; print ''; print ''; html_common_header(__('Cacti Login Failure')); print ''; print '
'; print '

' . $message . '

' . $custom_message . '

'; if ($auth_method != 2) { print '
' . __('Login Again') . '
'; } print '
'; } /** * auth_login_redirect - provide default page re-direction when a user first logs in. * * @param (string|array) $login_opts - optional array of user details * * @return (void) */ function auth_login_redirect($login_opts = '') { global $config; if ($login_opts == '') { $login_opts = db_fetch_cell_prepared('SELECT login_opts FROM user_auth WHERE id = ?', array($_SESSION['sess_user_id'])); } $newtheme = false; if (user_setting_exists('selected_theme', $_SESSION['sess_user_id']) && read_config_option('selected_theme') != read_user_setting('selected_theme')) { unset($_SESSION['selected_theme']); $newtheme = true; } // Decide what to do with an authenticated user switch ($login_opts) { case '1': /* referer */ /** * because we use plugins, we can't redirect back to graph_view.php if they don't * have console access */ if (isset($_SERVER['REDIRECT_URL'])) { $referer = sanitize_uri($_SERVER['REDIRECT_URL']); if (isset($_SERVER['REDIRECT_QUERY_STRING'])) { $referer .= '?' . $_SERVER['REDIRECT_QUERY_STRING']; } cacti_log(sprintf("DEBUG: Referer from REDIRECT_URL with Value: '%s', Effective: '%s'", $_SERVER['REDIRECT_URL'], $referer), false, 'AUTH', POLLER_VERBOSITY_DEBUG); } elseif (isset($_SERVER['HTTP_REFERER'])) { $referer = $_SERVER['HTTP_REFERER']; if (auth_basename($referer) == 'logout.php') { $referer = $config['url_path'] . 'index.php'; } elseif (strpos($referer, $config['url_path']) === false) { if (!is_realm_allowed(8)) { $referer = $config['url_path'] . 'graph_view.php' . ($newtheme ? '?newtheme=1':''); } else { $referer = $config['url_path'] . 'index.php' . ($newtheme ? '?newtheme=1':''); } } cacti_log(sprintf("DEBUG: Referer from HTTP_REFERER with Value: '%s', Effective: '%s'", $_SERVER['HTTP_REFERER'], $referer), false, 'AUTH', POLLER_VERBOSITY_DEBUG); } elseif (isset($_SERVER['REQUEST_URI'])) { $referer = sanitize_uri($_SERVER['REQUEST_URI']); if (auth_basename($referer) == 'logout.php') { $referer = $config['url_path'] . 'index.php'; } cacti_log(sprintf("DEBUG: Referer from REQUEST_URI with Value: '%s', Effective: '%s'", $_SERVER['REQUEST_URI'], $referer), false, 'AUTH', POLLER_VERBOSITY_DEBUG); } else { $referer = $config['url_path'] . 'index.php'; cacti_log(sprintf("DEBUG: Referer Short Circuit to '%s'", 'index.php'), false, 'AUTH', POLLER_VERBOSITY_DEBUG); } $referer .= ($newtheme ? (strpos($referer, '?') === false ? '?':'&') . 'newtheme=1':''); /* Strip out the login from the referer if present */ $referer = str_replace('?action=login', '', $referer); if (api_user_realm_auth(auth_basename($referer))) { header('Location: ' . $referer); } elseif (!is_realm_allowed(8)) { cacti_log(sprintf("DEBUG: Referer Overridden Due to Permissions to '%s'", 'graph_view.php'), false, 'AUTH', POLLER_VERBOSITY_DEBUG); header('Location: graph_view.php'); } else { cacti_log(sprintf("DEBUG: Referer Overridden Due to Permissions to '%s'", 'index.php'), false, 'AUTH', POLLER_VERBOSITY_DEBUG); header('Location: index.php'); } break; case '2': /* default console page */ if (!is_realm_allowed(8)) { header('Location: ' . $config['url_path'] . 'graph_view.php' . ($newtheme ? '?newtheme=1':'')); } else { header('Location: ' . $config['url_path'] . 'index.php' . ($newtheme ? '?newtheme=1':'')); } break; case '3': /* default graph page */ header('Location: ' . $config['url_path'] . 'graph_view.php' . ($newtheme ? '?newtheme=1':'')); break; default: api_plugin_hook_function('login_options_navigate', $login_opts); } exit; } /** * auth_basename - provides a URL knowledgable basename function * * @param (string) $referer - a URL that will included a basename * * @return (string) the file name without the arguments */ function auth_basename($referer) { $parts = explode('?', $referer); return basename($parts[0]); } /** * auth_login_create_user_from_template - creates a new user account from a template account * if there is an error that would block login, the function set's the globals * error and error_msg to inform the caller not to proceed with the login. * in special cases, such as basic auth, the function will print out a custom * error message and exit. * * @param (string) $username - The username to use for the copy * @param (int) $realm - The login realm to use for the copy * * @return (array|void) The copied new user account details or void on exit */ function auth_login_create_user_from_template($username, $realm) { global $error, $error_msg; cacti_log("NOTE: User '" . $username . "' does not exist, copying template user", false, 'AUTH'); $user = array(); $user_template = db_fetch_row_prepared('SELECT * FROM user_auth WHERE id = ?', array(get_template_account($username))); /* check that template user exists */ if (!empty($user_template)) { if ($realm == 3) { // This is an ldap login /* get user CN*/ $cn_full_name = read_config_option('cn_full_name'); $cn_email = read_config_option('cn_email'); if ($cn_full_name != '' || $cn_email != '') { $ldap_cn_search_response = cacti_ldap_search_cn($username, array($cn_full_name, $cn_email)); if (isset($ldap_cn_search_response['cn'])) { $data_override = array(); if (array_key_exists($cn_full_name, $ldap_cn_search_response['cn'])) { $data_override['full_name'] = $ldap_cn_search_response['cn'][$cn_full_name]; } else { $data_override['full_name'] = ''; } if (array_key_exists($cn_email, $ldap_cn_search_response['cn'])) { $data_override['email_address'] = $ldap_cn_search_response['cn'][$cn_email]; } else { $data_override['email_address'] = ''; } user_copy($user_template['username'], $username, $user_template['realm'], $realm, false, $data_override); } else { $ldap_response = (isset($ldap_cn_search_response[0]) ? $ldap_cn_search_response[0] : '(no response given)'); $ldap_code = (isset($ldap_cn_search_response['error_num']) ? $ldap_cn_search_response['error_num'] : '(no code given)'); cacti_log('LOGIN: Email Address and Full Name fields not found, reason: ' . $ldap_response . 'code: ' . $ldap_code, false, 'AUTH'); user_copy($user_template['username'], $username, $user_template['realm'], $realm); } } else { user_copy($user_template['username'], $username, $user_template['realm'], $realm); } } else { user_copy($user_template['username'], $username, $user_template['realm'], $realm); } /* requery newly created user */ $user = db_fetch_row_prepared('SELECT * FROM user_auth WHERE username = ? AND realm = ?', array($username, $realm)); } else { /* error */ $error = true; $error_msg = __('Access Denied! Template user id %s does not exist. Please contact your Administrator.', read_config_option('user_template')); cacti_log("LOGIN FAILED: Template user id '" . read_config_option('user_template') . "' does not exist.", false, 'AUTH'); if ($auth_method == 2) { auth_display_custom_error_message($error_msg); exit; } } return $user; } /** * check_reset_no_authentication - Attempts to switch Cacti from No Authentication to Local * authentication, or generate an error on failure through the globals error, and error_msg. * * @param (int) $auth_method - The current auth method * * @return (bool) Returns false on failure to set user account, otherwise redirects */ function check_reset_no_authentication($auth_method) { global $error, $error_msg; if ($auth_method == 0) { $admin_id = db_execute_prepared('SELECT id FROM user_auth WHERE id = ?', array(read_config_option('admin_user'))); cacti_log('Admin User (' . read_config_option('admin_user') . ' vs ' . $admin_id . ')', true, 'AUTH_NONE', POLLER_VERBOSITY_DEVDBG); if (!$admin_id) { $admin_sql_query = 'SELECT TOP 1 id FROM ( SELECT ua.id FROM user_auth AS ua INNER JOIN user_auth_realm AS uar ON uar.user_id = ua.id WHERE uar.realm_id = ?'; $admin_sql_params = array(15); if (db_table_exists('user_auth_group_realm')) { $admin_sql_query .= ' UNION SELECT ua.id FROM user_auth AS ua INNER JOIN user_auth_group_members AS uagm ON uagm.user_id = ua.id INNER JOIN user_auth_group AS uag ON uag.id = uagm.group_id INNER JOIN user_auth_group_realm AS uagr ON uagr.group_id=uag.group_id WHERE uag.enabled="on" AND ua.enabled="on" AND uagr.realm_id = ?'; $admin_sql_params[] = 15; } $admin_sql_query .= ' ) AS id'; cacti_log('SQL query ' . $admin_sql_query, true, 'AUTH_NONE', POLLER_VERBOSITY_DEVDBG); cacti_log('SQL param ' . implode(',', $admin_sql_params), true, 'AUTH_NONE', POLLER_VERBOSITY_DEVDBG); $admin_id = db_fetch_cell_prepared($admin_sql_query, $admin_sql_params); cacti_log('SQL result ' . $admin_id, true, 'AUTH_NONE', POLLER_VERBOSITY_DEVDBG); } if (!$admin_id) { $admin_id = db_fetch_cell('SELECT id FROM user_auth WHERE username = \'admin\''); cacti_log('Final attempt ' . $admin_id, true, 'AUTH_NONE', POLLER_VERBOSITY_DEVDBG); } if (!$admin_id) { $error = true; $error_msg = __('Authentication was previously not set. Attempted to set to Local Authentication, but no Administrative account was found.'); return false; } // Authentication method is currently set to none // lets switch this to basic and allow setting of // a password. db_execute_prepared("UPDATE user_auth SET password = '', must_change_password = 'on', password_change = 'on' WHERE id = ?", array($admin_id)); $auth_method = 1; set_config_option('auth_method', $auth_method, true); $_SESSION['sess_user_id'] = $admin_id; $_SESSION['sess_change_password'] = true; header ('Location: ' . $config['url_path'] . 'auth_changepassword.php?action=force&ref=' . (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : 'index.php')); exit; } }