[ Index ]

PHP Cross Reference of MantisBT

title

Body

[close]

/core/ -> ldap_api.php (source)

   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  }


Generated: Thu Jul 28 15:48:31 2011 Cross-referenced by PHPXref 0.7