Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/advapi32/tests/security.c | 90 ++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+)
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index f0b6c90390d..604d70ca34d 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -7930,6 +7930,95 @@ static void test_duplicate_token(void) CloseHandle(token); }
+static void test_GetKernelObjectSecurity(void) +{ + /* Basic tests for parameter validation. */ + + SECURITY_DESCRIPTOR_CONTROL control; + DWORD size, ret_size, revision; + BOOL ret, present, defaulted; + PSECURITY_DESCRIPTOR sd; + PSID sid; + ACL *acl; + + SetLastError(0xdeadbeef); + size = 0xdeadbeef; + ret = GetKernelObjectSecurity(NULL, OWNER_SECURITY_INFORMATION, NULL, 0, &size); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE, "got error %u\n", GetLastError()); + ok(size == 0xdeadbeef, "got size %u\n", size); + + SetLastError(0xdeadbeef); + ret = GetKernelObjectSecurity(GetCurrentProcess(), OWNER_SECURITY_INFORMATION, NULL, 0, NULL); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_NOACCESS, "got error %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + size = 0xdeadbeef; + ret = GetKernelObjectSecurity(GetCurrentProcess(), OWNER_SECURITY_INFORMATION, NULL, 0, &size); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %u\n", GetLastError()); + ok(size > 0 && size != 0xdeadbeef, "got size 0\n"); + + sd = malloc(size + 1); + + SetLastError(0xdeadbeef); + ret = GetKernelObjectSecurity(GetCurrentProcess(), OWNER_SECURITY_INFORMATION, sd, size - 1, &ret_size); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %u\n", GetLastError()); + ok(ret_size == size, "expected size %u, got %u\n", size, ret_size); + + SetLastError(0xdeadbeef); + ret = GetKernelObjectSecurity(GetCurrentProcess(), OWNER_SECURITY_INFORMATION, sd, size + 1, &ret_size); + ok(ret, "expected success\n"); + ok(GetLastError() == 0xdeadbeef, "got error %u\n", GetLastError()); + ok(ret_size == size, "expected size %u, got %u\n", size, ret_size); + + free(sd); + + /* Calling the function with flags not defined succeeds and yields an empty + * descriptor. */ + + SetLastError(0xdeadbeef); + ret = GetKernelObjectSecurity(GetCurrentProcess(), 0x100000, NULL, 0, &size); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %u\n", GetLastError()); + + sd = malloc(size); + SetLastError(0xdeadbeef); + ret = GetKernelObjectSecurity(GetCurrentProcess(), 0x100000, sd, size, &ret_size); + ok(ret, "expected success\n"); + ok(GetLastError() == 0xdeadbeef, "got error %u\n", GetLastError()); + ok(ret_size == size, "expected size %u, got %u\n", size, ret_size); + + ret = GetSecurityDescriptorControl(sd, &control, &revision); + ok(ret, "got error %u\n", GetLastError()); + todo_wine ok(control == SE_SELF_RELATIVE, "got control %#x\n", control); + ok(revision == SECURITY_DESCRIPTOR_REVISION1, "got revision %u\n", revision); + + ret = GetSecurityDescriptorOwner(sd, &sid, &defaulted); + ok(ret, "got error %u\n", GetLastError()); + ok(!sid, "expected no owner SID\n"); + ok(!defaulted, "expected owner not defaulted\n"); + + ret = GetSecurityDescriptorGroup(sd, &sid, &defaulted); + ok(ret, "got error %u\n", GetLastError()); + ok(!sid, "expected no group SID\n"); + ok(!defaulted, "expected group not defaulted\n"); + + ret = GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted); + ok(ret, "got error %u\n", GetLastError()); + todo_wine ok(!present, "expeced no DACL present\n"); + ok(!defaulted, "expected DACL not defaulted\n"); + + ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted); + ok(ret, "got error %u\n", GetLastError()); + ok(!present, "expeced no SACL present\n"); + ok(!defaulted, "expected SACL not defaulted\n"); + + free(sd); +} + START_TEST(security) { init(); @@ -7996,6 +8085,7 @@ START_TEST(security) test_create_process_token(); test_pseudo_handle_security(); test_duplicate_token(); + test_GetKernelObjectSecurity();
/* Must be the last test, modifies process token */ test_token_security_descriptor();
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/advapi32/tests/security.c | 257 +++++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+)
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index 604d70ca34d..1cd6e3ccbdc 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -8019,6 +8019,262 @@ static void test_GetKernelObjectSecurity(void) free(sd); }
+static void check_different_token(HANDLE token1, HANDLE token2) +{ + TOKEN_STATISTICS stats1, stats2; + DWORD size; + BOOL ret; + + ret = GetTokenInformation(token1, TokenStatistics, &stats1, sizeof(stats1), &size); + ok(ret, "got error %u\n", GetLastError()); + ret = GetTokenInformation(token2, TokenStatistics, &stats2, sizeof(stats2), &size); + ok(ret, "got error %u\n", GetLastError()); + + ok(memcmp(&stats1.TokenId, &stats2.TokenId, sizeof(LUID)), "expected different IDs\n"); +} + +static void test_elevation(void) +{ + TOKEN_LINKED_TOKEN linked, linked2; + DWORD orig_type, type, size; + TOKEN_ELEVATION elevation; + HANDLE token, token2; + BOOL ret; + + ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | READ_CONTROL | TOKEN_DUPLICATE + | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_DEFAULT, &token); + ok(ret, "got error %u\n", GetLastError()); + + ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size); + ok(ret, "got error %u\n", GetLastError()); + orig_type = type; + ret = GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &size); + ok(ret, "got error %u\n", GetLastError()); + ret = GetTokenInformation(token, TokenLinkedToken, &linked, sizeof(linked), &size); + todo_wine ok(ret, "got error %u\n", GetLastError()); + if (!ret) return; + + if (type == TokenElevationTypeDefault) + { + ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated); + ok(!linked.LinkedToken, "expected no linked token\n"); + } + else if (type == TokenElevationTypeLimited) + { + ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated); + ok(!!linked.LinkedToken, "expected a linked token\n"); + + TEST_GRANTED_ACCESS(linked.LinkedToken, TOKEN_ALL_ACCESS); + ret = GetTokenInformation(linked.LinkedToken, TokenElevationType, &type, sizeof(type), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(type == TokenElevationTypeFull, "got type %#x\n", type); + ret = GetTokenInformation(linked.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(elevation.TokenIsElevated == TRUE, "got elevation %#x\n", elevation.TokenIsElevated); + + /* Asking for the linked token again gives us a different token. */ + ret = GetTokenInformation(token, TokenLinkedToken, &linked2, sizeof(linked2), &size); + ok(ret, "got error %u\n", GetLastError()); + + ret = GetTokenInformation(linked2.LinkedToken, TokenElevationType, &type, sizeof(type), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(type == TokenElevationTypeFull, "got type %#x\n", type); + ret = GetTokenInformation(linked2.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(elevation.TokenIsElevated == TRUE, "got elevation %#x\n", elevation.TokenIsElevated); + + check_different_token(linked.LinkedToken, linked2.LinkedToken); + + CloseHandle(linked2.LinkedToken); + + /* Asking for the linked token's linked token gives us a new limited token. */ + ret = GetTokenInformation(linked.LinkedToken, TokenLinkedToken, &linked2, sizeof(linked2), &size); + ok(ret, "got error %u\n", GetLastError()); + + ret = GetTokenInformation(linked2.LinkedToken, TokenElevationType, &type, sizeof(type), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(type == TokenElevationTypeLimited, "got type %#x\n", type); + ret = GetTokenInformation(linked2.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated); + + check_different_token(token, linked2.LinkedToken); + + CloseHandle(linked2.LinkedToken); + + CloseHandle(linked.LinkedToken); + + type = TokenElevationTypeLimited; + ret = SetTokenInformation(token, TokenElevationType, &type, sizeof(type)); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError()); + + elevation.TokenIsElevated = FALSE; + ret = SetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation)); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError()); + } + else + { + ok(elevation.TokenIsElevated == TRUE, "got elevation %#x\n", elevation.TokenIsElevated); + ok(!!linked.LinkedToken, "expected a linked token\n"); + + TEST_GRANTED_ACCESS(linked.LinkedToken, TOKEN_ALL_ACCESS); + ret = GetTokenInformation(linked.LinkedToken, TokenElevationType, &type, sizeof(type), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(type == TokenElevationTypeLimited, "got type %#x\n", type); + ret = GetTokenInformation(linked.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated); + + /* Asking for the linked token again gives us a different token. */ + ret = GetTokenInformation(token, TokenLinkedToken, &linked2, sizeof(linked2), &size); + ok(ret, "got error %u\n", GetLastError()); + + ret = GetTokenInformation(linked2.LinkedToken, TokenElevationType, &type, sizeof(type), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(type == TokenElevationTypeLimited, "got type %#x\n", type); + ret = GetTokenInformation(linked2.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated); + + check_different_token(linked.LinkedToken, linked2.LinkedToken); + + CloseHandle(linked2.LinkedToken); + + /* Asking for the linked token's linked token gives us a new elevated token. */ + ret = GetTokenInformation(linked.LinkedToken, TokenLinkedToken, &linked2, sizeof(linked2), &size); + ok(ret, "got error %u\n", GetLastError()); + + ret = GetTokenInformation(linked2.LinkedToken, TokenElevationType, &type, sizeof(type), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(type == TokenElevationTypeFull, "got type %#x\n", type); + ret = GetTokenInformation(linked2.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(elevation.TokenIsElevated == TRUE, "got elevation %#x\n", elevation.TokenIsElevated); + + check_different_token(token, linked2.LinkedToken); + + CloseHandle(linked2.LinkedToken); + + CloseHandle(linked.LinkedToken); + + type = TokenElevationTypeLimited; + ret = SetTokenInformation(token, TokenElevationType, &type, sizeof(type)); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError()); + + elevation.TokenIsElevated = FALSE; + ret = SetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation)); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError()); + } + + ret = DuplicateTokenEx(token, TOKEN_ALL_ACCESS, NULL, SecurityAnonymous, TokenPrimary, &token2); + ok(ret, "got error %u\n", GetLastError()); + ret = GetTokenInformation(token2, TokenElevationType, &type, sizeof(type), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(type == orig_type, "expected same type\n"); + ret = GetTokenInformation(token2, TokenElevation, &elevation, sizeof(elevation), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(elevation.TokenIsElevated == (type == TokenElevationTypeFull), "got elevation %#x\n", elevation.TokenIsElevated); + ret = GetTokenInformation(token2, TokenLinkedToken, &linked, sizeof(linked), &size); + ok(ret, "got error %u\n", GetLastError()); + if (type == TokenElevationTypeDefault) + ok(!linked.LinkedToken, "expected no linked token\n"); + else + ok(!!linked.LinkedToken, "expected a linked token\n"); + CloseHandle(linked.LinkedToken); + CloseHandle(token2); + + ret = CreateRestrictedToken(token, 0, 0, NULL, 0, NULL, 0, NULL, &token2); + ok(ret, "got error %u\n", GetLastError()); + ret = GetTokenInformation(token2, TokenElevationType, &type, sizeof(type), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(type == orig_type, "expected same type\n"); + ret = GetTokenInformation(token2, TokenElevation, &elevation, sizeof(elevation), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(elevation.TokenIsElevated == (type == TokenElevationTypeFull), "got elevation %#x\n", elevation.TokenIsElevated); + ret = GetTokenInformation(token2, TokenLinkedToken, &linked, sizeof(linked), &size); + ok(ret, "got error %u\n", GetLastError()); + if (type == TokenElevationTypeDefault) + ok(!linked.LinkedToken, "expected no linked token\n"); + else + ok(!!linked.LinkedToken, "expected a linked token\n"); + CloseHandle(linked.LinkedToken); + CloseHandle(token2); + + if (type != TokenElevationTypeDefault) + { + char prev_privs_buffer[128], acl_buffer[256], prev_acl_buffer[256]; + TOKEN_PRIVILEGES privs, *prev_privs = (TOKEN_PRIVILEGES *)prev_privs_buffer; + TOKEN_DEFAULT_DACL *prev_acl = (TOKEN_DEFAULT_DACL *)prev_acl_buffer; + TOKEN_DEFAULT_DACL *ret_acl = (TOKEN_DEFAULT_DACL *)acl_buffer; + TOKEN_DEFAULT_DACL default_acl; + PRIVILEGE_SET priv_set; + BOOL ret, is_member; + DWORD size; + ACL acl; + + /* Linked tokens do not preserve privilege modifications. */ + + privs.PrivilegeCount = 1; + ret = LookupPrivilegeValueA(NULL, "SeChangeNotifyPrivilege", &privs.Privileges[0].Luid); + ok(ret, "got error %u\n", GetLastError()); + privs.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED; + ret = AdjustTokenPrivileges(token, FALSE, &privs, sizeof(prev_privs_buffer), prev_privs, &size); + ok(ret, "got error %u\n", GetLastError()); + + priv_set.PrivilegeCount = 1; + priv_set.Control = 0; + priv_set.Privilege[0] = privs.Privileges[0]; + ret = PrivilegeCheck(token, &priv_set, &is_member); + ok(ret, "got error %u\n", GetLastError()); + ok(!is_member, "not a member\n"); + + ret = GetTokenInformation(token, TokenLinkedToken, &linked, sizeof(linked), &size); + ok(ret, "got error %u\n", GetLastError()); + + ret = PrivilegeCheck(linked.LinkedToken, &priv_set, &is_member); + ok(ret, "got error %u\n", GetLastError()); + ok(is_member, "not a member\n"); + + CloseHandle(linked.LinkedToken); + + ret = AdjustTokenPrivileges(token, FALSE, prev_privs, 0, NULL, NULL); + ok(ret, "got error %u\n", GetLastError()); + + /* Linked tokens do not preserve default DACL modifications. */ + + ret = GetTokenInformation(token, TokenDefaultDacl, prev_acl, sizeof(prev_acl_buffer), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(prev_acl->DefaultDacl->AceCount, "expected non-empty default DACL\n"); + + InitializeAcl(&acl, sizeof(acl), ACL_REVISION); + default_acl.DefaultDacl = &acl; + ret = SetTokenInformation(token, TokenDefaultDacl, &default_acl, sizeof(default_acl)); + ok(ret, "got error %u\n", GetLastError()); + + ret = GetTokenInformation(token, TokenDefaultDacl, ret_acl, sizeof(acl_buffer), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(!ret_acl->DefaultDacl->AceCount, "expected empty default DACL\n"); + + ret = GetTokenInformation(token, TokenLinkedToken, &linked, sizeof(linked), &size); + ok(ret, "got error %u\n", GetLastError()); + + ret = GetTokenInformation(linked.LinkedToken, TokenDefaultDacl, ret_acl, sizeof(acl_buffer), &size); + ok(ret, "got error %u\n", GetLastError()); + ok(ret_acl->DefaultDacl->AceCount, "expected non-empty default DACL\n"); + + CloseHandle(linked.LinkedToken); + + ret = SetTokenInformation(token, TokenDefaultDacl, prev_acl, sizeof(*prev_acl)); + ok(ret, "got error %u\n", GetLastError()); + } + + CloseHandle(token); +} + START_TEST(security) { init(); @@ -8086,6 +8342,7 @@ START_TEST(security) test_pseudo_handle_security(); test_duplicate_token(); test_GetKernelObjectSecurity(); + test_elevation();
/* Must be the last test, modifies process token */ test_token_security_descriptor();
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=85696
Your paranoid android.
=== w2008s64 (32 bit report) ===
advapi32: security.c:8067: Test failed: got error 1312
=== wvistau64 (64 bit report) ===
advapi32: security.c:8025: Test failed: expected DACL not defaulted security.c:8030: Test failed: expected SACL not defaulted
=== w2008s64 (64 bit report) ===
advapi32: security.c:8025: Test failed: expected DACL not defaulted security.c:8030: Test failed: expected SACL not defaulted security.c:8067: Test failed: got error 1312
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/unix/security.c | 8 ++++++-- server/protocol.def | 8 ++++++++ server/token.c | 20 +++++++++++++++++--- 3 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/unix/security.c b/dlls/ntdll/unix/security.c index fc9cc9d4572..04f1b43a5cb 100644 --- a/dlls/ntdll/unix/security.c +++ b/dlls/ntdll/unix/security.c @@ -391,11 +391,15 @@ NTSTATUS WINAPI NtQueryInformationToken( HANDLE token, TOKEN_INFORMATION_CLASS c break;
case TokenElevationType: + SERVER_START_REQ( get_token_elevation ) { TOKEN_ELEVATION_TYPE *type = info; - FIXME("QueryInformationToken( ..., TokenElevationType, ...) semi-stub\n"); - *type = TokenElevationTypeFull; + + req->handle = wine_server_obj_handle( token ); + status = wine_server_call( req ); + if (!status) *type = reply->elevation; } + SERVER_END_REQ; break;
case TokenElevation: diff --git a/server/protocol.def b/server/protocol.def index fb3ee3a52de..43899bee240 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3433,6 +3433,14 @@ struct handle_info @END
+/* Get the token elevation type */ +@REQ(get_token_elevation) + obj_handle_t handle; /* handle to the token */ +@REPLY + int elevation; /* token elevation type */ +@END + + /* Create I/O completion port */ @REQ(create_completion) unsigned int access; /* desired access to a port */ diff --git a/server/token.c b/server/token.c index 2ae1cb1780a..5499841dd50 100644 --- a/server/token.c +++ b/server/token.c @@ -126,6 +126,7 @@ struct token ACL *default_dacl; /* the default DACL to assign to objects created by this user */ TOKEN_SOURCE source; /* source of the token */ int impersonation_level; /* impersonation level this token is capable of if non-primary token */ + int elevation; /* elevation type */ };
struct privilege @@ -541,7 +542,7 @@ static struct token *create_token( unsigned primary, const SID *user, const LUID_AND_ATTRIBUTES *privs, unsigned int priv_count, const ACL *default_dacl, TOKEN_SOURCE source, const luid_t *modified_id, - int impersonation_level ) + int impersonation_level, int elevation ) { struct token *token = alloc_object( &token_ops ); if (token) @@ -563,6 +564,7 @@ static struct token *create_token( unsigned primary, const SID *user, token->impersonation_level = impersonation_level; token->default_dacl = NULL; token->primary_group = NULL; + token->elevation = elevation;
/* copy user */ token->user = memdup( user, security_sid_len( user )); @@ -678,7 +680,7 @@ struct token *token_duplicate( struct token *src_token, unsigned primary, token = create_token( primary, src_token->user, NULL, 0, NULL, 0, src_token->default_dacl, src_token->source, modified_id, - impersonation_level ); + impersonation_level, src_token->elevation ); if (!token) return token;
/* copy groups */ @@ -890,7 +892,7 @@ struct token *token_create_admin( void ) static const TOKEN_SOURCE admin_source = {"SeMgr", {0, 0}}; token = create_token( TRUE, user_sid, admin_groups, ARRAY_SIZE( admin_groups ), admin_privs, ARRAY_SIZE( admin_privs ), default_dacl, - admin_source, NULL, -1 ); + admin_source, NULL, -1, TokenElevationTypeFull ); /* we really need a primary group */ assert( token->primary_group ); } @@ -1665,3 +1667,15 @@ DECL_HANDLER(set_token_default_dacl) release_object( token ); } } + +DECL_HANDLER(get_token_elevation) +{ + struct token *token; + + if ((token = (struct token *)get_handle_obj( current->process, req->handle, + TOKEN_QUERY, &token_ops ))) + { + reply->elevation = token->elevation; + release_object( token ); + } +}
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/advapi32/tests/security.c | 11 +++++------ dlls/ntdll/unix/security.c | 14 +++++++++++++- server/process.c | 2 +- server/protocol.def | 8 ++++++++ server/security.h | 2 +- server/token.c | 31 +++++++++++++++++++++++++++++-- 6 files changed, 57 insertions(+), 11 deletions(-)
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index 1cd6e3ccbdc..88d16dbee92 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -8051,8 +8051,7 @@ static void test_elevation(void) ret = GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &size); ok(ret, "got error %u\n", GetLastError()); ret = GetTokenInformation(token, TokenLinkedToken, &linked, sizeof(linked), &size); - todo_wine ok(ret, "got error %u\n", GetLastError()); - if (!ret) return; + ok(ret, "got error %u\n", GetLastError());
if (type == TokenElevationTypeDefault) { @@ -8125,7 +8124,7 @@ static void test_elevation(void) ok(type == TokenElevationTypeLimited, "got type %#x\n", type); ret = GetTokenInformation(linked.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size); ok(ret, "got error %u\n", GetLastError()); - ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated); + todo_wine ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated);
/* Asking for the linked token again gives us a different token. */ ret = GetTokenInformation(token, TokenLinkedToken, &linked2, sizeof(linked2), &size); @@ -8136,7 +8135,7 @@ static void test_elevation(void) ok(type == TokenElevationTypeLimited, "got type %#x\n", type); ret = GetTokenInformation(linked2.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size); ok(ret, "got error %u\n", GetLastError()); - ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated); + todo_wine ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated);
check_different_token(linked.LinkedToken, linked2.LinkedToken);
@@ -8162,12 +8161,12 @@ static void test_elevation(void) type = TokenElevationTypeLimited; ret = SetTokenInformation(token, TokenElevationType, &type, sizeof(type)); ok(!ret, "expected failure\n"); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError()); + todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError());
elevation.TokenIsElevated = FALSE; ret = SetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation)); ok(!ret, "expected failure\n"); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError()); + todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError()); }
ret = DuplicateTokenEx(token, TOKEN_ALL_ACCESS, NULL, SecurityAnonymous, TokenPrimary, &token2); diff --git a/dlls/ntdll/unix/security.c b/dlls/ntdll/unix/security.c index 04f1b43a5cb..c8cd04b70f3 100644 --- a/dlls/ntdll/unix/security.c +++ b/dlls/ntdll/unix/security.c @@ -167,7 +167,7 @@ NTSTATUS WINAPI NtQueryInformationToken( HANDLE token, TOKEN_INFORMATION_CLASS c 0, /* TokenAuditPolicy */ 0, /* TokenOrigin */ sizeof(TOKEN_ELEVATION_TYPE), /* TokenElevationType */ - 0, /* TokenLinkedToken */ + sizeof(TOKEN_LINKED_TOKEN), /* TokenLinkedToken */ sizeof(TOKEN_ELEVATION), /* TokenElevation */ 0, /* TokenHasRestrictions */ 0, /* TokenAccessInformation */ @@ -476,6 +476,18 @@ NTSTATUS WINAPI NtQueryInformationToken( HANDLE token, TOKEN_INFORMATION_CLASS c SERVER_END_REQ; break;
+ case TokenLinkedToken: + SERVER_START_REQ( create_linked_token ) + { + TOKEN_LINKED_TOKEN *linked = info; + + req->handle = wine_server_obj_handle( token ); + status = wine_server_call( req ); + if (!status) linked->LinkedToken = wine_server_ptr_handle( reply->linked ); + } + SERVER_END_REQ; + break; + default: ERR( "Unhandled token information class %u\n", class ); return STATUS_NOT_IMPLEMENTED; diff --git a/server/process.c b/server/process.c index 78821593da0..e5fe7cc6b6e 100644 --- a/server/process.c +++ b/server/process.c @@ -578,7 +578,7 @@ struct process *create_process( int fd, struct process *parent, int inherit_all, if (!parent) { process->handles = alloc_handle_table( process, 0 ); - process->token = token_create_admin(); + process->token = token_create_admin( TokenElevationTypeFull ); process->affinity = ~0; } else diff --git a/server/protocol.def b/server/protocol.def index 43899bee240..2641ac86ee8 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3441,6 +3441,14 @@ struct handle_info @END
+/* Create a token which is an elevation counterpart to this token */ +@REQ(create_linked_token) + obj_handle_t handle; /* handle to the token */ +@REPLY + obj_handle_t linked; /* handle to the linked token */ +@END + + /* Create I/O completion port */ @REQ(create_completion) unsigned int access; /* desired access to a port */ diff --git a/server/security.h b/server/security.h index 08bdb8de805..416e1b6902d 100644 --- a/server/security.h +++ b/server/security.h @@ -54,7 +54,7 @@ extern const PSID security_high_label_sid; /* token functions */
extern struct token *get_token_obj( struct process *process, obj_handle_t handle, unsigned int access ); -extern struct token *token_create_admin(void); +extern struct token *token_create_admin( int elevation ); extern int token_assign_label( struct token *token, PSID label ); extern struct token *token_duplicate( struct token *src_token, unsigned primary, int impersonation_level, const struct security_descriptor *sd, diff --git a/server/token.c b/server/token.c index 5499841dd50..6cdeeacca71 100644 --- a/server/token.c +++ b/server/token.c @@ -830,7 +830,7 @@ struct token *get_token_obj( struct process *process, obj_handle_t handle, unsig return (struct token *)get_handle_obj( process, handle, access, &token_ops ); }
-struct token *token_create_admin( void ) +struct token *token_create_admin( int elevation ) { struct token *token = NULL; static const SID_IDENTIFIER_AUTHORITY nt_authority = { SECURITY_NT_AUTHORITY }; @@ -892,7 +892,7 @@ struct token *token_create_admin( void ) static const TOKEN_SOURCE admin_source = {"SeMgr", {0, 0}}; token = create_token( TRUE, user_sid, admin_groups, ARRAY_SIZE( admin_groups ), admin_privs, ARRAY_SIZE( admin_privs ), default_dacl, - admin_source, NULL, -1, TokenElevationTypeFull ); + admin_source, NULL, -1, elevation ); /* we really need a primary group */ assert( token->primary_group ); } @@ -1679,3 +1679,30 @@ DECL_HANDLER(get_token_elevation) release_object( token ); } } + +DECL_HANDLER(create_linked_token) +{ + struct token *token, *linked; + + if ((token = (struct token *)get_handle_obj( current->process, req->handle, + TOKEN_QUERY, &token_ops ))) + { + if (token->elevation == TokenElevationTypeFull) + { + linked = token_create_admin( TokenElevationTypeLimited ); + reply->linked = alloc_handle( current->process, linked, TOKEN_ALL_ACCESS, 0 ); + release_object( linked ); + } + else if (token->elevation == TokenElevationTypeLimited) + { + linked = token_create_admin( TokenElevationTypeFull ); + reply->linked = alloc_handle( current->process, linked, TOKEN_ALL_ACCESS, 0 ); + release_object( linked ); + } + else + { + reply->linked = 0; + } + release_object( token ); + } +}
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=85698
Your paranoid android.
=== w2008s64 (32 bit report) ===
advapi32: security.c:8067: Test failed: got error 1312 security.c:8071: Test failed: got elevation 0x1 security.c:8072: Test failed: expected no linked token security.c:8192: Test failed: got elevation 0x1 security.c:8194: Test failed: got error 1312 security.c:8196: Test failed: expected no linked token security.c:8209: Test failed: got elevation 0x1 security.c:8211: Test failed: got error 1312 security.c:8213: Test failed: expected no linked token
=== wvistau64 (64 bit report) ===
advapi32: security.c:8025: Test failed: expected DACL not defaulted security.c:8030: Test failed: expected SACL not defaulted
=== w2008s64 (64 bit report) ===
advapi32: security.c:8025: Test failed: expected DACL not defaulted security.c:8030: Test failed: expected SACL not defaulted security.c:8067: Test failed: got error 1312 security.c:8071: Test failed: got elevation 0x1 security.c:8072: Test failed: expected no linked token security.c:8192: Test failed: got elevation 0x1 security.c:8194: Test failed: got error 1312 security.c:8196: Test failed: expected no linked token security.c:8209: Test failed: got elevation 0x1 security.c:8211: Test failed: got error 1312 security.c:8213: Test failed: expected no linked token
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/advapi32/tests/security.c | 4 ++-- dlls/ntdll/unix/security.c | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index 88d16dbee92..7b723e32103 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -8124,7 +8124,7 @@ static void test_elevation(void) ok(type == TokenElevationTypeLimited, "got type %#x\n", type); ret = GetTokenInformation(linked.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size); ok(ret, "got error %u\n", GetLastError()); - todo_wine ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated); + ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated);
/* Asking for the linked token again gives us a different token. */ ret = GetTokenInformation(token, TokenLinkedToken, &linked2, sizeof(linked2), &size); @@ -8135,7 +8135,7 @@ static void test_elevation(void) ok(type == TokenElevationTypeLimited, "got type %#x\n", type); ret = GetTokenInformation(linked2.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size); ok(ret, "got error %u\n", GetLastError()); - todo_wine ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated); + ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated);
check_different_token(linked.LinkedToken, linked2.LinkedToken);
diff --git a/dlls/ntdll/unix/security.c b/dlls/ntdll/unix/security.c index c8cd04b70f3..48bdb5a3689 100644 --- a/dlls/ntdll/unix/security.c +++ b/dlls/ntdll/unix/security.c @@ -403,11 +403,15 @@ NTSTATUS WINAPI NtQueryInformationToken( HANDLE token, TOKEN_INFORMATION_CLASS c break;
case TokenElevation: + SERVER_START_REQ( get_token_elevation ) { TOKEN_ELEVATION *elevation = info; - FIXME("QueryInformationToken( ..., TokenElevation, ...) semi-stub\n"); - elevation->TokenIsElevated = TRUE; + + req->handle = wine_server_obj_handle( token ); + status = wine_server_call( req ); + if (!status) elevation->TokenIsElevated = (reply->elevation == TokenElevationTypeFull); } + SERVER_END_REQ; break;
case TokenSessionId:
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=85699
Your paranoid android.
=== w2008s64 (32 bit report) ===
advapi32: security.c:8067: Test failed: got error 1312 security.c:8071: Test failed: got elevation 0x1 security.c:8072: Test failed: expected no linked token security.c:8192: Test failed: got elevation 0x1 security.c:8194: Test failed: got error 1312 security.c:8196: Test failed: expected no linked token security.c:8209: Test failed: got elevation 0x1 security.c:8211: Test failed: got error 1312 security.c:8213: Test failed: expected no linked token
=== wvistau64 (64 bit report) ===
advapi32: security.c:8025: Test failed: expected DACL not defaulted security.c:8030: Test failed: expected SACL not defaulted
=== w2008s64 (64 bit report) ===
advapi32: security.c:8025: Test failed: expected DACL not defaulted security.c:8030: Test failed: expected SACL not defaulted security.c:8067: Test failed: got error 1312 security.c:8071: Test failed: got elevation 0x1 security.c:8072: Test failed: expected no linked token security.c:8192: Test failed: got elevation 0x1 security.c:8194: Test failed: got error 1312 security.c:8196: Test failed: expected no linked token security.c:8209: Test failed: got elevation 0x1 security.c:8211: Test failed: got error 1312 security.c:8213: Test failed: expected no linked token
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=85695
Your paranoid android.
=== wvistau64 (64 bit report) ===
advapi32: security.c:8025: Test failed: expected DACL not defaulted security.c:8030: Test failed: expected SACL not defaulted
=== w2008s64 (64 bit report) ===
advapi32: security.c:8025: Test failed: expected DACL not defaulted security.c:8030: Test failed: expected SACL not defaulted