Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384/* * PROJECT: ReactOS Kernel * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: Security subsystem debug routines support * COPYRIGHT: Copyright 2022-2023 George Bișoc <george.bisoc@reactos.org> */
/* INCLUDES *******************************************************************/
#include <ntoskrnl.h>#define NDEBUG#include <debug.h>
/* PRIVATE FUNCTIONS **********************************************************/
#ifndef NDEBUG/** * @brief * Converts an Access Control Entry (ACE) type to a string. * * @return * Returns a converted ACE type strings. If no * known ACE type is found, it will return * UNKNOWN TYPE. */staticPCSTRSepGetAceTypeString( _In_ UCHAR AceType){#define TOSTR(x) #x static const PCSTR AceTypes[] = { TOSTR(ACCESS_ALLOWED_ACE_TYPE), TOSTR(ACCESS_DENIED_ACE_TYPE), TOSTR(SYSTEM_AUDIT_ACE_TYPE), TOSTR(SYSTEM_ALARM_ACE_TYPE), TOSTR(ACCESS_ALLOWED_COMPOUND_ACE_TYPE), TOSTR(ACCESS_ALLOWED_OBJECT_ACE_TYPE), TOSTR(ACCESS_DENIED_OBJECT_ACE_TYPE), TOSTR(SYSTEM_AUDIT_OBJECT_ACE_TYPE), TOSTR(SYSTEM_ALARM_OBJECT_ACE_TYPE), TOSTR(ACCESS_ALLOWED_CALLBACK_ACE_TYPE), TOSTR(ACCESS_DENIED_CALLBACK_ACE_TYPE), TOSTR(ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE), TOSTR(ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE), TOSTR(SYSTEM_AUDIT_CALLBACK_ACE_TYPE), TOSTR(SYSTEM_ALARM_CALLBACK_ACE_TYPE), TOSTR(SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE), TOSTR(SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE), TOSTR(SYSTEM_MANDATORY_LABEL_ACE_TYPE), };#undef TOSTR
if (AceType < RTL_NUMBER_OF(AceTypes)) return AceTypes[AceType]; else return "UNKNOWN TYPE";}
/** * @brief * Dumps the ACE flags to the debugger output. */staticVOIDSepDumpAceFlags( _In_ UCHAR AceFlags){#define ACE_FLAG_PRINT(x) \ if (AceFlags & x) \ { \ DbgPrint(#x "\n"); \ }
ACE_FLAG_PRINT(OBJECT_INHERIT_ACE); ACE_FLAG_PRINT(CONTAINER_INHERIT_ACE); ACE_FLAG_PRINT(NO_PROPAGATE_INHERIT_ACE); ACE_FLAG_PRINT(INHERIT_ONLY_ACE); ACE_FLAG_PRINT(INHERITED_ACE);#undef ACE_FLAG_PRINT}
/** * @brief * Iterates and dumps each ACE debug info in an ACL. */staticVOIDSepDumpAces( _In_ PACL Acl){ NTSTATUS Status; PACE Ace; ULONG AceIndex; PSID Sid; UNICODE_STRING SidString;
/* Loop all ACEs and dump their info */ for (AceIndex = 0; AceIndex < Acl->AceCount; AceIndex++) { /* Get the ACE at this index */ Status = RtlGetAce(Acl, AceIndex, (PVOID*)&Ace); if (!NT_SUCCESS(Status)) { /* * Normally this should never happen. * Just fail gracefully and stop further * debugging of ACEs. */ DbgPrint("SepDumpAces(): Failed to find the next ACE, stop dumping info...\n"); return; }
DbgPrint("================== %lu# ACE DUMP INFO ==================\n", AceIndex); DbgPrint("Ace -> 0x%p\n", Ace); DbgPrint("Ace->Header -> 0x%p\n", Ace->Header); DbgPrint("Ace->Header.AceType -> %s\n", SepGetAceTypeString(Ace->Header.AceType)); DbgPrint("Ace->AccessMask -> 0x%08lx\n", Ace->AccessMask);
Sid = SepGetSidFromAce(Ace); ASSERT(Sid); RtlConvertSidToUnicodeString(&SidString, Sid, TRUE); DbgPrint("Ace SID -> %wZ\n", &SidString); RtlFreeUnicodeString(&SidString);
DbgPrint("Ace->Header.AceSize -> %u\n", Ace->Header.AceSize); DbgPrint("Ace->Header.AceFlags:\n"); SepDumpAceFlags(Ace->Header.AceFlags); }}
/** * @brief * Dumps debug info of an Access Control List (ACL). */staticVOIDSepDumpAclInfo( _In_ PACL Acl, _In_ BOOLEAN IsSacl){ /* Dump relevant info */ DbgPrint("================== %s DUMP INFO ==================\n", IsSacl ? "SACL" : "DACL"); DbgPrint("Acl->AclRevision -> %u\n", Acl->AclRevision); DbgPrint("Acl->AclSize -> %u\n", Acl->AclSize); DbgPrint("Acl->AceCount -> %u\n", Acl->AceCount);
/* Dump all the ACEs present on this ACL */ SepDumpAces(Acl);}
/** * @brief * Dumps control flags of a security descriptor to the debugger. */staticVOIDSepDumpSdControlInfo( _In_ SECURITY_DESCRIPTOR_CONTROL SdControl){#define SD_CONTROL_PRINT(x) \ if (SdControl & x) \ { \ DbgPrint(#x "\n"); \ }
SD_CONTROL_PRINT(SE_OWNER_DEFAULTED); SD_CONTROL_PRINT(SE_GROUP_DEFAULTED); SD_CONTROL_PRINT(SE_DACL_PRESENT); SD_CONTROL_PRINT(SE_DACL_DEFAULTED); SD_CONTROL_PRINT(SE_SACL_PRESENT); SD_CONTROL_PRINT(SE_SACL_DEFAULTED); SD_CONTROL_PRINT(SE_DACL_UNTRUSTED); SD_CONTROL_PRINT(SE_SERVER_SECURITY); SD_CONTROL_PRINT(SE_DACL_AUTO_INHERIT_REQ); SD_CONTROL_PRINT(SE_SACL_AUTO_INHERIT_REQ); SD_CONTROL_PRINT(SE_DACL_AUTO_INHERITED); SD_CONTROL_PRINT(SE_SACL_AUTO_INHERITED); SD_CONTROL_PRINT(SE_DACL_PROTECTED); SD_CONTROL_PRINT(SE_SACL_PROTECTED); SD_CONTROL_PRINT(SE_RM_CONTROL_VALID); SD_CONTROL_PRINT(SE_SELF_RELATIVE);#undef SD_CONTROL_PRINT}
/** * @brief * Dumps each security identifier (SID) of an access token to debugger. */staticVOIDSepDumpSidsOfToken( _In_ PSID_AND_ATTRIBUTES Sids, _In_ ULONG SidCount){ ULONG SidIndex; UNICODE_STRING SidString;
/* Loop all SIDs and dump them */ for (SidIndex = 0; SidIndex < SidCount; SidIndex++) { RtlConvertSidToUnicodeString(&SidString, Sids[SidIndex].Sid, TRUE); DbgPrint("%lu# %wZ\n", SidIndex, &SidString); RtlFreeUnicodeString(&SidString); }}#endif
/* PUBLIC FUNCTIONS ***********************************************************/
/** * @brief * Dumps debug information of a security descriptor to the debugger. */VOIDSepDumpSdDebugInfo( _In_opt_ PISECURITY_DESCRIPTOR SecurityDescriptor){#ifndef NDEBUG UNICODE_STRING SidString; PSID OwnerSid, GroupSid; PACL Dacl, Sacl;#endif
/* Don't dump anything if no SD was provided */ if (!SecurityDescriptor) { return; }
#ifndef NDEBUG /* Cache the necessary security buffers to dump info from */ OwnerSid = SepGetOwnerFromDescriptor(SecurityDescriptor); GroupSid = SepGetGroupFromDescriptor(SecurityDescriptor); Sacl = SepGetSaclFromDescriptor(SecurityDescriptor); Dacl = SepGetDaclFromDescriptor(SecurityDescriptor);
DbgPrint("================== SECURITY DESCRIPTOR DUMP INFO ==================\n"); DbgPrint("SecurityDescriptor -> 0x%p\n", SecurityDescriptor); DbgPrint("SecurityDescriptor->Revision -> %u\n", SecurityDescriptor->Revision); DbgPrint("SecurityDescriptor->Control:\n"); SepDumpSdControlInfo(SecurityDescriptor->Control);
/* Dump the Owner SID if the SD belongs to an owner */ if (OwnerSid) { RtlConvertSidToUnicodeString(&SidString, OwnerSid, TRUE); DbgPrint("SD Owner SID -> %wZ\n", &SidString); RtlFreeUnicodeString(&SidString); }
/* Dump the Group SID if the SD belongs to a group */ if (GroupSid) { RtlConvertSidToUnicodeString(&SidString, GroupSid, TRUE); DbgPrint("SD Group SID -> %wZ\n", &SidString); RtlFreeUnicodeString(&SidString); }
/* Dump the ACL contents of SACL if this SD has one */ if (Sacl) { SepDumpAclInfo(Sacl, TRUE); }
/* Dump the ACL contents of DACL if this SD has one */ if (Dacl) { SepDumpAclInfo(Dacl, FALSE); }#endif}
/** * @brief * Dumps debug information of an access token to the debugger. */VOIDSepDumpTokenDebugInfo( _In_opt_ PTOKEN Token){#ifndef NDEBUG UNICODE_STRING SidString;#endif
/* Don't dump anything if no token was provided */ if (!Token) { return; }
#ifndef NDEBUG /* Dump relevant token info */ DbgPrint("================== ACCESS TOKEN DUMP INFO ==================\n"); DbgPrint("Token -> 0x%p\n", Token); DbgPrint("Token->ImageFileName -> %s\n", Token->ImageFileName); DbgPrint("Token->TokenSource.SourceName -> \"%-.*s\"\n", RTL_NUMBER_OF(Token->TokenSource.SourceName), Token->TokenSource.SourceName); DbgPrint("Token->TokenSource.SourceIdentifier -> %lu.%lu\n", Token->TokenSource.SourceIdentifier.HighPart, Token->TokenSource.SourceIdentifier.LowPart);
RtlConvertSidToUnicodeString(&SidString, Token->PrimaryGroup, TRUE); DbgPrint("Token primary group SID -> %wZ\n", &SidString); RtlFreeUnicodeString(&SidString);
DbgPrint("Token user and groups SIDs:\n"); SepDumpSidsOfToken(Token->UserAndGroups, Token->UserAndGroupCount);
if (SeTokenIsRestricted(Token)) { DbgPrint("Token restricted SIDs:\n"); SepDumpSidsOfToken(Token->RestrictedSids, Token->RestrictedSidCount); }#endif}
/** * @brief * Dumps security access rights to the debugger. */VOIDSepDumpAccessRightsStats( _In_ PACCESS_CHECK_RIGHTS AccessRights){ /* * Dump the access rights only if we have remaining rights * to dump in the first place. RemainingAccessRights can be 0 * if access check procedure has failed prematurely and this * member hasn't been filled yet. */ if (!AccessRights->RemainingAccessRights) { return; }
#ifndef NDEBUG DbgPrint("================== ACCESS CHECK RIGHTS STATISTICS ==================\n"); DbgPrint("Remaining access rights -> 0x%08lx\n", AccessRights->RemainingAccessRights); DbgPrint("Granted access rights -> 0x%08lx\n", AccessRights->GrantedAccessRights); DbgPrint("Denied access rights -> 0x%08lx\n", AccessRights->DeniedAccessRights);#endif}
/** * @brief * Dumps access and status values of each object type * in the result list. */VOIDSepDumpAccessAndStatusList( _In_ PACCESS_MASK GrantedAccessList, _In_ PNTSTATUS AccessStatusList, _In_ BOOLEAN IsResultList, _In_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength){#ifndef NDEBUG ULONG ResultListIndex; ULONG ObjectTypeIndex; ULONG ResultListLength;
DbgPrint("================== ACCESS & STATUS OBJECT TYPE LIST STATISTICS ==================\n"); ResultListLength = IsResultList ? ObjectTypeListLength : 1; for (ResultListIndex = 0; ResultListIndex < ResultListLength; ResultListIndex++) { DbgPrint("Result Index #%lu, Granted access rights -> 0x%08lx, Access status -> 0x%08lx\n", ResultListIndex, GrantedAccessList[ResultListIndex], AccessStatusList[ResultListIndex]); }
for (ObjectTypeIndex = 0; ObjectTypeIndex < ObjectTypeListLength; ObjectTypeIndex++) { DbgPrint("================== #%lu OBJECT ACCESS RIGHTS ==================\n", ObjectTypeIndex); DbgPrint("Remaining access rights -> 0x%08lx\n", ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.RemainingAccessRights); DbgPrint("Granted access rights -> 0x%08lx\n", ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.GrantedAccessRights); DbgPrint("Denied access rights -> 0x%08lx\n", ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.DeniedAccessRights); }#endif}
/* EOF */