From 0698743fde1352b625238250fc63dcbb42d03ab2 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Thu, 25 Jan 2024 16:38:10 +0100 Subject: [PATCH] Xnamespace: assign incoming clients to namespaces The association is done by matching client's and namespace's authentication token. Signed-off-by: Enrico Weigelt, metux IT consult --- Xext/namespace/hook-clientstate.c | 45 +++++++++++++++++++++++++++++++ Xext/namespace/hooks.h | 29 ++++++++++++++++++++ Xext/namespace/meson.build | 1 + Xext/namespace/namespace.c | 22 +++++++++++++-- Xext/namespace/namespace.h | 4 +++ 5 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 Xext/namespace/hook-clientstate.c create mode 100644 Xext/namespace/hooks.h diff --git a/Xext/namespace/hook-clientstate.c b/Xext/namespace/hook-clientstate.c new file mode 100644 index 000000000..ead262dba --- /dev/null +++ b/Xext/namespace/hook-clientstate.c @@ -0,0 +1,45 @@ +#define HOOK_NAME "clienstate" + +#include + +#include "dix/registry_priv.h" +#include "os/client_priv.h" +#include "os/auth.h" + +#include "namespace.h" +#include "hooks.h" + +void hookClientState(CallbackListPtr *pcbl, void *unused, void *calldata) +{ + XNS_HOOK_HEAD(NewClientInfoRec); + + switch (client->clientState) { + case ClientStateInitial: + // better assign *someting* than null -- clients can't do anything yet anyways + XnamespaceAssignClient(subj, &ns_anon); + break; + + case ClientStateRunning: + subj->authId = AuthorizationIDOfClient(client); + + short unsigned int name_len = 0, data_len = 0; + const char * name = NULL; + char * data = NULL; + if (AuthorizationFromID(subj->authId, &name_len, &name, &data_len, &data)) { + XnamespaceAssignClient(subj, XnsFindByAuth(name_len, name, data_len, data)); + } else { + XNS_HOOK_LOG("no auth data - assuming anon\n"); + } + break; + + case ClientStateRetained: + XnamespaceAssignClient(subj, NULL); + break; + case ClientStateGone: + XnamespaceAssignClient(subj, NULL); + break; + default: + XNS_HOOK_LOG("unknown state =%d\n", client->clientState); + break; + } +} diff --git a/Xext/namespace/hooks.h b/Xext/namespace/hooks.h new file mode 100644 index 000000000..3043ec93f --- /dev/null +++ b/Xext/namespace/hooks.h @@ -0,0 +1,29 @@ +#ifndef __XSERVER_NAMESPACE_HOOKS_H +#define __XSERVER_NAMESPACE_HOOKS_H + +#include "dix/registry_priv.h" +#include "include/misc.h" + +#include "namespace.h" + +#define XNS_HOOK_LOG(...) do { \ + printf("XNS [" HOOK_NAME "] (#%d@%d) {%s} <%s>: ", \ + (client ? client->index : -1), \ + (client ? client->sequence : -1), \ + (subj ? (subj->ns ? subj->ns->name : "(no ns)") : ""), \ + LookupRequestName(client ? client->majorOp : 0, \ + client ? client->minorOp : 0)); \ + printf(__VA_ARGS__); \ + } while (0) + +#define XNS_HOOK_HEAD(t) \ + t *param = calldata; \ + ClientPtr client = param->client; \ + if (!client) { \ + /* XNS_LOG("hook %s NULL client\n", HOOK_NAME); */ \ + } \ + struct XnamespaceClientPriv *subj = XnsClientPriv(client); + +void hookClientState(CallbackListPtr *pcbl, void *unused, void *calldata); + +#endif /* __XSERVER_NAMESPACE_HOOKS_H */ diff --git a/Xext/namespace/meson.build b/Xext/namespace/meson.build index 78dd9f1cb..d6a693bb8 100644 --- a/Xext/namespace/meson.build +++ b/Xext/namespace/meson.build @@ -2,6 +2,7 @@ libxserver_namespace = static_library( 'libxserver_namespace', [ 'config.c', + 'hook-clientstate.c', 'namespace.c', ], include_directories: inc, diff --git a/Xext/namespace/namespace.c b/Xext/namespace/namespace.c index 26e81df07..845c2e585 100644 --- a/Xext/namespace/namespace.c +++ b/Xext/namespace/namespace.c @@ -8,6 +8,7 @@ #include "miext/extinit_priv.h" #include "namespace.h" +#include "hooks.h" Bool noNamespaceExtension = TRUE; @@ -24,8 +25,9 @@ NamespaceExtensionInit(void) return; } - if (!dixRegisterPrivateKey - (&namespaceClientPrivKeyRec, PRIVATE_CLIENT, sizeof(struct XnamespaceClientPriv))) + if (!(dixRegisterPrivateKey(&namespaceClientPrivKeyRec, PRIVATE_CLIENT, + sizeof(struct XnamespaceClientPriv)) && + AddCallback(&ClientStateCallback, hookClientState, NULL))) FatalError("NamespaceExtensionInit: allocation failure\n"); /* Do the serverClient */ @@ -54,3 +56,19 @@ void XnamespaceAssignClientByName(struct XnamespaceClientPriv *priv, const char XnamespaceAssignClient(priv, newns); } + +struct Xnamespace* XnsFindByAuth(size_t szAuthProto, const char* authProto, size_t szAuthToken, const char* authToken) +{ + struct Xnamespace *walk; + xorg_list_for_each_entry(walk, &ns_list, entry) { + int protoLen = walk->authProto ? strlen(walk->authProto) : 0; + if ((protoLen == szAuthProto) && + (walk->authTokenLen == szAuthToken) && + (memcmp(walk->authTokenData, authToken, szAuthToken)==0) && + (memcmp(walk->authProto, authProto, szAuthProto)==0)) + return walk; + } + + // default to anonymous if credentials aren't assigned to specific NS + return &ns_anon; +} diff --git a/Xext/namespace/namespace.h b/Xext/namespace/namespace.h index 93549eb31..acabe1060 100644 --- a/Xext/namespace/namespace.h +++ b/Xext/namespace/namespace.h @@ -14,6 +14,9 @@ struct Xnamespace { const char *name; Bool builtin; Bool superPower; + const char *authProto; + char *authTokenData; + size_t authTokenLen; size_t refcnt; }; @@ -34,6 +37,7 @@ extern DevPrivateKeyRec namespaceClientPrivKeyRec; Bool XnsLoadConfig(void); struct Xnamespace *XnsFindByName(const char* name); +struct Xnamespace* XnsFindByAuth(size_t szAuthProto, const char* authProto, size_t szAuthToken, const char* authToken); void XnamespaceAssignClient(struct XnamespaceClientPriv *priv, struct Xnamespace *ns); void XnamespaceAssignClientByName(struct XnamespaceClientPriv *priv, const char *name);