ReactOS  0.4.15-dev-2985-g54406bf
token.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE: Security token implementation support
5  * COPYRIGHT: Copyright David Welch <welch@cwcom.net>
6  * Copyright 2021 George BiČ™oc <george.bisoc@reactos.org>
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 #include <ntlsa.h>
16 
17 /* GLOBALS ********************************************************************/
18 
20 
21 TOKEN_SOURCE SeSystemTokenSource = {"*SYSTEM*", {0}};
24 
26  TOKEN_READ,
30 };
31 
33 
34  /* Class 0 not used, blame MS! */
35  IQS_NONE,
36 
37  /* TokenUser */
39  /* TokenGroups */
41  /* TokenPrivileges */
43  /* TokenOwner */
45  /* TokenPrimaryGroup */
47  /* TokenDefaultDacl */
49  /* TokenSource */
51  /* TokenType */
53  /* TokenImpersonationLevel */
55  /* TokenStatistics */
57  /* TokenRestrictedSids */
59  /* TokenSessionId */
61  /* TokenGroupsAndPrivileges */
63  /* TokenSessionReference */
65  /* TokenSandBoxInert */
67  /* TokenAuditPolicy */
69  /* TokenOrigin */
71 };
72 
73 /* FUNCTIONS *****************************************************************/
74 
87 static
91 {
92  PAGED_CODE();
93 
95  sizeof(ERESOURCE),
97  if (Token->TokenLock == NULL)
98  {
99  DPRINT1("SepCreateTokenLock(): Failed to allocate memory!\n");
101  }
102 
103  ExInitializeResourceLite(Token->TokenLock);
104  return STATUS_SUCCESS;
105 }
106 
117 static
118 VOID
121 {
122  PAGED_CODE();
123 
124  ExDeleteResourceLite(Token->TokenLock);
126 }
127 
150 static
151 BOOLEAN
153  _In_ PSID_AND_ATTRIBUTES SidArrayToken1,
154  _In_ ULONG CountSidArray1,
155  _In_ PSID_AND_ATTRIBUTES SidArrayToken2,
156  _In_ ULONG CountSidArray2)
157 {
158  ULONG FirstCount, SecondCount;
159  PSID_AND_ATTRIBUTES FirstSidArray, SecondSidArray;
160  PAGED_CODE();
161 
162  /* Bail out if index counters provided are not equal */
163  if (CountSidArray1 != CountSidArray2)
164  {
165  DPRINT("SepCompareSidAndAttributesFromTokens(): Index counters are not the same!\n");
166  return FALSE;
167  }
168 
169  /* Loop over the SID arrays and compare them */
170  for (FirstCount = 0; FirstCount < CountSidArray1; FirstCount++)
171  {
172  for (SecondCount = 0; SecondCount < CountSidArray2; SecondCount++)
173  {
174  FirstSidArray = &SidArrayToken1[FirstCount];
175  SecondSidArray = &SidArrayToken2[SecondCount];
176 
177  if (RtlEqualSid(FirstSidArray->Sid, SecondSidArray->Sid) &&
178  FirstSidArray->Attributes == SecondSidArray->Attributes)
179  {
180  break;
181  }
182  }
183 
184  /* We've exhausted the array of the second token without finding this one */
185  if (SecondCount == CountSidArray2)
186  {
187  DPRINT("SepCompareSidAndAttributesFromTokens(): No matching elements could be found in either token!\n");
188  return FALSE;
189  }
190  }
191 
192  return TRUE;
193 }
194 
217 static
218 BOOLEAN
220  _In_ PLUID_AND_ATTRIBUTES PrivArrayToken1,
221  _In_ ULONG CountPrivArray1,
222  _In_ PLUID_AND_ATTRIBUTES PrivArrayToken2,
223  _In_ ULONG CountPrivArray2)
224 {
225  ULONG FirstCount, SecondCount;
226  PLUID_AND_ATTRIBUTES FirstPrivArray, SecondPrivArray;
227  PAGED_CODE();
228 
229  /* Bail out if index counters provided are not equal */
230  if (CountPrivArray1 != CountPrivArray2)
231  {
232  DPRINT("SepComparePrivilegeAndAttributesFromTokens(): Index counters are not the same!\n");
233  return FALSE;
234  }
235 
236  /* Loop over the privilege arrays and compare them */
237  for (FirstCount = 0; FirstCount < CountPrivArray1; FirstCount++)
238  {
239  for (SecondCount = 0; SecondCount < CountPrivArray2; SecondCount++)
240  {
241  FirstPrivArray = &PrivArrayToken1[FirstCount];
242  SecondPrivArray = &PrivArrayToken2[SecondCount];
243 
244  if (RtlEqualLuid(&FirstPrivArray->Luid, &SecondPrivArray->Luid) &&
245  FirstPrivArray->Attributes == SecondPrivArray->Attributes)
246  {
247  break;
248  }
249  }
250 
251  /* We've exhausted the array of the second token without finding this one */
252  if (SecondCount == CountPrivArray2)
253  {
254  DPRINT("SepComparePrivilegeAndAttributesFromTokens(): No matching elements could be found in either token!\n");
255  return FALSE;
256  }
257  }
258 
259  return TRUE;
260 }
261 
286 static
287 NTSTATUS
289  _In_ PTOKEN FirstToken,
290  _In_ PTOKEN SecondToken,
291  _Out_ PBOOLEAN Equal)
292 {
294  PAGED_CODE();
295 
296  ASSERT(FirstToken != SecondToken);
297 
298  /* Lock the tokens */
299  SepAcquireTokenLockShared(FirstToken);
300  SepAcquireTokenLockShared(SecondToken);
301 
302  /* Check if every SID that is present in either token is also present in the other one */
303  if (!SepCompareSidAndAttributesFromTokens(FirstToken->UserAndGroups,
304  FirstToken->UserAndGroupCount,
305  SecondToken->UserAndGroups,
306  SecondToken->UserAndGroupCount))
307  {
308  goto Quit;
309  }
310 
311  /* Is one token restricted but the other isn't? */
312  Restricted = SeTokenIsRestricted(FirstToken);
313  if (Restricted != SeTokenIsRestricted(SecondToken))
314  {
315  /* If that's the case then bail out */
316  goto Quit;
317  }
318 
319  /*
320  * If both tokens are restricted check if every SID
321  * that is restricted in either token is also restricted
322  * in the other one.
323  */
324  if (Restricted)
325  {
326  if (!SepCompareSidAndAttributesFromTokens(FirstToken->RestrictedSids,
327  FirstToken->RestrictedSidCount,
328  SecondToken->RestrictedSids,
329  SecondToken->RestrictedSidCount))
330  {
331  goto Quit;
332  }
333  }
334 
335  /* Check if every privilege present in either token is also present in the other one */
336  if (!SepComparePrivilegeAndAttributesFromTokens(FirstToken->Privileges,
337  FirstToken->PrivilegeCount,
338  SecondToken->Privileges,
339  SecondToken->PrivilegeCount))
340  {
341  goto Quit;
342  }
343 
344  /* If we're here then the tokens are equal */
345  IsEqual = TRUE;
346  DPRINT("SepCompareTokens(): Tokens are equal!\n");
347 
348 Quit:
349  /* Unlock the tokens */
350  SepReleaseTokenLock(SecondToken);
351  SepReleaseTokenLock(FirstToken);
352 
353  *Equal = IsEqual;
354  return STATUS_SUCCESS;
355 }
356 
377 static
378 NTSTATUS
382 {
384  PTOKEN TokenToImpersonate, ProcessToken;
385  ULONG IncludeEveryoneValueData;
386  PAGED_CODE();
387 
388  /*
389  * We must check first which kind of token
390  * shall we assign for the thread to impersonate,
391  * the one with Everyone Group SID or the other
392  * without. Invoke the registry helper to
393  * return the data value for us.
394  */
395  Status = SepRegQueryHelper(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Lsa",
396  L"EveryoneIncludesAnonymous",
397  REG_DWORD,
398  sizeof(IncludeEveryoneValueData),
399  &IncludeEveryoneValueData);
400  if (!NT_SUCCESS(Status))
401  {
402  DPRINT1("SepRegQueryHelper(): Failed to query the registry value (Status 0x%lx)\n", Status);
403  return Status;
404  }
405 
406  if (IncludeEveryoneValueData == 0)
407  {
408  DPRINT("SepImpersonateAnonymousToken(): Assigning the token not including the Everyone Group SID...\n");
409  TokenToImpersonate = SeAnonymousLogonTokenNoEveryone;
410  }
411  else
412  {
413  DPRINT("SepImpersonateAnonymousToken(): Assigning the token including the Everyone Group SID...\n");
414  TokenToImpersonate = SeAnonymousLogonToken;
415  }
416 
417  /*
418  * Tell the object manager that we're going to use this token
419  * object now by incrementing the reference count.
420  */
421  Status = ObReferenceObjectByPointer(TokenToImpersonate,
424  PreviousMode);
425  if (!NT_SUCCESS(Status))
426  {
427  DPRINT1("SepImpersonateAnonymousToken(): Couldn't be able to use the token, bail out...\n");
428  return Status;
429  }
430 
431  /*
432  * Reference the primary token of the current process that the anonymous
433  * logon token impersonation procedure is being performed. We'll be going
434  * to use the process' token to figure out if the process is actually
435  * restricted or not.
436  */
438  if (!ProcessToken)
439  {
440  DPRINT1("SepImpersonateAnonymousToken(): Couldn't be able to get the process' primary token, bail out...\n");
441  ObDereferenceObject(TokenToImpersonate);
442  return STATUS_UNSUCCESSFUL;
443  }
444 
445  /* Now, is the token from the current process restricted? */
446  if (SeTokenIsRestricted(ProcessToken))
447  {
448  DPRINT1("SepImpersonateAnonymousToken(): The process is restricted, can't do anything. Bail out...\n");
449  PsDereferencePrimaryToken(ProcessToken);
450  ObDereferenceObject(TokenToImpersonate);
451  return STATUS_ACCESS_DENIED;
452  }
453 
454  /*
455  * Finally it's time to impersonate! But first, fast dereference the
456  * process' primary token as we no longer need it.
457  */
460  if (!NT_SUCCESS(Status))
461  {
462  DPRINT1("SepImpersonateAnonymousToken(): Failed to impersonate, bail out...\n");
463  ObDereferenceObject(TokenToImpersonate);
464  return Status;
465  }
466 
467  return Status;
468 }
469 
470 static
471 VOID
474  _In_ ULONG Index)
475 {
476  ULONG TokenFlag;
477  ASSERT(Index < Token->PrivilegeCount);
478 
479  /* The high part of all values we are interested in is 0 */
480  if (Token->Privileges[Index].Luid.HighPart != 0)
481  {
482  return;
483  }
484 
485  /* Check for certain privileges to update flags */
486  if (Token->Privileges[Index].Luid.LowPart == SE_CHANGE_NOTIFY_PRIVILEGE)
487  {
488  TokenFlag = TOKEN_HAS_TRAVERSE_PRIVILEGE;
489  }
490  else if (Token->Privileges[Index].Luid.LowPart == SE_BACKUP_PRIVILEGE)
491  {
492  TokenFlag = TOKEN_HAS_BACKUP_PRIVILEGE;
493  }
494  else if (Token->Privileges[Index].Luid.LowPart == SE_RESTORE_PRIVILEGE)
495  {
496  TokenFlag = TOKEN_HAS_RESTORE_PRIVILEGE;
497  }
498  else if (Token->Privileges[Index].Luid.LowPart == SE_IMPERSONATE_PRIVILEGE)
499  {
501  }
502  else
503  {
504  /* Nothing to do */
505  return;
506  }
507 
508  /* Check if the specified privilege is enabled */
509  if (Token->Privileges[Index].Attributes & SE_PRIVILEGE_ENABLED)
510  {
511  /* It is enabled, so set the flag */
512  Token->TokenFlags |= TokenFlag;
513  }
514  else
515  {
516  /* Is is disabled, so remove the flag */
517  Token->TokenFlags &= ~TokenFlag;
518  }
519 }
520 
521 static
522 VOID
525 {
526  ULONG i;
527 
528  /* Loop all privileges */
529  for (i = 0; i < Token->PrivilegeCount; i++)
530  {
531  /* Updates the flags dor this privilege */
533  }
534 }
535 
536 static
537 VOID
540  _In_ ULONG Index)
541 {
542  ULONG MoveCount;
543  ASSERT(Index < Token->PrivilegeCount);
544 
545  /* Calculate the number of trailing privileges */
546  MoveCount = Token->PrivilegeCount - Index - 1;
547  if (MoveCount != 0)
548  {
549  /* Move them one location ahead */
550  RtlMoveMemory(&Token->Privileges[Index],
551  &Token->Privileges[Index + 1],
552  MoveCount * sizeof(LUID_AND_ATTRIBUTES));
553  }
554 
555  /* Update privilege count */
556  Token->PrivilegeCount--;
557 }
558 
559 VOID
560 NTAPI
562 {
564 }
565 
566 NTSTATUS
567 NTAPI
569  PVOID Src)
570 {
572  return STATUS_NOT_IMPLEMENTED;
573 }
574 
575 NTSTATUS
576 NTAPI
579  _In_ PACCESS_TOKEN NewAccessToken,
580  _Out_ PACCESS_TOKEN* OldAccessToken)
581 {
582  PTOKEN OldToken;
583  PTOKEN NewToken = (PTOKEN)NewAccessToken;
584 
585  PAGED_CODE();
586 
587  if (NewToken->TokenType != TokenPrimary)
588  return STATUS_BAD_TOKEN_TYPE;
589 
590  if (NewToken->TokenInUse)
591  {
594 
595  /* Maybe we're trying to set the same token */
596  OldToken = PsReferencePrimaryToken(Process);
597  if (OldToken == NewToken)
598  {
599  /* So it's a nop. */
600  *OldAccessToken = OldToken;
601  return STATUS_SUCCESS;
602  }
603 
604  Status = SepCompareTokens(OldToken, NewToken, &IsEqual);
605  if (!NT_SUCCESS(Status))
606  {
607  PsDereferencePrimaryToken(OldToken);
608  *OldAccessToken = NULL;
609  return Status;
610  }
611 
612  if (!IsEqual)
613  {
614  PsDereferencePrimaryToken(OldToken);
615  *OldAccessToken = NULL;
617  }
618  /* Silently return STATUS_SUCCESS but do not set the new token,
619  * as it's already in use elsewhere. */
620  *OldAccessToken = OldToken;
621  return STATUS_SUCCESS;
622  }
623 
624  /* Lock the new token */
626 
627  /* Mark new token in use */
628  NewToken->TokenInUse = TRUE;
629 
630  /* Set the session ID for the new token */
631  NewToken->SessionId = MmGetSessionId(Process);
632 
633  /* Unlock the new token */
634  SepReleaseTokenLock(NewToken);
635 
636  /* Reference the new token */
637  ObReferenceObject(NewToken);
638 
639  /* Replace the old with the new */
640  OldToken = ObFastReplaceObject(&Process->Token, NewToken);
641 
642  /* Lock the old token */
644 
645  /* Mark the old token as free */
646  OldToken->TokenInUse = FALSE;
647 
648  /* Unlock the old token */
649  SepReleaseTokenLock(OldToken);
650 
651  *OldAccessToken = (PACCESS_TOKEN)OldToken;
652  return STATUS_SUCCESS;
653 }
654 
655 VOID
656 NTAPI
658 {
659  PTOKEN OldToken;
660 
661  /* Remove the Token */
662  OldToken = ObFastReplaceObject(&Process->Token, NULL);
663 
664  /* Mark the Old Token as free */
665  OldToken->TokenInUse = FALSE;
666 
667  /* Dereference the Token */
668  ObDereferenceObject(OldToken);
669 }
670 
671 static ULONG
674 {
675  ULONG i;
676  ULONG uLength;
677 
678  PAGED_CODE();
679 
680  uLength = Count * sizeof(SID_AND_ATTRIBUTES);
681  for (i = 0; i < Count; i++)
682  uLength += RtlLengthSid(Src[i].Sid);
683 
684  return uLength;
685 }
686 
687 
688 static NTSTATUS
690  _In_ PTOKEN Token,
692  _In_opt_ PSID DefaultOwner,
693  _Out_opt_ PULONG PrimaryGroupIndex,
694  _Out_opt_ PULONG DefaultOwnerIndex)
695 {
696  ULONG i;
697 
698  /* We should return at least a search result */
699  if (!PrimaryGroupIndex && !DefaultOwnerIndex)
701 
702  if (PrimaryGroupIndex)
703  {
704  /* Initialize with an invalid index */
705  // Token->PrimaryGroup = NULL;
706  *PrimaryGroupIndex = Token->UserAndGroupCount;
707  }
708 
709  if (DefaultOwnerIndex)
710  {
711  if (DefaultOwner)
712  {
713  /* An owner is specified: check whether this is actually the user */
714  if (RtlEqualSid(Token->UserAndGroups[0].Sid, DefaultOwner))
715  {
716  /*
717  * It's the user (first element in array): set it
718  * as the owner and stop the search for it.
719  */
720  *DefaultOwnerIndex = 0;
721  DefaultOwnerIndex = NULL;
722  }
723  else
724  {
725  /* An owner is specified: initialize with an invalid index */
726  *DefaultOwnerIndex = Token->UserAndGroupCount;
727  }
728  }
729  else
730  {
731  /*
732  * No owner specified: set the user (first element in array)
733  * as the owner and stop the search for it.
734  */
735  *DefaultOwnerIndex = 0;
736  DefaultOwnerIndex = NULL;
737  }
738  }
739 
740  /* Validate and set the primary group and default owner indices */
741  for (i = 0; i < Token->UserAndGroupCount; i++)
742  {
743  /* Stop the search if we have found what we searched for */
744  if (!PrimaryGroupIndex && !DefaultOwnerIndex)
745  break;
746 
747  if (DefaultOwnerIndex && DefaultOwner &&
748  RtlEqualSid(Token->UserAndGroups[i].Sid, DefaultOwner) &&
749  (Token->UserAndGroups[i].Attributes & SE_GROUP_OWNER))
750  {
751  /* Owner is found, stop the search for it */
752  *DefaultOwnerIndex = i;
753  DefaultOwnerIndex = NULL;
754  }
755 
756  if (PrimaryGroupIndex &&
757  RtlEqualSid(Token->UserAndGroups[i].Sid, PrimaryGroup))
758  {
759  /* Primary group is found, stop the search for it */
760  // Token->PrimaryGroup = Token->UserAndGroups[i].Sid;
761  *PrimaryGroupIndex = i;
762  PrimaryGroupIndex = NULL;
763  }
764  }
765 
766  if (DefaultOwnerIndex)
767  {
768  if (*DefaultOwnerIndex == Token->UserAndGroupCount)
769  return STATUS_INVALID_OWNER;
770  }
771 
772  if (PrimaryGroupIndex)
773  {
774  if (*PrimaryGroupIndex == Token->UserAndGroupCount)
775  // if (Token->PrimaryGroup == NULL)
777  }
778 
779  return STATUS_SUCCESS;
780 }
781 
782 
783 NTSTATUS
784 NTAPI
786  _In_ PTOKEN Token,
792  _Out_ PTOKEN* NewAccessToken)
793 {
795  PTOKEN AccessToken;
796  PVOID EndMem;
797  ULONG VariableLength;
798  ULONG TotalSize;
799 
800  PAGED_CODE();
801 
802  /* Compute how much size we need to allocate for the token */
803  VariableLength = Token->VariableLength;
804  TotalSize = FIELD_OFFSET(TOKEN, VariablePart) + VariableLength;
805 
809  PreviousMode,
810  NULL,
811  TotalSize,
812  0,
813  0,
814  (PVOID*)&AccessToken);
815  if (!NT_SUCCESS(Status))
816  {
817  DPRINT1("ObCreateObject() failed (Status 0x%lx)\n", Status);
818  return Status;
819  }
820 
821  /* Zero out the buffer and initialize the token */
822  RtlZeroMemory(AccessToken, TotalSize);
823 
824  ExAllocateLocallyUniqueId(&AccessToken->TokenId);
825 
826  AccessToken->TokenType = TokenType;
827  AccessToken->ImpersonationLevel = Level;
828 
829  /* Initialise the lock for the access token */
830  Status = SepCreateTokenLock(AccessToken);
831  if (!NT_SUCCESS(Status))
832  {
833  ObDereferenceObject(AccessToken);
834  return Status;
835  }
836 
837  /* Copy the immutable fields */
838  RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
839  &Token->TokenSource.SourceIdentifier);
840  RtlCopyMemory(AccessToken->TokenSource.SourceName,
841  Token->TokenSource.SourceName,
842  sizeof(Token->TokenSource.SourceName));
843 
844  AccessToken->AuthenticationId = Token->AuthenticationId;
845  AccessToken->ParentTokenId = Token->ParentTokenId;
846  AccessToken->ExpirationTime = Token->ExpirationTime;
847  AccessToken->OriginatingLogonSession = Token->OriginatingLogonSession;
848 
849  /* Lock the source token and copy the mutable fields */
851 
852  AccessToken->SessionId = Token->SessionId;
853  RtlCopyLuid(&AccessToken->ModifiedId, &Token->ModifiedId);
854 
855  AccessToken->TokenFlags = Token->TokenFlags & ~TOKEN_SESSION_NOT_REFERENCED;
856 
857  /* Reference the logon session */
858  Status = SepRmReferenceLogonSession(&AccessToken->AuthenticationId);
859  if (!NT_SUCCESS(Status))
860  {
861  /* No logon session could be found, bail out */
862  DPRINT1("SepRmReferenceLogonSession() failed (Status 0x%lx)\n", Status);
863  /* Set the flag for proper cleanup by the delete procedure */
864  AccessToken->TokenFlags |= TOKEN_SESSION_NOT_REFERENCED;
865  goto Quit;
866  }
867 
868  /* Assign the data that reside in the TOKEN's variable information area */
869  AccessToken->VariableLength = VariableLength;
870  EndMem = (PVOID)&AccessToken->VariablePart;
871 
872  /* Copy the privileges */
873  AccessToken->PrivilegeCount = 0;
874  AccessToken->Privileges = NULL;
875  if (Token->Privileges && (Token->PrivilegeCount > 0))
876  {
877  ULONG PrivilegesLength = Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
878  PrivilegesLength = ALIGN_UP_BY(PrivilegesLength, sizeof(PVOID));
879 
880  ASSERT(VariableLength >= PrivilegesLength);
881 
882  AccessToken->PrivilegeCount = Token->PrivilegeCount;
883  AccessToken->Privileges = EndMem;
884  EndMem = (PVOID)((ULONG_PTR)EndMem + PrivilegesLength);
885  VariableLength -= PrivilegesLength;
886 
887  RtlCopyMemory(AccessToken->Privileges,
888  Token->Privileges,
889  AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
890  }
891 
892  /* Copy the user and groups */
893  AccessToken->UserAndGroupCount = 0;
894  AccessToken->UserAndGroups = NULL;
895  if (Token->UserAndGroups && (Token->UserAndGroupCount > 0))
896  {
897  AccessToken->UserAndGroupCount = Token->UserAndGroupCount;
898  AccessToken->UserAndGroups = EndMem;
899  EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
900  VariableLength -= ((ULONG_PTR)EndMem - (ULONG_PTR)AccessToken->UserAndGroups);
901 
902  Status = RtlCopySidAndAttributesArray(AccessToken->UserAndGroupCount,
903  Token->UserAndGroups,
904  VariableLength,
905  AccessToken->UserAndGroups,
906  EndMem,
907  &EndMem,
908  &VariableLength);
909  if (!NT_SUCCESS(Status))
910  {
911  DPRINT1("RtlCopySidAndAttributesArray(UserAndGroups) failed (Status 0x%lx)\n", Status);
912  goto Quit;
913  }
914  }
915 
916 #if 1
917  {
918  ULONG PrimaryGroupIndex;
919 
920  /* Find the token primary group */
922  Token->PrimaryGroup,
923  NULL,
924  &PrimaryGroupIndex,
925  NULL);
926  if (!NT_SUCCESS(Status))
927  {
928  DPRINT1("SepFindPrimaryGroupAndDefaultOwner failed (Status 0x%lx)\n", Status);
929  goto Quit;
930  }
931  AccessToken->PrimaryGroup = AccessToken->UserAndGroups[PrimaryGroupIndex].Sid;
932  }
933 #else
934  AccessToken->PrimaryGroup = (PVOID)((ULONG_PTR)AccessToken + (ULONG_PTR)Token->PrimaryGroup - (ULONG_PTR)Token->UserAndGroups);
935 #endif
936  AccessToken->DefaultOwnerIndex = Token->DefaultOwnerIndex;
937 
938  /* Copy the restricted SIDs */
939  AccessToken->RestrictedSidCount = 0;
940  AccessToken->RestrictedSids = NULL;
941  if (Token->RestrictedSids && (Token->RestrictedSidCount > 0))
942  {
943  AccessToken->RestrictedSidCount = Token->RestrictedSidCount;
944  AccessToken->RestrictedSids = EndMem;
945  EndMem = &AccessToken->RestrictedSids[AccessToken->RestrictedSidCount];
946  VariableLength -= ((ULONG_PTR)EndMem - (ULONG_PTR)AccessToken->RestrictedSids);
947 
948  Status = RtlCopySidAndAttributesArray(AccessToken->RestrictedSidCount,
949  Token->RestrictedSids,
950  VariableLength,
951  AccessToken->RestrictedSids,
952  EndMem,
953  &EndMem,
954  &VariableLength);
955  if (!NT_SUCCESS(Status))
956  {
957  DPRINT1("RtlCopySidAndAttributesArray(RestrictedSids) failed (Status 0x%lx)\n", Status);
958  goto Quit;
959  }
960  }
961 
962 
963  //
964  // FIXME: Implement the "EffectiveOnly" option, that removes all
965  // the disabled parts (privileges and groups) of the token.
966  //
967 
968 
969  //
970  // NOTE: So far our dynamic area only contains
971  // the default dacl, so this makes the following
972  // code pretty simple. The day where it stores
973  // other data, the code will require adaptations.
974  //
975 
976  /* Now allocate the TOKEN's dynamic information area and set the data */
977  AccessToken->DynamicAvailable = 0; // Unused memory in the dynamic area.
978  AccessToken->DynamicPart = NULL;
979  if (Token->DynamicPart && Token->DefaultDacl)
980  {
981  AccessToken->DynamicPart = ExAllocatePoolWithTag(PagedPool,
982  Token->DefaultDacl->AclSize,
984  if (AccessToken->DynamicPart == NULL)
985  {
987  goto Quit;
988  }
989  EndMem = (PVOID)AccessToken->DynamicPart;
990 
991  AccessToken->DefaultDacl = EndMem;
992 
993  RtlCopyMemory(AccessToken->DefaultDacl,
994  Token->DefaultDacl,
995  Token->DefaultDacl->AclSize);
996  }
997 
998  /* Unlock the source token */
1000 
1001  /* Return the token */
1002  *NewAccessToken = AccessToken;
1004 
1005 Quit:
1006  if (!NT_SUCCESS(Status))
1007  {
1008  /* Unlock the source token */
1010 
1011  /* Dereference the token, the delete procedure will clean it up */
1012  ObDereferenceObject(AccessToken);
1013  }
1014 
1015  return Status;
1016 }
1017 
1018 NTSTATUS
1019 NTAPI
1021  OUT PTOKEN *Token,
1022  IN BOOLEAN InUse,
1023  IN ULONG SessionId)
1024 {
1025  PTOKEN NewToken;
1027  NTSTATUS Status;
1028 
1029  /* Initialize the attributes and duplicate it */
1031  Status = SepDuplicateToken(ParentToken,
1033  FALSE,
1034  TokenPrimary,
1035  ParentToken->ImpersonationLevel,
1036  KernelMode,
1037  &NewToken);
1038  if (NT_SUCCESS(Status))
1039  {
1040  /* Insert it */
1041  Status = ObInsertObject(NewToken,
1042  NULL,
1043  0,
1044  0,
1045  NULL,
1046  NULL);
1047  if (NT_SUCCESS(Status))
1048  {
1049  /* Set the session ID */
1050  NewToken->SessionId = SessionId;
1051  NewToken->TokenInUse = InUse;
1052 
1053  /* Return the token */
1054  *Token = NewToken;
1055  }
1056  }
1057 
1058  /* Return status */
1059  return Status;
1060 }
1061 
1062 NTSTATUS
1063 NTAPI
1066 {
1067  PTOKEN ProcessToken;
1068  LUID ProcessTokenId, CallerParentId;
1069 
1070  /* Assume failure */
1071  *IsChild = FALSE;
1072 
1073  /* Reference the process token */
1074  ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess());
1075  if (!ProcessToken)
1076  return STATUS_UNSUCCESSFUL;
1077 
1078  /* Get its token ID */
1079  ProcessTokenId = ProcessToken->TokenId;
1080 
1081  /* Dereference the token */
1083 
1084  /* Get our parent token ID */
1085  CallerParentId = Token->ParentTokenId;
1086 
1087  /* Compare the token IDs */
1088  if (RtlEqualLuid(&CallerParentId, &ProcessTokenId))
1089  *IsChild = TRUE;
1090 
1091  /* Return success */
1092  return STATUS_SUCCESS;
1093 }
1094 
1095 NTSTATUS
1096 NTAPI
1098  OUT PBOOLEAN IsSibling)
1099 {
1100  PTOKEN ProcessToken;
1101  LUID ProcessParentId, ProcessAuthId;
1102  LUID CallerParentId, CallerAuthId;
1103 
1104  /* Assume failure */
1105  *IsSibling = FALSE;
1106 
1107  /* Reference the process token */
1108  ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess());
1109  if (!ProcessToken)
1110  return STATUS_UNSUCCESSFUL;
1111 
1112  /* Get its parent and authentication IDs */
1113  ProcessParentId = ProcessToken->ParentTokenId;
1114  ProcessAuthId = ProcessToken->AuthenticationId;
1115 
1116  /* Dereference the token */
1118 
1119  /* Get our parent and authentication IDs */
1120  CallerParentId = Token->ParentTokenId;
1121  CallerAuthId = Token->AuthenticationId;
1122 
1123  /* Compare the token IDs */
1124  if (RtlEqualLuid(&CallerParentId, &ProcessParentId) &&
1125  RtlEqualLuid(&CallerAuthId, &ProcessAuthId))
1126  {
1127  *IsSibling = TRUE;
1128  }
1129 
1130  /* Return success */
1131  return STATUS_SUCCESS;
1132 }
1133 
1134 NTSTATUS
1135 NTAPI
1139  OUT PACCESS_TOKEN* NewToken)
1140 {
1141  NTSTATUS Status;
1143 
1144  PAGED_CODE();
1145 
1147  NULL,
1148  0,
1149  NULL,
1150  NULL);
1151 
1154  FALSE,
1156  Level,
1157  PreviousMode,
1158  (PTOKEN*)NewToken);
1159 
1160  return Status;
1161 }
1162 
1163 VOID
1164 NTAPI
1166 {
1167  PTOKEN AccessToken = (PTOKEN)ObjectBody;
1168 
1169  DPRINT("SepDeleteToken()\n");
1170 
1171  /* Dereference the logon session */
1172  if ((AccessToken->TokenFlags & TOKEN_SESSION_NOT_REFERENCED) == 0)
1174 
1175  /* Delete the token lock */
1176  if (AccessToken->TokenLock)
1177  SepDeleteTokenLock(AccessToken);
1178 
1179  /* Delete the dynamic information area */
1180  if (AccessToken->DynamicPart)
1182 }
1183 
1184 
1185 CODE_SEG("INIT")
1186 VOID
1187 NTAPI
1189 {
1191  OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
1192 
1193  DPRINT("Creating Token Object Type\n");
1194 
1195  /* Initialize the Token type */
1196  RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
1197  RtlInitUnicodeString(&Name, L"Token");
1198  ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
1199  ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
1200  ObjectTypeInitializer.SecurityRequired = TRUE;
1201  ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(TOKEN);
1202  ObjectTypeInitializer.GenericMapping = SepTokenMapping;
1203  ObjectTypeInitializer.PoolType = PagedPool;
1204  ObjectTypeInitializer.ValidAccessMask = TOKEN_ALL_ACCESS;
1205  ObjectTypeInitializer.UseDefaultObject = TRUE;
1206  ObjectTypeInitializer.DeleteProcedure = SepDeleteToken;
1207  ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &SeTokenObjectType);
1208 }
1209 
1210 VOID
1211 NTAPI
1213  IN PTOKEN Token)
1214 {
1215  PAGED_CODE();
1216 
1217  /* Sanity checks */
1218  ASSERT(Token->TokenType == TokenPrimary);
1219  ASSERT(!Token->TokenInUse);
1220 
1221  /* Clean any previous token */
1222  if (Process->Token.Object) SeDeassignPrimaryToken(Process);
1223 
1224  /* Set the new token */
1226  Token->TokenInUse = TRUE;
1228 }
1229 
1230 NTSTATUS
1231 NTAPI
1239  _In_ PLUID AuthenticationId,
1240  _In_ PLARGE_INTEGER ExpirationTime,
1242  _In_ ULONG GroupCount,
1244  _In_ ULONG GroupsLength,
1245  _In_ ULONG PrivilegeCount,
1249  _In_opt_ PACL DefaultDacl,
1251  _In_ BOOLEAN SystemToken)
1252 {
1253  NTSTATUS Status;
1254  PTOKEN AccessToken;
1255  ULONG TokenFlags = 0;
1256  ULONG PrimaryGroupIndex, DefaultOwnerIndex;
1257  LUID TokenId;
1258  LUID ModifiedId;
1259  PVOID EndMem;
1260  ULONG PrivilegesLength;
1261  ULONG UserGroupsLength;
1262  ULONG VariableLength;
1263  ULONG TotalSize;
1264  ULONG i;
1265 
1266  PAGED_CODE();
1267 
1268  /* Loop all groups */
1269  for (i = 0; i < GroupCount; i++)
1270  {
1271  /* Check for mandatory groups */
1273  {
1274  /* Force them to be enabled */
1276  }
1277 
1278  /* Check of the group is an admin group */
1280  {
1281  /* Remember this so we can optimize queries later */
1282  TokenFlags |= TOKEN_HAS_ADMIN_GROUP;
1283  }
1284  }
1285 
1286  /* Allocate unique IDs for the token */
1287  ExAllocateLocallyUniqueId(&TokenId);
1288  ExAllocateLocallyUniqueId(&ModifiedId);
1289 
1290  /* Compute how much size we need to allocate for the token */
1291 
1292  /* Privileges size */
1293  PrivilegesLength = PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
1294  PrivilegesLength = ALIGN_UP_BY(PrivilegesLength, sizeof(PVOID));
1295 
1296  /* User and groups size */
1297  UserGroupsLength = (1 + GroupCount) * sizeof(SID_AND_ATTRIBUTES);
1298  UserGroupsLength += RtlLengthSid(User->Sid);
1299  for (i = 0; i < GroupCount; i++)
1300  {
1301  UserGroupsLength += RtlLengthSid(Groups[i].Sid);
1302  }
1303  UserGroupsLength = ALIGN_UP_BY(UserGroupsLength, sizeof(PVOID));
1304 
1305  /* Add the additional groups array length */
1306  UserGroupsLength += ALIGN_UP_BY(GroupsLength, sizeof(PVOID));
1307 
1308  VariableLength = PrivilegesLength + UserGroupsLength;
1309  TotalSize = FIELD_OFFSET(TOKEN, VariablePart) + VariableLength;
1310 
1314  PreviousMode,
1315  NULL,
1316  TotalSize,
1317  0,
1318  0,
1319  (PVOID*)&AccessToken);
1320  if (!NT_SUCCESS(Status))
1321  {
1322  DPRINT1("ObCreateObject() failed (Status 0x%lx)\n", Status);
1323  return Status;
1324  }
1325 
1326  /* Zero out the buffer and initialize the token */
1327  RtlZeroMemory(AccessToken, TotalSize);
1328 
1329  RtlCopyLuid(&AccessToken->TokenId, &TokenId);
1330 
1331  AccessToken->TokenType = TokenType;
1332  AccessToken->ImpersonationLevel = ImpersonationLevel;
1333 
1334  /* Initialise the lock for the access token */
1335  Status = SepCreateTokenLock(AccessToken);
1336  if (!NT_SUCCESS(Status))
1337  goto Quit;
1338 
1339  RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
1340  &TokenSource->SourceIdentifier);
1341  RtlCopyMemory(AccessToken->TokenSource.SourceName,
1342  TokenSource->SourceName,
1343  sizeof(TokenSource->SourceName));
1344 
1345  AccessToken->ExpirationTime = *ExpirationTime;
1346  RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
1347 
1348  AccessToken->TokenFlags = TokenFlags & ~TOKEN_SESSION_NOT_REFERENCED;
1349 
1350  /* Copy and reference the logon session */
1351  RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
1352  Status = SepRmReferenceLogonSession(&AccessToken->AuthenticationId);
1353  if (!NT_SUCCESS(Status))
1354  {
1355  /* No logon session could be found, bail out */
1356  DPRINT1("SepRmReferenceLogonSession() failed (Status 0x%lx)\n", Status);
1357  /* Set the flag for proper cleanup by the delete procedure */
1358  AccessToken->TokenFlags |= TOKEN_SESSION_NOT_REFERENCED;
1359  goto Quit;
1360  }
1361 
1362  /* Assign the data that reside in the TOKEN's variable information area */
1363  AccessToken->VariableLength = VariableLength;
1364  EndMem = (PVOID)&AccessToken->VariablePart;
1365 
1366  /* Copy the privileges */
1367  AccessToken->PrivilegeCount = PrivilegeCount;
1368  AccessToken->Privileges = NULL;
1369  if (PrivilegeCount > 0)
1370  {
1371  AccessToken->Privileges = EndMem;
1372  EndMem = (PVOID)((ULONG_PTR)EndMem + PrivilegesLength);
1373  VariableLength -= PrivilegesLength;
1374 
1375  if (PreviousMode != KernelMode)
1376  {
1377  _SEH2_TRY
1378  {
1379  RtlCopyMemory(AccessToken->Privileges,
1380  Privileges,
1381  PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
1382  }
1384  {
1386  }
1387  _SEH2_END;
1388  }
1389  else
1390  {
1391  RtlCopyMemory(AccessToken->Privileges,
1392  Privileges,
1393  PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
1394  }
1395 
1396  if (!NT_SUCCESS(Status))
1397  goto Quit;
1398  }
1399 
1400  /* Update the privilege flags */
1401  SepUpdatePrivilegeFlagsToken(AccessToken);
1402 
1403  /* Copy the user and groups */
1404  AccessToken->UserAndGroupCount = 1 + GroupCount;
1405  AccessToken->UserAndGroups = EndMem;
1406  EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
1407  VariableLength -= ((ULONG_PTR)EndMem - (ULONG_PTR)AccessToken->UserAndGroups);
1408 
1410  User,
1411  VariableLength,
1412  &AccessToken->UserAndGroups[0],
1413  EndMem,
1414  &EndMem,
1415  &VariableLength);
1416  if (!NT_SUCCESS(Status))
1417  goto Quit;
1418 
1419  Status = RtlCopySidAndAttributesArray(GroupCount,
1420  Groups,
1421  VariableLength,
1422  &AccessToken->UserAndGroups[1],
1423  EndMem,
1424  &EndMem,
1425  &VariableLength);
1426  if (!NT_SUCCESS(Status))
1427  goto Quit;
1428 
1429  /* Find the token primary group and default owner */
1431  PrimaryGroup,
1432  Owner,
1433  &PrimaryGroupIndex,
1434  &DefaultOwnerIndex);
1435  if (!NT_SUCCESS(Status))
1436  {
1437  DPRINT1("SepFindPrimaryGroupAndDefaultOwner failed (Status 0x%lx)\n", Status);
1438  goto Quit;
1439  }
1440 
1441  AccessToken->PrimaryGroup = AccessToken->UserAndGroups[PrimaryGroupIndex].Sid;
1442  AccessToken->DefaultOwnerIndex = DefaultOwnerIndex;
1443 
1444  /* Now allocate the TOKEN's dynamic information area and set the data */
1445  AccessToken->DynamicAvailable = 0; // Unused memory in the dynamic area.
1446  AccessToken->DynamicPart = NULL;
1447  if (DefaultDacl != NULL)
1448  {
1449  AccessToken->DynamicPart = ExAllocatePoolWithTag(PagedPool,
1450  DefaultDacl->AclSize,
1452  if (AccessToken->DynamicPart == NULL)
1453  {
1455  goto Quit;
1456  }
1457  EndMem = (PVOID)AccessToken->DynamicPart;
1458 
1459  AccessToken->DefaultDacl = EndMem;
1460 
1461  RtlCopyMemory(AccessToken->DefaultDacl,
1462  DefaultDacl,
1463  DefaultDacl->AclSize);
1464  }
1465 
1466  /* Insert the token only if it's not the system token, otherwise return it directly */
1467  if (!SystemToken)
1468  {
1469  Status = ObInsertObject(AccessToken,
1470  NULL,
1471  DesiredAccess,
1472  0,
1473  NULL,
1474  TokenHandle);
1475  if (!NT_SUCCESS(Status))
1476  {
1477  DPRINT1("ObInsertObject() failed (Status 0x%lx)\n", Status);
1478  }
1479  }
1480  else
1481  {
1482  /* Return pointer instead of handle */
1483  *TokenHandle = (HANDLE)AccessToken;
1484  }
1485 
1486 Quit:
1487  if (!NT_SUCCESS(Status))
1488  {
1489  /* Dereference the token, the delete procedure will clean it up */
1490  ObDereferenceObject(AccessToken);
1491  }
1492 
1493  return Status;
1494 }
1495 
1504 CODE_SEG("INIT")
1505 PTOKEN
1506 NTAPI
1508 {
1510  ULONG GroupAttributes, OwnerAttributes;
1512  LARGE_INTEGER Expiration;
1513  SID_AND_ATTRIBUTES UserSid;
1514  ULONG GroupsLength;
1517  PSID Owner;
1518  ULONG i;
1519  PTOKEN Token;
1520  NTSTATUS Status;
1521 
1522  /* Don't ever expire */
1523  Expiration.QuadPart = -1;
1524 
1525  /* All groups mandatory and enabled */
1528 
1529  /* User is Local System */
1530  UserSid.Sid = SeLocalSystemSid;
1531  UserSid.Attributes = 0;
1532 
1533  /* Primary group is Local System */
1535 
1536  /* Owner is Administrators */
1538 
1539  /* Groups are Administrators, World, and Authenticated Users */
1540  Groups[0].Sid = SeAliasAdminsSid;
1541  Groups[0].Attributes = OwnerAttributes;
1542  Groups[1].Sid = SeWorldSid;
1543  Groups[1].Attributes = GroupAttributes;
1545  Groups[2].Attributes = GroupAttributes;
1546  GroupsLength = sizeof(SID_AND_ATTRIBUTES) +
1547  SeLengthSid(Groups[0].Sid) +
1548  SeLengthSid(Groups[1].Sid) +
1549  SeLengthSid(Groups[2].Sid);
1550  ASSERT(GroupsLength <= sizeof(Groups));
1551 
1552  /* Setup the privileges */
1553  i = 0;
1555  Privileges[i++].Luid = SeTcbPrivilege;
1556 
1557  Privileges[i].Attributes = 0;
1559 
1560  Privileges[i].Attributes = 0;
1562 
1565 
1568 
1569  Privileges[i].Attributes = 0;
1571 
1572  Privileges[i].Attributes = 0;
1574 
1577 
1580 
1582  Privileges[i++].Luid = SeDebugPrivilege;
1583 
1585  Privileges[i++].Luid = SeAuditPrivilege;
1586 
1587  Privileges[i].Attributes = 0;
1588  Privileges[i++].Luid = SeSecurityPrivilege;
1589 
1590  Privileges[i].Attributes = 0;
1592 
1595 
1596  Privileges[i].Attributes = 0;
1597  Privileges[i++].Luid = SeBackupPrivilege;
1598 
1599  Privileges[i].Attributes = 0;
1600  Privileges[i++].Luid = SeRestorePrivilege;
1601 
1602  Privileges[i].Attributes = 0;
1603  Privileges[i++].Luid = SeShutdownPrivilege;
1604 
1605  Privileges[i].Attributes = 0;
1607 
1610 
1611  Privileges[i].Attributes = 0;
1613  ASSERT(i == 20);
1614 
1615  /* Setup the object attributes */
1618 
1619  /* Create the token */
1621  KernelMode,
1622  0,
1624  TokenPrimary,
1627  &Expiration,
1628  &UserSid,
1629  3,
1630  Groups,
1631  GroupsLength,
1632  20,
1633  Privileges,
1634  Owner,
1635  PrimaryGroup,
1638  TRUE);
1640 
1641  /* Return the token */
1642  return Token;
1643 }
1644 
1655 CODE_SEG("INIT")
1656 PTOKEN
1658 {
1659  SID_AND_ATTRIBUTES Groups[32], UserSid;
1661  PTOKEN Token;
1662  ULONG GroupsLength;
1663  LARGE_INTEGER Expiration;
1665  NTSTATUS Status;
1666 
1667  /* The token never expires */
1668  Expiration.QuadPart = -1;
1669 
1670  /* The user is the anonymous logon */
1671  UserSid.Sid = SeAnonymousLogonSid;
1672  UserSid.Attributes = 0;
1673 
1674  /* The primary group is also the anonymous logon */
1676 
1677  /* The only group for the token is the World */
1678  Groups[0].Sid = SeWorldSid;
1680  GroupsLength = sizeof(SID_AND_ATTRIBUTES) +
1681  SeLengthSid(Groups[0].Sid);
1682  ASSERT(GroupsLength <= sizeof(Groups));
1683 
1684  /* Initialise the object attributes for the token */
1687 
1688  /* Create token */
1690  KernelMode,
1691  0,
1693  TokenPrimary,
1696  &Expiration,
1697  &UserSid,
1698  1,
1699  Groups,
1700  GroupsLength,
1701  0,
1702  NULL,
1703  NULL,
1704  PrimaryGroup,
1707  TRUE);
1709 
1710  /* Return the anonymous logon token */
1711  return Token;
1712 }
1713 
1723 CODE_SEG("INIT")
1724 PTOKEN
1726 {
1727  SID_AND_ATTRIBUTES UserSid;
1729  PTOKEN Token;
1730  LARGE_INTEGER Expiration;
1732  NTSTATUS Status;
1733 
1734  /* The token never expires */
1735  Expiration.QuadPart = -1;
1736 
1737  /* The user is the anonymous logon */
1738  UserSid.Sid = SeAnonymousLogonSid;
1739  UserSid.Attributes = 0;
1740 
1741  /* The primary group is also the anonymous logon */
1743 
1744  /* Initialise the object attributes for the token */
1747 
1748  /* Create token */
1750  KernelMode,
1751  0,
1753  TokenPrimary,
1756  &Expiration,
1757  &UserSid,
1758  0,
1759  NULL,
1760  0,
1761  0,
1762  NULL,
1763  NULL,
1764  PrimaryGroup,
1767  TRUE);
1769 
1770  /* Return the anonymous (not including everyone) logon token */
1771  return Token;
1772 }
1773 
1774 /* PUBLIC FUNCTIONS ***********************************************************/
1775 
1776 /*
1777  * @unimplemented
1778  */
1779 NTSTATUS
1780 NTAPI
1782  IN ULONG Flags,
1783  IN PTOKEN_GROUPS SidsToDisable OPTIONAL,
1784  IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL,
1785  IN PTOKEN_GROUPS RestrictedSids OPTIONAL,
1786  OUT PACCESS_TOKEN * FilteredToken)
1787 {
1788  UNIMPLEMENTED;
1789  return STATUS_NOT_IMPLEMENTED;
1790 }
1791 
1823 NTSTATUS
1824 NTAPI
1826  _In_ PACCESS_TOKEN AccessToken,
1828  _Outptr_result_buffer_(_Inexpressible_(token-dependent)) PVOID *TokenInformation)
1829 {
1830  NTSTATUS Status;
1831  PTOKEN Token = (PTOKEN)AccessToken;
1833  union
1834  {
1835  PSID PSid;
1836  ULONG Ulong;
1837  } Unused;
1838 
1839  PAGED_CODE();
1840 
1841  /* Lock the token */
1843 
1844  switch (TokenInformationClass)
1845  {
1846  case TokenUser:
1847  {
1848  PTOKEN_USER tu;
1849 
1850  DPRINT("SeQueryInformationToken(TokenUser)\n");
1851  RequiredLength = sizeof(TOKEN_USER) +
1852  RtlLengthSid(Token->UserAndGroups[0].Sid);
1853 
1854  /* Allocate the output buffer */
1856  if (tu == NULL)
1857  {
1859  break;
1860  }
1861 
1863  &Token->UserAndGroups[0],
1864  RequiredLength - sizeof(TOKEN_USER),
1865  &tu->User,
1866  (PSID)(tu + 1),
1867  &Unused.PSid,
1868  &Unused.Ulong);
1869 
1870  /* Return the structure */
1871  *TokenInformation = tu;
1873  break;
1874  }
1875 
1876  case TokenGroups:
1877  {
1878  PTOKEN_GROUPS tg;
1879  ULONG SidLen;
1880  PSID Sid;
1881 
1882  DPRINT("SeQueryInformationToken(TokenGroups)\n");
1883  RequiredLength = sizeof(tg->GroupCount) +
1884  RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]);
1885 
1886  SidLen = RequiredLength - sizeof(tg->GroupCount) -
1887  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES));
1888 
1889  /* Allocate the output buffer */
1891  if (tg == NULL)
1892  {
1894  break;
1895  }
1896 
1897  Sid = (PSID)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
1898  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)));
1899 
1900  tg->GroupCount = Token->UserAndGroupCount - 1;
1901  Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
1902  &Token->UserAndGroups[1],
1903  SidLen,
1904  &tg->Groups[0],
1905  Sid,
1906  &Unused.PSid,
1907  &Unused.Ulong);
1908 
1909  /* Return the structure */
1910  *TokenInformation = tg;
1912  break;
1913  }
1914 
1915  case TokenPrivileges:
1916  {
1918 
1919  DPRINT("SeQueryInformationToken(TokenPrivileges)\n");
1920  RequiredLength = sizeof(tp->PrivilegeCount) +
1921  (Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
1922 
1923  /* Allocate the output buffer */
1925  if (tp == NULL)
1926  {
1928  break;
1929  }
1930 
1931  tp->PrivilegeCount = Token->PrivilegeCount;
1932  RtlCopyLuidAndAttributesArray(Token->PrivilegeCount,
1933  Token->Privileges,
1934  &tp->Privileges[0]);
1935 
1936  /* Return the structure */
1937  *TokenInformation = tp;
1939  break;
1940  }
1941 
1942  case TokenOwner:
1943  {
1944  PTOKEN_OWNER to;
1945  ULONG SidLen;
1946 
1947  DPRINT("SeQueryInformationToken(TokenOwner)\n");
1948  SidLen = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
1949  RequiredLength = sizeof(TOKEN_OWNER) + SidLen;
1950 
1951  /* Allocate the output buffer */
1953  if (to == NULL)
1954  {
1956  break;
1957  }
1958 
1959  to->Owner = (PSID)(to + 1);
1960  Status = RtlCopySid(SidLen,
1961  to->Owner,
1962  Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
1963 
1964  /* Return the structure */
1965  *TokenInformation = to;
1967  break;
1968  }
1969 
1970  case TokenPrimaryGroup:
1971  {
1973  ULONG SidLen;
1974 
1975  DPRINT("SeQueryInformationToken(TokenPrimaryGroup)\n");
1976  SidLen = RtlLengthSid(Token->PrimaryGroup);
1977  RequiredLength = sizeof(TOKEN_PRIMARY_GROUP) + SidLen;
1978 
1979  /* Allocate the output buffer */
1981  if (tpg == NULL)
1982  {
1984  break;
1985  }
1986 
1987  tpg->PrimaryGroup = (PSID)(tpg + 1);
1988  Status = RtlCopySid(SidLen,
1989  tpg->PrimaryGroup,
1990  Token->PrimaryGroup);
1991 
1992  /* Return the structure */
1993  *TokenInformation = tpg;
1995  break;
1996  }
1997 
1998  case TokenDefaultDacl:
1999  {
2000  PTOKEN_DEFAULT_DACL tdd;
2001 
2002  DPRINT("SeQueryInformationToken(TokenDefaultDacl)\n");
2004 
2005  if (Token->DefaultDacl != NULL)
2006  RequiredLength += Token->DefaultDacl->AclSize;
2007 
2008  /* Allocate the output buffer */
2010  if (tdd == NULL)
2011  {
2013  break;
2014  }
2015 
2016  if (Token->DefaultDacl != NULL)
2017  {
2018  tdd->DefaultDacl = (PACL)(tdd + 1);
2020  Token->DefaultDacl,
2021  Token->DefaultDacl->AclSize);
2022  }
2023  else
2024  {
2025  tdd->DefaultDacl = NULL;
2026  }
2027 
2028  /* Return the structure */
2029  *TokenInformation = tdd;
2031  break;
2032  }
2033 
2034  case TokenSource:
2035  {
2036  PTOKEN_SOURCE ts;
2037 
2038  DPRINT("SeQueryInformationToken(TokenSource)\n");
2039  RequiredLength = sizeof(TOKEN_SOURCE);
2040 
2041  /* Allocate the output buffer */
2043  if (ts == NULL)
2044  {
2046  break;
2047  }
2048 
2049  *ts = Token->TokenSource;
2050 
2051  /* Return the structure */
2052  *TokenInformation = ts;
2054  break;
2055  }
2056 
2057  case TokenType:
2058  {
2059  PTOKEN_TYPE tt;
2060 
2061  DPRINT("SeQueryInformationToken(TokenType)\n");
2062  RequiredLength = sizeof(TOKEN_TYPE);
2063 
2064  /* Allocate the output buffer */
2066  if (tt == NULL)
2067  {
2069  break;
2070  }
2071 
2072  *tt = Token->TokenType;
2073 
2074  /* Return the structure */
2075  *TokenInformation = tt;
2077  break;
2078  }
2079 
2081  {
2083 
2084  DPRINT("SeQueryInformationToken(TokenImpersonationLevel)\n");
2086 
2087  /* Fail if the token is not an impersonation token */
2088  if (Token->TokenType != TokenImpersonation)
2089  {
2091  break;
2092  }
2093 
2094  /* Allocate the output buffer */
2096  if (sil == NULL)
2097  {
2099  break;
2100  }
2101 
2102  *sil = Token->ImpersonationLevel;
2103 
2104  /* Return the structure */
2105  *TokenInformation = sil;
2107  break;
2108  }
2109 
2110  case TokenStatistics:
2111  {
2112  PTOKEN_STATISTICS ts;
2113 
2114  DPRINT("SeQueryInformationToken(TokenStatistics)\n");
2115  RequiredLength = sizeof(TOKEN_STATISTICS);
2116 
2117  /* Allocate the output buffer */
2119  if (ts == NULL)
2120  {
2122  break;
2123  }
2124 
2125  ts->TokenId = Token->TokenId;
2126  ts->AuthenticationId = Token->AuthenticationId;
2127  ts->ExpirationTime = Token->ExpirationTime;
2128  ts->TokenType = Token->TokenType;
2129  ts->ImpersonationLevel = Token->ImpersonationLevel;
2130  ts->DynamicCharged = Token->DynamicCharged;
2131  ts->DynamicAvailable = Token->DynamicAvailable;
2132  ts->GroupCount = Token->UserAndGroupCount - 1;
2133  ts->PrivilegeCount = Token->PrivilegeCount;
2134  ts->ModifiedId = Token->ModifiedId;
2135 
2136  /* Return the structure */
2137  *TokenInformation = ts;
2139  break;
2140  }
2141 
2142  case TokenSessionId:
2143  {
2144  DPRINT("SeQueryInformationToken(TokenSessionId)\n");
2145  Status = SeQuerySessionIdToken(Token, (PULONG)TokenInformation);
2146  break;
2147  }
2148 
2149  default:
2150  DPRINT1("SeQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
2152  break;
2153  }
2154 
2155  /* Release the lock of the token */
2157 
2158  return Status;
2159 }
2160 
2161 /*
2162  * @implemented
2163  */
2164 NTSTATUS
2165 NTAPI
2167  IN PULONG pSessionId)
2168 {
2169  PAGED_CODE();
2170 
2171  /* Lock the token */
2173 
2174  *pSessionId = ((PTOKEN)Token)->SessionId;
2175 
2176  /* Unlock the token */
2178 
2179  return STATUS_SUCCESS;
2180 }
2181 
2182 /*
2183  * @implemented
2184  */
2185 NTSTATUS
2186 NTAPI
2188  OUT PLUID LogonId)
2189 {
2190  PAGED_CODE();
2191 
2192  *LogonId = ((PTOKEN)Token)->AuthenticationId;
2193 
2194  return STATUS_SUCCESS;
2195 }
2196 
2197 
2198 /*
2199  * @implemented
2200  */
2202 NTAPI
2204 {
2205  PAGED_CODE();
2206 
2207  return ((PTOKEN)Token)->ImpersonationLevel;
2208 }
2209 
2210 
2211 /*
2212  * @implemented
2213  */
2216 {
2217  PAGED_CODE();
2218 
2219  return ((PTOKEN)Token)->TokenType;
2220 }
2221 
2222 
2223 /*
2224  * @implemented
2225  */
2226 BOOLEAN
2227 NTAPI
2229 {
2230  PAGED_CODE();
2231 
2232  // NOTE: Win7+ instead really checks the list of groups in the token
2233  // (since TOKEN_HAS_ADMIN_GROUP == TOKEN_WRITE_RESTRICTED ...)
2234  return (((PTOKEN)Token)->TokenFlags & TOKEN_HAS_ADMIN_GROUP) != 0;
2235 }
2236 
2237 /*
2238  * @implemented
2239  */
2240 BOOLEAN
2241 NTAPI
2243 {
2244  PAGED_CODE();
2245 
2246  return (((PTOKEN)Token)->TokenFlags & TOKEN_IS_RESTRICTED) != 0;
2247 }
2248 
2249 /*
2250  * @implemented
2251  * @note First introduced in NT 5.1 SP2 x86 (5.1.2600.2622), absent in NT 5.2,
2252  * then finally re-introduced in Vista+.
2253  */
2254 BOOLEAN
2255 NTAPI
2257 {
2258  PAGED_CODE();
2259 
2260  // NOTE: NT 5.1 SP2 x86 checks the SE_BACKUP_PRIVILEGES_CHECKED flag
2261  // while Vista+ checks the TOKEN_WRITE_RESTRICTED flag as one expects.
2262  return (((PTOKEN)Token)->TokenFlags & SE_BACKUP_PRIVILEGES_CHECKED) != 0;
2263 }
2264 
2284 BOOLEAN
2285 NTAPI
2287  _In_ PTOKEN ProcessToken,
2288  _In_ PTOKEN TokenToImpersonate,
2290 {
2291  BOOLEAN CanImpersonate;
2292  PAGED_CODE();
2293 
2294  /*
2295  * SecurityAnonymous and SecurityIdentification levels do not
2296  * allow impersonation. If we get such levels from the call
2297  * then something's seriously wrong.
2298  */
2301 
2302  /* Time to lock our tokens */
2303  SepAcquireTokenLockShared(ProcessToken);
2304  SepAcquireTokenLockShared(TokenToImpersonate);
2305 
2306  /* What kind of authentication ID does the token have? */
2307  if (RtlEqualLuid(&TokenToImpersonate->AuthenticationId,
2309  {
2310  /*
2311  * OK, it looks like the token has an anonymous
2312  * authentication. Is that token created by the system?
2313  */
2314  if (TokenToImpersonate->TokenSource.SourceName != SeSystemTokenSource.SourceName &&
2315  !RtlEqualLuid(&TokenToImpersonate->TokenSource.SourceIdentifier, &SeSystemTokenSource.SourceIdentifier))
2316  {
2317  /* It isn't, we can't impersonate regular tokens */
2318  DPRINT("SeTokenCanImpersonate(): Token has an anonymous authentication ID, can't impersonate!\n");
2319  CanImpersonate = FALSE;
2320  goto Quit;
2321  }
2322  }
2323 
2324  /* Are the SID values from both tokens equal? */
2325  if (!RtlEqualSid(ProcessToken->UserAndGroups->Sid,
2326  TokenToImpersonate->UserAndGroups->Sid))
2327  {
2328  /* They aren't, bail out */
2329  DPRINT("SeTokenCanImpersonate(): Tokens SIDs are not equal!\n");
2330  CanImpersonate = FALSE;
2331  goto Quit;
2332  }
2333 
2334  /*
2335  * Make sure the tokens aren't diverged in terms of
2336  * restrictions, that is, one token is restricted
2337  * but the other one isn't.
2338  */
2339  if (SeTokenIsRestricted(ProcessToken) !=
2340  SeTokenIsRestricted(TokenToImpersonate))
2341  {
2342  /*
2343  * One token is restricted so we cannot
2344  * continue further at this point, bail out.
2345  */
2346  DPRINT("SeTokenCanImpersonate(): One token is restricted, can't continue!\n");
2347  CanImpersonate = FALSE;
2348  goto Quit;
2349  }
2350 
2351  /* If we've reached that far then we can impersonate! */
2352  DPRINT("SeTokenCanImpersonate(): We can impersonate.\n");
2353  CanImpersonate = TRUE;
2354 
2355 Quit:
2356  /* We're done, unlock the tokens now */
2357  SepReleaseTokenLock(ProcessToken);
2358  SepReleaseTokenLock(TokenToImpersonate);
2359 
2360  return CanImpersonate;
2361 }
2362 
2363 /* SYSTEM CALLS ***************************************************************/
2364 
2365 /*
2366  * @implemented
2367  */
2370 NTSTATUS
2371 NTAPI
2376  PVOID TokenInformation,
2379 {
2380  NTSTATUS Status;
2382  PTOKEN Token;
2384  union
2385  {
2386  PSID PSid;
2387  ULONG Ulong;
2388  } Unused;
2389 
2390  PAGED_CODE();
2391 
2393 
2394  /* Check buffers and class validity */
2398  TokenInformation,
2400  ReturnLength,
2401  NULL,
2402  PreviousMode,
2403  TRUE);
2404  if (!NT_SUCCESS(Status))
2405  {
2406  DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status);
2407  return Status;
2408  }
2409 
2413  PreviousMode,
2414  (PVOID*)&Token,
2415  NULL);
2416  if (NT_SUCCESS(Status))
2417  {
2418  /* Lock the token */
2420 
2421  switch (TokenInformationClass)
2422  {
2423  case TokenUser:
2424  {
2425  PTOKEN_USER tu = (PTOKEN_USER)TokenInformation;
2426 
2427  DPRINT("NtQueryInformationToken(TokenUser)\n");
2428  RequiredLength = sizeof(TOKEN_USER) +
2429  RtlLengthSid(Token->UserAndGroups[0].Sid);
2430 
2431  _SEH2_TRY
2432  {
2434  {
2436  &Token->UserAndGroups[0],
2437  RequiredLength - sizeof(TOKEN_USER),
2438  &tu->User,
2439  (PSID)(tu + 1),
2440  &Unused.PSid,
2441  &Unused.Ulong);
2442  }
2443  else
2444  {
2446  }
2447 
2448  if (ReturnLength != NULL)
2449  {
2451  }
2452  }
2454  {
2456  }
2457  _SEH2_END;
2458 
2459  break;
2460  }
2461 
2462  case TokenGroups:
2463  {
2464  PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
2465 
2466  DPRINT("NtQueryInformationToken(TokenGroups)\n");
2467  RequiredLength = sizeof(tg->GroupCount) +
2468  RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]);
2469 
2470  _SEH2_TRY
2471  {
2473  {
2474  ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
2475  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES));
2476  PSID Sid = (PSID_AND_ATTRIBUTES)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
2477  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)));
2478 
2479  tg->GroupCount = Token->UserAndGroupCount - 1;
2480  Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
2481  &Token->UserAndGroups[1],
2482  SidLen,
2483  &tg->Groups[0],
2484  Sid,
2485  &Unused.PSid,
2486  &Unused.Ulong);
2487  }
2488  else
2489  {
2491  }
2492 
2493  if (ReturnLength != NULL)
2494  {
2496  }
2497  }
2499  {
2501  }
2502  _SEH2_END;
2503 
2504  break;
2505  }
2506 
2507  case TokenPrivileges:
2508  {
2509  PTOKEN_PRIVILEGES tp = (PTOKEN_PRIVILEGES)TokenInformation;
2510 
2511  DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
2512  RequiredLength = sizeof(tp->PrivilegeCount) +
2513  (Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
2514 
2515  _SEH2_TRY
2516  {
2518  {
2519  tp->PrivilegeCount = Token->PrivilegeCount;
2520  RtlCopyLuidAndAttributesArray(Token->PrivilegeCount,
2521  Token->Privileges,
2522  &tp->Privileges[0]);
2523  }
2524  else
2525  {
2527  }
2528 
2529  if (ReturnLength != NULL)
2530  {
2532  }
2533  }
2535  {
2537  }
2538  _SEH2_END;
2539 
2540  break;
2541  }
2542 
2543  case TokenOwner:
2544  {
2545  PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
2546  ULONG SidLen;
2547 
2548  DPRINT("NtQueryInformationToken(TokenOwner)\n");
2549  SidLen = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
2550  RequiredLength = sizeof(TOKEN_OWNER) + SidLen;
2551 
2552  _SEH2_TRY
2553  {
2555  {
2556  to->Owner = (PSID)(to + 1);
2557  Status = RtlCopySid(SidLen,
2558  to->Owner,
2559  Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
2560  }
2561  else
2562  {
2564  }
2565 
2566  if (ReturnLength != NULL)
2567  {
2569  }
2570  }
2572  {
2574  }
2575  _SEH2_END;
2576 
2577  break;
2578  }
2579 
2580  case TokenPrimaryGroup:
2581  {
2582  PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
2583  ULONG SidLen;
2584 
2585  DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
2586  SidLen = RtlLengthSid(Token->PrimaryGroup);
2587  RequiredLength = sizeof(TOKEN_PRIMARY_GROUP) + SidLen;
2588 
2589  _SEH2_TRY
2590  {
2592  {
2593  tpg->PrimaryGroup = (PSID)(tpg + 1);
2594  Status = RtlCopySid(SidLen,
2595  tpg->PrimaryGroup,
2596  Token->PrimaryGroup);
2597  }
2598  else
2599  {
2601  }
2602 
2603  if (ReturnLength != NULL)
2604  {
2606  }
2607  }
2609  {
2611  }
2612  _SEH2_END;
2613 
2614  break;
2615  }
2616 
2617  case TokenDefaultDacl:
2618  {
2619  PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
2620 
2621  DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
2623 
2624  if (Token->DefaultDacl != NULL)
2625  RequiredLength += Token->DefaultDacl->AclSize;
2626 
2627  _SEH2_TRY
2628  {
2630  {
2631  if (Token->DefaultDacl != NULL)
2632  {
2633  tdd->DefaultDacl = (PACL)(tdd + 1);
2635  Token->DefaultDacl,
2636  Token->DefaultDacl->AclSize);
2637  }
2638  else
2639  {
2640  tdd->DefaultDacl = NULL;
2641  }
2642  }
2643  else
2644  {
2646  }
2647 
2648  if (ReturnLength != NULL)
2649  {
2651  }
2652  }
2654  {
2656  }
2657  _SEH2_END;
2658 
2659  break;
2660  }
2661 
2662  case TokenSource:
2663  {
2664  PTOKEN_SOURCE ts = (PTOKEN_SOURCE)TokenInformation;
2665 
2666  DPRINT("NtQueryInformationToken(TokenSource)\n");
2667  RequiredLength = sizeof(TOKEN_SOURCE);
2668 
2669  _SEH2_TRY
2670  {
2672  {
2673  *ts = Token->TokenSource;
2674  }
2675  else
2676  {
2678  }
2679 
2680  if (ReturnLength != NULL)
2681  {
2683  }
2684  }
2686  {
2688  }
2689  _SEH2_END;
2690 
2691  break;
2692  }
2693 
2694  case TokenType:
2695  {
2696  PTOKEN_TYPE tt = (PTOKEN_TYPE)TokenInformation;
2697 
2698  DPRINT("NtQueryInformationToken(TokenType)\n");
2699  RequiredLength = sizeof(TOKEN_TYPE);
2700 
2701  _SEH2_TRY
2702  {
2704  {
2705  *tt = Token->TokenType;
2706  }
2707  else
2708  {
2710  }
2711 
2712  if (ReturnLength != NULL)
2713  {
2715  }
2716  }
2718  {
2720  }
2721  _SEH2_END;
2722 
2723  break;
2724  }
2725 
2727  {
2729 
2730  DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
2731 
2732  /* Fail if the token is not an impersonation token */
2733  if (Token->TokenType != TokenImpersonation)
2734  {
2736  break;
2737  }
2738 
2740 
2741  _SEH2_TRY
2742  {
2744  {
2745  *sil = Token->ImpersonationLevel;
2746  }
2747  else
2748  {
2750  }
2751 
2752  if (ReturnLength != NULL)
2753  {
2755  }
2756  }
2758  {
2760  }
2761  _SEH2_END;
2762 
2763  break;
2764  }
2765 
2766  case TokenStatistics:
2767  {
2768  PTOKEN_STATISTICS ts = (PTOKEN_STATISTICS)TokenInformation;
2769 
2770  DPRINT("NtQueryInformationToken(TokenStatistics)\n");
2771  RequiredLength = sizeof(TOKEN_STATISTICS);
2772 
2773  _SEH2_TRY
2774  {
2776  {
2777  ts->TokenId = Token->TokenId;
2778  ts->AuthenticationId = Token->AuthenticationId;
2779  ts->ExpirationTime = Token->ExpirationTime;
2780  ts->TokenType = Token->TokenType;
2781  ts->ImpersonationLevel = Token->ImpersonationLevel;
2782  ts->DynamicCharged = Token->DynamicCharged;
2783  ts->DynamicAvailable = Token->DynamicAvailable;
2784  ts->GroupCount = Token->UserAndGroupCount - 1;
2785  ts->PrivilegeCount = Token->PrivilegeCount;
2786  ts->ModifiedId = Token->ModifiedId;
2787  }
2788  else
2789  {
2791  }
2792 
2793  if (ReturnLength != NULL)
2794  {
2796  }
2797  }
2799  {
2801  }
2802  _SEH2_END;
2803 
2804  break;
2805  }
2806 
2807  case TokenOrigin:
2808  {
2809  PTOKEN_ORIGIN to = (PTOKEN_ORIGIN)TokenInformation;
2810 
2811  DPRINT("NtQueryInformationToken(TokenOrigin)\n");
2812  RequiredLength = sizeof(TOKEN_ORIGIN);
2813 
2814  _SEH2_TRY
2815  {
2817  {
2819  &Token->AuthenticationId);
2820  }
2821  else
2822  {
2824  }
2825 
2826  if (ReturnLength != NULL)
2827  {
2829  }
2830  }
2832  {
2834  }
2835  _SEH2_END;
2836 
2837  break;
2838  }
2839 
2841  DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
2843  break;
2844 
2845  case TokenRestrictedSids:
2846  {
2847  PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
2848 
2849  DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
2850  RequiredLength = sizeof(tg->GroupCount) +
2851  RtlLengthSidAndAttributes(Token->RestrictedSidCount, Token->RestrictedSids);
2852 
2853  _SEH2_TRY
2854  {
2856  {
2857  ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
2858  (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES));
2859  PSID Sid = (PSID)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
2860  (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)));
2861 
2862  tg->GroupCount = Token->RestrictedSidCount;
2863  Status = RtlCopySidAndAttributesArray(Token->RestrictedSidCount,
2864  Token->RestrictedSids,
2865  SidLen,
2866  &tg->Groups[0],
2867  Sid,
2868  &Unused.PSid,
2869  &Unused.Ulong);
2870  }
2871  else
2872  {
2874  }
2875 
2876  if (ReturnLength != NULL)
2877  {
2879  }
2880  }
2882  {
2884  }
2885  _SEH2_END;
2886 
2887  break;
2888  }
2889 
2890  case TokenSandBoxInert:
2891  DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
2893  break;
2894 
2895  case TokenSessionId:
2896  {
2897  ULONG SessionId = 0;
2898 
2899  DPRINT("NtQueryInformationToken(TokenSessionId)\n");
2900 
2902  if (NT_SUCCESS(Status))
2903  {
2904  _SEH2_TRY
2905  {
2906  /* Buffer size was already verified, no need to check here again */
2907  *(PULONG)TokenInformation = SessionId;
2908 
2909  if (ReturnLength != NULL)
2910  {
2911  *ReturnLength = sizeof(ULONG);
2912  }
2913  }
2915  {
2917  }
2918  _SEH2_END;
2919  }
2920 
2921  break;
2922  }
2923 
2924  default:
2925  DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
2927  break;
2928  }
2929 
2930  /* Unlock and dereference the token */
2933  }
2934 
2935  return Status;
2936 }
2937 
2938 
2939 /*
2940  * NtSetTokenInformation: Partly implemented.
2941  * Unimplemented:
2942  * TokenOrigin, TokenDefaultDacl
2943  */
2946 NTSTATUS
2947 NTAPI
2951  _In_reads_bytes_(TokenInformationLength) PVOID TokenInformation,
2953 {
2954  NTSTATUS Status;
2955  PTOKEN Token;
2957  ULONG NeededAccess = TOKEN_ADJUST_DEFAULT;
2958 
2959  PAGED_CODE();
2960 
2962 
2966  TokenInformation,
2968  PreviousMode);
2969  if (!NT_SUCCESS(Status))
2970  {
2971  /* Invalid buffers */
2972  DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status);
2973  return Status;
2974  }
2975 
2977  {
2978  NeededAccess |= TOKEN_ADJUST_SESSIONID;
2979  }
2980 
2982  NeededAccess,
2984  PreviousMode,
2985  (PVOID*)&Token,
2986  NULL);
2987  if (NT_SUCCESS(Status))
2988  {
2989  switch (TokenInformationClass)
2990  {
2991  case TokenOwner:
2992  {
2993  if (TokenInformationLength >= sizeof(TOKEN_OWNER))
2994  {
2995  PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
2996  PSID InputSid = NULL, CapturedSid;
2997  ULONG DefaultOwnerIndex;
2998 
2999  _SEH2_TRY
3000  {
3001  InputSid = to->Owner;
3002  }
3004  {
3006  _SEH2_YIELD(goto Cleanup);
3007  }
3008  _SEH2_END;
3009 
3010  Status = SepCaptureSid(InputSid,
3011  PreviousMode,
3012  PagedPool,
3013  FALSE,
3014  &CapturedSid);
3015  if (NT_SUCCESS(Status))
3016  {
3017  /* Lock the token */
3019 
3020  /* Find the owner amongst the existing token user and groups */
3022  NULL,
3023  CapturedSid,
3024  NULL,
3025  &DefaultOwnerIndex);
3026  if (NT_SUCCESS(Status))
3027  {
3028  /* Found it */
3029  Token->DefaultOwnerIndex = DefaultOwnerIndex;
3030  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3031  }
3032 
3033  /* Unlock the token */
3035 
3036  SepReleaseSid(CapturedSid,
3037  PreviousMode,
3038  FALSE);
3039  }
3040  }
3041  else
3042  {
3044  }
3045  break;
3046  }
3047 
3048  case TokenPrimaryGroup:
3049  {
3051  {
3052  PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
3053  PSID InputSid = NULL, CapturedSid;
3054  ULONG PrimaryGroupIndex;
3055 
3056  _SEH2_TRY
3057  {
3058  InputSid = tpg->PrimaryGroup;
3059  }
3061  {
3063  _SEH2_YIELD(goto Cleanup);
3064  }
3065  _SEH2_END;
3066 
3067  Status = SepCaptureSid(InputSid,
3068  PreviousMode,
3069  PagedPool,
3070  FALSE,
3071  &CapturedSid);
3072  if (NT_SUCCESS(Status))
3073  {
3074  /* Lock the token */
3076 
3077  /* Find the primary group amongst the existing token user and groups */
3079  CapturedSid,
3080  NULL,
3081  &PrimaryGroupIndex,
3082  NULL);
3083  if (NT_SUCCESS(Status))
3084  {
3085  /* Found it */
3086  Token->PrimaryGroup = Token->UserAndGroups[PrimaryGroupIndex].Sid;
3087  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3088  }
3089 
3090  /* Unlock the token */
3092 
3093  SepReleaseSid(CapturedSid,
3094  PreviousMode,
3095  FALSE);
3096  }
3097  }
3098  else
3099  {
3101  }
3102  break;
3103  }
3104 
3105  case TokenDefaultDacl:
3106  {
3108  {
3109  PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
3110  PACL InputAcl = NULL;
3111 
3112  _SEH2_TRY
3113  {
3114  InputAcl = tdd->DefaultDacl;
3115  }
3117  {
3119  _SEH2_YIELD(goto Cleanup);
3120  }
3121  _SEH2_END;
3122 
3123  if (InputAcl != NULL)
3124  {
3125  PACL CapturedAcl;
3126 
3127  /* Capture and copy the dacl */
3128  Status = SepCaptureAcl(InputAcl,
3129  PreviousMode,
3130  PagedPool,
3131  TRUE,
3132  &CapturedAcl);
3133  if (NT_SUCCESS(Status))
3134  {
3135  ULONG DynamicLength;
3136 
3137  /* Lock the token */
3139 
3140  //
3141  // NOTE: So far our dynamic area only contains
3142  // the default dacl, so this makes the following
3143  // code pretty simple. The day where it stores
3144  // other data, the code will require adaptations.
3145  //
3146 
3147  DynamicLength = Token->DynamicAvailable;
3148  // Add here any other data length present in the dynamic area...
3149  if (Token->DefaultDacl)
3150  DynamicLength += Token->DefaultDacl->AclSize;
3151 
3152  /* Reallocate the dynamic area if it is too small */
3154  if ((DynamicLength < CapturedAcl->AclSize) ||
3155  (Token->DynamicPart == NULL))
3156  {
3157  PVOID NewDynamicPart;
3158 
3159  NewDynamicPart = ExAllocatePoolWithTag(PagedPool,
3160  CapturedAcl->AclSize,
3162  if (NewDynamicPart == NULL)
3163  {
3165  }
3166  else
3167  {
3168  if (Token->DynamicPart != NULL)
3169  {
3170  // RtlCopyMemory(NewDynamicPart, Token->DynamicPart, DynamicLength);
3171  ExFreePoolWithTag(Token->DynamicPart, TAG_TOKEN_DYNAMIC);
3172  }
3173  Token->DynamicPart = NewDynamicPart;
3174  Token->DynamicAvailable = 0;
3175  }
3176  }
3177  else
3178  {
3179  Token->DynamicAvailable = DynamicLength - CapturedAcl->AclSize;
3180  }
3181 
3182  if (NT_SUCCESS(Status))
3183  {
3184  /* Set the new dacl */
3185  Token->DefaultDacl = (PVOID)Token->DynamicPart;
3186  RtlCopyMemory(Token->DefaultDacl,
3187  CapturedAcl,
3188  CapturedAcl->AclSize);
3189 
3190  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3191  }
3192 
3193  /* Unlock the token */
3195 
3196  ExFreePoolWithTag(CapturedAcl, TAG_ACL);
3197  }
3198  }
3199  else
3200  {
3201  /* Lock the token */
3203 
3204  /* Clear the default dacl if present */
3205  if (Token->DefaultDacl != NULL)
3206  {
3207  Token->DynamicAvailable += Token->DefaultDacl->AclSize;
3208  RtlZeroMemory(Token->DefaultDacl, Token->DefaultDacl->AclSize);
3209  Token->DefaultDacl = NULL;
3210 
3211  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3212  }
3213 
3214  /* Unlock the token */
3216  }
3217  }
3218  else
3219  {
3221  }
3222  break;
3223  }
3224 
3225  case TokenSessionId:
3226  {
3227  ULONG SessionId = 0;
3228 
3229  _SEH2_TRY
3230  {
3231  /* Buffer size was already verified, no need to check here again */
3232  SessionId = *(PULONG)TokenInformation;
3233  }
3235  {
3237  _SEH2_YIELD(goto Cleanup);
3238  }
3239  _SEH2_END;
3240 
3241  /* Check for TCB privilege */
3243  {
3245  break;
3246  }
3247 
3248  /* Lock the token */
3250 
3251  Token->SessionId = SessionId;
3252  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3253 
3254  /* Unlock the token */
3256 
3257  break;
3258  }
3259 
3260  case TokenSessionReference:
3261  {
3262  ULONG SessionReference;
3263 
3264  _SEH2_TRY
3265  {
3266  /* Buffer size was already verified, no need to check here again */
3267  SessionReference = *(PULONG)TokenInformation;
3268  }
3270  {
3272  _SEH2_YIELD(goto Cleanup);
3273  }
3274  _SEH2_END;
3275 
3276  /* Check for TCB privilege */
3278  {
3280  goto Cleanup;
3281  }
3282 
3283  /* Check if it is 0 */
3284  if (SessionReference == 0)
3285  {
3286  ULONG OldTokenFlags;
3287 
3288  /* Lock the token */
3290 
3291  /* Atomically set the flag in the token */
3292  OldTokenFlags = RtlInterlockedSetBits(&Token->TokenFlags,
3294  /*
3295  * If the flag was already set, do not dereference again
3296  * the logon session. Use SessionReference as an indicator
3297  * to know whether to really dereference the session.
3298  */
3299  if (OldTokenFlags == Token->TokenFlags)
3300  SessionReference = ULONG_MAX;
3301 
3302  /* Unlock the token */
3304  }
3305 
3306  /* Dereference the logon session if needed */
3307  if (SessionReference == 0)
3308  SepRmDereferenceLogonSession(&Token->AuthenticationId);
3309 
3310  break;
3311  }
3312 
3313  case TokenAuditPolicy:
3314  {
3315  PTOKEN_AUDIT_POLICY_INFORMATION PolicyInformation =
3316  (PTOKEN_AUDIT_POLICY_INFORMATION)TokenInformation;
3317  SEP_AUDIT_POLICY AuditPolicy;
3318  ULONG i;
3319 
3320  _SEH2_TRY
3321  {
3322  ProbeForRead(PolicyInformation,
3324  Policies[PolicyInformation->PolicyCount]),
3325  sizeof(ULONG));
3326 
3327  /* Loop all policies in the structure */
3328  for (i = 0; i < PolicyInformation->PolicyCount; i++)
3329  {
3330  /* Set the corresponding bits in the packed structure */
3331  switch (PolicyInformation->Policies[i].Category)
3332  {
3333  case AuditCategorySystem:
3334  AuditPolicy.PolicyElements.System = PolicyInformation->Policies[i].Value;
3335  break;
3336 
3337  case AuditCategoryLogon:
3338  AuditPolicy.PolicyElements.Logon = PolicyInformation->Policies[i].Value;
3339  break;
3340 
3342  AuditPolicy.PolicyElements.ObjectAccess = PolicyInformation->Policies[i].Value;
3343  break;
3344 
3346  AuditPolicy.PolicyElements.PrivilegeUse = PolicyInformation->Policies[i].Value;
3347  break;
3348 
3350  AuditPolicy.PolicyElements.DetailedTracking = PolicyInformation->Policies[i].Value;
3351  break;
3352 
3354  AuditPolicy.PolicyElements.PolicyChange = PolicyInformation->Policies[i].Value;
3355  break;
3356 
3358  AuditPolicy.PolicyElements.AccountManagement = PolicyInformation->Policies[i].Value;
3359  break;
3360 
3362  AuditPolicy.PolicyElements.DirectoryServiceAccess = PolicyInformation->Policies[i].Value;
3363  break;
3364 
3366  AuditPolicy.PolicyElements.AccountLogon = PolicyInformation->Policies[i].Value;
3367  break;
3368  }
3369  }
3370  }
3372  {
3374  _SEH2_YIELD(goto Cleanup);
3375  }
3376  _SEH2_END;
3377 
3378  /* Check for TCB privilege */
3380  {
3382  break;
3383  }
3384 
3385  /* Lock the token */
3387 
3388  /* Set the new audit policy */
3389  Token->AuditPolicy = AuditPolicy;
3390  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3391 
3392  /* Unlock the token */
3394 
3395  break;
3396  }
3397 
3398  case TokenOrigin:
3399  {
3401 
3402  _SEH2_TRY
3403  {
3404  /* Copy the token origin */
3405  TokenOrigin = *(PTOKEN_ORIGIN)TokenInformation;
3406  }
3408  {
3410  _SEH2_YIELD(goto Cleanup);
3411  }
3412  _SEH2_END;
3413 
3414  /* Check for TCB privilege */
3416  {
3418  break;
3419  }
3420 
3421  /* Lock the token */
3423 
3424  /* Check if there is no token origin set yet */
3425  if (RtlIsZeroLuid(&Token->OriginatingLogonSession))
3426  {
3427  /* Set the token origin */
3428  Token->OriginatingLogonSession =
3429  TokenOrigin.OriginatingLogonSession;
3430 
3431  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3432  }
3433 
3434  /* Unlock the token */
3436 
3437  break;
3438  }
3439 
3440  default:
3441  {
3442  DPRINT1("Invalid TokenInformationClass: 0x%lx\n",
3445  break;
3446  }
3447  }
3448 Cleanup:
3450  }
3451 
3452  if (!NT_SUCCESS(Status))
3453  {
3454  DPRINT1("NtSetInformationToken failed with Status 0x%lx\n", Status);
3455  }
3456 
3457  return Status;
3458 }
3459 
3460 
3461 /*
3462  * @implemented
3463  *
3464  * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
3465  * this is certainly NOT true, although I can't say for sure that EffectiveOnly
3466  * is correct either. -Gunnar
3467  * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
3468  * NOTE for readers: http://hex.pp.ua/nt/NtDuplicateToken.php is therefore
3469  * wrong in that regard, while MSDN documentation is correct.
3470  */
3473 NTSTATUS
3474 NTAPI
3476  _In_ HANDLE ExistingTokenHandle,
3482 {
3484  HANDLE hToken;
3485  PTOKEN Token;
3486  PTOKEN NewToken;
3487  PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService;
3488  BOOLEAN QoSPresent;
3490  NTSTATUS Status;
3491 
3492  PAGED_CODE();
3493 
3494  if (TokenType != TokenImpersonation &&
3496  {
3497  return STATUS_INVALID_PARAMETER;
3498  }
3499 
3501 
3502  if (PreviousMode != KernelMode)
3503  {
3504  _SEH2_TRY
3505  {
3507  }
3509  {
3510  /* Return the exception code */
3512  }
3513  _SEH2_END;
3514  }
3515 
3517  PreviousMode,
3518  PagedPool,
3519  FALSE,
3520  &CapturedSecurityQualityOfService,
3521  &QoSPresent);
3522  if (!NT_SUCCESS(Status))
3523  {
3524  DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status);
3525  return Status;
3526  }
3527 
3528  Status = ObReferenceObjectByHandle(ExistingTokenHandle,
3531  PreviousMode,
3532  (PVOID*)&Token,
3534  if (!NT_SUCCESS(Status))
3535  {
3536  DPRINT1("Failed to reference token (Status 0x%lx)\n", Status);
3537  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
3538  PreviousMode,
3539  FALSE);
3540  return Status;
3541  }
3542 
3543  /*
3544  * Fail, if the original token is an impersonation token and the caller
3545  * tries to raise the impersonation level of the new token above the
3546  * impersonation level of the original token.
3547  */
3548  if (Token->TokenType == TokenImpersonation)
3549  {
3550  if (QoSPresent &&
3551  CapturedSecurityQualityOfService->ImpersonationLevel >Token->ImpersonationLevel)
3552  {
3554  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
3555  PreviousMode,
3556  FALSE);
3558  }
3559  }
3560 
3561  /*
3562  * Fail, if a primary token is to be created from an impersonation token
3563  * and and the impersonation level of the impersonation token is below SecurityImpersonation.
3564  */
3565  if (Token->TokenType == TokenImpersonation &&
3566  TokenType == TokenPrimary &&
3567  Token->ImpersonationLevel < SecurityImpersonation)
3568  {
3570  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
3571  PreviousMode,
3572  FALSE);
3574  }
3575 
3578  EffectiveOnly,
3579  TokenType,
3580  (QoSPresent ? CapturedSecurityQualityOfService->ImpersonationLevel : SecurityAnonymous),
3581  PreviousMode,
3582  &NewToken);
3583 
3585 
3586  if (NT_SUCCESS(Status))
3587  {
3588  Status = ObInsertObject(NewToken,
3589  NULL,
3590  (DesiredAccess ? DesiredAccess : HandleInformation.GrantedAccess),
3591  0,
3592  NULL,
3593  &hToken);
3594  if (NT_SUCCESS(Status))
3595  {
3596  _SEH2_TRY
3597  {
3598  *NewTokenHandle = hToken;
3599  }
3601  {
3603  }
3604  _SEH2_END;
3605  }
3606  }
3607 
3608  /* Free the captured structure */
3609  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
3610  PreviousMode,
3611  FALSE);
3612 
3613  return Status;
3614 }
3615 
3618  IN BOOLEAN ResetToDefault,
3619  IN PTOKEN_GROUPS NewState,
3623 {
3624  UNIMPLEMENTED;
3625  return STATUS_NOT_IMPLEMENTED;
3626 }
3627 
3628 
3629 static
3630 NTSTATUS
3633  _In_ BOOLEAN DisableAllPrivileges,
3634  _In_opt_ PLUID_AND_ATTRIBUTES NewState,
3635  _In_ ULONG NewStateCount,
3638  _Out_ PULONG ChangedPrivileges,
3639  _Out_ PBOOLEAN ChangesMade)
3640 {
3641  ULONG i, j, PrivilegeCount, ChangeCount, NewAttributes;
3642 
3643  /* Count the found privileges and those that need to be changed */
3644  PrivilegeCount = 0;
3645  ChangeCount = 0;
3646  *ChangesMade = FALSE;
3647 
3648  /* Loop all privileges in the token */
3649  for (i = 0; i < Token->PrivilegeCount; i++)
3650  {
3651  /* Shall all of them be disabled? */
3652  if (DisableAllPrivileges)
3653  {
3654  /* The new attributes are the old ones, but disabled */
3655  NewAttributes = Token->Privileges[i].Attributes & ~SE_PRIVILEGE_ENABLED;
3656  }
3657  else
3658  {
3659  /* Otherwise loop all provided privileges */
3660  for (j = 0; j < NewStateCount; j++)
3661  {
3662  /* Check if this is the LUID we are looking for */
3663  if (RtlEqualLuid(&Token->Privileges[i].Luid, &NewState[j].Luid))
3664  {
3665  DPRINT("Found privilege\n");
3666 
3667  /* Copy SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED */
3668  NewAttributes = NewState[j].Attributes;
3669  NewAttributes &= (SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED);
3670  NewAttributes |= Token->Privileges[i].Attributes & ~SE_PRIVILEGE_ENABLED;
3671 
3672  /* Stop looking */
3673  break;
3674  }
3675  }
3676 
3677  /* Check if we didn't find the privilege */
3678  if (j == NewStateCount)
3679  {
3680  /* Continue with the token's next privilege */
3681  continue;
3682  }
3683  }
3684 
3685  /* We found a privilege, count it */
3686  PrivilegeCount++;
3687 
3688  /* Does the privilege need to be changed? */
3689  if (Token->Privileges[i].Attributes != NewAttributes)
3690  {
3691  /* Does the caller want the old privileges? */
3692  if (PreviousState != NULL)
3693  {
3694  /* Copy the old privilege */
3695  PreviousState->Privileges[ChangeCount] = Token->Privileges[i];
3696  }
3697 
3698  /* Does the caller want to apply the changes? */
3699  if (ApplyChanges)
3700  {
3701  /* Shall we remove the privilege? */
3702  if (NewAttributes & SE_PRIVILEGE_REMOVED)
3703  {
3704  /* Set the token as disabled and update flags for it */
3705  Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
3707 
3708  /* Remove the privilege */
3710 
3711  *ChangesMade = TRUE;
3712 
3713  /* Fix the running index and continue with next one */
3714  i--;
3715  continue;
3716  }
3717 
3718  /* Set the new attributes and update flags */
3719  Token->Privileges[i].Attributes = NewAttributes;
3721  *ChangesMade = TRUE;
3722  }
3723 
3724  /* Increment the change count */
3725  ChangeCount++;
3726  }
3727  }
3728 
3729  /* Set the number of saved privileges */
3730  if (PreviousState != NULL)
3731  PreviousState->PrivilegeCount = ChangeCount;
3732 
3733  /* Return the number of changed privileges */
3734  *ChangedPrivileges = ChangeCount;
3735 
3736  /* Check if we missed some */
3737  if (!DisableAllPrivileges && (PrivilegeCount < NewStateCount))
3738  {
3739  return STATUS_NOT_ALL_ASSIGNED;
3740  }
3741 
3742  return STATUS_SUCCESS;
3743 }
3744 
3745 
3746 /*
3747  * @implemented
3748  */
3751 NTSTATUS
3752 NTAPI
3755  _In_ BOOLEAN DisableAllPrivileges,
3756  _In_opt_ PTOKEN_PRIVILEGES NewState,
3761 {
3762  NTSTATUS Status;
3764  PTOKEN Token;
3765  PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
3766  ULONG CapturedCount = 0;
3767  ULONG CapturedLength = 0;
3768  ULONG NewStateSize = 0;
3769  ULONG ChangeCount;
3771  BOOLEAN ChangesMade = FALSE;
3772 
3773  PAGED_CODE();
3774 
3775  DPRINT("NtAdjustPrivilegesToken() called\n");
3776 
3777  /* Fail, if we do not disable all privileges but NewState is NULL */
3778  if (DisableAllPrivileges == FALSE && NewState == NULL)
3779  return STATUS_INVALID_PARAMETER;
3780 
3782  if (PreviousMode != KernelMode)
3783  {
3784  _SEH2_TRY
3785  {
3786  /* Probe NewState */
3787  if (DisableAllPrivileges == FALSE)
3788  {
3789  /* First probe the header */
3790  ProbeForRead(NewState, sizeof(TOKEN_PRIVILEGES), sizeof(ULONG));
3791 
3792  CapturedCount = NewState->PrivilegeCount;
3793  NewStateSize = FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges[CapturedCount]);
3794 
3795  ProbeForRead(NewState, NewStateSize, sizeof(ULONG));
3796  }
3797 
3798  /* Probe PreviousState and ReturnLength */
3799  if (PreviousState != NULL)
3800  {
3802  ProbeForWrite(ReturnLength, sizeof(ULONG), sizeof(ULONG));
3803  }
3804  }
3806  {
3807  /* Return the exception code */
3809  }
3810  _SEH2_END;
3811  }
3812  else
3813  {
3814  /* This is kernel mode, we trust the caller */
3815  if (DisableAllPrivileges == FALSE)
3816  CapturedCount = NewState->PrivilegeCount;
3817  }
3818 
3819  /* Do we need to capture the new state? */
3820  if (DisableAllPrivileges == FALSE)
3821  {
3822  _SEH2_TRY
3823  {
3824  /* Capture the new state array of privileges */
3825  Status = SeCaptureLuidAndAttributesArray(NewState->Privileges,
3826  CapturedCount,
3827  PreviousMode,
3828  NULL,
3829  0,
3830  PagedPool,
3831  TRUE,
3832  &CapturedPrivileges,
3833  &CapturedLength);
3834  }
3836  {
3837  /* Return the exception code */
3839  }
3840  _SEH2_END;
3841 
3842  if (!NT_SUCCESS(Status))
3843  return Status;
3844  }
3845 
3846  /* Reference the token */
3850  PreviousMode,
3851  (PVOID*)&Token,
3852  NULL);
3853  if (!NT_SUCCESS(Status))
3854  {
3855  DPRINT1("Failed to reference token (Status 0x%lx)\n", Status);
3856 
3857  /* Release the captured privileges */
3858  if (CapturedPrivileges != NULL)
3859  {
3860  SeReleaseLuidAndAttributesArray(CapturedPrivileges,
3861  PreviousMode,
3862  TRUE);
3863  }
3864 
3865  return Status;
3866  }
3867 
3868  /* Lock the token */
3870 
3871  /* Count the privileges that need to be changed, do not apply them yet */
3873  DisableAllPrivileges,
3874  CapturedPrivileges,
3875  CapturedCount,
3876  NULL,
3877  FALSE,
3878  &ChangeCount,
3879  &ChangesMade);
3880 
3881  /* Check if the caller asked for the previous state */
3882  if (PreviousState != NULL)
3883  {
3884  /* Calculate the required length */
3886 
3887  /* Try to return the required buffer length */
3888  _SEH2_TRY
3889  {
3891  }
3893  {
3894  /* Do cleanup and return the exception code */
3896  _SEH2_YIELD(goto Cleanup);
3897  }
3898  _SEH2_END;
3899 
3900  /* Fail, if the buffer length is smaller than the required length */
3902  {
3904  goto Cleanup;
3905  }
3906  }
3907 
3908  /* Now enter SEH, since we might return the old privileges */
3909  _SEH2_TRY
3910  {
3911  /* This time apply the changes */
3913  DisableAllPrivileges,
3914  CapturedPrivileges,
3915  CapturedCount,
3916  PreviousState,
3917  TRUE,
3918  &ChangeCount,
3919  &ChangesMade);
3920  }
3922  {
3923  /* Do cleanup and return the exception code */
3925  ChangesMade = TRUE; // Force write.
3926  _SEH2_YIELD(goto Cleanup);
3927  }
3928  _SEH2_END;
3929 
3930 Cleanup:
3931  /* Touch the token if we made changes */
3932  if (ChangesMade)
3933  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3934 
3935  /* Unlock and dereference the token */
3938 
3939  /* Release the captured privileges */
3940  if (CapturedPrivileges != NULL)
3941  {
3942  SeReleaseLuidAndAttributesArray(CapturedPrivileges,
3943  PreviousMode,
3944  TRUE);
3945  }
3946 
3947  DPRINT ("NtAdjustPrivilegesToken() done\n");
3948  return Status;
3949 }
3950 
3952 NTSTATUS
3953 NTAPI
3959  _In_ PLUID AuthenticationId,
3960  _In_ PLARGE_INTEGER ExpirationTime,
3968 {
3969  HANDLE hToken;
3971  ULONG PrivilegeCount, GroupCount;
3972  PSID OwnerSid, PrimaryGroupSid;
3973  PACL DefaultDacl;
3974  LARGE_INTEGER LocalExpirationTime = {{0, 0}};
3975  LUID LocalAuthenticationId;
3976  TOKEN_SOURCE LocalTokenSource;
3977  SECURITY_QUALITY_OF_SERVICE LocalSecurityQos;
3978  PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
3979  PSID_AND_ATTRIBUTES CapturedUser = NULL;
3980  PSID_AND_ATTRIBUTES CapturedGroups = NULL;
3981  PSID CapturedOwnerSid = NULL;
3982  PSID CapturedPrimaryGroupSid = NULL;
3983  PACL CapturedDefaultDacl = NULL;
3984  ULONG PrivilegesLength, UserLength, GroupsLength;
3985  NTSTATUS Status;
3986 
3987  PAGED_CODE();
3988 
3990 
3991  if (PreviousMode != KernelMode)
3992  {
3993  _SEH2_TRY
3994  {
3996 
3997  if (ObjectAttributes != NULL)
3998  {
4000  sizeof(OBJECT_ATTRIBUTES),
4001  sizeof(ULONG));
4002  LocalSecurityQos = *(SECURITY_QUALITY_OF_SERVICE*)ObjectAttributes->SecurityQualityOfService;
4003  }
4004 
4005  ProbeForRead(AuthenticationId,
4006  sizeof(LUID),
4007  sizeof(ULONG));
4008  LocalAuthenticationId = *AuthenticationId;
4009 
4010  LocalExpirationTime = ProbeForReadLargeInteger(ExpirationTime);
4011 
4013  sizeof(TOKEN_USER),
4014  sizeof(ULONG));
4015 
4017  sizeof(TOKEN_GROUPS),
4018  sizeof(ULONG));
4019  GroupCount = TokenGroups->GroupCount;
4020 
4022  sizeof(TOKEN_PRIVILEGES),
4023  sizeof(ULONG));
4024  PrivilegeCount = TokenPrivileges->PrivilegeCount;
4025 
4026  if (TokenOwner != NULL)
4027  {
4029  sizeof(TOKEN_OWNER),
4030  sizeof(ULONG));
4031  OwnerSid = TokenOwner->Owner;
4032  }
4033  else
4034  {
4035  OwnerSid = NULL;
4036  }
4037 
4039  sizeof(TOKEN_PRIMARY_GROUP),
4040  sizeof(ULONG));
4041  PrimaryGroupSid = TokenPrimaryGroup->PrimaryGroup;
4042 
4043  if (TokenDefaultDacl != NULL)
4044  {
4046  sizeof(TOKEN_DEFAULT_DACL),
4047  sizeof(ULONG));
4048  DefaultDacl = TokenDefaultDacl->DefaultDacl;
4049  }
4050  else
4051  {
4052  DefaultDacl = NULL;
4053  }
4054 
4056  sizeof(TOKEN_SOURCE),
4057  sizeof(ULONG));
4058  LocalTokenSource = *TokenSource;
4059  }
4061  {
4062  /* Return the exception code */
4064  }
4065  _SEH2_END;
4066  }
4067  else
4068  {
4069  if (ObjectAttributes != NULL)
4070  LocalSecurityQos = *(SECURITY_QUALITY_OF_SERVICE*)ObjectAttributes->SecurityQualityOfService;
4071  LocalAuthenticationId = *AuthenticationId;
4072  LocalExpirationTime = *ExpirationTime;
4073  GroupCount = TokenGroups->GroupCount;
4074  PrivilegeCount = TokenPrivileges->PrivilegeCount;
4075  OwnerSid = TokenOwner ? TokenOwner->Owner : NULL;
4076  PrimaryGroupSid = TokenPrimaryGroup->PrimaryGroup;
4077  DefaultDacl = TokenDefaultDacl ? TokenDefaultDacl->DefaultDacl : NULL;
4078  LocalTokenSource = *TokenSource;
4079  }
4080 
4081  /* Check token type */
4082  if ((TokenType < TokenPrimary) ||
4084  {
4085  return STATUS_BAD_TOKEN_TYPE;
4086  }
4087 
4088  /* Check for token creation privilege */
4090  {
4092  }
4093 
4094  /* Capture the user SID and attributes */
4096  1,
4097  PreviousMode,
4098  NULL,
4099  0,
4100  PagedPool,
4101  FALSE,
4102  &CapturedUser,
4103  &UserLength);
4104  if (!NT_SUCCESS(Status))
4105  {
4106  goto Cleanup;
4107  }
4108 
4109  /* Capture the groups SID and attributes array */
4111  GroupCount,
4112  PreviousMode,
4113  NULL,
4114  0,
4115  PagedPool,
4116  FALSE,
4117  &CapturedGroups,
4118  &GroupsLength);
4119  if (!NT_SUCCESS(Status))
4120  {
4121  goto Cleanup;
4122  }
4123 
4124  /* Capture privileges */
4126  PrivilegeCount,
4127  PreviousMode,
4128  NULL,
4129  0,
4130  PagedPool,
4131  FALSE,
4132  &CapturedPrivileges,
4133  &PrivilegesLength);
4134  if (!NT_SUCCESS(Status))
4135  {
4136  goto Cleanup;
4137  }
4138 
4139  /* Capture the token owner SID */
4140  if (TokenOwner != NULL)
4141  {
4142  Status = SepCaptureSid(OwnerSid,
4143  PreviousMode,
4144  PagedPool,
4145  FALSE,
4146  &CapturedOwnerSid);
4147  if (!NT_SUCCESS(Status))
4148  {
4149  goto Cleanup;
4150  }
4151  }
4152 
4153  /* Capture the token primary group SID */
4154  Status = SepCaptureSid(PrimaryGroupSid,
4155  PreviousMode,
4156  PagedPool,
4157  FALSE,
4158  &CapturedPrimaryGroupSid);
4159  if (!NT_SUCCESS(Status))
4160  {
4161  goto Cleanup;
4162  }
4163 
4164  /* Capture DefaultDacl */
4165  if (DefaultDacl != NULL)
4166  {
4167  Status = SepCaptureAcl(DefaultDacl,
4168  PreviousMode,
4169  NonPagedPool,
4170  FALSE,
4171  &CapturedDefaultDacl);
4172  if (!NT_SUCCESS(Status))
4173  {
4174  goto Cleanup;
4175  }
4176  }
4177 
4178  /* Call the internal function */
4179  Status = SepCreateToken(&hToken,
4180  PreviousMode,
4181  DesiredAccess,
4183  TokenType,
4184  LocalSecurityQos.ImpersonationLevel,
4185  &LocalAuthenticationId,
4186  &LocalExpirationTime,
4187  CapturedUser,
4188  GroupCount,
4189  CapturedGroups,
4190  GroupsLength,
4191  PrivilegeCount,
4192  CapturedPrivileges,
4193  CapturedOwnerSid,
4194  CapturedPrimaryGroupSid,
4195  CapturedDefaultDacl,
4196  &LocalTokenSource,
4197  FALSE);
4198  if (NT_SUCCESS(Status))
4199  {
4200  _SEH2_TRY
4201  {
4202  *TokenHandle = hToken;
4203  }
4205  {
4207  }
4208  _SEH2_END;
4209  }
4210 
4211 Cleanup:
4212 
4213  /* Release what we captured */
4216  SeReleaseLuidAndAttributesArray(CapturedPrivileges, PreviousMode, FALSE);
4217  SepReleaseSid(CapturedOwnerSid, PreviousMode, FALSE);
4218  SepReleaseSid(CapturedPrimaryGroupSid, PreviousMode, FALSE);
4219  SepReleaseAcl(CapturedDefaultDacl, PreviousMode, FALSE);
4220 
4221  return Status;
4222 }
4223 
4224 /*
4225  * @implemented
4226  */
4227 NTSTATUS
4228 NTAPI
4234 {
4235  PETHREAD Thread;
4236  HANDLE hToken;
4237  PTOKEN Token, NewToken = NULL, PrimaryToken;
4243  PACL Dacl = NULL;
4245  NTSTATUS Status;
4246  BOOLEAN RestoreImpersonation = FALSE;
4247 
4248  PAGED_CODE();
4249 
4251 
4252  if (PreviousMode != KernelMode)
4253  {
4254  _SEH2_TRY
4255  {
4257  }
4259  {
4260  /* Return the exception code */
4262  }
4263  _SEH2_END;
4264  }
4265 
4266  /* Validate object attributes */
4268 
4269  /*
4270  * At first open the thread token for information access and verify
4271  * that the token associated with thread is valid.
4272  */
4273 
4276  NULL);
4277  if (!NT_SUCCESS(Status))
4278  {
4279  return Status;
4280  }
4281 
4284  if (Token == NULL)
4285  {
4287  return STATUS_NO_TOKEN;
4288  }
4289 
4291  {
4295  }
4296 
4297  /*
4298  * Revert to self if OpenAsSelf is specified.
4299  */
4300 
4301  if (OpenAsSelf)
4302  {
4303  RestoreImpersonation = PsDisableImpersonation(PsGetCurrentThread(),
4305  }
4306 
4307  if (CopyOnOpen)
4308  {
4309  PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
4310 
4311  Status = SepCreateImpersonationTokenDacl(Token, PrimaryToken, &Dacl);
4312 
4313  ObFastDereferenceObject(&Thread->ThreadsProcess->Token, PrimaryToken);
4314 
4315  if (NT_SUCCESS(Status))
4316  {
4317  if (Dacl)
4318  {
4321  if (!NT_SUCCESS(Status))
4322  {
4323  DPRINT1("NtOpenThreadTokenEx(): Failed to create a security descriptor (Status 0x%lx)\n", Status);
4324  }
4325 
4327  FALSE);
4328  if (!NT_SUCCESS(Status))
4329  {
4330  DPRINT1("NtOpenThreadTokenEx(): Failed to set a DACL to the security descriptor (Status 0x%lx)\n", Status);
4331  }
4332  }
4333 
4336 
4339  KernelMode, &NewToken);
4340  if (!NT_SUCCESS(Status))
4341  {
4342  DPRINT1("NtOpenThreadTokenEx(): Failed to duplicate the token (Status 0x%lx)\n");
4343  }
4344 
4345  ObReferenceObject(NewToken);
4346  Status = ObInsertObject(NewToken, NULL, DesiredAccess, 0, NULL,
4347  &hToken);
4348  if (!NT_SUCCESS(Status))
4349  {
4350  DPRINT1("NtOpenThreadTokenEx(): Failed to insert the token object (Status 0x%lx)\n", Status);
4351  }
4352  }
4353  else
4354  {
4355  DPRINT1("NtOpenThreadTokenEx(): Failed to impersonate token from DACL (Status 0x%lx)\n", Status);
4356  }
4357  }
4358  else
4359  {
4362  PreviousMode, &hToken);
4363  if (!NT_SUCCESS(Status))
4364  {
4365  DPRINT1("NtOpenThreadTokenEx(): Failed to open the object (Status 0x%lx)\n", Status);
4366  }
4367  }
4368 
4370 
4371  if (RestoreImpersonation)
4372  {
4374  }
4375 
4377 
4378  if (NT_SUCCESS(Status) && CopyOnOpen)
4379  {
4381  if (!NT_SUCCESS(Status))
4382  {
4383  DPRINT1("NtOpenThreadTokenEx(): Failed to impersonate the client (Status 0x%lx)\n");
4384  }
4385  }
4386 
4387  if (NewToken) ObDereferenceObject(NewToken);
4388 
4390 
4391  if (NT_SUCCESS(Status))
4392  {
4393  _SEH2_TRY
4394  {
4395  *TokenHandle = hToken;
4396  }
4398  {
4400  }
4401  _SEH2_END;
4402  }
4403 
4404  return Status;
4405 }
4406 
4407 /*
4408  * @implemented
4409  */
4415 {
4416  return NtOpenThreadTokenEx(ThreadHandle, DesiredAccess, OpenAsSelf, 0,
4417  TokenHandle);
4418 }
4419 
4437 NTSTATUS
4438 NTAPI
4440  _In_ HANDLE FirstTokenHandle,
4441  _In_ HANDLE SecondTokenHandle,
4442  _Out_ PBOOLEAN Equal)
4443 {
4445  PTOKEN FirstToken, SecondToken;
4446  BOOLEAN IsEqual;
4447  NTSTATUS Status;
4448 
4449  PAGED_CODE();
4450 
4452 
4453  if (PreviousMode != KernelMode)
4454  {
4455  _SEH2_TRY
4456  {
4457  ProbeForWriteBoolean(Equal);
4458  }
4460  {
4461  /* Return the exception code */
4463  }
4464  _SEH2_END;
4465  }
4466 
4467  Status = ObReferenceObjectByHandle(FirstTokenHandle,
4468  TOKEN_QUERY,
4470  PreviousMode,
4471  (PVOID*)&FirstToken,
4472  NULL);
4473  if (!NT_SUCCESS(Status))
4474  {
4475  DPRINT1("ObReferenceObjectByHandle() failed (Status 0x%lx)\n", Status);
4476  return Status;
4477  }
4478 
4479  Status = ObReferenceObjectByHandle(SecondTokenHandle,
4480  TOKEN_QUERY,
4482  PreviousMode,
4483  (PVOID*)&SecondToken,
4484  NULL);
4485  if (!NT_SUCCESS(Status))
4486  {
4487  DPRINT1("ObReferenceObjectByHandle() failed (Status 0x%lx)\n", Status);
4488  ObDereferenceObject(FirstToken);
4489  return Status;
4490  }
4491 
4492  if (FirstToken != SecondToken)
4493  {
4494  Status = SepCompareTokens(FirstToken,
4495  SecondToken,
4496  &IsEqual);
4497  }
4498  else
4499  {
4500  IsEqual = TRUE;
4501  }
4502 
4503  ObDereferenceObject(SecondToken);
4504  ObDereferenceObject(FirstToken);
4505 
4506  if (NT_SUCCESS(Status))
4507  {
4508  _SEH2_TRY
4509  {
4510  *Equal = IsEqual;
4511  }
4513  {
4515  }
4516  _SEH2_END;
4517  }
4518 
4519  return Status;
4520 }
4521 
4522 NTSTATUS
4523 NTAPI
4524 NtFilterToken(IN HANDLE ExistingTokenHandle,
4525  IN ULONG Flags,
4526  IN PTOKEN_GROUPS SidsToDisable OPTIONAL,
4527  IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL,
4528  IN PTOKEN_GROUPS RestrictedSids OPTIONAL,
4530 {
4531  UNIMPLEMENTED;
4532  return STATUS_NOT_IMPLEMENTED;
4533 }
4534 
4559 NTSTATUS
4560 NTAPI
4562  _In_ HANDLE ThreadHandle)
4563 {
4564  PETHREAD Thread;
4566  NTSTATUS Status;
4567  PAGED_CODE();
4568 
4570 
4571  /* Obtain the thread object from the handle */
4572  Status = ObReferenceObjectByHandle(ThreadHandle,
4574  PsThreadType,
4575  PreviousMode,
4576  (PVOID*)&Thread,
4577  NULL);
4578  if (!NT_SUCCESS(Status))
4579  {
4580  DPRINT1("NtImpersonateAnonymousToken(): Failed to reference the object (Status 0x%lx)\n", Status);
4581  return Status;
4582  }
4583 
4584  /* Call the private routine to impersonate the token */
4586  if (!NT_SUCCESS(Status))
4587  {
4588  DPRINT1("NtImpersonateAnonymousToken(): Failed to impersonate the token (Status 0x%lx)\n", Status);
4589  }
4590 
4592  return Status;
4593 }
4594 
4595 /* EOF */
LUID AuthenticationId
Definition: setypes.h:1037
PTOKEN SeAnonymousLogonTokenNoEveryone
Definition: semgr.c:19
#define OBJ_OPENLINK
Definition: winternl.h:230
TOKEN_TYPE TokenType
Definition: setypes.h:221
const LUID SeSystemEnvironmentPrivilege
Definition: priv.c:39
enum _SECURITY_IMPERSONATION_LEVEL * PSECURITY_IMPERSONATION_LEVEL
#define SepAcquireTokenLockExclusive(Token)
Definition: se.h:216
static NTSTATUS SepFindPrimaryGroupAndDefaultOwner(_In_ PTOKEN Token, _In_ PSID PrimaryGroup, _In_opt_ PSID DefaultOwner, _Out_opt_ PULONG PrimaryGroupIndex, _Out_opt_ PULONG DefaultOwnerIndex)
Definition: token.c:689
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
NTSTATUS NTAPI PsImpersonateClient(IN PETHREAD Thread, IN PACCESS_TOKEN Token, IN BOOLEAN CopyOnOpen, IN BOOLEAN EffectiveOnly, IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
Definition: security.c:610
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
#define STATUS_NOT_ALL_ASSIGNED
Definition: ntstatus.h:85
_In_ HANDLE _In_opt_ HANDLE _Out_opt_ PHANDLE _In_ ACCESS_MASK _In_ ULONG HandleAttributes
Definition: obfuncs.h:429
_Must_inspect_result_ typedef _In_ PVOID Unused
Definition: iotypes.h:1166
NTSTATUS NTAPI SepRegQueryHelper(_In_ PCWSTR KeyName, _In_ PCWSTR ValueName, _In_ ULONG ValueType, _In_ ULONG DataLength, _Out_ PVOID ValueData)
A private registry helper that returns the desired value data based on the specifics requested by the...
Definition: srm.c:98
#define IN
Definition: typedefs.h:39
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3767
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
NTSTATUS NTAPI ObCreateObjectType(IN PUNICODE_STRING TypeName, IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, IN PVOID Reserved, OUT POBJECT_TYPE *ObjectType)
Definition: oblife.c:1048
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2654
#define STATUS_BAD_IMPERSONATION_LEVEL
Definition: ntstatus.h:401
const LUID SeSystemtimePrivilege
Definition: priv.c:29
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS NTAPI SeFilterToken(IN PACCESS_TOKEN ExistingToken, IN ULONG Flags, IN PTOKEN_GROUPS SidsToDisable OPTIONAL, IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL, IN PTOKEN_GROUPS RestrictedSids OPTIONAL, OUT PACCESS_TOKEN *FilteredToken)
Definition: token.c:1781
#define _In_opt_
Definition: ms_sal.h:309
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
NTSTATUS NTAPI SeQueryInformationToken(_In_ PACCESS_TOKEN AccessToken, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _Outptr_result_buffer_(_Inexpressible_(token-dependent)) PVOID *TokenInformation)
Queries information details about the given token to the call. The difference between NtQueryInformat...
Definition: token.c:1825
BOOLEAN NTAPI SeTokenCanImpersonate(_In_ PTOKEN ProcessToken, _In_ PTOKEN TokenToImpersonate, _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
Ensures that client impersonation can occur by checking if the token we're going to assign as the imp...
Definition: token.c:2286
_Inout_ PSE_IMPERSONATION_STATE ImpersonationState
Definition: psfuncs.h:189
NTSTATUS NTAPI NtFilterToken(IN HANDLE ExistingTokenHandle, IN ULONG Flags, IN PTOKEN_GROUPS SidsToDisable OPTIONAL, IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL, IN PTOKEN_GROUPS RestrictedSids OPTIONAL, OUT PHANDLE NewTokenHandle)
Definition: token.c:4524
#define _Inout_
Definition: ms_sal.h:378
NTSTATUS NTAPI SeIsTokenChild(IN PTOKEN Token, OUT PBOOLEAN IsChild)
Definition: token.c:1064
const LUID SeIncreaseQuotaPrivilege
Definition: priv.c:22
#define TOKEN_WRITE
Definition: setypes.h:903
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define THREAD_IMPERSONATE
Definition: pstypes.h:151
const LUID SeCreateTokenPrivilege
Definition: priv.c:19
VOID NTAPI SeReleaseSidAndAttributesArray(_In_ _Post_invalid_ PSID_AND_ATTRIBUTES CapturedSidAndAttributes, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Definition: sid.c:555
struct _TOKEN_PRIMARY_GROUP * PTOKEN_PRIMARY_GROUP
#define _Out_
Definition: ms_sal.h:345
const LUID SeCreatePermanentPrivilege
Definition: priv.c:33
const LUID SeDebugPrivilege
Definition: priv.c:37
NTSTATUS NTAPI SepCopyProxyData(PVOID *Dest, PVOID Src)
Definition: token.c:568
const LUID SeBackupPrivilege
Definition: priv.c:34
_In_ TOKEN_INFORMATION_CLASS _In_ ULONG TokenInformationLength
Definition: sefuncs.h:320
#define TRUE
Definition: types.h:120
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH _In_opt_ PEPROCESS _In_opt_ PETHREAD _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor
Definition: wsk.h:182
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
USHORT AclSize
Definition: ms-dtyp.idl:296
struct _TOKEN_DEFAULT_DACL TOKEN_DEFAULT_DACL
PACL SeSystemDefaultDacl
Definition: acl.c:19
BOOL ApplyChanges(HWND hwndDlg)
Definition: sounds.c:961
enum _TOKEN_TYPE * PTOKEN_TYPE
$ULONG GroupCount
Definition: setypes.h:1043
NTSTATUS NTAPI SeQuerySessionIdToken(IN PACCESS_TOKEN Token, IN PULONG pSessionId)
Definition: token.c:2166
$ULONG DynamicCharged
Definition: setypes.h:1041
LUID AuthenticationId
Definition: setypes.h:201
ULONG SessionId
Definition: dllmain.c:28
NTSYSAPI NTSTATUS NTAPI RtlCopySidAndAttributesArray(_In_ ULONG Count, _In_ PSID_AND_ATTRIBUTES Src, _In_ ULONG SidAreaSize, _In_ PSID_AND_ATTRIBUTES Dest, _In_ PSID SidArea, _Out_ PSID *RemainingSidArea, _Out_ PULONG RemainingSidAreaSize)
#define KeGetPreviousMode()
Definition: ketypes.h:1107
#define STATUS_CANT_OPEN_ANONYMOUS
Definition: ntstatus.h:402
LONG NTSTATUS
Definition: precomp.h:26
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
VOID NTAPI SeReleaseLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Privilege, KPROCESSOR_MODE PreviousMode, BOOLEAN CaptureIfKernel)
Definition: priv.c:383
#define SE_RESTORE_PRIVILEGE
Definition: security.c:672
struct _LUID_AND_ATTRIBUTES LUID_AND_ATTRIBUTES
static NTSTATUS SepImpersonateAnonymousToken(_In_ PETHREAD Thread, _In_ KPROCESSOR_MODE PreviousMode)
Private function that impersonates the system's anonymous logon token. The major bulk of the imperson...
Definition: token.c:379
NTSTATUS NTAPI NtCompareTokens(_In_ HANDLE FirstTokenHandle, _In_ HANDLE SecondTokenHandle, _Out_ PBOOLEAN Equal)
Compares tokens if they're equal or not.
Definition: token.c:4439
NTSTATUS NTAPI NtOpenThreadTokenEx(IN HANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN OpenAsSelf, IN ULONG HandleAttributes, OUT PHANDLE TokenHandle)
Definition: token.c:4229
LUID SeSystemAuthenticationId
Definition: token.c:22
_Out_ PBOOLEAN CopyOnOpen
Definition: psfuncs.h:154
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
NTSTATUS NTAPI ExDeleteResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1456
PVOID PACCESS_TOKEN
Definition: setypes.h:11
#define SE_PRIVILEGE_REMOVED
Definition: setypes.h:64
PTOKEN SeAnonymousLogonToken
Definition: semgr.c:18
BOOLEAN NTAPI SeSinglePrivilegeCheck(IN LUID PrivilegeValue, IN KPROCESSOR_MODE PreviousMode)
Definition: priv.c:520
#define TOKEN_HAS_TRAVERSE_PRIVILEGE
Definition: setypes.h:1128
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3070
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:55
const LUID SeAssignPrimaryTokenPrivilege
Definition: priv.c:20
#define TOKEN_IMPERSONATE
Definition: setypes.h:877
NTSYSAPI NTSTATUS NTAPI RtlCreateSecurityDescriptor(_Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ ULONG Revision)
#define _When_(expr, annos)
Definition: ms_sal.h:254
PSID SeAuthenticatedUsersSid
Definition: sid.c:51
if(dx==0 &&dy==0)
Definition: linetemp.h:174
TOpcodeData Groups[17][8]
NTSTATUS NTAPI ObOpenObjectByPointer(IN PVOID Object, IN ULONG HandleAttributes, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PHANDLE Handle)
Definition: obhandle.c:2738
static VOID SepUpdateSinglePrivilegeFlagToken(_Inout_ PTOKEN Token, _In_ ULONG Index)
Definition: token.c:472
NTSYSAPI NTSTATUS WINAPI RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR, BOOLEAN, PACL, BOOLEAN)
struct _TOKEN_USER TOKEN_USER
static __inline NTSTATUS DefaultSetInfoBufferCheck(ULONG Class, const INFORMATION_CLASS_INFO *ClassList, ULONG ClassListEntries, PVOID Buffer, ULONG BufferLength, KPROCESSOR_MODE PreviousMode)
Definition: probe.h:8
#define ICIF_SET_SIZE_VARIABLE
Definition: icif.h:22
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
NTSTATUS NTAPI SeCaptureLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Src, ULONG PrivilegeCount, KPROCESSOR_MODE PreviousMode, PLUID_AND_ATTRIBUTES AllocatedMem, ULONG AllocatedLength, POOL_TYPE PoolType, BOOLEAN CaptureIfKernel, PLUID_AND_ATTRIBUTES *Dest, PULONG Length)
Definition: priv.c:287
BOOLEAN NTAPI SeTokenIsRestricted(IN PACCESS_TOKEN Token)
Definition: token.c:2242
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
static __inline NTSTATUS DefaultQueryInfoBufferCheck(ULONG Class, const INFORMATION_CLASS_INFO *ClassList, ULONG ClassListEntries, PVOID Buffer, ULONG BufferLength, PULONG ReturnLength, PULONG_PTR ReturnLengthPtr, KPROCESSOR_MODE PreviousMode, BOOLEAN CompleteProbing)
Definition: probe.h:59
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define SECURITY_DESCRIPTOR_REVISION
Definition: setypes.h:58
NTSTATUS NTAPI SepDuplicateToken(_In_ PTOKEN Token, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ BOOLEAN EffectiveOnly, _In_ TOKEN_TYPE TokenType, _In_ SECURITY_IMPERSONATION_LEVEL Level, _In_ KPROCESSOR_MODE PreviousMode, _Out_ PTOKEN *NewAccessToken)
Definition: token.c:785
NTSTATUS NTAPI SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token, OUT PLUID LogonId)
Definition: token.c:2187
ULONG TokenFlags
Definition: setypes.h:223
NTSTATUS NTAPI NtImpersonateAnonymousToken(_In_ HANDLE ThreadHandle)
Allows the calling thread to impersonate the system's anonymous logon token.
Definition: token.c:4561
return STATUS_NOT_IMPLEMENTED
#define SE_PRIVILEGE_ENABLED
Definition: setypes.h:63
LUID SourceIdentifier
Definition: imports.h:279
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE _Out_ PHANDLE NewTokenHandle
Definition: sefuncs.h:417
struct _TOKEN_DEFAULT_DACL * PTOKEN_DEFAULT_DACL
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define SE_GROUP_OWNER
Definition: setypes.h:93
#define FALSE
Definition: types.h:117
LUID SeAnonymousAuthenticationId
Definition: token.c:23
#define RtlEqualLuid(Luid1, Luid2)
Definition: rtlfuncs.h:301
static VOID SepUpdatePrivilegeFlagsToken(_Inout_ PTOKEN Token)
Definition: token.c:523
NTSYSAPI VOID NTAPI RtlCopyLuidAndAttributesArray(ULONG Count, PLUID_AND_ATTRIBUTES Src, PLUID_AND_ATTRIBUTES Dest)
Definition: luid.c:33
#define ICIF_SET
Definition: icif.h:20
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
Definition: glfuncs.h:210
enum _SECURITY_IMPERSONATION_LEVEL SECURITY_IMPERSONATION_LEVEL
struct _TOKEN_ORIGIN * PTOKEN_ORIGIN
struct NameRec_ * Name
Definition: cdprocs.h:459
#define PsGetCurrentProcess
Definition: psfuncs.h:17
NTSTATUS NTAPI NtAdjustGroupsToken(IN HANDLE TokenHandle, IN BOOLEAN ResetToDefault, IN PTOKEN_GROUPS NewState, IN ULONG BufferLength, OUT PTOKEN_GROUPS PreviousState OPTIONAL, OUT PULONG ReturnLength)
Definition: token.c:3617
PTOKEN NTAPI SepCreateSystemProcessToken(VOID)
Creates the system process token.
Definition: token.c:1507
VOID NTAPI PsRestoreImpersonation(IN PETHREAD Thread, IN PSE_IMPERSONATION_STATE ImpersonationState)
Definition: security.c:965
unsigned char BOOLEAN
#define STATUS_BAD_TOKEN_TYPE
Definition: ntstatus.h:404
const LUID SeLoadDriverPrivilege
Definition: priv.c:27
POBJECT_TYPE SeTokenObjectType
Definition: token.c:19
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtQueryInformationToken(_In_ HANDLE TokenHandle, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _Out_writes_bytes_to_opt_(TokenInformationLength, *ReturnLength) PVOID TokenInformation, _In_ ULONG TokenInformationLength, _Out_ PULONG ReturnLength)
Definition: token.c:2372
#define SE_GROUP_ENABLED_BY_DEFAULT
Definition: setypes.h:91
const LUID SeTakeOwnershipPrivilege
Definition: priv.c:26
#define _In_
Definition: ms_sal.h:308
LUID ParentTokenId
Definition: setypes.h:202
NTSTATUS NTAPI SepCaptureAcl(IN PACL InputAcl, IN KPROCESSOR_MODE AccessMode, IN POOL_TYPE PoolType, IN BOOLEAN CaptureIfKernel, OUT PACL *CapturedAcl)
Definition: acl.c:299
_In_ ULONG _In_ ACCESS_MASK _In_ PSID Sid
Definition: rtlfuncs.h:1103
PSID Owner
Definition: setypes.h:978
NTSTATUS NTAPI SepCreateToken(_Out_ PHANDLE TokenHandle, _In_ KPROCESSOR_MODE PreviousMode, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ TOKEN_TYPE TokenType, _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, _In_ PLUID AuthenticationId, _In_ PLARGE_INTEGER ExpirationTime, _In_ PSID_AND_ATTRIBUTES User, _In_ ULONG GroupCount, _In_ PSID_AND_ATTRIBUTES Groups, _In_ ULONG GroupsLength, _In_ ULONG PrivilegeCount, _In_ PLUID_AND_ATTRIBUTES Privileges, _In_opt_ PSID Owner, _In_ PSID PrimaryGroup, _In_opt_ PACL DefaultDacl, _In_ PTOKEN_SOURCE TokenSource, _In_ BOOLEAN SystemToken)
Definition: token.c:1232
#define TOKEN_ADJUST_DEFAULT
Definition: setypes.h:882
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:715
static BOOLEAN SepCompareSidAndAttributesFromTokens(_In_ PSID_AND_ATTRIBUTES SidArrayToken1, _In_ ULONG CountSidArray1, _In_ PSID_AND_ATTRIBUTES SidArrayToken2, _In_ ULONG CountSidArray2)
Compares the elements of SID arrays provided by tokens. The elements that are being compared for equa...
Definition: token.c:152
NTSTATUS NTAPI ObReferenceObjectByPointer(IN PVOID Object, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode)
Definition: obref.c:381
NTSYSAPI ULONG NTAPI RtlLengthSid(IN PSID Sid)
Definition: sid.c:150
TOKEN_TYPE NTAPI SeTokenType(IN PACCESS_TOKEN Token)
Definition: token.c:2215
void * PVOID
Definition: retypes.h:9
TOKEN_TYPE TokenType
Definition: setypes.h:1039
struct _TOKEN_GROUPS * PTOKEN_GROUPS
SECURITY_IMPERSONATION_LEVEL NTAPI SeTokenImpersonationLevel(IN PACCESS_TOKEN Token)
Definition: token.c:2203
ULONG SessionId
Definition: setypes.h:207
NTSTATUS SepRmDereferenceLogonSession(PLUID LogonLuid)
Definition: srm.c:778
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:952
LUID OriginatingLogonSession
Definition: setypes.h:1057
#define ANONYMOUS_LOGON_LUID
Definition: setypes.h:673
NTSTATUS SepRmReferenceLogonSession(PLUID LogonLuid)
Definition: srm.c:495
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
BOOLEAN NTAPI PsDisableImpersonation(IN PETHREAD Thread, OUT PSE_IMPERSONATION_STATE ImpersonationState)
Definition: security.c:915
struct _ACL * PACL
Definition: security.c:104
UNICODE_STRING Restricted
Definition: utils.c:24
PULONG DynamicPart
Definition: setypes.h:219
#define ICIF_SIZE_VARIABLE
Definition: icif.h:23
Status
Definition: gdiplustypes.h:24
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ SaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ OwnerSize PSID _Inout_ PULONG _Out_writes_bytes_to_opt_ PrimaryGroupSize PSID PrimaryGroup
Definition: rtlfuncs.h:1558
#define SE_CHANGE_NOTIFY_PRIVILEGE
Definition: security.c:677
struct _SID_AND_ATTRIBUTES * PSID_AND_ATTRIBUTES
Definition: security.c:129
#define SE_PRIVILEGE_ENABLED_BY_DEFAULT
Definition: setypes.h:62
#define TAG_SE
Definition: tag.h:173
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
LARGE_INTEGER ExpirationTime
Definition: setypes.h:1038
int Count
Definition: noreturn.cpp:7
static NTSTATUS SepAdjustPrivileges(_Inout_ PTOKEN Token, _In_ BOOLEAN DisableAllPrivileges, _In_opt_ PLUID_AND_ATTRIBUTES NewState, _In_ ULONG NewStateCount, _Out_opt_ PTOKEN_PRIVILEGES PreviousState, _In_ BOOLEAN ApplyChanges, _Out_ PULONG ChangedPrivileges, _Out_ PBOOLEAN ChangesMade)
Definition: token.c:3631
#define STATUS_INVALID_PRIMARY_GROUP
Definition: ntstatus.h:327
#define TOKEN_HAS_RESTORE_PRIVILEGE
Definition: setypes.h:1130
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
const LUID SeCreatePagefilePrivilege
Definition: priv.c:32
struct _TOKEN_SOURCE * PTOKEN_SOURCE
#define TOKEN_QUERY
Definition: setypes.h:878
#define __kernel_entry
Definition: specstrings.h:355
#define ASSERT(a)
Definition: mode.c:44
const LUID SeRestorePrivilege
Definition: priv.c:35
PVOID FASTCALL ObFastReplaceObject(IN PEX_FAST_REF FastRef, IN PVOID Object)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define SE_GROUP_ENABLED
Definition: setypes.h:92
struct _TOKEN_OWNER TOKEN_OWNER
BOOLEAN TokenInUse
Definition: setypes.h:224
VOID NTAPI SepReleaseAcl(IN PACL CapturedAcl, IN KPROCESSOR_MODE AccessMode, IN BOOLEAN CaptureIfKernel)
Definition: acl.c:387
struct _TOKEN_SOURCE TOKEN_SOURCE
_In_ WDFCOLLECTION _In_ ULONG Index
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
struct _SID_AND_ATTRIBUTES SID_AND_ATTRIBUTES
static NTSTATUS SepCompareTokens(_In_ PTOKEN FirstToken, _In_ PTOKEN SecondToken, _Out_ PBOOLEAN Equal)
Compares tokens if they're equal based on all the following properties. If all of the said conditions...
Definition: token.c:288
_Out_ PBOOLEAN _Out_ PBOOLEAN _Out_ PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: psfuncs.h:154
#define ObDereferenceObject
Definition: obfuncs.h:203
#define STATUS_TOKEN_ALREADY_IN_USE
Definition: ntstatus.h:535
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: setypes.h:1040
VOID NTAPI SepFreeProxyData(PVOID ProxyData)
Definition: token.c:561
PVOID HANDLE
Definition: typedefs.h:73
#define TOKEN_ALL_ACCESS
Definition: setypes.h:896
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
#define RtlIsZeroLuid(_L1)
Definition: rtlfuncs.h:753
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2652
_In_ ACCESS_MASK _In_opt_ POBJECT_TYPE _In_ KPROCESSOR_MODE _Out_ PVOID _Out_opt_ POBJECT_HANDLE_INFORMATION HandleInformation
Definition: obfuncs.h:40
#define TOKEN_QUERY_SOURCE
Definition: setypes.h:879
SEP_AUDIT_POLICY_CATEGORIES PolicyElements
Definition: setypes.h:148
NTSTATUS NTAPI SeIsTokenSibling(IN PTOKEN Token, OUT PBOOLEAN IsSibling)
Definition: token.c:1097
#define ProbeForWriteBoolean(Ptr)
Definition: probe.h:31
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID NTAPI SeAssignPrimaryToken(IN PEPROCESS Process, IN PTOKEN Token)
Definition: token.c:1212
static const LUID SeChangeNotifyPrivilege
Definition: authpackage.c:167
VOID FASTCALL ObInitializeFastReference(IN PEX_FAST_REF FastRef, IN PVOID Object)
Definition: obref.c:107
#define SE_GROUP_MANDATORY
Definition: setypes.h:90
#define ProbeForReadLargeInteger(Ptr)
Definition: probe.h:75
enum _TOKEN_INFORMATION_CLASS TOKEN_INFORMATION_CLASS
#define STATUS_NO_TOKEN
Definition: ntstatus.h:360
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
PTOKEN SepCreateSystemAnonymousLogonToken(VOID)
Creates the anonymous logon token for the system. The difference between this token and the other one...
Definition: token.c:1657
VOID NTAPI SepInitializeTokenImplementation(VOID)
Definition: token.c:1188
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET * Privileges
Definition: sefuncs.h:13
NTSTATUS NTAPI SeSubProcessToken(IN PTOKEN ParentToken, OUT PTOKEN *Token, IN BOOLEAN InUse, IN ULONG SessionId)
Definition: token.c:1020
struct _SID * PSID
Definition: eventlog.c:35
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define TOKEN_DUPLICATE
Definition: setypes.h:876
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL Dacl
Definition: rtlfuncs.h:1552
char * PBOOLEAN
Definition: retypes.h:11
struct _TOKEN_OWNER * PTOKEN_OWNER
struct _TOKEN_PRIVILEGES * PTOKEN_PRIVILEGES
POBJECT_TYPE PsThreadType
Definition: thread.c:20
#define TAG_SE_TOKEN_LOCK
Definition: tag.h:184
PSID SeAliasAdminsSid
Definition: sid.c:43
struct _TOKEN_STATISTICS * PTOKEN_STATISTICS
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI SepReleaseSecurityQualityOfService(_In_opt_ PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases (frees) the captured SQOS data from an object in the memory pool.
Definition: sqos.c:225
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:240
static const WCHAR L[]
Definition: oid.c:1250
#define TOKEN_READ
Definition: setypes.h:901
TOKEN_SOURCE SeSystemTokenSource
Definition: token.c:21
#define SepReleaseTokenLock(Token)
Definition: se.h:227
__kernel_entry NTSTATUS NTAPI NtCreateToken(_Out_ PHANDLE TokenHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ TOKEN_TYPE TokenType, _In_ PLUID AuthenticationId, _In_ PLARGE_INTEGER ExpirationTime, _In_ PTOKEN_USER TokenUser, _In_ PTOKEN_GROUPS TokenGroups, _In_ PTOKEN_PRIVILEGES TokenPrivileges, _In_opt_ PTOKEN_OWNER TokenOwner, _In_ PTOKEN_PRIMARY_GROUP TokenPrimaryGroup, _In_opt_ PTOKEN_DEFAULT_DACL TokenDefaultDacl, _In_ PTOKEN_SOURCE TokenSource)
Definition: token.c:3954