-
-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathOperation.h
More file actions
134 lines (112 loc) · 4.9 KB
/
Operation.h
File metadata and controls
134 lines (112 loc) · 4.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#pragma once
// mute compatibility concerns
#define _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
#include <Windows.h>
#include <AccCtrl.h>
#include <AclAPI.h>
#include <string>
#include <vector>
#include <queue>
#include <algorithm>
#include <cwchar>
#include <map>
#include <mutex>
#include <format>
#include <iostream>
typedef struct ObjectEntry
{
std::wstring Name;
SE_OBJECT_TYPE ObjectType = {};
DWORD Attributes = {};
FILETIME ModifiedTime = {};
FILETIME CreationTime = {};
LARGE_INTEGER FileSize = {};
unsigned int Depth = {};
std::wstring NameExtended;
HANDLE hObject = nullptr;
}
ObjectEntry;
// generic header for allow, deny, and audit object aces
using ACE_ACCESS_HEADER = struct {
BYTE AceType;
BYTE AceFlags;
WORD AceSize;
ACCESS_MASK Mask;
} ;
using PACE_ACCESS_HEADER = ACE_ACCESS_HEADER*;;
// macros to iterate through access control entries
#define FirstAce(Acl) reinterpret_cast<PACE_ACCESS_HEADER>(((PUCHAR)(Acl) + sizeof(ACL)))
#define NextAce(Ace) reinterpret_cast<PACE_ACCESS_HEADER>((PUCHAR)(Ace) + ((PACE_ACCESS_HEADER)(Ace))->AceSize)
// define our own version of sid length since its faster
constexpr DWORD SidLength(PSID x) { return sizeof(SID) + (static_cast<SID*>(x)->SubAuthorityCount - 1) * sizeof(static_cast<SID*>(x)->SubAuthority); };
constexpr bool SidMatch(PSID x, PSID y) { return SidLength(x) == SidLength(y) && __builtin_memcmp(x, y, min(SidLength(x), SidLength(y))) == 0; };
constexpr bool SidNotMatch(PSID x, PSID y) { return !SidMatch(x, y); };
// macros for checking file attributes
constexpr bool CheckBitSet(DWORD x, DWORD y) { return (((x) & (y)) != 0); }
constexpr bool IsDirectory(DWORD x) { return CheckBitSet(x, FILE_ATTRIBUTE_DIRECTORY); };
constexpr bool IsHiddenSystem(DWORD x) { return CheckBitSet(x, FILE_ATTRIBUTE_HIDDEN) && CheckBitSet(x, FILE_ATTRIBUTE_SYSTEM); };
constexpr bool IsReparsePoint(DWORD x) { return CheckBitSet(x, FILE_ATTRIBUTE_REPARSE_POINT); };
// a few simple defines for convenience
constexpr bool IsInherited(const ACE_ACCESS_HEADER* x) { return CheckBitSet((x)->AceFlags, INHERITED_ACE); };
constexpr bool HasContainerInherit(const ACE_ACCESS_HEADER* x) { return CheckBitSet((x)->AceFlags, CONTAINER_INHERIT_ACE); };
constexpr bool HasObjectInherit(const ACE_ACCESS_HEADER* x) { return CheckBitSet((x)->AceFlags, OBJECT_INHERIT_ACE); };
constexpr bool HasInheritOnly(const ACE_ACCESS_HEADER* x) { return CheckBitSet((x)->AceFlags, INHERIT_ONLY_ACE); };
constexpr bool HasNoPropogate(const ACE_ACCESS_HEADER* x) { return CheckBitSet((x)->AceFlags, NO_PROPAGATE_INHERIT_ACE); };
constexpr DWORD GetNonOiCiIoBits(const ACE_ACCESS_HEADER* x) { return ((~(CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE | INHERIT_ONLY_ACE)) & (x)->AceFlags); };
// string helper operations
constexpr void ConvertToUpper(std::wstring& str)
{
std::ranges::transform(str, str.begin(), towupper);
}
template <typename... Args>
constexpr std::wstring OutToCsv(Args const&... args)
{
std::wstring out;
((out += out.empty() ? L"\"" : L",\"",
out += std::wstring_view{ args },
out += L"\""), ...);
return out + L"\n";
}
template<typename... Args>
void Print(std::wformat_string<Args...> fmt, Args&&... args) noexcept
{
static std::mutex oPrintMutex;
const std::wstring sLine = std::format(fmt, std::forward<Args>(args)...) + L"\n";
std::lock_guard<std::mutex> oLock(oPrintMutex);
std::wcout << sLine;
}
typedef enum SidActionResult : char
{
Nothing = 0,
Replace = 1 << 0,
Remove = 1 << 1
}
SidActionResult;
class Operation
{
protected:
static std::vector<std::wstring> SplitArgs(std::wstring sInput, const std::wstring & sDelimiter);
static std::vector<std::wstring> ProcessAndCheckArgs(int iArgsRequired, std::queue<std::wstring> & oArgList, const std::wstring & sDelimiter = L":");
void ProcessGranularTargetting(std::wstring sScope);
public:
bool AppliesToDacl = false;
bool AppliesToSacl = false;
bool AppliesToOwner = false;
bool AppliesToGroup = false;
bool AppliesToSd = false;
bool AppliesToObject = false;
bool AppliesToRootOnly = false;
bool AppliesToChildrenOnly = false;
bool ExclusiveOperation = false;
DWORD SpecialCommitFlags = false;
PSID DefaultSidWhenEmpty = nullptr;
virtual bool ProcessSdAction(std::wstring & sFileName, ObjectEntry & tObjectEntry, PSECURITY_DESCRIPTOR & tDescriptor, bool & bDescReplacement) { return false; }
virtual bool ProcessAclAction(const WCHAR * sSdPart, ObjectEntry & tObjectEntry, PACL & tCurrentAcl, bool & bAclReplacement);
virtual bool ProcessSidAction(const WCHAR * sSdPart, ObjectEntry & tObjectEntry, PSID & tCurrentSid, bool & bSidReplacement);
virtual SidActionResult DetermineSid(const WCHAR * const sSdPart, ObjectEntry & tObjectEntry, PSID const tCurrentSid, PSID & tResultantSid) { return Nothing; }
virtual void ProcessObjectAction(ObjectEntry & tObjectEntry) { }
static PSID GetSidFromAce(PACE_ACCESS_HEADER tAce) noexcept;
Operation(std::queue<std::wstring> & oArgList) noexcept;
virtual ~Operation() = default;
};
#include "OperationFactory.h"