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.

293 lines
7.8 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. Regsckey.c
  5. Abstract:
  6. This module contains the server side implementation for the Win32
  7. Registry APIs to set and get the SECURITY_DESCRIPTOR for a key. That
  8. is:
  9. - BaseRegGetKeySecurity
  10. - BaseRegSetKeySecurity
  11. Author:
  12. David J. Gilman (davegi) 10-Feb-1992
  13. Notes:
  14. See the Notes in Regkey.c.
  15. --*/
  16. #include <rpc.h>
  17. #include "regrpc.h"
  18. #include "localreg.h"
  19. #ifdef LOCAL
  20. #include "tsappcmp.h"
  21. #endif
  22. error_status_t
  23. BaseRegGetKeySecurity(
  24. HKEY hKey,
  25. SECURITY_INFORMATION RequestedInformation,
  26. PRPC_SECURITY_DESCRIPTOR pRpcSecurityDescriptor
  27. )
  28. /*++
  29. Routine Description:
  30. This API returns a copy of the security descriptor protecting a
  31. previously opened key. Based on the caller's access rights and
  32. privileges, this API returns a security descriptor containing the
  33. requested security descriptor fields. To read the supplied key's
  34. security descriptor the caller must be granted READ_CONTROL access or
  35. be the owner of the object. In addition, the caller must have
  36. SeSecurityPrivilege privilege to read the system ACL.
  37. Arguments:
  38. hKey - Supplies a handle to a previously opened key.
  39. SecurityInformation - Supplies the information needed to determine
  40. the type of security returned in the SECURITY_DESCRIPTOR.
  41. pSecurityDescriptor - Supplies a pointer to a buffer where the
  42. requested SECURITY_DESCRIPTOR will be written.
  43. lpcbSecurityDescriptor - Supplies a pointer to a DWORD which on input
  44. contains the size, in bytes, of the supplied SECURITY_DESCRIPTOR
  45. buffer. On output it contains the actual number of bytes required
  46. by the SECURITY_DESCRIPTOR.
  47. Return Value:
  48. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  49. Notes:
  50. If the buffer size passed in is too small, the correct value will be
  51. returned through lpcbSecurityDescriptor and the API will return,
  52. ERROR_INVALID_PARAMETER.
  53. --*/
  54. {
  55. NTSTATUS Status;
  56. PSECURITY_DESCRIPTOR lpSD;
  57. DWORD cbLen;
  58. DWORD Error = ERROR_SUCCESS;
  59. HKEY hPerflibKey = 0;
  60. OBJECT_ATTRIBUTES Obja;
  61. if (hKey == HKEY_PERFORMANCE_DATA ||
  62. hKey == HKEY_PERFORMANCE_TEXT ||
  63. hKey == HKEY_PERFORMANCE_NLSTEXT ) {
  64. //
  65. // For these special cases, get the hKey for Perflib
  66. // and return the Perflib's Security Info
  67. //
  68. UNICODE_STRING PerflibSubKeyString;
  69. BOOL bNeedSACL;
  70. bNeedSACL = RequestedInformation & SACL_SECURITY_INFORMATION;
  71. RtlInitUnicodeString (
  72. &PerflibSubKeyString,
  73. L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib");
  74. //
  75. // Initialize the OBJECT_ATTRIBUTES structure and open the key.
  76. //
  77. InitializeObjectAttributes(
  78. &Obja,
  79. &PerflibSubKeyString,
  80. OBJ_CASE_INSENSITIVE,
  81. NULL,
  82. NULL
  83. );
  84. Status = NtOpenKey(
  85. &hPerflibKey,
  86. bNeedSACL ?
  87. MAXIMUM_ALLOWED | ACCESS_SYSTEM_SECURITY :
  88. MAXIMUM_ALLOWED,
  89. &Obja
  90. );
  91. if ( ! NT_SUCCESS( Status )) {
  92. Error = RtlNtStatusToDosError( Status );
  93. pRpcSecurityDescriptor->cbInSecurityDescriptor = 0;
  94. pRpcSecurityDescriptor->cbOutSecurityDescriptor = 0;
  95. return (error_status_t)Error;
  96. }
  97. hKey = hPerflibKey;
  98. } else {
  99. ASSERT( IsPredefinedRegistryHandle( hKey ) == FALSE );
  100. }
  101. //
  102. // Allocate space for the security descriptor
  103. //
  104. lpSD = (PSECURITY_DESCRIPTOR)
  105. RtlAllocateHeap(
  106. RtlProcessHeap(), 0,
  107. pRpcSecurityDescriptor->cbInSecurityDescriptor
  108. );
  109. if ( !lpSD ) {
  110. Error = ERROR_OUTOFMEMORY;
  111. } else {
  112. Status = NtQuerySecurityObject(
  113. hKey,
  114. RequestedInformation,
  115. lpSD,
  116. pRpcSecurityDescriptor->cbInSecurityDescriptor,
  117. &cbLen
  118. );
  119. //
  120. // If the call fails, set the size of the buffer to zero so RPC
  121. // won't copy any data.
  122. //
  123. if( ! NT_SUCCESS( Status )) {
  124. Error = RtlNtStatusToDosError( Status );
  125. } else {
  126. //
  127. // Convert the security descriptor to a Self-relative form
  128. //
  129. Error = MapSDToRpcSD (
  130. lpSD,
  131. pRpcSecurityDescriptor
  132. );
  133. }
  134. if ( Error != ERROR_SUCCESS ) {
  135. pRpcSecurityDescriptor->cbInSecurityDescriptor = cbLen;
  136. pRpcSecurityDescriptor->cbOutSecurityDescriptor = 0;
  137. }
  138. //
  139. // Free the buffer that we allocated for the security descriptor
  140. //
  141. RtlFreeHeap(
  142. RtlProcessHeap(), 0,
  143. lpSD
  144. );
  145. }
  146. if (hPerflibKey) {
  147. // Close the Perflib that was created in the special cases
  148. NtClose(hPerflibKey);
  149. }
  150. return (error_status_t)Error;
  151. }
  152. error_status_t
  153. BaseRegSetKeySecurity(
  154. HKEY hKey,
  155. SECURITY_INFORMATION SecurityInformation,
  156. PRPC_SECURITY_DESCRIPTOR pRpcSecurityDescriptor
  157. )
  158. /*++
  159. Routine Description:
  160. This API can be used to set the security of a previously opened key.
  161. This call is only successful if the following conditions are met:
  162. o If the key's owner or group is to be set, the caller must
  163. have WRITE_OWNER permission or have SeTakeOwnershipPrivilege.
  164. o If the key's DACL is to be set, the caller must have
  165. WRITE_DAC permission or be the object's owner.
  166. o If the key's SACL is to be set, the caller must have
  167. SeSecurityPrivilege.
  168. Arguments:
  169. hKey - Supplies a handle to a previously opened key.
  170. SecurityInformation - Supplies a pointer to a SECURITY_INFORMATION
  171. structure that specifies the contents of the supplied
  172. SECURITY_DESCRIPTOR.
  173. pSecurityDescriptor - Supplies a pointer to the SECURITY_DESCRIPTOR
  174. to set on the supplied key.
  175. Return Value:
  176. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  177. --*/
  178. {
  179. NTSTATUS Status;
  180. if (hKey == HKEY_PERFORMANCE_DATA ||
  181. hKey == HKEY_PERFORMANCE_TEXT ||
  182. hKey == HKEY_PERFORMANCE_NLSTEXT ) {
  183. //
  184. // these keys get their security descriptor from
  185. // other "real" registry keys.
  186. //
  187. Status = STATUS_INVALID_HANDLE;
  188. } else {
  189. ASSERT( IsPredefinedRegistryHandle( hKey ) == FALSE );
  190. RPC_IMPERSONATE_CLIENT( NULL );
  191. //
  192. // Validate the security descriptor.
  193. //
  194. if( RtlValidRelativeSecurityDescriptor((PSECURITY_DESCRIPTOR)(pRpcSecurityDescriptor->lpSecurityDescriptor),
  195. pRpcSecurityDescriptor->cbInSecurityDescriptor,
  196. SecurityInformation )) {
  197. Status = NtSetSecurityObject(
  198. hKey,
  199. SecurityInformation,
  200. pRpcSecurityDescriptor->lpSecurityDescriptor
  201. );
  202. } else {
  203. //
  204. // We were passed a bogus security descriptor to set. Bail out
  205. //
  206. Status = STATUS_INVALID_PARAMETER;
  207. }
  208. RPC_REVERT_TO_SELF();
  209. }
  210. #ifdef LOCAL
  211. if (NT_SUCCESS(Status) && gpfnTermsrvSetKeySecurity) {
  212. gpfnTermsrvSetKeySecurity(hKey,
  213. SecurityInformation,
  214. pRpcSecurityDescriptor->lpSecurityDescriptor);
  215. }
  216. #endif
  217. return (error_status_t)RtlNtStatusToDosError( Status );
  218. }