#include "windef.h"
#include "winbase.h"
#include "winerror.h"
+#include "wine/winternl.h"
#include "aclapi.h"
#include "winnt.h"
#include "sddl.h"
#define THREAD_ALL_ACCESS_NT4 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff)
#define THREAD_ALL_ACCESS_VISTA (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xffff)
-/* copied from Wine winternl.h - not included in the Windows SDK */
-typedef enum _OBJECT_INFORMATION_CLASS {
- ObjectBasicInformation,
- ObjectNameInformation,
- ObjectTypeInformation,
- ObjectAllInformation,
- ObjectDataInformation
-} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;
-
-typedef struct _OBJECT_BASIC_INFORMATION {
- ULONG Attributes;
- ACCESS_MASK GrantedAccess;
- ULONG HandleCount;
- ULONG PointerCount;
- ULONG PagedPoolUsage;
- ULONG NonPagedPoolUsage;
- ULONG Reserved[3];
- ULONG NameInformationLength;
- ULONG TypeInformationLength;
- ULONG SecurityDescriptorLength;
- LARGE_INTEGER CreateTime;
-} OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION;
-
#define expect_eq(expr, value, type, format) { type ret_ = expr; ok((value) == ret_, #expr " expected " format " got " format "\n", (value), (ret_)); }
static BOOL (WINAPI *pAddAccessAllowedAceEx)(PACL, DWORD, DWORD, DWORD, PSID);
PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE);
static BOOL (WINAPI *pGetAclInformation)(PACL,LPVOID,DWORD,ACL_INFORMATION_CLASS);
static BOOL (WINAPI *pGetAce)(PACL,DWORD,LPVOID*);
+static NTSTATUS (WINAPI *pNtSetSecurityObject)(HANDLE,SECURITY_INFORMATION,PSECURITY_DESCRIPTOR);
+static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG);
+static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)(LPCWSTR,PUNICODE_STRING,PWSTR*,CURDIR*);
+static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING,PCANSI_STRING,BOOLEAN);
+static BOOL (WINAPI *pGetWindowsAccountDomainSid)(PSID,PSID,DWORD*);
+static void (WINAPI *pRtlInitAnsiString)(PANSI_STRING,PCSZ);
+static NTSTATUS (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
static HMODULE hmod;
static int myARGC;
hntdll = GetModuleHandleA("ntdll.dll");
pNtQueryObject = (void *)GetProcAddress( hntdll, "NtQueryObject" );
pNtAccessCheck = (void *)GetProcAddress( hntdll, "NtAccessCheck" );
+ pNtSetSecurityObject = (void *)GetProcAddress(hntdll, "NtSetSecurityObject");
+ pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile");
+ pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
+ pRtlAnsiStringToUnicodeString = (void *)GetProcAddress(hntdll, "RtlAnsiStringToUnicodeString");
+ pRtlInitAnsiString = (void *)GetProcAddress(hntdll, "RtlInitAnsiString");
+ pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
hmod = GetModuleHandleA("advapi32.dll");
pAddAccessAllowedAceEx = (void *)GetProcAddress(hmod, "AddAccessAllowedAceEx");
pConvertStringSidToSidA = (void *)GetProcAddress(hmod, "ConvertStringSidToSidA");
pGetAclInformation = (void *)GetProcAddress(hmod, "GetAclInformation");
pGetAce = (void *)GetProcAddress(hmod, "GetAce");
+ pGetWindowsAccountDomainSid = (void *)GetProcAddress(hmod, "GetWindowsAccountDomainSid");
myARGC = winetest_get_mainargs( &myARGV );
}
+static SECURITY_DESCRIPTOR* test_get_security_descriptor(HANDLE handle, int line)
+{
+ /* use HeapFree(GetProcessHeap(), 0, sd); when done */
+ DWORD ret, length, needed;
+ SECURITY_DESCRIPTOR *sd;
+
+ needed = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = GetKernelObjectSecurity(handle, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ NULL, 0, &needed);
+ ok_(__FILE__, line)(!ret, "GetKernelObjectSecurity should fail\n");
+ ok_(__FILE__, line)(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ ok_(__FILE__, line)(needed != 0xdeadbeef, "GetKernelObjectSecurity should return required buffer length\n");
+
+ length = needed;
+ sd = HeapAlloc(GetProcessHeap(), 0, length);
+
+ needed = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = GetKernelObjectSecurity(handle, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ sd, length, &needed);
+ ok_(__FILE__, line)(ret, "GetKernelObjectSecurity error %d\n", GetLastError());
+ ok_(__FILE__, line)(needed == length || needed == 0 /* file, pipe */, "GetKernelObjectSecurity should return %u instead of %u\n", length, needed);
+ return sd;
+}
+
+static void test_owner_equal(HANDLE Handle, PSID expected, int line)
+{
+ BOOL res;
+ SECURITY_DESCRIPTOR *queriedSD = NULL;
+ PSID owner;
+ BOOL owner_defaulted;
+
+ queriedSD = test_get_security_descriptor( Handle, line );
+
+ res = GetSecurityDescriptorOwner(queriedSD, &owner, &owner_defaulted);
+ ok_(__FILE__, line)(res, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
+
+ ok_(__FILE__, line)(EqualSid(owner, expected), "Owner SIDs are not equal\n");
+ ok_(__FILE__, line)(!owner_defaulted, "Defaulted is true\n");
+
+ HeapFree(GetProcessHeap(), 0, queriedSD);
+}
+
+static void test_group_equal(HANDLE Handle, PSID expected, int line)
+{
+ BOOL res;
+ SECURITY_DESCRIPTOR *queriedSD = NULL;
+ PSID group;
+ BOOL group_defaulted;
+
+ queriedSD = test_get_security_descriptor( Handle, line );
+
+ res = GetSecurityDescriptorGroup(queriedSD, &group, &group_defaulted);
+ ok_(__FILE__, line)(res, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
+
+ ok_(__FILE__, line)(EqualSid(group, expected), "Group SIDs are not equal\n");
+ ok_(__FILE__, line)(!group_defaulted, "Defaulted is true\n");
+
+ HeapFree(GetProcessHeap(), 0, queriedSD);
+}
+
static void test_sid(void)
{
struct sidRef refs[] = {
rc &= ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|FILE_ATTRIBUTE_COMPRESSED);
ok(rc == FILE_ATTRIBUTE_ARCHIVE, "expected FILE_ATTRIBUTE_ARCHIVE got %#x\n", rc);
- retSize = 0xdeadbeef;
rc = GetFileSecurityA(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
NULL, 0, &sdSize);
ok(!rc, "GetFileSecurity should fail\n");
DWORD acc_size = MAX_PATH;
DWORD dom_size = MAX_PATH;
ret = LookupAccountSidA (NULL, sid, account, &acc_size, domain, &dom_size, &use);
- ok(ret || (!ret && (GetLastError() == ERROR_NONE_MAPPED)),
+ ok(ret || GetLastError() == ERROR_NONE_MAPPED,
"LookupAccountSid(%s) failed: %d\n", str_sid, GetLastError());
if (ret)
trace(" %s %s\\%s %d\n", str_sid, domain, account, use);
/* 69 */ {TRUE, "S-1-16-16384"}, {TRUE, "S-1-5-33"}, {TRUE, "S-1-3-4"},
/* 72 */ {FALSE, "S-1-5-21-12-23-34-45-56-571"}, {FALSE, "S-1-5-21-12-23-34-45-56-572"},
/* 74 */ {TRUE, "S-1-5-22"}, {FALSE, "S-1-5-21-12-23-34-45-56-521"}, {TRUE, "S-1-5-32-573"},
-/* 77 */ {FALSE, "S-1-5-21-12-23-34-45-56-498"}, {TRUE, "S-1-5-32-574"}, {TRUE, "S-1-16-8448"}
+/* 77 */ {FALSE, "S-1-5-21-12-23-34-45-56-498"}, {TRUE, "S-1-5-32-574"}, {TRUE, "S-1-16-8448"},
+/* 80 */ {FALSE, NULL}, {TRUE, "S-1-2-1"}, {TRUE, "S-1-5-65-1"}, {FALSE, NULL},
+/* 84 */ {TRUE, "S-1-15-2-1"},
};
static void test_CreateWellKnownSid(void)
if (value->sid_string == NULL)
continue;
- if (i > WinAccountRasAndIasServersSid)
+ /* some SIDs aren't implemented by all Windows versions - detect it */
+ cb = sizeof(sid_buffer);
+ if (!pCreateWellKnownSid(i, NULL, sid_buffer, &cb))
{
- /* These SIDs aren't implemented by all Windows versions - detect it and break the loop */
- cb = sizeof(sid_buffer);
- if (!pCreateWellKnownSid(i, domainsid, sid_buffer, &cb))
- {
- skip("Well known SIDs starting from %u are not implemented\n", i);
- break;
- }
+ skip("Well known SID %u not implemented\n", i);
+ continue;
}
cb = sizeof(sid_buffer);
ok(ret, "Failed to lookup account name\n");
ok(sid_size == GetLengthSid(psid), "Expected %d, got %d\n", GetLengthSid(psid), sid_size);
ok(!lstrcmpA(account, user_name), "Expected %s, got %s\n", user_name, account);
- ok(!lstrcmpA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
+ ok(!lstrcmpiA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
ok(domain_size == domain_save - 1, "Expected %d, got %d\n", domain_save - 1, domain_size);
ok(strlen(domain) == domain_size, "Expected %d, got %d\n", lstrlenA(domain), domain_size);
ok(sid_use == SidTypeUser, "Expected SidTypeUser (%d), got %d\n", SidTypeUser, sid_use);
ok(ret, "Failed to lookup account name\n");
ok(sid_size != 0, "sid_size was zero\n");
ok(!lstrcmpA(account, "Everyone"), "Expected Everyone, got %s\n", account);
- ok(!lstrcmpA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
+ ok(!lstrcmpiA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
ok(domain_size == 0, "Expected 0, got %d\n", domain_size);
ok(strlen(domain) == domain_size, "Expected %d, got %d\n", lstrlenA(domain), domain_size);
ok(sid_use == SidTypeWellKnownGroup, "Expected SidTypeWellKnownGroup (%d), got %d\n", SidTypeWellKnownGroup, sid_use);
get_sid_info(psid, &account, &sid_dom);
ok(ret, "Failed to lookup account name\n");
/* Using a fixed string will not work on different locales */
- ok(!lstrcmpA(account, domain),
- "Got %s for account and %s for domain, these should be the same\n",
- account, domain);
+ ok(!lstrcmpiA(account, domain),
+ "Got %s for account and %s for domain, these should be the same\n", account, domain);
ok(sid_use == SidTypeDomain, "Expected SidTypeDomain (%d), got %d\n", SidTypeDomain, sid_use);
HeapFree(GetProcessHeap(), 0, psid);
static void test_process_security(void)
{
BOOL res;
+ PTOKEN_USER user;
PTOKEN_OWNER owner;
PTOKEN_PRIMARY_GROUP group;
- PSID AdminSid = NULL, UsersSid = NULL;
- PACL Acl = NULL;
- SECURITY_DESCRIPTOR *SecurityDescriptor = NULL;
- char buffer[MAX_PATH];
+ PSID AdminSid = NULL, UsersSid = NULL, UserSid = NULL;
+ PACL Acl = NULL, ThreadAcl = NULL;
+ SECURITY_DESCRIPTOR *SecurityDescriptor = NULL, *ThreadSecurityDescriptor = NULL;
+ char buffer[MAX_PATH], account[MAX_PATH], domain[MAX_PATH];
PROCESS_INFORMATION info;
STARTUPINFOA startup;
- SECURITY_ATTRIBUTES psa;
+ SECURITY_ATTRIBUTES psa, tsa;
HANDLE token, event;
- DWORD size;
+ DWORD size, acc_size, dom_size, ret;
+ SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
+ PSID EveryoneSid = NULL;
+ SID_NAME_USE use;
Acl = HeapAlloc(GetProcessHeap(), 0, 256);
res = InitializeAcl(Acl, 256, ACL_REVISION);
}
ok(res, "InitializeAcl failed with error %d\n", GetLastError());
+ res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
+ ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
+
/* get owner from the token we might be running as a user not admin */
res = OpenProcessToken( GetCurrentProcess(), MAXIMUM_ALLOWED, &token );
ok(res, "OpenProcessToken failed with error %d\n", GetLastError());
owner = HeapAlloc(GetProcessHeap(), 0, size);
res = GetTokenInformation( token, TokenOwner, owner, size, &size );
ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
- AdminSid = ((TOKEN_OWNER*)owner)->Owner;
+ AdminSid = owner->Owner;
+ test_sid_str(AdminSid);
res = GetTokenInformation( token, TokenPrimaryGroup, NULL, 0, &size );
ok(!res, "Expected failure, got %d\n", res);
group = HeapAlloc(GetProcessHeap(), 0, size);
res = GetTokenInformation( token, TokenPrimaryGroup, group, size, &size );
ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
- UsersSid = ((TOKEN_PRIMARY_GROUP*)group)->PrimaryGroup;
+ UsersSid = group->PrimaryGroup;
+ test_sid_str(UsersSid);
+
+ acc_size = sizeof(account);
+ dom_size = sizeof(domain);
+ ret = LookupAccountSidA( NULL, UsersSid, account, &acc_size, domain, &dom_size, &use );
+ ok(ret, "LookupAccountSid failed with %d\n", ret);
+ ok(use == SidTypeGroup, "expect SidTypeGroup, got %d\n", use);
+ ok(!strcmp(account, "None"), "expect None, got %s\n", account);
+
+ res = GetTokenInformation( token, TokenUser, NULL, 0, &size );
+ ok(!res, "Expected failure, got %d\n", res);
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+
+ user = HeapAlloc(GetProcessHeap(), 0, size);
+ res = GetTokenInformation( token, TokenUser, user, size, &size );
+ ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
+ UserSid = user->User.Sid;
+ test_sid_str(UserSid);
+ ok(EqualPrefixSid(UsersSid, UserSid), "TokenPrimaryGroup Sid and TokenUser Sid don't match.\n");
CloseHandle( token );
if (!res)
{
HeapFree(GetProcessHeap(), 0, group);
HeapFree(GetProcessHeap(), 0, owner);
+ HeapFree(GetProcessHeap(), 0, user);
HeapFree(GetProcessHeap(), 0, Acl);
return;
}
CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR );
CHECK_SET_SECURITY( event, SACL_SECURITY_INFORMATION, ERROR_ACCESS_DENIED );
CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
- /* NULL DACL is valid and means default DACL from token */
+ /* NULL DACL is valid and means that everyone has access */
SecurityDescriptor->Control |= SE_DACL_PRESENT;
CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE);
ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_SUCCESS );
+ test_owner_equal( event, AdminSid, __LINE__ );
+
+ res = SetSecurityDescriptorGroup(SecurityDescriptor, EveryoneSid, FALSE);
+ ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
+ CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_SUCCESS );
+ test_group_equal( event, EveryoneSid, __LINE__ );
+
+ res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
+ ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
+ CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
+ /* setting a dacl should not change the owner or group */
+ test_owner_equal( event, AdminSid, __LINE__ );
+ test_group_equal( event, EveryoneSid, __LINE__ );
+
+ /* Test again with a different SID in case the previous SID also happens to
+ * be the one that is incorrectly replacing the group. */
res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, FALSE);
ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_SUCCESS );
+ test_group_equal( event, UsersSid, __LINE__ );
+
res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
+ test_group_equal( event, UsersSid, __LINE__ );
sprintf(buffer, "%s tests/security.c test", myARGV[0]);
memset(&startup, 0, sizeof(startup));
psa.lpSecurityDescriptor = SecurityDescriptor;
psa.bInheritHandle = TRUE;
+ ThreadSecurityDescriptor = HeapAlloc( GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH );
+ res = InitializeSecurityDescriptor( ThreadSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
+ ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
+
+ ThreadAcl = HeapAlloc( GetProcessHeap(), 0, 256 );
+ res = InitializeAcl( ThreadAcl, 256, ACL_REVISION );
+ ok(res, "InitializeAcl failed with error %d\n", GetLastError());
+ res = AddAccessDeniedAce( ThreadAcl, ACL_REVISION, THREAD_SET_THREAD_TOKEN, AdminSid );
+ ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError() );
+ res = AddAccessAllowedAce( ThreadAcl, ACL_REVISION, THREAD_ALL_ACCESS, AdminSid );
+ ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
+
+ res = SetSecurityDescriptorOwner( ThreadSecurityDescriptor, AdminSid, FALSE );
+ ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
+ res = SetSecurityDescriptorGroup( ThreadSecurityDescriptor, UsersSid, FALSE );
+ ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
+ res = SetSecurityDescriptorDacl( ThreadSecurityDescriptor, TRUE, ThreadAcl, FALSE );
+ ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
+
+ tsa.nLength = sizeof(tsa);
+ tsa.lpSecurityDescriptor = ThreadSecurityDescriptor;
+ tsa.bInheritHandle = TRUE;
+
/* Doesn't matter what ACL say we should get full access for ourselves */
- res = CreateProcessA( NULL, buffer, &psa, NULL, FALSE, 0, NULL, NULL, &startup, &info );
+ res = CreateProcessA( NULL, buffer, &psa, &tsa, FALSE, 0, NULL, NULL, &startup, &info );
ok(res, "CreateProcess with err:%d\n", GetLastError());
TEST_GRANTED_ACCESS2( info.hProcess, PROCESS_ALL_ACCESS_NT4,
STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
+ TEST_GRANTED_ACCESS2( info.hThread, THREAD_ALL_ACCESS_NT4,
+ STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
winetest_wait_child_process( info.hProcess );
+ FreeSid(EveryoneSid);
CloseHandle( info.hProcess );
CloseHandle( info.hThread );
CloseHandle( event );
HeapFree(GetProcessHeap(), 0, group);
HeapFree(GetProcessHeap(), 0, owner);
+ HeapFree(GetProcessHeap(), 0, user);
HeapFree(GetProcessHeap(), 0, Acl);
HeapFree(GetProcessHeap(), 0, SecurityDescriptor);
+ HeapFree(GetProcessHeap(), 0, ThreadAcl);
+ HeapFree(GetProcessHeap(), 0, ThreadSecurityDescriptor);
}
static void test_process_security_child(void)
ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
&handle1, PROCESS_ALL_ACCESS, TRUE, 0 );
err = GetLastError();
- todo_wine
ok(!ret && err == ERROR_ACCESS_DENIED, "duplicating handle should have failed "
"with STATUS_ACCESS_DENIED, instead of err:%d\n", err);
/* These two should fail - they are denied by ACL */
handle = OpenProcess( PROCESS_VM_READ, FALSE, GetCurrentProcessId() );
- todo_wine
ok(handle == NULL, "OpenProcess(PROCESS_VM_READ) should have failed\n");
handle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId() );
- todo_wine
ok(handle == NULL, "OpenProcess(PROCESS_ALL_ACCESS) should have failed\n");
/* Documented privilege elevation */
TEST_GRANTED_ACCESS( handle1, PROCESS_VM_READ );
CloseHandle( handle1 );
CloseHandle( handle );
+
+ /* Test thread security */
+ handle = OpenThread( THREAD_TERMINATE, FALSE, GetCurrentThreadId() );
+ ok(handle != NULL, "OpenThread(THREAD_TERMINATE) with err:%d\n", GetLastError());
+ TEST_GRANTED_ACCESS( handle, PROCESS_TERMINATE );
+ CloseHandle( handle );
+
+ handle = OpenThread( THREAD_SET_THREAD_TOKEN, FALSE, GetCurrentThreadId() );
+ ok(handle == NULL, "OpenThread(THREAD_SET_THREAD_TOKEN) should have failed\n");
}
static void test_impersonation_level(void)
HeapFree(GetProcessHeap(), 0, OldAcl);
}
+/* helper function for test_CreateDirectoryA */
+static void get_nt_pathW(const char *name, UNICODE_STRING *nameW)
+{
+ UNICODE_STRING strW;
+ ANSI_STRING str;
+ NTSTATUS status;
+ BOOLEAN ret;
+
+ pRtlInitAnsiString(&str, name);
+
+ status = pRtlAnsiStringToUnicodeString(&strW, &str, TRUE);
+ ok(!status, "RtlAnsiStringToUnicodeString failed with %08x\n", status);
+
+ ret = pRtlDosPathNameToNtPathName_U(strW.Buffer, nameW, NULL, NULL);
+ ok(ret, "RtlDosPathNameToNtPathName_U failed\n");
+
+ pRtlFreeUnicodeString(&strW);
+}
+
+static void test_inherited_dacl(PACL dacl, PSID admin_sid, PSID user_sid, DWORD flags, DWORD mask,
+ BOOL todo_count, BOOL todo_sid, BOOL todo_flags, int line)
+{
+ ACL_SIZE_INFORMATION acl_size;
+ ACCESS_ALLOWED_ACE *ace;
+ BOOL bret;
+
+ bret = pGetAclInformation(dacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok_(__FILE__, line)(bret, "GetAclInformation failed\n");
+
+ if (todo_count)
+ todo_wine
+ ok_(__FILE__, line)(acl_size.AceCount == 2,
+ "GetAclInformation returned unexpected entry count (%d != 2)\n",
+ acl_size.AceCount);
+ else
+ ok_(__FILE__, line)(acl_size.AceCount == 2,
+ "GetAclInformation returned unexpected entry count (%d != 2)\n",
+ acl_size.AceCount);
+
+ if (acl_size.AceCount > 0)
+ {
+ bret = pGetAce(dacl, 0, (VOID **)&ace);
+ ok_(__FILE__, line)(bret, "Failed to get Current User ACE\n");
+
+ bret = EqualSid(&ace->SidStart, user_sid);
+ if (todo_sid)
+ todo_wine
+ ok_(__FILE__, line)(bret, "Current User ACE != Current User SID\n");
+ else
+ ok_(__FILE__, line)(bret, "Current User ACE != Current User SID\n");
+
+ if (todo_flags)
+ todo_wine
+ ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags,
+ "Current User ACE has unexpected flags (0x%x != 0x%x)\n",
+ ((ACE_HEADER *)ace)->AceFlags, flags);
+ else
+ ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags,
+ "Current User ACE has unexpected flags (0x%x != 0x%x)\n",
+ ((ACE_HEADER *)ace)->AceFlags, flags);
+
+ ok_(__FILE__, line)(ace->Mask == mask,
+ "Current User ACE has unexpected mask (0x%x != 0x%x)\n",
+ ace->Mask, mask);
+ }
+ if (acl_size.AceCount > 1)
+ {
+ bret = pGetAce(dacl, 1, (VOID **)&ace);
+ ok_(__FILE__, line)(bret, "Failed to get Administators Group ACE\n");
+
+ bret = EqualSid(&ace->SidStart, admin_sid);
+ if (todo_sid)
+ todo_wine
+ ok_(__FILE__, line)(bret, "Administators Group ACE != Administators Group SID\n");
+ else
+ ok_(__FILE__, line)(bret, "Administators Group ACE != Administators Group SID\n");
+
+ if (todo_flags)
+ todo_wine
+ ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags,
+ "Administators Group ACE has unexpected flags (0x%x != 0x%x)\n",
+ ((ACE_HEADER *)ace)->AceFlags, flags);
+ else
+ ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags,
+ "Administators Group ACE has unexpected flags (0x%x != 0x%x)\n",
+ ((ACE_HEADER *)ace)->AceFlags, flags);
+
+ ok_(__FILE__, line)(ace->Mask == mask,
+ "Administators Group ACE has unexpected mask (0x%x != 0x%x)\n",
+ ace->Mask, mask);
+ }
+}
+
static void test_CreateDirectoryA(void)
{
char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], *user;
char sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
PSECURITY_DESCRIPTOR pSD = &sd;
ACL_SIZE_INFORMATION acl_size;
- ACCESS_ALLOWED_ACE *ace;
+ UNICODE_STRING tmpfileW;
SECURITY_ATTRIBUTES sa;
+ OBJECT_ATTRIBUTES attr;
+ char tmpfile[MAX_PATH];
char tmpdir[MAX_PATH];
+ HANDLE token, hTemp;
+ IO_STATUS_BLOCK io;
struct _SID *owner;
BOOL bret = TRUE;
- HANDLE token;
+ NTSTATUS status;
DWORD error;
PACL pDacl;
- if (!pGetNamedSecurityInfoA || !pCreateWellKnownSid)
+ if (!pGetSecurityInfo || !pGetNamedSecurityInfoA || !pCreateWellKnownSid)
{
win_skip("Required functions are not available\n");
return;
goto done;
}
ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
+ test_inherited_dacl(pDacl, admin_sid, user_sid, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
+ 0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
+ LocalFree(pSD);
+
+ /* Test inheritance of ACLs in CreateFile without security descriptor */
+ strcpy(tmpfile, tmpdir);
+ lstrcatA(tmpfile, "/tmpfile");
+
+ hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
+ CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ ok(hTemp != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError());
+
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
+ test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
+ 0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
+ LocalFree(pSD);
+ CloseHandle(hTemp);
+
+ /* Test inheritance of ACLs in CreateFile with security descriptor -
+ * When a security descriptor is set, then inheritance doesn't take effect */
+ pSD = &sd;
+ InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
+ pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
+ bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
+ ok(bret, "Failed to initialize ACL\n");
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+ ok(bret, "Failed to add ACL to security desciptor\n");
+
+ strcpy(tmpfile, tmpdir);
+ lstrcatA(tmpfile, "/tmpfile");
+
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = pSD;
+ sa.bInheritHandle = TRUE;
+ hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, &sa,
+ CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ ok(hTemp != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError());
+ HeapFree(GetProcessHeap(), 0, pDacl);
+ error = pGetSecurityInfo(hTemp, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
ok(bret, "GetAclInformation failed\n");
- ok(acl_size.AceCount == 2, "GetAclInformation returned unexpected entry count (%d != 2).\n",
+ ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
acl_size.AceCount);
- 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");
- todo_wine ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
- "Current User ACE has unexpected flags (0x%x != 0x03)\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, "Administators Group ACE != Administators Group SID.\n");
- todo_wine ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
- "Administators Group ACE has unexpected flags (0x%x != 0x03)\n",
- ((ACE_HEADER *)ace)->AceFlags);
- ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n",
- ace->Mask);
- }
+ LocalFree(pSD);
+
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
+ bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok(bret, "GetAclInformation failed\n");
+ ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
+ acl_size.AceCount);
+ LocalFree(pSD);
+ CloseHandle(hTemp);
+
+ /* Test inheritance of ACLs in NtCreateFile without security descriptor */
+ strcpy(tmpfile, tmpdir);
+ lstrcatA(tmpfile, "/tmpfile");
+ get_nt_pathW(tmpfile, &tmpfileW);
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = &tmpfileW;
+ attr.Attributes = OBJ_CASE_INSENSITIVE;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+
+ status = pNtCreateFile(&hTemp, GENERIC_WRITE | DELETE, &attr, &io, NULL, 0,
+ FILE_SHARE_READ, FILE_CREATE, FILE_DELETE_ON_CLOSE, NULL, 0);
+ ok(!status, "NtCreateFile failed with %08x\n", status);
+ pRtlFreeUnicodeString(&tmpfileW);
+
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
+ test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
+ 0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
+ LocalFree(pSD);
+ CloseHandle(hTemp);
+
+ /* Test inheritance of ACLs in NtCreateFile with security descriptor -
+ * When a security descriptor is set, then inheritance doesn't take effect */
+ pSD = &sd;
+ InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
+ pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
+ bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
+ ok(bret, "Failed to initialize ACL\n");
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+ ok(bret, "Failed to add ACL to security desciptor\n");
+
+ strcpy(tmpfile, tmpdir);
+ lstrcatA(tmpfile, "/tmpfile");
+ get_nt_pathW(tmpfile, &tmpfileW);
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = &tmpfileW;
+ attr.Attributes = OBJ_CASE_INSENSITIVE;
+ attr.SecurityDescriptor = pSD;
+ attr.SecurityQualityOfService = NULL;
+
+ status = pNtCreateFile(&hTemp, GENERIC_WRITE | DELETE, &attr, &io, NULL, 0,
+ FILE_SHARE_READ, FILE_CREATE, FILE_DELETE_ON_CLOSE, NULL, 0);
+ ok(!status, "NtCreateFile failed with %08x\n", status);
+ pRtlFreeUnicodeString(&tmpfileW);
+ HeapFree(GetProcessHeap(), 0, pDacl);
+
+ error = pGetSecurityInfo(hTemp, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "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 == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
+ acl_size.AceCount);
+ LocalFree(pSD);
+
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "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 == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
+ acl_size.AceCount);
+ LocalFree(pSD);
+ CloseHandle(hTemp);
+
+ /* Test inheritance of ACLs in CreateDirectory without security descriptor */
+ strcpy(tmpfile, tmpdir);
+ lstrcatA(tmpfile, "/tmpdir");
+ bret = CreateDirectoryA(tmpfile, NULL);
+ ok(bret == TRUE, "CreateDirectoryA failed with error %u\n", GetLastError());
+
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
+ test_inherited_dacl(pDacl, admin_sid, user_sid,
+ OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERITED_ACE,
+ 0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
+ LocalFree(pSD);
+ bret = RemoveDirectoryA(tmpfile);
+ ok(bret == TRUE, "RemoveDirectoryA failed with error %u\n", GetLastError());
+
+ /* Test inheritance of ACLs in CreateDirectory with security descriptor */
+ pSD = &sd;
+ InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
+ pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
+ bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
+ ok(bret, "Failed to initialize ACL\n");
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+ ok(bret, "Failed to add ACL to security desciptor\n");
+
+ strcpy(tmpfile, tmpdir);
+ lstrcatA(tmpfile, "/tmpdir1");
+
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = pSD;
+ sa.bInheritHandle = TRUE;
+ bret = CreateDirectoryA(tmpfile, &sa);
+ ok(bret == TRUE, "CreateDirectoryA failed with error %u\n", GetLastError());
+ HeapFree(GetProcessHeap(), 0, pDacl);
+
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
+ bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok(bret, "GetAclInformation failed\n");
+ ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
+ acl_size.AceCount);
+ LocalFree(pSD);
+
+ SetLastError(0xdeadbeef);
+ bret = RemoveDirectoryA(tmpfile);
+ error = GetLastError();
+ ok(bret == FALSE, "RemoveDirectoryA unexpected succeeded\n");
+ ok(error == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %u\n", error);
+
+ pSD = &sd;
+ InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
+ pDacl = HeapAlloc(GetProcessHeap(), 0, 100);
+ 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");
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+ ok(bret, "Failed to add ACL to security desciptor.\n");
+ error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL,
+ NULL, pDacl, NULL);
+ ok(error == ERROR_SUCCESS, "SetNamedSecurityInfoA failed with error %u\n", error);
+ HeapFree(GetProcessHeap(), 0, pDacl);
+
+ bret = RemoveDirectoryA(tmpfile);
+ ok(bret == TRUE, "RemoveDirectoryA failed with error %u\n", GetLastError());
+
+ /* Test inheritance of ACLs in NtCreateFile(..., FILE_DIRECTORY_FILE, ...) without security descriptor */
+ strcpy(tmpfile, tmpdir);
+ lstrcatA(tmpfile, "/tmpdir");
+ get_nt_pathW(tmpfile, &tmpfileW);
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = &tmpfileW;
+ attr.Attributes = OBJ_CASE_INSENSITIVE;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+
+ status = pNtCreateFile(&hTemp, GENERIC_READ | DELETE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ, FILE_CREATE, FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE, NULL, 0);
+ ok(!status, "NtCreateFile failed with %08x\n", status);
+ RtlFreeUnicodeString(&tmpfileW);
+
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
+ test_inherited_dacl(pDacl, admin_sid, user_sid,
+ OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERITED_ACE,
+ 0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
+ LocalFree(pSD);
+ CloseHandle(hTemp);
+
+ /* Test inheritance of ACLs in NtCreateFile(..., FILE_DIRECTORY_FILE, ...) with security descriptor */
+ pSD = &sd;
+ InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
+ pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
+ bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
+ ok(bret, "Failed to initialize ACL\n");
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+ ok(bret, "Failed to add ACL to security desciptor\n");
+
+ strcpy(tmpfile, tmpdir);
+ lstrcatA(tmpfile, "/tmpdir2");
+ get_nt_pathW(tmpfile, &tmpfileW);
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = &tmpfileW;
+ attr.Attributes = OBJ_CASE_INSENSITIVE;
+ attr.SecurityDescriptor = pSD;
+ attr.SecurityQualityOfService = NULL;
+
+ status = pNtCreateFile(&hTemp, GENERIC_READ | DELETE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ, FILE_CREATE, FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE, NULL, 0);
+ ok(!status, "NtCreateFile failed with %08x\n", status);
+ RtlFreeUnicodeString(&tmpfileW);
+ HeapFree(GetProcessHeap(), 0, pDacl);
+
+ error = pGetSecurityInfo(hTemp, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "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 == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
+ acl_size.AceCount);
+ LocalFree(pSD);
+
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "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 == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
+ acl_size.AceCount);
+ LocalFree(pSD);
+ CloseHandle(hTemp);
done:
HeapFree(GetProcessHeap(), 0, user);
char invalid_path[] = "/an invalid file path";
int users_ace_id = -1, admins_ace_id = -1, i;
char software_key[] = "MACHINE\\Software";
- char sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
+ char sd[SECURITY_DESCRIPTOR_MIN_LENGTH+sizeof(void*)];
SECURITY_DESCRIPTOR_CONTROL control;
ACL_SIZE_INFORMATION acl_size;
CHAR windows_dir[MAX_PATH];
BOOL owner_defaulted;
BOOL group_defaulted;
BOOL dacl_defaulted;
- HANDLE token, hTemp;
+ HANDLE token, hTemp, h;
PSID owner, group;
BOOL dacl_present;
PACL pDacl;
BYTE flags;
+ NTSTATUS status;
if (!pSetNamedSecurityInfoA || !pGetNamedSecurityInfoA || !pCreateWellKnownSid)
{
NULL, NULL, NULL, NULL, NULL);
ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error);
+ pDacl = NULL;
error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,
- NULL, NULL, &pDacl, NULL, NULL);
+ NULL, NULL, &pDacl, NULL, &pSD);
ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
ok(pDacl != NULL, "DACL should not be NULL\n");
+ LocalFree(pSD);
error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,OWNER_SECURITY_INFORMATION,
NULL, NULL, &pDacl, NULL, NULL);
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);
+ hTemp = CreateFileA(tmpfile, WRITE_DAC|GENERIC_WRITE, FILE_SHARE_DELETE|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);
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(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);
+ 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(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);
+
+ /* show that setting empty DACL is not removing all file permissions */
+ pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
+ bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
+ ok(bret, "Failed to initialize ACL.\n");
+ error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
+ NULL, NULL, pDacl, NULL);
+ ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error);
+ HeapFree(GetProcessHeap(), 0, pDacl);
+
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, 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");
+ if (acl_size.AceCount > 0)
+ {
+ bret = pGetAce(pDacl, 0, (VOID **)&ace);
+ ok(bret, "Failed to get ACE.\n");
+ ok(((ACE_HEADER *)ace)->AceFlags & INHERITED_ACE,
+ "ACE has unexpected flags: 0x%x\n", ((ACE_HEADER *)ace)->AceFlags);
+ }
+ LocalFree(pSD);
+
+ h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+ CloseHandle(h);
+
+ /* test setting NULL DACL */
+ error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL);
+ ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error);
+
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
+ NULL, NULL, &pDacl, NULL, &pSD);
+ ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
+ todo_wine ok(!pDacl, "pDacl != NULL\n");
+ LocalFree(pSD);
+
+ h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+ CloseHandle(h);
+
+ /* NtSetSecurityObject doesn't inherit DACL entries */
+ pSD = sd+sizeof(void*)-((ULONG_PTR)sd)%sizeof(void*);
+ InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
+ pDacl = HeapAlloc(GetProcessHeap(), 0, 100);
+ bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
+ ok(bret, "Failed to initialize ACL.\n");
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+ ok(bret, "Failed to add ACL to security desciptor.\n");
+ status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
+ ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
+
+ h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+ CloseHandle(h);
+
+ pSetSecurityDescriptorControl(pSD, SE_DACL_AUTO_INHERIT_REQ, SE_DACL_AUTO_INHERIT_REQ);
+ status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
+ ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
+
+ h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+ CloseHandle(h);
+
+ pSetSecurityDescriptorControl(pSD, SE_DACL_AUTO_INHERIT_REQ|SE_DACL_AUTO_INHERITED,
+ SE_DACL_AUTO_INHERIT_REQ|SE_DACL_AUTO_INHERITED);
+ status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
+ ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
+
+ h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+ CloseHandle(h);
+
+ /* test if DACL is properly mapped to permission */
+ 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");
+ bret = pAddAccessDeniedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
+ ok(bret, "Failed to add Current User to ACL.\n");
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+ ok(bret, "Failed to add ACL to security desciptor.\n");
+ status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
+ ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
+
+ h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+ CloseHandle(h);
+
+ bret = InitializeAcl(pDacl, 100, ACL_REVISION);
+ ok(bret, "Failed to initialize ACL.\n");
+ bret = pAddAccessDeniedAceEx(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, user_sid);
+ ok(bret, "Failed to add Current User to ACL.\n");
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+ ok(bret, "Failed to add ACL to security desciptor.\n");
+ status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
+ ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
+
+ h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+ HeapFree(GetProcessHeap(), 0, pDacl);
HeapFree(GetProcessHeap(), 0, user);
CloseHandle(hTemp);
ok(bret, "Failed to get Builtin Admins ACE.\n");
flags = ((ACE_HEADER *)ace)->AceFlags;
ok(flags == 0x0
- || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* w2k8 */,
+ || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* w2k8 */
+ || broken(flags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)), /* win7 */
"Builtin Admins ACE has unexpected flags (0x%x != 0x0)\n", flags);
ok(ace->Mask == KEY_ALL_ACCESS || broken(ace->Mask == GENERIC_ALL) /* w2k8 */,
"Builtin Admins ACE has unexpected mask (0x%x != 0x%x)\n", ace->Mask, KEY_ALL_ACCESS);
Blank, SDDL_REVISION_1, &pSD, NULL);
ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
LocalFree(pSD);
+
+ SetLastError(0xdeadbeef);
+ ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "D:P(A;;GRGW;;;BA)(A;;GRGW;;;S-1-5-21-0-0-0-1000)S:(ML;;NWNR;;;S-1-16-12288)", SDDL_REVISION_1, &pSD, NULL);
+ ok(ret || broken(!ret && GetLastError() == ERROR_INVALID_DATATYPE) /* win2k */,
+ "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %u\n", GetLastError());
+ if (ret) LocalFree(pSD);
}
static void test_ConvertSecurityDescriptorToString(void)
static void test_GetSecurityInfo(void)
{
+ char domain_users_ptr[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
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];
+ PSID domain_users_sid = (PSID) domain_users_ptr, domain_sid;
+ SID_IDENTIFIER_AUTHORITY sia = { SECURITY_NT_AUTHORITY };
+ int domain_users_ace_id = -1, admins_ace_id = -1, i;
DWORD sid_size = sizeof(admin_ptr), l = sizeof(b);
PSID admin_sid = (PSID) admin_ptr, user_sid;
char sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
+ BOOL owner_defaulted, group_defaulted;
+ BOOL dacl_defaulted, dacl_present;
ACL_SIZE_INFORMATION acl_size;
PSECURITY_DESCRIPTOR pSD;
ACCESS_ALLOWED_ACE *ace;
PSID owner, group;
BOOL bret = TRUE;
PACL pDacl;
+ BYTE flags;
DWORD ret;
if (!pGetSecurityInfo || !pSetSecurityInfo)
win_skip("Failed to get current user token\n");
return;
}
- GetTokenInformation(token, TokenUser, b, l, &l);
+ bret = GetTokenInformation(token, TokenUser, b, l, &l);
+ ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
CloseHandle( token );
user_sid = ((TOKEN_USER *)b)->User.Sid;
NULL, NULL, pDacl, NULL);
ok(ret == ERROR_SUCCESS, "SetSecurityInfo returned %d\n", ret);
ret = pGetSecurityInfo(obj, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
- NULL, NULL, &pDacl, NULL, NULL);
+ NULL, NULL, &pDacl, NULL, &pSD);
ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret);
ok(pDacl && IsValidAcl(pDacl), "GetSecurityInfo returned invalid DACL.\n");
bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
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(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);
+ 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, "Administators Group ACE != Administators Group SID.\n");
+ ok(bret, "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, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n",
- ace->Mask);
+ ok(ace->Mask == 0x1f01ff,
+ "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
}
+ LocalFree(pSD);
CloseHandle(obj);
+
+ /* Obtain the "domain users" SID from the user SID */
+ if (!AllocateAndInitializeSid(&sia, 4, *GetSidSubAuthority(user_sid, 0),
+ *GetSidSubAuthority(user_sid, 1),
+ *GetSidSubAuthority(user_sid, 2),
+ *GetSidSubAuthority(user_sid, 3), 0, 0, 0, 0, &domain_sid))
+ {
+ win_skip("Failed to get current domain SID\n");
+ return;
+ }
+ sid_size = sizeof(domain_users_ptr);
+ pCreateWellKnownSid(WinAccountDomainUsersSid, domain_sid, domain_users_sid, &sid_size);
+ FreeSid(domain_sid);
+
+ /* Test querying the ownership of a process */
+ ret = pGetSecurityInfo(GetCurrentProcess(), SE_KERNEL_OBJECT,
+ OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION,
+ NULL, NULL, NULL, NULL, &pSD);
+ ok(!ret, "GetNamedSecurityInfo failed with error %d\n", ret);
+
+ bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted);
+ ok(bret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
+ ok(owner != NULL, "owner should not be NULL\n");
+ ok(EqualSid(owner, admin_sid) || EqualSid(owner, user_sid),
+ "Process owner SID != Administrators SID.\n");
+
+ bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted);
+ ok(bret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
+ ok(group != NULL, "group should not be NULL\n");
+ ok(EqualSid(group, domain_users_sid), "Process group SID != Domain Users SID.\n");
+ LocalFree(pSD);
+
+ /* Test querying the DACL of a process */
+ ret = pGetSecurityInfo(GetCurrentProcess(), SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
+ NULL, NULL, NULL, NULL, &pSD);
+ ok(!ret, "GetSecurityInfo failed with error %d\n", ret);
+
+ bret = GetSecurityDescriptorDacl(pSD, &dacl_present, &pDacl, &dacl_defaulted);
+ ok(bret, "GetSecurityDescriptorDacl failed with error %d\n", GetLastError());
+ ok(dacl_present, "DACL should be present\n");
+ ok(pDacl && IsValidAcl(pDacl), "GetSecurityDescriptorDacl returned invalid DACL.\n");
+ bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok(bret, "GetAclInformation failed\n");
+ ok(acl_size.AceCount != 0, "GetAclInformation returned no ACLs\n");
+ for (i=0; i<acl_size.AceCount; i++)
+ {
+ bret = pGetAce(pDacl, i, (VOID **)&ace);
+ ok(bret, "Failed to get ACE %d.\n", i);
+ bret = EqualSid(&ace->SidStart, domain_users_sid);
+ if (bret) domain_users_ace_id = i;
+ bret = EqualSid(&ace->SidStart, admin_sid);
+ if (bret) admins_ace_id = i;
+ }
+ ok(domain_users_ace_id != -1 || broken(domain_users_ace_id == -1) /* win2k */,
+ "Domain Users ACE not found.\n");
+ if (domain_users_ace_id != -1)
+ {
+ bret = pGetAce(pDacl, domain_users_ace_id, (VOID **)&ace);
+ ok(bret, "Failed to get Domain Users ACE.\n");
+ flags = ((ACE_HEADER *)ace)->AceFlags;
+ ok(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE),
+ "Domain Users ACE has unexpected flags (0x%x != 0x%x)\n", flags,
+ INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE);
+ ok(ace->Mask == GENERIC_READ, "Domain Users ACE has unexpected mask (0x%x != 0x%x)\n",
+ ace->Mask, GENERIC_READ);
+ }
+ ok(admins_ace_id != -1 || broken(admins_ace_id == -1) /* xp */,
+ "Builtin Admins ACE not found.\n");
+ if (admins_ace_id != -1)
+ {
+ bret = pGetAce(pDacl, admins_ace_id, (VOID **)&ace);
+ ok(bret, "Failed to get Builtin Admins ACE.\n");
+ flags = ((ACE_HEADER *)ace)->AceFlags;
+ ok(flags == 0x0, "Builtin Admins ACE has unexpected flags (0x%x != 0x0)\n", flags);
+ ok(ace->Mask == PROCESS_ALL_ACCESS || broken(ace->Mask == 0x1f0fff) /* win2k */,
+ "Builtin Admins ACE has unexpected mask (0x%x != 0x%x)\n", ace->Mask, PROCESS_ALL_ACCESS);
+ }
+ LocalFree(pSD);
}
static void test_GetSidSubAuthority(void)
static void test_default_handle_security(HANDLE token, HANDLE handle, GENERIC_MAPPING *mapping)
{
- DWORD ret, length, needed, granted, priv_set_len;
+ DWORD ret, granted, priv_set_len;
BOOL status;
PRIVILEGE_SET priv_set;
SECURITY_DESCRIPTOR *sd;
- needed = 0xdeadbeef;
- SetLastError(0xdeadbeef);
- ret = GetKernelObjectSecurity(handle, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
- NULL, 0, &needed);
- ok(!ret, "GetKernelObjectSecurity should fail\n");
- ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
- ok(needed != 0xdeadbeef, "GetKernelObjectSecurity should return required buffer length\n");
-
- length = needed;
- sd = HeapAlloc(GetProcessHeap(), 0, length);
-
- needed = 0xdeadbeef;
- SetLastError(0xdeadbeef);
- ret = GetKernelObjectSecurity(handle, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
- sd, length, &needed);
- ok(ret, "GetKernelObjectSecurity error %d\n", GetLastError());
- ok(needed == length || needed == 0 /* file, pipe */, "GetKernelObjectSecurity should return %u instead of %u\n", length, needed);
-
+ sd = test_get_security_descriptor(handle, __LINE__);
validate_default_security_descriptor(sd);
priv_set_len = sizeof(priv_set);
{
case GENERIC_READ:
case GENERIC_EXECUTE:
- ok(access == map[i].mapped || access == (map[i].mapped | THREAD_QUERY_LIMITED_INFORMATION) /* Vista+ */,
+ ok(access == map[i].mapped ||
+ access == (map[i].mapped | THREAD_QUERY_LIMITED_INFORMATION) /* Vista+ */ ||
+ access == (map[i].mapped | THREAD_QUERY_LIMITED_INFORMATION | THREAD_RESUME) /* win8 */,
"%d: expected %#x, got %#x\n", i, map[i].mapped, access);
break;
case GENERIC_WRITE:
todo_wine
- ok(access == map[i].mapped || access == (map[i].mapped | THREAD_SET_LIMITED_INFORMATION) /* Vista+ */,
+ ok(access == map[i].mapped ||
+ access == (map[i].mapped | THREAD_SET_LIMITED_INFORMATION) /* Vista+ */ ||
+ access == (map[i].mapped | THREAD_SET_LIMITED_INFORMATION | THREAD_RESUME) /* win8 */,
"%d: expected %#x, got %#x\n", i, map[i].mapped, access);
break;
case GENERIC_ALL:
CloseHandle(dup);
}
+ SetLastError( 0xdeadbeef );
+ ret = DuplicateHandle(GetCurrentProcess(), thread, GetCurrentProcess(), &dup,
+ THREAD_QUERY_INFORMATION, FALSE, 0);
+ ok(ret, "DuplicateHandle error %d\n", GetLastError());
+ access = get_obj_access(dup);
+ ok(access == (THREAD_QUERY_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION) /* Vista+ */ ||
+ access == THREAD_QUERY_INFORMATION /* before Vista */,
+ "expected THREAD_QUERY_INFORMATION|THREAD_QUERY_LIMITED_INFORMATION, got %#x\n", access);
+ CloseHandle(dup);
+
TerminateThread(thread, 0);
CloseHandle(thread);
}
"%d: expected %#x, got %#x\n", i, map[i].mapped, access);
break;
case GENERIC_WRITE:
- ok(access == map[i].mapped || access == (map[i].mapped | PROCESS_TERMINATE) /* before Vista */,
+ ok(access == map[i].mapped ||
+ access == (map[i].mapped | PROCESS_TERMINATE) /* before Vista */ ||
+ access == (map[i].mapped | PROCESS_SET_LIMITED_INFORMATION) /* win8 */,
"%d: expected %#x, got %#x\n", i, map[i].mapped, access);
break;
case GENERIC_EXECUTE:
CloseHandle(dup);
}
+ SetLastError( 0xdeadbeef );
+ ret = DuplicateHandle(GetCurrentProcess(), process, GetCurrentProcess(), &dup,
+ PROCESS_QUERY_INFORMATION, FALSE, 0);
+ ok(ret, "DuplicateHandle error %d\n", GetLastError());
+ access = get_obj_access(dup);
+ ok(access == (PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION) /* Vista+ */ ||
+ access == PROCESS_QUERY_INFORMATION /* before Vista */,
+ "expected PROCESS_QUERY_INFORMATION|PROCESS_QUERY_LIMITED_INFORMATION, got %#x\n", access);
+ CloseHandle(dup);
+
TerminateProcess(process, 0);
CloseHandle(process);
}
ret = GetSecurityDescriptorOwner( sd, &owner, &defaulted );
ok( ret, "error %u\n", GetLastError() );
ok( owner != (void *)0xdeadbeef, "owner not set\n" );
- todo_wine ok( !defaulted, "owner defaulted\n" );
+ ok( !defaulted, "owner defaulted\n" );
dacl = (void *)0xdeadbeef;
present = FALSE;
ok( ret, "error %u\n", GetLastError() );
ok( present, "dacl not present\n" );
ok( dacl != (void *)0xdeadbeef, "dacl not set\n" );
- todo_wine ok( !defaulted, "dacl defaulted\n" );
+ ok( !defaulted, "dacl defaulted\n" );
index = 0;
found = FALSE;
CloseHandle(token);
}
+static void test_AddAce(void)
+{
+ static SID const sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
+
+ char acl_buf[1024], ace_buf[256];
+ ACCESS_ALLOWED_ACE *ace = (ACCESS_ALLOWED_ACE*)ace_buf;
+ PACL acl = (PACL)acl_buf;
+ BOOL ret;
+
+ memset(ace, 0, sizeof(ace_buf));
+ ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
+ ace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD)+sizeof(SID);
+ memcpy(&ace->SidStart, &sidWorld, sizeof(sidWorld));
+
+ ret = InitializeAcl(acl, sizeof(acl_buf), ACL_REVISION2);
+ ok(ret, "InitializeAcl failed: %d\n", GetLastError());
+
+ ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize);
+ ok(ret, "AddAce failed: %d\n", GetLastError());
+ ret = AddAce(acl, ACL_REVISION2, MAXDWORD, ace, ace->Header.AceSize);
+ ok(ret, "AddAce failed: %d\n", GetLastError());
+ ret = AddAce(acl, ACL_REVISION3, MAXDWORD, ace, ace->Header.AceSize);
+ ok(ret, "AddAce failed: %d\n", GetLastError());
+ ok(acl->AclRevision == ACL_REVISION3, "acl->AclRevision = %d\n", acl->AclRevision);
+ ret = AddAce(acl, ACL_REVISION4, MAXDWORD, ace, ace->Header.AceSize);
+ ok(ret, "AddAce failed: %d\n", GetLastError());
+ ok(acl->AclRevision == ACL_REVISION4, "acl->AclRevision = %d\n", acl->AclRevision);
+ ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize);
+ ok(ret, "AddAce failed: %d\n", GetLastError());
+ ok(acl->AclRevision == ACL_REVISION4, "acl->AclRevision = %d\n", acl->AclRevision);
+ ret = AddAce(acl, ACL_REVISION2, MAXDWORD, ace, ace->Header.AceSize);
+ ok(ret, "AddAce failed: %d\n", GetLastError());
+
+ ret = AddAce(acl, MIN_ACL_REVISION-1, MAXDWORD, ace, ace->Header.AceSize);
+ ok(ret, "AddAce failed: %d\n", GetLastError());
+ /* next test succeededs but corrupts ACL */
+ ret = AddAce(acl, MAX_ACL_REVISION+1, MAXDWORD, ace, ace->Header.AceSize);
+ ok(ret, "AddAce failed: %d\n", GetLastError());
+ ok(acl->AclRevision == MAX_ACL_REVISION+1, "acl->AclRevision = %d\n", acl->AclRevision);
+ SetLastError(0xdeadbeef);
+ ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize);
+ ok(!ret, "AddAce succeeded\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError() = %d\n", GetLastError());
+}
+
+static void test_system_security_access(void)
+{
+ static const WCHAR testkeyW[] =
+ {'S','O','F','T','W','A','R','E','\\','W','i','n','e','\\','S','A','C','L','t','e','s','t',0};
+ LONG res;
+ HKEY hkey;
+ PSECURITY_DESCRIPTOR sd;
+ ACL *sacl;
+ DWORD err, len = 128;
+ TOKEN_PRIVILEGES priv, *priv_prev;
+ HANDLE token;
+ LUID luid;
+ BOOL ret;
+
+ if (!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &token )) return;
+ if (!LookupPrivilegeValueA( NULL, SE_SECURITY_NAME, &luid ))
+ {
+ CloseHandle( token );
+ return;
+ }
+
+ /* ACCESS_SYSTEM_SECURITY requires special privilege */
+ res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ|ACCESS_SYSTEM_SECURITY, NULL, &hkey, NULL );
+ if (res == ERROR_ACCESS_DENIED)
+ {
+ skip( "unprivileged user\n" );
+ CloseHandle( token );
+ return;
+ }
+ todo_wine ok( res == ERROR_PRIVILEGE_NOT_HELD, "got %d\n", res );
+
+ priv.PrivilegeCount = 1;
+ priv.Privileges[0].Luid = luid;
+ priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ priv_prev = HeapAlloc( GetProcessHeap(), 0, len );
+ ret = AdjustTokenPrivileges( token, FALSE, &priv, len, priv_prev, &len );
+ ok( ret, "got %u\n", GetLastError());
+
+ res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ|ACCESS_SYSTEM_SECURITY, NULL, &hkey, NULL );
+ if (res == ERROR_PRIVILEGE_NOT_HELD)
+ {
+ win_skip( "privilege not held\n" );
+ HeapFree( GetProcessHeap(), 0, priv_prev );
+ CloseHandle( token );
+ return;
+ }
+ ok( !res, "got %d\n", res );
+
+ /* restore privileges */
+ ret = AdjustTokenPrivileges( token, FALSE, priv_prev, 0, NULL, NULL );
+ ok( ret, "got %u\n", GetLastError() );
+ HeapFree( GetProcessHeap(), 0, priv_prev );
+
+ /* privilege is checked on access */
+ err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
+ todo_wine ok( err == ERROR_PRIVILEGE_NOT_HELD, "got %u\n", err );
+
+ priv.PrivilegeCount = 1;
+ priv.Privileges[0].Luid = luid;
+ priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ priv_prev = HeapAlloc( GetProcessHeap(), 0, len );
+ ret = AdjustTokenPrivileges( token, FALSE, &priv, len, priv_prev, &len );
+ ok( ret, "got %u\n", GetLastError());
+
+ err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
+ ok( err == ERROR_SUCCESS, "got %u\n", err );
+ RegCloseKey( hkey );
+ LocalFree( sd );
+
+ /* handle created without ACCESS_SYSTEM_SECURITY, privilege held */
+ res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ, NULL, &hkey, NULL );
+ ok( res == ERROR_SUCCESS, "got %d\n", res );
+
+ sd = NULL;
+ err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
+ todo_wine ok( err == ERROR_SUCCESS, "got %u\n", err );
+ RegCloseKey( hkey );
+ LocalFree( sd );
+
+ /* restore privileges */
+ ret = AdjustTokenPrivileges( token, FALSE, priv_prev, 0, NULL, NULL );
+ ok( ret, "got %u\n", GetLastError() );
+ HeapFree( GetProcessHeap(), 0, priv_prev );
+
+ /* handle created without ACCESS_SYSTEM_SECURITY, privilege not held */
+ res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ, NULL, &hkey, NULL );
+ ok( res == ERROR_SUCCESS, "got %d\n", res );
+
+ err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
+ todo_wine ok( err == ERROR_PRIVILEGE_NOT_HELD, "got %u\n", err );
+ RegCloseKey( hkey );
+
+ res = RegDeleteKeyW( HKEY_LOCAL_MACHINE, testkeyW );
+ ok( !res, "got %d\n", res );
+ CloseHandle( token );
+}
+
+static void test_GetWindowsAccountDomainSid(void)
+{
+ char *user, buffer1[SECURITY_MAX_SID_SIZE], buffer2[SECURITY_MAX_SID_SIZE];
+ SID_IDENTIFIER_AUTHORITY domain_ident = { SECURITY_NT_AUTHORITY };
+ PSID domain_sid = (PSID *)&buffer1;
+ PSID domain_sid2 = (PSID *)&buffer2;
+ DWORD sid_size;
+ PSID user_sid;
+ HANDLE token;
+ BOOL bret = TRUE;
+ int i;
+
+ if (!pGetWindowsAccountDomainSid)
+ {
+ win_skip("GetWindowsAccountDomainSid not available\n");
+ return;
+ }
+
+ 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;
+ }
+
+ bret = GetTokenInformation(token, TokenUser, NULL, 0, &sid_size);
+ ok(!bret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
+ user = HeapAlloc(GetProcessHeap(), 0, sid_size);
+ bret = GetTokenInformation(token, TokenUser, user, sid_size, &sid_size);
+ ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
+ CloseHandle(token);
+ user_sid = ((TOKEN_USER *)user)->User.Sid;
+
+ SetLastError(0xdeadbeef);
+ bret = pGetWindowsAccountDomainSid(0, 0, 0);
+ ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
+ ok(GetLastError() == ERROR_INVALID_SID, "expected ERROR_INVALID_SID, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ bret = pGetWindowsAccountDomainSid(user_sid, 0, 0);
+ ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ sid_size = SECURITY_MAX_SID_SIZE;
+ SetLastError(0xdeadbeef);
+ bret = pGetWindowsAccountDomainSid(user_sid, 0, &sid_size);
+ ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+ ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size);
+
+ SetLastError(0xdeadbeef);
+ bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, 0);
+ ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ sid_size = 1;
+ SetLastError(0xdeadbeef);
+ bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, &sid_size);
+ ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size);
+
+ sid_size = SECURITY_MAX_SID_SIZE;
+ bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, &sid_size);
+ ok(bret, "GetWindowsAccountDomainSid failed with error %d\n", GetLastError());
+ ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size);
+ InitializeSid(domain_sid2, &domain_ident, 4);
+ for (i = 0; i < 4; i++)
+ *GetSidSubAuthority(domain_sid2, i) = *GetSidSubAuthority(user_sid, i);
+ ok(EqualSid(domain_sid, domain_sid2), "unexpected domain sid\n");
+
+ HeapFree(GetProcessHeap(), 0, user);
+}
+
START_TEST(security)
{
init();
test_ConvertSecurityDescriptorToString();
test_PrivateObjectSecurity();
test_acls();
+ test_GetWindowsAccountDomainSid();
test_GetSecurityInfo();
test_GetSidSubAuthority();
test_CheckTokenMembership();
test_TokenIntegrityLevel();
test_default_dacl_owner_sid();
test_AdjustTokenPrivileges();
+ test_AddAce();
+ test_system_security_access();
}