diff options
author | Drew DeVault <sir@cmpwn.com> | 2016-12-02 08:10:03 -0500 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2016-12-02 08:10:03 -0500 |
commit | f23880b1fdd70a21b04317c18208a1f3ce356839 (patch) | |
tree | 51a54d43531ac28ef014193abef8f4ccd7a78332 | |
parent | Enforce mouse permissions (diff) | |
download | sway-f23880b1fdd70a21b04317c18208a1f3ce356839.tar.gz sway-f23880b1fdd70a21b04317c18208a1f3ce356839.tar.zst sway-f23880b1fdd70a21b04317c18208a1f3ce356839.zip |
Add support for command policies in config file
-rw-r--r-- | include/sway/commands.h | 10 | ||||
-rw-r--r-- | include/sway/security.h | 1 | ||||
-rw-r--r-- | sway/commands.c | 82 | ||||
-rw-r--r-- | sway/commands/commands.c | 23 | ||||
-rw-r--r-- | sway/commands/permit.c | 3 | ||||
-rw-r--r-- | sway/config.c | 21 | ||||
-rw-r--r-- | sway/security.c | 10 |
7 files changed, 142 insertions, 8 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h index 1d5d56ac..ccc3cf58 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h | |||
@@ -18,7 +18,10 @@ enum cmd_status { | |||
18 | CMD_BLOCK_MODE, | 18 | CMD_BLOCK_MODE, |
19 | CMD_BLOCK_BAR, | 19 | CMD_BLOCK_BAR, |
20 | CMD_BLOCK_BAR_COLORS, | 20 | CMD_BLOCK_BAR_COLORS, |
21 | CMD_BLOCK_INPUT | 21 | CMD_BLOCK_INPUT, |
22 | CMD_BLOCK_COMMANDS, | ||
23 | CMD_BLOCK_IPC, | ||
24 | CMD_BLOCK_IPC_EVENTS, | ||
22 | }; | 25 | }; |
23 | 26 | ||
24 | /** | 27 | /** |
@@ -58,6 +61,10 @@ struct cmd_results *handle_command(char *command); | |||
58 | * Do not use this under normal conditions. | 61 | * Do not use this under normal conditions. |
59 | */ | 62 | */ |
60 | struct cmd_results *config_command(char *command, enum cmd_status block); | 63 | struct cmd_results *config_command(char *command, enum cmd_status block); |
64 | /* | ||
65 | * Parses a command policy rule. | ||
66 | */ | ||
67 | struct cmd_results *config_commands_command(char *exec); | ||
61 | 68 | ||
62 | /** | 69 | /** |
63 | * Allocates a cmd_results object. | 70 | * Allocates a cmd_results object. |
@@ -93,6 +100,7 @@ sway_cmd cmd_client_unfocused; | |||
93 | sway_cmd cmd_client_urgent; | 100 | sway_cmd cmd_client_urgent; |
94 | sway_cmd cmd_client_placeholder; | 101 | sway_cmd cmd_client_placeholder; |
95 | sway_cmd cmd_client_background; | 102 | sway_cmd cmd_client_background; |
103 | sway_cmd cmd_commands; | ||
96 | sway_cmd cmd_debuglog; | 104 | sway_cmd cmd_debuglog; |
97 | sway_cmd cmd_exec; | 105 | sway_cmd cmd_exec; |
98 | sway_cmd cmd_exec_always; | 106 | sway_cmd cmd_exec_always; |
diff --git a/include/sway/security.h b/include/sway/security.h index ae2de0d8..aa51fd81 100644 --- a/include/sway/security.h +++ b/include/sway/security.h | |||
@@ -7,5 +7,6 @@ enum secure_feature get_feature_policy(pid_t pid); | |||
7 | enum command_context get_command_policy(const char *cmd); | 7 | enum command_context get_command_policy(const char *cmd); |
8 | 8 | ||
9 | struct feature_policy *alloc_feature_policy(const char *program); | 9 | struct feature_policy *alloc_feature_policy(const char *program); |
10 | struct command_policy *alloc_command_policy(const char *command); | ||
10 | 11 | ||
11 | #endif | 12 | #endif |
diff --git a/sway/commands.c b/sway/commands.c index e2bafcb2..0bfe9d13 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "sway/input_state.h" | 26 | #include "sway/input_state.h" |
27 | #include "sway/criteria.h" | 27 | #include "sway/criteria.h" |
28 | #include "sway/ipc-server.h" | 28 | #include "sway/ipc-server.h" |
29 | #include "sway/security.h" | ||
29 | #include "sway/input.h" | 30 | #include "sway/input.h" |
30 | #include "sway/border.h" | 31 | #include "sway/border.h" |
31 | #include "stringop.h" | 32 | #include "stringop.h" |
@@ -158,6 +159,7 @@ static struct cmd_handler handlers[] = { | |||
158 | { "client.placeholder", cmd_client_placeholder }, | 159 | { "client.placeholder", cmd_client_placeholder }, |
159 | { "client.unfocused", cmd_client_unfocused }, | 160 | { "client.unfocused", cmd_client_unfocused }, |
160 | { "client.urgent", cmd_client_urgent }, | 161 | { "client.urgent", cmd_client_urgent }, |
162 | { "commands", cmd_commands }, | ||
161 | { "debuglog", cmd_debuglog }, | 163 | { "debuglog", cmd_debuglog }, |
162 | { "default_orientation", cmd_orientation }, | 164 | { "default_orientation", cmd_orientation }, |
163 | { "exec", cmd_exec }, | 165 | { "exec", cmd_exec }, |
@@ -460,7 +462,85 @@ struct cmd_results *config_command(char *exec, enum cmd_status block) { | |||
460 | } else { | 462 | } else { |
461 | results = cmd_results_new(CMD_INVALID, argv[0], "This command is shimmed, but unimplemented"); | 463 | results = cmd_results_new(CMD_INVALID, argv[0], "This command is shimmed, but unimplemented"); |
462 | } | 464 | } |
463 | cleanup: | 465 | |
466 | cleanup: | ||
467 | free_argv(argc, argv); | ||
468 | return results; | ||
469 | } | ||
470 | |||
471 | struct cmd_results *config_commands_command(char *exec) { | ||
472 | struct cmd_results *results = NULL; | ||
473 | int argc; | ||
474 | char **argv = split_args(exec, &argc); | ||
475 | if (!argc) { | ||
476 | results = cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
477 | goto cleanup; | ||
478 | } | ||
479 | |||
480 | // Find handler for the command this is setting a policy for | ||
481 | char *cmd = argv[0]; | ||
482 | |||
483 | if (strcmp(cmd, "}") == 0) { | ||
484 | results = cmd_results_new(CMD_BLOCK_END, NULL, NULL); | ||
485 | goto cleanup; | ||
486 | } | ||
487 | |||
488 | struct cmd_handler *handler = find_handler(cmd, CMD_BLOCK_END); | ||
489 | if (!handler) { | ||
490 | char *input = cmd ? cmd : "(empty)"; | ||
491 | results = cmd_results_new(CMD_INVALID, input, "Unknown/invalid command"); | ||
492 | goto cleanup; | ||
493 | } | ||
494 | |||
495 | enum command_context context = 0; | ||
496 | |||
497 | struct { | ||
498 | char *name; | ||
499 | enum command_context context; | ||
500 | } context_names[] = { | ||
501 | { "config", CONTEXT_CONFIG }, | ||
502 | { "binding", CONTEXT_BINDING }, | ||
503 | { "ipc", CONTEXT_IPC }, | ||
504 | { "criteria", CONTEXT_CRITERIA }, | ||
505 | { "all", CONTEXT_ALL }, | ||
506 | }; | ||
507 | size_t names_len = 5; | ||
508 | |||
509 | for (int i = 1; i < argc; ++i) { | ||
510 | size_t j; | ||
511 | for (j = 0; j < names_len; ++j) { | ||
512 | if (strcmp(context_names[j].name, argv[i]) == 0) { | ||
513 | break; | ||
514 | } | ||
515 | } | ||
516 | if (j == names_len) { | ||
517 | results = cmd_results_new(CMD_INVALID, cmd, | ||
518 | "Invalid command context %s", argv[i]); | ||
519 | goto cleanup; | ||
520 | } | ||
521 | context |= context_names[j].context; | ||
522 | } | ||
523 | |||
524 | struct command_policy *policy = NULL; | ||
525 | for (int i = 0; i < config->command_policies->length; ++i) { | ||
526 | struct command_policy *p = config->command_policies->items[i]; | ||
527 | if (strcmp(p->command, cmd) == 0) { | ||
528 | policy = p; | ||
529 | break; | ||
530 | } | ||
531 | } | ||
532 | if (!policy) { | ||
533 | policy = alloc_command_policy(cmd); | ||
534 | list_add(config->command_policies, policy); | ||
535 | } | ||
536 | policy->context = context; | ||
537 | |||
538 | sway_log(L_INFO, "Set command policy for %s to %d", | ||
539 | policy->command, policy->context); | ||
540 | |||
541 | results = cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
542 | |||
543 | cleanup: | ||
464 | free_argv(argc, argv); | 544 | free_argv(argc, argv); |
465 | return results; | 545 | return results; |
466 | } | 546 | } |
diff --git a/sway/commands/commands.c b/sway/commands/commands.c new file mode 100644 index 00000000..5d248e30 --- /dev/null +++ b/sway/commands/commands.c | |||
@@ -0,0 +1,23 @@ | |||
1 | #include <stdbool.h> | ||
2 | #include <string.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/config.h" | ||
5 | #include "list.h" | ||
6 | #include "log.h" | ||
7 | |||
8 | struct cmd_results *cmd_commands(int argc, char **argv) { | ||
9 | struct cmd_results *error = NULL; | ||
10 | if ((error = checkarg(argc, "commands", EXPECTED_EQUAL_TO, 1))) { | ||
11 | return error; | ||
12 | } | ||
13 | |||
14 | if (strcmp(argv[0], "{") != 0) { | ||
15 | return cmd_results_new(CMD_FAILURE, "commands", "Expected block declaration"); | ||
16 | } | ||
17 | |||
18 | if (!config->reading) { | ||
19 | return cmd_results_new(CMD_FAILURE, "commands", "Can only be used in config file."); | ||
20 | } | ||
21 | |||
22 | return cmd_results_new(CMD_BLOCK_COMMANDS, NULL, NULL); | ||
23 | } | ||
diff --git a/sway/commands/permit.c b/sway/commands/permit.c index 8a7bb98c..258ea5b2 100644 --- a/sway/commands/permit.c +++ b/sway/commands/permit.c | |||
@@ -20,8 +20,7 @@ static enum secure_feature get_features(int argc, char **argv, | |||
20 | { "keyboard", FEATURE_KEYBOARD }, | 20 | { "keyboard", FEATURE_KEYBOARD }, |
21 | { "mouse", FEATURE_MOUSE }, | 21 | { "mouse", FEATURE_MOUSE }, |
22 | }; | 22 | }; |
23 | size_t names_len = sizeof(feature_names) / | 23 | size_t names_len = 7; |
24 | (sizeof(char *) + sizeof(enum secure_feature)); | ||
25 | 24 | ||
26 | for (int i = 1; i < argc; ++i) { | 25 | for (int i = 1; i < argc; ++i) { |
27 | size_t j; | 26 | size_t j; |
diff --git a/sway/config.c b/sway/config.c index a2f6a728..e55c6dea 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -580,7 +580,13 @@ bool read_config(FILE *file, struct sway_config *config) { | |||
580 | free(line); | 580 | free(line); |
581 | continue; | 581 | continue; |
582 | } | 582 | } |
583 | struct cmd_results *res = config_command(line, block); | 583 | struct cmd_results *res; |
584 | if (block == CMD_BLOCK_COMMANDS) { | ||
585 | // Special case | ||
586 | res = config_commands_command(line); | ||
587 | } else { | ||
588 | res = config_command(line, block); | ||
589 | } | ||
584 | switch(res->status) { | 590 | switch(res->status) { |
585 | case CMD_FAILURE: | 591 | case CMD_FAILURE: |
586 | case CMD_INVALID: | 592 | case CMD_INVALID: |
@@ -626,6 +632,14 @@ bool read_config(FILE *file, struct sway_config *config) { | |||
626 | } | 632 | } |
627 | break; | 633 | break; |
628 | 634 | ||
635 | case CMD_BLOCK_COMMANDS: | ||
636 | if (block == CMD_BLOCK_END) { | ||
637 | block = CMD_BLOCK_COMMANDS; | ||
638 | } else { | ||
639 | sway_log(L_ERROR, "Invalid block '%s'", line); | ||
640 | } | ||
641 | break; | ||
642 | |||
629 | case CMD_BLOCK_END: | 643 | case CMD_BLOCK_END: |
630 | switch(block) { | 644 | switch(block) { |
631 | case CMD_BLOCK_MODE: | 645 | case CMD_BLOCK_MODE: |
@@ -651,6 +665,11 @@ bool read_config(FILE *file, struct sway_config *config) { | |||
651 | block = CMD_BLOCK_BAR; | 665 | block = CMD_BLOCK_BAR; |
652 | break; | 666 | break; |
653 | 667 | ||
668 | case CMD_BLOCK_COMMANDS: | ||
669 | sway_log(L_DEBUG, "End of commands block"); | ||
670 | block = CMD_BLOCK_END; | ||
671 | break; | ||
672 | |||
654 | case CMD_BLOCK_END: | 673 | case CMD_BLOCK_END: |
655 | sway_log(L_ERROR, "Unmatched }"); | 674 | sway_log(L_ERROR, "Unmatched }"); |
656 | break; | 675 | break; |
diff --git a/sway/security.c b/sway/security.c index a4cecf16..670cae56 100644 --- a/sway/security.c +++ b/sway/security.c | |||
@@ -11,6 +11,13 @@ struct feature_policy *alloc_feature_policy(const char *program) { | |||
11 | return policy; | 11 | return policy; |
12 | } | 12 | } |
13 | 13 | ||
14 | struct command_policy *alloc_command_policy(const char *command) { | ||
15 | struct command_policy *policy = malloc(sizeof(struct command_policy)); | ||
16 | policy->command = strdup(command); | ||
17 | policy->context = CONTEXT_ALL; | ||
18 | return policy; | ||
19 | } | ||
20 | |||
14 | enum secure_feature get_feature_policy(pid_t pid) { | 21 | enum secure_feature get_feature_policy(pid_t pid) { |
15 | const char *fmt = "/proc/%d/exe"; | 22 | const char *fmt = "/proc/%d/exe"; |
16 | int pathlen = snprintf(NULL, 0, fmt, pid); | 23 | int pathlen = snprintf(NULL, 0, fmt, pid); |
@@ -50,9 +57,6 @@ enum command_context get_command_policy(const char *cmd) { | |||
50 | 57 | ||
51 | for (int i = 0; i < config->command_policies->length; ++i) { | 58 | for (int i = 0; i < config->command_policies->length; ++i) { |
52 | struct command_policy *policy = config->command_policies->items[i]; | 59 | struct command_policy *policy = config->command_policies->items[i]; |
53 | if (strcmp(policy->command, "*") == 0) { | ||
54 | default_policy = policy->context; | ||
55 | } | ||
56 | if (strcmp(policy->command, cmd) == 0) { | 60 | if (strcmp(policy->command, cmd) == 0) { |
57 | return policy->context; | 61 | return policy->context; |
58 | } | 62 | } |