Merge 15329:15546 from trunk
[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 DPRINT1("NtQueryInformationToken(TokenRestrictedSids) not implemented\n");
1051 Status = STATUS_NOT_IMPLEMENTED;
1052 break;
1053
1054 case TokenSandBoxInert:
1055 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
1056 Status = STATUS_NOT_IMPLEMENTED;
1057 break;
1058
1059 case TokenSessionId:
1060 {
1061 ULONG SessionId = 0;
1062
1063 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
1064
1065 Status = SeQuerySessionIdToken(Token,
1066 &SessionId);
1067
1068 if(NT_SUCCESS(Status))
1069 {
1070 _SEH_TRY
1071 {
1072 /* buffer size was already verified, no need to check here again */
1073 *(PULONG)TokenInformation = SessionId;
1074
1075 if(ReturnLength != NULL)
1076 {
1077 *ReturnLength = sizeof(ULONG);
1078 }
1079 }
1080 _SEH_HANDLE
1081 {
1082 Status = _SEH_GetExceptionCode();
1083 }
1084 _SEH_END;
1085 }
1086
1087 break;
1088 }
1089
1090 default:
1091 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
1092 Status = STATUS_INVALID_INFO_CLASS;
1093 break;
1094 }
1095
1096 ObDereferenceObject(Token);
1097 }
1098
1099 return(Status);
1100 }
1101
1102 /*
1103 * @unimplemented
1104 */
1105 NTSTATUS
1106 STDCALL
1107 SeQueryInformationToken(
1108 IN PACCESS_TOKEN Token,
1109 IN TOKEN_INFORMATION_CLASS TokenInformationClass,
1110 OUT PVOID *TokenInformation
1111 )
1112 {
1113 UNIMPLEMENTED;
1114 return STATUS_NOT_IMPLEMENTED;
1115 }
1116
1117 /*
1118 * @implemented
1119 */
1120 NTSTATUS
1121 STDCALL
1122 SeQuerySessionIdToken(
1123 IN PACCESS_TOKEN Token,
1124 IN PULONG pSessionId
1125 )
1126 {
1127 *pSessionId = ((PTOKEN)Token)->SessionId;
1128 return STATUS_SUCCESS;
1129 }
1130
1131 /*
1132 * NtSetTokenInformation: Partly implemented.
1133 * Unimplemented:
1134 * TokenOrigin, TokenDefaultDacl
1135 */
1136
1137 NTSTATUS STDCALL
1138 NtSetInformationToken(IN HANDLE TokenHandle,
1139 IN TOKEN_INFORMATION_CLASS TokenInformationClass,
1140 OUT PVOID TokenInformation,
1141 IN ULONG TokenInformationLength)
1142 {
1143 PTOKEN Token;
1144 KPROCESSOR_MODE PreviousMode;
1145 ULONG NeededAccess = TOKEN_ADJUST_DEFAULT;
1146 NTSTATUS Status = STATUS_SUCCESS;
1147
1148 PAGED_CODE();
1149
1150 PreviousMode = ExGetPreviousMode();
1151
1152 DefaultSetInfoBufferCheck(TokenInformationClass,
1153 SeTokenInformationClass,
1154 TokenInformation,
1155 TokenInformationLength,
1156 PreviousMode,
1157 &Status);
1158
1159 if(!NT_SUCCESS(Status))
1160 {
1161 /* Invalid buffers */
1162 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status);
1163 return Status;
1164 }
1165
1166 if(TokenInformationClass == TokenSessionId)
1167 {
1168 NeededAccess |= TOKEN_ADJUST_SESSIONID;
1169 }
1170
1171 Status = ObReferenceObjectByHandle(TokenHandle,
1172 NeededAccess,
1173 SepTokenObjectType,
1174 PreviousMode,
1175 (PVOID*)&Token,
1176 NULL);
1177 if (NT_SUCCESS(Status))
1178 {
1179 switch (TokenInformationClass)
1180 {
1181 case TokenOwner:
1182 {
1183 if(TokenInformationLength >= sizeof(TOKEN_OWNER))
1184 {
1185 PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
1186 PSID InputSid = NULL;
1187
1188 _SEH_TRY
1189 {
1190 InputSid = to->Owner;
1191 }
1192 _SEH_HANDLE
1193 {
1194 Status = _SEH_GetExceptionCode();
1195 }
1196 _SEH_END;
1197
1198 if(NT_SUCCESS(Status))
1199 {
1200 PSID CapturedSid;
1201
1202 Status = SepCaptureSid(InputSid,
1203 PreviousMode,
1204 PagedPool,
1205 FALSE,
1206 &CapturedSid);
1207 if(NT_SUCCESS(Status))
1208 {
1209 RtlCopySid(RtlLengthSid(CapturedSid),
1210 Token->UserAndGroups[Token->DefaultOwnerIndex].Sid,
1211 CapturedSid);
1212 SepReleaseSid(CapturedSid,
1213 PreviousMode,
1214 FALSE);
1215 }
1216 }
1217 }
1218 else
1219 {
1220 Status = STATUS_INFO_LENGTH_MISMATCH;
1221 }
1222 break;
1223 }
1224
1225 case TokenPrimaryGroup:
1226 {
1227 if(TokenInformationLength >= sizeof(TOKEN_PRIMARY_GROUP))
1228 {
1229 PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
1230 PSID InputSid = NULL;
1231
1232 _SEH_TRY
1233 {
1234 InputSid = tpg->PrimaryGroup;
1235 }
1236 _SEH_HANDLE
1237 {
1238 Status = _SEH_GetExceptionCode();
1239 }
1240 _SEH_END;
1241
1242 if(NT_SUCCESS(Status))
1243 {
1244 PSID CapturedSid;
1245
1246 Status = SepCaptureSid(InputSid,
1247 PreviousMode,
1248 PagedPool,
1249 FALSE,
1250 &CapturedSid);
1251 if(NT_SUCCESS(Status))
1252 {
1253 RtlCopySid(RtlLengthSid(CapturedSid),
1254 Token->PrimaryGroup,
1255 CapturedSid);
1256 SepReleaseSid(CapturedSid,
1257 PreviousMode,
1258 FALSE);
1259 }
1260 }
1261 }
1262 else
1263 {
1264 Status = STATUS_INFO_LENGTH_MISMATCH;
1265 }
1266 break;
1267 }
1268
1269 case TokenDefaultDacl:
1270 {
1271 if(TokenInformationLength >= sizeof(TOKEN_DEFAULT_DACL))
1272 {
1273 PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
1274 PACL InputAcl = NULL;
1275
1276 _SEH_TRY
1277 {
1278 InputAcl = tdd->DefaultDacl;
1279 }
1280 _SEH_HANDLE
1281 {
1282 Status = _SEH_GetExceptionCode();
1283 }
1284 _SEH_END;
1285
1286 if(NT_SUCCESS(Status))
1287 {
1288 if(InputAcl != NULL)
1289 {
1290 PACL CapturedAcl;
1291
1292 /* capture and copy the dacl */
1293 Status = SepCaptureAcl(InputAcl,
1294 PreviousMode,
1295 PagedPool,
1296 TRUE,
1297 &CapturedAcl);
1298 if(NT_SUCCESS(Status))
1299 {
1300 /* free the previous dacl if present */
1301 if(Token->DefaultDacl != NULL)
1302 {
1303 ExFreePool(Token->DefaultDacl);
1304 }
1305
1306 /* set the new dacl */
1307 Token->DefaultDacl = CapturedAcl;
1308 }
1309 }
1310 else
1311 {
1312 /* clear and free the default dacl if present */
1313 if(Token->DefaultDacl != NULL)
1314 {
1315 ExFreePool(Token->DefaultDacl);
1316 Token->DefaultDacl = NULL;
1317 }
1318 }
1319 }
1320 }
1321 else
1322 {
1323 Status = STATUS_INFO_LENGTH_MISMATCH;
1324 }
1325 break;
1326 }
1327
1328 case TokenSessionId:
1329 {
1330 ULONG SessionId = 0;
1331
1332 _SEH_TRY
1333 {
1334 /* buffer size was already verified, no need to check here again */
1335 SessionId = *(PULONG)TokenInformation;
1336 }
1337 _SEH_HANDLE
1338 {
1339 Status = _SEH_GetExceptionCode();
1340 }
1341 _SEH_END;
1342
1343 if(NT_SUCCESS(Status))
1344 {
1345 if(!SeSinglePrivilegeCheck(SeTcbPrivilege,
1346 PreviousMode))
1347 {
1348 Status = STATUS_PRIVILEGE_NOT_HELD;
1349 break;
1350 }
1351
1352 Token->SessionId = SessionId;
1353 }
1354 break;
1355 }
1356
1357 default:
1358 {
1359 Status = STATUS_NOT_IMPLEMENTED;
1360 break;
1361 }
1362 }
1363
1364 ObDereferenceObject(Token);
1365 }
1366
1367 return(Status);
1368 }
1369
1370
1371 /*
1372 * @implemented
1373 *
1374 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1375 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1376 * is correct either. -Gunnar
1377 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1378 */
1379 NTSTATUS STDCALL
1380 NtDuplicateToken(IN HANDLE ExistingTokenHandle,
1381 IN ACCESS_MASK DesiredAccess,
1382 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
1383 IN BOOLEAN EffectiveOnly,
1384 IN TOKEN_TYPE TokenType,
1385 OUT PHANDLE NewTokenHandle)
1386 {
1387 KPROCESSOR_MODE PreviousMode;
1388 HANDLE hToken;
1389 PTOKEN Token;
1390 PTOKEN NewToken;
1391 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService;
1392 BOOLEAN QoSPresent;
1393 NTSTATUS Status = STATUS_SUCCESS;
1394
1395 PAGED_CODE();
1396
1397 PreviousMode = KeGetPreviousMode();
1398
1399 if(PreviousMode != KernelMode)
1400 {
1401 _SEH_TRY
1402 {
1403 ProbeForWrite(NewTokenHandle,
1404 sizeof(HANDLE),
1405 sizeof(ULONG));
1406 }
1407 _SEH_HANDLE
1408 {
1409 Status = _SEH_GetExceptionCode();
1410 }
1411 _SEH_END;
1412
1413 if(!NT_SUCCESS(Status))
1414 {
1415 return Status;
1416 }
1417 }
1418
1419 Status = SepCaptureSecurityQualityOfService(ObjectAttributes,
1420 PreviousMode,
1421 PagedPool,
1422 FALSE,
1423 &CapturedSecurityQualityOfService,
1424 &QoSPresent);
1425 if(!NT_SUCCESS(Status))
1426 {
1427 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status);
1428 return Status;
1429 }
1430
1431 Status = ObReferenceObjectByHandle(ExistingTokenHandle,
1432 TOKEN_DUPLICATE,
1433 SepTokenObjectType,
1434 PreviousMode,
1435 (PVOID*)&Token,
1436 NULL);
1437 if (NT_SUCCESS(Status))
1438 {
1439 Status = SepDuplicateToken(Token,
1440 ObjectAttributes,
1441 EffectiveOnly,
1442 TokenType,
1443 (QoSPresent ? CapturedSecurityQualityOfService->ImpersonationLevel : SecurityAnonymous),
1444 PreviousMode,
1445 &NewToken);
1446
1447 ObDereferenceObject(Token);
1448
1449 if (NT_SUCCESS(Status))
1450 {
1451 Status = ObInsertObject((PVOID)NewToken,
1452 NULL,
1453 DesiredAccess,
1454 0,
1455 NULL,
1456 &hToken);
1457
1458 ObDereferenceObject(NewToken);
1459
1460 if (NT_SUCCESS(Status))
1461 {
1462 _SEH_TRY
1463 {
1464 *NewTokenHandle = hToken;
1465 }
1466 _SEH_HANDLE
1467 {
1468 Status = _SEH_GetExceptionCode();
1469 }
1470 _SEH_END;
1471 }
1472 }
1473 }
1474
1475 /* free the captured structure */
1476 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService,
1477 PreviousMode,
1478 FALSE);
1479
1480 return Status;
1481 }
1482
1483
1484 VOID SepAdjustGroups(PACCESS_TOKEN Token,
1485 ULONG a,
1486 BOOLEAN ResetToDefault,
1487 PSID_AND_ATTRIBUTES Groups,
1488 ULONG b,
1489 KPROCESSOR_MODE PreviousMode,
1490 ULONG c,
1491 PULONG d,
1492 PULONG e,
1493 PULONG f)
1494 {
1495 UNIMPLEMENTED;
1496 }
1497
1498
1499 NTSTATUS STDCALL
1500 NtAdjustGroupsToken(IN HANDLE TokenHandle,
1501 IN BOOLEAN ResetToDefault,
1502 IN PTOKEN_GROUPS NewState,
1503 IN ULONG BufferLength,
1504 OUT PTOKEN_GROUPS PreviousState OPTIONAL,
1505 OUT PULONG ReturnLength)
1506 {
1507 #if 0
1508 NTSTATUS Status;
1509 PACCESS_TOKEN Token;
1510 ULONG a;
1511 ULONG b;
1512 ULONG c;
1513
1514 PAGED_CODE();
1515
1516 Status = ObReferenceObjectByHandle(TokenHandle,
1517 ?,
1518 SepTokenObjectType,
1519 UserMode,
1520 (PVOID*)&Token,
1521 NULL);
1522
1523
1524 SepAdjustGroups(Token,
1525 0,
1526 ResetToDefault,
1527 NewState->Groups,
1528 ?,
1529 PreviousState,
1530 0,
1531 &a,
1532 &b,
1533 &c);
1534 #else
1535 UNIMPLEMENTED;
1536 return(STATUS_NOT_IMPLEMENTED);
1537 #endif
1538 }
1539
1540
1541 #if 0
1542 NTSTATUS
1543 SepAdjustPrivileges(PACCESS_TOKEN Token,
1544 ULONG a,
1545 KPROCESSOR_MODE PreviousMode,
1546 ULONG PrivilegeCount,
1547 PLUID_AND_ATTRIBUTES Privileges,
1548 PTOKEN_PRIVILEGES* PreviousState,
1549 PULONG b,
1550 PULONG c,
1551 PULONG d)
1552 {
1553 ULONG i;
1554
1555 *c = 0;
1556
1557 if (Token->PrivilegeCount > 0)
1558 {
1559 for (i = 0; i < Token->PrivilegeCount; i++)
1560 {
1561 if (PreviousMode != KernelMode)
1562 {
1563 if (Token->Privileges[i]->Attributes & SE_PRIVILEGE_ENABLED == 0)
1564 {
1565 if (a != 0)
1566 {
1567 if (PreviousState != NULL)
1568 {
1569 memcpy(&PreviousState[i],
1570 &Token->Privileges[i],
1571 sizeof(LUID_AND_ATTRIBUTES));
1572 }
1573 Token->Privileges[i].Attributes &= (~SE_PRIVILEGE_ENABLED);
1574 }
1575 }
1576 }
1577 }
1578 }
1579
1580 if (PreviousMode != KernelMode)
1581 {
1582 Token->TokenFlags = Token->TokenFlags & (~1);
1583 }
1584 else
1585 {
1586 if (PrivilegeCount <= ?)
1587 {
1588 }
1589 }
1590 if (
1591 }
1592 #endif
1593
1594
1595 /*
1596 * @implemented
1597 */
1598 NTSTATUS STDCALL
1599 NtAdjustPrivilegesToken (IN HANDLE TokenHandle,
1600 IN BOOLEAN DisableAllPrivileges,
1601 IN PTOKEN_PRIVILEGES NewState,
1602 IN ULONG BufferLength,
1603 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL,
1604 OUT PULONG ReturnLength OPTIONAL)
1605 {
1606 // PLUID_AND_ATTRIBUTES Privileges;
1607 KPROCESSOR_MODE PreviousMode;
1608 ULONG PrivilegeCount;
1609 PTOKEN Token;
1610 // ULONG Length;
1611 ULONG i;
1612 ULONG j;
1613 ULONG k;
1614 ULONG Count;
1615 #if 0
1616 ULONG a;
1617 ULONG b;
1618 ULONG c;
1619 #endif
1620 NTSTATUS Status;
1621
1622 PAGED_CODE();
1623
1624 DPRINT ("NtAdjustPrivilegesToken() called\n");
1625
1626 // PrivilegeCount = NewState->PrivilegeCount;
1627 PreviousMode = KeGetPreviousMode ();
1628 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
1629 // PrivilegeCount,
1630 // PreviousMode,
1631 // NULL,
1632 // 0,
1633 // NonPagedPool,
1634 // 1,
1635 // &Privileges,
1636 // &Length);
1637
1638 Status = ObReferenceObjectByHandle (TokenHandle,
1639 TOKEN_ADJUST_PRIVILEGES | (PreviousState != NULL ? TOKEN_QUERY : 0),
1640 SepTokenObjectType,
1641 PreviousMode,
1642 (PVOID*)&Token,
1643 NULL);
1644 if (!NT_SUCCESS(Status))
1645 {
1646 DPRINT1 ("Failed to reference token (Status %lx)\n", Status);
1647 // SeReleaseLuidAndAttributesArray(Privileges,
1648 // PreviousMode,
1649 // 0);
1650 return Status;
1651 }
1652
1653
1654 #if 0
1655 SepAdjustPrivileges(Token,
1656 0,
1657 PreviousMode,
1658 PrivilegeCount,
1659 Privileges,
1660 PreviousState,
1661 &a,
1662 &b,
1663 &c);
1664 #endif
1665
1666 PrivilegeCount = (BufferLength - FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges)) /
1667 sizeof(LUID_AND_ATTRIBUTES);
1668
1669 if (PreviousState != NULL)
1670 PreviousState->PrivilegeCount = 0;
1671
1672 k = 0;
1673 if (DisableAllPrivileges == TRUE)
1674 {
1675 for (i = 0; i < Token->PrivilegeCount; i++)
1676 {
1677 if (Token->Privileges[i].Attributes != 0)
1678 {
1679 DPRINT ("Attributes differ\n");
1680
1681 /* Save current privilege */
1682 if (PreviousState != NULL)
1683 {
1684 if (k < PrivilegeCount)
1685 {
1686 PreviousState->PrivilegeCount++;
1687 PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
1688 PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
1689 }
1690 else
1691 {
1692 /* FIXME: Should revert all the changes, calculate how
1693 * much space would be needed, set ResultLength
1694 * accordingly and fail.
1695 */
1696 }
1697 k++;
1698 }
1699
1700 /* Update current privlege */
1701 Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
1702 }
1703 }
1704 Status = STATUS_SUCCESS;
1705 }
1706 else
1707 {
1708 Count = 0;
1709 for (i = 0; i < Token->PrivilegeCount; i++)
1710 {
1711 for (j = 0; j < NewState->PrivilegeCount; j++)
1712 {
1713 if (Token->Privileges[i].Luid.LowPart == NewState->Privileges[j].Luid.LowPart &&
1714 Token->Privileges[i].Luid.HighPart == NewState->Privileges[j].Luid.HighPart)
1715 {
1716 DPRINT ("Found privilege\n");
1717
1718 if ((Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) !=
1719 (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED))
1720 {
1721 DPRINT ("Attributes differ\n");
1722 DPRINT ("Current attributes %lx desired attributes %lx\n",
1723 Token->Privileges[i].Attributes,
1724 NewState->Privileges[j].Attributes);
1725
1726 /* Save current privilege */
1727 if (PreviousState != NULL)
1728 {
1729 if (k < PrivilegeCount)
1730 {
1731 PreviousState->PrivilegeCount++;
1732 PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
1733 PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
1734 }
1735 else
1736 {
1737 /* FIXME: Should revert all the changes, calculate how
1738 * much space would be needed, set ResultLength
1739 * accordingly and fail.
1740 */
1741 }
1742 k++;
1743 }
1744
1745 /* Update current privlege */
1746 Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
1747 Token->Privileges[i].Attributes |=
1748 (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED);
1749 DPRINT ("New attributes %lx\n",
1750 Token->Privileges[i].Attributes);
1751 }
1752 Count++;
1753 }
1754 }
1755 }
1756 Status = Count < NewState->PrivilegeCount ? STATUS_NOT_ALL_ASSIGNED : STATUS_SUCCESS;
1757 }
1758
1759 if (ReturnLength != NULL)
1760 {
1761 *ReturnLength = sizeof(TOKEN_PRIVILEGES) +
1762 (sizeof(LUID_AND_ATTRIBUTES) * (k - 1));
1763 }
1764
1765 ObDereferenceObject (Token);
1766
1767 // SeReleaseLuidAndAttributesArray(Privileges,
1768 // PreviousMode,
1769 // 0);
1770
1771 DPRINT ("NtAdjustPrivilegesToken() done\n");
1772
1773 return Status;
1774 }
1775
1776 PTOKEN
1777 STDCALL
1778 SepCreateSystemProcessToken(VOID)
1779 {
1780 NTSTATUS Status;
1781 ULONG uSize;
1782 ULONG i;
1783
1784 PAGED_CODE();
1785
1786 ULONG uLocalSystemLength = RtlLengthSid(SeLocalSystemSid);
1787 ULONG uWorldLength = RtlLengthSid(SeWorldSid);
1788 ULONG uAuthUserLength = RtlLengthSid(SeAuthenticatedUserSid);
1789 ULONG uAdminsLength = RtlLengthSid(SeAliasAdminsSid);
1790
1791 PTOKEN AccessToken;
1792
1793 PVOID SidArea;
1794
1795 /*
1796 * Initialize the token
1797 */
1798 Status = ObCreateObject(KernelMode,
1799 SepTokenObjectType,
1800 NULL,
1801 KernelMode,
1802 NULL,
1803 sizeof(TOKEN),
1804 0,
1805 0,
1806 (PVOID*)&AccessToken);
1807 if (!NT_SUCCESS(Status))
1808 {
1809 return NULL;
1810 }
1811 Status = ObInsertObject(AccessToken,
1812 NULL,
1813 TOKEN_ALL_ACCESS,
1814 0,
1815 NULL,
1816 NULL);
1817
1818 Status = ExpAllocateLocallyUniqueId(&AccessToken->TokenId);
1819 if (!NT_SUCCESS(Status))
1820 {
1821 ObDereferenceObject(AccessToken);
1822 return NULL;
1823 }
1824
1825 Status = ExpAllocateLocallyUniqueId(&AccessToken->ModifiedId);
1826 if (!NT_SUCCESS(Status))
1827 {
1828 ObDereferenceObject(AccessToken);
1829 return NULL;
1830 }
1831
1832 Status = ExpAllocateLocallyUniqueId(&AccessToken->AuthenticationId);
1833 if (!NT_SUCCESS(Status))
1834 {
1835 ObDereferenceObject(AccessToken);
1836 return NULL;
1837 }
1838
1839 AccessToken->TokenLock = &SepTokenLock;
1840
1841 AccessToken->TokenType = TokenPrimary;
1842 AccessToken->ImpersonationLevel = SecurityDelegation;
1843 AccessToken->TokenSource.SourceIdentifier.LowPart = 0;
1844 AccessToken->TokenSource.SourceIdentifier.HighPart = 0;
1845 memcpy(AccessToken->TokenSource.SourceName, "SeMgr\0\0\0", 8);
1846 AccessToken->ExpirationTime.QuadPart = -1;
1847 AccessToken->UserAndGroupCount = 4;
1848
1849 uSize = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
1850 uSize += uLocalSystemLength;
1851 uSize += uWorldLength;
1852 uSize += uAuthUserLength;
1853 uSize += uAdminsLength;
1854
1855 AccessToken->UserAndGroups =
1856 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
1857 uSize,
1858 TAG('T', 'O', 'K', 'u'));
1859 SidArea = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
1860
1861 i = 0;
1862 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1863 AccessToken->UserAndGroups[i++].Attributes = 0;
1864 RtlCopySid(uLocalSystemLength, SidArea, SeLocalSystemSid);
1865 SidArea = (char*)SidArea + uLocalSystemLength;
1866
1867 AccessToken->DefaultOwnerIndex = i;
1868 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1869 AccessToken->PrimaryGroup = (PSID) SidArea;
1870 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT;
1871 Status = RtlCopySid(uAdminsLength, SidArea, SeAliasAdminsSid);
1872 SidArea = (char*)SidArea + uAdminsLength;
1873
1874 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1875 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
1876 RtlCopySid(uWorldLength, SidArea, SeWorldSid);
1877 SidArea = (char*)SidArea + uWorldLength;
1878
1879 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1880 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
1881 RtlCopySid(uAuthUserLength, SidArea, SeAuthenticatedUserSid);
1882 SidArea = (char*)SidArea + uAuthUserLength;
1883
1884 AccessToken->PrivilegeCount = 20;
1885
1886 uSize = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
1887 AccessToken->Privileges =
1888 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
1889 uSize,
1890 TAG('T', 'O', 'K', 'p'));
1891
1892 i = 0;
1893 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1894 AccessToken->Privileges[i++].Luid = SeTcbPrivilege;
1895
1896 AccessToken->Privileges[i].Attributes = 0;
1897 AccessToken->Privileges[i++].Luid = SeCreateTokenPrivilege;
1898
1899 AccessToken->Privileges[i].Attributes = 0;
1900 AccessToken->Privileges[i++].Luid = SeTakeOwnershipPrivilege;
1901
1902 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1903 AccessToken->Privileges[i++].Luid = SeCreatePagefilePrivilege;
1904
1905 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1906 AccessToken->Privileges[i++].Luid = SeLockMemoryPrivilege;
1907
1908 AccessToken->Privileges[i].Attributes = 0;
1909 AccessToken->Privileges[i++].Luid = SeAssignPrimaryTokenPrivilege;
1910
1911 AccessToken->Privileges[i].Attributes = 0;
1912 AccessToken->Privileges[i++].Luid = SeIncreaseQuotaPrivilege;
1913
1914 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1915 AccessToken->Privileges[i++].Luid = SeIncreaseBasePriorityPrivilege;
1916
1917 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1918 AccessToken->Privileges[i++].Luid = SeCreatePermanentPrivilege;
1919
1920 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1921 AccessToken->Privileges[i++].Luid = SeDebugPrivilege;
1922
1923 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1924 AccessToken->Privileges[i++].Luid = SeAuditPrivilege;
1925
1926 AccessToken->Privileges[i].Attributes = 0;
1927 AccessToken->Privileges[i++].Luid = SeSecurityPrivilege;
1928
1929 AccessToken->Privileges[i].Attributes = 0;
1930 AccessToken->Privileges[i++].Luid = SeSystemEnvironmentPrivilege;
1931
1932 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1933 AccessToken->Privileges[i++].Luid = SeChangeNotifyPrivilege;
1934
1935 AccessToken->Privileges[i].Attributes = 0;
1936 AccessToken->Privileges[i++].Luid = SeBackupPrivilege;
1937
1938 AccessToken->Privileges[i].Attributes = 0;
1939 AccessToken->Privileges[i++].Luid = SeRestorePrivilege;
1940
1941 AccessToken->Privileges[i].Attributes = 0;
1942 AccessToken->Privileges[i++].Luid = SeShutdownPrivilege;
1943
1944 AccessToken->Privileges[i].Attributes = 0;
1945 AccessToken->Privileges[i++].Luid = SeLoadDriverPrivilege;
1946
1947 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1948 AccessToken->Privileges[i++].Luid = SeProfileSingleProcessPrivilege;
1949
1950 AccessToken->Privileges[i].Attributes = 0;
1951 AccessToken->Privileges[i++].Luid = SeSystemtimePrivilege;
1952 #if 0
1953 AccessToken->Privileges[i].Attributes = 0;
1954 AccessToken->Privileges[i++].Luid = SeUndockPrivilege;
1955
1956 AccessToken->Privileges[i].Attributes = 0;
1957 AccessToken->Privileges[i++].Luid = SeManageVolumePrivilege;
1958 #endif
1959
1960 ASSERT(i == 20);
1961
1962 uSize = sizeof(ACL);
1963 uSize += sizeof(ACE) + uLocalSystemLength;
1964 uSize += sizeof(ACE) + uAdminsLength;
1965 uSize = (uSize & (~3)) + 8;
1966 AccessToken->DefaultDacl =
1967 (PACL) ExAllocatePoolWithTag(PagedPool,
1968 uSize,
1969 TAG('T', 'O', 'K', 'd'));
1970 Status = RtlCreateAcl(AccessToken->DefaultDacl, uSize, ACL_REVISION);
1971 if ( NT_SUCCESS(Status) )
1972 {
1973 Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid);
1974 }
1975
1976 if ( NT_SUCCESS(Status) )
1977 {
1978 Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_READ|GENERIC_EXECUTE|READ_CONTROL, SeAliasAdminsSid);
1979 }
1980
1981 if ( ! NT_SUCCESS(Status) )
1982 {
1983 ObDereferenceObject(AccessToken);
1984 return NULL;
1985 }
1986
1987 return AccessToken;
1988 }
1989
1990
1991 NTSTATUS STDCALL
1992 NtCreateToken(OUT PHANDLE TokenHandle,
1993 IN ACCESS_MASK DesiredAccess,
1994 IN POBJECT_ATTRIBUTES ObjectAttributes,
1995 IN TOKEN_TYPE TokenType,
1996 IN PLUID AuthenticationId,
1997 IN PLARGE_INTEGER ExpirationTime,
1998 IN PTOKEN_USER TokenUser,
1999 IN PTOKEN_GROUPS TokenGroups,
2000 IN PTOKEN_PRIVILEGES TokenPrivileges,
2001 IN PTOKEN_OWNER TokenOwner,
2002 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup,
2003 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl,
2004 IN PTOKEN_SOURCE TokenSource)
2005 {
2006 HANDLE hToken;
2007 PTOKEN AccessToken;
2008 LUID TokenId;
2009 LUID ModifiedId;
2010 PVOID EndMem;
2011 ULONG uLength;
2012 ULONG i;
2013 KPROCESSOR_MODE PreviousMode;
2014 NTSTATUS Status = STATUS_SUCCESS;
2015
2016 PAGED_CODE();
2017
2018 PreviousMode = ExGetPreviousMode();
2019
2020 if(PreviousMode != KernelMode)
2021 {
2022 _SEH_TRY
2023 {
2024 ProbeForWrite(TokenHandle,
2025 sizeof(HANDLE),
2026 sizeof(ULONG));
2027 ProbeForRead(AuthenticationId,
2028 sizeof(LUID),
2029 sizeof(ULONG));
2030 ProbeForRead(ExpirationTime,
2031 sizeof(LARGE_INTEGER),
2032 sizeof(ULONG));
2033 ProbeForRead(TokenUser,
2034 sizeof(TOKEN_USER),
2035 sizeof(ULONG));
2036 ProbeForRead(TokenGroups,
2037 sizeof(TOKEN_GROUPS),
2038 sizeof(ULONG));
2039 ProbeForRead(TokenPrivileges,
2040 sizeof(TOKEN_PRIVILEGES),
2041 sizeof(ULONG));
2042 ProbeForRead(TokenOwner,
2043 sizeof(TOKEN_OWNER),
2044 sizeof(ULONG));
2045 ProbeForRead(TokenPrimaryGroup,
2046 sizeof(TOKEN_PRIMARY_GROUP),
2047 sizeof(ULONG));
2048 ProbeForRead(TokenDefaultDacl,
2049 sizeof(TOKEN_DEFAULT_DACL),
2050 sizeof(ULONG));
2051 ProbeForRead(TokenSource,
2052 sizeof(TOKEN_SOURCE),
2053 sizeof(ULONG));
2054 }
2055 _SEH_HANDLE
2056 {
2057 Status = _SEH_GetExceptionCode();
2058 }
2059 _SEH_END;
2060
2061 if(!NT_SUCCESS(Status))
2062 {
2063 return Status;
2064 }
2065 }
2066
2067 Status = ZwAllocateLocallyUniqueId(&TokenId);
2068 if (!NT_SUCCESS(Status))
2069 return(Status);
2070
2071 Status = ZwAllocateLocallyUniqueId(&ModifiedId);
2072 if (!NT_SUCCESS(Status))
2073 return(Status);
2074
2075 Status = ObCreateObject(PreviousMode,
2076 SepTokenObjectType,
2077 ObjectAttributes,
2078 PreviousMode,
2079 NULL,
2080 sizeof(TOKEN),
2081 0,
2082 0,
2083 (PVOID*)&AccessToken);
2084 if (!NT_SUCCESS(Status))
2085 {
2086 DPRINT1("ObCreateObject() failed (Status %lx)\n");
2087 return(Status);
2088 }
2089
2090 AccessToken->TokenLock = &SepTokenLock;
2091
2092 RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
2093 &TokenSource->SourceIdentifier);
2094 memcpy(AccessToken->TokenSource.SourceName,
2095 TokenSource->SourceName,
2096 sizeof(TokenSource->SourceName));
2097
2098 RtlCopyLuid(&AccessToken->TokenId, &TokenId);
2099 RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
2100 AccessToken->ExpirationTime = *ExpirationTime;
2101 RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
2102
2103 AccessToken->UserAndGroupCount = TokenGroups->GroupCount + 1;
2104 AccessToken->PrivilegeCount = TokenPrivileges->PrivilegeCount;
2105 AccessToken->UserAndGroups = 0;
2106 AccessToken->Privileges = 0;
2107
2108 AccessToken->TokenType = TokenType;
2109 AccessToken->ImpersonationLevel = ((PSECURITY_QUALITY_OF_SERVICE)
2110 (ObjectAttributes->SecurityQualityOfService))->ImpersonationLevel;
2111
2112 /*
2113 * Normally we would just point these members into the variable information
2114 * area; however, our ObCreateObject() call can't allocate a variable information
2115 * area, so we allocate them seperately and provide a destroy function.
2116 */
2117
2118 uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
2119 uLength += RtlLengthSid(TokenUser->User.Sid);
2120 for (i = 0; i < TokenGroups->GroupCount; i++)
2121 uLength += RtlLengthSid(TokenGroups->Groups[i].Sid);
2122
2123 AccessToken->UserAndGroups =
2124 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
2125 uLength,
2126 TAG('T', 'O', 'K', 'u'));
2127
2128 EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
2129
2130 Status = RtlCopySidAndAttributesArray(1,
2131 &TokenUser->User,
2132 uLength,
2133 AccessToken->UserAndGroups,
2134 EndMem,
2135 &EndMem,
2136 &uLength);
2137 if (NT_SUCCESS(Status))
2138 {
2139 Status = RtlCopySidAndAttributesArray(TokenGroups->GroupCount,
2140 TokenGroups->Groups,
2141 uLength,
2142 &AccessToken->UserAndGroups[1],
2143 EndMem,
2144 &EndMem,
2145 &uLength);
2146 }
2147
2148 if (NT_SUCCESS(Status))
2149 {
2150 Status = SepFindPrimaryGroupAndDefaultOwner(
2151 AccessToken,
2152 TokenPrimaryGroup->PrimaryGroup,
2153 TokenOwner->Owner);
2154 }
2155
2156 if (NT_SUCCESS(Status))
2157 {
2158 uLength = TokenPrivileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
2159 AccessToken->Privileges =
2160 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
2161 uLength,
2162 TAG('T', 'O', 'K', 'p'));
2163
2164 for (i = 0; i < TokenPrivileges->PrivilegeCount; i++)
2165 {
2166 Status = MmCopyFromCaller(&AccessToken->Privileges[i],
2167 &TokenPrivileges->Privileges[i],
2168 sizeof(LUID_AND_ATTRIBUTES));
2169 if (!NT_SUCCESS(Status))
2170 break;
2171 }
2172 }
2173
2174 if (NT_SUCCESS(Status))
2175 {
2176 AccessToken->DefaultDacl =
2177 (PACL) ExAllocatePoolWithTag(PagedPool,
2178 TokenDefaultDacl->DefaultDacl->AclSize,
2179 TAG('T', 'O', 'K', 'd'));
2180 memcpy(AccessToken->DefaultDacl,
2181 TokenDefaultDacl->DefaultDacl,
2182 TokenDefaultDacl->DefaultDacl->AclSize);
2183 }
2184
2185 Status = ObInsertObject ((PVOID)AccessToken,
2186 NULL,
2187 DesiredAccess,
2188 0,
2189 NULL,
2190 &hToken);
2191 if (!NT_SUCCESS(Status))
2192 {
2193 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status);
2194 }
2195
2196 ObDereferenceObject(AccessToken);
2197
2198 if (NT_SUCCESS(Status))
2199 {
2200 _SEH_TRY
2201 {
2202 *TokenHandle = hToken;
2203 }
2204 _SEH_HANDLE
2205 {
2206 Status = _SEH_GetExceptionCode();
2207 }
2208 _SEH_END;
2209 }
2210
2211 return Status;
2212 }
2213
2214
2215 /*
2216 * @implemented
2217 */
2218 NTSTATUS STDCALL
2219 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token,
2220 OUT PLUID LogonId)
2221 {
2222 PAGED_CODE();
2223
2224 *LogonId = ((PTOKEN)Token)->AuthenticationId;
2225
2226 return STATUS_SUCCESS;
2227 }
2228
2229
2230 /*
2231 * @implemented
2232 */
2233 SECURITY_IMPERSONATION_LEVEL
2234 STDCALL
2235 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token)
2236 {
2237 PAGED_CODE();
2238
2239 return ((PTOKEN)Token)->ImpersonationLevel;
2240 }
2241
2242
2243 /*
2244 * @implemented
2245 */
2246 TOKEN_TYPE STDCALL
2247 SeTokenType(IN PACCESS_TOKEN Token)
2248 {
2249 PAGED_CODE();
2250
2251 return ((PTOKEN)Token)->TokenType;
2252 }
2253
2254
2255 /*
2256 * @unimplemented
2257 */
2258 BOOLEAN
2259 STDCALL
2260 SeTokenIsAdmin(
2261 IN PACCESS_TOKEN Token
2262 )
2263 {
2264 UNIMPLEMENTED;
2265 return FALSE;
2266 }
2267
2268 /*
2269 * @unimplemented
2270 */
2271 BOOLEAN
2272 STDCALL
2273 SeTokenIsRestricted(
2274 IN PACCESS_TOKEN Token
2275 )
2276 {
2277 UNIMPLEMENTED;
2278 return FALSE;
2279 }
2280
2281 /*
2282 * @unimplemented
2283 */
2284 BOOLEAN
2285 STDCALL
2286 SeTokenIsWriteRestricted(
2287 IN PACCESS_TOKEN Token
2288 )
2289 {
2290 UNIMPLEMENTED;
2291 return FALSE;
2292 }
2293
2294
2295 /*
2296 * @implemented
2297 */
2298 NTSTATUS
2299 STDCALL
2300 NtOpenThreadTokenEx(IN HANDLE ThreadHandle,
2301 IN ACCESS_MASK DesiredAccess,
2302 IN BOOLEAN OpenAsSelf,
2303 IN ULONG HandleAttributes,
2304 OUT PHANDLE TokenHandle)
2305 {
2306 PETHREAD Thread;
2307 HANDLE hToken;
2308 PTOKEN Token, NewToken, PrimaryToken;
2309 BOOLEAN CopyOnOpen, EffectiveOnly;
2310 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
2311 SE_IMPERSONATION_STATE ImpersonationState;
2312 OBJECT_ATTRIBUTES ObjectAttributes;
2313 SECURITY_DESCRIPTOR SecurityDescriptor;
2314 PACL Dacl = NULL;
2315 KPROCESSOR_MODE PreviousMode;
2316 NTSTATUS Status = STATUS_SUCCESS;
2317
2318 PAGED_CODE();
2319
2320 PreviousMode = ExGetPreviousMode();
2321
2322 if(PreviousMode != KernelMode)
2323 {
2324 _SEH_TRY
2325 {
2326 ProbeForWrite(TokenHandle,
2327 sizeof(HANDLE),
2328 sizeof(ULONG));
2329 }
2330 _SEH_HANDLE
2331 {
2332 Status = _SEH_GetExceptionCode();
2333 }
2334 _SEH_END;
2335
2336 if(!NT_SUCCESS(Status))
2337 {
2338 return Status;
2339 }
2340 }
2341
2342 /*
2343 * At first open the thread token for information access and verify
2344 * that the token associated with thread is valid.
2345 */
2346
2347 Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_QUERY_INFORMATION,
2348 PsThreadType, PreviousMode, (PVOID*)&Thread,
2349 NULL);
2350 if (!NT_SUCCESS(Status))
2351 {
2352 return Status;
2353 }
2354
2355 Token = PsReferenceImpersonationToken(Thread, &CopyOnOpen, &EffectiveOnly,
2356 &ImpersonationLevel);
2357 if (Token == NULL)
2358 {
2359 ObfDereferenceObject(Thread);
2360 return STATUS_NO_TOKEN;
2361 }
2362
2363 ObDereferenceObject(Thread);
2364
2365 if (ImpersonationLevel == SecurityAnonymous)
2366 {
2367 ObfDereferenceObject(Token);
2368 return STATUS_CANT_OPEN_ANONYMOUS;
2369 }
2370
2371 /*
2372 * Revert to self if OpenAsSelf is specified.
2373 */
2374
2375 if (OpenAsSelf)
2376 {
2377 PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState);
2378 }
2379
2380 if (CopyOnOpen)
2381 {
2382 Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_ALL_ACCESS,
2383 PsThreadType, PreviousMode,
2384 (PVOID*)&Thread, NULL);
2385 if (!NT_SUCCESS(Status))
2386 {
2387 ObfDereferenceObject(Token);
2388 if (OpenAsSelf)
2389 {
2390 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
2391 }
2392 return Status;
2393 }
2394
2395 PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
2396 Status = SepCreateImpersonationTokenDacl(Token, PrimaryToken, &Dacl);
2397 ObfDereferenceObject(PrimaryToken);
2398 ObfDereferenceObject(Thread);
2399 if (!NT_SUCCESS(Status))
2400 {
2401 ObfDereferenceObject(Token);
2402 if (OpenAsSelf)
2403 {
2404 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
2405 }
2406 return Status;
2407 }
2408
2409 RtlCreateSecurityDescriptor(&SecurityDescriptor,
2410 SECURITY_DESCRIPTOR_REVISION);
2411 RtlSetDaclSecurityDescriptor(&SecurityDescriptor, TRUE, Dacl,
2412 FALSE);
2413
2414 InitializeObjectAttributes(&ObjectAttributes, NULL, HandleAttributes,
2415 NULL, &SecurityDescriptor);
2416
2417 Status = SepDuplicateToken(Token, &ObjectAttributes, EffectiveOnly,
2418 TokenImpersonation, ImpersonationLevel,
2419 KernelMode, &NewToken);
2420 ExFreePool(Dacl);
2421 if (!NT_SUCCESS(Status))
2422 {
2423 ObfDereferenceObject(Token);
2424 if (OpenAsSelf)
2425 {
2426 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
2427 }
2428 return Status;
2429 }
2430
2431 Status = ObInsertObject(NewToken, NULL, DesiredAccess, 0, NULL,
2432 &hToken);
2433
2434 ObfDereferenceObject(NewToken);
2435 }
2436 else
2437 {
2438 Status = ObOpenObjectByPointer(Token, HandleAttributes,
2439 NULL, DesiredAccess, SepTokenObjectType,
2440 PreviousMode, &hToken);
2441 }
2442
2443 ObfDereferenceObject(Token);
2444
2445 if (OpenAsSelf)
2446 {
2447 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
2448 }
2449
2450 if(NT_SUCCESS(Status))
2451 {
2452 _SEH_TRY
2453 {
2454 *TokenHandle = hToken;
2455 }
2456 _SEH_HANDLE
2457 {
2458 Status = _SEH_GetExceptionCode();
2459 }
2460 _SEH_END;
2461 }
2462
2463 return Status;
2464 }
2465
2466 /*
2467 * @implemented
2468 */
2469 NTSTATUS STDCALL
2470 NtOpenThreadToken(IN HANDLE ThreadHandle,
2471 IN ACCESS_MASK DesiredAccess,
2472 IN BOOLEAN OpenAsSelf,
2473 OUT PHANDLE TokenHandle)
2474 {
2475 return NtOpenThreadTokenEx(ThreadHandle, DesiredAccess, OpenAsSelf, 0,
2476 TokenHandle);
2477 }
2478
2479 /* EOF */