PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Zend/Ldap.php

https://bitbucket.org/baruffaldi/website-2008-computer-shopping-3
PHP | 759 lines | 553 code | 49 blank | 157 comment | 48 complexity | 1c6307f998b16f45fe51b2699561f527 MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Ldap
  17. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id: Ldap.php 11765 2008-10-09 01:53:43Z miallen $
  20. */
  21. /**
  22. * @category Zend
  23. * @package Zend_Ldap
  24. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  25. * @license http://framework.zend.com/license/new-bsd New BSD License
  26. */
  27. class Zend_Ldap
  28. {
  29. const ACCTNAME_FORM_DN = 1;
  30. const ACCTNAME_FORM_USERNAME = 2;
  31. const ACCTNAME_FORM_BACKSLASH = 3;
  32. const ACCTNAME_FORM_PRINCIPAL = 4;
  33. /**
  34. * String used with ldap_connect for error handling purposes.
  35. *
  36. * @var string
  37. */
  38. private $_connectString;
  39. /**
  40. * The raw LDAP extension resource.
  41. *
  42. * @var resource
  43. */
  44. protected $_resource = null;
  45. /**
  46. * @param string $str The string to escape.
  47. * @return string The escaped string
  48. */
  49. public static function filterEscape($str)
  50. {
  51. $ret = '';
  52. $len = strlen($str);
  53. for ($si = 0; $si < $len; $si++) {
  54. $ch = $str[$si];
  55. $ord = ord($ch);
  56. if ($ord < 0x20 || $ord > 0x7e || strstr('*()\/', $ch)) {
  57. $ch = '\\' . dechex($ord);
  58. }
  59. $ret .= $ch;
  60. }
  61. return $ret;
  62. }
  63. /**
  64. * @param string $dn The DN to parse
  65. * @param array $keys An optional array to receive DN keys (e.g. CN, OU, DC, ...)
  66. * @param array $vals An optional array to receive DN values
  67. * @return bool True if the DN was successfully parsed or false if the string is not a valid DN.
  68. */
  69. public static function explodeDn($dn, array &$keys = null, array &$vals = null)
  70. {
  71. /* This is a classic state machine parser. Each iteration of the
  72. * loop processes one character. State 1 collects the key. When equals (=)
  73. * is encountered the state changes to 2 where the value is collected
  74. * until a comma (,) or semicolon (;) is encountered after which we switch back
  75. * to state 1. If a backslash (\) is encountered, state 3 is used to collect the
  76. * following character without engaging the logic of other states.
  77. */
  78. $key = null;
  79. $slen = strlen($dn);
  80. $state = 1;
  81. $ko = $vo = 0;
  82. for ($di = 0; $di <= $slen; $di++) {
  83. $ch = $di == $slen ? 0 : $dn[$di];
  84. switch ($state) {
  85. case 1: // collect key
  86. if ($ch === '=') {
  87. $key = trim(substr($dn, $ko, $di - $ko));
  88. if ($keys !== null) {
  89. $keys[] = $key;
  90. }
  91. $state = 2;
  92. $vo = $di + 1;
  93. } else if ($ch === ',' || $ch === ';') {
  94. return false;
  95. }
  96. break;
  97. case 2: // collect value
  98. if ($ch === '\\') {
  99. $state = 3;
  100. } else if ($ch === ',' || $ch === ';' || $ch === 0) {
  101. if ($vals !== null) {
  102. $vals[] = trim(substr($dn, $vo, $di - $vo));
  103. }
  104. $state = 1;
  105. $ko = $di + 1;
  106. } else if ($ch === '=') {
  107. return false;
  108. }
  109. break;
  110. case 3: // escaped
  111. $state = 2;
  112. break;
  113. }
  114. }
  115. return $state === 1 && $ko > 0;
  116. }
  117. /**
  118. * @param array $options Options used in connecting, binding, etc.
  119. * @return void
  120. */
  121. public function __construct(array $options = array())
  122. {
  123. $this->setOptions($options);
  124. }
  125. /**
  126. * Sets the options used in connecting, binding, etc.
  127. *
  128. * Valid option keys:
  129. * host
  130. * port
  131. * useSsl
  132. * username
  133. * password
  134. * bindRequiresDn
  135. * baseDn
  136. * accountCanonicalForm
  137. * accountDomainName
  138. * accountDomainNameShort
  139. * accountFilterFormat
  140. * allowEmptyPassword
  141. * useStartTls
  142. * optRefferals
  143. *
  144. * @param array $options Options used in connecting, binding, etc.
  145. * @return Zend_Ldap Provides a fluent interface
  146. * @throws Zend_Ldap_Exception
  147. */
  148. public function setOptions(array $options)
  149. {
  150. $permittedOptions = array(
  151. 'host' => null,
  152. 'port' => null,
  153. 'useSsl' => null,
  154. 'username' => null,
  155. 'password' => null,
  156. 'bindRequiresDn' => null,
  157. 'baseDn' => null,
  158. 'accountCanonicalForm' => null,
  159. 'accountDomainName' => null,
  160. 'accountDomainNameShort' => null,
  161. 'accountFilterFormat' => null,
  162. 'allowEmptyPassword' => null,
  163. 'useStartTls' => null,
  164. 'optReferrals' => null,
  165. );
  166. $diff = array_diff_key($options, $permittedOptions);
  167. if ($diff) {
  168. list($key, $val) = each($diff);
  169. require_once 'Zend/Ldap/Exception.php';
  170. throw new Zend_Ldap_Exception(null, "Unknown Zend_Ldap option: $key");
  171. }
  172. foreach ($permittedOptions as $key => $val) {
  173. if (!array_key_exists($key, $options)) {
  174. $options[$key] = null;
  175. } else {
  176. /* Enforce typing. This eliminates issues like Zend_Config_Ini
  177. * returning '1' as a string (ZF-3163).
  178. */
  179. switch ($key) {
  180. case 'port':
  181. case 'accountCanonicalForm':
  182. $options[$key] = (int)$options[$key];
  183. break;
  184. case 'useSsl':
  185. case 'bindRequiresDn':
  186. case 'allowEmptyPassword':
  187. case 'useStartTls':
  188. case 'optReferrals':
  189. $val = $options[$key];
  190. $options[$key] = $val === true ||
  191. $val === '1' ||
  192. strcasecmp($val, 'true') == 0;
  193. break;
  194. }
  195. }
  196. }
  197. $this->_options = $options;
  198. return $this;
  199. }
  200. /**
  201. * @return array The current options.
  202. */
  203. public function getOptions()
  204. {
  205. return $this->_options;
  206. }
  207. /**
  208. * @return resource The raw LDAP extension resource.
  209. */
  210. public function getResource()
  211. {
  212. /**
  213. * @todo by reference?
  214. */
  215. return $this->_resource;
  216. }
  217. /**
  218. * @return string The hostname of the LDAP server being used to authenticate accounts
  219. */
  220. protected function _getHost()
  221. {
  222. return $this->_options['host'];
  223. }
  224. /**
  225. * @return int The port of the LDAP server or 0 to indicate that no port value is set
  226. */
  227. protected function _getPort()
  228. {
  229. if ($this->_options['port'])
  230. return $this->_options['port'];
  231. return 0;
  232. }
  233. /**
  234. * @return string The default acctname for binding
  235. */
  236. protected function _getUsername()
  237. {
  238. return $this->_options['username'];
  239. }
  240. /**
  241. * @return string The default password for binding
  242. */
  243. protected function _getPassword()
  244. {
  245. return $this->_options['password'];
  246. }
  247. /**
  248. * @return boolean The default SSL / TLS encrypted transport control
  249. */
  250. protected function _getUseSsl()
  251. {
  252. return $this->_options['useSsl'];
  253. }
  254. /**
  255. * @return string The default base DN under which objects of interest are located
  256. */
  257. protected function _getBaseDn()
  258. {
  259. return $this->_options['baseDn'];
  260. }
  261. /**
  262. * @return string Either ACCTNAME_FORM_BACKSLASH, ACCTNAME_FORM_PRINCIPAL or ACCTNAME_FORM_USERNAME indicating the form usernames should be canonicalized to.
  263. */
  264. protected function _getAccountCanonicalForm()
  265. {
  266. /* Account names should always be qualified with a domain. In some scenarios
  267. * using non-qualified account names can lead to security vulnerabilities. If
  268. * no account canonical form is specified, we guess based in what domain
  269. * names have been supplied.
  270. */
  271. $accountCanonicalForm = $this->_options['accountCanonicalForm'];
  272. if (!$accountCanonicalForm) {
  273. $accountDomainName = $this->_options['accountDomainName'];
  274. $accountDomainNameShort = $this->_options['accountDomainNameShort'];
  275. if ($accountDomainNameShort) {
  276. $accountCanonicalForm = Zend_Ldap::ACCTNAME_FORM_BACKSLASH;
  277. } else if ($accountDomainName) {
  278. $accountCanonicalForm = Zend_Ldap::ACCTNAME_FORM_PRINCIPAL;
  279. } else {
  280. $accountCanonicalForm = Zend_Ldap::ACCTNAME_FORM_USERNAME;
  281. }
  282. }
  283. return $accountCanonicalForm;
  284. }
  285. /**
  286. * @return string A format string for building an LDAP search filter to match an account
  287. */
  288. protected function _getAccountFilterFormat()
  289. {
  290. return $this->_options['accountFilterFormat'];
  291. }
  292. /**
  293. * @return string The LDAP search filter for matching directory accounts
  294. */
  295. protected function _getAccountFilter($acctname)
  296. {
  297. $this->_splitName($acctname, $dname, $aname);
  298. $accountFilterFormat = $this->_getAccountFilterFormat();
  299. $aname = Zend_Ldap::filterEscape($aname);
  300. if ($accountFilterFormat)
  301. return sprintf($accountFilterFormat, $aname);
  302. if (!$this->_options['bindRequiresDn']) {
  303. // is there a better way to detect this?
  304. return "(&(objectClass=user)(sAMAccountName=$aname))";
  305. }
  306. return "(&(objectClass=posixAccount)(uid=$aname))";
  307. }
  308. /**
  309. * @param string $name The name to split
  310. * @param string $dname The resulting domain name (this is an out parameter)
  311. * @param string $aname The resulting account name (this is an out parameter)
  312. */
  313. protected function _splitName($name, &$dname, &$aname)
  314. {
  315. $dname = NULL;
  316. $aname = $name;
  317. $pos = strpos($name, '@');
  318. if ($pos) {
  319. $dname = substr($name, $pos + 1);
  320. $aname = substr($name, 0, $pos);
  321. } else {
  322. $pos = strpos($name, '\\');
  323. if ($pos) {
  324. $dname = substr($name, 0, $pos);
  325. $aname = substr($name, $pos + 1);
  326. }
  327. }
  328. }
  329. /**
  330. * @param string $acctname The name of the account
  331. * @return string The DN of the specified account
  332. * @throws Zend_Ldap_Exception
  333. */
  334. protected function _getAccountDn($acctname)
  335. {
  336. if (Zend_Ldap::explodeDn($acctname))
  337. return $acctname;
  338. $acctname = $this->getCanonicalAccountName($acctname, Zend_Ldap::ACCTNAME_FORM_USERNAME);
  339. $acct = $this->_getAccount($acctname, array('dn'));
  340. return $acct['dn'];
  341. }
  342. /**
  343. * @param string $dname The domain name to check
  344. * @return bool
  345. */
  346. protected function _isPossibleAuthority($dname)
  347. {
  348. if ($dname === null)
  349. return true;
  350. $accountDomainName = $this->_options['accountDomainName'];
  351. $accountDomainNameShort = $this->_options['accountDomainNameShort'];
  352. if ($accountDomainName === null && $accountDomainNameShort === null)
  353. return true;
  354. if (strcasecmp($dname, $accountDomainName) == 0)
  355. return true;
  356. if (strcasecmp($dname, $accountDomainNameShort) == 0)
  357. return true;
  358. return false;
  359. }
  360. /**
  361. * @param string $acctname The name to canonicalize
  362. * @param int $type The desired form of canonicalization
  363. * @return string The canonicalized name in the desired form
  364. * @throws Zend_Ldap_Exception
  365. */
  366. public function getCanonicalAccountName($acctname, $form = 0)
  367. {
  368. $this->_splitName($acctname, $dname, $uname);
  369. if (!$this->_isPossibleAuthority($dname)) {
  370. /**
  371. * @see Zend_Ldap_Exception
  372. */
  373. require_once 'Zend/Ldap/Exception.php';
  374. throw new Zend_Ldap_Exception(null,
  375. "Binding domain is not an authority for user: $acctname",
  376. Zend_Ldap_Exception::LDAP_X_DOMAIN_MISMATCH);
  377. }
  378. if ($form === Zend_Ldap::ACCTNAME_FORM_DN)
  379. return $this->_getAccountDn($acctname);
  380. if (!$uname) {
  381. /**
  382. * @see Zend_Ldap_Exception
  383. */
  384. require_once 'Zend/Ldap/Exception.php';
  385. throw new Zend_Ldap_Exception(null, "Invalid account name syntax: $acctname");
  386. }
  387. $uname = strtolower($uname);
  388. if ($form === 0)
  389. $form = $this->_getAccountCanonicalForm();
  390. switch ($form) {
  391. case Zend_Ldap::ACCTNAME_FORM_USERNAME:
  392. return $uname;
  393. case Zend_Ldap::ACCTNAME_FORM_BACKSLASH:
  394. $accountDomainNameShort = $this->_options['accountDomainNameShort'];
  395. if (!$accountDomainNameShort) {
  396. /**
  397. * @see Zend_Ldap_Exception
  398. */
  399. require_once 'Zend/Ldap/Exception.php';
  400. throw new Zend_Ldap_Exception(null, 'Option required: accountDomainNameShort');
  401. }
  402. return "$accountDomainNameShort\\$uname";
  403. case Zend_Ldap::ACCTNAME_FORM_PRINCIPAL:
  404. $accountDomainName = $this->_options['accountDomainName'];
  405. if (!$accountDomainName) {
  406. /**
  407. * @see Zend_Ldap_Exception
  408. */
  409. require_once 'Zend/Ldap/Exception.php';
  410. throw new Zend_Ldap_Exception(null, 'Option required: accountDomainName');
  411. }
  412. return "$uname@$accountDomainName";
  413. default:
  414. /**
  415. * @see Zend_Ldap_Exception
  416. */
  417. require_once 'Zend/Ldap/Exception.php';
  418. throw new Zend_Ldap_Exception(null, "Unknown canonical name form: $form");
  419. }
  420. }
  421. /**
  422. * @param array $attrs An array of names of desired attributes
  423. * @return array An array of the attributes representing the account
  424. * @throws Zend_Ldap_Exception
  425. */
  426. private function _getAccount($acctname, array $attrs = null)
  427. {
  428. $baseDn = $this->_getBaseDn();
  429. if (!$baseDn) {
  430. /**
  431. * @see Zend_Ldap_Exception
  432. */
  433. require_once 'Zend/Ldap/Exception.php';
  434. throw new Zend_Ldap_Exception(null, 'Base DN not set');
  435. }
  436. $accountFilter = $this->_getAccountFilter($acctname);
  437. if (!$accountFilter) {
  438. /**
  439. * @see Zend_Ldap_Exception
  440. */
  441. require_once 'Zend/Ldap/Exception.php';
  442. throw new Zend_Ldap_Exception(null, 'Invalid account filter');
  443. }
  444. if (!is_resource($this->_resource))
  445. $this->bind();
  446. $resource = $this->_resource;
  447. $str = $accountFilter;
  448. $code = 0;
  449. /**
  450. * @todo break out search operation into simple function (private for now)
  451. */
  452. if (!extension_loaded('ldap')) {
  453. /**
  454. * @see Zend_Ldap_Exception
  455. */
  456. require_once 'Zend/Ldap/Exception.php';
  457. throw new Zend_Ldap_Exception(null, 'LDAP extension not loaded');
  458. }
  459. $result = @ldap_search($resource,
  460. $baseDn,
  461. $accountFilter,
  462. $attrs);
  463. if (is_resource($result) === true) {
  464. $count = @ldap_count_entries($resource, $result);
  465. if ($count == 1) {
  466. $entry = @ldap_first_entry($resource, $result);
  467. if ($entry) {
  468. $acct = array('dn' => @ldap_get_dn($resource, $entry));
  469. $name = @ldap_first_attribute($resource, $entry, $berptr);
  470. while ($name) {
  471. $data = @ldap_get_values_len($resource, $entry, $name);
  472. $acct[$name] = $data;
  473. $name = @ldap_next_attribute($resource, $entry, $berptr);
  474. }
  475. @ldap_free_result($result);
  476. return $acct;
  477. }
  478. } else if ($count == 0) {
  479. /**
  480. * @see Zend_Ldap_Exception
  481. */
  482. require_once 'Zend/Ldap/Exception.php';
  483. $code = Zend_Ldap_Exception::LDAP_NO_SUCH_OBJECT;
  484. } else {
  485. /**
  486. * @todo limit search to 1 record and remove some of this logic?
  487. */
  488. $resource = null;
  489. $str = "$accountFilter: Unexpected result count: $count";
  490. /**
  491. * @see Zend_Ldap_Exception
  492. */
  493. require_once 'Zend/Ldap/Exception.php';
  494. $code = Zend_Ldap_Exception::LDAP_OPERATIONS_ERROR;
  495. }
  496. @ldap_free_result($result);
  497. }
  498. /**
  499. * @see Zend_Ldap_Exception
  500. */
  501. require_once 'Zend/Ldap/Exception.php';
  502. throw new Zend_Ldap_Exception($resource, $str, $code);
  503. }
  504. /**
  505. * @return Zend_Ldap Provides a fluent interface
  506. */
  507. public function disconnect()
  508. {
  509. if (is_resource($this->_resource)) {
  510. if (!extension_loaded('ldap')) {
  511. /**
  512. * @see Zend_Ldap_Exception
  513. */
  514. require_once 'Zend/Ldap/Exception.php';
  515. throw new Zend_Ldap_Exception(null, 'LDAP extension not loaded');
  516. }
  517. @ldap_unbind($this->_resource);
  518. }
  519. $this->_resource = null;
  520. return $this;
  521. }
  522. /**
  523. * @param string $host The hostname of the LDAP server to connect to
  524. * @param int $port The port number of the LDAP server to connect to
  525. * @return Zend_Ldap Provides a fluent interface
  526. * @throws Zend_Ldap_Exception
  527. */
  528. public function connect($host = null, $port = 0, $useSsl = false)
  529. {
  530. if ($host === null)
  531. $host = $this->_getHost();
  532. if ($port === 0)
  533. $port = $this->_getPort();
  534. if ($useSsl === false)
  535. $useSsl = $this->_getUseSsl();
  536. if (!$host) {
  537. /**
  538. * @see Zend_Ldap_Exception
  539. */
  540. require_once 'Zend/Ldap/Exception.php';
  541. throw new Zend_Ldap_Exception(null, 'A host parameter is required');
  542. }
  543. /* To connect using SSL it seems the client tries to verify the server
  544. * certificate by default. One way to disable this behavior is to set
  545. * 'TLS_REQCERT never' in OpenLDAP's ldap.conf and restarting Apache. Or,
  546. * if you really care about the server's cert you can put a cert on the
  547. * web server.
  548. */
  549. $url = $useSsl ? "ldaps://$host" : "ldap://$host";
  550. if ($port) {
  551. $url .= ":$port";
  552. }
  553. /* Because ldap_connect doesn't really try to connect, any connect error
  554. * will actually occur during the ldap_bind call. Therefore, we save the
  555. * connect string here for reporting it in error handling in bind().
  556. */
  557. $this->_connectString = $url;
  558. $this->disconnect();
  559. if (!extension_loaded('ldap')) {
  560. /**
  561. * @see Zend_Ldap_Exception
  562. */
  563. require_once 'Zend/Ldap/Exception.php';
  564. throw new Zend_Ldap_Exception(null, 'LDAP extension not loaded');
  565. }
  566. /* Only OpenLDAP 2.2 + supports URLs so if SSL is not requested, just
  567. * use the old form.
  568. */
  569. $resource = $useSsl ? @ldap_connect($url) : @ldap_connect($host, $port);
  570. if (is_resource($resource) === true) {
  571. $this->_resource = $resource;
  572. $optReferrals = $this->_options['optReferrals'] ? 1 : 0;
  573. if (@ldap_set_option($resource, LDAP_OPT_PROTOCOL_VERSION, 3) &&
  574. @ldap_set_option($resource, LDAP_OPT_REFERRALS, $optReferrals)) {
  575. if ($useSsl ||
  576. $this->_options['useStartTls'] !== true ||
  577. @ldap_start_tls($resource)) {
  578. return $this;
  579. }
  580. }
  581. /**
  582. * @see Zend_Ldap_Exception
  583. */
  584. require_once 'Zend/Ldap/Exception.php';
  585. $zle = new Zend_Ldap_Exception($resource, "$host:$port");
  586. $this->disconnect();
  587. throw $zle;
  588. }
  589. /**
  590. * @see Zend_Ldap_Exception
  591. */
  592. require_once 'Zend/Ldap/Exception.php';
  593. throw new Zend_Ldap_Exception("Failed to connect to LDAP server: $host:$port");
  594. }
  595. /**
  596. * @param string $username The username for authenticating the bind
  597. * @param string $password The password for authenticating the bind
  598. * @return Zend_Ldap Provides a fluent interface
  599. * @throws Zend_Ldap_Exception
  600. */
  601. public function bind($username = null, $password = null)
  602. {
  603. $moreCreds = true;
  604. if ($username === null) {
  605. $username = $this->_getUsername();
  606. $password = $this->_getPassword();
  607. $moreCreds = false;
  608. }
  609. if ($username === NULL) {
  610. /* Perform anonymous bind
  611. */
  612. $password = NULL;
  613. } else {
  614. /* Check to make sure the username is in DN form.
  615. */
  616. if (!Zend_Ldap::explodeDn($username)) {
  617. if ($this->_options['bindRequiresDn']) {
  618. /* moreCreds stops an infinite loop if _getUsername does not
  619. * return a DN and the bind requires it
  620. */
  621. if ($moreCreds) {
  622. try {
  623. $username = $this->_getAccountDn($username);
  624. } catch (Zend_Ldap_Exception $zle) {
  625. /**
  626. * @todo Temporary measure to deal with exception thrown for ldap extension not loaded
  627. */
  628. if (strpos($zle->getMessage(), 'LDAP extension not loaded') !== false) {
  629. throw $zle;
  630. }
  631. // end temporary measure
  632. switch ($zle->getCode()) {
  633. case Zend_Ldap_Exception::LDAP_NO_SUCH_OBJECT:
  634. case Zend_Ldap_Exception::LDAP_X_DOMAIN_MISMATCH:
  635. throw $zle;
  636. }
  637. throw new Zend_Ldap_Exception(null,
  638. 'Failed to retrieve DN for account: ' . $zle->getMessage(),
  639. Zend_Ldap_Exception::LDAP_OPERATIONS_ERROR);
  640. }
  641. } else {
  642. /**
  643. * @see Zend_Ldap_Exception
  644. */
  645. require_once 'Zend/Ldap/Exception.php';
  646. throw new Zend_Ldap_Exception(null, 'Binding requires username in DN form');
  647. }
  648. } else {
  649. $username = $this->getCanonicalAccountName($username,
  650. Zend_Ldap::ACCTNAME_FORM_PRINCIPAL);
  651. }
  652. }
  653. }
  654. if (!is_resource($this->_resource))
  655. $this->connect();
  656. if ($username !== null &&
  657. $password === '' &&
  658. $this->_options['allowEmptyPassword'] !== true) {
  659. /**
  660. * @see Zend_Ldap_Exception
  661. */
  662. require_once 'Zend/Ldap/Exception.php';
  663. $zle = new Zend_Ldap_Exception(null,
  664. 'Empty password not allowed - see allowEmptyPassword option.');
  665. } else {
  666. if (@ldap_bind($this->_resource, $username, $password))
  667. return $this;
  668. $message = $username === null ? $this->_connectString : $username;
  669. /**
  670. * @see Zend_Ldap_Exception
  671. */
  672. require_once 'Zend/Ldap/Exception.php';
  673. switch (Zend_Ldap_Exception::getLdapCode($this)) {
  674. case Zend_Ldap_Exception::LDAP_SERVER_DOWN:
  675. /* If the error is related to establishing a connection rather than binding,
  676. * the connect string is more informative than the username.
  677. */
  678. $message = $this->_connectString;
  679. }
  680. $zle = new Zend_Ldap_Exception($this->_resource, $message);
  681. }
  682. $this->disconnect();
  683. throw $zle;
  684. }
  685. }