ntoskrnl/ps/process.c
[reactos.git] / reactos / ntoskrnl / se / token.c
1 /* $Id: token.c,v 1.17 2002/06/17 22:52:32 joeg 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 #include <ddk/ntddk.h>
16 #include <internal/ps.h>
17 #include <internal/se.h>
18 #include <internal/safe.h>
19
20 #define NDEBUG
21 #include <internal/debug.h>
22
23 /* GLOBALS *******************************************************************/
24
25 POBJECT_TYPE SepTokenObjectType = NULL;
26
27 static GENERIC_MAPPING SepTokenMapping = {TOKEN_READ,
28 TOKEN_WRITE,
29 TOKEN_EXECUTE,
30 TOKEN_ALL_ACCESS};
31
32 #define SYSTEM_LUID 0x3E7;
33
34 /* FUNCTIONS *****************************************************************/
35
36 VOID SepFreeProxyData(PVOID ProxyData)
37 {
38 UNIMPLEMENTED;
39 }
40
41 NTSTATUS SepCopyProxyData(PVOID* Dest, PVOID Src)
42 {
43 UNIMPLEMENTED;
44 }
45
46 NTSTATUS SeExchangePrimaryToken(PEPROCESS Process,
47 PACCESS_TOKEN NewToken,
48 PACCESS_TOKEN* OldTokenP)
49 {
50 PACCESS_TOKEN OldToken;
51
52 if (NewToken->TokenType != TokenPrimary)
53 {
54 return(STATUS_UNSUCCESSFUL);
55 }
56 if (NewToken->TokenInUse != 0)
57 {
58 return(STATUS_UNSUCCESSFUL);
59 }
60 OldToken = Process->Token;
61 Process->Token = NewToken;
62 NewToken->TokenInUse = 1;
63 ObReferenceObjectByPointer(NewToken,
64 TOKEN_ALL_ACCESS,
65 SepTokenObjectType,
66 KernelMode);
67 OldToken->TokenInUse = 0;
68 *OldTokenP = OldToken;
69 return(STATUS_SUCCESS);
70 }
71
72
73 NTSTATUS
74 RtlCopySidAndAttributesArray(ULONG Count, // ebp + 8
75 PSID_AND_ATTRIBUTES Src, // ebp + C
76 ULONG SidAreaSize, // ebp + 10
77 PSID_AND_ATTRIBUTES Dest, // ebp + 14
78 PVOID SidArea, // ebp + 18
79 PVOID* RemainingSidArea, // ebp + 1C
80 PULONG RemainingSidAreaSize) // ebp + 20
81 {
82 ULONG Length; // ebp - 4
83 ULONG i;
84
85 Length = SidAreaSize;
86
87 for (i=0; i<Count; i++)
88 {
89 if (RtlLengthSid(Src[i].Sid) > Length)
90 {
91 return(STATUS_BUFFER_TOO_SMALL);
92 }
93 Length = Length - RtlLengthSid(Src[i].Sid);
94 Dest[i].Sid = SidArea;
95 Dest[i].Attributes = Src[i].Attributes;
96 RtlCopySid(RtlLengthSid(Src[i].Sid), SidArea, Src[i].Sid);
97 SidArea = SidArea + RtlLengthSid(Src[i].Sid);
98 }
99 *RemainingSidArea = SidArea;
100 *RemainingSidAreaSize = Length;
101 return(STATUS_SUCCESS);
102 }
103
104
105 static ULONG
106 RtlLengthSidAndAttributes(ULONG Count,
107 PSID_AND_ATTRIBUTES Src)
108 {
109 ULONG i;
110 ULONG uLength;
111
112 uLength = Count * sizeof(SID_AND_ATTRIBUTES);
113 for (i = 0; i < Count; i++)
114 uLength += RtlLengthSid(Src[i].Sid);
115
116 return(uLength);
117 }
118
119
120 NTSTATUS
121 SepFindPrimaryGroupAndDefaultOwner(PACCESS_TOKEN Token,
122 PSID PrimaryGroup,
123 PSID DefaultOwner)
124 {
125 ULONG i;
126
127 Token->PrimaryGroup = 0;
128
129 if (DefaultOwner)
130 {
131 Token->DefaultOwnerIndex = Token->UserAndGroupCount;
132 }
133
134 /* Validate and set the primary group and user pointers */
135 for (i = 0; i < Token->UserAndGroupCount; i++)
136 {
137 if (DefaultOwner &&
138 RtlEqualSid(Token->UserAndGroups[i].Sid, DefaultOwner))
139 {
140 Token->DefaultOwnerIndex = i;
141 }
142
143 if (RtlEqualSid(Token->UserAndGroups[i].Sid, PrimaryGroup))
144 {
145 Token->PrimaryGroup = Token->UserAndGroups[i].Sid;
146 }
147 }
148
149 if (Token->DefaultOwnerIndex == Token->UserAndGroupCount)
150 {
151 return(STATUS_INVALID_OWNER);
152 }
153
154 if (Token->PrimaryGroup == 0)
155 {
156 return(STATUS_INVALID_PRIMARY_GROUP);
157 }
158
159 return(STATUS_SUCCESS);
160 }
161
162
163 NTSTATUS
164 SepDuplicateToken(PACCESS_TOKEN Token,
165 POBJECT_ATTRIBUTES ObjectAttributes,
166 TOKEN_TYPE TokenType,
167 SECURITY_IMPERSONATION_LEVEL Level,
168 SECURITY_IMPERSONATION_LEVEL ExistingLevel,
169 KPROCESSOR_MODE PreviousMode,
170 PACCESS_TOKEN* NewAccessToken)
171 {
172 NTSTATUS Status;
173 ULONG uLength;
174 ULONG i;
175
176 PVOID EndMem;
177
178 PACCESS_TOKEN AccessToken;
179
180 Status = ObCreateObject(0,
181 TOKEN_ALL_ACCESS,
182 ObjectAttributes,
183 SepTokenObjectType,
184 (PVOID*)&AccessToken);
185 if (!NT_SUCCESS(Status))
186 {
187 DPRINT1("ObCreateObject() failed (Status %lx)\n");
188 return(Status);
189 }
190
191 Status = ZwAllocateLocallyUniqueId(&AccessToken->TokenId);
192 if (!NT_SUCCESS(Status))
193 {
194 ObDereferenceObject(AccessToken);
195 return(Status);
196 }
197
198 Status = ZwAllocateLocallyUniqueId(&AccessToken->ModifiedId);
199 if (!NT_SUCCESS(Status))
200 {
201 ObDereferenceObject(AccessToken);
202 return(Status);
203 }
204
205 AccessToken->TokenInUse = 0;
206 AccessToken->TokenType = TokenType;
207 AccessToken->ImpersonationLevel = Level;
208 AccessToken->AuthenticationId.QuadPart = SYSTEM_LUID;
209
210 AccessToken->TokenSource.SourceIdentifier.QuadPart = Token->TokenSource.SourceIdentifier.QuadPart;
211 memcpy(AccessToken->TokenSource.SourceName, Token->TokenSource.SourceName, sizeof(Token->TokenSource.SourceName));
212 AccessToken->ExpirationTime.QuadPart = Token->ExpirationTime.QuadPart;
213 AccessToken->UserAndGroupCount = Token->UserAndGroupCount;
214 AccessToken->DefaultOwnerIndex = Token->DefaultOwnerIndex;
215
216 uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
217 for (i = 0; i < Token->UserAndGroupCount; i++)
218 uLength += RtlLengthSid(Token->UserAndGroups[i].Sid);
219
220 AccessToken->UserAndGroups =
221 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
222 uLength,
223 TAG('T', 'O', 'K', 'u'));
224
225 EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
226
227 Status = RtlCopySidAndAttributesArray(AccessToken->UserAndGroupCount,
228 Token->UserAndGroups,
229 uLength,
230 AccessToken->UserAndGroups,
231 EndMem,
232 &EndMem,
233 &uLength);
234 if (NT_SUCCESS(Status))
235 {
236 Status = SepFindPrimaryGroupAndDefaultOwner(
237 AccessToken,
238 Token->PrimaryGroup,
239 0);
240 }
241
242 if (NT_SUCCESS(Status))
243 {
244 AccessToken->PrivilegeCount = Token->PrivilegeCount;
245
246 uLength = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
247 AccessToken->Privileges =
248 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
249 uLength,
250 TAG('T', 'O', 'K', 'p'));
251
252 for (i = 0; i < AccessToken->PrivilegeCount; i++)
253 {
254 RtlCopyLuid(&AccessToken->Privileges[i].Luid,
255 &Token->Privileges[i].Luid);
256 AccessToken->Privileges[i].Attributes =
257 Token->Privileges[i].Attributes;
258 }
259
260 if ( Token->DefaultDacl )
261 {
262 AccessToken->DefaultDacl =
263 (PACL) ExAllocatePoolWithTag(NonPagedPool,
264 Token->DefaultDacl->AclSize,
265 TAG('T', 'O', 'K', 'd'));
266 memcpy(AccessToken->DefaultDacl,
267 Token->DefaultDacl,
268 Token->DefaultDacl->AclSize);
269 }
270 else
271 {
272 AccessToken->DefaultDacl = 0;
273 }
274 }
275
276 if ( NT_SUCCESS(Status) )
277 {
278 *NewAccessToken = AccessToken;
279 return(STATUS_SUCCESS);
280 }
281
282 ObDereferenceObject(AccessToken);
283 return(Status);
284 }
285
286
287 NTSTATUS
288 SepInitializeNewProcess(struct _EPROCESS* NewProcess,
289 struct _EPROCESS* ParentProcess)
290 {
291 NTSTATUS Status;
292 PACCESS_TOKEN pNewToken;
293 PACCESS_TOKEN pParentToken;
294
295 OBJECT_ATTRIBUTES ObjectAttributes;
296
297 pParentToken = (PACCESS_TOKEN) ParentProcess->Token;
298
299 InitializeObjectAttributes(&ObjectAttributes,
300 NULL,
301 0,
302 NULL,
303 NULL);
304
305 Status = SepDuplicateToken(pParentToken,
306 &ObjectAttributes,
307 TokenPrimary,
308 pParentToken->ImpersonationLevel,
309 pParentToken->ImpersonationLevel,
310 KernelMode,
311 &pNewToken);
312 if ( ! NT_SUCCESS(Status) )
313 return Status;
314
315 NewProcess->Token = pNewToken;
316 return(STATUS_SUCCESS);
317 }
318
319
320 NTSTATUS SeCopyClientToken(PACCESS_TOKEN Token,
321 SECURITY_IMPERSONATION_LEVEL Level,
322 KPROCESSOR_MODE PreviousMode,
323 PACCESS_TOKEN* NewToken)
324 {
325 NTSTATUS Status;
326 OBJECT_ATTRIBUTES ObjectAttributes;
327
328 InitializeObjectAttributes(&ObjectAttributes,
329 NULL,
330 0,
331 NULL,
332 NULL);
333 Status = SepDuplicateToken(Token,
334 &ObjectAttributes,
335 0,
336 SecurityIdentification,
337 Level,
338 PreviousMode,
339 NewToken);
340 return(Status);
341 }
342
343
344 NTSTATUS STDCALL
345 SeCreateClientSecurity(IN struct _ETHREAD *Thread,
346 IN PSECURITY_QUALITY_OF_SERVICE Qos,
347 IN BOOLEAN RemoteClient,
348 OUT PSECURITY_CLIENT_CONTEXT ClientContext)
349 {
350 TOKEN_TYPE TokenType;
351 UCHAR b;
352 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
353 PACCESS_TOKEN Token;
354 ULONG g;
355 PACCESS_TOKEN NewToken;
356
357 Token = PsReferenceEffectiveToken(Thread,
358 &TokenType,
359 &b,
360 &ImpersonationLevel);
361 if (TokenType != 2)
362 {
363 ClientContext->DirectAccessEffectiveOnly = Qos->EffectiveOnly;
364 }
365 else
366 {
367 if (Qos->ImpersonationLevel > ImpersonationLevel)
368 {
369 if (Token != NULL)
370 {
371 ObDereferenceObject(Token);
372 }
373 return(STATUS_UNSUCCESSFUL);
374 }
375 if (ImpersonationLevel == 0 ||
376 ImpersonationLevel == 1 ||
377 (RemoteClient != FALSE && ImpersonationLevel != 3))
378 {
379 if (Token != NULL)
380 {
381 ObDereferenceObject(Token);
382 }
383 return(STATUS_UNSUCCESSFUL);
384 }
385 if (b != 0 ||
386 Qos->EffectiveOnly != 0)
387 {
388 ClientContext->DirectAccessEffectiveOnly = TRUE;
389 }
390 else
391 {
392 ClientContext->DirectAccessEffectiveOnly = FALSE;
393 }
394 }
395
396 if (Qos->ContextTrackingMode == 0)
397 {
398 ClientContext->DirectlyAccessClientToken = FALSE;
399 g = SeCopyClientToken(Token, ImpersonationLevel, 0, &NewToken);
400 if (g >= 0)
401 {
402 // ObDeleteCapturedInsertInfo(NewToken);
403 }
404 if (TokenType == TokenPrimary || Token != NULL)
405 {
406 ObDereferenceObject(Token);
407 }
408 if (g < 0)
409 {
410 return(g);
411 }
412 }
413 else
414 {
415 ClientContext->DirectlyAccessClientToken = TRUE;
416 if (RemoteClient != FALSE)
417 {
418 // SeGetTokenControlInformation(Token, &ClientContext->Unknown11);
419 }
420 NewToken = Token;
421 }
422 ClientContext->SecurityQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
423 ClientContext->SecurityQos.ImpersonationLevel = Qos->ImpersonationLevel;
424 ClientContext->SecurityQos.ContextTrackingMode = Qos->ContextTrackingMode;
425 ClientContext->SecurityQos.EffectiveOnly = Qos->EffectiveOnly;
426 ClientContext->ServerIsRemote = RemoteClient;
427 ClientContext->Token = NewToken;
428
429 return(STATUS_SUCCESS);
430 }
431
432
433 VOID STDCALL
434 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext,
435 IN PETHREAD ServerThread OPTIONAL)
436 {
437 UCHAR b;
438
439 if (ClientContext->DirectlyAccessClientToken == FALSE)
440 {
441 b = ClientContext->SecurityQos.EffectiveOnly;
442 }
443 else
444 {
445 b = ClientContext->DirectAccessEffectiveOnly;
446 }
447 if (ServerThread == NULL)
448 {
449 ServerThread = PsGetCurrentThread();
450 }
451 PsImpersonateClient(ServerThread,
452 ClientContext->Token,
453 1,
454 (ULONG)b,
455 ClientContext->SecurityQos.ImpersonationLevel);
456 }
457
458
459 VOID STDCALL
460 SepDeleteToken(PVOID ObjectBody)
461 {
462 PACCESS_TOKEN AccessToken = (PACCESS_TOKEN)ObjectBody;
463
464 if (AccessToken->UserAndGroups)
465 ExFreePool(AccessToken->UserAndGroups);
466
467 if (AccessToken->Privileges)
468 ExFreePool(AccessToken->Privileges);
469
470 if (AccessToken->DefaultDacl)
471 ExFreePool(AccessToken->DefaultDacl);
472 }
473
474
475 VOID
476 SepInitializeTokenImplementation(VOID)
477 {
478 SepTokenObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
479
480 SepTokenObjectType->Tag = TAG('T', 'O', 'K', 'T');
481 SepTokenObjectType->MaxObjects = ULONG_MAX;
482 SepTokenObjectType->MaxHandles = ULONG_MAX;
483 SepTokenObjectType->TotalObjects = 0;
484 SepTokenObjectType->TotalHandles = 0;
485 SepTokenObjectType->PagedPoolCharge = 0;
486 SepTokenObjectType->NonpagedPoolCharge = sizeof(ACCESS_TOKEN);
487 SepTokenObjectType->Mapping = &SepTokenMapping;
488 SepTokenObjectType->Dump = NULL;
489 SepTokenObjectType->Open = NULL;
490 SepTokenObjectType->Close = NULL;
491 SepTokenObjectType->Delete = SepDeleteToken;
492 SepTokenObjectType->Parse = NULL;
493 SepTokenObjectType->Security = NULL;
494 SepTokenObjectType->QueryName = NULL;
495 SepTokenObjectType->OkayToClose = NULL;
496 SepTokenObjectType->Create = NULL;
497 SepTokenObjectType->DuplicationNotify = NULL;
498
499 RtlCreateUnicodeString(&SepTokenObjectType->TypeName,
500 L"Token");
501 }
502
503
504 NTSTATUS STDCALL
505 NtQueryInformationToken(IN HANDLE TokenHandle,
506 IN TOKEN_INFORMATION_CLASS TokenInformationClass,
507 OUT PVOID TokenInformation,
508 IN ULONG TokenInformationLength,
509 OUT PULONG ReturnLength)
510 {
511 NTSTATUS Status;
512 PACCESS_TOKEN Token;
513 PVOID UnusedInfo;
514 PVOID EndMem;
515 PTOKEN_GROUPS PtrTokenGroups;
516 PTOKEN_DEFAULT_DACL PtrDefaultDacl;
517 PTOKEN_STATISTICS PtrTokenStatistics;
518 ULONG uLength;
519
520 Status = ObReferenceObjectByHandle(TokenHandle,
521 (TokenInformationClass == TokenSource) ? TOKEN_QUERY_SOURCE : TOKEN_QUERY,
522 SepTokenObjectType,
523 UserMode,
524 (PVOID*)&Token,
525 NULL);
526 if (!NT_SUCCESS(Status))
527 {
528 return(Status);
529 }
530
531 switch (TokenInformationClass)
532 {
533 case TokenUser:
534 DPRINT("NtQueryInformationToken(TokenUser)\n");
535 uLength = RtlLengthSidAndAttributes(1, Token->UserAndGroups);
536 if (TokenInformationLength < uLength)
537 {
538 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
539 if (NT_SUCCESS(Status))
540 Status = STATUS_BUFFER_TOO_SMALL;
541 }
542 else
543 {
544 Status = RtlCopySidAndAttributesArray(1,
545 Token->UserAndGroups,
546 TokenInformationLength,
547 TokenInformation,
548 TokenInformation + 8,
549 &UnusedInfo,
550 &uLength);
551 if (NT_SUCCESS(Status))
552 {
553 uLength = TokenInformationLength - uLength;
554 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
555 }
556 }
557 break;
558
559 case TokenGroups:
560 DPRINT("NtQueryInformationToken(TokenGroups)\n");
561 uLength = RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]) + sizeof(DWORD);
562 if (TokenInformationLength < uLength)
563 {
564 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
565 if (NT_SUCCESS(Status))
566 Status = STATUS_BUFFER_TOO_SMALL;
567 }
568 else
569 {
570 EndMem = TokenInformation + Token->UserAndGroupCount * sizeof(SID_AND_ATTRIBUTES);
571 PtrTokenGroups = (PTOKEN_GROUPS)TokenInformation;
572 PtrTokenGroups->GroupCount = Token->UserAndGroupCount - 1;
573 Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
574 &Token->UserAndGroups[1],
575 TokenInformationLength,
576 PtrTokenGroups->Groups,
577 EndMem,
578 &UnusedInfo,
579 &uLength);
580 if (NT_SUCCESS(Status))
581 {
582 uLength = TokenInformationLength - uLength;
583 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
584 }
585 }
586 break;
587
588 case TokenPrivileges:
589 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
590 uLength = sizeof(DWORD) + Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
591 if (TokenInformationLength < uLength)
592 {
593 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
594 if (NT_SUCCESS(Status))
595 Status = STATUS_BUFFER_TOO_SMALL;
596 }
597 else
598 {
599 ULONG i;
600 TOKEN_PRIVILEGES* pPriv = (TOKEN_PRIVILEGES*)TokenInformation;
601
602 pPriv->PrivilegeCount = Token->PrivilegeCount;
603 for (i = 0; i < Token->PrivilegeCount; i++)
604 {
605 RtlCopyLuid(&pPriv->Privileges[i].Luid, &Token->Privileges[i].Luid);
606 pPriv->Privileges[i].Attributes = Token->Privileges[i].Attributes;
607 }
608 Status = STATUS_SUCCESS;
609 }
610 break;
611
612 case TokenOwner:
613 DPRINT("NtQueryInformationToken(TokenOwner)\n");
614 uLength = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid) + sizeof(TOKEN_OWNER);
615 if (TokenInformationLength < uLength)
616 {
617 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
618 if (NT_SUCCESS(Status))
619 Status = STATUS_BUFFER_TOO_SMALL;
620 }
621 else
622 {
623 ((PTOKEN_OWNER)TokenInformation)->Owner =
624 (PSID)(((PTOKEN_OWNER)TokenInformation) + 1);
625 RtlCopySid(TokenInformationLength - sizeof(TOKEN_OWNER),
626 ((PTOKEN_OWNER)TokenInformation)->Owner,
627 Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
628 Status = STATUS_SUCCESS;
629 }
630 break;
631
632 case TokenPrimaryGroup:
633 DPRINT("NtQueryInformationToken(TokenPrimaryGroup),"
634 "Token->PrimaryGroup = 0x%08x\n", Token->PrimaryGroup);
635 uLength = RtlLengthSid(Token->PrimaryGroup) + sizeof(TOKEN_PRIMARY_GROUP);
636 if (TokenInformationLength < uLength)
637 {
638 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
639 if (NT_SUCCESS(Status))
640 Status = STATUS_BUFFER_TOO_SMALL;
641 }
642 else
643 {
644 ((PTOKEN_PRIMARY_GROUP)TokenInformation)->PrimaryGroup =
645 (PSID)(((PTOKEN_PRIMARY_GROUP)TokenInformation) + 1);
646 RtlCopySid(TokenInformationLength - sizeof(TOKEN_PRIMARY_GROUP),
647 ((PTOKEN_PRIMARY_GROUP)TokenInformation)->PrimaryGroup,
648 Token->PrimaryGroup);
649 Status = STATUS_SUCCESS;
650 }
651 break;
652
653 case TokenDefaultDacl:
654 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
655 PtrDefaultDacl = (PTOKEN_DEFAULT_DACL) TokenInformation;
656 uLength = (Token->DefaultDacl ? Token->DefaultDacl->AclSize : 0) + sizeof(TOKEN_DEFAULT_DACL);
657 if (TokenInformationLength < uLength)
658 {
659 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
660 if (NT_SUCCESS(Status))
661 Status = STATUS_BUFFER_TOO_SMALL;
662 }
663 else if (!Token->DefaultDacl)
664 {
665 PtrDefaultDacl->DefaultDacl = 0;
666 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
667 }
668 else
669 {
670 PtrDefaultDacl->DefaultDacl = (PACL) (PtrDefaultDacl + 1);
671 memmove(PtrDefaultDacl->DefaultDacl,
672 Token->DefaultDacl,
673 Token->DefaultDacl->AclSize);
674 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
675 }
676 break;
677
678 case TokenSource:
679 DPRINT("NtQueryInformationToken(TokenSource)\n");
680 if (TokenInformationLength < sizeof(TOKEN_SOURCE))
681 {
682 uLength = sizeof(TOKEN_SOURCE);
683 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
684 if (NT_SUCCESS(Status))
685 Status = STATUS_BUFFER_TOO_SMALL;
686 }
687 else
688 {
689 Status = MmCopyToCaller(TokenInformation, &Token->TokenSource, sizeof(TOKEN_SOURCE));
690 }
691 break;
692
693 case TokenType:
694 DPRINT("NtQueryInformationToken(TokenType)\n");
695 if (TokenInformationLength < sizeof(TOKEN_TYPE))
696 {
697 uLength = sizeof(TOKEN_TYPE);
698 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
699 if (NT_SUCCESS(Status))
700 Status = STATUS_BUFFER_TOO_SMALL;
701 }
702 else
703 {
704 Status = MmCopyToCaller(TokenInformation, &Token->TokenType, sizeof(TOKEN_TYPE));
705 }
706 break;
707
708 case TokenImpersonationLevel:
709 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
710 if (TokenInformationLength < sizeof(SECURITY_IMPERSONATION_LEVEL))
711 {
712 uLength = sizeof(SECURITY_IMPERSONATION_LEVEL);
713 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
714 if (NT_SUCCESS(Status))
715 Status = STATUS_BUFFER_TOO_SMALL;
716 }
717 else
718 {
719 Status = MmCopyToCaller(TokenInformation, &Token->ImpersonationLevel, sizeof(SECURITY_IMPERSONATION_LEVEL));
720 }
721 break;
722
723 case TokenStatistics:
724 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
725 if (TokenInformationLength < sizeof(TOKEN_STATISTICS))
726 {
727 uLength = sizeof(TOKEN_STATISTICS);
728 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
729 if (NT_SUCCESS(Status))
730 Status = STATUS_BUFFER_TOO_SMALL;
731 }
732 else
733 {
734 PtrTokenStatistics = (PTOKEN_STATISTICS)TokenInformation;
735 PtrTokenStatistics->TokenId = Token->TokenId;
736 PtrTokenStatistics->AuthenticationId = Token->AuthenticationId;
737 PtrTokenStatistics->ExpirationTime = Token->ExpirationTime;
738 PtrTokenStatistics->TokenType = Token->TokenType;
739 PtrTokenStatistics->ImpersonationLevel = Token->ImpersonationLevel;
740 PtrTokenStatistics->DynamicCharged = Token->DynamicCharged;
741 PtrTokenStatistics->DynamicAvailable = Token->DynamicAvailable;
742 PtrTokenStatistics->GroupCount = Token->UserAndGroupCount - 1;
743 PtrTokenStatistics->PrivilegeCount = Token->PrivilegeCount;
744 PtrTokenStatistics->ModifiedId = Token->ModifiedId;
745
746 Status = STATUS_SUCCESS;
747 }
748 break;
749 }
750
751 ObDereferenceObject(Token);
752
753 return(Status);
754 }
755
756
757 NTSTATUS STDCALL
758 NtSetInformationToken(IN HANDLE TokenHandle,
759 IN TOKEN_INFORMATION_CLASS TokenInformationClass,
760 OUT PVOID TokenInformation,
761 IN ULONG TokenInformationLength)
762 {
763 UNIMPLEMENTED;
764 }
765
766
767 NTSTATUS STDCALL
768 NtDuplicateToken(IN HANDLE ExistingTokenHandle,
769 IN ACCESS_MASK DesiredAccess,
770 IN POBJECT_ATTRIBUTES ObjectAttributes,
771 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
772 IN TOKEN_TYPE TokenType,
773 OUT PHANDLE NewTokenHandle)
774 {
775 #if 0
776 PACCESS_TOKEN Token;
777 PACCESS_TOKEN NewToken;
778 NTSTATUS Status;
779 ULONG ExistingImpersonationLevel;
780
781 Status = ObReferenceObjectByHandle(ExistingTokenHandle,
782 TOKEN_DUPLICATE,
783 SepTokenObjectType,
784 UserMode,
785 (PVOID*)&Token,
786 NULL);
787
788 ExistingImpersonationLevel = Token->ImpersonationLevel;
789 SepDuplicateToken(Token,
790 ObjectAttributes,
791 ImpersonationLevel,
792 TokenType,
793 ExistingImpersonationLevel,
794 KeGetPreviousMode(),
795 &NewToken);
796 #else
797 UNIMPLEMENTED;
798 #endif
799 }
800
801 VOID SepAdjustGroups(PACCESS_TOKEN Token,
802 ULONG a,
803 BOOLEAN ResetToDefault,
804 PSID_AND_ATTRIBUTES Groups,
805 ULONG b,
806 KPROCESSOR_MODE PreviousMode,
807 ULONG c,
808 PULONG d,
809 PULONG e,
810 PULONG f)
811 {
812 UNIMPLEMENTED;
813 }
814
815
816 NTSTATUS STDCALL
817 NtAdjustGroupsToken(IN HANDLE TokenHandle,
818 IN BOOLEAN ResetToDefault,
819 IN PTOKEN_GROUPS NewState,
820 IN ULONG BufferLength,
821 OUT PTOKEN_GROUPS PreviousState OPTIONAL,
822 OUT PULONG ReturnLength)
823 {
824 #if 0
825 NTSTATUS Status;
826 PACCESS_TOKEN Token;
827 ULONG a;
828 ULONG b;
829 ULONG c;
830
831 Status = ObReferenceObjectByHandle(TokenHandle,
832 ?,
833 SepTokenObjectType,
834 UserMode,
835 (PVOID*)&Token,
836 NULL);
837
838
839 SepAdjustGroups(Token,
840 0,
841 ResetToDefault,
842 NewState->Groups,
843 ?,
844 PreviousState,
845 0,
846 &a,
847 &b,
848 &c);
849 #else
850 UNIMPLEMENTED;
851 #endif
852 }
853
854
855 #if 0
856 NTSTATUS SepAdjustPrivileges(PACCESS_TOKEN Token, // 0x8
857 ULONG a, // 0xC
858 KPROCESSOR_MODE PreviousMode, // 0x10
859 ULONG PrivilegeCount, // 0x14
860 PLUID_AND_ATTRIBUTES Privileges, // 0x18
861 PTOKEN_PRIVILEGES* PreviousState, // 0x1C
862 PULONG b, // 0x20
863 PULONG c, // 0x24
864 PULONG d) // 0x28
865 {
866 ULONG i;
867
868 *c = 0;
869 if (Token->PrivilegeCount > 0)
870 {
871 for (i=0; i<Token->PrivilegeCount; i++)
872 {
873 if (PreviousMode != 0)
874 {
875 if (!(Token->Privileges[i]->Attributes &
876 SE_PRIVILEGE_ENABLED))
877 {
878 if (a != 0)
879 {
880 if (PreviousState != NULL)
881 {
882 memcpy(&PreviousState[i],
883 &Token->Privileges[i],
884 sizeof(LUID_AND_ATTRIBUTES));
885 }
886 Token->Privileges[i].Attributes =
887 Token->Privileges[i].Attributes &
888 (~SE_PRIVILEGE_ENABLED);
889 }
890 }
891 }
892 }
893 }
894 if (PreviousMode != 0)
895 {
896 Token->TokenFlags = Token->TokenFlags & (~1);
897 }
898 else
899 {
900 if (PrivilegeCount <= ?)
901 {
902
903 }
904 }
905 if (
906 }
907 #endif
908
909
910 NTSTATUS STDCALL
911 NtAdjustPrivilegesToken(IN HANDLE TokenHandle,
912 IN BOOLEAN DisableAllPrivileges,
913 IN PTOKEN_PRIVILEGES NewState,
914 IN ULONG BufferLength,
915 OUT PTOKEN_PRIVILEGES PreviousState,
916 OUT PULONG ReturnLength)
917 {
918 #if 0
919 ULONG PrivilegeCount;
920 ULONG Length;
921 PSID_AND_ATTRIBUTES Privileges;
922 ULONG a;
923 ULONG b;
924 ULONG c;
925
926 PrivilegeCount = NewState->PrivilegeCount;
927
928 SeCaptureLuidAndAttributesArray(NewState->Privileges,
929 &PrivilegeCount,
930 KeGetPreviousMode(),
931 NULL,
932 0,
933 NonPagedPool,
934 1,
935 &Privileges.
936 &Length);
937 SepAdjustPrivileges(Token,
938 0,
939 KeGetPreviousMode(),
940 PrivilegeCount,
941 Privileges,
942 PreviousState,
943 &a,
944 &b,
945 &c);
946 #else
947 UNIMPLEMENTED;
948 #endif
949 }
950
951
952 NTSTATUS
953 SepCreateSystemProcessToken(struct _EPROCESS* Process)
954 {
955 NTSTATUS Status;
956 ULONG uSize;
957 ULONG i;
958
959 ULONG uLocalSystemLength = RtlLengthSid(SeLocalSystemSid);
960 ULONG uWorldLength = RtlLengthSid(SeWorldSid);
961 ULONG uAuthUserLength = RtlLengthSid(SeAuthenticatedUserSid);
962 ULONG uAdminsLength = RtlLengthSid(SeAliasAdminsSid);
963
964 PACCESS_TOKEN AccessToken;
965
966 PVOID SidArea;
967
968 /*
969 * Initialize the token
970 */
971 Status = ObCreateObject(NULL,
972 TOKEN_ALL_ACCESS,
973 NULL,
974 SepTokenObjectType,
975 (PVOID*)&AccessToken);
976
977 Status = ZwAllocateLocallyUniqueId(&AccessToken->TokenId);
978 if (!NT_SUCCESS(Status))
979 {
980 ObDereferenceObject(AccessToken);
981 return(Status);
982 }
983
984 Status = ZwAllocateLocallyUniqueId(&AccessToken->ModifiedId);
985 if (!NT_SUCCESS(Status))
986 {
987 ObDereferenceObject(AccessToken);
988 return(Status);
989 }
990
991 AccessToken->AuthenticationId.QuadPart = SYSTEM_LUID;
992
993 AccessToken->TokenType = TokenPrimary;
994 AccessToken->ImpersonationLevel = SecurityDelegation;
995 AccessToken->TokenSource.SourceIdentifier.QuadPart = 0;
996 memcpy(AccessToken->TokenSource.SourceName, "SeMgr\0\0\0", 8);
997 AccessToken->ExpirationTime.QuadPart = -1;
998 AccessToken->UserAndGroupCount = 4;
999
1000 uSize = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
1001 uSize += uLocalSystemLength;
1002 uSize += uWorldLength;
1003 uSize += uAuthUserLength;
1004 uSize += uAdminsLength;
1005
1006 AccessToken->UserAndGroups =
1007 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1008 uSize,
1009 TAG('T', 'O', 'K', 'u'));
1010 SidArea = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
1011
1012 i = 0;
1013 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1014 AccessToken->UserAndGroups[i++].Attributes = 0;
1015 RtlCopySid(uLocalSystemLength, SidArea, SeLocalSystemSid);
1016 SidArea += uLocalSystemLength;
1017
1018 AccessToken->DefaultOwnerIndex = i;
1019 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1020 AccessToken->PrimaryGroup = (PSID) SidArea;
1021 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT;
1022 Status = RtlCopySid(uAdminsLength, SidArea, SeAliasAdminsSid);
1023 SidArea += uAdminsLength;
1024
1025 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1026 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
1027 RtlCopySid(uWorldLength, SidArea, SeWorldSid);
1028 SidArea += uWorldLength;
1029
1030 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1031 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
1032 RtlCopySid(uAuthUserLength, SidArea, SeAuthenticatedUserSid);
1033 SidArea += uAuthUserLength;
1034
1035 AccessToken->PrivilegeCount = 20;
1036
1037 uSize = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
1038 AccessToken->Privileges =
1039 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1040 uSize,
1041 TAG('T', 'O', 'K', 'p'));
1042
1043 i = 0;
1044 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1045 AccessToken->Privileges[i++].Luid = SeTcbPrivilege;
1046
1047 AccessToken->Privileges[i].Attributes = 0;
1048 AccessToken->Privileges[i++].Luid = SeCreateTokenPrivilege;
1049
1050 AccessToken->Privileges[i].Attributes = 0;
1051 AccessToken->Privileges[i++].Luid = SeTakeOwnershipPrivilege;
1052
1053 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1054 AccessToken->Privileges[i++].Luid = SeCreatePagefilePrivilege;
1055
1056 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1057 AccessToken->Privileges[i++].Luid = SeLockMemoryPrivilege;
1058
1059 AccessToken->Privileges[i].Attributes = 0;
1060 AccessToken->Privileges[i++].Luid = SeAssignPrimaryTokenPrivilege;
1061
1062 AccessToken->Privileges[i].Attributes = 0;
1063 AccessToken->Privileges[i++].Luid = SeIncreaseQuotaPrivilege;
1064
1065 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1066 AccessToken->Privileges[i++].Luid = SeIncreaseBasePriorityPrivilege;
1067
1068 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1069 AccessToken->Privileges[i++].Luid = SeCreatePermanentPrivilege;
1070
1071 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1072 AccessToken->Privileges[i++].Luid = SeDebugPrivilege;
1073
1074 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1075 AccessToken->Privileges[i++].Luid = SeAuditPrivilege;
1076
1077 AccessToken->Privileges[i].Attributes = 0;
1078 AccessToken->Privileges[i++].Luid = SeSecurityPrivilege;
1079
1080 AccessToken->Privileges[i].Attributes = 0;
1081 AccessToken->Privileges[i++].Luid = SeSystemEnvironmentPrivilege;
1082
1083 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1084 AccessToken->Privileges[i++].Luid = SeChangeNotifyPrivilege;
1085
1086 AccessToken->Privileges[i].Attributes = 0;
1087 AccessToken->Privileges[i++].Luid = SeBackupPrivilege;
1088
1089 AccessToken->Privileges[i].Attributes = 0;
1090 AccessToken->Privileges[i++].Luid = SeRestorePrivilege;
1091
1092 AccessToken->Privileges[i].Attributes = 0;
1093 AccessToken->Privileges[i++].Luid = SeShutdownPrivilege;
1094
1095 AccessToken->Privileges[i].Attributes = 0;
1096 AccessToken->Privileges[i++].Luid = SeLoadDriverPrivilege;
1097
1098 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1099 AccessToken->Privileges[i++].Luid = SeProfileSingleProcessPrivilege;
1100
1101 AccessToken->Privileges[i].Attributes = 0;
1102 AccessToken->Privileges[i++].Luid = SeSystemtimePrivilege;
1103 #if 0
1104 AccessToken->Privileges[i].Attributes = 0;
1105 AccessToken->Privileges[i++].Luid = SeUndockPrivilege;
1106
1107 AccessToken->Privileges[i].Attributes = 0;
1108 AccessToken->Privileges[i++].Luid = SeManageVolumePrivilege;
1109 #endif
1110
1111 assert( i == 20 );
1112
1113 uSize = sizeof(ACL);
1114 uSize += sizeof(ACE_HEADER) + uLocalSystemLength;
1115 uSize += sizeof(ACE_HEADER) + uAdminsLength;
1116 uSize = (uSize & (~3)) + 8;
1117 AccessToken->DefaultDacl =
1118 (PACL) ExAllocatePoolWithTag(NonPagedPool,
1119 uSize,
1120 TAG('T', 'O', 'K', 'd'));
1121 Status = RtlCreateAcl(AccessToken->DefaultDacl, uSize, ACL_REVISION);
1122 if ( NT_SUCCESS(Status) )
1123 {
1124 Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid);
1125 }
1126
1127 if ( NT_SUCCESS(Status) )
1128 {
1129 Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_READ|GENERIC_EXECUTE|READ_CONTROL, SeAliasAdminsSid);
1130 }
1131
1132 if ( ! NT_SUCCESS(Status) )
1133 {
1134 ObDereferenceObject(AccessToken);
1135 return Status;
1136 }
1137
1138 Process->Token = AccessToken;
1139 return(STATUS_SUCCESS);
1140 }
1141
1142 NTSTATUS STDCALL
1143 NtCreateToken(OUT PHANDLE UnsafeTokenHandle,
1144 IN ACCESS_MASK DesiredAccess,
1145 IN POBJECT_ATTRIBUTES UnsafeObjectAttributes,
1146 IN TOKEN_TYPE TokenType,
1147 IN PLUID AuthenticationId,
1148 IN PLARGE_INTEGER ExpirationTime,
1149 IN PTOKEN_USER TokenUser,
1150 IN PTOKEN_GROUPS TokenGroups,
1151 IN PTOKEN_PRIVILEGES TokenPrivileges,
1152 IN PTOKEN_OWNER TokenOwner,
1153 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup,
1154 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl,
1155 IN PTOKEN_SOURCE TokenSource)
1156 {
1157 HANDLE TokenHandle;
1158 PACCESS_TOKEN AccessToken;
1159 NTSTATUS Status;
1160 OBJECT_ATTRIBUTES SafeObjectAttributes;
1161 POBJECT_ATTRIBUTES ObjectAttributes;
1162 LUID TokenId;
1163 LUID ModifiedId;
1164 PVOID EndMem;
1165 ULONG uLength;
1166 ULONG i;
1167
1168 Status = MmCopyFromCaller(&SafeObjectAttributes,
1169 UnsafeObjectAttributes,
1170 sizeof(OBJECT_ATTRIBUTES));
1171 if (!NT_SUCCESS(Status))
1172 return(Status);
1173
1174 ObjectAttributes = &SafeObjectAttributes;
1175
1176 Status = ZwAllocateLocallyUniqueId(&TokenId);
1177 if (!NT_SUCCESS(Status))
1178 return(Status);
1179
1180 Status = ZwAllocateLocallyUniqueId(&ModifiedId);
1181 if (!NT_SUCCESS(Status))
1182 return(Status);
1183
1184 Status = ObCreateObject(&TokenHandle,
1185 DesiredAccess,
1186 ObjectAttributes,
1187 SepTokenObjectType,
1188 (PVOID*)&AccessToken);
1189 if (!NT_SUCCESS(Status))
1190 {
1191 DPRINT1("ObCreateObject() failed (Status %lx)\n");
1192 return(Status);
1193 }
1194
1195 RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
1196 &TokenSource->SourceIdentifier);
1197 memcpy(AccessToken->TokenSource.SourceName,
1198 TokenSource->SourceName,
1199 sizeof(TokenSource->SourceName));
1200
1201 RtlCopyLuid(&AccessToken->TokenId, &TokenId);
1202 RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
1203 AccessToken->ExpirationTime = *ExpirationTime;
1204 RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
1205
1206 AccessToken->UserAndGroupCount = TokenGroups->GroupCount + 1;
1207 AccessToken->PrivilegeCount = TokenPrivileges->PrivilegeCount;
1208 AccessToken->UserAndGroups = 0;
1209 AccessToken->Privileges = 0;
1210
1211 AccessToken->TokenType = TokenType;
1212 AccessToken->ImpersonationLevel = ObjectAttributes->SecurityQualityOfService->ImpersonationLevel;
1213
1214 /*
1215 * Normally we would just point these members into the variable information
1216 * area; however, our ObCreateObject() call can't allocate a variable information
1217 * area, so we allocate them seperately and provide a destroy function.
1218 */
1219
1220 uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
1221 uLength += RtlLengthSid(TokenUser->User.Sid);
1222 for (i = 0; i < TokenGroups->GroupCount; i++)
1223 uLength += RtlLengthSid(TokenGroups->Groups[i].Sid);
1224
1225 AccessToken->UserAndGroups =
1226 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1227 uLength,
1228 TAG('T', 'O', 'K', 'u'));
1229
1230 EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
1231
1232 Status = RtlCopySidAndAttributesArray(1,
1233 &TokenUser->User,
1234 uLength,
1235 AccessToken->UserAndGroups,
1236 EndMem,
1237 &EndMem,
1238 &uLength);
1239 if (NT_SUCCESS(Status))
1240 {
1241 Status = RtlCopySidAndAttributesArray(TokenGroups->GroupCount,
1242 TokenGroups->Groups,
1243 uLength,
1244 &AccessToken->UserAndGroups[1],
1245 EndMem,
1246 &EndMem,
1247 &uLength);
1248 }
1249
1250 if (NT_SUCCESS(Status))
1251 {
1252 Status = SepFindPrimaryGroupAndDefaultOwner(
1253 AccessToken,
1254 TokenPrimaryGroup->PrimaryGroup,
1255 TokenOwner->Owner);
1256 }
1257
1258 if (NT_SUCCESS(Status))
1259 {
1260 uLength = TokenPrivileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
1261 AccessToken->Privileges =
1262 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1263 uLength,
1264 TAG('T', 'O', 'K', 'p'));
1265
1266 for (i = 0; i < TokenPrivileges->PrivilegeCount; i++)
1267 {
1268 Status = MmCopyFromCaller(&AccessToken->Privileges[i],
1269 &TokenPrivileges->Privileges[i],
1270 sizeof(LUID_AND_ATTRIBUTES));
1271 if (!NT_SUCCESS(Status))
1272 break;
1273 }
1274 }
1275
1276 if (NT_SUCCESS(Status))
1277 {
1278 AccessToken->DefaultDacl =
1279 (PACL) ExAllocatePoolWithTag(NonPagedPool,
1280 TokenDefaultDacl->DefaultDacl->AclSize,
1281 TAG('T', 'O', 'K', 'd'));
1282 memcpy(AccessToken->DefaultDacl,
1283 TokenDefaultDacl->DefaultDacl,
1284 TokenDefaultDacl->DefaultDacl->AclSize);
1285 }
1286
1287 ObDereferenceObject(AccessToken);
1288
1289 if (NT_SUCCESS(Status))
1290 {
1291 Status = MmCopyToCaller(UnsafeTokenHandle,
1292 &TokenHandle,
1293 sizeof(HANDLE));
1294 }
1295
1296 if (!NT_SUCCESS(Status))
1297 {
1298 ZwClose(TokenHandle);
1299 return(Status);
1300 }
1301
1302 return(STATUS_SUCCESS);
1303 }
1304
1305
1306 SECURITY_IMPERSONATION_LEVEL STDCALL
1307 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token)
1308 {
1309 return(Token->ImpersonationLevel);
1310 }
1311
1312
1313 TOKEN_TYPE STDCALL
1314 SeTokenType(IN PACCESS_TOKEN Token)
1315 {
1316 return(Token->TokenType);
1317 }
1318
1319 /* EOF */