You are here

ldap_authentication.module in Lightweight Directory Access Protocol (LDAP) 7.2

This module injects itself into Drupal's Authentication stack.

File

ldap_authentication/ldap_authentication.module
View source
<?php

/**
 * @file
 * This module injects itself into Drupal's Authentication stack.
 */

/**
 * @todo fix advanced help for ../ldap/authentication settings page
 */
define('LDAP_AUTHENTICATION_PROJECT_TAG', 'ldap');
define('LDAP_AUTHENTICATION_MIXED', 1);
define('LDAP_AUTHENTICATION_EXCLUSIVE', 2);
define('LDAP_AUTHENTICATION_MODE_DEFAULT', 1);
define('LDAP_AUTHENTICATION_EXCL_IF_NO_AUTHZ_DEFAULT', 0);
define('LDAP_AUTHENTICATION_CONFLICT_LOG', 1);
define('LDAP_AUTHENTICATION_CONFLICT_RESOLVE', 2);
define('LDAP_AUTHENTICATION_CONFLICT_RESOLVE_DEFAULT', 2);
define('LDAP_AUTHENTICATION_EMAIL_UPDATE_ON_LDAP_CHANGE_ENABLE_NOTIFY', 1);
define('LDAP_AUTHENTICATION_EMAIL_UPDATE_ON_LDAP_CHANGE_ENABLE', 2);
define('LDAP_AUTHENTICATION_EMAIL_UPDATE_ON_LDAP_CHANGE_DISABLE', 3);
define('LDAP_AUTHENTICATION_EMAIL_UPDATE_ON_LDAP_CHANGE_DEFAULT', 1);
define('LDAP_AUTHENTICATION_EMAIL_FIELD_REMOVE', 2);
define('LDAP_AUTHENTICATION_EMAIL_FIELD_DISABLE', 3);
define('LDAP_AUTHENTICATION_EMAIL_FIELD_ALLOW', 4);
define('LDAP_AUTHENTICATION_EMAIL_FIELD_DEFAULT', 3);
define('LDAP_AUTHENTICATION_EMAIL_TEMPLATE_NONE', 1);
define('LDAP_AUTHENTICATION_EMAIL_TEMPLATE_ALWAYS', 2);
define('LDAP_AUTHENTICATION_EMAIL_TEMPLATE_IF_EMPTY', 3);
define('LDAP_AUTHENTICATION_EMAIL_TEMPLATE_DEFAULT', 3);
define('LDAP_AUTHENTICATION_DEFAULT_TEMPLATE', '@username@fake-domain.com');
define('LDAP_AUTHENTICATION_DEFAULT_TEMPLATE_REGEX', '.*@fake-domain\\.com');
define('LDAP_AUTHENTICATION_TEMPLATE_USAGE_NEVER_UPDATE_DEFAULT', 0);
define('LDAP_AUTHENTICATION_TEMPLATE_USAGE_RESOLVE_CONFLICT_DEFAULT', 0);
define('LDAP_AUTHENTICATION_TEMPLATE_USAGE_PROMPT_USER_DEFAULT', 0);
define('LDAP_AUTHENTICATION_PASSWORD_FIELD_SHOW', 2);
define('LDAP_AUTHENTICATION_PASSWORD_FIELD_HIDE', 3);
define('LDAP_AUTHENTICATION_PASSWORD_FIELD_ALLOW', 4);
define('LDAP_AUTHENTICATION_PASSWORD_FIELD_DEFAULT', 2);
define('LDAP_AUTHENTICATION_RESULT_FAIL_CONNECT', 1);
define('LDAP_AUTHENTICATION_RESULT_FAIL_BIND', 2);
define('LDAP_AUTHENTICATION_RESULT_FAIL_FIND', 3);
define('LDAP_AUTHENTICATION_RESULT_FAIL_DISALLOWED', 4);
define('LDAP_AUTHENTICATION_RESULT_FAIL_CREDENTIALS', 5);
define('LDAP_AUTHENTICATION_RESULT_SUCCESS', 6);
define('LDAP_AUTHENTICATION_RESULT_FAIL_GENERIC', 7);
define('LDAP_AUTHENTICATION_RESULT_FAIL_SERVER', 8);
define('LDAP_AUTHENTICATION_ACCT_CREATION_DEFAULT', 4);
define('LDAP_AUTHENTICATION_ACCT_CREATION_USER_SETTINGS_FOR_LDAP', 1);
define('LDAP_AUTHENTICATION_ACCT_CREATION_LDAP_BEHAVIOR', 4);
define('LDAP_AUTHENTICATION_HELP_LINK_TEXT_DEFAULT', 'Logon Help');
define('LDAP_AUTHENTICATION_DISABLED_FOR_BAD_CONF_MSG', 'The site logon is currently not working due to a configuration error.  Please see logs for additional details.');
define('LDAP_AUTHENTICATION_COOKIE_EXPIRE', 0);
define('LDAP_AUTHENTICATION_REDIRECT_ON_LOGIN_DEFAULT', 0);

/**
 * Implements hook_menu().
 */
function ldap_authentication_menu() {
  $items = [];
  $items['user/ldap-profile-update'] = [
    'title' => 'Update Profile',
    'page callback' => 'drupal_get_form',
    'page arguments' => [
      'ldap_authentication_profile_update_form',
    ],
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
    'file' => 'ldap_authentication.pages.inc',
  ];
  $items['admin/config/people/ldap/authentication'] = [
    'title' => 'Authentication',
    'description' => 'Configure LDAP Authentication',
    'page callback' => 'drupal_get_form',
    'page arguments' => [
      'ldap_authentication_admin_form',
    ],
    'access arguments' => [
      'administer site configuration',
    ],
    'type' => MENU_LOCAL_TASK,
    'weight' => 3,
    'file' => 'ldap_authentication.admin.inc',
  ];
  return $items;
}

/**
 * Implements hook_menu_alter().
 * since menu items are cached, only useful to add or alter callbacks
 * for ldap authentication driven menu items.
 */
function ldap_authentication_menu_alter(&$items) {
  ldap_servers_module_load_include('inc', 'ldap_authentication', 'ldap_authentication');
  $items['user/password']['access callback'] = 'ldap_authentication_show_reset_pwd';
  $auth_conf = ldap_authentication_get_valid_conf();
  if (@$auth_conf->ldapUserHelpLinkUrl) {
    $items['user/ldaphelp'] = [
      'title' => $auth_conf->ldapUserHelpLinkText,
      'page callback' => 'drupal_goto',
      'page arguments' => [
        $auth_conf->ldapUserHelpLinkUrl,
      ],
      'access callback' => 'ldap_authentication_show_ldap_help_link',
      'type' => MENU_LOCAL_TASK,
    ];
  }
}

/**
 * Implements hook_theme().
 */
function ldap_authentication_theme() {
  return [
    'ldap_authentication_user_login_block_links' => [
      'variables' => [
        'ldap_user_help_link' => NULL,
        'user_register' => TRUE,
      ],
      'render element' => 'element',
      'file' => 'ldap_authentication.theme.inc',
    ],
    'ldap_authentication_user_pass_message' => [
      'variables' => [
        'show_reset_pwd' => NULL,
        'auth_conf' => TRUE,
      ],
      'render element' => 'element',
      'file' => 'ldap_authentication.theme.inc',
    ],
    'ldap_authentication_user_pass_validate_ldap_authenticated' => [
      'variables' => [
        'account' => NULL,
        'auth_conf' => TRUE,
      ],
      'render element' => 'element',
      'file' => 'ldap_authentication.theme.inc',
    ],
    'ldap_authentication_login_message' => [
      'render element' => 'element',
      'variables' => [
        'message' => NULL,
      ],
      'file' => 'ldap_authentication.theme.inc',
    ],
    'ldap_authentication_message_not_found' => [
      'render element' => 'element',
      'variables' => [
        'message' => NULL,
      ],
      'file' => 'ldap_authentication.theme.inc',
    ],
    'ldap_authentication_message_not_authenticated' => [
      'render element' => 'element',
      'variables' => [
        'message' => NULL,
      ],
      'file' => 'ldap_authentication.theme.inc',
    ],
  ];
}

/**
 * Implements hook_help().
 */
function ldap_authentication_help($path, $arg) {
  $authentication_help = t('LDAP authentication allows authentication against an LDAP server.  It
        may be used alongside other authentication means such as built in Drupal authentication,
        open id, etc.  More detailed help is available on drupal.org at !helplink.', [
    '!helplink' => l(LDAP_SERVERS_DRUPAL_HELP_URL, LDAP_SERVERS_DRUPAL_HELP_URL),
  ]);
  switch ($path) {
    case 'admin/config/people/ldap/authentication':
      $output = '<p>' . $authentication_help . '</p>';
      return $output;
    case 'admin/help#ldap_authentication':
      $output = '<p>' . $authentication_help . '</p>';
      return $output;
  }
}

/**
 * Helper function that determines whether or not the user's profile
 * is valid or needs to be updated on login.
 *
 * Currently this only checks if mail is valid or not according to the
 * authentication settings.
 *
 * @return bool
 *   TRUE if the user's profile is valid, otherwise FALSE.
 */
function _ldap_authentication_verify_user_profile() {
  global $user;
  $result = TRUE;

  // We only want non-anonymous and non-1 users.
  if ($user->uid > 1) {

    // We store the value in the session for speed.
    if (isset($_SESSION['ldap_authentication_template']) && isset($_SESSION['ldap_authentication_template']['verify_user_profile'])) {
      return $_SESSION['ldap_authentication_template']['verify_user_profile'];
    }
    if (ldap_authentication_ldap_authenticated($user)) {
      $auth_conf = ldap_authentication_get_valid_conf();
      $regex = '`' . $auth_conf->templateUsagePromptRegex . '`i';
      if (preg_match($regex, $user->mail)) {
        $result = FALSE;
      }
      $_SESSION['ldap_authentication_template'] = [
        'verify_user_profile' => $result,
      ];
    }
  }
  return $result;
}

/**
 * Implements hook_init().
 */
function ldap_authentication_init() {
  $auth_conf = ldap_authentication_get_valid_conf();
  if ($auth_conf && $auth_conf->templateUsagePromptUser) {
    ldap_authentication_check_for_email_template();
  }
}

/**
 * Form submit callback to check for an email template and redirect if needed.
 */
function ldap_authentication_check_for_email_template() {
  if (!_ldap_authentication_verify_user_profile()) {
    $url = 'user/ldap-profile-update';
    $cp = current_path();

    // Avoid redirects on these two pages.
    if ($cp != $url && $cp != 'user/logout') {
      if (isset($_GET['destination'])) {
        unset($_GET['destination']);
      }
      drupal_goto($url, [
        'query' => [
          'next' => current_path(),
        ],
      ]);
    }
  }
}

/**
 * Implements hook_info().
 */
function ldap_authentication_info($field = 0) {
  $info['name'] = 'ldap_authentication';
  $info['protocol'] = 'LDAP';
  if ($field) {
    return $info[$field];
  }
  return $info;
}

/**
 * Determines if the passed user has a valid authmap record.
 *
 * @param object $user
 *   A drupal user account.
 *
 * @return bool
 *   true if user is recorded as ldap authenticated and identified (ldap_authentified)
 */
function ldap_authentication_ldap_authenticated($user) {
  if (!is_object($user) || $user->uid == 0) {
    return FALSE;
  }
  $authname = ldap_user_get_authname($user);
  return !empty($authname);
}

/**
 * A user access callback for using the single sign-on URL, denying access to
 * authenticated users, and granting access to anonymous users and menu
 * administrators viewing the menu item.
 */
function _ldap_authentication_user_access() {
  return (bool) (!$GLOBALS['user']->uid || !empty($GLOBALS['menu_admin']));
}

/**
 * Get LdapAuthenticationConf object.
 *
 * @return object LdapAuthenticationConf object if configured, otherwise FALSE
 */
function ldap_authentication_get_valid_conf($reset = FALSE) {
  static $auth_conf;
  if (!$reset && is_object($auth_conf)) {
    return $auth_conf;
  }
  ldap_servers_module_load_include('php', 'ldap_authentication', 'LdapAuthenticationConf.class');
  $auth_conf = new LdapAuthenticationConf();
  return $auth_conf->inDatabase ? $auth_conf : FALSE;
}

/**
 * Implements hook_ldap_ldap_server_in_use().
 */
function ldap_authentication_ldap_server_in_use($sid, $server_name) {
  $use_warnings = [];
  $auth_conf = ldap_authentication_get_valid_conf();
  if ($auth_conf && in_array($sid, array_keys($auth_conf->sids)) && !empty($auth_conf->sids[$sid])) {
    $use_warnings[] = t('This server (%server_name) may not be deleted or
      disabled because it is being used for ldap authentication.', [
      '%server_name' => $server_name,
    ]);
  }
  return $use_warnings;
}

/**
 *
 */
function ldap_authentication_show_reset_pwd($user = NULL) {
  if (!$user) {
    global $user;
  }
  $auth_conf = ldap_authentication_get_valid_conf();

  // Hide user/password form if ldap authentication is required and deny access
  // to users without ldap authorizations is enabled.
  if ($user->uid == 1 || !$auth_conf || current_path() == 'user/password' && $auth_conf->authenticationMode != LDAP_AUTHENTICATION_EXCLUSIVE) {
    return TRUE;

    // Always show at user/passwordurl. otherwise user 1 will not be able to reset password.
  }
  if ($user->uid == 0) {

    // Hide reset password for anonymous users if ldap only authentication and password updates are disabled, otherwise show.
    if ($auth_conf->authenticationMode == LDAP_AUTHENTICATION_EXCLUSIVE) {
      if ($auth_conf->passwordOption == LDAP_AUTHENTICATION_PASSWORD_FIELD_ALLOW) {
        return TRUE;
      }
      return FALSE;
    }
    return TRUE;
  }
  else {

    // Authenticated user.  hide if ldap authenticated and updating password is
    // not allowed, otherwise show.
    if (ldap_authentication_ldap_authenticated($user)) {
      if ($auth_conf->passwordOption == LDAP_AUTHENTICATION_PASSWORD_FIELD_ALLOW) {
        return TRUE;
      }
      return FALSE;
    }
    return TRUE;
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function ldap_authentication_form_user_pass_alter(&$form, $form_state) {

  // The following could be in a theme preproces function.
  $auth_conf = ldap_authentication_get_valid_conf();
  $form['ldap_warning'] = [
    '#type' => 'item',
    '#markup' => theme('ldap_authentication_user_pass_message', [
      'auth_conf' => $auth_conf,
    ]),
    '#weight' => 10,
  ];

  // Need to insert before user_pass_validate.
  array_unshift($form['#validate'], 'ldap_authentication_user_pass_validate');
}

/**
 * A validate handler on the login form. Check supplied username/password
 * against local users table. If successful, $form_state['uid']
 * is set to the matching user ID.
 */
function ldap_authentication_core_override_user_login_authenticate_validate($form, &$form_state) {

  // No additional validation of user credentials is needed when
  // $form_state['uid'] is set.
  if (!empty($form_state['uid'])) {
    return;
  }
  user_login_authenticate_validate($form, $form_state);
}

/**
 *
 */
function ldap_authentication_user_pass_validate(&$form_state) {
  $name_or_mail = trim($form_state['name']['#value']);
  if ($account = user_load_by_mail($name_or_mail)) {
  }
  else {
    $account = user_load_by_name($name_or_mail);
  }
  if (ldap_authentication_ldap_authenticated($account)) {
    $vars = [
      'account' => $account,
      'auth_conf' => ldap_authentication_get_valid_conf(),
    ];
    $error = TRUE;
    if (is_object($vars['auth_conf'])) {
      if ($vars['auth_conf']->passwordOption == LDAP_AUTHENTICATION_PASSWORD_FIELD_ALLOW) {
        $error = FALSE;
      }
    }
    if (!empty($error)) {
      form_set_error('name', theme('ldap_authentication_user_pass_validate_ldap_authenticated', $vars));
    }
  }
}

/**
 * Implements hook_form_FORM_ID_alter(). for user_profile_form.
 */
function ldap_authentication_form_user_profile_form_alter(&$form, $form_state) {
  ldap_servers_module_load_include('inc', 'ldap_authentication', 'ldap_authentication');
  _ldap_authentication_form_user_profile_form_alter($form, $form_state, 'user_login');
}

/**
 * Implements hook_form_FORM_ID_alter(). for user_login.
 */
function ldap_authentication_form_user_login_alter(&$form, &$form_state) {
  ldap_servers_module_load_include('inc', 'ldap_authentication', 'ldap_authentication');
  _ldap_authentication_login_form_alter($form, $form_state, 'user_login');
}

/**
 * Implements hook_form_FORM_ID_alter(). for user_login_block.
 */
function ldap_authentication_form_user_login_block_alter(&$form, &$form_state) {
  ldap_servers_module_load_include('inc', 'ldap_authentication', 'ldap_authentication');
  _ldap_authentication_login_form_alter($form, $form_state, 'user_login_block');
}

/**
 * Validate function for user logon forms.
 */
function ldap_authentication_user_login_authenticate_validate($form, &$form_state, $return_user = FALSE) {
  ldap_servers_module_load_include('inc', 'ldap_authentication', 'ldap_authentication');
  return _ldap_authentication_user_login_authenticate_validate($form_state, $return_user);
}

/**
 * Implements hook_user_presave().
 *  A user account is about to be created or updated.
 */
function ldap_authentication_user_presave(&$edit, $account, $category = NULL) {
}

/**
 * Implements hook_user_insert().
 *
 * A user account was created.
 * The module should save its custom additions to the user object into the database.
 */
function ldap_authentication_user_insert(&$edit, $account, $category) {
}

/**
 * Implements hook_user_update().
 *
 *  A user account was updated.
 *  Modules may use this hook to update their user data in a custom storage after a user account has been updated.
 */
function ldap_authentication_user_update($edit, $user, $category) {
}

/**
 *
 */
function ldap_authentication_show_ldap_help_link($user = NULL) {
  global $user;
  if (!($auth_conf = ldap_authentication_get_valid_conf())) {
    return FALSE;
  }
  elseif ($auth_conf->authenticationMode == LDAP_AUTHENTICATION_MIXED) {
    return ldap_authentication_ldap_authenticated($user);
  }
  elseif ($auth_conf->authenticationMode == LDAP_AUTHENTICATION_EXCLUSIVE) {
    if ($user->uid == 0 || ldap_authentication_ldap_authenticated($user)) {
      return TRUE;
    }
    else {
      return FALSE;
    }
  }
}

Functions

Namesort descending Description
ldap_authentication_check_for_email_template Form submit callback to check for an email template and redirect if needed.
ldap_authentication_core_override_user_login_authenticate_validate A validate handler on the login form. Check supplied username/password against local users table. If successful, $form_state['uid'] is set to the matching user ID.
ldap_authentication_form_user_login_alter Implements hook_form_FORM_ID_alter(). for user_login.
ldap_authentication_form_user_login_block_alter Implements hook_form_FORM_ID_alter(). for user_login_block.
ldap_authentication_form_user_pass_alter Implements hook_form_FORM_ID_alter().
ldap_authentication_form_user_profile_form_alter Implements hook_form_FORM_ID_alter(). for user_profile_form.
ldap_authentication_get_valid_conf Get LdapAuthenticationConf object.
ldap_authentication_help Implements hook_help().
ldap_authentication_info Implements hook_info().
ldap_authentication_init Implements hook_init().
ldap_authentication_ldap_authenticated Determines if the passed user has a valid authmap record.
ldap_authentication_ldap_server_in_use Implements hook_ldap_ldap_server_in_use().
ldap_authentication_menu Implements hook_menu().
ldap_authentication_menu_alter Implements hook_menu_alter(). since menu items are cached, only useful to add or alter callbacks for ldap authentication driven menu items.
ldap_authentication_show_ldap_help_link
ldap_authentication_show_reset_pwd
ldap_authentication_theme Implements hook_theme().
ldap_authentication_user_insert Implements hook_user_insert().
ldap_authentication_user_login_authenticate_validate Validate function for user logon forms.
ldap_authentication_user_pass_validate
ldap_authentication_user_presave Implements hook_user_presave(). A user account is about to be created or updated.
ldap_authentication_user_update Implements hook_user_update().
_ldap_authentication_user_access A user access callback for using the single sign-on URL, denying access to authenticated users, and granting access to anonymous users and menu administrators viewing the menu item.
_ldap_authentication_verify_user_profile Helper function that determines whether or not the user's profile is valid or needs to be updated on login.

Constants

Namesort descending Description
LDAP_AUTHENTICATION_ACCT_CREATION_DEFAULT
LDAP_AUTHENTICATION_ACCT_CREATION_LDAP_BEHAVIOR
LDAP_AUTHENTICATION_ACCT_CREATION_USER_SETTINGS_FOR_LDAP
LDAP_AUTHENTICATION_CONFLICT_LOG
LDAP_AUTHENTICATION_CONFLICT_RESOLVE
LDAP_AUTHENTICATION_CONFLICT_RESOLVE_DEFAULT
LDAP_AUTHENTICATION_COOKIE_EXPIRE
LDAP_AUTHENTICATION_DEFAULT_TEMPLATE
LDAP_AUTHENTICATION_DEFAULT_TEMPLATE_REGEX
LDAP_AUTHENTICATION_DISABLED_FOR_BAD_CONF_MSG
LDAP_AUTHENTICATION_EMAIL_FIELD_ALLOW
LDAP_AUTHENTICATION_EMAIL_FIELD_DEFAULT
LDAP_AUTHENTICATION_EMAIL_FIELD_DISABLE
LDAP_AUTHENTICATION_EMAIL_FIELD_REMOVE
LDAP_AUTHENTICATION_EMAIL_TEMPLATE_ALWAYS
LDAP_AUTHENTICATION_EMAIL_TEMPLATE_DEFAULT
LDAP_AUTHENTICATION_EMAIL_TEMPLATE_IF_EMPTY
LDAP_AUTHENTICATION_EMAIL_TEMPLATE_NONE
LDAP_AUTHENTICATION_EMAIL_UPDATE_ON_LDAP_CHANGE_DEFAULT
LDAP_AUTHENTICATION_EMAIL_UPDATE_ON_LDAP_CHANGE_DISABLE
LDAP_AUTHENTICATION_EMAIL_UPDATE_ON_LDAP_CHANGE_ENABLE
LDAP_AUTHENTICATION_EMAIL_UPDATE_ON_LDAP_CHANGE_ENABLE_NOTIFY
LDAP_AUTHENTICATION_EXCLUSIVE
LDAP_AUTHENTICATION_EXCL_IF_NO_AUTHZ_DEFAULT
LDAP_AUTHENTICATION_HELP_LINK_TEXT_DEFAULT
LDAP_AUTHENTICATION_MIXED
LDAP_AUTHENTICATION_MODE_DEFAULT
LDAP_AUTHENTICATION_PASSWORD_FIELD_ALLOW
LDAP_AUTHENTICATION_PASSWORD_FIELD_DEFAULT
LDAP_AUTHENTICATION_PASSWORD_FIELD_HIDE
LDAP_AUTHENTICATION_PASSWORD_FIELD_SHOW
LDAP_AUTHENTICATION_PROJECT_TAG @todo fix advanced help for ../ldap/authentication settings page
LDAP_AUTHENTICATION_REDIRECT_ON_LOGIN_DEFAULT
LDAP_AUTHENTICATION_RESULT_FAIL_BIND
LDAP_AUTHENTICATION_RESULT_FAIL_CONNECT
LDAP_AUTHENTICATION_RESULT_FAIL_CREDENTIALS
LDAP_AUTHENTICATION_RESULT_FAIL_DISALLOWED
LDAP_AUTHENTICATION_RESULT_FAIL_FIND
LDAP_AUTHENTICATION_RESULT_FAIL_GENERIC
LDAP_AUTHENTICATION_RESULT_FAIL_SERVER
LDAP_AUTHENTICATION_RESULT_SUCCESS
LDAP_AUTHENTICATION_TEMPLATE_USAGE_NEVER_UPDATE_DEFAULT
LDAP_AUTHENTICATION_TEMPLATE_USAGE_PROMPT_USER_DEFAULT
LDAP_AUTHENTICATION_TEMPLATE_USAGE_RESOLVE_CONFLICT_DEFAULT