--- a/includes/sessions.php Sun Aug 09 01:27:45 2009 -0400
+++ b/includes/sessions.php Mon Aug 10 22:43:26 2009 -0400
@@ -172,6 +172,20 @@
var $csrf_token = false;
/**
+ * Password change disabled, for auth plugins
+ * @var bool
+ */
+
+ var $password_change_disabled = false;
+
+ /**
+ * Password change page URL + title, for auth plugins
+ * @var array
+ */
+
+ var $password_change_dest = array('url' => '', 'title' => '');
+
+ /**
* Switch to track if we're started or not.
* @access private
* @var bool
@@ -923,7 +937,16 @@
}
else
{
- $session_key = hmac_sha1($password_hmac, $salt);
+ $key_pieces = array($password_hmac);
+ $sk_mode = 'generate';
+ $code = $plugins->setHook('session_key_calc');
+ foreach ( $code as $cmd )
+ {
+ eval($cmd);
+ }
+ $key_pieces = implode("\xFF", $key_pieces);
+
+ $session_key = hmac_sha1($key_pieces, $salt);
}
// Minimum level
@@ -1246,7 +1269,16 @@
// $loose_call is turned on only from validate_aes_session
if ( !$loose_call )
{
- $correct_key = hexdecode(hmac_sha1($row['password'], $row['salt']));
+ $key_pieces = array($row['password']);
+ $user_id =& $row['uid'];
+ $sk_mode = 'validate';
+ $code = $plugins->setHook('session_key_calc');
+ foreach ( $code as $cmd )
+ {
+ eval($cmd);
+ }
+ $key_pieces = implode("\xFF", $key_pieces);
+ $correct_key = hexdecode(hmac_sha1($key_pieces, $row['salt']));
$user_key = hexdecode($key);
if ( $correct_key !== $user_key || !is_string($user_key) )
{
@@ -1530,8 +1562,41 @@
}
/**
- * Grabs the user's password MD5
- * @return string, or bool false if access denied
+ * Prevent the user from changing their password. Authentication plugins may call this to enforce single sign-on.
+ * @param string URL to page where the user may change their password
+ * @param string Title of the page where the user may change their password
+ * @return null
+ */
+
+ function disable_password_change($change_url = false, $change_title = false)
+ {
+ if ( $this->password_change_disabled )
+ {
+ // don't allow calling twice. if we have two plugins doing this, somebody is bad at configuring websites.
+ return false;
+ }
+
+ if ( is_string($change_url) && is_string($change_title) )
+ {
+ $this->password_change_dest = array(
+ 'url' => $change_url,
+ 'title' => $change_title
+ );
+ }
+ else
+ {
+ $this->password_change_dest = array(
+ 'url' => false,
+ 'title' => false
+ );
+ }
+
+ $this->password_change_disabled = true;
+ }
+
+ /**
+ * Grabs the user's password MD5 - NOW DEPRECATED AND DISABLED.
+ * @return bool false
*/
function grab_password_hash()
@@ -2261,178 +2326,76 @@
}
/**
- * Updates a user's information in the database. Note that any of the values except $user_id can be false if you want to preserve the old values.
- * Not localized because this really isn't used a whole lot anymore.
+ * Change a user's e-mail address.
* @param int $user_id The user ID of the user to update - this cannot be changed
- * @param string $username The new username
- * @param string $old_pass The current password - only required if sessionManager::$user_level < USER_LEVEL_ADMIN. This should usually be an UNENCRYPTED string. This can also be an array - if it is, key 0 is treated as data AES-encrypted with key 1
- * @param string $password The new password
* @param string $email The new e-mail address
- * @param string $realname The new real name
- * @param string $signature The updated forum/comment signature
- * @param int $user_level The updated user level
* @return string 'success' if successful, or array of error strings on failure
*/
- function update_user($user_id, $username = false, $old_pass = false, $password = false, $email = false, $realname = false, $signature = false, $user_level = false)
+ function change_email($user_id, $email)
{
global $db, $session, $paths, $template, $plugins; // Common objects
// Create some arrays
- $errors = Array(); // Used to hold error strings
- $strs = Array(); // Sub-query statements
+ $errors = array(); // Used to hold error strings
// Scan the user ID for problems
- if(intval($user_id) < 1) $errors[] = 'SQL injection attempt';
-
- // Instanciate the AES encryption class
- $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
-
- // If all of our input vars are false, then we've effectively done our job so get out of here
- if($username === false && $password === false && $email === false && $realname === false && $signature === false && $user_level === false)
- {
- // echo 'debug: $session->update_user(): success (no changes requested)';
- return 'success';
- }
-
- // Initialize our authentication check
- $authed = false;
+ if ( intval($user_id) < 1 )
+ $errors[] = 'SQL injection attempt';
- // Verify the inputted password
- if(is_string($old_pass))
- {
- $q = $this->sql('SELECT password FROM '.table_prefix.'users WHERE user_id='.$user_id.';');
- if($db->numrows() < 1)
- {
- $errors[] = 'The password data could not be selected for verification.';
- }
- else
- {
- $row = $db->fetchrow();
- $real = $aes->decrypt($row['password'], $this->private_key, ENC_HEX);
- if($real == $old_pass)
- $authed = true;
- }
- }
-
- elseif(is_array($old_pass))
- {
- $old_pass = $aes->decrypt($old_pass[0], $old_pass[1]);
- $q = $this->sql('SELECT password FROM '.table_prefix.'users WHERE user_id='.$user_id.';');
- if($db->numrows() < 1)
- {
- $errors[] = 'The password data could not be selected for verification.';
- }
- else
- {
- $row = $db->fetchrow();
- $real = $aes->decrypt($row['password'], $this->private_key, ENC_HEX);
- if($real == $old_pass)
- $authed = true;
- }
- }
-
- // Initialize our query
- $q = 'UPDATE '.table_prefix.'users SET ';
+ $user_id = intval($user_id);
- if($this->auth_level >= USER_LEVEL_ADMIN || $authed) // Need the current password in order to update the e-mail address, change the username, or reset the password
- {
- // Username
- if(is_string($username))
- {
- // Check the username for problems
- if(!preg_match('#^'.$this->valid_username.'$#', $username))
- $errors[] = 'The username you entered contains invalid characters.';
- $strs[] = 'username=\''.$db->escape($username).'\'';
- }
- // Password
- if(is_string($password) && strlen($password) >= 6)
- {
- // Password needs to be encrypted before being stashed
- $encpass = $aes->encrypt($password, $this->private_key, ENC_HEX);
- if(!$encpass)
- $errors[] = 'The password could not be encrypted due to an internal error.';
- $strs[] = 'password=\''.$encpass.'\'';
- }
- // E-mail addy
- if(is_string($email))
- {
- if(!check_email_address($email))
- $errors[] = 'The e-mail address you entered is invalid.';
- $strs[] = 'email=\''.$db->escape($email).'\'';
- }
- }
- // Real name
- if(is_string($realname))
- {
- $strs[] = 'real_name=\''.$db->escape($realname).'\'';
- }
- // Forum/comment signature
- if(is_string($signature))
- {
- $strs[] = 'signature=\''.$db->escape($signature).'\'';
- }
- // User level
- if(is_int($user_level))
- {
- $strs[] = 'user_level='.$user_level;
- }
+ // Verify e-mail address
+ if ( !check_email_address($email) )
+ $errors[] = 'user_err_email_not_valid';
- // Add our generated query to the query string
- $q .= implode(',', $strs);
-
- // One last error check
- if(sizeof($strs) < 1) $errors[] = 'An internal error occured building the SQL query, this is a bug';
- if(sizeof($errors) > 0) return $errors;
+ if ( count($errors) > 0 )
+ return $errors;
- // Free our temp arrays
- unset($strs, $errors);
-
- // Finalize the query and run it
- $q .= ' WHERE user_id='.$user_id.';';
- $this->sql($q);
+ // Make query
+ $email = $db->escape($email);
+ $q = $db->sql_query('UPDATE ' . table_prefix . "users SET email = '$email' WHERE user_id = $user_id;");
// We also need to trigger re-activation.
- if ( is_string($email) )
+ switch(getConfig('account_activation', 'none'))
{
- switch(getConfig('account_activation'))
- {
- case 'user':
- case 'admin':
-
- if ( $session->user_level >= USER_LEVEL_MOD && getConfig('account_activation') == 'admin' )
- // Don't require re-activation by admins for admins
- break;
-
- // retrieve username
- if ( !$username )
+ case 'user':
+ case 'admin':
+
+ // Note: even with admin activation, activation e-mails are sent when an e-mail is changed.
+
+ if ( $session->user_level >= USER_LEVEL_MOD && getConfig('account_activation') == 'admin' )
+ // Trust admins and moderators
+ break;
+
+ // retrieve username
+ if ( !$username )
+ {
+ $q = $this->sql('SELECT username FROM ' . table_prefix . "users WHERE user_id = $user_id;");
+ if($db->numrows() < 1)
{
- $q = $this->sql('SELECT username FROM '.table_prefix.'users WHERE user_id='.$user_id.';');
- if($db->numrows() < 1)
- {
- $errors[] = 'The username could not be selected.';
- }
- else
- {
- $row = $db->fetchrow();
- $username = $row['username'];
- }
+ $errors[] = 'The username could not be selected.';
+ }
+ else
+ {
+ $row = $db->fetchrow();
+ $username = $row['username'];
}
- if ( !$username )
- return $errors;
-
- // Generate a totally random activation key
- $actkey = sha1 ( microtime() . mt_rand() );
- $a = $this->send_activation_mail($username, $actkey);
- if(!$a)
- {
- $this->admin_activation_request($username);
- }
- // Deactivate the account until e-mail is confirmed
- $q = $db->sql_query('UPDATE '.table_prefix.'users SET account_active=0,activation_key=\'' . $actkey . '\' WHERE user_id=' . $user_id . ';');
- break;
- }
+ }
+ if ( !$username )
+ return $errors;
+
+ // Generate an activation key
+ $actkey = sha1 ( microtime() . mt_rand() );
+ $a = $this->send_activation_mail($username, $actkey);
+ if(!$a)
+ {
+ $this->admin_activation_request($username);
+ }
+ // Deactivate the account until e-mail is confirmed
+ $q = $db->sql_query('UPDATE ' . table_prefix . "users SET account_active = 0, activation_key = '$actkey' WHERE user_id = $user_id;");
+ break;
}
// Yay! We're done