['regexp' => '/^[a-zA-Z0-9]+$/']]);
$hash = db_fetch_row_prepared('SELECT *
FROM user_auth_reset_hashes
WHERE hash = ?
AND expiry > NOW()
LIMIT 1',
[$user_hash]);
if (!$hash || $hash['hash'] != $user_hash) {
$errorMessage = "" . __('Incorrect resetlink hash') . '';
$action = 'formidentity';
}
break;
case 'resetrequest': // try to find user in db. If yes and has email, send resetlink
$user = [];
$identity = gnrv('identity');
if (filter_var($identity, FILTER_VALIDATE_EMAIL) ||
gfrv('identity', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^[a-zA-Z0-9]+$/']])) {
$user = db_fetch_row_prepared('SELECT id, username, email_address
FROM user_auth
WHERE (username = ? OR email_address = ?)
AND realm = 0
AND enabled = "on"
AND password_change = "on"
LIMIT 1',
[$identity, $identity]);
}
if (cacti_sizeof($user) && $user['email_address'] != '') {
$hash = generate_hash();
if (auth_reset_token_replace($user['id'], $hash, (int) read_config_option('secnotify_resetlink_timeout'))) {
$replacement = [
read_config_option('base_url') . CACTI_PATH_URL,
$user['username'],
read_config_option('base_url') . CACTI_PATH_URL . 'auth_resetpassword.php?action=formreset&hash=' . $hash
];
$search = ['', '', ''];
$body = str_replace($search, $replacement, read_config_option('secnotify_chpass_message'));
send_mail($user['email_address'], null, read_config_option('secnotify_chpass_subject'), $body, [], [], true);
cacti_log(sprintf('NOTE: Reset password request for user %s from IP %s', $user['username'], get_client_addr()), false, 'SYSTEM');
} else {
cacti_log(sprintf('ERROR: Unable to replace password reset token for user %s', $user['username']), false, 'AUTH');
}
} else {
cacti_log(sprintf('NOTE: Reset password request for unknown user "%s" from IP %s', db_qstr($identity), get_client_addr()), false, 'SYSTEM');
}
$errorMessage = "" . __('Reset password token was sent. Check your mailbox') . '';
$action = 'formidentity';
break;
case 'resetpassword': // check and save new password
$user_hash = gfrv('hash', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^[a-zA-Z0-9]+$/']]);
$hash = db_fetch_row_prepared('SELECT *
FROM user_auth_reset_hashes
WHERE hash = ?
AND expiry > NOW()
LIMIT 1',
[$user_hash]);
if (!$hash || $hash['hash'] != $user_hash) {
$errorMessage = "" . __('Incorrect resetlink hash') . '';
$action = 'formidentity';
break;
}
$user = db_fetch_row_prepared('SELECT *
FROM user_auth
WHERE id = ?
AND realm = 0
AND enabled = "on"',
[$hash['user_id']]);
if (!cacti_sizeof($user)) {
$errorMessage = "" . __('Password reset is not available for this account.') . '';
$action = 'formidentity';
break;
}
// Get passwords entered for change
$password = gnrv('password');
$password_confirm = gnrv('password_confirm');
// Secpass checking
$error = secpass_check_pass($password);
// Check new password passes basic checks
if ($error != 'ok') {
$errorMessage = "$error";
$action = 'formreset';
break;
}
// Check user password history
if (!secpass_check_history($user['id'], $password)) {
$action = 'formreset';
break;
}
// Password and Confirmed password checks
if ($password !== $password_confirm) {
$errorMessage = "" . __('Your new passwords do not match, please retype.') . '';
$action = 'formreset';
break;
}
// Check new password does not match stored password
if (compat_password_verify($password, $user['password'])) {
$errorMessage = "" . __('Your new password cannot be the same as the old password. Please try again.') . '';
$action = 'formreset';
break;
}
// If password isn't blank, password change is good to go
if ($password != '') {
db_check_password_length();
if (!db_begin_transaction()) {
$errorMessage = "" . __('Unable to securely consume the password reset link.') . '';
$action = 'formidentity';
break;
}
$locked_user = db_fetch_cell_prepared('SELECT id
FROM user_auth
WHERE id = ?
AND realm = 0
AND enabled = "on"
FOR UPDATE',
[$user['id']]);
$locked_token_user = db_fetch_cell_prepared('SELECT user_id
FROM user_auth_reset_hashes
WHERE user_id = ?
AND hash = ?
AND expiry > NOW()
FOR UPDATE',
[$user['id'], $user_hash]);
if ((int) $locked_user !== (int) $user['id'] ||
(int) $locked_token_user !== (int) $user['id']) {
db_rollback_transaction();
$errorMessage = "" . __('Incorrect resetlink hash') . '';
$action = 'formidentity';
break;
}
$reset_ok = true;
if (read_config_option('secpass_expirepass') > 0) {
$reset_ok = db_execute_prepared("UPDATE user_auth
SET lastchange = ?
WHERE id = ?
AND realm = 0
AND enabled = 'on'",
[time(), $user['id']]) !== false;
}
$history = intval(read_config_option('secpass_history'));
if ($history > 0) {
$h = db_fetch_row_prepared("SELECT password, password_history
FROM user_auth
WHERE id = ?
AND realm = 0
AND enabled = 'on'",
[$user['id']]);
$op = $h['password'];
$h = explode('|', $h['password_history']);
while (cacti_count($h) > $history - 1) {
array_shift($h);
}
$h[] = $op;
$h = implode('|', $h);
$reset_ok = $reset_ok && db_execute_prepared("UPDATE user_auth
SET password_history = ?
WHERE id = ?
AND realm = 0
AND enabled = 'on'",
[$h, $user['id']]) !== false;
}
$reset_ok = $reset_ok && db_execute_prepared('INSERT IGNORE INTO user_log
(username, result, time, ip)
VALUES (?, 3, NOW(), ?)',
[$user['username'], get_client_addr()]) !== false;
$reset_ok = $reset_ok && db_execute_prepared("UPDATE user_auth
SET must_change_password = '', password = ?
WHERE id = ?",
[compat_password_hash($password, PASSWORD_DEFAULT), $user['id']]) !== false;
$reset_ok = $reset_ok && db_execute_prepared('DELETE FROM user_auth_reset_hashes
WHERE user_id = ?',
[$user['id']]) !== false;
$reset_ok = $reset_ok && db_execute_prepared('DELETE FROM user_auth_cache WHERE user_id = ?', [$user['id']]) !== false;
$reset_ok = $reset_ok && db_execute_prepared('DELETE FROM sessions WHERE user_id = ?', [$user['id']]) !== false;
if (!$reset_ok || !db_commit_transaction()) {
db_rollback_transaction();
$errorMessage = "" . __('Unable to securely consume the password reset link.') . '';
$action = 'formidentity';
break;
}
raise_message('password_success');
header('Location: index.php');
exit;
} else {
$action = 'resetpassword';
$return = CACTI_PATH_URL . 'resetpassword.php';
}
break;
}
// show identity form or reset password form
if (api_plugin_hook_function('custom_password', OPER_MODE_NATIVE) == OPER_MODE_RESKIN) {
exit;
}
// Create tooltip for password complexity
$secpass_tooltip = "" . __('Password requirements include:') . '
';
$secpass_body = '';
if (read_config_option('secpass_minlen') > 0) {
$secpass_body .= __('Must be at least %d characters in length', read_config_option('secpass_minlen'));
}
if (read_config_option('secpass_reqmixcase') == 'on') {
$secpass_body .= ($secpass_body != '' ? '
' : '') . __('Must include mixed case');
}
if (read_config_option('secpass_reqnum') == 'on') {
$secpass_body .= ($secpass_body != '' ? '
' : '') . __('Must include at least 1 number');
}
if (read_config_option('secpass_reqspec') == 'on') {
$secpass_body .= ($secpass_body != '' ? '
' : '') . __('Must include at least 1 special character');
}
if (read_config_option('secpass_history') != '0') {
$secpass_body .= ($secpass_body != '' ? '
' : '') . __('Cannot be reused for %d password changes', read_config_option('secpass_history') + 1);
}
$secpass_tooltip .= $secpass_body;
$selectedTheme = get_selected_theme();
if ($action == 'formidentity') {
$title_message = __('Please enter your Cacti username or email address.');
} elseif ($action == 'formreset') {
$title_message = __('Please enter your new Cacti password.');
} else {
$title_message = __('Reset password problem.');
}
html_auth_header('reset_password', __('Reset Password'), __('Reset Password'), $title_message);
?>
|
|
|
|
|
'>
|
|
|
|
|
|
|
|
'>
|
$(function() {
if ($('#identity').length) {
$('#identity').focus();
} else {
$('#password').focus();
}
/* clear passwords */
$('#password').val('');
$('#password_confirm').val('');
});
");