Files
filegator/backend/Services/Auth/Adapters/LDAP.php
Luiz Kill a48fa3c717 Adds an attributes parameter to the ldap adapter (#184)
* Adds an attribute parameter to the ldap adapter

Using this parameter is much more efficient than the default action (which is to return all attributes and their associated values). The use of this parameter should therefore be considered good practice.

(from https://www.php.net/manual/en/function.ldap-search.php)

* Updates the docs about ldap_attributes parameter

* Enhances portuguese translation

* Update backend/Services/Auth/Adapters/LDAP.php

Commit suggestion
2021-02-18 09:18:30 +01:00

229 lines
7.0 KiB
PHP

<?php
/*
* This file is part of the FileGator package.
*
* (c) Adriano Hänggli <https://github.com/ahaenggli>
*
*/
namespace Filegator\Services\Auth\Adapters;
use Filegator\Services\Auth\AuthInterface;
use Filegator\Services\Auth\User;
use Filegator\Services\Auth\UsersCollection;
use Filegator\Services\Service;
use Filegator\Services\Session\SessionStorageInterface as Session;
/**
* @codeCoverageIgnore
*/
class LDAP implements Service, AuthInterface
{
const SESSION_KEY = 'LDAP_auth';
const GUEST_USERNAME = 'guest';
protected $session;
protected $private_repos = false;
protected $ldap_server;
protected $ldap_bindDN;
protected $ldap_bindPass;
protected $ldap_baseDN;
protected $ldap_filter;
protected $ldap_attributes;
protected $ldap_userFieldMapping;
public function __construct(Session $session)
{
$this->session = $session;
}
public function init(array $config = [])
{
if(!isset($config['ldap_server']) || empty($config['ldap_server']))
throw new \Exception('config ldap_server missing');
if (!extension_loaded('ldap')) throw new \Exception('ldap extension missing');
if($connect=ldap_connect($config['ldap_server'])){
ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);
$this->private_repos = $config['private_repos'];
$this->ldap_server = $config['ldap_server'];
$this->ldap_bindDN = $config['ldap_bindDN'];
$this->ldap_bindPass = $config['ldap_bindPass'];
$this->ldap_baseDN = $config['ldap_baseDN'];
$this->ldap_filter = $config['ldap_filter'];
$this->ldap_attributes = isset($config['ldap_attributes']) ? $config['ldap_attributes'] : ['*'];
$this->ldap_userFieldMapping = $config['ldap_userFieldMapping'];
}else {
@ldap_close($connect);
throw new \Exception('could not connect to domain');
}
@ldap_close($connect);
}
public function user(): ?User
{
return $this->session ? $this->session->get(self::SESSION_KEY, null) : null;
}
public function authenticate($username, $password): bool
{
$all_users = $this->getUsers();
foreach ($all_users as &$u) {
if ($u['username'] == $username && $this->verifyPassword($u['userDN'], $password)) {
$user = $this->mapToUserObject($u);
$this->store($user);
return true;
}
}
return false;
}
public function forget()
{
return $this->session->invalidate();
}
public function store(User $user)
{
return $this->session->set(self::SESSION_KEY, $user);
}
public function update($username, User $user, $password = ''): User
{
return new User(); // not used
}
public function add(User $user, $password): User
{
return new User(); // not used
}
public function delete(User $user)
{
return true; // not used
}
public function find($username): ?User
{
foreach ($this->getUsers() as $user) {
if ($user['username'] == $username) {
return $this->mapToUserObject($user);
}
}
return null;
}
public function getGuest(): User
{
$guest = $this->find(self::GUEST_USERNAME);
if (!$guest || !$guest->isGuest()) {
$guest = new User();
$guest->setUsername('guest');
$guest->setName('Guest');
$guest->setRole('guest');
$guest->setHomedir('/');
$guest->setPermissions([]);
return $guest;
}
return $guest;
}
public function allUsers(): UsersCollection
{
$users = new UsersCollection();
foreach ($this->getUsers() as $user) {
$users->addUser($this->mapToUserObject($user));
}
return $users;
}
protected function mapToUserObject(array $user): User
{
$new = new User();
$new->setUsername($user['username']);
$new->setName($user['name']);
$new->setRole($user['role']);
$new->setHomedir($user['homedir']);
$new->setPermissions($user['permissions'], true);
return $new;
}
protected function getUsers(): array
{
$ldapConn = @ldap_connect($this->ldap_server);
if (!$ldapConn) throw new \Exception('Cannot Connect to LDAP server');
@ldap_set_option($ldapConn, LDAP_OPT_PROTOCOL_VERSION, 3);
$ldapBind = @ldap_bind($ldapConn, $this->ldap_bindDN,$this->ldap_bindPass);
if (!$ldapBind) throw new \Exception('Cannot Bind to LDAP server: Wrong credentials?');
// search the LDAP server for users
$ldapSearch = @ldap_search($ldapConn, $this->ldap_baseDN, $this->ldap_filter, $this->ldap_attributes);
$ldapResults = @ldap_get_entries($ldapConn, $ldapSearch);
@ldap_close($ldapConn);
$users = [];
for ($item = 0; $item < $ldapResults['count']; $item++)
{
$user = [];
$user['username'] = $ldapResults[$item][$this->ldap_userFieldMapping['username']][0];
$user['name'] = $ldapResults[$item][$this->ldap_userFieldMapping['name']][0];
$user['role'] = 'user';
$user['homedir'] = '/';
$user['permissions']=$this->ldap_userFieldMapping['default_permissions'];
$user['userDN'] = $ldapResults[$item][$this->ldap_userFieldMapping['userDN']];
if(is_array($this->ldap_userFieldMapping['admin_usernames']))
{
if(in_array($user['username'], $this->ldap_userFieldMapping['admin_usernames'])) $user['role'] = 'admin';
}
// private repositories for each user?
if ($this->private_repos) {
$user->setHomedir('/'.$user['username']);
}
// ...but not for admins
if ($user['role'] == 'admin'){
$user['homedir'] = '/';
$user['permissions'] = 'read|write|upload|download|batchdownload|zip';
}
if(is_array($user) && !empty($user)) $users[] = $user;
}
return is_array($users) ? $users : [];
}
private function verifyPassword($auth_user, $password)
{
if(!isset($this->ldap_server) || empty($this->ldap_server)) return false;
if(!extension_loaded('ldap')) return false;
if($connect=ldap_connect($this->ldap_server))
{
ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);
if($bind=ldap_bind($connect, $auth_user, $password)){
@ldap_close($connect);
return true;
} else {
@ldap_close($connect);
return false;
}
}
@ldap_close($connect);
return false;
}
}