first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
LDAP-module README
Please read comments from auth.php in this directory.
+2277
View File
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,51 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Special setting for auth_ldap that cleans up context values on save..
*
* @package auth_ldap
* @copyright 2017 Stephen Bourget
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Special setting for auth_ldap that cleans up context values on save..
*
* @package auth_ldap
* @copyright 2017 Stephen Bourget
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class auth_ldap_admin_setting_special_contexts_configtext extends admin_setting_configtext {
/**
* We need to remove duplicates on save to prevent issues in other areas of Moodle.
*
* @param string $data Form data.
* @return string Empty when no errors.
*/
public function write_setting($data) {
// Try to remove duplicates before storing the contexts (to avoid problems in sync_users()).
$data = explode(';', $data);
$data = array_map(function($x) {
return core_text::strtolower(trim($x));
}, $data);
$data = implode(';', array_unique($data));
return parent::write_setting($data);
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Special setting for auth_ldap that lowercases values on save..
*
* @package auth_ldap
* @copyright 2017 Stephen Bourget
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Special setting for auth_ldap that lowercases values on save..
*
* @package auth_ldap
* @copyright 2017 Stephen Bourget
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class auth_ldap_admin_setting_special_lowercase_configtext extends admin_setting_configtext {
/**
* We need to convert the data to lowercase prior to save.
*
* @param string $data Form data.
* @return string Empty when no errors.
*/
public function write_setting($data) {
return parent::write_setting(core_text::strtolower($data));
}
}
@@ -0,0 +1,53 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Special admin setting for auth_ldap that validates ntlm usernames.
*
* @package auth_ldap
* @copyright 2017 Stephen Bourget
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Special admin setting for auth_ldap that validates ntlm usernames.
*
* @package auth_ldap
* @copyright 2017 Stephen Bourget
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class auth_ldap_admin_setting_special_ntlm_configtext extends admin_setting_configtext {
/**
* We need to validate the username format when using NTLM.
*
* @param string $data Form data.
* @return string Empty when no errors.
*/
public function validate($data) {
if (get_config('auth_ldap', 'ntlmsso_type') === 'ntlm') {
$format = trim($data);
if (!empty($format) && !preg_match('/%username%/i', $format)) {
return get_string('auth_ntlmsso_missing_username', 'auth_ldap');
}
}
return parent::validate($data);
}
}
@@ -0,0 +1,61 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace auth_ldap\adminpresets;
use core_adminpresets\local\setting\adminpresets_setting;
/**
* Basic text setting, cleans the param using the admin_setting paramtext attribute.
*
* @package auth_ldap
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_auth_ldap_admin_setting_special_contexts_configtext extends adminpresets_setting {
/**
* Validates the value using paramtype attribute
*
* @param string $value
* @return boolean Returned value is always true, whenever the value has been successfully cleaned or not.
*/
protected function set_value($value): bool {
$this->value = $value;
if (empty($this->settingdata->paramtype)) {
// For configfile, configpasswordunmask....
$this->settingdata->paramtype = 'RAW';
}
$paramtype = 'PARAM_' . strtoupper($this->settingdata->paramtype);
// Regexp.
if (!defined($paramtype)) {
$this->value = preg_replace($this->settingdata->paramtype, '', $this->value);
// Standard moodle param type.
} else {
$this->value = clean_param($this->value, constant($paramtype));
}
$this->set_visiblevalue();
return true;
}
}
+41
View File
@@ -0,0 +1,41 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for auth_ldap.
*
* @package auth_ldap
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_ldap\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for auth_ldap implementing null_provider.
*
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason(): string {
return 'privacy:metadata';
}
}
@@ -0,0 +1,59 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Adhoc task for LDAP user sync.
*
* @package auth_ldap
* @copyright Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_ldap\task;
use core\task\adhoc_task;
/**
* Adhoc task class for LDAP user sync.
*
* @package auth_ldap
* @copyright Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class asynchronous_sync_task extends adhoc_task {
/** @var string Message prefix for mtrace */
protected const MTRACE_MSG = 'Synced ldap users';
/**
* Constructor
*/
public function __construct() {
$this->set_component('auth_ldap');
}
/**
* Run users sync.
*/
public function execute() {
$data = $this->get_custom_data();
/** @var auth_plugin_ldap $auth */
$auth = get_auth_plugin('ldap');
$auth->update_users($data->users, $data->updatekeys);
mtrace(sprintf(" %s (%d)", self::MTRACE_MSG, count($data->users)));
}
}
+61
View File
@@ -0,0 +1,61 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* A scheduled task for LDAP roles sync.
*
* @package auth_ldap
* @author David Balch <david.balch@conted.ox.ac.uk>
* @copyright 2017 The Chancellor Masters and Scholars of the University of Oxford {@link http://www.tall.ox.ac.uk}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_ldap\task;
defined('MOODLE_INTERNAL') || die();
/**
* A scheduled task class for LDAP roles sync.
*
* @author David Balch <david.balch@conted.ox.ac.uk>
* @copyright 2017 The Chancellor Masters and Scholars of the University of Oxford {@link http://www.tall.ox.ac.uk}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class sync_roles extends \core\task\scheduled_task {
/**
* Get a descriptive name for this task (shown to admins).
*
* @return string
*/
public function get_name() {
return get_string('syncroles', 'auth_ldap');
}
/**
* Synchronise role assignments from LDAP.
*/
public function execute() {
global $DB;
if (is_enabled_auth('ldap')) {
$auth = get_auth_plugin('ldap');
$users = $DB->get_records('user', array('auth' => 'ldap'));
foreach ($users as $user) {
$auth->sync_roles($user);
}
}
}
}
+69
View File
@@ -0,0 +1,69 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* A scheduled task for LDAP user sync.
*
* @package auth_ldap
* @copyright 2015 Vadim Dvorovenko <Vadimon@mail.ru>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_ldap\task;
/**
* A scheduled task class for LDAP user sync.
*
* @copyright 2015 Vadim Dvorovenko <Vadimon@mail.ru>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class sync_task extends \core\task\scheduled_task {
/** @var string Message prefix for mtrace */
protected const MTRACE_MSG = 'Synced ldap users';
/**
* Get a descriptive name for this task (shown to admins).
*
* @return string
*/
public function get_name() {
return get_string('synctask', 'auth_ldap');
}
/**
* Run users sync.
*/
public function execute() {
if (is_enabled_auth('ldap')) {
/** @var auth_plugin_ldap $auth */
$auth = get_auth_plugin('ldap');
$count = 0;
$auth->sync_users_update_callback(function ($users, $updatekeys) use (&$count) {
$asynctask = new asynchronous_sync_task();
$asynctask->set_custom_data([
'users' => $users,
'updatekeys' => $updatekeys,
]);
\core\task\manager::queue_adhoc_task($asynctask);
$count++;
mtrace(sprintf(" %s (%d)", self::MTRACE_MSG, $count));
sleep(1);
});
}
}
}
+71
View File
@@ -0,0 +1,71 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* CAS user sync script.
*
* This script is meant to be called from a cronjob to sync moodle with the LDAP
* backend in those setups where the LDAP backend acts as 'master'.
*
* Notes:
* - it is required to use the web server account when executing PHP CLI scripts
* - you need to change the "www-data" to match the apache user account
* - use "su" if "sudo" not available
* - If you have a large number of users, you may want to raise the memory limits
* by passing -d momory_limit=256M
* - For debugging & better logging, you are encouraged to use in the command line:
* -d log_errors=1 -d error_reporting=E_ALL -d display_errors=0 -d html_errors=0
* - If you have a large number of users, you may want to raise the memory limits
* by passing -d momory_limit=256M
* - For debugging & better logging, you are encouraged to use in the command line:
* -d log_errors=1 -d error_reporting=E_ALL -d display_errors=0 -d html_errors=0
*
* Performance notes:
* We have optimized it as best as we could for PostgreSQL and MySQL, with 27K students
* we have seen this take 10 minutes.
*
* @package auth_ldap
* @copyright 2004 Martin Langhoff
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @deprecated since Moodle 3.0 MDL-51824 - please do not use this CLI script any more, use scheduled task instead.
* @todo MDL-50264 This will be deleted in Moodle 3.2.
*/
define('CLI_SCRIPT', true);
require(__DIR__.'/../../../config.php'); // global moodle config file.
require_once($CFG->dirroot.'/course/lib.php');
require_once($CFG->libdir.'/clilib.php');
// Ensure errors are well explained
set_debugging(DEBUG_DEVELOPER, true);
if (!is_enabled_auth('ldap')) {
error_log('[AUTH LDAP] '.get_string('pluginnotenabled', 'auth_ldap'));
die;
}
cli_problem('[AUTH LDAP] The users sync cron has been deprecated. Please use the scheduled task instead.');
// Abort execution of the CLI script if the auth_ldap\task\sync_task is enabled.
$taskdisabled = \core\task\manager::get_scheduled_task('auth_ldap\task\sync_task');
if (!$taskdisabled->get_disabled()) {
cli_error('[AUTH LDAP] The scheduled task sync_task is enabled, the cron execution has been aborted.');
}
$ldapauth = get_auth_plugin('ldap');
$ldapauth->sync_users(true);
+6
View File
@@ -0,0 +1,6 @@
<?php
function xmldb_auth_ldap_install() {
global $CFG, $DB;
}
+49
View File
@@ -0,0 +1,49 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Definition of auth_ldap tasks.
*
* @package auth_ldap
* @category task
* @copyright 2015 Vadim Dvorovenko <Vadimon@mail.ru>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$tasks = array(
array(
'classname' => 'auth_ldap\task\sync_roles',
'blocking' => 0,
'minute' => '0',
'hour' => '0',
'day' => '*',
'month' => '*',
'dayofweek' => '*',
'disabled' => 1
),
array(
'classname' => 'auth_ldap\task\sync_task',
'blocking' => 0,
'minute' => '0',
'hour' => '0',
'day' => '*',
'month' => '*',
'dayofweek' => '*',
'disabled' => 1
)
);
+44
View File
@@ -0,0 +1,44 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* LDAP authentication plugin upgrade code
*
* @package auth_ldap
* @copyright 2013 Iñaki Arenaza
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Function to upgrade auth_ldap.
* @param int $oldversion the version we are upgrading from
* @return bool result
*/
function xmldb_auth_ldap_upgrade($oldversion) {
// Automatically generated Moodle v4.1.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.2.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.3.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.4.0 release upgrade line.
// Put any upgrade step following this.
return true;
}
+170
View File
@@ -0,0 +1,170 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Strings for component 'auth_ldap', language 'en'.
*
* @package auth_ldap
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['auth_ldap_ad_create_req'] = 'Cannot create the new account in Active Directory. Make sure you meet all the requirements for this to work (LDAPS connection, bind user with adequate rights, etc.)';
$string['auth_ldap_attrcreators'] = 'List of groups or contexts whose members are allowed to create attributes. Separate multiple groups with \';\'. Usually something like \'cn=teachers,ou=staff,o=myorg\'';
$string['auth_ldap_attrcreators_key'] = 'Attribute creators';
$string['auth_ldap_auth_user_create_key'] = 'Create users externally';
$string['auth_ldap_bind_dn'] = 'If you want to use bind-user to search users, specify it here. Something like \'cn=ldapuser,ou=public,o=org\'';
$string['auth_ldap_bind_dn_key'] = 'Distinguished name';
$string['auth_ldap_bind_pw'] = 'Password for bind-user.';
$string['auth_ldap_bind_pw_key'] = 'Password';
$string['auth_ldap_bind_settings'] = 'Bind settings';
$string['auth_ldap_contexts'] = 'List of contexts where users are located. Separate different contexts with \';\'. For example: \'ou=users,o=org; ou=others,o=org\'';
$string['auth_ldap_contexts_key'] = 'Contexts';
$string['auth_ldap_create_context'] = 'If you enable user creation with email confirmation, specify the context where users are created. This context should be different from other users to prevent security issues. You don\'t need to add this context to ldap_context-variable, Moodle will search for users from this context automatically.<br /><b>Note!</b> You have to modify the method user_create() in file auth/ldap/auth.php to make user creation work';
$string['auth_ldap_create_context_key'] = 'Context for new users';
$string['auth_ldap_create_error'] = 'Error creating user in LDAP.';
$string['auth_ldapdescription'] = 'This method provides authentication against an external LDAP server. If the given username and password are valid, Moodle creates a new user entry in its database. This plugin can read user attributes from LDAP and prefill wanted fields in Moodle. For following logins only the username and password are checked.';
$string['auth_ldap_expiration_desc'] = 'Select \'{$a->no}\' to disable expired password checking or \'{$a->ldapserver}\' to read the password expiry time directly from the LDAP server.';
$string['auth_ldap_expiration_key'] = 'Expiry';
$string['auth_ldap_expiration_warning_desc'] = 'Number of days before password expiry warning is issued.';
$string['auth_ldap_expiration_warning_key'] = 'Expiry warning';
$string['auth_ldap_expireattr_desc'] = 'Optional: Overrides the LDAP attribute that stores password expiry time.';
$string['auth_ldap_expireattr_key'] = 'Expiry attribute';
$string['auth_ldapextrafields'] = 'These fields are optional. You can choose to pre-fill some Moodle user fields with information from the <b>LDAP fields</b> that you specify here. <p>If you leave these fields blank, then nothing will be transferred from LDAP and Moodle defaults will be used instead.</p><p>In either case, the user will be able to edit all of these fields after they log in.</p>';
$string['auth_ldap_graceattr_desc'] = 'Optional: Overrides grace login attribute';
$string['auth_ldap_gracelogin_key'] = 'Grace login attribute';
$string['auth_ldap_gracelogins_desc'] = 'Enable LDAP grace login support. After password has expired, user can log in until grace login count is 0. Enabling this setting displays grace login message if password has expired.';
$string['auth_ldap_gracelogins_key'] = 'Grace logins';
$string['auth_ldap_groupecreators'] = 'List of groups or contexts whose members are allowed to create groups. Separate multiple groups with \';\'. Usually something like \'cn=teachers,ou=staff,o=myorg\'';
$string['auth_ldap_groupecreators_key'] = 'Group creators';
$string['auth_ldap_host_url'] = 'Specify LDAP host in URL-form like \'ldap://ldap.myorg.com/\' or \'ldaps://ldap.myorg.com/\'. Separate multiple servers with \';\' to get failover support.';
$string['auth_ldap_host_url_key'] = 'Host URL';
$string['auth_ldap_changepasswordurl_key'] = 'Password-change URL';
$string['auth_ldap_ldap_encoding'] = 'Encoding used by the LDAP server, most likely utf-8. If LDAP v2 is selected, Active Directory uses its configured encoding, such as cp1252 or cp1250.';
$string['auth_ldap_ldap_encoding_key'] = 'LDAP encoding';
$string['auth_ldap_login_settings'] = 'Login settings';
$string['auth_ldap_memberattribute'] = 'Optional: Overrides user member attribute, when users belongs to a group. Usually \'member\'';
$string['auth_ldap_memberattribute_isdn'] = 'Overrides handling of member attribute values';
$string['auth_ldap_memberattribute_isdn_key'] = 'Member attribute uses dn';
$string['auth_ldap_memberattribute_key'] = 'Member attribute';
$string['auth_ldap_noconnect'] = 'LDAP-module cannot connect to server: {$a}';
$string['auth_ldap_noconnect_all'] = 'LDAP-module cannot connect to any servers: {$a}';
$string['auth_ldap_noextension'] = 'The PHP LDAP module does not seem to be present. Please ensure it is installed and enabled if you want to use this authentication plugin.';
$string['auth_ldap_no_mbstring'] = 'You need the mbstring extension to create users in Active Directory.';
$string['auth_ldapnotinstalled'] = 'Cannot use LDAP authentication. The PHP LDAP module is not installed.';
$string['auth_ldap_objectclass'] = 'Optional: Overrides objectClass used to name/search users on ldap_user_type. Usually you don\'t need to change this.';
$string['auth_ldap_objectclass_key'] = 'Object class';
$string['auth_ldap_opt_deref'] = 'Determines how aliases are handled during search. Select one of the following values: "No" (LDAP_DEREF_NEVER) or "Yes" (LDAP_DEREF_ALWAYS)';
$string['auth_ldap_opt_deref_key'] = 'Dereference aliases';
$string['auth_ldap_passtype'] = 'Specify the format of new or changed passwords in LDAP server.';
$string['auth_ldap_passtype_key'] = 'Password format';
$string['auth_ldap_passwdexpire_settings'] = 'LDAP password expiry settings';
$string['auth_ldap_preventpassindb'] = 'Select yes to prevent passwords from being stored in Moodle\'s DB.';
$string['auth_ldap_preventpassindb_key'] = 'Prevent password caching';
$string['auth_ldap_rolecontext'] = '{$a->localname} context';
$string['auth_ldap_rolecontext_help'] = 'LDAP context used to select for <i>{$a->localname}</i> mapping. Separate multiple groups with \';\'. Usually something like "cn={$a->shortname},ou=first-ou-with-role-groups,o=myorg; cn={$a->shortname},ou=second-ou-with-role-groups,o=myorg".';
$string['auth_ldap_search_sub'] = 'Search users from subcontexts.';
$string['auth_ldap_search_sub_key'] = 'Search subcontexts';
$string['auth_ldap_server_settings'] = 'LDAP server settings';
$string['auth_ldap_unsupportedusertype'] = 'auth: ldap user_create() does not support selected usertype: {$a}';
$string['auth_ldap_update_userinfo'] = 'Update user information (firstname, lastname, address..) from LDAP to Moodle. Specify "Data mapping" settings as you need.';
$string['auth_ldap_user_attribute'] = 'Optional: Overrides the attribute used to name/search users. Usually \'cn\'.';
$string['auth_ldap_user_attribute_key'] = 'User attribute';
$string['auth_ldap_suspended_attribute'] = 'Optional: When provided this attribute will be used to enable/suspend the locally created user account.';
$string['auth_ldap_suspended_attribute_key'] = 'Suspended attribute';
$string['auth_ldap_user_exists'] = 'LDAP username already exists.';
$string['auth_ldap_user_settings'] = 'User lookup settings';
$string['auth_ldap_user_type'] = 'Select how users are stored in LDAP. This setting also specifies how login expiry, grace logins and user creation will work.';
$string['auth_ldap_user_type_key'] = 'User type';
$string['auth_ldap_usertypeundefined'] = 'config.user_type not defined or function ldap_expirationtime2unix does not support selected type!';
$string['auth_ldap_usertypeundefined2'] = 'config.user_type not defined or function ldap_unixi2expirationtime does not support selected type!';
$string['auth_ldap_version'] = 'The version of the LDAP protocol your server is using.';
$string['auth_ldap_version_key'] = 'Version';
$string['auth_ntlmsso'] = 'NTLM SSO';
$string['auth_ntlmsso_enabled'] = 'Set to yes to attempt Single Sign On with the NTLM domain. Note that this requires additional setup on the server to work. For further details, see the documentation <a href="https://docs.moodle.org/en/NTLM_authentication">NTLM authentication</a>.';
$string['auth_ntlmsso_enabled_key'] = 'Enable';
$string['auth_ntlmsso_ie_fastpath'] = 'Set to enable the NTLM SSO fast path (bypasses certain steps if the client\'s browser is MS Internet Explorer).';
$string['auth_ntlmsso_ie_fastpath_key'] = 'MS IE fast path?';
$string['auth_ntlmsso_ie_fastpath_yesform'] = 'Yes, all other browsers use standard login form';
$string['auth_ntlmsso_ie_fastpath_yesattempt'] = 'Yes, attempt NTLM other browsers';
$string['auth_ntlmsso_ie_fastpath_attempt'] = 'Attempt NTLM with all browsers';
$string['auth_ntlmsso_maybeinvalidformat'] = 'Unable to extract the username from the REMOTE_USER header. Is the configured format right?';
$string['auth_ntlmsso_missing_username'] = 'You need to specify at least %username% in the remote username format';
$string['auth_ntlmsso_remoteuserformat_key'] = 'Remote username format';
$string['auth_ntlmsso_remoteuserformat'] = 'If you have chosen \'NTLM\' in \'Authentication type\', you can specify the remote username format here. If you leave this empty, the default DOMAIN\\username format will be used. You can use the optional <b>%domain%</b> placeholder to specify where the domain name appears, and the mandatory <b>%username%</b> placeholder to specify where the username appears. <br /><br />Some widely used formats are <tt>%domain%\\%username%</tt> (MS Windows default), <tt>%domain%/%username%</tt>, <tt>%domain%+%username%</tt> and just <tt>%username%</tt> (if there is no domain part).';
$string['auth_ntlmsso_subnet'] = 'If set, it will only attempt SSO with clients in this subnet. Format: xxx.xxx.xxx.xxx/bitmask. Separate multiple subnets with \',\' (comma).';
$string['auth_ntlmsso_subnet_key'] = 'Subnet';
$string['auth_ntlmsso_type_key'] = 'Authentication type';
$string['auth_ntlmsso_type'] = 'The authentication method configured in the web server to authenticate the users (if in doubt, choose NTLM)';
$string['cannotmaprole'] = 'The role "{$a->rolename}" cannot be mapped because its short name "{$a->shortname}" is too long and/or contains hyphens. To allow it to be mapped, the short name needs to be reduced to a maximum of {$a->charlimit} characters and any hyphens removed. <a href="{$a->link}">Edit the role</a>';
$string['connectingldap'] = "Connecting to LDAP server...\n";
$string['connectingldapsuccess'] = "Connecting to your LDAP server was successful";
$string['creatingtemptable'] = "Creating temporary table {\$a}\n";
$string['didntfindexpiretime'] = 'password_expire() didn\'t find expiration time.';
$string['didntgetusersfromldap'] = "Did not get any users from LDAP -- error? -- exiting\n";
$string['gotcountrecordsfromldap'] = "Got {\$a} records from LDAP\n";
$string['invalidusererrors'] = "Warning: Skipped creation of {\$a} user accounts.\n\n";
$string['invaliduserexception'] = "\nError: Cannot create new user account. Details and reason:\n{\$a}\nSkipping this user.\n\n";
$string['ldapnotconfigured'] = 'The LDAP host url is currently not configured';
$string['morethanoneuser'] = 'More than one user record found in LDAP. Using only the first one.';
$string['needbcmath'] = 'You need the BCMath extension to use expired password checking with Active Directory.';
$string['needmbstring'] = 'You need the mbstring extension to change passwords in Active Directory';
$string['nodnforusername'] = 'Error in user_update_password(). No DN for: {$a->username}';
$string['noemail'] = 'Tried to send you an email but failed!';
$string['notcalledfromserver'] = 'Should not be called from the web server!';
$string['noupdatestobedone'] = "No updates to be done\n";
$string['nouserentriestoremove'] = "No user entries to be removed\n";
$string['nouserentriestorevive'] = "No user entries to be revived\n";
$string['nouserstobeadded'] = 'No user entries to be added';
$string['ntlmsso_attempting'] = 'Attempting Single Sign On via NTLM...';
$string['ntlmsso_failed'] = 'Auto-login failed, try the normal login page...';
$string['ntlmsso_isdisabled'] = 'NTLM SSO is disabled.';
$string['ntlmsso_unknowntype'] = 'Unknown ntlmsso type!';
$string['pagedresultsnotsupp'] = 'LDAP paged results not supported (either your PHP version lacks support, you have configured Moodle to use LDAP protocol version 2 or Moodle cannot contact your LDAP server to see if paged support is available.)';
$string['pagesize'] = 'Make sure this value is smaller than your LDAP server result set size limit (the maximum number of entries that can be returned in a single query)';
$string['pagesize_key'] = 'Page size';
$string['pluginname'] = 'LDAP server';
$string['pluginnotenabled'] = 'Plugin not enabled!';
$string['renamingnotallowed'] = 'User renaming not allowed in LDAP';
$string['rootdseerror'] = 'Error querying rootDSE for Active Directory';
$string['syncroles'] = 'Synchronise system roles from LDAP';
$string['synctask'] = 'LDAP users sync job';
$string['sync_updateuserchunk'] = 'Set this value to the number of users you want updated per transaction. Setting this to 0 will update all users in one transaction.';
$string['sync_updateuserchunk_key'] = 'Sync update users chunk size';
$string['systemrolemapping'] = 'System role mapping';
$string['start_tls'] = 'Use regular LDAP service (port 389) with TLS encryption';
$string['start_tls_key'] = 'Use TLS';
$string['updateremfail'] = 'Error updating LDAP record. Error code: {$a->errno}; Error string: {$a->errstring}<br/>Key ({$a->key}) - old moodle value: \'{$a->ouvalue}\' new value: \'{$a->nuvalue}\'';
$string['updateremfailamb'] = 'Failed to update LDAP with ambiguous field {$a->key}; old moodle value: \'{$a->ouvalue}\', new value: \'{$a->nuvalue}\'';
$string['updatepasserror'] = 'Error in user_update_password(). Error code: {$a->errno}; Error string: {$a->errstring}';
$string['updatepasserrorexpire'] = 'Error in user_update_password() when reading password expiry time. Error code: {$a->errno}; Error string: {$a->errstring}';
$string['updatepasserrorexpiregrace'] = 'Error in user_update_password() when modifying expiry time and/or grace logins. Error code: {$a->errno}; Error string: {$a->errstring}';
$string['updateusernotfound'] = 'Could not find user while updating externally. Details follow: search base: \'{$a->userdn}\'; search filter: \'(objectClass=*)\'; search attributes: {$a->attribs}';
$string['user_activatenotsupportusertype'] = 'auth: ldap user_activate() does not support selected usertype: {$a}';
$string['user_disablenotsupportusertype'] = 'auth: ldap user_disable() does not support selected usertype: {$a}';
$string['userentriestoadd'] = "User entries to be added: {\$a}\n";
$string['userentriestoremove'] = "User entries to be removed: {\$a}\n";
$string['userentriestorevive'] = "User entries to be revived: {\$a}\n";
$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'] = 'It 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} doesn\'t exist or can\'t be read by bind DN.';
$string['diag_rolegroupnotfound'] = 'Group {$a->group} for role {$a->localname} doesn\'t exist or can\'t be read by bind DN.';
$string['privacy:metadata'] = 'The LDAP server authentication plugin does not store any personal data.';
+53
View File
@@ -0,0 +1,53 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Internal library of functions for module auth_ldap
*
* @package auth_ldap
* @author David Balch <david.balch@conted.ox.ac.uk>
* @copyright 2017 The Chancellor Masters and Scholars of the University of Oxford {@link http://www.tall.ox.ac.uk/}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Get a list of system roles assignable by the current or a specified user, including their localised names.
*
* @param integer|object $user A user id or object. By default (null) checks the permissions of the current user.
* @return array $roles, each role as an array with id, shortname, localname, and settingname for the config value.
*/
function get_ldap_assignable_role_names($user = null) {
$roles = array();
if ($assignableroles = get_assignable_roles(context_system::instance(), ROLENAME_SHORT, false, $user)) {
$systemroles = role_fix_names(get_all_roles(), context_system::instance(), ROLENAME_ORIGINAL);
foreach ($assignableroles as $shortname) {
foreach ($systemroles as $systemrole) {
if ($systemrole->shortname == $shortname) {
$roles[] = array('id' => $systemrole->id,
'shortname' => $shortname,
'localname' => $systemrole->localname,
'settingname' => $shortname . 'context');
break;
}
}
}
}
return $roles;
}
+37
View File
@@ -0,0 +1,37 @@
<?php
require(__DIR__.'/../../config.php');
$PAGE->set_url('/auth/ldap/ntlmsso_attempt.php');
$PAGE->set_context(context_system::instance());
// Define variables used in page
$site = get_site();
$authsequence = get_enabled_auth_plugins(); // Auths, in sequence.
if (!in_array('ldap', $authsequence, true)) {
throw new \moodle_exception('ldap_isdisabled', 'auth');
}
$authplugin = get_auth_plugin('ldap');
if (empty($authplugin->config->ntlmsso_enabled)) {
throw new \moodle_exception('ntlmsso_isdisabled', 'auth_ldap');
}
$sesskey = sesskey();
// Display the page header. This makes redirect respect the timeout we specify
// here (and not add 3 more secs) which in turn prevents a bug in both IE 6.x
// and FF 3.x (Windows version at least) where javascript timers fire up even
// when we've already left the page that set the timer.
$loginsite = get_string("loginsite");
$PAGE->navbar->add($loginsite);
$PAGE->set_title($loginsite);
$PAGE->set_heading($site->fullname);
echo $OUTPUT->header();
$msg = '<p>'.get_string('ntlmsso_attempting', 'auth_ldap').'</p>'
. '<img width="1", height="1" '
. ' src="' . $CFG->wwwroot . '/auth/ldap/ntlmsso_magic.php?sesskey='
. $sesskey . '" />';
redirect($CFG->wwwroot . '/auth/ldap/ntlmsso_finish.php', $msg, 3);
+34
View File
@@ -0,0 +1,34 @@
<?php
require(__DIR__.'/../../config.php');
$PAGE->set_url('/auth/ldap/ntlmsso_finish.php');
$PAGE->set_context(context_system::instance());
// Define variables used in page
$site = get_site();
$authsequence = get_enabled_auth_plugins(); // Auths, in sequence.
if (!in_array('ldap', $authsequence, true)) {
throw new \moodle_exception('ldap_isdisabled', 'auth');
}
$authplugin = get_auth_plugin('ldap');
if (empty($authplugin->config->ntlmsso_enabled)) {
throw new \moodle_exception('ntlmsso_isdisabled', 'auth_ldap');
}
// If ntlmsso_finish() succeeds, then the code never returns,
// so we only worry about failure.
if (!$authplugin->ntlmsso_finish()) {
// Redirect to login, saying "don't try again!"
// Display the page header. This makes redirect respect the timeout we specify
// here (and not add 3 more secs).
$loginsite = get_string("loginsite");
$PAGE->navbar->add($loginsite);
$PAGE->set_title($loginsite);
$PAGE->set_heading($site->fullname);
echo $OUTPUT->header();
redirect($CFG->wwwroot . '/login/index.php?authldap_skipntlmsso=1',
get_string('ntlmsso_failed','auth_ldap'), 3);
}
+47
View File
@@ -0,0 +1,47 @@
<?php
// Don't let lib/setup.php set any cookies
// as we will be executing under the OS security
// context of the user we are trying to login, rather than
// of the webserver.
define('NO_MOODLE_COOKIES', true);
require(__DIR__.'/../../config.php');
$PAGE->set_context(context_system::instance());
$authsequence = get_enabled_auth_plugins(); // Auths, in sequence.
if (!in_array('ldap', $authsequence, true)) {
throw new \moodle_exception('ldap_isdisabled', 'auth');
}
$authplugin = get_auth_plugin('ldap');
if (empty($authplugin->config->ntlmsso_enabled)) {
throw new \moodle_exception('ntlmsso_isdisabled', 'auth_ldap');
}
$sesskey = required_param('sesskey', PARAM_RAW);
$file = $CFG->dirroot.'/pix/spacer.gif';
if ($authplugin->ntlmsso_magic($sesskey) && file_exists($file)) {
if (!empty($authplugin->config->ntlmsso_ie_fastpath)) {
if (core_useragent::is_ie()) {
redirect($CFG->wwwroot.'/auth/ldap/ntlmsso_finish.php');
}
}
// Serve GIF
// Type
header('Content-Type: image/gif');
header('Content-Length: '.filesize($file));
// Output file
$handle = fopen($file, 'r');
fpassthru($handle);
fclose($handle);
exit;
} else {
throw new \moodle_exception('ntlmsso_iwamagicnotenabled', 'auth_ldap');
}
+347
View File
@@ -0,0 +1,347 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Admin settings and defaults.
*
* @package auth_ldap
* @copyright 2017 Stephen Bourget
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
if ($ADMIN->fulltree) {
if (!function_exists('ldap_connect')) {
$notify = new \core\output\notification(get_string('auth_ldap_noextension', 'auth_ldap'),
\core\output\notification::NOTIFY_WARNING);
$settings->add(new admin_setting_heading('auth_ldap_noextension', '', $OUTPUT->render($notify)));
} else {
// We use a couple of custom admin settings since we need to massage the data before it is inserted into the DB.
require_once($CFG->dirroot.'/auth/ldap/classes/admin_setting_special_lowercase_configtext.php');
require_once($CFG->dirroot.'/auth/ldap/classes/admin_setting_special_contexts_configtext.php');
require_once($CFG->dirroot.'/auth/ldap/classes/admin_setting_special_ntlm_configtext.php');
// We need to use some of the Moodle LDAP constants / functions to create the list of options.
require_once($CFG->dirroot.'/auth/ldap/auth.php');
// Introductory explanation.
$settings->add(new admin_setting_heading('auth_ldap/pluginname', '',
new lang_string('auth_ldapdescription', 'auth_ldap')));
// LDAP server settings.
$settings->add(new admin_setting_heading('auth_ldap/ldapserversettings',
new lang_string('auth_ldap_server_settings', 'auth_ldap'), ''));
// Host.
$settings->add(new admin_setting_configtext('auth_ldap/host_url',
get_string('auth_ldap_host_url_key', 'auth_ldap'),
get_string('auth_ldap_host_url', 'auth_ldap'), '', PARAM_RAW_TRIMMED));
// Version.
$versions = array();
$versions[2] = '2';
$versions[3] = '3';
$settings->add(new admin_setting_configselect('auth_ldap/ldap_version',
new lang_string('auth_ldap_version_key', 'auth_ldap'),
new lang_string('auth_ldap_version', 'auth_ldap'), 3, $versions));
// Start TLS.
$yesno = array(
new lang_string('no'),
new lang_string('yes'),
);
$settings->add(new admin_setting_configselect('auth_ldap/start_tls',
new lang_string('start_tls_key', 'auth_ldap'),
new lang_string('start_tls', 'auth_ldap'), 0 , $yesno));
// Encoding.
$settings->add(new admin_setting_configtext('auth_ldap/ldapencoding',
get_string('auth_ldap_ldap_encoding_key', 'auth_ldap'),
get_string('auth_ldap_ldap_encoding', 'auth_ldap'), 'utf-8', PARAM_RAW_TRIMMED));
// Page Size. (Hide if not available).
$settings->add(new admin_setting_configtext('auth_ldap/pagesize',
get_string('pagesize_key', 'auth_ldap'),
get_string('pagesize', 'auth_ldap'), '250', PARAM_INT));
// Bind settings.
$settings->add(new admin_setting_heading('auth_ldap/ldapbindsettings',
new lang_string('auth_ldap_bind_settings', 'auth_ldap'), ''));
// Store Password in DB.
$settings->add(new admin_setting_configselect('auth_ldap/preventpassindb',
new lang_string('auth_ldap_preventpassindb_key', 'auth_ldap'),
new lang_string('auth_ldap_preventpassindb', 'auth_ldap'), 0 , $yesno));
// User ID.
$settings->add(new admin_setting_configtext('auth_ldap/bind_dn',
get_string('auth_ldap_bind_dn_key', 'auth_ldap'),
get_string('auth_ldap_bind_dn', 'auth_ldap'), '', PARAM_RAW_TRIMMED));
// Password.
$settings->add(new admin_setting_configpasswordunmask('auth_ldap/bind_pw',
get_string('auth_ldap_bind_pw_key', 'auth_ldap'),
get_string('auth_ldap_bind_pw', 'auth_ldap'), ''));
// User Lookup settings.
$settings->add(new admin_setting_heading('auth_ldap/ldapuserlookup',
new lang_string('auth_ldap_user_settings', 'auth_ldap'), ''));
// User Type.
$settings->add(new admin_setting_configselect('auth_ldap/user_type',
new lang_string('auth_ldap_user_type_key', 'auth_ldap'),
new lang_string('auth_ldap_user_type', 'auth_ldap'), 'default', ldap_supported_usertypes()));
// Contexts.
$settings->add(new auth_ldap_admin_setting_special_contexts_configtext('auth_ldap/contexts',
get_string('auth_ldap_contexts_key', 'auth_ldap'),
get_string('auth_ldap_contexts', 'auth_ldap'), '', PARAM_RAW_TRIMMED));
// Search subcontexts.
$settings->add(new admin_setting_configselect('auth_ldap/search_sub',
new lang_string('auth_ldap_search_sub_key', 'auth_ldap'),
new lang_string('auth_ldap_search_sub', 'auth_ldap'), 0 , $yesno));
// Dereference aliases.
$optderef = array();
$optderef[LDAP_DEREF_NEVER] = get_string('no');
$optderef[LDAP_DEREF_ALWAYS] = get_string('yes');
$settings->add(new admin_setting_configselect('auth_ldap/opt_deref',
new lang_string('auth_ldap_opt_deref_key', 'auth_ldap'),
new lang_string('auth_ldap_opt_deref', 'auth_ldap'), LDAP_DEREF_NEVER , $optderef));
// User attribute.
$settings->add(new auth_ldap_admin_setting_special_lowercase_configtext('auth_ldap/user_attribute',
get_string('auth_ldap_user_attribute_key', 'auth_ldap'),
get_string('auth_ldap_user_attribute', 'auth_ldap'), '', PARAM_RAW));
// Suspended attribute.
$settings->add(new auth_ldap_admin_setting_special_lowercase_configtext('auth_ldap/suspended_attribute',
get_string('auth_ldap_suspended_attribute_key', 'auth_ldap'),
get_string('auth_ldap_suspended_attribute', 'auth_ldap'), '', PARAM_RAW));
// Member attribute.
$settings->add(new auth_ldap_admin_setting_special_lowercase_configtext('auth_ldap/memberattribute',
get_string('auth_ldap_memberattribute_key', 'auth_ldap'),
get_string('auth_ldap_memberattribute', 'auth_ldap'), '', PARAM_RAW));
// Member attribute uses dn.
$settings->add(new admin_setting_configselect('auth_ldap/memberattribute_isdn',
get_string('auth_ldap_memberattribute_isdn_key', 'auth_ldap'),
get_string('auth_ldap_memberattribute_isdn', 'auth_ldap'), 0, $yesno));
// Object class.
$settings->add(new admin_setting_configtext('auth_ldap/objectclass',
get_string('auth_ldap_objectclass_key', 'auth_ldap'),
get_string('auth_ldap_objectclass', 'auth_ldap'), '', PARAM_RAW_TRIMMED));
// Force Password change Header.
$settings->add(new admin_setting_heading('auth_ldap/ldapforcepasswordchange',
new lang_string('forcechangepassword', 'auth'), ''));
// Force Password change.
$settings->add(new admin_setting_configselect('auth_ldap/forcechangepassword',
new lang_string('forcechangepassword', 'auth'),
new lang_string('forcechangepasswordfirst_help', 'auth'), 0 , $yesno));
// Standard Password Change.
$settings->add(new admin_setting_configselect('auth_ldap/stdchangepassword',
new lang_string('stdchangepassword', 'auth'), new lang_string('stdchangepassword_expl', 'auth') .' '.
get_string('stdchangepassword_explldap', 'auth'), 0 , $yesno));
// Password Type.
$passtype = array();
$passtype['plaintext'] = get_string('plaintext', 'auth');
$passtype['md5'] = get_string('md5', 'auth');
$passtype['sha1'] = get_string('sha1', 'auth');
$settings->add(new admin_setting_configselect('auth_ldap/passtype',
new lang_string('auth_ldap_passtype_key', 'auth_ldap'),
new lang_string('auth_ldap_passtype', 'auth_ldap'), 'plaintext', $passtype));
// Password change URL.
$settings->add(new admin_setting_configtext('auth_ldap/changepasswordurl',
get_string('auth_ldap_changepasswordurl_key', 'auth_ldap'),
get_string('changepasswordhelp', 'auth'), '', PARAM_URL));
// Password Expiration Header.
$settings->add(new admin_setting_heading('auth_ldap/passwordexpire',
new lang_string('auth_ldap_passwdexpire_settings', 'auth_ldap'), ''));
// Password Expiration.
// Create the description lang_string object.
$strno = get_string('no');
$strldapserver = get_string('pluginname', 'auth_ldap');
$langobject = new stdClass();
$langobject->no = $strno;
$langobject->ldapserver = $strldapserver;
$description = new lang_string('auth_ldap_expiration_desc', 'auth_ldap', $langobject);
// Now create the options.
$expiration = array();
$expiration['0'] = $strno;
$expiration['1'] = $strldapserver;
// Add the setting.
$settings->add(new admin_setting_configselect('auth_ldap/expiration',
new lang_string('auth_ldap_expiration_key', 'auth_ldap'),
$description, 0 , $expiration));
// Password Expiration warning.
$settings->add(new admin_setting_configtext('auth_ldap/expiration_warning',
get_string('auth_ldap_expiration_warning_key', 'auth_ldap'),
get_string('auth_ldap_expiration_warning_desc', 'auth_ldap'), '', PARAM_RAW));
// Password Expiration attribute.
$settings->add(new auth_ldap_admin_setting_special_lowercase_configtext('auth_ldap/expireattr',
get_string('auth_ldap_expireattr_key', 'auth_ldap'),
get_string('auth_ldap_expireattr_desc', 'auth_ldap'), '', PARAM_RAW));
// Grace Logins.
$settings->add(new admin_setting_configselect('auth_ldap/gracelogins',
new lang_string('auth_ldap_gracelogins_key', 'auth_ldap'),
new lang_string('auth_ldap_gracelogins_desc', 'auth_ldap'), 0 , $yesno));
// Grace logins attribute.
$settings->add(new auth_ldap_admin_setting_special_lowercase_configtext('auth_ldap/graceattr',
get_string('auth_ldap_gracelogin_key', 'auth_ldap'),
get_string('auth_ldap_graceattr_desc', 'auth_ldap'), '', PARAM_RAW));
// User Creation.
$settings->add(new admin_setting_heading('auth_ldap/usercreation',
new lang_string('auth_user_create', 'auth'), ''));
// Create users externally.
$settings->add(new admin_setting_configselect('auth_ldap/auth_user_create',
new lang_string('auth_ldap_auth_user_create_key', 'auth_ldap'),
new lang_string('auth_user_creation', 'auth'), 0 , $yesno));
// Context for new users.
$settings->add(new admin_setting_configtext('auth_ldap/create_context',
get_string('auth_ldap_create_context_key', 'auth_ldap'),
get_string('auth_ldap_create_context', 'auth_ldap'), '', PARAM_RAW_TRIMMED));
// System roles mapping header.
$settings->add(new admin_setting_heading('auth_ldap/systemrolemapping',
new lang_string('systemrolemapping', 'auth_ldap'), ''));
// Create system role mapping field for each assignable system role.
$roles = get_ldap_assignable_role_names();
foreach ($roles as $role) {
// Before we can add this setting we need to check a few things.
// A) It does not exceed 100 characters otherwise it will break the DB as the 'name' field
// in the 'config_plugins' table is a varchar(100).
// B) The setting name does not contain hyphens. If it does then it will fail the check
// in parse_setting_name() and everything will explode. Role short names are validated
// against PARAM_ALPHANUMEXT which is similar to the regex used in parse_setting_name()
// except it also allows hyphens.
// Instead of shortening the name and removing/replacing the hyphens we are showing a warning.
// If we were to manipulate the setting name by removing the hyphens we may get conflicts, eg
// 'thisisashortname' and 'this-is-a-short-name'. The same applies for shortening the setting name.
if (core_text::strlen($role['settingname']) > 100 || !preg_match('/^[a-zA-Z0-9_]+$/', $role['settingname'])) {
$url = new moodle_url('/admin/roles/define.php', array('action' => 'edit', 'roleid' => $role['id']));
$a = (object)['rolename' => $role['localname'], 'shortname' => $role['shortname'], 'charlimit' => 93,
'link' => $url->out()];
$settings->add(new admin_setting_heading('auth_ldap/role_not_mapped_' . sha1($role['settingname']), '',
get_string('cannotmaprole', 'auth_ldap', $a)));
} else {
$settings->add(new admin_setting_configtext('auth_ldap/' . $role['settingname'],
get_string('auth_ldap_rolecontext', 'auth_ldap', $role),
get_string('auth_ldap_rolecontext_help', 'auth_ldap', $role), '', PARAM_RAW_TRIMMED));
}
}
// User Account Sync.
$settings->add(new admin_setting_heading('auth_ldap/syncusers',
new lang_string('auth_sync_script', 'auth'), ''));
// Remove external user.
$deleteopt = array();
$deleteopt[AUTH_REMOVEUSER_KEEP] = get_string('auth_remove_keep', 'auth');
$deleteopt[AUTH_REMOVEUSER_SUSPEND] = get_string('auth_remove_suspend', 'auth');
$deleteopt[AUTH_REMOVEUSER_FULLDELETE] = get_string('auth_remove_delete', 'auth');
$settings->add(new admin_setting_configselect('auth_ldap/removeuser',
new lang_string('auth_remove_user_key', 'auth'),
new lang_string('auth_remove_user', 'auth'), AUTH_REMOVEUSER_KEEP, $deleteopt));
// Sync Suspension.
$settings->add(new admin_setting_configselect('auth_ldap/sync_suspended',
new lang_string('auth_sync_suspended_key', 'auth'),
new lang_string('auth_sync_suspended', 'auth'), 0 , $yesno));
// Sync update users chunk size.
$settings->add(new admin_setting_configtext('auth_ldap/sync_updateuserchunk',
new lang_string('sync_updateuserchunk_key', 'auth_ldap'),
new lang_string('sync_updateuserchunk', 'auth_ldap'), 1000, PARAM_INT));
// NTLM SSO Header.
$settings->add(new admin_setting_heading('auth_ldap/ntlm',
new lang_string('auth_ntlmsso', 'auth_ldap'), ''));
// Enable NTLM.
$settings->add(new admin_setting_configselect('auth_ldap/ntlmsso_enabled',
new lang_string('auth_ntlmsso_enabled_key', 'auth_ldap'),
new lang_string('auth_ntlmsso_enabled', 'auth_ldap'), 0 , $yesno));
// Subnet.
$settings->add(new admin_setting_configtext('auth_ldap/ntlmsso_subnet',
get_string('auth_ntlmsso_subnet_key', 'auth_ldap'),
get_string('auth_ntlmsso_subnet', 'auth_ldap'), '', PARAM_RAW_TRIMMED));
// NTLM Fast Path.
$fastpathoptions = array();
$fastpathoptions[AUTH_NTLM_FASTPATH_YESFORM] = get_string('auth_ntlmsso_ie_fastpath_yesform', 'auth_ldap');
$fastpathoptions[AUTH_NTLM_FASTPATH_YESATTEMPT] = get_string('auth_ntlmsso_ie_fastpath_yesattempt', 'auth_ldap');
$fastpathoptions[AUTH_NTLM_FASTPATH_ATTEMPT] = get_string('auth_ntlmsso_ie_fastpath_attempt', 'auth_ldap');
$settings->add(new admin_setting_configselect('auth_ldap/ntlmsso_ie_fastpath',
new lang_string('auth_ntlmsso_ie_fastpath_key', 'auth_ldap'),
new lang_string('auth_ntlmsso_ie_fastpath', 'auth_ldap'),
AUTH_NTLM_FASTPATH_ATTEMPT, $fastpathoptions));
// Authentication type.
$types = array();
$types['ntlm'] = 'NTLM';
$types['kerberos'] = 'Kerberos';
$settings->add(new admin_setting_configselect('auth_ldap/ntlmsso_type',
new lang_string('auth_ntlmsso_type_key', 'auth_ldap'),
new lang_string('auth_ntlmsso_type', 'auth_ldap'), 'ntlm', $types));
// Remote Username format.
$settings->add(new auth_ldap_admin_setting_special_ntlm_configtext('auth_ldap/ntlmsso_remoteuserformat',
get_string('auth_ntlmsso_remoteuserformat_key', 'auth_ldap'),
get_string('auth_ntlmsso_remoteuserformat', 'auth_ldap'), '', PARAM_RAW_TRIMMED));
}
// Display locking / mapping of profile fields.
$authplugin = get_auth_plugin('ldap');
$help = get_string('auth_ldapextrafields', 'auth_ldap');
$help .= get_string('auth_updatelocal_expl', 'auth');
$help .= get_string('auth_fieldlock_expl', 'auth');
$help .= get_string('auth_updateremote_expl', 'auth');
$help .= '<hr />';
$help .= get_string('auth_updateremote_ldap', 'auth');
display_auth_lock_options($settings, $authplugin->authtype, $authplugin->userfields,
$help, true, true, $authplugin->get_custom_user_profile_fields());
}
+622
View File
@@ -0,0 +1,622 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace auth_ldap;
/**
* LDAP authentication plugin tests.
*
* NOTE: in order to execute this test you need to set up
* OpenLDAP server with core, cosine, nis and internet schemas
* and add configuration constants to config.php or phpunit.xml configuration file:
*
* define('TEST_AUTH_LDAP_HOST_URL', 'ldap://127.0.0.1');
* define('TEST_AUTH_LDAP_BIND_DN', 'cn=someuser,dc=example,dc=local');
* define('TEST_AUTH_LDAP_BIND_PW', 'somepassword');
* define('TEST_AUTH_LDAP_DOMAIN', 'dc=example,dc=local');
*
* @package auth_ldap
* @copyright 2013 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use auth_plugin_ldap;
use auth_ldap\task\{
sync_task,
asynchronous_sync_task,
};
/**
* LDAP authentication plugin tests.
*
* @package auth_ldap
* @copyright 2013 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class auth_ldap_test extends \advanced_testcase {
public static function setUpBeforeClass(): void {
global $CFG;
parent::setUpBeforeClass();
require_once($CFG->dirroot . '/auth/ldap/auth.php');
require_once($CFG->libdir . '/ldaplib.php');
}
/**
* Data provider for auth_ldap tests
*
* Used to ensure that all the paged stuff works properly, irrespectively
* of the pagesize configured (that implies all the chunking and paging
* built in the plugis is doing its work consistently). Both searching and
* not searching within subcontexts.
*
* @return array[]
*/
public function auth_ldap_provider() {
$pagesizes = [1, 3, 5, 1000];
$subcontexts = [0, 1];
$combinations = [];
foreach ($pagesizes as $pagesize) {
foreach ($subcontexts as $subcontext) {
$combinations["pagesize {$pagesize}, subcontexts {$subcontext}"] = [$pagesize, $subcontext];
}
}
return $combinations;
}
/**
* General auth_ldap testcase
*
* @dataProvider auth_ldap_provider
* @param int $pagesize Value to be configured in settings controlling page size.
* @param int $subcontext Value to be configured in settings controlling searching in subcontexts.
*/
public function test_auth_ldap(int $pagesize, int $subcontext): void {
global $DB;
if (!extension_loaded('ldap')) {
$this->markTestSkipped('LDAP extension is not loaded.');
}
$this->resetAfterTest();
if (!defined('TEST_AUTH_LDAP_HOST_URL') or !defined('TEST_AUTH_LDAP_BIND_DN') or !defined('TEST_AUTH_LDAP_BIND_PW') or !defined('TEST_AUTH_LDAP_DOMAIN')) {
$this->markTestSkipped('External LDAP test server not configured.');
}
// Make sure we can connect the server.
$debuginfo = '';
if (!$connection = ldap_connect_moodle(TEST_AUTH_LDAP_HOST_URL, 3, 'rfc2307', TEST_AUTH_LDAP_BIND_DN, TEST_AUTH_LDAP_BIND_PW, LDAP_DEREF_NEVER, $debuginfo, false)) {
$this->markTestSkipped('Can not connect to LDAP test server: '.$debuginfo);
}
$this->enable_plugin();
// Create new empty test container.
$topdn = 'dc=moodletest,'.TEST_AUTH_LDAP_DOMAIN;
$this->recursive_delete($connection, TEST_AUTH_LDAP_DOMAIN, 'dc=moodletest');
$o = array();
$o['objectClass'] = array('dcObject', 'organizationalUnit');
$o['dc'] = 'moodletest';
$o['ou'] = 'MOODLETEST';
if (!ldap_add($connection, 'dc=moodletest,'.TEST_AUTH_LDAP_DOMAIN, $o)) {
$this->markTestSkipped('Can not create test LDAP container.');
}
// Create a few users.
$o = array();
$o['objectClass'] = array('organizationalUnit');
$o['ou'] = 'users';
ldap_add($connection, 'ou='.$o['ou'].','.$topdn, $o);
$createdusers = array();
for ($i=1; $i<=5; $i++) {
$this->create_ldap_user($connection, $topdn, $i);
$createdusers[] = 'username' . $i;
}
// Set up creators group.
$assignedroles = array('username1', 'username2');
$o = array();
$o['objectClass'] = array('posixGroup');
$o['cn'] = 'creators';
$o['gidNumber'] = 1;
$o['memberUid'] = $assignedroles;
ldap_add($connection, 'cn='.$o['cn'].','.$topdn, $o);
$creatorrole = $DB->get_record('role', array('shortname'=>'coursecreator'));
$this->assertNotEmpty($creatorrole);
// Configure the plugin a bit.
set_config('host_url', TEST_AUTH_LDAP_HOST_URL, 'auth_ldap');
set_config('start_tls', 0, 'auth_ldap');
set_config('ldap_version', 3, 'auth_ldap');
set_config('ldapencoding', 'utf-8', 'auth_ldap');
set_config('pagesize', $pagesize, 'auth_ldap');
set_config('bind_dn', TEST_AUTH_LDAP_BIND_DN, 'auth_ldap');
set_config('bind_pw', TEST_AUTH_LDAP_BIND_PW, 'auth_ldap');
set_config('user_type', 'rfc2307', 'auth_ldap');
set_config('contexts', 'ou=users,'.$topdn, 'auth_ldap');
set_config('search_sub', $subcontext, 'auth_ldap');
set_config('opt_deref', LDAP_DEREF_NEVER, 'auth_ldap');
set_config('user_attribute', 'cn', 'auth_ldap');
set_config('memberattribute', 'memberuid', 'auth_ldap');
set_config('memberattribute_isdn', 0, 'auth_ldap');
set_config('coursecreatorcontext', 'cn=creators,'.$topdn, 'auth_ldap');
set_config('removeuser', AUTH_REMOVEUSER_KEEP, 'auth_ldap');
set_config('field_map_email', 'mail', 'auth_ldap');
set_config('field_updatelocal_email', 'oncreate', 'auth_ldap');
set_config('field_updateremote_email', '0', 'auth_ldap');
set_config('field_lock_email', 'unlocked', 'auth_ldap');
set_config('field_map_firstname', 'givenName', 'auth_ldap');
set_config('field_updatelocal_firstname', 'oncreate', 'auth_ldap');
set_config('field_updateremote_firstname', '0', 'auth_ldap');
set_config('field_lock_firstname', 'unlocked', 'auth_ldap');
set_config('field_map_lastname', 'sn', 'auth_ldap');
set_config('field_updatelocal_lastname', 'oncreate', 'auth_ldap');
set_config('field_updateremote_lastname', '0', 'auth_ldap');
set_config('field_lock_lastname', 'unlocked', 'auth_ldap');
$this->assertEquals(2, $DB->count_records('user'));
$this->assertEquals(0, $DB->count_records('role_assignments'));
/** @var \auth_plugin_ldap $auth */
$auth = get_auth_plugin('ldap');
ob_start();
$sink = $this->redirectEvents();
$auth->sync_users(true);
$events = $sink->get_events();
$sink->close();
ob_end_clean();
// Check events, 5 users created with 2 users having roles.
$this->assertCount(7, $events);
foreach ($events as $index => $event) {
$username = $DB->get_field('user', 'username', array('id' => $event->relateduserid)); // Get username.
if ($event->eventname === '\core\event\user_created') {
$this->assertContains($username, $createdusers);
unset($events[$index]); // Remove matching event.
} else if ($event->eventname === '\core\event\role_assigned') {
$this->assertContains($username, $assignedroles);
unset($events[$index]); // Remove matching event.
} else {
$this->fail('Unexpected event found: ' . $event->eventname);
}
}
// If all the user_created and role_assigned events have matched
// then the $events array should be now empty.
$this->assertCount(0, $events);
$this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap')));
$this->assertEquals(2, $DB->count_records('role_assignments'));
$this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id)));
for ($i=1; $i<=5; $i++) {
$this->assertTrue($DB->record_exists('user', array('username'=>'username'.$i, 'email'=>'user'.$i.'@example.com', 'firstname'=>'Firstname'.$i, 'lastname'=>'Lastname'.$i)));
}
$this->delete_ldap_user($connection, $topdn, 1);
ob_start();
$sink = $this->redirectEvents();
$auth->sync_users(true);
$events = $sink->get_events();
$sink->close();
ob_end_clean();
// Check events, no new event.
$this->assertCount(0, $events);
$this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap')));
$this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
$this->assertEquals(0, $DB->count_records('user', array('deleted'=>1)));
$this->assertEquals(2, $DB->count_records('role_assignments'));
$this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id)));
set_config('removeuser', AUTH_REMOVEUSER_SUSPEND, 'auth_ldap');
/** @var \auth_plugin_ldap $auth */
$auth = get_auth_plugin('ldap');
ob_start();
$sink = $this->redirectEvents();
$auth->sync_users(true);
$events = $sink->get_events();
$sink->close();
ob_end_clean();
// Check events, 1 user got updated.
$this->assertCount(1, $events);
$event = reset($events);
$this->assertInstanceOf('\core\event\user_updated', $event);
$this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap')));
$this->assertEquals(0, $DB->count_records('user', array('auth'=>'nologin', 'username'=>'username1')));
$this->assertEquals(1, $DB->count_records('user', array('auth'=>'ldap', 'suspended'=>'1', 'username'=>'username1')));
$this->assertEquals(0, $DB->count_records('user', array('deleted'=>1)));
$this->assertEquals(2, $DB->count_records('role_assignments'));
$this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id)));
$this->create_ldap_user($connection, $topdn, 1);
ob_start();
$sink = $this->redirectEvents();
$auth->sync_users(true);
$events = $sink->get_events();
$sink->close();
ob_end_clean();
// Check events, 1 user got updated.
$this->assertCount(1, $events);
$event = reset($events);
$this->assertInstanceOf('\core\event\user_updated', $event);
$this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap')));
$this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
$this->assertEquals(0, $DB->count_records('user', array('deleted'=>1)));
$this->assertEquals(2, $DB->count_records('role_assignments'));
$this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id)));
$DB->set_field('user', 'auth', 'nologin', array('username'=>'username1'));
ob_start();
$sink = $this->redirectEvents();
$auth->sync_users(true);
$events = $sink->get_events();
$sink->close();
ob_end_clean();
// Check events, 1 user got updated.
$this->assertCount(1, $events);
$event = reset($events);
$this->assertInstanceOf('\core\event\user_updated', $event);
$this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap')));
$this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
$this->assertEquals(0, $DB->count_records('user', array('deleted'=>1)));
$this->assertEquals(2, $DB->count_records('role_assignments'));
$this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id)));
set_config('removeuser', AUTH_REMOVEUSER_FULLDELETE, 'auth_ldap');
/** @var \auth_plugin_ldap $auth */
$auth = get_auth_plugin('ldap');
$this->delete_ldap_user($connection, $topdn, 1);
ob_start();
$sink = $this->redirectEvents();
$auth->sync_users(true);
$events = $sink->get_events();
$sink->close();
ob_end_clean();
// Check events, 2 events role_unassigned and user_deleted.
$this->assertCount(2, $events);
$event = array_pop($events);
$this->assertInstanceOf('\core\event\user_deleted', $event);
$event = array_pop($events);
$this->assertInstanceOf('\core\event\role_unassigned', $event);
$this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap')));
$this->assertEquals(0, $DB->count_records('user', array('username'=>'username1')));
$this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
$this->assertEquals(1, $DB->count_records('user', array('deleted'=>1)));
$this->assertEquals(1, $DB->count_records('role_assignments'));
$this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id)));
$this->create_ldap_user($connection, $topdn, 1);
ob_start();
$sink = $this->redirectEvents();
$auth->sync_users(true);
$events = $sink->get_events();
$sink->close();
ob_end_clean();
// Check events, 2 events role_assigned and user_created.
$this->assertCount(2, $events);
$event = array_pop($events);
$this->assertInstanceOf('\core\event\role_assigned', $event);
$event = array_pop($events);
$this->assertInstanceOf('\core\event\user_created', $event);
$this->assertEquals(6, $DB->count_records('user', array('auth'=>'ldap')));
$this->assertEquals(1, $DB->count_records('user', array('username'=>'username1')));
$this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
$this->assertEquals(1, $DB->count_records('user', array('deleted'=>1)));
$this->assertEquals(2, $DB->count_records('role_assignments'));
$this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id)));
// Let's test syncing users in chunks of '1'.
set_config('field_updatelocal_email', 'onlogin', 'auth_ldap');
set_config('sync_updateuserchunk', 1, 'auth_ldap');
/** @var auth_plugin_ldap $auth */
$auth = get_auth_plugin('ldap');
$count = 0;
ob_start();
$auth->sync_users_update_callback(function ($users, $updatekeys) use (&$count) {
$count++;
});
ob_end_clean();
// After updating in chunks of '1', we should have counted more than one update.
$this->assertGreaterThan(1, $count);
ob_start();
\core\cron::setup_user();
$cron = new sync_task();
$cron->execute();
$this->runAdhocTasks('\auth_ldap\task\asynchronous_sync_task');
$output = ob_get_contents();
ob_end_clean();
// Use Reflection to make protected constants available.
$rp = new \ReflectionClassConstant(sync_task::class, 'MTRACE_MSG');
$synctaskmsg = $rp->getValue();
$rp = new \ReflectionClassConstant(asynchronous_sync_task::class, 'MTRACE_MSG');
$asynctaskmsg = $rp->getValue();
$this->assertMatchesRegularExpression(
sprintf('/%s.*%s/s', $synctaskmsg, $asynctaskmsg),
$output
);
$this->recursive_delete($connection, TEST_AUTH_LDAP_DOMAIN, 'dc=moodletest');
ldap_close($connection);
}
/**
* Test logging in via LDAP calls a user_loggedin event.
*/
public function test_ldap_user_loggedin_event(): void {
global $CFG, $DB, $USER;
$this->resetAfterTest();
$this->assertFalse(isloggedin());
$user = $DB->get_record('user', array('username'=>'admin'));
// Note: we are just going to trigger the function that calls the event,
// not actually perform a LDAP login, for the sake of sanity.
$ldap = new \auth_plugin_ldap();
// Set the key for the cache flag we want to set which is used by LDAP.
set_cache_flag($ldap->pluginconfig . '/ntlmsess', sesskey(), $user->username, AUTH_NTLMTIMEOUT);
// We are going to need to set the sesskey as the user's password in order for the LDAP log in to work.
update_internal_user_password($user, sesskey());
// The function ntlmsso_finish is responsible for triggering the event, so call it directly and catch the event.
$sink = $this->redirectEvents();
// We need to supress this function call, or else we will get the message "session_regenerate_id(): Cannot
// regenerate session id - headers already sent" as the ntlmsso_finish function calls complete_user_login
@$ldap->ntlmsso_finish();
$events = $sink->get_events();
$sink->close();
// Check that the event is valid.
$this->assertCount(1, $events);
$event = reset($events);
$this->assertInstanceOf('\core\event\user_loggedin', $event);
$this->assertEquals('user', $event->objecttable);
$this->assertEquals('2', $event->objectid);
$this->assertEquals(\context_system::instance()->id, $event->contextid);
}
/**
* Test logging in via LDAP calls a user_loggedin event.
*/
public function test_ldap_user_signup(): void {
global $CFG, $DB;
// User to create.
$user = array(
'username' => 'usersignuptest1',
'password' => 'Moodle2014!',
'idnumber' => 'idsignuptest1',
'firstname' => 'First Name User Test 1',
'lastname' => 'Last Name User Test 1',
'middlename' => 'Middle Name User Test 1',
'lastnamephonetic' => '最後のお名前のテスト一号',
'firstnamephonetic' => 'お名前のテスト一号',
'alternatename' => 'Alternate Name User Test 1',
'email' => 'usersignuptest1@example.com',
'description' => 'This is a description for user 1',
'city' => 'Perth',
'country' => 'AU',
'mnethostid' => $CFG->mnet_localhost_id,
'auth' => 'ldap'
);
if (!extension_loaded('ldap')) {
$this->markTestSkipped('LDAP extension is not loaded.');
}
$this->resetAfterTest();
if (!defined('TEST_AUTH_LDAP_HOST_URL') or !defined('TEST_AUTH_LDAP_BIND_DN') or !defined('TEST_AUTH_LDAP_BIND_PW') or !defined('TEST_AUTH_LDAP_DOMAIN')) {
$this->markTestSkipped('External LDAP test server not configured.');
}
// Make sure we can connect the server.
$debuginfo = '';
if (!$connection = ldap_connect_moodle(TEST_AUTH_LDAP_HOST_URL, 3, 'rfc2307', TEST_AUTH_LDAP_BIND_DN, TEST_AUTH_LDAP_BIND_PW, LDAP_DEREF_NEVER, $debuginfo, false)) {
$this->markTestSkipped('Can not connect to LDAP test server: '.$debuginfo);
}
$this->enable_plugin();
// Create new empty test container.
$topdn = 'dc=moodletest,'.TEST_AUTH_LDAP_DOMAIN;
$this->recursive_delete($connection, TEST_AUTH_LDAP_DOMAIN, 'dc=moodletest');
$o = array();
$o['objectClass'] = array('dcObject', 'organizationalUnit');
$o['dc'] = 'moodletest';
$o['ou'] = 'MOODLETEST';
if (!ldap_add($connection, 'dc=moodletest,'.TEST_AUTH_LDAP_DOMAIN, $o)) {
$this->markTestSkipped('Can not create test LDAP container.');
}
// Create a few users.
$o = array();
$o['objectClass'] = array('organizationalUnit');
$o['ou'] = 'users';
ldap_add($connection, 'ou='.$o['ou'].','.$topdn, $o);
// Configure the plugin a bit.
set_config('host_url', TEST_AUTH_LDAP_HOST_URL, 'auth_ldap');
set_config('start_tls', 0, 'auth_ldap');
set_config('ldap_version', 3, 'auth_ldap');
set_config('ldapencoding', 'utf-8', 'auth_ldap');
set_config('pagesize', '2', 'auth_ldap');
set_config('bind_dn', TEST_AUTH_LDAP_BIND_DN, 'auth_ldap');
set_config('bind_pw', TEST_AUTH_LDAP_BIND_PW, 'auth_ldap');
set_config('user_type', 'rfc2307', 'auth_ldap');
set_config('contexts', 'ou=users,'.$topdn, 'auth_ldap');
set_config('search_sub', 0, 'auth_ldap');
set_config('opt_deref', LDAP_DEREF_NEVER, 'auth_ldap');
set_config('user_attribute', 'cn', 'auth_ldap');
set_config('memberattribute', 'memberuid', 'auth_ldap');
set_config('memberattribute_isdn', 0, 'auth_ldap');
set_config('creators', 'cn=creators,'.$topdn, 'auth_ldap');
set_config('removeuser', AUTH_REMOVEUSER_KEEP, 'auth_ldap');
set_config('field_map_email', 'mail', 'auth_ldap');
set_config('field_updatelocal_email', 'oncreate', 'auth_ldap');
set_config('field_updateremote_email', '0', 'auth_ldap');
set_config('field_lock_email', 'unlocked', 'auth_ldap');
set_config('field_map_firstname', 'givenName', 'auth_ldap');
set_config('field_updatelocal_firstname', 'oncreate', 'auth_ldap');
set_config('field_updateremote_firstname', '0', 'auth_ldap');
set_config('field_lock_firstname', 'unlocked', 'auth_ldap');
set_config('field_map_lastname', 'sn', 'auth_ldap');
set_config('field_updatelocal_lastname', 'oncreate', 'auth_ldap');
set_config('field_updateremote_lastname', '0', 'auth_ldap');
set_config('field_lock_lastname', 'unlocked', 'auth_ldap');
set_config('passtype', 'md5', 'auth_ldap');
set_config('create_context', 'ou=users,'.$topdn, 'auth_ldap');
$this->assertEquals(2, $DB->count_records('user'));
$this->assertEquals(0, $DB->count_records('role_assignments'));
/** @var \auth_plugin_ldap $auth */
$auth = get_auth_plugin('ldap');
$sink = $this->redirectEvents();
$mailsink = $this->redirectEmails();
$auth->user_signup((object)$user, false);
$this->assertEquals(1, $mailsink->count());
$events = $sink->get_events();
$sink->close();
// Verify 2 events get generated.
$this->assertCount(2, $events);
// Get record from db.
$dbuser = $DB->get_record('user', array('username' => $user['username']));
$user['id'] = $dbuser->id;
// Last event is user_created.
$event = array_pop($events);
$this->assertInstanceOf('\core\event\user_created', $event);
$this->assertEquals($user['id'], $event->objectid);
$this->assertEquals(\context_user::instance($user['id']), $event->get_context());
// First event is user_password_updated.
$event = array_pop($events);
$this->assertInstanceOf('\core\event\user_password_updated', $event);
$this->assertEventContextNotUsed($event);
// Delete user which we just created.
ldap_delete($connection, 'cn='.$user['username'].',ou=users,'.$topdn);
}
protected function create_ldap_user($connection, $topdn, $i) {
$o = array();
$o['objectClass'] = array('inetOrgPerson', 'organizationalPerson', 'person', 'posixAccount');
$o['cn'] = 'username'.$i;
$o['sn'] = 'Lastname'.$i;
$o['givenName'] = 'Firstname'.$i;
$o['uid'] = $o['cn'];
$o['uidnumber'] = 2000+$i;
$o['gidNumber'] = 1000+$i;
$o['homeDirectory'] = '/';
$o['mail'] = 'user'.$i.'@example.com';
$o['userPassword'] = 'pass'.$i;
ldap_add($connection, 'cn='.$o['cn'].',ou=users,'.$topdn, $o);
}
protected function delete_ldap_user($connection, $topdn, $i) {
ldap_delete($connection, 'cn=username'.$i.',ou=users,'.$topdn);
}
protected function enable_plugin() {
$auths = get_enabled_auth_plugins();
if (!in_array('ldap', $auths)) {
$auths[] = 'ldap';
}
set_config('auth', implode(',', $auths));
}
protected function recursive_delete($connection, $dn, $filter) {
if ($res = ldap_list($connection, $dn, $filter, array('dn'))) {
$info = ldap_get_entries($connection, $res);
ldap_free_result($res);
if ($info['count'] > 0) {
if ($res = ldap_search($connection, "$filter,$dn", 'cn=*', array('dn'))) {
$info = ldap_get_entries($connection, $res);
ldap_free_result($res);
foreach ($info as $i) {
if (isset($i['dn'])) {
ldap_delete($connection, $i['dn']);
}
}
}
if ($res = ldap_search($connection, "$filter,$dn", 'ou=*', array('dn'))) {
$info = ldap_get_entries($connection, $res);
ldap_free_result($res);
foreach ($info as $i) {
if (isset($i['dn']) and $info[0]['dn'] != $i['dn']) {
ldap_delete($connection, $i['dn']);
}
}
}
ldap_delete($connection, "$filter,$dn");
}
}
}
}
+15
View File
@@ -0,0 +1,15 @@
This files describes API changes in the auth_ldap code.
=== 3.4 ===
* The "auth_ldap/coursecreators" setting was replaced with dynamically generated "auth_ldap/<role>context" settings,
migrating any existing value to a new setting in this style.
=== 3.3 ===
* The config.html file was migrated to use the admin settings API.
The identifier for configuration data stored in config_plugins table was converted from 'auth/ldap' to 'auth_ldap'.
=== 2.9.1 ===
* auth_plugin_ldap::update_user_record() accepts an additional (optional) param
to trigger update event.
+30
View File
@@ -0,0 +1,30 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Version details
*
* @package auth_ldap
* @author Martin Dougiamas
* @author Iñaki Arenaza
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2024042200; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2024041600; // Requires this Moodle version.
$plugin->component = 'auth_ldap'; // Full name of the plugin (used for diagnostics)