ReactOS 0.4.15-dev-7674-gc0b4db1
accesschk.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Security access check control implementation
5 * COPYRIGHT: Copyright 2014 Timo Kreuzer <timo.kreuzer@reactos.org>
6 * Copyright 2014 Eric Kohl
7 * Copyright 2022-2023 George Bișoc <george.bisoc@reactos.org>
8 */
9
10/* INCLUDES *******************************************************************/
11
12#include <ntoskrnl.h>
13#define NDEBUG
14#include <debug.h>
15
16/* PRIVATE FUNCTIONS **********************************************************/
17
41static
42VOID
45 _In_ ULONG ObjectTypeListLength,
47 _In_opt_ PGUID ObjectTypeGuid)
48{
49 ULONG ObjectTypeIndex;
50 ULONG ReturnedObjectIndex;
52
53 PAGED_CODE();
54
55 DPRINT("Access rights 0x%08lx\n", AccessMask);
56
57 /*
58 * The object type of interest is the one that was supplied
59 * by the creator who made the ACE. If the object type was
60 * not supplied then we have no clear indication from where
61 * shall we start updating the access rights of objects on
62 * this list, so we have to begin from the root (aka the
63 * object itself).
64 */
65 if (!ObjectTypeGuid)
66 {
67 DPRINT("No object type provided, updating access rights from root\n");
68 ReturnedObjectIndex = 0;
69 goto LoopAndUpdateRightsObjects;
70 }
71
72 /* Check if that object exists in the list */
73 if (SepObjectTypeGuidInList(ObjectTypeList,
74 ObjectTypeListLength,
75 ObjectTypeGuid,
76 &ReturnedObjectIndex))
77 {
78LoopAndUpdateRightsObjects:
79 /* Update the access rights of the target object */
80 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.DeniedAccessRights |=
81 (AccessMask & ~ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.GrantedAccessRights);
82 DPRINT("Denied rights 0x%08lx of target object at index %lu\n",
83 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.DeniedAccessRights, ReturnedObjectIndex);
84
85 /* And update the children of the target object */
86 for (ObjectTypeIndex = ReturnedObjectIndex + 1;
87 ObjectTypeIndex < ObjectTypeListLength;
88 ObjectTypeIndex++)
89 {
90 /*
91 * Stop looking for children objects if we hit an object that has
92 * the same level as the target object or less.
93 */
94 Level = ObjectTypeList[ObjectTypeIndex].Level;
95 if (Level <= ObjectTypeList[ReturnedObjectIndex].Level)
96 {
97 DPRINT("We looked for all children objects, stop looking\n");
98 break;
99 }
100
101 /* Update the access right of the child */
102 ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.DeniedAccessRights |=
103 (AccessMask & ~ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.GrantedAccessRights);
104 DPRINT("Denied rights 0x%08lx of child object at index %lu\n",
105 ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.DeniedAccessRights, ObjectTypeIndex);
106 }
107 }
108}
109
133static
134VOID
136 _Inout_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList,
137 _In_ ULONG ObjectTypeListLength,
139 _In_opt_ PGUID ObjectTypeGuid)
140{
141 ULONG ObjectTypeIndex;
142 ULONG ReturnedObjectIndex;
144
145 PAGED_CODE();
146
147 DPRINT("Access rights 0x%08lx\n", AccessMask);
148
149 /*
150 * Begin updating the access rights from the root object
151 * (see comment in SepDenyAccessObjectTypeListMaximum).
152 */
153 if (!ObjectTypeGuid)
154 {
155 DPRINT("No object type provided, updating access rights from root\n");
156 ReturnedObjectIndex = 0;
157 goto LoopAndUpdateRightsObjects;
158 }
159
160 /* Check if that object exists in the list */
161 if (SepObjectTypeGuidInList(ObjectTypeList,
162 ObjectTypeListLength,
163 ObjectTypeGuid,
164 &ReturnedObjectIndex))
165 {
166LoopAndUpdateRightsObjects:
167 /* Update the access rights of the target object */
168 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.GrantedAccessRights |=
169 (AccessMask & ~ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.DeniedAccessRights);
170 DPRINT("Granted rights 0x%08lx of target object at index %lu\n",
171 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.GrantedAccessRights, ReturnedObjectIndex);
172
173 /* And update the children of the target object */
174 for (ObjectTypeIndex = ReturnedObjectIndex + 1;
175 ObjectTypeIndex < ObjectTypeListLength;
176 ObjectTypeIndex++)
177 {
178 /*
179 * Stop looking for children objects if we hit an object that has
180 * the same level as the target object or less.
181 */
182 Level = ObjectTypeList[ObjectTypeIndex].Level;
183 if (Level <= ObjectTypeList[ReturnedObjectIndex].Level)
184 {
185 break;
186 }
187
188 /* Update the access right of the child */
189 ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.GrantedAccessRights |=
190 (AccessMask & ~ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.DeniedAccessRights);
191 DPRINT("Granted rights 0x%08lx of child object at index %lu\n",
192 ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.GrantedAccessRights, ObjectTypeIndex);
193 }
194 }
195}
196
226static
227VOID
229 _Inout_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList,
230 _In_ ULONG ObjectTypeListLength,
232 _In_opt_ PGUID ObjectTypeGuid,
233 _Out_opt_ PBOOLEAN BreakOnDeny)
234{
235 ULONG ReturnedObjectIndex;
236 BOOLEAN MustBreak;
237
238 PAGED_CODE();
239
240 DPRINT("Access rights 0x%08lx\n", AccessMask);
241
242 /* Assume we do not want to break at first */
243 MustBreak = FALSE;
244
245 /*
246 * If no object type was supplied then tell the caller it has to break on
247 * searching for other ACEs if the requested remaining access right is
248 * denied by the deny ACE itself. Track down that denied right too.
249 */
250 if (!ObjectTypeGuid)
251 {
252 if (ObjectTypeList[0].ObjectAccessRights.RemainingAccessRights & AccessMask)
253 {
254 DPRINT("Root object requests remaining access right that is denied 0x%08lx\n", AccessMask);
255 MustBreak = TRUE;
256 }
257
258 ObjectTypeList[0].ObjectAccessRights.DeniedAccessRights |=
259 (AccessMask & ~ObjectTypeList[0].ObjectAccessRights.GrantedAccessRights);
260 DPRINT("Denied rights of root object 0x%08lx\n", ObjectTypeList[0].ObjectAccessRights.DeniedAccessRights);
261 goto Quit;
262 }
263
264 /*
265 * If the object exists tell the caller it has to break down if the requested
266 * remaining access right is denied by the ACE. Track down the denied right too.
267 */
268 if (SepObjectTypeGuidInList(ObjectTypeList,
269 ObjectTypeListLength,
270 ObjectTypeGuid,
271 &ReturnedObjectIndex))
272 {
273 if (ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.RemainingAccessRights & AccessMask)
274 {
275 DPRINT("Object at index %lu requests remaining access right that is denied 0x%08lx\n", ReturnedObjectIndex, AccessMask);
276 MustBreak = TRUE;
277 }
278
279 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.DeniedAccessRights |=
280 (AccessMask & ~ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.GrantedAccessRights);
281 DPRINT("Denied rights 0x%08lx of object at index %lu\n",
282 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.DeniedAccessRights, ReturnedObjectIndex);
283 }
284
285Quit:
286 /* Signal the caller he has to break if he wants to */
287 if (BreakOnDeny)
288 {
289 *BreakOnDeny = MustBreak;
290 }
291}
292
322static
323VOID
325 _Inout_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList,
326 _In_ ULONG ObjectTypeListLength,
328 _In_ BOOLEAN RemoveRemainingRights,
329 _In_opt_ PGUID ObjectTypeGuid)
330{
331 ULONG ReturnedObjectIndex;
332
333 PAGED_CODE();
334
335 DPRINT("Access rights 0x%08lx\n", AccessMask);
336
337 /*
338 * If no object type was supplied then remove the remaining rights
339 * of the object itself, the root. Track down that right to the
340 * granted rights as well.
341 */
342 if (!ObjectTypeGuid)
343 {
344 if (RemoveRemainingRights)
345 {
346 ObjectTypeList[0].ObjectAccessRights.RemainingAccessRights &= ~AccessMask;
347 DPRINT("Remaining rights of root object 0x%08lx\n", ObjectTypeList[0].ObjectAccessRights.RemainingAccessRights);
348 }
349
350 ObjectTypeList[0].ObjectAccessRights.GrantedAccessRights |=
351 (AccessMask & ~ObjectTypeList[0].ObjectAccessRights.DeniedAccessRights);
352 DPRINT("Granted rights of root object 0x%08lx\n", ObjectTypeList[0].ObjectAccessRights.GrantedAccessRights);
353 return;
354 }
355
356 /*
357 * Grant access to the object if it exists by removing the remaining
358 * rights. Unlike the NtAccessCheckByTypeResultList variant we do not
359 * care about the children of the target object beccause NtAccessCheckByType
360 * will either grant or deny access to the entire hierarchy of the list.
361 */
362 if (SepObjectTypeGuidInList(ObjectTypeList,
363 ObjectTypeListLength,
364 ObjectTypeGuid,
365 &ReturnedObjectIndex))
366 {
367 /* Remove the remaining rights of that object */
368 if (RemoveRemainingRights)
369 {
370 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.RemainingAccessRights &= ~AccessMask;
371 DPRINT("Remaining rights of object 0x%08lx at index %lu\n",
372 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.RemainingAccessRights, ReturnedObjectIndex);
373 }
374
375 /* And track it down to the granted access rights */
376 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.GrantedAccessRights |=
377 (AccessMask & ~ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.DeniedAccessRights);
378 DPRINT("Granted rights of object 0x%08lx at index %lu\n",
379 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.GrantedAccessRights, ReturnedObjectIndex);
380 }
381}
382
458static
459VOID
461 _In_ ACCESS_CHECK_RIGHT_TYPE ActionType,
462 _In_ ACCESS_MASK RemainingAccess,
463 _In_ PACL Dacl,
464 _In_ PACCESS_TOKEN AccessToken,
465 _In_ PACCESS_TOKEN PrimaryAccessToken,
467 _In_opt_ PSID PrincipalSelfSid,
470 _In_ ULONG ObjectTypeListLength,
471 _In_ BOOLEAN UseResultList,
472 _Inout_ PACCESS_CHECK_RIGHTS AccessCheckRights)
473{
475 PACE CurrentAce;
477 ULONG ObjectTypeIndex;
478 PSID Sid;
479 PGUID ObjectTypeGuid;
480 ACCESS_MASK Access;
481 BOOLEAN BreakOnDeny;
482
483 PAGED_CODE();
484
485 /* These parameters are really needed */
486 ASSERT(Dacl);
487 ASSERT(AccessToken);
488
489 /* TODO: To be removed once we support compound ACEs handling in Se */
490 DBG_UNREFERENCED_PARAMETER(PrimaryAccessToken);
491
492 /* Determine how we should analyze the ACEs */
493 switch (ActionType)
494 {
495 /*
496 * We got the acknowledgement the calling thread desires
497 * maximum rights (as according to MAXIMUM_ALLOWED access
498 * mask). Analyze the ACE of the given DACL.
499 */
501 {
502 /* Loop over the DACL to retrieve ACEs */
503 for (AceIndex = 0; AceIndex < Dacl->AceCount; AceIndex++)
504 {
505 /* Obtain a ACE now */
506 Status = RtlGetAce(Dacl, AceIndex, (PVOID*)&CurrentAce);
507
508 /* Getting this ACE is important, otherwise something is seriously wrong */
510
511 /*
512 * Now it's time to analyze it based upon the
513 * type of this ACE we're being given.
514 */
515 if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
516 {
517 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
518 {
519 /* Get the SID from this ACE */
520 Sid = SepGetSidFromAce(CurrentAce);
521 ASSERT(Sid);
522
523 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, TRUE, IsTokenRestricted))
524 {
525 /* Get this access right from the ACE */
526 Access = CurrentAce->AccessMask;
527
528 /* Map this access right if it has a generic mask right */
529 if ((Access & GENERIC_ACCESS) && GenericMapping)
530 {
532 }
533
534 /* Deny access rights that have not been granted yet */
535 AccessCheckRights->DeniedAccessRights |= (Access & ~AccessCheckRights->GrantedAccessRights);
536 DPRINT("DeniedAccessRights 0x%08lx\n", AccessCheckRights->DeniedAccessRights);
537 }
538 }
539 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
540 {
541 /* Get the SID from this ACE */
542 Sid = SepGetSidFromAce(CurrentAce);
543 ASSERT(Sid);
544
545 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, FALSE, IsTokenRestricted))
546 {
547 /* Get this access right from the ACE */
548 Access = CurrentAce->AccessMask;
549
550 /* Map this access right if it has a generic mask right */
551 if ((Access & GENERIC_ACCESS) && GenericMapping)
552 {
554 }
555
556 /* Grant access rights that have not been denied yet */
557 AccessCheckRights->GrantedAccessRights |= (Access & ~AccessCheckRights->DeniedAccessRights);
558 DPRINT("GrantedAccessRights 0x%08lx\n", AccessCheckRights->GrantedAccessRights);
559 }
560 }
561 else if (CurrentAce->Header.AceType == ACCESS_DENIED_OBJECT_ACE_TYPE)
562 {
563 /* Get the SID and object type from this ACE */
564 Sid = SepGetSidFromAce(CurrentAce);
565 ObjectTypeGuid = SepGetObjectTypeGuidFromAce(CurrentAce, TRUE);
566 ASSERT(Sid);
567
568 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, TRUE, IsTokenRestricted))
569 {
570 /* Get this access right from the ACE */
571 Access = CurrentAce->AccessMask;
572
573 /* Map this access right if it has a generic mask right */
574 if ((Access & GENERIC_ACCESS) && GenericMapping)
575 {
577 }
578
579 /* If no list was passed treat this is as ACCESS_DENIED_ACE_TYPE */
580 if (!ObjectTypeList && !ObjectTypeListLength)
581 {
582 AccessCheckRights->DeniedAccessRights |= (Access & ~AccessCheckRights->GrantedAccessRights);
583 DPRINT("DeniedAccessRights 0x%08lx\n", AccessCheckRights->DeniedAccessRights);
584 }
585 else if (!UseResultList)
586 {
587 /*
588 * We have an object type list but the caller wants to deny access
589 * to the entire hierarchy list. Evaluate the rights of the object
590 * for the whole list. Ignore what the function tells us if we have
591 * to break on deny or not because we only want to keep track of
592 * denied rights.
593 */
594 SepDenyAccessObjectTypeList(ObjectTypeList,
595 ObjectTypeListLength,
596 Access,
597 ObjectTypeGuid,
598 NULL);
599 }
600 else
601 {
602 /* Otherwise evaluate the access rights for each sub-object */
604 ObjectTypeListLength,
605 Access,
606 ObjectTypeGuid);
607 }
608 }
609 }
610 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_OBJECT_ACE_TYPE)
611 {
612 /* Get the SID and object type from this ACE */
613 Sid = SepGetSidFromAce(CurrentAce);
614 ObjectTypeGuid = SepGetObjectTypeGuidFromAce(CurrentAce, FALSE);
615 ASSERT(Sid);
616
617 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, FALSE, IsTokenRestricted))
618 {
619 /* Get this access right from the ACE */
620 Access = CurrentAce->AccessMask;
621
622 /* Map this access right if it has a generic mask right */
623 if ((Access & GENERIC_ACCESS) && GenericMapping)
624 {
626 }
627
628 /* If no list was passed treat this is as ACCESS_ALLOWED_ACE_TYPE */
629 if (!ObjectTypeList && !ObjectTypeListLength)
630 {
631 AccessCheckRights->GrantedAccessRights |= (Access & ~AccessCheckRights->DeniedAccessRights);
632 DPRINT("GrantedAccessRights 0x%08lx\n", AccessCheckRights->GrantedAccessRights);
633 }
634 else if (!UseResultList)
635 {
636 /*
637 * We have an object type list but the caller wants to allow access
638 * to the entire hierarchy list. Evaluate the rights of the object
639 * for the whole list.
640 */
641 SepAllowAccessObjectTypeList(ObjectTypeList,
642 ObjectTypeListLength,
643 Access,
644 FALSE,
645 ObjectTypeGuid);
646 }
647 else
648 {
649 /* Otherwise evaluate the access rights for each sub-object */
651 ObjectTypeListLength,
652 Access,
653 ObjectTypeGuid);
654 }
655 }
656 }
657 else
658 {
659 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
660 }
661 }
662 }
663
664 /* We're done here */
665 break;
666 }
667
668 /*
669 * We got the acknowledgement the calling thread desires
670 * only a subset of rights therefore we have to act a little
671 * different here.
672 */
674 {
675 /* Cache the remaining access rights to be addressed */
676 ASSERT(RemainingAccess != 0);
677 AccessCheckRights->RemainingAccessRights = RemainingAccess;
678
679 /* Fill the remaining rights of each object in the list if we have one */
680 if (ObjectTypeList && (ObjectTypeListLength != 0))
681 {
682 for (ObjectTypeIndex = 0;
683 ObjectTypeIndex < ObjectTypeListLength;
684 ObjectTypeIndex++)
685 {
686 ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.RemainingAccessRights = RemainingAccess;
687 }
688 }
689
690 /* Loop over the DACL to retrieve ACEs */
691 for (AceIndex = 0; AceIndex < Dacl->AceCount; AceIndex++)
692 {
693 /* Obtain a ACE now */
694 Status = RtlGetAce(Dacl, AceIndex, (PVOID*)&CurrentAce);
695
696 /* Getting this ACE is important, otherwise something is seriously wrong */
698
699 /*
700 * Now it's time to analyze it based upon the
701 * type of this ACE we're being given.
702 */
703 if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
704 {
705 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
706 {
707 /* Get the SID from this ACE */
708 Sid = SepGetSidFromAce(CurrentAce);
709 ASSERT(Sid);
710
711 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, TRUE, IsTokenRestricted))
712 {
713 /* Get this access right from the ACE */
714 Access = CurrentAce->AccessMask;
715
716 /* Map this access right if it has a generic mask right */
717 if ((Access & GENERIC_ACCESS) && GenericMapping)
718 {
720 }
721
722 /*
723 * The caller requests a right that cannot be
724 * granted. Access is implicitly denied for
725 * the calling thread. Track this access right.
726 */
727 if (AccessCheckRights->RemainingAccessRights & Access)
728 {
729 DPRINT("Refuted access 0x%08lx\n", Access);
730 AccessCheckRights->DeniedAccessRights |= Access;
731 break;
732 }
733 }
734 }
735 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
736 {
737 /* Get the SID from this ACE */
738 Sid = SepGetSidFromAce(CurrentAce);
739 ASSERT(Sid);
740
741 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, FALSE, IsTokenRestricted))
742 {
743 /* Get this access right from the ACE */
744 Access = CurrentAce->AccessMask;
745
746 /* Map this access right if it has a generic mask right */
747 if ((Access & GENERIC_ACCESS) && GenericMapping)
748 {
750 }
751
752 /* Remove the remaining rights */
753 DPRINT("RemainingAccessRights 0x%08lx Access 0x%08lx\n", AccessCheckRights->RemainingAccessRights, Access);
754 AccessCheckRights->RemainingAccessRights &= ~Access;
755 DPRINT("RemainingAccessRights 0x%08lx\n", AccessCheckRights->RemainingAccessRights);
756
757 /* Track the granted access right */
758 AccessCheckRights->GrantedAccessRights |= Access;
759 }
760 }
761 else if (CurrentAce->Header.AceType == ACCESS_DENIED_OBJECT_ACE_TYPE)
762 {
763 /* Get the SID and object type from this ACE */
764 Sid = SepGetSidFromAce(CurrentAce);
765 ObjectTypeGuid = SepGetObjectTypeGuidFromAce(CurrentAce, TRUE);
766 ASSERT(Sid);
767
768 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, TRUE, IsTokenRestricted))
769 {
770 /* Get this access right from the ACE */
771 Access = CurrentAce->AccessMask;
772
773 /* Map this access right if it has a generic mask right */
774 if ((Access & GENERIC_ACCESS) && GenericMapping)
775 {
777 }
778
779 /* If no list was passed treat this is as ACCESS_DENIED_ACE_TYPE */
780 if (!ObjectTypeList && !ObjectTypeListLength)
781 {
782 if (AccessCheckRights->RemainingAccessRights & Access)
783 {
784 DPRINT("Refuted access 0x%08lx\n", Access);
785 AccessCheckRights->DeniedAccessRights |= Access;
786 break;
787 }
788 }
789 else
790 {
791 /*
792 * Otherwise evaluate the rights of the object for the entire list.
793 * The function will signal us if the caller requested a right that is
794 * denied by the ACE of an object in the list.
795 */
796 SepDenyAccessObjectTypeList(ObjectTypeList,
797 ObjectTypeListLength,
798 Access,
799 ObjectTypeGuid,
800 &BreakOnDeny);
801
802 /* We are acknowledged the caller requested a denied right */
803 if (BreakOnDeny)
804 {
805 DPRINT("Refuted access 0x%08lx\n", Access);
806 break;
807 }
808 }
809 }
810 }
811 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_OBJECT_ACE_TYPE)
812 {
813 /* Get the SID and object type from this ACE */
814 Sid = SepGetSidFromAce(CurrentAce);
815 ObjectTypeGuid = SepGetObjectTypeGuidFromAce(CurrentAce, FALSE);
816 ASSERT(Sid);
817
818 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, FALSE, IsTokenRestricted))
819 {
820 /* Get this access right from the ACE */
821 Access = CurrentAce->AccessMask;
822
823 /* Map this access right if it has a generic mask right */
824 if ((Access & GENERIC_ACCESS) && GenericMapping)
825 {
827 }
828
829 /* If no list was passed treat this is as ACCESS_ALLOWED_ACE_TYPE */
830 if (!ObjectTypeList && !ObjectTypeListLength)
831 {
832 /* Remove the remaining rights */
833 DPRINT("RemainingAccessRights 0x%08lx Access 0x%08lx\n", AccessCheckRights->RemainingAccessRights, Access);
834 AccessCheckRights->RemainingAccessRights &= ~Access;
835 DPRINT("RemainingAccessRights 0x%08lx\n", AccessCheckRights->RemainingAccessRights);
836
837 /* Track the granted access right */
838 AccessCheckRights->GrantedAccessRights |= Access;
839 }
840 else
841 {
842 /* Otherwise evaluate the rights of the object for the entire list */
843 SepAllowAccessObjectTypeList(ObjectTypeList,
844 ObjectTypeListLength,
845 Access,
846 TRUE,
847 ObjectTypeGuid);
848 }
849 }
850 }
851 else
852 {
853 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
854 }
855 }
856 }
857
858 /* We're done here */
859 break;
860 }
861
862 /* We shouldn't reach here */
864 }
865}
866
940static
944 _In_opt_ PACCESS_TOKEN ClientAccessToken,
945 _In_ PACCESS_TOKEN PrimaryAccessToken,
946 _In_opt_ PSID PrincipalSelfSid,
949 _In_ ULONG ObjectTypeListLength,
953 _In_ BOOLEAN UseResultList,
955 _Out_ PACCESS_MASK GrantedAccessList,
956 _Out_ PNTSTATUS AccessStatusList)
957{
958 ACCESS_MASK RemainingAccess;
959 ACCESS_MASK WantedRights;
960 ACCESS_MASK MaskDesired;
961 ACCESS_MASK GrantedRights = 0;
962 ULONG ResultListIndex;
963 ULONG ObjectTypeIndex;
964 PACL Dacl;
965 BOOLEAN Present;
966 BOOLEAN Defaulted;
968 BOOLEAN AccessIsGranted = FALSE;
970 ACCESS_CHECK_RIGHTS AccessCheckRights = {0};
971
972 PAGED_CODE();
973
974 /* A security descriptor must be expected for access checks */
976
977 /* Check for no access desired */
978 if (!DesiredAccess)
979 {
980 /* Check if we had no previous access */
982 {
983 /* Then there's nothing to give */
984 DPRINT1("The caller has no previously granted access gained!\n");
986 goto ReturnCommonStatus;
987 }
988
989 /* Return the previous access only */
991 *Privileges = NULL;
992 goto ReturnCommonStatus;
993 }
994
995 /* Map given accesses */
999
1000 /* Initialize remaining access rights */
1001 RemainingAccess = DesiredAccess;
1002
1003 /*
1004 * Initialize the required rights if the caller wants to know access
1005 * for the object and each sub-object in the list.
1006 */
1007 if (UseResultList)
1008 {
1010 {
1012 MaskDesired = ~MAXIMUM_ALLOWED;
1013 }
1014 else
1015 {
1016 WantedRights = MaskDesired = DesiredAccess | PreviouslyGrantedAccess;
1017 }
1018 }
1019
1020 /*
1021 * Obtain the token provided by the caller. Client (or also
1022 * called impersonation or thread) token takes precedence over
1023 * the primary token which is the token associated with the security
1024 * context of the main calling process. This is because it is the
1025 * client itself that requests access of an object or subset of
1026 * multiple objects. Otherwise obtain the security context of the
1027 * main process (the actual primary token).
1028 */
1029 Token = ClientAccessToken ? ClientAccessToken : PrimaryAccessToken;
1030
1031 /*
1032 * We should at least expect a primary token
1033 * to be present if client token is not
1034 * available.
1035 */
1036 ASSERT(Token);
1037
1038 /*
1039 * Check for ACCESS_SYSTEM_SECURITY and WRITE_OWNER access.
1040 * Write down a set of privileges that have been checked
1041 * if the caller wants it.
1042 */
1043 Status = SePrivilegePolicyCheck(&RemainingAccess,
1045 NULL,
1046 Token,
1047 Privileges,
1048 AccessMode);
1049 if (!NT_SUCCESS(Status))
1050 {
1051 goto ReturnCommonStatus;
1052 }
1053
1054 /* Succeed if there are no more rights to grant */
1055 if (RemainingAccess == 0)
1056 {
1058 goto ReturnCommonStatus;
1059 }
1060
1061 /*
1062 * HACK: Temporary hack that checks if the caller passed an empty
1063 * generic mapping. In such cases we cannot mask out the remaining
1064 * access rights without a proper mapping so the only option we
1065 * can do is to check if the client is an administrator,
1066 * since they are powerful users.
1067 *
1068 * See CORE-18576 for information.
1069 */
1070 if (GenericMapping->GenericRead == 0 &&
1074 {
1075 if (SeTokenIsAdmin(Token))
1076 {
1077 /* Grant him access */
1078 PreviouslyGrantedAccess |= RemainingAccess;
1080 goto ReturnCommonStatus;
1081 }
1082
1083 /* It's not an admin so bail out */
1086 goto ReturnCommonStatus;
1087 }
1088
1089 /* Get the DACL */
1091 &Present,
1092 &Dacl,
1093 &Defaulted);
1094 if (!NT_SUCCESS(Status))
1095 {
1096 goto ReturnCommonStatus;
1097 }
1098
1099 /* Grant desired access if the object is unprotected */
1100 if (Present == FALSE || Dacl == NULL)
1101 {
1102 PreviouslyGrantedAccess |= RemainingAccess;
1103 if (RemainingAccess & MAXIMUM_ALLOWED)
1104 {
1105 PreviouslyGrantedAccess &= ~MAXIMUM_ALLOWED;
1107 }
1108
1110 goto ReturnCommonStatus;
1111 }
1112
1113 /* Deny access if the DACL is empty */
1114 if (Dacl->AceCount == 0)
1115 {
1116 if (RemainingAccess == MAXIMUM_ALLOWED && PreviouslyGrantedAccess != 0)
1117 {
1119 }
1120 else
1121 {
1122 DPRINT1("The DACL has no ACEs and the caller has no previously granted access!\n");
1125 }
1126 goto ReturnCommonStatus;
1127 }
1128
1129 /*
1130 * Determine the MAXIMUM_ALLOWED access rights according to the DACL.
1131 * Or if the caller is supplying a list of object types then determine
1132 * the rights of each object on that list.
1133 */
1134 if ((DesiredAccess & MAXIMUM_ALLOWED) || UseResultList)
1135 {
1136 /* Perform access checks against ACEs from this DACL */
1138 0,
1139 Dacl,
1140 Token,
1141 PrimaryAccessToken,
1142 FALSE,
1143 PrincipalSelfSid,
1145 ObjectTypeList,
1146 ObjectTypeListLength,
1147 UseResultList,
1148 &AccessCheckRights);
1149
1150 /*
1151 * Perform further access checks if this token
1152 * has restricted SIDs.
1153 */
1155 {
1157 0,
1158 Dacl,
1159 Token,
1160 PrimaryAccessToken,
1161 TRUE,
1162 PrincipalSelfSid,
1164 ObjectTypeList,
1165 ObjectTypeListLength,
1166 UseResultList,
1167 &AccessCheckRights);
1168 }
1169
1170 /* The caller did not provide an object type list, check access only for that object */
1171 if (!ObjectTypeList && !ObjectTypeListLength)
1172 {
1173 /* Fail if some rights have not been granted */
1174 RemainingAccess &= ~(MAXIMUM_ALLOWED | AccessCheckRights.GrantedAccessRights);
1175 if (RemainingAccess != 0)
1176 {
1177 DPRINT("Failed to grant access rights, access denied. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", RemainingAccess, DesiredAccess);
1180 goto ReturnCommonStatus;
1181 }
1182
1183 /* Set granted access right and access status */
1184 PreviouslyGrantedAccess |= AccessCheckRights.GrantedAccessRights;
1185 if (PreviouslyGrantedAccess != 0)
1186 {
1188 }
1189 else
1190 {
1191 DPRINT("Failed to grant access rights, access denied. PreviouslyGrantedAccess == 0 DesiredAccess = %08lx\n", DesiredAccess);
1193 }
1194
1195 /* We are done here */
1196 goto ReturnCommonStatus;
1197 }
1198 else if (!UseResultList)
1199 {
1200 /*
1201 * We have a list but the caller wants to know if access can be granted
1202 * to an object in the list. Access will either be granted or denied
1203 * to the whole hierarchy of the list. Look for every object in the list
1204 * that has granted access rights and collect them.
1205 */
1206 for (ObjectTypeIndex = 0;
1207 ObjectTypeIndex < ObjectTypeListLength;
1208 ObjectTypeIndex++)
1209 {
1210 if (ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.GrantedAccessRights != 0)
1211 {
1212 GrantedRights |= ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.GrantedAccessRights;
1213 }
1214 }
1215
1216 /* Now check if acccess can be granted */
1217 RemainingAccess &= ~(MAXIMUM_ALLOWED | GrantedRights);
1218 if (RemainingAccess != 0)
1219 {
1220 DPRINT("Failed to grant access rights to the whole object hierarchy list, access denied. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n",
1221 RemainingAccess, DesiredAccess);
1224 goto ReturnCommonStatus;
1225 }
1226
1227 /* Set granted access right and access status */
1228 PreviouslyGrantedAccess |= GrantedRights;
1229 if (PreviouslyGrantedAccess != 0)
1230 {
1232 }
1233 else
1234 {
1235 DPRINT("Failed to grant access rights to the whole object hierarchy list, access denied. PreviouslyGrantedAccess == 0 DesiredAccess = %08lx\n",
1238 }
1239
1240 /* We are done here */
1241 goto ReturnCommonStatus;
1242 }
1243 else
1244 {
1245 /*
1246 * We have a list and the caller wants to know access for each
1247 * sub-object in the list. Report the access status and granted
1248 * rights for the object and each sub-object in the list.
1249 */
1250 for (ObjectTypeIndex = 0;
1251 ObjectTypeIndex < ObjectTypeListLength;
1252 ObjectTypeIndex++)
1253 {
1254 /* Check if we have some rights */
1255 GrantedRights = (ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.GrantedAccessRights | PreviouslyGrantedAccess) & MaskDesired;
1256 if (GrantedRights != 0)
1257 {
1258 /*
1259 * If we still have some remaining rights to grant the ultimate
1260 * conclusion is that the caller has no access to the object itself.
1261 */
1262 RemainingAccess = (~GrantedRights & WantedRights);
1263 if (RemainingAccess != 0)
1264 {
1265 DPRINT("Failed to grant access rights at specific object at index %lu, access denied. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n",
1266 ObjectTypeIndex, RemainingAccess, DesiredAccess);
1267 AccessStatusList[ObjectTypeIndex] = STATUS_ACCESS_DENIED;
1268 }
1269 else
1270 {
1271 AccessStatusList[ObjectTypeIndex] = STATUS_SUCCESS;
1272 }
1273 }
1274 else
1275 {
1276 /* No access is given */
1277 DPRINT("Failed to grant access rights at specific object at index %lu. No access is given\n", ObjectTypeIndex);
1278 AccessStatusList[ObjectTypeIndex] = STATUS_ACCESS_DENIED;
1279 }
1280
1281 /* Return the access rights to the caller */
1282 GrantedAccessList[ObjectTypeIndex] = GrantedRights;
1283 }
1284
1285 /*
1286 * We have built a list of access statuses for each object but
1287 * we still need to figure out the common status for the
1288 * function. The same status code will be used to check if
1289 * we should report any security debug stuff once we are done.
1290 */
1292 for (ResultListIndex = 0; ResultListIndex < ObjectTypeListLength; ResultListIndex++)
1293 {
1294 /* There is at least one sub-object of which access cannot be granted */
1295 if (AccessStatusList[ResultListIndex] == STATUS_ACCESS_DENIED)
1296 {
1297 Status = AccessStatusList[ResultListIndex];
1298 break;
1299 }
1300 }
1301
1302 /* We are done here */
1303 goto ReturnCommonStatus;
1304 }
1305 }
1306
1307 /* Grant rights according to the DACL */
1309 RemainingAccess,
1310 Dacl,
1311 Token,
1312 PrimaryAccessToken,
1313 FALSE,
1314 PrincipalSelfSid,
1316 ObjectTypeList,
1317 ObjectTypeListLength,
1318 UseResultList,
1319 &AccessCheckRights);
1320
1321 /* The caller did not provide an object type list, check access only for that object */
1322 if (!ObjectTypeList && !ObjectTypeListLength)
1323 {
1324 /* Fail if some rights have not been granted */
1325 if (AccessCheckRights.RemainingAccessRights != 0)
1326 {
1327 DPRINT("Failed to grant access rights, access denied. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", AccessCheckRights.RemainingAccessRights, DesiredAccess);
1330 goto ReturnCommonStatus;
1331 }
1332 }
1333 else
1334 {
1335 /*
1336 * We have an object type list, look for the object of which
1337 * remaining rights are all granted.
1338 */
1339 for (ObjectTypeIndex = 0;
1340 ObjectTypeIndex < ObjectTypeListLength;
1341 ObjectTypeIndex++)
1342 {
1343 if (ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.RemainingAccessRights == 0)
1344 {
1345 AccessIsGranted = TRUE;
1346 break;
1347 }
1348 }
1349
1350 if (!AccessIsGranted)
1351 {
1352 DPRINT("Failed to grant access rights to the whole object hierarchy list, access denied. DesiredAccess = 0x%08lx\n", DesiredAccess);
1355 goto ReturnCommonStatus;
1356 }
1357 }
1358
1359 /*
1360 * Perform further access checks if this token
1361 * has restricted SIDs.
1362 */
1364 {
1366 RemainingAccess,
1367 Dacl,
1368 Token,
1369 PrimaryAccessToken,
1370 TRUE,
1371 PrincipalSelfSid,
1373 ObjectTypeList,
1374 ObjectTypeListLength,
1375 UseResultList,
1376 &AccessCheckRights);
1377
1378 /* The caller did not provide an object type list, check access only for that object */
1379 if (!ObjectTypeList && !ObjectTypeListLength)
1380 {
1381 /* Fail if some rights have not been granted */
1382 if (AccessCheckRights.RemainingAccessRights != 0)
1383 {
1384 DPRINT("Failed to grant access rights, access denied. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", AccessCheckRights.RemainingAccessRights, DesiredAccess);
1387 goto ReturnCommonStatus;
1388 }
1389 }
1390 else
1391 {
1392 /*
1393 * We have an object type list, look for the object of which remaining
1394 * rights are all granted. The user may have access to the requested
1395 * object but on a restricted token case the user is only granted partial
1396 * access. If access is denied to restricted SIDs, the bottom line is that
1397 * access is denied to the user.
1398 */
1399 AccessIsGranted = FALSE;
1400 for (ObjectTypeIndex = 0;
1401 ObjectTypeIndex < ObjectTypeListLength;
1402 ObjectTypeIndex++)
1403 {
1404 if (ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.RemainingAccessRights == 0)
1405 {
1406 AccessIsGranted = TRUE;
1407 break;
1408 }
1409 }
1410
1411 if (!AccessIsGranted)
1412 {
1413 DPRINT("Failed to grant access rights to the whole object hierarchy list, access denied. DesiredAccess = 0x%08lx\n", DesiredAccess);
1416 goto ReturnCommonStatus;
1417 }
1418 }
1419 }
1420
1421 /* Set granted access rights */
1423
1424 /* Fail if no rights have been granted */
1425 if (PreviouslyGrantedAccess == 0)
1426 {
1427 DPRINT("Failed to grant access rights, access denied. PreviouslyGrantedAccess == 0 DesiredAccess = %08lx\n", DesiredAccess);
1429 goto ReturnCommonStatus;
1430 }
1431
1432 /*
1433 * If we're here then we granted all the desired
1434 * access rights the caller wanted.
1435 */
1437
1438ReturnCommonStatus:
1439 if (!UseResultList)
1440 {
1441 *GrantedAccessList = PreviouslyGrantedAccess;
1442 *AccessStatusList = Status;
1443 }
1444
1445#if DBG
1446 /* Dump security debug info on access denied case */
1448 {
1451
1452 if (ObjectTypeList && (ObjectTypeListLength != 0))
1453 {
1454 SepDumpAccessAndStatusList(GrantedAccessList,
1455 AccessStatusList,
1456 UseResultList,
1457 ObjectTypeList,
1458 ObjectTypeListLength);
1459 }
1460 else
1461 {
1462 SepDumpAccessRightsStats(&AccessCheckRights);
1463 }
1464 }
1465#endif
1466
1467 return NT_SUCCESS(Status);
1468}
1469
1480static
1481ULONG
1483 _In_ PPRIVILEGE_SET PrivilegeSet)
1484{
1485 if (PrivilegeSet == NULL)
1486 return 0;
1487
1488 if (PrivilegeSet->PrivilegeCount == 0)
1489 return (ULONG)(sizeof(PRIVILEGE_SET) - sizeof(LUID_AND_ATTRIBUTES));
1490
1491 return (ULONG)(sizeof(PRIVILEGE_SET) +
1492 (PrivilegeSet->PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES));
1493}
1494
1590static
1594 _In_ HANDLE ClientToken,
1595 _In_opt_ PSID PrincipalSelfSid,
1598 _Out_writes_bytes_(*PrivilegeSetLength) PPRIVILEGE_SET PrivilegeSet,
1599 _Inout_ PULONG PrivilegeSetLength,
1600 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
1601 _In_ ULONG ObjectTypeListLength,
1602 _In_ BOOLEAN UseResultList,
1605{
1606 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL;
1607 POBJECT_TYPE_LIST_INTERNAL CapturedObjectTypeList = NULL;
1608 PSID CapturedPrincipalSelfSid = NULL;
1613 ULONG CapturedPrivilegeSetLength, RequiredPrivilegeSetLength;
1614 ULONG ResultListIndex;
1615 PTOKEN Token;
1617
1618 PAGED_CODE();
1619
1620 /* Check if this is kernel mode */
1621 if (PreviousMode == KernelMode)
1622 {
1623 /* Check if kernel wants everything */
1625 {
1626 /* Give it */
1628 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
1629 }
1630 else
1631 {
1632 /* Just give the desired access */
1634 }
1635
1636 /* Success */
1638 return STATUS_SUCCESS;
1639 }
1640
1641 /* Protect probe in SEH */
1642 _SEH2_TRY
1643 {
1644 /* Probe all pointers */
1646 ProbeForRead(PrivilegeSetLength, sizeof(ULONG), sizeof(ULONG));
1647 ProbeForWrite(PrivilegeSet, *PrivilegeSetLength, sizeof(ULONG));
1648
1649 /*
1650 * Probe the access and status list based on the way
1651 * we are going to fill data in.
1652 */
1653 if (UseResultList)
1654 {
1655 /* Bail out on an empty list */
1656 if (!ObjectTypeListLength)
1657 {
1658 DPRINT1("The object type list is empty\n");
1660 }
1661
1662 ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK) * ObjectTypeListLength, sizeof(ULONG));
1663 ProbeForWrite(AccessStatus, sizeof(NTSTATUS) * ObjectTypeListLength, sizeof(ULONG));
1664 }
1665 else
1666 {
1667 ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK), sizeof(ULONG));
1668 ProbeForWrite(AccessStatus, sizeof(NTSTATUS), sizeof(ULONG));
1669 }
1670
1671 /* Capture the privilege set length and the mapping */
1672 CapturedPrivilegeSetLength = *PrivilegeSetLength;
1673 }
1675 {
1676 /* Return the exception code */
1678 }
1679 _SEH2_END;
1680
1681 /* Check for unmapped access rights */
1683 {
1684 DPRINT1("Some generic rights are not mapped\n");
1686 }
1687
1688 /* Reference the token */
1689 Status = ObReferenceObjectByHandle(ClientToken,
1693 (PVOID*)&Token,
1694 NULL);
1695 if (!NT_SUCCESS(Status))
1696 {
1697 DPRINT1("Failed to reference token (Status 0x%08lx)\n", Status);
1698 return Status;
1699 }
1700
1701 /* Check token type */
1702 if (Token->TokenType != TokenImpersonation)
1703 {
1704 DPRINT("No impersonation token\n");
1707 }
1708
1709 /* Check the impersonation level */
1710 if (Token->ImpersonationLevel < SecurityIdentification)
1711 {
1712 DPRINT1("Impersonation level < SecurityIdentification\n");
1715 }
1716
1717 /* Capture the object type list, the list is probed by the function itself */
1718 Status = SeCaptureObjectTypeList(ObjectTypeList,
1719 ObjectTypeListLength,
1721 &CapturedObjectTypeList);
1722 if (!NT_SUCCESS(Status))
1723 {
1724 DPRINT1("Failed to capture the object type list (Status 0x%08lx)\n", Status);
1726 return Status;
1727 }
1728
1729 /* Check for ACCESS_SYSTEM_SECURITY and WRITE_OWNER access */
1732 NULL,
1733 Token,
1734 &Privileges,
1735 PreviousMode);
1736 if (!NT_SUCCESS(Status))
1737 {
1738 DPRINT1("SePrivilegePolicyCheck failed (Status 0x%08lx)\n", Status);
1739 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1741
1742 /*
1743 * The caller does not have the required access to do an access check.
1744 * Propagate the access and status for the whole hierarchy of the list
1745 * or just to single target object.
1746 */
1747 if (UseResultList)
1748 {
1749 for (ResultListIndex = 0; ResultListIndex < ObjectTypeListLength; ResultListIndex++)
1750 {
1751 AccessStatus[ResultListIndex] = Status;
1752 GrantedAccess[ResultListIndex] = 0;
1753 }
1754 }
1755 else
1756 {
1758 *GrantedAccess = 0;
1759 }
1760
1761 return STATUS_SUCCESS;
1762 }
1763
1764 /* Check the size of the privilege set and return the privileges */
1765 if (Privileges != NULL)
1766 {
1767 DPRINT("Privileges != NULL\n");
1768
1769 /* Calculate the required privilege set buffer size */
1770 RequiredPrivilegeSetLength = SepGetPrivilegeSetLength(Privileges);
1771
1772 /* Fail if the privilege set buffer is too small */
1773 if (CapturedPrivilegeSetLength < RequiredPrivilegeSetLength)
1774 {
1776 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1778 *PrivilegeSetLength = RequiredPrivilegeSetLength;
1780 }
1781
1782 /* Copy the privilege set to the caller */
1783 RtlCopyMemory(PrivilegeSet,
1784 Privileges,
1785 RequiredPrivilegeSetLength);
1786
1787 /* Free the local privilege set */
1789 }
1790 else
1791 {
1792 DPRINT("Privileges == NULL\n");
1793
1794 /* Fail if the privilege set buffer is too small */
1795 if (CapturedPrivilegeSetLength < sizeof(PRIVILEGE_SET))
1796 {
1797 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1799 *PrivilegeSetLength = sizeof(PRIVILEGE_SET);
1801 }
1802
1803 /* Initialize the privilege set */
1804 PrivilegeSet->PrivilegeCount = 0;
1805 PrivilegeSet->Control = 0;
1806 }
1807
1808 /* Capture the security descriptor */
1811 PagedPool,
1812 FALSE,
1813 &CapturedSecurityDescriptor);
1814 if (!NT_SUCCESS(Status))
1815 {
1816 DPRINT1("Failed to capture the Security Descriptor\n");
1817 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1819 return Status;
1820 }
1821
1822 /* Check the captured security descriptor */
1823 if (CapturedSecurityDescriptor == NULL)
1824 {
1825 DPRINT1("Security Descriptor is NULL\n");
1826 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1829 }
1830
1831 /* Check security descriptor for valid owner and group */
1832 if (SepGetOwnerFromDescriptor(CapturedSecurityDescriptor) == NULL ||
1833 SepGetGroupFromDescriptor(CapturedSecurityDescriptor) == NULL)
1834 {
1835 DPRINT1("Security Descriptor does not have a valid group or owner\n");
1836 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
1838 FALSE);
1839 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1842 }
1843
1844 /* Capture the principal self SID if we have one */
1845 if (PrincipalSelfSid)
1846 {
1847 Status = SepCaptureSid(PrincipalSelfSid,
1849 PagedPool,
1850 TRUE,
1851 &CapturedPrincipalSelfSid);
1852 if (!NT_SUCCESS(Status))
1853 {
1854 DPRINT1("Failed to capture the principal self SID (Status 0x%08lx)\n", Status);
1855 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
1857 FALSE);
1858 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1860 return Status;
1861 }
1862 }
1863
1864 /* Set up the subject context, and lock it */
1866
1867 /* Lock the token */
1869
1870 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
1872 {
1873 if (SepTokenIsOwner(Token, CapturedSecurityDescriptor, FALSE))
1874 {
1877 else
1879
1881 }
1882 }
1883
1884 if (DesiredAccess == 0)
1885 {
1886 /*
1887 * Propagate the access and status for the whole hierarchy
1888 * of the list or just to single target object.
1889 */
1890 if (UseResultList)
1891 {
1892 for (ResultListIndex = 0; ResultListIndex < ObjectTypeListLength; ResultListIndex++)
1893 {
1894 AccessStatus[ResultListIndex] = STATUS_SUCCESS;
1895 GrantedAccess[ResultListIndex] = PreviouslyGrantedAccess;
1896 }
1897 }
1898 else
1899 {
1902 }
1903 }
1904 else
1905 {
1906 /* Now perform the access check */
1907 SepAccessCheckWorker(CapturedSecurityDescriptor,
1908 Token,
1910 CapturedPrincipalSelfSid,
1912 CapturedObjectTypeList,
1913 ObjectTypeListLength,
1917 UseResultList,
1918 NULL,
1920 AccessStatus);
1921 }
1922
1923 /* Release subject context and unlock the token */
1926
1927 /* Release the caputed principal self SID */
1928 SepReleaseSid(CapturedPrincipalSelfSid,
1930 TRUE);
1931
1932 /* Release the captured security descriptor */
1933 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
1935 FALSE);
1936
1937 /* Release the object type list */
1938 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1939
1940 /* Dereference the token */
1942
1943 /* Check succeeded */
1944 return STATUS_SUCCESS;
1945}
1946
1947/* PUBLIC FUNCTIONS ***********************************************************/
1948
1992BOOLEAN
1993NTAPI
2005{
2006 BOOLEAN ret;
2007
2008 PAGED_CODE();
2009
2010 /* Check if this is kernel mode */
2011 if (AccessMode == KernelMode)
2012 {
2013 /* Check if kernel wants everything */
2015 {
2016 /* Give it */
2018 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
2020 }
2021 else
2022 {
2023 /* Give the desired and previous access */
2025 }
2026
2027 /* Success */
2029 return TRUE;
2030 }
2031
2032 /* Check if we didn't get an SD */
2033 if (!SecurityDescriptor)
2034 {
2035 /* Automatic failure */
2037 return FALSE;
2038 }
2039
2040 /* Check for invalid impersonation */
2043 {
2045 return FALSE;
2046 }
2047
2048 /* Acquire the lock if needed */
2051
2052 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
2054 {
2057
2060 FALSE))
2061 {
2064 else
2066
2068 }
2069 }
2070
2071 if (DesiredAccess == 0)
2072 {
2074 if (PreviouslyGrantedAccess == 0)
2075 {
2076 DPRINT1("Request for zero access to an object. Denying.\n");
2078 ret = FALSE;
2079 }
2080 else
2081 {
2083 ret = TRUE;
2084 }
2085 }
2086 else
2087 {
2088 /* Call the internal function */
2092 NULL,
2094 NULL,
2095 0,
2098 AccessMode,
2099 FALSE,
2100 Privileges,
2102 AccessStatus);
2103 }
2104
2105 /* Release the lock if needed */
2108
2109 return ret;
2110}
2111
2136BOOLEAN
2137NTAPI
2143{
2144 PACL Dacl;
2147
2148 PAGED_CODE();
2149
2151
2152 if (SecurityDescriptor == NULL)
2153 return FALSE;
2154
2155 /* Get DACL */
2157 /* If no DACL, grant access */
2158 if (Dacl == NULL)
2159 return TRUE;
2160
2161 /* No ACE -> Deny */
2162 if (!Dacl->AceCount)
2163 return FALSE;
2164
2165 /* Can't perform the check on restricted token */
2166 if (AccessState->Flags & TOKEN_IS_RESTRICTED)
2167 return FALSE;
2168
2169 /* Browse the ACEs */
2170 for (AceIndex = 0, Ace = (PKNOWN_ACE)((ULONG_PTR)Dacl + sizeof(ACL));
2171 AceIndex < Dacl->AceCount;
2172 AceIndex++, Ace = (PKNOWN_ACE)((ULONG_PTR)Ace + Ace->Header.AceSize))
2173 {
2174 if (Ace->Header.AceFlags & INHERIT_ONLY_ACE)
2175 continue;
2176
2177 /* If access-allowed ACE */
2178 if (Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
2179 {
2180 /* Check if all accesses are granted */
2181 if (!(Ace->Mask & DesiredAccess))
2182 continue;
2183
2184 /* Check SID and grant access if matching */
2185 if (RtlEqualSid(SeWorldSid, &(Ace->SidStart)))
2186 return TRUE;
2187 }
2188 /* If access-denied ACE */
2189 else if (Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE)
2190 {
2191 /* Here, only check if it denies any access wanted and deny if so */
2192 if (Ace->Mask & DesiredAccess)
2193 return FALSE;
2194 }
2195 }
2196
2197 /* Faulty, deny */
2198 return FALSE;
2199}
2200
2201/* SYSTEM CALLS ***************************************************************/
2202
2213NTAPI
2216 _In_ HANDLE ClientToken,
2219 _Out_writes_bytes_(*PrivilegeSetLength) PPRIVILEGE_SET PrivilegeSet,
2220 _Inout_ PULONG PrivilegeSetLength,
2223{
2224 PAGED_CODE();
2225
2226 /* Invoke the internal function to do the job */
2228 ClientToken,
2229 NULL,
2232 PrivilegeSet,
2233 PrivilegeSetLength,
2234 NULL,
2235 0,
2236 FALSE,
2238 AccessStatus);
2239}
2240
2253NTAPI
2256 _In_opt_ PSID PrincipalSelfSid,
2257 _In_ HANDLE ClientToken,
2259 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
2260 _In_ ULONG ObjectTypeListLength,
2262 _Out_writes_bytes_(*PrivilegeSetLength) PPRIVILEGE_SET PrivilegeSet,
2263 _Inout_ PULONG PrivilegeSetLength,
2266{
2267 PAGED_CODE();
2268
2269 /* Invoke the internal function to do the job */
2271 ClientToken,
2272 PrincipalSelfSid,
2275 PrivilegeSet,
2276 PrivilegeSetLength,
2277 ObjectTypeList,
2278 ObjectTypeListLength,
2279 FALSE,
2281 AccessStatus);
2282}
2283
2296NTAPI
2299 _In_opt_ PSID PrincipalSelfSid,
2300 _In_ HANDLE ClientToken,
2302 _In_reads_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
2303 _In_ ULONG ObjectTypeListLength,
2305 _Out_writes_bytes_(*PrivilegeSetLength) PPRIVILEGE_SET PrivilegeSet,
2306 _Inout_ PULONG PrivilegeSetLength,
2307 _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccess,
2308 _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatus)
2309{
2310 PAGED_CODE();
2311
2312 /* Invoke the internal function to do the job */
2314 ClientToken,
2315 PrincipalSelfSid,
2318 PrivilegeSet,
2319 PrivilegeSetLength,
2320 ObjectTypeList,
2321 ObjectTypeListLength,
2322 TRUE,
2324 AccessStatus);
2325}
2326
2327/* EOF */
#define PAGED_CODE()
unsigned char BOOLEAN
static GENERIC_MAPPING GenericMapping
Definition: SeInheritance.c:11
static VOID SepAnalyzeAcesFromDacl(_In_ ACCESS_CHECK_RIGHT_TYPE ActionType, _In_ ACCESS_MASK RemainingAccess, _In_ PACL Dacl, _In_ PACCESS_TOKEN AccessToken, _In_ PACCESS_TOKEN PrimaryAccessToken, _In_ BOOLEAN IsTokenRestricted, _In_opt_ PSID PrincipalSelfSid, _In_ PGENERIC_MAPPING GenericMapping, _In_opt_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ BOOLEAN UseResultList, _Inout_ PACCESS_CHECK_RIGHTS AccessCheckRights)
Analyzes an access control entry that is present in a discretionary access control list (DACL) for ac...
Definition: accesschk.c:460
static VOID SepDenyAccessObjectTypeList(_Inout_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ ACCESS_MASK AccessMask, _In_opt_ PGUID ObjectTypeGuid, _Out_opt_ PBOOLEAN BreakOnDeny)
Denies access of a target object in the object type list. This access is denied for the whole hierarc...
Definition: accesschk.c:228
static NTSTATUS SepAccessCheck(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ HANDLE ClientToken, _In_opt_ PSID PrincipalSelfSid, _In_ ACCESS_MASK DesiredAccess, _In_ PGENERIC_MAPPING GenericMapping, _Out_writes_bytes_(*PrivilegeSetLength) PPRIVILEGE_SET PrivilegeSet, _Inout_ PULONG PrivilegeSetLength, _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ BOOLEAN UseResultList, _Out_ PACCESS_MASK GrantedAccess, _Out_ PNTSTATUS AccessStatus)
Internal function that performs a security check against the client who requests access on a resource...
Definition: accesschk.c:1592
NTSTATUS NTAPI NtAccessCheck(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ HANDLE ClientToken, _In_ ACCESS_MASK DesiredAccess, _In_ PGENERIC_MAPPING GenericMapping, _Out_writes_bytes_(*PrivilegeSetLength) PPRIVILEGE_SET PrivilegeSet, _Inout_ PULONG PrivilegeSetLength, _Out_ PACCESS_MASK GrantedAccess, _Out_ PNTSTATUS AccessStatus)
Determines whether security access can be granted to a client that requests such access on an object.
Definition: accesschk.c:2214
static BOOLEAN SepAccessCheckWorker(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_opt_ PACCESS_TOKEN ClientAccessToken, _In_ PACCESS_TOKEN PrimaryAccessToken, _In_opt_ PSID PrincipalSelfSid, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ ACCESS_MASK PreviouslyGrantedAccess, _In_ PGENERIC_MAPPING GenericMapping, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN UseResultList, _Out_opt_ PPRIVILEGE_SET *Privileges, _Out_ PACCESS_MASK GrantedAccessList, _Out_ PNTSTATUS AccessStatusList)
Private worker function that determines whether security access rights can be givento the calling thr...
Definition: accesschk.c:942
BOOLEAN NTAPI SeAccessCheck(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext, _In_ BOOLEAN SubjectContextLocked, _In_ ACCESS_MASK DesiredAccess, _In_ ACCESS_MASK PreviouslyGrantedAccess, _Out_ PPRIVILEGE_SET *Privileges, _In_ PGENERIC_MAPPING GenericMapping, _In_ KPROCESSOR_MODE AccessMode, _Out_ PACCESS_MASK GrantedAccess, _Out_ PNTSTATUS AccessStatus)
Determines whether security access rights can be given to an object depending on the security descrip...
Definition: accesschk.c:1994
NTSTATUS NTAPI NtAccessCheckByType(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_opt_ PSID PrincipalSelfSid, _In_ HANDLE ClientToken, _In_ ACCESS_MASK DesiredAccess, _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ PGENERIC_MAPPING GenericMapping, _Out_writes_bytes_(*PrivilegeSetLength) PPRIVILEGE_SET PrivilegeSet, _Inout_ PULONG PrivilegeSetLength, _Out_ PACCESS_MASK GrantedAccess, _Out_ PNTSTATUS AccessStatus)
Determines whether security access can be granted to a client that requests such access on the object...
Definition: accesschk.c:2254
static VOID SepDenyAccessObjectTypeResultList(_Inout_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ ACCESS_MASK AccessMask, _In_opt_ PGUID ObjectTypeGuid)
Denies access of a target object and the children objects in an object type list.
Definition: accesschk.c:43
BOOLEAN NTAPI SeFastTraverseCheck(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ PACCESS_STATE AccessState, _In_ ACCESS_MASK DesiredAccess, _In_ KPROCESSOR_MODE AccessMode)
Determines whether security access rights can be given to an object depending on the security descrip...
Definition: accesschk.c:2138
static VOID SepAllowAccessObjectTypeList(_Inout_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ ACCESS_MASK AccessMask, _In_ BOOLEAN RemoveRemainingRights, _In_opt_ PGUID ObjectTypeGuid)
Allows access of a target object in the object type list. This access is allowed for the whole hierar...
Definition: accesschk.c:324
NTSTATUS NTAPI NtAccessCheckByTypeResultList(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_opt_ PSID PrincipalSelfSid, _In_ HANDLE ClientToken, _In_ ACCESS_MASK DesiredAccess, _In_reads_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ PGENERIC_MAPPING GenericMapping, _Out_writes_bytes_(*PrivilegeSetLength) PPRIVILEGE_SET PrivilegeSet, _Inout_ PULONG PrivilegeSetLength, _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccess, _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatus)
Determines whether security access can be granted to a client that requests such access on the object...
Definition: accesschk.c:2297
static VOID SepAllowAccessObjectTypeResultList(_Inout_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ ACCESS_MASK AccessMask, _In_opt_ PGUID ObjectTypeGuid)
Allows access of a target object and the children objects in an object type list.
Definition: accesschk.c:135
static ULONG SepGetPrivilegeSetLength(_In_ PPRIVILEGE_SET PrivilegeSet)
Retrieves the length size of a set list of privileges structure.
Definition: accesschk.c:1482
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define GENERIC_ACCESS
Definition: security.c:35
@ Ace
Definition: card.h:12
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BOOL WINAPI IsTokenRestricted(HANDLE TokenHandle)
Definition: token.c:207
#define GENERIC_READ
Definition: compat.h:135
#define PagedPool
Definition: env_spec_w32.h:308
#define ExGetPreviousMode
Definition: ex.h:140
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
Status
Definition: gdiplustypes.h:25
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
@ SecurityImpersonation
Definition: lsa.idl:57
@ SecurityIdentification
Definition: lsa.idl:56
#define ASSERT(a)
Definition: mode.c:44
@ TokenImpersonation
Definition: imports.h:274
* PNTSTATUS
Definition: strlen.c:14
#define _Out_opt_
Definition: ms_sal.h:346
#define _Inout_
Definition: ms_sal.h:378
#define _Out_writes_bytes_(size)
Definition: ms_sal.h:350
#define _Out_writes_(size)
Definition: ms_sal.h:348
#define _Out_
Definition: ms_sal.h:345
#define _In_reads_opt_(size)
Definition: ms_sal.h:320
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
#define _In_reads_(size)
Definition: ms_sal.h:319
#define KernelMode
Definition: asm.h:34
_In_ ACCESS_MASK AccessMask
Definition: exfuncs.h:186
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL Dacl
Definition: rtlfuncs.h:1593
NTSYSAPI NTSTATUS NTAPI RtlGetAce(PACL Acl, ULONG AceIndex, PVOID *Ace)
_In_ ULONG _In_ ACCESS_MASK _In_ PSID Sid
Definition: rtlfuncs.h:1133
NTSYSAPI VOID NTAPI RtlMapGenericMask(PACCESS_MASK AccessMask, PGENERIC_MAPPING GenericMapping)
NTSYSAPI NTSTATUS NTAPI RtlGetDaclSecurityDescriptor(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _Out_ PBOOLEAN DaclPresent, _Out_ PACL *Dacl, _Out_ PBOOLEAN DaclDefaulted)
NTSYSAPI BOOLEAN NTAPI RtlEqualSid(_In_ PSID Sid1, _In_ PSID Sid2)
#define WRITE_DAC
Definition: nt_native.h:59
ULONG ACCESS_MASK
Definition: nt_native.h:40
ACCESS_MASK * PACCESS_MASK
Definition: nt_native.h:41
#define GENERIC_ALL
Definition: nt_native.h:92
#define READ_CONTROL
Definition: nt_native.h:58
#define GENERIC_WRITE
Definition: nt_native.h:90
#define GENERIC_EXECUTE
Definition: nt_native.h:91
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
#define DEFAULT_UNREACHABLE
#define DBG_UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:318
VOID NTAPI SepReleaseSid(_In_ PSID CapturedSid, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases a captured SID.
Definition: sid.c:400
PGUID SepGetObjectTypeGuidFromAce(_In_ PACE Ace, _In_ BOOLEAN IsAceDenied)
Captures an object type GUID from an object access control entry (ACE).
Definition: objtype.c:180
NTSTATUS NTAPI SepCaptureSid(_In_ PSID InputSid, _In_ KPROCESSOR_MODE AccessMode, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PSID *CapturedSid)
Captures a SID.
Definition: sid.c:314
VOID SeReleaseObjectTypeList(_In_ _Post_invalid_ POBJECT_TYPE_LIST_INTERNAL CapturedObjectTypeList, _In_ KPROCESSOR_MODE PreviousMode)
Releases a buffer list of object types.
Definition: objtype.c:378
NTSTATUS SeCaptureObjectTypeList(_In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ KPROCESSOR_MODE PreviousMode, _Out_ POBJECT_TYPE_LIST_INTERNAL *CapturedObjectTypeList)
Captures a list of object types and converts it to an internal form for use by the kernel....
Definition: objtype.c:282
FORCEINLINE PSID SepGetOwnerFromDescriptor(_Inout_ PSECURITY_DESCRIPTOR _Descriptor)
Definition: se.h:109
#define SepAcquireTokenLockShared(Token)
Definition: se.h:290
@ AccessCheckMaximum
Definition: se.h:60
@ AccessCheckRegular
Definition: se.h:61
enum _ACCESS_CHECK_RIGHT_TYPE ACCESS_CHECK_RIGHT_TYPE
NTSTATUS NTAPI SePrivilegePolicyCheck(_Inout_ PACCESS_MASK DesiredAccess, _Inout_ PACCESS_MASK GrantedAccess, _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, _In_ PTOKEN Token, _Out_opt_ PPRIVILEGE_SET *OutPrivilegeSet, _In_ KPROCESSOR_MODE PreviousMode)
Checks the security policy and returns a set of privileges based upon the said security policy contex...
Definition: priv.c:244
PSID SeWorldSid
Definition: sid.c:25
FORCEINLINE PSID SepGetGroupFromDescriptor(_Inout_ PSECURITY_DESCRIPTOR _Descriptor)
Definition: se.h:89
PSID NTAPI SepGetSidFromAce(_In_ PACE Ace)
Captures a security identifier from a given access control entry. This identifier is valid for the wh...
Definition: sid.c:572
BOOLEAN SepObjectTypeGuidInList(_In_reads_(ObjectTypeListLength) POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ PGUID ObjectTypeGuid, _Out_ PULONG ObjectIndex)
Searches for an object type GUID if it exists on an object type list.
Definition: objtype.c:223
FORCEINLINE PACL SepGetDaclFromDescriptor(_Inout_ PSECURITY_DESCRIPTOR _Descriptor)
Definition: se.h:129
BOOLEAN NTAPI SepTokenIsOwner(_In_ PACCESS_TOKEN _Token, _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ BOOLEAN TokenLocked)
Checks if a token belongs to the main user, being the owner.
Definition: token.c:511
#define SepReleaseTokenLock(Token)
Definition: se.h:296
struct _KNOWN_ACE * PKNOWN_ACE
BOOLEAN NTAPI SepSidInTokenEx(_In_ PACCESS_TOKEN _Token, _In_ PSID PrincipalSelfSid, _In_ PSID _Sid, _In_ BOOLEAN Deny, _In_ BOOLEAN Restricted)
Checks if a SID is present in a token.
Definition: sid.c:443
VOID SepDumpTokenDebugInfo(_In_opt_ PTOKEN Token)
Dumps debug information of an access token to the debugger.
Definition: debug.c:280
VOID SepDumpAccessAndStatusList(_In_ PACCESS_MASK GrantedAccessList, _In_ PNTSTATUS AccessStatusList, _In_ BOOLEAN IsResultList, _In_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength)
Dumps access and status values of each object type in the result list.
Definition: debug.c:353
VOID SepDumpAccessRightsStats(_In_ PACCESS_CHECK_RIGHTS AccessRights)
Dumps security access rights to the debugger.
Definition: debug.c:325
VOID SepDumpSdDebugInfo(_In_opt_ PISECURITY_DESCRIPTOR SecurityDescriptor)
Dumps debug information of a security descriptor to the debugger.
Definition: debug.c:217
VOID NTAPI SeFreePrivileges(_In_ PPRIVILEGE_SET Privileges)
Frees a set of privileges.
Definition: priv.c:669
NTSTATUS NTAPI SeCaptureSecurityDescriptor(_In_ PSECURITY_DESCRIPTOR _OriginalSecurityDescriptor, _In_ KPROCESSOR_MODE CurrentMode, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor)
Captures a security descriptor.
Definition: sd.c:386
NTSTATUS NTAPI SeReleaseSecurityDescriptor(_In_ PSECURITY_DESCRIPTOR CapturedSecurityDescriptor, _In_ KPROCESSOR_MODE CurrentMode, _In_ BOOLEAN CaptureIfKernelMode)
Releases a captured security descriptor buffer.
Definition: sd.c:760
BOOLEAN NTAPI SeTokenIsAdmin(_In_ PACCESS_TOKEN Token)
Determines if a token is either an admin token or not. Such condition is checked based upon TOKEN_HAS...
Definition: token.c:2103
POBJECT_TYPE SeTokenObjectType
Definition: token.c:17
BOOLEAN NTAPI SeTokenIsRestricted(_In_ PACCESS_TOKEN Token)
Determines if a token is restricted or not, based upon the token flags.
Definition: token.c:2126
#define STATUS_NO_IMPERSONATION_TOKEN
Definition: ntstatus.h:328
#define STATUS_INVALID_SECURITY_DESCR
Definition: ntstatus.h:357
#define STATUS_GENERIC_NOT_MAPPED
Definition: ntstatus.h:466
#define STATUS_BAD_IMPERSONATION_LEVEL
Definition: ntstatus.h:401
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
unsigned short USHORT
Definition: pedump.c:61
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define DPRINT
Definition: sndvol32.h:71
ACCESS_MASK RemainingAccessRights
Definition: se.h:43
ACCESS_MASK GrantedAccessRights
Definition: se.h:44
Definition: rtltypes.h:993
ACCESS_MASK GenericExecute
Definition: nt_native.h:567
ACCESS_MASK GenericRead
Definition: nt_native.h:565
ACCESS_MASK GenericAll
Definition: nt_native.h:568
ACCESS_MASK GenericWrite
Definition: nt_native.h:566
Definition: se.h:15
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: setypes.h:219
PACCESS_TOKEN ClientToken
Definition: setypes.h:218
PACCESS_TOKEN PrimaryToken
Definition: setypes.h:220
VOID NTAPI SeLockSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Locks both the referenced primary and client access tokens of a security subject context.
Definition: subject.c:107
VOID NTAPI SeReleaseSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Releases both the primary and client tokens of a security subject context.
Definition: subject.c:171
VOID NTAPI SeUnlockSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Unlocks both the referenced primary and client access tokens of a security subject context.
Definition: subject.c:138
VOID NTAPI SeCaptureSubjectContext(_Out_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Captures the security subject context of the calling thread and calling process.
Definition: subject.c:85
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
int ret
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:56
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH _In_opt_ PEPROCESS _In_opt_ PETHREAD _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor
Definition: wsk.h:191
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
_In_ PEPROCESS _In_ KPROCESSOR_MODE AccessMode
Definition: mmfuncs.h:396
#define ObDereferenceObject
Definition: obfuncs.h:203
_In_ ULONG AceIndex
Definition: rtlfuncs.h:1862
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET * Privileges
Definition: sefuncs.h:17
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN SubjectContextLocked
Definition: sefuncs.h:14
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK PreviouslyGrantedAccess
Definition: sefuncs.h:16
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET _In_ PGENERIC_MAPPING _In_ KPROCESSOR_MODE _Out_ PACCESS_MASK _Out_ PNTSTATUS AccessStatus
Definition: sefuncs.h:21
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
_In_opt_ PVOID _In_opt_ PUNICODE_STRING _In_ PSECURITY_DESCRIPTOR _In_ PACCESS_STATE AccessState
Definition: sefuncs.h:417
_In_ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
Definition: sefuncs.h:13
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET _In_ PGENERIC_MAPPING _In_ KPROCESSOR_MODE _Out_ PACCESS_MASK GrantedAccess
Definition: sefuncs.h:20
#define INHERIT_ONLY_ACE
Definition: setypes.h:749
#define ACCESS_DENIED_OBJECT_ACE_TYPE
Definition: setypes.h:726
#define ACCESS_ALLOWED_ACE_TYPE
Definition: setypes.h:717
#define TOKEN_QUERY
Definition: setypes.h:928
struct _LUID_AND_ATTRIBUTES LUID_AND_ATTRIBUTES
#define ACCESS_DENIED_ACE_TYPE
Definition: setypes.h:718
#define ACCESS_ALLOWED_OBJECT_ACE_TYPE
Definition: setypes.h:725
#define TOKEN_IS_RESTRICTED
Definition: setypes.h:1183
struct _PRIVILEGE_SET PRIVILEGE_SET