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.

507 lines
13 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1999 - 1999
  3. Module Name:
  4. syncmgr.cxx
  5. Abstract:
  6. This file contains code for Syncmgr to workaround the security
  7. restrictions placed on HKLM registry key. Normal users cannot
  8. write to HKLM now. So, SENS (running as LocalSystem) does the
  9. dirty work for Syncmgr.
  10. Author:
  11. Gopal Parupudi <GopalP>
  12. Notes:
  13. This code is authored by RogerG.
  14. Revision History:
  15. GopalP 3/10/1999 Start.
  16. RogerG 9/29/1999 Plug security holes.
  17. --*/
  18. #include <precomp.hxx>
  19. typedef enum SYNCMGRCMDEXECID
  20. {
  21. SYNCMGRCMDEXECID_UPDATERUNKEY = 1,
  22. SYNCMGRCMDEXECID_RESETREGSECURITY = 2,
  23. } SYNCMGRCMDEXECID;
  24. // functions local to file implementation is in.
  25. HRESULT SyncMgrExecCmdUpdateRunKey(DWORD nCmdID, DWORD nCmdExecOpt);
  26. HRESULT SyncMgrExecCmdResetRegSecurity(DWORD nCmdID, DWORD nCmdExecOpt);
  27. BOOL SyncMgrGetSecurityDescriptor(SECURITY_ATTRIBUTES *psa,PSECURITY_DESCRIPTOR psd,
  28. PACL *ppOutAcl);
  29. BOOL SyncMgrSetRegKeySecurityEveryone(HKEY hKeyParent,LPCTSTR lpSubKey,SECURITY_DESCRIPTOR *psd); // helper function
  30. HRESULT SyncSetSubKeySecurityEveryone(HKEY hKeyParent,SECURITY_DESCRIPTOR *psd); // helper function
  31. // end of local function delclaration
  32. //--------------------------------------------------------------------------------
  33. //
  34. // FUNCTION: RPC_SyncMgrExecCmd, public
  35. //
  36. // PURPOSE: Executes specified SyncMgr cmd.
  37. //
  38. //
  39. // COMMENTS:
  40. //
  41. //
  42. //--------------------------------------------------------------------------------
  43. error_status_t RPC_SyncMgrExecCmd(handle_t hRpc, DWORD nCmdID, DWORD nCmdExecOpt)
  44. {
  45. HRESULT hr = E_UNEXPECTED;
  46. switch (nCmdID)
  47. {
  48. case SYNCMGRCMDEXECID_UPDATERUNKEY:
  49. hr = SyncMgrExecCmdUpdateRunKey(nCmdID,nCmdExecOpt);
  50. break;
  51. case SYNCMGRCMDEXECID_RESETREGSECURITY:
  52. hr = SyncMgrExecCmdResetRegSecurity(nCmdID,nCmdExecOpt);
  53. break;
  54. default:
  55. hr = S_FALSE;
  56. break;
  57. }
  58. return hr;
  59. }
  60. //--------------------------------------------------------------------------------
  61. //
  62. // FUNCTION: SyncMgrExecCmdUpdateRunKey
  63. //
  64. // PURPOSE: Updates the RunKey under HKLM to set if mobsync.exe
  65. // is run on shell startup.
  66. //
  67. //
  68. // COMMENTS:
  69. //
  70. //
  71. //--------------------------------------------------------------------------------
  72. const TCHAR szRunKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
  73. const TCHAR szRunKeyCommandLine[] = TEXT("%SystemRoot%\\system32\\mobsync.exe /logon");
  74. const TCHAR szRunKeyValueName[] = TEXT("Synchronization Manager");
  75. HRESULT SyncMgrExecCmdUpdateRunKey(DWORD nCmdID, DWORD nCmdExecOpt)
  76. {
  77. HRESULT hr;
  78. HKEY hKeyRun;
  79. BOOL fLogon = nCmdExecOpt ? TRUE : FALSE; // CmdExecOpt of zero means to remove, else write.
  80. if (ERROR_SUCCESS == (hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,szRunKey,
  81. NULL,KEY_READ | KEY_WRITE,&hKeyRun)))
  82. {
  83. if (fLogon)
  84. {
  85. hr = RegSetValueEx(hKeyRun, szRunKeyValueName, 0, REG_EXPAND_SZ,
  86. (BYTE *) szRunKeyCommandLine,(lstrlen(szRunKeyCommandLine) + 1)*sizeof(TCHAR));
  87. }
  88. else
  89. {
  90. hr = RegDeleteValue(hKeyRun, szRunKeyValueName);
  91. }
  92. RegCloseKey(hKeyRun);
  93. }
  94. return hr;
  95. }
  96. //--------------------------------------------------------------------------------
  97. //
  98. // FUNCTION: SyncMgrGetSecurityDescriptor
  99. //
  100. // PURPOSE: Creates an appropriate secuirty descriptor to set on
  101. // the subkeys.
  102. //
  103. //
  104. // COMMENTS:
  105. //
  106. //
  107. //--------------------------------------------------------------------------------
  108. BOOL SyncMgrGetSecurityDescriptor(SECURITY_ATTRIBUTES *psa
  109. ,PSECURITY_DESCRIPTOR psd,
  110. PACL *ppOutAcl)
  111. {
  112. BOOL bRetVal;
  113. int cbAcl;
  114. PACL pAcl = NULL;
  115. PSID pInteractiveUserSid = NULL;
  116. PSID pLocalSystemSid = NULL;
  117. PSID pAdminsSid = NULL;
  118. SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
  119. SID_IDENTIFIER_AUTHORITY LocalSystemAuthority = SECURITY_NT_AUTHORITY;
  120. *ppOutAcl = NULL;
  121. bRetVal = FALSE;
  122. // in the structure.
  123. bRetVal = InitializeSecurityDescriptor(
  124. psd, // Pointer to SD
  125. SECURITY_DESCRIPTOR_REVISION // SD revision
  126. );
  127. if (!bRetVal)
  128. {
  129. goto errRtn;
  130. }
  131. // setup acls.
  132. bRetVal = AllocateAndInitializeSid(
  133. &LocalSystemAuthority, // Pointer to identifier authority
  134. 1, // Count of subauthority
  135. SECURITY_INTERACTIVE_RID, // Subauthority 0
  136. 0, // Subauthority 1
  137. 0, // Subauthority 2
  138. 0, // Subauthority 3
  139. 0, // Subauthority 4
  140. 0, // Subauthority 5
  141. 0, // Subauthority 6
  142. 0, // Subauthority 7
  143. &pInteractiveUserSid // pointer to pointer to SID
  144. );
  145. if (!bRetVal)
  146. {
  147. goto errRtn;
  148. }
  149. bRetVal = AllocateAndInitializeSid(
  150. &LocalSystemAuthority,// Pointer to identifier authority
  151. 2, // Count of subauthority
  152. SECURITY_BUILTIN_DOMAIN_RID, // Subauthority 1
  153. DOMAIN_ALIAS_RID_ADMINS, // Subauthority 2
  154. 0, // Subauthority 2
  155. 0, // Subauthority 3
  156. 0, // Subauthority 4
  157. 0, // Subauthority 5
  158. 0, // Subauthority 6
  159. 0, // Subauthority 7
  160. &pAdminsSid // pointer to pointer to SID
  161. );
  162. if (!bRetVal)
  163. {
  164. goto errRtn;
  165. }
  166. bRetVal = AllocateAndInitializeSid(
  167. &LocalSystemAuthority,// Pointer to identifier authority
  168. 1, // Count of subauthority
  169. SECURITY_LOCAL_SYSTEM_RID, // Subauthority 0
  170. 0, // Subauthority 1
  171. 0, // Subauthority 2
  172. 0, // Subauthority 3
  173. 0, // Subauthority 4
  174. 0, // Subauthority 5
  175. 0, // Subauthority 6
  176. 0, // Subauthority 7
  177. &pLocalSystemSid // pointer to pointer to SID
  178. );
  179. if (!bRetVal)
  180. {
  181. goto errRtn;
  182. }
  183. cbAcl = sizeof (ACL)
  184. + 3 * sizeof (ACCESS_ALLOWED_ACE)
  185. + GetLengthSid(pInteractiveUserSid)
  186. + GetLengthSid(pLocalSystemSid)
  187. + GetLengthSid(pAdminsSid);
  188. pAcl = (PACL) new char[cbAcl];
  189. if (NULL == pAcl)
  190. {
  191. bRetVal = FALSE;
  192. goto errRtn;
  193. }
  194. bRetVal = InitializeAcl(
  195. pAcl, // Pointer to the ACL
  196. cbAcl, // Size of ACL
  197. ACL_REVISION // Revision level of ACL
  198. );
  199. if (!bRetVal)
  200. {
  201. goto errRtn;
  202. }
  203. bRetVal = AddAccessAllowedAce(
  204. pAcl, // Pointer to the ACL
  205. ACL_REVISION, // ACL revision level
  206. SPECIFIC_RIGHTS_ALL | GENERIC_READ | DELETE , // Access Mask
  207. pInteractiveUserSid // Pointer to SID
  208. );
  209. if (!bRetVal)
  210. {
  211. goto errRtn;
  212. }
  213. bRetVal = AddAccessAllowedAce(
  214. pAcl, // Pointer to the ACL
  215. ACL_REVISION, // ACL revision level
  216. GENERIC_ALL, // Access Mask
  217. pAdminsSid // Pointer to SID
  218. );
  219. if (!bRetVal)
  220. {
  221. goto errRtn;
  222. }
  223. bRetVal = AddAccessAllowedAce(
  224. pAcl, // Pointer to the ACL
  225. ACL_REVISION, // ACL revision level
  226. GENERIC_ALL, // Access Mask
  227. pLocalSystemSid // Pointer to SID
  228. );
  229. if (!bRetVal)
  230. {
  231. goto errRtn;
  232. }
  233. bRetVal = SetSecurityDescriptorDacl(psd,TRUE,pAcl,FALSE);
  234. if (!bRetVal)
  235. {
  236. goto errRtn;
  237. }
  238. psa->nLength = sizeof(SECURITY_ATTRIBUTES);
  239. psa->lpSecurityDescriptor = psd;
  240. psa->bInheritHandle = FALSE;
  241. errRtn:
  242. if (pInteractiveUserSid)
  243. {
  244. FreeSid(pInteractiveUserSid);
  245. }
  246. if (pLocalSystemSid)
  247. {
  248. FreeSid(pLocalSystemSid);
  249. }
  250. if (pAdminsSid)
  251. {
  252. FreeSid(pAdminsSid);
  253. }
  254. //
  255. // On failure, we clean the ACL up. On success, the caller cleans
  256. // it up after using it.
  257. //
  258. if (FALSE == bRetVal)
  259. {
  260. if (pAcl)
  261. {
  262. delete pAcl;
  263. }
  264. }
  265. else
  266. {
  267. *ppOutAcl = pAcl;
  268. }
  269. return bRetVal;
  270. }
  271. //--------------------------------------------------------------------------------
  272. //
  273. // FUNCTION: SyncMgrExecCmdResetRegSecurity
  274. //
  275. // PURPOSE: Makes sure HKLM..\SyncMgr key and all keys below
  276. // it can be accessed by all users.
  277. //
  278. //
  279. // COMMENTS:
  280. //
  281. //
  282. //--------------------------------------------------------------------------------
  283. const TCHAR szSyncMgrTopLevelKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\SyncMgr");
  284. HRESULT SyncMgrExecCmdResetRegSecurity(DWORD nCmdID, DWORD nCmdExecOpt)
  285. {
  286. HRESULT hr = E_UNEXPECTED;
  287. SECURITY_ATTRIBUTES sa;
  288. SECURITY_DESCRIPTOR sd;
  289. PACL pAcl = NULL;
  290. if (!SyncMgrGetSecurityDescriptor(&sa,&sd,&pAcl))
  291. {
  292. SensPrintA(SENS_ERR, ("Unable to GetSecurity Attribs"));
  293. return E_FAIL;
  294. }
  295. // first try to set toplevel key
  296. if (SyncMgrSetRegKeySecurityEveryone(HKEY_LOCAL_MACHINE,szSyncMgrTopLevelKey,&sd))
  297. {
  298. HKEY hKeySyncMgr;
  299. // open the Key with REG_OPTION_OPEN_LINK so if someone places a symbolic
  300. // link under syncmgr we don't traverse it.
  301. if (ERROR_SUCCESS == (hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,szSyncMgrTopLevelKey,
  302. REG_OPTION_OPEN_LINK,KEY_READ | KEY_WRITE,&hKeySyncMgr)) )
  303. {
  304. SyncSetSubKeySecurityEveryone(hKeySyncMgr,&sd);
  305. RegCloseKey(hKeySyncMgr);
  306. }
  307. }
  308. if (pAcl)
  309. {
  310. delete pAcl;
  311. }
  312. return hr;
  313. }
  314. //--------------------------------------------------------------------------------
  315. //
  316. // FUNCTION: SyncSetSubKeySecurity
  317. //
  318. // PURPOSE: sets the security on all subkeys on the parent to everyone.
  319. //
  320. //
  321. // COMMENTS:
  322. //
  323. //
  324. //--------------------------------------------------------------------------------
  325. #define MAX_KEY_LENGTH 255
  326. HRESULT SyncSetSubKeySecurityEveryone(HKEY hKeyParent,SECURITY_DESCRIPTOR *psd)
  327. {
  328. HRESULT hr;
  329. HRESULT hrSubKey;
  330. int iIndexCount;
  331. DWORD cbSubKey;
  332. TCHAR szSubKey[MAX_KEY_LENGTH];
  333. iIndexCount = 0;
  334. hr = ERROR_SUCCESS;
  335. hrSubKey = ERROR_SUCCESS;
  336. do
  337. {
  338. HKEY hKeySubKey;
  339. HRESULT hrCurSubKey;
  340. cbSubKey = MAX_KEY_LENGTH;
  341. hr = RegEnumKeyEx(hKeyParent,iIndexCount,szSubKey,&cbSubKey,NULL,NULL,NULL,NULL);
  342. if(hr != ERROR_SUCCESS)
  343. {
  344. hr = (ERROR_NO_MORE_ITEMS == hr) ? ERROR_SUCCESS : hr;
  345. break;
  346. }
  347. SyncMgrSetRegKeySecurityEveryone(hKeyParent,szSubKey,psd);
  348. // failure to open want to remember error but keep going through
  349. // remaining subkeys.
  350. if (ERROR_SUCCESS == (hrCurSubKey = RegOpenKeyEx (hKeyParent,szSubKey,REG_OPTION_OPEN_LINK ,KEY_READ | KEY_WRITE, &hKeySubKey)))
  351. {
  352. hrCurSubKey = SyncSetSubKeySecurityEveryone(hKeySubKey,psd);
  353. RegCloseKey(hKeySubKey);
  354. }
  355. if (ERROR_SUCCESS != hrCurSubKey)
  356. {
  357. hrSubKey = hrCurSubKey;
  358. }
  359. ++iIndexCount;
  360. } while (ERROR_SUCCESS == hr);
  361. return (ERROR_SUCCESS != hr) ? hr : hrSubKey;
  362. }
  363. //--------------------------------------------------------------------------------
  364. //
  365. // FUNCTION: SyncMgrSetRegKeySecurityEveryone
  366. //
  367. // PURPOSE: Gives Everyone all access to the specified RegKey.
  368. //
  369. //
  370. // COMMENTS:
  371. //
  372. //
  373. //--------------------------------------------------------------------------------
  374. BOOL SyncMgrSetRegKeySecurityEveryone(HKEY hKeyParent,LPCTSTR lpSubKey,SECURITY_DESCRIPTOR *psd)
  375. {
  376. BOOL fResult = FALSE;
  377. HKEY hKey = NULL;
  378. // key must be openned with WRITE_DAC
  379. if (ERROR_SUCCESS != RegOpenKeyEx(hKeyParent,
  380. lpSubKey,
  381. REG_OPTION_OPEN_LINK, WRITE_DAC,&hKey) )
  382. {
  383. hKey = NULL;
  384. }
  385. if (hKey)
  386. {
  387. if (ERROR_SUCCESS == RegSetKeySecurity(hKey,
  388. (SECURITY_INFORMATION) DACL_SECURITY_INFORMATION,
  389. psd) )
  390. {
  391. fResult = TRUE;
  392. }
  393. RegCloseKey(hKey);
  394. }
  395. ASSERT(TRUE == fResult); // debugging lets find out when this fails.
  396. return fResult;
  397. }