PageRenderTime 25ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/phpBB/includes/auth/auth_ldap.php

http://github.com/phpbb/phpbb3
PHP | 346 lines | 258 code | 43 blank | 45 comment | 33 complexity | 63b7b9484d91e5facca8f7f34176e1cc MD5 | raw file
Possible License(s): AGPL-1.0
  1. <?php
  2. /**
  3. *
  4. * LDAP auth plug-in for phpBB3
  5. *
  6. * Authentication plug-ins is largely down to Sergey Kanareykin, our thanks to him.
  7. *
  8. * @package login
  9. * @copyright (c) 2005 phpBB Group
  10. * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
  11. *
  12. */
  13. /**
  14. * @ignore
  15. */
  16. if (!defined('IN_PHPBB'))
  17. {
  18. exit;
  19. }
  20. /**
  21. * Connect to ldap server
  22. * Only allow changing authentication to ldap if we can connect to the ldap server
  23. * Called in acp_board while setting authentication plugins
  24. */
  25. function init_ldap()
  26. {
  27. global $config, $user;
  28. if (!@extension_loaded('ldap'))
  29. {
  30. return $user->lang['LDAP_NO_LDAP_EXTENSION'];
  31. }
  32. $config['ldap_port'] = (int) $config['ldap_port'];
  33. if ($config['ldap_port'])
  34. {
  35. $ldap = @ldap_connect($config['ldap_server'], $config['ldap_port']);
  36. }
  37. else
  38. {
  39. $ldap = @ldap_connect($config['ldap_server']);
  40. }
  41. if (!$ldap)
  42. {
  43. return $user->lang['LDAP_NO_SERVER_CONNECTION'];
  44. }
  45. @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
  46. @ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
  47. if ($config['ldap_user'] || $config['ldap_password'])
  48. {
  49. if (!@ldap_bind($ldap, htmlspecialchars_decode($config['ldap_user']), htmlspecialchars_decode($config['ldap_password'])))
  50. {
  51. return $user->lang['LDAP_INCORRECT_USER_PASSWORD'];
  52. }
  53. }
  54. // ldap_connect only checks whether the specified server is valid, so the connection might still fail
  55. $search = @ldap_search(
  56. $ldap,
  57. htmlspecialchars_decode($config['ldap_base_dn']),
  58. ldap_user_filter($user->data['username']),
  59. (empty($config['ldap_email'])) ?
  60. array(htmlspecialchars_decode($config['ldap_uid'])) :
  61. array(htmlspecialchars_decode($config['ldap_uid']), htmlspecialchars_decode($config['ldap_email'])),
  62. 0,
  63. 1
  64. );
  65. if ($search === false)
  66. {
  67. return $user->lang['LDAP_SEARCH_FAILED'];
  68. }
  69. $result = @ldap_get_entries($ldap, $search);
  70. @ldap_close($ldap);
  71. if (!is_array($result) || sizeof($result) < 2)
  72. {
  73. return sprintf($user->lang['LDAP_NO_IDENTITY'], $user->data['username']);
  74. }
  75. if (!empty($config['ldap_email']) && !isset($result[0][htmlspecialchars_decode($config['ldap_email'])]))
  76. {
  77. return $user->lang['LDAP_NO_EMAIL'];
  78. }
  79. return false;
  80. }
  81. /**
  82. * Login function
  83. */
  84. function login_ldap(&$username, &$password)
  85. {
  86. global $db, $config, $user;
  87. // do not allow empty password
  88. if (!$password)
  89. {
  90. return array(
  91. 'status' => LOGIN_ERROR_PASSWORD,
  92. 'error_msg' => 'NO_PASSWORD_SUPPLIED',
  93. 'user_row' => array('user_id' => ANONYMOUS),
  94. );
  95. }
  96. if (!$username)
  97. {
  98. return array(
  99. 'status' => LOGIN_ERROR_USERNAME,
  100. 'error_msg' => 'LOGIN_ERROR_USERNAME',
  101. 'user_row' => array('user_id' => ANONYMOUS),
  102. );
  103. }
  104. if (!@extension_loaded('ldap'))
  105. {
  106. return array(
  107. 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
  108. 'error_msg' => 'LDAP_NO_LDAP_EXTENSION',
  109. 'user_row' => array('user_id' => ANONYMOUS),
  110. );
  111. }
  112. $config['ldap_port'] = (int) $config['ldap_port'];
  113. if ($config['ldap_port'])
  114. {
  115. $ldap = @ldap_connect($config['ldap_server'], $config['ldap_port']);
  116. }
  117. else
  118. {
  119. $ldap = @ldap_connect($config['ldap_server']);
  120. }
  121. if (!$ldap)
  122. {
  123. return array(
  124. 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
  125. 'error_msg' => 'LDAP_NO_SERVER_CONNECTION',
  126. 'user_row' => array('user_id' => ANONYMOUS),
  127. );
  128. }
  129. @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
  130. @ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
  131. if ($config['ldap_user'] || $config['ldap_password'])
  132. {
  133. if (!@ldap_bind($ldap, htmlspecialchars_decode($config['ldap_user']), htmlspecialchars_decode($config['ldap_password'])))
  134. {
  135. return $user->lang['LDAP_NO_SERVER_CONNECTION'];
  136. }
  137. }
  138. $search = @ldap_search(
  139. $ldap,
  140. htmlspecialchars_decode($config['ldap_base_dn']),
  141. ldap_user_filter($username),
  142. (empty($config['ldap_email'])) ?
  143. array(htmlspecialchars_decode($config['ldap_uid'])) :
  144. array(htmlspecialchars_decode($config['ldap_uid']), htmlspecialchars_decode($config['ldap_email'])),
  145. 0,
  146. 1
  147. );
  148. $ldap_result = @ldap_get_entries($ldap, $search);
  149. if (is_array($ldap_result) && sizeof($ldap_result) > 1)
  150. {
  151. if (@ldap_bind($ldap, $ldap_result[0]['dn'], htmlspecialchars_decode($password)))
  152. {
  153. @ldap_close($ldap);
  154. $sql ='SELECT user_id, username, user_password, user_passchg, user_email, user_type
  155. FROM ' . USERS_TABLE . "
  156. WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
  157. $result = $db->sql_query($sql);
  158. $row = $db->sql_fetchrow($result);
  159. $db->sql_freeresult($result);
  160. if ($row)
  161. {
  162. unset($ldap_result);
  163. // User inactive...
  164. if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE)
  165. {
  166. return array(
  167. 'status' => LOGIN_ERROR_ACTIVE,
  168. 'error_msg' => 'ACTIVE_ERROR',
  169. 'user_row' => $row,
  170. );
  171. }
  172. // Successful login... set user_login_attempts to zero...
  173. return array(
  174. 'status' => LOGIN_SUCCESS,
  175. 'error_msg' => false,
  176. 'user_row' => $row,
  177. );
  178. }
  179. else
  180. {
  181. // retrieve default group id
  182. $sql = 'SELECT group_id
  183. FROM ' . GROUPS_TABLE . "
  184. WHERE group_name = '" . $db->sql_escape('REGISTERED') . "'
  185. AND group_type = " . GROUP_SPECIAL;
  186. $result = $db->sql_query($sql);
  187. $row = $db->sql_fetchrow($result);
  188. $db->sql_freeresult($result);
  189. if (!$row)
  190. {
  191. trigger_error('NO_GROUP');
  192. }
  193. // generate user account data
  194. $ldap_user_row = array(
  195. 'username' => $username,
  196. 'user_password' => phpbb_hash($password),
  197. 'user_email' => (!empty($config['ldap_email'])) ? utf8_htmlspecialchars($ldap_result[0][htmlspecialchars_decode($config['ldap_email'])][0]) : '',
  198. 'group_id' => (int) $row['group_id'],
  199. 'user_type' => USER_NORMAL,
  200. 'user_ip' => $user->ip,
  201. 'user_new' => ($config['new_member_post_limit']) ? 1 : 0,
  202. );
  203. unset($ldap_result);
  204. // this is the user's first login so create an empty profile
  205. return array(
  206. 'status' => LOGIN_SUCCESS_CREATE_PROFILE,
  207. 'error_msg' => false,
  208. 'user_row' => $ldap_user_row,
  209. );
  210. }
  211. }
  212. else
  213. {
  214. unset($ldap_result);
  215. @ldap_close($ldap);
  216. // Give status about wrong password...
  217. return array(
  218. 'status' => LOGIN_ERROR_PASSWORD,
  219. 'error_msg' => 'LOGIN_ERROR_PASSWORD',
  220. 'user_row' => array('user_id' => ANONYMOUS),
  221. );
  222. }
  223. }
  224. @ldap_close($ldap);
  225. return array(
  226. 'status' => LOGIN_ERROR_USERNAME,
  227. 'error_msg' => 'LOGIN_ERROR_USERNAME',
  228. 'user_row' => array('user_id' => ANONYMOUS),
  229. );
  230. }
  231. /**
  232. * Generates a filter string for ldap_search to find a user
  233. *
  234. * @param $username string Username identifying the searched user
  235. *
  236. * @return string A filter string for ldap_search
  237. */
  238. function ldap_user_filter($username)
  239. {
  240. global $config;
  241. $filter = '(' . $config['ldap_uid'] . '=' . ldap_escape(htmlspecialchars_decode($username)) . ')';
  242. if ($config['ldap_user_filter'])
  243. {
  244. $_filter = ($config['ldap_user_filter'][0] == '(' && substr($config['ldap_user_filter'], -1) == ')') ? $config['ldap_user_filter'] : "({$config['ldap_user_filter']})";
  245. $filter = "(&{$filter}{$_filter})";
  246. }
  247. return $filter;
  248. }
  249. /**
  250. * Escapes an LDAP AttributeValue
  251. */
  252. function ldap_escape($string)
  253. {
  254. return str_replace(array('*', '\\', '(', ')'), array('\\*', '\\\\', '\\(', '\\)'), $string);
  255. }
  256. /**
  257. * This function is used to output any required fields in the authentication
  258. * admin panel. It also defines any required configuration table fields.
  259. */
  260. function acp_ldap(&$new)
  261. {
  262. global $user;
  263. $tpl = '
  264. <dl>
  265. <dt><label for="ldap_server">' . $user->lang['LDAP_SERVER'] . ':</label><br /><span>' . $user->lang['LDAP_SERVER_EXPLAIN'] . '</span></dt>
  266. <dd><input type="text" id="ldap_server" size="40" name="config[ldap_server]" value="' . $new['ldap_server'] . '" /></dd>
  267. </dl>
  268. <dl>
  269. <dt><label for="ldap_port">' . $user->lang['LDAP_PORT'] . ':</label><br /><span>' . $user->lang['LDAP_PORT_EXPLAIN'] . '</span></dt>
  270. <dd><input type="text" id="ldap_port" size="40" name="config[ldap_port]" value="' . $new['ldap_port'] . '" /></dd>
  271. </dl>
  272. <dl>
  273. <dt><label for="ldap_dn">' . $user->lang['LDAP_DN'] . ':</label><br /><span>' . $user->lang['LDAP_DN_EXPLAIN'] . '</span></dt>
  274. <dd><input type="text" id="ldap_dn" size="40" name="config[ldap_base_dn]" value="' . $new['ldap_base_dn'] . '" /></dd>
  275. </dl>
  276. <dl>
  277. <dt><label for="ldap_uid">' . $user->lang['LDAP_UID'] . ':</label><br /><span>' . $user->lang['LDAP_UID_EXPLAIN'] . '</span></dt>
  278. <dd><input type="text" id="ldap_uid" size="40" name="config[ldap_uid]" value="' . $new['ldap_uid'] . '" /></dd>
  279. </dl>
  280. <dl>
  281. <dt><label for="ldap_user_filter">' . $user->lang['LDAP_USER_FILTER'] . ':</label><br /><span>' . $user->lang['LDAP_USER_FILTER_EXPLAIN'] . '</span></dt>
  282. <dd><input type="text" id="ldap_user_filter" size="40" name="config[ldap_user_filter]" value="' . $new['ldap_user_filter'] . '" /></dd>
  283. </dl>
  284. <dl>
  285. <dt><label for="ldap_email">' . $user->lang['LDAP_EMAIL'] . ':</label><br /><span>' . $user->lang['LDAP_EMAIL_EXPLAIN'] . '</span></dt>
  286. <dd><input type="text" id="ldap_email" size="40" name="config[ldap_email]" value="' . $new['ldap_email'] . '" /></dd>
  287. </dl>
  288. <dl>
  289. <dt><label for="ldap_user">' . $user->lang['LDAP_USER'] . ':</label><br /><span>' . $user->lang['LDAP_USER_EXPLAIN'] . '</span></dt>
  290. <dd><input type="text" id="ldap_user" size="40" name="config[ldap_user]" value="' . $new['ldap_user'] . '" /></dd>
  291. </dl>
  292. <dl>
  293. <dt><label for="ldap_password">' . $user->lang['LDAP_PASSWORD'] . ':</label><br /><span>' . $user->lang['LDAP_PASSWORD_EXPLAIN'] . '</span></dt>
  294. <dd><input type="password" id="ldap_password" size="40" name="config[ldap_password]" value="' . $new['ldap_password'] . '" autocomplete="off" /></dd>
  295. </dl>
  296. ';
  297. // These are fields required in the config table
  298. return array(
  299. 'tpl' => $tpl,
  300. 'config' => array('ldap_server', 'ldap_port', 'ldap_base_dn', 'ldap_uid', 'ldap_user_filter', 'ldap_email', 'ldap_user', 'ldap_password')
  301. );
  302. }