2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/advapi32/token/token.c
5 * PURPOSE: Token functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
13 #include <ndk/setypes.h>
15 WINE_DEFAULT_DEBUG_CHANNEL(advapi
);
21 AdjustTokenGroups(HANDLE TokenHandle
,
23 PTOKEN_GROUPS NewState
,
25 PTOKEN_GROUPS PreviousState
,
30 Status
= NtAdjustGroupsToken(TokenHandle
,
35 (PULONG
)ReturnLength
);
36 if (!NT_SUCCESS(Status
))
38 SetLastError(RtlNtStatusToDosError(Status
));
50 AdjustTokenPrivileges(HANDLE TokenHandle
,
51 BOOL DisableAllPrivileges
,
52 PTOKEN_PRIVILEGES NewState
,
54 PTOKEN_PRIVILEGES PreviousState
,
59 Status
= NtAdjustPrivilegesToken(TokenHandle
,
64 (PULONG
)ReturnLength
);
65 if (STATUS_NOT_ALL_ASSIGNED
== Status
)
67 SetLastError(ERROR_NOT_ALL_ASSIGNED
);
71 if (!NT_SUCCESS(Status
))
73 SetLastError(RtlNtStatusToDosError(Status
));
77 /* AdjustTokenPrivileges is documented to do this */
78 SetLastError(ERROR_SUCCESS
);
88 GetTokenInformation(HANDLE TokenHandle
,
89 TOKEN_INFORMATION_CLASS TokenInformationClass
,
90 LPVOID TokenInformation
,
91 DWORD TokenInformationLength
,
96 Status
= NtQueryInformationToken(TokenHandle
,
97 TokenInformationClass
,
99 TokenInformationLength
,
100 (PULONG
)ReturnLength
);
101 if (!NT_SUCCESS(Status
))
103 SetLastError(RtlNtStatusToDosError(Status
));
115 SetTokenInformation(HANDLE TokenHandle
,
116 TOKEN_INFORMATION_CLASS TokenInformationClass
,
117 LPVOID TokenInformation
,
118 DWORD TokenInformationLength
)
122 Status
= NtSetInformationToken(TokenHandle
,
123 TokenInformationClass
,
125 TokenInformationLength
);
126 if (!NT_SUCCESS(Status
))
128 SetLastError(RtlNtStatusToDosError(Status
));
141 AccessCheck(IN PSECURITY_DESCRIPTOR pSecurityDescriptor
,
142 IN HANDLE ClientToken
,
143 IN DWORD DesiredAccess
,
144 IN PGENERIC_MAPPING GenericMapping
,
145 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL
,
146 IN OUT LPDWORD PrivilegeSetLength
,
147 OUT LPDWORD GrantedAccess
,
148 OUT LPBOOL AccessStatus
)
151 NTSTATUS NtAccessStatus
;
153 /* Do the access check */
154 Status
= NtAccessCheck(pSecurityDescriptor
,
159 (PULONG
)PrivilegeSetLength
,
160 (PACCESS_MASK
)GrantedAccess
,
163 /* See if the access check operation succeeded */
164 if (!NT_SUCCESS(Status
))
167 SetLastError(RtlNtStatusToDosError(Status
));
171 /* Now check the access status */
172 if (!NT_SUCCESS(NtAccessStatus
))
175 SetLastError(RtlNtStatusToDosError(NtAccessStatus
));
176 *AccessStatus
= FALSE
;
181 *AccessStatus
= TRUE
;
184 /* Check succeeded */
191 BOOL WINAPI
AccessCheckByType(
192 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
193 PSID PrincipalSelfSid
,
196 POBJECT_TYPE_LIST ObjectTypeList
,
197 DWORD ObjectTypeListLength
,
198 PGENERIC_MAPPING GenericMapping
,
199 PPRIVILEGE_SET PrivilegeSet
,
200 LPDWORD PrivilegeSetLength
,
201 LPDWORD GrantedAccess
,
206 *AccessStatus
= TRUE
;
208 return !*AccessStatus
;
215 OpenProcessToken(HANDLE ProcessHandle
,
221 TRACE("%p, %x, %p.\n", ProcessHandle
, DesiredAccess
, TokenHandle
);
223 Status
= NtOpenProcessToken(ProcessHandle
,
226 if (!NT_SUCCESS(Status
))
228 ERR("NtOpenProcessToken failed! Status %08x.\n", Status
);
229 SetLastError(RtlNtStatusToDosError(Status
));
233 TRACE("Returning token %p.\n", *TokenHandle
);
243 OpenThreadToken(HANDLE ThreadHandle
,
250 Status
= NtOpenThreadToken(ThreadHandle
,
254 if (!NT_SUCCESS(Status
))
256 SetLastError(RtlNtStatusToDosError(Status
));
268 SetThreadToken(IN PHANDLE ThreadHandle OPTIONAL
,
269 IN HANDLE TokenHandle
)
274 hThread
= (ThreadHandle
!= NULL
) ? *ThreadHandle
: NtCurrentThread();
276 Status
= NtSetInformationThread(hThread
,
277 ThreadImpersonationToken
,
280 if (!NT_SUCCESS(Status
))
282 SetLastError(RtlNtStatusToDosError(Status
));
294 DuplicateTokenEx(IN HANDLE ExistingTokenHandle
,
295 IN DWORD dwDesiredAccess
,
296 IN LPSECURITY_ATTRIBUTES lpTokenAttributes OPTIONAL
,
297 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
298 IN TOKEN_TYPE TokenType
,
299 OUT PHANDLE DuplicateTokenHandle
)
301 OBJECT_ATTRIBUTES ObjectAttributes
;
303 SECURITY_QUALITY_OF_SERVICE Sqos
;
305 TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle
, dwDesiredAccess
,
306 ImpersonationLevel
, TokenType
, DuplicateTokenHandle
);
308 Sqos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
309 Sqos
.ImpersonationLevel
= ImpersonationLevel
;
310 Sqos
.ContextTrackingMode
= 0;
311 Sqos
.EffectiveOnly
= FALSE
;
313 if (lpTokenAttributes
!= NULL
)
315 InitializeObjectAttributes(&ObjectAttributes
,
317 lpTokenAttributes
->bInheritHandle
? OBJ_INHERIT
: 0,
319 lpTokenAttributes
->lpSecurityDescriptor
);
323 InitializeObjectAttributes(&ObjectAttributes
,
330 ObjectAttributes
.SecurityQualityOfService
= &Sqos
;
332 Status
= NtDuplicateToken(ExistingTokenHandle
,
337 DuplicateTokenHandle
);
338 if (!NT_SUCCESS(Status
))
340 ERR("NtDuplicateToken failed: Status %08x\n", Status
);
341 SetLastError(RtlNtStatusToDosError(Status
));
345 TRACE("Returning token %p.\n", *DuplicateTokenHandle
);
355 DuplicateToken(IN HANDLE ExistingTokenHandle
,
356 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
357 OUT PHANDLE DuplicateTokenHandle
)
359 return DuplicateTokenEx(ExistingTokenHandle
,
360 TOKEN_IMPERSONATE
| TOKEN_QUERY
,
364 DuplicateTokenHandle
);
372 CheckTokenMembership(IN HANDLE ExistingTokenHandle
,
376 PISECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
377 ACCESS_MASK GrantedAccess
;
380 PRIVILEGE_SET PrivilegeSet
;
381 LUID_AND_ATTRIBUTES Privileges
[4];
383 ULONG PrivBufferSize
= sizeof(PrivBuffer
);
384 GENERIC_MAPPING GenericMapping
=
386 STANDARD_RIGHTS_READ
,
387 STANDARD_RIGHTS_WRITE
,
388 STANDARD_RIGHTS_EXECUTE
,
393 HANDLE hToken
= NULL
;
394 NTSTATUS Status
, AccessStatus
;
396 /* doesn't return gracefully if IsMember is NULL! */
399 SidLen
= RtlLengthSid(SidToCheck
);
401 if (ExistingTokenHandle
== NULL
)
403 Status
= NtOpenThreadToken(NtCurrentThread(),
408 if (Status
== STATUS_NO_TOKEN
)
410 /* we're not impersonating, open the primary token */
411 Status
= NtOpenProcessToken(NtCurrentProcess(),
412 TOKEN_QUERY
| TOKEN_DUPLICATE
,
414 if (NT_SUCCESS(Status
))
416 HANDLE hNewToken
= FALSE
;
419 /* duplicate the primary token to create an impersonation token */
420 DupRet
= DuplicateTokenEx(hToken
,
421 TOKEN_QUERY
| TOKEN_IMPERSONATE
,
423 SecurityImpersonation
,
431 WARN("Failed to duplicate the primary token!\n");
439 if (!NT_SUCCESS(Status
))
446 hToken
= ExistingTokenHandle
;
449 /* create a security descriptor */
450 SecurityDescriptor
= RtlAllocateHeap(RtlGetProcessHeap(),
452 sizeof(SECURITY_DESCRIPTOR
) +
453 sizeof(ACL
) + SidLen
+
454 sizeof(ACCESS_ALLOWED_ACE
));
455 if (SecurityDescriptor
== NULL
)
457 Status
= STATUS_INSUFFICIENT_RESOURCES
;
461 Status
= RtlCreateSecurityDescriptor(SecurityDescriptor
,
462 SECURITY_DESCRIPTOR_REVISION
);
463 if (!NT_SUCCESS(Status
))
468 /* set the owner and group */
469 Status
= RtlSetOwnerSecurityDescriptor(SecurityDescriptor
,
472 if (!NT_SUCCESS(Status
))
477 Status
= RtlSetGroupSecurityDescriptor(SecurityDescriptor
,
480 if (!NT_SUCCESS(Status
))
485 /* create the DACL */
486 Dacl
= (PACL
)(SecurityDescriptor
+ 1);
487 Status
= RtlCreateAcl(Dacl
,
488 sizeof(ACL
) + SidLen
+ sizeof(ACCESS_ALLOWED_ACE
),
490 if (!NT_SUCCESS(Status
))
495 Status
= RtlAddAccessAllowedAce(Dacl
,
499 if (!NT_SUCCESS(Status
))
504 /* assign the DACL to the security descriptor */
505 Status
= RtlSetDaclSecurityDescriptor(SecurityDescriptor
,
509 if (!NT_SUCCESS(Status
))
514 /* it's time to perform the access check. Just use _some_ desired access right
515 (same as for the ACE) and see if we're getting it granted. This indicates
516 our SID is a member of the token. We however can't use a generic access
517 right as those aren't mapped and return an error (STATUS_GENERIC_NOT_MAPPED). */
518 Status
= NtAccessCheck(SecurityDescriptor
,
522 &PrivBuffer
.PrivilegeSet
,
526 if (NT_SUCCESS(Status
) && NT_SUCCESS(AccessStatus
) && (GrantedAccess
== 0x1))
532 if (hToken
!= NULL
&& hToken
!= ExistingTokenHandle
)
537 if (SecurityDescriptor
!= NULL
)
539 RtlFreeHeap(RtlGetProcessHeap(),
544 if (!NT_SUCCESS(Status
))
546 SetLastError(RtlNtStatusToDosError(Status
));
558 IsTokenRestricted(HANDLE TokenHandle
)
561 PTOKEN_GROUPS lpGroups
;
565 /* determine the required buffer size and allocate enough memory to read the
566 list of restricted SIDs */
567 Status
= NtQueryInformationToken(TokenHandle
,
572 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
574 SetLastError(RtlNtStatusToDosError(Status
));
578 AllocAndReadRestrictedSids
:
579 lpGroups
= (PTOKEN_GROUPS
)HeapAlloc(GetProcessHeap(),
582 if (lpGroups
== NULL
)
584 SetLastError(ERROR_OUTOFMEMORY
);
588 /* actually read the list of the restricted SIDs */
589 Status
= NtQueryInformationToken(TokenHandle
,
594 if (NT_SUCCESS(Status
))
596 Ret
= (lpGroups
->GroupCount
!= 0);
598 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
600 /* looks like the token was modified in the meanwhile, let's just try again */
601 HeapFree(GetProcessHeap(),
605 goto AllocAndReadRestrictedSids
;
609 SetLastError(RtlNtStatusToDosError(Status
));
612 /* free allocated memory */
613 HeapFree(GetProcessHeap(),
622 CreateRestrictedToken(HANDLE TokenHandle
,
624 DWORD DisableSidCount
,
625 PSID_AND_ATTRIBUTES pSidAndAttributes
,
626 DWORD DeletePrivilegeCount
,
627 PLUID_AND_ATTRIBUTES pLUIDAndAttributes
,
628 DWORD RestrictedSidCount
,
629 PSID_AND_ATTRIBUTES pSIDAndAttributes
,
630 PHANDLE NewTokenHandle
)
642 GetSiteSidFromToken(IN HANDLE TokenHandle
)
644 PTOKEN_GROUPS RestrictedSids
;
648 PSID PSiteSid
= NULL
;
649 SID_IDENTIFIER_AUTHORITY InternetSiteAuthority
= {SECURITY_INTERNETSITE_AUTHORITY
};
651 Status
= NtQueryInformationToken(TokenHandle
,
656 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
658 SetLastError(RtlNtStatusToDosError(Status
));
662 RestrictedSids
= (PTOKEN_GROUPS
)RtlAllocateHeap(RtlGetProcessHeap(),
665 if (RestrictedSids
== NULL
)
667 SetLastError(ERROR_OUTOFMEMORY
);
671 Status
= NtQueryInformationToken(TokenHandle
,
676 if (NT_SUCCESS(Status
))
678 for (i
= 0; i
< RestrictedSids
->GroupCount
; i
++)
680 SID
* RSSid
= RestrictedSids
->Groups
[i
].Sid
;
682 if (RtlCompareMemory(&(RSSid
->IdentifierAuthority
),
683 &InternetSiteAuthority
,
684 sizeof(SID_IDENTIFIER_AUTHORITY
)) ==
685 sizeof(SID_IDENTIFIER_AUTHORITY
))
687 PSiteSid
= RtlAllocateHeap(RtlGetProcessHeap(),
689 RtlLengthSid((RestrictedSids
->
691 if (PSiteSid
== NULL
)
693 SetLastError(ERROR_OUTOFMEMORY
);
697 RtlCopySid(RtlLengthSid(RestrictedSids
->Groups
[i
].Sid
),
699 RestrictedSids
->Groups
[i
].Sid
);
708 SetLastError(RtlNtStatusToDosError(Status
));
711 RtlFreeHeap(RtlGetProcessHeap(), 0, RestrictedSids
);
718 CreateProcessWithTokenW(IN HANDLE hToken
,
719 IN DWORD dwLogonFlags
,
720 IN LPCWSTR lpApplicationName OPTIONAL
,
721 IN OUT LPWSTR lpCommandLine OPTIONAL
,
722 IN DWORD dwCreationFlags
,
723 IN LPVOID lpEnvironment OPTIONAL
,
724 IN LPCWSTR lpCurrentDirectory OPTIONAL
,
725 IN LPSTARTUPINFOW lpStartupInfo
,
726 OUT LPPROCESS_INFORMATION lpProcessInfo
)