* Created 01/11/98
*/
-#define NTOS_MODE_USER
-#include <ntos.h>
-#include <windows.h>
-
-WINBOOL
-STDCALL
-AdjustTokenGroups (
- HANDLE TokenHandle,
- WINBOOL ResetToDefault,
+#include <advapi32.h>
+
+#define NDEBUG
+#include <wine/debug.h>
+#include <debug.h>
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+AdjustTokenGroups (HANDLE TokenHandle,
+ BOOL ResetToDefault,
PTOKEN_GROUPS NewState,
DWORD BufferLength,
PTOKEN_GROUPS PreviousState,
- PDWORD ReturnLength
- )
+ PDWORD ReturnLength)
{
- NTSTATUS errCode;
- errCode = NtAdjustGroupsToken(TokenHandle,ResetToDefault,NewState,
- BufferLength, PreviousState, (PULONG)ReturnLength );
- if ( !NT_SUCCESS(errCode) ) {
- SetLastError(RtlNtStatusToDosError(errCode));
- return FALSE;
- }
- return TRUE;
+ NTSTATUS Status;
+
+ Status = NtAdjustGroupsToken (TokenHandle,
+ ResetToDefault,
+ NewState,
+ BufferLength,
+ PreviousState,
+ (PULONG)ReturnLength);
+ if (!NT_SUCCESS (Status))
+ {
+ SetLastError (RtlNtStatusToDosError (Status));
+ return FALSE;
+ }
+
+ return TRUE;
}
-WINBOOL
-STDCALL
-AdjustTokenPrivileges (
- HANDLE TokenHandle,
- WINBOOL DisableAllPrivileges,
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+AdjustTokenPrivileges (HANDLE TokenHandle,
+ BOOL DisableAllPrivileges,
PTOKEN_PRIVILEGES NewState,
DWORD BufferLength,
PTOKEN_PRIVILEGES PreviousState,
- PDWORD ReturnLength
- )
-{ NTSTATUS errCode;
- errCode = NtAdjustPrivilegesToken(TokenHandle,DisableAllPrivileges,NewState,
- BufferLength, PreviousState, (PULONG)ReturnLength );
- if ( !NT_SUCCESS(errCode) ) {
- SetLastError(RtlNtStatusToDosError(errCode));
- return FALSE;
- }
- return TRUE;
+ PDWORD ReturnLength)
+{
+ NTSTATUS Status;
+
+ Status = NtAdjustPrivilegesToken (TokenHandle,
+ DisableAllPrivileges,
+ NewState,
+ BufferLength,
+ PreviousState,
+ (PULONG)ReturnLength);
+ if (STATUS_NOT_ALL_ASSIGNED == Status)
+ {
+ SetLastError(ERROR_NOT_ALL_ASSIGNED);
+ return TRUE;
+ }
+ if (! NT_SUCCESS(Status))
+ {
+ SetLastError(RtlNtStatusToDosError(Status));
+ return FALSE;
+ }
+
+ SetLastError(ERROR_SUCCESS); /* AdjustTokenPrivileges is documented to do this */
+ return TRUE;
}
-WINBOOL
-STDCALL
-GetTokenInformation (
- HANDLE TokenHandle,
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetTokenInformation (HANDLE TokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
LPVOID TokenInformation,
DWORD TokenInformationLength,
- PDWORD ReturnLength
- )
+ PDWORD ReturnLength)
{
- NTSTATUS errCode;
- errCode = NtQueryInformationToken(TokenHandle,TokenInformationClass,TokenInformation,
- TokenInformationLength, (PULONG)ReturnLength);
- if ( !NT_SUCCESS(errCode) ) {
- SetLastError(RtlNtStatusToDosError(errCode));
- return FALSE;
- }
- return TRUE;
+ NTSTATUS Status;
+
+ Status = NtQueryInformationToken (TokenHandle,
+ TokenInformationClass,
+ TokenInformation,
+ TokenInformationLength,
+ (PULONG)ReturnLength);
+ if (!NT_SUCCESS (Status))
+ {
+ SetLastError (RtlNtStatusToDosError (Status));
+ return FALSE;
+ }
+
+ return TRUE;
}
-WINBOOL
-STDCALL
-SetTokenInformation (
- HANDLE TokenHandle,
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetTokenInformation (HANDLE TokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
LPVOID TokenInformation,
- DWORD TokenInformationLength
- )
+ DWORD TokenInformationLength)
{
- NTSTATUS errCode;
- errCode = NtSetInformationToken(TokenHandle,TokenInformationClass,TokenInformation,
- TokenInformationLength);
- if ( !NT_SUCCESS(errCode) ) {
- SetLastError(RtlNtStatusToDosError(errCode));
- return FALSE;
- }
- return TRUE;
+ NTSTATUS Status;
+
+ Status = NtSetInformationToken (TokenHandle,
+ TokenInformationClass,
+ TokenInformation,
+ TokenInformationLength);
+ if (!NT_SUCCESS (Status))
+ {
+ SetLastError (RtlNtStatusToDosError (Status));
+ return FALSE;
+ }
+
+ return TRUE;
}
-WINBOOL
-STDCALL
-AccessCheck (
- PSECURITY_DESCRIPTOR pSecurityDescriptor,
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+AccessCheck (PSECURITY_DESCRIPTOR pSecurityDescriptor,
HANDLE ClientToken,
DWORD DesiredAccess,
PGENERIC_MAPPING GenericMapping,
PPRIVILEGE_SET PrivilegeSet,
LPDWORD PrivilegeSetLength,
LPDWORD GrantedAccess,
- LPBOOL AccessStatus
- )
+ LPBOOL AccessStatus)
{
- NTSTATUS errCode;
- errCode = NtAccessCheck( pSecurityDescriptor,
- ClientToken,
- DesiredAccess,
- GenericMapping,
- PrivilegeSet,
- (PULONG)PrivilegeSetLength,
- (PULONG)GrantedAccess,
- (PBOOLEAN)AccessStatus);
- if ( !NT_SUCCESS(errCode) ) {
- SetLastError(RtlNtStatusToDosError(errCode));
- return FALSE;
- }
- return TRUE;
-}
+ NTSTATUS Status;
+ NTSTATUS AccessStat;
+
+ Status = NtAccessCheck (pSecurityDescriptor,
+ ClientToken,
+ DesiredAccess,
+ GenericMapping,
+ PrivilegeSet,
+ (PULONG)PrivilegeSetLength,
+ (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;
+}
-WINBOOL
-STDCALL
-OpenProcessToken (
- HANDLE ProcessHandle,
+/*
+ * @implemented
+ */
+BOOL STDCALL
+OpenProcessToken (HANDLE ProcessHandle,
DWORD DesiredAccess,
- PHANDLE TokenHandle
- )
+ PHANDLE TokenHandle)
{
- NTSTATUS errCode;
- errCode = NtOpenProcessToken(ProcessHandle,DesiredAccess,TokenHandle);
- if ( !NT_SUCCESS(errCode) ) {
- SetLastError(RtlNtStatusToDosError(errCode));
- return FALSE;
- }
- return TRUE;
-}
+ NTSTATUS Status;
+ Status = NtOpenProcessToken (ProcessHandle,
+ DesiredAccess,
+ TokenHandle);
+ if (!NT_SUCCESS (Status))
+ {
+ SetLastError (RtlNtStatusToDosError (Status));
+ return FALSE;
+ }
+
+ return TRUE;
+}
-WINBOOL
-STDCALL
-OpenThreadToken (
- HANDLE ThreadHandle,
+/*
+ * @implemented
+ */
+BOOL STDCALL
+OpenThreadToken (HANDLE ThreadHandle,
DWORD DesiredAccess,
- WINBOOL OpenAsSelf,
- PHANDLE TokenHandle
- )
+ BOOL OpenAsSelf,
+ PHANDLE TokenHandle)
{
- NTSTATUS errCode;
- errCode = NtOpenThreadToken(ThreadHandle,DesiredAccess,OpenAsSelf,TokenHandle);
- if ( !NT_SUCCESS(errCode) ) {
- SetLastError(RtlNtStatusToDosError(errCode));
- return FALSE;
- }
- return TRUE;
+ NTSTATUS Status;
+
+ Status = NtOpenThreadToken (ThreadHandle,
+ DesiredAccess,
+ OpenAsSelf,
+ TokenHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastError (RtlNtStatusToDosError (Status));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetThreadToken (IN PHANDLE ThreadHandle OPTIONAL,
+ IN HANDLE TokenHandle)
+{
+ NTSTATUS Status;
+ HANDLE hThread;
+
+ hThread = ((ThreadHandle != NULL) ? *ThreadHandle : NtCurrentThread());
+
+ Status = NtSetInformationThread (hThread,
+ ThreadImpersonationToken,
+ &TokenHandle,
+ sizeof(HANDLE));
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastError (RtlNtStatusToDosError (Status));
+ return FALSE;
+ }
+
+ return TRUE;
}
-WINBOOL
-STDCALL
-SetThreadToken (
- PHANDLE ThreadHandle,
- HANDLE TokenHandle
- )
+/*
+ * @implemented
+ */
+BOOL STDCALL
+DuplicateTokenEx (IN HANDLE ExistingTokenHandle,
+ IN DWORD dwDesiredAccess,
+ IN LPSECURITY_ATTRIBUTES lpTokenAttributes OPTIONAL,
+ IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
+ IN TOKEN_TYPE TokenType,
+ OUT PHANDLE DuplicateTokenHandle)
{
- NTSTATUS errCode;
- HANDLE hThread = NtCurrentThread();
- if ( ThreadHandle != NULL )
- hThread = ThreadHandle;
- errCode = NtSetInformationThread(hThread,ThreadImpersonationToken,TokenHandle,sizeof(HANDLE));
- if ( !NT_SUCCESS(errCode) ) {
- SetLastError(RtlNtStatusToDosError(errCode));
- return FALSE;
- }
- return TRUE;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ SECURITY_QUALITY_OF_SERVICE Sqos;
+
+ Sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
+ Sqos.ImpersonationLevel = ImpersonationLevel;
+ Sqos.ContextTrackingMode = 0;
+ Sqos.EffectiveOnly = FALSE;
+
+ if (lpTokenAttributes != NULL)
+ {
+ InitializeObjectAttributes(&ObjectAttributes,
+ NULL,
+ lpTokenAttributes->bInheritHandle ? OBJ_INHERIT : 0,
+ NULL,
+ lpTokenAttributes->lpSecurityDescriptor);
+ }
+ else
+ {
+ InitializeObjectAttributes(&ObjectAttributes,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ }
+
+ ObjectAttributes.SecurityQualityOfService = &Sqos;
+
+ Status = NtDuplicateToken (ExistingTokenHandle,
+ dwDesiredAccess,
+ &ObjectAttributes,
+ FALSE,
+ TokenType,
+ DuplicateTokenHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastError(RtlNtStatusToDosError(Status));
+ return FALSE;
+ }
+
+ return TRUE;
}
-WINBOOL
-STDCALL
-DuplicateTokenEx (
- HANDLE ExistingTokenHandle,
- DWORD dwDesiredAccess,
- LPSECURITY_ATTRIBUTES lpTokenAttributes,
- SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
- TOKEN_TYPE TokenType,
- PHANDLE DuplicateTokenHandle
- )
+/*
+ * @implemented
+ */
+BOOL STDCALL
+DuplicateToken (IN HANDLE ExistingTokenHandle,
+ IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
+ OUT PHANDLE DuplicateTokenHandle)
{
- NTSTATUS errCode;
- HANDLE NewToken;
-
- OBJECT_ATTRIBUTES ObjectAttributes;
-
-
- ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
- ObjectAttributes.RootDirectory = NULL;
- ObjectAttributes.ObjectName = NULL;
- ObjectAttributes.Attributes = 0;
- if ( lpTokenAttributes->bInheritHandle )
- ObjectAttributes.Attributes |= OBJ_INHERIT;
-
- ObjectAttributes.SecurityDescriptor = lpTokenAttributes->lpSecurityDescriptor;
- ObjectAttributes.SecurityQualityOfService = NULL;
-
- errCode = NtDuplicateToken( ExistingTokenHandle, dwDesiredAccess,
- &ObjectAttributes, ImpersonationLevel,
- TokenType, &NewToken );
-
- if ( !NT_SUCCESS(errCode) ) {
- SetLastError(RtlNtStatusToDosError(errCode));
- return FALSE;
- }
- return TRUE;
+ return DuplicateTokenEx (ExistingTokenHandle,
+ TOKEN_IMPERSONATE | TOKEN_QUERY,
+ NULL,
+ ImpersonationLevel,
+ TokenImpersonation,
+ DuplicateTokenHandle);
}
-WINBOOL
-STDCALL
-DuplicateToken (
- HANDLE ExistingTokenHandle,
- SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
- PHANDLE DuplicateTokenHandle
- )
+/*
+ * @implemented
+ */
+BOOL STDCALL
+CheckTokenMembership(IN HANDLE ExistingTokenHandle,
+ IN PSID SidToCheck,
+ OUT PBOOL IsMember)
{
- return DuplicateTokenEx (
- ExistingTokenHandle,
- TOKEN_DUPLICATE|TOKEN_IMPERSONATE|TOKEN_QUERY,
- NULL,
- ImpersonationLevel,
- TokenImpersonation,
- DuplicateTokenHandle
- );
+ 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;
+}