Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
integration
prechecker
Commits
ec2d8ceb
Commit
ec2d8ceb
authored
Sep 30, 2012
by
Simon Coggins
Browse files
MDL-35332 lib: Improve security of hashed passwords
parent
63197378
Changes
27
Hide whitespace changes
Inline
Side-by-side
admin/tool/uploaduser/index.php
View file @
ec2d8ceb
...
...
@@ -618,7 +618,7 @@ if ($formdata = $mform2->is_cancelled()) {
// Do not mess with passwords of remote users.
}
else
if
(
!
$isinternalauth
)
{
$existinguser
->
password
=
'not cached'
;
$existinguser
->
password
=
AUTH_PASSWORD_NOT_CACHED
;
$upt
->
track
(
'password'
,
'-'
,
'normal'
,
false
);
// clean up prefs
unset_user_preference
(
'create_password'
,
$existinguser
);
...
...
@@ -626,6 +626,8 @@ if ($formdata = $mform2->is_cancelled()) {
}
else
if
(
!
empty
(
$user
->
password
))
{
if
(
$updatepasswords
)
{
// Check for passwords that we want to force users to reset next
// time they log in.
$errmsg
=
null
;
$weak
=
!
check_password_policy
(
$user
->
password
,
$errmsg
);
if
(
$resetpasswords
==
UU_PWRESET_ALL
or
(
$resetpasswords
==
UU_PWRESET_WEAK
and
$weak
))
{
...
...
@@ -638,7 +640,12 @@ if ($formdata = $mform2->is_cancelled()) {
unset_user_preference
(
'auth_forcepasswordchange'
,
$existinguser
);
}
unset_user_preference
(
'create_password'
,
$existinguser
);
// no need to create password any more
$existinguser
->
password
=
hash_internal_user_password
(
$user
->
password
);
// Use a low cost factor when generating bcrypt hash otherwise
// hashing would be slow when uploading lots of users. Hashes
// will be automatically updated to a higher cost factor the first
// time the user logs in.
$existinguser
->
password
=
hash_internal_user_password
(
$user
->
password
,
true
);
$upt
->
track
(
'password'
,
$user
->
password
,
'normal'
,
false
);
}
else
{
// do not print password when not changed
...
...
@@ -771,10 +778,14 @@ if ($formdata = $mform2->is_cancelled()) {
}
$forcechangepassword
=
true
;
}
$user
->
password
=
hash_internal_user_password
(
$user
->
password
);
// Use a low cost factor when generating bcrypt hash otherwise
// hashing would be slow when uploading lots of users. Hashes
// will be automatically updated to a higher cost factor the first
// time the user logs in.
$user
->
password
=
hash_internal_user_password
(
$user
->
password
,
true
);
}
}
else
{
$user
->
password
=
'not cached'
;
$user
->
password
=
AUTH_PASSWORD_NOT_CACHED
;
$upt
->
track
(
'password'
,
'-'
,
'normal'
,
false
);
}
...
...
auth/db/auth.php
View file @
ec2d8ceb
...
...
@@ -221,6 +221,9 @@ class auth_plugin_db extends auth_plugin_base {
if
(
$this
->
is_internal
())
{
$puser
=
$DB
->
get_record
(
'user'
,
array
(
'id'
=>
$user
->
id
),
'*'
,
MUST_EXIST
);
// This will also update the stored hash to the latest algorithm
// if the existing hash is using an out-of-date algorithm (or the
// legacy md5 algorithm).
if
(
update_internal_user_password
(
$puser
,
$newpassword
))
{
$user
->
password
=
$puser
->
password
;
return
true
;
...
...
auth/email/auth.php
View file @
ec2d8ceb
...
...
@@ -59,6 +59,9 @@ class auth_plugin_email extends auth_plugin_base {
*/
function
user_update_password
(
$user
,
$newpassword
)
{
$user
=
get_complete_user_data
(
'id'
,
$user
->
id
);
// This will also update the stored hash to the latest algorithm
// if the existing hash is using an out-of-date algorithm (or the
// legacy md5 algorithm).
return
update_internal_user_password
(
$user
,
$newpassword
);
}
...
...
auth/ldap/auth.php
View file @
ec2d8ceb
...
...
@@ -529,6 +529,9 @@ class auth_plugin_ldap extends auth_plugin_base {
profile_save_data
(
$user
);
$this
->
update_user_record
(
$user
->
username
);
// This will also update the stored hash to the latest algorithm
// if the existing hash is using an out-of-date algorithm (or the
// legacy md5 algorithm).
update_internal_user_password
(
$user
,
$plainslashedpassword
);
$user
=
$DB
->
get_record
(
'user'
,
array
(
'id'
=>
$user
->
id
));
...
...
auth/manual/auth.php
View file @
ec2d8ceb
...
...
@@ -82,6 +82,9 @@ class auth_plugin_manual extends auth_plugin_base {
*/
function
user_update_password
(
$user
,
$newpassword
)
{
$user
=
get_complete_user_data
(
'id'
,
$user
->
id
);
// This will also update the stored hash to the latest algorithm
// if the existing hash is using an out-of-date algorithm (or the
// legacy md5 algorithm).
return
update_internal_user_password
(
$user
,
$newpassword
);
}
...
...
auth/none/auth.php
View file @
ec2d8ceb
...
...
@@ -59,6 +59,9 @@ class auth_plugin_none extends auth_plugin_base {
*/
function
user_update_password
(
$user
,
$newpassword
)
{
$user
=
get_complete_user_data
(
'id'
,
$user
->
id
);
// This will also update the stored hash to the latest algorithm
// if the existing hash is using an out-of-date algorithm (or the
// legacy md5 algorithm).
return
update_internal_user_password
(
$user
,
$newpassword
);
}
...
...
auth/webservice/auth.php
View file @
ec2d8ceb
...
...
@@ -85,6 +85,9 @@ class auth_plugin_webservice extends auth_plugin_base {
*/
function
user_update_password
(
$user
,
$newpassword
)
{
$user
=
get_complete_user_data
(
'id'
,
$user
->
id
);
// This will also update the stored hash to the latest algorithm
// if the existing hash is using an out-of-date algorithm (or the
// legacy md5 algorithm).
return
update_internal_user_password
(
$user
,
$newpassword
);
}
...
...
backup/util/dbops/restore_dbops.class.php
View file @
ec2d8ceb
...
...
@@ -1052,7 +1052,7 @@ abstract class restore_dbops {
// Most external plugins do not store passwords locally
if
(
!
empty
(
$userauth
->
preventpassindb
))
{
$user
->
password
=
'not cached'
;
$user
->
password
=
AUTH_PASSWORD_NOT_CACHED
;
// If Moodle is responsible for storing/validating pwd and reset functionality is available, mark
}
else
if
(
$userauth
->
isinternal
and
$userauth
->
canresetpwd
)
{
...
...
config-dist.php
View file @
ec2d8ceb
...
...
@@ -63,28 +63,7 @@ $CFG->dboptions = array(
//=========================================================================
// 2. SECRET PASSWORD SALT
//=========================================================================
// User password salt is very important security feature, it is created
// automatically in installer, you have to uncomment and modify value
// on the next line if you are creating config.php manually.
//
// $CFG->passwordsaltmain = 'a_very_long_random_string_of_characters#@6&*1';
//
// After changing the main salt you have to copy old value into one
// of the following settings - this allows migration to the new salt
// during the next login of each user.
//
// $CFG->passwordsaltalt1 = '';
// $CFG->passwordsaltalt2 = '';
// $CFG->passwordsaltalt3 = '';
// ....
// $CFG->passwordsaltalt19 = '';
// $CFG->passwordsaltalt20 = '';
//=========================================================================
// 3. WEB SITE LOCATION
// 2. WEB SITE LOCATION
//=========================================================================
// Now you need to tell Moodle where it is located. Specify the full
// web address to where moodle has been installed. If your web site
...
...
@@ -98,7 +77,7 @@ $CFG->wwwroot = 'http://example.com/moodle';
//=========================================================================
//
4
. DATA FILES LOCATION
//
3
. DATA FILES LOCATION
//=========================================================================
// Now you need a place where Moodle can save uploaded files. This
// directory should be readable AND WRITEABLE by the web server user
...
...
@@ -114,7 +93,7 @@ $CFG->dataroot = '/home/example/moodledata';
//=========================================================================
//
5
. DATA FILES PERMISSIONS
//
4
. DATA FILES PERMISSIONS
//=========================================================================
// The following parameter sets the permissions of new directories
// created by Moodle within the data directory. The format is in
...
...
@@ -128,7 +107,7 @@ $CFG->directorypermissions = 02777;
//=========================================================================
//
6
. DIRECTORY LOCATION (most people can just ignore this setting)
//
5
. DIRECTORY LOCATION (most people can just ignore this setting)
//=========================================================================
// A very few webhosts use /admin as a special URL for you to access a
// control panel or something. Unfortunately this conflicts with the
...
...
@@ -140,7 +119,7 @@ $CFG->admin = 'admin';
//=========================================================================
//
7
. OTHER MISCELLANEOUS SETTINGS (ignore these for new installations)
//
6
. OTHER MISCELLANEOUS SETTINGS (ignore these for new installations)
//=========================================================================
//
// These are additional tweaks for which no GUI exists in Moodle yet.
...
...
@@ -471,7 +450,7 @@ $CFG->admin = 'admin';
// $CFG->svgicons = false;
//
//=========================================================================
//
8
. SETTINGS FOR DEVELOPMENT SERVERS - not intended for production use!!!
//
7
. SETTINGS FOR DEVELOPMENT SERVERS - not intended for production use!!!
//=========================================================================
//
// Force a debugging mode regardless the settings in the site administration
...
...
@@ -512,7 +491,7 @@ $CFG->admin = 'admin';
// $CFG->showcrondebugging = true;
//
//=========================================================================
//
9
. FORCED SETTINGS
//
8
. FORCED SETTINGS
//=========================================================================
// It is possible to specify normal admin settings here, the point is that
// they can not be changed through the standard admin settings pages any more.
...
...
@@ -527,12 +506,35 @@ $CFG->admin = 'admin';
// 'otherplugin' => array('mysetting' => 'myvalue', 'thesetting' => 'thevalue'));
//
//=========================================================================
//
10
. PHPUNIT SUPPORT
//
9
. PHPUNIT SUPPORT
//=========================================================================
// $CFG->phpunit_prefix = 'phpu_';
// $CFG->phpunit_dataroot = '/home/example/phpu_moodledata';
// $CFG->phpunit_directorypermissions = 02777; // optional
//
//
//=========================================================================
// 10. SECRET PASSWORD SALT
//=========================================================================
// A single site-wide password salt is no longer required *unless* you are
// upgrading an older version of Moodle (prior to 2.5), or if you are using
// a PHP version below 5.3.7. If upgrading, keep any values from your old
// config.php file. If you are using PHP < 5.3.7 set to a long random string
// below:
//
// $CFG->passwordsaltmain = 'a_very_long_random_string_of_characters#@6&*1';
//
// You may also have some alternative salts to allow migration from previously
// used salts.
//
// $CFG->passwordsaltalt1 = '';
// $CFG->passwordsaltalt2 = '';
// $CFG->passwordsaltalt3 = '';
// ....
// $CFG->passwordsaltalt19 = '';
// $CFG->passwordsaltalt20 = '';
//
//
//=========================================================================
// 11. BEHAT SUPPORT
//=========================================================================
...
...
lib/cronlib.php
View file @
ec2d8ceb
...
...
@@ -216,7 +216,11 @@ function cron_run() {
// note: we can not send emails to suspended accounts
foreach
(
$newusers
as
$newuser
)
{
if
(
setnew_password_and_mail
(
$newuser
))
{
// Use a low cost factor when generating bcrypt hash otherwise
// hashing would be slow when emailing lots of users. Hashes
// will be automatically updated to a higher cost factor the first
// time the user logs in.
if
(
setnew_password_and_mail
(
$newuser
,
true
))
{
unset_user_preference
(
'create_password'
,
$newuser
);
set_user_preference
(
'auth_forcepasswordchange'
,
1
,
$newuser
);
}
else
{
...
...
lib/db/install.xml
View file @
ec2d8ceb
...
...
@@ -753,7 +753,7 @@
<FIELD
NAME=
"suspended"
TYPE=
"int"
LENGTH=
"1"
NOTNULL=
"true"
DEFAULT=
"0"
SEQUENCE=
"false"
COMMENT=
"suspended flag prevents users to log in"
/>
<FIELD
NAME=
"mnethostid"
TYPE=
"int"
LENGTH=
"10"
NOTNULL=
"true"
DEFAULT=
"0"
SEQUENCE=
"false"
/>
<FIELD
NAME=
"username"
TYPE=
"char"
LENGTH=
"100"
NOTNULL=
"true"
SEQUENCE=
"false"
/>
<FIELD
NAME=
"password"
TYPE=
"char"
LENGTH=
"
3
2"
NOTNULL=
"true"
SEQUENCE=
"false"
/>
<FIELD
NAME=
"password"
TYPE=
"char"
LENGTH=
"2
55
"
NOTNULL=
"true"
SEQUENCE=
"false"
/>
<FIELD
NAME=
"idnumber"
TYPE=
"char"
LENGTH=
"255"
NOTNULL=
"true"
SEQUENCE=
"false"
/>
<FIELD
NAME=
"firstname"
TYPE=
"char"
LENGTH=
"100"
NOTNULL=
"true"
SEQUENCE=
"false"
/>
<FIELD
NAME=
"lastname"
TYPE=
"char"
LENGTH=
"100"
NOTNULL=
"true"
SEQUENCE=
"false"
/>
...
...
lib/db/upgrade.php
View file @
ec2d8ceb
...
...
@@ -1564,6 +1564,18 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint
(
true
,
2012120300.07
);
}
if
(
$oldversion
<
2013020900.00
)
{
// Changing precision of field password on table user to (255).
$table
=
new
xmldb_table
(
'user'
);
$field
=
new
xmldb_field
(
'password'
,
XMLDB_TYPE_CHAR
,
'255'
,
null
,
XMLDB_NOTNULL
,
null
,
null
,
'username'
);
// Launch change of precision for field password.
$dbman
->
change_field_precision
(
$table
,
$field
);
// Main savepoint reached.
upgrade_main_savepoint
(
true
,
2013020900.00
);
}
return
true
;
}
lib/installlib.php
View file @
ec2d8ceb
...
...
@@ -233,7 +233,10 @@ function install_generate_configphp($database, $cfg) {
}
$configphp
.
=
'$CFG->directorypermissions = '
.
$chmod
.
';'
.
PHP_EOL
.
PHP_EOL
;
$configphp
.
=
'$CFG->passwordsaltmain = '
.
var_export
(
complex_random_string
(),
true
)
.
';'
.
PHP_EOL
.
PHP_EOL
;
// A site-wide salt is only needed if bcrypt is not properly supported by the current version of PHP.
if
(
password_compat_not_supported
())
{
$configphp
.
=
'$CFG->passwordsaltmain = '
.
var_export
(
complex_random_string
(),
true
)
.
';'
.
PHP_EOL
.
PHP_EOL
;
}
$configphp
.
=
'require_once(dirname(__FILE__) . \'/lib/setup.php\');'
.
PHP_EOL
.
PHP_EOL
;
$configphp
.
=
'// There is no php closing tag in this file,'
.
PHP_EOL
;
...
...
lib/moodlelib.php
View file @
ec2d8ceb
...
...
@@ -493,6 +493,11 @@ define('USER_CAN_IGNORE_FILE_SIZE_LIMITS', -1);
define
(
'COURSE_DISPLAY_SINGLEPAGE'
,
0
);
// display all sections on one page
define
(
'COURSE_DISPLAY_MULTIPAGE'
,
1
);
// split pages into a page per section
/**
* Authentication constants.
*/
define
(
'AUTH_PASSWORD_NOT_CACHED'
,
'not cached'
);
// String used in password field when password is not stored.
/// PARAMETER HANDLING ////////////////////////////////////////////////////
/**
...
...
@@ -3845,6 +3850,7 @@ function create_user_record($username, $password, $auth = 'manual') {
if
(
!
empty
(
$CFG
->
{
'auth_'
.
$newuser
->
auth
.
'_forcechangepassword'
})){
set_user_preference
(
'auth_forcepasswordchange'
,
1
,
$user
);
}
// Set the password.
update_internal_user_password
(
$user
,
$password
);
// fetch full user record for the event, the complete user data contains too much info
...
...
@@ -4197,7 +4203,10 @@ function authenticate_user_login($username, $password, $ignorelockout=false, &$f
$user
->
auth
=
$auth
;
}
update_internal_user_password
(
$user
,
$password
);
// just in case salt or encoding were changed (magic quotes too one day)
// If the existing hash is using an out-of-date algorithm (or the
// legacy md5 algorithm), then we should update to the current
// hash algorithm while we have access to the user's password.
update_internal_user_password
(
$user
,
$password
);
if
(
$authplugin
->
is_synchronised_with_external
())
{
// update user record from external DB
$user
=
update_user_record
(
$username
);
...
...
@@ -4307,28 +4316,81 @@ function complete_user_login($user) {
}
/**
* Compare password against hash stored in internal user table.
* If necessary it also updates the stored hash to new format.
* Check a password hash to see if it was hashed using the
* legacy hash algorithm (md5).
*
* @param string $password String to check.
* @return boolean True if the $password matches the format of an md5 sum.
*/
function
password_is_legacy_hash
(
$password
)
{
return
(
bool
)
preg_match
(
'/^[0-9a-f]{32}$/'
,
$password
);
}
/**
* Checks whether the password compatibility library will work with the current
* version of PHP. This cannot be done using PHP version numbers since the fix
* has been backported to earlier versions in some distributions.
*
* See https://github.com/ircmaxell/password_compat/issues/10 for
* more details.
*
* @return bool True if the library is NOT supported.
*/
function
password_compat_not_supported
()
{
$hash
=
'$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG'
;
// Create a one off application cache to store bcrypt support status as
// the support status doesn't change and crypt() is slow.
$cache
=
cache
::
make_from_params
(
cache_store
::
MODE_APPLICATION
,
'core'
,
'password_compat'
);
if
(
!
$bcryptsupport
=
$cache
->
get
(
'bcryptsupport'
))
{
$test
=
crypt
(
'password'
,
$hash
);
// Cache string instead of boolean to avoid MDL-37472.
if
(
$test
==
$hash
)
{
$bcryptsupport
=
'supported'
;
}
else
{
$bcryptsupport
=
'not supported'
;
}
$cache
->
set
(
'bcryptsupport'
,
$bcryptsupport
);
}
// Return true if bcrypt *not* supported.
return
(
$bcryptsupport
!==
'supported'
);
}
/**
* Compare password against hash stored in user object to determine if it is valid.
*
* If necessary it also updates the stored hash to the current format.
*
* @param stdClass $user (
p
assword property may be updated)
* @param string $password
p
lain text password
* @return bool
is
password valid
?
* @param stdClass $user (
P
assword property may be updated)
.
* @param string $password
P
lain text password
.
* @return bool
True if
password
is
valid
.
*/
function
validate_internal_user_password
(
$user
,
$password
)
{
global
$CFG
;
require_once
(
$CFG
->
libdir
.
'/password_compat/lib/password.php'
);
if
(
!
isset
(
$CFG
->
passwordsaltmain
))
{
$CFG
->
passwordsaltmain
=
''
;
if
(
$user
->
password
===
AUTH_PASSWORD_NOT_CACHED
)
{
// Internal password is not used at all, it can not validate.
return
false
;
}
$validated
=
false
;
// If hash isn't a legacy (md5) hash, validate using the library function.
if
(
!
password_is_legacy_hash
(
$user
->
password
))
{
return
password_verify
(
$password
,
$user
->
password
);
}
if
(
$user
->
password
===
'not cached'
)
{
// i
nternal password is not used at all, it can not validate
// Otherwise we need to check for a legacy (md5) hash instead. If the hash
// i
s valid we can then update it to the new algorithm.
}
else
if
(
$user
->
password
===
md5
(
$password
.
$CFG
->
passwordsaltmain
)
$sitesalt
=
isset
(
$CFG
->
passwordsaltmain
)
?
$CFG
->
passwordsaltmain
:
''
;
$validated
=
false
;
if
(
$user
->
password
===
md5
(
$password
.
$sitesalt
)
or
$user
->
password
===
md5
(
$password
)
or
$user
->
password
===
md5
(
addslashes
(
$password
)
.
$
CFG
->
passwordsaltmain
)
or
$user
->
password
===
md5
(
addslashes
(
$password
)
.
$
sitesalt
)
or
$user
->
password
===
md5
(
addslashes
(
$password
)))
{
// note: we are intentionally using the addslashes() here because we
// need to accept old password hashes of passwords with magic quotes
...
...
@@ -4347,7 +4409,8 @@ function validate_internal_user_password($user, $password) {
}
if
(
$validated
)
{
// force update of password hash using latest main password salt and encoding if needed
// If the password matches the existing md5 hash, update to the
// current hash algorithm while we have access to the user's password.
update_internal_user_password
(
$user
,
$password
);
}
...
...
@@ -4355,39 +4418,85 @@ function validate_internal_user_password($user, $password) {
}
/**
* Calculate hashed value from password using current hash mechanism.
* Calculate hash for a plain text password.
*
* @param string $password Plain text password to be hashed.
* @param bool $fasthash If true, use a low cost factor when generating the hash
* This is much faster to generate but makes the hash
* less secure. It is used when lots of hashes need to
* be generated quickly.
* @return string The hashed password.
*
* @param string $password
* @return string password hash
* @throws moodle_exception If a problem occurs while generating the hash.
*/
function
hash_internal_user_password
(
$password
)
{
function
hash_internal_user_password
(
$password
,
$fasthash
=
false
)
{
global
$CFG
;
require_once
(
$CFG
->
libdir
.
'/password_compat/lib/password.php'
);
if
(
isset
(
$CFG
->
passwordsaltmain
))
{
return
md5
(
$password
.
$CFG
->
passwordsaltmain
);
}
else
{
return
md5
(
$password
);
// Use the legacy hashing algorithm (md5) if PHP is not new enough
// to support bcrypt properly
if
(
password_compat_not_supported
())
{
if
(
isset
(
$CFG
->
passwordsaltmain
))
{
return
md5
(
$password
.
$CFG
->
passwordsaltmain
);
}
else
{
return
md5
(
$password
);
}
}
// Set the cost factor to 4 for fast hashing, otherwise use default cost.
$options
=
(
$fasthash
)
?
array
(
'cost'
=>
4
)
:
array
();
$generatedhash
=
password_hash
(
$password
,
PASSWORD_DEFAULT
,
$options
);
if
(
$generatedhash
===
false
)
{
throw
new
moodle_exception
(
'Failed to generate password hash.'
);
}
return
$generatedhash
;
}
/**
* Update password hash in user object.
* Update password hash in user object
(if necessary)
.
*
* @param stdClass $user (password property may be updated)
* @param string $password plain text password
* @return bool always returns true
* The password is updated if:
* 1. The password has changed (the hash of $user->password is different
* to the hash of $password).
* 2. The existing hash is using an out-of-date algorithm (or the legacy
* md5 algorithm).
*
* Updating the password will modify the $user object and the database
* record to use the current hashing algorithm.
*
* @param stdClass $user User object (password property may be updated).
* @param string $password Plain text password.
* @return bool Always returns true.
*/
function
update_internal_user_password
(
$user
,
$password
)
{
global
$DB
;
global
$CFG
,
$DB
;
require_once
(
$CFG
->
libdir
.
'/password_compat/lib/password.php'
);
// Use the legacy hashing algorithm (md5) if PHP doesn't support
// bcrypt properly.
$legacyhash
=
password_compat_not_supported
();
// Figure out what the hashed password should be.
$authplugin
=
get_auth_plugin
(
$user
->
auth
);
if
(
$authplugin
->
prevent_local_passwords
())
{
$hashedpassword
=
'not cached'
;
$hashedpassword
=
AUTH_PASSWORD_NOT_CACHED
;
}
else
{
$hashedpassword
=
hash_internal_user_password
(
$password
);
}
if
(
$user
->
password
!==
$hashedpassword
)
{
if
(
$legacyhash
)
{
$passwordchanged
=
(
$user
->
password
!==
$hashedpassword
);
$algorithmchanged
=
false
;
}
else
{
// If verification fails then it means the password has changed.
$passwordchanged
=
!
password_verify
(
$password
,
$user
->
password
);
$algorithmchanged
=
password_needs_rehash
(
$user
->
password
,
PASSWORD_DEFAULT
);
}
if
(
$passwordchanged
||
$algorithmchanged
)
{
$DB
->
set_field
(
'user'
,
'password'
,
$hashedpassword
,
array
(
'id'
=>
$user
->
id
));
$user
->
password
=
$hashedpassword
;
}
...
...
@@ -5588,9 +5697,10 @@ function generate_email_supportuser() {
* @global object
* @global object
* @param user $user A {@link $USER} object
* @param boolean $fasthash If true, use a low cost factor when generating the hash for speed.
* @return boolean|string Returns "true" if mail was sent OK and "false" if there was an error
*/
function
setnew_password_and_mail
(
$user
)
{
function
setnew_password_and_mail
(
$user
,
$fasthash
=
false
)
{
global
$CFG
,
$DB
;
// we try to send the mail in language the user understands,
...
...
@@ -5604,7 +5714,8 @@ function setnew_password_and_mail($user) {
$newpassword
=
generate_password
();
$DB
->
set_field
(
'user'
,
'password'
,
hash_internal_user_password
(
$newpassword
),
array
(
'id'
=>
$user
->
id
));
$hashedpassword
=
hash_internal_user_password
(
$newpassword
,
$fasthash
);
$DB
->
set_field
(
'user'
,
'password'
,
$hashedpassword
,
array
(
'id'
=>
$user
->
id
));
$a
=
new
stdClass
();
$a
->
firstname
=
fullname
(
$user
,
true
);
...
...
lib/password_compat/lib/password.php
0 → 100644
View file @
ec2d8ceb
<?php
/**
* A Compatibility library with PHP 5.5's simplified password hashing API.
*
* @author Anthony Ferrara <ircmaxell@php.net>
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @copyright 2012 The Authors
*/
if
(
!
defined
(
'PASSWORD_BCRYPT'
))
{
define
(
'PASSWORD_BCRYPT'
,
1
);
define
(
'PASSWORD_DEFAULT'
,
PASSWORD_BCRYPT
);
/**
* Hash the password using the specified algorithm
*
* @param string $password The password to hash
* @param int $algo The algorithm to use (Defined by PASSWORD_* constants)
* @param array $options The options for the algorithm to use
*
* @return string|false The hashed password, or false on error.
*/
function
password_hash
(
$password
,
$algo
,
array
$options
=
array
())
{
if
(
!
function_exists
(
'crypt'
))
{
trigger_error
(
"Crypt must be loaded for password_hash to function"
,
E_USER_WARNING
);
return
null
;
}
if
(
!
is_string
(
$password
))
{
trigger_error
(
"password_hash(): Password must be a string"
,
E_USER_WARNING
);
return
null
;
}
if
(
!
is_int
(
$algo
))
{
trigger_error
(
"password_hash() expects parameter 2 to be long, "
.
gettype
(
$algo
)
.
" given"
,
E_USER_WARNING
);
return
null
;
}
switch
(
$algo
)
{
case
PASSWORD_BCRYPT
:
// Note that this is a C constant, but not exposed to PHP, so we don't define it here.
$cost
=
10
;
if
(
isset
(
$options
[
'cost'
]))
{
$cost
=
$options
[
'cost'
];
if
(
$cost
<
4
||
$cost
>
31
)
{
trigger_error
(
sprintf
(
"password_hash(): Invalid bcrypt cost parameter specified: %d"
,
$cost
),
E_USER_WARNING
);
return
null
;
}
}
$required_salt_len
=
22
;
$hash_format
=
sprintf
(
"$2y$%02d$"
,
$cost
);
break
;
default
:
trigger_error
(
sprintf
(
"password_hash(): Unknown password hashing algorithm: %s"
,
$algo
),
E_USER_WARNING
);
return
null
;
}
if
(
isset
(
$options
[
'salt'
]))
{
switch
(
gettype
(
$options
[
'salt'
]))
{
case
'NULL'
:
case
'boolean'
:
case
'integer'
:
case
'double'
:
case
'string'
:
$salt
=
(
string
)
$options
[
'salt'
];
break
;
case
'object'
:
if
(
method_exists
(
$options
[
'salt'
],
'__tostring'
))
{
$salt
=
(
string
)
$options
[
'salt'
];
break
;
}
case
'array'
:
case
'resource'
: