diff cinst/nssstore_win.c @ 676:cb40af11ec3a

Obtain privileges required for registry modification
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 30 Jun 2014 11:25:40 +0200
parents 4ad764bfb39c
children 85c5aa9aba2b
line wrap: on
line diff
--- 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++)
     {

http://wald.intevation.org/projects/trustbridge/