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.
This commit is contained in:
		
							parent
							
								
									0c730887c4
								
							
						
					
					
						commit
						049c0eb49c
					
				
					 4 changed files with 90 additions and 3 deletions
				
			
		|  | @ -479,6 +479,48 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para> | ||||||
|   </varlistentry> |   </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> | </variablelist> | ||||||
| 
 | 
 | ||||||
| </para> | </para> | ||||||
|  |  | ||||||
|  | @ -63,6 +63,8 @@ Settings::Settings() | ||||||
|     lockCPU = getEnv("NIX_AFFINITY_HACK", "1") == "1"; |     lockCPU = getEnv("NIX_AFFINITY_HACK", "1") == "1"; | ||||||
|     showTrace = false; |     showTrace = false; | ||||||
|     enableImportNative = false; |     enableImportNative = false; | ||||||
|  |     trustedUsers = Strings({"root"}); | ||||||
|  |     allowedUsers = Strings({"*"}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -152,6 +154,8 @@ void Settings::update() | ||||||
|     get(logServers, "log-servers"); |     get(logServers, "log-servers"); | ||||||
|     get(enableImportNative, "allow-unsafe-native-code-during-evaluation"); |     get(enableImportNative, "allow-unsafe-native-code-during-evaluation"); | ||||||
|     get(useCaseHack, "use-case-hack"); |     get(useCaseHack, "use-case-hack"); | ||||||
|  |     get(trustedUsers, "trusted-users"); | ||||||
|  |     get(allowedUsers, "allowed-users"); | ||||||
| 
 | 
 | ||||||
|     string subs = getEnv("NIX_SUBSTITUTERS", "default"); |     string subs = getEnv("NIX_SUBSTITUTERS", "default"); | ||||||
|     if (subs == "default") { |     if (subs == "default") { | ||||||
|  |  | ||||||
|  | @ -203,6 +203,15 @@ struct Settings { | ||||||
|     /* Whether the importNative primop should be enabled */ |     /* Whether the importNative primop should be enabled */ | ||||||
|     bool enableImportNative; |     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: | private: | ||||||
|     SettingsMap settings, overrides; |     SettingsMap settings, overrides; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,6 +7,8 @@ | ||||||
| #include "affinity.hh" | #include "affinity.hh" | ||||||
| #include "globals.hh" | #include "globals.hh" | ||||||
| 
 | 
 | ||||||
|  | #include <algorithm> | ||||||
|  | 
 | ||||||
| #include <cstring> | #include <cstring> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| #include <signal.h> | #include <signal.h> | ||||||
|  | @ -18,6 +20,7 @@ | ||||||
| #include <fcntl.h> | #include <fcntl.h> | ||||||
| #include <errno.h> | #include <errno.h> | ||||||
| #include <pwd.h> | #include <pwd.h> | ||||||
|  | #include <grp.h> | ||||||
| 
 | 
 | ||||||
| using namespace nix; | using namespace nix; | ||||||
| 
 | 
 | ||||||
|  | @ -451,7 +454,7 @@ static void performOp(bool trusted, unsigned int clientVersion, | ||||||
|     case wopImportPaths: { |     case wopImportPaths: { | ||||||
|         startWork(); |         startWork(); | ||||||
|         TunnelSource source(from); |         TunnelSource source(from); | ||||||
|         Paths paths = store->importPaths(true, source); |         Paths paths = store->importPaths(!trusted, source); | ||||||
|         stopWork(); |         stopWork(); | ||||||
|         writeStrings(paths, to); |         writeStrings(paths, to); | ||||||
|         break; |         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 | #define SD_LISTEN_FDS_START 3 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -870,9 +894,17 @@ static void daemonLoop() | ||||||
|             struct passwd * pw = getpwuid(cred.uid); |             struct passwd * pw = getpwuid(cred.uid); | ||||||
|             string user = pw ? pw->pw_name : int2String(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 | #endif | ||||||
| 
 | 
 | ||||||
|             /* Fork a child to handle the connection. */ |             /* Fork a child to handle the connection. */ | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue