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