1
0
mirror of https://github.com/mailcow/mailcow-dockerized.git synced 2025-12-13 18:06:01 +00:00

[Web] Fix authentication when mailbox or domain is deactivated

This commit is contained in:
FreddleSpl0it
2025-03-13 14:39:03 +01:00
parent 2596b9d386
commit cb08132a74
2 changed files with 103 additions and 12 deletions

View File

@@ -178,25 +178,40 @@ function user_login($user, $pass, $extra = null){
return false; return false;
} }
$stmt = $pdo->prepare("SELECT * FROM `mailbox` $stmt = $pdo->prepare("SELECT
mailbox.*,
domain.active AS d_active
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 `domain`.`active`='1'
AND `username` = :user"); AND `username` = :user");
$stmt->execute(array(':user' => $user)); $stmt->execute(array(':user' => $user));
$row = $stmt->fetch(PDO::FETCH_ASSOC); $row = $stmt->fetch(PDO::FETCH_ASSOC);
// user does not exist, try call idp login and create user if possible via rest flow // user does not exist, try call idp login and create user if possible via rest flow
if (!$row){ if (!$row){
$result = false;
if ($iam_settings['authsource'] == 'keycloak' && intval($iam_settings['mailpassword_flow']) == 1){ if ($iam_settings['authsource'] == 'keycloak' && intval($iam_settings['mailpassword_flow']) == 1){
$result = keycloak_mbox_login_rest($user, $pass, array('is_internal' => $is_internal, 'create' => true)); $result = keycloak_mbox_login_rest($user, $pass, array('is_internal' => $is_internal, 'create' => true));
if ($result !== false) return $result;
} else if ($iam_settings['authsource'] == 'ldap') { } else if ($iam_settings['authsource'] == 'ldap') {
$result = ldap_mbox_login($user, $pass, array('is_internal' => $is_internal, 'create' => true)); $result = ldap_mbox_login($user, $pass, array('is_internal' => $is_internal, 'create' => true));
if ($result !== false) return $result; }
if ($result !== false){
// double check if mailbox is active
$stmt = $pdo->prepare("SELECT * FROM `mailbox`
INNER JOIN domain on mailbox.domain = domain.domain
WHERE `kind` NOT REGEXP 'location|thing|group'
AND `mailbox`.`active`='1'
AND `domain`.`active`='1'
AND `username` = :user");
$stmt->execute(array(':user' => $user));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (!empty($row)) {
return true;
} }
} }
if ($row['active'] != 1) { clear_session();
return false; return false;
} }
@@ -206,6 +221,19 @@ function user_login($user, $pass, $extra = null){
if (intval($iam_settings['mailpassword_flow']) == 1){ if (intval($iam_settings['mailpassword_flow']) == 1){
$result = keycloak_mbox_login_rest($user, $pass, array('is_internal' => $is_internal)); $result = keycloak_mbox_login_rest($user, $pass, array('is_internal' => $is_internal));
if ($result !== false) { if ($result !== false) {
// double check if mailbox and domain is active
$stmt = $pdo->prepare("SELECT * FROM `mailbox`
INNER JOIN domain on mailbox.domain = domain.domain
WHERE `kind` NOT REGEXP 'location|thing|group'
AND `mailbox`.`active`='1'
AND `domain`.`active`='1'
AND `username` = :user");
$stmt->execute(array(':user' => $user));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (empty($row)) {
return false;
}
// 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 && !$is_internal) { if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0 && !$is_internal) {
@@ -245,6 +273,19 @@ function user_login($user, $pass, $extra = null){
// user authsource is ldap // user authsource is ldap
$result = ldap_mbox_login($user, $pass, array('is_internal' => $is_internal)); $result = ldap_mbox_login($user, $pass, array('is_internal' => $is_internal));
if ($result !== false) { if ($result !== false) {
// double check if mailbox and domain is active
$stmt = $pdo->prepare("SELECT * FROM `mailbox`
INNER JOIN domain on mailbox.domain = domain.domain
WHERE `kind` NOT REGEXP 'location|thing|group'
AND `mailbox`.`active`='1'
AND `domain`.`active`='1'
AND `username` = :user");
$stmt->execute(array(':user' => $user));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (empty($row)) {
return false;
}
// 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 && !$is_internal) { if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0 && !$is_internal) {
@@ -278,6 +319,9 @@ function user_login($user, $pass, $extra = null){
return $result; return $result;
break; break;
case 'mailcow': case 'mailcow':
if ($row['active'] != 1 || $row['d_active'] != 1) {
return false;
}
// verify password // verify password
if (verify_hash($row['password'], $pass) !== false) { if (verify_hash($row['password'], $pass) !== false) {
// check for tfa authenticators // check for tfa authenticators

View File

@@ -2653,17 +2653,25 @@ function identity_provider($_action = null, $_data = null, $_extra = null) {
$mapper_key = array_search($user_template, $iam_settings['mappers']); $mapper_key = array_search($user_template, $iam_settings['mappers']);
// token valid, get mailbox // token valid, get mailbox
$stmt = $pdo->prepare("SELECT * FROM `mailbox` $stmt = $pdo->prepare("SELECT
mailbox.*,
domain.active AS d_active
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 `username` = :user");
AND `domain`.`active`='1'
AND `username` = :user
AND (`authsource`='keycloak' OR `authsource`='generic-oidc')");
$stmt->execute(array(':user' => $info['email'])); $stmt->execute(array(':user' => $info['email']));
$row = $stmt->fetch(PDO::FETCH_ASSOC); $row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row){ if ($row){
// success if (!in_array($row['authsource'], array("keycloak", "generic-oidc"))) {
clear_session();
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $info['email'], "The user's authentication source is not of type OIDC"),
'msg' => 'login_failed'
);
return false;
}
if ($mapper_key !== false) { if ($mapper_key !== false) {
// update user // update user
$_SESSION['access_all_exception'] = '1'; $_SESSION['access_all_exception'] = '1';
@@ -2673,6 +2681,26 @@ function identity_provider($_action = null, $_data = null, $_extra = null) {
'template' => $iam_settings['templates'][$mapper_key] 'template' => $iam_settings['templates'][$mapper_key]
)); ));
$_SESSION['access_all_exception'] = '0'; $_SESSION['access_all_exception'] = '0';
// get updated row
$stmt = $pdo->prepare("SELECT
mailbox.*,
domain.active AS d_active
FROM `mailbox`
INNER JOIN domain on mailbox.domain = domain.domain
WHERE `kind` NOT REGEXP 'location|thing|group'
AND `username` = :user");
$stmt->execute(array(':user' => $info['email']));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
}
if ($row['active'] != 1 || $row['d_active'] != 1) {
clear_session();
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $info['email'], 'Domain or mailbox is inactive'),
'msg' => 'login_failed'
);
return false;
} }
set_user_loggedin_session($info['email']); set_user_loggedin_session($info['email']);
$_SESSION['iam_token'] = $plain_token; $_SESSION['iam_token'] = $plain_token;
@@ -2715,6 +2743,25 @@ function identity_provider($_action = null, $_data = null, $_extra = null) {
return false; return false;
} }
// double check if mailbox and domain is active
$stmt = $pdo->prepare("SELECT * FROM `mailbox`
INNER JOIN domain on mailbox.domain = domain.domain
WHERE `kind` NOT REGEXP 'location|thing|group'
AND `mailbox`.`active`='1'
AND `domain`.`active`='1'
AND `username` = :user");
$stmt->execute(array(':user' => $info['email']));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (empty($row)) {
clear_session();
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $info['email'], 'Domain or mailbox is inactive'),
'msg' => 'login_failed'
);
return false;
}
set_user_loggedin_session($info['email']); set_user_loggedin_session($info['email']);
$_SESSION['iam_token'] = $plain_token; $_SESSION['iam_token'] = $plain_token;
$_SESSION['iam_refresh_token'] = $plain_refreshtoken; $_SESSION['iam_refresh_token'] = $plain_refreshtoken;