Commit af2d01c2 authored by Michael Müller's avatar Michael Müller Committed by Alexandre Julliard

server: Implement changing the label of a security descriptor.

parent 2ebe6796
...@@ -6163,9 +6163,12 @@ static void test_AddMandatoryAce(void) ...@@ -6163,9 +6163,12 @@ static void test_AddMandatoryAce(void)
{ {
static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
{SECURITY_MANDATORY_LOW_RID}}; {SECURITY_MANDATORY_LOW_RID}};
static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
{SECURITY_MANDATORY_MEDIUM_RID}};
static SID_IDENTIFIER_AUTHORITY sia_world = {SECURITY_WORLD_SID_AUTHORITY};
char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
SECURITY_DESCRIPTOR *sd2, *sd = (SECURITY_DESCRIPTOR *)&buffer_sd; SECURITY_DESCRIPTOR *sd2, *sd = (SECURITY_DESCRIPTOR *)&buffer_sd;
BOOL defaulted, present, ret, found; BOOL defaulted, present, ret, found, found2;
ACL_SIZE_INFORMATION acl_size_info; ACL_SIZE_INFORMATION acl_size_info;
SYSTEM_MANDATORY_LABEL_ACE *ace; SYSTEM_MANDATORY_LABEL_ACE *ace;
char buffer_acl[256]; char buffer_acl[256];
...@@ -6173,6 +6176,7 @@ static void test_AddMandatoryAce(void) ...@@ -6173,6 +6176,7 @@ static void test_AddMandatoryAce(void)
SECURITY_ATTRIBUTES sa; SECURITY_ATTRIBUTES sa;
DWORD index, size; DWORD index, size;
HANDLE handle; HANDLE handle;
SID *everyone;
ACL *sacl; ACL *sacl;
if (!pAddMandatoryAce) if (!pAddMandatoryAce)
...@@ -6268,6 +6272,151 @@ static void test_AddMandatoryAce(void) ...@@ -6268,6 +6272,151 @@ static void test_AddMandatoryAce(void)
ok(EqualSid(&ace->SidStart, &low_level), "Expected low integrity level\n"); ok(EqualSid(&ace->SidStart, &low_level), "Expected low integrity level\n");
HeapFree(GetProcessHeap(), 0, sd2); HeapFree(GetProcessHeap(), 0, sd2);
ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level);
ok(ret, "AddMandatoryAce failed with error %u\n", GetLastError());
ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
ok(ret, "SetKernelObjectSecurity 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(sacl->AceCount == 2, "Expected 2 ACEs, got %d\n", sacl->AceCount);
ok(!defaulted, "SACL defaulted\n");
index = 0;
found = found2 = FALSE;
while (pGetAce(sacl, index++, (void **)&ace))
{
if (ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE)
{
if (EqualSid(&ace->SidStart, &low_level))
{
found = TRUE;
ok(!ace->Header.AceFlags, "Expected 0 as flags, got %#x\n", ace->Header.AceFlags);
ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP,
"Expected SYSTEM_MANDATORY_LABEL_NO_WRITE_UP as mask, got %#x\n", ace->Mask);
}
if (EqualSid(&ace->SidStart, &medium_level))
{
found2 = TRUE;
ok(!ace->Header.AceFlags, "Expected 0 as flags, got %#x\n", ace->Header.AceFlags);
ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP,
"Expected SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP as mask, got %#x\n", ace->Mask);
}
}
}
ok(found, "Could not find low mandatory label\n");
ok(found2, "Could not find medium mandatory label\n");
HeapFree(GetProcessHeap(), 0, sd2);
ret = SetSecurityDescriptorSacl(sd, FALSE, NULL, FALSE);
ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
ok(ret, "SetKernelObjectSecurity 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 %d, 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 && sacl != (void *)0xdeadbeef, "SACL not set\n");
ok(!defaulted, "SACL defaulted\n");
ok(!sacl->AceCount, "SACL contains an unexpected ACE count %u\n", sacl->AceCount);
HeapFree(GetProcessHeap(), 0, sd2);
ret = InitializeAcl(acl, 256, ACL_REVISION);
ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
ret = pAddMandatoryAce(acl, ACL_REVISION3, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level);
ok(ret, "AddMandatoryAce failed with error %u\n", GetLastError());
ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
ok(ret, "SetKernelObjectSecurity 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 %d, 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(sacl->AclRevision == ACL_REVISION3, "Expected revision 3, got %d\n", sacl->AclRevision);
ok(!defaulted, "SACL defaulted\n");
HeapFree(GetProcessHeap(), 0, sd2);
ret = InitializeAcl(acl, 256, ACL_REVISION);
ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
ret = AllocateAndInitializeSid(&sia_world, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, (void **)&everyone);
ok(ret, "AllocateAndInitializeSid failed with error %u\n", GetLastError());
ret = AddAccessAllowedAce(acl, ACL_REVISION, KEY_READ, everyone);
ok(ret, "AddAccessAllowedAce failed with error %u\n", GetLastError());
ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
ok(ret, "SetKernelObjectSecurity 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 %d, 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 && sacl != (void *)0xdeadbeef, "SACL not set\n");
ok(!defaulted, "SACL defaulted\n");
ok(!sacl->AceCount, "SACL contains an unexpected ACE count %u\n", sacl->AceCount);
FreeSid(everyone);
HeapFree(GetProcessHeap(), 0, sd2);
CloseHandle(handle); CloseHandle(handle);
} }
......
...@@ -1775,7 +1775,8 @@ NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle, ...@@ -1775,7 +1775,8 @@ NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
return STATUS_INVALID_SECURITY_DESCR; return STATUS_INVALID_SECURITY_DESCR;
} }
if (SecurityInformation & SACL_SECURITY_INFORMATION) if (SecurityInformation & SACL_SECURITY_INFORMATION ||
SecurityInformation & LABEL_SECURITY_INFORMATION)
{ {
status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted ); status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
if (status != STATUS_SUCCESS) return status; if (status != STATUS_SUCCESS) return status;
......
...@@ -687,7 +687,8 @@ DECL_HANDLER(set_security_object) ...@@ -687,7 +687,8 @@ DECL_HANDLER(set_security_object)
} }
if (req->security_info & OWNER_SECURITY_INFORMATION || if (req->security_info & OWNER_SECURITY_INFORMATION ||
req->security_info & GROUP_SECURITY_INFORMATION) req->security_info & GROUP_SECURITY_INFORMATION ||
req->security_info & LABEL_SECURITY_INFORMATION)
access |= WRITE_OWNER; access |= WRITE_OWNER;
if (req->security_info & SACL_SECURITY_INFORMATION) if (req->security_info & SACL_SECURITY_INFORMATION)
access |= ACCESS_SYSTEM_SECURITY; access |= ACCESS_SYSTEM_SECURITY;
......
...@@ -542,6 +542,7 @@ int set_sd_defaults_from_token( struct object *obj, const struct security_descri ...@@ -542,6 +542,7 @@ int set_sd_defaults_from_token( struct object *obj, const struct security_descri
int present; int present;
const SID *owner = NULL, *group = NULL; const SID *owner = NULL, *group = NULL;
const ACL *sacl, *dacl; const ACL *sacl, *dacl;
ACL *replaced_sacl = NULL;
char *ptr; char *ptr;
if (!set_info) return 1; if (!set_info) return 1;
...@@ -586,6 +587,14 @@ int set_sd_defaults_from_token( struct object *obj, const struct security_descri ...@@ -586,6 +587,14 @@ int set_sd_defaults_from_token( struct object *obj, const struct security_descri
sacl = sd_get_sacl( sd, &present ); sacl = sd_get_sacl( sd, &present );
if (set_info & SACL_SECURITY_INFORMATION && present) if (set_info & SACL_SECURITY_INFORMATION && present)
new_sd.sacl_len = sd->sacl_len; new_sd.sacl_len = sd->sacl_len;
else if (set_info & LABEL_SECURITY_INFORMATION && present)
{
const ACL *old_sacl = NULL;
if (obj->sd && obj->sd->control & SE_SACL_PRESENT) old_sacl = sd_get_sacl( obj->sd, &present );
if (!(replaced_sacl = replace_security_labels( old_sacl, sacl ))) return 0;
new_sd.sacl_len = replaced_sacl->AclSize;
sacl = replaced_sacl;
}
else else
{ {
if (obj->sd) sacl = sd_get_sacl( obj->sd, &present ); if (obj->sd) sacl = sd_get_sacl( obj->sd, &present );
...@@ -616,7 +625,11 @@ int set_sd_defaults_from_token( struct object *obj, const struct security_descri ...@@ -616,7 +625,11 @@ int set_sd_defaults_from_token( struct object *obj, const struct security_descri
ptr = mem_alloc( sizeof(new_sd) + new_sd.owner_len + new_sd.group_len + ptr = mem_alloc( sizeof(new_sd) + new_sd.owner_len + new_sd.group_len +
new_sd.sacl_len + new_sd.dacl_len ); new_sd.sacl_len + new_sd.dacl_len );
if (!ptr) return 0; if (!ptr)
{
free( replaced_sacl );
return 0;
}
new_sd_ptr = (struct security_descriptor*)ptr; new_sd_ptr = (struct security_descriptor*)ptr;
memcpy( ptr, &new_sd, sizeof(new_sd) ); memcpy( ptr, &new_sd, sizeof(new_sd) );
...@@ -629,6 +642,7 @@ int set_sd_defaults_from_token( struct object *obj, const struct security_descri ...@@ -629,6 +642,7 @@ int set_sd_defaults_from_token( struct object *obj, const struct security_descri
ptr += new_sd.sacl_len; ptr += new_sd.sacl_len;
memcpy( ptr, dacl, new_sd.dacl_len ); memcpy( ptr, dacl, new_sd.dacl_len );
free( replaced_sacl );
free( obj->sd ); free( obj->sd );
obj->sd = new_sd_ptr; obj->sd = new_sd_ptr;
return 1; return 1;
......
...@@ -97,6 +97,7 @@ static inline int thread_single_check_privilege( struct thread *thread, const LU ...@@ -97,6 +97,7 @@ static inline int thread_single_check_privilege( struct thread *thread, const LU
extern int sd_is_valid( const struct security_descriptor *sd, data_size_t size ); extern int sd_is_valid( const struct security_descriptor *sd, data_size_t size );
extern ACL *extract_security_labels( const ACL *sacl ); extern ACL *extract_security_labels( const ACL *sacl );
extern ACL *replace_security_labels( const ACL *old_sacl, const ACL *new_sacl );
/* gets the discretionary access control list from a security descriptor */ /* gets the discretionary access control list from a security descriptor */
static inline const ACL *sd_get_dacl( const struct security_descriptor *sd, int *present ) static inline const ACL *sd_get_dacl( const struct security_descriptor *sd, int *present )
......
...@@ -377,6 +377,75 @@ ACL *extract_security_labels( const ACL *sacl ) ...@@ -377,6 +377,75 @@ ACL *extract_security_labels( const ACL *sacl )
return label_acl; return label_acl;
} }
/* replace security labels in an existing SACL */
ACL *replace_security_labels( const ACL *old_sacl, const ACL *new_sacl )
{
const ACE_HEADER *ace;
ACE_HEADER *replaced_ace;
size_t size = sizeof(ACL);
unsigned int i, count = 0;
BYTE revision = ACL_REVISION;
ACL *replaced_acl;
if (old_sacl)
{
revision = max( revision, old_sacl->AclRevision );
ace = (const ACE_HEADER *)(old_sacl + 1);
for (i = 0; i < old_sacl->AceCount; i++, ace = ace_next( ace ))
{
if (ace->AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE) continue;
size += ace->AceSize;
count++;
}
}
if (new_sacl)
{
revision = max( revision, new_sacl->AclRevision );
ace = (const ACE_HEADER *)(new_sacl + 1);
for (i = 0; i < new_sacl->AceCount; i++, ace = ace_next( ace ))
{
if (ace->AceType != SYSTEM_MANDATORY_LABEL_ACE_TYPE) continue;
size += ace->AceSize;
count++;
}
}
replaced_acl = mem_alloc( size );
if (!replaced_acl) return NULL;
replaced_acl->AclRevision = revision;
replaced_acl->Sbz1 = 0;
replaced_acl->AclSize = size;
replaced_acl->AceCount = count;
replaced_acl->Sbz2 = 0;
replaced_ace = (ACE_HEADER *)(replaced_acl + 1);
if (old_sacl)
{
ace = (const ACE_HEADER *)(old_sacl + 1);
for (i = 0; i < old_sacl->AceCount; i++, ace = ace_next( ace ))
{
if (ace->AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE) continue;
memcpy( replaced_ace, ace, ace->AceSize );
replaced_ace = (ACE_HEADER *)ace_next( replaced_ace );
}
}
if (new_sacl)
{
ace = (const ACE_HEADER *)(new_sacl + 1);
for (i = 0; i < new_sacl->AceCount; i++, ace = ace_next( ace ))
{
if (ace->AceType != SYSTEM_MANDATORY_LABEL_ACE_TYPE) continue;
memcpy( replaced_ace, ace, ace->AceSize );
replaced_ace = (ACE_HEADER *)ace_next( replaced_ace );
}
}
return replaced_acl;
}
/* maps from generic rights to specific rights as given by a mapping */ /* maps from generic rights to specific rights as given by a mapping */
static inline void map_generic_mask(unsigned int *mask, const GENERIC_MAPPING *mapping) static inline void map_generic_mask(unsigned int *mask, const GENERIC_MAPPING *mapping)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment