Skip to content
This repository was archived by the owner on Sep 10, 2021. It is now read-only.

Commit 73f3ff4

Browse files
committed
ENH: refs #952. Change models and controllers to use new password storage
1 parent 03cbdc9 commit 73f3ff4

File tree

14 files changed

+150
-151
lines changed

14 files changed

+150
-151
lines changed

core/AppController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public function preDispatch()
108108
if(count($tmp) == 2)
109109
{
110110
$userDao = $userModel->load($tmp[0]);
111-
if($userDao != false && md5($userDao->getPassword()) == $tmp[1])
111+
if($userDao != false && $userModel->hashExists($tmp[1]))
112112
{
113113
$user->Dao = $userDao;
114114
}

core/controllers/UserController.php

Lines changed: 39 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -102,34 +102,8 @@ function recoverpasswordAction()
102102
}
103103
}
104104

105-
// Create a new password
106-
$keychars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
107-
$length = 10;
108-
109-
/** make_seed_recoverpass */
110-
function make_seed_recoverpass()
111-
{
112-
list($usec, $sec) = explode(' ', microtime());
113-
return (float) $sec + ((float) $usec * 100000);
114-
}
115-
srand(make_seed_recoverpass());
116-
117-
$pass = "";
118-
$max = strlen($keychars) - 1;
119-
for($i = 0; $i <= $length; $i++)
120-
{
121-
$pass .= substr($keychars, rand(0, $max), 1);
122-
}
123-
$encrypted = md5($pass);
124-
125-
$passwordPrefix = Zend_Registry::get('configGlobal')->password->prefix;
126-
$salted = $pass;
127-
if(isset($passwordPrefix) && !empty($passwordPrefix))
128-
{
129-
$salted = $passwordPrefix.$pass;
130-
}
131-
132-
$user->setPassword(md5($salted));
105+
$pass = UtilityComponent::generateRandomString(10);
106+
$this->User->changePassword($user, $pass);
133107

134108
// Send the email
135109
$url = $this->getServerURL().$this->view->webroot;
@@ -384,7 +358,7 @@ function verifyemailAction()
384358
session_start();
385359
}
386360
$this->userSession->Dao = $this->User->createUser(
387-
$email, $pendingUser->getPassword(), $pendingUser->getFirstname(), $pendingUser->getLastname(), 0, true);
361+
$email, null, $pendingUser->getFirstname(), $pendingUser->getLastname(), 0, $pendingUser->getSalt());
388362
session_write_close();
389363

390364
$this->PendingUser->delete($pendingUser);
@@ -408,8 +382,15 @@ function ajaxloginAction()
408382
return;
409383
}
410384
$userDao = $this->User->getByEmail($form->getValue('email'));
411-
$passwordPrefix = Zend_Registry::get('configGlobal')->password->prefix;
412-
if($userDao !== false && md5($passwordPrefix.$form->getValue('password')) == $userDao->getPassword())
385+
if($userDao === false)
386+
{
387+
echo JsonComponent::encode(array('status' => 'error', 'message' => 'Invalid username or password'));
388+
return;
389+
}
390+
$instanceSalt = Zend_Registry::get('configGlobal')->password->prefix;
391+
$passwordHash = hash($userDao->getHashAlg(), $instanceSalt.$userDao->getSalt().$form->getValue('password'));
392+
393+
if($this->User->hashExists($passwordHash))
413394
{
414395
$notifications = Zend_Registry::get('notifier')->callback('CALLBACK_CORE_AUTH_INTERCEPT', array('user' => $userDao));
415396
foreach($notifications as $module => $value)
@@ -420,7 +401,11 @@ function ajaxloginAction()
420401
return;
421402
}
422403
}
423-
setcookie('midasUtil', $userDao->getKey().'-'.md5($userDao->getPassword()), time() + 60 * 60 * 24 * 30, '/'); //30 days
404+
if($userDao->getSalt() == '')
405+
{
406+
$passwordHash = $this->User->convertLegacyPasswordHash($userDao, $form->getValue('password'));
407+
}
408+
setcookie('midasUtil', $userDao->getKey().'-'.$passwordHash, time() + 60 * 60 * 24 * 30, '/'); //30 days
424409
Zend_Session::start();
425410
$user = new Zend_Session_Namespace('Auth_User');
426411
$user->setExpirationSeconds(60 * Zend_Registry::get('configGlobal')->session->lifetime);
@@ -431,7 +416,7 @@ function ajaxloginAction()
431416
}
432417
else
433418
{
434-
echo JsonComponent::encode(array('status' => 'error', 'message' => 'Login failed'));
419+
echo JsonComponent::encode(array('status' => 'error', 'message' => 'Invalid username or password'));
435420
}
436421
}
437422

@@ -473,10 +458,16 @@ function loginAction()
473458
if(!$authModule)
474459
{
475460
$userDao = $this->User->getByEmail($form->getValue('email'));
461+
if($userDao === false)
462+
{
463+
echo JsonComponent::encode(array('status' => false, 'message' => 'Invalid email or password'));
464+
return;
465+
}
476466
}
477467

478-
$passwordPrefix = Zend_Registry::get('configGlobal')->password->prefix;
479-
if($authModule || $userDao !== false && md5($passwordPrefix.$form->getValue('password')) == $userDao->getPassword())
468+
$instanceSalt = Zend_Registry::get('configGlobal')->password->prefix;
469+
$passwordHash = hash($userDao->getHashAlg(), $instanceSalt.$userDao->getSalt().$form->getValue('password'));
470+
if($authModule || $this->User->hashExists($passwordHash))
480471
{
481472
$notifications = Zend_Registry::get('notifier')->callback('CALLBACK_CORE_AUTH_INTERCEPT', array('user' => $userDao));
482473
foreach($notifications as $module => $value)
@@ -487,12 +478,16 @@ function loginAction()
487478
return;
488479
}
489480
}
481+
if($userDao->getSalt() == '')
482+
{
483+
$passwordHash = $this->User->convertLegacyPasswordHash($userDao, $form->getValue('password'));
484+
}
490485
$remember = $form->getValue('remerberMe');
491486
if(isset($remember) && $remember == 1)
492487
{
493488
if(!$this->isTestingEnv())
494489
{
495-
setcookie('midasUtil', $userDao->getKey().'-'.md5($userDao->getPassword()), time() + 60 * 60 * 24 * 30, '/'); //30 days
490+
setcookie('midasUtil', $userDao->getKey().'-'.$passwordHash, time() + 60 * 60 * 24 * 30, '/'); //30 days
496491
}
497492
}
498493
else
@@ -533,7 +528,7 @@ function loginAction()
533528
{
534529
echo JsonComponent::encode(array(
535530
'status' => false,
536-
'message' => 'Invalid login'));
531+
'message' => 'Invalid email or password'));
537532
}
538533
}
539534
} // end method login
@@ -673,22 +668,23 @@ public function settingsAction()
673668
}
674669
$oldPass = $this->_getParam('oldPassword');
675670
$newPass = $this->_getParam('newPassword');
676-
$passwordPrefix = Zend_Registry::get('configGlobal')->password->prefix;
677-
$userDao = $this->User->load($userDao->getKey());
678-
if($userDao != false && ((!$userDao->isAdmin() && $this->userSession->Dao->isAdmin()) || md5($passwordPrefix.$oldPass) == $userDao->getPassword()))
671+
$instanceSalt = Zend_Registry::get('configGlobal')->password->prefix;
672+
$hashedPasswordOld = hash($userDao->getHashAlg(), $instanceSalt.$userDao->getSalt().$oldPass);
673+
674+
if((!$userDao->isAdmin() && $this->userSession->Dao->isAdmin()) || $this->User->hashExists($hashedPasswordOld))
679675
{
680-
$userDao->setPassword(md5($passwordPrefix.$newPass));
681-
$this->User->save($userDao);
676+
$this->User->changePassword($userDao, $newPass);
682677
if(!isset($userId))
683678
{
684679
$this->userSession->Dao = $userDao;
685680
}
686681
echo JsonComponent::encode(array(true, $this->t('Changes saved')));
687-
Zend_Registry::get('notifier')->callback('CALLBACK_CORE_PASSWORD_CHANGED', array('userDao' => $userDao));
682+
Zend_Registry::get('notifier')->callback('CALLBACK_CORE_PASSWORD_CHANGED', array('userDao' => $userDao, 'password' => $newPass));
688683
}
689684
else
690685
{
691686
echo JsonComponent::encode(array(false, $this->t('The old password is incorrect')));
687+
return;
692688
}
693689
}
694690

core/controllers/components/MIDAS2MigrationComponent.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,6 @@ function migrate($userid)
505505
try
506506
{
507507
$userDao = $User->createUser($email, $password, $firstname, $lastname);
508-
$userDao->setPassword($password); // this is the encrypted password
509508
$User->save($userDao);
510509
}
511510
catch(Zend_Exception $e)

core/controllers/components/UtilityComponent.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ public static function generateRandomString($length, $alphabet = null)
622622

623623
$salt = '';
624624
$max = strlen($alphabet) - 1;
625-
for($i = 0; $i <= $length; $i++)
625+
for($i = 0; $i < $length; $i++)
626626
{
627627
$salt .= substr($alphabet, rand(0, $max), 1);
628628
}

core/database/upgrade/3.2.12.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public function mysql()
1414
{
1515
$this->db->query("ALTER TABLE `user` ADD COLUMN `hash_alg` varchar(32) NOT NULL default ''");
1616
$this->db->query("ALTER TABLE `user` ADD COLUMN `salt` varchar(64) NOT NULL default ''");
17+
$this->db->query("ALTER TABLE `pendinguser` ADD COLUMN `salt` varchar(64) NOT NULL default ''");
1718

1819
$this->db->query("CREATE TABLE `password` (
1920
`hash` varchar(128) NOT NULL,
@@ -22,12 +23,14 @@ public function mysql()
2223
$this->_movePasswords();
2324

2425
$this->db->query("ALTER TABLE `user` DROP `password`");
26+
$this->db->query("ALTER TABLE `pendinguser` DROP `password`");
2527
}
2628

2729
public function pgsql()
2830
{
2931
$this->db->query("ALTER TABLE \"user\" ADD COLUMN hash_alg character varying(32) NOT NULL DEFAULT ''");
3032
$this->db->query("ALTER TABLE \"user\" ADD COLUMN salt character varying(64) NOT NULL DEFAULT ''");
33+
$this->db->query("ALTER TABLE \"pendinguser\" ADD COLUMN salt character varying(64) NOT NULL DEFAULT ''");
3134

3235
$this->db->query("CREATE TABLE password (
3336
hash character varying(128) NOT NULL,
@@ -39,6 +42,7 @@ public function pgsql()
3942
$this->db->query("CLUSTER password USING password_hash");
4043

4144
$this->db->query("ALTER TABLE \"user\" DROP COLUMN password");
45+
$this->db->query("ALTER TABLE \"pendinguser\" DROP COLUMN password");
4246
}
4347

4448
public function postUpgrade()
@@ -59,9 +63,8 @@ private function _movePasswords()
5963
{
6064
$this->db->insert('password', array('hash' => $row['password']));
6165
}
62-
// Set the salt and hash alg to be the old instance wide salt and md5 for legacy users (i.e. all users currently in the system)
63-
$instanceSalt = Zend_Registry::get('configGlobal')->password->prefix;
64-
$this->db->update('user', array('hash_alg' => 'md5', 'salt' => $instanceSalt));
66+
// Set the salt and hash alg to the appropriate value to denote a legacy user
67+
$this->db->update('user', array('hash_alg' => 'md5', 'salt' => ''));
6568
}
6669
}
6770
?>

core/models/base/PendingUserModelBase.php

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public function __construct()
3838
'email' => array('type' => MIDAS_DATA),
3939
'firstname' => array('type' => MIDAS_DATA),
4040
'lastname' => array('type' => MIDAS_DATA),
41-
'password' => array('type' => MIDAS_DATA),
41+
'salt' => array('type' => MIDAS_DATA),
4242
'date_creation' => array('type' => MIDAS_DATA)
4343
);
4444
$this->initialize(); // required
@@ -49,26 +49,20 @@ public abstract function getByParams($params);
4949
public abstract function getAllByParams($params);
5050

5151
/**
52-
* Create the database record for inviting a user via email that is not registered yet
53-
* @param email The email of the user (should not exist in Midas already)
54-
* @param group The group to invite the user to
55-
* @param inviter The user issuing the invitation (typically the session user)
56-
* @return the created NewUserInvitationDao
52+
* Create the database record for a user who has registered but not had their email verified yet
5753
*/
5854
public function createPendingUser($email, $firstName, $lastName, $password)
5955
{
6056
$email = strtolower($email);
61-
$passwordPrefix = Zend_Registry::get('configGlobal')->password->prefix;
62-
if(isset($passwordPrefix) && !empty($passwordPrefix))
63-
{
64-
$password = $passwordPrefix.$password;
65-
}
57+
$instanceSalt = Zend_Registry::get('configGlobal')->password->prefix;
58+
$userSalt = UtilityComponent::generateRandomString(32);
59+
6660
$pendingUser = MidasLoader::newDao('PendingUserDao');
6761
$pendingUser->setEmail($email);
6862
$pendingUser->setAuthKey(UtilityComponent::generateRandomString(64, '0123456789abcdef'));
6963
$pendingUser->setFirstname($firstName);
7064
$pendingUser->setLastname($lastName);
71-
$pendingUser->setPassword(md5($password));
65+
$pendingUser->setSalt($userSalt);
7266
$pendingUser->setDateCreation(date('c'));
7367

7468
$userModel = MidasLoader::loadModel('User');
@@ -82,6 +76,7 @@ public function createPendingUser($email, $firstName, $lastName, $password)
8276
{
8377
$this->delete($existingPendingUser);
8478
}
79+
$userModel->storePasswordHash(hash('sha256', $instanceSalt.$userSalt.$password));
8580

8681
$this->save($pendingUser);
8782
return $pendingUser;

0 commit comments

Comments
 (0)