diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2011-05-10 02:42:17 +0200 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2011-05-10 02:42:17 +0200 |
commit | 1bc2695744c729804af32d48ce68854cba4de8f7 (patch) | |
tree | e4c165bc0bba244437c462247fd7ffcd842c0918 /sysdep/unix/main.c | |
parent | 46bb7e0d176a4dc0a47bb406988f92fb29cceaf4 (diff) |
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.
Diffstat (limited to 'sysdep/unix/main.c')
-rw-r--r-- | sysdep/unix/main.c | 83 |
1 files changed, 81 insertions, 2 deletions
diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c index fd921ace..744062b4 100644 --- a/sysdep/unix/main.c +++ b/sysdep/unix/main.c @@ -8,11 +8,15 @@ #undef LOCAL_DEBUG +#define _GNU_SOURCE 1 + #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <signal.h> +#include <pwd.h> +#include <grp.h> #include "nest/bird.h" #include "lib/lists.h" @@ -59,6 +63,29 @@ async_dump(void) } /* + * 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 <config-file>] [-d] [-D <debug-file>] [-p] [-s <control-socket>]\n", bird_name); + fprintf(stderr, "Usage: %s [-c <config-file>] [-d] [-D <debug-file>] [-p] [-s <control-socket>] [-u <user>] [-g <group>]\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); |