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