diff options
author | flu0r1ne <flu0r1ne@flu0r1ne.net> | 2023-11-20 16:29:36 -0600 |
---|---|---|
committer | flu0r1ne <flu0r1ne@flu0r1ne.net> | 2023-11-20 16:29:36 -0600 |
commit | de259f866554bf8ea815b028af564155a2eee2b5 (patch) | |
tree | 7b0992d63b3bcb5794382a341b4cf09e2ef24bc5 | |
parent | d028778c1c132cf6691837ef5076f4dd5b5c5c82 (diff) | |
download | wg2nd-de259f866554bf8ea815b028af564155a2eee2b5.tar.xz wg2nd-de259f866554bf8ea815b028af564155a2eee2b5.zip |
Drop capabilities by default and retain required capabilities upfront
-rw-r--r-- | makefile | 3 | ||||
-rw-r--r-- | src/main.cpp | 73 |
2 files changed, 74 insertions, 2 deletions
@@ -12,6 +12,7 @@ CC = gcc CFLAGS = -Wall -Wextra -Werror -Wno-unused-function CFLAGS += -Isrc +CFLAGS += -DHAVE_LIBCAP # Compiler flags CXXFLAGS = $(CFLAGS) @@ -25,7 +26,7 @@ RELEASE_LDFLAGS = -lrt DEBUGFLAGS = -ggdb -O0 -fsanitize=address -fno-omit-frame-pointer # Linking flags -LDFLAGS = +LDFLAGS = -lcap C_OBJECTS := src/crypto/encoding.o C_OBJECTS += src/crypto/curve25519.o diff --git a/src/main.cpp b/src/main.cpp index 8ae37eb..36226c7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,6 +15,12 @@ #include <cstdio> #include <getopt.h> +#ifdef HAVE_LIBCAP + +#include <sys/capability.h> + +#endif /* HAVE_LIBCAP */ + // ===================================== // ERROR HANDING - FROM FCUTILS // ===================================== @@ -253,7 +259,7 @@ SystemdConfig generate_cfg_or_die( std::filesystem::path const & keyfile_or_output_path, std::optional<std::string> const & filename ) { - std::fstream cfg_stream { config_path }; + std::fstream cfg_stream { config_path, std::ios_base::in }; if(!cfg_stream.is_open()) { die("Failed to open config file %s", config_path.string().c_str()); @@ -421,6 +427,60 @@ static int wg2nd_install(char const * prog, int argc, char **argv) { return 0; } +#ifdef HAVE_LIBCAP + +// Drop excess capabilities and ensure the process have proper capabilities upfront +void drop_excess_capabilities(std::vector<cap_value_t> cap_required) { + + cap_t current_cap = cap_get_proc(); + cap_t wanted_cap = cap_get_proc(); + + if(!current_cap || !wanted_cap) { + goto die_cap_failure; + } + + if(cap_clear(wanted_cap)) { + goto die_cap_failure; + } + + // Add required capabilities to the wanted set + for(cap_value_t cap : cap_required) { + cap_flag_value_t is_set; + + // Print nice error message if the user does not have the required permissions + if(cap_get_flag(current_cap, cap, CAP_PERMITTED, &is_set)) { + goto die_cap_failure; + } + + if(is_set != CAP_SET) { + char * name = cap_to_name(cap); + die("Failed to obtain capability \"%s\": do you need to elevate permissions?", name); + } + + if(cap_set_flag(wanted_cap, CAP_PERMITTED, 1, &cap, CAP_SET)) { + goto die_cap_failure; + } + + if(cap_set_flag(wanted_cap, CAP_EFFECTIVE, 1, &cap, CAP_SET)) { + goto die_cap_failure; + } + } + + if(cap_set_proc(wanted_cap)) { + goto die_cap_failure; + } + + if(cap_free(wanted_cap) || cap_free(current_cap)) { + goto die_cap_failure; + } + + return; + +die_cap_failure: + die_errno("Failed to drop capabilities"); +} +#endif /* HAVE_LIBCAP */ + int main(int argc, char **argv) { char const * prog = "wg2nd"; @@ -434,6 +494,17 @@ int main(int argc, char **argv) { std::string action = argv[1]; +#ifdef HAVE_LIBCAP + std::vector<cap_value_t> required_caps; + + if(action == "install") { + required_caps.push_back(CAP_CHOWN); + required_caps.push_back(CAP_DAC_OVERRIDE); + } + + drop_excess_capabilities(required_caps); +#endif /* HAVE_LIBCAP */ + if (action == "generate") { return wg2nd_generate(prog, argc - 1, argv + 1); } else if (action == "install") { |