commit
02512e0f4f
@ -269,6 +269,7 @@ code {
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
background: #fbfbfb;
|
background: #fbfbfb;
|
||||||
border: 1px solid #ededed;
|
border: 1px solid #ededed;
|
||||||
|
min-height: 110px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag-box {
|
.tag-box {
|
||||||
|
@ -937,22 +937,33 @@ function check_login($user, $pass, $app_passwd_data = false) {
|
|||||||
}
|
}
|
||||||
foreach ($rows as $row) {
|
foreach ($rows as $row) {
|
||||||
// verify password
|
// verify password
|
||||||
if (verify_hash($row['password'], $pass) !== false) {
|
if ($app_passwd_data['eas'] !== true && $app_passwd_data['dav'] !== true){
|
||||||
// check for tfa authenticators
|
if (verify_hash($row['password'], $pass) !== false) {
|
||||||
$authenticators = get_tfa($user);
|
// check for tfa authenticators
|
||||||
if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0) {
|
$authenticators = get_tfa($user);
|
||||||
$_SESSION['pending_mailcow_cc_username'] = $user;
|
if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0) {
|
||||||
$_SESSION['pending_mailcow_cc_role'] = "user";
|
$_SESSION['pending_mailcow_cc_username'] = $user;
|
||||||
$_SESSION['pending_tfa_methods'] = $authenticators['additional'];
|
$_SESSION['pending_mailcow_cc_role'] = "user";
|
||||||
unset($_SESSION['ldelay']);
|
$_SESSION['pending_tfa_methods'] = $authenticators['additional'];
|
||||||
$_SESSION['return'][] = array(
|
unset($_SESSION['ldelay']);
|
||||||
'type' => 'success',
|
$_SESSION['return'][] = array(
|
||||||
'log' => array(__FUNCTION__, $user, '*'),
|
'type' => 'success',
|
||||||
'msg' => array('logged_in_as', $user)
|
'log' => array(__FUNCTION__, $user, '*'),
|
||||||
);
|
'msg' => array('logged_in_as', $user)
|
||||||
return "pending";
|
);
|
||||||
} else {
|
return "pending";
|
||||||
if ($app_passwd_data['eas'] === true || $app_passwd_data['dav'] === true) {
|
} else {
|
||||||
|
// 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));
|
||||||
|
|
||||||
|
unset($_SESSION['ldelay']);
|
||||||
|
return "user";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elseif ($app_passwd_data['eas'] === true || $app_passwd_data['dav'] === true) {
|
||||||
|
if (array_key_exists("app_passwd_id", $row)){
|
||||||
|
if (verify_hash($row['password'], $pass) !== false) {
|
||||||
$service = ($app_passwd_data['eas'] === true) ? 'EAS' : 'DAV';
|
$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 = $pdo->prepare("REPLACE INTO sasl_log (`service`, `app_password`, `username`, `real_rip`) VALUES (:service, :app_id, :username, :remote_addr)");
|
||||||
$stmt->execute(array(
|
$stmt->execute(array(
|
||||||
@ -961,13 +972,10 @@ function check_login($user, $pass, $app_passwd_data = false) {
|
|||||||
':username' => $user,
|
':username' => $user,
|
||||||
':remote_addr' => ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'])
|
':remote_addr' => ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'])
|
||||||
));
|
));
|
||||||
}
|
|
||||||
|
|
||||||
unset($_SESSION['ldelay']);
|
unset($_SESSION['ldelay']);
|
||||||
// Reactivate TFA if it was set to "deactivate TFA for next login"
|
return "user";
|
||||||
$stmt = $pdo->prepare("UPDATE `tfa` SET `active`='1' WHERE `username` = :user");
|
}
|
||||||
$stmt->execute(array(':user' => $user));
|
|
||||||
return "user";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1626,12 +1634,8 @@ function verify_tfa_login($username, $_data) {
|
|||||||
global $WebAuthn;
|
global $WebAuthn;
|
||||||
|
|
||||||
if ($_data['tfa_method'] != 'u2f'){
|
if ($_data['tfa_method'] != 'u2f'){
|
||||||
$stmt = $pdo->prepare("SELECT `authmech` FROM `tfa`
|
|
||||||
WHERE `username` = :username AND `id` = :id AND `active` = '1'");
|
|
||||||
$stmt->execute(array(':username' => $username, ':id' => $_data['id']));
|
|
||||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
switch ($row["authmech"]) {
|
switch ($_data["tfa_method"]) {
|
||||||
case "yubi_otp":
|
case "yubi_otp":
|
||||||
if (!ctype_alnum($_data['token']) || strlen($_data['token']) != 44) {
|
if (!ctype_alnum($_data['token']) || strlen($_data['token']) != 44) {
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
@ -1645,10 +1649,9 @@ function verify_tfa_login($username, $_data) {
|
|||||||
$stmt = $pdo->prepare("SELECT `id`, `secret` FROM `tfa`
|
$stmt = $pdo->prepare("SELECT `id`, `secret` FROM `tfa`
|
||||||
WHERE `username` = :username
|
WHERE `username` = :username
|
||||||
AND `authmech` = 'yubi_otp'
|
AND `authmech` = 'yubi_otp'
|
||||||
AND `id` = :id
|
|
||||||
AND `active` = '1'
|
AND `active` = '1'
|
||||||
AND `secret` LIKE :modhex");
|
AND `secret` LIKE :modhex");
|
||||||
$stmt->execute(array(':username' => $username, ':modhex' => '%' . $yubico_modhex_id, ':id' => $_data['id']));
|
$stmt->execute(array(':username' => $username, ':modhex' => '%' . $yubico_modhex_id));
|
||||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
$yubico_auth = explode(':', $row['secret']);
|
$yubico_auth = explode(':', $row['secret']);
|
||||||
$yubi = new Auth_Yubico($yubico_auth[0], $yubico_auth[1]);
|
$yubi = new Auth_Yubico($yubico_auth[0], $yubico_auth[1]);
|
||||||
|
@ -182,30 +182,19 @@ function recursiveBase64StrToArrayBuffer(obj) {
|
|||||||
keyboard: false
|
keyboard: false
|
||||||
});
|
});
|
||||||
|
|
||||||
// validate Yubi OTP tfa
|
|
||||||
$("#pending_tfa_tab_yubi_otp").click(function(){
|
|
||||||
$(".totp-authenticator-selection").removeClass("active");
|
|
||||||
$(".webauthn-authenticator-selection").removeClass("active");
|
|
||||||
|
|
||||||
$("#collapseTotpTFA").collapse('hide');
|
|
||||||
$("#collapseWebAuthnTFA").collapse('hide');
|
|
||||||
});
|
|
||||||
$(".yubi-authenticator-selection").click(function(){
|
|
||||||
$(".yubi-authenticator-selection").removeClass("active");
|
|
||||||
$(this).addClass("active");
|
|
||||||
|
|
||||||
var id = $(this).children('input').first().val();
|
|
||||||
$("#yubi_selected_id").val(id);
|
|
||||||
|
|
||||||
$("#collapseYubiTFA").collapse('show');
|
|
||||||
});
|
|
||||||
// validate Time based OTP tfa
|
// validate Time based OTP tfa
|
||||||
$("#pending_tfa_tab_totp").click(function(){
|
$("#pending_tfa_tab_totp").click(function(){
|
||||||
$(".yubi-authenticator-selection").removeClass("active");
|
|
||||||
$(".webauthn-authenticator-selection").removeClass("active");
|
$(".webauthn-authenticator-selection").removeClass("active");
|
||||||
|
|
||||||
$("#collapseYubiTFA").collapse('hide');
|
|
||||||
$("#collapseWebAuthnTFA").collapse('hide');
|
$("#collapseWebAuthnTFA").collapse('hide');
|
||||||
|
|
||||||
|
// select default if only one authenticator exists
|
||||||
|
if ($('.totp-authenticator-selection').length == 1){
|
||||||
|
$('.totp-authenticator-selection').addClass("active");
|
||||||
|
var id = $('.totp-authenticator-selection').children('input').first().val();
|
||||||
|
$("#totp_selected_id").val(id);
|
||||||
|
$("#collapseTotpTFA").collapse('show');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
$(".totp-authenticator-selection").click(function(){
|
$(".totp-authenticator-selection").click(function(){
|
||||||
$(".totp-authenticator-selection").removeClass("active");
|
$(".totp-authenticator-selection").removeClass("active");
|
||||||
@ -216,13 +205,37 @@ function recursiveBase64StrToArrayBuffer(obj) {
|
|||||||
|
|
||||||
$("#collapseTotpTFA").collapse('show');
|
$("#collapseTotpTFA").collapse('show');
|
||||||
});
|
});
|
||||||
|
if ($('.totp-authenticator-selection').length == 1 &&
|
||||||
|
$('#pending_tfa_tab_yubi_otp').length == 0 &&
|
||||||
|
$('.webauthn-authenticator-selection').length == 0){
|
||||||
|
|
||||||
|
// select default if only one authenticator exists
|
||||||
|
$('.totp-authenticator-selection').addClass("active");
|
||||||
|
|
||||||
|
var id = $('.totp-authenticator-selection').children('input').first().val();
|
||||||
|
$("#totp_selected_id").val(id);
|
||||||
|
|
||||||
|
$("#collapseTotpTFA").collapse('show');
|
||||||
|
setTimeout(function() { $("#collapseTotpTFA").find('input[name="token"]').focus(); }, 1000);
|
||||||
|
}
|
||||||
|
$('#pending_tfa_tab_totp').on('shown.bs.tab', function() {
|
||||||
|
// autofocus
|
||||||
|
setTimeout(function() { $("#collapseTotpTFA").find('input[name="token"]').focus(); }, 200);
|
||||||
|
});
|
||||||
|
// validate Yubi OTP tfa
|
||||||
|
if ($('.webauthn-authenticator-selection').length == 0){
|
||||||
|
// autofocus
|
||||||
|
setTimeout(function() { $("#collapseYubiTFA").find('input[name="token"]').focus(); }, 1000);
|
||||||
|
}
|
||||||
|
$('#pending_tfa_tab_yubi_otp').on('shown.bs.tab', function() {
|
||||||
|
// autofocus
|
||||||
|
$("#collapseYubiTFA").find('input[name="token"]').focus();
|
||||||
|
});
|
||||||
// validate WebAuthn tfa
|
// validate WebAuthn tfa
|
||||||
$("#pending_tfa_tab_webauthn").click(function(){
|
$("#pending_tfa_tab_webauthn").click(function(){
|
||||||
$(".totp-authenticator-selection").removeClass("active");
|
$(".totp-authenticator-selection").removeClass("active");
|
||||||
$(".yubi-authenticator-selection").removeClass("active");
|
|
||||||
|
|
||||||
$("#collapseTotpTFA").collapse('hide');
|
$("#collapseTotpTFA").collapse('hide');
|
||||||
$("#collapseYubiTFA").collapse('hide');
|
|
||||||
});
|
});
|
||||||
$(".webauthn-authenticator-selection").click(function(){
|
$(".webauthn-authenticator-selection").click(function(){
|
||||||
$(".webauthn-authenticator-selection").removeClass("active");
|
$(".webauthn-authenticator-selection").removeClass("active");
|
||||||
|
@ -206,20 +206,9 @@
|
|||||||
<form role="form" method="post">
|
<form role="form" method="post">
|
||||||
<legend>
|
<legend>
|
||||||
<i class="bi bi-shield-fill-check"></i>
|
<i class="bi bi-shield-fill-check"></i>
|
||||||
Authenticators
|
Authenticate
|
||||||
</legend>
|
</legend>
|
||||||
<div class="list-group">
|
<div class="collapse in pending-tfa-collapse" id="collapseYubiTFA">
|
||||||
{% for authenticator in pending_tfa_methods %}
|
|
||||||
{% if authenticator["authmech"] == "yubi_otp" %}
|
|
||||||
<a href="#" class="list-group-item yubi-authenticator-selection">
|
|
||||||
<i class="bi bi-key-fill" style="margin-right: 5px"></i>
|
|
||||||
<span>{{ authenticator["key_id"] }}</span>
|
|
||||||
<input type="hidden" value="{{ authenticator["id"] }}" />
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
<div class="collapse pending-tfa-collapse" id="collapseYubiTFA">
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<span class="input-group-addon" id="yubi-addon"><img alt="Yubicon Icon" src="/img/yubi.ico"></span>
|
<span class="input-group-addon" id="yubi-addon"><img alt="Yubicon Icon" src="/img/yubi.ico"></span>
|
||||||
|
Loading…
Reference in New Issue
Block a user