summaryrefslogtreecommitdiff
path: root/sysdep/unix
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2011-05-10 02:42:17 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2011-05-10 02:42:17 +0200
commit1bc2695744c729804af32d48ce68854cba4de8f7 (patch)
treee4c165bc0bba244437c462247fd7ffcd842c0918 /sysdep/unix
parent46bb7e0d176a4dc0a47bb406988f92fb29cceaf4 (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')
-rw-r--r--sysdep/unix/main.c83
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);