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