diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2014-07-17 16:57:07 +0200 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2014-07-17 16:57:07 +0200 |
commit | 049c0eb49c621ae50f49c8a06dc6c3a9839ef388 (patch) | |
tree | 63c0f299510adda0e21c7d323917eefcd5e1f6ce | |
parent | 0c730887c4ec4a03fb854490e422c134a1bf8139 (diff) | |
download | guix-049c0eb49c621ae50f49c8a06dc6c3a9839ef388.tar.gz |
nix-daemon: Add trusted-users and allowed-users options
‘trusted-users’ is a list of users and groups that have elevated rights, such as the ability to specify binary caches. It defaults to ‘root’. A typical value would be ‘@wheel’ to specify all users in the wheel group. ‘allowed-users’ is a list of users and groups that are allowed to connect to the daemon. It defaults to ‘*’. A typical value would be ‘@users’ to specify the ‘users’ group.
-rw-r--r-- | doc/manual/conf-file.xml | 42 | ||||
-rw-r--r-- | src/libstore/globals.cc | 4 | ||||
-rw-r--r-- | src/libstore/globals.hh | 9 | ||||
-rw-r--r-- | src/nix-daemon/nix-daemon.cc | 38 |
4 files changed, 90 insertions, 3 deletions
diff --git a/doc/manual/conf-file.xml b/doc/manual/conf-file.xml index 29f7f9c51a..6af4c77654 100644 --- a/doc/manual/conf-file.xml +++ b/doc/manual/conf-file.xml @@ -479,6 +479,48 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para> </varlistentry> + <varlistentry xml:id="conf-trusted-users"><term><literal>trusted-users</literal></term> + + <listitem> + + <para>A list of names of users (separated by whitespace) that + have additional rights when connecting to the Nix daemon, such + as the ability to specify additional binary caches, or to import + unsigned NARs. You can also specify groups by prefixing them + with <literal>@</literal>; for instance, + <literal>@wheel</literal> means all users in the + <literal>wheel</literal> group. The default is + <literal>root</literal>.</para> + + <warning><para>The users listed here have the ability to + compromise the security of a multi-user Nix store. For instance, + they could install Trojan horses subsequently executed by other + users. So you should consider carefully whether to add users to + this list.</para></warning> + + </listitem> + + </varlistentry> + + + <varlistentry xml:id="conf-allowed-users"><term><literal>allowed-users</literal></term> + + <listitem> + + <para>A list of names of users (separated by whitespace) that + are allowed to connect to the Nix daemon. As with the + <option>trusted-users</option> option, you can specify groups by + prefixing them with <literal>@</literal>. Also, you can allow + all users by specifying <literal>*</literal>. The default is + <literal>*</literal>.</para> + + <para>Note that trusted users are always allowed to connect.</para> + + </listitem> + + </varlistentry> + + </variablelist> </para> diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 60bc1dba13..2bfebb77a1 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -63,6 +63,8 @@ Settings::Settings() lockCPU = getEnv("NIX_AFFINITY_HACK", "1") == "1"; showTrace = false; enableImportNative = false; + trustedUsers = Strings({"root"}); + allowedUsers = Strings({"*"}); } @@ -152,6 +154,8 @@ void Settings::update() get(logServers, "log-servers"); get(enableImportNative, "allow-unsafe-native-code-during-evaluation"); get(useCaseHack, "use-case-hack"); + get(trustedUsers, "trusted-users"); + get(allowedUsers, "allowed-users"); string subs = getEnv("NIX_SUBSTITUTERS", "default"); if (subs == "default") { diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index 8dd59a9c79..f1748336fd 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -203,6 +203,15 @@ struct Settings { /* Whether the importNative primop should be enabled */ bool enableImportNative; + /* List of users that have elevated rights in the Nix daemon, such + as the ability to specify additional binary caches, or to + import unsigned NARs. */ + Strings trustedUsers; + + /* List of users that are allowed to connect to the daemon, in + addition to the trusted users. These have normal rights. */ + Strings allowedUsers; + private: SettingsMap settings, overrides; diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc index fd030fe476..dde501d309 100644 --- a/src/nix-daemon/nix-daemon.cc +++ b/src/nix-daemon/nix-daemon.cc @@ -7,6 +7,8 @@ #include "affinity.hh" #include "globals.hh" +#include <algorithm> + #include <cstring> #include <unistd.h> #include <signal.h> @@ -18,6 +20,7 @@ #include <fcntl.h> #include <errno.h> #include <pwd.h> +#include <grp.h> using namespace nix; @@ -451,7 +454,7 @@ static void performOp(bool trusted, unsigned int clientVersion, case wopImportPaths: { startWork(); TunnelSource source(from); - Paths paths = store->importPaths(true, source); + Paths paths = store->importPaths(!trusted, source); stopWork(); writeStrings(paths, to); break; @@ -770,6 +773,27 @@ static void setSigChldAction(bool autoReap) } +bool matchUser(const string & user, const string & group, const Strings & users) +{ + if (find(users.begin(), users.end(), "*") != users.end()) + return true; + + if (find(users.begin(), users.end(), user) != users.end()) + return true; + + for (auto & i : users) + if (string(i, 0, 1) == "@") { + if (group == string(i, 1)) return true; + struct group * gr = getgrnam(i.c_str() + 1); + if (!gr) continue; + for (char * * mem = gr->gr_mem; *mem; mem++) + if (user == string(*mem)) return true; + } + + return false; +} + + #define SD_LISTEN_FDS_START 3 @@ -870,9 +894,17 @@ static void daemonLoop() struct passwd * pw = getpwuid(cred.uid); string user = pw ? pw->pw_name : int2String(cred.uid); - if (cred.uid == 0) trusted = true; + struct group * gr = getgrgid(cred.gid); + string group = gr ? gr->gr_name : int2String(cred.gid); + + if (matchUser(user, group, settings.trustedUsers)) + trusted = true; + + if (!trusted && !matchUser(user, group, settings.allowedUsers)) + throw Error(format("user `%1%' is not allowed to connect to the Nix daemon") % user); - printMsg(lvlInfo, format("accepted connection from pid %1%, user %2%") % clientPid % user); + printMsg(lvlInfo, format((string) "accepted connection from pid %1%, user %2%" + + (trusted ? " (trusted)" : "")) % clientPid % user); #endif /* Fork a child to handle the connection. */ |