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?re…
==============================================================================
--- 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=7312…
==============================================================================
--- 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=73…
==============================================================================
--- 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=7312…
==============================================================================
--- 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/testli…
==============================================================================
--- 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/SeQueryIn…
==============================================================================
--- 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);
//----------------------------------------------------------------//