ReactOS 0.4.15-dev-6067-g0b695a6
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
86VOID
89 _In_ ACCESS_MASK RemainingAccess,
91 _In_ PACCESS_TOKEN AccessToken,
92 _In_ PACCESS_TOKEN PrimaryAccessToken,
94 _In_opt_ PSID PrincipalSelfSid,
96 _In_opt_ POBJECT_TYPE_LIST ObjectTypeList,
97 _In_ ULONG ObjectTypeListLength,
98 _Inout_ PACCESS_CHECK_RIGHTS AccessCheckRights)
99{
101 PACE CurrentAce;
103 PSID Sid;
104 ACCESS_MASK Access;
105
106 PAGED_CODE();
107
108 /* These parameters are really needed */
109 ASSERT(Dacl);
110 ASSERT(AccessToken);
111
112 /* TODO: To be removed once we support object type handling in Se */
113 DBG_UNREFERENCED_PARAMETER(ObjectTypeList);
114 DBG_UNREFERENCED_PARAMETER(ObjectTypeListLength);
115
116 /* TODO: To be removed once we support compound ACEs handling in Se */
117 DBG_UNREFERENCED_PARAMETER(PrimaryAccessToken);
118
119 /* Determine how we should analyze the ACEs */
120 switch (ActionType)
121 {
122 /*
123 * We got the acknowledgement the calling thread desires
124 * maximum rights (as according to MAXIMUM_ALLOWED access
125 * mask). Analyze the ACE of the given DACL.
126 */
128 {
129 /* Loop over the DACL to retrieve ACEs */
130 for (AceIndex = 0; AceIndex < Dacl->AceCount; AceIndex++)
131 {
132 /* Obtain a ACE now */
133 Status = RtlGetAce(Dacl, AceIndex, (PVOID*)&CurrentAce);
134
135 /* Getting this ACE is important, otherwise something is seriously wrong */
137
138 /*
139 * Now it's time to analyze it based upon the
140 * type of this ACE we're being given.
141 */
142 if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
143 {
144 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
145 {
146 /* Get the SID from this ACE */
148 ASSERT(Sid);
149
150 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, TRUE, IsTokenRestricted))
151 {
152 /* Get this access right from the ACE */
153 Access = CurrentAce->AccessMask;
154
155 /* Map this access right if it has a generic mask right */
156 if ((Access & GENERIC_ACCESS) && GenericMapping)
157 {
159 }
160
161 /* Deny access rights that have not been granted yet */
162 AccessCheckRights->DeniedAccessRights |= (Access & ~AccessCheckRights->GrantedAccessRights);
163 DPRINT("SepAnalyzeAcesFromDacl(): DeniedAccessRights 0x%08lx\n", AccessCheckRights->DeniedAccessRights);
164 }
165 }
166 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
167 {
168 /* Get the SID from this ACE */
170 ASSERT(Sid);
171
172 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, FALSE, IsTokenRestricted))
173 {
174 /* Get this access right from the ACE */
175 Access = CurrentAce->AccessMask;
176
177 /* Map this access right if it has a generic mask right */
178 if ((Access & GENERIC_ACCESS) && GenericMapping)
179 {
181 }
182
183 /* Grant access rights that have not been denied yet */
184 AccessCheckRights->GrantedAccessRights |= (Access & ~AccessCheckRights->DeniedAccessRights);
185 DPRINT("SepAnalyzeAcesFromDacl(): GrantedAccessRights 0x%08lx\n", AccessCheckRights->GrantedAccessRights);
186 }
187 }
188 else
189 {
190 DPRINT1("SepAnalyzeAcesFromDacl(): Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
191 }
192 }
193 }
194
195 /* We're done here */
196 break;
197 }
198
199 /*
200 * We got the acknowledgement the calling thread desires
201 * only a subset of rights therefore we have to act a little
202 * different here.
203 */
205 {
206 /* Cache the remaining access rights to be addressed */
207 ASSERT(RemainingAccess != 0);
208 AccessCheckRights->RemainingAccessRights = RemainingAccess;
209
210 /* Loop over the DACL to retrieve ACEs */
211 for (AceIndex = 0; AceIndex < Dacl->AceCount; AceIndex++)
212 {
213 /* Obtain a ACE now */
214 Status = RtlGetAce(Dacl, AceIndex, (PVOID*)&CurrentAce);
215
216 /* Getting this ACE is important, otherwise something is seriously wrong */
218
219 /*
220 * Now it's time to analyze it based upon the
221 * type of this ACE we're being given.
222 */
223 if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
224 {
225 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
226 {
227 /* Get the SID from this ACE */
229 ASSERT(Sid);
230
231 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, TRUE, IsTokenRestricted))
232 {
233 /* Get this access right from the ACE */
234 Access = CurrentAce->AccessMask;
235
236 /* Map this access right if it has a generic mask right */
237 if ((Access & GENERIC_ACCESS) && GenericMapping)
238 {
240 }
241
242 /*
243 * The caller requests a right that cannot be
244 * granted. Access is implicitly denied for
245 * the calling thread. Track this access right.
246 */
247 if (AccessCheckRights->RemainingAccessRights & Access)
248 {
249 DPRINT("SepAnalyzeAcesFromDacl(): Refuted access 0x%08lx\n", Access);
250 AccessCheckRights->DeniedAccessRights |= Access;
251 break;
252 }
253 }
254 }
255 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
256 {
257 /* Get the SID from this ACE */
259 ASSERT(Sid);
260
261 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, FALSE, IsTokenRestricted))
262 {
263 /* Get this access right from the ACE */
264 Access = CurrentAce->AccessMask;
265
266 /* Map this access right if it has a generic mask right */
267 if ((Access & GENERIC_ACCESS) && GenericMapping)
268 {
270 }
271
272 /* Remove the remaining rights */
273 DPRINT("SepAnalyzeAcesFromDacl(): RemainingAccessRights 0x%08lx Access 0x%08lx\n", AccessCheckRights->RemainingAccessRights, Access);
274 AccessCheckRights->RemainingAccessRights &= ~Access;
275 DPRINT("SepAnalyzeAcesFromDacl(): RemainingAccessRights 0x%08lx\n", AccessCheckRights->RemainingAccessRights);
276
277 /* Track the granted access right */
278 AccessCheckRights->GrantedAccessRights |= Access;
279 }
280 }
281 else
282 {
283 DPRINT1("SepAnalyzeAcesFromDacl(): Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
284 }
285 }
286 }
287
288 /* We're done here */
289 break;
290 }
291
292 /* We shouldn't reach here */
294 }
295}
296
372NTAPI
375 _In_opt_ PACCESS_TOKEN ClientAccessToken,
376 _In_ PACCESS_TOKEN PrimaryAccessToken,
377 _In_opt_ PSID PrincipalSelfSid,
379 _In_opt_ POBJECT_TYPE_LIST ObjectTypeList,
380 _In_ ULONG ObjectTypeListLength,
384 _In_ BOOLEAN UseResultList,
386 _Out_ PACCESS_MASK GrantedAccessList,
387 _Out_ PNTSTATUS AccessStatusList)
388{
389 ACCESS_MASK RemainingAccess;
390 ULONG ResultListLength;
391 ULONG ResultListIndex;
392 PACL Dacl;
393 BOOLEAN Present;
394 BOOLEAN Defaulted;
397 ACCESS_CHECK_RIGHTS AccessCheckRights = {0};
398
399 PAGED_CODE();
400
401 /* A security descriptor must be expected for access checks */
403
404 /* Check for no access desired */
405 if (!DesiredAccess)
406 {
407 /* Check if we had no previous access */
409 {
410 /* Then there's nothing to give */
411 DPRINT1("SepAccessCheck(): The caller has no previously granted access gained!\n");
413 goto ReturnCommonStatus;
414 }
415
416 /* Return the previous access only */
418 *Privileges = NULL;
419 goto ReturnCommonStatus;
420 }
421
422 /* Map given accesses */
426
427 /* Initialize remaining access rights */
428 RemainingAccess = DesiredAccess;
429
430 /*
431 * Obtain the token provided by the caller. Client (or also
432 * called impersonation or thread) token takes precedence over
433 * the primary token which is the token associated with the security
434 * context of the main calling process. This is because it is the
435 * client itself that requests access of an object or subset of
436 * multiple objects. Otherwise obtain the security context of the
437 * main process (the actual primary token).
438 */
439 Token = ClientAccessToken ? ClientAccessToken : PrimaryAccessToken;
440
441 /*
442 * We should at least expect a primary token
443 * to be present if client token is not
444 * available.
445 */
446 ASSERT(Token);
447
448 /*
449 * Check for ACCESS_SYSTEM_SECURITY and WRITE_OWNER access.
450 * Write down a set of privileges that have been checked
451 * if the caller wants it.
452 */
453 Status = SePrivilegePolicyCheck(&RemainingAccess,
455 NULL,
456 Token,
458 AccessMode);
459 if (!NT_SUCCESS(Status))
460 {
461 goto ReturnCommonStatus;
462 }
463
464 /* Succeed if there are no more rights to grant */
465 if (RemainingAccess == 0)
466 {
468 goto ReturnCommonStatus;
469 }
470
471 /* Get the DACL */
473 &Present,
474 &Dacl,
475 &Defaulted);
476 if (!NT_SUCCESS(Status))
477 {
478 goto ReturnCommonStatus;
479 }
480
481 /* Grant desired access if the object is unprotected */
482 if (Present == FALSE || Dacl == NULL)
483 {
484 PreviouslyGrantedAccess |= RemainingAccess;
485 if (RemainingAccess & MAXIMUM_ALLOWED)
486 {
487 PreviouslyGrantedAccess &= ~MAXIMUM_ALLOWED;
489 }
490
492 goto ReturnCommonStatus;
493 }
494
495 /* Deny access if the DACL is empty */
496 if (Dacl->AceCount == 0)
497 {
498 if (RemainingAccess == MAXIMUM_ALLOWED && PreviouslyGrantedAccess != 0)
499 {
501 }
502 else
503 {
504 DPRINT1("SepAccessCheck(): The DACL has no ACEs and the caller has no previously granted access!\n");
507 }
508 goto ReturnCommonStatus;
509 }
510
511 /* Determine the MAXIMUM_ALLOWED access rights according to the DACL */
513 {
514 /* Perform access checks against ACEs from this DACL */
516 0,
517 Dacl,
518 Token,
519 PrimaryAccessToken,
520 FALSE,
521 PrincipalSelfSid,
523 ObjectTypeList,
524 ObjectTypeListLength,
525 &AccessCheckRights);
526
527 /*
528 * Perform further access checks if this token
529 * has restricted SIDs.
530 */
532 {
534 0,
535 Dacl,
536 Token,
537 PrimaryAccessToken,
538 TRUE,
539 PrincipalSelfSid,
541 ObjectTypeList,
542 ObjectTypeListLength,
543 &AccessCheckRights);
544 }
545
546 /* Fail if some rights have not been granted */
547 RemainingAccess &= ~(MAXIMUM_ALLOWED | AccessCheckRights.GrantedAccessRights);
548 if (RemainingAccess != 0)
549 {
550 DPRINT1("SepAccessCheck(): Failed to grant access rights. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", RemainingAccess, DesiredAccess);
553 goto ReturnCommonStatus;
554 }
555
556 /* Set granted access right and access status */
557 PreviouslyGrantedAccess |= AccessCheckRights.GrantedAccessRights;
559 {
561 }
562 else
563 {
564 DPRINT1("SepAccessCheck(): Failed to grant access rights. PreviouslyGrantedAccess == 0 DesiredAccess = %08lx\n", DesiredAccess);
566 }
567
568 /* We have successfully granted all the rights */
569 goto ReturnCommonStatus;
570 }
571
572 /* Grant rights according to the DACL */
574 RemainingAccess,
575 Dacl,
576 Token,
577 PrimaryAccessToken,
578 FALSE,
579 PrincipalSelfSid,
581 ObjectTypeList,
582 ObjectTypeListLength,
583 &AccessCheckRights);
584
585 /* Fail if some rights have not been granted */
586 if (AccessCheckRights.RemainingAccessRights != 0)
587 {
588 DPRINT1("SepAccessCheck(): Failed to grant access rights. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", AccessCheckRights.RemainingAccessRights, DesiredAccess);
591 goto ReturnCommonStatus;
592 }
593
594 /*
595 * Perform further access checks if this token
596 * has restricted SIDs.
597 */
599 {
601 RemainingAccess,
602 Dacl,
603 Token,
604 PrimaryAccessToken,
605 TRUE,
606 PrincipalSelfSid,
608 ObjectTypeList,
609 ObjectTypeListLength,
610 &AccessCheckRights);
611
612 /* Fail if some rights have not been granted */
613 if (AccessCheckRights.RemainingAccessRights != 0)
614 {
615 DPRINT1("SepAccessCheck(): Failed to grant access rights. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", AccessCheckRights.RemainingAccessRights, DesiredAccess);
618 goto ReturnCommonStatus;
619 }
620 }
621
622 /* Set granted access rights */
624
625 /* Fail if no rights have been granted */
627 {
628 DPRINT1("SepAccessCheck(): Failed to grant access rights. PreviouslyGrantedAccess == 0 DesiredAccess = %08lx\n", DesiredAccess);
630 goto ReturnCommonStatus;
631 }
632
633 /*
634 * If we're here then we granted all the desired
635 * access rights the caller wanted.
636 */
638
639ReturnCommonStatus:
640 ResultListLength = UseResultList ? ObjectTypeListLength : 1;
641 for (ResultListIndex = 0; ResultListIndex < ResultListLength; ResultListIndex++)
642 {
643 GrantedAccessList[ResultListIndex] = PreviouslyGrantedAccess;
644 AccessStatusList[ResultListIndex] = Status;
645 }
646
647#if DBG
648 /* Dump security debug info on access denied case */
650 {
653 SepDumpAccessRightsStats(&AccessCheckRights);
654 }
655#endif
656
657 return NT_SUCCESS(Status);
658}
659
671static PSID
673 _In_ PSECURITY_DESCRIPTOR _SecurityDescriptor)
674{
675 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
676 PSID Owner;
677
681 else
683
684 return Owner;
685}
686
698static PSID
700 _In_ PSECURITY_DESCRIPTOR _SecurityDescriptor)
701{
702 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
703 PSID Group;
704
708 else
709 Group = (PSID)SecurityDescriptor->Group;
710
711 return Group;
712}
713
724static
725ULONG
727 _In_ PPRIVILEGE_SET PrivilegeSet)
728{
729 if (PrivilegeSet == NULL)
730 return 0;
731
732 if (PrivilegeSet->PrivilegeCount == 0)
733 return (ULONG)(sizeof(PRIVILEGE_SET) - sizeof(LUID_AND_ATTRIBUTES));
734
735 return (ULONG)(sizeof(PRIVILEGE_SET) +
736 (PrivilegeSet->PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES));
737}
738
739/* PUBLIC FUNCTIONS ***********************************************************/
740
785NTAPI
797{
798 BOOLEAN ret;
799
800 PAGED_CODE();
801
802 /* Check if this is kernel mode */
803 if (AccessMode == KernelMode)
804 {
805 /* Check if kernel wants everything */
807 {
808 /* Give it */
810 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
812 }
813 else
814 {
815 /* Give the desired and previous access */
817 }
818
819 /* Success */
821 return TRUE;
822 }
823
824 /* Check if we didn't get an SD */
826 {
827 /* Automatic failure */
829 return FALSE;
830 }
831
832 /* Check for invalid impersonation */
835 {
837 return FALSE;
838 }
839
840 /* Acquire the lock if needed */
843
844 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
846 {
849
852 FALSE))
853 {
856 else
858
860 }
861 }
862
863 if (DesiredAccess == 0)
864 {
867 {
868 DPRINT1("Request for zero access to an object. Denying.\n");
870 ret = FALSE;
871 }
872 else
873 {
875 ret = TRUE;
876 }
877 }
878 else
879 {
880 /* Call the internal function */
884 NULL,
886 NULL,
887 0,
891 FALSE,
895 }
896
897 /* Release the lock if needed */
900
901 return ret;
902}
903
929NTAPI
935{
936 PACL Dacl;
939
940 PAGED_CODE();
941
943
945 return FALSE;
946
947 /* Get DACL */
949 /* If no DACL, grant access */
950 if (Dacl == NULL)
951 return TRUE;
952
953 /* No ACE -> Deny */
954 if (!Dacl->AceCount)
955 return FALSE;
956
957 /* Can't perform the check on restricted token */
958 if (AccessState->Flags & TOKEN_IS_RESTRICTED)
959 return FALSE;
960
961 /* Browse the ACEs */
962 for (AceIndex = 0, Ace = (PKNOWN_ACE)((ULONG_PTR)Dacl + sizeof(ACL));
963 AceIndex < Dacl->AceCount;
964 AceIndex++, Ace = (PKNOWN_ACE)((ULONG_PTR)Ace + Ace->Header.AceSize))
965 {
966 if (Ace->Header.AceFlags & INHERIT_ONLY_ACE)
967 continue;
968
969 /* If access-allowed ACE */
970 if (Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
971 {
972 /* Check if all accesses are granted */
973 if (!(Ace->Mask & DesiredAccess))
974 continue;
975
976 /* Check SID and grant access if matching */
977 if (RtlEqualSid(SeWorldSid, &(Ace->SidStart)))
978 return TRUE;
979 }
980 /* If access-denied ACE */
981 else if (Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE)
982 {
983 /* Here, only check if it denies any access wanted and deny if so */
984 if (Ace->Mask & DesiredAccess)
985 return FALSE;
986 }
987 }
988
989 /* Faulty, deny */
990 return FALSE;
991}
992
993/* SYSTEM CALLS ***************************************************************/
994
1039NTAPI
1045 _Out_opt_ PPRIVILEGE_SET PrivilegeSet,
1046 _Inout_ PULONG PrivilegeSetLength,
1049{
1050 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL;
1055 ULONG CapturedPrivilegeSetLength, RequiredPrivilegeSetLength;
1056 PTOKEN Token;
1058
1059 PAGED_CODE();
1060
1061 /* Check if this is kernel mode */
1062 if (PreviousMode == KernelMode)
1063 {
1064 /* Check if kernel wants everything */
1066 {
1067 /* Give it */
1069 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
1070 }
1071 else
1072 {
1073 /* Just give the desired access */
1075 }
1076
1077 /* Success */
1079 return STATUS_SUCCESS;
1080 }
1081
1082 /* Protect probe in SEH */
1083 _SEH2_TRY
1084 {
1085 /* Probe all pointers */
1087 ProbeForRead(PrivilegeSetLength, sizeof(ULONG), sizeof(ULONG));
1088 ProbeForWrite(PrivilegeSet, *PrivilegeSetLength, sizeof(ULONG));
1089 ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK), sizeof(ULONG));
1090 ProbeForWrite(AccessStatus, sizeof(NTSTATUS), sizeof(ULONG));
1091
1092 /* Capture the privilege set length and the mapping */
1093 CapturedPrivilegeSetLength = *PrivilegeSetLength;
1094 }
1096 {
1097 /* Return the exception code */
1099 }
1100 _SEH2_END;
1101
1102 /* Check for unmapped access rights */
1105
1106 /* Reference the token */
1111 (PVOID*)&Token,
1112 NULL);
1113 if (!NT_SUCCESS(Status))
1114 {
1115 DPRINT("Failed to reference token (Status %lx)\n", Status);
1116 return Status;
1117 }
1118
1119 /* Check token type */
1120 if (Token->TokenType != TokenImpersonation)
1121 {
1122 DPRINT("No impersonation token\n");
1125 }
1126
1127 /* Check the impersonation level */
1128 if (Token->ImpersonationLevel < SecurityIdentification)
1129 {
1130 DPRINT("Impersonation level < SecurityIdentification\n");
1133 }
1134
1135 /* Check for ACCESS_SYSTEM_SECURITY and WRITE_OWNER access */
1138 NULL,
1139 Token,
1140 &Privileges,
1141 PreviousMode);
1142 if (!NT_SUCCESS(Status))
1143 {
1144 DPRINT("SePrivilegePolicyCheck failed (Status 0x%08lx)\n", Status);
1147 *GrantedAccess = 0;
1148 return STATUS_SUCCESS;
1149 }
1150
1151 /* Check the size of the privilege set and return the privileges */
1152 if (Privileges != NULL)
1153 {
1154 DPRINT("Privileges != NULL\n");
1155
1156 /* Calculate the required privilege set buffer size */
1157 RequiredPrivilegeSetLength = SepGetPrivilegeSetLength(Privileges);
1158
1159 /* Fail if the privilege set buffer is too small */
1160 if (CapturedPrivilegeSetLength < RequiredPrivilegeSetLength)
1161 {
1164 *PrivilegeSetLength = RequiredPrivilegeSetLength;
1166 }
1167
1168 /* Copy the privilege set to the caller */
1169 RtlCopyMemory(PrivilegeSet,
1170 Privileges,
1171 RequiredPrivilegeSetLength);
1172
1173 /* Free the local privilege set */
1175 }
1176 else
1177 {
1178 DPRINT("Privileges == NULL\n");
1179
1180 /* Fail if the privilege set buffer is too small */
1181 if (CapturedPrivilegeSetLength < sizeof(PRIVILEGE_SET))
1182 {
1184 *PrivilegeSetLength = sizeof(PRIVILEGE_SET);
1186 }
1187
1188 /* Initialize the privilege set */
1189 PrivilegeSet->PrivilegeCount = 0;
1190 PrivilegeSet->Control = 0;
1191 }
1192
1193 /* Capture the security descriptor */
1196 PagedPool,
1197 FALSE,
1198 &CapturedSecurityDescriptor);
1199 if (!NT_SUCCESS(Status))
1200 {
1201 DPRINT("Failed to capture the Security Descriptor\n");
1203 return Status;
1204 }
1205
1206 /* Check the captured security descriptor */
1207 if (CapturedSecurityDescriptor == NULL)
1208 {
1209 DPRINT("Security Descriptor is NULL\n");
1212 }
1213
1214 /* Check security descriptor for valid owner and group */
1215 if (SepGetSDOwner(CapturedSecurityDescriptor) == NULL ||
1216 SepGetSDGroup(CapturedSecurityDescriptor) == NULL)
1217 {
1218 DPRINT("Security Descriptor does not have a valid group or owner\n");
1219 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
1221 FALSE);
1224 }
1225
1226 /* Set up the subject context, and lock it */
1228
1229 /* Lock the token */
1231
1232 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
1234 {
1235 if (SepTokenIsOwner(Token, CapturedSecurityDescriptor, FALSE))
1236 {
1239 else
1241
1243 }
1244 }
1245
1246 if (DesiredAccess == 0)
1247 {
1250 }
1251 else
1252 {
1253 /* Now perform the access check */
1254 SepAccessCheck(CapturedSecurityDescriptor,
1255 Token,
1257 NULL,
1259 NULL,
1260 0,
1264 FALSE,
1265 NULL,
1267 AccessStatus);
1268 }
1269
1270 /* Release subject context and unlock the token */
1273
1274 /* Release the captured security descriptor */
1275 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
1277 FALSE);
1278
1279 /* Dereference the token */
1281
1282 /* Check succeeded */
1283 return STATUS_SUCCESS;
1284}
1285
1329NTAPI
1332 _In_ PSID PrincipalSelfSid,
1333 _In_ HANDLE ClientToken,
1335 _In_ POBJECT_TYPE_LIST ObjectTypeList,
1336 _In_ ULONG ObjectTypeLength,
1338 _In_ PPRIVILEGE_SET PrivilegeSet,
1339 _Inout_ PULONG PrivilegeSetLength,
1342{
1345}
1346
1391NTAPI
1394 _In_ PSID PrincipalSelfSid,
1395 _In_ HANDLE ClientToken,
1397 _In_ POBJECT_TYPE_LIST ObjectTypeList,
1398 _In_ ULONG ObjectTypeLength,
1400 _In_ PPRIVILEGE_SET PrivilegeSet,
1401 _Inout_ PULONG PrivilegeSetLength,
1404{
1407}
1408
1409/* EOF */
#define PAGED_CODE()
unsigned char BOOLEAN
static GENERIC_MAPPING GenericMapping
Definition: SeInheritance.c:11
static PSID SepGetSDGroup(_In_ PSECURITY_DESCRIPTOR _SecurityDescriptor)
Retrieves the group from a security descriptor.
Definition: accesschk.c:699
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:786
static PSID SepGetSDOwner(_In_ PSECURITY_DESCRIPTOR _SecurityDescriptor)
Retrieves the main user from a security descriptor.
Definition: accesschk.c:672
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 ObjectTypeList, _In_ ULONG ObjectTypeListLength, _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:87
NTSTATUS NTAPI NtAccessCheckByType(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ PSID PrincipalSelfSid, _In_ HANDLE ClientToken, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_TYPE_LIST ObjectTypeList, _In_ ULONG ObjectTypeLength, _In_ PGENERIC_MAPPING GenericMapping, _In_ PPRIVILEGE_SET PrivilegeSet, _Inout_ PULONG PrivilegeSetLength, _Out_ PACCESS_MASK GrantedAccess, _Out_ PNTSTATUS AccessStatus)
Determines whether security access could be granted or not on an object by the requestor who wants su...
Definition: accesschk.c:1330
BOOLEAN NTAPI SepAccessCheck(_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 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 function that determines whether security access rights can be given to the calling thread in...
Definition: accesschk.c:373
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:930
NTSTATUS NTAPI NtAccessCheckByTypeResultList(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ PSID PrincipalSelfSid, _In_ HANDLE ClientToken, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_TYPE_LIST ObjectTypeList, _In_ ULONG ObjectTypeLength, _In_ PGENERIC_MAPPING GenericMapping, _In_ PPRIVILEGE_SET PrivilegeSet, _Inout_ PULONG PrivilegeSetLength, _Out_ PACCESS_MASK GrantedAccess, _Out_ PNTSTATUS AccessStatus)
Determines whether security access could be granted or not on an object by the requestor who wants su...
Definition: accesschk.c:1392
NTSTATUS NTAPI NtAccessCheck(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ HANDLE TokenHandle, _In_ ACCESS_MASK DesiredAccess, _In_ PGENERIC_MAPPING GenericMapping, _Out_opt_ PPRIVILEGE_SET PrivilegeSet, _Inout_ PULONG PrivilegeSetLength, _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:1040
static ULONG SepGetPrivilegeSetLength(_In_ PPRIVILEGE_SET PrivilegeSet)
Retrieves the length size of a set list of privileges structure.
Definition: accesschk.c:726
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define GENERIC_ACCESS
Definition: security.c:35
#define UNIMPLEMENTED
Definition: debug.h:115
@ 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 ULONG_PTR
Definition: config.h:101
#define PagedPool
Definition: env_spec_w32.h:308
#define ExGetPreviousMode
Definition: ex.h:139
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
struct _SID * PSID
Definition: eventlog.c:35
#define _Out_opt_
Definition: ms_sal.h:346
#define _Inout_
Definition: ms_sal.h:378
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
#define KernelMode
Definition: asm.h:34
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:718
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL Dacl
Definition: rtlfuncs.h:1593
_In_opt_ PSID Group
Definition: rtlfuncs.h:1646
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ SaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ OwnerSize PSID Owner
Definition: rtlfuncs.h:1597
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
#define SepAcquireTokenLockShared(Token)
Definition: se.h:280
@ AccessCheckMaximum
Definition: se.h:50
@ AccessCheckRegular
Definition: se.h:51
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 PACL SepGetDaclFromDescriptor(_Inout_ PVOID _Descriptor)
Definition: se.h:119
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:286
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
PSID NTAPI SepGetSidFromAce(_In_ UCHAR AceType, _In_ PACE Ace)
Captures a security identifier from a given access control entry. This identifier is valid for the wh...
Definition: sid.c:579
VOID SepDumpTokenDebugInfo(_In_opt_ PTOKEN Token)
Dumps debug information of an access token to the debugger.
Definition: debug.c:280
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
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:2159
#define STATUS_NO_IMPERSONATION_TOKEN
Definition: ntstatus.h:328
#define STATUS_INVALID_SECURITY_DESCR
Definition: ntstatus.h:357
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#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
#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 GenericAll
Definition: nt_native.h:568
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
#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
int ret
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
_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_ALLOWED_ACE_TYPE
Definition: setypes.h:717
#define TOKEN_QUERY
Definition: setypes.h:924
#define SE_SELF_RELATIVE
Definition: setypes.h:830
struct _LUID_AND_ATTRIBUTES LUID_AND_ATTRIBUTES
#define ACCESS_DENIED_ACE_TYPE
Definition: setypes.h:718
#define TOKEN_IS_RESTRICTED
Definition: setypes.h:1179
struct _PRIVILEGE_SET PRIVILEGE_SET