You are here

ldapauth.module in LDAP integration 6

Same filename and directory in other branches
  1. 5.2 ldapauth.module
  2. 5 ldapauth.module

ldapauth provides authentication against ldap server.

File

ldapauth.module
View source
<?php

/**
 * @file
 * ldapauth provides authentication against ldap server.
 */

//////////////////////////////////////////////////////////////////////////////
define('LDAPAUTH_AUTH_MIXED', 0);
define('LDAPAUTH_AUTH_EXCLUSIVED', 1);
define('LDAPAUTH_CONFLICT_LOG', 0);
define('LDAPAUTH_CONFLICT_RESOLVE', 1);
define('LDAPAUTH_EMAIL_FIELD_NO', 0);
define('LDAPAUTH_EMAIL_FIELD_REMOVE', 1);
define('LDAPAUTH_EMAIL_FIELD_DISABLE', 2);
define('LDAPAUTH_PROFILE', 'LDAP authentication');
define('LDAPAUTH_PROFILE_WEIGHT', 4);
define('LDAPAUTH_USERNAME_FIELD_NO', 0);
define('LDAPAUTH_USERNAME_FIELD_REMOVE', 1);
define('LDAPAUTH_USERNAME_FIELD_DISABLE', 2);

// hook_*_alter operations (a.la. ldap in Drupal 7)
define('LDAPAUTH_SYNC_CONTEXT_INSERT_DRUPAL_USER', 1);
define('LDAPAUTH_SYNC_CONTEXT_UPDATE_DRUPAL_USER', 2);
define('LDAPAUTH_SYNC_CONTEXT_AUTHENTICATE_DRUPAL_USER', 3);
define('LDAPAUTH_SYNC_CONTEXT_CRON', 4);
define('LDAPAUTH_SYNC_CONTEXT_DELETE_DRUPAL_USER', 5);
define('LDAPAUTH_SYNC_CONTEXT_DISABLE_DRUPAL_USER', 6);
define('LDAPAUTH_LOGIN_PROCESS', variable_get('ldapauth_login_process', LDAPAUTH_AUTH_MIXED));
define('LDAPAUTH_LOGIN_CONFLICT', variable_get('ldapauth_login_conflict', LDAPAUTH_CONFLICT_LOG));
define('LDAPAUTH_FORGET_PASSWORDS', variable_get('ldapauth_forget_passwords', TRUE));
define('LDAPAUTH_SYNC_PASSWORDS', variable_get('ldapauth_sync_passwords', FALSE));
define('LDAPAUTH_DISABLE_PASS_CHANGE', variable_get('ldapauth_disable_pass_change', FALSE));
define('LDAPAUTH_ALTER_EMAIL_FIELD', variable_get('ldapauth_alter_email_field', LDAPAUTH_EMAIL_FIELD_NO));
define('LDAPAUTH_DEFAULT_USER_ATTR', variable_get('ldapauth_default_user_attr', 'uid'));
define('LDAPAUTH_DEFAULT_MAIL_ATTR', variable_get('ldapauth_default_mail_attr', 'mail'));
define('LDAPAUTH_ALTER_USERNAME_FIELD', variable_get('ldapauth_alter_username_field', LDAPAUTH_USERNAME_FIELD_NO));

//////////////////////////////////////////////////////////////////////////////

// Core API hooks

/**
 * Implements hook_init().
 */
function ldapauth_init() {
  module_load_include('inc', 'ldapauth', 'includes/LDAPInterface');
  module_load_include('inc', 'ldapauth', 'includes/ldap.core');
}

/**
 * Implementation of hook_help().
 */
function ldapauth_help($path, $arg) {
  switch ($path) {
    case 'admin/settings/ldapauth':
      return '<p>' . t('A system wide settings will affect all configured LDAP servers.') . '</p>';
  }
}

/**
 * Implements hook_menu().
 */
function ldapauth_menu() {
  $items = array(
    'admin/settings/ldap' => array(
      'title' => 'LDAP',
      'description' => 'Configure LDAP integration settings.',
      'page callback' => 'ldapauth_admin_menu_block_page',
      'access arguments' => array(
        'administer ldap modules',
      ),
      'file' => 'ldapauth.admin.inc',
    ),
    'admin/settings/ldap/ldapauth' => array(
      'title' => 'Authentication',
      'description' => 'Configure LDAP authentication settings.',
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'ldapauth_admin_settings',
      ),
      'access arguments' => array(
        'administer ldap modules',
      ),
      'file' => 'ldapauth.admin.inc',
    ),
    'admin/settings/ldap/ldapauth/configure' => array(
      'title' => 'Settings',
      'type' => MENU_DEFAULT_LOCAL_TASK,
    ),
    'admin/settings/ldap/ldapauth/list' => array(
      'title' => 'List',
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'ldapauth_admin_list',
      ),
      'type' => MENU_LOCAL_TASK,
      'weight' => 1,
      'access arguments' => array(
        'administer ldap modules',
      ),
      'file' => 'ldapauth.admin.inc',
    ),
    'admin/settings/ldap/ldapauth/add' => array(
      'title' => 'Add Server',
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'ldapauth_admin_form',
        4,
      ),
      'type' => MENU_LOCAL_TASK,
      'weight' => 2,
      'access arguments' => array(
        'administer ldap modules',
      ),
      'file' => 'ldapauth.admin.inc',
    ),
    'admin/settings/ldap/ldapauth/edit' => array(
      'title' => 'Configure LDAP Server',
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'ldapauth_admin_form',
        4,
        5,
      ),
      'type' => MENU_CALLBACK,
      'access arguments' => array(
        'administer ldap modules',
      ),
      'file' => 'ldapauth.admin.inc',
    ),
    'admin/settings/ldap/ldapauth/edit/%/test' => array(
      'title' => 'Test LDAP Server',
      'page callback' => '_ldapauth_ajax_test',
      'page arguments' => array(
        5,
      ),
      'type' => MENU_CALLBACK,
      'access arguments' => array(
        'administer ldap modules',
      ),
      'file' => 'ldapauth.admin.inc',
    ),
    'admin/settings/ldap/ldapauth/delete' => array(
      'title' => 'Delete LDAP Server',
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'ldapauth_admin_delete',
        5,
      ),
      'type' => MENU_CALLBACK,
      'access arguments' => array(
        'administer ldap modules',
      ),
      'file' => 'ldapauth.admin.inc',
    ),
    'admin/settings/ldap/ldapauth/activate' => array(
      'title' => 'Activate LDAP Source',
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'ldapauth_admin_activate',
      ),
      'access arguments' => array(
        'administer ldap modules',
      ),
      'type' => MENU_CALLBACK,
      'file' => 'ldapauth.admin.inc',
    ),
    'admin/settings/ldap/ldapauth/deactivate' => array(
      'title' => 'De-activate LDAP Source',
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'ldapauth_admin_deactivate',
      ),
      'access arguments' => array(
        'administer ldap modules',
      ),
      'type' => MENU_CALLBACK,
      'file' => 'ldapauth.admin.inc',
    ),
    'admin/settings/ldap/ldapauth/user/%user/tolocal' => array(
      'title' => 'Convert LDAP user to local user',
      'page callback' => 'ldapauth_user_to_local_user',
      'page arguments' => array(
        5,
      ),
      'type' => MENU_CALLBACK,
      'access arguments' => array(
        'administer users',
      ),
      'file' => 'ldapauth.admin.inc',
    ),
  );

  // Need ctools to export or import
  if (module_exists("ctools")) {
    $items['admin/settings/ldap/ldapauth/export/%ldapauth_server'] = array(
      'title' => 'Export Server Settings',
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'ldapauth_admin_export_form',
        5,
      ),
      'type' => MENU_CALLBACK,
      'access arguments' => array(
        'administer ldap modules',
      ),
      'file' => 'ldapauth.admin.inc',
    );
    $items['admin/settings/ldap/ldapauth/import'] = array(
      'title' => 'Import Server',
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'ldapauth_admin_import_form',
      ),
      'type' => MENU_LOCAL_TASK,
      'weight' => 3,
      'access arguments' => array(
        'administer ldap modules',
      ),
      'file' => 'ldapauth.admin.inc',
    );
  }
  return $items;
}

/**
 * Implements hook_theme().
 */
function ldapauth_theme() {
  return array(
    'ldapauth_admin_list' => array(
      'arguments' => array(
        'form' => NULL,
      ),
      'file' => 'ldapauth.theme.inc',
    ),
  );
}

/**
 * Implements hook_user().
 */
function ldapauth_user($op, &$edit, &$account, $category = NULL) {
  switch ($op) {
    case 'validate':
      if (isset($account->ldap_authentified) && LDAPAUTH_ALTER_EMAIL_FIELD == LDAPAUTH_EMAIL_FIELD_REMOVE || LDAPAUTH_ALTER_EMAIL_FIELD == LDAPAUTH_EMAIL_FIELD_DISABLE) {
        unset($edit['mail']);
      }
      break;
    case 'update':

      // Handle password mods after ldapdata does update in submit
      if ($category == 'account') {

        // If authentication is being done in "LDAP only" mode, passwords
        // should not be written to the database, or users would be able
        // to log in even after removing their LDAP entry.
        if (isset($account->ldap_authentified) && (LDAPAUTH_LOGIN_PROCESS == LDAPAUTH_AUTH_EXCLUSIVED || !LDAPAUTH_SYNC_PASSWORDS)) {
          $edit['pass'] = NULL;
        }
      }
      break;
    case 'view':
      $category_title = t('LDAP authentication');
      if (user_access('administer users') && isset($account->ldap_authentified) && $account->ldap_dn) {
        $server = ldapauth_server_load($account->ldap_config);
        $account->content[$category_title] = array(
          '#type' => 'user_profile_category',
          '#title' => $category_title,
          '#attributes' => array(
            'class' => 'ldapauth-entry',
          ),
          '#weight' => LDAPAUTH_PROFILE_WEIGHT,
          'ldap_to_local' => array(
            '#type' => 'user_profile_item',
            '#title' => t('Convert User'),
            '#value' => l(t('Convert from LDAP user to local Drupal user'), 'admin/settings/ldap/ldapauth/user/' . $account->uid . '/tolocal'),
            '#weight' => -1,
          ),
          'ldap_server' => array(
            '#type' => 'user_profile_item',
            '#title' => t('LDAP server'),
            '#value' => l($server->name, 'admin/settings/ldap/ldapauth/edit/' . $server->sid),
            '#weight' => 0,
          ),
          'ldap_dn' => array(
            '#type' => 'user_profile_item',
            '#title' => t('LDAP dn'),
            '#value' => $account->ldap_dn,
            '#weight' => 1,
          ),
        );
        if (!empty($server->puid_attr)) {
          $user_info = ldapauth_userinfo_load_by_uid($account->uid);
          $puid = $user_info ? $user_info->puid : t("PUID MISSING!!!!");
          $account->content[$category_title]['ldap_puid'] = array(
            '#type' => 'user_profile_item',
            '#title' => t('LDAP PUID'),
            '#value' => $puid,
            '#weight' => 3,
          );
        }
      }
      break;
    case 'delete':
      $user_info = ldapauth_userinfo_load_by_uid($account->uid);
      ldapauth_userinfo_delete($user_info);
      db_query("DELETE FROM {authmap} WHERE uid = %d AND module = 'ldapauth'", $account->uid);
      break;
  }
}

/**
 * Implementation of hook_menu_alter().
 */
function ldapauth_menu_alter(&$callbacks) {
  if (variable_get('ldapauth_disable_pass_change', FALSE)) {
    unset($callbacks['user/password']);
  }
}

/**
 * Implements hook_perm().
 */
function ldapauth_perm() {
  return array(
    'administer ldap modules',
  );
}

/**
 * Implements hook_form_alter().
 */
function ldapauth_form_alter(&$form, $form_state, $form_id) {
  global $user;

  // Replace the drupal authenticate function is it's used as validation.
  if (isset($form['#validate']) && is_array($form['#validate']) && ($key = array_search('user_login_authenticate_validate', $form['#validate']))) {
    $form['#validate'][$key] = 'ldapauth_login_authenticate_validate';
  }
  switch ($form_id) {
    case 'user_login_block':
    case 'user_login':
      if (LDAPAUTH_DISABLE_PASS_CHANGE && $user->uid != 1) {
        unset($form['links']);
        $key = array_search('user_login_final_validate', $form['#validate']);
        $form['#validate'][$key] = 'ldapauth_user_login_final_validate';
      }
      break;
    case 'user_profile_form':
      $account = $form["_account"]["#value"];
      if ($user->uid != 1 && isset($account->ldap_authentified)) {
        switch (LDAPAUTH_ALTER_USERNAME_FIELD) {
          case LDAPAUTH_USERNAME_FIELD_REMOVE:
            $form['account']['name']['#type'] = 'hidden';
            $form['account']['name']['#attributes']['READONLY'] = 'READONLY';
            break;
          case LDAPAUTH_USERNAME_FIELD_DISABLE:
            $form['account']['name']['#attributes']['READONLY'] = 'READONLY';
            $form['account']['name']['#description'] = t('NOTE: Can only be changed on the LDAP server.') . '<br/>' . $form['account']['name']['#description'];
            break;
        }
        if (LDAPAUTH_DISABLE_PASS_CHANGE) {
          unset($form['account']['pass']);
        }
        switch (LDAPAUTH_ALTER_EMAIL_FIELD) {
          case LDAPAUTH_EMAIL_FIELD_REMOVE:
            $form['account']['mail']['#type'] = 'hidden';
            $form['account']['mail']['#attributes']['READONLY'] = 'READONLY';
            break;
          case LDAPAUTH_EMAIL_FIELD_DISABLE:
            $form['account']['mail']['#attributes']['READONLY'] = 'READONLY';
            break;
        }

        // Remove fieldset if empty.
        if (isset($form['account']) && !isset($form['account']['pass']) && $form['account']['mail']['#type'] == 'hidden' && count(array_filter($form['account'], create_function('$a', 'return is_array($a) ? TRUE : FALSE;'))) == 1) {
          $form['mail'] = $form['account']['mail'];
          unset($form['account']);
        }
      }
      break;
  }
}
function ldapauth_user_login_final_validate($form_id, &$form_states) {
  global $user;
  if (!$user->uid) {
    form_set_error('name', t('Sorry, unrecognized username or password.'));
    watchdog('user', 'Login attempt failed for %user.', array(
      '%user' => $form_values['name'],
    ));
  }
}
function ldapauth_form_user_pass_alter(&$form, &$form_state) {
  $form['#validate'][] = 'ldapauth_user_pass';
}
function ldapauth_user_pass($form, &$form_state) {
  if (isset($account->ldap_authentified)) {
    $can_reset = FALSE;
    if (!LDAPAUTH_DISABLE_PASS_CHANGE) {

      // Admin allows password changes via Drupal
      $server = ldapauth_server_load($account->ldap_config);

      // Get user's ldapauth server info
      if (!empty($server->ldapdata_binddn) && !empty($server->ldapdata_bindpw)) {
        $can_reset = TRUE;

        // Assume the advance user info in ldapdata can change passwords.
      }
    }
    if (!$can_reset) {
      form_set_error('name', t("This is an LDAP account, to change or retrieve the password, please, contact your LDAP administrator"));
      unset($form_state['values']['account']);
    }
  }
}

/**
 * Implements hook_exit().
 */
function ldapauth_exit() {

  // We delete the login info here, instead of just not storing it at
  // _ldapauth_auth(), so at least ldapgroups can use it at login time.
  if (LDAPAUTH_FORGET_PASSWORDS && isset($_SESSION['ldap_login'])) {
    unset($_SESSION['ldap_login']);
  }
}

//////////////////////////////////////////////////////////////////////////////

// Login process functions

/**
 * Main user validation function.  Replaces Drupal default login form validation.
 *
 * If successful, sets the global $user object.
 */
function ldapauth_login_authenticate_validate($form, &$form_state) {
  ldapauth_authenticate($form_state['values']);
}

/**
 * Main user authentication function.  Called by form validator.
 *
 * If successful, sets the global $user object.
 */
function ldapauth_authenticate($form_values = array()) {
  global $user, $_ldapauth_ldap;
  $name = $form_values['name'];
  $pass = $form_values['pass'];

  // The user_login_name_validate() is not called if the user is being authenticated
  // from the httpauth or services modules, therefore call it here.
  $form_state['values'] = $form_values;
  user_login_name_validate(NULL, $form_state);
  if (form_get_errors()) {
    ldapauth_debug_msg(t("authenticate: User, @user, failed Drupal core login name validation test.", array(
      '@user' => $name,
    )));
    return;
  }

  // (Design decision) uid=1 (admin user) must always authenticate to local database
  // this user is critical for all drupal admin and upgrade operations so it is best
  // left with drupal's native authentication.
  $result = db_query("SELECT uid FROM {users} WHERE LOWER(name) = LOWER('%s') AND uid = '1'", $name);
  if ($account = db_fetch_object($result)) {
    ldapauth_debug_msg(t("authenticate: User, @user, is local admin(uid=1)", array(
      '@user' => $name,
    )));
    user_authenticate($form_values);
    return;
  }
  if (LDAPAUTH_LOGIN_PROCESS == LDAPAUTH_AUTH_MIXED) {

    // Authenticate local users first.
    $result = db_query("SELECT name, data FROM {users} WHERE LOWER(name) = LOWER('%s')", $name);
    if ($row = db_fetch_array($result)) {
      $data = unserialize($row['data']);
      if (!isset($data['ldap_authentified']) || $data['ldap_authentified'] == 0) {

        // A local user with same name exists - authenticate that user.
        ldapauth_debug_msg(t("authenticate: User, @user, is a local Drupal user - calling Drupal authentication", array(
          '@user' => $name,
        )));
        if (user_authenticate($form_values)) {

          // Nullify global ldap resource for good measure.
          unset($_ldapauth_ldap);
          return;
        }
        ldapauth_debug_msg(t("authenticate: User, @user: Drupal authentication failed, seeing if id/password works with an LDAP user.", array(
          '@user' => $name,
        )));
      }
    }
  }

  // Find and Authenticate LDAP user.
  if (!($dn = _ldapauth_auth($name, $pass))) {
    ldapauth_debug_msg(t("authenticate: User, @user, was not found in LDAP or authentication failed..", array(
      '@user' => $name,
    )));
    return;
  }
  ldapauth_debug_msg(t("authenticate: User, @user, mapped to LDAP DN, @dn.", array(
    '@user' => $name,
    '@dn' => $dn,
  )));

  // See if there is a matching Drupal user account
  $error = '';
  $account = ldapauth_drupal_user_lookup($_ldapauth_ldap, $name, $dn, $error);
  if ($account === NULL) {
    form_set_error("name", $error);
    watchdog('ldapauth', $error, NULL, WATCHDOG_ERROR);
  }

  // Allow other modules to determine if this ldap user can access server.
  if (ldapauth_user_denied($_ldapauth_ldap, $name, $dn, $account)) {
    ldapauth_debug_msg(t("authenticate: User, @user, denied by another module via hook_ldap_user_deny().", array(
      '@user' => $name,
    )));
    return;
  }

  // Have account: Do some default login checks
  if ($account !== FALSE) {
    ldapauth_debug_msg(t("authenticate: User, @user, was linked to existing Drupal account, @duser(uid=@uid).", array(
      '@user' => $name,
      '@duser' => $account->name,
      '@uid' => $account->uid,
    )));
    if ($account->status != 1) {

      // User is blocked.
      ldapauth_debug_msg(t("authenticate: User, @user, was marked as blocked in Drupal database.", array(
        '@user' => $name,
      )));
      return;

      // Returns default unknown id/password msg per core
    }
    if (drupal_is_denied('mail', $account->mail)) {
      ldapauth_debug_msg(t("authenticate: User, @user, was denied because it was registered using a reserved e-mail address.", array(
        '@user' => $name,
      )));
      form_set_error('name', t('The name %name is registered using a reserved e-mail address and therefore could not be logged in.', array(
        '%name' => $account->name,
      )));
    }
    if ($account->uid == 1) {
      ldapauth_debug_msg(t("authenticate: User, @user, denied by another module via hook_ldap_user_deny().", array(
        '@user' => $name,
      )));
      return;

      // LDAP user matched superuser!! Shouldn't get here but just in case
    }
  }

  // If there is any validations errors, we do not query LDAP.
  if (form_get_errors()) {
    return;
  }

  // No matching Drupal user, try to create one for this LDAP account.
  if (!$account) {
    ldapauth_debug_msg(t("authenticate: Attempting to creating local Drupal user, @user.", array(
      '@user' => $name,
    )));
    $error = '';
    $account = ldapauth_drupal_user_create($_ldapauth_ldap, $name, $dn, $error);
    if ($account === FALSE) {
      form_set_error('name', $error);
      return;
    }
    $user = $account;
  }
  else {
    $data = array(
      'ldap_dn' => $dn,
      'ldap_config' => $_ldapauth_ldap
        ->getOption('sid'),
      'ldap_name' => $name,
    );

    // LDAP and local user conflict.
    if (!isset($account->ldap_authentified)) {
      if (LDAPAUTH_LOGIN_CONFLICT == LDAPAUTH_CONFLICT_LOG) {
        watchdog('ldapauth', 'LDAP user with DN %dn has a naming conflict with a local drupal user %name', array(
          '%dn' => $dn,
          '%name' => $account->name,
        ), WATCHDOG_ERROR);
        drupal_set_message(t('Another user already exists in the system with the same login name. You should contact the system administrator in order to solve this conflict.'), 'error');
        return;
      }
      else {
        $data['ldap_authentified'] = TRUE;
        $drupal_name = ldapauth_drupal_user_name($name, $_ldapauth_ldap, $dn);
        $data['authname_ldapauth'] = $drupal_name;
      }
    }

    // Successfull login.
    // Save the new login data.
    if (LDAPAUTH_LOGIN_PROCESS == LDAPAUTH_AUTH_MIXED && LDAPAUTH_SYNC_PASSWORDS) {
      $data['pass'] = $pass;
    }
    $user = user_save($account, $data);

    // Make sure the ldapauth_users info is current (User object may have been moved).
    $user_info = ldapauth_userinfo_load_by_uid($user->uid);
    if (empty($user_info)) {

      // Don't have entry, so make one.
      $user_info = new stdClass();
      $user_info->uid = $user->uid;
    }
    $user_info->sid = $user->ldap_config;
    $user_info->machine_name = $_ldapauth_ldap
      ->getOption('machine_name');
    $user_info->dn = $dn;
    $user_info->puid = $account->ldap_puid;

    // set in drupal_user_lookup
    ldapauth_userinfo_save($user_info);
  }
  ldapauth_debug_msg(t("authenticate: User, @user, has been authenticated as an LDAP user.", array(
    '@user' => $name,
  )));

  // Save user's authentication data to the session.
  $_SESSION['ldap_login']['dn'] = $dn;
  $_SESSION['ldap_login']['pass'] = $pass;
  user_authenticate_finalize($form_values);
  return $user;
}

/**
 * Authenticate the user against LDAP servers.
 *
 * Note: Related server information is passed via the global _ldapauth_ldap variable.
 *
 * @param $name
 *   A username.
 * @param $pass
 *   A password.
 *
 * @return
 *  User's LDAP dn success, FALSE otherwise.
 */
function _ldapauth_auth($name, $pass, $create_account = FALSE) {
  global $_ldapauth_ldap;

  // Don't allow empty passwords because they cause problems on some setups.
  // http://drupal.org/node/87831
  if (empty($pass)) {
    return FALSE;
  }

  // Cycle through LDAP configurations.  First one to succeed wins.
  $result = db_query("SELECT sid FROM {ldapauth} WHERE status = 1 ORDER BY weight");
  while ($row = db_fetch_object($result)) {

    // Initialize LDAP.
    if (!_ldapauth_init($row->sid)) {
      return FALSE;
    }

    // Look up the user in LDAP.
    if (!($ldap = _ldapauth_user_lookup($name)) || !isset($ldap['dn'])) {
      continue;
    }

    // Filter users based on their LDAP data.
    if (($code = _ldapauth_ldap_info($row->sid, 'filter_php')) && !eval($code)) {
      continue;
    }

    // Try to authenticate.
    if (!$_ldapauth_ldap
      ->connect($ldap['dn'], $pass)) {
      ldapauth_debug_msg(t("authenticate: Matching LDAP entry found, but password was not valid. sid=@sid, dn=@dn", array(
        '@dn' => $ldap['dn'],
        '@sid' => $row->sid,
      )));
      continue;
    }

    // Register this new user.  See http://drupal.org/node/553482 and http://drupal.org/node/551738
    if ($create_account) {
      $error = '';
      $account = ldapauth_drupal_user_create($_ldapauth_ldap, $name, $ldap['dn'], $error);
      if ($account === FALSE) {
        drupal_set_message(check_plain($error), 'error');
        return;
      }
    }
    return $ldap['dn'];
  }
  return FALSE;
}

/**
 * Queries LDAP server for the user.
 *
 * Note: Assumes that global $_ldapauth_ldap variable has been initialized.
 *
 * @param $name
 *   A login name.
 *
 * @return
 *   An array with user's LDAP data or NULL if not found.
 */
function _ldapauth_user_lookup($name) {
  global $_ldapauth_ldap;
  if (!$_ldapauth_ldap) {
    return;
  }

  // Transform login name.
  $login_name = ($code = _ldapauth_ldap_info($_ldapauth_ldap
    ->getOption('sid'), 'login_php')) ? eval($code) : $name;

  // If there is no bindn and bindpw - the connect will be an anonymous connect.
  $success = $_ldapauth_ldap
    ->connect($_ldapauth_ldap
    ->getOption('binddn'), $_ldapauth_ldap
    ->getOption('bindpw'));
  if (!$success) {
    watchdog('ldapauth', "Failed to connect to ldap in _ldapauth_user_lookup()", array(), WATCHDOG_ERROR);
    return;
  }
  foreach (explode("\r\n", $_ldapauth_ldap
    ->getOption('basedn')) as $base_dn) {
    if (empty($base_dn)) {
      continue;
    }
    $name_attr = $_ldapauth_ldap
      ->getOption('user_attr') ? $_ldapauth_ldap
      ->getOption('user_attr') : LDAPAUTH_DEFAULT_USER_ATTR;
    $filter = $name_attr . '=' . $login_name;
    $attrs = ldapauth_attributes_needed(LDAPAUTH_SYNC_CONTEXT_AUTHENTICATE_DRUPAL_USER, $_ldapauth_ldap
      ->getOption('sid'));
    $result = $_ldapauth_ldap
      ->search($base_dn, $filter, $attrs);
    if (!$result) {
      continue;
    }
    $num_matches = $result['count'];

    // Must find exactly one user for authentication to.
    if ($num_matches != 1) {
      watchdog('ldapauth', "Error: %num_matches users found with \$%filter under %base_dn.", array(
        '%num_matches' => $num_matches,
        '%filter' => $filter,
        '%base_dn' => $base_dn,
      ), WATCHDOG_ERROR);
      continue;
    }
    $match = $result[0];

    // These lines serve to fix the attribute name in case a
    // naughty server (i.e.: MS Active Directory) is messing the
    // characters' case.
    // This was contributed by Dan "Gribnif" Wilga, and described
    // here: http://drupal.org/node/87833
    if (!isset($match[$name_attr][0])) {
      $name_attr = drupal_strtolower($name_attr);
      if (!isset($match[$name_attr][0])) {
        continue;
      }
    }

    // Finally, we must filter out results with spaces added before
    // or after, which are considered OK by LDAP but are no good for us
    // We allow lettercase independence, as requested by Marc Galera
    // on http://drupal.org/node/97728
    //
    // Some setups have multiple $name_attr per entry, as pointed out by
    // Clarence "sparr" Risher on http://drupal.org/node/102008, so we
    // loop through all possible options.
    foreach ($match[$name_attr] as $value) {
      if (drupal_strtolower(trim($value)) == drupal_strtolower($login_name)) {
        return $match;
      }
    }
  }
}

//////////////////////////////////////////////////////////////////////////////

// Auxiliary functions

/**
 * Initiates the LDAPInterfase class.
 *
 * @param $sid
 *   An ID of the LDAP server configuration or user object.
 *
 * @return
 */
function _ldapauth_init($sid) {
  global $_ldapauth_ldap;
  if (!($sid = is_object($sid) ? isset($sid->ldap_config) ? $sid->ldap_config : NULL : $sid)) {
    return;
  }
  $server = ldapauth_server_load($sid);
  if (!empty($server) && $server->status == 1) {
    $_ldapauth_ldap = new LDAPInterface();
    $_ldapauth_ldap
      ->setOption('sid', $sid);
    $_ldapauth_ldap
      ->setOption('name', $server->name);
    $_ldapauth_ldap
      ->setOption('machine_name', $server->machine_name);
    $_ldapauth_ldap
      ->setOption('server', $server->server);
    $_ldapauth_ldap
      ->setOption('port', $server->port);
    $_ldapauth_ldap
      ->setOption('tls', $server->tls);
    $_ldapauth_ldap
      ->setOption('enc_type', $server->enc_type);
    $_ldapauth_ldap
      ->setOption('basedn', $server->basedn);
    $_ldapauth_ldap
      ->setOption('user_attr', $server->user_attr);
    $_ldapauth_ldap
      ->setOption('mail_attr', $server->mail_attr);
    $_ldapauth_ldap
      ->setOption('puid_attr', $server->puid_attr);
    $_ldapauth_ldap
      ->setOption('binary_puid', $server->binary_puid);
    $_ldapauth_ldap
      ->setOption('binddn', $server->binddn);
    $_ldapauth_ldap
      ->setOption('bindpw', $server->bindpw);
    return $_ldapauth_ldap;
  }
  return FALSE;
}

/**
 * Retrieve the saved ldapauth PhP code filters.
 *
 * @param $sid
 *   A server ID or user object.
 * @param $req
 *   The filter code needed, e.g. login_php or filter_php.
 *
 * @return
 *   The attribute value.
 */
function _ldapauth_ldap_info($sid, $req) {
  if (!($sid = is_object($sid) ? isset($sid->ldap_config) ? $sid->ldap_config : NULL : $sid)) {
    return;
  }
  $server = ldapauth_server_load($sid);
  switch ($req) {
    case 'login_php':
      return $server->login_php;
    case 'filter_php':
      return $server->filter_php;
  }
}

//////////////////////////////////////////////////////////////////////////////

// CTools/Features functions

/**
 * Implementation of hook_ctools_plugin_api().
 *
 * Tell CTools that we support the default_ldapauth_ldapservers API.
 */
function ldapauth_ctools_plugin_api($owner, $api) {
  if ($owner == 'ldapauth' && $api == 'default_ldapauth_ldapservers') {
    return array(
      'version' => 1,
    );
  }
}

/**
 * Implementation of hook_features_api().
 *
 * Defines the ldap_settings and ldap_servers feature components.
 * Note:  This defines feature support for ldapauth, ldapdata, ldapgroups and
 * ldapsync modules since they all build on ldapauth.
 */
function ldapauth_features_api() {
  $info = array(
    'ldap_servers' => array(
      'name' => 'LDAP Integration',
      'default_hook' => 'default_ldap_servers',
      'default_file' => FEATURES_DEFAULTS_INCLUDED_COMMON,
      'feature_source' => TRUE,
      'file' => drupal_get_path('module', 'ldapauth') . '/ldapauth.features.inc',
    ),
  );
  if (module_exists('strongarm')) {
    $info['ldap_settings'] = array(
      'name' => 'LDAP Integration',
      'default_hook' => 'default_ldap_settings',
      'default_file' => FEATURES_DEFAULTS_INCLUDED_COMMON,
      'feature_source' => TRUE,
      'file' => drupal_get_path('module', 'ldapauth') . '/ldapauth.features.inc',
    );
  }
  return $info;
}

/**
 * Implements hook_ldap_attributes_needed_alter
 *
 * @param Array $attributes array of attributes to be returned from ldap queries
 * @param String $op The operation being performed
 * @param Mixed $server Server sid or server object
 */
function ldapauth_ldap_attributes_needed_alter(&$attributes, $op, $server = NULL) {
  $attributes[] = 'dn';

  // DN is minimum attribute for all ops.
  if ($server) {
    $ldap_server = is_object($server) ? $server : ldapauth_server_load($server);
    switch ($op) {
      case LDAPAUTH_SYNC_CONTEXT_INSERT_DRUPAL_USER:
      case LDAPAUTH_SYNC_CONTEXT_UPDATE_DRUPAL_USER:
      case LDAPAUTH_SYNC_CONTEXT_AUTHENTICATE_DRUPAL_USER:
        $attributes[] = $ldap_server->user_attr;
        $attributes[] = $ldap_server->mail_attr;
        if (!empty($ldap_server->puid_attr)) {
          $attributes[] = $ldap_server->puid_attr;
        }
        break;
    }
  }
}

Functions

Namesort descending Description
ldapauth_authenticate Main user authentication function. Called by form validator.
ldapauth_ctools_plugin_api Implementation of hook_ctools_plugin_api().
ldapauth_exit Implements hook_exit().
ldapauth_features_api Implementation of hook_features_api().
ldapauth_form_alter Implements hook_form_alter().
ldapauth_form_user_pass_alter
ldapauth_help Implementation of hook_help().
ldapauth_init Implements hook_init().
ldapauth_ldap_attributes_needed_alter Implements hook_ldap_attributes_needed_alter
ldapauth_login_authenticate_validate Main user validation function. Replaces Drupal default login form validation.
ldapauth_menu Implements hook_menu().
ldapauth_menu_alter Implementation of hook_menu_alter().
ldapauth_perm Implements hook_perm().
ldapauth_theme Implements hook_theme().
ldapauth_user Implements hook_user().
ldapauth_user_login_final_validate
ldapauth_user_pass
_ldapauth_auth Authenticate the user against LDAP servers.
_ldapauth_init Initiates the LDAPInterfase class.
_ldapauth_ldap_info Retrieve the saved ldapauth PhP code filters.
_ldapauth_user_lookup Queries LDAP server for the user.

Constants