weiden(a)svn.reactos.com wrote:
Thomas Weidenmueller <w3seek(a)reactos.com>
- Fix various security structures and constants
- Add code to capture quality of service structures and ACLs
- Secure buffer access in NtQueryInformationToken, NtSetInformationToken,
NtNotifyChangeDirectoryFile and NtQueryDirectoryFile
Modified: trunk/reactos/include/ddk/setypes.h
Modified: trunk/reactos/include/ntos/security.h
Modified: trunk/reactos/lib/rtl/sid.c
Modified: trunk/reactos/ntoskrnl/include/internal/ob.h
Modified: trunk/reactos/ntoskrnl/include/internal/se.h
Modified: trunk/reactos/ntoskrnl/io/dir.c
Modified: trunk/reactos/ntoskrnl/ob/object.c
Modified: trunk/reactos/ntoskrnl/se/acl.c
Modified: trunk/reactos/ntoskrnl/se/luid.c
Modified: trunk/reactos/ntoskrnl/se/sd.c
Modified: trunk/reactos/ntoskrnl/se/sid.c
Modified: trunk/reactos/ntoskrnl/se/token.c
------------------------------------------------------------------------
What didn't make it in the ros-diff:
Index: ntoskrnl/se/sid.c
===================================================================
--- ntoskrnl/se/sid.c (.../trunk/reactos) (revision 13937)
+++ ntoskrnl/se/sid.c (.../branches/alex_devel_branch/reactos)
(revision 13942)
@@ -466,4 +466,107 @@
return(TRUE);
}
+NTSTATUS
+SepCaptureSid(IN PSID InputSid,
+ IN KPROCESSOR_MODE AccessMode,
+ IN POOL_TYPE PoolType,
+ IN BOOLEAN CaptureIfKernel,
+ OUT PSID *CapturedSid)
+{
+ ULONG SidSize = 0;
+ PISID NewSid, Sid = (PISID)InputSid;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ if(AccessMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForRead(Sid,
+ sizeof(*Sid) - sizeof(Sid->SubAuthority),
+ sizeof(UCHAR));
+ SidSize = RtlLengthRequiredSid(Sid->SubAuthorityCount);
+ ProbeForRead(Sid,
+ SidSize,
+ sizeof(UCHAR));
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(NT_SUCCESS(Status))
+ {
+ /* allocate a SID and copy it */
+ NewSid = ExAllocatePool(PoolType,
+ SidSize);
+ if(NewSid != NULL)
+ {
+ _SEH_TRY
+ {
+ RtlCopyMemory(NewSid,
+ Sid,
+ SidSize);
+
+ *CapturedSid = NewSid;
+ }
+ _SEH_HANDLE
+ {
+ ExFreePool(NewSid);
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+ else
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ }
+ else if(!CaptureIfKernel)
+ {
+ *CapturedSid = InputSid;
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ SidSize = RtlLengthRequiredSid(Sid->SubAuthorityCount);
+
+ /* allocate a SID and copy it */
+ NewSid = ExAllocatePool(PoolType,
+ SidSize);
+ if(NewSid != NULL)
+ {
+ RtlCopyMemory(NewSid,
+ Sid,
+ SidSize);
+
+ *CapturedSid = NewSid;
+ }
+ else
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ return Status;
+}
+
+VOID
+SepReleaseSid(IN PSID CapturedSid,
+ IN KPROCESSOR_MODE AccessMode,
+ IN BOOLEAN CaptureIfKernel)
+{
+ PAGED_CODE();
+
+ if(CapturedSid != NULL &&
+ (AccessMode == UserMode ||
+ (AccessMode == KernelMode && CaptureIfKernel)))
+ {
+ ExFreePool(CapturedSid);
+ }
+}
+
/* EOF */
Index: ntoskrnl/se/token.c
===================================================================
--- ntoskrnl/se/token.c (.../trunk/reactos) (revision 13937)
+++ ntoskrnl/se/token.c (.../branches/alex_devel_branch/reactos)
(revision 13942)
@@ -18,12 +18,54 @@
/* GLOBALS
*******************************************************************/
POBJECT_TYPE SepTokenObjectType = NULL;
+ERESOURCE SepTokenLock;
static GENERIC_MAPPING SepTokenMapping = {TOKEN_READ,
TOKEN_WRITE,
TOKEN_EXECUTE,
TOKEN_ALL_ACCESS};
+static const INFORMATION_CLASS_INFO SeTokenInformationClass[] = {
+
+ /* Class 0 not used, blame M$! */
+ ICI_SQ_SAME( 0, 0, 0),
+
+ /* TokenUser */
+ ICI_SQ_SAME( sizeof(TOKEN_USER), sizeof(ULONG),
ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
+ /* TokenGroups */
+ ICI_SQ_SAME( sizeof(TOKEN_GROUPS), sizeof(ULONG),
ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
+ /* TokenPrivileges */
+ ICI_SQ_SAME( sizeof(TOKEN_PRIVILEGES), sizeof(ULONG),
ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
+ /* TokenOwner */
+ ICI_SQ_SAME( sizeof(TOKEN_OWNER), sizeof(ULONG),
ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
+ /* TokenPrimaryGroup */
+ ICI_SQ_SAME( sizeof(TOKEN_PRIMARY_GROUP), sizeof(ULONG),
ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
+ /* TokenDefaultDacl */
+ ICI_SQ_SAME( sizeof(TOKEN_DEFAULT_DACL), sizeof(ULONG),
ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
+ /* TokenSource */
+ ICI_SQ_SAME( sizeof(TOKEN_SOURCE), sizeof(ULONG),
ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
+ /* TokenType */
+ ICI_SQ_SAME( sizeof(TOKEN_TYPE), sizeof(ULONG),
ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
+ /* TokenImpersonationLevel */
+ ICI_SQ_SAME( sizeof(SECURITY_IMPERSONATION_LEVEL), sizeof(ULONG),
ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
+ /* TokenStatistics */
+ ICI_SQ_SAME( sizeof(TOKEN_STATISTICS), sizeof(ULONG),
ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
+ /* TokenRestrictedSids */
+ ICI_SQ_SAME( sizeof(TOKEN_GROUPS), sizeof(ULONG),
ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
+ /* TokenSessionId */
+ ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG),
ICIF_QUERY | ICIF_SET ),
+ /* TokenGroupsAndPrivileges */
+ ICI_SQ_SAME( sizeof(TOKEN_GROUPS_AND_PRIVILEGES), sizeof(ULONG),
ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
+ /* TokenSessionReference */
+ ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG),
ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
+ /* TokenSandBoxInert */
+ ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG),
ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
+ /* TokenAuditPolicy */
+ ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG),
ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
+ /* TokenOrigin */
+ ICI_SQ_SAME( sizeof(TOKEN_ORIGIN), sizeof(ULONG),
ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
+};
+
/* FUNCTIONS
*****************************************************************/
VOID SepFreeProxyData(PVOID ProxyData)
@@ -140,6 +182,8 @@
PVOID EndMem;
PTOKEN AccessToken;
NTSTATUS Status;
+
+ PAGED_CODE();
Status = ObCreateObject(PreviousMode,
SepTokenObjectType,
@@ -170,6 +214,8 @@
return(Status);
}
+ AccessToken->TokenLock = &SepTokenLock;
+
AccessToken->TokenInUse = 0;
AccessToken->TokenType = TokenType;
AccessToken->ImpersonationLevel = Level;
@@ -189,7 +235,7 @@
uLength += RtlLengthSid(Token->UserAndGroups[i].Sid);
AccessToken->UserAndGroups =
- (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
+ (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
uLength,
TAG('T', 'O', 'K', 'u'));
@@ -216,7 +262,7 @@
uLength = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
AccessToken->Privileges =
- (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
+ (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
uLength,
TAG('T', 'O', 'K', 'p'));
@@ -231,7 +277,7 @@
if ( Token->DefaultDacl )
{
AccessToken->DefaultDacl =
- (PACL) ExAllocatePoolWithTag(NonPagedPool,
+ (PACL) ExAllocatePoolWithTag(PagedPool,
Token->DefaultDacl->AclSize,
TAG('T', 'O', 'K', 'd'));
memcpy(AccessToken->DefaultDacl,
@@ -534,6 +580,8 @@
VOID INIT_FUNCTION
SepInitializeTokenImplementation(VOID)
{
+ ExInitializeResource(&SepTokenLock);
+
SepTokenObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
SepTokenObjectType->Tag = TAG('T', 'O', 'K', 'T');
@@ -555,8 +603,7 @@
SepTokenObjectType->Create = NULL;
SepTokenObjectType->DuplicationNotify = NULL;
- RtlpCreateUnicodeString(&SepTokenObjectType->TypeName,
- L"Token", NonPagedPool);
+ RtlInitUnicodeString(&SepTokenObjectType->TypeName, L"Token");
ObpCreateTypeObject (SepTokenObjectType);
}
@@ -571,266 +618,456 @@
IN ULONG TokenInformationLength,
OUT PULONG ReturnLength)
{
- NTSTATUS Status, LengthStatus;
- PVOID UnusedInfo;
- PVOID EndMem;
+ union
+ {
+ PVOID Ptr;
+ ULONG Ulong;
+ } Unused;
PTOKEN Token;
- ULONG Length;
- PTOKEN_GROUPS PtrTokenGroups;
- PTOKEN_DEFAULT_DACL PtrDefaultDacl;
- PTOKEN_STATISTICS PtrTokenStatistics;
+ ULONG RequiredLength;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
+
+ PreviousMode = ExGetPreviousMode();
+
+ /* Check buffers and class validity */
+ DefaultQueryInfoBufferCheck(TokenInformationClass,
+ SeTokenInformationClass,
+ TokenInformation,
+ TokenInformationLength,
+ ReturnLength,
+ PreviousMode,
+ &Status);
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status);
+ return Status;
+ }
+
Status = ObReferenceObjectByHandle(TokenHandle,
(TokenInformationClass == TokenSource) ?
TOKEN_QUERY_SOURCE : TOKEN_QUERY,
SepTokenObjectType,
- UserMode,
+ PreviousMode,
(PVOID*)&Token,
NULL);
- if (!NT_SUCCESS(Status))
+ if (NT_SUCCESS(Status))
+ {
+ switch (TokenInformationClass)
{
- return(Status);
- }
+ case TokenUser:
+ {
+ PTOKEN_USER tu = (PTOKEN_USER)TokenInformation;
+
+ DPRINT("NtQueryInformationToken(TokenUser)\n");
+ RequiredLength = sizeof(TOKEN_USER) +
+ RtlLengthSid(Token->UserAndGroups[0].Sid);
- switch (TokenInformationClass)
- {
- case TokenUser:
- DPRINT("NtQueryInformationToken(TokenUser)\n");
- Length = RtlLengthSidAndAttributes(1, Token->UserAndGroups);
- if (TokenInformationLength < Length)
- {
- Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
- if (NT_SUCCESS(Status))
- Status = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- Status = RtlCopySidAndAttributesArray(1,
- Token->UserAndGroups,
- TokenInformationLength,
- TokenInformation,
- (char*)TokenInformation + 8,
- &UnusedInfo,
- &Length);
- if (NT_SUCCESS(Status))
- {
- Length = TokenInformationLength - Length;
- Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
- }
- }
- break;
+ _SEH_TRY
+ {
+ if(TokenInformationLength >= RequiredLength)
+ {
+ Status = RtlCopySidAndAttributesArray(1,
+ &Token->UserAndGroups[0],
+ RequiredLength -
sizeof(TOKEN_USER),
+ &tu->User,
+ (PSID)(tu + 1),
+ &Unused.Ptr,
+ &Unused.Ulong);
+ }
+ else
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ if(ReturnLength != NULL)
+ {
+ *ReturnLength = RequiredLength;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ break;
+ }
case TokenGroups:
- DPRINT("NtQueryInformationToken(TokenGroups)\n");
- Length = RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1,
&Token->UserAndGroups[1]) + sizeof(ULONG);
- if (TokenInformationLength < Length)
- {
- Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
- if (NT_SUCCESS(Status))
- Status = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- EndMem = (char*)TokenInformation + Token->UserAndGroupCount *
sizeof(SID_AND_ATTRIBUTES);
- PtrTokenGroups = (PTOKEN_GROUPS)TokenInformation;
- PtrTokenGroups->GroupCount = Token->UserAndGroupCount - 1;
- Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
- &Token->UserAndGroups[1],
- TokenInformationLength,
- PtrTokenGroups->Groups,
- EndMem,
- &UnusedInfo,
- &Length);
- if (NT_SUCCESS(Status))
- {
- Length = TokenInformationLength - Length;
- Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
- }
- }
- break;
+ {
+ PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
+
+ DPRINT("NtQueryInformationToken(TokenGroups)\n");
+ RequiredLength = sizeof(tg->GroupCount) +
+
RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1,
&Token->UserAndGroups[1]);
- case TokenPrivileges:
- DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
- Length = sizeof(ULONG) + Token->PrivilegeCount *
sizeof(LUID_AND_ATTRIBUTES);
- if (TokenInformationLength < Length)
- {
- Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
- if (NT_SUCCESS(Status))
- Status = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- ULONG i;
- TOKEN_PRIVILEGES* pPriv = (TOKEN_PRIVILEGES*)TokenInformation;
+ _SEH_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)));
- pPriv->PrivilegeCount = Token->PrivilegeCount;
- for (i = 0; i < Token->PrivilegeCount; i++)
- {
- RtlCopyLuid(&pPriv->Privileges[i].Luid,
&Token->Privileges[i].Luid);
- pPriv->Privileges[i].Attributes = Token->Privileges[i].Attributes;
- }
- Status = STATUS_SUCCESS;
- }
+ tg->GroupCount = Token->UserAndGroupCount - 1;
+ Status =
RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
+ &Token->UserAndGroups[1],
+ SidLen,
+ &tg->Groups[0],
+ (PSID)Sid,
+ &Unused.Ptr,
+ &Unused.Ulong);
+ }
+ else
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ if(ReturnLength != NULL)
+ {
+ *ReturnLength = RequiredLength;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
break;
+ }
+
+ case TokenPrivileges:
+ {
+ PTOKEN_PRIVILEGES tp = (PTOKEN_PRIVILEGES)TokenInformation;
+
+ DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
+ RequiredLength = sizeof(tp->PrivilegeCount) +
+ (Token->PrivilegeCount *
sizeof(LUID_AND_ATTRIBUTES));
+ _SEH_TRY
+ {
+ if(TokenInformationLength >= RequiredLength)
+ {
+ tp->PrivilegeCount = Token->PrivilegeCount;
+ RtlCopyLuidAndAttributesArray(Token->PrivilegeCount,
+ Token->Privileges,
+ &tp->Privileges[0]);
+ }
+ else
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ if(ReturnLength != NULL)
+ {
+ *ReturnLength = RequiredLength;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ break;
+ }
+
case TokenOwner:
- DPRINT("NtQueryInformationToken(TokenOwner)\n");
- Length =
RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid) +
sizeof(TOKEN_OWNER);
- if (TokenInformationLength < Length)
- {
- Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
- if (NT_SUCCESS(Status))
- Status = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- ((PTOKEN_OWNER)TokenInformation)->Owner =
- (PSID)(((PTOKEN_OWNER)TokenInformation) + 1);
- RtlCopySid(TokenInformationLength - sizeof(TOKEN_OWNER),
- ((PTOKEN_OWNER)TokenInformation)->Owner,
- Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
- Status = STATUS_SUCCESS;
- }
- break;
+ {
+ ULONG SidLen;
+ PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
+
+ DPRINT("NtQueryInformationToken(TokenOwner)\n");
+ SidLen =
RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
+ RequiredLength = sizeof(TOKEN_OWNER) + SidLen;
+ _SEH_TRY
+ {
+ if(TokenInformationLength >= RequiredLength)
+ {
+ to->Owner = (PSID)(to + 1);
+ Status = RtlCopySid(SidLen,
+ to->Owner,
+
Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
+ }
+ else
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ if(ReturnLength != NULL)
+ {
+ *ReturnLength = RequiredLength;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ break;
+ }
+
case TokenPrimaryGroup:
- DPRINT("NtQueryInformationToken(TokenPrimaryGroup),"
- "Token->PrimaryGroup = 0x%08x\n", Token->PrimaryGroup);
- Length = RtlLengthSid(Token->PrimaryGroup) +
sizeof(TOKEN_PRIMARY_GROUP);
- if (TokenInformationLength < Length)
- {
- Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
- if (NT_SUCCESS(Status))
- Status = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- ((PTOKEN_PRIMARY_GROUP)TokenInformation)->PrimaryGroup =
- (PSID)(((PTOKEN_PRIMARY_GROUP)TokenInformation) + 1);
- RtlCopySid(TokenInformationLength - sizeof(TOKEN_PRIMARY_GROUP),
- ((PTOKEN_PRIMARY_GROUP)TokenInformation)->PrimaryGroup,
- Token->PrimaryGroup);
- Status = STATUS_SUCCESS;
- }
- break;
+ {
+ ULONG SidLen;
+ PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
+ DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
+ SidLen = RtlLengthSid(Token->PrimaryGroup);
+ RequiredLength = sizeof(TOKEN_PRIMARY_GROUP) + SidLen;
+
+ _SEH_TRY
+ {
+ if(TokenInformationLength >= RequiredLength)
+ {
+ tpg->PrimaryGroup = (PSID)(tpg + 1);
+ Status = RtlCopySid(SidLen,
+ tpg->PrimaryGroup,
+ Token->PrimaryGroup);
+ }
+ else
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ if(ReturnLength != NULL)
+ {
+ *ReturnLength = RequiredLength;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ break;
+ }
+
case TokenDefaultDacl:
- DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
- PtrDefaultDacl = (PTOKEN_DEFAULT_DACL) TokenInformation;
- Length = (Token->DefaultDacl ? Token->DefaultDacl->AclSize : 0) +
sizeof(TOKEN_DEFAULT_DACL);
- if (TokenInformationLength < Length)
- {
- Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
- if (NT_SUCCESS(Status))
- Status = STATUS_BUFFER_TOO_SMALL;
- }
- else if (!Token->DefaultDacl)
- {
- PtrDefaultDacl->DefaultDacl = 0;
- Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
- }
- else
- {
- PtrDefaultDacl->DefaultDacl = (PACL) (PtrDefaultDacl + 1);
- memmove(PtrDefaultDacl->DefaultDacl,
- Token->DefaultDacl,
- Token->DefaultDacl->AclSize);
- Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
- }
- break;
+ {
+ PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
+ DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
+ RequiredLength = sizeof(TOKEN_DEFAULT_DACL);
+
+ if(Token->DefaultDacl != NULL)
+ {
+ RequiredLength += Token->DefaultDacl->AclSize;
+ }
+
+ _SEH_TRY
+ {
+ if(TokenInformationLength >= RequiredLength)
+ {
+ if(Token->DefaultDacl != NULL)
+ {
+ tdd->DefaultDacl = (PACL)(tdd + 1);
+ RtlCopyMemory(tdd->DefaultDacl,
+ Token->DefaultDacl,
+ Token->DefaultDacl->AclSize);
+ }
+ else
+ {
+ tdd->DefaultDacl = NULL;
+ }
+ }
+ else
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ if(ReturnLength != NULL)
+ {
+ *ReturnLength = RequiredLength;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ break;
+ }
+
case TokenSource:
- DPRINT("NtQueryInformationToken(TokenSource)\n");
- if (TokenInformationLength < sizeof(TOKEN_SOURCE))
- {
- Length = sizeof(TOKEN_SOURCE);
- Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
- if (NT_SUCCESS(Status))
- Status = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- Status = MmCopyToCaller(TokenInformation, &Token->TokenSource,
sizeof(TOKEN_SOURCE));
- }
- break;
+ {
+ PTOKEN_SOURCE ts = (PTOKEN_SOURCE)TokenInformation;
+ DPRINT("NtQueryInformationToken(TokenSource)\n");
+ RequiredLength = sizeof(TOKEN_SOURCE);
+
+ _SEH_TRY
+ {
+ if(TokenInformationLength >= RequiredLength)
+ {
+ *ts = Token->TokenSource;
+ }
+ else
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ if(ReturnLength != NULL)
+ {
+ *ReturnLength = RequiredLength;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ break;
+ }
+
case TokenType:
- DPRINT("NtQueryInformationToken(TokenType)\n");
- if (TokenInformationLength < sizeof(TOKEN_TYPE))
- {
- Length = sizeof(TOKEN_TYPE);
- Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
- if (NT_SUCCESS(Status))
- Status = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- Status = MmCopyToCaller(TokenInformation, &Token->TokenType,
sizeof(TOKEN_TYPE));
- }
- break;
+ {
+ PTOKEN_TYPE tt = (PTOKEN_TYPE)TokenInformation;
+ DPRINT("NtQueryInformationToken(TokenType)\n");
+ RequiredLength = sizeof(TOKEN_TYPE);
+
+ _SEH_TRY
+ {
+ if(TokenInformationLength >= RequiredLength)
+ {
+ *tt = Token->TokenType;
+ }
+ else
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ if(ReturnLength != NULL)
+ {
+ *ReturnLength = RequiredLength;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ break;
+ }
+
case TokenImpersonationLevel:
- DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
- if (TokenInformationLength < sizeof(SECURITY_IMPERSONATION_LEVEL))
- {
- Length = sizeof(SECURITY_IMPERSONATION_LEVEL);
- Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
- if (NT_SUCCESS(Status))
- Status = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- Status = MmCopyToCaller(TokenInformation,
&Token->ImpersonationLevel, sizeof(SECURITY_IMPERSONATION_LEVEL));
- }
- break;
+ {
+ PSECURITY_IMPERSONATION_LEVEL sil =
(PSECURITY_IMPERSONATION_LEVEL)TokenInformation;
+ DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
+ RequiredLength = sizeof(SECURITY_IMPERSONATION_LEVEL);
+
+ _SEH_TRY
+ {
+ if(TokenInformationLength >= RequiredLength)
+ {
+ *sil = Token->ImpersonationLevel;
+ }
+ else
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ if(ReturnLength != NULL)
+ {
+ *ReturnLength = RequiredLength;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ break;
+ }
+
case TokenStatistics:
- DPRINT("NtQueryInformationToken(TokenStatistics)\n");
- if (TokenInformationLength < sizeof(TOKEN_STATISTICS))
- {
- Length = sizeof(TOKEN_STATISTICS);
- Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
- if (NT_SUCCESS(Status))
- Status = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- PtrTokenStatistics = (PTOKEN_STATISTICS)TokenInformation;
- PtrTokenStatistics->TokenId = Token->TokenId;
- PtrTokenStatistics->AuthenticationId = Token->AuthenticationId;
- PtrTokenStatistics->ExpirationTime = Token->ExpirationTime;
- PtrTokenStatistics->TokenType = Token->TokenType;
- PtrTokenStatistics->ImpersonationLevel = Token->ImpersonationLevel;
- PtrTokenStatistics->DynamicCharged = Token->DynamicCharged;
- PtrTokenStatistics->DynamicAvailable = Token->DynamicAvailable;
- PtrTokenStatistics->GroupCount = Token->UserAndGroupCount - 1;
- PtrTokenStatistics->PrivilegeCount = Token->PrivilegeCount;
- PtrTokenStatistics->ModifiedId = Token->ModifiedId;
+ {
+ PTOKEN_STATISTICS ts = (PTOKEN_STATISTICS)TokenInformation;
- Status = STATUS_SUCCESS;
- }
- break;
+ DPRINT("NtQueryInformationToken(TokenStatistics)\n");
+ RequiredLength = sizeof(TOKEN_STATISTICS);
+ _SEH_TRY
+ {
+ if(TokenInformationLength >= RequiredLength)
+ {
+ 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;
+ }
+ else
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ if(ReturnLength != NULL)
+ {
+ *ReturnLength = RequiredLength;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ break;
+ }
+
case TokenOrigin:
- DPRINT("NtQueryInformationToken(TokenOrigin)\n");
- if (TokenInformationLength < sizeof(TOKEN_ORIGIN))
- {
- Status = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- Status =
MmCopyToCaller(&((PTOKEN_ORIGIN)TokenInformation)->OriginatingLogonSession,
- &Token->AuthenticationId, sizeof(LUID));
- }
- Length = sizeof(TOKEN_ORIGIN);
- LengthStatus = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
- if (NT_SUCCESS(Status))
- {
- Status = LengthStatus;
- }
- break;
+ {
+ PTOKEN_ORIGIN to = (PTOKEN_ORIGIN)TokenInformation;
+ DPRINT("NtQueryInformationToken(TokenOrigin)\n");
+ RequiredLength = sizeof(TOKEN_ORIGIN);
+
+ _SEH_TRY
+ {
+ if(TokenInformationLength >= RequiredLength)
+ {
+ RtlCopyLuid(&to->OriginatingLogonSession,
+ &Token->AuthenticationId);
+ }
+ else
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ if(ReturnLength != NULL)
+ {
+ *ReturnLength = RequiredLength;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ break;
+ }
+
case TokenGroupsAndPrivileges:
DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not
implemented\n");
Status = STATUS_NOT_IMPLEMENTED;
@@ -847,27 +1084,44 @@
break;
case TokenSessionId:
- DPRINT("NtQueryInformationToken(TokenSessionId)\n");
- if (TokenInformationLength < sizeof(ULONG))
- {
- Length = sizeof(ULONG);
- Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
- if (NT_SUCCESS(Status))
- Status = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- Status = MmCopyToCaller(TokenInformation, &Token->SessionId,
sizeof(ULONG));
- }
- break;
+ {
+ ULONG SessionId = 0;
+ DPRINT("NtQueryInformationToken(TokenSessionId)\n");
+
+ Status = SeQuerySessionIdToken(Token,
+ &SessionId);
+
+ if(NT_SUCCESS(Status))
+ {
+ _SEH_TRY
+ {
+ /* buffer size was already verified, no need to check here
again */
+ *(PULONG)TokenInformation = SessionId;
+
+ if(ReturnLength != NULL)
+ {
+ *ReturnLength = sizeof(ULONG);
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+
+ break;
+ }
+
default:
- DPRINT1("NtQueryInformationToken(%d) invalid parameter\n");
- Status = STATUS_INVALID_PARAMETER;
+ DPRINT1("NtQueryInformationToken(%d) invalid information class\n",
TokenInformationClass);
+ Status = STATUS_INVALID_INFO_CLASS;
break;
}
- ObDereferenceObject(Token);
+ ObDereferenceObject(Token);
+ }
return(Status);
}
@@ -888,7 +1142,7 @@
}
/*
- * @unimplemented
+ * @implemented
*/
NTSTATUS
STDCALL
@@ -897,14 +1151,14 @@
IN PULONG pSessionId
)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ *pSessionId = ((PTOKEN)Token)->SessionId;
+ return STATUS_SUCCESS;
}
/*
* NtSetTokenInformation: Partly implemented.
* Unimplemented:
- * TokenOrigin, TokenDefaultDacl, TokenSessionId
+ * TokenOrigin, TokenDefaultDacl
*/
NTSTATUS STDCALL
@@ -913,123 +1167,229 @@
OUT PVOID TokenInformation,
IN ULONG TokenInformationLength)
{
- NTSTATUS Status;
PTOKEN Token;
- TOKEN_OWNER TokenOwnerSet = { 0 };
- TOKEN_PRIMARY_GROUP TokenPrimaryGroupSet = { 0 };
- DWORD NeededAccess = 0;
+ KPROCESSOR_MODE PreviousMode;
+ ULONG NeededAccess = TOKEN_ADJUST_DEFAULT;
+ NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
+
+ PreviousMode = ExGetPreviousMode();
+
+ DefaultSetInfoBufferCheck(TokenInformationClass,
+ SeTokenInformationClass,
+ TokenInformation,
+ TokenInformationLength,
+ PreviousMode,
+ &Status);
- switch (TokenInformationClass)
- {
- case TokenOwner:
- case TokenPrimaryGroup:
- NeededAccess = TOKEN_ADJUST_DEFAULT;
- break;
+ if(!NT_SUCCESS(Status))
+ {
+ /* Invalid buffers */
+ DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status);
+ return Status;
+ }
+
+ if(TokenInformationClass == TokenSessionId)
+ {
+ NeededAccess |= TOKEN_ADJUST_SESSIONID;
+ }
- case TokenDefaultDacl:
- if (TokenInformationLength < sizeof(TOKEN_DEFAULT_DACL))
- return STATUS_BUFFER_TOO_SMALL;
- NeededAccess = TOKEN_ADJUST_DEFAULT;
- break;
-
- default:
- DPRINT1("NtSetInformationToken: lying about success (stub) -
%x\n", TokenInformationClass);
- return STATUS_SUCCESS;
-
- }
-
Status = ObReferenceObjectByHandle(TokenHandle,
NeededAccess,
SepTokenObjectType,
- UserMode,
+ PreviousMode,
(PVOID*)&Token,
NULL);
- if (!NT_SUCCESS(Status))
+ if (NT_SUCCESS(Status))
+ {
+ switch (TokenInformationClass)
{
- return(Status);
- }
-
- switch (TokenInformationClass)
- {
- case TokenOwner:
- MmCopyFromCaller( &TokenOwnerSet, TokenInformation,
- min(sizeof(TokenOwnerSet),TokenInformationLength) );
- RtlCopySid(TokenInformationLength - sizeof(TOKEN_OWNER),
- Token->UserAndGroups[Token->DefaultOwnerIndex].Sid,
- TokenOwnerSet.Owner);
- Status = STATUS_SUCCESS;
- DPRINT("NtSetInformationToken(TokenOwner)\n");
- break;
+ case TokenOwner:
+ {
+ if(TokenInformationLength >= sizeof(TOKEN_OWNER))
+ {
+ PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
+ PSID InputSid = NULL;
+
+ _SEH_TRY
+ {
+ InputSid = to->Owner;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(NT_SUCCESS(Status))
+ {
+ PSID CapturedSid;
+
+ Status = SepCaptureSid(InputSid,
+ PreviousMode,
+ PagedPool,
+ FALSE,
+ &CapturedSid);
+ if(NT_SUCCESS(Status))
+ {
+ RtlCopySid(RtlLengthSid(CapturedSid),
+
Token->UserAndGroups[Token->DefaultOwnerIndex].Sid,
+ CapturedSid);
+ SepReleaseSid(CapturedSid,
+ PreviousMode,
+ FALSE);
+ }
+ }
+ }
+ else
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ break;
+ }
- case TokenPrimaryGroup:
- MmCopyFromCaller( &TokenPrimaryGroupSet, TokenInformation,
- min(sizeof(TokenPrimaryGroupSet),
- TokenInformationLength) );
- RtlCopySid(TokenInformationLength - sizeof(TOKEN_PRIMARY_GROUP),
- Token->PrimaryGroup,
- TokenPrimaryGroupSet.PrimaryGroup);
- Status = STATUS_SUCCESS;
- DPRINT("NtSetInformationToken(TokenPrimaryGroup),"
- "Token->PrimaryGroup = 0x%08x\n", Token->PrimaryGroup);
- break;
-
- case TokenDefaultDacl:
+ case TokenPrimaryGroup:
{
- TOKEN_DEFAULT_DACL TokenDefaultDacl = { 0 };
- ACL OldAcl;
- PACL NewAcl;
+ if(TokenInformationLength >= sizeof(TOKEN_PRIMARY_GROUP))
+ {
+ PTOKEN_PRIMARY_GROUP tpg =
(PTOKEN_PRIMARY_GROUP)TokenInformation;
+ PSID InputSid = NULL;
- Status = MmCopyFromCaller( &TokenDefaultDacl, TokenInformation,
- sizeof(TOKEN_DEFAULT_DACL) );
- if (!NT_SUCCESS(Status))
+ _SEH_TRY
{
- Status = STATUS_INVALID_PARAMETER;
- break;
+ InputSid = tpg->PrimaryGroup;
}
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
- Status = MmCopyFromCaller( &OldAcl, TokenDefaultDacl.DefaultDacl,
- sizeof(ACL) );
- if (!NT_SUCCESS(Status))
+ if(NT_SUCCESS(Status))
{
- Status = STATUS_INVALID_PARAMETER;
- break;
+ PSID CapturedSid;
+
+ Status = SepCaptureSid(InputSid,
+ PreviousMode,
+ PagedPool,
+ FALSE,
+ &CapturedSid);
+ if(NT_SUCCESS(Status))
+ {
+ RtlCopySid(RtlLengthSid(CapturedSid),
+ Token->PrimaryGroup,
+ CapturedSid);
+ SepReleaseSid(CapturedSid,
+ PreviousMode,
+ FALSE);
+ }
}
+ }
+ else
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ break;
+ }
+
+ case TokenDefaultDacl:
+ {
+ if(TokenInformationLength >= sizeof(TOKEN_DEFAULT_DACL))
+ {
+ PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
+ PACL InputAcl = NULL;
- NewAcl = ExAllocatePool(NonPagedPool, sizeof(ACL));
- if (NewAcl == NULL)
+ _SEH_TRY
{
- Status = STATUS_INSUFFICIENT_RESOURCES;
- break;
+ InputAcl = tdd->DefaultDacl;
}
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
- Status = MmCopyFromCaller( NewAcl, TokenDefaultDacl.DefaultDacl,
- OldAcl.AclSize );
- if (!NT_SUCCESS(Status))
+ if(NT_SUCCESS(Status))
{
- Status = STATUS_INVALID_PARAMETER;
- ExFreePool(NewAcl);
- break;
+ if(InputAcl != NULL)
+ {
+ PACL CapturedAcl;
+
+ /* capture and copy the dacl */
+ Status = SepCaptureAcl(InputAcl,
+ PreviousMode,
+ PagedPool,
+ TRUE,
+ &CapturedAcl);
+ if(NT_SUCCESS(Status))
+ {
+ /* free the previous dacl if present */
+ if(Token->DefaultDacl != NULL)
+ {
+ ExFreePool(Token->DefaultDacl);
+ }
+
+ /* set the new dacl */
+ Token->DefaultDacl = CapturedAcl;
+ }
+ }
+ else
+ {
+ /* clear and free the default dacl if present */
+ if(Token->DefaultDacl != NULL)
+ {
+ ExFreePool(Token->DefaultDacl);
+ Token->DefaultDacl = NULL;
+ }
+ }
}
+ }
+ else
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ break;
+ }
+
+ case TokenSessionId:
+ {
+ ULONG SessionId = 0;
- if (Token->DefaultDacl)
+ _SEH_TRY
+ {
+ /* buffer size was already verified, no need to check here
again */
+ SessionId = *(PULONG)TokenInformation;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(NT_SUCCESS(Status))
+ {
+ if(!SeSinglePrivilegeCheck(SeTcbPrivilege,
+ PreviousMode))
{
- ExFreePool(Token->DefaultDacl);
+ Status = STATUS_PRIVILEGE_NOT_HELD;
+ break;
}
- Token->DefaultDacl = NewAcl;
+ Token->SessionId = SessionId;
+ }
+ break;
+ }
- Status = STATUS_SUCCESS;
+ default:
+ {
+ Status = STATUS_NOT_IMPLEMENTED;
break;
}
-
- default:
- Status = STATUS_NOT_IMPLEMENTED;
- break;
}
- ObDereferenceObject(Token);
+ ObDereferenceObject(Token);
+ }
return(Status);
}
@@ -1045,16 +1405,18 @@
*/
NTSTATUS STDCALL
NtDuplicateToken(IN HANDLE ExistingTokenHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL /*is it really
optional?*/,
- IN BOOLEAN EffectiveOnly,
- IN TOKEN_TYPE TokenType,
- OUT PHANDLE NewTokenHandle)
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN BOOLEAN EffectiveOnly,
+ IN TOKEN_TYPE TokenType,
+ OUT PHANDLE NewTokenHandle)
{
KPROCESSOR_MODE PreviousMode;
HANDLE hToken;
PTOKEN Token;
PTOKEN NewToken;
+ PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService;
+ BOOLEAN QoSPresent;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
@@ -1081,57 +1443,66 @@
}
}
+ Status = SepCaptureSecurityQualityOfService(ObjectAttributes,
+ PreviousMode,
+ PagedPool,
+ FALSE,
+
&CapturedSecurityQualityOfService,
+ &QoSPresent);
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n",
Status);
+ return Status;
+ }
+
Status = ObReferenceObjectByHandle(ExistingTokenHandle,
TOKEN_DUPLICATE,
SepTokenObjectType,
PreviousMode,
(PVOID*)&Token,
NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to reference token (Status %lx)\n", Status);
- return Status;
- }
+ if (NT_SUCCESS(Status))
+ {
+ Status = SepDuplicateToken(Token,
+ ObjectAttributes,
+ EffectiveOnly,
+ TokenType,
+ (QoSPresent ?
CapturedSecurityQualityOfService->ImpersonationLevel : SecurityAnonymous),
+ PreviousMode,
+ &NewToken);
- Status = SepDuplicateToken(Token,
- ObjectAttributes,
- EffectiveOnly,
- TokenType,
- ObjectAttributes->SecurityQualityOfService ?
-
((PSECURITY_QUALITY_OF_SERVICE)(ObjectAttributes->SecurityQualityOfService))->ImpersonationLevel
:
- 0 /*SecurityAnonymous*/,
- PreviousMode,
- &NewToken);
+ ObDereferenceObject(Token);
- ObDereferenceObject(Token);
-
- if (!NT_SUCCESS(Status))
+ if (NT_SUCCESS(Status))
{
- DPRINT1("Failed to duplicate token (Status %lx)\n", Status);
- return Status;
- }
+ Status = ObInsertObject((PVOID)NewToken,
+ NULL,
+ DesiredAccess,
+ 0,
+ NULL,
+ &hToken);
- Status = ObInsertObject((PVOID)NewToken,
- NULL,
- DesiredAccess,
- 0,
- NULL,
- &hToken);
+ ObDereferenceObject(NewToken);
- ObDereferenceObject(NewToken);
-
- if (NT_SUCCESS(Status))
- {
- _SEH_TRY
+ if (NT_SUCCESS(Status))
{
- *NewTokenHandle = hToken;
+ _SEH_TRY
+ {
+ *NewTokenHandle = hToken;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
}
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
}
+ }
+
+ /* free the captured structure */
+ SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
+ PreviousMode,
+ FALSE);
return Status;
}
@@ -1408,6 +1779,8 @@
NTSTATUS Status;
ULONG uSize;
ULONG i;
+
+ PAGED_CODE();
ULONG uLocalSystemLength = RtlLengthSid(SeLocalSystemSid);
ULONG uWorldLength = RtlLengthSid(SeWorldSid);
@@ -1456,6 +1829,8 @@
return Status;
}
+ AccessToken->TokenLock = &SepTokenLock;
+
AccessToken->TokenType = TokenPrimary;
AccessToken->ImpersonationLevel = SecurityDelegation;
AccessToken->TokenSource.SourceIdentifier.LowPart = 0;
@@ -1706,6 +2081,8 @@
return(Status);
}
+ AccessToken->TokenLock = &SepTokenLock;
+
RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
&TokenSource->SourceIdentifier);
memcpy(AccessToken->TokenSource.SourceName,
@@ -1738,7 +2115,7 @@
uLength += RtlLengthSid(TokenGroups->Groups[i].Sid);
AccessToken->UserAndGroups =
- (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
+ (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
uLength,
TAG('T', 'O', 'K', 'u'));
@@ -1774,7 +2151,7 @@
{
uLength = TokenPrivileges->PrivilegeCount *
sizeof(LUID_AND_ATTRIBUTES);
AccessToken->Privileges =
- (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
+ (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
uLength,
TAG('T', 'O', 'K', 'p'));
@@ -1791,7 +2168,7 @@
if (NT_SUCCESS(Status))
{
AccessToken->DefaultDacl =
- (PACL) ExAllocatePoolWithTag(NonPagedPool,
+ (PACL) ExAllocatePoolWithTag(PagedPool,
TokenDefaultDacl->DefaultDacl->AclSize,
TAG('T', 'O', 'K', 'd'));
memcpy(AccessToken->DefaultDacl,
Index: ntoskrnl/se/sd.c
===================================================================
--- ntoskrnl/se/sd.c (.../trunk/reactos) (revision 13937)
+++ ntoskrnl/se/sd.c (.../branches/alex_devel_branch/reactos)
(revision 13942)
@@ -108,6 +108,174 @@
return TRUE;
}
+
+NTSTATUS
+SepCaptureSecurityQualityOfService(IN POBJECT_ATTRIBUTES
ObjectAttributes OPTIONAL,
+ IN KPROCESSOR_MODE AccessMode,
+ IN POOL_TYPE PoolType,
+ IN BOOLEAN CaptureIfKernel,
+ OUT PSECURITY_QUALITY_OF_SERVICE
*CapturedSecurityQualityOfService,
+ OUT PBOOLEAN Present)
+{
+ PSECURITY_QUALITY_OF_SERVICE CapturedQos;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ ASSERT(CapturedSecurityQualityOfService);
+ ASSERT(Present);
+
+ if(ObjectAttributes != NULL)
+ {
+ if(AccessMode != KernelMode)
+ {
+ SECURITY_QUALITY_OF_SERVICE SafeQos;
+
+ _SEH_TRY
+ {
+ ProbeForRead(ObjectAttributes,
+ sizeof(ObjectAttributes),
+ sizeof(ULONG));
+ if(ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
+ {
+ if(ObjectAttributes->SecurityQualityOfService != NULL)
+ {
+ ProbeForRead(ObjectAttributes->SecurityQualityOfService,
+ sizeof(SECURITY_QUALITY_OF_SERVICE),
+ sizeof(ULONG));
+
+
if(((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length
==
+ sizeof(SECURITY_QUALITY_OF_SERVICE))
+ {
+ /* don't allocate memory here because ExAllocate should
bugcheck
+ the system if it's buggy, SEH would catch that! So
make a local
+ copy of the qos structure.*/
+ RtlCopyMemory(&SafeQos,
+ ObjectAttributes->SecurityQualityOfService,
+ sizeof(SECURITY_QUALITY_OF_SERVICE));
+ *Present = TRUE;
+ }
+ else
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ }
+ else
+ {
+ *CapturedSecurityQualityOfService = NULL;
+ *Present = FALSE;
+ }
+ }
+ else
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(NT_SUCCESS(Status))
+ {
+ if(*Present)
+ {
+ CapturedQos = ExAllocatePool(PoolType,
+
sizeof(SECURITY_QUALITY_OF_SERVICE));
+ if(CapturedQos != NULL)
+ {
+ RtlCopyMemory(CapturedQos,
+ &SafeQos,
+ sizeof(SECURITY_QUALITY_OF_SERVICE));
+ *CapturedSecurityQualityOfService = CapturedQos;
+ }
+ else
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ else
+ {
+ *CapturedSecurityQualityOfService = NULL;
+ }
+ }
+ }
+ else
+ {
+ if(ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
+ {
+ if(CaptureIfKernel)
+ {
+ if(ObjectAttributes->SecurityQualityOfService != NULL)
+ {
+
if(((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length
==
+ sizeof(SECURITY_QUALITY_OF_SERVICE))
+ {
+ CapturedQos = ExAllocatePool(PoolType,
+
sizeof(SECURITY_QUALITY_OF_SERVICE));
+ if(CapturedQos != NULL)
+ {
+ RtlCopyMemory(CapturedQos,
+ ObjectAttributes->SecurityQualityOfService,
+ sizeof(SECURITY_QUALITY_OF_SERVICE));
+ *CapturedSecurityQualityOfService = CapturedQos;
+ *Present = TRUE;
+ }
+ else
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ else
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ }
+ else
+ {
+ *CapturedSecurityQualityOfService = NULL;
+ *Present = FALSE;
+ }
+ }
+ else
+ {
+ *CapturedSecurityQualityOfService =
(PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService;
+ *Present = (ObjectAttributes->SecurityQualityOfService != NULL);
+ }
+ }
+ else
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ }
+ }
+ else
+ {
+ *CapturedSecurityQualityOfService = NULL;
+ *Present = FALSE;
+ }
+
+ return Status;
+}
+
+
+VOID
+SepReleaseSecurityQualityOfService(IN PSECURITY_QUALITY_OF_SERVICE
CapturedSecurityQualityOfService OPTIONAL,
+ IN KPROCESSOR_MODE AccessMode,
+ IN BOOLEAN CaptureIfKernel)
+{
+ PAGED_CODE();
+
+ if(CapturedSecurityQualityOfService != NULL &&
+ (AccessMode == UserMode ||
+ (AccessMode == KernelMode && CaptureIfKernel)))
+ {
+ ExFreePool(CapturedSecurityQualityOfService);
+ }
+}
+
+
/*
* @implemented
*/
@@ -129,6 +297,8 @@
ULONG DescriptorSize = 0;
NTSTATUS Status = STATUS_SUCCESS;
+ PAGED_CODE();
+
if(OriginalSecurityDescriptor != NULL)
{
if(CurrentMode != KernelMode)
@@ -144,39 +314,40 @@
DescriptorSize,
sizeof(ULONG));
- if(OriginalSecurityDescriptor->Revision !=
SECURITY_DESCRIPTOR_REVISION1)
+ if(OriginalSecurityDescriptor->Revision ==
SECURITY_DESCRIPTOR_REVISION1)
{
- Status = STATUS_UNKNOWN_REVISION;
- _SEH_LEAVE;
- }
-
- /* make a copy on the stack */
- DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision;
- DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1;
- DescriptorCopy.Control = OriginalSecurityDescriptor->Control;
- DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ?
- sizeof(SECURITY_DESCRIPTOR_RELATIVE) :
sizeof(SECURITY_DESCRIPTOR));
+ /* make a copy on the stack */
+ DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision;
+ DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1;
+ DescriptorCopy.Control = OriginalSecurityDescriptor->Control;
+ DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ?
+ sizeof(SECURITY_DESCRIPTOR_RELATIVE) :
sizeof(SECURITY_DESCRIPTOR));
- /* probe and copy the entire security descriptor structure. The
SIDs
- and ACLs will be probed and copied later though */
- ProbeForRead(OriginalSecurityDescriptor,
- DescriptorSize,
- sizeof(ULONG));
- if(DescriptorCopy.Control & SE_SELF_RELATIVE)
- {
- PSECURITY_DESCRIPTOR_RELATIVE RelSD =
(PSECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor;
-
- DescriptorCopy.Owner = (PSID)RelSD->Owner;
- DescriptorCopy.Group = (PSID)RelSD->Group;
- DescriptorCopy.Sacl = (PACL)RelSD->Sacl;
- DescriptorCopy.Dacl = (PACL)RelSD->Dacl;
+ /* probe and copy the entire security descriptor structure.
The SIDs
+ and ACLs will be probed and copied later though */
+ ProbeForRead(OriginalSecurityDescriptor,
+ DescriptorSize,
+ sizeof(ULONG));
+ if(DescriptorCopy.Control & SE_SELF_RELATIVE)
+ {
+ PSECURITY_DESCRIPTOR_RELATIVE RelSD =
(PSECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor;
+
+ DescriptorCopy.Owner = (PSID)RelSD->Owner;
+ DescriptorCopy.Group = (PSID)RelSD->Group;
+ DescriptorCopy.Sacl = (PACL)RelSD->Sacl;
+ DescriptorCopy.Dacl = (PACL)RelSD->Dacl;
+ }
+ else
+ {
+ DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner;
+ DescriptorCopy.Group = OriginalSecurityDescriptor->Group;
+ DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl;
+ DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl;
+ }
}
else
{
- DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner;
- DescriptorCopy.Group = OriginalSecurityDescriptor->Group;
- DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl;
- DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl;
+ Status = STATUS_UNKNOWN_REVISION;
}
}
_SEH_HANDLE
@@ -572,6 +743,8 @@
IN BOOLEAN CaptureIfKernelMode
)
{
+ PAGED_CODE();
+
/* WARNING! You need to call this function with the same value for
CurrentMode
and CaptureIfKernelMode that you previously passed to
SeCaptureSecurityDescriptor() in order to avoid memory
leaks! */