From 5831f7ab68a7166a492812d6301868541fdc9ae3 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 1 Dec 2016 19:27:35 -0500 Subject: Write example security config, start on code --- config.d/security | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 config.d/security (limited to 'config.d') diff --git a/config.d/security b/config.d/security new file mode 100644 index 00000000..bff55f0f --- /dev/null +++ b/config.d/security @@ -0,0 +1,52 @@ +# sway security rules +# +# Read sway-security(7) for details on how to secure your sway install. +# +# You MUST read this man page if you intend to attempt to secure your sway +# installation. + +# Configures which programs are allowed to use which sway features +permit $PREFIX/swaylock lock +permit $PREFIX/swaybar panel +permit $PREFIX/swaybg background +permit $PREFIX/swaygrab screenshot + +permit * fullscreen keyboard mouse + +# Configures which IPC features are enabled +ipc { + command enabled + outputs enabled + workspaces enabled + tree enabled + marks enabled + bar-config enabled + inputs enabled + + events { + workspace enabled + output enabled + mode enabled + window enabled + bar-config enabled + binding enabled + modifier enabled + input enabled + } +} + +# Limits the contexts from which certain commands are permitted +commands { + fullscreen bindsym criteria + bindsym config + exit bindsym + kill bindsym + + # You should not change these unless you know what you're doing - it could + # cripple your security + reload bindsym + restart bindsym + permit config + reject config + ipc config +} -- cgit v1.2.3 From 44cc0ef125332f1fe3dad7d16ed0a78a25cd1974 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 1 Dec 2016 19:38:36 -0500 Subject: Add config related code and initial headers --- config.d/security | 10 +++++----- include/security.h | 9 +++++++++ include/sway/config.h | 39 ++++++++++++++++++++++++++++++++++++--- sway/config.c | 24 ++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 include/security.h (limited to 'config.d') diff --git a/config.d/security b/config.d/security index bff55f0f..fe75d8ea 100644 --- a/config.d/security +++ b/config.d/security @@ -37,15 +37,15 @@ ipc { # Limits the contexts from which certain commands are permitted commands { - fullscreen bindsym criteria + fullscreen binding criteria bindsym config - exit bindsym - kill bindsym + exit binding + kill binding # You should not change these unless you know what you're doing - it could # cripple your security - reload bindsym - restart bindsym + reload binding + restart binding permit config reject config ipc config diff --git a/include/security.h b/include/security.h new file mode 100644 index 00000000..efc25ce6 --- /dev/null +++ b/include/security.h @@ -0,0 +1,9 @@ +#ifndef _SWAY_SECURITY_H +#define _SWAY_SECURITY_H +#include +#include "sway/config.h" + +const struct feature_permissions *get_permissions(pid_t pid); +enum command_context get_command_context(const char *cmd); + +#endif diff --git a/include/sway/config.h b/include/sway/config.h index 8d077ee7..3744386c 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -103,9 +103,6 @@ struct pid_workspace { time_t *time_added; }; -void pid_workspace_add(struct pid_workspace *pw); -void free_pid_workspace(struct pid_workspace *pw); - struct bar_config { /** * One of "dock", "hide", "invisible" @@ -184,6 +181,35 @@ enum edge_border_types { E_BOTH /**< hide vertical and horizontal edge borders */ }; +enum command_context { + CONTEXT_CONFIG = 1, + CONTEXT_BINDING = 2, + CONTEXT_IPC = 4, + CONTEXT_CRITERIA = 8, + CONTEXT_ALL = 0xFFFFFFFF, +}; + +struct command_policy { + char *command; + enum command_context context; +}; + +enum secure_feature { + FEATURE_LOCK = 1, + FEATURE_PANEL = 2, + FEATURE_BACKGROUND = 4, + FEATURE_SCREENSHOT = 8, + FEATURE_FULLSCREEN = 16, + FEATURE_KEYBOARD = 32, + FEATURE_MOUSE = 64, +}; + +struct feature_policy { + char *program; + bool permit; + enum secure_feature features; +}; + /** * The configuration struct. The result of loading a config file. */ @@ -252,8 +278,15 @@ struct sway_config { int32_t floating_maximum_height; int32_t floating_minimum_width; int32_t floating_minimum_height; + + // Security + list_t *command_policies; + list_t *feature_policies; }; +void pid_workspace_add(struct pid_workspace *pw); +void free_pid_workspace(struct pid_workspace *pw); + /** * Loads the main config from the given path. is_active should be true when * reloading the config. diff --git a/sway/config.c b/sway/config.c index 7d5999d8..a2f6a728 100644 --- a/sway/config.c +++ b/sway/config.c @@ -167,6 +167,16 @@ void free_pid_workspace(struct pid_workspace *pw) { free(pw); } +void free_command_policy(struct command_policy *policy) { + free(policy->command); + free(policy); +} + +void free_feature_policy(struct feature_policy *policy) { + free(policy->program); + free(policy); +} + void free_config(struct sway_config *config) { int i; for (i = 0; i < config->symbols->length; ++i) { @@ -211,6 +221,16 @@ void free_config(struct sway_config *config) { } list_free(config->output_configs); + for (i = 0; i < config->command_policies->length; ++i) { + free_command_policy(config->command_policies->items[i]); + } + list_free(config->command_policies); + + for (i = 0; i < config->feature_policies->length; ++i) { + free_feature_policy(config->feature_policies->items[i]); + } + list_free(config->feature_policies); + list_free(config->active_bar_modifiers); free_flat_list(config->config_chain); free(config->font); @@ -321,6 +341,10 @@ static void config_defaults(struct sway_config *config) { config->border_colors.placeholder.child_border = 0x0C0C0CFF; config->border_colors.background = 0xFFFFFFFF; + + // Security + config->command_policies = create_list(); + config->feature_policies = create_list(); } static int compare_modifiers(const void *left, const void *right) { -- cgit v1.2.3 From 76cab04b4d7828f3c4f607c49e1e6ad78aa6e3da Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 1 Dec 2016 21:36:43 -0500 Subject: Implement permit and reject commands --- config | 204 ------------------------------------------------ config.d/security | 52 ------------ config.d/security.in | 52 ++++++++++++ config.in | 198 ++++++++++++++++++++++++++++++++++++++++++++++ include/security.h | 9 --- include/sway/commands.h | 2 + include/sway/security.h | 6 +- sway/commands.c | 2 + sway/commands/permit.c | 95 ++++++++++++++++++++++ sway/security.c | 7 ++ 10 files changed, 360 insertions(+), 267 deletions(-) delete mode 100644 config delete mode 100644 config.d/security create mode 100644 config.d/security.in create mode 100644 config.in delete mode 100644 include/security.h create mode 100644 sway/commands/permit.c (limited to 'config.d') diff --git a/config b/config deleted file mode 100644 index 47bf1e4f..00000000 --- a/config +++ /dev/null @@ -1,204 +0,0 @@ -# Default config for sway -# -# Copy this to ~/.config/sway/config and edit it to your liking. -# -# Read `man 5 sway` for a complete reference. - -### Variables -# -# Logo key. Use Mod1 for Alt. -set $mod Mod4 -# Home row direction keys, like vim -set $left h -set $down j -set $up k -set $right l -# Your preferred terminal emulator -set $term urxvt -# Your preferred application launcher -set $menu dmenu_run - -### Output configuration -# -# Default wallpaper (more resolutions are available in /usr/share/sway/) -output * bg /usr/share/sway/Sway_Wallpaper_Blue_1920x1080.png fill -# -# Example configuration: -# -# output HDMI-A-1 resolution 1920x1080 position 1920,0 -# -# You can get the names of your outputs by running: swaymsg -t get_outputs - -### Input configuration -# -# Example configuration: -# -# input "2:14:SynPS/2_Synaptics_TouchPad" { -# dwt enabled -# tap enabled -# natural_scroll enabled -# middle_emulation enabled -# } -# -# You can get the names of your inputs by running: swaymsg -t get_inputs -# The escape symbol "\" has to be removed. -# Read `man 5 sway-input` for more information about this section. - -### Key bindings -# -# Basics: -# - # start a terminal - bindsym $mod+Return exec $term - - # kill focused window - bindsym $mod+Shift+q kill - - # start your launcher - bindsym $mod+d exec $menu - - # Drag floating windows by holding down $mod and left mouse button. - # Resize them with right mouse button + $mod. - # Despite the name, also works for non-floating windows. - # Change normal to inverse to use left mouse button for resizing and right - # mouse button for dragging. - floating_modifier $mod normal - - # reload the configuration file - bindsym $mod+Shift+c reload - - # exit sway (logs you out of your wayland session) - bindsym $mod+Shift+e exit -# -# Moving around: -# - # Move your focus around - bindsym $mod+$left focus left - bindsym $mod+$down focus down - bindsym $mod+$up focus up - bindsym $mod+$right focus right - # or use $mod+[up|down|left|right] - bindsym $mod+Left focus left - bindsym $mod+Down focus down - bindsym $mod+Up focus up - bindsym $mod+Right focus right - - # _move_ the focused window with the same, but add Shift - bindsym $mod+Shift+$left move left - bindsym $mod+Shift+$down move down - bindsym $mod+Shift+$up move up - bindsym $mod+Shift+$right move right - # ditto, with arrow keys - bindsym $mod+Shift+Left move left - bindsym $mod+Shift+Down move down - bindsym $mod+Shift+Up move up - bindsym $mod+Shift+Right move right -# -# Workspaces: -# - # switch to workspace - bindsym $mod+1 workspace 1 - bindsym $mod+2 workspace 2 - bindsym $mod+3 workspace 3 - bindsym $mod+4 workspace 4 - bindsym $mod+5 workspace 5 - bindsym $mod+6 workspace 6 - bindsym $mod+7 workspace 7 - bindsym $mod+8 workspace 8 - bindsym $mod+9 workspace 9 - bindsym $mod+0 workspace 10 - # move focused container to workspace - bindsym $mod+Shift+1 move container to workspace 1 - bindsym $mod+Shift+2 move container to workspace 2 - bindsym $mod+Shift+3 move container to workspace 3 - bindsym $mod+Shift+4 move container to workspace 4 - bindsym $mod+Shift+5 move container to workspace 5 - bindsym $mod+Shift+6 move container to workspace 6 - bindsym $mod+Shift+7 move container to workspace 7 - bindsym $mod+Shift+8 move container to workspace 8 - bindsym $mod+Shift+9 move container to workspace 9 - bindsym $mod+Shift+0 move container to workspace 10 - # Note: workspaces can have any name you want, not just numbers. - # We just use 1-10 as the default. -# -# Layout stuff: -# - # You can "split" the current object of your focus with - # $mod+b or $mod+v, for horizontal and vertical splits - # respectively. - bindsym $mod+b splith - bindsym $mod+v splitv - - # Switch the current container between different layout styles - bindsym $mod+s layout stacking - bindsym $mod+w layout tabbed - bindsym $mod+e layout toggle split - - # Make the current focus fullscreen - bindsym $mod+f fullscreen - - # Toggle the current focus between tiling and floating mode - bindsym $mod+Shift+space floating toggle - - # Swap focus between the tiling area and the floating area - bindsym $mod+space focus mode_toggle - - # move focus to the parent container - bindsym $mod+a focus parent -# -# Scratchpad: -# - # Sway has a "scratchpad", which is a bag of holding for windows. - # You can send windows there and get them back later. - - # Move the currently focused window to the scratchpad - bindsym $mod+Shift+minus move scratchpad - - # Show the next scratchpad window or hide the focused scratchpad window. - # If there are multiple scratchpad windows, this command cycles through them. - bindsym $mod+minus scratchpad show -# -# Resizing containers: -# -mode "resize" { - # left will shrink the containers width - # right will grow the containers width - # up will shrink the containers height - # down will grow the containers height - bindsym $left resize shrink width 10 px or 10 ppt - bindsym $down resize grow height 10 px or 10 ppt - bindsym $up resize shrink height 10 px or 10 ppt - bindsym $right resize grow width 10 px or 10 ppt - - # ditto, with arrow keys - bindsym Left resize shrink width 10 px or 10 ppt - bindsym Down resize grow height 10 px or 10 ppt - bindsym Up resize shrink height 10 px or 10 ppt - bindsym Right resize grow width 10 px or 10 ppt - - # return to default mode - bindsym Return mode "default" - bindsym Escape mode "default" -} -bindsym $mod+r mode "resize" - -# -# Status Bar: -# -# Read `man 5 sway-bar` for more information about this section. -bar { - position top - colors { - statusline #ffffff - background #323232 - inactive_workspace #32323200 #32323200 #5c5c5c - } -} - -# You may want this: -# -# include ~/.config/sway/conf.d/* -# -# Protip: -# -# include ~/.config/sway/`hostname`/* diff --git a/config.d/security b/config.d/security deleted file mode 100644 index fe75d8ea..00000000 --- a/config.d/security +++ /dev/null @@ -1,52 +0,0 @@ -# sway security rules -# -# Read sway-security(7) for details on how to secure your sway install. -# -# You MUST read this man page if you intend to attempt to secure your sway -# installation. - -# Configures which programs are allowed to use which sway features -permit $PREFIX/swaylock lock -permit $PREFIX/swaybar panel -permit $PREFIX/swaybg background -permit $PREFIX/swaygrab screenshot - -permit * fullscreen keyboard mouse - -# Configures which IPC features are enabled -ipc { - command enabled - outputs enabled - workspaces enabled - tree enabled - marks enabled - bar-config enabled - inputs enabled - - events { - workspace enabled - output enabled - mode enabled - window enabled - bar-config enabled - binding enabled - modifier enabled - input enabled - } -} - -# Limits the contexts from which certain commands are permitted -commands { - fullscreen binding criteria - bindsym config - exit binding - kill binding - - # You should not change these unless you know what you're doing - it could - # cripple your security - reload binding - restart binding - permit config - reject config - ipc config -} diff --git a/config.d/security.in b/config.d/security.in new file mode 100644 index 00000000..f59b2980 --- /dev/null +++ b/config.d/security.in @@ -0,0 +1,52 @@ +# sway security rules +# +# Read sway-security(7) for details on how to secure your sway install. +# +# You MUST read this man page if you intend to attempt to secure your sway +# installation. + +# Configures which programs are allowed to use which sway features +permit __PREFIX__/swaylock lock +permit __PREFIX__/swaybar panel +permit __PREFIX__/swaybg background +permit __PREFIX__/swaygrab screenshot + +permit * fullscreen keyboard mouse + +# Configures which IPC features are enabled +ipc { + command enabled + outputs enabled + workspaces enabled + tree enabled + marks enabled + bar-config enabled + inputs enabled + + events { + workspace enabled + output enabled + mode enabled + window enabled + bar-config enabled + binding enabled + modifier enabled + input enabled + } +} + +# Limits the contexts from which certain commands are permitted +commands { + fullscreen binding criteria + bindsym config + exit binding + kill binding + + # You should not change these unless you know what you're doing - it could + # cripple your security + reload binding + restart binding + permit config + reject config + ipc config +} diff --git a/config.in b/config.in new file mode 100644 index 00000000..ddd0fec5 --- /dev/null +++ b/config.in @@ -0,0 +1,198 @@ +# Default config for sway +# +# Copy this to ~/.config/sway/config and edit it to your liking. +# +# Read `man 5 sway` for a complete reference. + +### Variables +# +# Logo key. Use Mod1 for Alt. +set $mod Mod4 +# Home row direction keys, like vim +set $left h +set $down j +set $up k +set $right l +# Your preferred terminal emulator +set $term urxvt +# Your preferred application launcher +set $menu dmenu_run + +### Output configuration +# +# Default wallpaper (more resolutions are available in /usr/share/sway/) +output * bg /usr/share/sway/Sway_Wallpaper_Blue_1920x1080.png fill +# +# Example configuration: +# +# output HDMI-A-1 resolution 1920x1080 position 1920,0 +# +# You can get the names of your outputs by running: swaymsg -t get_outputs + +### Input configuration +# +# Example configuration: +# +# input "2:14:SynPS/2_Synaptics_TouchPad" { +# dwt enabled +# tap enabled +# natural_scroll enabled +# middle_emulation enabled +# } +# +# You can get the names of your inputs by running: swaymsg -t get_inputs +# The escape symbol "\" has to be removed. +# Read `man 5 sway-input` for more information about this section. + +### Key bindings +# +# Basics: +# + # start a terminal + bindsym $mod+Return exec $term + + # kill focused window + bindsym $mod+Shift+q kill + + # start your launcher + bindsym $mod+d exec $menu + + # Drag floating windows by holding down $mod and left mouse button. + # Resize them with right mouse button + $mod. + # Despite the name, also works for non-floating windows. + # Change normal to inverse to use left mouse button for resizing and right + # mouse button for dragging. + floating_modifier $mod normal + + # reload the configuration file + bindsym $mod+Shift+c reload + + # exit sway (logs you out of your wayland session) + bindsym $mod+Shift+e exit +# +# Moving around: +# + # Move your focus around + bindsym $mod+$left focus left + bindsym $mod+$down focus down + bindsym $mod+$up focus up + bindsym $mod+$right focus right + # or use $mod+[up|down|left|right] + bindsym $mod+Left focus left + bindsym $mod+Down focus down + bindsym $mod+Up focus up + bindsym $mod+Right focus right + + # _move_ the focused window with the same, but add Shift + bindsym $mod+Shift+$left move left + bindsym $mod+Shift+$down move down + bindsym $mod+Shift+$up move up + bindsym $mod+Shift+$right move right + # ditto, with arrow keys + bindsym $mod+Shift+Left move left + bindsym $mod+Shift+Down move down + bindsym $mod+Shift+Up move up + bindsym $mod+Shift+Right move right +# +# Workspaces: +# + # switch to workspace + bindsym $mod+1 workspace 1 + bindsym $mod+2 workspace 2 + bindsym $mod+3 workspace 3 + bindsym $mod+4 workspace 4 + bindsym $mod+5 workspace 5 + bindsym $mod+6 workspace 6 + bindsym $mod+7 workspace 7 + bindsym $mod+8 workspace 8 + bindsym $mod+9 workspace 9 + bindsym $mod+0 workspace 10 + # move focused container to workspace + bindsym $mod+Shift+1 move container to workspace 1 + bindsym $mod+Shift+2 move container to workspace 2 + bindsym $mod+Shift+3 move container to workspace 3 + bindsym $mod+Shift+4 move container to workspace 4 + bindsym $mod+Shift+5 move container to workspace 5 + bindsym $mod+Shift+6 move container to workspace 6 + bindsym $mod+Shift+7 move container to workspace 7 + bindsym $mod+Shift+8 move container to workspace 8 + bindsym $mod+Shift+9 move container to workspace 9 + bindsym $mod+Shift+0 move container to workspace 10 + # Note: workspaces can have any name you want, not just numbers. + # We just use 1-10 as the default. +# +# Layout stuff: +# + # You can "split" the current object of your focus with + # $mod+b or $mod+v, for horizontal and vertical splits + # respectively. + bindsym $mod+b splith + bindsym $mod+v splitv + + # Switch the current container between different layout styles + bindsym $mod+s layout stacking + bindsym $mod+w layout tabbed + bindsym $mod+e layout toggle split + + # Make the current focus fullscreen + bindsym $mod+f fullscreen + + # Toggle the current focus between tiling and floating mode + bindsym $mod+Shift+space floating toggle + + # Swap focus between the tiling area and the floating area + bindsym $mod+space focus mode_toggle + + # move focus to the parent container + bindsym $mod+a focus parent +# +# Scratchpad: +# + # Sway has a "scratchpad", which is a bag of holding for windows. + # You can send windows there and get them back later. + + # Move the currently focused window to the scratchpad + bindsym $mod+Shift+minus move scratchpad + + # Show the next scratchpad window or hide the focused scratchpad window. + # If there are multiple scratchpad windows, this command cycles through them. + bindsym $mod+minus scratchpad show +# +# Resizing containers: +# +mode "resize" { + # left will shrink the containers width + # right will grow the containers width + # up will shrink the containers height + # down will grow the containers height + bindsym $left resize shrink width 10 px or 10 ppt + bindsym $down resize grow height 10 px or 10 ppt + bindsym $up resize shrink height 10 px or 10 ppt + bindsym $right resize grow width 10 px or 10 ppt + + # ditto, with arrow keys + bindsym Left resize shrink width 10 px or 10 ppt + bindsym Down resize grow height 10 px or 10 ppt + bindsym Up resize shrink height 10 px or 10 ppt + bindsym Right resize grow width 10 px or 10 ppt + + # return to default mode + bindsym Return mode "default" + bindsym Escape mode "default" +} +bindsym $mod+r mode "resize" + +# +# Status Bar: +# +# Read `man 5 sway-bar` for more information about this section. +bar { + position top + colors { + statusline #ffffff + background #323232 + inactive_workspace #32323200 #32323200 #5c5c5c + } +} + +include __SYSCONFDIR__/etc/sway/config.d/* diff --git a/include/security.h b/include/security.h deleted file mode 100644 index 3a5dbca0..00000000 --- a/include/security.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _SWAY_SECURITY_H -#define _SWAY_SECURITY_H -#include -#include "sway/config.h" - -enum secure_features get_feature_policy(pid_t pid); -enum command_context get_command_policy(const char *cmd); - -#endif diff --git a/include/sway/commands.h b/include/sway/commands.h index db5e94d9..1d5d56ac 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -122,6 +122,8 @@ sway_cmd cmd_new_float; sway_cmd cmd_new_window; sway_cmd cmd_orientation; sway_cmd cmd_output; +sway_cmd cmd_permit; +sway_cmd cmd_reject; sway_cmd cmd_reload; sway_cmd cmd_resize; sway_cmd cmd_scratchpad; diff --git a/include/sway/security.h b/include/sway/security.h index efc25ce6..ae2de0d8 100644 --- a/include/sway/security.h +++ b/include/sway/security.h @@ -3,7 +3,9 @@ #include #include "sway/config.h" -const struct feature_permissions *get_permissions(pid_t pid); -enum command_context get_command_context(const char *cmd); +enum secure_feature get_feature_policy(pid_t pid); +enum command_context get_command_policy(const char *cmd); + +struct feature_policy *alloc_feature_policy(const char *program); #endif diff --git a/sway/commands.c b/sway/commands.c index de29a7af..e2bafcb2 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -187,6 +187,8 @@ static struct cmd_handler handlers[] = { { "new_float", cmd_new_float }, { "new_window", cmd_new_window }, { "output", cmd_output }, + { "permit", cmd_permit }, + { "reject", cmd_reject }, { "reload", cmd_reload }, { "resize", cmd_resize }, { "scratchpad", cmd_scratchpad }, diff --git a/sway/commands/permit.c b/sway/commands/permit.c new file mode 100644 index 00000000..8a7bb98c --- /dev/null +++ b/sway/commands/permit.c @@ -0,0 +1,95 @@ +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/security.h" +#include "log.h" + +static enum secure_feature get_features(int argc, char **argv, + struct cmd_results **error) { + enum secure_feature features = 0; + + struct { + char *name; + enum secure_feature feature; + } feature_names[] = { + { "lock", FEATURE_LOCK }, + { "panel", FEATURE_PANEL }, + { "background", FEATURE_BACKGROUND }, + { "screenshot", FEATURE_SCREENSHOT }, + { "fullscreen", FEATURE_FULLSCREEN }, + { "keyboard", FEATURE_KEYBOARD }, + { "mouse", FEATURE_MOUSE }, + }; + size_t names_len = sizeof(feature_names) / + (sizeof(char *) + sizeof(enum secure_feature)); + + for (int i = 1; i < argc; ++i) { + size_t j; + for (j = 0; j < names_len; ++j) { + if (strcmp(feature_names[j].name, argv[i]) == 0) { + break; + } + } + if (j == names_len) { + *error = cmd_results_new(CMD_INVALID, + "permit", "Invalid feature grant %s", argv[i]); + return 0; + } + features |= feature_names[j].feature; + } + return features; +} + +static struct feature_policy *get_policy(const char *name) { + struct feature_policy *policy = NULL; + for (int i = 0; i < config->feature_policies->length; ++i) { + struct feature_policy *p = config->feature_policies->items[i]; + if (strcmp(p->program, name) == 0) { + policy = p; + break; + } + } + if (!policy) { + policy = alloc_feature_policy(name); + list_add(config->feature_policies, policy); + } + return policy; +} + +struct cmd_results *cmd_permit(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "permit", EXPECTED_MORE_THAN, 1))) { + return error; + } + + struct feature_policy *policy = get_policy(argv[0]); + policy->features |= get_features(argc, argv, &error); + + if (error) { + return error; + } + + sway_log(L_DEBUG, "Permissions granted to %s for features %d", + policy->program, policy->features); + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} + +struct cmd_results *cmd_reject(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "reject", EXPECTED_MORE_THAN, 1))) { + return error; + } + + struct feature_policy *policy = get_policy(argv[0]); + policy->features &= ~get_features(argc, argv, &error); + + if (error) { + return error; + } + + sway_log(L_DEBUG, "Permissions granted to %s for features %d", + policy->program, policy->features); + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/security.c b/sway/security.c index 00e5e8d7..776bd527 100644 --- a/sway/security.c +++ b/sway/security.c @@ -4,6 +4,13 @@ #include "sway/security.h" #include "log.h" +struct feature_policy *alloc_feature_policy(const char *program) { + struct feature_policy *policy = malloc(sizeof(struct feature_policy)); + policy->program = strdup(program); + policy->features = FEATURE_FULLSCREEN | FEATURE_KEYBOARD | FEATURE_MOUSE; + return policy; +} + enum secure_feature get_feature_policy(pid_t pid) { const char *fmt = "/proc/%d/exe"; int pathlen = snprintf(NULL, 0, fmt, pid); -- cgit v1.2.3 From 3dbeb9c35cd3cd71b318370b776bdaa00436a356 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 2 Dec 2016 10:05:43 -0500 Subject: Add sway-security(7) --- config.d/security.in | 3 +- sway/CMakeLists.txt | 1 + sway/sway-security.7.txt | 229 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 231 insertions(+), 2 deletions(-) create mode 100644 sway/sway-security.7.txt (limited to 'config.d') diff --git a/config.d/security.in b/config.d/security.in index f59b2980..a1efb98f 100644 --- a/config.d/security.in +++ b/config.d/security.in @@ -28,10 +28,9 @@ ipc { output enabled mode enabled window enabled - bar-config enabled - binding enabled modifier enabled input enabled + binding disabled } } diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index 9349c30d..89388220 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt @@ -73,3 +73,4 @@ add_manpage(sway 1) add_manpage(sway 5) add_manpage(sway-input 5) add_manpage(sway-bar 5) +add_manpage(sway-security 7) diff --git a/sway/sway-security.7.txt b/sway/sway-security.7.txt new file mode 100644 index 00000000..f3d4a229 --- /dev/null +++ b/sway/sway-security.7.txt @@ -0,0 +1,229 @@ +///// +vim:set ts=4 sw=4 tw=82 noet: +///// +sway-security (7) +================= + +Name +---- +sway-security - Guidelines for securing your sway install + +Security Overview +----------------- + +**Sway is NOT secure**. We are working on it but do not trust that we have it all +figured out yet. The following man page is provisional. + +Securing sway requires careful configuration of your environment, the sort that's +usually best suited to a distro maintainer who wants to ship a secure sway +environment in their distro. Sway provides a number of means of securing it but +you must make a few changes external to sway first. + +Configuration security +---------------------- + +Many of Sway's security features are configurable. It's important that a possibly +untrusted program is not able to edit this. Security rules are kept in +_/etc/sway/config.d/security_ (usually), which should only be writable by root. +However, configuration of security rules is not limited to this file - any config +file that sway loads (including i.e. _~/.config/sway/config_) should not be editable +by the user you intend to run programs as. One simple strategy is to use +/etc/sway/config instead of a config file in your home directory, but that doesn't +work well for multi-user systems. A more robust strategy is to run untrusted +programs as another user, or in a sandbox. Configuring this is up to you. + +Note that _/etc/sway/config.d/*_ must be included explicitly from your config file. +This is done by default in /etc/sway/config but you must check your own config if +you choose to place it in other locations. + +Environment security +-------------------- + +LD_PRELOAD is a mechanism designed by GNU for the purpose of ruining the security +of your system. One of the many ways LD_PRELOAD kills security is by making +Wayland keyloggers possible. + +There are a number of strategies for dealing with this but they all suck a little. +In order of most practical to least practical: + +1. Only run important programs via exec. Sway's exec command will ensure that + LD_PRELOAD is unset when running programs. + +2. Remove LD_PRELOAD support from your dynamic loader (requires patching libc). + This may break programs that rely on LD_PRELOAD for legitimate functionality, + but this is the most effective solution. + +3. Use static linking for important programs. Of course statically linked programs + are unaffected by the security dumpster fire that is dynamic linking. + +Note that should you choose method 1, you MUST ensure that sway itself isn't +compromised by LD_PRELOAD. It probably isn't, but you can be sure by setting +/usr/bin/sway to a+s (setuid), which will instruct the dynamic linker not to +permit LD_PRELOAD for it (and will also run it as root, which sway will shortly +drop). You could also statically link sway itself. + +Read your log +------------- + +Sway does sanity checks and prints big red warnings to stderr if they fail. Read +them. + +Feature policies +---------------- + +Certain sway features are security sensitive and may be configured with security +policies. These features are: + +**background**:: + Permission for a program to become the background. + +**fullscreen**:: + Permission to become fullscreen. Note that users can always make a window + fullscreen themselves with the fullscreen command. + +**keyboard**:: + Permission to receive keyboard events. + +**lock**:: + Permission for a program to act as a screen locker. This involves becoming + fullscreen (on all outputs) and accepting all keyboard and mouse input for the + duration of the process. + +**mouse**:: + Permission to receive mouse events. + +**panel**:: + Permission for a program to stick its windows to the sides of the screen. + +**screenshot**:: + Permission to take screenshots or record the screen. + +By default, all programs are granted **fullscreen**, **keyboard**, and **mouse** +permissions. You can use the following config commands to control a program's +access: + +**permit** :: + Permits to use (each feature seperated by a space). + may be * to affect the default policy. + +**reject** :: + Disallows from using (each feature seperated by a space). + may be * to affect the default policy. + +Note that policy enforcement requires procfs to be mounted at /proc and the sway +process to be able to access _/proc/[pid]/exe_ (see **procfs(5)** for details on +this access - setcap cap_sys_ptrace=eip /usr/bin/sway should do the trick). If +sway is unable to read _/proc/[pid]/exe_, it will apply the default policy. + +Command policies +---------------- + +You can also control the context from which a command may execute. The different +contexts you can control are: + +**config**:: + Can be run from your config file. + +**binding**:: + Can be run from bindsym or bindcode commands. + +**ipc**:: + Can be run by IPC clients. + +**criteria**:: + Can be run when evaluating window criteria. + +By default a command is allowed to execute in any context. To configure this, open +a commands block and fill it with policies: + + commands { + + ... + } + +For example, you could do this to limit the use of the focus command to just +binding and critiera: + + commands { + focus binding criteria + } + +IPC policies +------------ + +By default all programs can connect to IPC for backwards compatability with i3. +However, you can whitelist IPC access like so: + + reject * ipc + permit /usr/bin/swaybar ipc + permit /usr/bin/swaygrab ipc + # etc + +Note that it's suggested you do not enable swaymsg to access IPC if you intend to +secure your IPC socket, because any program could just run swaymsg itself instead +of connecting to IPC directly. + +You can also configure which features of IPC are available with an IPC block: + + ipc { + ... + } + +The following commands are available within this block: + +**bar-config** :: + Controls GET_BAR_CONFIG (required for swaybar to work at all). + +**command** :: + Controls executing sway commands via IPC. + +**inputs** :: + Controls GET_INPUTS (input device information). + +**marks** :: + Controls GET_MARKS. + +**outputs** :: + Controls GET_OUTPUTS. + +**tree** :: + Controls GET_TREE. + +**workspaces** :: + Controls GET_WORKSPACES. + +You can also control which IPC events can be raised with an events block: + + ipc { + events { + ... + } + } + +The following commands are vaild within an ipc events block: + +**binding** :: + Controls keybinding notifications (disabled by default). + +**input** :: + Controls input device hotplugging notifications. + +**mode** :: + Controls output hotplugging notifications. + +**output** :: + Controls output hotplugging notifications. + +**window** :: + Controls window event notifications. + +**workspace** :: + Controls workspace notifications. + +Disabling some of these may cause swaybar to behave incorrectly. + +Authors +------- +Maintained by Drew DeVault , who is assisted by other open +source contributors. For more information about sway development, see +. -- cgit v1.2.3 From 25a4a85a59802d3e437129370945d4b4a662c7b2 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 2 Dec 2016 15:56:36 -0500 Subject: Run config files through sed and install to /etc --- config.d/security.in | 8 ++++---- config.in | 2 +- sway/CMakeLists.txt | 30 +++++++++++++++++++++++++----- swaylock/CMakeLists.txt | 2 +- 4 files changed, 31 insertions(+), 11 deletions(-) (limited to 'config.d') diff --git a/config.d/security.in b/config.d/security.in index a1efb98f..b5690dc7 100644 --- a/config.d/security.in +++ b/config.d/security.in @@ -6,10 +6,10 @@ # installation. # Configures which programs are allowed to use which sway features -permit __PREFIX__/swaylock lock -permit __PREFIX__/swaybar panel -permit __PREFIX__/swaybg background -permit __PREFIX__/swaygrab screenshot +permit __PREFIX__/bin/swaylock lock +permit __PREFIX__/bin/swaybar panel +permit __PREFIX__/bin/swaybg background +permit __PREFIX__/bin/swaygrab screenshot permit * fullscreen keyboard mouse diff --git a/config.in b/config.in index ddd0fec5..3cb0525e 100644 --- a/config.in +++ b/config.in @@ -195,4 +195,4 @@ bar { } } -include __SYSCONFDIR__/etc/sway/config.d/* +include __SYSCONFDIR__/sway/config.d/* diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index 89388220..15fa1720 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt @@ -63,11 +63,31 @@ install( DESTINATION bin COMPONENT runtime ) -install( - FILES ${PROJECT_SOURCE_DIR}/config - DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/sway/ - COMPONENT configuration -) + +add_custom_target(configs ALL) + +function(add_config name source destination) + add_custom_command( + OUTPUT ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${name} + COMMAND sed -r + 's?__PREFIX__?${CMAKE_INSTALL_PREFIX}?g\; s?__SYSCONFDIR__?${CMAKE_INSTALL_FULL_SYSCONFDIR}?g' + ${PROJECT_SOURCE_DIR}/${source}.in > ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${name} + DEPENDS ${PROJECT_SOURCE_DIR}/${source}.in + COMMENT "Generating config file ${source}" + ) + + install( + FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${name} + DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/${destination} + COMPONENT configuration + ) + + add_custom_target(config-${name} DEPENDS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${name}) + add_dependencies(configs config-${name}) +endfunction() + +add_config(config config sway) +add_config(security config.d/security sway/config.d) add_manpage(sway 1) add_manpage(sway 5) diff --git a/swaylock/CMakeLists.txt b/swaylock/CMakeLists.txt index febbd1af..4aec6424 100644 --- a/swaylock/CMakeLists.txt +++ b/swaylock/CMakeLists.txt @@ -42,7 +42,7 @@ install( install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/pam/swaylock - DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/pam.d/ + DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/pam.d/ COMPONENT data ) -- cgit v1.2.3 From e7a764fdf450a8259ddbc17446dd720fa1157b44 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 3 Dec 2016 12:38:42 -0500 Subject: Disallow everything by default And update config.d/security to configure sane defaults --- config.d/security.in | 5 +++-- sway/commands.c | 2 +- sway/security.c | 21 ++++++++++++++++----- sway/sway-security.7.txt | 19 ++++++++++++++----- 4 files changed, 34 insertions(+), 13 deletions(-) (limited to 'config.d') diff --git a/config.d/security.in b/config.d/security.in index b5690dc7..47592b05 100644 --- a/config.d/security.in +++ b/config.d/security.in @@ -6,13 +6,12 @@ # installation. # Configures which programs are allowed to use which sway features +permit * fullscreen keyboard mouse ipc permit __PREFIX__/bin/swaylock lock permit __PREFIX__/bin/swaybar panel permit __PREFIX__/bin/swaybg background permit __PREFIX__/bin/swaygrab screenshot -permit * fullscreen keyboard mouse - # Configures which IPC features are enabled ipc { command enabled @@ -36,6 +35,8 @@ ipc { # Limits the contexts from which certain commands are permitted commands { + * all + fullscreen binding criteria bindsym config exit binding diff --git a/sway/commands.c b/sway/commands.c index 3d8f8c5b..d87d0084 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -524,7 +524,7 @@ struct cmd_results *config_commands_command(char *exec) { } struct cmd_handler *handler = find_handler(cmd, CMD_BLOCK_END); - if (!handler) { + if (!handler && strcmp(cmd, "*") != 0) { char *input = cmd ? cmd : "(empty)"; results = cmd_results_new(CMD_INVALID, input, "Unknown/invalid command"); goto cleanup; diff --git a/sway/security.c b/sway/security.c index 1d236b1d..f16fdd1f 100644 --- a/sway/security.c +++ b/sway/security.c @@ -5,16 +5,25 @@ #include "log.h" struct feature_policy *alloc_feature_policy(const char *program) { + uint32_t default_policy = 0; + for (int i = 0; i < config->feature_policies->length; ++i) { + struct feature_policy *policy = config->feature_policies->items[i]; + if (strcmp(policy->program, "*") == 0) { + default_policy = policy->features; + break; + } + } + struct feature_policy *policy = malloc(sizeof(struct feature_policy)); policy->program = strdup(program); - policy->features = FEATURE_FULLSCREEN | FEATURE_KEYBOARD | FEATURE_MOUSE | FEATURE_IPC; + policy->features = default_policy; return policy; } struct command_policy *alloc_command_policy(const char *command) { struct command_policy *policy = malloc(sizeof(struct command_policy)); policy->command = strdup(command); - policy->context = CONTEXT_ALL; + policy->context = 0; return policy; } @@ -25,8 +34,7 @@ enum secure_feature get_feature_policy(pid_t pid) { snprintf(path, pathlen + 1, fmt, pid); static char link[2048]; - enum secure_feature default_policy = - FEATURE_FULLSCREEN | FEATURE_KEYBOARD | FEATURE_MOUSE; + uint32_t default_policy = 0; ssize_t len = readlink(path, link, sizeof(link)); if (len < 0) { @@ -53,10 +61,13 @@ enum secure_feature get_feature_policy(pid_t pid) { } enum command_context get_command_policy(const char *cmd) { - enum command_context default_policy = CONTEXT_ALL; + uint32_t default_policy = 0; for (int i = 0; i < config->command_policies->length; ++i) { struct command_policy *policy = config->command_policies->items[i]; + if (strcmp(policy->command, "*") == 0) { + default_policy = policy->context; + } if (strcmp(policy->command, cmd) == 0) { return policy->context; } diff --git a/sway/sway-security.7.txt b/sway/sway-security.7.txt index 53c7b876..9a2581b1 100644 --- a/sway/sway-security.7.txt +++ b/sway/sway-security.7.txt @@ -124,8 +124,14 @@ To work correctly, sway's own programs require the following permissions: - swaybg: background - swaylock: lock, keyboard -- swaybar: panel, mouse -- swaygrab: screenshot +- swaybar: panel, mouse, ipc +- swaygrab: screenshot, ipc + +When you first declare a policy for an executable, it will inherit the default +policy. Further changes to the default policy will not retroactively affect which +permissions an earlier policy inherits. You must explicitly reject any features +from the default policy that you do not want an executable to receive permission +for. Command policies ---------------- @@ -145,6 +151,9 @@ contexts you can control are: **criteria**:: Can be run when evaluating window criteria. +**all**:: + Shorthand for granting permission in all contexts. + By default a command is allowed to execute in any context. To configure this, open a commands block and fill it with policies: @@ -160,13 +169,13 @@ binding and critiera: focus binding criteria } +Setting a command policy overwrites any previous policy that was in place. + IPC policies ------------ -By default all programs can connect to IPC for backwards compatability with i3. -However, you can whitelist IPC access like so: +You may whitelist IPC access like so: - reject * ipc permit /usr/bin/swaybar ipc permit /usr/bin/swaygrab ipc # etc -- cgit v1.2.3