public
nobgit
read
NobMail
Based on mailcow: dockerized
Languages
Repository composition by tracked source files.
PHP
49%
JavaScript
35%
HTML
9%
CSS
4%
Shell
2%
Python
1%
Lua
0%
Perl
0%
Ruby
0%
SCSS
0%
Create file
Wiki Documentation
Clone
https://nobgit.com/orgs/nobgit/nobmail.git
ssh://[email protected]:2222/orgs/nobgit/nobmail.git
Commit
[Web] tfa extra debugging
b185f83f
data/web/inc/functions.inc.php | 94 +++++++++++++++++++++++++++++++++++++-----
1 file changed, 84 insertions(+), 10 deletions(-)
Diff
diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php
index 12efd60b..c58662fd 100644
--- a/data/web/inc/functions.inc.php
+++ b/data/web/inc/functions.inc.php
@@ -1626,12 +1626,28 @@ function verify_tfa_login($username, $_data) {
global $tfa;
global $WebAuthn;
+ // just for debugging
+ // remove later
+ $_SESSION['return'][] = array(
+ 'type' => 'info',
+ 'log' => array(__FUNCTION__, 'tfa_post_data_log'),
+ 'msg' => $_data
+ );
+
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);
+ // just for debugging
+ // remove later
+ $_SESSION['return'][] = array(
+ 'type' => 'info',
+ 'log' => array(__FUNCTION__, 'tfa_verify_authmech'),
+ 'msg' => $row
+ );
+
switch ($row["authmech"]) {
case "yubi_otp":
if (!ctype_alnum($_data['token']) || strlen($_data['token']) != 44) {
@@ -1718,6 +1734,7 @@ function verify_tfa_login($username, $_data) {
}
break;
case "webauthn":
+ // prepare authenticator data
$tokenData = json_decode($_data['token']);
$clientDataJSON = base64_decode($tokenData->clientDataJSON);
$authenticatorData = base64_decode($tokenData->authenticatorData);
@@ -1725,10 +1742,28 @@ function verify_tfa_login($username, $_data) {
$id = base64_decode($tokenData->id);
$challenge = $_SESSION['challenge'];
- $stmt = $pdo->prepare("SELECT `id`, `key_id`, `keyHandle`, `username`, `publicKey` FROM `tfa` WHERE `id` = :id");
+ // just for debugging
+ // remove later
+ $_SESSION['return'][] = array(
+ 'type' => 'info',
+ 'log' => array(__FUNCTION__, 'tfa_try_verify'),
+ 'msg' => 'try grab authenticator'
+ );
+
+ // fetch authenticator
+ $stmt = $pdo->prepare("SELECT `id`, `key_id`, `keyHandle`, `username`, `publicKey` FROM `tfa` WHERE `id` = :id AND `active`='1'");
$stmt->execute(array(':id' => $_data['id']));
$process_webauthn = $stmt->fetch(PDO::FETCH_ASSOC);
+ // just for debugging
+ // remove later
+ $_SESSION['return'][] = array(
+ 'type' => 'info',
+ 'log' => array(__FUNCTION__, 'tfa_authenticator_grabbed'),
+ 'msg' => 'grabbed authenticator from db'
+ );
+
+ // return err if no authenticator was found
if (empty($process_webauthn)){
$_SESSION['return'][] = array(
'type' => 'danger',
@@ -1738,6 +1773,7 @@ function verify_tfa_login($username, $_data) {
return false;
}
+ // return err if authenticator has no publicKey
if (empty($process_webauthn['publicKey']) || $process_webauthn['publicKey'] === false) {
$_SESSION['return'][] = array(
'type' => 'danger',
@@ -1746,6 +1782,8 @@ function verify_tfa_login($username, $_data) {
);
return false;
}
+
+ // try verify authenticator
try {
$WebAuthn->processGet($clientDataJSON, $authenticatorData, $signature, $process_webauthn['publicKey'], $challenge, null, $GLOBALS['WEBAUTHN_UV_FLAG_LOGIN'], $GLOBALS['WEBAUTHN_USER_PRESENT_FLAG']);
}
@@ -1758,26 +1796,54 @@ function verify_tfa_login($username, $_data) {
return false;
}
-
+ // just for debugging
+ // remove later
+ $_SESSION['return'][] = array(
+ 'type' => 'info',
+ 'log' => array(__FUNCTION__, 'tfa_progress'),
+ 'msg' => 'authenticator verified, check user role'
+ );
+
+ // if verified, check user role
$stmt = $pdo->prepare("SELECT `superadmin` FROM `admin` WHERE `username` = :username");
$stmt->execute(array(':username' => $process_webauthn['username']));
$obj_props = $stmt->fetch(PDO::FETCH_ASSOC);
if ($obj_props['superadmin'] === 1) {
- $_SESSION["mailcow_cc_role"] = "admin";
+ // is admin
+ $_SESSION["mailcow_cc_role"] = "admin";
}
elseif ($obj_props['superadmin'] === 0) {
- $_SESSION["mailcow_cc_role"] = "domainadmin";
+ // is domainadmin
+ $_SESSION["mailcow_cc_role"] = "domainadmin";
}
else {
- $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :username");
- $stmt->execute(array(':username' => $process_webauthn['username']));
- $row = $stmt->fetch(PDO::FETCH_ASSOC);
- if ($row['username'] == $process_webauthn['username']) {
+ // just for debugging
+ // remove later
+ $_SESSION['return'][] = array(
+ 'type' => 'info',
+ 'log' => array(__FUNCTION__, 'tfa_progress'),
+ 'msg' => 'no admin or domainadmin role, check if normal user'
+ );
+
+ // no admin, check if normal user
+ $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :username");
+ $stmt->execute(array(':username' => $process_webauthn['username']));
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+ if (!empty($row['username']) {
+ // is user
$_SESSION["mailcow_cc_role"] = "user";
- }
+ } else {
+ // err, no specific role found
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $username, '*'),
+ 'msg' => array('webauthn_verification_failed', 'could not determine user role')
+ );
+ return false;
+ }
}
-
+ // check if fetched user and pendig_user matches
if ($process_webauthn['username'] != $_SESSION['pending_mailcow_cc_username']){
$_SESSION['return'][] = array(
'type' => 'danger',
@@ -1787,7 +1853,15 @@ function verify_tfa_login($username, $_data) {
return false;
}
+ // just for debugging
+ // remove later
+ $_SESSION['return'][] = array(
+ 'type' => 'info',
+ 'log' => array(__FUNCTION__, 'tfa_success'),
+ 'msg' => 'tfa flow success'
+ );
+ // set user session data and delete WebAuthn challenge session
$_SESSION["mailcow_cc_username"] = $process_webauthn['username'];
$_SESSION['tfa_id'] = $process_webauthn['id'];
$_SESSION['authReq'] = null;