server: fix for default_set_sd which contained a number of issues related to setting defaults from tokens.

Joris van der Wel joris at jorisvanderwel.com
Tue Jun 24 17:04:20 CDT 2014


server: fix for default_set_sd which contained a number of issues related
to setting defaults from tokens.

* SetSecurityInfo should not reset owner and group to default if
SECURITY_INFORMATION does not contain OWNER_SECURITY_INFORMATION or
GROUP_SECURITY_INFORMATION
* The create functions for objects (create_event, create_mapping,
create_mutex, create_semaphore) should set defaults if the security
descriptor is NULL (it already did this properly if the security descriptor
is empty).
* For certain objects: The impersonation token of the thread should also be
used to determine the default owner, dacl, not just the primary token.
* Any of the 4 SE_*_DEFAULTED controls should not be stored on the object,
their usage is transient

Tested on Wine, XP sp3, Vista sp2 and 8.1 update 1

---
 dlls/advapi32/tests/security.c | 225
+++++++++++++++++++++++++++++++++--------
 server/event.c                 |  50 ++++-----
 server/mapping.c               |   8 +-
 server/mutex.c                 |  40 ++++----
 server/object.c                |  92 ++++++++++++-----
 server/object.h                |   7 +-
 server/semaphore.c             |  40 ++++----
 server/timer.c                 |  32 +++---
 8 files changed, 340 insertions(+), 154 deletions(-)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-patches/attachments/20140625/066de437/attachment-0001.html>
-------------- next part --------------
From 4424e62abbaac3ffe4073a38740e4eb6ee60316a Mon Sep 17 00:00:00 2001
From: Joris van der Wel <joris at jorisvanderwel.com>
Date: Tue, 24 Jun 2014 22:51:40 +0200
Subject: server: fix for default_set_sd which contained a number of issues
 related to setting defaults from tokens.

* SetSecurityInfo should not reset owner and group to default if SECURITY_INFORMATION does not contain OWNER_SECURITY_INFORMATION or GROUP_SECURITY_INFORMATION
* The create functions for objects (create_event, create_mapping, create_mutex, create_semaphore) should set defaults if the security descriptor is NULL (it already did this properly if the security descriptor is empty).
* For certain objects: The impersonation token of the thread should also be used to determine the default owner, dacl, not just the primary token.
* Any of the 4 SE_*_DEFAULTED controls should not be stored on the object, their usage is transient
---
 dlls/advapi32/tests/security.c | 225 +++++++++++++++++++++++++++++++++--------
 server/event.c                 |  50 ++++-----
 server/mapping.c               |   8 +-
 server/mutex.c                 |  40 ++++----
 server/object.c                |  92 ++++++++++++-----
 server/object.h                |   7 +-
 server/semaphore.c             |  40 ++++----
 server/timer.c                 |  32 +++---
 8 files changed, 340 insertions(+), 154 deletions(-)

diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index 05da0ae..ac9e15e 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -208,6 +208,32 @@ static void init(void)
     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_sid(void)
 {
     struct sidRef refs[] = {
@@ -2464,6 +2490,88 @@ static void test_granted_access(HANDLE handle, ACCESS_MASK access,
                "with %s, instead of %d\n", #e, err); \
     }while(0)
 
+#define CHECK_DACL_IS_NULL(o) \
+    do{ \
+        SECURITY_DESCRIPTOR *queriedSD = NULL; \
+        PACL queriedAcl = NULL; \
+        BOOL dacl_present; \
+        BOOL dacl_defaulted; \
+        SECURITY_DESCRIPTOR_CONTROL control; \
+        DWORD revision; \
+        queriedSD = test_get_security_descriptor( o, __LINE__ ); \
+        queriedAcl = (PACL)0xdeadbeef; \
+        res = GetSecurityDescriptorDacl(queriedSD, &dacl_present, &queriedAcl, &dacl_defaulted); \
+        ok(res, "GetSecurityDescriptorDacl failed with error %d\n", GetLastError()); \
+        res = GetSecurityDescriptorControl(queriedSD, &control, &revision); \
+        ok(res, "GetSecurityDescriptorControl failed with error %d\n", GetLastError()); \
+        ok(dacl_present, "DACL should be present (even though the DACL is NULL)\n"); \
+        ok(queriedAcl == NULL, "Setting a NULL DACL, should also return a NULL DACL\n"); \
+        ok(!dacl_defaulted, "Defaulted is true\n"); \
+        ok((control & SE_DACL_DEFAULTED) == 0, "SE_DACL_DEFAULTED is set\n"); \
+        HeapFree(GetProcessHeap(), 0, queriedSD); \
+    }while(0)
+    
+#define CHECK_DACL_IS_SET(o) \
+    do{ \
+        SECURITY_DESCRIPTOR *queriedSD = NULL; \
+        PACL queriedAcl = NULL; \
+        BOOL dacl_present; \
+        BOOL dacl_defaulted; \
+        SECURITY_DESCRIPTOR_CONTROL control; \
+        DWORD revision; \
+        queriedSD = test_get_security_descriptor( o, __LINE__ ); \
+        queriedAcl = (PACL)0xdeadbeef; \
+        res = GetSecurityDescriptorDacl(queriedSD, &dacl_present, &queriedAcl, &dacl_defaulted); \
+        ok(res, "GetSecurityDescriptorDacl failed with error %d\n", GetLastError()); \
+        res = GetSecurityDescriptorControl(queriedSD, &control, &revision); \
+        ok(res, "GetSecurityDescriptorControl failed with error %d\n", GetLastError()); \
+        ok(dacl_present, "DACL should be present\n"); \
+        ok(queriedAcl != NULL, "DACL is NULL\n"); \
+        ok(!dacl_defaulted, "Defaulted is true\n"); \
+        ok((control & SE_DACL_DEFAULTED) == 0, "SE_DACL_DEFAULTED is set\n"); \
+        HeapFree(GetProcessHeap(), 0, queriedSD); \
+    }while(0)
+
+#define CHECK_GROUP( o, expected ) \
+    do {\
+        SECURITY_DESCRIPTOR *queriedSD = NULL; \
+        PSID group; \
+        BOOL group_defaulted; \
+        SECURITY_DESCRIPTOR_CONTROL control; \
+        DWORD revision; \
+        LPSTR sid_str = NULL; \
+        queriedSD = test_get_security_descriptor( o, __LINE__ ); \
+        res = GetSecurityDescriptorGroup(queriedSD, &group, &group_defaulted); \
+        ok(res, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError()); \
+        res = pConvertSidToStringSidA( group, &sid_str ); \
+        ok(res, "ConvertSidToStringSidA failed with error %d\n", GetLastError()); \
+        res = GetSecurityDescriptorControl(queriedSD, &control, &revision); \
+        ok(res, "GetSecurityDescriptorControl failed with error %d\n", GetLastError()); \
+        ok(EqualSid(group, expected), "Group SIDs are not equal, actual value is %s\n", sid_str); \
+        ok(!group_defaulted, "Defaulted is true\n"); \
+        ok((control & SE_GROUP_DEFAULTED) == 0, "SE_GROUP_DEFAULTED is set\n"); \
+        HeapFree(GetProcessHeap(), 0, queriedSD); \
+        LocalFree(sid_str); \
+    }while(0)
+    
+#define CHECK_GROUP_IS_SET( o ) \
+do {\
+    SECURITY_DESCRIPTOR *queriedSD = NULL; \
+    PSID group; \
+    BOOL group_defaulted; \
+    SECURITY_DESCRIPTOR_CONTROL control; \
+    DWORD revision; \
+    queriedSD = test_get_security_descriptor( o, __LINE__ ); \
+    res = GetSecurityDescriptorGroup(queriedSD, &group, &group_defaulted); \
+    ok(res, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError()); \
+    res = GetSecurityDescriptorControl(queriedSD, &control, &revision); \
+    ok(res, "GetSecurityDescriptorControl failed with error %d\n", GetLastError()); \
+    ok(group != NULL, "Group SID is NULL\n"); \
+    ok(!group_defaulted, "Defaulted is true"); \
+    ok((control & SE_GROUP_DEFAULTED) == 0, "SE_GROUP_DEFAULTED is set\n"); \
+    HeapFree(GetProcessHeap(), 0, queriedSD); \
+}while(0)
+
 static void test_process_security(void)
 {
     BOOL res;
@@ -2475,9 +2583,11 @@ static void test_process_security(void)
     char buffer[MAX_PATH];
     PROCESS_INFORMATION info;
     STARTUPINFOA startup;
-    SECURITY_ATTRIBUTES psa;
+    SECURITY_ATTRIBUTES sa;
     HANDLE token, event;
     DWORD size;
+    SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
+    PSID EveryoneSid = NULL;
 
     Acl = HeapAlloc(GetProcessHeap(), 0, 256);
     res = InitializeAcl(Acl, 256, ACL_REVISION);
@@ -2488,6 +2598,9 @@ static void test_process_security(void)
         return;
     }
     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 );
@@ -2538,29 +2651,69 @@ static void test_process_security(void)
 
     event = CreateEventA( NULL, TRUE, TRUE, "test_event" );
     ok(event != NULL, "CreateEvent %d\n", GetLastError());
+    /* lpEventAttributes is NULL and therefore no security descriptor has been set yet.
+     * The dacl should have been set according to the primary token of the creating 
+     * process (TOKEN_DEFAULT_DACL)
+     */ 
+    CHECK_DACL_IS_SET( event );
+    CHECK_GROUP_IS_SET( event );
 
     SecurityDescriptor->Revision = 0;
     CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_UNKNOWN_REVISION );
+    CHECK_DACL_IS_SET( event );
+    CHECK_GROUP_IS_SET( event );
     SecurityDescriptor->Revision = SECURITY_DESCRIPTOR_REVISION;
 
     CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR );
     CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR );
     CHECK_SET_SECURITY( event, SACL_SECURITY_INFORMATION, ERROR_ACCESS_DENIED );
+    CHECK_DACL_IS_SET( event );
+    CHECK_GROUP_IS_SET( event );
     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 */
+    CHECK_DACL_IS_NULL( event );
+    CHECK_GROUP_IS_SET( event );
+    
     SecurityDescriptor->Control |= SE_DACL_PRESENT;
     CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
+    CHECK_DACL_IS_NULL( event );
+    CHECK_GROUP_IS_SET( event );
 
     /* Set owner and group and dacl */
     res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE);
     ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
     CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_SUCCESS );
+    CHECK_DACL_IS_NULL( event ); /* DACL should remain NULL for now */
+    CHECK_GROUP_IS_SET( event );
     res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, FALSE);
     ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
+    CHECK_DACL_IS_NULL( event ); /* DACL should remain NULL for now */
     CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_SUCCESS );
+    CHECK_GROUP( event, UsersSid );
     res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
     ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
     CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
+    CHECK_DACL_IS_SET( event );
+    CHECK_GROUP( event, UsersSid );
+    /* set the user again, the previous DACL should remain set even though 
+       the security descriptor has a different DACL 
+       (DACL_SECURITY_INFORMATION is not given) */
+    res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, NULL, FALSE);
+    ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
+    CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_SUCCESS );
+    CHECK_DACL_IS_SET( event );
+
+    /* set a different group, it should remain set even if we change the dacl */
+    res = SetSecurityDescriptorGroup(SecurityDescriptor, EveryoneSid, FALSE);
+    ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
+    CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_SUCCESS );
+    CHECK_GROUP( event, EveryoneSid );
+    CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
+    CHECK_DACL_IS_NULL( event );
+    CHECK_GROUP( event, EveryoneSid );
+    
+    res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
+    ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
 
     sprintf(buffer, "%s tests/security.c test", myARGV[0]);
     memset(&startup, 0, sizeof(startup));
@@ -2568,12 +2721,12 @@ static void test_process_security(void)
     startup.dwFlags = STARTF_USESHOWWINDOW;
     startup.wShowWindow = SW_SHOWNORMAL;
 
-    psa.nLength = sizeof(psa);
-    psa.lpSecurityDescriptor = SecurityDescriptor;
-    psa.bInheritHandle = TRUE;
+    sa.nLength = sizeof(sa);
+    sa.lpSecurityDescriptor = SecurityDescriptor;
+    sa.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, &sa, NULL, 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 );
@@ -2586,6 +2739,7 @@ static void test_process_security(void)
     HeapFree(GetProcessHeap(), 0, owner);
     HeapFree(GetProcessHeap(), 0, Acl);
     HeapFree(GetProcessHeap(), 0, SecurityDescriptor);
+    FreeSid(EveryoneSid);
 }
 
 static void test_process_security_child(void)
@@ -4390,7 +4544,7 @@ static void test_CreateRestrictedToken(void)
     CloseHandle(process_token);
 }
 
-static void validate_default_security_descriptor(SECURITY_DESCRIPTOR *sd)
+static void validate_default_security_descriptor(SECURITY_DESCRIPTOR *sd, const char *todo_platform)
 {
     BOOL ret, present, defaulted;
     ACL *acl;
@@ -4405,9 +4559,9 @@ static void validate_default_security_descriptor(SECURITY_DESCRIPTOR *sd)
     SetLastError(0xdeadbeef);
     ret = GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted);
     ok(ret, "GetSecurityDescriptorDacl error %d\n", GetLastError());
-todo_wine
+todo(todo_platform)
     ok(present == 1, "acl is not present\n");
-todo_wine
+todo(todo_platform)
     ok(acl != (void *)0xdeadbeef && acl != NULL, "acl pointer is not set\n");
     ok(defaulted == 0, "defaulted is set to TRUE\n");
 
@@ -4416,7 +4570,7 @@ todo_wine
     SetLastError(0xdeadbeef);
     ret = GetSecurityDescriptorOwner(sd, &sid, &defaulted);
     ok(ret, "GetSecurityDescriptorOwner error %d\n", GetLastError());
-todo_wine
+todo(todo_platform)
     ok(sid != (void *)0xdeadbeef && sid != NULL, "sid pointer is not set\n");
     ok(defaulted == 0, "defaulted is set to TRUE\n");
 
@@ -4425,44 +4579,27 @@ todo_wine
     SetLastError(0xdeadbeef);
     ret = GetSecurityDescriptorGroup(sd, &sid, &defaulted);
     ok(ret, "GetSecurityDescriptorGroup error %d\n", GetLastError());
-todo_wine
+todo(todo_platform)
     ok(sid != (void *)0xdeadbeef && sid != NULL, "sid pointer is not set\n");
     ok(defaulted == 0, "defaulted is set to TRUE\n");
 }
 
-static void test_default_handle_security(HANDLE token, HANDLE handle, GENERIC_MAPPING *mapping)
+static void test_default_handle_security(HANDLE token, HANDLE handle, GENERIC_MAPPING *mapping, const char *todo_platform)
 {
-    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);
-
-    validate_default_security_descriptor(sd);
+    sd = test_get_security_descriptor(handle, __LINE__);
+    validate_default_security_descriptor(sd, todo_platform);
 
     priv_set_len = sizeof(priv_set);
     granted = 0xdeadbeef;
     status = 0xdeadbeef;
     SetLastError(0xdeadbeef);
     ret = AccessCheck(sd, token, MAXIMUM_ALLOWED, mapping, &priv_set, &priv_set_len, &granted, &status);
-todo_wine {
+todo(todo_platform) {
     ok(ret, "AccessCheck error %d\n", GetLastError());
     ok(status == 1, "expected 1, got %d\n", status);
     ok(granted == mapping->GenericAll, "expected all access %#x, got %#x\n", mapping->GenericAll, granted);
@@ -4472,7 +4609,7 @@ todo_wine {
     status = 0xdeadbeef;
     SetLastError(0xdeadbeef);
     ret = AccessCheck(sd, token, 0, mapping, &priv_set, &priv_set_len, &granted, &status);
-todo_wine {
+todo(todo_platform) {
     ok(ret, "AccessCheck error %d\n", GetLastError());
     ok(status == 0 || broken(status == 1) /* NT4 */, "expected 0, got %d\n", status);
     ok(granted == 0 || broken(granted == mapping->GenericRead) /* NT4 */, "expected 0, got %#x\n", granted);
@@ -4482,7 +4619,7 @@ todo_wine {
     status = 0xdeadbeef;
     SetLastError(0xdeadbeef);
     ret = AccessCheck(sd, token, ACCESS_SYSTEM_SECURITY, mapping, &priv_set, &priv_set_len, &granted, &status);
-todo_wine {
+todo(todo_platform) {
     ok(ret, "AccessCheck error %d\n", GetLastError());
     ok(status == 0, "expected 0, got %d\n", status);
     ok(granted == 0, "expected 0, got %#x\n", granted);
@@ -4492,7 +4629,7 @@ todo_wine {
     status = 0xdeadbeef;
     SetLastError(0xdeadbeef);
     ret = AccessCheck(sd, token, mapping->GenericRead, mapping, &priv_set, &priv_set_len, &granted, &status);
-todo_wine {
+todo(todo_platform) {
     ok(ret, "AccessCheck error %d\n", GetLastError());
     ok(status == 1, "expected 1, got %d\n", status);
     ok(granted == mapping->GenericRead, "expected read access %#x, got %#x\n", mapping->GenericRead, granted);
@@ -4502,7 +4639,7 @@ todo_wine {
     status = 0xdeadbeef;
     SetLastError(0xdeadbeef);
     ret = AccessCheck(sd, token, mapping->GenericWrite, mapping, &priv_set, &priv_set_len, &granted, &status);
-todo_wine {
+todo(todo_platform) {
     ok(ret, "AccessCheck error %d\n", GetLastError());
     ok(status == 1, "expected 1, got %d\n", status);
     ok(granted == mapping->GenericWrite, "expected write access %#x, got %#x\n", mapping->GenericWrite, granted);
@@ -4512,7 +4649,7 @@ todo_wine {
     status = 0xdeadbeef;
     SetLastError(0xdeadbeef);
     ret = AccessCheck(sd, token, mapping->GenericExecute, mapping, &priv_set, &priv_set_len, &granted, &status);
-todo_wine {
+todo(todo_platform) {
     ok(ret, "AccessCheck error %d\n", GetLastError());
     ok(status == 1, "expected 1, got %d\n", status);
     ok(granted == mapping->GenericExecute, "expected execute access %#x, got %#x\n", mapping->GenericExecute, granted);
@@ -4585,7 +4722,7 @@ todo_wine
         ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError());
     }
 
-    test_default_handle_security(token, mutex, &mapping);
+    test_default_handle_security(token, mutex, &mapping, "none");
 
     CloseHandle (mutex);
 }
@@ -4642,7 +4779,7 @@ todo_wine
         ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError());
     }
 
-    test_default_handle_security(token, event, &mapping);
+    test_default_handle_security(token, event, &mapping, "none");
 
     CloseHandle(event);
 }
@@ -4692,7 +4829,7 @@ static void test_semaphore_security(HANDLE token)
         CloseHandle(dup);
     }
 
-    test_default_handle_security(token, sem, &mapping);
+    test_default_handle_security(token, sem, &mapping, "none");
 
     CloseHandle(sem);
 }
@@ -4753,7 +4890,7 @@ static void test_named_pipe_security(HANDLE token)
                             0, 0, NMPWAIT_USE_DEFAULT_WAIT, NULL);
     ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe error %d\n", GetLastError());
 
-    test_default_handle_security(token, pipe, &mapping);
+    test_default_handle_security(token, pipe, &mapping, "wine");
 
     SetLastError(0xdeadbeef);
     file = CreateFileA(WINE_TEST_PIPE, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, 0, 0);
@@ -5341,7 +5478,7 @@ static void test_default_dacl_owner_sid(void)
     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;
@@ -5350,7 +5487,7 @@ static void test_default_dacl_owner_sid(void)
     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;
diff --git a/server/event.c b/server/event.c
index 4d3c562..2871ad9 100644
--- a/server/event.c
+++ b/server/event.c
@@ -52,22 +52,22 @@ static int event_signal( struct object *obj, unsigned int access);
 
 static const struct object_ops event_ops =
 {
-    sizeof(struct event),      /* size */
-    event_dump,                /* dump */
-    event_get_type,            /* get_type */
-    add_queue,                 /* add_queue */
-    remove_queue,              /* remove_queue */
-    event_signaled,            /* signaled */
-    event_satisfied,           /* satisfied */
-    event_signal,              /* signal */
-    no_get_fd,                 /* get_fd */
-    event_map_access,          /* map_access */
-    default_get_sd,            /* get_sd */
-    default_set_sd,            /* set_sd */
-    no_lookup_name,            /* lookup_name */
-    no_open_file,              /* open_file */
-    no_close_handle,           /* close_handle */
-    no_destroy                 /* destroy */
+    sizeof(struct event),         /* size */
+    event_dump,                   /* dump */
+    event_get_type,               /* get_type */
+    add_queue,                    /* add_queue */
+    remove_queue,                 /* remove_queue */
+    event_signaled,               /* signaled */
+    event_satisfied,              /* satisfied */
+    event_signal,                 /* signal */
+    no_get_fd,                    /* get_fd */
+    event_map_access,             /* map_access */
+    default_get_sd,               /* get_sd */
+    default_set_sd_impersonation, /* set_sd */
+    no_lookup_name,               /* lookup_name */
+    no_open_file,                 /* open_file */
+    no_close_handle,              /* close_handle */
+    no_destroy                    /* destroy */
 };
 
 
@@ -94,7 +94,7 @@ static const struct object_ops keyed_event_ops =
     no_get_fd,                   /* get_fd */
     keyed_event_map_access,      /* map_access */
     default_get_sd,              /* get_sd */
-    default_set_sd,              /* set_sd */
+    default_set_sd_impersonation,/* set_sd */
     no_lookup_name,              /* lookup_name */
     no_open_file,                /* open_file */
     no_close_handle,             /* close_handle */
@@ -115,10 +115,10 @@ struct event *create_event( struct directory *root, const struct unicode_str *na
             /* initialize it if it didn't already exist */
             event->manual_reset = manual_reset;
             event->signaled     = initial_state;
-            if (sd) default_set_sd( &event->obj, sd, OWNER_SECURITY_INFORMATION|
-                                                     GROUP_SECURITY_INFORMATION|
-                                                     DACL_SECURITY_INFORMATION|
-                                                     SACL_SECURITY_INFORMATION );
+            default_set_sd_impersonation( &event->obj, sd, OWNER_SECURITY_INFORMATION|
+                                                           GROUP_SECURITY_INFORMATION|
+                                                           DACL_SECURITY_INFORMATION|
+                                                           SACL_SECURITY_INFORMATION );
         }
     }
     return event;
@@ -214,10 +214,10 @@ struct keyed_event *create_keyed_event( struct directory *root, const struct uni
         if (get_error() != STATUS_OBJECT_NAME_EXISTS)
         {
             /* initialize it if it didn't already exist */
-            if (sd) default_set_sd( &event->obj, sd, OWNER_SECURITY_INFORMATION|
-                                                     GROUP_SECURITY_INFORMATION|
-                                                     DACL_SECURITY_INFORMATION|
-                                                     SACL_SECURITY_INFORMATION );
+            default_set_sd_impersonation( &event->obj, sd, OWNER_SECURITY_INFORMATION|
+                                                           GROUP_SECURITY_INFORMATION|
+                                                           DACL_SECURITY_INFORMATION|
+                                                           SACL_SECURITY_INFORMATION );
         }
     }
     return event;
diff --git a/server/mapping.c b/server/mapping.c
index 64b3003..4efb92a 100644
--- a/server/mapping.c
+++ b/server/mapping.c
@@ -484,10 +484,10 @@ static struct object *create_mapping( struct directory *root, const struct unico
     if (get_error() == STATUS_OBJECT_NAME_EXISTS)
         return &mapping->obj;  /* Nothing else to do */
 
-    if (sd) default_set_sd( &mapping->obj, sd, OWNER_SECURITY_INFORMATION|
-                                               GROUP_SECURITY_INFORMATION|
-                                               DACL_SECURITY_INFORMATION|
-                                               SACL_SECURITY_INFORMATION );
+    default_set_sd( &mapping->obj, sd, OWNER_SECURITY_INFORMATION|
+                                       GROUP_SECURITY_INFORMATION|
+                                       DACL_SECURITY_INFORMATION|
+                                       SACL_SECURITY_INFORMATION );
     mapping->header_size = 0;
     mapping->base        = 0;
     mapping->fd          = NULL;
diff --git a/server/mutex.c b/server/mutex.c
index 910fbca..89eb769 100644
--- a/server/mutex.c
+++ b/server/mutex.c
@@ -55,22 +55,22 @@ static int mutex_signal( struct object *obj, unsigned int access );
 
 static const struct object_ops mutex_ops =
 {
-    sizeof(struct mutex),      /* size */
-    mutex_dump,                /* dump */
-    mutex_get_type,            /* get_type */
-    add_queue,                 /* add_queue */
-    remove_queue,              /* remove_queue */
-    mutex_signaled,            /* signaled */
-    mutex_satisfied,           /* satisfied */
-    mutex_signal,              /* signal */
-    no_get_fd,                 /* get_fd */
-    mutex_map_access,          /* map_access */
-    default_get_sd,            /* get_sd */
-    default_set_sd,            /* set_sd */
-    no_lookup_name,            /* lookup_name */
-    no_open_file,              /* open_file */
-    no_close_handle,           /* close_handle */
-    mutex_destroy              /* destroy */
+    sizeof(struct mutex),         /* size */
+    mutex_dump,                   /* dump */
+    mutex_get_type,               /* get_type */
+    add_queue,                    /* add_queue */
+    remove_queue,                 /* remove_queue */
+    mutex_signaled,               /* signaled */
+    mutex_satisfied,              /* satisfied */
+    mutex_signal,                 /* signal */
+    no_get_fd,                    /* get_fd */
+    mutex_map_access,             /* map_access */
+    default_get_sd,               /* get_sd */
+    default_set_sd_impersonation, /* set_sd */
+    no_lookup_name,               /* lookup_name */
+    no_open_file,                 /* open_file */
+    no_close_handle,              /* close_handle */
+    mutex_destroy                 /* destroy */
 };
 
 
@@ -111,10 +111,10 @@ static struct mutex *create_mutex( struct directory *root, const struct unicode_
             mutex->owner = NULL;
             mutex->abandoned = 0;
             if (owned) do_grab( mutex, current );
-            if (sd) default_set_sd( &mutex->obj, sd, OWNER_SECURITY_INFORMATION|
-                                                     GROUP_SECURITY_INFORMATION|
-                                                     DACL_SECURITY_INFORMATION|
-                                                     SACL_SECURITY_INFORMATION );
+            default_set_sd_impersonation( &mutex->obj, sd, OWNER_SECURITY_INFORMATION|
+                                                           GROUP_SECURITY_INFORMATION|
+                                                           DACL_SECURITY_INFORMATION|
+                                                           SACL_SECURITY_INFORMATION );
         }
     }
     return mutex;
diff --git a/server/object.c b/server/object.c
index c206747..afcb101 100644
--- a/server/object.c
+++ b/server/object.c
@@ -423,10 +423,10 @@ struct security_descriptor *default_get_sd( struct object *obj )
     return obj->sd;
 }
 
-int default_set_sd( struct object *obj, const struct security_descriptor *sd,
-                    unsigned int set_info )
+int set_sd_defaulting_token( struct object *obj, const struct security_descriptor *sd,
+                    unsigned int set_info, struct token *token )
 {
-    struct security_descriptor new_sd, *new_sd_ptr;
+    struct security_descriptor new_sd = {0}, *new_sd_ptr;
     int present;
     const SID *owner, *group;
     const ACL *sacl, *dacl;
@@ -434,60 +434,91 @@ int default_set_sd( struct object *obj, const struct security_descriptor *sd,
 
     if (!set_info) return 1;
 
-    new_sd.control = sd->control & ~SE_SELF_RELATIVE;
+    new_sd.control = sd ? sd->control & ~SE_SELF_RELATIVE : 0;
+    
+    /* note: SE_*_DEFAULTED is never stored */
 
-    owner = sd_get_owner( sd );
+    owner = sd ? sd_get_owner( sd ) : NULL;
     if (set_info & OWNER_SECURITY_INFORMATION && owner)
+    {
         new_sd.owner_len = sd->owner_len;
+    }
     else
     {
-        owner = token_get_user( current->process->token );
-        new_sd.owner_len = security_sid_len( owner );
-        new_sd.control |= SE_OWNER_DEFAULTED;
+        owner = obj->sd ? sd_get_owner( obj->sd ) : NULL;
+        
+        if (owner)
+        {
+            new_sd.owner_len = obj->sd->owner_len;
+        }
+        else if (token)
+        {
+            owner = token_get_user( token );
+            new_sd.owner_len = security_sid_len( owner );
+        }
     }
 
-    group = sd_get_group( sd );
+    group = sd ? sd_get_group( sd ) : NULL;
     if (set_info & GROUP_SECURITY_INFORMATION && group)
+    {
         new_sd.group_len = sd->group_len;
+    }
     else
     {
-        group = token_get_primary_group( current->process->token );
-        new_sd.group_len = security_sid_len( group );
-        new_sd.control |= SE_GROUP_DEFAULTED;
+        group = obj->sd ? sd_get_group( obj->sd ) : NULL;
+        if (group)
+        {
+            new_sd.group_len = obj->sd->group_len;
+        }
+        else if (token)
+        {
+            group = token_get_primary_group( token );
+            new_sd.group_len = security_sid_len( group );
+        }
     }
-
+    
     new_sd.control |= SE_SACL_PRESENT;
-    sacl = sd_get_sacl( sd, &present );
+    present = 0;
+    sacl = sd ? sd_get_sacl( sd, &present ) : NULL;
     if (set_info & SACL_SECURITY_INFORMATION && present)
+    {
         new_sd.sacl_len = sd->sacl_len;
+    }
     else
     {
-        if (obj->sd) sacl = sd_get_sacl( obj->sd, &present );
+        present = 0;
+        sacl = obj->sd ? sd_get_sacl( obj->sd, &present ) : NULL;
 
-        if (obj->sd && present)
+        if (present)
+        {
             new_sd.sacl_len = obj->sd->sacl_len;
+        }
         else
         {
             new_sd.sacl_len = 0;
-            new_sd.control |= SE_SACL_DEFAULTED;
         }
     }
-
+    
     new_sd.control |= SE_DACL_PRESENT;
-    dacl = sd_get_dacl( sd, &present );
+    present = 0;
+    dacl = sd ? sd_get_dacl( sd, &present ) : NULL;
     if (set_info & DACL_SECURITY_INFORMATION && present)
+    {
         new_sd.dacl_len = sd->dacl_len;
+    }
     else
     {
-        if (obj->sd) dacl = sd_get_dacl( obj->sd, &present );
+        present = 0;
+        dacl = obj->sd ? sd_get_dacl( obj->sd, &present ) : NULL;
 
-        if (obj->sd && present)
+        if (present)
+        {
             new_sd.dacl_len = obj->sd->dacl_len;
-        else
+        }
+        else if (token)
         {
-            dacl = token_get_default_dacl( current->process->token );
+            dacl = token_get_default_dacl( token );
             new_sd.dacl_len = dacl->AclSize;
-            new_sd.control |= SE_DACL_DEFAULTED;
         }
     }
 
@@ -511,6 +542,19 @@ int default_set_sd( struct object *obj, const struct security_descriptor *sd,
     return 1;
 }
 
+/** Set the security descriptor, only use the current primary token for defaults. */
+int default_set_sd( struct object *obj, const struct security_descriptor *sd,
+                    unsigned int set_info )
+{
+    return set_sd_defaulting_token( obj, sd, set_info, current ? current->process->token : NULL );
+}
+
+/** Set the security descriptor, use the current thread impersonation token for defaults. */
+int default_set_sd_impersonation( struct object *obj, const struct security_descriptor *sd,
+                    unsigned int set_info )
+{
+    return set_sd_defaulting_token( obj, sd, set_info, current ? thread_get_impersonation_token(current) : NULL );
+}
 struct object *no_lookup_name( struct object *obj, struct unicode_str *name,
                                unsigned int attr )
 {
diff --git a/server/object.h b/server/object.h
index bb3ff21..8cb18b8 100644
--- a/server/object.h
+++ b/server/object.h
@@ -138,7 +138,12 @@ extern int no_signal( struct object *obj, unsigned int access );
 extern struct fd *no_get_fd( struct object *obj );
 extern unsigned int no_map_access( struct object *obj, unsigned int access );
 extern struct security_descriptor *default_get_sd( struct object *obj );
-extern int default_set_sd( struct object *obj, const struct security_descriptor *sd, unsigned int set_info );
+extern int set_sd_defaulting_token( struct object *obj, const struct security_descriptor *sd, 
+                                    unsigned int set_info, struct token *token );
+extern int default_set_sd( struct object *obj, const struct security_descriptor *sd, 
+                           unsigned int set_info );
+extern int default_set_sd_impersonation( struct object *obj, const struct security_descriptor *sd, 
+                                         unsigned int set_info );
 extern struct object *no_lookup_name( struct object *obj, struct unicode_str *name, unsigned int attributes );
 extern struct object *no_open_file( struct object *obj, unsigned int access, unsigned int sharing,
                                     unsigned int options );
diff --git a/server/semaphore.c b/server/semaphore.c
index d87325c..4856339 100644
--- a/server/semaphore.c
+++ b/server/semaphore.c
@@ -52,22 +52,22 @@ static int semaphore_signal( struct object *obj, unsigned int access );
 
 static const struct object_ops semaphore_ops =
 {
-    sizeof(struct semaphore),      /* size */
-    semaphore_dump,                /* dump */
-    semaphore_get_type,            /* get_type */
-    add_queue,                     /* add_queue */
-    remove_queue,                  /* remove_queue */
-    semaphore_signaled,            /* signaled */
-    semaphore_satisfied,           /* satisfied */
-    semaphore_signal,              /* signal */
-    no_get_fd,                     /* get_fd */
-    semaphore_map_access,          /* map_access */
-    default_get_sd,                /* get_sd */
-    default_set_sd,                /* set_sd */
-    no_lookup_name,                /* lookup_name */
-    no_open_file,                  /* open_file */
-    no_close_handle,               /* close_handle */
-    no_destroy                     /* destroy */
+    sizeof(struct semaphore),         /* size */
+    semaphore_dump,                   /* dump */
+    semaphore_get_type,               /* get_type */
+    add_queue,                        /* add_queue */
+    remove_queue,                     /* remove_queue */
+    semaphore_signaled,               /* signaled */
+    semaphore_satisfied,              /* satisfied */
+    semaphore_signal,                 /* signal */
+    no_get_fd,                        /* get_fd */
+    semaphore_map_access,             /* map_access */
+    default_get_sd,                   /* get_sd */
+    default_set_sd_impersonation,     /* set_sd */
+    no_lookup_name,                   /* lookup_name */
+    no_open_file,                     /* open_file */
+    no_close_handle,                  /* close_handle */
+    no_destroy                        /* destroy */
 };
 
 
@@ -89,10 +89,10 @@ static struct semaphore *create_semaphore( struct directory *root, const struct
             /* initialize it if it didn't already exist */
             sem->count = initial;
             sem->max   = max;
-            if (sd) default_set_sd( &sem->obj, sd, OWNER_SECURITY_INFORMATION|
-                                                   GROUP_SECURITY_INFORMATION|
-                                                   DACL_SECURITY_INFORMATION|
-                                                   SACL_SECURITY_INFORMATION );
+            default_set_sd_impersonation( &sem->obj, sd, OWNER_SECURITY_INFORMATION|
+                                                         GROUP_SECURITY_INFORMATION|
+                                                         DACL_SECURITY_INFORMATION|
+                                                         SACL_SECURITY_INFORMATION );
         }
     }
     return sem;
diff --git a/server/timer.c b/server/timer.c
index 9c293f2..42cd8c2 100644
--- a/server/timer.c
+++ b/server/timer.c
@@ -59,22 +59,22 @@ static void timer_destroy( struct object *obj );
 
 static const struct object_ops timer_ops =
 {
-    sizeof(struct timer),      /* size */
-    timer_dump,                /* dump */
-    timer_get_type,            /* get_type */
-    add_queue,                 /* add_queue */
-    remove_queue,              /* remove_queue */
-    timer_signaled,            /* signaled */
-    timer_satisfied,           /* satisfied */
-    no_signal,                 /* signal */
-    no_get_fd,                 /* get_fd */
-    timer_map_access,          /* map_access */
-    default_get_sd,            /* get_sd */
-    default_set_sd,            /* set_sd */
-    no_lookup_name,            /* lookup_name */
-    no_open_file,              /* open_file */
-    no_close_handle,           /* close_handle */
-    timer_destroy              /* destroy */
+    sizeof(struct timer),         /* size */
+    timer_dump,                   /* dump */
+    timer_get_type,               /* get_type */
+    add_queue,                    /* add_queue */
+    remove_queue,                 /* remove_queue */
+    timer_signaled,               /* signaled */
+    timer_satisfied,              /* satisfied */
+    no_signal,                    /* signal */
+    no_get_fd,                    /* get_fd */
+    timer_map_access,             /* map_access */
+    default_get_sd,               /* get_sd */
+    default_set_sd_impersonation, /* set_sd */
+    no_lookup_name,               /* lookup_name */
+    no_open_file,                 /* open_file */
+    no_close_handle,              /* close_handle */
+    timer_destroy                 /* destroy */
 };
 
 
-- 
1.8.1.msysgit.1



More information about the wine-patches mailing list