Sync with trunk r43000
[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 /* Zero out the buffer */
252 RtlZeroMemory(AccessToken, sizeof(TOKEN));
253
254 Status = ZwAllocateLocallyUniqueId(&AccessToken->TokenId);
255 if (!NT_SUCCESS(Status))
256 {
257 ObDereferenceObject(AccessToken);
258 return(Status);
259 }
260
261 Status = ZwAllocateLocallyUniqueId(&AccessToken->ModifiedId);
262 if (!NT_SUCCESS(Status))
263 {
264 ObDereferenceObject(AccessToken);
265 return(Status);
266 }
267
268 AccessToken->TokenLock = &SepTokenLock;
269
270 AccessToken->TokenType = TokenType;
271 AccessToken->ImpersonationLevel = Level;
272 RtlCopyLuid(&AccessToken->AuthenticationId, &Token->AuthenticationId);
273
274 AccessToken->TokenSource.SourceIdentifier.LowPart = Token->TokenSource.SourceIdentifier.LowPart;
275 AccessToken->TokenSource.SourceIdentifier.HighPart = Token->TokenSource.SourceIdentifier.HighPart;
276 memcpy(AccessToken->TokenSource.SourceName,
277 Token->TokenSource.SourceName,
278 sizeof(Token->TokenSource.SourceName));
279 AccessToken->ExpirationTime.QuadPart = Token->ExpirationTime.QuadPart;
280 AccessToken->UserAndGroupCount = Token->UserAndGroupCount;
281 AccessToken->DefaultOwnerIndex = Token->DefaultOwnerIndex;
282
283 uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
284 for (i = 0; i < Token->UserAndGroupCount; i++)
285 uLength += RtlLengthSid(Token->UserAndGroups[i].Sid);
286
287 AccessToken->UserAndGroups =
288 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
289 uLength,
290 'uKOT');
291
292 EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
293
294 Status = RtlCopySidAndAttributesArray(AccessToken->UserAndGroupCount,
295 Token->UserAndGroups,
296 uLength,
297 AccessToken->UserAndGroups,
298 EndMem,
299 &EndMem,
300 &uLength);
301 if (NT_SUCCESS(Status))
302 {
303 Status = SepFindPrimaryGroupAndDefaultOwner(
304 AccessToken,
305 Token->PrimaryGroup,
306 0);
307 }
308
309 if (NT_SUCCESS(Status))
310 {
311 AccessToken->PrivilegeCount = Token->PrivilegeCount;
312
313 uLength = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
314 AccessToken->Privileges =
315 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
316 uLength,
317 'pKOT');
318
319 for (i = 0; i < AccessToken->PrivilegeCount; i++)
320 {
321 RtlCopyLuid(&AccessToken->Privileges[i].Luid,
322 &Token->Privileges[i].Luid);
323 AccessToken->Privileges[i].Attributes =
324 Token->Privileges[i].Attributes;
325 }
326
327 if ( Token->DefaultDacl )
328 {
329 AccessToken->DefaultDacl =
330 (PACL) ExAllocatePoolWithTag(PagedPool,
331 Token->DefaultDacl->AclSize,
332 'kDOT');
333 memcpy(AccessToken->DefaultDacl,
334 Token->DefaultDacl,
335 Token->DefaultDacl->AclSize);
336 }
337 }
338
339 if ( NT_SUCCESS(Status) )
340 {
341 *NewAccessToken = AccessToken;
342 return(STATUS_SUCCESS);
343 }
344
345 return(Status);
346 }
347
348 NTSTATUS
349 NTAPI
350 SeSubProcessToken(IN PTOKEN ParentToken,
351 OUT PTOKEN *Token,
352 IN BOOLEAN InUse,
353 IN ULONG SessionId)
354 {
355 PTOKEN NewToken;
356 OBJECT_ATTRIBUTES ObjectAttributes;
357 NTSTATUS Status;
358
359 /* Initialize the attributes and duplicate it */
360 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
361 Status = SepDuplicateToken(ParentToken,
362 &ObjectAttributes,
363 FALSE,
364 TokenPrimary,
365 ParentToken->ImpersonationLevel,
366 KernelMode,
367 &NewToken);
368 if (NT_SUCCESS(Status))
369 {
370 /* Insert it */
371 Status = ObInsertObject(NewToken,
372 NULL,
373 0,
374 0,
375 NULL,
376 NULL);
377 if (NT_SUCCESS(Status))
378 {
379 /* Set the session ID */
380 NewToken->SessionId = SessionId;
381 NewToken->TokenInUse = InUse;
382
383 /* Return the token */
384 *Token = NewToken;
385 }
386 }
387
388 /* Return status */
389 return Status;
390 }
391
392 NTSTATUS
393 NTAPI
394 SeIsTokenChild(IN PTOKEN Token,
395 OUT PBOOLEAN IsChild)
396 {
397 PTOKEN ProcessToken;
398 LUID ProcessLuid, CallerLuid;
399
400 /* Assume failure */
401 *IsChild = FALSE;
402
403 /* Reference the process token */
404 ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess());
405
406 /* Get the ID */
407 ProcessLuid = ProcessToken->TokenId;
408
409 /* Dereference the token */
410 ObFastDereferenceObject(&PsGetCurrentProcess()->Token, ProcessToken);
411
412 /* Get our LUID */
413 CallerLuid = Token->TokenId;
414
415 /* Compare the LUIDs */
416 if (RtlEqualLuid(&CallerLuid, &ProcessLuid)) *IsChild = TRUE;
417
418 /* Return success */
419 return STATUS_SUCCESS;
420 }
421
422 NTSTATUS
423 NTAPI
424 SeCopyClientToken(IN PACCESS_TOKEN Token,
425 IN SECURITY_IMPERSONATION_LEVEL Level,
426 IN KPROCESSOR_MODE PreviousMode,
427 OUT PACCESS_TOKEN* NewToken)
428 {
429 NTSTATUS Status;
430 OBJECT_ATTRIBUTES ObjectAttributes;
431
432 PAGED_CODE();
433
434 InitializeObjectAttributes(&ObjectAttributes,
435 NULL,
436 0,
437 NULL,
438 NULL);
439 Status = SepDuplicateToken(Token,
440 &ObjectAttributes,
441 FALSE,
442 TokenImpersonation,
443 Level,
444 PreviousMode,
445 (PTOKEN*)NewToken);
446
447 return(Status);
448 }
449
450 VOID NTAPI
451 SepDeleteToken(PVOID ObjectBody)
452 {
453 PTOKEN AccessToken = (PTOKEN)ObjectBody;
454
455 if (AccessToken->UserAndGroups)
456 ExFreePool(AccessToken->UserAndGroups);
457
458 if (AccessToken->Privileges)
459 ExFreePool(AccessToken->Privileges);
460
461 if (AccessToken->DefaultDacl)
462 ExFreePool(AccessToken->DefaultDacl);
463 }
464
465
466 VOID
467 INIT_FUNCTION
468 NTAPI
469 SepInitializeTokenImplementation(VOID)
470 {
471 UNICODE_STRING Name;
472 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
473
474 ExInitializeResource(&SepTokenLock);
475
476 DPRINT("Creating Token Object Type\n");
477
478 /* Initialize the Token type */
479 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
480 RtlInitUnicodeString(&Name, L"Token");
481 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
482 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
483 ObjectTypeInitializer.SecurityRequired = TRUE;
484 ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(TOKEN);
485 ObjectTypeInitializer.GenericMapping = SepTokenMapping;
486 ObjectTypeInitializer.PoolType = PagedPool;
487 ObjectTypeInitializer.ValidAccessMask = TOKEN_ALL_ACCESS;
488 ObjectTypeInitializer.UseDefaultObject = TRUE;
489 ObjectTypeInitializer.DeleteProcedure = SepDeleteToken;
490 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &SepTokenObjectType);
491 }
492
493 VOID
494 NTAPI
495 SeAssignPrimaryToken(IN PEPROCESS Process,
496 IN PTOKEN Token)
497 {
498 PAGED_CODE();
499
500 /* Sanity checks */
501 ASSERT(Token->TokenType == TokenPrimary);
502 ASSERT(!Token->TokenInUse);
503
504 /* Clean any previous token */
505 if (Process->Token.Object) SeDeassignPrimaryToken(Process);
506
507 /* Set the new token */
508 ObReferenceObject(Token);
509 Token->TokenInUse = TRUE;
510 ObInitializeFastReference(&Process->Token, Token);
511 }
512
513 PTOKEN
514 NTAPI
515 SepCreateSystemProcessToken(VOID)
516 {
517 NTSTATUS Status;
518 ULONG uSize;
519 ULONG i;
520 ULONG uLocalSystemLength;
521 ULONG uWorldLength;
522 ULONG uAuthUserLength;
523 ULONG uAdminsLength;
524 PTOKEN AccessToken;
525 PVOID SidArea;
526
527 PAGED_CODE();
528
529 uLocalSystemLength = RtlLengthSid(SeLocalSystemSid);
530 uWorldLength = RtlLengthSid(SeWorldSid);
531 uAuthUserLength = RtlLengthSid(SeAuthenticatedUserSid);
532 uAdminsLength = RtlLengthSid(SeAliasAdminsSid);
533
534 /*
535 * Initialize the token
536 */
537 Status = ObCreateObject(KernelMode,
538 SepTokenObjectType,
539 NULL,
540 KernelMode,
541 NULL,
542 sizeof(TOKEN),
543 0,
544 0,
545 (PVOID*)&AccessToken);
546 if (!NT_SUCCESS(Status))
547 {
548 return NULL;
549 }
550
551 /* Zero out the buffer */
552 RtlZeroMemory(AccessToken, sizeof(TOKEN));
553
554 Status = ExpAllocateLocallyUniqueId(&AccessToken->TokenId);
555 if (!NT_SUCCESS(Status))
556 {
557 ObDereferenceObject(AccessToken);
558 return NULL;
559 }
560
561 Status = ExpAllocateLocallyUniqueId(&AccessToken->ModifiedId);
562 if (!NT_SUCCESS(Status))
563 {
564 ObDereferenceObject(AccessToken);
565 return NULL;
566 }
567
568 Status = ExpAllocateLocallyUniqueId(&AccessToken->AuthenticationId);
569 if (!NT_SUCCESS(Status))
570 {
571 ObDereferenceObject(AccessToken);
572 return NULL;
573 }
574
575 AccessToken->TokenLock = &SepTokenLock;
576
577 AccessToken->TokenType = TokenPrimary;
578 AccessToken->ImpersonationLevel = SecurityDelegation;
579 memcpy(AccessToken->TokenSource.SourceName, "SeMgr\0\0\0", 8);
580 AccessToken->ExpirationTime.QuadPart = -1;
581 AccessToken->UserAndGroupCount = 4;
582
583 uSize = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
584 uSize += uLocalSystemLength;
585 uSize += uWorldLength;
586 uSize += uAuthUserLength;
587 uSize += uAdminsLength;
588
589 AccessToken->UserAndGroups =
590 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
591 uSize,
592 'uKOT');
593 SidArea = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
594
595 i = 0;
596 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
597 AccessToken->UserAndGroups[i++].Attributes = 0;
598 RtlCopySid(uLocalSystemLength, SidArea, SeLocalSystemSid);
599 SidArea = (char*)SidArea + uLocalSystemLength;
600
601 AccessToken->DefaultOwnerIndex = i;
602 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
603 AccessToken->PrimaryGroup = (PSID) SidArea;
604 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT;
605 Status = RtlCopySid(uAdminsLength, SidArea, SeAliasAdminsSid);
606 SidArea = (char*)SidArea + uAdminsLength;
607
608 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
609 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
610 RtlCopySid(uWorldLength, SidArea, SeWorldSid);
611 SidArea = (char*)SidArea + uWorldLength;
612
613 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
614 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
615 RtlCopySid(uAuthUserLength, SidArea, SeAuthenticatedUserSid);
616 SidArea = (char*)SidArea + uAuthUserLength;
617
618 AccessToken->PrivilegeCount = 20;
619
620 uSize = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
621 AccessToken->Privileges =
622 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
623 uSize,
624 'pKOT');
625
626 i = 0;
627 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
628 AccessToken->Privileges[i++].Luid = SeTcbPrivilege;
629
630 AccessToken->Privileges[i].Attributes = 0;
631 AccessToken->Privileges[i++].Luid = SeCreateTokenPrivilege;
632
633 AccessToken->Privileges[i].Attributes = 0;
634 AccessToken->Privileges[i++].Luid = SeTakeOwnershipPrivilege;
635
636 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
637 AccessToken->Privileges[i++].Luid = SeCreatePagefilePrivilege;
638
639 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
640 AccessToken->Privileges[i++].Luid = SeLockMemoryPrivilege;
641
642 AccessToken->Privileges[i].Attributes = 0;
643 AccessToken->Privileges[i++].Luid = SeAssignPrimaryTokenPrivilege;
644
645 AccessToken->Privileges[i].Attributes = 0;
646 AccessToken->Privileges[i++].Luid = SeIncreaseQuotaPrivilege;
647
648 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
649 AccessToken->Privileges[i++].Luid = SeIncreaseBasePriorityPrivilege;
650
651 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
652 AccessToken->Privileges[i++].Luid = SeCreatePermanentPrivilege;
653
654 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
655 AccessToken->Privileges[i++].Luid = SeDebugPrivilege;
656
657 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
658 AccessToken->Privileges[i++].Luid = SeAuditPrivilege;
659
660 AccessToken->Privileges[i].Attributes = 0;
661 AccessToken->Privileges[i++].Luid = SeSecurityPrivilege;
662
663 AccessToken->Privileges[i].Attributes = 0;
664 AccessToken->Privileges[i++].Luid = SeSystemEnvironmentPrivilege;
665
666 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
667 AccessToken->Privileges[i++].Luid = SeChangeNotifyPrivilege;
668
669 AccessToken->Privileges[i].Attributes = 0;
670 AccessToken->Privileges[i++].Luid = SeBackupPrivilege;
671
672 AccessToken->Privileges[i].Attributes = 0;
673 AccessToken->Privileges[i++].Luid = SeRestorePrivilege;
674
675 AccessToken->Privileges[i].Attributes = 0;
676 AccessToken->Privileges[i++].Luid = SeShutdownPrivilege;
677
678 AccessToken->Privileges[i].Attributes = 0;
679 AccessToken->Privileges[i++].Luid = SeLoadDriverPrivilege;
680
681 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
682 AccessToken->Privileges[i++].Luid = SeProfileSingleProcessPrivilege;
683
684 AccessToken->Privileges[i].Attributes = 0;
685 AccessToken->Privileges[i++].Luid = SeSystemtimePrivilege;
686 #if 0
687 AccessToken->Privileges[i].Attributes = 0;
688 AccessToken->Privileges[i++].Luid = SeUndockPrivilege;
689
690 AccessToken->Privileges[i].Attributes = 0;
691 AccessToken->Privileges[i++].Luid = SeManageVolumePrivilege;
692 #endif
693
694 ASSERT(i == 20);
695
696 uSize = sizeof(ACL);
697 uSize += sizeof(ACE) + uLocalSystemLength;
698 uSize += sizeof(ACE) + uAdminsLength;
699 uSize = (uSize & (~3)) + 8;
700 AccessToken->DefaultDacl =
701 (PACL) ExAllocatePoolWithTag(PagedPool,
702 uSize,
703 'kDOT');
704 Status = RtlCreateAcl(AccessToken->DefaultDacl, uSize, ACL_REVISION);
705 if ( NT_SUCCESS(Status) )
706 {
707 Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid);
708 }
709
710 if ( NT_SUCCESS(Status) )
711 {
712 Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE|READ_CONTROL, SeAliasAdminsSid);
713 }
714
715 if ( ! NT_SUCCESS(Status) )
716 {
717 ObDereferenceObject(AccessToken);
718 return NULL;
719 }
720
721 return AccessToken;
722 }
723
724 /* PUBLIC FUNCTIONS ***********************************************************/
725
726 /*
727 * @unimplemented
728 */
729 NTSTATUS
730 NTAPI
731 SeFilterToken(IN PACCESS_TOKEN ExistingToken,
732 IN ULONG Flags,
733 IN PTOKEN_GROUPS SidsToDisable OPTIONAL,
734 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL,
735 IN PTOKEN_GROUPS RestrictedSids OPTIONAL,
736 OUT PACCESS_TOKEN * FilteredToken)
737 {
738 UNIMPLEMENTED;
739 return STATUS_NOT_IMPLEMENTED;
740 }
741
742 /*
743 * @unimplemented
744 */
745 NTSTATUS
746 NTAPI
747 SeQueryInformationToken(IN PACCESS_TOKEN Token,
748 IN TOKEN_INFORMATION_CLASS TokenInformationClass,
749 OUT PVOID *TokenInformation)
750 {
751 UNIMPLEMENTED;
752 return STATUS_NOT_IMPLEMENTED;
753 }
754
755 /*
756 * @implemented
757 */
758 NTSTATUS
759 NTAPI
760 SeQuerySessionIdToken(IN PACCESS_TOKEN Token,
761 IN PULONG pSessionId)
762 {
763 *pSessionId = ((PTOKEN)Token)->SessionId;
764 return STATUS_SUCCESS;
765 }
766
767 /*
768 * @implemented
769 */
770 NTSTATUS NTAPI
771 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token,
772 OUT PLUID LogonId)
773 {
774 PAGED_CODE();
775
776 *LogonId = ((PTOKEN)Token)->AuthenticationId;
777
778 return STATUS_SUCCESS;
779 }
780
781
782 /*
783 * @implemented
784 */
785 SECURITY_IMPERSONATION_LEVEL
786 NTAPI
787 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token)
788 {
789 PAGED_CODE();
790
791 return ((PTOKEN)Token)->ImpersonationLevel;
792 }
793
794
795 /*
796 * @implemented
797 */
798 TOKEN_TYPE NTAPI
799 SeTokenType(IN PACCESS_TOKEN Token)
800 {
801 PAGED_CODE();
802
803 return ((PTOKEN)Token)->TokenType;
804 }
805
806
807 /*
808 * @implemented
809 */
810 BOOLEAN
811 NTAPI
812 SeTokenIsAdmin(IN PACCESS_TOKEN Token)
813 {
814 PAGED_CODE();
815 return (((PTOKEN)Token)->TokenFlags & TOKEN_WRITE_RESTRICTED) != 0;
816 }
817
818 /*
819 * @implemented
820 */
821 BOOLEAN
822 NTAPI
823 SeTokenIsRestricted(IN PACCESS_TOKEN Token)
824 {
825 PAGED_CODE();
826 return (((PTOKEN)Token)->TokenFlags & TOKEN_IS_RESTRICTED) != 0;
827 }
828
829 /*
830 * @implemented
831 */
832 BOOLEAN
833 NTAPI
834 SeTokenIsWriteRestricted(IN PACCESS_TOKEN Token)
835 {
836 PAGED_CODE();
837 return (((PTOKEN)Token)->TokenFlags & TOKEN_HAS_RESTORE_PRIVILEGE) != 0;
838 }
839
840 /* SYSTEM CALLS ***************************************************************/
841
842 /*
843 * @implemented
844 */
845 NTSTATUS NTAPI
846 NtQueryInformationToken(IN HANDLE TokenHandle,
847 IN TOKEN_INFORMATION_CLASS TokenInformationClass,
848 OUT PVOID TokenInformation,
849 IN ULONG TokenInformationLength,
850 OUT PULONG ReturnLength)
851 {
852 union
853 {
854 PVOID Ptr;
855 ULONG Ulong;
856 } Unused;
857 PTOKEN Token;
858 ULONG RequiredLength;
859 KPROCESSOR_MODE PreviousMode;
860 NTSTATUS Status = STATUS_SUCCESS;
861
862 PAGED_CODE();
863
864 PreviousMode = ExGetPreviousMode();
865
866 /* Check buffers and class validity */
867 Status = DefaultQueryInfoBufferCheck(TokenInformationClass,
868 SeTokenInformationClass,
869 sizeof(SeTokenInformationClass) / sizeof(SeTokenInformationClass[0]),
870 TokenInformation,
871 TokenInformationLength,
872 ReturnLength,
873 NULL,
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;
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, CapturedSid;
1458
1459 _SEH2_TRY
1460 {
1461 InputSid = to->Owner;
1462 }
1463 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1464 {
1465 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1466 }
1467 _SEH2_END;
1468
1469 Status = SepCaptureSid(InputSid,
1470 PreviousMode,
1471 PagedPool,
1472 FALSE,
1473 &CapturedSid);
1474 if(NT_SUCCESS(Status))
1475 {
1476 RtlCopySid(RtlLengthSid(CapturedSid),
1477 Token->UserAndGroups[Token->DefaultOwnerIndex].Sid,
1478 CapturedSid);
1479 SepReleaseSid(CapturedSid,
1480 PreviousMode,
1481 FALSE);
1482 }
1483 }
1484 else
1485 {
1486 Status = STATUS_INFO_LENGTH_MISMATCH;
1487 }
1488 break;
1489 }
1490
1491 case TokenPrimaryGroup:
1492 {
1493 if(TokenInformationLength >= sizeof(TOKEN_PRIMARY_GROUP))
1494 {
1495 PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
1496 PSID InputSid = NULL, CapturedSid;
1497
1498 _SEH2_TRY
1499 {
1500 InputSid = tpg->PrimaryGroup;
1501 }
1502 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1503 {
1504 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1505 }
1506 _SEH2_END;
1507
1508 Status = SepCaptureSid(InputSid,
1509 PreviousMode,
1510 PagedPool,
1511 FALSE,
1512 &CapturedSid);
1513 if(NT_SUCCESS(Status))
1514 {
1515 RtlCopySid(RtlLengthSid(CapturedSid),
1516 Token->PrimaryGroup,
1517 CapturedSid);
1518 SepReleaseSid(CapturedSid,
1519 PreviousMode,
1520 FALSE);
1521 }
1522 }
1523 else
1524 {
1525 Status = STATUS_INFO_LENGTH_MISMATCH;
1526 }
1527 break;
1528 }
1529
1530 case TokenDefaultDacl:
1531 {
1532 if(TokenInformationLength >= sizeof(TOKEN_DEFAULT_DACL))
1533 {
1534 PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
1535 PACL InputAcl = NULL;
1536
1537 _SEH2_TRY
1538 {
1539 InputAcl = tdd->DefaultDacl;
1540 }
1541 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1542 {
1543 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1544 }
1545 _SEH2_END;
1546
1547 if(InputAcl != NULL)
1548 {
1549 PACL CapturedAcl;
1550
1551 /* capture and copy the dacl */
1552 Status = SepCaptureAcl(InputAcl,
1553 PreviousMode,
1554 PagedPool,
1555 TRUE,
1556 &CapturedAcl);
1557 if(NT_SUCCESS(Status))
1558 {
1559 /* free the previous dacl if present */
1560 if(Token->DefaultDacl != NULL)
1561 {
1562 ExFreePool(Token->DefaultDacl);
1563 }
1564
1565 /* set the new dacl */
1566 Token->DefaultDacl = CapturedAcl;
1567 }
1568 }
1569 else
1570 {
1571 /* clear and free the default dacl if present */
1572 if(Token->DefaultDacl != NULL)
1573 {
1574 ExFreePool(Token->DefaultDacl);
1575 Token->DefaultDacl = NULL;
1576 }
1577 }
1578 }
1579 else
1580 {
1581 Status = STATUS_INFO_LENGTH_MISMATCH;
1582 }
1583 break;
1584 }
1585
1586 case TokenSessionId:
1587 {
1588 ULONG SessionId = 0;
1589
1590 _SEH2_TRY
1591 {
1592 /* buffer size was already verified, no need to check here again */
1593 SessionId = *(PULONG)TokenInformation;
1594 }
1595 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1596 {
1597 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1598 }
1599 _SEH2_END;
1600
1601 if(!SeSinglePrivilegeCheck(SeTcbPrivilege,
1602 PreviousMode))
1603 {
1604 Status = STATUS_PRIVILEGE_NOT_HELD;
1605 break;
1606 }
1607
1608 Token->SessionId = SessionId;
1609 break;
1610 }
1611
1612 default:
1613 {
1614 Status = STATUS_NOT_IMPLEMENTED;
1615 break;
1616 }
1617 }
1618
1619 ObDereferenceObject(Token);
1620 }
1621
1622 return(Status);
1623 }
1624
1625
1626 /*
1627 * @implemented
1628 *
1629 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1630 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1631 * is correct either. -Gunnar
1632 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1633 */
1634 NTSTATUS NTAPI
1635 NtDuplicateToken(IN HANDLE ExistingTokenHandle,
1636 IN ACCESS_MASK DesiredAccess,
1637 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
1638 IN BOOLEAN EffectiveOnly,
1639 IN TOKEN_TYPE TokenType,
1640 OUT PHANDLE NewTokenHandle)
1641 {
1642 KPROCESSOR_MODE PreviousMode;
1643 HANDLE hToken;
1644 PTOKEN Token;
1645 PTOKEN NewToken;
1646 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService;
1647 BOOLEAN QoSPresent;
1648 NTSTATUS Status;
1649
1650 PAGED_CODE();
1651
1652 PreviousMode = KeGetPreviousMode();
1653
1654 if (PreviousMode != KernelMode)
1655 {
1656 _SEH2_TRY
1657 {
1658 ProbeForWriteHandle(NewTokenHandle);
1659 }
1660 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1661 {
1662 /* Return the exception code */
1663 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1664 }
1665 _SEH2_END;
1666 }
1667
1668 Status = SepCaptureSecurityQualityOfService(ObjectAttributes,
1669 PreviousMode,
1670 PagedPool,
1671 FALSE,
1672 &CapturedSecurityQualityOfService,
1673 &QoSPresent);
1674 if(!NT_SUCCESS(Status))
1675 {
1676 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status);
1677 return Status;
1678 }
1679
1680 Status = ObReferenceObjectByHandle(ExistingTokenHandle,
1681 TOKEN_DUPLICATE,
1682 SepTokenObjectType,
1683 PreviousMode,
1684 (PVOID*)&Token,
1685 NULL);
1686 if (NT_SUCCESS(Status))
1687 {
1688 Status = SepDuplicateToken(Token,
1689 ObjectAttributes,
1690 EffectiveOnly,
1691 TokenType,
1692 (QoSPresent ? CapturedSecurityQualityOfService->ImpersonationLevel : SecurityAnonymous),
1693 PreviousMode,
1694 &NewToken);
1695
1696 ObDereferenceObject(Token);
1697
1698 if (NT_SUCCESS(Status))
1699 {
1700 Status = ObInsertObject((PVOID)NewToken,
1701 NULL,
1702 DesiredAccess,
1703 0,
1704 NULL,
1705 &hToken);
1706
1707 if (NT_SUCCESS(Status))
1708 {
1709 _SEH2_TRY
1710 {
1711 *NewTokenHandle = hToken;
1712 }
1713 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1714 {
1715 Status = _SEH2_GetExceptionCode();
1716 }
1717 _SEH2_END;
1718 }
1719 }
1720 }
1721
1722 /* free the captured structure */
1723 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
1724 PreviousMode,
1725 FALSE);
1726
1727 return Status;
1728 }
1729
1730 NTSTATUS NTAPI
1731 NtAdjustGroupsToken(IN HANDLE TokenHandle,
1732 IN BOOLEAN ResetToDefault,
1733 IN PTOKEN_GROUPS NewState,
1734 IN ULONG BufferLength,
1735 OUT PTOKEN_GROUPS PreviousState OPTIONAL,
1736 OUT PULONG ReturnLength)
1737 {
1738 UNIMPLEMENTED;
1739 return(STATUS_NOT_IMPLEMENTED);
1740 }
1741
1742 /*
1743 * @implemented
1744 */
1745 NTSTATUS NTAPI
1746 NtAdjustPrivilegesToken (IN HANDLE TokenHandle,
1747 IN BOOLEAN DisableAllPrivileges,
1748 IN PTOKEN_PRIVILEGES NewState,
1749 IN ULONG BufferLength,
1750 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL,
1751 OUT PULONG ReturnLength OPTIONAL)
1752 {
1753 // PLUID_AND_ATTRIBUTES Privileges;
1754 KPROCESSOR_MODE PreviousMode;
1755 ULONG PrivilegeCount;
1756 PTOKEN Token;
1757 // ULONG Length;
1758 ULONG i;
1759 ULONG j;
1760 ULONG k;
1761 ULONG Count;
1762 #if 0
1763 ULONG a;
1764 ULONG b;
1765 ULONG c;
1766 #endif
1767 NTSTATUS Status;
1768
1769 PAGED_CODE();
1770
1771 DPRINT ("NtAdjustPrivilegesToken() called\n");
1772
1773 // PrivilegeCount = NewState->PrivilegeCount;
1774 PreviousMode = KeGetPreviousMode ();
1775 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
1776 // PrivilegeCount,
1777 // PreviousMode,
1778 // NULL,
1779 // 0,
1780 // NonPagedPool,
1781 // 1,
1782 // &Privileges,
1783 // &Length);
1784
1785 Status = ObReferenceObjectByHandle (TokenHandle,
1786 TOKEN_ADJUST_PRIVILEGES | (PreviousState != NULL ? TOKEN_QUERY : 0),
1787 SepTokenObjectType,
1788 PreviousMode,
1789 (PVOID*)&Token,
1790 NULL);
1791 if (!NT_SUCCESS(Status))
1792 {
1793 DPRINT1 ("Failed to reference token (Status %lx)\n", Status);
1794 // SeReleaseLuidAndAttributesArray(Privileges,
1795 // PreviousMode,
1796 // 0);
1797 return Status;
1798 }
1799
1800
1801 #if 0
1802 SepAdjustPrivileges(Token,
1803 0,
1804 PreviousMode,
1805 PrivilegeCount,
1806 Privileges,
1807 PreviousState,
1808 &a,
1809 &b,
1810 &c);
1811 #endif
1812
1813 PrivilegeCount = (BufferLength - FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges)) /
1814 sizeof(LUID_AND_ATTRIBUTES);
1815
1816 if (PreviousState != NULL)
1817 PreviousState->PrivilegeCount = 0;
1818
1819 k = 0;
1820 if (DisableAllPrivileges == TRUE)
1821 {
1822 for (i = 0; i < Token->PrivilegeCount; i++)
1823 {
1824 if (Token->Privileges[i].Attributes != 0)
1825 {
1826 DPRINT ("Attributes differ\n");
1827
1828 /* Save current privilege */
1829 if (PreviousState != NULL)
1830 {
1831 if (k < PrivilegeCount)
1832 {
1833 PreviousState->PrivilegeCount++;
1834 PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
1835 PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
1836 }
1837 else
1838 {
1839 /* FIXME: Should revert all the changes, calculate how
1840 * much space would be needed, set ResultLength
1841 * accordingly and fail.
1842 */
1843 }
1844 k++;
1845 }
1846
1847 /* Update current privlege */
1848 Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
1849 }
1850 }
1851 Status = STATUS_SUCCESS;
1852 }
1853 else
1854 {
1855 Count = 0;
1856 for (i = 0; i < Token->PrivilegeCount; i++)
1857 {
1858 for (j = 0; j < NewState->PrivilegeCount; j++)
1859 {
1860 if (Token->Privileges[i].Luid.LowPart == NewState->Privileges[j].Luid.LowPart &&
1861 Token->Privileges[i].Luid.HighPart == NewState->Privileges[j].Luid.HighPart)
1862 {
1863 DPRINT ("Found privilege\n");
1864
1865 if ((Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) !=
1866 (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED))
1867 {
1868 DPRINT ("Attributes differ\n");
1869 DPRINT ("Current attributes %lx desired attributes %lx\n",
1870 Token->Privileges[i].Attributes,
1871 NewState->Privileges[j].Attributes);
1872
1873 /* Save current privilege */
1874 if (PreviousState != NULL)
1875 {
1876 if (k < PrivilegeCount)
1877 {
1878 PreviousState->PrivilegeCount++;
1879 PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
1880 PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
1881 }
1882 else
1883 {
1884 /* FIXME: Should revert all the changes, calculate how
1885 * much space would be needed, set ResultLength
1886 * accordingly and fail.
1887 */
1888 }
1889 k++;
1890 }
1891
1892 /* Update current privlege */
1893 Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
1894 Token->Privileges[i].Attributes |=
1895 (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED);
1896 DPRINT ("New attributes %lx\n",
1897 Token->Privileges[i].Attributes);
1898 }
1899 Count++;
1900 }
1901 }
1902 }
1903 Status = Count < NewState->PrivilegeCount ? STATUS_NOT_ALL_ASSIGNED : STATUS_SUCCESS;
1904 }
1905
1906 if (ReturnLength != NULL)
1907 {
1908 *ReturnLength = sizeof(TOKEN_PRIVILEGES) +
1909 (sizeof(LUID_AND_ATTRIBUTES) * (k - 1));
1910 }
1911
1912 ObDereferenceObject (Token);
1913
1914 // SeReleaseLuidAndAttributesArray(Privileges,
1915 // PreviousMode,
1916 // 0);
1917
1918 DPRINT ("NtAdjustPrivilegesToken() done\n");
1919
1920 return Status;
1921 }
1922
1923 NTSTATUS NTAPI
1924 NtCreateToken(OUT PHANDLE TokenHandle,
1925 IN ACCESS_MASK DesiredAccess,
1926 IN POBJECT_ATTRIBUTES ObjectAttributes,
1927 IN TOKEN_TYPE TokenType,
1928 IN PLUID AuthenticationId,
1929 IN PLARGE_INTEGER ExpirationTime,
1930 IN PTOKEN_USER TokenUser,
1931 IN PTOKEN_GROUPS TokenGroups,
1932 IN PTOKEN_PRIVILEGES TokenPrivileges,
1933 IN PTOKEN_OWNER TokenOwner,
1934 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup,
1935 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl,
1936 IN PTOKEN_SOURCE TokenSource)
1937 {
1938 HANDLE hToken;
1939 PTOKEN AccessToken;
1940 LUID TokenId;
1941 LUID ModifiedId;
1942 PVOID EndMem;
1943 ULONG uLength;
1944 ULONG i;
1945 KPROCESSOR_MODE PreviousMode;
1946 ULONG nTokenPrivileges = 0;
1947 LARGE_INTEGER LocalExpirationTime = {{0, 0}};
1948 NTSTATUS Status;
1949
1950 PAGED_CODE();
1951
1952 PreviousMode = ExGetPreviousMode();
1953
1954 if(PreviousMode != KernelMode)
1955 {
1956 _SEH2_TRY
1957 {
1958 ProbeForWriteHandle(TokenHandle);
1959 ProbeForRead(AuthenticationId,
1960 sizeof(LUID),
1961 sizeof(ULONG));
1962 LocalExpirationTime = ProbeForReadLargeInteger(ExpirationTime);
1963 ProbeForRead(TokenUser,
1964 sizeof(TOKEN_USER),
1965 sizeof(ULONG));
1966 ProbeForRead(TokenGroups,
1967 sizeof(TOKEN_GROUPS),
1968 sizeof(ULONG));
1969 ProbeForRead(TokenPrivileges,
1970 sizeof(TOKEN_PRIVILEGES),
1971 sizeof(ULONG));
1972 ProbeForRead(TokenOwner,
1973 sizeof(TOKEN_OWNER),
1974 sizeof(ULONG));
1975 ProbeForRead(TokenPrimaryGroup,
1976 sizeof(TOKEN_PRIMARY_GROUP),
1977 sizeof(ULONG));
1978 ProbeForRead(TokenDefaultDacl,
1979 sizeof(TOKEN_DEFAULT_DACL),
1980 sizeof(ULONG));
1981 ProbeForRead(TokenSource,
1982 sizeof(TOKEN_SOURCE),
1983 sizeof(ULONG));
1984 nTokenPrivileges = TokenPrivileges->PrivilegeCount;
1985 }
1986 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1987 {
1988 /* Return the exception code */
1989 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1990 }
1991 _SEH2_END;
1992 }
1993 else
1994 {
1995 nTokenPrivileges = TokenPrivileges->PrivilegeCount;
1996 LocalExpirationTime = *ExpirationTime;
1997 }
1998
1999 Status = ZwAllocateLocallyUniqueId(&TokenId);
2000 if (!NT_SUCCESS(Status))
2001 return(Status);
2002
2003 Status = ZwAllocateLocallyUniqueId(&ModifiedId);
2004 if (!NT_SUCCESS(Status))
2005 return(Status);
2006
2007 Status = ObCreateObject(PreviousMode,
2008 SepTokenObjectType,
2009 ObjectAttributes,
2010 PreviousMode,
2011 NULL,
2012 sizeof(TOKEN),
2013 0,
2014 0,
2015 (PVOID*)&AccessToken);
2016 if (!NT_SUCCESS(Status))
2017 {
2018 DPRINT1("ObCreateObject() failed (Status %lx)\n");
2019 return(Status);
2020 }
2021
2022 /* Zero out the buffer */
2023 RtlZeroMemory(AccessToken, sizeof(TOKEN));
2024
2025 AccessToken->TokenLock = &SepTokenLock;
2026
2027 RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
2028 &TokenSource->SourceIdentifier);
2029 memcpy(AccessToken->TokenSource.SourceName,
2030 TokenSource->SourceName,
2031 sizeof(TokenSource->SourceName));
2032
2033 RtlCopyLuid(&AccessToken->TokenId, &TokenId);
2034 RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
2035 AccessToken->ExpirationTime = *ExpirationTime;
2036 RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
2037
2038 AccessToken->UserAndGroupCount = TokenGroups->GroupCount + 1;
2039 AccessToken->PrivilegeCount = TokenPrivileges->PrivilegeCount;
2040
2041 AccessToken->TokenType = TokenType;
2042 AccessToken->ImpersonationLevel = ((PSECURITY_QUALITY_OF_SERVICE)
2043 (ObjectAttributes->SecurityQualityOfService))->ImpersonationLevel;
2044
2045 /*
2046 * Normally we would just point these members into the variable information
2047 * area; however, our ObCreateObject() call can't allocate a variable information
2048 * area, so we allocate them seperately and provide a destroy function.
2049 */
2050
2051 uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
2052 uLength += RtlLengthSid(TokenUser->User.Sid);
2053 for (i = 0; i < TokenGroups->GroupCount; i++)
2054 uLength += RtlLengthSid(TokenGroups->Groups[i].Sid);
2055
2056 AccessToken->UserAndGroups =
2057 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
2058 uLength,
2059 'uKOT');
2060
2061 EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
2062
2063 Status = RtlCopySidAndAttributesArray(1,
2064 &TokenUser->User,
2065 uLength,
2066 AccessToken->UserAndGroups,
2067 EndMem,
2068 &EndMem,
2069 &uLength);
2070 if (NT_SUCCESS(Status))
2071 {
2072 Status = RtlCopySidAndAttributesArray(TokenGroups->GroupCount,
2073 TokenGroups->Groups,
2074 uLength,
2075 &AccessToken->UserAndGroups[1],
2076 EndMem,
2077 &EndMem,
2078 &uLength);
2079 }
2080
2081 if (NT_SUCCESS(Status))
2082 {
2083 Status = SepFindPrimaryGroupAndDefaultOwner(
2084 AccessToken,
2085 TokenPrimaryGroup->PrimaryGroup,
2086 TokenOwner->Owner);
2087 }
2088
2089 if (NT_SUCCESS(Status))
2090 {
2091 uLength = TokenPrivileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
2092 AccessToken->Privileges =
2093 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
2094 uLength,
2095 'pKOT');
2096
2097 if (PreviousMode != KernelMode)
2098 {
2099 _SEH2_TRY
2100 {
2101 RtlCopyMemory(AccessToken->Privileges,
2102 TokenPrivileges->Privileges,
2103 nTokenPrivileges * sizeof(LUID_AND_ATTRIBUTES));
2104 }
2105 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2106 {
2107 Status = _SEH2_GetExceptionCode();
2108 }
2109 _SEH2_END;
2110 }
2111 else
2112 {
2113 RtlCopyMemory(AccessToken->Privileges,
2114 TokenPrivileges->Privileges,
2115 nTokenPrivileges * sizeof(LUID_AND_ATTRIBUTES));
2116 }
2117 }
2118
2119 if (NT_SUCCESS(Status))
2120 {
2121 AccessToken->DefaultDacl =
2122 (PACL) ExAllocatePoolWithTag(PagedPool,
2123 TokenDefaultDacl->DefaultDacl->AclSize,
2124 'kDOT');
2125 memcpy(AccessToken->DefaultDacl,
2126 TokenDefaultDacl->DefaultDacl,
2127 TokenDefaultDacl->DefaultDacl->AclSize);
2128 }
2129
2130 Status = ObInsertObject ((PVOID)AccessToken,
2131 NULL,
2132 DesiredAccess,
2133 0,
2134 NULL,
2135 &hToken);
2136 if (!NT_SUCCESS(Status))
2137 {
2138 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status);
2139 }
2140
2141 if (NT_SUCCESS(Status))
2142 {
2143 _SEH2_TRY
2144 {
2145 *TokenHandle = hToken;
2146 }
2147 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2148 {
2149 Status = _SEH2_GetExceptionCode();
2150 }
2151 _SEH2_END;
2152 }
2153
2154 return Status;
2155 }
2156
2157 /*
2158 * @implemented
2159 */
2160 NTSTATUS
2161 NTAPI
2162 NtOpenThreadTokenEx(IN HANDLE ThreadHandle,
2163 IN ACCESS_MASK DesiredAccess,
2164 IN BOOLEAN OpenAsSelf,
2165 IN ULONG HandleAttributes,
2166 OUT PHANDLE TokenHandle)
2167 {
2168 PETHREAD Thread;
2169 HANDLE hToken;
2170 PTOKEN Token, NewToken, PrimaryToken;
2171 BOOLEAN CopyOnOpen, EffectiveOnly;
2172 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
2173 SE_IMPERSONATION_STATE ImpersonationState;
2174 OBJECT_ATTRIBUTES ObjectAttributes;
2175 SECURITY_DESCRIPTOR SecurityDescriptor;
2176 PACL Dacl = NULL;
2177 KPROCESSOR_MODE PreviousMode;
2178 NTSTATUS Status;
2179
2180 PAGED_CODE();
2181
2182 PreviousMode = ExGetPreviousMode();
2183
2184 if (PreviousMode != KernelMode)
2185 {
2186 _SEH2_TRY
2187 {
2188 ProbeForWriteHandle(TokenHandle);
2189 }
2190 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2191 {
2192 /* Return the exception code */
2193 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2194 }
2195 _SEH2_END;
2196 }
2197
2198 /*
2199 * At first open the thread token for information access and verify
2200 * that the token associated with thread is valid.
2201 */
2202
2203 Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_QUERY_INFORMATION,
2204 PsThreadType, PreviousMode, (PVOID*)&Thread,
2205 NULL);
2206 if (!NT_SUCCESS(Status))
2207 {
2208 return Status;
2209 }
2210
2211 Token = PsReferenceImpersonationToken(Thread, &CopyOnOpen, &EffectiveOnly,
2212 &ImpersonationLevel);
2213 if (Token == NULL)
2214 {
2215 ObDereferenceObject(Thread);
2216 return STATUS_NO_TOKEN;
2217 }
2218
2219 ObDereferenceObject(Thread);
2220
2221 if (ImpersonationLevel == SecurityAnonymous)
2222 {
2223 ObDereferenceObject(Token);
2224 return STATUS_CANT_OPEN_ANONYMOUS;
2225 }
2226
2227 /*
2228 * Revert to self if OpenAsSelf is specified.
2229 */
2230
2231 if (OpenAsSelf)
2232 {
2233 PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState);
2234 }
2235
2236 if (CopyOnOpen)
2237 {
2238 Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_ALL_ACCESS,
2239 PsThreadType, PreviousMode,
2240 (PVOID*)&Thread, NULL);
2241 if (!NT_SUCCESS(Status))
2242 {
2243 ObDereferenceObject(Token);
2244 if (OpenAsSelf)
2245 {
2246 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
2247 }
2248 return Status;
2249 }
2250
2251 PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
2252 Status = SepCreateImpersonationTokenDacl(Token, PrimaryToken, &Dacl);
2253 ASSERT(FALSE);
2254 ObDereferenceObject(PrimaryToken);
2255 ObDereferenceObject(Thread);
2256 if (!NT_SUCCESS(Status))
2257 {
2258 ObDereferenceObject(Token);
2259 if (OpenAsSelf)
2260 {
2261 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
2262 }
2263 return Status;
2264 }
2265
2266 RtlCreateSecurityDescriptor(&SecurityDescriptor,
2267 SECURITY_DESCRIPTOR_REVISION);
2268 RtlSetDaclSecurityDescriptor(&SecurityDescriptor, TRUE, Dacl,
2269 FALSE);
2270
2271 InitializeObjectAttributes(&ObjectAttributes, NULL, HandleAttributes,
2272 NULL, &SecurityDescriptor);
2273
2274 Status = SepDuplicateToken(Token, &ObjectAttributes, EffectiveOnly,
2275 TokenImpersonation, ImpersonationLevel,
2276 KernelMode, &NewToken);
2277 ExFreePool(Dacl);
2278 if (!NT_SUCCESS(Status))
2279 {
2280 ObDereferenceObject(Token);
2281 if (OpenAsSelf)
2282 {
2283 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
2284 }
2285 return Status;
2286 }
2287
2288 Status = ObInsertObject(NewToken, NULL, DesiredAccess, 0, NULL,
2289 &hToken);
2290
2291 }
2292 else
2293 {
2294 Status = ObOpenObjectByPointer(Token, HandleAttributes,
2295 NULL, DesiredAccess, SepTokenObjectType,
2296 PreviousMode, &hToken);
2297 }
2298
2299 ObDereferenceObject(Token);
2300
2301 if (OpenAsSelf)
2302 {
2303 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
2304 }
2305
2306 if(NT_SUCCESS(Status))
2307 {
2308 _SEH2_TRY
2309 {
2310 *TokenHandle = hToken;
2311 }
2312 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2313 {
2314 Status = _SEH2_GetExceptionCode();
2315 }
2316 _SEH2_END;
2317 }
2318
2319 return Status;
2320 }
2321
2322 /*
2323 * @implemented
2324 */
2325 NTSTATUS NTAPI
2326 NtOpenThreadToken(IN HANDLE ThreadHandle,
2327 IN ACCESS_MASK DesiredAccess,
2328 IN BOOLEAN OpenAsSelf,
2329 OUT PHANDLE TokenHandle)
2330 {
2331 return NtOpenThreadTokenEx(ThreadHandle, DesiredAccess, OpenAsSelf, 0,
2332 TokenHandle);
2333 }
2334
2335
2336
2337 /*
2338 * @unimplemented
2339 */
2340 NTSTATUS
2341 NTAPI
2342 NtCompareTokens(IN HANDLE FirstTokenHandle,
2343 IN HANDLE SecondTokenHandle,
2344 OUT PBOOLEAN Equal)
2345 {
2346 KPROCESSOR_MODE PreviousMode;
2347 PTOKEN FirstToken, SecondToken;
2348 BOOLEAN IsEqual;
2349 NTSTATUS Status;
2350
2351 PAGED_CODE();
2352
2353 PreviousMode = ExGetPreviousMode();
2354
2355 if (PreviousMode != KernelMode)
2356 {
2357 _SEH2_TRY
2358 {
2359 ProbeForWriteBoolean(Equal);
2360 }
2361 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2362 {
2363 /* Return the exception code */
2364 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2365 }
2366 _SEH2_END;
2367 }
2368
2369 Status = ObReferenceObjectByHandle(FirstTokenHandle,
2370 TOKEN_QUERY,
2371 SepTokenObjectType,
2372 PreviousMode,
2373 (PVOID*)&FirstToken,
2374 NULL);
2375 if (!NT_SUCCESS(Status))
2376 return Status;
2377
2378 Status = ObReferenceObjectByHandle(SecondTokenHandle,
2379 TOKEN_QUERY,
2380 SepTokenObjectType,
2381 PreviousMode,
2382 (PVOID*)&SecondToken,
2383 NULL);
2384 if (!NT_SUCCESS(Status))
2385 {
2386 ObDereferenceObject(FirstToken);
2387 return Status;
2388 }
2389
2390 if (FirstToken != SecondToken)
2391 {
2392 Status = SepCompareTokens(FirstToken,
2393 SecondToken,
2394 &IsEqual);
2395 }
2396 else
2397 IsEqual = TRUE;
2398
2399 ObDereferenceObject(FirstToken);
2400 ObDereferenceObject(SecondToken);
2401
2402 if (NT_SUCCESS(Status))
2403 {
2404 _SEH2_TRY
2405 {
2406 *Equal = IsEqual;
2407 }
2408 _SEH2_EXCEPT(ExSystemExceptionFilter())
2409 {
2410 Status = _SEH2_GetExceptionCode();
2411 }
2412 _SEH2_END;
2413 }
2414
2415 return Status;
2416 }
2417
2418 NTSTATUS
2419 NTAPI
2420 NtFilterToken(IN HANDLE ExistingTokenHandle,
2421 IN ULONG Flags,
2422 IN PTOKEN_GROUPS SidsToDisable OPTIONAL,
2423 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL,
2424 IN PTOKEN_GROUPS RestrictedSids OPTIONAL,
2425 OUT PHANDLE NewTokenHandle)
2426 {
2427 UNIMPLEMENTED;
2428 return STATUS_NOT_IMPLEMENTED;
2429 }
2430
2431 /*
2432 * @unimplemented
2433 */
2434 NTSTATUS
2435 NTAPI
2436 NtImpersonateAnonymousToken(IN HANDLE Thread)
2437 {
2438 UNIMPLEMENTED;
2439 return STATUS_NOT_IMPLEMENTED;
2440 }
2441
2442 /* EOF */