ReactOS  0.4.15-dev-2144-g2282205
token.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS kernel
4  * FILE: ntoskrnl/se/token.c
5  * PURPOSE: Security manager
6  *
7  * PROGRAMMERS: David Welch <welch@cwcom.net>
8  */
9 
10 /* INCLUDES *******************************************************************/
11 
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15 #include <ntlsa.h>
16 
18 {
20  struct
21  {
24  } Policies[1];
26 
27 /* GLOBALS ********************************************************************/
28 
30 
31 TOKEN_SOURCE SeSystemTokenSource = {"*SYSTEM*", {0}};
34 
36  TOKEN_READ,
40 };
41 
42 static const INFORMATION_CLASS_INFO SeTokenInformationClass[] = {
43 
44  /* Class 0 not used, blame MS! */
45  ICI_SQ_SAME( 0, 0, 0),
46 
47  /* TokenUser */
48  ICI_SQ_SAME( sizeof(TOKEN_USER), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET_SIZE_VARIABLE ),
49  /* TokenGroups */
50  ICI_SQ_SAME( sizeof(TOKEN_GROUPS), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET_SIZE_VARIABLE ),
51  /* TokenPrivileges */
52  ICI_SQ_SAME( sizeof(TOKEN_PRIVILEGES), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET_SIZE_VARIABLE ),
53  /* TokenOwner */
54  ICI_SQ_SAME( sizeof(TOKEN_OWNER), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
55  /* TokenPrimaryGroup */
56  ICI_SQ_SAME( sizeof(TOKEN_PRIMARY_GROUP), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
57  /* TokenDefaultDacl */
58  ICI_SQ_SAME( sizeof(TOKEN_DEFAULT_DACL), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
59  /* TokenSource */
60  ICI_SQ_SAME( sizeof(TOKEN_SOURCE), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET_SIZE_VARIABLE ),
61  /* TokenType */
62  ICI_SQ_SAME( sizeof(TOKEN_TYPE), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
63  /* TokenImpersonationLevel */
64  ICI_SQ_SAME( sizeof(SECURITY_IMPERSONATION_LEVEL), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
65  /* TokenStatistics */
66  ICI_SQ_SAME( sizeof(TOKEN_STATISTICS), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET_SIZE_VARIABLE ),
67  /* TokenRestrictedSids */
68  ICI_SQ_SAME( sizeof(TOKEN_GROUPS), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
69  /* TokenSessionId */
70  ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY | ICIF_SET ),
71  /* TokenGroupsAndPrivileges */
72  ICI_SQ_SAME( sizeof(TOKEN_GROUPS_AND_PRIVILEGES), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
73  /* TokenSessionReference */
74  ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_SET | ICIF_QUERY_SIZE_VARIABLE ),
75  /* TokenSandBoxInert */
76  ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
77  /* TokenAuditPolicy */
78  ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG), ICIF_QUERY | ICIF_SET | ICIF_QUERY_SIZE_VARIABLE ),
79  /* TokenOrigin */
80  ICI_SQ_SAME( sizeof(TOKEN_ORIGIN), sizeof(ULONG), ICIF_QUERY | ICIF_SET | ICIF_QUERY_SIZE_VARIABLE ),
81 };
82 
83 /* FUNCTIONS *****************************************************************/
84 
97 static
101 {
102  PAGED_CODE();
103 
105  sizeof(ERESOURCE),
107  if (Token->TokenLock == NULL)
108  {
109  DPRINT1("SepCreateTokenLock(): Failed to allocate memory!\n");
111  }
112 
113  ExInitializeResourceLite(Token->TokenLock);
114  return STATUS_SUCCESS;
115 }
116 
127 static
128 VOID
131 {
132  PAGED_CODE();
133 
134  ExDeleteResourceLite(Token->TokenLock);
136 }
137 
138 static NTSTATUS
140  IN PTOKEN SecondToken,
141  OUT PBOOLEAN Equal)
142 {
144 
145  ASSERT(FirstToken != SecondToken);
146 
147  /* Lock the tokens */
148  SepAcquireTokenLockShared(FirstToken);
149  SepAcquireTokenLockShared(SecondToken);
150 
151  /* FIXME: Check if every SID that is present in either token is also present in the other one */
152 
153  Restricted = SeTokenIsRestricted(FirstToken);
154  if (Restricted == SeTokenIsRestricted(SecondToken))
155  {
156  if (Restricted)
157  {
158  /* FIXME: Check if every SID that is restricted in either token is also restricted in the other one */
159  }
160 
161  /* FIXME: Check if every privilege that is present in either token is also present in the other one */
162  DPRINT1("FIXME: Pretending tokens are equal!\n");
163  IsEqual = TRUE;
164  }
165 
166  /* Unlock the tokens */
167  SepReleaseTokenLock(SecondToken);
168  SepReleaseTokenLock(FirstToken);
169 
170  *Equal = IsEqual;
171  return STATUS_SUCCESS;
172 }
173 
174 static
175 VOID
178  _In_ ULONG Index)
179 {
180  ULONG TokenFlag;
181  ASSERT(Index < Token->PrivilegeCount);
182 
183  /* The high part of all values we are interested in is 0 */
184  if (Token->Privileges[Index].Luid.HighPart != 0)
185  {
186  return;
187  }
188 
189  /* Check for certain privileges to update flags */
190  if (Token->Privileges[Index].Luid.LowPart == SE_CHANGE_NOTIFY_PRIVILEGE)
191  {
192  TokenFlag = TOKEN_HAS_TRAVERSE_PRIVILEGE;
193  }
194  else if (Token->Privileges[Index].Luid.LowPart == SE_BACKUP_PRIVILEGE)
195  {
196  TokenFlag = TOKEN_HAS_BACKUP_PRIVILEGE;
197  }
198  else if (Token->Privileges[Index].Luid.LowPart == SE_RESTORE_PRIVILEGE)
199  {
200  TokenFlag = TOKEN_HAS_RESTORE_PRIVILEGE;
201  }
202  else if (Token->Privileges[Index].Luid.LowPart == SE_IMPERSONATE_PRIVILEGE)
203  {
205  }
206  else
207  {
208  /* Nothing to do */
209  return;
210  }
211 
212  /* Check if the specified privilege is enabled */
213  if (Token->Privileges[Index].Attributes & SE_PRIVILEGE_ENABLED)
214  {
215  /* It is enabled, so set the flag */
216  Token->TokenFlags |= TokenFlag;
217  }
218  else
219  {
220  /* Is is disabled, so remove the flag */
221  Token->TokenFlags &= ~TokenFlag;
222  }
223 }
224 
225 static
226 VOID
229 {
230  ULONG i;
231 
232  /* Loop all privileges */
233  for (i = 0; i < Token->PrivilegeCount; i++)
234  {
235  /* Updates the flags dor this privilege */
237  }
238 }
239 
240 static
241 VOID
244  _In_ ULONG Index)
245 {
246  ULONG MoveCount;
247  ASSERT(Index < Token->PrivilegeCount);
248 
249  /* Calculate the number of trailing privileges */
250  MoveCount = Token->PrivilegeCount - Index - 1;
251  if (MoveCount != 0)
252  {
253  /* Move them one location ahead */
254  RtlMoveMemory(&Token->Privileges[Index],
255  &Token->Privileges[Index + 1],
256  MoveCount * sizeof(LUID_AND_ATTRIBUTES));
257  }
258 
259  /* Update privilege count */
260  Token->PrivilegeCount--;
261 }
262 
263 VOID
264 NTAPI
266 {
268 }
269 
270 NTSTATUS
271 NTAPI
273  PVOID Src)
274 {
276  return STATUS_NOT_IMPLEMENTED;
277 }
278 
279 NTSTATUS
280 NTAPI
283  _In_ PACCESS_TOKEN NewAccessToken,
284  _Out_ PACCESS_TOKEN* OldAccessToken)
285 {
286  PTOKEN OldToken;
287  PTOKEN NewToken = (PTOKEN)NewAccessToken;
288 
289  PAGED_CODE();
290 
291  if (NewToken->TokenType != TokenPrimary)
292  return STATUS_BAD_TOKEN_TYPE;
293 
294  if (NewToken->TokenInUse)
295  {
298 
299  /* Maybe we're trying to set the same token */
300  OldToken = PsReferencePrimaryToken(Process);
301  if (OldToken == NewToken)
302  {
303  /* So it's a nop. */
304  *OldAccessToken = OldToken;
305  return STATUS_SUCCESS;
306  }
307 
308  Status = SepCompareTokens(OldToken, NewToken, &IsEqual);
309  if (!NT_SUCCESS(Status))
310  {
311  PsDereferencePrimaryToken(OldToken);
312  *OldAccessToken = NULL;
313  return Status;
314  }
315 
316  if (!IsEqual)
317  {
318  PsDereferencePrimaryToken(OldToken);
319  *OldAccessToken = NULL;
321  }
322  /* Silently return STATUS_SUCCESS but do not set the new token,
323  * as it's already in use elsewhere. */
324  *OldAccessToken = OldToken;
325  return STATUS_SUCCESS;
326  }
327 
328  /* Lock the new token */
330 
331  /* Mark new token in use */
332  NewToken->TokenInUse = TRUE;
333 
334  // TODO: Set a correct SessionId for NewToken
335 
336  /* Unlock the new token */
337  SepReleaseTokenLock(NewToken);
338 
339  /* Reference the new token */
340  ObReferenceObject(NewToken);
341 
342  /* Replace the old with the new */
343  OldToken = ObFastReplaceObject(&Process->Token, NewToken);
344 
345  /* Lock the old token */
347 
348  /* Mark the old token as free */
349  OldToken->TokenInUse = FALSE;
350 
351  /* Unlock the old token */
352  SepReleaseTokenLock(OldToken);
353 
354  *OldAccessToken = (PACCESS_TOKEN)OldToken;
355  return STATUS_SUCCESS;
356 }
357 
358 VOID
359 NTAPI
361 {
362  PTOKEN OldToken;
363 
364  /* Remove the Token */
365  OldToken = ObFastReplaceObject(&Process->Token, NULL);
366 
367  /* Mark the Old Token as free */
368  OldToken->TokenInUse = FALSE;
369 
370  /* Dereference the Token */
371  ObDereferenceObject(OldToken);
372 }
373 
374 static ULONG
377 {
378  ULONG i;
379  ULONG uLength;
380 
381  PAGED_CODE();
382 
383  uLength = Count * sizeof(SID_AND_ATTRIBUTES);
384  for (i = 0; i < Count; i++)
385  uLength += RtlLengthSid(Src[i].Sid);
386 
387  return uLength;
388 }
389 
390 
391 static NTSTATUS
393  _In_ PTOKEN Token,
395  _In_opt_ PSID DefaultOwner,
396  _Out_opt_ PULONG PrimaryGroupIndex,
397  _Out_opt_ PULONG DefaultOwnerIndex)
398 {
399  ULONG i;
400 
401  /* We should return at least a search result */
402  if (!PrimaryGroupIndex && !DefaultOwnerIndex)
404 
405  if (PrimaryGroupIndex)
406  {
407  /* Initialize with an invalid index */
408  // Token->PrimaryGroup = NULL;
409  *PrimaryGroupIndex = Token->UserAndGroupCount;
410  }
411 
412  if (DefaultOwnerIndex)
413  {
414  if (DefaultOwner)
415  {
416  /* An owner is specified: check whether this is actually the user */
417  if (RtlEqualSid(Token->UserAndGroups[0].Sid, DefaultOwner))
418  {
419  /*
420  * It's the user (first element in array): set it
421  * as the owner and stop the search for it.
422  */
423  *DefaultOwnerIndex = 0;
424  DefaultOwnerIndex = NULL;
425  }
426  else
427  {
428  /* An owner is specified: initialize with an invalid index */
429  *DefaultOwnerIndex = Token->UserAndGroupCount;
430  }
431  }
432  else
433  {
434  /*
435  * No owner specified: set the user (first element in array)
436  * as the owner and stop the search for it.
437  */
438  *DefaultOwnerIndex = 0;
439  DefaultOwnerIndex = NULL;
440  }
441  }
442 
443  /* Validate and set the primary group and default owner indices */
444  for (i = 0; i < Token->UserAndGroupCount; i++)
445  {
446  /* Stop the search if we have found what we searched for */
447  if (!PrimaryGroupIndex && !DefaultOwnerIndex)
448  break;
449 
450  if (DefaultOwnerIndex && DefaultOwner &&
451  RtlEqualSid(Token->UserAndGroups[i].Sid, DefaultOwner) &&
452  (Token->UserAndGroups[i].Attributes & SE_GROUP_OWNER))
453  {
454  /* Owner is found, stop the search for it */
455  *DefaultOwnerIndex = i;
456  DefaultOwnerIndex = NULL;
457  }
458 
459  if (PrimaryGroupIndex &&
460  RtlEqualSid(Token->UserAndGroups[i].Sid, PrimaryGroup))
461  {
462  /* Primary group is found, stop the search for it */
463  // Token->PrimaryGroup = Token->UserAndGroups[i].Sid;
464  *PrimaryGroupIndex = i;
465  PrimaryGroupIndex = NULL;
466  }
467  }
468 
469  if (DefaultOwnerIndex)
470  {
471  if (*DefaultOwnerIndex == Token->UserAndGroupCount)
472  return STATUS_INVALID_OWNER;
473  }
474 
475  if (PrimaryGroupIndex)
476  {
477  if (*PrimaryGroupIndex == Token->UserAndGroupCount)
478  // if (Token->PrimaryGroup == NULL)
480  }
481 
482  return STATUS_SUCCESS;
483 }
484 
485 
486 NTSTATUS
487 NTAPI
489  _In_ PTOKEN Token,
495  _Out_ PTOKEN* NewAccessToken)
496 {
498  PTOKEN AccessToken;
499  PVOID EndMem;
500  ULONG VariableLength;
501  ULONG TotalSize;
502 
503  PAGED_CODE();
504 
505  /* Compute how much size we need to allocate for the token */
506  VariableLength = Token->VariableLength;
507  TotalSize = FIELD_OFFSET(TOKEN, VariablePart) + VariableLength;
508 
512  PreviousMode,
513  NULL,
514  TotalSize,
515  0,
516  0,
517  (PVOID*)&AccessToken);
518  if (!NT_SUCCESS(Status))
519  {
520  DPRINT1("ObCreateObject() failed (Status 0x%lx)\n", Status);
521  return Status;
522  }
523 
524  /* Zero out the buffer and initialize the token */
525  RtlZeroMemory(AccessToken, TotalSize);
526 
527  ExAllocateLocallyUniqueId(&AccessToken->TokenId);
528 
529  AccessToken->TokenType = TokenType;
530  AccessToken->ImpersonationLevel = Level;
531 
532  /* Initialise the lock for the access token */
533  Status = SepCreateTokenLock(AccessToken);
534  if (!NT_SUCCESS(Status))
535  {
536  ObDereferenceObject(AccessToken);
537  return Status;
538  }
539 
540  /* Copy the immutable fields */
541  RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
542  &Token->TokenSource.SourceIdentifier);
543  RtlCopyMemory(AccessToken->TokenSource.SourceName,
544  Token->TokenSource.SourceName,
545  sizeof(Token->TokenSource.SourceName));
546 
547  AccessToken->AuthenticationId = Token->AuthenticationId;
548  AccessToken->ParentTokenId = Token->ParentTokenId;
549  AccessToken->ExpirationTime = Token->ExpirationTime;
550  AccessToken->OriginatingLogonSession = Token->OriginatingLogonSession;
551 
552  /* Lock the source token and copy the mutable fields */
554 
555  AccessToken->SessionId = Token->SessionId;
556  RtlCopyLuid(&AccessToken->ModifiedId, &Token->ModifiedId);
557 
558  AccessToken->TokenFlags = Token->TokenFlags & ~TOKEN_SESSION_NOT_REFERENCED;
559 
560  /* Copy and reference the logon session */
561  // RtlCopyLuid(&AccessToken->AuthenticationId, &Token->AuthenticationId);
562  Status = SepRmReferenceLogonSession(&AccessToken->AuthenticationId);
563  if (!NT_SUCCESS(Status))
564  {
565  /* No logon session could be found, bail out */
566  DPRINT1("SepRmReferenceLogonSession() failed (Status 0x%lx)\n", Status);
567  /* Set the flag for proper cleanup by the delete procedure */
568  AccessToken->TokenFlags |= TOKEN_SESSION_NOT_REFERENCED;
569  goto Quit;
570  }
571 
572  /* Assign the data that reside in the TOKEN's variable information area */
573  AccessToken->VariableLength = VariableLength;
574  EndMem = (PVOID)&AccessToken->VariablePart;
575 
576  /* Copy the privileges */
577  AccessToken->PrivilegeCount = 0;
578  AccessToken->Privileges = NULL;
579  if (Token->Privileges && (Token->PrivilegeCount > 0))
580  {
581  ULONG PrivilegesLength = Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
582  PrivilegesLength = ALIGN_UP_BY(PrivilegesLength, sizeof(PVOID));
583 
584  ASSERT(VariableLength >= PrivilegesLength);
585 
586  AccessToken->PrivilegeCount = Token->PrivilegeCount;
587  AccessToken->Privileges = EndMem;
588  EndMem = (PVOID)((ULONG_PTR)EndMem + PrivilegesLength);
589  VariableLength -= PrivilegesLength;
590 
591  RtlCopyMemory(AccessToken->Privileges,
592  Token->Privileges,
593  AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
594  }
595 
596  /* Copy the user and groups */
597  AccessToken->UserAndGroupCount = 0;
598  AccessToken->UserAndGroups = NULL;
599  if (Token->UserAndGroups && (Token->UserAndGroupCount > 0))
600  {
601  AccessToken->UserAndGroupCount = Token->UserAndGroupCount;
602  AccessToken->UserAndGroups = EndMem;
603  EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
604  VariableLength -= ((ULONG_PTR)EndMem - (ULONG_PTR)AccessToken->UserAndGroups);
605 
606  Status = RtlCopySidAndAttributesArray(AccessToken->UserAndGroupCount,
607  Token->UserAndGroups,
608  VariableLength,
609  AccessToken->UserAndGroups,
610  EndMem,
611  &EndMem,
612  &VariableLength);
613  if (!NT_SUCCESS(Status))
614  {
615  DPRINT1("RtlCopySidAndAttributesArray(UserAndGroups) failed (Status 0x%lx)\n", Status);
616  goto Quit;
617  }
618  }
619 
620 #if 1
621  {
622  ULONG PrimaryGroupIndex;
623 
624  /* Find the token primary group */
626  Token->PrimaryGroup,
627  NULL,
628  &PrimaryGroupIndex,
629  NULL);
630  if (!NT_SUCCESS(Status))
631  {
632  DPRINT1("SepFindPrimaryGroupAndDefaultOwner failed (Status 0x%lx)\n", Status);
633  goto Quit;
634  }
635  AccessToken->PrimaryGroup = AccessToken->UserAndGroups[PrimaryGroupIndex].Sid;
636  }
637 #else
638  AccessToken->PrimaryGroup = (PVOID)((ULONG_PTR)AccessToken + (ULONG_PTR)Token->PrimaryGroup - (ULONG_PTR)Token->UserAndGroups);
639 #endif
640  AccessToken->DefaultOwnerIndex = Token->DefaultOwnerIndex;
641 
642  /* Copy the restricted SIDs */
643  AccessToken->RestrictedSidCount = 0;
644  AccessToken->RestrictedSids = NULL;
645  if (Token->RestrictedSids && (Token->RestrictedSidCount > 0))
646  {
647  AccessToken->RestrictedSidCount = Token->RestrictedSidCount;
648  AccessToken->RestrictedSids = EndMem;
649  EndMem = &AccessToken->RestrictedSids[AccessToken->RestrictedSidCount];
650  VariableLength -= ((ULONG_PTR)EndMem - (ULONG_PTR)AccessToken->RestrictedSids);
651 
652  Status = RtlCopySidAndAttributesArray(AccessToken->RestrictedSidCount,
653  Token->RestrictedSids,
654  VariableLength,
655  AccessToken->RestrictedSids,
656  EndMem,
657  &EndMem,
658  &VariableLength);
659  if (!NT_SUCCESS(Status))
660  {
661  DPRINT1("RtlCopySidAndAttributesArray(RestrictedSids) failed (Status 0x%lx)\n", Status);
662  goto Quit;
663  }
664  }
665 
666 
667  //
668  // FIXME: Implement the "EffectiveOnly" option, that removes all
669  // the disabled parts (privileges and groups) of the token.
670  //
671 
672 
673  //
674  // NOTE: So far our dynamic area only contains
675  // the default dacl, so this makes the following
676  // code pretty simple. The day where it stores
677  // other data, the code will require adaptations.
678  //
679 
680  /* Now allocate the TOKEN's dynamic information area and set the data */
681  AccessToken->DynamicAvailable = 0; // Unused memory in the dynamic area.
682  AccessToken->DynamicPart = NULL;
683  if (Token->DynamicPart && Token->DefaultDacl)
684  {
685  AccessToken->DynamicPart = ExAllocatePoolWithTag(PagedPool,
686  Token->DefaultDacl->AclSize,
688  if (AccessToken->DynamicPart == NULL)
689  {
691  goto Quit;
692  }
693  EndMem = (PVOID)AccessToken->DynamicPart;
694 
695  AccessToken->DefaultDacl = EndMem;
696 
697  RtlCopyMemory(AccessToken->DefaultDacl,
698  Token->DefaultDacl,
699  Token->DefaultDacl->AclSize);
700  }
701 
702  /* Unlock the source token */
704 
705  /* Return the token */
706  *NewAccessToken = AccessToken;
708 
709 Quit:
710  if (!NT_SUCCESS(Status))
711  {
712  /* Unlock the source token */
714 
715  /* Dereference the token, the delete procedure will clean it up */
716  ObDereferenceObject(AccessToken);
717  }
718 
719  return Status;
720 }
721 
722 NTSTATUS
723 NTAPI
725  OUT PTOKEN *Token,
726  IN BOOLEAN InUse,
728 {
729  PTOKEN NewToken;
732 
733  /* Initialize the attributes and duplicate it */
735  Status = SepDuplicateToken(ParentToken,
737  FALSE,
738  TokenPrimary,
739  ParentToken->ImpersonationLevel,
740  KernelMode,
741  &NewToken);
742  if (NT_SUCCESS(Status))
743  {
744  /* Insert it */
745  Status = ObInsertObject(NewToken,
746  NULL,
747  0,
748  0,
749  NULL,
750  NULL);
751  if (NT_SUCCESS(Status))
752  {
753  /* Set the session ID */
754  NewToken->SessionId = SessionId;
755  NewToken->TokenInUse = InUse;
756 
757  /* Return the token */
758  *Token = NewToken;
759  }
760  }
761 
762  /* Return status */
763  return Status;
764 }
765 
766 NTSTATUS
767 NTAPI
770 {
771  PTOKEN ProcessToken;
772  LUID ProcessTokenId, CallerParentId;
773 
774  /* Assume failure */
775  *IsChild = FALSE;
776 
777  /* Reference the process token */
779  if (!ProcessToken)
780  return STATUS_UNSUCCESSFUL;
781 
782  /* Get its token ID */
783  ProcessTokenId = ProcessToken->TokenId;
784 
785  /* Dereference the token */
787 
788  /* Get our parent token ID */
789  CallerParentId = Token->ParentTokenId;
790 
791  /* Compare the token IDs */
792  if (RtlEqualLuid(&CallerParentId, &ProcessTokenId))
793  *IsChild = TRUE;
794 
795  /* Return success */
796  return STATUS_SUCCESS;
797 }
798 
799 NTSTATUS
800 NTAPI
802  OUT PBOOLEAN IsSibling)
803 {
804  PTOKEN ProcessToken;
805  LUID ProcessParentId, ProcessAuthId;
806  LUID CallerParentId, CallerAuthId;
807 
808  /* Assume failure */
809  *IsSibling = FALSE;
810 
811  /* Reference the process token */
813  if (!ProcessToken)
814  return STATUS_UNSUCCESSFUL;
815 
816  /* Get its parent and authentication IDs */
817  ProcessParentId = ProcessToken->ParentTokenId;
818  ProcessAuthId = ProcessToken->AuthenticationId;
819 
820  /* Dereference the token */
822 
823  /* Get our parent and authentication IDs */
824  CallerParentId = Token->ParentTokenId;
825  CallerAuthId = Token->AuthenticationId;
826 
827  /* Compare the token IDs */
828  if (RtlEqualLuid(&CallerParentId, &ProcessParentId) &&
829  RtlEqualLuid(&CallerAuthId, &ProcessAuthId))
830  {
831  *IsSibling = TRUE;
832  }
833 
834  /* Return success */
835  return STATUS_SUCCESS;
836 }
837 
838 NTSTATUS
839 NTAPI
843  OUT PACCESS_TOKEN* NewToken)
844 {
847 
848  PAGED_CODE();
849 
851  NULL,
852  0,
853  NULL,
854  NULL);
855 
858  FALSE,
860  Level,
861  PreviousMode,
862  (PTOKEN*)NewToken);
863 
864  return Status;
865 }
866 
867 VOID
868 NTAPI
870 {
871  PTOKEN AccessToken = (PTOKEN)ObjectBody;
872 
873  DPRINT("SepDeleteToken()\n");
874 
875  /* Dereference the logon session */
876  if ((AccessToken->TokenFlags & TOKEN_SESSION_NOT_REFERENCED) == 0)
878 
879  /* Delete the token lock */
880  if (AccessToken->TokenLock)
881  SepDeleteTokenLock(AccessToken);
882 
883  /* Delete the dynamic information area */
884  if (AccessToken->DynamicPart)
886 }
887 
888 
889 CODE_SEG("INIT")
890 VOID
891 NTAPI
893 {
895  OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
896 
897  DPRINT("Creating Token Object Type\n");
898 
899  /* Initialize the Token type */
900  RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
901  RtlInitUnicodeString(&Name, L"Token");
902  ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
903  ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
904  ObjectTypeInitializer.SecurityRequired = TRUE;
905  ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(TOKEN);
906  ObjectTypeInitializer.GenericMapping = SepTokenMapping;
907  ObjectTypeInitializer.PoolType = PagedPool;
908  ObjectTypeInitializer.ValidAccessMask = TOKEN_ALL_ACCESS;
909  ObjectTypeInitializer.UseDefaultObject = TRUE;
910  ObjectTypeInitializer.DeleteProcedure = SepDeleteToken;
911  ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &SeTokenObjectType);
912 }
913 
914 VOID
915 NTAPI
917  IN PTOKEN Token)
918 {
919  PAGED_CODE();
920 
921  /* Sanity checks */
922  ASSERT(Token->TokenType == TokenPrimary);
923  ASSERT(!Token->TokenInUse);
924 
925  /* Clean any previous token */
926  if (Process->Token.Object) SeDeassignPrimaryToken(Process);
927 
928  /* Set the new token */
930  Token->TokenInUse = TRUE;
932 }
933 
934 NTSTATUS
935 NTAPI
943  _In_ PLUID AuthenticationId,
944  _In_ PLARGE_INTEGER ExpirationTime,
946  _In_ ULONG GroupCount,
948  _In_ ULONG GroupsLength,
949  _In_ ULONG PrivilegeCount,
953  _In_opt_ PACL DefaultDacl,
955  _In_ BOOLEAN SystemToken)
956 {
958  PTOKEN AccessToken;
959  ULONG TokenFlags = 0;
960  ULONG PrimaryGroupIndex, DefaultOwnerIndex;
961  LUID TokenId;
962  LUID ModifiedId;
963  PVOID EndMem;
964  ULONG PrivilegesLength;
965  ULONG UserGroupsLength;
966  ULONG VariableLength;
967  ULONG TotalSize;
968  ULONG i;
969 
970  PAGED_CODE();
971 
972  /* Loop all groups */
973  for (i = 0; i < GroupCount; i++)
974  {
975  /* Check for mandatory groups */
977  {
978  /* Force them to be enabled */
980  }
981 
982  /* Check of the group is an admin group */
984  {
985  /* Remember this so we can optimize queries later */
986  TokenFlags |= TOKEN_HAS_ADMIN_GROUP;
987  }
988  }
989 
990  /* Allocate unique IDs for the token */
991  ExAllocateLocallyUniqueId(&TokenId);
992  ExAllocateLocallyUniqueId(&ModifiedId);
993 
994  /* Compute how much size we need to allocate for the token */
995 
996  /* Privileges size */
997  PrivilegesLength = PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
998  PrivilegesLength = ALIGN_UP_BY(PrivilegesLength, sizeof(PVOID));
999 
1000  /* User and groups size */
1001  UserGroupsLength = (1 + GroupCount) * sizeof(SID_AND_ATTRIBUTES);
1002  UserGroupsLength += RtlLengthSid(User->Sid);
1003  for (i = 0; i < GroupCount; i++)
1004  {
1005  UserGroupsLength += RtlLengthSid(Groups[i].Sid);
1006  }
1007  UserGroupsLength = ALIGN_UP_BY(UserGroupsLength, sizeof(PVOID));
1008 
1009  /* Add the additional groups array length */
1010  UserGroupsLength += ALIGN_UP_BY(GroupsLength, sizeof(PVOID));
1011 
1012  VariableLength = PrivilegesLength + UserGroupsLength;
1013  TotalSize = FIELD_OFFSET(TOKEN, VariablePart) + VariableLength;
1014 
1018  PreviousMode,
1019  NULL,
1020  TotalSize,
1021  0,
1022  0,
1023  (PVOID*)&AccessToken);
1024  if (!NT_SUCCESS(Status))
1025  {
1026  DPRINT1("ObCreateObject() failed (Status 0x%lx)\n", Status);
1027  return Status;
1028  }
1029 
1030  /* Zero out the buffer and initialize the token */
1031  RtlZeroMemory(AccessToken, TotalSize);
1032 
1033  RtlCopyLuid(&AccessToken->TokenId, &TokenId);
1034 
1035  AccessToken->TokenType = TokenType;
1036  AccessToken->ImpersonationLevel = ImpersonationLevel;
1037 
1038  /* Initialise the lock for the access token */
1039  Status = SepCreateTokenLock(AccessToken);
1040  if (!NT_SUCCESS(Status))
1041  goto Quit;
1042 
1043  RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
1044  &TokenSource->SourceIdentifier);
1045  RtlCopyMemory(AccessToken->TokenSource.SourceName,
1046  TokenSource->SourceName,
1047  sizeof(TokenSource->SourceName));
1048 
1049  AccessToken->ExpirationTime = *ExpirationTime;
1050  RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
1051 
1052  AccessToken->TokenFlags = TokenFlags & ~TOKEN_SESSION_NOT_REFERENCED;
1053 
1054  /* Copy and reference the logon session */
1055  RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
1056  Status = SepRmReferenceLogonSession(&AccessToken->AuthenticationId);
1057  if (!NT_SUCCESS(Status))
1058  {
1059  /* No logon session could be found, bail out */
1060  DPRINT1("SepRmReferenceLogonSession() failed (Status 0x%lx)\n", Status);
1061  /* Set the flag for proper cleanup by the delete procedure */
1062  AccessToken->TokenFlags |= TOKEN_SESSION_NOT_REFERENCED;
1063  goto Quit;
1064  }
1065 
1066  /* Assign the data that reside in the TOKEN's variable information area */
1067  AccessToken->VariableLength = VariableLength;
1068  EndMem = (PVOID)&AccessToken->VariablePart;
1069 
1070  /* Copy the privileges */
1071  AccessToken->PrivilegeCount = PrivilegeCount;
1072  AccessToken->Privileges = NULL;
1073  if (PrivilegeCount > 0)
1074  {
1075  AccessToken->Privileges = EndMem;
1076  EndMem = (PVOID)((ULONG_PTR)EndMem + PrivilegesLength);
1077  VariableLength -= PrivilegesLength;
1078 
1079  if (PreviousMode != KernelMode)
1080  {
1081  _SEH2_TRY
1082  {
1083  RtlCopyMemory(AccessToken->Privileges,
1084  Privileges,
1085  PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
1086  }
1088  {
1090  }
1091  _SEH2_END;
1092  }
1093  else
1094  {
1095  RtlCopyMemory(AccessToken->Privileges,
1096  Privileges,
1097  PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
1098  }
1099 
1100  if (!NT_SUCCESS(Status))
1101  goto Quit;
1102  }
1103 
1104  /* Update the privilege flags */
1105  SepUpdatePrivilegeFlagsToken(AccessToken);
1106 
1107  /* Copy the user and groups */
1108  AccessToken->UserAndGroupCount = 1 + GroupCount;
1109  AccessToken->UserAndGroups = EndMem;
1110  EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
1111  VariableLength -= ((ULONG_PTR)EndMem - (ULONG_PTR)AccessToken->UserAndGroups);
1112 
1114  User,
1115  VariableLength,
1116  &AccessToken->UserAndGroups[0],
1117  EndMem,
1118  &EndMem,
1119  &VariableLength);
1120  if (!NT_SUCCESS(Status))
1121  goto Quit;
1122 
1123  Status = RtlCopySidAndAttributesArray(GroupCount,
1124  Groups,
1125  VariableLength,
1126  &AccessToken->UserAndGroups[1],
1127  EndMem,
1128  &EndMem,
1129  &VariableLength);
1130  if (!NT_SUCCESS(Status))
1131  goto Quit;
1132 
1133  /* Find the token primary group and default owner */
1135  PrimaryGroup,
1136  Owner,
1137  &PrimaryGroupIndex,
1138  &DefaultOwnerIndex);
1139  if (!NT_SUCCESS(Status))
1140  {
1141  DPRINT1("SepFindPrimaryGroupAndDefaultOwner failed (Status 0x%lx)\n", Status);
1142  goto Quit;
1143  }
1144 
1145  AccessToken->PrimaryGroup = AccessToken->UserAndGroups[PrimaryGroupIndex].Sid;
1146  AccessToken->DefaultOwnerIndex = DefaultOwnerIndex;
1147 
1148  /* Now allocate the TOKEN's dynamic information area and set the data */
1149  AccessToken->DynamicAvailable = 0; // Unused memory in the dynamic area.
1150  AccessToken->DynamicPart = NULL;
1151  if (DefaultDacl != NULL)
1152  {
1153  AccessToken->DynamicPart = ExAllocatePoolWithTag(PagedPool,
1154  DefaultDacl->AclSize,
1156  if (AccessToken->DynamicPart == NULL)
1157  {
1159  goto Quit;
1160  }
1161  EndMem = (PVOID)AccessToken->DynamicPart;
1162 
1163  AccessToken->DefaultDacl = EndMem;
1164 
1165  RtlCopyMemory(AccessToken->DefaultDacl,
1166  DefaultDacl,
1167  DefaultDacl->AclSize);
1168  }
1169 
1170  /* Insert the token only if it's not the system token, otherwise return it directly */
1171  if (!SystemToken)
1172  {
1173  Status = ObInsertObject(AccessToken,
1174  NULL,
1175  DesiredAccess,
1176  0,
1177  NULL,
1178  TokenHandle);
1179  if (!NT_SUCCESS(Status))
1180  {
1181  DPRINT1("ObInsertObject() failed (Status 0x%lx)\n", Status);
1182  }
1183  }
1184  else
1185  {
1186  /* Return pointer instead of handle */
1187  *TokenHandle = (HANDLE)AccessToken;
1188  }
1189 
1190 Quit:
1191  if (!NT_SUCCESS(Status))
1192  {
1193  /* Dereference the token, the delete procedure will clean it up */
1194  ObDereferenceObject(AccessToken);
1195  }
1196 
1197  return Status;
1198 }
1199 
1200 PTOKEN
1201 NTAPI
1203 {
1205  ULONG GroupAttributes, OwnerAttributes;
1207  LARGE_INTEGER Expiration;
1208  SID_AND_ATTRIBUTES UserSid;
1209  ULONG GroupsLength;
1212  PSID Owner;
1213  ULONG i;
1214  PTOKEN Token;
1215  NTSTATUS Status;
1216 
1217  /* Don't ever expire */
1218  Expiration.QuadPart = -1;
1219 
1220  /* All groups mandatory and enabled */
1223 
1224  /* User is Local System */
1225  UserSid.Sid = SeLocalSystemSid;
1226  UserSid.Attributes = 0;
1227 
1228  /* Primary group is Local System */
1230 
1231  /* Owner is Administrators */
1233 
1234  /* Groups are Administrators, World, and Authenticated Users */
1235  Groups[0].Sid = SeAliasAdminsSid;
1236  Groups[0].Attributes = OwnerAttributes;
1237  Groups[1].Sid = SeWorldSid;
1238  Groups[1].Attributes = GroupAttributes;
1240  Groups[2].Attributes = GroupAttributes;
1241  GroupsLength = sizeof(SID_AND_ATTRIBUTES) +
1242  SeLengthSid(Groups[0].Sid) +
1243  SeLengthSid(Groups[1].Sid) +
1244  SeLengthSid(Groups[2].Sid);
1245  ASSERT(GroupsLength <= sizeof(Groups));
1246 
1247  /* Setup the privileges */
1248  i = 0;
1250  Privileges[i++].Luid = SeTcbPrivilege;
1251 
1252  Privileges[i].Attributes = 0;
1254 
1255  Privileges[i].Attributes = 0;
1257 
1260 
1263 
1264  Privileges[i].Attributes = 0;
1266 
1267  Privileges[i].Attributes = 0;
1269 
1272 
1275 
1277  Privileges[i++].Luid = SeDebugPrivilege;
1278 
1280  Privileges[i++].Luid = SeAuditPrivilege;
1281 
1282  Privileges[i].Attributes = 0;
1283  Privileges[i++].Luid = SeSecurityPrivilege;
1284 
1285  Privileges[i].Attributes = 0;
1287 
1290 
1291  Privileges[i].Attributes = 0;
1292  Privileges[i++].Luid = SeBackupPrivilege;
1293 
1294  Privileges[i].Attributes = 0;
1295  Privileges[i++].Luid = SeRestorePrivilege;
1296 
1297  Privileges[i].Attributes = 0;
1298  Privileges[i++].Luid = SeShutdownPrivilege;
1299 
1300  Privileges[i].Attributes = 0;
1302 
1305 
1306  Privileges[i].Attributes = 0;
1308  ASSERT(i == 20);
1309 
1310  /* Setup the object attributes */
1313 
1314  /* Create the token */
1316  KernelMode,
1317  0,
1319  TokenPrimary,
1322  &Expiration,
1323  &UserSid,
1324  3,
1325  Groups,
1326  GroupsLength,
1327  20,
1328  Privileges,
1329  Owner,
1330  PrimaryGroup,
1333  TRUE);
1335 
1336  /* Return the token */
1337  return Token;
1338 }
1339 
1340 /* PUBLIC FUNCTIONS ***********************************************************/
1341 
1342 /*
1343  * @unimplemented
1344  */
1345 NTSTATUS
1346 NTAPI
1348  IN ULONG Flags,
1349  IN PTOKEN_GROUPS SidsToDisable OPTIONAL,
1350  IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL,
1351  IN PTOKEN_GROUPS RestrictedSids OPTIONAL,
1352  OUT PACCESS_TOKEN * FilteredToken)
1353 {
1354  UNIMPLEMENTED;
1355  return STATUS_NOT_IMPLEMENTED;
1356 }
1357 
1358 /*
1359  * @implemented
1360  *
1361  * NOTE: SeQueryInformationToken is just NtQueryInformationToken without all
1362  * the bells and whistles needed for user-mode buffer access protection.
1363  */
1364 NTSTATUS
1365 NTAPI
1368  OUT PVOID *TokenInformation)
1369 {
1370  NTSTATUS Status;
1371  PTOKEN Token = (PTOKEN)AccessToken;
1373  union
1374  {
1375  PSID PSid;
1376  ULONG Ulong;
1377  } Unused;
1378 
1379  PAGED_CODE();
1380 
1382  {
1383  DPRINT1("SeQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
1385  }
1386 
1387  // TODO: Lock the token
1388 
1389  switch (TokenInformationClass)
1390  {
1391  case TokenUser:
1392  {
1393  PTOKEN_USER tu;
1394 
1395  DPRINT("SeQueryInformationToken(TokenUser)\n");
1396  RequiredLength = sizeof(TOKEN_USER) +
1397  RtlLengthSid(Token->UserAndGroups[0].Sid);
1398 
1399  /* Allocate the output buffer */
1401  if (tu == NULL)
1402  {
1404  break;
1405  }
1406 
1408  &Token->UserAndGroups[0],
1409  RequiredLength - sizeof(TOKEN_USER),
1410  &tu->User,
1411  (PSID)(tu + 1),
1412  &Unused.PSid,
1413  &Unused.Ulong);
1414 
1415  /* Return the structure */
1416  *TokenInformation = tu;
1418  break;
1419  }
1420 
1421  case TokenGroups:
1422  {
1423  PTOKEN_GROUPS tg;
1424  ULONG SidLen;
1425  PSID Sid;
1426 
1427  DPRINT("SeQueryInformationToken(TokenGroups)\n");
1428  RequiredLength = sizeof(tg->GroupCount) +
1429  RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]);
1430 
1431  SidLen = RequiredLength - sizeof(tg->GroupCount) -
1432  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES));
1433 
1434  /* Allocate the output buffer */
1436  if (tg == NULL)
1437  {
1439  break;
1440  }
1441 
1442  Sid = (PSID)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
1443  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)));
1444 
1445  tg->GroupCount = Token->UserAndGroupCount - 1;
1446  Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
1447  &Token->UserAndGroups[1],
1448  SidLen,
1449  &tg->Groups[0],
1450  Sid,
1451  &Unused.PSid,
1452  &Unused.Ulong);
1453 
1454  /* Return the structure */
1455  *TokenInformation = tg;
1457  break;
1458  }
1459 
1460  case TokenPrivileges:
1461  {
1463 
1464  DPRINT("SeQueryInformationToken(TokenPrivileges)\n");
1465  RequiredLength = sizeof(tp->PrivilegeCount) +
1466  (Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
1467 
1468  /* Allocate the output buffer */
1470  if (tp == NULL)
1471  {
1473  break;
1474  }
1475 
1476  tp->PrivilegeCount = Token->PrivilegeCount;
1477  RtlCopyLuidAndAttributesArray(Token->PrivilegeCount,
1478  Token->Privileges,
1479  &tp->Privileges[0]);
1480 
1481  /* Return the structure */
1482  *TokenInformation = tp;
1484  break;
1485  }
1486 
1487  case TokenOwner:
1488  {
1489  PTOKEN_OWNER to;
1490  ULONG SidLen;
1491 
1492  DPRINT("SeQueryInformationToken(TokenOwner)\n");
1493  SidLen = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
1494  RequiredLength = sizeof(TOKEN_OWNER) + SidLen;
1495 
1496  /* Allocate the output buffer */
1498  if (to == NULL)
1499  {
1501  break;
1502  }
1503 
1504  to->Owner = (PSID)(to + 1);
1505  Status = RtlCopySid(SidLen,
1506  to->Owner,
1507  Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
1508 
1509  /* Return the structure */
1510  *TokenInformation = to;
1512  break;
1513  }
1514 
1515  case TokenPrimaryGroup:
1516  {
1518  ULONG SidLen;
1519 
1520  DPRINT("SeQueryInformationToken(TokenPrimaryGroup)\n");
1521  SidLen = RtlLengthSid(Token->PrimaryGroup);
1522  RequiredLength = sizeof(TOKEN_PRIMARY_GROUP) + SidLen;
1523 
1524  /* Allocate the output buffer */
1526  if (tpg == NULL)
1527  {
1529  break;
1530  }
1531 
1532  tpg->PrimaryGroup = (PSID)(tpg + 1);
1533  Status = RtlCopySid(SidLen,
1534  tpg->PrimaryGroup,
1535  Token->PrimaryGroup);
1536 
1537  /* Return the structure */
1538  *TokenInformation = tpg;
1540  break;
1541  }
1542 
1543  case TokenDefaultDacl:
1544  {
1545  PTOKEN_DEFAULT_DACL tdd;
1546 
1547  DPRINT("SeQueryInformationToken(TokenDefaultDacl)\n");
1549 
1550  if (Token->DefaultDacl != NULL)
1551  RequiredLength += Token->DefaultDacl->AclSize;
1552 
1553  /* Allocate the output buffer */
1555  if (tdd == NULL)
1556  {
1558  break;
1559  }
1560 
1561  if (Token->DefaultDacl != NULL)
1562  {
1563  tdd->DefaultDacl = (PACL)(tdd + 1);
1565  Token->DefaultDacl,
1566  Token->DefaultDacl->AclSize);
1567  }
1568  else
1569  {
1570  tdd->DefaultDacl = NULL;
1571  }
1572 
1573  /* Return the structure */
1574  *TokenInformation = tdd;
1576  break;
1577  }
1578 
1579  case TokenSource:
1580  {
1581  PTOKEN_SOURCE ts;
1582 
1583  DPRINT("SeQueryInformationToken(TokenSource)\n");
1584  RequiredLength = sizeof(TOKEN_SOURCE);
1585 
1586  /* Allocate the output buffer */
1588  if (ts == NULL)
1589  {
1591  break;
1592  }
1593 
1594  *ts = Token->TokenSource;
1595 
1596  /* Return the structure */
1597  *TokenInformation = ts;
1599  break;
1600  }
1601 
1602  case TokenType:
1603  {
1604  PTOKEN_TYPE tt;
1605 
1606  DPRINT("SeQueryInformationToken(TokenType)\n");
1607  RequiredLength = sizeof(TOKEN_TYPE);
1608 
1609  /* Allocate the output buffer */
1611  if (tt == NULL)
1612  {
1614  break;
1615  }
1616 
1617  *tt = Token->TokenType;
1618 
1619  /* Return the structure */
1620  *TokenInformation = tt;
1622  break;
1623  }
1624 
1626  {
1628 
1629  DPRINT("SeQueryInformationToken(TokenImpersonationLevel)\n");
1631 
1632  /* Fail if the token is not an impersonation token */
1633  if (Token->TokenType != TokenImpersonation)
1634  {
1636  break;
1637  }
1638 
1639  /* Allocate the output buffer */
1641  if (sil == NULL)
1642  {
1644  break;
1645  }
1646 
1647  *sil = Token->ImpersonationLevel;
1648 
1649  /* Return the structure */
1650  *TokenInformation = sil;
1652  break;
1653  }
1654 
1655  case TokenStatistics:
1656  {
1658 
1659  DPRINT("SeQueryInformationToken(TokenStatistics)\n");
1660  RequiredLength = sizeof(TOKEN_STATISTICS);
1661 
1662  /* Allocate the output buffer */
1664  if (ts == NULL)
1665  {
1667  break;
1668  }
1669 
1670  ts->TokenId = Token->TokenId;
1671  ts->AuthenticationId = Token->AuthenticationId;
1672  ts->ExpirationTime = Token->ExpirationTime;
1673  ts->TokenType = Token->TokenType;
1674  ts->ImpersonationLevel = Token->ImpersonationLevel;
1675  ts->DynamicCharged = Token->DynamicCharged;
1676  ts->DynamicAvailable = Token->DynamicAvailable;
1677  ts->GroupCount = Token->UserAndGroupCount - 1;
1678  ts->PrivilegeCount = Token->PrivilegeCount;
1679  ts->ModifiedId = Token->ModifiedId;
1680 
1681  /* Return the structure */
1682  *TokenInformation = ts;
1684  break;
1685  }
1686 
1687 /*
1688  * The following 4 cases are only implemented in NtQueryInformationToken
1689  */
1690 #if 0
1691 
1692  case TokenOrigin:
1693  {
1694  PTOKEN_ORIGIN to;
1695 
1696  DPRINT("SeQueryInformationToken(TokenOrigin)\n");
1697  RequiredLength = sizeof(TOKEN_ORIGIN);
1698 
1699  /* Allocate the output buffer */
1701  if (to == NULL)
1702  {
1704  break;
1705  }
1706 
1708  &Token->AuthenticationId);
1709 
1710  /* Return the structure */
1711  *TokenInformation = to;
1713  break;
1714  }
1715 
1717  DPRINT1("SeQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1719  break;
1720 
1721  case TokenRestrictedSids:
1722  {
1723  PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
1724  ULONG SidLen;
1725  PSID Sid;
1726 
1727  DPRINT("SeQueryInformationToken(TokenRestrictedSids)\n");
1728  RequiredLength = sizeof(tg->GroupCount) +
1729  RtlLengthSidAndAttributes(Token->RestrictedSidCount, Token->RestrictedSids);
1730 
1731  SidLen = RequiredLength - sizeof(tg->GroupCount) -
1732  (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES));
1733 
1734  /* Allocate the output buffer */
1736  if (tg == NULL)
1737  {
1739  break;
1740  }
1741 
1742  Sid = (PSID)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
1743  (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)));
1744 
1745  tg->GroupCount = Token->RestrictedSidCount;
1746  Status = RtlCopySidAndAttributesArray(Token->RestrictedSidCount,
1747  Token->RestrictedSids,
1748  SidLen,
1749  &tg->Groups[0],
1750  Sid,
1751  &Unused.PSid,
1752  &Unused.Ulong);
1753 
1754  /* Return the structure */
1755  *TokenInformation = tg;
1757  break;
1758  }
1759 
1760  case TokenSandBoxInert:
1761  DPRINT1("SeQueryInformationToken(TokenSandboxInert) not implemented\n");
1763  break;
1764 
1765 #endif
1766 
1767  case TokenSessionId:
1768  {
1769  DPRINT("SeQueryInformationToken(TokenSessionId)\n");
1770  Status = SeQuerySessionIdToken(Token, (PULONG)TokenInformation);
1771  break;
1772  }
1773 
1774  default:
1775  DPRINT1("SeQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
1777  break;
1778  }
1779 
1780  return Status;
1781 }
1782 
1783 /*
1784  * @implemented
1785  */
1786 NTSTATUS
1787 NTAPI
1789  IN PULONG pSessionId)
1790 {
1791  PAGED_CODE();
1792 
1793  /* Lock the token */
1795 
1796  *pSessionId = ((PTOKEN)Token)->SessionId;
1797 
1798  /* Unlock the token */
1800 
1801  return STATUS_SUCCESS;
1802 }
1803 
1804 /*
1805  * @implemented
1806  */
1807 NTSTATUS
1808 NTAPI
1810  OUT PLUID LogonId)
1811 {
1812  PAGED_CODE();
1813 
1814  *LogonId = ((PTOKEN)Token)->AuthenticationId;
1815 
1816  return STATUS_SUCCESS;
1817 }
1818 
1819 
1820 /*
1821  * @implemented
1822  */
1824 NTAPI
1826 {
1827  PAGED_CODE();
1828 
1829  return ((PTOKEN)Token)->ImpersonationLevel;
1830 }
1831 
1832 
1833 /*
1834  * @implemented
1835  */
1838 {
1839  PAGED_CODE();
1840 
1841  return ((PTOKEN)Token)->TokenType;
1842 }
1843 
1844 
1845 /*
1846  * @implemented
1847  */
1848 BOOLEAN
1849 NTAPI
1851 {
1852  PAGED_CODE();
1853 
1854  // NOTE: Win7+ instead really checks the list of groups in the token
1855  // (since TOKEN_HAS_ADMIN_GROUP == TOKEN_WRITE_RESTRICTED ...)
1856  return (((PTOKEN)Token)->TokenFlags & TOKEN_HAS_ADMIN_GROUP) != 0;
1857 }
1858 
1859 /*
1860  * @implemented
1861  */
1862 BOOLEAN
1863 NTAPI
1865 {
1866  PAGED_CODE();
1867 
1868  return (((PTOKEN)Token)->TokenFlags & TOKEN_IS_RESTRICTED) != 0;
1869 }
1870 
1871 /*
1872  * @implemented
1873  * @note First introduced in NT 5.1 SP2 x86 (5.1.2600.2622), absent in NT 5.2,
1874  * then finally re-introduced in Vista+.
1875  */
1876 BOOLEAN
1877 NTAPI
1879 {
1880  PAGED_CODE();
1881 
1882  // NOTE: NT 5.1 SP2 x86 checks the SE_BACKUP_PRIVILEGES_CHECKED flag
1883  // while Vista+ checks the TOKEN_WRITE_RESTRICTED flag as one expects.
1884  return (((PTOKEN)Token)->TokenFlags & SE_BACKUP_PRIVILEGES_CHECKED) != 0;
1885 }
1886 
1887 /* SYSTEM CALLS ***************************************************************/
1888 
1889 /*
1890  * @implemented
1891  */
1894 NTSTATUS
1895 NTAPI
1900  PVOID TokenInformation,
1903 {
1904  NTSTATUS Status;
1906  PTOKEN Token;
1908  union
1909  {
1910  PSID PSid;
1911  ULONG Ulong;
1912  } Unused;
1913 
1914  PAGED_CODE();
1915 
1917 
1918  /* Check buffers and class validity */
1922  TokenInformation,
1924  ReturnLength,
1925  NULL,
1926  PreviousMode);
1927  if (!NT_SUCCESS(Status))
1928  {
1929  DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status);
1930  return Status;
1931  }
1932 
1936  PreviousMode,
1937  (PVOID*)&Token,
1938  NULL);
1939  if (NT_SUCCESS(Status))
1940  {
1941  /* Lock the token */
1943 
1944  switch (TokenInformationClass)
1945  {
1946  case TokenUser:
1947  {
1948  PTOKEN_USER tu = (PTOKEN_USER)TokenInformation;
1949 
1950  DPRINT("NtQueryInformationToken(TokenUser)\n");
1951  RequiredLength = sizeof(TOKEN_USER) +
1952  RtlLengthSid(Token->UserAndGroups[0].Sid);
1953 
1954  _SEH2_TRY
1955  {
1957  {
1959  &Token->UserAndGroups[0],
1960  RequiredLength - sizeof(TOKEN_USER),
1961  &tu->User,
1962  (PSID)(tu + 1),
1963  &Unused.PSid,
1964  &Unused.Ulong);
1965  }
1966  else
1967  {
1969  }
1970 
1971  if (ReturnLength != NULL)
1972  {
1974  }
1975  }
1977  {
1979  }
1980  _SEH2_END;
1981 
1982  break;
1983  }
1984 
1985  case TokenGroups:
1986  {
1987  PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
1988 
1989  DPRINT("NtQueryInformationToken(TokenGroups)\n");
1990  RequiredLength = sizeof(tg->GroupCount) +
1991  RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]);
1992 
1993  _SEH2_TRY
1994  {
1996  {
1997  ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
1998  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES));
1999  PSID Sid = (PSID_AND_ATTRIBUTES)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
2000  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)));
2001 
2002  tg->GroupCount = Token->UserAndGroupCount - 1;
2003  Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
2004  &Token->UserAndGroups[1],
2005  SidLen,
2006  &tg->Groups[0],
2007  Sid,
2008  &Unused.PSid,
2009  &Unused.Ulong);
2010  }
2011  else
2012  {
2014  }
2015 
2016  if (ReturnLength != NULL)
2017  {
2019  }
2020  }
2022  {
2024  }
2025  _SEH2_END;
2026 
2027  break;
2028  }
2029 
2030  case TokenPrivileges:
2031  {
2032  PTOKEN_PRIVILEGES tp = (PTOKEN_PRIVILEGES)TokenInformation;
2033 
2034  DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
2035  RequiredLength = sizeof(tp->PrivilegeCount) +
2036  (Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
2037 
2038  _SEH2_TRY
2039  {
2041  {
2042  tp->PrivilegeCount = Token->PrivilegeCount;
2043  RtlCopyLuidAndAttributesArray(Token->PrivilegeCount,
2044  Token->Privileges,
2045  &tp->Privileges[0]);
2046  }
2047  else
2048  {
2050  }
2051 
2052  if (ReturnLength != NULL)
2053  {
2055  }
2056  }
2058  {
2060  }
2061  _SEH2_END;
2062 
2063  break;
2064  }
2065 
2066  case TokenOwner:
2067  {
2068  PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
2069  ULONG SidLen;
2070 
2071  DPRINT("NtQueryInformationToken(TokenOwner)\n");
2072  SidLen = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
2073  RequiredLength = sizeof(TOKEN_OWNER) + SidLen;
2074 
2075  _SEH2_TRY
2076  {
2078  {
2079  to->Owner = (PSID)(to + 1);
2080  Status = RtlCopySid(SidLen,
2081  to->Owner,
2082  Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
2083  }
2084  else
2085  {
2087  }
2088 
2089  if (ReturnLength != NULL)
2090  {
2092  }
2093  }
2095  {
2097  }
2098  _SEH2_END;
2099 
2100  break;
2101  }
2102 
2103  case TokenPrimaryGroup:
2104  {
2105  PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
2106  ULONG SidLen;
2107 
2108  DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
2109  SidLen = RtlLengthSid(Token->PrimaryGroup);
2110  RequiredLength = sizeof(TOKEN_PRIMARY_GROUP) + SidLen;
2111 
2112  _SEH2_TRY
2113  {
2115  {
2116  tpg->PrimaryGroup = (PSID)(tpg + 1);
2117  Status = RtlCopySid(SidLen,
2118  tpg->PrimaryGroup,
2119  Token->PrimaryGroup);
2120  }
2121  else
2122  {
2124  }
2125 
2126  if (ReturnLength != NULL)
2127  {
2129  }
2130  }
2132  {
2134  }
2135  _SEH2_END;
2136 
2137  break;
2138  }
2139 
2140  case TokenDefaultDacl:
2141  {
2142  PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
2143 
2144  DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
2146 
2147  if (Token->DefaultDacl != NULL)
2148  RequiredLength += Token->DefaultDacl->AclSize;
2149 
2150  _SEH2_TRY
2151  {
2153  {
2154  if (Token->DefaultDacl != NULL)
2155  {
2156  tdd->DefaultDacl = (PACL)(tdd + 1);
2158  Token->DefaultDacl,
2159  Token->DefaultDacl->AclSize);
2160  }
2161  else
2162  {
2163  tdd->DefaultDacl = NULL;
2164  }
2165  }
2166  else
2167  {
2169  }
2170 
2171  if (ReturnLength != NULL)
2172  {
2174  }
2175  }
2177  {
2179  }
2180  _SEH2_END;
2181 
2182  break;
2183  }
2184 
2185  case TokenSource:
2186  {
2187  PTOKEN_SOURCE ts = (PTOKEN_SOURCE)TokenInformation;
2188 
2189  DPRINT("NtQueryInformationToken(TokenSource)\n");
2190  RequiredLength = sizeof(TOKEN_SOURCE);
2191 
2192  _SEH2_TRY
2193  {
2195  {
2196  *ts = Token->TokenSource;
2197  }
2198  else
2199  {
2201  }
2202 
2203  if (ReturnLength != NULL)
2204  {
2206  }
2207  }
2209  {
2211  }
2212  _SEH2_END;
2213 
2214  break;
2215  }
2216 
2217  case TokenType:
2218  {
2219  PTOKEN_TYPE tt = (PTOKEN_TYPE)TokenInformation;
2220 
2221  DPRINT("NtQueryInformationToken(TokenType)\n");
2222  RequiredLength = sizeof(TOKEN_TYPE);
2223 
2224  _SEH2_TRY
2225  {
2227  {
2228  *tt = Token->TokenType;
2229  }
2230  else
2231  {
2233  }
2234 
2235  if (ReturnLength != NULL)
2236  {
2238  }
2239  }
2241  {
2243  }
2244  _SEH2_END;
2245 
2246  break;
2247  }
2248 
2250  {
2252 
2253  DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
2254 
2255  /* Fail if the token is not an impersonation token */
2256  if (Token->TokenType != TokenImpersonation)
2257  {
2259  break;
2260  }
2261 
2263 
2264  _SEH2_TRY
2265  {
2267  {
2268  *sil = Token->ImpersonationLevel;
2269  }
2270  else
2271  {
2273  }
2274 
2275  if (ReturnLength != NULL)
2276  {
2278  }
2279  }
2281  {
2283  }
2284  _SEH2_END;
2285 
2286  break;
2287  }
2288 
2289  case TokenStatistics:
2290  {
2291  PTOKEN_STATISTICS ts = (PTOKEN_STATISTICS)TokenInformation;
2292 
2293  DPRINT("NtQueryInformationToken(TokenStatistics)\n");
2294  RequiredLength = sizeof(TOKEN_STATISTICS);
2295 
2296  _SEH2_TRY
2297  {
2299  {
2300  ts->TokenId = Token->TokenId;
2301  ts->AuthenticationId = Token->AuthenticationId;
2302  ts->ExpirationTime = Token->ExpirationTime;
2303  ts->TokenType = Token->TokenType;
2304  ts->ImpersonationLevel = Token->ImpersonationLevel;
2305  ts->DynamicCharged = Token->DynamicCharged;
2306  ts->DynamicAvailable = Token->DynamicAvailable;
2307  ts->GroupCount = Token->UserAndGroupCount - 1;
2308  ts->PrivilegeCount = Token->PrivilegeCount;
2309  ts->ModifiedId = Token->ModifiedId;
2310  }
2311  else
2312  {
2314  }
2315 
2316  if (ReturnLength != NULL)
2317  {
2319  }
2320  }
2322  {
2324  }
2325  _SEH2_END;
2326 
2327  break;
2328  }
2329 
2330  case TokenOrigin:
2331  {
2332  PTOKEN_ORIGIN to = (PTOKEN_ORIGIN)TokenInformation;
2333 
2334  DPRINT("NtQueryInformationToken(TokenOrigin)\n");
2335  RequiredLength = sizeof(TOKEN_ORIGIN);
2336 
2337  _SEH2_TRY
2338  {
2340  {
2342  &Token->AuthenticationId);
2343  }
2344  else
2345  {
2347  }
2348 
2349  if (ReturnLength != NULL)
2350  {
2352  }
2353  }
2355  {
2357  }
2358  _SEH2_END;
2359 
2360  break;
2361  }
2362 
2364  DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
2366  break;
2367 
2368  case TokenRestrictedSids:
2369  {
2370  PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
2371 
2372  DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
2373  RequiredLength = sizeof(tg->GroupCount) +
2374  RtlLengthSidAndAttributes(Token->RestrictedSidCount, Token->RestrictedSids);
2375 
2376  _SEH2_TRY
2377  {
2379  {
2380  ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
2381  (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES));
2382  PSID Sid = (PSID)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
2383  (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)));
2384 
2385  tg->GroupCount = Token->RestrictedSidCount;
2386  Status = RtlCopySidAndAttributesArray(Token->RestrictedSidCount,
2387  Token->RestrictedSids,
2388  SidLen,
2389  &tg->Groups[0],
2390  Sid,
2391  &Unused.PSid,
2392  &Unused.Ulong);
2393  }
2394  else
2395  {
2397  }
2398 
2399  if (ReturnLength != NULL)
2400  {
2402  }
2403  }
2405  {
2407  }
2408  _SEH2_END;
2409 
2410  break;
2411  }
2412 
2413  case TokenSandBoxInert:
2414  DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
2416  break;
2417 
2418  case TokenSessionId:
2419  {
2420  ULONG SessionId = 0;
2421 
2422  DPRINT("NtQueryInformationToken(TokenSessionId)\n");
2423 
2425  if (NT_SUCCESS(Status))
2426  {
2427  _SEH2_TRY
2428  {
2429  /* Buffer size was already verified, no need to check here again */
2430  *(PULONG)TokenInformation = SessionId;
2431 
2432  if (ReturnLength != NULL)
2433  {
2434  *ReturnLength = sizeof(ULONG);
2435  }
2436  }
2438  {
2440  }
2441  _SEH2_END;
2442  }
2443 
2444  break;
2445  }
2446 
2447  default:
2448  DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
2450  break;
2451  }
2452 
2453  /* Unlock and dereference the token */
2456  }
2457 
2458  return Status;
2459 }
2460 
2461 
2462 /*
2463  * NtSetTokenInformation: Partly implemented.
2464  * Unimplemented:
2465  * TokenOrigin, TokenDefaultDacl
2466  */
2469 NTSTATUS
2470 NTAPI
2474  _In_reads_bytes_(TokenInformationLength) PVOID TokenInformation,
2476 {
2477  NTSTATUS Status;
2478  PTOKEN Token;
2480  ULONG NeededAccess = TOKEN_ADJUST_DEFAULT;
2481 
2482  PAGED_CODE();
2483 
2485 
2489  TokenInformation,
2491  PreviousMode);
2492  if (!NT_SUCCESS(Status))
2493  {
2494  /* Invalid buffers */
2495  DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status);
2496  return Status;
2497  }
2498 
2500  {
2501  NeededAccess |= TOKEN_ADJUST_SESSIONID;
2502  }
2503 
2505  NeededAccess,
2507  PreviousMode,
2508  (PVOID*)&Token,
2509  NULL);
2510  if (NT_SUCCESS(Status))
2511  {
2512  switch (TokenInformationClass)
2513  {
2514  case TokenOwner:
2515  {
2516  if (TokenInformationLength >= sizeof(TOKEN_OWNER))
2517  {
2518  PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
2519  PSID InputSid = NULL, CapturedSid;
2520  ULONG DefaultOwnerIndex;
2521 
2522  _SEH2_TRY
2523  {
2524  InputSid = to->Owner;
2525  }
2527  {
2529  _SEH2_YIELD(goto Cleanup);
2530  }
2531  _SEH2_END;
2532 
2533  Status = SepCaptureSid(InputSid,
2534  PreviousMode,
2535  PagedPool,
2536  FALSE,
2537  &CapturedSid);
2538  if (NT_SUCCESS(Status))
2539  {
2540  /* Lock the token */
2542 
2543  /* Find the owner amongst the existing token user and groups */
2545  NULL,
2546  CapturedSid,
2547  NULL,
2548  &DefaultOwnerIndex);
2549  if (NT_SUCCESS(Status))
2550  {
2551  /* Found it */
2552  Token->DefaultOwnerIndex = DefaultOwnerIndex;
2553  ExAllocateLocallyUniqueId(&Token->ModifiedId);
2554  }
2555 
2556  /* Unlock the token */
2558 
2559  SepReleaseSid(CapturedSid,
2560  PreviousMode,
2561  FALSE);
2562  }
2563  }
2564  else
2565  {
2567  }
2568  break;
2569  }
2570 
2571  case TokenPrimaryGroup:
2572  {
2574  {
2575  PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
2576  PSID InputSid = NULL, CapturedSid;
2577  ULONG PrimaryGroupIndex;
2578 
2579  _SEH2_TRY
2580  {
2581  InputSid = tpg->PrimaryGroup;
2582  }
2584  {
2586  _SEH2_YIELD(goto Cleanup);
2587  }
2588  _SEH2_END;
2589 
2590  Status = SepCaptureSid(InputSid,
2591  PreviousMode,
2592  PagedPool,
2593  FALSE,
2594  &CapturedSid);
2595  if (NT_SUCCESS(Status))
2596  {
2597  /* Lock the token */
2599 
2600  /* Find the primary group amongst the existing token user and groups */
2602  CapturedSid,
2603  NULL,
2604  &PrimaryGroupIndex,
2605  NULL);
2606  if (NT_SUCCESS(Status))
2607  {
2608  /* Found it */
2609  Token->PrimaryGroup = Token->UserAndGroups[PrimaryGroupIndex].Sid;
2610  ExAllocateLocallyUniqueId(&Token->ModifiedId);
2611  }
2612 
2613  /* Unlock the token */
2615 
2616  SepReleaseSid(CapturedSid,
2617  PreviousMode,
2618  FALSE);
2619  }
2620  }
2621  else
2622  {
2624  }
2625  break;
2626  }
2627 
2628  case TokenDefaultDacl:
2629  {
2631  {
2632  PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
2633  PACL InputAcl = NULL;
2634 
2635  _SEH2_TRY
2636  {
2637  InputAcl = tdd->DefaultDacl;
2638  }
2640  {
2642  _SEH2_YIELD(goto Cleanup);
2643  }
2644  _SEH2_END;
2645 
2646  if (InputAcl != NULL)
2647  {
2648  PACL CapturedAcl;
2649 
2650  /* Capture and copy the dacl */
2651  Status = SepCaptureAcl(InputAcl,
2652  PreviousMode,
2653  PagedPool,
2654  TRUE,
2655  &CapturedAcl);
2656  if (NT_SUCCESS(Status))
2657  {
2658  ULONG DynamicLength;
2659 
2660  /* Lock the token */
2662 
2663  //
2664  // NOTE: So far our dynamic area only contains
2665  // the default dacl, so this makes the following
2666  // code pretty simple. The day where it stores
2667  // other data, the code will require adaptations.
2668  //
2669 
2670  DynamicLength = Token->DynamicAvailable;
2671  // Add here any other data length present in the dynamic area...
2672  if (Token->DefaultDacl)
2673  DynamicLength += Token->DefaultDacl->AclSize;
2674 
2675  /* Reallocate the dynamic area if it is too small */
2677  if ((DynamicLength < CapturedAcl->AclSize) ||
2678  (Token->DynamicPart == NULL))
2679  {
2680  PVOID NewDynamicPart;
2681 
2682  NewDynamicPart = ExAllocatePoolWithTag(PagedPool,
2683  CapturedAcl->AclSize,
2685  if (NewDynamicPart == NULL)
2686  {
2688  }
2689  else
2690  {
2691  if (Token->DynamicPart != NULL)
2692  {
2693  // RtlCopyMemory(NewDynamicPart, Token->DynamicPart, DynamicLength);
2694  ExFreePoolWithTag(Token->DynamicPart, TAG_TOKEN_DYNAMIC);
2695  }
2696  Token->DynamicPart = NewDynamicPart;
2697  Token->DynamicAvailable = 0;
2698  }
2699  }
2700  else
2701  {
2702  Token->DynamicAvailable = DynamicLength - CapturedAcl->AclSize;
2703  }
2704 
2705  if (NT_SUCCESS(Status))
2706  {
2707  /* Set the new dacl */
2708  Token->DefaultDacl = (PVOID)Token->DynamicPart;
2709  RtlCopyMemory(Token->DefaultDacl,
2710  CapturedAcl,
2711  CapturedAcl->AclSize);
2712 
2713  ExAllocateLocallyUniqueId(&Token->ModifiedId);
2714  }
2715 
2716  /* Unlock the token */
2718 
2719  ExFreePoolWithTag(CapturedAcl, TAG_ACL);
2720  }
2721  }
2722  else
2723  {
2724  /* Lock the token */
2726 
2727  /* Clear the default dacl if present */
2728  if (Token->DefaultDacl != NULL)
2729  {
2730  Token->DynamicAvailable += Token->DefaultDacl->AclSize;
2731  RtlZeroMemory(Token->DefaultDacl, Token->DefaultDacl->AclSize);
2732  Token->DefaultDacl = NULL;
2733 
2734  ExAllocateLocallyUniqueId(&Token->ModifiedId);
2735  }
2736 
2737  /* Unlock the token */
2739  }
2740  }
2741  else
2742  {
2744  }
2745  break;
2746  }
2747 
2748  case TokenSessionId:
2749  {
2750  ULONG SessionId = 0;
2751 
2752  _SEH2_TRY
2753  {
2754  /* Buffer size was already verified, no need to check here again */
2755  SessionId = *(PULONG)TokenInformation;
2756  }
2758  {
2760  _SEH2_YIELD(goto Cleanup);
2761  }
2762  _SEH2_END;
2763 
2764  /* Check for TCB privilege */
2766  {
2768  break;
2769  }
2770 
2771  /* Lock the token */
2773 
2774  Token->SessionId = SessionId;
2775  ExAllocateLocallyUniqueId(&Token->ModifiedId);
2776 
2777  /* Unlock the token */
2779 
2780  break;
2781  }
2782 
2783  case TokenSessionReference:
2784  {
2785  ULONG SessionReference;
2786 
2787  _SEH2_TRY
2788  {
2789  /* Buffer size was already verified, no need to check here again */
2790  SessionReference = *(PULONG)TokenInformation;
2791  }
2793  {
2795  _SEH2_YIELD(goto Cleanup);
2796  }
2797  _SEH2_END;
2798 
2799  /* Check for TCB privilege */
2801  {
2803  goto Cleanup;
2804  }
2805 
2806  /* Check if it is 0 */
2807  if (SessionReference == 0)
2808  {
2809  ULONG OldTokenFlags;
2810 
2811  /* Lock the token */
2813 
2814  /* Atomically set the flag in the token */
2815  OldTokenFlags = RtlInterlockedSetBits(&Token->TokenFlags,
2817  /*
2818  * If the flag was already set, do not dereference again
2819  * the logon session. Use SessionReference as an indicator
2820  * to know whether to really dereference the session.
2821  */
2822  if (OldTokenFlags == Token->TokenFlags)
2823  SessionReference = ULONG_MAX;
2824 
2825  /* Unlock the token */
2827  }
2828 
2829  /* Dereference the logon session if needed */
2830  if (SessionReference == 0)
2831  SepRmDereferenceLogonSession(&Token->AuthenticationId);
2832 
2833  break;
2834  }
2835 
2836  case TokenAuditPolicy:
2837  {
2838  PTOKEN_AUDIT_POLICY_INFORMATION PolicyInformation =
2839  (PTOKEN_AUDIT_POLICY_INFORMATION)TokenInformation;
2840  SEP_AUDIT_POLICY AuditPolicy;
2841  ULONG i;
2842 
2843  _SEH2_TRY
2844  {
2845  ProbeForRead(PolicyInformation,
2847  Policies[PolicyInformation->PolicyCount]),
2848  sizeof(ULONG));
2849 
2850  /* Loop all policies in the structure */
2851  for (i = 0; i < PolicyInformation->PolicyCount; i++)
2852  {
2853  /* Set the corresponding bits in the packed structure */
2854  switch (PolicyInformation->Policies[i].Category)
2855  {
2856  case AuditCategorySystem:
2857  AuditPolicy.PolicyElements.System = PolicyInformation->Policies[i].Value;
2858  break;
2859 
2860  case AuditCategoryLogon:
2861  AuditPolicy.PolicyElements.Logon = PolicyInformation->Policies[i].Value;
2862  break;
2863 
2865  AuditPolicy.PolicyElements.ObjectAccess = PolicyInformation->Policies[i].Value;
2866  break;
2867 
2869  AuditPolicy.PolicyElements.PrivilegeUse = PolicyInformation->Policies[i].Value;
2870  break;
2871 
2873  AuditPolicy.PolicyElements.DetailedTracking = PolicyInformation->Policies[i].Value;
2874  break;
2875 
2877  AuditPolicy.PolicyElements.PolicyChange = PolicyInformation->Policies[i].Value;
2878  break;
2879 
2881  AuditPolicy.PolicyElements.AccountManagement = PolicyInformation->Policies[i].Value;
2882  break;
2883 
2885  AuditPolicy.PolicyElements.DirectoryServiceAccess = PolicyInformation->Policies[i].Value;
2886  break;
2887 
2889  AuditPolicy.PolicyElements.AccountLogon = PolicyInformation->Policies[i].Value;
2890  break;
2891  }
2892  }
2893  }
2895  {
2897  _SEH2_YIELD(goto Cleanup);
2898  }
2899  _SEH2_END;
2900 
2901  /* Check for TCB privilege */
2903  {
2905  break;
2906  }
2907 
2908  /* Lock the token */
2910 
2911  /* Set the new audit policy */
2912  Token->AuditPolicy = AuditPolicy;
2913  ExAllocateLocallyUniqueId(&Token->ModifiedId);
2914 
2915  /* Unlock the token */
2917 
2918  break;
2919  }
2920 
2921  case TokenOrigin:
2922  {
2924 
2925  _SEH2_TRY
2926  {
2927  /* Copy the token origin */
2928  TokenOrigin = *(PTOKEN_ORIGIN)TokenInformation;
2929  }
2931  {
2933  _SEH2_YIELD(goto Cleanup);
2934  }
2935  _SEH2_END;
2936 
2937  /* Check for TCB privilege */
2939  {
2941  break;
2942  }
2943 
2944  /* Lock the token */
2946 
2947  /* Check if there is no token origin set yet */
2948  if (RtlIsZeroLuid(&Token->OriginatingLogonSession))
2949  {
2950  /* Set the token origin */
2951  Token->OriginatingLogonSession =
2952  TokenOrigin.OriginatingLogonSession;
2953 
2954  ExAllocateLocallyUniqueId(&Token->ModifiedId);
2955  }
2956 
2957  /* Unlock the token */
2959 
2960  break;
2961  }
2962 
2963  default:
2964  {
2965  DPRINT1("Invalid TokenInformationClass: 0x%lx\n",
2968  break;
2969  }
2970  }
2971 Cleanup:
2973  }
2974 
2975  if (!NT_SUCCESS(Status))
2976  {
2977  DPRINT1("NtSetInformationToken failed with Status 0x%lx\n", Status);
2978  }
2979 
2980  return Status;
2981 }
2982 
2983 
2984 /*
2985  * @implemented
2986  *
2987  * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
2988  * this is certainly NOT true, although I can't say for sure that EffectiveOnly
2989  * is correct either. -Gunnar
2990  * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
2991  * NOTE for readers: http://hex.pp.ua/nt/NtDuplicateToken.php is therefore
2992  * wrong in that regard, while MSDN documentation is correct.
2993  */
2996 NTSTATUS
2997 NTAPI
2999  _In_ HANDLE ExistingTokenHandle,
3005 {
3007  HANDLE hToken;
3008  PTOKEN Token;
3009  PTOKEN NewToken;
3010  PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService;
3011  BOOLEAN QoSPresent;
3013  NTSTATUS Status;
3014 
3015  PAGED_CODE();
3016 
3017  if (TokenType != TokenImpersonation &&
3019  {
3020  return STATUS_INVALID_PARAMETER;
3021  }
3022 
3024 
3025  if (PreviousMode != KernelMode)
3026  {
3027  _SEH2_TRY
3028  {
3030  }
3032  {
3033  /* Return the exception code */
3035  }
3036  _SEH2_END;
3037  }
3038 
3040  PreviousMode,
3041  PagedPool,
3042  FALSE,
3043  &CapturedSecurityQualityOfService,
3044  &QoSPresent);
3045  if (!NT_SUCCESS(Status))
3046  {
3047  DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status);
3048  return Status;
3049  }
3050 
3051  Status = ObReferenceObjectByHandle(ExistingTokenHandle,
3054  PreviousMode,
3055  (PVOID*)&Token,
3057  if (!NT_SUCCESS(Status))
3058  {
3059  DPRINT1("Failed to reference token (Status 0x%lx)\n", Status);
3060  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
3061  PreviousMode,
3062  FALSE);
3063  return Status;
3064  }
3065 
3066  /*
3067  * Fail, if the original token is an impersonation token and the caller
3068  * tries to raise the impersonation level of the new token above the
3069  * impersonation level of the original token.
3070  */
3071  if (Token->TokenType == TokenImpersonation)
3072  {
3073  if (QoSPresent &&
3074  CapturedSecurityQualityOfService->ImpersonationLevel >Token->ImpersonationLevel)
3075  {
3077  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
3078  PreviousMode,
3079  FALSE);
3081  }
3082  }
3083 
3084  /*
3085  * Fail, if a primary token is to be created from an impersonation token
3086  * and and the impersonation level of the impersonation token is below SecurityImpersonation.
3087  */
3088  if (Token->TokenType == TokenImpersonation &&
3089  TokenType == TokenPrimary &&
3090  Token->ImpersonationLevel < SecurityImpersonation)
3091  {
3093  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
3094  PreviousMode,
3095  FALSE);
3097  }
3098 
3101  EffectiveOnly,
3102  TokenType,
3103  (QoSPresent ? CapturedSecurityQualityOfService->ImpersonationLevel : SecurityAnonymous),
3104  PreviousMode,
3105  &NewToken);
3106 
3108 
3109  if (NT_SUCCESS(Status))
3110  {
3111  Status = ObInsertObject(NewToken,
3112  NULL,
3113  (DesiredAccess ? DesiredAccess : HandleInformation.GrantedAccess),
3114  0,
3115  NULL,
3116  &hToken);
3117  if (NT_SUCCESS(Status))
3118  {
3119  _SEH2_TRY
3120  {
3121  *NewTokenHandle = hToken;
3122  }
3124  {
3126  }
3127  _SEH2_END;
3128  }
3129  }
3130 
3131  /* Free the captured structure */
3132  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
3133  PreviousMode,
3134  FALSE);
3135 
3136  return Status;
3137 }
3138 
3141  IN BOOLEAN ResetToDefault,
3142  IN PTOKEN_GROUPS NewState,
3146 {
3147  UNIMPLEMENTED;
3148  return STATUS_NOT_IMPLEMENTED;
3149 }
3150 
3151 
3152 static
3153 NTSTATUS
3156  _In_ BOOLEAN DisableAllPrivileges,
3157  _In_opt_ PLUID_AND_ATTRIBUTES NewState,
3158  _In_ ULONG NewStateCount,
3161  _Out_ PULONG ChangedPrivileges,
3162  _Out_ PBOOLEAN ChangesMade)
3163 {
3164  ULONG i, j, PrivilegeCount, ChangeCount, NewAttributes;
3165 
3166  /* Count the found privileges and those that need to be changed */
3167  PrivilegeCount = 0;
3168  ChangeCount = 0;
3169  *ChangesMade = FALSE;
3170 
3171  /* Loop all privileges in the token */
3172  for (i = 0; i < Token->PrivilegeCount; i++)
3173  {
3174  /* Shall all of them be disabled? */
3175  if (DisableAllPrivileges)
3176  {
3177  /* The new attributes are the old ones, but disabled */
3178  NewAttributes = Token->Privileges[i].Attributes & ~SE_PRIVILEGE_ENABLED;
3179  }
3180  else
3181  {
3182  /* Otherwise loop all provided privileges */
3183  for (j = 0; j < NewStateCount; j++)
3184  {
3185  /* Check if this is the LUID we are looking for */
3186  if (RtlEqualLuid(&Token->Privileges[i].Luid, &NewState[j].Luid))
3187  {
3188  DPRINT("Found privilege\n");
3189 
3190  /* Copy SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED */
3191  NewAttributes = NewState[j].Attributes;
3192  NewAttributes &= (SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED);
3193  NewAttributes |= Token->Privileges[i].Attributes & ~SE_PRIVILEGE_ENABLED;
3194 
3195  /* Stop looking */
3196  break;
3197  }
3198  }
3199 
3200  /* Check if we didn't find the privilege */
3201  if (j == NewStateCount)
3202  {
3203  /* Continue with the token's next privilege */
3204  continue;
3205  }
3206  }
3207 
3208  /* We found a privilege, count it */
3209  PrivilegeCount++;
3210 
3211  /* Does the privilege need to be changed? */
3212  if (Token->Privileges[i].Attributes != NewAttributes)
3213  {
3214  /* Does the caller want the old privileges? */
3215  if (PreviousState != NULL)
3216  {
3217  /* Copy the old privilege */
3218  PreviousState->Privileges[ChangeCount] = Token->Privileges[i];
3219  }
3220 
3221  /* Does the caller want to apply the changes? */
3222  if (ApplyChanges)
3223  {
3224  /* Shall we remove the privilege? */
3225  if (NewAttributes & SE_PRIVILEGE_REMOVED)
3226  {
3227  /* Set the token as disabled and update flags for it */
3228  Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
3230 
3231  /* Remove the privilege */
3233 
3234  *ChangesMade = TRUE;
3235 
3236  /* Fix the running index and continue with next one */
3237  i--;
3238  continue;
3239  }
3240 
3241  /* Set the new attributes and update flags */
3242  Token->Privileges[i].Attributes = NewAttributes;
3244  *ChangesMade = TRUE;
3245  }
3246 
3247  /* Increment the change count */
3248  ChangeCount++;
3249  }
3250  }
3251 
3252  /* Set the number of saved privileges */
3253  if (PreviousState != NULL)
3254  PreviousState->PrivilegeCount = ChangeCount;
3255 
3256  /* Return the number of changed privileges */
3257  *ChangedPrivileges = ChangeCount;
3258 
3259  /* Check if we missed some */
3260  if (!DisableAllPrivileges && (PrivilegeCount < NewStateCount))
3261  {
3262  return STATUS_NOT_ALL_ASSIGNED;
3263  }
3264 
3265  return STATUS_SUCCESS;
3266 }
3267 
3268 
3269 /*
3270  * @implemented
3271  */
3274 NTSTATUS
3275 NTAPI
3278  _In_ BOOLEAN DisableAllPrivileges,
3279  _In_opt_ PTOKEN_PRIVILEGES NewState,
3284 {
3285  NTSTATUS Status;
3287  PTOKEN Token;
3288  PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
3289  ULONG CapturedCount = 0;
3290  ULONG CapturedLength = 0;
3291  ULONG NewStateSize = 0;
3292  ULONG ChangeCount;
3294  BOOLEAN ChangesMade = FALSE;
3295 
3296  PAGED_CODE();
3297 
3298  DPRINT("NtAdjustPrivilegesToken() called\n");
3299 
3300  /* Fail, if we do not disable all privileges but NewState is NULL */
3301  if (DisableAllPrivileges == FALSE && NewState == NULL)
3302  return STATUS_INVALID_PARAMETER;
3303 
3305  if (PreviousMode != KernelMode)
3306  {
3307  _SEH2_TRY
3308  {
3309  /* Probe NewState */
3310  if (DisableAllPrivileges == FALSE)
3311  {
3312  /* First probe the header */
3313  ProbeForRead(NewState, sizeof(TOKEN_PRIVILEGES), sizeof(ULONG));
3314 
3315  CapturedCount = NewState->PrivilegeCount;
3316  NewStateSize = FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges[CapturedCount]);
3317 
3318  ProbeForRead(NewState, NewStateSize, sizeof(ULONG));
3319  }
3320 
3321  /* Probe PreviousState and ReturnLength */
3322  if (PreviousState != NULL)
3323  {
3325  ProbeForWrite(ReturnLength, sizeof(ULONG), sizeof(ULONG));
3326  }
3327  }
3329  {
3330  /* Return the exception code */
3332  }
3333  _SEH2_END;
3334  }
3335  else
3336  {
3337  /* This is kernel mode, we trust the caller */
3338  if (DisableAllPrivileges == FALSE)
3339  CapturedCount = NewState->PrivilegeCount;
3340  }
3341 
3342  /* Do we need to capture the new state? */
3343  if (DisableAllPrivileges == FALSE)
3344  {
3345  _SEH2_TRY
3346  {
3347  /* Capture the new state array of privileges */
3348  Status = SeCaptureLuidAndAttributesArray(NewState->Privileges,
3349  CapturedCount,
3350  PreviousMode,
3351  NULL,
3352  0,
3353  PagedPool,
3354  TRUE,
3355  &CapturedPrivileges,
3356  &CapturedLength);
3357  }
3359  {
3360  /* Return the exception code */
3362  }
3363  _SEH2_END;
3364 
3365  if (!NT_SUCCESS(Status))
3366  return Status;
3367  }
3368 
3369  /* Reference the token */
3373  PreviousMode,
3374  (PVOID*)&Token,
3375  NULL);
3376  if (!NT_SUCCESS(Status))
3377  {
3378  DPRINT1("Failed to reference token (Status 0x%lx)\n", Status);
3379 
3380  /* Release the captured privileges */
3381  if (CapturedPrivileges != NULL)
3382  {
3383  SeReleaseLuidAndAttributesArray(CapturedPrivileges,
3384  PreviousMode,
3385  TRUE);
3386  }
3387 
3388  return Status;
3389  }
3390 
3391  /* Lock the token */
3393 
3394  /* Count the privileges that need to be changed, do not apply them yet */
3396  DisableAllPrivileges,
3397  CapturedPrivileges,
3398  CapturedCount,
3399  NULL,
3400  FALSE,
3401  &ChangeCount,
3402  &ChangesMade);
3403 
3404  /* Check if the caller asked for the previous state */
3405  if (PreviousState != NULL)
3406  {
3407  /* Calculate the required length */
3409 
3410  /* Try to return the required buffer length */
3411  _SEH2_TRY
3412  {
3414  }
3416  {
3417  /* Do cleanup and return the exception code */
3419  _SEH2_YIELD(goto Cleanup);
3420  }
3421  _SEH2_END;
3422 
3423  /* Fail, if the buffer length is smaller than the required length */
3425  {
3427  goto Cleanup;
3428  }
3429  }
3430 
3431  /* Now enter SEH, since we might return the old privileges */
3432  _SEH2_TRY
3433  {
3434  /* This time apply the changes */
3436  DisableAllPrivileges,
3437  CapturedPrivileges,
3438  CapturedCount,
3439  PreviousState,
3440  TRUE,
3441  &ChangeCount,
3442  &ChangesMade);
3443  }
3445  {
3446  /* Do cleanup and return the exception code */
3448  ChangesMade = TRUE; // Force write.
3449  _SEH2_YIELD(goto Cleanup);
3450  }
3451  _SEH2_END;
3452 
3453 Cleanup:
3454  /* Touch the token if we made changes */
3455  if (ChangesMade)
3456  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3457 
3458  /* Unlock and dereference the token */
3461 
3462  /* Release the captured privileges */
3463  if (CapturedPrivileges != NULL)
3464  {
3465  SeReleaseLuidAndAttributesArray(CapturedPrivileges,
3466  PreviousMode,
3467  TRUE);
3468  }
3469 
3470  DPRINT ("NtAdjustPrivilegesToken() done\n");
3471  return Status;
3472 }
3473 
3475 NTSTATUS
3476 NTAPI
3482  _In_ PLUID AuthenticationId,
3483  _In_ PLARGE_INTEGER ExpirationTime,
3491 {
3492  HANDLE hToken;
3494  ULONG PrivilegeCount, GroupCount;
3495  PSID OwnerSid, PrimaryGroupSid;
3496  PACL DefaultDacl;
3497  LARGE_INTEGER LocalExpirationTime = {{0, 0}};
3498  LUID LocalAuthenticationId;
3499  TOKEN_SOURCE LocalTokenSource;
3500  SECURITY_QUALITY_OF_SERVICE LocalSecurityQos;
3501  PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
3502  PSID_AND_ATTRIBUTES CapturedUser = NULL;
3503  PSID_AND_ATTRIBUTES CapturedGroups = NULL;
3504  PSID CapturedOwnerSid = NULL;
3505  PSID CapturedPrimaryGroupSid = NULL;
3506  PACL CapturedDefaultDacl = NULL;
3507  ULONG PrivilegesLength, UserLength, GroupsLength;
3508  NTSTATUS Status;
3509 
3510  PAGED_CODE();
3511 
3513 
3514  if (PreviousMode != KernelMode)
3515  {
3516  _SEH2_TRY
3517  {
3519 
3520  if (ObjectAttributes != NULL)
3521  {
3523  sizeof(OBJECT_ATTRIBUTES),
3524  sizeof(ULONG));
3525  LocalSecurityQos = *(SECURITY_QUALITY_OF_SERVICE*)ObjectAttributes->SecurityQualityOfService;
3526  }
3527 
3528  ProbeForRead(AuthenticationId,
3529  sizeof(LUID),
3530  sizeof(ULONG));
3531  LocalAuthenticationId = *AuthenticationId;
3532 
3533  LocalExpirationTime = ProbeForReadLargeInteger(ExpirationTime);
3534 
3536  sizeof(TOKEN_USER),
3537  sizeof(ULONG));
3538 
3540  sizeof(TOKEN_GROUPS),
3541  sizeof(ULONG));
3542  GroupCount = TokenGroups->GroupCount;
3543 
3545  sizeof(TOKEN_PRIVILEGES),
3546  sizeof(ULONG));
3547  PrivilegeCount = TokenPrivileges->PrivilegeCount;
3548 
3549  if (TokenOwner != NULL)
3550  {
3552  sizeof(TOKEN_OWNER),
3553  sizeof(ULONG));
3554  OwnerSid = TokenOwner->Owner;
3555  }
3556  else
3557  {
3558  OwnerSid = NULL;
3559  }
3560 
3562  sizeof(TOKEN_PRIMARY_GROUP),
3563  sizeof(ULONG));
3564  PrimaryGroupSid = TokenPrimaryGroup->PrimaryGroup;
3565 
3566  if (TokenDefaultDacl != NULL)
3567  {
3569  sizeof(TOKEN_DEFAULT_DACL),
3570  sizeof(ULONG));
3571  DefaultDacl = TokenDefaultDacl->DefaultDacl;
3572  }
3573  else
3574  {
3575  DefaultDacl = NULL;
3576  }
3577 
3579  sizeof(TOKEN_SOURCE),
3580  sizeof(ULONG));
3581  LocalTokenSource = *TokenSource;
3582  }
3584  {
3585  /* Return the exception code */
3587  }
3588  _SEH2_END;
3589  }
3590  else
3591  {
3592  if (ObjectAttributes != NULL)
3593  LocalSecurityQos = *(SECURITY_QUALITY_OF_SERVICE*)ObjectAttributes->SecurityQualityOfService;
3594  LocalAuthenticationId = *AuthenticationId;
3595  LocalExpirationTime = *ExpirationTime;
3596  GroupCount = TokenGroups->GroupCount;
3597  PrivilegeCount = TokenPrivileges->PrivilegeCount;
3598  OwnerSid = TokenOwner ? TokenOwner->Owner : NULL;
3599  PrimaryGroupSid = TokenPrimaryGroup->PrimaryGroup;
3600  DefaultDacl = TokenDefaultDacl ? TokenDefaultDacl->DefaultDacl : NULL;
3601  LocalTokenSource = *TokenSource;
3602  }
3603 
3604  /* Check token type */
3605  if ((TokenType < TokenPrimary) ||
3607  {
3608  return STATUS_BAD_TOKEN_TYPE;
3609  }
3610 
3611  /* Check for token creation privilege */
3613  {
3615  }
3616 
3617  /* Capture the user SID and attributes */
3619  1,
3620  PreviousMode,
3621  NULL,
3622  0,
3623  PagedPool,
3624  FALSE,
3625  &CapturedUser,
3626  &UserLength);
3627  if (!NT_SUCCESS(Status))
3628  {
3629  goto Cleanup;
3630  }
3631 
3632  /* Capture the groups SID and attributes array */
3634  GroupCount,
3635  PreviousMode,
3636  NULL,
3637  0,
3638  PagedPool,
3639  FALSE,
3640  &CapturedGroups,
3641  &GroupsLength);
3642  if (!NT_SUCCESS(Status))
3643  {
3644  goto Cleanup;
3645  }
3646 
3647  /* Capture privileges */
3649  PrivilegeCount,
3650  PreviousMode,
3651  NULL,
3652  0,
3653  PagedPool,
3654  FALSE,
3655  &CapturedPrivileges,
3656  &PrivilegesLength);
3657  if (!NT_SUCCESS(Status))
3658  {
3659  goto Cleanup;
3660  }
3661 
3662  /* Capture the token owner SID */
3663  if (TokenOwner != NULL)
3664  {
3665  Status = SepCaptureSid(OwnerSid,
3666  PreviousMode,
3667  PagedPool,
3668  FALSE,
3669  &CapturedOwnerSid);
3670  if (!NT_SUCCESS(Status))
3671  {
3672  goto Cleanup;
3673  }
3674  }
3675 
3676  /* Capture the token primary group SID */
3677  Status = SepCaptureSid(PrimaryGroupSid,
3678  PreviousMode,
3679  PagedPool,
3680  FALSE,
3681  &CapturedPrimaryGroupSid);
3682  if (!NT_SUCCESS(Status))
3683  {
3684  goto Cleanup;
3685  }
3686 
3687  /* Capture DefaultDacl */
3688  if (DefaultDacl != NULL)
3689  {
3690  Status = SepCaptureAcl(DefaultDacl,
3691  PreviousMode,
3692  NonPagedPool,
3693  FALSE,
3694  &CapturedDefaultDacl);
3695  if (!NT_SUCCESS(Status))
3696  {
3697  goto Cleanup;
3698  }
3699  }
3700 
3701  /* Call the internal function */
3702  Status = SepCreateToken(&hToken,
3703  PreviousMode,
3704  DesiredAccess,
3706  TokenType,
3707  LocalSecurityQos.ImpersonationLevel,
3708  &LocalAuthenticationId,
3709  &LocalExpirationTime,
3710  CapturedUser,
3711  GroupCount,
3712  CapturedGroups,
3713  0, // FIXME: Should capture
3714  PrivilegeCount,
3715  CapturedPrivileges,
3716  CapturedOwnerSid,
3717  CapturedPrimaryGroupSid,
3718  CapturedDefaultDacl,
3719  &LocalTokenSource,
3720  FALSE);
3721  if (NT_SUCCESS(Status))
3722  {
3723  _SEH2_TRY
3724  {
3725  *TokenHandle = hToken;
3726  }
3728  {
3730  }
3731  _SEH2_END;
3732  }
3733 
3734 Cleanup:
3735 
3736  /* Release what we captured */
3739  SeReleaseLuidAndAttributesArray(CapturedPrivileges, PreviousMode, FALSE);
3740  SepReleaseSid(CapturedOwnerSid, PreviousMode, FALSE);
3741  SepReleaseSid(CapturedPrimaryGroupSid, PreviousMode, FALSE);
3742  SepReleaseAcl(CapturedDefaultDacl, PreviousMode, FALSE);
3743 
3744  return Status;
3745 }
3746 
3747 /*
3748  * @implemented
3749  */
3750 NTSTATUS
3751 NTAPI
3757 {
3758  PETHREAD Thread, NewThread;
3759  HANDLE hToken;
3760  PTOKEN Token, NewToken = NULL, PrimaryToken;
3766  PACL Dacl = NULL;
3768  NTSTATUS Status;
3769  BOOLEAN RestoreImpersonation = FALSE;
3770 
3771  PAGED_CODE();
3772 
3774 
3775  if (PreviousMode != KernelMode)
3776  {
3777  _SEH2_TRY
3778  {
3780  }
3782  {
3783  /* Return the exception code */
3785  }
3786  _SEH2_END;
3787  }
3788 
3789  /* Validate object attributes */
3791 
3792  /*
3793  * At first open the thread token for information access and verify
3794  * that the token associated with thread is valid.
3795  */
3796 
3799  NULL);
3800  if (!NT_SUCCESS(Status))
3801  {
3802  return Status;
3803  }
3804 
3807  if (Token == NULL)
3808  {
3810  return STATUS_NO_TOKEN;
3811  }
3812 
3814  {
3818  }
3819 
3820  /*
3821  * Revert to self if OpenAsSelf is specified.
3822  */
3823 
3824  if (OpenAsSelf)
3825  {
3826  RestoreImpersonation = PsDisableImpersonation(PsGetCurrentThread(),
3828  }
3829 
3830  if (CopyOnOpen)
3831  {
3834  (PVOID*)&NewThread, NULL);
3835  if (NT_SUCCESS(Status))
3836  {
3837  PrimaryToken = PsReferencePrimaryToken(NewThread->ThreadsProcess);
3838 
3839  Status = SepCreateImpersonationTokenDacl(Token, PrimaryToken, &Dacl);
3840 
3841  ObFastDereferenceObject(&NewThread->ThreadsProcess->Token, PrimaryToken);
3842 
3843  if (NT_SUCCESS(Status))
3844  {
3845  if (Dacl)
3846  {
3850  FALSE);
3851  }
3852 
3855 
3858  KernelMode, &NewToken);
3859  if (NT_SUCCESS(Status))
3860  {
3861  ObReferenceObject(NewToken);
3862  Status = ObInsertObject(NewToken, NULL, DesiredAccess, 0, NULL,
3863  &hToken);
3864  }
3865  }
3866  }
3867  }
3868  else
3869  {
3872  PreviousMode, &hToken);
3873  }
3874 
3876 
3877  if (RestoreImpersonation)
3878  {
3880  }
3881 
3883 
3884  if (NT_SUCCESS(Status) && CopyOnOpen)
3885  {
3887  }
3888 
3889  if (NewToken) ObDereferenceObject(NewToken);
3890 
3891  if (CopyOnOpen && NewThread) ObDereferenceObject(NewThread);
3892 
3894 
3895  if (NT_SUCCESS(Status))
3896  {
3897  _SEH2_TRY
3898  {
3899  *TokenHandle = hToken;
3900  }
3902  {
3904  }
3905  _SEH2_END;
3906  }
3907 
3908  return Status;
3909 }
3910 
3911 /*
3912  * @implemented
3913  */
3919 {
3920  return NtOpenThreadTokenEx(ThreadHandle, DesiredAccess, OpenAsSelf, 0,
3921  TokenHandle);
3922 }
3923 
3924 /*
3925  * @unimplemented
3926  */
3927 NTSTATUS
3928 NTAPI
3929 NtCompareTokens(IN HANDLE FirstTokenHandle,
3930  IN HANDLE SecondTokenHandle,
3931  OUT PBOOLEAN Equal)
3932 {
3934  PTOKEN FirstToken, SecondToken;
3935  BOOLEAN IsEqual;
3936  NTSTATUS Status;
3937 
3938  PAGED_CODE();
3939 
3941 
3942  if (PreviousMode != KernelMode)
3943  {
3944  _SEH2_TRY
3945  {
3946  ProbeForWriteBoolean(Equal);
3947  }
3949  {
3950  /* Return the exception code */
3952  }
3953  _SEH2_END;
3954  }
3955 
3956  Status = ObReferenceObjectByHandle(FirstTokenHandle,
3957  TOKEN_QUERY,
3959  PreviousMode,
3960  (PVOID*)&FirstToken,
3961  NULL);
3962  if (!NT_SUCCESS(Status))
3963  return Status;
3964 
3965  Status = ObReferenceObjectByHandle(SecondTokenHandle,
3966  TOKEN_QUERY,
3968  PreviousMode,
3969  (PVOID*)&SecondToken,
3970  NULL);
3971  if (!NT_SUCCESS(Status))
3972  {
3973  ObDereferenceObject(FirstToken);
3974  return Status;
3975  }
3976 
3977  if (FirstToken != SecondToken)
3978  {
3979  Status = SepCompareTokens(FirstToken,
3980  SecondToken,
3981  &IsEqual);
3982  }
3983  else
3984  {
3985  IsEqual = TRUE;
3986  }
3987 
3988  ObDereferenceObject(SecondToken);
3989  ObDereferenceObject(FirstToken);
3990 
3991  if (NT_SUCCESS(Status))
3992  {
3993  _SEH2_TRY
3994  {
3995  *Equal = IsEqual;
3996  }
3998  {
4000  }
4001  _SEH2_END;
4002  }
4003 
4004  return Status;
4005 }
4006 
4007 NTSTATUS
4008 NTAPI
4009 NtFilterToken(IN HANDLE ExistingTokenHandle,
4010  IN ULONG Flags,
4011  IN PTOKEN_GROUPS SidsToDisable OPTIONAL,
4012  IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL,
4013  IN PTOKEN_GROUPS RestrictedSids OPTIONAL,
4015 {
4016  UNIMPLEMENTED;
4017  return STATUS_NOT_IMPLEMENTED;
4018 }
4019 
4020 /*
4021  * @unimplemented
4022  */
4023 NTSTATUS
4024 NTAPI
4026 {
4027  UNIMPLEMENTED;
4028  return STATUS_NOT_IMPLEMENTED;
4029 }
4030 
4031 /* EOF */
#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:200
static NTSTATUS SepFindPrimaryGroupAndDefaultOwner(_In_ PTOKEN Token, _In_ PSID PrimaryGroup, _In_opt_ PSID DefaultOwner, _Out_opt_ PULONG PrimaryGroupIndex, _Out_opt_ PULONG DefaultOwnerIndex)
Definition: token.c:392
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
NTSTATUS NTAPI NtImpersonateAnonymousToken(IN HANDLE Thread)
Definition: token.c:4025
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
#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:1347
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
_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:4009
NTSTATUS NTAPI SeIsTokenChild(IN PTOKEN Token, OUT PBOOLEAN IsChild)
Definition: token.c:768
#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
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:272
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
NTSTATUS NTAPI SeQuerySessionIdToken(IN PACCESS_TOKEN Token, IN PULONG pSessionId)
Definition: token.c:1788
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
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:207
NTSTATUS NTAPI NtOpenThreadTokenEx(IN HANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN OpenAsSelf, IN ULONG HandleAttributes, OUT PHANDLE TokenHandle)
Definition: token.c:3752
LUID SeSystemAuthenticationId
Definition: token.c:32
_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
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
NTSYSAPI NTSTATUS NTAPI RtlCreateSecurityDescriptor(_Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ ULONG Revision)
PSID SeAuthenticatedUsersSid
Definition: sid.c:51
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:2739
static VOID SepUpdateSinglePrivilegeFlagToken(_Inout_ PTOKEN Token, _In_ ULONG Index)
Definition: token.c:176
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
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:1864
#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:488
NTSTATUS NTAPI SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token, OUT PLUID LogonId)
Definition: token.c:1809
ULONG TokenFlags
Definition: setypes.h:210
NTSTATUS NTAPI NtCompareTokens(IN HANDLE FirstTokenHandle, IN HANDLE SecondTokenHandle, OUT PBOOLEAN Equal)
Definition: token.c:3929
return STATUS_NOT_IMPLEMENTED
#define SE_PRIVILEGE_ENABLED
Definition: setypes.h:63
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:496
#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:33
#define RtlEqualLuid(Luid1, Luid2)
Definition: rtlfuncs.h:301
static VOID SepUpdatePrivilegeFlagsToken(_Inout_ PTOKEN Token)
Definition: token.c:227
NTSYSAPI VOID NTAPI RtlCopyLuidAndAttributesArray(ULONG Count, PLUID_AND_ATTRIBUTES Src, PLUID_AND_ATTRIBUTES Dest)
Definition: luid.c:33
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
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
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:3140
PTOKEN NTAPI SepCreateSystemProcessToken(VOID)
Definition: token.c:1202
VOID NTAPI PsRestoreImpersonation(IN PETHREAD Thread, IN PSE_IMPERSONATION_STATE ImpersonationState)
Definition: security.c:924
unsigned char BOOLEAN
static const char * ts(int t)
#define STATUS_BAD_TOKEN_TYPE
Definition: ntstatus.h:404
const LUID SeLoadDriverPrivilege
Definition: priv.c:27
POBJECT_TYPE SeTokenObjectType
Definition: token.c:29
_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:1896
#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:273
_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:936
#define TOKEN_ADJUST_DEFAULT
Definition: setypes.h:878
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:715
NTSYSAPI ULONG NTAPI RtlLengthSid(IN PSID Sid)
Definition: sid.c:150
TOKEN_TYPE NTAPI SeTokenType(IN PACCESS_TOKEN Token)
Definition: token.c:1837
void * PVOID
Definition: retypes.h:9
struct _TOKEN_GROUPS * PTOKEN_GROUPS
SECURITY_IMPERSONATION_LEVEL NTAPI SeTokenImpersonationLevel(IN PACCESS_TOKEN Token)
Definition: token.c:1825
ULONG SessionId
Definition: setypes.h:194
NTSTATUS SepRmDereferenceLogonSession(PLUID LogonLuid)
Definition: srm.c:664
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:381
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:874
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
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:3154
#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 _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
#define __kernel_entry
Definition: specstrings.h:355
#define ASSERT(a)
Definition: mode.c:45
if(!(yy_init))
Definition: macro.lex.yy.c:714
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:361
struct _TOKEN_SOURCE TOKEN_SOURCE
_In_ WDFCOLLECTION _In_ ULONG Index
struct _TOKEN_AUDIT_POLICY_INFORMATION * PTOKEN_AUDIT_POLICY_INFORMATION
struct _SID_AND_ATTRIBUTES SID_AND_ATTRIBUTES
_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
VOID NTAPI SepFreeProxyData(PVOID ProxyData)
Definition: token.c:265
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:363
SEP_AUDIT_POLICY_CATEGORIES PolicyElements
Definition: setypes.h:148
NTSTATUS NTAPI SeIsTokenSibling(IN PTOKEN Token, OUT PBOOLEAN IsSibling)
Definition: token.c:801
#define ProbeForWriteBoolean(Ptr)
Definition: probe.h:31
VOID NTAPI SeAssignPrimaryToken(IN PEPROCESS Process, IN PTOKEN Token)
Definition: token.c:916
#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:109
#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
VOID NTAPI SepInitializeTokenImplementation(VOID)
Definition: token.c:892
_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:724
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
TOKEN_SOURCE SeSystemTokenSource
Definition: token.c:31
#define SepReleaseTokenLock(Token)
Definition: se.h:211
__kernel_entry NTSTATUS NTAPI NtCreateToken(_Out_ PHANDLE TokenHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ TOKEN_TYPE TokenType, _In_ PLUID AuthenticationId, _In_ PLARGE_INTEGER ExpirationTime, _In_ PTOKEN_USER TokenUser, _In_ PTOKEN_GROUPS TokenGroups, _In_ PTOKEN_PRIVILEGES TokenPrivileges, _In_opt_ PTOKEN_OWNER TokenOwner, _In_ PTOKEN_PRIMARY_GROUP TokenPrimaryGroup, _In_opt_ PTOKEN_DEFAULT_DACL TokenDefaultDacl, _In_ PTOKEN_SOURCE TokenSource)
Definition: token.c:3477
NTSTATUS NTAPI SeCaptureSidAndAttributesArray(_In_ PSID_AND_ATTRIBUTES SrcSidAndAttributes, _In_ ULONG AttributeCount, _In_ KPROCESSOR_MODE PreviousMode, _In_opt_ PVOID AllocatedMem, _In_ ULONG AllocatedLength, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PSID_AND_ATTRIBUTES *CapturedSidAndAttributes, _Out_ PULONG ResultLength)
Definition: sid.c:354
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:454
static GENERIC_MAPPING SepTokenMapping
Definition: token.c:35
#define TAG_TOKEN_DYNAMIC
Definition: tag.h:180
static __inline NTSTATUS DefaultQueryInfoBufferCheck(ULONG Class, const INFORMATION_CLASS_INFO *ClassList, ULONG ClassListEntries, PVOID Buffer, ULONG BufferLength, PULONG ReturnLength, PULONG_PTR ReturnLengthPtr, KPROCESSOR_MODE PreviousMode)
Definition: probe.h:59
VOID NTAPI SeDeassignPrimaryToken(PEPROCESS Process)
Definition: token.c:360
const LUID SeLockMemoryPrivilege
Definition: priv.c:21
NTSYSAPI BOOLEAN WINAPI RtlCopySid(DWORD, PSID, PSID)
struct _TOKEN_AUDIT_POLICY_INFORMATION TOKEN_AUDIT_POLICY_INFORMATION
const LUID SeProfileSingleProcessPrivilege
Definition: priv.c:30
PACCESS_TOKEN NTAPI PsReferencePrimaryToken(PEPROCESS Process)
Definition: security.c:440
static const WCHAR Cleanup[]
Definition: register.c:80
PSID SeWorldSid
Definition: sid.c:27
const LUID SeIncreaseBasePriorityPrivilege
Definition: priv.c:31
enum _TOKEN_TYPE TOKEN_TYPE
#define SYSTEM_LUID
Definition: setypes.h:672
PACCESS_TOKEN NTAPI PsReferenceImpersonationToken(IN PETHREAD Thread, OUT PBOOLEAN CopyOnOpen, OUT PBOOLEAN EffectiveOnly, OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
Definition: security.c:808
const LUID SeTcbPrivilege
Definition: priv.c:24
FORCEINLINE ULONG ObpValidateAttributes(IN ULONG Attributes, IN KPROCESSOR_MODE PreviousMode)
Definition: ob_x.h:22
#define _In_
Definition: no_sal2.h:158
#define TAG_ACL
Definition: tag.h:174
static VOID SepRemovePrivilegeToken(_Inout_ PTOKEN Token, _In_ ULONG Index)
Definition: token.c:242
#define SE_IMPERSONATE_PRIVILEGE
Definition: security.c:683
static VOID SepDeleteTokenLock(_Inout_ PTOKEN Token)
Deletes a lock of a token.
Definition: token.c:129
const LUID SeShutdownPrivilege
Definition: priv.c:36
_SEH2_END
Definition: create.c:4400
PERESOURCE TokenLock
Definition: setypes.h:191
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2932
LONG NTAPI ExSystemExceptionFilter(VOID)
Definition: harderr.c:351
GENERIC_MAPPING GenericMapping
Definition: obtypes.h:358
#define TOKEN_HAS_ADMIN_GROUP
Definition: setypes.h:1128
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 i
Definition: glfuncs.h:248
NTSTATUS NTAPI SeQueryInformationToken(IN PACCESS_TOKEN AccessToken, IN TOKEN_INFORMATION_CLASS TokenInformationClass, OUT PVOID *TokenInformation)
Definition: token.c:1366
struct _TOKEN * PTOKEN
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
VOID NTAPI SepDeleteToken(PVOID ObjectBody)
Definition: token.c:869
#define SE_BACKUP_PRIVILEGES_CHECKED
Definition: setypes.h:1133
VOID NTAPI ExAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
Definition: uuid.c:334
SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY]
Definition: setypes.h:964
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
LUID TokenId
Definition: setypes.h:187
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: lsa.idl:65
_In_ ULONG _Out_opt_ PULONG RequiredLength
Definition: wmifuncs.h:29
unsigned int * PULONG
Definition: retypes.h:1
BOOLEAN NTAPI SeTokenIsAdmin(IN PACCESS_TOKEN Token)
Definition: token.c:1850
_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 Owner
Definition: rtlfuncs.h:1556
#define NULL
Definition: types.h:112
_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 LogonId
#define STATUS_INVALID_OWNER
Definition: ntstatus.h:326
VOID NTAPI SepReleaseSid(IN PSID CapturedSid, IN KPROCESSOR_MODE AccessMode, IN BOOLEAN CaptureIfKernel)
Definition: sid.c:338
VOID NTAPI PsDereferencePrimaryToken(IN PACCESS_TOKEN PrimaryToken)
Definition: security.c:861
#define DPRINT1
Definition: precomp.h:8
BOOL WINAPI IsChild(_In_ HWND, _In_ HWND)
const LUID SeSecurityPrivilege
Definition: priv.c:25
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtSetInformationToken(_In_ HANDLE TokenHandle, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _In_reads_bytes_(TokenInformationLength) PVOID TokenInformation, _In_ ULONG TokenInformationLength)
Definition: token.c:2471
#define RtlInterlockedSetBits(Flags, Flag)
Definition: rtlfuncs.h:3436
NTSYSAPI void WINAPI RtlCopyLuid(PLUID, const LUID *)
NTSTATUS NTAPI NtOpenThreadToken(IN HANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN OpenAsSelf, OUT PHANDLE TokenHandle)
Definition: token.c:3915
VOID FASTCALL ObFastDereferenceObject(IN PEX_FAST_REF FastRef, IN PVOID Object)
Definition: obref.c:169
PSID SeLocalSystemSid
Definition: sid.c:40
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
$ULONG GroupCount
Definition: setypes.h:960
#define _When_(c, a)
Definition: no_sal2.h:38
#define SepAcquireTokenLockShared(Token)
Definition: se.h:205
#define OUT
Definition: typedefs.h:40
#define ObReferenceObject
Definition: obfuncs.h:204
static NTSTATUS SepCreateTokenLock(_Inout_ PTOKEN Token)
Creates a lock for the token.
Definition: token.c:99
#define THREAD_QUERY_INFORMATION
Definition: pstypes.h:141
#define TOKEN_HAS_IMPERSONATE_PRIVILEGE
Definition: setypes.h:1132
ULONG ERESOURCE
Definition: env_spec_w32.h:594
unsigned int ULONG
Definition: retypes.h:1
#define SE_BACKUP_PRIVILEGE
Definition: security.c:671
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define UNIMPLEMENTED
Definition: debug.h:115
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
struct _TOKEN_USER * PTOKEN_USER
_In_ ACCESS_MASK _In_ BOOLEAN OpenAsSelf
Definition: zwfuncs.h:699
#define ULONG_PTR
Definition: config.h:101
SID_AND_ATTRIBUTES User
Definition: setypes.h:956
static const INFORMATION_CLASS_INFO SeTokenInformationClass[]
Definition: token.c:42
#define ALIGN_UP_BY(size, align)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
static ULONG RtlLengthSidAndAttributes(ULONG Count, PSID_AND_ATTRIBUTES Src)
Definition: token.c:375
static NTSTATUS SepCompareTokens(IN PTOKEN FirstToken, IN PTOKEN SecondToken, OUT PBOOLEAN Equal)
Definition: token.c:139
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtDuplicateToken(_In_ HANDLE ExistingTokenHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ BOOLEAN EffectiveOnly, _In_ TOKEN_TYPE TokenType, _Out_ PHANDLE NewTokenHandle)
Definition: token.c:2998
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define STATUS_SUCCESS
Definition: shellext.h:65
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define TOKEN_HAS_BACKUP_PRIVILEGE
Definition: setypes.h:1125
#define DPRINT
Definition: sndvol32.h:71
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN EffectiveOnly
Definition: sefuncs.h:417
struct _TOKEN_STATISTICS TOKEN_STATISTICS
unsigned long Ulong
Definition: utypes.h:42
OB_DELETE_METHOD DeleteProcedure
Definition: obtypes.h:369
#define SeLengthSid(Sid)
Definition: sefuncs.h:570
#define TOKEN_ADJUST_SESSIONID
Definition: setypes.h:879
NTSTATUS NTAPI SepCaptureSid(IN PSID InputSid, IN KPROCESSOR_MODE AccessMode, IN POOL_TYPE PoolType, IN BOOLEAN CaptureIfKernel, OUT PSID *CapturedSid)
Definition: sid.c:270
#define TOKEN_ADJUST_PRIVILEGES
Definition: setypes.h:876
#define TOKEN_SESSION_NOT_REFERENCED
Definition: setypes.h:1130
BOOLEAN NTAPI SeTokenIsWriteRestricted(IN PACCESS_TOKEN Token)
Definition: token.c:1878
struct _TOKEN TOKEN
const LUID SeAuditPrivilege
Definition: priv.c:38
NTSTATUS NTAPI SeExchangePrimaryToken(_In_ PEPROCESS Process, _In_ PACCESS_TOKEN NewAccessToken, _Out_ PACCESS_TOKEN *OldAccessToken)
Definition: token.c:281
NTSTATUS NTAPI SeCopyClientToken(IN PACCESS_TOKEN Token, IN SECURITY_IMPERSONATION_LEVEL Level, IN KPROCESSOR_MODE PreviousMode, OUT PACCESS_TOKEN *NewToken)
Definition: token.c:840
ULONG ACCESS_MASK
Definition: nt_native.h:40
struct _TOKEN_PRIMARY_GROUP TOKEN_PRIMARY_GROUP
#define TOKEN_EXECUTE
Definition: setypes.h:904
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtAdjustPrivilegesToken(_In_ HANDLE TokenHandle, _In_ BOOLEAN DisableAllPrivileges, _In_opt_ PTOKEN_PRIVILEGES NewState, _In_ ULONG BufferLength, _Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PTOKEN_PRIVILEGES PreviousState, _When_(PreviousState!=NULL, _Out_) PULONG ReturnLength)
Definition: token.c:3276
_In_ TOKEN_INFORMATION_CLASS TokenInformationClass
Definition: sefuncs.h:318
NTSTATUS NTAPI SepCreateImpersonationTokenDacl(_In_ PTOKEN Token, _In_ PTOKEN PrimaryToken, _Out_ PACL *Dacl)
Definition: acl.c:225
#define ULONG_MAX
Definition: limits.h:44
NTSYSAPI BOOLEAN NTAPI RtlEqualSid(_In_ PSID Sid1, _In_ PSID Sid2)
struct _TOKEN_ORIGIN TOKEN_ORIGIN
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ WDF_POWER_DEVICE_STATE PreviousState
Definition: wdfdevice.h:829
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE TokenType
Definition: sefuncs.h:417
#define TOKEN_IS_RESTRICTED
Definition: setypes.h:1129
#define PAGED_CODE()
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
VOID NTAPI PsDereferenceImpersonationToken(IN PACCESS_TOKEN ImpersonationToken)
Definition: security.c:847