diff cinst/nssstore_win.c @ 668:ef6d3dc9e930

Framework for NSS multiuser installation on windows
author Andre Heinecke <andre.heinecke@intevation.de>
date Thu, 26 Jun 2014 17:42:24 +0200
parents 69dd092e2512
children 175370634226
line wrap: on
line diff
--- a/cinst/nssstore_win.c	Thu Jun 26 17:41:53 2014 +0200
+++ b/cinst/nssstore_win.c	Thu Jun 26 17:42:24 2014 +0200
@@ -59,8 +59,12 @@
 #define SELECTION_FILE_NAME L"currently_selected.txt"
 #endif
 
+/**@def The maximum time to wait for the NSS Process */
 #define PROCESS_TIMEOUT 30000
 
+/**@def The registry key to look for user profile directories */
+#define PROFILE_LIST L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"
+
 /**@brief Write strv of instructions to a handle
 *
 * Writes the null terminated list of instructions to
@@ -134,12 +138,113 @@
   return true;
 }
 
+/**@brief Get the path to all users default registry hive
+ *
+ * Enumerates the keys in #PROFILE_LIST and retuns a
+ * strv array with the utf-8 encoded paths to their suggested
+ * registry hive location.
+ *
+ * Users with an SID not starting with S-1-5-21- are ignored
+ * as is the current user.
+ *
+ * Use strv_free to free that array.
+ *
+ * @returns a newly allocated strv of the paths to the registry hives or NULL
+ */
+
+static char**
+locate_other_hives()
+{
+  HKEY profile_list = NULL;
+  int ret = 0;
+  DWORD index = 0,
+        key_len = 257;
+  /* According to
+     http://msdn.microsoft.com/en-us/library/windows/desktop/ms724872%28v=vs.85%29.aspx
+     a registry key is limited to 255 characters. But according to
+     http://www.sepago.de/e/holger/2010/07/20/how-long-can-a-registry-key-name-really-be
+     the actual limit is 256 + \0 thus we create a buffer for 257 wchar_t's*/
+  wchar_t key_name[257];
+  char **retval = NULL;
+  bool error = true;
+
+  ret = RegOpenKeyExW (HKEY_LOCAL_MACHINE, PROFILE_LIST, 0,
+                       KEY_READ, &profile_list);
+  if (ret != ERROR_SUCCESS)
+    {
+      ERRORPRINTF ("Failed to open profile list. Error: %i", ret);
+      return NULL;
+    }
+
+  while ((ret = RegEnumKeyExW (profile_list, index++,
+                               key_name, &key_len,
+                               NULL, NULL, NULL, NULL)) == ERROR_SUCCESS)
+    {
+      if (key_len == 257)
+        {
+          ERRORPRINTF ("Registry key too long.");
+          goto done;
+        }
+      DEBUGPRINTF ("Key : %S", key_name);
+
+      /* Reset key_len to buffer size */
+      key_len = 257;
+
+      if (wcsncmp (L"S-1-5-21-", key_name, 9) != 0)
+        {
+          /* S-1-5-21 is the well known prefix for local users. Skip all others */
+          continue;
+        }
+    }
+
+  if (ret != ERROR_NO_MORE_ITEMS)
+    {
+      ERRORPRINTF ("Failed to enumeratre profile list. Error: %i", ret);
+      goto done;
+    }
+
+done:
+  RegCloseKey (profile_list);
+
+  if (error)
+    {
+      strv_free (retval);
+      retval = NULL;
+    }
+
+  return retval;
+}
+
+/**@brief Register NSS process as runOnce for other users
+*
+* Loads the registry hives of other users on the system and
+* adds a RunOnce registry key to start the NSS process to
+* install the current selection on their next login.
+*
+* This should avoid conflicts with their firefox / thunderbird
+* while making the certificates available for their applications.
+*
+* This function needs SE_BACKUP_NAME and SE_RESTORE_NAME
+* privileges.
+*
+* @param [in] selection_file filename of the file containing
+*             the users install / remove selection.
+*/
+void
+register_proccesses_for_others (wchar_t *selection_file)
+{
+  char **hives = locate_other_hives();
+
+  strv_free (hives);
+  printf("Selection file %S", selection_file);
+}
+
 /**@brief Start the process to install / remove
 *
 * Starts the NSS installation process for the current user
 *
 * @param [in] selection_file filename of the file containing
-*             the users installall / remove selection.
+*             the users install / remove selection.
 *
 * @returns true on success, false on error.
 */
@@ -518,7 +623,10 @@
 
   DEBUGPRINTF ("Wrote selection file. Loc: %S\n", selection_file_name);
 
-  /* TODO loop over all users create startup entries for them*/
+  if (is_elevated())
+    {
+      register_proccesses_for_others (selection_file_name);
+    }
 
   if (!start_procces_for_user (selection_file_name))
     {

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