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.

309 lines
8.5 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 = NULL;
  60. OBJECT_ATTRIBUTES Obja;
  61. if( pRpcSecurityDescriptor == NULL ) {
  62. //
  63. // malicious client/RPC attack
  64. //
  65. return ERROR_INVALID_PARAMETER;
  66. }
  67. if (hKey == HKEY_PERFORMANCE_DATA ||
  68. hKey == HKEY_PERFORMANCE_TEXT ||
  69. hKey == HKEY_PERFORMANCE_NLSTEXT ) {
  70. //
  71. // For these special cases, get the hKey for Perflib
  72. // and return the Perflib's Security Info
  73. //
  74. UNICODE_STRING PerflibSubKeyString;
  75. BOOL bNeedSACL;
  76. bNeedSACL = RequestedInformation & SACL_SECURITY_INFORMATION;
  77. RtlInitUnicodeString (
  78. &PerflibSubKeyString,
  79. L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib");
  80. //
  81. // Initialize the OBJECT_ATTRIBUTES structure and open the key.
  82. //
  83. InitializeObjectAttributes(
  84. &Obja,
  85. &PerflibSubKeyString,
  86. OBJ_CASE_INSENSITIVE,
  87. NULL,
  88. NULL
  89. );
  90. Status = NtOpenKey(
  91. &hPerflibKey,
  92. bNeedSACL ?
  93. MAXIMUM_ALLOWED | ACCESS_SYSTEM_SECURITY :
  94. MAXIMUM_ALLOWED,
  95. &Obja
  96. );
  97. if ( ! NT_SUCCESS( Status )) {
  98. Error = RtlNtStatusToDosError( Status );
  99. pRpcSecurityDescriptor->cbInSecurityDescriptor = 0;
  100. pRpcSecurityDescriptor->cbOutSecurityDescriptor = 0;
  101. return (error_status_t)Error;
  102. }
  103. hKey = hPerflibKey;
  104. } else {
  105. ASSERT( IsPredefinedRegistryHandle( hKey ) == FALSE );
  106. }
  107. //
  108. // Allocate space for the security descriptor
  109. //
  110. lpSD = (PSECURITY_DESCRIPTOR)
  111. RtlAllocateHeap(
  112. RtlProcessHeap(), 0,
  113. pRpcSecurityDescriptor->cbInSecurityDescriptor
  114. );
  115. if ( !lpSD ) {
  116. Error = ERROR_OUTOFMEMORY;
  117. } else {
  118. Status = NtQuerySecurityObject(
  119. hKey,
  120. RequestedInformation,
  121. lpSD,
  122. pRpcSecurityDescriptor->cbInSecurityDescriptor,
  123. &cbLen
  124. );
  125. //
  126. // If the call fails, set the size of the buffer to zero so RPC
  127. // won't copy any data.
  128. //
  129. if( ! NT_SUCCESS( Status )) {
  130. Error = RtlNtStatusToDosError( Status );
  131. } else {
  132. //
  133. // Convert the security descriptor to a Self-relative form
  134. //
  135. Error = MapSDToRpcSD (
  136. lpSD,
  137. pRpcSecurityDescriptor
  138. );
  139. }
  140. if ( Error != ERROR_SUCCESS ) {
  141. pRpcSecurityDescriptor->cbInSecurityDescriptor = cbLen;
  142. pRpcSecurityDescriptor->cbOutSecurityDescriptor = 0;
  143. }
  144. //
  145. // Free the buffer that we allocated for the security descriptor
  146. //
  147. RtlFreeHeap(
  148. RtlProcessHeap(), 0,
  149. lpSD
  150. );
  151. }
  152. if (hPerflibKey) {
  153. // Close the Perflib that was created in the special cases
  154. NtClose(hPerflibKey);
  155. }
  156. return (error_status_t)Error;
  157. }
  158. error_status_t
  159. BaseRegSetKeySecurity(
  160. HKEY hKey,
  161. SECURITY_INFORMATION SecurityInformation,
  162. PRPC_SECURITY_DESCRIPTOR pRpcSecurityDescriptor
  163. )
  164. /*++
  165. Routine Description:
  166. This API can be used to set the security of a previously opened key.
  167. This call is only successful if the following conditions are met:
  168. o If the key's owner or group is to be set, the caller must
  169. have WRITE_OWNER permission or have SeTakeOwnershipPrivilege.
  170. o If the key's DACL is to be set, the caller must have
  171. WRITE_DAC permission or be the object's owner.
  172. o If the key's SACL is to be set, the caller must have
  173. SeSecurityPrivilege.
  174. Arguments:
  175. hKey - Supplies a handle to a previously opened key.
  176. SecurityInformation - Supplies a pointer to a SECURITY_INFORMATION
  177. structure that specifies the contents of the supplied
  178. SECURITY_DESCRIPTOR.
  179. pSecurityDescriptor - Supplies a pointer to the SECURITY_DESCRIPTOR
  180. to set on the supplied key.
  181. Return Value:
  182. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  183. --*/
  184. {
  185. NTSTATUS Status;
  186. if( pRpcSecurityDescriptor == NULL ||
  187. pRpcSecurityDescriptor->lpSecurityDescriptor == NULL
  188. ) {
  189. //
  190. // malicious client/RPC attack
  191. //
  192. return ERROR_INVALID_PARAMETER;
  193. }
  194. if (hKey == HKEY_PERFORMANCE_DATA ||
  195. hKey == HKEY_PERFORMANCE_TEXT ||
  196. hKey == HKEY_PERFORMANCE_NLSTEXT ) {
  197. //
  198. // these keys get their security descriptor from
  199. // other "real" registry keys.
  200. //
  201. Status = STATUS_INVALID_HANDLE;
  202. } else {
  203. ASSERT( IsPredefinedRegistryHandle( hKey ) == FALSE );
  204. RPC_IMPERSONATE_CLIENT( NULL );
  205. //
  206. // Validate the security descriptor.
  207. //
  208. if( RtlValidRelativeSecurityDescriptor((PSECURITY_DESCRIPTOR)(pRpcSecurityDescriptor->lpSecurityDescriptor),
  209. pRpcSecurityDescriptor->cbInSecurityDescriptor,
  210. SecurityInformation )) {
  211. Status = NtSetSecurityObject(
  212. hKey,
  213. SecurityInformation,
  214. pRpcSecurityDescriptor->lpSecurityDescriptor
  215. );
  216. } else {
  217. //
  218. // We were passed a bogus security descriptor to set. Bail out
  219. //
  220. Status = STATUS_INVALID_PARAMETER;
  221. }
  222. RPC_REVERT_TO_SELF();
  223. }
  224. #ifdef LOCAL
  225. if (NT_SUCCESS(Status) && gpfnTermsrvSetKeySecurity) {
  226. gpfnTermsrvSetKeySecurity(hKey,
  227. SecurityInformation,
  228. pRpcSecurityDescriptor->lpSecurityDescriptor);
  229. }
  230. #endif
  231. return (error_status_t)RtlNtStatusToDosError( Status );
  232. }