-/* $Id: token.c,v 1.11 2004/07/06 22:07:25 gvg Exp $
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/advapi32/token/token.c
* Created 01/11/98
*/
-#define NTOS_MODE_USER
-#include <ntos.h>
-#include <windows.h>
+#include <advapi32.h>
+
+#define NDEBUG
+#include <wine/debug.h>
+#include <debug.h>
/*
* @implemented
LPBOOL AccessStatus)
{
NTSTATUS Status;
+ NTSTATUS AccessStat;
Status = NtAccessCheck (pSecurityDescriptor,
ClientToken,
GenericMapping,
PrivilegeSet,
(PULONG)PrivilegeSetLength,
- (PULONG)GrantedAccess,
- (PBOOLEAN)AccessStatus);
+ (PACCESS_MASK)GrantedAccess,
+ &AccessStat);
if (!NT_SUCCESS (Status))
{
SetLastError (RtlNtStatusToDosError (Status));
return FALSE;
}
+ if (!NT_SUCCESS (AccessStat))
+ {
+ SetLastError (RtlNtStatusToDosError (Status));
+ *AccessStatus = FALSE;
+ return TRUE;
+ }
+
+ *AccessStatus = TRUE;
+
return TRUE;
}
* @implemented
*/
BOOL STDCALL
-SetThreadToken (PHANDLE ThreadHandle,
- HANDLE TokenHandle)
+SetThreadToken (IN PHANDLE ThreadHandle OPTIONAL,
+ IN HANDLE TokenHandle)
{
NTSTATUS Status;
HANDLE hThread;
- hThread = NtCurrentThread();
- if (ThreadHandle != NULL)
- hThread = ThreadHandle;
+ hThread = ((ThreadHandle != NULL) ? *ThreadHandle : NtCurrentThread());
Status = NtSetInformationThread (hThread,
ThreadImpersonationToken,
- TokenHandle,
+ &TokenHandle,
sizeof(HANDLE));
if (!NT_SUCCESS(Status))
{
* @implemented
*/
BOOL STDCALL
-DuplicateTokenEx (HANDLE ExistingTokenHandle,
- DWORD dwDesiredAccess,
- LPSECURITY_ATTRIBUTES lpTokenAttributes,
- SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
- TOKEN_TYPE TokenType,
- PHANDLE DuplicateTokenHandle)
+DuplicateTokenEx (IN HANDLE ExistingTokenHandle,
+ IN DWORD dwDesiredAccess,
+ IN LPSECURITY_ATTRIBUTES lpTokenAttributes OPTIONAL,
+ IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
+ IN TOKEN_TYPE TokenType,
+ OUT PHANDLE DuplicateTokenHandle)
{
OBJECT_ATTRIBUTES ObjectAttributes;
- HANDLE NewToken;
NTSTATUS Status;
+ SECURITY_QUALITY_OF_SERVICE Sqos;
- ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
- ObjectAttributes.RootDirectory = NULL;
- ObjectAttributes.ObjectName = NULL;
- ObjectAttributes.Attributes = 0;
- if (lpTokenAttributes->bInheritHandle)
+ Sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
+ Sqos.ImpersonationLevel = ImpersonationLevel;
+ Sqos.ContextTrackingMode = 0;
+ Sqos.EffectiveOnly = FALSE;
+
+ if (lpTokenAttributes != NULL)
{
- ObjectAttributes.Attributes |= OBJ_INHERIT;
+ InitializeObjectAttributes(&ObjectAttributes,
+ NULL,
+ lpTokenAttributes->bInheritHandle ? OBJ_INHERIT : 0,
+ NULL,
+ lpTokenAttributes->lpSecurityDescriptor);
}
- ObjectAttributes.SecurityDescriptor = lpTokenAttributes->lpSecurityDescriptor;
- ObjectAttributes.SecurityQualityOfService = NULL;
+ else
+ {
+ InitializeObjectAttributes(&ObjectAttributes,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ }
+
+ ObjectAttributes.SecurityQualityOfService = &Sqos;
Status = NtDuplicateToken (ExistingTokenHandle,
dwDesiredAccess,
&ObjectAttributes,
- ImpersonationLevel,
+ FALSE,
TokenType,
- &NewToken);
+ DuplicateTokenHandle);
if (!NT_SUCCESS(Status))
{
SetLastError(RtlNtStatusToDosError(Status));
* @implemented
*/
BOOL STDCALL
-DuplicateToken (HANDLE ExistingTokenHandle,
- SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
- PHANDLE DuplicateTokenHandle)
+DuplicateToken (IN HANDLE ExistingTokenHandle,
+ IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
+ OUT PHANDLE DuplicateTokenHandle)
{
return DuplicateTokenEx (ExistingTokenHandle,
- TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY,
+ TOKEN_IMPERSONATE | TOKEN_QUERY,
NULL,
ImpersonationLevel,
TokenImpersonation,
DuplicateTokenHandle);
}
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+CheckTokenMembership(IN HANDLE ExistingTokenHandle,
+ IN PSID SidToCheck,
+ OUT PBOOL IsMember)
+{
+ PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
+ ACCESS_MASK GrantedAccess;
+ struct
+ {
+ PRIVILEGE_SET PrivilegeSet;
+ LUID_AND_ATTRIBUTES Privileges[4];
+ } PrivBuffer;
+ ULONG PrivBufferSize = sizeof(PrivBuffer);
+ GENERIC_MAPPING GenericMapping =
+ {
+ STANDARD_RIGHTS_READ,
+ STANDARD_RIGHTS_WRITE,
+ STANDARD_RIGHTS_EXECUTE,
+ STANDARD_RIGHTS_ALL
+ };
+ PACL Dacl;
+ ULONG SidLen;
+ HANDLE hToken = NULL;
+ NTSTATUS Status, AccessStatus;
+
+ /* doesn't return gracefully if IsMember is NULL! */
+ *IsMember = FALSE;
+
+ SidLen = RtlLengthSid(SidToCheck);
+
+ if (ExistingTokenHandle == NULL)
+ {
+ Status = NtOpenThreadToken(NtCurrentThread(),
+ TOKEN_QUERY,
+ FALSE,
+ &hToken);
+
+ if (Status == STATUS_NO_TOKEN)
+ {
+ /* we're not impersonating, open the primary token */
+ Status = NtOpenProcessToken(NtCurrentProcess(),
+ TOKEN_QUERY | TOKEN_DUPLICATE,
+ &hToken);
+ if (NT_SUCCESS(Status))
+ {
+ HANDLE hNewToken = FALSE;
+ BOOL DupRet;
+
+ /* duplicate the primary token to create an impersonation token */
+ DupRet = DuplicateTokenEx(hToken,
+ TOKEN_QUERY | TOKEN_IMPERSONATE,
+ NULL,
+ SecurityImpersonation,
+ TokenImpersonation,
+ &hNewToken);
+
+ NtClose(hToken);
+
+ if (!DupRet)
+ {
+ DPRINT1("Failed to duplicate the primary token!\n");
+ return FALSE;
+ }
+
+ hToken = hNewToken;
+ }
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+ }
+ else
+ {
+ hToken = ExistingTokenHandle;
+ }
+
+ /* create a security descriptor */
+ SecurityDescriptor = RtlAllocateHeap(RtlGetProcessHeap(),
+ 0,
+ sizeof(SECURITY_DESCRIPTOR) +
+ sizeof(ACL) + SidLen +
+ sizeof(ACCESS_ALLOWED_ACE));
+ if (SecurityDescriptor == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Cleanup;
+ }
+
+ Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
+ SECURITY_DESCRIPTOR_REVISION);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ /* set the owner and group */
+ Status = RtlSetOwnerSecurityDescriptor(SecurityDescriptor,
+ SidToCheck,
+ FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ Status = RtlSetGroupSecurityDescriptor(SecurityDescriptor,
+ SidToCheck,
+ FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ /* create the DACL */
+ Dacl = (PACL)(SecurityDescriptor + 1);
+ Status = RtlCreateAcl(Dacl,
+ sizeof(ACL) + SidLen + sizeof(ACCESS_ALLOWED_ACE),
+ ACL_REVISION);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ Status = RtlAddAccessAllowedAce(Dacl,
+ ACL_REVISION,
+ 0x1,
+ SidToCheck);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ /* assign the DACL to the security descriptor */
+ Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor,
+ TRUE,
+ Dacl,
+ FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ /* it's time to perform the access check. Just use _some_ desired access right
+ (same as for the ACE) and see if we're getting it granted. This indicates
+ our SID is a member of the token. We however can't use a generic access
+ right as those aren't mapped and return an error (STATUS_GENERIC_NOT_MAPPED). */
+ Status = NtAccessCheck(SecurityDescriptor,
+ hToken,
+ 0x1,
+ &GenericMapping,
+ &PrivBuffer.PrivilegeSet,
+ &PrivBufferSize,
+ &GrantedAccess,
+ &AccessStatus);
+
+ if (NT_SUCCESS(Status) && NT_SUCCESS(AccessStatus) && (GrantedAccess == 0x1))
+ {
+ *IsMember = TRUE;
+ }
+
+Cleanup:
+ if (hToken != NULL && hToken != ExistingTokenHandle)
+ {
+ NtClose(hToken);
+ }
+
+ if (SecurityDescriptor != NULL)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(),
+ 0,
+ SecurityDescriptor);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastError(RtlNtStatusToDosError(Status));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+IsTokenRestricted(HANDLE TokenHandle)
+{
+ ULONG RetLength;
+ PTOKEN_GROUPS lpGroups;
+ NTSTATUS Status;
+ BOOL Ret = FALSE;
+
+ /* determine the required buffer size and allocate enough memory to read the
+ list of restricted SIDs */
+
+ Status = NtQueryInformationToken(TokenHandle,
+ TokenRestrictedSids,
+ NULL,
+ 0,
+ &RetLength);
+ if (Status != STATUS_BUFFER_TOO_SMALL)
+ {
+ SetLastError(RtlNtStatusToDosError(Status));
+ return FALSE;
+ }
+
+AllocAndReadRestrictedSids:
+ lpGroups = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(),
+ 0,
+ RetLength);
+ if (lpGroups == NULL)
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+
+ /* actually read the list of the restricted SIDs */
+
+ Status = NtQueryInformationToken(TokenHandle,
+ TokenRestrictedSids,
+ lpGroups,
+ RetLength,
+ &RetLength);
+ if (NT_SUCCESS(Status))
+ {
+ Ret = (lpGroups->GroupCount != 0);
+ }
+ else if (Status == STATUS_BUFFER_TOO_SMALL)
+ {
+ /* looks like the token was modified in the meanwhile, let's just try again */
+
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpGroups);
+
+ goto AllocAndReadRestrictedSids;
+ }
+ else
+ {
+ SetLastError(RtlNtStatusToDosError(Status));
+ }
+
+ /* free allocated memory */
+
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpGroups);
+
+ return Ret;
+}
+
+BOOL STDCALL
+CreateRestrictedToken(
+ HANDLE TokenHandle,
+ DWORD Flags,
+ DWORD DisableSidCount,
+ PSID_AND_ATTRIBUTES pSidAndAttributes,
+ DWORD DeletePrivilegeCount,
+ PLUID_AND_ATTRIBUTES pLUIDAndAttributes,
+ DWORD RestrictedSidCount,
+ PSID_AND_ATTRIBUTES pSIDAndAttributes,
+ PHANDLE NewTokenHandle
+)
+{
+ FIXME("unimplemented!\n", __FUNCTION__);
+ return FALSE;
+}
+
+
+
/* EOF */