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)
20 AdjustTokenGroups (HANDLE TokenHandle
,
22 PTOKEN_GROUPS NewState
,
24 PTOKEN_GROUPS PreviousState
,
29 Status
= NtAdjustGroupsToken (TokenHandle
,
34 (PULONG
)ReturnLength
);
35 if (!NT_SUCCESS (Status
))
37 SetLastError (RtlNtStatusToDosError (Status
));
49 AdjustTokenPrivileges (HANDLE TokenHandle
,
50 BOOL DisableAllPrivileges
,
51 PTOKEN_PRIVILEGES NewState
,
53 PTOKEN_PRIVILEGES PreviousState
,
58 Status
= NtAdjustPrivilegesToken (TokenHandle
,
63 (PULONG
)ReturnLength
);
64 if (STATUS_NOT_ALL_ASSIGNED
== Status
)
66 SetLastError(ERROR_NOT_ALL_ASSIGNED
);
69 if (! NT_SUCCESS(Status
))
71 SetLastError(RtlNtStatusToDosError(Status
));
75 SetLastError(ERROR_SUCCESS
); /* AdjustTokenPrivileges is documented to do this */
84 GetTokenInformation (HANDLE TokenHandle
,
85 TOKEN_INFORMATION_CLASS TokenInformationClass
,
86 LPVOID TokenInformation
,
87 DWORD TokenInformationLength
,
92 Status
= NtQueryInformationToken (TokenHandle
,
93 TokenInformationClass
,
95 TokenInformationLength
,
96 (PULONG
)ReturnLength
);
97 if (!NT_SUCCESS (Status
))
99 SetLastError (RtlNtStatusToDosError (Status
));
111 SetTokenInformation (HANDLE TokenHandle
,
112 TOKEN_INFORMATION_CLASS TokenInformationClass
,
113 LPVOID TokenInformation
,
114 DWORD TokenInformationLength
)
118 Status
= NtSetInformationToken (TokenHandle
,
119 TokenInformationClass
,
121 TokenInformationLength
);
122 if (!NT_SUCCESS (Status
))
124 SetLastError (RtlNtStatusToDosError (Status
));
136 AccessCheck (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
139 PGENERIC_MAPPING GenericMapping
,
140 PPRIVILEGE_SET PrivilegeSet
,
141 LPDWORD PrivilegeSetLength
,
142 LPDWORD GrantedAccess
,
148 Status
= NtAccessCheck (pSecurityDescriptor
,
153 (PULONG
)PrivilegeSetLength
,
154 (PACCESS_MASK
)GrantedAccess
,
156 if (!NT_SUCCESS (Status
))
158 SetLastError (RtlNtStatusToDosError (Status
));
162 if (!NT_SUCCESS (AccessStat
))
164 SetLastError (RtlNtStatusToDosError (Status
));
165 *AccessStatus
= FALSE
;
169 *AccessStatus
= TRUE
;
179 OpenProcessToken (HANDLE ProcessHandle
,
185 Status
= NtOpenProcessToken (ProcessHandle
,
188 if (!NT_SUCCESS (Status
))
190 SetLastError (RtlNtStatusToDosError (Status
));
202 OpenThreadToken (HANDLE ThreadHandle
,
209 Status
= NtOpenThreadToken (ThreadHandle
,
213 if (!NT_SUCCESS(Status
))
215 SetLastError (RtlNtStatusToDosError (Status
));
227 SetThreadToken (IN PHANDLE ThreadHandle OPTIONAL
,
228 IN HANDLE TokenHandle
)
233 hThread
= ((ThreadHandle
!= NULL
) ? *ThreadHandle
: NtCurrentThread());
235 Status
= NtSetInformationThread (hThread
,
236 ThreadImpersonationToken
,
239 if (!NT_SUCCESS(Status
))
241 SetLastError (RtlNtStatusToDosError (Status
));
253 DuplicateTokenEx (IN HANDLE ExistingTokenHandle
,
254 IN DWORD dwDesiredAccess
,
255 IN LPSECURITY_ATTRIBUTES lpTokenAttributes OPTIONAL
,
256 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
257 IN TOKEN_TYPE TokenType
,
258 OUT PHANDLE DuplicateTokenHandle
)
260 OBJECT_ATTRIBUTES ObjectAttributes
;
262 SECURITY_QUALITY_OF_SERVICE Sqos
;
264 Sqos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
265 Sqos
.ImpersonationLevel
= ImpersonationLevel
;
266 Sqos
.ContextTrackingMode
= 0;
267 Sqos
.EffectiveOnly
= FALSE
;
269 if (lpTokenAttributes
!= NULL
)
271 InitializeObjectAttributes(&ObjectAttributes
,
273 lpTokenAttributes
->bInheritHandle
? OBJ_INHERIT
: 0,
275 lpTokenAttributes
->lpSecurityDescriptor
);
279 InitializeObjectAttributes(&ObjectAttributes
,
286 ObjectAttributes
.SecurityQualityOfService
= &Sqos
;
288 Status
= NtDuplicateToken (ExistingTokenHandle
,
293 DuplicateTokenHandle
);
294 if (!NT_SUCCESS(Status
))
296 SetLastError(RtlNtStatusToDosError(Status
));
308 DuplicateToken (IN HANDLE ExistingTokenHandle
,
309 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
310 OUT PHANDLE DuplicateTokenHandle
)
312 return DuplicateTokenEx (ExistingTokenHandle
,
313 TOKEN_IMPERSONATE
| TOKEN_QUERY
,
317 DuplicateTokenHandle
);
325 CheckTokenMembership(IN HANDLE ExistingTokenHandle
,
329 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
330 ACCESS_MASK GrantedAccess
;
333 PRIVILEGE_SET PrivilegeSet
;
334 LUID_AND_ATTRIBUTES Privileges
[4];
336 ULONG PrivBufferSize
= sizeof(PrivBuffer
);
337 GENERIC_MAPPING GenericMapping
=
339 STANDARD_RIGHTS_READ
,
340 STANDARD_RIGHTS_WRITE
,
341 STANDARD_RIGHTS_EXECUTE
,
346 HANDLE hToken
= NULL
;
347 NTSTATUS Status
, AccessStatus
;
349 /* doesn't return gracefully if IsMember is NULL! */
352 SidLen
= RtlLengthSid(SidToCheck
);
354 if (ExistingTokenHandle
== NULL
)
356 Status
= NtOpenThreadToken(NtCurrentThread(),
361 if (Status
== STATUS_NO_TOKEN
)
363 /* we're not impersonating, open the primary token */
364 Status
= NtOpenProcessToken(NtCurrentProcess(),
365 TOKEN_QUERY
| TOKEN_DUPLICATE
,
367 if (NT_SUCCESS(Status
))
369 HANDLE hNewToken
= FALSE
;
372 /* duplicate the primary token to create an impersonation token */
373 DupRet
= DuplicateTokenEx(hToken
,
374 TOKEN_QUERY
| TOKEN_IMPERSONATE
,
376 SecurityImpersonation
,
384 DPRINT1("Failed to duplicate the primary token!\n");
392 if (!NT_SUCCESS(Status
))
399 hToken
= ExistingTokenHandle
;
402 /* create a security descriptor */
403 SecurityDescriptor
= RtlAllocateHeap(RtlGetProcessHeap(),
405 sizeof(SECURITY_DESCRIPTOR
) +
406 sizeof(ACL
) + SidLen
+
407 sizeof(ACCESS_ALLOWED_ACE
));
408 if (SecurityDescriptor
== NULL
)
410 Status
= STATUS_INSUFFICIENT_RESOURCES
;
414 Status
= RtlCreateSecurityDescriptor(SecurityDescriptor
,
415 SECURITY_DESCRIPTOR_REVISION
);
416 if (!NT_SUCCESS(Status
))
421 /* set the owner and group */
422 Status
= RtlSetOwnerSecurityDescriptor(SecurityDescriptor
,
425 if (!NT_SUCCESS(Status
))
430 Status
= RtlSetGroupSecurityDescriptor(SecurityDescriptor
,
433 if (!NT_SUCCESS(Status
))
438 /* create the DACL */
439 Dacl
= (PACL
)(SecurityDescriptor
+ 1);
440 Status
= RtlCreateAcl(Dacl
,
441 sizeof(ACL
) + SidLen
+ sizeof(ACCESS_ALLOWED_ACE
),
443 if (!NT_SUCCESS(Status
))
448 Status
= RtlAddAccessAllowedAce(Dacl
,
452 if (!NT_SUCCESS(Status
))
457 /* assign the DACL to the security descriptor */
458 Status
= RtlSetDaclSecurityDescriptor(SecurityDescriptor
,
462 if (!NT_SUCCESS(Status
))
467 /* it's time to perform the access check. Just use _some_ desired access right
468 (same as for the ACE) and see if we're getting it granted. This indicates
469 our SID is a member of the token. We however can't use a generic access
470 right as those aren't mapped and return an error (STATUS_GENERIC_NOT_MAPPED). */
471 Status
= NtAccessCheck(SecurityDescriptor
,
475 &PrivBuffer
.PrivilegeSet
,
480 if (NT_SUCCESS(Status
) && NT_SUCCESS(AccessStatus
) && (GrantedAccess
== 0x1))
486 if (hToken
!= NULL
&& hToken
!= ExistingTokenHandle
)
491 if (SecurityDescriptor
!= NULL
)
493 RtlFreeHeap(RtlGetProcessHeap(),
498 if (!NT_SUCCESS(Status
))
500 SetLastError(RtlNtStatusToDosError(Status
));
512 IsTokenRestricted(HANDLE TokenHandle
)
515 PTOKEN_GROUPS lpGroups
;
519 /* determine the required buffer size and allocate enough memory to read the
520 list of restricted SIDs */
522 Status
= NtQueryInformationToken(TokenHandle
,
527 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
529 SetLastError(RtlNtStatusToDosError(Status
));
533 AllocAndReadRestrictedSids
:
534 lpGroups
= (PTOKEN_GROUPS
)HeapAlloc(GetProcessHeap(),
537 if (lpGroups
== NULL
)
539 SetLastError(ERROR_OUTOFMEMORY
);
543 /* actually read the list of the restricted SIDs */
545 Status
= NtQueryInformationToken(TokenHandle
,
550 if (NT_SUCCESS(Status
))
552 Ret
= (lpGroups
->GroupCount
!= 0);
554 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
556 /* looks like the token was modified in the meanwhile, let's just try again */
558 HeapFree(GetProcessHeap(),
562 goto AllocAndReadRestrictedSids
;
566 SetLastError(RtlNtStatusToDosError(Status
));
569 /* free allocated memory */
571 HeapFree(GetProcessHeap(),