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