From: Elizabeth Figura zfigura@codeweavers.com
--- server/token.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/server/token.c b/server/token.c index 4df8d2e0c6e..f23013103dd 100644 --- a/server/token.c +++ b/server/token.c @@ -134,6 +134,8 @@ struct group
static void token_dump( struct object *obj, int verbose ); static void token_destroy( struct object *obj ); +static int token_set_sd( struct object *obj, const struct security_descriptor *sd, + unsigned int set_info );
static const struct object_ops token_ops = { @@ -148,7 +150,7 @@ static const struct object_ops token_ops = no_get_fd, /* get_fd */ default_map_access, /* map_access */ default_get_sd, /* get_sd */ - default_set_sd, /* set_sd */ + token_set_sd, /* set_sd */ no_get_full_name, /* get_full_name */ no_lookup_name, /* lookup_name */ no_link_name, /* link_name */ @@ -167,6 +169,12 @@ static void token_dump( struct object *obj, int verbose ) token->token_id.low_part, token->primary, token->impersonation_level ); }
+static int token_set_sd( struct object *obj, const struct security_descriptor *sd, + unsigned int set_info ) +{ + return default_set_sd( obj, sd, set_info & ~LABEL_SECURITY_INFORMATION ); +} + void security_set_thread_token( struct thread *thread, obj_handle_t handle ) { if (!handle)
From: Elizabeth Figura zfigura@codeweavers.com
And assign it in token_create_admin().
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56640 --- dlls/advapi32/tests/security.c | 22 +++++++++------------- server/process.c | 6 ------ server/security.h | 1 - server/token.c | 29 ++++++++++++++++++++++++++++- 4 files changed, 37 insertions(+), 21 deletions(-)
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index 2669c13748b..43709352560 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -7376,23 +7376,19 @@ static void test_token_security_descriptor(void) defaulted = TRUE; ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted); ok(ret, "GetSecurityDescriptorDacl failed with error %lu\n", GetLastError()); - todo_wine ok(present, "DACL not present\n");
- if (present) - { - ok(acl2 != (void *)0xdeadbeef, "DACL not set\n"); - ok(!defaulted, "DACL defaulted\n"); + ok(acl2 != (void *)0xdeadbeef, "DACL not set\n"); + ok(!defaulted, "DACL defaulted\n");
- index = 0; - found = FALSE; - while (GetAce(acl2, index++, (void **)&ace)) - { - if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE && EqualSid(&ace->SidStart, psid)) - found = TRUE; - } - ok(!found, "Access allowed ACE was inherited\n"); + index = 0; + found = FALSE; + while (GetAce(acl2, index++, (void **)&ace)) + { + if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE && EqualSid(&ace->SidStart, psid)) + found = TRUE; } + ok(!found, "Access allowed ACE was inherited\n");
free(sd2);
diff --git a/server/process.c b/server/process.c index f6d1641cb94..fc3ae322134 100644 --- a/server/process.c +++ b/server/process.c @@ -735,12 +735,6 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla if (!process->handles || !process->token) goto error; process->session_id = token_get_session_id( process->token );
- /* Assign a high security label to the token. The default would be medium - * but Wine provides admin access to all applications right now so high - * makes more sense for the time being. */ - if (!token_assign_label( process->token, &high_label_sid )) - goto error; - set_fd_events( process->msg_fd, POLLIN ); /* start listening to events */ return process;
diff --git a/server/security.h b/server/security.h index 58ab1594eae..f4dff679179 100644 --- a/server/security.h +++ b/server/security.h @@ -50,7 +50,6 @@ extern const struct sid local_system_sid; extern const struct sid builtin_users_sid; extern const struct sid builtin_admins_sid; extern const struct sid domain_users_sid; -extern const struct sid high_label_sid;
struct ace { diff --git a/server/token.c b/server/token.c index f23013103dd..da7f0bb7ff2 100644 --- a/server/token.c +++ b/server/token.c @@ -72,7 +72,6 @@ struct sid_attrs
const struct sid world_sid = { SID_REVISION, 1, SECURITY_WORLD_SID_AUTHORITY, { SECURITY_WORLD_RID } }; const struct sid local_system_sid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_LOCAL_SYSTEM_RID } }; -const struct sid high_label_sid = { SID_REVISION, 1, SECURITY_MANDATORY_LABEL_AUTHORITY, { SECURITY_MANDATORY_HIGH_RID } }; const struct sid local_user_sid = { SID_REVISION, 5, SECURITY_NT_AUTHORITY, { SECURITY_NT_NON_UNIQUE, 0, 0, 0, 1000 } }; const struct sid builtin_admins_sid = { SID_REVISION, 2, SECURITY_NT_AUTHORITY, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } }; const struct sid builtin_users_sid = { SID_REVISION, 2, SECURITY_NT_AUTHORITY, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } }; @@ -82,6 +81,7 @@ static const struct sid local_sid = { SID_REVISION, 1, SECURITY_LOCAL_SID_AUTHOR static const struct sid interactive_sid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_INTERACTIVE_RID } }; static const struct sid anonymous_logon_sid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_ANONYMOUS_LOGON_RID } }; static const struct sid authenticated_user_sid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_AUTHENTICATED_USER_RID } }; +static const struct sid high_label_sid = { SID_REVISION, 1, SECURITY_MANDATORY_LABEL_AUTHORITY, { SECURITY_MANDATORY_HIGH_RID } };
static struct luid prev_luid_value = { 1000, 0 };
@@ -649,6 +649,24 @@ struct token *token_duplicate( struct token *src_token, unsigned primary, if (sd) default_set_sd( &token->obj, sd, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION );
+ if (src_token->obj.sd) + { + const struct acl *sacl; + const struct ace *ace; + unsigned int i; + int present; + + sacl = sd_get_sacl( src_token->obj.sd, &present ); + if (present) + { + for (i = 0, ace = ace_first( sacl ); i < sacl->count; i++, ace = ace_next( ace )) + { + if (ace->type != SYSTEM_MANDATORY_LABEL_ACE_TYPE) continue; + token_assign_label( token, (const struct sid *)(ace + 1) ); + } + } + } + return token; }
@@ -785,6 +803,15 @@ struct token *token_create_admin( unsigned primary, int impersonation_level, int /* we really need a primary group */ assert( token->primary_group );
+ /* Assign a high security label to the token. The default would be medium + * but Wine provides admin access to all applications right now so high + * makes more sense for the time being. */ + if (!token_assign_label( token, &high_label_sid )) + { + release_object( token ); + return NULL; + } + free( default_dacl ); return token; }
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/advapi32/tests/security.c | 104 ++++++++++++++++++++++++++++----- 1 file changed, 91 insertions(+), 13 deletions(-)
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index 43709352560..77a6c747916 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -7198,7 +7198,7 @@ static void test_maximum_allowed(void) CloseHandle(handle); }
-static void test_token_label(void) +static void check_token_label(HANDLE token, DWORD *level, BOOL sacl_inherited) { static SID medium_sid = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, {SECURITY_MANDATORY_MEDIUM_RID}}; @@ -7210,19 +7210,9 @@ static void test_token_label(void) SECURITY_DESCRIPTOR *sd; ACL *sacl = NULL, *dacl; DWORD size, revision; - HANDLE token; char *str; SID *sid;
- if (!pAddMandatoryAce) - { - win_skip("Mandatory integrity control is not supported.\n"); - return; - } - - ret = OpenProcessToken(GetCurrentProcess(), READ_CONTROL | WRITE_OWNER, &token); - ok(ret, "OpenProcessToken failed with error %lu\n", GetLastError()); - ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected GetKernelObjectSecurity return value %d, error %lu\n", ret, GetLastError()); @@ -7233,8 +7223,12 @@ static void test_token_label(void)
ret = GetSecurityDescriptorControl(sd, &control, &revision); ok(ret, "GetSecurityDescriptorControl failed with error %lu\n", GetLastError()); - todo_wine ok(control == (SE_SELF_RELATIVE | SE_SACL_AUTO_INHERITED | SE_SACL_PRESENT), - "Unexpected security descriptor control %#x\n", control); + if (sacl_inherited) + todo_wine ok(control == (SE_SELF_RELATIVE | SE_SACL_AUTO_INHERITED | SE_SACL_PRESENT), + "Unexpected security descriptor control %#x\n", control); + else + todo_wine ok(control == (SE_SELF_RELATIVE | SE_SACL_PRESENT), + "Unexpected security descriptor control %#x\n", control); ok(revision == 1, "Unexpected security descriptor revision %lu\n", revision);
sid = (void *)0xdeadbeef; @@ -7270,6 +7264,7 @@ static void test_token_label(void) sid = (SID *)&ace->SidStart; ConvertSidToStringSidA(sid, &str); ok(EqualSid(sid, &medium_sid) || EqualSid(sid, &high_sid), "Got unexpected SID %s\n", str); + *level = sid->SubAuthority[0]; LocalFree(str);
ret = GetSecurityDescriptorDacl(sd, &present, &dacl, &defaulted); @@ -7277,6 +7272,89 @@ static void test_token_label(void) todo_wine ok(!present, "DACL present\n");
free(sd); +} + +static void test_token_label(void) +{ + SID low_sid = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, + {SECURITY_MANDATORY_LOW_RID}}; + char sacl_buffer[50]; + SECURITY_ATTRIBUTES attr = {.nLength = sizeof(SECURITY_ATTRIBUTES)}; + ACL *sacl = (ACL *)sacl_buffer; + TOKEN_LINKED_TOKEN linked; + DWORD level, level2, size; + PSECURITY_DESCRIPTOR sd; + HANDLE token, token2; + BOOL ret; + + if (!pAddMandatoryAce) + { + win_skip("Mandatory integrity control is not supported.\n"); + return; + } + + ret = OpenProcessToken(GetCurrentProcess(), READ_CONTROL | TOKEN_QUERY | TOKEN_DUPLICATE, &token); + ok(ret, "OpenProcessToken failed with error %lu\n", GetLastError()); + + check_token_label(token, &level, TRUE); + + ret = DuplicateTokenEx(token, READ_CONTROL, NULL, SecurityAnonymous, TokenPrimary, &token2); + ok(ret, "Failed to duplicate token, error %lu\n", GetLastError()); + + check_token_label(token2, &level2, TRUE); + ok(level2 == level, "Expected level %#lx, got %#lx.\n", level, level2); + + CloseHandle(token2); + + ret = DuplicateTokenEx(token, READ_CONTROL, NULL, SecurityImpersonation, TokenImpersonation, &token2); + ok(ret, "Failed to duplicate token, error %lu\n", GetLastError()); + + check_token_label(token2, &level2, TRUE); + ok(level2 == level, "Expected level %#lx, got %#lx.\n", level, level2); + + CloseHandle(token2); + + /* Any label set in the SD when calling DuplicateTokenEx() is ignored. */ + + ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %lu\n", GetLastError()); + + sd = malloc(size); + ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size); + ok(ret, "GetKernelObjectSecurity failed with error %lu\n", GetLastError()); + + InitializeAcl(sacl, sizeof(sacl_buffer), ACL_REVISION); + AddMandatoryAce(sacl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_sid); + SetSecurityDescriptorSacl(sd, TRUE, sacl, FALSE); + + attr.lpSecurityDescriptor = sd; + ret = DuplicateTokenEx(token, TOKEN_ALL_ACCESS, &attr, SecurityImpersonation, TokenImpersonation, &token2); + ok(ret, "Failed to duplicate token, error %lu\n", GetLastError()); + + check_token_label(token2, &level2, TRUE); + ok(level2 == level, "Expected level %#lx, got %#lx.\n", level, level2); + + /* Trying to set a SD on the token also claims success but has no effect. */ + + ret = SetKernelObjectSecurity(token2, LABEL_SECURITY_INFORMATION, sd); + ok(ret, "Failed to set SD, error %lu\n", GetLastError()); + + check_token_label(token2, &level2, FALSE); + ok(level2 == level, "Expected level %#lx, got %#lx.\n", level, level2); + + free(sd); + + /* Test the linked token. */ + + ret = GetTokenInformation(token, TokenLinkedToken, &linked, sizeof(linked), &size); + ok(ret, "Failed to get linked token, error %lu\n", GetLastError()); + + check_token_label(linked.LinkedToken, &level2, TRUE); + ok(level2 == level, "Expected level %#lx, got %#lx.\n", level, level2); + + CloseHandle(linked.LinkedToken); + CloseHandle(token); }