mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
refactor: Refactored authorizers to classes (#7497)
* Refactored authorizers to classes * Merge changes for #7335 * ! fix php 5.3 incompatibility * Update ADAuthorizationAuthorizer.php * Fix get_user -> getUser * Rename AuthorizerFactory to Auth, fix interface missing functions * Add phpdocs to all interface methods and normalize the names a bit. * Re-work auth_test.php AD bind tests to work properly with the new class. Reflection is not the nicest tool, but I think it is appropriate here. Handle exceptions more nicely in auth_test.php * Restore AD getUseList fix Not sure how it got removed * fix auth_test.php style
This commit is contained in:
354
LibreNMS/Authentication/ADAuthorizationAuthorizer.php
Normal file
354
LibreNMS/Authentication/ADAuthorizationAuthorizer.php
Normal file
@ -0,0 +1,354 @@
|
||||
<?php
|
||||
|
||||
namespace LibreNMS\Authentication;
|
||||
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
|
||||
class ADAuthorizationAuthorizer extends AuthorizerBase
|
||||
{
|
||||
protected $ldap_connection;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if (! isset($_SESSION['username'])) {
|
||||
$_SESSION['username'] = '';
|
||||
}
|
||||
|
||||
// Disable certificate checking before connect if required
|
||||
if (Config::has('auth_ad_check_certificates') &&
|
||||
Config::get('auth_ad_check_certificates') == 0) {
|
||||
putenv('LDAPTLS_REQCERT=never');
|
||||
};
|
||||
|
||||
// Set up connection to LDAP server
|
||||
$this->ldap_connection = @ldap_connect(Config::get('auth_ad_url'));
|
||||
if (! $this->ldap_connection) {
|
||||
echo '<h2>Fatal error while connecting to AD url ' . Config::get('auth_ad_url') . ': ' . ldap_error($this->ldap_connection) . '</h2>';
|
||||
exit;
|
||||
}
|
||||
|
||||
// disable referrals and force ldap version to 3
|
||||
ldap_set_option($this->ldap_connection, LDAP_OPT_REFERRALS, 0);
|
||||
ldap_set_option($this->ldap_connection, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
|
||||
// Bind to AD
|
||||
if (Config::has('auth_ad_binduser') && Config::has('auth_ad_bindpassword')) {
|
||||
// With specified bind user
|
||||
if (! ldap_bind($this->ldap_connection, Config::get('auth_ad_binduser') . '@' . Config::get('auth_ad_domain'), Config::get('auth_ad_bindpassword'))) {
|
||||
echo ldap_error($this->ldap_connection);
|
||||
}
|
||||
} else {
|
||||
// Anonymous
|
||||
if (! ldap_bind($this->ldap_connection)) {
|
||||
echo ldap_error($this->ldap_connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function authenticate($username, $password)
|
||||
{
|
||||
if (isset($_SERVER['REMOTE_USER'])) {
|
||||
$_SESSION['username'] = mres($_SERVER['REMOTE_USER']);
|
||||
|
||||
if ($this->userExists($_SESSION['username'])) {
|
||||
$this->addUser($username, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
$_SESSION['username'] = Config::get('http_auth_guest');
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
public function addUser($username, $password, $level = 0, $email = '', $realname = '', $can_modify_passwd = 0, $description = '')
|
||||
{
|
||||
// Check to see if user is already added in the database
|
||||
if (!$this->userExists($username)) {
|
||||
$userid = dbInsert(array('username' => $username, 'realname' => $realname, 'email' => $email, 'descr' => $description, 'level' => $level, 'can_modify_passwd' => $can_modify_passwd, 'user_id' => $this->getUserid($username)), 'users');
|
||||
if ($userid == false) {
|
||||
return false;
|
||||
} else {
|
||||
foreach (dbFetchRows('select notifications.* from notifications where not exists( select 1 from notifications_attribs where notifications.notifications_id = notifications_attribs.notifications_id and notifications_attribs.user_id = ?) order by notifications.notifications_id desc', array($userid)) as $notif) {
|
||||
dbInsert(array('notifications_id'=>$notif['notifications_id'],'user_id'=>$userid,'key'=>'read','value'=>1), 'notifications_attribs');
|
||||
}
|
||||
}
|
||||
return $userid;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected function userExistsInDb($username)
|
||||
{
|
||||
$return = dbFetchCell('SELECT COUNT(*) FROM users WHERE username = ?', array($username), true);
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function userExists($username, $throw_exception = false)
|
||||
{
|
||||
if ($this->authLdapSessionCacheGet('user_exists')) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$search = ldap_search(
|
||||
$this->ldap_connection,
|
||||
Config::get('auth_ad_base_dn'),
|
||||
get_auth_ad_user_filter($username),
|
||||
array('samaccountname')
|
||||
);
|
||||
$entries = ldap_get_entries($this->ldap_connection, $search);
|
||||
|
||||
if ($entries['count']) {
|
||||
/*
|
||||
* Cache positiv result as this will result in more queries which we
|
||||
* want to speed up.
|
||||
*/
|
||||
$this->authLdapSessionCacheSet('user_exists', 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public function getUserlevel($username)
|
||||
{
|
||||
$userlevel = $this->authLdapSessionCacheGet('userlevel');
|
||||
if ($userlevel) {
|
||||
return $userlevel;
|
||||
} else {
|
||||
$userlevel = 0;
|
||||
}
|
||||
|
||||
// Find all defined groups $username is in
|
||||
$search = ldap_search(
|
||||
$this->ldap_connection,
|
||||
Config::get('auth_ad_base_dn'),
|
||||
get_auth_ad_user_filter($username),
|
||||
array('memberOf')
|
||||
);
|
||||
$entries = ldap_get_entries($this->ldap_connection, $search);
|
||||
|
||||
// Loop the list and find the highest level
|
||||
foreach ($entries[0]['memberof'] as $entry) {
|
||||
$group_cn = $this->getCn($entry);
|
||||
$auth_ad_groups = Config::get('auth_ad_groups');
|
||||
if ($auth_ad_groups[$group_cn]['level'] > $userlevel) {
|
||||
$userlevel = $auth_ad_groups[$group_cn]['level'];
|
||||
}
|
||||
}
|
||||
|
||||
$this->authLdapSessionCacheSet('userlevel', $userlevel);
|
||||
return $userlevel;
|
||||
}
|
||||
|
||||
|
||||
public function getUserid($username)
|
||||
{
|
||||
$user_id = $this->authLdapSessionCacheGet('userid');
|
||||
if (isset($user_id)) {
|
||||
return $user_id;
|
||||
} else {
|
||||
$user_id = -1;
|
||||
}
|
||||
|
||||
$attributes = array('objectsid');
|
||||
$search = ldap_search(
|
||||
$this->ldap_connection,
|
||||
Config::get('auth_ad_base_dn'),
|
||||
get_auth_ad_user_filter($username),
|
||||
$attributes
|
||||
);
|
||||
$entries = ldap_get_entries($this->ldap_connection, $search);
|
||||
|
||||
if ($entries['count']) {
|
||||
$user_id = preg_replace('/.*-(\d+)$/', '$1', $this->sidFromLdap($entries[0]['objectsid'][0]));
|
||||
}
|
||||
|
||||
$this->authLdapSessionCacheSet('userid', $user_id);
|
||||
return $user_id;
|
||||
}
|
||||
|
||||
|
||||
public function deleteUser($userid)
|
||||
{
|
||||
dbDelete('bill_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('devices_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('ports_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('users_prefs', '`user_id` = ?', array($userid));
|
||||
dbDelete('users', '`user_id` = ?', array($userid));
|
||||
return dbDelete('users', '`user_id` = ?', array($userid));
|
||||
}
|
||||
|
||||
|
||||
public function getUserlist()
|
||||
{
|
||||
$userlist = array();
|
||||
$userhash = array();
|
||||
|
||||
$ldap_groups = $this->getGroupList();
|
||||
|
||||
foreach ($ldap_groups as $ldap_group) {
|
||||
$search_filter = "(memberOf=$ldap_group)";
|
||||
if (Config::get('auth_ad_user_filter')) {
|
||||
$search_filter = "(&{" . Config::get('auth_ad_user_filter') . $search_filter . ")";
|
||||
}
|
||||
$search = ldap_search($this->ldap_connection, Config::get('auth_ad_base_dn'), $search_filter, array('samaccountname','displayname','objectsid','mail'));
|
||||
$results = ldap_get_entries($this->ldap_connection, $search);
|
||||
|
||||
foreach ($results as $result) {
|
||||
if (isset($result['samaccountname'][0])) {
|
||||
$userid = preg_replace(
|
||||
'/.*-(\d+)$/',
|
||||
'$1',
|
||||
$this->sidFromLdap($result['objectsid'][0])
|
||||
);
|
||||
|
||||
// don't make duplicates, user may be member of more than one group
|
||||
$userhash[$result['samaccountname'][0]] = array(
|
||||
'realname' => $result['displayName'][0],
|
||||
'user_id' => $userid,
|
||||
'email' => $result['mail'][0]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array_keys($userhash) as $key) {
|
||||
$userlist[] = array(
|
||||
'username' => $key,
|
||||
'realname' => $userhash[$key]['realname'],
|
||||
'user_id' => $userhash[$key]['user_id'],
|
||||
'email' => $userhash[$key]['email']
|
||||
);
|
||||
}
|
||||
|
||||
return $userlist;
|
||||
}
|
||||
|
||||
public function getUser($user_id)
|
||||
{
|
||||
// not supported so return 0
|
||||
return dbFetchRow('SELECT * FROM `users` WHERE `user_id` = ?', array($user_id), true);
|
||||
}
|
||||
|
||||
|
||||
public function updateUser($user_id, $realname, $level, $can_modify_passwd, $email)
|
||||
{
|
||||
dbUpdate(array('realname' => $realname, 'can_modify_passwd' => $can_modify_passwd, 'email' => $email), 'users', '`user_id` = ?', array($user_id));
|
||||
}
|
||||
|
||||
|
||||
protected function getFullname($username)
|
||||
{
|
||||
$attributes = array('name');
|
||||
$result = ldap_search(
|
||||
$this->ldap_connection,
|
||||
Config::get('auth_ad_base_dn'),
|
||||
get_auth_ad_user_filter($username),
|
||||
$attributes
|
||||
);
|
||||
$entries = ldap_get_entries($this->ldap_connection, $result);
|
||||
if ($entries['count'] > 0) {
|
||||
$membername = $entries[0]['name'][0];
|
||||
} else {
|
||||
$membername = $username;
|
||||
}
|
||||
|
||||
return $membername;
|
||||
}
|
||||
|
||||
|
||||
public function getGroupList()
|
||||
{
|
||||
$ldap_groups = array();
|
||||
|
||||
// show all Active Directory Users by default
|
||||
$default_group = 'Users';
|
||||
|
||||
if (Config::has('auth_ad_group')) {
|
||||
if (Config::get('auth_ad_group') !== $default_group) {
|
||||
$ldap_groups[] = Config::get('auth_ad_group');
|
||||
}
|
||||
}
|
||||
|
||||
if (!Config::has('auth_ad_groups') && !Config::has('auth_ad_group')) {
|
||||
$ldap_groups[] = $this->getDn($default_group);
|
||||
}
|
||||
|
||||
foreach (Config::get('auth_ad_groups') as $key => $value) {
|
||||
$ldap_groups[] = $this->getDn($key);
|
||||
}
|
||||
|
||||
return $ldap_groups;
|
||||
}
|
||||
|
||||
protected function getDn($samaccountname)
|
||||
{
|
||||
$attributes = array('dn');
|
||||
$result = ldap_search(
|
||||
$this->ldap_connection,
|
||||
Config::get('auth_ad_base_dn'),
|
||||
get_auth_ad_group_filter($samaccountname),
|
||||
$attributes
|
||||
);
|
||||
$entries = ldap_get_entries($this->ldap_connection, $result);
|
||||
if ($entries['count'] > 0) {
|
||||
return $entries[0]['dn'];
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
protected function getCn($dn)
|
||||
{
|
||||
preg_match('/[^,]*/', $dn, $matches, PREG_OFFSET_CAPTURE, 3);
|
||||
return $matches[0][0];
|
||||
}
|
||||
|
||||
protected function sidFromLdap($sid)
|
||||
{
|
||||
$sidHex = unpack('H*hex', $sid);
|
||||
$subAuths = unpack('H2/H2/n/N/V*', $sid);
|
||||
$revLevel = hexdec(substr($sidHex, 0, 2));
|
||||
$authIdent = hexdec(substr($sidHex, 4, 12));
|
||||
return 'S-'.$revLevel.'-'.$authIdent.'-'.implode('-', $subAuths);
|
||||
}
|
||||
|
||||
protected function authLdapSessionCacheGet($attr)
|
||||
{
|
||||
$ttl = 300;
|
||||
if (Config::get('auth_ldap_cache_ttl')) {
|
||||
$ttl = Config::get('auth_ldap_cache_ttl');
|
||||
}
|
||||
|
||||
// auth_ldap cache present in this session?
|
||||
if (! isset($_SESSION['auth_ldap'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$cache = $_SESSION['auth_ldap'];
|
||||
|
||||
// $attr present in cache?
|
||||
if (! isset($cache[$attr])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Value still valid?
|
||||
if (time() - $cache[$attr]['last_updated'] >= $ttl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $cache[$attr]['value'];
|
||||
}
|
||||
|
||||
|
||||
protected function authLdapSessionCacheSet($attr, $value)
|
||||
{
|
||||
$_SESSION['auth_ldap'][$attr]['value'] = $value;
|
||||
$_SESSION['auth_ldap'][$attr]['last_updated'] = time();
|
||||
}
|
||||
}
|
451
LibreNMS/Authentication/ActiveDirectoryAuthorizer.php
Normal file
451
LibreNMS/Authentication/ActiveDirectoryAuthorizer.php
Normal file
@ -0,0 +1,451 @@
|
||||
<?php
|
||||
|
||||
// easier to rewrite for Active Directory than to bash it into existing LDAP implementation
|
||||
|
||||
// disable certificate checking before connect if required
|
||||
namespace LibreNMS\Authentication;
|
||||
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
|
||||
class ActiveDirectoryAuthorizer extends AuthorizerBase
|
||||
{
|
||||
protected $ldap_connection;
|
||||
protected $ad_init;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if (Config::has('auth_ad_check_certificates') &&
|
||||
!Config::get('auth_ad_check_certificates')) {
|
||||
putenv('LDAPTLS_REQCERT=never');
|
||||
};
|
||||
|
||||
if (Config::has('auth_ad_check_certificates') && Config::get('auth_ad_debug')) {
|
||||
ldap_set_option(null, LDAP_OPT_DEBUG_LEVEL, 7);
|
||||
}
|
||||
|
||||
$this->ad_init = false; // this variable tracks if bind has been called so we don't call it multiple times
|
||||
$this->ldap_connection = @ldap_connect(Config::get('auth_ad_url'));
|
||||
|
||||
// disable referrals and force ldap version to 3
|
||||
ldap_set_option($this->ldap_connection, LDAP_OPT_REFERRALS, 0);
|
||||
ldap_set_option($this->ldap_connection, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
}
|
||||
|
||||
public function authenticate($username, $password)
|
||||
{
|
||||
if ($this->ldap_connection) {
|
||||
// bind with sAMAccountName instead of full LDAP DN
|
||||
if ($username && $password && ldap_bind($this->ldap_connection, $username . '@' . Config::get('auth_ad_domain'), $password)) {
|
||||
$this->ad_init = true;
|
||||
// group membership in one of the configured groups is required
|
||||
if (Config::get('auth_ad_require_groupmembership', true)) {
|
||||
// cycle through defined groups, test for memberOf-ship
|
||||
foreach (Config::get('auth_ad_groups', array()) as $group => $level) {
|
||||
if ($this->userInGroup($username, $group)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// failed to find user
|
||||
if (Config::get('auth_ad_debug', false)) {
|
||||
throw new AuthenticationException('User is not in one of the required groups or user/group is outside the base dn');
|
||||
}
|
||||
|
||||
throw new AuthenticationException();
|
||||
} else {
|
||||
// group membership is not required and user is valid
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($password) || $password == '') {
|
||||
throw new AuthenticationException('A password is required');
|
||||
} elseif (Config::get('auth_ad_debug', false)) {
|
||||
ldap_get_option($this->ldap_connection, LDAP_OPT_DIAGNOSTIC_MESSAGE, $extended_error);
|
||||
throw new AuthenticationException(ldap_error($this->ldap_connection).'<br />'.$extended_error);
|
||||
}
|
||||
|
||||
throw new AuthenticationException(ldap_error($this->ldap_connection));
|
||||
}
|
||||
|
||||
public function reauthenticate($sess_id, $token)
|
||||
{
|
||||
if ($this->adBind(false, true)) {
|
||||
$sess_id = clean($sess_id);
|
||||
$token = clean($token);
|
||||
list($username, $hash) = explode('|', $token);
|
||||
|
||||
if (!$this->userExists($username)) {
|
||||
if (Config::get('auth_ad_debug', false)) {
|
||||
throw new AuthenticationException("$username is not a valid AD user");
|
||||
}
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
return $this->checkRememberMe($sess_id, $token);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected function userInGroup($username, $groupname)
|
||||
{
|
||||
// check if user is member of the given group or nested groups
|
||||
|
||||
|
||||
$search_filter = "(&(objectClass=group)(cn=$groupname))";
|
||||
|
||||
// get DN for auth_ad_group
|
||||
$search = ldap_search(
|
||||
$this->ldap_connection,
|
||||
Config::get('auth_ad_base_dn'),
|
||||
$search_filter,
|
||||
array("cn")
|
||||
);
|
||||
$result = ldap_get_entries($this->ldap_connection, $search);
|
||||
|
||||
if ($result == false || $result['count'] !== 1) {
|
||||
if (Config::get('auth_ad_debug', false)) {
|
||||
if ($result == false) {
|
||||
// FIXME: what went wrong?
|
||||
throw new AuthenticationException("LDAP query failed for group '$groupname' using filter '$search_filter'");
|
||||
} elseif ($result['count'] == 0) {
|
||||
throw new AuthenticationException("Failed to find group matching '$groupname' using filter '$search_filter'");
|
||||
} elseif ($result['count'] > 1) {
|
||||
throw new AuthenticationException("Multiple groups returned for '$groupname' using filter '$search_filter'");
|
||||
}
|
||||
}
|
||||
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
$group_dn = $result[0]["dn"];
|
||||
|
||||
$search = ldap_search(
|
||||
$this->ldap_connection,
|
||||
Config::get('auth_ad_base_dn'),
|
||||
// add 'LDAP_MATCHING_RULE_IN_CHAIN to the user filter to search for $username in nested $group_dn
|
||||
// limiting to "DN" for shorter array
|
||||
"(&" . get_auth_ad_user_filter($username) . "(memberOf:1.2.840.113556.1.4.1941:=$group_dn))",
|
||||
array("DN")
|
||||
);
|
||||
$entries = ldap_get_entries($this->ldap_connection, $search);
|
||||
|
||||
return ($entries["count"] > 0);
|
||||
}
|
||||
|
||||
protected function userExistsInDb($username)
|
||||
{
|
||||
$return = dbFetchCell('SELECT COUNT(*) FROM users WHERE username = ?', array($username), true);
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function userExists($username, $throw_exception = false)
|
||||
{
|
||||
$this->adBind(); // make sure we called bind
|
||||
|
||||
$search = ldap_search(
|
||||
$this->ldap_connection,
|
||||
Config::get('auth_ad_base_dn'),
|
||||
get_auth_ad_user_filter($username),
|
||||
array('samaccountname')
|
||||
);
|
||||
$entries = ldap_get_entries($this->ldap_connection, $search);
|
||||
|
||||
|
||||
if ($entries['count']) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public function getUserlevel($username)
|
||||
{
|
||||
$this->adBind(); // make sure we called bind
|
||||
|
||||
$userlevel = 0;
|
||||
if (!Config::get('auth_ad_require_groupmembership', true)) {
|
||||
if (Config::get('auth_ad_global_read', false)) {
|
||||
$userlevel = 5;
|
||||
}
|
||||
}
|
||||
|
||||
// cycle through defined groups, test for memberOf-ship
|
||||
foreach (Config::get('auth_ad_groups', array()) as $group => $level) {
|
||||
try {
|
||||
if ($this->userInGroup($username, $group)) {
|
||||
$userlevel = max($userlevel, $level['level']);
|
||||
}
|
||||
} catch (AuthenticationException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
return $userlevel;
|
||||
}
|
||||
|
||||
|
||||
public function getUserid($username)
|
||||
{
|
||||
$this->adBind(); // make sure we called bind
|
||||
|
||||
$attributes = array('objectsid');
|
||||
$search = ldap_search(
|
||||
$this->ldap_connection,
|
||||
Config::get('auth_ad_base_dn'),
|
||||
get_auth_ad_user_filter($username),
|
||||
$attributes
|
||||
);
|
||||
$entries = ldap_get_entries($this->ldap_connection, $search);
|
||||
|
||||
if ($entries['count']) {
|
||||
return $this->getUseridFromSid($this->sidFromLdap($entries[0]['objectsid'][0]));
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected function getDomainSid()
|
||||
{
|
||||
$this->adBind(); // make sure we called bind
|
||||
|
||||
// Extract only the domain components
|
||||
$dn_candidate = preg_replace('/^.*?DC=/i', 'DC=', Config::get('auth_ad_base_dn'));
|
||||
|
||||
$search = ldap_read(
|
||||
$this->ldap_connection,
|
||||
$dn_candidate,
|
||||
'(objectClass=*)',
|
||||
array('objectsid')
|
||||
);
|
||||
$entry = ldap_get_entries($this->ldap_connection, $search);
|
||||
return substr($this->sidFromLdap($entry[0]['objectsid'][0]), 0, 41);
|
||||
}
|
||||
|
||||
public function getUser($user_id)
|
||||
{
|
||||
$this->adBind(); // make sure we called bind
|
||||
|
||||
$domain_sid = $this->getDomainSid();
|
||||
|
||||
$search_filter = "(&(objectcategory=person)(objectclass=user)(objectsid=$domain_sid-$user_id))";
|
||||
$attributes = array('samaccountname', 'displayname', 'objectsid', 'mail');
|
||||
$search = ldap_search($this->ldap_connection, Config::get('auth_ad_base_dn'), $search_filter, $attributes);
|
||||
$entry = ldap_get_entries($this->ldap_connection, $search);
|
||||
|
||||
if (isset($entry[0]['samaccountname'][0])) {
|
||||
return $this->userFromAd($entry[0]);
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
public function deleteUser($userid)
|
||||
{
|
||||
dbDelete('bill_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('devices_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('ports_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('users_prefs', '`user_id` = ?', array($userid));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public function getUserlist()
|
||||
{
|
||||
$this->adBind(); // make sure we called bind
|
||||
|
||||
$userlist = array();
|
||||
$ldap_groups = $this->getGroupList();
|
||||
|
||||
foreach ($ldap_groups as $ldap_group) {
|
||||
$search_filter = "(memberOf=$ldap_group)";
|
||||
if (Config::get('auth_ad_user_filter')) {
|
||||
$search_filter = "(&" . Config::get('auth_ad_user_filter') . $search_filter .")";
|
||||
}
|
||||
$attributes = array('samaccountname', 'displayname', 'objectsid', 'mail');
|
||||
$search = ldap_search($this->ldap_connection, Config::get('auth_ad_base_dn'), $search_filter, $attributes);
|
||||
$results = ldap_get_entries($this->ldap_connection, $search);
|
||||
|
||||
foreach ($results as $result) {
|
||||
if (isset($result['samaccountname'][0])) {
|
||||
$userlist[$result['samaccountname'][0]] = $this->userFromAd($result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array_values($userlist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a user array from an AD LDAP entry
|
||||
* Must have the attributes: objectsid, samaccountname, displayname, mail
|
||||
* @internal
|
||||
*
|
||||
* @param $entry
|
||||
* @return array
|
||||
*/
|
||||
protected function userFromAd($entry)
|
||||
{
|
||||
return array(
|
||||
'user_id' => $this->getUseridFromSid($this->sidFromLdap($entry['objectsid'][0])),
|
||||
'username' => $entry['samaccountname'][0],
|
||||
'realname' => $entry['displayname'][0],
|
||||
'email' => $entry['mail'][0],
|
||||
'descr' => '',
|
||||
'level' => $this->getUserlevel($entry['samaccountname'][0]),
|
||||
'can_modify_passwd' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
protected function getEmail($username)
|
||||
{
|
||||
$this->adBind(); // make sure we called bind
|
||||
|
||||
$attributes = array('mail');
|
||||
$search = ldap_search(
|
||||
$this->ldap_connection,
|
||||
Config::get('auth_ad_base_dn'),
|
||||
get_auth_ad_user_filter($username),
|
||||
$attributes
|
||||
);
|
||||
$result = ldap_get_entries($this->ldap_connection, $search);
|
||||
unset($result[0]['mail']['count']);
|
||||
return current($result[0]['mail']);
|
||||
}
|
||||
|
||||
protected function getFullname($username)
|
||||
{
|
||||
$this->adBind(); // make sure we called bind
|
||||
|
||||
$attributes = array('name');
|
||||
$result = ldap_search(
|
||||
$this->ldap_connection,
|
||||
Config::get('auth_ad_base_dn'),
|
||||
get_auth_ad_user_filter($username),
|
||||
$attributes
|
||||
);
|
||||
$entries = ldap_get_entries($this->ldap_connection, $result);
|
||||
if ($entries['count'] > 0) {
|
||||
$membername = $entries[0]['name'][0];
|
||||
} else {
|
||||
$membername = $username;
|
||||
}
|
||||
|
||||
return $membername;
|
||||
}
|
||||
|
||||
|
||||
public function getGroupList()
|
||||
{
|
||||
$ldap_groups = array();
|
||||
|
||||
// show all Active Directory Users by default
|
||||
$default_group = 'Users';
|
||||
|
||||
if (Config::has('auth_ad_group')) {
|
||||
if (Config::get('auth_ad_group') !== $default_group) {
|
||||
$ldap_groups[] = Config::get('auth_ad_group');
|
||||
}
|
||||
}
|
||||
|
||||
if (!Config::has('auth_ad_groups') && !Config::has('auth_ad_group')) {
|
||||
$ldap_groups[] = $this->getDn($default_group);
|
||||
}
|
||||
|
||||
foreach (Config::get('auth_ad_groups') as $key => $value) {
|
||||
$ldap_groups[] = $this->getDn($key);
|
||||
}
|
||||
|
||||
return $ldap_groups;
|
||||
}
|
||||
|
||||
protected function getDn($samaccountname)
|
||||
{
|
||||
$this->adBind(); // make sure we called bind
|
||||
|
||||
$attributes = array('dn');
|
||||
$result = ldap_search(
|
||||
$this->ldap_connection,
|
||||
Config::get('auth_ad_base_dn'),
|
||||
get_auth_ad_group_filter($samaccountname),
|
||||
$attributes
|
||||
);
|
||||
$entries = ldap_get_entries($this->ldap_connection, $result);
|
||||
if ($entries['count'] > 0) {
|
||||
return $entries[0]['dn'];
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
protected function getCn($dn)
|
||||
{
|
||||
$dn = str_replace('\\,', '~C0mmA~', $dn);
|
||||
preg_match('/[^,]*/', $dn, $matches, PREG_OFFSET_CAPTURE, 3);
|
||||
return str_replace('~C0mmA~', ',', $matches[0][0]);
|
||||
}
|
||||
|
||||
protected function getUseridFromSid($sid)
|
||||
{
|
||||
return preg_replace('/.*-(\d+)$/', '$1', $sid);
|
||||
}
|
||||
|
||||
protected function sidFromLdap($sid)
|
||||
{
|
||||
$sidUnpacked = unpack('H*hex', $sid);
|
||||
$sidHex = array_shift($sidUnpacked);
|
||||
$subAuths = unpack('H2/H2/n/N/V*', $sid);
|
||||
$revLevel = hexdec(substr($sidHex, 0, 2));
|
||||
$authIdent = hexdec(substr($sidHex, 4, 12));
|
||||
return 'S-'.$revLevel.'-'.$authIdent.'-'.implode('-', $subAuths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind to AD with the bind user if available, otherwise anonymous bind
|
||||
* @internal
|
||||
*
|
||||
* @param bool $allow_anonymous attempt anonymous bind if bind user isn't available
|
||||
* @param bool $force force rebind
|
||||
* @return bool success or failure
|
||||
*/
|
||||
protected function adBind($allow_anonymous = true, $force = false)
|
||||
{
|
||||
if ($this->ad_init && !$force) {
|
||||
return true; // bind already attempted
|
||||
}
|
||||
|
||||
// set timeout
|
||||
ldap_set_option(
|
||||
$this->ldap_connection,
|
||||
LDAP_OPT_NETWORK_TIMEOUT,
|
||||
Config::has('auth_ad_timeout') ? Config::has('auth_ad_timeout') : 5
|
||||
);
|
||||
|
||||
// With specified bind user
|
||||
if (Config::has('auth_ad_binduser') && Config::has('auth_ad_bindpassword')) {
|
||||
$this->ad_init = true;
|
||||
$bind = ldap_bind(
|
||||
$this->ldap_connection,
|
||||
Config::get('auth_ad_binduser') . '@' . Config::get('auth_ad_domain'),
|
||||
Config::get('auth_ad_bindpassword')
|
||||
);
|
||||
ldap_set_option($this->ldap_connection, LDAP_OPT_NETWORK_TIMEOUT, -1); // restore timeout
|
||||
return $bind;
|
||||
}
|
||||
|
||||
$bind = false;
|
||||
|
||||
// Anonymous
|
||||
if ($allow_anonymous) {
|
||||
$this->ad_init = true;
|
||||
$bind = ldap_bind($this->ldap_connection);
|
||||
}
|
||||
|
||||
ldap_set_option($this->ldap_connection, LDAP_OPT_NETWORK_TIMEOUT, -1); // restore timeout
|
||||
return $bind;
|
||||
}
|
||||
}
|
39
LibreNMS/Authentication/Auth.php
Normal file
39
LibreNMS/Authentication/Auth.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace LibreNMS\Authentication;
|
||||
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Interfaces\Authentication\Authorizer;
|
||||
|
||||
class Auth
|
||||
{
|
||||
protected static $_instance;
|
||||
|
||||
/**
|
||||
* Gets the authorizer based on the config
|
||||
*
|
||||
* @return Authorizer
|
||||
*/
|
||||
public static function get()
|
||||
{
|
||||
if (!static::$_instance) {
|
||||
$configToClassMap = array(
|
||||
'mysql' => 'LibreNMS\Authentication\MysqlAuthorizer',
|
||||
'active_directory' => 'LibreNMS\Authentication\ActiveDirectoryAuthorizer',
|
||||
'ldap' => 'LibreNMS\Authentication\LdapAuthorizer',
|
||||
'radius' => 'LibreNMS\Authentication\RadiusAuthorizer',
|
||||
'http-auth' => 'LibreNMS\Authentication\HttpAuthAuthorizer',
|
||||
'ad-authorization' => 'LibreNMS\Authentication\ADAuthorizationAuthorizer',
|
||||
'ldap-authorization' => 'LibreNMS\Authentication\LdapAuthorizationAuthorizer',
|
||||
);
|
||||
|
||||
$auth_mechanism = Config::get('auth_mechanism');
|
||||
if (!isset($configToClassMap[$auth_mechanism])) {
|
||||
throw new \RuntimeException($auth_mechanism . ' not found as auth_mechanism');
|
||||
}
|
||||
|
||||
static::$_instance = new $configToClassMap[$auth_mechanism]();
|
||||
}
|
||||
return static::$_instance;
|
||||
}
|
||||
}
|
260
LibreNMS/Authentication/AuthorizerBase.php
Normal file
260
LibreNMS/Authentication/AuthorizerBase.php
Normal file
@ -0,0 +1,260 @@
|
||||
<?php
|
||||
/**
|
||||
* AuthorizerBase.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>
|
||||
*/
|
||||
namespace LibreNMS\Authentication;
|
||||
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Interfaces\Authentication\Authorizer;
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
use Phpass\PasswordHash;
|
||||
|
||||
abstract class AuthorizerBase implements Authorizer
|
||||
{
|
||||
protected static $HAS_AUTH_USERMANAGEMENT = 0;
|
||||
protected static $CAN_UPDATE_USER = 0;
|
||||
|
||||
/**
|
||||
* Log out the user, unset cookies, destroy the session
|
||||
*
|
||||
* @param string $message The logout message.
|
||||
*/
|
||||
public function logOutUser($message = 'Logged Out')
|
||||
{
|
||||
global $auth_message;
|
||||
|
||||
dbInsert(array('user' => $_SESSION['username'], 'address' => get_client_ip(), 'result' => 'Logged Out'), 'authlog');
|
||||
|
||||
$this->clearRememberMe($_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
|
||||
*/
|
||||
public function logInUser()
|
||||
{
|
||||
// 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'] = $this->getUserlevel($_SESSION['username']);
|
||||
}
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
$_SESSION['user_id'] = $this->getUserid($_SESSION['username']);
|
||||
}
|
||||
|
||||
// check for valid user_id
|
||||
if ($_SESSION['user_id'] === false || $_SESSION['user_id'] < 0) {
|
||||
throw new AuthenticationException('Invalid Credentials');
|
||||
}
|
||||
|
||||
if (!$this->sessionAuthenticated()) {
|
||||
// check twofactor
|
||||
if (Config::get('twofactor') === true && !isset($_SESSION['twofactor'])) {
|
||||
if (TwoFactor::showForm()) {
|
||||
return false; // not done yet, one more cycle to show the 2fa form
|
||||
}
|
||||
}
|
||||
|
||||
// if two factor isn't enabled or it has passed already ware are logged in
|
||||
if (!Config::get('twofactor') || $_SESSION['twofactor']) {
|
||||
$_SESSION['authenticated'] = true;
|
||||
dbInsert(array('user' => $_SESSION['username'], 'address' => get_client_ip(), 'result' => 'Logged In'), 'authlog');
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->sessionAuthenticated()) {
|
||||
$this->setRememberMe();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the session is authenticated
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function sessionAuthenticated()
|
||||
{
|
||||
return isset($_SESSION['authenticated']) && $_SESSION['authenticated'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or update the remember me cookie if $_SESSION['remember'] is set
|
||||
* If setting a new cookie, $_SESSION['username'] must be set
|
||||
*/
|
||||
protected function setRememberMe()
|
||||
{
|
||||
if (!isset($_SESSION['remember'])) {
|
||||
return;
|
||||
}
|
||||
unset($_SESSION['remember']);
|
||||
|
||||
$sess_id = session_id();
|
||||
$expiration = time() + 60 * 60 * 24 * Config::get('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, Config::get('secure_cookies'), true);
|
||||
setcookie('token', $token_id, $expiration, '/', null, Config::get('secure_cookies'), true);
|
||||
setcookie('auth', $auth, $expiration, '/', null, Config::get('secure_cookies'), 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
|
||||
*/
|
||||
protected function checkRememberMe($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;
|
||||
}
|
||||
|
||||
$this->clearRememberMe($uname);
|
||||
throw new AuthenticationException('Cookie invalid, please log in.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear remember cookie and remove our database record
|
||||
*
|
||||
* @param $username
|
||||
*/
|
||||
protected function clearRememberMe($username)
|
||||
{
|
||||
dbDelete(
|
||||
'session',
|
||||
'`session_username` = ? AND `session_value` = ?',
|
||||
array($username, $_COOKIE['sess_id'])
|
||||
);
|
||||
|
||||
unset($_COOKIE);
|
||||
|
||||
$time = time() - 60 * 60 * 24 * Config::get('auth_remember'); // time in the past to make sure
|
||||
|
||||
setcookie('sess_id', '', $time, '/', null, Config::get('secure_cookies'));
|
||||
setcookie('token', '', $time, '/', null, Config::get('secure_cookies'));
|
||||
setcookie('auth', '', $time, '/', null, Config::get('secure_cookies'));
|
||||
}
|
||||
|
||||
|
||||
abstract public function authenticate($username, $password);
|
||||
|
||||
public function reauthenticate($sess_id, $token)
|
||||
{
|
||||
//not supported by default
|
||||
return false;
|
||||
}
|
||||
|
||||
public function canUpdatePasswords($username = '')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function changePassword($username, $newpassword)
|
||||
{
|
||||
//not supported by default
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function canManageUsers()
|
||||
{
|
||||
return static::$HAS_AUTH_USERMANAGEMENT;
|
||||
}
|
||||
|
||||
public function addUser($username, $password, $level = 0, $email = '', $realname = '', $can_modify_passwd = 0, $description = '')
|
||||
{
|
||||
//not supported by default
|
||||
return 0;
|
||||
}
|
||||
|
||||
abstract public function userExists($username, $throw_exception = false);
|
||||
|
||||
abstract public function getUserlevel($username);
|
||||
|
||||
abstract public function getUserid($username);
|
||||
|
||||
abstract public function getUser($user_id);
|
||||
|
||||
public function deleteUser($userid)
|
||||
{
|
||||
//not supported by default
|
||||
return 0;
|
||||
}
|
||||
|
||||
abstract public function getUserlist();
|
||||
|
||||
public function canUpdateUsers()
|
||||
{
|
||||
return static::$CAN_UPDATE_USER;
|
||||
}
|
||||
|
||||
public function updateUser($user_id, $realname, $level, $can_modify_passwd, $email)
|
||||
{
|
||||
//not supported by default
|
||||
return 0;
|
||||
}
|
||||
}
|
106
LibreNMS/Authentication/HttpAuthAuthorizer.php
Normal file
106
LibreNMS/Authentication/HttpAuthAuthorizer.php
Normal file
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace LibreNMS\Authentication;
|
||||
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
use Phpass\PasswordHash;
|
||||
|
||||
class HttpAuthAuthorizer extends AuthorizerBase
|
||||
{
|
||||
protected static $HAS_AUTH_USERMANAGEMENT = 1;
|
||||
protected static $CAN_UPDATE_USER = 1;
|
||||
|
||||
public function authenticate($username, $password)
|
||||
{
|
||||
if ($this->userExists($username)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new AuthenticationException('No matching user found and http_auth_guest is not set');
|
||||
}
|
||||
|
||||
|
||||
public function addUser($username, $password, $level = 0, $email = '', $realname = '', $can_modify_passwd = 1, $description = '')
|
||||
{
|
||||
if (!$this->userExists($username)) {
|
||||
$hasher = new PasswordHash(8, false);
|
||||
$encrypted = $hasher->HashPassword($password);
|
||||
$userid = dbInsert(array('username' => $username, 'password' => $encrypted, 'level' => $level, 'email' => $email, 'realname' => $realname, 'can_modify_passwd' => $can_modify_passwd, 'descr' => $description), 'users');
|
||||
if ($userid == false) {
|
||||
return false;
|
||||
} else {
|
||||
foreach (dbFetchRows('select notifications.* from notifications where not exists( select 1 from notifications_attribs where notifications.notifications_id = notifications_attribs.notifications_id and notifications_attribs.user_id = ?) order by notifications.notifications_id desc', array($userid)) as $notif) {
|
||||
dbInsert(array('notifications_id' => $notif['notifications_id'], 'user_id' => $userid, 'key' => 'read', 'value' => 1), 'notifications_attribs');
|
||||
}
|
||||
}
|
||||
return $userid;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function userExists($username, $throw_exception = false)
|
||||
{
|
||||
$query = 'SELECT COUNT(*) FROM `users` WHERE `username`=?';
|
||||
$params = array($username);
|
||||
|
||||
if (Config::has('http_auth_guest')) {
|
||||
$query .= ' OR `username`=?';
|
||||
$params[] = Config::get('http_auth_guest');
|
||||
}
|
||||
|
||||
return dbFetchCell($query, $params) > 0;
|
||||
}
|
||||
|
||||
|
||||
public function getUserlevel($username)
|
||||
{
|
||||
$user_level = dbFetchCell('SELECT `level` FROM `users` WHERE `username`=?', array($username));
|
||||
|
||||
if ($user_level) {
|
||||
return $user_level;
|
||||
}
|
||||
|
||||
if (Config::has('http_auth_guest')) {
|
||||
return dbFetchCell('SELECT `level` FROM `users` WHERE `username`=?', array(Config::get('http_auth_guest')));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public function getUserid($username)
|
||||
{
|
||||
$user_id = dbFetchCell('SELECT `user_id` FROM `users` WHERE `username`=?', array($username));
|
||||
|
||||
if ($user_id) {
|
||||
return $user_id;
|
||||
}
|
||||
|
||||
if (Config::has('http_auth_guest')) {
|
||||
return dbFetchCell('SELECT `user_id` FROM `users` WHERE `username`=?', array(Config::get('http_auth_guest')));
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
public function getUserlist()
|
||||
{
|
||||
return dbFetchRows('SELECT * FROM `users`');
|
||||
}
|
||||
|
||||
|
||||
public function getUser($user_id)
|
||||
{
|
||||
return dbFetchRow('SELECT * FROM `users` WHERE `user_id` = ?', array($user_id));
|
||||
}
|
||||
|
||||
|
||||
public function updateUser($user_id, $realname, $level, $can_modify_passwd, $email)
|
||||
{
|
||||
dbUpdate(array('realname' => $realname, 'level' => $level, 'can_modify_passwd' => $can_modify_passwd, 'email' => $email), 'users', '`user_id` = ?', array($user_id));
|
||||
}
|
||||
}
|
290
LibreNMS/Authentication/LdapAuthorizationAuthorizer.php
Normal file
290
LibreNMS/Authentication/LdapAuthorizationAuthorizer.php
Normal file
@ -0,0 +1,290 @@
|
||||
<?php
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* libreNMS HTTP-Authentication and LDAP Authorization Library
|
||||
* @author Maximilian Wilhelm <max@rfc2324.org>
|
||||
* @copyright 2016 LibreNMS, Barbarossa
|
||||
* @license GPL
|
||||
* @package LibreNMS
|
||||
* @subpackage Authentication
|
||||
*
|
||||
* This Authentitation / Authorization module provides the ability to let
|
||||
* the webserver (e.g. Apache) do the user Authentication (using Kerberos
|
||||
* f.e.) and let libreNMS do the Authorization of the already known user.
|
||||
* Authorization and setting of libreNMS user level is done by LDAP group
|
||||
* names specified in the configuration file. The group configuration is
|
||||
* basicly copied from the existing ldap Authentication module.
|
||||
*
|
||||
* Most of the code is copied from the http-auth and ldap Authentication
|
||||
* modules already existing.
|
||||
*
|
||||
* To save lots of redundant queries to the LDAP server and speed up the
|
||||
* libreNMS WebUI, all information is cached within the PHP $_SESSION as
|
||||
* long as specified in $config['auth_ldap_cache_ttl'] (Default: 300s).
|
||||
*/
|
||||
|
||||
namespace LibreNMS\Authentication;
|
||||
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
|
||||
class LdapAuthorizationAuthorizer extends AuthorizerBase
|
||||
{
|
||||
protected $ldap_connection;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if (! isset($_SESSION['username'])) {
|
||||
$_SESSION['username'] = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up connection to LDAP server
|
||||
*/
|
||||
$this->ldap_connection = @ldap_connect(Config::get('auth_ldap_server'), Config::get('auth_ldap_port'));
|
||||
if (! $this->ldap_connection) {
|
||||
echo '<h2>Fatal error while connecting to LDAP server ' . Config::get('auth_ldap_server') . ':' . Config::get('auth_ldap_port') . ': ' . ldap_error($this->ldap_connection) . '</h2>';
|
||||
exit;
|
||||
}
|
||||
if (Config::get('auth_ldap_version')) {
|
||||
ldap_set_option($this->ldap_connection, LDAP_OPT_PROTOCOL_VERSION, Config::get('auth_ldap_version'));
|
||||
}
|
||||
|
||||
if (Config::get('auth_ldap_starttls') && (Config::get('auth_ldap_starttls') == 'optional' || Config::get('auth_ldap_starttls') == 'require')) {
|
||||
$tls = ldap_start_tls($this->ldap_connection);
|
||||
if (Config::get('auth_ldap_starttls') == 'require' && $tls === false) {
|
||||
echo '<h2>Fatal error: LDAP TLS required but not successfully negotiated:' . ldap_error($this->ldap_connection) . '</h2>';
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function authenticate($username, $password)
|
||||
{
|
||||
if (isset($_SERVER['REMOTE_USER'])) {
|
||||
$_SESSION['username'] = mres($_SERVER['REMOTE_USER']);
|
||||
|
||||
if ($this->userExists($_SESSION['username'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$_SESSION['username'] = Config::get('http_auth_guest');
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
public function userExists($username, $throw_exception = false)
|
||||
{
|
||||
if ($this->authLdapSessionCacheGet('user_exists')) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$filter = '(' . Config::get('auth_ldap_prefix') . $username . ')';
|
||||
$search = ldap_search($this->ldap_connection, trim(Config::get('auth_ldap_suffix'), ','), $filter);
|
||||
$entries = ldap_get_entries($this->ldap_connection, $search);
|
||||
if ($entries['count']) {
|
||||
/*
|
||||
* Cache positiv result as this will result in more queries which we
|
||||
* want to speed up.
|
||||
*/
|
||||
$this->authLdapSessionCacheSet('user_exists', 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't cache that user doesn't exists as this might be a misconfiguration
|
||||
* on some end and the user will be happy if it "just works" after the user
|
||||
* has been added to LDAP.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public function getUserlevel($username)
|
||||
{
|
||||
$userlevel = $this->authLdapSessionCacheGet('userlevel');
|
||||
if ($userlevel) {
|
||||
return $userlevel;
|
||||
} else {
|
||||
$userlevel = 0;
|
||||
}
|
||||
|
||||
// Find all defined groups $username is in
|
||||
$filter = '(&(|(cn=' . join(')(cn=', array_keys(Config::get('auth_ldap_groups'))) . '))(' . Config::get('auth_ldap_groupmemberattr') .'=' . $this->getMembername($username) . '))';
|
||||
$search = ldap_search($this->ldap_connection, Config::get('auth_ldap_groupbase'), $filter);
|
||||
$entries = ldap_get_entries($this->ldap_connection, $search);
|
||||
|
||||
// Loop the list and find the highest level
|
||||
foreach ($entries as $entry) {
|
||||
$groupname = $entry['cn'][0];
|
||||
$authLdapGroups = Config::get('auth_ldap_groups');
|
||||
if ($authLdapGroups[$groupname]['level'] > $userlevel) {
|
||||
$userlevel = $authLdapGroups[$groupname]['level'];
|
||||
}
|
||||
}
|
||||
|
||||
$this->authLdapSessionCacheSet('userlevel', $userlevel);
|
||||
return $userlevel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function getUserid($username)
|
||||
{
|
||||
$user_id = $this->authLdapSessionCacheGet('userid');
|
||||
if (isset($user_id)) {
|
||||
return $user_id;
|
||||
} else {
|
||||
$user_id = -1;
|
||||
}
|
||||
|
||||
$filter = '(' . Config::get('auth_ldap_prefix') . $username . ')';
|
||||
$search = ldap_search($this->ldap_connection, trim(Config::get('auth_ldap_suffix'), ','), $filter);
|
||||
$entries = ldap_get_entries($this->ldap_connection, $search);
|
||||
|
||||
if ($entries['count']) {
|
||||
$user_id = $entries[0]['uidnumber'][0];
|
||||
}
|
||||
|
||||
$this->authLdapSessionCacheSet('userid', $user_id);
|
||||
return $user_id;
|
||||
}
|
||||
|
||||
|
||||
public function getUserlist()
|
||||
{
|
||||
$userlist = array ();
|
||||
|
||||
$filter = '(' . Config::get('auth_ldap_prefix') . '*)';
|
||||
|
||||
$search = ldap_search($this->ldap_connection, trim(Config::get('auth_ldap_suffix'), ','), $filter);
|
||||
$entries = ldap_get_entries($this->ldap_connection, $search);
|
||||
|
||||
if ($entries['count']) {
|
||||
foreach ($entries as $entry) {
|
||||
$username = $entry['uid'][0];
|
||||
$realname = $entry['cn'][0];
|
||||
$user_id = $entry['uidnumber'][0];
|
||||
$email = $entry[Config::get('auth_ldap_emailattr')][0];
|
||||
$ldap_groups = $this->getGroupList();
|
||||
foreach ($ldap_groups as $ldap_group) {
|
||||
$ldap_comparison = ldap_compare(
|
||||
$this->ldap_connection,
|
||||
$ldap_group,
|
||||
Config::get('auth_ldap_groupmemberattr'),
|
||||
$this->getMembername($username)
|
||||
);
|
||||
if (! Config::has('auth_ldap_group') || $ldap_comparison === true) {
|
||||
$userlist[] = array(
|
||||
'username' => $username,
|
||||
'realname' => $realname,
|
||||
'user_id' => $user_id,
|
||||
'email' => $email,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $userlist;
|
||||
}
|
||||
|
||||
|
||||
public function getUser($user_id)
|
||||
{
|
||||
foreach ($this->getUserlist() as $users) {
|
||||
if ($users['user_id'] === $user_id) {
|
||||
return $users['username'];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
protected function getMembername($username)
|
||||
{
|
||||
if (Config::get('auth_ldap_groupmembertype') == 'fulldn') {
|
||||
$membername = Config::get('auth_ldap_prefix') . $username . Config::get('auth_ldap_suffix');
|
||||
} elseif (Config::get('auth_ldap_groupmembertype') == 'puredn') {
|
||||
$filter = '(' . Config::get('auth_ldap_attr.uid') . '=' . $username . ')';
|
||||
$search = ldap_search($this->ldap_connection, Config::get('auth_ldap_groupbase'), $filter);
|
||||
$entries = ldap_get_entries($this->ldap_connection, $search);
|
||||
$membername = $entries[0]['dn'];
|
||||
} else {
|
||||
$membername = $username;
|
||||
}
|
||||
|
||||
return $membername;
|
||||
}
|
||||
|
||||
|
||||
protected function authLdapSessionCacheGet($attr)
|
||||
{
|
||||
$ttl = 300;
|
||||
if (Config::get('auth_ldap_cache_ttl')) {
|
||||
$ttl = Config::get('auth_ldap_cache_ttl');
|
||||
}
|
||||
|
||||
// auth_ldap cache present in this session?
|
||||
if (! isset($_SESSION['auth_ldap'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$cache = $_SESSION['auth_ldap'];
|
||||
|
||||
// $attr present in cache?
|
||||
if (! isset($cache[$attr])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Value still valid?
|
||||
if (time() - $cache[$attr]['last_updated'] >= $ttl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$cache[$attr]['value'];
|
||||
}
|
||||
|
||||
|
||||
protected function authLdapSessionCacheSet($attr, $value)
|
||||
{
|
||||
$_SESSION['auth_ldap'][$attr]['value'] = $value;
|
||||
$_SESSION['auth_ldap'][$attr]['last_updated'] = time();
|
||||
}
|
||||
|
||||
|
||||
public function getGroupList()
|
||||
{
|
||||
$ldap_groups = array();
|
||||
$default_group = 'cn=groupname,ou=groups,dc=example,dc=com';
|
||||
if (Config::has('auth_ldap_group')) {
|
||||
if (Config::get('auth_ldap_group') !== $default_group) {
|
||||
$ldap_groups[] = Config::get('auth_ldap_group');
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Config::get('auth_ldap_groups') as $key => $value) {
|
||||
$dn = "cn=$key,".Config::get('auth_ldap_groupbase');
|
||||
$ldap_groups[] = $dn;
|
||||
}
|
||||
|
||||
return $ldap_groups;
|
||||
}
|
||||
}
|
302
LibreNMS/Authentication/LdapAuthorizer.php
Normal file
302
LibreNMS/Authentication/LdapAuthorizer.php
Normal file
@ -0,0 +1,302 @@
|
||||
<?php
|
||||
|
||||
namespace LibreNMS\Authentication;
|
||||
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
|
||||
class LdapAuthorizer extends AuthorizerBase
|
||||
{
|
||||
protected $ldap_connection;
|
||||
|
||||
public function authenticate($username, $password)
|
||||
{
|
||||
$connection = $this->getLdapConnection(true);
|
||||
|
||||
if ($username) {
|
||||
if ($password && ldap_bind($connection, $this->getFullDn($username), $password)) {
|
||||
if (!Config::has('auth_ldap_group')) {
|
||||
return true;
|
||||
} else {
|
||||
$ldap_groups = $this->getGroupList();
|
||||
foreach ($ldap_groups as $ldap_group) {
|
||||
$ldap_comparison = ldap_compare(
|
||||
$connection,
|
||||
$ldap_group,
|
||||
Config::get('auth_ldap_groupmemberattr', 'memberUid'),
|
||||
$this->getMembername($username)
|
||||
);
|
||||
if ($ldap_comparison === true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($password) || $password == '') {
|
||||
throw new AuthenticationException('A password is required');
|
||||
}
|
||||
|
||||
throw new AuthenticationException(ldap_error($connection));
|
||||
}
|
||||
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
|
||||
public function reauthenticate($sess_id, $token)
|
||||
{
|
||||
$sess_id = clean($sess_id);
|
||||
$token = clean($token);
|
||||
|
||||
list($username, $hash) = explode('|', $token);
|
||||
|
||||
if (!$this->userExists($username, true)) {
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
return $this->checkRememberMe($sess_id, $token);
|
||||
}
|
||||
|
||||
public function userExists($username, $throw_exception = false)
|
||||
{
|
||||
try {
|
||||
$connection = $this->getLdapConnection();
|
||||
|
||||
$filter = '(' . Config::get('auth_ldap_prefix') . $username . ')';
|
||||
$search = ldap_search($connection, trim(Config::get('auth_ldap_suffix'), ','), $filter);
|
||||
$entries = ldap_get_entries($connection, $search);
|
||||
if ($entries['count']) {
|
||||
return 1;
|
||||
}
|
||||
} catch (AuthenticationException $e) {
|
||||
if ($throw_exception) {
|
||||
throw $e;
|
||||
} else {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public function getUserlevel($username)
|
||||
{
|
||||
$userlevel = 0;
|
||||
|
||||
try {
|
||||
$connection = $this->getLdapConnection();
|
||||
$groups = Config::get('auth_ldap_groups');
|
||||
|
||||
// Find all defined groups $username is in
|
||||
$filter = '(&(|(cn=' . join(')(cn=', array_keys($groups)) . '))(' . Config::get('auth_ldap_groupmemberattr', 'memberUid') . '=' . $this->getMembername($username) . '))';
|
||||
$search = ldap_search($connection, Config::get('auth_ldap_groupbase'), $filter);
|
||||
$entries = ldap_get_entries($connection, $search);
|
||||
|
||||
// Loop the list and find the highest level
|
||||
foreach ($entries as $entry) {
|
||||
$groupname = $entry['cn'][0];
|
||||
if ($groups[$groupname]['level'] > $userlevel) {
|
||||
$userlevel = $groups[$groupname]['level'];
|
||||
}
|
||||
}
|
||||
} catch (AuthenticationException $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
|
||||
return $userlevel;
|
||||
}
|
||||
|
||||
|
||||
public function getUserid($username)
|
||||
{
|
||||
try {
|
||||
$connection = $this->getLdapConnection();
|
||||
|
||||
$filter = '(' . Config::get('auth_ldap_prefix') . $username . ')';
|
||||
$search = ldap_search($connection, trim(Config::get('auth_ldap_suffix'), ','), $filter);
|
||||
$entries = ldap_get_entries($connection, $search);
|
||||
|
||||
if ($entries['count']) {
|
||||
$uid_attr = strtolower(Config::get('auth_ldap_uid_attribute', 'uidnumber'));
|
||||
return $entries[0][$uid_attr][0];
|
||||
}
|
||||
} catch (AuthenticationException $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public function getUserlist()
|
||||
{
|
||||
$userlist = array();
|
||||
|
||||
try {
|
||||
$connection = $this->getLdapConnection();
|
||||
|
||||
$filter = '(' . Config::get('auth_ldap_prefix') . '*)';
|
||||
$search = ldap_search($connection, trim(Config::get('auth_ldap_suffix'), ','), $filter);
|
||||
$entries = ldap_get_entries($connection, $search);
|
||||
|
||||
if ($entries['count']) {
|
||||
foreach ($entries as $entry) {
|
||||
$username = $entry['uid'][0];
|
||||
$realname = $entry['cn'][0];
|
||||
$uid_attr = strtolower(Config::get('auth_ldap_uid_attribute', 'uidnumber'));
|
||||
$user_id = $entry[$uid_attr][0];
|
||||
$email = $entry[Config::get('auth_ldap_emailattr', 'mail')][0];
|
||||
$ldap_groups = $this->getGroupList();
|
||||
foreach ($ldap_groups as $ldap_group) {
|
||||
$ldap_comparison = $this->ldap_compare(
|
||||
$connection,
|
||||
$ldap_group,
|
||||
Config::get('auth_ldap_groupmemberattr', 'memberUid'),
|
||||
$this->getMembername($username)
|
||||
);
|
||||
if (!Config::has('auth_ldap_group') || $ldap_comparison === true) {
|
||||
$userlist[$username] = array(
|
||||
'username' => $username,
|
||||
'realname' => $realname,
|
||||
'user_id' => $user_id,
|
||||
'email' => $email,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (AuthenticationException $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
|
||||
return $userlist;
|
||||
}
|
||||
|
||||
public function getUser($user_id)
|
||||
{
|
||||
foreach ($this->getUserlist() as $user) {
|
||||
if ($user['user_id'] === $user_id) {
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function getMembername($username)
|
||||
{
|
||||
$type = Config::get('auth_ldap_groupmembertype');
|
||||
|
||||
if ($type == 'fulldn') {
|
||||
return $this->getFullDn($username);
|
||||
}
|
||||
|
||||
if ($type == 'puredn') {
|
||||
try {
|
||||
$connection = $this->getLdapConnection();
|
||||
$filter = '(' . Config::get('auth_ldap_attr.uid') . '=' . $username . ')';
|
||||
$search = ldap_search($connection, Config::get('auth_ldap_groupbase'), $filter);
|
||||
$entries = ldap_get_entries($connection, $search);
|
||||
return $entries[0]['dn'];
|
||||
} catch (AuthenticationException $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
return $username;
|
||||
}
|
||||
|
||||
|
||||
public function getGroupList()
|
||||
{
|
||||
$ldap_groups = array();
|
||||
|
||||
$default_group = 'cn=groupname,ou=groups,dc=example,dc=com'; // in the documentation
|
||||
if (Config::get('auth_ldap_group', $default_group) !== $default_group) {
|
||||
$ldap_groups[] = Config::get('auth_ldap_group');
|
||||
}
|
||||
|
||||
foreach (Config::get('auth_ldap_groups') as $key => $value) {
|
||||
$ldap_groups[] = "cn=$key,".Config::get('auth_ldap_groupbase');
|
||||
}
|
||||
|
||||
return $ldap_groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full dn with auth_ldap_prefix and auth_ldap_suffix
|
||||
* @internal
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getFullDn($username)
|
||||
{
|
||||
return Config::get('auth_ldap_prefix', '') . $username . Config::get('auth_ldap_suffix', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ldap connection. If it hasn't been established yet, connect and try to bind.
|
||||
* @internal
|
||||
*
|
||||
* @param bool $skip_bind do not attempt to bind on connection
|
||||
* @return false|resource
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
protected function getLdapConnection($skip_bind = false)
|
||||
{
|
||||
|
||||
if ($this->ldap_connection) {
|
||||
return $this->ldap_connection; // bind already attempted
|
||||
}
|
||||
|
||||
$this->ldap_connection = @ldap_connect(Config::get('auth_ldap_server'), Config::get('auth_ldap_port', 389));
|
||||
|
||||
if (!$this->ldap_connection) {
|
||||
throw new AuthenticationException('Unable to connect to ldap server');
|
||||
}
|
||||
|
||||
ldap_set_option($this->ldap_connection, LDAP_OPT_PROTOCOL_VERSION, Config::get('auth_ldap_version', 2));
|
||||
|
||||
$use_tls = Config::get('auth_ldap_starttls');
|
||||
if ($use_tls == 'optional'||$use_tls == 'require') {
|
||||
$tls_success = ldap_start_tls($this->ldap_connection);
|
||||
if ($use_tls == 'require' && $tls_success === false) {
|
||||
$error = ldap_error($this->ldap_connection);
|
||||
throw new AuthenticationException("Fatal error: LDAP TLS required but not successfully negotiated: $error");
|
||||
}
|
||||
}
|
||||
|
||||
if ($skip_bind) {
|
||||
return $this->ldap_connection;
|
||||
}
|
||||
|
||||
// set timeout
|
||||
ldap_set_option($this->ldap_connection, LDAP_OPT_NETWORK_TIMEOUT, Config::get('auth_ldap_timeout', 5));
|
||||
|
||||
// With specified bind user
|
||||
if ((Config::has('auth_ldap_binduser') || Config::has('auth_ldap_binddn'))
|
||||
&& Config::has('auth_ldap_bindpassword')
|
||||
) {
|
||||
if (Config::has('auth_ldap_binddn')) {
|
||||
$bind_dn = Config::get('auth_ldap_binddn');
|
||||
} else {
|
||||
$bind_dn = $this->getFullDn(Config::get('auth_ldap_binduser'));
|
||||
}
|
||||
|
||||
if (ldap_bind(
|
||||
$this->ldap_connection,
|
||||
$bind_dn,
|
||||
Config::get('auth_ldap_bindpassword')
|
||||
)) {
|
||||
ldap_set_option($this->ldap_connection, LDAP_OPT_NETWORK_TIMEOUT, -1); // restore timeout
|
||||
return $this->ldap_connection;
|
||||
}
|
||||
}
|
||||
|
||||
// Anonymous
|
||||
ldap_bind($this->ldap_connection);
|
||||
|
||||
ldap_set_option($this->ldap_connection, LDAP_OPT_NETWORK_TIMEOUT, -1); // restore timeout
|
||||
return $this->ldap_connection;
|
||||
}
|
||||
}
|
161
LibreNMS/Authentication/MysqlAuthorizer.php
Normal file
161
LibreNMS/Authentication/MysqlAuthorizer.php
Normal file
@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
namespace LibreNMS\Authentication;
|
||||
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
use Phpass\PasswordHash;
|
||||
|
||||
class MysqlAuthorizer extends AuthorizerBase
|
||||
{
|
||||
protected static $HAS_AUTH_USERMANAGEMENT = 1;
|
||||
protected static $CAN_UPDATE_USER = 1;
|
||||
|
||||
public function authenticate($username, $password)
|
||||
{
|
||||
$encrypted_old = md5($password);
|
||||
$row = dbFetchRow('SELECT username,password FROM `users` WHERE `username`= ?', array($username), true);
|
||||
if ($row['username'] && $row['username'] == $username) {
|
||||
// Migrate from old, unhashed password
|
||||
if ($row['password'] == $encrypted_old) {
|
||||
$row_type = dbFetchRow('DESCRIBE users password');
|
||||
if ($row_type['Type'] == 'varchar(34)') {
|
||||
$this->changePassword($username, $password);
|
||||
}
|
||||
|
||||
return true;
|
||||
} elseif (substr($row['password'], 0, 3) == '$1$') {
|
||||
$row_type = dbFetchRow('DESCRIBE users password');
|
||||
if ($row_type['Type'] == 'varchar(60)') {
|
||||
if ($row['password'] == crypt($password, $row['password'])) {
|
||||
$this->changePassword($username, $password);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$hasher = new PasswordHash(8, false);
|
||||
if ($hasher->CheckPassword($password, $row['password'])) {
|
||||
return true;
|
||||
}
|
||||
}//end if
|
||||
|
||||
throw new AuthenticationException();
|
||||
}//end authenticate()
|
||||
|
||||
|
||||
public function reauthenticate($sess_id, $token)
|
||||
{
|
||||
return $this->checkRememberMe($sess_id, $token);
|
||||
}//end reauthenticate()
|
||||
|
||||
|
||||
public function canUpdatePasswords($username = '')
|
||||
{
|
||||
/*
|
||||
* By default allow the password to be modified, unless the existing
|
||||
* user is explicitly prohibited to do so.
|
||||
*/
|
||||
|
||||
if (empty($username) || !$this->userExists($username)) {
|
||||
return 1;
|
||||
} else {
|
||||
return dbFetchCell('SELECT can_modify_passwd FROM users WHERE username = ?', array($username), true);
|
||||
}
|
||||
}//end passwordscanchange()
|
||||
|
||||
|
||||
/**
|
||||
* From: http://code.activestate.com/recipes/576894-generate-a-salt/
|
||||
* This public function generates a password salt as a string of x (default = 15) characters
|
||||
* ranging from a-zA-Z0-9.
|
||||
* @param $max integer The number of characters in the string
|
||||
* @author AfroSoft <scripts@afrosoft.co.cc>
|
||||
*/
|
||||
public function generateSalt($max = 15)
|
||||
{
|
||||
$characterList = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
$i = 0;
|
||||
$salt = '';
|
||||
do {
|
||||
$salt .= $characterList{mt_rand(0, strlen($characterList))};
|
||||
$i++;
|
||||
} while ($i <= $max);
|
||||
|
||||
return $salt;
|
||||
}//end generateSalt()
|
||||
|
||||
|
||||
public function changePassword($username, $password)
|
||||
{
|
||||
$hasher = new PasswordHash(8, false);
|
||||
$encrypted = $hasher->HashPassword($password);
|
||||
return dbUpdate(array('password' => $encrypted), 'users', '`username` = ?', array($username));
|
||||
}//end changepassword()
|
||||
|
||||
public function addUser($username, $password, $level = 0, $email = '', $realname = '', $can_modify_passwd = 1, $description = '')
|
||||
{
|
||||
if (!$this->userExists($username)) {
|
||||
$hasher = new PasswordHash(8, false);
|
||||
$encrypted = $hasher->HashPassword($password);
|
||||
$userid = dbInsert(array('username' => $username, 'password' => $encrypted, 'level' => $level, 'email' => $email, 'realname' => $realname, 'can_modify_passwd' => $can_modify_passwd, 'descr' => $description), 'users');
|
||||
if ($userid == false) {
|
||||
return false;
|
||||
} else {
|
||||
foreach (dbFetchRows('select notifications.* from notifications where not exists( select 1 from notifications_attribs where notifications.notifications_id = notifications_attribs.notifications_id and notifications_attribs.user_id = ?) order by notifications.notifications_id desc', array($userid)) as $notif) {
|
||||
dbInsert(array('notifications_id'=>$notif['notifications_id'],'user_id'=>$userid,'key'=>'read','value'=>1), 'notifications_attribs');
|
||||
}
|
||||
}
|
||||
return $userid;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}//end adduser()
|
||||
|
||||
|
||||
public function userExists($username, $throw_exception = false)
|
||||
{
|
||||
$return = @dbFetchCell('SELECT COUNT(*) FROM users WHERE username = ?', array($username), true);
|
||||
return $return;
|
||||
}//end userExists()
|
||||
|
||||
|
||||
public function getUserlevel($username)
|
||||
{
|
||||
return dbFetchCell('SELECT `level` FROM `users` WHERE `username` = ?', array($username), true);
|
||||
}//end getUserlevel()
|
||||
|
||||
|
||||
public function getUserid($username)
|
||||
{
|
||||
return dbFetchCell('SELECT `user_id` FROM `users` WHERE `username` = ?', array($username), true);
|
||||
}//end getUserid()
|
||||
|
||||
|
||||
public function deleteUser($userid)
|
||||
{
|
||||
dbDelete('bill_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('devices_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('ports_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('users_prefs', '`user_id` = ?', array($userid));
|
||||
dbDelete('users', '`user_id` = ?', array($userid));
|
||||
|
||||
return dbDelete('users', '`user_id` = ?', array($userid));
|
||||
}//end deluser()
|
||||
|
||||
|
||||
public function getUserlist()
|
||||
{
|
||||
return dbFetchRows('SELECT * FROM `users` ORDER BY `username`');
|
||||
}//end getUserlist()
|
||||
|
||||
|
||||
public function getUser($user_id)
|
||||
{
|
||||
return dbFetchRow('SELECT * FROM `users` WHERE `user_id` = ?', array($user_id), true);
|
||||
}//end getUser()
|
||||
|
||||
|
||||
public function updateUser($user_id, $realname, $level, $can_modify_passwd, $email)
|
||||
{
|
||||
dbUpdate(array('realname' => $realname, 'level' => $level, 'can_modify_passwd' => $can_modify_passwd, 'email' => $email), 'users', '`user_id` = ?', array($user_id));
|
||||
}//end updateUser()
|
||||
}
|
111
LibreNMS/Authentication/RadiusAuthorizer.php
Normal file
111
LibreNMS/Authentication/RadiusAuthorizer.php
Normal file
@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace LibreNMS\Authentication;
|
||||
|
||||
use Dapphp\Radius\Radius;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
use Phpass\PasswordHash;
|
||||
|
||||
class RadiusAuthorizer extends AuthorizerBase
|
||||
{
|
||||
protected static $HAS_AUTH_USERMANAGEMENT = 1;
|
||||
protected static $CAN_UPDATE_USER = 1;
|
||||
|
||||
/** @var Radius $radius */
|
||||
protected $radius;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->radius = new Radius(Config::get('radius.hostname'), Config::get('radius.secret'), Config::get('radius.suffix'), Config::get('radius.timeout'), Config::get('radius.port'));
|
||||
}
|
||||
|
||||
public function authenticate($username, $password)
|
||||
{
|
||||
global $debug;
|
||||
|
||||
if (empty($username)) {
|
||||
throw new AuthenticationException('Username is required');
|
||||
}
|
||||
|
||||
if ($debug) {
|
||||
$this->radius->setDebug(true);
|
||||
}
|
||||
|
||||
if ($this->radius->accessRequest($username, $password) === true) {
|
||||
$this->addUser($username, $password);
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
public function addUser($username, $password, $level = 1, $email = '', $realname = '', $can_modify_passwd = 0, $description = '')
|
||||
{
|
||||
// Check to see if user is already added in the database
|
||||
if (!$this->userExists($username)) {
|
||||
$hasher = new PasswordHash(8, false);
|
||||
$encrypted = $hasher->HashPassword($password);
|
||||
if (Config::get('radius.default_level') > 0) {
|
||||
$level = Config::get('radius.default_level');
|
||||
}
|
||||
$userid = dbInsert(array('username' => $username, 'password' => $encrypted, 'realname' => $realname, 'email' => $email, 'descr' => $description, 'level' => $level, 'can_modify_passwd' => $can_modify_passwd), 'users');
|
||||
if ($userid == false) {
|
||||
return false;
|
||||
} else {
|
||||
foreach (dbFetchRows('select notifications.* from notifications where not exists( select 1 from notifications_attribs where notifications.notifications_id = notifications_attribs.notifications_id and notifications_attribs.user_id = ?) order by notifications.notifications_id desc', array($userid)) as $notif) {
|
||||
dbInsert(array('notifications_id'=>$notif['notifications_id'],'user_id'=>$userid,'key'=>'read','value'=>1), 'notifications_attribs');
|
||||
}
|
||||
}
|
||||
return $userid;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function userExists($username, $throw_exception = false)
|
||||
{
|
||||
return dbFetchCell('SELECT COUNT(*) FROM users WHERE username = ?', array($username), true);
|
||||
}
|
||||
|
||||
|
||||
public function getUserlevel($username)
|
||||
{
|
||||
return dbFetchCell('SELECT `level` FROM `users` WHERE `username` = ?', array($username), true);
|
||||
}
|
||||
|
||||
|
||||
public function getUserid($username)
|
||||
{
|
||||
return dbFetchCell('SELECT `user_id` FROM `users` WHERE `username` = ?', array($username), true);
|
||||
}
|
||||
|
||||
|
||||
public function deleteUser($userid)
|
||||
{
|
||||
dbDelete('bill_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('devices_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('ports_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('users_prefs', '`user_id` = ?', array($userid));
|
||||
dbDelete('users', '`user_id` = ?', array($userid));
|
||||
return dbDelete('users', '`user_id` = ?', array($userid));
|
||||
}
|
||||
|
||||
|
||||
public function getUserlist()
|
||||
{
|
||||
return dbFetchRows('SELECT * FROM `users`');
|
||||
}
|
||||
|
||||
|
||||
public function getUser($user_id)
|
||||
{
|
||||
return dbFetchRow('SELECT * FROM `users` WHERE `user_id` = ?', array($user_id), true);
|
||||
}
|
||||
|
||||
|
||||
public function updateUser($user_id, $realname, $level, $can_modify_passwd, $email)
|
||||
{
|
||||
dbUpdate(array('realname' => $realname, 'level' => $level, 'can_modify_passwd' => $can_modify_passwd, 'email' => $email), 'users', '`user_id` = ?', array($user_id));
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@
|
||||
|
||||
namespace LibreNMS\Authentication;
|
||||
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
|
||||
class TwoFactor
|
||||
@ -129,8 +130,6 @@ class TwoFactor
|
||||
*/
|
||||
public static function getForm($form_tags = true)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$ret = '';
|
||||
|
||||
if ($form_tags) {
|
||||
@ -140,7 +139,7 @@ class TwoFactor
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
<img src="' . $config['title_image'] . '">
|
||||
<img src="' . Config::get('title_image') . '">
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
@ -179,7 +178,7 @@ class TwoFactor
|
||||
*/
|
||||
public static function showForm()
|
||||
{
|
||||
global $twofactorform, $config;
|
||||
global $twofactorform;
|
||||
|
||||
$twofactor = get_user_pref('twofactor');
|
||||
|
||||
@ -191,10 +190,10 @@ class TwoFactor
|
||||
|
||||
// lockout the user if there are too many failures
|
||||
if ($twofactor['fails'] >= 3) {
|
||||
if (!$config['twofactor_lock']) {
|
||||
if (!Config::get('twofactor_lock')) {
|
||||
throw new AuthenticationException('Too many two-factor failures, please contact administrator.');
|
||||
} elseif ((time() - $twofactor['last']) < $config['twofactor_lock']) {
|
||||
$msg = "Too many two-factor failures, please wait " . $config['twofactor_lock'] . " seconds";
|
||||
} elseif ((time() - $twofactor['last']) < Config::get('twofactor_lock')) {
|
||||
$msg = "Too many two-factor failures, please wait " . Config::get('twofactor_lock') . " seconds";
|
||||
throw new AuthenticationException($msg);
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
namespace LibreNMS;
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
use LibreNMS\Exceptions\DatabaseConnectException;
|
||||
|
||||
class IRCBot
|
||||
@ -539,15 +540,16 @@ class IRCBot
|
||||
|
||||
private function hostAuth()
|
||||
{
|
||||
global $authorizer;
|
||||
foreach ($this->config['irc_auth'] as $nms_user => $hosts) {
|
||||
foreach ($hosts as $host) {
|
||||
$host = preg_replace("/\*/", ".*", $host);
|
||||
if (preg_match("/$host/", $this->getUserHost($this->data))) {
|
||||
$user_id = get_userid(mres($nms_user));
|
||||
$user = get_user($user_id);
|
||||
$user_id = Auth::get()->getUserid(mres($nms_user));
|
||||
$user = Auth::get()->getUser($user_id);
|
||||
$this->user['name'] = $user['username'];
|
||||
$this->user['id'] = $user_id;
|
||||
$this->user['level'] = get_userlevel($user['username']);
|
||||
$this->user['level'] = Auth::get()->getUserlevel($user['username']);
|
||||
$this->user['expire'] = (time() + ($this->config['irc_authtime'] * 3600));
|
||||
if ($this->user['level'] < 5) {
|
||||
foreach (dbFetchRows('SELECT device_id FROM devices_perms WHERE user_id = ?', array($this->user['id'])) as $tmp) {
|
||||
@ -577,12 +579,13 @@ class IRCBot
|
||||
|
||||
private function _auth($params)
|
||||
{
|
||||
global $authorizer;
|
||||
$params = explode(' ', $params, 2);
|
||||
if (strlen($params[0]) == 64) {
|
||||
if ($this->tokens[$this->getUser($this->data)] == $params[0]) {
|
||||
$this->user['expire'] = (time() + ($this->config['irc_authtime'] * 3600));
|
||||
$tmp_user = get_user($this->user['id']);
|
||||
$tmp = get_userlevel($tmp_user['username']);
|
||||
$tmp_user = Auth::get()->getUser($this->user['id']);
|
||||
$tmp = Auth::get()->getUserlevel($tmp_user['username']);
|
||||
$this->user['level'] = $tmp;
|
||||
if ($this->user['level'] < 5) {
|
||||
foreach (dbFetchRows('SELECT device_id FROM devices_perms WHERE user_id = ?', array($this->user['id'])) as $tmp) {
|
||||
@ -599,8 +602,8 @@ class IRCBot
|
||||
return $this->respond('Nope.');
|
||||
}
|
||||
} else {
|
||||
$user_id = get_userid(mres($params[0]));
|
||||
$user = get_user($user_id);
|
||||
$user_id = Auth::get()->getUserid(mres($params[0]));
|
||||
$user = Auth::get()->getUser($user_id);
|
||||
if ($user['email'] && $user['username'] == $params[0]) {
|
||||
$token = hash('gost', openssl_random_pseudo_bytes(1024));
|
||||
$this->tokens[$this->getUser($this->data)] = $token;
|
||||
|
170
LibreNMS/Interfaces/Authentication/Authorizer.php
Normal file
170
LibreNMS/Interfaces/Authentication/Authorizer.php
Normal file
@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
namespace LibreNMS\Interfaces\Authentication;
|
||||
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
|
||||
interface Authorizer
|
||||
{
|
||||
/**
|
||||
* Authenticate the user and password.
|
||||
* Some Authorizer methods may only check username.
|
||||
*
|
||||
* @param $username
|
||||
* @param $password
|
||||
* @return true throws an Exception on failure
|
||||
* @throws AuthenticationException thrown if the username or password is invalid
|
||||
*/
|
||||
public function authenticate($username, $password);
|
||||
|
||||
/**
|
||||
* Check for cookie token to see if this is a valid saved session
|
||||
* Authorizers should check if the user is still valid then return checkRememberMe()
|
||||
*
|
||||
* @param int $sess_id
|
||||
* @param string $token
|
||||
* @return bool
|
||||
* @throws AuthenticationException thrown if the cookie or user is invalid
|
||||
*/
|
||||
public function reauthenticate($sess_id, $token);
|
||||
|
||||
/**
|
||||
* Check if a $username exists.
|
||||
*
|
||||
* @param string $username
|
||||
* @param bool $throw_exception If this is enabled instead of returning false, this will throw an exception.
|
||||
* @return bool
|
||||
*/
|
||||
public function userExists($username, $throw_exception = false);
|
||||
|
||||
/**
|
||||
* Get the userlevel of $username
|
||||
*
|
||||
* @param string $username The username to check
|
||||
* @return int
|
||||
*/
|
||||
public function getUserlevel($username);
|
||||
|
||||
/**
|
||||
* Get the user_id of $username
|
||||
*
|
||||
* @param string $username
|
||||
* @return int
|
||||
*/
|
||||
public function getUserid($username);
|
||||
|
||||
/**
|
||||
* Get an array describing this $user_id.
|
||||
*
|
||||
* It should contain the fields:
|
||||
* user_id
|
||||
* username
|
||||
* realname
|
||||
* email
|
||||
* descr
|
||||
* level
|
||||
* can_modify_passwd
|
||||
*
|
||||
* @param int $user_id
|
||||
* @return array
|
||||
*/
|
||||
public function getUser($user_id);
|
||||
|
||||
/**
|
||||
* Add a new user.
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param int $level
|
||||
* @param string $email
|
||||
* @param string $realname
|
||||
* @param int $can_modify_passwd If this user is allowed to edit their password
|
||||
* @param string $description
|
||||
* @return int|false Returns the added user_id or false if adding failed
|
||||
*/
|
||||
public function addUser($username, $password, $level = 0, $email = '', $realname = '', $can_modify_passwd = 0, $description = '');
|
||||
|
||||
/**
|
||||
* Update the some of the fields of a user
|
||||
*
|
||||
* @param int $user_id The user_id to update
|
||||
* @param string $realname
|
||||
* @param int $level
|
||||
* @param int $can_modify_passwd
|
||||
* @param string $email
|
||||
* @return bool If the update was successful
|
||||
*/
|
||||
public function updateUser($user_id, $realname, $level, $can_modify_passwd, $email);
|
||||
|
||||
/**
|
||||
* @param string $username The $username to update
|
||||
* @param string $newpassword
|
||||
* @return bool If the update was successful
|
||||
*/
|
||||
public function changePassword($username, $newpassword);
|
||||
|
||||
/**
|
||||
* Delete a user.
|
||||
*
|
||||
* @param int $user_id
|
||||
* @return bool If the deletion was successful
|
||||
*/
|
||||
public function deleteUser($user_id);
|
||||
|
||||
/**
|
||||
* Get a list of all users in this Authorizer
|
||||
* !Warning! this could be very slow for some Authorizer types or configurations
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getUserlist();
|
||||
|
||||
/**
|
||||
* Check if this Authorizer can add or remove users.
|
||||
* You must also check canUpdateUsers() to see if it can edit users.
|
||||
* You must check canUpdatePasswords() to see if it can set passwords.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canManageUsers();
|
||||
|
||||
/**
|
||||
* Check if this Authorizer can modify users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canUpdateUsers();
|
||||
|
||||
/**
|
||||
* Check if this Authorizer can set new passwords.
|
||||
*
|
||||
* @param string $username Optionally, check if $username can set their own password
|
||||
* @return bool
|
||||
*/
|
||||
public function canUpdatePasswords($username = '');
|
||||
|
||||
/**
|
||||
* Log out the user, unset cookies, destroy the session
|
||||
*
|
||||
* @param string $message The logout message.
|
||||
*/
|
||||
public function logOutUser($message = 'Logged Out');
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public function logInUser();
|
||||
|
||||
/**
|
||||
* Check if the session is authenticated
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function sessionAuthenticated();
|
||||
}
|
@ -12,16 +12,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
$init_modules = array();
|
||||
if (php_sapi_name() != 'cli') {
|
||||
$init_modules[] = 'auth';
|
||||
}
|
||||
require __DIR__ . '/includes/init.php';
|
||||
|
||||
if (auth_usermanagement()) {
|
||||
if (Auth::get()->canManageUsers()) {
|
||||
if (isset($argv[1]) && isset($argv[2]) && isset($argv[3])) {
|
||||
if (!user_exists($argv[1])) {
|
||||
if (adduser($argv[1], $argv[2], $argv[3], @$argv[4])) {
|
||||
if (!Auth::get()->userExists($argv[1])) {
|
||||
if (Auth::get()->addUser($argv[1], $argv[2], $argv[3], @$argv[4])) {
|
||||
echo 'User '.$argv[1]." added successfully\n";
|
||||
}
|
||||
} else {
|
||||
|
@ -12,15 +12,17 @@
|
||||
* the source code distribution for details.
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
function authToken(\Slim\Route $route)
|
||||
{
|
||||
$app = \Slim\Slim::getInstance();
|
||||
$token = $app->request->headers->get('X-Auth-Token');
|
||||
if (isset($token) && !empty($token)) {
|
||||
if (!function_exists('get_user')) {
|
||||
if (!method_exists(Auth::get(), 'getUser')) {
|
||||
$username = dbFetchCell('SELECT `U`.`username` FROM `api_tokens` AS AT JOIN `users` AS U ON `AT`.`user_id`=`U`.`user_id` WHERE `AT`.`token_hash`=?', array($token));
|
||||
} else {
|
||||
$username = get_user(dbFetchCell('SELECT `AT`.`user_id` FROM `api_tokens` AS AT WHERE `AT`.`token_hash`=?', array($token)));
|
||||
$username = Auth::get()->getUser(dbFetchCell('SELECT `AT`.`user_id` FROM `api_tokens` AS AT WHERE `AT`.`token_hash`=?', array($token)));
|
||||
}
|
||||
if (!empty($username)) {
|
||||
$authenticated = true;
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
use LibreNMS\Authentication\TwoFactor;
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
|
||||
@ -26,29 +27,30 @@ dbDelete('session', '`session_expiry` < ?', array(time()));
|
||||
|
||||
session_start();
|
||||
|
||||
if ($vars['page'] == 'logout' && session_authenticated()) {
|
||||
log_out_user();
|
||||
$authorizer = Auth::get();
|
||||
if ($vars['page'] == 'logout' && $authorizer->sessionAuthenticated()) {
|
||||
$authorizer->logOutUser();
|
||||
header('Location: ' . $config['base_url']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
if (session_authenticated()) {
|
||||
if ($authorizer->sessionAuthenticated()) {
|
||||
// session authenticated already
|
||||
log_in_user();
|
||||
$authorizer->logInUser();
|
||||
} else {
|
||||
// try authentication methods
|
||||
|
||||
if (isset($_POST['twofactor']) && TwoFactor::authenticate($_POST['twofactor'])) {
|
||||
// process two-factor auth tokens
|
||||
log_in_user();
|
||||
$authorizer->logInUser();
|
||||
} elseif (isset($_COOKIE['sess_id'], $_COOKIE['token']) &&
|
||||
reauthenticate(clean($_COOKIE['sess_id']), clean($_COOKIE['token']))
|
||||
$authorizer->reauthenticate(clean($_COOKIE['sess_id']), clean($_COOKIE['token']))
|
||||
) {
|
||||
$_SESSION['remember'] = true;
|
||||
$_SESSION['twofactor'] = true; // trust cookie
|
||||
// cookie authentication
|
||||
log_in_user();
|
||||
$authorizer->logInUser();
|
||||
} else {
|
||||
// collect username and password
|
||||
$password = null;
|
||||
@ -62,14 +64,14 @@ try {
|
||||
}
|
||||
|
||||
// form authentication
|
||||
if (isset($username) && authenticate($username, $password)) {
|
||||
if (isset($username) && $authorizer->authenticate($username, $password)) {
|
||||
$_SESSION['username'] = $username;
|
||||
|
||||
if (isset($_POST['remember'])) {
|
||||
$_SESSION['remember'] = $_POST['remember'];
|
||||
}
|
||||
|
||||
if (log_in_user()) {
|
||||
if ($authorizer->logInUser()) {
|
||||
// redirect to original uri or home page.
|
||||
header('Location: '.rtrim($config['base_url'], '/').$_SERVER['REQUEST_URI'], true, 303);
|
||||
}
|
||||
@ -86,7 +88,7 @@ try {
|
||||
array('user' => $_SESSION['username'], 'address' => get_client_ip(), 'result' => $auth_message),
|
||||
'authlog'
|
||||
);
|
||||
log_out_user($auth_message);
|
||||
$authorizer->logOutUser($auth_message);
|
||||
}
|
||||
|
||||
session_write_close();
|
||||
|
@ -1,508 +0,0 @@
|
||||
<?php
|
||||
|
||||
// easier to rewrite for Active Directory than to bash it into existing LDAP implementation
|
||||
|
||||
// disable certificate checking before connect if required
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
|
||||
function init_auth()
|
||||
{
|
||||
global $ad_init, $ldap_connection, $config;
|
||||
|
||||
if (isset($config['auth_ad_check_certificates']) &&
|
||||
!$config['auth_ad_check_certificates']) {
|
||||
putenv('LDAPTLS_REQCERT=never');
|
||||
};
|
||||
|
||||
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
|
||||
ldap_set_option($ldap_connection, LDAP_OPT_REFERRALS, 0);
|
||||
ldap_set_option($ldap_connection, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
}
|
||||
|
||||
function authenticate($username, $password)
|
||||
{
|
||||
global $ldap_connection, $ad_init;
|
||||
|
||||
if ($ldap_connection) {
|
||||
// bind with sAMAccountName instead of full LDAP DN
|
||||
if ($username && $password && ldap_bind($ldap_connection, $username . '@' . Config::get('auth_ad_domain'), $password)) {
|
||||
$ad_init = true;
|
||||
// group membership in one of the configured groups is required
|
||||
if (Config::get('auth_ad_require_groupmembership', true)) {
|
||||
// cycle through defined groups, test for memberOf-ship
|
||||
foreach (Config::get('auth_ad_groups', array()) as $group => $level) {
|
||||
if (user_in_group($username, $group)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// failed to find user
|
||||
if (Config::get('auth_ad_debug', false)) {
|
||||
throw new AuthenticationException('User is not in one of the required groups or user/group is outside the base dn');
|
||||
}
|
||||
|
||||
throw new AuthenticationException();
|
||||
} else {
|
||||
// group membership is not required and user is valid
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($password) || $password == '') {
|
||||
throw new AuthenticationException('A password is required');
|
||||
} elseif (Config::get('auth_ad_debug', false)) {
|
||||
ldap_get_option($ldap_connection, LDAP_OPT_DIAGNOSTIC_MESSAGE, $extended_error);
|
||||
throw new AuthenticationException(ldap_error($ldap_connection).'<br />'.$extended_error);
|
||||
}
|
||||
|
||||
throw new AuthenticationException(ldap_error($ldap_connection));
|
||||
}
|
||||
|
||||
function reauthenticate($sess_id, $token)
|
||||
{
|
||||
global $ldap_connection;
|
||||
|
||||
if (ad_bind($ldap_connection, false, true)) {
|
||||
$sess_id = clean($sess_id);
|
||||
$token = clean($token);
|
||||
list($username, $hash) = explode('|', $token);
|
||||
|
||||
if (!user_exists($username)) {
|
||||
if (Config::get('auth_ad_debug', false)) {
|
||||
throw new AuthenticationException("$username is not a valid AD user");
|
||||
}
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
return check_remember_me($sess_id, $token);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function user_in_group($username, $groupname)
|
||||
{
|
||||
// check if user is member of the given group or nested groups
|
||||
|
||||
global $ldap_connection;
|
||||
|
||||
$search_filter = "(&(objectClass=group)(cn=$groupname))";
|
||||
|
||||
// get DN for auth_ad_group
|
||||
$search = ldap_search(
|
||||
$ldap_connection,
|
||||
Config::get('auth_ad_base_dn'),
|
||||
$search_filter,
|
||||
array("cn")
|
||||
);
|
||||
$result = ldap_get_entries($ldap_connection, $search);
|
||||
|
||||
if ($result == false || $result['count'] !== 1) {
|
||||
if (Config::get('auth_ad_debug', false)) {
|
||||
if ($result == false) {
|
||||
// FIXME: what went wrong?
|
||||
throw new AuthenticationException("LDAP query failed for group '$groupname' using filter '$search_filter'");
|
||||
} elseif ($result['count'] == 0) {
|
||||
throw new AuthenticationException("Failed to find group matching '$groupname' using filter '$search_filter'");
|
||||
} elseif ($result['count'] > 1) {
|
||||
throw new AuthenticationException("Multiple groups returned for '$groupname' using filter '$search_filter'");
|
||||
}
|
||||
}
|
||||
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
$group_dn = $result[0]["dn"];
|
||||
|
||||
$search = ldap_search(
|
||||
$ldap_connection,
|
||||
Config::get('auth_ad_base_dn'),
|
||||
// add 'LDAP_MATCHING_RULE_IN_CHAIN to the user filter to search for $username in nested $group_dn
|
||||
// limiting to "DN" for shorter array
|
||||
"(&" . get_auth_ad_user_filter($username) . "(memberOf:1.2.840.113556.1.4.1941:=$group_dn))",
|
||||
array("DN")
|
||||
);
|
||||
$entries = ldap_get_entries($ldap_connection, $search);
|
||||
|
||||
return ($entries["count"] > 0);
|
||||
}
|
||||
|
||||
|
||||
function passwordscanchange()
|
||||
{
|
||||
// not supported so return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function changepassword()
|
||||
{
|
||||
// not supported so return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function auth_usermanagement()
|
||||
{
|
||||
// not supported so return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function adduser($username, $level = 0, $email = '', $realname = '', $can_modify_passwd = 0, $description = '')
|
||||
{
|
||||
// not supported so return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
function user_exists_in_db($username)
|
||||
{
|
||||
$return = dbFetchCell('SELECT COUNT(*) FROM users WHERE username = ?', array($username), true);
|
||||
return $return;
|
||||
}
|
||||
|
||||
function user_exists($username)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
ad_bind($ldap_connection); // make sure we called bind
|
||||
|
||||
$search = ldap_search(
|
||||
$ldap_connection,
|
||||
$config['auth_ad_base_dn'],
|
||||
get_auth_ad_user_filter($username),
|
||||
array('samaccountname')
|
||||
);
|
||||
$entries = ldap_get_entries($ldap_connection, $search);
|
||||
|
||||
|
||||
if ($entries['count']) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function get_userlevel($username)
|
||||
{
|
||||
global $ldap_connection;
|
||||
ad_bind($ldap_connection); // make sure we called bind
|
||||
|
||||
$userlevel = 0;
|
||||
if (!Config::get('auth_ad_require_groupmembership', true)) {
|
||||
if (Config::get('auth_ad_global_read', false)) {
|
||||
$userlevel = 5;
|
||||
}
|
||||
}
|
||||
|
||||
// cycle through defined groups, test for memberOf-ship
|
||||
foreach (Config::get('auth_ad_groups', array()) as $group => $level) {
|
||||
try {
|
||||
if (user_in_group($username, $group)) {
|
||||
$userlevel = max($userlevel, $level['level']);
|
||||
}
|
||||
} catch (AuthenticationException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
return $userlevel;
|
||||
}
|
||||
|
||||
|
||||
function get_userid($username)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
ad_bind($ldap_connection); // make sure we called bind
|
||||
|
||||
$attributes = array('objectsid');
|
||||
$search = ldap_search(
|
||||
$ldap_connection,
|
||||
$config['auth_ad_base_dn'],
|
||||
get_auth_ad_user_filter($username),
|
||||
$attributes
|
||||
);
|
||||
$entries = ldap_get_entries($ldap_connection, $search);
|
||||
|
||||
if ($entries['count']) {
|
||||
return get_userid_from_sid(sid_from_ldap($entries[0]['objectsid'][0]));
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
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']);
|
||||
|
||||
$search = ldap_read(
|
||||
$ldap_connection,
|
||||
$dn_candidate,
|
||||
'(objectClass=*)',
|
||||
array('objectsid')
|
||||
);
|
||||
$entry = ldap_get_entries($ldap_connection, $search);
|
||||
return substr(sid_from_ldap($entry[0]['objectsid'][0]), 0, 41);
|
||||
}
|
||||
|
||||
function get_user($user_id)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
ad_bind($ldap_connection); // make sure we called bind
|
||||
|
||||
$domain_sid = get_domain_sid();
|
||||
|
||||
$search_filter = "(&(objectcategory=person)(objectclass=user)(objectsid=$domain_sid-$user_id))";
|
||||
$attributes = array('samaccountname', 'displayname', 'objectsid', 'mail');
|
||||
$search = ldap_search($ldap_connection, $config['auth_ad_base_dn'], $search_filter, $attributes);
|
||||
$entry = ldap_get_entries($ldap_connection, $search);
|
||||
|
||||
if (isset($entry[0]['samaccountname'][0])) {
|
||||
return user_from_ad($entry[0]);
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
function deluser($userid)
|
||||
{
|
||||
dbDelete('bill_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('devices_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('ports_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('users_prefs', '`user_id` = ?', array($userid));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function get_userlist()
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
ad_bind($ldap_connection); // make sure we called bind
|
||||
|
||||
$userlist = array();
|
||||
$ldap_groups = get_group_list();
|
||||
|
||||
foreach ($ldap_groups as $ldap_group) {
|
||||
$search_filter = "(memberOf=$ldap_group)";
|
||||
if ($config['auth_ad_user_filter']) {
|
||||
$search_filter = "(&{$config['auth_ad_user_filter']}$search_filter)";
|
||||
}
|
||||
$attributes = array('samaccountname', 'displayname', 'objectsid', 'mail');
|
||||
$search = ldap_search($ldap_connection, $config['auth_ad_base_dn'], $search_filter, $attributes);
|
||||
$results = ldap_get_entries($ldap_connection, $search);
|
||||
|
||||
foreach ($results as $result) {
|
||||
if (isset($result['samaccountname'][0])) {
|
||||
$userlist[$result['samaccountname'][0]] = user_from_ad($result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array_values($userlist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a user array from an AD LDAP entry
|
||||
* Must have the attributes: objectsid, samaccountname, displayname, mail
|
||||
* @internal
|
||||
*
|
||||
* @param $entry
|
||||
* @return array
|
||||
*/
|
||||
function user_from_ad($entry)
|
||||
{
|
||||
return array(
|
||||
'user_id' => get_userid_from_sid(sid_from_ldap($entry['objectsid'][0])),
|
||||
'username' => $entry['samaccountname'][0],
|
||||
'realname' => $entry['displayname'][0],
|
||||
'email' => $entry['mail'][0],
|
||||
'descr' => '',
|
||||
'level' => get_userlevel($entry['samaccountname'][0]),
|
||||
'can_modify_passwd' => 0,
|
||||
'twofactor' => 0,
|
||||
// 'dashboard' => 'broken!',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function can_update_users()
|
||||
{
|
||||
// not supported so return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function update_user($user_id, $realname, $level, $can_modify_passwd, $email)
|
||||
{
|
||||
// not supported so return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
function get_email($username)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
ad_bind($ldap_connection); // make sure we called bind
|
||||
|
||||
$attributes = array('mail');
|
||||
$search = ldap_search(
|
||||
$ldap_connection,
|
||||
$config['auth_ad_base_dn'],
|
||||
get_auth_ad_user_filter($username),
|
||||
$attributes
|
||||
);
|
||||
$result = ldap_get_entries($ldap_connection, $search);
|
||||
unset($result[0]['mail']['count']);
|
||||
return current($result[0]['mail']);
|
||||
}
|
||||
|
||||
function get_fullname($username)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
ad_bind($ldap_connection); // make sure we called bind
|
||||
|
||||
$attributes = array('name');
|
||||
$result = ldap_search(
|
||||
$ldap_connection,
|
||||
$config['auth_ad_base_dn'],
|
||||
get_auth_ad_user_filter($username),
|
||||
$attributes
|
||||
);
|
||||
$entries = ldap_get_entries($ldap_connection, $result);
|
||||
if ($entries['count'] > 0) {
|
||||
$membername = $entries[0]['name'][0];
|
||||
} else {
|
||||
$membername = $username;
|
||||
}
|
||||
|
||||
return $membername;
|
||||
}
|
||||
|
||||
|
||||
function get_group_list()
|
||||
{
|
||||
global $config;
|
||||
|
||||
$ldap_groups = array();
|
||||
|
||||
// show all Active Directory Users by default
|
||||
$default_group = 'Users';
|
||||
|
||||
if (isset($config['auth_ad_group'])) {
|
||||
if ($config['auth_ad_group'] !== $default_group) {
|
||||
$ldap_groups[] = $config['auth_ad_group'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($config['auth_ad_groups']) && !isset($config['auth_ad_group'])) {
|
||||
$ldap_groups[] = get_dn($default_group);
|
||||
}
|
||||
|
||||
foreach ($config['auth_ad_groups'] as $key => $value) {
|
||||
$ldap_groups[] = get_dn($key);
|
||||
}
|
||||
|
||||
return $ldap_groups;
|
||||
}
|
||||
|
||||
function get_dn($samaccountname)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
ad_bind($ldap_connection); // make sure we called bind
|
||||
|
||||
$attributes = array('dn');
|
||||
$result = ldap_search(
|
||||
$ldap_connection,
|
||||
$config['auth_ad_base_dn'],
|
||||
get_auth_ad_group_filter($samaccountname),
|
||||
$attributes
|
||||
);
|
||||
$entries = ldap_get_entries($ldap_connection, $result);
|
||||
if ($entries['count'] > 0) {
|
||||
return $entries[0]['dn'];
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function get_cn($dn)
|
||||
{
|
||||
$dn = str_replace('\\,', '~C0mmA~', $dn);
|
||||
preg_match('/[^,]*/', $dn, $matches, PREG_OFFSET_CAPTURE, 3);
|
||||
return str_replace('~C0mmA~', ',', $matches[0][0]);
|
||||
}
|
||||
|
||||
function get_userid_from_sid($sid)
|
||||
{
|
||||
return preg_replace('/.*-(\d+)$/', '$1', $sid);
|
||||
}
|
||||
|
||||
function sid_from_ldap($sid)
|
||||
{
|
||||
$sidUnpacked = unpack('H*hex', $sid);
|
||||
$sidHex = array_shift($sidUnpacked);
|
||||
$subAuths = unpack('H2/H2/n/N/V*', $sid);
|
||||
$revLevel = hexdec(substr($sidHex, 0, 2));
|
||||
$authIdent = hexdec(substr($sidHex, 4, 12));
|
||||
return 'S-'.$revLevel.'-'.$authIdent.'-'.implode('-', $subAuths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind to AD with the bind user if available, otherwise anonymous bind
|
||||
* @internal
|
||||
*
|
||||
* @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, $force = false)
|
||||
{
|
||||
global $config, $ad_init;
|
||||
|
||||
if ($ad_init && !$force) {
|
||||
return true; // bind already attempted
|
||||
}
|
||||
|
||||
// set timeout
|
||||
ldap_set_option(
|
||||
$connection,
|
||||
LDAP_OPT_NETWORK_TIMEOUT,
|
||||
isset($config['auth_ad_timeout']) ? isset($config['auth_ad_timeout']) : 5
|
||||
);
|
||||
|
||||
// With specified bind user
|
||||
if (isset($config['auth_ad_binduser'], $config['auth_ad_bindpassword'])) {
|
||||
$ad_init = true;
|
||||
$bind = ldap_bind(
|
||||
$connection,
|
||||
"${config['auth_ad_binduser']}@${config['auth_ad_domain']}",
|
||||
"${config['auth_ad_bindpassword']}"
|
||||
);
|
||||
ldap_set_option($connection, LDAP_OPT_NETWORK_TIMEOUT, -1); // restore timeout
|
||||
return $bind;
|
||||
}
|
||||
|
||||
$bind = false;
|
||||
|
||||
// Anonymous
|
||||
if ($allow_anonymous) {
|
||||
$ad_init = true;
|
||||
$bind = ldap_bind($connection);
|
||||
}
|
||||
|
||||
ldap_set_option($connection, LDAP_OPT_NETWORK_TIMEOUT, -1); // restore timeout
|
||||
return $bind;
|
||||
}
|
@ -1,401 +0,0 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
|
||||
function init_auth()
|
||||
{
|
||||
global $ldap_connection, $config;
|
||||
|
||||
if (! isset($_SESSION['username'])) {
|
||||
$_SESSION['username'] = '';
|
||||
}
|
||||
|
||||
// Disable certificate checking before connect if required
|
||||
if (isset($config['auth_ad_check_certificates']) &&
|
||||
$config['auth_ad_check_certificates'] == 0) {
|
||||
putenv('LDAPTLS_REQCERT=never');
|
||||
};
|
||||
|
||||
// Set up connection to LDAP server
|
||||
$ldap_connection = @ldap_connect($config['auth_ad_url']);
|
||||
if (! $ldap_connection) {
|
||||
echo '<h2>Fatal error while connecting to AD url ' . $config['auth_ad_url'] . ': ' . ldap_error($ldap_connection) . '</h2>';
|
||||
exit;
|
||||
}
|
||||
|
||||
// disable referrals and force ldap version to 3
|
||||
ldap_set_option($ldap_connection, LDAP_OPT_REFERRALS, 0);
|
||||
ldap_set_option($ldap_connection, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
|
||||
// Bind to AD
|
||||
if (isset($config['auth_ad_binduser']) && isset($config['auth_ad_bindpassword'])) {
|
||||
// With specified bind user
|
||||
if (! ldap_bind($ldap_connection, "${config['auth_ad_binduser']}@${config['auth_ad_domain']}", "${config['auth_ad_bindpassword']}")) {
|
||||
echo ldap_error($ldap_connection);
|
||||
}
|
||||
} else {
|
||||
// Anonymous
|
||||
if (! ldap_bind($ldap_connection)) {
|
||||
echo ldap_error($ldap_connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function authenticate($username, $password)
|
||||
{
|
||||
global $config;
|
||||
|
||||
if (isset($_SERVER['REMOTE_USER'])) {
|
||||
$_SESSION['username'] = mres($_SERVER['REMOTE_USER']);
|
||||
|
||||
if (user_exists($_SESSION['username'])) {
|
||||
adduser($username);
|
||||
return 1;
|
||||
}
|
||||
|
||||
$_SESSION['username'] = $config['http_auth_guest'];
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
|
||||
function reauthenticate($sess_id, $token)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function passwordscanchange()
|
||||
{
|
||||
// not supported so return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function changepassword()
|
||||
{
|
||||
// not supported so return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function auth_usermanagement()
|
||||
{
|
||||
// not supported so return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function adduser($username, $level = 0, $email = '', $realname = '', $can_modify_passwd = 0, $description = '')
|
||||
{
|
||||
// Check to see if user is already added in the database
|
||||
if (!user_exists_in_db($username)) {
|
||||
$userid = dbInsert(array('username' => $username, 'realname' => $realname, 'email' => $email, 'descr' => $description, 'level' => $level, 'can_modify_passwd' => $can_modify_passwd, 'user_id' => get_userid($username)), 'users');
|
||||
if ($userid == false) {
|
||||
return false;
|
||||
} else {
|
||||
foreach (dbFetchRows('select notifications.* from notifications where not exists( select 1 from notifications_attribs where notifications.notifications_id = notifications_attribs.notifications_id and notifications_attribs.user_id = ?) order by notifications.notifications_id desc', array($userid)) as $notif) {
|
||||
dbInsert(array('notifications_id'=>$notif['notifications_id'],'user_id'=>$userid,'key'=>'read','value'=>1), 'notifications_attribs');
|
||||
}
|
||||
}
|
||||
return $userid;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function user_exists_in_db($username)
|
||||
{
|
||||
$return = dbFetchCell('SELECT COUNT(*) FROM users WHERE username = ?', array($username), true);
|
||||
return $return;
|
||||
}
|
||||
|
||||
function user_exists($username)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
|
||||
if (auth_ldap_session_cache_get('user_exists')) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$search = ldap_search(
|
||||
$ldap_connection,
|
||||
$config['auth_ad_base_dn'],
|
||||
get_auth_ad_user_filter($username),
|
||||
array('samaccountname')
|
||||
);
|
||||
$entries = ldap_get_entries($ldap_connection, $search);
|
||||
|
||||
if ($entries['count']) {
|
||||
/*
|
||||
* Cache positiv result as this will result in more queries which we
|
||||
* want to speed up.
|
||||
*/
|
||||
auth_ldap_session_cache_set('user_exists', 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function get_userlevel($username)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
|
||||
$userlevel = auth_ldap_session_cache_get('userlevel');
|
||||
if ($userlevel) {
|
||||
return $userlevel;
|
||||
} else {
|
||||
$userlevel = 0;
|
||||
}
|
||||
|
||||
// Find all defined groups $username is in
|
||||
$search = ldap_search(
|
||||
$ldap_connection,
|
||||
$config['auth_ad_base_dn'],
|
||||
get_auth_ad_user_filter($username),
|
||||
array('memberOf')
|
||||
);
|
||||
$entries = ldap_get_entries($ldap_connection, $search);
|
||||
|
||||
// Loop the list and find the highest level
|
||||
foreach ($entries[0]['memberof'] as $entry) {
|
||||
$group_cn = get_cn($entry);
|
||||
if ($config['auth_ad_groups'][$group_cn]['level'] > $userlevel) {
|
||||
$userlevel = $config['auth_ad_groups'][$group_cn]['level'];
|
||||
}
|
||||
}
|
||||
|
||||
auth_ldap_session_cache_set('userlevel', $userlevel);
|
||||
return $userlevel;
|
||||
}
|
||||
|
||||
|
||||
function get_userid($username)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
|
||||
$user_id = auth_ldap_session_cache_get('userid');
|
||||
if (isset($user_id)) {
|
||||
return $user_id;
|
||||
} else {
|
||||
$user_id = -1;
|
||||
}
|
||||
|
||||
$attributes = array('objectsid');
|
||||
$search = ldap_search(
|
||||
$ldap_connection,
|
||||
$config['auth_ad_base_dn'],
|
||||
get_auth_ad_user_filter($username),
|
||||
$attributes
|
||||
);
|
||||
$entries = ldap_get_entries($ldap_connection, $search);
|
||||
|
||||
if ($entries['count']) {
|
||||
$user_id = preg_replace('/.*-(\d+)$/', '$1', sid_from_ldap($entries[0]['objectsid'][0]));
|
||||
}
|
||||
|
||||
auth_ldap_session_cache_set('userid', $user_id);
|
||||
return $user_id;
|
||||
}
|
||||
|
||||
|
||||
function deluser($userid)
|
||||
{
|
||||
dbDelete('bill_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('devices_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('ports_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('users_prefs', '`user_id` = ?', array($userid));
|
||||
dbDelete('users', '`user_id` = ?', array($userid));
|
||||
return dbDelete('users', '`user_id` = ?', array($userid));
|
||||
}
|
||||
|
||||
|
||||
function get_userlist()
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
$userlist = array();
|
||||
$userhash = array();
|
||||
|
||||
$ldap_groups = get_group_list();
|
||||
|
||||
foreach ($ldap_groups as $ldap_group) {
|
||||
$search_filter = "(memberOf=$ldap_group)";
|
||||
if ($config['auth_ad_user_filter']) {
|
||||
$search_filter = "(&{$config['auth_ad_user_filter']}$search_filter)";
|
||||
}
|
||||
$search = ldap_search($ldap_connection, $config['auth_ad_base_dn'], $search_filter, array('samaccountname','displayname','objectsid','mail'));
|
||||
$results = ldap_get_entries($ldap_connection, $search);
|
||||
|
||||
foreach ($results as $result) {
|
||||
if (isset($result['samaccountname'][0])) {
|
||||
$userid = preg_replace(
|
||||
'/.*-(\d+)$/',
|
||||
'$1',
|
||||
sid_from_ldap($result['objectsid'][0])
|
||||
);
|
||||
|
||||
// don't make duplicates, user may be member of more than one group
|
||||
$userhash[$result['samaccountname'][0]] = array(
|
||||
'realname' => $result['displayName'][0],
|
||||
'user_id' => $userid,
|
||||
'email' => $result['mail'][0]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array_keys($userhash) as $key) {
|
||||
$userlist[] = array(
|
||||
'username' => $key,
|
||||
'realname' => $userhash[$key]['realname'],
|
||||
'user_id' => $userhash[$key]['user_id'],
|
||||
'email' => $userhash[$key]['email']
|
||||
);
|
||||
}
|
||||
|
||||
return $userlist;
|
||||
}
|
||||
|
||||
|
||||
function can_update_users()
|
||||
{
|
||||
// not supported so return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function get_user($user_id)
|
||||
{
|
||||
// not supported so return 0
|
||||
return dbFetchRow('SELECT * FROM `users` WHERE `user_id` = ?', array($user_id), true);
|
||||
}
|
||||
|
||||
|
||||
function update_user($user_id, $realname, $level, $can_modify_passwd, $email)
|
||||
{
|
||||
dbUpdate(array('realname' => $realname, 'can_modify_passwd' => $can_modify_passwd, 'email' => $email), 'users', '`user_id` = ?', array($user_id));
|
||||
}
|
||||
|
||||
|
||||
function get_fullname($username)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
|
||||
$attributes = array('name');
|
||||
$result = ldap_search(
|
||||
$ldap_connection,
|
||||
$config['auth_ad_base_dn'],
|
||||
get_auth_ad_user_filter($username),
|
||||
$attributes
|
||||
);
|
||||
$entries = ldap_get_entries($ldap_connection, $result);
|
||||
if ($entries['count'] > 0) {
|
||||
$membername = $entries[0]['name'][0];
|
||||
} else {
|
||||
$membername = $username;
|
||||
}
|
||||
|
||||
return $membername;
|
||||
}
|
||||
|
||||
|
||||
function get_group_list()
|
||||
{
|
||||
global $config;
|
||||
|
||||
$ldap_groups = array();
|
||||
|
||||
// show all Active Directory Users by default
|
||||
$default_group = 'Users';
|
||||
|
||||
if (isset($config['auth_ad_group'])) {
|
||||
if ($config['auth_ad_group'] !== $default_group) {
|
||||
$ldap_groups[] = $config['auth_ad_group'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($config['auth_ad_groups']) && !isset($config['auth_ad_group'])) {
|
||||
$ldap_groups[] = get_dn($default_group);
|
||||
}
|
||||
|
||||
foreach ($config['auth_ad_groups'] as $key => $value) {
|
||||
$ldap_groups[] = get_dn($key);
|
||||
}
|
||||
|
||||
return $ldap_groups;
|
||||
}
|
||||
|
||||
function get_dn($samaccountname)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
|
||||
|
||||
$attributes = array('dn');
|
||||
$result = ldap_search(
|
||||
$ldap_connection,
|
||||
$config['auth_ad_base_dn'],
|
||||
get_auth_ad_group_filter($samaccountname),
|
||||
$attributes
|
||||
);
|
||||
$entries = ldap_get_entries($ldap_connection, $result);
|
||||
if ($entries['count'] > 0) {
|
||||
return $entries[0]['dn'];
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function get_cn($dn)
|
||||
{
|
||||
preg_match('/[^,]*/', $dn, $matches, PREG_OFFSET_CAPTURE, 3);
|
||||
return $matches[0][0];
|
||||
}
|
||||
|
||||
function sid_from_ldap($sid)
|
||||
{
|
||||
$sidHex = unpack('H*hex', $sid);
|
||||
$subAuths = unpack('H2/H2/n/N/V*', $sid);
|
||||
$revLevel = hexdec(substr($sidHex, 0, 2));
|
||||
$authIdent = hexdec(substr($sidHex, 4, 12));
|
||||
return 'S-'.$revLevel.'-'.$authIdent.'-'.implode('-', $subAuths);
|
||||
}
|
||||
|
||||
function auth_ldap_session_cache_get($attr)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$ttl = 300;
|
||||
if ($config['auth_ldap_cache_ttl']) {
|
||||
$ttl = $config['auth_ldap_cache_ttl'];
|
||||
}
|
||||
|
||||
// auth_ldap cache present in this session?
|
||||
if (! isset($_SESSION['auth_ldap'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$cache = $_SESSION['auth_ldap'];
|
||||
|
||||
// $attr present in cache?
|
||||
if (! isset($cache[$attr])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Value still valid?
|
||||
if (time() - $cache[$attr]['last_updated'] >= $ttl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $cache[$attr]['value'];
|
||||
}
|
||||
|
||||
|
||||
function auth_ldap_session_cache_set($attr, $value)
|
||||
{
|
||||
$_SESSION['auth_ldap'][$attr]['value'] = $value;
|
||||
$_SESSION['auth_ldap'][$attr]['last_updated'] = time();
|
||||
}
|
@ -1,200 +0,0 @@
|
||||
<?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\Authentication\TwoFactor;
|
||||
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;
|
||||
|
||||
// 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');
|
||||
}
|
||||
|
||||
if (!session_authenticated()) {
|
||||
// check twofactor
|
||||
if ($config['twofactor'] === true && !isset($_SESSION['twofactor'])) {
|
||||
if (TwoFactor::showForm()) {
|
||||
return false; // not done yet, one more cycle to show the 2fa form
|
||||
}
|
||||
}
|
||||
|
||||
// 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');
|
||||
}
|
||||
}
|
||||
|
||||
if (session_authenticated()) {
|
||||
set_remember_me();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the session is authenticated
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function session_authenticated()
|
||||
{
|
||||
return isset($_SESSION['authenticated']) && $_SESSION['authenticated'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or update the remember me cookie if $_SESSION['remember'] is set
|
||||
* If setting a new cookie, $_SESSION['username'] must be set
|
||||
*/
|
||||
function set_remember_me()
|
||||
{
|
||||
global $config;
|
||||
|
||||
if (!isset($_SESSION['remember'])) {
|
||||
return;
|
||||
}
|
||||
unset($_SESSION['remember']);
|
||||
|
||||
$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, $config['secure_cookies'], true);
|
||||
setcookie('token', $token_id, $expiration, '/', null, $config['secure_cookies'], true);
|
||||
setcookie('auth', $auth, $expiration, '/', null, $config['secure_cookies'], 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, '/', null, $config['secure_cookies']);
|
||||
setcookie('token', '', $time, '/', null, $config['secure_cookies']);
|
||||
setcookie('auth', '', $time, '/', null, $config['secure_cookies']);
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
use Phpass\PasswordHash;
|
||||
|
||||
function init_auth()
|
||||
{
|
||||
}
|
||||
|
||||
function authenticate($username, $password)
|
||||
{
|
||||
if (user_exists($username)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new AuthenticationException('No matching user found and http_auth_guest is not set');
|
||||
}
|
||||
|
||||
|
||||
function reauthenticate($sess_id, $token)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function passwordscanchange($username = '')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function changepassword($username, $newpassword)
|
||||
{
|
||||
// Not supported
|
||||
}
|
||||
|
||||
|
||||
function auth_usermanagement()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
function adduser($username, $password, $level, $email = '', $realname = '', $can_modify_passwd = 1, $description = '')
|
||||
{
|
||||
if (!user_exists($username)) {
|
||||
$hasher = new PasswordHash(8, false);
|
||||
$encrypted = $hasher->HashPassword($password);
|
||||
$userid = dbInsert(array('username' => $username, 'password' => $encrypted, 'level' => $level, 'email' => $email, 'realname' => $realname, 'can_modify_passwd' => $can_modify_passwd, 'descr' => $description), 'users');
|
||||
if ($userid == false) {
|
||||
return false;
|
||||
} else {
|
||||
foreach (dbFetchRows('select notifications.* from notifications where not exists( select 1 from notifications_attribs where notifications.notifications_id = notifications_attribs.notifications_id and notifications_attribs.user_id = ?) order by notifications.notifications_id desc', array($userid)) as $notif) {
|
||||
dbInsert(array('notifications_id'=>$notif['notifications_id'],'user_id'=>$userid,'key'=>'read','value'=>1), 'notifications_attribs');
|
||||
}
|
||||
}
|
||||
return $userid;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function user_exists($username)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$query = 'SELECT COUNT(*) FROM `users` WHERE `username`=?';
|
||||
$params = array($username);
|
||||
|
||||
if (isset($config['http_auth_guest'])) {
|
||||
$query .= ' OR `username`=?';
|
||||
$params[] = $config['http_auth_guest'];
|
||||
}
|
||||
|
||||
return dbFetchCell($query, $params) > 0;
|
||||
}
|
||||
|
||||
|
||||
function get_userlevel($username)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$user_level = dbFetchCell('SELECT `level` FROM `users` WHERE `username`=?', array($username));
|
||||
|
||||
if ($user_level) {
|
||||
return $user_level;
|
||||
}
|
||||
|
||||
if (isset($config['http_auth_guest'])) {
|
||||
return dbFetchCell('SELECT `level` FROM `users` WHERE `username`=?', array($config['http_auth_guest']));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function get_userid($username)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$user_id = dbFetchCell('SELECT `user_id` FROM `users` WHERE `username`=?', array($username));
|
||||
|
||||
if ($user_id) {
|
||||
return $user_id;
|
||||
}
|
||||
|
||||
if (isset($config['http_auth_guest'])) {
|
||||
return dbFetchCell('SELECT `user_id` FROM `users` WHERE `username`=?', array($config['http_auth_guest']));
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
function deluser($username)
|
||||
{
|
||||
// Not supported
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function get_userlist()
|
||||
{
|
||||
return dbFetchRows('SELECT * FROM `users`');
|
||||
}
|
||||
|
||||
|
||||
function can_update_users()
|
||||
{
|
||||
// supported so return 1
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
function get_user($user_id)
|
||||
{
|
||||
return dbFetchRow('SELECT * FROM `users` WHERE `user_id` = ?', array($user_id));
|
||||
}
|
||||
|
||||
|
||||
function update_user($user_id, $realname, $level, $can_modify_passwd, $email)
|
||||
{
|
||||
dbUpdate(array('realname' => $realname, 'level' => $level, 'can_modify_passwd' => $can_modify_passwd, 'email' => $email), 'users', '`user_id` = ?', array($user_id));
|
||||
}
|
@ -1,354 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* libreNMS HTTP-Authentication and LDAP Authorization Library
|
||||
* @author Maximilian Wilhelm <max@rfc2324.org>
|
||||
* @copyright 2016 LibreNMS, Barbarossa
|
||||
* @license GPL
|
||||
* @package LibreNMS
|
||||
* @subpackage Authentication
|
||||
*
|
||||
* This Authentitation / Authorization module provides the ability to let
|
||||
* the webserver (e.g. Apache) do the user Authentication (using Kerberos
|
||||
* f.e.) and let libreNMS do the Authorization of the already known user.
|
||||
* Authorization and setting of libreNMS user level is done by LDAP group
|
||||
* names specified in the configuration file. The group configuration is
|
||||
* basicly copied from the existing ldap Authentication module.
|
||||
*
|
||||
* Most of the code is copied from the http-auth and ldap Authentication
|
||||
* modules already existing.
|
||||
*
|
||||
* To save lots of redundant queries to the LDAP server and speed up the
|
||||
* libreNMS WebUI, all information is cached within the PHP $_SESSION as
|
||||
* long as specified in $config['auth_ldap_cache_ttl'] (Default: 300s).
|
||||
*/
|
||||
|
||||
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
|
||||
function init_auth()
|
||||
{
|
||||
global $ldap_connection, $config;
|
||||
|
||||
if (! isset($_SESSION['username'])) {
|
||||
$_SESSION['username'] = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up connection to LDAP server
|
||||
*/
|
||||
$ldap_connection = @ldap_connect($config['auth_ldap_server'], $config['auth_ldap_port']);
|
||||
if (! $ldap_connection) {
|
||||
echo '<h2>Fatal error while connecting to LDAP server ' . $config['auth_ldap_server'] . ':' . $config['auth_ldap_port'] . ': ' . ldap_error($ldap_connection) . '</h2>';
|
||||
exit;
|
||||
}
|
||||
if ($config['auth_ldap_version']) {
|
||||
ldap_set_option($ldap_connection, LDAP_OPT_PROTOCOL_VERSION, $config['auth_ldap_version']);
|
||||
}
|
||||
|
||||
if ($config['auth_ldap_starttls'] && ($config['auth_ldap_starttls'] == 'optional' || $config['auth_ldap_starttls'] == 'require')) {
|
||||
$tls = ldap_start_tls($ldap_connection);
|
||||
if ($config['auth_ldap_starttls'] == 'require' && $tls === false) {
|
||||
echo '<h2>Fatal error: LDAP TLS required but not successfully negotiated:' . ldap_error($ldap_connection) . '</h2>';
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function authenticate($username, $password)
|
||||
{
|
||||
global $config;
|
||||
|
||||
if (isset($_SERVER['REMOTE_USER'])) {
|
||||
$_SESSION['username'] = mres($_SERVER['REMOTE_USER']);
|
||||
|
||||
if (user_exists($_SESSION['username'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$_SESSION['username'] = $config['http_auth_guest'];
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
|
||||
function reauthenticate($sess_id, $token)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function passwordscanchange($username = '')
|
||||
{
|
||||
// Not supported
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function changepassword($username, $newpassword)
|
||||
{
|
||||
// Not supported
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function auth_usermanagement()
|
||||
{
|
||||
// Not supported
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function adduser($username, $password, $level, $email = '', $realname = '', $can_modify_passwd = 1, $description = '')
|
||||
{
|
||||
// Not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function user_exists($username)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
|
||||
if (auth_ldap_session_cache_get('user_exists')) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$filter = '(' . $config['auth_ldap_prefix'] . $username . ')';
|
||||
$search = ldap_search($ldap_connection, trim($config['auth_ldap_suffix'], ','), $filter);
|
||||
$entries = ldap_get_entries($ldap_connection, $search);
|
||||
if ($entries['count']) {
|
||||
/*
|
||||
* Cache positiv result as this will result in more queries which we
|
||||
* want to speed up.
|
||||
*/
|
||||
auth_ldap_session_cache_set('user_exists', 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't cache that user doesn't exists as this might be a misconfiguration
|
||||
* on some end and the user will be happy if it "just works" after the user
|
||||
* has been added to LDAP.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function get_userlevel($username)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
|
||||
$userlevel = auth_ldap_session_cache_get('userlevel');
|
||||
if ($userlevel) {
|
||||
return $userlevel;
|
||||
} else {
|
||||
$userlevel = 0;
|
||||
}
|
||||
|
||||
// Find all defined groups $username is in
|
||||
$filter = '(&(|(cn=' . join(')(cn=', array_keys($config['auth_ldap_groups'])) . '))(' . $config['auth_ldap_groupmemberattr'] .'=' . get_membername($username) . '))';
|
||||
$search = ldap_search($ldap_connection, $config['auth_ldap_groupbase'], $filter);
|
||||
$entries = ldap_get_entries($ldap_connection, $search);
|
||||
|
||||
// Loop the list and find the highest level
|
||||
foreach ($entries as $entry) {
|
||||
$groupname = $entry['cn'][0];
|
||||
if ($config['auth_ldap_groups'][$groupname]['level'] > $userlevel) {
|
||||
$userlevel = $config['auth_ldap_groups'][$groupname]['level'];
|
||||
}
|
||||
}
|
||||
|
||||
auth_ldap_session_cache_set('userlevel', $userlevel);
|
||||
return $userlevel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function get_userid($username)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
|
||||
$user_id = auth_ldap_session_cache_get('userid');
|
||||
if (isset($user_id)) {
|
||||
return $user_id;
|
||||
} else {
|
||||
$user_id = -1;
|
||||
}
|
||||
|
||||
$filter = '(' . $config['auth_ldap_prefix'] . $username . ')';
|
||||
$search = ldap_search($ldap_connection, trim($config['auth_ldap_suffix'], ','), $filter);
|
||||
$entries = ldap_get_entries($ldap_connection, $search);
|
||||
|
||||
if ($entries['count']) {
|
||||
$user_id = $entries[0]['uidnumber'][0];
|
||||
}
|
||||
|
||||
auth_ldap_session_cache_set('userid', $user_id);
|
||||
return $user_id;
|
||||
}
|
||||
|
||||
|
||||
function deluser($username)
|
||||
{
|
||||
// Not supported
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function get_userlist()
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
$userlist = array ();
|
||||
|
||||
$filter = '(' . $config['auth_ldap_prefix'] . '*)';
|
||||
|
||||
$search = ldap_search($ldap_connection, trim($config['auth_ldap_suffix'], ','), $filter);
|
||||
$entries = ldap_get_entries($ldap_connection, $search);
|
||||
|
||||
if ($entries['count']) {
|
||||
foreach ($entries as $entry) {
|
||||
$username = $entry['uid'][0];
|
||||
$realname = $entry['cn'][0];
|
||||
$user_id = $entry['uidnumber'][0];
|
||||
$email = $entry[$config['auth_ldap_emailattr']][0];
|
||||
$ldap_groups = get_group_list();
|
||||
foreach ($ldap_groups as $ldap_group) {
|
||||
$ldap_comparison = ldap_compare(
|
||||
$ldap_connection,
|
||||
$ldap_group,
|
||||
$config['auth_ldap_groupmemberattr'],
|
||||
get_membername($username)
|
||||
);
|
||||
if (! isset($config['auth_ldap_group']) || $ldap_comparison === true) {
|
||||
$userlist[] = array(
|
||||
'username' => $username,
|
||||
'realname' => $realname,
|
||||
'user_id' => $user_id,
|
||||
'email' => $email,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $userlist;
|
||||
}
|
||||
|
||||
|
||||
function can_update_users()
|
||||
{
|
||||
// not supported
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function get_user($user_id)
|
||||
{
|
||||
foreach (get_userlist() as $users) {
|
||||
if ($users['user_id'] === $user_id) {
|
||||
return $users['username'];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function update_user($user_id, $realname, $level, $can_modify_passwd, $email)
|
||||
{
|
||||
// Not supported
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function get_membername($username)
|
||||
{
|
||||
global $config, $ldap_connection;
|
||||
if ($config['auth_ldap_groupmembertype'] == 'fulldn') {
|
||||
$membername = $config['auth_ldap_prefix'] . $username . $config['auth_ldap_suffix'];
|
||||
} elseif ($config['auth_ldap_groupmembertype'] == 'puredn') {
|
||||
$filter = '(' . $config['auth_ldap_attr']['uid'] . '=' . $username . ')';
|
||||
$search = ldap_search($ldap_connection, $config['auth_ldap_groupbase'], $filter);
|
||||
$entries = ldap_get_entries($ldap_connection, $search);
|
||||
$membername = $entries[0]['dn'];
|
||||
} else {
|
||||
$membername = $username;
|
||||
}
|
||||
|
||||
return $membername;
|
||||
}
|
||||
|
||||
|
||||
function auth_ldap_session_cache_get($attr)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$ttl = 300;
|
||||
if ($config['auth_ldap_cache_ttl']) {
|
||||
$ttl = $config['auth_ldap_cache_ttl'];
|
||||
}
|
||||
|
||||
// auth_ldap cache present in this session?
|
||||
if (! isset($_SESSION['auth_ldap'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$cache = $_SESSION['auth_ldap'];
|
||||
|
||||
// $attr present in cache?
|
||||
if (! isset($cache[$attr])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Value still valid?
|
||||
if (time() - $cache[$attr]['last_updated'] >= $ttl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$cache[$attr]['value'];
|
||||
}
|
||||
|
||||
|
||||
function auth_ldap_session_cache_set($attr, $value)
|
||||
{
|
||||
$_SESSION['auth_ldap'][$attr]['value'] = $value;
|
||||
$_SESSION['auth_ldap'][$attr]['last_updated'] = time();
|
||||
}
|
||||
|
||||
|
||||
function get_group_list()
|
||||
{
|
||||
global $config;
|
||||
|
||||
$ldap_groups = array();
|
||||
$default_group = 'cn=groupname,ou=groups,dc=example,dc=com';
|
||||
if (isset($config['auth_ldap_group'])) {
|
||||
if ($config['auth_ldap_group'] !== $default_group) {
|
||||
$ldap_groups[] = $config['auth_ldap_group'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($config['auth_ldap_groups'] as $key => $value) {
|
||||
$dn = "cn=$key,".$config['auth_ldap_groupbase'];
|
||||
$ldap_groups[] = $dn;
|
||||
}
|
||||
|
||||
return $ldap_groups;
|
||||
}
|
@ -1,352 +0,0 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
|
||||
function init_auth()
|
||||
{
|
||||
// deferred
|
||||
}
|
||||
|
||||
|
||||
function authenticate($username, $password)
|
||||
{
|
||||
$connection = get_ldap_connection(true);
|
||||
|
||||
if ($username) {
|
||||
if ($password && ldap_bind($connection, get_full_dn($username), $password)) {
|
||||
if (!Config::has('auth_ldap_group')) {
|
||||
return true;
|
||||
} else {
|
||||
$ldap_groups = get_group_list();
|
||||
foreach ($ldap_groups as $ldap_group) {
|
||||
$ldap_comparison = ldap_compare(
|
||||
$connection,
|
||||
$ldap_group,
|
||||
Config::get('auth_ldap_groupmemberattr', 'memberUid'),
|
||||
get_membername($username)
|
||||
);
|
||||
if ($ldap_comparison === true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($password) || $password == '') {
|
||||
throw new AuthenticationException('A password is required');
|
||||
}
|
||||
|
||||
throw new AuthenticationException(ldap_error($connection));
|
||||
}
|
||||
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
|
||||
function reauthenticate($sess_id, $token)
|
||||
{
|
||||
$sess_id = clean($sess_id);
|
||||
$token = clean($token);
|
||||
|
||||
list($username, $hash) = explode('|', $token);
|
||||
|
||||
if (!user_exists($username, true)) {
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
return check_remember_me($sess_id, $token);
|
||||
}
|
||||
|
||||
|
||||
function passwordscanchange($username = '')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function changepassword($username, $newpassword)
|
||||
{
|
||||
// Not supported (for now)
|
||||
}
|
||||
|
||||
|
||||
function auth_usermanagement()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function adduser($username, $password, $level, $email = '', $realname = '', $can_modify_passwd = '1')
|
||||
{
|
||||
// Not supported
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function user_exists($username, $throw_exception = false)
|
||||
{
|
||||
try {
|
||||
$connection = get_ldap_connection();
|
||||
|
||||
$filter = '(' . Config::get('auth_ldap_prefix') . $username . ')';
|
||||
$search = ldap_search($connection, trim(Config::get('auth_ldap_suffix'), ','), $filter);
|
||||
$entries = ldap_get_entries($connection, $search);
|
||||
if ($entries['count']) {
|
||||
return 1;
|
||||
}
|
||||
} catch (AuthenticationException $e) {
|
||||
if ($throw_exception) {
|
||||
throw $e;
|
||||
} else {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function get_userlevel($username)
|
||||
{
|
||||
$userlevel = 0;
|
||||
|
||||
try {
|
||||
$connection = get_ldap_connection();
|
||||
$groups = Config::get('auth_ldap_groups');
|
||||
|
||||
// Find all defined groups $username is in
|
||||
$filter = '(&(|(cn=' . join(')(cn=', array_keys($groups)) . '))(' . Config::get('auth_ldap_groupmemberattr', 'memberUid') . '=' . get_membername($username) . '))';
|
||||
$search = ldap_search($connection, Config::get('auth_ldap_groupbase'), $filter);
|
||||
$entries = ldap_get_entries($connection, $search);
|
||||
|
||||
// Loop the list and find the highest level
|
||||
foreach ($entries as $entry) {
|
||||
$groupname = $entry['cn'][0];
|
||||
if ($groups[$groupname]['level'] > $userlevel) {
|
||||
$userlevel = $groups[$groupname]['level'];
|
||||
}
|
||||
}
|
||||
} catch (AuthenticationException $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
|
||||
return $userlevel;
|
||||
}
|
||||
|
||||
|
||||
function get_userid($username)
|
||||
{
|
||||
try {
|
||||
$connection = get_ldap_connection();
|
||||
|
||||
$filter = '(' . Config::get('auth_ldap_prefix') . $username . ')';
|
||||
$search = ldap_search($connection, trim(Config::get('auth_ldap_suffix'), ','), $filter);
|
||||
$entries = ldap_get_entries($connection, $search);
|
||||
|
||||
if ($entries['count']) {
|
||||
$uid_attr = strtolower(Config::get('auth_ldap_uid_attribute', 'uidnumber'));
|
||||
return $entries[0][$uid_attr][0];
|
||||
}
|
||||
} catch (AuthenticationException $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
function deluser($username)
|
||||
{
|
||||
// Not supported
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function get_userlist()
|
||||
{
|
||||
$userlist = array();
|
||||
|
||||
try {
|
||||
$connection = get_ldap_connection();
|
||||
|
||||
$filter = '(' . Config::get('auth_ldap_prefix') . '*)';
|
||||
$search = ldap_search($connection, trim(Config::get('auth_ldap_suffix'), ','), $filter);
|
||||
$entries = ldap_get_entries($connection, $search);
|
||||
|
||||
if ($entries['count']) {
|
||||
foreach ($entries as $entry) {
|
||||
$username = $entry['uid'][0];
|
||||
$realname = $entry['cn'][0];
|
||||
$uid_attr = strtolower(Config::get('auth_ldap_uid_attribute', 'uidnumber'));
|
||||
$user_id = $entry[$uid_attr][0];
|
||||
$email = $entry[Config::get('auth_ldap_emailattr', 'mail')][0];
|
||||
$ldap_groups = get_group_list();
|
||||
foreach ($ldap_groups as $ldap_group) {
|
||||
$ldap_comparison = ldap_compare(
|
||||
$connection,
|
||||
$ldap_group,
|
||||
Config::get('auth_ldap_groupmemberattr', 'memberUid'),
|
||||
get_membername($username)
|
||||
);
|
||||
if (!Config::has('auth_ldap_group') || $ldap_comparison === true) {
|
||||
$userlist[$username] = array(
|
||||
'username' => $username,
|
||||
'realname' => $realname,
|
||||
'user_id' => $user_id,
|
||||
'email' => $email,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (AuthenticationException $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
|
||||
return $userlist;
|
||||
}
|
||||
|
||||
|
||||
function can_update_users()
|
||||
{
|
||||
// not supported so return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function get_user($user_id)
|
||||
{
|
||||
foreach (get_userlist() as $user) {
|
||||
if ($user['user_id'] === $user_id) {
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function update_user($user_id, $realname, $level, $can_modify_passwd, $email)
|
||||
{
|
||||
// not supported
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function get_membername($username)
|
||||
{
|
||||
$type = Config::get('auth_ldap_groupmembertype');
|
||||
|
||||
if ($type == 'fulldn') {
|
||||
return get_full_dn($username);
|
||||
}
|
||||
|
||||
if ($type == 'puredn') {
|
||||
try {
|
||||
$connection = get_ldap_connection();
|
||||
$filter = '(' . Config::get('auth_ldap_attr.uid') . '=' . $username . ')';
|
||||
$search = ldap_search($connection, Config::get('auth_ldap_groupbase'), $filter);
|
||||
$entries = ldap_get_entries($connection, $search);
|
||||
return $entries[0]['dn'];
|
||||
} catch (AuthenticationException $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
return $username;
|
||||
}
|
||||
|
||||
|
||||
function get_group_list()
|
||||
{
|
||||
$ldap_groups = array();
|
||||
|
||||
$default_group = 'cn=groupname,ou=groups,dc=example,dc=com'; // in the documentation
|
||||
if (Config::get('auth_ldap_group', $default_group) !== $default_group) {
|
||||
$ldap_groups[] = Config::get('auth_ldap_group');
|
||||
}
|
||||
|
||||
foreach (Config::get('auth_ldap_groups') as $key => $value) {
|
||||
$ldap_groups[] = "cn=$key,".Config::get('auth_ldap_groupbase');
|
||||
}
|
||||
|
||||
return $ldap_groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full dn with auth_ldap_prefix and auth_ldap_suffix
|
||||
* @internal
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function get_full_dn($username)
|
||||
{
|
||||
return Config::get('auth_ldap_prefix', '') . $username . Config::get('auth_ldap_suffix', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ldap connection. If it hasn't been established yet, connect and try to bind.
|
||||
* @internal
|
||||
*
|
||||
* @param bool $skip_bind do not attempt to bind on connection
|
||||
* @return false|resource
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
function get_ldap_connection($skip_bind = false)
|
||||
{
|
||||
global $ldap_connection;
|
||||
|
||||
if ($ldap_connection) {
|
||||
return $ldap_connection; // bind already attempted
|
||||
}
|
||||
|
||||
$ldap_connection = @ldap_connect(Config::get('auth_ldap_server'), Config::get('auth_ldap_port', 389));
|
||||
|
||||
if (!$ldap_connection) {
|
||||
throw new AuthenticationException('Unable to connect to ldap server');
|
||||
}
|
||||
|
||||
ldap_set_option($ldap_connection, LDAP_OPT_PROTOCOL_VERSION, Config::get('auth_ldap_version', 2));
|
||||
|
||||
$use_tls = Config::get('auth_ldap_starttls');
|
||||
if ($use_tls == 'optional'||$use_tls == 'require') {
|
||||
$tls_success = ldap_start_tls($ldap_connection);
|
||||
if ($use_tls == 'require' && $tls_success === false) {
|
||||
$error = ldap_error($ldap_connection);
|
||||
throw new AuthenticationException("Fatal error: LDAP TLS required but not successfully negotiated: $error");
|
||||
}
|
||||
}
|
||||
|
||||
if ($skip_bind) {
|
||||
return $ldap_connection;
|
||||
}
|
||||
|
||||
// set timeout
|
||||
ldap_set_option($ldap_connection, LDAP_OPT_NETWORK_TIMEOUT, Config::get('auth_ldap_timeout', 5));
|
||||
|
||||
// With specified bind user
|
||||
if ((Config::has('auth_ldap_binduser') || Config::has('auth_ldap_binddn'))
|
||||
&& Config::has('auth_ldap_bindpassword')
|
||||
) {
|
||||
if (Config::has('auth_ldap_binddn')) {
|
||||
$bind_dn = Config::get('auth_ldap_binddn');
|
||||
} else {
|
||||
$bind_dn = get_full_dn(Config::get('auth_ldap_binduser'));
|
||||
}
|
||||
|
||||
if (ldap_bind(
|
||||
$ldap_connection,
|
||||
$bind_dn,
|
||||
Config::get('auth_ldap_bindpassword')
|
||||
)) {
|
||||
ldap_set_option($ldap_connection, LDAP_OPT_NETWORK_TIMEOUT, -1); // restore timeout
|
||||
return $ldap_connection;
|
||||
}
|
||||
}
|
||||
|
||||
// Anonymous
|
||||
ldap_bind($ldap_connection);
|
||||
|
||||
ldap_set_option($ldap_connection, LDAP_OPT_NETWORK_TIMEOUT, -1); // restore timeout
|
||||
return $ldap_connection;
|
||||
}
|
@ -1,171 +0,0 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
use Phpass\PasswordHash;
|
||||
|
||||
function init_auth()
|
||||
{
|
||||
}
|
||||
|
||||
function authenticate($username, $password)
|
||||
{
|
||||
$encrypted_old = md5($password);
|
||||
$row = dbFetchRow('SELECT username,password FROM `users` WHERE `username`= ?', array($username), true);
|
||||
if ($row['username'] && $row['username'] == $username) {
|
||||
// Migrate from old, unhashed password
|
||||
if ($row['password'] == $encrypted_old) {
|
||||
$row_type = dbFetchRow('DESCRIBE users password');
|
||||
if ($row_type['Type'] == 'varchar(34)') {
|
||||
changepassword($username, $password);
|
||||
}
|
||||
|
||||
return true;
|
||||
} elseif (substr($row['password'], 0, 3) == '$1$') {
|
||||
$row_type = dbFetchRow('DESCRIBE users password');
|
||||
if ($row_type['Type'] == 'varchar(60)') {
|
||||
if ($row['password'] == crypt($password, $row['password'])) {
|
||||
changepassword($username, $password);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$hasher = new PasswordHash(8, false);
|
||||
if ($hasher->CheckPassword($password, $row['password'])) {
|
||||
return true;
|
||||
}
|
||||
}//end if
|
||||
|
||||
throw new AuthenticationException();
|
||||
}//end authenticate()
|
||||
|
||||
|
||||
function reauthenticate($sess_id, $token)
|
||||
{
|
||||
return check_remember_me($sess_id, $token);
|
||||
}//end reauthenticate()
|
||||
|
||||
|
||||
function passwordscanchange($username = '')
|
||||
{
|
||||
/*
|
||||
* By default allow the password to be modified, unless the existing
|
||||
* user is explicitly prohibited to do so.
|
||||
*/
|
||||
|
||||
if (empty($username) || !user_exists($username)) {
|
||||
return 1;
|
||||
} else {
|
||||
return dbFetchCell('SELECT can_modify_passwd FROM users WHERE username = ?', array($username), true);
|
||||
}
|
||||
}//end passwordscanchange()
|
||||
|
||||
|
||||
/**
|
||||
* From: http://code.activestate.com/recipes/576894-generate-a-salt/
|
||||
* This function generates a password salt as a string of x (default = 15) characters
|
||||
* ranging from a-zA-Z0-9.
|
||||
* @param $max integer The number of characters in the string
|
||||
* @author AfroSoft <scripts@afrosoft.co.cc>
|
||||
*/
|
||||
function generateSalt($max = 15)
|
||||
{
|
||||
$characterList = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
$i = 0;
|
||||
$salt = '';
|
||||
do {
|
||||
$salt .= $characterList{mt_rand(0, strlen($characterList))};
|
||||
$i++;
|
||||
} while ($i <= $max);
|
||||
|
||||
return $salt;
|
||||
}//end generateSalt()
|
||||
|
||||
|
||||
function changepassword($username, $password)
|
||||
{
|
||||
$hasher = new PasswordHash(8, false);
|
||||
$encrypted = $hasher->HashPassword($password);
|
||||
return dbUpdate(array('password' => $encrypted), 'users', '`username` = ?', array($username));
|
||||
}//end changepassword()
|
||||
|
||||
|
||||
function auth_usermanagement()
|
||||
{
|
||||
return 1;
|
||||
}//end auth_usermanagement()
|
||||
|
||||
|
||||
function adduser($username, $password, $level, $email = '', $realname = '', $can_modify_passwd = 1, $description = '')
|
||||
{
|
||||
if (!user_exists($username)) {
|
||||
$hasher = new PasswordHash(8, false);
|
||||
$encrypted = $hasher->HashPassword($password);
|
||||
$userid = dbInsert(array('username' => $username, 'password' => $encrypted, 'level' => $level, 'email' => $email, 'realname' => $realname, 'can_modify_passwd' => $can_modify_passwd, 'descr' => $description), 'users');
|
||||
if ($userid == false) {
|
||||
return false;
|
||||
} else {
|
||||
foreach (dbFetchRows('select notifications.* from notifications where not exists( select 1 from notifications_attribs where notifications.notifications_id = notifications_attribs.notifications_id and notifications_attribs.user_id = ?) order by notifications.notifications_id desc', array($userid)) as $notif) {
|
||||
dbInsert(array('notifications_id'=>$notif['notifications_id'],'user_id'=>$userid,'key'=>'read','value'=>1), 'notifications_attribs');
|
||||
}
|
||||
}
|
||||
return $userid;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}//end adduser()
|
||||
|
||||
|
||||
function user_exists($username)
|
||||
{
|
||||
$return = @dbFetchCell('SELECT COUNT(*) FROM users WHERE username = ?', array($username), true);
|
||||
return $return;
|
||||
}//end user_exists()
|
||||
|
||||
|
||||
function get_userlevel($username)
|
||||
{
|
||||
return dbFetchCell('SELECT `level` FROM `users` WHERE `username` = ?', array($username), true);
|
||||
}//end get_userlevel()
|
||||
|
||||
|
||||
function get_userid($username)
|
||||
{
|
||||
return dbFetchCell('SELECT `user_id` FROM `users` WHERE `username` = ?', array($username), true);
|
||||
}//end get_userid()
|
||||
|
||||
|
||||
function deluser($userid)
|
||||
{
|
||||
dbDelete('bill_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('devices_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('ports_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('users_prefs', '`user_id` = ?', array($userid));
|
||||
dbDelete('users', '`user_id` = ?', array($userid));
|
||||
|
||||
return dbDelete('users', '`user_id` = ?', array($userid));
|
||||
}//end deluser()
|
||||
|
||||
|
||||
function get_userlist()
|
||||
{
|
||||
return dbFetchRows('SELECT * FROM `users` ORDER BY `username`');
|
||||
}//end get_userlist()
|
||||
|
||||
|
||||
function can_update_users()
|
||||
{
|
||||
// supported so return 1
|
||||
return 1;
|
||||
}//end can_update_users()
|
||||
|
||||
|
||||
function get_user($user_id)
|
||||
{
|
||||
return dbFetchRow('SELECT * FROM `users` WHERE `user_id` = ?', array($user_id), true);
|
||||
}//end get_user()
|
||||
|
||||
|
||||
function update_user($user_id, $realname, $level, $can_modify_passwd, $email)
|
||||
{
|
||||
dbUpdate(array('realname' => $realname, 'level' => $level, 'can_modify_passwd' => $can_modify_passwd, 'email' => $email), 'users', '`user_id` = ?', array($user_id));
|
||||
}//end update_user()
|
@ -1,137 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Dapphp\Radius\Radius;
|
||||
use LibreNMS\Exceptions\AuthenticationException;
|
||||
use Phpass\PasswordHash;
|
||||
|
||||
function init_auth()
|
||||
{
|
||||
/** @var Radius $radius */
|
||||
global $radius, $config;
|
||||
|
||||
$radius = new Radius($config['radius']['hostname'], $config['radius']['secret'], $config['radius']['suffix'], $config['radius']['timeout'], $config['radius']['port']);
|
||||
}
|
||||
|
||||
function authenticate($username, $password)
|
||||
{
|
||||
global $radius, $debug;
|
||||
|
||||
if (empty($username)) {
|
||||
throw new AuthenticationException('Username is required');
|
||||
}
|
||||
|
||||
if ($debug) {
|
||||
$radius->setDebug(true);
|
||||
}
|
||||
|
||||
if ($radius->accessRequest($username, $password) === true) {
|
||||
adduser($username, $password);
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
function reauthenticate($sess_id, $token)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function passwordscanchange()
|
||||
{
|
||||
// not supported so return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function changepassword()
|
||||
{
|
||||
// not supported so return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function auth_usermanagement()
|
||||
{
|
||||
// not supported so return 0
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
function adduser($username, $password, $level = 1, $email = '', $realname = '', $can_modify_passwd = 0, $description = '')
|
||||
{
|
||||
// Check to see if user is already added in the database
|
||||
global $config;
|
||||
if (!user_exists($username)) {
|
||||
$hasher = new PasswordHash(8, false);
|
||||
$encrypted = $hasher->HashPassword($password);
|
||||
if ($config['radius']['default_level'] > 0) {
|
||||
$level = $config['radius']['default_level'];
|
||||
}
|
||||
$userid = dbInsert(array('username' => $username, 'password' => $encrypted, 'realname' => $realname, 'email' => $email, 'descr' => $description, 'level' => $level, 'can_modify_passwd' => $can_modify_passwd), 'users');
|
||||
if ($userid == false) {
|
||||
return false;
|
||||
} else {
|
||||
foreach (dbFetchRows('select notifications.* from notifications where not exists( select 1 from notifications_attribs where notifications.notifications_id = notifications_attribs.notifications_id and notifications_attribs.user_id = ?) order by notifications.notifications_id desc', array($userid)) as $notif) {
|
||||
dbInsert(array('notifications_id'=>$notif['notifications_id'],'user_id'=>$userid,'key'=>'read','value'=>1), 'notifications_attribs');
|
||||
}
|
||||
}
|
||||
return $userid;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function user_exists($username)
|
||||
{
|
||||
return dbFetchCell('SELECT COUNT(*) FROM users WHERE username = ?', array($username), true);
|
||||
}
|
||||
|
||||
|
||||
function get_userlevel($username)
|
||||
{
|
||||
return dbFetchCell('SELECT `level` FROM `users` WHERE `username` = ?', array($username), true);
|
||||
}
|
||||
|
||||
|
||||
function get_userid($username)
|
||||
{
|
||||
return dbFetchCell('SELECT `user_id` FROM `users` WHERE `username` = ?', array($username), true);
|
||||
}
|
||||
|
||||
|
||||
function deluser($userid)
|
||||
{
|
||||
dbDelete('bill_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('devices_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('ports_perms', '`user_id` = ?', array($userid));
|
||||
dbDelete('users_prefs', '`user_id` = ?', array($userid));
|
||||
dbDelete('users', '`user_id` = ?', array($userid));
|
||||
return dbDelete('users', '`user_id` = ?', array($userid));
|
||||
}
|
||||
|
||||
|
||||
function get_userlist()
|
||||
{
|
||||
return dbFetchRows('SELECT * FROM `users`');
|
||||
}
|
||||
|
||||
|
||||
function can_update_users()
|
||||
{
|
||||
// supported so return 1
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
function get_user($user_id)
|
||||
{
|
||||
return dbFetchRow('SELECT * FROM `users` WHERE `user_id` = ?', array($user_id), true);
|
||||
}
|
||||
|
||||
|
||||
function update_user($user_id, $realname, $level, $can_modify_passwd, $email)
|
||||
{
|
||||
dbUpdate(array('realname' => $realname, 'level' => $level, 'can_modify_passwd' => $can_modify_passwd, 'email' => $email), 'users', '`user_id` = ?', array($user_id));
|
||||
}
|
@ -12,6 +12,8 @@
|
||||
* @copyright (C) 2013 LibreNMS Group
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
/**
|
||||
* Compare $t with the value of $vars[$v], if that exists
|
||||
* @param string $v Name of the var to test
|
||||
@ -1586,6 +1588,7 @@ function get_disks_with_smart($device, $app_id)
|
||||
*/
|
||||
function get_dashboards($user_id = null)
|
||||
{
|
||||
global $authorizer;
|
||||
$default = get_user_pref('dashboard');
|
||||
$dashboards = dbFetchRows(
|
||||
"SELECT * FROM `dashboards` WHERE dashboards.access > 0 || dashboards.user_id = ?",
|
||||
@ -1600,7 +1603,7 @@ function get_dashboards($user_id = null)
|
||||
foreach ($dashboards as $dashboard) {
|
||||
$duid = $dashboard['user_id'];
|
||||
if (!isset($usernames[$duid])) {
|
||||
$user = get_user($duid);
|
||||
$user = Auth::get()->getUser($duid);
|
||||
$usernames[$duid] = $user['username'];
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
// FIXME - this could do with some performance improvements, i think. possible rearranging some tables and setting flags at poller time (nothing changes outside of then anyways)
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
use LibreNMS\Device\WirelessSensor;
|
||||
use LibreNMS\ObjectCache;
|
||||
|
||||
@ -657,7 +658,7 @@ if ($_SESSION['userlevel'] >= '10') {
|
||||
<li role="presentation" class="divider"></li>
|
||||
|
||||
<?php if ($_SESSION['userlevel'] >= '10') {
|
||||
if (auth_usermanagement()) {
|
||||
if (Auth::get()->canManageUsers()) {
|
||||
echo('
|
||||
<li><a href="adduser/"><i class="fa fa-user-plus fa-fw fa-lg" aria-hidden="true"></i> Add User</a></li>
|
||||
<li><a href="deluser/"><i class="fa fa-user-times fa-fw fa-lg" aria-hidden="true"></i> Remove User</a></li>
|
||||
|
@ -1,4 +1,6 @@
|
||||
<?php
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
session_start();
|
||||
if (empty($_POST) && !empty($_SESSION) && !isset($_REQUEST['stage'])) {
|
||||
$_POST = $_SESSION;
|
||||
@ -473,9 +475,9 @@ if (!file_exists("../config.php")) {
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<?php
|
||||
if (auth_usermanagement()) {
|
||||
if (!user_exists($add_user)) {
|
||||
if (adduser($add_user, $add_pass, '10', $add_email)) {
|
||||
if (Auth::get()->canManageUsers()) {
|
||||
if (!Auth::get()->userExists($add_user)) {
|
||||
if (Auth::get()->addUser($add_user, $add_pass, '10', $add_email)) {
|
||||
echo("<div class='alert alert-success'>User has been added successfully</div>");
|
||||
$proceed = 0;
|
||||
} else {
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
$no_refresh = true;
|
||||
|
||||
if ($_SESSION['userlevel'] < '10') {
|
||||
@ -12,10 +14,10 @@ if ($_SESSION['userlevel'] < '10') {
|
||||
|
||||
$pagetitle[] = 'Add user';
|
||||
|
||||
if (auth_usermanagement()) {
|
||||
if (Auth::get()->canManageUsers()) {
|
||||
if ($_POST['action'] == 'add') {
|
||||
if ($_POST['new_username']) {
|
||||
if (!user_exists($_POST['new_username'])) {
|
||||
if (!Auth::get()->userExists($_POST['new_username'])) {
|
||||
if (isset($_POST['can_modify_passwd'])) {
|
||||
$_POST['can_modify_passwd'] = 1;
|
||||
} else {
|
||||
@ -23,7 +25,7 @@ if ($_SESSION['userlevel'] < '10') {
|
||||
}
|
||||
|
||||
// FIXME: missing email field here on the form
|
||||
if (adduser($_POST['new_username'], $_POST['new_password'], $_POST['new_level'], $_POST['new_email'], $_POST['new_realname'], $_POST['can_modify_passwd'])) {
|
||||
if (Auth::get()->addUser($_POST['new_username'], $_POST['new_password'], $_POST['new_level'], $_POST['new_email'], $_POST['new_realname'], $_POST['can_modify_passwd'])) {
|
||||
echo '<span class=info>User '.$_POST['username'].' added!</span>';
|
||||
}
|
||||
} else {
|
||||
|
@ -12,6 +12,8 @@
|
||||
* the source code distribution for details.
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
if (is_admin() === true) {
|
||||
if (empty($_POST['token'])) {
|
||||
$_POST['token'] = bin2hex(openssl_random_pseudo_bytes(16));
|
||||
@ -54,7 +56,7 @@ if (is_admin() === true) {
|
||||
<div class="col-sm-4">
|
||||
<select class="form-control" id="user_id" name="user_id">
|
||||
<?php
|
||||
foreach ($userlist = get_userlist() as $users) {
|
||||
foreach ($userlist = Auth::get()->getUserlist() as $users) {
|
||||
echo '<option value="'.$users['user_id'].'">'.$users['username'].'</option>';
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
echo '<div style="margin: 10px;">';
|
||||
|
||||
if ($_SESSION['userlevel'] < 10 || $_SESSION['userlevel'] > 10) {
|
||||
@ -9,12 +11,12 @@ if ($_SESSION['userlevel'] < 10 || $_SESSION['userlevel'] > 10) {
|
||||
|
||||
$pagetitle[] = 'Delete user';
|
||||
|
||||
if (auth_usermanagement()) {
|
||||
if (Auth::get()->canManageUsers()) {
|
||||
if ($vars['action'] == 'del') {
|
||||
$delete_username = dbFetchCell('SELECT username FROM users WHERE user_id = ?', array($vars['id']));
|
||||
|
||||
if ($vars['confirm'] == 'yes') {
|
||||
if (deluser($vars['id']) >= 0) {
|
||||
if (Auth::get()->deleteUser($vars['id']) >= 0) {
|
||||
print_message('<div class="infobox">User "'.$delete_username.'" deleted!');
|
||||
} else {
|
||||
print_error('Error deleting user "'.$delete_username.'"!');
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
$no_refresh = true;
|
||||
|
||||
require 'includes/javascript-interfacepicker.inc.php';
|
||||
@ -12,7 +14,7 @@ if ($_SESSION['userlevel'] != '10') {
|
||||
include 'includes/error-no-perm.inc.php';
|
||||
} else {
|
||||
if ($vars['user_id'] && !$vars['edit']) {
|
||||
$user_data = get_user($vars['user_id']);
|
||||
$user_data = Auth::get()->getUser($vars['user_id']);
|
||||
echo '<p><h2>'.$user_data['realname']."</h2><a href='edituser/'>Change...</a></p>";
|
||||
// Perform actions if requested
|
||||
if ($vars['action'] == 'deldevperm') {
|
||||
@ -249,10 +251,10 @@ if ($_SESSION['userlevel'] != '10') {
|
||||
$vars['can_modify_passwd'] = '1';
|
||||
}
|
||||
|
||||
update_user($vars['user_id'], $vars['new_realname'], $vars['new_level'], $vars['can_modify_passwd'], $vars['new_email']);
|
||||
Auth::get()->updateUser($vars['user_id'], $vars['new_realname'], $vars['new_level'], $vars['can_modify_passwd'], $vars['new_email']);
|
||||
print_message('User has been updated');
|
||||
if (!empty($vars['new_pass1']) && $vars['new_pass1'] == $vars['new_pass2'] && passwordscanchange($vars['cur_username'])) {
|
||||
if (changepassword($vars['cur_username'], $vars['new_pass1']) == 1) {
|
||||
if (!empty($vars['new_pass1']) && $vars['new_pass1'] == $vars['new_pass2'] && Auth::get()->canUpdatePasswords($vars['cur_username'])) {
|
||||
if (Auth::get()->changePassword($vars['cur_username'], $vars['new_pass1']) == 1) {
|
||||
print_message("User password has been updated");
|
||||
} else {
|
||||
print_error("Password couldn't be updated");
|
||||
@ -262,7 +264,7 @@ if ($_SESSION['userlevel'] != '10') {
|
||||
}
|
||||
}
|
||||
|
||||
$users_details = get_user($vars['user_id']);
|
||||
$users_details = Auth::get()->getUser($vars['user_id']);
|
||||
if (!empty($users_details)) {
|
||||
if (!empty($vars['dashboard']) && $vars['dashboard'] != $users_details['dashboard']) {
|
||||
set_user_pref('dashboard', $vars['dashboard']);
|
||||
@ -273,7 +275,7 @@ if ($_SESSION['userlevel'] != '10') {
|
||||
<input type='hidden' name='cur_username' value='" . $users_details['username'] . "'>
|
||||
<input type='hidden' name='edit' value='yes'>
|
||||
";
|
||||
if (can_update_users() == '1') {
|
||||
if (Auth::get()->canUpdateUsers() == '1') {
|
||||
if (empty($vars['new_realname'])) {
|
||||
$vars['new_realname'] = $users_details['realname'];
|
||||
}
|
||||
@ -335,7 +337,7 @@ if ($_SESSION['userlevel'] != '10') {
|
||||
</div>
|
||||
</div>";
|
||||
|
||||
if (passwordscanchange($users_details['username'])) {
|
||||
if (Auth::get()->canUpdatePasswords($users_details['username'])) {
|
||||
echo "
|
||||
<div class='form-group'>
|
||||
<label for='new_pass1' class='col-sm-2 control-label'>Password</label>
|
||||
@ -430,7 +432,7 @@ if ($_SESSION['userlevel'] != '10') {
|
||||
}//end if !empty($users_details)
|
||||
}//end if
|
||||
} else {
|
||||
$user_list = get_userlist();
|
||||
$user_list = Auth::get()->getUserlist();
|
||||
|
||||
echo '<h3>Select a user to edit</h3>';
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
* @subpackage Notifications
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
use LibreNMS\ObjectCache;
|
||||
|
||||
$notifications = new ObjectCache('notifications');
|
||||
@ -75,7 +76,7 @@ foreach ($notifications['sticky'] as $notif) {
|
||||
echo "<span class='pull-right'>";
|
||||
|
||||
if ($notif['user_id'] != $_SESSION['user_id']) {
|
||||
$sticky_user = get_user($notif['user_id']);
|
||||
$sticky_user = Auth::get()->getUser($notif['user_id']);
|
||||
echo "<code>Sticky by ${sticky_user['username']}</code>";
|
||||
} else {
|
||||
echo '<button class="btn btn-primary fa fa-bell-slash-o unstick-notif" data-toggle="tooltip" data-placement="bottom" title="Remove Sticky" style="margin-top:-10px;"></button>';
|
||||
@ -101,7 +102,7 @@ foreach ($notifications['sticky'] as $notif) {
|
||||
<?php
|
||||
foreach ($notifications['unread'] as $notif) {
|
||||
if (is_numeric($notif['source'])) {
|
||||
$source_user = get_user($notif['source']);
|
||||
$source_user = Auth::get()->getUser($notif['source']);
|
||||
$notif['source'] = $source_user['username'];
|
||||
}
|
||||
echo '<div class="well"><div class="row"> <div class="col-md-12">';
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
use LibreNMS\Authentication\TwoFactor;
|
||||
|
||||
$no_refresh = true;
|
||||
@ -13,11 +14,11 @@ if ($_SESSION['userlevel'] == 11) {
|
||||
demo_account();
|
||||
} else {
|
||||
if ($_POST['action'] == 'changepass') {
|
||||
if (authenticate($_SESSION['username'], $_POST['old_pass'])) {
|
||||
if (Auth::get()->authenticate($_SESSION['username'], $_POST['old_pass'])) {
|
||||
if ($_POST['new_pass'] == '' || $_POST['new_pass2'] == '') {
|
||||
$changepass_message = 'Password must not be blank.';
|
||||
} elseif ($_POST['new_pass'] == $_POST['new_pass2']) {
|
||||
changepassword($_SESSION['username'], $_POST['new_pass']);
|
||||
Auth::get()->changePassword($_SESSION['username'], $_POST['new_pass']);
|
||||
$changepass_message = 'Password Changed.';
|
||||
} else {
|
||||
$changepass_message = "Passwords don't match.";
|
||||
@ -35,7 +36,7 @@ if ($_SESSION['userlevel'] == 11) {
|
||||
|
||||
include 'includes/update-preferences-password.inc.php';
|
||||
|
||||
if (passwordscanchange($_SESSION['username'])) {
|
||||
if (Auth::get()->canUpdatePasswords($_SESSION['username'])) {
|
||||
echo '<h3>Change Password</h3>';
|
||||
echo '<hr>';
|
||||
echo "<div class='well'>";
|
||||
|
@ -22,6 +22,7 @@
|
||||
* @subpackage Alerts
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
/**
|
||||
* Generate SQL from Rule
|
||||
@ -231,14 +232,14 @@ function RunRules($device)
|
||||
*/
|
||||
function GetContacts($results)
|
||||
{
|
||||
global $config;
|
||||
global $config, $authorizer;
|
||||
if (sizeof($results) == 0) {
|
||||
return array();
|
||||
}
|
||||
if ($config['alert']['default_only'] === true || $config['alerts']['email']['default_only'] === true) {
|
||||
return array(''.($config['alert']['default_mail'] ? $config['alert']['default_mail'] : $config['alerts']['email']['default']) => 'NOC');
|
||||
}
|
||||
$users = get_userlist();
|
||||
$users = Auth::get()->getUserlist();
|
||||
$contacts = array();
|
||||
$uids = array();
|
||||
foreach ($results as $result) {
|
||||
@ -280,7 +281,7 @@ function GetContacts($results)
|
||||
$user['realname'] = $user['username'];
|
||||
}
|
||||
if (empty($user['level'])) {
|
||||
$user['level'] = get_userlevel($user['username']);
|
||||
$user['level'] = Auth::get()->getUserlevel($user['username']);
|
||||
}
|
||||
if ($config['alert']['globals'] && ( $user['level'] >= 5 && $user['level'] < 10 )) {
|
||||
$contacts[$user['email']] = $user['realname'];
|
||||
|
@ -27,6 +27,8 @@
|
||||
* @param array $modules Which modules to initialize
|
||||
*/
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
|
||||
global $config;
|
||||
|
||||
$install_dir = realpath(__DIR__ . '/..');
|
||||
@ -149,11 +151,9 @@ if (!module_selected('nodb', $init_modules)) {
|
||||
require $install_dir . '/includes/process_config.inc.php';
|
||||
}
|
||||
|
||||
if (file_exists($install_dir . '/html/includes/authentication/'.$config['auth_mechanism'].'.inc.php')) {
|
||||
require_once $install_dir . '/html/includes/authentication/functions.php';
|
||||
require_once $install_dir . '/html/includes/authentication/'.$config['auth_mechanism'].'.inc.php';
|
||||
init_auth();
|
||||
} else {
|
||||
try {
|
||||
Auth::get();
|
||||
} catch (Exception $exception) {
|
||||
print_error('ERROR: no valid auth_mechanism defined!');
|
||||
exit();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
|
||||
use LibreNMS\Authentication\Auth;
|
||||
use Phpass\PasswordHash;
|
||||
|
||||
$options = getopt('u:rdvh');
|
||||
@ -42,85 +43,108 @@ if ($config['auth_mechanism'] = 'ldap' || $config['auth_mechanism'] = "active_di
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
$authorizer = Auth::get();
|
||||
|
||||
if (function_exists('ad_bind')) {
|
||||
if (isset($config['auth_ad_binduser']) && isset($config['auth_ad_bindpassword'])) {
|
||||
if (!ad_bind($ldap_connection, false)) {
|
||||
$ldap_error = ldap_error($ldap_connection);
|
||||
echo $ldap_error . PHP_EOL;
|
||||
if ($ldap_error == 'Invalid credentials') {
|
||||
print_error('AD bind failed for user ' . $config['auth_ad_binduser'] . '@' . $config['auth_ad_domain'] .
|
||||
'. Check $config[\'auth_ad_binduser\'] and $config[\'auth_ad_bindpassword\'] in your config.php');
|
||||
// AD bind tests
|
||||
if ($authorizer instanceof \LibreNMS\Authentication\ActiveDirectoryAuthorizer) {
|
||||
// peek inside the class
|
||||
$lc_rp = new ReflectionProperty($authorizer, 'ldap_connection');
|
||||
$lc_rp->setAccessible(true);
|
||||
$adbind_rm = new ReflectionMethod($authorizer, 'adBind');
|
||||
$adbind_rm->setAccessible(true);
|
||||
|
||||
$bind_success = false;
|
||||
if (isset($config['auth_ad_binduser']) && isset($config['auth_ad_bindpassword'])) {
|
||||
$bind_success = $adbind_rm->invoke($authorizer, false, true);
|
||||
if (!$bind_success) {
|
||||
$ldap_error = ldap_error($lc_rp->getValue($authorizer));
|
||||
echo $ldap_error . PHP_EOL;
|
||||
if ($ldap_error == 'Invalid credentials') {
|
||||
print_error('AD bind failed for user ' . $config['auth_ad_binduser'] . '@' . $config['auth_ad_domain'] .
|
||||
'. Check $config[\'auth_ad_binduser\'] and $config[\'auth_ad_bindpassword\'] in your config.php');
|
||||
}
|
||||
} else {
|
||||
print_message('AD bind success');
|
||||
}
|
||||
} else {
|
||||
print_message('AD bind success');
|
||||
$bind_success = $adbind_rm->invoke($authorizer, true, true);
|
||||
if (!$bind_success) {
|
||||
echo ldap_error($lc_rp->getValue($authorizer)) . PHP_EOL;
|
||||
print_message("Could not anonymous bind to AD");
|
||||
} else {
|
||||
print_message('AD bind anonymous successful');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!ad_bind($ldap_connection)) {
|
||||
echo ldap_error($ldap_connection) . PHP_EOL;
|
||||
print_message("Could not anonymous bind to AD");
|
||||
|
||||
if (!$bind_success) {
|
||||
print_error("Could not bind to AD, you will not be able to use the API or alert AD users");
|
||||
}
|
||||
}
|
||||
|
||||
$auth = false;
|
||||
if (isset($options['r'])) {
|
||||
echo "Reauthenticate Test\n";
|
||||
|
||||
$session = dbFetchRow(
|
||||
'SELECT * FROM `session` WHERE `session_username`=? ORDER BY `session_id` DESC LIMIT 1',
|
||||
array($test_username)
|
||||
);
|
||||
d_echo($session);
|
||||
if (empty($session)) {
|
||||
print_error('Requires previous login with \'Remember me\' box checked on the webui');
|
||||
exit;
|
||||
}
|
||||
|
||||
$hasher = new PasswordHash(8, false);
|
||||
$token = $session['session_username'] . '|' . $hasher->HashPassword($session['session_username'] . $session['session_token']);
|
||||
|
||||
$auth = $authorizer->reauthenticate($session['session_value'], $token);
|
||||
if ($auth) {
|
||||
print_message("Reauthentication successful.\n");
|
||||
} else {
|
||||
print_message('AD bind anonymous successful');
|
||||
print_error('Reauthentication failed or is unsupported');
|
||||
}
|
||||
} else {
|
||||
echo 'Password: ';
|
||||
`stty -echo`;
|
||||
$test_password = trim(fgets(STDIN));
|
||||
`stty echo`;
|
||||
echo PHP_EOL;
|
||||
|
||||
echo "Authenticate user $test_username: \n";
|
||||
$auth = $authorizer->authenticate($test_username, $test_password);
|
||||
unset($test_password);
|
||||
|
||||
if ($auth) {
|
||||
print_message("AUTH SUCCESS\n");
|
||||
} else {
|
||||
if (isset($ldap_connection)) {
|
||||
echo ldap_error($ldap_connection) . PHP_EOL;
|
||||
}
|
||||
print_error('AUTH FAILURE');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$auth = false;
|
||||
if (isset($options['r'])) {
|
||||
echo "Reauthenticate Test\n";
|
||||
|
||||
$session = dbFetchRow('SELECT * FROM `session` WHERE `session_username`=? ORDER BY `session_id` DESC LIMIT 1', array($test_username));
|
||||
d_echo($session);
|
||||
if (empty($session)) {
|
||||
print_error('Requires previous login with \'Remember me\' box checked on the webui');
|
||||
exit;
|
||||
}
|
||||
|
||||
$hasher = new PasswordHash(8, false);
|
||||
$token = $session['session_username'] . '|' . $hasher->HashPassword($session['session_username'] . $session['session_token']);
|
||||
|
||||
$auth = reauthenticate($session['session_value'], $token);
|
||||
if ($auth) {
|
||||
print_message("Reauthentication successful.\n");
|
||||
} else {
|
||||
print_error('Reauthentication failed or is unsupported');
|
||||
}
|
||||
} else {
|
||||
echo 'Password: ';
|
||||
`stty -echo`;
|
||||
$test_password = trim(fgets(STDIN));
|
||||
`stty echo`;
|
||||
echo PHP_EOL;
|
||||
|
||||
echo "Authenticate user $test_username: \n";
|
||||
$auth = authenticate($test_username, $test_password);
|
||||
unset($test_password);
|
||||
|
||||
if ($auth) {
|
||||
print_message("AUTH SUCCESS\n");
|
||||
} else {
|
||||
if (isset($ldap_connection)) {
|
||||
echo ldap_error($ldap_connection) . PHP_EOL;
|
||||
$user_id = $authorizer->getUserid($test_username);
|
||||
|
||||
echo "User ($user_id):\n";
|
||||
if (method_exists($authorizer, 'getUser')) {
|
||||
$user = $authorizer->getUser($user_id);
|
||||
|
||||
unset($user['password']);
|
||||
unset($user['remember_token']);
|
||||
foreach ($user as $property => $value) {
|
||||
echo " $property => $value\n";
|
||||
}
|
||||
}
|
||||
print_error('AUTH FAILURE');
|
||||
}
|
||||
}
|
||||
|
||||
if ($auth) {
|
||||
$user_id = get_userid($test_username);
|
||||
|
||||
echo "User ($user_id):\n";
|
||||
if (function_exists('get_user')) {
|
||||
$user = get_user($user_id);
|
||||
|
||||
unset($user['password']);
|
||||
unset($user['remember_token']);
|
||||
foreach ($user as $property => $value) {
|
||||
echo " $property => $value\n";
|
||||
if (method_exists($authorizer, 'getGroupList')) {
|
||||
echo 'Groups: ' . implode('; ', $authorizer->getGroupList()) . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
if (function_exists('get_group_list')) {
|
||||
echo 'Groups: ' . implode('; ', get_group_list()) . PHP_EOL;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo "Error: " . get_class($e) . " thrown!\n";
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
|
Reference in New Issue
Block a user