Leaked source code of windows server 2003
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.

1094 lines
25 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. regacl.c
  5. Abstract:
  6. This provides routines to parse the ACE lists present in the regini
  7. text input files. It also provides routines to create the appropriate
  8. security descriptor from the list of ACEs.
  9. Author:
  10. John Vert (jvert) 15-Sep-1992
  11. Notes:
  12. This is based on the SETACL program used in SETUP, written by RobertRe
  13. Revision History:
  14. John Vert (jvert) 15-Sep-1992
  15. created
  16. Lonny McMichael (lonnym) 25-March-1999
  17. added new predefined ACEs (UserR and PowerR)
  18. --*/
  19. #include <nt.h>
  20. #include <ntrtl.h>
  21. #include <nturtl.h>
  22. #include <windows.h>
  23. #include <stdio.h>
  24. #include <wchar.h>
  25. #include <seopaque.h>
  26. #include <sertlp.h>
  27. //
  28. // Private function prototypes
  29. //
  30. BOOLEAN
  31. RegpInitializeACEs(
  32. VOID
  33. );
  34. //
  35. // Universal well-known SIDs
  36. //
  37. PSID SeNullSid;
  38. PSID SeWorldSid;
  39. PSID SeCreatorOwnerSid;
  40. PSID SeInteractiveUserSid;
  41. PSID SeTerminalUserSid;
  42. //
  43. // SIDs defined by NT
  44. //
  45. PSID SeNtAuthoritySid;
  46. PSID SeLocalSystemSid;
  47. PSID SeLocalAdminSid;
  48. PSID SeAliasAdminsSid;
  49. PSID SeAliasSystemOpsSid;
  50. PSID SeAliasPowerUsersSid;
  51. PSID SeAliasUsersSid;
  52. SID_IDENTIFIER_AUTHORITY SepNullSidAuthority = SECURITY_NULL_SID_AUTHORITY;
  53. SID_IDENTIFIER_AUTHORITY SepWorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
  54. SID_IDENTIFIER_AUTHORITY SepLocalSidAuthority = SECURITY_LOCAL_SID_AUTHORITY;
  55. SID_IDENTIFIER_AUTHORITY SepCreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY;
  56. SID_IDENTIFIER_AUTHORITY SepNtAuthority = SECURITY_NT_AUTHORITY;
  57. //
  58. // SID of primary domain, and admin account in that domain.
  59. //
  60. PSID SepPrimaryDomainSid;
  61. PSID SepPrimaryDomainAdminSid;
  62. //
  63. // Number of ACEs currently defined
  64. //
  65. #define ACE_COUNT 32
  66. typedef struct _ACE_DATA {
  67. ACCESS_MASK AccessMask;
  68. PSID *Sid;
  69. UCHAR AceType;
  70. UCHAR AceFlags;
  71. } ACE_DATA, *PACE_DATA;
  72. //
  73. // Table describing the data to put into each ACE.
  74. //
  75. // This table is read during initialization and used to construct a
  76. // series of ACEs. The index of each ACE in the Aces array defined below
  77. // corresponds to the ordinals used in the input data file.
  78. //
  79. ACE_DATA AceDataTable[ACE_COUNT] = {
  80. {
  81. 0,
  82. NULL,
  83. 0,
  84. 0
  85. },
  86. //
  87. // ACE 1 - ADMIN Full
  88. //
  89. {
  90. KEY_ALL_ACCESS,
  91. &SeAliasAdminsSid,
  92. ACCESS_ALLOWED_ACE_TYPE,
  93. CONTAINER_INHERIT_ACE
  94. },
  95. //
  96. // ACE 2 - ADMIN Read
  97. //
  98. {
  99. KEY_READ,
  100. &SeAliasAdminsSid,
  101. ACCESS_ALLOWED_ACE_TYPE,
  102. CONTAINER_INHERIT_ACE
  103. },
  104. //
  105. // ACE 3 - ADMIN Read Write
  106. //
  107. {
  108. KEY_READ | KEY_WRITE,
  109. &SeAliasAdminsSid,
  110. ACCESS_ALLOWED_ACE_TYPE,
  111. CONTAINER_INHERIT_ACE
  112. },
  113. //
  114. // ACE 4 - ADMIN Read Write Delete
  115. //
  116. {
  117. KEY_READ | KEY_WRITE | DELETE,
  118. &SeAliasAdminsSid,
  119. ACCESS_ALLOWED_ACE_TYPE,
  120. CONTAINER_INHERIT_ACE
  121. },
  122. //
  123. // ACE 5 - Creator Full
  124. //
  125. {
  126. KEY_ALL_ACCESS,
  127. &SeCreatorOwnerSid,
  128. ACCESS_ALLOWED_ACE_TYPE,
  129. CONTAINER_INHERIT_ACE
  130. },
  131. //
  132. // ACE 6 - Creator Read Write
  133. //
  134. {
  135. KEY_READ | KEY_WRITE,
  136. &SeCreatorOwnerSid,
  137. ACCESS_ALLOWED_ACE_TYPE,
  138. CONTAINER_INHERIT_ACE
  139. },
  140. //
  141. // ACE 7 - World Full
  142. //
  143. {
  144. KEY_ALL_ACCESS,
  145. &SeWorldSid,
  146. ACCESS_ALLOWED_ACE_TYPE,
  147. CONTAINER_INHERIT_ACE
  148. },
  149. //
  150. // ACE 8 - World Read
  151. //
  152. {
  153. KEY_READ,
  154. &SeWorldSid,
  155. ACCESS_ALLOWED_ACE_TYPE,
  156. CONTAINER_INHERIT_ACE
  157. },
  158. //
  159. // ACE 9 - World Read Write
  160. //
  161. {
  162. KEY_READ | KEY_WRITE,
  163. &SeWorldSid,
  164. ACCESS_ALLOWED_ACE_TYPE,
  165. CONTAINER_INHERIT_ACE
  166. },
  167. //
  168. // ACE 10 - World Read Write Delete
  169. //
  170. {
  171. KEY_READ | KEY_WRITE | DELETE,
  172. &SeWorldSid,
  173. ACCESS_ALLOWED_ACE_TYPE,
  174. CONTAINER_INHERIT_ACE
  175. },
  176. //
  177. // ACE 11 - PowerUser Full
  178. //
  179. {
  180. KEY_ALL_ACCESS,
  181. &SeAliasPowerUsersSid,
  182. ACCESS_ALLOWED_ACE_TYPE,
  183. CONTAINER_INHERIT_ACE
  184. },
  185. //
  186. // ACE 12 - PowerUser Read Write
  187. //
  188. {
  189. KEY_READ | KEY_WRITE,
  190. &SeAliasPowerUsersSid,
  191. ACCESS_ALLOWED_ACE_TYPE,
  192. CONTAINER_INHERIT_ACE
  193. },
  194. //
  195. // ACE 13 - PowerUser Read Write Delete
  196. //
  197. {
  198. KEY_READ | KEY_WRITE | DELETE,
  199. &SeAliasPowerUsersSid,
  200. ACCESS_ALLOWED_ACE_TYPE,
  201. CONTAINER_INHERIT_ACE
  202. },
  203. //
  204. // ACE 14 - System Ops Full
  205. //
  206. {
  207. KEY_ALL_ACCESS,
  208. &SeAliasSystemOpsSid,
  209. ACCESS_ALLOWED_ACE_TYPE,
  210. CONTAINER_INHERIT_ACE
  211. },
  212. //
  213. // ACE 15 - System Ops Read Write
  214. //
  215. {
  216. KEY_READ | KEY_WRITE,
  217. &SeAliasSystemOpsSid,
  218. ACCESS_ALLOWED_ACE_TYPE,
  219. CONTAINER_INHERIT_ACE
  220. },
  221. //
  222. // ACE 16 - System Ops Read Write Delete
  223. //
  224. {
  225. KEY_READ | KEY_WRITE | DELETE,
  226. &SeAliasSystemOpsSid,
  227. ACCESS_ALLOWED_ACE_TYPE,
  228. CONTAINER_INHERIT_ACE
  229. },
  230. //
  231. // ACE 17 - System Full
  232. //
  233. {
  234. KEY_ALL_ACCESS,
  235. &SeLocalSystemSid,
  236. ACCESS_ALLOWED_ACE_TYPE,
  237. CONTAINER_INHERIT_ACE
  238. },
  239. //
  240. // ACE 18 - System Read Write
  241. //
  242. {
  243. KEY_READ | KEY_WRITE,
  244. &SeLocalSystemSid,
  245. ACCESS_ALLOWED_ACE_TYPE,
  246. CONTAINER_INHERIT_ACE
  247. },
  248. //
  249. // ACE 19 - System Read
  250. //
  251. {
  252. KEY_READ,
  253. &SeLocalSystemSid,
  254. ACCESS_ALLOWED_ACE_TYPE,
  255. CONTAINER_INHERIT_ACE
  256. },
  257. //
  258. // ACE 20 - ADMIN Read Write Execute
  259. //
  260. {
  261. KEY_READ | KEY_WRITE | KEY_EXECUTE,
  262. &SeAliasAdminsSid,
  263. ACCESS_ALLOWED_ACE_TYPE,
  264. CONTAINER_INHERIT_ACE
  265. },
  266. //
  267. // ACE 21 - Interactive User Full
  268. //
  269. {
  270. KEY_ALL_ACCESS,
  271. &SeInteractiveUserSid,
  272. ACCESS_ALLOWED_ACE_TYPE,
  273. CONTAINER_INHERIT_ACE
  274. },
  275. //
  276. // ACE 22 - Interactive User Read
  277. //
  278. {
  279. KEY_READ,
  280. &SeInteractiveUserSid,
  281. ACCESS_ALLOWED_ACE_TYPE,
  282. CONTAINER_INHERIT_ACE
  283. },
  284. //
  285. // ACE 23 - Interactive User Read Write
  286. //
  287. {
  288. KEY_READ | KEY_WRITE,
  289. &SeInteractiveUserSid,
  290. ACCESS_ALLOWED_ACE_TYPE,
  291. CONTAINER_INHERIT_ACE
  292. },
  293. //
  294. // ACE 24 - Interactive User Read Write Delete
  295. //
  296. {
  297. KEY_READ | KEY_WRITE | DELETE,
  298. &SeInteractiveUserSid,
  299. ACCESS_ALLOWED_ACE_TYPE,
  300. CONTAINER_INHERIT_ACE
  301. },
  302. //
  303. // ACE 25 - Normal Users Read / Write
  304. //
  305. {
  306. KEY_READ | KEY_WRITE,
  307. &SeAliasUsersSid,
  308. ACCESS_ALLOWED_ACE_TYPE,
  309. CONTAINER_INHERIT_ACE
  310. },
  311. //
  312. // ACE 26 - Terminal User Full
  313. //
  314. {
  315. KEY_ALL_ACCESS,
  316. &SeTerminalUserSid,
  317. ACCESS_ALLOWED_ACE_TYPE,
  318. CONTAINER_INHERIT_ACE
  319. },
  320. //
  321. // ACE 27 - Terminal User Read
  322. //
  323. {
  324. KEY_READ,
  325. &SeTerminalUserSid,
  326. ACCESS_ALLOWED_ACE_TYPE,
  327. CONTAINER_INHERIT_ACE
  328. },
  329. //
  330. // ACE 28 - Terminal User Read Write
  331. //
  332. {
  333. KEY_READ | KEY_WRITE,
  334. &SeTerminalUserSid,
  335. ACCESS_ALLOWED_ACE_TYPE,
  336. CONTAINER_INHERIT_ACE
  337. },
  338. //
  339. // ACE 29 - Terminal User Read Write Delete
  340. //
  341. {
  342. KEY_READ | KEY_WRITE | DELETE,
  343. &SeTerminalUserSid,
  344. ACCESS_ALLOWED_ACE_TYPE,
  345. CONTAINER_INHERIT_ACE
  346. },
  347. //
  348. // ACE 30 - Normal Users Read
  349. //
  350. {
  351. KEY_READ,
  352. &SeAliasUsersSid,
  353. ACCESS_ALLOWED_ACE_TYPE,
  354. CONTAINER_INHERIT_ACE
  355. },
  356. //
  357. // ACE 31 - PowerUser Read
  358. //
  359. {
  360. KEY_READ,
  361. &SeAliasPowerUsersSid,
  362. ACCESS_ALLOWED_ACE_TYPE,
  363. CONTAINER_INHERIT_ACE
  364. }
  365. };
  366. PKNOWN_ACE Aces[ACE_COUNT];
  367. BOOLEAN
  368. RegInitializeSecurity(
  369. VOID
  370. )
  371. /*++
  372. Routine Description:
  373. This routine initializes the defined ACEs. It must be called before any
  374. of the routines to create security descriptors
  375. Arguments:
  376. None.
  377. Return Value:
  378. TRUE - initialization successful
  379. FALSE - initialization failed
  380. --*/
  381. {
  382. NTSTATUS Status;
  383. SID_IDENTIFIER_AUTHORITY NullSidAuthority;
  384. SID_IDENTIFIER_AUTHORITY WorldSidAuthority;
  385. SID_IDENTIFIER_AUTHORITY LocalSidAuthority;
  386. SID_IDENTIFIER_AUTHORITY CreatorSidAuthority;
  387. SID_IDENTIFIER_AUTHORITY SeNtAuthority;
  388. NullSidAuthority = SepNullSidAuthority;
  389. WorldSidAuthority = SepWorldSidAuthority;
  390. LocalSidAuthority = SepLocalSidAuthority;
  391. CreatorSidAuthority = SepCreatorSidAuthority;
  392. SeNtAuthority = SepNtAuthority;
  393. SeNullSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0, RtlLengthRequiredSid(1) );
  394. SeWorldSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0, RtlLengthRequiredSid(1) );
  395. SeCreatorOwnerSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0, RtlLengthRequiredSid(1) );
  396. SeInteractiveUserSid = (PSID)RtlAllocateHeap(RtlProcessHeap(), 0, RtlLengthRequiredSid(2) );
  397. SeTerminalUserSid = (PSID)RtlAllocateHeap(RtlProcessHeap(), 0, RtlLengthRequiredSid(2) );
  398. //
  399. // Fail initialization if we didn't get enough memory for the universal
  400. // SIDs
  401. //
  402. if (SeNullSid==NULL ||
  403. SeWorldSid==NULL ||
  404. SeCreatorOwnerSid==NULL ||
  405. SeInteractiveUserSid == NULL ||
  406. SeTerminalUserSid == NULL
  407. ) {
  408. return FALSE;
  409. }
  410. Status = RtlInitializeSid(SeNullSid, &NullSidAuthority, 1);
  411. if (!NT_SUCCESS( Status )) {
  412. return FALSE;
  413. }
  414. Status = RtlInitializeSid(SeWorldSid, &WorldSidAuthority, 1);
  415. if (!NT_SUCCESS( Status )) {
  416. return FALSE;
  417. }
  418. Status = RtlInitializeSid(SeCreatorOwnerSid, &CreatorSidAuthority, 1);
  419. if (!NT_SUCCESS( Status )) {
  420. return FALSE;
  421. }
  422. Status = RtlInitializeSid( SeInteractiveUserSid, &SeNtAuthority, 1 );
  423. if (!NT_SUCCESS( Status )) {
  424. return FALSE;
  425. }
  426. Status = RtlInitializeSid( SeTerminalUserSid, &SeNtAuthority, 1 );
  427. if (!NT_SUCCESS( Status )) {
  428. return FALSE;
  429. }
  430. *(RtlSubAuthoritySid(SeNullSid, 0)) = SECURITY_NULL_RID;
  431. *(RtlSubAuthoritySid(SeWorldSid, 0)) = SECURITY_WORLD_RID;
  432. *(RtlSubAuthoritySid(SeCreatorOwnerSid, 0)) = SECURITY_CREATOR_OWNER_RID;
  433. *(RtlSubAuthoritySid(SeInteractiveUserSid, 0 )) = SECURITY_INTERACTIVE_RID;
  434. *(RtlSubAuthoritySid(SeTerminalUserSid, 0 )) = SECURITY_TERMINAL_SERVER_RID;
  435. //
  436. // Allocate and initialize the NT defined SIDs
  437. //
  438. SeNtAuthoritySid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0, RtlLengthRequiredSid(0) );
  439. SeLocalSystemSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0, RtlLengthRequiredSid(1) );
  440. SeAliasAdminsSid = (PSID)RtlAllocateHeap(RtlProcessHeap(), 0, RtlLengthRequiredSid(2) );
  441. SeAliasSystemOpsSid = (PSID)RtlAllocateHeap(RtlProcessHeap(), 0, RtlLengthRequiredSid(2) );
  442. SeAliasPowerUsersSid = (PSID)RtlAllocateHeap(RtlProcessHeap(), 0, RtlLengthRequiredSid(2) );
  443. SeAliasUsersSid = (PSID)RtlAllocateHeap(RtlProcessHeap(), 0, RtlLengthRequiredSid(2) );
  444. //
  445. // fail initialization if we couldn't allocate memory for the NT SIDs
  446. //
  447. if (SeNtAuthoritySid == NULL ||
  448. SeLocalSystemSid == NULL ||
  449. SeAliasAdminsSid == NULL ||
  450. SeAliasPowerUsersSid == NULL ||
  451. SeAliasSystemOpsSid == NULL
  452. ) {
  453. return FALSE;
  454. }
  455. Status = RtlInitializeSid( SeNtAuthoritySid, &SeNtAuthority, 0 );
  456. if (!NT_SUCCESS( Status )) {
  457. return FALSE;
  458. }
  459. Status = RtlInitializeSid( SeLocalSystemSid, &SeNtAuthority, 1 );
  460. if (!NT_SUCCESS( Status )) {
  461. return FALSE;
  462. }
  463. Status = RtlInitializeSid( SeAliasAdminsSid, &SeNtAuthority, 2 );
  464. if (!NT_SUCCESS( Status )) {
  465. return FALSE;
  466. }
  467. Status = RtlInitializeSid( SeAliasSystemOpsSid, &SeNtAuthority, 2 );
  468. if (!NT_SUCCESS( Status )) {
  469. return FALSE;
  470. }
  471. Status = RtlInitializeSid( SeAliasPowerUsersSid, &SeNtAuthority, 2 );
  472. if (!NT_SUCCESS( Status )) {
  473. return FALSE;
  474. }
  475. Status = RtlInitializeSid( SeAliasUsersSid, &SeNtAuthority, 2 );
  476. if (!NT_SUCCESS( Status )) {
  477. return FALSE;
  478. }
  479. *(RtlSubAuthoritySid( SeLocalSystemSid, 0 )) = SECURITY_LOCAL_SYSTEM_RID;
  480. *(RtlSubAuthoritySid( SeAliasAdminsSid, 0 )) = SECURITY_BUILTIN_DOMAIN_RID;
  481. *(RtlSubAuthoritySid( SeAliasAdminsSid, 1 )) = DOMAIN_ALIAS_RID_ADMINS;
  482. *(RtlSubAuthoritySid( SeAliasSystemOpsSid, 0 )) = SECURITY_BUILTIN_DOMAIN_RID;
  483. *(RtlSubAuthoritySid( SeAliasSystemOpsSid, 1 )) = DOMAIN_ALIAS_RID_SYSTEM_OPS;
  484. *(RtlSubAuthoritySid( SeAliasPowerUsersSid, 0 )) = SECURITY_BUILTIN_DOMAIN_RID;
  485. *(RtlSubAuthoritySid( SeAliasPowerUsersSid, 1 )) = DOMAIN_ALIAS_RID_POWER_USERS;
  486. *(RtlSubAuthoritySid( SeAliasUsersSid, 0 )) = SECURITY_BUILTIN_DOMAIN_RID;
  487. *(RtlSubAuthoritySid( SeAliasUsersSid, 1 )) = DOMAIN_ALIAS_RID_USERS;
  488. //
  489. // The SIDs have been successfully created. Now create the table of ACEs
  490. //
  491. return RegpInitializeACEs();
  492. }
  493. BOOLEAN
  494. RegpInitializeACEs(
  495. VOID
  496. )
  497. /*++
  498. Routine Description:
  499. Initializes the table of ACEs described in the AceDataTable. This is
  500. called at initialization time by RiInitializeSecurity after the SIDs
  501. have been created.
  502. Arguments:
  503. None.
  504. Return Value:
  505. TRUE - ACEs successfully constructed.
  506. FALSE - initialization failed.
  507. --*/
  508. {
  509. ULONG i;
  510. ULONG LengthRequired;
  511. NTSTATUS Status;
  512. for (i=1; i<ACE_COUNT; i++) {
  513. LengthRequired = RtlLengthSid( *(AceDataTable[i].Sid) ) +
  514. sizeof( KNOWN_ACE ) - sizeof( ULONG );
  515. Aces[i] = (PKNOWN_ACE)RtlAllocateHeap( RtlProcessHeap(), 0, LengthRequired );
  516. if (Aces[i] == NULL) {
  517. return FALSE;
  518. }
  519. Aces[i]->Header.AceType = AceDataTable[i].AceType;
  520. Aces[i]->Header.AceFlags = AceDataTable[i].AceFlags;
  521. Aces[i]->Header.AceSize = (USHORT)LengthRequired;
  522. Aces[i]->Mask = AceDataTable[i].AccessMask;
  523. Status = RtlCopySid( RtlLengthSid(*(AceDataTable[i].Sid)),
  524. &Aces[i]->SidStart,
  525. *(AceDataTable[i].Sid)
  526. );
  527. if (!NT_SUCCESS( Status )) {
  528. return FALSE;
  529. }
  530. }
  531. return TRUE;
  532. }
  533. BOOLEAN
  534. RegUnicodeToDWORD(
  535. IN OUT PWSTR *String,
  536. IN ULONG Base OPTIONAL,
  537. OUT PULONG Value
  538. )
  539. {
  540. PCWSTR s;
  541. WCHAR c, Sign;
  542. ULONG nChars, Result, Digit, Shift;
  543. s = *String;
  544. Sign = UNICODE_NULL;
  545. while (*s != UNICODE_NULL && *s <= ' ') {
  546. s += 1;
  547. }
  548. c = *s;
  549. if (c == L'-' || c == L'+') {
  550. Sign = c;
  551. c = *++s;
  552. }
  553. if (Base == 0) {
  554. Base = 10;
  555. Shift = 0;
  556. if (c == L'0') {
  557. c = *++s;
  558. if (c == L'x') {
  559. c = *++s;
  560. Base = 16;
  561. Shift = 4;
  562. }
  563. else
  564. if (c == L'o') {
  565. c = *++s;
  566. Base = 8;
  567. Shift = 3;
  568. }
  569. else
  570. if (c == L'b') {
  571. c = *++s;
  572. Base = 2;
  573. Shift = 1;
  574. }
  575. else {
  576. c = *--s;
  577. }
  578. }
  579. }
  580. else {
  581. switch( Base ) {
  582. case 16: Shift = 4; break;
  583. case 8: Shift = 3; break;
  584. case 2: Shift = 1; break;
  585. case 10: Shift = 0; break;
  586. default: return FALSE;
  587. }
  588. }
  589. //
  590. // Return an error if end of string before we start
  591. //
  592. if (c == UNICODE_NULL) {
  593. return FALSE;
  594. }
  595. Result = 0;
  596. while (c != UNICODE_NULL) {
  597. if (c >= L'0' && c <= L'9') {
  598. Digit = c - L'0';
  599. }
  600. else
  601. if (c >= L'A' && c <= L'F') {
  602. Digit = c - L'A' + 10;
  603. }
  604. else
  605. if (c >= L'a' && c <= L'f') {
  606. Digit = c - L'a' + 10;
  607. }
  608. else {
  609. break;
  610. }
  611. if (Digit >= Base) {
  612. break;
  613. }
  614. if (Shift == 0) {
  615. Result = (Base * Result) + Digit;
  616. }
  617. else {
  618. Result = (Result << Shift) | Digit;
  619. }
  620. c = *++s;
  621. }
  622. if (Sign == L'-') {
  623. Result = (ULONG)(-(LONG)Result);
  624. }
  625. try {
  626. *String = (PWSTR)s;
  627. *Value = Result;
  628. }
  629. except( EXCEPTION_EXECUTE_HANDLER ) {
  630. return FALSE;
  631. }
  632. return TRUE;
  633. }
  634. BOOLEAN
  635. RegUnicodeToQWORD(
  636. IN OUT PWSTR *String,
  637. IN ULONG Base OPTIONAL,
  638. OUT PDWORDLONG Value
  639. )
  640. {
  641. PCWSTR s;
  642. WCHAR c, Sign;
  643. ULONG nChars, Digit, Shift;
  644. DWORDLONG Result;
  645. s = *String;
  646. Sign = UNICODE_NULL;
  647. while (*s != UNICODE_NULL && *s <= ' ') {
  648. s += 1;
  649. }
  650. c = *s;
  651. if (c == L'-' || c == L'+') {
  652. Sign = c;
  653. c = *++s;
  654. }
  655. if (Base == 0) {
  656. Base = 10;
  657. Shift = 0;
  658. if (c == L'0') {
  659. c = *++s;
  660. if (c == L'x') {
  661. c = *++s;
  662. Base = 16;
  663. Shift = 4;
  664. }
  665. else
  666. if (c == L'o') {
  667. c = *++s;
  668. Base = 8;
  669. Shift = 3;
  670. }
  671. else
  672. if (c == L'b') {
  673. c = *++s;
  674. Base = 2;
  675. Shift = 1;
  676. }
  677. else {
  678. c = *--s;
  679. }
  680. }
  681. }
  682. else {
  683. switch( Base ) {
  684. case 16: Shift = 4; break;
  685. case 8: Shift = 3; break;
  686. case 2: Shift = 1; break;
  687. case 10: Shift = 0; break;
  688. default: return FALSE;
  689. }
  690. }
  691. //
  692. // Return an error if end of string before we start
  693. //
  694. if (c == UNICODE_NULL) {
  695. return FALSE;
  696. }
  697. Result = 0;
  698. while (c != UNICODE_NULL) {
  699. if (c >= L'0' && c <= L'9') {
  700. Digit = c - L'0';
  701. }
  702. else
  703. if (c >= L'A' && c <= L'F') {
  704. Digit = c - L'A' + 10;
  705. }
  706. else
  707. if (c >= L'a' && c <= L'f') {
  708. Digit = c - L'a' + 10;
  709. }
  710. else {
  711. break;
  712. }
  713. if (Digit >= Base) {
  714. break;
  715. }
  716. if (Shift == 0) {
  717. Result = (Base * Result) + Digit;
  718. }
  719. else {
  720. Result = (Result << Shift) | Digit;
  721. }
  722. c = *++s;
  723. }
  724. if (Sign == L'-') {
  725. Result = (DWORDLONG)(-(LONGLONG)Result);
  726. }
  727. try {
  728. *String = (PWSTR)s;
  729. *Value = Result;
  730. }
  731. except( EXCEPTION_EXECUTE_HANDLER ) {
  732. return FALSE;
  733. }
  734. return TRUE;
  735. }
  736. BOOLEAN
  737. RegCreateSecurity(
  738. IN PWSTR AclStart,
  739. OUT PSECURITY_DESCRIPTOR SecurityDescriptor
  740. )
  741. /*++
  742. Routine Description:
  743. Computes the appropriate security descriptor based on a string of the
  744. form "1 2 3 ..." where each number is the index of a particular
  745. ACE from the pre-defined list of ACEs.
  746. Arguments:
  747. AclStart - Supplies a unicode string representing a list of ACEs
  748. SecurityDescriptor - Returns the initialized security descriptor
  749. that represents all the ACEs supplied
  750. Return Value:
  751. TRUE if successful and FALSE if not.
  752. --*/
  753. {
  754. PWSTR p;
  755. PWSTR StringEnd, StringStart;
  756. ULONG AceCount=0;
  757. ULONG AceIndex;
  758. ULONG i;
  759. PACL Acl;
  760. NTSTATUS Status;
  761. //
  762. // First we need to count the number of ACEs in the ACL.
  763. //
  764. p=AclStart;
  765. StringEnd = AclStart + wcslen( AclStart );
  766. //
  767. // strip leading white space
  768. //
  769. while ((*p == L' ' || *p == L'\t') && p != StringEnd) {
  770. p += 1;
  771. }
  772. StringStart = p;
  773. //
  774. // Count number of digits in the string
  775. //
  776. while (p != StringEnd) {
  777. if (iswdigit( *p )) {
  778. ++AceCount;
  779. do {
  780. p += 1;
  781. }
  782. while (iswdigit( *p ) && p != StringEnd);
  783. }
  784. else {
  785. p += 1;
  786. }
  787. }
  788. Acl = RtlAllocateHeap( RtlProcessHeap(), 0, 256 );
  789. if (Acl == NULL) {
  790. return FALSE;
  791. }
  792. Status = RtlCreateAcl( Acl, 256, ACL_REVISION2 );
  793. if (!NT_SUCCESS( Status )) {
  794. RtlFreeHeap( RtlProcessHeap(), 0, Acl );
  795. return FALSE;
  796. }
  797. p = StringStart;
  798. for (i=0; i<AceCount; i++) {
  799. AceIndex = wcstoul( p, &p, 10 );
  800. if (AceIndex == 0) {
  801. //
  802. // zero is not a valid index, so it must mean there is some
  803. // unexpected garbage in the ACE list
  804. //
  805. break;
  806. }
  807. Status = RtlAddAce( Acl,
  808. ACL_REVISION2,
  809. MAXULONG,
  810. Aces[AceIndex],
  811. Aces[AceIndex]->Header.AceSize
  812. );
  813. if (!NT_SUCCESS( Status )) {
  814. RtlFreeHeap( RtlProcessHeap(), 0, Acl );
  815. return FALSE;
  816. }
  817. }
  818. //
  819. // We now have an appropriately formed ACL, initialize the security
  820. // descriptor.
  821. //
  822. Status = RtlCreateSecurityDescriptor( SecurityDescriptor,
  823. SECURITY_DESCRIPTOR_REVISION
  824. );
  825. if (!NT_SUCCESS( Status )) {
  826. RtlFreeHeap( RtlProcessHeap(), 0, Acl );
  827. return FALSE;
  828. }
  829. Status = RtlSetDaclSecurityDescriptor( SecurityDescriptor,
  830. TRUE,
  831. Acl,
  832. FALSE
  833. );
  834. if (!NT_SUCCESS( Status )) {
  835. RtlFreeHeap( RtlProcessHeap(), 0, Acl );
  836. return FALSE;
  837. }
  838. return TRUE;
  839. }
  840. BOOLEAN
  841. RegFormatSecurity(
  842. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  843. OUT PWSTR AceList
  844. )
  845. {
  846. NTSTATUS Status;
  847. BOOLEAN DaclPresent, DaclDefaulted;
  848. PACL Acl;
  849. PWSTR s;
  850. ULONG AceIndex, MyAceIndex;
  851. PKNOWN_ACE Ace;
  852. s = AceList;
  853. *s = UNICODE_NULL;
  854. Acl = NULL;
  855. Status = RtlGetDaclSecurityDescriptor( SecurityDescriptor,
  856. &DaclPresent,
  857. &Acl,
  858. &DaclDefaulted
  859. );
  860. if (NT_SUCCESS( Status ) && DaclPresent && Acl != NULL) {
  861. for (AceIndex=0; AceIndex<Acl->AceCount; AceIndex++) {
  862. Status = RtlGetAce( Acl, AceIndex, &Ace );
  863. if (!NT_SUCCESS( Status )) {
  864. return FALSE;
  865. }
  866. for (MyAceIndex=1; MyAceIndex<ACE_COUNT; MyAceIndex++) {
  867. if (Ace->Header.AceType == Aces[ MyAceIndex ]->Header.AceType &&
  868. Ace->Header.AceFlags == Aces[ MyAceIndex ]->Header.AceFlags &&
  869. Ace->Mask == Aces[ MyAceIndex ]->Mask
  870. ) {
  871. if (RtlEqualSid( (PSID)&Ace->SidStart, (PSID)&Aces[ MyAceIndex ]->SidStart )) {
  872. if (s != AceList) {
  873. *s++ = L' ';
  874. }
  875. s += swprintf( s, L"%d", MyAceIndex );
  876. break;
  877. }
  878. }
  879. }
  880. }
  881. }
  882. *s = UNICODE_NULL;
  883. return s != AceList;
  884. }
  885. VOID
  886. RegDestroySecurity(
  887. IN PSECURITY_DESCRIPTOR SecurityDescriptor
  888. )
  889. /*++
  890. Routine Description:
  891. This routine cleans up and destroys a security descriptor that was
  892. previously created with RegCreateSecurity.
  893. Arguments:
  894. SecurityDescriptor - Supplies a pointer to the security descriptor that
  895. was previously initialized by RegCreateSecurity.
  896. Return Value:
  897. None.
  898. --*/
  899. {
  900. NTSTATUS Status;
  901. BOOLEAN DaclPresent, DaclDefaulted;
  902. PACL Acl;
  903. ULONG AceIndex;
  904. PKNOWN_ACE Ace;
  905. Acl = NULL;
  906. Status = RtlGetDaclSecurityDescriptor( SecurityDescriptor,
  907. &DaclPresent,
  908. &Acl,
  909. &DaclDefaulted
  910. );
  911. if (NT_SUCCESS( Status ) && DaclPresent && Acl != NULL) {
  912. RtlFreeHeap( RtlProcessHeap(), 0, Acl );
  913. }
  914. return;
  915. }