From: "Erich E. Hoover" Subject: advapi32: Report world-access ACL by default for registry objects. Message-Id: Date: Thu, 7 Feb 2013 11:59:17 -0700 The attached patch fixes an issue where the Opera installer expects registry keys to return an ACL (Bug #32904), concluding the cleanup of [Get|Set]NamedSecurityInfo. This patch addresses the issue by attaching a default security descriptor to registry objects that contains a world-access ACL, which is sufficient to keep the installer from encountering an error. The included test shows that this behavior is essentially the case for system keys on Windows, though the "Authenticated Users" (AU) ACL is returned instead. Since the AU ACL is not recognized by Wine, using that ACL would be a poor choice to return at this time, as it would cause accessing registry keys to fail. From f6f2e0fe4ec7d7f405fc8c446e6df44e2624becd Mon Sep 17 00:00:00 2001 From: Erich Hoover Date: Thu, 7 Feb 2013 11:50:17 -0700 Subject: advapi32: Report world-access ACL by default for registry objects. --- dlls/advapi32/tests/security.c | 37 +++++++++++++++++++++++++++++++++---- server/registry.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index e4adab1..d9be5ae 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -3005,10 +3005,12 @@ static void test_SetEntriesInAclA(void) static void test_GetNamedSecurityInfoA(void) { - char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], dacl[100], *user; + char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], *user; + char users_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES]; + PSID admin_sid = (PSID) admin_ptr, users_sid = (PSID) users_ptr, user_sid; DWORD sid_size = sizeof(admin_ptr), user_size; char invalid_path[] = "/an invalid file path"; - PSID admin_sid = (PSID) admin_ptr, user_sid; + char software_key[] = "MACHINE\\Software"; char sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; SECURITY_DESCRIPTOR_CONTROL control; ACL_SIZE_INFORMATION acl_size; @@ -3113,10 +3115,10 @@ static void test_GetNamedSecurityInfoA(void) /* Create security descriptor information and test that it comes back the same */ pSD = &sd; - pDacl = (PACL)&dacl; + pDacl = HeapAlloc(GetProcessHeap(), 0, 100); InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); pCreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size); - bret = InitializeAcl(pDacl, sizeof(dacl), ACL_REVISION); + bret = InitializeAcl(pDacl, 100, ACL_REVISION); ok(bret, "Failed to initialize ACL.\n"); bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid); ok(bret, "Failed to add Current User to ACL.\n"); @@ -3178,6 +3180,33 @@ static void test_GetNamedSecurityInfoA(void) LocalFree(pSD); HeapFree(GetProcessHeap(), 0, user); CloseHandle(hTemp); + + /* Test querying the ACL of a built-in registry key + * Note: Wine currently returns the World SID since none of the actual SIDs are recognized by + * Wine as having permission to access system components. + */ + sid_size = sizeof(users_ptr); + pCreateWellKnownSid(WinBuiltinUsersSid, NULL, users_sid, &sid_size); + error = pGetNamedSecurityInfoA(software_key, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, + NULL, NULL, &pDacl, NULL, &pSD); + ok(!error, "GetNamedSecurityInfo failed with error %d\n", error); + bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); + ok(bret, "GetAclInformation failed\n"); + todo_wine ok(acl_size.AceCount >= 8, "ACE count unexpected (%d, expected 8 or more)\n", + acl_size.AceCount); + if (acl_size.AceCount > 0) + { + bret = pGetAce(pDacl, 0, (VOID **)&ace); + ok(bret, "Failed to get MACHINE\\Software ACE.\n"); + bret = EqualSid(&ace->SidStart, users_sid); + todo_wine ok(bret, "MACHINE\\Software ACE SID != Builtin Users SID.\n"); + ok(((ACE_HEADER *)ace)->AceFlags == 0, + "MACHINE\\Software ACE has unexpected flags (0x%x != 0x0)\n", + ((ACE_HEADER *)ace)->AceFlags); + todo_wine ok(ace->Mask == 0x20019, + "MACHINE\\Software ACE has unexpected mask (0x%x != 0x20019)\n", ace->Mask); + } + LocalFree(pSD); } static void test_ConvertStringSecurityDescriptor(void) diff --git a/server/registry.c b/server/registry.c index a144c26..94ce9d6 100644 --- a/server/registry.c +++ b/server/registry.c @@ -50,6 +50,9 @@ #include "winternl.h" #include "wine/library.h" +#define WINE_SIZE_OF_WORLD_SID FIELD_OFFSET(SID, SubAuthority[((SID *)security_world_sid)->SubAuthorityCount]) +#define WINE_SIZE_OF_WORLD_ACCESS_ACL (sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + WINE_SIZE_OF_WORLD_SID - sizeof(DWORD)) + struct notify { struct list entry; /* entry in list of notifications */ @@ -421,6 +424,13 @@ static struct key *alloc_key( const struct unicode_str *name, timeout_t modif ) struct key *key; if ((key = alloc_object( &key_ops ))) { + struct security_descriptor *sd = mem_alloc(sizeof(struct security_descriptor)+sizeof(ACL) + +sizeof(ACCESS_ALLOWED_ACE) + +WINE_SIZE_OF_WORLD_SID*3); + char *ptr = (char *)(sd + 1); + PACCESS_ALLOWED_ACE pACE; + ACL *pACL; + key->name = NULL; key->class = NULL; key->namelen = name->len; @@ -435,6 +445,31 @@ static struct key *alloc_key( const struct unicode_str *name, timeout_t modif ) key->modif = modif; key->parent = NULL; list_init( &key->notify_list ); + sd->control = SE_DACL_PRESENT; + sd->owner_len = WINE_SIZE_OF_WORLD_SID; + memcpy( ptr, security_world_sid, sd->owner_len ); + ptr += sd->owner_len; + sd->group_len = WINE_SIZE_OF_WORLD_SID; + memcpy( ptr, security_world_sid, sd->group_len ); + ptr += sd->group_len; + sd->sacl_len = 0; + pACL = (ACL *)ptr; + pACE = (PACCESS_ALLOWED_ACE) (pACL + 1); + pACL->AclRevision = ACL_REVISION; + pACL->Sbz1 = 0; + pACL->AclSize = WINE_SIZE_OF_WORLD_ACCESS_ACL; + pACL->AceCount = 1; + pACL->Sbz2 = 0; + pACE->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; + pACE->Header.AceFlags = 0; + pACE->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) + WINE_SIZE_OF_WORLD_SID - sizeof(DWORD); + pACE->Mask = KEY_ALL_ACCESS; + memcpy( &pACE->SidStart, security_world_sid, WINE_SIZE_OF_WORLD_SID ); + sd->dacl_len = pACL->AclSize; + ptr += sd->dacl_len; + default_set_sd( &key->obj, sd, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION + |SACL_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION ); + free( sd ); if (name->len && !(key->name = memdup( name->str, name->len ))) { release_object( key ); -- 1.7.9.5