diff --git a/data/web/inc/functions.auth.inc.php b/data/web/inc/functions.auth.inc.php index e047b83ba..7fd535be1 100644 --- a/data/web/inc/functions.auth.inc.php +++ b/data/web/inc/functions.auth.inc.php @@ -178,25 +178,40 @@ function user_login($user, $pass, $extra = null){ 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 WHERE `kind` NOT REGEXP 'location|thing|group' - AND `domain`.`active`='1' AND `username` = :user"); $stmt->execute(array(':user' => $user)); $row = $stmt->fetch(PDO::FETCH_ASSOC); // user does not exist, try call idp login and create user if possible via rest flow if (!$row){ + $result = false; 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)); - if ($result !== false) return $result; } else if ($iam_settings['authsource'] == 'ldap') { $result = ldap_mbox_login($user, $pass, array('is_internal' => $is_internal, 'create' => true)); - if ($result !== false) return $result; } - } - if ($row['active'] != 1) { + 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; + } + } + clear_session(); return false; } @@ -206,6 +221,19 @@ function user_login($user, $pass, $extra = null){ if (intval($iam_settings['mailpassword_flow']) == 1){ $result = keycloak_mbox_login_rest($user, $pass, array('is_internal' => $is_internal)); 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 $authenticators = get_tfa($user); 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 $result = ldap_mbox_login($user, $pass, array('is_internal' => $is_internal)); 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 $authenticators = get_tfa($user); 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; break; case 'mailcow': + if ($row['active'] != 1 || $row['d_active'] != 1) { + return false; + } // verify password if (verify_hash($row['password'], $pass) !== false) { // check for tfa authenticators diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index 187036b47..5b67dd1e4 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -2653,17 +2653,25 @@ function identity_provider($_action = null, $_data = null, $_extra = null) { $mapper_key = array_search($user_template, $iam_settings['mappers']); // 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 WHERE `kind` NOT REGEXP 'location|thing|group' - AND `mailbox`.`active`='1' - AND `domain`.`active`='1' - AND `username` = :user - AND (`authsource`='keycloak' OR `authsource`='generic-oidc')"); + AND `username` = :user"); $stmt->execute(array(':user' => $info['email'])); $row = $stmt->fetch(PDO::FETCH_ASSOC); 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) { // update user $_SESSION['access_all_exception'] = '1'; @@ -2673,6 +2681,26 @@ function identity_provider($_action = null, $_data = null, $_extra = null) { 'template' => $iam_settings['templates'][$mapper_key] )); $_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']); $_SESSION['iam_token'] = $plain_token; @@ -2715,6 +2743,25 @@ function identity_provider($_action = null, $_data = null, $_extra = null) { 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']); $_SESSION['iam_token'] = $plain_token; $_SESSION['iam_refresh_token'] = $plain_refreshtoken;