Silence compiler warnings (3/11).
[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 PreviousMode);
875
876 if(!NT_SUCCESS(Status))
877 {
878 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status);
879 return Status;
880 }
881
882 Status = ObReferenceObjectByHandle(TokenHandle,
883 (TokenInformationClass == TokenSource) ? TOKEN_QUERY_SOURCE : TOKEN_QUERY,
884 SepTokenObjectType,
885 PreviousMode,
886 (PVOID*)&Token,
887 NULL);
888 if (NT_SUCCESS(Status))
889 {
890 switch (TokenInformationClass)
891 {
892 case TokenUser:
893 {
894 PTOKEN_USER tu = (PTOKEN_USER)TokenInformation;
895
896 DPRINT("NtQueryInformationToken(TokenUser)\n");
897 RequiredLength = sizeof(TOKEN_USER) +
898 RtlLengthSid(Token->UserAndGroups[0].Sid);
899
900 _SEH2_TRY
901 {
902 if(TokenInformationLength >= RequiredLength)
903 {
904 Status = RtlCopySidAndAttributesArray(1,
905 &Token->UserAndGroups[0],
906 RequiredLength - sizeof(TOKEN_USER),
907 &tu->User,
908 (PSID)(tu + 1),
909 &Unused.Ptr,
910 &Unused.Ulong);
911 }
912 else
913 {
914 Status = STATUS_BUFFER_TOO_SMALL;
915 }
916
917 if(ReturnLength != NULL)
918 {
919 *ReturnLength = RequiredLength;
920 }
921 }
922 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
923 {
924 Status = _SEH2_GetExceptionCode();
925 }
926 _SEH2_END;
927
928 break;
929 }
930
931 case TokenGroups:
932 {
933 PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
934
935 DPRINT("NtQueryInformationToken(TokenGroups)\n");
936 RequiredLength = sizeof(tg->GroupCount) +
937 RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]);
938
939 _SEH2_TRY
940 {
941 if(TokenInformationLength >= RequiredLength)
942 {
943 ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
944 ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES));
945 PSID_AND_ATTRIBUTES Sid = (PSID_AND_ATTRIBUTES)((ULONG_PTR)TokenInformation + sizeof(tg->GroupCount) +
946 ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)));
947
948 tg->GroupCount = Token->UserAndGroupCount - 1;
949 Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
950 &Token->UserAndGroups[1],
951 SidLen,
952 &tg->Groups[0],
953 (PSID)Sid,
954 &Unused.Ptr,
955 &Unused.Ulong);
956 }
957 else
958 {
959 Status = STATUS_BUFFER_TOO_SMALL;
960 }
961
962 if(ReturnLength != NULL)
963 {
964 *ReturnLength = RequiredLength;
965 }
966 }
967 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
968 {
969 Status = _SEH2_GetExceptionCode();
970 }
971 _SEH2_END;
972
973 break;
974 }
975
976 case TokenPrivileges:
977 {
978 PTOKEN_PRIVILEGES tp = (PTOKEN_PRIVILEGES)TokenInformation;
979
980 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
981 RequiredLength = sizeof(tp->PrivilegeCount) +
982 (Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
983
984 _SEH2_TRY
985 {
986 if(TokenInformationLength >= RequiredLength)
987 {
988 tp->PrivilegeCount = Token->PrivilegeCount;
989 RtlCopyLuidAndAttributesArray(Token->PrivilegeCount,
990 Token->Privileges,
991 &tp->Privileges[0]);
992 }
993 else
994 {
995 Status = STATUS_BUFFER_TOO_SMALL;
996 }
997
998 if(ReturnLength != NULL)
999 {
1000 *ReturnLength = RequiredLength;
1001 }
1002 }
1003 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1004 {
1005 Status = _SEH2_GetExceptionCode();
1006 }
1007 _SEH2_END;
1008
1009 break;
1010 }
1011
1012 case TokenOwner:
1013 {
1014 ULONG SidLen;
1015 PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
1016
1017 DPRINT("NtQueryInformationToken(TokenOwner)\n");
1018 SidLen = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
1019 RequiredLength = sizeof(TOKEN_OWNER) + SidLen;
1020
1021 _SEH2_TRY
1022 {
1023 if(TokenInformationLength >= RequiredLength)
1024 {
1025 to->Owner = (PSID)(to + 1);
1026 Status = RtlCopySid(SidLen,
1027 to->Owner,
1028 Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
1029 }
1030 else
1031 {
1032 Status = STATUS_BUFFER_TOO_SMALL;
1033 }
1034
1035 if(ReturnLength != NULL)
1036 {
1037 *ReturnLength = RequiredLength;
1038 }
1039 }
1040 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1041 {
1042 Status = _SEH2_GetExceptionCode();
1043 }
1044 _SEH2_END;
1045
1046 break;
1047 }
1048
1049 case TokenPrimaryGroup:
1050 {
1051 ULONG SidLen;
1052 PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
1053
1054 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
1055 SidLen = RtlLengthSid(Token->PrimaryGroup);
1056 RequiredLength = sizeof(TOKEN_PRIMARY_GROUP) + SidLen;
1057
1058 _SEH2_TRY
1059 {
1060 if(TokenInformationLength >= RequiredLength)
1061 {
1062 tpg->PrimaryGroup = (PSID)(tpg + 1);
1063 Status = RtlCopySid(SidLen,
1064 tpg->PrimaryGroup,
1065 Token->PrimaryGroup);
1066 }
1067 else
1068 {
1069 Status = STATUS_BUFFER_TOO_SMALL;
1070 }
1071
1072 if(ReturnLength != NULL)
1073 {
1074 *ReturnLength = RequiredLength;
1075 }
1076 }
1077 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1078 {
1079 Status = _SEH2_GetExceptionCode();
1080 }
1081 _SEH2_END;
1082
1083 break;
1084 }
1085
1086 case TokenDefaultDacl:
1087 {
1088 PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
1089
1090 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
1091 RequiredLength = sizeof(TOKEN_DEFAULT_DACL);
1092
1093 if(Token->DefaultDacl != NULL)
1094 {
1095 RequiredLength += Token->DefaultDacl->AclSize;
1096 }
1097
1098 _SEH2_TRY
1099 {
1100 if(TokenInformationLength >= RequiredLength)
1101 {
1102 if(Token->DefaultDacl != NULL)
1103 {
1104 tdd->DefaultDacl = (PACL)(tdd + 1);
1105 RtlCopyMemory(tdd->DefaultDacl,
1106 Token->DefaultDacl,
1107 Token->DefaultDacl->AclSize);
1108 }
1109 else
1110 {
1111 tdd->DefaultDacl = NULL;
1112 }
1113 }
1114 else
1115 {
1116 Status = STATUS_BUFFER_TOO_SMALL;
1117 }
1118
1119 if(ReturnLength != NULL)
1120 {
1121 *ReturnLength = RequiredLength;
1122 }
1123 }
1124 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1125 {
1126 Status = _SEH2_GetExceptionCode();
1127 }
1128 _SEH2_END;
1129
1130 break;
1131 }
1132
1133 case TokenSource:
1134 {
1135 PTOKEN_SOURCE ts = (PTOKEN_SOURCE)TokenInformation;
1136
1137 DPRINT("NtQueryInformationToken(TokenSource)\n");
1138 RequiredLength = sizeof(TOKEN_SOURCE);
1139
1140 _SEH2_TRY
1141 {
1142 if(TokenInformationLength >= RequiredLength)
1143 {
1144 *ts = Token->TokenSource;
1145 }
1146 else
1147 {
1148 Status = STATUS_BUFFER_TOO_SMALL;
1149 }
1150
1151 if(ReturnLength != NULL)
1152 {
1153 *ReturnLength = RequiredLength;
1154 }
1155 }
1156 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1157 {
1158 Status = _SEH2_GetExceptionCode();
1159 }
1160 _SEH2_END;
1161
1162 break;
1163 }
1164
1165 case TokenType:
1166 {
1167 PTOKEN_TYPE tt = (PTOKEN_TYPE)TokenInformation;
1168
1169 DPRINT("NtQueryInformationToken(TokenType)\n");
1170 RequiredLength = sizeof(TOKEN_TYPE);
1171
1172 _SEH2_TRY
1173 {
1174 if(TokenInformationLength >= RequiredLength)
1175 {
1176 *tt = Token->TokenType;
1177 }
1178 else
1179 {
1180 Status = STATUS_BUFFER_TOO_SMALL;
1181 }
1182
1183 if(ReturnLength != NULL)
1184 {
1185 *ReturnLength = RequiredLength;
1186 }
1187 }
1188 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1189 {
1190 Status = _SEH2_GetExceptionCode();
1191 }
1192 _SEH2_END;
1193
1194 break;
1195 }
1196
1197 case TokenImpersonationLevel:
1198 {
1199 PSECURITY_IMPERSONATION_LEVEL sil = (PSECURITY_IMPERSONATION_LEVEL)TokenInformation;
1200
1201 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
1202 RequiredLength = sizeof(SECURITY_IMPERSONATION_LEVEL);
1203
1204 _SEH2_TRY
1205 {
1206 if(TokenInformationLength >= RequiredLength)
1207 {
1208 *sil = Token->ImpersonationLevel;
1209 }
1210 else
1211 {
1212 Status = STATUS_BUFFER_TOO_SMALL;
1213 }
1214
1215 if(ReturnLength != NULL)
1216 {
1217 *ReturnLength = RequiredLength;
1218 }
1219 }
1220 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1221 {
1222 Status = _SEH2_GetExceptionCode();
1223 }
1224 _SEH2_END;
1225
1226 break;
1227 }
1228
1229 case TokenStatistics:
1230 {
1231 PTOKEN_STATISTICS ts = (PTOKEN_STATISTICS)TokenInformation;
1232
1233 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
1234 RequiredLength = sizeof(TOKEN_STATISTICS);
1235
1236 _SEH2_TRY
1237 {
1238 if(TokenInformationLength >= RequiredLength)
1239 {
1240 ts->TokenId = Token->TokenId;
1241 ts->AuthenticationId = Token->AuthenticationId;
1242 ts->ExpirationTime = Token->ExpirationTime;
1243 ts->TokenType = Token->TokenType;
1244 ts->ImpersonationLevel = Token->ImpersonationLevel;
1245 ts->DynamicCharged = Token->DynamicCharged;
1246 ts->DynamicAvailable = Token->DynamicAvailable;
1247 ts->GroupCount = Token->UserAndGroupCount - 1;
1248 ts->PrivilegeCount = Token->PrivilegeCount;
1249 ts->ModifiedId = Token->ModifiedId;
1250 }
1251 else
1252 {
1253 Status = STATUS_BUFFER_TOO_SMALL;
1254 }
1255
1256 if(ReturnLength != NULL)
1257 {
1258 *ReturnLength = RequiredLength;
1259 }
1260 }
1261 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1262 {
1263 Status = _SEH2_GetExceptionCode();
1264 }
1265 _SEH2_END;
1266
1267 break;
1268 }
1269
1270 case TokenOrigin:
1271 {
1272 PTOKEN_ORIGIN to = (PTOKEN_ORIGIN)TokenInformation;
1273
1274 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
1275 RequiredLength = sizeof(TOKEN_ORIGIN);
1276
1277 _SEH2_TRY
1278 {
1279 if(TokenInformationLength >= RequiredLength)
1280 {
1281 RtlCopyLuid(&to->OriginatingLogonSession,
1282 &Token->AuthenticationId);
1283 }
1284 else
1285 {
1286 Status = STATUS_BUFFER_TOO_SMALL;
1287 }
1288
1289 if(ReturnLength != NULL)
1290 {
1291 *ReturnLength = RequiredLength;
1292 }
1293 }
1294 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1295 {
1296 Status = _SEH2_GetExceptionCode();
1297 }
1298 _SEH2_END;
1299
1300 break;
1301 }
1302
1303 case TokenGroupsAndPrivileges:
1304 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1305 Status = STATUS_NOT_IMPLEMENTED;
1306 break;
1307
1308 case TokenRestrictedSids:
1309 {
1310 PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
1311
1312 DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
1313 RequiredLength = sizeof(tg->GroupCount) +
1314 RtlLengthSidAndAttributes(Token->RestrictedSidCount, Token->RestrictedSids);
1315
1316 _SEH2_TRY
1317 {
1318 if(TokenInformationLength >= RequiredLength)
1319 {
1320 ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
1321 (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES));
1322 PSID_AND_ATTRIBUTES Sid = (PSID_AND_ATTRIBUTES)((ULONG_PTR)TokenInformation + sizeof(tg->GroupCount) +
1323 (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)));
1324
1325 tg->GroupCount = Token->RestrictedSidCount;
1326 Status = RtlCopySidAndAttributesArray(Token->RestrictedSidCount,
1327 Token->RestrictedSids,
1328 SidLen,
1329 &tg->Groups[0],
1330 (PSID)Sid,
1331 &Unused.Ptr,
1332 &Unused.Ulong);
1333 }
1334 else
1335 {
1336 Status = STATUS_BUFFER_TOO_SMALL;
1337 }
1338
1339 if(ReturnLength != NULL)
1340 {
1341 *ReturnLength = RequiredLength;
1342 }
1343 }
1344 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1345 {
1346 Status = _SEH2_GetExceptionCode();
1347 }
1348 _SEH2_END;
1349
1350 break;
1351 }
1352
1353 case TokenSandBoxInert:
1354 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
1355 Status = STATUS_NOT_IMPLEMENTED;
1356 break;
1357
1358 case TokenSessionId:
1359 {
1360 ULONG SessionId = 0;
1361
1362 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
1363
1364 Status = SeQuerySessionIdToken(Token,
1365 &SessionId);
1366
1367 if(NT_SUCCESS(Status))
1368 {
1369 _SEH2_TRY
1370 {
1371 /* buffer size was already verified, no need to check here again */
1372 *(PULONG)TokenInformation = SessionId;
1373
1374 if(ReturnLength != NULL)
1375 {
1376 *ReturnLength = sizeof(ULONG);
1377 }
1378 }
1379 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1380 {
1381 Status = _SEH2_GetExceptionCode();
1382 }
1383 _SEH2_END;
1384 }
1385
1386 break;
1387 }
1388
1389 default:
1390 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
1391 Status = STATUS_INVALID_INFO_CLASS;
1392 break;
1393 }
1394
1395 ObDereferenceObject(Token);
1396 }
1397
1398 return(Status);
1399 }
1400
1401
1402 /*
1403 * NtSetTokenInformation: Partly implemented.
1404 * Unimplemented:
1405 * TokenOrigin, TokenDefaultDacl
1406 */
1407
1408 NTSTATUS NTAPI
1409 NtSetInformationToken(IN HANDLE TokenHandle,
1410 IN TOKEN_INFORMATION_CLASS TokenInformationClass,
1411 OUT PVOID TokenInformation,
1412 IN ULONG TokenInformationLength)
1413 {
1414 PTOKEN Token;
1415 KPROCESSOR_MODE PreviousMode;
1416 ULONG NeededAccess = TOKEN_ADJUST_DEFAULT;
1417 NTSTATUS Status = STATUS_SUCCESS;
1418
1419 PAGED_CODE();
1420
1421 PreviousMode = ExGetPreviousMode();
1422
1423 Status = DefaultSetInfoBufferCheck(TokenInformationClass,
1424 SeTokenInformationClass,
1425 sizeof(SeTokenInformationClass) / sizeof(SeTokenInformationClass[0]),
1426 TokenInformation,
1427 TokenInformationLength,
1428 PreviousMode);
1429
1430 if(!NT_SUCCESS(Status))
1431 {
1432 /* Invalid buffers */
1433 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status);
1434 return Status;
1435 }
1436
1437 if(TokenInformationClass == TokenSessionId)
1438 {
1439 NeededAccess |= TOKEN_ADJUST_SESSIONID;
1440 }
1441
1442 Status = ObReferenceObjectByHandle(TokenHandle,
1443 NeededAccess,
1444 SepTokenObjectType,
1445 PreviousMode,
1446 (PVOID*)&Token,
1447 NULL);
1448 if (NT_SUCCESS(Status))
1449 {
1450 switch (TokenInformationClass)
1451 {
1452 case TokenOwner:
1453 {
1454 if(TokenInformationLength >= sizeof(TOKEN_OWNER))
1455 {
1456 PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
1457 PSID InputSid = NULL;
1458
1459 _SEH2_TRY
1460 {
1461 InputSid = to->Owner;
1462 }
1463 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1464 {
1465 Status = _SEH2_GetExceptionCode();
1466 }
1467 _SEH2_END;
1468
1469 if(NT_SUCCESS(Status))
1470 {
1471 PSID CapturedSid;
1472
1473 Status = SepCaptureSid(InputSid,
1474 PreviousMode,
1475 PagedPool,
1476 FALSE,
1477 &CapturedSid);
1478 if(NT_SUCCESS(Status))
1479 {
1480 RtlCopySid(RtlLengthSid(CapturedSid),
1481 Token->UserAndGroups[Token->DefaultOwnerIndex].Sid,
1482 CapturedSid);
1483 SepReleaseSid(CapturedSid,
1484 PreviousMode,
1485 FALSE);
1486 }
1487 }
1488 }
1489 else
1490 {
1491 Status = STATUS_INFO_LENGTH_MISMATCH;
1492 }
1493 break;
1494 }
1495
1496 case TokenPrimaryGroup:
1497 {
1498 if(TokenInformationLength >= sizeof(TOKEN_PRIMARY_GROUP))
1499 {
1500 PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
1501 PSID InputSid = NULL;
1502
1503 _SEH2_TRY
1504 {
1505 InputSid = tpg->PrimaryGroup;
1506 }
1507 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1508 {
1509 Status = _SEH2_GetExceptionCode();
1510 }
1511 _SEH2_END;
1512
1513 if(NT_SUCCESS(Status))
1514 {
1515 PSID CapturedSid;
1516
1517 Status = SepCaptureSid(InputSid,
1518 PreviousMode,
1519 PagedPool,
1520 FALSE,
1521 &CapturedSid);
1522 if(NT_SUCCESS(Status))
1523 {
1524 RtlCopySid(RtlLengthSid(CapturedSid),
1525 Token->PrimaryGroup,
1526 CapturedSid);
1527 SepReleaseSid(CapturedSid,
1528 PreviousMode,
1529 FALSE);
1530 }
1531 }
1532 }
1533 else
1534 {
1535 Status = STATUS_INFO_LENGTH_MISMATCH;
1536 }
1537 break;
1538 }
1539
1540 case TokenDefaultDacl:
1541 {
1542 if(TokenInformationLength >= sizeof(TOKEN_DEFAULT_DACL))
1543 {
1544 PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
1545 PACL InputAcl = NULL;
1546
1547 _SEH2_TRY
1548 {
1549 InputAcl = tdd->DefaultDacl;
1550 }
1551 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1552 {
1553 Status = _SEH2_GetExceptionCode();
1554 }
1555 _SEH2_END;
1556
1557 if(NT_SUCCESS(Status))
1558 {
1559 if(InputAcl != NULL)
1560 {
1561 PACL CapturedAcl;
1562
1563 /* capture and copy the dacl */
1564 Status = SepCaptureAcl(InputAcl,
1565 PreviousMode,
1566 PagedPool,
1567 TRUE,
1568 &CapturedAcl);
1569 if(NT_SUCCESS(Status))
1570 {
1571 /* free the previous dacl if present */
1572 if(Token->DefaultDacl != NULL)
1573 {
1574 ExFreePool(Token->DefaultDacl);
1575 }
1576
1577 /* set the new dacl */
1578 Token->DefaultDacl = CapturedAcl;
1579 }
1580 }
1581 else
1582 {
1583 /* clear and free the default dacl if present */
1584 if(Token->DefaultDacl != NULL)
1585 {
1586 ExFreePool(Token->DefaultDacl);
1587 Token->DefaultDacl = NULL;
1588 }
1589 }
1590 }
1591 }
1592 else
1593 {
1594 Status = STATUS_INFO_LENGTH_MISMATCH;
1595 }
1596 break;
1597 }
1598
1599 case TokenSessionId:
1600 {
1601 ULONG SessionId = 0;
1602
1603 _SEH2_TRY
1604 {
1605 /* buffer size was already verified, no need to check here again */
1606 SessionId = *(PULONG)TokenInformation;
1607 }
1608 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1609 {
1610 Status = _SEH2_GetExceptionCode();
1611 }
1612 _SEH2_END;
1613
1614 if(NT_SUCCESS(Status))
1615 {
1616 if(!SeSinglePrivilegeCheck(SeTcbPrivilege,
1617 PreviousMode))
1618 {
1619 Status = STATUS_PRIVILEGE_NOT_HELD;
1620 break;
1621 }
1622
1623 Token->SessionId = SessionId;
1624 }
1625 break;
1626 }
1627
1628 default:
1629 {
1630 Status = STATUS_NOT_IMPLEMENTED;
1631 break;
1632 }
1633 }
1634
1635 ObDereferenceObject(Token);
1636 }
1637
1638 return(Status);
1639 }
1640
1641
1642 /*
1643 * @implemented
1644 *
1645 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1646 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1647 * is correct either. -Gunnar
1648 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1649 */
1650 NTSTATUS NTAPI
1651 NtDuplicateToken(IN HANDLE ExistingTokenHandle,
1652 IN ACCESS_MASK DesiredAccess,
1653 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
1654 IN BOOLEAN EffectiveOnly,
1655 IN TOKEN_TYPE TokenType,
1656 OUT PHANDLE NewTokenHandle)
1657 {
1658 KPROCESSOR_MODE PreviousMode;
1659 HANDLE hToken;
1660 PTOKEN Token;
1661 PTOKEN NewToken;
1662 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService;
1663 BOOLEAN QoSPresent;
1664 NTSTATUS Status = STATUS_SUCCESS;
1665
1666 PAGED_CODE();
1667
1668 PreviousMode = KeGetPreviousMode();
1669
1670 if(PreviousMode != KernelMode)
1671 {
1672 _SEH2_TRY
1673 {
1674 ProbeForWriteHandle(NewTokenHandle);
1675 }
1676 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1677 {
1678 Status = _SEH2_GetExceptionCode();
1679 }
1680 _SEH2_END;
1681
1682 if(!NT_SUCCESS(Status))
1683 {
1684 return Status;
1685 }
1686 }
1687
1688 Status = SepCaptureSecurityQualityOfService(ObjectAttributes,
1689 PreviousMode,
1690 PagedPool,
1691 FALSE,
1692 &CapturedSecurityQualityOfService,
1693 &QoSPresent);
1694 if(!NT_SUCCESS(Status))
1695 {
1696 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status);
1697 return Status;
1698 }
1699
1700 Status = ObReferenceObjectByHandle(ExistingTokenHandle,
1701 TOKEN_DUPLICATE,
1702 SepTokenObjectType,
1703 PreviousMode,
1704 (PVOID*)&Token,
1705 NULL);
1706 if (NT_SUCCESS(Status))
1707 {
1708 Status = SepDuplicateToken(Token,
1709 ObjectAttributes,
1710 EffectiveOnly,
1711 TokenType,
1712 (QoSPresent ? CapturedSecurityQualityOfService->ImpersonationLevel : SecurityAnonymous),
1713 PreviousMode,
1714 &NewToken);
1715
1716 ObDereferenceObject(Token);
1717
1718 if (NT_SUCCESS(Status))
1719 {
1720 Status = ObInsertObject((PVOID)NewToken,
1721 NULL,
1722 DesiredAccess,
1723 0,
1724 NULL,
1725 &hToken);
1726
1727 if (NT_SUCCESS(Status))
1728 {
1729 _SEH2_TRY
1730 {
1731 *NewTokenHandle = hToken;
1732 }
1733 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1734 {
1735 Status = _SEH2_GetExceptionCode();
1736 }
1737 _SEH2_END;
1738 }
1739 }
1740 }
1741
1742 /* free the captured structure */
1743 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
1744 PreviousMode,
1745 FALSE);
1746
1747 return Status;
1748 }
1749
1750 NTSTATUS NTAPI
1751 NtAdjustGroupsToken(IN HANDLE TokenHandle,
1752 IN BOOLEAN ResetToDefault,
1753 IN PTOKEN_GROUPS NewState,
1754 IN ULONG BufferLength,
1755 OUT PTOKEN_GROUPS PreviousState OPTIONAL,
1756 OUT PULONG ReturnLength)
1757 {
1758 UNIMPLEMENTED;
1759 return(STATUS_NOT_IMPLEMENTED);
1760 }
1761
1762 /*
1763 * @implemented
1764 */
1765 NTSTATUS NTAPI
1766 NtAdjustPrivilegesToken (IN HANDLE TokenHandle,
1767 IN BOOLEAN DisableAllPrivileges,
1768 IN PTOKEN_PRIVILEGES NewState,
1769 IN ULONG BufferLength,
1770 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL,
1771 OUT PULONG ReturnLength OPTIONAL)
1772 {
1773 // PLUID_AND_ATTRIBUTES Privileges;
1774 KPROCESSOR_MODE PreviousMode;
1775 ULONG PrivilegeCount;
1776 PTOKEN Token;
1777 // ULONG Length;
1778 ULONG i;
1779 ULONG j;
1780 ULONG k;
1781 ULONG Count;
1782 #if 0
1783 ULONG a;
1784 ULONG b;
1785 ULONG c;
1786 #endif
1787 NTSTATUS Status;
1788
1789 PAGED_CODE();
1790
1791 DPRINT ("NtAdjustPrivilegesToken() called\n");
1792
1793 // PrivilegeCount = NewState->PrivilegeCount;
1794 PreviousMode = KeGetPreviousMode ();
1795 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
1796 // PrivilegeCount,
1797 // PreviousMode,
1798 // NULL,
1799 // 0,
1800 // NonPagedPool,
1801 // 1,
1802 // &Privileges,
1803 // &Length);
1804
1805 Status = ObReferenceObjectByHandle (TokenHandle,
1806 TOKEN_ADJUST_PRIVILEGES | (PreviousState != NULL ? TOKEN_QUERY : 0),
1807 SepTokenObjectType,
1808 PreviousMode,
1809 (PVOID*)&Token,
1810 NULL);
1811 if (!NT_SUCCESS(Status))
1812 {
1813 DPRINT1 ("Failed to reference token (Status %lx)\n", Status);
1814 // SeReleaseLuidAndAttributesArray(Privileges,
1815 // PreviousMode,
1816 // 0);
1817 return Status;
1818 }
1819
1820
1821 #if 0
1822 SepAdjustPrivileges(Token,
1823 0,
1824 PreviousMode,
1825 PrivilegeCount,
1826 Privileges,
1827 PreviousState,
1828 &a,
1829 &b,
1830 &c);
1831 #endif
1832
1833 PrivilegeCount = (BufferLength - FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges)) /
1834 sizeof(LUID_AND_ATTRIBUTES);
1835
1836 if (PreviousState != NULL)
1837 PreviousState->PrivilegeCount = 0;
1838
1839 k = 0;
1840 if (DisableAllPrivileges == TRUE)
1841 {
1842 for (i = 0; i < Token->PrivilegeCount; i++)
1843 {
1844 if (Token->Privileges[i].Attributes != 0)
1845 {
1846 DPRINT ("Attributes differ\n");
1847
1848 /* Save current privilege */
1849 if (PreviousState != NULL)
1850 {
1851 if (k < PrivilegeCount)
1852 {
1853 PreviousState->PrivilegeCount++;
1854 PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
1855 PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
1856 }
1857 else
1858 {
1859 /* FIXME: Should revert all the changes, calculate how
1860 * much space would be needed, set ResultLength
1861 * accordingly and fail.
1862 */
1863 }
1864 k++;
1865 }
1866
1867 /* Update current privlege */
1868 Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
1869 }
1870 }
1871 Status = STATUS_SUCCESS;
1872 }
1873 else
1874 {
1875 Count = 0;
1876 for (i = 0; i < Token->PrivilegeCount; i++)
1877 {
1878 for (j = 0; j < NewState->PrivilegeCount; j++)
1879 {
1880 if (Token->Privileges[i].Luid.LowPart == NewState->Privileges[j].Luid.LowPart &&
1881 Token->Privileges[i].Luid.HighPart == NewState->Privileges[j].Luid.HighPart)
1882 {
1883 DPRINT ("Found privilege\n");
1884
1885 if ((Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) !=
1886 (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED))
1887 {
1888 DPRINT ("Attributes differ\n");
1889 DPRINT ("Current attributes %lx desired attributes %lx\n",
1890 Token->Privileges[i].Attributes,
1891 NewState->Privileges[j].Attributes);
1892
1893 /* Save current privilege */
1894 if (PreviousState != NULL)
1895 {
1896 if (k < PrivilegeCount)
1897 {
1898 PreviousState->PrivilegeCount++;
1899 PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
1900 PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
1901 }
1902 else
1903 {
1904 /* FIXME: Should revert all the changes, calculate how
1905 * much space would be needed, set ResultLength
1906 * accordingly and fail.
1907 */
1908 }
1909 k++;
1910 }
1911
1912 /* Update current privlege */
1913 Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
1914 Token->Privileges[i].Attributes |=
1915 (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED);
1916 DPRINT ("New attributes %lx\n",
1917 Token->Privileges[i].Attributes);
1918 }
1919 Count++;
1920 }
1921 }
1922 }
1923 Status = Count < NewState->PrivilegeCount ? STATUS_NOT_ALL_ASSIGNED : STATUS_SUCCESS;
1924 }
1925
1926 if (ReturnLength != NULL)
1927 {
1928 *ReturnLength = sizeof(TOKEN_PRIVILEGES) +
1929 (sizeof(LUID_AND_ATTRIBUTES) * (k - 1));
1930 }
1931
1932 ObDereferenceObject (Token);
1933
1934 // SeReleaseLuidAndAttributesArray(Privileges,
1935 // PreviousMode,
1936 // 0);
1937
1938 DPRINT ("NtAdjustPrivilegesToken() done\n");
1939
1940 return Status;
1941 }
1942
1943 NTSTATUS NTAPI
1944 NtCreateToken(OUT PHANDLE TokenHandle,
1945 IN ACCESS_MASK DesiredAccess,
1946 IN POBJECT_ATTRIBUTES ObjectAttributes,
1947 IN TOKEN_TYPE TokenType,
1948 IN PLUID AuthenticationId,
1949 IN PLARGE_INTEGER ExpirationTime,
1950 IN PTOKEN_USER TokenUser,
1951 IN PTOKEN_GROUPS TokenGroups,
1952 IN PTOKEN_PRIVILEGES TokenPrivileges,
1953 IN PTOKEN_OWNER TokenOwner,
1954 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup,
1955 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl,
1956 IN PTOKEN_SOURCE TokenSource)
1957 {
1958 HANDLE hToken;
1959 PTOKEN AccessToken;
1960 LUID TokenId;
1961 LUID ModifiedId;
1962 PVOID EndMem;
1963 ULONG uLength;
1964 ULONG i;
1965 KPROCESSOR_MODE PreviousMode;
1966 ULONG nTokenPrivileges = 0;
1967 LARGE_INTEGER LocalExpirationTime = {{0, 0}};
1968 NTSTATUS Status = STATUS_SUCCESS;
1969
1970 PAGED_CODE();
1971
1972 PreviousMode = ExGetPreviousMode();
1973
1974 if(PreviousMode != KernelMode)
1975 {
1976 _SEH2_TRY
1977 {
1978 ProbeForWriteHandle(TokenHandle);
1979 ProbeForRead(AuthenticationId,
1980 sizeof(LUID),
1981 sizeof(ULONG));
1982 LocalExpirationTime = ProbeForReadLargeInteger(ExpirationTime);
1983 ProbeForRead(TokenUser,
1984 sizeof(TOKEN_USER),
1985 sizeof(ULONG));
1986 ProbeForRead(TokenGroups,
1987 sizeof(TOKEN_GROUPS),
1988 sizeof(ULONG));
1989 ProbeForRead(TokenPrivileges,
1990 sizeof(TOKEN_PRIVILEGES),
1991 sizeof(ULONG));
1992 ProbeForRead(TokenOwner,
1993 sizeof(TOKEN_OWNER),
1994 sizeof(ULONG));
1995 ProbeForRead(TokenPrimaryGroup,
1996 sizeof(TOKEN_PRIMARY_GROUP),
1997 sizeof(ULONG));
1998 ProbeForRead(TokenDefaultDacl,
1999 sizeof(TOKEN_DEFAULT_DACL),
2000 sizeof(ULONG));
2001 ProbeForRead(TokenSource,
2002 sizeof(TOKEN_SOURCE),
2003 sizeof(ULONG));
2004 nTokenPrivileges = TokenPrivileges->PrivilegeCount;
2005 }
2006 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2007 {
2008 Status = _SEH2_GetExceptionCode();
2009 }
2010 _SEH2_END;
2011
2012 if(!NT_SUCCESS(Status))
2013 {
2014 return Status;
2015 }
2016 }
2017 else
2018 {
2019 nTokenPrivileges = TokenPrivileges->PrivilegeCount;
2020 LocalExpirationTime = *ExpirationTime;
2021 }
2022
2023 Status = ZwAllocateLocallyUniqueId(&TokenId);
2024 if (!NT_SUCCESS(Status))
2025 return(Status);
2026
2027 Status = ZwAllocateLocallyUniqueId(&ModifiedId);
2028 if (!NT_SUCCESS(Status))
2029 return(Status);
2030
2031 Status = ObCreateObject(PreviousMode,
2032 SepTokenObjectType,
2033 ObjectAttributes,
2034 PreviousMode,
2035 NULL,
2036 sizeof(TOKEN),
2037 0,
2038 0,
2039 (PVOID*)&AccessToken);
2040 if (!NT_SUCCESS(Status))
2041 {
2042 DPRINT1("ObCreateObject() failed (Status %lx)\n");
2043 return(Status);
2044 }
2045
2046 AccessToken->TokenLock = &SepTokenLock;
2047
2048 RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
2049 &TokenSource->SourceIdentifier);
2050 memcpy(AccessToken->TokenSource.SourceName,
2051 TokenSource->SourceName,
2052 sizeof(TokenSource->SourceName));
2053
2054 RtlCopyLuid(&AccessToken->TokenId, &TokenId);
2055 RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
2056 AccessToken->ExpirationTime = *ExpirationTime;
2057 RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
2058
2059 AccessToken->UserAndGroupCount = TokenGroups->GroupCount + 1;
2060 AccessToken->PrivilegeCount = TokenPrivileges->PrivilegeCount;
2061 AccessToken->UserAndGroups = 0;
2062 AccessToken->Privileges = 0;
2063
2064 AccessToken->TokenType = TokenType;
2065 AccessToken->ImpersonationLevel = ((PSECURITY_QUALITY_OF_SERVICE)
2066 (ObjectAttributes->SecurityQualityOfService))->ImpersonationLevel;
2067
2068 /*
2069 * Normally we would just point these members into the variable information
2070 * area; however, our ObCreateObject() call can't allocate a variable information
2071 * area, so we allocate them seperately and provide a destroy function.
2072 */
2073
2074 uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
2075 uLength += RtlLengthSid(TokenUser->User.Sid);
2076 for (i = 0; i < TokenGroups->GroupCount; i++)
2077 uLength += RtlLengthSid(TokenGroups->Groups[i].Sid);
2078
2079 AccessToken->UserAndGroups =
2080 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
2081 uLength,
2082 TAG('T', 'O', 'K', 'u'));
2083
2084 EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
2085
2086 Status = RtlCopySidAndAttributesArray(1,
2087 &TokenUser->User,
2088 uLength,
2089 AccessToken->UserAndGroups,
2090 EndMem,
2091 &EndMem,
2092 &uLength);
2093 if (NT_SUCCESS(Status))
2094 {
2095 Status = RtlCopySidAndAttributesArray(TokenGroups->GroupCount,
2096 TokenGroups->Groups,
2097 uLength,
2098 &AccessToken->UserAndGroups[1],
2099 EndMem,
2100 &EndMem,
2101 &uLength);
2102 }
2103
2104 if (NT_SUCCESS(Status))
2105 {
2106 Status = SepFindPrimaryGroupAndDefaultOwner(
2107 AccessToken,
2108 TokenPrimaryGroup->PrimaryGroup,
2109 TokenOwner->Owner);
2110 }
2111
2112 if (NT_SUCCESS(Status))
2113 {
2114 uLength = TokenPrivileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
2115 AccessToken->Privileges =
2116 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
2117 uLength,
2118 TAG('T', 'O', 'K', 'p'));
2119
2120 if (PreviousMode != KernelMode)
2121 {
2122 _SEH2_TRY
2123 {
2124 RtlCopyMemory(AccessToken->Privileges,
2125 TokenPrivileges->Privileges,
2126 nTokenPrivileges * sizeof(LUID_AND_ATTRIBUTES));
2127 }
2128 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2129 {
2130 Status = _SEH2_GetExceptionCode();
2131 }
2132 _SEH2_END;
2133 }
2134 else
2135 {
2136 RtlCopyMemory(AccessToken->Privileges,
2137 TokenPrivileges->Privileges,
2138 nTokenPrivileges * sizeof(LUID_AND_ATTRIBUTES));
2139 }
2140 }
2141
2142 if (NT_SUCCESS(Status))
2143 {
2144 AccessToken->DefaultDacl =
2145 (PACL) ExAllocatePoolWithTag(PagedPool,
2146 TokenDefaultDacl->DefaultDacl->AclSize,
2147 TAG('T', 'O', 'K', 'd'));
2148 memcpy(AccessToken->DefaultDacl,
2149 TokenDefaultDacl->DefaultDacl,
2150 TokenDefaultDacl->DefaultDacl->AclSize);
2151 }
2152
2153 Status = ObInsertObject ((PVOID)AccessToken,
2154 NULL,
2155 DesiredAccess,
2156 0,
2157 NULL,
2158 &hToken);
2159 if (!NT_SUCCESS(Status))
2160 {
2161 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status);
2162 }
2163
2164 if (NT_SUCCESS(Status))
2165 {
2166 _SEH2_TRY
2167 {
2168 *TokenHandle = hToken;
2169 }
2170 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2171 {
2172 Status = _SEH2_GetExceptionCode();
2173 }
2174 _SEH2_END;
2175 }
2176
2177 return Status;
2178 }
2179
2180 /*
2181 * @implemented
2182 */
2183 NTSTATUS
2184 NTAPI
2185 NtOpenThreadTokenEx(IN HANDLE ThreadHandle,
2186 IN ACCESS_MASK DesiredAccess,
2187 IN BOOLEAN OpenAsSelf,
2188 IN ULONG HandleAttributes,
2189 OUT PHANDLE TokenHandle)
2190 {
2191 PETHREAD Thread;
2192 HANDLE hToken;
2193 PTOKEN Token, NewToken, PrimaryToken;
2194 BOOLEAN CopyOnOpen, EffectiveOnly;
2195 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
2196 SE_IMPERSONATION_STATE ImpersonationState;
2197 OBJECT_ATTRIBUTES ObjectAttributes;
2198 SECURITY_DESCRIPTOR SecurityDescriptor;
2199 PACL Dacl = NULL;
2200 KPROCESSOR_MODE PreviousMode;
2201 NTSTATUS Status = STATUS_SUCCESS;
2202
2203 PAGED_CODE();
2204
2205 PreviousMode = ExGetPreviousMode();
2206
2207 if(PreviousMode != KernelMode)
2208 {
2209 _SEH2_TRY
2210 {
2211 ProbeForWriteHandle(TokenHandle);
2212 }
2213 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2214 {
2215 Status = _SEH2_GetExceptionCode();
2216 }
2217 _SEH2_END;
2218
2219 if(!NT_SUCCESS(Status))
2220 {
2221 return Status;
2222 }
2223 }
2224
2225 /*
2226 * At first open the thread token for information access and verify
2227 * that the token associated with thread is valid.
2228 */
2229
2230 Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_QUERY_INFORMATION,
2231 PsThreadType, PreviousMode, (PVOID*)&Thread,
2232 NULL);
2233 if (!NT_SUCCESS(Status))
2234 {
2235 return Status;
2236 }
2237
2238 Token = PsReferenceImpersonationToken(Thread, &CopyOnOpen, &EffectiveOnly,
2239 &ImpersonationLevel);
2240 if (Token == NULL)
2241 {
2242 ObfDereferenceObject(Thread);
2243 return STATUS_NO_TOKEN;
2244 }
2245
2246 ObDereferenceObject(Thread);
2247
2248 if (ImpersonationLevel == SecurityAnonymous)
2249 {
2250 ObfDereferenceObject(Token);
2251 return STATUS_CANT_OPEN_ANONYMOUS;
2252 }
2253
2254 /*
2255 * Revert to self if OpenAsSelf is specified.
2256 */
2257
2258 if (OpenAsSelf)
2259 {
2260 PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState);
2261 }
2262
2263 if (CopyOnOpen)
2264 {
2265 Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_ALL_ACCESS,
2266 PsThreadType, PreviousMode,
2267 (PVOID*)&Thread, NULL);
2268 if (!NT_SUCCESS(Status))
2269 {
2270 ObfDereferenceObject(Token);
2271 if (OpenAsSelf)
2272 {
2273 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
2274 }
2275 return Status;
2276 }
2277
2278 PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
2279 Status = SepCreateImpersonationTokenDacl(Token, PrimaryToken, &Dacl);
2280 ASSERT(FALSE);
2281 ObfDereferenceObject(PrimaryToken);
2282 ObfDereferenceObject(Thread);
2283 if (!NT_SUCCESS(Status))
2284 {
2285 ObfDereferenceObject(Token);
2286 if (OpenAsSelf)
2287 {
2288 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
2289 }
2290 return Status;
2291 }
2292
2293 RtlCreateSecurityDescriptor(&SecurityDescriptor,
2294 SECURITY_DESCRIPTOR_REVISION);
2295 RtlSetDaclSecurityDescriptor(&SecurityDescriptor, TRUE, Dacl,
2296 FALSE);
2297
2298 InitializeObjectAttributes(&ObjectAttributes, NULL, HandleAttributes,
2299 NULL, &SecurityDescriptor);
2300
2301 Status = SepDuplicateToken(Token, &ObjectAttributes, EffectiveOnly,
2302 TokenImpersonation, ImpersonationLevel,
2303 KernelMode, &NewToken);
2304 ExFreePool(Dacl);
2305 if (!NT_SUCCESS(Status))
2306 {
2307 ObfDereferenceObject(Token);
2308 if (OpenAsSelf)
2309 {
2310 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
2311 }
2312 return Status;
2313 }
2314
2315 Status = ObInsertObject(NewToken, NULL, DesiredAccess, 0, NULL,
2316 &hToken);
2317
2318 }
2319 else
2320 {
2321 Status = ObOpenObjectByPointer(Token, HandleAttributes,
2322 NULL, DesiredAccess, SepTokenObjectType,
2323 PreviousMode, &hToken);
2324 }
2325
2326 ObfDereferenceObject(Token);
2327
2328 if (OpenAsSelf)
2329 {
2330 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
2331 }
2332
2333 if(NT_SUCCESS(Status))
2334 {
2335 _SEH2_TRY
2336 {
2337 *TokenHandle = hToken;
2338 }
2339 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2340 {
2341 Status = _SEH2_GetExceptionCode();
2342 }
2343 _SEH2_END;
2344 }
2345
2346 return Status;
2347 }
2348
2349 /*
2350 * @implemented
2351 */
2352 NTSTATUS NTAPI
2353 NtOpenThreadToken(IN HANDLE ThreadHandle,
2354 IN ACCESS_MASK DesiredAccess,
2355 IN BOOLEAN OpenAsSelf,
2356 OUT PHANDLE TokenHandle)
2357 {
2358 return NtOpenThreadTokenEx(ThreadHandle, DesiredAccess, OpenAsSelf, 0,
2359 TokenHandle);
2360 }
2361
2362
2363
2364 /*
2365 * @unimplemented
2366 */
2367 NTSTATUS
2368 NTAPI
2369 NtCompareTokens(IN HANDLE FirstTokenHandle,
2370 IN HANDLE SecondTokenHandle,
2371 OUT PBOOLEAN Equal)
2372 {
2373 KPROCESSOR_MODE PreviousMode;
2374 PTOKEN FirstToken, SecondToken;
2375 BOOLEAN IsEqual;
2376 NTSTATUS Status = STATUS_SUCCESS;
2377
2378 PAGED_CODE();
2379
2380 PreviousMode = ExGetPreviousMode();
2381
2382 if (PreviousMode != KernelMode)
2383 {
2384 _SEH2_TRY
2385 {
2386 ProbeForWriteBoolean(Equal);
2387 }
2388 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2389 {
2390 Status = _SEH2_GetExceptionCode();
2391 }
2392 _SEH2_END;
2393
2394 if (!NT_SUCCESS(Status))
2395 return Status;
2396 }
2397
2398 Status = ObReferenceObjectByHandle(FirstTokenHandle,
2399 TOKEN_QUERY,
2400 SepTokenObjectType,
2401 PreviousMode,
2402 (PVOID*)&FirstToken,
2403 NULL);
2404 if (!NT_SUCCESS(Status))
2405 return Status;
2406
2407 Status = ObReferenceObjectByHandle(SecondTokenHandle,
2408 TOKEN_QUERY,
2409 SepTokenObjectType,
2410 PreviousMode,
2411 (PVOID*)&SecondToken,
2412 NULL);
2413 if (!NT_SUCCESS(Status))
2414 {
2415 ObDereferenceObject(FirstToken);
2416 return Status;
2417 }
2418
2419 if (FirstToken != SecondToken)
2420 {
2421 Status = SepCompareTokens(FirstToken,
2422 SecondToken,
2423 &IsEqual);
2424 }
2425 else
2426 IsEqual = TRUE;
2427
2428 ObDereferenceObject(FirstToken);
2429 ObDereferenceObject(SecondToken);
2430
2431 if (NT_SUCCESS(Status))
2432 {
2433 _SEH2_TRY
2434 {
2435 *Equal = IsEqual;
2436 }
2437 _SEH2_EXCEPT(ExSystemExceptionFilter())
2438 {
2439 Status = _SEH2_GetExceptionCode();
2440 }
2441 _SEH2_END;
2442 }
2443
2444 return Status;
2445 }
2446
2447 NTSTATUS
2448 NTAPI
2449 NtFilterToken(IN HANDLE ExistingTokenHandle,
2450 IN ULONG Flags,
2451 IN PTOKEN_GROUPS SidsToDisable OPTIONAL,
2452 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL,
2453 IN PTOKEN_GROUPS RestrictedSids OPTIONAL,
2454 OUT PHANDLE NewTokenHandle)
2455 {
2456 UNIMPLEMENTED;
2457 return STATUS_NOT_IMPLEMENTED;
2458 }
2459
2460 /*
2461 * @unimplemented
2462 */
2463 NTSTATUS
2464 NTAPI
2465 NtImpersonateAnonymousToken(IN HANDLE Thread)
2466 {
2467 UNIMPLEMENTED;
2468 return STATUS_NOT_IMPLEMENTED;
2469 }
2470
2471 /* EOF */