mirror of
https://gitlab.winehq.org/wine/wine.git
synced 2024-11-19 17:06:04 -07:00
Merge branch 'mr/default-explorer-token' into 'master'
explorer, services: Use admin tokens when appropriate. See merge request wine/wine!6602
This commit is contained in:
commit
bb3a7726ba
11 changed files with 113 additions and 21 deletions
|
@ -28,6 +28,7 @@
|
|||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "winternl.h"
|
||||
#include "winuser.h"
|
||||
#include "aclapi.h"
|
||||
#include "winnt.h"
|
||||
#include "sddl.h"
|
||||
|
@ -8571,6 +8572,42 @@ static void test_elevation(void)
|
|||
CloseHandle(token);
|
||||
}
|
||||
|
||||
static void test_admin_elevation(void)
|
||||
{
|
||||
/* Tokens with elevation type TokenElevationTypeDefault should still come
|
||||
back as elevated from a TokenElevation query if they belong to the admin
|
||||
group. The owner of the desktop window should have such a token. */
|
||||
DWORD tid, pid;
|
||||
HANDLE hproc, htok;
|
||||
TOKEN_ELEVATION_TYPE elevation_type;
|
||||
TOKEN_ELEVATION elevation;
|
||||
DWORD size;
|
||||
BOOL ret;
|
||||
|
||||
tid = GetWindowThreadProcessId(GetDesktopWindow(), &pid);
|
||||
ok(tid, "got error %lu\n", GetLastError());
|
||||
|
||||
hproc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
|
||||
ok(hproc != NULL, "got error %lu\n", GetLastError());
|
||||
|
||||
ret = OpenProcessToken(hproc, TOKEN_READ, &htok);
|
||||
ok(ret, "got error %lu\n", GetLastError());
|
||||
|
||||
CloseHandle(hproc);
|
||||
|
||||
size = sizeof(elevation_type);
|
||||
ret = GetTokenInformation(htok, TokenElevationType, &elevation_type, size, &size);
|
||||
ok(ret, "got error %lu\n", GetLastError());
|
||||
ok(elevation_type == TokenElevationTypeDefault, "unexpected elevation type %d\n", elevation_type);
|
||||
|
||||
size = sizeof(elevation);
|
||||
ret = GetTokenInformation(htok, TokenElevation, &elevation, size, &size);
|
||||
ok(ret, "got error %lu\n", GetLastError());
|
||||
ok(elevation.TokenIsElevated, "expected token to be elevated\n");
|
||||
|
||||
CloseHandle(htok);
|
||||
}
|
||||
|
||||
static void test_group_as_file_owner(void)
|
||||
{
|
||||
char sd_buffer[200], sid_buffer[100];
|
||||
|
@ -8717,6 +8754,7 @@ START_TEST(security)
|
|||
test_AccessCheck();
|
||||
test_token_attr();
|
||||
test_GetTokenInformation();
|
||||
test_admin_elevation();
|
||||
test_LookupAccountSid();
|
||||
test_LookupAccountName();
|
||||
test_security_descriptor();
|
||||
|
|
|
@ -704,8 +704,8 @@ BOOL WINAPI DuplicateTokenEx( HANDLE token, DWORD access, LPSECURITY_ATTRIBUTES
|
|||
BOOL WINAPI GetTokenInformation( HANDLE token, TOKEN_INFORMATION_CLASS class,
|
||||
LPVOID info, DWORD len, LPDWORD retlen )
|
||||
{
|
||||
TRACE("(%p, %s, %p, %ld, %p):\n",
|
||||
token,
|
||||
TRACE("(%p, %d [%s], %p, %ld, %p):\n",
|
||||
token, class,
|
||||
(class == TokenUser) ? "TokenUser" :
|
||||
(class == TokenGroups) ? "TokenGroups" :
|
||||
(class == TokenPrivileges) ? "TokenPrivileges" :
|
||||
|
@ -721,6 +721,8 @@ BOOL WINAPI GetTokenInformation( HANDLE token, TOKEN_INFORMATION_CLASS class,
|
|||
(class == TokenGroupsAndPrivileges) ? "TokenGroupsAndPrivileges" :
|
||||
(class == TokenSessionReference) ? "TokenSessionReference" :
|
||||
(class == TokenSandBoxInert) ? "TokenSandBoxInert" :
|
||||
(class == TokenElevation) ? "TokenElevation" :
|
||||
(class == TokenElevationType) ? "TokenElevationType" :
|
||||
"Unknown",
|
||||
info, len, retlen);
|
||||
|
||||
|
|
|
@ -1837,6 +1837,19 @@ NTSTATUS WINAPI NtSetInformationProcess( HANDLE handle, PROCESSINFOCLASS class,
|
|||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
||||
case ProcessWineSetAdminToken:
|
||||
SERVER_START_REQ( create_primary_admin_token )
|
||||
{
|
||||
if (!(ret = wine_server_call( req )))
|
||||
{
|
||||
HANDLE token = wine_server_ptr_handle( reply->token );
|
||||
PROCESS_ACCESS_TOKEN info = { .Token = token, .Thread = NULL };
|
||||
ret = NtSetInformationProcess( handle, ProcessAccessToken, &info, sizeof(info) );
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
||||
case ProcessPowerThrottlingState:
|
||||
FIXME( "ProcessPowerThrottlingState - stub\n" );
|
||||
return STATUS_SUCCESS;
|
||||
|
|
|
@ -516,7 +516,7 @@ NTSTATUS WINAPI NtQueryInformationToken( HANDLE token, TOKEN_INFORMATION_CLASS c
|
|||
|
||||
req->handle = wine_server_obj_handle( token );
|
||||
status = wine_server_call( req );
|
||||
if (!status) *type = reply->elevation;
|
||||
if (!status) *type = reply->elevation_type;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
break;
|
||||
|
@ -528,7 +528,7 @@ NTSTATUS WINAPI NtQueryInformationToken( HANDLE token, TOKEN_INFORMATION_CLASS c
|
|||
|
||||
req->handle = wine_server_obj_handle( token );
|
||||
status = wine_server_call( req );
|
||||
if (!status) elevation->TokenIsElevated = (reply->elevation == TokenElevationTypeFull);
|
||||
if (!status) elevation->TokenIsElevated = reply->is_elevated;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
break;
|
||||
|
|
|
@ -765,8 +765,7 @@ HWND get_desktop_window(void)
|
|||
static const WCHAR system_dir[] = {'C',':','\\','w','i','n','d','o','w','s','\\',
|
||||
's','y','s','t','e','m','3','2','\\',0};
|
||||
RTL_USER_PROCESS_PARAMETERS params = { sizeof(params), sizeof(params) };
|
||||
ULONG_PTR buffer[offsetof( PS_ATTRIBUTE_LIST, Attributes[2] ) / sizeof(ULONG_PTR)];
|
||||
PS_ATTRIBUTE_LIST *ps_attr = (PS_ATTRIBUTE_LIST *)buffer;
|
||||
PS_ATTRIBUTE_LIST ps_attr;
|
||||
PS_CREATE_INFO create_info;
|
||||
WCHAR desktop[MAX_PATH];
|
||||
PEB *peb = NtCurrentTeb()->Peb;
|
||||
|
@ -799,30 +798,24 @@ HWND get_desktop_window(void)
|
|||
RtlInitUnicodeString( ¶ms.WindowTitle, appnameW + 4 );
|
||||
RtlInitUnicodeString( ¶ms.Desktop, desktop );
|
||||
|
||||
ps_attr->Attributes[0].Attribute = PS_ATTRIBUTE_IMAGE_NAME;
|
||||
ps_attr->Attributes[0].Size = sizeof(appnameW) - sizeof(WCHAR);
|
||||
ps_attr->Attributes[0].ValuePtr = (WCHAR *)appnameW;
|
||||
ps_attr->Attributes[0].ReturnLength = NULL;
|
||||
|
||||
ps_attr->Attributes[1].Attribute = PS_ATTRIBUTE_TOKEN;
|
||||
ps_attr->Attributes[1].Size = sizeof(HANDLE);
|
||||
ps_attr->Attributes[1].ValuePtr = GetCurrentThreadEffectiveToken();
|
||||
ps_attr->Attributes[1].ReturnLength = NULL;
|
||||
|
||||
ps_attr->TotalLength = offsetof( PS_ATTRIBUTE_LIST, Attributes[2] );
|
||||
ps_attr.TotalLength = sizeof(ps_attr);
|
||||
ps_attr.Attributes[0].Attribute = PS_ATTRIBUTE_IMAGE_NAME;
|
||||
ps_attr.Attributes[0].Size = sizeof(appnameW) - sizeof(WCHAR);
|
||||
ps_attr.Attributes[0].ValuePtr = (WCHAR *)appnameW;
|
||||
ps_attr.Attributes[0].ReturnLength = NULL;
|
||||
|
||||
if (NtCurrentTeb64() && !NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR])
|
||||
{
|
||||
NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR] = TRUE;
|
||||
status = NtCreateUserProcess( &process, &thread, PROCESS_ALL_ACCESS, THREAD_ALL_ACCESS,
|
||||
NULL, NULL, 0, THREAD_CREATE_FLAGS_CREATE_SUSPENDED, ¶ms,
|
||||
&create_info, ps_attr );
|
||||
&create_info, &ps_attr );
|
||||
NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR] = FALSE;
|
||||
}
|
||||
else
|
||||
status = NtCreateUserProcess( &process, &thread, PROCESS_ALL_ACCESS, THREAD_ALL_ACCESS,
|
||||
NULL, NULL, 0, THREAD_CREATE_FLAGS_CREATE_SUSPENDED, ¶ms,
|
||||
&create_info, ps_attr );
|
||||
&create_info, &ps_attr );
|
||||
if (!status)
|
||||
{
|
||||
NtResumeThread( thread, NULL );
|
||||
|
|
|
@ -872,6 +872,7 @@ NTSTATUS WINAPI wow64_NtSetInformationProcess( UINT *args )
|
|||
case ProcessPagePriority: /* MEMORY_PRIORITY_INFORMATION */
|
||||
case ProcessPowerThrottlingState: /* PROCESS_POWER_THROTTLING_STATE */
|
||||
case ProcessLeapSecondInformation: /* PROCESS_LEAP_SECOND_INFO */
|
||||
case ProcessWineSetAdminToken: /* NULL */
|
||||
return NtSetInformationProcess( handle, class, ptr, len );
|
||||
|
||||
case ProcessAccessToken: /* PROCESS_ACCESS_TOKEN */
|
||||
|
|
|
@ -1897,6 +1897,7 @@ typedef enum _PROCESSINFOCLASS {
|
|||
#ifdef __WINESRC__
|
||||
ProcessWineMakeProcessSystem = 1000,
|
||||
ProcessWineLdtCopy,
|
||||
ProcessWineSetAdminToken,
|
||||
#endif
|
||||
} PROCESSINFOCLASS;
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#define COBJMACROS
|
||||
#define OEMRESOURCE
|
||||
#include <windows.h>
|
||||
#include <winternl.h>
|
||||
#include <rpc.h>
|
||||
#include <shlobj.h>
|
||||
#include <shellapi.h>
|
||||
|
@ -1208,6 +1209,7 @@ void manage_desktop( WCHAR *arg )
|
|||
HMODULE shell32;
|
||||
HANDLE thread;
|
||||
DWORD id;
|
||||
NTSTATUS status;
|
||||
|
||||
/* get the rest of the command line (if any) */
|
||||
while (*p && !is_whitespace(*p)) p++;
|
||||
|
@ -1260,6 +1262,10 @@ void manage_desktop( WCHAR *arg )
|
|||
SetThreadDesktop( desktop );
|
||||
}
|
||||
|
||||
/* the desktop process should always have an admin token */
|
||||
status = NtSetInformationProcess( GetCurrentProcess(), ProcessWineSetAdminToken, NULL, 0 );
|
||||
if (status) WARN( "couldn't set admin token for desktop, error %08lx\n", status );
|
||||
|
||||
/* create the desktop window */
|
||||
hwnd = CreateWindowExW( 0, DESKTOP_CLASS_ATOM, NULL,
|
||||
WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, 0, 0, 0, 0, 0, &guid );
|
||||
|
|
|
@ -1279,6 +1279,13 @@ int __cdecl main(int argc, char *argv[])
|
|||
JOBOBJECT_ASSOCIATE_COMPLETION_PORT port_info;
|
||||
HANDLE started_event, process_monitor_thread;
|
||||
DWORD err;
|
||||
NTSTATUS status;
|
||||
|
||||
/* FIXME: Until we start honoring each service's lpServiceStartName, we want
|
||||
services to inherit a default admin token. */
|
||||
status = NtSetInformationProcess( GetCurrentProcess(), ProcessWineSetAdminToken, NULL, 0 );
|
||||
if (status)
|
||||
WARN( "couldn't set admin token, error %08lx\n", status );
|
||||
|
||||
job_object = CreateJobObjectW(NULL, NULL);
|
||||
job_limit.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_BREAKAWAY_OK | JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK;
|
||||
|
|
|
@ -3305,6 +3305,13 @@ enum caret_state
|
|||
@END
|
||||
|
||||
|
||||
/* Create a new primary admin token with Default elevation. */
|
||||
@REQ(create_primary_admin_token)
|
||||
@REPLY
|
||||
obj_handle_t token; /* handle to the token */
|
||||
@END
|
||||
|
||||
|
||||
/* Open a security token */
|
||||
@REQ(open_token)
|
||||
obj_handle_t handle; /* handle to the thread or process */
|
||||
|
@ -3762,7 +3769,8 @@ typedef union
|
|||
unsigned int session_id; /* token session id */
|
||||
int primary; /* is the token primary or impersonation? */
|
||||
int impersonation_level; /* level of impersonation */
|
||||
int elevation; /* elevation type */
|
||||
int elevation_type; /* elevation type (TokenElevation*) */
|
||||
int is_elevated; /* is the token elevated as per GetTokenInformation(TokenElevation)? */
|
||||
int group_count; /* the number of groups the token is a member of */
|
||||
int privilege_count; /* the number of privileges the token has */
|
||||
@END
|
||||
|
|
|
@ -1209,6 +1209,22 @@ DECL_HANDLER(create_token)
|
|||
}
|
||||
|
||||
|
||||
/* create a new primary admin token with Default elevation */
|
||||
DECL_HANDLER(create_primary_admin_token)
|
||||
{
|
||||
struct token *token = token_create_admin( TRUE, SecurityIdentification,
|
||||
TokenElevationTypeDefault, default_session_id );
|
||||
if (!token)
|
||||
{
|
||||
set_error( STATUS_UNSUCCESSFUL );
|
||||
return;
|
||||
}
|
||||
|
||||
reply->token = alloc_handle( current->process, token, TOKEN_ALL_ACCESS, 0 );
|
||||
release_object( token );
|
||||
}
|
||||
|
||||
|
||||
/* open a security token */
|
||||
DECL_HANDLER(open_token)
|
||||
{
|
||||
|
@ -1538,7 +1554,14 @@ DECL_HANDLER(get_token_info)
|
|||
reply->session_id = token->session_id;
|
||||
reply->primary = token->primary;
|
||||
reply->impersonation_level = token->impersonation_level;
|
||||
reply->elevation = token->elevation;
|
||||
reply->elevation_type = token->elevation;
|
||||
/* Tokens with TokenElevationTypeDefault are considered elevated for the
|
||||
purposes of GetTokenInformation(TokenElevation) if they belong to the
|
||||
admins group. */
|
||||
if (token->elevation == TokenElevationTypeDefault)
|
||||
reply->is_elevated = token_sid_present( token, &builtin_admins_sid, FALSE );
|
||||
else
|
||||
reply->is_elevated = token->elevation == TokenElevationTypeFull;
|
||||
reply->group_count = list_count( &token->groups );
|
||||
reply->privilege_count = list_count( &token->privileges );
|
||||
release_object( token );
|
||||
|
|
Loading…
Reference in a new issue