Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

792 lines
18 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. rtdmpsec.c
  5. Abstract:
  6. NT level registry security test program #1, basic non-error paths.
  7. Dump out the security descriptors of a sub-tree of the registry.
  8. rtdmpsec <KeyPath>
  9. Will ennumerate and dump out the subkeys and values of KeyPath,
  10. and then apply itself recursively to each subkey it finds.
  11. It assumes data values are null terminated strings.
  12. Example:
  13. rtdmpsec \REGISTRY\MACHINE\TEST\bigkey
  14. Author:
  15. John Vert (jvert) 24-Jan-92
  16. based on rtdmp.c by
  17. Bryan Willman (bryanwi) 10-Dec-91
  18. and getdacl.c by RobertRe
  19. Revision History:
  20. Richard Ward (richardw) 14 April 1992 Changed ACE_HEADER
  21. --*/
  22. #include "cmp.h"
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #define WORK_SIZE 1024
  27. //
  28. // Get a pointer to the first ace in an acl
  29. //
  30. #define FirstAce(Acl) ((PVOID)((PUCHAR)(Acl) + sizeof(ACL)))
  31. //
  32. // Get a pointer to the following ace
  33. //
  34. #define NextAce(Ace) ((PVOID)((PUCHAR)(Ace) + ((PACE_HEADER)(Ace))->AceSize))
  35. //
  36. // Generic ACE structure, to be used for casting ACE's of known types
  37. //
  38. typedef struct _KNOWN_ACE {
  39. ACE_HEADER Header;
  40. ACCESS_MASK Mask;
  41. ULONG SidStart;
  42. } KNOWN_ACE, *PKNOWN_ACE;
  43. VOID
  44. InitVars();
  45. VOID
  46. PrintAcl (
  47. IN PACL Acl
  48. );
  49. VOID
  50. PrintAccessMask(
  51. IN ACCESS_MASK AccessMask
  52. );
  53. void __cdecl main(int, char *);
  54. void processargs();
  55. void print(PUNICODE_STRING);
  56. void
  57. DumpSecurity(
  58. HANDLE Handle
  59. );
  60. void
  61. Dump(
  62. HANDLE Handle
  63. );
  64. UNICODE_STRING WorkName;
  65. WCHAR workbuffer[WORK_SIZE];
  66. //
  67. // Universal well known SIDs
  68. //
  69. PSID NullSid;
  70. PSID WorldSid;
  71. PSID LocalSid;
  72. PSID CreatorOwnerSid;
  73. //
  74. // Sids defined by NT
  75. //
  76. PSID NtAuthoritySid;
  77. PSID DialupSid;
  78. PSID NetworkSid;
  79. PSID BatchSid;
  80. PSID InteractiveSid;
  81. PSID LocalSystemSid;
  82. void
  83. __cdecl main(
  84. int argc,
  85. char *argv[]
  86. )
  87. {
  88. NTSTATUS status;
  89. OBJECT_ATTRIBUTES ObjectAttributes;
  90. HANDLE BaseHandle;
  91. InitVars();
  92. //
  93. // Process args
  94. //
  95. WorkName.MaximumLength = WORK_SIZE;
  96. WorkName.Length = 0L;
  97. WorkName.Buffer = &(workbuffer[0]);
  98. processargs(argc, argv);
  99. //
  100. // Set up and open KeyPath
  101. //
  102. printf("rtdmpsec: starting\n");
  103. InitializeObjectAttributes(
  104. &ObjectAttributes,
  105. &WorkName,
  106. 0,
  107. (HANDLE)NULL,
  108. NULL
  109. );
  110. ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
  111. status = NtOpenKey(
  112. &BaseHandle,
  113. MAXIMUM_ALLOWED,
  114. &ObjectAttributes
  115. );
  116. if (!NT_SUCCESS(status)) {
  117. printf("rtdmpsec: t0: %08lx\n", status);
  118. exit(1);
  119. }
  120. Dump(BaseHandle);
  121. }
  122. void
  123. Dump(
  124. HANDLE Handle
  125. )
  126. {
  127. NTSTATUS status;
  128. PKEY_BASIC_INFORMATION KeyInformation;
  129. OBJECT_ATTRIBUTES ObjectAttributes;
  130. ULONG NamePos;
  131. ULONG index;
  132. STRING enumname;
  133. HANDLE WorkHandle;
  134. ULONG ResultLength;
  135. static char buffer[WORK_SIZE];
  136. PUCHAR p;
  137. KeyInformation = (PKEY_BASIC_INFORMATION)buffer;
  138. NamePos = WorkName.Length;
  139. //
  140. // Print name of node we are about to dump out
  141. //
  142. printf("\n");
  143. print(&WorkName);
  144. printf("::\n");
  145. //
  146. // Print out node's values
  147. //
  148. DumpSecurity(Handle);
  149. //
  150. // Enumerate node's children and apply ourselves to each one
  151. //
  152. for (index = 0; TRUE; index++) {
  153. RtlZeroMemory(KeyInformation, WORK_SIZE);
  154. status = NtEnumerateKey(
  155. Handle,
  156. index,
  157. KeyBasicInformation,
  158. KeyInformation,
  159. WORK_SIZE,
  160. &ResultLength
  161. );
  162. if (status == STATUS_NO_MORE_ENTRIES) {
  163. WorkName.Length = NamePos;
  164. return;
  165. } else if (!NT_SUCCESS(status)) {
  166. printf("rtdmpsec: dump1: status = %08lx\n", status);
  167. exit(1);
  168. }
  169. enumname.Buffer = &(KeyInformation->Name[0]);
  170. enumname.Length = KeyInformation->NameLength;
  171. enumname.MaximumLength = KeyInformation->NameLength;
  172. p = WorkName.Buffer;
  173. p += WorkName.Length;
  174. *p = '\\';
  175. p++;
  176. *p = '\0';
  177. WorkName.Length += 2;
  178. RtlAppendStringToString((PSTRING)&WorkName, (PSTRING)&enumname);
  179. InitializeObjectAttributes(
  180. &ObjectAttributes,
  181. &enumname,
  182. 0,
  183. Handle,
  184. NULL
  185. );
  186. ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
  187. status = NtOpenKey(
  188. &WorkHandle,
  189. MAXIMUM_ALLOWED,
  190. &ObjectAttributes
  191. );
  192. if (!NT_SUCCESS(status)) {
  193. if (status == STATUS_ACCESS_DENIED) {
  194. printf("\n");
  195. print(&WorkName);
  196. printf("::\n\tAccess denied!\n");
  197. } else {
  198. printf("rtdmpsec: dump2: %08lx\n", status);
  199. exit(1);
  200. }
  201. } else {
  202. Dump(WorkHandle);
  203. NtClose(WorkHandle);
  204. }
  205. WorkName.Length = NamePos;
  206. }
  207. }
  208. void
  209. DumpSecurity(
  210. HANDLE Handle
  211. )
  212. {
  213. PSECURITY_DESCRIPTOR SecurityDescriptor;
  214. NTSTATUS Status;
  215. ULONG Length;
  216. PACL Dacl;
  217. BOOLEAN DaclPresent;
  218. BOOLEAN DaclDefaulted;
  219. Status = NtQuerySecurityObject( Handle,
  220. DACL_SECURITY_INFORMATION,
  221. NULL,
  222. 0,
  223. &Length );
  224. if (Status != STATUS_BUFFER_TOO_SMALL) {
  225. printf("DumpSecurity t0: NtQuerySecurityObject failed %lx\n",Status);
  226. exit(1);
  227. }
  228. SecurityDescriptor = malloc(Length);
  229. if (SecurityDescriptor == NULL) {
  230. printf("DumpSecurity: couldn't malloc buffer\n");
  231. exit(1);
  232. }
  233. Status = NtQuerySecurityObject( Handle,
  234. DACL_SECURITY_INFORMATION,
  235. SecurityDescriptor,
  236. Length,
  237. &Length );
  238. if (!NT_SUCCESS(Status)) {
  239. printf("DumpSecurity t1: NtQuerySecurityObject failed %lx\n",Status);
  240. exit(1);
  241. }
  242. Dacl = NULL;
  243. Status = RtlGetDaclSecurityDescriptor( SecurityDescriptor,
  244. &DaclPresent,
  245. &Dacl,
  246. &DaclDefaulted );
  247. if (!NT_SUCCESS(Status)) {
  248. printf("DumpSecurity t2: RtlGetDaclSecurityDescriptor failed %lx\n",Status);
  249. }
  250. if (DaclPresent) {
  251. PrintAcl(Dacl);
  252. } else {
  253. printf("\tAcl not present\n");
  254. }
  255. }
  256. void
  257. print(
  258. PUNICODE_STRING String
  259. )
  260. {
  261. static ANSI_STRING temp;
  262. static char tempbuffer[WORK_SIZE];
  263. temp.MaximumLength = WORK_SIZE;
  264. temp.Length = 0L;
  265. temp.Buffer = tempbuffer;
  266. RtlUnicodeStringToAnsiString(&temp, String, FALSE);
  267. printf("%s", temp.Buffer);
  268. return;
  269. }
  270. void
  271. processargs(
  272. int argc,
  273. char *argv[]
  274. )
  275. {
  276. ANSI_STRING temp;
  277. if ( (argc != 2) )
  278. {
  279. printf("Usage: %s <KeyPath>\n",
  280. argv[0]);
  281. exit(1);
  282. }
  283. RtlInitAnsiString(
  284. &temp,
  285. argv[1]
  286. );
  287. RtlAnsiStringToUnicodeString(
  288. &WorkName,
  289. &temp,
  290. FALSE
  291. );
  292. return;
  293. }
  294. BOOLEAN
  295. SidTranslation(
  296. PSID Sid,
  297. PSTRING AccountName
  298. )
  299. // AccountName is expected to have a large maximum length
  300. {
  301. if (RtlEqualSid(Sid, WorldSid)) {
  302. RtlInitString( AccountName, "WORLD");
  303. return(TRUE);
  304. }
  305. if (RtlEqualSid(Sid, LocalSid)) {
  306. RtlInitString( AccountName, "LOCAL");
  307. return(TRUE);
  308. }
  309. if (RtlEqualSid(Sid, NetworkSid)) {
  310. RtlInitString( AccountName, "NETWORK");
  311. return(TRUE);
  312. }
  313. if (RtlEqualSid(Sid, BatchSid)) {
  314. RtlInitString( AccountName, "BATCH");
  315. return(TRUE);
  316. }
  317. if (RtlEqualSid(Sid, InteractiveSid)) {
  318. RtlInitString( AccountName, "INTERACTIVE");
  319. return(TRUE);
  320. }
  321. if (RtlEqualSid(Sid, LocalSystemSid)) {
  322. RtlInitString( AccountName, "SYSTEM");
  323. return(TRUE);
  324. }
  325. //
  326. // if (RtlEqualSid(Sid, LocalManagerSid)) {
  327. // RtlInitString( AccountName, "LOCAL MANAGER");
  328. // return(TRUE);
  329. // }
  330. // if (RtlEqualSid(Sid, LocalAdminSid)) {
  331. // RtlInitString( AccountName, "LOCAL ADMIN");
  332. // return(TRUE);
  333. // }
  334. return(FALSE);
  335. }
  336. VOID
  337. DisplayAccountSid(
  338. PSID Sid
  339. )
  340. {
  341. UCHAR Buffer[128];
  342. STRING AccountName;
  343. UCHAR i;
  344. ULONG Tmp;
  345. PSID_IDENTIFIER_AUTHORITY IdentifierAuthority;
  346. UCHAR SubAuthorityCount;
  347. Buffer[0] = 0;
  348. AccountName.MaximumLength = 127;
  349. AccountName.Length = 0;
  350. AccountName.Buffer = (PVOID)&Buffer[0];
  351. if (SidTranslation( (PSID)Sid, &AccountName) ) {
  352. printf("%s\n", AccountName.Buffer );
  353. } else {
  354. IdentifierAuthority = RtlIdentifierAuthoritySid(Sid);
  355. //
  356. // HACK! HACK!
  357. // The next line prints the revision of the SID. Since there is no
  358. // rtl routine which gives us the SID revision, we must make due.
  359. // luckily, the revision field is the first field in the SID, so we
  360. // can just cast the pointer.
  361. //
  362. printf("S-%u-", (USHORT) *((PUCHAR) Sid) );
  363. if ( (IdentifierAuthority->Value[0] != 0) ||
  364. (IdentifierAuthority->Value[1] != 0) ){
  365. printf("0x%02hx%02hx%02hx%02hx%02hx%02hx",
  366. IdentifierAuthority->Value[0],
  367. IdentifierAuthority->Value[1],
  368. IdentifierAuthority->Value[2],
  369. IdentifierAuthority->Value[3],
  370. IdentifierAuthority->Value[4],
  371. IdentifierAuthority->Value[5] );
  372. } else {
  373. Tmp = IdentifierAuthority->Value[5] +
  374. (IdentifierAuthority->Value[4] << 8) +
  375. (IdentifierAuthority->Value[3] << 16) +
  376. (IdentifierAuthority->Value[2] << 24);
  377. printf("%lu", Tmp);
  378. }
  379. SubAuthorityCount = *RtlSubAuthorityCountSid(Sid);
  380. for (i=0;i<SubAuthorityCount ;i++ ) {
  381. printf("-%lu", (*RtlSubAuthoritySid(Sid, i)));
  382. }
  383. printf("\n");
  384. }
  385. }
  386. VOID
  387. InitVars()
  388. {
  389. ULONG SidWithZeroSubAuthorities;
  390. ULONG SidWithOneSubAuthority;
  391. ULONG SidWithThreeSubAuthorities;
  392. ULONG SidWithFourSubAuthorities;
  393. SID_IDENTIFIER_AUTHORITY NullSidAuthority = SECURITY_NULL_SID_AUTHORITY;
  394. SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
  395. SID_IDENTIFIER_AUTHORITY LocalSidAuthority = SECURITY_LOCAL_SID_AUTHORITY;
  396. SID_IDENTIFIER_AUTHORITY CreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY;
  397. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  398. //
  399. // The following SID sizes need to be allocated
  400. //
  401. SidWithZeroSubAuthorities = RtlLengthRequiredSid( 0 );
  402. SidWithOneSubAuthority = RtlLengthRequiredSid( 1 );
  403. SidWithThreeSubAuthorities = RtlLengthRequiredSid( 3 );
  404. SidWithFourSubAuthorities = RtlLengthRequiredSid( 4 );
  405. //
  406. // Allocate and initialize the universal SIDs
  407. //
  408. NullSid = (PSID)malloc(SidWithOneSubAuthority);
  409. WorldSid = (PSID)malloc(SidWithOneSubAuthority);
  410. LocalSid = (PSID)malloc(SidWithOneSubAuthority);
  411. CreatorOwnerSid = (PSID)malloc(SidWithOneSubAuthority);
  412. RtlInitializeSid( NullSid, &NullSidAuthority, 1 );
  413. RtlInitializeSid( WorldSid, &WorldSidAuthority, 1 );
  414. RtlInitializeSid( LocalSid, &LocalSidAuthority, 1 );
  415. RtlInitializeSid( CreatorOwnerSid, &CreatorSidAuthority, 1 );
  416. *(RtlSubAuthoritySid( NullSid, 0 )) = SECURITY_NULL_RID;
  417. *(RtlSubAuthoritySid( WorldSid, 0 )) = SECURITY_WORLD_RID;
  418. *(RtlSubAuthoritySid( LocalSid, 0 )) = SECURITY_LOCAL_RID;
  419. *(RtlSubAuthoritySid( CreatorOwnerSid, 0 )) = SECURITY_CREATOR_OWNER_RID;
  420. //
  421. // Allocate and initialize the NT defined SIDs
  422. //
  423. NtAuthoritySid = (PSID)malloc(SidWithZeroSubAuthorities);
  424. DialupSid = (PSID)malloc(SidWithOneSubAuthority);
  425. NetworkSid = (PSID)malloc(SidWithOneSubAuthority);
  426. BatchSid = (PSID)malloc(SidWithOneSubAuthority);
  427. InteractiveSid = (PSID)malloc(SidWithOneSubAuthority);
  428. LocalSystemSid = (PSID)malloc(SidWithOneSubAuthority);
  429. RtlInitializeSid( NtAuthoritySid, &NtAuthority, 0 );
  430. RtlInitializeSid( DialupSid, &NtAuthority, 1 );
  431. RtlInitializeSid( NetworkSid, &NtAuthority, 1 );
  432. RtlInitializeSid( BatchSid, &NtAuthority, 1 );
  433. RtlInitializeSid( InteractiveSid, &NtAuthority, 1 );
  434. RtlInitializeSid( LocalSystemSid, &NtAuthority, 1 );
  435. *(RtlSubAuthoritySid( DialupSid, 0 )) = SECURITY_DIALUP_RID;
  436. *(RtlSubAuthoritySid( NetworkSid, 0 )) = SECURITY_NETWORK_RID;
  437. *(RtlSubAuthoritySid( BatchSid, 0 )) = SECURITY_BATCH_RID;
  438. *(RtlSubAuthoritySid( InteractiveSid, 0 )) = SECURITY_INTERACTIVE_RID;
  439. *(RtlSubAuthoritySid( LocalSystemSid, 0 )) = SECURITY_LOCAL_SYSTEM_RID;
  440. return;
  441. }
  442. VOID
  443. PrintAcl (
  444. IN PACL Acl
  445. )
  446. /*++
  447. Routine Description:
  448. This routine dumps an Acl for debug purposes (via printf). It is
  449. specialized to dump standard aces.
  450. Arguments:
  451. Acl - Supplies the Acl to dump
  452. Return Value:
  453. None
  454. --*/
  455. {
  456. ULONG i;
  457. PKNOWN_ACE Ace;
  458. BOOLEAN KnownType;
  459. PCHAR AceTypes[] = { "Access Allowed",
  460. "Access Denied ",
  461. "System Audit ",
  462. "System Alarm "
  463. };
  464. if (Acl == NULL) {
  465. printf("\tAcl == ALL ACCESS GRANTED!\n");
  466. return;
  467. }
  468. //
  469. // Dump the Acl header
  470. //
  471. printf("\tRevision: %02x", Acl->AclRevision);
  472. printf(" Size: %04x", Acl->AclSize);
  473. printf(" AceCount: %04x\n", Acl->AceCount);
  474. //
  475. // Now for each Ace we want do dump it
  476. //
  477. for (i = 0, Ace = FirstAce(Acl);
  478. i < Acl->AceCount;
  479. i++, Ace = NextAce(Ace) ) {
  480. //
  481. // print out the ace header
  482. //
  483. printf("\n\tAceHeader: %08lx ", *(PULONG)Ace);
  484. //
  485. // special case on the standard ace types
  486. //
  487. if ((Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) ||
  488. (Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE) ||
  489. (Ace->Header.AceType == SYSTEM_AUDIT_ACE_TYPE) ||
  490. (Ace->Header.AceType == SYSTEM_ALARM_ACE_TYPE)) {
  491. //
  492. // The following array is indexed by ace types and must
  493. // follow the allowed, denied, audit, alarm seqeuence
  494. //
  495. PCHAR AceTypes[] = { "Access Allowed",
  496. "Access Denied ",
  497. "System Audit ",
  498. "System Alarm "
  499. };
  500. printf(AceTypes[Ace->Header.AceType]);
  501. PrintAccessMask(Ace->Mask);
  502. KnownType = TRUE;
  503. } else {
  504. KnownType = FALSE;
  505. printf(" Unknown Ace Type\n");
  506. }
  507. printf("\n");
  508. printf("\tAceSize = %d\n",Ace->Header.AceSize);
  509. printf("\tAce Flags = ");
  510. if (Ace->Header.AceFlags & OBJECT_INHERIT_ACE) {
  511. printf("OBJECT_INHERIT_ACE\n");
  512. printf(" ");
  513. }
  514. if (Ace->Header.AceFlags & CONTAINER_INHERIT_ACE) {
  515. printf("CONTAINER_INHERIT_ACE\n");
  516. printf(" ");
  517. }
  518. if (Ace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE) {
  519. printf("NO_PROPAGATE_INHERIT_ACE\n");
  520. printf(" ");
  521. }
  522. if (Ace->Header.AceFlags & INHERIT_ONLY_ACE) {
  523. printf("INHERIT_ONLY_ACE\n");
  524. printf(" ");
  525. }
  526. if (Ace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG) {
  527. printf("SUCCESSFUL_ACCESS_ACE_FLAG\n");
  528. printf(" ");
  529. }
  530. if (Ace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG) {
  531. printf("FAILED_ACCESS_ACE_FLAG\n");
  532. printf(" ");
  533. }
  534. printf("\n");
  535. printf("\tSid = ");
  536. DisplayAccountSid(&Ace->SidStart);
  537. }
  538. }
  539. VOID
  540. PrintAccessMask(
  541. IN ACCESS_MASK AccessMask
  542. )
  543. {
  544. printf("\n\tAccess Mask: ");
  545. if (AccessMask == KEY_ALL_ACCESS) {
  546. printf("KEY_ALL_ACCESS\n\t ");
  547. return;
  548. }
  549. if (AccessMask == KEY_READ) {
  550. printf("KEY_READ\n\t ");
  551. return;
  552. }
  553. if (AccessMask == KEY_WRITE) {
  554. printf("KEY_WRITE\n\t ");
  555. return;
  556. }
  557. if (AccessMask & KEY_QUERY_VALUE) {
  558. printf("KEY_QUERY_VALUE\n\t ");
  559. }
  560. if (AccessMask & KEY_SET_VALUE) {
  561. printf("KEY_SET_VALUE\n\t ");
  562. }
  563. if (AccessMask & KEY_CREATE_SUB_KEY) {
  564. printf("KEY_CREATE_SUB_KEY\n\t ");
  565. }
  566. if (AccessMask & KEY_ENUMERATE_SUB_KEYS) {
  567. printf("KEY_ENUMERATE_SUB_KEYS\n\t ");
  568. }
  569. if (AccessMask & KEY_NOTIFY) {
  570. printf("KEY_NOTIFY\n\t ");
  571. }
  572. if (AccessMask & KEY_CREATE_LINK) {
  573. printf("KEY_CREATE_LINK\n\t ");
  574. }
  575. if (AccessMask & GENERIC_ALL) {
  576. printf("GENERIC_ALL\n\t ");
  577. }
  578. if (AccessMask & GENERIC_EXECUTE) {
  579. printf("GENERIC_EXECUTE\n\t ");
  580. }
  581. if (AccessMask & GENERIC_WRITE) {
  582. printf("GENERIC_WRITE\n\t ");
  583. }
  584. if (AccessMask & GENERIC_READ) {
  585. printf("GENERIC_READ\n\t ");
  586. }
  587. if (AccessMask & GENERIC_READ) {
  588. printf("GENERIC_READ\n\t ");
  589. }
  590. if (AccessMask & MAXIMUM_ALLOWED) {
  591. printf("MAXIMUM_ALLOWED\n\t ");
  592. }
  593. if (AccessMask & ACCESS_SYSTEM_SECURITY) {
  594. printf("ACCESS_SYSTEM_SECURITY\n\t ");
  595. }
  596. if (AccessMask & WRITE_OWNER) {
  597. printf("WRITE_OWNER\n\t ");
  598. }
  599. if (AccessMask & WRITE_DAC) {
  600. printf("WRITE_DAC\n\t ");
  601. }
  602. if (AccessMask & READ_CONTROL) {
  603. printf("READ_CONTROL\n\t ");
  604. }
  605. if (AccessMask & DELETE) {
  606. printf("DELETE\n\t ");
  607. }
  608. }