浏览代码

[Web] multiple tfa - user support

FreddleSpl0it 3 年之前
父节点
当前提交
49c506eed9
共有 4 个文件被更改,包括 60 次插入21 次删除
  1. 31 16
      data/web/inc/functions.inc.php
  2. 3 3
      data/web/inc/triggers.inc.php
  3. 25 2
      data/web/templates/user/tab-user-auth.twig
  4. 1 0
      data/web/user.php

+ 31 - 16
data/web/inc/functions.inc.php

@@ -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']);
-      $_SESSION['return'][] =  array(
-        'type' => 'success',
-        'log' => array(__FUNCTION__, $user, '*'),
-        'msg' => array('logged_in_as', $user)
-      );
-      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'])
-        ));
+      // check for tfa authenticators
+      $authenticators = get_tfa($user);
+      if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0) {
+        $_SESSION['pending_mailcow_cc_username'] = $user;
+        $_SESSION['pending_mailcow_cc_role'] = "user";
+        $_SESSION['pending_tfa_methods'] = $authenticators['additional'];
+        unset($_SESSION['ldelay']);
+        $_SESSION['return'][] =  array(
+          'type' => 'success',
+          'log' => array(__FUNCTION__, $user, '*'),
+          'msg' => array('logged_in_as', $user)
+        );
+        return "pending";
+      } 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";
     }
     }
   }
   }
 
 

+ 3 - 3
data/web/inc/triggers.inc.php

@@ -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_role']);
-        unset($_SESSION['pending_tfa_methods']);
+    unset($_SESSION['pending_mailcow_cc_username']);
+    unset($_SESSION['pending_mailcow_cc_role']);
+    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']);
 	}
 	}

+ 25 - 2
data/web/templates/user/tab-user-auth.twig

@@ -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>
-          <p><a href="#pwChangeModal" data-toggle="modal"><i class="bi bi-pencil-fill"></i> {{ lang.user.change_password }}</a></p>
+        </div>
+      </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>

+ 1 - 0
data/web/user.php

@@ -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,