1 /*
2  * PROJECT:         ReactOS kernel-mode tests
3  * LICENSE:         LGPLv2.1+ - See COPYING.LIB in the top level directory
4  * PURPOSE:         Kernel-Mode Test Suite Helper functions for Se tests
5  * PROGRAMMER:      Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #include <kmt_test.h>
9 #include "se.h"
10 
11 NTSTATUS
RtlxAddAuditAccessAceEx(_Inout_ PACL Acl,_In_ ULONG Revision,_In_ ULONG Flags,_In_ ACCESS_MASK AccessMask,_In_ PSID Sid,_In_ BOOLEAN Success,_In_ BOOLEAN Failure)12 RtlxAddAuditAccessAceEx(
13     _Inout_ PACL Acl,
14     _In_ ULONG Revision,
15     _In_ ULONG Flags,
16     _In_ ACCESS_MASK AccessMask,
17     _In_ PSID Sid,
18     _In_ BOOLEAN Success,
19     _In_ BOOLEAN Failure)
20 {
21     NTSTATUS Status;
22     USHORT AceSize;
23     PSYSTEM_AUDIT_ACE Ace;
24 
25     if (Success) Flags |= SUCCESSFUL_ACCESS_ACE_FLAG;
26     if (Failure) Flags |= FAILED_ACCESS_ACE_FLAG;
27 
28     AceSize = FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart) + RtlLengthSid(Sid);
29     Ace = ExAllocatePoolWithTag(PagedPool, AceSize, 'cAmK');
30     if (!Ace)
31         return STATUS_INSUFFICIENT_RESOURCES;
32     Ace->Header.AceType = SYSTEM_AUDIT_ACE_TYPE;
33     Ace->Header.AceFlags = Flags;
34     Ace->Header.AceSize = AceSize;
35     Ace->Mask = AccessMask;
36     Status = RtlCopySid(AceSize - FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart),
37                         (PSID)&Ace->SidStart,
38                         Sid);
39     ASSERT(NT_SUCCESS(Status));
40     if (NT_SUCCESS(Status))
41     {
42         Status = RtlAddAce(Acl,
43                            Revision,
44                            MAXULONG,
45                            Ace,
46                            AceSize);
47     }
48     ExFreePoolWithTag(Ace, 'cAmK');
49     return Status;
50 }
51 
52 NTSTATUS
RtlxAddMandatoryLabelAceEx(_Inout_ PACL Acl,_In_ ULONG Revision,_In_ ULONG Flags,_In_ ACCESS_MASK AccessMask,_In_ PSID Sid)53 RtlxAddMandatoryLabelAceEx(
54     _Inout_ PACL Acl,
55     _In_ ULONG Revision,
56     _In_ ULONG Flags,
57     _In_ ACCESS_MASK AccessMask,
58     _In_ PSID Sid)
59 {
60     NTSTATUS Status;
61     USHORT AceSize;
62     PSYSTEM_MANDATORY_LABEL_ACE Ace;
63 
64     AceSize = FIELD_OFFSET(SYSTEM_MANDATORY_LABEL_ACE, SidStart) + RtlLengthSid(Sid);
65     Ace = ExAllocatePoolWithTag(PagedPool, AceSize, 'cAmK');
66     if (!Ace)
67         return STATUS_INSUFFICIENT_RESOURCES;
68     Ace->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE;
69     Ace->Header.AceFlags = Flags;
70     Ace->Header.AceSize = AceSize;
71     Ace->Mask = AccessMask;
72     Status = RtlCopySid(AceSize - FIELD_OFFSET(SYSTEM_MANDATORY_LABEL_ACE, SidStart),
73                         (PSID)&Ace->SidStart,
74                         Sid);
75     ASSERT(NT_SUCCESS(Status));
76     if (NT_SUCCESS(Status))
77     {
78         Status = RtlAddAce(Acl,
79                            Revision,
80                            MAXULONG,
81                            Ace,
82                            AceSize);
83     }
84     ExFreePoolWithTag(Ace, 'cAmK');
85     return Status;
86 }
87 
88 VOID
CheckSid__(_In_ PSID Sid,_In_ ULONG SidSize,_In_ PISID ExpectedSid,_In_ PCSTR FileAndLine)89 CheckSid__(
90     _In_ PSID Sid,
91     _In_ ULONG SidSize,
92     _In_ PISID ExpectedSid,
93     _In_ PCSTR FileAndLine)
94 {
95     BOOLEAN Okay;
96     ULONG Length;
97 
98     KmtOk(Sid != NULL, FileAndLine, "Sid is NULL\n");
99     if (KmtSkip(Sid != NULL, FileAndLine, "No Sid\n"))
100         return;
101     if (KmtSkip(SidSize >= sizeof(ULONG), FileAndLine, "Sid too small: %lu\n", SidSize))
102         return;
103     Okay = RtlValidSid(Sid);
104     KmtOk(Okay == TRUE, FileAndLine, "Invalid Sid\n");
105     if (KmtSkip(Okay, FileAndLine, "Invalid Sid\n"))
106         return;
107 
108     Length = RtlLengthSid(Sid);
109     KmtOk(SidSize >= Length, FileAndLine, "SidSize %lu too small, need %lu\n", SidSize, Length);
110     if (KmtSkip(SidSize >= Length, FileAndLine, "Sid too small\n"))
111         return;
112     Okay = RtlEqualSid(Sid, ExpectedSid);
113     KmtOk(Okay, FileAndLine, "Sids %p and %p not equal\n", Sid, ExpectedSid);
114     if (!Okay)
115     {
116         WCHAR Buffer1[128];
117         WCHAR Buffer2[128];
118         UNICODE_STRING SidString1, SidString2;
119         RtlInitEmptyUnicodeString(&SidString1, Buffer1, sizeof(Buffer1));
120         RtlInitEmptyUnicodeString(&SidString2, Buffer2, sizeof(Buffer2));
121         (void)RtlConvertSidToUnicodeString(&SidString1, Sid, FALSE);
122         (void)RtlConvertSidToUnicodeString(&SidString2, ExpectedSid, FALSE);
123         KmtOk(0, FileAndLine, "Got %wZ, expected %wZ\n", &SidString1, &SidString2);
124     }
125 }
126 
127 VOID
VCheckAcl__(_In_ PACL Acl,_In_ ULONG AceCount,_In_ PCSTR FileAndLine,_In_ va_list Arguments)128 VCheckAcl__(
129     _In_ PACL Acl,
130     _In_ ULONG AceCount,
131     _In_ PCSTR FileAndLine,
132     _In_ va_list Arguments)
133 {
134     ULONG i;
135     ULONG Offset;
136     PACE_HEADER AceHeader;
137     INT AceType;
138     INT AceFlags;
139     ACCESS_MASK Mask;
140     PISID Sid;
141     PACCESS_ALLOWED_ACE AllowedAce;
142     PACCESS_DENIED_ACE DeniedAce;
143     PSYSTEM_AUDIT_ACE AuditAce;
144 
145     KmtOk(Acl != NULL, FileAndLine, "Acl is NULL\n");
146     if (KmtSkip(Acl != NULL, FileAndLine, "No ACL\n"))
147         return;
148     KmtOk((ULONG_PTR)Acl % sizeof(ULONG) == 0, FileAndLine, "Unaligned ACL %p\n", Acl);
149     KmtOk(Acl->AclRevision == ACL_REVISION, FileAndLine, "AclRevision is %u\n", Acl->AclRevision);
150     KmtOk(Acl->Sbz1 == 0, FileAndLine, "Sbz1 is %u\n", Acl->Sbz1);
151     KmtOk(Acl->Sbz2 == 0, FileAndLine, "Sbz2 is %u\n", Acl->Sbz2);
152     KmtOk(Acl->AclSize >= sizeof(*Acl), FileAndLine, "AclSize too small: %u\n", Acl->AclSize);
153     KmtOk(Acl->AceCount == AceCount, FileAndLine, "AceCount is %u, expected %lu\n", Acl->AceCount, AceCount);
154     Offset = sizeof(*Acl);
155     for (i = 0; i < Acl->AceCount; i++)
156     {
157         KmtOk(Acl->AclSize >= Offset + sizeof(*AceHeader), FileAndLine, "AclSize too small (%u) at Offset %lu, ACE #%lu\n", Acl->AclSize, Offset, i);
158         if (Acl->AclSize < Offset + sizeof(*AceHeader))
159             break;
160         AceHeader = (PACE_HEADER)((PUCHAR)Acl + Offset);
161         KmtOk((ULONG_PTR)AceHeader % sizeof(ULONG) == 0, FileAndLine, "[%lu] Unaligned ACE %p\n", i, AceHeader);
162         KmtOk(AceHeader->AceSize % sizeof(ULONG) == 0, FileAndLine, "[%lu] Unaligned ACE size %u\n", i, AceHeader->AceSize);
163         KmtOk(Acl->AclSize >= Offset + AceHeader->AceSize, FileAndLine, "[%lu] AclSize too small (%u) at Offset %lu\n", i, Acl->AclSize, Offset);
164         if (Acl->AclSize < Offset + AceHeader->AceSize)
165             break;
166         Offset += AceHeader->AceSize;
167         if (i >= AceCount)
168             continue;
169         AceType = va_arg(Arguments, INT);
170         AceFlags = va_arg(Arguments, INT);
171         KmtOk(AceHeader->AceType == AceType, FileAndLine, "[%lu] AceType is %u, expected %u\n", i, AceHeader->AceType, AceType);
172         KmtOk(AceHeader->AceFlags == AceFlags, FileAndLine, "[%lu] AceFlags is 0x%x, expected 0x%x\n", i, AceHeader->AceFlags, AceFlags);
173         if (AceType == ACCESS_ALLOWED_ACE_TYPE)
174         {
175             Sid = va_arg(Arguments, PSID);
176             Mask = va_arg(Arguments, INT);
177             KmtOk(AceHeader->AceSize >= sizeof(*AllowedAce), FileAndLine, "[%lu] AllowedAce AceSize too small: %u\n", i, AceHeader->AceSize);
178             if (AceHeader->AceSize < sizeof(*AllowedAce))
179                 continue;
180             AllowedAce = (PACCESS_ALLOWED_ACE)AceHeader;
181             KmtOk(AllowedAce->Mask == Mask, FileAndLine, "[%lu] AllowedAce Mask is 0x%lx, expected 0x%lx\n", i, AllowedAce->Mask, Mask);
182             CheckSid__((PSID)&AllowedAce->SidStart,
183                        AceHeader->AceSize - FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart),
184                        Sid,
185                        FileAndLine);
186         }
187         else if (AceType == ACCESS_DENIED_ACE_TYPE)
188         {
189             Sid = va_arg(Arguments, PSID);
190             Mask = va_arg(Arguments, INT);
191             KmtOk(AceHeader->AceSize >= sizeof(*DeniedAce), FileAndLine, "[%lu] DeniedAce AceSize too small: %u\n", i, AceHeader->AceSize);
192             if (AceHeader->AceSize < sizeof(*DeniedAce))
193                 continue;
194             DeniedAce = (PACCESS_DENIED_ACE)AceHeader;
195             KmtOk(DeniedAce->Mask == Mask, FileAndLine, "[%lu] DeniedAce Mask is 0x%lx, expected 0x%lx\n", i, DeniedAce->Mask, Mask);
196             CheckSid__((PSID)&DeniedAce->SidStart,
197                        AceHeader->AceSize - FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart),
198                        Sid,
199                        FileAndLine);
200         }
201         else if (AceType == SYSTEM_AUDIT_ACE_TYPE)
202         {
203             Sid = va_arg(Arguments, PSID);
204             Mask = va_arg(Arguments, INT);
205             KmtOk(AceHeader->AceSize >= sizeof(*AuditAce), FileAndLine, "[%lu] AuditAce AceSize too small: %u\n", i, AceHeader->AceSize);
206             if (AceHeader->AceSize < sizeof(*AuditAce))
207                 continue;
208             AuditAce = (PSYSTEM_AUDIT_ACE)AceHeader;
209             KmtOk(AuditAce->Mask == Mask, FileAndLine, "[%lu] AuditAce Mask is 0x%lx, expected 0x%lx\n", i, AuditAce->Mask, Mask);
210             CheckSid__((PSID)&AuditAce->SidStart,
211                        AceHeader->AceSize - FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart),
212                        Sid,
213                        FileAndLine);
214         }
215     }
216 }
217 
218 VOID
CheckAcl__(_In_ PACL Acl,_In_ ULONG AceCount,_In_ PCSTR FileAndLine,...)219 CheckAcl__(
220     _In_ PACL Acl,
221     _In_ ULONG AceCount,
222     _In_ PCSTR FileAndLine,
223     ...)
224 {
225     va_list Arguments;
226 
227     va_start(Arguments, FileAndLine);
228     VCheckAcl__(Acl, AceCount, FileAndLine, Arguments);
229     va_end(Arguments);
230 }
231