You are here

function ldap_authentication_test_credentials in Lightweight Directory Access Protocol (LDAP) 8.2

Same name and namespace in other branches
  1. 7.2 ldap_authentication/ldap_authentication.inc \ldap_authentication_test_credentials()
1 call to ldap_authentication_test_credentials()
_ldap_authentication_user_login_authenticate_validate in ldap_authentication/ldap_authentication.inc
user form validation will take care of username, pwd fields this function validates ldap authentication specific

File

ldap_authentication/ldap_authentication.inc, line 400
ldap_authentication helper functions

Code

function ldap_authentication_test_credentials($auth_conf, $sso_login, $authname, $password, &$watchdog_tokens) {
  $detailed_watchdog_log = config('ldap_help.settings')
    ->get('watchdog_detail');
  $authentication_result = LDAP_AUTHENTICATION_RESULT_FAIL_GENERIC;
  $ldap_user = FALSE;
  $ldap_server = NULL;
  foreach ($auth_conf->enabledAuthenticationServers as $sid => $ldap_server) {
    $watchdog_tokens['%sid'] = $sid;
    $watchdog_tokens['%bind_method'] = $ldap_server->bind_method;
    if ($detailed_watchdog_log) {
      watchdog('ldap_authentication', '%username : Trying server %sid where bind_method = %bind_method', $watchdog_tokens, WATCHDOG_DEBUG);
    }

    // #1 CONNECT TO SERVER
    $authentication_result = LDAP_AUTHENTICATION_RESULT_FAIL_GENERIC;
    $result = $ldap_server
      ->connect();
    if ($result != LDAP_SUCCESS) {
      $authentication_result = LDAP_AUTHENTICATION_RESULT_FAIL_CONNECT;
      $watchdog_tokens['%err_msg'] = $ldap_server
        ->errorMsg('ldap');
      if ($detailed_watchdog_log) {
        watchdog('ldap_authentication', '%username : Failed connecting to %sid.  Error: %err_msg', $watchdog_tokens, WATCHDOG_DEBUG);
      }
      $watchdog_tokens['%err_msg'] = NULL;
      continue;

      // next server, please
    }
    elseif ($detailed_watchdog_log) {
      watchdog('ldap_authentication', '%username : Success at connecting to %sid', $watchdog_tokens, WATCHDOG_DEBUG);
    }

    /**
      *
      LDAP_SERVERS_BIND_METHOD_SERVICE_ACCT => t('Service Account Bind.  Use credentials in following section to
      bind to ldap.  This option is usually a best practice. Service account is entered in next section.'),
    LDAP_SERVERS_BIND_METHOD_USER => t('Bind with Users Credentials.  Use users\' entered credentials
      to bind to LDAP.  This is only useful for modules that work during user logon such
      as ldap authentication and ldap authorization.  This option is not a best practice in most cases.
      The users dn must be of the form "cn=[username],[base dn]" for this option to work.'),
    LDAP_SERVERS_BIND_METHOD_ANON_USER => t('Anonymous Bind for search, then Bind with Users Credentials.
      Searches for user DN then uses users\' entered credentials to bind to LDAP.  This is only useful for
      modules that work during user logon such as ldap authentication and ldap authorization.
      The users dn must be discovered by an anonymous search for this option to work.'),
    LDAP_SERVERS_BIND_METHOD_ANON => t('Anonymous Bind. Use no credentials to bind to ldap server.
      Will not work on most ldaps.'),
    */
    $bind_success = FALSE;
    if ($ldap_server->bind_method == LDAP_SERVERS_BIND_METHOD_SERVICE_ACCT) {
      $bind_success = $ldap_server
        ->bind(NULL, NULL, FALSE) == LDAP_SUCCESS;
    }
    elseif ($ldap_server->bind_method == LDAP_SERVERS_BIND_METHOD_ANON || $ldap_server->bind_method == LDAP_SERVERS_BIND_METHOD_ANON_USER) {
      $bind_success = $ldap_server
        ->bind(NULL, NULL, TRUE) == LDAP_SUCCESS;
    }
    elseif ($sso_login) {
      watchdog('ldap_authentication', 'Trying to use SSO with LDAP_SERVERS_BIND_METHOD_USER bind method.', $watchdog_tokens, WATCHDOG_ERROR);
    }
    elseif ($ldap_server->bind_method == LDAP_SERVERS_BIND_METHOD_USER && $sso_login == FALSE) {

      // with sso enabled this method of binding isn't valid
      foreach ($ldap_server->basedn as $basedn) {
        $search = array(
          '%basedn',
          '%username',
        );
        $transformname = $ldap_server
          ->userUsernameToLdapNameTransform($authname, $watchdog_tokens);
        $replace = array(
          $basedn,
          $transformname,
        );
        $userdn = str_replace($search, $replace, $ldap_server->user_dn_expression);
        $bind_success = $ldap_server
          ->bind($userdn, $password, FALSE) == LDAP_SUCCESS;
        if ($bind_success) {
          break;
        }
      }
    }
    else {
      watchdog('ldap_authentication', 'No bind method set in ldap_server->bind_method in _ldap_authentication_user_login_authenticate_validate.', $watchdog_tokens, WATCHDOG_ERROR);
    }
    if (!$bind_success) {
      if ($detailed_watchdog_log) {
        $watchdog_tokens['%err_text'] = $ldap_server
          ->errorMsg('ldap');
        watchdog('ldap_authentication', '%username : Trying server %sid where bind_method = %bind_method.  Error: %err_text', $watchdog_tokens, WATCHDOG_DEBUG);
        $watchdog_tokens['%err_text'] = NULL;
      }
      $authentication_result = $ldap_server->bind_method == LDAP_SERVERS_BIND_METHOD_USER ? LDAP_AUTHENTICATION_RESULT_FAIL_CREDENTIALS : LDAP_AUTHENTICATION_RESULT_FAIL_BIND;
      continue;

      // if bind fails, onto next server
    }

    // #3 DOES USER EXIST IN SERVER'S LDAP
    if ($ldap_server->bind_method == LDAP_SERVERS_BIND_METHOD_ANON_USER) {
      $ldap_user = $ldap_server
        ->userUserNameToExistingLdapEntry($authname);
    }
    elseif ($sso_login) {
      $ldap_user = $ldap_server
        ->userUserNameToExistingLdapEntry($authname);
      if ($detailed_watchdog_log) {
        $watchdog_tokens['%result'] = var_export($result, TRUE);
        watchdog('ldap_authentication', '%username : attempting single sign-on
          login in bind_method of LDAP_SERVERS_BIND_METHOD_USER. Result of
          userUserNameToExistingLdapEntry: <pre>%result</pre>', $watchdog_tokens, WATCHDOG_DEBUG);
      }
    }
    else {
      $ldap_user = $ldap_server
        ->userUserNameToExistingLdapEntry($authname);
    }
    if (!$ldap_user) {
      if ($detailed_watchdog_log) {
        $watchdog_tokens['%err_text'] = $ldap_server
          ->errorMsg('ldap');
        watchdog('ldap_authentication', '%username : Trying server %sid where bind_method = %bind_method.  Error: %err_text', $watchdog_tokens, WATCHDOG_DEBUG);
        $watchdog_tokens['%err_text'] = NULL;
      }
      if ($ldap_server
        ->ldapErrorNumber()) {
        $authentication_result = LDAP_AUTHENTICATION_RESULT_FAIL_SERVER;
        break;
      }
      $authentication_result = LDAP_AUTHENTICATION_RESULT_FAIL_FIND;
      continue;

      // next server, please
    }
    $watchdog_tokens['%dn'] = $ldap_user['dn'];
    $watchdog_tokens['%mail'] = $ldap_user['mail'];

    /**
     * #4 CHECK ALLOWED AND EXCLUDED LIST AND PHP FOR ALLOWED USERS
     */
    if (!$auth_conf
      ->allowUser($authname, $ldap_user)) {
      $authentication_result = LDAP_AUTHENTICATION_RESULT_FAIL_DISALLOWED;
      break;

      // regardless of how many servers, disallowed user fails
    }

    /**
     * #5 TEST PASSWORD
     */
    $credentials_pass = FALSE;
    if ($sso_login) {

      /** If we have $sso_login passed in as true from the fake form state in
       * passed from _ldap_authentication_user_login_sso(), we will be relying
       * on the webserver for actually authenticating the user, either by NTLM
       * or user/password if configured as a fallback. Since the webserver has
       * already authenticated the user, and the web server only contains the
       * user's LDAP user name, instead of binding on the username/pass, we
       * simply look up the user's account in LDAP, and make sure it matches
       * what is contained in the global $_SERVER array populated by the web
       * server authentication.
       */
      $credentials_pass = (bool) $ldap_user;
    }
    else {
      $credentials_pass = $ldap_server
        ->bind($ldap_user['dn'], $password, FALSE) == LDAP_SUCCESS;
    }
    if (!$credentials_pass) {
      if ($detailed_watchdog_log) {
        $watchdog_tokens['%err_text'] = $ldap_server
          ->errorMsg('ldap');
        watchdog('ldap_authentication', '%username : Testing user credentials on server %sid where bind_method = %bind_method.  Error: %err_text', $watchdog_tokens, WATCHDOG_DEBUG);
        $watchdog_tokens['%err_text'] = NULL;
      }
      $authentication_result = LDAP_AUTHENTICATION_RESULT_FAIL_CREDENTIALS;
      continue;

      // next server, please
    }
    else {
      $authentication_result = LDAP_AUTHENTICATION_RESULT_SUCCESS;
      if ($ldap_server->bind_method == LDAP_SERVERS_BIND_METHOD_ANON_USER) {
        $ldap_user = $ldap_server
          ->userUserNameToExistingLdapEntry($authname);

        // after successful bind, lookup user again to get private attributes
        $watchdog_tokens['%mail'] = $ldap_user['mail'];
      }
      if ($ldap_server->bind_method == LDAP_SERVERS_BIND_METHOD_SERVICE_ACCT || $ldap_server->bind_method == LDAP_SERVERS_BIND_METHOD_ANON_USER) {
        $ldap_server
          ->disconnect();
      }
      break;

      //success
    }
  }

  // end loop through servers
  $watchdog_tokens['%result'] = $result;
  $watchdog_tokens['%auth_result'] = $authentication_result;
  $watchdog_tokens['%err_text'] = _ldap_authentication_err_text($authentication_result);
  if ($detailed_watchdog_log) {
    watchdog('ldap_authentication', '%username : Authentication result id=%result auth_result=%auth_result (%err_text)', $watchdog_tokens, WATCHDOG_DEBUG);
  }
  return array(
    $authentication_result,
    $ldap_user,
    $ldap_server,
  );
}