ReactOS  0.4.15-dev-2504-g2b52f3b
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 #include <ntlsa.h>
15 
17 {
19  struct
20  {
23  } Policies[1];
25 
26 /* GLOBALS ********************************************************************/
27 
29 
30 TOKEN_SOURCE SeSystemTokenSource = {"*SYSTEM*", {0}};
33 
35  TOKEN_READ,
39 };
40 
42 
43  /* Class 0 not used, blame MS! */
44  IQS_SAME(0, 0, 0),
45 
46  /* TokenUser */
48  /* TokenGroups */
50  /* TokenPrivileges */
52  /* TokenOwner */
54  /* TokenPrimaryGroup */
56  /* TokenDefaultDacl */
58  /* TokenSource */
60  /* TokenType */
62  /* TokenImpersonationLevel */
64  /* TokenStatistics */
66  /* TokenRestrictedSids */
68  /* TokenSessionId */
70  /* TokenGroupsAndPrivileges */
72  /* TokenSessionReference */
74  /* TokenSandBoxInert */
76  /* TokenAuditPolicy */
78  /* TokenOrigin */
80 };
81 
82 /* FUNCTIONS *****************************************************************/
83 
96 static
100 {
101  PAGED_CODE();
102 
104  sizeof(ERESOURCE),
106  if (Token->TokenLock == NULL)
107  {
108  DPRINT1("SepCreateTokenLock(): Failed to allocate memory!\n");
110  }
111 
112  ExInitializeResourceLite(Token->TokenLock);
113  return STATUS_SUCCESS;
114 }
115 
126 static
127 VOID
130 {
131  PAGED_CODE();
132 
133  ExDeleteResourceLite(Token->TokenLock);
135 }
136 
159 static
160 BOOLEAN
162  _In_ PSID_AND_ATTRIBUTES SidArrayToken1,
163  _In_ ULONG CountSidArray1,
164  _In_ PSID_AND_ATTRIBUTES SidArrayToken2,
165  _In_ ULONG CountSidArray2)
166 {
167  ULONG FirstCount, SecondCount;
168  PSID_AND_ATTRIBUTES FirstSidArray, SecondSidArray;
169  PAGED_CODE();
170 
171  /* Bail out if index counters provided are not equal */
172  if (CountSidArray1 != CountSidArray2)
173  {
174  DPRINT("SepCompareSidAndAttributesFromTokens(): Index counters are not the same!\n");
175  return FALSE;
176  }
177 
178  /* Loop over the SID arrays and compare them */
179  for (FirstCount = 0; FirstCount < CountSidArray1; FirstCount++)
180  {
181  for (SecondCount = 0; SecondCount < CountSidArray2; SecondCount++)
182  {
183  FirstSidArray = &SidArrayToken1[FirstCount];
184  SecondSidArray = &SidArrayToken2[SecondCount];
185 
186  if (RtlEqualSid(FirstSidArray->Sid, SecondSidArray->Sid) &&
187  FirstSidArray->Attributes == SecondSidArray->Attributes)
188  {
189  break;
190  }
191  }
192 
193  /* We've exhausted the array of the second token without finding this one */
194  if (SecondCount == CountSidArray2)
195  {
196  DPRINT("SepCompareSidAndAttributesFromTokens(): No matching elements could be found in either token!\n");
197  return FALSE;
198  }
199  }
200 
201  return TRUE;
202 }
203 
226 static
227 BOOLEAN
229  _In_ PLUID_AND_ATTRIBUTES PrivArrayToken1,
230  _In_ ULONG CountPrivArray1,
231  _In_ PLUID_AND_ATTRIBUTES PrivArrayToken2,
232  _In_ ULONG CountPrivArray2)
233 {
234  ULONG FirstCount, SecondCount;
235  PLUID_AND_ATTRIBUTES FirstPrivArray, SecondPrivArray;
236  PAGED_CODE();
237 
238  /* Bail out if index counters provided are not equal */
239  if (CountPrivArray1 != CountPrivArray2)
240  {
241  DPRINT("SepComparePrivilegeAndAttributesFromTokens(): Index counters are not the same!\n");
242  return FALSE;
243  }
244 
245  /* Loop over the privilege arrays and compare them */
246  for (FirstCount = 0; FirstCount < CountPrivArray1; FirstCount++)
247  {
248  for (SecondCount = 0; SecondCount < CountPrivArray2; SecondCount++)
249  {
250  FirstPrivArray = &PrivArrayToken1[FirstCount];
251  SecondPrivArray = &PrivArrayToken2[SecondCount];
252 
253  if (RtlEqualLuid(&FirstPrivArray->Luid, &SecondPrivArray->Luid) &&
254  FirstPrivArray->Attributes == SecondPrivArray->Attributes)
255  {
256  break;
257  }
258  }
259 
260  /* We've exhausted the array of the second token without finding this one */
261  if (SecondCount == CountPrivArray2)
262  {
263  DPRINT("SepComparePrivilegeAndAttributesFromTokens(): No matching elements could be found in either token!\n");
264  return FALSE;
265  }
266  }
267 
268  return TRUE;
269 }
270 
295 static
296 NTSTATUS
298  _In_ PTOKEN FirstToken,
299  _In_ PTOKEN SecondToken,
300  _Out_ PBOOLEAN Equal)
301 {
303  PAGED_CODE();
304 
305  ASSERT(FirstToken != SecondToken);
306 
307  /* Lock the tokens */
308  SepAcquireTokenLockShared(FirstToken);
309  SepAcquireTokenLockShared(SecondToken);
310 
311  /* Check if every SID that is present in either token is also present in the other one */
312  if (!SepCompareSidAndAttributesFromTokens(FirstToken->UserAndGroups,
313  FirstToken->UserAndGroupCount,
314  SecondToken->UserAndGroups,
315  SecondToken->UserAndGroupCount))
316  {
317  goto Quit;
318  }
319 
320  /* Is one token restricted but the other isn't? */
321  Restricted = SeTokenIsRestricted(FirstToken);
322  if (Restricted != SeTokenIsRestricted(SecondToken))
323  {
324  /* If that's the case then bail out */
325  goto Quit;
326  }
327 
328  /*
329  * If both tokens are restricted check if every SID
330  * that is restricted in either token is also restricted
331  * in the other one.
332  */
333  if (Restricted)
334  {
335  if (!SepCompareSidAndAttributesFromTokens(FirstToken->RestrictedSids,
336  FirstToken->RestrictedSidCount,
337  SecondToken->RestrictedSids,
338  SecondToken->RestrictedSidCount))
339  {
340  goto Quit;
341  }
342  }
343 
344  /* Check if every privilege present in either token is also present in the other one */
345  if (!SepComparePrivilegeAndAttributesFromTokens(FirstToken->Privileges,
346  FirstToken->PrivilegeCount,
347  SecondToken->Privileges,
348  SecondToken->PrivilegeCount))
349  {
350  goto Quit;
351  }
352 
353  /* If we're here then the tokens are equal */
354  IsEqual = TRUE;
355  DPRINT("SepCompareTokens(): Tokens are equal!\n");
356 
357 Quit:
358  /* Unlock the tokens */
359  SepReleaseTokenLock(SecondToken);
360  SepReleaseTokenLock(FirstToken);
361 
362  *Equal = IsEqual;
363  return STATUS_SUCCESS;
364 }
365 
386 static
387 NTSTATUS
391 {
393  PTOKEN TokenToImpersonate, ProcessToken;
394  ULONG IncludeEveryoneValueData;
395  PAGED_CODE();
396 
397  /*
398  * We must check first which kind of token
399  * shall we assign for the thread to impersonate,
400  * the one with Everyone Group SID or the other
401  * without. Invoke the registry helper to
402  * return the data value for us.
403  */
404  Status = SepRegQueryHelper(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Lsa",
405  L"EveryoneIncludesAnonymous",
406  REG_DWORD,
407  sizeof(IncludeEveryoneValueData),
408  &IncludeEveryoneValueData);
409  if (!NT_SUCCESS(Status))
410  {
411  DPRINT1("SepRegQueryHelper(): Failed to query the registry value (Status 0x%lx)\n", Status);
412  return Status;
413  }
414 
415  if (IncludeEveryoneValueData == 0)
416  {
417  DPRINT("SepImpersonateAnonymousToken(): Assigning the token not including the Everyone Group SID...\n");
418  TokenToImpersonate = SeAnonymousLogonTokenNoEveryone;
419  }
420  else
421  {
422  DPRINT("SepImpersonateAnonymousToken(): Assigning the token including the Everyone Group SID...\n");
423  TokenToImpersonate = SeAnonymousLogonToken;
424  }
425 
426  /*
427  * Tell the object manager that we're going to use this token
428  * object now by incrementing the reference count.
429  */
430  Status = ObReferenceObjectByPointer(TokenToImpersonate,
433  PreviousMode);
434  if (!NT_SUCCESS(Status))
435  {
436  DPRINT1("SepImpersonateAnonymousToken(): Couldn't be able to use the token, bail out...\n");
437  return Status;
438  }
439 
440  /*
441  * Reference the primary token of the current process that the anonymous
442  * logon token impersonation procedure is being performed. We'll be going
443  * to use the process' token to figure out if the process is actually
444  * restricted or not.
445  */
447  if (!ProcessToken)
448  {
449  DPRINT1("SepImpersonateAnonymousToken(): Couldn't be able to get the process' primary token, bail out...\n");
450  ObDereferenceObject(TokenToImpersonate);
451  return STATUS_UNSUCCESSFUL;
452  }
453 
454  /* Now, is the token from the current process restricted? */
455  if (SeTokenIsRestricted(ProcessToken))
456  {
457  DPRINT1("SepImpersonateAnonymousToken(): The process is restricted, can't do anything. Bail out...\n");
458  PsDereferencePrimaryToken(ProcessToken);
459  ObDereferenceObject(TokenToImpersonate);
460  return STATUS_ACCESS_DENIED;
461  }
462 
463  /*
464  * Finally it's time to impersonate! But first, fast dereference the
465  * process' primary token as we no longer need it.
466  */
469  if (!NT_SUCCESS(Status))
470  {
471  DPRINT1("SepImpersonateAnonymousToken(): Failed to impersonate, bail out...\n");
472  ObDereferenceObject(TokenToImpersonate);
473  return Status;
474  }
475 
476  return Status;
477 }
478 
479 static
480 VOID
483  _In_ ULONG Index)
484 {
485  ULONG TokenFlag;
486  ASSERT(Index < Token->PrivilegeCount);
487 
488  /* The high part of all values we are interested in is 0 */
489  if (Token->Privileges[Index].Luid.HighPart != 0)
490  {
491  return;
492  }
493 
494  /* Check for certain privileges to update flags */
495  if (Token->Privileges[Index].Luid.LowPart == SE_CHANGE_NOTIFY_PRIVILEGE)
496  {
497  TokenFlag = TOKEN_HAS_TRAVERSE_PRIVILEGE;
498  }
499  else if (Token->Privileges[Index].Luid.LowPart == SE_BACKUP_PRIVILEGE)
500  {
501  TokenFlag = TOKEN_HAS_BACKUP_PRIVILEGE;
502  }
503  else if (Token->Privileges[Index].Luid.LowPart == SE_RESTORE_PRIVILEGE)
504  {
505  TokenFlag = TOKEN_HAS_RESTORE_PRIVILEGE;
506  }
507  else if (Token->Privileges[Index].Luid.LowPart == SE_IMPERSONATE_PRIVILEGE)
508  {
510  }
511  else
512  {
513  /* Nothing to do */
514  return;
515  }
516 
517  /* Check if the specified privilege is enabled */
518  if (Token->Privileges[Index].Attributes & SE_PRIVILEGE_ENABLED)
519  {
520  /* It is enabled, so set the flag */
521  Token->TokenFlags |= TokenFlag;
522  }
523  else
524  {
525  /* Is is disabled, so remove the flag */
526  Token->TokenFlags &= ~TokenFlag;
527  }
528 }
529 
530 static
531 VOID
534 {
535  ULONG i;
536 
537  /* Loop all privileges */
538  for (i = 0; i < Token->PrivilegeCount; i++)
539  {
540  /* Updates the flags dor this privilege */
542  }
543 }
544 
545 static
546 VOID
549  _In_ ULONG Index)
550 {
551  ULONG MoveCount;
552  ASSERT(Index < Token->PrivilegeCount);
553 
554  /* Calculate the number of trailing privileges */
555  MoveCount = Token->PrivilegeCount - Index - 1;
556  if (MoveCount != 0)
557  {
558  /* Move them one location ahead */
559  RtlMoveMemory(&Token->Privileges[Index],
560  &Token->Privileges[Index + 1],
561  MoveCount * sizeof(LUID_AND_ATTRIBUTES));
562  }
563 
564  /* Update privilege count */
565  Token->PrivilegeCount--;
566 }
567 
568 VOID
569 NTAPI
571 {
573 }
574 
575 NTSTATUS
576 NTAPI
578  PVOID Src)
579 {
581  return STATUS_NOT_IMPLEMENTED;
582 }
583 
584 NTSTATUS
585 NTAPI
588  _In_ PACCESS_TOKEN NewAccessToken,
589  _Out_ PACCESS_TOKEN* OldAccessToken)
590 {
591  PTOKEN OldToken;
592  PTOKEN NewToken = (PTOKEN)NewAccessToken;
593 
594  PAGED_CODE();
595 
596  if (NewToken->TokenType != TokenPrimary)
597  return STATUS_BAD_TOKEN_TYPE;
598 
599  if (NewToken->TokenInUse)
600  {
603 
604  /* Maybe we're trying to set the same token */
605  OldToken = PsReferencePrimaryToken(Process);
606  if (OldToken == NewToken)
607  {
608  /* So it's a nop. */
609  *OldAccessToken = OldToken;
610  return STATUS_SUCCESS;
611  }
612 
613  Status = SepCompareTokens(OldToken, NewToken, &IsEqual);
614  if (!NT_SUCCESS(Status))
615  {
616  PsDereferencePrimaryToken(OldToken);
617  *OldAccessToken = NULL;
618  return Status;
619  }
620 
621  if (!IsEqual)
622  {
623  PsDereferencePrimaryToken(OldToken);
624  *OldAccessToken = NULL;
626  }
627  /* Silently return STATUS_SUCCESS but do not set the new token,
628  * as it's already in use elsewhere. */
629  *OldAccessToken = OldToken;
630  return STATUS_SUCCESS;
631  }
632 
633  /* Lock the new token */
635 
636  /* Mark new token in use */
637  NewToken->TokenInUse = TRUE;
638 
639  /* Set the session ID for the new token */
640  NewToken->SessionId = MmGetSessionId(Process);
641 
642  /* Unlock the new token */
643  SepReleaseTokenLock(NewToken);
644 
645  /* Reference the new token */
646  ObReferenceObject(NewToken);
647 
648  /* Replace the old with the new */
649  OldToken = ObFastReplaceObject(&Process->Token, NewToken);
650 
651  /* Lock the old token */
653 
654  /* Mark the old token as free */
655  OldToken->TokenInUse = FALSE;
656 
657  /* Unlock the old token */
658  SepReleaseTokenLock(OldToken);
659 
660  *OldAccessToken = (PACCESS_TOKEN)OldToken;
661  return STATUS_SUCCESS;
662 }
663 
664 VOID
665 NTAPI
667 {
668  PTOKEN OldToken;
669 
670  /* Remove the Token */
671  OldToken = ObFastReplaceObject(&Process->Token, NULL);
672 
673  /* Mark the Old Token as free */
674  OldToken->TokenInUse = FALSE;
675 
676  /* Dereference the Token */
677  ObDereferenceObject(OldToken);
678 }
679 
680 static ULONG
683 {
684  ULONG i;
685  ULONG uLength;
686 
687  PAGED_CODE();
688 
689  uLength = Count * sizeof(SID_AND_ATTRIBUTES);
690  for (i = 0; i < Count; i++)
691  uLength += RtlLengthSid(Src[i].Sid);
692 
693  return uLength;
694 }
695 
696 
697 static NTSTATUS
699  _In_ PTOKEN Token,
701  _In_opt_ PSID DefaultOwner,
702  _Out_opt_ PULONG PrimaryGroupIndex,
703  _Out_opt_ PULONG DefaultOwnerIndex)
704 {
705  ULONG i;
706 
707  /* We should return at least a search result */
708  if (!PrimaryGroupIndex && !DefaultOwnerIndex)
710 
711  if (PrimaryGroupIndex)
712  {
713  /* Initialize with an invalid index */
714  // Token->PrimaryGroup = NULL;
715  *PrimaryGroupIndex = Token->UserAndGroupCount;
716  }
717 
718  if (DefaultOwnerIndex)
719  {
720  if (DefaultOwner)
721  {
722  /* An owner is specified: check whether this is actually the user */
723  if (RtlEqualSid(Token->UserAndGroups[0].Sid, DefaultOwner))
724  {
725  /*
726  * It's the user (first element in array): set it
727  * as the owner and stop the search for it.
728  */
729  *DefaultOwnerIndex = 0;
730  DefaultOwnerIndex = NULL;
731  }
732  else
733  {
734  /* An owner is specified: initialize with an invalid index */
735  *DefaultOwnerIndex = Token->UserAndGroupCount;
736  }
737  }
738  else
739  {
740  /*
741  * No owner specified: set the user (first element in array)
742  * as the owner and stop the search for it.
743  */
744  *DefaultOwnerIndex = 0;
745  DefaultOwnerIndex = NULL;
746  }
747  }
748 
749  /* Validate and set the primary group and default owner indices */
750  for (i = 0; i < Token->UserAndGroupCount; i++)
751  {
752  /* Stop the search if we have found what we searched for */
753  if (!PrimaryGroupIndex && !DefaultOwnerIndex)
754  break;
755 
756  if (DefaultOwnerIndex && DefaultOwner &&
757  RtlEqualSid(Token->UserAndGroups[i].Sid, DefaultOwner) &&
758  (Token->UserAndGroups[i].Attributes & SE_GROUP_OWNER))
759  {
760  /* Owner is found, stop the search for it */
761  *DefaultOwnerIndex = i;
762  DefaultOwnerIndex = NULL;
763  }
764 
765  if (PrimaryGroupIndex &&
766  RtlEqualSid(Token->UserAndGroups[i].Sid, PrimaryGroup))
767  {
768  /* Primary group is found, stop the search for it */
769  // Token->PrimaryGroup = Token->UserAndGroups[i].Sid;
770  *PrimaryGroupIndex = i;
771  PrimaryGroupIndex = NULL;
772  }
773  }
774 
775  if (DefaultOwnerIndex)
776  {
777  if (*DefaultOwnerIndex == Token->UserAndGroupCount)
778  return STATUS_INVALID_OWNER;
779  }
780 
781  if (PrimaryGroupIndex)
782  {
783  if (*PrimaryGroupIndex == Token->UserAndGroupCount)
784  // if (Token->PrimaryGroup == NULL)
786  }
787 
788  return STATUS_SUCCESS;
789 }
790 
791 
792 NTSTATUS
793 NTAPI
795  _In_ PTOKEN Token,
801  _Out_ PTOKEN* NewAccessToken)
802 {
804  PTOKEN AccessToken;
805  PVOID EndMem;
806  ULONG VariableLength;
807  ULONG TotalSize;
808 
809  PAGED_CODE();
810 
811  /* Compute how much size we need to allocate for the token */
812  VariableLength = Token->VariableLength;
813  TotalSize = FIELD_OFFSET(TOKEN, VariablePart) + VariableLength;
814 
818  PreviousMode,
819  NULL,
820  TotalSize,
821  0,
822  0,
823  (PVOID*)&AccessToken);
824  if (!NT_SUCCESS(Status))
825  {
826  DPRINT1("ObCreateObject() failed (Status 0x%lx)\n", Status);
827  return Status;
828  }
829 
830  /* Zero out the buffer and initialize the token */
831  RtlZeroMemory(AccessToken, TotalSize);
832 
833  ExAllocateLocallyUniqueId(&AccessToken->TokenId);
834 
835  AccessToken->TokenType = TokenType;
836  AccessToken->ImpersonationLevel = Level;
837 
838  /* Initialise the lock for the access token */
839  Status = SepCreateTokenLock(AccessToken);
840  if (!NT_SUCCESS(Status))
841  {
842  ObDereferenceObject(AccessToken);
843  return Status;
844  }
845 
846  /* Copy the immutable fields */
847  RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
848  &Token->TokenSource.SourceIdentifier);
849  RtlCopyMemory(AccessToken->TokenSource.SourceName,
850  Token->TokenSource.SourceName,
851  sizeof(Token->TokenSource.SourceName));
852 
853  AccessToken->AuthenticationId = Token->AuthenticationId;
854  AccessToken->ParentTokenId = Token->ParentTokenId;
855  AccessToken->ExpirationTime = Token->ExpirationTime;
856  AccessToken->OriginatingLogonSession = Token->OriginatingLogonSession;
857 
858  /* Lock the source token and copy the mutable fields */
860 
861  AccessToken->SessionId = Token->SessionId;
862  RtlCopyLuid(&AccessToken->ModifiedId, &Token->ModifiedId);
863 
864  AccessToken->TokenFlags = Token->TokenFlags & ~TOKEN_SESSION_NOT_REFERENCED;
865 
866  /* Copy and reference the logon session */
867  // RtlCopyLuid(&AccessToken->AuthenticationId, &Token->AuthenticationId);
868  Status = SepRmReferenceLogonSession(&AccessToken->AuthenticationId);
869  if (!NT_SUCCESS(Status))
870  {
871  /* No logon session could be found, bail out */
872  DPRINT1("SepRmReferenceLogonSession() failed (Status 0x%lx)\n", Status);
873  /* Set the flag for proper cleanup by the delete procedure */
874  AccessToken->TokenFlags |= TOKEN_SESSION_NOT_REFERENCED;
875  goto Quit;
876  }
877 
878  /* Assign the data that reside in the TOKEN's variable information area */
879  AccessToken->VariableLength = VariableLength;
880  EndMem = (PVOID)&AccessToken->VariablePart;
881 
882  /* Copy the privileges */
883  AccessToken->PrivilegeCount = 0;
884  AccessToken->Privileges = NULL;
885  if (Token->Privileges && (Token->PrivilegeCount > 0))
886  {
887  ULONG PrivilegesLength = Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
888  PrivilegesLength = ALIGN_UP_BY(PrivilegesLength, sizeof(PVOID));
889 
890  ASSERT(VariableLength >= PrivilegesLength);
891 
892  AccessToken->PrivilegeCount = Token->PrivilegeCount;
893  AccessToken->Privileges = EndMem;
894  EndMem = (PVOID)((ULONG_PTR)EndMem + PrivilegesLength);
895  VariableLength -= PrivilegesLength;
896 
897  RtlCopyMemory(AccessToken->Privileges,
898  Token->Privileges,
899  AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
900  }
901 
902  /* Copy the user and groups */
903  AccessToken->UserAndGroupCount = 0;
904  AccessToken->UserAndGroups = NULL;
905  if (Token->UserAndGroups && (Token->UserAndGroupCount > 0))
906  {
907  AccessToken->UserAndGroupCount = Token->UserAndGroupCount;
908  AccessToken->UserAndGroups = EndMem;
909  EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
910  VariableLength -= ((ULONG_PTR)EndMem - (ULONG_PTR)AccessToken->UserAndGroups);
911 
912  Status = RtlCopySidAndAttributesArray(AccessToken->UserAndGroupCount,
913  Token->UserAndGroups,
914  VariableLength,
915  AccessToken->UserAndGroups,
916  EndMem,
917  &EndMem,
918  &VariableLength);
919  if (!NT_SUCCESS(Status))
920  {
921  DPRINT1("RtlCopySidAndAttributesArray(UserAndGroups) failed (Status 0x%lx)\n", Status);
922  goto Quit;
923  }
924  }
925 
926 #if 1
927  {
928  ULONG PrimaryGroupIndex;
929 
930  /* Find the token primary group */
932  Token->PrimaryGroup,
933  NULL,
934  &PrimaryGroupIndex,
935  NULL);
936  if (!NT_SUCCESS(Status))
937  {
938  DPRINT1("SepFindPrimaryGroupAndDefaultOwner failed (Status 0x%lx)\n", Status);
939  goto Quit;
940  }
941  AccessToken->PrimaryGroup = AccessToken->UserAndGroups[PrimaryGroupIndex].Sid;
942  }
943 #else
944  AccessToken->PrimaryGroup = (PVOID)((ULONG_PTR)AccessToken + (ULONG_PTR)Token->PrimaryGroup - (ULONG_PTR)Token->UserAndGroups);
945 #endif
946  AccessToken->DefaultOwnerIndex = Token->DefaultOwnerIndex;
947 
948  /* Copy the restricted SIDs */
949  AccessToken->RestrictedSidCount = 0;
950  AccessToken->RestrictedSids = NULL;
951  if (Token->RestrictedSids && (Token->RestrictedSidCount > 0))
952  {
953  AccessToken->RestrictedSidCount = Token->RestrictedSidCount;
954  AccessToken->RestrictedSids = EndMem;
955  EndMem = &AccessToken->RestrictedSids[AccessToken->RestrictedSidCount];
956  VariableLength -= ((ULONG_PTR)EndMem - (ULONG_PTR)AccessToken->RestrictedSids);
957 
958  Status = RtlCopySidAndAttributesArray(AccessToken->RestrictedSidCount,
959  Token->RestrictedSids,
960  VariableLength,
961  AccessToken->RestrictedSids,
962  EndMem,
963  &EndMem,
964  &VariableLength);
965  if (!NT_SUCCESS(Status))
966  {
967  DPRINT1("RtlCopySidAndAttributesArray(RestrictedSids) failed (Status 0x%lx)\n", Status);
968  goto Quit;
969  }
970  }
971 
972 
973  //
974  // FIXME: Implement the "EffectiveOnly" option, that removes all
975  // the disabled parts (privileges and groups) of the token.
976  //
977 
978 
979  //
980  // NOTE: So far our dynamic area only contains
981  // the default dacl, so this makes the following
982  // code pretty simple. The day where it stores
983  // other data, the code will require adaptations.
984  //
985 
986  /* Now allocate the TOKEN's dynamic information area and set the data */
987  AccessToken->DynamicAvailable = 0; // Unused memory in the dynamic area.
988  AccessToken->DynamicPart = NULL;
989  if (Token->DynamicPart && Token->DefaultDacl)
990  {
991  AccessToken->DynamicPart = ExAllocatePoolWithTag(PagedPool,
992  Token->DefaultDacl->AclSize,
994  if (AccessToken->DynamicPart == NULL)
995  {
997  goto Quit;
998  }
999  EndMem = (PVOID)AccessToken->DynamicPart;
1000 
1001  AccessToken->DefaultDacl = EndMem;
1002 
1003  RtlCopyMemory(AccessToken->DefaultDacl,
1004  Token->DefaultDacl,
1005  Token->DefaultDacl->AclSize);
1006  }
1007 
1008  /* Unlock the source token */
1010 
1011  /* Return the token */
1012  *NewAccessToken = AccessToken;
1014 
1015 Quit:
1016  if (!NT_SUCCESS(Status))
1017  {
1018  /* Unlock the source token */
1020 
1021  /* Dereference the token, the delete procedure will clean it up */
1022  ObDereferenceObject(AccessToken);
1023  }
1024 
1025  return Status;
1026 }
1027 
1028 NTSTATUS
1029 NTAPI
1031  OUT PTOKEN *Token,
1032  IN BOOLEAN InUse,
1033  IN ULONG SessionId)
1034 {
1035  PTOKEN NewToken;
1037  NTSTATUS Status;
1038 
1039  /* Initialize the attributes and duplicate it */
1041  Status = SepDuplicateToken(ParentToken,
1043  FALSE,
1044  TokenPrimary,
1045  ParentToken->ImpersonationLevel,
1046  KernelMode,
1047  &NewToken);
1048  if (NT_SUCCESS(Status))
1049  {
1050  /* Insert it */
1051  Status = ObInsertObject(NewToken,
1052  NULL,
1053  0,
1054  0,
1055  NULL,
1056  NULL);
1057  if (NT_SUCCESS(Status))
1058  {
1059  /* Set the session ID */
1060  NewToken->SessionId = SessionId;
1061  NewToken->TokenInUse = InUse;
1062 
1063  /* Return the token */
1064  *Token = NewToken;
1065  }
1066  }
1067 
1068  /* Return status */
1069  return Status;
1070 }
1071 
1072 NTSTATUS
1073 NTAPI
1076 {
1077  PTOKEN ProcessToken;
1078  LUID ProcessTokenId, CallerParentId;
1079 
1080  /* Assume failure */
1081  *IsChild = FALSE;
1082 
1083  /* Reference the process token */
1084  ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess());
1085  if (!ProcessToken)
1086  return STATUS_UNSUCCESSFUL;
1087 
1088  /* Get its token ID */
1089  ProcessTokenId = ProcessToken->TokenId;
1090 
1091  /* Dereference the token */
1093 
1094  /* Get our parent token ID */
1095  CallerParentId = Token->ParentTokenId;
1096 
1097  /* Compare the token IDs */
1098  if (RtlEqualLuid(&CallerParentId, &ProcessTokenId))
1099  *IsChild = TRUE;
1100 
1101  /* Return success */
1102  return STATUS_SUCCESS;
1103 }
1104 
1105 NTSTATUS
1106 NTAPI
1108  OUT PBOOLEAN IsSibling)
1109 {
1110  PTOKEN ProcessToken;
1111  LUID ProcessParentId, ProcessAuthId;
1112  LUID CallerParentId, CallerAuthId;
1113 
1114  /* Assume failure */
1115  *IsSibling = FALSE;
1116 
1117  /* Reference the process token */
1118  ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess());
1119  if (!ProcessToken)
1120  return STATUS_UNSUCCESSFUL;
1121 
1122  /* Get its parent and authentication IDs */
1123  ProcessParentId = ProcessToken->ParentTokenId;
1124  ProcessAuthId = ProcessToken->AuthenticationId;
1125 
1126  /* Dereference the token */
1128 
1129  /* Get our parent and authentication IDs */
1130  CallerParentId = Token->ParentTokenId;
1131  CallerAuthId = Token->AuthenticationId;
1132 
1133  /* Compare the token IDs */
1134  if (RtlEqualLuid(&CallerParentId, &ProcessParentId) &&
1135  RtlEqualLuid(&CallerAuthId, &ProcessAuthId))
1136  {
1137  *IsSibling = TRUE;
1138  }
1139 
1140  /* Return success */
1141  return STATUS_SUCCESS;
1142 }
1143 
1144 NTSTATUS
1145 NTAPI
1149  OUT PACCESS_TOKEN* NewToken)
1150 {
1151  NTSTATUS Status;
1153 
1154  PAGED_CODE();
1155 
1157  NULL,
1158  0,
1159  NULL,
1160  NULL);
1161 
1164  FALSE,
1166  Level,
1167  PreviousMode,
1168  (PTOKEN*)NewToken);
1169 
1170  return Status;
1171 }
1172 
1173 VOID
1174 NTAPI
1176 {
1177  PTOKEN AccessToken = (PTOKEN)ObjectBody;
1178 
1179  DPRINT("SepDeleteToken()\n");
1180 
1181  /* Dereference the logon session */
1182  if ((AccessToken->TokenFlags & TOKEN_SESSION_NOT_REFERENCED) == 0)
1184 
1185  /* Delete the token lock */
1186  if (AccessToken->TokenLock)
1187  SepDeleteTokenLock(AccessToken);
1188 
1189  /* Delete the dynamic information area */
1190  if (AccessToken->DynamicPart)
1192 }
1193 
1194 
1195 CODE_SEG("INIT")
1196 VOID
1197 NTAPI
1199 {
1201  OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
1202 
1203  DPRINT("Creating Token Object Type\n");
1204 
1205  /* Initialize the Token type */
1206  RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
1207  RtlInitUnicodeString(&Name, L"Token");
1208  ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
1209  ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
1210  ObjectTypeInitializer.SecurityRequired = TRUE;
1211  ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(TOKEN);
1212  ObjectTypeInitializer.GenericMapping = SepTokenMapping;
1213  ObjectTypeInitializer.PoolType = PagedPool;
1214  ObjectTypeInitializer.ValidAccessMask = TOKEN_ALL_ACCESS;
1215  ObjectTypeInitializer.UseDefaultObject = TRUE;
1216  ObjectTypeInitializer.DeleteProcedure = SepDeleteToken;
1217  ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &SeTokenObjectType);
1218 }
1219 
1220 VOID
1221 NTAPI
1223  IN PTOKEN Token)
1224 {
1225  PAGED_CODE();
1226 
1227  /* Sanity checks */
1228  ASSERT(Token->TokenType == TokenPrimary);
1229  ASSERT(!Token->TokenInUse);
1230 
1231  /* Clean any previous token */
1232  if (Process->Token.Object) SeDeassignPrimaryToken(Process);
1233 
1234  /* Set the new token */
1236  Token->TokenInUse = TRUE;
1238 }
1239 
1240 NTSTATUS
1241 NTAPI
1249  _In_ PLUID AuthenticationId,
1250  _In_ PLARGE_INTEGER ExpirationTime,
1252  _In_ ULONG GroupCount,
1254  _In_ ULONG GroupsLength,
1255  _In_ ULONG PrivilegeCount,
1259  _In_opt_ PACL DefaultDacl,
1261  _In_ BOOLEAN SystemToken)
1262 {
1263  NTSTATUS Status;
1264  PTOKEN AccessToken;
1265  ULONG TokenFlags = 0;
1266  ULONG PrimaryGroupIndex, DefaultOwnerIndex;
1267  LUID TokenId;
1268  LUID ModifiedId;
1269  PVOID EndMem;
1270  ULONG PrivilegesLength;
1271  ULONG UserGroupsLength;
1272  ULONG VariableLength;
1273  ULONG TotalSize;
1274  ULONG i;
1275 
1276  PAGED_CODE();
1277 
1278  /* Loop all groups */
1279  for (i = 0; i < GroupCount; i++)
1280  {
1281  /* Check for mandatory groups */
1283  {
1284  /* Force them to be enabled */
1286  }
1287 
1288  /* Check of the group is an admin group */
1290  {
1291  /* Remember this so we can optimize queries later */
1292  TokenFlags |= TOKEN_HAS_ADMIN_GROUP;
1293  }
1294  }
1295 
1296  /* Allocate unique IDs for the token */
1297  ExAllocateLocallyUniqueId(&TokenId);
1298  ExAllocateLocallyUniqueId(&ModifiedId);
1299 
1300  /* Compute how much size we need to allocate for the token */
1301 
1302  /* Privileges size */
1303  PrivilegesLength = PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
1304  PrivilegesLength = ALIGN_UP_BY(PrivilegesLength, sizeof(PVOID));
1305 
1306  /* User and groups size */
1307  UserGroupsLength = (1 + GroupCount) * sizeof(SID_AND_ATTRIBUTES);
1308  UserGroupsLength += RtlLengthSid(User->Sid);
1309  for (i = 0; i < GroupCount; i++)
1310  {
1311  UserGroupsLength += RtlLengthSid(Groups[i].Sid);
1312  }
1313  UserGroupsLength = ALIGN_UP_BY(UserGroupsLength, sizeof(PVOID));
1314 
1315  /* Add the additional groups array length */
1316  UserGroupsLength += ALIGN_UP_BY(GroupsLength, sizeof(PVOID));
1317 
1318  VariableLength = PrivilegesLength + UserGroupsLength;
1319  TotalSize = FIELD_OFFSET(TOKEN, VariablePart) + VariableLength;
1320 
1324  PreviousMode,
1325  NULL,
1326  TotalSize,
1327  0,
1328  0,
1329  (PVOID*)&AccessToken);
1330  if (!NT_SUCCESS(Status))
1331  {
1332  DPRINT1("ObCreateObject() failed (Status 0x%lx)\n", Status);
1333  return Status;
1334  }
1335 
1336  /* Zero out the buffer and initialize the token */
1337  RtlZeroMemory(AccessToken, TotalSize);
1338 
1339  RtlCopyLuid(&AccessToken->TokenId, &TokenId);
1340 
1341  AccessToken->TokenType = TokenType;
1342  AccessToken->ImpersonationLevel = ImpersonationLevel;
1343 
1344  /* Initialise the lock for the access token */
1345  Status = SepCreateTokenLock(AccessToken);
1346  if (!NT_SUCCESS(Status))
1347  goto Quit;
1348 
1349  RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
1350  &TokenSource->SourceIdentifier);
1351  RtlCopyMemory(AccessToken->TokenSource.SourceName,
1352  TokenSource->SourceName,
1353  sizeof(TokenSource->SourceName));
1354 
1355  AccessToken->ExpirationTime = *ExpirationTime;
1356  RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
1357 
1358  AccessToken->TokenFlags = TokenFlags & ~TOKEN_SESSION_NOT_REFERENCED;
1359 
1360  /* Copy and reference the logon session */
1361  RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
1362  Status = SepRmReferenceLogonSession(&AccessToken->AuthenticationId);
1363  if (!NT_SUCCESS(Status))
1364  {
1365  /* No logon session could be found, bail out */
1366  DPRINT1("SepRmReferenceLogonSession() failed (Status 0x%lx)\n", Status);
1367  /* Set the flag for proper cleanup by the delete procedure */
1368  AccessToken->TokenFlags |= TOKEN_SESSION_NOT_REFERENCED;
1369  goto Quit;
1370  }
1371 
1372  /* Assign the data that reside in the TOKEN's variable information area */
1373  AccessToken->VariableLength = VariableLength;
1374  EndMem = (PVOID)&AccessToken->VariablePart;
1375 
1376  /* Copy the privileges */
1377  AccessToken->PrivilegeCount = PrivilegeCount;
1378  AccessToken->Privileges = NULL;
1379  if (PrivilegeCount > 0)
1380  {
1381  AccessToken->Privileges = EndMem;
1382  EndMem = (PVOID)((ULONG_PTR)EndMem + PrivilegesLength);
1383  VariableLength -= PrivilegesLength;
1384 
1385  if (PreviousMode != KernelMode)
1386  {
1387  _SEH2_TRY
1388  {
1389  RtlCopyMemory(AccessToken->Privileges,
1390  Privileges,
1391  PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
1392  }
1394  {
1396  }
1397  _SEH2_END;
1398  }
1399  else
1400  {
1401  RtlCopyMemory(AccessToken->Privileges,
1402  Privileges,
1403  PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
1404  }
1405 
1406  if (!NT_SUCCESS(Status))
1407  goto Quit;
1408  }
1409 
1410  /* Update the privilege flags */
1411  SepUpdatePrivilegeFlagsToken(AccessToken);
1412 
1413  /* Copy the user and groups */
1414  AccessToken->UserAndGroupCount = 1 + GroupCount;
1415  AccessToken->UserAndGroups = EndMem;
1416  EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
1417  VariableLength -= ((ULONG_PTR)EndMem - (ULONG_PTR)AccessToken->UserAndGroups);
1418 
1420  User,
1421  VariableLength,
1422  &AccessToken->UserAndGroups[0],
1423  EndMem,
1424  &EndMem,
1425  &VariableLength);
1426  if (!NT_SUCCESS(Status))
1427  goto Quit;
1428 
1429  Status = RtlCopySidAndAttributesArray(GroupCount,
1430  Groups,
1431  VariableLength,
1432  &AccessToken->UserAndGroups[1],
1433  EndMem,
1434  &EndMem,
1435  &VariableLength);
1436  if (!NT_SUCCESS(Status))
1437  goto Quit;
1438 
1439  /* Find the token primary group and default owner */
1441  PrimaryGroup,
1442  Owner,
1443  &PrimaryGroupIndex,
1444  &DefaultOwnerIndex);
1445  if (!NT_SUCCESS(Status))
1446  {
1447  DPRINT1("SepFindPrimaryGroupAndDefaultOwner failed (Status 0x%lx)\n", Status);
1448  goto Quit;
1449  }
1450 
1451  AccessToken->PrimaryGroup = AccessToken->UserAndGroups[PrimaryGroupIndex].Sid;
1452  AccessToken->DefaultOwnerIndex = DefaultOwnerIndex;
1453 
1454  /* Now allocate the TOKEN's dynamic information area and set the data */
1455  AccessToken->DynamicAvailable = 0; // Unused memory in the dynamic area.
1456  AccessToken->DynamicPart = NULL;
1457  if (DefaultDacl != NULL)
1458  {
1459  AccessToken->DynamicPart = ExAllocatePoolWithTag(PagedPool,
1460  DefaultDacl->AclSize,
1462  if (AccessToken->DynamicPart == NULL)
1463  {
1465  goto Quit;
1466  }
1467  EndMem = (PVOID)AccessToken->DynamicPart;
1468 
1469  AccessToken->DefaultDacl = EndMem;
1470 
1471  RtlCopyMemory(AccessToken->DefaultDacl,
1472  DefaultDacl,
1473  DefaultDacl->AclSize);
1474  }
1475 
1476  /* Insert the token only if it's not the system token, otherwise return it directly */
1477  if (!SystemToken)
1478  {
1479  Status = ObInsertObject(AccessToken,
1480  NULL,
1481  DesiredAccess,
1482  0,
1483  NULL,
1484  TokenHandle);
1485  if (!NT_SUCCESS(Status))
1486  {
1487  DPRINT1("ObInsertObject() failed (Status 0x%lx)\n", Status);
1488  }
1489  }
1490  else
1491  {
1492  /* Return pointer instead of handle */
1493  *TokenHandle = (HANDLE)AccessToken;
1494  }
1495 
1496 Quit:
1497  if (!NT_SUCCESS(Status))
1498  {
1499  /* Dereference the token, the delete procedure will clean it up */
1500  ObDereferenceObject(AccessToken);
1501  }
1502 
1503  return Status;
1504 }
1505 
1514 CODE_SEG("INIT")
1515 PTOKEN
1516 NTAPI
1518 {
1520  ULONG GroupAttributes, OwnerAttributes;
1522  LARGE_INTEGER Expiration;
1523  SID_AND_ATTRIBUTES UserSid;
1524  ULONG GroupsLength;
1527  PSID Owner;
1528  ULONG i;
1529  PTOKEN Token;
1530  NTSTATUS Status;
1531 
1532  /* Don't ever expire */
1533  Expiration.QuadPart = -1;
1534 
1535  /* All groups mandatory and enabled */
1538 
1539  /* User is Local System */
1540  UserSid.Sid = SeLocalSystemSid;
1541  UserSid.Attributes = 0;
1542 
1543  /* Primary group is Local System */
1545 
1546  /* Owner is Administrators */
1548 
1549  /* Groups are Administrators, World, and Authenticated Users */
1550  Groups[0].Sid = SeAliasAdminsSid;
1551  Groups[0].Attributes = OwnerAttributes;
1552  Groups[1].Sid = SeWorldSid;
1553  Groups[1].Attributes = GroupAttributes;
1555  Groups[2].Attributes = GroupAttributes;
1556  GroupsLength = sizeof(SID_AND_ATTRIBUTES) +
1557  SeLengthSid(Groups[0].Sid) +
1558  SeLengthSid(Groups[1].Sid) +
1559  SeLengthSid(Groups[2].Sid);
1560  ASSERT(GroupsLength <= sizeof(Groups));
1561 
1562  /* Setup the privileges */
1563  i = 0;
1565  Privileges[i++].Luid = SeTcbPrivilege;
1566 
1567  Privileges[i].Attributes = 0;
1569 
1570  Privileges[i].Attributes = 0;
1572 
1575 
1578 
1579  Privileges[i].Attributes = 0;
1581 
1582  Privileges[i].Attributes = 0;
1584 
1587 
1590 
1592  Privileges[i++].Luid = SeDebugPrivilege;
1593 
1595  Privileges[i++].Luid = SeAuditPrivilege;
1596 
1597  Privileges[i].Attributes = 0;
1598  Privileges[i++].Luid = SeSecurityPrivilege;
1599 
1600  Privileges[i].Attributes = 0;
1602 
1605 
1606  Privileges[i].Attributes = 0;
1607  Privileges[i++].Luid = SeBackupPrivilege;
1608 
1609  Privileges[i].Attributes = 0;
1610  Privileges[i++].Luid = SeRestorePrivilege;
1611 
1612  Privileges[i].Attributes = 0;
1613  Privileges[i++].Luid = SeShutdownPrivilege;
1614 
1615  Privileges[i].Attributes = 0;
1617 
1620 
1621  Privileges[i].Attributes = 0;
1623  ASSERT(i == 20);
1624 
1625  /* Setup the object attributes */
1628 
1629  /* Create the token */
1631  KernelMode,
1632  0,
1634  TokenPrimary,
1637  &Expiration,
1638  &UserSid,
1639  3,
1640  Groups,
1641  GroupsLength,
1642  20,
1643  Privileges,
1644  Owner,
1645  PrimaryGroup,
1648  TRUE);
1650 
1651  /* Return the token */
1652  return Token;
1653 }
1654 
1665 CODE_SEG("INIT")
1666 PTOKEN
1668 {
1669  SID_AND_ATTRIBUTES Groups[32], UserSid;
1671  PTOKEN Token;
1672  ULONG GroupsLength;
1673  LARGE_INTEGER Expiration;
1675  NTSTATUS Status;
1676 
1677  /* The token never expires */
1678  Expiration.QuadPart = -1;
1679 
1680  /* The user is the anonymous logon */
1681  UserSid.Sid = SeAnonymousLogonSid;
1682  UserSid.Attributes = 0;
1683 
1684  /* The primary group is also the anonymous logon */
1686 
1687  /* The only group for the token is the World */
1688  Groups[0].Sid = SeWorldSid;
1690  GroupsLength = sizeof(SID_AND_ATTRIBUTES) +
1691  SeLengthSid(Groups[0].Sid);
1692  ASSERT(GroupsLength <= sizeof(Groups));
1693 
1694  /* Initialise the object attributes for the token */
1697 
1698  /* Create token */
1700  KernelMode,
1701  0,
1703  TokenPrimary,
1706  &Expiration,
1707  &UserSid,
1708  1,
1709  Groups,
1710  GroupsLength,
1711  0,
1712  NULL,
1713  NULL,
1714  PrimaryGroup,
1717  TRUE);
1719 
1720  /* Return the anonymous logon token */
1721  return Token;
1722 }
1723 
1733 CODE_SEG("INIT")
1734 PTOKEN
1736 {
1737  SID_AND_ATTRIBUTES UserSid;
1739  PTOKEN Token;
1740  LARGE_INTEGER Expiration;
1742  NTSTATUS Status;
1743 
1744  /* The token never expires */
1745  Expiration.QuadPart = -1;
1746 
1747  /* The user is the anonymous logon */
1748  UserSid.Sid = SeAnonymousLogonSid;
1749  UserSid.Attributes = 0;
1750 
1751  /* The primary group is also the anonymous logon */
1753 
1754  /* Initialise the object attributes for the token */
1757 
1758  /* Create token */
1760  KernelMode,
1761  0,
1763  TokenPrimary,
1766  &Expiration,
1767  &UserSid,
1768  0,
1769  NULL,
1770  0,
1771  0,
1772  NULL,
1773  NULL,
1774  PrimaryGroup,
1777  TRUE);
1779 
1780  /* Return the anonymous (not including everyone) logon token */
1781  return Token;
1782 }
1783 
1784 /* PUBLIC FUNCTIONS ***********************************************************/
1785 
1786 /*
1787  * @unimplemented
1788  */
1789 NTSTATUS
1790 NTAPI
1792  IN ULONG Flags,
1793  IN PTOKEN_GROUPS SidsToDisable OPTIONAL,
1794  IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL,
1795  IN PTOKEN_GROUPS RestrictedSids OPTIONAL,
1796  OUT PACCESS_TOKEN * FilteredToken)
1797 {
1798  UNIMPLEMENTED;
1799  return STATUS_NOT_IMPLEMENTED;
1800 }
1801 
1827 NTSTATUS
1828 NTAPI
1830  _In_ PACCESS_TOKEN AccessToken,
1832  _Outptr_result_buffer_(_Inexpressible_(token-dependent)) PVOID *TokenInformation)
1833 {
1834  NTSTATUS Status;
1835  PTOKEN Token = (PTOKEN)AccessToken;
1837  union
1838  {
1839  PSID PSid;
1840  ULONG Ulong;
1841  } Unused;
1842 
1843  PAGED_CODE();
1844 
1845  /* Lock the token */
1847 
1848  switch (TokenInformationClass)
1849  {
1850  case TokenUser:
1851  {
1852  PTOKEN_USER tu;
1853 
1854  DPRINT("SeQueryInformationToken(TokenUser)\n");
1855  RequiredLength = sizeof(TOKEN_USER) +
1856  RtlLengthSid(Token->UserAndGroups[0].Sid);
1857 
1858  /* Allocate the output buffer */
1860  if (tu == NULL)
1861  {
1863  break;
1864  }
1865 
1867  &Token->UserAndGroups[0],
1868  RequiredLength - sizeof(TOKEN_USER),
1869  &tu->User,
1870  (PSID)(tu + 1),
1871  &Unused.PSid,
1872  &Unused.Ulong);
1873 
1874  /* Return the structure */
1875  *TokenInformation = tu;
1877  break;
1878  }
1879 
1880  case TokenGroups:
1881  {
1882  PTOKEN_GROUPS tg;
1883  ULONG SidLen;
1884  PSID Sid;
1885 
1886  DPRINT("SeQueryInformationToken(TokenGroups)\n");
1887  RequiredLength = sizeof(tg->GroupCount) +
1888  RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]);
1889 
1890  SidLen = RequiredLength - sizeof(tg->GroupCount) -
1891  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES));
1892 
1893  /* Allocate the output buffer */
1895  if (tg == NULL)
1896  {
1898  break;
1899  }
1900 
1901  Sid = (PSID)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
1902  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)));
1903 
1904  tg->GroupCount = Token->UserAndGroupCount - 1;
1905  Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
1906  &Token->UserAndGroups[1],
1907  SidLen,
1908  &tg->Groups[0],
1909  Sid,
1910  &Unused.PSid,
1911  &Unused.Ulong);
1912 
1913  /* Return the structure */
1914  *TokenInformation = tg;
1916  break;
1917  }
1918 
1919  case TokenPrivileges:
1920  {
1922 
1923  DPRINT("SeQueryInformationToken(TokenPrivileges)\n");
1924  RequiredLength = sizeof(tp->PrivilegeCount) +
1925  (Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
1926 
1927  /* Allocate the output buffer */
1929  if (tp == NULL)
1930  {
1932  break;
1933  }
1934 
1935  tp->PrivilegeCount = Token->PrivilegeCount;
1936  RtlCopyLuidAndAttributesArray(Token->PrivilegeCount,
1937  Token->Privileges,
1938  &tp->Privileges[0]);
1939 
1940  /* Return the structure */
1941  *TokenInformation = tp;
1943  break;
1944  }
1945 
1946  case TokenOwner:
1947  {
1948  PTOKEN_OWNER to;
1949  ULONG SidLen;
1950 
1951  DPRINT("SeQueryInformationToken(TokenOwner)\n");
1952  SidLen = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
1953  RequiredLength = sizeof(TOKEN_OWNER) + SidLen;
1954 
1955  /* Allocate the output buffer */
1957  if (to == NULL)
1958  {
1960  break;
1961  }
1962 
1963  to->Owner = (PSID)(to + 1);
1964  Status = RtlCopySid(SidLen,
1965  to->Owner,
1966  Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
1967 
1968  /* Return the structure */
1969  *TokenInformation = to;
1971  break;
1972  }
1973 
1974  case TokenPrimaryGroup:
1975  {
1977  ULONG SidLen;
1978 
1979  DPRINT("SeQueryInformationToken(TokenPrimaryGroup)\n");
1980  SidLen = RtlLengthSid(Token->PrimaryGroup);
1981  RequiredLength = sizeof(TOKEN_PRIMARY_GROUP) + SidLen;
1982 
1983  /* Allocate the output buffer */
1985  if (tpg == NULL)
1986  {
1988  break;
1989  }
1990 
1991  tpg->PrimaryGroup = (PSID)(tpg + 1);
1992  Status = RtlCopySid(SidLen,
1993  tpg->PrimaryGroup,
1994  Token->PrimaryGroup);
1995 
1996  /* Return the structure */
1997  *TokenInformation = tpg;
1999  break;
2000  }
2001 
2002  case TokenDefaultDacl:
2003  {
2004  PTOKEN_DEFAULT_DACL tdd;
2005 
2006  DPRINT("SeQueryInformationToken(TokenDefaultDacl)\n");
2008 
2009  if (Token->DefaultDacl != NULL)
2010  RequiredLength += Token->DefaultDacl->AclSize;
2011 
2012  /* Allocate the output buffer */
2014  if (tdd == NULL)
2015  {
2017  break;
2018  }
2019 
2020  if (Token->DefaultDacl != NULL)
2021  {
2022  tdd->DefaultDacl = (PACL)(tdd + 1);
2024  Token->DefaultDacl,
2025  Token->DefaultDacl->AclSize);
2026  }
2027  else
2028  {
2029  tdd->DefaultDacl = NULL;
2030  }
2031 
2032  /* Return the structure */
2033  *TokenInformation = tdd;
2035  break;
2036  }
2037 
2038  case TokenSource:
2039  {
2040  PTOKEN_SOURCE ts;
2041 
2042  DPRINT("SeQueryInformationToken(TokenSource)\n");
2043  RequiredLength = sizeof(TOKEN_SOURCE);
2044 
2045  /* Allocate the output buffer */
2047  if (ts == NULL)
2048  {
2050  break;
2051  }
2052 
2053  *ts = Token->TokenSource;
2054 
2055  /* Return the structure */
2056  *TokenInformation = ts;
2058  break;
2059  }
2060 
2061  case TokenType:
2062  {
2063  PTOKEN_TYPE tt;
2064 
2065  DPRINT("SeQueryInformationToken(TokenType)\n");
2066  RequiredLength = sizeof(TOKEN_TYPE);
2067 
2068  /* Allocate the output buffer */
2070  if (tt == NULL)
2071  {
2073  break;
2074  }
2075 
2076  *tt = Token->TokenType;
2077 
2078  /* Return the structure */
2079  *TokenInformation = tt;
2081  break;
2082  }
2083 
2085  {
2087 
2088  DPRINT("SeQueryInformationToken(TokenImpersonationLevel)\n");
2090 
2091  /* Fail if the token is not an impersonation token */
2092  if (Token->TokenType != TokenImpersonation)
2093  {
2095  break;
2096  }
2097 
2098  /* Allocate the output buffer */
2100  if (sil == NULL)
2101  {
2103  break;
2104  }
2105 
2106  *sil = Token->ImpersonationLevel;
2107 
2108  /* Return the structure */
2109  *TokenInformation = sil;
2111  break;
2112  }
2113 
2114  case TokenStatistics:
2115  {
2116  PTOKEN_STATISTICS ts;
2117 
2118  DPRINT("SeQueryInformationToken(TokenStatistics)\n");
2119  RequiredLength = sizeof(TOKEN_STATISTICS);
2120 
2121  /* Allocate the output buffer */
2123  if (ts == NULL)
2124  {
2126  break;
2127  }
2128 
2129  ts->TokenId = Token->TokenId;
2130  ts->AuthenticationId = Token->AuthenticationId;
2131  ts->ExpirationTime = Token->ExpirationTime;
2132  ts->TokenType = Token->TokenType;
2133  ts->ImpersonationLevel = Token->ImpersonationLevel;
2134  ts->DynamicCharged = Token->DynamicCharged;
2135  ts->DynamicAvailable = Token->DynamicAvailable;
2136  ts->GroupCount = Token->UserAndGroupCount - 1;
2137  ts->PrivilegeCount = Token->PrivilegeCount;
2138  ts->ModifiedId = Token->ModifiedId;
2139 
2140  /* Return the structure */
2141  *TokenInformation = ts;
2143  break;
2144  }
2145 
2146  case TokenSessionId:
2147  {
2148  DPRINT("SeQueryInformationToken(TokenSessionId)\n");
2149  Status = SeQuerySessionIdToken(Token, (PULONG)TokenInformation);
2150  break;
2151  }
2152 
2153  default:
2154  DPRINT1("SeQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
2156  break;
2157  }
2158 
2159  /* Release the lock of the token */
2161 
2162  return Status;
2163 }
2164 
2165 /*
2166  * @implemented
2167  */
2168 NTSTATUS
2169 NTAPI
2171  IN PULONG pSessionId)
2172 {
2173  PAGED_CODE();
2174 
2175  /* Lock the token */
2177 
2178  *pSessionId = ((PTOKEN)Token)->SessionId;
2179 
2180  /* Unlock the token */
2182 
2183  return STATUS_SUCCESS;
2184 }
2185 
2186 /*
2187  * @implemented
2188  */
2189 NTSTATUS
2190 NTAPI
2192  OUT PLUID LogonId)
2193 {
2194  PAGED_CODE();
2195 
2196  *LogonId = ((PTOKEN)Token)->AuthenticationId;
2197 
2198  return STATUS_SUCCESS;
2199 }
2200 
2201 
2202 /*
2203  * @implemented
2204  */
2206 NTAPI
2208 {
2209  PAGED_CODE();
2210 
2211  return ((PTOKEN)Token)->ImpersonationLevel;
2212 }
2213 
2214 
2215 /*
2216  * @implemented
2217  */
2220 {
2221  PAGED_CODE();
2222 
2223  return ((PTOKEN)Token)->TokenType;
2224 }
2225 
2226 
2227 /*
2228  * @implemented
2229  */
2230 BOOLEAN
2231 NTAPI
2233 {
2234  PAGED_CODE();
2235 
2236  // NOTE: Win7+ instead really checks the list of groups in the token
2237  // (since TOKEN_HAS_ADMIN_GROUP == TOKEN_WRITE_RESTRICTED ...)
2238  return (((PTOKEN)Token)->TokenFlags & TOKEN_HAS_ADMIN_GROUP) != 0;
2239 }
2240 
2241 /*
2242  * @implemented
2243  */
2244 BOOLEAN
2245 NTAPI
2247 {
2248  PAGED_CODE();
2249 
2250  return (((PTOKEN)Token)->TokenFlags & TOKEN_IS_RESTRICTED) != 0;
2251 }
2252 
2253 /*
2254  * @implemented
2255  * @note First introduced in NT 5.1 SP2 x86 (5.1.2600.2622), absent in NT 5.2,
2256  * then finally re-introduced in Vista+.
2257  */
2258 BOOLEAN
2259 NTAPI
2261 {
2262  PAGED_CODE();
2263 
2264  // NOTE: NT 5.1 SP2 x86 checks the SE_BACKUP_PRIVILEGES_CHECKED flag
2265  // while Vista+ checks the TOKEN_WRITE_RESTRICTED flag as one expects.
2266  return (((PTOKEN)Token)->TokenFlags & SE_BACKUP_PRIVILEGES_CHECKED) != 0;
2267 }
2268 
2288 BOOLEAN
2289 NTAPI
2291  _In_ PTOKEN ProcessToken,
2292  _In_ PTOKEN TokenToImpersonate,
2294 {
2295  BOOLEAN CanImpersonate;
2296  PAGED_CODE();
2297 
2298  /*
2299  * SecurityAnonymous and SecurityIdentification levels do not
2300  * allow impersonation. If we get such levels from the call
2301  * then something's seriously wrong.
2302  */
2305 
2306  /* Time to lock our tokens */
2307  SepAcquireTokenLockShared(ProcessToken);
2308  SepAcquireTokenLockShared(TokenToImpersonate);
2309 
2310  /* What kind of authentication ID does the token have? */
2311  if (RtlEqualLuid(&TokenToImpersonate->AuthenticationId,
2313  {
2314  /*
2315  * OK, it looks like the token has an anonymous
2316  * authentication. Is that token created by the system?
2317  */
2318  if (TokenToImpersonate->TokenSource.SourceName != SeSystemTokenSource.SourceName &&
2319  !RtlEqualLuid(&TokenToImpersonate->TokenSource.SourceIdentifier, &SeSystemTokenSource.SourceIdentifier))
2320  {
2321  /* It isn't, we can't impersonate regular tokens */
2322  DPRINT("SeTokenCanImpersonate(): Token has an anonymous authentication ID, can't impersonate!\n");
2323  CanImpersonate = FALSE;
2324  goto Quit;
2325  }
2326  }
2327 
2328  /* Are the SID values from both tokens equal? */
2329  if (!RtlEqualSid(ProcessToken->UserAndGroups->Sid,
2330  TokenToImpersonate->UserAndGroups->Sid))
2331  {
2332  /* They aren't, bail out */
2333  DPRINT("SeTokenCanImpersonate(): Tokens SIDs are not equal!\n");
2334  CanImpersonate = FALSE;
2335  goto Quit;
2336  }
2337 
2338  /*
2339  * Make sure the tokens aren't diverged in terms of
2340  * restrictions, that is, one token is restricted
2341  * but the other one isn't.
2342  */
2343  if (SeTokenIsRestricted(ProcessToken) !=
2344  SeTokenIsRestricted(TokenToImpersonate))
2345  {
2346  /*
2347  * One token is restricted so we cannot
2348  * continue further at this point, bail out.
2349  */
2350  DPRINT("SeTokenCanImpersonate(): One token is restricted, can't continue!\n");
2351  CanImpersonate = FALSE;
2352  goto Quit;
2353  }
2354 
2355  /* If we've reached that far then we can impersonate! */
2356  DPRINT("SeTokenCanImpersonate(): We can impersonate.\n");
2357  CanImpersonate = TRUE;
2358 
2359 Quit:
2360  /* We're done, unlock the tokens now */
2361  SepReleaseTokenLock(ProcessToken);
2362  SepReleaseTokenLock(TokenToImpersonate);
2363 
2364  return CanImpersonate;
2365 }
2366 
2367 /* SYSTEM CALLS ***************************************************************/
2368 
2369 /*
2370  * @implemented
2371  */
2374 NTSTATUS
2375 NTAPI
2380  PVOID TokenInformation,
2383 {
2384  NTSTATUS Status;
2386  PTOKEN Token;
2388  union
2389  {
2390  PSID PSid;
2391  ULONG Ulong;
2392  } Unused;
2393 
2394  PAGED_CODE();
2395 
2397 
2398  /* Check buffers and class validity */
2402  TokenInformation,
2404  ReturnLength,
2405  NULL,
2406  PreviousMode);
2407  if (!NT_SUCCESS(Status))
2408  {
2409  DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status);
2410  return Status;
2411  }
2412 
2416  PreviousMode,
2417  (PVOID*)&Token,
2418  NULL);
2419  if (NT_SUCCESS(Status))
2420  {
2421  /* Lock the token */
2423 
2424  switch (TokenInformationClass)
2425  {
2426  case TokenUser:
2427  {
2428  PTOKEN_USER tu = (PTOKEN_USER)TokenInformation;
2429 
2430  DPRINT("NtQueryInformationToken(TokenUser)\n");
2431  RequiredLength = sizeof(TOKEN_USER) +
2432  RtlLengthSid(Token->UserAndGroups[0].Sid);
2433 
2434  _SEH2_TRY
2435  {
2437  {
2439  &Token->UserAndGroups[0],
2440  RequiredLength - sizeof(TOKEN_USER),
2441  &tu->User,
2442  (PSID)(tu + 1),
2443  &Unused.PSid,
2444  &Unused.Ulong);
2445  }
2446  else
2447  {
2449  }
2450 
2451  if (ReturnLength != NULL)
2452  {
2454  }
2455  }
2457  {
2459  }
2460  _SEH2_END;
2461 
2462  break;
2463  }
2464 
2465  case TokenGroups:
2466  {
2467  PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
2468 
2469  DPRINT("NtQueryInformationToken(TokenGroups)\n");
2470  RequiredLength = sizeof(tg->GroupCount) +
2471  RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]);
2472 
2473  _SEH2_TRY
2474  {
2476  {
2477  ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
2478  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES));
2479  PSID Sid = (PSID_AND_ATTRIBUTES)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
2480  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)));
2481 
2482  tg->GroupCount = Token->UserAndGroupCount - 1;
2483  Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
2484  &Token->UserAndGroups[1],
2485  SidLen,
2486  &tg->Groups[0],
2487  Sid,
2488  &Unused.PSid,
2489  &Unused.Ulong);
2490  }
2491  else
2492  {
2494  }
2495 
2496  if (ReturnLength != NULL)
2497  {
2499  }
2500  }
2502  {
2504  }
2505  _SEH2_END;
2506 
2507  break;
2508  }
2509 
2510  case TokenPrivileges:
2511  {
2512  PTOKEN_PRIVILEGES tp = (PTOKEN_PRIVILEGES)TokenInformation;
2513 
2514  DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
2515  RequiredLength = sizeof(tp->PrivilegeCount) +
2516  (Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
2517 
2518  _SEH2_TRY
2519  {
2521  {
2522  tp->PrivilegeCount = Token->PrivilegeCount;
2523  RtlCopyLuidAndAttributesArray(Token->PrivilegeCount,
2524  Token->Privileges,
2525  &tp->Privileges[0]);
2526  }
2527  else
2528  {
2530  }
2531 
2532  if (ReturnLength != NULL)
2533  {
2535  }
2536  }
2538  {
2540  }
2541  _SEH2_END;
2542 
2543  break;
2544  }
2545 
2546  case TokenOwner:
2547  {
2548  PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
2549  ULONG SidLen;
2550 
2551  DPRINT("NtQueryInformationToken(TokenOwner)\n");
2552  SidLen = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
2553  RequiredLength = sizeof(TOKEN_OWNER) + SidLen;
2554 
2555  _SEH2_TRY
2556  {
2558  {
2559  to->Owner = (PSID)(to + 1);
2560  Status = RtlCopySid(SidLen,
2561  to->Owner,
2562  Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
2563  }
2564  else
2565  {
2567  }
2568 
2569  if (ReturnLength != NULL)
2570  {
2572  }
2573  }
2575  {
2577  }
2578  _SEH2_END;
2579 
2580  break;
2581  }
2582 
2583  case TokenPrimaryGroup:
2584  {
2585  PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
2586  ULONG SidLen;
2587 
2588  DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
2589  SidLen = RtlLengthSid(Token->PrimaryGroup);
2590  RequiredLength = sizeof(TOKEN_PRIMARY_GROUP) + SidLen;
2591 
2592  _SEH2_TRY
2593  {
2595  {
2596  tpg->PrimaryGroup = (PSID)(tpg + 1);
2597  Status = RtlCopySid(SidLen,
2598  tpg->PrimaryGroup,
2599  Token->PrimaryGroup);
2600  }
2601  else
2602  {
2604  }
2605 
2606  if (ReturnLength != NULL)
2607  {
2609  }
2610  }
2612  {
2614  }
2615  _SEH2_END;
2616 
2617  break;
2618  }
2619 
2620  case TokenDefaultDacl:
2621  {
2622  PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
2623 
2624  DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
2626 
2627  if (Token->DefaultDacl != NULL)
2628  RequiredLength += Token->DefaultDacl->AclSize;
2629 
2630  _SEH2_TRY
2631  {
2633  {
2634  if (Token->DefaultDacl != NULL)
2635  {
2636  tdd->DefaultDacl = (PACL)(tdd + 1);
2638  Token->DefaultDacl,
2639  Token->DefaultDacl->AclSize);
2640  }
2641  else
2642  {
2643  tdd->DefaultDacl = NULL;
2644  }
2645  }
2646  else
2647  {
2649  }
2650 
2651  if (ReturnLength != NULL)
2652  {
2654  }
2655  }
2657  {
2659  }
2660  _SEH2_END;
2661 
2662  break;
2663  }
2664 
2665  case TokenSource:
2666  {
2667  PTOKEN_SOURCE ts = (PTOKEN_SOURCE)TokenInformation;
2668 
2669  DPRINT("NtQueryInformationToken(TokenSource)\n");
2670  RequiredLength = sizeof(TOKEN_SOURCE);
2671 
2672  _SEH2_TRY
2673  {
2675  {
2676  *ts = Token->TokenSource;
2677  }
2678  else
2679  {
2681  }
2682 
2683  if (ReturnLength != NULL)
2684  {
2686  }
2687  }
2689  {
2691  }
2692  _SEH2_END;
2693 
2694  break;
2695  }
2696 
2697  case TokenType:
2698  {
2699  PTOKEN_TYPE tt = (PTOKEN_TYPE)TokenInformation;
2700 
2701  DPRINT("NtQueryInformationToken(TokenType)\n");
2702  RequiredLength = sizeof(TOKEN_TYPE);
2703 
2704  _SEH2_TRY
2705  {
2707  {
2708  *tt = Token->TokenType;
2709  }
2710  else
2711  {
2713  }
2714 
2715  if (ReturnLength != NULL)
2716  {
2718  }
2719  }
2721  {
2723  }
2724  _SEH2_END;
2725 
2726  break;
2727  }
2728 
2730  {
2732 
2733  DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
2734 
2735  /* Fail if the token is not an impersonation token */
2736  if (Token->TokenType != TokenImpersonation)
2737  {
2739  break;
2740  }
2741 
2743 
2744  _SEH2_TRY
2745  {
2747  {
2748  *sil = Token->ImpersonationLevel;
2749  }
2750  else
2751  {
2753  }
2754 
2755  if (ReturnLength != NULL)
2756  {
2758  }
2759  }
2761  {
2763  }
2764  _SEH2_END;
2765 
2766  break;
2767  }
2768 
2769  case TokenStatistics:
2770  {
2771  PTOKEN_STATISTICS ts = (PTOKEN_STATISTICS)TokenInformation;
2772 
2773  DPRINT("NtQueryInformationToken(TokenStatistics)\n");
2774  RequiredLength = sizeof(TOKEN_STATISTICS);
2775 
2776  _SEH2_TRY
2777  {
2779  {
2780  ts->TokenId = Token->TokenId;
2781  ts->AuthenticationId = Token->AuthenticationId;
2782  ts->ExpirationTime = Token->ExpirationTime;
2783  ts->TokenType = Token->TokenType;
2784  ts->ImpersonationLevel = Token->ImpersonationLevel;
2785  ts->DynamicCharged = Token->DynamicCharged;
2786  ts->DynamicAvailable = Token->DynamicAvailable;
2787  ts->GroupCount = Token->UserAndGroupCount - 1;
2788  ts->PrivilegeCount = Token->PrivilegeCount;
2789  ts->ModifiedId = Token->ModifiedId;
2790  }
2791  else
2792  {
2794  }
2795 
2796  if (ReturnLength != NULL)
2797  {
2799  }
2800  }
2802  {
2804  }
2805  _SEH2_END;
2806 
2807  break;
2808  }
2809 
2810  case TokenOrigin:
2811  {
2812  PTOKEN_ORIGIN to = (PTOKEN_ORIGIN)TokenInformation;
2813 
2814  DPRINT("NtQueryInformationToken(TokenOrigin)\n");
2815  RequiredLength = sizeof(TOKEN_ORIGIN);
2816 
2817  _SEH2_TRY
2818  {
2820  {
2822  &Token->AuthenticationId);
2823  }
2824  else
2825  {
2827  }
2828 
2829  if (ReturnLength != NULL)
2830  {
2832  }
2833  }
2835  {
2837  }
2838  _SEH2_END;
2839 
2840  break;
2841  }
2842 
2844  DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
2846  break;
2847 
2848  case TokenRestrictedSids:
2849  {
2850  PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
2851 
2852  DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
2853  RequiredLength = sizeof(tg->GroupCount) +
2854  RtlLengthSidAndAttributes(Token->RestrictedSidCount, Token->RestrictedSids);
2855 
2856  _SEH2_TRY
2857  {
2859  {
2860  ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
2861  (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES));
2862  PSID Sid = (PSID)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
2863  (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)));
2864 
2865  tg->GroupCount = Token->RestrictedSidCount;
2866  Status = RtlCopySidAndAttributesArray(Token->RestrictedSidCount,
2867  Token->RestrictedSids,
2868  SidLen,
2869  &tg->Groups[0],
2870  Sid,
2871  &Unused.PSid,
2872  &Unused.Ulong);
2873  }
2874  else
2875  {
2877  }
2878 
2879  if (ReturnLength != NULL)
2880  {
2882  }
2883  }
2885  {
2887  }
2888  _SEH2_END;
2889 
2890  break;
2891  }
2892 
2893  case TokenSandBoxInert:
2894  DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
2896  break;
2897 
2898  case TokenSessionId:
2899  {
2900  ULONG SessionId = 0;
2901 
2902  DPRINT("NtQueryInformationToken(TokenSessionId)\n");
2903 
2905  if (NT_SUCCESS(Status))
2906  {
2907  _SEH2_TRY
2908  {
2909  /* Buffer size was already verified, no need to check here again */
2910  *(PULONG)TokenInformation = SessionId;
2911 
2912  if (ReturnLength != NULL)
2913  {
2914  *ReturnLength = sizeof(ULONG);
2915  }
2916  }
2918  {
2920  }
2921  _SEH2_END;
2922  }
2923 
2924  break;
2925  }
2926 
2927  default:
2928  DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
2930  break;
2931  }
2932 
2933  /* Unlock and dereference the token */
2936  }
2937 
2938  return Status;
2939 }
2940 
2941 
2942 /*
2943  * NtSetTokenInformation: Partly implemented.
2944  * Unimplemented:
2945  * TokenOrigin, TokenDefaultDacl
2946  */
2949 NTSTATUS
2950 NTAPI
2954  _In_reads_bytes_(TokenInformationLength) PVOID TokenInformation,
2956 {
2957  NTSTATUS Status;
2958  PTOKEN Token;
2960  ULONG NeededAccess = TOKEN_ADJUST_DEFAULT;
2961 
2962  PAGED_CODE();
2963 
2965 
2969  TokenInformation,
2971  PreviousMode);
2972  if (!NT_SUCCESS(Status))
2973  {
2974  /* Invalid buffers */
2975  DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status);
2976  return Status;
2977  }
2978 
2980  {
2981  NeededAccess |= TOKEN_ADJUST_SESSIONID;
2982  }
2983 
2985  NeededAccess,
2987  PreviousMode,
2988  (PVOID*)&Token,
2989  NULL);
2990  if (NT_SUCCESS(Status))
2991  {
2992  switch (TokenInformationClass)
2993  {
2994  case TokenOwner:
2995  {
2996  if (TokenInformationLength >= sizeof(TOKEN_OWNER))
2997  {
2998  PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
2999  PSID InputSid = NULL, CapturedSid;
3000  ULONG DefaultOwnerIndex;
3001 
3002  _SEH2_TRY
3003  {
3004  InputSid = to->Owner;
3005  }
3007  {
3009  _SEH2_YIELD(goto Cleanup);
3010  }
3011  _SEH2_END;
3012 
3013  Status = SepCaptureSid(InputSid,
3014  PreviousMode,
3015  PagedPool,
3016  FALSE,
3017  &CapturedSid);
3018  if (NT_SUCCESS(Status))
3019  {
3020  /* Lock the token */
3022 
3023  /* Find the owner amongst the existing token user and groups */
3025  NULL,
3026  CapturedSid,
3027  NULL,
3028  &DefaultOwnerIndex);
3029  if (NT_SUCCESS(Status))
3030  {
3031  /* Found it */
3032  Token->DefaultOwnerIndex = DefaultOwnerIndex;
3033  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3034  }
3035 
3036  /* Unlock the token */
3038 
3039  SepReleaseSid(CapturedSid,
3040  PreviousMode,
3041  FALSE);
3042  }
3043  }
3044  else
3045  {
3047  }
3048  break;
3049  }
3050 
3051  case TokenPrimaryGroup:
3052  {
3054  {
3055  PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
3056  PSID InputSid = NULL, CapturedSid;
3057  ULONG PrimaryGroupIndex;
3058 
3059  _SEH2_TRY
3060  {
3061  InputSid = tpg->PrimaryGroup;
3062  }
3064  {
3066  _SEH2_YIELD(goto Cleanup);
3067  }
3068  _SEH2_END;
3069 
3070  Status = SepCaptureSid(InputSid,
3071  PreviousMode,
3072  PagedPool,
3073  FALSE,
3074  &CapturedSid);
3075  if (NT_SUCCESS(Status))
3076  {
3077  /* Lock the token */
3079 
3080  /* Find the primary group amongst the existing token user and groups */
3082  CapturedSid,
3083  NULL,
3084  &PrimaryGroupIndex,
3085  NULL);
3086  if (NT_SUCCESS(Status))
3087  {
3088  /* Found it */
3089  Token->PrimaryGroup = Token->UserAndGroups[PrimaryGroupIndex].Sid;
3090  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3091  }
3092 
3093  /* Unlock the token */
3095 
3096  SepReleaseSid(CapturedSid,
3097  PreviousMode,
3098  FALSE);
3099  }
3100  }
3101  else
3102  {
3104  }
3105  break;
3106  }
3107 
3108  case TokenDefaultDacl:
3109  {
3111  {
3112  PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
3113  PACL InputAcl = NULL;
3114 
3115  _SEH2_TRY
3116  {
3117  InputAcl = tdd->DefaultDacl;
3118  }
3120  {
3122  _SEH2_YIELD(goto Cleanup);
3123  }
3124  _SEH2_END;
3125 
3126  if (InputAcl != NULL)
3127  {
3128  PACL CapturedAcl;
3129 
3130  /* Capture and copy the dacl */
3131  Status = SepCaptureAcl(InputAcl,
3132  PreviousMode,
3133  PagedPool,
3134  TRUE,
3135  &CapturedAcl);
3136  if (NT_SUCCESS(Status))
3137  {
3138  ULONG DynamicLength;
3139 
3140  /* Lock the token */
3142 
3143  //
3144  // NOTE: So far our dynamic area only contains
3145  // the default dacl, so this makes the following
3146  // code pretty simple. The day where it stores
3147  // other data, the code will require adaptations.
3148  //
3149 
3150  DynamicLength = Token->DynamicAvailable;
3151  // Add here any other data length present in the dynamic area...
3152  if (Token->DefaultDacl)
3153  DynamicLength += Token->DefaultDacl->AclSize;
3154 
3155  /* Reallocate the dynamic area if it is too small */
3157  if ((DynamicLength < CapturedAcl->AclSize) ||
3158  (Token->DynamicPart == NULL))
3159  {
3160  PVOID NewDynamicPart;
3161 
3162  NewDynamicPart = ExAllocatePoolWithTag(PagedPool,
3163  CapturedAcl->AclSize,
3165  if (NewDynamicPart == NULL)
3166  {
3168  }
3169  else
3170  {
3171  if (Token->DynamicPart != NULL)
3172  {
3173  // RtlCopyMemory(NewDynamicPart, Token->DynamicPart, DynamicLength);
3174  ExFreePoolWithTag(Token->DynamicPart, TAG_TOKEN_DYNAMIC);
3175  }
3176  Token->DynamicPart = NewDynamicPart;
3177  Token->DynamicAvailable = 0;
3178  }
3179  }
3180  else
3181  {
3182  Token->DynamicAvailable = DynamicLength - CapturedAcl->AclSize;
3183  }
3184 
3185  if (NT_SUCCESS(Status))
3186  {
3187  /* Set the new dacl */
3188  Token->DefaultDacl = (PVOID)Token->DynamicPart;
3189  RtlCopyMemory(Token->DefaultDacl,
3190  CapturedAcl,
3191  CapturedAcl->AclSize);
3192 
3193  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3194  }
3195 
3196  /* Unlock the token */
3198 
3199  ExFreePoolWithTag(CapturedAcl, TAG_ACL);
3200  }
3201  }
3202  else
3203  {
3204  /* Lock the token */
3206 
3207  /* Clear the default dacl if present */
3208  if (Token->DefaultDacl != NULL)
3209  {
3210  Token->DynamicAvailable += Token->DefaultDacl->AclSize;
3211  RtlZeroMemory(Token->DefaultDacl, Token->DefaultDacl->AclSize);
3212  Token->DefaultDacl = NULL;
3213 
3214  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3215  }
3216 
3217  /* Unlock the token */
3219  }
3220  }
3221  else
3222  {
3224  }
3225  break;
3226  }
3227 
3228  case TokenSessionId:
3229  {
3230  ULONG SessionId = 0;
3231 
3232  _SEH2_TRY
3233  {
3234  /* Buffer size was already verified, no need to check here again */
3235  SessionId = *(PULONG)TokenInformation;
3236  }
3238  {
3240  _SEH2_YIELD(goto Cleanup);
3241  }
3242  _SEH2_END;
3243 
3244  /* Check for TCB privilege */
3246  {
3248  break;
3249  }
3250 
3251  /* Lock the token */
3253 
3254  Token->SessionId = SessionId;
3255  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3256 
3257  /* Unlock the token */
3259 
3260  break;
3261  }
3262 
3263  case TokenSessionReference:
3264  {
3265  ULONG SessionReference;
3266 
3267  _SEH2_TRY
3268  {
3269  /* Buffer size was already verified, no need to check here again */
3270  SessionReference = *(PULONG)TokenInformation;
3271  }
3273  {
3275  _SEH2_YIELD(goto Cleanup);
3276  }
3277  _SEH2_END;
3278 
3279  /* Check for TCB privilege */
3281  {
3283  goto Cleanup;
3284  }
3285 
3286  /* Check if it is 0 */
3287  if (SessionReference == 0)
3288  {
3289  ULONG OldTokenFlags;
3290 
3291  /* Lock the token */
3293 
3294  /* Atomically set the flag in the token */
3295  OldTokenFlags = RtlInterlockedSetBits(&Token->TokenFlags,
3297  /*
3298  * If the flag was already set, do not dereference again
3299  * the logon session. Use SessionReference as an indicator
3300  * to know whether to really dereference the session.
3301  */
3302  if (OldTokenFlags == Token->TokenFlags)
3303  SessionReference = ULONG_MAX;
3304 
3305  /* Unlock the token */
3307  }
3308 
3309  /* Dereference the logon session if needed */
3310  if (SessionReference == 0)
3311  SepRmDereferenceLogonSession(&Token->AuthenticationId);
3312 
3313  break;
3314  }
3315 
3316  case TokenAuditPolicy:
3317  {
3318  PTOKEN_AUDIT_POLICY_INFORMATION PolicyInformation =
3319  (PTOKEN_AUDIT_POLICY_INFORMATION)TokenInformation;
3320  SEP_AUDIT_POLICY AuditPolicy;
3321  ULONG i;
3322 
3323  _SEH2_TRY
3324  {
3325  ProbeForRead(PolicyInformation,
3327  Policies[PolicyInformation->PolicyCount]),
3328  sizeof(ULONG));
3329 
3330  /* Loop all policies in the structure */
3331  for (i = 0; i < PolicyInformation->PolicyCount; i++)
3332  {
3333  /* Set the corresponding bits in the packed structure */
3334  switch (PolicyInformation->Policies[i].Category)
3335  {
3336  case AuditCategorySystem:
3337  AuditPolicy.PolicyElements.System = PolicyInformation->Policies[i].Value;
3338  break;
3339 
3340  case AuditCategoryLogon:
3341  AuditPolicy.PolicyElements.Logon = PolicyInformation->Policies[i].Value;
3342  break;
3343 
3345  AuditPolicy.PolicyElements.ObjectAccess = PolicyInformation->Policies[i].Value;
3346  break;
3347 
3349  AuditPolicy.PolicyElements.PrivilegeUse = PolicyInformation->Policies[i].Value;
3350  break;
3351 
3353  AuditPolicy.PolicyElements.DetailedTracking = PolicyInformation->Policies[i].Value;
3354  break;
3355 
3357  AuditPolicy.PolicyElements.PolicyChange = PolicyInformation->Policies[i].Value;
3358  break;
3359 
3361  AuditPolicy.PolicyElements.AccountManagement = PolicyInformation->Policies[i].Value;
3362  break;
3363 
3365  AuditPolicy.PolicyElements.DirectoryServiceAccess = PolicyInformation->Policies[i].Value;
3366  break;
3367 
3369  AuditPolicy.PolicyElements.AccountLogon = PolicyInformation->Policies[i].Value;
3370  break;
3371  }
3372  }
3373  }
3375  {
3377  _SEH2_YIELD(goto Cleanup);
3378  }
3379  _SEH2_END;
3380 
3381  /* Check for TCB privilege */
3383  {
3385  break;
3386  }
3387 
3388  /* Lock the token */
3390 
3391  /* Set the new audit policy */
3392  Token->AuditPolicy = AuditPolicy;
3393  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3394 
3395  /* Unlock the token */
3397 
3398  break;
3399  }
3400 
3401  case TokenOrigin:
3402  {
3404 
3405  _SEH2_TRY
3406  {
3407  /* Copy the token origin */
3408  TokenOrigin = *(PTOKEN_ORIGIN)TokenInformation;
3409  }
3411  {
3413  _SEH2_YIELD(goto Cleanup);
3414  }
3415  _SEH2_END;
3416 
3417  /* Check for TCB privilege */
3419  {
3421  break;
3422  }
3423 
3424  /* Lock the token */
3426 
3427  /* Check if there is no token origin set yet */
3428  if (RtlIsZeroLuid(&Token->OriginatingLogonSession))
3429  {
3430  /* Set the token origin */
3431  Token->OriginatingLogonSession =
3432  TokenOrigin.OriginatingLogonSession;
3433 
3434  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3435  }
3436 
3437  /* Unlock the token */
3439 
3440  break;
3441  }
3442 
3443  default:
3444  {
3445  DPRINT1("Invalid TokenInformationClass: 0x%lx\n",
3448  break;
3449  }
3450  }
3451 Cleanup:
3453  }
3454 
3455  if (!NT_SUCCESS(Status))
3456  {
3457  DPRINT1("NtSetInformationToken failed with Status 0x%lx\n", Status);
3458  }
3459 
3460  return Status;
3461 }
3462 
3463 
3464 /*
3465  * @implemented
3466  *
3467  * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
3468  * this is certainly NOT true, although I can't say for sure that EffectiveOnly
3469  * is correct either. -Gunnar
3470  * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
3471  * NOTE for readers: http://hex.pp.ua/nt/NtDuplicateToken.php is therefore
3472  * wrong in that regard, while MSDN documentation is correct.
3473  */
3476 NTSTATUS
3477 NTAPI
3479  _In_ HANDLE ExistingTokenHandle,
3485 {
3487  HANDLE hToken;
3488  PTOKEN Token;
3489  PTOKEN NewToken;
3490  PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService;
3491  BOOLEAN QoSPresent;
3493  NTSTATUS Status;
3494 
3495  PAGED_CODE();
3496 
3497  if (TokenType != TokenImpersonation &&
3499  {
3500  return STATUS_INVALID_PARAMETER;
3501  }
3502 
3504 
3505  if (PreviousMode != KernelMode)
3506  {
3507  _SEH2_TRY
3508  {
3510  }
3512  {
3513  /* Return the exception code */
3515  }
3516  _SEH2_END;
3517  }
3518 
3520  PreviousMode,
3521  PagedPool,
3522  FALSE,
3523  &CapturedSecurityQualityOfService,
3524  &QoSPresent);
3525  if (!NT_SUCCESS(Status))
3526  {
3527  DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status);
3528  return Status;
3529  }
3530 
3531  Status = ObReferenceObjectByHandle(ExistingTokenHandle,
3534  PreviousMode,
3535  (PVOID*)&Token,
3537  if (!NT_SUCCESS(Status))
3538  {
3539  DPRINT1("Failed to reference token (Status 0x%lx)\n", Status);
3540  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
3541  PreviousMode,
3542  FALSE);
3543  return Status;
3544  }
3545 
3546  /*
3547  * Fail, if the original token is an impersonation token and the caller
3548  * tries to raise the impersonation level of the new token above the
3549  * impersonation level of the original token.
3550  */
3551  if (Token->TokenType == TokenImpersonation)
3552  {
3553  if (QoSPresent &&
3554  CapturedSecurityQualityOfService->ImpersonationLevel >Token->ImpersonationLevel)
3555  {
3557  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
3558  PreviousMode,
3559  FALSE);
3561  }
3562  }
3563 
3564  /*
3565  * Fail, if a primary token is to be created from an impersonation token
3566  * and and the impersonation level of the impersonation token is below SecurityImpersonation.
3567  */
3568  if (Token->TokenType == TokenImpersonation &&
3569  TokenType == TokenPrimary &&
3570  Token->ImpersonationLevel < SecurityImpersonation)
3571  {
3573  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
3574  PreviousMode,
3575  FALSE);
3577  }
3578 
3581  EffectiveOnly,
3582  TokenType,
3583  (QoSPresent ? CapturedSecurityQualityOfService->ImpersonationLevel : SecurityAnonymous),
3584  PreviousMode,
3585  &NewToken);
3586 
3588 
3589  if (NT_SUCCESS(Status))
3590  {
3591  Status = ObInsertObject(NewToken,
3592  NULL,
3593  (DesiredAccess ? DesiredAccess : HandleInformation.GrantedAccess),
3594  0,
3595  NULL,
3596  &hToken);
3597  if (NT_SUCCESS(Status))
3598  {
3599  _SEH2_TRY
3600  {
3601  *NewTokenHandle = hToken;
3602  }
3604  {
3606  }
3607  _SEH2_END;
3608  }
3609  }
3610 
3611  /* Free the captured structure */
3612  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
3613  PreviousMode,
3614  FALSE);
3615 
3616  return Status;
3617 }
3618 
3621  IN BOOLEAN ResetToDefault,
3622  IN PTOKEN_GROUPS NewState,
3626 {
3627  UNIMPLEMENTED;
3628  return STATUS_NOT_IMPLEMENTED;
3629 }
3630 
3631 
3632 static
3633 NTSTATUS
3636  _In_ BOOLEAN DisableAllPrivileges,
3637  _In_opt_ PLUID_AND_ATTRIBUTES NewState,
3638  _In_ ULONG NewStateCount,
3641  _Out_ PULONG ChangedPrivileges,
3642  _Out_ PBOOLEAN ChangesMade)
3643 {
3644  ULONG i, j, PrivilegeCount, ChangeCount, NewAttributes;
3645 
3646  /* Count the found privileges and those that need to be changed */
3647  PrivilegeCount = 0;
3648  ChangeCount = 0;
3649  *ChangesMade = FALSE;
3650 
3651  /* Loop all privileges in the token */
3652  for (i = 0; i < Token->PrivilegeCount; i++)
3653  {
3654  /* Shall all of them be disabled? */
3655  if (DisableAllPrivileges)
3656  {
3657  /* The new attributes are the old ones, but disabled */
3658  NewAttributes = Token->Privileges[i].Attributes & ~SE_PRIVILEGE_ENABLED;
3659  }
3660  else
3661  {
3662  /* Otherwise loop all provided privileges */
3663  for (j = 0; j < NewStateCount; j++)
3664  {
3665  /* Check if this is the LUID we are looking for */
3666  if (RtlEqualLuid(&Token->Privileges[i].Luid, &NewState[j].Luid))
3667  {
3668  DPRINT("Found privilege\n");
3669 
3670  /* Copy SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED */
3671  NewAttributes = NewState[j].Attributes;
3672  NewAttributes &= (SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED);
3673  NewAttributes |= Token->Privileges[i].Attributes & ~SE_PRIVILEGE_ENABLED;
3674 
3675  /* Stop looking */
3676  break;
3677  }
3678  }
3679 
3680  /* Check if we didn't find the privilege */
3681  if (j == NewStateCount)
3682  {
3683  /* Continue with the token's next privilege */
3684  continue;
3685  }
3686  }
3687 
3688  /* We found a privilege, count it */
3689  PrivilegeCount++;
3690 
3691  /* Does the privilege need to be changed? */
3692  if (Token->Privileges[i].Attributes != NewAttributes)
3693  {
3694  /* Does the caller want the old privileges? */
3695  if (PreviousState != NULL)
3696  {
3697  /* Copy the old privilege */
3698  PreviousState->Privileges[ChangeCount] = Token->Privileges[i];
3699  }
3700 
3701  /* Does the caller want to apply the changes? */
3702  if (ApplyChanges)
3703  {
3704  /* Shall we remove the privilege? */
3705  if (NewAttributes & SE_PRIVILEGE_REMOVED)
3706  {
3707  /* Set the token as disabled and update flags for it */
3708  Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
3710 
3711  /* Remove the privilege */
3713 
3714  *ChangesMade = TRUE;
3715 
3716  /* Fix the running index and continue with next one */
3717  i--;
3718  continue;
3719  }
3720 
3721  /* Set the new attributes and update flags */
3722  Token->Privileges[i].Attributes = NewAttributes;
3724  *ChangesMade = TRUE;
3725  }
3726 
3727  /* Increment the change count */
3728  ChangeCount++;
3729  }
3730  }
3731 
3732  /* Set the number of saved privileges */
3733  if (PreviousState != NULL)
3734  PreviousState->PrivilegeCount = ChangeCount;
3735 
3736  /* Return the number of changed privileges */
3737  *ChangedPrivileges = ChangeCount;
3738 
3739  /* Check if we missed some */
3740  if (!DisableAllPrivileges && (PrivilegeCount < NewStateCount))
3741  {
3742  return STATUS_NOT_ALL_ASSIGNED;
3743  }
3744 
3745  return STATUS_SUCCESS;
3746 }
3747 
3748 
3749 /*
3750  * @implemented
3751  */
3754 NTSTATUS
3755 NTAPI
3758  _In_ BOOLEAN DisableAllPrivileges,
3759  _In_opt_ PTOKEN_PRIVILEGES NewState,
3764 {
3765  NTSTATUS Status;
3767  PTOKEN Token;
3768  PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
3769  ULONG CapturedCount = 0;
3770  ULONG CapturedLength = 0;
3771  ULONG NewStateSize = 0;
3772  ULONG ChangeCount;
3774  BOOLEAN ChangesMade = FALSE;
3775 
3776  PAGED_CODE();
3777 
3778  DPRINT("NtAdjustPrivilegesToken() called\n");
3779 
3780  /* Fail, if we do not disable all privileges but NewState is NULL */
3781  if (DisableAllPrivileges == FALSE && NewState == NULL)
3782  return STATUS_INVALID_PARAMETER;
3783 
3785  if (PreviousMode != KernelMode)
3786  {
3787  _SEH2_TRY
3788  {
3789  /* Probe NewState */
3790  if (DisableAllPrivileges == FALSE)
3791  {
3792  /* First probe the header */
3793  ProbeForRead(NewState, sizeof(TOKEN_PRIVILEGES), sizeof(ULONG));
3794 
3795  CapturedCount = NewState->PrivilegeCount;
3796  NewStateSize = FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges[CapturedCount]);
3797 
3798  ProbeForRead(NewState, NewStateSize, sizeof(ULONG));
3799  }
3800 
3801  /* Probe PreviousState and ReturnLength */
3802  if (PreviousState != NULL)
3803  {
3805  ProbeForWrite(ReturnLength, sizeof(ULONG), sizeof(ULONG));
3806  }
3807  }
3809  {
3810  /* Return the exception code */
3812  }
3813  _SEH2_END;
3814  }
3815  else
3816  {
3817  /* This is kernel mode, we trust the caller */
3818  if (DisableAllPrivileges == FALSE)
3819  CapturedCount = NewState->PrivilegeCount;
3820  }
3821 
3822  /* Do we need to capture the new state? */
3823  if (DisableAllPrivileges == FALSE)
3824  {
3825  _SEH2_TRY
3826  {
3827  /* Capture the new state array of privileges */
3828  Status = SeCaptureLuidAndAttributesArray(NewState->Privileges,
3829  CapturedCount,
3830  PreviousMode,
3831  NULL,
3832  0,
3833  PagedPool,
3834  TRUE,
3835  &CapturedPrivileges,
3836  &CapturedLength);
3837  }
3839  {
3840  /* Return the exception code */
3842  }
3843  _SEH2_END;
3844 
3845  if (!NT_SUCCESS(Status))
3846  return Status;
3847  }
3848 
3849  /* Reference the token */
3853  PreviousMode,
3854  (PVOID*)&Token,
3855  NULL);
3856  if (!NT_SUCCESS(Status))
3857  {
3858  DPRINT1("Failed to reference token (Status 0x%lx)\n", Status);
3859 
3860  /* Release the captured privileges */
3861  if (CapturedPrivileges != NULL)
3862  {
3863  SeReleaseLuidAndAttributesArray(CapturedPrivileges,
3864  PreviousMode,
3865  TRUE);
3866  }
3867 
3868  return Status;
3869  }
3870 
3871  /* Lock the token */
3873 
3874  /* Count the privileges that need to be changed, do not apply them yet */
3876  DisableAllPrivileges,
3877  CapturedPrivileges,
3878  CapturedCount,
3879  NULL,
3880  FALSE,
3881  &ChangeCount,
3882  &ChangesMade);
3883 
3884  /* Check if the caller asked for the previous state */
3885  if (PreviousState != NULL)
3886  {
3887  /* Calculate the required length */
3889 
3890  /* Try to return the required buffer length */
3891  _SEH2_TRY
3892  {
3894  }
3896  {
3897  /* Do cleanup and return the exception code */
3899  _SEH2_YIELD(goto Cleanup);
3900  }
3901  _SEH2_END;
3902 
3903  /* Fail, if the buffer length is smaller than the required length */
3905  {
3907  goto Cleanup;
3908  }
3909  }
3910 
3911  /* Now enter SEH, since we might return the old privileges */
3912  _SEH2_TRY
3913  {
3914  /* This time apply the changes */
3916  DisableAllPrivileges,
3917  CapturedPrivileges,
3918  CapturedCount,
3919  PreviousState,
3920  TRUE,
3921  &ChangeCount,
3922  &ChangesMade);
3923  }
3925  {
3926  /* Do cleanup and return the exception code */
3928  ChangesMade = TRUE; // Force write.
3929  _SEH2_YIELD(goto Cleanup);
3930  }
3931  _SEH2_END;
3932 
3933 Cleanup:
3934  /* Touch the token if we made changes */
3935  if (ChangesMade)
3936  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3937 
3938  /* Unlock and dereference the token */
3941 
3942  /* Release the captured privileges */
3943  if (CapturedPrivileges != NULL)
3944  {
3945  SeReleaseLuidAndAttributesArray(CapturedPrivileges,
3946  PreviousMode,
3947  TRUE);
3948  }
3949 
3950  DPRINT ("NtAdjustPrivilegesToken() done\n");
3951  return Status;
3952 }
3953 
3955 NTSTATUS
3956 NTAPI
3962  _In_ PLUID AuthenticationId,
3963  _In_ PLARGE_INTEGER ExpirationTime,
3971 {
3972  HANDLE hToken;
3974  ULONG PrivilegeCount, GroupCount;
3975  PSID OwnerSid, PrimaryGroupSid;
3976  PACL DefaultDacl;
3977  LARGE_INTEGER LocalExpirationTime = {{0, 0}};
3978  LUID LocalAuthenticationId;
3979  TOKEN_SOURCE LocalTokenSource;
3980  SECURITY_QUALITY_OF_SERVICE LocalSecurityQos;
3981  PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
3982  PSID_AND_ATTRIBUTES CapturedUser = NULL;
3983  PSID_AND_ATTRIBUTES CapturedGroups = NULL;
3984  PSID CapturedOwnerSid = NULL;
3985  PSID CapturedPrimaryGroupSid = NULL;
3986  PACL CapturedDefaultDacl = NULL;
3987  ULONG PrivilegesLength, UserLength, GroupsLength;
3988  NTSTATUS Status;
3989 
3990  PAGED_CODE();
3991 
3993 
3994  if (PreviousMode != KernelMode)
3995  {
3996  _SEH2_TRY
3997  {
3999 
4000  if (ObjectAttributes != NULL)
4001  {
4003  sizeof(OBJECT_ATTRIBUTES),
4004  sizeof(ULONG));
4005  LocalSecurityQos = *(SECURITY_QUALITY_OF_SERVICE*)ObjectAttributes->SecurityQualityOfService;
4006  }
4007 
4008  ProbeForRead(AuthenticationId,
4009  sizeof(LUID),
4010  sizeof(ULONG));
4011  LocalAuthenticationId = *AuthenticationId;
4012 
4013  LocalExpirationTime = ProbeForReadLargeInteger(ExpirationTime);
4014 
4016  sizeof(TOKEN_USER),
4017  sizeof(ULONG));
4018 
4020  sizeof(TOKEN_GROUPS),
4021  sizeof(ULONG));
4022  GroupCount = TokenGroups->GroupCount;
4023 
4025  sizeof(TOKEN_PRIVILEGES),
4026  sizeof(ULONG));
4027  PrivilegeCount = TokenPrivileges->PrivilegeCount;
4028 
4029  if (TokenOwner != NULL)
4030  {
4032  sizeof(TOKEN_OWNER),
4033  sizeof(ULONG));
4034  OwnerSid = TokenOwner->Owner;
4035  }
4036  else
4037  {
4038  OwnerSid = NULL;
4039  }
4040 
4042  sizeof(TOKEN_PRIMARY_GROUP),
4043  sizeof(ULONG));
4044  PrimaryGroupSid = TokenPrimaryGroup->PrimaryGroup;
4045 
4046  if (TokenDefaultDacl != NULL)
4047  {
4049  sizeof(TOKEN_DEFAULT_DACL),
4050  sizeof(ULONG));
4051  DefaultDacl = TokenDefaultDacl->DefaultDacl;
4052  }
4053  else
4054  {
4055  DefaultDacl = NULL;
4056  }
4057 
4059  sizeof(TOKEN_SOURCE),
4060  sizeof(ULONG));
4061  LocalTokenSource = *TokenSource;
4062  }
4064  {
4065  /* Return the exception code */
4067  }
4068  _SEH2_END;
4069  }
4070  else
4071  {
4072  if (ObjectAttributes != NULL)
4073  LocalSecurityQos = *(SECURITY_QUALITY_OF_SERVICE*)ObjectAttributes->SecurityQualityOfService;
4074  LocalAuthenticationId = *AuthenticationId;
4075  LocalExpirationTime = *ExpirationTime;
4076  GroupCount = TokenGroups->GroupCount;
4077  PrivilegeCount = TokenPrivileges->PrivilegeCount;
4078  OwnerSid = TokenOwner ? TokenOwner->Owner : NULL;
4079  PrimaryGroupSid = TokenPrimaryGroup->PrimaryGroup;
4080  DefaultDacl = TokenDefaultDacl ? TokenDefaultDacl->DefaultDacl : NULL;
4081  LocalTokenSource = *TokenSource;
4082  }
4083 
4084  /* Check token type */
4085  if ((TokenType < TokenPrimary) ||
4087  {
4088  return STATUS_BAD_TOKEN_TYPE;
4089  }
4090 
4091  /* Check for token creation privilege */
4093  {
4095  }
4096 
4097  /* Capture the user SID and attributes */
4099  1,
4100  PreviousMode,
4101  NULL,
4102  0,
4103  PagedPool,
4104  FALSE,
4105  &CapturedUser,
4106  &UserLength);
4107  if (!NT_SUCCESS(Status))
4108  {
4109  goto Cleanup;
4110  }
4111 
4112  /* Capture the groups SID and attributes array */
4114  GroupCount,
4115  PreviousMode,
4116  NULL,
4117  0,
4118  PagedPool,
4119  FALSE,
4120  &CapturedGroups,
4121  &GroupsLength);
4122  if (!NT_SUCCESS(Status))
4123  {
4124  goto Cleanup;
4125  }
4126 
4127  /* Capture privileges */
4129  PrivilegeCount,
4130  PreviousMode,
4131  NULL,
4132  0,
4133  PagedPool,
4134  FALSE,
4135  &CapturedPrivileges,
4136  &PrivilegesLength);
4137  if (!NT_SUCCESS(Status))
4138  {
4139  goto Cleanup;
4140  }
4141 
4142  /* Capture the token owner SID */
4143  if (TokenOwner != NULL)
4144  {
4145  Status = SepCaptureSid(OwnerSid,
4146  PreviousMode,
4147  PagedPool,
4148  FALSE,
4149  &CapturedOwnerSid);
4150  if (!NT_SUCCESS(Status))
4151  {
4152  goto Cleanup;
4153  }
4154  }
4155 
4156  /* Capture the token primary group SID */
4157  Status = SepCaptureSid(PrimaryGroupSid,
4158  PreviousMode,
4159  PagedPool,
4160  FALSE,
4161  &CapturedPrimaryGroupSid);
4162  if (!NT_SUCCESS(Status))
4163  {
4164  goto Cleanup;
4165  }
4166 
4167  /* Capture DefaultDacl */
4168  if (DefaultDacl != NULL)
4169  {
4170  Status = SepCaptureAcl(DefaultDacl,
4171  PreviousMode,
4172  NonPagedPool,
4173  FALSE,
4174  &CapturedDefaultDacl);
4175  if (!NT_SUCCESS(Status))
4176  {
4177  goto Cleanup;
4178  }
4179  }
4180 
4181  /* Call the internal function */
4182  Status = SepCreateToken(&hToken,
4183  PreviousMode,
4184  DesiredAccess,
4186  TokenType,
4187  LocalSecurityQos.ImpersonationLevel,
4188  &LocalAuthenticationId,
4189  &LocalExpirationTime,
4190  CapturedUser,
4191  GroupCount,
4192  CapturedGroups,
4193  0, // FIXME: Should capture
4194  PrivilegeCount,
4195  CapturedPrivileges,
4196  CapturedOwnerSid,
4197  CapturedPrimaryGroupSid,
4198  CapturedDefaultDacl,
4199  &LocalTokenSource,
4200  FALSE);
4201  if (NT_SUCCESS(Status))
4202  {
4203  _SEH2_TRY
4204  {
4205  *TokenHandle = hToken;
4206  }
4208  {
4210  }
4211  _SEH2_END;
4212  }
4213 
4214 Cleanup:
4215 
4216  /* Release what we captured */
4219  SeReleaseLuidAndAttributesArray(CapturedPrivileges, PreviousMode, FALSE);
4220  SepReleaseSid(CapturedOwnerSid, PreviousMode, FALSE);
4221  SepReleaseSid(CapturedPrimaryGroupSid, PreviousMode, FALSE);
4222  SepReleaseAcl(CapturedDefaultDacl, PreviousMode, FALSE);
4223 
4224  return Status;
4225 }
4226 
4227 /*
4228  * @implemented
4229  */
4230 NTSTATUS
4231 NTAPI
4237 {
4238  PETHREAD Thread, NewThread;
4239  HANDLE hToken;
4240  PTOKEN Token, NewToken = NULL, PrimaryToken;
4246  PACL Dacl = NULL;
4248  NTSTATUS Status;
4249  BOOLEAN RestoreImpersonation = FALSE;
4250 
4251  PAGED_CODE();
4252 
4254 
4255  if (PreviousMode != KernelMode)
4256  {
4257  _SEH2_TRY
4258  {
4260  }
4262  {
4263  /* Return the exception code */
4265  }
4266  _SEH2_END;
4267  }
4268 
4269  /* Validate object attributes */
4271 
4272  /*
4273  * At first open the thread token for information access and verify
4274  * that the token associated with thread is valid.
4275  */
4276 
4279  NULL);
4280  if (!NT_SUCCESS(Status))
4281  {
4282  return Status;
4283  }
4284 
4287  if (Token == NULL)
4288  {
4290  return STATUS_NO_TOKEN;
4291  }
4292 
4294  {
4298  }
4299 
4300  /*
4301  * Revert to self if OpenAsSelf is specified.
4302  */
4303 
4304  if (OpenAsSelf)
4305  {
4306  RestoreImpersonation = PsDisableImpersonation(PsGetCurrentThread(),
4308  }
4309 
4310  if (CopyOnOpen)
4311  {
4314  (PVOID*)&NewThread, NULL);
4315  if (NT_SUCCESS(Status))
4316  {
4317  PrimaryToken = PsReferencePrimaryToken(NewThread->ThreadsProcess);
4318 
4319  Status = SepCreateImpersonationTokenDacl(Token, PrimaryToken, &Dacl);
4320 
4321  ObFastDereferenceObject(&NewThread->ThreadsProcess->Token, PrimaryToken);
4322 
4323  if (NT_SUCCESS(Status))
4324  {
4325  if (Dacl)
4326  {
4330  FALSE);
4331  }
4332 
4335 
4338  KernelMode, &NewToken);
4339  if (NT_SUCCESS(Status))
4340  {
4341  ObReferenceObject(NewToken);
4342  Status = ObInsertObject(NewToken, NULL, DesiredAccess, 0, NULL,
4343  &hToken);
4344  }
4345  }
4346  }
4347  }
4348  else
4349  {
4352  PreviousMode, &hToken);
4353  }
4354 
4356 
4357  if (RestoreImpersonation)
4358  {
4360  }
4361 
4363 
4364  if (NT_SUCCESS(Status) && CopyOnOpen)
4365  {
4367  }
4368 
4369  if (NewToken) ObDereferenceObject(NewToken);
4370 
4371  if (CopyOnOpen && NewThread) ObDereferenceObject(NewThread);
4372 
4374 
4375  if (NT_SUCCESS(Status))
4376  {
4377  _SEH2_TRY
4378  {
4379  *TokenHandle = hToken;
4380  }
4382  {
4384  }
4385  _SEH2_END;
4386  }
4387 
4388  return Status;
4389 }
4390 
4391 /*
4392  * @implemented
4393  */
4399 {
4400  return NtOpenThreadTokenEx(ThreadHandle, DesiredAccess, OpenAsSelf, 0,
4401  TokenHandle);
4402 }
4403 
4421 NTSTATUS
4422 NTAPI
4424  _In_ HANDLE FirstTokenHandle,
4425  _In_ HANDLE SecondTokenHandle,
4426  _Out_ PBOOLEAN Equal)
4427 {
4429  PTOKEN FirstToken, SecondToken;
4430  BOOLEAN IsEqual;
4431  NTSTATUS Status;
4432 
4433  PAGED_CODE();
4434 
4436 
4437  if (PreviousMode != KernelMode)
4438  {
4439  _SEH2_TRY
4440  {
4441  ProbeForWriteBoolean(Equal);
4442  }
4444  {
4445  /* Return the exception code */
4447  }
4448  _SEH2_END;
4449  }
4450 
4451  Status = ObReferenceObjectByHandle(FirstTokenHandle,
4452  TOKEN_QUERY,
4454  PreviousMode,
4455  (PVOID*)&FirstToken,
4456  NULL);
4457  if (!NT_SUCCESS(Status))
4458  {
4459  DPRINT1("ObReferenceObjectByHandle() failed (Status 0x%lx)\n", Status);
4460  return Status;
4461  }
4462 
4463  Status = ObReferenceObjectByHandle(SecondTokenHandle,
4464  TOKEN_QUERY,
4466  PreviousMode,
4467  (PVOID*)&SecondToken,
4468  NULL);
4469  if (!NT_SUCCESS(Status))
4470  {
4471  DPRINT1("ObReferenceObjectByHandle() failed (Status 0x%lx)\n", Status);
4472  ObDereferenceObject(FirstToken);
4473  return Status;
4474  }
4475 
4476  if (FirstToken != SecondToken)
4477  {
4478  Status = SepCompareTokens(FirstToken,
4479  SecondToken,
4480  &IsEqual);
4481  }
4482  else
4483  {
4484  IsEqual = TRUE;
4485  }
4486 
4487  ObDereferenceObject(SecondToken);
4488  ObDereferenceObject(FirstToken);
4489 
4490  if (NT_SUCCESS(Status))
4491  {
4492  _SEH2_TRY
4493  {
4494  *Equal = IsEqual;
4495  }
4497  {
4499  }
4500  _SEH2_END;
4501  }
4502 
4503  return Status;
4504 }
4505 
4506 NTSTATUS
4507 NTAPI
4508 NtFilterToken(IN HANDLE ExistingTokenHandle,
4509  IN ULONG Flags,
4510  IN PTOKEN_GROUPS SidsToDisable OPTIONAL,
4511  IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL,
4512  IN PTOKEN_GROUPS RestrictedSids OPTIONAL,
4514 {
4515  UNIMPLEMENTED;
4516  return STATUS_NOT_IMPLEMENTED;
4517 }
4518 
4543 NTSTATUS
4544 NTAPI
4546  _In_ HANDLE ThreadHandle)
4547 {
4548  PETHREAD Thread;
4550  NTSTATUS Status;
4551  PAGED_CODE();
4552 
4554 
4555  /* Obtain the thread object from the handle */
4556  Status = ObReferenceObjectByHandle(ThreadHandle,
4558  PsThreadType,
4559  PreviousMode,
4560  (PVOID*)&Thread,
4561  NULL);
4562  if (!NT_SUCCESS(Status))
4563  {
4564  DPRINT1("NtImpersonateAnonymousToken(): Failed to reference the object (Status 0x%lx)\n", Status);
4565  return Status;
4566  }
4567 
4568  /* Call the private routine to impersonate the token */
4570  if (!NT_SUCCESS(Status))
4571  {
4572  DPRINT1("NtImpersonateAnonymousToken(): Failed to impersonate the token (Status 0x%lx)\n", Status);
4573  }
4574 
4576  return Status;
4577 }
4578 
4579 /* EOF */
LUID AuthenticationId
Definition: setypes.h:1033
PTOKEN SeAnonymousLogonTokenNoEveryone
Definition: semgr.c:19
#define OBJ_OPENLINK
Definition: winternl.h:230
TOKEN_TYPE TokenType
Definition: setypes.h:208
const LUID SeSystemEnvironmentPrivilege
Definition: priv.c:39
enum _SECURITY_IMPERSONATION_LEVEL * PSECURITY_IMPERSONATION_LEVEL
#define SepAcquireTokenLockExclusive(Token)
Definition: se.h:206
static NTSTATUS SepFindPrimaryGroupAndDefaultOwner(_In_ PTOKEN Token, _In_ PSID PrimaryGroup, _In_opt_ PSID DefaultOwner, _Out_opt_ PULONG PrimaryGroupIndex, _Out_opt_ PULONG DefaultOwnerIndex)
Definition: token.c:698
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:103
#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
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2654
#define _Must_inspect_result_
Definition: no_sal2.h:62
#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:1791
#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:1829
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:2290
_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:4508
NTSTATUS NTAPI SeIsTokenChild(IN PTOKEN Token, OUT PBOOLEAN IsChild)
Definition: token.c:1074
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
const LUID SeIncreaseQuotaPrivilege
Definition: priv.c:22
#define TOKEN_WRITE
Definition: setypes.h:899
#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
const LUID SeCreatePermanentPrivilege
Definition: priv.c:33
const LUID SeDebugPrivilege
Definition: priv.c:37
NTSTATUS NTAPI SepCopyProxyData(PVOID *Dest, PVOID Src)
Definition: token.c:577
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:1039
NTSTATUS NTAPI SeQuerySessionIdToken(IN PACCESS_TOKEN Token, IN PULONG pSessionId)
Definition: token.c:2170
$ULONG DynamicCharged
Definition: setypes.h:1037
LUID AuthenticationId
Definition: setypes.h:188
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:388
NTSTATUS NTAPI NtCompareTokens(_In_ HANDLE FirstTokenHandle, _In_ HANDLE SecondTokenHandle, _Out_ PBOOLEAN Equal)
Compares tokens if they're equal or not.
Definition: token.c:4423
NTSTATUS NTAPI SepCaptureSecurityQualityOfService(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN POOL_TYPE PoolType, IN BOOLEAN CaptureIfKernel, OUT PSECURITY_QUALITY_OF_SERVICE *CapturedSecurityQualityOfService, OUT PBOOLEAN Present)
Definition: sd.c:221
NTSTATUS NTAPI NtOpenThreadTokenEx(IN HANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN OpenAsSelf, IN ULONG HandleAttributes, OUT PHANDLE TokenHandle)
Definition: token.c:4232
LUID SeSystemAuthenticationId
Definition: token.c:31
_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:1124
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3066
_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:873
NTSYSAPI NTSTATUS NTAPI RtlCreateSecurityDescriptor(_Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ ULONG Revision)
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:481
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:2246
#define _In_opt_
Definition: no_sal2.h:212
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#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:794
NTSTATUS NTAPI SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token, OUT PLUID LogonId)
Definition: token.c:2191
ULONG TokenFlags
Definition: setypes.h:210
NTSTATUS NTAPI NtImpersonateAnonymousToken(_In_ HANDLE ThreadHandle)
Allows the calling thread to impersonate the system's anonymous logon token.
Definition: token.c:4545
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
#define _Out_writes_bytes_to_opt_(s, c)
Definition: no_sal2.h:240
_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:32
#define RtlEqualLuid(Luid1, Luid2)
Definition: rtlfuncs.h:301
static VOID SepUpdatePrivilegeFlagsToken(_Inout_ PTOKEN Token)
Definition: token.c:532
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:3620
PTOKEN NTAPI SepCreateSystemProcessToken(VOID)
Creates the system process token.
Definition: token.c:1517
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:28
_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:2376
#define SE_GROUP_ENABLED_BY_DEFAULT
Definition: setypes.h:91
const LUID SeTakeOwnershipPrivilege
Definition: priv.c:26
#define _Out_
Definition: no_sal2.h:160
LUID ParentTokenId
Definition: setypes.h:189
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:974
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:1242
#define TOKEN_ADJUST_DEFAULT
Definition: setypes.h:878
_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:161
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:2219
void * PVOID
Definition: retypes.h:9
TOKEN_TYPE TokenType
Definition: setypes.h:1035
struct _TOKEN_GROUPS * PTOKEN_GROUPS
SECURITY_IMPERSONATION_LEVEL NTAPI SeTokenImpersonationLevel(IN PACCESS_TOKEN Token)
Definition: token.c:2207
ULONG SessionId
Definition: setypes.h:194
NTSTATUS SepRmDereferenceLogonSession(PLUID LogonLuid)
Definition: srm.c:687
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:1053
#define ANONYMOUS_LOGON_LUID
Definition: setypes.h:673
NTSTATUS SepRmReferenceLogonSession(PLUID LogonLuid)
Definition: srm.c:404
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:206
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
#define _Out_opt_
Definition: no_sal2.h:214
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:1034
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:3634
#define STATUS_INVALID_PRIMARY_GROUP
Definition: ntstatus.h:327
#define TOKEN_HAS_RESTORE_PRIVILEGE
Definition: setypes.h:1126
_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:874
#define __kernel_entry
Definition: specstrings.h:355
#define ASSERT(a)
Definition: mode.c:45
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:211
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 _TOKEN_AUDIT_POLICY_INFORMATION * PTOKEN_AUDIT_POLICY_INFORMATION
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:297
_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:1036
VOID NTAPI SepFreeProxyData(PVOID ProxyData)
Definition: token.c:570
PVOID HANDLE
Definition: typedefs.h:73
#define TOKEN_ALL_ACCESS
Definition: setypes.h:892
#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:2653
_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:875
VOID NTAPI SepReleaseSecurityQualityOfService(IN PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN BOOLEAN CaptureIfKernel)
Definition: sd.c:377
SEP_AUDIT_POLICY_CATEGORIES PolicyElements
Definition: setypes.h:148
NTSTATUS NTAPI SeIsTokenSibling(IN PTOKEN Token, OUT PBOOLEAN IsSibling)
Definition: token.c:1107
#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:1222
#define _Inout_
Definition: no_sal2.h:162
static const LUID SeChangeNotifyPrivilege
Definition: authpackage.c:167
CODE_SEG("INIT")
Definition: fsrtlpc.c:19
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:1667
VOID NTAPI SepInitializeTokenImplementation(VOID)
Definition: token.c:1198
_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:1030
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:872
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL Dacl
Definition: rtlfuncs.h:1552
unsigned char UCHAR
Definition: xmlstorage.h:181
char * PBOOLEAN
Definition: retypes.h:11
struct _TOKEN_OWNER * PTOKEN_OWNER
struct _TOKEN_PRIVILEGES * PTOKEN_PRIVILEGES
struct _TOKEN_AUDIT_POLICY_INFORMATION::@1808 Policies[1]
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
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:240
static const WCHAR L[]
Definition: oid.c:1250
#define TOKEN_READ
Definition: setypes.h:897<