diff --git a/include/user.php b/include/user.php index 944b772..2532e20 100644 --- a/include/user.php +++ b/include/user.php @@ -63,11 +63,55 @@ class User { { $sQuery = "SELECT * FROM user_list - WHERE email = '?' - AND password = password('?')"; - $hResult = query_parameters($sQuery, $sEmail, $sPassword); + WHERE email = '?' AND password = "; + + $sMysqlSHAPasswordPart = "SHA1('?');"; + $sMysqlPasswordPart = "password('?');"; + $sMysql40xPasswordPart = "old_password('?');"; + + // if true we used an old style password and we need to + // update the users password to the new style + $bUsedOldStylePassword = false; + + $oRow = null; // null out the row object + + // if we aren't logged in yet + // try to login with the mysql sha1() value of the password + if(!$oRow) + { + $hResult = query_parameters($sQuery.$sMysqlSHAPasswordPart, + $sEmail, $sPassword); + $oRow = mysql_fetch_object($hResult); + } + + // if we aren't logged in yet + // try to login with the mysql password() value of the password + if(!$oRow) + { + $hResult = query_parameters($sQuery.$sMysqlPasswordPart, + $sEmail, $sPassword); + $oRow = mysql_fetch_object($hResult); + if($oRow) $bUsedOldStylePassword = true; + } + + // if we aren't logged in yet + // try to login with the mysql old_password() value of the password + if(!$oRow) + { + // make sure we have a newer version, older versions may not + $sResult = mysql_get_server_info(); + $fVersion = substr($sResult, 0, 3); + + // if we have a newer version of mysql, try with the 'old_password()' function + if($fVersion >= 4.1) + { + $hResult = query_parameters($sQuery.$sMysql40xPasswordPart, + $sEmail, $sPassword); + $oRow = mysql_fetch_object($hResult); + if($oRow) $bUsedOldStylePassword = true; + } + } - $oRow = mysql_fetch_object($hResult); if($oRow) { $this->iUserId = $oRow->userid; @@ -76,6 +120,12 @@ class User { $this->sStamp = $oRow->stamp; $this->sDateCreated = $oRow->created; $this->sWineRelease = $oRow->CVSrelease; + + // if we used an old style password, update the users password + if($bUsedOldStylePassword) + { + $this->update_password($sPassword); + } } if($this->isLoggedIn()) @@ -115,7 +165,7 @@ class User { } else { $hResult = query_parameters("INSERT INTO user_list (realname, email, CVSrelease, password, stamp,". - "created) VALUES ('?', '?', '?', password('?'), ?, ?)", + "created) VALUES ('?', '?', '?', SHA1('?'), ?, ?)", $sRealname, $sEmail, $sWineRelease, $sPassword, "NOW()", "NOW()"); if(!$hResult) return USER_CREATE_FAILED; @@ -180,7 +230,8 @@ class User { { if($sPassword) { - if (query_parameters("UPDATE user_list SET password = password('?') WHERE userid = '?'", + if (query_parameters("UPDATE user_list SET password = SHA1('?') ". + "WHERE userid = '?'", $sPassword, $this->iUserId)) return true; } diff --git a/unit_test/test_user.php b/unit_test/test_user.php index d4badde..5758b4c 100644 --- a/unit_test/test_user.php +++ b/unit_test/test_user.php @@ -319,12 +319,15 @@ if(!test_user_update_password()) echo "test_user_update_password() passed\n"; } +// perform tests related to user password migration +include_once("test_user_password_migration.php"); + /* Perform the maintainer tests here because they require that a user we can log into */ /* and we want to save on having to clean up the user by duplicating the cleanup code below */ include_once("test_maintainer.php"); -/* TODO: the rest of the user member functions we don't currently test */ +/* TODO: the rest of the user member functions we don't currently test */ /* clean up the user we created during the tests */ /* so the unit test leaves no trace that it ran */ diff --git a/unit_test/test_user_password_migration.php b/unit_test/test_user_password_migration.php new file mode 100644 index 0000000..af05b2e --- /dev/null +++ b/unit_test/test_user_password_migration.php @@ -0,0 +1,85 @@ +password; + + // test that the user was created with the sha1 hash of their password + $sQuery = "select password from user_list where userid = '?';"; + $hResult = query_parameters($sQuery, $oUser->iUserId); + $oRow = mysql_fetch_object($hResult); + if($sTestUserPasswordSHA1 != $oRow->password) + { + error("sTestUserPasswordSHA1 $sTestUserPasswordSHA1 doesn't match oRow->password of $oRow->password after user::create()"); + $bSuccess = false; + } + + // build an array of the different types of password hashing + $aPasswordForm = array(); + $aPasswordForm[] = "old_password('?')"; + $aPasswordForm[] = "password('?')"; + $aPasswordForm[] = "sha1('?')"; + + foreach($aPasswordForm as $sPasswordForm) + { + // manually set the users password + $sQuery = "update user_list set password = ".$sPasswordForm." where userid = '?';"; + query_parameters($sQuery, $sTestPassword, $oUser->iUserId); + + // attempt to login + $retval = $oUser->login($sTestEmail, $sTestPassword); + if($retval != SUCCESS) + { + error("Failed to login when the user has an $sPasswordForm generated hash!"); + $bSuccess = false; + } + + // test that the users password has been updated to the SHA1 hash + // after the user was logged in + $sQuery = "select password from user_list where userid = '?';"; + $hResult = query_parameters($sQuery, $oUser->iUserId); + $oRow = mysql_fetch_object($hResult); + if($sTestUserPasswordSHA1 != $oRow->password) + { + error("sTestUserPasswordSHA1 $sTestUserPasswordSHA1 doesn't match oRow->password of $oRow->password"); + $bSuccess = false; + } + } + + // delete the user we created, we want the database to be left + // as it was before we ran our tests on it + $oUser->delete(); + + return $bSuccess; +} + + + +if(!test_user_password_migration()) +{ + echo "test_user_password_migration() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_user_password_migration() passed\n"; +} + +?>