diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index f3def5e3f74..eed8d10f0b0 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -52,6 +52,7 @@ C_SRCS = \ unix/loader.c \ unix/process.c \ unix/registry.c \ + unix/security.c \ unix/serial.c \ unix/server.c \ unix/signal_arm.c \ diff --git a/dlls/ntdll/misc.c b/dlls/ntdll/misc.c index 4b7bb2296dd..a75188e9816 100644 --- a/dlls/ntdll/misc.c +++ b/dlls/ntdll/misc.c @@ -32,14 +32,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntdll); -LPCSTR debugstr_ObjectAttributes(const OBJECT_ATTRIBUTES *oa) -{ - if (!oa) return ""; - return wine_dbg_sprintf( "{name=%s, attr=0x%08x, hRoot=%p, sd=%p}", - debugstr_us(oa->ObjectName), oa->Attributes, - oa->RootDirectory, oa->SecurityDescriptor ); -} - LPCSTR debugstr_us( const UNICODE_STRING *us ) { if (!us) return ""; @@ -567,18 +559,6 @@ ULONG WINAPIV EtwTraceMessage( TRACEHANDLE handle, ULONG flags, LPGUID guid, /*U return ret; } -NTSTATUS WINAPI NtCreateLowBoxToken(HANDLE *token_handle, HANDLE existing_token_handle, ACCESS_MASK desired_access, - OBJECT_ATTRIBUTES *object_attributes, SID *package_sid, ULONG capability_count, - SID_AND_ATTRIBUTES *capabilities, ULONG handle_count, HANDLE *handle) -{ - FIXME("(%p, %p, %x, %p, %p, %u, %p, %u, %p): stub\n", token_handle, existing_token_handle, desired_access, - object_attributes, package_sid, capability_count, capabilities, handle_count, handle); - - /* We need to return a NULL handle since later it will be passed to CloseHandle and that must not fail */ - *token_handle = NULL; - return STATUS_SUCCESS; -} - /********************************************************************* * ApiSetQueryApiSetPresence (NTDLL.@) */ diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index e42f2ac1750..8375339f578 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -42,637 +42,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntdll); * Token */ -/****************************************************************************** - * NtDuplicateToken [NTDLL.@] - * ZwDuplicateToken [NTDLL.@] - */ -NTSTATUS WINAPI NtDuplicateToken( - IN HANDLE ExistingToken, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, - IN TOKEN_TYPE TokenType, - OUT PHANDLE NewToken) -{ - NTSTATUS status; - data_size_t len; - struct object_attributes *objattr; - - TRACE("(%p,0x%08x,%s,0x%08x,0x%08x,%p)\n", - ExistingToken, DesiredAccess, debugstr_ObjectAttributes(ObjectAttributes), - ImpersonationLevel, TokenType, NewToken); - - if ((status = alloc_object_attributes( ObjectAttributes, &objattr, &len ))) return status; - - if (ObjectAttributes && ObjectAttributes->SecurityQualityOfService) - { - SECURITY_QUALITY_OF_SERVICE *SecurityQOS = ObjectAttributes->SecurityQualityOfService; - TRACE("ObjectAttributes->SecurityQualityOfService = {%d, %d, %d, %s}\n", - SecurityQOS->Length, SecurityQOS->ImpersonationLevel, - SecurityQOS->ContextTrackingMode, - SecurityQOS->EffectiveOnly ? "TRUE" : "FALSE"); - ImpersonationLevel = SecurityQOS->ImpersonationLevel; - } - - SERVER_START_REQ( duplicate_token ) - { - req->handle = wine_server_obj_handle( ExistingToken ); - req->access = DesiredAccess; - req->primary = (TokenType == TokenPrimary); - req->impersonation_level = ImpersonationLevel; - wine_server_add_data( req, objattr, len ); - status = wine_server_call( req ); - if (!status) *NewToken = wine_server_ptr_handle( reply->new_handle ); - } - SERVER_END_REQ; - - RtlFreeHeap( GetProcessHeap(), 0, objattr ); - return status; -} - -/****************************************************************************** - * NtOpenProcessToken [NTDLL.@] - * ZwOpenProcessToken [NTDLL.@] - */ -NTSTATUS WINAPI NtOpenProcessToken( - HANDLE ProcessHandle, - DWORD DesiredAccess, - HANDLE *TokenHandle) -{ - return NtOpenProcessTokenEx( ProcessHandle, DesiredAccess, 0, TokenHandle ); -} - -/****************************************************************************** - * NtOpenProcessTokenEx [NTDLL.@] - * ZwOpenProcessTokenEx [NTDLL.@] - */ -NTSTATUS WINAPI NtOpenProcessTokenEx( HANDLE process, DWORD access, DWORD attributes, - HANDLE *handle ) -{ - NTSTATUS ret; - - TRACE("(%p,0x%08x,0x%08x,%p)\n", process, access, attributes, handle); - - SERVER_START_REQ( open_token ) - { - req->handle = wine_server_obj_handle( process ); - req->access = access; - req->attributes = attributes; - req->flags = 0; - ret = wine_server_call( req ); - if (!ret) *handle = wine_server_ptr_handle( reply->token ); - } - SERVER_END_REQ; - return ret; -} - -/****************************************************************************** - * NtOpenThreadToken [NTDLL.@] - * ZwOpenThreadToken [NTDLL.@] - */ -NTSTATUS WINAPI NtOpenThreadToken( - HANDLE ThreadHandle, - DWORD DesiredAccess, - BOOLEAN OpenAsSelf, - HANDLE *TokenHandle) -{ - return NtOpenThreadTokenEx( ThreadHandle, DesiredAccess, OpenAsSelf, 0, TokenHandle ); -} - -/****************************************************************************** - * NtOpenThreadTokenEx [NTDLL.@] - * ZwOpenThreadTokenEx [NTDLL.@] - */ -NTSTATUS WINAPI NtOpenThreadTokenEx( HANDLE thread, DWORD access, BOOLEAN as_self, DWORD attributes, - HANDLE *handle ) -{ - NTSTATUS ret; - - TRACE("(%p,0x%08x,%u,0x%08x,%p)\n", thread, access, as_self, attributes, handle ); - - SERVER_START_REQ( open_token ) - { - req->handle = wine_server_obj_handle( thread ); - req->access = access; - req->attributes = attributes; - req->flags = OPEN_TOKEN_THREAD; - if (as_self) req->flags |= OPEN_TOKEN_AS_SELF; - ret = wine_server_call( req ); - if (!ret) *handle = wine_server_ptr_handle( reply->token ); - } - SERVER_END_REQ; - - return ret; -} - -/****************************************************************************** - * NtAdjustPrivilegesToken [NTDLL.@] - * ZwAdjustPrivilegesToken [NTDLL.@] - * - * FIXME: parameters unsafe - */ -NTSTATUS WINAPI NtAdjustPrivilegesToken( - IN HANDLE TokenHandle, - IN BOOLEAN DisableAllPrivileges, - IN PTOKEN_PRIVILEGES NewState, - IN DWORD BufferLength, - OUT PTOKEN_PRIVILEGES PreviousState, - OUT PDWORD ReturnLength) -{ - NTSTATUS ret; - - TRACE("(%p,0x%08x,%p,0x%08x,%p,%p)\n", - TokenHandle, DisableAllPrivileges, NewState, BufferLength, PreviousState, ReturnLength); - - SERVER_START_REQ( adjust_token_privileges ) - { - req->handle = wine_server_obj_handle( TokenHandle ); - req->disable_all = DisableAllPrivileges; - req->get_modified_state = (PreviousState != NULL); - if (!DisableAllPrivileges) - { - wine_server_add_data( req, NewState->Privileges, - NewState->PrivilegeCount * sizeof(NewState->Privileges[0]) ); - } - if (PreviousState && BufferLength >= FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges )) - wine_server_set_reply( req, PreviousState->Privileges, - BufferLength - FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) ); - ret = wine_server_call( req ); - if (PreviousState) - { - if (ReturnLength) *ReturnLength = reply->len + FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ); - PreviousState->PrivilegeCount = reply->len / sizeof(LUID_AND_ATTRIBUTES); - } - } - SERVER_END_REQ; - - return ret; -} - -/****************************************************************************** -* NtQueryInformationToken [NTDLL.@] -* ZwQueryInformationToken [NTDLL.@] -* -* NOTES -* Buffer for TokenUser: -* 0x00 TOKEN_USER the PSID field points to the SID -* 0x08 SID -* -*/ -NTSTATUS WINAPI NtQueryInformationToken( - HANDLE token, - TOKEN_INFORMATION_CLASS tokeninfoclass, - PVOID tokeninfo, - ULONG tokeninfolength, - PULONG retlen ) -{ - static const ULONG info_len [] = - { - 0, - 0, /* TokenUser */ - 0, /* TokenGroups */ - 0, /* TokenPrivileges */ - 0, /* TokenOwner */ - 0, /* TokenPrimaryGroup */ - 0, /* TokenDefaultDacl */ - sizeof(TOKEN_SOURCE), /* TokenSource */ - sizeof(TOKEN_TYPE), /* TokenType */ - sizeof(SECURITY_IMPERSONATION_LEVEL), /* TokenImpersonationLevel */ - sizeof(TOKEN_STATISTICS), /* TokenStatistics */ - 0, /* TokenRestrictedSids */ - sizeof(DWORD), /* TokenSessionId */ - 0, /* TokenGroupsAndPrivileges */ - 0, /* TokenSessionReference */ - 0, /* TokenSandBoxInert */ - 0, /* TokenAuditPolicy */ - 0, /* TokenOrigin */ - sizeof(TOKEN_ELEVATION_TYPE), /* TokenElevationType */ - 0, /* TokenLinkedToken */ - sizeof(TOKEN_ELEVATION), /* TokenElevation */ - 0, /* TokenHasRestrictions */ - 0, /* TokenAccessInformation */ - 0, /* TokenVirtualizationAllowed */ - sizeof(DWORD), /* TokenVirtualizationEnabled */ - sizeof(TOKEN_MANDATORY_LABEL) + sizeof(SID), /* TokenIntegrityLevel [sizeof(SID) includes one SubAuthority] */ - 0, /* TokenUIAccess */ - 0, /* TokenMandatoryPolicy */ - 0, /* TokenLogonSid */ - sizeof(DWORD), /* TokenIsAppContainer */ - 0, /* TokenCapabilities */ - sizeof(TOKEN_APPCONTAINER_INFORMATION) + sizeof(SID), /* TokenAppContainerSid */ - 0, /* TokenAppContainerNumber */ - 0, /* TokenUserClaimAttributes*/ - 0, /* TokenDeviceClaimAttributes */ - 0, /* TokenRestrictedUserClaimAttributes */ - 0, /* TokenRestrictedDeviceClaimAttributes */ - 0, /* TokenDeviceGroups */ - 0, /* TokenRestrictedDeviceGroups */ - 0, /* TokenSecurityAttributes */ - 0, /* TokenIsRestricted */ - 0 /* TokenProcessTrustLevel */ - }; - - ULONG len = 0; - NTSTATUS status = STATUS_SUCCESS; - - TRACE("(%p,%d,%p,%d,%p)\n", - token,tokeninfoclass,tokeninfo,tokeninfolength,retlen); - - if (tokeninfoclass < MaxTokenInfoClass) - len = info_len[tokeninfoclass]; - - if (retlen) *retlen = len; - - if (tokeninfolength < len) - return STATUS_BUFFER_TOO_SMALL; - - switch (tokeninfoclass) - { - case TokenUser: - SERVER_START_REQ( get_token_sid ) - { - TOKEN_USER * tuser = tokeninfo; - PSID sid = tuser + 1; - DWORD sid_len = tokeninfolength < sizeof(TOKEN_USER) ? 0 : tokeninfolength - sizeof(TOKEN_USER); - - req->handle = wine_server_obj_handle( token ); - req->which_sid = tokeninfoclass; - wine_server_set_reply( req, sid, sid_len ); - status = wine_server_call( req ); - if (retlen) *retlen = reply->sid_len + sizeof(TOKEN_USER); - if (status == STATUS_SUCCESS) - { - tuser->User.Sid = sid; - tuser->User.Attributes = 0; - } - } - SERVER_END_REQ; - break; - case TokenGroups: - { - void *buffer; - - /* reply buffer is always shorter than output one */ - buffer = tokeninfolength ? RtlAllocateHeap(GetProcessHeap(), 0, tokeninfolength) : NULL; - - SERVER_START_REQ( get_token_groups ) - { - TOKEN_GROUPS *groups = tokeninfo; - - req->handle = wine_server_obj_handle( token ); - wine_server_set_reply( req, buffer, tokeninfolength ); - status = wine_server_call( req ); - if (status == STATUS_BUFFER_TOO_SMALL) - { - if (retlen) *retlen = reply->user_len; - } - else if (status == STATUS_SUCCESS) - { - struct token_groups *tg = buffer; - unsigned int *attr = (unsigned int *)(tg + 1); - ULONG i; - const int non_sid_portion = (sizeof(struct token_groups) + tg->count * sizeof(unsigned int)); - SID *sids = (SID *)((char *)tokeninfo + FIELD_OFFSET( TOKEN_GROUPS, Groups[tg->count] )); - - if (retlen) *retlen = reply->user_len; - - groups->GroupCount = tg->count; - memcpy( sids, (char *)buffer + non_sid_portion, - reply->user_len - FIELD_OFFSET( TOKEN_GROUPS, Groups[tg->count] )); - - for (i = 0; i < tg->count; i++) - { - groups->Groups[i].Attributes = attr[i]; - groups->Groups[i].Sid = sids; - sids = (SID *)((char *)sids + RtlLengthSid(sids)); - } - } - else if (retlen) *retlen = 0; - } - SERVER_END_REQ; - - RtlFreeHeap(GetProcessHeap(), 0, buffer); - break; - } - case TokenPrimaryGroup: - SERVER_START_REQ( get_token_sid ) - { - TOKEN_PRIMARY_GROUP *tgroup = tokeninfo; - PSID sid = tgroup + 1; - DWORD sid_len = tokeninfolength < sizeof(TOKEN_PRIMARY_GROUP) ? 0 : tokeninfolength - sizeof(TOKEN_PRIMARY_GROUP); - - req->handle = wine_server_obj_handle( token ); - req->which_sid = tokeninfoclass; - wine_server_set_reply( req, sid, sid_len ); - status = wine_server_call( req ); - if (retlen) *retlen = reply->sid_len + sizeof(TOKEN_PRIMARY_GROUP); - if (status == STATUS_SUCCESS) - tgroup->PrimaryGroup = sid; - } - SERVER_END_REQ; - break; - case TokenPrivileges: - SERVER_START_REQ( get_token_privileges ) - { - TOKEN_PRIVILEGES *tpriv = tokeninfo; - req->handle = wine_server_obj_handle( token ); - if (tpriv && tokeninfolength > FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges )) - wine_server_set_reply( req, tpriv->Privileges, tokeninfolength - FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) ); - status = wine_server_call( req ); - if (retlen) *retlen = FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) + reply->len; - if (tpriv) tpriv->PrivilegeCount = reply->len / sizeof(LUID_AND_ATTRIBUTES); - } - SERVER_END_REQ; - break; - case TokenOwner: - SERVER_START_REQ( get_token_sid ) - { - TOKEN_OWNER *towner = tokeninfo; - PSID sid = towner + 1; - DWORD sid_len = tokeninfolength < sizeof(TOKEN_OWNER) ? 0 : tokeninfolength - sizeof(TOKEN_OWNER); - - req->handle = wine_server_obj_handle( token ); - req->which_sid = tokeninfoclass; - wine_server_set_reply( req, sid, sid_len ); - status = wine_server_call( req ); - if (retlen) *retlen = reply->sid_len + sizeof(TOKEN_OWNER); - if (status == STATUS_SUCCESS) - towner->Owner = sid; - } - SERVER_END_REQ; - break; - case TokenImpersonationLevel: - SERVER_START_REQ( get_token_impersonation_level ) - { - SECURITY_IMPERSONATION_LEVEL *impersonation_level = tokeninfo; - req->handle = wine_server_obj_handle( token ); - status = wine_server_call( req ); - if (status == STATUS_SUCCESS) - *impersonation_level = reply->impersonation_level; - } - SERVER_END_REQ; - break; - case TokenStatistics: - SERVER_START_REQ( get_token_statistics ) - { - TOKEN_STATISTICS *statistics = tokeninfo; - req->handle = wine_server_obj_handle( token ); - status = wine_server_call( req ); - if (status == STATUS_SUCCESS) - { - statistics->TokenId.LowPart = reply->token_id.low_part; - statistics->TokenId.HighPart = reply->token_id.high_part; - statistics->AuthenticationId.LowPart = 0; /* FIXME */ - statistics->AuthenticationId.HighPart = 0; /* FIXME */ - statistics->ExpirationTime.u.HighPart = 0x7fffffff; - statistics->ExpirationTime.u.LowPart = 0xffffffff; - statistics->TokenType = reply->primary ? TokenPrimary : TokenImpersonation; - statistics->ImpersonationLevel = reply->impersonation_level; - - /* kernel information not relevant to us */ - statistics->DynamicCharged = 0; - statistics->DynamicAvailable = 0; - - statistics->GroupCount = reply->group_count; - statistics->PrivilegeCount = reply->privilege_count; - statistics->ModifiedId.LowPart = reply->modified_id.low_part; - statistics->ModifiedId.HighPart = reply->modified_id.high_part; - } - } - SERVER_END_REQ; - break; - case TokenType: - SERVER_START_REQ( get_token_statistics ) - { - TOKEN_TYPE *token_type = tokeninfo; - req->handle = wine_server_obj_handle( token ); - status = wine_server_call( req ); - if (status == STATUS_SUCCESS) - *token_type = reply->primary ? TokenPrimary : TokenImpersonation; - } - SERVER_END_REQ; - break; - case TokenDefaultDacl: - SERVER_START_REQ( get_token_default_dacl ) - { - TOKEN_DEFAULT_DACL *default_dacl = tokeninfo; - ACL *acl = (ACL *)(default_dacl + 1); - DWORD acl_len; - - if (tokeninfolength < sizeof(TOKEN_DEFAULT_DACL)) acl_len = 0; - else acl_len = tokeninfolength - sizeof(TOKEN_DEFAULT_DACL); - - req->handle = wine_server_obj_handle( token ); - wine_server_set_reply( req, acl, acl_len ); - status = wine_server_call( req ); - - if (retlen) *retlen = reply->acl_len + sizeof(TOKEN_DEFAULT_DACL); - if (status == STATUS_SUCCESS) - { - if (reply->acl_len) - default_dacl->DefaultDacl = acl; - else - default_dacl->DefaultDacl = NULL; - } - } - SERVER_END_REQ; - break; - case TokenElevationType: - { - TOKEN_ELEVATION_TYPE *elevation_type = tokeninfo; - FIXME("QueryInformationToken( ..., TokenElevationType, ...) semi-stub\n"); - *elevation_type = TokenElevationTypeFull; - } - break; - case TokenElevation: - { - TOKEN_ELEVATION *elevation = tokeninfo; - FIXME("QueryInformationToken( ..., TokenElevation, ...) semi-stub\n"); - elevation->TokenIsElevated = TRUE; - } - break; - case TokenSessionId: - { - *((DWORD*)tokeninfo) = 0; - FIXME("QueryInformationToken( ..., TokenSessionId, ...) semi-stub\n"); - } - break; - case TokenVirtualizationEnabled: - { - *(DWORD *)tokeninfo = 0; - TRACE("QueryInformationToken( ..., TokenVirtualizationEnabled, ...) semi-stub\n"); - } - break; - case TokenIntegrityLevel: - { - /* report always "S-1-16-12288" (high mandatory level) for now */ - static const SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, - {SECURITY_MANDATORY_HIGH_RID}}; - - TOKEN_MANDATORY_LABEL *tml = tokeninfo; - PSID psid = tml + 1; - - tml->Label.Sid = psid; - tml->Label.Attributes = SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED; - memcpy(psid, &high_level, sizeof(SID)); - } - break; - case TokenAppContainerSid: - { - TOKEN_APPCONTAINER_INFORMATION *container = tokeninfo; - FIXME("QueryInformationToken( ..., TokenAppContainerSid, ...) semi-stub\n"); - container->TokenAppContainer = NULL; - } - break; - case TokenIsAppContainer: - { - TRACE("TokenIsAppContainer semi-stub\n"); - *(DWORD*)tokeninfo = 0; - break; - } - case TokenLogonSid: - SERVER_START_REQ( get_token_sid ) - { - TOKEN_GROUPS * groups = tokeninfo; - PSID sid = groups + 1; - DWORD sid_len = tokeninfolength < sizeof(TOKEN_GROUPS) ? 0 : tokeninfolength - sizeof(TOKEN_GROUPS); - - req->handle = wine_server_obj_handle( token ); - req->which_sid = tokeninfoclass; - wine_server_set_reply( req, sid, sid_len ); - status = wine_server_call( req ); - if (retlen) *retlen = reply->sid_len + sizeof(TOKEN_GROUPS); - if (status == STATUS_SUCCESS) - { - groups->GroupCount = 1; - groups->Groups[0].Sid = sid; - groups->Groups[0].Attributes = 0; - } - } - SERVER_END_REQ; - break; - default: - { - ERR("Unhandled Token Information class %d!\n", tokeninfoclass); - return STATUS_NOT_IMPLEMENTED; - } - } - return status; -} - -/****************************************************************************** -* NtSetInformationToken [NTDLL.@] -* ZwSetInformationToken [NTDLL.@] -*/ -NTSTATUS WINAPI NtSetInformationToken( - HANDLE TokenHandle, - TOKEN_INFORMATION_CLASS TokenInformationClass, - PVOID TokenInformation, - ULONG TokenInformationLength) -{ - NTSTATUS ret = STATUS_NOT_IMPLEMENTED; - - TRACE("%p %d %p %u\n", TokenHandle, TokenInformationClass, - TokenInformation, TokenInformationLength); - - switch (TokenInformationClass) - { - case TokenDefaultDacl: - if (TokenInformationLength < sizeof(TOKEN_DEFAULT_DACL)) - { - ret = STATUS_INFO_LENGTH_MISMATCH; - break; - } - if (!TokenInformation) - { - ret = STATUS_ACCESS_VIOLATION; - break; - } - SERVER_START_REQ( set_token_default_dacl ) - { - ACL *acl = ((TOKEN_DEFAULT_DACL *)TokenInformation)->DefaultDacl; - WORD size; - - if (acl) size = acl->AclSize; - else size = 0; - - req->handle = wine_server_obj_handle( TokenHandle ); - wine_server_add_data( req, acl, size ); - ret = wine_server_call( req ); - } - SERVER_END_REQ; - break; - case TokenSessionId: - if (TokenInformationLength < sizeof(DWORD)) - { - ret = STATUS_INFO_LENGTH_MISMATCH; - break; - } - if (!TokenInformation) - { - ret = STATUS_ACCESS_VIOLATION; - break; - } - FIXME("TokenSessionId stub!\n"); - ret = STATUS_SUCCESS; - break; - case TokenIntegrityLevel: - FIXME("TokenIntegrityLevel stub!\n"); - ret = STATUS_SUCCESS; - break; - default: - FIXME("unimplemented class %u\n", TokenInformationClass); - break; - } - - return ret; -} - -/****************************************************************************** -* NtAdjustGroupsToken [NTDLL.@] -* ZwAdjustGroupsToken [NTDLL.@] -*/ -NTSTATUS WINAPI NtAdjustGroupsToken( - HANDLE TokenHandle, - BOOLEAN ResetToDefault, - PTOKEN_GROUPS NewState, - ULONG BufferLength, - PTOKEN_GROUPS PreviousState, - PULONG ReturnLength) -{ - FIXME("%p %d %p %u %p %p\n", TokenHandle, ResetToDefault, - NewState, BufferLength, PreviousState, ReturnLength); - return STATUS_NOT_IMPLEMENTED; -} - -/****************************************************************************** -* NtPrivilegeCheck [NTDLL.@] -* ZwPrivilegeCheck [NTDLL.@] -*/ -NTSTATUS WINAPI NtPrivilegeCheck( - HANDLE ClientToken, - PPRIVILEGE_SET RequiredPrivileges, - PBOOLEAN Result) -{ - NTSTATUS status; - SERVER_START_REQ( check_token_privileges ) - { - req->handle = wine_server_obj_handle( ClientToken ); - req->all_required = (RequiredPrivileges->Control & PRIVILEGE_SET_ALL_NECESSARY) != 0; - wine_server_add_data( req, RequiredPrivileges->Privilege, - RequiredPrivileges->PrivilegeCount * sizeof(RequiredPrivileges->Privilege[0]) ); - wine_server_set_reply( req, RequiredPrivileges->Privilege, - RequiredPrivileges->PrivilegeCount * sizeof(RequiredPrivileges->Privilege[0]) ); - - status = wine_server_call( req ); - - if (status == STATUS_SUCCESS) - *Result = reply->has_privileges != 0; - } - SERVER_END_REQ; - return status; -} - /* * Misc */ diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index eeac81cacae..8c46da8e022 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -133,8 +133,8 @@ # @ stub NtAccessCheckByTypeResultListAndAuditAlarmByHandle @ stdcall -syscall NtAddAtom(ptr long ptr) # @ stub NtAddBootEntry -@ stdcall NtAdjustGroupsToken(long long ptr long ptr ptr) -@ stdcall NtAdjustPrivilegesToken(long long ptr long ptr ptr) +@ stdcall -syscall NtAdjustGroupsToken(long long ptr long ptr ptr) +@ stdcall -syscall NtAdjustPrivilegesToken(long long ptr long ptr ptr) @ stdcall -syscall NtAlertResumeThread(long ptr) @ stdcall -syscall NtAlertThread(long) @ stdcall NtAllocateLocallyUniqueId(ptr) @@ -169,7 +169,7 @@ @ stdcall -syscall NtCreateKey(ptr long ptr long ptr long ptr) @ stdcall -syscall NtCreateKeyTransacted(ptr long ptr long ptr long long ptr) @ stdcall -syscall NtCreateKeyedEvent(ptr long ptr long) -@ stdcall NtCreateLowBoxToken(ptr long long ptr ptr long ptr long ptr) +@ stdcall -syscall NtCreateLowBoxToken(ptr long long ptr ptr long ptr long ptr) @ stdcall -syscall NtCreateMailslotFile(ptr long ptr ptr long long long ptr) @ stdcall -syscall NtCreateMutant(ptr long ptr long) @ stdcall -syscall NtCreateNamedPipeFile(ptr long ptr ptr long long long long long long long long long ptr) @@ -201,7 +201,7 @@ @ stdcall -syscall NtDeviceIoControlFile(long long ptr ptr ptr long ptr long ptr long) @ stdcall NtDisplayString(ptr) @ stdcall -syscall NtDuplicateObject(long long long ptr long long long) -@ stdcall NtDuplicateToken(long long ptr long long ptr) +@ stdcall -syscall NtDuplicateToken(long long ptr long long ptr) # @ stub NtEnumerateBootEntries @ stub NtEnumerateBus @ stdcall -syscall NtEnumerateKey(long long long ptr long ptr) @@ -226,7 +226,7 @@ @ stub NtGetPlugPlayEvent @ stdcall NtGetTickCount() @ stdcall -syscall NtGetWriteWatch(long long ptr long ptr ptr ptr) -@ stdcall NtImpersonateAnonymousToken(long) +@ stdcall -syscall NtImpersonateAnonymousToken(long) @ stub NtImpersonateClientOfPort @ stub NtImpersonateThread @ stub NtInitializeRegistry @@ -264,18 +264,18 @@ @ stdcall -syscall NtOpenMutant(ptr long ptr) @ stub NtOpenObjectAuditAlarm @ stdcall -syscall NtOpenProcess(ptr long ptr ptr) -@ stdcall NtOpenProcessToken(long long ptr) -@ stdcall NtOpenProcessTokenEx(long long long ptr) +@ stdcall -syscall NtOpenProcessToken(long long ptr) +@ stdcall -syscall NtOpenProcessTokenEx(long long long ptr) @ stdcall -syscall NtOpenSection(ptr long ptr) @ stdcall -syscall NtOpenSemaphore(ptr long ptr) @ stdcall -syscall NtOpenSymbolicLinkObject (ptr long ptr) @ stdcall -syscall NtOpenThread(ptr long ptr ptr) -@ stdcall NtOpenThreadToken(long long long ptr) -@ stdcall NtOpenThreadTokenEx(long long long long ptr) +@ stdcall -syscall NtOpenThreadToken(long long long ptr) +@ stdcall -syscall NtOpenThreadTokenEx(long long long long ptr) @ stdcall -syscall NtOpenTimer(ptr long ptr) @ stub NtPlugPlayControl @ stdcall -syscall NtPowerInformation(long ptr long ptr long) -@ stdcall NtPrivilegeCheck(ptr ptr ptr) +@ stdcall -syscall NtPrivilegeCheck(ptr ptr ptr) @ stub NtPrivilegeObjectAuditAlarm @ stub NtPrivilegedServiceAuditAlarm @ stdcall -syscall NtProtectVirtualMemory(long ptr ptr long ptr) @@ -297,7 +297,7 @@ @ stub NtQueryInformationPort @ stdcall -syscall NtQueryInformationProcess(long long ptr long ptr) @ stdcall -syscall NtQueryInformationThread(long long ptr long ptr) -@ stdcall NtQueryInformationToken(long long ptr long ptr) +@ stdcall -syscall NtQueryInformationToken(long long ptr long ptr) @ stdcall NtQueryInstallUILanguage(ptr) @ stub NtQueryIntervalProfile @ stdcall -syscall NtQueryIoCompletion(long long ptr long ptr) @@ -379,7 +379,7 @@ @ stdcall -syscall NtSetInformationObject(long long ptr long) @ stdcall -syscall NtSetInformationProcess(long long ptr long) @ stdcall -syscall NtSetInformationThread(long long ptr long) -@ stdcall NtSetInformationToken(long long ptr long) +@ stdcall -syscall NtSetInformationToken(long long ptr long) @ stdcall -syscall NtSetIntervalProfile(long long) @ stdcall -syscall NtSetIoCompletion(ptr long long long long) @ stdcall -syscall NtSetLdtEntries(long int64 long int64) @@ -1122,8 +1122,8 @@ # @ stub ZwAccessCheckByTypeResultListAndAuditAlarmByHandle @ stdcall -private -syscall ZwAddAtom(ptr long ptr) NtAddAtom # @ stub ZwAddBootEntry -@ stdcall -private ZwAdjustGroupsToken(long long ptr long ptr ptr) NtAdjustGroupsToken -@ stdcall -private ZwAdjustPrivilegesToken(long long ptr long ptr ptr) NtAdjustPrivilegesToken +@ stdcall -private -syscall ZwAdjustGroupsToken(long long ptr long ptr ptr) NtAdjustGroupsToken +@ stdcall -private -syscall ZwAdjustPrivilegesToken(long long ptr long ptr ptr) NtAdjustPrivilegesToken @ stdcall -private -syscall ZwAlertResumeThread(long ptr) NtAlertResumeThread @ stdcall -private -syscall ZwAlertThread(long) NtAlertThread @ stdcall -private ZwAllocateLocallyUniqueId(ptr) NtAllocateLocallyUniqueId @@ -1158,6 +1158,7 @@ @ stdcall -private -syscall ZwCreateKey(ptr long ptr long ptr long ptr) NtCreateKey @ stdcall -private -syscall ZwCreateKeyTransacted(ptr long ptr long ptr long long ptr) NtCreateKeyTransacted @ stdcall -private -syscall ZwCreateKeyedEvent(ptr long ptr long) NtCreateKeyedEvent +@ stdcall -private -syscall ZwCreateLowBoxToken(ptr long long ptr ptr long ptr long ptr) NtCreateLowBoxToken @ stdcall -private -syscall ZwCreateMailslotFile(ptr long ptr ptr long long long ptr) NtCreateMailslotFile @ stdcall -private -syscall ZwCreateMutant(ptr long ptr long) NtCreateMutant @ stdcall -private -syscall ZwCreateNamedPipeFile(ptr long ptr ptr long long long long long long long long long ptr) NtCreateNamedPipeFile @@ -1188,7 +1189,7 @@ @ stdcall -private -syscall ZwDeviceIoControlFile(long long ptr ptr ptr long ptr long ptr long) NtDeviceIoControlFile @ stdcall -private ZwDisplayString(ptr) NtDisplayString @ stdcall -private -syscall ZwDuplicateObject(long long long ptr long long long) NtDuplicateObject -@ stdcall -private ZwDuplicateToken(long long ptr long long ptr) NtDuplicateToken +@ stdcall -private -syscall ZwDuplicateToken(long long ptr long long ptr) NtDuplicateToken # @ stub ZwEnumerateBootEntries @ stub ZwEnumerateBus @ stdcall -private -syscall ZwEnumerateKey(long long long ptr long ptr) NtEnumerateKey @@ -1213,7 +1214,7 @@ @ stub ZwGetPlugPlayEvent @ stdcall -private ZwGetTickCount() NtGetTickCount @ stdcall -private -syscall ZwGetWriteWatch(long long ptr long ptr ptr ptr) NtGetWriteWatch -@ stdcall -private ZwImpersonateAnonymousToken(long) NtImpersonateAnonymousToken +@ stdcall -private -syscall ZwImpersonateAnonymousToken(long) NtImpersonateAnonymousToken @ stub ZwImpersonateClientOfPort @ stub ZwImpersonateThread @ stub ZwInitializeRegistry @@ -1251,18 +1252,18 @@ @ stdcall -private -syscall ZwOpenMutant(ptr long ptr) NtOpenMutant @ stub ZwOpenObjectAuditAlarm @ stdcall -private -syscall ZwOpenProcess(ptr long ptr ptr) NtOpenProcess -@ stdcall -private ZwOpenProcessToken(long long ptr) NtOpenProcessToken -@ stdcall -private ZwOpenProcessTokenEx(long long long ptr) NtOpenProcessTokenEx +@ stdcall -private -syscall ZwOpenProcessToken(long long ptr) NtOpenProcessToken +@ stdcall -private -syscall ZwOpenProcessTokenEx(long long long ptr) NtOpenProcessTokenEx @ stdcall -private -syscall ZwOpenSection(ptr long ptr) NtOpenSection @ stdcall -private -syscall ZwOpenSemaphore(ptr long ptr) NtOpenSemaphore @ stdcall -private -syscall ZwOpenSymbolicLinkObject (ptr long ptr) NtOpenSymbolicLinkObject @ stdcall -private -syscall ZwOpenThread(ptr long ptr ptr) NtOpenThread -@ stdcall -private ZwOpenThreadToken(long long long ptr) NtOpenThreadToken -@ stdcall -private ZwOpenThreadTokenEx(long long long long ptr) NtOpenThreadTokenEx +@ stdcall -private -syscall ZwOpenThreadToken(long long long ptr) NtOpenThreadToken +@ stdcall -private -syscall ZwOpenThreadTokenEx(long long long long ptr) NtOpenThreadTokenEx @ stdcall -private -syscall ZwOpenTimer(ptr long ptr) NtOpenTimer @ stub ZwPlugPlayControl @ stdcall -private -syscall ZwPowerInformation(long ptr long ptr long) NtPowerInformation -@ stdcall -private ZwPrivilegeCheck(ptr ptr ptr) NtPrivilegeCheck +@ stdcall -private -syscall ZwPrivilegeCheck(ptr ptr ptr) NtPrivilegeCheck @ stub ZwPrivilegeObjectAuditAlarm @ stub ZwPrivilegedServiceAuditAlarm @ stdcall -private -syscall ZwProtectVirtualMemory(long ptr ptr long ptr) NtProtectVirtualMemory @@ -1284,7 +1285,7 @@ @ stub ZwQueryInformationPort @ stdcall -private -syscall ZwQueryInformationProcess(long long ptr long ptr) NtQueryInformationProcess @ stdcall -private -syscall ZwQueryInformationThread(long long ptr long ptr) NtQueryInformationThread -@ stdcall -private ZwQueryInformationToken(long long ptr long ptr) NtQueryInformationToken +@ stdcall -private -syscall ZwQueryInformationToken(long long ptr long ptr) NtQueryInformationToken @ stdcall -private ZwQueryInstallUILanguage(ptr) NtQueryInstallUILanguage @ stub ZwQueryIntervalProfile @ stdcall -private -syscall ZwQueryIoCompletion(long long ptr long ptr) NtQueryIoCompletion @@ -1366,7 +1367,7 @@ @ stdcall -private -syscall ZwSetInformationObject(long long ptr long) NtSetInformationObject @ stdcall -private -syscall ZwSetInformationProcess(long long ptr long) NtSetInformationProcess @ stdcall -private -syscall ZwSetInformationThread(long long ptr long) NtSetInformationThread -@ stdcall -private ZwSetInformationToken(long long ptr long) NtSetInformationToken +@ stdcall -private -syscall ZwSetInformationToken(long long ptr long) NtSetInformationToken @ stdcall -private -syscall ZwSetIntervalProfile(long long) NtSetIntervalProfile @ stdcall -private -syscall ZwSetIoCompletion(ptr long long long long) NtSetIoCompletion @ stdcall -private -syscall ZwSetLdtEntries(long int64 long int64) NtSetLdtEntries diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 8ff6e3731ed..1f27cd100a7 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -57,7 +57,6 @@ extern RUNTIME_FUNCTION *lookup_function_info( ULONG_PTR pc, ULONG_PTR *base, LD /* debug helpers */ extern LPCSTR debugstr_us( const UNICODE_STRING *str ) DECLSPEC_HIDDEN; -extern LPCSTR debugstr_ObjectAttributes(const OBJECT_ATTRIBUTES *oa) DECLSPEC_HIDDEN; /* init routines */ extern void version_init(void) DECLSPEC_HIDDEN; @@ -71,8 +70,6 @@ extern NTSTATUS restart_process( RTL_USER_PROCESS_PARAMETERS *params, NTSTATUS s /* server support */ extern BOOL is_wow64 DECLSPEC_HIDDEN; -extern NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret, - data_size_t *ret_len ) DECLSPEC_HIDDEN; /* module handling */ extern LIST_ENTRY tls_links DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/sec.c b/dlls/ntdll/sec.c index 5876e06c5b5..fdb0ccb6265 100644 --- a/dlls/ntdll/sec.c +++ b/dlls/ntdll/sec.c @@ -1603,16 +1603,6 @@ RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel) return Status; } -/****************************************************************************** - * NtImpersonateAnonymousToken [NTDLL.@] - */ -NTSTATUS WINAPI -NtImpersonateAnonymousToken(HANDLE thread) -{ - FIXME("(%p): stub\n", thread); - return STATUS_NOT_IMPLEMENTED; -} - /****************************************************************************** * NtAccessCheck [NTDLL.@] * ZwAccessCheck [NTDLL.@] diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index 8aa36c75eb5..edbdd91c1b9 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -37,89 +37,6 @@ #include "wine/debug.h" #include "ntdll_misc.h" -/* creates a struct security_descriptor and contained information in one contiguous piece of memory */ -NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret, - data_size_t *ret_len ) -{ - unsigned int len = sizeof(**ret); - PSID owner = NULL, group = NULL; - ACL *dacl, *sacl; - BOOLEAN dacl_present, sacl_present, defaulted; - PSECURITY_DESCRIPTOR sd; - NTSTATUS status; - - *ret = NULL; - *ret_len = 0; - - if (!attr) return STATUS_SUCCESS; - - if (attr->Length != sizeof(*attr)) return STATUS_INVALID_PARAMETER; - - if ((sd = attr->SecurityDescriptor)) - { - len += sizeof(struct security_descriptor); - - if ((status = RtlGetOwnerSecurityDescriptor( sd, &owner, &defaulted ))) return status; - if ((status = RtlGetGroupSecurityDescriptor( sd, &group, &defaulted ))) return status; - if ((status = RtlGetSaclSecurityDescriptor( sd, &sacl_present, &sacl, &defaulted ))) return status; - if ((status = RtlGetDaclSecurityDescriptor( sd, &dacl_present, &dacl, &defaulted ))) return status; - if (owner) len += RtlLengthSid( owner ); - if (group) len += RtlLengthSid( group ); - if (sacl_present && sacl) len += sacl->AclSize; - if (dacl_present && dacl) len += dacl->AclSize; - - /* fix alignment for the Unicode name that follows the structure */ - len = (len + sizeof(WCHAR) - 1) & ~(sizeof(WCHAR) - 1); - } - - if (attr->ObjectName) - { - if (attr->ObjectName->Length & (sizeof(WCHAR) - 1)) return STATUS_OBJECT_NAME_INVALID; - len += attr->ObjectName->Length; - } - else if (attr->RootDirectory) return STATUS_OBJECT_NAME_INVALID; - - len = (len + 3) & ~3; /* DWORD-align the entire structure */ - - *ret = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, len ); - if (!*ret) return STATUS_NO_MEMORY; - - (*ret)->rootdir = wine_server_obj_handle( attr->RootDirectory ); - (*ret)->attributes = attr->Attributes; - - if (attr->SecurityDescriptor) - { - struct security_descriptor *descr = (struct security_descriptor *)(*ret + 1); - unsigned char *ptr = (unsigned char *)(descr + 1); - - descr->control = ((SECURITY_DESCRIPTOR *)sd)->Control & ~SE_SELF_RELATIVE; - if (owner) descr->owner_len = RtlLengthSid( owner ); - if (group) descr->group_len = RtlLengthSid( group ); - if (sacl_present && sacl) descr->sacl_len = sacl->AclSize; - if (dacl_present && dacl) descr->dacl_len = dacl->AclSize; - - memcpy( ptr, owner, descr->owner_len ); - ptr += descr->owner_len; - memcpy( ptr, group, descr->group_len ); - ptr += descr->group_len; - memcpy( ptr, sacl, descr->sacl_len ); - ptr += descr->sacl_len; - memcpy( ptr, dacl, descr->dacl_len ); - (*ret)->sd_len = (sizeof(*descr) + descr->owner_len + descr->group_len + descr->sacl_len + - descr->dacl_len + sizeof(WCHAR) - 1) & ~(sizeof(WCHAR) - 1); - } - - if (attr->ObjectName) - { - unsigned char *ptr = (unsigned char *)(*ret + 1) + (*ret)->sd_len; - (*ret)->name_len = attr->ObjectName->Length; - memcpy( ptr, attr->ObjectName->Buffer, (*ret)->name_len ); - } - - *ret_len = len; - return STATUS_SUCCESS; -} - /****************************************************************** * RtlRunOnceInitialize (NTDLL.@) diff --git a/dlls/ntdll/unix/security.c b/dlls/ntdll/unix/security.c new file mode 100644 index 00000000000..e8eff25c758 --- /dev/null +++ b/dlls/ntdll/unix/security.c @@ -0,0 +1,635 @@ +/* + * Security functions + * + * Copyright 1996-1998 Marcus Meissner + * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep unix +#endif + +#include +#include +#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "unix_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ntdll); + + +/*********************************************************************** + * NtOpenProcessToken (NTDLL.@) + */ +NTSTATUS WINAPI NtOpenProcessToken( HANDLE process, DWORD access, HANDLE *handle ) +{ + return NtOpenProcessTokenEx( process, access, 0, handle ); +} + + +/*********************************************************************** + * NtOpenProcessTokenEx (NTDLL.@) + */ +NTSTATUS WINAPI NtOpenProcessTokenEx( HANDLE process, DWORD access, DWORD attributes, HANDLE *handle ) +{ + NTSTATUS ret; + + TRACE( "(%p,0x%08x,0x%08x,%p)\n", process, access, attributes, handle ); + + SERVER_START_REQ( open_token ) + { + req->handle = wine_server_obj_handle( process ); + req->access = access; + req->attributes = attributes; + req->flags = 0; + ret = wine_server_call( req ); + if (!ret) *handle = wine_server_ptr_handle( reply->token ); + } + SERVER_END_REQ; + return ret; +} + + +/*********************************************************************** + * NtOpenThreadToken (NTDLL.@) + */ +NTSTATUS WINAPI NtOpenThreadToken( HANDLE thread, DWORD access, BOOLEAN self, HANDLE *handle ) +{ + return NtOpenThreadTokenEx( thread, access, self, 0, handle ); +} + + +/*********************************************************************** + * NtOpenThreadTokenEx (NTDLL.@) + */ +NTSTATUS WINAPI NtOpenThreadTokenEx( HANDLE thread, DWORD access, BOOLEAN self, DWORD attributes, + HANDLE *handle ) +{ + NTSTATUS ret; + + TRACE( "(%p,0x%08x,%u,0x%08x,%p)\n", thread, access, self, attributes, handle ); + + SERVER_START_REQ( open_token ) + { + req->handle = wine_server_obj_handle( thread ); + req->access = access; + req->attributes = attributes; + req->flags = OPEN_TOKEN_THREAD; + if (self) req->flags |= OPEN_TOKEN_AS_SELF; + ret = wine_server_call( req ); + if (!ret) *handle = wine_server_ptr_handle( reply->token ); + } + SERVER_END_REQ; + return ret; +} + + +/*********************************************************************** + * NtDuplicateToken (NTDLL.@) + */ +NTSTATUS WINAPI NtDuplicateToken( HANDLE token, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, + SECURITY_IMPERSONATION_LEVEL level, TOKEN_TYPE type, HANDLE *handle ) +{ + NTSTATUS status; + data_size_t len; + struct object_attributes *objattr; + + if ((status = alloc_object_attributes( attr, &objattr, &len ))) return status; + + if (attr && attr->SecurityQualityOfService) + { + SECURITY_QUALITY_OF_SERVICE *qos = attr->SecurityQualityOfService; + TRACE( "ObjectAttributes->SecurityQualityOfService = {%d, %d, %d, %s}\n", + qos->Length, qos->ImpersonationLevel, qos->ContextTrackingMode, + qos->EffectiveOnly ? "TRUE" : "FALSE"); + level = qos->ImpersonationLevel; + } + + SERVER_START_REQ( duplicate_token ) + { + req->handle = wine_server_obj_handle( token ); + req->access = access; + req->primary = (type == TokenPrimary); + req->impersonation_level = level; + wine_server_add_data( req, objattr, len ); + status = wine_server_call( req ); + if (!status) *handle = wine_server_ptr_handle( reply->new_handle ); + } + SERVER_END_REQ; + free( objattr ); + return status; +} + + +/*********************************************************************** + * NtQueryInformationToken (NTDLL.@) + */ +NTSTATUS WINAPI NtQueryInformationToken( HANDLE token, TOKEN_INFORMATION_CLASS class, + void *info, ULONG length, ULONG *retlen ) +{ + static const ULONG info_len [] = + { + 0, + 0, /* TokenUser */ + 0, /* TokenGroups */ + 0, /* TokenPrivileges */ + 0, /* TokenOwner */ + 0, /* TokenPrimaryGroup */ + 0, /* TokenDefaultDacl */ + sizeof(TOKEN_SOURCE), /* TokenSource */ + sizeof(TOKEN_TYPE), /* TokenType */ + sizeof(SECURITY_IMPERSONATION_LEVEL), /* TokenImpersonationLevel */ + sizeof(TOKEN_STATISTICS), /* TokenStatistics */ + 0, /* TokenRestrictedSids */ + sizeof(DWORD), /* TokenSessionId */ + 0, /* TokenGroupsAndPrivileges */ + 0, /* TokenSessionReference */ + 0, /* TokenSandBoxInert */ + 0, /* TokenAuditPolicy */ + 0, /* TokenOrigin */ + sizeof(TOKEN_ELEVATION_TYPE), /* TokenElevationType */ + 0, /* TokenLinkedToken */ + sizeof(TOKEN_ELEVATION), /* TokenElevation */ + 0, /* TokenHasRestrictions */ + 0, /* TokenAccessInformation */ + 0, /* TokenVirtualizationAllowed */ + sizeof(DWORD), /* TokenVirtualizationEnabled */ + sizeof(TOKEN_MANDATORY_LABEL) + sizeof(SID), /* TokenIntegrityLevel [sizeof(SID) includes one SubAuthority] */ + 0, /* TokenUIAccess */ + 0, /* TokenMandatoryPolicy */ + 0, /* TokenLogonSid */ + sizeof(DWORD), /* TokenIsAppContainer */ + 0, /* TokenCapabilities */ + sizeof(TOKEN_APPCONTAINER_INFORMATION) + sizeof(SID), /* TokenAppContainerSid */ + 0, /* TokenAppContainerNumber */ + 0, /* TokenUserClaimAttributes*/ + 0, /* TokenDeviceClaimAttributes */ + 0, /* TokenRestrictedUserClaimAttributes */ + 0, /* TokenRestrictedDeviceClaimAttributes */ + 0, /* TokenDeviceGroups */ + 0, /* TokenRestrictedDeviceGroups */ + 0, /* TokenSecurityAttributes */ + 0, /* TokenIsRestricted */ + 0 /* TokenProcessTrustLevel */ + }; + + ULONG len = 0; + NTSTATUS status = STATUS_SUCCESS; + + TRACE( "(%p,%d,%p,%d,%p)\n", token, class, info, length, retlen ); + + if (class < MaxTokenInfoClass) len = info_len[class]; + if (retlen) *retlen = len; + if (length < len) return STATUS_BUFFER_TOO_SMALL; + + switch (class) + { + case TokenUser: + SERVER_START_REQ( get_token_sid ) + { + TOKEN_USER *tuser = info; + PSID sid = tuser + 1; + DWORD sid_len = length < sizeof(TOKEN_USER) ? 0 : length - sizeof(TOKEN_USER); + + req->handle = wine_server_obj_handle( token ); + req->which_sid = class; + wine_server_set_reply( req, sid, sid_len ); + status = wine_server_call( req ); + if (retlen) *retlen = reply->sid_len + sizeof(TOKEN_USER); + if (status == STATUS_SUCCESS) + { + tuser->User.Sid = sid; + tuser->User.Attributes = 0; + } + } + SERVER_END_REQ; + break; + + case TokenGroups: + { + /* reply buffer is always shorter than output one */ + void *buffer = malloc( length ); + + SERVER_START_REQ( get_token_groups ) + { + TOKEN_GROUPS *groups = info; + + req->handle = wine_server_obj_handle( token ); + wine_server_set_reply( req, buffer, length ); + status = wine_server_call( req ); + if (status == STATUS_BUFFER_TOO_SMALL) + { + if (retlen) *retlen = reply->user_len; + } + else if (status == STATUS_SUCCESS) + { + struct token_groups *tg = buffer; + unsigned int *attr = (unsigned int *)(tg + 1); + ULONG i; + const int non_sid_portion = (sizeof(struct token_groups) + tg->count * sizeof(unsigned int)); + SID *sids = (SID *)((char *)info + FIELD_OFFSET( TOKEN_GROUPS, Groups[tg->count] )); + + if (retlen) *retlen = reply->user_len; + + groups->GroupCount = tg->count; + memcpy( sids, (char *)buffer + non_sid_portion, + reply->user_len - offsetof( TOKEN_GROUPS, Groups[tg->count] )); + + for (i = 0; i < tg->count; i++) + { + groups->Groups[i].Attributes = attr[i]; + groups->Groups[i].Sid = sids; + sids = (SID *)((char *)sids + offsetof( SID, SubAuthority[sids->SubAuthorityCount] )); + } + } + else if (retlen) *retlen = 0; + } + SERVER_END_REQ; + free( buffer ); + break; + } + + case TokenPrimaryGroup: + SERVER_START_REQ( get_token_sid ) + { + TOKEN_PRIMARY_GROUP *tgroup = info; + PSID sid = tgroup + 1; + DWORD sid_len = length < sizeof(TOKEN_PRIMARY_GROUP) ? 0 : length - sizeof(TOKEN_PRIMARY_GROUP); + + req->handle = wine_server_obj_handle( token ); + req->which_sid = class; + wine_server_set_reply( req, sid, sid_len ); + status = wine_server_call( req ); + if (retlen) *retlen = reply->sid_len + sizeof(TOKEN_PRIMARY_GROUP); + if (status == STATUS_SUCCESS) tgroup->PrimaryGroup = sid; + } + SERVER_END_REQ; + break; + + case TokenPrivileges: + SERVER_START_REQ( get_token_privileges ) + { + TOKEN_PRIVILEGES *tpriv = info; + req->handle = wine_server_obj_handle( token ); + if (tpriv && length > FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges )) + wine_server_set_reply( req, tpriv->Privileges, length - FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) ); + status = wine_server_call( req ); + if (retlen) *retlen = FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) + reply->len; + if (tpriv) tpriv->PrivilegeCount = reply->len / sizeof(LUID_AND_ATTRIBUTES); + } + SERVER_END_REQ; + break; + + case TokenOwner: + SERVER_START_REQ( get_token_sid ) + { + TOKEN_OWNER *towner = info; + PSID sid = towner + 1; + DWORD sid_len = length < sizeof(TOKEN_OWNER) ? 0 : length - sizeof(TOKEN_OWNER); + + req->handle = wine_server_obj_handle( token ); + req->which_sid = class; + wine_server_set_reply( req, sid, sid_len ); + status = wine_server_call( req ); + if (retlen) *retlen = reply->sid_len + sizeof(TOKEN_OWNER); + if (status == STATUS_SUCCESS) towner->Owner = sid; + } + SERVER_END_REQ; + break; + + case TokenImpersonationLevel: + SERVER_START_REQ( get_token_impersonation_level ) + { + SECURITY_IMPERSONATION_LEVEL *level = info; + req->handle = wine_server_obj_handle( token ); + status = wine_server_call( req ); + if (status == STATUS_SUCCESS) *level = reply->impersonation_level; + } + SERVER_END_REQ; + break; + + case TokenStatistics: + SERVER_START_REQ( get_token_statistics ) + { + TOKEN_STATISTICS *statistics = info; + req->handle = wine_server_obj_handle( token ); + status = wine_server_call( req ); + if (status == STATUS_SUCCESS) + { + statistics->TokenId.LowPart = reply->token_id.low_part; + statistics->TokenId.HighPart = reply->token_id.high_part; + statistics->AuthenticationId.LowPart = 0; /* FIXME */ + statistics->AuthenticationId.HighPart = 0; /* FIXME */ + statistics->ExpirationTime.u.HighPart = 0x7fffffff; + statistics->ExpirationTime.u.LowPart = 0xffffffff; + statistics->TokenType = reply->primary ? TokenPrimary : TokenImpersonation; + statistics->ImpersonationLevel = reply->impersonation_level; + + /* kernel information not relevant to us */ + statistics->DynamicCharged = 0; + statistics->DynamicAvailable = 0; + + statistics->GroupCount = reply->group_count; + statistics->PrivilegeCount = reply->privilege_count; + statistics->ModifiedId.LowPart = reply->modified_id.low_part; + statistics->ModifiedId.HighPart = reply->modified_id.high_part; + } + } + SERVER_END_REQ; + break; + + case TokenType: + SERVER_START_REQ( get_token_statistics ) + { + TOKEN_TYPE *type = info; + req->handle = wine_server_obj_handle( token ); + status = wine_server_call( req ); + if (status == STATUS_SUCCESS) *type = reply->primary ? TokenPrimary : TokenImpersonation; + } + SERVER_END_REQ; + break; + + case TokenDefaultDacl: + SERVER_START_REQ( get_token_default_dacl ) + { + TOKEN_DEFAULT_DACL *default_dacl = info; + ACL *acl = (ACL *)(default_dacl + 1); + DWORD acl_len = length < sizeof(TOKEN_DEFAULT_DACL) ? 0 : length - sizeof(TOKEN_DEFAULT_DACL); + + req->handle = wine_server_obj_handle( token ); + wine_server_set_reply( req, acl, acl_len ); + status = wine_server_call( req ); + if (retlen) *retlen = reply->acl_len + sizeof(TOKEN_DEFAULT_DACL); + if (status == STATUS_SUCCESS) + { + if (reply->acl_len) + default_dacl->DefaultDacl = acl; + else + default_dacl->DefaultDacl = NULL; + } + } + SERVER_END_REQ; + break; + + case TokenElevationType: + { + TOKEN_ELEVATION_TYPE *type = info; + FIXME("QueryInformationToken( ..., TokenElevationType, ...) semi-stub\n"); + *type = TokenElevationTypeFull; + } + break; + + case TokenElevation: + { + TOKEN_ELEVATION *elevation = info; + FIXME("QueryInformationToken( ..., TokenElevation, ...) semi-stub\n"); + elevation->TokenIsElevated = TRUE; + } + break; + + case TokenSessionId: + { + *(DWORD *)info = 0; + FIXME("QueryInformationToken( ..., TokenSessionId, ...) semi-stub\n"); + } + break; + + case TokenVirtualizationEnabled: + { + *(DWORD *)info = 0; + TRACE("QueryInformationToken( ..., TokenVirtualizationEnabled, ...) semi-stub\n"); + } + break; + + case TokenIntegrityLevel: + { + /* report always "S-1-16-12288" (high mandatory level) for now */ + static const SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, + {SECURITY_MANDATORY_HIGH_RID}}; + + TOKEN_MANDATORY_LABEL *tml = info; + PSID psid = tml + 1; + + tml->Label.Sid = psid; + tml->Label.Attributes = SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED; + memcpy( psid, &high_level, sizeof(SID) ); + } + break; + + case TokenAppContainerSid: + { + TOKEN_APPCONTAINER_INFORMATION *container = info; + FIXME("QueryInformationToken( ..., TokenAppContainerSid, ...) semi-stub\n"); + container->TokenAppContainer = NULL; + } + break; + + case TokenIsAppContainer: + { + TRACE("TokenIsAppContainer semi-stub\n"); + *(DWORD *)info = 0; + break; + } + + case TokenLogonSid: + SERVER_START_REQ( get_token_sid ) + { + TOKEN_GROUPS * groups = info; + PSID sid = groups + 1; + DWORD sid_len = length < sizeof(TOKEN_GROUPS) ? 0 : length - sizeof(TOKEN_GROUPS); + + req->handle = wine_server_obj_handle( token ); + req->which_sid = class; + wine_server_set_reply( req, sid, sid_len ); + status = wine_server_call( req ); + if (retlen) *retlen = reply->sid_len + sizeof(TOKEN_GROUPS); + if (status == STATUS_SUCCESS) + { + groups->GroupCount = 1; + groups->Groups[0].Sid = sid; + groups->Groups[0].Attributes = 0; + } + } + SERVER_END_REQ; + break; + + default: + ERR( "Unhandled token information class %u\n", class ); + return STATUS_NOT_IMPLEMENTED; + } + return status; +} + + +/*********************************************************************** + * NtSetInformationToken (NTDLL.@) + */ +NTSTATUS WINAPI NtSetInformationToken( HANDLE token, TOKEN_INFORMATION_CLASS class, + void *info, ULONG length ) +{ + NTSTATUS ret = STATUS_NOT_IMPLEMENTED; + + TRACE( "%p %d %p %u\n", token, class, info, length ); + + switch (class) + { + case TokenDefaultDacl: + if (length < sizeof(TOKEN_DEFAULT_DACL)) + { + ret = STATUS_INFO_LENGTH_MISMATCH; + break; + } + if (!info) + { + ret = STATUS_ACCESS_VIOLATION; + break; + } + SERVER_START_REQ( set_token_default_dacl ) + { + ACL *acl = ((TOKEN_DEFAULT_DACL *)info)->DefaultDacl; + WORD size; + + if (acl) size = acl->AclSize; + else size = 0; + req->handle = wine_server_obj_handle( token ); + wine_server_add_data( req, acl, size ); + ret = wine_server_call( req ); + } + SERVER_END_REQ; + break; + + case TokenSessionId: + if (length < sizeof(DWORD)) + { + ret = STATUS_INFO_LENGTH_MISMATCH; + break; + } + if (!info) + { + ret = STATUS_ACCESS_VIOLATION; + break; + } + FIXME("TokenSessionId stub!\n"); + ret = STATUS_SUCCESS; + break; + + case TokenIntegrityLevel: + FIXME( "TokenIntegrityLevel stub!\n" ); + ret = STATUS_SUCCESS; + break; + + default: + FIXME( "unimplemented class %u\n", class ); + break; + } + return ret; +} + + +/*********************************************************************** + * NtCreateLowBoxToken (NTDLL.@) + */ +NTSTATUS WINAPI NtCreateLowBoxToken( HANDLE *token_handle, HANDLE token, ACCESS_MASK access, + OBJECT_ATTRIBUTES *attr, SID *sid, ULONG count, + SID_AND_ATTRIBUTES *capabilities, ULONG handle_count, HANDLE *handle ) +{ + FIXME("(%p, %p, %x, %p, %p, %u, %p, %u, %p): stub\n", + token_handle, token, access, attr, sid, count, capabilities, handle_count, handle ); + + /* we need to return a NULL handle since later it will be passed to NtClose and that must not fail */ + *token_handle = NULL; + return STATUS_SUCCESS; +} + + +/*********************************************************************** + * NtAdjustGroupsToken (NTDLL.@) + */ +NTSTATUS WINAPI NtAdjustGroupsToken( HANDLE token, BOOLEAN reset, TOKEN_GROUPS *groups, + ULONG length, TOKEN_GROUPS *prev, ULONG *retlen ) +{ + FIXME( "%p %d %p %u %p %p\n", token, reset, groups, length, prev, retlen ); + return STATUS_NOT_IMPLEMENTED; +} + + +/*********************************************************************** + * NtAdjustPrivilegesToken (NTDLL.@) + */ +NTSTATUS WINAPI NtAdjustPrivilegesToken( HANDLE token, BOOLEAN disable, TOKEN_PRIVILEGES *privs, + DWORD length, TOKEN_PRIVILEGES *prev, DWORD *retlen ) +{ + NTSTATUS ret; + + TRACE( "(%p,0x%08x,%p,0x%08x,%p,%p)\n", token, disable, privs, length, prev, retlen ); + + SERVER_START_REQ( adjust_token_privileges ) + { + req->handle = wine_server_obj_handle( token ); + req->disable_all = disable; + req->get_modified_state = (prev != NULL); + if (!disable) + wine_server_add_data( req, privs->Privileges, + privs->PrivilegeCount * sizeof(privs->Privileges[0]) ); + if (prev && length >= FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges )) + wine_server_set_reply( req, prev->Privileges, + length - FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) ); + ret = wine_server_call( req ); + if (prev) + { + if (retlen) *retlen = reply->len + FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ); + prev->PrivilegeCount = reply->len / sizeof(LUID_AND_ATTRIBUTES); + } + } + SERVER_END_REQ; + return ret; +} + + +/*********************************************************************** + * NtPrivilegeCheck (NTDLL.@) + */ +NTSTATUS WINAPI NtPrivilegeCheck( HANDLE token, PRIVILEGE_SET *privs, BOOLEAN *res ) +{ + NTSTATUS status; + + SERVER_START_REQ( check_token_privileges ) + { + req->handle = wine_server_obj_handle( token ); + req->all_required = (privs->Control & PRIVILEGE_SET_ALL_NECESSARY) != 0; + wine_server_add_data( req, privs->Privilege, privs->PrivilegeCount * sizeof(privs->Privilege[0]) ); + wine_server_set_reply( req, privs->Privilege, privs->PrivilegeCount * sizeof(privs->Privilege[0]) ); + status = wine_server_call( req ); + if (status == STATUS_SUCCESS) *res = reply->has_privileges != 0; + } + SERVER_END_REQ; + return status; +} + + +/*********************************************************************** + * NtImpersonateAnonymousToken (NTDLL.@) + */ +NTSTATUS WINAPI NtImpersonateAnonymousToken( HANDLE thread ) +{ + FIXME( "(%p): stub\n", thread ); + return STATUS_NOT_IMPLEMENTED; +}