1 /*
2 * PROJECT:         ReactOS kernel-mode tests
3 * LICENSE:         GPLv2+ - See COPYING in the top level directory
4 * PURPOSE:         Kernel-Mode Test Suite Process Notification Routines test
5 * PROGRAMMER:      Constantine Belev (Moscow State Technical University)
6 *                  Denis Grishin (Moscow State Technical University)
7 *                  Egor Sinitsyn (Moscow State Technical University)
8 */
9 
10 #include <kmt_test.h>
11 #include <ntifs.h>
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 //------------------------------------------------------------------------------//
17 //      Testing Functions                                                       //
18 //------------------------------------------------------------------------------//
19 
20 // Testing function for SQIT
21 
22 void TestsSeQueryInformationToken(PACCESS_TOKEN Token)
23 {
24     NTSTATUS Status;
25     PVOID Buffer = NULL;
26     PSID sid;
27     PTOKEN_OWNER Towner;
28     PTOKEN_DEFAULT_DACL TDefDacl;
29     PTOKEN_GROUPS TGroups;
30     ULONG GroupCount;
31     PACL acl;
32     PTOKEN_STATISTICS TStats;
33     PTOKEN_TYPE TType;
34     PTOKEN_USER TUser;
35     BOOLEAN Flag;
36     ULONG i;
37 
38     //----------------------------------------------------------------//
39     // Testing SeQueryInformationToken with various args              //
40     //----------------------------------------------------------------//
41 
42     ok(Token != NULL, "Token is not captured. Testing SQIT interrupted\n\n");
43 
44     if (Token == NULL) return;
45 
46     Status = SeQueryInformationToken(Token, TokenOwner, &Buffer);
47     ok((Status == STATUS_SUCCESS), "SQIT with TokenOwner arg fails with status 0x%08X\n", Status);
48     if (Status == STATUS_SUCCESS)
49     {
50         ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenOwner arg. But Buffer == NULL\n");
51 
52         if (Buffer)
53         {
54             Towner = (TOKEN_OWNER *)Buffer;
55             sid = Towner->Owner;
56             ok((RtlValidSid(sid) == TRUE), "TokenOwner's SID is not a valid SID\n");
57             ExFreePool(Buffer);
58         }
59     }
60 
61     //----------------------------------------------------------------//
62 
63     Buffer = NULL;
64     Status = SeQueryInformationToken(Token, TokenDefaultDacl, &Buffer);
65     ok(Status == STATUS_SUCCESS, "SQIT with TokenDefaultDacl fails with status 0x%08X\n", Status);
66     if (Status == STATUS_SUCCESS)
67     {
68         ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenDefaultDacl arg. But Buffer == NULL\n");
69         if (Buffer)
70         {
71             TDefDacl = (PTOKEN_DEFAULT_DACL)Buffer;
72             acl = TDefDacl->DefaultDacl;
73             ok(((acl->AclRevision == ACL_REVISION || acl->AclRevision == ACL_REVISION_DS) == TRUE), "DACL is invalid\n");
74             ExFreePool(Buffer);
75         }
76     }
77 
78     //----------------------------------------------------------------//
79 
80     Buffer = NULL;
81     Status = SeQueryInformationToken(Token, TokenGroups, &Buffer);
82     ok(Status == STATUS_SUCCESS, "SQIT with TokenGroups fails with status 0x%08X\n", Status);
83     if (Status == STATUS_SUCCESS)
84     {
85         ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenGroups arg. But Buffer == NULL\n");
86         if (Buffer)
87         {
88             TGroups = (PTOKEN_GROUPS)Buffer;
89             GroupCount = TGroups->GroupCount;
90             Flag = TRUE;
91             for (i = 0; i < GroupCount; i++)
92             {
93                 sid = TGroups->Groups[i].Sid;
94                 if (!RtlValidSid(sid))
95                 {
96                     Flag = FALSE;
97                     break;
98                 }
99             }
100             ok((Flag == TRUE), "TokenGroup's SIDs are not valid\n");
101             ExFreePool(Buffer);
102         }
103     }
104 
105     //----------------------------------------------------------------//
106 
107     // Call SQIT with TokenImpersonationLevel argument
108     //
109     // What's up? Why SQIT fails with right arg?
110     // Because your token has Token->TokenType != TokenImpersonation. -hbelusca
111 
112     Buffer = NULL;
113     Status = SeQueryInformationToken(Token, TokenImpersonationLevel, &Buffer);
114     ok(Status == STATUS_SUCCESS, "SQIT with TokenImpersonationLevel fails with status 0x%08X\n", Status);
115     if (Buffer) ExFreePool(Buffer);
116 
117     Buffer = NULL;
118     Status = SeQueryInformationToken(Token, TokenImpersonationLevel, &Buffer);
119     ok(Status == STATUS_SUCCESS, "and again: SQIT with TokenImpersonationLevel fails with status 0x%08X\n", Status);
120     if (Status == STATUS_SUCCESS)
121     {
122         ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenImpersonationLevel arg. But Buffer == NULL\n");
123     } else {
124         ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n");
125     }
126     if (Buffer) ExFreePool(Buffer);
127 
128     //----------------------------------------------------------------//
129 
130     // Call SQIT with the 4 classes (TokenOrigin, TokenGroupsAndPrivileges,
131     // TokenRestrictedSids and TokenSandBoxInert) are not supported by
132     // SeQueryInformationToken (only NtQueryInformationToken supports them).
133     //
134 
135     Buffer = NULL;
136     Status = SeQueryInformationToken(Token, TokenOrigin, &Buffer);
137     ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenOrigin failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status);
138     ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n");
139 
140     Buffer = NULL;
141     Status = SeQueryInformationToken(Token, TokenGroupsAndPrivileges, &Buffer);
142     ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenGroupsAndPrivileges failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status);
143     ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n");
144 
145     Buffer = NULL;
146     Status = SeQueryInformationToken(Token, TokenRestrictedSids, &Buffer);
147     ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenRestrictedSids failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status);
148     ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n");
149 
150     Buffer = NULL;
151     Status = SeQueryInformationToken(Token, TokenSandBoxInert, &Buffer);
152     ok(Status == STATUS_INVALID_INFO_CLASS, "SQIT with TokenSandBoxInert failed with Status 0x%08X; expected STATUS_INVALID_INFO_CLASS\n", Status);
153     ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n");
154 
155     //----------------------------------------------------------------//
156 
157     Buffer = NULL;
158     Status = SeQueryInformationToken(Token, TokenStatistics, &Buffer);
159     ok(Status == STATUS_SUCCESS, "SQIT with TokenStatistics fails with status 0x%08X\n", Status);
160     if (Status == STATUS_SUCCESS)
161     {
162         ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenStatistics arg. But Buffer == NULL\n");
163         if (Buffer)
164         {
165             TStats = (PTOKEN_STATISTICS)Buffer;
166             // just put 0 into 1st arg or use trace to print TokenStatistics
167             ok(1, "print statistics:\n\tTokenID = %u_%d\n\tSecurityImperLevel = %d\n\tPrivCount = %d\n\tGroupCount = %d\n\n", TStats->TokenId.LowPart,
168                 TStats->TokenId.HighPart,
169                 TStats->ImpersonationLevel,
170                 TStats->PrivilegeCount,
171                 TStats->GroupCount
172                 );
173             ExFreePool(Buffer);
174         }
175     } else {
176         ok(Buffer == NULL, "Wrong. SQIT call failed. But Buffer != NULL\n");
177     }
178 
179     //----------------------------------------------------------------//
180 
181     Buffer = NULL;
182     Status = SeQueryInformationToken(Token, TokenType, &Buffer);
183     ok(Status == STATUS_SUCCESS, "SQIT with TokenType fails with status 0x%08X\n", Status);
184     if (Status == STATUS_SUCCESS)
185     {
186         ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenType arg. But Buffer == NULL\n");
187         if (Buffer)
188         {
189             TType = (PTOKEN_TYPE)Buffer;
190             ok((*TType == TokenPrimary || *TType == TokenImpersonation), "TokenType in not a primary nor impersonation. FAILED\n");
191             ExFreePool(Buffer);
192         }
193     }
194 
195     //----------------------------------------------------------------//
196 
197     Buffer = NULL;
198     Status = SeQueryInformationToken(Token, TokenUser, &Buffer);
199     ok(Status == STATUS_SUCCESS, "SQIT with TokenUser fails\n");
200     if (Status == STATUS_SUCCESS)
201     {
202         ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenUser arg. But Buffer == NULL\n");
203         if (Buffer)
204         {
205             TUser = (PTOKEN_USER)Buffer;
206             ok(RtlValidSid(TUser->User.Sid), "TokenUser has an invalid Sid\n");
207             ExFreePool(Buffer);
208         }
209     }
210 
211     //----------------------------------------------------------------//
212 
213     Buffer = NULL;
214     Status = SeQueryInformationToken(Token, TokenSandBoxInert, &Buffer);
215     ok(Status != STATUS_SUCCESS, "SQIT must fail with wrong TOKEN_INFORMATION_CLASS arg\n");
216 }
217 
218 //------------------------------------------------------------------------------//
219 
220 //------------------------------------------------------------------------------//
221 //      Body of the main test                                                   //
222 //------------------------------------------------------------------------------//
223 
224 START_TEST(SeQueryInfoToken)
225 {
226     PACCESS_STATE AccessState;
227     ACCESS_MASK AccessMask = MAXIMUM_ALLOWED;
228     ACCESS_MASK DesiredAccess = MAXIMUM_ALLOWED;
229     NTSTATUS Status = STATUS_SUCCESS;
230     PAUX_ACCESS_DATA AuxData = NULL;
231     PPRIVILEGE_SET NewPrivilegeSet;
232     BOOLEAN Checker;
233     PPRIVILEGE_SET Privileges = NULL;
234     PSECURITY_SUBJECT_CONTEXT SubjectContext = NULL;
235     PACCESS_TOKEN Token = NULL;
236     PTOKEN_PRIVILEGES TPrivileges;
237     PVOID Buffer;
238     POBJECT_TYPE PsProcessType = NULL;
239     PGENERIC_MAPPING GenericMapping;
240     ULONG i;
241 
242     SubjectContext = ExAllocatePool(PagedPool, sizeof(SECURITY_SUBJECT_CONTEXT));
243 
244     SeCaptureSubjectContext(SubjectContext);
245     SeLockSubjectContext(SubjectContext);
246     Token = SeQuerySubjectContextToken(SubjectContext);
247 
248     // Testing SQIT with current Token
249     TestsSeQueryInformationToken(Token);
250 
251     //----------------------------------------------------------------//
252     //      Creating an ACCESS_STATE structure                        //
253     //----------------------------------------------------------------//
254 
255     AccessState = ExAllocatePool(PagedPool, sizeof(ACCESS_STATE));
256     PsProcessType = ExAllocatePool(PagedPool, sizeof(OBJECT_TYPE));
257     AuxData = ExAllocatePool(PagedPool, 0xC8);
258     GenericMapping = ExAllocatePool(PagedPool, sizeof(GENERIC_MAPPING));
259 
260     Status = SeCreateAccessState(AccessState,
261                                  (PVOID)AuxData,
262                                  DesiredAccess,
263                                  GenericMapping
264                                 );
265 
266     ok((Status == STATUS_SUCCESS), "SeCreateAccessState failed with Status 0x%08X\n", Status);
267 
268     SeCaptureSubjectContext(&AccessState->SubjectSecurityContext);
269     SeLockSubjectContext(&AccessState->SubjectSecurityContext);
270     Token = SeQuerySubjectContextToken(&AccessState->SubjectSecurityContext);
271 
272     // Testing SQIT with AccessState Token
273     TestsSeQueryInformationToken(Token);
274 
275     //----------------------------------------------------------------//
276     //      Testing other functions                                   //
277     //----------------------------------------------------------------//
278 
279     //----------------------------------------------------------------//
280     //      Testing SeAppendPrivileges                                //
281     //----------------------------------------------------------------//
282 
283     AuxData->PrivilegeSet->PrivilegeCount = 1;
284 
285     //  Testing SeAppendPrivileges. Must change PrivilegeCount to 2 (1 + 1)
286 
287     NewPrivilegeSet = ExAllocatePool(PagedPool, sizeof(PRIVILEGE_SET));
288     NewPrivilegeSet->PrivilegeCount = 1;
289 
290     Status = SeAppendPrivileges(AccessState, NewPrivilegeSet);
291     ok(Status == STATUS_SUCCESS, "SeAppendPrivileges failed\n");
292     ok((AuxData->PrivilegeSet->PrivilegeCount == 2),"PrivelegeCount must be 2, but it is %d\n", AuxData->PrivilegeSet->PrivilegeCount);
293     ExFreePool(NewPrivilegeSet);
294 
295     //----------------------------------------------------------------//
296 
297     // Testing SeAppendPrivileges. Must change PrivilegeCount to 6 (2 + 4)
298 
299     NewPrivilegeSet = ExAllocatePool(PagedPool, 4*sizeof(PRIVILEGE_SET));
300     NewPrivilegeSet->PrivilegeCount = 4;
301 
302     Status = SeAppendPrivileges(AccessState, NewPrivilegeSet);
303     ok(Status == STATUS_SUCCESS, "SeAppendPrivileges failed\n");
304     ok((AuxData->PrivilegeSet->PrivilegeCount == 6),"PrivelegeCount must be 6, but it is %d\n", AuxData->PrivilegeSet->PrivilegeCount);
305     ExFreePool(NewPrivilegeSet);
306 
307     //----------------------------------------------------------------//
308     //      Testing SePrivilegeCheck                                  //
309     //----------------------------------------------------------------//
310 
311     // KPROCESSOR_MODE is set to KernelMode ===> Always return TRUE
312     ok(SePrivilegeCheck(AuxData->PrivilegeSet, &(AccessState->SubjectSecurityContext), KernelMode), "SePrivilegeCheck failed with KernelMode mode arg\n");
313     // and call it again
314     ok(SePrivilegeCheck(AuxData->PrivilegeSet, &(AccessState->SubjectSecurityContext), KernelMode), "SePrivilegeCheck failed with KernelMode mode arg\n");
315 
316     //----------------------------------------------------------------//
317 
318     // KPROCESSOR_MODE is set to UserMode. Expect false
319     ok(!SePrivilegeCheck(AuxData->PrivilegeSet, &(AccessState->SubjectSecurityContext), UserMode), "SePrivilegeCheck unexpected success with UserMode arg\n");
320 
321     //----------------------------------------------------------------//
322 
323     //----------------------------------------------------------------//
324     //      Testing SeFreePrivileges                                  //
325     //----------------------------------------------------------------//
326 
327     Privileges = NULL;
328     Checker = SeAccessCheck(
329         AccessState->SecurityDescriptor,
330         &AccessState->SubjectSecurityContext,
331         FALSE,
332         AccessState->OriginalDesiredAccess,
333         AccessState->PreviouslyGrantedAccess,
334         &Privileges,
335         (PGENERIC_MAPPING)((PCHAR*)PsProcessType + 52),
336         KernelMode,
337         &AccessMask,
338         &Status
339         );
340     ok(Checker, "Checker is NULL\n");
341     ok((Privileges != NULL), "Privileges is NULL\n");
342     if (Privileges)
343     {
344         trace("AuxData->PrivilegeSet->PrivilegeCount = %d ; Privileges->PrivilegeCount = %d\n",
345               AuxData->PrivilegeSet->PrivilegeCount, Privileges->PrivilegeCount);
346     }
347     if (Privileges) SeFreePrivileges(Privileges);
348 
349 
350     //----------------------------------------------------------------//
351     //      Testing SePrivilegeCheck                                  //
352     //----------------------------------------------------------------//
353     // I'm trying to make success call of SePrivilegeCheck from UserMode
354     // If we sets Privileges properly, can we expect true from SePrivilegeCheck?
355     // answer: yes
356     // This test demonstrates it
357 
358     Buffer = NULL;
359     Status = SeQueryInformationToken(Token, TokenPrivileges, &Buffer);
360     if (Status == STATUS_SUCCESS)
361     {
362         ok(Buffer != NULL, "Wrong. SQIT call was successful with TokenPrivileges arg. But Buffer == NULL\n");
363         if (Buffer)
364         {
365             TPrivileges = (PTOKEN_PRIVILEGES)(Buffer);
366             //trace("TPCount = %u\n\n", TPrivileges->PrivilegeCount);
367 
368             NewPrivilegeSet = ExAllocatePool(PagedPool, 14*sizeof(PRIVILEGE_SET));
369             NewPrivilegeSet->PrivilegeCount = 14;
370 
371             ok((SeAppendPrivileges(AccessState, NewPrivilegeSet)) == STATUS_SUCCESS, "SeAppendPrivileges failed\n");
372             ok((AuxData->PrivilegeSet->PrivilegeCount == 20),"PrivelegeCount must be 20, but it is %d\n", AuxData->PrivilegeSet->PrivilegeCount);
373             ExFreePool(NewPrivilegeSet);
374             for (i = 0; i < AuxData->PrivilegeSet->PrivilegeCount; i++)
375             {
376                 AuxData->PrivilegeSet->Privilege[i].Attributes = TPrivileges->Privileges[i].Attributes;
377                 AuxData->PrivilegeSet->Privilege[i].Luid = TPrivileges->Privileges[i].Luid;
378             }
379             //trace("AccessState->privCount = %u\n\n", ((PAUX_ACCESS_DATA)(AccessState->AuxData))->PrivilegeSet->PrivilegeCount);
380 
381             ok(SePrivilegeCheck(AuxData->PrivilegeSet, &(AccessState->SubjectSecurityContext), UserMode), "SePrivilegeCheck fails in UserMode, but I wish it will success\n");
382         }
383     }
384 
385     // Call SeFreePrivileges again
386 
387     Privileges = NULL;
388     Checker = SeAccessCheck(
389         AccessState->SecurityDescriptor,
390         &AccessState->SubjectSecurityContext,
391         TRUE,
392         AccessState->OriginalDesiredAccess,
393         AccessState->PreviouslyGrantedAccess,
394         &Privileges,
395         (PGENERIC_MAPPING)((PCHAR*)PsProcessType + 52),
396         KernelMode,
397         &AccessMask,
398         &Status
399         );
400     ok(Checker, "Checker is NULL\n");
401     ok((Privileges != NULL), "Privileges is NULL\n");
402     if (Privileges)
403     {
404         trace("AuxData->PrivilegeSet->PrivilegeCount = %d ; Privileges->PrivilegeCount = %d\n",
405               AuxData->PrivilegeSet->PrivilegeCount, Privileges->PrivilegeCount);
406     }
407     if (Privileges) SeFreePrivileges(Privileges);
408 
409     //----------------------------------------------------------------//
410     //      Missing for now                                           //
411     //----------------------------------------------------------------//
412 
413     SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
414     SeUnlockSubjectContext(SubjectContext);
415 
416     SeDeleteAccessState(AccessState);
417 
418     if (GenericMapping) ExFreePool(GenericMapping);
419     if (PsProcessType) ExFreePool(PsProcessType);
420     if (SubjectContext) ExFreePool(SubjectContext);
421     if (AuxData) ExFreePool(AuxData);
422     if (AccessState) ExFreePool(AccessState);
423 }