aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorflu0r1ne <flu0r1ne@flu0r1ne.net>2023-11-20 16:29:36 -0600
committerflu0r1ne <flu0r1ne@flu0r1ne.net>2023-11-20 16:29:36 -0600
commitde259f866554bf8ea815b028af564155a2eee2b5 (patch)
tree7b0992d63b3bcb5794382a341b4cf09e2ef24bc5
parentd028778c1c132cf6691837ef5076f4dd5b5c5c82 (diff)
downloadwg2nd-de259f866554bf8ea815b028af564155a2eee2b5.tar.xz
wg2nd-de259f866554bf8ea815b028af564155a2eee2b5.zip
Drop capabilities by default and retain required capabilities upfront
-rw-r--r--makefile3
-rw-r--r--src/main.cpp73
2 files changed, 74 insertions, 2 deletions
diff --git a/makefile b/makefile
index eb34c1b..5eaa730 100644
--- a/makefile
+++ b/makefile
@@ -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") {