From 722c2b1008416ff72be4e1d60060e79957061584 Mon Sep 17 00:00:00 2001 From: Erich Hoover Date: Mon, 26 Nov 2012 12:13:47 -0700 Subject: [PATCH] advapi: Implement GetNamedSecurityInfoW on top of GetSecurityInfo. --- dlls/advapi32/security.c | 104 +++++++------------------- dlls/advapi32/tests/security.c | 131 +++++++++++++++++++++++++++------ 2 files changed, 133 insertions(+), 102 deletions(-) diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c index 6c1cdf1d3b4..5a481ed4a46 100644 --- a/dlls/advapi32/security.c +++ b/dlls/advapi32/security.c @@ -5456,9 +5456,12 @@ DWORD WINAPI GetNamedSecurityInfoW( LPWSTR name, SE_OBJECT_TYPE type, SECURITY_INFORMATION info, PSID* owner, PSID* group, PACL* dacl, PACL* sacl, PSECURITY_DESCRIPTOR* descriptor ) { - DWORD needed, offset; - SECURITY_DESCRIPTOR_RELATIVE *relative = NULL; - BYTE *buffer; + OBJECT_ATTRIBUTES attr; + UNICODE_STRING nameW; + IO_STATUS_BLOCK io; + DWORD access = 0; + HANDLE hFile; + DWORD status; TRACE( "%s %d %d %p %p %p %p %p\n", debugstr_w(name), type, info, owner, group, dacl, sacl, descriptor ); @@ -5473,85 +5476,28 @@ DWORD WINAPI GetNamedSecurityInfoW( LPWSTR name, SE_OBJECT_TYPE type, || ((info & DACL_SECURITY_INFORMATION) && !dacl) || ((info & SACL_SECURITY_INFORMATION) && !sacl) )) return ERROR_INVALID_PARAMETER; + if (!RtlDosPathNameToNtPathName_U( name, &nameW, NULL, NULL )) + return ERROR_PATH_NOT_FOUND; - needed = !descriptor ? 0 : sizeof(SECURITY_DESCRIPTOR_RELATIVE); - if (info & OWNER_SECURITY_INFORMATION) - needed += sizeof(sidWorld); - if (info & GROUP_SECURITY_INFORMATION) - needed += sizeof(sidWorld); - if (info & DACL_SECURITY_INFORMATION) - needed += WINE_SIZE_OF_WORLD_ACCESS_ACL; + if (info & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION)) + access |= READ_CONTROL; if (info & SACL_SECURITY_INFORMATION) - needed += WINE_SIZE_OF_WORLD_ACCESS_ACL; + access |= ACCESS_SYSTEM_SECURITY; + attr.Length = sizeof(attr); + attr.RootDirectory = 0; + attr.Attributes = OBJ_CASE_INSENSITIVE; + attr.ObjectName = &nameW; + attr.SecurityDescriptor = NULL; - if(descriptor) - { - /* must be freed by caller */ - *descriptor = HeapAlloc( GetProcessHeap(), 0, needed ); - if (!*descriptor) return ERROR_NOT_ENOUGH_MEMORY; - - if (!InitializeSecurityDescriptor( *descriptor, SECURITY_DESCRIPTOR_REVISION )) - { - HeapFree( GetProcessHeap(), 0, *descriptor ); - return ERROR_INVALID_SECURITY_DESCR; - } - - relative = *descriptor; - relative->Control |= SE_SELF_RELATIVE; - - buffer = (BYTE *)relative; - offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE); - } - else - { - buffer = HeapAlloc( GetProcessHeap(), 0, needed ); - if (!buffer) return ERROR_NOT_ENOUGH_MEMORY; - offset = 0; - } - - if (info & OWNER_SECURITY_INFORMATION) - { - memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) ); - if(relative) - relative->Owner = offset; - if (owner) - *owner = buffer + offset; - offset += sizeof(sidWorld); - } - if (info & GROUP_SECURITY_INFORMATION) - { - memcpy( buffer + offset, &sidWorld, sizeof(sidWorld) ); - if(relative) - relative->Group = offset; - if (group) - *group = buffer + offset; - offset += sizeof(sidWorld); - } - if (info & DACL_SECURITY_INFORMATION) - { - GetWorldAccessACL( (PACL)(buffer + offset) ); - if(relative) - { - relative->Control |= SE_DACL_PRESENT; - relative->Dacl = offset; - } - if (dacl) - *dacl = (PACL)(buffer + offset); - offset += WINE_SIZE_OF_WORLD_ACCESS_ACL; - } - if (info & SACL_SECURITY_INFORMATION) - { - GetWorldAccessACL( (PACL)(buffer + offset) ); - if(relative) - { - relative->Control |= SE_SACL_PRESENT; - relative->Sacl = offset; - } - if (sacl) - *sacl = (PACL)(buffer + offset); - } - - return ERROR_SUCCESS; + status = NtCreateFile( &hFile, access, &attr, &io, NULL, FILE_FLAG_BACKUP_SEMANTICS, + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, + FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0 ); + RtlFreeUnicodeString( &nameW ); + if (status != STATUS_SUCCESS) + return RtlNtStatusToDosError( status ); + status = GetSecurityInfo( hFile, type, info, owner, group, dacl, sacl, descriptor ); + CloseHandle( hFile ); + return status; } /****************************************************************************** diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index 2a4df4dfa4f..f53d50fe143 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -3005,32 +3005,53 @@ static void test_SetEntriesInAclA(void) static void test_GetNamedSecurityInfoA(void) { + char b[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES]; + char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], dacl[100]; + DWORD sid_size = sizeof(admin_ptr), l = sizeof(b); char invalid_path[] = "/an invalid file path"; - PSECURITY_DESCRIPTOR pSecDesc; - DWORD revision; + PSID admin_sid = (PSID) admin_ptr, user_sid; + char sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; SECURITY_DESCRIPTOR_CONTROL control; - PSID owner; - PSID group; - PACL dacl; + ACL_SIZE_INFORMATION acl_size; + CHAR windows_dir[MAX_PATH]; + PSECURITY_DESCRIPTOR pSD; + ACCESS_ALLOWED_ACE *ace; + BOOL bret = TRUE, isNT4; + char tmpfile[MAX_PATH]; + DWORD error, revision; BOOL owner_defaulted; BOOL group_defaulted; - DWORD error; - BOOL ret, isNT4; - CHAR windows_dir[MAX_PATH]; + HANDLE token, hTemp; + PSID owner, group; + PACL pDacl; - if (!pGetNamedSecurityInfoA || !pSetNamedSecurityInfoA) + if (!pSetNamedSecurityInfoA || !pGetNamedSecurityInfoA || !pCreateWellKnownSid) { - win_skip("[Get|Set]NamedSecurityInfoA is not available\n"); + win_skip("Required functions are not available\n"); return; } - ret = GetWindowsDirectoryA(windows_dir, MAX_PATH); - ok(ret, "GetWindowsDirectory failed with error %d\n", GetLastError()); + if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token)) + { + if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE; + else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE; + } + if (!bret) + { + win_skip("Failed to get current user token\n"); + return; + } + GetTokenInformation(token, TokenUser, b, l, &l); + CloseHandle( token ); + user_sid = ((TOKEN_USER *)b)->User.Sid; + + bret = GetWindowsDirectoryA(windows_dir, MAX_PATH); + ok(bret, "GetWindowsDirectory failed with error %d\n", GetLastError()); SetLastError(0xdeadbeef); error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, - NULL, NULL, NULL, NULL, &pSecDesc); + NULL, NULL, NULL, NULL, &pSD); if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) { win_skip("GetNamedSecurityInfoA is not implemented\n"); @@ -3038,8 +3059,8 @@ static void test_GetNamedSecurityInfoA(void) } ok(!error, "GetNamedSecurityInfo failed with error %d\n", error); - ret = GetSecurityDescriptorControl(pSecDesc, &control, &revision); - ok(ret, "GetSecurityDescriptorControl failed with error %d\n", GetLastError()); + bret = GetSecurityDescriptorControl(pSD, &control, &revision); + ok(bret, "GetSecurityDescriptorControl failed with error %d\n", GetLastError()); ok((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == (SE_SELF_RELATIVE|SE_DACL_PRESENT) || broken((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT), /* NT4 */ "control (0x%x) doesn't have (SE_SELF_RELATIVE|SE_DACL_PRESENT) flags set\n", control); @@ -3047,14 +3068,14 @@ static void test_GetNamedSecurityInfoA(void) isNT4 = (control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT; - ret = GetSecurityDescriptorOwner(pSecDesc, &owner, &owner_defaulted); - ok(ret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError()); + bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted); + ok(bret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError()); ok(owner != NULL, "owner should not be NULL\n"); - ret = GetSecurityDescriptorGroup(pSecDesc, &group, &group_defaulted); - ok(ret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError()); + bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted); + ok(bret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError()); ok(group != NULL, "group should not be NULL\n"); - LocalFree(pSecDesc); + LocalFree(pSD); /* NULL descriptor tests */ @@ -3069,12 +3090,12 @@ static void test_GetNamedSecurityInfoA(void) ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error); error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,DACL_SECURITY_INFORMATION, - NULL, NULL, &dacl, NULL, NULL); + NULL, NULL, &pDacl, NULL, NULL); ok(!error, "GetNamedSecurityInfo failed with error %d\n", error); - ok(dacl != NULL, "dacl should not be NULL\n"); + ok(pDacl != NULL, "DACL should not be NULL\n"); error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,OWNER_SECURITY_INFORMATION, - NULL, NULL, &dacl, NULL, NULL); + NULL, NULL, &pDacl, NULL, NULL); ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error); /* Test behavior of SetNamedSecurityInfo with an invalid path */ @@ -3083,6 +3104,70 @@ static void test_GetNamedSecurityInfoA(void) NULL, NULL, NULL); ok(error == ERROR_FILE_NOT_FOUND, "Unexpected error returned: 0x%x\n", error); ok(GetLastError() == 0xdeadbeef, "Expected last error to remain unchanged.\n"); + + /* Create security descriptor information and test that it comes back the same */ + pSD = &sd; + pDacl = (PACL)&dacl; + InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); + pCreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size); + bret = InitializeAcl(pDacl, sizeof(dacl), 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"); + bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, admin_sid); + ok(bret, "Failed to add Administrator Group to ACL.\n"); + bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE); + ok(bret, "Failed to add ACL to security desciptor.\n"); + GetTempFileNameA(".", "foo", 0, tmpfile); + hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_FLAG_DELETE_ON_CLOSE, NULL); + SetLastError(0xdeadbeef); + error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, + NULL, pDacl, NULL); + if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) + { + win_skip("SetNamedSecurityInfoA is not implemented\n"); + CloseHandle(hTemp); + return; + } + ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error); + SetLastError(0xdeadbeef); + error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, + NULL, NULL, &pDacl, NULL, &pSD); + if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) + { + win_skip("GetNamedSecurityInfoA is not implemented\n"); + return; + } + ok(!error, "GetNamedSecurityInfo failed with error %d\n", error); + + bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); + ok(bret, "GetAclInformation failed\n"); + if (acl_size.AceCount > 0) + { + bret = pGetAce(pDacl, 0, (VOID **)&ace); + ok(bret, "Failed to get Current User ACE.\n"); + bret = EqualSid(&ace->SidStart, user_sid); + todo_wine ok(bret, "Current User ACE != Current User SID.\n"); + ok(((ACE_HEADER *)ace)->AceFlags == 0, + "Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags); + ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n", + ace->Mask); + } + if (acl_size.AceCount > 1) + { + bret = pGetAce(pDacl, 1, (VOID **)&ace); + ok(bret, "Failed to get Administators Group ACE.\n"); + bret = EqualSid(&ace->SidStart, admin_sid); + todo_wine ok(bret || broken(!bret) /* win2k */, + "Administators Group ACE != Administators Group SID.\n"); + ok(((ACE_HEADER *)ace)->AceFlags == 0, + "Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags); + ok(ace->Mask == 0x1f01ff || broken(ace->Mask == GENERIC_ALL) /* win2k */, + "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask); + } + LocalFree(pSD); + CloseHandle(hTemp); } static void test_ConvertStringSecurityDescriptor(void)