diff --git a/auth/ldap/auth.php b/auth/ldap/auth.php index 8ec2bd7..4283d5e 100644 --- a/auth/ldap/auth.php +++ b/auth/ldap/auth.php @@ -16,6 +16,14 @@ if (!defined('MOODLE_INTERNAL')) { die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page } +// See http://support.microsoft.com/kb/305144 to interprete these values. +if (!defined('AUTH_AD_ACCOUNTDISABLE')) { + define('AUTH_AD_ACCOUNTDISABLE', 0x0002); +} +if (!defined('AUTH_AD_NORMAL_ACCOUNT')) { + define('AUTH_AD_NORMAL_ACCOUNT', 0x0200); +} + require_once($CFG->libdir.'/authlib.php'); /** @@ -271,11 +279,54 @@ class auth_plugin_ldap extends auth_plugin_base { $newuser['uniqueId'] = $extusername; $newuser['logindisabled'] = "TRUE"; $newuser['userpassword'] = $extpassword; + $uadd = $this->ldap_add($ldapconnection, $this->config->user_attribute.'="'.$this->ldap_addslashes($userobject->username).','.$this->config->create_context.'"', $newuser); + break; + case 'ad': + // User account creation is a two step process with AD. First you + // create the user object, then you set the password. If you try + // to set the password while creating the user, the operation + // fails. + + // Passwords in Active Directory must be encoded as Unicode + // strings (UCS-2 Little Endian format) and surrounded with + // double quotes. See http://support.microsoft.com/?kbid=269190 + if (!function_exists('mb_convert_encoding')) { + error ('You need the mbstring extension to create ' . + 'users in Active Directory'); + } + + // First create the user account, and mark it as disabled. + $newuser['objectClass'] = array('top','person','user','organizationalPerson'); + $newuser['sAMAccountName'] = $extusername; + $newuser['userAccountControl'] = AUTH_AD_NORMAL_ACCOUNT | + AUTH_AD_ACCOUNTDISABLE; + $userdn = 'cn=' . $this->ldap_addslashes($userobject->username) . + ',' . $this->config->create_context; + if (!ldap_add($ldapconnection, $userdn, $newuser)) { + error('Cannot create the new account in Active Directory. ' . + 'Make sure you meet all the requirements for this to ' . + 'work (LDAPS connection, bind user with adequate '. + 'rights, etc.)'); + } + + // Now set the password + unset($newuser); + $newuser['unicodePwd'] = mb_convert_encoding('"'.$plainpass.'"', + "UCS-2LE", + "UTF-8"); + if(!ldap_modify($ldapconnection, $userdn, $newuser)) { + // Something went wrong: delete the user account and error out + ldap_delete ($ldapconnection, $userdn); + error('Cannot set the password for the new account. ' . + 'Make sure you meet all the requirements for this to' . + 'work (LPADS connection, bind user with adequate '. + 'rights, etc.)'); + } + $uadd = true; break; default: print_error('auth_ldap_unsupportedusertype','auth',$this->config->user_type); } - $uadd = $this->ldap_add($ldapconnection, $this->config->user_attribute.'="'.$this->ldap_addslashes($userobject->username).','.$this->config->create_context.'"', $newuser); ldap_close($ldapconnection); return $uadd; @@ -760,6 +811,16 @@ class auth_plugin_ldap extends auth_plugin_base { case 'edir': $newinfo['loginDisabled']="FALSE"; break; + case 'ad': + // We need to unset the ACCOUNTDISABLE bit in the + // userAccountControl attribute ( see + // http://support.microsoft.com/kb/305144 ) + $sr = ldap_read($ldapconnection, $userdn, '(objectClass=*)', + array('userAccountControl')); + $info = ldap_get_entries($ldapconnection, $sr); + $newinfo['userAccountControl'] = $info[0]['userAccountControl'][0] + & (~AUTH_AD_ACCOUNTDISABLE); + break; default: error ('auth: ldap user_activate() does not support selected usertype:"'.$this->config->user_type.'" (..yet)'); } @@ -785,6 +846,16 @@ class auth_plugin_ldap extends auth_plugin_base { case 'edir': $newinfo['loginDisabled']="TRUE"; break; + case 'ad': + // We need to set the ACCOUNTDISABLE bit in the + // userAccountControl attribute ( see + // http://support.microsoft.com/kb/305144 ) + $sr = ldap_read($ldapconnection, $userdn, '(objectClass=*)', + array('userAccountControl')); + $info = auth_ldap_get_entries($ldapconnection, $sr); + $newinfo['userAccountControl'] = $info[0]['userAccountControl'][0] + | AUTH_AD_ACCOUNTDISABLE; + break; default: error ('auth: ldap user_disable() does not support selected usertype (..yet)'); } @@ -1684,6 +1755,93 @@ class auth_plugin_ldap extends auth_plugin_base { array('\\"', '\\00'), $text); return $text; } + + /** + * The functions below added by Johnbin Wang + */ + + /** + * Returns true if plugin allows signup of new users. + * + * @return bool + */ + function can_signup() { + return true; + } + + /** + * Sign up a new user ready for confirmation. + * Password is passed in plaintext. + * + * @param object $user new user object (with system magic quotes) + * @param boolean $notify print notice with link and terminate + */ + function user_signup($user, $notify=true) { + $plainpass = $user->password; + $user->password = hash_internal_user_password($user->password); + + if (!$this->user_exists($user->username)) { + if (!$this->user_create($user,$plainpass)) { + error("Could not add user to authentication module!"); + } + } else { + error("User already exists on authentication database."); + } + + if (!($user->id = insert_record('user', $user)) ) { + print_error('auth_emailnoinsert','auth'); + } + if (!send_confirmation_email($user)) { + print_error('auth_emailnoemail','auth'); + } + + if ($notify) { + global $CFG; + $emailconfirm = get_string('emailconfirm'); + print_header($emailconfirm, $emailconfirm, $emailconfirm); + notice(get_string('emailconfirmsent', '', $user->email), "$CFG->wwwroot/index.php"); + } else { + return true; + } + } + + /** + * Returns true if plugin allows confirming of new users. + * + * @return bool + */ + function can_confirm() { + return true; + } + + /** + * Confirm the new user as registered. + * + * @param string $username (with system magic quotes) + * @param string $confirmsecret (with system magic quotes) + */ + function user_confirm($username, $confirmsecret) { + $user = get_complete_user_data('username', $username); + + if (!empty($user)) { + if ($user->confirmed) { + return AUTH_CONFIRM_ALREADY; + } else if ($user->secret == stripslashes($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; + } + if(!$this->user_activate($user->username)){ + return AUTH_CONFIRM_FAIL; + } + return AUTH_CONFIRM_OK; + } + } else { + return AUTH_CONFIRM_ERROR; + } + } } ?>