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)
14 #include <wine/debug.h>
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
);
70 if (! NT_SUCCESS(Status
))
72 SetLastError(RtlNtStatusToDosError(Status
));
76 SetLastError(ERROR_SUCCESS
); /* AdjustTokenPrivileges is documented to do this */
85 GetTokenInformation (HANDLE TokenHandle
,
86 TOKEN_INFORMATION_CLASS TokenInformationClass
,
87 LPVOID TokenInformation
,
88 DWORD TokenInformationLength
,
93 Status
= NtQueryInformationToken (TokenHandle
,
94 TokenInformationClass
,
96 TokenInformationLength
,
97 (PULONG
)ReturnLength
);
98 if (!NT_SUCCESS (Status
))
100 SetLastError (RtlNtStatusToDosError (Status
));
112 SetTokenInformation (HANDLE TokenHandle
,
113 TOKEN_INFORMATION_CLASS TokenInformationClass
,
114 LPVOID TokenInformation
,
115 DWORD TokenInformationLength
)
119 Status
= NtSetInformationToken (TokenHandle
,
120 TokenInformationClass
,
122 TokenInformationLength
);
123 if (!NT_SUCCESS (Status
))
125 SetLastError (RtlNtStatusToDosError (Status
));
137 AccessCheck (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
140 PGENERIC_MAPPING GenericMapping
,
141 PPRIVILEGE_SET PrivilegeSet
,
142 LPDWORD PrivilegeSetLength
,
143 LPDWORD GrantedAccess
,
149 Status
= NtAccessCheck (pSecurityDescriptor
,
154 (PULONG
)PrivilegeSetLength
,
155 (PACCESS_MASK
)GrantedAccess
,
157 if (!NT_SUCCESS (Status
))
159 SetLastError (RtlNtStatusToDosError (Status
));
163 if (!NT_SUCCESS (AccessStat
))
165 SetLastError (RtlNtStatusToDosError (Status
));
166 *AccessStatus
= FALSE
;
170 *AccessStatus
= TRUE
;
180 OpenProcessToken (HANDLE ProcessHandle
,
186 Status
= NtOpenProcessToken (ProcessHandle
,
189 if (!NT_SUCCESS (Status
))
191 SetLastError (RtlNtStatusToDosError (Status
));
203 OpenThreadToken (HANDLE ThreadHandle
,
210 Status
= NtOpenThreadToken (ThreadHandle
,
214 if (!NT_SUCCESS(Status
))
216 SetLastError (RtlNtStatusToDosError (Status
));
228 SetThreadToken (IN PHANDLE ThreadHandle OPTIONAL
,
229 IN HANDLE TokenHandle
)
234 hThread
= ((ThreadHandle
!= NULL
) ? *ThreadHandle
: NtCurrentThread());
236 Status
= NtSetInformationThread (hThread
,
237 ThreadImpersonationToken
,
240 if (!NT_SUCCESS(Status
))
242 SetLastError (RtlNtStatusToDosError (Status
));
254 DuplicateTokenEx (IN HANDLE ExistingTokenHandle
,
255 IN DWORD dwDesiredAccess
,
256 IN LPSECURITY_ATTRIBUTES lpTokenAttributes OPTIONAL
,
257 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
258 IN TOKEN_TYPE TokenType
,
259 OUT PHANDLE DuplicateTokenHandle
)
261 OBJECT_ATTRIBUTES ObjectAttributes
;
263 SECURITY_QUALITY_OF_SERVICE Sqos
;
265 Sqos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
266 Sqos
.ImpersonationLevel
= ImpersonationLevel
;
267 Sqos
.ContextTrackingMode
= 0;
268 Sqos
.EffectiveOnly
= FALSE
;
270 if (lpTokenAttributes
!= NULL
)
272 InitializeObjectAttributes(&ObjectAttributes
,
274 lpTokenAttributes
->bInheritHandle
? OBJ_INHERIT
: 0,
276 lpTokenAttributes
->lpSecurityDescriptor
);
280 InitializeObjectAttributes(&ObjectAttributes
,
287 ObjectAttributes
.SecurityQualityOfService
= &Sqos
;
289 Status
= NtDuplicateToken (ExistingTokenHandle
,
294 DuplicateTokenHandle
);
295 if (!NT_SUCCESS(Status
))
297 SetLastError(RtlNtStatusToDosError(Status
));
309 DuplicateToken (IN HANDLE ExistingTokenHandle
,
310 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
311 OUT PHANDLE DuplicateTokenHandle
)
313 return DuplicateTokenEx (ExistingTokenHandle
,
314 TOKEN_IMPERSONATE
| TOKEN_QUERY
,
318 DuplicateTokenHandle
);
326 CheckTokenMembership(IN HANDLE ExistingTokenHandle
,
330 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
331 ACCESS_MASK GrantedAccess
;
334 PRIVILEGE_SET PrivilegeSet
;
335 LUID_AND_ATTRIBUTES Privileges
[4];
337 ULONG PrivBufferSize
= sizeof(PrivBuffer
);
338 GENERIC_MAPPING GenericMapping
=
340 STANDARD_RIGHTS_READ
,
341 STANDARD_RIGHTS_WRITE
,
342 STANDARD_RIGHTS_EXECUTE
,
347 HANDLE hToken
= NULL
;
348 NTSTATUS Status
, AccessStatus
;
350 /* doesn't return gracefully if IsMember is NULL! */
353 SidLen
= RtlLengthSid(SidToCheck
);
355 if (ExistingTokenHandle
== NULL
)
357 Status
= NtOpenThreadToken(NtCurrentThread(),
362 if (Status
== STATUS_NO_TOKEN
)
364 /* we're not impersonating, open the primary token */
365 Status
= NtOpenProcessToken(NtCurrentProcess(),
366 TOKEN_QUERY
| TOKEN_DUPLICATE
,
368 if (NT_SUCCESS(Status
))
370 HANDLE hNewToken
= FALSE
;
373 /* duplicate the primary token to create an impersonation token */
374 DupRet
= DuplicateTokenEx(hToken
,
375 TOKEN_QUERY
| TOKEN_IMPERSONATE
,
377 SecurityImpersonation
,
385 DPRINT1("Failed to duplicate the primary token!\n");
393 if (!NT_SUCCESS(Status
))
400 hToken
= ExistingTokenHandle
;
403 /* create a security descriptor */
404 SecurityDescriptor
= RtlAllocateHeap(RtlGetProcessHeap(),
406 sizeof(SECURITY_DESCRIPTOR
) +
407 sizeof(ACL
) + SidLen
+
408 sizeof(ACCESS_ALLOWED_ACE
));
409 if (SecurityDescriptor
== NULL
)
411 Status
= STATUS_INSUFFICIENT_RESOURCES
;
415 Status
= RtlCreateSecurityDescriptor(SecurityDescriptor
,
416 SECURITY_DESCRIPTOR_REVISION
);
417 if (!NT_SUCCESS(Status
))
422 /* set the owner and group */
423 Status
= RtlSetOwnerSecurityDescriptor(SecurityDescriptor
,
426 if (!NT_SUCCESS(Status
))
431 Status
= RtlSetGroupSecurityDescriptor(SecurityDescriptor
,
434 if (!NT_SUCCESS(Status
))
439 /* create the DACL */
440 Dacl
= (PACL
)(SecurityDescriptor
+ 1);
441 Status
= RtlCreateAcl(Dacl
,
442 sizeof(ACL
) + SidLen
+ sizeof(ACCESS_ALLOWED_ACE
),
444 if (!NT_SUCCESS(Status
))
449 Status
= RtlAddAccessAllowedAce(Dacl
,
453 if (!NT_SUCCESS(Status
))
458 /* assign the DACL to the security descriptor */
459 Status
= RtlSetDaclSecurityDescriptor(SecurityDescriptor
,
463 if (!NT_SUCCESS(Status
))
468 /* it's time to perform the access check. Just use _some_ desired access right
469 (same as for the ACE) and see if we're getting it granted. This indicates
470 our SID is a member of the token. We however can't use a generic access
471 right as those aren't mapped and return an error (STATUS_GENERIC_NOT_MAPPED). */
472 Status
= NtAccessCheck(SecurityDescriptor
,
476 &PrivBuffer
.PrivilegeSet
,
481 if (NT_SUCCESS(Status
) && NT_SUCCESS(AccessStatus
) && (GrantedAccess
== 0x1))
487 if (hToken
!= NULL
&& hToken
!= ExistingTokenHandle
)
492 if (SecurityDescriptor
!= NULL
)
494 RtlFreeHeap(RtlGetProcessHeap(),
499 if (!NT_SUCCESS(Status
))
501 SetLastError(RtlNtStatusToDosError(Status
));
513 IsTokenRestricted(HANDLE TokenHandle
)
516 PTOKEN_GROUPS lpGroups
;
520 /* determine the required buffer size and allocate enough memory to read the
521 list of restricted SIDs */
523 Status
= NtQueryInformationToken(TokenHandle
,
528 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
530 SetLastError(RtlNtStatusToDosError(Status
));
534 AllocAndReadRestrictedSids
:
535 lpGroups
= (PTOKEN_GROUPS
)HeapAlloc(GetProcessHeap(),
538 if (lpGroups
== NULL
)
540 SetLastError(ERROR_OUTOFMEMORY
);
544 /* actually read the list of the restricted SIDs */
546 Status
= NtQueryInformationToken(TokenHandle
,
551 if (NT_SUCCESS(Status
))
553 Ret
= (lpGroups
->GroupCount
!= 0);
555 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
557 /* looks like the token was modified in the meanwhile, let's just try again */
559 HeapFree(GetProcessHeap(),
563 goto AllocAndReadRestrictedSids
;
567 SetLastError(RtlNtStatusToDosError(Status
));
570 /* free allocated memory */
572 HeapFree(GetProcessHeap(),
580 CreateRestrictedToken(
583 DWORD DisableSidCount
,
584 PSID_AND_ATTRIBUTES pSidAndAttributes
,
585 DWORD DeletePrivilegeCount
,
586 PLUID_AND_ATTRIBUTES pLUIDAndAttributes
,
587 DWORD RestrictedSidCount
,
588 PSID_AND_ATTRIBUTES pSIDAndAttributes
,
589 PHANDLE NewTokenHandle
592 FIXME("unimplemented!\n", __FUNCTION__
);