diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2011-05-15 16:29:44 +0200 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2011-05-15 16:29:44 +0200 |
commit | e8b89a610443f32b901801668cbae634e13f3e68 (patch) | |
tree | ee0f68cc90ad6df6c2d44fa8a9cca2fc449c0071 | |
parent | 1bc2695744c729804af32d48ce68854cba4de8f7 (diff) |
Update and document the privilege restriction.
-rw-r--r-- | doc/bird.sgml | 32 | ||||
-rw-r--r-- | sysdep/linux/syspriv.h | 5 | ||||
-rw-r--r-- | sysdep/unix/main.c | 47 |
3 files changed, 69 insertions, 15 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml index 31b2c03f..01e70e82 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -145,10 +145,42 @@ options. The most important ones are: <tag>-s <m/name of communication socket/</tag> use given filename for a socket for communications with the client, default is <it/prefix/<file>/var/run/bird.ctl</file>. + + <tag>-u <m/user/</tag> + drop privileges and use that user ID, see the next section for details. + + <tag>-g <m/group/</tag> + use that group ID, see the next section for details. </descrip> <p>BIRD writes messages about its work to log files or syslog (according to config). +<sect>Privileges + +<p>BIRD, as a routing daemon, uses several privileged operations (like +setting routing table and using raw sockets). Traditionally, BIRD is +executed and runs with root privileges, which may be prone to security +problems. The recommended way is to use a privilege restriction +(options <cf/-u/, <cf/-g/). In that case BIRD is executed with root +privileges, but it changes its user and group ID to an unprivileged +ones, while using Linux capabilities to retain just required +privileges (capabilities CAP_NET_*). Note that the control socket is +created before the privileges are dropped, but the config file is read +after that. The privilege restriction is not implemented in BSD port +of BIRD. + +<p>A nonprivileged user (as an argument to <cf/-u/ options) may be the +user <cf/nobody/, but it is suggested to use a new dedicated user +account (like <cf/bird/). The similar considerations apply for +the group option, but there is one more condition -- the users +in the same group can use <file/birdc/ to control BIRD. + +<p>Finally, there is a possibility to use external tools to run BIRD in +an environment with restricted privileges. This may need some +configuration, but it is generally easy -- BIRD needs just the +standard library, privileges to read the config file and create the +control socket and the CAP_NET_* capabilities. + <chapt>About routing tables <p>BIRD has one or more routing tables which may or may not be diff --git a/sysdep/linux/syspriv.h b/sysdep/linux/syspriv.h index bfe19ac3..b2cdde85 100644 --- a/sysdep/linux/syspriv.h +++ b/sysdep/linux/syspriv.h @@ -48,15 +48,20 @@ drop_uid(uid_t uid) CAP_TO_MASK(CAP_NET_ADMIN) | CAP_TO_MASK(CAP_NET_RAW); + /* change effective user ID to be able to switch to that + user ID completely after dropping CAP_SETUID */ if (seteuid(uid) < 0) die("seteuid: %m"); + /* restrict the capabilities */ if (set_capabilities(caps) < 0) die("capset: %m"); + /* keep the capabilities after dropping root ID */ if (prctl(PR_SET_KEEPCAPS, 1) < 0) die("prctl: %m"); + /* completely switch to the unprivileged user ID */ if (setresuid(uid, uid, uid) < 0) die("setresuid: %m"); } diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c index 744062b4..610d207d 100644 --- a/sysdep/unix/main.c +++ b/sysdep/unix/main.c @@ -383,7 +383,7 @@ cli_connect(sock *s, int size UNUSED) } static void -cli_init_unix(void) +cli_init_unix(uid_t use_uid, gid_t use_gid) { sock *s; @@ -393,6 +393,13 @@ cli_init_unix(void) s->rx_hook = cli_connect; s->rbsize = 1024; sk_open_unix(s, path_control_socket); + + if (use_uid || use_gid) + if (chown(path_control_socket, use_uid, use_gid) < 0) + die("chown: %m"); + + if (chmod(path_control_socket, 0660) < 0) + die("chmod: %m"); } /* @@ -503,9 +510,13 @@ get_uid(const char *s) { struct passwd *pw; char *endptr; - + long int rv; + + if (!s) + return 0; + errno = 0; - long int rv = strtol(s, &endptr, 10); + rv = strtol(s, &endptr, 10); if (!errno && !*endptr) return rv; @@ -522,9 +533,13 @@ get_gid(const char *s) { struct group *gr; char *endptr; + long int rv; + + if (!s) + return 0; errno = 0; - long int rv = strtol(s, &endptr, 10); + rv = strtol(s, &endptr, 10); if (!errno && !*endptr) return rv; @@ -601,24 +616,26 @@ 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); - - DBG("Initializing.\n"); resource_init(); olock_init(); io_init(); rt_init(); if_init(); + uid_t use_uid = get_uid(use_user); + gid_t use_gid = get_gid(use_group); + if (!parse_and_exit) - cli_init_unix(); + { + test_old_bird(path_control_socket); + cli_init_unix(use_uid, use_gid); + } + + if (use_gid) + drop_gid(use_gid); + + if (use_uid) + drop_uid(use_uid); protos_build(); proto_build(&proto_unix_kernel); |