From d342d1413cd1ca7ca49e4d42906c4bb51e8fba5e Mon Sep 17 00:00:00 2001 From: Rob Shearman Date: Wed, 21 Feb 2007 17:10:45 +0000 Subject: [PATCH] server: Add get_token_impersonation_level server call for retrieving the impersonation level from a token. Add tests for GetTokenInformation(TokenImpersonationLevel). --- dlls/advapi32/tests/security.c | 24 ++++++++++++++++++++---- dlls/ntdll/nt.c | 15 ++++++++++++++- include/wine/server_protocol.h | 17 ++++++++++++++++- server/protocol.def | 7 +++++++ server/request.h | 2 ++ server/token.c | 17 +++++++++++++++++ server/trace.c | 13 +++++++++++++ 7 files changed, 89 insertions(+), 6 deletions(-) diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index 201c649b93e..95d2f9cc23b 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -840,7 +840,7 @@ static void test_AccessCheck(void) /* test GetTokenInformation for the various attributes */ static void test_token_attr(void) { - HANDLE Token; + HANDLE Token, ImpersonationToken; DWORD Size; TOKEN_PRIVILEGES *Privileges; TOKEN_GROUPS *Groups; @@ -848,6 +848,7 @@ static void test_token_attr(void) BOOL ret; DWORD i, GLE; LPSTR SidString; + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; /* cygwin-like use case */ ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &Token); @@ -855,16 +856,20 @@ static void test_token_attr(void) if (ret) { BYTE buf[1024]; - DWORD bufsize = sizeof(buf); - ret = GetTokenInformation(Token, TokenUser,(void*)buf, bufsize, &bufsize); + Size = sizeof(buf); + ret = GetTokenInformation(Token, TokenUser,(void*)buf, Size, &Size); ok(ret, "GetTokenInformation failed with error %d\n", GetLastError()); + Size = sizeof(ImpersonationLevel); + ret = GetTokenInformation(Token, TokenImpersonationLevel, &ImpersonationLevel, Size, &Size); + GLE = GetLastError(); + ok(!ret && (GLE == ERROR_INVALID_PARAMETER), "GetTokenInformation(TokenImpersonationLevel) on primary token should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GLE); CloseHandle(Token); } if(!pConvertSidToStringSidA) return; - ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token); + ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_DUPLICATE, &Token); GLE = GetLastError(); ok(ret || (GLE == ERROR_CALL_NOT_IMPLEMENTED), "OpenProcessToken failed with error %d\n", GLE); @@ -928,6 +933,17 @@ static void test_token_attr(void) trace("\t%s, 0x%x\n", Name, Privileges->Privileges[i].Attributes); } HeapFree(GetProcessHeap(), 0, Privileges); + + ret = DuplicateToken(Token, SecurityAnonymous, &ImpersonationToken); + ok(ret, "DuplicateToken failed with error %d\n", GetLastError()); + + Size = sizeof(ImpersonationLevel); + ret = GetTokenInformation(ImpersonationToken, TokenImpersonationLevel, &ImpersonationLevel, Size, &Size); + ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError()); + ok(ImpersonationLevel == SecurityAnonymous, "ImpersonationLevel should have been SecurityAnonymous instead of %d\n", ImpersonationLevel); + + CloseHandle(ImpersonationToken); + CloseHandle(Token); } typedef union _MAX_SID diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index 43ce6e13a1e..ce3c31a33ed 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -217,8 +217,10 @@ NTSTATUS WINAPI NtQueryInformationToken( case TokenType: len = sizeof (TOKEN_TYPE); break; -#if 0 case TokenImpersonationLevel: + len = sizeof(SECURITY_IMPERSONATION_LEVEL); + break; +#if 0 case TokenStatistics: #endif /* 0 */ default: @@ -352,6 +354,17 @@ NTSTATUS WINAPI NtQueryInformationToken( owner->Owner = sid; } break; + case TokenImpersonationLevel: + SERVER_START_REQ( get_token_impersonation_level ) + { + SECURITY_IMPERSONATION_LEVEL *impersonation_level = tokeninfo; + req->handle = token; + status = wine_server_call( req ); + if (status == STATUS_SUCCESS) + *impersonation_level = reply->impersonation_level; + } + SERVER_END_REQ; + break; default: { ERR("Unhandled Token Information class %d!\n", tokeninfoclass); diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index b5c620170c2..db13e0c6dbc 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -3992,6 +3992,18 @@ struct get_object_info_reply }; +struct get_token_impersonation_level_request +{ + struct request_header __header; + obj_handle_t handle; +}; +struct get_token_impersonation_level_reply +{ + struct reply_header __header; + int impersonation_level; +}; + + enum request { REQ_new_process, @@ -4210,6 +4222,7 @@ enum request REQ_open_symlink, REQ_query_symlink, REQ_get_object_info, + REQ_get_token_impersonation_level, REQ_NB_REQUESTS }; @@ -4433,6 +4446,7 @@ union generic_request struct open_symlink_request open_symlink_request; struct query_symlink_request query_symlink_request; struct get_object_info_request get_object_info_request; + struct get_token_impersonation_level_request get_token_impersonation_level_request; }; union generic_reply { @@ -4654,8 +4668,9 @@ union generic_reply struct open_symlink_reply open_symlink_reply; struct query_symlink_reply query_symlink_reply; struct get_object_info_reply get_object_info_reply; + struct get_token_impersonation_level_reply get_token_impersonation_level_reply; }; -#define SERVER_PROTOCOL_VERSION 277 +#define SERVER_PROTOCOL_VERSION 278 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index e4f16a995a7..69daab37ba7 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2862,3 +2862,10 @@ enum message_type unsigned int access; /* granted access mask */ unsigned int ref_count; /* object ref count */ @END + +/* Query the impersonation level of an impersonation token */ +@REQ(get_token_impersonation_level) + obj_handle_t handle; /* handle to the object */ +@REPLY + int impersonation_level; /* impersonation level of the impersonation token */ +@END diff --git a/server/request.h b/server/request.h index 9119ec1994b..b24d7c7a9e4 100644 --- a/server/request.h +++ b/server/request.h @@ -326,6 +326,7 @@ DECL_HANDLER(create_symlink); DECL_HANDLER(open_symlink); DECL_HANDLER(query_symlink); DECL_HANDLER(get_object_info); +DECL_HANDLER(get_token_impersonation_level); #ifdef WANT_REQUEST_HANDLERS @@ -548,6 +549,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_open_symlink, (req_handler)req_query_symlink, (req_handler)req_get_object_info, + (req_handler)req_get_token_impersonation_level, }; #endif /* WANT_REQUEST_HANDLERS */ diff --git a/server/token.c b/server/token.c index c4906a5fd75..573634bd97b 100644 --- a/server/token.c +++ b/server/token.c @@ -1386,6 +1386,23 @@ DECL_HANDLER(get_token_groups) } } +DECL_HANDLER(get_token_impersonation_level) +{ + struct token *token; + + if ((token = (struct token *)get_handle_obj( current->process, req->handle, + TOKEN_QUERY, + &token_ops ))) + { + if (token->primary) + set_error( STATUS_INVALID_PARAMETER ); + else + reply->impersonation_level = token->impersonation_level; + + release_object( token ); + } +} + DECL_HANDLER(set_security_object) { data_size_t sd_size = get_req_data_size(); diff --git a/server/trace.c b/server/trace.c index 50926f581b5..d4bcf08fdb1 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3443,6 +3443,16 @@ static void dump_get_object_info_reply( const struct get_object_info_reply *req fprintf( stderr, " ref_count=%08x", req->ref_count ); } +static void dump_get_token_impersonation_level_request( const struct get_token_impersonation_level_request *req ) +{ + fprintf( stderr, " handle=%p", req->handle ); +} + +static void dump_get_token_impersonation_level_reply( const struct get_token_impersonation_level_reply *req ) +{ + fprintf( stderr, " impersonation_level=%d", req->impersonation_level ); +} + static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_new_process_request, (dump_func)dump_get_new_process_info_request, @@ -3660,6 +3670,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_open_symlink_request, (dump_func)dump_query_symlink_request, (dump_func)dump_get_object_info_request, + (dump_func)dump_get_token_impersonation_level_request, }; static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { @@ -3879,6 +3890,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_open_symlink_reply, (dump_func)dump_query_symlink_reply, (dump_func)dump_get_object_info_reply, + (dump_func)dump_get_token_impersonation_level_reply, }; static const char * const req_names[REQ_NB_REQUESTS] = { @@ -4098,6 +4110,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "open_symlink", "query_symlink", "get_object_info", + "get_token_impersonation_level", }; static const struct