From: martinlanghoff Date: Thu, 4 Jan 2007 04:52:42 +0000 (+0000) Subject: multiauth: migrated all files to the new OO API, written new API documentation X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=b9ddb2d5eaebab5bbcaee6710afc312a3ef006b9;p=moodle.git multiauth: migrated all files to the new OO API, written new API documentation Author: Martin Langhoff --- diff --git a/auth/README b/auth/README index 251d28ddbf..3caa42f3b0 100644 --- a/auth/README +++ b/auth/README @@ -6,12 +6,17 @@ check that a user has provided a correct - username, and - password. -Even when external forms of authentication are being -used, Moodle still maintains the internal "user" table -with all the associated information about that user such -as name, email address and so on. +Even when external forms of authentication are being used, Moodle still +maintains the internal "user" table with all the associated information about +that user such as name, email address and so on. -The active method is set by the admin on the Configuration page. +Multiauthentication in Moodle 1.8 +------------------------------------- + +The active methods are set by the admin on the Configuration page. Multiple +authentication plugins can now be used and ordered in a fail-through sequence. +One plugin can be selected for interactive login as well (which will need to be +part of the enabled plugin sequence). email - authentication by email (DEFAULT METHOD) @@ -84,27 +89,127 @@ db - Uses an external database to check username/password a new Moodle account is created ------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- Authentication API +------------------ + +Each authentication plugin is now contained in a subfolder as a class definition +in the auth.php file. For instance, the LDAP authentication plugin is the class +called auth_plugin_ldap defined in: + + /auth/ldap/auth.php + +To instantiate the class, there is a function in lib/moodlelib called +get_auth_plugin() that does the work for you: + + $ldapauth = get_auth_plugin('ldap'); + +If an auth is not specified, get_auth_plugin() will return you the auth plugin +defined in the $CFG->auth variable. + +Auth plugin classes are pretty basic. They contain the same functions that were +previously in each plugin's lib.php file, but refactored to become class +methods, and tweaked to reference the plugin's instantiated config to get at the +settings, rather than the global $CFG variable. + +Configuration +----------------- + +All auth plugins must have a config property that contains the name value pairs +from the config_plugins table. This is populated using the get_config() function +in the constructor. The settings keys have also had the "auth_" prefix, as well +as the auth plugin name, trimmed. For instance, what used to be + + echo $CFG->auth_ldapversion; + +is now accessed as + + echo $ldapauth->config->version; + +Authentication settings have been moved to the config_plugins database table, +with the plugin field set to "auth/foo" (for instance, "auth/ldap"). + +Upgrading from Moodle 1.7 +----------------------------- + +Moodle will upgrade the old auth settings (in $CFG->auth_foobar where foo is the +auth plugin and bar is the setting) to the new style in the config_plugin +database table. + +Method Names +----------------- + +When the functions from lib.php were ported to methods in auth.php, the "auth_" +prefix was dropped. For instance, calls to + + auth_user_login($user, $pass); + +now become + + $ldapauth->user_login($user, $pass); + +this also avoids having to worry about which auth/lib file to include since +Moodle takes care of it for you when you create an instance with +get_auth_plugin(). + +Code Usage +----------------- + +Code calling auth plugins can use method_exists() to determine plugin +functionality, much in the same way that function_exists() was used until now. +In addition, auth plugins provide some methods by default that can be called: + +user_login($username, $password) + This is the primary method that is used by the authenticate_user_login() + function in moodlelib.php. This method should return a boolean indicating + whether or not the username and password authenticate successfully. + +is_internal() + Returns true if this authentication plugin is "internal" (which means that + Moodle stores the users' passwords and other details in the local Moodle + database). + +can_change_password() + Returns true if the plugin can change the users' passwords. + +change_password_url() + Returns the URL for changing the users' passwords, or false if the default + URL can be used. + +user_update_password($username, $newpassword) + Updates the user's password. -This file describes Moodle interface functions to authentication modules. +config_form() + Displays the configuration form for the auth plugin, for use in the admin + pages. -Most of functions are from ldap-authentication module and are not implemented (yet?) -on other modules. Please feel free to extend other modules to support same features -or roll your own module. +process_config() + Saves the auth plugin's configuration to the database. -Some of new function are still tested and are not documented here yet. +Other Methods +------------------ +Most of functions are from ldap-authentication module and are not implemented +(yet?) on other modules. Please feel free to extend other modules to support +same features or roll your own module. +Some of the new functions are still to be tested and are not documented here +yet. AUTHENTICATION -Basic fuctions to authenticate users with external db + +Basic fuctions to authenticate users with external db. Mandatory: - - auth_user_login ($username, $password) - + + auth_plugin_foo() + + Constructor. At the least, it populates config member variable with settings + from the Moodle database. It makes sense to put other startup code here. + + user_login($username, $password) + Authenticate username, password with userdatabase. Returns: @@ -112,17 +217,18 @@ Mandatory: and false if they don't Optional: - - auth_get_userinfo($username) - + + get_userinfo($username) + Query other userinformation from database. Returns: Userinformation in array ( name => value, .... or false in case of error - auth_validate_form(&$form, &$err) - + + validate_form(&$form, &$err) + Validate form data. Returns: @@ -131,7 +237,7 @@ Optional: COURSE CREATING - auth_iscreator($username) + iscreator($username) should user have rights to create courses @@ -145,15 +251,16 @@ Functions that enable usercreation, activation and deactivation from moodle to external database - auth_user_exists ($username) - + user_exists ($username) + Checks if given username exist on external db Returns: true if given usernname exist or false - - auth_user_create ($userobject,$plainpass) - + + + user_create ($userobject,$plainpass) + Creates new user to external db. User should be created in inactive stage until confirmed by email. @@ -161,18 +268,18 @@ from moodle to external database True on success otherwise false - auth_user_activate ($username) - + user_activate ($username) + activate new user after email-address is confirmed Returns: True on success otherwise false - auth_user_disable ($username) { - + user_disable ($username) { + deactivate user in external db. - + Returns: True on success otherwise false @@ -180,16 +287,16 @@ from moodle to external database USER INFORMATION AND SYNCRONIZATION - auth_get_userlist () + get_userlist () Get list of usernames in external db. Returns: All usernames in array or false on error. - - auth_get_users($filter='*') - + + get_users($filter='*') + Get ALL USEROBJECTS FROM EXTERNAL DB. Returns: diff --git a/auth/README2 b/auth/README2 new file mode 100644 index 0000000000..40ba27490d --- /dev/null +++ b/auth/README2 @@ -0,0 +1,92 @@ +AUTHENTICATION PLUGINS +---------------------- +Each authentication plugin is now contained in a subfolder as a class definition +in the auth.php file. For instance, the LDAP authentication plugin is the class +called auth_plugin_ldap defined in: + + /auth/ldap/auth.php + +To instantiate the class, there is a function in lib/moodlelib called +get_auth_plugin() that does the work for you: + + $ldapauth = get_auth_plugin('ldap'); + +If an auth is not specified, get_auth_plugin() will return you the auth plugin +defined in the $CFG->auth variable. + +Auth plugin classes are pretty basic. They contain the same functions that were +previously in each plugin's lib.php file, but refactored to become class +methods, and tweaked to reference the plugin's instantiated config to get at the +settings, rather than the global $CFG variable. + +Configuration +----------------- + +All auth plugins must have a config property that contains the name value pairs +from the config_plugins table. This is populated using the get_config() function +in the constructor. The settings keys have also had the "auth_" prefix, as well +as the auth plugin name, trimmed. For instance, what used to be + + echo $CFG->auth_ldapversion; + +is now accessed as + + echo $ldapauth->config->version; + +Authentication settings have been moved to the config_plugins database table, +with the plugin field set to "auth/foo" (for instance, "auth/ldap"). + +Method Names +----------------- + +When the functions from lib.php were ported to methods in auth.php, the "auth_" +prefix was dropped. For instance, calls to + + auth_user_login($user, $pass); + +now become + + $ldapauth->user_login($user, $pass); + +this also avoids having to worry about which auth/lib file to include since +Moodle takes care of it for you when you create an instance with +get_auth_plugin(). + +Code Use +----------------- + +Code calling auth plugins can use method_exists() to determine plugin +functionality, much in the same way that function_exists() was used until now. +In addition, auth plugins provide some methods by default that can be called: + +user_login($username, $password) + This is the primary method that is used by the authenticate_user_login() + function in moodlelib.php. This method should return a boolean indicating + whether or not the username and password authenticate successfully. + +is_internal() + Returns true if this authentication plugin is "internal" (which means that + Moodle stores the users' passwords and other details in the local Moodle + database). + +can_change_password() + Returns true if the plugin can change the users' passwords. + +change_password_url() + Returns the URL for changing the users' passwords, or false if the default + URL can be used. + +Other Methods +----------------- + +get_userinfo() + This method should return an array of fields from the authentication source + for the given username. + +Upgrading from Moodle 1.7 +----------------------------- + +Moodle will upgrade the old auth settings (in $CFG->auth_foobar where foo is the +auth plugin and bar is the setting) to the new style in the config_plugin +database table. + diff --git a/auth/authlib.php b/auth/authlib.php new file mode 100644 index 0000000000..9aa2e7548e --- /dev/null +++ b/auth/authlib.php @@ -0,0 +1,33 @@ + diff --git a/auth/cas/auth.php b/auth/cas/auth.php new file mode 100644 index 0000000000..cc716cd6bb --- /dev/null +++ b/auth/cas/auth.php @@ -0,0 +1,298 @@ +config = get_config('auth/cas'); + } + + /** + * Authenticates user againt CAS with LDAP. + * Returns true if the username and password work and false if they are + * wrong or don't exist. + * + * @param string $username The username + * @param string $password The password + * @returns bool Authentication success or failure. + */ + function user_login ($username, $password) { + + // TODO: find how to get at LDAP funcs + + global $CFG; + + // don't allow blank usernames or passwords + if (!$username or !$password) { + return false; + } + + // CAS specific + if ($CFG->auth == "cas" and !empty($this->config->enabled)) { + if ($this->config->create_user == '0') { + if (record_exists('user', 'username', $username)) { + return true; + } + else { + return false; + } + } + else { + return true; + } + } + + $ldap_connection = ldap_connect(); + + if ($ldap_connection) { + $ldap_user_dn = auth_ldap_find_userdn($ldap_connection, $username); + + // if ldap_user_dn is empty, user does not exist + if (!$ldap_user_dn) { + ldap_close($ldap_connection); + return false; + } + + // Try to bind with current username and password + $ldap_login = ldap_bind($ldap_connection, $ldap_user_dn, $password); + ldap_close($ldap_connection); + if ($ldap_login) { + if ($this->config->create_user=='0') { //cas specific + if (record_exists('user', 'username', $username)) { + return true; + }else{ + return false; + } + }else{ + return true; + } + } + } else { + ldap_close($ldap_connection); + error("LDAP part of CAS-module cannot connect to server: $CFG->ldap_host_url"); + } + return false; + } + + /** + * Authenticates user against CAS from screen login + * the user doesn't have a CAS Ticket yet. + * + * Returns an object user if the username and password work + * and nothing if they don't + * + * @param string $username + * @param string $password + * + */ + function authenticate_user_login ($username, $password) { + + // TODO: fix SOMEOTHER:: + + global $CFG; + // FIX ME: $cas_validate is not global + $cas_validate = true; + phpCAS::client($this->config->casversion, $this->config->hostname, (int) $this->config->port, $this->config->baseuri); + phpCAS::setLang($this->config->language); + phpCAS::forceAuthentication(); + if ($this->config->create_user == '0') { + if (record_exists('user', 'username', phpCAS::getUser())) { + // TODO::SOMEOTHER:: + $user = authenticate_user_login(phpCAS::getUser(), 'cas'); + } + else { + // login as guest if CAS but not Moodle and not automatic creation + if ($CFG->guestloginbutton) { + // TODO::SOMEOTHER:: + $user = authenticate_user_login('guest', 'guest'); + } + else { + // TODO::SOMEOTHER:: + $user = authenticate_user_login(phpCAS::getUser(), 'cas'); + } + } + } + else { + // TODO::SOMEOTHER:: + $user = authenticate_user_login(phpCAS::getUser(), 'cas'); + } + return $user; + } + + /** + * Authenticates user against CAS when first call of Moodle + * if already in CAS (cookie with the CAS ticket), don't have to log again (SSO) + * + * Returns an object user if the username and password work + * and nothing if they don't + * + * @param object $user + * + */ + function automatic_authenticate ($user='') { + + // TODO: fix SOMEOTHER:: + + global $CFG; + // FIX ME: $cas_validate is not global, but it works anyway ;-) + if (!$cas_validate) { + $cas_validate = true; + phpCAS::client($this->config->casversion, $this->config->hostname, (int) $this->config->port, $this->config->baseuri); + phpCAS::setLang($this->config->language); + $cas_user_exist = phpCAS::checkAuthentication(); + if (!$cas_user_exist and !$CFG->guestloginbutton) { + $cas_user_exist=phpCAS::forceAuthentication(); + } + if ($cas_user_exist) { + if ($this->config->create_user == '0') { + if (record_exists('user', 'username', phpCAS::getUser())) { + // TODO::SOMEOTHER:: + $user = authenticate_user_login(phpCAS::getUser(), 'cas'); + } + else { + // login as guest if CAS but not Moodle and not automatic creation + if ($CFG->guestloginbutton) { + // TODO::SOMEOTHER:: + $user = authenticate_user_login('guest', 'guest'); + } + else { + // TODO::SOMEOTHER:: + $user = authenticate_user_login(phpCAS::getUser(), 'cas'); + } + } + } + else { + // TODO::SOMEOTHER:: + $user = authenticate_user_login(phpCAS::getUser(), 'cas'); + } + return $user; + } + else { + return; + } + } + else { + return $user; + } + } + + /** + * Returns true if this authentication plugin is 'internal'. + * + * @returns bool + */ + function is_internal() { + return false; + } + + /** + * Returns true if this authentication plugin can change the user's + * password. + * + * @returns bool + */ + function can_change_password() { + return false; + } + + /** + * Prints a form for configuring this authentication plugin. + * + * This function is called from admin/auth.php, and outputs a full page with + * a form for configuring this plugin. + * + * @param array $page An object containing all the data for this page. + */ + function config_form($config, $err) { + include 'config.html'; + } + + /** + * Returns the URL for changing the user's pw, or false if the default can + * be used. + * + * @returns bool + */ + function change_password_url() { + return $this->config->changepasswordurl; + } + + /** + * Processes and stores configuration data for this authentication plugin. + */ + function process_config($config) { + // set to defaults if undefined + if (!isset ($config->hostname)) { + $config->hostname = ''; + } + if (!isset ($config->port)) { + $config->port = ''; + } + if (!isset ($config->casversion)) { + $config->casversion = ''; + } + if (!isset ($config->baseuri)) { + $config->baseuri = ''; + } + if (!isset ($config->language)) { + $config->language = ''; + } + if (!isset ($config->use_cas)) { + $config->use_cas = ''; + } + if (!isset ($config->auth_user_create)) { + $config->auth_user_create = ''; + } + if (!isset ($config->create_user)) { + $config->create_user = '0'; + } + if (!isset($config->changepasswordurl)) { + $config->changepasswordurl = ''; + } + + // save CAS settings + set_config('hostname', $config->hostname, 'auth/cas'); + set_config('port', $config->port, 'auth/cas'); + set_config('casversion', $config->casversion, 'auth/cas'); + set_config('baseuri', $config->baseuri, 'auth/cas'); + set_config('language', $config->language, 'auth/cas'); + set_config('use_cas', $config->use_cas, 'auth/cas'); + set_config('auth_user_create', $config->auth_user_create, 'auth/cas'); + set_config('create_user', $config->create_user, 'auth/cas'); + set_config('changepasswordurl', $config->changepasswordurl, 'auth/cas'); + + // save LDAP settings + // TODO: Do we want the CAS LDAP settings to be separate from the LDAP settings? + $ldapauth = get_auth_plugin('ldap'); + $ldapauth->process_config($config); + + return true; + } + +} + +?> diff --git a/auth/cas/auth_ldap_sync_users.php b/auth/cas/auth_ldap_sync_users.php index 29e74d41dc..2e7316151c 100644 --- a/auth/cas/auth_ldap_sync_users.php +++ b/auth/cas/auth_ldap_sync_users.php @@ -22,7 +22,7 @@ */ -if(!empty($_SERVER['GATEWAY_INTERFACE'])){ +if (!empty($_SERVER['GATEWAY_INTERFACE'])) { error_log("should not be called from apache!"); exit; } @@ -32,9 +32,10 @@ require_once(dirname(dirname(dirname(__FILE__))).'/config.php'); // global moodl require_once($CFG->dirroot.'/course/lib.php'); require_once($CFG->dirroot.'/lib/blocklib.php'); require_once($CFG->dirroot.'/mod/resource/lib.php'); -require_once($CFG->dirroot.'/auth/cas/lib.php'); //cas specific require_once($CFG->dirroot.'/mod/forum/lib.php'); +require_once($CFG->dirroot.'/lib/moodlelib.php'); $CFG->debug=10; -auth_sync_users(1000, true ); +$casauth = get_auth_plugin('cas'); +$casauth->sync_users(1000, true); ?> \ No newline at end of file diff --git a/auth/cas/config.html b/auth/cas/config.html index d6e1f91009..9d2084e787 100644 --- a/auth/cas/config.html +++ b/auth/cas/config.html @@ -1,118 +1,187 @@ cas_hostname)) { - $config->cas_hostname = ""; + + global $CFG; + require_once 'languages.php'; + + $createoptions[0] = get_string("no"); + $createoptions[1] = get_string("yes"); + + // set to defaults if undefined + if (!isset ($config->hostname)) { + $config->hostname = ''; } - if (!isset ($config->cas_port)) { - $config->cas_port = ""; + if (!isset ($config->port)) { + $config->port = ''; } - if (!isset ($config->cas_version)) { - $config->cas_version = ""; + if (!isset ($config->casversion)) { + $config->casversion = ''; } - if (!isset ($config->cas_baseuri)) { - $config->cas_baseuri = ""; + if (!isset ($config->baseuri)) { + $config->baseuri = ''; } - if (!isset ($config->cas_language)) { - $config->cas_language = ""; + if (!isset ($config->language)) { + $config->language = ''; } - if (!isset ($config->cas_use_cas)) { - $config->cas_use_cas = ""; + if (!isset ($config->use_cas)) { + $config->use_cas = ''; } - if (!isset ($config->cas_create_user)) { - $config->cas_create_user = "0"; + if (!isset ($config->auth_user_create)) { + $config->auth_user_create = '0'; + } + if (!isset ($config->create_user)) { + $config->create_user = '0'; + } + if (!isset($config->changepasswordurl)) { + $config->changepasswordurl = ''; } -?> +?> + + - + + - - - + + + + - + + + + + + + + - + - + - + - + - - + + - + + -dirroot.'/auth/ldap/config.html'); -?> + + + + + +
-

+

cas_enabled:use_cas: - cas_enabled, get_string("no"),"","");?> - - + unset($options); + $options[1] = get_string('yes'); + choose_from_menu ($options, 'use_cas', $config->use_cas, get_string('no'), '', ''); + + ?>
cas_hostname: - - -
hostname: - + +
cas_baseuri:baseuri: - - + +
port: - + +
cas_port:casversion: - - - - + +
cas_version:language: - - - - + language, ''); + + ?>
cas_language:
auth_user_create: - cas_language, "");?> + auth_user_create, ''); + if (isset($err['auth_user_create'])) { + formerr($err['auth_user_create']); + } + + ?> - +
cas_create_user:create_user: - cas_create_user, "");?> - - + create_user, ''); + + ?>
changepasswordurl: + + +
+config_form(get_config('auth/ldap'), $err); + +?> diff --git a/auth/cas/index_form.html b/auth/cas/index_form.html index 74554831ce..0cc529d5cd 100644 --- a/auth/cas/index_form.html +++ b/auth/cas/index_form.html @@ -65,11 +65,9 @@ print_string("loginstepsnone"); break; default: + $authplugin = get_auth_plugin($CFG->auth); echo format_text($CFG->auth_instructions); - if (!function_exists('auth_user_login')) { - require_once("../auth/$CFG->auth/lib.php"); - } - if (!empty($CFG->auth_user_create) and function_exists('auth_user_create') ){ + if (!empty($authplugin->config->user_create) and method_exists($authplugin, 'user_create')) { ?>
diff --git a/auth/cas/lib.php b/auth/cas/lib.php deleted file mode 100644 index 29d0aee4f7..0000000000 --- a/auth/cas/lib.php +++ /dev/null @@ -1,171 +0,0 @@ -dirroot.'/config.php'); -require_once($CFG->dirroot.'/auth/ldap/lib.php'); -require_once($CFG->dirroot.'/lib/cas/CAS.php'); -$cas_validate=false; - -/** - * replace the ldap auth_user_login function - * authenticates user againt CAS with ldap - * Returns true if the username and password work - * and false if they don't - * - * @param string $username - * @param string $password - * -*/ -function cas_ldap_auth_user_login ($username, $password) { -/// Returns true if the username and password work -/// and false if they don't - - global $CFG; - if (!$username or !$password) { // Don't allow blank usernames or passwords - return false; - } - - if ($CFG->auth == "cas" && !empty($CFG->cas_enabled)){ //cas specific - if ($CFG->cas_create_user=="0"){ - if (record_exists('user', 'username', $username)){ - return true; - }else{ - return false; - } - }else{ - return true; - } - } - - $ldap_connection = auth_ldap_connect(); - - if ($ldap_connection) { - $ldap_user_dn = auth_ldap_find_userdn($ldap_connection, $username); - - //if ldap_user_dn is empty, user does not exist - if(!$ldap_user_dn){ - ldap_close($ldap_connection); - return false; - } - - // Try to bind with current username and password - $ldap_login = ldap_bind($ldap_connection, $ldap_user_dn, $password); - ldap_close($ldap_connection); - if ($ldap_login) { - if ($CFG->cas_create_user=="0"){ //cas specific - if (record_exists('user', 'username', $username)){ - return true; - }else{ - return false; - } - }else{ - return true; - } - } - } else { - ldap_close($ldap_connection); - error("LDAP part of CAS-module cannot connect to server: $CFG->ldap_host_url"); - } - return false; -} - -/** - * authenticates user against CAS from screen login - * the user doesn't have a CAS Ticket yet. - * - * Returns an object user if the username and password work - * and nothing if they don't - * - * @param string $username - * @param string $password - * -*/ -function cas_authenticate_user_login ($username, $password) { - - global $CFG; - // FIX ME: $cas_validate is not global - $cas_validate=true; - phpCAS::client($CFG->cas_version,$CFG->cas_hostname,(int)$CFG->cas_port,$CFG->cas_baseuri); - phpCAS::setLang($CFG->cas_language); - phpCAS::forceAuthentication(); - if ($CFG->cas_create_user=="0"){ - if (record_exists('user', 'username', phpCAS::getUser())) { - $user = authenticate_user_login(phpCAS::getUser(), 'cas'); - }else{ - //login as guest if CAS but not Moodle and not automatic creation - if ($CFG->guestloginbutton){ - $user = authenticate_user_login('guest', 'guest'); - }else{ - $user = authenticate_user_login(phpCAS::getUser(), 'cas'); - } - } - }else{ - $user = authenticate_user_login(phpCAS::getUser(), 'cas'); - } - return $user; -} - -/** - * authenticates user against CAS when first call of Moodle - * if already in CAS (cookie with the CAS ticket), don't have to log again (SSO) - * - * Returns an object user if the username and password work - * and nothing if they don't - * - * @param object $user - * -*/ -function cas_automatic_authenticate ($user="") { - global $CFG; - // FIX ME: $cas_validate is not global, but it works anyway ;-) - if (!$cas_validate){ - $cas_validate=true; - phpCAS::client($CFG->cas_version,$CFG->cas_hostname,(int)$CFG->cas_port,$CFG->cas_baseuri); - phpCAS::setLang($CFG->cas_language); - $cas_user_exist=phpCAS::checkAuthentication(); - if (!$cas_user_exist && !$CFG->guestloginbutton){ - $cas_user_exist=phpCAS::forceAuthentication(); - } - if ($cas_user_exist){ - if ($CFG->cas_create_user=="0"){ - if (record_exists('user', 'username', phpCAS::getUser())) { - $user = authenticate_user_login(phpCAS::getUser(), 'cas'); - }else{ - //login as guest if CAS but not Moodle and not automatic creation - if ($CFG->guestloginbutton){ - $user = authenticate_user_login('guest', 'guest'); - }else{ - $user = authenticate_user_login(phpCAS::getUser(), 'cas'); - } - } - }else{ - - $user = authenticate_user_login(phpCAS::getUser(), 'cas'); - } - return $user; - }else{ - return; - } - - }else{ - return $user; - } -} - - -?> \ No newline at end of file diff --git a/auth/cas/login.php b/auth/cas/login.php index d7d09a40f7..504f68d95b 100644 --- a/auth/cas/login.php +++ b/auth/cas/login.php @@ -24,6 +24,8 @@ defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); } $loginsite = get_string("loginsite"); + $casauth = get_auth_plugin('cas'); + $ldapauth = get_auth_plugin('ldap'); $frm = false; @@ -59,9 +61,8 @@ defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); $user = false; /// Can't log in as guest if guest button is disabled $frm = false; } else if (!$user) { - if ($CFG->auth == "cas" && $frm->username != 'guest'){ /// Cas SSO case - require_once($CFG->dirroot.'/auth/cas/lib.php'); - $user = cas_authenticate_user_login($frm->username, $frm->password); + if ($CFG->auth == "cas" && $frm->username != 'guest') { /// Cas SSO case + $user = $casauth->authenticate_user_login($frm->username, $frm->password); }else{ $user = authenticate_user_login($frm->username, $frm->password); } @@ -101,18 +102,19 @@ defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); $SESSION->justloggedin = true; // Restore the calendar filters, if saved - if(intval(get_user_preferences('calendar_persistflt', 0))) { + if (intval(get_user_preferences('calendar_persistflt', 0))) { include_once($CFG->dirroot.'/calendar/lib.php'); calendar_set_filters_status(get_user_preferences('calendar_savedflt', 0xff)); } //Select password change url - if (is_internal_auth() || $CFG->{'auth_'.$USER->auth.'_stdchangepassword'}){ + $userauth = get_auth_plugin($USER->auth); + if (method_exists($userauth, 'can_change_password') and $userauth->can_change_password()) { $passwordchangeurl=$CFG->wwwroot.'/login/change_password.php'; } // check whether the user should be changing password - if (get_user_preferences('auth_forcepasswordchange', false)){ + if (get_user_preferences('auth_forcepasswordchange', false)) { if (isset($passwordchangeurl)) { redirect($passwordchangeurl); } else { @@ -140,9 +142,8 @@ defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); // check if user password has expired // Currently supported only for ldap-authentication module - if (isset($CFG->ldap_expiration) && $CFG->ldap_expiration == 1 ) { - if (function_exists('auth_password_expire')){ - $days2expire = auth_password_expire($USER->username); + if ($ldapauth->config->expiration == 1) { + $days2expire = $ldapauth->password_expire($USER->username); if (intval($days2expire) > 0 && intval($days2expire) < intval($CFG->{$USER->auth.'_expiration_warning'})) { print_header("$site->fullname: $loginsite", "$site->fullname", $loginsite, $focus, "", true, "
$langmenu
"); notice_yesno(get_string('auth_passwordwillexpire', 'auth', $days2expire), $passwordchangeurl, $urltogo); @@ -153,8 +154,7 @@ defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); notice_yesno(get_string('auth_passwordisexpired', 'auth'), $passwordchangeurl, $urltogo); print_footer(); exit; - } - } + } } reset_login_count(); @@ -166,8 +166,7 @@ defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); exit; } else { - if ($CFG->auth == "cas" ){ /// CAS error login - require_once($CFG->dirroot.'/auth/cas/lib.php'); + if ($CFG->auth == "cas" ) { /// CAS error login $errormsg = get_string("invalidcaslogin"); phpCAS::logout("$CFG->wwwroot/auth/cas/forbidden.php"); }else{ @@ -175,8 +174,7 @@ defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); } } } - require_once($CFG->dirroot.'/auth/cas/lib.php'); - $user=cas_automatic_authenticate($user); + $user = $casauth->automatic_authenticate($user); if ($user) { if (! $user->confirmed ) { // they never confirmed via email print_header(get_string("mustconfirm"), get_string("mustconfirm") ); @@ -210,18 +208,19 @@ defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); $SESSION->justloggedin = true; // Restore the calendar filters, if saved - if(intval(get_user_preferences('calendar_persistflt', 0))) { + if (intval(get_user_preferences('calendar_persistflt', 0))) { include_once($CFG->dirroot.'/calendar/lib.php'); calendar_set_filters_status(get_user_preferences('calendar_savedflt', 0xff)); } //Select password change url - if (is_internal_auth() || $CFG->{'auth_'.$USER->auth.'_stdchangepassword'}){ + $userauth = get_auth_plugin($USER->auth); + if (method_exists($userauth, 'can_change_password') and $userauth->can_change_password()) { $passwordchangeurl=$CFG->wwwroot.'/login/change_password.php'; } // check whether the user should be changing password - if (get_user_preferences('auth_forcepasswordchange', false)){ + if (get_user_preferences('auth_forcepasswordchange', false)) { if (isset($passwordchangeurl)) { redirect($passwordchangeurl); } else { @@ -249,9 +248,8 @@ defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); // check if user password has expired // Currently supported only for ldap-authentication module - if (isset($CFG->ldap_expiration) && $CFG->ldap_expiration == 1 ) { - if (function_exists('auth_password_expire')){ - $days2expire = auth_password_expire($USER->username); + if ($ldapauth->config->expiration == 1) { + $days2expire = $ldapauth->password_expire($USER->username); if (intval($days2expire) > 0 && intval($days2expire) < intval($CFG->{$USER->auth.'_expiration_warning'})) { print_header("$site->fullname: $loginsite", "$site->fullname", $loginsite, $focus, "", true, "
$langmenu
"); notice_yesno(get_string('auth_passwordwillexpire', 'auth', $days2expire), $passwordchangeurl, $urltogo); @@ -262,8 +260,7 @@ defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); notice_yesno(get_string('auth_passwordisexpired', 'auth'), $passwordchangeurl, $urltogo); print_footer(); exit; - } - } + } } reset_login_count(); @@ -274,7 +271,7 @@ defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); exit; } else { - if(!$CFG->guestloginbutton){ + if (!$CFG->guestloginbutton) { $errormsg = get_string("invalidcaslogin"); phpCAS::logout("$CFG->wwwroot/auth/cas/forbidden.php"); } diff --git a/auth/cas/logout.php b/auth/cas/logout.php index 9cb57a8692..5f0a5cc87a 100644 --- a/auth/cas/logout.php +++ b/auth/cas/logout.php @@ -4,7 +4,7 @@ defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); global $CFG; - if ($CFG->cas_logout){ + if ($CFG->cas_logout) { require_once($CFG->dirroot.'/config.php'); include_once($CFG->dirroot.'/lib/cas/CAS.php'); phpCAS::client($CFG->cas_version,$CFG->cas_hostname,(int)$CFG->cas_port,$CFG->cas_baseuri); diff --git a/auth/db/auth.php b/auth/db/auth.php new file mode 100644 index 0000000000..f1f126e8ec --- /dev/null +++ b/auth/db/auth.php @@ -0,0 +1,560 @@ +config = get_config('auth/db'); + } + + /** + * Returns true if the username and password work and false if they are + * wrong or don't exist. + * + * @param string $username The username + * @param string $password The password + * @returns bool Authentication success or failure. + */ + function user_login ($username, $password) { + + global $CFG; + + // This is a hack to workaround what seems to be a bug in ADOdb with accessing + // two databases of the same kind ... it seems to get confused when trying to access + // the first database again, after having accessed the second. + // The following hack will make the database explicit which keeps it happy + // This seems to broke postgesql so .. + + $prefix = $CFG->prefix.''; // Remember it. The '' is to prevent PHP5 reference.. see bug 3223 + + if ($CFG->dbtype != 'postgres7') { + $CFG->prefix = $CFG->dbname.$CFG->prefix; + } + + // Connect to the external database + $authdb = &ADONewConnection($this->config->type); + $authdb->PConnect($this->config->host, $this->config->user, $this->config->pass, $this->config->name); + $authdb->SetFetchMode(ADODB_FETCH_ASSOC); + + if ($this->config->passtype === 'internal') { + // lookup username externally, but resolve + // password locally -- to support backend that + // don't track passwords + $rs = $authdb->Execute("SELECT * FROM {$this->config->table} + WHERE {$this->config->fielduser} = '$username' "); + $authdb->Close(); + + if (!$rs) { + notify("Could not connect to the specified authentication database..."); + + return false; + } + + if ( $rs->RecordCount() ) { + // user exists exterally + // check username/password internally + if ($user = get_record('user', 'username', $username)) { + return validate_internal_user_password($user, $password); + } + } else { + // user does not exist externally + return false; + } + + } else { + // normal case: use external db for passwords + + if ($this->config->passtype === 'md5') { // Re-format password accordingly + $password = md5($password); + } + + $rs = $authdb->Execute("SELECT * FROM {$this->config->table} + WHERE {$this->config->fielduser} = '$username' + AND {$this->config->fieldpass} = '$password' "); + $authdb->Close(); + + $CFG->prefix = $prefix; + + if (!$rs) { + notify("Could not connect to the specified authentication database..."); + return false; + } + + if ( $rs->RecordCount() ) { + return true; + } else { + return false; + } + + } + } + + + /** + * Reads any other information for a user from external database, + * then returns it in an array + */ + function get_userinfo($username) { + + global $CFG; + + ADOLoadCode($this->config->type); + $authdb = &ADONewConnection(); + $authdb->PConnect($this->config->host, $this->config->user, $this->config->pass, $this->config->name); + $authdb->SetFetchMode(ADODB_FETCH_ASSOC); + + $fields = array("firstname", "lastname", "email", "phone1", "phone2", + "department", "address", "city", "country", "description", + "idnumber", "lang"); + + $result = array(); + + foreach ($fields as $field) { + if ($this->config->{'field_map_' . $field}) { + if ($rs = $authdb->Execute("SELECT " . $this->config->{'field_map_' . $field} . " FROM {$this->config->table} + WHERE {$this->config->fielduser} = '$username'")) { + if ( $rs->RecordCount() == 1 ) { + if (!empty($CFG->unicodedb)) { + $result["$field"] = addslashes(stripslashes($rs->fields[0])); + } else { + $result["$field"] = addslashes(stripslashes(utf8_decode($rs->fields[0]))); + } + } + } + } + } + $authdb->Close(); + + return $result; + } + + + function user_update_password($username, $newpassword) { + + if ($this->config->passtype === 'internal') { + return set_field('user', 'password', md5($newpassword), 'username', $username); + } else { + // we should have never been called! + return false; + } + } + + /** + * syncronizes user fron external db to moodle user table + * + * Sync shouid be done by using idnumber attribute, not username. + * You need to pass firstsync parameter to function to fill in + * idnumbers if they dont exists in moodle user table. + * + * Syncing users removes (disables) users that dont exists anymore in external db. + * Creates new users and updates coursecreator status of users. + * + * @param bool $do_updates Optional: set to true to force an update of existing accounts + * + * This implementation is simpler but less scalable than the one found in the LDAP module. + * + */ + function sync_users ($do_updates=0) { + + global $CFG; + $pcfg = get_config('auth/db'); + + /// + /// list external users + /// + $userlist = $this->get_userlist(); + $quoteduserlist = implode("', '", $userlist); + $quoteduserlist = "'$quoteduserlist'"; + + /// + /// delete obsolete internal users + /// + + // find obsolete users + if (count($userlist)) { + $sql = 'SELECT u.id, u.username + FROM ' . $CFG->prefix .'user u + WHERE u.auth=\'db\' AND u.deleted=\'0\' AND u.username NOT IN (' . $quoteduserlist . ')'; + } else { + $sql = 'SELECT u.id, u.username + FROM ' . $CFG->prefix .'user u + WHERE u.auth=\'db\' AND u.deleted=\'0\' '; + } + $remove_users = get_records_sql($sql); + + if (!empty($remove_users)) { + print "User entries to remove: ". count($remove_users) . "\n"; + + begin_sql(); + foreach ($remove_users as $user) { + //following is copy pasted from admin/user.php + //maybe this should moved to function in lib/datalib.php + unset($updateuser); + $updateuser->id = $user->id; + $updateuser->deleted = "1"; + $updateuser->timemodified = time(); + if (update_record("user", $updateuser)) { + // unenrol_student($user->id); // From all courses + // remove_teacher($user->id); // From all courses + // remove_admin($user->id); + delete_records('role_assignments', 'userid', $user->id); // unassign all roles + notify(get_string("deletedactivity", "", fullname($user, true)) ); + } else { + notify(get_string("deletednot", "", fullname($user, true))); + } + //copy pasted part ends + } + commit_sql(); + } + unset($remove_users); // free mem! + + if (!count($userlist)) { + // exit right here + // nothing else to do + return true; + } + + /// + /// update existing accounts + /// + if ($do_updates) { + // narrow down what fields we need to update + $all_keys = array_keys(get_object_vars($this->config)); + $updatekeys = array(); + foreach ($all_keys as $key) { + if (preg_match('/^field_updatelocal_(.+)$/',$key, $match)) { + if ($this->config->{$key} === 'onlogin') { + array_push($updatekeys, $match[1]); // the actual key name + } + } + } + // print_r($all_keys); print_r($updatekeys); + unset($all_keys); unset($key); + + // only go ahead if we actually + // have fields to update locally + if (!empty($updatekeys)) { + $sql = 'SELECT u.id, u.username + FROM ' . $CFG->prefix .'user u + WHERE u.auth=\'db\' AND u.deleted=\'0\' AND u.username IN (' . $quoteduserlist . ')'; + $update_users = get_records_sql($sql); + + foreach ($update_users as $user) { + $this->db_update_user_record($user->username, $updatekeys); + } + unset($update_users); // free memory + } + } + + + /// + /// create missing accounts + /// + // NOTE: this is very memory intensive + // and generally inefficient + $sql = 'SELECT u.id, u.username + FROM ' . $CFG->prefix .'user u + WHERE u.auth=\'db\' AND u.deleted=\'0\''; + + $users = get_records_sql($sql); + + // simplify down to usernames + $usernames = array(); + foreach ($users as $user) { + array_push($usernames, $user->username); + } + unset($users); + + $add_users = array_diff($userlist, $usernames); + unset($usernames); + + if (!empty($add_users)) { + print "User entries to add: ". count($add_users). "\n"; + begin_sql(); + foreach($add_users as $user) { + $username = $user; + $user = $this->get_userinfo_asobj($user); + + // prep a few params + $user->username = $username; + $user->modified = time(); + $user->confirmed = 1; + $user->auth = 'db'; + + // insert it + $old_debug=$CFG->debug; + $CFG->debug=10; + + // maybe the user has been deleted before + if ($old_user = get_record('user', 'username', $user->username, 'deleted', 1)) { + $user->id = $old_user->id; + set_field('user', 'deleted', 0, 'username', $user->username); + echo "Revived user $user->username id $user->id\n"; + } elseif ($id=insert_record ('user',$user)) { // it is truly a new user + echo "inserted user $user->username id $id\n"; + $user->id = $id; + // if relevant, tag for password generation + if ($this->config->passtype === 'internal') { + set_user_preference('auth_forcepasswordchange', 1, $id); + set_user_preference('create_password', 1, $id); + } + } else { + echo "error inserting user $user->username \n"; + } + $CFG->debug=$old_debug; + } + commit_sql(); + unset($add_users); // free mem + } + return true; + } + + function user_exists ($username) { + $authdb = &ADONewConnection($this->config->type); + $authdb->PConnect($this->config->host, $this->config->user, $this->config->pass, $this->config->name); + $authdb->SetFetchMode(ADODB_FETCH_ASSOC); + + $rs = $authdb->Execute("SELECT * FROM {$this->config->table} + WHERE {$this->config->fielduser} = '$username' "); + $authdb->Close(); + + if (!$rs) { + notify("Could not connect to the specified authentication database..."); + return false; + } + + if ( $rs->RecordCount() ) { + // user exists exterally + // check username/password internally + // ?? there is no $password variable, so why?? + /*if ($user = get_record('user', 'username', $username)) { + return ($user->password == md5($password)); + }*/ + return $rs->RecordCount(); + } else { + // user does not exist externally + return false; + } + } + + + function get_userlist() { + // Connect to the external database + $authdb = &ADONewConnection($this->config->type); + $authdb->PConnect($this->config->host,$this->config->user,$this->config->pass,$this->config->name); + $authdb->SetFetchMode(ADODB_FETCH_ASSOC); + + // fetch userlist + $rs = $authdb->Execute("SELECT {$this->config->fielduser} AS username + FROM {$this->config->table} "); + $authdb->Close(); + + if (!$rs) { + notify("Could not connect to the specified authentication database..."); + return false; + } + + if ( $rs->RecordCount() ) { + $userlist = array(); + while ($rec = $rs->FetchRow()) { + array_push($userlist, $rec['username']); + } + return $userlist; + } else { + return array(); + } + } + + /** + * reads userinformation from DB and return it in an object + * + * @param string $username username + * @return array + */ + function get_userinfo_asobj($username) { + $user_array = truncate_userinfo($this->get_userinfo($username)); + $user = new object; + foreach($user_array as $key=>$value) { + $user->{$key} = $value; + } + return $user; + } + + /* + * will update a local user record from an external source. + * is a lighter version of the one in moodlelib -- won't do + * expensive ops such as enrolment + * + * If you don't pass $updatekeys, there is a performance hit and + * values removed from DB won't be removed from moodle. + */ + function db_update_user_record($username, $updatekeys=false) { + + $pcfg = get_config('auth/db'); + + //just in case check text case + $username = trim(moodle_strtolower($username)); + + // get the current user record + $user = get_record('user', 'username', $username); + if (empty($user)) { // trouble + error_log("Cannot update non-existent user: $username"); + die; + } + + // TODO: this had a function_exists() - now we have a $this + if ($newinfo = $this->get_userinfo($username)) { + $newinfo = truncate_userinfo($newinfo); + + if (empty($updatekeys)) { // all keys? this does not support removing values + $updatekeys = array_keys($newinfo); + } + + foreach ($updatekeys as $key) { + unset($value); + if (isset($newinfo[$key])) { + $value = $newinfo[$key]; + $value = addslashes(stripslashes($value)); // Just in case + } else { + $value = ''; + } + if (!empty($this->config->{'field_updatelocal_' . $key})) { + if ($user->{$key} != $value) { // only update if it's changed + set_field('user', $key, $value, 'username', $username); + } + } + } + } + return get_record_select("user", "username = '$username' AND deleted <> '1'"); + } + + // A chance to validate form data, and last chance to + // do stuff before it is inserted in config_plugin + function validate_form(&$form, &$err) { + if ($form['passtype'] === 'internal') { + $this->config->changepasswordurl = ''; + set_config('changepasswordurl', '', 'auth/db'); + } + return true; + } + + /** + * Returns true if this authentication plugin is 'internal'. + * + * @returns bool + */ + function is_internal() { + return false; + } + + /** + * Returns true if this authentication plugin can change the user's + * password. + * + * @returns bool + */ + function can_change_password() { + return ($this->config->passtype === 'internal'); + } + + /** + * Returns the URL for changing the user's pw, or false if the default can + * be used. + * + * @returns bool + */ + function change_password_url() { + return $this->config->changepasswordurl; + } + + /** + * Prints a form for configuring this authentication plugin. + * + * This function is called from admin/auth.php, and outputs a full page with + * a form for configuring this plugin. + * + * @param array $page An object containing all the data for this page. + */ + function config_form($config, $err) { + include "config.html"; + } + + /** + * Processes and stores configuration data for this authentication plugin. + */ + function process_config($config) { + // set to defaults if undefined + if (!isset($config->host)) { + $config->host = "localhost"; + } + if (!isset($config->type)) { + $config->type = "mysql"; + } + if (!isset($config->name)) { + $config->name = ""; + } + if (!isset($config->user)) { + $config->user = ""; + } + if (!isset($config->pass)) { + $config->pass = ""; + } + if (!isset($config->table)) { + $config->table = ""; + } + if (!isset($config->fielduser)) { + $config->fielduser = ""; + } + if (!isset($config->fieldpass)) { + $config->fieldpass = ""; + } + if (!isset($config->passtype)) { + $config->passtype = "plaintext"; + } + if (!isset($config->changepasswordurl)) { + $config->changepasswordurl = ''; + } + + // save settings + set_config('host', $config->host, 'auth/db'); + set_config('type', $config->type, 'auth/db'); + set_config('name', $config->name, 'auth/db'); + set_config('user', $config->user, 'auth/db'); + set_config('pass', $config->pass, 'auth/db'); + set_config('table', $config->table, 'auth/db'); + set_config('fielduser', $config->fielduser, 'auth/db'); + set_config('fieldpass', $config->fieldpass, 'auth/db'); + set_config('passtype', $config->passtype, 'auth/db'); + set_config('changepasswordurl', $config->changepasswordurl, 'auth/db'); + + return true; + } + +} + +?> diff --git a/auth/db/auth_db_sync_users.php b/auth/db/auth_db_sync_users.php index 3e05508f7e..c9bcac97a9 100644 --- a/auth/db/auth_db_sync_users.php +++ b/auth/db/auth_db_sync_users.php @@ -21,7 +21,7 @@ */ -if(!empty($_SERVER['GATEWAY_INTERFACE'])){ +if (!empty($_SERVER['GATEWAY_INTERFACE'])) { error_log("should not be called from apache!"); exit; } @@ -31,9 +31,10 @@ require_once(dirname(dirname(dirname(__FILE__))).'/config.php'); // global moodl require_once($CFG->dirroot.'/course/lib.php'); require_once($CFG->dirroot.'/lib/blocklib.php'); require_once($CFG->dirroot.'/mod/resource/lib.php'); -require_once($CFG->dirroot.'/auth/db/lib.php'); +require_once($CFG->dirroot.'/lib/moodlelib.php'); require_once($CFG->dirroot.'/mod/forum/lib.php'); $CFG->debug=10; -auth_sync_users(true ); +$dbauth = get_auth_plugin('db'); +$dbauth->sync_users(true); ?> \ No newline at end of file diff --git a/auth/db/config.html b/auth/db/config.html index a455c3f307..e2058e681b 100644 --- a/auth/db/config.html +++ b/auth/db/config.html @@ -1,54 +1,65 @@ auth_dbhost)) { - $config->auth_dbhost = "localhost"; + + // set to defaults if undefined + if (!isset($config->host)) { + $config->host = "localhost"; + } + if (!isset($config->type)) { + $config->type = "mysql"; } - if (!isset($config->auth_dbtype)) { - $config->auth_dbtype = "mysql"; + if (!isset($config->name)) { + $config->name = ""; } - if (!isset($config->auth_dbname)) { - $config->auth_dbname = ""; + if (!isset($config->user)) { + $config->user = ""; } - if (!isset($config->auth_dbuser)) { - $config->auth_dbuser = ""; + if (!isset($config->pass)) { + $config->pass = ""; } - if (!isset($config->auth_dbpass)) { - $config->auth_dbpass = ""; + if (!isset($config->table)) { + $config->table = ""; } - if (!isset($config->auth_dbtable)) { - $config->auth_dbtable = ""; + if (!isset($config->fielduser)) { + $config->fielduser = ""; } - if (!isset($config->auth_dbfielduser)) { - $config->auth_dbfielduser = ""; + if (!isset($config->fieldpass)) { + $config->fieldpass = ""; } - if (!isset($config->auth_dbfieldpass)) { - $config->auth_dbfieldpass = ""; + if (!isset($config->passtype)) { + $config->passtype = "plaintext"; } - if (!isset($config->auth_dbpasstype)) { - $config->auth_dbpasstype = "plaintext"; + if (!isset($config->changepasswordurl)) { + $config->changepasswordurl = ''; } $pluginconfig = get_config('auth/db'); + ?> + - + - + - + @@ -58,97 +69,130 @@ - + - + - - + + - + - - + + - - + + - + - + - - + + - - - - + + + +
auth_dbhost: host: - - - - + +
auth_dbtype: type: auth_dbtype, ""); + choose_from_menu($dboptions, "type", $config->type, ""); ?>
auth_dbname: name: - - - - + +
auth_dbuser: - - - user: - + +
auth_dbpass: pass: - - + + - +
auth_dbtable: - - - table: - + +
auth_dbfielduser: - - - fielduser: - + +
auth_dbfieldpass: fieldpass: - - - - + +
auth_dbpasstype: - auth_dbpasstype, ""); - ?> - - passtype: - + passtype, ""); + + ?>
: - - changepasswordurl: - - + +
diff --git a/auth/db/lib.php b/auth/db/lib.php deleted file mode 100644 index e0db9bc677..0000000000 --- a/auth/db/lib.php +++ /dev/null @@ -1,463 +0,0 @@ -prefix.''; // Remember it. The '' is to prevent PHP5 reference.. see bug 3223 - - if ($CFG->dbtype != 'postgres7') { - $CFG->prefix = $CFG->dbname.$CFG->prefix; - } - - // Connect to the external database - $authdb = &ADONewConnection($CFG->auth_dbtype); - $authdb->PConnect($CFG->auth_dbhost,$CFG->auth_dbuser,$CFG->auth_dbpass,$CFG->auth_dbname); - $authdb->SetFetchMode(ADODB_FETCH_ASSOC); ///Set Assoc mode always after DB connection - - if ($CFG->auth_dbpasstype === 'internal') { - // lookup username externally, but resolve - // password locally -- to support backend that - // don't track passwords - $rs = $authdb->Execute("SELECT * FROM $CFG->auth_dbtable - WHERE $CFG->auth_dbfielduser = '$username' "); - $authdb->Close(); - - if (!$rs) { - notify("Could not connect to the specified authentication database..."); - - return false; - } - - if ( $rs->RecordCount() ) { - // user exists exterally - // check username/password internally - if ($user = get_record('user', 'username', $username)) { - return validate_internal_user_password($user, $password); - } - } else { - // user does not exist externally - return false; - } - - } else { - // normal case: use external db for passwords - - if ($CFG->auth_dbpasstype === 'md5') { // Re-format password accordingly - $password = md5($password); - } - - $rs = $authdb->Execute("SELECT * FROM $CFG->auth_dbtable - WHERE $CFG->auth_dbfielduser = '$username' - AND $CFG->auth_dbfieldpass = '$password' "); - $authdb->Close(); - - $CFG->prefix = $prefix; - - if (!$rs) { - notify("Could not connect to the specified authentication database..."); - return false; - } - - if ( $rs->RecordCount() ) { - return true; - } else { - return false; - } - - } -} - - -function auth_get_userinfo($username){ -// Reads any other information for a user from external database, -// then returns it in an array - - global $CFG; - - $config = (array) $CFG; - - $pcfg = get_config('auth/db'); - $pcfg = (array) $pcfg; - - ADOLoadCode($CFG->auth_dbtype); - $authdb = &ADONewConnection(); - $authdb->PConnect($CFG->auth_dbhost,$CFG->auth_dbuser,$CFG->auth_dbpass,$CFG->auth_dbname); - $authdb->SetFetchMode(ADODB_FETCH_ASSOC); ///Set Assoc mode always after DB connection - - $fields = array("firstname", "lastname", "email", "phone1", "phone2", - "department", "address", "city", "country", "description", - "idnumber", "lang"); - - $result = array(); - - foreach ($fields as $field) { - if ($pcfg["field_map_$field"]) { - if ($rs = $authdb->Execute("SELECT ".$pcfg["field_map_$field"]." FROM $CFG->auth_dbtable - WHERE $CFG->auth_dbfielduser = '$username'")) { - if ( $rs->RecordCount() == 1 ) { - // TODO: fix encoding conversion - $result["$field"] = addslashes(stripslashes($rs->fields[0])); - } - } - } - } - - return $result; -} - - -function auth_user_update_password($username, $newpassword) { - global $CFG; - if ($CFG->auth_dbpasstype === 'internal') { - return set_field('user', 'password', md5($newpassword), 'username', $username); - } else { - // we should have never been called! - return false; - } -} - -/** - * syncronizes user fron external db to moodle user table - * - * Sync shouid be done by using idnumber attribute, not username. - * You need to pass firstsync parameter to function to fill in - * idnumbers if they dont exists in moodle user table. - * - * Syncing users removes (disables) users that dont exists anymore in external db. - * Creates new users and updates coursecreator status of users. - * - * @param bool $do_updates Optional: set to true to force an update of existing accounts - * - * This implementation is simpler but less scalable than the one found in the LDAP module. - * - */ -function auth_sync_users ($do_updates=0) { - - global $CFG; - $pcfg = get_config('auth/db'); - - /// - /// list external users - /// - $userlist = auth_get_userlist(); - $quoteduserlist = implode("', '", $userlist); - $quoteduserlist = "'$quoteduserlist'"; - - /// - /// delete obsolete internal users - /// - - // find obsolete users - if (count($userlist)) { - $sql = 'SELECT u.id, u.username - FROM ' . $CFG->prefix .'user u - WHERE u.auth=\'db\' AND u.deleted=\'0\' AND u.username NOT IN (' . $quoteduserlist . ')'; - } else { - $sql = 'SELECT u.id, u.username - FROM ' . $CFG->prefix .'user u - WHERE u.auth=\'db\' AND u.deleted=\'0\' '; - } - $remove_users = get_records_sql($sql); - - if (!empty($remove_users)){ - print "User entries to remove: ". count($remove_users) . "\n"; - - begin_sql(); - foreach ($remove_users as $user) { - //following is copy pasted from admin/user.php - //maybe this should moved to function in lib/datalib.php - unset($updateuser); - $updateuser->id = $user->id; - $updateuser->deleted = "1"; - $updateuser->timemodified = time(); - if (update_record("user", $updateuser)) { - // unenrol_student($user->id); // From all courses - // remove_teacher($user->id); // From all courses - // remove_admin($user->id); - delete_records('role_assignments', 'userid', $user->id); // unassign all roles - notify(get_string("deletedactivity", "", fullname($user, true)) ); - } else { - notify(get_string("deletednot", "", fullname($user, true))); - } - //copy pasted part ends - } - commit_sql(); - } - unset($remove_users); // free mem! - - if (!count($userlist)) { - // exit right here - // nothing else to do - return true; - } - - /// - /// update existing accounts - /// - if ($do_updates) { - // narrow down what fields we need to update - $all_keys = array_keys(get_object_vars($pcfg)); - $updatekeys = array(); - foreach ($all_keys as $key) { - if (preg_match('/^field_updatelocal_(.+)$/',$key, $match)) { - if ($pcfg->{$key} === 'onlogin') { - array_push($updatekeys, $match[1]); // the actual key name - } - } - } - // print_r($all_keys); print_r($updatekeys); - unset($all_keys); unset($key); - - // only go ahead if we actually - // have fields to update locally - if (!empty($updatekeys)) { - $sql = 'SELECT u.id, u.username - FROM ' . $CFG->prefix .'user u - WHERE u.auth=\'db\' AND u.deleted=\'0\' AND u.username IN (' . $quoteduserlist . ')'; - $update_users = get_records_sql($sql); - - foreach ($update_users as $user) { - auth_db_update_user_record($user->username, $updatekeys); - } - unset($update_users); // free memory - } - } - - - /// - /// create missing accounts - /// - // NOTE: this is very memory intensive - // and generally inefficient - $sql = 'SELECT u.id, u.username - FROM ' . $CFG->prefix .'user u - WHERE u.auth=\'db\' AND u.deleted=\'0\''; - - $users = get_records_sql($sql); - - // simplify down to usernames - $usernames = array(); - foreach ($users as $user) { - array_push($usernames, $user->username); - } - unset($users); - - $add_users = array_diff($userlist, $usernames); - unset($usernames); - - if(!empty($add_users)){ - print "User entries to add: ". count($add_users). "\n"; - begin_sql(); - foreach($add_users as $user){ - $username = $user; - $user = auth_get_userinfo_asobj($user); - - // prep a few params - $user->username = $username; - $user->modified = time(); - $user->confirmed = 1; - $user->auth = 'db'; - - // insert it - $old_debug=$CFG->debug; - $CFG->debug=10; - - // maybe the user has been deleted before - if ($old_user = get_record('user', 'username', $user->username, 'deleted', 1)) { - $user->id = $old_user->id; - set_field('user', 'deleted', 0, 'username', $user->username); - echo "Revived user $user->username id $user->id\n"; - } elseif ($id=insert_record ('user',$user)) { // it is truly a new user - echo "inserted user $user->username id $id\n"; - $user->id = $id; - // if relevant, tag for password generation - if ($CFG->auth_dbpasstype === 'internal') { - set_user_preference('auth_forcepasswordchange', 1, $id); - set_user_preference('create_password', 1, $id); - } - } else { - echo "error inserting user $user->username \n"; - } - $CFG->debug=$old_debug; - } - commit_sql(); - unset($add_users); // free mem - } - return true; -} - -function auth_user_exists ($username) { - global $CFG; - $authdb = &ADONewConnection($CFG->auth_dbtype); - $authdb->PConnect($CFG->auth_dbhost,$CFG->auth_dbuser,$CFG->auth_dbpass,$CFG->auth_dbname); - $authdb->SetFetchMode(ADODB_FETCH_ASSOC); ///Set Assoc mode always after DB connection - - $rs = $authdb->Execute("SELECT * FROM $CFG->auth_dbtable - WHERE $CFG->auth_dbfielduser = '$username' "); - $authdb->Close(); - - if (!$rs) { - notify("Could not connect to the specified authentication database..."); - return false; - } - - if ( $rs->RecordCount() ) { - // user exists exterally - // check username/password internally - // ?? there is no $password variable, so why?? - /*if ($user = get_record('user', 'username', $username)) { - return ($user->password == md5($password)); - }*/ - return $rs->RecordCount(); - } else { - // user does not exist externally - return false; - } -} - - -function auth_get_userlist() { - - global $CFG; - - // Connect to the external database - $authdb = &ADONewConnection($CFG->auth_dbtype); - $authdb->PConnect($CFG->auth_dbhost,$CFG->auth_dbuser,$CFG->auth_dbpass,$CFG->auth_dbname); - $authdb->SetFetchMode(ADODB_FETCH_ASSOC); ///Set Assoc mode always after DB connection - - // fetch userlist - $rs = $authdb->Execute("SELECT $CFG->auth_dbfielduser AS username - FROM $CFG->auth_dbtable "); - $authdb->Close(); - - if (!$rs) { - notify("Could not connect to the specified authentication database..."); - return false; - } - - if ( $rs->RecordCount() ) { - $userlist = array(); - while ($rec = $rs->FetchRow()) { - array_push($userlist, $rec['username']); - } - return $userlist; - } else { - return array(); - } -} - -/** - * reads userinformation from DB and return it in an object - * - * @param string $username username - * @return array - */ -function auth_get_userinfo_asobj($username){ - $user_array = truncate_userinfo(auth_get_userinfo($username)); - $user = new object; - foreach($user_array as $key=>$value){ - $user->{$key} = $value; - } - return $user; -} - -function auth_db_update_user_record($username, $updatekeys=false) { -/// will update a local user record from an external source. -/// is a lighter version of the one in moodlelib -- won't do -/// expensive ops such as enrolment -/// -/// If you don't pass $updatekeys, there is a performance hit and -/// values removed from DB won't be removed from moodle. - - global $CFG; - - $pcfg = get_config('auth/db'); - - //just in case check text case - $username = trim(moodle_strtolower($username)); - - // get the current user record - $user = get_record('user', 'username', $username); - if (empty($user)) { // trouble - error_log("Cannot update non-existent user: $username"); - die; - } - - if (function_exists('auth_get_userinfo')) { - if ($newinfo = auth_get_userinfo($username)) { - $newinfo = truncate_userinfo($newinfo); - - if (empty($updatekeys)) { // all keys? this does not support removing values - $updatekeys = array_keys($newinfo); - } - - foreach ($updatekeys as $key){ - unset($value); - if (isset($newinfo[$key])) { - $value = $newinfo[$key]; - $value = addslashes(stripslashes($value)); // Just in case - } else { - $value = ''; - } - if (!empty($pcfg->{'field_updatelocal_' . $key})) { - if ($user->{$key} != $value) { // only update if it's changed - set_field('user', $key, $value, 'username', $username); - } - } - } - } - } - return get_record_select("user", "username = '$username' AND deleted <> '1'"); -} - -// A chance to validate form data, and last chance to -// do stuff before it is inserted in config_plugin -function auth_validate_form(&$form, &$err) { - - // compat until we rework auth a bit - if ($form['auth_dbpasstype'] === 'internal') { - $CFG->auth_db_stdchangepassword = true; - if ($conf = get_record('config', 'name', 'auth_db_stdchangepassword')) { - $conf->value = 1; - if (! update_record('config', $conf)) { - notify("Could not update $name to $value"); - } - } else { - $conf = new StdClass; - $conf->name = 'auth_db_stdchangepassword'; - $conf->value = 1; - if (! insert_record('config', $conf)) { - notify("Error: could not add new variable $name !"); - } - } - } else { - $CFG->auth_db_stdchangepassword = false; - if ($conf = get_record('config', 'name', 'auth_db_stdchangepassword')) { - $conf->value = 0; - if (! update_record('config', $conf)) { - notify("Could not update $name to $value"); - } - } else { - $conf = new StdClass; - $conf->name = 'auth_db_stdchangepassword'; - $conf->value = 0; - if (! insert_record('config', $conf)) { - notify("Error: could not add new variable $name !"); - } - } - } - return true; -} - -?> diff --git a/auth/email/auth.php b/auth/email/auth.php new file mode 100644 index 0000000000..cec823d6eb --- /dev/null +++ b/auth/email/auth.php @@ -0,0 +1,166 @@ +config = get_config('auth/email'); + } + + /** + * Returns true if the username and password work and false if they are + * wrong or don't exist. + * + * @param string $username The username + * @param string $password The password + * @returns bool Authentication success or failure. + */ + function user_login ($username, $password) { + if ($user = get_record('user', 'username', $username)) { + return validate_internal_user_password($user, $password); + } + return false; + } + + /* + * Updates the user's password. + * + * called when the user password is updated. + * + * @param mixed $username Username + * @param mixed $newpassword Plaintext password + * @return boolean result + * + */ + function user_update_password($username, $newpassword) { + $user = get_complete_user_data('username', $username); + return update_internal_user_password($user, $newpassword); + } + + /* + * Sign up a new user ready for confirmation. + */ + function user_signup($user, $notify = true) { + if (! ($user->id = insert_record('user', $user)) ) { + error('Could not add your record to the database!'); + } + if (! send_confirmation_email($user)) { + error('Tried to send you an email but failed!'); + } + + if ($notify) { + global $CFG; + $emailconfirm = get_string('emailconfirm'); + print_header($emailconfirm, $emailconfirm, $emailconfirm); + notice(get_string('emailconfirmsent', '', $user->email), "$CFG->wwwroot/index.php"); + } + } + + /* + * Confirm the new user as registered. + */ + function user_confirm($username, $confirmsecret) { + $user = get_complete_user_data('username', $username); + + if (!empty($user)) { + if ($user->confirmed) { + return AUTH_CONFIRM_ALREADY; + } + if ($user->secret == $confirmsecret) { // They have provided the secret key to get in + if (!set_field("user", "confirmed", 1, "id", $user->id)) { + return AUTH_CONFIRM_FAIL; + } + if (!set_field("user", "firstaccess", time(), "id", $user->id)) { + return AUTH_CONFIRM_FAIL; + } + return AUTH_CONFIRM_OK; + } + } + } + + /** + * Returns true if this authentication plugin is 'internal'. + * + * @returns bool + */ + function is_internal() { + return true; + } + + /** + * Returns true if this authentication plugin can change the user's + * password. + * + * @returns bool + */ + function can_change_password() { + return true; + } + + /** + * Returns the URL for changing the user's pw, or false if the default can + * be used. + * + * @returns bool + */ + function change_password_url() { + return false; + } + + /** + * Prints a form for configuring this authentication plugin. + * + * This function is called from admin/auth.php, and outputs a full page with + * a form for configuring this plugin. + * + * @param array $page An object containing all the data for this page. + */ + function config_form($config, $err) { + include "config.html"; + } + + /** + * Processes and stores configuration data for this authentication plugin. + */ + function process_config($config) { + return true; + } + +} + +?> diff --git a/auth/email/config.html b/auth/email/config.html index f686f3a952..b150158000 100644 --- a/auth/email/config.html +++ b/auth/email/config.html @@ -1,4 +1,11 @@
- \ No newline at end of file + + +
diff --git a/auth/email/lib.php b/auth/email/lib.php deleted file mode 100644 index d16b8e284e..0000000000 --- a/auth/email/lib.php +++ /dev/null @@ -1,19 +0,0 @@ - diff --git a/auth/fc/auth.php b/auth/fc/auth.php new file mode 100644 index 0000000000..0308bb2991 --- /dev/null +++ b/auth/fc/auth.php @@ -0,0 +1,219 @@ +config = get_config('auth/fc'); + } + + /** + * Returns true if the username and password work and false if they are + * wrong or don't exist. + * + * @param string $username The username + * @param string $password The password + * @returns bool Authentication success or failure. + */ + function user_login ($username, $password) { + global $CFG; + $retval = false; + + // Don't allow blank usernames or passwords + if (!$username or !$password) { + return $retval; + } + + $fpp = new fcFPP($this->config->host, $this->config->fppport); + if ($fpp->open()) { + if ($fpp->login($username, $password)) { + $retval = true; + } + } + $fpp->close(); + + return $retval; + } + + /** + * Get user information from FirstCLass server and return it in an array. + * Localize this routine to fit your needs. + */ + function get_userinfo($username) { + /* + Moodle FirstCLass fieldID in UserInfo form + ------ ----------------------------------- + firstname 1202 + lastname 1204 + email 1252 + icq - + phone1 1206 + phone2 1207 (Fax) + institution - + department - + address 1205 + city - + country - + lang - + timezone 8030 (Not used yet. Need to figure out how FC codes timezones) + + description Get data from users resume. Pictures will be removed. + + */ + + $userinfo = array(); + + $fpp = new fcFPP($this->config->host, $this->config->port); + if ($fpp->open()) { + if ($fpp->login($this->config->userid, $this->config->passwd)) { + $userinfo['firstname'] = $fpp->getUserInfo($username,"1202"); + $userinfo['lastname'] = $fpp->getUserInfo($username,"1204"); + $userinfo['email'] = strtok($fpp->getUserInfo($username,"1252"),','); + $userinfo['phone1'] = $fpp->getUserInfo($username,"1206"); + $userinfo['phone2'] = $fpp->getUserInfo($username,"1207"); + $userinfo['description'] = $fpp->getResume($username); + } + } + $fpp->close(); + + foreach($userinfo as $key => $value) { + if (!$value) { + unset($userinfo[$key]); + } + } + + return $userinfo; + } + + /** + * Get users group membership from the FirstClass server user and check if + * user is member of one of the groups of creators. + */ + function iscreator($username = 0) { + global $USER; + + if (! $this->config->creators) { + return false; + } + if (! $username) { + $username = $USER->username; + } + + $fcgroups = array(); + + $fpp = new fcFPP($this->config->host, $this->config->port); + if ($fpp->open()) { + if ($fpp->login($this->config->userid, $this->config->passwd)) { + $fcgroups = $fpp->getGroups($username); + } + } + $fpp->close(); + + if ((! $fcgroups)) { + return false; + } + + $creators = explode(";", $this->config->creators); + + foreach($creators as $creator) { + If (in_array($creator, $fcgroups)) return true; + } + + return false; + } + + /** + * Returns true if this authentication plugin is 'internal'. + * + * @returns bool + */ + function is_internal() { + return false; + } + + /** + * Returns true if this authentication plugin can change the user's + * password. + * + * @returns bool + */ + function can_change_password() { + return false; + } + + /** + * Prints a form for configuring this authentication plugin. + * + * This function is called from admin/auth.php, and outputs a full page with + * a form for configuring this plugin. + * + * @param array $page An object containing all the data for this page. + */ + function config_form($config, $err) { + include "config.html"; + } + + /** + * Processes and stores configuration data for this authentication plugin. + */ + function process_config($config) { + // set to defaults if undefined + if (!isset($config->host)) { + $config->host = "127.0.0.1"; + } + if (!isset($config->fppport)) { + $config->fppport = "3333"; + } + if (!isset($config->userid)) { + $config->userid = "fcMoodle"; + } + if (!isset($config->passwd)) { + $config->passwd = ""; + } + if (!isset($config->creators)) { + $config->creators = ""; + } + if (!isset($config->changepasswordurl)) { + $config->changepasswordurl = ''; + } + + // save settings + set_config('host', $config->user, 'auth/fc'); + set_config('fppport', $config->fppport, 'auth/fc'); + set_config('userid', $config->userid, 'auth/fc'); + set_config('passwd', $config->passwd, 'auth/fc'); + set_config('creators', $config->creators, 'auth/fc'); + set_config('changepasswordurl', $config->changepasswordurl, 'auth/fc'); + + return true; + } + +} + +?> diff --git a/auth/fc/config.html b/auth/fc/config.html index 9f15f8ee92..f1d87ee1a7 100644 --- a/auth/fc/config.html +++ b/auth/fc/config.html @@ -1,85 +1,105 @@ auth_fchost)) { - $config->auth_fchost = "127.0.0.1"; + + // set to defaults if undefined + if (!isset($config->host)) { + $config->host = "127.0.0.1"; + } + if (!isset($config->fppport)) { + $config->fppport = "3333"; } - if (!isset($config->auth_fcfppport)) { - $config->auth_fcfppport = "3333"; + if (!isset($config->userid)) { + $config->userid = "fcMoodle"; } - if (!isset($config->auth_fcuserid)) { - $config->auth_fcuserid = "fcMoodle"; + if (!isset($config->passwd)) { + $config->passwd = ""; } - if (!isset($config->auth_fcpasswd)) { - $config->auth_fcpasswd = ""; + if (!isset($config->creators)) { + $config->creators = ""; } - if (!isset($config->auth_fccreators)) { - $config->auth_fccreators = ""; + if (!isset($config->changepasswordurl)) { + $config->changepasswordurl = ''; } + if (!isset($config->changepasswordurl)) { + $config->changepasswordurl = ''; + } + ?> + - + - + - + - + - + - - - + + - + + +
auth_fchost:host: - - + + - +
auth_fcfppport:fppport: - - + + - +
auth_fcuserid:userid: - - + + - +
auth_fcpasswd:passwd: - - + + - +
auth_fccreators:creators: - - + + - +
: - - changepasswordurl: - - + +
diff --git a/auth/fc/fcFPP.php b/auth/fc/fcFPP.php index b9f25a70ca..5ddd2c5a37 100644 --- a/auth/fc/fcFPP.php +++ b/auth/fc/fcFPP.php @@ -40,22 +40,22 @@ class fcFPP // open a connection to the FirstClass server function open() { - if($this->_debug) echo "Connecting to host "; + if ($this->_debug) echo "Connecting to host "; $host = $this->_hostname; $port = $this->_port; - if($this->_debug) echo "[$host:$port].."; + if ($this->_debug) echo "[$host:$port].."; // open the connection to the FirstClass server $conn = fsockopen($host, $port, $errno, $errstr, 5); - if(!$conn) + if (!$conn) { echo "connection failed!".$errno. $errstr; return false; } // We are connected - if($this->_debug) echo "connected!"; + if ($this->_debug) echo "connected!"; // Read connection message. $line = fgets ($conn); //+0 @@ -74,7 +74,7 @@ class fcFPP $conn = &$this->_conn; // close it if it's open - if($conn) + if ($conn) { fclose($conn); @@ -90,7 +90,7 @@ class fcFPP function login($userid, $passwd) { // we did have a connection right?! - if($this->_conn) + if ($this->_conn) { # Send username fputs($this->_conn,"$userid\r\n"); @@ -105,13 +105,13 @@ class fcFPP $line = fgets ($this->_conn); //+0 $line = fgets ($this->_conn); //+0 or message - if($this->_debug) echo $line; + if ($this->_debug) echo $line; if (preg_match ("/^\+0/", $line)) { //+0, user with subadmin privileges $this->_user = $userid; $this->_pwd = $passwd; return TRUE; - } elseif (strpos($line, 'You are not allowed')){ // Denied access but a valid user and password + } elseif (strpos($line, 'You are not allowed')) { // Denied access but a valid user and password // "Sorry. You are not allowed to login with the FPP interface" return TRUE; } else { //Invalid user or password @@ -124,12 +124,12 @@ class fcFPP } // Get the list of groups the user is a member of - function getGroups($userid){ + function getGroups($userid) { $groups = array(); // we must be logged in as a user with subadmin privileges - if($this->_conn AND $this->_user) { + if ($this->_conn AND $this->_user) { # Send BA-command to get groups fputs($this->_conn,"GET USER '" . $userid . "' 4 -1\r"); $line = ""; @@ -141,7 +141,7 @@ class fcFPP list( , , $groups[$n++]) = explode(" ",$line,3); $line = trim(fgets ($this->_conn)); } - if($this->_debug) echo "getGroups:" . implode(",",$groups); + if ($this->_debug) echo "getGroups:" . implode(",",$groups); } return $groups; @@ -149,24 +149,24 @@ class fcFPP // Check if the user is member of any of the groups. // Return the list of groups the user is member of. - function isMemberOf($userid, $groups){ + function isMemberOf($userid, $groups) { $usergroups = array_map("strtolower",$this->getGroups($userid)); $groups = array_map("strtolower",$groups); $result = array_intersect($groups,$usergroups); - if($this->_debug) echo "isMemberOf:" . implode(",",$result); + if ($this->_debug) echo "isMemberOf:" . implode(",",$result); return $result; } - function getUserInfo($userid, $field){ + function getUserInfo($userid, $field) { $userinfo = ""; - if($this->_conn AND $this->_user) { + if ($this->_conn AND $this->_user) { # Send BA-command to get data fputs($this->_conn,"GET USER '" . $userid . "' " . $field . "\r"); $line = ""; @@ -178,20 +178,20 @@ class fcFPP list( , , $userinfo) = explode(" ",$line,3); $line = trim(fgets ($this->_conn)); } - if($this->_debug) echo "getUserInfo:" . $userinfo; + if ($this->_debug) echo "getUserInfo:" . $userinfo; } return str_replace('\r',' ',trim($userinfo,'"')); } - function getResume($userid){ + function getResume($userid) { $resume = ""; $pattern = "/\[.+:.+\..+\]/"; // Remove references to pictures in resumes - if($this->_conn AND $this->_user) { + if ($this->_conn AND $this->_user) { # Send BA-command to get data fputs($this->_conn,"GET RESUME '" . $userid . "' 6\r"); $line = ""; @@ -205,7 +205,7 @@ class fcFPP //print $line; } - if($this->_debug) echo "getResume:" . $resume; + if ($this->_debug) echo "getResume:" . $resume; } return $resume; diff --git a/auth/fc/lib.php b/auth/fc/lib.php deleted file mode 100644 index 70bedab44b..0000000000 --- a/auth/fc/lib.php +++ /dev/null @@ -1,154 +0,0 @@ -auth_fchost; - $port = $CFG->auth_fcfppport; - - $retval = FALSE; - - if (!$username or !$password) { // Don't allow blank usernames or passwords - return $retval; - } - - - $fpp = new fcFPP($hostname,$port); - if ($fpp->open()) { - if ($fpp->login($username,$password)){ - $retval = TRUE; - } - } - $fpp->close(); - - return $retval; - - -} - -function auth_get_userinfo($username){ -// Get user information from FirstCLass server and return it in an array. -// Localize this routine to fit your needs. - -/* -Moodle FirstCLass fieldID in UserInfo form ------- ----------------------------------- -firstname 1202 -lastname 1204 -email 1252 -icq - -phone1 1206 -phone2 1207 (Fax) -institution - -department - -address 1205 -city - -country - -lang - -timezone 8030 (Not used yet. Need to figure out how FC codes timezones) - -description Get data from users resume. Pictures will be removed. - -*/ - - global $CFG; - - $hostname = $CFG->auth_fchost; - $port = $CFG->auth_fcfppport; - $userid = $CFG->auth_fcuserid; - $passwd = $CFG->auth_fcpasswd; - - $userinfo = array(); - - $fpp = new fcFPP($hostname,$port); - if ($fpp->open()) { - if ($fpp->login($userid,$passwd)){ - - $userinfo['firstname'] = $fpp->getUserInfo($username,"1202"); - $userinfo['lastname'] = $fpp->getUserInfo($username,"1204"); - $userinfo['email'] = strtok($fpp->getUserInfo($username,"1252"),','); - $userinfo['phone1'] = $fpp->getUserInfo($username,"1206"); - $userinfo['phone2'] = $fpp->getUserInfo($username,"1207"); - $userinfo['description'] = $fpp->getResume($username); - - } - } - - $fpp->close(); - - foreach($userinfo as $key => $value) { - if (!$value) { - unset($userinfo[$key]); - } - } - - return $userinfo; - -} - - -function auth_iscreator($username=0) { -//Get users group membership from the FirstClass server user and check if -// user is member of one of the groups of creators. - - global $CFG, $USER; - - if (! $CFG->auth_fccreators) { - return false; - } - - if (! $username) { - $username=$USER->username; - } - - $fcgroups = array(); - - $hostname = $CFG->auth_fchost; - $port = $CFG->auth_fcfppport; - $userid = $CFG->auth_fcuserid; - $passwd = $CFG->auth_fcpasswd; - - $fpp = new fcFPP($hostname,$port); - if ($fpp->open()) { - if ($fpp->login($userid,$passwd)){ - $fcgroups = $fpp->getGroups($username); - } - } - $fpp->close(); - - - if ((! $fcgroups)) { - return false; - } - - $creators = explode(";",$CFG->auth_fccreators); - - foreach($creators as $creator) { - If (in_array($creator, $fcgroups)) return true; - } - - return false; -} - diff --git a/auth/imap/auth.php b/auth/imap/auth.php new file mode 100644 index 0000000000..ad8e581ba7 --- /dev/null +++ b/auth/imap/auth.php @@ -0,0 +1,155 @@ +config = get_config('auth/imap'); + } + + /** + * Returns true if the username and password work and false if they are + * wrong or don't exist. + * + * @param string $username The username + * @param string $password The password + * @returns bool Authentication success or failure. + */ + function user_login ($username, $password) { + if (! function_exists('imap_open')) { + error("Cannot use IMAP authentication. The PHP IMAP module is not installed."); + } + + global $CFG; + $hosts = split(';', $this->config->host); // Could be multiple hosts + + foreach ($hosts as $host) { // Try each host in turn + $host = trim($host); + + switch ($this->config->type) { + case 'imapssl': + $host = '{'.$host.":{$this->config->port}/imap/ssl}"; + break; + + case 'imapcert': + $host = '{'.$host.":{$this->config->port}/imap/ssl/novalidate-cert}"; + break; + + case 'imaptls': + $host = '{'.$host.":{$this->config->port}/imap/tls}"; + break; + + default: + $host = '{'.$host.":{$this->config->port}/imap}"; + } + + error_reporting(0); + $connection = imap_open($host, $username, $password, OP_HALFOPEN); + error_reporting($CFG->debug); + + if ($connection) { + imap_close($connection); + return true; + } + } + + return false; // No match + } + + /** + * Returns true if this authentication plugin is 'internal'. + * + * @returns bool + */ + function is_internal() { + return false; + } + + /** + * Returns true if this authentication plugin can change the user's + * password. + * + * @returns bool + */ + function can_change_password() { + return false; + } + + /** + * Returns the URL for changing the user's pw, or false if the default can + * be used. + * + * @returns bool + */ + function change_password_url() { + return $CFG->changepasswordurl; // TODO: will this be global? + //return $this->config->changepasswordurl; + } + + /** + * Prints a form for configuring this authentication plugin. + * + * This function is called from admin/auth.php, and outputs a full page with + * a form for configuring this plugin. + * + * @param array $page An object containing all the data for this page. + */ + function config_form($config, $err) { + include "config.html"; + } + + /** + * Processes and stores configuration data for this authentication plugin. + */ + function process_config($config) { + // set to defaults if undefined + if (!isset ($config->host)) { + $config->host = '127.0.0.1'; + } + if (!isset ($config->type)) { + $config->type = 'imap'; + } + if (!isset ($config->port)) { + $config->port = '143'; + } + if (!isset($config->changepasswordurl)) { + $config->changepasswordurl = ''; + } + + // save settings + set_config('host', $config->host, 'auth/imap'); + set_config('type', $config->type, 'auth/imap'); + set_config('port', $config->port, 'auth/imap'); + set_config('changepasswordurl', $config->changepasswordurl, 'auth/imap'); + + return true; + } + +} + +?> diff --git a/auth/imap/config.html b/auth/imap/config.html index 40619cb499..6ce0de0b79 100644 --- a/auth/imap/config.html +++ b/auth/imap/config.html @@ -1,60 +1,94 @@ auth_imaphost)) { - $config->auth_imaphost = "127.0.0.1"; - } - if (!isset($config->auth_imaptype)) { - $config->auth_imaptype = "imap"; - } - if (!isset($config->auth_imapport)) { - $config->auth_imapport = "143"; - } + +// set to defaults if undefined +if (!isset($config->host)) { + $config->host = '127.0.0.1'; +} +if (!isset($config->type)) { + $config->type = 'imap'; +} +if (!isset($config->port)) { + $config->port = '143'; +} +if (!isset($config->changepasswordurl)) { + $config->changepasswordurl = ''; +} + ?> + + - + - - + + - + - + - + - + - \ No newline at end of file + + +
auth_imaphost: host: - - + + - - +
auth_imaptype: - auth_imaptype, ""); - ?> - type: - + type, ''); + + ?>
auth_imapport: port: - - - - + +
: changepasswordurl: - - - - + +
diff --git a/auth/imap/lib.php b/auth/imap/lib.php deleted file mode 100644 index a2c0927415..0000000000 --- a/auth/imap/lib.php +++ /dev/null @@ -1,47 +0,0 @@ -auth_imaphost); // Could be multiple hosts - - foreach ($hosts as $host) { // Try each host in turn - - $host = trim($host); - - switch ($CFG->auth_imaptype) { - case "imapssl": - $host = '{'.$host.":$CFG->auth_imapport/imap/ssl}"; - break; - - case "imapcert": - $host = '{'.$host.":$CFG->auth_imapport/imap/ssl/novalidate-cert}"; - break; - - case "imaptls": - $host = '{'.$host.":$CFG->auth_imapport/imap/notls}"; - break; - - default: - $host = '{'.$host.":$CFG->auth_imapport}"; - } - - error_reporting(0); - $connection = imap_open($host, $username, $password, OP_HALFOPEN); - error_reporting($CFG->debug); - - if ($connection) { - imap_close($connection); - return true; - } - } - - return false; // No match -} - - -?> diff --git a/auth/ldap/auth.php b/auth/ldap/auth.php new file mode 100644 index 0000000000..465143fb8e --- /dev/null +++ b/auth/ldap/auth.php @@ -0,0 +1,1651 @@ +config = get_config('auth/ldap'); + } + + /** + * Returns true if the username and password work and false if they are + * wrong or don't exist. + * + * @param string $username The username + * @param string $password The password + * @returns bool Authentication success or failure. + */ + function user_login($username, $password) { + + global $CFG; + + if (!$username or !$password) { // Don't allow blank usernames or passwords + return false; + } + + // CAS-supplied auth tokens override LDAP auth + if ($CFG->auth == "cas" and !empty($CFG->cas_enabled)) { + return cas_ldap_auth_user_login($username, $password); + } + + $ldapconnection = $this->ldap_connect(); + + if ($ldapconnection) { + $ldap_user_dn = $this->ldap_find_userdn($ldapconnection, $username); + + //if ldap_user_dn is empty, user does not exist + if (!$ldap_user_dn) { + ldap_close($ldapconnection); + return false; + } + + // Try to bind with current username and password + $ldap_login = @ldap_bind($ldapconnection, $ldap_user_dn, stripslashes($password)); + ldap_close($ldapconnection); + if ($ldap_login) { + return true; + } + } + else { + @ldap_close($ldapconnection); + error("LDAP-module cannot connect to server: $this->config->host_url"); + } + return false; + } + + /** + * reads userinformation from ldap and return it in array() + * + * Read user information from external database and returns it as array(). + * Function should return all information available. If you are saving + * this information to moodle user-table you should honor syncronization flags + * + * @param string $username username + * @return array + */ + function get_userinfo($username) { + global $CFG; + $ldapconnection = $this->ldap_connect(); + $config = (array)$CFG; + $attrmap = $this->ldap_attributes(); + + $result = array(); + $search_attribs = array(); + + foreach ($attrmap as $key=>$values) { + if (!is_array($values)) { + $values = array($values); + } + foreach ($values as $value) { + if (!in_array($value, $search_attribs)) { + array_push($search_attribs, $value); + } + } + } + + $user_dn = $this->ldap_find_userdn($ldapconnection, $username); + + if (empty($this->config->objectclass)) { // Can't send empty filter + $this->config->objectclass="objectClass=*"; + } + + $user_info_result = ldap_read($ldapconnection, $user_dn, $this->config->objectclass, $search_attribs); + + if ($user_info_result) { + $user_entry = $this->ldap_get_entries($ldapconnection, $user_info_result); + foreach ($attrmap as $key=>$values) { + if (!is_array($values)) { + $values = array($values); + } + $ldapval = NULL; + foreach ($values as $value) { + if (is_array($user_entry[0][strtolower($value)])) { + if (!empty($CFG->unicodedb)) { + $newval = addslashes(stripslashes($user_entry[0][strtolower($value)][0])); + } + else { + $newval = addslashes(stripslashes(utf8_decode($user_entry[0][strtolower($value)][0]))); + } + } + else { + if (!empty($CFG->unicodedb)) { + $newval = addslashes(stripslashes($user_entry[0][strtolower($value)])); + } + else { + $newval = addslashes(stripslashes(utf8_decode($user_entry[0][strtolower($value)]))); + } + } + if (!empty($newval)) { // favour ldap entries that are set + $ldapval = $newval; + } + } + if (!is_null($ldapval)) { + $result[$key] = $ldapval; + } + } + } + + @ldap_close($ldapconnection); + + return $result; + } + + /** + * reads userinformation from ldap and return it in an object + * + * @param string $username username + * @return array + */ + function get_userinfo_asobj($username) { + $user_array = truncate_userinfo($this->get_userinfo($username)); + $user = new object; + foreach ($user_array as $key=>$value) { + $user->{$key} = $value; + } + return $user; + } + + /** + * returns all usernames from external database + * + * get_userlist returns all usernames from external database + * + * @return array + */ + function get_userlist() { + global $CFG; + $this->ldap_init(); + return $this->ldap_get_userlist("({$this->config->user_attribute}=*)"); + } + + /** + * checks if user exists on external db + */ + function user_exists($username) { + global $CFG; + $this->ldap_init(); + //returns true if given usernname exist on ldap + $users = $this->ldap_get_userlist("({$this->config->user_attribute}=$username)"); + return count($users); + } + + /** + * creates new user on external database + * + * user_create() creates new user on external database + * By using information in userobject + * Use user_exists to prevent dublicate usernames + * + * @param mixed $userobject Moodle userobject + * @param mixed $plainpass Plaintext password + */ + function user_create($userobject, $plainpass) { + global $CFG; + $ldapconnection = $this->ldap_connect(); + $attrmap = $this->ldap_attributes(); + + $newuser = array(); + + foreach ($attrmap as $key => $values) { + if (!is_array($values)) { + $values = array($values); + } + foreach ($values as $value) { + if (!empty($userobject->$key) ) { + if (!empty($CFG->unicodedb)) { + $newuser[$value] = $userobject->$key; + } + else { + $newuser[$value] = utf8_encode($userobject->$key); + } + } + } + } + + //Following sets all mandatory and other forced attribute values + //User should be creted as login disabled untill email confirmation is processed + //Feel free to add your user type and send patches to paca@sci.fi to add them + //Moodle distribution + + switch ($this->config->user_type) { + case 'edir': + $newuser['objectClass']= array("inetOrgPerson","organizationalPerson","person","top"); + $newuser['uniqueId']= $userobject->username; + $newuser['logindisabled']="TRUE"; + $newuser['userpassword']=$plainpass; + break; + default: + error('auth: ldap user_create() does not support selected usertype:"'.$this->config->user_type.'" (..yet)'); + } + $uadd = $this->ldap_add($ldapconnection, "{$this->config->user_attribute}={$userobject->username},{$this->config->create_context}", $newuser); + ldap_close($ldapconnection); + return $uadd; + + } + + /** + * + * get_users() returns userobjects from external database + * + * Function returns users from external databe as Moodle userobjects + * If filter is not present it should return ALL users in external database + * + * @param mixed $filter substring of username + * @returns array of userobjects + */ + function get_users($filter = '*', $dontlistcreated = false) { + global $CFG; + + $ldapconnection = $this->ldap_connect(); + $fresult = array(); + + if ($filter=="*") { + $filter = "(&(".$this->config->user_attribute."=*)(".$this->config->objectclass."))"; + } + + $contexts = explode(";",$this->config->contexts); + + if (!empty($this->config->create_context) and empty($dontlistcreated)) { + array_push($contexts, $this->config->create_context); + } + + $attrmap = $this->ldap_attributes(); + + $search_attribs = array(); + + foreach ($attrmap as $key=>$values) { + if (!is_array($values)) { + $values = array($values); + } + foreach ($values as $value) { + if (!in_array($value, $search_attribs)) { + array_push($search_attribs, $value); + } + } + } + + + foreach ($contexts as $context) { + + $context = trim($context); + if (empty($context)) { + continue; + } + + if ($this->config->search_sub) { + //use ldap_search to find first user from subtree + $ldap_result = ldap_search($ldapconnection, $context, + $filter, + $search_attribs); + } + else { + //search only in this context + $ldap_result = ldap_list($ldapconnection, $context, + $filter, + $search_attribs); + } + + $users = $this->ldap_get_entries($ldapconnection, $ldap_result); + + //add found users to list + foreach ($users as $ldapuser=>$attribs) { + $user = new object(); + foreach ($attrmap as $key=>$value) { + if (isset($users[$ldapuser][$value][0])) { + $user->$key=$users[$ldapuser][$value][0]; + } + } + //quick way to get around binarystrings + $user->guid=bin2hex($user->guid); + //add authentication source stamp + $user->auth = AUTH_LDAP_NAME; + $fresult[$user->username]=$user; + + } + } + + return $fresult; + } + + /** + * return number of days to user password expires + * + * If userpassword does not expire it should return 0. If password is already expired + * it should return negative value. + * + * @param mixed $username username + * @return integer + */ + function password_expire($username) { + global $CFG ; + $result = false; + + $ldapconnection = $this->ldap_connect(); + $user_dn = $this->ldap_find_userdn($ldapconnection, $username); + $search_attribs = array($this->config->expireattr); + $sr = ldap_read($ldapconnection, $user_dn, 'objectclass=*', $search_attribs); + if ($sr) { + $info=$this->ldap_get_entries($ldapconnection, $sr); + if ( empty($info[0][strtolower($this->config->expireattr)][0])) { + //error_log("ldap: no expiration value".$info[0][$this->config->expireattr]); + // no expiration attribute, password does not expire + $result = 0; + } + else { + $now = time(); + $expiretime = $this->ldap_expirationtime2unix($info[0][strtolower($this->config->expireattr)][0]); + if ($expiretime > $now) { + $result = ceil(($expiretime - $now) / DAYSECS); + } + else { + $result = floor(($expiretime - $now) / DAYSECS); + } + } + } + else { + error_log("ldap: password_expire did't find expiration time."); + } + + //error_log("ldap: password_expire user $user_dn expires in $result days!"); + return $result; + } + + /** + * syncronizes user fron external db to moodle user table + * + * Sync shouid be done by using idnumber attribute, not username. + * You need to pass firstsync parameter to function to fill in + * idnumbers if they dont exists in moodle user table. + * + * Syncing users removes (disables) users that dont exists anymore in external db. + * Creates new users and updates coursecreator status of users. + * + * @param mixed $firstsync Optional: set to true to fill idnumber fields if not filled yet + */ + function sync_users ($bulk_insert_records = 1000, $do_updates = 1) { + //Syncronizes userdb with ldap + //This will add, rename + /// OPTIONAL PARAMETERS + /// $bulk_insert_records = 1 // will insert $bulkinsert_records per insert statement + /// valid only with $unsafe. increase to a couple thousand for + /// blinding fast inserts -- but test it: you may hit mysqld's + /// max_allowed_packet limit. + /// $do_updates = 1 // will do pull in data updates from ldap if relevant + + + global $CFG ; + + // configure a temp table + print "Configuring temp table\n"; + if (strtolower($CFG->dbtype) === 'mysql') { + // help old mysql versions cope with large temp tables + execute_sql('SET SQL_BIG_TABLES=1', false); + execute_sql('CREATE TEMPORARY TABLE ' . $CFG->prefix .'extuser (idnumber VARCHAR(64), PRIMARY KEY (idnumber)) TYPE=MyISAM',false); + } + elseif (strtolower($CFG->dbtype) === 'postgres7') { + $bulk_insert_records = 1; // no support for multiple sets of values + execute_sql('CREATE TEMPORARY TABLE '.$CFG->prefix.'extuser (idnumber VARCHAR(64), PRIMARY KEY (idnumber))',false); + } + + print "connecting to ldap\n"; + $ldapconnection = $this->ldap_connect(); + + if (!$ldapconnection) { + @ldap_close($ldapconnection); + notify("LDAP-module cannot connect to server: $CFG->ldap_host_url"); + return false; + } + + //// + //// get user's list from ldap to sql in a scalable fashion + //// + // prepare some data we'll need + if (! empty($this->config->objectclass)) { + $this->config->objectclass="objectClass=*"; + } + + $filter = "(&(".$this->config->user_attribute."=*)(".$this->config->objectclass."))"; + + $contexts = explode(";",$this->config->contexts); + + if (!empty($this->config->create_context)) { + array_push($contexts, $this->config->create_context); + } + + $fresult = array(); + $count = 0; + foreach ($contexts as $context) { + $context = trim($context); + if (empty($context)) { + continue; + } + begin_sql(); + if ($this->config->search_sub) { + //use ldap_search to find first user from subtree + $ldap_result = ldap_search($ldapconnection, $context, + $filter, + array($this->config->user_attribute)); + } + else { + //search only in this context + $ldap_result = ldap_list($ldapconnection, $context, + $filter, + array($this->config->user_attribute)); + } + + if ($entry = ldap_first_entry($ldapconnection, $ldap_result)) { + do { + $value = ldap_get_values_len($ldapconnection, $entry,$this->config->user_attribute); + $value = $value[0]; + $count++; + array_push($fresult, $value); + if (count($fresult) >= $bulk_insert_records) { + $this->ldap_bulk_insert($fresult); + //print var_dump($fresult); + $fresult=array(); + } + } + while ($entry = ldap_next_entry($ldapconnection, $entry)); + } + + // insert any remaining users and release mem + if (count($fresult)) { + $this->ldap_bulk_insert($fresult); + $fresult=array(); + } + commit_sql(); + } + // free mem + $ldap_results = 0; + + /// preserve our user database + /// if the temp table is empty, it probably means that something went wrong, exit + /// so as to avoid mass deletion of users; which is hard to undo + $count = get_record_sql('SELECT COUNT(idnumber) AS count, 1 FROM ' . $CFG->prefix .'extuser'); + $count = $count->{'count'}; + if ($count < 1) { + print "Did not get any users from LDAP -- error? -- exiting\n"; + exit; + } + + //// + //// User removal + //// + // find users in DB that aren't in ldap -- to be removed! + // this is still not as scalable + $sql = 'SELECT u.id, u.username + FROM ' . $CFG->prefix .'user u LEFT JOIN ' . $CFG->prefix .'extuser e + ON u.idnumber = e.idnumber + WHERE u.auth=\'' . AUTH_LDAP_NAME . '\' AND u.deleted=\'0\' AND e.idnumber IS NULL'; + //print($sql); + $remove_users = get_records_sql($sql); + + if (!empty($remove_users)) { + print "User entries to remove: ". count($remove_users) . "\n"; + + begin_sql(); + foreach ($remove_users as $user) { + //following is copy pasted from admin/user.php + //maybe this should moved to function in lib/datalib.php + unset($updateuser); + $updateuser->id = $user->id; + $updateuser->deleted = '1'; + //$updateuser->username = "$user->username".time(); // Remember it just in case + //$updateuser->email = ''; // Clear this field to free it up + $updateuser->timemodified = time(); + if (update_record("user", $updateuser)) { + // unenrol_student($user->id); // From all courses + // remove_teacher($user->id); // From all courses + // remove_admin($user->id); + delete_records('role_assignments', 'userid', $user->id); // unassign all roles + notify(get_string('deletedactivity', '', fullname($user, true)) ); + } + else { + notify(get_string('deletednot', '', fullname($user, true))); + } + //copy pasted part ends + } + commit_sql(); + } + $remove_users = 0; // free mem! + + //// + //// User Updates + //// (time-consuming, optional) + //// + if ($do_updates) { + // narrow down what fields we need to update + $all_keys = array_keys(get_object_vars($this->config)); + $updatekeys = array(); + foreach ($all_keys as $key) { + if (preg_match('/^field_updatelocal_(.+)$/',$key, $match)) { + // if we have a field to update it from + // and it must be updated 'onlogin' we + // update it on cron + if ( !empty($this->config->{'field_map_'.$match[1]}) + and $this->config->{$match[0]} === 'onlogin') { + array_push($updatekeys, $match[1]); // the actual key name + } + } + } + // print_r($all_keys); print_r($updatekeys); + unset($all_keys); unset($key); + + } + if ( $do_updates and !(empty($updatekeys)) ) { // run updates only if relevant + $users = get_records_sql('SELECT u.username, u.id FROM ' . $CFG->prefix . 'user u WHERE u.deleted=0 and u.auth=\'' . AUTH_LDAP_NAME . '\'' ); + if (!empty($users)) { + print "User entries to update: ". count($users). "\n"; + $sitecontext = get_context_instance(CONTEXT_SYSTEM); + + if ($creatorroles = get_roles_with_capability('moodle/legacy:coursecreator', CAP_ALLOW)) { + $creatorrole = array_shift($creatorroles); // We can only use one, let's use the first one + + begin_sql(); + $xcount = 0; + $maxxcount = 100; + + foreach ($users as $user) { + echo "updating user $user->username \n"; + $this->update_user_record($user->username, $updatekeys); + + // update course creators + if (!empty($this->config->creators) and !empty($this->config->memberattribute) ) { + if ($this->iscreator($user->username)) { // Following calls will not create duplicates + role_assign($creatorrole->id, $user->id, 0, $sitecontext->id, 0, 0, 0, 'ldap'); + $xcount++; + } else { + role_unassign($creatorrole->id, $user->id, 0, $sitecontext->id); + $xcount++; + } + } + + if ($xcount++ > $maxxcount) { + commit_sql(); + begin_sql(); + $xcount = 0; + } + } + commit_sql(); + unset($users); // free mem + } + } + } // end do updates + + //// + //// User Additions + //// + // find users missing in DB that are in LDAP + // note that get_records_sql wants at least 2 fields returned, + // and gives me a nifty object I don't want. + $sql = 'SELECT e.idnumber,1 + FROM ' . $CFG->prefix .'extuser e LEFT JOIN ' . $CFG->prefix .'user u + ON e.idnumber = u.idnumber + WHERE u.id IS NULL OR (u.id IS NOT NULL AND u.deleted=1)'; + $add_users = get_records_sql($sql); // get rid of the fat + + if (!empty($add_users)) { + print "User entries to add: ". count($add_users). "\n"; + + if ($creatorroles = get_roles_with_capability('moodle/legacy:coursecreator', CAP_ALLOW)) { + $creatorrole = array_shift($roles); // We can only use one, let's use the first one + } + + begin_sql(); + foreach ($add_users as $user) { + $user = $this->get_userinfo_asobj($user->idnumber); + //print $user->username . "\n"; + + // prep a few params + $user->modified = time(); + $user->confirmed = 1; + $user->auth = AUTH_LDAP_NAME; + + // insert it + $old_debug=$CFG->debug; + $CFG->debug=10; + + // maybe the user has been deleted before + if ($old_user = get_record('user', 'idnumber', $user->idnumber, 'deleted', 1)) { + $user->id = $old_user->id; + set_field('user', 'deleted', 0, 'idnumber', $user->idnumber); + echo "Revived user $user->username with idnumber $user->idnumber id $user->id\n"; + } + elseif ($id = insert_record('user',$user)) { // it is truly a new user + echo "inserted user $user->username with idnumber $user->idnumber id $id\n"; + $user->id = $id; + } + else { + echo "error inserting user $user->username with idnumber $user->idnumber \n"; + } + $CFG->debug = $old_debug; + $userobj = $this->update_user_record($user->username); + if (isset($this->config->forcechangepassword) and $this->config->forcechangepassword) { + set_user_preference('auth_forcepasswordchange', 1, $userobj->id); + } + + // update course creators + if (isset($creatorrole->id) and !empty($this->config->creators) and !empty($this->config->memberattribute)) { + if ($this->iscreator($user->username)) { + if (user_has_role_assignment($user->id, $creatorrole->id, $sitecontext->id)) { + role_unassign($creatorrole->id, $user->id, 0, $sitecontext->id); + } else { + role_assign($creatorrole->id, $user->id, 0, $sitecontext->id, 0, 0, 0, 'ldap'); + } + } + } + } + commit_sql(); + unset($add_users); // free mem + } + return true; + } + + /** + * Update a local user record from an external source. + * This is a lighter version of the one in moodlelib -- won't do + * expensive ops such as enrolment. + * + * If you don't pass $updatekeys, there is a performance hit and + * values removed from LDAP won't be removed from moodle. + */ + function update_user_record($username, $updatekeys = false) { + + global $CFG; + + //just in case check text case + $username = trim(moodle_strtolower($username)); + + // get the current user record + $user = get_record('user', 'username', $username); + if (empty($user)) { // trouble + error_log("Cannot update non-existent user: $username"); + die; + } + + if (function_exists('auth_get_userinfo')) { + if ($newinfo = auth_get_userinfo($username)) { + $newinfo = truncate_userinfo($newinfo); + + if (empty($updatekeys)) { // all keys? this does not support removing values + $updatekeys = array_keys($newinfo); + } + + foreach ($updatekeys as $key) { + unset($value); + if (isset($newinfo[$key])) { + $value = $newinfo[$key]; + $value = addslashes(stripslashes($value)); // Just in case + } + else { + $value = ''; + } + if (!empty($this->config->{'field_updatelocal_' . $key})) { + if ($user->{$key} != $value) { // only update if it's changed + set_field('user', $key, $value, 'username', $username); + } + } + } + } + } + return get_record_select("user", "username = '$username' AND deleted <> '1'"); + } + + function ldap_bulk_insert($users) { + // bulk insert in SQL's temp table + // $users is an array of usernames + global $CFG; + + // bulk insert -- superfast with $bulk_insert_records + $sql = 'INSERT INTO '.$CFG->prefix.'extuser (idnumber) VALUES '; + // make those values safe + array_map('addslashes', $users); + // join and quote the whole lot + $sql = $sql . '(\'' . join('\'),(\'', $users) . '\')'; + print "+ " . count($users) . " users\n"; + execute_sql($sql, false); + + } + + + /* + * user_activate activates user in external db. + * + * Activates (enables) user in external db so user can login to external db + * + * @param mixed $username username + * @return boolen result + */ + function user_activate($username) { + + global $CFG; + + $ldapconnection = $this->ldap_connect(); + + $userdn = $this->ldap_find_userdn($ldapconnection, $username); + switch ($this->config->user_type) { + case 'edir': + $newinfo['loginDisabled']="FALSE"; + break; + default: + error ('auth: ldap user_activate() does not support selected usertype:"'.$this->config->user_type.'" (..yet)'); + } + $result = ldap_modify($ldapconnection, $userdn, $newinfo); + ldap_close($ldapconnection); + return $result; + } + + /* + * user_disables disables user in external db. + * + * Disables user in external db so user can't login to external db + * + * @param mixed $username username + * @return boolean result + */ + function user_disable($username) { + global $CFG; + + $ldapconnection = $this->ldap_connect(); + + $userdn = $this->ldap_find_userdn($ldapconnection, $username); + switch ($this->config->user_type) { + case 'edir': + $newinfo['loginDisabled']="TRUE"; + break; + default: + error ('auth: ldap user_disable() does not support selected usertype (..yet)'); + } + $result = ldap_modify($ldapconnection, $userdn, $newinfo); + ldap_close($ldapconnection); + return $result; + } + + /* + * Returns true if user should be coursecreator. + * + * @param mixed $username username + * @return boolean result + */ + function iscreator($username = false) { + ///if user is member of creator group return true + global $USER, $CFG; + $this->ldap_init(); + if (! $username) { + $username = $USER->username; + } + if ((! $this->config->creators) or (! $this->config->memberattribute)) { + return null; + } + return $this->ldap_isgroupmember($username, $this->config->creators); + } + + /* + * user_update saves userinformation from moodle to external db + * + * Called when the user record is updated. + * Modifies user in external database. It takes olduser (before changes) and newuser (after changes) + * conpares information saved modified information to external db. + * + * @param mixed $olduser Userobject before modifications + * @param mixed $newuser Userobject new modified userobject + * @return boolean result + * + */ + function user_update($olduser, $newuser) { + + global $USER, $CFG; + + $ldapconnection = $this->ldap_connect(); + + $result = array(); + $search_attribs = array(); + + $attrmap = $this->ldap_attributes(); + foreach ($attrmap as $key => $values) { + if (!is_array($values)) { + $values = array($values); + } + foreach ($values as $value) { + if (!in_array($value, $search_attribs)) { + array_push($search_attribs, $value); + } + } + } + + $user_dn = $this->ldap_find_userdn($ldapconnection, $olduser->username); + + $user_info_result = ldap_read($ldapconnection, $user_dn, + $this->config->objectclass, $search_attribs); + + if ($user_info_result) { + + $user_entry = $this->ldap_get_entries($ldapconnection, $user_info_result); + if (count($user_entry) > 1) { + trigger_error("ldap: Strange! More than one user record found in ldap. Only using the first one."); + } + $user_entry = $user_entry[0]; + + //error_log(var_export($user_entry) . 'fpp' ); + + foreach ($attrmap as $key => $ldapkeys) { + + // only process if the moodle field ($key) has changed and we + // are set to update LDAP with it + if ($olduser->$key !== $newuser->$key and + !empty($this->config->{'field_updateremote_'. $key})) { + + // for ldap values that could be in more than one + // ldap key, we will do our best to match + // where they came from + $ambiguous = true; + $changed = false; + if (!is_array($ldapkeys)) { + $ldapkeys = array($ldapkeys); + } + if (count($ldapkeys) < 2) { + $ambiguous = false; + } + + foreach ($ldapkeys as $ldapkey) { + $ldapkey = strtolower($ldapkey); + $ldapvalue = $user_entry[$ldapkey][0]; + if (!$ambiguous) { + // skip update if the values already match + if ( !($newuser->$key === $ldapvalue) ) { + ldap_modify($ldapconnection, $user_dn, array($ldapkey => $newuser->$key)); + } + else { + error_log("Skip updating field $key for entry $user_dn: it seems to be already same on LDAP. + old moodle value: '{$olduser->$key}' + new value: '{$newuser->$key}' + current value in ldap entry: '{$ldapvalue}'"); + } + } + else { + // ambiguous + // value empty before in Moodle (and LDAP) - use 1st ldap candidate field + // no need to guess + if (empty($olduser->$key)) { // value empty before - use 1st ldap candidate + if (ldap_modify($ldapconnection, $user_dn, array($ldapkey => $newuser->$key))) { + $changed = true; + last; + } + else { + error ('Error updating LDAP record. Error code: ' + . ldap_errno($ldapconnection) . '; Error string : ' + . ldap_err2str(ldap_errno($ldapconnection))); + } + } + + // we found which ldap key to update! + if (!empty($ldapvalue) and $olduser->$key === $ldapvalue ) { + // error_log("Matched: ". $olduser->$key . " === " . $ldapvalue); + if (ldap_modify($ldapconnection, $user_dn, array($ldapkey => $newuser->$key))) { + $changed = true; + last; + } + else { + error ('Error updating LDAP record. Error code: ' + . ldap_errno($ldapconnection) . '; Error string : ' + . ldap_err2str(ldap_errno($ldapconnection))); + } + } + } + } + + if ($ambiguous and !$changed) { + error_log("Failed to update LDAP with ambiguous field $key". + " old moodle value: '" . $olduser->$key . + "' new value '" . $newuser->$key ); + } + } + } + + + } + else { + error_log("ERROR:No user found in LDAP"); + @ldap_close($ldapconnection); + return false; + } + + @ldap_close($ldapconnection); + + return true; + + } + + /* + * changes userpassword in external db + * + * called when the user password is updated. + * changes userpassword in external db + * + * @param mixed $username Username + * @param mixed $newpassword Plaintext password + * @param mixed $oldpassword Plaintext old password to bind ldap with + * @return boolean result + * + */ + // function user_update_password($username, $newpassword) { + function user_update_password($user, $newpassword) { + /// called when the user password is updated -- it assumes it is called by an admin + /// or that you've otherwise checked the user's credentials + /// IMPORTANT: $newpassword must be cleartext, not crypted/md5'ed + + global $CFG, $USER; + $result = false; + $username = $user->username; + + $ldapconnection = $this->ldap_connect(); + + $user_dn = $this->ldap_find_userdn($ldapconnection, $username); + + if (!$user_dn) { + error_log('LDAP Error in user_update_password(). No DN for: ' . $username); + return false; + } + + switch ($this->config->user_type) { + case 'edir': + //Change password + $result = ldap_modify($ldapconnection, $user_dn, array('userPassword' => $newpassword)); + if (!$result) { + error_log('LDAP Error in user_update_password(). Error code: ' + . ldap_errno($ldapconnection) . '; Error string : ' + . ldap_err2str(ldap_errno($ldapconnection))); + } + //Update password expiration time, grace logins count + $search_attribs = array($this->config->expireattr, 'passwordExpirationInterval','loginGraceLimit' ); + $sr = ldap_read($ldapconnection, $user_dn, 'objectclass=*', $search_attribs); + if ($sr) { + $info=$this->ldap_get_entries($ldapconnection, $sr); + $newattrs = array(); + if (!empty($info[0][$this->config->expireattr][0])) { + //Set expiration time only if passwordExpirationInterval is defined + if (!empty($info[0]['passwordExpirationInterval'][0])) { + $expirationtime = time() + $info[0]['passwordExpirationInterval'][0]; + $ldapexpirationtime = $this->ldap_unix2expirationtime($expirationtime); + $newattrs['passwordExpirationTime'] = $ldapexpirationtime; + } + + //set gracelogin count + if (!empty($info[0]['loginGraceLimit'][0])) { + $newattrs['loginGraceRemaining']= $info[0]['loginGraceLimit'][0]; + } + + //Store attribute changes to ldap + $result = ldap_modify($ldapconnection, $user_dn, $newattrs); + if (!$result) { + error_log('LDAP Error in user_update_password() when modifying expirationtime and/or gracelogins. Error code: ' + . ldap_errno($ldapconnection) . '; Error string : ' + . ldap_err2str(ldap_errno($ldapconnection))); + } + } + } + else { + error_log('LDAP Error in user_update_password() when reading password expiration time. Error code: ' + . ldap_errno($ldapconnection) . '; Error string : ' + . ldap_err2str(ldap_errno($ldapconnection))); + } + break; + + default: + $usedconnection = &$ldapconnection; + // send ldap the password in cleartext, it will md5 it itself + $result = ldap_modify($ldapconnection, $user_dn, array('userPassword' => $newpassword)); + if (!$result) { + error_log('LDAP Error in user_update_password(). Error code: ' + . ldap_errno($ldapconnection) . '; Error string : ' + . ldap_err2str(ldap_errno($ldapconnection))); + } + + } + + @ldap_close($ldapconnection); + return $result; + } + + //PRIVATE FUNCTIONS starts + //private functions are named as ldap_* + + /** + * returns predefined usertypes + * + * @return array of predefined usertypes + */ + + function ldap_suppported_usertypes() { + // returns array of supported usertypes (schemas) + // If you like to add our own please name and describe it here + // And then add case clauses in relevant places in functions + // iauth_ldap_init, auth_user_create, auth_check_expire, auth_check_grace + $types['edir']='Novell Edirectory'; + $types['rfc2307']='posixAccount (rfc2307)'; + $types['rfc2307bis']='posixAccount (rfc2307bis)'; + $types['samba']='sambaSamAccount (v.3.0.7)'; + $types['ad']='MS ActiveDirectory'; + return $types; + } + + + /** + * initializes needed variables for ldap-module + * + * Uses names defined in ldap_supported_usertypes. + * $default is first defined as: + * $default['pseudoname'] = array( + * 'typename1' => 'value', + * 'typename2' => 'value' + * .... + * ); + * + * @return array of default values + */ + function ldap_getdefaults() { + $default['objectclass'] = array( + 'edir' => 'User', + 'rfc2703' => 'posixAccount', + 'rfc2703bis' => 'posixAccount', + 'samba' => 'sambaSamAccount', + 'ad' => 'user', + 'default' => '*' + ); + $default['user_attribute'] = array( + 'edir' => 'cn', + 'rfc2307' => 'uid', + 'rfc2307bis' => 'uid', + 'samba' => 'uid', + 'ad' => 'cn', + 'default' => 'cn' + ); + $default['memberattribute'] = array( + 'edir' => 'member', + 'rfc2307' => 'member', + 'rfc2307bis' => 'member', + 'samba' => 'member', + 'ad' => 'member', + 'default' => 'member' + ); + $default['memberattribute_isdn'] = array( + 'edir' => '1', + 'rfc2307' => '0', + 'rfc2307bis' => '1', + 'samba' => '0', //is this right? + 'ad' => '1', + 'default' => '0' + ); + $default['expireattr'] = array ( + 'edir' => 'passwordExpirationTime', + 'rfc2307' => 'shadowExpire', + 'rfc2307bis' => 'shadowExpire', + 'samba' => '', //No support yet + 'ad' => '', //No support yet + 'default' => '' + ); + return $default; + } + + /** + * return binaryfields of selected usertype + * + * + * @return array + */ + function ldap_getbinaryfields () { + global $CFG; + $binaryfields = array ( + 'edir' => array('guid'), + 'rfc2703' => array(), + 'rfc2703bis' => array(), + 'samba' => array(), + 'ad' => array(), + 'default' => '*' + ); + if (!empty($this->config->user_type)) { + return $binaryfields[$this->config->user_type]; + } + else { + return $binaryfields['default']; + } + } + + function ldap_isbinary ($field) { + if (!isset($field)) { + return null ; + } + return array_search($field, $this->ldap_getbinaryfields()); + } + + /** + * set $CFG-values for ldap_module + * + * Get default configuration values with ldap_getdefaults() + * and by using this information $CFG-> values are set + * If $CFG->value is alredy set current value is honored. + * + * + */ + function ldap_init () { + global $CFG; + + $default = $this->ldap_getdefaults(); + + // TODO: do we need set_config calls here? + + foreach ($default as $key => $value) { + //set defaults if overriding fields not set + if (empty($this->config->{$key})) { + if (!empty($this->config->user_type) and !empty($default[$key][$this->config->user_type])) { + $this->config->{$key} = $default[$key][$this->config->user_type]; + } + else { + //use default value if user_type not set + if (!empty($default[$key]['default'])) { + $this->config->{$key} = $default[$key]['default']; + } + else { + unset($this->config->{$key}); + } + } + } + } + //hack prefix to objectclass + if ('objectClass=' != substr($this->config->objectclass, 0, 12)) { + $this->config->objectclass = 'objectClass='.$this->config->objectclass; + } + + //all chages go in $CFG , no need to return value + } + + /** + * take expirationtime and return it as unixseconds + * + * takes expriration timestamp as readed from ldap + * returns it as unix seconds + * depends on $config->user_type variable + * + * @param mixed time Time stamp readed from ldap as it is. + * @return timestamp + */ + function ldap_expirationtime2unix ($time) { + + global $CFG; + $result = false; + switch ($this->config->user_type) { + case 'edir': + $yr=substr($time,0,4); + $mo=substr($time,4,2); + $dt=substr($time,6,2); + $hr=substr($time,8,2); + $min=substr($time,10,2); + $sec=substr($time,12,2); + $result = mktime($hr,$min,$sec,$mo,$dt,$yr); + break; + case 'posix': + $result = $time * DAYSECS; //The shadowExpire contains the number of DAYS between 01/01/1970 and the actual expiration date + break; + default: + error('config.user_type not defined or function ldap_expirationtime2unix does not support selected type!'); + } + return $result; + } + + /** + * takes unixtime and return it formated for storing in ldap + * + * @param integer unix time stamp + */ + function ldap_unix2expirationtime($time) { + global $CFG; + $result = false; + switch ($this->config->user_type) { + case 'edir': + $result=date('YmdHis', $time).'Z'; + break; + case 'posix': + $result = $time ; //Already in correct format + break; + default: + error('config.user_type not defined or function ldap_unixi2expirationtime does not support selected type!'); + } + return $result; + + } + + /* + * checks if user belong to specific group(s) + * + * Returns true if user belongs group in grupdns string. + * + * @param mixed $username username + * @param mixed $groupdns string of group dn separated by ; + * + */ + function ldap_isgroupmember($username='', $groupdns='') { + // Takes username and groupdn(s) , separated by ; + // Returns true if user is member of any given groups + + global $CFG ; + $result = false; + $ldapconnection = $this->ldap_connect(); + + if (empty($username) or empty($groupdns)) { + return $result; + } + + if ($this->config->memberattribute_isdn) { + $username=$this->ldap_find_userdn($ldapconnection, $username); + } + if (! $username ) { + return $result; + } + + $groups = explode(";",$groupdns); + + foreach ($groups as $group) { + $group = trim($group); + if (empty($group)) { + continue; + } + //echo "Checking group $group for member $username\n"; + $search = @ldap_read($ldapconnection, $group, '('.$this->config->memberattribute.'='.$username.')', array($this->config->memberattribute)); + + if (!empty($search) and ldap_count_entries($ldapconnection, $search)) {$info = $this->ldap_get_entries($ldapconnection, $search); + + if (count($info) > 0 ) { + // user is member of group + $result = true; + break; + } + } + } + + return $result; + + } + + /** + * connects to ldap server + * + * Tries connect to specified ldap servers. + * Returns connection result or error. + * + * @return connection result + */ + function ldap_connect($binddn='',$bindpwd='') { + /// connects and binds to ldap-server + /// Returns connection result + + global $CFG; + $this->ldap_init(); + + //Select bind password, With empty values use + //ldap_bind_* variables or anonymous bind if ldap_bind_* are empty + if ($binddn == '' and $bindpwd == '') { + if (!empty($this->config->bind_dn)) { + $binddn = $this->config->bind_dn; + } + if (!empty($this->config->bind_pw)) { + $bindpwd = $this->config->bind_pw; + } + } + + $urls = explode(";",$this->config->host_url); + + foreach ($urls as $server) { + $server = trim($server); + if (empty($server)) { + continue; + } + + $connresult = ldap_connect($server); + //ldap_connect returns ALWAYS true + + if (!empty($this->config->version)) { + ldap_set_option($connresult, LDAP_OPT_PROTOCOL_VERSION, $this->config->version); + } + + if (!empty($binddn)) { + //bind with search-user + //$debuginfo .= 'Using bind user'.$binddn.'and password:'.$bindpwd; + $bindresult=ldap_bind($connresult, $binddn,$bindpwd); + } + else { + //bind anonymously + $bindresult=@ldap_bind($connresult); + } + + if (!empty($this->config->opt_deref)) { + ldap_set_option($connresult, LDAP_OPT_DEREF, $this->config->opt_deref); + } + + if ($bindresult) { + return $connresult; + } + + $debuginfo .= "
Server: '$server'
Connection: '$connresult'
Bind result: '$bindresult'
"; + } + + //If any of servers are alive we have already returned connection + error("LDAP-module cannot connect any LDAP servers : $debuginfo"); + return false; + } + + /** + * retuns dn of username + * + * Search specified contexts for username and return user dn + * like: cn=username,ou=suborg,o=org + * + * @param mixed $ldapconnection $ldapconnection result + * @param mixed $username username + * + */ + + function ldap_find_userdn ($ldapconnection, $username) { + + global $CFG; + + //default return value + $ldap_user_dn = FALSE; + + //get all contexts and look for first matching user + $ldap_contexts = explode(";",$this->config->contexts); + + if (!empty($this->config->create_context)) { + array_push($ldap_contexts, $this->config->create_context); + } + + foreach ($ldap_contexts as $context) { + + $context = trim($context); + if (empty($context)) { + continue; + } + + if ($this->config->search_sub) { + //use ldap_search to find first user from subtree + $ldap_result = ldap_search($ldapconnection, $context, "(".$this->config->user_attribute."=".$username.")",array($this->config->user_attribute)); + + } + else { + //search only in this context + $ldap_result = ldap_list($ldapconnection, $context, "(".$this->config->user_attribute."=".$username.")",array($this->config->user_attribute)); + } + + $entry = ldap_first_entry($ldapconnection,$ldap_result); + + if ($entry) { + $ldap_user_dn = ldap_get_dn($ldapconnection, $entry); + break ; + } + } + + return $ldap_user_dn; + } + + /** + * retuns user attribute mappings between moodle and ldap + * + * @return array + */ + + function ldap_attributes () { + $fields = array("firstname", "lastname", "email", "phone1", "phone2", + "department", "address", "city", "country", "description", + "idnumber", "lang" ); + $moodleattributes = array(); + foreach ($fields as $field) { + if (!empty($this->config->{"field_map_$field"})) { + $moodleattributes[$field] = $this->config->{"field_map_$field"}; + if (preg_match('/,/',$moodleattributes[$field])) { + $moodleattributes[$field] = explode(',', $moodleattributes[$field]); // split ? + } + } + } + $moodleattributes['username'] = $this->config->user_attribute; + return $moodleattributes; + } + + /** + * return all usernames from ldap + * + * @return array + */ + + function ldap_get_userlist($filter="*") { + /// returns all users from ldap servers + global $CFG; + + $fresult = array(); + + $ldapconnection = $this->ldap_connect(); + + if ($filter=="*") { + $filter = "(&(".$this->config->user_attribute."=*)(".$this->config->objectclass."))"; + } + + $contexts = explode(";",$this->config->contexts); + + if (!empty($this->config->create_context)) { + array_push($contexts, $this->config->create_context); + } + + foreach ($contexts as $context) { + + $context = trim($context); + if (empty($context)) { + continue; + } + + if ($this->config->search_sub) { + //use ldap_search to find first user from subtree + $ldap_result = ldap_search($ldapconnection, $context,$filter,array($this->config->user_attribute)); + } + else { + //search only in this context + $ldap_result = ldap_list($ldapconnection, $context, + $filter, + array($this->config->user_attribute)); + } + + $users = $this->ldap_get_entries($ldapconnection, $ldap_result); + + //add found users to list + for ($i=0;$iconfig->user_attribute][0]) ); + } + } + + return $fresult; + } + + /** + * return entries from ldap + * + * Returns values like ldap_get_entries but is + * binary compatible and return all attributes as array + * + * @return array ldap-entries + */ + + function ldap_get_entries($conn, $searchresult) { + //Returns values like ldap_get_entries but is + //binary compatible + $i=0; + $fresult=array(); + $entry = ldap_first_entry($conn, $searchresult); + do { + $attributes = @ldap_get_attributes($conn, $entry); + for ($j=0; $j<$attributes['count']; $j++) { + $values = ldap_get_values_len($conn, $entry,$attributes[$j]); + if (is_array($values)) { + $fresult[$i][$attributes[$j]] = $values; + } + else { + $fresult[$i][$attributes[$j]] = array($values); + } + } + $i++; + } + while ($entry = @ldap_next_entry($conn, $entry)); + //were done + return ($fresult); + } + + /** + * Returns true if this authentication plugin is 'internal'. + * + * @returns bool + */ + function is_internal() { + return false; + } + + /** + * Returns true if this authentication plugin can change the user's + * password. + * + * @returns bool + */ + function can_change_password() { + return true; + } + + /** + * Returns the URL for changing the user's pw, or false if the default can + * be used. + * + * @returns bool + */ + function change_password_url() { + return $CFG->changepasswordurl; // TODO: will this be global? + } + + /** + * Prints a form for configuring this authentication plugin. + * + * This function is called from admin/auth.php, and outputs a full page with + * a form for configuring this plugin. + * + * @param array $page An object containing all the data for this page. + */ + function config_form($config, $err) { + include "config.html"; + } + + /** + * Processes and stores configuration data for this authentication plugin. + */ + function process_config($config) { + // set to defaults if undefined + if (!isset($config->host_url)) + { $config->host_url = ''; } + if (!isset($config->contexts)) + { $config->contexts = ''; } + if (!isset($config->user_type)) + { $config->user_type = ''; } + if (!isset($config->user_attribute)) + { $config->user_attribute = ''; } + if (!isset($config->search_sub)) + { $config->search_sub = ''; } + if (!isset($config->opt_deref)) + { $config->opt_deref = ''; } + if (!isset($config->preventpassindb)) + { $config->preventpassindb = 0; } + if (!isset($config->bind_dn)) + {$config->bind_dn = ''; } + if (!isset($config->bind_pw)) + {$config->bind_pw = ''; } + if (!isset($config->version)) + {$config->version = '2'; } + if (!isset($config->objectclass)) + {$config->objectclass = ''; } + if (!isset($config->memberattribute)) + {$config->memberattribute = ''; } + if (!isset($config->creators)) + {$config->creators = ''; } + if (!isset($config->create_context)) + {$config->create_context = ''; } + if (!isset($config->expiration)) + {$config->expiration = ''; } + if (!isset($config->expiration_warning)) + {$config->expiration_warning = '10'; } + if (!isset($config->expireattr)) + {$config->expireattr = ''; } + if (!isset($config->gracelogins)) + {$config->gracelogins = ''; } + if (!isset($config->graceattr)) + {$config->graceattr = ''; } + if (!isset($config->auth_user_create)) + {$config->auth_user_create = ''; } + if (!isset($config->forcechangepassword)) + {$config->forcechangepassword = false; } + if (!isset($config->stdchangepassword)) + {$config->stdchangepassword = false; } + if (!isset($config->changepasswordurl)) + {$config->changepasswordurl = ''; } + + // save settings + set_config('host_url', $config->host_url, 'auth/ldap'); + set_config('contexts', $config->contexts, 'auth/ldap'); + set_config('user_type', $config->user_type, 'auth/ldap'); + set_config('user_attribute', $config->user_attribute, 'auth/ldap'); + set_config('search_sub', $config->search_sub, 'auth/ldap'); + set_config('opt_deref', $config->opt_deref, 'auth/ldap'); + set_config('preventpassindb', $config->preventpassindb, 'auth/ldap'); + set_config('bind_dn', $config->bind_dn, 'auth/ldap'); + set_config('bind_pw', $config->bind_pw, 'auth/ldap'); + set_config('version', $config->version, 'auth/ldap'); + set_config('objectclass', $config->objectclass, 'auth/ldap'); + set_config('memberattribute', $config->memberattribute, 'auth/ldap'); + set_config('creators', $config->creators, 'auth/ldap'); + set_config('create_context', $config->create_context, 'auth/ldap'); + set_config('expiration', $config->expiration, 'auth/ldap'); + set_config('expiration_warning', $config->expiration_warning, 'auth/ldap'); + set_config('expireattr', $config->expireattr, 'auth/ldap'); + set_config('gracelogins', $config->gracelogins, 'auth/ldap'); + set_config('graceattr', $config->graceattr, 'auth/ldap'); + set_config('auth_user_create', $config->auth_user_create, 'auth/ldap'); + set_config('forcechangepassword', $config->forcechangepassword, 'auth/ldap'); + set_config('stdchangepassword', $config->stdchangepassword, 'auth/ldap'); + set_config('changepasswordurl', $config->changepasswordurl, 'auth/ldap'); + + return true; + } + +} + +?> diff --git a/auth/ldap/auth_ldap_sync_users.php b/auth/ldap/auth_ldap_sync_users.php index 1696b12830..c5d5d16e66 100755 --- a/auth/ldap/auth_ldap_sync_users.php +++ b/auth/ldap/auth_ldap_sync_users.php @@ -21,7 +21,7 @@ */ -if(!empty($_SERVER['GATEWAY_INTERFACE'])){ +if (!empty($_SERVER['GATEWAY_INTERFACE'])) { error_log("should not be called from apache!"); exit; } @@ -31,9 +31,11 @@ require_once(dirname(dirname(dirname(__FILE__))).'/config.php'); // global moodl require_once($CFG->dirroot.'/course/lib.php'); require_once($CFG->dirroot.'/lib/blocklib.php'); require_once($CFG->dirroot.'/mod/resource/lib.php'); -require_once($CFG->dirroot.'/auth/ldap/lib.php'); require_once($CFG->dirroot.'/mod/forum/lib.php'); $CFG->debug=10; -auth_sync_users(1000, true ); -?> \ No newline at end of file +require_once($CFG->dirroot.'/lib/moodlelib.php'); +$ldapauth = get_auth_plugin('ldap'); +$ldapauth->sync_users(1000, true); + +?> diff --git a/auth/ldap/config.html b/auth/ldap/config.html index 0c50e3420e..9f22fb1099 100644 --- a/auth/ldap/config.html +++ b/auth/ldap/config.html @@ -1,226 +1,234 @@ ldap_host_url)) - { $config->ldap_host_url = ''; } - if (!isset($config->ldap_contexts)) - { $config->ldap_contexts = ''; } - if (!isset($config->ldap_user_type)) - { $config->ldap_user_type = ''; } - if (!isset($config->ldap_user_attribute)) - { $config->ldap_user_attribute = ''; } - if (!isset($config->ldap_search_sub)) - { $config->ldap_search_sub = ''; } - if (!isset($config->ldap_opt_deref)) - { $config->ldap_opt_deref = ''; } - if (!isset($config->ldap_preventpassindb)) - { $config->ldap_preventpassindb = 0; } - if (!isset($config->ldap_bind_dn)) - {$config->ldap_bind_dn = ''; } - if (!isset($config->ldap_bind_pw)) - {$config->ldap_bind_pw = ''; } - if (!isset($config->ldap_version)) - {$config->ldap_version = '2'; } - if (!isset($config->ldap_objectclass)) - {$config->ldap_objectclass = ''; } - if (!isset($config->ldap_memberattribute)) - {$config->ldap_memberattribute = ''; } - if (!isset($config->ldap_creators)) - {$config->ldap_creators = ''; } - if (!isset($config->ldap_create_context)) - {$config->ldap_create_context = ''; } - if (!isset($config->ldap_expiration)) - {$config->ldap_expiration = ''; } - if (!isset($config->ldap_expiration_warning)) - {$config->ldap_expiration_warning = '10'; } - if (!isset($config->ldap_expireattr)) - {$config->ldap_expireattr = ''; } - if (!isset($config->ldap_gracelogins)) - {$config->ldap_gracelogins = ''; } - if (!isset($config->ldap_graceattr)) - {$config->ldap_graceattr = ''; } + + $createoptions[0] = get_string("no"); + $createoptions[1] = get_string("yes"); + + // set to defaults if undefined + if (!isset($config->host_url)) + { $config->host_url = ''; } + if (!isset($config->contexts)) + { $config->contexts = ''; } + if (!isset($config->user_type)) + { $config->user_type = ''; } + if (!isset($config->user_attribute)) + { $config->user_attribute = ''; } + if (!isset($config->search_sub)) + { $config->search_sub = ''; } + if (!isset($config->opt_deref)) + { $config->opt_deref = ''; } + if (!isset($config->preventpassindb)) + { $config->preventpassindb = 0; } + if (!isset($config->bind_dn)) + {$config->bind_dn = ''; } + if (!isset($config->bind_pw)) + {$config->bind_pw = ''; } + if (!isset($config->version)) + {$config->version = '2'; } + if (!isset($config->objectclass)) + {$config->objectclass = ''; } + if (!isset($config->memberattribute)) + {$config->memberattribute = ''; } + if (!isset($config->creators)) + {$config->creators = ''; } + if (!isset($config->create_context)) + {$config->create_context = ''; } + if (!isset($config->expiration)) + {$config->expiration = ''; } + if (!isset($config->expiration_warning)) + {$config->expiration_warning = '10'; } + if (!isset($config->expireattr)) + {$config->expireattr = ''; } + if (!isset($config->gracelogins)) + {$config->gracelogins = ''; } + if (!isset($config->graceattr)) + {$config->graceattr = ''; } if (!isset($config->auth_user_create)) {$config->auth_user_create = ''; } - if (!isset($config->auth_ldap_forcechangepassword)) - {$config->auth_ldap_forcechangepassword = false; } - if (!isset($config->auth_ldap_stdchangepassword)) - {$config->auth_ldap_stdchangepassword = false; } + if (!isset($config->forcechangepassword)) + {$config->forcechangepassword = false; } + if (!isset($config->stdchangepassword)) + {$config->stdchangepassword = false; } + if (!isset($config->changepasswordurl)) + {$config->changepasswordurl = ''; } $yesno = array( get_string('no'), get_string('yes') ); -if (!function_exists('ldap_connect')){ // Is php4-ldap really there? +if (!function_exists('ldap_connect')) { // Is php4-ldap really there? print '

Warning: The PHP LDAP module does not seem to be present. Please ensure it is installed and enabled.

'; } ?> + + - + - + - + - + - + - + - + - + - + - + - + - + @@ -228,11 +236,11 @@ if (!function_exists('ldap_connect')){ // Is php4-ldap really there? @@ -245,11 +253,11 @@ if (!function_exists('ldap_connect')){ // Is php4-ldap really there? @@ -259,76 +267,91 @@ if (!function_exists('ldap_connect')){ // Is php4-ldap really there? + + + + + + - + - + - + - + - + @@ -336,60 +359,67 @@ if (!function_exists('ldap_connect')){ // Is php4-ldap really there? + + + + + + - + - + '; -$help .= get_string("auth_updateremote_ldap","auth"); +$help .= get_string('auth_updateremote_ldap','auth'); -print_auth_lock_options($auth, $user_fields, $help, true, true); -?> - - - - - - +global $user_fields; +print_auth_lock_options('ldap', $user_fields, $help, true, true); +?> +
-

+

ldap_host_url:host_url: - - + + - +
ldap_version:version: ldap_version, ""); - if (isset($err["ldap_version"])) formerr($err["ldap_version"]); + $versions[2] = '2'; + $versions[3] = '3'; + choose_from_menu($versions, 'version', $config->version, ''); + if (isset($err['version'])) formerr($err['version']); ?> - +
-

+

ldap_preventpassindb:preventpassindb: ldap_preventpassindb, ""); + $choices['0'] = get_string('no'); + $choices['1'] = get_string('yes'); + choose_from_menu ($choices, 'preventpassindb', $config->preventpassindb, ''); ?> - +
ldap_bind_dn:bind_dn: - - + + - +
ldap_bind_pw:bind_pw: - - + + - +
-

+

ldap_user_type:user_type: - ldap_user_type, ""); ?> - + ldap_suppported_usertypes(), 'user_type', $config->user_type, ''); ?> + - +
ldap_contexts:contexts: - - + + - +
ldap_search_sub:search_sub: ldap_search_sub, ""); + $choices['0'] = get_string('no'); + $choices['1'] = get_string('yes'); + choose_from_menu ($choices, 'search_sub', $config->search_sub, ''); ?> - + - +
ldap_opt_deref:opt_deref: ldap_opt_deref, LDAP_DEREF_NEVER); - if (isset($err["ldap_opt_deref"])) formerr($err["ldap_opt_deref"]); + $opt_deref[LDAP_DEREF_NEVER] = get_string('no'); + $opt_deref[LDAP_DEREF_ALWAYS] = get_string('yes'); + choose_from_menu($opt_deref, 'opt_deref', $config->opt_deref, LDAP_DEREF_NEVER); + if (isset($err['opt_deref'])) formerr($err['opt_deref']); ?> - +
ldap_user_attribute:user_attribute: - - + + - +
ldap_memberattribute:memberattribute: - - + + - +
ldap_objectclass:objectclass: - - + + - +
-

+

: - + +
: - + +
changepasswordurl: + + +
-

+

ldap_expiration:expiration: ldap_expiration, ""); - if (isset($err["ldap_expiration"])) formerr($err["ldap_expiration"]); + $expiration['0'] = 'no'; + $expiration['1'] = 'LDAP'; + choose_from_menu($expiration, 'expiration', $config->expiration, ''); + if (isset($err['expiration'])) formerr($err['expiration']); ?> - +
ldap_expiration_warning:expiration_warning: - - expiration_warning?>" /> + - +
ldap_exprireattr:exprireattr: - - expireattr?>" /> + - +
ldap_gracelogins:gracelogins: ldap_gracelogins, ""); - if (isset($err["ldap_expiration"])) formerr($err["ldap_expiration"]); + $grace['0'] = get_string('no'); + $grace['1'] = get_string('yes'); + choose_from_menu($grace, 'gracelogins', $config->gracelogins, ''); + if (isset($err['expiration'])) formerr($err['expiration']); ?> - +
ldap_graceattr:graceattr: - - graceattr?>" /> + - +
-

+

auth_user_create: + auth_user_create, ''); + if (isset($err['auth_user_create'])) { + formerr($err['auth_user_create']); + } + + ?> + + +
ldap_create_context:create_context: - - + + - +
-

+

ldap_creators:creators: - - + + - +
: - - - - - -
diff --git a/auth/ldap/lib.php b/auth/ldap/lib.php deleted file mode 100644 index 3d1e72eecb..0000000000 --- a/auth/ldap/lib.php +++ /dev/null @@ -1,1505 +0,0 @@ -auth == "cas" && !empty($CFG->cas_enabled)) { - return cas_ldap_auth_user_login($username, $password); - } - - $ldapconnection = auth_ldap_connect(); - - if ($ldapconnection) { - $ldap_user_dn = auth_ldap_find_userdn($ldapconnection, $username); - - //if ldap_user_dn is empty, user does not exist - if(!$ldap_user_dn){ - ldap_close($ldapconnection); - return false; - } - - // Try to bind with current username and password - $ldap_login = @ldap_bind($ldapconnection, $ldap_user_dn, stripslashes($password)); - ldap_close($ldapconnection); - if ($ldap_login) { - return true; - } - } else { - @ldap_close($ldapconnection); - error("LDAP-module cannot connect to server: $CFG->ldap_host_url"); - } - return false; -} - -/** - * reads userinformation from ldap and return it in array() - * - * Read user information from external database and returns it as array(). - * Function should return all information available. If you are saving - * this information to moodle user-table you should honor syncronization flags - * - * @param string $username username - * @return array - */ -function auth_get_userinfo($username){ - global $CFG; - $ldapconnection=auth_ldap_connect(); - $config = (array)$CFG; - $attrmap = auth_ldap_attributes(); - - $result = array(); - $search_attribs = array(); - - foreach ($attrmap as $key=>$values) { - if (!is_array($values)) { - $values = array($values); - } - foreach ($values as $value) { - if (!in_array($value, $search_attribs)) { - array_push($search_attribs, $value); - } - } - } - - $user_dn = auth_ldap_find_userdn($ldapconnection, $username); - - if (empty($CFG->ldap_objectclass)) { // Can't send empty filter - $CFG->ldap_objectclass="objectClass=*"; - } - - $user_info_result = ldap_read($ldapconnection,$user_dn,$CFG->ldap_objectclass, $search_attribs); - - if ($user_info_result) { - $user_entry = ldap_get_entries($ldapconnection, $user_info_result); - foreach ($attrmap as $key=>$values){ - if (!is_array($values)) { - $values = array($values); - } - $ldapval = NULL; - foreach ($values as $value) { - if(is_array($user_entry[0][strtolower($value)])) { - // TODO: fix encoding conversion - $newval = addslashes(stripslashes($user_entry[0][strtolower($value)][0])); - } - else { - // TODO: fix encoding conversion - $newval = addslashes(stripslashes($user_entry[0][strtolower($value)])); - } - if (!empty($newval)) { // favour ldap entries that are set - $ldapval = $newval; - } - } - if (!is_null($ldapval)) { - $result[$key] = $ldapval; - } - } - } - - @ldap_close($ldapconnection); - - return $result; -} - -/** - * reads userinformation from ldap and return it in an object - * - * @param string $username username - * @return array - */ -function auth_get_userinfo_asobj($username){ - $user_array = truncate_userinfo(auth_get_userinfo($username)); - $user = new object; - foreach($user_array as $key=>$value){ - $user->{$key} = $value; - } - return $user; -} - -/** - * returns all usernames from external database - * - * auth_get_userlist returns all usernames from external database - * - * @return array - */ -function auth_get_userlist () { - global $CFG; - auth_ldap_init(); - return auth_ldap_get_userlist("($CFG->ldap_user_attribute=*)"); -} -/** - * checks if user exists on external db - */ -function auth_user_exists ($username) { - global $CFG; - auth_ldap_init(); - //returns true if given usernname exist on ldap - $users = auth_ldap_get_userlist("($CFG->ldap_user_attribute=$username)"); - return count($users); -} - -/** - * creates new user on external database - * - * auth_user_create() creates new user on external database - * By using information in userobject - * Use auth_user_exists to prevent dublicate usernames - * - * @param mixed $userobject Moodle userobject - * @param mixed $plainpass Plaintext password - */ -function auth_user_create ($userobject,$plainpass) { - global $CFG; - $ldapconnection = auth_ldap_connect(); - $attrmap = auth_ldap_attributes(); - - $newuser = array(); - - foreach ($attrmap as $key=>$values){ - if (!is_array($values)) { - $values = array($values); - } - foreach ($values as $value) { - if(!empty($userobject->$key) ){ - $newuser[$value]= $userobject->$key; - } - } - } - - //Following sets all mandatory and other forced attribute values - //User should be creted as login disabled untill email confirmation is processed - //Feel free to add your user type and send patches to paca@sci.fi to add them - //Moodle distribution - - switch ($CFG->ldap_user_type) { - case 'edir': - $newuser['objectClass']= array("inetOrgPerson","organizationalPerson","person","top"); - $newuser['uniqueId']= $userobject->username; - $newuser['logindisabled']="TRUE"; - $newuser['userpassword']=$plainpass; - break; - default: - error('auth: ldap auth_user_create() does not support selected usertype:"'.$CFG->ldap_user_type.'" (..yet)'); - } - $uadd = ldap_add($ldapconnection, $CFG->ldap_user_attribute."=$userobject->username,".$CFG->ldap_create_context, $newuser); - - ldap_close($ldapconnection); - return $uadd; - -} - -/*/ - * - * auth_get_users() returns userobjects from external database - * - * Function returns users from external databe as Moodle userobjects - * If filter is not present it should return ALL users in external database - * - * @param mixed $filter substring of username - * @returns array of userobjects - */ -function auth_get_users($filter='*', $dontlistcreated=false) { - global $CFG; - - $ldapconnection = auth_ldap_connect(); - $fresult = array(); - - if ($filter=="*") { - $filter = "(&(".$CFG->ldap_user_attribute."=*)(".$CFG->ldap_objectclass."))"; - } - - $contexts = explode(";",$CFG->ldap_contexts); - - if (!empty($CFG->ldap_create_context) and empty($dontlistcreated)){ - array_push($contexts, $CFG->ldap_create_context); - } - - $attrmap = auth_ldap_attributes(); - - $search_attribs = array(); - - foreach ($attrmap as $key=>$values) { - if (!is_array($values)) { - $values = array($values); - } - foreach ($values as $value) { - if (!in_array($value, $search_attribs)) { - array_push($search_attribs, $value); - } - } - } - - - foreach ($contexts as $context) { - - $context = trim($context); - if (empty($context)) { - continue; - } - - if ($CFG->ldap_search_sub) { - //use ldap_search to find first user from subtree - $ldap_result = ldap_search($ldapconnection, $context, - $filter, - $search_attribs); - } else { - //search only in this context - $ldap_result = ldap_list($ldapconnection, $context, - $filter, - $search_attribs); - } - - $users = auth_ldap_get_entries($ldapconnection, $ldap_result); - - //add found users to list - foreach ($users as $ldapuser=>$attribs) { - $user = new object(); - foreach ($attrmap as $key=>$value){ - if(isset($users[$ldapuser][$value][0])){ - $user->$key=$users[$ldapuser][$value][0]; - } - } - //quick way to get around binarystrings - $user->guid=bin2hex($user->guid); - //add authentication source stamp - $user->auth = AUTH_LDAP_NAME; - $fresult[$user->username]=$user; - - } - } - - return $fresult; -} - -/** - * return number of days to user password expires - * - * If userpassword does not expire it should return 0. If password is already expired - * it should return negative value. - * - * @param mixed $username username - * @return integer - */ -function auth_password_expire($username) { - global $CFG ; - $result = false; - - $ldapconnection = auth_ldap_connect(); - $user_dn = auth_ldap_find_userdn($ldapconnection, $username); - $search_attribs = array($CFG->ldap_expireattr); - $sr = ldap_read($ldapconnection, $user_dn, 'objectclass=*', $search_attribs); - if ($sr) { - $info=auth_ldap_get_entries($ldapconnection, $sr); - if ( empty($info[0][strtolower($CFG->ldap_expireattr)][0])) { - //error_log("ldap: no expiration value".$info[0][$CFG->ldap_expireattr]); - // no expiration attribute, password does not expire - $result = 0; - } else { - $now = time(); - $expiretime = auth_ldap_expirationtime2unix($info[0][strtolower($CFG->ldap_expireattr)][0]); - if ($expiretime > $now) { - $result = ceil(($expiretime - $now) / DAYSECS); - } else { - $result = floor(($expiretime - $now) / DAYSECS); - } - } - } else { - error_log("ldap: auth_password_expire did't find expiration time!."); - } - - //error_log("ldap: auth_password_expire user $user_dn expires in $result days!"); - return $result; -} - -/** - * syncronizes user fron external db to moodle user table - * - * Sync shouid be done by using idnumber attribute, not username. - * You need to pass firstsync parameter to function to fill in - * idnumbers if they dont exists in moodle user table. - * - * Syncing users removes (disables) users that dont exists anymore in external db. - * Creates new users and updates coursecreator status of users. - * - * @param mixed $firstsync Optional: set to true to fill idnumber fields if not filled yet - */ -function auth_sync_users ($bulk_insert_records = 1000, $do_updates=1) { -//Syncronizes userdb with ldap -//This will add, rename -/// OPTIONAL PARAMETERS -/// $bulk_insert_records = 1 // will insert $bulkinsert_records per insert statement -/// valid only with $unsafe. increase to a couple thousand for -/// blinding fast inserts -- but test it: you may hit mysqld's -/// max_allowed_packet limit. -/// $do_updates = 1 // will do pull in data updates from ldap if relevant - - - global $CFG ; - $pcfg = get_config('auth/ldap'); - - // configure a temp table - print "Configuring temp table\n"; - if(strtolower($CFG->dbtype) === 'mysql'){ - // help old mysql versions cope with large temp tables - execute_sql('SET SQL_BIG_TABLES=1', false); - execute_sql('CREATE TEMPORARY TABLE ' . $CFG->prefix .'extuser (idnumber VARCHAR(64), PRIMARY KEY (idnumber)) TYPE=MyISAM',false); - } elseif (strtolower($CFG->dbtype) === 'postgres7'){ - $bulk_insert_records = 1; // no support for multiple sets of values - execute_sql('CREATE TEMPORARY TABLE '.$CFG->prefix.'extuser (idnumber VARCHAR(64), PRIMARY KEY (idnumber))',false); - } - - - print "connecting to ldap\n"; - $ldapconnection = auth_ldap_connect(); - if (!$ldapconnection) { - @ldap_close($ldapconnection); - notify("LDAP-module cannot connect to server: $CFG->ldap_host_url"); - return false; - } - - //// - //// get user's list from ldap to sql in a scalable fashion - //// - // prepare some data we'll need - if (! empty($CFG->ldap_objectclass)) { - $CFG->ldap_objectclass="objectClass=*"; - } - - $filter = "(&(".$CFG->ldap_user_attribute."=*)(".$CFG->ldap_objectclass."))"; - - $contexts = explode(";",$CFG->ldap_contexts); - - if (!empty($CFG->ldap_create_context)){ - array_push($contexts, $CFG->ldap_create_context); - } - - $fresult = array(); - $count = 0; - foreach ($contexts as $context) { - $context = trim($context); - if (empty($context)) { - continue; - } - begin_sql(); - if ($CFG->ldap_search_sub) { - //use ldap_search to find first user from subtree - $ldap_result = ldap_search($ldapconnection, $context, - $filter, - array($CFG->ldap_user_attribute)); - } else { - //search only in this context - $ldap_result = ldap_list($ldapconnection, $context, - $filter, - array($CFG->ldap_user_attribute)); - } - - if ($entry = ldap_first_entry($ldapconnection, $ldap_result)) { - do { - $value = ldap_get_values_len($ldapconnection, $entry,$CFG->ldap_user_attribute); - $value = $value[0]; - $count++; - array_push($fresult, $value); - if(count($fresult) >= $bulk_insert_records){ - auth_ldap_bulk_insert($fresult); - //print var_dump($fresult); - $fresult=array(); - } - } - while ($entry = ldap_next_entry($ldapconnection, $entry)); - } - - // insert any remaining users and release mem - if(count($fresult)){ - auth_ldap_bulk_insert($fresult); - $fresult=array(); - } - commit_sql(); - } - // free mem - $ldap_results = 0; - - /// preserve our user database - /// if the temp table is empty, it probably means that something went wrong, exit - /// so as to avoid mass deletion of users; which is hard to undo - $count = get_record_sql('SELECT COUNT(idnumber) AS count, 1 FROM ' . $CFG->prefix .'extuser'); - $count = $count->{'count'}; - if($count < 1){ - print "Did not get any users from LDAP -- error? -- exiting\n"; - exit; - } - - //// - //// User removal - //// - // find users in DB that aren't in ldap -- to be removed! - // this is still not as scalable - $sql = 'SELECT u.id, u.username - FROM ' . $CFG->prefix .'user u LEFT JOIN ' . $CFG->prefix .'extuser e - ON u.idnumber = e.idnumber - WHERE u.auth=\'' . AUTH_LDAP_NAME . '\' AND u.deleted=\'0\' AND e.idnumber IS NULL'; - //print($sql); - $remove_users = get_records_sql($sql); - - if (!empty($remove_users)){ - print "User entries to remove: ". count($remove_users) . "\n"; - - begin_sql(); - foreach ($remove_users as $user) { - //following is copy pasted from admin/user.php - //maybe this should moved to function in lib/datalib.php - unset($updateuser); - $updateuser->id = $user->id; - $updateuser->deleted = "1"; - //$updateuser->username = "$user->username".time(); // Remember it just in case - //$updateuser->email = ""; // Clear this field to free it up - $updateuser->timemodified = time(); - if (update_record("user", $updateuser)) { - // unenrol_student($user->id); // From all courses - // remove_teacher($user->id); // From all courses - // remove_admin($user->id); - delete_records('role_assignments', 'userid', $user->id); // unassign all roles - notify(get_string("deletedactivity", "", fullname($user, true)) ); - } else { - notify(get_string("deletednot", "", fullname($user, true))); - } - //copy pasted part ends - } - commit_sql(); - } - $remove_users = 0; // free mem! - - //// - //// User Updates - //// (time-consuming, optional) - //// - if ($do_updates) { - // narrow down what fields we need to update - $all_keys = array_keys(get_object_vars($pcfg)); - $updatekeys = array(); - foreach ($all_keys as $key) { - if (preg_match('/^field_updatelocal_(.+)$/',$key, $match)) { - // if we have a field to update it from - // and it must be updated 'onlogin' we - // update it on cron - if ( !empty($pcfg->{'field_map_'.$match[1]}) - && $pcfg->{$match[0]} === 'onlogin') { - array_push($updatekeys, $match[1]); // the actual key name - } - } - } - // print_r($all_keys); print_r($updatekeys); - unset($all_keys); unset($key); - - } - if ( $do_updates && !(empty($updatekeys)) ) { // run updates only if relevant - $users = get_records_sql('SELECT u.username, u.id FROM ' . $CFG->prefix . 'user u WHERE u.deleted=0 and u.auth=\'' . AUTH_LDAP_NAME . '\'' ); - if (!empty($users)) { - print "User entries to update: ". count($users). "\n"; - - $sitecontext = get_context_instance(CONTEXT_SYSTEM); - - if ($creatorroles = get_roles_with_capability('moodle/legacy:coursecreator', CAP_ALLOW)) { - - $creatorrole = array_shift($creatorroles); // We can only use one, let's use the first one - - begin_sql(); - $xcount=0; $maxxcount=100; - foreach ($users as $user) { - echo "updating user $user->username \n"; - auth_ldap_update_user_record($user->username, $updatekeys); - - // update course creators - if (!empty($CFG->ldap_creators) && !empty($CFG->ldap_memberattribute) ) { - if (auth_iscreator($user->username)) { // Following calls will not create duplicates - role_assign($creatorrole->id, $user->id, 0, $sitecontext->id, 0, 0, 0, 'ldap'); - $xcount++; - } else { - role_unassign($creatorrole->id, $user->id, 0, $sitecontext->id); - $xcount++; - } - } - - if ($xcount++ > $maxxcount) { - commit_sql(); - begin_sql(); - $xcount=0; - } - } - commit_sql(); - unset($users); // free mem - } - } - } // end do updates - - //// - //// User Additions - //// - // find users missing in DB that are in LDAP - // note that get_records_sql wants at least 2 fields returned, - // and gives me a nifty object I don't want. - $sql = 'SELECT e.idnumber,1 - FROM ' . $CFG->prefix .'extuser e LEFT JOIN ' . $CFG->prefix .'user u - ON e.idnumber = u.idnumber - WHERE u.id IS NULL OR (u.id IS NOT NULL AND u.deleted=1)'; - $add_users = get_records_sql($sql); // get rid of the fat - - if(!empty($add_users)){ - print "User entries to add: ". count($add_users). "\n"; - - if ($creatorroles = get_roles_with_capability('moodle/legacy:coursecreator', CAP_ALLOW)) { - $creatorrole = array_shift($roles); // We can only use one, let's use the first one - } - - begin_sql(); - foreach($add_users as $user){ - $user = auth_get_userinfo_asobj($user->idnumber); - //print $user->username . "\n"; - - // prep a few params - $user->modified = time(); - $user->confirmed = 1; - $user->auth = AUTH_LDAP_NAME; - - // insert it - $old_debug=$CFG->debug; - $CFG->debug=10; - - // maybe the user has been deleted before - if ($old_user = get_record('user', 'idnumber', $user->idnumber, 'deleted', 1)) { - $user->id = $old_user->id; - set_field('user', 'deleted', 0, 'idnumber', $user->idnumber); - echo "Revived user $user->username with idnumber $user->idnumber id $user->id\n"; - } elseif ($id=insert_record ('user',$user)) { // it is truly a new user - echo "inserted user $user->username with idnumber $user->idnumber id $id\n"; - $user->id = $id; - } else { - echo "error inserting user $user->username with idnumber $user->idnumber \n"; - } - $CFG->debug=$old_debug; - $userobj = auth_ldap_update_user_record($user->username); - if(isset($CFG->{'auth_ldap_forcechangepassword'}) && $CFG->{'auth_ldap_forcechangepassword'}){ - set_user_preference('auth_forcepasswordchange', 1, $userobj->id); - } - - if (isset($creatorrole->id) && !empty($CFG->ldap_creators) && !empty($CFG->ldap_memberattribute) ) { - if (auth_iscreator($user->username)) { - if (user_has_role_assignment($user->id, $creatorrole->id, $sitecontext->id)) { - role_unassign($creatorrole->id, $user->id, 0, $sitecontext->id); - } else { - role_assign($creatorrole->id, $user->id, 0, $sitecontext->id, 0, 0, 0, 'ldap'); - } - } - } - } - commit_sql(); - unset($add_users); // free mem - } - return true; -} - -function auth_ldap_update_user_record($username, $updatekeys=false) { -/// will update a local user record from an external source. -/// is a lighter version of the one in moodlelib -- won't do -/// expensive ops such as enrolment -/// -/// If you don't pass $updatekeys, there is a performance hit and -/// values removed from LDAP won't be removed from moodle. - - global $CFG; - - $pcfg = get_config('auth/ldap'); - - //just in case check text case - $username = trim(moodle_strtolower($username)); - - // get the current user record - $user = get_record('user', 'username', $username); - if (empty($user)) { // trouble - error_log("Cannot update non-existent user: $username"); - die; - } - - if (function_exists('auth_get_userinfo')) { - if ($newinfo = auth_get_userinfo($username)) { - $newinfo = truncate_userinfo($newinfo); - - if (empty($updatekeys)) { // all keys? this does not support removing values - $updatekeys = array_keys($newinfo); - } - - foreach ($updatekeys as $key){ - unset($value); - if (isset($newinfo[$key])) { - $value = $newinfo[$key]; - $value = addslashes(stripslashes($value)); // Just in case - } else { - $value = ''; - } - if (!empty($pcfg->{'field_updatelocal_' . $key})) { - if ($user->{$key} != $value) { // only update if it's changed - set_field('user', $key, $value, 'username', $username); - } - } - } - } - } - return get_record_select("user", "username = '$username' AND deleted <> '1'"); -} - -function auth_ldap_bulk_insert($users){ -// bulk insert in SQL's temp table -// $users is an array of usernames - global $CFG; - - // bulk insert -- superfast with $bulk_insert_records - $sql = 'INSERT INTO '.$CFG->prefix.'extuser (idnumber) VALUES '; - // make those values safe - $users = array_map('addslashes', $users); - // join and quote the whole lot - $sql = $sql . '(\'' . join('\'),(\'', $users) . '\')'; - print "+ " . count($users) . " users\n"; - execute_sql($sql, false); - -} - - -/* - * auth_user_activate activates user in external db. - * - * Activates (enables) user in external db so user can login to external db - * - * @param mixed $username username - * @return boolen result - */ -function auth_user_activate ($username) { - - global $CFG; - - $ldapconnection = auth_ldap_connect(); - - $userdn = auth_ldap_find_userdn($ldapconnection, $username); - switch ($CFG->ldap_user_type) { - case 'edir': - $newinfo['loginDisabled']="FALSE"; - break; - default: - error ('auth: ldap auth_user_activate() does not support selected usertype:"'.$CFG->ldap_user_type.'" (..yet)'); - } - $result = ldap_modify($ldapconnection, $userdn, $newinfo); - ldap_close($ldapconnection); - return $result; -} - -/* - * auth_user_disables disables user in external db. - * - * Disables user in external db so user can't login to external db - * - * @param mixed $username username - * @return boolean result - */ -function auth_user_disable ($username) { - global $CFG; - - $ldapconnection = auth_ldap_connect(); - - $userdn = auth_ldap_find_userdn($ldapconnection, $username); - switch ($CFG->ldap_user_type) { - case 'edir': - $newinfo['loginDisabled']="TRUE"; - break; - default: - error ('auth: ldap auth_user_disable() does not support selected usertype (..yet)'); - } - $result = ldap_modify($ldapconnection, $userdn, $newinfo); - ldap_close($ldapconnection); - return $result; -} - -/* - * auth_iscreator returns true if user should be coursecreator - * - * auth_iscreator returns true if user should be coursecreator - * - * @param mixed $username username - * @return boolean result - */ -function auth_iscreator($username=0) { -///if user is member of creator group return true - global $USER , $CFG; - auth_ldap_init(); - - if (! $username) { - $username=$USER->username; - } - - if ((! $CFG->ldap_creators) OR (! $CFG->ldap_memberattribute)) { - return null; - } - - return auth_ldap_isgroupmember($username, $CFG->ldap_creators); - -} - -/* - * auth_user_update saves userinformation from moodle to external db - * - * Called when the user record is updated. - * Modifies user in external database. It takes olduser (before changes) and newuser (after changes) - * conpares information saved modified information to external db. - * - * @param mixed $olduser Userobject before modifications - * @param mixed $newuser Userobject new modified userobject - * @return boolean result - * - */ -function auth_user_update($olduser, $newuser) { - - global $USER , $CFG; - - $pcfg = get_config('auth/ldap'); - - $ldapconnection = auth_ldap_connect(); - - $result = array(); - $search_attribs = array(); - - $attrmap = auth_ldap_attributes(); - foreach ($attrmap as $key=>$values) { - if (!is_array($values)) { - $values = array($values); - } - foreach ($values as $value) { - if (!in_array($value, $search_attribs)) { - array_push($search_attribs, $value); - } - } - } - - $user_dn = auth_ldap_find_userdn($ldapconnection, $olduser->username); - - $user_info_result = ldap_read($ldapconnection,$user_dn,$CFG->ldap_objectclass, $search_attribs); - - if ($user_info_result){ - - $user_entry = auth_ldap_get_entries($ldapconnection, $user_info_result); - if (count($user_entry) > 1) { - trigger_error("ldap: Strange! More than one user record found in ldap. Only using the first one."); - } - $user_entry = $user_entry[0]; - - //error_log(var_export($user_entry) . 'fpp' ); - - foreach ($attrmap as $key=>$ldapkeys){ - - // only process if the moodle field ($key) has changed and we - // are set to update LDAP with it - if ($olduser->$key !== $newuser->$key && - !empty($pcfg->{'field_updateremote_'. $key})) { - - // for ldap values that could be in more than one - // ldap key, we will do our best to match - // where they came from - $ambiguous = true; - $changed = false; - if (!is_array($ldapkeys)) { - $ldapkeys = array($ldapkeys); - } - if (count($ldapkeys) < 2) { - $ambiguous = false; - } - - foreach ($ldapkeys as $ldapkey) { - $ldapkey = strtolower($ldapkey); - $ldapvalue = $user_entry[$ldapkey][0]; - if (!$ambiguous) { - // skip update if the values already match - if( !($newuser->$key === $ldapvalue) ){ - ldap_modify($ldapconnection, $user_dn, array($ldapkey => $newuser->$key)); - } else { - error_log("Skip updating field $key for entry $user_dn: it seems to be already same on LDAP. " . - " old moodle value: '" . $olduser->$key . - "' new value '" . $newuser->$key . - "' current value in ldap entry " . $ldapvalue); - } - } else { // ambiguous - // value empty before in Moodle (and LDAP) - use 1st ldap candidate field - // no need to guess - if (empty($olduser->$key)) { // value empty before - use 1st ldap candidate - if(ldap_modify($ldapconnection, $user_dn, array($ldapkey => $newuser->$key))){ - $changed=true; - last; - } else { - error ('Error updating LDAP record. Error code: ' - . ldap_errno($ldapconnection) . '; Error string : ' - . ldap_err2str(ldap_errno($ldapconnection))); - } - } - - // we found which ldap key to update! - if ( !empty($ldapvalue) && $olduser->$key === $ldapvalue ) { - // error_log("Matched: ". $olduser->$key . " === " . $ldapvalue); - if(ldap_modify($ldapconnection, $user_dn, array($ldapkey => $newuser->$key))){ - $changed=true; - last; - } else { - error ('Error updating LDAP record. Error code: ' - . ldap_errno($ldapconnection) . '; Error string : ' - . ldap_err2str(ldap_errno($ldapconnection))); - } - } - } - } - - if ($ambiguous AND !$changed) { - error_log("Failed to update LDAP with ambiguous field $key". - " old moodle value: '" . $olduser->$key . - "' new value '" . $newuser->$key ); - } - } - } - - - } else { - error_log("ERROR:No user found in LDAP"); - @ldap_close($ldapconnection); - return false; - } - - @ldap_close($ldapconnection); - - return true; - -} - -/* - * changes userpassword in external db - * - * called when the user password is updated. - * changes userpassword in external db - * - * @param mixed $username Username - * @param mixed $newpassword Plaintext password - * @param mixed $oldpassword Plaintext old password to bind ldap with - * @return boolean result - * - */ -function auth_user_update_password($username, $newpassword) { -/// called when the user password is updated -- it assumes it is called by an admin -/// or that you've otherwise checked the user's credentials -/// IMPORTANT: $newpassword must be cleartext, not crypted/md5'ed - - global $CFG, $USER; - $result = false; - - $ldapconnection = auth_ldap_connect(); - - $user_dn = auth_ldap_find_userdn($ldapconnection, $username); - - if(!$user_dn){ - error_log('LDAP Error in auth_user_update_password(). No DN for: ' . $username); - return false; - } - - switch ($CFG->ldap_user_type) { - case 'edir': - //Change password - $result = ldap_modify($ldapconnection, $user_dn, array('userPassword' => $newpassword)); - if(!$result){ - error_log('LDAP Error in auth_user_update_password(). Error code: ' - . ldap_errno($ldapconnection) . '; Error string : ' - . ldap_err2str(ldap_errno($ldapconnection))); - } - //Update password expiration time, grace logins count - $search_attribs = array($CFG->ldap_expireattr, 'passwordExpirationInterval','loginGraceLimit' ); - $sr = ldap_read($ldapconnection, $user_dn, 'objectclass=*', $search_attribs); - if ($sr) { - $info=auth_ldap_get_entries($ldapconnection, $sr); - $newattrs = array(); - if (!empty($info[0][$CFG->ldap_expireattr][0])) { - //Set expiration time only if passwordExpirationInterval is defined - if (!empty($info[0]['passwordExpirationInterval'][0])) { - $expirationtime = time() + $info[0]['passwordExpirationInterval'][0]; - $ldapexpirationtime = auth_ldap_unix2expirationtime($expirationtime); - $newattrs['passwordExpirationTime'] = $ldapexpirationtime; - } - - //set gracelogin count - if (!empty($info[0]['loginGraceLimit'][0])) { - $newattrs['loginGraceRemaining']= $info[0]['loginGraceLimit'][0]; - } - - //Store attribute changes to ldap - $result = ldap_modify($ldapconnection, $user_dn, $newattrs); - if(!$result){ - error_log('LDAP Error in auth_user_update_password() when modifying expirationtime and/or gracelogins. Error code: ' - . ldap_errno($ldapconnection) . '; Error string : ' - . ldap_err2str(ldap_errno($ldapconnection))); - } - } - } else { - error_log('LDAP Error in auth_user_update_password() when reading password expiration time. Error code: ' - . ldap_errno($ldapconnection) . '; Error string : ' - . ldap_err2str(ldap_errno($ldapconnection))); - } - break; - default: - $usedconnection = &$ldapconnection; - // send ldap the password in cleartext, it will md5 it itself - $result = ldap_modify($ldapconnection, $user_dn, array('userPassword' => $newpassword)); - if(!$result){ - error_log('LDAP Error in auth_user_update_password(). Error code: ' - . ldap_errno($ldapconnection) . '; Error string : ' - . ldap_err2str(ldap_errno($ldapconnection))); - } - - } - - - @ldap_close($ldapconnection); - - return $result; -} - -//PRIVATE FUNCTIONS starts -//private functions are named as auth_ldap* - -/** - * returns predefined usertypes - * - * @return array of predefined usertypes - */ - -function auth_ldap_suppported_usertypes (){ -// returns array of supported usertypes (schemas) -// If you like to add our own please name and describe it here -// And then add case clauses in relevant places in functions -// iauth_ldap_init, auth_user_create, auth_check_expire, auth_check_grace - $types['edir']='Novell Edirectory'; - $types['rfc2307']='posixAccount (rfc2307)'; - $types['rfc2307bis']='posixAccount (rfc2307bis)'; - $types['samba']='sambaSamAccount (v.3.0.7)'; - $types['ad']='MS ActiveDirectory'; - return $types; -} - - -/** - * initializes needed variables for ldap-module - * - * Uses names defined in auth_ldap_supported_usertypes. - * $default is first defined as: - * $default['pseudoname'] = array( - * 'typename1' => 'value', - * 'typename2' => 'value' - * .... - * ); - * - * @return array of default values - */ - -function auth_ldap_getdefaults(){ - $default['ldap_objectclass'] = array( - 'edir' => 'User', - 'rfc2703' => 'posixAccount', - 'rfc2703bis' => 'posixAccount', - 'samba' => 'sambaSamAccount', - 'ad' => 'user', - 'default' => '*' - ); - $default['ldap_user_attribute'] = array( - 'edir' => 'cn', - 'rfc2307' => 'uid', - 'rfc2307bis' => 'uid', - 'samba' => 'uid', - 'ad' => 'cn', - 'default' => 'cn' - ); - $default['ldap_memberattribute'] = array( - 'edir' => 'member', - 'rfc2307' => 'member', - 'rfc2307bis' => 'member', - 'samba' => 'member', - 'ad' => 'member', - 'default' => 'member' - ); - $default['ldap_memberattribute_isdn'] = array( - 'edir' => '1', - 'rfc2307' => '0', - 'rfc2307bis' => '1', - 'samba' => '0', //is this right? - 'ad' => '1', - 'default' => '0' - ); - $default['ldap_expireattr'] = array ( - 'edir' => 'passwordExpirationTime', - 'rfc2307' => 'shadowExpire', - 'rfc2307bis' => 'shadowExpire', - 'samba' => '', //No support yet - 'ad' => '', //No support yet - 'default' => '' - ); - return $default; -} - -/** - * return binaryfields of selected usertype - * - * - * @return array - */ - -function auth_ldap_getbinaryfields () { - global $CFG; - $binaryfields = array ( - 'edir' => array('guid'), - 'rfc2703' => array(), - 'rfc2703bis' => array(), - 'samba' => array(), - 'ad' => array(), - 'default' => '*' - ); - if (!empty($CFG->ldap_user_type)) { - return $binaryfields[$CFG->ldap_user_type]; - } else { - return $binaryfields['default']; - } - } - -function auth_ldap_isbinary ($field) { - if (!isset($field)) { - return null ; - } - return array_search($field, auth_ldap_getbinaryfields()); -} - -/** - * set $CFG-values for ldap_module - * - * Get default configuration values with auth_ldap_getdefaults() - * and by using this information $CFG-> values are set - * If $CFG->value is alredy set current value is honored. - * - * - */ -function auth_ldap_init () { - global $CFG; - - $default = auth_ldap_getdefaults(); - - foreach ($default as $key => $value) { - //set defaults if overriding fields not set - if(empty($CFG->{$key})) { - if (!empty($CFG->ldap_user_type) && !empty($default[$key][$CFG->ldap_user_type])) { - $CFG->{$key} = $default[$key][$CFG->ldap_user_type]; - }else { - //use default value if user_type not set - if(!empty($default[$key]['default'])){ - $CFG->$key = $default[$key]['default']; - }else { - unset($CFG->$key); - } - } - } - } - //hack prefix to objectclass - if ('objectClass=' != substr($CFG->ldap_objectclass, 0, 12)) { - $CFG->ldap_objectclass = 'objectClass='.$CFG->ldap_objectclass; - } - - //all chages go in $CFG , no need to return value -} - -/** - * take expirationtime and return it as unixseconds - * - * takes expriration timestamp as readed from ldap - * returns it as unix seconds - * depends on $CFG->usertype variable - * - * @param mixed time Time stamp readed from ldap as it is. - * @return timestamp - */ - -function auth_ldap_expirationtime2unix ($time) { - - global $CFG; - $result = false; - switch ($CFG->ldap_user_type) { - case 'edir': - $yr=substr($time,0,4); - $mo=substr($time,4,2); - $dt=substr($time,6,2); - $hr=substr($time,8,2); - $min=substr($time,10,2); - $sec=substr($time,12,2); - $result = mktime($hr,$min,$sec,$mo,$dt,$yr); - break; - case 'posix': - $result = $time * DAYSECS ; //The shadowExpire contains the number of DAYS between 01/01/1970 and the actual expiration date - break; - default: - error('CFG->ldap_user_type not defined or function auth_ldap_expirationtime2unix does not support selected type!'); -} - return $result; -} - -/** - * takes unixtime and return it formated for storing in ldap - * - * @param integer unix time stamp - */ -function auth_ldap_unix2expirationtime ($time) { - global $CFG; - $result = false; - switch ($CFG->ldap_user_type) { - case 'edir': - $result=date('YmdHis', $time).'Z'; - break; - case 'posix': - $result = $time ; //Already in correct format - break; - default: - error('CFG->ldap_user_type not defined or function auth_ldap_unixi2expirationtime does not support selected type!'); - } - return $result; - -} - -/* - * checks if user belong to specific group(s) - * - * Returns true if user belongs group in grupdns string. - * - * @param mixed $username username - * @param mixed $groupdns string of group dn separated by ; - * - */ -function auth_ldap_isgroupmember ($username='', $groupdns='') { -// Takes username and groupdn(s) , separated by ; -// Returns true if user is member of any given groups - - global $CFG ; - $result = false; - $ldapconnection = auth_ldap_connect(); - - if (empty($username) OR empty($groupdns)) { - return $result; - } - - if ($CFG->ldap_memberattribute_isdn) { - $username=auth_ldap_find_userdn($ldapconnection, $username); - } - if (! $username ) { - return $result; - } - - $groups = explode(";",$groupdns); - - foreach ($groups as $group){ - $group = trim($group); - if (empty($group)) { - continue; - } - //echo "Checking group $group for member $username\n"; - $search = @ldap_read($ldapconnection, $group, '('.$CFG->ldap_memberattribute.'='.$username.')', array($CFG->ldap_memberattribute)); - - if (!empty($search) AND ldap_count_entries($ldapconnection, $search)) {$info = auth_ldap_get_entries($ldapconnection, $search); - - if (count($info) > 0 ) { - // user is member of group - $result = true; - break; - } - } -} - - return $result; - -} - -/** - * connects to ldap server - * - * Tries connect to specified ldap servers. - * Returns connection result or error. - * - * @return connection result - */ -function auth_ldap_connect($binddn='',$bindpwd=''){ -/// connects and binds to ldap-server -/// Returns connection result - - global $CFG; - auth_ldap_init(); - - //Select bind password, With empty values use - //ldap_bind_* variables or anonymous bind if ldap_bind_* are empty - if ($binddn == '' AND $bindpwd == '') { - if (!empty($CFG->ldap_bind_dn)){ - $binddn = $CFG->ldap_bind_dn; - } - if (!empty($CFG->ldap_bind_pw)){ - $bindpwd = $CFG->ldap_bind_pw; - } - } - - $urls = explode(";",$CFG->ldap_host_url); - - foreach ($urls as $server){ - $server = trim($server); - if (empty($server)) { - continue; - } - - $connresult = ldap_connect($server); - //ldap_connect returns ALWAYS true - - if (!empty($CFG->ldap_version)) { - ldap_set_option($connresult, LDAP_OPT_PROTOCOL_VERSION, $CFG->ldap_version); - } - - if (!empty($binddn)){ - //bind with search-user - //$debuginfo .= 'Using bind user'.$binddn.'and password:'.$bindpwd; - $bindresult=ldap_bind($connresult, $binddn,$bindpwd); - } else { - //bind anonymously - $bindresult=@ldap_bind($connresult); - } - - if (!empty($CFG->ldap_opt_deref)) { - ldap_set_option($connresult, LDAP_OPT_DEREF, $CFG->ldap_opt_deref); - } - - if ($bindresult) { - return $connresult; - } - - $debuginfo .= "
Server: '$server'
Connection: '$connresult'
Bind result: '$bindresult'
"; - } - - //If any of servers are alive we have already returned connection - error("LDAP-module cannot connect any LDAP servers : $debuginfo"); - return false; -} - -/** - * retuns dn of username - * - * Search specified contexts for username and return user dn - * like: cn=username,ou=suborg,o=org - * - * @param mixed $ldapconnection $ldapconnection result - * @param mixed $username username - * - */ - -function auth_ldap_find_userdn ($ldapconnection, $username){ - - global $CFG; - - //default return value - $ldap_user_dn = FALSE; - - //get all contexts and look for first matching user - $ldap_contexts = explode(";",$CFG->ldap_contexts); - - if (!empty($CFG->ldap_create_context)){ - array_push($ldap_contexts, $CFG->ldap_create_context); - } - - foreach ($ldap_contexts as $context) { - - $context = trim($context); - if (empty($context)) { - continue; - } - - if ($CFG->ldap_search_sub){ - //use ldap_search to find first user from subtree - $ldap_result = ldap_search($ldapconnection, $context, "(".$CFG->ldap_user_attribute."=".$username.")",array($CFG->ldap_user_attribute)); - - } else { - //search only in this context - $ldap_result = ldap_list($ldapconnection, $context, "(".$CFG->ldap_user_attribute."=".$username.")",array($CFG->ldap_user_attribute)); - } - - $entry = ldap_first_entry($ldapconnection,$ldap_result); - - if ($entry){ - $ldap_user_dn = ldap_get_dn($ldapconnection, $entry); - break ; - } - } - - return $ldap_user_dn; -} - -/** - * retuns user attribute mappings between moodle and ldap - * - * @return array - */ - -function auth_ldap_attributes (){ - - global $CFG; - - $config = (array)$CFG; - $fields = array("firstname", "lastname", "email", "phone1", "phone2", - "department", "address", "city", "country", "description", - "idnumber", "lang" ); - - $pcfg = get_config('auth/ldap'); - - $moodleattributes = array(); - foreach ($fields as $field) { - if (!empty($pcfg->{"field_map_$field"})) { - $moodleattributes[$field] = $pcfg->{"field_map_$field"}; - if (preg_match('/,/',$moodleattributes[$field])) { - $moodleattributes[$field] = explode(',', $moodleattributes[$field]); // split ? - } - } - } - $moodleattributes['username']=$config["ldap_user_attribute"]; - return $moodleattributes; -} - -/** - * return all usernames from ldap - * - * @return array - */ - -function auth_ldap_get_userlist($filter="*") { -/// returns all users from ldap servers - global $CFG; - - $fresult = array(); - - $ldapconnection = auth_ldap_connect(); - - if ($filter=="*") { - $filter = "(&(".$CFG->ldap_user_attribute."=*)(".$CFG->ldap_objectclass."))"; - } - - $contexts = explode(";",$CFG->ldap_contexts); - - if (!empty($CFG->ldap_create_context)){ - array_push($contexts, $CFG->ldap_create_context); - } - - foreach ($contexts as $context) { - - $context = trim($context); - if (empty($context)) { - continue; - } - - if ($CFG->ldap_search_sub) { - //use ldap_search to find first user from subtree - $ldap_result = ldap_search($ldapconnection, $context,$filter,array($CFG->ldap_user_attribute)); - } else { - //search only in this context - $ldap_result = ldap_list($ldapconnection, $context, - $filter, - array($CFG->ldap_user_attribute)); - } - - $users = auth_ldap_get_entries($ldapconnection, $ldap_result); - - //add found users to list - for ($i=0;$ildap_user_attribute][0]) ); - } - } - - return $fresult; -} - -/** - * return entries from ldap - * - * Returns values like ldap_get_entries but is - * binary compatible and return all attributes as array - * - * @return array ldap-entries - */ - -function auth_ldap_get_entries($conn, $searchresult){ -//Returns values like ldap_get_entries but is -//binary compatible - $i=0; - $fresult=array(); - $entry = ldap_first_entry($conn, $searchresult); - do { - $attributes = @ldap_get_attributes($conn, $entry); - for($j=0; $j<$attributes['count']; $j++) { - $values = ldap_get_values_len($conn, $entry,$attributes[$j]); - if (is_array($values)) { - $fresult[$i][$attributes[$j]] = $values; - } else { - $fresult[$i][$attributes[$j]] = array($values); - } - } - $i++; - } - while ($entry = @ldap_next_entry($conn, $entry)); - //were done - return ($fresult); -} - - - - -?> diff --git a/auth/manual/auth.php b/auth/manual/auth.php new file mode 100644 index 0000000000..e6311c7a12 --- /dev/null +++ b/auth/manual/auth.php @@ -0,0 +1,121 @@ +config = get_config('auth/manual'); + } + + /** + * Returns true if the username and password work and false if they are + * wrong or don't exist. + * + * @param string $username The username + * @param string $password The password + * @returns bool Authentication success or failure. + */ + function user_login ($username, $password) { + if ($user = get_record('user', 'username', $username)) { + if (validate_internal_user_password($user, $password)) { + return true; + // return AUTH_OK; + } + } + return false; + // return AUTH_FAIL; + } + + /* + * Updates the user's password. + * + * called when the user password is updated. + * + * @param mixed $username Username + * @param mixed $newpassword Plaintext password + * @return boolean result + * + */ + function user_update_password($username, $newpassword) { + $user = get_complete_user_data('username', $username); + return update_internal_user_password($user, $newpassword); + } + + /** + * Returns true if this authentication plugin is 'internal'. + * + * @returns bool + */ + function is_internal() { + return true; + } + + /** + * Returns true if this authentication plugin can change the user's + * password. + * + * @returns bool + */ + function can_change_password() { + return true; + } + + /** + * Returns the URL for changing the user's pw, or false if the default can + * be used. + * + * @returns bool + */ + function change_password_url() { + return false; + } + + /** + * Prints a form for configuring this authentication plugin. + * + * This function is called from admin/auth.php, and outputs a full page with + * a form for configuring this plugin. + * + * @param array $page An object containing all the data for this page. + */ + function config_form($config, $err) { + include "config.html"; + } + + /** + * Processes and stores configuration data for this authentication plugin. + */ + function process_config($config) { + return true; + } + +} + +?> diff --git a/auth/manual/config.html b/auth/manual/config.html index 7288eb46f8..59e4bf953e 100644 --- a/auth/manual/config.html +++ b/auth/manual/config.html @@ -1,11 +1,11 @@ - - : - - - - - - - - - + +
+ + + +
diff --git a/auth/manual/lib.php b/auth/manual/lib.php deleted file mode 100644 index a398cb4e84..0000000000 --- a/auth/manual/lib.php +++ /dev/null @@ -1,16 +0,0 @@ - diff --git a/auth/nntp/auth.php b/auth/nntp/auth.php new file mode 100644 index 0000000000..a86d1cd4c9 --- /dev/null +++ b/auth/nntp/auth.php @@ -0,0 +1,123 @@ +config = get_config('auth/nntp'); + } + + /** + * Returns true if the username and password work and false if they are + * wrong or don't exist. + * + * @param string $username The username + * @param string $password The password + * @returns bool Authentication success or failure. + */ + function user_login ($username, $password) { + if (! function_exists('imap_open')) { + error("Cannot use NNTP authentication. The PHP IMAP module is not installed."); + } + + global $CFG; + + // try each multiple host + $hosts = split(';', $this->config->host); + foreach ($hosts as $host) { + $host = '{' . trim($host) . ':' . $this->config->port . '/nntp}'; + + error_reporting(0); + $connection = imap_open($host, $username, $password, OP_HALFOPEN); + error_reporting($CFG->debug); + + if ($connection) { + imap_close($connection); + return true; + } + } + return false; + } + + /** + * Returns true if this authentication plugin is 'internal'. + * + * @returns bool + */ + function is_internal() { + return false; + } + + /** + * Returns true if this authentication plugin can change the user's + * password. + * + * @returns bool + */ + function can_change_password() { + return false; + } + + /** + * Prints a form for configuring this authentication plugin. + * + * This function is called from admin/auth.php, and outputs a full page with + * a form for configuring this plugin. + * + * @param array $page An object containing all the data for this page. + */ + function config_form($config, $err) { + include "config.html"; + } + + /** + * Processes and stores configuration data for this authentication plugin. + */ + function process_config($config) { + // set to defaults if undefined + if (!isset ($config->host)) { + $config->host = '127.0.0.1'; + } + if (!isset ($config->port)) { + $config->port = '119'; + } + if (!isset($config->changepasswordurl)) { + $config->changepasswordurl = ''; + } + + // save settings + set_config('host', $config->host, 'auth/nntp'); + set_config('port', $config->port, 'auth/nntp'); + set_config('changepasswordurl', $config->changepasswordurl, 'auth/nntp'); + + return true; + } + +} + +?> diff --git a/auth/nntp/config.html b/auth/nntp/config.html index f8216d086b..abcd86b645 100644 --- a/auth/nntp/config.html +++ b/auth/nntp/config.html @@ -1,43 +1,75 @@ auth_nntphost)) { - $config->auth_nntphost = "127.0.0.1"; - } - if (!isset($config->auth_nntpport)) { - $config->auth_nntpport = "119"; - } + +// set to defaults if undefined +if (!isset($config->host)) { + $config->host = "127.0.0.1"; +} +if (!isset($config->port)) { + $config->port = "119"; +} +if (!isset($config->changepasswordurl)) { + $config->changepasswordurl = ''; +} + ?> + - + - - + + - - + + - \ No newline at end of file + + +
auth_nntphost: host: - - + + - - +
auth_nntpport: - - - port: - + +
: - - changepasswordurl: - - + +
diff --git a/auth/nntp/lib.php b/auth/nntp/lib.php deleted file mode 100644 index 502d051edd..0000000000 --- a/auth/nntp/lib.php +++ /dev/null @@ -1,30 +0,0 @@ -auth_nntphost); // Could be multiple hosts - - foreach ($hosts as $host) { // Try each host in turn - $host = '{'.trim($host).":$CFG->auth_nntpport/nntp}"; - - error_reporting(0); - $connection = imap_open($host, $username, $password, OP_HALFOPEN); - error_reporting($CFG->debug); - - if ($connection) { - imap_close($connection); - return true; - } - } - - return false; // No match -} - - -?> diff --git a/auth/none/auth.php b/auth/none/auth.php new file mode 100644 index 0000000000..520c832814 --- /dev/null +++ b/auth/none/auth.php @@ -0,0 +1,118 @@ +config = get_config('auth/none'); + } + + /** + * Returns true if the username and password work or don't exist and false + * if the user exists and the password is wrong. + * + * @param string $username The username + * @param string $password The password + * @returns bool Authentication success or failure. + */ + function user_login ($username, $password) { + if ($user = get_record('user', 'username', $username)) { + return validate_internal_user_password($user, $password); + } + return true; + } + + /* + * Updates the user's password. + * + * called when the user password is updated. + * + * @param mixed $username Username + * @param mixed $newpassword Plaintext password + * @return boolean result + * + */ + function user_update_password($username, $newpassword) { + $user = get_complete_user_data('username', $username); + return update_internal_user_password($user, $newpassword); + } + + /** + * Returns true if this authentication plugin is 'internal'. + * + * @returns bool + */ + function is_internal() { + return true; + } + + /** + * Returns true if this authentication plugin can change the user's + * password. + * + * @returns bool + */ + function can_change_password() { + return true; + } + + /** + * Returns the URL for changing the user's pw, or false if the default can + * be used. + * + * @returns bool + */ + function change_password_url() { + return false; + } + + /** + * Prints a form for configuring this authentication plugin. + * + * This function is called from admin/auth.php, and outputs a full page with + * a form for configuring this plugin. + * + * @param array $page An object containing all the data for this page. + */ + function config_form($config, $err) { + include "config.html"; + } + + /** + * Processes and stores configuration data for this authentication plugin. + */ + function process_config($config) { + return true; + } + +} + +?> diff --git a/auth/none/config.html b/auth/none/config.html index e3056dbba4..f8e7d03620 100644 --- a/auth/none/config.html +++ b/auth/none/config.html @@ -1,3 +1,11 @@
- \ No newline at end of file + + + +
diff --git a/auth/none/lib.php b/auth/none/lib.php deleted file mode 100644 index f3734dce18..0000000000 --- a/auth/none/lib.php +++ /dev/null @@ -1,17 +0,0 @@ - diff --git a/auth/pam/auth.php b/auth/pam/auth.php new file mode 100644 index 0000000000..037ebd6672 --- /dev/null +++ b/auth/pam/auth.php @@ -0,0 +1,118 @@ +config = get_config('auth/pam'); + $this->errormessage = ''; + } + + /** + * Returns true if the username and password work and false if they are + * wrong or don't exist. + * + * @param string $username The username + * @param string $password The password + * @returns bool Authentication success or failure. + */ + function user_login ($username, $password) { + // variable to store possible errors during authentication + $errormessage = str_repeat(' ', 2048); + + // just for testing and debugging + // error_reporting(E_ALL); + if (pam_auth($username, $password, &$errormessage)) { + return true; + } + else { + $this->lasterror = $errormessage; + return false; + } + } + + /** + * Returns true if this authentication plugin is 'internal'. + * + * @returns bool + */ + function is_internal() { + return false; + } + + /** + * Returns true if this authentication plugin can change the user's + * password. + * + * @returns bool + */ + function can_change_password() { + return false; + } + + /** + * Prints a form for configuring this authentication plugin. + * + * This function is called from admin/auth.php, and outputs a full page with + * a form for configuring this plugin. + * + * @param array $page An object containing all the data for this page. + */ + function config_form($config, $err) { + include "config.html"; + } + + /** + * Processes and stores configuration data for this authentication plugin. + */ + function process_config($config) { + return true; + } + +} + +?> diff --git a/auth/pam/config.html b/auth/pam/config.html index fa9c94a07a..ba6c0eaf10 100644 --- a/auth/pam/config.html +++ b/auth/pam/config.html @@ -1,10 +1,11 @@ - -

:

- - - - - - - - \ No newline at end of file + +
+ + + +
diff --git a/auth/pam/lib.php b/auth/pam/lib.php deleted file mode 100644 index 24fd39a775..0000000000 --- a/auth/pam/lib.php +++ /dev/null @@ -1,42 +0,0 @@ - diff --git a/auth/pop3/auth.php b/auth/pop3/auth.php new file mode 100644 index 0000000000..1770fc7a7f --- /dev/null +++ b/auth/pop3/auth.php @@ -0,0 +1,159 @@ +config = get_config('auth/pop3'); + } + + /** + * Returns true if the username and password work and false if they are + * wrong or don't exist. + * + * @param string $username The username + * @param string $password The password + * @returns bool Authentication success or failure. + */ + function user_login($username, $password) { + if (! function_exists('imap_open')) { + error("Cannot use POP3 authentication. The PHP IMAP module is not installed."); + } + + global $CFG; + $hosts = split(';', $this->config->host); // Could be multiple hosts + foreach ($hosts as $host) { // Try each host in turn + $host = trim($host); + + // remove any trailing slash + if (substr($host, -1) == '/') { + $host = substr($host, 0, strlen($host) - 1); + } + + switch ($this->config->type) { + case 'pop3': + $host = '{'.$host.":{$this->config->port}/pop3}{$this->config->mailbox}"; + break; + + case 'pop3notls': + $host = '{'.$host.":{$this->config->port}/pop3/notls}{$this->config->mailbox}"; + break; + + case 'pop3cert': + $host = '{'.$host.":{$this->config->port}/pop3/ssl/novalidate-cert}{$this->config->mailbox}"; + break; + } + + error_reporting(0); + $connection = imap_open($host, $username, $password); + error_reporting($CFG->debug); + + if ($connection) { + imap_close($connection); + return true; + } + } + return false; // No matches found + } + + /** + * Returns true if this authentication plugin is 'internal'. + * + * @returns bool + */ + function is_internal() { + return false; + } + + /** + * Returns true if this authentication plugin can change the user's + * password. + * + * @returns bool + */ + function can_change_password() { + return false; + } + + /** + * Returns the URL for changing the user's pw, or false if the default can + * be used. + * + * @returns bool + */ + function change_password_url() { + return $CFG->changepasswordurl; // TODO: will this be global? + //return $this->config->changepasswordurl; + } + + /** + * Prints a form for configuring this authentication plugin. + * + * This function is called from admin/auth.php, and outputs a full page with + * a form for configuring this plugin. + * + * @param array $page An object containing all the data for this page. + */ + function config_form($config, $err) { + include "config.html"; + } + + /** + * Processes and stores configuration data for this authentication plugin. + */ + function process_config($config) { + // set to defaults if undefined + if (!isset ($config->host)) { + $config->host = '127.0.0.1'; + } + if (!isset ($config->type)) { + $config->type = 'pop3notls'; + } + if (!isset ($config->port)) { + $config->port = '143'; + } + if (!isset ($config->mailbox)) { + $config->mailbox = 'INBOX'; + } + if (!isset($config->changepasswordurl)) { + $config->changepasswordurl = ''; + } + + // save settings + set_config('host', $config->host, 'auth/pop3'); + set_config('type', $config->type, 'auth/pop3'); + set_config('port', $config->port, 'auth/pop3'); + set_config('mailbox', $config->mailbox, 'auth/pop3'); + set_config('changepasswordurl', $config->changepasswordurl, 'auth/pop3'); + + return true; + } + +} + +?> diff --git a/auth/pop3/config.html b/auth/pop3/config.html index d35962cd29..893423cbe2 100644 --- a/auth/pop3/config.html +++ b/auth/pop3/config.html @@ -1,75 +1,112 @@ -auth_pop3host)) { - $config->auth_pop3host = "127.0.0.1"; - } - if (!isset($config->auth_pop3type)) { - $config->auth_pop3type = "pop3notls"; - } - if (!isset($config->auth_pop3port)) { - $config->auth_pop3port = "110"; - } - if (!isset($config->auth_pop3mailbox)) { - $config->auth_pop3mailbox = "INBOX"; - } +host)) { + $config->host = '127.0.0.1'; +} +if (!isset($config->type)) { + $config->type = 'pop3notls'; +} +if (!isset($config->port)) { + $config->port = '110'; +} +if (!isset($config->mailbox)) { + $config->mailbox = 'INBOX'; +} +if (!isset($config->changepasswordurl)) { + $config->changepasswordurl = ''; +} + ?> + + - + - + - + - - + + - + - + - - + + - \ No newline at end of file + +
auth_pop3host: host: - - + + - - +
auth_pop3type: type: - auth_pop3type, ""); - ?> - - + type, ''); + + ?>
auth_pop3port: - - - port: - + +
auth_pop3mailbox: mailbox: - - - - + +
: - - changepasswordurl: - - + +
diff --git a/auth/pop3/lib.php b/auth/pop3/lib.php deleted file mode 100644 index e5faf1095b..0000000000 --- a/auth/pop3/lib.php +++ /dev/null @@ -1,47 +0,0 @@ -auth_pop3host); // Could be multiple hosts - - foreach ($hosts as $host) { // Try each host in turn - - $host = trim($host); - - // remove any trailing slash - if (substr($host, -1) == '/') { - $host = substr($host, 0, strlen($host) - 1); - } - - switch ($CFG->auth_pop3type) { - case "pop3": - $host = '{'.$host.":$CFG->auth_pop3port/pop3}$CFG->auth_pop3mailbox"; - break; - case "pop3notls": - $host = '{'.$host.":$CFG->auth_pop3port/pop3/notls}$CFG->auth_pop3mailbox"; - break; - case "pop3cert": - $host = '{'.$host.":$CFG->auth_pop3port/pop3/ssl/novalidate-cert}$CFG->auth_pop3mailbox"; - break; - } - - error_reporting(0); - $connection = imap_open($host, $username, $password); - error_reporting($CFG->debug); - - if ($connection) { - imap_close($connection); - return true; - } - } - - return false; // No matches found -} - - -?> diff --git a/auth/radius/auth.php b/auth/radius/auth.php new file mode 100644 index 0000000000..abe23e310c --- /dev/null +++ b/auth/radius/auth.php @@ -0,0 +1,144 @@ + + * + * 2006-08-31 File created. + */ + +// This page cannot be called directly +if (!isset($CFG)) exit; + +/** + * RADIUS authentication plugin. + */ +class auth_plugin_radius { + + /** + * The configuration details for the plugin. + */ + var $config; + + /** + * Constructor. + */ + function auth_plugin_radius() { + $this->config = get_config('auth/radius'); + } + + /** + * Returns true if the username and password work and false if they are + * wrong or don't exist. + * + * @param string $username The username + * @param string $password The password + * @returns bool Authentication success or failure. + */ + function user_login ($username, $password) { + require_once 'Auth/RADIUS.php'; + + // Added by Clive on 7th May for test purposes + // printf("Username: $username
"); + // printf("Password: $password
"); + // printf("host: $this->config->host
"); + // printf("nasport: $this->config->nasport
"); + // printf("secret: $this->config->secret
"); + + $rauth = new Auth_RADIUS_PAP($username, $password); + $rauth->addServer($this->config->host, $this->config->nasport, $this->config->secret); + + if (!$rauth->start()) { + printf("Radius start: %s
\n", $rauth->getError()); + exit; + } + + $result = $rauth->send(); + if (PEAR::isError($result)) { + printf("Radius send failed: %s
\n", $result->getMessage()); + exit; + } else if ($result === true) { + // printf("Radius Auth succeeded
\n"); + return true; + } else { + // printf("Radius Auth rejected
\n"); + return false; + } + + // get attributes, even if auth failed + if (!$rauth->getAttributes()) { + printf("Radius getAttributes: %s
\n", $rauth->getError()); + } else { + $rauth->dumpAttributes(); + } + + $rauth->close(); + } + + /** + * Returns true if this authentication plugin is 'internal'. + * + * @returns bool + */ + function is_internal() { + return false; + } + + /** + * Returns true if this authentication plugin can change the user's + * password. + * + * @returns bool + */ + function can_change_password() { + return false; + } + + /** + * Prints a form for configuring this authentication plugin. + * + * This function is called from admin/auth.php, and outputs a full page with + * a form for configuring this plugin. + * + * @param array $page An object containing all the data for this page. + */ + function config_form($config, $err) { + include "config.html"; + } + + /** + * Processes and stores configuration data for this authentication plugin. + */ + function process_config($config) { + // set to defaults if undefined + if (!isset ($config->host)) { + $config->host = '127.0.0.1'; + } + if (!isset ($config->nasport)) { + $config->nasport = '1812'; + } + if (!isset ($config->secret)) { + $config->secret = ''; + } + if (!isset($config->changepasswordurl)) { + $config->changepasswordurl = ''; + } + + // save settings + set_config('host', $config->host, 'auth/radius'); + set_config('nasport', $config->nasport, 'auth/radius'); + set_config('secret', $config->secret, 'auth/radius'); + set_config('changepasswordurl', $config->changepasswordurl, 'auth/radius'); + + return true; + } + +} + +?> diff --git a/auth/radius/config.html b/auth/radius/config.html index 656aa5577b..32dc7d0c9b 100644 --- a/auth/radius/config.html +++ b/auth/radius/config.html @@ -1,61 +1,87 @@ -Warning: The Auth_RADIUS module does not seem to be present. Please ensure it is installed and enabled.

'; } - if (!isset($config->auth_radiushost)) { - $config->auth_radiushost = "127.0.0.1"; - } - if (!isset($config->auth_radiusnasport)) { - $config->auth_radiusport = "0"; - } - if (!isset($config->auth_radiussecret)) { - $config->auth_radiussecret = ""; - } + +// set to defaults if undefined +if (!isset($config->host)) { + $config->host = '127.0.0.1'; +} +if (!isset($config->nasport)) { + $config->nasport = '1812'; +} +if (!isset($config->secret)) { + $config->secret = ''; +} +if (!isset($config->changepasswordurl)) { + $config->changepasswordurl = ''; +} + ?> - -

auth_radiushost: - - - - + + + + - - - - - + + + + + + + + - + + - - - + + - - - - - + + + + + - + + +
host: - -

auth_radiusnasport:

- - -
nasport: - + +

auth_radiussecret:

- -
secret: - -

:

- + +
changepasswordurl: - - + +
diff --git a/auth/radius/lib.php b/auth/radius/lib.php deleted file mode 100644 index 08645fad22..0000000000 --- a/auth/radius/lib.php +++ /dev/null @@ -1,50 +0,0 @@ - - -function auth_user_login ($username, $password) { - // Returns true if the username and password work - // and false if they are wrong or don't exist. - - require_once 'Auth/RADIUS.php'; - - global $CFG; - - // Added by Clive on 7th May for test purposes - // printf("Username: $username
"); - // printf("Password: $password
"); - // printf("auth_radiushost: $CFG->auth_radiushost
"); - // printf("auth_radiusnasport: $CFG->auth_radiusnasport
"); - // printf("auth_radiussecret: $CFG->auth_radiussecret
"); - - $rauth = new Auth_RADIUS_PAP($username, $password); - $rauth->addServer($CFG->auth_radiushost, $CFG->auth_radiusnasport, $CFG->auth_radiussecret); - - if (!$rauth->start()) { - printf("Radius start: %s
\n", $rauth->getError()); - exit; - } - - $result = $rauth->send(); - if (PEAR::isError($result)) { - printf("Radius send failed: %s
\n", $result->getMessage()); - exit; - } else if ($result === true) { - // printf("Radius Auth succeeded
\n"); - return true; - } else { - // printf("Radius Auth rejected
\n"); - return false; - } - - // get attributes, even if auth failed - if (!$rauth->getAttributes()) { - printf("Radius getAttributes: %s
\n", $rauth->getError()); - } else { - $rauth->dumpAttributes(); - } - - $rauth->close(); -} -?> - diff --git a/auth/shibboleth/README.txt b/auth/shibboleth/README.txt index 32db7c2760..ec2633bf7b 100644 --- a/auth/shibboleth/README.txt +++ b/auth/shibboleth/README.txt @@ -132,7 +132,7 @@ Example 2: The country, city and street are provided in one Shibboleth attribute If you want to use this hook you have to be a skilled PHP programmer. It is strongly recommended that you take a look at the file -moodle/auth/shibboleth/lib.php, especially the function 'auth_get_userinfo' +moodle/auth/shibboleth/auth.php, especially the function 'get_userinfo' where this file is included. The context of the file is the same as within this login function. So you can directly edit the object $result. diff --git a/auth/shibboleth/auth.php b/auth/shibboleth/auth.php new file mode 100644 index 0000000000..aca3583523 --- /dev/null +++ b/auth/shibboleth/auth.php @@ -0,0 +1,193 @@ +config = get_config('auth/shibboleth'); + } + + /** + * Returns true if the username and password work and false if they are + * wrong or don't exist. + * + * @param string $username The username + * @param string $password The password + * @returns bool Authentication success or failure. + */ + function user_login($username, $password) { + // If we are in the shibboleth directory then we trust the server var + if (!empty($_SERVER[$config->user_attribute])) { + return ($_SERVER[$config->user_attribute] == $username); + } else { + // If we are not, the user has used the manual login and the login name is + // unknown, so we return false. + return false; + } + } + + function get_userinfo($username) { + // reads user information from shibboleth attributes and return it in array() + global $CFG; + + // Check whether we have got all the essential attributes + if ( + empty($_SERVER[$config->user_attribute]) + || empty($_SERVER[$config->field_map_firstname]) + || empty($_SERVER[$config->field_map_lastname]) + || empty($_SERVER[$config->field_map_email]) + ) { + error(get_string( 'shib_not_all_attributes_error', 'auth' , "'".$config->user_attribute."' ('".$_SERVER[$config->user_attribute]."'), '".$config->field_map_firstname."' ('".$_SERVER[$config->field_map_firstname]."'), '".$config->field_map_lastname."' ('".$_SERVER[$config->field_map_lastname]."') and '".$config->field_map_email."' ('".$_SERVER[$config->field_map_email]."')")); + } + + $attrmap = $this->get_attributes(); + + $result = array(); + $search_attribs = array(); + + foreach ($attrmap as $key=>$value) { + if (!empty($CFG->unicodedb)) { + $result[$key] = $this->get_first_string($_SERVER[$value]); + } else { + $result[$key] = $this->get_first_string(utf8_decode($_SERVER[$value])); + } + } + + // Provide an API to modify the information to fit the Moodle internal + // data representation + if ( + $config->convert_data + && $config->convert_data != '' + && is_readable($config->convert_data) + ) { + + // Include a custom file outside the Moodle dir to + // modify the variable $moodleattributes + include($config->convert_data); + } + + return $result; + } + + /* + * Returns array containg attribute mappings between Moodle and Shibboleth. + */ + function get_attributes() { + $configarray = (array) $this->config; + + $fields = array("firstname", "lastname", "email", "phone1", "phone2", + "department", "address", "city", "country", "description", + "idnumber", "lang", "guid"); + + $moodleattributes = array(); + foreach ($fields as $field) { + if ($configarray["field_map_$field"]) { + $moodleattributes[$field] = $configarray["field_map_$field"]; + } + } + $moodleattributes['username'] = $configarray["user_attribute"]; + + return $moodleattributes; + } + + /** + * Returns true if this authentication plugin is 'internal'. + * + * @returns bool + */ + function is_internal() { + return false; + } + + /** + * Returns true if this authentication plugin can change the user's + * password. + * + * @returns bool + */ + function can_change_password() { + return false; + } + + /** + * Prints a form for configuring this authentication plugin. + * + * This function is called from admin/auth.php, and outputs a full page with + * a form for configuring this plugin. + * + * @param array $page An object containing all the data for this page. + */ + function config_form($config, $err) { + include "config.html"; + } + + /** + * Processes and stores configuration data for this authentication plugin. + */ + function process_config($config) { + // set to defaults if undefined + if (!isset($config->auth_instructions) or empty($config->user_attribute)) { + $config->auth_instructions = get_string('shibboleth_instructions', 'auth', $CFG->wwwroot.'/auth/shibboleth/index.php'); + } + if (!isset ($config->user_attribute)) { + $config->user_attribute = ''; + } + if (!isset ($config->convert_data)) { + $config->convert_data = ''; + } + if (!isset($config->changepasswordurl)) { + $config->changepasswordurl = ''; + } + + // save settings + set_config('user_attribute', $config->user_attribute, 'auth/shibboleth'); + set_config('convert_data', $config->convert_data, 'auth/shibboleth'); + set_config('auth_instructions', $config->auth_instructions, 'auth/shibboleth'); + set_config('changepasswordurl', $config->changepasswordurl, 'auth/shibboleth'); + + return true; + } + + /** + * Cleans and returns first of potential many values (multi-valued attributes) + */ + function get_first_string($string) { + $list = split( ';', $string); + $clean_string = rtrim($list[0]); + + return $clean_string; + } +} + +?> diff --git a/auth/shibboleth/config.html b/auth/shibboleth/config.html index a2712ba776..a20e9d2fe1 100755 --- a/auth/shibboleth/config.html +++ b/auth/shibboleth/config.html @@ -1,58 +1,83 @@ auth_instructions) or empty($pluginconfig->shib_user_attribute)) { + global $CFG; + + // Set to defaults if undefined + if (!isset($config->auth_instructions) or empty($config->user_attribute)) { $config->auth_instructions = get_string('auth_shib_instructions', 'auth', $CFG->wwwroot.'/auth/shibboleth/index.php'); } - - if (!isset ($pluginconfig->user_attribute)) { - $pluginconfig->user_attribute = ''; + if (!isset ($config->user_attribute)) { + $config->user_attribute = ''; + } + if (!isset ($config->convert_data)) { + $config->convert_data = ''; } - if (!isset ($pluginconfig->convert_data)) { - $pluginconfig->convert_data = ''; + if (!isset($config->changepasswordurl)) { + $config->changepasswordurl = ''; } + ?> - - -

- -

- - + + - + - + + -', true, false); ?> - - + + - + - + + + + + + + + +', true, false); + +?> +
:: - -
:: - + - wwwroot.'/auth/shibboleth/index.php')) ?> - + wwwroot.'/auth/shibboleth/index.php')); + helpbutton("text", get_string("helptext")); + + ?>
:: - - convert_data && $pluginconfig->convert_data != '' && !is_readable($pluginconfig->convert_data)){ + + convert_data and $config->convert_data != '' and !is_readable($config->convert_data)) { echo '
'; print_string("auth_shib_convert_data_warning", "auth"); echo ''; - } - ?> + } + + ?>
changepasswordurl: + +
diff --git a/auth/shibboleth/index.php b/auth/shibboleth/index.php index 5ea4566ad9..e71094b8c6 100644 --- a/auth/shibboleth/index.php +++ b/auth/shibboleth/index.php @@ -5,7 +5,7 @@ require('lib.php'); if (isloggedin() && $USER->username != 'guest') { // Nothing to do - if (isset($SESSION->wantsurl) and (strpos($SESSION->wantsurl, $CFG->wwwroot) === 0)){ + if (isset($SESSION->wantsurl) and (strpos($SESSION->wantsurl, $CFG->wwwroot) === 0)) { $urltogo = $SESSION->wantsurl; /// Because it's an address in this site unset($SESSION->wantsurl); @@ -20,14 +20,14 @@ $pluginconfig = get_config('auth/shibboleth'); // Check whether Shibboleth is configured properly - if (empty($pluginconfig->shib_user_attribute)) { + if (empty($pluginconfig->user_attribute)) { error(get_string( 'shib_not_set_up_error', 'auth')); } /// If we can find the Shibboleth attribute, save it in session and return to main login page - if (!empty($_SERVER[$pluginconfig->shib_user_attribute])) { // Shibboleth auto-login - $frm->username = $_SERVER[$pluginconfig->shib_user_attribute]; - $frm->password = substr(base64_encode($_SERVER[$pluginconfig->shib_user_attribute]),0,8); + if (!empty($_SERVER[$pluginconfig->user_attribute])) { // Shibboleth auto-login + $frm->username = $_SERVER[$pluginconfig->user_attribute]; + $frm->password = substr(base64_encode($_SERVER[$pluginconfig->user_attribute]),0,8); // The random password consists of the first 8 letters of the base 64 encoded user ID // This password is never used unless the user account is converted to manual @@ -72,8 +72,8 @@ // If we can find any (user independent) Shibboleth attributes but no user // attributes we probably didn't receive any user attributes - elseif (!empty($_SERVER['HTTP_SHIB_APPLICATION_ID'])){ - error(get_string( 'shib_no_attributes_error', 'auth' , '\''.$pluginconfig->shib_user_attribute.'\', \''.$pluginconfig->field_map_firstname.'\', \''.$pluginconfig->field_map_lastname.'\' and \''.$pluginconfig->field_map_email.'\'')); + elseif (!empty($_SERVER['HTTP_SHIB_APPLICATION_ID'])) { + error(get_string( 'shib_no_attributes_error', 'auth' , '\''.$pluginconfig->user_attribute.'\', \''.$pluginconfig->field_map_firstname.'\', \''.$pluginconfig->field_map_lastname.'\' and \''.$pluginconfig->field_map_email.'\'')); } else { error(get_string( 'shib_not_set_up_error', 'auth')); } diff --git a/auth/shibboleth/lib.php b/auth/shibboleth/lib.php deleted file mode 100755 index 038fd1dfa5..0000000000 --- a/auth/shibboleth/lib.php +++ /dev/null @@ -1,97 +0,0 @@ -shib_user_attribute])) { - return ($_SERVER[$pluginconfig->shib_user_attribute] == $username); - } else { - // If we are not, the user has used the manual login and the login name is - // unknown, so we return false. - return false; - } -} - -function auth_get_userinfo($username) { -// reads user information from shibboleth attributes and return it in array() - global $CFG; - - $pluginconfig = get_config('auth/shibboleth'); - - // Check whether we have got all the essential attributes - if ( - empty($_SERVER[$pluginconfig->shib_user_attribute]) - || empty($_SERVER[$pluginconfig->field_map_firstname]) - || empty($_SERVER[$pluginconfig->field_map_lastname]) - || empty($_SERVER[$pluginconfig->field_map_email]) - ) { - error(get_string( 'shib_not_all_attributes_error', 'auth' , "'".$pluginconfig->shib_user_attribute."' ('".$_SERVER[$pluginconfig->shib_user_attribute]."'), '".$pluginconfig->field_map_firstname."' ('".$_SERVER[$pluginconfig->field_map_firstname]."'), '".$pluginconfig->field_map_lastname."' ('".$_SERVER[$pluginconfig->field_map_lastname]."') and '".$pluginconfig->field_map_email."' ('".$_SERVER[$pluginconfig->field_map_email]."')")); - } - - $attrmap = auth_shib_attributes(); - - $result = array(); - $search_attribs = array(); - - foreach ($attrmap as $key=>$value) { - $result[$key]= get_first_string($_SERVER[$value]); - } - - // Provide an API to modify the information to fit the Moodle internal - // data representation - if ( - $pluginconfig->convert_data - && $pluginconfig->convert_data != '' - && is_readable($pluginconfig->convert_data) - ){ - - // Include a custom file outside the Moodle dir to - // modify the variable $moodleattributes - include($pluginconfig->convert_data); - } - - return $result; -} - -function auth_shib_attributes(){ -//returns array containg attribute mappings between Moodle and shibboleth - global $CFG; - - $pluginconfig = get_config('auth/shibboleth'); - $pluginconfig = (array) $pluginconfig; - - $fields = array("firstname", "lastname", "email", "phone1", "phone2", - "department", "address", "city", "country", "description", - "idnumber", "lang", "guid"); - - $moodleattributes = array(); - foreach ($fields as $field) { - if ($pluginconfig["field_map_$field"]) { - $moodleattributes[$field] = $pluginconfig["field_map_$field"]; - } - } - $moodleattributes['username']=$pluginconfig["shib_user_attribute"]; - - return $moodleattributes; -} - -function get_first_string($string){ -// Cleans and returns first of potential many values (multi-valued attributes) - - $list = split( ';', $string); - $clean_string = rtrim($list[0]); - - return $clean_string; - -} -?> diff --git a/lang/en_utf8/auth.php b/lang/en_utf8/auth.php index f01f94b08e..a43640cb73 100644 --- a/lang/en_utf8/auth.php +++ b/lang/en_utf8/auth.php @@ -1,28 +1,33 @@ -\'$a\' and return fields username and password.
Be careful not to enter an incorrect URL as you may lock yourself out of this site.
Leave this setting blank to use the default login page.'; $string['alternateloginurl'] = 'Alternate Login URL'; -$string['auth_cas_baseuri'] = 'URI of the server (nothing if no baseUri)
For example, if the CAS server responds to host.domaine.fr/CAS/ then
cas_baseuri = CAS/'; -$string['auth_cas_create_user'] = 'Turn this on if you want to insert CAS-authenticated users in Moodle database. If not then only users who already exist in the Moodle database can log in.'; -$string['auth_cas_enabled'] = 'Turn this on if you want to use CAS authentication.'; -$string['auth_cas_hostname'] = 'Hostname of the CAS server
eg: host.domain.fr'; -$string['auth_cas_invalidcaslogin'] = 'Sorry, your login has failed - you could not be authorised'; -$string['auth_cas_language'] = 'Selected language'; + +// CAS plugin $string['auth_cas_logincas'] = 'Secure connection access'; -$string['auth_cas_port'] = 'Port of the CAS server'; +$string['auth_cas_invalidcaslogin'] = 'Sorry, your login has failed - you could not be authorised'; $string['auth_cas_server_settings'] = 'CAS server configuration'; -$string['auth_cas_text'] = 'Secure connection'; +$string['auth_castitle'] = 'Use a CAS server (SSO)'; +$string['auth_cas_hostname'] = 'Hostname of the CAS server
eg: host.domain.fr'; +$string['auth_cas_baseuri'] = 'URI of the server (nothing if no baseUri)
For example, if the CAS server responds to host.domaine.fr/CAS/ then
cas_baseuri = CAS/'; +$string['auth_cas_port'] = 'Port of the CAS server'; $string['auth_cas_version'] = 'Version of CAS'; +$string['auth_cas_language'] = 'Selected language'; $string['auth_casdescription'] = 'This method uses a CAS server (Central Authentication Service) to authenticate users in a Single Sign On environment (SSO). You can also use a simple LDAP authentication. If the given username and password are valid according to CAS, Moodle creates a new user entry in its database, taking user attributes from LDAP if required. On following logins only the username and password are checked.'; -$string['auth_castitle'] = 'Use a CAS server (SSO)'; -$string['auth_changepasswordhelp'] = 'Change password help'; -$string['auth_changepasswordhelp_expl'] = 'Display lost password help to users who have lost their $a password. This will be displayed either as well as or instead of the Change Password URL or Internal Moodle password change.'; +$string['auth_cas_enabled'] = 'Turn this on if you want to use CAS authentication.'; +$string['auth_cas_text'] = 'Secure connection'; +$string['auth_cas_create_user'] = 'Turn this on if you want to insert CAS-authenticated users in Moodle database. If not then only users who already exist in the Moodle database can log in.'; + $string['auth_changepasswordurl'] = 'Change password URL'; $string['auth_changepasswordurl_expl'] = 'Specify the url to send users who have lost their $a password. Set Use standard Change Password page to No.'; +$string['auth_changepasswordhelp'] = 'Change password help'; +$string['auth_changepasswordhelp_expl'] = 'Display lost password help to users who have lost their $a password. This will be displayed either as well as or instead of the Change Password URL or Internal Moodle password change.'; $string['auth_common_settings'] = 'Common settings'; $string['auth_data_mapping'] = 'Data mapping'; + +// Database plugin $string['auth_dbdescription'] = 'This method uses an external database table to check whether a given username and password is valid. If the account is a new one, then information from other fields may also be copied across into Moodle.'; $string['auth_dbextrafields'] = 'These fields are optional. You can choose to pre-fill some Moodle user fields with information from the external database fields that you specify here.

If you leave these blank, then defaults will be used.

In either case, the user will be able to edit all of these fields after they log in.

'; $string['auth_dbfieldpass'] = 'Name of the field containing passwords'; @@ -35,8 +40,12 @@ $string['auth_dbtable'] = 'Name of the table in the database'; $string['auth_dbtitle'] = 'Use an external database'; $string['auth_dbtype'] = 'The database type (See the ADOdb documentation for details)'; $string['auth_dbuser'] = 'Username with read access to the database'; + +// Email plugin $string['auth_emaildescription'] = 'Email confirmation is the default authentication method. When the user signs up, choosing their own new username and password, a confirmation email is sent to the user\'s email address. This email contains a secure link to a page where the user can confirm their account. Future logins just check the username and password against the stored values in the Moodle database.'; -$string['auth_emailtitle'] = 'Email-based authentication'; +$string['auth_emailtitle'] = 'Email-based self-registration'; + +// FirstClass plugin $string['auth_fccreators'] = 'List of groups whose members are allowed to create new courses. Separate multiple groups with \';\'. Names must be spelled exactly as on FirstClass server. System is case-sensitive.'; $string['auth_fcdescription'] = 'This method uses a FisrtClass server to check whether a given username and password is valid.'; $string['auth_fcfppport'] = 'Server port (3333 is the most common)'; @@ -44,6 +53,8 @@ $string['auth_fchost'] = 'The FirstClass server address. Use the IP number or DN $string['auth_fcpasswd'] = 'Password for the account above.'; $string['auth_fctitle'] = 'Use a FirstClass server'; $string['auth_fcuserid'] = 'Userid for FirstClass account with privilege \'Subadministrator\' set.'; + +// Fieldlocks $string['auth_fieldlock'] = 'Lock value'; $string['auth_fieldlock_expl'] = '

Lock value: If enabled, will prevent Moodle users and admins from editing the field directly. Use this option if you are maintaining this data in the external auth system.

'; $string['auth_fieldlocks'] = 'Lock user fields'; @@ -53,11 +64,13 @@ $string['auth_imaphost'] = 'The IMAP server address. Use the IP number, not DNS $string['auth_imapport'] = 'IMAP server port number. Usually this is 143 or 993.'; $string['auth_imaptitle'] = 'Use an IMAP server'; $string['auth_imaptype'] = 'The IMAP server type. IMAP servers can have different types of authentication and negotiation.'; + +// LDAP plugin $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_pw'] = 'Password for bind-user.'; $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_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.
Note! You have to modify function auth_user_create() in file auth/ldap/lib.php to make user creation work'; +$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.
Note! You have to modify the method user_create() in file auth/ldap/auth.php to make user creation work'; $string['auth_ldap_creators'] = 'List of groups whose members are allowed to create new courses. Separate multiple groups with \';\'. Usually something like \'cn=teachers,ou=staff,o=myorg\''; $string['auth_ldap_expiration_desc'] = 'Select No to disable expired password checking or LDAP to read passwordexpiration time directly from LDAP'; $string['auth_ldap_expiration_warning_desc'] = 'Number of days before password expiration warning is issued.'; @@ -89,42 +102,69 @@ $string['auth_ldapdescription'] = 'This method provides authentication against a password are checked.'; $string['auth_ldapextrafields'] = 'These fields are optional. You can choose to pre-fill some Moodle user fields with information from the LDAP fields that you specify here.

If you leave these fields blank, then nothing will be transferred from LDAP and Moodle defaults will be used instead.

In either case, the user will be able to edit all of these fields after they log in.

'; $string['auth_ldaptitle'] = 'Use an LDAP server'; + +// Manual plugin $string['auth_manualdescription'] = 'This method removes any way for users to create their own accounts. All accounts must be manually created by the admin user.'; $string['auth_manualtitle'] = 'Manual accounts only'; + +// MNET plugin +$string['auth_mnettitle'] = 'Moodle Network authentication'; +$string['auth_mnetdescription'] = 'Users are authenticated according to the web of trust defined in your Moodle Network settings.'; +$string['auth_mnet_rpc_negotiation_timeout'] = 'The timeout in seconds for authentication over the XMLRPC transport.'; +$string['auth_mnet_auto_add_remote_users'] = 'When set to Yes, a local user record is auto-created when a remote user logs in for the first time.'; + $string['auth_multiplehosts'] = 'Multiple hosts OR addresses can be specified (eg host1.com;host2.com;host3.com) or (eg xxx.xxx.xxx.xxx;xxx.xxx.xxx.xxx)'; + +// NNTP plugin $string['auth_nntpdescription'] = 'This method uses an NNTP server to check whether a given username and password is valid.'; $string['auth_nntphost'] = 'The NNTP server address. Use the IP number, not DNS name.'; $string['auth_nntpport'] = 'Server port (119 is the most common)'; $string['auth_nntptitle'] = 'Use an NNTP server'; + +// None plugin $string['auth_nonedescription'] = 'Users can sign in and create valid accounts immediately, with no authentication against an external server and no confirmation via email. Be careful using this option - think of the security and administration problems this could cause.'; $string['auth_nonetitle'] = 'No authentication'; + +// PAM plugin $string['auth_pamdescription'] = 'This method uses PAM to access the native usernames on this server. You have to install PHP4 PAM Authentication in order to use this module.'; $string['auth_pamtitle'] = 'PAM (Pluggable Authentication Modules)'; + $string['auth_passwordisexpired'] = 'Your password is expired. Do you want change your password now?'; $string['auth_passwordwillexpire'] = 'Your password will expire in $a days. Do you want change your password now?'; + +// POP3 plugin $string['auth_pop3description'] = 'This method uses a POP3 server to check whether a given username and password is valid.'; $string['auth_pop3host'] = 'The POP3 server address. Use the IP number, not DNS name.'; $string['auth_pop3mailbox'] = 'Name of the mailbox to attempt a connection with. (usually INBOX)'; $string['auth_pop3port'] = 'Server port (110 is the most common, 995 is common for SSL)'; $string['auth_pop3title'] = 'Use a POP3 server'; $string['auth_pop3type'] = 'Server type. If your server uses certificate security, choose pop3cert.'; + +// RADIUS plugin +$string['auth_radiustitle'] = 'Use a RADIUS server'; $string['auth_radiusdescription'] = 'This method uses a RADIUS server to check whether a given username and password is valid.'; $string['auth_radiushost'] = 'Address of the RADIUS server'; $string['auth_radiusnasport'] = 'Port to use to connect'; $string['auth_radiussecret'] = 'Shared secret'; -$string['auth_radiustitle'] = 'Use a RADIUS server'; -$string['auth_shib_convert_data'] = 'Data modification API'; -$string['auth_shib_convert_data_description'] = 'You can use this API to further modify the data provided by Shibboleth. Read the README for further instructions.'; -$string['auth_shib_convert_data_warning'] = 'The file does not exist or is not readable by the webserver process!'; -$string['auth_shib_instructions'] = 'Use the Shibboleth login to get access via Shibboleth, if your institution supports it.
Otherwise, use the normal login form shown here.'; -$string['auth_shib_instructions_help'] = 'Here you should provide custom instructions for your users to explain Shibboleth. It will be shown on the login page in the instructions section. The instructions must include a link to \"$a\" that users click when they want to log in.'; + +// Shibboleth plugin +$string['auth_shibbolethdescription'] = 'Using this method users are created and authenticated using Shibboleth.
Be sure to read the README for Shibboleth on how to set up your Moodle with Shibboleth'; +$string['auth_shibbolethtitle'] = 'Shibboleth'; +$string['auth_shibboleth_login'] = 'Shibboleth Login'; +$string['auth_shibboleth_manual_login'] = 'Manual Login'; $string['auth_shib_only'] = 'Shibboleth only'; $string['auth_shib_only_description'] = 'Check this option if a Shibboleth authentication shall be enforced'; $string['auth_shib_username_description'] = 'Name of the webserver Shibboleth environment variable that shall be used as Moodle username'; -$string['auth_shibboleth_login'] = 'Shibboleth Login'; -$string['auth_shibboleth_manual_login'] = 'Manual Login'; -$string['auth_shibbolethdescription'] = 'Using this method users are created and authenticated using Shibboleth.
Be sure to read the README for Shibboleth on how to set up your Moodle with Shibboleth'; -$string['auth_shibbolethtitle'] = 'Shibboleth'; +$string['auth_shib_instructions'] = 'Use the Shibboleth login to get access via Shibboleth, if your institution supports it.
Otherwise, use the normal login form shown here.'; +$string['auth_shib_convert_data'] = 'Data modification API'; +$string['auth_shib_convert_data_description'] = 'You can use this API to further modify the data provided by Shibboleth. Read the README for further instructions.'; +$string['auth_shib_instructions_help'] = 'Here you should provide custom instructions for your users to explain Shibboleth. It will be shown on the login page in the instructions section. The instructions must include a link to \"$a\" that users click when they want to log in.'; +$string['auth_shib_convert_data_warning'] = 'The file does not exist or is not readable by the webserver process!'; + +$string['shib_not_set_up_error'] = 'Shibboleth authentication doesn\'t seem to be set up correctly because no Shibboleth environment variables are present for this page. Please consult the README for further instructions on how to set up Shibboleth authentication or contact the webmaster of this Moodle installation.'; +$string['shib_no_attributes_error'] = 'You seem to be Shibboleth authenticated but Moodle didn\'t receive any user attributes. Please check that your Identity Provider releases the necessary attributes ($a) to the Service Provider Moodle is running on or inform the webmaster of this server.'; +$string['shib_not_all_attributes_error'] = 'Moodle needs certain Shibboleth attributes which are not present in your case. The attributes are: $a
Please contact the webmaster of this server or your Identity Provider.'; + $string['auth_updatelocal'] = 'Update local'; $string['auth_updatelocal_expl'] = '

Update local: If enabled, the field will be updated (from external auth) every time the user logs in or there is a user synchronization. Fields set to update locally should be locked.

'; $string['auth_updateremote'] = 'Update external'; @@ -139,29 +179,28 @@ $string['changepassword'] = 'Change password URL'; $string['changepasswordhelp'] = 'Here you can specify a location at which your users can recover or change their username/password if they\'ve forgotten it. This will be provided to users as a button on the login page and their user page. if you leave this blank the button will not be printed.'; $string['chooseauthmethod'] = 'Choose an authentication method'; $string['createpasswordifneeded'] = 'Create password if needed'; +$string['infilefield'] = 'Field required in file'; $string['forcechangepassword'] = 'Force change password'; $string['forcechangepassword_help'] = 'Force users to change password on their next login to Moodle.'; $string['forcechangepasswordfirst_help'] = 'Force users to change password on their first login to Moodle.'; $string['guestloginbutton'] = 'Guest login button'; -$string['infilefield'] = 'Field required in file'; $string['instructions'] = 'Instructions'; $string['internal'] = 'Internal'; -$string['locked'] = 'Locked'; $string['md5'] = 'MD5 encryption'; $string['passwordhandling'] = 'Password field handling'; $string['plaintext'] = 'Plain text'; -$string['shib_no_attributes_error'] = 'You seem to be Shibboleth authenticated but Moodle didn\'t receive any user attributes. Please check that your Identity Provider releases the necessary attributes ($a) to the Service Provider Moodle is running on or inform the webmaster of this server.'; -$string['shib_not_all_attributes_error'] = 'Moodle needs certain Shibboleth attributes which are not present in your case. The attributes are: $a
Please contact the webmaster of this server or your Identity Provider.'; -$string['shib_not_set_up_error'] = 'Shibboleth authentication doesn\'t seem to be set up correctly because no Shibboleth environment variables are present for this page. Please consult the README for further instructions on how to set up Shibboleth authentication or contact the webmaster of this Moodle installation.'; +$string['selfregistration'] = 'Self registration'; +$string['selfregistration_help'] = 'Choose which auth plugin will handle user self-registration.'; $string['showguestlogin'] = 'You can hide or show the guest login button on the login page.'; $string['stdchangepassword'] = 'Use standard Change Password Page'; $string['stdchangepassword_expl'] = 'If the external authentication system allows password changes through Moodle, switch this to Yes. This setting overrides \'Change Password URL\'.'; $string['stdchangepassword_explldap'] = 'NOTE: It is recommended that you use LDAP over an SSL encrypted tunnel (ldaps://) if the LDAP server is remote.'; +$string['update_oncreate'] = 'On creation'; +$string['update_onlogin'] = 'On every login'; +$string['update_onupdate'] = 'On update'; +$string['update_never'] = 'Never'; $string['unlocked'] = 'Unlocked'; $string['unlockedifempty'] = 'Unlocked if empty'; -$string['update_never'] = 'Never'; -$string['update_oncreate'] = 'On creation'; -$string['update_onlogin'] = 'On every login'; -$string['update_onupdate'] = 'On update'; +$string['locked'] = 'Locked'; ?>