View source
<?php
define('REQUIREMENT_INFO', -1);
define('REQUIREMENT_OK', 0);
define('REQUIREMENT_WARNING', 1);
define('REQUIREMENT_ERROR', 2);
function ldaphelp_status() {
drupal_add_css(drupal_get_path('module', 'system') . '/system.css', 'module', 'all', FALSE);
include_once drupal_get_path('module', 'system') . '/system.admin.inc';
$heading = "Server and LDAP Modules";
$key = 'server';
$phpinfo = ldaphelp_parsePHPModules();
$status = ldaphelp_get_server($phpinfo, $info);
$reportingtext .= _ldaphelp_parse_status_to_text($status, $heading);
$content .= "<h3>{$heading}</h3>" . theme_status_report($status);
$heading = "LDAP Authentication Settings";
$status = ldaphelp_get_ldapauth($info);
$content .= "<h3>{$heading}</h3>" . theme_status_report($status);
$reportingtext .= _ldaphelp_parse_status_to_text($status, $heading);
$conf_data = _ldaphelp_get_configuration(TRUE, NULL);
$ldaps = $conf_data['ldaps'];
foreach ($ldaps as $sid => $ldap) {
$heading = "LDAP Server: " . $ldap['name'] . ' LDAP (sid=' . $ldap['sid'] . ')';
$edit_ldap = l(t('[edit]'), "admin/settings/ldap/ldapauth/edit/" . $sid);
$test_results = _ldaphelp_testldap($ldap, $sid);
$status = ldaphelp_get_ldap_server($info, $sid, $ldap, $test_results, $edit_ldap);
$content .= "<h3>{$heading}</h3>" . theme_status_report($status);
$reportingtext .= _ldaphelp_parse_status_to_text($status, $heading, array(
$edit_ldap => "",
));
}
$reportingtext .= _ldaphelp_parse_status_to_text(array(), "RAW ADMIN SETTINGS");
$reportingtext .= ldaphelp_arraytotxt($conf_data['admin_settings']);
foreach ($conf_data['ldaps'] as $sid => $ldap) {
$reportingtext .= "\r\nLDAP sid={$sid}\r\n" . ldaphelp_arraytotxt($conf_data['ldaps'][$sid]);
}
$content .= '<h3>Bug and Support Reporting Info</h3><p>
Cut and paste this into a text file and attach it to any bug or support requests.
<strong><em>Remove or replace any data you feel should not be made public before sharing this data.</em></strong></p>
<form><textarea cols="80" rows="20">' . $reportingtext . '</textarea></form>';
return $content;
}
function ldaphelp_get_server($phpinfo, &$info) {
$info['phpversion'] = phpversion();
$info['ldaploaded'] = extension_loaded('ldap');
$info['ldap'] = $phpinfo['ldap'];
$text = "";
foreach ($phpinfo['ldap'] as $key => $value) {
$text .= "<br/>{$key}: " . $value[0];
}
$info['ldap']['text'] = $text;
$modules = module_rebuild_cache();
$ldapmodules = array(
'ldapauth',
'ldapgroups',
'ldapdata',
'ldaphelp',
'ldapsync',
);
foreach ($ldapmodules as $ldapmodule) {
$data['status'] = $modules[$ldapmodule]->status;
$data['schema_version'] = $modules[$ldapmodule]->schema_version;
$data['version'] = $modules[$ldapmodule]->info['version'];
$data['text'] = "status: " . $data['status'] . ", schema_version: " . $data['schema_version'] . ", v: " . $data['version'];
$info[$ldapmodule] = $data;
}
if ($phpinfo['Apache Environment']) {
$status[] = array(
'title' => 'Apache',
'value' => $phpinfo['Apache Environment']['SERVER_SOFTWARE'],
);
}
elseif ($_SERVER["SERVER_SOFTWARE"]) {
$status[] = array(
'title' => 'SERVER_SOFTWARE',
'value' => $_SERVER["SERVER_SOFTWARE"],
);
}
$status[] = array(
'title' => 'PHP version',
'value' => phpversion(),
);
if (!$info['ldaploaded']) {
$status[] = array(
'title' => 'PHP ldap extension not loaded',
'value' => l(t('PHP LDAP extension'), 'http://us2.php.net/ldap') . ' ' . t('must be loaded for LDAP Integration to work.
It comes compiled with most versions of PHP.'),
'severity' => REQUIREMENT_ERROR,
);
}
else {
$status[] = array(
'title' => 'PHP ldap extension data',
'value' => $info['ldap']['text'],
'severity' => 0,
);
}
$status[] = array(
'title' => 'Drupal',
'value' => VERSION,
'severity' => "0",
);
foreach ($ldapmodules as $ldapmodule) {
$status[] = array(
'title' => $ldapmodule,
value => $info[$ldapmodule]['text'],
'severity' => "0",
);
}
return $status;
}
function ldaphelp_get_ldapauth(&$info) {
$info['ldapauth']['login_process_text'] = LDAPAUTH_LOGIN_PROCESS == LDAPAUTH_AUTH_EXCLUSIVED ? "LDAP directory only" : "Mixed Mode";
$info['ldapauth']['login_process_text'] .= " (" . LDAPAUTH_LOGIN_PROCESS . ')';
$info['ldapauth']['login_conflict_text'] = LDAPAUTH_LOGIN_CONFLICT == LDAPAUTH_CONFLICT_RESOLVE ? "Associate local account with the ldap entry" : "Disallow login and log the conflict";
$info['ldapauth']['login_conflict_text'] .= " (" . LDAPAUTH_LOGIN_CONFLICT . ')';
$status[] = array(
'title' => 'Authentication mode',
value => $info['ldapauth']['login_process_text'],
'severity' => "0",
);
$status[] = array(
'title' => 'Conflict Resolve Feature',
value => $info['ldapauth']['login_conflict_text'],
'severity' => "0",
);
$info['ldapauth']['ldapauth_disable_pass_change_text'] = LDAPAUTH_FORGET_PASSWORDS == TRUE ? "Do not " : "Do";
$info['ldapauth']['ldapauth_disable_pass_change_text'] .= 'store users\' passwords during sessions.';
$status[] = array(
'title' => 'Security: Store Passwords',
value => $info['ldapauth']['ldapauth_disable_pass_change_text'],
'severity' => "0",
);
$info['ldapauth']['ldapauth_disable_pass_change_text'] = LDAPAUTH_SYNC_PASSWORDS == FALSE ? "Do not " : "Do";
$info['ldapauth']['ldapauth_disable_pass_change_text'] .= 'sync LDAP password with the Drupal password';
$status[] = array(
'title' => 'Security: Sync Passwords',
value => $info['ldapauth']['ldapauth_disable_pass_change_text'],
'severity' => "0",
);
$create_users = variable_get('ldapauth_create_users', TRUE);
$info['ldapauth']['ldapauth_disable_pass_change_text'] = $create_users_ == FALSE ? "Do not " : "Do";
$info['ldapauth']['ldapauth_disable_pass_change_text'] .= 'create new Drupal users if not present.';
$status[] = array(
'title' => 'Security: New Users',
value => $info['ldapauth']['ldapauth_disable_pass_change_text'],
'severity' => "0",
);
switch (LDAPAUTH_ALTER_USERNAME_FIELD) {
case 0:
$alter_type = "Do nothing ( 0 )";
break;
case 1:
$alter_type = "Remove username field from form ( 1 )";
break;
case 2:
$alter_type = "Disable username field on form ( 2 )";
break;
default:
$alter_type = "UNKNOWN ACTION ( " . LDAPAUTH_ALTER_USERNAME_FIELD . ")";
}
$info['ldapauth']['ldapauth_disable_pass_change_text'] = $alter_type;
$status[] = array(
'title' => 'UI: Username Field',
value => $info['ldapauth']['ldapauth_disable_pass_change_text'],
'severity' => "0",
);
$info['ldapauth']['ldapauth_disable_pass_change_text'] = LDAPAUTH_DISABLE_PASS_CHANGE == TRUE ? "R" : "Do not R";
$info['ldapauth']['ldapauth_disable_pass_change_text'] .= 'emove password change fields from user edit form';
$status[] = array(
'title' => 'UI: Password Field',
value => $info['ldapauth']['ldapauth_disable_pass_change_text'],
'severity' => "0",
);
switch (LDAPAUTH_ALTER_EMAIL_FIELD) {
case 0:
$alter_type = "Do nothing ( 0 )";
break;
case 1:
$alter_type = "Remove email field from form ( 1 )";
break;
case 2:
$alter_type = "Disable email field on form ( 2 )";
break;
default:
$alter_type = "UNKNOWN ACTION ( " . LDAPAUTH_ALTER_EMAIL_FIELD . ")";
}
$info['ldapauth']['ldapauth_disable_pass_change_text'] = $alter_type;
$status[] = array(
'title' => 'UI: Email Field',
value => $info['ldapauth']['ldapauth_disable_pass_change_text'],
'severity' => "0",
);
$disable_picture = variable_get('ldapdata_disable_picture_change', NULL);
if ($disable_picture !== NULL) {
$info['ldapauth']['ldapauth_disable_pass_change_text'] = $disable_picture == TRUE ? "R" : "Do not R";
$info['ldapauth']['ldapauth_disable_pass_change_text'] .= 'emove picture change fields from user edit form';
$status[] = array(
'title' => 'UI: Picture Field',
value => $info['ldapauth']['ldapauth_disable_pass_change_text'],
'severity' => "0",
);
}
return $status;
}
function ldaphelp_get_ldap_server(&$info, $sid, &$ldap, &$test, $edit_ldap) {
$description = "server: " . $ldap['server'] . "<br/>port: " . $ldap['port'] . "<br/>tls: " . $ldap['tls'] . "<br/>encrypted: " . $ldap['encrypted'];
$status[] = array(
'title' => 'Server Settings ' . $edit_ldap,
'value' => $description,
'severity' => "0",
);
$description = "user_attr:<code> " . $ldap['user_attr'] . "</code><br/>mail_attr: <code>" . $ldap['mail_attr'] . "</code>";
$status[] = array(
'title' => 'Login Procedure ' . $edit_ldap,
'value' => $description,
'severity' => "0",
);
$description = "binddn: <code>" . $ldap['binddn'] . "</code><br/>bindpw: " . $ldap['bindpw'];
$status[] = array(
'title' => 'Advanced Configuration ' . $edit_ldap,
'value' => $description,
'severity' => "0",
);
$description = "Bind Type: " . $test['bind_type'] . "<br/>Bind Result?: " . $test['bind_result_text'];
if (!$test['bind_success']) {
$description .= ldaphelp_arraytohtml(array(
'LDAP Error' => $test['bind_result_error'],
'LDAP Error Number' => $test['bind_result_errno'],
));
if ($test['bind_result_errno'] === 49) {
$suggestions = "<ul>";
if ($test['bind_type'] == 'anon') {
$suggestions .= "<li>This LDAP server does not appear to allow anonymous connections. You will need to supply a dn and password in the advanced settings that can search the LDAP server.</li>";
}
else {
$suggestions .= "<li>The dn and/or password supplied in the advanced configuration section does not seem to be valid for this server.</li>";
}
$suggestions .= "</ul>";
$description .= ldaphelp_arraytohtml(array(
'Suggestions' => $suggestions,
));
}
}
$severity = $test['bind_success'] === TRUE ? "0" : "2";
$status[] = array(
'title' => 'Server Bind Test',
'value' => $description,
'severity' => $severity,
);
if ($test['bind_success'] === TRUE) {
foreach ($test['basedns'] as $basedn) {
if (isset($basedn['result']['base_dn_error'])) {
$usersfound = FALSE;
$usersfoundtext = "No";
$validbasedn = $basedn['basedn'];
$severity = 2;
$error = array(
'mal_formed_dn' => "<br/>This Base DN is incorrect: <br/><code>" . $basedn['basedn'] . "</code><br/>Test error was: " . $basedn['result']['base_dn_error'],
);
$suggestions = "<br/>Suggestions: <ul>";
$suggestions .= "<li>Make sure this DN does exists on the server.</li>";
$suggestions .= "<li>Verify the spelling and capitalization of the DN</li>";
$suggestions .= "<li>Make sure there are no extra spaces in the DN, e.g. after commas</li>";
$suggestions .= "</ul>";
$error['mal_formed_dn'] .= $suggestions;
}
elseif (isset($basedn['result']['count'])) {
$usersfound = TRUE;
$usersfoundtext = "Yes";
$severity = 0;
$error = '';
}
else {
$usersfound = FALSE;
$usersfoundtext = "No";
$validbasedn = $basedn['basedn'];
$severity = 2;
$error = array();
$result = ldaphelp_baddn($basedn['basedn'], 'Base DN');
if (!$result['boolean']) {
$error['mal_formed_dn'] = $result['text'];
}
$error['bind_success_search_failed'] = "<br/>Successfully bound to server <code>" . $ldap['server'] . "</code>, but found" . " no users in generic search (" . $ldap['user_attr'] . "=*) Suggestions: <ul>";
if ($basedn['result']['no_user_attr_success'] && !$data['result']['with_user_attr_success']) {
$error['bind_success_search_failed'] .= "<li> User attribute name <code>" . $ldap['user_attr'] . " </code> may be wrong. Found LDAP entries with search filter <code>CN=*</code>, " . " but not with search filter <code>" . $ldap['user_attr'] . "=*</code>.</li>";
}
if ($tests['bind_type'] == 'anon') {
$error['bind_success_search_failed'] .= "<li>Anonymous searches of your LDAP or the Base DN <code>" . $basedn['basedn'] . " </code> may not be allowed. Perhaps you need to create or use a service account to query the ldap.</li>";
}
else {
$error['bind_success_search_failed'] .= "<li>The DN and password supplied in the advanced settings area may not have the rights to search your LDAP server and/or the Base DN <code>" . $basedn['basedn'] . " </code>. Check with your LDAP administrator to see that this user can search all your Base DNs.</li>";
}
$error['bind_success_search_failed'] .= "<li>Perhaps Base DN is incorrect: <code>" . $basedn['basedn'] . "</code></li>";
$error['bind_success_search_failed'] .= "<li>Perhaps this Base DN does not have any entries and/or users defined under it.</li>";
$error['bind_success_search_failed'] .= "</ul>";
}
$header = 'Base DN:<br/><code>' . $basedn['basedn'] . '</code>';
$value = "<br/>Found Users in search of base DN?: <strong>" . $usersfoundtext . "</strong>" . $error['bind_success_search_failed'] . $error['mal_formed_dn'];
$status[] = array(
'title' => $header . ' ' . $edit_ldap,
'value' => $value,
'severity' => $severity,
);
}
}
return $status;
}
function _ldaphelp_parse_status_to_text($status, $heading, $replacements = array()) {
$var_del = "\r\n------------------------------------------------\r\n";
$section_del = "\r\n================================================\r\n";
$name_val_del = ":\r\n";
$lr = "\r\n";
$replacements = array_merge($replacements, array(
'<br/>' => $lr,
'<ul>' => $lr,
'</ul>' => $lr,
'<li>' => $lr,
'</li>' => "",
"<code>" => "",
"</code>" => "",
"<strong>" => "",
"</strong>" => "",
));
$content = $section_del . drupal_strtoupper($heading) . $section_del;
foreach ($status as $item) {
$item['value'] = str_replace(array_keys($replacements), array_values($replacements), $item['value']);
$item['title'] = str_replace(array_keys($replacements), array_values($replacements), $item['title']);
$content .= $item['title'] . $name_val_del . $item['value'] . $var_del;
}
return $content;
}
function _ldaphelp_testldap($ldap, $sid) {
global $_ldapauth_ldap;
$test = array();
_ldapauth_init($sid);
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;
}
if ($test['bind_success'] === TRUE) {
foreach (explode("\r\n", $_ldapauth_ldap
->getOption('basedn')) as $base_dn) {
$basedn_data = array();
$results = $_ldapauth_ldap
->retrieveAttributes($base_dn, array());
if (empty($results)) {
$basedn_data['result']['base_dn_error'] = 'DN does not exist.';
}
$user_attr = $_ldapauth_ldap
->getOption('user_attr') ? $_ldapauth_ldap
->getOption('user_attr') : LDAPAUTH_DEFAULT_USER_ATTR;
$filter = "{$user_attr}=*";
$result = $_ldapauth_ldap
->search($base_dn, $filter, array(
$user_attr,
), 0, 1, 1);
$basedn_data['result']['error'] = ldap_error($_ldapauth_ldap->connection);
$basedn_data['basedn'] = $base_dn;
$basedn_data['result']['count'] = $result['count'];
$basedn_data['result']['sample0'] = $result[0];
$basedn_data['result']['dnufn'] = ldap_dn2ufn($base_dn);
if (!$basedn_data['result']['count']) {
$basedn_data['result']['with_user_attr_success'] = FALSE;
$filter = "CN=*";
$result = $_ldapauth_ldap
->search($base_dn, $filter, array(
$user_attr,
), 0, 1, 1);
$basedn_data['result']['no_user_attr_success'] = $result['count'] ? TRUE : FALSE;
}
else {
$basedn_data['result']['with_user_attr_success'] = TRUE;
}
$test['basedns'][] = $basedn_data;
}
}
return $test;
}
function ldaphelp_baddn($dn, $dn_name) {
$result = array();
$valid_attr_name = '[a-zA-Z\\d\\s]';
$valid_attr_values = '[a-zA-Z\\d\\s]';
$regex = '/^(' . $valid_attr_name . '*\\=' . $valid_attr_values . '*[,]{1})*(' . $valid_attr_name . '*\\=' . $valid_attr_values . '*){1}$/';
$match = preg_match($regex, $dn) ? TRUE : FALSE;
$result['boolean'] = $match;
if (!$match) {
$result['text'] = "Invalid format for:<br/> <code><strong>" . htmlspecialchars($dn) . "</strong><code><br/> One cause may be editing {$dn_name} with a wysiwyg editor which leaves html.";
}
return $result;
}
function ldaphelp_parsePHPModules() {
ob_start();
phpinfo();
$s = ob_get_contents();
ob_end_clean();
$s = strip_tags($s, '<h2><th><td>');
$s = preg_replace('/<th[^>]*>([^<]+)<\\/th>/', "<info>\\1</info>", $s);
$s = preg_replace('/<td[^>]*>([^<]+)<\\/td>/', "<info>\\1</info>", $s);
$vtmp = preg_split('/(<h2>[^<]+<\\/h2>)/', $s, -1, PREG_SPLIT_DELIM_CAPTURE);
$vmodules = array();
for ($i = 1; $i < count($vtmp); $i++) {
if (preg_match('/<h2>([^<]+)<\\/h2>/', $vtmp[$i], $vmat)) {
$vname = trim($vmat[1]);
$vtmp2 = explode("\n", $vtmp[$i + 1]);
foreach ($vtmp2 as $vone) {
$vpat = '<info>([^<]+)<\\/info>';
$vpat3 = "/{$vPat}\\s*{$vpat}\\s*{$vpat}/";
$vpat2 = "/{$vPat}\\s*{$vpat}/";
if (preg_match($vpat3, $vone, $vmat)) {
$vmodules[$vname][trim($vmat[1])] = array(
trim($vmat[2]),
trim($vmat[3]),
);
}
elseif (preg_match($vpat2, $vone, $vmat)) {
$vmodules[$vname][trim($vmat[1])] = trim($vmat[2]);
}
}
}
}
return $vmodules;
}