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 <pemphp@free.fr>
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 <pemphp@free.fr>
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);
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: