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 ); + } +}