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