From 327617fb499c3ef37f01c7a2f84af6d8dd530c59 Mon Sep 17 00:00:00 2001
From: Dave Reid <dave@davereid.net>
Date: Thu, 30 Jun 2011 09:02:53 -0500
Subject: [PATCH] Issue #1205138: Do not re-hash password hashes that are already non-MD5 hashes in user_update_7000().

---
 .../upgrade/drupal-6.user-non-md5.database.php     |   68 ++++++++++++++++++++
 modules/simpletest/tests/upgrade/upgrade.user.test |   40 ++++++++++++
 modules/user/user.install                          |    6 ++
 3 files changed, 114 insertions(+), 0 deletions(-)
 create mode 100644 modules/simpletest/tests/upgrade/drupal-6.user-non-md5.database.php

diff --git a/modules/simpletest/tests/upgrade/drupal-6.user-non-md5.database.php b/modules/simpletest/tests/upgrade/drupal-6.user-non-md5.database.php
new file mode 100644
index 0000000..0d48d65
--- /dev/null
+++ b/modules/simpletest/tests/upgrade/drupal-6.user-non-md5.database.php
@@ -0,0 +1,68 @@
+<?php
+// Change the password field to allow longer hashes.
+db_change_field('users', 'pass', 'pass', array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => ''));
+
+db_insert('users')->fields(array(
+  'uid',
+  'name',
+  'pass',
+  'mail',
+  'mode',
+  'sort',
+  'threshold',
+  'theme',
+  'signature',
+  'signature_format',
+  'created',
+  'access',
+  'login',
+  'status',
+  'timezone',
+  'language',
+  'picture',
+  'init',
+  'data',
+))
+->values(array(
+  'uid' => 100,
+  'name' => 'admin2',
+  'pass' => '$S$CQ147sACwJ9shdRWto5Vkj.DA43xecVepEtDraUQGFUs/2atFU/S', // 'admin'
+  'mail' => 'admin2@example.com',
+  'mode' => '0',
+  'sort' => '0',
+  'threshold' => '0',
+  'theme' => '',
+  'signature' => '',
+  'signature_format' => '0',
+  'created' => '1277671599',
+  'access' => '1277671612',
+  'login' => '1277671612',
+  'status' => '1',
+  'timezone' => '-21600',
+  'language' => '',
+  'picture' => '',
+  'init' => 'admin2@example.com',
+  'data' => 'a:0:{}',
+))
+->values(array(
+  'uid' => 101,
+  'name' => 'normal',
+  'pass' => 'U$S$9OjRAmk7gwK97pMYSZpDXer1SQ/0H9m0aCx8zo5xXToFUha1kSjU', // 'normal'
+  'mail' => 'normal@example.com',
+  'mode' => '0',
+  'sort' => '0',
+  'threshold' => '0',
+  'theme' => '',
+  'signature' => '',
+  'signature_format' => '0',
+  'created' => '1277671599',
+  'access' => '1277671612',
+  'login' => '1277671612',
+  'status' => '1',
+  'timezone' => '-21600',
+  'language' => '',
+  'picture' => '',
+  'init' => 'normal@example.com',
+  'data' => 'a:0:{}',
+))
+->execute();
diff --git a/modules/simpletest/tests/upgrade/upgrade.user.test b/modules/simpletest/tests/upgrade/upgrade.user.test
index 6c66921..ebad57c 100644
--- a/modules/simpletest/tests/upgrade/upgrade.user.test
+++ b/modules/simpletest/tests/upgrade/upgrade.user.test
@@ -58,3 +58,43 @@ class UserUpgradePathNoPasswordTokenTestCase extends UpgradePathTestCase {
     $this->assertEqual(variable_get('user_mail_register_no_approval_required_body'), '[user:name], [site:name], [site:url], [site:url-brief], [user:mail], [date:medium], [site:login-url], [user:edit-url], [user:one-time-login-url].', 'Existing email templates have been modified (password token not involved).');
   }
 }
+
+/**
+ * Upgrade test for user.module (non-MD5 password hashes).
+ */
+class UserUpgradeNonMD5PasswordHashesTestCase extends UpgradePathTestCase {
+  public static function getInfo() {
+    return array(
+      'name'  => 'User upgrade path (non-MD5 password hashes)',
+      'description'  => 'User upgrade path tests (non-MD5 password hashes).',
+      'group' => 'Upgrade path',
+    );
+  }
+
+  public function setUp() {
+    // Path to the database dump files.
+    $this->databaseDumpFiles = array(
+      drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-6.bare.database.php',
+      drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-6.user-non-md5.database.php',
+    );
+    parent::setUp();
+  }
+
+  /**
+   * Test a successful upgrade.
+   */
+  public function testUserUpgrade() {
+    // Assert that users with non-MD5 passwords in Drupal 6 can log in directly
+    // and did not have their password hashes destroyed by user_update_7000().
+    $this->drupalLogin((object) array(
+      'uid' => 100,
+      'name' => 'admin2',
+      'pass_raw' => 'admin',
+    ));
+    $this->drupalLogin((object) array(
+      'uid' => 101,
+      'name' => 'normal',
+      'pass_raw' => 'normal',
+    ));
+  }
+}
diff --git a/modules/user/user.install b/modules/user/user.install
index 75fca65..25981a8 100644
--- a/modules/user/user.install
+++ b/modules/user/user.install
@@ -421,6 +421,12 @@ function user_update_7000(&$sandbox) {
     $result = db_query_range("SELECT uid, pass FROM {users} WHERE uid > 0 ORDER BY uid", $sandbox['user_from'], $count);
     foreach ($result as $account) {
       $has_rows = TRUE;
+
+      // If this password is already a valid non-MD5 hash, skip upgrading it.
+      if (preg_match('/^U?\$/', $account->pass)) {
+        continue;
+      }
+
       $new_hash = user_hash_password($account->pass, $hash_count_log2);
       if ($new_hash) {
         // Indicate an updated password.
-- 
1.7.1

