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