mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
fix: Improve authentication load time and security (#6615)
* fix: minimize session open time page/graphs speedup part 2 Write close the session as soon as we no longer need to write to it. Prevents the session from blocking other requests. Do not run through full authentication functions if the session is already authenticated. Removes password from the session as well as some items to prevent session fixation from #4608. WARNING: This will cause issues for ad/ldap users who do not have a bind user configured! * Do no erase username when using cookie auth. Properly close the session in ajax_setresolution.php * write close the session as soon as possible in ajax_setresolution.php * Remove session regeneration. It is not compatible with the current code and would require more changes. * Totally refactor authentication. Extract code to functions for re-use and improved readability * Use exceptions for authentication and error logging Tested: mysql, ad_auth with and without bind user * fix a couple scrutinizer issues * fix reauthenticate in radius
This commit is contained in:
35
LibreNMS/Exceptions/AuthenticationException.php
Normal file
35
LibreNMS/Exceptions/AuthenticationException.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* AuthenticationException.php
|
||||
*
|
||||
* Throw this when authentication fails. Sets the default message to 'Invalid credentials' so we don't leak any info.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @package LibreNMS
|
||||
* @link http://librenms.org
|
||||
* @copyright 2017 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace LibreNMS\Exceptions;
|
||||
|
||||
class AuthenticationException extends \Exception
|
||||
{
|
||||
// Redefine the exception so message defaults to a generic 'Invalid credentials'
|
||||
public function __construct($message = 'Invalid credentials', $code = 0, \Exception $previous = null)
|
||||
{
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,13 @@
|
||||
<?php
|
||||
|
||||
session_start();
|
||||
if (isset($_REQUEST['width']) and isset($_REQUEST['height'])) {
|
||||
|
||||
if (isset($_REQUEST['width'], $_REQUEST['height'])) {
|
||||
$_SESSION['screen_width'] = $_REQUEST['width'];
|
||||
$_SESSION['screen_height'] = $_REQUEST['height'];
|
||||
}
|
||||
|
||||
session_write_close();
|
||||
|
||||
header('Content-type: text/plain');
|
||||
echo $_SESSION['screen_width'];
|
||||
echo $_SESSION['screen_height'];
|
||||
echo $_SESSION['screen_width'] . 'x' . $_SESSION['screen_height'];
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
use Phpass\PasswordHash;
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
|
||||
@ini_set('session.use_only_cookies', 1);
|
||||
@ini_set('session.cookie_httponly', 1);
|
||||
|
||||
session_start();
|
||||
ini_set('session.use_only_cookies', 1);
|
||||
ini_set('session.cookie_httponly', 1);
|
||||
ini_set('session.use_strict_mode', 1); // php >= 5.5.2
|
||||
ini_set('session.use_trans_sid', 0); // insecure feature, be sure it is disabled
|
||||
|
||||
// Preflight checks
|
||||
if (!is_dir($config['rrd_dir'])) {
|
||||
@@ -23,91 +23,68 @@ if (!is_writable($config['temp_dir'])) {
|
||||
// Clear up any old sessions
|
||||
dbDelete('session', '`session_expiry` < ?', array(time()));
|
||||
|
||||
session_start();
|
||||
|
||||
if ($vars['page'] == 'logout' && $_SESSION['authenticated']) {
|
||||
dbInsert(array('user' => $_SESSION['username'], 'address' => get_client_ip(), 'result' => 'Logged Out'), 'authlog');
|
||||
dbDelete('session', '`session_username` = ? AND session_value = ?', array($_SESSION['username'], $_COOKIE['sess_id']));
|
||||
unset($_SESSION);
|
||||
unset($_COOKIE);
|
||||
setcookie('sess_id', '', (time() - 60 * 60 * 24 * $config['auth_remember']), '/');
|
||||
setcookie('token', '', (time() - 60 * 60 * 24 * $config['auth_remember']), '/');
|
||||
setcookie('auth', '', (time() - 60 * 60 * 24 * $config['auth_remember']), '/');
|
||||
session_destroy();
|
||||
$auth_message = 'Logged Out';
|
||||
log_out_user();
|
||||
header('Location: ' . $config['base_url']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// We are only interested in login details passed via POST.
|
||||
if (isset($_POST['username']) && isset($_POST['password'])) {
|
||||
$_SESSION['username'] = clean($_POST['username']);
|
||||
$_SESSION['password'] = $_POST['password'];
|
||||
} elseif (isset($_GET['username']) && isset($_GET['password'])) {
|
||||
$_SESSION['username'] = clean($_GET['username']);
|
||||
$_SESSION['password'] = $_GET['password'];
|
||||
} elseif (isset($_SERVER['REMOTE_USER'])) {
|
||||
$_SESSION['username'] = $_SERVER['REMOTE_USER'];
|
||||
} elseif (isset($_SERVER['PHP_AUTH_USER']) && $config['auth_mechanism'] === 'http-auth') {
|
||||
$_SESSION['username'] = $_SERVER['PHP_AUTH_USER'];
|
||||
}
|
||||
|
||||
if (!isset($config['auth_mechanism'])) {
|
||||
$config['auth_mechanism'] = 'mysql';
|
||||
}
|
||||
|
||||
$auth_success = 0;
|
||||
|
||||
if ((isset($_SESSION['username'])) || (isset($_COOKIE['sess_id'],$_COOKIE['token']))) {
|
||||
if (reauthenticate($_COOKIE['sess_id'], $_COOKIE['token']) || authenticate($_SESSION['username'], $_SESSION['password'])) {
|
||||
$_SESSION['userlevel'] = get_userlevel($_SESSION['username']);
|
||||
$_SESSION['user_id'] = get_userid($_SESSION['username']);
|
||||
if (!$_SESSION['authenticated']) {
|
||||
if ($config['twofactor'] === true && !isset($_SESSION['twofactor'])) {
|
||||
include_once $config['install_dir'].'/html/includes/authentication/twofactor.lib.php';
|
||||
twofactor_auth();
|
||||
}
|
||||
|
||||
if (!$config['twofactor'] || $_SESSION['twofactor']) {
|
||||
$_SESSION['authenticated'] = true;
|
||||
dbInsert(array('user' => $_SESSION['username'], 'address' => get_client_ip(), 'result' => 'Logged In'), 'authlog');
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_POST['remember'])) {
|
||||
$sess_id = session_id();
|
||||
$token = strgen();
|
||||
$auth = strgen();
|
||||
$hasher = new PasswordHash(8, false);
|
||||
$token_id = $_SESSION['username'].'|'.$hasher->HashPassword($_SESSION['username'].$token);
|
||||
// If we have been asked to remember the user then set the relevant cookies and create a session in the DB.
|
||||
setcookie('sess_id', $sess_id, (time() + 60 * 60 * 24 * $config['auth_remember']), '/', null, false, true);
|
||||
setcookie('token', $token_id, (time() + 60 * 60 * 24 * $config['auth_remember']), '/', null, false, true);
|
||||
setcookie('auth', $auth, (time() + 60 * 60 * 24 * $config['auth_remember']), '/', null, false, true);
|
||||
dbInsert(array('session_username' => $_SESSION['username'], 'session_value' => $sess_id, 'session_token' => $token, 'session_auth' => $auth, 'session_expiry' => time() + 60 * 60 * 24 * $config['auth_remember']), 'session');
|
||||
}
|
||||
|
||||
if (isset($_COOKIE['sess_id'],$_COOKIE['token'],$_COOKIE['auth'])) {
|
||||
// If we have the remember me cookies set then update session expiry times to keep us logged in.
|
||||
$sess_id = session_id();
|
||||
dbUpdate(array('session_value' => $sess_id, 'session_expiry' => time() + 60 * 60 * 24 * $config['auth_remember']), 'session', 'session_auth=?', array($_COOKIE['auth']));
|
||||
setcookie('sess_id', $sess_id, (time() + 60 * 60 * 24 * $config['auth_remember']), '/', null, false, true);
|
||||
setcookie('token', $_COOKIE['token'], (time() + 60 * 60 * 24 * $config['auth_remember']), '/', null, false, true);
|
||||
setcookie('auth', $_COOKIE['auth'], (time() + 60 * 60 * 24 * $config['auth_remember']), '/', null, false, true);
|
||||
}
|
||||
|
||||
$permissions = permissions_cache($_SESSION['user_id']);
|
||||
if (isset($_POST['username'])) {
|
||||
// Trim the trailing slash off of base_url and concatenate the (relative) REQUEST_URI
|
||||
header('Location: '.rtrim($config['base_url'], '/').$_SERVER['REQUEST_URI'], true, 303);
|
||||
exit;
|
||||
}
|
||||
} elseif (isset($_SESSION['username'])) {
|
||||
global $auth_error;
|
||||
if (isset($auth_error)) {
|
||||
$auth_message = $auth_error;
|
||||
try {
|
||||
if (isset($_SESSION['authenticated']) && $_SESSION['authenticated']) {
|
||||
// session authenticated already
|
||||
log_in_user();
|
||||
} else {
|
||||
$auth_message = 'Authentication Failed';
|
||||
// try authentication methods
|
||||
|
||||
// cookie authentication
|
||||
if (isset($_COOKIE['sess_id'], $_COOKIE['token']) &&
|
||||
reauthenticate(clean($_COOKIE['sess_id']), clean($_COOKIE['token']))
|
||||
) {
|
||||
log_in_user();
|
||||
|
||||
// update cookie expiry times
|
||||
set_remember_me();
|
||||
} else {
|
||||
// collect username and password
|
||||
$password = null;
|
||||
if (isset($_REQUEST['username']) && isset($_REQUEST['password'])) {
|
||||
$username = clean($_REQUEST['username']);
|
||||
$password = $_REQUEST['password'];
|
||||
} elseif (isset($_SERVER['REMOTE_USER'])) {
|
||||
$username = $_SERVER['REMOTE_USER'];
|
||||
} elseif (isset($_SERVER['PHP_AUTH_USER']) && $config['auth_mechanism'] === 'http-auth') {
|
||||
$username = $_SERVER['PHP_AUTH_USER'];
|
||||
}
|
||||
unset($_SESSION['authenticated']);
|
||||
dbInsert(array('user' => $_SESSION['username'], 'address' => get_client_ip(), 'result' => 'Authentication Failure'), 'authlog');
|
||||
|
||||
// form authentication
|
||||
if (isset($username) && authenticate($username, $password)) {
|
||||
$_SESSION['username'] = $username;
|
||||
log_in_user();
|
||||
|
||||
// set cookie if requested
|
||||
if (isset($_POST['remember'])) {
|
||||
set_remember_me();
|
||||
}
|
||||
|
||||
// redirect to original uri or home page.
|
||||
header('Location: '.rtrim($config['base_url'], '/').$_SERVER['REQUEST_URI'], true, 303);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (AuthenticationException $ae) {
|
||||
$auth_message = $ae->getMessage();
|
||||
if ($debug) {
|
||||
$auth_message .= '<br /> ' . $ae->getFile() . ': ' . $ae->getLine();
|
||||
}
|
||||
|
||||
dbInsert(
|
||||
array('user' => $_SESSION['username'], 'address' => get_client_ip(), 'result' => $auth_message),
|
||||
'authlog'
|
||||
);
|
||||
log_out_user($auth_message);
|
||||
}
|
||||
|
||||
session_write_close();
|
||||
unset($username, $password);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
|
||||
use Phpass\PasswordHash;
|
||||
|
||||
// easier to rewrite for Active Directory than to bash it into existing LDAP implementation
|
||||
|
||||
// disable certificate checking before connect if required
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
|
||||
if (isset($config['auth_ad_check_certificates']) &&
|
||||
!$config['auth_ad_check_certificates']) {
|
||||
putenv('LDAPTLS_REQCERT=never');
|
||||
@@ -14,6 +14,7 @@ if (isset($config['auth_ad_debug']) && $config['auth_ad_debug']) {
|
||||
ldap_set_option(null, LDAP_OPT_DEBUG_LEVEL, 7);
|
||||
}
|
||||
|
||||
$ad_init = false; // this variable tracks if bind has been called so we don't call it multiple times
|
||||
$ldap_connection = @ldap_connect($config['auth_ad_url']);
|
||||
|
||||
// disable referrals and force ldap version to 3
|
||||
@@ -21,18 +22,14 @@ $ldap_connection = @ldap_connect($config['auth_ad_url']);
|
||||
ldap_set_option($ldap_connection, LDAP_OPT_REFERRALS, 0);
|
||||
ldap_set_option($ldap_connection, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
|
||||
// Bind to AD
|
||||
if (!ad_bind($ldap_connection)) {
|
||||
d_echo(ldap_error($ldap_connection) . PHP_EOL);
|
||||
}
|
||||
|
||||
function authenticate($username, $password)
|
||||
{
|
||||
global $config, $ldap_connection, $auth_error;
|
||||
global $config, $ldap_connection, $ad_init;
|
||||
|
||||
if ($ldap_connection) {
|
||||
// bind with sAMAccountName instead of full LDAP DN
|
||||
if ($username && $password && ldap_bind($ldap_connection, "{$username}@{$config['auth_ad_domain']}", $password)) {
|
||||
$ad_init = true;
|
||||
// group membership in one of the configured groups is required
|
||||
if (isset($config['auth_ad_require_groupmembership']) &&
|
||||
$config['auth_ad_require_groupmembership']) {
|
||||
@@ -49,72 +46,57 @@ function authenticate($username, $password)
|
||||
$group_cn = get_cn($entry);
|
||||
if (isset($config['auth_ad_groups'][$group_cn]['level'])) {
|
||||
// user is in one of the defined groups
|
||||
adduser($username);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// failed to find user
|
||||
if (isset($config['auth_ad_debug']) && $config['auth_ad_debug']) {
|
||||
if ($entries['count'] == 0) {
|
||||
$auth_error = 'No groups found for user, check base dn';
|
||||
throw new AuthenticationException('No groups found for user, check base dn');
|
||||
} else {
|
||||
$auth_error = 'User is not in one of the required groups';
|
||||
throw new AuthenticationException('User is not in one of the required groups');
|
||||
}
|
||||
} else {
|
||||
$auth_error = 'Invalid credentials';
|
||||
}
|
||||
|
||||
return 0;
|
||||
throw new AuthenticationException();
|
||||
} else {
|
||||
// group membership is not required and user is valid
|
||||
adduser($username);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($password) || $password == '') {
|
||||
$auth_error = "A password is required";
|
||||
throw new AuthenticationException('A password is required');
|
||||
} elseif (isset($config['auth_ad_debug']) && $config['auth_ad_debug']) {
|
||||
ldap_get_option($ldap_connection, LDAP_OPT_DIAGNOSTIC_MESSAGE, $extended_error);
|
||||
$auth_error = ldap_error($ldap_connection).'<br />'.$extended_error;
|
||||
} else {
|
||||
$auth_error = ldap_error($ldap_connection);
|
||||
throw new AuthenticationException(ldap_error($ldap_connection).'<br />'.$extended_error);
|
||||
}
|
||||
|
||||
return 0;
|
||||
throw new AuthenticationException(ldap_error($ldap_connection));
|
||||
}
|
||||
|
||||
function reauthenticate($sess_id, $token)
|
||||
{
|
||||
global $ldap_connection;
|
||||
global $config, $ldap_connection;
|
||||
|
||||
if (ad_bind($ldap_connection, false)) {
|
||||
if (ad_bind($ldap_connection, false, true)) {
|
||||
$sess_id = clean($sess_id);
|
||||
$token = clean($token);
|
||||
list($username, $hash) = explode('|', $token);
|
||||
|
||||
if (!user_exists($username)) {
|
||||
d_echo("$username is not a valid AD user\n");
|
||||
return 0;
|
||||
if (isset($config['auth_ad_debug']) && $config['auth_ad_debug']) {
|
||||
throw new AuthenticationException("$username is not a valid AD user");
|
||||
}
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
$session = dbFetchRow(
|
||||
"SELECT * FROM `session` WHERE `session_username`=? AND session_value=?",
|
||||
array($username, $sess_id),
|
||||
true
|
||||
);
|
||||
$hasher = new PasswordHash(8, false);
|
||||
if ($hasher->CheckPassword($username . $session['session_token'], $hash)) {
|
||||
$_SESSION['username'] = $username;
|
||||
return 1;
|
||||
} else {
|
||||
d_echo("Reauthenticate token check failed\n");
|
||||
return 0;
|
||||
}
|
||||
return check_remember_me($sess_id, $token);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -154,6 +136,7 @@ function user_exists_in_db($username)
|
||||
function user_exists($username)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
ad_bind($ldap_connection); // make sure we called bind
|
||||
|
||||
$search = ldap_search(
|
||||
$ldap_connection,
|
||||
@@ -175,6 +158,7 @@ function user_exists($username)
|
||||
function get_userlevel($username)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
ad_bind($ldap_connection); // make sure we called bind
|
||||
|
||||
$userlevel = 0;
|
||||
if (isset($config['auth_ad_require_groupmembership']) && $config['auth_ad_require_groupmembership'] == 0) {
|
||||
@@ -209,6 +193,7 @@ function get_userlevel($username)
|
||||
function get_userid($username)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
ad_bind($ldap_connection); // make sure we called bind
|
||||
|
||||
$attributes = array('objectsid');
|
||||
$search = ldap_search(
|
||||
@@ -229,6 +214,7 @@ function get_userid($username)
|
||||
function get_domain_sid()
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
ad_bind($ldap_connection); // make sure we called bind
|
||||
|
||||
// Extract only the domain components
|
||||
$dn_candidate = preg_replace('/^.*?DC=/i', 'DC=', $config['auth_ad_base_dn']);
|
||||
@@ -246,6 +232,7 @@ function get_domain_sid()
|
||||
function get_user($user_id)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
ad_bind($ldap_connection); // make sure we called bind
|
||||
|
||||
$domain_sid = get_domain_sid();
|
||||
|
||||
@@ -274,8 +261,9 @@ function deluser($userid)
|
||||
function get_userlist()
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
$userlist = array();
|
||||
ad_bind($ldap_connection); // make sure we called bind
|
||||
|
||||
$userlist = array();
|
||||
$ldap_groups = get_group_list();
|
||||
|
||||
foreach ($ldap_groups as $ldap_group) {
|
||||
@@ -337,6 +325,7 @@ function update_user($user_id, $realname, $level, $can_modify_passwd, $email)
|
||||
function get_email($username)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
ad_bind($ldap_connection); // make sure we called bind
|
||||
|
||||
$attributes = array('mail');
|
||||
$search = ldap_search(
|
||||
@@ -353,6 +342,7 @@ function get_email($username)
|
||||
function get_fullname($username)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
ad_bind($ldap_connection); // make sure we called bind
|
||||
|
||||
$attributes = array('name');
|
||||
$result = ldap_search(
|
||||
@@ -401,7 +391,7 @@ function get_group_list()
|
||||
function get_dn($samaccountname)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
|
||||
ad_bind($ldap_connection); // make sure we called bind
|
||||
|
||||
$attributes = array('dn');
|
||||
$result = ldap_search(
|
||||
@@ -446,14 +436,20 @@ function sid_from_ldap($sid)
|
||||
*
|
||||
* @param resource $connection the ldap connection resource
|
||||
* @param bool $allow_anonymous attempt anonymous bind if bind user isn't available
|
||||
* @param bool $force force rebind
|
||||
* @return bool success or failure
|
||||
*/
|
||||
function ad_bind($connection, $allow_anonymous = true)
|
||||
function ad_bind($connection, $allow_anonymous = true, $force = false)
|
||||
{
|
||||
global $config;
|
||||
global $config, $ad_init;
|
||||
|
||||
if ($ad_init && !$force) {
|
||||
return true; // bind already attempted
|
||||
}
|
||||
|
||||
if (isset($config['auth_ad_binduser']) && isset($config['auth_ad_bindpassword'])) {
|
||||
// With specified bind user
|
||||
if (isset($config['auth_ad_binduser'], $config['auth_ad_bindpassword'])) {
|
||||
$ad_init = true;
|
||||
return ldap_bind(
|
||||
$connection,
|
||||
"${config['auth_ad_binduser']}@${config['auth_ad_domain']}",
|
||||
@@ -461,8 +457,9 @@ function ad_bind($connection, $allow_anonymous = true)
|
||||
);
|
||||
}
|
||||
|
||||
if ($allow_anonymous) {
|
||||
// Anonymous
|
||||
if ($allow_anonymous) {
|
||||
$ad_init = true;
|
||||
return ldap_bind($connection);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
|
||||
if (! isset($_SESSION['username'])) {
|
||||
$_SESSION['username'] = '';
|
||||
}
|
||||
@@ -47,17 +49,16 @@ function authenticate($username, $password)
|
||||
}
|
||||
|
||||
$_SESSION['username'] = $config['http_auth_guest'];
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
|
||||
function reauthenticate($sess_id, $token)
|
||||
{
|
||||
// not supported so return 0
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
179
html/includes/authentication/functions.php
Normal file
179
html/includes/authentication/functions.php
Normal file
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
/**
|
||||
* functions.php
|
||||
*
|
||||
* authentication functions
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @package LibreNMS
|
||||
* @link http://librenms.org
|
||||
* @copyright 2017 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
use Phpass\PasswordHash;
|
||||
|
||||
/**
|
||||
* Log out the user, unset cookies, destroy the session
|
||||
*
|
||||
* @param string $message The logout message.
|
||||
*/
|
||||
function log_out_user($message = 'Logged Out')
|
||||
{
|
||||
global $auth_message;
|
||||
|
||||
dbInsert(array('user' => $_SESSION['username'], 'address' => get_client_ip(), 'result' => 'Logged Out'), 'authlog');
|
||||
|
||||
clear_remember_me($_SESSION['username']);
|
||||
|
||||
unset($_SESSION['authenticated']);
|
||||
session_destroy();
|
||||
|
||||
$auth_message = $message; // global variable used to display a message to the user
|
||||
}
|
||||
|
||||
/**
|
||||
* Log in the user and set up a few login tasks
|
||||
* $_SESSION['username'] must be set prior to calling this function
|
||||
* If twofactor authentication is enabled, it will be checked here.
|
||||
*
|
||||
* If everything goes well, $_SESSION['authenticated'] will be true after this function completes.
|
||||
* @return bool If the user was successfully logged in.
|
||||
* @throws AuthenticationException if anything failed why trying to log in
|
||||
*/
|
||||
function log_in_user()
|
||||
{
|
||||
global $config, $permissions;
|
||||
|
||||
// set up variables, but don't override existing ones (ad anonymous bind can only get user_id at login)
|
||||
if (!isset($_SESSION['userlevel'])) {
|
||||
$_SESSION['userlevel'] = get_userlevel($_SESSION['username']);
|
||||
}
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
$_SESSION['user_id'] = get_userid($_SESSION['username']);
|
||||
}
|
||||
|
||||
// check for valid user_id
|
||||
if ($_SESSION['user_id'] === false || $_SESSION['user_id'] < 0) {
|
||||
throw new AuthenticationException('Invalid Credentials');
|
||||
}
|
||||
|
||||
// check twofactor
|
||||
if ($config['twofactor'] === true && !isset($_SESSION['twofactor'])) {
|
||||
include_once $config['install_dir'].'/html/includes/authentication/twofactor.lib.php';
|
||||
twofactor_auth();
|
||||
}
|
||||
|
||||
// if two factor isn't enabled or it has passed already ware are logged in
|
||||
if (!$config['twofactor'] || $_SESSION['twofactor']) {
|
||||
$_SESSION['authenticated'] = true;
|
||||
dbInsert(array('user' => $_SESSION['username'], 'address' => get_client_ip(), 'result' => 'Logged In'), 'authlog');
|
||||
} else {
|
||||
throw new AuthenticationException('Two-Factor Auth Failed');
|
||||
}
|
||||
|
||||
// populate the permissions cache
|
||||
$permissions = permissions_cache($_SESSION['user_id']);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or update the remember me cookie
|
||||
* If setting a new cookie, $_SESSION['username'] must be set
|
||||
*/
|
||||
function set_remember_me()
|
||||
{
|
||||
global $config;
|
||||
$sess_id = session_id();
|
||||
$expiration = time() + 60 * 60 * 24 * $config['auth_remember'];
|
||||
|
||||
$db_entry = array(
|
||||
'session_value' => $sess_id,
|
||||
'session_expiry' => $expiration,
|
||||
);
|
||||
|
||||
if (isset($_COOKIE['token'], $_COOKIE['auth'])) {
|
||||
$token_id = $_COOKIE['token'];
|
||||
$auth = $_COOKIE['auth'];
|
||||
dbUpdate($db_entry, 'session', 'session_auth=?', array($_COOKIE['auth']));
|
||||
} else {
|
||||
$token = strgen();
|
||||
$auth = strgen();
|
||||
$hasher = new PasswordHash(8, false);
|
||||
$token_id = $_SESSION['username'] . '|' . $hasher->HashPassword($_SESSION['username'] . $token);
|
||||
|
||||
$db_entry['session_username'] = $_SESSION['username'];
|
||||
$db_entry['session_token'] = $token;
|
||||
$db_entry['session_auth'] = $auth;
|
||||
dbInsert($db_entry, 'session');
|
||||
}
|
||||
|
||||
setcookie('sess_id', $sess_id, $expiration, '/', null, false, true);
|
||||
setcookie('token', $token_id, $expiration, '/', null, false, true);
|
||||
setcookie('auth', $auth, $expiration, '/', null, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the remember me cookie
|
||||
* If the cookie is valid, $_SESSION['username'] will be set
|
||||
*
|
||||
* @param string $sess_id sess_id cookie value
|
||||
* @param string $token token cookie value
|
||||
* @return bool is the remember me token valid
|
||||
* @throws AuthenticationException thrown if the cookie is invalid
|
||||
*/
|
||||
function check_remember_me($sess_id, $token)
|
||||
{
|
||||
list($uname, $hash) = explode('|', $token);
|
||||
$session = dbFetchRow(
|
||||
"SELECT * FROM `session` WHERE `session_username`=? AND `session_value`=?",
|
||||
array($uname, $sess_id),
|
||||
true
|
||||
);
|
||||
|
||||
$hasher = new PasswordHash(8, false);
|
||||
if ($hasher->CheckPassword($uname . $session['session_token'], $hash)) {
|
||||
$_SESSION['username'] = $uname;
|
||||
return true;
|
||||
}
|
||||
|
||||
clear_remember_me($uname);
|
||||
throw new AuthenticationException('Cookie invalid, please log in.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear remember cookie and remove our database record
|
||||
*
|
||||
* @param $username
|
||||
*/
|
||||
function clear_remember_me($username)
|
||||
{
|
||||
global $config;
|
||||
|
||||
dbDelete(
|
||||
'session',
|
||||
'`session_username` = ? AND `session_value` = ?',
|
||||
array($username, $_COOKIE['sess_id'])
|
||||
);
|
||||
|
||||
unset($_COOKIE);
|
||||
|
||||
$time = time() - 60 * 60 * 24 * $config['auth_remember']; // time in the past to make sure
|
||||
setcookie('sess_id', '', $time, '/');
|
||||
setcookie('token', '', $time, '/');
|
||||
setcookie('auth', '', $time, '/');
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
use Phpass\PasswordHash;
|
||||
|
||||
if (!isset($_SESSION['username'])) {
|
||||
@@ -16,19 +17,19 @@ function authenticate($username, $password)
|
||||
|
||||
$row = @dbFetchRow('SELECT username FROM `users` WHERE `username`=?', array($_SESSION['username']));
|
||||
if (isset($row['username']) && $row['username'] == $_SESSION['username']) {
|
||||
return 1;
|
||||
return true;
|
||||
} else {
|
||||
$_SESSION['username'] = $config['http_auth_guest'];
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
|
||||
function reauthenticate($sess_id = '', $token = '')
|
||||
function reauthenticate($sess_id, $token)
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
*/
|
||||
|
||||
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
|
||||
if (! isset($_SESSION['username'])) {
|
||||
$_SESSION['username'] = '';
|
||||
}
|
||||
@@ -71,21 +73,20 @@ function authenticate($username, $password)
|
||||
$_SESSION['username'] = mres($_SERVER['REMOTE_USER']);
|
||||
|
||||
if (user_exists($_SESSION['username'])) {
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
$_SESSION['username'] = $config['http_auth_guest'];
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
|
||||
function reauthenticate($sess_id = '', $token = '')
|
||||
function reauthenticate($sess_id, $token)
|
||||
{
|
||||
// Not supported
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
|
||||
$ldap_connection = @ldap_connect($config['auth_ldap_server'], $config['auth_ldap_port']);
|
||||
|
||||
if ($config['auth_ldap_starttls'] && ($config['auth_ldap_starttls'] == 'optional' || $config['auth_ldap_starttls'] == 'require')) {
|
||||
@@ -15,14 +17,18 @@ function authenticate($username, $password)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
|
||||
if ($username && $ldap_connection) {
|
||||
if (!$ldap_connection) {
|
||||
throw new AuthenticationException('Unable to connect to ldap server');
|
||||
}
|
||||
|
||||
if ($username) {
|
||||
if ($config['auth_ldap_version']) {
|
||||
ldap_set_option($ldap_connection, LDAP_OPT_PROTOCOL_VERSION, $config['auth_ldap_version']);
|
||||
}
|
||||
|
||||
if ($password && ldap_bind($ldap_connection, $config['auth_ldap_prefix'].$username.$config['auth_ldap_suffix'], $password)) {
|
||||
if (!$config['auth_ldap_group']) {
|
||||
return 1;
|
||||
return true;
|
||||
} else {
|
||||
$ldap_groups = get_group_list();
|
||||
foreach ($ldap_groups as $ldap_group) {
|
||||
@@ -33,26 +39,26 @@ function authenticate($username, $password)
|
||||
get_membername($username)
|
||||
);
|
||||
if ($ldap_comparison === true) {
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif (!isset($password) || $password == '') {
|
||||
echo 'A password is required';
|
||||
} else {
|
||||
echo ldap_error($ldap_connection);
|
||||
}
|
||||
} else {
|
||||
// FIXME return a warning that LDAP couldn't connect?
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (!isset($password) || $password == '') {
|
||||
throw new AuthenticationException('A password is required');
|
||||
}
|
||||
|
||||
throw new AuthenticationException(ldap_error($ldap_connection));
|
||||
}
|
||||
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
|
||||
function reauthenticate($sess_id, $token)
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
use Phpass\PasswordHash;
|
||||
|
||||
function authenticate($username, $password)
|
||||
@@ -14,7 +15,7 @@ function authenticate($username, $password)
|
||||
changepassword($username, $password);
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
} elseif (substr($row['password'], 0, 3) == '$1$') {
|
||||
$row_type = dbFetchRow('DESCRIBE users password');
|
||||
if ($row_type['Type'] == 'varchar(60)') {
|
||||
@@ -26,27 +27,17 @@ function authenticate($username, $password)
|
||||
|
||||
$hasher = new PasswordHash(8, false);
|
||||
if ($hasher->CheckPassword($password, $row['password'])) {
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
}//end if
|
||||
|
||||
return 0;
|
||||
throw new AuthenticationException();
|
||||
}//end authenticate()
|
||||
|
||||
|
||||
function reauthenticate($sess_id, $token)
|
||||
{
|
||||
$sess_id = clean($sess_id);
|
||||
$token = clean($token);
|
||||
list($uname,$hash) = explode('|', $token);
|
||||
$session = dbFetchRow("SELECT * FROM `session` WHERE `session_username` = '$uname' AND session_value='$sess_id'", array(), true);
|
||||
$hasher = new PasswordHash(8, false);
|
||||
if ($hasher->CheckPassword($uname.$session['session_token'], $hash)) {
|
||||
$_SESSION['username'] = $uname;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return check_remember_me($sess_id, $token);
|
||||
}//end reauthenticate()
|
||||
|
||||
|
||||
|
||||
@@ -1,33 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Dapphp\Radius\Radius;
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
use Phpass\PasswordHash;
|
||||
|
||||
/** @var Radius $radius */
|
||||
$radius = new Radius($config['radius']['hostname'], $config['radius']['secret'], $config['radius']['suffix'], $config['radius']['timeout'], $config['radius']['port']);
|
||||
|
||||
function authenticate($username, $password)
|
||||
{
|
||||
global $config, $radius, $debug;
|
||||
global $radius, $debug;
|
||||
|
||||
if (empty($username)) {
|
||||
return 0;
|
||||
} else {
|
||||
throw new AuthenticationException('Username is required');
|
||||
}
|
||||
|
||||
if ($debug) {
|
||||
$radius->SetDebug(true);
|
||||
}
|
||||
$rad = $radius->AccessRequest($username, $password);
|
||||
if ($rad === true) {
|
||||
adduser($username);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
$radius->setDebug(true);
|
||||
}
|
||||
|
||||
if ($radius->accessRequest($username, $password) === true) {
|
||||
adduser($username, $password);
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
function reauthenticate($sess_id, $token)
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -308,7 +308,7 @@ echo('<h5>Powered by <a href="' . $config['project_home'] . '" target="_blank" r
|
||||
<?php
|
||||
}
|
||||
|
||||
if (dbFetchCell("SELECT COUNT(`device_id`) FROM `devices` WHERE `last_polled` <= DATE_ADD(NOW(), INTERVAL - 15 minute) AND `ignore` = 0 AND `disabled` = 0 AND status = 1", array()) > 0) {
|
||||
if (dbFetchCell("SELECT COUNT(*) FROM `devices` WHERE `last_polled` <= DATE_ADD(NOW(), INTERVAL - 15 minute) AND `ignore` = 0 AND `disabled` = 0 AND status = 1", array()) > 0) {
|
||||
$msg_box[] = array('type' => 'warning', 'message' => "<a href=\"poll-log/filter=unpolled/\">It appears as though you have some devices that haven't completed polling within the last 15 minutes, you may want to check that out :)</a>",'title' => 'Devices unpolled');
|
||||
}
|
||||
|
||||
|
||||
@@ -165,6 +165,7 @@ if (module_selected('auth', $init_modules) ||
|
||||
$config['allow_unauth_graphs'] != true
|
||||
)
|
||||
) {
|
||||
require $install_dir . '/html/includes/authentication/functions.php';
|
||||
require $install_dir . '/html/includes/authenticate.inc.php';
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user