[Web] multiple tfa - user support

This commit is contained in:
FreddleSpl0it 2022-03-07 11:41:13 +01:00
parent df33f1a130
commit a2d57d43d1
No known key found for this signature in database
GPG Key ID: F1B3BE8A3BBA3451
4 changed files with 60 additions and 21 deletions

View File

@ -936,24 +936,39 @@ function check_login($user, $pass, $app_passwd_data = false) {
$rows = array_merge($rows, $stmt->fetchAll(PDO::FETCH_ASSOC)); $rows = array_merge($rows, $stmt->fetchAll(PDO::FETCH_ASSOC));
} }
foreach ($rows as $row) { foreach ($rows as $row) {
// verify password
if (verify_hash($row['password'], $pass) !== false) { if (verify_hash($row['password'], $pass) !== false) {
unset($_SESSION['ldelay']); // check for tfa authenticators
$_SESSION['return'][] = array( $authenticators = get_tfa($user);
'type' => 'success', if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0) {
'log' => array(__FUNCTION__, $user, '*'), $_SESSION['pending_mailcow_cc_username'] = $user;
'msg' => array('logged_in_as', $user) $_SESSION['pending_mailcow_cc_role'] = "user";
); $_SESSION['pending_tfa_methods'] = $authenticators['additional'];
if ($app_passwd_data['eas'] === true || $app_passwd_data['dav'] === true) { unset($_SESSION['ldelay']);
$service = ($app_passwd_data['eas'] === true) ? 'EAS' : 'DAV'; $_SESSION['return'][] = array(
$stmt = $pdo->prepare("REPLACE INTO sasl_log (`service`, `app_password`, `username`, `real_rip`) VALUES (:service, :app_id, :username, :remote_addr)"); 'type' => 'success',
$stmt->execute(array( 'log' => array(__FUNCTION__, $user, '*'),
':service' => $service, 'msg' => array('logged_in_as', $user)
':app_id' => $row['app_passwd_id'], );
':username' => $user, return "pending";
':remote_addr' => ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR']) } else {
)); if ($app_passwd_data['eas'] === true || $app_passwd_data['dav'] === true) {
$service = ($app_passwd_data['eas'] === true) ? 'EAS' : 'DAV';
$stmt = $pdo->prepare("REPLACE INTO sasl_log (`service`, `app_password`, `username`, `real_rip`) VALUES (:service, :app_id, :username, :remote_addr)");
$stmt->execute(array(
':service' => $service,
':app_id' => $row['app_passwd_id'],
':username' => $user,
':remote_addr' => ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'])
));
}
unset($_SESSION['ldelay']);
// Reactivate TFA if it was set to "deactivate TFA for next login"
$stmt = $pdo->prepare("UPDATE `tfa` SET `active`='1' WHERE `username` = :user");
$stmt->execute(array(':user' => $user));
return "user";
} }
return "user";
} }
} }

View File

@ -61,9 +61,9 @@ if (isset($_POST["login_user"]) && isset($_POST["pass_user"])) {
header("Location: /user"); 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['mailcow_cc_username']); unset($_SESSION['mailcow_cc_username']);
unset($_SESSION['mailcow_cc_role']); unset($_SESSION['mailcow_cc_role']);
} }

View File

@ -15,6 +15,10 @@
<i class="bi bi-inbox-fill"></i> {{ lang.user.open_webmail_sso }} <i class="bi bi-inbox-fill"></i> {{ lang.user.open_webmail_sso }}
</a> </a>
{% endif %} {% endif %}
<div>
<hr>
<p><a href="#pwChangeModal" data-toggle="modal"><i class="bi bi-pencil-fill"></i> {{ lang.user.change_password }}</a></p>
</div>
</div> </div>
</div> </div>
<hr> <hr>
@ -40,8 +44,27 @@
</div> </div>
</div> </div>
<p>{{ mailboxdata.quota_used|formatBytes(2) }} / {% if mailboxdata.quota == 0 %}{% else %}{{ mailboxdata.quota|formatBytes(2) }}{% endif %}<br>{{ mailboxdata.messages }} {{ lang.user.messages }}</p> <p>{{ mailboxdata.quota_used|formatBytes(2) }} / {% if mailboxdata.quota == 0 %}{% else %}{{ mailboxdata.quota|formatBytes(2) }}{% endif %}<br>{{ mailboxdata.messages }} {{ lang.user.messages }}</p>
<hr> </div>
<p><a href="#pwChangeModal" data-toggle="modal"><i class="bi bi-pencil-fill"></i> {{ lang.user.change_password }}</a></p> </div>
<hr>
{# TFA #}
<div class="row">
<div class="col-sm-3 col-xs-5 text-right">{{ lang.tfa.tfa }}:</div>
<div class="col-sm-9 col-xs-7">
<p id="tfa_pretty">{{ tfa_data.pretty }}</p>
{% include 'tfa_keys.twig' %}
<br>
</div>
</div>
<div class="row">
<div class="col-sm-3 col-xs-5 text-right">{{ lang.tfa.set_tfa }}:</div>
<div class="col-sm-9 col-xs-7">
<select data-style="btn btn-sm dropdown-toggle bs-placeholder btn-default" data-width="fit" id="selectTFA" class="selectpicker" title="{{ lang.tfa.select }}">
<option value="yubi_otp">{{ lang.tfa.yubi_otp }}</option>
<option value="webauthn">{{ lang.tfa.webauthn }}</option>
<option value="totp">{{ lang.tfa.totp }}</option>
<option value="none">{{ lang.tfa.none }}</option>
</select>
</div> </div>
</div> </div>
<hr> <hr>

View File

@ -76,6 +76,7 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
'acl_json' => json_encode($_SESSION['acl']), 'acl_json' => json_encode($_SESSION['acl']),
'user_spam_score' => mailbox('get', 'spam_score', $username), 'user_spam_score' => mailbox('get', 'spam_score', $username),
'tfa_data' => $tfa_data, 'tfa_data' => $tfa_data,
'tfa_id' => @$_SESSION['tfa_id'],
'fido2_data' => $fido2_data, 'fido2_data' => $fido2_data,
'mailboxdata' => $mailboxdata, 'mailboxdata' => $mailboxdata,
'clientconfigstr' => $clientconfigstr, 'clientconfigstr' => $clientconfigstr,