includes/sessions.php
changeset 1079 fcc42560afe6
parent 1071 f374801eb775
child 1081 745200a9cc2a
--- 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