auth.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. <?php
  2. use dokuwiki\Utf8\Sort;
  3. /**
  4. * LDAP authentication backend
  5. *
  6. * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
  7. * @author Andreas Gohr <andi@splitbrain.org>
  8. * @author Chris Smith <chris@jalakaic.co.uk>
  9. * @author Jan Schumann <js@schumann-it.com>
  10. */
  11. class auth_plugin_authldap extends DokuWiki_Auth_Plugin
  12. {
  13. /* @var resource $con holds the LDAP connection */
  14. protected $con = null;
  15. /* @var int $bound What type of connection does already exist? */
  16. protected $bound = 0; // 0: anonymous, 1: user, 2: superuser
  17. /* @var array $users User data cache */
  18. protected $users = null;
  19. /* @var array $pattern User filter pattern */
  20. protected $pattern = null;
  21. /**
  22. * Constructor
  23. */
  24. public function __construct()
  25. {
  26. parent::__construct();
  27. // ldap extension is needed
  28. if (!function_exists('ldap_connect')) {
  29. $this->debug("LDAP err: PHP LDAP extension not found.", -1, __LINE__, __FILE__);
  30. $this->success = false;
  31. return;
  32. }
  33. // Add the capabilities to change the password
  34. $this->cando['modPass'] = $this->getConf('modPass');
  35. }
  36. /**
  37. * Check user+password
  38. *
  39. * Checks if the given user exists and the given
  40. * plaintext password is correct by trying to bind
  41. * to the LDAP server
  42. *
  43. * @param string $user
  44. * @param string $pass
  45. * @return bool
  46. * @author Andreas Gohr <andi@splitbrain.org>
  47. */
  48. public function checkPass($user, $pass)
  49. {
  50. // reject empty password
  51. if (empty($pass)) return false;
  52. if (!$this->openLDAP()) return false;
  53. // indirect user bind
  54. if ($this->getConf('binddn') && $this->getConf('bindpw')) {
  55. // use superuser credentials
  56. if (!@ldap_bind($this->con, $this->getConf('binddn'), conf_decodeString($this->getConf('bindpw')))) {
  57. $this->debug('LDAP bind as superuser: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__);
  58. return false;
  59. }
  60. $this->bound = 2;
  61. } elseif ($this->getConf('binddn') &&
  62. $this->getConf('usertree') &&
  63. $this->getConf('userfilter')
  64. ) {
  65. // special bind string
  66. $dn = $this->makeFilter(
  67. $this->getConf('binddn'),
  68. array('user' => $user, 'server' => $this->getConf('server'))
  69. );
  70. } elseif (strpos($this->getConf('usertree'), '%{user}')) {
  71. // direct user bind
  72. $dn = $this->makeFilter(
  73. $this->getConf('usertree'),
  74. array('user' => $user, 'server' => $this->getConf('server'))
  75. );
  76. } else {
  77. // Anonymous bind
  78. if (!@ldap_bind($this->con)) {
  79. msg("LDAP: can not bind anonymously", -1);
  80. $this->debug('LDAP anonymous bind: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__);
  81. return false;
  82. }
  83. }
  84. // Try to bind to with the dn if we have one.
  85. if (!empty($dn)) {
  86. // User/Password bind
  87. if (!@ldap_bind($this->con, $dn, $pass)) {
  88. $this->debug("LDAP: bind with $dn failed", -1, __LINE__, __FILE__);
  89. $this->debug('LDAP user dn bind: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__);
  90. return false;
  91. }
  92. $this->bound = 1;
  93. return true;
  94. } else {
  95. // See if we can find the user
  96. $info = $this->fetchUserData($user, true);
  97. if (empty($info['dn'])) {
  98. return false;
  99. } else {
  100. $dn = $info['dn'];
  101. }
  102. // Try to bind with the dn provided
  103. if (!@ldap_bind($this->con, $dn, $pass)) {
  104. $this->debug("LDAP: bind with $dn failed", -1, __LINE__, __FILE__);
  105. $this->debug('LDAP user bind: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__);
  106. return false;
  107. }
  108. $this->bound = 1;
  109. return true;
  110. }
  111. }
  112. /**
  113. * Return user info
  114. *
  115. * Returns info about the given user needs to contain
  116. * at least these fields:
  117. *
  118. * name string full name of the user
  119. * mail string email addres of the user
  120. * grps array list of groups the user is in
  121. *
  122. * This LDAP specific function returns the following
  123. * addional fields:
  124. *
  125. * dn string distinguished name (DN)
  126. * uid string Posix User ID
  127. * inbind bool for internal use - avoid loop in binding
  128. *
  129. * @param string $user
  130. * @param bool $requireGroups (optional) - ignored, groups are always supplied by this plugin
  131. * @return array containing user data or false
  132. * @author <evaldas.auryla@pheur.org>
  133. * @author Stephane Chazelas <stephane.chazelas@emerson.com>
  134. * @author Steffen Schoch <schoch@dsb.net>
  135. *
  136. * @author Andreas Gohr <andi@splitbrain.org>
  137. * @author Trouble
  138. * @author Dan Allen <dan.j.allen@gmail.com>
  139. */
  140. public function getUserData($user, $requireGroups = true)
  141. {
  142. return $this->fetchUserData($user);
  143. }
  144. /**
  145. * @param string $user
  146. * @param bool $inbind authldap specific, true if in bind phase
  147. * @return array containing user data or false
  148. */
  149. protected function fetchUserData($user, $inbind = false)
  150. {
  151. global $conf;
  152. if (!$this->openLDAP()) return array();
  153. // force superuser bind if wanted and not bound as superuser yet
  154. if ($this->getConf('binddn') && $this->getConf('bindpw') && $this->bound < 2) {
  155. // use superuser credentials
  156. if (!@ldap_bind($this->con, $this->getConf('binddn'), conf_decodeString($this->getConf('bindpw')))) {
  157. $this->debug('LDAP bind as superuser: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__);
  158. return array();
  159. }
  160. $this->bound = 2;
  161. } elseif ($this->bound == 0 && !$inbind) {
  162. // in some cases getUserData is called outside the authentication workflow
  163. // eg. for sending email notification on subscribed pages. This data might not
  164. // be accessible anonymously, so we try to rebind the current user here
  165. list($loginuser, $loginsticky, $loginpass) = auth_getCookie();
  166. if ($loginuser && $loginpass) {
  167. $loginpass = auth_decrypt($loginpass, auth_cookiesalt(!$loginsticky, true));
  168. $this->checkPass($loginuser, $loginpass);
  169. }
  170. }
  171. $info = array();
  172. $info['user'] = $user;
  173. $this->debug('LDAP user to find: ' . hsc($info['user']), 0, __LINE__, __FILE__);
  174. $info['server'] = $this->getConf('server');
  175. $this->debug('LDAP Server: ' . hsc($info['server']), 0, __LINE__, __FILE__);
  176. //get info for given user
  177. $base = $this->makeFilter($this->getConf('usertree'), $info);
  178. if ($this->getConf('userfilter')) {
  179. $filter = $this->makeFilter($this->getConf('userfilter'), $info);
  180. } else {
  181. $filter = "(ObjectClass=*)";
  182. }
  183. $this->debug('LDAP Filter: ' . hsc($filter), 0, __LINE__, __FILE__);
  184. $this->debug('LDAP user search: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__);
  185. $this->debug('LDAP search at: ' . hsc($base . ' ' . $filter), 0, __LINE__, __FILE__);
  186. $sr = $this->ldapSearch($this->con, $base, $filter, $this->getConf('userscope'), $this->getConf('attributes'));
  187. if ($sr === false) {
  188. $this->debug('User ldap_search failed. Check configuration.', 0, __LINE__, __FILE__);
  189. return false;
  190. }
  191. $result = @ldap_get_entries($this->con, $sr);
  192. // if result is not an array
  193. if (!is_array($result)) {
  194. // no objects found
  195. $this->debug('LDAP search returned non-array result: ' . hsc(print($result)), -1, __LINE__, __FILE__);
  196. return array();
  197. }
  198. // Don't accept more or less than one response
  199. if ($result['count'] != 1) {
  200. $this->debug(
  201. 'LDAP search returned ' . hsc($result['count']) . ' results while it should return 1!',
  202. -1,
  203. __LINE__,
  204. __FILE__
  205. );
  206. //for($i = 0; $i < $result["count"]; $i++) {
  207. //$this->_debug('result: '.hsc(print_r($result[$i])), 0, __LINE__, __FILE__);
  208. //}
  209. return array();
  210. }
  211. $this->debug('LDAP search found single result !', 0, __LINE__, __FILE__);
  212. $user_result = $result[0];
  213. ldap_free_result($sr);
  214. // general user info
  215. $info['dn'] = $user_result['dn'];
  216. $info['gid'] = $user_result['gidnumber'][0];
  217. $info['mail'] = $user_result['mail'][0];
  218. $info['name'] = $user_result['cn'][0];
  219. $info['grps'] = array();
  220. // overwrite if other attribs are specified.
  221. if (is_array($this->getConf('mapping'))) {
  222. foreach ($this->getConf('mapping') as $localkey => $key) {
  223. if (is_array($key)) {
  224. // use regexp to clean up user_result
  225. // $key = array($key=>$regexp), only handles the first key-value
  226. $regexp = current($key);
  227. $key = key($key);
  228. if ($user_result[$key]) foreach ($user_result[$key] as $grpkey => $grp) {
  229. if ($grpkey !== 'count' && preg_match($regexp, $grp, $match)) {
  230. if ($localkey == 'grps') {
  231. $info[$localkey][] = $match[1];
  232. } else {
  233. $info[$localkey] = $match[1];
  234. }
  235. }
  236. }
  237. } else {
  238. $info[$localkey] = $user_result[$key][0];
  239. }
  240. }
  241. }
  242. $user_result = array_merge($info, $user_result);
  243. //get groups for given user if grouptree is given
  244. if ($this->getConf('grouptree') || $this->getConf('groupfilter')) {
  245. $base = $this->makeFilter($this->getConf('grouptree'), $user_result);
  246. $filter = $this->makeFilter($this->getConf('groupfilter'), $user_result);
  247. $sr = $this->ldapSearch(
  248. $this->con,
  249. $base,
  250. $filter,
  251. $this->getConf('groupscope'),
  252. array($this->getConf('groupkey'))
  253. );
  254. $this->debug('LDAP group search: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__);
  255. $this->debug('LDAP search at: ' . hsc($base . ' ' . $filter), 0, __LINE__, __FILE__);
  256. if (!$sr) {
  257. msg("LDAP: Reading group memberships failed", -1);
  258. return array();
  259. }
  260. $result = ldap_get_entries($this->con, $sr);
  261. ldap_free_result($sr);
  262. if (is_array($result)) foreach ($result as $grp) {
  263. if (!empty($grp[$this->getConf('groupkey')])) {
  264. $group = $grp[$this->getConf('groupkey')];
  265. if (is_array($group)) {
  266. $group = $group[0];
  267. } else {
  268. $this->debug('groupkey did not return a detailled result', 0, __LINE__, __FILE__);
  269. }
  270. if ($group === '') continue;
  271. $this->debug('LDAP usergroup: ' . hsc($group), 0, __LINE__, __FILE__);
  272. $info['grps'][] = $group;
  273. }
  274. }
  275. }
  276. // always add the default group to the list of groups
  277. if (!$info['grps'] or !in_array($conf['defaultgroup'], $info['grps'])) {
  278. $info['grps'][] = $conf['defaultgroup'];
  279. }
  280. return $info;
  281. }
  282. /**
  283. * Definition of the function modifyUser in order to modify the password
  284. *
  285. * @param string $user nick of the user to be changed
  286. * @param array $changes array of field/value pairs to be changed (password will be clear text)
  287. * @return bool true on success, false on error
  288. */
  289. public function modifyUser($user, $changes)
  290. {
  291. // open the connection to the ldap
  292. if (!$this->openLDAP()) {
  293. $this->debug('LDAP cannot connect: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__);
  294. return false;
  295. }
  296. // find the information about the user, in particular the "dn"
  297. $info = $this->getUserData($user, true);
  298. if (empty($info['dn'])) {
  299. $this->debug('LDAP cannot find your user dn', 0, __LINE__, __FILE__);
  300. return false;
  301. }
  302. $dn = $info['dn'];
  303. // find the old password of the user
  304. list($loginuser, $loginsticky, $loginpass) = auth_getCookie();
  305. if ($loginuser !== null) { // the user is currently logged in
  306. $secret = auth_cookiesalt(!$loginsticky, true);
  307. $pass = auth_decrypt($loginpass, $secret);
  308. // bind with the ldap
  309. if (!@ldap_bind($this->con, $dn, $pass)) {
  310. $this->debug(
  311. 'LDAP user bind failed: ' . hsc($dn) . ': ' . hsc(ldap_error($this->con)),
  312. 0,
  313. __LINE__,
  314. __FILE__
  315. );
  316. return false;
  317. }
  318. } elseif ($this->getConf('binddn') && $this->getConf('bindpw')) {
  319. // we are changing the password on behalf of the user (eg: forgotten password)
  320. // bind with the superuser ldap
  321. if (!@ldap_bind($this->con, $this->getConf('binddn'), conf_decodeString($this->getConf('bindpw')))) {
  322. $this->debug('LDAP bind as superuser: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__);
  323. return false;
  324. }
  325. } else {
  326. return false; // no otherway
  327. }
  328. // Generate the salted hashed password for LDAP
  329. $phash = new \dokuwiki\PassHash();
  330. $hash = $phash->hash_ssha($changes['pass']);
  331. // change the password
  332. if (!@ldap_mod_replace($this->con, $dn, array('userpassword' => $hash))) {
  333. $this->debug(
  334. 'LDAP mod replace failed: ' . hsc($dn) . ': ' . hsc(ldap_error($this->con)),
  335. 0,
  336. __LINE__,
  337. __FILE__
  338. );
  339. return false;
  340. }
  341. return true;
  342. }
  343. /**
  344. * Most values in LDAP are case-insensitive
  345. *
  346. * @return bool
  347. */
  348. public function isCaseSensitive()
  349. {
  350. return false;
  351. }
  352. /**
  353. * Bulk retrieval of user data
  354. *
  355. * @param int $start index of first user to be returned
  356. * @param int $limit max number of users to be returned
  357. * @param array $filter array of field/pattern pairs, null for no filter
  358. * @return array of userinfo (refer getUserData for internal userinfo details)
  359. * @author Dominik Eckelmann <dokuwiki@cosmocode.de>
  360. */
  361. public function retrieveUsers($start = 0, $limit = 0, $filter = array())
  362. {
  363. if (!$this->openLDAP()) return array();
  364. if (is_null($this->users)) {
  365. // Perform the search and grab all their details
  366. if ($this->getConf('userfilter')) {
  367. $all_filter = str_replace('%{user}', '*', $this->getConf('userfilter'));
  368. } else {
  369. $all_filter = "(ObjectClass=*)";
  370. }
  371. $sr = ldap_search($this->con, $this->getConf('usertree'), $all_filter);
  372. $entries = ldap_get_entries($this->con, $sr);
  373. $users_array = array();
  374. $userkey = $this->getConf('userkey');
  375. for ($i = 0; $i < $entries["count"]; $i++) {
  376. array_push($users_array, $entries[$i][$userkey][0]);
  377. }
  378. Sort::asort($users_array);
  379. $result = $users_array;
  380. if (!$result) return array();
  381. $this->users = array_fill_keys($result, false);
  382. }
  383. $i = 0;
  384. $count = 0;
  385. $this->constructPattern($filter);
  386. $result = array();
  387. foreach ($this->users as $user => &$info) {
  388. if ($i++ < $start) {
  389. continue;
  390. }
  391. if ($info === false) {
  392. $info = $this->getUserData($user);
  393. }
  394. if ($this->filter($user, $info)) {
  395. $result[$user] = $info;
  396. if (($limit > 0) && (++$count >= $limit)) break;
  397. }
  398. }
  399. return $result;
  400. }
  401. /**
  402. * Make LDAP filter strings.
  403. *
  404. * Used by auth_getUserData to make the filter
  405. * strings for grouptree and groupfilter
  406. *
  407. * @param string $filter ldap search filter with placeholders
  408. * @param array $placeholders placeholders to fill in
  409. * @return string
  410. * @author Troels Liebe Bentsen <tlb@rapanden.dk>
  411. */
  412. protected function makeFilter($filter, $placeholders)
  413. {
  414. preg_match_all("/%{([^}]+)/", $filter, $matches, PREG_PATTERN_ORDER);
  415. //replace each match
  416. foreach ($matches[1] as $match) {
  417. //take first element if array
  418. if (is_array($placeholders[$match])) {
  419. $value = $placeholders[$match][0];
  420. } else {
  421. $value = $placeholders[$match];
  422. }
  423. $value = $this->filterEscape($value);
  424. $filter = str_replace('%{' . $match . '}', $value, $filter);
  425. }
  426. return $filter;
  427. }
  428. /**
  429. * return true if $user + $info match $filter criteria, false otherwise
  430. *
  431. * @param string $user the user's login name
  432. * @param array $info the user's userinfo array
  433. * @return bool
  434. * @author Chris Smith <chris@jalakai.co.uk>
  435. *
  436. */
  437. protected function filter($user, $info)
  438. {
  439. foreach ($this->pattern as $item => $pattern) {
  440. if ($item == 'user') {
  441. if (!preg_match($pattern, $user)) return false;
  442. } elseif ($item == 'grps') {
  443. if (!count(preg_grep($pattern, $info['grps']))) return false;
  444. } else {
  445. if (!preg_match($pattern, $info[$item])) return false;
  446. }
  447. }
  448. return true;
  449. }
  450. /**
  451. * Set the filter pattern
  452. *
  453. * @param $filter
  454. * @return void
  455. * @author Chris Smith <chris@jalakai.co.uk>
  456. *
  457. */
  458. protected function constructPattern($filter)
  459. {
  460. $this->pattern = array();
  461. foreach ($filter as $item => $pattern) {
  462. $this->pattern[$item] = '/' . str_replace('/', '\/', $pattern) . '/i'; // allow regex characters
  463. }
  464. }
  465. /**
  466. * Escape a string to be used in a LDAP filter
  467. *
  468. * Ported from Perl's Net::LDAP::Util escape_filter_value
  469. *
  470. * @param string $string
  471. * @return string
  472. * @author Andreas Gohr
  473. */
  474. protected function filterEscape($string)
  475. {
  476. // see https://github.com/adldap/adLDAP/issues/22
  477. return preg_replace_callback(
  478. '/([\x00-\x1F\*\(\)\\\\])/',
  479. function ($matches) {
  480. return "\\" . join("", unpack("H2", $matches[1]));
  481. },
  482. $string
  483. );
  484. }
  485. /**
  486. * Opens a connection to the configured LDAP server and sets the wanted
  487. * option on the connection
  488. *
  489. * @author Andreas Gohr <andi@splitbrain.org>
  490. */
  491. protected function openLDAP()
  492. {
  493. if ($this->con) return true; // connection already established
  494. if ($this->getConf('debug')) {
  495. ldap_set_option(null, LDAP_OPT_DEBUG_LEVEL, 7);
  496. }
  497. $this->bound = 0;
  498. $port = $this->getConf('port');
  499. $bound = false;
  500. $servers = explode(',', $this->getConf('server'));
  501. foreach ($servers as $server) {
  502. $server = trim($server);
  503. $this->con = @ldap_connect($server, $port);
  504. if (!$this->con) {
  505. continue;
  506. }
  507. /*
  508. * When OpenLDAP 2.x.x is used, ldap_connect() will always return a resource as it does
  509. * not actually connect but just initializes the connecting parameters. The actual
  510. * connect happens with the next calls to ldap_* funcs, usually with ldap_bind().
  511. *
  512. * So we should try to bind to server in order to check its availability.
  513. */
  514. //set protocol version and dependend options
  515. if ($this->getConf('version')) {
  516. if (!@ldap_set_option(
  517. $this->con,
  518. LDAP_OPT_PROTOCOL_VERSION,
  519. $this->getConf('version')
  520. )
  521. ) {
  522. msg('Setting LDAP Protocol version ' . $this->getConf('version') . ' failed', -1);
  523. $this->debug('LDAP version set: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__);
  524. } else {
  525. //use TLS (needs version 3)
  526. if ($this->getConf('starttls')) {
  527. if (!@ldap_start_tls($this->con)) {
  528. msg('Starting TLS failed', -1);
  529. $this->debug('LDAP TLS set: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__);
  530. }
  531. }
  532. // needs version 3
  533. if ($this->getConf('referrals') > -1) {
  534. if (!@ldap_set_option(
  535. $this->con,
  536. LDAP_OPT_REFERRALS,
  537. $this->getConf('referrals')
  538. )
  539. ) {
  540. msg('Setting LDAP referrals failed', -1);
  541. $this->debug('LDAP referal set: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__);
  542. }
  543. }
  544. }
  545. }
  546. //set deref mode
  547. if ($this->getConf('deref')) {
  548. if (!@ldap_set_option($this->con, LDAP_OPT_DEREF, $this->getConf('deref'))) {
  549. msg('Setting LDAP Deref mode ' . $this->getConf('deref') . ' failed', -1);
  550. $this->debug('LDAP deref set: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__);
  551. }
  552. }
  553. /* As of PHP 5.3.0 we can set timeout to speedup skipping of invalid servers */
  554. if (defined('LDAP_OPT_NETWORK_TIMEOUT')) {
  555. ldap_set_option($this->con, LDAP_OPT_NETWORK_TIMEOUT, 1);
  556. }
  557. if ($this->getConf('binddn') && $this->getConf('bindpw')) {
  558. $bound = @ldap_bind($this->con, $this->getConf('binddn'), conf_decodeString($this->getConf('bindpw')));
  559. $this->bound = 2;
  560. } else {
  561. $bound = @ldap_bind($this->con);
  562. }
  563. if ($bound) {
  564. break;
  565. }
  566. }
  567. if (!$bound) {
  568. msg("LDAP: couldn't connect to LDAP server", -1);
  569. $this->debug(ldap_error($this->con), 0, __LINE__, __FILE__);
  570. return false;
  571. }
  572. $this->cando['getUsers'] = true;
  573. return true;
  574. }
  575. /**
  576. * Wraps around ldap_search, ldap_list or ldap_read depending on $scope
  577. *
  578. * @param resource $link_identifier
  579. * @param string $base_dn
  580. * @param string $filter
  581. * @param string $scope can be 'base', 'one' or 'sub'
  582. * @param null|array $attributes
  583. * @param int $attrsonly
  584. * @param int $sizelimit
  585. * @return resource
  586. * @author Andreas Gohr <andi@splitbrain.org>
  587. */
  588. protected function ldapSearch(
  589. $link_identifier,
  590. $base_dn,
  591. $filter,
  592. $scope = 'sub',
  593. $attributes = null,
  594. $attrsonly = 0,
  595. $sizelimit = 0
  596. )
  597. {
  598. if (is_null($attributes)) $attributes = array();
  599. if ($scope == 'base') {
  600. return @ldap_read(
  601. $link_identifier,
  602. $base_dn,
  603. $filter,
  604. $attributes,
  605. $attrsonly,
  606. $sizelimit
  607. );
  608. } elseif ($scope == 'one') {
  609. return @ldap_list(
  610. $link_identifier,
  611. $base_dn,
  612. $filter,
  613. $attributes,
  614. $attrsonly,
  615. $sizelimit
  616. );
  617. } else {
  618. return @ldap_search(
  619. $link_identifier,
  620. $base_dn,
  621. $filter,
  622. $attributes,
  623. $attrsonly,
  624. $sizelimit
  625. );
  626. }
  627. }
  628. /**
  629. * Wrapper around msg() but outputs only when debug is enabled
  630. *
  631. * @param string $message
  632. * @param int $err
  633. * @param int $line
  634. * @param string $file
  635. * @return void
  636. */
  637. protected function debug($message, $err, $line, $file)
  638. {
  639. if (!$this->getConf('debug')) return;
  640. msg($message, $err, $line, $file);
  641. }
  642. }