PageRenderTime 35ms CodeModel.GetById 9ms RepoModel.GetById 1ms app.codeStats 0ms

/mrbs-1.4.8/web/auth_ldap.inc

#
PHP | 511 lines | 355 code | 47 blank | 109 comment | 45 complexity | fff3d4723a871b5b9f8d32f35c833c54 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. // $Id: auth_ldap.inc 2202 2011-12-17 20:05:28Z jberanek $
  3. /* ~~JFL 2003/11/12 By default, use the http session mechanism */
  4. if (!isset($auth['session']))
  5. {
  6. $auth['session']='http';
  7. }
  8. /* authLdapAction($callback, $user, &$object)
  9. *
  10. * Connects/binds to all configured LDAP servers/base DNs and
  11. * then performs a callback, passing the LDAP object, $base_dn,
  12. * user DN (in $dn), $user and a generic object $object
  13. *
  14. * $callback - The callback function
  15. * $user - The user name
  16. * &$object - Reference to the generic object, type defined by caller
  17. *
  18. * Returns:
  19. * 0 - The pair are invalid or do not exist
  20. * non-zero - The pair are valid
  21. */
  22. function authLdapAction($callback, $user, &$object)
  23. {
  24. global $auth;
  25. global $ldap_host;
  26. global $ldap_port;
  27. global $ldap_v3;
  28. global $ldap_tls;
  29. global $ldap_base_dn;
  30. global $ldap_user_attrib;
  31. global $ldap_dn_search_attrib;
  32. global $ldap_dn_search_dn;
  33. global $ldap_dn_search_password;
  34. global $ldap_filter;
  35. global $ldap_group_member_attrib;
  36. global $ldap_admin_group_dn;
  37. global $ldap_email_attrib;
  38. global $ldap_disable_referrals;
  39. if (!function_exists("ldap_connect"))
  40. {
  41. die("<hr><p><b>ERROR: PHP's 'ldap' extension is not installed/enabled. ".
  42. "Please check your MRBS and web server configuration.</b></p><hr>\n");
  43. }
  44. // Transfer the values from the config variables into a local
  45. // associative array, turning them all into arrays
  46. $config_items = array(
  47. 'ldap_host',
  48. 'ldap_port',
  49. 'ldap_base_dn',
  50. 'ldap_user_attrib',
  51. 'ldap_dn_search_attrib',
  52. 'ldap_dn_search_dn',
  53. 'ldap_dn_search_password',
  54. 'ldap_filter',
  55. 'ldap_group_member_attrib',
  56. 'ldap_admin_group_dn',
  57. 'ldap_v3',
  58. 'ldap_tls',
  59. 'ldap_email_attrib',
  60. 'ldap_disable_referrals'
  61. );
  62. $all_ldap_opts = array();
  63. foreach ($config_items as $item)
  64. {
  65. if (!isset($$item))
  66. {
  67. continue;
  68. }
  69. if (is_array($$item))
  70. {
  71. $all_ldap_opts[$item] = $$item;
  72. }
  73. // The case where the config item _isn't_ an array is handled
  74. // further down
  75. }
  76. $count = null;
  77. foreach ($all_ldap_opts as $key => $value)
  78. {
  79. if (isset($count))
  80. {
  81. if (count($value) != $count)
  82. {
  83. authLdapDebug("Count of LDAP array config variables doesn't match, aborting!");
  84. fatal_error(TRUE,
  85. "MRBS configuration error: Count of LDAP array config variables doesn't match, aborting!",
  86. false);
  87. return 0;
  88. }
  89. }
  90. $count = count($value);
  91. }
  92. // Turn any non-array config items into arrays in $all_ldap_opts
  93. foreach ($config_items as $item)
  94. {
  95. if (!isset($$item))
  96. {
  97. continue;
  98. }
  99. if (!is_array($$item))
  100. {
  101. $all_ldap_opts[$item] = array_fill(0, $count, $$item);
  102. }
  103. }
  104. foreach ($all_ldap_opts['ldap_host'] as $idx => $host)
  105. {
  106. // establish ldap connection
  107. // the '@' suppresses errors
  108. if (isset($all_ldap_opts['ldap_port'][$idx]))
  109. {
  110. $ldap = @ldap_connect($host, $all_ldap_opts['ldap_port'][$idx]);
  111. }
  112. else
  113. {
  114. $ldap = @ldap_connect($host);
  115. }
  116. // Check that connection was established
  117. if ($ldap)
  118. {
  119. authLdapDebug("authLdapAction: Got LDAP connection");
  120. if (isset($all_ldap_opts['ldap_v3'][$idx]) &&
  121. $all_ldap_opts['ldap_v3'][$idx])
  122. {
  123. ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
  124. }
  125. if (isset($all_ldap_opts['ldap_tls'][$idx]) &&
  126. $all_ldap_opts['ldap_tls'][$idx])
  127. {
  128. ldap_start_tls($ldap);
  129. }
  130. if(isset($all_ldap_opts['ldap_disable_referrals'][$idx]) && $all_ldap_opts['ldap_disable_referrals'][$idx])
  131. {
  132. // Required to do a search on Active Directory for Win 2003+
  133. ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
  134. }
  135. if (isset($all_ldap_opts['ldap_dn_search_attrib'][$idx]))
  136. {
  137. if (isset($all_ldap_opts['ldap_dn_search_dn'][$idx]) &&
  138. isset($all_ldap_opts['ldap_dn_search_password'][$idx]))
  139. {
  140. // Bind with DN and password
  141. $res = @ldap_bind($ldap, $all_ldap_opts['ldap_dn_search_dn'][$idx],
  142. $all_ldap_opts['ldap_dn_search_password'][$idx]);
  143. }
  144. else
  145. {
  146. // Anonymous bind
  147. $res = @ldap_bind($ldap);
  148. }
  149. authLdapDebug("authLdapAction: Result of initial bind is $res");
  150. if ($res)
  151. {
  152. $res = @ldap_search($ldap,
  153. $all_ldap_opts['ldap_base_dn'][$idx],
  154. "(". $all_ldap_opts['ldap_dn_search_attrib'][$idx] ."=$user)");
  155. if (@ldap_count_entries($ldap, $res) == 1)
  156. {
  157. authLdapDebug("authLdapAction: Found one entry using '".
  158. $all_ldap_opts['ldap_dn_search_attrib'][$idx]."'");
  159. $entries = ldap_get_entries($ldap, $res);
  160. $dn = $entries[0]["dn"];
  161. $user_search = "distinguishedName=" . $dn;
  162. }
  163. else
  164. {
  165. authLdapDebug("authLdapAction: Didn't find entry using '".
  166. $all_ldap_opts['ldap_dn_search_attrib'][$idx]."'");
  167. }
  168. authLdapDebug("authLdapAction: base_dn '".
  169. $all_ldap_opts['ldap_base_dn'][$idx].
  170. "' user $user dn $dn");
  171. }
  172. }
  173. else
  174. {
  175. // construct dn for user
  176. $user_search = $all_ldap_opts['ldap_user_attrib'][$idx] . "=" . $user;
  177. $dn = $user_search . "," . $all_ldap_opts['ldap_base_dn'][$idx];
  178. authLdapDebug("authLdapAction: Constructed dn '$dn' and ".
  179. "user_search '$user_search' using '".
  180. $all_ldap_opts['ldap_user_attrib'][$idx]."'");
  181. }
  182. foreach ($config_items as $item)
  183. {
  184. if (isset($all_ldap_opts[$item][$idx]))
  185. {
  186. $object['config'][$item] = $all_ldap_opts[$item][$idx];
  187. }
  188. }
  189. $res = $callback($ldap, $all_ldap_opts['ldap_base_dn'][$idx], $dn,
  190. $user_search, $user, $object);
  191. if ($res)
  192. {
  193. return $res;
  194. }
  195. } // if ($ldap)
  196. @ldap_unbind($ldap);
  197. } // foreach
  198. }
  199. /* authLdapGetEmail($user)
  200. *
  201. * Gets the email address of the user from LDAP
  202. *
  203. * $user - The user name
  204. *
  205. * Returns:
  206. * The user's email address or ''
  207. */
  208. function authLdapGetEmail($user)
  209. {
  210. $email = '';
  211. $object = array();
  212. $res = authLdapAction("authLdapGetEmailCallback", $user, $object);
  213. if ($res)
  214. {
  215. $email = $object['email'];
  216. }
  217. return $email;
  218. }
  219. /* authLdapGetEmailCallback(&$ldap, $base_dn, $dn, $user_search,
  220. $user, &$object)
  221. *
  222. * Checks if the specified username/password pair are valid
  223. *
  224. * &$ldap - Reference to the LDAP object
  225. * $base_dn - The base DN
  226. * $dn - The user's DN
  227. * $user_search - The LDAP filter to find the user
  228. * $user - The user name
  229. * &$object - Reference to the generic object
  230. *
  231. * Returns:
  232. * 0 - Didn't find a user
  233. * non-zero - Found a user
  234. */
  235. function authLdapGetEmailCallback(&$ldap, $base_dn, $dn, $user_search,
  236. $user, &$object)
  237. {
  238. $email_attrib = $object['config']['ldap_email_attrib'];
  239. authLdapDebug("authLdapGetEmailCallback: base_dn '$base_dn' dn '$dn' ".
  240. "user_search '$user_search' user '$user'");
  241. if ($ldap && $base_dn && $dn && $user_search)
  242. {
  243. $res = @ldap_read(
  244. $ldap,
  245. $dn,
  246. "(objectclass=*)",
  247. array(strtolower($email_attrib))
  248. );
  249. if (@ldap_count_entries($ldap, $res) > 0)
  250. {
  251. authLdapDebug("authLdapGetEmailCallback: search successful");
  252. $entries = ldap_get_entries($ldap, $res);
  253. $object['email'] = $entries[0][strtolower($email_attrib)][0];
  254. authLdapDebug("authLdapGetEmailCallback: email is '".
  255. $object['email']."'");
  256. return 1;
  257. }
  258. }
  259. return 0;
  260. }
  261. /* authValidateUser($user, $pass)
  262. *
  263. * Checks if the specified username/password pair are valid
  264. *
  265. * $user - The user name
  266. * $pass - The password
  267. *
  268. * Returns:
  269. * 0 - The pair are invalid or do not exist
  270. * non-zero - The pair are valid
  271. */
  272. function authValidateUser($user, $pass)
  273. {
  274. // Check if we do not have a username/password
  275. // User can always bind to LDAP anonymously with empty password,
  276. // therefore we need to block empty password here...
  277. if (!isset($user) || !isset($pass) || strlen($pass)==0)
  278. {
  279. authLdapDebug("Empty username or password passed");
  280. return 0;
  281. }
  282. $object = array();
  283. $object['pass'] = $pass;
  284. return authLdapAction("authValidateUserCallback", $user, $object);
  285. }
  286. /* authValidateUserCallback(&$ldap, $base_dn, $dn, $user_search,
  287. $user, &$object)
  288. *
  289. * Checks if the specified username/password pair are valid
  290. *
  291. * &$ldap - Reference to the LDAP object
  292. * $base_dn - The base DN
  293. * $dn - The user's DN
  294. * $user_search - The LDAP filter to find the user
  295. * $user - The user name
  296. * &$object - Reference to the generic object
  297. *
  298. * Returns:
  299. * 0 - Didn't find a user
  300. * non-zero - Found a user
  301. */
  302. function authValidateUserCallback(&$ldap, $base_dn, $dn, $user_search,
  303. $user, &$object)
  304. {
  305. authLdapDebug("authValidateUserCallback: base_dn '$base_dn' ".
  306. "dn '$dn' user '$user'");
  307. $pass = $object['pass'];
  308. // try an authenticated bind
  309. // use this to confirm that the user/password pair
  310. if ($dn && @ldap_bind($ldap, $dn, $pass))
  311. {
  312. $filter = $object['config']['ldap_filter'];
  313. // however if there is a filter check that the
  314. // user is part of the group defined by the filter
  315. if (! $filter)
  316. {
  317. authLdapDebug("authValidateUserCallback: Successful authenticated ".
  318. "bind with no \$ldap_filter");
  319. return 1;
  320. }
  321. else
  322. {
  323. authLdapDebug("authValidateUserCallback: Successful authenticated ".
  324. "bind checking '$filter'");
  325. $res = @ldap_read($ldap,
  326. $dn,
  327. "($filter)",
  328. array()
  329. );
  330. if (@ldap_count_entries($ldap, $res) > 0)
  331. {
  332. authLdapDebug("authValidateUserCallback: Found entry with filter");
  333. return 1;
  334. }
  335. authLdapDebug("authValidateUserCallback: No entry found with filter");
  336. }
  337. }
  338. else
  339. {
  340. authLdapDebug("authValidateUserCallback: Bind to '$dn' failed");
  341. }
  342. if ($ldap_unbind_between_attempts)
  343. {
  344. @ldap_unbind($ldap);
  345. }
  346. // return failure if no connection is established
  347. return 0;
  348. }
  349. /* authLdapCheckAdminGroupCallback(&$ldap, $base_dn, $dn, $user_search,
  350. $user, &$object)
  351. *
  352. * Checks if the specified username is in an admin group
  353. *
  354. * &$ldap - Reference to the LDAP object
  355. * $base_dn - The base DN
  356. * $dn - The user's DN
  357. * $user_search - The LDAP filter to find the user
  358. * $user - The user name
  359. * &$object - Reference to the generic object
  360. *
  361. * Returns:
  362. * 0 - Not in the admin group
  363. * non-zero - In the admin group
  364. */
  365. function authLdapCheckAdminGroupCallback(&$ldap, $base_dn, $dn, $user_search,
  366. $user, &$object)
  367. {
  368. $admin_group_dn = $object['config']['ldap_admin_group_dn'];
  369. $group_member_attrib = $object['config']['ldap_group_member_attrib'];
  370. authLdapDebug("authLdapCheckAdminGroupCallback: base_dn '$base_dn' ".
  371. "dn '$dn' user_search '$user_search' user '$user'");
  372. if ($ldap && $base_dn && $dn && $user_search)
  373. {
  374. $res = @ldap_read(
  375. $ldap,
  376. $dn,
  377. "(objectclass=*)",
  378. array(strtolower($group_member_attrib))
  379. );
  380. if (@ldap_count_entries($ldap, $res) > 0)
  381. {
  382. authLdapDebug("authCheckAdminGroupCallback: search successful".
  383. " $group_member_attrib");
  384. $entries = ldap_get_entries($ldap, $res);
  385. foreach ($entries[0][strtolower($group_member_attrib)] as $group)
  386. {
  387. if (strcasecmp($group, $admin_group_dn) == 0)
  388. {
  389. return 1;
  390. }
  391. }
  392. }
  393. }
  394. return 0;
  395. }
  396. /* authGetUserLevel($user)
  397. *
  398. * Determines the users access level
  399. *
  400. * $user - The user name
  401. *
  402. * Returns:
  403. * The users access level
  404. */
  405. function authGetUserLevel($user)
  406. {
  407. global $auth;
  408. global $ldap_admin_group_dn;
  409. $admins = $auth['admin'];
  410. // User not logged in, user level '0'
  411. if (!isset($user))
  412. {
  413. return 0;
  414. }
  415. if ($ldap_admin_group_dn)
  416. {
  417. $res = authLdapAction("authLdapCheckAdminGroupCallback", $user, $object);
  418. if ($res)
  419. {
  420. return 2;
  421. }
  422. else
  423. {
  424. return 1;
  425. }
  426. }
  427. // Check if the user is an admin
  428. foreach ($admins as $admin)
  429. {
  430. if (strcasecmp($user, $admin) == 0)
  431. {
  432. return 2;
  433. }
  434. }
  435. // Everybody else is access level '1'
  436. return 1;
  437. }
  438. /* authLdapDebug($message)
  439. *
  440. * Output LDAP debugging, if the configuration variable
  441. * $ldap_debug is true.
  442. *
  443. */
  444. function authLdapDebug($message)
  445. {
  446. global $ldap_debug;
  447. if ($ldap_debug)
  448. {
  449. error_log($message);
  450. }
  451. }
  452. ?>