mirror of
https://github.com/librenms/librenms.git
synced 2024-09-23 03:18:54 +00:00
Merge pull request #3531 from wiad/issue-3530
Added auth module combining http authentication and AD authorization
This commit is contained in:
commit
2a1ae6a3f9
@ -168,3 +168,27 @@ $config['radius']['timeout'] = 3;
|
||||
$config['radius']['users_purge'] = 14;//Purge users who haven't logged in for 14 days.
|
||||
$config['radius']['default_level'] = 1;//Set the default user level when automatically creating a user.
|
||||
```
|
||||
|
||||
#### HTTP Authentication / AD Authorization
|
||||
|
||||
Config option: `ad-authorization`
|
||||
|
||||
This module is a combination of ___http-auth___ and ___active_directory___
|
||||
|
||||
LibreNMS will expect the user to have authenticated via your webservice already (e.g. using Kerberos Authentication in Apache) but will use Active Directory lookups to determine and assign the userlevel of a user.
|
||||
The userlevel will be calculated by using AD group membership information as the ___active_directory___ module does.
|
||||
|
||||
The configuration is the same as for the ___active_directory___ module with two extra, optional options: auth_ad_binduser and auth_ad_bindpassword.
|
||||
These should be set to a AD user with read capabilities in your AD Domain in order to be able to perform searches.
|
||||
If these options are omitted, the module will attempt an anonymous bind (which then of course must be allowed by your Active Directory server(s)).
|
||||
|
||||
There is also one extra option for controlling user information caching: auth_ldap_cache_ttl.
|
||||
This option allows to control how long user information (user_exists, userid, userlevel) are cached within the PHP Session.
|
||||
The default value is 300 seconds.
|
||||
To disable this caching (highly discourage) set this option to 0.
|
||||
|
||||
```php
|
||||
$config['auth_ad_binduser'] = "ad_binduser";
|
||||
$config['auth_ad_bindpassword'] = "ad_bindpassword";
|
||||
$config['auth_ldap_cache_ttl'] = 300;
|
||||
```
|
||||
|
359
html/includes/authentication/ad-authorization.inc.php
Normal file
359
html/includes/authentication/ad-authorization.inc.php
Normal file
@ -0,0 +1,359 @@
|
||||
<?php
|
||||
|
||||
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
|
||||
$ds = @ldap_connect($config['auth_ad_url']);
|
||||
if (! $ds) {
|
||||
echo '<h2>Fatal error while connecting to AD url ' . $config['auth_ad_url'] . ': ' . ldap_error($ds) . '</h2>';
|
||||
exit;
|
||||
}
|
||||
|
||||
// disable referrals and force ldap version to 3
|
||||
ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
|
||||
ldap_set_option($ds, 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($ds, "${config['auth_ad_binduser']}@${config['auth_ad_domain']}", "${config['auth_ad_bindpassword']}")) {
|
||||
echo ldap_error($ds);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Anonymous
|
||||
if (! ldap_bind($ds)) {
|
||||
echo ldap_error($ds);
|
||||
}
|
||||
}
|
||||
|
||||
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 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function reauthenticate() {
|
||||
// not supported so return 0
|
||||
return 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='', $twofactor=0) {
|
||||
// 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, 'twofactor' => $twofactor, '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, $ds;
|
||||
|
||||
if (auth_ldap_session_cache_get ('user_exists'))
|
||||
return 1;
|
||||
|
||||
$search = ldap_search($ds, $config['auth_ad_base_dn'],
|
||||
"(samaccountname=${username})",array('samaccountname'));
|
||||
$entries = ldap_get_entries($ds, $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, $ds;
|
||||
|
||||
$userlevel = auth_ldap_session_cache_get ('userlevel');
|
||||
if ($userlevel) {
|
||||
return $userlevel;
|
||||
}
|
||||
else {
|
||||
$userlevel = 0;
|
||||
}
|
||||
|
||||
// Find all defined groups $username is in
|
||||
$search = ldap_search($ds, $config['auth_ad_base_dn'],
|
||||
"(samaccountname={$username})", array('memberOf'));
|
||||
$entries = ldap_get_entries($ds, $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, $ds;
|
||||
|
||||
$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($ds, $config['auth_ad_base_dn'],
|
||||
"(samaccountname={$username})", $attributes);
|
||||
$entries = ldap_get_entries($ds, $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($username) {
|
||||
dbDelete('bill_perms', '`user_name` = ?', array($username));
|
||||
dbDelete('devices_perms', '`user_name` = ?', array($username));
|
||||
dbDelete('ports_perms', '`user_name` = ?', array($username));
|
||||
dbDelete('users_prefs', '`user_name` = ?', array($username));
|
||||
dbDelete('users', '`user_name` = ?', array($username));
|
||||
return dbDelete('users', '`username` = ?', array($username));
|
||||
}
|
||||
|
||||
|
||||
function get_userlist() {
|
||||
global $config, $ds;
|
||||
$userlist = array();
|
||||
$userhash = array();
|
||||
|
||||
$ldap_groups = get_group_list();
|
||||
|
||||
foreach($ldap_groups as $ldap_group) {
|
||||
$group_cn = get_cn($ldap_group);
|
||||
$search = ldap_search($ds, $config['auth_ad_base_dn'], "(cn={$group_cn})", array('member'));
|
||||
$entries = ldap_get_entries($ds, $search);
|
||||
|
||||
foreach($entries[0]['member'] as $member) {
|
||||
$member_cn = get_cn($member);
|
||||
$search = ldap_search($ds, $config['auth_ad_base_dn'], "(cn={$member_cn})",
|
||||
array('sAMAccountname', 'displayName', 'objectSID', 'mail'));
|
||||
$results = ldap_get_entries($ds, $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, $ds;
|
||||
|
||||
$attributes = array('name');
|
||||
$result = ldap_search($ds, $config['auth_ad_base_dn'],
|
||||
"(samaccountname={$username})", $attributes);
|
||||
$entries = ldap_get_entries($ds, $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, $ds;
|
||||
|
||||
|
||||
$attributes = array('dn');
|
||||
$result = ldap_search($ds, $config['auth_ad_base_dn'],
|
||||
"(samaccountname={$samaccountname})", $attributes);
|
||||
$entries = ldap_get_entries($ds, $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 ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user