Update and document the privilege restriction.
This commit is contained in:
parent
1bc2695744
commit
e8b89a6104
3 changed files with 69 additions and 15 deletions
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue