mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
* AD Authorization fixes Remove mres() and $_SESSION usage. Remove broken addUser function and use Mysql addUser. * AD Authorization fixes Remove mres() and $_SESSION usage. Remove broken addUser function and use Mysql addUser. Extract common AD auth code to ADUtils * AD Authorization fixes Remove mres() and $_SESSION usage. Remove broken addUser function and use Mysql addUser. Extract common AD auth code to ADUtils * Send no user info to log instead of toast. * Remove commented code * add abstract getConnection() method that is required. * Actually return the value
237 lines
7.3 KiB
PHP
237 lines
7.3 KiB
PHP
<?php
|
|
/**
|
|
* ActiveDirectoryCommonirectoryCommon.php
|
|
*
|
|
* Common code from AD auth modules
|
|
*
|
|
* 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 2018 Tony Murray
|
|
* @author Tony Murray <murraytony@gmail.com>
|
|
*/
|
|
|
|
namespace LibreNMS\Authentication;
|
|
|
|
use LibreNMS\Config;
|
|
|
|
trait ActiveDirectoryCommon
|
|
{
|
|
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);
|
|
if (PHP_INT_SIZE <= 4) {
|
|
for ($i = 1; $i <= count($subAuths); $i++) {
|
|
if ($subAuths[$i] < 0) {
|
|
$subAuths[$i] = $subAuths[$i] + 0x100000000;
|
|
}
|
|
}
|
|
}
|
|
$revLevel = hexdec(substr($sidHex, 0, 2));
|
|
$authIdent = hexdec(substr($sidHex, 4, 12));
|
|
return 'S-'.$revLevel.'-'.$authIdent.'-'.implode('-', $subAuths);
|
|
}
|
|
|
|
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 getDn($samaccountname)
|
|
{
|
|
$link_identifier = $this->getConnection();
|
|
$attributes = ['dn'];
|
|
$result = ldap_search(
|
|
$link_identifier,
|
|
Config::get('auth_ad_base_dn'),
|
|
$this->groupFilter($samaccountname),
|
|
$attributes
|
|
);
|
|
$entries = ldap_get_entries($link_identifier, $result);
|
|
if ($entries['count'] > 0) {
|
|
return $entries[0]['dn'];
|
|
} else {
|
|
return '';
|
|
}
|
|
}
|
|
|
|
protected function userFilter($username)
|
|
{
|
|
// don't return disabled users
|
|
$user_filter = "(&(samaccountname=$username)(!(useraccountcontrol:1.2.840.113556.1.4.803:=2))";
|
|
|
|
$extra = Config::get('auth_ad_user_filter');
|
|
if ($extra) {
|
|
$user_filter .= $extra;
|
|
}
|
|
$user_filter .= ')';
|
|
|
|
return $user_filter;
|
|
}
|
|
|
|
protected function groupFilter($groupname)
|
|
{
|
|
$group_filter = "(samaccountname=$groupname)";
|
|
|
|
$extra = Config::get('auth_ad_group_filter');
|
|
if ($extra) {
|
|
$group_filter = "(&$extra$group_filter)";
|
|
}
|
|
|
|
return $group_filter;
|
|
}
|
|
|
|
protected function getFullname($username)
|
|
{
|
|
$connection = $this->getConnection();
|
|
$attributes = ['name'];
|
|
$result = ldap_search(
|
|
$connection,
|
|
Config::get('auth_ad_base_dn'),
|
|
$this->userFilter($username),
|
|
$attributes
|
|
);
|
|
$entries = ldap_get_entries($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;
|
|
}
|
|
|
|
public function getUserlist()
|
|
{
|
|
$connection = $this->getConnection();
|
|
|
|
$userlist = array();
|
|
$ldap_groups = $this->getGroupList();
|
|
|
|
foreach ($ldap_groups as $ldap_group) {
|
|
$search_filter = "(&(memberOf:1.2.840.113556.1.4.1941:=$ldap_group)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))";
|
|
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($connection, Config::get('auth_ad_base_dn'), $search_filter, $attributes);
|
|
$results = ldap_get_entries($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' => isset($entry['mail'][0]) ? $entry['mail'][0] : null,
|
|
'descr' => '',
|
|
'level' => $this->getUserlevel($entry['samaccountname'][0]),
|
|
'can_modify_passwd' => 0,
|
|
);
|
|
}
|
|
|
|
public function getUser($user_id)
|
|
{
|
|
$connection = $this->getConnection();
|
|
$domain_sid = $this->getDomainSid();
|
|
|
|
$search_filter = "(&(objectcategory=person)(objectclass=user)(objectsid=$domain_sid-$user_id))";
|
|
$attributes = array('samaccountname', 'displayname', 'objectsid', 'mail');
|
|
$search = ldap_search($connection, Config::get('auth_ad_base_dn'), $search_filter, $attributes);
|
|
$entry = ldap_get_entries($connection, $search);
|
|
|
|
if (isset($entry[0]['samaccountname'][0])) {
|
|
return $this->userFromAd($entry[0]);
|
|
}
|
|
|
|
return array();
|
|
}
|
|
|
|
protected function getDomainSid()
|
|
{
|
|
$connection = $this->getConnection();
|
|
|
|
// Extract only the domain components
|
|
$dn_candidate = preg_replace('/^.*?DC=/i', 'DC=', Config::get('auth_ad_base_dn'));
|
|
|
|
$search = ldap_read(
|
|
$connection,
|
|
$dn_candidate,
|
|
'(objectClass=*)',
|
|
array('objectsid')
|
|
);
|
|
$entry = ldap_get_entries($connection, $search);
|
|
return substr($this->sidFromLdap($entry[0]['objectsid'][0]), 0, 41);
|
|
}
|
|
|
|
/**
|
|
* Provide a connected and bound ldap connection resource
|
|
*
|
|
* @return resource
|
|
*/
|
|
abstract protected function getConnection();
|
|
}
|