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