You are here

ldaphelp.module in LDAP integration 6

The ldaphelp module is a module to help admins debug ldap_integration modules.

File

ldaphelp/ldaphelp.module
View source
<?php

/**
 * @file
 * The ldaphelp module is a module to help admins debug ldap_integration modules.
 *
 */
global $_ldaphelp_ldaps;
$default_fields['server-settings']['port'] = 389;
$default_fields['server-settings']['tls'] = 1;
$default_fields['server-settings']['encrypted'] = 0;
$default_fields['login-procedure']['user_attr'] = 'uid';
$default_fields['login-procedure']['mail_attr'] = 'mail';

// http://msdn.microsoft.com/en-us/library/aa705886(VS.85).aspx
$_ldaphelp_ldaps['ad']['name'] = t('Active Directory LDAP');
$_ldaphelp_ldaps['ad']['description'] = t('Microsoft Active Directory');
$_ldaphelp_ldaps['ad']['fields'] = $default_fields;
$_ldaphelp_ldaps['ad']['fields']['login-procedure']['user_attr'] = 'sAMAccountName';
$_ldaphelp_ldaps['ad']['person_object_class'] = 'person';
$_ldaphelp_ldaps['ad']['fingerprint_attribute'] = 'mS-DS-CreatorSID';

// http://www.novell.com/documentation/edir873/index.html?page=/documentation/edir873/edir873/data/h0000007.html
$_ldaphelp_ldaps['novell_edir']['name'] = t('Novell eDirectory');
$_ldaphelp_ldaps['novell_edir']['description'] = t('Novell eDirectory LDAP');
$_ldaphelp_ldaps['novell_edir']['fields'] = $default_fields;
$_ldaphelp_ldaps['novell_edir']['person_object_class'] = 'person';
$_ldaphelp_ldaps['openldap']['name'] = t('openLDAP');
$_ldaphelp_ldaps['openldap']['description'] = t('openLDAP default configuration');
$_ldaphelp_ldaps['openldap']['fields'] = $default_fields;
$_ldaphelp_ldaps['openldap']['fields']['login-procedure']['user_attr'] = 'cn';
$_ldaphelp_ldaps['openldap']['person_object_class'] = 'person';

// http://images.apple.com/server/macosx/docs/Open_Directory_Admin_v10.5_3rd_Ed.pdf
$_ldaphelp_ldaps['macosxldap']['name'] = t('Mac OS X Server LDAP');
$_ldaphelp_ldaps['macosxldap']['description'] = t('A variation on OpenLDAP');
$_ldaphelp_ldaps['macosxldap']['fields'] = $default_fields;
$_ldaphelp_ldaps['macosxldap']['fields']['login-procedure']['user_attr'] = 'uid';
$_ldaphelp_ldaps['macosxldap']['person_object_class'] = 'person';
$_ldaphelp_ldaps['macosxldap']['fingerprint_attribute'] = 'apple-generateduid';

/**
 * Implementation of hook_init().
 */
function ldaphelp_init() {
  module_load_include('inc', 'ldapauth', 'ldapauth.admin');
  module_load_include('inc', 'ldapauth', 'includes/ldap.core');
  module_load_include('inc', 'ldapauth', 'includes/LDAPInterface');
  drupal_add_css(drupal_get_path('module', 'ldaphelp') . '/ldaphelp.css', 'module');
}

/**
 * Implementation of hook_menu().
 */
function ldaphelp_menu() {
  $items = array();
  $items['admin/settings/ldap/help'] = array(
    'title' => 'LDAP Help',
    'description' => 'Debugging and Configuration Help with LDAP',
    'page callback' => 'ldaphelp_main',
    'access arguments' => array(
      'administer ldap modules',
    ),
  );
  $items['admin/settings/ldap/help/resources'] = array(
    'title' => 'Resources',
    'description' => 'Some help resources for LDAP modules',
    'page callback' => 'ldaphelp_main',
    'access arguments' => array(
      'administer ldap modules',
    ),
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => 2,
  );
  $items['admin/settings/ldap/help/status'] = array(
    'title' => 'Status',
    'description' => 'LDAP status page',
    'page callback' => 'ldaphelp_status',
    'access arguments' => array(
      'administer ldap modules',
    ),
    'file' => 'ldaphelp_status.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 4,
  );
  $items['admin/settings/ldap/help/watchdog'] = array(
    'title' => 'Watchdog',
    'description' => 'LDAP watchdog logs',
    'page callback' => 'ldaphelp_watchdog_list',
    'access arguments' => array(
      'administer ldap modules',
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 5,
  );
  $items['admin/settings/ldap/help/addcommon'] = array(
    'title' => 'Common LDAPs',
    'description' => 'Add a new LDAP starting with common defaults such as Active Directory defaults.',
    'page callback' => 'ldaphelp_addcommon',
    'access arguments' => array(
      'administer ldap modules',
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 7,
  );
  $items['admin/settings/ldap/help/wizard'] = array(
    'title' => 'Wizard',
    'description' => 'A multi step form to help figure out LDAP server configuration.',
    'access arguments' => array(
      'administer ldap modules',
    ),
    'file' => 'ldaphelp_wizard.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 13,
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'ldaphelp_wizard_form',
    ),
  );
  $items['admin/settings/ldap/help/users'] = array(
    'title' => 'User Info',
    'description' => 'Some ways to list LDAP user information.',
    'access arguments' => array(
      'administer ldap modules',
    ),
    //    'file' => 'ldaphelp_wizard.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 20,
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'ldaphelp_users',
    ),
  );
  $items['admin/settings/ldap/help/users/list'] = array(
    'title' => 'User Info',
    'description' => 'Some ways to list LDAP user information.',
    'access arguments' => array(
      'administer ldap modules',
    ),
    //    'file' => 'ldaphelp_wizard.inc',
    //    'type' => MENU_LOCAL_TASK,
    'weight' => 20,
    'page callback' => 'ldaphelp_users_list',
  );
  return $items;
}
function _ldaphelp_bind_test($ldapserver) {
  global $_ldapauth_ldap;
  $test = array();
  $_ldapauth_ldap = new LDAPInterface();
  foreach ($ldapserver as $key => $value) {
    $_ldapauth_ldap
      ->setOption($key, $value);
  }
  if ($_ldapauth_ldap
    ->getOption('binddn') && $_ldapauth_ldap
    ->getOption('bindpw')) {
    $test['bind_result'] = $_ldapauth_ldap
      ->connectAndBind($_ldapauth_ldap
      ->getOption('binddn'), $_ldapauth_ldap
      ->getOption('bindpw'));
    $test['bind_type'] = "non-anon";
  }
  else {
    $test['bind_result'] = $_ldapauth_ldap
      ->connectAndBind();
    $test['bind_type'] = "anon";
  }
  if ($test['bind_result']) {
    $test['bind_result_text'] = "Success";
    $test['bind_success'] = TRUE;
  }
  else {
    $test['bind_result_error'] = ldap_error($_ldapauth_ldap->connection);
    $test['bind_result_errno'] = ldap_errno($_ldapauth_ldap->connection);
    $test['bind_result_text'] = "Fail";
    $test['bind_success'] = FALSE;
  }
  return $test;
}
function ldaphelp_bind_trial_message($trial) {
  $tls = $trial['tls'] ? "1" : "0";
  $text = "Failed to bind to server: " . $trial['server'] . ", port=" . $trial['port'] . ", tls={$tls} <br/>";
  $text .= "error: " . $trial['results']['bind_result_error'];
  return $text;
}
function ldaphelp_addcommon() {
  if (!module_exists('ldapauth')) {
    drupal_set_message(t('Links below will not work until ldapauth module is not enabled.'), 'warning');
  }
  global $_ldaphelp_ldaps;
  $content = '<h3>' . t('LDAP Integration Default LDAPs') . '</h3>';
  $content .= '<p>' . t('These links simply start an Add LDAP Server form with some common defaults.') . '</p>';
  $content .= '<ul>';
  foreach ($_ldaphelp_ldaps as $ldap_type => $default_data) {
    $content .= "<li>" . l($default_data['name'] . ' ' . t('Common Settings:'), 'admin/settings/ldap/ldapauth/add/' . $ldap_type) . "<br/><code>";
    $content .= ldaphelp_display_settings_short($_ldaphelp_ldaps[$ldap_type]['fields']);
    $content .= "</code></li>";
  }
  $content .= "</ul>";
  return $content;
}
function ldaphelp_form_ldapauth_admin_form_alter(&$form, $form_state) {
  global $_ldaphelp_ldaps;
  if (in_array(arg(4), array_keys($_ldaphelp_ldaps))) {
    $ldap_type = arg(4);
    foreach ($_ldaphelp_ldaps[$ldap_type]['fields'] as $fieldset => $pairs) {
      foreach ($pairs as $fieldname => $value) {
        $form[$fieldset][$fieldname]['#default_value'] = $value;
      }
    }
  }

  // don't hide/collapse login fieldset if data in it.
  if ($form['login-procedure']['basedn']['#default_value'] || $form['login-procedure']['user_attr']['#default_value'] || $form['login-procedure']['mail_attr']['#default_value']) {
    $form['login-procedure']['#collapsed'] = FALSE;
  }
}

/**
 * Get config information for general config and each ldap server defined.
 *
 * @param boolean $admin_settings
 * @param array $sids Array of server ids to look up, NULL means all.
 */
function _ldaphelp_get_configuration($admin_settings = TRUE, $sids = NULL) {
  if ($admin_settings) {
    $form = ldapauth_admin_settings();
    $data['admin_settings'] = _ldaphelp_get_form_values($form);
  }
  $data['ldaps'] = array();

  //TODO: This won't work with an array of sids!!!!
  if (!(is_array($sids) && count($sids) == 0)) {
    if ($sids == NULL) {
      $result = db_query("SELECT sid FROM {ldapauth} ORDER BY name");
      while ($row = db_fetch_object($result)) {
        $sids[] = $row->sid;
      }
    }
    if (count($sids) > 0) {
      foreach ($sids as $sid) {
        $form = ldapauth_admin_form($form_state, 'edit', $sid);
        $data['ldaps'][$sid] = _ldaphelp_get_form_values($form);
        unset($data['ldaps'][$sid]['bindpw_clear']);
      }
    }
  }
  return $data;
}
function _ldaphelp_get_form_values(&$form) {
  $values = array();
  foreach ($form as $key => $item) {
    if ($form[$key]['#type'] == 'fieldset') {
      foreach ($form[$key] as $subskey => $subitem) {
        if (drupal_substr($subskey, 0, 1) != '#') {
          $values[$subskey] = $subitem['#value'] ? $subitem['#value'] : $subitem['#default_value'];
        }
      }
    }
    elseif (drupal_substr($key, 0, 1) != '#' && $key != 'submit' && $key != 'reset') {
      $values[$key] = $item['#value'] ? $item['#value'] : $item['#default_value'];
    }
  }
  return $values;
}
function ldaphelp_display_settings_short($ldap) {
  foreach ($ldap as $fieldset => $pairs) {
    foreach ($ldap[$fieldset] as $fieldname => $value) {
      $ret .= "{$fieldname} = {$value}; ";
    }
  }
  return $ret;
}
function ldaphelp_arraytohtmllist($array) {
  foreach ($array as $key => $value) {
    $text .= "<li>{$key}: {$value}</li>\r\n";
  }
  return "<ul>{$text}</ul>";
}
function ldaphelp_arraytohtml($array) {
  foreach ($array as $key => $value) {
    $text .= "<br/>{$key}: {$value}";
  }
  return $text;
}
function ldaphelp_arraytotxt($array) {
  foreach ($array as $key => $value) {
    if (!is_object($value) && !is_array($value)) {
      $text .= "{$key}: {$value}\r\n";
    }
  }
  return $text;
}
function ldaphelp_get_export_comments($export_conf_data) {
  if ($export_conf_data['admin_settings']) {
    $text = "\r\nAdmin Settings: \r\n" . ldaphelp_arraytotxt($export_conf_data['admin_settings']);
  }
  foreach ($export_conf_data['ldaps'] as $sid => $ldap) {
    $text .= "\r\n" . ldaphelp_arraytotxt($ldap);
  }
  return $text;
}
function ldaphelp_main() {
  $text = '<h3>' . t('LDAP Help Module') . '</h3><p>' . t('This module is meant to assist Drupal admins in configuring, debugging, sharing, and submitting
  support and bug request related to LDAP integration modules.') . '<strong><em> ' . t('LDAP Help Module should be disabled unless you are debugging or configuring ldap problems.') . '</em></strong> ' . t('It adds no functionality to the LDAP modules.') . '</p>';
  $path = drupal_get_path("module", "ldapauth");
  $text .= <<<EOT

  <h3>LDAP Integration Module Resources</h3>
  <ul>
  <li>The <a href="/{<span class="php-variable">$path</span>}/README.txt">readme file</a> covers basics of module.</li>
  <li><a href="http://drupal.org/node/62217">LDAP Integration Contributed Module Documentation</a>
  overviews ldapauth, ldapgroups, and ldapdata modules and their installation and configuration.
  Sometimes out of date.  Be sure that documentation matches the version you are using.  This
  is a great opportunity for new users to contribute to the module:  when  you first use the
  documentation take notes on what needs to be clarified.
  </li>
  <li>Search <a href="http://drupal.org/project/issues/search/ldap_integration">issue que</a>  For best results,
  select version and category before searching.</li>
  <li><a href="http://drupal.org/project/issues/ldap_integration">View all issues</a></li>
  </ul>

   <h3>General Drupal Support Help</h3>

  <ul>
  <li><a href="http://drupal.org/node/314185">How to report a problem in Drupal</a></li>
  <li><a href="http://drupal.org/node/19279">How to report bugs in Drupal</a></li>
  <li><a href="http://drupal.org/Troubleshooting-FAQ">Drupal Troubleshooting FAQ</a></li>
  </ul>

  <h3>General LDAP Resources</h3>
  <ul>
  <li><a href="http://us.php.net/manual/en/book.ldap.php">PHP LDAP</a></li>
  <li><a href="http://directory.apache.org/studio/">Apache Directory Studio</a> LDAP Browser and Directory Client.</li>
  <li><a href="http://www.novell.com/documentation/edir873/index.html?page=/documentation/edir873/edir873/data/h0000007.html">Novell Edirectory</a></li>
  <li><a href="http://images.apple.com/server/macosx/docs/Open_Directory_Admin_v10.5_3rd_Ed.pdf">Apple Open Directory</a></li>
  <li><a href="http://msdn.microsoft.com/en-us/library/aa705886(VS.85).aspx">Microsoft Active Directory LDAP</a></li>
  </ul>

EOT;
  return $text;
}
function ldaphelp_watchdog_list() {

  /* watchdog table */
  drupal_add_css(drupal_get_path('module', 'ldaphelp') . '/ldaphelp.css', 'module', 'all', FALSE);
  $path = drupal_get_path("module", "ldapauth");
  $_content = "";
  if (module_exists('dblog')) {
    include_once drupal_get_path('module', 'dblog') . '/dblog.admin.inc';
    $_SESSION['dblog_overview_filter']['type'] = array(
      'ldapauth' => 'ldapauth',
    );
    if (!($_SESSION['dblog_overview_filter'] || $_SESSION['dblog_overview_filter']['severity'])) {
      $_SESSION['dblog_overview_filter']['severity'] = array();
    }
    $_content .= "<h3>" . t('LDAP Watchdog Errors and Notifications') . "</h3>";
    $_content .= dblog_overview();
    $_content .= l('...more watchdog', 'admin/reports/dblog');
  }
  else {
    $_content .= "<h3>" . t('LDAP Help Watchdog Errors and Notifications') . "</h3>";
    $_content .= 'This feature requires <code>Database logging</code> module to be turned on. ';
    $_content .= l('Module enable page', 'admin/build/modules');
  }
  return $_content;
}
function ldaphelp_users(&$form_state) {
  $form = array();
  $form['info'] = array(
    '#value' => t('Get a list of local Drupal users have been authenticated by LDAP.'),
  );
  $form['check_ldap'] = array(
    '#type' => 'checkbox',
    '#title' => t('Verify with LDAP'),
    '#description' => "If checked, the LDAP server will be queried to verify the user exists.",
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('List Users'),
  );
  return $form;
}
function ldaphelp_users_submit($form, $form_state) {
  $url = 'admin/settings/ldap/help/users/list';
  if ($form_state['values']['check_ldap']) {
    $url .= '/verify';
  }
  drupal_goto($url);
}

/**
 * Generate a list of all Drupal users marked as ldap_authentified.
 *
 * @param string $verify If not null, verify that the LDAP info matches the
 *                       Drupal account info.
 */
function ldaphelp_users_list($verify = NULL) {
  $header = array(
    "User Name",
    'LDAP Server',
    'LDAP DN',
    'PUID Status',
  );
  $verify = isset($verify);
  if ($verify) {
    $header[] = "Verified";
  }
  $rows = array();
  $result = db_query("SELECT uid, name, data FROM {users} WHERE status = %d ORDER BY name ASC", 1);
  while ($row = db_fetch_array($result)) {
    $data = unserialize($row['data']);
    if ($data['ldap_authentified']) {
      $name = l($row['name'], "user/{$row['uid']}");
      $dn = $data['ldap_dn'];
      $server = ldapauth_server_load($data['ldap_config']);
      $using_puid = false;
      if (!empty($server)) {
        $sid = $server->machine_name;
        $puid = NULL;
        $using_puid = !empty($server->puid_attr);
        $puid_status = t('Not Used');
        if ($using_puid) {
          $user_info = ldapauth_userinfo_load_by_uid($row['uid']);
          if (!empty($user_info) && isset($user_info->puid)) {
            $puid_status = t('Set');
            $puid = $user_info->puid;
          }
          else {
            $puid_status = t("Not set");
          }
        }
        if ($verify) {
          $verified = ldaphelp_ldap_user_verify($data['ldap_config'], $data['ldap_dn'], $puid);
        }
      }
      else {
        $sid = t("Invalid Server Id");
        $puid_status = t('No server');
        $verified = t("No server");
      }
      $row = array(
        $name,
        $sid,
        $dn,
        $puid_status,
      );
      if ($verify) {
        $row[] = $verified;
      }
      $rows[] = $row;
    }
  }
  $output = "<p>" . t('This is a list of local Drupal users who have been marked as "LDAP Authenticated". The server and dn info are from the Drupal user data.') . "</p><p>" . t('The PUID status indicates if the user (and server) is using the Persistent Unique ID (PUID) and if it is set or not.') . "</p><p>" . t('Note that since the local data may be out of sync with the LDAP server, the verified option can be selected to verify that the local user data matchs the LDAP information.  If a user is not found, this indicates that the user has either been deleted from LDAP or their lDAP user entry was moved since their last login.') . "</p>";
  $output .= theme_table($header, $rows);
  return $output;
}

/**
 * Verify that a user can be found from the Drupal account information.
 *
 * @param int $sid The server id to look on
 * @param string $dn The user's dn from the account data.
 * @param string $puid The user's PUID or NULL if not using PUIDs.
 */
function ldaphelp_ldap_user_verify($sid, $dn, $puid) {
  global $_ldapauth_ldap;
  static $ldap_sid;

  // Only re init/bind if new server.
  if ($ldap_sid != $sid) {
    $ldap = _ldapauth_init($sid);
    if (!$ldap) {
      return t("LDAP server init failed!");
    }

    // If there is no bindn and bindpw - the connect will be an anonymous connect.
    $success = $ldap
      ->connect($ldap
      ->getOption('binddn'), $ldap
      ->getOption('bindpw'));
    if (!$success) {
      return t("LDAP bind failed!");
    }
    $ldap_sid = $sid;
  }
  else {
    $ldap = $_ldapauth_ldap;
  }
  if ($puid) {
    $puid_dn = ldaphelp_ldap_user_find_by_puid($ldap, $puid);
    if ($puid_dn === FALSE) {
      return t('PUID not unique!');
    }
    elseif ($puid_dn === NULL) {

      //return t('PUID not found');
    }
    elseif (strtolower($puid_dn) != strtolower($dn)) {
      return t('PUID dn does not match - will be corrected next time the user logs in or is synced.');
    }
    else {
      return t('User found by PUID');
    }
  }
  $entry = ldapauth_user_lookup_by_dn($ldap, $dn, LDAPAUTH_SYNC_CONTEXT_AUTHENTICATE_DRUPAL_USER, TRUE);
  if (isset($entry['dn'])) {
    if ($puid) {

      // PUID not found but DN valid
      return t("User found / No PUID set, but will be be set next time this user login in or is synced.");
    }
    return t("User found");
  }
  if ($puid) {

    // PUID not found and DN invalid
    return t("User not found / PUID can not be set for this user!");
  }
  return t("User not found");
}

/**
 * Lookup a user's ldap entry using the PUID attribute.
 *
 * @param LDAPInterface $ldap
 * @param String $puid
 * @return The user dn, NULL if not found, FALSE if not unique
 */
function ldaphelp_ldap_user_find_by_puid($ldap, $puid) {
  $sid = $ldap
    ->getOption('sid');
  $filter = ldapauth_puid_filter($sid, $puid);
  $attrs = array();
  foreach (explode("\r\n", $ldap
    ->getOption('basedn')) as $base_dn) {
    if (empty($base_dn)) {
      continue;
    }
    $result = $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) {
      return FALSE;
    }
    return $result[0]['dn'];
  }
  return NULL;
}

Functions

Namesort descending Description
ldaphelp_addcommon
ldaphelp_arraytohtml
ldaphelp_arraytohtmllist
ldaphelp_arraytotxt
ldaphelp_bind_trial_message
ldaphelp_display_settings_short
ldaphelp_form_ldapauth_admin_form_alter
ldaphelp_get_export_comments
ldaphelp_init Implementation of hook_init().
ldaphelp_ldap_user_find_by_puid Lookup a user's ldap entry using the PUID attribute.
ldaphelp_ldap_user_verify Verify that a user can be found from the Drupal account information.
ldaphelp_main
ldaphelp_menu Implementation of hook_menu().
ldaphelp_users
ldaphelp_users_list Generate a list of all Drupal users marked as ldap_authentified.
ldaphelp_users_submit
ldaphelp_watchdog_list
_ldaphelp_bind_test
_ldaphelp_get_configuration Get config information for general config and each ldap server defined.
_ldaphelp_get_form_values

Globals

Namesort descending Description
$_ldaphelp_ldaps @file The ldaphelp module is a module to help admins debug ldap_integration modules.