Update and document the privilege restriction.

This commit is contained in:
Ondrej Zajicek 2011-05-15 16:29:44 +02:00
parent 1bc2695744
commit e8b89a6104
3 changed files with 69 additions and 15 deletions

View file

@ -145,10 +145,42 @@ options. The most important ones are:
<tag>-s <m/name of communication socket/</tag> <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>. 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> </descrip>
<p>BIRD writes messages about its work to log files or syslog (according to config). <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 <chapt>About routing tables
<p>BIRD has one or more routing tables which may or may not be <p>BIRD has one or more routing tables which may or may not be

View file

@ -48,15 +48,20 @@ drop_uid(uid_t uid)
CAP_TO_MASK(CAP_NET_ADMIN) | CAP_TO_MASK(CAP_NET_ADMIN) |
CAP_TO_MASK(CAP_NET_RAW); 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) if (seteuid(uid) < 0)
die("seteuid: %m"); die("seteuid: %m");
/* restrict the capabilities */
if (set_capabilities(caps) < 0) if (set_capabilities(caps) < 0)
die("capset: %m"); die("capset: %m");
/* keep the capabilities after dropping root ID */
if (prctl(PR_SET_KEEPCAPS, 1) < 0) if (prctl(PR_SET_KEEPCAPS, 1) < 0)
die("prctl: %m"); die("prctl: %m");
/* completely switch to the unprivileged user ID */
if (setresuid(uid, uid, uid) < 0) if (setresuid(uid, uid, uid) < 0)
die("setresuid: %m"); die("setresuid: %m");
} }

View file

@ -383,7 +383,7 @@ cli_connect(sock *s, int size UNUSED)
} }
static void static void
cli_init_unix(void) cli_init_unix(uid_t use_uid, gid_t use_gid)
{ {
sock *s; sock *s;
@ -393,6 +393,13 @@ cli_init_unix(void)
s->rx_hook = cli_connect; s->rx_hook = cli_connect;
s->rbsize = 1024; s->rbsize = 1024;
sk_open_unix(s, path_control_socket); 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; struct passwd *pw;
char *endptr; char *endptr;
long int rv;
if (!s)
return 0;
errno = 0; errno = 0;
long int rv = strtol(s, &endptr, 10); rv = strtol(s, &endptr, 10);
if (!errno && !*endptr) if (!errno && !*endptr)
return rv; return rv;
@ -522,9 +533,13 @@ get_gid(const char *s)
{ {
struct group *gr; struct group *gr;
char *endptr; char *endptr;
long int rv;
if (!s)
return 0;
errno = 0; errno = 0;
long int rv = strtol(s, &endptr, 10); rv = strtol(s, &endptr, 10);
if (!errno && !*endptr) if (!errno && !*endptr)
return rv; return rv;
@ -601,24 +616,26 @@ main(int argc, char **argv)
log_init_debug(""); log_init_debug("");
log_switch(debug_flag, NULL, NULL); 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(); resource_init();
olock_init(); olock_init();
io_init(); io_init();
rt_init(); rt_init();
if_init(); if_init();
uid_t use_uid = get_uid(use_user);
gid_t use_gid = get_gid(use_group);
if (!parse_and_exit) 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(); protos_build();
proto_build(&proto_unix_kernel); proto_build(&proto_unix_kernel);