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