aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2016-12-02 08:17:45 -0500
committerDrew DeVault <sir@cmpwn.com>2016-12-02 08:17:45 -0500
commit39cf9a82f7c1f7e5d7b4952cabf215c8459a99e2 (patch)
tree267efa5b40f7272bdfec16eac054961df6f4d417
parentf23880b1fdd70a21b04317c18208a1f3ce356839 (diff)
Enforce command policies
-rw-r--r--include/sway/commands.h2
-rw-r--r--include/sway/security.h2
-rw-r--r--sway/commands.c12
-rw-r--r--sway/handlers.c14
-rw-r--r--sway/ipc-server.c2
-rw-r--r--sway/security.c17
6 files changed, 39 insertions, 10 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h
index ccc3cf58..9e8d013e 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -54,7 +54,7 @@ int sp_index;
/**
* Parse and handles a command.
*/
-struct cmd_results *handle_command(char *command);
+struct cmd_results *handle_command(char *command, enum command_context context);
/**
* Parse and handles a command during config file loading.
*
diff --git a/include/sway/security.h b/include/sway/security.h
index aa51fd81..1cc85bee 100644
--- a/include/sway/security.h
+++ b/include/sway/security.h
@@ -6,6 +6,8 @@
enum secure_feature get_feature_policy(pid_t pid);
enum command_context get_command_policy(const char *cmd);
+const char *command_policy_str(enum command_context context);
+
struct feature_policy *alloc_feature_policy(const char *program);
struct command_policy *alloc_command_policy(const char *command);
diff --git a/sway/commands.c b/sway/commands.c
index 0bfe9d13..5d5087b1 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -323,7 +323,7 @@ static struct cmd_handler *find_handler(char *line, enum cmd_status block) {
return res;
}
-struct cmd_results *handle_command(char *_exec) {
+struct cmd_results *handle_command(char *_exec, enum command_context context) {
// Even though this function will process multiple commands we will only
// return the last error, if any (for now). (Since we have access to an
// error string we could e.g. concatonate all errors there.)
@@ -397,6 +397,16 @@ struct cmd_results *handle_command(char *_exec) {
free_argv(argc, argv);
goto cleanup;
}
+ if (!(get_command_policy(argv[0]) & context)) {
+ if (results) {
+ free_cmd_results(results);
+ }
+ results = cmd_results_new(CMD_INVALID, cmd,
+ "Permission denied for %s via %s", cmd,
+ command_policy_str(context));
+ free_argv(argc, argv);
+ goto cleanup;
+ }
struct cmd_results *res = handler->handle(argc-1, argv+1);
if (res->status != CMD_SUCCESS) {
free_argv(argc, argv);
diff --git a/sway/handlers.c b/sway/handlers.c
index a329329d..ee52ba38 100644
--- a/sway/handlers.c
+++ b/sway/handlers.c
@@ -386,7 +386,7 @@ static bool handle_view_created(wlc_handle handle) {
struct criteria *crit = criteria->items[i];
sway_log(L_DEBUG, "for_window '%s' matches new view %p, cmd: '%s'",
crit->crit_raw, newview, crit->cmdlist);
- struct cmd_results *res = handle_command(crit->cmdlist);
+ struct cmd_results *res = handle_command(crit->cmdlist, CONTEXT_CRITERIA);
if (res->status != CMD_SUCCESS) {
sway_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error);
}
@@ -585,7 +585,7 @@ static void handle_binding_command(struct sway_binding *binding) {
reload = true;
}
- struct cmd_results *res = handle_command(binding->command);
+ struct cmd_results *res = handle_command(binding->command, CONTEXT_BINDING);
if (res->status != CMD_SUCCESS) {
sway_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error);
}
@@ -936,18 +936,18 @@ bool handle_pointer_scroll(wlc_handle view, uint32_t time, const struct wlc_modi
int y_amount = (int)_amount[1];
if (x_amount > 0 && strcmp(config->floating_scroll_up_cmd, "")) {
- handle_command(config->floating_scroll_up_cmd);
+ handle_command(config->floating_scroll_up_cmd, CONTEXT_BINDING);
return EVENT_HANDLED;
} else if (x_amount < 0 && strcmp(config->floating_scroll_down_cmd, "")) {
- handle_command(config->floating_scroll_down_cmd);
+ handle_command(config->floating_scroll_down_cmd, CONTEXT_BINDING);
return EVENT_HANDLED;
}
if (y_amount > 0 && strcmp(config->floating_scroll_right_cmd, "")) {
- handle_command(config->floating_scroll_right_cmd);
+ handle_command(config->floating_scroll_right_cmd, CONTEXT_BINDING);
return EVENT_HANDLED;
} else if (y_amount < 0 && strcmp(config->floating_scroll_left_cmd, "")) {
- handle_command(config->floating_scroll_left_cmd);
+ handle_command(config->floating_scroll_left_cmd, CONTEXT_BINDING);
return EVENT_HANDLED;
}
}
@@ -960,7 +960,7 @@ static void handle_wlc_ready(void) {
config->active = true;
while (config->cmd_queue->length) {
char *line = config->cmd_queue->items[0];
- struct cmd_results *res = handle_command(line);
+ struct cmd_results *res = handle_command(line, CONTEXT_CONFIG);
if (res->status != CMD_SUCCESS) {
sway_log(L_ERROR, "Error on line '%s': %s", line, res->error);
}
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index ebb5ce58..e575081b 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -312,7 +312,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
switch (client->current_command) {
case IPC_COMMAND:
{
- struct cmd_results *results = handle_command(buf);
+ struct cmd_results *results = handle_command(buf, CONTEXT_IPC);
const char *json = cmd_results_to_json(results);
char reply[256];
int length = snprintf(reply, sizeof(reply), "%s", json);
diff --git a/sway/security.c b/sway/security.c
index 670cae56..2ccc30fd 100644
--- a/sway/security.c
+++ b/sway/security.c
@@ -64,3 +64,20 @@ enum command_context get_command_policy(const char *cmd) {
return default_policy;
}
+
+const char *command_policy_str(enum command_context context) {
+ switch (context) {
+ case CONTEXT_ALL:
+ return "all";
+ case CONTEXT_CONFIG:
+ return "config";
+ case CONTEXT_BINDING:
+ return "binding";
+ case CONTEXT_IPC:
+ return "IPC";
+ case CONTEXT_CRITERIA:
+ return "criteria";
+ default:
+ return "unknown";
+ }
+}