summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2016-12-02 17:34:26 -0500
committerLibravatar Drew DeVault <sir@cmpwn.com>2016-12-02 17:34:26 -0500
commitc8dc4925d1e0f5d5086a4c15415ee9fb0b7e6155 (patch)
treee4019d0e2408f00d054907c35202a6104c6bb272
parentAdd IPC policy to config (diff)
downloadsway-c8dc4925d1e0f5d5086a4c15415ee9fb0b7e6155.tar.gz
sway-c8dc4925d1e0f5d5086a4c15415ee9fb0b7e6155.tar.zst
sway-c8dc4925d1e0f5d5086a4c15415ee9fb0b7e6155.zip
Add IPC security policy command handlers
-rw-r--r--include/sway/commands.h5
-rw-r--r--sway/commands.c30
-rw-r--r--sway/commands/ipc.c140
-rw-r--r--sway/config.c26
4 files changed, 200 insertions, 1 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h
index 9e8d013e..3ab8d5af 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -120,6 +120,7 @@ sway_cmd cmd_gaps;
120sway_cmd cmd_hide_edge_borders; 120sway_cmd cmd_hide_edge_borders;
121sway_cmd cmd_include; 121sway_cmd cmd_include;
122sway_cmd cmd_input; 122sway_cmd cmd_input;
123sway_cmd cmd_ipc;
123sway_cmd cmd_kill; 124sway_cmd cmd_kill;
124sway_cmd cmd_layout; 125sway_cmd cmd_layout;
125sway_cmd cmd_log_colors; 126sway_cmd cmd_log_colors;
@@ -192,4 +193,8 @@ sway_cmd input_cmd_pointer_accel;
192sway_cmd input_cmd_scroll_method; 193sway_cmd input_cmd_scroll_method;
193sway_cmd input_cmd_tap; 194sway_cmd input_cmd_tap;
194 195
196sway_cmd cmd_ipc_cmd;
197sway_cmd cmd_ipc_events;
198sway_cmd cmd_ipc_event_cmd;
199
195#endif 200#endif
diff --git a/sway/commands.c b/sway/commands.c
index 5d5087b1..47f7533c 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -180,6 +180,7 @@ static struct cmd_handler handlers[] = {
180 { "hide_edge_borders", cmd_hide_edge_borders }, 180 { "hide_edge_borders", cmd_hide_edge_borders },
181 { "include", cmd_include }, 181 { "include", cmd_include },
182 { "input", cmd_input }, 182 { "input", cmd_input },
183 { "ipc", cmd_ipc },
183 { "kill", cmd_kill }, 184 { "kill", cmd_kill },
184 { "layout", cmd_layout }, 185 { "layout", cmd_layout },
185 { "log_colors", cmd_log_colors }, 186 { "log_colors", cmd_log_colors },
@@ -292,6 +293,26 @@ static struct cmd_handler bar_colors_handlers[] = {
292 { "urgent_workspace", bar_colors_cmd_urgent_workspace }, 293 { "urgent_workspace", bar_colors_cmd_urgent_workspace },
293}; 294};
294 295
296static struct cmd_handler ipc_handlers[] = {
297 { "bar-config", cmd_ipc_cmd },
298 { "command", cmd_ipc_cmd },
299 { "events", cmd_ipc_events },
300 { "inputs", cmd_ipc_cmd },
301 { "marks", cmd_ipc_cmd },
302 { "outputs", cmd_ipc_cmd },
303 { "tree", cmd_ipc_cmd },
304 { "workspaces", cmd_ipc_cmd },
305};
306
307static struct cmd_handler ipc_event_handlers[] = {
308 { "binding", cmd_ipc_event_cmd },
309 { "input", cmd_ipc_event_cmd },
310 { "mode", cmd_ipc_event_cmd },
311 { "output", cmd_ipc_event_cmd },
312 { "window", cmd_ipc_event_cmd },
313 { "workspace", cmd_ipc_event_cmd },
314};
315
295static int handler_compare(const void *_a, const void *_b) { 316static int handler_compare(const void *_a, const void *_b) {
296 const struct cmd_handler *a = _a; 317 const struct cmd_handler *a = _a;
297 const struct cmd_handler *b = _b; 318 const struct cmd_handler *b = _b;
@@ -311,10 +332,17 @@ static struct cmd_handler *find_handler(char *line, enum cmd_status block) {
311 sizeof(bar_colors_handlers) / sizeof(struct cmd_handler), 332 sizeof(bar_colors_handlers) / sizeof(struct cmd_handler),
312 sizeof(struct cmd_handler), handler_compare); 333 sizeof(struct cmd_handler), handler_compare);
313 } else if (block == CMD_BLOCK_INPUT) { 334 } else if (block == CMD_BLOCK_INPUT) {
314 sway_log(L_DEBUG, "looking at input handlers");
315 res = bsearch(&d, input_handlers, 335 res = bsearch(&d, input_handlers,
316 sizeof(input_handlers) / sizeof(struct cmd_handler), 336 sizeof(input_handlers) / sizeof(struct cmd_handler),
317 sizeof(struct cmd_handler), handler_compare); 337 sizeof(struct cmd_handler), handler_compare);
338 } else if (block == CMD_BLOCK_IPC) {
339 res = bsearch(&d, ipc_handlers,
340 sizeof(ipc_handlers) / sizeof(struct cmd_handler),
341 sizeof(struct cmd_handler), handler_compare);
342 } else if (block == CMD_BLOCK_IPC_EVENTS) {
343 res = bsearch(&d, ipc_event_handlers,
344 sizeof(ipc_event_handlers) / sizeof(struct cmd_handler),
345 sizeof(struct cmd_handler), handler_compare);
318 } else { 346 } else {
319 res = bsearch(&d, handlers, 347 res = bsearch(&d, handlers,
320 sizeof(handlers) / sizeof(struct cmd_handler), 348 sizeof(handlers) / sizeof(struct cmd_handler),
diff --git a/sway/commands/ipc.c b/sway/commands/ipc.c
new file mode 100644
index 00000000..e6ae27a4
--- /dev/null
+++ b/sway/commands/ipc.c
@@ -0,0 +1,140 @@
1#include <stdio.h>
2#include <string.h>
3#include "sway/commands.h"
4#include "sway/config.h"
5#include "ipc.h"
6#include "log.h"
7#include "util.h"
8
9struct cmd_results *cmd_ipc(int argc, char **argv) {
10 struct cmd_results *error = NULL;
11 if ((error = checkarg(argc, "ipc", EXPECTED_EQUAL_TO, 1))) {
12 return error;
13 }
14
15 if (config->reading && strcmp("{", argv[0]) != 0) {
16 return cmd_results_new(CMD_INVALID, "ipc",
17 "Expected '{' at start of IPC config definition.");
18 }
19
20 if (!config->reading) {
21 return cmd_results_new(CMD_FAILURE, "ipc", "Can only be used in config file.");
22 }
23
24 return cmd_results_new(CMD_BLOCK_IPC, NULL, NULL);
25}
26
27struct cmd_results *cmd_ipc_events(int argc, char **argv) {
28 struct cmd_results *error = NULL;
29 if ((error = checkarg(argc, "events", EXPECTED_EQUAL_TO, 1))) {
30 return error;
31 }
32
33 if (config->reading && strcmp("{", argv[0]) != 0) {
34 return cmd_results_new(CMD_INVALID, "events",
35 "Expected '{' at start of IPC event config definition.");
36 }
37
38 if (!config->reading) {
39 return cmd_results_new(CMD_FAILURE, "events", "Can only be used in config file.");
40 }
41
42 return cmd_results_new(CMD_BLOCK_IPC_EVENTS, NULL, NULL);
43}
44
45struct cmd_results *cmd_ipc_cmd(int argc, char **argv) {
46 struct cmd_results *error = NULL;
47 if ((error = checkarg(argc, "ipc", EXPECTED_EQUAL_TO, 1))) {
48 return error;
49 }
50
51 bool enabled;
52 if (strcmp(argv[0], "enabled") == 0) {
53 enabled = true;
54 } else if (strcmp(argv[0], "disabled") == 0) {
55 enabled = false;
56 } else {
57 return cmd_results_new(CMD_INVALID, argv[-1],
58 "Argument must be one of 'enabled' or 'disabled'");
59 }
60
61 struct {
62 char *name;
63 enum ipc_command_type type;
64 } types[] = {
65 { "command", IPC_COMMAND },
66 { "workspaces", IPC_GET_WORKSPACES },
67 { "outputs", IPC_GET_OUTPUTS },
68 { "tree", IPC_GET_TREE },
69 { "marks", IPC_GET_MARKS },
70 { "bar-config", IPC_GET_BAR_CONFIG },
71 { "inputs", IPC_GET_INPUTS },
72 };
73
74 uint32_t type = 0;
75
76 for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) {
77 if (strcmp(types[i].name, argv[-1]) == 0) {
78 type = types[i].type;
79 break;
80 }
81 }
82
83 if (enabled) {
84 config->ipc_policy |= type;
85 sway_log(L_DEBUG, "Enabled IPC %s feature", argv[-1]);
86 } else {
87 config->ipc_policy &= ~type;
88 sway_log(L_DEBUG, "Disabled IPC %s feature", argv[-1]);
89 }
90
91 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
92}
93
94struct cmd_results *cmd_ipc_event_cmd(int argc, char **argv) {
95 struct cmd_results *error = NULL;
96 if ((error = checkarg(argc, "ipc", EXPECTED_EQUAL_TO, 1))) {
97 return error;
98 }
99
100 bool enabled;
101 if (strcmp(argv[0], "enabled") == 0) {
102 enabled = true;
103 } else if (strcmp(argv[0], "disabled") == 0) {
104 enabled = false;
105 } else {
106 return cmd_results_new(CMD_INVALID, argv[-1],
107 "Argument must be one of 'enabled' or 'disabled'");
108 }
109
110 struct {
111 char *name;
112 enum ipc_command_type type;
113 } types[] = {
114 { "workspace", event_mask(IPC_EVENT_WORKSPACE) },
115 { "output", event_mask(IPC_EVENT_OUTPUT) },
116 { "mode", event_mask(IPC_EVENT_MODE) },
117 { "window", event_mask(IPC_EVENT_WINDOW) },
118 { "binding", event_mask(IPC_EVENT_BINDING) },
119 { "input", event_mask(IPC_EVENT_INPUT) },
120 };
121
122 uint32_t type = 0;
123
124 for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) {
125 if (strcmp(types[i].name, argv[-1]) == 0) {
126 type = types[i].type;
127 break;
128 }
129 }
130
131 if (enabled) {
132 config->ipc_policy |= type;
133 sway_log(L_DEBUG, "Enabled IPC %s event", argv[-1]);
134 } else {
135 config->ipc_policy &= ~type;
136 sway_log(L_DEBUG, "Disabled IPC %s event", argv[-1]);
137 }
138
139 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
140}
diff --git a/sway/config.c b/sway/config.c
index b1b0aac9..e737f83c 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -641,6 +641,22 @@ bool read_config(FILE *file, struct sway_config *config) {
641 } 641 }
642 break; 642 break;
643 643
644 case CMD_BLOCK_IPC:
645 if (block == CMD_BLOCK_END) {
646 block = CMD_BLOCK_IPC;
647 } else {
648 sway_log(L_ERROR, "Invalid block '%s'", line);
649 }
650 break;
651
652 case CMD_BLOCK_IPC_EVENTS:
653 if (block == CMD_BLOCK_IPC) {
654 block = CMD_BLOCK_IPC_EVENTS;
655 } else {
656 sway_log(L_ERROR, "Invalid block '%s'", line);
657 }
658 break;
659
644 case CMD_BLOCK_END: 660 case CMD_BLOCK_END:
645 switch(block) { 661 switch(block) {
646 case CMD_BLOCK_MODE: 662 case CMD_BLOCK_MODE:
@@ -671,6 +687,16 @@ bool read_config(FILE *file, struct sway_config *config) {
671 block = CMD_BLOCK_END; 687 block = CMD_BLOCK_END;
672 break; 688 break;
673 689
690 case CMD_BLOCK_IPC:
691 sway_log(L_DEBUG, "End of IPC block");
692 block = CMD_BLOCK_END;
693 break;
694
695 case CMD_BLOCK_IPC_EVENTS:
696 sway_log(L_DEBUG, "End of IPC events block");
697 block = CMD_BLOCK_IPC;
698 break;
699
674 case CMD_BLOCK_END: 700 case CMD_BLOCK_END:
675 sway_log(L_ERROR, "Unmatched }"); 701 sway_log(L_ERROR, "Unmatched }");
676 break; 702 break;