Sync to trunk r39350.
[reactos.git] / reactos / ntoskrnl / se / token.c
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 /* GLOBALS ********************************************************************/
21
22 POBJECT_TYPE SepTokenObjectType = NULL;
23 ERESOURCE SepTokenLock;
24
25 static GENERIC_MAPPING SepTokenMapping = {TOKEN_READ,
26 TOKEN_WRITE,
27 TOKEN_EXECUTE,
28 TOKEN_ALL_ACCESS};
29
30 static const INFORMATION_CLASS_INFO SeTokenInformationClass[] = {
31
32 /* Class 0 not used, blame M$! */
33 ICI_SQ_SAME( 0, 0, 0),
34
35 /* TokenUser */
36 ICI_SQ_SAME( sizeof(TOKEN_USER), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
37 /* TokenGroups */
38 ICI_SQ_SAME( sizeof(TOKEN_GROUPS), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
39 /* TokenPrivileges */
40 ICI_SQ_SAME( sizeof(TOKEN_PRIVILEGES), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
41 /* TokenOwner */
42 ICI_SQ_SAME( sizeof(TOKEN_OWNER), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
43 /* TokenPrimaryGroup */
44 ICI_SQ_SAME( sizeof(TOKEN_PRIMARY_GROUP), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
45 /* TokenDefaultDacl */
46 ICI_SQ_SAME( sizeof(TOKEN_DEFAULT_DACL), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
47 /* TokenSource */
48 ICI_SQ_SAME( sizeof(TOKEN_SOURCE), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
49 /* TokenType */
50 ICI_SQ_SAME( sizeof(TOKEN_TYPE), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
51 /* TokenImpersonationLevel */
52 ICI_SQ_SAME( sizeof(SECURITY_IMPERSONATION_LEVEL), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
53 /* TokenStatistics */
54 ICI_SQ_SAME( sizeof(TOKEN_STATISTICS), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE | ICIF_SET | ICIF_SET_SIZE_VARIABLE ),
55 /* TokenRestrictedSids */
56 ICI_SQ_SAME( sizeof(TOKEN_GROUPS), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
57 /* TokenSessionId */
58 ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY | ICIF_SET ),
59 /* TokenGroupsAndPrivileges */
60 ICI_SQ_SAME( sizeof(TOKEN_GROUPS_AND_PRIVILEGES), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
61 /* TokenSessionReference */
62 ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
63 /* TokenSandBoxInert */
64 ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
65 /* TokenAuditPolicy */
66 ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
67 /* TokenOrigin */
68 ICI_SQ_SAME( sizeof(TOKEN_ORIGIN), sizeof(ULONG), ICIF_QUERY | ICIF_QUERY_SIZE_VARIABLE ),
69 };
70
71 /* FUNCTIONS *****************************************************************/
72
73 static NTSTATUS
74 SepCompareTokens(IN PTOKEN FirstToken,
75 IN PTOKEN SecondToken,
76 OUT PBOOLEAN Equal)
77 {
78 BOOLEAN Restricted, IsEqual = FALSE;
79
80 ASSERT(FirstToken != SecondToken);
81
82 /* FIXME: Check if every SID that is present in either token is also present in the other one */
83
84 Restricted = SeTokenIsRestricted(FirstToken);
85 if (Restricted == SeTokenIsRestricted(SecondToken))
86 {
87 if (Restricted)
88 {
89 /* FIXME: Check if every SID that is restricted in either token is also restricted in the other one */
90 }
91
92 /* FIXME: Check if every privilege that is present in either token is also present in the other one */
93 }
94
95 *Equal = IsEqual;
96 return STATUS_SUCCESS;
97 }
98
99 VOID
100 NTAPI
101 SepFreeProxyData(PVOID ProxyData)
102 {
103 UNIMPLEMENTED;
104 }
105
106 NTSTATUS
107 NTAPI
108 SepCopyProxyData(PVOID* Dest, PVOID Src)
109 {
110 UNIMPLEMENTED;
111 return(STATUS_NOT_IMPLEMENTED);
112 }
113
114 NTSTATUS
115 NTAPI
116 SeExchangePrimaryToken(PEPROCESS Process,
117 PACCESS_TOKEN NewTokenP,
118 PACCESS_TOKEN* OldTokenP)
119 {
120 PTOKEN OldToken;
121 PTOKEN NewToken = (PTOKEN)NewTokenP;
122
123 PAGED_CODE();
124
125 if (NewToken->TokenType != TokenPrimary) return(STATUS_BAD_TOKEN_TYPE);
126 if (NewToken->TokenInUse) return(STATUS_TOKEN_ALREADY_IN_USE);
127
128 /* Mark new token in use */
129 NewToken->TokenInUse = 1;
130
131 /* Reference the New Token */
132 ObReferenceObject(NewToken);
133
134 /* Replace the old with the new */
135 OldToken = ObFastReplaceObject(&Process->Token, NewToken);
136
137 /* Mark the Old Token as free */
138 OldToken->TokenInUse = 0;
139
140 *OldTokenP = (PACCESS_TOKEN)OldToken;
141 return STATUS_SUCCESS;
142 }
143
144 VOID
145 NTAPI
146 SeDeassignPrimaryToken(PEPROCESS Process)
147 {
148 PTOKEN OldToken;
149
150 /* Remove the Token */
151 OldToken = ObFastReplaceObject(&Process->Token, NULL);
152
153 /* Mark the Old Token as free */
154 OldToken->TokenInUse = 0;
155 }
156
157 static ULONG
158 RtlLengthSidAndAttributes(ULONG Count,
159 PSID_AND_ATTRIBUTES Src)
160 {
161 ULONG i;
162 ULONG uLength;
163
164 PAGED_CODE();
165
166 uLength = Count * sizeof(SID_AND_ATTRIBUTES);
167 for (i = 0; i < Count; i++)
168 uLength += RtlLengthSid(Src[i].Sid);
169
170 return(uLength);
171 }
172
173
174 NTSTATUS
175 NTAPI
176 SepFindPrimaryGroupAndDefaultOwner(PTOKEN Token,
177 PSID PrimaryGroup,
178 PSID DefaultOwner)
179 {
180 ULONG i;
181
182 Token->PrimaryGroup = 0;
183
184 if (DefaultOwner)
185 {
186 Token->DefaultOwnerIndex = Token->UserAndGroupCount;
187 }
188
189 /* Validate and set the primary group and user pointers */
190 for (i = 0; i < Token->UserAndGroupCount; i++)
191 {
192 if (DefaultOwner &&
193 RtlEqualSid(Token->UserAndGroups[i].Sid, DefaultOwner))
194 {
195 Token->DefaultOwnerIndex = i;
196 }
197
198 if (RtlEqualSid(Token->UserAndGroups[i].Sid, PrimaryGroup))
199 {
200 Token->PrimaryGroup = Token->UserAndGroups[i].Sid;
201 }
202 }
203
204 if (Token->DefaultOwnerIndex == Token->UserAndGroupCount)
205 {
206 return(STATUS_INVALID_OWNER);
207 }
208
209 if (Token->PrimaryGroup == 0)
210 {
211 return(STATUS_INVALID_PRIMARY_GROUP);
212 }
213
214 return(STATUS_SUCCESS);
215 }
216
217
218 NTSTATUS
219 NTAPI
220 SepDuplicateToken(PTOKEN Token,
221 POBJECT_ATTRIBUTES ObjectAttributes,
222 BOOLEAN EffectiveOnly,
223 TOKEN_TYPE TokenType,
224 SECURITY_IMPERSONATION_LEVEL Level,
225 KPROCESSOR_MODE PreviousMode,
226 PTOKEN* NewAccessToken)
227 {
228 ULONG uLength;
229 ULONG i;
230 PVOID EndMem;
231 PTOKEN AccessToken;
232 NTSTATUS Status;
233
234 PAGED_CODE();
235
236 Status = ObCreateObject(PreviousMode,
237 SepTokenObjectType,
238 ObjectAttributes,
239 PreviousMode,
240 NULL,
241 sizeof(TOKEN),
242 0,
243 0,
244 (PVOID*)&AccessToken);
245 if (!NT_SUCCESS(Status))
246 {
247 DPRINT1("ObCreateObject() failed (Status %lx)\n");
248 return(Status);
249 }
250
251 Status = ZwAllocateLocallyUniqueId(&AccessToken->TokenId);
252 if (!NT_SUCCESS(Status))
253 {
254 ObDereferenceObject(AccessToken);
255 return(Status);
256 }
257
258 Status = ZwAllocateLocallyUniqueId(&AccessToken->ModifiedId);
259 if (!NT_SUCCESS(Status))
260 {
261 ObDereferenceObject(AccessToken);
262 return(Status);
263 }
264
265 AccessToken->TokenLock = &SepTokenLock;
266
267 AccessToken->TokenInUse = 0;
268 AccessToken->TokenType = TokenType;
269 AccessToken->ImpersonationLevel = Level;
270 RtlCopyLuid(&AccessToken->AuthenticationId, &Token->AuthenticationId);
271
272 AccessToken->TokenSource.SourceIdentifier.LowPart = Token->TokenSource.SourceIdentifier.LowPart;
273 AccessToken->TokenSource.SourceIdentifier.HighPart = Token->TokenSource.SourceIdentifier.HighPart;
274 memcpy(AccessToken->TokenSource.SourceName,
275 Token->TokenSource.SourceName,
276 sizeof(Token->TokenSource.SourceName));
277 AccessToken->ExpirationTime.QuadPart = Token->ExpirationTime.QuadPart;
278 AccessToken->UserAndGroupCount = Token->UserAndGroupCount;
279 AccessToken->DefaultOwnerIndex = Token->DefaultOwnerIndex;
280
281 uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
282 for (i = 0; i < Token->UserAndGroupCount; i++)
283 uLength += RtlLengthSid(Token->UserAndGroups[i].Sid);
284
285 AccessToken->UserAndGroups =
286 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
287 uLength,
288 TAG('T', 'O', 'K', 'u'));
289
290 EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
291
292 Status = RtlCopySidAndAttributesArray(AccessToken->UserAndGroupCount,
293 Token->UserAndGroups,
294 uLength,
295 AccessToken->UserAndGroups,
296 EndMem,
297 &EndMem,
298 &uLength);
299 if (NT_SUCCESS(Status))
300 {
301 Status = SepFindPrimaryGroupAndDefaultOwner(
302 AccessToken,
303 Token->PrimaryGroup,
304 0);
305 }
306
307 if (NT_SUCCESS(Status))
308 {
309 AccessToken->PrivilegeCount = Token->PrivilegeCount;
310
311 uLength = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
312 AccessToken->Privileges =
313 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
314 uLength,
315 TAG('T', 'O', 'K', 'p'));
316
317 for (i = 0; i < AccessToken->PrivilegeCount; i++)
318 {
319 RtlCopyLuid(&AccessToken->Privileges[i].Luid,
320 &Token->Privileges[i].Luid);
321 AccessToken->Privileges[i].Attributes =
322 Token->Privileges[i].Attributes;
323 }
324
325 if ( Token->DefaultDacl )
326 {
327 AccessToken->DefaultDacl =
328 (PACL) ExAllocatePoolWithTag(PagedPool,
329 Token->DefaultDacl->AclSize,
330 TAG('T', 'O', 'K', 'd'));
331 memcpy(AccessToken->DefaultDacl,
332 Token->DefaultDacl,
333 Token->DefaultDacl->AclSize);
334 }
335 else
336 {
337 AccessToken->DefaultDacl = 0;
338 }
339 }
340
341 if ( NT_SUCCESS(Status) )
342 {
343 *NewAccessToken = AccessToken;
344 return(STATUS_SUCCESS);
345 }
346
347 return(Status);
348 }
349
350 NTSTATUS
351 NTAPI
352 SeSubProcessToken(IN PTOKEN ParentToken,
353 OUT PTOKEN *Token,
354 IN BOOLEAN InUse,
355 IN ULONG SessionId)
356 {
357 PTOKEN NewToken;
358 OBJECT_ATTRIBUTES ObjectAttributes;
359 NTSTATUS Status;
360
361 /* Initialize the attributes and duplicate it */
362 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
363 Status = SepDuplicateToken(ParentToken,
364 &ObjectAttributes,
365 FALSE,
366 TokenPrimary,
367 ParentToken->ImpersonationLevel,
368 KernelMode,
369 &NewToken);
370 if (NT_SUCCESS(Status))
371 {
372 /* Insert it */
373 Status = ObInsertObject(NewToken,
374 NULL,
375 0,
376 0,
377 NULL,
378 NULL);
379 if (NT_SUCCESS(Status))
380 {
381 /* Set the session ID */
382 NewToken->SessionId = SessionId;
383 NewToken->TokenInUse = InUse;
384
385 /* Return the token */
386 *Token = NewToken;
387 }
388 }
389
390 /* Return status */
391 return Status;
392 }
393
394 NTSTATUS
395 NTAPI
396 SeIsTokenChild(IN PTOKEN Token,
397 OUT PBOOLEAN IsChild)
398 {
399 PTOKEN ProcessToken;
400 LUID ProcessLuid, CallerLuid;
401
402 /* Assume failure */
403 *IsChild = FALSE;
404
405 /* Reference the process token */
406 ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess());
407
408 /* Get the ID */
409 ProcessLuid = ProcessToken->TokenId;
410
411 /* Dereference the token */
412 ObFastDereferenceObject(&PsGetCurrentProcess()->Token, ProcessToken);
413
414 /* Get our LUID */
415 CallerLuid = Token->TokenId;
416
417 /* Compare the LUIDs */
418 if (RtlEqualLuid(&CallerLuid, &ProcessLuid)) *IsChild = TRUE;
419
420 /* Return success */
421 return STATUS_SUCCESS;
422 }
423
424 NTSTATUS
425 NTAPI
426 SeCopyClientToken(IN PACCESS_TOKEN Token,
427 IN SECURITY_IMPERSONATION_LEVEL Level,
428 IN KPROCESSOR_MODE PreviousMode,
429 OUT PACCESS_TOKEN* NewToken)
430 {
431 NTSTATUS Status;
432 OBJECT_ATTRIBUTES ObjectAttributes;
433
434 PAGED_CODE();
435
436 InitializeObjectAttributes(&ObjectAttributes,
437 NULL,
438 0,
439 NULL,
440 NULL);
441 Status = SepDuplicateToken(Token,
442 &ObjectAttributes,
443 FALSE,
444 TokenImpersonation,
445 Level,
446 PreviousMode,
447 (PTOKEN*)NewToken);
448
449 return(Status);
450 }
451
452 VOID NTAPI
453 SepDeleteToken(PVOID ObjectBody)
454 {
455 PTOKEN AccessToken = (PTOKEN)ObjectBody;
456
457 if (AccessToken->UserAndGroups)
458 ExFreePool(AccessToken->UserAndGroups);
459
460 if (AccessToken->Privileges)
461 ExFreePool(AccessToken->Privileges);
462
463 if (AccessToken->DefaultDacl)
464 ExFreePool(AccessToken->DefaultDacl);
465 }
466
467
468 VOID
469 INIT_FUNCTION
470 NTAPI
471 SepInitializeTokenImplementation(VOID)
472 {
473 UNICODE_STRING Name;
474 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
475
476 ExInitializeResource(&SepTokenLock);
477
478 DPRINT("Creating Token Object Type\n");
479
480 /* Initialize the Token type */
481 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
482 RtlInitUnicodeString(&Name, L"Token");
483 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
484 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
485 ObjectTypeInitializer.SecurityRequired = TRUE;
486 ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(TOKEN);
487 ObjectTypeInitializer.GenericMapping = SepTokenMapping;
488 ObjectTypeInitializer.PoolType = PagedPool;
489 ObjectTypeInitializer.ValidAccessMask = TOKEN_ALL_ACCESS;
490 ObjectTypeInitializer.UseDefaultObject = TRUE;
491 ObjectTypeInitializer.DeleteProcedure = SepDeleteToken;
492 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &SepTokenObjectType);
493 }
494
495 VOID
496 NTAPI
497 SeAssignPrimaryToken(IN PEPROCESS Process,
498 IN PTOKEN Token)
499 {
500 PAGED_CODE();
501
502 /* Sanity checks */
503 ASSERT(Token->TokenType == TokenPrimary);
504 ASSERT(!Token->TokenInUse);
505
506 /* Clean any previous token */
507 if (Process->Token.Object) SeDeassignPrimaryToken(Process);
508
509 /* Set the new token */
510 ObReferenceObject(Token);
511 Token->TokenInUse = TRUE;
512 ObInitializeFastReference(&Process->Token, Token);
513 }
514
515 PTOKEN
516 NTAPI
517 SepCreateSystemProcessToken(VOID)
518 {
519 NTSTATUS Status;
520 ULONG uSize;
521 ULONG i;
522 ULONG uLocalSystemLength;
523 ULONG uWorldLength;
524 ULONG uAuthUserLength;
525 ULONG uAdminsLength;
526 PTOKEN AccessToken;
527 PVOID SidArea;
528
529 PAGED_CODE();
530
531 uLocalSystemLength = RtlLengthSid(SeLocalSystemSid);
532 uWorldLength = RtlLengthSid(SeWorldSid);
533 uAuthUserLength = RtlLengthSid(SeAuthenticatedUserSid);
534 uAdminsLength = RtlLengthSid(SeAliasAdminsSid);
535
536 /*
537 * Initialize the token
538 */
539 Status = ObCreateObject(KernelMode,
540 SepTokenObjectType,
541 NULL,
542 KernelMode,
543 NULL,
544 sizeof(TOKEN),
545 0,
546 0,
547 (PVOID*)&AccessToken);
548 if (!NT_SUCCESS(Status))
549 {
550 return NULL;
551 }
552
553 Status = ExpAllocateLocallyUniqueId(&AccessToken->TokenId);
554 if (!NT_SUCCESS(Status))
555 {
556 ObDereferenceObject(AccessToken);
557 return NULL;
558 }
559
560 Status = ExpAllocateLocallyUniqueId(&AccessToken->ModifiedId);
561 if (!NT_SUCCESS(Status))
562 {
563 ObDereferenceObject(AccessToken);
564 return NULL;
565 }
566
567 Status = ExpAllocateLocallyUniqueId(&AccessToken->AuthenticationId);
568 if (!NT_SUCCESS(Status))
569 {
570 ObDereferenceObject(AccessToken);
571 return NULL;
572 }
573
574 AccessToken->TokenLock = &SepTokenLock;
575
576 AccessToken->TokenType = TokenPrimary;
577 AccessToken->ImpersonationLevel = SecurityDelegation;
578 AccessToken->TokenSource.SourceIdentifier.LowPart = 0;
579 AccessToken->TokenSource.SourceIdentifier.HighPart = 0;
580 memcpy(AccessToken->TokenSource.SourceName, "SeMgr\0\0\0", 8);
581 AccessToken->ExpirationTime.QuadPart = -1;
582 AccessToken->UserAndGroupCount = 4;
583
584 uSize = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
585 uSize += uLocalSystemLength;
586 uSize += uWorldLength;
587 uSize += uAuthUserLength;
588 uSize += uAdminsLength;
589
590 AccessToken->UserAndGroups =
591 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
592 uSize,
593 TAG('T', 'O', 'K', 'u'));
594 SidArea = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
595
596 i = 0;
597 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
598 AccessToken->UserAndGroups[i++].Attributes = 0;
599 RtlCopySid(uLocalSystemLength, SidArea, SeLocalSystemSid);
600 SidArea = (char*)SidArea + uLocalSystemLength;
601
602 AccessToken->DefaultOwnerIndex = i;
603 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
604 AccessToken->PrimaryGroup = (PSID) SidArea;
605 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT;
606 Status = RtlCopySid(uAdminsLength, SidArea, SeAliasAdminsSid);
607 SidArea = (char*)SidArea + uAdminsLength;
608
609 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
610 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
611 RtlCopySid(uWorldLength, SidArea, SeWorldSid);
612 SidArea = (char*)SidArea + uWorldLength;
613
614 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
615 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
616 RtlCopySid(uAuthUserLength, SidArea, SeAuthenticatedUserSid);
617 SidArea = (char*)SidArea + uAuthUserLength;
618
619 AccessToken->PrivilegeCount = 20;
620
621 uSize = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
622 AccessToken->Privileges =
623 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
624 uSize,
625 TAG('T', 'O', 'K', 'p'));
626
627 i = 0;
628 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
629 AccessToken->Privileges[i++].Luid = SeTcbPrivilege;
630
631 AccessToken->Privileges[i].Attributes = 0;
632 AccessToken->Privileges[i++].Luid = SeCreateTokenPrivilege;
633
634 AccessToken->Privileges[i].Attributes = 0;
635 AccessToken->Privileges[i++].Luid = SeTakeOwnershipPrivilege;
636
637 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
638 AccessToken->Privileges[i++].Luid = SeCreatePagefilePrivilege;
639
640 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
641 AccessToken->Privileges[i++].Luid = SeLockMemoryPrivilege;
642
643 AccessToken->Privileges[i].Attributes = 0;
644 AccessToken->Privileges[i++].Luid = SeAssignPrimaryTokenPrivilege;
645
646 AccessToken->Privileges[i].Attributes = 0;
647 AccessToken->Privileges[i++].Luid = SeIncreaseQuotaPrivilege;
648
649 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
650 AccessToken->Privileges[i++].Luid = SeIncreaseBasePriorityPrivilege;
651
652 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
653 AccessToken->Privileges[i++].Luid = SeCreatePermanentPrivilege;
654
655 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
656 AccessToken->Privileges[i++].Luid = SeDebugPrivilege;
657
658 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
659 AccessToken->Privileges[i++].Luid = SeAuditPrivilege;
660
661 AccessToken->Privileges[i].Attributes = 0;
662 AccessToken->Privileges[i++].Luid = SeSecurityPrivilege;
663
664 AccessToken->Privileges[i].Attributes = 0;
665 AccessToken->Privileges[i++].Luid = SeSystemEnvironmentPrivilege;
666
667 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
668 AccessToken->Privileges[i++].Luid = SeChangeNotifyPrivilege;
669
670 AccessToken->Privileges[i].Attributes = 0;
671 AccessToken->Privileges[i++].Luid = SeBackupPrivilege;
672
673 AccessToken->Privileges[i].Attributes = 0;
674 AccessToken->Privileges[i++].Luid = SeRestorePrivilege;
675
676 AccessToken->Privileges[i].Attributes = 0;
677 AccessToken->Privileges[i++].Luid = SeShutdownPrivilege;
678
679 AccessToken->Privileges[i].Attributes = 0;
680 AccessToken->Privileges[i++].Luid = SeLoadDriverPrivilege;
681
682 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
683 AccessToken->Privileges[i++].Luid = SeProfileSingleProcessPrivilege;
684
685 AccessToken->Privileges[i].Attributes = 0;
686 AccessToken->Privileges[i++].Luid = SeSystemtimePrivilege;
687 #if 0
688 AccessToken->Privileges[i].Attributes = 0;
689 AccessToken->Privileges[i++].Luid = SeUndockPrivilege;
690
691 AccessToken->Privileges[i].Attributes = 0;
692 AccessToken->Privileges[i++].Luid = SeManageVolumePrivilege;
693 #endif
694
695 ASSERT(i == 20);
696
697 uSize = sizeof(ACL);
698 uSize += sizeof(ACE) + uLocalSystemLength;
699 uSize += sizeof(ACE) + uAdminsLength;
700 uSize = (uSize & (~3)) + 8;
701 AccessToken->DefaultDacl =
702 (PACL) ExAllocatePoolWithTag(PagedPool,
703 uSize,
704 TAG('T', 'O', 'K', 'd'));
705 Status = RtlCreateAcl(AccessToken->DefaultDacl, uSize, ACL_REVISION);
706 if ( NT_SUCCESS(Status) )
707 {
708 Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid);
709 }
710
711 if ( NT_SUCCESS(Status) )
712 {
713 Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE|READ_CONTROL, SeAliasAdminsSid);
714 }
715
716 if ( ! NT_SUCCESS(Status) )
717 {
718 ObDereferenceObject(AccessToken);
719 return NULL;
720 }
721
722 return AccessToken;
723 }
724
725 /* PUBLIC FUNCTIONS ***********************************************************/
726
727 /*
728 * @unimplemented
729 */
730 NTSTATUS
731 NTAPI
732 SeFilterToken(IN PACCESS_TOKEN ExistingToken,
733 IN ULONG Flags,
734 IN PTOKEN_GROUPS SidsToDisable OPTIONAL,
735 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL,
736 IN PTOKEN_GROUPS RestrictedSids OPTIONAL,
737 OUT PACCESS_TOKEN * FilteredToken)
738 {
739 UNIMPLEMENTED;
740 return STATUS_NOT_IMPLEMENTED;
741 }
742
743 /*
744 * @unimplemented
745 */
746 NTSTATUS
747 NTAPI
748 SeQueryInformationToken(IN PACCESS_TOKEN Token,
749 IN TOKEN_INFORMATION_CLASS TokenInformationClass,
750 OUT PVOID *TokenInformation)
751 {
752 UNIMPLEMENTED;
753 return STATUS_NOT_IMPLEMENTED;
754 }
755
756 /*
757 * @implemented
758 */
759 NTSTATUS
760 NTAPI
761 SeQuerySessionIdToken(IN PACCESS_TOKEN Token,
762 IN PULONG pSessionId)
763 {
764 *pSessionId = ((PTOKEN)Token)->SessionId;
765 return STATUS_SUCCESS;
766 }
767
768 /*
769 * @implemented
770 */
771 NTSTATUS NTAPI
772 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token,
773 OUT PLUID LogonId)
774 {
775 PAGED_CODE();
776
777 *LogonId = ((PTOKEN)Token)->AuthenticationId;
778
779 return STATUS_SUCCESS;
780 }
781
782
783 /*
784 * @implemented
785 */
786 SECURITY_IMPERSONATION_LEVEL
787 NTAPI
788 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token)
789 {
790 PAGED_CODE();
791
792 return ((PTOKEN)Token)->ImpersonationLevel;
793 }
794
795
796 /*
797 * @implemented
798 */
799 TOKEN_TYPE NTAPI
800 SeTokenType(IN PACCESS_TOKEN Token)
801 {
802 PAGED_CODE();
803
804 return ((PTOKEN)Token)->TokenType;
805 }
806
807
808 /*
809 * @implemented
810 */
811 BOOLEAN
812 NTAPI
813 SeTokenIsAdmin(IN PACCESS_TOKEN Token)
814 {
815 PAGED_CODE();
816 return (((PTOKEN)Token)->TokenFlags & TOKEN_WRITE_RESTRICTED) != 0;
817 }
818
819 /*
820 * @implemented
821 */
822 BOOLEAN
823 NTAPI
824 SeTokenIsRestricted(IN PACCESS_TOKEN Token)
825 {
826 PAGED_CODE();
827 return (((PTOKEN)Token)->TokenFlags & TOKEN_IS_RESTRICTED) != 0;
828 }
829
830 /*
831 * @implemented
832 */
833 BOOLEAN
834 NTAPI
835 SeTokenIsWriteRestricted(IN PACCESS_TOKEN Token)
836 {
837 PAGED_CODE();
838 return (((PTOKEN)Token)->TokenFlags & TOKEN_HAS_RESTORE_PRIVILEGE) != 0;
839 }
840
841 /* SYSTEM CALLS ***************************************************************/
842
843 /*
844 * @implemented
845 */
846 NTSTATUS NTAPI
847 NtQueryInformationToken(IN HANDLE TokenHandle,
848 IN TOKEN_INFORMATION_CLASS TokenInformationClass,
849 OUT PVOID TokenInformation,
850 IN ULONG TokenInformationLength,
851 OUT PULONG ReturnLength)
852 {
853 union
854 {
855 PVOID Ptr;
856 ULONG Ulong;
857 } Unused;
858 PTOKEN Token;
859 ULONG RequiredLength;
860 KPROCESSOR_MODE PreviousMode;
861 NTSTATUS Status = STATUS_SUCCESS;
862
863 PAGED_CODE();
864
865 PreviousMode = ExGetPreviousMode();
866
867 /* Check buffers and class validity */
868 Status = DefaultQueryInfoBufferCheck(TokenInformationClass,
869 SeTokenInformationClass,
870 sizeof(SeTokenInformationClass) / sizeof(SeTokenInformationClass[0]),
871 TokenInformation,
872 TokenInformationLength,
873 ReturnLength,
874 NULL,
875 PreviousMode);
876
877 if(!NT_SUCCESS(Status))
878 {
879 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status);
880 return Status;
881 }
882
883 Status = ObReferenceObjectByHandle(TokenHandle,
884 (TokenInformationClass == TokenSource) ? TOKEN_QUERY_SOURCE : TOKEN_QUERY,
885 SepTokenObjectType,
886 PreviousMode,
887 (PVOID*)&Token,
888 NULL);
889 if (NT_SUCCESS(Status))
890 {
891 switch (TokenInformationClass)
892 {
893 case TokenUser:
894 {
895 PTOKEN_USER tu = (PTOKEN_USER)TokenInformation;
896
897 DPRINT("NtQueryInformationToken(TokenUser)\n");
898 RequiredLength = sizeof(TOKEN_USER) +
899 RtlLengthSid(Token->UserAndGroups[0].Sid);
900
901 _SEH2_TRY
902 {
903 if(TokenInformationLength >= RequiredLength)
904 {
905 Status = RtlCopySidAndAttributesArray(1,
906 &Token->UserAndGroups[0],
907 RequiredLength - sizeof(TOKEN_USER),
908 &tu->User,
909 (PSID)(tu + 1),
910 &Unused.Ptr,
911 &Unused.Ulong);
912 }
913 else
914 {
915 Status = STATUS_BUFFER_TOO_SMALL;
916 }
917
918 if(ReturnLength != NULL)
919 {
920 *ReturnLength = RequiredLength;
921 }
922 }
923 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
924 {
925 Status = _SEH2_GetExceptionCode();
926 }
927 _SEH2_END;
928
929 break;
930 }
931
932 case TokenGroups:
933 {
934 PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
935
936 DPRINT("NtQueryInformationToken(TokenGroups)\n");
937 RequiredLength = sizeof(tg->GroupCount) +
938 RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]);
939
940 _SEH2_TRY
941 {
942 if(TokenInformationLength >= RequiredLength)
943 {
944 ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
945 ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES));
946 PSID_AND_ATTRIBUTES Sid = (PSID_AND_ATTRIBUTES)((ULONG_PTR)TokenInformation + sizeof(tg->GroupCount) +
947 ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)));
948
949 tg->GroupCount = Token->UserAndGroupCount - 1;
950 Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
951 &Token->UserAndGroups[1],
952 SidLen,
953 &tg->Groups[0],
954 (PSID)Sid,
955 &Unused.Ptr,
956 &Unused.Ulong);
957 }
958 else
959 {
960 Status = STATUS_BUFFER_TOO_SMALL;
961 }
962
963 if(ReturnLength != NULL)
964 {
965 *ReturnLength = RequiredLength;
966 }
967 }
968 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
969 {
970 Status = _SEH2_GetExceptionCode();
971 }
972 _SEH2_END;
973
974 break;
975 }
976
977 case TokenPrivileges:
978 {
979 PTOKEN_PRIVILEGES tp = (PTOKEN_PRIVILEGES)TokenInformation;
980
981 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
982 RequiredLength = sizeof(tp->PrivilegeCount) +
983 (Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
984
985 _SEH2_TRY
986 {
987 if(TokenInformationLength >= RequiredLength)
988 {
989 tp->PrivilegeCount = Token->PrivilegeCount;
990 RtlCopyLuidAndAttributesArray(Token->PrivilegeCount,
991 Token->Privileges,
992 &tp->Privileges[0]);
993 }
994 else
995 {
996 Status = STATUS_BUFFER_TOO_SMALL;
997 }
998
999 if(ReturnLength != NULL)
1000 {
1001 *ReturnLength = RequiredLength;
1002 }
1003 }
1004 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1005 {
1006 Status = _SEH2_GetExceptionCode();
1007 }
1008 _SEH2_END;
1009
1010 break;
1011 }
1012
1013 case TokenOwner:
1014 {
1015 ULONG SidLen;
1016 PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
1017
1018 DPRINT("NtQueryInformationToken(TokenOwner)\n");
1019 SidLen = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
1020 RequiredLength = sizeof(TOKEN_OWNER) + SidLen;
1021
1022 _SEH2_TRY
1023 {
1024 if(TokenInformationLength >= RequiredLength)
1025 {
1026 to->Owner = (PSID)(to + 1);
1027 Status = RtlCopySid(SidLen,
1028 to->Owner,
1029 Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
1030 }
1031 else
1032 {
1033 Status = STATUS_BUFFER_TOO_SMALL;
1034 }
1035
1036 if(ReturnLength != NULL)
1037 {
1038 *ReturnLength = RequiredLength;
1039 }
1040 }
1041 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1042 {
1043 Status = _SEH2_GetExceptionCode();
1044 }
1045 _SEH2_END;
1046
1047 break;
1048 }
1049
1050 case TokenPrimaryGroup:
1051 {
1052 ULONG SidLen;
1053 PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
1054
1055 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
1056 SidLen = RtlLengthSid(Token->PrimaryGroup);
1057 RequiredLength = sizeof(TOKEN_PRIMARY_GROUP) + SidLen;
1058
1059 _SEH2_TRY
1060 {
1061 if(TokenInformationLength >= RequiredLength)
1062 {
1063 tpg->PrimaryGroup = (PSID)(tpg + 1);
1064 Status = RtlCopySid(SidLen,
1065 tpg->PrimaryGroup,
1066 Token->PrimaryGroup);
1067 }
1068 else
1069 {
1070 Status = STATUS_BUFFER_TOO_SMALL;
1071 }
1072
1073 if(ReturnLength != NULL)
1074 {
1075 *ReturnLength = RequiredLength;
1076 }
1077 }
1078 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1079 {
1080 Status = _SEH2_GetExceptionCode();
1081 }
1082 _SEH2_END;
1083
1084 break;
1085 }
1086
1087 case TokenDefaultDacl:
1088 {
1089 PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
1090
1091 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
1092 RequiredLength = sizeof(TOKEN_DEFAULT_DACL);
1093
1094 if(Token->DefaultDacl != NULL)
1095 {
1096 RequiredLength += Token->DefaultDacl->AclSize;
1097 }
1098
1099 _SEH2_TRY
1100 {
1101 if(TokenInformationLength >= RequiredLength)
1102 {
1103 if(Token->DefaultDacl != NULL)
1104 {
1105 tdd->DefaultDacl = (PACL)(tdd + 1);
1106 RtlCopyMemory(tdd->DefaultDacl,
1107 Token->DefaultDacl,
1108 Token->DefaultDacl->AclSize);
1109 }
1110 else
1111 {
1112 tdd->DefaultDacl = NULL;
1113 }
1114 }
1115 else
1116 {
1117 Status = STATUS_BUFFER_TOO_SMALL;
1118 }
1119
1120 if(ReturnLength != NULL)
1121 {
1122 *ReturnLength = RequiredLength;
1123 }
1124 }
1125 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1126 {
1127 Status = _SEH2_GetExceptionCode();
1128 }
1129 _SEH2_END;
1130
1131 break;
1132 }
1133
1134 case TokenSource:
1135 {
1136 PTOKEN_SOURCE ts = (PTOKEN_SOURCE)TokenInformation;
1137
1138 DPRINT("NtQueryInformationToken(TokenSource)\n");
1139 RequiredLength = sizeof(TOKEN_SOURCE);
1140
1141 _SEH2_TRY
1142 {
1143 if(TokenInformationLength >= RequiredLength)
1144 {
1145 *ts = Token->TokenSource;
1146 }
1147 else
1148 {
1149 Status = STATUS_BUFFER_TOO_SMALL;
1150 }
1151
1152 if(ReturnLength != NULL)
1153 {
1154 *ReturnLength = RequiredLength;
1155 }
1156 }
1157 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1158 {
1159 Status = _SEH2_GetExceptionCode();
1160 }
1161 _SEH2_END;
1162
1163 break;
1164 }
1165
1166 case TokenType:
1167 {
1168 PTOKEN_TYPE tt = (PTOKEN_TYPE)TokenInformation;
1169
1170 DPRINT("NtQueryInformationToken(TokenType)\n");
1171 RequiredLength = sizeof(TOKEN_TYPE);
1172
1173 _SEH2_TRY
1174 {
1175 if(TokenInformationLength >= RequiredLength)
1176 {
1177 *tt = Token->TokenType;
1178 }
1179 else
1180 {
1181 Status = STATUS_BUFFER_TOO_SMALL;
1182 }
1183
1184 if(ReturnLength != NULL)
1185 {
1186 *ReturnLength = RequiredLength;
1187 }
1188 }
1189 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1190 {
1191 Status = _SEH2_GetExceptionCode();
1192 }
1193 _SEH2_END;
1194
1195 break;
1196 }
1197
1198 case TokenImpersonationLevel:
1199 {
1200 PSECURITY_IMPERSONATION_LEVEL sil = (PSECURITY_IMPERSONATION_LEVEL)TokenInformation;
1201
1202 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
1203 RequiredLength = sizeof(SECURITY_IMPERSONATION_LEVEL);
1204
1205 _SEH2_TRY
1206 {
1207 if(TokenInformationLength >= RequiredLength)
1208 {
1209 *sil = Token->ImpersonationLevel;
1210 }
1211 else
1212 {
1213 Status = STATUS_BUFFER_TOO_SMALL;
1214 }
1215
1216 if(ReturnLength != NULL)
1217 {
1218 *ReturnLength = RequiredLength;
1219 }
1220 }
1221 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1222 {
1223 Status = _SEH2_GetExceptionCode();
1224 }
1225 _SEH2_END;
1226
1227 break;
1228 }
1229
1230 case TokenStatistics:
1231 {
1232 PTOKEN_STATISTICS ts = (PTOKEN_STATISTICS)TokenInformation;
1233
1234 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
1235 RequiredLength = sizeof(TOKEN_STATISTICS);
1236
1237 _SEH2_TRY
1238 {
1239 if(TokenInformationLength >= RequiredLength)
1240 {
1241 ts->TokenId = Token->TokenId;
1242 ts->AuthenticationId = Token->AuthenticationId;
1243 ts->ExpirationTime = Token->ExpirationTime;
1244 ts->TokenType = Token->TokenType;
1245 ts->ImpersonationLevel = Token->ImpersonationLevel;
1246 ts->DynamicCharged = Token->DynamicCharged;
1247 ts->DynamicAvailable = Token->DynamicAvailable;
1248 ts->GroupCount = Token->UserAndGroupCount - 1;
1249 ts->PrivilegeCount = Token->PrivilegeCount;
1250 ts->ModifiedId = Token->ModifiedId;
1251 }
1252 else
1253 {
1254 Status = STATUS_BUFFER_TOO_SMALL;
1255 }
1256
1257 if(ReturnLength != NULL)
1258 {
1259 *ReturnLength = RequiredLength;
1260 }
1261 }
1262 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1263 {
1264 Status = _SEH2_GetExceptionCode();
1265 }
1266 _SEH2_END;
1267
1268 break;
1269 }
1270
1271 case TokenOrigin:
1272 {
1273 PTOKEN_ORIGIN to = (PTOKEN_ORIGIN)TokenInformation;
1274
1275 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
1276 RequiredLength = sizeof(TOKEN_ORIGIN);
1277
1278 _SEH2_TRY
1279 {
1280 if(TokenInformationLength >= RequiredLength)
1281 {
1282 RtlCopyLuid(&to->OriginatingLogonSession,
1283 &Token->AuthenticationId);
1284 }
1285 else
1286 {
1287 Status = STATUS_BUFFER_TOO_SMALL;
1288 }
1289
1290 if(ReturnLength != NULL)
1291 {
1292 *ReturnLength = RequiredLength;
1293 }
1294 }
1295 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1296 {
1297 Status = _SEH2_GetExceptionCode();
1298 }
1299 _SEH2_END;
1300
1301 break;
1302 }
1303
1304 case TokenGroupsAndPrivileges:
1305 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1306 Status = STATUS_NOT_IMPLEMENTED;
1307 break;
1308
1309 case TokenRestrictedSids:
1310 {
1311 PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
1312
1313 DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
1314 RequiredLength = sizeof(tg->GroupCount) +
1315 RtlLengthSidAndAttributes(Token->RestrictedSidCount, Token->RestrictedSids);
1316
1317 _SEH2_TRY
1318 {
1319 if(TokenInformationLength >= RequiredLength)
1320 {
1321 ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
1322 (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES));
1323 PSID_AND_ATTRIBUTES Sid = (PSID_AND_ATTRIBUTES)((ULONG_PTR)TokenInformation + sizeof(tg->GroupCount) +
1324 (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)));
1325
1326 tg->GroupCount = Token->RestrictedSidCount;
1327 Status = RtlCopySidAndAttributesArray(Token->RestrictedSidCount,
1328 Token->RestrictedSids,
1329 SidLen,
1330 &tg->Groups[0],
1331 (PSID)Sid,
1332 &Unused.Ptr,
1333 &Unused.Ulong);
1334 }
1335 else
1336 {
1337 Status = STATUS_BUFFER_TOO_SMALL;
1338 }
1339
1340 if(ReturnLength != NULL)
1341 {
1342 *ReturnLength = RequiredLength;
1343 }
1344 }
1345 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1346 {
1347 Status = _SEH2_GetExceptionCode();
1348 }
1349 _SEH2_END;
1350
1351 break;
1352 }
1353
1354 case TokenSandBoxInert:
1355 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
1356 Status = STATUS_NOT_IMPLEMENTED;
1357 break;
1358
1359 case TokenSessionId:
1360 {
1361 ULONG SessionId = 0;
1362
1363 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
1364
1365 Status = SeQuerySessionIdToken(Token,
1366 &SessionId);
1367
1368 if(NT_SUCCESS(Status))
1369 {
1370 _SEH2_TRY
1371 {
1372 /* buffer size was already verified, no need to check here again */
1373 *(PULONG)TokenInformation = SessionId;
1374
1375 if(ReturnLength != NULL)
1376 {
1377 *ReturnLength = sizeof(ULONG);
1378 }
1379 }
1380 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1381 {
1382 Status = _SEH2_GetExceptionCode();
1383 }
1384 _SEH2_END;
1385 }
1386
1387 break;
1388 }
1389
1390 default:
1391 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
1392 Status = STATUS_INVALID_INFO_CLASS;
1393 break;
1394 }
1395
1396 ObDereferenceObject(Token);
1397 }
1398
1399 return(Status);
1400 }
1401
1402
1403 /*
1404 * NtSetTokenInformation: Partly implemented.
1405 * Unimplemented:
1406 * TokenOrigin, TokenDefaultDacl
1407 */
1408
1409 NTSTATUS NTAPI
1410 NtSetInformationToken(IN HANDLE TokenHandle,
1411 IN TOKEN_INFORMATION_CLASS TokenInformationClass,
1412 OUT PVOID TokenInformation,
1413 IN ULONG TokenInformationLength)
1414 {
1415 PTOKEN Token;
1416 KPROCESSOR_MODE PreviousMode;
1417 ULONG NeededAccess = TOKEN_ADJUST_DEFAULT;
1418 NTSTATUS Status = STATUS_SUCCESS;
1419
1420 PAGED_CODE();
1421
1422 PreviousMode = ExGetPreviousMode();
1423
1424 Status = DefaultSetInfoBufferCheck(TokenInformationClass,
1425 SeTokenInformationClass,
1426 sizeof(SeTokenInformationClass) / sizeof(SeTokenInformationClass[0]),
1427 TokenInformation,
1428 TokenInformationLength,
1429 PreviousMode);
1430
1431 if(!NT_SUCCESS(Status))
1432 {
1433 /* Invalid buffers */
1434 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status);
1435 return Status;
1436 }
1437
1438 if(TokenInformationClass == TokenSessionId)
1439 {
1440 NeededAccess |= TOKEN_ADJUST_SESSIONID;
1441 }
1442
1443 Status = ObReferenceObjectByHandle(TokenHandle,
1444 NeededAccess,
1445 SepTokenObjectType,
1446 PreviousMode,
1447 (PVOID*)&Token,
1448 NULL);
1449 if (NT_SUCCESS(Status))
1450 {
1451 switch (TokenInformationClass)
1452 {
1453 case TokenOwner:
1454 {
1455 if(TokenInformationLength >= sizeof(TOKEN_OWNER))
1456 {
1457 PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
1458 PSID InputSid = NULL;
1459
1460 _SEH2_TRY
1461 {
1462 InputSid = to->Owner;
1463 }
1464 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1465 {
1466 Status = _SEH2_GetExceptionCode();
1467 }
1468 _SEH2_END;
1469
1470 if(NT_SUCCESS(Status))
1471 {
1472 PSID CapturedSid;
1473
1474 Status = SepCaptureSid(InputSid,
1475 PreviousMode,
1476 PagedPool,
1477 FALSE,
1478 &CapturedSid);
1479 if(NT_SUCCESS(Status))
1480 {
1481 RtlCopySid(RtlLengthSid(CapturedSid),
1482 Token->UserAndGroups[Token->DefaultOwnerIndex].Sid,
1483 CapturedSid);
1484 SepReleaseSid(CapturedSid,
1485 PreviousMode,
1486 FALSE);
1487 }
1488 }
1489 }
1490 else
1491 {
1492 Status = STATUS_INFO_LENGTH_MISMATCH;
1493 }
1494 break;
1495 }
1496
1497 case TokenPrimaryGroup:
1498 {
1499 if(TokenInformationLength >= sizeof(TOKEN_PRIMARY_GROUP))
1500 {
1501 PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
1502 PSID InputSid = NULL;
1503
1504 _SEH2_TRY
1505 {
1506 InputSid = tpg->PrimaryGroup;
1507 }
1508 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1509 {
1510 Status = _SEH2_GetExceptionCode();
1511 }
1512 _SEH2_END;
1513
1514 if(NT_SUCCESS(Status))
1515 {
1516 PSID CapturedSid;
1517
1518 Status = SepCaptureSid(InputSid,
1519 PreviousMode,
1520 PagedPool,
1521 FALSE,
1522 &CapturedSid);
1523 if(NT_SUCCESS(Status))
1524 {
1525 RtlCopySid(RtlLengthSid(CapturedSid),
1526 Token->PrimaryGroup,
1527 CapturedSid);
1528 SepReleaseSid(CapturedSid,
1529 PreviousMode,
1530 FALSE);
1531 }
1532 }
1533 }
1534 else
1535 {
1536 Status = STATUS_INFO_LENGTH_MISMATCH;
1537 }
1538 break;
1539 }
1540
1541 case TokenDefaultDacl:
1542 {
1543 if(TokenInformationLength >= sizeof(TOKEN_DEFAULT_DACL))
1544 {
1545 PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
1546 PACL InputAcl = NULL;
1547
1548 _SEH2_TRY
1549 {
1550 InputAcl = tdd->DefaultDacl;
1551 }
1552 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1553 {
1554 Status = _SEH2_GetExceptionCode();
1555 }
1556 _SEH2_END;
1557
1558 if(NT_SUCCESS(Status))
1559 {
1560 if(InputAcl != NULL)
1561 {
1562 PACL CapturedAcl;
1563
1564 /* capture and copy the dacl */
1565 Status = SepCaptureAcl(InputAcl,
1566 PreviousMode,
1567 PagedPool,
1568 TRUE,
1569 &CapturedAcl);
1570 if(NT_SUCCESS(Status))
1571 {
1572 /* free the previous dacl if present */
1573 if(Token->DefaultDacl != NULL)
1574 {
1575 ExFreePool(Token->DefaultDacl);
1576 }
1577
1578 /* set the new dacl */
1579 Token->DefaultDacl = CapturedAcl;
1580 }
1581 }
1582 else
1583 {
1584 /* clear and free the default dacl if present */
1585 if(Token->DefaultDacl != NULL)
1586 {
1587 ExFreePool(Token->DefaultDacl);
1588 Token->DefaultDacl = NULL;
1589 }
1590 }
1591 }
1592 }
1593 else
1594 {
1595 Status = STATUS_INFO_LENGTH_MISMATCH;
1596 }
1597 break;
1598 }
1599
1600 case TokenSessionId:
1601 {
1602 ULONG SessionId = 0;
1603
1604 _SEH2_TRY
1605 {
1606 /* buffer size was already verified, no need to check here again */
1607 SessionId = *(PULONG)TokenInformation;
1608 }
1609 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1610 {
1611 Status = _SEH2_GetExceptionCode();
1612 }
1613 _SEH2_END;
1614
1615 if(NT_SUCCESS(Status))
1616 {
1617 if(!SeSinglePrivilegeCheck(SeTcbPrivilege,
1618 PreviousMode))
1619 {
1620 Status = STATUS_PRIVILEGE_NOT_HELD;
1621 break;
1622 }
1623
1624 Token->SessionId = SessionId;
1625 }
1626 break;
1627 }
1628
1629 default:
1630 {
1631 Status = STATUS_NOT_IMPLEMENTED;
1632 break;
1633 }
1634 }
1635
1636 ObDereferenceObject(Token);
1637 }
1638
1639 return(Status);
1640 }
1641
1642
1643 /*
1644 * @implemented
1645 *
1646 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1647 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1648 * is correct either. -Gunnar
1649 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1650 */
1651 NTSTATUS NTAPI
1652 NtDuplicateToken(IN HANDLE ExistingTokenHandle,
1653 IN ACCESS_MASK DesiredAccess,
1654 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
1655 IN BOOLEAN EffectiveOnly,
1656 IN TOKEN_TYPE TokenType,
1657 OUT PHANDLE NewTokenHandle)
1658 {
1659 KPROCESSOR_MODE PreviousMode;
1660 HANDLE hToken;
1661 PTOKEN Token;
1662 PTOKEN NewToken;
1663 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService;
1664 BOOLEAN QoSPresent;
1665 NTSTATUS Status = STATUS_SUCCESS;
1666
1667 PAGED_CODE();
1668
1669 PreviousMode = KeGetPreviousMode();
1670
1671 if(PreviousMode != KernelMode)
1672 {
1673 _SEH2_TRY
1674 {
1675 ProbeForWriteHandle(NewTokenHandle);
1676 }
1677 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1678 {
1679 Status = _SEH2_GetExceptionCode();
1680 }
1681 _SEH2_END;
1682
1683 if(!NT_SUCCESS(Status))
1684 {
1685 return Status;
1686 }
1687 }
1688
1689 Status = SepCaptureSecurityQualityOfService(ObjectAttributes,
1690 PreviousMode,
1691 PagedPool,
1692 FALSE,
1693 &CapturedSecurityQualityOfService,
1694 &QoSPresent);
1695 if(!NT_SUCCESS(Status))
1696 {
1697 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status);
1698 return Status;
1699 }
1700
1701 Status = ObReferenceObjectByHandle(ExistingTokenHandle,
1702 TOKEN_DUPLICATE,
1703 SepTokenObjectType,
1704 PreviousMode,
1705 (PVOID*)&Token,
1706 NULL);
1707 if (NT_SUCCESS(Status))
1708 {
1709 Status = SepDuplicateToken(Token,
1710 ObjectAttributes,
1711 EffectiveOnly,
1712 TokenType,
1713 (QoSPresent ? CapturedSecurityQualityOfService->ImpersonationLevel : SecurityAnonymous),
1714 PreviousMode,
1715 &NewToken);
1716
1717 ObDereferenceObject(Token);
1718
1719 if (NT_SUCCESS(Status))
1720 {
1721 Status = ObInsertObject((PVOID)NewToken,
1722 NULL,
1723 DesiredAccess,
1724 0,
1725 NULL,
1726 &hToken);
1727
1728 if (NT_SUCCESS(Status))
1729 {
1730 _SEH2_TRY
1731 {
1732 *NewTokenHandle = hToken;
1733 }
1734 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1735 {
1736 Status = _SEH2_GetExceptionCode();
1737 }
1738 _SEH2_END;
1739 }
1740 }
1741 }
1742
1743 /* free the captured structure */
1744 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
1745 PreviousMode,
1746 FALSE);
1747
1748 return Status;
1749 }
1750
1751 NTSTATUS NTAPI
1752 NtAdjustGroupsToken(IN HANDLE TokenHandle,
1753 IN BOOLEAN ResetToDefault,
1754 IN PTOKEN_GROUPS NewState,
1755 IN ULONG BufferLength,
1756 OUT PTOKEN_GROUPS PreviousState OPTIONAL,
1757 OUT PULONG ReturnLength)
1758 {
1759 UNIMPLEMENTED;
1760 return(STATUS_NOT_IMPLEMENTED);
1761 }
1762
1763 /*
1764 * @implemented
1765 */
1766 NTSTATUS NTAPI
1767 NtAdjustPrivilegesToken (IN HANDLE TokenHandle,
1768 IN BOOLEAN DisableAllPrivileges,
1769 IN PTOKEN_PRIVILEGES NewState,
1770 IN ULONG BufferLength,
1771 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL,
1772 OUT PULONG ReturnLength OPTIONAL)
1773 {
1774 // PLUID_AND_ATTRIBUTES Privileges;
1775 KPROCESSOR_MODE PreviousMode;
1776 ULONG PrivilegeCount;
1777 PTOKEN Token;
1778 // ULONG Length;
1779 ULONG i;
1780 ULONG j;
1781 ULONG k;
1782 ULONG Count;
1783 #if 0
1784 ULONG a;
1785 ULONG b;
1786 ULONG c;
1787 #endif
1788 NTSTATUS Status;
1789
1790 PAGED_CODE();
1791
1792 DPRINT ("NtAdjustPrivilegesToken() called\n");
1793
1794 // PrivilegeCount = NewState->PrivilegeCount;
1795 PreviousMode = KeGetPreviousMode ();
1796 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
1797 // PrivilegeCount,
1798 // PreviousMode,
1799 // NULL,
1800 // 0,
1801 // NonPagedPool,
1802 // 1,
1803 // &Privileges,
1804 // &Length);
1805
1806 Status = ObReferenceObjectByHandle (TokenHandle,
1807 TOKEN_ADJUST_PRIVILEGES | (PreviousState != NULL ? TOKEN_QUERY : 0),
1808 SepTokenObjectType,
1809 PreviousMode,
1810 (PVOID*)&Token,
1811 NULL);
1812 if (!NT_SUCCESS(Status))
1813 {
1814 DPRINT1 ("Failed to reference token (Status %lx)\n", Status);
1815 // SeReleaseLuidAndAttributesArray(Privileges,
1816 // PreviousMode,
1817 // 0);
1818 return Status;
1819 }
1820
1821
1822 #if 0
1823 SepAdjustPrivileges(Token,
1824 0,
1825 PreviousMode,
1826 PrivilegeCount,
1827 Privileges,
1828 PreviousState,
1829 &a,
1830 &b,
1831 &c);
1832 #endif
1833
1834 PrivilegeCount = (BufferLength - FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges)) /
1835 sizeof(LUID_AND_ATTRIBUTES);
1836
1837 if (PreviousState != NULL)
1838 PreviousState->PrivilegeCount = 0;
1839
1840 k = 0;
1841 if (DisableAllPrivileges == TRUE)
1842 {
1843 for (i = 0; i < Token->PrivilegeCount; i++)
1844 {
1845 if (Token->Privileges[i].Attributes != 0)
1846 {
1847 DPRINT ("Attributes differ\n");
1848
1849 /* Save current privilege */
1850 if (PreviousState != NULL)
1851 {
1852 if (k < PrivilegeCount)
1853 {
1854 PreviousState->PrivilegeCount++;
1855 PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
1856 PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
1857 }
1858 else
1859 {
1860 /* FIXME: Should revert all the changes, calculate how
1861 * much space would be needed, set ResultLength
1862 * accordingly and fail.
1863 */
1864 }
1865 k++;
1866 }
1867
1868 /* Update current privlege */
1869 Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
1870 }
1871 }
1872 Status = STATUS_SUCCESS;
1873 }
1874 else
1875 {
1876 Count = 0;
1877 for (i = 0; i < Token->PrivilegeCount; i++)
1878 {
1879 for (j = 0; j < NewState->PrivilegeCount; j++)
1880 {
1881 if (Token->Privileges[i].Luid.LowPart == NewState->Privileges[j].Luid.LowPart &&
1882 Token->Privileges[i].Luid.HighPart == NewState->Privileges[j].Luid.HighPart)
1883 {
1884 DPRINT ("Found privilege\n");
1885
1886 if ((Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) !=
1887 (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED))
1888 {
1889 DPRINT ("Attributes differ\n");
1890 DPRINT ("Current attributes %lx desired attributes %lx\n",
1891 Token->Privileges[i].Attributes,
1892 NewState->Privileges[j].Attributes);
1893
1894 /* Save current privilege */
1895 if (PreviousState != NULL)
1896 {
1897 if (k < PrivilegeCount)
1898 {
1899 PreviousState->PrivilegeCount++;
1900 PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
1901 PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
1902 }
1903 else
1904 {
1905 /* FIXME: Should revert all the changes, calculate how
1906 * much space would be needed, set ResultLength
1907 * accordingly and fail.
1908 */
1909 }
1910 k++;
1911 }
1912
1913 /* Update current privlege */
1914 Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
1915 Token->Privileges[i].Attributes |=
1916 (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED);
1917 DPRINT ("New attributes %lx\n",
1918 Token->Privileges[i].Attributes);
1919 }
1920 Count++;
1921 }
1922 }
1923 }
1924 Status = Count < NewState->PrivilegeCount ? STATUS_NOT_ALL_ASSIGNED : STATUS_SUCCESS;
1925 }
1926
1927 if (ReturnLength != NULL)
1928 {
1929 *ReturnLength = sizeof(TOKEN_PRIVILEGES) +
1930 (sizeof(LUID_AND_ATTRIBUTES) * (k - 1));
1931 }
1932
1933 ObDereferenceObject (Token);
1934
1935 // SeReleaseLuidAndAttributesArray(Privileges,
1936 // PreviousMode,
1937 // 0);
1938
1939 DPRINT ("NtAdjustPrivilegesToken() done\n");
1940
1941 return Status;
1942 }
1943
1944 NTSTATUS NTAPI
1945 NtCreateToken(OUT PHANDLE TokenHandle,
1946 IN ACCESS_MASK DesiredAccess,
1947 IN POBJECT_ATTRIBUTES ObjectAttributes,
1948 IN TOKEN_TYPE TokenType,
1949 IN PLUID AuthenticationId,
1950 IN PLARGE_INTEGER ExpirationTime,
1951 IN PTOKEN_USER TokenUser,
1952 IN PTOKEN_GROUPS TokenGroups,
1953 IN PTOKEN_PRIVILEGES TokenPrivileges,
1954 IN PTOKEN_OWNER TokenOwner,
1955 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup,
1956 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl,
1957 IN PTOKEN_SOURCE TokenSource)
1958 {
1959 HANDLE hToken;
1960 PTOKEN AccessToken;
1961 LUID TokenId;
1962 LUID ModifiedId;
1963 PVOID EndMem;
1964 ULONG uLength;
1965 ULONG i;
1966 KPROCESSOR_MODE PreviousMode;
1967 ULONG nTokenPrivileges = 0;
1968 LARGE_INTEGER LocalExpirationTime = {{0, 0}};
1969 NTSTATUS Status = STATUS_SUCCESS;
1970
1971 PAGED_CODE();
1972
1973 PreviousMode = ExGetPreviousMode();
1974
1975 if(PreviousMode != KernelMode)
1976 {
1977 _SEH2_TRY
1978 {
1979 ProbeForWriteHandle(TokenHandle);
1980 ProbeForRead(AuthenticationId,
1981 sizeof(LUID),
1982 sizeof(ULONG));
1983 LocalExpirationTime = ProbeForReadLargeInteger(ExpirationTime);
1984 ProbeForRead(TokenUser,
1985 sizeof(TOKEN_USER),
1986 sizeof(ULONG));
1987 ProbeForRead(TokenGroups,
1988 sizeof(TOKEN_GROUPS),
1989 sizeof(ULONG));
1990 ProbeForRead(TokenPrivileges,
1991 sizeof(TOKEN_PRIVILEGES),
1992 sizeof(ULONG));
1993 ProbeForRead(TokenOwner,
1994 sizeof(TOKEN_OWNER),
1995 sizeof(ULONG));
1996 ProbeForRead(TokenPrimaryGroup,
1997 sizeof(TOKEN_PRIMARY_GROUP),
1998 sizeof(ULONG));
1999 ProbeForRead(TokenDefaultDacl,
2000 sizeof(TOKEN_DEFAULT_DACL),
2001 sizeof(ULONG));
2002 ProbeForRead(TokenSource,
2003 sizeof(TOKEN_SOURCE),
2004 sizeof(ULONG));
2005 nTokenPrivileges = TokenPrivileges->PrivilegeCount;
2006 }
2007 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2008 {
2009 Status = _SEH2_GetExceptionCode();
2010 }
2011 _SEH2_END;
2012
2013 if(!NT_SUCCESS(Status))
2014 {
2015 return Status;
2016 }
2017 }
2018 else
2019 {
2020 nTokenPrivileges = TokenPrivileges->PrivilegeCount;
2021 LocalExpirationTime = *ExpirationTime;
2022 }
2023
2024 Status = ZwAllocateLocallyUniqueId(&TokenId);
2025 if (!NT_SUCCESS(Status))
2026 return(Status);
2027
2028 Status = ZwAllocateLocallyUniqueId(&ModifiedId);
2029 if (!NT_SUCCESS(Status))
2030 return(Status);
2031
2032 Status = ObCreateObject(PreviousMode,
2033 SepTokenObjectType,
2034 ObjectAttributes,
2035 PreviousMode,
2036 NULL,
2037 sizeof(TOKEN),
2038 0,
2039 0,
2040 (PVOID*)&AccessToken);
2041 if (!NT_SUCCESS(Status))
2042 {
2043 DPRINT1("ObCreateObject() failed (Status %lx)\n");
2044 return(Status);
2045 }
2046
2047 AccessToken->TokenLock = &SepTokenLock;
2048
2049 RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
2050 &TokenSource->SourceIdentifier);
2051 memcpy(AccessToken->TokenSource.SourceName,
2052 TokenSource->SourceName,
2053 sizeof(TokenSource->SourceName));
2054
2055 RtlCopyLuid(&AccessToken->TokenId, &TokenId);
2056 RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
2057 AccessToken->ExpirationTime = *ExpirationTime;
2058 RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
2059
2060 AccessToken->UserAndGroupCount = TokenGroups->GroupCount + 1;
2061 AccessToken->PrivilegeCount = TokenPrivileges->PrivilegeCount;
2062 AccessToken->UserAndGroups = 0;
2063 AccessToken->Privileges = 0;
2064
2065 AccessToken->TokenType = TokenType;
2066 AccessToken->ImpersonationLevel = ((PSECURITY_QUALITY_OF_SERVICE)
2067 (ObjectAttributes->SecurityQualityOfService))->ImpersonationLevel;
2068
2069 /*
2070 * Normally we would just point these members into the variable information
2071 * area; however, our ObCreateObject() call can't allocate a variable information
2072 * area, so we allocate them seperately and provide a destroy function.
2073 */
2074
2075 uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
2076 uLength += RtlLengthSid(TokenUser->User.Sid);
2077 for (i = 0; i < TokenGroups->GroupCount; i++)
2078 uLength += RtlLengthSid(TokenGroups->Groups[i].Sid);
2079
2080 AccessToken->UserAndGroups =
2081 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
2082 uLength,
2083 TAG('T', 'O', 'K', 'u'));
2084
2085 EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
2086
2087 Status = RtlCopySidAndAttributesArray(1,
2088 &TokenUser->User,
2089 uLength,
2090 AccessToken->UserAndGroups,
2091 EndMem,
2092 &EndMem,
2093 &uLength);
2094 if (NT_SUCCESS(Status))
2095 {
2096 Status = RtlCopySidAndAttributesArray(TokenGroups->GroupCount,
2097 TokenGroups->Groups,
2098 uLength,
2099 &AccessToken->UserAndGroups[1],
2100 EndMem,
2101 &EndMem,
2102 &uLength);
2103 }
2104
2105 if (NT_SUCCESS(Status))
2106 {
2107 Status = SepFindPrimaryGroupAndDefaultOwner(
2108 AccessToken,
2109 TokenPrimaryGroup->PrimaryGroup,
2110 TokenOwner->Owner);
2111 }
2112
2113 if (NT_SUCCESS(Status))
2114 {
2115 uLength = TokenPrivileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
2116 AccessToken->Privileges =
2117 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
2118 uLength,
2119 TAG('T', 'O', 'K', 'p'));
2120
2121 if (PreviousMode != KernelMode)
2122 {
2123 _SEH2_TRY
2124 {
2125 RtlCopyMemory(AccessToken->Privileges,
2126 TokenPrivileges->Privileges,
2127 nTokenPrivileges * sizeof(LUID_AND_ATTRIBUTES));
2128 }
2129 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2130 {
2131 Status = _SEH2_GetExceptionCode();
2132 }
2133 _SEH2_END;
2134 }
2135 else
2136 {
2137 RtlCopyMemory(AccessToken->Privileges,
2138 TokenPrivileges->Privileges,
2139 nTokenPrivileges * sizeof(LUID_AND_ATTRIBUTES));
2140 }
2141 }
2142
2143 if (NT_SUCCESS(Status))
2144 {
2145 AccessToken->DefaultDacl =
2146 (PACL) ExAllocatePoolWithTag(PagedPool,
2147 TokenDefaultDacl->DefaultDacl->AclSize,
2148 TAG('T', 'O', 'K', 'd'));
2149 memcpy(AccessToken->DefaultDacl,
2150 TokenDefaultDacl->DefaultDacl,
2151 TokenDefaultDacl->DefaultDacl->AclSize);
2152 }
2153
2154 Status = ObInsertObject ((PVOID)AccessToken,
2155 NULL,
2156 DesiredAccess,
2157 0,
2158 NULL,
2159 &hToken);
2160 if (!NT_SUCCESS(Status))
2161 {
2162 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status);
2163 }
2164
2165 if (NT_SUCCESS(Status))
2166 {
2167 _SEH2_TRY
2168 {
2169 *TokenHandle = hToken;
2170 }
2171 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2172 {
2173 Status = _SEH2_GetExceptionCode();
2174 }
2175 _SEH2_END;
2176 }
2177
2178 return Status;
2179 }
2180
2181 /*
2182 * @implemented
2183 */
2184 NTSTATUS
2185 NTAPI
2186 NtOpenThreadTokenEx(IN HANDLE ThreadHandle,
2187 IN ACCESS_MASK DesiredAccess,
2188 IN BOOLEAN OpenAsSelf,
2189 IN ULONG HandleAttributes,
2190 OUT PHANDLE TokenHandle)
2191 {
2192 PETHREAD Thread;
2193 HANDLE hToken;
2194 PTOKEN Token, NewToken, PrimaryToken;
2195 BOOLEAN CopyOnOpen, EffectiveOnly;
2196 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
2197 SE_IMPERSONATION_STATE ImpersonationState;
2198 OBJECT_ATTRIBUTES ObjectAttributes;
2199 SECURITY_DESCRIPTOR SecurityDescriptor;
2200 PACL Dacl = NULL;
2201 KPROCESSOR_MODE PreviousMode;
2202 NTSTATUS Status = STATUS_SUCCESS;
2203
2204 PAGED_CODE();
2205
2206 PreviousMode = ExGetPreviousMode();
2207
2208 if(PreviousMode != KernelMode)
2209 {
2210 _SEH2_TRY
2211 {
2212 ProbeForWriteHandle(TokenHandle);
2213 }
2214 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2215 {
2216 Status = _SEH2_GetExceptionCode();
2217 }
2218 _SEH2_END;
2219
2220 if(!NT_SUCCESS(Status))
2221 {
2222 return Status;
2223 }
2224 }
2225
2226 /*
2227 * At first open the thread token for information access and verify
2228 * that the token associated with thread is valid.
2229 */
2230
2231 Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_QUERY_INFORMATION,
2232 PsThreadType, PreviousMode, (PVOID*)&Thread,
2233 NULL);
2234 if (!NT_SUCCESS(Status))
2235 {
2236 return Status;
2237 }
2238
2239 Token = PsReferenceImpersonationToken(Thread, &CopyOnOpen, &EffectiveOnly,
2240 &ImpersonationLevel);
2241 if (Token == NULL)
2242 {
2243 ObfDereferenceObject(Thread);
2244 return STATUS_NO_TOKEN;
2245 }
2246
2247 ObDereferenceObject(Thread);
2248
2249 if (ImpersonationLevel == SecurityAnonymous)
2250 {
2251 ObfDereferenceObject(Token);
2252 return STATUS_CANT_OPEN_ANONYMOUS;
2253 }
2254
2255 /*
2256 * Revert to self if OpenAsSelf is specified.
2257 */
2258
2259 if (OpenAsSelf)
2260 {
2261 PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState);
2262 }
2263
2264 if (CopyOnOpen)
2265 {
2266 Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_ALL_ACCESS,
2267 PsThreadType, PreviousMode,
2268 (PVOID*)&Thread, NULL);
2269 if (!NT_SUCCESS(Status))
2270 {
2271 ObfDereferenceObject(Token);
2272 if (OpenAsSelf)
2273 {
2274 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
2275 }
2276 return Status;
2277 }
2278
2279 PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
2280 Status = SepCreateImpersonationTokenDacl(Token, PrimaryToken, &Dacl);
2281 ASSERT(FALSE);
2282 ObfDereferenceObject(PrimaryToken);
2283 ObfDereferenceObject(Thread);
2284 if (!NT_SUCCESS(Status))
2285 {
2286 ObfDereferenceObject(Token);
2287 if (OpenAsSelf)
2288 {
2289 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
2290 }
2291 return Status;
2292 }
2293
2294 RtlCreateSecurityDescriptor(&SecurityDescriptor,
2295 SECURITY_DESCRIPTOR_REVISION);
2296 RtlSetDaclSecurityDescriptor(&SecurityDescriptor, TRUE, Dacl,
2297 FALSE);
2298
2299 InitializeObjectAttributes(&ObjectAttributes, NULL, HandleAttributes,
2300 NULL, &SecurityDescriptor);
2301
2302 Status = SepDuplicateToken(Token, &ObjectAttributes, EffectiveOnly,
2303 TokenImpersonation, ImpersonationLevel,
2304 KernelMode, &NewToken);
2305 ExFreePool(Dacl);
2306 if (!NT_SUCCESS(Status))
2307 {
2308 ObfDereferenceObject(Token);
2309 if (OpenAsSelf)
2310 {
2311 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
2312 }
2313 return Status;
2314 }
2315
2316 Status = ObInsertObject(NewToken, NULL, DesiredAccess, 0, NULL,
2317 &hToken);
2318
2319 }
2320 else
2321 {
2322 Status = ObOpenObjectByPointer(Token, HandleAttributes,
2323 NULL, DesiredAccess, SepTokenObjectType,
2324 PreviousMode, &hToken);
2325 }
2326
2327 ObfDereferenceObject(Token);
2328
2329 if (OpenAsSelf)
2330 {
2331 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
2332 }
2333
2334 if(NT_SUCCESS(Status))
2335 {
2336 _SEH2_TRY
2337 {
2338 *TokenHandle = hToken;
2339 }
2340 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2341 {
2342 Status = _SEH2_GetExceptionCode();
2343 }
2344 _SEH2_END;
2345 }
2346
2347 return Status;
2348 }
2349
2350 /*
2351 * @implemented
2352 */
2353 NTSTATUS NTAPI
2354 NtOpenThreadToken(IN HANDLE ThreadHandle,
2355 IN ACCESS_MASK DesiredAccess,
2356 IN BOOLEAN OpenAsSelf,
2357 OUT PHANDLE TokenHandle)
2358 {
2359 return NtOpenThreadTokenEx(ThreadHandle, DesiredAccess, OpenAsSelf, 0,
2360 TokenHandle);
2361 }
2362
2363
2364
2365 /*
2366 * @unimplemented
2367 */
2368 NTSTATUS
2369 NTAPI
2370 NtCompareTokens(IN HANDLE FirstTokenHandle,
2371 IN HANDLE SecondTokenHandle,
2372 OUT PBOOLEAN Equal)
2373 {
2374 KPROCESSOR_MODE PreviousMode;
2375 PTOKEN FirstToken, SecondToken;
2376 BOOLEAN IsEqual;
2377 NTSTATUS Status = STATUS_SUCCESS;
2378
2379 PAGED_CODE();
2380
2381 PreviousMode = ExGetPreviousMode();
2382
2383 if (PreviousMode != KernelMode)
2384 {
2385 _SEH2_TRY
2386 {
2387 ProbeForWriteBoolean(Equal);
2388 }
2389 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2390 {
2391 Status = _SEH2_GetExceptionCode();
2392 }
2393 _SEH2_END;
2394
2395 if (!NT_SUCCESS(Status))
2396 return Status;
2397 }
2398
2399 Status = ObReferenceObjectByHandle(FirstTokenHandle,
2400 TOKEN_QUERY,
2401 SepTokenObjectType,
2402 PreviousMode,
2403 (PVOID*)&FirstToken,
2404 NULL);
2405 if (!NT_SUCCESS(Status))
2406 return Status;
2407
2408 Status = ObReferenceObjectByHandle(SecondTokenHandle,
2409 TOKEN_QUERY,
2410 SepTokenObjectType,
2411 PreviousMode,
2412 (PVOID*)&SecondToken,
2413 NULL);
2414 if (!NT_SUCCESS(Status))
2415 {
2416 ObDereferenceObject(FirstToken);
2417 return Status;
2418 }
2419
2420 if (FirstToken != SecondToken)
2421 {
2422 Status = SepCompareTokens(FirstToken,
2423 SecondToken,
2424 &IsEqual);
2425 }
2426 else
2427 IsEqual = TRUE;
2428
2429 ObDereferenceObject(FirstToken);
2430 ObDereferenceObject(SecondToken);
2431
2432 if (NT_SUCCESS(Status))
2433 {
2434 _SEH2_TRY
2435 {
2436 *Equal = IsEqual;
2437 }
2438 _SEH2_EXCEPT(ExSystemExceptionFilter())
2439 {
2440 Status = _SEH2_GetExceptionCode();
2441 }
2442 _SEH2_END;
2443 }
2444
2445 return Status;
2446 }
2447
2448 NTSTATUS
2449 NTAPI
2450 NtFilterToken(IN HANDLE ExistingTokenHandle,
2451 IN ULONG Flags,
2452 IN PTOKEN_GROUPS SidsToDisable OPTIONAL,
2453 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL,
2454 IN PTOKEN_GROUPS RestrictedSids OPTIONAL,
2455 OUT PHANDLE NewTokenHandle)
2456 {
2457 UNIMPLEMENTED;
2458 return STATUS_NOT_IMPLEMENTED;
2459 }
2460
2461 /*
2462 * @unimplemented
2463 */
2464 NTSTATUS
2465 NTAPI
2466 NtImpersonateAnonymousToken(IN HANDLE Thread)
2467 {
2468 UNIMPLEMENTED;
2469 return STATUS_NOT_IMPLEMENTED;
2470 }
2471
2472 /* EOF */