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