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