Merge 14981:15268 from trunk
[reactos.git] / reactos / ntoskrnl / se / semgr.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/se/semgr.c
6 * PURPOSE: Security manager
7 *
8 * PROGRAMMERS: No programmer listed.
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 #define TAG_SXPT TAG('S', 'X', 'P', 'T')
18
19
20 /* GLOBALS ******************************************************************/
21
22 PSE_EXPORTS EXPORTED SeExports = NULL;
23
24 static ERESOURCE SepSubjectContextLock;
25
26
27 /* PROTOTYPES ***************************************************************/
28
29 static BOOLEAN SepInitExports(VOID);
30
31
32 /* FUNCTIONS ****************************************************************/
33
34 BOOLEAN INIT_FUNCTION
35 SeInit1(VOID)
36 {
37 SepInitLuid();
38
39 if (!SepInitSecurityIDs())
40 return FALSE;
41
42 if (!SepInitDACLs())
43 return FALSE;
44
45 if (!SepInitSDs())
46 return FALSE;
47
48 SepInitPrivileges();
49
50 if (!SepInitExports())
51 return FALSE;
52
53 /* Initialize the subject context lock */
54 ExInitializeResource(&SepSubjectContextLock);
55
56 return TRUE;
57 }
58
59
60 BOOLEAN INIT_FUNCTION
61 SeInit2(VOID)
62 {
63 SepInitializeTokenImplementation();
64
65 return TRUE;
66 }
67
68
69 BOOLEAN
70 SeInitSRM(VOID)
71 {
72 OBJECT_ATTRIBUTES ObjectAttributes;
73 UNICODE_STRING Name;
74 HANDLE DirectoryHandle;
75 HANDLE EventHandle;
76 NTSTATUS Status;
77
78 /* Create '\Security' directory */
79 RtlInitUnicodeString(&Name,
80 L"\\Security");
81 InitializeObjectAttributes(&ObjectAttributes,
82 &Name,
83 OBJ_PERMANENT,
84 0,
85 NULL);
86 Status = ZwCreateDirectoryObject(&DirectoryHandle,
87 DIRECTORY_ALL_ACCESS,
88 &ObjectAttributes);
89 if (!NT_SUCCESS(Status))
90 {
91 DPRINT1("Failed to create 'Security' directory!\n");
92 return FALSE;
93 }
94
95 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
96 RtlInitUnicodeString(&Name,
97 L"\\LSA_AUTHENTICATION_INITALIZED");
98 InitializeObjectAttributes(&ObjectAttributes,
99 &Name,
100 OBJ_PERMANENT,
101 DirectoryHandle,
102 SePublicDefaultSd);
103 Status = ZwCreateEvent(&EventHandle,
104 EVENT_ALL_ACCESS,
105 &ObjectAttributes,
106 SynchronizationEvent,
107 FALSE);
108 if (!NT_SUCCESS(Status))
109 {
110 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
111 NtClose(DirectoryHandle);
112 return FALSE;
113 }
114
115 ZwClose(EventHandle);
116 ZwClose(DirectoryHandle);
117
118 /* FIXME: Create SRM port and listener thread */
119
120 return TRUE;
121 }
122
123
124 static BOOLEAN INIT_FUNCTION
125 SepInitExports(VOID)
126 {
127 SeExports = ExAllocatePoolWithTag(NonPagedPool,
128 sizeof(SE_EXPORTS),
129 TAG_SXPT);
130 if (SeExports == NULL)
131 return FALSE;
132
133 SeExports->SeCreateTokenPrivilege = SeCreateTokenPrivilege;
134 SeExports->SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
135 SeExports->SeLockMemoryPrivilege = SeLockMemoryPrivilege;
136 SeExports->SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege;
137 SeExports->SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege;
138 SeExports->SeTcbPrivilege = SeTcbPrivilege;
139 SeExports->SeSecurityPrivilege = SeSecurityPrivilege;
140 SeExports->SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege;
141 SeExports->SeLoadDriverPrivilege = SeLoadDriverPrivilege;
142 SeExports->SeCreatePagefilePrivilege = SeCreatePagefilePrivilege;
143 SeExports->SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
144 SeExports->SeSystemProfilePrivilege = SeSystemProfilePrivilege;
145 SeExports->SeSystemtimePrivilege = SeSystemtimePrivilege;
146 SeExports->SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
147 SeExports->SeCreatePermanentPrivilege = SeCreatePermanentPrivilege;
148 SeExports->SeBackupPrivilege = SeBackupPrivilege;
149 SeExports->SeRestorePrivilege = SeRestorePrivilege;
150 SeExports->SeShutdownPrivilege = SeShutdownPrivilege;
151 SeExports->SeDebugPrivilege = SeDebugPrivilege;
152 SeExports->SeAuditPrivilege = SeAuditPrivilege;
153 SeExports->SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege;
154 SeExports->SeChangeNotifyPrivilege = SeChangeNotifyPrivilege;
155 SeExports->SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege;
156
157 SeExports->SeNullSid = SeNullSid;
158 SeExports->SeWorldSid = SeWorldSid;
159 SeExports->SeLocalSid = SeLocalSid;
160 SeExports->SeCreatorOwnerSid = SeCreatorOwnerSid;
161 SeExports->SeCreatorGroupSid = SeCreatorGroupSid;
162 SeExports->SeNtAuthoritySid = SeNtAuthoritySid;
163 SeExports->SeDialupSid = SeDialupSid;
164 SeExports->SeNetworkSid = SeNetworkSid;
165 SeExports->SeBatchSid = SeBatchSid;
166 SeExports->SeInteractiveSid = SeInteractiveSid;
167 SeExports->SeLocalSystemSid = SeLocalSystemSid;
168 SeExports->SeAliasAdminsSid = SeAliasAdminsSid;
169 SeExports->SeAliasUsersSid = SeAliasUsersSid;
170 SeExports->SeAliasGuestsSid = SeAliasGuestsSid;
171 SeExports->SeAliasPowerUsersSid = SeAliasPowerUsersSid;
172 SeExports->SeAliasAccountOpsSid = SeAliasAccountOpsSid;
173 SeExports->SeAliasSystemOpsSid = SeAliasSystemOpsSid;
174 SeExports->SeAliasPrintOpsSid = SeAliasPrintOpsSid;
175 SeExports->SeAliasBackupOpsSid = SeAliasBackupOpsSid;
176
177 return TRUE;
178 }
179
180
181 VOID SepReferenceLogonSession(PLUID AuthenticationId)
182 {
183 UNIMPLEMENTED;
184 }
185
186 VOID SepDeReferenceLogonSession(PLUID AuthenticationId)
187 {
188 UNIMPLEMENTED;
189 }
190
191
192 /*
193 * @implemented
194 */
195 VOID STDCALL
196 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
197 {
198 PETHREAD Thread;
199 BOOLEAN CopyOnOpen;
200 BOOLEAN EffectiveOnly;
201
202 PAGED_CODE();
203
204 Thread = PsGetCurrentThread();
205 if (Thread == NULL)
206 {
207 SubjectContext->ProcessAuditId = 0;
208 SubjectContext->PrimaryToken = NULL;
209 SubjectContext->ClientToken = NULL;
210 SubjectContext->ImpersonationLevel = 0;
211 }
212 else
213 {
214 SubjectContext->ProcessAuditId = Thread->ThreadsProcess;
215 SubjectContext->ClientToken =
216 PsReferenceImpersonationToken(Thread,
217 &CopyOnOpen,
218 &EffectiveOnly,
219 &SubjectContext->ImpersonationLevel);
220 SubjectContext->PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
221 }
222 }
223
224
225 /*
226 * @implemented
227 */
228 VOID STDCALL
229 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
230 {
231 PAGED_CODE();
232
233 KeEnterCriticalRegion();
234 ExAcquireResourceExclusiveLite(&SepSubjectContextLock, TRUE);
235 }
236
237
238 /*
239 * @implemented
240 */
241 VOID STDCALL
242 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
243 {
244 PAGED_CODE();
245
246 ExReleaseResourceLite(&SepSubjectContextLock);
247 KeLeaveCriticalRegion();
248 }
249
250
251 /*
252 * @implemented
253 */
254 VOID STDCALL
255 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
256 {
257 PAGED_CODE();
258
259 if (SubjectContext->PrimaryToken != NULL)
260 {
261 ObDereferenceObject(SubjectContext->PrimaryToken);
262 }
263
264 if (SubjectContext->ClientToken != NULL)
265 {
266 ObDereferenceObject(SubjectContext->ClientToken);
267 }
268 }
269
270
271 /*
272 * @implemented
273 */
274 NTSTATUS STDCALL
275 SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
276 {
277 PAGED_CODE();
278
279 if (*SecurityDescriptor != NULL)
280 {
281 ExFreePool(*SecurityDescriptor);
282 *SecurityDescriptor = NULL;
283 }
284
285 return STATUS_SUCCESS;
286 }
287
288
289 /*
290 * @unimplemented
291 */
292 NTSTATUS STDCALL
293 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
294 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
295 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
296 IN GUID *ObjectType OPTIONAL,
297 IN BOOLEAN IsDirectoryObject,
298 IN ULONG AutoInheritFlags,
299 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
300 IN PGENERIC_MAPPING GenericMapping,
301 IN POOL_TYPE PoolType)
302 {
303 UNIMPLEMENTED;
304 return STATUS_NOT_IMPLEMENTED;
305 }
306
307
308 /*
309 * FUNCTION: Creates a security descriptor for a new object.
310 * ARGUMENTS:
311 * ParentDescriptor =
312 * ExplicitDescriptor =
313 * NewDescriptor =
314 * IsDirectoryObject =
315 * SubjectContext =
316 * GeneralMapping =
317 * PoolType =
318 * RETURNS: Status
319 *
320 * @implemented
321 */
322 NTSTATUS STDCALL
323 SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
324 PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
325 PSECURITY_DESCRIPTOR *NewDescriptor,
326 BOOLEAN IsDirectoryObject,
327 PSECURITY_SUBJECT_CONTEXT SubjectContext,
328 PGENERIC_MAPPING GenericMapping,
329 POOL_TYPE PoolType)
330 {
331 PSECURITY_DESCRIPTOR Descriptor;
332 PTOKEN Token;
333 ULONG OwnerLength = 0;
334 ULONG GroupLength = 0;
335 ULONG DaclLength = 0;
336 ULONG SaclLength = 0;
337 ULONG Length = 0;
338 ULONG Control = 0;
339 ULONG_PTR Current;
340 PSID Owner = NULL;
341 PSID Group = NULL;
342 PACL Dacl = NULL;
343 PACL Sacl = NULL;
344
345 PAGED_CODE();
346
347 /* Lock subject context */
348 SeLockSubjectContext(SubjectContext);
349
350 if (SubjectContext->ClientToken != NULL)
351 {
352 Token = SubjectContext->ClientToken;
353 }
354 else
355 {
356 Token = SubjectContext->PrimaryToken;
357 }
358
359
360 /* Inherit the Owner SID */
361 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
362 {
363 DPRINT("Use explicit owner sid!\n");
364 Owner = ExplicitDescriptor->Owner;
365 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
366 {
367 Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
368 }
369 }
370 else
371 {
372 if (Token != NULL)
373 {
374 DPRINT("Use token owner sid!\n");
375 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
376 }
377 else
378 {
379 DPRINT("Use default owner sid!\n");
380 Owner = SeLocalSystemSid;
381 }
382
383 Control |= SE_OWNER_DEFAULTED;
384 }
385
386 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
387
388
389 /* Inherit the Group SID */
390 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
391 {
392 DPRINT("Use explicit group sid!\n");
393 Group = ExplicitDescriptor->Group;
394 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
395 {
396 Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
397 }
398 }
399 else
400 {
401 if (Token != NULL)
402 {
403 DPRINT("Use token group sid!\n");
404 Group = Token->PrimaryGroup;
405 }
406 else
407 {
408 DPRINT("Use default group sid!\n");
409 Group = SeLocalSystemSid;
410 }
411
412 Control |= SE_OWNER_DEFAULTED;
413 }
414
415 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
416
417
418 /* Inherit the DACL */
419 if (ExplicitDescriptor != NULL &&
420 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
421 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
422 {
423 DPRINT("Use explicit DACL!\n");
424 Dacl = ExplicitDescriptor->Dacl;
425 if (Dacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
426 {
427 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
428 }
429
430 Control |= SE_DACL_PRESENT;
431 }
432 else if (ParentDescriptor != NULL &&
433 (ParentDescriptor->Control & SE_DACL_PRESENT))
434 {
435 DPRINT("Use parent DACL!\n");
436 /* FIXME: Inherit */
437 Dacl = ParentDescriptor->Dacl;
438 if (Dacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
439 {
440 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
441 }
442 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
443 }
444 else if (Token != NULL && Token->DefaultDacl != NULL)
445 {
446 DPRINT("Use token default DACL!\n");
447 /* FIXME: Inherit */
448 Dacl = Token->DefaultDacl;
449 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
450 }
451 else
452 {
453 DPRINT("Use NULL DACL!\n");
454 Dacl = NULL;
455 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
456 }
457
458 DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
459
460
461 /* Inherit the SACL */
462 if (ExplicitDescriptor != NULL &&
463 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
464 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
465 {
466 DPRINT("Use explicit SACL!\n");
467 Sacl = ExplicitDescriptor->Sacl;
468 if (Sacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
469 {
470 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
471 }
472
473 Control |= SE_SACL_PRESENT;
474 }
475 else if (ParentDescriptor != NULL &&
476 (ParentDescriptor->Control & SE_SACL_PRESENT))
477 {
478 DPRINT("Use parent SACL!\n");
479 /* FIXME: Inherit */
480 Sacl = ParentDescriptor->Sacl;
481 if (Sacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
482 {
483 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
484 }
485 Control |= (SE_SACL_PRESENT | SE_SACL_DEFAULTED);
486 }
487
488 SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
489
490
491 /* Allocate and initialize the new security descriptor */
492 Length = sizeof(SECURITY_DESCRIPTOR) +
493 OwnerLength + GroupLength + DaclLength + SaclLength;
494
495 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
496 sizeof(SECURITY_DESCRIPTOR),
497 OwnerLength,
498 GroupLength,
499 DaclLength,
500 SaclLength);
501
502 Descriptor = ExAllocatePool(NonPagedPool,
503 Length);
504 RtlZeroMemory( Descriptor, Length );
505
506 if (Descriptor == NULL)
507 {
508 DPRINT1("ExAlloctePool() failed\n");
509 /* FIXME: Unlock subject context */
510 return STATUS_INSUFFICIENT_RESOURCES;
511 }
512
513 RtlCreateSecurityDescriptor(Descriptor,
514 SECURITY_DESCRIPTOR_REVISION);
515
516 Descriptor->Control = Control | SE_SELF_RELATIVE;
517
518 Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
519
520 if (SaclLength != 0)
521 {
522 RtlCopyMemory((PVOID)Current,
523 Sacl,
524 SaclLength);
525 Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
526 Current += SaclLength;
527 }
528
529 if (DaclLength != 0)
530 {
531 RtlCopyMemory((PVOID)Current,
532 Dacl,
533 DaclLength);
534 Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
535 Current += DaclLength;
536 }
537
538 if (OwnerLength != 0)
539 {
540 RtlCopyMemory((PVOID)Current,
541 Owner,
542 OwnerLength);
543 Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
544 Current += OwnerLength;
545 DPRINT("Owner of %x at %x\n", Descriptor, Descriptor->Owner);
546 }
547 else
548 DPRINT("Owner of %x is zero length\n", Descriptor);
549
550 if (GroupLength != 0)
551 {
552 memmove((PVOID)Current,
553 Group,
554 GroupLength);
555 Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
556 }
557
558 /* Unlock subject context */
559 SeUnlockSubjectContext(SubjectContext);
560
561 *NewDescriptor = Descriptor;
562
563 DPRINT("Descrptor %x\n", Descriptor);
564 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
565
566 return STATUS_SUCCESS;
567 }
568
569
570 static BOOLEAN
571 SepSidInToken(PACCESS_TOKEN _Token,
572 PSID Sid)
573 {
574 ULONG i;
575 PTOKEN Token = (PTOKEN)_Token;
576
577 PAGED_CODE();
578
579 if (Token->UserAndGroupCount == 0)
580 {
581 return FALSE;
582 }
583
584 for (i=0; i<Token->UserAndGroupCount; i++)
585 {
586 if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
587 {
588 if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
589 {
590 return TRUE;
591 }
592
593 return FALSE;
594 }
595 }
596
597 return FALSE;
598 }
599
600
601 /*
602 * FUNCTION: Determines whether the requested access rights can be granted
603 * to an object protected by a security descriptor and an object owner
604 * ARGUMENTS:
605 * SecurityDescriptor = Security descriptor protecting the object
606 * SubjectSecurityContext = Subject's captured security context
607 * SubjectContextLocked = Indicates the user's subject context is locked
608 * DesiredAccess = Access rights the caller is trying to acquire
609 * PreviouslyGrantedAccess = Specified the access rights already granted
610 * Privileges = ?
611 * GenericMapping = Generic mapping associated with the object
612 * AccessMode = Access mode used for the check
613 * GrantedAccess (OUT) = On return specifies the access granted
614 * AccessStatus (OUT) = Status indicating why access was denied
615 * RETURNS: If access was granted, returns TRUE
616 *
617 * @implemented
618 */
619 BOOLEAN STDCALL
620 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
621 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
622 IN BOOLEAN SubjectContextLocked,
623 IN ACCESS_MASK DesiredAccess,
624 IN ACCESS_MASK PreviouslyGrantedAccess,
625 OUT PPRIVILEGE_SET* Privileges,
626 IN PGENERIC_MAPPING GenericMapping,
627 IN KPROCESSOR_MODE AccessMode,
628 OUT PACCESS_MASK GrantedAccess,
629 OUT PNTSTATUS AccessStatus)
630 {
631 LUID_AND_ATTRIBUTES Privilege;
632 ACCESS_MASK CurrentAccess;
633 PACCESS_TOKEN Token;
634 ULONG i;
635 PACL Dacl;
636 BOOLEAN Present;
637 BOOLEAN Defaulted;
638 PACE CurrentAce;
639 PSID Sid;
640 NTSTATUS Status;
641
642 PAGED_CODE();
643
644 CurrentAccess = PreviouslyGrantedAccess;
645
646 if (SubjectContextLocked == FALSE)
647 {
648 SeLockSubjectContext(SubjectSecurityContext);
649 }
650
651 Token = SubjectSecurityContext->ClientToken ?
652 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
653
654 /* Get the DACL */
655 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
656 &Present,
657 &Dacl,
658 &Defaulted);
659 if (!NT_SUCCESS(Status))
660 {
661 if (SubjectContextLocked == FALSE)
662 {
663 SeUnlockSubjectContext(SubjectSecurityContext);
664 }
665
666 *AccessStatus = Status;
667 return FALSE;
668 }
669
670 /* RULE 1: Grant desired access if the object is unprotected */
671 if (Present == TRUE && Dacl == NULL)
672 {
673 if (SubjectContextLocked == FALSE)
674 {
675 SeUnlockSubjectContext(SubjectSecurityContext);
676 }
677
678 *GrantedAccess = DesiredAccess;
679 *AccessStatus = STATUS_SUCCESS;
680 return TRUE;
681 }
682
683 CurrentAccess = PreviouslyGrantedAccess;
684
685 /* RULE 2: Check token for 'take ownership' privilege */
686 Privilege.Luid = SeTakeOwnershipPrivilege;
687 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
688
689 if (SepPrivilegeCheck(Token,
690 &Privilege,
691 1,
692 PRIVILEGE_SET_ALL_NECESSARY,
693 AccessMode))
694 {
695 CurrentAccess |= WRITE_OWNER;
696 if (DesiredAccess == CurrentAccess)
697 {
698 if (SubjectContextLocked == FALSE)
699 {
700 SeUnlockSubjectContext(SubjectSecurityContext);
701 }
702
703 *GrantedAccess = CurrentAccess;
704 *AccessStatus = STATUS_SUCCESS;
705 return TRUE;
706 }
707 }
708
709 /* RULE 3: Check whether the token is the owner */
710 Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
711 &Sid,
712 &Defaulted);
713 if (!NT_SUCCESS(Status))
714 {
715 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
716 if (SubjectContextLocked == FALSE)
717 {
718 SeUnlockSubjectContext(SubjectSecurityContext);
719 }
720
721 *AccessStatus = Status;
722 return FALSE;
723 }
724
725 if (SepSidInToken(Token, Sid))
726 {
727 CurrentAccess |= (READ_CONTROL | WRITE_DAC);
728 if (DesiredAccess == CurrentAccess)
729 {
730 if (SubjectContextLocked == FALSE)
731 {
732 SeUnlockSubjectContext(SubjectSecurityContext);
733 }
734
735 *GrantedAccess = CurrentAccess;
736 *AccessStatus = STATUS_SUCCESS;
737 return TRUE;
738 }
739 }
740
741 /* Fail if DACL is absent */
742 if (Present == FALSE)
743 {
744 if (SubjectContextLocked == FALSE)
745 {
746 SeUnlockSubjectContext(SubjectSecurityContext);
747 }
748
749 *GrantedAccess = 0;
750 *AccessStatus = STATUS_ACCESS_DENIED;
751 return TRUE;
752 }
753
754 /* RULE 4: Grant rights according to the DACL */
755 CurrentAce = (PACE)(Dacl + 1);
756 for (i = 0; i < Dacl->AceCount; i++)
757 {
758 Sid = (PSID)(CurrentAce + 1);
759 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
760 {
761 if (SepSidInToken(Token, Sid))
762 {
763 if (SubjectContextLocked == FALSE)
764 {
765 SeUnlockSubjectContext(SubjectSecurityContext);
766 }
767
768 *GrantedAccess = 0;
769 *AccessStatus = STATUS_ACCESS_DENIED;
770 return TRUE;
771 }
772 }
773
774 if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
775 {
776 if (SepSidInToken(Token, Sid))
777 {
778 CurrentAccess |= CurrentAce->AccessMask;
779 }
780 }
781 }
782
783 if (SubjectContextLocked == FALSE)
784 {
785 SeUnlockSubjectContext(SubjectSecurityContext);
786 }
787
788 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
789 CurrentAccess, DesiredAccess);
790
791 *GrantedAccess = CurrentAccess & DesiredAccess;
792
793 *AccessStatus =
794 (*GrantedAccess == DesiredAccess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
795
796 return TRUE;
797 }
798
799
800 NTSTATUS STDCALL
801 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
802 IN HANDLE TokenHandle,
803 IN ACCESS_MASK DesiredAccess,
804 IN PGENERIC_MAPPING GenericMapping,
805 OUT PPRIVILEGE_SET PrivilegeSet,
806 OUT PULONG ReturnLength,
807 OUT PACCESS_MASK GrantedAccess,
808 OUT PNTSTATUS AccessStatus)
809 {
810 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
811 KPROCESSOR_MODE PreviousMode;
812 PTOKEN Token;
813 NTSTATUS Status;
814
815 PAGED_CODE();
816
817 DPRINT("NtAccessCheck() called\n");
818
819 PreviousMode = KeGetPreviousMode();
820 if (PreviousMode == KernelMode)
821 {
822 *GrantedAccess = DesiredAccess;
823 *AccessStatus = STATUS_SUCCESS;
824 return STATUS_SUCCESS;
825 }
826
827 Status = ObReferenceObjectByHandle(TokenHandle,
828 TOKEN_QUERY,
829 SepTokenObjectType,
830 PreviousMode,
831 (PVOID*)&Token,
832 NULL);
833 if (!NT_SUCCESS(Status))
834 {
835 DPRINT1("Failed to reference token (Status %lx)\n", Status);
836 return Status;
837 }
838
839 /* Check token type */
840 if (Token->TokenType != TokenImpersonation)
841 {
842 DPRINT1("No impersonation token\n");
843 ObDereferenceObject(Token);
844 return STATUS_ACCESS_VIOLATION;
845 }
846
847 /* Check impersonation level */
848 if (Token->ImpersonationLevel < SecurityAnonymous)
849 {
850 DPRINT1("Invalid impersonation level\n");
851 ObDereferenceObject(Token);
852 return STATUS_ACCESS_VIOLATION;
853 }
854
855 RtlZeroMemory(&SubjectSecurityContext,
856 sizeof(SECURITY_SUBJECT_CONTEXT));
857 SubjectSecurityContext.ClientToken = Token;
858 SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
859
860 /* Lock subject context */
861 SeLockSubjectContext(&SubjectSecurityContext);
862
863 if (SeAccessCheck(SecurityDescriptor,
864 &SubjectSecurityContext,
865 TRUE,
866 DesiredAccess,
867 0,
868 &PrivilegeSet,
869 GenericMapping,
870 PreviousMode,
871 GrantedAccess,
872 AccessStatus))
873 {
874 Status = *AccessStatus;
875 }
876 else
877 {
878 Status = STATUS_ACCESS_DENIED;
879 }
880
881 /* Unlock subject context */
882 SeUnlockSubjectContext(&SubjectSecurityContext);
883
884 ObDereferenceObject(Token);
885
886 DPRINT("NtAccessCheck() done\n");
887
888 return Status;
889 }
890
891 /* EOF */