# HG changeset patch # User Andre Heinecke # Date 1403797344 -7200 # Node ID ef6d3dc9e930f3d539d335343042c43fdd793ca2 # Parent fb69aef056ea2b8616f9610d570ad782123b6e3f Framework for NSS multiuser installation on windows diff -r fb69aef056ea -r ef6d3dc9e930 cinst/nssstore_win.c --- 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)) {