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