From 1bc2695744c729804af32d48ce68854cba4de8f7 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Tue, 10 May 2011 02:42:17 +0200 Subject: Allows run with restricted privileges. Adds option -u and -g to specify user and group. When different user (than root) is specified, linux capabilities CAP_NET_* are kept. --- sysdep/unix/main.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 2 deletions(-) (limited to 'sysdep/unix') diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c index fd921ac..744062b 100644 --- a/sysdep/unix/main.c +++ b/sysdep/unix/main.c @@ -8,11 +8,15 @@ #undef LOCAL_DEBUG +#define _GNU_SOURCE 1 + #include #include #include #include #include +#include +#include #include "nest/bird.h" #include "lib/lists.h" @@ -58,6 +62,29 @@ async_dump(void) debug("\n"); } +/* + * Dropping privileges + */ + +#ifdef CONFIG_RESTRICTED_PRIVILEGES +#include "lib/syspriv.h" +#else + +static inline void +drop_uid(uid_t uid) +{ + die("Cannot change user on this platform"); +} + +#endif + +static inline void +drop_gid(gid_t gid) +{ + if (setgid(gid) < 0) + die("setgid: %m"); +} + /* * Reading the Configuration */ @@ -444,14 +471,16 @@ signal_init(void) * Parsing of command-line arguments */ -static char *opt_list = "c:dD:ps:"; +static char *opt_list = "c:dD:ps:u:g:"; static int parse_and_exit; char *bird_name; +static char *use_user; +static char *use_group; static void usage(void) { - fprintf(stderr, "Usage: %s [-c ] [-d] [-D ] [-p] [-s ]\n", bird_name); + fprintf(stderr, "Usage: %s [-c ] [-d] [-D ] [-p] [-s ] [-u ] [-g ]\n", bird_name); exit(1); } @@ -469,6 +498,44 @@ get_bird_name(char *s, char *def) return t+1; } +static inline uid_t +get_uid(const char *s) +{ + struct passwd *pw; + char *endptr; + + errno = 0; + long int rv = strtol(s, &endptr, 10); + + if (!errno && !*endptr) + return rv; + + pw = getpwnam(s); + if (!pw) + die("Cannot find user '%s'", s); + + return pw->pw_uid; +} + +static inline gid_t +get_gid(const char *s) +{ + struct group *gr; + char *endptr; + + errno = 0; + long int rv = strtol(s, &endptr, 10); + + if (!errno && !*endptr) + return rv; + + gr = getgrnam(s); + if (!gr) + die("Cannot find group '%s'", s); + + return gr->gr_gid; +} + static void parse_args(int argc, char **argv) { @@ -504,6 +571,12 @@ parse_args(int argc, char **argv) case 's': path_control_socket = optarg; break; + case 'u': + use_user = optarg; + break; + case 'g': + use_group = optarg; + break; default: usage(); } @@ -528,6 +601,12 @@ main(int argc, char **argv) log_init_debug(""); log_switch(debug_flag, NULL, NULL); + if (use_group) + drop_gid(get_gid(use_group)); + + if (use_user) + drop_uid(get_uid(use_user)); + if (!parse_and_exit) test_old_bird(path_control_socket); -- cgit v1.2.3