- Added return values to some unimplemented functions.
[reactos.git] / reactos / ntoskrnl / se / token.c
1 /* $Id: token.c,v 1.30 2003/12/14 17:44:02 hbirr 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 PACCESS_TOKEN Token;
501 PVOID UnusedInfo;
502 PVOID EndMem;
503 PTOKEN_GROUPS PtrTokenGroups;
504 PTOKEN_DEFAULT_DACL PtrDefaultDacl;
505 PTOKEN_STATISTICS PtrTokenStatistics;
506 ULONG uLength;
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 uLength = RtlLengthSidAndAttributes(1, Token->UserAndGroups);
524 if (TokenInformationLength < uLength)
525 {
526 Status = MmCopyToCaller(ReturnLength, &uLength, 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 TokenInformation + 8,
537 &UnusedInfo,
538 &uLength);
539 if (NT_SUCCESS(Status))
540 {
541 uLength = TokenInformationLength - uLength;
542 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
543 }
544 }
545 break;
546
547 case TokenGroups:
548 DPRINT("NtQueryInformationToken(TokenGroups)\n");
549 uLength = RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]) + sizeof(DWORD);
550 if (TokenInformationLength < uLength)
551 {
552 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
553 if (NT_SUCCESS(Status))
554 Status = STATUS_BUFFER_TOO_SMALL;
555 }
556 else
557 {
558 EndMem = 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 &uLength);
568 if (NT_SUCCESS(Status))
569 {
570 uLength = TokenInformationLength - uLength;
571 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
572 }
573 }
574 break;
575
576 case TokenPrivileges:
577 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
578 uLength = sizeof(DWORD) + Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
579 if (TokenInformationLength < uLength)
580 {
581 Status = MmCopyToCaller(ReturnLength, &uLength, 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 uLength = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid) + sizeof(TOKEN_OWNER);
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_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 uLength = RtlLengthSid(Token->PrimaryGroup) + sizeof(TOKEN_PRIMARY_GROUP);
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
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 uLength = (Token->DefaultDacl ? Token->DefaultDacl->AclSize : 0) + sizeof(TOKEN_DEFAULT_DACL);
645 if (TokenInformationLength < uLength)
646 {
647 Status = MmCopyToCaller(ReturnLength, &uLength, 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, &uLength, 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, &uLength, sizeof(ULONG));
663 }
664 break;
665
666 case TokenSource:
667 DPRINT("NtQueryInformationToken(TokenSource)\n");
668 if (TokenInformationLength < sizeof(TOKEN_SOURCE))
669 {
670 uLength = sizeof(TOKEN_SOURCE);
671 Status = MmCopyToCaller(ReturnLength, &uLength, 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 uLength = sizeof(TOKEN_TYPE);
686 Status = MmCopyToCaller(ReturnLength, &uLength, 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 uLength = sizeof(SECURITY_IMPERSONATION_LEVEL);
701 Status = MmCopyToCaller(ReturnLength, &uLength, 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 uLength = sizeof(TOKEN_STATISTICS);
716 Status = MmCopyToCaller(ReturnLength, &uLength, 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 NTSTATUS STDCALL
746 NtSetInformationToken(IN HANDLE TokenHandle,
747 IN TOKEN_INFORMATION_CLASS TokenInformationClass,
748 OUT PVOID TokenInformation,
749 IN ULONG TokenInformationLength)
750 {
751 UNIMPLEMENTED;
752 return(STATUS_NOT_IMPLEMENTED);
753 }
754
755
756 /*
757 * @unimplemented
758 */
759 NTSTATUS STDCALL
760 NtDuplicateToken(IN HANDLE ExistingTokenHandle,
761 IN ACCESS_MASK DesiredAccess,
762 IN POBJECT_ATTRIBUTES ObjectAttributes,
763 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
764 IN TOKEN_TYPE TokenType,
765 OUT PHANDLE NewTokenHandle)
766 {
767 #if 0
768 PACCESS_TOKEN Token;
769 PACCESS_TOKEN NewToken;
770 NTSTATUS Status;
771 ULONG ExistingImpersonationLevel;
772
773 Status = ObReferenceObjectByHandle(ExistingTokenHandle,
774 TOKEN_DUPLICATE,
775 SepTokenObjectType,
776 UserMode,
777 (PVOID*)&Token,
778 NULL);
779
780 ExistingImpersonationLevel = Token->ImpersonationLevel;
781 SepDuplicateToken(Token,
782 ObjectAttributes,
783 ImpersonationLevel,
784 TokenType,
785 ExistingImpersonationLevel,
786 KeGetPreviousMode(),
787 &NewToken);
788 #else
789 UNIMPLEMENTED;
790 return(STATUS_NOT_IMPLEMENTED);
791 #endif
792 }
793
794 VOID SepAdjustGroups(PACCESS_TOKEN Token,
795 ULONG a,
796 BOOLEAN ResetToDefault,
797 PSID_AND_ATTRIBUTES Groups,
798 ULONG b,
799 KPROCESSOR_MODE PreviousMode,
800 ULONG c,
801 PULONG d,
802 PULONG e,
803 PULONG f)
804 {
805 UNIMPLEMENTED;
806 }
807
808
809 NTSTATUS STDCALL
810 NtAdjustGroupsToken(IN HANDLE TokenHandle,
811 IN BOOLEAN ResetToDefault,
812 IN PTOKEN_GROUPS NewState,
813 IN ULONG BufferLength,
814 OUT PTOKEN_GROUPS PreviousState OPTIONAL,
815 OUT PULONG ReturnLength)
816 {
817 #if 0
818 NTSTATUS Status;
819 PACCESS_TOKEN Token;
820 ULONG a;
821 ULONG b;
822 ULONG c;
823
824 Status = ObReferenceObjectByHandle(TokenHandle,
825 ?,
826 SepTokenObjectType,
827 UserMode,
828 (PVOID*)&Token,
829 NULL);
830
831
832 SepAdjustGroups(Token,
833 0,
834 ResetToDefault,
835 NewState->Groups,
836 ?,
837 PreviousState,
838 0,
839 &a,
840 &b,
841 &c);
842 #else
843 UNIMPLEMENTED;
844 return(STATUS_NOT_IMPLEMENTED);
845 #endif
846 }
847
848
849 #if 0
850 NTSTATUS
851 SepAdjustPrivileges(PACCESS_TOKEN Token,
852 ULONG a,
853 KPROCESSOR_MODE PreviousMode,
854 ULONG PrivilegeCount,
855 PLUID_AND_ATTRIBUTES Privileges,
856 PTOKEN_PRIVILEGES* PreviousState,
857 PULONG b,
858 PULONG c,
859 PULONG d)
860 {
861 ULONG i;
862
863 *c = 0;
864
865 if (Token->PrivilegeCount > 0)
866 {
867 for (i = 0; i < Token->PrivilegeCount; i++)
868 {
869 if (PreviousMode != KernelMode)
870 {
871 if (Token->Privileges[i]->Attributes & SE_PRIVILEGE_ENABLED == 0)
872 {
873 if (a != 0)
874 {
875 if (PreviousState != NULL)
876 {
877 memcpy(&PreviousState[i],
878 &Token->Privileges[i],
879 sizeof(LUID_AND_ATTRIBUTES));
880 }
881 Token->Privileges[i].Attributes &= (~SE_PRIVILEGE_ENABLED);
882 }
883 }
884 }
885 }
886 }
887
888 if (PreviousMode != KernelMode)
889 {
890 Token->TokenFlags = Token->TokenFlags & (~1);
891 }
892 else
893 {
894 if (PrivilegeCount <= ?)
895 {
896 }
897 }
898 if (
899 }
900 #endif
901
902
903 /*
904 * @implemented
905 */
906 NTSTATUS STDCALL
907 NtAdjustPrivilegesToken (IN HANDLE TokenHandle,
908 IN BOOLEAN DisableAllPrivileges,
909 IN PTOKEN_PRIVILEGES NewState,
910 IN ULONG BufferLength,
911 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL,
912 OUT PULONG ReturnLength OPTIONAL)
913 {
914 // PLUID_AND_ATTRIBUTES Privileges;
915 KPROCESSOR_MODE PreviousMode;
916 // ULONG PrivilegeCount;
917 PACCESS_TOKEN Token;
918 // ULONG Length;
919 ULONG i;
920 ULONG j;
921 ULONG k;
922 #if 0
923 ULONG a;
924 ULONG b;
925 ULONG c;
926 #endif
927 NTSTATUS Status;
928
929 DPRINT ("NtAdjustPrivilegesToken() called\n");
930
931 // PrivilegeCount = NewState->PrivilegeCount;
932 PreviousMode = KeGetPreviousMode ();
933 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
934 // PrivilegeCount,
935 // PreviousMode,
936 // NULL,
937 // 0,
938 // NonPagedPool,
939 // 1,
940 // &Privileges,
941 // &Length);
942
943 Status = ObReferenceObjectByHandle (TokenHandle,
944 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
945 SepTokenObjectType,
946 PreviousMode,
947 (PVOID*)&Token,
948 NULL);
949 if (!NT_SUCCESS(Status))
950 {
951 DPRINT1 ("Failed to reference token (Status %lx)\n", Status);
952 // SeReleaseLuidAndAttributesArray(Privileges,
953 // PreviousMode,
954 // 0);
955 return Status;
956 }
957
958
959 #if 0
960 SepAdjustPrivileges(Token,
961 0,
962 PreviousMode,
963 PrivilegeCount,
964 Privileges,
965 PreviousState,
966 &a,
967 &b,
968 &c);
969 #endif
970
971 k = 0;
972 if (DisableAllPrivileges == TRUE)
973 {
974 for (i = 0; i < Token->PrivilegeCount; i++)
975 {
976 if (Token->Privileges[i].Attributes != 0)
977 {
978 DPRINT ("Attributes differ\n");
979
980 /* Save current privilege */
981 if (PreviousState != NULL && k < PreviousState->PrivilegeCount)
982 {
983 PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
984 PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
985 k++;
986 }
987
988 /* Update current privlege */
989 Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
990 }
991 }
992 }
993 else
994 {
995 for (i = 0; i < Token->PrivilegeCount; i++)
996 {
997 for (j = 0; j < NewState->PrivilegeCount; j++)
998 {
999 if (Token->Privileges[i].Luid.LowPart == NewState->Privileges[j].Luid.LowPart &&
1000 Token->Privileges[i].Luid.HighPart == NewState->Privileges[j].Luid.HighPart)
1001 {
1002 DPRINT ("Found privilege\n");
1003
1004 if ((Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) !=
1005 (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED))
1006 {
1007 DPRINT ("Attributes differ\n");
1008 DPRINT ("Current attributes %lx desired attributes %lx\n",
1009 Token->Privileges[i].Attributes,
1010 NewState->Privileges[j].Attributes);
1011
1012 /* Save current privilege */
1013 if (PreviousState != NULL && k < PreviousState->PrivilegeCount)
1014 {
1015 PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
1016 PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
1017 k++;
1018 }
1019
1020 /* Update current privlege */
1021 Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
1022 Token->Privileges[i].Attributes |=
1023 (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED);
1024 DPRINT ("New attributes %lx\n",
1025 Token->Privileges[i].Attributes);
1026 }
1027 }
1028 }
1029 }
1030 }
1031
1032 if (ReturnLength != NULL)
1033 {
1034 *ReturnLength = sizeof(TOKEN_PRIVILEGES) +
1035 (sizeof(LUID_AND_ATTRIBUTES) * (k - 1));
1036 }
1037
1038 ObDereferenceObject (Token);
1039
1040 // SeReleaseLuidAndAttributesArray(Privileges,
1041 // PreviousMode,
1042 // 0);
1043
1044 DPRINT ("NtAdjustPrivilegesToken() done\n");
1045
1046 if (k < NewState->PrivilegeCount)
1047 {
1048 return STATUS_NOT_ALL_ASSIGNED;
1049 }
1050
1051 return STATUS_SUCCESS;
1052 }
1053
1054
1055 NTSTATUS
1056 SepCreateSystemProcessToken(struct _EPROCESS* Process)
1057 {
1058 NTSTATUS Status;
1059 ULONG uSize;
1060 ULONG i;
1061
1062 ULONG uLocalSystemLength = RtlLengthSid(SeLocalSystemSid);
1063 ULONG uWorldLength = RtlLengthSid(SeWorldSid);
1064 ULONG uAuthUserLength = RtlLengthSid(SeAuthenticatedUserSid);
1065 ULONG uAdminsLength = RtlLengthSid(SeAliasAdminsSid);
1066
1067 PACCESS_TOKEN AccessToken;
1068
1069 PVOID SidArea;
1070
1071 /*
1072 * Initialize the token
1073 */
1074 Status = ObCreateObject(KernelMode,
1075 SepTokenObjectType,
1076 NULL,
1077 KernelMode,
1078 NULL,
1079 sizeof(ACCESS_TOKEN),
1080 0,
1081 0,
1082 (PVOID*)&AccessToken);
1083 if (!NT_SUCCESS(Status))
1084 {
1085 return(Status);
1086 }
1087
1088 Status = NtAllocateLocallyUniqueId(&AccessToken->TokenId);
1089 if (!NT_SUCCESS(Status))
1090 {
1091 ObDereferenceObject(AccessToken);
1092 return(Status);
1093 }
1094
1095 Status = NtAllocateLocallyUniqueId(&AccessToken->ModifiedId);
1096 if (!NT_SUCCESS(Status))
1097 {
1098 ObDereferenceObject(AccessToken);
1099 return(Status);
1100 }
1101
1102 AccessToken->AuthenticationId.LowPart = SYSTEM_LUID;
1103 AccessToken->AuthenticationId.HighPart = 0;
1104
1105 AccessToken->TokenType = TokenPrimary;
1106 AccessToken->ImpersonationLevel = SecurityDelegation;
1107 AccessToken->TokenSource.SourceIdentifier.LowPart = 0;
1108 AccessToken->TokenSource.SourceIdentifier.HighPart = 0;
1109 memcpy(AccessToken->TokenSource.SourceName, "SeMgr\0\0\0", 8);
1110 AccessToken->ExpirationTime.QuadPart = -1;
1111 AccessToken->UserAndGroupCount = 4;
1112
1113 uSize = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
1114 uSize += uLocalSystemLength;
1115 uSize += uWorldLength;
1116 uSize += uAuthUserLength;
1117 uSize += uAdminsLength;
1118
1119 AccessToken->UserAndGroups =
1120 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1121 uSize,
1122 TAG('T', 'O', 'K', 'u'));
1123 SidArea = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
1124
1125 i = 0;
1126 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1127 AccessToken->UserAndGroups[i++].Attributes = 0;
1128 RtlCopySid(uLocalSystemLength, SidArea, SeLocalSystemSid);
1129 SidArea += uLocalSystemLength;
1130
1131 AccessToken->DefaultOwnerIndex = i;
1132 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1133 AccessToken->PrimaryGroup = (PSID) SidArea;
1134 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT;
1135 Status = RtlCopySid(uAdminsLength, SidArea, SeAliasAdminsSid);
1136 SidArea += uAdminsLength;
1137
1138 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1139 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
1140 RtlCopySid(uWorldLength, SidArea, SeWorldSid);
1141 SidArea += uWorldLength;
1142
1143 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1144 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
1145 RtlCopySid(uAuthUserLength, SidArea, SeAuthenticatedUserSid);
1146 SidArea += uAuthUserLength;
1147
1148 AccessToken->PrivilegeCount = 20;
1149
1150 uSize = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
1151 AccessToken->Privileges =
1152 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1153 uSize,
1154 TAG('T', 'O', 'K', 'p'));
1155
1156 i = 0;
1157 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1158 AccessToken->Privileges[i++].Luid = SeTcbPrivilege;
1159
1160 AccessToken->Privileges[i].Attributes = 0;
1161 AccessToken->Privileges[i++].Luid = SeCreateTokenPrivilege;
1162
1163 AccessToken->Privileges[i].Attributes = 0;
1164 AccessToken->Privileges[i++].Luid = SeTakeOwnershipPrivilege;
1165
1166 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1167 AccessToken->Privileges[i++].Luid = SeCreatePagefilePrivilege;
1168
1169 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1170 AccessToken->Privileges[i++].Luid = SeLockMemoryPrivilege;
1171
1172 AccessToken->Privileges[i].Attributes = 0;
1173 AccessToken->Privileges[i++].Luid = SeAssignPrimaryTokenPrivilege;
1174
1175 AccessToken->Privileges[i].Attributes = 0;
1176 AccessToken->Privileges[i++].Luid = SeIncreaseQuotaPrivilege;
1177
1178 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1179 AccessToken->Privileges[i++].Luid = SeIncreaseBasePriorityPrivilege;
1180
1181 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1182 AccessToken->Privileges[i++].Luid = SeCreatePermanentPrivilege;
1183
1184 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1185 AccessToken->Privileges[i++].Luid = SeDebugPrivilege;
1186
1187 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1188 AccessToken->Privileges[i++].Luid = SeAuditPrivilege;
1189
1190 AccessToken->Privileges[i].Attributes = 0;
1191 AccessToken->Privileges[i++].Luid = SeSecurityPrivilege;
1192
1193 AccessToken->Privileges[i].Attributes = 0;
1194 AccessToken->Privileges[i++].Luid = SeSystemEnvironmentPrivilege;
1195
1196 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1197 AccessToken->Privileges[i++].Luid = SeChangeNotifyPrivilege;
1198
1199 AccessToken->Privileges[i].Attributes = 0;
1200 AccessToken->Privileges[i++].Luid = SeBackupPrivilege;
1201
1202 AccessToken->Privileges[i].Attributes = 0;
1203 AccessToken->Privileges[i++].Luid = SeRestorePrivilege;
1204
1205 AccessToken->Privileges[i].Attributes = 0;
1206 AccessToken->Privileges[i++].Luid = SeShutdownPrivilege;
1207
1208 AccessToken->Privileges[i].Attributes = 0;
1209 AccessToken->Privileges[i++].Luid = SeLoadDriverPrivilege;
1210
1211 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1212 AccessToken->Privileges[i++].Luid = SeProfileSingleProcessPrivilege;
1213
1214 AccessToken->Privileges[i].Attributes = 0;
1215 AccessToken->Privileges[i++].Luid = SeSystemtimePrivilege;
1216 #if 0
1217 AccessToken->Privileges[i].Attributes = 0;
1218 AccessToken->Privileges[i++].Luid = SeUndockPrivilege;
1219
1220 AccessToken->Privileges[i].Attributes = 0;
1221 AccessToken->Privileges[i++].Luid = SeManageVolumePrivilege;
1222 #endif
1223
1224 assert( i == 20 );
1225
1226 uSize = sizeof(ACL);
1227 uSize += sizeof(ACE) + uLocalSystemLength;
1228 uSize += sizeof(ACE) + uAdminsLength;
1229 uSize = (uSize & (~3)) + 8;
1230 AccessToken->DefaultDacl =
1231 (PACL) ExAllocatePoolWithTag(NonPagedPool,
1232 uSize,
1233 TAG('T', 'O', 'K', 'd'));
1234 Status = RtlCreateAcl(AccessToken->DefaultDacl, uSize, ACL_REVISION);
1235 if ( NT_SUCCESS(Status) )
1236 {
1237 Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid);
1238 }
1239
1240 if ( NT_SUCCESS(Status) )
1241 {
1242 Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_READ|GENERIC_EXECUTE|READ_CONTROL, SeAliasAdminsSid);
1243 }
1244
1245 if ( ! NT_SUCCESS(Status) )
1246 {
1247 ObDereferenceObject(AccessToken);
1248 return Status;
1249 }
1250
1251 Process->Token = AccessToken;
1252 return(STATUS_SUCCESS);
1253 }
1254
1255
1256 NTSTATUS STDCALL
1257 NtCreateToken(OUT PHANDLE UnsafeTokenHandle,
1258 IN ACCESS_MASK DesiredAccess,
1259 IN POBJECT_ATTRIBUTES UnsafeObjectAttributes,
1260 IN TOKEN_TYPE TokenType,
1261 IN PLUID AuthenticationId,
1262 IN PLARGE_INTEGER ExpirationTime,
1263 IN PTOKEN_USER TokenUser,
1264 IN PTOKEN_GROUPS TokenGroups,
1265 IN PTOKEN_PRIVILEGES TokenPrivileges,
1266 IN PTOKEN_OWNER TokenOwner,
1267 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup,
1268 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl,
1269 IN PTOKEN_SOURCE TokenSource)
1270 {
1271 HANDLE TokenHandle;
1272 PACCESS_TOKEN AccessToken;
1273 NTSTATUS Status;
1274 OBJECT_ATTRIBUTES SafeObjectAttributes;
1275 POBJECT_ATTRIBUTES ObjectAttributes;
1276 LUID TokenId;
1277 LUID ModifiedId;
1278 PVOID EndMem;
1279 ULONG uLength;
1280 ULONG i;
1281
1282 Status = MmCopyFromCaller(&SafeObjectAttributes,
1283 UnsafeObjectAttributes,
1284 sizeof(OBJECT_ATTRIBUTES));
1285 if (!NT_SUCCESS(Status))
1286 return(Status);
1287
1288 ObjectAttributes = &SafeObjectAttributes;
1289
1290 Status = ZwAllocateLocallyUniqueId(&TokenId);
1291 if (!NT_SUCCESS(Status))
1292 return(Status);
1293
1294 Status = ZwAllocateLocallyUniqueId(&ModifiedId);
1295 if (!NT_SUCCESS(Status))
1296 return(Status);
1297
1298 Status = ObCreateObject(ExGetPreviousMode(),
1299 SepTokenObjectType,
1300 ObjectAttributes,
1301 ExGetPreviousMode(),
1302 NULL,
1303 sizeof(ACCESS_TOKEN),
1304 0,
1305 0,
1306 (PVOID*)&AccessToken);
1307 if (!NT_SUCCESS(Status))
1308 {
1309 DPRINT1("ObCreateObject() failed (Status %lx)\n");
1310 return(Status);
1311 }
1312
1313 Status = ObInsertObject ((PVOID)AccessToken,
1314 NULL,
1315 DesiredAccess,
1316 0,
1317 NULL,
1318 &TokenHandle);
1319 if (!NT_SUCCESS(Status))
1320 {
1321 DPRINT1("ObInsertObject() failed (Status %lx)\n");
1322 ObDereferenceObject (AccessToken);
1323 return Status;
1324 }
1325
1326 RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
1327 &TokenSource->SourceIdentifier);
1328 memcpy(AccessToken->TokenSource.SourceName,
1329 TokenSource->SourceName,
1330 sizeof(TokenSource->SourceName));
1331
1332 RtlCopyLuid(&AccessToken->TokenId, &TokenId);
1333 RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
1334 AccessToken->ExpirationTime = *ExpirationTime;
1335 RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
1336
1337 AccessToken->UserAndGroupCount = TokenGroups->GroupCount + 1;
1338 AccessToken->PrivilegeCount = TokenPrivileges->PrivilegeCount;
1339 AccessToken->UserAndGroups = 0;
1340 AccessToken->Privileges = 0;
1341
1342 AccessToken->TokenType = TokenType;
1343 AccessToken->ImpersonationLevel = ObjectAttributes->SecurityQualityOfService->ImpersonationLevel;
1344
1345 /*
1346 * Normally we would just point these members into the variable information
1347 * area; however, our ObCreateObject() call can't allocate a variable information
1348 * area, so we allocate them seperately and provide a destroy function.
1349 */
1350
1351 uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
1352 uLength += RtlLengthSid(TokenUser->User.Sid);
1353 for (i = 0; i < TokenGroups->GroupCount; i++)
1354 uLength += RtlLengthSid(TokenGroups->Groups[i].Sid);
1355
1356 AccessToken->UserAndGroups =
1357 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1358 uLength,
1359 TAG('T', 'O', 'K', 'u'));
1360
1361 EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
1362
1363 Status = RtlCopySidAndAttributesArray(1,
1364 &TokenUser->User,
1365 uLength,
1366 AccessToken->UserAndGroups,
1367 EndMem,
1368 &EndMem,
1369 &uLength);
1370 if (NT_SUCCESS(Status))
1371 {
1372 Status = RtlCopySidAndAttributesArray(TokenGroups->GroupCount,
1373 TokenGroups->Groups,
1374 uLength,
1375 &AccessToken->UserAndGroups[1],
1376 EndMem,
1377 &EndMem,
1378 &uLength);
1379 }
1380
1381 if (NT_SUCCESS(Status))
1382 {
1383 Status = SepFindPrimaryGroupAndDefaultOwner(
1384 AccessToken,
1385 TokenPrimaryGroup->PrimaryGroup,
1386 TokenOwner->Owner);
1387 }
1388
1389 if (NT_SUCCESS(Status))
1390 {
1391 uLength = TokenPrivileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
1392 AccessToken->Privileges =
1393 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1394 uLength,
1395 TAG('T', 'O', 'K', 'p'));
1396
1397 for (i = 0; i < TokenPrivileges->PrivilegeCount; i++)
1398 {
1399 Status = MmCopyFromCaller(&AccessToken->Privileges[i],
1400 &TokenPrivileges->Privileges[i],
1401 sizeof(LUID_AND_ATTRIBUTES));
1402 if (!NT_SUCCESS(Status))
1403 break;
1404 }
1405 }
1406
1407 if (NT_SUCCESS(Status))
1408 {
1409 AccessToken->DefaultDacl =
1410 (PACL) ExAllocatePoolWithTag(NonPagedPool,
1411 TokenDefaultDacl->DefaultDacl->AclSize,
1412 TAG('T', 'O', 'K', 'd'));
1413 memcpy(AccessToken->DefaultDacl,
1414 TokenDefaultDacl->DefaultDacl,
1415 TokenDefaultDacl->DefaultDacl->AclSize);
1416 }
1417
1418 ObDereferenceObject(AccessToken);
1419
1420 if (NT_SUCCESS(Status))
1421 {
1422 Status = MmCopyToCaller(UnsafeTokenHandle,
1423 &TokenHandle,
1424 sizeof(HANDLE));
1425 }
1426
1427 if (!NT_SUCCESS(Status))
1428 {
1429 ZwClose(TokenHandle);
1430 return(Status);
1431 }
1432
1433 return(STATUS_SUCCESS);
1434 }
1435
1436
1437 /*
1438 * @implemented
1439 */
1440 SECURITY_IMPERSONATION_LEVEL STDCALL
1441 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token)
1442 {
1443 return(Token->ImpersonationLevel);
1444 }
1445
1446
1447 /*
1448 * @implemented
1449 */
1450 TOKEN_TYPE STDCALL
1451 SeTokenType(IN PACCESS_TOKEN Token)
1452 {
1453 return(Token->TokenType);
1454 }
1455
1456 /* EOF */