-/* $Id: token.c,v 1.14 2002/02/22 13:36:24 ekohl Exp $
+/* $Id: token.c,v 1.37 2004/07/13 08:43:35 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
/* INCLUDES *****************************************************************/
#include <limits.h>
-#include <ddk/ntddk.h>
+#define NTOS_MODE_KERNEL
+#include <ntos.h>
+#include <internal/ob.h>
#include <internal/ps.h>
#include <internal/se.h>
+#include <internal/safe.h>
+#define NDEBUG
#include <internal/debug.h>
/* GLOBALS *******************************************************************/
TOKEN_EXECUTE,
TOKEN_ALL_ACCESS};
+#define SYSTEM_LUID 0x3E7;
+
/* FUNCTIONS *****************************************************************/
VOID SepFreeProxyData(PVOID ProxyData)
NTSTATUS SepCopyProxyData(PVOID* Dest, PVOID Src)
{
UNIMPLEMENTED;
+ return(STATUS_NOT_IMPLEMENTED);
}
NTSTATUS SeExchangePrimaryToken(PEPROCESS Process,
return(STATUS_SUCCESS);
}
-NTSTATUS SepDuplicationToken(PACCESS_TOKEN Token,
- POBJECT_ATTRIBUTES ObjectAttributes,
- TOKEN_TYPE TokenType,
- SECURITY_IMPERSONATION_LEVEL Level,
- SECURITY_IMPERSONATION_LEVEL ExistingLevel,
- KPROCESSOR_MODE PreviousMode,
- PACCESS_TOKEN* NewAccessToken)
+static ULONG
+RtlLengthSidAndAttributes(ULONG Count,
+ PSID_AND_ATTRIBUTES Src)
{
- UNIMPLEMENTED;
+ ULONG i;
+ ULONG uLength;
+
+ uLength = Count * sizeof(SID_AND_ATTRIBUTES);
+ for (i = 0; i < Count; i++)
+ uLength += RtlLengthSid(Src[i].Sid);
+
+ return(uLength);
+}
+
+
+NTSTATUS
+SepFindPrimaryGroupAndDefaultOwner(PACCESS_TOKEN Token,
+ PSID PrimaryGroup,
+ PSID DefaultOwner)
+{
+ ULONG i;
+
+ Token->PrimaryGroup = 0;
+
+ if (DefaultOwner)
+ {
+ Token->DefaultOwnerIndex = Token->UserAndGroupCount;
+ }
+
+ /* Validate and set the primary group and user pointers */
+ for (i = 0; i < Token->UserAndGroupCount; i++)
+ {
+ if (DefaultOwner &&
+ RtlEqualSid(Token->UserAndGroups[i].Sid, DefaultOwner))
+ {
+ Token->DefaultOwnerIndex = i;
+ }
+
+ if (RtlEqualSid(Token->UserAndGroups[i].Sid, PrimaryGroup))
+ {
+ Token->PrimaryGroup = Token->UserAndGroups[i].Sid;
+ }
+ }
+
+ if (Token->DefaultOwnerIndex == Token->UserAndGroupCount)
+ {
+ return(STATUS_INVALID_OWNER);
+ }
+
+ if (Token->PrimaryGroup == 0)
+ {
+ return(STATUS_INVALID_PRIMARY_GROUP);
+ }
+
+ return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS
+SepDuplicateToken(PACCESS_TOKEN Token,
+ POBJECT_ATTRIBUTES ObjectAttributes,
+ TOKEN_TYPE TokenType,
+ SECURITY_IMPERSONATION_LEVEL Level,
+ SECURITY_IMPERSONATION_LEVEL ExistingLevel,
+ KPROCESSOR_MODE PreviousMode,
+ PACCESS_TOKEN* NewAccessToken)
+{
+ NTSTATUS Status;
+ ULONG uLength;
+ ULONG i;
+
+ PVOID EndMem;
+
+ PACCESS_TOKEN AccessToken;
+
+ Status = ObCreateObject(PreviousMode,
+ SepTokenObjectType,
+ ObjectAttributes,
+ PreviousMode,
+ NULL,
+ sizeof(ACCESS_TOKEN),
+ 0,
+ 0,
+ (PVOID*)&AccessToken);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ObCreateObject() failed (Status %lx)\n");
+ return(Status);
+ }
+
+ Status = ZwAllocateLocallyUniqueId(&AccessToken->TokenId);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(AccessToken);
+ return(Status);
+ }
+
+ Status = ZwAllocateLocallyUniqueId(&AccessToken->ModifiedId);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(AccessToken);
+ return(Status);
+ }
+
+ AccessToken->TokenInUse = 0;
+ AccessToken->TokenType = TokenType;
+ AccessToken->ImpersonationLevel = Level;
+ AccessToken->AuthenticationId.LowPart = SYSTEM_LUID;
+ AccessToken->AuthenticationId.HighPart = 0;
+
+ AccessToken->TokenSource.SourceIdentifier.LowPart = Token->TokenSource.SourceIdentifier.LowPart;
+ AccessToken->TokenSource.SourceIdentifier.HighPart = Token->TokenSource.SourceIdentifier.HighPart;
+ memcpy(AccessToken->TokenSource.SourceName,
+ Token->TokenSource.SourceName,
+ sizeof(Token->TokenSource.SourceName));
+ AccessToken->ExpirationTime.QuadPart = Token->ExpirationTime.QuadPart;
+ AccessToken->UserAndGroupCount = Token->UserAndGroupCount;
+ AccessToken->DefaultOwnerIndex = Token->DefaultOwnerIndex;
+
+ uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
+ for (i = 0; i < Token->UserAndGroupCount; i++)
+ uLength += RtlLengthSid(Token->UserAndGroups[i].Sid);
+
+ AccessToken->UserAndGroups =
+ (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
+ uLength,
+ TAG('T', 'O', 'K', 'u'));
+
+ EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
+
+ Status = RtlCopySidAndAttributesArray(AccessToken->UserAndGroupCount,
+ Token->UserAndGroups,
+ uLength,
+ AccessToken->UserAndGroups,
+ EndMem,
+ &EndMem,
+ &uLength);
+ if (NT_SUCCESS(Status))
+ {
+ Status = SepFindPrimaryGroupAndDefaultOwner(
+ AccessToken,
+ Token->PrimaryGroup,
+ 0);
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ AccessToken->PrivilegeCount = Token->PrivilegeCount;
+
+ uLength = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
+ AccessToken->Privileges =
+ (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
+ uLength,
+ TAG('T', 'O', 'K', 'p'));
+
+ for (i = 0; i < AccessToken->PrivilegeCount; i++)
+ {
+ RtlCopyLuid(&AccessToken->Privileges[i].Luid,
+ &Token->Privileges[i].Luid);
+ AccessToken->Privileges[i].Attributes =
+ Token->Privileges[i].Attributes;
+ }
+
+ if ( Token->DefaultDacl )
+ {
+ AccessToken->DefaultDacl =
+ (PACL) ExAllocatePoolWithTag(NonPagedPool,
+ Token->DefaultDacl->AclSize,
+ TAG('T', 'O', 'K', 'd'));
+ memcpy(AccessToken->DefaultDacl,
+ Token->DefaultDacl,
+ Token->DefaultDacl->AclSize);
+ }
+ else
+ {
+ AccessToken->DefaultDacl = 0;
+ }
+ }
+
+ if ( NT_SUCCESS(Status) )
+ {
+ *NewAccessToken = AccessToken;
+ return(STATUS_SUCCESS);
+ }
+
+ ObDereferenceObject(AccessToken);
+ return(Status);
+}
+
+
+NTSTATUS
+SepInitializeNewProcess(struct _EPROCESS* NewProcess,
+ struct _EPROCESS* ParentProcess)
+{
+ NTSTATUS Status;
+ PACCESS_TOKEN pNewToken;
+ PACCESS_TOKEN pParentToken;
+
+ OBJECT_ATTRIBUTES ObjectAttributes;
+
+ pParentToken = (PACCESS_TOKEN) ParentProcess->Token;
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+
+ Status = SepDuplicateToken(pParentToken,
+ &ObjectAttributes,
+ TokenPrimary,
+ pParentToken->ImpersonationLevel,
+ pParentToken->ImpersonationLevel,
+ KernelMode,
+ &pNewToken);
+ if ( ! NT_SUCCESS(Status) )
+ return Status;
+
+ NewProcess->Token = pNewToken;
+ return(STATUS_SUCCESS);
}
+
NTSTATUS SeCopyClientToken(PACCESS_TOKEN Token,
SECURITY_IMPERSONATION_LEVEL Level,
KPROCESSOR_MODE PreviousMode,
0,
NULL,
NULL);
- Status = SepDuplicationToken(Token,
+ Status = SepDuplicateToken(Token,
&ObjectAttributes,
0,
SecurityIdentification,
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
SeCreateClientSecurity(IN struct _ETHREAD *Thread,
IN PSECURITY_QUALITY_OF_SERVICE Qos,
}
+/*
+ * @implemented
+ */
VOID STDCALL
SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext,
IN PETHREAD ServerThread OPTIONAL)
}
-VOID
-SeInitializeTokenManager(VOID)
+VOID STDCALL
+SepDeleteToken(PVOID ObjectBody)
+{
+ PACCESS_TOKEN AccessToken = (PACCESS_TOKEN)ObjectBody;
+
+ if (AccessToken->UserAndGroups)
+ ExFreePool(AccessToken->UserAndGroups);
+
+ if (AccessToken->Privileges)
+ ExFreePool(AccessToken->Privileges);
+
+ if (AccessToken->DefaultDacl)
+ ExFreePool(AccessToken->DefaultDacl);
+}
+
+
+VOID INIT_FUNCTION
+SepInitializeTokenImplementation(VOID)
{
SepTokenObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
-
+
SepTokenObjectType->Tag = TAG('T', 'O', 'K', 'T');
SepTokenObjectType->MaxObjects = ULONG_MAX;
SepTokenObjectType->MaxHandles = ULONG_MAX;
SepTokenObjectType->Dump = NULL;
SepTokenObjectType->Open = NULL;
SepTokenObjectType->Close = NULL;
- SepTokenObjectType->Delete = NULL;
+ SepTokenObjectType->Delete = SepDeleteToken;
SepTokenObjectType->Parse = NULL;
SepTokenObjectType->Security = NULL;
SepTokenObjectType->QueryName = NULL;
SepTokenObjectType->OkayToClose = NULL;
SepTokenObjectType->Create = NULL;
SepTokenObjectType->DuplicationNotify = NULL;
+
RtlCreateUnicodeString(&SepTokenObjectType->TypeName,
L"Token");
-}
-
-NTSTATUS
-RtlCopySidAndAttributesArray(ULONG Count, // ebp + 8
- PSID_AND_ATTRIBUTES Src, // ebp + C
- ULONG MaxLength, // ebp + 10
- PSID_AND_ATTRIBUTES Dest, // ebp + 14
- PVOID e, // ebp + 18
- PVOID* f, // ebp + 1C
- PULONG g) // ebp + 20
-{
- ULONG Length; // ebp - 4
- ULONG i;
-
- Length = MaxLength;
-
- for (i=0; i<Count; i++)
- {
- if (RtlLengthSid(Src[i].Sid) > Length)
- {
- return(STATUS_UNSUCCESSFUL);
- }
- Length = Length - RtlLengthSid(Src[i].Sid);
- Dest[i].Sid = e;
- Dest[i].Attributes = Src[i].Attributes;
- RtlCopySid(RtlLengthSid(Src[i].Sid), e, Src[i].Sid);
- e = e + RtlLengthSid(Src[i].Sid) + sizeof(ULONG);
- }
- *f = e;
- *g = Length;
- return(STATUS_SUCCESS);
+ ObpCreateTypeObject (SepTokenObjectType);
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
NtQueryInformationToken(IN HANDLE TokenHandle,
IN TOKEN_INFORMATION_CLASS TokenInformationClass,
IN ULONG TokenInformationLength,
OUT PULONG ReturnLength)
{
- NTSTATUS Status;
- PACCESS_TOKEN Token;
- PVOID UnusedInfo;
- PVOID EndMem;
- PTOKEN_GROUPS PtrTokenGroups;
- PTOKEN_DEFAULT_DACL PtrDefaultDacl;
- PTOKEN_STATISTICS PtrTokenStatistics;
-
- Status = ObReferenceObjectByHandle(TokenHandle,
- 0,
- SepTokenObjectType,
- UserMode,
- (PVOID*)&Token,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- switch (TokenInformationClass)
- {
+ NTSTATUS Status;
+ PVOID UnusedInfo;
+ PVOID EndMem;
+ PACCESS_TOKEN Token;
+ ULONG Length;
+ PTOKEN_GROUPS PtrTokenGroups;
+ PTOKEN_DEFAULT_DACL PtrDefaultDacl;
+ PTOKEN_STATISTICS PtrTokenStatistics;
+
+ Status = ObReferenceObjectByHandle(TokenHandle,
+ (TokenInformationClass == TokenSource) ? TOKEN_QUERY_SOURCE : TOKEN_QUERY,
+ SepTokenObjectType,
+ UserMode,
+ (PVOID*)&Token,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+
+ switch (TokenInformationClass)
+ {
case TokenUser:
- Status = RtlCopySidAndAttributesArray(1,
- Token->UserAndGroups,
- TokenInformationLength,
- TokenInformation,
- TokenInformation + 8,
- &UnusedInfo,
- ReturnLength);
- if (!NT_SUCCESS(Status))
+ DPRINT("NtQueryInformationToken(TokenUser)\n");
+ Length = RtlLengthSidAndAttributes(1, Token->UserAndGroups);
+ if (TokenInformationLength < Length)
{
- ObDereferenceObject(Token);
- return(Status);
+ 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;
-
case TokenGroups:
- EndMem = 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,
- ReturnLength);
- if (!NT_SUCCESS(Status))
+ DPRINT("NtQueryInformationToken(TokenGroups)\n");
+ Length = RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]) + sizeof(ULONG);
+ if (TokenInformationLength < Length)
{
- ObDereferenceObject(Token);
- return(Status);
+ 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;
-
+
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;
+
+ 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;
+ }
break;
-
+
case TokenOwner:
- ((PTOKEN_OWNER)TokenInformation)->Owner =
- (PSID)(((PTOKEN_OWNER)TokenInformation) + 1);
- RtlCopySid(TokenInformationLength - sizeof(TOKEN_OWNER),
- ((PTOKEN_OWNER)TokenInformation)->Owner,
- Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
+ 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;
-
+
case TokenPrimaryGroup:
- ((PTOKEN_PRIMARY_GROUP)TokenInformation)->PrimaryGroup =
- (PSID)(((PTOKEN_PRIMARY_GROUP)TokenInformation) + 1);
- RtlCopySid(TokenInformationLength - sizeof(TOKEN_OWNER),
- ((PTOKEN_PRIMARY_GROUP)TokenInformation)->PrimaryGroup,
- Token->PrimaryGroup);
+ 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;
-
+
case TokenDefaultDacl:
- PtrDefaultDacl = (PTOKEN_DEFAULT_DACL)TokenInformation;
- PtrDefaultDacl->DefaultDacl = (PACL)(PtrDefaultDacl + 1);
- memmove(PtrDefaultDacl->DefaultDacl,
- Token->DefaultDacl,
- Token->DefaultDacl->AclSize);
+ 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;
-
+
case TokenSource:
- memcpy(TokenInformation, &Token->TokenSource, sizeof(TOKEN_SOURCE));
+ 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;
-
+
case TokenType:
- *((PTOKEN_TYPE)TokenInformation) = Token->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;
-
+
case TokenImpersonationLevel:
- *((PSECURITY_IMPERSONATION_LEVEL)TokenInformation) =
- Token->ImpersonationLevel;
+ 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;
-
+
case TokenStatistics:
- 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;
+ 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;
+
+ Status = STATUS_SUCCESS;
+ }
break;
- }
-
- ObDereferenceObject(Token);
- return(STATUS_SUCCESS);
+ }
+
+ ObDereferenceObject(Token);
+
+ return(Status);
}
+/*
+ * NtSetTokenInformation: Partly implemented.
+ * Unimplemented:
+ * TokenOrigin, TokenDefaultDacl, TokenSessionId
+ */
NTSTATUS STDCALL
NtSetInformationToken(IN HANDLE TokenHandle,
OUT PVOID TokenInformation,
IN ULONG TokenInformationLength)
{
- UNIMPLEMENTED;
+ NTSTATUS Status;
+ PACCESS_TOKEN Token;
+ TOKEN_OWNER TokenOwnerSet = { 0 };
+ TOKEN_PRIMARY_GROUP TokenPrimaryGroupSet = { 0 };
+ DWORD NeededAccess = 0;
+
+ switch (TokenInformationClass)
+ {
+ case TokenOwner:
+ case TokenPrimaryGroup:
+ NeededAccess = TOKEN_ADJUST_DEFAULT;
+ break;
+
+ default:
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ Status = ObReferenceObjectByHandle(TokenHandle,
+ NeededAccess,
+ SepTokenObjectType,
+ UserMode,
+ (PVOID*)&Token,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ 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 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;
+
+ default:
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+
+ ObDereferenceObject(Token);
+
+ return(Status);
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
NtDuplicateToken(IN HANDLE ExistingTokenHandle,
IN ACCESS_MASK DesiredAccess,
IN TOKEN_TYPE TokenType,
OUT PHANDLE NewTokenHandle)
{
-#if 0
- PACCESS_TOKEN Token;
- PACCESS_TOKEN NewToken;
- NTSTATUS Status;
- ULONG ExistingImpersonationLevel;
-
- Status = ObReferenceObjectByHandle(ExistingTokenHandle,
- ?,
- SepTokenObjectType,
- UserMode,
- (PVOID*)&Token,
- NULL);
-
- ExistingImpersonationLevel = Token->ImpersonationLevel;
- SepDuplicateToken(Token,
- ObjectAttributes,
- ImpersonationLevel,
- TokenType,
- ExistingImpersonationLevel,
- KeGetPreviousMode(),
- &NewToken);
-#else
- UNIMPLEMENTED;
-#endif
+ KPROCESSOR_MODE PreviousMode;
+ PACCESS_TOKEN Token;
+ PACCESS_TOKEN NewToken;
+ NTSTATUS Status;
+ ULONG ExistingImpersonationLevel;
+
+ PreviousMode = KeGetPreviousMode();
+ 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;
+ }
+
+ ExistingImpersonationLevel = Token->ImpersonationLevel;
+ Status = SepDuplicateToken(Token,
+ ObjectAttributes,
+ TokenType,
+ ImpersonationLevel,
+ ExistingImpersonationLevel,
+ PreviousMode,
+ &NewToken);
+
+ ObDereferenceObject(Token);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to duplicate token (Status %lx)\n", Status);
+ return Status;
+ }
+
+ Status = ObInsertObject((PVOID)NewToken,
+ NULL,
+ DesiredAccess,
+ 0,
+ NULL,
+ NewTokenHandle);
+
+ ObDereferenceObject(NewToken);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create token handle (Status %lx)\n");
+ return Status;
+ }
+
+ return STATUS_SUCCESS;
}
+
VOID SepAdjustGroups(PACCESS_TOKEN Token,
ULONG a,
BOOLEAN ResetToDefault,
&c);
#else
UNIMPLEMENTED;
+ return(STATUS_NOT_IMPLEMENTED);
#endif
}
#if 0
-NTSTATUS SepAdjustPrivileges(PACCESS_TOKEN Token, // 0x8
- ULONG a, // 0xC
- KPROCESSOR_MODE PreviousMode, // 0x10
- ULONG PrivilegeCount, // 0x14
- PLUID_AND_ATTRIBUTES Privileges, // 0x18
- PTOKEN_PRIVILEGES* PreviousState, // 0x1C
- PULONG b, // 0x20
- PULONG c, // 0x24
- PULONG d) // 0x28
+NTSTATUS
+SepAdjustPrivileges(PACCESS_TOKEN Token,
+ ULONG a,
+ KPROCESSOR_MODE PreviousMode,
+ ULONG PrivilegeCount,
+ PLUID_AND_ATTRIBUTES Privileges,
+ PTOKEN_PRIVILEGES* PreviousState,
+ PULONG b,
+ PULONG c,
+ PULONG d)
{
- ULONG i;
-
- *c = 0;
- if (Token->PrivilegeCount > 0)
- {
- for (i=0; i<Token->PrivilegeCount; i++)
- {
- if (PreviousMode != 0)
- {
- if (!(Token->Privileges[i]->Attributes &
- SE_PRIVILEGE_ENABLED))
+ ULONG i;
+
+ *c = 0;
+
+ if (Token->PrivilegeCount > 0)
+ {
+ for (i = 0; i < Token->PrivilegeCount; i++)
+ {
+ if (PreviousMode != KernelMode)
+ {
+ if (Token->Privileges[i]->Attributes & SE_PRIVILEGE_ENABLED == 0)
+ {
+ if (a != 0)
{
- if (a != 0)
- {
- if (PreviousState != NULL)
- {
- memcpy(&PreviousState[i],
- &Token->Privileges[i],
- sizeof(LUID_AND_ATTRIBUTES));
- }
- Token->Privileges[i].Attributes =
- Token->Privileges[i].Attributes &
- (~SE_PRIVILEGE_ENABLED);
- }
+ if (PreviousState != NULL)
+ {
+ memcpy(&PreviousState[i],
+ &Token->Privileges[i],
+ sizeof(LUID_AND_ATTRIBUTES));
+ }
+ Token->Privileges[i].Attributes &= (~SE_PRIVILEGE_ENABLED);
}
- }
- }
- }
- if (PreviousMode != 0)
- {
- Token->TokenFlags = Token->TokenFlags & (~1);
- }
- else
- {
- if (PrivilegeCount <= ?)
- {
-
- }
+ }
+ }
+ }
+ }
+
+ if (PreviousMode != KernelMode)
+ {
+ Token->TokenFlags = Token->TokenFlags & (~1);
+ }
+ else
+ {
+ if (PrivilegeCount <= ?)
+ {
+ }
}
if (
}
#endif
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
-NtAdjustPrivilegesToken(IN HANDLE TokenHandle,
- IN BOOLEAN DisableAllPrivileges,
- IN PTOKEN_PRIVILEGES NewState,
- IN ULONG BufferLength,
- OUT PTOKEN_PRIVILEGES PreviousState,
- OUT PULONG ReturnLength)
+NtAdjustPrivilegesToken (IN HANDLE TokenHandle,
+ IN BOOLEAN DisableAllPrivileges,
+ IN PTOKEN_PRIVILEGES NewState,
+ IN ULONG BufferLength,
+ OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL,
+ OUT PULONG ReturnLength OPTIONAL)
{
+// PLUID_AND_ATTRIBUTES Privileges;
+ KPROCESSOR_MODE PreviousMode;
+// ULONG PrivilegeCount;
+ PACCESS_TOKEN Token;
+// ULONG Length;
+ ULONG i;
+ ULONG j;
+ ULONG k;
+ ULONG Count;
#if 0
- ULONG PrivilegeCount;
- ULONG Length;
- PSID_AND_ATTRIBUTES Privileges;
ULONG a;
ULONG b;
ULONG c;
-
- PrivilegeCount = NewState->PrivilegeCount;
-
- SeCaptureLuidAndAttributesArray(NewState->Privileges,
- &PrivilegeCount,
- KeGetPreviousMode(),
- NULL,
- 0,
- NonPagedPool,
- 1,
- &Privileges.
- &Length);
+#endif
+ NTSTATUS Status;
+
+ DPRINT ("NtAdjustPrivilegesToken() called\n");
+
+// PrivilegeCount = NewState->PrivilegeCount;
+ PreviousMode = KeGetPreviousMode ();
+// SeCaptureLuidAndAttributesArray(NewState->Privileges,
+// PrivilegeCount,
+// PreviousMode,
+// NULL,
+// 0,
+// NonPagedPool,
+// 1,
+// &Privileges,
+// &Length);
+
+ Status = ObReferenceObjectByHandle (TokenHandle,
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
+ SepTokenObjectType,
+ PreviousMode,
+ (PVOID*)&Token,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1 ("Failed to reference token (Status %lx)\n", Status);
+// SeReleaseLuidAndAttributesArray(Privileges,
+// PreviousMode,
+// 0);
+ return Status;
+ }
+
+
+#if 0
SepAdjustPrivileges(Token,
0,
- KeGetPreviousMode(),
+ PreviousMode,
PrivilegeCount,
Privileges,
PreviousState,
&a,
&b,
&c);
-#else
- UNIMPLEMENTED;
#endif
+
+ k = 0;
+ if (DisableAllPrivileges == TRUE)
+ {
+ for (i = 0; i < Token->PrivilegeCount; i++)
+ {
+ if (Token->Privileges[i].Attributes != 0)
+ {
+ DPRINT ("Attributes differ\n");
+
+ /* Save current privilege */
+ if (PreviousState != NULL && k < PreviousState->PrivilegeCount)
+ {
+ PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
+ PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
+ k++;
+ }
+
+ /* Update current privlege */
+ Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
+ }
+ }
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ Count = 0;
+ for (i = 0; i < Token->PrivilegeCount; i++)
+ {
+ for (j = 0; j < NewState->PrivilegeCount; j++)
+ {
+ if (Token->Privileges[i].Luid.LowPart == NewState->Privileges[j].Luid.LowPart &&
+ Token->Privileges[i].Luid.HighPart == NewState->Privileges[j].Luid.HighPart)
+ {
+ DPRINT ("Found privilege\n");
+
+ if ((Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) !=
+ (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED))
+ {
+ DPRINT ("Attributes differ\n");
+ DPRINT ("Current attributes %lx desired attributes %lx\n",
+ Token->Privileges[i].Attributes,
+ NewState->Privileges[j].Attributes);
+
+ /* Save current privilege */
+ if (PreviousState != NULL && k < PreviousState->PrivilegeCount)
+ {
+ PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
+ PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
+ k++;
+ }
+
+ /* Update current privlege */
+ Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
+ Token->Privileges[i].Attributes |=
+ (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED);
+ DPRINT ("New attributes %lx\n",
+ Token->Privileges[i].Attributes);
+ }
+ Count++;
+ }
+ }
+ }
+ Status = Count < NewState->PrivilegeCount ? STATUS_NOT_ALL_ASSIGNED : STATUS_SUCCESS;
+ }
+
+ if (ReturnLength != NULL)
+ {
+ *ReturnLength = sizeof(TOKEN_PRIVILEGES) +
+ (sizeof(LUID_AND_ATTRIBUTES) * (k - 1));
+ }
+
+ ObDereferenceObject (Token);
+
+// SeReleaseLuidAndAttributesArray(Privileges,
+// PreviousMode,
+// 0);
+
+ DPRINT ("NtAdjustPrivilegesToken() done\n");
+
+ return Status;
}
+
+NTSTATUS
+SepCreateSystemProcessToken(struct _EPROCESS* Process)
+{
+ NTSTATUS Status;
+ ULONG uSize;
+ ULONG i;
+
+ ULONG uLocalSystemLength = RtlLengthSid(SeLocalSystemSid);
+ ULONG uWorldLength = RtlLengthSid(SeWorldSid);
+ ULONG uAuthUserLength = RtlLengthSid(SeAuthenticatedUserSid);
+ ULONG uAdminsLength = RtlLengthSid(SeAliasAdminsSid);
+
+ PACCESS_TOKEN AccessToken;
+
+ PVOID SidArea;
+
+ /*
+ * Initialize the token
+ */
+ Status = ObCreateObject(KernelMode,
+ SepTokenObjectType,
+ NULL,
+ KernelMode,
+ NULL,
+ sizeof(ACCESS_TOKEN),
+ 0,
+ 0,
+ (PVOID*)&AccessToken);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+
+ Status = NtAllocateLocallyUniqueId(&AccessToken->TokenId);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(AccessToken);
+ return(Status);
+ }
+
+ Status = NtAllocateLocallyUniqueId(&AccessToken->ModifiedId);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(AccessToken);
+ return(Status);
+ }
+
+ AccessToken->AuthenticationId.LowPart = SYSTEM_LUID;
+ AccessToken->AuthenticationId.HighPart = 0;
+
+ AccessToken->TokenType = TokenPrimary;
+ AccessToken->ImpersonationLevel = SecurityDelegation;
+ AccessToken->TokenSource.SourceIdentifier.LowPart = 0;
+ AccessToken->TokenSource.SourceIdentifier.HighPart = 0;
+ memcpy(AccessToken->TokenSource.SourceName, "SeMgr\0\0\0", 8);
+ AccessToken->ExpirationTime.QuadPart = -1;
+ AccessToken->UserAndGroupCount = 4;
+
+ uSize = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
+ uSize += uLocalSystemLength;
+ uSize += uWorldLength;
+ uSize += uAuthUserLength;
+ uSize += uAdminsLength;
+
+ AccessToken->UserAndGroups =
+ (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
+ uSize,
+ TAG('T', 'O', 'K', 'u'));
+ SidArea = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
+
+ i = 0;
+ AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
+ AccessToken->UserAndGroups[i++].Attributes = 0;
+ RtlCopySid(uLocalSystemLength, SidArea, SeLocalSystemSid);
+ SidArea = (char*)SidArea + uLocalSystemLength;
+
+ AccessToken->DefaultOwnerIndex = i;
+ AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
+ AccessToken->PrimaryGroup = (PSID) SidArea;
+ AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT;
+ Status = RtlCopySid(uAdminsLength, SidArea, SeAliasAdminsSid);
+ SidArea = (char*)SidArea + uAdminsLength;
+
+ AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
+ AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
+ RtlCopySid(uWorldLength, SidArea, SeWorldSid);
+ SidArea = (char*)SidArea + uWorldLength;
+
+ AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
+ AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
+ RtlCopySid(uAuthUserLength, SidArea, SeAuthenticatedUserSid);
+ SidArea = (char*)SidArea + uAuthUserLength;
+
+ AccessToken->PrivilegeCount = 20;
+
+ uSize = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
+ AccessToken->Privileges =
+ (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
+ uSize,
+ TAG('T', 'O', 'K', 'p'));
+
+ i = 0;
+ AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+ AccessToken->Privileges[i++].Luid = SeTcbPrivilege;
+
+ AccessToken->Privileges[i].Attributes = 0;
+ AccessToken->Privileges[i++].Luid = SeCreateTokenPrivilege;
+
+ AccessToken->Privileges[i].Attributes = 0;
+ AccessToken->Privileges[i++].Luid = SeTakeOwnershipPrivilege;
+
+ AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+ AccessToken->Privileges[i++].Luid = SeCreatePagefilePrivilege;
+
+ AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+ AccessToken->Privileges[i++].Luid = SeLockMemoryPrivilege;
+
+ AccessToken->Privileges[i].Attributes = 0;
+ AccessToken->Privileges[i++].Luid = SeAssignPrimaryTokenPrivilege;
+
+ AccessToken->Privileges[i].Attributes = 0;
+ AccessToken->Privileges[i++].Luid = SeIncreaseQuotaPrivilege;
+
+ AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+ AccessToken->Privileges[i++].Luid = SeIncreaseBasePriorityPrivilege;
+
+ AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+ AccessToken->Privileges[i++].Luid = SeCreatePermanentPrivilege;
+
+ AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+ AccessToken->Privileges[i++].Luid = SeDebugPrivilege;
+
+ AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+ AccessToken->Privileges[i++].Luid = SeAuditPrivilege;
+
+ AccessToken->Privileges[i].Attributes = 0;
+ AccessToken->Privileges[i++].Luid = SeSecurityPrivilege;
+
+ AccessToken->Privileges[i].Attributes = 0;
+ AccessToken->Privileges[i++].Luid = SeSystemEnvironmentPrivilege;
+
+ AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+ AccessToken->Privileges[i++].Luid = SeChangeNotifyPrivilege;
+
+ AccessToken->Privileges[i].Attributes = 0;
+ AccessToken->Privileges[i++].Luid = SeBackupPrivilege;
+
+ AccessToken->Privileges[i].Attributes = 0;
+ AccessToken->Privileges[i++].Luid = SeRestorePrivilege;
+
+ AccessToken->Privileges[i].Attributes = 0;
+ AccessToken->Privileges[i++].Luid = SeShutdownPrivilege;
+
+ AccessToken->Privileges[i].Attributes = 0;
+ AccessToken->Privileges[i++].Luid = SeLoadDriverPrivilege;
+
+ AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+ AccessToken->Privileges[i++].Luid = SeProfileSingleProcessPrivilege;
+
+ AccessToken->Privileges[i].Attributes = 0;
+ AccessToken->Privileges[i++].Luid = SeSystemtimePrivilege;
+#if 0
+ AccessToken->Privileges[i].Attributes = 0;
+ AccessToken->Privileges[i++].Luid = SeUndockPrivilege;
+
+ AccessToken->Privileges[i].Attributes = 0;
+ AccessToken->Privileges[i++].Luid = SeManageVolumePrivilege;
+#endif
+
+ assert( i == 20 );
+
+ uSize = sizeof(ACL);
+ uSize += sizeof(ACE) + uLocalSystemLength;
+ uSize += sizeof(ACE) + uAdminsLength;
+ uSize = (uSize & (~3)) + 8;
+ AccessToken->DefaultDacl =
+ (PACL) ExAllocatePoolWithTag(NonPagedPool,
+ uSize,
+ TAG('T', 'O', 'K', 'd'));
+ Status = RtlCreateAcl(AccessToken->DefaultDacl, uSize, ACL_REVISION);
+ if ( NT_SUCCESS(Status) )
+ {
+ Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid);
+ }
+
+ if ( NT_SUCCESS(Status) )
+ {
+ Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_READ|GENERIC_EXECUTE|READ_CONTROL, SeAliasAdminsSid);
+ }
+
+ if ( ! NT_SUCCESS(Status) )
+ {
+ ObDereferenceObject(AccessToken);
+ return Status;
+ }
+
+ Process->Token = AccessToken;
+ return(STATUS_SUCCESS);
+}
+
+
NTSTATUS STDCALL
-NtCreateToken(OUT PHANDLE TokenHandle,
+NtCreateToken(OUT PHANDLE UnsafeTokenHandle,
IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN POBJECT_ATTRIBUTES UnsafeObjectAttributes,
IN TOKEN_TYPE TokenType,
IN PLUID AuthenticationId,
IN PLARGE_INTEGER ExpirationTime,
IN PTOKEN_DEFAULT_DACL TokenDefaultDacl,
IN PTOKEN_SOURCE TokenSource)
{
-#if 0
- PACCESS_TOKEN AccessToken;
- NTSTATUS Status;
-
- Status = ObCreateObject(TokenHandle,
+ HANDLE TokenHandle;
+ PACCESS_TOKEN AccessToken;
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES SafeObjectAttributes;
+ POBJECT_ATTRIBUTES ObjectAttributes;
+ LUID TokenId;
+ LUID ModifiedId;
+ PVOID EndMem;
+ ULONG uLength;
+ ULONG i;
+
+ Status = MmCopyFromCaller(&SafeObjectAttributes,
+ UnsafeObjectAttributes,
+ sizeof(OBJECT_ATTRIBUTES));
+ if (!NT_SUCCESS(Status))
+ return(Status);
+
+ ObjectAttributes = &SafeObjectAttributes;
+
+ Status = ZwAllocateLocallyUniqueId(&TokenId);
+ if (!NT_SUCCESS(Status))
+ return(Status);
+
+ Status = ZwAllocateLocallyUniqueId(&ModifiedId);
+ if (!NT_SUCCESS(Status))
+ return(Status);
+
+ Status = ObCreateObject(ExGetPreviousMode(),
+ SepTokenObjectType,
+ ObjectAttributes,
+ ExGetPreviousMode(),
+ NULL,
+ sizeof(ACCESS_TOKEN),
+ 0,
+ 0,
+ (PVOID*)&AccessToken);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ObCreateObject() failed (Status %lx)\n");
+ return(Status);
+ }
+
+ Status = ObInsertObject ((PVOID)AccessToken,
+ NULL,
DesiredAccess,
- ObjectAttributes,
- SeTokenType);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- AccessToken->TokenType = TokenType;
- RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
- AccessToken->ExpirationTime = *ExpirationTime;
- AccessToken->
-#endif
- UNIMPLEMENTED;
+ 0,
+ NULL,
+ &TokenHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ObInsertObject() failed (Status %lx)\n");
+ ObDereferenceObject (AccessToken);
+ return Status;
+ }
+
+ RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
+ &TokenSource->SourceIdentifier);
+ memcpy(AccessToken->TokenSource.SourceName,
+ TokenSource->SourceName,
+ sizeof(TokenSource->SourceName));
+
+ RtlCopyLuid(&AccessToken->TokenId, &TokenId);
+ RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
+ AccessToken->ExpirationTime = *ExpirationTime;
+ RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
+
+ AccessToken->UserAndGroupCount = TokenGroups->GroupCount + 1;
+ AccessToken->PrivilegeCount = TokenPrivileges->PrivilegeCount;
+ AccessToken->UserAndGroups = 0;
+ AccessToken->Privileges = 0;
+
+ AccessToken->TokenType = TokenType;
+ AccessToken->ImpersonationLevel = ObjectAttributes->SecurityQualityOfService->ImpersonationLevel;
+
+ /*
+ * Normally we would just point these members into the variable information
+ * area; however, our ObCreateObject() call can't allocate a variable information
+ * area, so we allocate them seperately and provide a destroy function.
+ */
+
+ uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
+ uLength += RtlLengthSid(TokenUser->User.Sid);
+ for (i = 0; i < TokenGroups->GroupCount; i++)
+ uLength += RtlLengthSid(TokenGroups->Groups[i].Sid);
+
+ AccessToken->UserAndGroups =
+ (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
+ uLength,
+ TAG('T', 'O', 'K', 'u'));
+
+ EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
+
+ Status = RtlCopySidAndAttributesArray(1,
+ &TokenUser->User,
+ uLength,
+ AccessToken->UserAndGroups,
+ EndMem,
+ &EndMem,
+ &uLength);
+ if (NT_SUCCESS(Status))
+ {
+ Status = RtlCopySidAndAttributesArray(TokenGroups->GroupCount,
+ TokenGroups->Groups,
+ uLength,
+ &AccessToken->UserAndGroups[1],
+ EndMem,
+ &EndMem,
+ &uLength);
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ Status = SepFindPrimaryGroupAndDefaultOwner(
+ AccessToken,
+ TokenPrimaryGroup->PrimaryGroup,
+ TokenOwner->Owner);
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ uLength = TokenPrivileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
+ AccessToken->Privileges =
+ (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
+ uLength,
+ TAG('T', 'O', 'K', 'p'));
+
+ for (i = 0; i < TokenPrivileges->PrivilegeCount; i++)
+ {
+ Status = MmCopyFromCaller(&AccessToken->Privileges[i],
+ &TokenPrivileges->Privileges[i],
+ sizeof(LUID_AND_ATTRIBUTES));
+ if (!NT_SUCCESS(Status))
+ break;
+ }
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ AccessToken->DefaultDacl =
+ (PACL) ExAllocatePoolWithTag(NonPagedPool,
+ TokenDefaultDacl->DefaultDacl->AclSize,
+ TAG('T', 'O', 'K', 'd'));
+ memcpy(AccessToken->DefaultDacl,
+ TokenDefaultDacl->DefaultDacl,
+ TokenDefaultDacl->DefaultDacl->AclSize);
+ }
+
+ ObDereferenceObject(AccessToken);
+
+ if (NT_SUCCESS(Status))
+ {
+ Status = MmCopyToCaller(UnsafeTokenHandle,
+ &TokenHandle,
+ sizeof(HANDLE));
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ ZwClose(TokenHandle);
+ return(Status);
+ }
+
+ return(STATUS_SUCCESS);
+}
+
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token,
+ OUT PLUID LogonId)
+{
+ LogonId->LowPart = Token->AuthenticationId.LowPart;
+ LogonId->HighPart = Token->AuthenticationId.HighPart;
+
+ return STATUS_SUCCESS;
}
+/*
+ * @implemented
+ */
SECURITY_IMPERSONATION_LEVEL STDCALL
SeTokenImpersonationLevel(IN PACCESS_TOKEN Token)
{
- return(Token->ImpersonationLevel);
+ return Token->ImpersonationLevel;
}
+/*
+ * @implemented
+ */
TOKEN_TYPE STDCALL
SeTokenType(IN PACCESS_TOKEN Token)
{
- return(Token->TokenType);
+ return Token->TokenType;
}
+
+
/* EOF */