diff options
author | 2017-02-20 06:30:25 -0500 | |
---|---|---|
committer | 2017-02-20 06:33:04 -0500 | |
commit | 1980a0835804b205da1fa00187640ae8a0c4f9be (patch) | |
tree | 7d79e173a654443f15bd33c0d7f81f3c1d889af7 /sway/ipc-server.c | |
parent | Add initial support code for new IPC security (diff) | |
download | sway-1980a0835804b205da1fa00187640ae8a0c4f9be.tar.gz sway-1980a0835804b205da1fa00187640ae8a0c4f9be.tar.zst sway-1980a0835804b205da1fa00187640ae8a0c4f9be.zip |
Enforce new IPC policies
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 { | |||
35 | struct wlc_event_source *event_source; | 35 | struct wlc_event_source *event_source; |
36 | int fd; | 36 | int fd; |
37 | uint32_t payload_length; | 37 | uint32_t payload_length; |
38 | uint32_t security_policy; | ||
38 | enum ipc_command_type current_command; | 39 | enum ipc_command_type current_command; |
39 | enum ipc_command_type subscribed_events; | 40 | enum ipc_command_type subscribed_events; |
40 | }; | 41 | }; |
@@ -125,7 +126,6 @@ struct sockaddr_un *ipc_user_sockaddr(void) { | |||
125 | return ipc_sockaddr; | 126 | return ipc_sockaddr; |
126 | } | 127 | } |
127 | 128 | ||
128 | /* | ||
129 | static pid_t get_client_pid(int client_fd) { | 129 | static pid_t get_client_pid(int client_fd) { |
130 | // FreeBSD supports getting uid/gid, but not pid | 130 | // FreeBSD supports getting uid/gid, but not pid |
131 | #ifdef __linux__ | 131 | #ifdef __linux__ |
@@ -141,7 +141,6 @@ static pid_t get_client_pid(int client_fd) { | |||
141 | return -1; | 141 | return -1; |
142 | #endif | 142 | #endif |
143 | } | 143 | } |
144 | */ | ||
145 | 144 | ||
146 | int ipc_handle_connection(int fd, uint32_t mask, void *data) { | 145 | int ipc_handle_connection(int fd, uint32_t mask, void *data) { |
147 | (void) fd; (void) data; | 146 | (void) fd; (void) data; |
@@ -172,6 +171,9 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { | |||
172 | client->subscribed_events = 0; | 171 | client->subscribed_events = 0; |
173 | client->event_source = wlc_event_loop_add_fd(client_fd, WLC_EVENT_READABLE, ipc_client_handle_readable, client); | 172 | client->event_source = wlc_event_loop_add_fd(client_fd, WLC_EVENT_READABLE, ipc_client_handle_readable, client); |
174 | 173 | ||
174 | pid_t pid = get_client_pid(client->fd); | ||
175 | client->security_policy = get_ipc_policy(pid); | ||
176 | |||
175 | list_add(ipc_client_list, client); | 177 | list_add(ipc_client_list, client); |
176 | 178 | ||
177 | return 0; | 179 | return 0; |
@@ -342,6 +344,9 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
342 | switch (client->current_command) { | 344 | switch (client->current_command) { |
343 | case IPC_COMMAND: | 345 | case IPC_COMMAND: |
344 | { | 346 | { |
347 | if (!(client->security_policy & IPC_FEATURE_COMMAND)) { | ||
348 | goto exit_denied; | ||
349 | } | ||
345 | struct cmd_results *results = handle_command(buf, CONTEXT_IPC); | 350 | struct cmd_results *results = handle_command(buf, CONTEXT_IPC); |
346 | const char *json = cmd_results_to_json(results); | 351 | const char *json = cmd_results_to_json(results); |
347 | char reply[256]; | 352 | char reply[256]; |
@@ -353,6 +358,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
353 | 358 | ||
354 | case IPC_SUBSCRIBE: | 359 | case IPC_SUBSCRIBE: |
355 | { | 360 | { |
361 | // TODO: Check if they're permitted to use these events | ||
356 | struct json_object *request = json_tokener_parse(buf); | 362 | struct json_object *request = json_tokener_parse(buf); |
357 | if (request == NULL) { | 363 | if (request == NULL) { |
358 | ipc_send_reply(client, "{\"success\": false}", 18); | 364 | ipc_send_reply(client, "{\"success\": false}", 18); |
@@ -391,6 +397,9 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
391 | 397 | ||
392 | case IPC_GET_WORKSPACES: | 398 | case IPC_GET_WORKSPACES: |
393 | { | 399 | { |
400 | if (!(client->security_policy & IPC_FEATURE_GET_TREE)) { | ||
401 | goto exit_denied; | ||
402 | } | ||
394 | json_object *workspaces = json_object_new_array(); | 403 | json_object *workspaces = json_object_new_array(); |
395 | container_map(&root_container, ipc_get_workspaces_callback, workspaces); | 404 | container_map(&root_container, ipc_get_workspaces_callback, workspaces); |
396 | const char *json_string = json_object_to_json_string(workspaces); | 405 | const char *json_string = json_object_to_json_string(workspaces); |
@@ -401,6 +410,9 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
401 | 410 | ||
402 | case IPC_GET_INPUTS: | 411 | case IPC_GET_INPUTS: |
403 | { | 412 | { |
413 | if (!(client->security_policy & IPC_FEATURE_GET_TREE)) { | ||
414 | goto exit_denied; | ||
415 | } | ||
404 | json_object *inputs = json_object_new_array(); | 416 | json_object *inputs = json_object_new_array(); |
405 | if (input_devices) { | 417 | if (input_devices) { |
406 | for(int i=0; i<input_devices->length; i++) { | 418 | for(int i=0; i<input_devices->length; i++) { |
@@ -424,6 +436,9 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
424 | 436 | ||
425 | case IPC_GET_OUTPUTS: | 437 | case IPC_GET_OUTPUTS: |
426 | { | 438 | { |
439 | if (!(client->security_policy & IPC_FEATURE_GET_TREE)) { | ||
440 | goto exit_denied; | ||
441 | } | ||
427 | json_object *outputs = json_object_new_array(); | 442 | json_object *outputs = json_object_new_array(); |
428 | container_map(&root_container, ipc_get_outputs_callback, outputs); | 443 | container_map(&root_container, ipc_get_outputs_callback, outputs); |
429 | const char *json_string = json_object_to_json_string(outputs); | 444 | const char *json_string = json_object_to_json_string(outputs); |
@@ -434,6 +449,9 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
434 | 449 | ||
435 | case IPC_GET_TREE: | 450 | case IPC_GET_TREE: |
436 | { | 451 | { |
452 | if (!(client->security_policy & IPC_FEATURE_GET_TREE)) { | ||
453 | goto exit_denied; | ||
454 | } | ||
437 | json_object *tree = ipc_json_describe_container_recursive(&root_container); | 455 | json_object *tree = ipc_json_describe_container_recursive(&root_container); |
438 | const char *json_string = json_object_to_json_string(tree); | 456 | const char *json_string = json_object_to_json_string(tree); |
439 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); | 457 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); |
@@ -498,6 +516,9 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
498 | 516 | ||
499 | case IPC_GET_BAR_CONFIG: | 517 | case IPC_GET_BAR_CONFIG: |
500 | { | 518 | { |
519 | if (!(client->security_policy & IPC_FEATURE_GET_BAR_CONFIG)) { | ||
520 | goto exit_denied; | ||
521 | } | ||
501 | if (!buf[0]) { | 522 | if (!buf[0]) { |
502 | // Send list of configured bar IDs | 523 | // Send list of configured bar IDs |
503 | json_object *bars = json_object_new_array(); | 524 | json_object *bars = json_object_new_array(); |
@@ -538,7 +559,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
538 | goto exit_cleanup; | 559 | goto exit_cleanup; |
539 | } | 560 | } |
540 | 561 | ||
541 | //exit_denied: | 562 | exit_denied: |
542 | ipc_send_reply(client, error_denied, (uint32_t)strlen(error_denied)); | 563 | ipc_send_reply(client, error_denied, (uint32_t)strlen(error_denied)); |
543 | 564 | ||
544 | exit_cleanup: | 565 | exit_cleanup: |
@@ -589,10 +610,33 @@ void ipc_get_outputs_callback(swayc_t *container, void *data) { | |||
589 | } | 610 | } |
590 | 611 | ||
591 | void ipc_send_event(const char *json_string, enum ipc_command_type event) { | 612 | void ipc_send_event(const char *json_string, enum ipc_command_type event) { |
613 | static struct { | ||
614 | enum ipc_command_type event; | ||
615 | enum ipc_feature feature; | ||
616 | } security_mappings[] = { | ||
617 | { IPC_EVENT_WORKSPACE, IPC_FEATURE_EVENT_WORKSPACE }, | ||
618 | { IPC_EVENT_OUTPUT, IPC_FEATURE_EVENT_OUTPUT }, | ||
619 | { IPC_EVENT_MODE, IPC_FEATURE_EVENT_MODE }, | ||
620 | { IPC_EVENT_WINDOW, IPC_FEATURE_EVENT_WINDOW }, | ||
621 | { IPC_EVENT_BINDING, IPC_FEATURE_EVENT_BINDING }, | ||
622 | { IPC_EVENT_INPUT, IPC_FEATURE_EVENT_INPUT } | ||
623 | }; | ||
624 | |||
625 | uint32_t security_mask = 0; | ||
626 | for (size_t i = 0; i < sizeof(security_mappings) / sizeof(security_mappings[0]); ++i) { | ||
627 | if (security_mappings[i].event == event) { | ||
628 | security_mask = security_mappings[i].feature; | ||
629 | break; | ||
630 | } | ||
631 | } | ||
632 | |||
592 | int i; | 633 | int i; |
593 | struct ipc_client *client; | 634 | struct ipc_client *client; |
594 | for (i = 0; i < ipc_client_list->length; i++) { | 635 | for (i = 0; i < ipc_client_list->length; i++) { |
595 | client = ipc_client_list->items[i]; | 636 | client = ipc_client_list->items[i]; |
637 | if (!(client->security_policy & security_mask)) { | ||
638 | continue; | ||
639 | } | ||
596 | if ((client->subscribed_events & event_mask(event)) == 0) { | 640 | if ((client->subscribed_events & event_mask(event)) == 0) { |
597 | continue; | 641 | continue; |
598 | } | 642 | } |