From c5adfe45129f4fe2648998c8cbf7837782f6f3c2 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Fri, 10 Dec 2004 16:50:38 +0000 Subject: [PATCH] - Fix definitions of SecurityAnonymous, SecurityIdentification, SecurityImpersonation, SecurityDelegation. - Fix prototype of NtDuplicateToken and change DuplicateTokenEx accordingly. - Implement NtOpenThreadToken[Ex] (complete rewrite), PsDisableImpersonation and PsRestoreImpersonation. svn path=/trunk/; revision=11999 --- reactos/include/ntos/security.h | 8 +- reactos/include/ntos/zw.h | 4 +- reactos/lib/advapi32/token/token.c | 12 +- reactos/ntoskrnl/include/internal/se.h | 5 + reactos/ntoskrnl/ps/create.c | 93 +++++-------- reactos/ntoskrnl/ps/thread.c | 19 +-- reactos/ntoskrnl/se/acl.c | 45 ++++++- reactos/ntoskrnl/se/token.c | 173 +++++++++++++++++++++++-- 8 files changed, 254 insertions(+), 105 deletions(-) diff --git a/reactos/include/ntos/security.h b/reactos/include/ntos/security.h index 0e766bfc1d9..829a96ea308 100644 --- a/reactos/include/ntos/security.h +++ b/reactos/include/ntos/security.h @@ -188,10 +188,10 @@ typedef enum _TOKEN_INFORMATION_CLASS typedef ULONG SECURITY_IMPERSONATION_LEVEL, *PSECURITY_IMPERSONATION_LEVEL; -#define SecurityAnonymous ((SECURITY_IMPERSONATION_LEVEL)1) -#define SecurityIdentification ((SECURITY_IMPERSONATION_LEVEL)2) -#define SecurityImpersonation ((SECURITY_IMPERSONATION_LEVEL)3) -#define SecurityDelegation ((SECURITY_IMPERSONATION_LEVEL)4) +#define SecurityAnonymous ((SECURITY_IMPERSONATION_LEVEL)0) +#define SecurityIdentification ((SECURITY_IMPERSONATION_LEVEL)1) +#define SecurityImpersonation ((SECURITY_IMPERSONATION_LEVEL)2) +#define SecurityDelegation ((SECURITY_IMPERSONATION_LEVEL)3) typedef ULONG ACCESS_MASK, *PACCESS_MASK; typedef ULONG TOKEN_TYPE, *PTOKEN_TYPE; diff --git a/reactos/include/ntos/zw.h b/reactos/include/ntos/zw.h index 7bd45996930..5fde605bcef 100755 --- a/reactos/include/ntos/zw.h +++ b/reactos/include/ntos/zw.h @@ -1,5 +1,5 @@ -/* $Id: zw.h,v 1.36 2004/11/25 22:18:15 ion Exp $ +/* $Id: zw.h,v 1.37 2004/12/10 16:50:36 navaraf Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -5839,7 +5839,7 @@ NtDuplicateToken( IN HANDLE ExistingToken, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, - IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, + IN BOOLEAN EffectiveOnly, IN TOKEN_TYPE TokenType, OUT PHANDLE NewToken ); diff --git a/reactos/lib/advapi32/token/token.c b/reactos/lib/advapi32/token/token.c index e76a2b0dc79..3374d021ac5 100644 --- a/reactos/lib/advapi32/token/token.c +++ b/reactos/lib/advapi32/token/token.c @@ -1,4 +1,4 @@ -/* $Id: token.c,v 1.14 2004/09/27 20:04:53 gvg Exp $ +/* $Id: token.c,v 1.15 2004/12/10 16:50:37 navaraf Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -259,9 +259,15 @@ DuplicateTokenEx (HANDLE ExistingTokenHandle, PHANDLE DuplicateTokenHandle) { OBJECT_ATTRIBUTES ObjectAttributes; + SECURITY_QUALITY_OF_SERVICE Qos; HANDLE NewToken; NTSTATUS Status; + Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); + Qos.ImpersonationLevel = ImpersonationLevel; + Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; + Qos.EffectiveOnly = FALSE; + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); ObjectAttributes.RootDirectory = NULL; ObjectAttributes.ObjectName = NULL; @@ -271,12 +277,12 @@ DuplicateTokenEx (HANDLE ExistingTokenHandle, ObjectAttributes.Attributes |= OBJ_INHERIT; } ObjectAttributes.SecurityDescriptor = lpTokenAttributes->lpSecurityDescriptor; - ObjectAttributes.SecurityQualityOfService = NULL; + ObjectAttributes.SecurityQualityOfService = &Qos; Status = NtDuplicateToken (ExistingTokenHandle, dwDesiredAccess, &ObjectAttributes, - ImpersonationLevel, + FALSE, TokenType, &NewToken); if (!NT_SUCCESS(Status)) diff --git a/reactos/ntoskrnl/include/internal/se.h b/reactos/ntoskrnl/include/internal/se.h index b9d7e338696..a4c82c4893b 100644 --- a/reactos/ntoskrnl/include/internal/se.h +++ b/reactos/ntoskrnl/include/internal/se.h @@ -110,6 +110,11 @@ BOOLEAN SepInitSecurityIDs(VOID); BOOLEAN SepInitDACLs(VOID); BOOLEAN SepInitSDs(VOID); +NTSTATUS STDCALL +SepCreateImpersonationTokenDacl(PACCESS_TOKEN Token, + PACCESS_TOKEN PrimaryToken, + PACL *Dacl); + VOID SepInitializeTokenImplementation(VOID); NTSTATUS SepCreateSystemProcessToken(struct _EPROCESS* Process); diff --git a/reactos/ntoskrnl/ps/create.c b/reactos/ntoskrnl/ps/create.c index 614f3aa24d8..2d65116d653 100644 --- a/reactos/ntoskrnl/ps/create.c +++ b/reactos/ntoskrnl/ps/create.c @@ -1,4 +1,4 @@ -/* $Id: create.c,v 1.86 2004/11/20 16:46:05 weiden Exp $ +/* $Id: create.c,v 1.87 2004/12/10 16:50:37 navaraf Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -232,63 +232,6 @@ NtImpersonateThread(IN HANDLE ThreadHandle, return STATUS_SUCCESS; } -/* - * @implemented - */ -NTSTATUS STDCALL -NtOpenThreadToken (IN HANDLE ThreadHandle, - IN ACCESS_MASK DesiredAccess, - IN BOOLEAN OpenAsSelf, - OUT PHANDLE TokenHandle) -{ - PACCESS_TOKEN Token; - PETHREAD Thread; - NTSTATUS Status; - - Status = ObReferenceObjectByHandle (ThreadHandle, - 0, - PsThreadType, - UserMode, - (PVOID*)&Thread, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - if (OpenAsSelf) - { - Token = Thread->ThreadsProcess->Token; - } - else - { - if (Thread->ActiveImpersonationInfo == FALSE) - { - ObDereferenceObject (Thread); - return STATUS_NO_TOKEN; - } - - Token = Thread->ImpersonationInfo->Token; - } - - if (Token == NULL) - { - ObDereferenceObject (Thread); - return STATUS_NO_TOKEN; - } - - Status = ObCreateHandle (PsGetCurrentProcess(), - Token, - DesiredAccess, - FALSE, - TokenHandle); - - ObDereferenceObject (Thread); - - return Status; -} - - /* * @implemented */ @@ -339,7 +282,7 @@ PsDereferencePrimaryToken( } /* - * @unimplemented + * @implemented */ BOOLEAN STDCALL @@ -348,12 +291,32 @@ PsDisableImpersonation( IN PSE_IMPERSONATION_STATE ImpersonationState ) { - UNIMPLEMENTED; - return FALSE; + if (Thread->ActiveImpersonationInfo == FALSE) + { + ImpersonationState->Token = NULL; + ImpersonationState->CopyOnOpen = FALSE; + ImpersonationState->EffectiveOnly = FALSE; + ImpersonationState->Level = 0; + return TRUE; + } + +/* FIXME */ +/* ExfAcquirePushLockExclusive(&Thread->ThreadLock); */ + + Thread->ActiveImpersonationInfo = FALSE; + ImpersonationState->Token = Thread->ImpersonationInfo->Token; + ImpersonationState->CopyOnOpen = Thread->ImpersonationInfo->CopyOnOpen; + ImpersonationState->EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly; + ImpersonationState->Level = Thread->ImpersonationInfo->Level; + +/* FIXME */ +/* ExfReleasePushLock(&Thread->ThreadLock); */ + + return TRUE; } /* - * @unimplemented + * @implemented */ VOID STDCALL @@ -362,7 +325,11 @@ PsRestoreImpersonation( IN PSE_IMPERSONATION_STATE ImpersonationState ) { - UNIMPLEMENTED; + PsImpersonateClient(Thread, ImpersonationState->Token, + ImpersonationState->CopyOnOpen, + ImpersonationState->EffectiveOnly, + ImpersonationState->Level); + ObfDereferenceObject(ImpersonationState->Token); } VOID diff --git a/reactos/ntoskrnl/ps/thread.c b/reactos/ntoskrnl/ps/thread.c index f75156f527c..ca018d4669d 100644 --- a/reactos/ntoskrnl/ps/thread.c +++ b/reactos/ntoskrnl/ps/thread.c @@ -1,4 +1,4 @@ -/* $Id: thread.c,v 1.139 2004/11/27 16:52:35 hbirr Exp $ +/* $Id: thread.c,v 1.140 2004/12/10 16:50:37 navaraf Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -1006,21 +1006,4 @@ PsLookupThreadByThreadId(IN PVOID ThreadId, return STATUS_INVALID_PARAMETER; } -/* - * @unimplemented - */ -NTSTATUS -STDCALL -NtOpenThreadTokenEx( - IN HANDLE ThreadHandle, - IN ACCESS_MASK DesiredAccess, - IN BOOLEAN OpenAsSelf, - IN ULONG HandleAttributes, - OUT PHANDLE TokenHandle - ) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - /* EOF */ diff --git a/reactos/ntoskrnl/se/acl.c b/reactos/ntoskrnl/se/acl.c index 3e20306e330..bc145acbada 100644 --- a/reactos/ntoskrnl/se/acl.c +++ b/reactos/ntoskrnl/se/acl.c @@ -1,4 +1,4 @@ -/* $Id: acl.c,v 1.21 2004/11/06 21:32:16 navaraf Exp $ +/* $Id: acl.c,v 1.22 2004/12/10 16:50:37 navaraf Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -219,4 +219,47 @@ SepInitDACLs(VOID) return(TRUE); } +NTSTATUS STDCALL +SepCreateImpersonationTokenDacl(PACCESS_TOKEN Token, + PACCESS_TOKEN PrimaryToken, + PACL *Dacl) +{ + ULONG AclLength; + PVOID TokenDacl; + + AclLength = sizeof(ACL) + + (sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid)) + + (sizeof(ACE) + RtlLengthSid(SeRestrictedCodeSid)) + + (sizeof(ACE) + RtlLengthSid(SeLocalSystemSid)) + + (sizeof(ACE) + RtlLengthSid(Token->UserAndGroups->Sid)) + + (sizeof(ACE) + RtlLengthSid(PrimaryToken->UserAndGroups->Sid)); + + TokenDacl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_ACL); + if (TokenDacl == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlCreateAcl(TokenDacl, AclLength, ACL_REVISION); + RtlAddAccessAllowedAce(TokenDacl, ACL_REVISION, GENERIC_ALL, + Token->UserAndGroups->Sid); + RtlAddAccessAllowedAce(TokenDacl, ACL_REVISION, GENERIC_ALL, + PrimaryToken->UserAndGroups->Sid); + RtlAddAccessAllowedAce(TokenDacl, ACL_REVISION, GENERIC_ALL, + SeAliasAdminsSid); + RtlAddAccessAllowedAce(TokenDacl, ACL_REVISION, GENERIC_ALL, + SeLocalSystemSid); + + /* FIXME */ +#if 0 + if (Token->RestrictedSids != NULL || PrimaryToken->RestrictedSids != NULL) + { + RtlAddAccessAllowedAce(TokenDacl, ACL_REVISION, GENERIC_ALL, + SeRestrictedCodeSid); + } +#endif + + return STATUS_SUCCESS; +} + /* EOF */ diff --git a/reactos/ntoskrnl/se/token.c b/reactos/ntoskrnl/se/token.c index 2e8d77f2f31..440bf7bc685 100644 --- a/reactos/ntoskrnl/se/token.c +++ b/reactos/ntoskrnl/se/token.c @@ -1,4 +1,4 @@ -/* $Id: token.c,v 1.42 2004/10/22 20:48:00 ekohl Exp $ +/* $Id: token.c,v 1.43 2004/12/10 16:50:38 navaraf Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -133,9 +133,9 @@ SepFindPrimaryGroupAndDefaultOwner(PACCESS_TOKEN Token, NTSTATUS SepDuplicateToken(PACCESS_TOKEN Token, POBJECT_ATTRIBUTES ObjectAttributes, + BOOLEAN EffectiveOnly, TOKEN_TYPE TokenType, SECURITY_IMPERSONATION_LEVEL Level, - SECURITY_IMPERSONATION_LEVEL ExistingLevel, KPROCESSOR_MODE PreviousMode, PACCESS_TOKEN* NewAccessToken) { @@ -281,9 +281,9 @@ SepInitializeNewProcess(struct _EPROCESS* NewProcess, Status = SepDuplicateToken(pParentToken, &ObjectAttributes, + FALSE, TokenPrimary, pParentToken->ImpersonationLevel, - pParentToken->ImpersonationLevel, KernelMode, &pNewToken); if ( ! NT_SUCCESS(Status) ) @@ -307,10 +307,12 @@ SeAppendPrivileges( return STATUS_NOT_IMPLEMENTED; } -NTSTATUS SeCopyClientToken(PACCESS_TOKEN Token, - SECURITY_IMPERSONATION_LEVEL Level, - KPROCESSOR_MODE PreviousMode, - PACCESS_TOKEN* NewToken) +NTSTATUS +STDCALL +SeCopyClientToken(PACCESS_TOKEN Token, + SECURITY_IMPERSONATION_LEVEL Level, + KPROCESSOR_MODE PreviousMode, + PACCESS_TOKEN* NewToken) { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; @@ -322,8 +324,8 @@ NTSTATUS SeCopyClientToken(PACCESS_TOKEN Token, NULL); Status = SepDuplicateToken(Token, &ObjectAttributes, - 0, - SecurityIdentification, + FALSE, + TokenImpersonation, Level, PreviousMode, NewToken); @@ -968,7 +970,7 @@ NTSTATUS STDCALL NtDuplicateToken(IN HANDLE ExistingTokenHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, - IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, + IN BOOLEAN EffectiveOnly, IN TOKEN_TYPE TokenType, OUT PHANDLE NewTokenHandle) { @@ -976,7 +978,6 @@ NtDuplicateToken(IN HANDLE ExistingTokenHandle, PACCESS_TOKEN Token; PACCESS_TOKEN NewToken; NTSTATUS Status; - ULONG ExistingImpersonationLevel; PreviousMode = KeGetPreviousMode(); Status = ObReferenceObjectByHandle(ExistingTokenHandle, @@ -991,12 +992,11 @@ NtDuplicateToken(IN HANDLE ExistingTokenHandle, return Status; } - ExistingImpersonationLevel = Token->ImpersonationLevel; Status = SepDuplicateToken(Token, ObjectAttributes, + EffectiveOnly, TokenType, - ImpersonationLevel, - ExistingImpersonationLevel, + ObjectAttributes->SecurityQualityOfService->ImpersonationLevel, PreviousMode, &NewToken); @@ -1748,4 +1748,149 @@ SeTokenIsWriteRestricted( } +/* + * @implemented + */ +NTSTATUS +STDCALL +NtOpenThreadTokenEx(IN HANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN BOOLEAN OpenAsSelf, + IN ULONG HandleAttributes, + OUT PHANDLE TokenHandle) +{ + PETHREAD Thread; + PACCESS_TOKEN Token, NewToken, PrimaryToken; + BOOLEAN CopyOnOpen, EffectiveOnly; + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; + SE_IMPERSONATION_STATE ImpersonationState; + OBJECT_ATTRIBUTES ObjectAttributes; + SECURITY_DESCRIPTOR SecurityDescriptor; + PACL Dacl = NULL; + NTSTATUS Status; + + /* + * At first open the thread token for information access and verify + * that the token associated with thread is valid. + */ + + Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_QUERY_INFORMATION, + PsThreadType, UserMode, (PVOID*)&Thread, + NULL); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + Token = PsReferenceImpersonationToken(Thread, &CopyOnOpen, &EffectiveOnly, + &ImpersonationLevel); + if (Token == NULL) + { + ObfDereferenceObject(Thread); + return STATUS_NO_TOKEN; + } + + ObDereferenceObject(Thread); + + if (ImpersonationLevel == SecurityAnonymous) + { + ObfDereferenceObject(Token); + return STATUS_CANT_OPEN_ANONYMOUS; + } + + /* + * Revert to self if OpenAsSelf is specified. + */ + + if (OpenAsSelf) + { + PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState); + } + + if (CopyOnOpen) + { + Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_ALL_ACCESS, + PsThreadType, UserMode, + (PVOID*)&Thread, NULL); + if (!NT_SUCCESS(Status)) + { + ObfDereferenceObject(Token); + if (OpenAsSelf) + { + PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState); + } + return Status; + } + + PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess); + Status = SepCreateImpersonationTokenDacl(Token, PrimaryToken, &Dacl); + ObfDereferenceObject(PrimaryToken); + ObfDereferenceObject(Thread); + if (!NT_SUCCESS(Status)) + { + ObfDereferenceObject(Token); + if (OpenAsSelf) + { + PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState); + } + return Status; + } + + RtlCreateSecurityDescriptor(&SecurityDescriptor, + SECURITY_DESCRIPTOR_REVISION); + RtlSetDaclSecurityDescriptor(&SecurityDescriptor, TRUE, Dacl, + FALSE); + + InitializeObjectAttributes(&ObjectAttributes, NULL, HandleAttributes, + NULL, &SecurityDescriptor); + + Status = SepDuplicateToken(Token, &ObjectAttributes, EffectiveOnly, + TokenImpersonation, ImpersonationLevel, + KernelMode, &NewToken); + ExFreePool(Dacl); + if (!NT_SUCCESS(Status)) + { + ObfDereferenceObject(Token); + if (OpenAsSelf) + { + PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState); + } + return Status; + } + + Status = ObInsertObject(NewToken, NULL, DesiredAccess, 0, NULL, + TokenHandle); + + ObfDereferenceObject(NewToken); + } + else + { + Status = ObOpenObjectByPointer(Token, HandleAttributes, + NULL, DesiredAccess, SepTokenObjectType, + ExGetPreviousMode(), TokenHandle); + } + + ObfDereferenceObject(Token); + + if (OpenAsSelf) + { + PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState); + } + + return Status; +} + +/* + * @implemented + */ +NTSTATUS STDCALL +NtOpenThreadToken(IN HANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN BOOLEAN OpenAsSelf, + OUT PHANDLE TokenHandle) +{ + return NtOpenThreadTokenEx(ThreadHandle, DesiredAccess, OpenAsSelf, 0, + TokenHandle); +} + /* EOF */