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.

387 lines
12 KiB

  1. // Copied from \nt\private\net\config\upgrade\netupgrd
  2. // August 98 -- t-sdey
  3. #pragma hdrstop
  4. #include <winnt32.h>
  5. #include "idchange.h"
  6. DWORD
  7. DwRegKeySetAdministratorSecurity(HKEY hkey, DWORD samDesired,
  8. PSECURITY_DESCRIPTOR* ppsdOld);
  9. DWORD
  10. DwRegCreateOrOpenKeyExWithAdminAccess(HKEY hkey, LPCTSTR szSubKey,
  11. DWORD samDesired,
  12. BOOL fCreate, HKEY* phkeySubKey,
  13. PSECURITY_DESCRIPTOR* ppsd);
  14. DWORD
  15. DwRegOpenKeyExWithAdminAccess(HKEY hkey, LPCTSTR szSubKey, DWORD samDesired,
  16. HKEY* phkeySubKey, PSECURITY_DESCRIPTOR* ppsd)
  17. {
  18. return DwRegCreateOrOpenKeyExWithAdminAccess(hkey, szSubKey, samDesired,
  19. FALSE, phkeySubKey, ppsd);
  20. }
  21. //+--------------------------------------------------------------------------
  22. //
  23. // Function: DwRegCreateOrOpenKeyExWithAdminAccess
  24. //
  25. // Purpose: Creates/Opens a subkey. If the key exists but the local
  26. // administrators group does not have samDesired access to
  27. // it, the function will add the access needed to the
  28. // security descriptor
  29. //
  30. // Arguments:
  31. // hkeyParent [in] The key to create the subkey in
  32. // szSubKey [in] The subkey name
  33. // samDesired [in] The desired access for phkey
  34. // fCreate [in] TRUE if the key is to be created.
  35. // phSubkey [out] The handle to the subkey
  36. // ppsdOrig [out] The previous security settings of the key
  37. // if it already existed, optional
  38. //
  39. // Returns: DWORD. ERROR_SUCCESS or a failure code from winerror.h
  40. //
  41. // Author: billbe 15 Dec 1997
  42. //
  43. // Notes:
  44. //
  45. DWORD
  46. DwRegCreateOrOpenKeyExWithAdminAccess(HKEY hkey, LPCTSTR szSubKey,
  47. DWORD samDesired,
  48. BOOL fCreate, HKEY* phkeySubKey,
  49. PSECURITY_DESCRIPTOR* ppsd)
  50. {
  51. DWORD dwError = ERROR_SUCCESS;
  52. if (ppsd)
  53. {
  54. *ppsd = NULL;
  55. }
  56. // Create or open the key based on fCreate
  57. //
  58. if (fCreate)
  59. {
  60. dwError = RegCreateKeyEx(hkey, szSubKey, 0, NULL,
  61. REG_OPTION_NON_VOLATILE, samDesired, NULL, phkeySubKey,
  62. NULL);
  63. }
  64. else
  65. {
  66. dwError = RegOpenKeyEx(hkey, szSubKey, 0, samDesired,
  67. phkeySubKey);
  68. }
  69. // If access was denied we either tried to create or open a prexisting
  70. // key that we didn't have access to. We need to grant ourselves
  71. // permission.
  72. //
  73. if (ERROR_ACCESS_DENIED == dwError)
  74. {
  75. // open with access to read and set security
  76. dwError = RegOpenKeyEx(hkey, szSubKey, 0,
  77. WRITE_DAC | READ_CONTROL, phkeySubKey);
  78. if (ERROR_SUCCESS == dwError)
  79. {
  80. // Grant samDesired access to the local Administrators group
  81. dwError = DwRegKeySetAdministratorSecurity(*phkeySubKey, samDesired,
  82. ppsd);
  83. // Close and reopen the key with samDesired access
  84. RegCloseKey(*phkeySubKey);
  85. if (ERROR_SUCCESS == dwError)
  86. {
  87. dwError = RegOpenKeyEx(hkey, szSubKey, 0, samDesired,
  88. phkeySubKey);
  89. }
  90. }
  91. }
  92. return dwError;
  93. }
  94. //+--------------------------------------------------------------------------
  95. //
  96. // Function: DwAddToRegKeySecurityDescriptor
  97. //
  98. // Purpose: Adds access for a specified SID to a registry key
  99. //
  100. // Arguments:
  101. // hkey [in] The registry key that will receive the
  102. // modified security descriptor
  103. // psidGroup [in] The SID (in self-relative mode) that will be
  104. // granted access to the key
  105. // dwAccessMask [in] The access level to grant
  106. // ppsd [out] The previous security descriptor
  107. //
  108. // Returns: DWORD. ERROR_SUCCESS or a failure code from winerror.h
  109. //
  110. // Author: billbe 13 Dec 1997
  111. //
  112. // Notes: This function is based on AddToRegKeySD in the MSDN
  113. // article Windows NT Security by Christopher Nefcy
  114. //
  115. DWORD
  116. DwAddToRegKeySecurityDescriptor(HKEY hkey, PSID psidGroup,
  117. DWORD dwAccessMask,
  118. PSECURITY_DESCRIPTOR* ppsd)
  119. {
  120. PSECURITY_DESCRIPTOR psdAbsolute = NULL;
  121. PACL pdacl;
  122. DWORD cbSecurityDescriptor = 0;
  123. DWORD dwSecurityDescriptorRevision;
  124. DWORD cbDacl = 0;
  125. SECURITY_DESCRIPTOR_CONTROL sdc;
  126. PACL pdaclNew = NULL;
  127. DWORD cbAddDaclLength = 0;
  128. BOOL fAceFound = FALSE;
  129. BOOL fHasDacl = FALSE;
  130. BOOL fDaclDefaulted = FALSE;
  131. ACCESS_ALLOWED_ACE* pAce;
  132. DWORD i;
  133. BOOL fAceForGroupPresent = FALSE;
  134. DWORD dwMask;
  135. PSECURITY_DESCRIPTOR psdRelative = NULL;
  136. DWORD cbSize = 0;
  137. // Get the current security descriptor for hkey
  138. //
  139. DWORD dwError = RegGetKeySecurity(hkey, DACL_SECURITY_INFORMATION,
  140. psdRelative, &cbSize);
  141. if (ERROR_INSUFFICIENT_BUFFER == dwError)
  142. {
  143. psdRelative = malloc(cbSize);
  144. dwError = RegGetKeySecurity(hkey, DACL_SECURITY_INFORMATION,
  145. psdRelative, &cbSize);
  146. }
  147. // get security descriptor control from the security descriptor
  148. if (!GetSecurityDescriptorControl(psdRelative,
  149. (PSECURITY_DESCRIPTOR_CONTROL) &sdc,
  150. (LPDWORD) &dwSecurityDescriptorRevision))
  151. {
  152. return (GetLastError());
  153. }
  154. // check if DACL is present
  155. if (SE_DACL_PRESENT & sdc)
  156. {
  157. // get dacl
  158. if (!GetSecurityDescriptorDacl(psdRelative, (LPBOOL) &fHasDacl,
  159. (PACL *) &pdacl, (LPBOOL) &fDaclDefaulted))
  160. {
  161. return ( GetLastError());
  162. }
  163. // get dacl length
  164. cbDacl = pdacl->AclSize;
  165. // now check if SID's ACE is there
  166. for (i = 0; i < pdacl->AceCount; i++)
  167. {
  168. if (!GetAce(pdacl, i, (LPVOID *) &pAce))
  169. {
  170. return ( GetLastError());
  171. }
  172. // check if group sid is already there
  173. if (EqualSid((PSID) &(pAce->SidStart), psidGroup))
  174. {
  175. // If the correct access is present, return success
  176. if ((pAce->Mask & dwAccessMask) == dwAccessMask)
  177. {
  178. return ERROR_SUCCESS;
  179. }
  180. fAceForGroupPresent = TRUE;
  181. break;
  182. }
  183. }
  184. // if the group did not exist, we will need to add room
  185. // for another ACE
  186. if (!fAceForGroupPresent)
  187. {
  188. // get length of new DACL
  189. cbAddDaclLength = sizeof(ACCESS_ALLOWED_ACE) -
  190. sizeof(DWORD) + GetLengthSid(psidGroup);
  191. }
  192. }
  193. else
  194. {
  195. // get length of new DACL
  196. cbAddDaclLength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) -
  197. sizeof(DWORD) + GetLengthSid (psidGroup);
  198. }
  199. // get memory needed for new DACL
  200. pdaclNew = (PACL) malloc (cbDacl + cbAddDaclLength);
  201. if (!pdaclNew)
  202. {
  203. return (GetLastError());
  204. }
  205. // get the sd length
  206. cbSecurityDescriptor = GetSecurityDescriptorLength(psdRelative);
  207. // get memory for new SD
  208. psdAbsolute = (PSECURITY_DESCRIPTOR)
  209. malloc(cbSecurityDescriptor + cbAddDaclLength);
  210. if (!psdAbsolute)
  211. {
  212. dwError = GetLastError();
  213. goto ErrorExit;
  214. }
  215. // change self-relative SD to absolute by making new SD
  216. if (!InitializeSecurityDescriptor(psdAbsolute,
  217. SECURITY_DESCRIPTOR_REVISION))
  218. {
  219. dwError = GetLastError();
  220. goto ErrorExit;
  221. }
  222. // init new DACL
  223. if (!InitializeAcl(pdaclNew, cbDacl + cbAddDaclLength,
  224. ACL_REVISION))
  225. {
  226. dwError = GetLastError();
  227. goto ErrorExit;
  228. }
  229. // now add in all of the ACEs into the new DACL (if org DACL is there)
  230. if (SE_DACL_PRESENT & sdc)
  231. {
  232. for (i = 0; i < pdacl->AceCount; i++)
  233. {
  234. // get ace from original dacl
  235. if (!GetAce(pdacl, i, (LPVOID*) &pAce))
  236. {
  237. dwError = GetLastError();
  238. goto ErrorExit;
  239. }
  240. // If an ACE for our SID exists, we just need to bump
  241. // up the access level instead of creating a new ACE
  242. //
  243. if (EqualSid((PSID) &(pAce->SidStart), psidGroup))
  244. dwMask = dwAccessMask | pAce->Mask;
  245. else
  246. dwMask = pAce->Mask;
  247. // now add ace to new dacl
  248. if (!AddAccessAllowedAce(pdaclNew,
  249. ACL_REVISION, dwMask,
  250. (PSID) &(pAce->SidStart)))
  251. {
  252. dwError = GetLastError();
  253. goto ErrorExit;
  254. }
  255. }
  256. }
  257. // Add a new ACE for our SID if one was not already present
  258. if (!fAceForGroupPresent)
  259. {
  260. // now add new ACE to new DACL
  261. if (!AddAccessAllowedAce(pdaclNew, ACL_REVISION, dwAccessMask,
  262. psidGroup))
  263. {
  264. dwError = GetLastError();
  265. goto ErrorExit;
  266. }
  267. }
  268. // check if everything went ok
  269. if (!IsValidAcl(pdaclNew))
  270. {
  271. dwError = GetLastError();
  272. goto ErrorExit;
  273. }
  274. // now set security descriptor DACL
  275. if (!SetSecurityDescriptorDacl(psdAbsolute, TRUE, pdaclNew,
  276. fDaclDefaulted))
  277. {
  278. dwError = GetLastError();
  279. goto ErrorExit;
  280. }
  281. // check if everything went ok
  282. if (!IsValidSecurityDescriptor(psdAbsolute))
  283. {
  284. dwError = GetLastError();
  285. goto ErrorExit;
  286. }
  287. // now set the reg key security (this will overwrite any
  288. // existing security)
  289. dwError = RegSetKeySecurity(hkey,
  290. (SECURITY_INFORMATION)(DACL_SECURITY_INFORMATION), psdAbsolute);
  291. if (ppsd)
  292. {
  293. *ppsd = psdRelative;
  294. }
  295. ErrorExit:
  296. // free memory
  297. if (psdAbsolute)
  298. {
  299. free (psdAbsolute);
  300. if (pdaclNew)
  301. {
  302. free((VOID*) pdaclNew);
  303. }
  304. }
  305. return dwError;
  306. }
  307. //+--------------------------------------------------------------------------
  308. //
  309. // Function: DwRegKeySetAdministratorSecurity
  310. //
  311. // Purpose: Grants the local Administrators group full access to
  312. // hkey.
  313. //
  314. // Arguments:
  315. // hkey [in] The registry key
  316. // ppsdOld [out] The previous security descriptor for hkey
  317. //
  318. // Returns: DWORD. ERROR_SUCCESS or a failure code from winerror.h
  319. //
  320. // Author: billbe 13 Dec 1997
  321. //
  322. // Notes:
  323. //
  324. DWORD
  325. DwRegKeySetAdministratorSecurity(HKEY hkey, DWORD samDesired,
  326. PSECURITY_DESCRIPTOR* ppsdOld)
  327. {
  328. PSID psid;
  329. SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY;
  330. DWORD dwError = ERROR_SUCCESS;
  331. // Get sid for the local Administrators group
  332. if (!AllocateAndInitializeSid(&sidAuth, 2,
  333. SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
  334. 0, 0, 0, 0, 0, 0, &psid) )
  335. {
  336. dwError = GetLastError();
  337. }
  338. if (ERROR_SUCCESS == dwError)
  339. {
  340. // Add all access privileges for the local administrators group
  341. dwError = DwAddToRegKeySecurityDescriptor(hkey, psid,
  342. samDesired, ppsdOld);
  343. }
  344. return dwError;
  345. }