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