From e45c86375aa741c2968d53f20491e33b15698284 Mon Sep 17 00:00:00 2001 From: Marco Ferrante Date: Sat, 17 Nov 2018 16:36:24 +0100 Subject: [PATCH] MDL-64071 auth: enhanced diagnostic of LDAP auth config --- auth/ldap/auth.php | 102 +++++++++++++++++++++++++------- auth/ldap/lang/en/auth_ldap.php | 6 ++ 2 files changed, 85 insertions(+), 23 deletions(-) diff --git a/auth/ldap/auth.php b/auth/ldap/auth.php index cd9e347d4bb..ebe55cc163f 100644 --- a/auth/ldap/auth.php +++ b/auth/ldap/auth.php @@ -2082,6 +2082,31 @@ class auth_plugin_ldap extends auth_plugin_base { return (bool)$user->suspended; } + /** + * Test a DN + * + * @param resource $ldapconn + * @param string $dn The DN to check for existence + * @param string $message The identifier of a string as in get_string() + * @param string|object|array $a An object, string or number that can be used + * within translation strings as in get_string() + * @return true or a message in case of error + */ + private function test_dn($ldapconn, $dn, $message, $a = null) { + $ldapresult = @ldap_read($ldapconn, $dn, '(objectClass=*)', array()); + if (!$ldapresult) { + if (ldap_errno($ldapconn) == 32) { + // No such object. + return get_string($message, 'auth_ldap', $a); + } + + $a = array('code' => ldap_errno($ldapconn), 'subject' => $a, 'message' => ldap_error($ldapconn)); + return get_string('diag_genericerror', 'auth_ldap', $a); + } + + return true; + } + /** * Test if settings are correct, print info to output. */ @@ -2089,35 +2114,66 @@ class auth_plugin_ldap extends auth_plugin_base { global $OUTPUT; if (!function_exists('ldap_connect')) { // Is php-ldap really there? - echo $OUTPUT->notification(get_string('auth_ldap_noextension', 'auth_ldap')); + echo $OUTPUT->notification(get_string('auth_ldap_noextension', 'auth_ldap'), \core\output\notification::NOTIFY_ERROR); return; } // Check to see if this is actually configured. - if ((isset($this->config->host_url)) && ($this->config->host_url !== '')) { - - try { - $ldapconn = $this->ldap_connect(); - // Try to connect to the LDAP server. See if the page size setting is supported on this server. - $pagedresultssupported = ldap_paged_results_supported($this->config->ldap_version, $ldapconn); - } catch (Exception $e) { - - // If we couldn't connect and get the supported options, we can only assume we don't support paged results. - $pagedresultssupported = false; - } - - // Display paged file results. - if ((!$pagedresultssupported)) { - echo $OUTPUT->notification(get_string('pagedresultsnotsupp', 'auth_ldap'), \core\output\notification::NOTIFY_INFO); - } else if ($ldapconn) { - // We were able to connect successfuly. - echo $OUTPUT->notification(get_string('connectingldapsuccess', 'auth_ldap'), \core\output\notification::NOTIFY_SUCCESS); - } - - } else { + if (empty($this->config->host_url)) { // LDAP is not even configured. - echo $OUTPUT->notification(get_string('ldapnotconfigured', 'auth_ldap'), \core\output\notification::NOTIFY_INFO); + echo $OUTPUT->notification(get_string('ldapnotconfigured', 'auth_ldap'), \core\output\notification::NOTIFY_ERROR); + return; } + + if ($this->config->ldap_version != 3) { + echo $OUTPUT->notification(get_string('diag_toooldversion', 'auth_ldap'), \core\output\notification::NOTIFY_WARNING); + } + + try { + $ldapconn = $this->ldap_connect(); + } catch (Exception $e) { + echo $OUTPUT->notification($e->getMessage(), \core\output\notification::NOTIFY_ERROR); + return; + } + + // Display paged file results. + if (!ldap_paged_results_supported($this->config->ldap_version, $ldapconn)) { + echo $OUTPUT->notification(get_string('pagedresultsnotsupp', 'auth_ldap'), \core\output\notification::NOTIFY_INFO); + } + + // Check contexts. + foreach (explode(';', $this->config->contexts) as $context) { + $context = trim($context); + if (empty($context)) { + echo $OUTPUT->notification(get_string('diag_emptycontext', 'auth_ldap'), \core\output\notification::NOTIFY_WARNING); + continue; + } + + $message = $this->test_dn($ldapconn, $context, 'diag_contextnotfound', $context); + if ($message !== true) { + echo $OUTPUT->notification($message, \core\output\notification::NOTIFY_WARNING); + } + } + + // Create system role mapping field for each assignable system role. + $roles = get_ldap_assignable_role_names(); + foreach ($roles as $role) { + foreach (explode(';', $this->config->{$role['settingname']}) as $groupdn) { + if (empty($groupdn)) { + continue; + } + + $role['group'] = $groupdn; + $message = $this->test_dn($ldapconn, $groupdn, 'diag_rolegroupnotfound', $role); + if ($message !== true) { + echo $OUTPUT->notification($message, \core\output\notification::NOTIFY_WARNING); + } + } + } + + $this->ldap_close(true); + // We were able to connect successfuly. + echo $OUTPUT->notification(get_string('connectingldapsuccess', 'auth_ldap'), \core\output\notification::NOTIFY_SUCCESS); } /** diff --git a/auth/ldap/lang/en/auth_ldap.php b/auth/ldap/lang/en/auth_ldap.php index 6d92020cd89..91ed1d9a84f 100644 --- a/auth/ldap/lang/en/auth_ldap.php +++ b/auth/ldap/lang/en/auth_ldap.php @@ -163,6 +163,12 @@ $string['userentriestoupdate'] = "User entries to be updated: {\$a}\n"; $string['usernotfound'] = 'User not found in LDAP'; $string['useracctctrlerror'] = 'Error getting userAccountControl for {$a}'; +$string['diag_genericerror'] = 'LDAP error {$a->code} reading {$a->subject}: {$a->message}.'; +$string['diag_toooldversion'] = 'Its is very unlikely a modern LDAP server uses LDAPv2 protocol. Wrong settings can corrupt values in user fields. Check with your LDAP administrator.'; +$string['diag_emptycontext'] = 'Empty context found.'; +$string['diag_contextnotfound'] = 'Context {$a} does not exists or cannot be read by bind DN.'; +$string['diag_rolegroupnotfound'] = 'Group {$a->group} for role {$a->localname} does not exists or cannot be read by bind DN.'; + // Deprecated since Moodle 3.4. $string['auth_ldap_creators'] = 'List of groups or contexts whose members are allowed to create new courses. Separate multiple groups with \';\'. Usually something like \'cn=teachers,ou=staff,o=myorg\''; $string['auth_ldap_creators_key'] = 'Creators';