ReactOS  0.4.15-dev-1377-ga59cecd
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 ERESOURCE SepTokenLock; // FIXME: Global lock!
31 
32 TOKEN_SOURCE SeSystemTokenSource = {"*SYSTEM*", {0}};
35 
37  TOKEN_READ,
41 };
42 
43 static const INFORMATION_CLASS_INFO SeTokenInformationClass[] = {
44 
45  /* Class 0 not used, blame MS! */
46  ICI_SQ_SAME( 0, 0, 0),
47 
48  /* TokenUser */
49  ICI_SQ_SAME( sizeof(TOKEN_USER), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET_SIZE_VARIABLE ),
50  /* TokenGroups */
51  ICI_SQ_SAME( sizeof(TOKEN_GROUPS), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET_SIZE_VARIABLE ),
52  /* TokenPrivileges */
53  ICI_SQ_SAME( sizeof(TOKEN_PRIVILEGES), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET_SIZE_VARIABLE ),
54  /* TokenOwner */
55  ICI_SQ_SAME( sizeof(TOKEN_OWNER), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
56  /* TokenPrimaryGroup */
57  ICI_SQ_SAME( sizeof(TOKEN_PRIMARY_GROUP), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
58  /* TokenDefaultDacl */
59  ICI_SQ_SAME( sizeof(TOKEN_DEFAULT_DACL), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
60  /* TokenSource */
61  ICI_SQ_SAME( sizeof(TOKEN_SOURCE), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET_SIZE_VARIABLE ),
62  /* TokenType */
63  ICI_SQ_SAME( sizeof(TOKEN_TYPE), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
64  /* TokenImpersonationLevel */
65  ICI_SQ_SAME( sizeof(SECURITY_IMPERSONATION_LEVEL), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
66  /* TokenStatistics */
67  ICI_SQ_SAME( sizeof(TOKEN_STATISTICS), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET_SIZE_VARIABLE ),
68  /* TokenRestrictedSids */
69  ICI_SQ_SAME( sizeof(TOKEN_GROUPS), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
70  /* TokenSessionId */
71  ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY | ICIF_SET ),
72  /* TokenGroupsAndPrivileges */
73  ICI_SQ_SAME( sizeof(TOKEN_GROUPS_AND_PRIVILEGES), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
74  /* TokenSessionReference */
75  ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_SET | ICIF_QUERY_SIZE_VARIABLE ),
76  /* TokenSandBoxInert */
77  ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
78  /* TokenAuditPolicy */
79  ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG), ICIF_QUERY | ICIF_SET | ICIF_QUERY_SIZE_VARIABLE ),
80  /* TokenOrigin */
81  ICI_SQ_SAME( sizeof(TOKEN_ORIGIN), sizeof(ULONG), ICIF_QUERY | ICIF_SET | ICIF_QUERY_SIZE_VARIABLE ),
82 };
83 
84 /* FUNCTIONS *****************************************************************/
85 
86 static NTSTATUS
88  IN PTOKEN SecondToken,
89  OUT PBOOLEAN Equal)
90 {
92 
93  ASSERT(FirstToken != SecondToken);
94 
95  /* Lock the tokens */
96  SepAcquireTokenLockShared(FirstToken);
97  SepAcquireTokenLockShared(SecondToken);
98 
99  /* FIXME: Check if every SID that is present in either token is also present in the other one */
100 
101  Restricted = SeTokenIsRestricted(FirstToken);
102  if (Restricted == SeTokenIsRestricted(SecondToken))
103  {
104  if (Restricted)
105  {
106  /* FIXME: Check if every SID that is restricted in either token is also restricted in the other one */
107  }
108 
109  /* FIXME: Check if every privilege that is present in either token is also present in the other one */
110  DPRINT1("FIXME: Pretending tokens are equal!\n");
111  IsEqual = TRUE;
112  }
113 
114  /* Unlock the tokens */
115  SepReleaseTokenLock(SecondToken);
116  SepReleaseTokenLock(FirstToken);
117 
118  *Equal = IsEqual;
119  return STATUS_SUCCESS;
120 }
121 
122 static
123 VOID
126  _In_ ULONG Index)
127 {
128  ULONG TokenFlag;
129  ASSERT(Index < Token->PrivilegeCount);
130 
131  /* The high part of all values we are interested in is 0 */
132  if (Token->Privileges[Index].Luid.HighPart != 0)
133  {
134  return;
135  }
136 
137  /* Check for certain privileges to update flags */
138  if (Token->Privileges[Index].Luid.LowPart == SE_CHANGE_NOTIFY_PRIVILEGE)
139  {
140  TokenFlag = TOKEN_HAS_TRAVERSE_PRIVILEGE;
141  }
142  else if (Token->Privileges[Index].Luid.LowPart == SE_BACKUP_PRIVILEGE)
143  {
144  TokenFlag = TOKEN_HAS_BACKUP_PRIVILEGE;
145  }
146  else if (Token->Privileges[Index].Luid.LowPart == SE_RESTORE_PRIVILEGE)
147  {
148  TokenFlag = TOKEN_HAS_RESTORE_PRIVILEGE;
149  }
150  else if (Token->Privileges[Index].Luid.LowPart == SE_IMPERSONATE_PRIVILEGE)
151  {
153  }
154  else
155  {
156  /* Nothing to do */
157  return;
158  }
159 
160  /* Check if the specified privilege is enabled */
161  if (Token->Privileges[Index].Attributes & SE_PRIVILEGE_ENABLED)
162  {
163  /* It is enabled, so set the flag */
164  Token->TokenFlags |= TokenFlag;
165  }
166  else
167  {
168  /* Is is disabled, so remove the flag */
169  Token->TokenFlags &= ~TokenFlag;
170  }
171 }
172 
173 static
174 VOID
177 {
178  ULONG i;
179 
180  /* Loop all privileges */
181  for (i = 0; i < Token->PrivilegeCount; i++)
182  {
183  /* Updates the flags dor this privilege */
185  }
186 }
187 
188 static
189 VOID
192  _In_ ULONG Index)
193 {
194  ULONG MoveCount;
195  ASSERT(Index < Token->PrivilegeCount);
196 
197  /* Calculate the number of trailing privileges */
198  MoveCount = Token->PrivilegeCount - Index - 1;
199  if (MoveCount != 0)
200  {
201  /* Move them one location ahead */
202  RtlMoveMemory(&Token->Privileges[Index],
203  &Token->Privileges[Index + 1],
204  MoveCount * sizeof(LUID_AND_ATTRIBUTES));
205  }
206 
207  /* Update privilege count */
208  Token->PrivilegeCount--;
209 }
210 
211 VOID
212 NTAPI
214 {
216 }
217 
218 NTSTATUS
219 NTAPI
221  PVOID Src)
222 {
224  return STATUS_NOT_IMPLEMENTED;
225 }
226 
227 NTSTATUS
228 NTAPI
231  _In_ PACCESS_TOKEN NewAccessToken,
232  _Out_ PACCESS_TOKEN* OldAccessToken)
233 {
234  PTOKEN OldToken;
235  PTOKEN NewToken = (PTOKEN)NewAccessToken;
236 
237  PAGED_CODE();
238 
239  if (NewToken->TokenType != TokenPrimary)
240  return STATUS_BAD_TOKEN_TYPE;
241 
242  if (NewToken->TokenInUse)
243  {
246 
247  /* Maybe we're trying to set the same token */
248  OldToken = PsReferencePrimaryToken(Process);
249  if (OldToken == NewToken)
250  {
251  /* So it's a nop. */
252  *OldAccessToken = OldToken;
253  return STATUS_SUCCESS;
254  }
255 
256  Status = SepCompareTokens(OldToken, NewToken, &IsEqual);
257  if (!NT_SUCCESS(Status))
258  {
259  PsDereferencePrimaryToken(OldToken);
260  *OldAccessToken = NULL;
261  return Status;
262  }
263 
264  if (!IsEqual)
265  {
266  PsDereferencePrimaryToken(OldToken);
267  *OldAccessToken = NULL;
269  }
270  /* Silently return STATUS_SUCCESS but do not set the new token,
271  * as it's already in use elsewhere. */
272  *OldAccessToken = OldToken;
273  return STATUS_SUCCESS;
274  }
275 
276  /* Lock the new token */
278 
279  /* Mark new token in use */
280  NewToken->TokenInUse = TRUE;
281 
282  // TODO: Set a correct SessionId for NewToken
283 
284  /* Unlock the new token */
285  SepReleaseTokenLock(NewToken);
286 
287  /* Reference the new token */
288  ObReferenceObject(NewToken);
289 
290  /* Replace the old with the new */
291  OldToken = ObFastReplaceObject(&Process->Token, NewToken);
292 
293  /* Lock the old token */
295 
296  /* Mark the old token as free */
297  OldToken->TokenInUse = FALSE;
298 
299  /* Unlock the old token */
300  SepReleaseTokenLock(OldToken);
301 
302  *OldAccessToken = (PACCESS_TOKEN)OldToken;
303  return STATUS_SUCCESS;
304 }
305 
306 VOID
307 NTAPI
309 {
310  PTOKEN OldToken;
311 
312  /* Remove the Token */
313  OldToken = ObFastReplaceObject(&Process->Token, NULL);
314 
315  /* Mark the Old Token as free */
316  OldToken->TokenInUse = FALSE;
317 
318  /* Dereference the Token */
319  ObDereferenceObject(OldToken);
320 }
321 
322 static ULONG
325 {
326  ULONG i;
327  ULONG uLength;
328 
329  PAGED_CODE();
330 
331  uLength = Count * sizeof(SID_AND_ATTRIBUTES);
332  for (i = 0; i < Count; i++)
333  uLength += RtlLengthSid(Src[i].Sid);
334 
335  return uLength;
336 }
337 
338 
339 static NTSTATUS
341  _In_ PTOKEN Token,
343  _In_opt_ PSID DefaultOwner,
344  _Out_opt_ PULONG PrimaryGroupIndex,
345  _Out_opt_ PULONG DefaultOwnerIndex)
346 {
347  ULONG i;
348 
349  /* We should return at least a search result */
350  if (!PrimaryGroupIndex && !DefaultOwnerIndex)
352 
353  if (PrimaryGroupIndex)
354  {
355  /* Initialize with an invalid index */
356  // Token->PrimaryGroup = NULL;
357  *PrimaryGroupIndex = Token->UserAndGroupCount;
358  }
359 
360  if (DefaultOwnerIndex)
361  {
362  if (DefaultOwner)
363  {
364  /* An owner is specified: check whether this is actually the user */
365  if (RtlEqualSid(Token->UserAndGroups[0].Sid, DefaultOwner))
366  {
367  /*
368  * It's the user (first element in array): set it
369  * as the owner and stop the search for it.
370  */
371  *DefaultOwnerIndex = 0;
372  DefaultOwnerIndex = NULL;
373  }
374  else
375  {
376  /* An owner is specified: initialize with an invalid index */
377  *DefaultOwnerIndex = Token->UserAndGroupCount;
378  }
379  }
380  else
381  {
382  /*
383  * No owner specified: set the user (first element in array)
384  * as the owner and stop the search for it.
385  */
386  *DefaultOwnerIndex = 0;
387  DefaultOwnerIndex = NULL;
388  }
389  }
390 
391  /* Validate and set the primary group and default owner indices */
392  for (i = 0; i < Token->UserAndGroupCount; i++)
393  {
394  /* Stop the search if we have found what we searched for */
395  if (!PrimaryGroupIndex && !DefaultOwnerIndex)
396  break;
397 
398  if (DefaultOwnerIndex && DefaultOwner &&
399  RtlEqualSid(Token->UserAndGroups[i].Sid, DefaultOwner) &&
400  (Token->UserAndGroups[i].Attributes & SE_GROUP_OWNER))
401  {
402  /* Owner is found, stop the search for it */
403  *DefaultOwnerIndex = i;
404  DefaultOwnerIndex = NULL;
405  }
406 
407  if (PrimaryGroupIndex &&
408  RtlEqualSid(Token->UserAndGroups[i].Sid, PrimaryGroup))
409  {
410  /* Primary group is found, stop the search for it */
411  // Token->PrimaryGroup = Token->UserAndGroups[i].Sid;
412  *PrimaryGroupIndex = i;
413  PrimaryGroupIndex = NULL;
414  }
415  }
416 
417  if (DefaultOwnerIndex)
418  {
419  if (*DefaultOwnerIndex == Token->UserAndGroupCount)
420  return STATUS_INVALID_OWNER;
421  }
422 
423  if (PrimaryGroupIndex)
424  {
425  if (*PrimaryGroupIndex == Token->UserAndGroupCount)
426  // if (Token->PrimaryGroup == NULL)
428  }
429 
430  return STATUS_SUCCESS;
431 }
432 
433 
434 NTSTATUS
435 NTAPI
437  _In_ PTOKEN Token,
443  _Out_ PTOKEN* NewAccessToken)
444 {
446  PTOKEN AccessToken;
447  PVOID EndMem;
448  ULONG VariableLength;
449  ULONG TotalSize;
450 
451  PAGED_CODE();
452 
453  /* Compute how much size we need to allocate for the token */
454  VariableLength = Token->VariableLength;
455  TotalSize = FIELD_OFFSET(TOKEN, VariablePart) + VariableLength;
456 
460  PreviousMode,
461  NULL,
462  TotalSize,
463  0,
464  0,
465  (PVOID*)&AccessToken);
466  if (!NT_SUCCESS(Status))
467  {
468  DPRINT1("ObCreateObject() failed (Status 0x%lx)\n", Status);
469  return Status;
470  }
471 
472  /* Zero out the buffer and initialize the token */
473  RtlZeroMemory(AccessToken, TotalSize);
474 
475  ExAllocateLocallyUniqueId(&AccessToken->TokenId);
476 
477  AccessToken->TokenType = TokenType;
478  AccessToken->ImpersonationLevel = Level;
479 
480  AccessToken->TokenLock = &SepTokenLock; // FIXME: Global lock!
481 
482  /* Copy the immutable fields */
483  RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
484  &Token->TokenSource.SourceIdentifier);
485  RtlCopyMemory(AccessToken->TokenSource.SourceName,
486  Token->TokenSource.SourceName,
487  sizeof(Token->TokenSource.SourceName));
488 
489  AccessToken->AuthenticationId = Token->AuthenticationId;
490  AccessToken->ParentTokenId = Token->ParentTokenId;
491  AccessToken->ExpirationTime = Token->ExpirationTime;
492  AccessToken->OriginatingLogonSession = Token->OriginatingLogonSession;
493 
494 
495  /* Lock the source token and copy the mutable fields */
497 
498  AccessToken->SessionId = Token->SessionId;
499  RtlCopyLuid(&AccessToken->ModifiedId, &Token->ModifiedId);
500 
501  AccessToken->TokenFlags = Token->TokenFlags & ~TOKEN_SESSION_NOT_REFERENCED;
502 
503  /* Copy and reference the logon session */
504  // RtlCopyLuid(&AccessToken->AuthenticationId, &Token->AuthenticationId);
505  Status = SepRmReferenceLogonSession(&AccessToken->AuthenticationId);
506  if (!NT_SUCCESS(Status))
507  {
508  /* No logon session could be found, bail out */
509  DPRINT1("SepRmReferenceLogonSession() failed (Status 0x%lx)\n", Status);
510  /* Set the flag for proper cleanup by the delete procedure */
511  AccessToken->TokenFlags |= TOKEN_SESSION_NOT_REFERENCED;
512  goto Quit;
513  }
514 
515  /* Assign the data that reside in the TOKEN's variable information area */
516  AccessToken->VariableLength = VariableLength;
517  EndMem = (PVOID)&AccessToken->VariablePart;
518 
519  /* Copy the privileges */
520  AccessToken->PrivilegeCount = 0;
521  AccessToken->Privileges = NULL;
522  if (Token->Privileges && (Token->PrivilegeCount > 0))
523  {
524  ULONG PrivilegesLength = Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
525  PrivilegesLength = ALIGN_UP_BY(PrivilegesLength, sizeof(PVOID));
526 
527  ASSERT(VariableLength >= PrivilegesLength);
528 
529  AccessToken->PrivilegeCount = Token->PrivilegeCount;
530  AccessToken->Privileges = EndMem;
531  EndMem = (PVOID)((ULONG_PTR)EndMem + PrivilegesLength);
532  VariableLength -= PrivilegesLength;
533 
534  RtlCopyMemory(AccessToken->Privileges,
535  Token->Privileges,
536  AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
537  }
538 
539  /* Copy the user and groups */
540  AccessToken->UserAndGroupCount = 0;
541  AccessToken->UserAndGroups = NULL;
542  if (Token->UserAndGroups && (Token->UserAndGroupCount > 0))
543  {
544  AccessToken->UserAndGroupCount = Token->UserAndGroupCount;
545  AccessToken->UserAndGroups = EndMem;
546  EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
547  VariableLength -= ((ULONG_PTR)EndMem - (ULONG_PTR)AccessToken->UserAndGroups);
548 
549  Status = RtlCopySidAndAttributesArray(AccessToken->UserAndGroupCount,
550  Token->UserAndGroups,
551  VariableLength,
552  AccessToken->UserAndGroups,
553  EndMem,
554  &EndMem,
555  &VariableLength);
556  if (!NT_SUCCESS(Status))
557  {
558  DPRINT1("RtlCopySidAndAttributesArray(UserAndGroups) failed (Status 0x%lx)\n", Status);
559  goto Quit;
560  }
561  }
562 
563 #if 1
564  {
565  ULONG PrimaryGroupIndex;
566 
567  /* Find the token primary group */
569  Token->PrimaryGroup,
570  NULL,
571  &PrimaryGroupIndex,
572  NULL);
573  if (!NT_SUCCESS(Status))
574  {
575  DPRINT1("SepFindPrimaryGroupAndDefaultOwner failed (Status 0x%lx)\n", Status);
576  goto Quit;
577  }
578  AccessToken->PrimaryGroup = AccessToken->UserAndGroups[PrimaryGroupIndex].Sid;
579  }
580 #else
581  AccessToken->PrimaryGroup = (PVOID)((ULONG_PTR)AccessToken + (ULONG_PTR)Token->PrimaryGroup - (ULONG_PTR)Token->UserAndGroups);
582 #endif
583  AccessToken->DefaultOwnerIndex = Token->DefaultOwnerIndex;
584 
585  /* Copy the restricted SIDs */
586  AccessToken->RestrictedSidCount = 0;
587  AccessToken->RestrictedSids = NULL;
588  if (Token->RestrictedSids && (Token->RestrictedSidCount > 0))
589  {
590  AccessToken->RestrictedSidCount = Token->RestrictedSidCount;
591  AccessToken->RestrictedSids = EndMem;
592  EndMem = &AccessToken->RestrictedSids[AccessToken->RestrictedSidCount];
593  VariableLength -= ((ULONG_PTR)EndMem - (ULONG_PTR)AccessToken->RestrictedSids);
594 
595  Status = RtlCopySidAndAttributesArray(AccessToken->RestrictedSidCount,
596  Token->RestrictedSids,
597  VariableLength,
598  AccessToken->RestrictedSids,
599  EndMem,
600  &EndMem,
601  &VariableLength);
602  if (!NT_SUCCESS(Status))
603  {
604  DPRINT1("RtlCopySidAndAttributesArray(RestrictedSids) failed (Status 0x%lx)\n", Status);
605  goto Quit;
606  }
607  }
608 
609 
610  //
611  // FIXME: Implement the "EffectiveOnly" option, that removes all
612  // the disabled parts (privileges and groups) of the token.
613  //
614 
615 
616  //
617  // NOTE: So far our dynamic area only contains
618  // the default dacl, so this makes the following
619  // code pretty simple. The day where it stores
620  // other data, the code will require adaptations.
621  //
622 
623  /* Now allocate the TOKEN's dynamic information area and set the data */
624  AccessToken->DynamicAvailable = 0; // Unused memory in the dynamic area.
625  AccessToken->DynamicPart = NULL;
626  if (Token->DynamicPart && Token->DefaultDacl)
627  {
628  AccessToken->DynamicPart = ExAllocatePoolWithTag(PagedPool,
629  Token->DefaultDacl->AclSize,
631  if (AccessToken->DynamicPart == NULL)
632  {
634  goto Quit;
635  }
636  EndMem = (PVOID)AccessToken->DynamicPart;
637 
638  AccessToken->DefaultDacl = EndMem;
639 
640  RtlCopyMemory(AccessToken->DefaultDacl,
641  Token->DefaultDacl,
642  Token->DefaultDacl->AclSize);
643  }
644 
645  /* Unlock the source token */
647 
648  /* Return the token */
649  *NewAccessToken = AccessToken;
651 
652 Quit:
653  if (!NT_SUCCESS(Status))
654  {
655  /* Unlock the source token */
657 
658  /* Dereference the token, the delete procedure will clean it up */
659  ObDereferenceObject(AccessToken);
660  }
661 
662  return Status;
663 }
664 
665 NTSTATUS
666 NTAPI
668  OUT PTOKEN *Token,
669  IN BOOLEAN InUse,
671 {
672  PTOKEN NewToken;
675 
676  /* Initialize the attributes and duplicate it */
678  Status = SepDuplicateToken(ParentToken,
680  FALSE,
681  TokenPrimary,
682  ParentToken->ImpersonationLevel,
683  KernelMode,
684  &NewToken);
685  if (NT_SUCCESS(Status))
686  {
687  /* Insert it */
688  Status = ObInsertObject(NewToken,
689  NULL,
690  0,
691  0,
692  NULL,
693  NULL);
694  if (NT_SUCCESS(Status))
695  {
696  /* Set the session ID */
697  NewToken->SessionId = SessionId;
698  NewToken->TokenInUse = InUse;
699 
700  /* Return the token */
701  *Token = NewToken;
702  }
703  }
704 
705  /* Return status */
706  return Status;
707 }
708 
709 NTSTATUS
710 NTAPI
713 {
714  PTOKEN ProcessToken;
715  LUID ProcessTokenId, CallerParentId;
716 
717  /* Assume failure */
718  *IsChild = FALSE;
719 
720  /* Reference the process token */
722  if (!ProcessToken)
723  return STATUS_UNSUCCESSFUL;
724 
725  /* Get its token ID */
726  ProcessTokenId = ProcessToken->TokenId;
727 
728  /* Dereference the token */
730 
731  /* Get our parent token ID */
732  CallerParentId = Token->ParentTokenId;
733 
734  /* Compare the token IDs */
735  if (RtlEqualLuid(&CallerParentId, &ProcessTokenId))
736  *IsChild = TRUE;
737 
738  /* Return success */
739  return STATUS_SUCCESS;
740 }
741 
742 NTSTATUS
743 NTAPI
745  OUT PBOOLEAN IsSibling)
746 {
747  PTOKEN ProcessToken;
748  LUID ProcessParentId, ProcessAuthId;
749  LUID CallerParentId, CallerAuthId;
750 
751  /* Assume failure */
752  *IsSibling = FALSE;
753 
754  /* Reference the process token */
756  if (!ProcessToken)
757  return STATUS_UNSUCCESSFUL;
758 
759  /* Get its parent and authentication IDs */
760  ProcessParentId = ProcessToken->ParentTokenId;
761  ProcessAuthId = ProcessToken->AuthenticationId;
762 
763  /* Dereference the token */
765 
766  /* Get our parent and authentication IDs */
767  CallerParentId = Token->ParentTokenId;
768  CallerAuthId = Token->AuthenticationId;
769 
770  /* Compare the token IDs */
771  if (RtlEqualLuid(&CallerParentId, &ProcessParentId) &&
772  RtlEqualLuid(&CallerAuthId, &ProcessAuthId))
773  {
774  *IsSibling = TRUE;
775  }
776 
777  /* Return success */
778  return STATUS_SUCCESS;
779 }
780 
781 NTSTATUS
782 NTAPI
786  OUT PACCESS_TOKEN* NewToken)
787 {
790 
791  PAGED_CODE();
792 
794  NULL,
795  0,
796  NULL,
797  NULL);
798 
801  FALSE,
803  Level,
804  PreviousMode,
805  (PTOKEN*)NewToken);
806 
807  return Status;
808 }
809 
810 VOID
811 NTAPI
813 {
814  PTOKEN AccessToken = (PTOKEN)ObjectBody;
815 
816  DPRINT("SepDeleteToken()\n");
817 
818  /* Dereference the logon session */
819  if ((AccessToken->TokenFlags & TOKEN_SESSION_NOT_REFERENCED) == 0)
821 
822  /* Delete the dynamic information area */
823  if (AccessToken->DynamicPart)
825 }
826 
827 
828 CODE_SEG("INIT")
829 VOID
830 NTAPI
832 {
834  OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
835 
836  ExInitializeResource(&SepTokenLock); // FIXME: Global lock!
837 
838  DPRINT("Creating Token Object Type\n");
839 
840  /* Initialize the Token type */
841  RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
842  RtlInitUnicodeString(&Name, L"Token");
843  ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
844  ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
845  ObjectTypeInitializer.SecurityRequired = TRUE;
846  ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(TOKEN);
847  ObjectTypeInitializer.GenericMapping = SepTokenMapping;
848  ObjectTypeInitializer.PoolType = PagedPool;
849  ObjectTypeInitializer.ValidAccessMask = TOKEN_ALL_ACCESS;
850  ObjectTypeInitializer.UseDefaultObject = TRUE;
851  ObjectTypeInitializer.DeleteProcedure = SepDeleteToken;
852  ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &SeTokenObjectType);
853 }
854 
855 VOID
856 NTAPI
858  IN PTOKEN Token)
859 {
860  PAGED_CODE();
861 
862  /* Sanity checks */
863  ASSERT(Token->TokenType == TokenPrimary);
864  ASSERT(!Token->TokenInUse);
865 
866  /* Clean any previous token */
867  if (Process->Token.Object) SeDeassignPrimaryToken(Process);
868 
869  /* Set the new token */
871  Token->TokenInUse = TRUE;
873 }
874 
875 NTSTATUS
876 NTAPI
884  _In_ PLUID AuthenticationId,
885  _In_ PLARGE_INTEGER ExpirationTime,
887  _In_ ULONG GroupCount,
889  _In_ ULONG GroupsLength,
890  _In_ ULONG PrivilegeCount,
894  _In_opt_ PACL DefaultDacl,
896  _In_ BOOLEAN SystemToken)
897 {
899  PTOKEN AccessToken;
900  ULONG TokenFlags = 0;
901  ULONG PrimaryGroupIndex, DefaultOwnerIndex;
902  LUID TokenId;
903  LUID ModifiedId;
904  PVOID EndMem;
905  ULONG PrivilegesLength;
906  ULONG UserGroupsLength;
907  ULONG VariableLength;
908  ULONG TotalSize;
909  ULONG i;
910 
911  PAGED_CODE();
912 
913  /* Loop all groups */
914  for (i = 0; i < GroupCount; i++)
915  {
916  /* Check for mandatory groups */
918  {
919  /* Force them to be enabled */
921  }
922 
923  /* Check of the group is an admin group */
925  {
926  /* Remember this so we can optimize queries later */
927  TokenFlags |= TOKEN_HAS_ADMIN_GROUP;
928  }
929  }
930 
931  /* Allocate unique IDs for the token */
932  ExAllocateLocallyUniqueId(&TokenId);
933  ExAllocateLocallyUniqueId(&ModifiedId);
934 
935  /* Compute how much size we need to allocate for the token */
936 
937  /* Privileges size */
938  PrivilegesLength = PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
939  PrivilegesLength = ALIGN_UP_BY(PrivilegesLength, sizeof(PVOID));
940 
941  /* User and groups size */
942  UserGroupsLength = (1 + GroupCount) * sizeof(SID_AND_ATTRIBUTES);
943  UserGroupsLength += RtlLengthSid(User->Sid);
944  for (i = 0; i < GroupCount; i++)
945  {
946  UserGroupsLength += RtlLengthSid(Groups[i].Sid);
947  }
948  UserGroupsLength = ALIGN_UP_BY(UserGroupsLength, sizeof(PVOID));
949 
950  /* Add the additional groups array length */
951  UserGroupsLength += ALIGN_UP_BY(GroupsLength, sizeof(PVOID));
952 
953  VariableLength = PrivilegesLength + UserGroupsLength;
954  TotalSize = FIELD_OFFSET(TOKEN, VariablePart) + VariableLength;
955 
959  PreviousMode,
960  NULL,
961  TotalSize,
962  0,
963  0,
964  (PVOID*)&AccessToken);
965  if (!NT_SUCCESS(Status))
966  {
967  DPRINT1("ObCreateObject() failed (Status 0x%lx)\n", Status);
968  return Status;
969  }
970 
971  /* Zero out the buffer and initialize the token */
972  RtlZeroMemory(AccessToken, TotalSize);
973 
974  RtlCopyLuid(&AccessToken->TokenId, &TokenId);
975 
976  AccessToken->TokenType = TokenType;
977  AccessToken->ImpersonationLevel = ImpersonationLevel;
978 
979  AccessToken->TokenLock = &SepTokenLock; // FIXME: Global lock!
980 
981  RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
982  &TokenSource->SourceIdentifier);
983  RtlCopyMemory(AccessToken->TokenSource.SourceName,
984  TokenSource->SourceName,
985  sizeof(TokenSource->SourceName));
986 
987  AccessToken->ExpirationTime = *ExpirationTime;
988  RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
989 
990  AccessToken->TokenFlags = TokenFlags & ~TOKEN_SESSION_NOT_REFERENCED;
991 
992  /* Copy and reference the logon session */
993  RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
994  Status = SepRmReferenceLogonSession(&AccessToken->AuthenticationId);
995  if (!NT_SUCCESS(Status))
996  {
997  /* No logon session could be found, bail out */
998  DPRINT1("SepRmReferenceLogonSession() failed (Status 0x%lx)\n", Status);
999  /* Set the flag for proper cleanup by the delete procedure */
1000  AccessToken->TokenFlags |= TOKEN_SESSION_NOT_REFERENCED;
1001  goto Quit;
1002  }
1003 
1004  /* Assign the data that reside in the TOKEN's variable information area */
1005  AccessToken->VariableLength = VariableLength;
1006  EndMem = (PVOID)&AccessToken->VariablePart;
1007 
1008  /* Copy the privileges */
1009  AccessToken->PrivilegeCount = PrivilegeCount;
1010  AccessToken->Privileges = NULL;
1011  if (PrivilegeCount > 0)
1012  {
1013  AccessToken->Privileges = EndMem;
1014  EndMem = (PVOID)((ULONG_PTR)EndMem + PrivilegesLength);
1015  VariableLength -= PrivilegesLength;
1016 
1017  if (PreviousMode != KernelMode)
1018  {
1019  _SEH2_TRY
1020  {
1021  RtlCopyMemory(AccessToken->Privileges,
1022  Privileges,
1023  PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
1024  }
1026  {
1028  }
1029  _SEH2_END;
1030  }
1031  else
1032  {
1033  RtlCopyMemory(AccessToken->Privileges,
1034  Privileges,
1035  PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
1036  }
1037 
1038  if (!NT_SUCCESS(Status))
1039  goto Quit;
1040  }
1041 
1042  /* Update the privilege flags */
1043  SepUpdatePrivilegeFlagsToken(AccessToken);
1044 
1045  /* Copy the user and groups */
1046  AccessToken->UserAndGroupCount = 1 + GroupCount;
1047  AccessToken->UserAndGroups = EndMem;
1048  EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
1049  VariableLength -= ((ULONG_PTR)EndMem - (ULONG_PTR)AccessToken->UserAndGroups);
1050 
1052  User,
1053  VariableLength,
1054  &AccessToken->UserAndGroups[0],
1055  EndMem,
1056  &EndMem,
1057  &VariableLength);
1058  if (!NT_SUCCESS(Status))
1059  goto Quit;
1060 
1061  Status = RtlCopySidAndAttributesArray(GroupCount,
1062  Groups,
1063  VariableLength,
1064  &AccessToken->UserAndGroups[1],
1065  EndMem,
1066  &EndMem,
1067  &VariableLength);
1068  if (!NT_SUCCESS(Status))
1069  goto Quit;
1070 
1071  /* Find the token primary group and default owner */
1073  PrimaryGroup,
1074  Owner,
1075  &PrimaryGroupIndex,
1076  &DefaultOwnerIndex);
1077  if (!NT_SUCCESS(Status))
1078  {
1079  DPRINT1("SepFindPrimaryGroupAndDefaultOwner failed (Status 0x%lx)\n", Status);
1080  goto Quit;
1081  }
1082 
1083  AccessToken->PrimaryGroup = AccessToken->UserAndGroups[PrimaryGroupIndex].Sid;
1084  AccessToken->DefaultOwnerIndex = DefaultOwnerIndex;
1085 
1086  /* Now allocate the TOKEN's dynamic information area and set the data */
1087  AccessToken->DynamicAvailable = 0; // Unused memory in the dynamic area.
1088  AccessToken->DynamicPart = NULL;
1089  if (DefaultDacl != NULL)
1090  {
1091  AccessToken->DynamicPart = ExAllocatePoolWithTag(PagedPool,
1092  DefaultDacl->AclSize,
1094  if (AccessToken->DynamicPart == NULL)
1095  {
1097  goto Quit;
1098  }
1099  EndMem = (PVOID)AccessToken->DynamicPart;
1100 
1101  AccessToken->DefaultDacl = EndMem;
1102 
1103  RtlCopyMemory(AccessToken->DefaultDacl,
1104  DefaultDacl,
1105  DefaultDacl->AclSize);
1106  }
1107 
1108  /* Insert the token only if it's not the system token, otherwise return it directly */
1109  if (!SystemToken)
1110  {
1111  Status = ObInsertObject(AccessToken,
1112  NULL,
1113  DesiredAccess,
1114  0,
1115  NULL,
1116  TokenHandle);
1117  if (!NT_SUCCESS(Status))
1118  {
1119  DPRINT1("ObInsertObject() failed (Status 0x%lx)\n", Status);
1120  }
1121  }
1122  else
1123  {
1124  /* Return pointer instead of handle */
1125  *TokenHandle = (HANDLE)AccessToken;
1126  }
1127 
1128 Quit:
1129  if (!NT_SUCCESS(Status))
1130  {
1131  /* Dereference the token, the delete procedure will clean it up */
1132  ObDereferenceObject(AccessToken);
1133  }
1134 
1135  return Status;
1136 }
1137 
1138 PTOKEN
1139 NTAPI
1141 {
1143  ULONG GroupAttributes, OwnerAttributes;
1145  LARGE_INTEGER Expiration;
1146  SID_AND_ATTRIBUTES UserSid;
1147  ULONG GroupsLength;
1150  PSID Owner;
1151  ULONG i;
1152  PTOKEN Token;
1153  NTSTATUS Status;
1154 
1155  /* Don't ever expire */
1156  Expiration.QuadPart = -1;
1157 
1158  /* All groups mandatory and enabled */
1161 
1162  /* User is Local System */
1163  UserSid.Sid = SeLocalSystemSid;
1164  UserSid.Attributes = 0;
1165 
1166  /* Primary group is Local System */
1168 
1169  /* Owner is Administrators */
1171 
1172  /* Groups are Administrators, World, and Authenticated Users */
1173  Groups[0].Sid = SeAliasAdminsSid;
1174  Groups[0].Attributes = OwnerAttributes;
1175  Groups[1].Sid = SeWorldSid;
1176  Groups[1].Attributes = GroupAttributes;
1178  Groups[2].Attributes = GroupAttributes;
1179  GroupsLength = sizeof(SID_AND_ATTRIBUTES) +
1180  SeLengthSid(Groups[0].Sid) +
1181  SeLengthSid(Groups[1].Sid) +
1182  SeLengthSid(Groups[2].Sid);
1183  ASSERT(GroupsLength <= sizeof(Groups));
1184 
1185  /* Setup the privileges */
1186  i = 0;
1188  Privileges[i++].Luid = SeTcbPrivilege;
1189 
1190  Privileges[i].Attributes = 0;
1192 
1193  Privileges[i].Attributes = 0;
1195 
1198 
1201 
1202  Privileges[i].Attributes = 0;
1204 
1205  Privileges[i].Attributes = 0;
1207 
1210 
1213 
1215  Privileges[i++].Luid = SeDebugPrivilege;
1216 
1218  Privileges[i++].Luid = SeAuditPrivilege;
1219 
1220  Privileges[i].Attributes = 0;
1221  Privileges[i++].Luid = SeSecurityPrivilege;
1222 
1223  Privileges[i].Attributes = 0;
1225 
1228 
1229  Privileges[i].Attributes = 0;
1230  Privileges[i++].Luid = SeBackupPrivilege;
1231 
1232  Privileges[i].Attributes = 0;
1233  Privileges[i++].Luid = SeRestorePrivilege;
1234 
1235  Privileges[i].Attributes = 0;
1236  Privileges[i++].Luid = SeShutdownPrivilege;
1237 
1238  Privileges[i].Attributes = 0;
1240 
1243 
1244  Privileges[i].Attributes = 0;
1246  ASSERT(i == 20);
1247 
1248  /* Setup the object attributes */
1251 
1252  /* Create the token */
1254  KernelMode,
1255  0,
1257  TokenPrimary,
1260  &Expiration,
1261  &UserSid,
1262  3,
1263  Groups,
1264  GroupsLength,
1265  20,
1266  Privileges,
1267  Owner,
1268  PrimaryGroup,
1271  TRUE);
1273 
1274  /* Return the token */
1275  return Token;
1276 }
1277 
1278 /* PUBLIC FUNCTIONS ***********************************************************/
1279 
1280 /*
1281  * @unimplemented
1282  */
1283 NTSTATUS
1284 NTAPI
1286  IN ULONG Flags,
1287  IN PTOKEN_GROUPS SidsToDisable OPTIONAL,
1288  IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL,
1289  IN PTOKEN_GROUPS RestrictedSids OPTIONAL,
1290  OUT PACCESS_TOKEN * FilteredToken)
1291 {
1292  UNIMPLEMENTED;
1293  return STATUS_NOT_IMPLEMENTED;
1294 }
1295 
1296 /*
1297  * @implemented
1298  *
1299  * NOTE: SeQueryInformationToken is just NtQueryInformationToken without all
1300  * the bells and whistles needed for user-mode buffer access protection.
1301  */
1302 NTSTATUS
1303 NTAPI
1306  OUT PVOID *TokenInformation)
1307 {
1308  NTSTATUS Status;
1309  PTOKEN Token = (PTOKEN)AccessToken;
1311  union
1312  {
1313  PSID PSid;
1314  ULONG Ulong;
1315  } Unused;
1316 
1317  PAGED_CODE();
1318 
1320  {
1321  DPRINT1("SeQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
1323  }
1324 
1325  // TODO: Lock the token
1326 
1327  switch (TokenInformationClass)
1328  {
1329  case TokenUser:
1330  {
1331  PTOKEN_USER tu;
1332 
1333  DPRINT("SeQueryInformationToken(TokenUser)\n");
1334  RequiredLength = sizeof(TOKEN_USER) +
1335  RtlLengthSid(Token->UserAndGroups[0].Sid);
1336 
1337  /* Allocate the output buffer */
1339  if (tu == NULL)
1340  {
1342  break;
1343  }
1344 
1346  &Token->UserAndGroups[0],
1347  RequiredLength - sizeof(TOKEN_USER),
1348  &tu->User,
1349  (PSID)(tu + 1),
1350  &Unused.PSid,
1351  &Unused.Ulong);
1352 
1353  /* Return the structure */
1354  *TokenInformation = tu;
1356  break;
1357  }
1358 
1359  case TokenGroups:
1360  {
1361  PTOKEN_GROUPS tg;
1362  ULONG SidLen;
1363  PSID Sid;
1364 
1365  DPRINT("SeQueryInformationToken(TokenGroups)\n");
1366  RequiredLength = sizeof(tg->GroupCount) +
1367  RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]);
1368 
1369  SidLen = RequiredLength - sizeof(tg->GroupCount) -
1370  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES));
1371 
1372  /* Allocate the output buffer */
1374  if (tg == NULL)
1375  {
1377  break;
1378  }
1379 
1380  Sid = (PSID)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
1381  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)));
1382 
1383  tg->GroupCount = Token->UserAndGroupCount - 1;
1384  Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
1385  &Token->UserAndGroups[1],
1386  SidLen,
1387  &tg->Groups[0],
1388  Sid,
1389  &Unused.PSid,
1390  &Unused.Ulong);
1391 
1392  /* Return the structure */
1393  *TokenInformation = tg;
1395  break;
1396  }
1397 
1398  case TokenPrivileges:
1399  {
1401 
1402  DPRINT("SeQueryInformationToken(TokenPrivileges)\n");
1403  RequiredLength = sizeof(tp->PrivilegeCount) +
1404  (Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
1405 
1406  /* Allocate the output buffer */
1408  if (tp == NULL)
1409  {
1411  break;
1412  }
1413 
1414  tp->PrivilegeCount = Token->PrivilegeCount;
1415  RtlCopyLuidAndAttributesArray(Token->PrivilegeCount,
1416  Token->Privileges,
1417  &tp->Privileges[0]);
1418 
1419  /* Return the structure */
1420  *TokenInformation = tp;
1422  break;
1423  }
1424 
1425  case TokenOwner:
1426  {
1427  PTOKEN_OWNER to;
1428  ULONG SidLen;
1429 
1430  DPRINT("SeQueryInformationToken(TokenOwner)\n");
1431  SidLen = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
1432  RequiredLength = sizeof(TOKEN_OWNER) + SidLen;
1433 
1434  /* Allocate the output buffer */
1436  if (to == NULL)
1437  {
1439  break;
1440  }
1441 
1442  to->Owner = (PSID)(to + 1);
1443  Status = RtlCopySid(SidLen,
1444  to->Owner,
1445  Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
1446 
1447  /* Return the structure */
1448  *TokenInformation = to;
1450  break;
1451  }
1452 
1453  case TokenPrimaryGroup:
1454  {
1456  ULONG SidLen;
1457 
1458  DPRINT("SeQueryInformationToken(TokenPrimaryGroup)\n");
1459  SidLen = RtlLengthSid(Token->PrimaryGroup);
1460  RequiredLength = sizeof(TOKEN_PRIMARY_GROUP) + SidLen;
1461 
1462  /* Allocate the output buffer */
1464  if (tpg == NULL)
1465  {
1467  break;
1468  }
1469 
1470  tpg->PrimaryGroup = (PSID)(tpg + 1);
1471  Status = RtlCopySid(SidLen,
1472  tpg->PrimaryGroup,
1473  Token->PrimaryGroup);
1474 
1475  /* Return the structure */
1476  *TokenInformation = tpg;
1478  break;
1479  }
1480 
1481  case TokenDefaultDacl:
1482  {
1483  PTOKEN_DEFAULT_DACL tdd;
1484 
1485  DPRINT("SeQueryInformationToken(TokenDefaultDacl)\n");
1487 
1488  if (Token->DefaultDacl != NULL)
1489  RequiredLength += Token->DefaultDacl->AclSize;
1490 
1491  /* Allocate the output buffer */
1493  if (tdd == NULL)
1494  {
1496  break;
1497  }
1498 
1499  if (Token->DefaultDacl != NULL)
1500  {
1501  tdd->DefaultDacl = (PACL)(tdd + 1);
1503  Token->DefaultDacl,
1504  Token->DefaultDacl->AclSize);
1505  }
1506  else
1507  {
1508  tdd->DefaultDacl = NULL;
1509  }
1510 
1511  /* Return the structure */
1512  *TokenInformation = tdd;
1514  break;
1515  }
1516 
1517  case TokenSource:
1518  {
1519  PTOKEN_SOURCE ts;
1520 
1521  DPRINT("SeQueryInformationToken(TokenSource)\n");
1522  RequiredLength = sizeof(TOKEN_SOURCE);
1523 
1524  /* Allocate the output buffer */
1526  if (ts == NULL)
1527  {
1529  break;
1530  }
1531 
1532  *ts = Token->TokenSource;
1533 
1534  /* Return the structure */
1535  *TokenInformation = ts;
1537  break;
1538  }
1539 
1540  case TokenType:
1541  {
1542  PTOKEN_TYPE tt;
1543 
1544  DPRINT("SeQueryInformationToken(TokenType)\n");
1545  RequiredLength = sizeof(TOKEN_TYPE);
1546 
1547  /* Allocate the output buffer */
1549  if (tt == NULL)
1550  {
1552  break;
1553  }
1554 
1555  *tt = Token->TokenType;
1556 
1557  /* Return the structure */
1558  *TokenInformation = tt;
1560  break;
1561  }
1562 
1564  {
1566 
1567  DPRINT("SeQueryInformationToken(TokenImpersonationLevel)\n");
1569 
1570  /* Fail if the token is not an impersonation token */
1571  if (Token->TokenType != TokenImpersonation)
1572  {
1574  break;
1575  }
1576 
1577  /* Allocate the output buffer */
1579  if (sil == NULL)
1580  {
1582  break;
1583  }
1584 
1585  *sil = Token->ImpersonationLevel;
1586 
1587  /* Return the structure */
1588  *TokenInformation = sil;
1590  break;
1591  }
1592 
1593  case TokenStatistics:
1594  {
1596 
1597  DPRINT("SeQueryInformationToken(TokenStatistics)\n");
1598  RequiredLength = sizeof(TOKEN_STATISTICS);
1599 
1600  /* Allocate the output buffer */
1602  if (ts == NULL)
1603  {
1605  break;
1606  }
1607 
1608  ts->TokenId = Token->TokenId;
1609  ts->AuthenticationId = Token->AuthenticationId;
1610  ts->ExpirationTime = Token->ExpirationTime;
1611  ts->TokenType = Token->TokenType;
1612  ts->ImpersonationLevel = Token->ImpersonationLevel;
1613  ts->DynamicCharged = Token->DynamicCharged;
1614  ts->DynamicAvailable = Token->DynamicAvailable;
1615  ts->GroupCount = Token->UserAndGroupCount - 1;
1616  ts->PrivilegeCount = Token->PrivilegeCount;
1617  ts->ModifiedId = Token->ModifiedId;
1618 
1619  /* Return the structure */
1620  *TokenInformation = ts;
1622  break;
1623  }
1624 
1625 /*
1626  * The following 4 cases are only implemented in NtQueryInformationToken
1627  */
1628 #if 0
1629 
1630  case TokenOrigin:
1631  {
1632  PTOKEN_ORIGIN to;
1633 
1634  DPRINT("SeQueryInformationToken(TokenOrigin)\n");
1635  RequiredLength = sizeof(TOKEN_ORIGIN);
1636 
1637  /* Allocate the output buffer */
1639  if (to == NULL)
1640  {
1642  break;
1643  }
1644 
1646  &Token->AuthenticationId);
1647 
1648  /* Return the structure */
1649  *TokenInformation = to;
1651  break;
1652  }
1653 
1655  DPRINT1("SeQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1657  break;
1658 
1659  case TokenRestrictedSids:
1660  {
1661  PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
1662  ULONG SidLen;
1663  PSID Sid;
1664 
1665  DPRINT("SeQueryInformationToken(TokenRestrictedSids)\n");
1666  RequiredLength = sizeof(tg->GroupCount) +
1667  RtlLengthSidAndAttributes(Token->RestrictedSidCount, Token->RestrictedSids);
1668 
1669  SidLen = RequiredLength - sizeof(tg->GroupCount) -
1670  (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES));
1671 
1672  /* Allocate the output buffer */
1674  if (tg == NULL)
1675  {
1677  break;
1678  }
1679 
1680  Sid = (PSID)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
1681  (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)));
1682 
1683  tg->GroupCount = Token->RestrictedSidCount;
1684  Status = RtlCopySidAndAttributesArray(Token->RestrictedSidCount,
1685  Token->RestrictedSids,
1686  SidLen,
1687  &tg->Groups[0],
1688  Sid,
1689  &Unused.PSid,
1690  &Unused.Ulong);
1691 
1692  /* Return the structure */
1693  *TokenInformation = tg;
1695  break;
1696  }
1697 
1698  case TokenSandBoxInert:
1699  DPRINT1("SeQueryInformationToken(TokenSandboxInert) not implemented\n");
1701  break;
1702 
1703 #endif
1704 
1705  case TokenSessionId:
1706  {
1707  DPRINT("SeQueryInformationToken(TokenSessionId)\n");
1708  Status = SeQuerySessionIdToken(Token, (PULONG)TokenInformation);
1709  break;
1710  }
1711 
1712  default:
1713  DPRINT1("SeQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
1715  break;
1716  }
1717 
1718  return Status;
1719 }
1720 
1721 /*
1722  * @implemented
1723  */
1724 NTSTATUS
1725 NTAPI
1727  IN PULONG pSessionId)
1728 {
1729  PAGED_CODE();
1730 
1731  /* Lock the token */
1733 
1734  *pSessionId = ((PTOKEN)Token)->SessionId;
1735 
1736  /* Unlock the token */
1738 
1739  return STATUS_SUCCESS;
1740 }
1741 
1742 /*
1743  * @implemented
1744  */
1745 NTSTATUS
1746 NTAPI
1748  OUT PLUID LogonId)
1749 {
1750  PAGED_CODE();
1751 
1752  *LogonId = ((PTOKEN)Token)->AuthenticationId;
1753 
1754  return STATUS_SUCCESS;
1755 }
1756 
1757 
1758 /*
1759  * @implemented
1760  */
1762 NTAPI
1764 {
1765  PAGED_CODE();
1766 
1767  return ((PTOKEN)Token)->ImpersonationLevel;
1768 }
1769 
1770 
1771 /*
1772  * @implemented
1773  */
1776 {
1777  PAGED_CODE();
1778 
1779  return ((PTOKEN)Token)->TokenType;
1780 }
1781 
1782 
1783 /*
1784  * @implemented
1785  */
1786 BOOLEAN
1787 NTAPI
1789 {
1790  PAGED_CODE();
1791 
1792  // NOTE: Win7+ instead really checks the list of groups in the token
1793  // (since TOKEN_HAS_ADMIN_GROUP == TOKEN_WRITE_RESTRICTED ...)
1794  return (((PTOKEN)Token)->TokenFlags & TOKEN_HAS_ADMIN_GROUP) != 0;
1795 }
1796 
1797 /*
1798  * @implemented
1799  */
1800 BOOLEAN
1801 NTAPI
1803 {
1804  PAGED_CODE();
1805 
1806  return (((PTOKEN)Token)->TokenFlags & TOKEN_IS_RESTRICTED) != 0;
1807 }
1808 
1809 /*
1810  * @implemented
1811  * @note First introduced in NT 5.1 SP2 x86 (5.1.2600.2622), absent in NT 5.2,
1812  * then finally re-introduced in Vista+.
1813  */
1814 BOOLEAN
1815 NTAPI
1817 {
1818  PAGED_CODE();
1819 
1820  // NOTE: NT 5.1 SP2 x86 checks the SE_BACKUP_PRIVILEGES_CHECKED flag
1821  // while Vista+ checks the TOKEN_WRITE_RESTRICTED flag as one expects.
1822  return (((PTOKEN)Token)->TokenFlags & SE_BACKUP_PRIVILEGES_CHECKED) != 0;
1823 }
1824 
1825 /* SYSTEM CALLS ***************************************************************/
1826 
1827 /*
1828  * @implemented
1829  */
1832 NTSTATUS
1833 NTAPI
1838  PVOID TokenInformation,
1841 {
1842  NTSTATUS Status;
1844  PTOKEN Token;
1846  union
1847  {
1848  PSID PSid;
1849  ULONG Ulong;
1850  } Unused;
1851 
1852  PAGED_CODE();
1853 
1855 
1856  /* Check buffers and class validity */
1860  TokenInformation,
1862  ReturnLength,
1863  NULL,
1864  PreviousMode);
1865  if (!NT_SUCCESS(Status))
1866  {
1867  DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status);
1868  return Status;
1869  }
1870 
1874  PreviousMode,
1875  (PVOID*)&Token,
1876  NULL);
1877  if (NT_SUCCESS(Status))
1878  {
1879  /* Lock the token */
1881 
1882  switch (TokenInformationClass)
1883  {
1884  case TokenUser:
1885  {
1886  PTOKEN_USER tu = (PTOKEN_USER)TokenInformation;
1887 
1888  DPRINT("NtQueryInformationToken(TokenUser)\n");
1889  RequiredLength = sizeof(TOKEN_USER) +
1890  RtlLengthSid(Token->UserAndGroups[0].Sid);
1891 
1892  _SEH2_TRY
1893  {
1895  {
1897  &Token->UserAndGroups[0],
1898  RequiredLength - sizeof(TOKEN_USER),
1899  &tu->User,
1900  (PSID)(tu + 1),
1901  &Unused.PSid,
1902  &Unused.Ulong);
1903  }
1904  else
1905  {
1907  }
1908 
1909  if (ReturnLength != NULL)
1910  {
1912  }
1913  }
1915  {
1917  }
1918  _SEH2_END;
1919 
1920  break;
1921  }
1922 
1923  case TokenGroups:
1924  {
1925  PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
1926 
1927  DPRINT("NtQueryInformationToken(TokenGroups)\n");
1928  RequiredLength = sizeof(tg->GroupCount) +
1929  RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]);
1930 
1931  _SEH2_TRY
1932  {
1934  {
1935  ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
1936  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES));
1937  PSID Sid = (PSID_AND_ATTRIBUTES)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
1938  ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)));
1939 
1940  tg->GroupCount = Token->UserAndGroupCount - 1;
1941  Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
1942  &Token->UserAndGroups[1],
1943  SidLen,
1944  &tg->Groups[0],
1945  Sid,
1946  &Unused.PSid,
1947  &Unused.Ulong);
1948  }
1949  else
1950  {
1952  }
1953 
1954  if (ReturnLength != NULL)
1955  {
1957  }
1958  }
1960  {
1962  }
1963  _SEH2_END;
1964 
1965  break;
1966  }
1967 
1968  case TokenPrivileges:
1969  {
1970  PTOKEN_PRIVILEGES tp = (PTOKEN_PRIVILEGES)TokenInformation;
1971 
1972  DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
1973  RequiredLength = sizeof(tp->PrivilegeCount) +
1974  (Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
1975 
1976  _SEH2_TRY
1977  {
1979  {
1980  tp->PrivilegeCount = Token->PrivilegeCount;
1981  RtlCopyLuidAndAttributesArray(Token->PrivilegeCount,
1982  Token->Privileges,
1983  &tp->Privileges[0]);
1984  }
1985  else
1986  {
1988  }
1989 
1990  if (ReturnLength != NULL)
1991  {
1993  }
1994  }
1996  {
1998  }
1999  _SEH2_END;
2000 
2001  break;
2002  }
2003 
2004  case TokenOwner:
2005  {
2006  PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
2007  ULONG SidLen;
2008 
2009  DPRINT("NtQueryInformationToken(TokenOwner)\n");
2010  SidLen = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
2011  RequiredLength = sizeof(TOKEN_OWNER) + SidLen;
2012 
2013  _SEH2_TRY
2014  {
2016  {
2017  to->Owner = (PSID)(to + 1);
2018  Status = RtlCopySid(SidLen,
2019  to->Owner,
2020  Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
2021  }
2022  else
2023  {
2025  }
2026 
2027  if (ReturnLength != NULL)
2028  {
2030  }
2031  }
2033  {
2035  }
2036  _SEH2_END;
2037 
2038  break;
2039  }
2040 
2041  case TokenPrimaryGroup:
2042  {
2043  PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
2044  ULONG SidLen;
2045 
2046  DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
2047  SidLen = RtlLengthSid(Token->PrimaryGroup);
2048  RequiredLength = sizeof(TOKEN_PRIMARY_GROUP) + SidLen;
2049 
2050  _SEH2_TRY
2051  {
2053  {
2054  tpg->PrimaryGroup = (PSID)(tpg + 1);
2055  Status = RtlCopySid(SidLen,
2056  tpg->PrimaryGroup,
2057  Token->PrimaryGroup);
2058  }
2059  else
2060  {
2062  }
2063 
2064  if (ReturnLength != NULL)
2065  {
2067  }
2068  }
2070  {
2072  }
2073  _SEH2_END;
2074 
2075  break;
2076  }
2077 
2078  case TokenDefaultDacl:
2079  {
2080  PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
2081 
2082  DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
2084 
2085  if (Token->DefaultDacl != NULL)
2086  RequiredLength += Token->DefaultDacl->AclSize;
2087 
2088  _SEH2_TRY
2089  {
2091  {
2092  if (Token->DefaultDacl != NULL)
2093  {
2094  tdd->DefaultDacl = (PACL)(tdd + 1);
2096  Token->DefaultDacl,
2097  Token->DefaultDacl->AclSize);
2098  }
2099  else
2100  {
2101  tdd->DefaultDacl = NULL;
2102  }
2103  }
2104  else
2105  {
2107  }
2108 
2109  if (ReturnLength != NULL)
2110  {
2112  }
2113  }
2115  {
2117  }
2118  _SEH2_END;
2119 
2120  break;
2121  }
2122 
2123  case TokenSource:
2124  {
2125  PTOKEN_SOURCE ts = (PTOKEN_SOURCE)TokenInformation;
2126 
2127  DPRINT("NtQueryInformationToken(TokenSource)\n");
2128  RequiredLength = sizeof(TOKEN_SOURCE);
2129 
2130  _SEH2_TRY
2131  {
2133  {
2134  *ts = Token->TokenSource;
2135  }
2136  else
2137  {
2139  }
2140 
2141  if (ReturnLength != NULL)
2142  {
2144  }
2145  }
2147  {
2149  }
2150  _SEH2_END;
2151 
2152  break;
2153  }
2154 
2155  case TokenType:
2156  {
2157  PTOKEN_TYPE tt = (PTOKEN_TYPE)TokenInformation;
2158 
2159  DPRINT("NtQueryInformationToken(TokenType)\n");
2160  RequiredLength = sizeof(TOKEN_TYPE);
2161 
2162  _SEH2_TRY
2163  {
2165  {
2166  *tt = Token->TokenType;
2167  }
2168  else
2169  {
2171  }
2172 
2173  if (ReturnLength != NULL)
2174  {
2176  }
2177  }
2179  {
2181  }
2182  _SEH2_END;
2183 
2184  break;
2185  }
2186 
2188  {
2190 
2191  DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
2192 
2193  /* Fail if the token is not an impersonation token */
2194  if (Token->TokenType != TokenImpersonation)
2195  {
2197  break;
2198  }
2199 
2201 
2202  _SEH2_TRY
2203  {
2205  {
2206  *sil = Token->ImpersonationLevel;
2207  }
2208  else
2209  {
2211  }
2212 
2213  if (ReturnLength != NULL)
2214  {
2216  }
2217  }
2219  {
2221  }
2222  _SEH2_END;
2223 
2224  break;
2225  }
2226 
2227  case TokenStatistics:
2228  {
2229  PTOKEN_STATISTICS ts = (PTOKEN_STATISTICS)TokenInformation;
2230 
2231  DPRINT("NtQueryInformationToken(TokenStatistics)\n");
2232  RequiredLength = sizeof(TOKEN_STATISTICS);
2233 
2234  _SEH2_TRY
2235  {
2237  {
2238  ts->TokenId = Token->TokenId;
2239  ts->AuthenticationId = Token->AuthenticationId;
2240  ts->ExpirationTime = Token->ExpirationTime;
2241  ts->TokenType = Token->TokenType;
2242  ts->ImpersonationLevel = Token->ImpersonationLevel;
2243  ts->DynamicCharged = Token->DynamicCharged;
2244  ts->DynamicAvailable = Token->DynamicAvailable;
2245  ts->GroupCount = Token->UserAndGroupCount - 1;
2246  ts->PrivilegeCount = Token->PrivilegeCount;
2247  ts->ModifiedId = Token->ModifiedId;
2248  }
2249  else
2250  {
2252  }
2253 
2254  if (ReturnLength != NULL)
2255  {
2257  }
2258  }
2260  {
2262  }
2263  _SEH2_END;
2264 
2265  break;
2266  }
2267 
2268  case TokenOrigin:
2269  {
2270  PTOKEN_ORIGIN to = (PTOKEN_ORIGIN)TokenInformation;
2271 
2272  DPRINT("NtQueryInformationToken(TokenOrigin)\n");
2273  RequiredLength = sizeof(TOKEN_ORIGIN);
2274 
2275  _SEH2_TRY
2276  {
2278  {
2280  &Token->AuthenticationId);
2281  }
2282  else
2283  {
2285  }
2286 
2287  if (ReturnLength != NULL)
2288  {
2290  }
2291  }
2293  {
2295  }
2296  _SEH2_END;
2297 
2298  break;
2299  }
2300 
2302  DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
2304  break;
2305 
2306  case TokenRestrictedSids:
2307  {
2308  PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
2309 
2310  DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
2311  RequiredLength = sizeof(tg->GroupCount) +
2312  RtlLengthSidAndAttributes(Token->RestrictedSidCount, Token->RestrictedSids);
2313 
2314  _SEH2_TRY
2315  {
2317  {
2318  ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
2319  (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES));
2320  PSID Sid = (PSID)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
2321  (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)));
2322 
2323  tg->GroupCount = Token->RestrictedSidCount;
2324  Status = RtlCopySidAndAttributesArray(Token->RestrictedSidCount,
2325  Token->RestrictedSids,
2326  SidLen,
2327  &tg->Groups[0],
2328  Sid,
2329  &Unused.PSid,
2330  &Unused.Ulong);
2331  }
2332  else
2333  {
2335  }
2336 
2337  if (ReturnLength != NULL)
2338  {
2340  }
2341  }
2343  {
2345  }
2346  _SEH2_END;
2347 
2348  break;
2349  }
2350 
2351  case TokenSandBoxInert:
2352  DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
2354  break;
2355 
2356  case TokenSessionId:
2357  {
2358  ULONG SessionId = 0;
2359 
2360  DPRINT("NtQueryInformationToken(TokenSessionId)\n");
2361 
2363  if (NT_SUCCESS(Status))
2364  {
2365  _SEH2_TRY
2366  {
2367  /* Buffer size was already verified, no need to check here again */
2368  *(PULONG)TokenInformation = SessionId;
2369 
2370  if (ReturnLength != NULL)
2371  {
2372  *ReturnLength = sizeof(ULONG);
2373  }
2374  }
2376  {
2378  }
2379  _SEH2_END;
2380  }
2381 
2382  break;
2383  }
2384 
2385  default:
2386  DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
2388  break;
2389  }
2390 
2391  /* Unlock and dereference the token */
2394  }
2395 
2396  return Status;
2397 }
2398 
2399 
2400 /*
2401  * NtSetTokenInformation: Partly implemented.
2402  * Unimplemented:
2403  * TokenOrigin, TokenDefaultDacl
2404  */
2407 NTSTATUS
2408 NTAPI
2412  _In_reads_bytes_(TokenInformationLength) PVOID TokenInformation,
2414 {
2415  NTSTATUS Status;
2416  PTOKEN Token;
2418  ULONG NeededAccess = TOKEN_ADJUST_DEFAULT;
2419 
2420  PAGED_CODE();
2421 
2423 
2427  TokenInformation,
2429  PreviousMode);
2430  if (!NT_SUCCESS(Status))
2431  {
2432  /* Invalid buffers */
2433  DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status);
2434  return Status;
2435  }
2436 
2438  {
2439  NeededAccess |= TOKEN_ADJUST_SESSIONID;
2440  }
2441 
2443  NeededAccess,
2445  PreviousMode,
2446  (PVOID*)&Token,
2447  NULL);
2448  if (NT_SUCCESS(Status))
2449  {
2450  switch (TokenInformationClass)
2451  {
2452  case TokenOwner:
2453  {
2454  if (TokenInformationLength >= sizeof(TOKEN_OWNER))
2455  {
2456  PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
2457  PSID InputSid = NULL, CapturedSid;
2458  ULONG DefaultOwnerIndex;
2459 
2460  _SEH2_TRY
2461  {
2462  InputSid = to->Owner;
2463  }
2465  {
2467  _SEH2_YIELD(goto Cleanup);
2468  }
2469  _SEH2_END;
2470 
2471  Status = SepCaptureSid(InputSid,
2472  PreviousMode,
2473  PagedPool,
2474  FALSE,
2475  &CapturedSid);
2476  if (NT_SUCCESS(Status))
2477  {
2478  /* Lock the token */
2480 
2481  /* Find the owner amongst the existing token user and groups */
2483  NULL,
2484  CapturedSid,
2485  NULL,
2486  &DefaultOwnerIndex);
2487  if (NT_SUCCESS(Status))
2488  {
2489  /* Found it */
2490  Token->DefaultOwnerIndex = DefaultOwnerIndex;
2491  ExAllocateLocallyUniqueId(&Token->ModifiedId);
2492  }
2493 
2494  /* Unlock the token */
2496 
2497  SepReleaseSid(CapturedSid,
2498  PreviousMode,
2499  FALSE);
2500  }
2501  }
2502  else
2503  {
2505  }
2506  break;
2507  }
2508 
2509  case TokenPrimaryGroup:
2510  {
2512  {
2513  PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
2514  PSID InputSid = NULL, CapturedSid;
2515  ULONG PrimaryGroupIndex;
2516 
2517  _SEH2_TRY
2518  {
2519  InputSid = tpg->PrimaryGroup;
2520  }
2522  {
2524  _SEH2_YIELD(goto Cleanup);
2525  }
2526  _SEH2_END;
2527 
2528  Status = SepCaptureSid(InputSid,
2529  PreviousMode,
2530  PagedPool,
2531  FALSE,
2532  &CapturedSid);
2533  if (NT_SUCCESS(Status))
2534  {
2535  /* Lock the token */
2537 
2538  /* Find the primary group amongst the existing token user and groups */
2540  CapturedSid,
2541  NULL,
2542  &PrimaryGroupIndex,
2543  NULL);
2544  if (NT_SUCCESS(Status))
2545  {
2546  /* Found it */
2547  Token->PrimaryGroup = Token->UserAndGroups[PrimaryGroupIndex].Sid;
2548  ExAllocateLocallyUniqueId(&Token->ModifiedId);
2549  }
2550 
2551  /* Unlock the token */
2553 
2554  SepReleaseSid(CapturedSid,
2555  PreviousMode,
2556  FALSE);
2557  }
2558  }
2559  else
2560  {
2562  }
2563  break;
2564  }
2565 
2566  case TokenDefaultDacl:
2567  {
2569  {
2570  PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
2571  PACL InputAcl = NULL;
2572 
2573  _SEH2_TRY
2574  {
2575  InputAcl = tdd->DefaultDacl;
2576  }
2578  {
2580  _SEH2_YIELD(goto Cleanup);
2581  }
2582  _SEH2_END;
2583 
2584  if (InputAcl != NULL)
2585  {
2586  PACL CapturedAcl;
2587 
2588  /* Capture and copy the dacl */
2589  Status = SepCaptureAcl(InputAcl,
2590  PreviousMode,
2591  PagedPool,
2592  TRUE,
2593  &CapturedAcl);
2594  if (NT_SUCCESS(Status))
2595  {
2596  ULONG DynamicLength;
2597 
2598  /* Lock the token */
2600 
2601  //
2602  // NOTE: So far our dynamic area only contains
2603  // the default dacl, so this makes the following
2604  // code pretty simple. The day where it stores
2605  // other data, the code will require adaptations.
2606  //
2607 
2608  DynamicLength = Token->DynamicAvailable;
2609  // Add here any other data length present in the dynamic area...
2610  if (Token->DefaultDacl)
2611  DynamicLength += Token->DefaultDacl->AclSize;
2612 
2613  /* Reallocate the dynamic area if it is too small */
2615  if ((DynamicLength < CapturedAcl->AclSize) ||
2616  (Token->DynamicPart == NULL))
2617  {
2618  PVOID NewDynamicPart;
2619 
2620  NewDynamicPart = ExAllocatePoolWithTag(PagedPool,
2621  CapturedAcl->AclSize,
2623  if (NewDynamicPart == NULL)
2624  {
2626  }
2627  else
2628  {
2629  if (Token->DynamicPart != NULL)
2630  {
2631  // RtlCopyMemory(NewDynamicPart, Token->DynamicPart, DynamicLength);
2632  ExFreePoolWithTag(Token->DynamicPart, TAG_TOKEN_DYNAMIC);
2633  }
2634  Token->DynamicPart = NewDynamicPart;
2635  Token->DynamicAvailable = 0;
2636  }
2637  }
2638  else
2639  {
2640  Token->DynamicAvailable = DynamicLength - CapturedAcl->AclSize;
2641  }
2642 
2643  if (NT_SUCCESS(Status))
2644  {
2645  /* Set the new dacl */
2646  Token->DefaultDacl = (PVOID)Token->DynamicPart;
2647  RtlCopyMemory(Token->DefaultDacl,
2648  CapturedAcl,
2649  CapturedAcl->AclSize);
2650 
2651  ExAllocateLocallyUniqueId(&Token->ModifiedId);
2652  }
2653 
2654  /* Unlock the token */
2656 
2657  ExFreePoolWithTag(CapturedAcl, TAG_ACL);
2658  }
2659  }
2660  else
2661  {
2662  /* Lock the token */
2664 
2665  /* Clear the default dacl if present */
2666  if (Token->DefaultDacl != NULL)
2667  {
2668  Token->DynamicAvailable += Token->DefaultDacl->AclSize;
2669  RtlZeroMemory(Token->DefaultDacl, Token->DefaultDacl->AclSize);
2670  Token->DefaultDacl = NULL;
2671 
2672  ExAllocateLocallyUniqueId(&Token->ModifiedId);
2673  }
2674 
2675  /* Unlock the token */
2677  }
2678  }
2679  else
2680  {
2682  }
2683  break;
2684  }
2685 
2686  case TokenSessionId:
2687  {
2688  ULONG SessionId = 0;
2689 
2690  _SEH2_TRY
2691  {
2692  /* Buffer size was already verified, no need to check here again */
2693  SessionId = *(PULONG)TokenInformation;
2694  }
2696  {
2698  _SEH2_YIELD(goto Cleanup);
2699  }
2700  _SEH2_END;
2701 
2702  /* Check for TCB privilege */
2704  {
2706  break;
2707  }
2708 
2709  /* Lock the token */
2711 
2712  Token->SessionId = SessionId;
2713  ExAllocateLocallyUniqueId(&Token->ModifiedId);
2714 
2715  /* Unlock the token */
2717 
2718  break;
2719  }
2720 
2721  case TokenSessionReference:
2722  {
2723  ULONG SessionReference;
2724 
2725  _SEH2_TRY
2726  {
2727  /* Buffer size was already verified, no need to check here again */
2728  SessionReference = *(PULONG)TokenInformation;
2729  }
2731  {
2733  _SEH2_YIELD(goto Cleanup);
2734  }
2735  _SEH2_END;
2736 
2737  /* Check for TCB privilege */
2739  {
2741  goto Cleanup;
2742  }
2743 
2744  /* Check if it is 0 */
2745  if (SessionReference == 0)
2746  {
2747  ULONG OldTokenFlags;
2748 
2749  /* Lock the token */
2751 
2752  /* Atomically set the flag in the token */
2753  OldTokenFlags = RtlInterlockedSetBits(&Token->TokenFlags,
2755  /*
2756  * If the flag was already set, do not dereference again
2757  * the logon session. Use SessionReference as an indicator
2758  * to know whether to really dereference the session.
2759  */
2760  if (OldTokenFlags == Token->TokenFlags)
2761  SessionReference = ULONG_MAX;
2762 
2763  /* Unlock the token */
2765  }
2766 
2767  /* Dereference the logon session if needed */
2768  if (SessionReference == 0)
2769  SepRmDereferenceLogonSession(&Token->AuthenticationId);
2770 
2771  break;
2772  }
2773 
2774  case TokenAuditPolicy:
2775  {
2776  PTOKEN_AUDIT_POLICY_INFORMATION PolicyInformation =
2777  (PTOKEN_AUDIT_POLICY_INFORMATION)TokenInformation;
2778  SEP_AUDIT_POLICY AuditPolicy;
2779  ULONG i;
2780 
2781  _SEH2_TRY
2782  {
2783  ProbeForRead(PolicyInformation,
2785  Policies[PolicyInformation->PolicyCount]),
2786  sizeof(ULONG));
2787 
2788  /* Loop all policies in the structure */
2789  for (i = 0; i < PolicyInformation->PolicyCount; i++)
2790  {
2791  /* Set the corresponding bits in the packed structure */
2792  switch (PolicyInformation->Policies[i].Category)
2793  {
2794  case AuditCategorySystem:
2795  AuditPolicy.PolicyElements.System = PolicyInformation->Policies[i].Value;
2796  break;
2797 
2798  case AuditCategoryLogon:
2799  AuditPolicy.PolicyElements.Logon = PolicyInformation->Policies[i].Value;
2800  break;
2801 
2803  AuditPolicy.PolicyElements.ObjectAccess = PolicyInformation->Policies[i].Value;
2804  break;
2805 
2807  AuditPolicy.PolicyElements.PrivilegeUse = PolicyInformation->Policies[i].Value;
2808  break;
2809 
2811  AuditPolicy.PolicyElements.DetailedTracking = PolicyInformation->Policies[i].Value;
2812  break;
2813 
2815  AuditPolicy.PolicyElements.PolicyChange = PolicyInformation->Policies[i].Value;
2816  break;
2817 
2819  AuditPolicy.PolicyElements.AccountManagement = PolicyInformation->Policies[i].Value;
2820  break;
2821 
2823  AuditPolicy.PolicyElements.DirectoryServiceAccess = PolicyInformation->Policies[i].Value;
2824  break;
2825 
2827  AuditPolicy.PolicyElements.AccountLogon = PolicyInformation->Policies[i].Value;
2828  break;
2829  }
2830  }
2831  }
2833  {
2835  _SEH2_YIELD(goto Cleanup);
2836  }
2837  _SEH2_END;
2838 
2839  /* Check for TCB privilege */
2841  {
2843  break;
2844  }
2845 
2846  /* Lock the token */
2848 
2849  /* Set the new audit policy */
2850  Token->AuditPolicy = AuditPolicy;
2851  ExAllocateLocallyUniqueId(&Token->ModifiedId);
2852 
2853  /* Unlock the token */
2855 
2856  break;
2857  }
2858 
2859  case TokenOrigin:
2860  {
2862 
2863  _SEH2_TRY
2864  {
2865  /* Copy the token origin */
2866  TokenOrigin = *(PTOKEN_ORIGIN)TokenInformation;
2867  }
2869  {
2871  _SEH2_YIELD(goto Cleanup);
2872  }
2873  _SEH2_END;
2874 
2875  /* Check for TCB privilege */
2877  {
2879  break;
2880  }
2881 
2882  /* Lock the token */
2884 
2885  /* Check if there is no token origin set yet */
2886  if (RtlIsZeroLuid(&Token->OriginatingLogonSession))
2887  {
2888  /* Set the token origin */
2889  Token->OriginatingLogonSession =
2890  TokenOrigin.OriginatingLogonSession;
2891 
2892  ExAllocateLocallyUniqueId(&Token->ModifiedId);
2893  }
2894 
2895  /* Unlock the token */
2897 
2898  break;
2899  }
2900 
2901  default:
2902  {
2903  DPRINT1("Invalid TokenInformationClass: 0x%lx\n",
2906  break;
2907  }
2908  }
2909 Cleanup:
2911  }
2912 
2913  if (!NT_SUCCESS(Status))
2914  {
2915  DPRINT1("NtSetInformationToken failed with Status 0x%lx\n", Status);
2916  }
2917 
2918  return Status;
2919 }
2920 
2921 
2922 /*
2923  * @implemented
2924  *
2925  * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
2926  * this is certainly NOT true, although I can't say for sure that EffectiveOnly
2927  * is correct either. -Gunnar
2928  * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
2929  * NOTE for readers: http://hex.pp.ua/nt/NtDuplicateToken.php is therefore
2930  * wrong in that regard, while MSDN documentation is correct.
2931  */
2934 NTSTATUS
2935 NTAPI
2937  _In_ HANDLE ExistingTokenHandle,
2943 {
2945  HANDLE hToken;
2946  PTOKEN Token;
2947  PTOKEN NewToken;
2948  PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService;
2949  BOOLEAN QoSPresent;
2951  NTSTATUS Status;
2952 
2953  PAGED_CODE();
2954 
2955  if (TokenType != TokenImpersonation &&
2957  {
2958  return STATUS_INVALID_PARAMETER;
2959  }
2960 
2962 
2963  if (PreviousMode != KernelMode)
2964  {
2965  _SEH2_TRY
2966  {
2968  }
2970  {
2971  /* Return the exception code */
2973  }
2974  _SEH2_END;
2975  }
2976 
2978  PreviousMode,
2979  PagedPool,
2980  FALSE,
2981  &CapturedSecurityQualityOfService,
2982  &QoSPresent);
2983  if (!NT_SUCCESS(Status))
2984  {
2985  DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status);
2986  return Status;
2987  }
2988 
2989  Status = ObReferenceObjectByHandle(ExistingTokenHandle,
2992  PreviousMode,
2993  (PVOID*)&Token,
2995  if (!NT_SUCCESS(Status))
2996  {
2997  DPRINT1("Failed to reference token (Status 0x%lx)\n", Status);
2998  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
2999  PreviousMode,
3000  FALSE);
3001  return Status;
3002  }
3003 
3004  /*
3005  * Fail, if the original token is an impersonation token and the caller
3006  * tries to raise the impersonation level of the new token above the
3007  * impersonation level of the original token.
3008  */
3009  if (Token->TokenType == TokenImpersonation)
3010  {
3011  if (QoSPresent &&
3012  CapturedSecurityQualityOfService->ImpersonationLevel >Token->ImpersonationLevel)
3013  {
3015  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
3016  PreviousMode,
3017  FALSE);
3019  }
3020  }
3021 
3022  /*
3023  * Fail, if a primary token is to be created from an impersonation token
3024  * and and the impersonation level of the impersonation token is below SecurityImpersonation.
3025  */
3026  if (Token->TokenType == TokenImpersonation &&
3027  TokenType == TokenPrimary &&
3028  Token->ImpersonationLevel < SecurityImpersonation)
3029  {
3031  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
3032  PreviousMode,
3033  FALSE);
3035  }
3036 
3039  EffectiveOnly,
3040  TokenType,
3041  (QoSPresent ? CapturedSecurityQualityOfService->ImpersonationLevel : SecurityAnonymous),
3042  PreviousMode,
3043  &NewToken);
3044 
3046 
3047  if (NT_SUCCESS(Status))
3048  {
3049  Status = ObInsertObject(NewToken,
3050  NULL,
3051  (DesiredAccess ? DesiredAccess : HandleInformation.GrantedAccess),
3052  0,
3053  NULL,
3054  &hToken);
3055  if (NT_SUCCESS(Status))
3056  {
3057  _SEH2_TRY
3058  {
3059  *NewTokenHandle = hToken;
3060  }
3062  {
3064  }
3065  _SEH2_END;
3066  }
3067  }
3068 
3069  /* Free the captured structure */
3070  SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
3071  PreviousMode,
3072  FALSE);
3073 
3074  return Status;
3075 }
3076 
3079  IN BOOLEAN ResetToDefault,
3080  IN PTOKEN_GROUPS NewState,
3084 {
3085  UNIMPLEMENTED;
3086  return STATUS_NOT_IMPLEMENTED;
3087 }
3088 
3089 
3090 static
3091 NTSTATUS
3094  _In_ BOOLEAN DisableAllPrivileges,
3095  _In_opt_ PLUID_AND_ATTRIBUTES NewState,
3096  _In_ ULONG NewStateCount,
3099  _Out_ PULONG ChangedPrivileges,
3100  _Out_ PBOOLEAN ChangesMade)
3101 {
3102  ULONG i, j, PrivilegeCount, ChangeCount, NewAttributes;
3103 
3104  /* Count the found privileges and those that need to be changed */
3105  PrivilegeCount = 0;
3106  ChangeCount = 0;
3107  *ChangesMade = FALSE;
3108 
3109  /* Loop all privileges in the token */
3110  for (i = 0; i < Token->PrivilegeCount; i++)
3111  {
3112  /* Shall all of them be disabled? */
3113  if (DisableAllPrivileges)
3114  {
3115  /* The new attributes are the old ones, but disabled */
3116  NewAttributes = Token->Privileges[i].Attributes & ~SE_PRIVILEGE_ENABLED;
3117  }
3118  else
3119  {
3120  /* Otherwise loop all provided privileges */
3121  for (j = 0; j < NewStateCount; j++)
3122  {
3123  /* Check if this is the LUID we are looking for */
3124  if (RtlEqualLuid(&Token->Privileges[i].Luid, &NewState[j].Luid))
3125  {
3126  DPRINT("Found privilege\n");
3127 
3128  /* Copy SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED */
3129  NewAttributes = NewState[j].Attributes;
3130  NewAttributes &= (SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED);
3131  NewAttributes |= Token->Privileges[i].Attributes & ~SE_PRIVILEGE_ENABLED;
3132 
3133  /* Stop looking */
3134  break;
3135  }
3136  }
3137 
3138  /* Check if we didn't find the privilege */
3139  if (j == NewStateCount)
3140  {
3141  /* Continue with the token's next privilege */
3142  continue;
3143  }
3144  }
3145 
3146  /* We found a privilege, count it */
3147  PrivilegeCount++;
3148 
3149  /* Does the privilege need to be changed? */
3150  if (Token->Privileges[i].Attributes != NewAttributes)
3151  {
3152  /* Does the caller want the old privileges? */
3153  if (PreviousState != NULL)
3154  {
3155  /* Copy the old privilege */
3156  PreviousState->Privileges[ChangeCount] = Token->Privileges[i];
3157  }
3158 
3159  /* Does the caller want to apply the changes? */
3160  if (ApplyChanges)
3161  {
3162  /* Shall we remove the privilege? */
3163  if (NewAttributes & SE_PRIVILEGE_REMOVED)
3164  {
3165  /* Set the token as disabled and update flags for it */
3166  Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
3168 
3169  /* Remove the privilege */
3171 
3172  *ChangesMade = TRUE;
3173 
3174  /* Fix the running index and continue with next one */
3175  i--;
3176  continue;
3177  }
3178 
3179  /* Set the new attributes and update flags */
3180  Token->Privileges[i].Attributes = NewAttributes;
3182  *ChangesMade = TRUE;
3183  }
3184 
3185  /* Increment the change count */
3186  ChangeCount++;
3187  }
3188  }
3189 
3190  /* Set the number of saved privileges */
3191  if (PreviousState != NULL)
3192  PreviousState->PrivilegeCount = ChangeCount;
3193 
3194  /* Return the number of changed privileges */
3195  *ChangedPrivileges = ChangeCount;
3196 
3197  /* Check if we missed some */
3198  if (!DisableAllPrivileges && (PrivilegeCount < NewStateCount))
3199  {
3200  return STATUS_NOT_ALL_ASSIGNED;
3201  }
3202 
3203  return STATUS_SUCCESS;
3204 }
3205 
3206 
3207 /*
3208  * @implemented
3209  */
3212 NTSTATUS
3213 NTAPI
3216  _In_ BOOLEAN DisableAllPrivileges,
3217  _In_opt_ PTOKEN_PRIVILEGES NewState,
3222 {
3223  NTSTATUS Status;
3225  PTOKEN Token;
3226  PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
3227  ULONG CapturedCount = 0;
3228  ULONG CapturedLength = 0;
3229  ULONG NewStateSize = 0;
3230  ULONG ChangeCount;
3232  BOOLEAN ChangesMade = FALSE;
3233 
3234  PAGED_CODE();
3235 
3236  DPRINT("NtAdjustPrivilegesToken() called\n");
3237 
3238  /* Fail, if we do not disable all privileges but NewState is NULL */
3239  if (DisableAllPrivileges == FALSE && NewState == NULL)
3240  return STATUS_INVALID_PARAMETER;
3241 
3243  if (PreviousMode != KernelMode)
3244  {
3245  _SEH2_TRY
3246  {
3247  /* Probe NewState */
3248  if (DisableAllPrivileges == FALSE)
3249  {
3250  /* First probe the header */
3251  ProbeForRead(NewState, sizeof(TOKEN_PRIVILEGES), sizeof(ULONG));
3252 
3253  CapturedCount = NewState->PrivilegeCount;
3254  NewStateSize = FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges[CapturedCount]);
3255 
3256  ProbeForRead(NewState, NewStateSize, sizeof(ULONG));
3257  }
3258 
3259  /* Probe PreviousState and ReturnLength */
3260  if (PreviousState != NULL)
3261  {
3263  ProbeForWrite(ReturnLength, sizeof(ULONG), sizeof(ULONG));
3264  }
3265  }
3267  {
3268  /* Return the exception code */
3270  }
3271  _SEH2_END;
3272  }
3273  else
3274  {
3275  /* This is kernel mode, we trust the caller */
3276  if (DisableAllPrivileges == FALSE)
3277  CapturedCount = NewState->PrivilegeCount;
3278  }
3279 
3280  /* Do we need to capture the new state? */
3281  if (DisableAllPrivileges == FALSE)
3282  {
3283  _SEH2_TRY
3284  {
3285  /* Capture the new state array of privileges */
3286  Status = SeCaptureLuidAndAttributesArray(NewState->Privileges,
3287  CapturedCount,
3288  PreviousMode,
3289  NULL,
3290  0,
3291  PagedPool,
3292  TRUE,
3293  &CapturedPrivileges,
3294  &CapturedLength);
3295  }
3297  {
3298  /* Return the exception code */
3300  }
3301  _SEH2_END;
3302 
3303  if (!NT_SUCCESS(Status))
3304  return Status;
3305  }
3306 
3307  /* Reference the token */
3311  PreviousMode,
3312  (PVOID*)&Token,
3313  NULL);
3314  if (!NT_SUCCESS(Status))
3315  {
3316  DPRINT1("Failed to reference token (Status 0x%lx)\n", Status);
3317 
3318  /* Release the captured privileges */
3319  if (CapturedPrivileges != NULL)
3320  {
3321  SeReleaseLuidAndAttributesArray(CapturedPrivileges,
3322  PreviousMode,
3323  TRUE);
3324  }
3325 
3326  return Status;
3327  }
3328 
3329  /* Lock the token */
3331 
3332  /* Count the privileges that need to be changed, do not apply them yet */
3334  DisableAllPrivileges,
3335  CapturedPrivileges,
3336  CapturedCount,
3337  NULL,
3338  FALSE,
3339  &ChangeCount,
3340  &ChangesMade);
3341 
3342  /* Check if the caller asked for the previous state */
3343  if (PreviousState != NULL)
3344  {
3345  /* Calculate the required length */
3347 
3348  /* Try to return the required buffer length */
3349  _SEH2_TRY
3350  {
3352  }
3354  {
3355  /* Do cleanup and return the exception code */
3357  _SEH2_YIELD(goto Cleanup);
3358  }
3359  _SEH2_END;
3360 
3361  /* Fail, if the buffer length is smaller than the required length */
3363  {
3365  goto Cleanup;
3366  }
3367  }
3368 
3369  /* Now enter SEH, since we might return the old privileges */
3370  _SEH2_TRY
3371  {
3372  /* This time apply the changes */
3374  DisableAllPrivileges,
3375  CapturedPrivileges,
3376  CapturedCount,
3377  PreviousState,
3378  TRUE,
3379  &ChangeCount,
3380  &ChangesMade);
3381  }
3383  {
3384  /* Do cleanup and return the exception code */
3386  ChangesMade = TRUE; // Force write.
3387  _SEH2_YIELD(goto Cleanup);
3388  }
3389  _SEH2_END;
3390 
3391 Cleanup:
3392  /* Touch the token if we made changes */
3393  if (ChangesMade)
3394  ExAllocateLocallyUniqueId(&Token->ModifiedId);
3395 
3396  /* Unlock and dereference the token */
3399 
3400  /* Release the captured privileges */
3401  if (CapturedPrivileges != NULL)
3402  {
3403  SeReleaseLuidAndAttributesArray(CapturedPrivileges,
3404  PreviousMode,
3405  TRUE);
3406  }
3407 
3408  DPRINT ("NtAdjustPrivilegesToken() done\n");
3409  return Status;
3410 }
3411 
3413 NTSTATUS
3414 NTAPI
3420  _In_ PLUID AuthenticationId,
3421  _In_ PLARGE_INTEGER ExpirationTime,
3429 {
3430  HANDLE hToken;
3432  ULONG PrivilegeCount, GroupCount;
3433  PSID OwnerSid, PrimaryGroupSid;
3434  PACL DefaultDacl;
3435  LARGE_INTEGER LocalExpirationTime = {{0, 0}};
3436  LUID LocalAuthenticationId;
3437  TOKEN_SOURCE LocalTokenSource;
3438  SECURITY_QUALITY_OF_SERVICE LocalSecurityQos;
3439  PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
3440  PSID_AND_ATTRIBUTES CapturedUser = NULL;
3441  PSID_AND_ATTRIBUTES CapturedGroups = NULL;
3442  PSID CapturedOwnerSid = NULL;
3443  PSID CapturedPrimaryGroupSid = NULL;
3444  PACL CapturedDefaultDacl = NULL;
3445  ULONG PrivilegesLength, UserLength, GroupsLength;
3446  NTSTATUS Status;
3447 
3448  PAGED_CODE();
3449 
3451 
3452  if (PreviousMode != KernelMode)
3453  {
3454  _SEH2_TRY
3455  {
3457 
3458  if (ObjectAttributes != NULL)
3459  {
3461  sizeof(OBJECT_ATTRIBUTES),
3462  sizeof(ULONG));
3463  LocalSecurityQos = *(SECURITY_QUALITY_OF_SERVICE*)ObjectAttributes->SecurityQualityOfService;
3464  }
3465 
3466  ProbeForRead(AuthenticationId,
3467  sizeof(LUID),
3468  sizeof(ULONG));
3469  LocalAuthenticationId = *AuthenticationId;
3470 
3471  LocalExpirationTime = ProbeForReadLargeInteger(ExpirationTime);
3472 
3474  sizeof(TOKEN_USER),
3475  sizeof(ULONG));
3476 
3478  sizeof(TOKEN_GROUPS),
3479  sizeof(ULONG));
3480  GroupCount = TokenGroups->GroupCount;
3481 
3483  sizeof(TOKEN_PRIVILEGES),
3484  sizeof(ULONG));
3485  PrivilegeCount = TokenPrivileges->PrivilegeCount;
3486 
3487  if (TokenOwner != NULL)
3488  {
3490  sizeof(TOKEN_OWNER),
3491  sizeof(ULONG));
3492  OwnerSid = TokenOwner->Owner;
3493  }
3494  else
3495  {
3496  OwnerSid = NULL;
3497  }
3498 
3500  sizeof(TOKEN_PRIMARY_GROUP),
3501  sizeof(ULONG));
3502  PrimaryGroupSid = TokenPrimaryGroup->PrimaryGroup;
3503 
3504  if (TokenDefaultDacl != NULL)
3505  {
3507  sizeof(TOKEN_DEFAULT_DACL),
3508  sizeof(ULONG));
3509  DefaultDacl = TokenDefaultDacl->DefaultDacl;
3510  }
3511  else
3512  {
3513  DefaultDacl = NULL;
3514  }
3515 
3517  sizeof(TOKEN_SOURCE),
3518  sizeof(ULONG));
3519  LocalTokenSource = *TokenSource;
3520  }
3522  {
3523  /* Return the exception code */
3525  }
3526  _SEH2_END;
3527  }
3528  else
3529  {
3530  if (ObjectAttributes != NULL)
3531  LocalSecurityQos = *(SECURITY_QUALITY_OF_SERVICE*)ObjectAttributes->SecurityQualityOfService;
3532  LocalAuthenticationId = *AuthenticationId;
3533  LocalExpirationTime = *ExpirationTime;
3534  GroupCount = TokenGroups->GroupCount;
3535  PrivilegeCount = TokenPrivileges->PrivilegeCount;
3536  OwnerSid = TokenOwner ? TokenOwner->Owner : NULL;
3537  PrimaryGroupSid = TokenPrimaryGroup->PrimaryGroup;
3538  DefaultDacl = TokenDefaultDacl ? TokenDefaultDacl->DefaultDacl : NULL;
3539  LocalTokenSource = *TokenSource;
3540  }
3541 
3542  /* Check token type */
3543  if ((TokenType < TokenPrimary) ||
3545  {
3546  return STATUS_BAD_TOKEN_TYPE;
3547  }
3548 
3549  /* Check for token creation privilege */
3551  {
3553  }
3554 
3555  /* Capture the user SID and attributes */
3557  1,
3558  PreviousMode,
3559  NULL,
3560  0,
3561  PagedPool,
3562  FALSE,
3563  &CapturedUser,
3564  &UserLength);
3565  if (!NT_SUCCESS(Status))
3566  {
3567  goto Cleanup;
3568  }
3569 
3570  /* Capture the groups SID and attributes array */
3572  GroupCount,
3573  PreviousMode,
3574  NULL,
3575  0,
3576  PagedPool,
3577  FALSE,
3578  &CapturedGroups,
3579  &GroupsLength);
3580  if (!NT_SUCCESS(Status))
3581  {
3582  goto Cleanup;
3583  }
3584 
3585  /* Capture privileges */
3587  PrivilegeCount,
3588  PreviousMode,
3589  NULL,
3590  0,
3591  PagedPool,
3592  FALSE,
3593  &CapturedPrivileges,
3594  &PrivilegesLength);
3595  if (!NT_SUCCESS(Status))
3596  {
3597  goto Cleanup;
3598  }
3599 
3600  /* Capture the token owner SID */
3601  if (TokenOwner != NULL)
3602  {
3603  Status = SepCaptureSid(OwnerSid,
3604  PreviousMode,
3605  PagedPool,
3606  FALSE,
3607  &CapturedOwnerSid);
3608  if (!NT_SUCCESS(Status))
3609  {
3610  goto Cleanup;
3611  }
3612  }
3613 
3614  /* Capture the token primary group SID */
3615  Status = SepCaptureSid(PrimaryGroupSid,
3616  PreviousMode,
3617  PagedPool,
3618  FALSE,
3619  &CapturedPrimaryGroupSid);
3620  if (!NT_SUCCESS(Status))
3621  {
3622  goto Cleanup;
3623  }
3624 
3625  /* Capture DefaultDacl */
3626  if (DefaultDacl != NULL)
3627  {
3628  Status = SepCaptureAcl(DefaultDacl,
3629  PreviousMode,
3630  NonPagedPool,
3631  FALSE,
3632  &CapturedDefaultDacl);
3633  if (!NT_SUCCESS(Status))
3634  {
3635  goto Cleanup;
3636  }
3637  }
3638 
3639  /* Call the internal function */
3640  Status = SepCreateToken(&hToken,
3641  PreviousMode,
3642  DesiredAccess,
3644  TokenType,
3645  LocalSecurityQos.ImpersonationLevel,
3646  &LocalAuthenticationId,
3647  &LocalExpirationTime,
3648  CapturedUser,
3649  GroupCount,
3650  CapturedGroups,
3651  0, // FIXME: Should capture
3652  PrivilegeCount,
3653  CapturedPrivileges,
3654  CapturedOwnerSid,
3655  CapturedPrimaryGroupSid,
3656  CapturedDefaultDacl,
3657  &LocalTokenSource,
3658  FALSE);
3659  if (NT_SUCCESS(Status))
3660  {
3661  _SEH2_TRY
3662  {
3663  *TokenHandle = hToken;
3664  }
3666  {
3668  }
3669  _SEH2_END;
3670  }
3671 
3672 Cleanup:
3673 
3674  /* Release what we captured */
3677  SeReleaseLuidAndAttributesArray(CapturedPrivileges, PreviousMode, FALSE);
3678  SepReleaseSid(CapturedOwnerSid, PreviousMode, FALSE);
3679  SepReleaseSid(CapturedPrimaryGroupSid, PreviousMode, FALSE);
3680  SepReleaseAcl(CapturedDefaultDacl, PreviousMode, FALSE);
3681 
3682  return Status;
3683 }
3684 
3685 /*
3686  * @implemented
3687  */
3688 NTSTATUS
3689 NTAPI
3695 {
3696  PETHREAD Thread, NewThread;
3697  HANDLE hToken;
3698  PTOKEN Token, NewToken = NULL, PrimaryToken;
3704  PACL Dacl = NULL;
3706  NTSTATUS Status;
3707  BOOLEAN RestoreImpersonation = FALSE;
3708 
3709  PAGED_CODE();
3710 
3712 
3713  if (PreviousMode != KernelMode)
3714  {
3715  _SEH2_TRY
3716  {
3718  }
3720  {
3721  /* Return the exception code */
3723  }
3724  _SEH2_END;
3725  }
3726 
3727  /* Validate object attributes */
3729 
3730  /*
3731  * At first open the thread token for information access and verify
3732  * that the token associated with thread is valid.
3733  */
3734 
3737  NULL);
3738  if (!NT_SUCCESS(Status))
3739  {
3740  return Status;
3741  }
3742 
3745  if (Token == NULL)
3746  {
3748  return STATUS_NO_TOKEN;
3749  }
3750 
3752  {
3756  }
3757 
3758  /*
3759  * Revert to self if OpenAsSelf is specified.
3760  */
3761 
3762  if (OpenAsSelf)
3763  {
3764  RestoreImpersonation = PsDisableImpersonation(PsGetCurrentThread(),
3766  }
3767 
3768  if (CopyOnOpen)
3769  {
3772  (PVOID*)&NewThread, NULL);
3773  if (NT_SUCCESS(Status))
3774  {
3775  PrimaryToken = PsReferencePrimaryToken(NewThread->ThreadsProcess);
3776 
3777  Status = SepCreateImpersonationTokenDacl(Token, PrimaryToken, &Dacl);
3778 
3779  ObFastDereferenceObject(&NewThread->ThreadsProcess->Token, PrimaryToken);
3780 
3781  if (NT_SUCCESS(Status))
3782  {
3783  if (Dacl)
3784  {
3788  FALSE);
3789  }
3790 
3793 
3796  KernelMode, &NewToken);
3797  if (NT_SUCCESS(Status))
3798  {
3799  ObReferenceObject(NewToken);
3800  Status = ObInsertObject(NewToken, NULL, DesiredAccess, 0, NULL,
3801  &hToken);
3802  }
3803  }
3804  }
3805  }
3806  else
3807  {
3810  PreviousMode, &hToken);
3811  }
3812 
3814 
3815  if (RestoreImpersonation)
3816  {
3818  }
3819 
3821 
3822  if (NT_SUCCESS(Status) && CopyOnOpen)
3823  {
3825  }
3826 
3827  if (NewToken) ObDereferenceObject(NewToken);
3828 
3829  if (CopyOnOpen && NewThread) ObDereferenceObject(NewThread);
3830 
3832 
3833  if (NT_SUCCESS(Status))
3834  {
3835  _SEH2_TRY
3836  {
3837  *TokenHandle = hToken;
3838  }
3840  {
3842  }
3843  _SEH2_END;
3844  }
3845 
3846  return Status;
3847 }
3848 
3849 /*
3850  * @implemented
3851  */
3857 {
3858  return NtOpenThreadTokenEx(ThreadHandle, DesiredAccess, OpenAsSelf, 0,
3859  TokenHandle);
3860 }
3861 
3862 /*
3863  * @unimplemented
3864  */
3865 NTSTATUS
3866 NTAPI
3867 NtCompareTokens(IN HANDLE FirstTokenHandle,
3868  IN HANDLE SecondTokenHandle,
3869  OUT PBOOLEAN Equal)
3870 {
3872  PTOKEN FirstToken, SecondToken;
3873  BOOLEAN IsEqual;
3874  NTSTATUS Status;
3875 
3876  PAGED_CODE();
3877 
3879 
3880  if (PreviousMode != KernelMode)
3881  {
3882  _SEH2_TRY
3883  {
3884  ProbeForWriteBoolean(Equal);
3885  }
3887  {
3888  /* Return the exception code */
3890  }
3891  _SEH2_END;
3892  }
3893 
3894  Status = ObReferenceObjectByHandle(FirstTokenHandle,
3895  TOKEN_QUERY,
3897  PreviousMode,
3898  (PVOID*)&FirstToken,
3899  NULL);
3900  if (!NT_SUCCESS(Status))
3901  return Status;
3902 
3903  Status = ObReferenceObjectByHandle(SecondTokenHandle,
3904  TOKEN_QUERY,
3906  PreviousMode,
3907  (PVOID*)&SecondToken,
3908  NULL);
3909  if (!NT_SUCCESS(Status))
3910  {
3911  ObDereferenceObject(FirstToken);
3912  return Status;
3913  }
3914 
3915  if (FirstToken != SecondToken)
3916  {
3917  Status = SepCompareTokens(FirstToken,
3918  SecondToken,
3919  &IsEqual);
3920  }
3921  else
3922  {
3923  IsEqual = TRUE;
3924  }
3925 
3926  ObDereferenceObject(SecondToken);
3927  ObDereferenceObject(FirstToken);
3928 
3929  if (NT_SUCCESS(Status))
3930  {
3931  _SEH2_TRY
3932  {
3933  *Equal = IsEqual;
3934  }
3936  {
3938  }
3939  _SEH2_END;
3940  }
3941 
3942  return Status;
3943 }
3944 
3945 NTSTATUS
3946 NTAPI
3947 NtFilterToken(IN HANDLE ExistingTokenHandle,
3948  IN ULONG Flags,
3949  IN PTOKEN_GROUPS SidsToDisable OPTIONAL,
3950  IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL,
3951  IN PTOKEN_GROUPS RestrictedSids OPTIONAL,
3953 {
3954  UNIMPLEMENTED;
3955  return STATUS_NOT_IMPLEMENTED;
3956 }
3957 
3958 /*
3959  * @unimplemented
3960  */
3961 NTSTATUS
3962 NTAPI
3964 {
3965  UNIMPLEMENTED;
3966  return STATUS_NOT_IMPLEMENTED;
3967 }
3968 
3969 /* EOF */
#define OBJ_OPENLINK
Definition: winternl.h:230
TOKEN_TYPE TokenType
Definition: setypes.h:175
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:340
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
NTSTATUS NTAPI NtImpersonateAnonymousToken(IN HANDLE Thread)
Definition: token.c:3963
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:1149
struct _TOKEN_AUDIT_POLICY_INFORMATION::@1816 Policies[1]
#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 ExInitializeResource
Definition: exfuncs.h:346
#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:1285
#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:3947
ERESOURCE SepTokenLock
Definition: token.c:30
NTSTATUS NTAPI SeIsTokenChild(IN PTOKEN Token, OUT PBOOLEAN IsChild)
Definition: token.c:711
#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:220
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:1726
LUID AuthenticationId
Definition: setypes.h:155
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:3690
LUID SeSystemAuthenticationId
Definition: token.c:33
_Out_ PBOOLEAN CopyOnOpen
Definition: psfuncs.h:154
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:124
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:1802
#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:436
NTSTATUS NTAPI SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token, OUT PLUID LogonId)
Definition: token.c:1747
ULONG TokenFlags
Definition: setypes.h:177
NTSTATUS NTAPI NtCompareTokens(IN HANDLE FirstTokenHandle, IN HANDLE SecondTokenHandle, OUT PBOOLEAN Equal)
Definition: token.c:3867
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:34
#define RtlEqualLuid(Luid1, Luid2)
Definition: rtlfuncs.h:301
static VOID SepUpdatePrivilegeFlagsToken(_Inout_ PTOKEN Token)
Definition: token.c:175
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:3078
PTOKEN NTAPI SepCreateSystemProcessToken(VOID)
Definition: token.c:1140
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:1834
#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:156
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
void DPRINT(...)
Definition: polytest.cpp:61
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:877
#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:1775
void * PVOID
Definition: retypes.h:9
struct _TOKEN_GROUPS * PTOKEN_GROUPS
SECURITY_IMPERSONATION_LEVEL NTAPI SeTokenImpersonationLevel(IN PACCESS_TOKEN Token)
Definition: token.c:1763
ULONG SessionId
Definition: setypes.h:161
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:173
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:3092
#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:351
#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:178
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:213
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:137
NTSTATUS NTAPI SeIsTokenSibling(IN PTOKEN Token, OUT PBOOLEAN IsSibling)
Definition: token.c:744
#define ProbeForWriteBoolean(Ptr)
Definition: probe.h:31
VOID NTAPI SeAssignPrimaryToken(IN PEPROCESS Process, IN PTOKEN Token)
Definition: token.c:857
#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:831
_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:667
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
POBJECT_TYPE PsThreadType
Definition: thread.c:20
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:32
#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:3415
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:36
#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:308
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:190
#define SE_IMPERSONATE_PRIVILEGE
Definition: security.c:683
const LUID SeShutdownPrivilege
Definition: priv.c:36
_SEH2_END
Definition: create.c:4400
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:1304
struct _TOKEN * PTOKEN
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
VOID NTAPI SepDeleteToken(PVOID ObjectBody)
Definition: token.c:812
#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:154
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:1788
_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:2409
#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:3853
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
#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:43
#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:323
static NTSTATUS SepCompareTokens(IN PTOKEN FirstToken, IN PTOKEN SecondToken, OUT PBOOLEAN Equal)
Definition: token.c:87
_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:2936
#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
_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:1816
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:229
NTSTATUS NTAPI SeCopyClientToken(IN PACCESS_TOKEN Token, IN SECURITY_IMPERSONATION_LEVEL Level, IN KPROCESSOR_MODE PreviousMode, OUT PACCESS_TOKEN *NewToken)
Definition: token.c:783
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:3214
_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