[PATCH v2 1/5] server: Implement querying the security label of a security descriptor.

Matteo Bruni mbruni at codeweavers.com
Wed Jun 14 13:20:40 CDT 2017


From: Michael Müller <michael at fds-team.de>

Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
---
v2: Drop early exit from extract_security_label(), it broke the tests
in the next patch among other things.

 dlls/advapi32/tests/security.c | 84 ++++++++++++++++++++++++++++++++++++++----
 include/winnt.h                | 35 +++++++++---------
 server/handle.c                | 55 +++++++++++++++++++++++++++
 3 files changed, 150 insertions(+), 24 deletions(-)

diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index fa3211ce44..d701251c83 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -6163,11 +6163,17 @@ static void test_AddMandatoryAce(void)
 {
     static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
                             {SECURITY_MANDATORY_LOW_RID}};
+    char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
+    SECURITY_DESCRIPTOR *sd2, *sd = (SECURITY_DESCRIPTOR *)&buffer_sd;
+    BOOL defaulted, present, ret, found;
+    ACL_SIZE_INFORMATION acl_size_info;
     SYSTEM_MANDATORY_LABEL_ACE *ace;
     char buffer_acl[256];
-    ACL *pAcl = (ACL *)&buffer_acl;
-    BOOL ret, found;
-    DWORD index;
+    ACL *acl = (ACL *)&buffer_acl;
+    SECURITY_ATTRIBUTES sa;
+    DWORD index, size;
+    HANDLE handle;
+    ACL *sacl;
 
     if (!pAddMandatoryAce)
     {
@@ -6175,21 +6181,49 @@ static void test_AddMandatoryAce(void)
         return;
     }
 
-    ret = InitializeAcl(pAcl, 256, ACL_REVISION);
+    ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
+    ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
+
+    sa.nLength = sizeof(sa);
+    sa.lpSecurityDescriptor = sd;
+    sa.bInheritHandle = FALSE;
+
+    handle = CreateEventA(&sa, TRUE, TRUE, "test_event");
+    ok(handle != NULL, "CreateEventA failed with error %u\n", GetLastError());
+
+    ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
+    ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+       "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
+
+    sd2 = HeapAlloc(GetProcessHeap(), 0, size);
+    ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
+    ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
+
+    sacl = (void *)0xdeadbeef;
+    present = TRUE;
+    ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
+    ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+    todo_wine ok(!present, "SACL is present\n");
+    todo_wine ok(sacl == (void *)0xdeadbeef, "SACL is set\n");
+
+    HeapFree(GetProcessHeap(), 0, sd2);
+    CloseHandle(handle);
+
+    ret = InitializeAcl(acl, 256, ACL_REVISION);
     ok(ret, "InitializeAcl failed with %u\n", GetLastError());
 
     SetLastError(0xdeadbeef);
-    ret = pAddMandatoryAce(pAcl, ACL_REVISION, 0, 0x1234, &low_level);
+    ret = pAddMandatoryAce(acl, ACL_REVISION, 0, 0x1234, &low_level);
     ok(!ret, "AddMandatoryAce succeeded\n");
     ok(GetLastError() == ERROR_INVALID_PARAMETER,
        "Expected ERROR_INVALID_PARAMETER got %u\n", GetLastError());
 
-    ret = pAddMandatoryAce(pAcl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level);
+    ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level);
     ok(ret, "AddMandatoryAce failed with %u\n", GetLastError());
 
     index = 0;
     found = FALSE;
-    while (pGetAce( pAcl, index++, (void **)&ace ))
+    while (pGetAce(acl, index++, (void **)&ace))
     {
         if (ace->Header.AceType != SYSTEM_MANDATORY_LABEL_ACE_TYPE) continue;
         ok(ace->Header.AceFlags == 0, "Expected flags 0, got %x\n", ace->Header.AceFlags);
@@ -6199,6 +6233,42 @@ static void test_AddMandatoryAce(void)
         found = TRUE;
     }
     ok(found, "Could not find mandatory label ace\n");
+
+    ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
+    ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+
+    handle = CreateEventA(&sa, TRUE, TRUE, "test_event");
+    ok(handle != NULL, "CreateEventA failed with error %u\n", GetLastError());
+
+    ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
+    ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+       "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
+
+    sd2 = HeapAlloc(GetProcessHeap(), 0, size);
+    ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
+    ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
+
+    sacl = (void *)0xdeadbeef;
+    present = FALSE;
+    defaulted = TRUE;
+    ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
+    ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+    ok(present, "SACL not present\n");
+    ok(sacl != (void *)0xdeadbeef, "SACL not set\n");
+    ok(!defaulted, "SACL defaulted\n");
+    ret = pGetAclInformation(sacl, &acl_size_info, sizeof(acl_size_info), AclSizeInformation);
+    ok(ret, "GetAclInformation failed with error %u\n", GetLastError());
+    ok(acl_size_info.AceCount == 1, "SACL contains an unexpected ACE count %u\n", acl_size_info.AceCount);
+
+    ret = pGetAce(sacl, 0, (void **)&ace);
+    ok(ret, "GetAce failed with error %u\n", GetLastError());
+    ok (ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType);
+    ok(!ace->Header.AceFlags, "Unexpected ACE flags %#x\n", ace->Header.AceFlags);
+    ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "Unexpected ACE mask %#x\n", ace->Mask);
+    ok(EqualSid(&ace->SidStart, &low_level), "Expected low integrity level\n");
+
+    HeapFree(GetProcessHeap(), 0, sd2);
+    CloseHandle(handle);
 }
 
 static void test_system_security_access(void)
diff --git a/include/winnt.h b/include/winnt.h
index 450499c129..c328cbf622 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -5272,23 +5272,24 @@ typedef struct _TAPE_GET_MEDIA_PARAMETERS {
 /* ----------------------------- begin registry ----------------------------- */
 
 /* Registry security values */
-#define OWNER_SECURITY_INFORMATION	0x00000001
-#define GROUP_SECURITY_INFORMATION	0x00000002
-#define DACL_SECURITY_INFORMATION	0x00000004
-#define SACL_SECURITY_INFORMATION	0x00000008
-
-#define REG_OPTION_RESERVED		0x00000000
-#define REG_OPTION_NON_VOLATILE		0x00000000
-#define REG_OPTION_VOLATILE		0x00000001
-#define REG_OPTION_CREATE_LINK		0x00000002
-#define REG_OPTION_BACKUP_RESTORE	0x00000004 /* FIXME */
-#define REG_OPTION_OPEN_LINK		0x00000008
-#define REG_LEGAL_OPTION	       (REG_OPTION_RESERVED|  \
-					REG_OPTION_NON_VOLATILE|  \
-					REG_OPTION_VOLATILE|  \
-					REG_OPTION_CREATE_LINK|  \
-					REG_OPTION_BACKUP_RESTORE|  \
-					REG_OPTION_OPEN_LINK)
+#define OWNER_SECURITY_INFORMATION      0x00000001
+#define GROUP_SECURITY_INFORMATION      0x00000002
+#define DACL_SECURITY_INFORMATION       0x00000004
+#define SACL_SECURITY_INFORMATION       0x00000008
+#define LABEL_SECURITY_INFORMATION      0x00000010
+
+#define REG_OPTION_RESERVED             0x00000000
+#define REG_OPTION_NON_VOLATILE         0x00000000
+#define REG_OPTION_VOLATILE             0x00000001
+#define REG_OPTION_CREATE_LINK          0x00000002
+#define REG_OPTION_BACKUP_RESTORE       0x00000004 /* FIXME */
+#define REG_OPTION_OPEN_LINK            0x00000008
+#define REG_LEGAL_OPTION               (REG_OPTION_RESERVED | \
+                                        REG_OPTION_NON_VOLATILE | \
+                                        REG_OPTION_VOLATILE | \
+                                        REG_OPTION_CREATE_LINK | \
+                                        REG_OPTION_BACKUP_RESTORE | \
+                                        REG_OPTION_OPEN_LINK)
 
 
 #define REG_CREATED_NEW_KEY	0x00000001
diff --git a/server/handle.c b/server/handle.c
index 3f42352bce..d7446c2fd1 100644
--- a/server/handle.c
+++ b/server/handle.c
@@ -700,6 +700,52 @@ DECL_HANDLER(set_security_object)
     release_object( obj );
 }
 
+/* extract security labels from SACL */
+static int extract_security_label( ACL **out, const ACL *sacl )
+{
+    size_t size = sizeof(ACL);
+    const ACE_HEADER *ace;
+    ACE_HEADER *label_ace;
+    unsigned int i, count = 0;
+    ACL *label_acl;
+
+    *out = NULL;
+    if (!sacl) return 1;
+
+    ace = (const ACE_HEADER *)(sacl + 1);
+    for (i = 0; i < sacl->AceCount; i++, ace = ace_next( ace ))
+    {
+        if (ace->AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE)
+        {
+            size += ace->AceSize;
+            count++;
+        }
+    }
+
+    label_acl = mem_alloc( size );
+    if (!label_acl) return 0;
+
+    label_acl->AclRevision = sacl->AclRevision;
+    label_acl->Sbz1 = 0;
+    label_acl->AclSize = size;
+    label_acl->AceCount = count;
+    label_acl->Sbz2 = 0;
+    label_ace = (ACE_HEADER *)(label_acl + 1);
+
+    ace = (const ACE_HEADER *)(sacl + 1);
+    for (i = 0; i < sacl->AceCount; i++, ace = ace_next( ace ))
+    {
+        if (ace->AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE)
+        {
+            memcpy( label_ace, ace, ace->AceSize );
+            label_ace = (ACE_HEADER *)ace_next( label_ace );
+        }
+    }
+
+    *out = label_acl;
+    return 1;
+}
+
 DECL_HANDLER(get_security_object)
 {
     const struct security_descriptor *sd;
@@ -709,6 +755,7 @@ DECL_HANDLER(get_security_object)
     int present;
     const SID *owner, *group;
     const ACL *sacl, *dacl;
+    ACL *label_acl = NULL;
 
     if (req->security_info & SACL_SECURITY_INFORMATION)
         access |= ACCESS_SYSTEM_SECURITY;
@@ -736,6 +783,12 @@ DECL_HANDLER(get_security_object)
         sacl = sd_get_sacl( sd, &present );
         if (req->security_info & SACL_SECURITY_INFORMATION && present)
             req_sd.sacl_len = sd->sacl_len;
+        else if (req->security_info & LABEL_SECURITY_INFORMATION && present)
+        {
+            if (!extract_security_label( &label_acl, sacl )) goto error;
+            req_sd.sacl_len = label_acl ? label_acl->AclSize : 0;
+            sacl = label_acl;
+        }
         else
             req_sd.sacl_len = 0;
 
@@ -766,7 +819,9 @@ DECL_HANDLER(get_security_object)
             set_error(STATUS_BUFFER_TOO_SMALL);
     }
 
+error:
     release_object( obj );
+    free( label_acl );
 }
 
 struct enum_handle_info
-- 
2.13.0




More information about the wine-patches mailing list