| [ Index ] |
PHP Cross Reference of MantisBT |
[Summary view] [Print] [Text view]
1 <?php 2 # MantisBT - A PHP based bugtracking system 3 4 # MantisBT is free software: you can redistribute it and/or modify 5 # it under the terms of the GNU General Public License as published by 6 # the Free Software Foundation, either version 2 of the License, or 7 # (at your option) any later version. 8 # 9 # MantisBT is distributed in the hope that it will be useful, 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 # GNU General Public License for more details. 13 # 14 # You should have received a copy of the GNU General Public License 15 # along with MantisBT. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * LDAP API 19 * 20 * @package CoreAPI 21 * @subpackage LDAPAPI 22 * @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org 23 * @copyright Copyright (C) 2002 - 2011 MantisBT Team - mantisbt-dev@lists.sourceforge.net 24 * @link http://www.mantisbt.org 25 * 26 * @uses config_api.php 27 * @uses constant_inc.php 28 * @uses logging_api.php 29 * @uses user_api.php 30 * @uses utility_api.php 31 */ 32 33 require_api( 'config_api.php' ); 34 require_api( 'constant_inc.php' ); 35 require_api( 'logging_api.php' ); 36 require_api( 'user_api.php' ); 37 require_api( 'utility_api.php' ); 38 39 /** 40 * Connect and bind to the LDAP directory 41 * @param string $p_binddn 42 * @param string $p_password 43 * @return resource or false 44 */ 45 function ldap_connect_bind( $p_binddn = '', $p_password = '' ) { 46 if( !extension_loaded( 'ldap' ) ) { 47 log_event( LOG_LDAP, "Error: LDAP extension missing in php" ); 48 trigger_error( ERROR_LDAP_EXTENSION_NOT_LOADED, ERROR ); 49 } 50 51 $t_ldap_server = config_get( 'ldap_server' ); 52 53 log_event( LOG_LDAP, "Attempting connection to LDAP server '{$t_ldap_server}'." ); 54 $t_ds = @ldap_connect( $t_ldap_server ); 55 if ( $t_ds !== false && $t_ds > 0 ) { 56 log_event( LOG_LDAP, "Connection accepted to LDAP server" ); 57 $t_protocol_version = config_get( 'ldap_protocol_version' ); 58 59 if( $t_protocol_version > 0 ) { 60 log_event( LOG_LDAP, "Setting LDAP protocol to to ldap server to " . $t_protocol_version ); 61 ldap_set_option( $t_ds, LDAP_OPT_PROTOCOL_VERSION, $t_protocol_version ); 62 } 63 64 # Set referrals flag. 65 $t_follow_referrals = ON == config_get( 'ldap_follow_referrals' ); 66 ldap_set_option( $t_ds, LDAP_OPT_REFERRALS, $t_follow_referrals ); 67 68 # If no Bind DN and Password is set, attempt to login as the configured 69 # Bind DN. 70 if( is_blank( $p_binddn ) && is_blank( $p_password ) ) { 71 $p_binddn = config_get( 'ldap_bind_dn', '' ); 72 $p_password = config_get( 'ldap_bind_passwd', '' ); 73 } 74 75 if( !is_blank( $p_binddn ) && !is_blank( $p_password ) ) { 76 log_event( LOG_LDAP, "Attempting bind to ldap server with username and password" ); 77 $t_br = @ldap_bind( $t_ds, $p_binddn, $p_password ); 78 } else { 79 # Either the Bind DN or the Password are empty, so attempt an anonymous bind. 80 log_event( LOG_LDAP, "Attempting anonymous bind to ldap server" ); 81 $t_br = @ldap_bind( $t_ds ); 82 } 83 84 if ( !$t_br ) { 85 log_event( LOG_LDAP, "bind to ldap server failed: " . ldap_error( $t_ds ) ); 86 trigger_error( ERROR_LDAP_AUTH_FAILED, ERROR ); 87 } else { 88 log_event( LOG_LDAP, "bind to ldap server successful" ); 89 } 90 } else { 91 log_event( LOG_LDAP, "Connection to ldap server failed" ); 92 trigger_error( ERROR_LDAP_SERVER_CONNECT_FAILED, ERROR ); 93 } 94 95 return $t_ds; 96 } 97 98 $g_cache_ldap_email = array(); 99 100 /** 101 * returns an email address from LDAP, given a userid 102 * @param int $p_user_id 103 * @return string 104 */ 105 function ldap_email( $p_user_id ) { 106 global $g_cache_ldap_email; 107 108 if( isset( $g_cache_ldap_email[ (int)$p_user_id ] ) ) { 109 return $g_cache_ldap_email[ (int)$p_user_id ]; 110 } 111 112 $t_username = user_get_field( $p_user_id, 'username' ); 113 $t_email = ldap_email_from_username( $t_username ); 114 115 $g_cache_ldap_email[ (int)$p_user_id ] = $t_email; 116 return $t_email; 117 } 118 119 /** 120 * Return an email address from LDAP, given a username 121 * @param string $p_username 122 * @return string 123 */ 124 function ldap_email_from_username( $p_username ) { 125 if ( ldap_simulation_is_enabled() ) { 126 return ldap_simulation_email_from_username( $p_username ); 127 } 128 129 $t_email = ldap_get_field_from_username( $p_username, 'mail' ); 130 if ( $t_email === null ) { 131 return ''; 132 } 133 134 return $t_email; 135 } 136 137 /** 138 * Gets a user's real name (common name) given the id. 139 * 140 * @param int $p_user_id The user id. 141 * @return string real name. 142 */ 143 function ldap_realname( $p_user_id ) { 144 $t_username = user_get_field( $p_user_id, 'username' ); 145 return ldap_realname_from_username( $t_username ); 146 } 147 148 /** 149 * Gets a user real name given their user name. 150 * 151 * @param string $p_username The user's name. 152 * @return string The user's real name. 153 */ 154 function ldap_realname_from_username( $p_username ) { 155 if ( ldap_simulation_is_enabled() ) { 156 return ldap_simulatiom_realname_from_username( $p_username ); 157 } 158 159 $t_ldap_realname_field = config_get( 'ldap_realname_field' ); 160 $t_realname = ldap_get_field_from_username( $p_username, $t_ldap_realname_field ); 161 if ( $t_realname === null ) { 162 return ''; 163 } 164 165 return $t_realname; 166 } 167 168 /** 169 * Escapes the LDAP string to disallow injection. 170 * 171 * @param string $p_string The string to escape. 172 * @return string The escaped string. 173 */ 174 function ldap_escape_string( $p_string ) { 175 $t_find = array( '\\', '*', '(', ')', '/', "\x00" ); 176 $t_replace = array( '\5c', '\2a', '\28', '\29', '\2f', '\00' ); 177 178 $t_string = str_replace( $t_find, $t_replace, $p_string ); 179 180 return $t_string; 181 } 182 183 /** 184 * Gets the value of a specific field from LDAP given the user name 185 * and LDAP field name. 186 * 187 * @todo Implement caching by retrieving all needed information in one query. 188 * @todo Implement logging to LDAP queries same way like DB queries. 189 * 190 * @param string $p_username The user name. 191 * @param string $p_field The LDAP field name. 192 * @return string The field value or null if not found. 193 */ 194 function ldap_get_field_from_username( $p_username, $p_field ) { 195 $t_ldap_organization = config_get( 'ldap_organization' ); 196 $t_ldap_root_dn = config_get( 'ldap_root_dn' ); 197 $t_ldap_uid_field = config_get( 'ldap_uid_field' ); 198 199 $c_username = ldap_escape_string( $p_username ); 200 201 # Bind 202 log_event( LOG_LDAP, "Binding to LDAP server" ); 203 $t_ds = ldap_connect_bind(); 204 if ( $t_ds === false ) { 205 log_event( LOG_LDAP, "ldap_connect_bind() returned false." ); 206 return null; 207 } 208 209 # Search 210 $t_search_filter = "(&$t_ldap_organization($t_ldap_uid_field=$c_username))"; 211 $t_search_attrs = array( $t_ldap_uid_field, $p_field, 'dn' ); 212 213 log_event( LOG_LDAP, "Searching for $t_search_filter" ); 214 $t_sr = ldap_search( $t_ds, $t_ldap_root_dn, $t_search_filter, $t_search_attrs ); 215 if ( $t_sr === false ) { 216 ldap_unbind( $t_ds ); 217 log_event( LOG_LDAP, "ldap_search() returned false." ); 218 return null; 219 } 220 221 # Get results 222 $t_info = ldap_get_entries( $t_ds, $t_sr ); 223 if ( $t_info === false ) { 224 log_event( LOG_LDAP, "ldap_get_entries() returned false." ); 225 return null; 226 } 227 228 # Free results / unbind 229 log_event( LOG_LDAP, "Unbinding from LDAP server" ); 230 ldap_free_result( $t_sr ); 231 ldap_unbind( $t_ds ); 232 233 # If no matches, return null. 234 if ( count( $t_info ) == 0 ) { 235 log_event( LOG_LDAP, "No matches found." ); 236 return null; 237 } 238 239 # Make sure the requested field exists 240 if( is_array($t_info[0]) && array_key_exists( $p_field, $t_info[0] ) ) { 241 $t_value = $t_info[0][$p_field][0]; 242 log_event( LOG_LDAP, "Found value '{$t_value}' for field '{$p_field}'." ); 243 } else { 244 log_event( LOG_LDAP, "WARNING: field '$p_field' does not exist" ); 245 return null; 246 } 247 248 return $t_value; 249 } 250 251 /** 252 * Attempt to authenticate the user against the LDAP directory 253 * return true on successful authentication, false otherwise 254 * @param int $p_user_id 255 * @param string $p_password 256 * @return bool 257 */ 258 function ldap_authenticate( $p_user_id, $p_password ) { 259 # if password is empty and ldap allows anonymous login, then 260 # the user will be able to login, hence, we need to check 261 # for this special case. 262 if ( is_blank( $p_password ) ) { 263 return false; 264 } 265 266 $t_username = user_get_field( $p_user_id, 'username' ); 267 268 return ldap_authenticate_by_username( $t_username, $p_password ); 269 } 270 271 /** 272 * Authenticates an user via LDAP given the username and password. 273 * 274 * @param string $p_username The user name. 275 * @param string $p_password The password. 276 * @return true: authenticated, false: failed to authenticate. 277 */ 278 function ldap_authenticate_by_username( $p_username, $p_password ) { 279 if ( ldap_simulation_is_enabled() ) { 280 log_event( LOG_LDAP, "Authenticating via LDAP simulation" ); 281 $t_authenticated = ldap_simulation_authenticate_by_username( $p_username, $p_password ); 282 } else { 283 $c_username = ldap_escape_string( $p_username ); 284 285 $t_ldap_organization = config_get( 'ldap_organization' ); 286 $t_ldap_root_dn = config_get( 'ldap_root_dn' ); 287 288 $t_ldap_uid_field = config_get( 'ldap_uid_field', 'uid' ); 289 $t_search_filter = "(&$t_ldap_organization($t_ldap_uid_field=$c_username))"; 290 $t_search_attrs = array( 291 $t_ldap_uid_field, 292 'dn', 293 ); 294 295 # Bind 296 log_event( LOG_LDAP, "Binding to LDAP server" ); 297 $t_ds = ldap_connect_bind(); 298 if ( $t_ds === false ) { 299 log_event( LOG_LDAP, "ldap_connect_bind() returned false." ); 300 return null; 301 } 302 303 # Search for the user id 304 log_event( LOG_LDAP, "Searching for $t_search_filter" ); 305 $t_sr = ldap_search( $t_ds, $t_ldap_root_dn, $t_search_filter, $t_search_attrs ); 306 if ( $t_sr === false ) { 307 ldap_unbind( $t_ds ); 308 log_event( LOG_LDAP, "ldap_search() returned false." ); 309 return null; 310 } 311 312 $t_info = ldap_get_entries( $t_ds, $t_sr ); 313 if ( $t_info === false ) { 314 log_event( LOG_LDAP, "ldap_get_entries() returned false." ); 315 return null; 316 } 317 318 $t_authenticated = false; 319 320 if ( $t_info ) { 321 # Try to authenticate to each until we get a match 322 for ( $i = 0; $i < $t_info['count']; $i++ ) { 323 $t_dn = $t_info[$i]['dn']; 324 325 # Attempt to bind with the DN and password 326 if ( @ldap_bind( $t_ds, $t_dn, $p_password ) ) { 327 $t_authenticated = true; 328 break; 329 } 330 } 331 } 332 333 ldap_free_result( $t_sr ); 334 ldap_unbind( $t_ds ); 335 } 336 337 # If user authenticated successfully then update the local DB with information 338 # from LDAP. This will allow us to use the local data after login without 339 # having to go back to LDAP. This will also allow fallback to DB if LDAP is down. 340 if ( $t_authenticated ) { 341 $t_user_id = user_get_id_by_name( $p_username ); 342 343 if ( false !== $t_user_id ) { 344 user_set_field( $t_user_id, 'password', md5( $p_password ) ); 345 346 if ( ON == config_get( 'use_ldap_realname' ) ) { 347 $t_realname = ldap_realname( $t_user_id ); 348 user_set_field( $t_user_id, 'realname', $t_realname ); 349 } 350 351 if ( ON == config_get( 'use_ldap_email' ) ) { 352 $t_email = ldap_email_from_username( $p_username ); 353 user_set_field( $t_user_id, 'email', $t_email ); 354 } 355 } 356 } 357 358 return $t_authenticated; 359 } 360 361 /** 362 * Checks if the LDAP simulation mode is enabled. 363 * 364 * @return bool true if enabled, false otherwise. 365 */ 366 function ldap_simulation_is_enabled() { 367 $t_filename = config_get( 'ldap_simulation_file_path' ); 368 return !is_blank( $t_filename ); 369 } 370 371 /** 372 * Gets a user from LDAP simulation mode given the username. 373 * 374 * @param string $p_username The user name. 375 * @return mixed an associate array with user information or null if not found. 376 */ 377 function ldap_simulation_get_user( $p_username ) { 378 $t_filename = config_get( 'ldap_simulation_file_path' ); 379 $t_lines = file( $t_filename ); 380 if ( $t_lines === false ) { 381 log_event( LOG_LDAP, "ldap_simulation_get_user: could not read simulation data from $t_filename." ); 382 trigger_error( ERROR_LDAP_SERVER_CONNECT_FAILED, ERROR ); 383 } 384 385 foreach ( $t_lines as $t_line ) { 386 $t_line = trim( $t_line, " \t\r\n" ); 387 $t_row = explode( ',', $t_line ); 388 389 if ( $t_row[0] != $p_username ) { 390 continue; 391 } 392 393 $t_user = array(); 394 395 $t_user['username'] = $t_row[0]; 396 $t_user['realname'] = $t_row[1]; 397 $t_user['email'] = $t_row[2]; 398 $t_user['password'] = $t_row[3]; 399 400 return $t_user; 401 } 402 403 log_event( LOG_LDAP, "ldap_simulation_get_user: user '$p_username' not found." ); 404 return null; 405 } 406 407 /** 408 * Given a username, gets the email address or empty address if user is not found. 409 * 410 * @param string $p_username The user name. 411 * @return The email address or blank if user is not found. 412 */ 413 function ldap_simulation_email_from_username( $p_username ) { 414 $t_user = ldap_simulation_get_user( $p_username ); 415 if ( $t_user === null ) { 416 log_event( LOG_LDAP, "ldap_simulation_email_from_username: user '$p_username' not found." ); 417 return ''; 418 } 419 420 log_event( LOG_LDAP, "ldap_simulation_email_from_username: user '$p_username' has email '{$t_user['email']}'." ); 421 return $t_user['email']; 422 } 423 424 /** 425 * Given a username, this methods gets the realname or empty string if not found. 426 * 427 * @param string $p_username The username. 428 * @return string The real name or an empty string if not found. 429 */ 430 function ldap_simulatiom_realname_from_username( $p_username ) { 431 $t_user = ldap_simulation_get_user( $p_username ); 432 if ( $t_user === null ) { 433 log_event( LOG_LDAP, "ldap_simulatiom_realname_from_username: user '$p_username' not found." ); 434 return ''; 435 } 436 437 log_event( LOG_LDAP, "ldap_simulatiom_realname_from_username: user '$p_username' has email '{$t_user['realname']}'." ); 438 return $t_user['realname']; 439 } 440 441 /** 442 * Authenticates the specified user id / password based on the simulation data. 443 * 444 * @param string $p_username The username. 445 * @param string $p_password The password. 446 * @return bool true for authenticated, false otherwise. 447 */ 448 function ldap_simulation_authenticate_by_username( $p_username, $p_password ) { 449 $c_username = ldap_escape_string( $p_username ); 450 451 $t_user = ldap_simulation_get_user( $c_username ); 452 if ( $t_user === null ) { 453 log_event( LOG_LDAP, "ldap_simulation_authenticate: user '$p_username' not found." ); 454 return false; 455 } 456 457 if ( $t_user['password'] != $p_password ) { 458 log_event( LOG_LDAP, "ldap_simulation_authenticate: expected password '{$t_user['password']}' and got '$p_password'." ); 459 return false; 460 } 461 462 log_event( LOG_LDAP, "ldap_simulation_authenticate: authentication successful for user '$p_username'." ); 463 return true; 464 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Jul 28 15:48:31 2011 | Cross-referenced by PHPXref 0.7 |