From 158c0f2911894f5f97af7361f639f97f6d100c82 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sun, 18 May 2025 18:13:20 +0100 Subject: [PATCH] permissions: add permission management for keyboards (#10367) --- src/config/ConfigManager.cpp | 2 ++ src/devices/IKeyboard.hpp | 3 ++ src/managers/input/InputManager.cpp | 24 ++++++++++++++- .../permissions/DynamicPermissionManager.cpp | 30 ++++++++++++------- .../permissions/DynamicPermissionManager.hpp | 1 + 5 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 564ebcda..f5f0bed3 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2900,6 +2900,8 @@ std::optional CConfigManager::handlePermission(const std::string& c type = PERMISSION_TYPE_SCREENCOPY; else if (data[1] == "plugin") type = PERMISSION_TYPE_PLUGIN; + else if (data[1] == "keyboard" || data[1] == "keeb") + type = PERMISSION_TYPE_KEYBOARD; if (data[2] == "ask") mode = PERMISSION_RULE_ALLOW_MODE_ASK; diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index 3d7b2dd1..c66aee27 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -78,6 +78,9 @@ class IKeyboard : public IHID { bool m_enabled = true; bool m_allowBinds = true; + // permission flag: whether this keyboard is allowed to be processed + bool m_allowed = true; + // if the keymap is overridden by the implementation, // don't try to set keyboard rules anymore, to avoid overwriting the requested one. // e.g. Virtual keyboards with custom maps. diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index cd603ca5..f9f36cf2 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -36,6 +36,7 @@ #include "../../managers/HookSystemManager.hpp" #include "../../managers/EventManager.hpp" #include "../../managers/LayoutManager.hpp" +#include "../../managers/permissions/DynamicPermissionManager.hpp" #include "../../helpers/time/Time.hpp" @@ -1054,6 +1055,27 @@ void CInputManager::applyConfigToKeyboard(SP pKeyboard) { pKeyboard->m_resolveBindsBySym = RESOLVEBINDSBYSYM; pKeyboard->m_allowBinds = ALLOWBINDS; + const auto PERM = g_pDynamicPermissionManager->clientPermissionModeWithString(-1, pKeyboard->m_hlName, PERMISSION_TYPE_KEYBOARD); + if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) { + const auto PROMISE = g_pDynamicPermissionManager->promiseFor(-1, pKeyboard->m_hlName, PERMISSION_TYPE_KEYBOARD); + if (!PROMISE) + Debug::log(ERR, "BUG THIS: No promise for client permission for keyboard"); + else { + PROMISE->then([k = WP{pKeyboard}](SP> r) { + if (r->hasError()) { + Debug::log(ERR, "BUG THIS: No permission returned for keyboard"); + return; + } + + if (!k) + return; + + k->m_allowed = r->result() == PERMISSION_RULE_ALLOW_MODE_ALLOW; + }); + } + } else + pKeyboard->m_allowed = PERM == PERMISSION_RULE_ALLOW_MODE_ALLOW; + try { if (NUMLOCKON == pKeyboard->m_numlockOn && REPEATDELAY == pKeyboard->m_repeatDelay && REPEATRATE == pKeyboard->m_repeatRate && RULES != "" && RULES == pKeyboard->m_currentRules.rules && MODEL == pKeyboard->m_currentRules.model && LAYOUT == pKeyboard->m_currentRules.layout && @@ -1382,7 +1404,7 @@ void CInputManager::updateKeyboardsLeds(SP pKeyboard) { } void CInputManager::onKeyboardKey(std::any event, SP pKeyboard) { - if (!pKeyboard->m_enabled) + if (!pKeyboard->m_enabled || !pKeyboard->m_allowed) return; const bool DISALLOWACTION = pKeyboard->isVirtual() && shouldIgnoreVirtualKeyboard(pKeyboard); diff --git a/src/managers/permissions/DynamicPermissionManager.cpp b/src/managers/permissions/DynamicPermissionManager.cpp index e111343e..dd1fd4cf 100644 --- a/src/managers/permissions/DynamicPermissionManager.cpp +++ b/src/managers/permissions/DynamicPermissionManager.cpp @@ -52,6 +52,7 @@ static const char* permissionToString(eDynamicPermissionType type) { case PERMISSION_TYPE_UNKNOWN: return "PERMISSION_TYPE_UNKNOWN"; case PERMISSION_TYPE_SCREENCOPY: return "PERMISSION_TYPE_SCREENCOPY"; case PERMISSION_TYPE_PLUGIN: return "PERMISSION_TYPE_PLUGIN"; + case PERMISSION_TYPE_KEYBOARD: return "PERMISSION_TYPE_KEYBOARD"; } return "error"; @@ -59,9 +60,10 @@ static const char* permissionToString(eDynamicPermissionType type) { static const char* permissionToHumanString(eDynamicPermissionType type) { switch (type) { - case PERMISSION_TYPE_UNKNOWN: return "requesting an unknown permission"; - case PERMISSION_TYPE_SCREENCOPY: return "trying to capture your screen"; - case PERMISSION_TYPE_PLUGIN: return "trying to load a plugin"; + case PERMISSION_TYPE_UNKNOWN: return "An application {} is requesting an unknown permission."; + case PERMISSION_TYPE_SCREENCOPY: return "An application {} is trying to capture your screen.

Do you want to allow it to do so?"; + case PERMISSION_TYPE_PLUGIN: return "An application {} is trying to load a plugin: {}.

Do you want to load it?"; + case PERMISSION_TYPE_KEYBOARD: return "A new keyboard has been plugged in: {}.

Do you want to allow it to operate?"; } return "error"; @@ -184,7 +186,7 @@ eDynamicPermissionAllowMode CDynamicPermissionManager::clientPermissionMode(wl_c return PERMISSION_RULE_ALLOW_MODE_PENDING; } - // if we are here, we need to ask. + // if we are here, we need to ask, that's the fallback for all these (keyboards wont come here) askForPermission(client, LOOKUP.value_or(""), permission); return PERMISSION_RULE_ALLOW_MODE_PENDING; @@ -232,6 +234,10 @@ eDynamicPermissionAllowMode CDynamicPermissionManager::clientPermissionModeWithS } else if ((*it)->m_allowMode == PERMISSION_RULE_ALLOW_MODE_PENDING) { Debug::log(TRACE, "CDynamicPermissionManager::clientHasPermission: permission pending by config rule"); return PERMISSION_RULE_ALLOW_MODE_PENDING; + } else if ((*it)->m_allowMode == PERMISSION_RULE_ALLOW_MODE_ASK) { + Debug::log(TRACE, "CDynamicPermissionManager::clientHasPermission: permission ask by config rule"); + askForPermission(nullptr, str, permission, pid); + return PERMISSION_RULE_ALLOW_MODE_PENDING; } else Debug::log(TRACE, "CDynamicPermissionManager::clientHasPermission: permission ask by config rule"); } @@ -247,6 +253,10 @@ eDynamicPermissionAllowMode CDynamicPermissionManager::clientPermissionModeWithS return PERMISSION_RULE_ALLOW_MODE_PENDING; } + // keyboards are allow default + if (permission == PERMISSION_TYPE_KEYBOARD) + return PERMISSION_RULE_ALLOW_MODE_ALLOW; + // if we are here, we need to ask. askForPermission(nullptr, str, permission, pid); @@ -263,22 +273,20 @@ void CDynamicPermissionManager::askForPermission(wl_client* client, const std::s std::string description = ""; if (binaryPath.empty()) - description = std::format("An unknown application (wayland client ID 0x{:x}) is {}.", (uintptr_t)client, permissionToHumanString(type)); + description = std::format(std::runtime_format(permissionToHumanString(type)), std::format("unknown application (wayland client ID 0x{:x})", (uintptr_t)client)); else if (client) { std::string binaryName = binaryPath.contains("/") ? binaryPath.substr(binaryPath.find_last_of('/') + 1) : binaryPath; - description = std::format("An application {} ({}) is {}.", binaryName, binaryPath, permissionToHumanString(type)); + description = std::format(std::runtime_format(permissionToHumanString(type)), std::format("{} ({})", binaryName, binaryPath)); } else if (pid >= 0) { if (type == PERMISSION_TYPE_PLUGIN) { const auto LOOKUP = binaryNameForPid(pid); - description = std::format("An application {} is {}:
{}", LOOKUP.value_or("Unknown"), permissionToHumanString(type), binaryPath); + description = std::format(std::runtime_format(permissionToHumanString(type)), LOOKUP.value_or("Unknown"), binaryPath); } else { const auto LOOKUP = binaryNameForPid(pid); - description = std::format("An application {} ({}) is {}.", LOOKUP.value_or("Unknown"), binaryPath, permissionToHumanString(type)); + description = std::format(std::runtime_format(permissionToHumanString(type)), LOOKUP.value_or("Unknown"), binaryPath); } } else - description = std::format("An application is {}:
{}", permissionToHumanString(type), binaryPath); - - description += "

Do you want to allow this?"; + description = std::format(std::runtime_format(permissionToHumanString(type)), binaryPath); std::vector options; diff --git a/src/managers/permissions/DynamicPermissionManager.hpp b/src/managers/permissions/DynamicPermissionManager.hpp index f8cfe3ad..a61f256e 100644 --- a/src/managers/permissions/DynamicPermissionManager.hpp +++ b/src/managers/permissions/DynamicPermissionManager.hpp @@ -17,6 +17,7 @@ enum eDynamicPermissionType : uint8_t { PERMISSION_TYPE_UNKNOWN = 0, PERMISSION_TYPE_SCREENCOPY, PERMISSION_TYPE_PLUGIN, + PERMISSION_TYPE_KEYBOARD, }; enum eDynamicPermissionRuleSource : uint8_t {