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