Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 83 additions & 22 deletions Xext/namespace/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,20 @@
#include "namespace.h"

struct Xnamespace ns_root = {
.allowMouseMotion = TRUE,
.allowShape = TRUE,
.allowTransparency = TRUE,
.allowXInput = TRUE,
.allowXKeyboard = TRUE,
.perms = {
.allowComposite = TRUE,
.allowGlobalKeyboard = TRUE,
.allowMouseMotion = TRUE,
.allowRandr = TRUE,
.allowRender = TRUE,
.allowShape = TRUE,
.allowScreen = TRUE,
.allowTransparency = TRUE,
.allowXInput = TRUE,
.allowXKeyboard = TRUE,
},
.builtin = TRUE,
.isRoot = TRUE,
.name = NS_NAME_ROOT,
.refcnt = 1,
.superPower = TRUE,
Expand All @@ -25,9 +33,14 @@ struct Xnamespace ns_anon = {
.refcnt = 1,
};

struct Xnamespace *ns_default;

struct xorg_list ns_list = { 0 };

struct xorg_list client_list = { 0 };

char *namespaceConfigFile = NULL;
static const char *default_namespace;

static struct Xnamespace* select_ns(const char* name)
{
Expand All @@ -47,7 +60,7 @@ static struct Xnamespace* select_ns(const char* name)
'a' <= c && c <= 'f' ? c - 'a' + 10 : \
'A' <= c && c <= 'F' ? c - 'A' + 10 : -1)

// warning: no error checking, no buffer clearing
/* warning: no error checking, no buffer clearing */
static int hex2bin(const char *in, char *out)
{
while (in[0] && in[1]) {
Expand All @@ -70,7 +83,7 @@ static int hex2bin(const char *in, char *out)
*/
static void parseLine(char *line, struct Xnamespace **walk_ns)
{
// trim newline and comments
/* trim newline and comments */
char *c1 = strchr(line, '\n');
if (c1 != NULL)
*c1 = 0;
Expand All @@ -84,6 +97,17 @@ static void parseLine(char *line, struct Xnamespace **walk_ns)
if (token == NULL)
return;

if (strcmp(token, "default") == 0)
{
if ((token = strtok(NULL, " ")) == NULL)
{
XNS_LOG("none given, default DENY\n");
return;
}
default_namespace = strdup(token);
return;
}

/* if no "namespace" statement hasn't been issued yet, use root NS */
struct Xnamespace * curr = (*walk_ns ? *walk_ns : &ns_root);

Expand All @@ -97,6 +121,8 @@ static void parseLine(char *line, struct Xnamespace **walk_ns)
}

curr = *walk_ns = select_ns(token);
/* anything made from the config should be retained, this flag will serve dual purpose */
curr->builtin = TRUE;
return;
}

Expand All @@ -106,6 +132,11 @@ static void parseLine(char *line, struct Xnamespace **walk_ns)
if (token == NULL)
return;

if (strcmp(token, "generate") == 0) {
GenerateAuthForXnamespace(curr);
return;
}

struct auth_token *new_token = calloc(1, sizeof(struct auth_token));
if (new_token == NULL)
FatalError("Xnamespace: failed allocating token\n");
Expand All @@ -131,20 +162,31 @@ static void parseLine(char *line, struct Xnamespace **walk_ns)
return;
}


if (strcmp(token, "allow") == 0)
{
while ((token = strtok(NULL, " ")) != NULL)
{
if (strcmp(token, "mouse-motion") == 0)
curr->allowMouseMotion = TRUE;
curr->perms.allowMouseMotion = TRUE;
else if (strcmp(token, "shape") == 0)
curr->allowShape = TRUE;
curr->perms.allowShape = TRUE;
else if (strcmp(token, "transparency") == 0)
curr->allowTransparency = TRUE;
curr->perms.allowTransparency = TRUE;
else if (strcmp(token, "xinput") == 0)
curr->allowXInput = TRUE;
curr->perms.allowXInput = TRUE;
else if (strcmp(token, "xkeyboard") == 0)
curr->allowXKeyboard = TRUE;
curr->perms.allowXKeyboard = TRUE;
else if (strcmp(token, "globalxkeyboard") == 0)
curr->perms.allowGlobalKeyboard = TRUE;
else if (strcmp(token, "render") == 0)
curr->perms.allowRender = TRUE;
else if (strcmp(token, "randr") == 0)
curr->perms.allowRandr = TRUE;
else if (strcmp(token, "screen") == 0)
curr->perms.allowScreen = TRUE;
else if (strcmp(token, "composite") == 0)
curr->perms.allowComposite = TRUE;
else
XNS_LOG("unknown allow: %s\n", token);
}
Expand All @@ -156,12 +198,25 @@ static void parseLine(char *line, struct Xnamespace **walk_ns)
curr->superPower = TRUE;
return;
}

if (strcmp(token, "client") == 0)
{
while ((token = strtok(NULL, " ")) != NULL) {
struct client_token *new_token = calloc(1, sizeof(struct client_token));
new_token->clientName = strdup(token);
new_token->Designation = curr;
xorg_list_append_ndup(&new_token->entry, &client_list);
XNS_LOG("client %s added for %s\n",new_token->clientName,curr->name);
}
}
XNS_LOG("unknown token \"%s\"\n", token);
}

Bool XnsLoadConfig(void)
{
/* default to anon namespace */
default_namespace = "anon";
ns_default = &ns_anon;

xorg_list_append_ndup(&ns_root.entry, &ns_list);
xorg_list_append_ndup(&ns_anon.entry, &ns_list);

Expand Down Expand Up @@ -197,14 +252,20 @@ Bool XnsLoadConfig(void)
}
}

return TRUE;
}

struct Xnamespace *XnsFindByName(const char* name) {
struct Xnamespace *walk;
xorg_list_for_each_entry(walk, &ns_list, entry) {
if (strcmp(walk->name, name)==0)
return walk;
if (strcmp(default_namespace, "new_ns") == 0) {
XNS_LOG("Defaulting to NEW Namespace per client\n");
ns_default->builtin = FALSE;
} else if (strcmp(default_namespace, "deny") == 0) {
XNS_LOG("Defaulting to DENY connection\n");
ns_default->deny = TRUE;
} else if (strcmp(default_namespace, "anon") == 0) {
XNS_LOG("Defaulting to anon connection\n");
} else if (XnsFindByName(default_namespace)) {
XNS_LOG("found default ns %s\n",default_namespace);
ns_default = XnsFindByName(default_namespace);
} else {
XNS_LOG("Incorrect Default, Defaulting to anon\n");
}
return NULL;

return TRUE;
}
75 changes: 67 additions & 8 deletions Xext/namespace/hook-clientstate.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#define HOOK_NAME "clienstate"

#include <dix-config.h>
#include <libgen.h>

#include "dix/registry_priv.h"
#include "os/client_priv.h"
Expand All @@ -14,24 +15,69 @@ 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);
case ClientStateInitial: {
/* nothing can happen in this state. auth cookie can't be loaded from env yet */
subj->pid = GetClientPid(client);
break;
}
case ClientStateRunning: {
/* just get actual name instead of path or command flags */
const char *clientName = strtok(basename((char*)GetClientCmdName(client)), " ");

XNS_LOG("pid: %d\n",GetClientPid(client));

case ClientStateRunning:
subj->authId = AuthorizationIDOfClient(client);
/* only change if uninitialized from client name walk (0) */
if (subj->authId==0 && XnamespaceAssignByClientName(subj,clientName)==0) {
XnsRegisterPid(subj);
return;
}

/* check env (XAUTHORITY) */
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");
} /* midpoint - we're not in the client lists nor do we have auth from env */
else if(XnsAssignByPid(subj)==0) {
/* processes can connect multiple times, keep them together */
return;
}
break;
else if (ns_default->deny) {
XNS_LOG("Deny Connection Request From %s\n",clientName);
client->noClientException = -1;
return;
}
else if (!ns_default->builtin) {
/* builtin flag should only be unset if the config is set as new_ns
* "fancy" formatted name
*/
int len = snprintf(NULL, 0, "%s%d", clientName, client->index);
char *str = malloc(len + 1);
snprintf(str, len+1, "%s%d", clientName, client->index);

struct Xnamespace *new_run_ns = GenerateNewXnamespaceForClient(&ns_anon, str);
free(str);
if (new_run_ns!=NULL) {
subj->authId = GenerateAuthForXnamespace(new_run_ns);
XnamespaceAssignClient(subj, new_run_ns);}
else {
XNS_LOG("Failed to assign new namespace, assigning to anon\n");
XnamespaceAssignClient(subj,&ns_anon);
}
}
/* authId should ONLY be 0 at this point if it's truly unauthorized */
if (subj->authId!=0) {
XnsRegisterPid(subj);
return;
}
XNS_HOOK_LOG("No Auth, Assigning to default %s\n",ns_default->name);
/* if we end up here, there is no auth - dump to the default */
XnamespaceAssignClient(subj,ns_default);
XnsRegisterPid(subj);
break;
}
case ClientStateRetained:
break;
case ClientStateGone:
Expand All @@ -49,7 +95,20 @@ void hookClientDestroy(CallbackListPtr *pcbl, void *unused, void *calldata)

if (!subj)
return; /* no XNS devprivate assigned ? */

XnsRemovePid(subj);
if(subj->ns->builtin==0) {
if (subj->ns->refcnt==1) {
/* this was the last client in the (new by default) namespace */
subj->ns->refcnt--;
/* Delete function checks for 0 client references */
if (DeleteXnamespace(subj->ns)!=0)
XNS_LOG("Failed to delete namespace\n");
subj->ns = NULL;
return;
} else {
/* don't delete, clients are still connected */
}
}
XnamespaceAssignClient(subj, NULL);
/* the devprivate is embedded, so no free() necessary */
}
55 changes: 45 additions & 10 deletions Xext/namespace/hook-device.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,68 @@ void hookDevice(CallbackListPtr *pcbl, void *unused, void *calldata)
if (subj->ns->superPower)
goto pass;

// should be safe to pass for anybody
/* should be safe to pass for anybody */
switch (client->majorOp) {
case X_QueryPointer:
if (subj->ns->perms.allowMouseMotion)
goto pass;
goto block;
case X_QueryKeymap:
if (subj->ns->perms.allowGlobalKeyboard)
goto pass;
goto block;
case X_GetInputFocus:
case X_GetKeyboardMapping:
case X_GetModifierMapping:
case X_GrabButton: // needed by xterm -- should be safe
case X_GrabButton: /* needed by xterm -- should be safe */
goto pass;
case EXTENSION_MAJOR_XKEYBOARD:
if (subj->ns->perms.allowXKeyboard)
goto pass;
switch(client->minorOp) {
case X_kbSelectEvents: // needed by xterm
case X_kbGetMap: // needed by xterm
case X_kbBell: // needed by GIMP
case X_kbPerClientFlags: // needed by firefox
case X_kbGetState: // needed by firefox
case X_kbGetNames: // needed by firefox
case X_kbGetControls: // needed by firefox
case X_kbSelectEvents: /* needed by xterm */
case X_kbGetMap: /* needed by xterm */
case X_kbBell: /* needed by GIMP */
case X_kbPerClientFlags: /* needed by firefox */
case X_kbGetState: /* needed by firefox */
case X_kbGetNames: /* needed by firefox */
case X_kbGetControls: /* needed by firefox */
goto pass;
default:
XNS_HOOK_LOG("BLOCKED unhandled XKEYBOARD %s\n", LookupRequestName(client->majorOp, client->minorOp));
goto block;
}

case X_GrabPointer:
case X_GetPointerMapping:
case X_SetInputFocus:
case X_WarpPointer:
if (subj->ns->perms.allowXInput)
goto pass;
goto block;
case X_GrabKeyboard:
case X_UngrabKeyboard:
if (subj->ns->perms.allowXKeyboard)
goto pass;
goto block;

case EXTENSION_MAJOR_XINPUT:
switch (client->minorOp) {
case X_ListInputDevices:
case X_XIQueryDevice:
case X_XIGetProperty:
goto pass;
case X_XIQueryPointer:
if (subj->ns->perms.allowMouseMotion)
goto pass;
goto block;

case X_XIQueryDevice:
case X_XIChangeCursor:
case X_XIGrabDevice:
case X_XIUngrabDevice:
if (subj->ns->perms.allowXInput)
goto pass;
goto block;
default:
XNS_HOOK_LOG("BLOCKED unhandled Xinput request\n");
goto block;
Expand Down
Loading
Loading