瀏覽代碼

[Web] Fix authentication when mailbox or domain is deactivated

FreddleSpl0it 5 月之前
父節點
當前提交
cb08132a74
共有 2 個文件被更改,包括 103 次插入12 次删除
  1. 50 6
      data/web/inc/functions.auth.inc.php
  2. 53 6
      data/web/inc/functions.inc.php

+ 50 - 6
data/web/inc/functions.auth.inc.php

@@ -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 ($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;
     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

+ 53 - 6
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']);
       $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 `domain`.`active`='1'
-          AND `username` = :user
-          AND (`authsource`='keycloak' OR `authsource`='generic-oidc')");
+          AND `username` = :user");
       $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;