|  | @@ -1250,6 +1250,7 @@ function set_tfa($_data) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  function fido2($_data) {
 | 
	
		
			
				|  |  |    global $pdo;
 | 
	
		
			
				|  |  | +  global $WebAuthn;
 | 
	
		
			
				|  |  |    $_data_log = $_data;
 | 
	
		
			
				|  |  |    // Not logging registration data, only actions
 | 
	
		
			
				|  |  |    // Silent errors for "get" requests
 | 
	
	
		
			
				|  | @@ -1383,6 +1384,81 @@ function fido2($_data) {
 | 
	
		
			
				|  |  |          'msg' => array('object_modified', htmlspecialchars($username))
 | 
	
		
			
				|  |  |        );
 | 
	
		
			
				|  |  |      break;
 | 
	
		
			
				|  |  | +    case "verify":
 | 
	
		
			
				|  |  | +      $tokenData = json_decode($_data['token']);
 | 
	
		
			
				|  |  | +      $clientDataJSON = base64_decode($tokenData->clientDataJSON);
 | 
	
		
			
				|  |  | +      $authenticatorData = base64_decode($tokenData->authenticatorData);
 | 
	
		
			
				|  |  | +      $signature = base64_decode($tokenData->signature);
 | 
	
		
			
				|  |  | +      $id = base64_decode($tokenData->id);
 | 
	
		
			
				|  |  | +      $challenge = $_SESSION['challenge'];
 | 
	
		
			
				|  |  | +      $process_fido2 = fido2(array("action" => "get_by_b64cid", "cid" => $tokenData->id));
 | 
	
		
			
				|  |  | +      if ($process_fido2['pub_key'] === false) {
 | 
	
		
			
				|  |  | +        $_SESSION['return'][] =  array(
 | 
	
		
			
				|  |  | +          'type' => 'danger',
 | 
	
		
			
				|  |  | +          'log' => array("fido2_login", $_data['user'], $process_fido2['username']),
 | 
	
		
			
				|  |  | +          'msg' => "login_failed"
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        return false;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      try {
 | 
	
		
			
				|  |  | +        $WebAuthn->processGet($clientDataJSON, $authenticatorData, $signature, $process_fido2['pub_key'], $challenge, null, $GLOBALS['FIDO2_UV_FLAG_LOGIN'], $GLOBALS['FIDO2_USER_PRESENT_FLAG']);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      catch (Throwable $ex) {
 | 
	
		
			
				|  |  | +        unset($process_fido2);
 | 
	
		
			
				|  |  | +        $_SESSION['return'][] =  array(
 | 
	
		
			
				|  |  | +          'type' => 'danger',
 | 
	
		
			
				|  |  | +          'log' => array("fido2_login", $_data['user'], $process_fido2['username'], $ex->getMessage()),
 | 
	
		
			
				|  |  | +          'msg' => "login_failed"
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        return false;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      $return = new stdClass();
 | 
	
		
			
				|  |  | +      $return->success = true;
 | 
	
		
			
				|  |  | +      $stmt = $pdo->prepare("SELECT `superadmin` FROM `admin` WHERE `username` = :username");
 | 
	
		
			
				|  |  | +      $stmt->execute(array(':username' => $process_fido2['username']));
 | 
	
		
			
				|  |  | +      $obj_props = $stmt->fetch(PDO::FETCH_ASSOC);
 | 
	
		
			
				|  |  | +      if ($obj_props['superadmin'] === 1 && (!$_data['user'] || $_data['user'] == "admin")) {
 | 
	
		
			
				|  |  | +        $_SESSION["mailcow_cc_role"] = "admin";
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      elseif ($obj_props['superadmin'] === 0 && (!$_data['user'] || $_data['user'] == "domainadmin")) {
 | 
	
		
			
				|  |  | +        $_SESSION["mailcow_cc_role"] = "domainadmin";
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      elseif (!isset($obj_props['superadmin']) && (!$_data['user'] || $_data['user'] == "user")) {
 | 
	
		
			
				|  |  | +        $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :username");
 | 
	
		
			
				|  |  | +        $stmt->execute(array(':username' => $process_fido2['username']));
 | 
	
		
			
				|  |  | +        $row = $stmt->fetch(PDO::FETCH_ASSOC);
 | 
	
		
			
				|  |  | +        if ($row['username'] == $process_fido2['username']) {
 | 
	
		
			
				|  |  | +          $_SESSION["mailcow_cc_role"] = "user";
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      else {
 | 
	
		
			
				|  |  | +        $_SESSION['return'][] =  array(
 | 
	
		
			
				|  |  | +          'type' => 'danger',
 | 
	
		
			
				|  |  | +          'log' => array("fido2_login", $_data['user'], $process_fido2['username']),
 | 
	
		
			
				|  |  | +          'msg' => 'login_failed'
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        return false;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      if (empty($_SESSION["mailcow_cc_role"])) {
 | 
	
		
			
				|  |  | +        session_unset();
 | 
	
		
			
				|  |  | +        session_destroy();
 | 
	
		
			
				|  |  | +        $_SESSION['return'][] =  array(
 | 
	
		
			
				|  |  | +          'type' => 'danger',
 | 
	
		
			
				|  |  | +          'log' => array("fido2_login", $_data['user'], $process_fido2['username']),
 | 
	
		
			
				|  |  | +          'msg' => 'login_failed'
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        return false;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      $_SESSION["mailcow_cc_username"] = $process_fido2['username'];
 | 
	
		
			
				|  |  | +      $_SESSION["fido2_cid"] = $process_fido2['cid'];
 | 
	
		
			
				|  |  | +      unset($_SESSION["challenge"]);
 | 
	
		
			
				|  |  | +      $_SESSION['return'][] =  array(
 | 
	
		
			
				|  |  | +        'type' => 'success',
 | 
	
		
			
				|  |  | +        'log' => array("fido2_login", $_data['user'], $process_fido2['username']),
 | 
	
		
			
				|  |  | +        'msg' => array('logged_in_as', $process_fido2['username'])
 | 
	
		
			
				|  |  | +      );
 | 
	
		
			
				|  |  | +      return true;
 | 
	
		
			
				|  |  | +    break;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  function unset_tfa_key($_data) {
 |