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