7c042821ee0a63f649b3e683b81332b0d97482e1
[reactos.git] / rosapps / tests / tokentest / tokentest.c
1 #define UNICODE
2 #define _UNICODE
3
4 #define ANONYMOUSUNIONS
5 #include <windows.h>
6 #include <stdlib.h>
7
8 #define NTOS_MODE_USER
9 #include <ndk/ntndk.h>
10
11
12 #define INCLUDE_THE_DDK_HEADERS
13 #ifdef INCLUDE_THE_DDK_HEADERS
14 #include <ddk/ntddk.h>
15 #define ROS_ACE_HEADER ACE_HEADER
16 #define ROS_ACE ACE
17
18 #else
19 typedef LONG NTSTATUS, *PNTSTATUS;
20
21 typedef struct _UNICODE_STRING
22 {
23 USHORT Length;
24 USHORT MaximumLength;
25 PWSTR Buffer;
26 } UNICODE_STRING, *PUNICODE_STRING;
27
28 typedef struct _OBJECT_ATTRIBUTES {
29 ULONG Length;
30 HANDLE RootDirectory;
31 PUNICODE_STRING ObjectName;
32 ULONG Attributes;
33 PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR
34 PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE
35 } OBJECT_ATTRIBUTES;
36 typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;
37
38 typedef struct _ROS_ACE_HEADER
39 {
40 CHAR AceType;
41 CHAR AceFlags;
42 USHORT AceSize;
43 } ROS_ACE_HEADER, *PROS_ACE_HEADER;
44
45 typedef struct
46 {
47 ACE_HEADER Header;
48 ACCESS_MASK AccessMask;
49 } ROS_ACE, *PROS_ACE;
50
51 NTSYSAPI
52 NTSTATUS
53 NTAPI
54 RtlConvertSidToUnicodeString (
55 IN OUT PUNICODE_STRING String,
56 IN PSID Sid,
57 IN BOOLEAN AllocateString
58 );
59
60 NTSYSAPI
61 NTSTATUS
62 NTAPI
63 RtlCreateAcl(
64 PACL Acl,
65 ULONG AclSize,
66 ULONG AclRevision);
67
68 NTSYSAPI
69 NTSTATUS
70 NTAPI
71 RtlAddAccessAllowedAce (
72 PACL Acl,
73 ULONG Revision,
74 ACCESS_MASK AccessMask,
75 PSID Sid
76 );
77
78 NTSYSAPI
79 NTSTATUS
80 NTAPI
81 RtlGetAce (
82 PACL Acl,
83 ULONG AceIndex,
84 PROS_ACE *Ace
85 );
86
87 NTSYSAPI
88 NTSTATUS
89 NTAPI
90 ZwAllocateLocallyUniqueId(
91 OUT PLUID Luid
92 );
93
94 NTSYSAPI
95 NTSTATUS
96 NTAPI
97 ZwCreateToken(
98 OUT PHANDLE TokenHandle,
99 IN ACCESS_MASK DesiredAccess,
100 IN POBJECT_ATTRIBUTES ObjectAttributes,
101 IN TOKEN_TYPE TokenType,
102 IN PLUID AuthenticationId,
103 IN PLARGE_INTEGER ExpirationTime,
104 IN PTOKEN_USER TokenUser,
105 IN PTOKEN_GROUPS TokenGroups,
106 IN PTOKEN_PRIVILEGES TokenPrivileges,
107 IN PTOKEN_OWNER TokenOwner,
108 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup,
109 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl,
110 IN PTOKEN_SOURCE TokenSource
111 );
112 #define NT_SUCCESS(StatCode) ((NTSTATUS)(StatCode) >= 0)
113 #endif
114
115 #include <stdio.h>
116
117 #define INITIAL_PRIV_ENABLED SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED
118 #define INITIAL_PRIV_DISABLED 0
119 LUID_AND_ATTRIBUTES InitialPrivilegeSet[] =
120 {
121 { { 0x00000007, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeTcbPrivilege
122 { { 0x00000002, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeCreateTokenPrivilege
123 { { 0x00000009, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeTakeOwnershipPrivilege
124 { { 0x0000000f, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeCreatePagefilePrivilege
125 { { 0x00000004, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeLockMemoryPrivilege
126 { { 0x00000003, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeAssignPrimaryTokenPrivilege
127 { { 0x00000005, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeIncreaseQuotaPrivilege
128 { { 0x0000000e, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeIncreaseBasePriorityPrivilege
129 { { 0x00000010, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeCreatePermanentPrivilege
130 { { 0x00000014, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeDebugPrivilege
131 { { 0x00000015, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeAuditPrivilege
132 { { 0x00000008, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeSecurityPrivilege
133 { { 0x00000016, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeSystemEnvironmentPrivilege
134 { { 0x00000017, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeChangeNotifyPrivilege
135 { { 0x00000011, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeBackupPrivilege
136 { { 0x00000012, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeRestorePrivilege
137 { { 0x00000013, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeShutdownPrivilege
138 { { 0x0000000a, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeLoadDriverPrivilege
139 { { 0x0000000d, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeProfileSingleProcessPrivilege
140 { { 0x0000000c, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeSystemtimePrivilege
141 { { 0x00000019, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeUndockPrivilege
142 { { 0x0000001c, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeManageVolumePrivilege
143 };
144
145 typedef struct _SID_2
146 {
147 UCHAR Revision;
148 UCHAR SubAuthorityCount;
149 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
150 ULONG SubAuthority[2];
151 } SID_2;
152
153 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
154 void
155 PrintSid(SID_AND_ATTRIBUTES* pSid, TOKEN_OWNER* pOwner, TOKEN_PRIMARY_GROUP* pPrimary)
156 {
157 UNICODE_STRING scSid;
158
159 RtlConvertSidToUnicodeString(&scSid, pSid->Sid, TRUE);
160 printf("%wZ [", &scSid);
161 LocalFree(scSid.Buffer);
162
163 if ( EqualSid(pSid->Sid, pOwner->Owner) )
164 printf("owner,");
165
166 if ( EqualSid(pSid->Sid, pPrimary->PrimaryGroup) )
167 printf("primary,");
168
169 if ( pSid->Attributes & SE_GROUP_ENABLED )
170 {
171 if ( pSid->Attributes & SE_GROUP_ENABLED_BY_DEFAULT )
172 printf("enabled-default,");
173 else
174 printf("enabled,");
175 }
176
177 if ( pSid->Attributes & SE_GROUP_LOGON_ID )
178 printf("logon,");
179
180
181 if ( pSid->Attributes & SE_GROUP_MANDATORY )
182 printf("mandatory,");
183
184 printf("]\n");
185 }
186
187 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
188 void
189 DisplayTokenSids(TOKEN_USER* pUser,
190 TOKEN_GROUPS* pGroups,
191 TOKEN_OWNER* pOwner,
192 TOKEN_PRIMARY_GROUP* pPrimary)
193 {
194 DWORD i;
195
196 printf("\nSids:\n");
197 PrintSid(&pUser->User, pOwner, pPrimary);
198 printf("\nGroups:\n");
199 for (i = 0; i < pGroups->GroupCount; i++)
200 PrintSid(&pGroups->Groups[i], pOwner, pPrimary);
201 }
202
203 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
204 void
205 DisplayTokenPrivileges(TOKEN_PRIVILEGES* pPriv)
206 {
207 WCHAR buffer[256];
208 DWORD i;
209
210 printf("\nprivileges:\n");
211 for (i = 0; i < pPriv->PrivilegeCount; i++)
212 {
213 DWORD cbName = sizeof(buffer) / sizeof(buffer[0]);
214 LookupPrivilegeName(0, &pPriv->Privileges[i].Luid, buffer, &cbName);
215
216 printf("%S{0x%08x, 0x%08x} [", buffer, pPriv->Privileges[i].Luid.HighPart, pPriv->Privileges[i].Luid.LowPart);
217
218 if ( pPriv->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED )
219 printf("enabled,");
220 if ( pPriv->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED_BY_DEFAULT )
221 printf("default,");
222 if ( pPriv->Privileges[i].Attributes & SE_PRIVILEGE_USED_FOR_ACCESS )
223 printf("used");
224
225 printf("]\n");
226 }
227 }
228
229 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
230 void
231 DisplayDacl(PACL pAcl)
232 {
233 DWORD i;
234 NTSTATUS status;
235
236 if ( ! pAcl )
237 {
238 printf("\nNo Default Dacl.\n");
239 return;
240 }
241
242 printf("\nDacl:\n");
243 for (i = 0; i < pAcl->AceCount; i++)
244 {
245 UNICODE_STRING scSid;
246 ROS_ACE* pAce;
247 LPWSTR wszType = 0;
248 PSID pSid;
249
250 status = RtlGetAce(pAcl, i, (ROS_ACE**) &pAce);
251 if ( ! NT_SUCCESS(status) )
252 {
253 printf("RtlGetAce(): status = 0x%08x\n", status);
254 break;
255 }
256
257 pSid = (PSID) (pAce + 1);
258 if ( pAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE )
259 wszType = L"allow";
260 if ( pAce->Header.AceType == ACCESS_DENIED_ACE_TYPE )
261 wszType = L"deny ";
262
263 status = RtlConvertSidToUnicodeString(&scSid, pSid, TRUE);
264 if ( ! NT_SUCCESS(status) )
265 {
266 printf("RtlConvertSidToUnicodeString(): status = 0x%08x\n", status);
267 break;
268 }
269
270 printf("%d.) %S %wZ 0x%08x\n", i, wszType, &scSid, pAce->AccessMask);
271 LocalFree(scSid.Buffer);
272 }
273 }
274
275 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
276 PVOID
277 GetFromToken(HANDLE hToken, TOKEN_INFORMATION_CLASS tic)
278 {
279 BOOL bResult;
280 DWORD n;
281 PBYTE p = 0;
282
283 bResult = GetTokenInformation(hToken, tic, 0, 0, &n);
284 if ( ! bResult && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
285 return 0;
286
287 p = (PBYTE) malloc(n);
288 if ( ! GetTokenInformation(hToken, tic, p, n, &n) )
289 {
290 printf("GetFromToken() failed for TOKEN_INFORMATION_CLASS(%d): %d\n", tic, GetLastError());
291 free(p);
292 return 0;
293 }
294
295 return p;
296 }
297
298 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
299 void
300 DisplayToken(HANDLE hTokenSource)
301 {
302 TOKEN_USER* pTokenUser = (PTOKEN_USER) GetFromToken(hTokenSource, TokenUser);
303 TOKEN_GROUPS* pTokenGroups = (PTOKEN_GROUPS) GetFromToken(hTokenSource, TokenGroups);
304 TOKEN_OWNER* pTokenOwner = (PTOKEN_OWNER) GetFromToken(hTokenSource, TokenOwner);
305 TOKEN_PRIMARY_GROUP* pTokenPrimaryGroup = (PTOKEN_PRIMARY_GROUP) GetFromToken(hTokenSource, TokenPrimaryGroup);
306 TOKEN_PRIVILEGES* pTokenPrivileges = (PTOKEN_PRIVILEGES) GetFromToken(hTokenSource, TokenPrivileges);
307 TOKEN_DEFAULT_DACL* pTokenDefaultDacl = (PTOKEN_DEFAULT_DACL) GetFromToken(hTokenSource, TokenDefaultDacl);
308
309 DisplayTokenSids(pTokenUser, pTokenGroups, pTokenOwner, pTokenPrimaryGroup);
310 // DisplayTokenPrivileges(pTokenPrivileges);
311 DisplayDacl(pTokenDefaultDacl->DefaultDacl);
312
313 free(pTokenUser);
314 free(pTokenGroups);
315 free(pTokenOwner);
316 free(pTokenPrimaryGroup);
317 free(pTokenPrivileges);
318 free(pTokenDefaultDacl);
319 }
320
321 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
322 BOOL
323 EnablePrivilege(LPWSTR wszName)
324 {
325 HANDLE hToken;
326 TOKEN_PRIVILEGES priv = {1, {{{0, 0}, SE_PRIVILEGE_ENABLED}}};
327 BOOL bResult;
328
329 LookupPrivilegeValue(0, wszName, &priv.Privileges[0].Luid);
330
331 OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
332
333 AdjustTokenPrivileges(hToken, FALSE, &priv, sizeof priv, 0, 0);
334 bResult = GetLastError() == ERROR_SUCCESS;
335
336 CloseHandle(hToken);
337 return bResult;
338 }
339
340 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
341 NTSTATUS
342 CreateInitialSystemToken(HANDLE* phSystemToken)
343 {
344 static SID sidSystem = { 1, 1, {SECURITY_NT_AUTHORITY}, {SECURITY_LOCAL_SYSTEM_RID} };
345 static SID sidEveryone = { 1, 1, {SECURITY_WORLD_SID_AUTHORITY}, {SECURITY_WORLD_RID} };
346 static SID sidAuthenticatedUser = { 1, 1, {SECURITY_NT_AUTHORITY}, {SECURITY_AUTHENTICATED_USER_RID} };
347 static SID_2 sidAdministrators = { 1, 2, {SECURITY_NT_AUTHORITY}, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS} };
348 static const int nGroupCount = 3;
349
350 NTSTATUS status;
351 ULONG uSize;
352 DWORD i;
353
354 TOKEN_USER tkUser;
355 TOKEN_OWNER tkDefaultOwner;
356 TOKEN_PRIMARY_GROUP tkPrimaryGroup;
357
358 TOKEN_GROUPS* ptkGroups = 0;
359 TOKEN_PRIVILEGES* ptkPrivileges = 0;
360 TOKEN_DEFAULT_DACL tkDefaultDacl = { 0 };
361
362 LARGE_INTEGER tkExpiration;
363
364 LUID authId = SYSTEM_LUID;
365
366 TOKEN_SOURCE source =
367 {
368 { '*', '*', 'A', 'N', 'O', 'N', '*', '*' },
369 {0, 0}
370 };
371
372 SECURITY_QUALITY_OF_SERVICE sqos =
373 {
374 sizeof(sqos),
375 SecurityAnonymous,
376 SECURITY_STATIC_TRACKING,
377 FALSE
378 };
379
380 OBJECT_ATTRIBUTES oa =
381 {
382 sizeof(oa),
383 0,
384 0,
385 0,
386 0,
387 &sqos
388 };
389
390 tkExpiration.QuadPart = -1;
391 status = ZwAllocateLocallyUniqueId(&source.SourceIdentifier);
392 if ( status != 0 )
393 return status;
394
395 tkUser.User.Sid = &sidSystem;
396 tkUser.User.Attributes = 0;
397
398 // Under WinXP (the only MS OS I've tested) ZwCreateToken()
399 // squawks if we use sidAdministrators here -- though running
400 // a progrem under AT and using the DisplayToken() function
401 // shows that the system token does default ownership to
402 // Administrator.
403
404 // For now, default ownership to system, since that works
405 tkDefaultOwner.Owner = &sidSystem;
406 tkPrimaryGroup.PrimaryGroup = &sidSystem;
407
408 uSize = sizeof(TOKEN_GROUPS) - sizeof(ptkGroups->Groups);
409 uSize += sizeof(SID_AND_ATTRIBUTES) * nGroupCount;
410
411 ptkGroups = (TOKEN_GROUPS*) malloc(uSize);
412 ptkGroups->GroupCount = nGroupCount;
413
414 ptkGroups->Groups[0].Sid = (SID*) &sidAdministrators;
415 ptkGroups->Groups[0].Attributes = SE_GROUP_ENABLED;
416
417 ptkGroups->Groups[1].Sid = &sidEveryone;
418 ptkGroups->Groups[1].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
419
420 ptkGroups->Groups[2].Sid = &sidAuthenticatedUser;
421 ptkGroups->Groups[2].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
422
423 uSize = sizeof(TOKEN_PRIVILEGES) - sizeof(ptkPrivileges->Privileges);
424 uSize += sizeof(LUID_AND_ATTRIBUTES) * sizeof(InitialPrivilegeSet) / sizeof(InitialPrivilegeSet[0]);
425 ptkPrivileges = (TOKEN_PRIVILEGES*) malloc(uSize);
426 ptkPrivileges->PrivilegeCount = sizeof(InitialPrivilegeSet) / sizeof(InitialPrivilegeSet[0]);
427 for (i = 0; i < ptkPrivileges->PrivilegeCount; i++)
428 {
429 ptkPrivileges->Privileges[i].Luid.HighPart = InitialPrivilegeSet[i].Luid.HighPart;
430 ptkPrivileges->Privileges[i].Luid.LowPart = InitialPrivilegeSet[i].Luid.LowPart;
431 ptkPrivileges->Privileges[i].Attributes = InitialPrivilegeSet[i].Attributes;
432 }
433
434 // Calculate the length needed for the ACL
435 uSize = sizeof(ACL);
436 uSize += sizeof(ACE) + sizeof(sidSystem);
437 uSize += sizeof(ACE) + sizeof(sidAdministrators);
438 uSize = (uSize & (~3)) + 8;
439 tkDefaultDacl.DefaultDacl = (PACL) malloc(uSize);
440
441 status = RtlCreateAcl(tkDefaultDacl.DefaultDacl, uSize, ACL_REVISION);
442 if ( ! NT_SUCCESS(status) )
443 printf("RtlCreateAcl() failed: 0x%08x\n", status);
444
445 status = RtlAddAccessAllowedAce(tkDefaultDacl.DefaultDacl, ACL_REVISION, GENERIC_ALL, &sidSystem);
446 if ( ! NT_SUCCESS(status) )
447 printf("RtlAddAccessAllowedAce() failed: 0x%08x\n", status);
448
449 status = RtlAddAccessAllowedAce(tkDefaultDacl.DefaultDacl, ACL_REVISION, GENERIC_READ|GENERIC_EXECUTE|READ_CONTROL, (PSID) &sidAdministrators);
450 if ( ! NT_SUCCESS(status) )
451 printf("RtlAddAccessAllowedAce() failed: 0x%08x\n", status);
452
453 printf("Parameters being passed into ZwCreateToken:\n\n");
454 DisplayTokenSids(&tkUser, ptkGroups, &tkDefaultOwner, &tkPrimaryGroup);
455 DisplayDacl(tkDefaultDacl.DefaultDacl);
456
457 printf("Calling ZwCreateToken()...\n");
458 status = ZwCreateToken(phSystemToken,
459 TOKEN_ALL_ACCESS,
460 &oa,
461 TokenPrimary,
462 &authId,
463 &tkExpiration,
464 &tkUser,
465 ptkGroups,
466 ptkPrivileges,
467 &tkDefaultOwner,
468 &tkPrimaryGroup,
469 &tkDefaultDacl,
470 &source);
471
472 // Cleanup
473 free(ptkGroups);
474 free(ptkPrivileges);
475 free(tkDefaultDacl.DefaultDacl);
476
477 return status;
478 }
479
480 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
481 int
482 main(int argc, char* argv[])
483 {
484 NTSTATUS Status;
485 HANDLE hSystemToken;
486 CHAR buffer[512];
487 HANDLE hOurToken;
488
489 printf("Current process Token:\n");
490
491 Status=ZwOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_QUERY_SOURCE, &hOurToken);
492 if ( NT_SUCCESS(Status) )
493 {
494 DisplayToken(hOurToken);
495 CloseHandle(hOurToken);
496 }
497 else
498 {
499 printf("ZwOpenProcessToken() failed: 0x%08x\n", Status);
500 }
501
502 //#define ENABLE_PRIVILEGE
503 #ifdef ENABLE_PRIVILEGE
504 EnablePrivilege(SE_CREATE_TOKEN_NAME);
505 #endif
506
507 // Now do the other one
508 Status = CreateInitialSystemToken(&hSystemToken);
509 if ( NT_SUCCESS(Status) )
510 {
511 printf("System Token: 0x%08x\n", hSystemToken);
512 DisplayToken(hSystemToken);
513 CloseHandle(hSystemToken);
514 }
515 else
516 {
517 printf("CreateInitialSystemToken() return: 0x%08x\n", Status);
518 }
519
520 printf("press return");
521 gets(buffer);
522
523 return 0;
524 }