Index: modules/user/user.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.install,v
retrieving revision 1.5
diff -u -p -r1.5 user.install
--- modules/user/user.install	8 Jan 2008 07:46:41 -0000	1.5
+++ modules/user/user.install	15 Feb 2008 21:26:08 -0000
@@ -149,6 +149,13 @@ function user_schema() {
         'default' => '',
         'description' => t("User's password (md5 hash)."),
       ),
+      'salt' => array(
+	'type' => 'varchar',
+	'length' => 32,
+	'not null' => TRUE,
+	'default' => '',
+	'description' => t("Salt for user's password."),
+      ),
       'mail' => array(
         'type' => 'varchar',
         'length' => 64,
@@ -288,3 +295,16 @@ function user_schema() {
   return $schema;
 }
 
+function user_update_1() {
+  $ret = array();
+  db_add_field($ret, 'users', 'salt', array('type' => 'varchar', 'length' => 32, 'not null' => TRUE, 'default' => '', 'description' => t("Salt for user's password.")));
+  // generate salts for existing users
+  $result = db_query("SELECT uid FROM {users} WHERE uid <> 0");
+  while ($user = db_fetch_object($result)) {
+    // pgsql only has a two op concat
+    $ret[] = update_sql("UPDATE {users} SET salt = MD5(CONCAT(CONCAT(init, created), '". mt_rand() ."')) WHERE uid = '$user->uid'");
+  }
+  $ret[] = update_sql('UPDATE {users} SET pass = MD5(CONCAT(pass, salt)) WHERE uid <> 0');
+  return $ret;
+}
+
Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.893
diff -u -p -r1.893 user.module
--- modules/user/user.module	6 Feb 2008 19:38:28 -0000	1.893
+++ modules/user/user.module	15 Feb 2008 21:26:08 -0000
@@ -156,7 +156,7 @@ function user_load($array = array()) {
       $params[] = $value;
     }
     else if ($key == 'pass') {
-      $query[] = "pass = '%s'";
+      $query[] = "pass = MD5(CONCAT('%s', salt))";
       $params[] = md5($value);
     }
     else {
@@ -213,7 +213,8 @@ function user_save($account, $array = ar
   if (is_object($account) && $account->uid) {
     user_module_invoke('update', $array, $account, $category);
     $query = '';
-    $data = unserialize(db_result(db_query('SELECT data FROM {users} WHERE uid = %d', $account->uid)));
+    $old_account = db_fetch_object(db_query('SELECT data, init, created, salt FROM {users} WHERE uid = %d', $account->uid));
+    $data = unserialize($old_account->data);
     // Consider users edited by an administrator as logged in, if they haven't
     // already, so anonymous users can view the profile (if allowed).
     if (empty($array['access']) && empty($account->access) && user_access('administer users')) {
@@ -222,7 +223,7 @@ function user_save($account, $array = ar
     foreach ($array as $key => $value) {
       if ($key == 'pass' && !empty($value)) {
         $query .= "$key = '%s', ";
-        $v[] = md5($value);
+        $v[$key] = md5($value);
       }
       else if ((substr($key, 0, 4) !== 'auth') && ($key != 'pass')) {
         if (in_array($key, $user_fields)) {
@@ -241,6 +242,14 @@ function user_save($account, $array = ar
         }
       }
     }
+    if (isset($v['pass'])) {
+      $init = isset($v['init']) ? $v['init'] : $old_account->init;
+      $created = isset($v['created']) ? $v['created'] : $old_account->created;
+      // Generate a new salt
+      $query .= "salt = '%s', ";
+      $v['salt'] = md5($init . $created . mt_rand());
+      $v['pass'] = md5($v['pass'] . $v['salt']);
+    }
     $query .= "data = '%s' ";
     $v[] = serialize($data);
 
@@ -303,25 +312,32 @@ function user_save($account, $array = ar
       switch ($key) {
         case 'pass':
           $fields[] = $key;
-          $values[] = md5($value);
+          $values[$key] = md5($value);
           $s[] = "'%s'";
           break;
         case 'mode':       case 'sort':     case 'timezone':
         case 'threshold':  case 'created':  case 'access':
         case 'login':      case 'status':
           $fields[] = $key;
-          $values[] = $value;
+          $values[$key] = $value;
           $s[] = "%d";
           break;
         default:
           if (substr($key, 0, 4) !== 'auth' && in_array($key, $user_fields)) {
             $fields[] = $key;
-            $values[] = $value;
+            $values[$key] = $value;
             $s[] = "'%s'";
           }
           break;
       }
     }
+    if (isset($values['pass'])) {
+      // Create a new salt
+      $fields[] = 'salt';
+      $values['salt'] = md5((isset($values['init']) ? $values['init'] : '') . $values['created'] . mt_rand());
+      $s[] = "'%s'";
+      $values['pass'] = md5($values['pass'] . $values['salt']);
+    }
     $success = db_query('INSERT INTO {users} ('. implode(', ', $fields) .') VALUES ('. implode(', ', $s) .')', $values);
     if (!$success) {
       // On a failed INSERT some other existing user's uid may be returned.
