* Move setuid stuff to libutil.
* Install libexpr header files.
This commit is contained in:
		
							parent
							
								
									e5a6c09b12
								
							
						
					
					
						commit
						bafc1690fc
					
				
					 4 changed files with 146 additions and 142 deletions
				
			
		|  | @ -850,4 +850,140 @@ bool string2Int(const string & s, int & n) | |||
| } | ||||
| 
 | ||||
|   | ||||
| //////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| 
 | ||||
| static bool haveSwitched; | ||||
| static uid_t savedUid, nixUid; | ||||
| static gid_t savedGid, nixGid; | ||||
| 
 | ||||
| 
 | ||||
| #if HAVE_SETRESUID | ||||
| #define _setuid(uid) setresuid(uid, uid, savedUid) | ||||
| #define _setgid(gid) setresgid(gid, gid, savedGid) | ||||
| #else | ||||
| /* Only works properly when run by root. */ | ||||
| #define _setuid(uid) setuid(uid) | ||||
| #define _setgid(gid) setgid(gid) | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| SwitchToOriginalUser::SwitchToOriginalUser() | ||||
| { | ||||
| #if SETUID_HACK && HAVE_SETRESUID | ||||
|     /* Temporarily switch the effective uid/gid back to the saved
 | ||||
|        uid/gid (which is the uid/gid of the user that executed the Nix | ||||
|        program; it's *not* the real uid/gid, since we changed that to | ||||
|        the Nix user in switchToNixUser()). */ | ||||
|     if (haveSwitched) { | ||||
|         if (setuid(savedUid) == -1) | ||||
|             throw SysError(format("temporarily restoring uid to `%1%'") % savedUid);  | ||||
|         if (setgid(savedGid) == -1) | ||||
|             throw SysError(format("temporarily restoring gid to `%1%'") % savedGid);  | ||||
|     } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| SwitchToOriginalUser::~SwitchToOriginalUser() | ||||
| { | ||||
| #if SETUID_HACK && HAVE_SETRESUID | ||||
|     /* Switch the effective uid/gid back to the Nix user. */ | ||||
|     if (haveSwitched) { | ||||
|         if (setuid(nixUid) == -1) | ||||
|             throw SysError(format("restoring uid to `%1%'") % nixUid);  | ||||
|         if (setgid(nixGid) == -1) | ||||
|             throw SysError(format("restoring gid to `%1%'") % nixGid);  | ||||
|     } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void switchToNixUser() | ||||
| { | ||||
| #if SETUID_HACK | ||||
| 
 | ||||
|     /* Don't do anything if this is not a setuid binary. */ | ||||
|     if (getuid() == geteuid() && getgid() == getegid()) return; | ||||
| 
 | ||||
|     /* Here we set the uid and gid to the Nix user and group,
 | ||||
|        respectively, IF the current (real) user is a member of the Nix | ||||
|        group.  Otherwise we just drop all privileges. */ | ||||
|      | ||||
|     /* Lookup the Nix gid. */ | ||||
|     struct group * gr = getgrnam(NIX_GROUP); | ||||
|     if (!gr) { | ||||
|         cerr << format("missing group `%1%'\n") % NIX_GROUP; | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     /* Get the supplementary group IDs for the current user. */ | ||||
|     int maxGids = 512, nrGids; | ||||
|     gid_t gids[maxGids]; | ||||
|     if ((nrGids = getgroups(maxGids, gids)) == -1) { | ||||
|         cerr << format("unable to query gids\n"); | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     /* !!! Apparently it is unspecified whether getgroups() includes
 | ||||
|        the effective gid.  In that case the following test is always | ||||
|        true *if* the program is installed setgid (which we do when we | ||||
|        have setresuid()).  On Linux this doesn't appear to be the | ||||
|        case, but we should switch to the real gid before doing this | ||||
|        test, and then switch back to the saved gid. */  | ||||
| 
 | ||||
|     /* Check that the current user is a member of the Nix group. */ | ||||
|     bool found = false; | ||||
|     for (int i = 0; i < nrGids; ++i) | ||||
|         if (gids[i] == gr->gr_gid) { | ||||
|             found = true; | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|     if (!found) { | ||||
|         /* Not in the Nix group - drop all root/Nix privileges. */ | ||||
|         _setgid(getgid()); | ||||
|         _setuid(getuid()); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     savedUid = getuid(); | ||||
|     savedGid = getgid(); | ||||
| 
 | ||||
|     /* Set the real, effective and saved gids to gr->gr_gid.  Also
 | ||||
|        make very sure that this succeeded.  We switch the gid first | ||||
|        because we cannot do it after we have dropped root uid. */ | ||||
|     nixGid = gr->gr_gid; | ||||
|     if (_setgid(nixGid) != 0 || getgid() != nixGid || getegid() != nixGid) { | ||||
|         cerr << format("unable to set gid to `%1%'\n") % NIX_GROUP; | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     /* Lookup the Nix uid. */ | ||||
|     struct passwd * pw = getpwnam(NIX_USER); | ||||
|     if (!pw) { | ||||
|         cerr << format("missing user `%1%'\n") % NIX_USER; | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     /* This will drop all root privileges, setting the real, effective
 | ||||
|        and saved uids to pw->pw_uid.  Also make very sure that this | ||||
|        succeeded.*/ | ||||
|     nixUid = pw->pw_uid; | ||||
|     if (_setuid(nixUid) != 0 || getuid() != nixUid || geteuid() != nixUid) { | ||||
|         cerr << format("unable to set uid to `%1%'\n") % NIX_USER; | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     /* !!! for setuid operation, we should: 1) wipe the environment;
 | ||||
|        2) verify file descriptors 0, 1, 2; 3) etc. | ||||
|        See: http://www.daemon-systems.org/man/setuid.7.html
 | ||||
|     */ | ||||
| 
 | ||||
|     haveSwitched = true; | ||||
|      | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue