Clean-up NtQueryInformationToken().
[reactos.git] / reactos / ntoskrnl / se / token.c
1 /* $Id: token.c,v 1.34 2004/03/19 12:47:17 ekohl Exp $
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 TOKEN_TYPE TokenType,
137 SECURITY_IMPERSONATION_LEVEL Level,
138 SECURITY_IMPERSONATION_LEVEL ExistingLevel,
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 AccessToken->AuthenticationId.LowPart = SYSTEM_LUID;
183 AccessToken->AuthenticationId.HighPart = 0;
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 PACCESS_TOKEN pNewToken;
271 PACCESS_TOKEN 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 TokenPrimary,
286 pParentToken->ImpersonationLevel,
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 NTSTATUS SeCopyClientToken(PACCESS_TOKEN Token,
299 SECURITY_IMPERSONATION_LEVEL Level,
300 KPROCESSOR_MODE PreviousMode,
301 PACCESS_TOKEN* NewToken)
302 {
303 NTSTATUS Status;
304 OBJECT_ATTRIBUTES ObjectAttributes;
305
306 InitializeObjectAttributes(&ObjectAttributes,
307 NULL,
308 0,
309 NULL,
310 NULL);
311 Status = SepDuplicateToken(Token,
312 &ObjectAttributes,
313 0,
314 SecurityIdentification,
315 Level,
316 PreviousMode,
317 NewToken);
318 return(Status);
319 }
320
321
322 /*
323 * @implemented
324 */
325 NTSTATUS STDCALL
326 SeCreateClientSecurity(IN struct _ETHREAD *Thread,
327 IN PSECURITY_QUALITY_OF_SERVICE Qos,
328 IN BOOLEAN RemoteClient,
329 OUT PSECURITY_CLIENT_CONTEXT ClientContext)
330 {
331 TOKEN_TYPE TokenType;
332 UCHAR b;
333 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
334 PACCESS_TOKEN Token;
335 ULONG g;
336 PACCESS_TOKEN NewToken;
337
338 Token = PsReferenceEffectiveToken(Thread,
339 &TokenType,
340 &b,
341 &ImpersonationLevel);
342 if (TokenType != 2)
343 {
344 ClientContext->DirectAccessEffectiveOnly = Qos->EffectiveOnly;
345 }
346 else
347 {
348 if (Qos->ImpersonationLevel > ImpersonationLevel)
349 {
350 if (Token != NULL)
351 {
352 ObDereferenceObject(Token);
353 }
354 return(STATUS_UNSUCCESSFUL);
355 }
356 if (ImpersonationLevel == 0 ||
357 ImpersonationLevel == 1 ||
358 (RemoteClient != FALSE && ImpersonationLevel != 3))
359 {
360 if (Token != NULL)
361 {
362 ObDereferenceObject(Token);
363 }
364 return(STATUS_UNSUCCESSFUL);
365 }
366 if (b != 0 ||
367 Qos->EffectiveOnly != 0)
368 {
369 ClientContext->DirectAccessEffectiveOnly = TRUE;
370 }
371 else
372 {
373 ClientContext->DirectAccessEffectiveOnly = FALSE;
374 }
375 }
376
377 if (Qos->ContextTrackingMode == 0)
378 {
379 ClientContext->DirectlyAccessClientToken = FALSE;
380 g = SeCopyClientToken(Token, ImpersonationLevel, 0, &NewToken);
381 if (g >= 0)
382 {
383 // ObDeleteCapturedInsertInfo(NewToken);
384 }
385 if (TokenType == TokenPrimary || Token != NULL)
386 {
387 ObDereferenceObject(Token);
388 }
389 if (g < 0)
390 {
391 return(g);
392 }
393 }
394 else
395 {
396 ClientContext->DirectlyAccessClientToken = TRUE;
397 if (RemoteClient != FALSE)
398 {
399 // SeGetTokenControlInformation(Token, &ClientContext->Unknown11);
400 }
401 NewToken = Token;
402 }
403 ClientContext->SecurityQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
404 ClientContext->SecurityQos.ImpersonationLevel = Qos->ImpersonationLevel;
405 ClientContext->SecurityQos.ContextTrackingMode = Qos->ContextTrackingMode;
406 ClientContext->SecurityQos.EffectiveOnly = Qos->EffectiveOnly;
407 ClientContext->ServerIsRemote = RemoteClient;
408 ClientContext->Token = NewToken;
409
410 return(STATUS_SUCCESS);
411 }
412
413
414 /*
415 * @implemented
416 */
417 VOID STDCALL
418 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext,
419 IN PETHREAD ServerThread OPTIONAL)
420 {
421 UCHAR b;
422
423 if (ClientContext->DirectlyAccessClientToken == FALSE)
424 {
425 b = ClientContext->SecurityQos.EffectiveOnly;
426 }
427 else
428 {
429 b = ClientContext->DirectAccessEffectiveOnly;
430 }
431 if (ServerThread == NULL)
432 {
433 ServerThread = PsGetCurrentThread();
434 }
435 PsImpersonateClient(ServerThread,
436 ClientContext->Token,
437 1,
438 (ULONG)b,
439 ClientContext->SecurityQos.ImpersonationLevel);
440 }
441
442
443 VOID STDCALL
444 SepDeleteToken(PVOID ObjectBody)
445 {
446 PACCESS_TOKEN AccessToken = (PACCESS_TOKEN)ObjectBody;
447
448 if (AccessToken->UserAndGroups)
449 ExFreePool(AccessToken->UserAndGroups);
450
451 if (AccessToken->Privileges)
452 ExFreePool(AccessToken->Privileges);
453
454 if (AccessToken->DefaultDacl)
455 ExFreePool(AccessToken->DefaultDacl);
456 }
457
458
459 VOID INIT_FUNCTION
460 SepInitializeTokenImplementation(VOID)
461 {
462 SepTokenObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
463
464 SepTokenObjectType->Tag = TAG('T', 'O', 'K', 'T');
465 SepTokenObjectType->MaxObjects = ULONG_MAX;
466 SepTokenObjectType->MaxHandles = ULONG_MAX;
467 SepTokenObjectType->TotalObjects = 0;
468 SepTokenObjectType->TotalHandles = 0;
469 SepTokenObjectType->PagedPoolCharge = 0;
470 SepTokenObjectType->NonpagedPoolCharge = sizeof(ACCESS_TOKEN);
471 SepTokenObjectType->Mapping = &SepTokenMapping;
472 SepTokenObjectType->Dump = NULL;
473 SepTokenObjectType->Open = NULL;
474 SepTokenObjectType->Close = NULL;
475 SepTokenObjectType->Delete = SepDeleteToken;
476 SepTokenObjectType->Parse = NULL;
477 SepTokenObjectType->Security = NULL;
478 SepTokenObjectType->QueryName = NULL;
479 SepTokenObjectType->OkayToClose = NULL;
480 SepTokenObjectType->Create = NULL;
481 SepTokenObjectType->DuplicationNotify = NULL;
482
483 RtlCreateUnicodeString(&SepTokenObjectType->TypeName,
484 L"Token");
485 ObpCreateTypeObject (SepTokenObjectType);
486 }
487
488
489 /*
490 * @implemented
491 */
492 NTSTATUS STDCALL
493 NtQueryInformationToken(IN HANDLE TokenHandle,
494 IN TOKEN_INFORMATION_CLASS TokenInformationClass,
495 OUT PVOID TokenInformation,
496 IN ULONG TokenInformationLength,
497 OUT PULONG ReturnLength)
498 {
499 NTSTATUS Status;
500 PVOID UnusedInfo;
501 PVOID EndMem;
502 PACCESS_TOKEN Token;
503 ULONG Length;
504 PTOKEN_GROUPS PtrTokenGroups;
505 PTOKEN_DEFAULT_DACL PtrDefaultDacl;
506 PTOKEN_STATISTICS PtrTokenStatistics;
507
508 Status = ObReferenceObjectByHandle(TokenHandle,
509 (TokenInformationClass == TokenSource) ? TOKEN_QUERY_SOURCE : TOKEN_QUERY,
510 SepTokenObjectType,
511 UserMode,
512 (PVOID*)&Token,
513 NULL);
514 if (!NT_SUCCESS(Status))
515 {
516 return(Status);
517 }
518
519 switch (TokenInformationClass)
520 {
521 case TokenUser:
522 DPRINT("NtQueryInformationToken(TokenUser)\n");
523 Length = RtlLengthSidAndAttributes(1, Token->UserAndGroups);
524 if (TokenInformationLength < Length)
525 {
526 Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
527 if (NT_SUCCESS(Status))
528 Status = STATUS_BUFFER_TOO_SMALL;
529 }
530 else
531 {
532 Status = RtlCopySidAndAttributesArray(1,
533 Token->UserAndGroups,
534 TokenInformationLength,
535 TokenInformation,
536 (char*)TokenInformation + 8,
537 &UnusedInfo,
538 &Length);
539 if (NT_SUCCESS(Status))
540 {
541 Length = TokenInformationLength - Length;
542 Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
543 }
544 }
545 break;
546
547 case TokenGroups:
548 DPRINT("NtQueryInformationToken(TokenGroups)\n");
549 Length = RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]) + sizeof(ULONG);
550 if (TokenInformationLength < Length)
551 {
552 Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
553 if (NT_SUCCESS(Status))
554 Status = STATUS_BUFFER_TOO_SMALL;
555 }
556 else
557 {
558 EndMem = (char*)TokenInformation + Token->UserAndGroupCount * sizeof(SID_AND_ATTRIBUTES);
559 PtrTokenGroups = (PTOKEN_GROUPS)TokenInformation;
560 PtrTokenGroups->GroupCount = Token->UserAndGroupCount - 1;
561 Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
562 &Token->UserAndGroups[1],
563 TokenInformationLength,
564 PtrTokenGroups->Groups,
565 EndMem,
566 &UnusedInfo,
567 &Length);
568 if (NT_SUCCESS(Status))
569 {
570 Length = TokenInformationLength - Length;
571 Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
572 }
573 }
574 break;
575
576 case TokenPrivileges:
577 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
578 Length = sizeof(ULONG) + Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
579 if (TokenInformationLength < Length)
580 {
581 Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
582 if (NT_SUCCESS(Status))
583 Status = STATUS_BUFFER_TOO_SMALL;
584 }
585 else
586 {
587 ULONG i;
588 TOKEN_PRIVILEGES* pPriv = (TOKEN_PRIVILEGES*)TokenInformation;
589
590 pPriv->PrivilegeCount = Token->PrivilegeCount;
591 for (i = 0; i < Token->PrivilegeCount; i++)
592 {
593 RtlCopyLuid(&pPriv->Privileges[i].Luid, &Token->Privileges[i].Luid);
594 pPriv->Privileges[i].Attributes = Token->Privileges[i].Attributes;
595 }
596 Status = STATUS_SUCCESS;
597 }
598 break;
599
600 case TokenOwner:
601 DPRINT("NtQueryInformationToken(TokenOwner)\n");
602 Length = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid) + sizeof(TOKEN_OWNER);
603 if (TokenInformationLength < Length)
604 {
605 Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
606 if (NT_SUCCESS(Status))
607 Status = STATUS_BUFFER_TOO_SMALL;
608 }
609 else
610 {
611 ((PTOKEN_OWNER)TokenInformation)->Owner =
612 (PSID)(((PTOKEN_OWNER)TokenInformation) + 1);
613 RtlCopySid(TokenInformationLength - sizeof(TOKEN_OWNER),
614 ((PTOKEN_OWNER)TokenInformation)->Owner,
615 Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
616 Status = STATUS_SUCCESS;
617 }
618 break;
619
620 case TokenPrimaryGroup:
621 DPRINT("NtQueryInformationToken(TokenPrimaryGroup),"
622 "Token->PrimaryGroup = 0x%08x\n", Token->PrimaryGroup);
623 Length = RtlLengthSid(Token->PrimaryGroup) + sizeof(TOKEN_PRIMARY_GROUP);
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 ((PTOKEN_PRIMARY_GROUP)TokenInformation)->PrimaryGroup =
633 (PSID)(((PTOKEN_PRIMARY_GROUP)TokenInformation) + 1);
634 RtlCopySid(TokenInformationLength - sizeof(TOKEN_PRIMARY_GROUP),
635 ((PTOKEN_PRIMARY_GROUP)TokenInformation)->PrimaryGroup,
636 Token->PrimaryGroup);
637 Status = STATUS_SUCCESS;
638 }
639 break;
640
641 case TokenDefaultDacl:
642 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
643 PtrDefaultDacl = (PTOKEN_DEFAULT_DACL) TokenInformation;
644 Length = (Token->DefaultDacl ? Token->DefaultDacl->AclSize : 0) + sizeof(TOKEN_DEFAULT_DACL);
645 if (TokenInformationLength < Length)
646 {
647 Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
648 if (NT_SUCCESS(Status))
649 Status = STATUS_BUFFER_TOO_SMALL;
650 }
651 else if (!Token->DefaultDacl)
652 {
653 PtrDefaultDacl->DefaultDacl = 0;
654 Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
655 }
656 else
657 {
658 PtrDefaultDacl->DefaultDacl = (PACL) (PtrDefaultDacl + 1);
659 memmove(PtrDefaultDacl->DefaultDacl,
660 Token->DefaultDacl,
661 Token->DefaultDacl->AclSize);
662 Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
663 }
664 break;
665
666 case TokenSource:
667 DPRINT("NtQueryInformationToken(TokenSource)\n");
668 if (TokenInformationLength < sizeof(TOKEN_SOURCE))
669 {
670 Length = sizeof(TOKEN_SOURCE);
671 Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
672 if (NT_SUCCESS(Status))
673 Status = STATUS_BUFFER_TOO_SMALL;
674 }
675 else
676 {
677 Status = MmCopyToCaller(TokenInformation, &Token->TokenSource, sizeof(TOKEN_SOURCE));
678 }
679 break;
680
681 case TokenType:
682 DPRINT("NtQueryInformationToken(TokenType)\n");
683 if (TokenInformationLength < sizeof(TOKEN_TYPE))
684 {
685 Length = sizeof(TOKEN_TYPE);
686 Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
687 if (NT_SUCCESS(Status))
688 Status = STATUS_BUFFER_TOO_SMALL;
689 }
690 else
691 {
692 Status = MmCopyToCaller(TokenInformation, &Token->TokenType, sizeof(TOKEN_TYPE));
693 }
694 break;
695
696 case TokenImpersonationLevel:
697 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
698 if (TokenInformationLength < sizeof(SECURITY_IMPERSONATION_LEVEL))
699 {
700 Length = sizeof(SECURITY_IMPERSONATION_LEVEL);
701 Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
702 if (NT_SUCCESS(Status))
703 Status = STATUS_BUFFER_TOO_SMALL;
704 }
705 else
706 {
707 Status = MmCopyToCaller(TokenInformation, &Token->ImpersonationLevel, sizeof(SECURITY_IMPERSONATION_LEVEL));
708 }
709 break;
710
711 case TokenStatistics:
712 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
713 if (TokenInformationLength < sizeof(TOKEN_STATISTICS))
714 {
715 Length = sizeof(TOKEN_STATISTICS);
716 Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
717 if (NT_SUCCESS(Status))
718 Status = STATUS_BUFFER_TOO_SMALL;
719 }
720 else
721 {
722 PtrTokenStatistics = (PTOKEN_STATISTICS)TokenInformation;
723 PtrTokenStatistics->TokenId = Token->TokenId;
724 PtrTokenStatistics->AuthenticationId = Token->AuthenticationId;
725 PtrTokenStatistics->ExpirationTime = Token->ExpirationTime;
726 PtrTokenStatistics->TokenType = Token->TokenType;
727 PtrTokenStatistics->ImpersonationLevel = Token->ImpersonationLevel;
728 PtrTokenStatistics->DynamicCharged = Token->DynamicCharged;
729 PtrTokenStatistics->DynamicAvailable = Token->DynamicAvailable;
730 PtrTokenStatistics->GroupCount = Token->UserAndGroupCount - 1;
731 PtrTokenStatistics->PrivilegeCount = Token->PrivilegeCount;
732 PtrTokenStatistics->ModifiedId = Token->ModifiedId;
733
734 Status = STATUS_SUCCESS;
735 }
736 break;
737 }
738
739 ObDereferenceObject(Token);
740
741 return(Status);
742 }
743
744 /*
745 * NtSetTokenInformation: Partly implemented.
746 * Unimplemented:
747 * TokenOrigin, TokenDefaultDacl, TokenSessionId
748 */
749
750 NTSTATUS STDCALL
751 NtSetInformationToken(IN HANDLE TokenHandle,
752 IN TOKEN_INFORMATION_CLASS TokenInformationClass,
753 OUT PVOID TokenInformation,
754 IN ULONG TokenInformationLength)
755 {
756 NTSTATUS Status;
757 PACCESS_TOKEN Token;
758 TOKEN_OWNER TokenOwnerSet = { 0 };
759 TOKEN_PRIMARY_GROUP TokenPrimaryGroupSet = { 0 };
760 DWORD NeededAccess = 0;
761
762 switch (TokenInformationClass)
763 {
764 case TokenOwner:
765 case TokenPrimaryGroup:
766 NeededAccess = TOKEN_ADJUST_DEFAULT;
767 break;
768
769 default:
770 return STATUS_NOT_IMPLEMENTED;
771 }
772
773 Status = ObReferenceObjectByHandle(TokenHandle,
774 NeededAccess,
775 SepTokenObjectType,
776 UserMode,
777 (PVOID*)&Token,
778 NULL);
779 if (!NT_SUCCESS(Status))
780 {
781 return(Status);
782 }
783
784 switch (TokenInformationClass)
785 {
786 case TokenOwner:
787 MmCopyFromCaller( &TokenOwnerSet, TokenInformation,
788 min(sizeof(TokenOwnerSet),TokenInformationLength) );
789 RtlCopySid(TokenInformationLength - sizeof(TOKEN_OWNER),
790 Token->UserAndGroups[Token->DefaultOwnerIndex].Sid,
791 TokenOwnerSet.Owner);
792 Status = STATUS_SUCCESS;
793 DPRINT("NtSetInformationToken(TokenOwner)\n");
794 break;
795
796 case TokenPrimaryGroup:
797 MmCopyFromCaller( &TokenPrimaryGroupSet, TokenInformation,
798 min(sizeof(TokenPrimaryGroupSet),
799 TokenInformationLength) );
800 RtlCopySid(TokenInformationLength - sizeof(TOKEN_PRIMARY_GROUP),
801 Token->PrimaryGroup,
802 TokenPrimaryGroupSet.PrimaryGroup);
803 Status = STATUS_SUCCESS;
804 DPRINT("NtSetInformationToken(TokenPrimaryGroup),"
805 "Token->PrimaryGroup = 0x%08x\n", Token->PrimaryGroup);
806 break;
807
808 default:
809 Status = STATUS_NOT_IMPLEMENTED;
810 break;
811 }
812
813 ObDereferenceObject(Token);
814
815 return(Status);
816 }
817
818
819 /*
820 * @implemented
821 */
822 NTSTATUS STDCALL
823 NtDuplicateToken(IN HANDLE ExistingTokenHandle,
824 IN ACCESS_MASK DesiredAccess,
825 IN POBJECT_ATTRIBUTES ObjectAttributes,
826 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
827 IN TOKEN_TYPE TokenType,
828 OUT PHANDLE NewTokenHandle)
829 {
830 PACCESS_TOKEN Token;
831 PACCESS_TOKEN NewToken;
832 NTSTATUS Status;
833 ULONG ExistingImpersonationLevel;
834
835 Status = ObReferenceObjectByHandle(ExistingTokenHandle,
836 TOKEN_DUPLICATE,
837 SepTokenObjectType,
838 UserMode,
839 (PVOID*)&Token,
840 NULL);
841 if (!NT_SUCCESS(Status))
842 {
843 DPRINT1 ("Failed to reference token (Status %lx)\n", Status);
844 return Status;
845 }
846
847 ExistingImpersonationLevel = Token->ImpersonationLevel;
848 Status = SepDuplicateToken(Token,
849 ObjectAttributes,
850 ImpersonationLevel,
851 TokenType,
852 ExistingImpersonationLevel,
853 KeGetPreviousMode(),
854 &NewToken);
855 if (!NT_SUCCESS(Status))
856 {
857 DPRINT1 ("Failed to duplicate token (Status %lx)\n", Status);
858 return Status;
859 }
860
861 return STATUS_SUCCESS;
862 }
863
864 VOID SepAdjustGroups(PACCESS_TOKEN Token,
865 ULONG a,
866 BOOLEAN ResetToDefault,
867 PSID_AND_ATTRIBUTES Groups,
868 ULONG b,
869 KPROCESSOR_MODE PreviousMode,
870 ULONG c,
871 PULONG d,
872 PULONG e,
873 PULONG f)
874 {
875 UNIMPLEMENTED;
876 }
877
878
879 NTSTATUS STDCALL
880 NtAdjustGroupsToken(IN HANDLE TokenHandle,
881 IN BOOLEAN ResetToDefault,
882 IN PTOKEN_GROUPS NewState,
883 IN ULONG BufferLength,
884 OUT PTOKEN_GROUPS PreviousState OPTIONAL,
885 OUT PULONG ReturnLength)
886 {
887 #if 0
888 NTSTATUS Status;
889 PACCESS_TOKEN Token;
890 ULONG a;
891 ULONG b;
892 ULONG c;
893
894 Status = ObReferenceObjectByHandle(TokenHandle,
895 ?,
896 SepTokenObjectType,
897 UserMode,
898 (PVOID*)&Token,
899 NULL);
900
901
902 SepAdjustGroups(Token,
903 0,
904 ResetToDefault,
905 NewState->Groups,
906 ?,
907 PreviousState,
908 0,
909 &a,
910 &b,
911 &c);
912 #else
913 UNIMPLEMENTED;
914 return(STATUS_NOT_IMPLEMENTED);
915 #endif
916 }
917
918
919 #if 0
920 NTSTATUS
921 SepAdjustPrivileges(PACCESS_TOKEN Token,
922 ULONG a,
923 KPROCESSOR_MODE PreviousMode,
924 ULONG PrivilegeCount,
925 PLUID_AND_ATTRIBUTES Privileges,
926 PTOKEN_PRIVILEGES* PreviousState,
927 PULONG b,
928 PULONG c,
929 PULONG d)
930 {
931 ULONG i;
932
933 *c = 0;
934
935 if (Token->PrivilegeCount > 0)
936 {
937 for (i = 0; i < Token->PrivilegeCount; i++)
938 {
939 if (PreviousMode != KernelMode)
940 {
941 if (Token->Privileges[i]->Attributes & SE_PRIVILEGE_ENABLED == 0)
942 {
943 if (a != 0)
944 {
945 if (PreviousState != NULL)
946 {
947 memcpy(&PreviousState[i],
948 &Token->Privileges[i],
949 sizeof(LUID_AND_ATTRIBUTES));
950 }
951 Token->Privileges[i].Attributes &= (~SE_PRIVILEGE_ENABLED);
952 }
953 }
954 }
955 }
956 }
957
958 if (PreviousMode != KernelMode)
959 {
960 Token->TokenFlags = Token->TokenFlags & (~1);
961 }
962 else
963 {
964 if (PrivilegeCount <= ?)
965 {
966 }
967 }
968 if (
969 }
970 #endif
971
972
973 /*
974 * @implemented
975 */
976 NTSTATUS STDCALL
977 NtAdjustPrivilegesToken (IN HANDLE TokenHandle,
978 IN BOOLEAN DisableAllPrivileges,
979 IN PTOKEN_PRIVILEGES NewState,
980 IN ULONG BufferLength,
981 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL,
982 OUT PULONG ReturnLength OPTIONAL)
983 {
984 // PLUID_AND_ATTRIBUTES Privileges;
985 KPROCESSOR_MODE PreviousMode;
986 // ULONG PrivilegeCount;
987 PACCESS_TOKEN Token;
988 // ULONG Length;
989 ULONG i;
990 ULONG j;
991 ULONG k;
992 #if 0
993 ULONG a;
994 ULONG b;
995 ULONG c;
996 #endif
997 NTSTATUS Status;
998
999 DPRINT ("NtAdjustPrivilegesToken() called\n");
1000
1001 // PrivilegeCount = NewState->PrivilegeCount;
1002 PreviousMode = KeGetPreviousMode ();
1003 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
1004 // PrivilegeCount,
1005 // PreviousMode,
1006 // NULL,
1007 // 0,
1008 // NonPagedPool,
1009 // 1,
1010 // &Privileges,
1011 // &Length);
1012
1013 Status = ObReferenceObjectByHandle (TokenHandle,
1014 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1015 SepTokenObjectType,
1016 PreviousMode,
1017 (PVOID*)&Token,
1018 NULL);
1019 if (!NT_SUCCESS(Status))
1020 {
1021 DPRINT1 ("Failed to reference token (Status %lx)\n", Status);
1022 // SeReleaseLuidAndAttributesArray(Privileges,
1023 // PreviousMode,
1024 // 0);
1025 return Status;
1026 }
1027
1028
1029 #if 0
1030 SepAdjustPrivileges(Token,
1031 0,
1032 PreviousMode,
1033 PrivilegeCount,
1034 Privileges,
1035 PreviousState,
1036 &a,
1037 &b,
1038 &c);
1039 #endif
1040
1041 k = 0;
1042 if (DisableAllPrivileges == TRUE)
1043 {
1044 for (i = 0; i < Token->PrivilegeCount; i++)
1045 {
1046 if (Token->Privileges[i].Attributes != 0)
1047 {
1048 DPRINT ("Attributes differ\n");
1049
1050 /* Save current privilege */
1051 if (PreviousState != NULL && k < PreviousState->PrivilegeCount)
1052 {
1053 PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
1054 PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
1055 k++;
1056 }
1057
1058 /* Update current privlege */
1059 Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
1060 }
1061 }
1062 }
1063 else
1064 {
1065 for (i = 0; i < Token->PrivilegeCount; i++)
1066 {
1067 for (j = 0; j < NewState->PrivilegeCount; j++)
1068 {
1069 if (Token->Privileges[i].Luid.LowPart == NewState->Privileges[j].Luid.LowPart &&
1070 Token->Privileges[i].Luid.HighPart == NewState->Privileges[j].Luid.HighPart)
1071 {
1072 DPRINT ("Found privilege\n");
1073
1074 if ((Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) !=
1075 (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED))
1076 {
1077 DPRINT ("Attributes differ\n");
1078 DPRINT ("Current attributes %lx desired attributes %lx\n",
1079 Token->Privileges[i].Attributes,
1080 NewState->Privileges[j].Attributes);
1081
1082 /* Save current privilege */
1083 if (PreviousState != NULL && k < PreviousState->PrivilegeCount)
1084 {
1085 PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
1086 PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
1087 k++;
1088 }
1089
1090 /* Update current privlege */
1091 Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
1092 Token->Privileges[i].Attributes |=
1093 (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED);
1094 DPRINT ("New attributes %lx\n",
1095 Token->Privileges[i].Attributes);
1096 }
1097 }
1098 }
1099 }
1100 }
1101
1102 if (ReturnLength != NULL)
1103 {
1104 *ReturnLength = sizeof(TOKEN_PRIVILEGES) +
1105 (sizeof(LUID_AND_ATTRIBUTES) * (k - 1));
1106 }
1107
1108 ObDereferenceObject (Token);
1109
1110 // SeReleaseLuidAndAttributesArray(Privileges,
1111 // PreviousMode,
1112 // 0);
1113
1114 DPRINT ("NtAdjustPrivilegesToken() done\n");
1115
1116 if (k < NewState->PrivilegeCount)
1117 {
1118 return STATUS_NOT_ALL_ASSIGNED;
1119 }
1120
1121 return STATUS_SUCCESS;
1122 }
1123
1124
1125 NTSTATUS
1126 SepCreateSystemProcessToken(struct _EPROCESS* Process)
1127 {
1128 NTSTATUS Status;
1129 ULONG uSize;
1130 ULONG i;
1131
1132 ULONG uLocalSystemLength = RtlLengthSid(SeLocalSystemSid);
1133 ULONG uWorldLength = RtlLengthSid(SeWorldSid);
1134 ULONG uAuthUserLength = RtlLengthSid(SeAuthenticatedUserSid);
1135 ULONG uAdminsLength = RtlLengthSid(SeAliasAdminsSid);
1136
1137 PACCESS_TOKEN AccessToken;
1138
1139 PVOID SidArea;
1140
1141 /*
1142 * Initialize the token
1143 */
1144 Status = ObCreateObject(KernelMode,
1145 SepTokenObjectType,
1146 NULL,
1147 KernelMode,
1148 NULL,
1149 sizeof(ACCESS_TOKEN),
1150 0,
1151 0,
1152 (PVOID*)&AccessToken);
1153 if (!NT_SUCCESS(Status))
1154 {
1155 return(Status);
1156 }
1157
1158 Status = NtAllocateLocallyUniqueId(&AccessToken->TokenId);
1159 if (!NT_SUCCESS(Status))
1160 {
1161 ObDereferenceObject(AccessToken);
1162 return(Status);
1163 }
1164
1165 Status = NtAllocateLocallyUniqueId(&AccessToken->ModifiedId);
1166 if (!NT_SUCCESS(Status))
1167 {
1168 ObDereferenceObject(AccessToken);
1169 return(Status);
1170 }
1171
1172 AccessToken->AuthenticationId.LowPart = SYSTEM_LUID;
1173 AccessToken->AuthenticationId.HighPart = 0;
1174
1175 AccessToken->TokenType = TokenPrimary;
1176 AccessToken->ImpersonationLevel = SecurityDelegation;
1177 AccessToken->TokenSource.SourceIdentifier.LowPart = 0;
1178 AccessToken->TokenSource.SourceIdentifier.HighPart = 0;
1179 memcpy(AccessToken->TokenSource.SourceName, "SeMgr\0\0\0", 8);
1180 AccessToken->ExpirationTime.QuadPart = -1;
1181 AccessToken->UserAndGroupCount = 4;
1182
1183 uSize = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
1184 uSize += uLocalSystemLength;
1185 uSize += uWorldLength;
1186 uSize += uAuthUserLength;
1187 uSize += uAdminsLength;
1188
1189 AccessToken->UserAndGroups =
1190 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1191 uSize,
1192 TAG('T', 'O', 'K', 'u'));
1193 SidArea = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
1194
1195 i = 0;
1196 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1197 AccessToken->UserAndGroups[i++].Attributes = 0;
1198 RtlCopySid(uLocalSystemLength, SidArea, SeLocalSystemSid);
1199 SidArea = (char*)SidArea + uLocalSystemLength;
1200
1201 AccessToken->DefaultOwnerIndex = i;
1202 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1203 AccessToken->PrimaryGroup = (PSID) SidArea;
1204 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT;
1205 Status = RtlCopySid(uAdminsLength, SidArea, SeAliasAdminsSid);
1206 SidArea = (char*)SidArea + uAdminsLength;
1207
1208 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1209 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
1210 RtlCopySid(uWorldLength, SidArea, SeWorldSid);
1211 SidArea = (char*)SidArea + uWorldLength;
1212
1213 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1214 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
1215 RtlCopySid(uAuthUserLength, SidArea, SeAuthenticatedUserSid);
1216 SidArea = (char*)SidArea + uAuthUserLength;
1217
1218 AccessToken->PrivilegeCount = 20;
1219
1220 uSize = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
1221 AccessToken->Privileges =
1222 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1223 uSize,
1224 TAG('T', 'O', 'K', 'p'));
1225
1226 i = 0;
1227 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1228 AccessToken->Privileges[i++].Luid = SeTcbPrivilege;
1229
1230 AccessToken->Privileges[i].Attributes = 0;
1231 AccessToken->Privileges[i++].Luid = SeCreateTokenPrivilege;
1232
1233 AccessToken->Privileges[i].Attributes = 0;
1234 AccessToken->Privileges[i++].Luid = SeTakeOwnershipPrivilege;
1235
1236 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1237 AccessToken->Privileges[i++].Luid = SeCreatePagefilePrivilege;
1238
1239 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1240 AccessToken->Privileges[i++].Luid = SeLockMemoryPrivilege;
1241
1242 AccessToken->Privileges[i].Attributes = 0;
1243 AccessToken->Privileges[i++].Luid = SeAssignPrimaryTokenPrivilege;
1244
1245 AccessToken->Privileges[i].Attributes = 0;
1246 AccessToken->Privileges[i++].Luid = SeIncreaseQuotaPrivilege;
1247
1248 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1249 AccessToken->Privileges[i++].Luid = SeIncreaseBasePriorityPrivilege;
1250
1251 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1252 AccessToken->Privileges[i++].Luid = SeCreatePermanentPrivilege;
1253
1254 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1255 AccessToken->Privileges[i++].Luid = SeDebugPrivilege;
1256
1257 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1258 AccessToken->Privileges[i++].Luid = SeAuditPrivilege;
1259
1260 AccessToken->Privileges[i].Attributes = 0;
1261 AccessToken->Privileges[i++].Luid = SeSecurityPrivilege;
1262
1263 AccessToken->Privileges[i].Attributes = 0;
1264 AccessToken->Privileges[i++].Luid = SeSystemEnvironmentPrivilege;
1265
1266 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1267 AccessToken->Privileges[i++].Luid = SeChangeNotifyPrivilege;
1268
1269 AccessToken->Privileges[i].Attributes = 0;
1270 AccessToken->Privileges[i++].Luid = SeBackupPrivilege;
1271
1272 AccessToken->Privileges[i].Attributes = 0;
1273 AccessToken->Privileges[i++].Luid = SeRestorePrivilege;
1274
1275 AccessToken->Privileges[i].Attributes = 0;
1276 AccessToken->Privileges[i++].Luid = SeShutdownPrivilege;
1277
1278 AccessToken->Privileges[i].Attributes = 0;
1279 AccessToken->Privileges[i++].Luid = SeLoadDriverPrivilege;
1280
1281 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1282 AccessToken->Privileges[i++].Luid = SeProfileSingleProcessPrivilege;
1283
1284 AccessToken->Privileges[i].Attributes = 0;
1285 AccessToken->Privileges[i++].Luid = SeSystemtimePrivilege;
1286 #if 0
1287 AccessToken->Privileges[i].Attributes = 0;
1288 AccessToken->Privileges[i++].Luid = SeUndockPrivilege;
1289
1290 AccessToken->Privileges[i].Attributes = 0;
1291 AccessToken->Privileges[i++].Luid = SeManageVolumePrivilege;
1292 #endif
1293
1294 assert( i == 20 );
1295
1296 uSize = sizeof(ACL);
1297 uSize += sizeof(ACE) + uLocalSystemLength;
1298 uSize += sizeof(ACE) + uAdminsLength;
1299 uSize = (uSize & (~3)) + 8;
1300 AccessToken->DefaultDacl =
1301 (PACL) ExAllocatePoolWithTag(NonPagedPool,
1302 uSize,
1303 TAG('T', 'O', 'K', 'd'));
1304 Status = RtlCreateAcl(AccessToken->DefaultDacl, uSize, ACL_REVISION);
1305 if ( NT_SUCCESS(Status) )
1306 {
1307 Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid);
1308 }
1309
1310 if ( NT_SUCCESS(Status) )
1311 {
1312 Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_READ|GENERIC_EXECUTE|READ_CONTROL, SeAliasAdminsSid);
1313 }
1314
1315 if ( ! NT_SUCCESS(Status) )
1316 {
1317 ObDereferenceObject(AccessToken);
1318 return Status;
1319 }
1320
1321 Process->Token = AccessToken;
1322 return(STATUS_SUCCESS);
1323 }
1324
1325
1326 NTSTATUS STDCALL
1327 NtCreateToken(OUT PHANDLE UnsafeTokenHandle,
1328 IN ACCESS_MASK DesiredAccess,
1329 IN POBJECT_ATTRIBUTES UnsafeObjectAttributes,
1330 IN TOKEN_TYPE TokenType,
1331 IN PLUID AuthenticationId,
1332 IN PLARGE_INTEGER ExpirationTime,
1333 IN PTOKEN_USER TokenUser,
1334 IN PTOKEN_GROUPS TokenGroups,
1335 IN PTOKEN_PRIVILEGES TokenPrivileges,
1336 IN PTOKEN_OWNER TokenOwner,
1337 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup,
1338 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl,
1339 IN PTOKEN_SOURCE TokenSource)
1340 {
1341 HANDLE TokenHandle;
1342 PACCESS_TOKEN AccessToken;
1343 NTSTATUS Status;
1344 OBJECT_ATTRIBUTES SafeObjectAttributes;
1345 POBJECT_ATTRIBUTES ObjectAttributes;
1346 LUID TokenId;
1347 LUID ModifiedId;
1348 PVOID EndMem;
1349 ULONG uLength;
1350 ULONG i;
1351
1352 Status = MmCopyFromCaller(&SafeObjectAttributes,
1353 UnsafeObjectAttributes,
1354 sizeof(OBJECT_ATTRIBUTES));
1355 if (!NT_SUCCESS(Status))
1356 return(Status);
1357
1358 ObjectAttributes = &SafeObjectAttributes;
1359
1360 Status = ZwAllocateLocallyUniqueId(&TokenId);
1361 if (!NT_SUCCESS(Status))
1362 return(Status);
1363
1364 Status = ZwAllocateLocallyUniqueId(&ModifiedId);
1365 if (!NT_SUCCESS(Status))
1366 return(Status);
1367
1368 Status = ObCreateObject(ExGetPreviousMode(),
1369 SepTokenObjectType,
1370 ObjectAttributes,
1371 ExGetPreviousMode(),
1372 NULL,
1373 sizeof(ACCESS_TOKEN),
1374 0,
1375 0,
1376 (PVOID*)&AccessToken);
1377 if (!NT_SUCCESS(Status))
1378 {
1379 DPRINT1("ObCreateObject() failed (Status %lx)\n");
1380 return(Status);
1381 }
1382
1383 Status = ObInsertObject ((PVOID)AccessToken,
1384 NULL,
1385 DesiredAccess,
1386 0,
1387 NULL,
1388 &TokenHandle);
1389 if (!NT_SUCCESS(Status))
1390 {
1391 DPRINT1("ObInsertObject() failed (Status %lx)\n");
1392 ObDereferenceObject (AccessToken);
1393 return Status;
1394 }
1395
1396 RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
1397 &TokenSource->SourceIdentifier);
1398 memcpy(AccessToken->TokenSource.SourceName,
1399 TokenSource->SourceName,
1400 sizeof(TokenSource->SourceName));
1401
1402 RtlCopyLuid(&AccessToken->TokenId, &TokenId);
1403 RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
1404 AccessToken->ExpirationTime = *ExpirationTime;
1405 RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
1406
1407 AccessToken->UserAndGroupCount = TokenGroups->GroupCount + 1;
1408 AccessToken->PrivilegeCount = TokenPrivileges->PrivilegeCount;
1409 AccessToken->UserAndGroups = 0;
1410 AccessToken->Privileges = 0;
1411
1412 AccessToken->TokenType = TokenType;
1413 AccessToken->ImpersonationLevel = ObjectAttributes->SecurityQualityOfService->ImpersonationLevel;
1414
1415 /*
1416 * Normally we would just point these members into the variable information
1417 * area; however, our ObCreateObject() call can't allocate a variable information
1418 * area, so we allocate them seperately and provide a destroy function.
1419 */
1420
1421 uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
1422 uLength += RtlLengthSid(TokenUser->User.Sid);
1423 for (i = 0; i < TokenGroups->GroupCount; i++)
1424 uLength += RtlLengthSid(TokenGroups->Groups[i].Sid);
1425
1426 AccessToken->UserAndGroups =
1427 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1428 uLength,
1429 TAG('T', 'O', 'K', 'u'));
1430
1431 EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
1432
1433 Status = RtlCopySidAndAttributesArray(1,
1434 &TokenUser->User,
1435 uLength,
1436 AccessToken->UserAndGroups,
1437 EndMem,
1438 &EndMem,
1439 &uLength);
1440 if (NT_SUCCESS(Status))
1441 {
1442 Status = RtlCopySidAndAttributesArray(TokenGroups->GroupCount,
1443 TokenGroups->Groups,
1444 uLength,
1445 &AccessToken->UserAndGroups[1],
1446 EndMem,
1447 &EndMem,
1448 &uLength);
1449 }
1450
1451 if (NT_SUCCESS(Status))
1452 {
1453 Status = SepFindPrimaryGroupAndDefaultOwner(
1454 AccessToken,
1455 TokenPrimaryGroup->PrimaryGroup,
1456 TokenOwner->Owner);
1457 }
1458
1459 if (NT_SUCCESS(Status))
1460 {
1461 uLength = TokenPrivileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
1462 AccessToken->Privileges =
1463 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1464 uLength,
1465 TAG('T', 'O', 'K', 'p'));
1466
1467 for (i = 0; i < TokenPrivileges->PrivilegeCount; i++)
1468 {
1469 Status = MmCopyFromCaller(&AccessToken->Privileges[i],
1470 &TokenPrivileges->Privileges[i],
1471 sizeof(LUID_AND_ATTRIBUTES));
1472 if (!NT_SUCCESS(Status))
1473 break;
1474 }
1475 }
1476
1477 if (NT_SUCCESS(Status))
1478 {
1479 AccessToken->DefaultDacl =
1480 (PACL) ExAllocatePoolWithTag(NonPagedPool,
1481 TokenDefaultDacl->DefaultDacl->AclSize,
1482 TAG('T', 'O', 'K', 'd'));
1483 memcpy(AccessToken->DefaultDacl,
1484 TokenDefaultDacl->DefaultDacl,
1485 TokenDefaultDacl->DefaultDacl->AclSize);
1486 }
1487
1488 ObDereferenceObject(AccessToken);
1489
1490 if (NT_SUCCESS(Status))
1491 {
1492 Status = MmCopyToCaller(UnsafeTokenHandle,
1493 &TokenHandle,
1494 sizeof(HANDLE));
1495 }
1496
1497 if (!NT_SUCCESS(Status))
1498 {
1499 ZwClose(TokenHandle);
1500 return(Status);
1501 }
1502
1503 return(STATUS_SUCCESS);
1504 }
1505
1506
1507 /*
1508 * @implemented
1509 */
1510 SECURITY_IMPERSONATION_LEVEL STDCALL
1511 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token)
1512 {
1513 return(Token->ImpersonationLevel);
1514 }
1515
1516
1517 /*
1518 * @implemented
1519 */
1520 TOKEN_TYPE STDCALL
1521 SeTokenType(IN PACCESS_TOKEN Token)
1522 {
1523 return(Token->TokenType);
1524 }
1525
1526 /* EOF */