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