diff options
Diffstat (limited to 'sway/ipc-server.c')
-rw-r--r-- | sway/ipc-server.c | 50 |
1 files changed, 47 insertions, 3 deletions
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index dfe88ed6..20a19b44 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -35,6 +35,7 @@ struct ipc_client { struct wlc_event_source *event_source; int fd; uint32_t payload_length; + uint32_t security_policy; enum ipc_command_type current_command; enum ipc_command_type subscribed_events; }; @@ -125,7 +126,6 @@ struct sockaddr_un *ipc_user_sockaddr(void) { return ipc_sockaddr; } -/* static pid_t get_client_pid(int client_fd) { // FreeBSD supports getting uid/gid, but not pid #ifdef __linux__ @@ -141,7 +141,6 @@ static pid_t get_client_pid(int client_fd) { return -1; #endif } -*/ int ipc_handle_connection(int fd, uint32_t mask, void *data) { (void) fd; (void) data; @@ -172,6 +171,9 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { client->subscribed_events = 0; client->event_source = wlc_event_loop_add_fd(client_fd, WLC_EVENT_READABLE, ipc_client_handle_readable, client); + pid_t pid = get_client_pid(client->fd); + client->security_policy = get_ipc_policy(pid); + list_add(ipc_client_list, client); return 0; @@ -342,6 +344,9 @@ void ipc_client_handle_command(struct ipc_client *client) { switch (client->current_command) { case IPC_COMMAND: { + if (!(client->security_policy & IPC_FEATURE_COMMAND)) { + goto exit_denied; + } struct cmd_results *results = handle_command(buf, CONTEXT_IPC); const char *json = cmd_results_to_json(results); char reply[256]; @@ -353,6 +358,7 @@ void ipc_client_handle_command(struct ipc_client *client) { case IPC_SUBSCRIBE: { + // TODO: Check if they're permitted to use these events struct json_object *request = json_tokener_parse(buf); if (request == NULL) { ipc_send_reply(client, "{\"success\": false}", 18); @@ -391,6 +397,9 @@ void ipc_client_handle_command(struct ipc_client *client) { case IPC_GET_WORKSPACES: { + if (!(client->security_policy & IPC_FEATURE_GET_TREE)) { + goto exit_denied; + } json_object *workspaces = json_object_new_array(); container_map(&root_container, ipc_get_workspaces_callback, workspaces); const char *json_string = json_object_to_json_string(workspaces); @@ -401,6 +410,9 @@ void ipc_client_handle_command(struct ipc_client *client) { case IPC_GET_INPUTS: { + if (!(client->security_policy & IPC_FEATURE_GET_TREE)) { + goto exit_denied; + } json_object *inputs = json_object_new_array(); if (input_devices) { for(int i=0; i<input_devices->length; i++) { @@ -424,6 +436,9 @@ void ipc_client_handle_command(struct ipc_client *client) { case IPC_GET_OUTPUTS: { + if (!(client->security_policy & IPC_FEATURE_GET_TREE)) { + goto exit_denied; + } json_object *outputs = json_object_new_array(); container_map(&root_container, ipc_get_outputs_callback, outputs); const char *json_string = json_object_to_json_string(outputs); @@ -434,6 +449,9 @@ void ipc_client_handle_command(struct ipc_client *client) { case IPC_GET_TREE: { + if (!(client->security_policy & IPC_FEATURE_GET_TREE)) { + goto exit_denied; + } json_object *tree = ipc_json_describe_container_recursive(&root_container); const char *json_string = json_object_to_json_string(tree); ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); @@ -498,6 +516,9 @@ void ipc_client_handle_command(struct ipc_client *client) { case IPC_GET_BAR_CONFIG: { + if (!(client->security_policy & IPC_FEATURE_GET_BAR_CONFIG)) { + goto exit_denied; + } if (!buf[0]) { // Send list of configured bar IDs json_object *bars = json_object_new_array(); @@ -538,7 +559,7 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_cleanup; } -//exit_denied: +exit_denied: ipc_send_reply(client, error_denied, (uint32_t)strlen(error_denied)); exit_cleanup: @@ -589,10 +610,33 @@ void ipc_get_outputs_callback(swayc_t *container, void *data) { } void ipc_send_event(const char *json_string, enum ipc_command_type event) { + static struct { + enum ipc_command_type event; + enum ipc_feature feature; + } security_mappings[] = { + { IPC_EVENT_WORKSPACE, IPC_FEATURE_EVENT_WORKSPACE }, + { IPC_EVENT_OUTPUT, IPC_FEATURE_EVENT_OUTPUT }, + { IPC_EVENT_MODE, IPC_FEATURE_EVENT_MODE }, + { IPC_EVENT_WINDOW, IPC_FEATURE_EVENT_WINDOW }, + { IPC_EVENT_BINDING, IPC_FEATURE_EVENT_BINDING }, + { IPC_EVENT_INPUT, IPC_FEATURE_EVENT_INPUT } + }; + + uint32_t security_mask = 0; + for (size_t i = 0; i < sizeof(security_mappings) / sizeof(security_mappings[0]); ++i) { + if (security_mappings[i].event == event) { + security_mask = security_mappings[i].feature; + break; + } + } + int i; struct ipc_client *client; for (i = 0; i < ipc_client_list->length; i++) { client = ipc_client_list->items[i]; + if (!(client->security_policy & security_mask)) { + continue; + } if ((client->subscribed_events & event_mask(event)) == 0) { continue; } |