* 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
				
			
		|  | @ -1,11 +1,12 @@ | ||||||
| pkglib_LTLIBRARIES = libexpr.la | pkglib_LTLIBRARIES = libexpr.la | ||||||
| 
 | 
 | ||||||
| libexpr_la_SOURCES = nixexpr.cc nixexpr.hh \ | libexpr_la_SOURCES = \ | ||||||
|  eval.cc eval.hh primops.cc \ |  nixexpr.cc eval.cc primops.cc lexer-tab.cc parser-tab.cc \ | ||||||
|  lexer-tab.cc lexer-tab.hh parser-tab.cc parser-tab.hh \ |  get-drvs.cc attr-path.cc expr-to-xml.cc | ||||||
|  get-drvs.cc get-drvs.hh \ | 
 | ||||||
|  attr-path.cc attr-path.hh \ | pkginclude_HEADERS = \ | ||||||
|  expr-to-xml.cc expr-to-xml.hh |  nixexpr.hh eval.hh parser.hh lexer-tab.hh parser-tab.hh \ | ||||||
|  |  get-drvs.hh attr-path.hh expr-to-xml.hh | ||||||
| 
 | 
 | ||||||
| libexpr_la_LIBADD = ../libutil/libutil.la ../libstore/libstore.la \ | libexpr_la_LIBADD = ../libutil/libutil.la ../libstore/libstore.la \ | ||||||
|  ../boost/format/libformat.la |  ../boost/format/libformat.la | ||||||
|  |  | ||||||
|  | @ -207,139 +207,6 @@ static void initAndRun(int argc, char * * argv) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 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 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -246,15 +246,15 @@ string int2String(int n); | ||||||
| bool string2Int(const string & s, int & n); | bool string2Int(const string & s, int & n); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* !!! HACK HACK HACK - this should be in shared.hh, but it's to
 | /* Setuid support. */ | ||||||
|    facilitate a quick hack - will remove this eventually (famous last |  | ||||||
|    words). */ |  | ||||||
| struct SwitchToOriginalUser | struct SwitchToOriginalUser | ||||||
| { | { | ||||||
|     SwitchToOriginalUser(); |     SwitchToOriginalUser(); | ||||||
|     ~SwitchToOriginalUser(); |     ~SwitchToOriginalUser(); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | void switchToNixUser(); | ||||||
|  | 
 | ||||||
|   |   | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue