# HG changeset patch # User Andre Heinecke # Date 1404120340 -7200 # Node ID cb40af11ec3a9471e1208aae2a3ecca7424d3dd4 # Parent 4ad764bfb39caf2f5eaeacb71daa18ac956d95d5 Obtain privileges required for registry modification diff -r 4ad764bfb39c -r cb40af11ec3a cinst/nssstore_win.c --- a/cinst/nssstore_win.c Fri Jun 27 18:53:52 2014 +0200 +++ b/cinst/nssstore_win.c Mon Jun 30 11:25:40 2014 +0200 @@ -429,6 +429,105 @@ return retval; } +/** @brief Increase the privileges of the current token to allow registry access + * + * To load another users registry you need SE_BACKUP_NAME and SE_RESTORE_NAME + * privileges. Normally if we are running elevated we can obtain them. + * + * @returns true if the privileges could be obtained. False otherwise + */ +static bool +get_backup_restore_priv() +{ + HANDLE hToken = NULL; + PTOKEN_PRIVILEGES psToken = NULL; + DWORD token_size = 0, + dwI = 0, + token_size_new = 0, + privilege_size = 128; + char privilege_name[128]; + bool retval = false; + bool backup_found = false; + bool restore_found = false; + + + if (!OpenProcessToken (GetCurrentProcess(), + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) + { + PRINTLASTERROR ("Failed to get process token."); + return false; + } + + /* Get the size for the token */ + GetTokenInformation (hToken, TokenPrivileges, NULL, 0, &token_size); + if (token_size == 0) + { + PRINTLASTERROR ("Failed to get token size."); + goto done; + } + + psToken = xmalloc(token_size); + + if (!GetTokenInformation (hToken, TokenPrivileges, psToken, token_size, &token_size_new)) + { + PRINTLASTERROR ("Failed to get token information."); + goto done; + } + + if (token_size != token_size_new) + { + ERRORPRINTF ("Size changed."); + goto done; + } + + for(dwI = 0; dwI < psToken->PrivilegeCount; dwI++) + { + privilege_size = sizeof (privilege_name); + if (!LookupPrivilegeNameA (NULL, &psToken->Privileges[dwI].Luid, + privilege_name, &privilege_size)) + { + PRINTLASTERROR ("Failed to lookup privilege name"); + } + + if(strcmp(privilege_name, "SeRestorePrivilege") == 0) + { + psToken->Privileges[dwI].Attributes |= SE_PRIVILEGE_ENABLED; + restore_found = true; + continue; + } + if(strcmp(privilege_name, "SeBackupPrivilege") == 0) + { + psToken->Privileges[dwI].Attributes |= SE_PRIVILEGE_ENABLED; + backup_found = true; + continue; + } + if (backup_found && restore_found) + { + break; + } + } + + if (backup_found && restore_found) + { + if(!AdjustTokenPrivileges (hToken, 0, psToken, token_size, NULL, NULL)) + { + PRINTLASTERROR ("Failed to adjust token privileges."); + } + else + { + retval = true; + } + } + +done: + if (hToken != NULL) + { + CloseHandle(hToken); + } + xfree(psToken); + return retval; +} + /**@brief Register NSS process as runOnce for other users * * Loads the registry hives of other users on the system and @@ -444,7 +543,7 @@ * @param [in] selection_file filename of the file containing * the users install / remove selection. */ -void +static void register_proccesses_for_others (wchar_t *selection_file) { char **hives = locate_other_hives(); @@ -456,6 +555,13 @@ DEBUGPRINTF ("No hives found."); return; } + + if (!get_backup_restore_priv()) + { + ERRORPRINTF ("Failed to obtain backup / restore privileges."); + return; + } + run_command = get_command_line (selection_file); for (i = 0; hives[i] != NULL; i++) {