* Verify that the desired target user is in the build users group (as
specified in the setuid config file).
This commit is contained in:
		
							parent
							
								
									f07ac41656
								
							
						
					
					
						commit
						62ab131412
					
				
					 1 changed files with 43 additions and 10 deletions
				
			
		|  | @ -17,7 +17,10 @@ | |||
| using namespace nix; | ||||
| 
 | ||||
| 
 | ||||
| static void secureChown(uid_t uidTarget, gid_t gidTarget, | ||||
| /* Recursively change the ownership of `path' from `uidFrom' to
 | ||||
|    `uidTo' and `gidTo'.  Barf if we encounter a file not owned by | ||||
|    `uidFrom'. */ | ||||
| static void secureChown(uid_t uidFrom, uid_t uidTo, gid_t gidTo, | ||||
|     const Path & path) | ||||
| { | ||||
|     /* Recursively chown `path' to the specified uid and gid, but only
 | ||||
|  | @ -35,24 +38,53 @@ static uid_t nameToUid(const string & userName) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void runBuilder(const string & targetUser, | ||||
| /* Run `program' under user account `targetUser'.  `targetUser' should
 | ||||
|    be a member of `buildUsersGroup'.  The ownership of the current | ||||
|    directory is changed from the Nix user (uidNix) to the target | ||||
|    user. */ | ||||
| static void runBuilder(uid_t uidNix, | ||||
|     const string & buildUsersGroup, const string & targetUser, | ||||
|     string program, int argc, char * * argv) | ||||
| { | ||||
|     uid_t uidTargetUser = nameToUid(targetUser); | ||||
|     gid_t gidBuilders = 1234; | ||||
| 
 | ||||
|     /* Sanity check. */ | ||||
|     if (uidTargetUser == 0) | ||||
|         throw Error("won't setuid to root"); | ||||
| 
 | ||||
|     /* Get the gid and members of buildUsersGroup. */ | ||||
|     struct group * gr = getgrnam(buildUsersGroup.c_str()); | ||||
|     if (!gr) | ||||
|         throw Error(format("group `%1%' does not exist") % buildUsersGroup); | ||||
|     gid_t gidBuildUsers = gr->gr_gid; | ||||
| 
 | ||||
|     /* Verify that the target user is a member of that group. */ | ||||
|     Strings users; | ||||
|     bool found = false; | ||||
|     for (char * * p = gr->gr_mem; *p; ++p) | ||||
|         if (string(*p) == targetUser) { | ||||
|             found = true; | ||||
|             break; | ||||
|         } | ||||
|     if (!found) | ||||
|         throw Error(format("user `%1%' is not a member of `%2%'") | ||||
|             % targetUser % buildUsersGroup); | ||||
|      | ||||
|     /* Chown the current directory, *if* it is owned by the Nix
 | ||||
|        account.  The idea is that the current directory is the | ||||
|        temporary build directory in /tmp or somewhere else, and we | ||||
|        don't want to create that directory here. */ | ||||
|     secureChown(uidTargetUser, gidBuilders, "."); | ||||
|     secureChown(uidNix, uidTargetUser, gidBuildUsers, "."); | ||||
| 
 | ||||
|                  | ||||
|     /* Set the real, effective and saved gid.  Must be done before
 | ||||
|        setuid(), otherwise it won't set the real and saved gids. */ | ||||
|     if (setgroups(0, 0) == -1) | ||||
|         throw SysError("cannot clear the set of supplementary groups"); | ||||
|     //setgid(gidBuilders);
 | ||||
| 
 | ||||
|     if (setgid(gidBuildUsers) == -1 || | ||||
|         getgid() != gidBuildUsers || | ||||
|         getegid() != gidBuildUsers) | ||||
|         throw SysError("setgid failed"); | ||||
| 
 | ||||
|     /* Set the real, effective and saved uid. */ | ||||
|     if (setuid(uidTargetUser) == -1 || | ||||
|  | @ -116,14 +148,14 @@ static void run(int argc, char * * argv) | |||
|         throw Error(format("parse error in `%1%'") % configFile); | ||||
| 
 | ||||
|     Strings::iterator i = tokens.begin(); | ||||
|     string allowedUser = *i++; | ||||
|     string nixUser = *i++; | ||||
|     string buildUsersGroup = *i++; | ||||
| 
 | ||||
| 
 | ||||
|     /* Check that the caller (real uid) is the one allowed to call
 | ||||
|        this program. */ | ||||
|     uid_t uidAllowedUser = nameToUid(allowedUser); | ||||
|     if (uidAllowedUser != getuid()) | ||||
|     uid_t uidNix = nameToUid(nixUser); | ||||
|     if (uidNix != getuid()) | ||||
|         throw Error("you are not allowed to call this program, go away"); | ||||
|      | ||||
|      | ||||
|  | @ -137,7 +169,8 @@ static void run(int argc, char * * argv) | |||
|         /* Syntax: nix-setuid-helper run-builder <username> <program>
 | ||||
|              <args...> */ | ||||
|         if (argc < 4) throw Error("missing user name / program name"); | ||||
|         runBuilder(argv[2], argv[3], argc - 4, argv + 4); | ||||
|         runBuilder(uidNix, buildUsersGroup, | ||||
|             argv[2], argv[3], argc - 4, argv + 4); | ||||
|     } | ||||
| 
 | ||||
|     else if (command == "fix-ownership") { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue