Issues (3083)

htdocs/class/auth/auth_ldap.php (1 issue)

1
<?php
2
/**
3
 * XOOPS Authentification base class
4
 *
5
 * You may not change or alter any portion of this comment or credits
6
 * of supporting developers from this source code or any supporting source code
7
 * which is considered copyrighted (c) material of the original comment or credit authors.
8
 * This program is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * @copyright           The XOOPS Project (https://xoops.org)
13
 * @license             GNU GPL 2 (https://www.gnu.org/licenses/gpl-2.0.html)
14
 * @package             kernel
15
 * @subpackage          auth
16
 * @since               2.0
17
 * @author              Pierre-Eric MENUET <[email protected]>
18
 */
19
defined('XOOPS_ROOT_PATH') || exit('Restricted access');
20
21
/**
22
 *
23
 * @package             kernel
24
 * @subpackage          auth
25
 * @description         Authentification class for standard LDAP Server V2 or V3
26
 * @author              Pierre-Eric MENUET <[email protected]>
27
 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
28
 */
29
if (file_exists($file = $GLOBALS['xoops']->path('class/auth/auth_provisionning.php'))) {
30
    include_once $file;
31
}
32
33
if (!class_exists('XoopsAuthProvisionning')) {
34
    trigger_error('Required class XoopsAuthProvisionning was not found at line ' . __FILE__ . ' at line ' . __LINE__, E_USER_WARNING);
35
36
    return false;
37
}
38
39
/**
40
 * XoopsAuthLdap
41
 *
42
 * @package
43
 * @author              John
44
 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
45
 * @access              public
46
 */
47
class XoopsAuthLdap extends XoopsAuth
48
{
49
    public $cp1252_map = array(
50
        "\xc2\x80" => "\xe2\x82\xac",
51
        /**
52
         * EURO SIGN
53
         */
54
        "\xc2\x82" => "\xe2\x80\x9a",
55
        /**
56
         * SINGLE LOW-9 QUOTATION MARK
57
         */
58
        "\xc2\x83" => "\xc6\x92",
59
        /**
60
         * LATIN SMALL LETTER F WITH HOOK
61
         */
62
        "\xc2\x84" => "\xe2\x80\x9e",
63
        /**
64
         * DOUBLE LOW-9 QUOTATION MARK
65
         */
66
        "\xc2\x85" => "\xe2\x80\xa6",
67
        /**
68
         * HORIZONTAL ELLIPSIS
69
         */
70
        "\xc2\x86" => "\xe2\x80\xa0",
71
        /**
72
         * DAGGER
73
         */
74
        "\xc2\x87" => "\xe2\x80\xa1",
75
        /**
76
         * DOUBLE DAGGER
77
         */
78
        "\xc2\x88" => "\xcb\x86",
79
        /**
80
         * MODIFIER LETTER CIRCUMFLEX ACCENT
81
         */
82
        "\xc2\x89" => "\xe2\x80\xb0",
83
        /**
84
         * PER MILLE SIGN
85
         */
86
        "\xc2\x8a" => "\xc5\xa0",
87
        /**
88
         * LATIN CAPITAL LETTER S WITH CARON
89
         */
90
        "\xc2\x8b" => "\xe2\x80\xb9",
91
        /**
92
         * SINGLE LEFT-POINTING ANGLE QUOTATION
93
         */
94
        "\xc2\x8c" => "\xc5\x92",
95
        /**
96
         * LATIN CAPITAL LIGATURE OE
97
         */
98
        "\xc2\x8e" => "\xc5\xbd",
99
        /**
100
         * LATIN CAPITAL LETTER Z WITH CARON
101
         */
102
        "\xc2\x91" => "\xe2\x80\x98",
103
        /**
104
         * LEFT SINGLE QUOTATION MARK
105
         */
106
        "\xc2\x92" => "\xe2\x80\x99",
107
        /**
108
         * RIGHT SINGLE QUOTATION MARK
109
         */
110
        "\xc2\x93" => "\xe2\x80\x9c",
111
        /**
112
         * LEFT DOUBLE QUOTATION MARK
113
         */
114
        "\xc2\x94" => "\xe2\x80\x9d",
115
        /**
116
         * RIGHT DOUBLE QUOTATION MARK
117
         */
118
        "\xc2\x95" => "\xe2\x80\xa2",
119
        /**
120
         * BULLET
121
         */
122
        "\xc2\x96" => "\xe2\x80\x93",
123
        /**
124
         * EN DASH
125
         */
126
        "\xc2\x97" => "\xe2\x80\x94",
127
        /**
128
         * EM DASH
129
         */
130
        "\xc2\x98" => "\xcb\x9c",
131
        /**
132
         * SMALL TILDE
133
         */
134
        "\xc2\x99" => "\xe2\x84\xa2",
135
        /**
136
         * TRADEMARK SIGN
137
         */
138
        "\xc2\x9a" => "\xc5\xa1",
139
        /**
140
         * LATIN SMALL LETTER S WITH CARON
141
         */
142
        "\xc2\x9b" => "\xe2\x80\xba",
143
        /**
144
         * SINGLE RIGHT-POINTING ANGLE QUOTATION
145
         */
146
        "\xc2\x9c" => "\xc5\x93",
147
        /**
148
         * LATIN SMALL LIGATURE OE
149
         */
150
        "\xc2\x9e" => "\xc5\xbe",
151
        /**
152
         * LATIN SMALL LETTER Z WITH CARON
153
         */
154
        "\xc2\x9f" => "\xc5\xb8");
155
    /**
156
     * LATIN CAPITAL LETTER Y WITH DIAERESIS
157
     */
158
159
    public $ldap_server;
160
    public $ldap_port    = '389';
161
    public $ldap_version = '3';
162
    public $ldap_base_dn;
163
    public $ldap_loginname_asdn;
164
    public $ldap_loginldap_attr;
165
    public $ldap_mail_attr;
166
    public $ldap_name_attr;
167
    public $ldap_surname_attr;
168
    public $ldap_givenname_attr;
169
    public $ldap_manager_dn;
170
    public $ldap_manager_pass;
171
    public $_ds;
172
173
    /**
174
     * Authentication Service constructor
175
     * @param XoopsDatabase $dao
176
     */
177
    public function __construct(XoopsDatabase $dao = null)
178
    {
179
        $this->_dao = $dao;
180
        // The config handler object allows us to look at the configuration options that are stored in the database
181
        /** @var XoopsConfigHandler $config_handler */
182
        $config_handler = xoops_getHandler('config');
183
        $config         = $config_handler->getConfigsByCat(XOOPS_CONF_AUTH);
184
        $confcount      = count($config);
0 ignored issues
show
The assignment to $confcount is dead and can be removed.
Loading history...
185
        foreach ($config as $key => $val) {
186
            $this->$key = $val;
187
        }
188
    }
189
190
    /**
191
     * XoopsAuthLdap::cp1252_to_utf8()
192
     *
193
     * @param mixed $str
194
     *
195
     * @return string
196
     */
197
    public function cp1252_to_utf8($str)
198
    {
199
        return strtr(xoops_utf8_encode($str), $this->cp1252_map);
200
    }
201
202
    /**
203
     * Authenticate  user again LDAP directory (Bind)
204
     *               2 options :
205
     *         Authenticate directly with uname in the DN
206
     *         Authenticate with manager, search the dn
207
     *
208
     * @param  string $uname Username
209
     * @param  string $pwd   Password
210
     * @return bool
211
     */
212
    public function authenticate($uname, $pwd = null)
213
    {
214
        $authenticated = false;
215
        if (!extension_loaded('ldap')) {
216
            $this->setErrors(0, _AUTH_LDAP_EXTENSION_NOT_LOAD);
217
218
            return $authenticated;
219
        }
220
        $this->_ds = ldap_connect($this->ldap_server, $this->ldap_port);
221
        if ($this->_ds) {
222
            ldap_set_option($this->_ds, LDAP_OPT_PROTOCOL_VERSION, $this->ldap_version);
223
            if ($this->ldap_use_TLS) { // We use TLS secure connection
224
                if (!ldap_start_tls($this->_ds)) {
225
                    $this->setErrors(0, _AUTH_LDAP_START_TLS_FAILED);
226
                }
227
            }
228
            // If the uid is not in the DN we proceed to a search
229
            // The uid is not always in the dn
230
            $userDN = $this->getUserDN($uname);
231
            if (!$userDN) {
232
                return false;
233
            }
234
            // We bind as user to test the credentials
235
            $authenticated = ldap_bind($this->_ds, $userDN, stripslashes($pwd));
236
            if ($authenticated) {
237
                // We load the Xoops User database
238
                return $this->loadXoopsUser($userDN, $uname, $pwd);
239
            } else {
240
                $this->setErrors(ldap_errno($this->_ds), ldap_err2str(ldap_errno($this->_ds)) . '(' . $userDN . ')');
241
            }
242
        } else {
243
            $this->setErrors(0, _AUTH_LDAP_SERVER_NOT_FOUND);
244
        }
245
        @ldap_close($this->_ds);
246
247
        return $authenticated;
248
    }
249
250
    /**
251
     * Compose the user DN with the configuration.
252
     *
253
     * @param $uname
254
     * @return userDN or false
255
     */
256
    public function getUserDN($uname)
257
    {
258
        $userDN = false;
259
        if (!$this->ldap_loginname_asdn) {
260
            // Bind with the manager
261
            if (!ldap_bind($this->_ds, $this->ldap_manager_dn, stripslashes($this->ldap_manager_pass))) {
262
                $this->setErrors(ldap_errno($this->_ds), ldap_err2str(ldap_errno($this->_ds)) . '(' . $this->ldap_manager_dn . ')');
263
264
                return false;
265
            }
266
            $filter = $this->getFilter($uname);
267
            $sr     = ldap_search($this->_ds, $this->ldap_base_dn, $filter);
268
            $info   = ldap_get_entries($this->_ds, $sr);
269
            if ($info['count'] > 0) {
270
                $userDN = $info[0]['dn'];
271
            } else {
272
                $this->setErrors(0, sprintf(_AUTH_LDAP_USER_NOT_FOUND, $uname, $filter, $this->ldap_base_dn));
273
            }
274
        } else {
275
            $userDN = $this->ldap_loginldap_attr . '=' . $uname . ',' . $this->ldap_base_dn;
276
        }
277
278
        return $userDN;
279
    }
280
281
    /**
282
     * Load user from XOOPS Database
283
     *
284
     * @param $uname
285
     * @return XoopsUser object
286
     */
287
    public function getFilter($uname)
288
    {
289
        $filter = '';
290
        if ($this->ldap_filter_person != '') {
291
            $filter = str_replace('@@loginname@@', $uname, $this->ldap_filter_person);
292
        } else {
293
            $filter = $this->ldap_loginldap_attr . '=' . $uname;
294
        }
295
296
        return $filter;
297
    }
298
299
    /**
300
     * XoopsAuthLdap::loadXoopsUser()
301
     *
302
     * @param  mixed $userdn
303
     * @param  mixed $uname
304
     * @param  mixed $pwd
305
     * @return bool
306
     */
307
    public function loadXoopsUser($userdn, $uname, $pwd = null)
308
    {
309
        $provisHandler = XoopsAuthProvisionning::getInstance($this);
310
        $sr            = ldap_read($this->_ds, $userdn, '(objectclass=*)');
311
        $entries       = ldap_get_entries($this->_ds, $sr);
312
        if ($entries['count'] > 0) {
313
            $xoopsUser = $provisHandler->sync($entries[0], $uname, $pwd);
314
        } else {
315
            $this->setErrors(0, sprintf('loadXoopsUser - ' . _AUTH_LDAP_CANT_READ_ENTRY, $userdn));
316
        }
317
318
        return $xoopsUser;
319
    }
320
} // end class
321
322