# HG changeset patch # User Andre Heinecke # Date 1409325095 -7200 # Node ID 427e2e18b8c85fdc708f9b1417e10a772d0d16b5 # Parent 85c497b45488fbba1d19e22253fe5590cec8fffb Move Shell functions into util Due to a bug in mingw only one c file may include shlobj.h as there is an unguarded inline definition in there leading to multiple definition errors. Thus the get_program_data get_program_files utility functions. diff -r 85c497b45488 -r 427e2e18b8c8 cinst/nssstore_win.c --- a/cinst/nssstore_win.c Fri Aug 29 16:08:50 2014 +0200 +++ b/cinst/nssstore_win.c Fri Aug 29 17:11:35 2014 +0200 @@ -47,7 +47,6 @@ #include #include #include -#include #include "logging.h" #include "util.h" @@ -735,147 +734,6 @@ return true; } -/**@brief Create a directory with restricted access rights - * - * This creates a security attributes structure that restricts - * write access to the Administrators group but allows everyone to read files - * in that directory. - * Basically a very complicated version of mkdir path -m 644 - * - * If the directory exists the permissions of that directory are checked if - * they are acceptable and true or false is returned accordingly. - * - * Code based on msdn example: - * http://msdn.microsoft.com/en-us/library/windows/desktop/aa446595%28v=vs.85%29.aspx - * - * @param[in] path Path of the directory to create - * - * @returns true on success of if the directory exists, false on error - */ -bool -create_restricted_directory (LPWSTR path) -{ - bool retval = false; - PSID everyone_SID = NULL, - admin_SID = NULL; - PACL access_control_list = NULL; - PSECURITY_DESCRIPTOR descriptor = NULL; - EXPLICIT_ACCESS explicit_access[2]; - SID_IDENTIFIER_AUTHORITY world_identifier = {SECURITY_WORLD_SID_AUTHORITY}, - admin_identifier = {SECURITY_NT_AUTHORITY}; - SECURITY_ATTRIBUTES security_attributes; - - ZeroMemory(&security_attributes, sizeof(security_attributes)); - ZeroMemory(&explicit_access, 2 * sizeof(EXPLICIT_ACCESS)); - - /* Create a well-known SID for the Everyone group. */ - if(!AllocateAndInitializeSid(&world_identifier, /* top-level identifier */ - 1, /* subauthorties count */ - SECURITY_WORLD_RID, /* Only one authority */ - 0, 0, 0, 0, 0, 0, 0, /* No other authorities*/ - &everyone_SID)) - { - PRINTLASTERROR ("Failed to allocate world sid.\n"); - return false; - } - - /* Initialize the first EXPLICIT_ACCESS structure for an ACE. - to allow everyone read access */ - explicit_access[0].grfAccessPermissions = GENERIC_READ; /* Give read access */ - explicit_access[0].grfAccessMode = SET_ACCESS; /* Overwrite other access for all users */ - explicit_access[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; /* make it stick */ - explicit_access[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; - explicit_access[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; - explicit_access[0].Trustee.ptstrName = (LPTSTR) everyone_SID; - - /* Create the SID for the BUILTIN\Administrators group. */ - if(!AllocateAndInitializeSid(&admin_identifier, - 2, - SECURITY_BUILTIN_DOMAIN_RID, /*BUILTIN\ */ - DOMAIN_ALIAS_RID_ADMINS, /*\Administrators */ - 0, 0, 0, 0, 0, 0, /* No other */ - &admin_SID)) - { - PRINTLASTERROR ("Failed to allocate admin sid."); - goto done; - } - - /* explicit_access[1] grants admins full rights for this object and inherits - it to the children */ - explicit_access[1].grfAccessPermissions = GENERIC_ALL; - explicit_access[1].grfAccessMode = SET_ACCESS; - explicit_access[1].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; - explicit_access[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; - explicit_access[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; - explicit_access[1].Trustee.ptstrName = (LPTSTR) admin_SID; - - /* Set up the ACL structure. */ - if (ERROR_SUCCESS != SetEntriesInAcl(2, explicit_access, NULL, &access_control_list)) - { - PRINTLASTERROR ("Failed to set up Acl."); - goto done; - } - - /* Initialize a security descriptor */ - descriptor = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, - SECURITY_DESCRIPTOR_MIN_LENGTH); - if (descriptor == NULL) - { - PRINTLASTERROR("Failed to allocate descriptor."); - goto done; - } - - if (!InitializeSecurityDescriptor(descriptor, - SECURITY_DESCRIPTOR_REVISION)) - { - PRINTLASTERROR("Failed to initialize descriptor."); - goto done; - } - - /* Now we add the ACL to the the descriptor */ - if (!SetSecurityDescriptorDacl(descriptor, - TRUE, /* bDaclPresent flag */ - access_control_list, - FALSE)) /* not a default DACL */ - { - PRINTLASTERROR("Failed to set security descriptor."); - goto done; - } - - /* Finally set up the security attributes structure */ - security_attributes.nLength = sizeof (SECURITY_ATTRIBUTES); - security_attributes.lpSecurityDescriptor = descriptor; - security_attributes.bInheritHandle = FALSE; - - /* Use the security attributes to create the directory */ - if (!CreateDirectoryW(path, &security_attributes)) - { - DWORD err = GetLastError(); - if (err == ERROR_ALREADY_EXISTS) - { - /* Verify that the directory has the correct rights */ - // TODO - retval = true; - goto done; - } - ERRORPRINTF ("Failed to create directory. Err: %lu", err); - } - retval = true; - -done: - - if (everyone_SID) - FreeSid(everyone_SID); - if (admin_SID) - FreeSid(admin_SID); - if (access_control_list) - LocalFree(access_control_list); - if (descriptor) - LocalFree(descriptor); - - return retval; -} - /**@brief Writes the selection file containing the instructions * * If the process is running elevated the instructions are @@ -894,19 +752,13 @@ { wchar_t *folder_name = NULL, *path = NULL; - HRESULT result = E_FAIL; HANDLE hFile = NULL; size_t path_len; - result = SHGetKnownFolderPath (&FOLDERID_ProgramData, /* Get program data dir */ - KF_FLAG_CREATE | /* Create if it does not exist */ - KF_FLAG_INIT, /* Initialize it if created */ - INVALID_HANDLE_VALUE, /* Get it for the default user */ - &folder_name); - - if (result != S_OK) + folder_name = get_program_data_folder(); + if (!folder_name) { - PRINTLASTERROR ("Failed to get folder path"); + ERRORPRINTF("Failed to look up ProgramData folder.\n"); return NULL; } diff -r 85c497b45488 -r 427e2e18b8c8 common/util.c --- a/common/util.c Fri Aug 29 16:08:50 2014 +0200 +++ b/common/util.c Fri Aug 29 17:11:35 2014 +0200 @@ -17,6 +17,9 @@ #include #else #include +#include +#include +#include #endif #ifndef APPNAME @@ -426,6 +429,46 @@ return ret; } +#ifdef _WIN32 +char * +get_program_files_folder () +{ + wchar_t *folder_name = NULL; + char *retval = NULL; + if (SHGetKnownFolderPath (&FOLDERID_ProgramFiles, /* Get program data dir */ + KF_FLAG_NO_ALIAS, + INVALID_HANDLE_VALUE, /* Get it for the default user */ + &folder_name) != S_OK) + { + PRINTLASTERROR ("Failed to get program files folder."); + return NULL; + } + + retval = wchar_to_utf8 (folder_name, wcslen(folder_name)); + CoTaskMemFree (folder_name); + return retval; +} + +/* This is a bit ridicoulous but necessary as shlobj.h contains an inline + definition. So only one C file may include it and thus we have to put + all our shlobj calls into one file... */ +wchar_t * +get_program_data_folder () +{ + wchar_t *folder_name = NULL; + if (SHGetKnownFolderPath (&FOLDERID_ProgramData, /* Get program data dir */ + KF_FLAG_CREATE | /* Create if it does not exist */ + KF_FLAG_INIT, /* Initialize it if created */ + INVALID_HANDLE_VALUE, /* Get it for the default user */ + &folder_name) != S_OK) + { + PRINTLASTERROR ("Failed to get folder path"); + return NULL; + } + return folder_name; +} +#endif + bool is_admin() { @@ -556,3 +599,128 @@ #endif } +#ifdef WIN32 +bool +create_restricted_directory (LPWSTR path) +{ + bool retval = false; + PSID everyone_SID = NULL, + admin_SID = NULL; + PACL access_control_list = NULL; + PSECURITY_DESCRIPTOR descriptor = NULL; + EXPLICIT_ACCESS explicit_access[2]; + SID_IDENTIFIER_AUTHORITY world_identifier = {SECURITY_WORLD_SID_AUTHORITY}, + admin_identifier = {SECURITY_NT_AUTHORITY}; + SECURITY_ATTRIBUTES security_attributes; + + ZeroMemory(&security_attributes, sizeof(security_attributes)); + ZeroMemory(&explicit_access, 2 * sizeof(EXPLICIT_ACCESS)); + + /* Create a well-known SID for the Everyone group. */ + if(!AllocateAndInitializeSid(&world_identifier, /* top-level identifier */ + 1, /* subauthorties count */ + SECURITY_WORLD_RID, /* Only one authority */ + 0, 0, 0, 0, 0, 0, 0, /* No other authorities*/ + &everyone_SID)) + { + PRINTLASTERROR ("Failed to allocate world sid.\n"); + return false; + } + + /* Initialize the first EXPLICIT_ACCESS structure for an ACE. + to allow everyone read access */ + explicit_access[0].grfAccessPermissions = GENERIC_READ; /* Give read access */ + explicit_access[0].grfAccessMode = SET_ACCESS; /* Overwrite other access for all users */ + explicit_access[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; /* make it stick */ + explicit_access[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; + explicit_access[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + explicit_access[0].Trustee.ptstrName = (LPTSTR) everyone_SID; + + /* Create the SID for the BUILTIN\Administrators group. */ + if(!AllocateAndInitializeSid(&admin_identifier, + 2, + SECURITY_BUILTIN_DOMAIN_RID, /*BUILTIN\ */ + DOMAIN_ALIAS_RID_ADMINS, /*\Administrators */ + 0, 0, 0, 0, 0, 0, /* No other */ + &admin_SID)) + { + PRINTLASTERROR ("Failed to allocate admin sid."); + goto done; + } + + /* explicit_access[1] grants admins full rights for this object and inherits + it to the children */ + explicit_access[1].grfAccessPermissions = GENERIC_ALL; + explicit_access[1].grfAccessMode = SET_ACCESS; + explicit_access[1].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; + explicit_access[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; + explicit_access[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; + explicit_access[1].Trustee.ptstrName = (LPTSTR) admin_SID; + + /* Set up the ACL structure. */ + if (ERROR_SUCCESS != SetEntriesInAcl(2, explicit_access, NULL, &access_control_list)) + { + PRINTLASTERROR ("Failed to set up Acl."); + goto done; + } + + /* Initialize a security descriptor */ + descriptor = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, + SECURITY_DESCRIPTOR_MIN_LENGTH); + if (descriptor == NULL) + { + PRINTLASTERROR("Failed to allocate descriptor."); + goto done; + } + + if (!InitializeSecurityDescriptor(descriptor, + SECURITY_DESCRIPTOR_REVISION)) + { + PRINTLASTERROR("Failed to initialize descriptor."); + goto done; + } + + /* Now we add the ACL to the the descriptor */ + if (!SetSecurityDescriptorDacl(descriptor, + TRUE, /* bDaclPresent flag */ + access_control_list, + FALSE)) /* not a default DACL */ + { + PRINTLASTERROR("Failed to set security descriptor."); + goto done; + } + + /* Finally set up the security attributes structure */ + security_attributes.nLength = sizeof (SECURITY_ATTRIBUTES); + security_attributes.lpSecurityDescriptor = descriptor; + security_attributes.bInheritHandle = FALSE; + + /* Use the security attributes to create the directory */ + if (!CreateDirectoryW(path, &security_attributes)) + { + DWORD err = GetLastError(); + if (err == ERROR_ALREADY_EXISTS) + { + /* Verify that the directory has the correct rights */ + // TODO + retval = true; + goto done; + } + ERRORPRINTF ("Failed to create directory. Err: %lu", err); + } + retval = true; + +done: + + if (everyone_SID) + FreeSid(everyone_SID); + if (admin_SID) + FreeSid(admin_SID); + if (access_control_list) + LocalFree(access_control_list); + if (descriptor) + LocalFree(descriptor); + + return retval; +} +#endif diff -r 85c497b45488 -r 427e2e18b8c8 common/util.h --- a/common/util.h Fri Aug 29 16:08:50 2014 +0200 +++ b/common/util.h Fri Aug 29 17:11:35 2014 +0200 @@ -100,6 +100,42 @@ */ char * read_registry_string (const HKEY root, const wchar_t *key, const wchar_t *name); + +/**@brief Get the utf-8 encoded path to the program files folder. + * + * Uses SHGetKnownFolderPath to look up the ProgramFiles folder. + * @returns a newly allocated string containing the value or NULL on + * error. + */ +char * get_program_files_folder (); + +/**@brief Get the path to the program data folder. + * + * Uses SHGetKnownFolderPath to look up the ProgramData folder. + * The return value should be freed with CoTaskMemFree + * @returns a reference containing the value or NULL on error. + */ +wchar_t * get_program_data_folder (); + +/**@brief Create a directory with restricted access rights + * + * This creates a security attributes structure that restricts + * write access to the Administrators group but allows everyone to read files + * in that directory. + * Basically a very complicated version of mkdir path -m 644 + * + * If the directory exists the permissions of that directory are checked if + * they are acceptable and true or false is returned accordingly. + * + * Code based on msdn example: + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa446595%28v=vs.85%29.aspx + * + * @param[in] path Path of the directory to create + * + * @returns true on success of if the directory exists, false on error + */ +bool create_restricted_directory (LPWSTR path); + #endif #ifdef __cplusplus