1
0
mirror of https://github.com/mailcow/mailcow-dockerized.git synced 2024-11-24 08:32:50 +02:00

[Web] Force user pass update via Modal

This commit is contained in:
FreddleSpl0it 2024-08-20 09:43:08 +02:00
parent 74b4097ee0
commit 2f401c9fc4
No known key found for this signature in database
GPG Key ID: 00E14E7634F4BEC5
6 changed files with 170 additions and 78 deletions

View File

@ -0,0 +1,6 @@
<?php
session_start();
unset($_SESSION['pending_mailcow_cc_username']);
unset($_SESSION['pending_mailcow_cc_role']);
unset($_SESSION['pending_pw_update']);
?>

View File

@ -60,6 +60,7 @@ $globalVariables = [
), ),
'js_path' => '/cache/'.basename($JSPath), 'js_path' => '/cache/'.basename($JSPath),
'pending_tfa_methods' => @$_SESSION['pending_tfa_methods'], 'pending_tfa_methods' => @$_SESSION['pending_tfa_methods'],
'pending_pw_update' => @$_SESSION['pending_pw_update'],
'pending_tfa_authmechs' => $pending_tfa_authmechs, 'pending_tfa_authmechs' => $pending_tfa_authmechs,
'pending_mailcow_cc_username' => @$_SESSION['pending_mailcow_cc_username'], 'pending_mailcow_cc_username' => @$_SESSION['pending_mailcow_cc_username'],
'lang_footer' => json_encode($lang['footer']), 'lang_footer' => json_encode($lang['footer']),

View File

@ -905,7 +905,7 @@ function check_login($user, $pass, $app_passwd_data = false) {
} }
// Validate mailbox user // Validate mailbox user
$stmt = $pdo->prepare("SELECT `password` FROM `mailbox` $stmt = $pdo->prepare("SELECT `password`, JSON_UNQUOTE(JSON_EXTRACT(`attributes`, '$.force_pw_update')) AS `force_pw_update` FROM `mailbox`
INNER JOIN domain on mailbox.domain = domain.domain INNER JOIN domain on mailbox.domain = domain.domain
WHERE `kind` NOT REGEXP 'location|thing|group' WHERE `kind` NOT REGEXP 'location|thing|group'
AND `mailbox`.`active`='1' AND `mailbox`.`active`='1'
@ -944,6 +944,12 @@ function check_login($user, $pass, $app_passwd_data = false) {
if (verify_hash($row['password'], $pass) !== false) { if (verify_hash($row['password'], $pass) !== false) {
if (!array_key_exists("app_passwd_id", $row)){ if (!array_key_exists("app_passwd_id", $row)){
// password is not a app password // password is not a app password
// check if pw update is required
if (array_key_exists('force_pw_update', $row) && intval($row['force_pw_update']) == 1) {
$_SESSION['pending_pw_update'] = True;
}
// check for tfa authenticators // check for tfa authenticators
$authenticators = get_tfa($user); $authenticators = get_tfa($user);
if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0 && if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0 &&
@ -1079,9 +1085,10 @@ function edit_user_account($_data) {
!isset($_data_log['user_new_pass2']) ?: $_data_log['user_new_pass2'] = '*'; !isset($_data_log['user_new_pass2']) ?: $_data_log['user_new_pass2'] = '*';
!isset($_data_log['user_old_pass']) ?: $_data_log['user_old_pass'] = '*'; !isset($_data_log['user_old_pass']) ?: $_data_log['user_old_pass'] = '*';
$username = $_SESSION['mailcow_cc_username']; $username = (!empty($_data['username'])) ? $_data['username'] : $_SESSION['mailcow_cc_username'];
$role = $_SESSION['mailcow_cc_role']; $role = (!empty($_data['role'])) ? $_data['role'] : $_SESSION['mailcow_cc_role'];
$password_old = $_data['user_old_pass']; $password_old = $_data['user_old_pass'];
$skip_old_password_check = $_data['skip_old_password_check'];
$pw_recovery_email = $_data['pw_recovery_email']; $pw_recovery_email = $_data['pw_recovery_email'];
if (filter_var($username, FILTER_VALIDATE_EMAIL === false) || $role != 'user') { if (filter_var($username, FILTER_VALIDATE_EMAIL === false) || $role != 'user') {
@ -1094,20 +1101,22 @@ function edit_user_account($_data) {
} }
// edit password // edit password
if (!empty($password_old) && !empty($_data['user_new_pass']) && !empty($_data['user_new_pass2'])) { if ((!empty($password_old) || $skip_old_password_check) && !empty($_data['user_new_pass']) && !empty($_data['user_new_pass2'])) {
$stmt = $pdo->prepare("SELECT `password` FROM `mailbox` if (!$skip_old_password_check) {
WHERE `kind` NOT REGEXP 'location|thing|group' $stmt = $pdo->prepare("SELECT `password` FROM `mailbox`
AND `username` = :user"); WHERE `kind` NOT REGEXP 'location|thing|group'
$stmt->execute(array(':user' => $username)); AND `username` = :user");
$row = $stmt->fetch(PDO::FETCH_ASSOC); $stmt->execute(array(':user' => $username));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (!verify_hash($row['password'], $password_old)) { if (!verify_hash($row['password'], $password_old)) {
$_SESSION['return'][] = array( $_SESSION['return'][] = array(
'type' => 'danger', 'type' => 'danger',
'log' => array(__FUNCTION__, $_data_log), 'log' => array(__FUNCTION__, $_data_log),
'msg' => 'access_denied' 'msg' => 'access_denied'
); );
return false; return false;
}
} }
$password_new = $_data['user_new_pass']; $password_new = $_data['user_new_pass'];
@ -1152,6 +1161,7 @@ function edit_user_account($_data) {
'log' => array(__FUNCTION__, $_data_log), 'log' => array(__FUNCTION__, $_data_log),
'msg' => array('mailbox_modified', htmlspecialchars($username)) 'msg' => array('mailbox_modified', htmlspecialchars($username))
); );
return true;
} }
function user_get_alias_details($username) { function user_get_alias_details($username) {
global $pdo; global $pdo;

View File

@ -10,8 +10,30 @@ if (!empty($_GET['sso_token'])) {
} }
} }
if (isset($_POST["forced_pw_update"]) && !empty($_POST['new_password']) && !empty($_POST['new_password2'])) {
$result = edit_user_account(array(
'username' => $_SESSION['pending_mailcow_cc_username'],
'role' => $_SESSION['pending_mailcow_cc_role'],
'user_new_pass' => $_POST['new_password'],
'user_new_pass2' => $_POST['new_password2'],
'skip_old_password_check' => True
));
if ($result) {
$_SESSION['mailcow_cc_username'] = $_SESSION['pending_mailcow_cc_username'];
$_SESSION['mailcow_cc_role'] = $_SESSION['pending_mailcow_cc_role'];
unset($_SESSION['pending_mailcow_cc_username']);
unset($_SESSION['pending_mailcow_cc_role']);
unset($_SESSION['pending_pw_update']);
}
header("Location: /");
exit;
}
if (isset($_POST["pw_reset_request"]) && !empty($_POST['username'])) { if (isset($_POST["pw_reset_request"]) && !empty($_POST['username'])) {
reset_password("issue", $_POST['username']); $resultreset_password("issue", $_POST['username']);
header("Location: /"); header("Location: /");
exit; exit;
} }
@ -47,13 +69,15 @@ if (isset($_POST["verify_tfa_login"])) {
header("Location: /"); header("Location: /");
exit; exit;
} else { } else {
$_SESSION['mailcow_cc_username'] = $_SESSION['pending_mailcow_cc_username']; if (!$_SESSION['pending_pw_update']) {
$_SESSION['mailcow_cc_role'] = $_SESSION['pending_mailcow_cc_role']; $_SESSION['mailcow_cc_username'] = $_SESSION['pending_mailcow_cc_username'];
unset($_SESSION['pending_mailcow_cc_username']); $_SESSION['mailcow_cc_role'] = $_SESSION['pending_mailcow_cc_role'];
unset($_SESSION['pending_mailcow_cc_role']); unset($_SESSION['pending_mailcow_cc_username']);
unset($_SESSION['pending_tfa_methods']); unset($_SESSION['pending_mailcow_cc_role']);
unset($_SESSION['pending_tfa_methods']);
header("Location: /user"); header("Location: /user");
}
} }
} else { } else {
unset($_SESSION['pending_pw_reset_token']); unset($_SESSION['pending_pw_reset_token']);
@ -97,24 +121,30 @@ if (isset($_POST["login_user"]) && isset($_POST["pass_user"])) {
header("Location: /mailbox"); header("Location: /mailbox");
} }
elseif ($as == "user") { elseif ($as == "user") {
$_SESSION['mailcow_cc_username'] = $login_user; if ($_SESSION['pending_pw_update']) {
$_SESSION['mailcow_cc_role'] = "user"; $_SESSION['pending_mailcow_cc_username'] = $login_user;
$http_parameters = explode('&', $_SESSION['index_query_string']); $_SESSION['pending_mailcow_cc_role'] = "user";
unset($_SESSION['index_query_string']); } else {
if (in_array('mobileconfig', $http_parameters)) { $_SESSION['mailcow_cc_username'] = $login_user;
if (in_array('only_email', $http_parameters)) { $_SESSION['mailcow_cc_role'] = "user";
header("Location: /mobileconfig.php?only_email"); $http_parameters = explode('&', $_SESSION['index_query_string']);
die(); unset($_SESSION['index_query_string']);
} if (in_array('mobileconfig', $http_parameters)) {
header("Location: /mobileconfig.php"); if (in_array('only_email', $http_parameters)) {
die(); header("Location: /mobileconfig.php?only_email");
die();
} }
header("Location: /user"); header("Location: /mobileconfig.php");
die();
}
header("Location: /user");
}
} }
elseif ($as != "pending") { elseif ($as != "pending") {
unset($_SESSION['pending_mailcow_cc_username']); unset($_SESSION['pending_mailcow_cc_username']);
unset($_SESSION['pending_mailcow_cc_role']); unset($_SESSION['pending_mailcow_cc_role']);
unset($_SESSION['pending_tfa_methods']); unset($_SESSION['pending_tfa_methods']);
unset($_SESSION['pending_pw_update']);
unset($_SESSION['mailcow_cc_username']); unset($_SESSION['mailcow_cc_username']);
unset($_SESSION['mailcow_cc_role']); unset($_SESSION['mailcow_cc_role']);
} }

View File

@ -211,8 +211,31 @@ function recursiveBase64StrToArrayBuffer(obj) {
mailcow_alert_box('{{ alert_msg|raw|e("js") }}', '{{ alert_type }}'); mailcow_alert_box('{{ alert_msg|raw|e("js") }}', '{{ alert_type }}');
{% endfor %} {% endfor %}
// Confirm PW Update modal
{% if pending_pw_update %}
new bootstrap.Modal(document.getElementById("ConfirmPWUpdateModal"), {
backdrop: 'static',
keyboard: false
}).show();
$('#ConfirmPWUpdateModal').on('hidden.bs.modal', function(){
// cancel pending login
$.ajax({
type: "GET",
cache: false,
dataType: 'script',
url: '/inc/ajax/destroy_pw_update.php',
complete: function(data){
window.location = window.location.href.split("#")[0];
}
});
});
{% endif %}
// Confirm TFA modal // Confirm TFA modal
{% if pending_tfa_methods %} {% if pending_tfa_methods %}
new bootstrap.Modal(document.getElementById("ConfirmTFAModal"), { new bootstrap.Modal(document.getElementById("ConfirmTFAModal"), {
backdrop: 'static', backdrop: 'static',
keyboard: false keyboard: false
@ -343,7 +366,7 @@ function recursiveBase64StrToArrayBuffer(obj) {
} }
}); });
}); });
{% endif %} {% endif %}
// Validate FIDO2 // Validate FIDO2

View File

@ -140,7 +140,6 @@
<button type="button" class="btn-close" data-bs-dismiss="modal"></button> <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div> </div>
<div class="modal-body p-0 pt-4"> <div class="modal-body p-0 pt-4">
<ul class="nav nav-tabs px-1" id="tabContent"> <ul class="nav nav-tabs px-1" id="tabContent">
{% if pending_tfa_authmechs["webauthn"] is defined and pending_tfa_authmechs["u2f"] is not defined %} {% if pending_tfa_authmechs["webauthn"] is defined and pending_tfa_authmechs["u2f"] is not defined %}
@ -311,6 +310,29 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
{% if pending_pw_update %}
<div class="modal fade" id="ConfirmPWUpdateModal" tabindex="-1" role="dialog" aria-labelledby="ConfirmPWUpdateModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">{{ lang.user.change_password }}</h3>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form method="post" autofill="off">
<input type="password" autocorrect="off" autocapitalize="none" class="form-control mb-2" name="new_password" placeholder="{{ lang.login.new_password }}" />
<input type="password" autocorrect="off" autocapitalize="none" class="form-control mb-2" name="new_password2" placeholder="{{ lang.login.new_password_confirm }}" />
<div class="d-flex justify-content-end mt-4" style="position: relative">
<button type="submit" class="btn btn-xs-lg d-block d-sm-inline btn-success" name="forced_pw_update">{{ lang.user.change_password }}</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endif %}
{% if mailcow_cc_role == 'admin' %} {% if mailcow_cc_role == 'admin' %}
<div id="RestartContainer" class="modal fade" role="dialog"> <div id="RestartContainer" class="modal fade" role="dialog">
<div class="modal-dialog"> <div class="modal-dialog">