permissions: add permission management for keyboards (#10367)

This commit is contained in:
Vaxry 2025-05-18 18:13:20 +01:00 committed by GitHub
parent 44cb8f769e
commit 158c0f2911
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 48 additions and 12 deletions

View File

@ -2900,6 +2900,8 @@ std::optional<std::string> CConfigManager::handlePermission(const std::string& c
type = PERMISSION_TYPE_SCREENCOPY; type = PERMISSION_TYPE_SCREENCOPY;
else if (data[1] == "plugin") else if (data[1] == "plugin")
type = PERMISSION_TYPE_PLUGIN; type = PERMISSION_TYPE_PLUGIN;
else if (data[1] == "keyboard" || data[1] == "keeb")
type = PERMISSION_TYPE_KEYBOARD;
if (data[2] == "ask") if (data[2] == "ask")
mode = PERMISSION_RULE_ALLOW_MODE_ASK; mode = PERMISSION_RULE_ALLOW_MODE_ASK;

View File

@ -78,6 +78,9 @@ class IKeyboard : public IHID {
bool m_enabled = true; bool m_enabled = true;
bool m_allowBinds = 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, // if the keymap is overridden by the implementation,
// don't try to set keyboard rules anymore, to avoid overwriting the requested one. // don't try to set keyboard rules anymore, to avoid overwriting the requested one.
// e.g. Virtual keyboards with custom maps. // e.g. Virtual keyboards with custom maps.

View File

@ -36,6 +36,7 @@
#include "../../managers/HookSystemManager.hpp" #include "../../managers/HookSystemManager.hpp"
#include "../../managers/EventManager.hpp" #include "../../managers/EventManager.hpp"
#include "../../managers/LayoutManager.hpp" #include "../../managers/LayoutManager.hpp"
#include "../../managers/permissions/DynamicPermissionManager.hpp"
#include "../../helpers/time/Time.hpp" #include "../../helpers/time/Time.hpp"
@ -1054,6 +1055,27 @@ void CInputManager::applyConfigToKeyboard(SP<IKeyboard> pKeyboard) {
pKeyboard->m_resolveBindsBySym = RESOLVEBINDSBYSYM; pKeyboard->m_resolveBindsBySym = RESOLVEBINDSBYSYM;
pKeyboard->m_allowBinds = ALLOWBINDS; 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<IKeyboard>{pKeyboard}](SP<CPromiseResult<eDynamicPermissionAllowMode>> 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 { try {
if (NUMLOCKON == pKeyboard->m_numlockOn && REPEATDELAY == pKeyboard->m_repeatDelay && REPEATRATE == pKeyboard->m_repeatRate && RULES != "" && 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 && RULES == pKeyboard->m_currentRules.rules && MODEL == pKeyboard->m_currentRules.model && LAYOUT == pKeyboard->m_currentRules.layout &&
@ -1382,7 +1404,7 @@ void CInputManager::updateKeyboardsLeds(SP<IKeyboard> pKeyboard) {
} }
void CInputManager::onKeyboardKey(std::any event, SP<IKeyboard> pKeyboard) { void CInputManager::onKeyboardKey(std::any event, SP<IKeyboard> pKeyboard) {
if (!pKeyboard->m_enabled) if (!pKeyboard->m_enabled || !pKeyboard->m_allowed)
return; return;
const bool DISALLOWACTION = pKeyboard->isVirtual() && shouldIgnoreVirtualKeyboard(pKeyboard); const bool DISALLOWACTION = pKeyboard->isVirtual() && shouldIgnoreVirtualKeyboard(pKeyboard);

View File

@ -52,6 +52,7 @@ static const char* permissionToString(eDynamicPermissionType type) {
case PERMISSION_TYPE_UNKNOWN: return "PERMISSION_TYPE_UNKNOWN"; case PERMISSION_TYPE_UNKNOWN: return "PERMISSION_TYPE_UNKNOWN";
case PERMISSION_TYPE_SCREENCOPY: return "PERMISSION_TYPE_SCREENCOPY"; case PERMISSION_TYPE_SCREENCOPY: return "PERMISSION_TYPE_SCREENCOPY";
case PERMISSION_TYPE_PLUGIN: return "PERMISSION_TYPE_PLUGIN"; case PERMISSION_TYPE_PLUGIN: return "PERMISSION_TYPE_PLUGIN";
case PERMISSION_TYPE_KEYBOARD: return "PERMISSION_TYPE_KEYBOARD";
} }
return "error"; return "error";
@ -59,9 +60,10 @@ static const char* permissionToString(eDynamicPermissionType type) {
static const char* permissionToHumanString(eDynamicPermissionType type) { static const char* permissionToHumanString(eDynamicPermissionType type) {
switch (type) { switch (type) {
case PERMISSION_TYPE_UNKNOWN: return "requesting an unknown permission"; case PERMISSION_TYPE_UNKNOWN: return "An application <b>{}</b> is requesting an unknown permission.";
case PERMISSION_TYPE_SCREENCOPY: return "trying to capture your screen"; case PERMISSION_TYPE_SCREENCOPY: return "An application <b>{}</b> is trying to capture your screen.<br/><br/>Do you want to allow it to do so?";
case PERMISSION_TYPE_PLUGIN: return "trying to load a plugin"; case PERMISSION_TYPE_PLUGIN: return "An application <b>{}</b> is trying to load a plugin: <b>{}</b>.<br/><br/>Do you want to load it?";
case PERMISSION_TYPE_KEYBOARD: return "A new keyboard has been plugged in: {}.<br/><br/>Do you want to allow it to operate?";
} }
return "error"; return "error";
@ -184,7 +186,7 @@ eDynamicPermissionAllowMode CDynamicPermissionManager::clientPermissionMode(wl_c
return PERMISSION_RULE_ALLOW_MODE_PENDING; 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); askForPermission(client, LOOKUP.value_or(""), permission);
return PERMISSION_RULE_ALLOW_MODE_PENDING; return PERMISSION_RULE_ALLOW_MODE_PENDING;
@ -232,6 +234,10 @@ eDynamicPermissionAllowMode CDynamicPermissionManager::clientPermissionModeWithS
} else if ((*it)->m_allowMode == PERMISSION_RULE_ALLOW_MODE_PENDING) { } else if ((*it)->m_allowMode == PERMISSION_RULE_ALLOW_MODE_PENDING) {
Debug::log(TRACE, "CDynamicPermissionManager::clientHasPermission: permission pending by config rule"); Debug::log(TRACE, "CDynamicPermissionManager::clientHasPermission: permission pending by config rule");
return PERMISSION_RULE_ALLOW_MODE_PENDING; 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 } else
Debug::log(TRACE, "CDynamicPermissionManager::clientHasPermission: permission ask by config rule"); Debug::log(TRACE, "CDynamicPermissionManager::clientHasPermission: permission ask by config rule");
} }
@ -247,6 +253,10 @@ eDynamicPermissionAllowMode CDynamicPermissionManager::clientPermissionModeWithS
return PERMISSION_RULE_ALLOW_MODE_PENDING; 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. // if we are here, we need to ask.
askForPermission(nullptr, str, permission, pid); askForPermission(nullptr, str, permission, pid);
@ -263,22 +273,20 @@ void CDynamicPermissionManager::askForPermission(wl_client* client, const std::s
std::string description = ""; std::string description = "";
if (binaryPath.empty()) 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) { else if (client) {
std::string binaryName = binaryPath.contains("/") ? binaryPath.substr(binaryPath.find_last_of('/') + 1) : binaryPath; std::string binaryName = binaryPath.contains("/") ? binaryPath.substr(binaryPath.find_last_of('/') + 1) : binaryPath;
description = std::format("An application <b>{}</b> ({}) is {}.", binaryName, binaryPath, permissionToHumanString(type)); description = std::format(std::runtime_format(permissionToHumanString(type)), std::format("{}</b> ({})", binaryName, binaryPath));
} else if (pid >= 0) { } else if (pid >= 0) {
if (type == PERMISSION_TYPE_PLUGIN) { if (type == PERMISSION_TYPE_PLUGIN) {
const auto LOOKUP = binaryNameForPid(pid); const auto LOOKUP = binaryNameForPid(pid);
description = std::format("An application <b>{}</b> is {}:<br/><b>{}</b>", LOOKUP.value_or("Unknown"), permissionToHumanString(type), binaryPath); description = std::format(std::runtime_format(permissionToHumanString(type)), LOOKUP.value_or("Unknown"), binaryPath);
} else { } else {
const auto LOOKUP = binaryNameForPid(pid); const auto LOOKUP = binaryNameForPid(pid);
description = std::format("An application <b>{}</b> ({}) is {}.", LOOKUP.value_or("Unknown"), binaryPath, permissionToHumanString(type)); description = std::format(std::runtime_format(permissionToHumanString(type)), LOOKUP.value_or("Unknown"), binaryPath);
} }
} else } else
description = std::format("An application is {}:<br/><b>{}</b>", permissionToHumanString(type), binaryPath); description = std::format(std::runtime_format(permissionToHumanString(type)), binaryPath);
description += "<br/><br/>Do you want to allow this?";
std::vector<std::string> options; std::vector<std::string> options;

View File

@ -17,6 +17,7 @@ enum eDynamicPermissionType : uint8_t {
PERMISSION_TYPE_UNKNOWN = 0, PERMISSION_TYPE_UNKNOWN = 0,
PERMISSION_TYPE_SCREENCOPY, PERMISSION_TYPE_SCREENCOPY,
PERMISSION_TYPE_PLUGIN, PERMISSION_TYPE_PLUGIN,
PERMISSION_TYPE_KEYBOARD,
}; };
enum eDynamicPermissionRuleSource : uint8_t { enum eDynamicPermissionRuleSource : uint8_t {