xref: /plugin/pureldap/classes/Client.php (revision 8595f73ee5f2a82759e15e55b70cf3d4afb2d3d4)
1<?php
2
3namespace dokuwiki\plugin\pureldap\classes;
4
5use FreeDSx\Ldap\Entry\Attribute;
6use FreeDSx\Ldap\Exception\BindException;
7use FreeDSx\Ldap\Exception\ConnectionException;
8use FreeDSx\Ldap\Exception\OperationException;
9use FreeDSx\Ldap\LdapClient;
10
11require_once __DIR__ . '/../vendor/autoload.php';
12
13abstract class Client
14{
15    /** @var array the configuration */
16    protected $config;
17
18    /** @var LdapClient */
19    protected $ldap;
20
21    /** @var bool is this client authenticated already? */
22    protected $isAuthenticated = false;
23
24    /** @var array cached user info */
25    protected $userCache = [];
26
27    /**
28     * Client constructor.
29     * @param array $config
30     */
31    public function __construct($config)
32    {
33        $this->config = $this->prepareConfig($config);
34        $this->ldap = new LdapClient($this->config);
35    }
36
37    /**
38     * Setup sane config defaults
39     *
40     * @param array $config
41     * @return array
42     */
43    protected function prepareConfig($config)
44    {
45        $defaults = [
46            'defaultgroup' => 'user', // we expect this to be passed from global conf
47            'use_tls' => false,
48            'use_ssl' => false,
49            'port' => '',
50            'admin_username' => '',
51            'admin_password' => '',
52        ];
53
54        $config = array_merge($defaults, $config);
55
56        // default port depends on SSL setting
57        if (!$config['port']) {
58            $config['port'] = $config['use_ssl'] ? 636 : 389;
59        }
60
61        return $config;
62    }
63
64    /**
65     * Authenticate as admin
66     */
67    public function autoAuth()
68    {
69        if ($this->isAuthenticated) return true;
70        return $this->authenticate($this->config['admin_username'], $this->config['admin_password']);
71    }
72
73    /**
74     * Authenticates a given user. This client will remain authenticated
75     *
76     * @param string $user
77     * @param string $pass
78     * @return bool was the authentication successful?
79     */
80    public function authenticate($user, $pass)
81    {
82        if ($this->config['use_tls']) {
83            try {
84                $this->ldap->startTls();
85            } catch (OperationException $e) {
86                $this->debug($e);
87            }
88        }
89
90        try {
91            $this->ldap->bind($user, $pass);
92        } catch (BindException $e) {
93            return false;
94        } catch (ConnectionException $e) {
95            $this->debug($e);
96            return false;
97        } catch (OperationException $e) {
98            $this->debug($e);
99            return false;
100        }
101
102        $this->isAuthenticated = true;
103        return true;
104    }
105
106    /**
107     * Get info for a single user, use cache if available
108     *
109     * @param string $username
110     * @param bool $fetchgroups Are groups needed?
111     * @return array|null
112     */
113    public function getCachedUser($username, $fetchgroups = true)
114    {
115        if (isset($this->userCache[$username])) {
116            if (!$fetchgroups || is_array($this->userCache[$username]['grps'])) {
117                return $this->userCache[$username];
118            }
119        }
120
121        // fetch fresh data
122        $info = $this->getUser($username, $fetchgroups);
123
124        // store in cache
125        if ($info !== null) {
126            $this->userCache[$username] = $info;
127        }
128
129        return $info;
130    }
131
132    /**
133     * Fetch a single user
134     *
135     * @param string $username
136     * @param bool $fetchgroups Shall groups be fetched, too?
137     * @return null|array
138     */
139    abstract public function getUser($username, $fetchgroups = true);
140
141    /**
142     * Helper method to get the first value of the given attribute
143     *
144     * The given attribute may be null, an empty string is returned then
145     *
146     * @param Attribute|null $attribute
147     * @return string
148     */
149    protected function attr2str($attribute) {
150        if($attribute !== null) {
151            return $attribute->firstValue();
152        }
153        return '';
154    }
155
156
157    /**
158     * Handle debugging
159     *
160     * @param \Exception $e
161     */
162    protected function debug(\Exception $e)
163    {
164        if (defined('DOKU_UNITTEST')) {
165            throw new \RuntimeException('', 0, $e);
166        }
167
168        msg($e->getMessage(), -1);
169    }
170}
171