aheinecke@404: /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik aheinecke@404: * Software engineering by Intevation GmbH aheinecke@404: * aheinecke@404: * This file is Free Software under the GNU GPL (v>=2) aheinecke@404: * and comes with ABSOLUTELY NO WARRANTY! aheinecke@404: * See LICENSE.txt for details. aheinecke@404: */ aheinecke@321: #include "util.h" aheinecke@505: #include "logging.h" andre@644: #include "strhelp.h" aheinecke@505: wilde@323: #ifndef _WIN32 wilde@323: #include wilde@323: #include andre@644: #include andre@644: #include andre@644: #include wilde@323: #else aheinecke@321: #include aheinecke@321: #endif aheinecke@321: aheinecke@321: bool wilde@323: is_elevated() wilde@323: { wilde@323: bool ret = false; wilde@323: #ifndef _WIN32 wilde@323: ret = (geteuid() == 0); wilde@323: #else wilde@323: HANDLE hToken = NULL; wilde@323: if (OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &hToken)) wilde@323: { wilde@323: DWORD elevation; wilde@323: DWORD cbSize = sizeof (DWORD); wilde@323: if (GetTokenInformation (hToken, TokenElevation, &elevation, wilde@323: sizeof (TokenElevation), &cbSize)) wilde@323: { wilde@323: ret = elevation; wilde@323: } wilde@323: } wilde@323: if (hToken) wilde@323: CloseHandle (hToken); wilde@323: #endif wilde@323: return ret; wilde@323: } aheinecke@505: aheinecke@505: bool is_admin() aheinecke@505: { aheinecke@505: #ifndef _WIN32 andre@644: struct passwd *current_user = getpwuid (geteuid()); andre@644: int ngroups = 0, andre@644: ret = 0, andre@644: i = 0; andre@644: gid_t * groups = NULL; andre@644: andre@644: if (current_user == NULL) andre@644: { andre@644: ERRORPRINTF ("Failed to obtain user information."); andre@644: return false; andre@644: } andre@644: andre@644: ret = getgrouplist (current_user->pw_name, current_user->pw_gid, NULL, andre@644: &ngroups); andre@644: andre@644: if (ret != -1 || ngroups <= 0) andre@644: { andre@644: ERRORPRINTF ("Unknown error in getgrouplist call"); andre@644: return false; andre@644: } andre@644: andre@644: groups = xmalloc (((unsigned int)ngroups) * sizeof (gid_t)); andre@644: andre@644: ret = getgrouplist (current_user->pw_name, current_user->pw_gid, groups, andre@644: &ngroups); andre@644: andre@644: if (ret != ngroups) andre@644: { andre@644: ERRORPRINTF ("Group length mismatch."); andre@644: xfree (groups); andre@644: return false; andre@644: } andre@644: andre@644: for (i = 0; i < ngroups; i++) andre@644: { andre@644: struct group *gr = getgrgid (groups[i]); andre@644: if (gr == NULL) andre@644: { andre@644: ERRORPRINTF ("Error in group enumeration"); andre@644: xfree (groups); andre@644: return false; andre@644: } andre@644: if (strcmp("sudo", gr->gr_name) == 0) andre@644: { andre@644: DEBUGPRINTF ("User is in sudo group \n"); andre@644: xfree (groups); andre@644: return true; andre@644: } andre@644: } andre@644: andre@644: DEBUGPRINTF ("User is not in sudo group"); andre@644: aheinecke@505: return false; aheinecke@505: #else aheinecke@505: bool retval = false; aheinecke@505: BOOL in_admin_group = FALSE; aheinecke@505: HANDLE hToken = NULL; aheinecke@505: HANDLE hTokenToCheck = NULL; aheinecke@505: DWORD cbSize = 0; aheinecke@505: TOKEN_ELEVATION_TYPE elevation; aheinecke@505: BYTE admin_id[SECURITY_MAX_SID_SIZE]; aheinecke@505: aheinecke@505: if (!OpenProcessToken(GetCurrentProcess(), aheinecke@505: TOKEN_QUERY | TOKEN_DUPLICATE, &hToken)) aheinecke@505: { aheinecke@505: PRINTLASTERROR ("Failed to duplicate process token.\n"); aheinecke@505: return false; aheinecke@505: } aheinecke@505: aheinecke@505: if (!GetTokenInformation(hToken, TokenElevationType, &elevation, aheinecke@505: sizeof(elevation), &cbSize)) aheinecke@505: { aheinecke@505: PRINTLASTERROR ("Failed to get token information.\n"); aheinecke@505: goto done; aheinecke@505: } aheinecke@505: aheinecke@505: /* If limited check the the linked token instead */ aheinecke@505: if (TokenElevationTypeLimited == elevation) aheinecke@505: { aheinecke@505: if (!GetTokenInformation(hToken, TokenLinkedToken, &hTokenToCheck, aheinecke@505: sizeof(hTokenToCheck), &cbSize)) aheinecke@505: { aheinecke@505: PRINTLASTERROR ("Failed to get the linked token.\n"); aheinecke@505: goto done; aheinecke@505: } aheinecke@505: } aheinecke@505: aheinecke@505: if (!hTokenToCheck) /* The linked token is already of the correct type */ aheinecke@505: { aheinecke@505: if (!DuplicateToken(hToken, SecurityIdentification, &hTokenToCheck)) aheinecke@505: { aheinecke@505: PRINTLASTERROR ("Failed to duplicate token for identification.\n"); aheinecke@505: goto done; aheinecke@505: } aheinecke@505: } aheinecke@505: aheinecke@505: /* Do the sid dance for the adminSID */ aheinecke@505: cbSize = sizeof(admin_id); aheinecke@505: if (!CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &admin_id, aheinecke@505: &cbSize)) aheinecke@505: { aheinecke@505: PRINTLASTERROR ("Failed to get admin sid.\n"); aheinecke@505: goto done; aheinecke@505: } aheinecke@505: aheinecke@505: /* The actual check */ aheinecke@505: if (!CheckTokenMembership(hTokenToCheck, &admin_id, &in_admin_group)) aheinecke@505: { aheinecke@505: PRINTLASTERROR ("Failed to check token membership.\n"); aheinecke@505: goto done; aheinecke@505: } aheinecke@505: aheinecke@505: if (in_admin_group) aheinecke@505: { aheinecke@505: /* Winbool to standard bool */ aheinecke@505: retval = true; aheinecke@505: } aheinecke@505: aheinecke@505: done: aheinecke@505: if (hToken) CloseHandle(hToken); aheinecke@505: if (hTokenToCheck) CloseHandle(hTokenToCheck); aheinecke@505: aheinecke@505: return retval; aheinecke@505: #endif aheinecke@505: } aheinecke@505: