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.

802 lines
18 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. Predefh.c
  5. Abstract:
  6. This module contains routines for opening the Win32 Registry API's
  7. predefined handles.
  8. A predefined handle is used as a root to an absolute or relative
  9. sub-tree in the real Nt Registry. An absolute predefined handle maps
  10. to a specific key within the Registry. A relative predefined handle
  11. maps to a key relative to some additional information such as the
  12. current user.
  13. Predefined handles are strictly part of the Win32 Registry API. The
  14. Nt Registry API knows nothing about them.
  15. A predefined handle can be used anywhere that a non-predefined handle
  16. (i.e. one returned from RegCreateKey(), RegOpenKey() or
  17. RegConnectRegistry()) can be used.
  18. Author:
  19. David J. Gilman (davegi) 15-Nov-1991
  20. --*/
  21. #include <rpc.h>
  22. #include "regrpc.h"
  23. #include "localreg.h"
  24. #include "regclass.h"
  25. #include "ntconreg.h"
  26. #include "regsec.h"
  27. #ifdef LOCAL
  28. #include "tsappcmp.h"
  29. #if defined(LEAK_TRACK)
  30. #include "regleak.h"
  31. #endif // LEAK_TRACK
  32. #endif
  33. //
  34. // Determine the length of a Unicode string w/o the trailing NULL.
  35. //
  36. #define LENGTH( str ) ( sizeof( str ) - sizeof( UNICODE_NULL ))
  37. //
  38. // Nt Registry name space.
  39. //
  40. #define MACHINE L"\\REGISTRY\\MACHINE"
  41. #define USER L"\\REGISTRY\\USER"
  42. #define CLASSES L"\\REGISTRY\\MACHINE\\SOFTWARE\\CLASSES"
  43. #define CURRENTCONFIG L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\HARDWARE PROFILES\\CURRENT"
  44. extern const
  45. UNICODE_STRING MachineStringKey = {
  46. LENGTH( MACHINE ),
  47. LENGTH( MACHINE ),
  48. MACHINE
  49. };
  50. extern const
  51. UNICODE_STRING UserStringKey = {
  52. LENGTH( USER ),
  53. LENGTH( USER ),
  54. USER
  55. };
  56. extern const
  57. UNICODE_STRING ClassesStringKey = {
  58. LENGTH( CLASSES ),
  59. LENGTH( CLASSES ),
  60. CLASSES
  61. };
  62. extern const
  63. UNICODE_STRING CurrentConfigStringKey = {
  64. LENGTH( CURRENTCONFIG ),
  65. LENGTH( CURRENTCONFIG ),
  66. CURRENTCONFIG
  67. };
  68. HANDLE RestrictedMachineHandle = NULL;
  69. NTSTATUS
  70. InitSecurityAcls(PSECURITY_DESCRIPTOR *SecurityDescriptor)
  71. /*++
  72. Routine Description:
  73. Gives GENERIC_ALL to admins and denies WRITE_OWNER | WRITE_DAC from everyone
  74. Arguments:
  75. Return Value:
  76. --*/
  77. {
  78. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  79. SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
  80. PSID BuiltInAdministrators = NULL;
  81. PSID Everyone = NULL;
  82. NTSTATUS Status;
  83. ULONG AclSize;
  84. ACL *Acl;
  85. *SecurityDescriptor = NULL;
  86. Status = RtlAllocateAndInitializeSid(
  87. &WorldAuthority,
  88. 1,
  89. SECURITY_WORLD_RID,
  90. 0,0,0,0,0,0,0,
  91. &Everyone );
  92. if( !NT_SUCCESS(Status) ) {
  93. goto Exit;
  94. }
  95. Status = RtlAllocateAndInitializeSid(
  96. &NtAuthority,
  97. 2,
  98. SECURITY_BUILTIN_DOMAIN_RID,
  99. DOMAIN_ALIAS_RID_ADMINS,
  100. 0,0,0,0,0,0,
  101. &BuiltInAdministrators );
  102. if( !NT_SUCCESS(Status) ) {
  103. goto Exit;
  104. }
  105. AclSize = sizeof (ACL) +
  106. (2 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (ULONG))) +
  107. GetLengthSid(BuiltInAdministrators) +
  108. GetLengthSid(Everyone);
  109. *SecurityDescriptor = (PSECURITY_DESCRIPTOR)RtlAllocateHeap( RtlProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH + AclSize);
  110. if (!*SecurityDescriptor) {
  111. Status = STATUS_INSUFFICIENT_RESOURCES;
  112. goto Exit;
  113. }
  114. Acl = (ACL *)((BYTE *)(*SecurityDescriptor) + SECURITY_DESCRIPTOR_MIN_LENGTH);
  115. Status = RtlCreateAcl( Acl,
  116. AclSize,
  117. ACL_REVISION);
  118. if( !NT_SUCCESS(Status) ) {
  119. goto Exit;
  120. }
  121. Status = RtlAddAccessAllowedAce(Acl,
  122. ACL_REVISION,
  123. (KEY_ALL_ACCESS & ~(WRITE_OWNER | WRITE_DAC)),
  124. Everyone);
  125. if( !NT_SUCCESS(Status) ) {
  126. goto Exit;
  127. }
  128. Status = RtlAddAccessAllowedAce(Acl,
  129. ACL_REVISION,
  130. GENERIC_ALL,
  131. BuiltInAdministrators);
  132. if( !NT_SUCCESS(Status) ) {
  133. goto Exit;
  134. }
  135. Status = RtlCreateSecurityDescriptor(
  136. *SecurityDescriptor,
  137. SECURITY_DESCRIPTOR_REVISION
  138. );
  139. if( !NT_SUCCESS(Status) ) {
  140. goto Exit;
  141. }
  142. Status = RtlSetDaclSecurityDescriptor( *SecurityDescriptor,
  143. TRUE,
  144. Acl,
  145. FALSE);
  146. Exit:
  147. if( Everyone ) {
  148. RtlFreeSid( Everyone );
  149. }
  150. if( BuiltInAdministrators ) {
  151. RtlFreeSid( BuiltInAdministrators );
  152. }
  153. return Status;
  154. }
  155. error_status_t
  156. OpenClassesRoot(
  157. IN PREGISTRY_SERVER_NAME ServerName,
  158. IN REGSAM samDesired,
  159. OUT PRPC_HKEY phKey
  160. )
  161. /*++
  162. Routine Description:
  163. Attempts to open the the HKEY_CLASSES_ROOT predefined handle.
  164. Arguments:
  165. ServerName - Not used.
  166. samDesired - This access mask describes the desired security access
  167. for the key.
  168. phKey - Returns a handle to the key \REGISTRY\MACHINE\SOFTWARE\CLASSES.
  169. Return Value:
  170. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  171. --*/
  172. {
  173. PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
  174. OBJECT_ATTRIBUTES Obja;
  175. NTSTATUS Status;
  176. UNICODE_STRING UsersHive;
  177. UNICODE_STRING UsersMergedHive;
  178. UNREFERENCED_PARAMETER( ServerName );
  179. //
  180. // Impersonate the client.
  181. //
  182. RPC_IMPERSONATE_CLIENT( NULL );
  183. #ifdef LOCAL
  184. //
  185. // Multiuser CLASSES key so each user has their own key. If opening
  186. // CLASSES in execute mode - open it under HKEY_CURRENT_USER else
  187. // just let it fall thru here and open the global one.
  188. //
  189. if (gpfnTermsrvOpenUserClasses) {
  190. Status = gpfnTermsrvOpenUserClasses(samDesired,phKey);
  191. } else {
  192. *phKey = NULL;
  193. }
  194. if (!(*phKey)) {
  195. #endif // LOCAL
  196. //
  197. // Initialize the SECURITY_DESCRIPTOR.
  198. //
  199. Status = InitSecurityAcls(&SecurityDescriptor);
  200. if( ! NT_SUCCESS( Status )) {
  201. goto error_exit;
  202. }
  203. #ifdef LOCAL
  204. if (gbCombinedClasses) {
  205. // first try for a per-user HKCR
  206. Status = OpenCombinedClassesRoot( samDesired, phKey );
  207. if ( NT_SUCCESS( Status ) ) {
  208. goto error_exit;
  209. }
  210. }
  211. #endif
  212. //
  213. // Initialize the OBJECT_ATTRIBUTES structure so that it creates
  214. // (opens) the key "\REGISTRY\MACHINE\SOFTWARE\CLASSES" with a Security
  215. // Descriptor that allows everyone complete access.
  216. //
  217. InitializeObjectAttributes(
  218. &Obja,
  219. (PUNICODE_STRING)&ClassesStringKey,
  220. OBJ_CASE_INSENSITIVE,
  221. NULL,
  222. SecurityDescriptor
  223. );
  224. Status = NtCreateKey(
  225. phKey,
  226. samDesired, // MAXIMUM_ALLOWED,
  227. &Obja,
  228. 0,
  229. NULL,
  230. REG_OPTION_NON_VOLATILE,
  231. NULL
  232. );
  233. #ifdef LOCAL
  234. }
  235. #endif // LOCAL
  236. #if DBG
  237. if( ! NT_SUCCESS( Status )) {
  238. DbgPrint(
  239. "Winreg Server: "
  240. "Creating HKEY_CLASSES_ROOT failed, status = 0x%x\n",
  241. Status
  242. );
  243. }
  244. #endif
  245. error_exit:
  246. if( SecurityDescriptor != NULL ) {
  247. RtlFreeHeap( RtlProcessHeap(), 0, SecurityDescriptor );
  248. }
  249. RPC_REVERT_TO_SELF();
  250. return (error_status_t)RtlNtStatusToDosError( Status );
  251. }
  252. error_status_t
  253. OpenCurrentUser(
  254. IN PREGISTRY_SERVER_NAME ServerName,
  255. IN REGSAM samDesired,
  256. OUT PRPC_HKEY phKey
  257. )
  258. /*++
  259. Routine Description:
  260. Attempts to open the the HKEY_CURRENT_USER predefined handle.
  261. Arguments:
  262. ServerName - Not used.
  263. samDesired - This access mask describes the desired security access
  264. for the key.
  265. phKey - Returns a handle to the key \REGISTRY\USER\*.
  266. Return Value:
  267. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  268. --*/
  269. {
  270. NTSTATUS Status;
  271. UNREFERENCED_PARAMETER( ServerName );
  272. //
  273. // Impersonate the client.
  274. //
  275. RPC_IMPERSONATE_CLIENT( NULL );
  276. //
  277. // Open the registry key.
  278. //
  279. Status = RtlOpenCurrentUser( samDesired, /* MAXIMUM_ALLOWED, */ phKey );
  280. RPC_REVERT_TO_SELF();
  281. //
  282. // Map the returned status
  283. //
  284. return (error_status_t)RtlNtStatusToDosError( Status );
  285. }
  286. error_status_t
  287. OpenLocalMachine(
  288. IN PREGISTRY_SERVER_NAME ServerName,
  289. IN REGSAM samDesired,
  290. OUT PRPC_HKEY phKey
  291. )
  292. /*++
  293. Routine Description:
  294. Attempt to open the the HKEY_LOCAL_MACHINE predefined handle.
  295. Arguments:
  296. ServerName - Not used.
  297. samDesired - This access mask describes the desired security access
  298. for the key.
  299. phKey - Returns a handle to the key \REGISTRY\MACHINE.
  300. Return Value:
  301. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  302. --*/
  303. {
  304. OBJECT_ATTRIBUTES Obja;
  305. NTSTATUS Status;
  306. UNREFERENCED_PARAMETER( ServerName );
  307. //
  308. // Impersonate the client.
  309. //
  310. RPC_IMPERSONATE_CLIENT( NULL );
  311. InitializeObjectAttributes(
  312. &Obja,
  313. (PUNICODE_STRING)&MachineStringKey,
  314. OBJ_CASE_INSENSITIVE,
  315. NULL,
  316. NULL
  317. );
  318. Status = NtOpenKey(
  319. phKey,
  320. samDesired, // MAXIMUM_ALLOWED,
  321. &Obja
  322. );
  323. #if DBG
  324. if( ! NT_SUCCESS( Status )) {
  325. DbgPrint(
  326. "Winreg Server: "
  327. "Opening HKEY_LOCAL_MACHINE failed, status = 0x%x\n",
  328. Status
  329. );
  330. }
  331. #endif
  332. if ( NT_SUCCESS( Status ) )
  333. {
  334. if (! REGSEC_CHECK_REMOTE( phKey ) )
  335. {
  336. ASSERT( RestrictedMachineHandle != NULL );
  337. NtClose(*phKey);
  338. *phKey = REGSEC_FLAG_HANDLE( RestrictedMachineHandle, CHECK_MACHINE_PATHS );
  339. }
  340. }
  341. RPC_REVERT_TO_SELF();
  342. return (error_status_t)RtlNtStatusToDosError( Status );
  343. }
  344. error_status_t
  345. OpenUsers(
  346. IN PREGISTRY_SERVER_NAME ServerName,
  347. IN REGSAM samDesired,
  348. OUT PRPC_HKEY phKey
  349. )
  350. /*++
  351. Routine Description:
  352. Attempts to open the the HKEY_USERS predefined handle.
  353. Arguments:
  354. ServerName - Not used.
  355. samDesired - This access mask describes the desired security access
  356. for the key.
  357. phKey - Returns a handle to the key \REGISTRY\USER.
  358. Return Value:
  359. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  360. --*/
  361. {
  362. OBJECT_ATTRIBUTES Obja;
  363. NTSTATUS Status;
  364. UNREFERENCED_PARAMETER( ServerName );
  365. //
  366. // Impersonate the client.
  367. //
  368. RPC_IMPERSONATE_CLIENT( NULL );
  369. InitializeObjectAttributes(
  370. &Obja,
  371. (PUNICODE_STRING)&UserStringKey,
  372. OBJ_CASE_INSENSITIVE,
  373. NULL,
  374. NULL
  375. );
  376. Status = NtOpenKey(
  377. phKey,
  378. samDesired, // MAXIMUM_ALLOWED,
  379. &Obja
  380. );
  381. #if DBG
  382. if( ! NT_SUCCESS( Status )) {
  383. DbgPrint(
  384. "Winreg Server: "
  385. "Opening HKEY_USERS failed, status = 0x%x\n",
  386. Status
  387. );
  388. }
  389. #endif
  390. /*
  391. if ( NT_SUCCESS( Status ) )
  392. {
  393. if (! REGSEC_CHECK_REMOTE( phKey ) )
  394. {
  395. *phKey = REGSEC_FLAG_HANDLE( *phKey, CHECK_USER_PATHS );
  396. }
  397. }
  398. */
  399. RPC_REVERT_TO_SELF();
  400. return (error_status_t)RtlNtStatusToDosError( Status );
  401. }
  402. error_status_t
  403. OpenCurrentConfig(
  404. IN PREGISTRY_SERVER_NAME ServerName,
  405. IN REGSAM samDesired,
  406. OUT PRPC_HKEY phKey
  407. )
  408. /*++
  409. Routine Description:
  410. Attempts to open the the HKEY_CURRENT_CONFIG predefined handle.
  411. Arguments:
  412. ServerName - Not used.
  413. samDesired - This access mask describes the desired security access
  414. for the key.
  415. phKey - Returns a handle to the key \REGISTRY\MACHINE\SYSTEM\CURRENTCONTROLSET\HARDWARE PROFILES\CURRENT
  416. Return Value:
  417. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  418. --*/
  419. {
  420. OBJECT_ATTRIBUTES Obja;
  421. NTSTATUS Status;
  422. UNREFERENCED_PARAMETER( ServerName );
  423. //
  424. // Impersonate the client.
  425. //
  426. RPC_IMPERSONATE_CLIENT( NULL );
  427. InitializeObjectAttributes(
  428. &Obja,
  429. (PUNICODE_STRING)&CurrentConfigStringKey,
  430. OBJ_CASE_INSENSITIVE,
  431. NULL,
  432. NULL
  433. );
  434. Status = NtOpenKey(
  435. phKey,
  436. samDesired, // MAXIMUM_ALLOWED,
  437. &Obja
  438. );
  439. #if DBG
  440. if( ! NT_SUCCESS( Status )) {
  441. DbgPrint(
  442. "Winreg Server: "
  443. "Opening HKEY_CURRENT_CONFIG failed, status = 0x%x\n",
  444. Status
  445. );
  446. }
  447. #endif
  448. RPC_REVERT_TO_SELF();
  449. return (error_status_t)RtlNtStatusToDosError( Status );
  450. }
  451. error_status_t
  452. OpenPerformanceData(
  453. IN PREGISTRY_SERVER_NAME ServerName,
  454. IN REGSAM samDesired,
  455. OUT PRPC_HKEY phKey
  456. )
  457. /*++
  458. Routine Description:
  459. Attempts to open the the HKEY_PERFORMANCE_DATA predefined handle.
  460. Arguments:
  461. ServerName - Not used.
  462. samDesired - Not used.
  463. phKey - Returns a the predefined handle HKEY_PERFORMANCE_DATA.
  464. Return Value:
  465. Returns ERROR_SUCCESS (0) for success;
  466. or a DOS (not NT) error-code for failure.
  467. --*/
  468. {
  469. NTSTATUS status;
  470. if ( 0 ) {
  471. DBG_UNREFERENCED_PARAMETER(ServerName);
  472. DBG_UNREFERENCED_PARAMETER(samDesired);
  473. }
  474. //
  475. // Impersonate the client.
  476. //
  477. RPC_IMPERSONATE_CLIENT( NULL );
  478. if ( ! REGSEC_CHECK_PERF( phKey ) )
  479. {
  480. RPC_REVERT_TO_SELF();
  481. return( ERROR_ACCESS_DENIED );
  482. }
  483. // Move lodctr/unlodctr access check to part of PerfOpenKey()
  484. status = PerfOpenKey( HKEY_PERFORMANCE_DATA );
  485. RPC_REVERT_TO_SELF();
  486. *phKey = (RPC_HKEY) HKEY_PERFORMANCE_DATA;
  487. return ERROR_SUCCESS;
  488. }
  489. error_status_t
  490. OpenPerformanceText(
  491. IN PREGISTRY_SERVER_NAME ServerName,
  492. IN REGSAM samDesired,
  493. OUT PRPC_HKEY phKey
  494. )
  495. /*++
  496. Routine Description:
  497. Attempts to open the the HKEY_PERFORMANCE_TEXT predefined handle.
  498. Arguments:
  499. ServerName - Not used.
  500. samDesired - Not used.
  501. phKey - Returns the predefined handle HKEY_PERFORMANCE_TEXT.
  502. Return Value:
  503. Returns ERROR_SUCCESS (0) for success;
  504. or a DOS (not NT) error-code for failure.
  505. --*/
  506. {
  507. error_status_t Status = ERROR_SUCCESS;
  508. // No need to call OpenPerformanceData for getting text (HWC 4/1994)
  509. // Status = OpenPerformanceData(ServerName, samDesired, phKey);
  510. // if (Status==ERROR_SUCCESS) {
  511. *phKey = HKEY_PERFORMANCE_TEXT;
  512. // }
  513. return(Status);
  514. }
  515. error_status_t
  516. OpenPerformanceNlsText(
  517. IN PREGISTRY_SERVER_NAME ServerName,
  518. IN REGSAM samDesired,
  519. OUT PRPC_HKEY phKey
  520. )
  521. /*++
  522. Routine Description:
  523. Attempts to open the the HKEY_PERFORMANCE_TEXT predefined handle.
  524. Arguments:
  525. ServerName - Not used.
  526. samDesired - Not used.
  527. phKey - Returns the predefined handle HKEY_PERFORMANCE_NLSTEXT.
  528. Return Value:
  529. Returns ERROR_SUCCESS (0) for success;
  530. or a DOS (not NT) error-code for failure.
  531. --*/
  532. {
  533. error_status_t Status = ERROR_SUCCESS;
  534. // No need to call OpenPerformanceData for getting text (HWC 4/1994)
  535. // Status = OpenPerformanceData(ServerName, samDesired, phKey);
  536. // if (Status==ERROR_SUCCESS) {
  537. *phKey = HKEY_PERFORMANCE_NLSTEXT;
  538. // }
  539. return(Status);
  540. }
  541. error_status_t
  542. OpenDynData(
  543. IN PREGISTRY_SERVER_NAME ServerName,
  544. IN REGSAM samDesired,
  545. OUT PRPC_HKEY phKey
  546. )
  547. /*++
  548. Routine Description:
  549. Attempts to open the the HKEY_DYN_DATA predefined handle.
  550. There is currently no HKEY_DYN_DATA on NT, thus this
  551. function always returns ERROR_CALL_NOT_IMPLEMENTED.
  552. Arguments:
  553. ServerName - Not used.
  554. samDesired - This access mask describes the desired security access
  555. for the key.
  556. phKey - Returns a handle to the key HKEY_DYN_DATA
  557. Return Value:
  558. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  559. --*/
  560. {
  561. return((error_status_t)ERROR_CALL_NOT_IMPLEMENTED);
  562. }
  563. //
  564. // Default ("fake") handle returned to all check_machine_paths-like connections
  565. //
  566. NTSTATUS
  567. OpenMachineKey(PHANDLE phKey)
  568. {
  569. OBJECT_ATTRIBUTES Obja;
  570. NTSTATUS Status;
  571. InitializeObjectAttributes(
  572. &Obja,
  573. (PUNICODE_STRING)&MachineStringKey,
  574. OBJ_CASE_INSENSITIVE,
  575. NULL,
  576. NULL
  577. );
  578. Status = NtOpenKey(
  579. phKey,
  580. MAXIMUM_ALLOWED,
  581. &Obja
  582. );
  583. return Status;
  584. }
  585. NTSTATUS
  586. InitRestrictedMachineHandle()
  587. {
  588. return OpenMachineKey(&RestrictedMachineHandle);
  589. }
  590. VOID
  591. CleanupRestrictedMachineHandle()
  592. {
  593. if( RestrictedMachineHandle != NULL ) {
  594. NtClose(RestrictedMachineHandle);
  595. RestrictedMachineHandle = NULL;
  596. }
  597. }