aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2016-12-02 08:10:03 -0500
committerLibravatar Drew DeVault <sir@cmpwn.com>2016-12-02 08:10:03 -0500
commitf23880b1fdd70a21b04317c18208a1f3ce356839 (patch)
tree51a54d43531ac28ef014193abef8f4ccd7a78332
parentEnforce mouse permissions (diff)
downloadsway-f23880b1fdd70a21b04317c18208a1f3ce356839.tar.gz
sway-f23880b1fdd70a21b04317c18208a1f3ce356839.tar.zst
sway-f23880b1fdd70a21b04317c18208a1f3ce356839.zip
Add support for command policies in config file
-rw-r--r--include/sway/commands.h10
-rw-r--r--include/sway/security.h1
-rw-r--r--sway/commands.c82
-rw-r--r--sway/commands/commands.c23
-rw-r--r--sway/commands/permit.c3
-rw-r--r--sway/config.c21
-rw-r--r--sway/security.c10
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 */
60struct cmd_results *config_command(char *command, enum cmd_status block); 63struct cmd_results *config_command(char *command, enum cmd_status block);
64/*
65 * Parses a command policy rule.
66 */
67struct 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;
93sway_cmd cmd_client_urgent; 100sway_cmd cmd_client_urgent;
94sway_cmd cmd_client_placeholder; 101sway_cmd cmd_client_placeholder;
95sway_cmd cmd_client_background; 102sway_cmd cmd_client_background;
103sway_cmd cmd_commands;
96sway_cmd cmd_debuglog; 104sway_cmd cmd_debuglog;
97sway_cmd cmd_exec; 105sway_cmd cmd_exec;
98sway_cmd cmd_exec_always; 106sway_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);
7enum command_context get_command_policy(const char *cmd); 7enum command_context get_command_policy(const char *cmd);
8 8
9struct feature_policy *alloc_feature_policy(const char *program); 9struct feature_policy *alloc_feature_policy(const char *program);
10struct 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
466cleanup:
467 free_argv(argc, argv);
468 return results;
469}
470
471struct 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
543cleanup:
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
8struct 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
14struct 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
14enum secure_feature get_feature_policy(pid_t pid) { 21enum 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 }