diff --git a/doc/manual/conf-file.xml b/doc/manual/conf-file.xml
index 29f7f9c51..6af4c7765 100644
--- a/doc/manual/conf-file.xml
+++ b/doc/manual/conf-file.xml
@@ -479,6 +479,48 @@ flag, e.g. --option gc-keep-outputs false.
+ trusted-users
+
+
+
+ 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 @; for instance,
+ @wheel means all users in the
+ wheel group. The default is
+ root.
+
+ 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.
+
+
+
+
+
+
+ allowed-users
+
+
+
+ A list of names of users (separated by whitespace) that
+ are allowed to connect to the Nix daemon. As with the
+ option, you can specify groups by
+ prefixing them with @. Also, you can allow
+ all users by specifying *. The default is
+ *.
+
+ Note that trusted users are always allowed to connect.
+
+
+
+
+
+
diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc
index 60bc1dba1..2bfebb77a 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 8dd59a9c7..f1748336f 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 fd030fe47..dde501d30 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
+
#include
#include
#include
@@ -18,6 +20,7 @@
#include
#include
#include
+#include
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);
- printMsg(lvlInfo, format("accepted connection from pid %1%, user %2%") % clientPid % user);
+ 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((string) "accepted connection from pid %1%, user %2%"
+ + (trusted ? " (trusted)" : "")) % clientPid % user);
#endif
/* Fork a child to handle the connection. */