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