From f790bae8dcb9bc84f87f3fad5ac751f5ceddf7b9 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Wed, 19 Mar 2025 10:50:56 +0100 Subject: [PATCH] Xnamespace: initial config loader This loads the configuration (simple text file) passed via command line. For now just supporting static configuration, that's loaded on server startup. Signed-off-by: Enrico Weigelt, metux IT consult --- Xext/namespace/config.c | 162 ++++++++++++++++++++++++++++++++- Xext/namespace/ns.conf.example | 13 +++ miext/extinit_priv.h | 2 + os/utils.c | 13 +++ 4 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 Xext/namespace/ns.conf.example diff --git a/Xext/namespace/config.c b/Xext/namespace/config.c index 741c5ed0a..8c450c553 100644 --- a/Xext/namespace/config.c +++ b/Xext/namespace/config.c @@ -3,6 +3,8 @@ #include #include +#include "os/auth.h" + #include "namespace.h" struct Xnamespace ns_root = { @@ -25,11 +27,165 @@ struct Xnamespace ns_anon = { struct xorg_list ns_list = { 0 }; +char *namespaceConfigFile = NULL; + +static struct Xnamespace* select_ns(const char* name) +{ + struct Xnamespace *walk; + xorg_list_for_each_entry(walk, &ns_list, entry) { + if (strcmp(walk->name, name)==0) + return walk; + } + + struct Xnamespace *newns = calloc(1, sizeof(struct Xnamespace)); + newns->name = strdup(name); + xorg_list_append(&newns->entry, &ns_list); + return newns; +} + +#define atox(c) ('0' <= c && c <= '9' ? c - '0' : \ + 'a' <= c && c <= 'f' ? c - 'a' + 10 : \ + 'A' <= c && c <= 'F' ? c - 'A' + 10 : -1) + +// warning: no error checking, no buffer clearing +static int hex2bin(const char *in, char *out) +{ + while (in[0] && in[1]) { + int top = atox(in[0]); + if (top == -1) + return 0; + int bottom = atox(in[1]); + if (bottom == -1) + return 0; + *out++ = (top << 4) | bottom; + in += 2; + } + return 1; +} + +/* + * loadConfig + * + * Load the container config +*/ +static void parseLine(char *line, struct Xnamespace **walk_ns) +{ + // trim newline and comments + char *c1 = strchr(line, '\n'); + if (c1 != NULL) + *c1 = 0; + c1 = strchr(line, '#'); + if (c1 != NULL) + *c1 = 0; + + /* get the first token */ + char *token = strtok(line, " "); + + if (token == NULL) + return; + + // if no "container" statement hasn't been issued yet, use root NS + struct Xnamespace * curr = (*walk_ns ? *walk_ns : &ns_root); + + if (strcmp(token, "container") == 0) + { + if ((token = strtok(NULL, " ")) == NULL) + { + XNS_LOG("container missing id\n"); + return; + } + + curr = *walk_ns = select_ns(token); + return; + } + + if (strcmp(token, "auth") == 0) + { + token = strtok(NULL, " "); + if (token == NULL) + return; + + curr->authProto = strdup(token); + token = strtok(NULL, " "); + + curr->authTokenLen = strlen(token)/2; + curr->authTokenData = calloc(1, curr->authTokenLen); + if (!curr->authTokenData) { + curr->authTokenLen = 0; + return; + } + hex2bin(token, curr->authTokenData); + + AddAuthorization(strlen(curr->authProto), + curr->authProto, + curr->authTokenLen, + curr->authTokenData); + return; + } + + if (strcmp(token, "allow") == 0) + { + while ((token = strtok(NULL, " ")) != NULL) + { + if (strcmp(token, "mouse-motion") == 0) + curr->allowMouseMotion = TRUE; + else if (strcmp(token, "shape") == 0) + curr->allowShape = TRUE; + else if (strcmp(token, "transparency") == 0) + curr->allowTransparency = TRUE; + else if (strcmp(token, "xinput") == 0) + curr->allowXInput = TRUE; + else if (strcmp(token, "xkeyboard") == 0) + curr->allowXKeyboard = TRUE; + else + XNS_LOG("unknown allow: %s\n", token); + } + return; + } + + if (strcmp(token, "superpower") == 0) + { + curr->superPower = TRUE; + return; + } + + XNS_LOG("unknown token \"%s\"\n", token); +} + Bool XnsLoadConfig(void) { - xorg_list_init(&ns_list); - xorg_list_add(&ns_root.entry, &ns_list); - xorg_list_add(&ns_anon.entry, &ns_list); + xorg_list_append_ndup(&ns_root.entry, &ns_list); + xorg_list_append_ndup(&ns_anon.entry, &ns_list); + + if (!namespaceConfigFile) { + XNS_LOG("no namespace config given - Xnamespace disabled\n"); + return FALSE; + } + + FILE *fp = fopen(namespaceConfigFile, "r"); + if (fp == NULL) { + FatalError("failed loading container config: %s\n", namespaceConfigFile); + return FALSE; + } + + struct Xnamespace *walk_ns = NULL; + char linebuf[1024]; + while (fgets(linebuf, sizeof(linebuf), fp) != NULL) + parseLine(linebuf, &walk_ns); + + fclose(fp); + + XNS_LOG("loaded namespace config file: %s\n", namespaceConfigFile); + + struct Xnamespace *ns; + xorg_list_for_each_entry(ns, &ns_list, entry) { + XNS_LOG("namespace: \"%s\" \"%s\" \"", + ns->name, + ns->authProto); + for (int i=0; iauthTokenLen; i++) + printf("%02X", (unsigned char)ns->authTokenData[i]); + printf("\"\n"); + } return TRUE; } diff --git a/Xext/namespace/ns.conf.example b/Xext/namespace/ns.conf.example new file mode 100644 index 000000000..28623832e --- /dev/null +++ b/Xext/namespace/ns.conf.example @@ -0,0 +1,13 @@ + +# auth + auth MIT-MAGIC-COOKIE-1 46f8e62b78e58962de0ceefc05ad90b0 + +# container +container xeyes root + auth MIT-MAGIC-COOKIE-1 46f8e62b78e58962de0ceefc05ad90b8 + allow mouse-motion + allow shape + allow xinput + +container xclock root + auth MIT-MAGIC-COOKIE-1 46f8e62b78e58962de0ceefc05ad90b7 diff --git a/miext/extinit_priv.h b/miext/extinit_priv.h index 10351807d..c892c0c6a 100644 --- a/miext/extinit_priv.h +++ b/miext/extinit_priv.h @@ -25,6 +25,8 @@ extern Bool noXFixesExtension; extern Bool noXFree86BigfontExtension; extern Bool noNamespaceExtension; +extern char *namespaceConfigFile; + void CompositeExtensionInit(void); void DamageExtensionInit(void); void DbeExtensionInit(void); diff --git a/os/utils.c b/os/utils.c index 4a6834350..a6714e8af 100644 --- a/os/utils.c +++ b/os/utils.c @@ -294,6 +294,9 @@ UseMsg(void) ErrorF("+iglx Allow creating indirect GLX contexts\n"); ErrorF("-iglx Prohibit creating indirect GLX contexts (default)\n"); ErrorF("-I ignore all remaining arguments\n"); +#ifdef CONFIG_NAMESPACE + ErrorF("-namespace Enable NAMESPACE extension with given config file\n"); +#endif /* CONFIG_NAMESPACE */ LockServerUseMsg(); ErrorF("-maxclients n set maximum number of clients (power of two)\n"); ErrorF("-nolisten string don't listen on protocol\n"); @@ -692,6 +695,16 @@ ProcessCommandLine(int argc, char *argv[]) UseMsg(); } } +#ifdef CONFIG_NAMESPACE + else if (strcmp(argv[i], "-namespace") == 0) { + if (++i < argc) { + namespaceConfigFile = argv[i]; + noNamespaceExtension = FALSE; + } + else + UseMsg(); + } +#endif #ifdef XINERAMA else if (strcmp(argv[i], "+xinerama") == 0) { noPanoramiXExtension = FALSE;