Author: hbelusca Date: Fri Nov 4 17:52:32 2016 New Revision: 73122
URL: http://svn.reactos.org/svn/reactos?rev=73122&view=rev Log: [NTOS] - accesschk.c: Remove redundant SepAccessCheck/SepAccessCheckEx pair of private functions; instead just rename SepAccessCheckEx into SepAccessCheck and use it directly in the code. NOTE: SepAccessCheck is *incomplete* (in particular it doesn't retrieve the information needed to initialize the 'Privileges' parameter). - sid.c: Comments formatting fix. - token.c: * Finish to implement SeQueryInformationToken . This function is really the same as NtQueryInformationToken but without all the stuff needed for user-mode buffer access protection. * Some code simplifications in NtQueryInformationToken. I need this to fix a "FIXME: Use SeQueryInformationToken" in some code I'm also fixing (& commit later).
[NDK]: Fix parameter types and add annotations to RtlCopySidAndAttributesArray.
[KMTESTS:NTOS_SE] - Reenable the 'SeQueryInfoToken' test. - Show that SeQueryInformationToken doesn't support 4 token information classes, which are supported only by NtQueryInformationToken. - Fix calling of SeAccessCheck. In particular the 'Privileges' parameter is not allocated by the caller, but instead is allocated by SeAccessCheck *and* returned to the caller (who then must free the buffer using SeFreePrivileges). This fixes the encountered BSODs that leaded to disabling preventively the test in r59178. - Minor code cleaning.
Modified: trunk/reactos/ntoskrnl/se/accesschk.c trunk/reactos/ntoskrnl/se/sid.c trunk/reactos/ntoskrnl/se/token.c trunk/reactos/sdk/include/ndk/rtlfuncs.h trunk/reactos/sdk/lib/rtl/sid.c trunk/rostests/kmtests/kmtest_drv/testlist.c trunk/rostests/kmtests/ntos_se/SeQueryInfoToken.c
Modified: trunk/reactos/ntoskrnl/se/accesschk.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/accesschk.c?rev... ============================================================================== --- trunk/reactos/ntoskrnl/se/accesschk.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/se/accesschk.c [iso-8859-1] Fri Nov 4 17:52:32 2016 @@ -18,8 +18,11 @@
/* PRIVATE FUNCTIONS **********************************************************/
+/* + * FIXME: Incomplete! + */ BOOLEAN NTAPI -SepAccessCheckEx(IN PSECURITY_DESCRIPTOR SecurityDescriptor, +SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE_LIST ObjectTypeList, @@ -46,7 +49,7 @@ NTSTATUS Status; PAGED_CODE();
- DPRINT("SepAccessCheckEx()\n"); + DPRINT("SepAccessCheck()\n");
/* Check for no access desired */ if (!DesiredAccess) @@ -281,31 +284,6 @@ }
return NT_SUCCESS(Status); -} - -BOOLEAN NTAPI -SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, - IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext, - IN ACCESS_MASK DesiredAccess, - IN ACCESS_MASK PreviouslyGrantedAccess, - OUT PPRIVILEGE_SET* Privileges, - IN PGENERIC_MAPPING GenericMapping, - IN KPROCESSOR_MODE AccessMode, - OUT PACCESS_MASK GrantedAccess, - OUT PNTSTATUS AccessStatus) -{ - return SepAccessCheckEx(SecurityDescriptor, - SubjectSecurityContext, - DesiredAccess, - NULL, - 0, - PreviouslyGrantedAccess, - Privileges, - GenericMapping, - AccessMode, - GrantedAccess, - AccessStatus, - FALSE); }
static PSID @@ -443,12 +421,15 @@ ret = SepAccessCheck(SecurityDescriptor, SubjectSecurityContext, DesiredAccess, + NULL, + 0, PreviouslyGrantedAccess, Privileges, GenericMapping, AccessMode, GrantedAccess, - AccessStatus); + AccessStatus, + FALSE); }
/* Release the lock if needed */ @@ -687,12 +668,15 @@ SepAccessCheck(SecurityDescriptor, // FIXME: use CapturedSecurityDescriptor &SubjectSecurityContext, DesiredAccess, + NULL, + 0, PreviouslyGrantedAccess, &PrivilegeSet, //FIXME GenericMapping, PreviousMode, GrantedAccess, - AccessStatus); + AccessStatus, + FALSE); }
/* Release subject context and unlock the token */
Modified: trunk/reactos/ntoskrnl/se/sid.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/sid.c?rev=73122... ============================================================================== --- trunk/reactos/ntoskrnl/se/sid.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/se/sid.c [iso-8859-1] Fri Nov 4 17:52:32 2016 @@ -297,7 +297,7 @@ } _SEH2_END;
- /* allocate a SID and copy it */ + /* Allocate a SID and copy it */ NewSid = ExAllocatePoolWithTag(PoolType, SidSize, TAG_SID); if (!NewSid) return STATUS_INSUFFICIENT_RESOURCES; @@ -324,7 +324,7 @@ { SidSize = RtlLengthRequiredSid(Sid->SubAuthorityCount);
- /* allocate a SID and copy it */ + /* Allocate a SID and copy it */ NewSid = ExAllocatePoolWithTag(PoolType, SidSize, TAG_SID); if (NewSid == NULL) return STATUS_INSUFFICIENT_RESOURCES;
Modified: trunk/reactos/ntoskrnl/se/token.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/token.c?rev=731... ============================================================================== --- trunk/reactos/ntoskrnl/se/token.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/se/token.c [iso-8859-1] Fri Nov 4 17:52:32 2016 @@ -232,7 +232,7 @@
PAGED_CODE();
- if (NewToken->TokenType != TokenPrimary) return(STATUS_BAD_TOKEN_TYPE); + if (NewToken->TokenType != TokenPrimary) return STATUS_BAD_TOKEN_TYPE; if (NewToken->TokenInUse) { BOOLEAN IsEqual; @@ -348,12 +348,12 @@
if (Token->DefaultOwnerIndex == Token->UserAndGroupCount) { - return(STATUS_INVALID_OWNER); + return STATUS_INVALID_OWNER; }
if (Token->PrimaryGroup == 0) { - return(STATUS_INVALID_PRIMARY_GROUP); + return STATUS_INVALID_PRIMARY_GROUP; }
return STATUS_SUCCESS; @@ -1060,16 +1060,26 @@ }
/* - * @unimplemented + * @implemented + * + * NOTE: SeQueryInformationToken is just NtQueryInformationToken without all + * the bells and whistles needed for user-mode buffer access protection. */ NTSTATUS NTAPI -SeQueryInformationToken(IN PACCESS_TOKEN Token, +SeQueryInformationToken(IN PACCESS_TOKEN AccessToken, IN TOKEN_INFORMATION_CLASS TokenInformationClass, OUT PVOID *TokenInformation) { NTSTATUS Status; - PSECURITY_IMPERSONATION_LEVEL SeImpersonationLvl; + PTOKEN Token = (PTOKEN)AccessToken; + ULONG RequiredLength; + union + { + PSID PSid; + ULONG Ulong; + } Unused; + PAGED_CODE();
if (TokenInformationClass >= MaxTokenInfoClass) @@ -1080,31 +1090,395 @@
switch (TokenInformationClass) { - case TokenImpersonationLevel: - /* It is mandatory to have an impersonation token */ - if (((PTOKEN)Token)->TokenType != TokenImpersonation) - { - Status = STATUS_INVALID_INFO_CLASS; - break; - } + case TokenUser: + { + PTOKEN_USER tu; + + DPRINT("SeQueryInformationToken(TokenUser)\n"); + RequiredLength = sizeof(TOKEN_USER) + + RtlLengthSid(Token->UserAndGroups[0].Sid);
/* Allocate the output buffer */ - SeImpersonationLvl = ExAllocatePoolWithTag(PagedPool, sizeof(SECURITY_IMPERSONATION_LEVEL), TAG_SE); - if (SeImpersonationLvl == NULL) + tu = ExAllocatePoolWithTag(PagedPool, RequiredLength, TAG_SE); + if (tu == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; break; }
- /* Set impersonation level and return the structure */ - *SeImpersonationLvl = ((PTOKEN)Token)->ImpersonationLevel; - *TokenInformation = SeImpersonationLvl; + Status = RtlCopySidAndAttributesArray(1, + &Token->UserAndGroups[0], + RequiredLength - sizeof(TOKEN_USER), + &tu->User, + (PSID)(tu + 1), + &Unused.PSid, + &Unused.Ulong); + + /* Return the structure */ + *TokenInformation = tu; Status = STATUS_SUCCESS; break; + } + + case TokenGroups: + { + PTOKEN_GROUPS tg; + ULONG SidLen; + PSID Sid; + + DPRINT("SeQueryInformationToken(TokenGroups)\n"); + RequiredLength = sizeof(tg->GroupCount) + + RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]); + + SidLen = RequiredLength - sizeof(tg->GroupCount) - + ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)); + + /* Allocate the output buffer */ + tg = ExAllocatePoolWithTag(PagedPool, RequiredLength, TAG_SE); + if (tg == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + Sid = (PSID)((ULONG_PTR)tg + sizeof(tg->GroupCount) + + ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES))); + + tg->GroupCount = Token->UserAndGroupCount - 1; + Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1, + &Token->UserAndGroups[1], + SidLen, + &tg->Groups[0], + Sid, + &Unused.PSid, + &Unused.Ulong); + + /* Return the structure */ + *TokenInformation = tg; + Status = STATUS_SUCCESS; + break; + } + + case TokenPrivileges: + { + PTOKEN_PRIVILEGES tp; + + DPRINT("SeQueryInformationToken(TokenPrivileges)\n"); + RequiredLength = sizeof(tp->PrivilegeCount) + + (Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES)); + + /* Allocate the output buffer */ + tp = ExAllocatePoolWithTag(PagedPool, RequiredLength, TAG_SE); + if (tp == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + tp->PrivilegeCount = Token->PrivilegeCount; + RtlCopyLuidAndAttributesArray(Token->PrivilegeCount, + Token->Privileges, + &tp->Privileges[0]); + + /* Return the structure */ + *TokenInformation = tp; + Status = STATUS_SUCCESS; + break; + } + + case TokenOwner: + { + PTOKEN_OWNER to; + ULONG SidLen; + + DPRINT("SeQueryInformationToken(TokenOwner)\n"); + SidLen = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid); + RequiredLength = sizeof(TOKEN_OWNER) + SidLen; + + /* Allocate the output buffer */ + to = ExAllocatePoolWithTag(PagedPool, RequiredLength, TAG_SE); + if (to == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + to->Owner = (PSID)(to + 1); + Status = RtlCopySid(SidLen, + to->Owner, + Token->UserAndGroups[Token->DefaultOwnerIndex].Sid); + + /* Return the structure */ + *TokenInformation = to; + Status = STATUS_SUCCESS; + break; + } + + case TokenPrimaryGroup: + { + PTOKEN_PRIMARY_GROUP tpg; + ULONG SidLen; + + DPRINT("SeQueryInformationToken(TokenPrimaryGroup)\n"); + SidLen = RtlLengthSid(Token->PrimaryGroup); + RequiredLength = sizeof(TOKEN_PRIMARY_GROUP) + SidLen; + + /* Allocate the output buffer */ + tpg = ExAllocatePoolWithTag(PagedPool, RequiredLength, TAG_SE); + if (tpg == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + tpg->PrimaryGroup = (PSID)(tpg + 1); + Status = RtlCopySid(SidLen, + tpg->PrimaryGroup, + Token->PrimaryGroup); + + /* Return the structure */ + *TokenInformation = tpg; + Status = STATUS_SUCCESS; + break; + } + + case TokenDefaultDacl: + { + PTOKEN_DEFAULT_DACL tdd; + + DPRINT("SeQueryInformationToken(TokenDefaultDacl)\n"); + RequiredLength = sizeof(TOKEN_DEFAULT_DACL); + + if (Token->DefaultDacl != NULL) + RequiredLength += Token->DefaultDacl->AclSize; + + /* Allocate the output buffer */ + tdd = ExAllocatePoolWithTag(PagedPool, RequiredLength, TAG_SE); + if (tdd == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + if (Token->DefaultDacl != NULL) + { + tdd->DefaultDacl = (PACL)(tdd + 1); + RtlCopyMemory(tdd->DefaultDacl, + Token->DefaultDacl, + Token->DefaultDacl->AclSize); + } + else + { + tdd->DefaultDacl = NULL; + } + + /* Return the structure */ + *TokenInformation = tdd; + Status = STATUS_SUCCESS; + break; + } + + case TokenSource: + { + PTOKEN_SOURCE ts; + + DPRINT("SeQueryInformationToken(TokenSource)\n"); + RequiredLength = sizeof(TOKEN_SOURCE); + + /* Allocate the output buffer */ + ts = ExAllocatePoolWithTag(PagedPool, RequiredLength, TAG_SE); + if (ts == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + *ts = Token->TokenSource; + + /* Return the structure */ + *TokenInformation = ts; + Status = STATUS_SUCCESS; + break; + } + + case TokenType: + { + PTOKEN_TYPE tt; + + DPRINT("SeQueryInformationToken(TokenType)\n"); + RequiredLength = sizeof(TOKEN_TYPE); + + /* Allocate the output buffer */ + tt = ExAllocatePoolWithTag(PagedPool, RequiredLength, TAG_SE); + if (tt == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + *tt = Token->TokenType; + + /* Return the structure */ + *TokenInformation = tt; + Status = STATUS_SUCCESS; + break; + } + + case TokenImpersonationLevel: + { + PSECURITY_IMPERSONATION_LEVEL sil; + + DPRINT("SeQueryInformationToken(TokenImpersonationLevel)\n"); + RequiredLength = sizeof(SECURITY_IMPERSONATION_LEVEL); + + /* Fail if the token is not an impersonation token */ + if (Token->TokenType != TokenImpersonation) + { + Status = STATUS_INVALID_INFO_CLASS; + break; + } + + /* Allocate the output buffer */ + sil = ExAllocatePoolWithTag(PagedPool, RequiredLength, TAG_SE); + if (sil == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + *sil = Token->ImpersonationLevel; + + /* Return the structure */ + *TokenInformation = sil; + Status = STATUS_SUCCESS; + break; + } + + case TokenStatistics: + { + PTOKEN_STATISTICS ts; + + DPRINT("SeQueryInformationToken(TokenStatistics)\n"); + RequiredLength = sizeof(TOKEN_STATISTICS); + + /* Allocate the output buffer */ + ts = ExAllocatePoolWithTag(PagedPool, RequiredLength, TAG_SE); + if (ts == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + ts->TokenId = Token->TokenId; + ts->AuthenticationId = Token->AuthenticationId; + ts->ExpirationTime = Token->ExpirationTime; + ts->TokenType = Token->TokenType; + ts->ImpersonationLevel = Token->ImpersonationLevel; + ts->DynamicCharged = Token->DynamicCharged; + ts->DynamicAvailable = Token->DynamicAvailable; + ts->GroupCount = Token->UserAndGroupCount - 1; + ts->PrivilegeCount = Token->PrivilegeCount; + ts->ModifiedId = Token->ModifiedId; + + /* Return the structure */ + *TokenInformation = ts; + Status = STATUS_SUCCESS; + break; + } + +/* + * The following 4 cases are only implemented in NtQueryInformationToken + */ +#if 0 + + case TokenOrigin: + { + PTOKEN_ORIGIN to; + + DPRINT("SeQueryInformationToken(TokenOrigin)\n"); + RequiredLength = sizeof(TOKEN_ORIGIN); + + /* Allocate the output buffer */ + to = ExAllocatePoolWithTag(PagedPool, RequiredLength, TAG_SE); + if (to == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + RtlCopyLuid(&to->OriginatingLogonSession, + &Token->AuthenticationId); + + /* Return the structure */ + *TokenInformation = to; + Status = STATUS_SUCCESS; + break; + } + + case TokenGroupsAndPrivileges: + DPRINT1("SeQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case TokenRestrictedSids: + { + PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation; + ULONG SidLen; + PSID Sid; + + DPRINT("SeQueryInformationToken(TokenRestrictedSids)\n"); + RequiredLength = sizeof(tg->GroupCount) + + RtlLengthSidAndAttributes(Token->RestrictedSidCount, Token->RestrictedSids); + + SidLen = RequiredLength - sizeof(tg->GroupCount) - + (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)); + + /* Allocate the output buffer */ + tg = ExAllocatePoolWithTag(PagedPool, RequiredLength, TAG_SE); + if (tg == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + Sid = (PSID)((ULONG_PTR)tg + sizeof(tg->GroupCount) + + (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES))); + + tg->GroupCount = Token->RestrictedSidCount; + Status = RtlCopySidAndAttributesArray(Token->RestrictedSidCount, + Token->RestrictedSids, + SidLen, + &tg->Groups[0], + Sid, + &Unused.PSid, + &Unused.Ulong); + + /* Return the structure */ + *TokenInformation = tg; + Status = STATUS_SUCCESS; + break; + } + + case TokenSandBoxInert: + DPRINT1("SeQueryInformationToken(TokenSandboxInert) not implemented\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + +#endif + + case TokenSessionId: + { + DPRINT("SeQueryInformationToken(TokenSessionId)\n"); + + Status = SeQuerySessionIdToken(Token, (PULONG)TokenInformation); + + // Status = STATUS_SUCCESS; + break; + }
default: - UNIMPLEMENTED; - Status = STATUS_NOT_IMPLEMENTED; + DPRINT1("SeQueryInformationToken(%d) invalid information class\n", TokenInformationClass); + Status = STATUS_INVALID_INFO_CLASS; break; }
@@ -1212,15 +1586,15 @@ IN ULONG TokenInformationLength, OUT PULONG ReturnLength) { + NTSTATUS Status; + KPROCESSOR_MODE PreviousMode; + PTOKEN Token; + ULONG RequiredLength; union { - PVOID Ptr; + PSID PSid; ULONG Ulong; } Unused; - PTOKEN Token; - ULONG RequiredLength; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status;
PAGED_CODE();
@@ -1229,7 +1603,7 @@ /* Check buffers and class validity */ Status = DefaultQueryInfoBufferCheck(TokenInformationClass, SeTokenInformationClass, - sizeof(SeTokenInformationClass) / sizeof(SeTokenInformationClass[0]), + RTL_NUMBER_OF(SeTokenInformationClass), TokenInformation, TokenInformationLength, ReturnLength, @@ -1257,7 +1631,7 @@
DPRINT("NtQueryInformationToken(TokenUser)\n"); RequiredLength = sizeof(TOKEN_USER) + - RtlLengthSid(Token->UserAndGroups[0].Sid); + RtlLengthSid(Token->UserAndGroups[0].Sid);
_SEH2_TRY { @@ -1268,7 +1642,7 @@ RequiredLength - sizeof(TOKEN_USER), &tu->User, (PSID)(tu + 1), - &Unused.Ptr, + &Unused.PSid, &Unused.Ulong); } else @@ -1296,24 +1670,24 @@
DPRINT("NtQueryInformationToken(TokenGroups)\n"); RequiredLength = sizeof(tg->GroupCount) + - RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]); + RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]);
_SEH2_TRY { if (TokenInformationLength >= RequiredLength) { ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) - - ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)); - PSID_AND_ATTRIBUTES Sid = (PSID_AND_ATTRIBUTES)((ULONG_PTR)TokenInformation + sizeof(tg->GroupCount) + - ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES))); + ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)); + PSID Sid = (PSID_AND_ATTRIBUTES)((ULONG_PTR)tg + sizeof(tg->GroupCount) + + ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)));
tg->GroupCount = Token->UserAndGroupCount - 1; Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1], SidLen, &tg->Groups[0], - (PSID)Sid, - &Unused.Ptr, + Sid, + &Unused.PSid, &Unused.Ulong); } else @@ -1341,7 +1715,7 @@
DPRINT("NtQueryInformationToken(TokenPrivileges)\n"); RequiredLength = sizeof(tp->PrivilegeCount) + - (Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES)); + (Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
_SEH2_TRY { @@ -1373,8 +1747,8 @@
case TokenOwner: { + PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation; ULONG SidLen; - PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
DPRINT("NtQueryInformationToken(TokenOwner)\n"); SidLen = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid); @@ -1410,8 +1784,8 @@
case TokenPrimaryGroup: { + PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation; ULONG SidLen; - PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n"); SidLen = RtlLengthSid(Token->PrimaryGroup); @@ -1453,9 +1827,7 @@ RequiredLength = sizeof(TOKEN_DEFAULT_DACL);
if (Token->DefaultDacl != NULL) - { RequiredLength += Token->DefaultDacl->AclSize; - }
_SEH2_TRY { @@ -1688,17 +2060,17 @@ if (TokenInformationLength >= RequiredLength) { ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) - - (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)); - PSID_AND_ATTRIBUTES Sid = (PSID_AND_ATTRIBUTES)((ULONG_PTR)TokenInformation + sizeof(tg->GroupCount) + - (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES))); + (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)); + PSID Sid = (PSID)((ULONG_PTR)tg + sizeof(tg->GroupCount) + + (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)));
tg->GroupCount = Token->RestrictedSidCount; Status = RtlCopySidAndAttributesArray(Token->RestrictedSidCount, Token->RestrictedSids, SidLen, &tg->Groups[0], - (PSID)Sid, - &Unused.Ptr, + Sid, + &Unused.PSid, &Unused.Ulong); } else @@ -1731,14 +2103,12 @@
DPRINT("NtQueryInformationToken(TokenSessionId)\n");
- Status = SeQuerySessionIdToken(Token, - &SessionId); - + Status = SeQuerySessionIdToken(Token, &SessionId); if (NT_SUCCESS(Status)) { _SEH2_TRY { - /* buffer size was already verified, no need to check here again */ + /* Buffer size was already verified, no need to check here again */ *(PULONG)TokenInformation = SessionId;
if (ReturnLength != NULL) @@ -1792,7 +2162,7 @@
Status = DefaultSetInfoBufferCheck(TokenInformationClass, SeTokenInformationClass, - sizeof(SeTokenInformationClass) / sizeof(SeTokenInformationClass[0]), + RTL_NUMBER_OF(SeTokenInformationClass), TokenInformation, TokenInformationLength, PreviousMode); @@ -2179,14 +2549,16 @@ * @implemented * * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K - * this is certainly NOT true, thou i can't say for sure that EffectiveOnly + * this is certainly NOT true, although I can't say for sure that EffectiveOnly * is correct either. -Gunnar * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI + * NOTE for readers: http://hex.pp.ua/nt/NtDuplicateToken.php is therefore + * wrong in that regard. */ NTSTATUS NTAPI NtDuplicateToken(IN HANDLE ExistingTokenHandle, IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN BOOLEAN EffectiveOnly, IN TOKEN_TYPE TokenType, OUT PHANDLE NewTokenHandle) @@ -2330,7 +2702,7 @@ OUT PULONG ReturnLength) { UNIMPLEMENTED; - return(STATUS_NOT_IMPLEMENTED); + return STATUS_NOT_IMPLEMENTED; }
Modified: trunk/reactos/sdk/include/ndk/rtlfuncs.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/include/ndk/rtlfuncs.h?... ============================================================================== --- trunk/reactos/sdk/include/ndk/rtlfuncs.h [iso-8859-1] (original) +++ trunk/reactos/sdk/include/ndk/rtlfuncs.h [iso-8859-1] Fri Nov 4 17:52:32 2016 @@ -1279,13 +1279,13 @@ NTSTATUS NTAPI RtlCopySidAndAttributesArray( - ULONG Count, - PSID_AND_ATTRIBUTES Src, - ULONG SidAreaSize, - PSID_AND_ATTRIBUTES Dest, - PVOID SidArea, - PVOID* RemainingSidArea, - PULONG RemainingSidAreaSize + _In_ ULONG Count, + _In_ PSID_AND_ATTRIBUTES Src, + _In_ ULONG SidAreaSize, + _In_ PSID_AND_ATTRIBUTES Dest, + _In_ PSID SidArea, + _Out_ PSID* RemainingSidArea, + _Out_ PULONG RemainingSidAreaSize );
_IRQL_requires_max_(APC_LEVEL)
Modified: trunk/reactos/sdk/lib/rtl/sid.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/lib/rtl/sid.c?rev=73122... ============================================================================== --- trunk/reactos/sdk/lib/rtl/sid.c [iso-8859-1] (original) +++ trunk/reactos/sdk/lib/rtl/sid.c [iso-8859-1] Fri Nov 4 17:52:32 2016 @@ -250,8 +250,8 @@ IN PSID_AND_ATTRIBUTES Src, IN ULONG SidAreaSize, IN PSID_AND_ATTRIBUTES Dest, - IN PVOID SidArea, - OUT PVOID* RemainingSidArea, + IN PSID SidArea, + OUT PSID* RemainingSidArea, OUT PULONG RemainingSidAreaSize) { ULONG SidLength, i; @@ -273,7 +273,7 @@ RtlCopySid(SidLength, SidArea, Src[i].Sid);
/* Push the buffer area where the SID will reset */ - SidArea = (PVOID)((ULONG_PTR)SidArea + SidLength); + SidArea = (PSID)((ULONG_PTR)SidArea + SidLength); }
/* Return how much space is left, and where the buffer is at now */
Modified: trunk/rostests/kmtests/kmtest_drv/testlist.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/kmtests/kmtest_drv/testlis... ============================================================================== --- trunk/rostests/kmtests/kmtest_drv/testlist.c [iso-8859-1] (original) +++ trunk/rostests/kmtests/kmtest_drv/testlist.c [iso-8859-1] Fri Nov 4 17:52:32 2016 @@ -132,8 +132,6 @@ { "-ObTypeNoClean", Test_ObTypeNoClean }, { "ObTypes", Test_ObTypes }, { "PsNotify", Test_PsNotify }, - { "SeInheritance", Test_SeInheritance }, - { "-SeQueryInfoToken", Test_SeQueryInfoToken }, { "RtlAvlTreeKM", Test_RtlAvlTree }, { "RtlExceptionKM", Test_RtlException }, { "RtlIntSafeKM", Test_RtlIntSafe }, @@ -142,6 +140,8 @@ { "RtlRegistryKM", Test_RtlRegistry }, { "RtlSplayTreeKM", Test_RtlSplayTree }, { "RtlUnicodeStringKM", Test_RtlUnicodeString }, + { "SeInheritance", Test_SeInheritance }, + { "SeQueryInfoToken", Test_SeQueryInfoToken }, { "ZwAllocateVirtualMemory", Test_ZwAllocateVirtualMemory }, { "ZwCreateSection", Test_ZwCreateSection }, { "ZwMapViewOfSection", Test_ZwMapViewOfSection },
Modified: trunk/rostests/kmtests/ntos_se/SeQueryInfoToken.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/kmtests/ntos_se/SeQueryInf... ============================================================================== --- trunk/rostests/kmtests/ntos_se/SeQueryInfoToken.c [iso-8859-1] (original) +++ trunk/rostests/kmtests/ntos_se/SeQueryInfoToken.c [iso-8859-1] Fri Nov 4 17:52:32 2016 @@ -44,10 +44,10 @@ if (Token == NULL) return;
Status = SeQueryInformationToken(Token, TokenOwner, &Buffer); - ok((Status == STATUS_SUCCESS), "SQIT with TokenOwner arg fails with status 0x%X\n", Status); - if (Status == STATUS_SUCCESS) - { - ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenOwner arg. But Buffer = NULL\n"); + ok((Status == STATUS_SUCCESS), "SQIT with TokenOwner arg fails with status 0x%08X\n", Status); + if (Status == STATUS_SUCCESS) + { + ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenOwner arg. But Buffer == NULL\n");
if (Buffer) { @@ -62,10 +62,10 @@
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenDefaultDacl, &Buffer); - ok(Status == STATUS_SUCCESS, "SQIT with TokenDefaultDacl fails with status 0x%X\n", Status); - if (Status == STATUS_SUCCESS) - { - ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenDefaultDacl arg. But Buffer = NULL\n"); + ok(Status == STATUS_SUCCESS, "SQIT with TokenDefaultDacl fails with status 0x%08X\n", Status); + if (Status == STATUS_SUCCESS) + { + ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenDefaultDacl arg. But Buffer == NULL\n"); if (Buffer) { TDefDacl = (PTOKEN_DEFAULT_DACL)Buffer; @@ -79,10 +79,10 @@
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenGroups, &Buffer); - ok(Status == STATUS_SUCCESS, "SQIT with TokenGroups fails with status 0x%X\n", Status); - if (Status == STATUS_SUCCESS) - { - ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenGroups arg. But Buffer = NULL\n"); + ok(Status == STATUS_SUCCESS, "SQIT with TokenGroups fails with status 0x%08X\n", Status); + if (Status == STATUS_SUCCESS) + { + ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenGroups arg. But Buffer == NULL\n"); if (Buffer) { TGroups = (PTOKEN_GROUPS)Buffer; @@ -107,58 +107,88 @@ // Call SQIT with TokenImpersonationLevel argument // // What's up? Why SQIT fails with right arg? + // Because your token has Token->TokenType != TokenImpersonation. -hbelusca
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenImpersonationLevel, &Buffer); - ok(Status == STATUS_SUCCESS, "SQIT with TokenImpersonationLevel fails with status 0x%X\n", Status); + ok(Status == STATUS_SUCCESS, "SQIT with TokenImpersonationLevel fails with status 0x%08X\n", Status); + if (Buffer) ExFreePool(Buffer);
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenImpersonationLevel, &Buffer); - ok(Status == STATUS_SUCCESS, "and again: SQIT with TokenImpersonationLevel fails with status 0x%X\n", Status); - if (Status == STATUS_SUCCESS) - { - ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenImpersonationLevel arg. But Buffer = NULL\n"); + ok(Status == STATUS_SUCCESS, "and again: SQIT with TokenImpersonationLevel fails with status 0x%08X\n", Status); + if (Status == STATUS_SUCCESS) + { + ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenImpersonationLevel arg. But Buffer == NULL\n"); } else { - ok(Buffer == NULL, "Wrong. SQIT call is't success. But Buffer != NULL\n"); - } + ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n"); + } + if (Buffer) ExFreePool(Buffer); + + //----------------------------------------------------------------// + + // Call SQIT with the 4 classes (TokenOrigin, TokenGroupsAndPrivileges, + // TokenRestrictedSids and TokenSandBoxInert) are not supported by + // SeQueryInformationToken (only NtQueryInformationToken supports them). + // + + Buffer = NULL; + Status = SeQueryInformationToken(Token, TokenOrigin, &Buffer); + ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenOrigin failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status); + ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n"); + + Buffer = NULL; + Status = SeQueryInformationToken(Token, TokenGroupsAndPrivileges, &Buffer); + ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenGroupsAndPrivileges failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status); + ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n"); + + Buffer = NULL; + Status = SeQueryInformationToken(Token, TokenRestrictedSids, &Buffer); + ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenRestrictedSids failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status); + ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n"); + + Buffer = NULL; + Status = SeQueryInformationToken(Token, TokenSandBoxInert, &Buffer); + ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenSandBoxInert failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status); + ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n");
//----------------------------------------------------------------//
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenStatistics, &Buffer); - ok(Status == STATUS_SUCCESS, "SQIT with TokenStatistics fails with status 0x%X\n", Status); - if (Status == STATUS_SUCCESS) - { - ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenStatistics arg. But Buffer = NULL\n"); + ok(Status == STATUS_SUCCESS, "SQIT with TokenStatistics fails with status 0x%08X\n", Status); + if (Status == STATUS_SUCCESS) + { + ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenStatistics arg. But Buffer == NULL\n"); if (Buffer) { TStats = (PTOKEN_STATISTICS)Buffer; - // just put 0 into 1st arg or use trace to print TokenStatistics f + // just put 0 into 1st arg or use trace to print TokenStatistics ok(1, "print statistics:\n\tTokenID = %u_%d\n\tSecurityImperLevel = %d\n\tPrivCount = %d\n\tGroupCount = %d\n\n", TStats->TokenId.LowPart, TStats->TokenId.HighPart, TStats->ImpersonationLevel, TStats->PrivilegeCount, TStats->GroupCount ); - ExFreePool(TStats); + ExFreePool(Buffer); } } else { - ok(Buffer == NULL, "Wrong. SQIT call is't success. But Buffer != NULL\n"); + ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n"); }
//----------------------------------------------------------------//
Buffer = NULL; Status = SeQueryInformationToken(Token, TokenType, &Buffer); - ok(Status == STATUS_SUCCESS, "SQIT with TokenType fails with status 0x%X\n", Status); - if (Status == STATUS_SUCCESS) - { - ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenType arg. But Buffer = NULL\n"); + ok(Status == STATUS_SUCCESS, "SQIT with TokenType fails with status 0x%08X\n", Status); + if (Status == STATUS_SUCCESS) + { + ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenType arg. But Buffer == NULL\n"); if (Buffer) { TType = (PTOKEN_TYPE)Buffer; ok((*TType == TokenPrimary || *TType == TokenImpersonation), "TokenType in not a primary nor impersonation. FAILED\n"); - ExFreePool(TType); + ExFreePool(Buffer); } }
@@ -169,12 +199,12 @@ ok(Status == STATUS_SUCCESS, "SQIT with TokenUser fails\n"); if (Status == STATUS_SUCCESS) { - ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenUser arg. But Buffer = NULL\n"); + ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenUser arg. But Buffer == NULL\n"); if (Buffer) { TUser = (PTOKEN_USER)Buffer; ok(RtlValidSid(TUser->User.Sid), "TokenUser has an invalid Sid\n"); - ExFreePool(TUser); + ExFreePool(Buffer); } }
@@ -237,7 +267,6 @@
SeCaptureSubjectContext(&AccessState->SubjectSecurityContext); SeLockSubjectContext(&AccessState->SubjectSecurityContext); - Token = SeQuerySubjectContextToken(&AccessState->SubjectSecurityContext);
// Testing SQIT with AccessState Token @@ -295,8 +324,7 @@ // Testing SeFreePrivileges // //----------------------------------------------------------------//
- Privileges = ExAllocatePool(PagedPool, AuxData->PrivilegeSet->PrivilegeCount*sizeof(PRIVILEGE_SET)); - + Privileges = NULL; Checker = SeAccessCheck( AccessState->SecurityDescriptor, &AccessState->SubjectSecurityContext, @@ -311,6 +339,11 @@ ); ok(Checker, "Checker is NULL\n"); ok((Privileges != NULL), "Privileges is NULL\n"); + if (Privileges) + { + trace("AuxData->PrivilegeSet->PrivilegeCount = %d ; Privileges->PrivilegeCount = %d\n", + AuxData->PrivilegeSet->PrivilegeCount, Privileges->PrivilegeCount); + } if (Privileges) SeFreePrivileges(Privileges);
@@ -326,7 +359,7 @@ Status = SeQueryInformationToken(Token, TokenPrivileges, &Buffer); if (Status == STATUS_SUCCESS) { - ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenPrivileges arg. But Buffer = NULL\n"); + ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenPrivileges arg. But Buffer == NULL\n"); if (Buffer) { TPrivileges = (PTOKEN_PRIVILEGES)(Buffer); @@ -351,8 +384,7 @@
// Call SeFreePrivileges again
- Privileges = ExAllocatePool(PagedPool, 20*sizeof(PRIVILEGE_SET)); - + Privileges = NULL; Checker = SeAccessCheck( AccessState->SecurityDescriptor, &AccessState->SubjectSecurityContext, @@ -367,6 +399,11 @@ ); ok(Checker, "Checker is NULL\n"); ok((Privileges != NULL), "Privileges is NULL\n"); + if (Privileges) + { + trace("AuxData->PrivilegeSet->PrivilegeCount = %d ; Privileges->PrivilegeCount = %d\n", + AuxData->PrivilegeSet->PrivilegeCount, Privileges->PrivilegeCount); + } if (Privileges) SeFreePrivileges(Privileges);
//----------------------------------------------------------------//