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.

2075 lines
57 KiB

  1. #include "pch.h"
  2. //*************************************************************
  3. //
  4. // CheckSlash()
  5. //
  6. // Purpose: Checks for an ending slash and adds one if
  7. // it is missing.
  8. //
  9. // Parameters: lpDir - directory
  10. // cchBuffer - Buffer size in char
  11. // pcchRemaining - buffer remaining after adding '\',
  12. // can be NULL if not required
  13. //
  14. // Return: Pointer to the end of the string
  15. //
  16. // Comments:
  17. //
  18. // History: Date Author Comment
  19. // 02/14/02 santanuc Created
  20. //
  21. //*************************************************************
  22. LPTSTR CheckSlash (LPTSTR lpDir, UINT cchBuffer, UINT* pcchRemaining)
  23. {
  24. UINT cchDir = lstrlen(lpDir);
  25. LPTSTR lpEnd;
  26. lpEnd = lpDir + cchDir;
  27. if (pcchRemaining) {
  28. *pcchRemaining = cchBuffer - cchDir - 1;
  29. }
  30. if (*(lpEnd - 1) != TEXT('\\')) {
  31. if (cchDir + 1 >= cchBuffer) { // No space to put \, should never happen
  32. return NULL;
  33. }
  34. *lpEnd = TEXT('\\');
  35. lpEnd++;
  36. *lpEnd = TEXT('\0');
  37. if (pcchRemaining)
  38. *pcchRemaining -= 1;
  39. }
  40. return lpEnd;
  41. }
  42. //*************************************************************
  43. //
  44. // SecureProfileDirectory()
  45. //
  46. // Purpose: Creates a secure directory that only the user
  47. // (identified by pSid), admin, and system have
  48. // access to.
  49. //
  50. // Parameters: lpDirectory - Directory Name
  51. // pSid - Sid for user
  52. //
  53. // Return: ERROR_SUCCESS if successful
  54. // Win32 error code if an error occurs
  55. //
  56. // Comments:
  57. //
  58. // History: Date Author Comment
  59. // 7/20/95 ericflo Created
  60. // 2/14/02 santanuc Changed to secure the directory
  61. // only rather than creating it recursively
  62. //
  63. //*************************************************************
  64. DWORD SecureProfileDirectory (LPTSTR lpDirectory, PSID pSid)
  65. {
  66. PACL pAcl = NULL;
  67. DWORD dwError;
  68. //
  69. // Verbose Output
  70. //
  71. DEBUGMSG ((DM_VERBOSE, "SecureProfileDirectory: Entering with <%s>", lpDirectory));
  72. if (!pSid) {
  73. // Nothing to secure
  74. DEBUGMSG ((DM_VERBOSE, "SecureProfileDirectory: NULL sid specified"));
  75. return ERROR_SUCCESS;
  76. }
  77. //
  78. // Get the default ACL
  79. //
  80. pAcl = CreateDefaultAcl (pSid);
  81. if (!pAcl) {
  82. DEBUGMSG ((DM_WARNING, "SecureProfileDirectory: Fail to create ACL"));
  83. }
  84. //
  85. // Attempt to secure the directory
  86. //
  87. dwError = SetNamedSecurityInfo( (PTSTR) lpDirectory,
  88. SE_FILE_OBJECT,
  89. DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
  90. NULL,
  91. NULL,
  92. pAcl,
  93. NULL );
  94. if (dwError != ERROR_SUCCESS) {
  95. DEBUGMSG ((DM_WARNING, "SecureProfileDirectory: Failed to set security descriptor dacl for profile directory. Error = %d", GetLastError()));
  96. }
  97. else {
  98. DEBUGMSG ((DM_VERBOSE, "SecureProfileDirectory: Secure the directory <%s>", lpDirectory));
  99. }
  100. FreeDefaultAcl (pAcl);
  101. return dwError;
  102. }
  103. //*************************************************************
  104. //
  105. // SetMachineProfileKeySecurity
  106. //
  107. // Purpose: Sets the security on the profile key under HKLM/ProfileList
  108. //
  109. // Parameters: pSid - User's sid
  110. // lpKeyName - Name of the registry key
  111. //
  112. // Return: TRUE if successful
  113. // FALSE if an error occurs
  114. //
  115. // Comments:
  116. //
  117. // History: Date Author Comment
  118. // 2/22/99 ushaji adapted
  119. //
  120. //*************************************************************
  121. BOOL SetMachineProfileKeySecurity (PSID pSid, LPTSTR lpKeyName)
  122. {
  123. SECURITY_DESCRIPTOR sd;
  124. SECURITY_ATTRIBUTES sa;
  125. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  126. PACL pAcl = NULL;
  127. PSID psidSystem = NULL, psidAdmin = NULL, psidUsers = NULL;
  128. DWORD cbAcl, aceIndex;
  129. ACE_HEADER * lpAceHeader;
  130. BOOL bRetVal = FALSE;
  131. HKEY hKeyProfile=NULL;
  132. DWORD Error, dwDisp;
  133. //
  134. // Get the system sid
  135. //
  136. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  137. 0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
  138. DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to initialize system sid. Error = %d", GetLastError()));
  139. goto Exit;
  140. }
  141. //
  142. // Get the Admin sid
  143. //
  144. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  145. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  146. 0, 0, 0, 0, &psidAdmin)) {
  147. DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to initialize admin sid. Error = %d", GetLastError()));
  148. goto Exit;
  149. }
  150. //
  151. // Get the users sid
  152. //
  153. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  154. DOMAIN_ALIAS_RID_USERS,
  155. 0, 0, 0, 0, 0, 0, &psidUsers)) {
  156. DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to initialize authenticated users sid. Error = %d", GetLastError()));
  157. goto Exit;
  158. }
  159. //
  160. // Allocate space for the ACL. (No Inheritable Aces)
  161. //
  162. cbAcl = (GetLengthSid (psidSystem)) +
  163. (GetLengthSid (psidAdmin)) +
  164. (GetLengthSid (psidUsers)) +
  165. (GetLengthSid (pSid)) +
  166. sizeof(ACL) +
  167. (4 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  168. pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  169. if (!pAcl) {
  170. goto Exit;
  171. }
  172. if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
  173. DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to initialize acl. Error = %d", GetLastError()));
  174. goto Exit;
  175. }
  176. //
  177. // Add Aces. Non-inheritable ACEs first
  178. //
  179. aceIndex = 0;
  180. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) {
  181. DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
  182. goto Exit;
  183. }
  184. aceIndex++;
  185. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) {
  186. DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
  187. goto Exit;
  188. }
  189. aceIndex++;
  190. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_READ, psidUsers)) {
  191. DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
  192. goto Exit;
  193. }
  194. aceIndex++;
  195. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS ^ (WRITE_DAC | WRITE_OWNER), pSid)) {
  196. DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
  197. goto Exit;
  198. }
  199. //
  200. // Put together the security descriptor
  201. //
  202. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
  203. DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to initialize security descriptor. Error = %d", GetLastError()));
  204. goto Exit;
  205. }
  206. if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
  207. DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to set security descriptor dacl. Error = %d", GetLastError()));
  208. goto Exit;
  209. }
  210. Error = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  211. lpKeyName,
  212. 0,
  213. NULL,
  214. REG_OPTION_NON_VOLATILE,
  215. WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
  216. NULL,
  217. &hKeyProfile,
  218. &dwDisp);
  219. if (Error != ERROR_SUCCESS) {
  220. DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Couldn't open registry key to set security. Error = %d", Error));
  221. SetLastError(Error);
  222. goto Exit;
  223. }
  224. //
  225. // Set the security
  226. //
  227. Error = RegSetKeySecurity(hKeyProfile, DACL_SECURITY_INFORMATION, &sd);
  228. if (Error != ERROR_SUCCESS) {
  229. DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Couldn't set security. Error = %d", Error));
  230. SetLastError(Error);
  231. goto Exit;
  232. }
  233. else {
  234. bRetVal = TRUE;
  235. }
  236. Exit:
  237. if (psidSystem) {
  238. FreeSid(psidSystem);
  239. }
  240. if (psidAdmin) {
  241. FreeSid(psidAdmin);
  242. }
  243. if (psidUsers) {
  244. FreeSid(psidUsers);
  245. }
  246. if (pAcl) {
  247. GlobalFree (pAcl);
  248. }
  249. if (hKeyProfile) {
  250. RegCloseKey(hKeyProfile);
  251. }
  252. return bRetVal;
  253. }
  254. PACL
  255. CreateDefaultAcl (
  256. PSID pSid
  257. )
  258. {
  259. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  260. PACL pAcl = NULL;
  261. PSID psidSystem = NULL, psidAdmin = NULL;
  262. DWORD cbAcl, aceIndex;
  263. ACE_HEADER * lpAceHeader;
  264. BOOL bRetVal = FALSE;
  265. BOOL bFreeSid = TRUE;
  266. //
  267. // Get the system sid
  268. //
  269. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  270. 0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
  271. DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to initialize system sid. Error = %d", GetLastError()));
  272. goto Exit;
  273. }
  274. //
  275. // Get the Admin sid
  276. //
  277. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  278. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  279. 0, 0, 0, 0, &psidAdmin)) {
  280. DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to initialize admin sid. Error = %d", GetLastError()));
  281. goto Exit;
  282. }
  283. //
  284. // Allocate space for the ACL
  285. //
  286. cbAcl = (2 * GetLengthSid (pSid)) + (2 * GetLengthSid (psidSystem)) +
  287. (2 * GetLengthSid (psidAdmin)) + sizeof(ACL) +
  288. (6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  289. pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  290. if (!pAcl) {
  291. goto Exit;
  292. }
  293. if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
  294. DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to initialize acl. Error = %d", GetLastError()));
  295. goto Exit;
  296. }
  297. //
  298. // Add Aces for User, System, and Admin. Non-inheritable ACEs first
  299. //
  300. aceIndex = 0;
  301. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, pSid)) {
  302. DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
  303. goto Exit;
  304. }
  305. aceIndex++;
  306. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidSystem)) {
  307. DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
  308. goto Exit;
  309. }
  310. aceIndex++;
  311. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidAdmin)) {
  312. DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
  313. goto Exit;
  314. }
  315. //
  316. // Now the inheritable ACEs
  317. //
  318. aceIndex++;
  319. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, pSid)) {
  320. DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
  321. goto Exit;
  322. }
  323. if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
  324. DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to get ace (%d). Error = %d", aceIndex, GetLastError()));
  325. goto Exit;
  326. }
  327. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  328. aceIndex++;
  329. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
  330. DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
  331. goto Exit;
  332. }
  333. if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
  334. DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to get ace (%d). Error = %d", aceIndex, GetLastError()));
  335. goto Exit;
  336. }
  337. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  338. aceIndex++;
  339. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
  340. DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
  341. goto Exit;
  342. }
  343. if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
  344. DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to get ace (%d). Error = %d", aceIndex, GetLastError()));
  345. goto Exit;
  346. }
  347. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  348. Exit:
  349. if (psidSystem) {
  350. FreeSid(psidSystem);
  351. }
  352. if (psidAdmin) {
  353. FreeSid(psidAdmin);
  354. }
  355. return pAcl;
  356. }
  357. VOID
  358. FreeDefaultAcl (
  359. PACL pAcl
  360. )
  361. {
  362. if (pAcl) {
  363. GlobalFree (pAcl);
  364. }
  365. }
  366. BOOL
  367. OurConvertSidToStringSid (
  368. IN PSID Sid,
  369. OUT PWSTR *SidString
  370. )
  371. {
  372. UNICODE_STRING UnicodeString;
  373. NTSTATUS NtStatus;
  374. //
  375. // Convert the sid into text format
  376. //
  377. NtStatus = RtlConvertSidToUnicodeString (&UnicodeString, Sid, TRUE);
  378. if (!NT_SUCCESS (NtStatus)) {
  379. DEBUGMSG ((
  380. DM_WARNING,
  381. "CreateUserProfile: RtlConvertSidToUnicodeString failed, status = 0x%x",
  382. NtStatus
  383. ));
  384. return FALSE;
  385. }
  386. *SidString = UnicodeString.Buffer;
  387. return TRUE;
  388. }
  389. VOID
  390. DeleteSidString (
  391. PWSTR SidString
  392. )
  393. {
  394. UNICODE_STRING String;
  395. if (!SidString) {
  396. return;
  397. }
  398. RtlInitUnicodeString (&String, SidString);
  399. RtlFreeUnicodeString (&String);
  400. }
  401. BOOL
  402. GetProfileRoot (
  403. IN PSID Sid,
  404. OUT PWSTR ProfileDir,
  405. IN UINT cchBuffer
  406. )
  407. {
  408. WCHAR LocalProfileKey[MAX_PATH];
  409. HKEY hKey;
  410. DWORD Size;
  411. DWORD Type;
  412. DWORD Attributes;
  413. DWORD cchExpandedRoot;
  414. PWSTR SidString = NULL;
  415. WCHAR ExpandedRoot[MAX_PATH];
  416. HRESULT hr;
  417. BOOL bResult = FALSE;
  418. if (cchBuffer) {
  419. ProfileDir[0] = 0;
  420. }
  421. if (!OurConvertSidToStringSid (Sid, &SidString)) {
  422. DEBUGMSG ((DM_WARNING, "GetProfileRoot: Can't convert SID to string"));
  423. goto Exit;
  424. }
  425. //
  426. // Check if this user's profile exists
  427. //
  428. hr = StringCchCopy(LocalProfileKey, ARRAYSIZE(LocalProfileKey), PROFILE_LIST_PATH);
  429. if (FAILED(hr))
  430. goto Exit;
  431. hr = StringCchCat(LocalProfileKey, ARRAYSIZE(LocalProfileKey), TEXT("\\"));
  432. if (FAILED(hr))
  433. goto Exit;
  434. hr = StringCchCat(LocalProfileKey, ARRAYSIZE(LocalProfileKey), SidString);
  435. if (FAILED(hr))
  436. goto Exit;
  437. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, LocalProfileKey,
  438. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  439. Size = cchBuffer * sizeof(WCHAR);
  440. RegQueryValueEx (hKey, PROFILE_IMAGE_VALUE_NAME, NULL,
  441. &Type, (LPBYTE) ProfileDir, &Size);
  442. RegCloseKey (hKey);
  443. }
  444. if (cchBuffer && ProfileDir[0]) {
  445. cchExpandedRoot = ExpandEnvironmentStrings (ProfileDir, ExpandedRoot, ARRAYSIZE(ExpandedRoot));
  446. if (!cchExpandedRoot || cchExpandedRoot > ARRAYSIZE(ExpandedRoot)) {
  447. ProfileDir[0] = 0;
  448. DEBUGMSG ((DM_VERBOSE, "GetProfileRoot: ExpandEnvironmentStrings failed."));
  449. goto Exit;
  450. }
  451. Attributes = GetFileAttributes (ExpandedRoot);
  452. if (Attributes == 0xFFFFFFFF || !(Attributes & FILE_ATTRIBUTE_DIRECTORY)) {
  453. ProfileDir[0] = 0;
  454. DEBUGMSG ((DM_VERBOSE, "GetProfileRoot: Profile %s is not vaild", SidString));
  455. } else {
  456. if (FAILED(StringCchCopy(ProfileDir, cchBuffer, ExpandedRoot))) {
  457. ProfileDir[0] = 0;
  458. DEBUGMSG ((DM_VERBOSE, "GetProfileRoot: Not enough buffer space"));
  459. }
  460. else {
  461. bResult = TRUE;
  462. }
  463. }
  464. } else {
  465. DEBUGMSG ((DM_VERBOSE, "GetProfileRoot: SID %s does not have a profile directory", SidString));
  466. }
  467. Exit:
  468. DeleteSidString (SidString);
  469. return bResult;
  470. }
  471. BOOL
  472. UpdateProfileSecurity (
  473. PSID Sid
  474. )
  475. {
  476. WCHAR ProfileDir[MAX_PATH];
  477. WCHAR ExpProfileDir[MAX_PATH];
  478. WCHAR LocalProfileKey[MAX_PATH];
  479. PWSTR SidString = NULL;
  480. PWSTR End, Save;
  481. LONG rc;
  482. DWORD dwError = ERROR_SUCCESS;
  483. DWORD dwSize;
  484. DWORD dwType;
  485. DWORD cchExpProfileDir;
  486. HKEY hKey;
  487. BOOL b = FALSE;
  488. BOOL UnloadProfile = FALSE;
  489. HRESULT hr;
  490. UINT cchRemaining;
  491. __try {
  492. //
  493. // Convert the sid into text format
  494. //
  495. if (!OurConvertSidToStringSid (Sid, &SidString)) {
  496. dwError = GetLastError();
  497. DEBUGMSG ((DM_WARNING, "UpdateProfileSecurity: Can't convert SID to string"));
  498. __leave;
  499. }
  500. //
  501. // Check if this user's profile exists already
  502. //
  503. hr = StringCchCopy(LocalProfileKey, ARRAYSIZE(LocalProfileKey), PROFILE_LIST_PATH);
  504. if (FAILED(hr)) {
  505. dwError = HRESULT_CODE(hr);
  506. __leave;
  507. }
  508. hr = StringCchCat(LocalProfileKey, ARRAYSIZE(LocalProfileKey), TEXT("\\"));
  509. if (FAILED(hr)){
  510. dwError = HRESULT_CODE(hr);
  511. __leave;
  512. }
  513. hr = StringCchCat(LocalProfileKey, ARRAYSIZE(LocalProfileKey), SidString);
  514. if (FAILED(hr)) {
  515. dwError = HRESULT_CODE(hr);
  516. __leave;
  517. }
  518. ProfileDir[0] = 0;
  519. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, LocalProfileKey,
  520. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  521. dwSize = sizeof(ProfileDir);
  522. RegQueryValueEx (hKey, PROFILE_IMAGE_VALUE_NAME, NULL,
  523. &dwType, (LPBYTE) ProfileDir, &dwSize);
  524. RegCloseKey (hKey);
  525. }
  526. if (!ProfileDir[0]) {
  527. DEBUGMSG ((DM_WARNING, "UpdateProfileSecurity: No profile for specified user"));
  528. dwError = ERROR_BAD_PROFILE;
  529. __leave;
  530. }
  531. if (!SetMachineProfileKeySecurity(Sid, LocalProfileKey)) {
  532. DEBUGMSG ((DM_WARNING, "UpdateProfileSecurity: Fail to set security for ProfileList entry. Error %d", GetLastError()));
  533. }
  534. //
  535. // The user has a profile, so update the security settings
  536. //
  537. cchExpProfileDir = ExpandEnvironmentStrings (ProfileDir, ExpProfileDir, ARRAYSIZE(ExpProfileDir));
  538. if (!cchExpProfileDir || cchExpProfileDir > ARRAYSIZE(ExpProfileDir)) {
  539. dwError = cchExpProfileDir ? ERROR_BUFFER_OVERFLOW : GetLastError();
  540. DEBUGMSG ((DM_WARNING, "UpdateProfileSecurity: ExpandEnvironmentStrings failed. Error %d", dwError));
  541. __leave;
  542. }
  543. //
  544. // Load the hive temporary so the security can be fixed
  545. //
  546. End = CheckSlash (ExpProfileDir, ARRAYSIZE(ExpProfileDir), &cchRemaining);
  547. if (!End) {
  548. dwError = ERROR_BUFFER_OVERFLOW;
  549. __leave;
  550. }
  551. Save = End - 1;
  552. hr = StringCchCopy(End, cchRemaining, L"NTUSER.DAT");
  553. if (FAILED(hr)) {
  554. dwError = HRESULT_CODE(hr);
  555. __leave;
  556. }
  557. rc = MyRegLoadKey (HKEY_USERS, SidString, ExpProfileDir);
  558. *Save = 0;
  559. if (rc != ERROR_SUCCESS) {
  560. DEBUGMSG((DM_WARNING, "UpdateProfileSecurity: Failed to load hive, error = %d.", rc));
  561. dwError = rc;
  562. __leave;
  563. }
  564. UnloadProfile = TRUE;
  565. if (!SetupNewHive (SidString, Sid)) {
  566. dwError = GetLastError();
  567. DEBUGMSG((DM_WARNING, "UpdateProfileSecurity: SetupNewHive failed, error = %d.", GetLastError()));
  568. __leave;
  569. }
  570. //
  571. // Fix the file system security
  572. //
  573. dwError = SecureProfileDirectory (ExpProfileDir, Sid);
  574. if (dwError != ERROR_SUCCESS) {
  575. DEBUGMSG((DM_WARNING, "UpdateProfileSecurity: SecureProfileDirectory failed, error = %d.", GetLastError()));
  576. __leave;
  577. }
  578. b = TRUE;
  579. }
  580. __finally {
  581. if (UnloadProfile) {
  582. MyRegUnLoadKey (HKEY_USERS, SidString);
  583. }
  584. DeleteSidString (SidString);
  585. SetLastError (dwError);
  586. }
  587. return b;
  588. }
  589. //*************************************************************
  590. //
  591. // DeleteProfileGuidSettings()
  592. //
  593. // Purpose: Deletes the GUID value and associated GUID entry
  594. // from ProfileGuid key
  595. //
  596. // Parameters: hProfile - Profile List sid entry key
  597. //
  598. // Return: TRUE if successful
  599. // FALSE if an error occurs
  600. //
  601. // Comments:
  602. //
  603. // History: Date Author Comment
  604. // 02/13/2002 Santanuc Created
  605. //
  606. //*************************************************************
  607. BOOL DeleteProfileGuidSettings (HKEY hProfile)
  608. {
  609. LONG lResult;
  610. TCHAR szTemp[MAX_PATH];
  611. TCHAR szUserGuid[MAX_PATH];
  612. HKEY hKey;
  613. DWORD dwType, dwSize;
  614. HRESULT hr;
  615. //
  616. // Query for the user guid
  617. //
  618. dwSize = MAX_PATH * sizeof(TCHAR);
  619. lResult = RegQueryValueEx (hProfile, PROFILE_GUID, NULL, &dwType, (LPBYTE) szUserGuid, &dwSize);
  620. if (lResult == ERROR_SUCCESS) {
  621. //
  622. // Delete the profile GUID value
  623. //
  624. RegDeleteValue (hProfile, PROFILE_GUID);
  625. hr = StringCchCopy(szTemp, ARRAYSIZE(szTemp), PROFILE_GUID_PATH);
  626. if (FAILED(hr))
  627. return FALSE;
  628. hr = StringCchCat(szTemp, ARRAYSIZE(szTemp), TEXT("\\"));
  629. if (FAILED(hr))
  630. return FALSE;
  631. hr = StringCchCat(szTemp, ARRAYSIZE(szTemp), szUserGuid);
  632. if (FAILED(hr))
  633. return FALSE;
  634. //
  635. // Delete the profile guid from the guid list
  636. //
  637. lResult = RegDeleteKey(HKEY_LOCAL_MACHINE, szTemp);
  638. if (lResult != ERROR_SUCCESS) {
  639. DEBUGMSG((DM_WARNING, "DeleteProfile: failed to delete profile guid. Error = %d", lResult));
  640. }
  641. }
  642. else if (lResult == ERROR_FILE_NOT_FOUND) {
  643. lResult = ERROR_SUCCESS;
  644. }
  645. return (lResult == ERROR_SUCCESS) ? TRUE : FALSE;
  646. }
  647. /***************************************************************************\
  648. * GetUserSid
  649. *
  650. * Allocs space for the user sid, fills it in and returns a pointer. Caller
  651. * The sid should be freed by calling DeleteUserSid.
  652. *
  653. * Note the sid returned is the user's real sid, not the per-logon sid.
  654. *
  655. * Returns pointer to sid or NULL on failure.
  656. *
  657. * History:
  658. * 26-Aug-92 Davidc Created.
  659. \***************************************************************************/
  660. PSID GetUserSid (HANDLE UserToken)
  661. {
  662. PTOKEN_USER pUser, pTemp;
  663. PSID pSid;
  664. DWORD BytesRequired = 200;
  665. NTSTATUS status;
  666. //
  667. // Allocate space for the user info
  668. //
  669. pUser = (PTOKEN_USER)LocalAlloc(LMEM_FIXED, BytesRequired);
  670. if (pUser == NULL) {
  671. DEBUGMSG((DM_WARNING, "GetUserSid: Failed to allocate %d bytes",
  672. BytesRequired));
  673. return NULL;
  674. }
  675. //
  676. // Read in the UserInfo
  677. //
  678. status = NtQueryInformationToken(
  679. UserToken, // Handle
  680. TokenUser, // TokenInformationClass
  681. pUser, // TokenInformation
  682. BytesRequired, // TokenInformationLength
  683. &BytesRequired // ReturnLength
  684. );
  685. if (status == STATUS_BUFFER_TOO_SMALL) {
  686. //
  687. // Allocate a bigger buffer and try again.
  688. //
  689. pTemp = LocalReAlloc(pUser, BytesRequired, LMEM_MOVEABLE);
  690. if (pTemp == NULL) {
  691. DEBUGMSG((DM_WARNING, "GetUserSid: Failed to allocate %d bytes",
  692. BytesRequired));
  693. LocalFree (pUser);
  694. return NULL;
  695. }
  696. pUser = pTemp;
  697. status = NtQueryInformationToken(
  698. UserToken, // Handle
  699. TokenUser, // TokenInformationClass
  700. pUser, // TokenInformation
  701. BytesRequired, // TokenInformationLength
  702. &BytesRequired // ReturnLength
  703. );
  704. }
  705. if (!NT_SUCCESS(status)) {
  706. DEBUGMSG((DM_WARNING, "GetUserSid: Failed to query user info from user token, status = 0x%x",
  707. status));
  708. LocalFree(pUser);
  709. return NULL;
  710. }
  711. BytesRequired = RtlLengthSid(pUser->User.Sid);
  712. pSid = LocalAlloc(LMEM_FIXED, BytesRequired);
  713. if (pSid == NULL) {
  714. DEBUGMSG((DM_WARNING, "GetUserSid: Failed to allocate %d bytes",
  715. BytesRequired));
  716. LocalFree(pUser);
  717. return NULL;
  718. }
  719. status = RtlCopySid(BytesRequired, pSid, pUser->User.Sid);
  720. LocalFree(pUser);
  721. if (!NT_SUCCESS(status)) {
  722. DEBUGMSG((DM_WARNING, "GetUserSid: RtlCopySid Failed. status = %d",
  723. status));
  724. LocalFree(pSid);
  725. pSid = NULL;
  726. }
  727. return pSid;
  728. }
  729. /***************************************************************************\
  730. * DeleteUserSid
  731. *
  732. * Deletes a user sid previously returned by GetUserSid()
  733. *
  734. * Returns nothing.
  735. *
  736. * History:
  737. * 26-Aug-92 Davidc Created
  738. *
  739. \***************************************************************************/
  740. VOID DeleteUserSid(PSID Sid)
  741. {
  742. LocalFree(Sid);
  743. }
  744. //*************************************************************
  745. //
  746. // MyRegLoadKey()
  747. //
  748. // Purpose: Loads a hive into the registry
  749. //
  750. // Parameters: hKey - Key to load the hive into
  751. // lpSubKey - Subkey name
  752. // lpFile - hive filename
  753. //
  754. // Return: ERROR_SUCCESS if successful
  755. // Error number if an error occurs
  756. //
  757. // Comments:
  758. //
  759. // History: Date Author Comment
  760. // 6/22/95 ericflo Created
  761. //
  762. //*************************************************************
  763. LONG MyRegLoadKey(HKEY hKey, LPTSTR lpSubKey, LPTSTR lpFile)
  764. {
  765. NTSTATUS Status;
  766. BOOLEAN WasEnabled;
  767. HANDLE hToken;
  768. BOOLEAN bClient = FALSE;
  769. int error;
  770. WCHAR szException[20];
  771. __try {
  772. if (OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken)) {
  773. CloseHandle(hToken);
  774. bClient = TRUE; // Enable privilege on thread token
  775. }
  776. //
  777. // Enable the restore privilege
  778. //
  779. Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, bClient, &WasEnabled);
  780. if (NT_SUCCESS(Status)) {
  781. error = RegLoadKey(hKey, lpSubKey, lpFile);
  782. //
  783. // Restore the privilege to its previous state
  784. //
  785. Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, bClient, &WasEnabled);
  786. if (!NT_SUCCESS(Status)) {
  787. DEBUGMSG((DM_WARNING, "MyRegLoadKey: Failed to restore RESTORE privilege to previous enabled state"));
  788. }
  789. //
  790. // Convert a sharing violation error to success since the hive
  791. // is already loaded
  792. //
  793. if (error == ERROR_SHARING_VIOLATION) {
  794. error = ERROR_SUCCESS;
  795. }
  796. //
  797. // Check if the hive was loaded
  798. //
  799. if (error != ERROR_SUCCESS) {
  800. DEBUGMSG((DM_WARNING, "MyRegLoadKey: Failed to load subkey <%s>, error =%d", lpSubKey, error));
  801. }
  802. } else {
  803. error = ERROR_ACCESS_DENIED;
  804. DEBUGMSG((DM_WARNING, "MyRegLoadKey: Failed to enable restore privilege to load registry key, error %u", error));
  805. }
  806. } __except(EXCEPTION_EXECUTE_HANDLER) {
  807. error = GetExceptionCode();
  808. if (SUCCEEDED(StringCchPrintf(szException, ARRAYSIZE(szException), L"!!!! 0x%x ", error))) {
  809. OutputDebugString(szException);
  810. OutputDebugString(L"Exception hit in MyRegLoadKey in userenv\n");
  811. }
  812. ASSERT(error == 0);
  813. }
  814. DEBUGMSG((DM_VERBOSE, "MyRegLoadKey: Returning %d.", error));
  815. return error;
  816. }
  817. //*************************************************************
  818. //
  819. // MyRegUnLoadKey()
  820. //
  821. // Purpose: Unloads a registry key
  822. //
  823. // Parameters: hKey - Registry handle
  824. // lpSubKey - Subkey to be unloaded
  825. //
  826. //
  827. // Return: TRUE if successful
  828. // FALSE if an error occurs
  829. //
  830. // Comments:
  831. //
  832. // History: Date Author Comment
  833. // 6/19/95 ericflo Ported
  834. //
  835. //*************************************************************
  836. BOOL MyRegUnLoadKey(HKEY hKey, LPTSTR lpSubKey)
  837. {
  838. BOOL bResult = TRUE;
  839. LONG error;
  840. NTSTATUS Status;
  841. BOOLEAN WasEnabled;
  842. HANDLE hToken;
  843. BOOLEAN bClient = FALSE;
  844. DWORD dwException;
  845. WCHAR szException[20];
  846. __try {
  847. if (OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken)) {
  848. CloseHandle(hToken);
  849. bClient = TRUE; // Enable privilege on thread token
  850. }
  851. //
  852. // Enable the restore privilege
  853. //
  854. Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, bClient, &WasEnabled);
  855. if (NT_SUCCESS(Status)) {
  856. error = RegUnLoadKey(hKey, lpSubKey);
  857. if ( error != ERROR_SUCCESS) {
  858. DEBUGMSG((DM_WARNING, "MyRegUnLoadKey: Failed to unmount hive %x", error));
  859. SetLastError(error);
  860. bResult = FALSE;
  861. }
  862. //
  863. // Restore the privilege to its previous state
  864. //
  865. Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, bClient, &WasEnabled);
  866. if (!NT_SUCCESS(Status)) {
  867. DEBUGMSG((DM_WARNING, "MyRegUnLoadKey: Failed to restore RESTORE privilege to previous enabled state"));
  868. }
  869. } else {
  870. DEBUGMSG((DM_WARNING, "MyRegUnloadKey: Failed to enable restore privilege to unload registry key"));
  871. Status = ERROR_ACCESS_DENIED;
  872. SetLastError(Status);
  873. bResult = FALSE;
  874. }
  875. } __except(EXCEPTION_EXECUTE_HANDLER) {
  876. bResult = FALSE;
  877. dwException = GetExceptionCode();
  878. if (SUCCEEDED(StringCchPrintf(szException, ARRAYSIZE(szException), L"!!!! 0x%x ", dwException))) {
  879. OutputDebugString(szException);
  880. OutputDebugString(L"Exception hit in MyRegUnLoadKey in userenv\n");
  881. }
  882. ASSERT(dwException == 0);
  883. }
  884. DEBUGMSG((DM_VERBOSE, "MyRegUnloadKey: Returning %d, error %u.", bResult, GetLastError()));
  885. return bResult;
  886. }
  887. //*************************************************************
  888. //
  889. // SetDefaultUserHiveSecurity()
  890. //
  891. // Purpose: Initializes a user hive with the
  892. // appropriate acls
  893. //
  894. // Parameters: pSid - Sid (used by CreateNewUser)
  895. // RootKey - registry handle to hive root
  896. //
  897. // Return: ERROR_SUCCESS if successful
  898. // other error code if an error occurs
  899. //
  900. // Comments:
  901. //
  902. // History: Date Author Comment
  903. // 7/18/95 ericflo Created as part of
  904. // SetupNewHive
  905. // 3/29/98 adamed Moved out of SetupNewHive
  906. // to this function
  907. //
  908. //*************************************************************
  909. BOOL SetDefaultUserHiveSecurity(PSID pSid, HKEY RootKey)
  910. {
  911. DWORD Error;
  912. SECURITY_DESCRIPTOR sd;
  913. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  914. PACL pAcl = NULL;
  915. PSID psidUser = NULL, psidSystem = NULL, psidAdmin = NULL, psidRestricted = NULL;
  916. DWORD cbAcl, AceIndex;
  917. ACE_HEADER * lpAceHeader;
  918. BOOL bRetVal = FALSE;
  919. BOOL bFreeSid = TRUE;
  920. //
  921. // Verbose Output
  922. //
  923. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Entering"));
  924. //
  925. // Create the security descriptor that will be applied to each key
  926. //
  927. //
  928. // Give the user access by their real sid so they still have access
  929. // when they logoff and logon again
  930. //
  931. psidUser = pSid;
  932. bFreeSid = FALSE;
  933. if (!psidUser) {
  934. DEBUGMSG((DM_WARNING, "SetDefaultUserHiveSecurity: Failed to get user sid"));
  935. return FALSE;
  936. }
  937. //
  938. // Get the system sid
  939. //
  940. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  941. 0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
  942. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to initialize system sid. Error = %d",
  943. GetLastError()));
  944. goto Exit;
  945. }
  946. //
  947. // Get the admin sid
  948. //
  949. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  950. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  951. 0, 0, 0, 0, &psidAdmin)) {
  952. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to initialize admin sid. Error = %d",
  953. GetLastError()));
  954. goto Exit;
  955. }
  956. //
  957. // Get the Restricted sid
  958. //
  959. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_RESTRICTED_CODE_RID,
  960. 0, 0, 0, 0, 0, 0, 0, &psidRestricted)) {
  961. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to initialize restricted sid. Error = %d",
  962. GetLastError()));
  963. goto Exit;
  964. }
  965. //
  966. // Allocate space for the ACL
  967. //
  968. cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) +
  969. (2 * GetLengthSid (psidAdmin)) + (2*GetLengthSid(psidRestricted)) +
  970. sizeof(ACL) +
  971. (8 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  972. pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  973. if (!pAcl) {
  974. goto Exit;
  975. }
  976. if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
  977. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to initialize acl. Error = %d", GetLastError()));
  978. goto Exit;
  979. }
  980. //
  981. // Add Aces for User, System, and Admin. Non-inheritable ACEs first
  982. //
  983. AceIndex = 0;
  984. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidUser)) {
  985. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for user. Error = %d", GetLastError()));
  986. goto Exit;
  987. }
  988. AceIndex++;
  989. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) {
  990. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for system. Error = %d", GetLastError()));
  991. goto Exit;
  992. }
  993. AceIndex++;
  994. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) {
  995. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for admin. Error = %d", GetLastError()));
  996. goto Exit;
  997. }
  998. AceIndex++;
  999. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_READ, psidRestricted)) {
  1000. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for Restricted. Error = %d", GetLastError()));
  1001. goto Exit;
  1002. }
  1003. //
  1004. // Now the inheritable ACEs
  1005. //
  1006. AceIndex++;
  1007. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidUser)) {
  1008. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for user. Error = %d", GetLastError()));
  1009. goto Exit;
  1010. }
  1011. if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
  1012. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
  1013. goto Exit;
  1014. }
  1015. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  1016. AceIndex++;
  1017. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
  1018. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for system. Error = %d", GetLastError()));
  1019. goto Exit;
  1020. }
  1021. if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
  1022. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
  1023. goto Exit;
  1024. }
  1025. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  1026. AceIndex++;
  1027. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
  1028. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for admin. Error = %d", GetLastError()));
  1029. goto Exit;
  1030. }
  1031. if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
  1032. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
  1033. goto Exit;
  1034. }
  1035. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  1036. AceIndex++;
  1037. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ, psidRestricted)) {
  1038. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for restricted. Error = %d", GetLastError()));
  1039. goto Exit;
  1040. }
  1041. if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
  1042. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
  1043. goto Exit;
  1044. }
  1045. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  1046. //
  1047. // Put together the security descriptor
  1048. //
  1049. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
  1050. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to initialize security descriptor. Error = %d", GetLastError()));
  1051. goto Exit;
  1052. }
  1053. if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
  1054. DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to set security descriptor dacl. Error = %d", GetLastError()));
  1055. goto Exit;
  1056. }
  1057. //
  1058. // Set the security descriptor on the entire tree
  1059. //
  1060. Error = ApplySecurityToRegistryTree(RootKey, &sd);
  1061. if (ERROR_SUCCESS == Error) {
  1062. bRetVal = TRUE;
  1063. }
  1064. else
  1065. SetLastError(Error);
  1066. Exit:
  1067. //
  1068. // Free the sids and acl
  1069. //
  1070. if (bFreeSid && psidUser) {
  1071. DeleteUserSid (psidUser);
  1072. }
  1073. if (psidSystem) {
  1074. FreeSid(psidSystem);
  1075. }
  1076. if (psidAdmin) {
  1077. FreeSid(psidAdmin);
  1078. }
  1079. if (pAcl) {
  1080. GlobalFree (pAcl);
  1081. }
  1082. return bRetVal;
  1083. }
  1084. //*************************************************************
  1085. //
  1086. // SetupNewHive()
  1087. //
  1088. // Purpose: Initializes the new user hive created by copying
  1089. // the default hive.
  1090. //
  1091. // Parameters: lpSidString - Sid string
  1092. // pSid - Sid (used by CreateNewUser)
  1093. //
  1094. // Return: TRUE if successful
  1095. // FALSE if an error occurs
  1096. //
  1097. // Comments:
  1098. //
  1099. // History: Date Author Comment
  1100. // 7/18/95 ericflo Created
  1101. //
  1102. //*************************************************************
  1103. BOOL SetupNewHive(LPTSTR lpSidString, PSID pSid)
  1104. {
  1105. DWORD Error, IgnoreError;
  1106. HKEY RootKey;
  1107. BOOL bRetVal = FALSE;
  1108. HRESULT hr;
  1109. UINT cchRemaining;
  1110. //
  1111. // Verbose Output
  1112. //
  1113. DEBUGMSG((DM_VERBOSE, "SetupNewHive: Entering"));
  1114. //
  1115. // Open the root of the user's profile
  1116. //
  1117. Error = RegOpenKeyEx(HKEY_USERS,
  1118. lpSidString,
  1119. 0,
  1120. KEY_READ | WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
  1121. &RootKey);
  1122. if (Error != ERROR_SUCCESS) {
  1123. DEBUGMSG((DM_WARNING, "SetupNewHive: Failed to open root of user registry, error = %d", Error));
  1124. } else {
  1125. //
  1126. // First Secure the entire hive -- use security that
  1127. // will be sufficient for most of the hive.
  1128. // After this, we can add special settings to special
  1129. // sections of this hive.
  1130. //
  1131. if (SetDefaultUserHiveSecurity(pSid, RootKey)) {
  1132. TCHAR szSubKey[MAX_PATH];
  1133. LPTSTR lpEnd;
  1134. //
  1135. // Change the security on certain keys in the user's registry
  1136. // so that only Admin's and the OS have write access.
  1137. //
  1138. hr = StringCchCopy(szSubKey, ARRAYSIZE(szSubKey), lpSidString);
  1139. if (FAILED(hr)) {
  1140. SetLastError(HRESULT_CODE(hr));
  1141. return FALSE;
  1142. }
  1143. lpEnd = CheckSlash(szSubKey, ARRAYSIZE(szSubKey), &cchRemaining);
  1144. if (!lpEnd) {
  1145. SetLastError(ERROR_BUFFER_OVERFLOW);
  1146. return FALSE;
  1147. }
  1148. hr = StringCchCopy(lpEnd, cchRemaining, WINDOWS_POLICIES_KEY);
  1149. if (FAILED(hr)) {
  1150. SetLastError(HRESULT_CODE(hr));
  1151. return FALSE;
  1152. }
  1153. if (!SecureUserKey(szSubKey, pSid)) {
  1154. DEBUGMSG((DM_WARNING, "SetupNewHive: Failed to secure windows policies key"));
  1155. }
  1156. hr = StringCchCopy(lpEnd, cchRemaining, ROOT_POLICIES_KEY);
  1157. if (FAILED(hr)) {
  1158. SetLastError(HRESULT_CODE(hr));
  1159. return FALSE;
  1160. }
  1161. if (!SecureUserKey(szSubKey, pSid)) {
  1162. DEBUGMSG((DM_WARNING, "SetupNewHive: Failed to secure root policies key"));
  1163. }
  1164. bRetVal = TRUE;
  1165. } else {
  1166. Error = GetLastError();
  1167. DEBUGMSG((DM_WARNING, "SetupNewHive: Failed to apply security to user registry tree, error = %d", Error));
  1168. }
  1169. RegFlushKey (RootKey);
  1170. IgnoreError = RegCloseKey(RootKey);
  1171. if (IgnoreError != ERROR_SUCCESS) {
  1172. DEBUGMSG((DM_WARNING, "SetupNewHive: Failed to close reg key, error = %d", IgnoreError));
  1173. }
  1174. }
  1175. //
  1176. // Verbose Output
  1177. //
  1178. DEBUGMSG((DM_VERBOSE, "SetupNewHive: Leaving with a return value of %d, error %u", bRetVal, Error));
  1179. if (!bRetVal)
  1180. SetLastError(Error);
  1181. return(bRetVal);
  1182. }
  1183. //*************************************************************
  1184. //
  1185. // ApplySecurityToRegistryTree()
  1186. //
  1187. // Purpose: Applies the passed security descriptor to the passed
  1188. // key and all its descendants. Only the parts of
  1189. // the descriptor inddicated in the security
  1190. // info value are actually applied to each registry key.
  1191. //
  1192. // Parameters: RootKey - Registry key
  1193. // pSD - Security Descriptor
  1194. //
  1195. // Return: ERROR_SUCCESS if successful
  1196. //
  1197. // Comments:
  1198. //
  1199. // History: Date Author Comment
  1200. // 7/19/95 ericflo Created
  1201. //
  1202. //*************************************************************
  1203. DWORD ApplySecurityToRegistryTree(HKEY RootKey, PSECURITY_DESCRIPTOR pSD)
  1204. {
  1205. DWORD Error = ERROR_SUCCESS;
  1206. DWORD SubKeyIndex;
  1207. LPTSTR SubKeyName;
  1208. HKEY SubKey;
  1209. DWORD cchMaxSubKeySize;
  1210. //
  1211. // First apply security
  1212. //
  1213. RegSetKeySecurity(RootKey, DACL_SECURITY_INFORMATION, pSD);
  1214. Error = RegQueryInfoKey(RootKey, NULL, NULL, NULL, NULL,
  1215. &cchMaxSubKeySize, NULL, NULL,
  1216. NULL, NULL, NULL, NULL);
  1217. if (Error != ERROR_SUCCESS) {
  1218. DEBUGMSG ((DM_WARNING, "ApplySecurityToRegistryTree: Failed to query reg key. error = %d", Error));
  1219. return Error;
  1220. }
  1221. cchMaxSubKeySize++; // Include the null terminator
  1222. //
  1223. // Open each sub-key and apply security to its sub-tree
  1224. //
  1225. SubKeyIndex = 0;
  1226. SubKeyName = GlobalAlloc (GPTR, cchMaxSubKeySize * sizeof(TCHAR));
  1227. if (!SubKeyName) {
  1228. DEBUGMSG ((DM_WARNING, "ApplySecurityToRegistryTree: Failed to allocate memory, error = %d", GetLastError()));
  1229. return GetLastError();
  1230. }
  1231. while (TRUE) {
  1232. //
  1233. // Get the next sub-key name
  1234. //
  1235. Error = RegEnumKey(RootKey, SubKeyIndex, SubKeyName, cchMaxSubKeySize);
  1236. if (Error != ERROR_SUCCESS) {
  1237. if (Error == ERROR_NO_MORE_ITEMS) {
  1238. //
  1239. // Successful end of enumeration
  1240. //
  1241. Error = ERROR_SUCCESS;
  1242. } else {
  1243. DEBUGMSG ((DM_WARNING, "ApplySecurityToRegistryTree: Registry enumeration failed with error = %d", Error));
  1244. }
  1245. break;
  1246. }
  1247. //
  1248. // Open the sub-key
  1249. //
  1250. Error = RegOpenKeyEx(RootKey,
  1251. SubKeyName,
  1252. 0,
  1253. KEY_READ | WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
  1254. &SubKey);
  1255. if (Error == ERROR_SUCCESS) {
  1256. //
  1257. // Apply security to the sub-tree
  1258. //
  1259. ApplySecurityToRegistryTree(SubKey, pSD);
  1260. //
  1261. // We're finished with the sub-key
  1262. //
  1263. RegCloseKey(SubKey);
  1264. }
  1265. //
  1266. // Go enumerate the next sub-key
  1267. //
  1268. SubKeyIndex ++;
  1269. }
  1270. GlobalFree (SubKeyName);
  1271. return Error;
  1272. }
  1273. //*************************************************************
  1274. //
  1275. // SecureUserKey()
  1276. //
  1277. // Purpose: Sets security on a key in the user's hive
  1278. // so only admin's can change it.
  1279. //
  1280. // Parameters: lpKey - Key to secure
  1281. // pSid - Sid (used by CreateNewUser)
  1282. //
  1283. // Return: TRUE if successful
  1284. // FALSE if an error occurs
  1285. //
  1286. // Comments:
  1287. //
  1288. // History: Date Author Comment
  1289. // 6/20/95 ericflo Created
  1290. //
  1291. //*************************************************************
  1292. BOOL SecureUserKey(LPTSTR lpKey, PSID pSid)
  1293. {
  1294. DWORD Error;
  1295. HKEY RootKey;
  1296. SECURITY_DESCRIPTOR sd;
  1297. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  1298. PACL pAcl = NULL;
  1299. PSID psidUser = NULL, psidSystem = NULL, psidAdmin = NULL, psidRestricted = NULL;
  1300. DWORD cbAcl, AceIndex, dwDisp;
  1301. ACE_HEADER * lpAceHeader;
  1302. BOOL bRetVal = FALSE;
  1303. BOOL bFreeSid = TRUE;
  1304. //
  1305. // Verbose Output
  1306. //
  1307. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Entering"));
  1308. //
  1309. // Create the security descriptor
  1310. //
  1311. //
  1312. // Give the user access by their real sid so they still have access
  1313. // when they logoff and logon again
  1314. //
  1315. psidUser = pSid;
  1316. bFreeSid = FALSE;
  1317. if (!psidUser) {
  1318. DEBUGMSG ((DM_WARNING, "SecureUserKey: Failed to get user sid"));
  1319. return FALSE;
  1320. }
  1321. //
  1322. // Get the system sid
  1323. //
  1324. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  1325. 0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
  1326. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to initialize system sid. Error = %d", GetLastError()));
  1327. goto Exit;
  1328. }
  1329. //
  1330. // Get the admin sid
  1331. //
  1332. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  1333. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  1334. 0, 0, 0, 0, &psidAdmin)) {
  1335. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to initialize admin sid. Error = %d", GetLastError()));
  1336. goto Exit;
  1337. }
  1338. //
  1339. // Get the restricted sid
  1340. //
  1341. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_RESTRICTED_CODE_RID,
  1342. 0, 0, 0, 0, 0, 0, 0, &psidRestricted)) {
  1343. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to initialize restricted sid. Error = %d", GetLastError()));
  1344. goto Exit;
  1345. }
  1346. //
  1347. // Allocate space for the ACL
  1348. //
  1349. cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) +
  1350. (2 * GetLengthSid (psidAdmin)) + (2 * GetLengthSid (psidRestricted)) +
  1351. sizeof(ACL) +
  1352. (8 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  1353. pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  1354. if (!pAcl) {
  1355. goto Exit;
  1356. }
  1357. if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
  1358. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to initialize acl. Error = %d", GetLastError()));
  1359. goto Exit;
  1360. }
  1361. //
  1362. // Add Aces for User, System, and Admin. Non-inheritable ACEs first
  1363. //
  1364. AceIndex = 0;
  1365. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_READ, psidUser)) {
  1366. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for user. Error = %d", GetLastError()));
  1367. goto Exit;
  1368. }
  1369. AceIndex++;
  1370. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) {
  1371. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for system. Error = %d", GetLastError()));
  1372. goto Exit;
  1373. }
  1374. AceIndex++;
  1375. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) {
  1376. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for admin. Error = %d", GetLastError()));
  1377. goto Exit;
  1378. }
  1379. AceIndex++;
  1380. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_READ, psidRestricted)) {
  1381. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for restricted. Error = %d", GetLastError()));
  1382. goto Exit;
  1383. }
  1384. //
  1385. // Now the inheritable ACEs
  1386. //
  1387. AceIndex++;
  1388. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ, psidUser)) {
  1389. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for user. Error = %d", GetLastError()));
  1390. goto Exit;
  1391. }
  1392. if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
  1393. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
  1394. goto Exit;
  1395. }
  1396. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  1397. AceIndex++;
  1398. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
  1399. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for system. Error = %d", GetLastError()));
  1400. goto Exit;
  1401. }
  1402. if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
  1403. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
  1404. goto Exit;
  1405. }
  1406. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  1407. AceIndex++;
  1408. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
  1409. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for admin. Error = %d", GetLastError()));
  1410. goto Exit;
  1411. }
  1412. if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
  1413. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
  1414. goto Exit;
  1415. }
  1416. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  1417. AceIndex++;
  1418. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ, psidRestricted)) {
  1419. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for restricted. Error = %d", GetLastError()));
  1420. goto Exit;
  1421. }
  1422. if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
  1423. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
  1424. goto Exit;
  1425. }
  1426. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  1427. //
  1428. // Put together the security descriptor
  1429. //
  1430. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
  1431. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to initialize security descriptor. Error = %d", GetLastError()));
  1432. goto Exit;
  1433. }
  1434. if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
  1435. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to set security descriptor dacl. Error = %d", GetLastError()));
  1436. goto Exit;
  1437. }
  1438. //
  1439. // Open the root of the user's profile
  1440. //
  1441. Error = RegCreateKeyEx(HKEY_USERS,
  1442. lpKey,
  1443. 0,
  1444. NULL,
  1445. REG_OPTION_NON_VOLATILE,
  1446. WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
  1447. NULL,
  1448. &RootKey,
  1449. &dwDisp);
  1450. if (Error != ERROR_SUCCESS) {
  1451. DEBUGMSG ((DM_WARNING, "SecureUserKey: Failed to open root of user registry, error = %d", Error));
  1452. } else {
  1453. //
  1454. // Set the security descriptor on the key
  1455. //
  1456. Error = ApplySecurityToRegistryTree(RootKey, &sd);
  1457. if (Error == ERROR_SUCCESS) {
  1458. bRetVal = TRUE;
  1459. } else {
  1460. DEBUGMSG ((DM_WARNING, "SecureUserKey: Failed to apply security to registry key, error = %d", Error));
  1461. SetLastError(Error);
  1462. }
  1463. RegCloseKey(RootKey);
  1464. }
  1465. Exit:
  1466. //
  1467. // Free the sids and acl
  1468. //
  1469. if (bFreeSid && psidUser) {
  1470. DeleteUserSid (psidUser);
  1471. }
  1472. if (psidRestricted) {
  1473. FreeSid(psidRestricted);
  1474. }
  1475. if (psidSystem) {
  1476. FreeSid(psidSystem);
  1477. }
  1478. if (psidAdmin) {
  1479. FreeSid(psidAdmin);
  1480. }
  1481. if (pAcl) {
  1482. GlobalFree (pAcl);
  1483. }
  1484. //
  1485. // Verbose Output
  1486. //
  1487. DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Leaving with a return value of %d", bRetVal));
  1488. return(bRetVal);
  1489. }
  1490. //*************************************************************
  1491. //
  1492. // ProduceWFromA()
  1493. //
  1494. // Purpose: Creates a buffer for a Unicode string and copies
  1495. // the ANSI text into it (converting in the process)
  1496. //
  1497. // Parameters: pszA - ANSI string
  1498. //
  1499. //
  1500. // Return: Unicode pointer if successful
  1501. // NULL if an error occurs
  1502. //
  1503. // Comments: The caller needs to free this pointer.
  1504. //
  1505. //
  1506. // History: Date Author Comment
  1507. // 5/24/95 ericflo Ported
  1508. //
  1509. //*************************************************************
  1510. LPWSTR ProduceWFromA(LPCSTR pszA)
  1511. {
  1512. LPWSTR pszW;
  1513. int cch;
  1514. if (!pszA)
  1515. return (LPWSTR)pszA;
  1516. cch = MultiByteToWideChar(CP_ACP, 0, pszA, -1, NULL, 0);
  1517. if (cch == 0)
  1518. cch = 1;
  1519. pszW = LocalAlloc(LPTR, cch * sizeof(WCHAR));
  1520. if (pszW) {
  1521. if (!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszA, -1, pszW, cch)) {
  1522. LocalFree(pszW);
  1523. pszW = NULL;
  1524. }
  1525. }
  1526. return pszW;
  1527. }
  1528. //*************************************************************
  1529. //
  1530. // IsUserAnAdminMember()
  1531. //
  1532. // Purpose: Determines if the user is a member of the administrators group.
  1533. //
  1534. // Parameters: hToken - User's token
  1535. //
  1536. // Return: TRUE if user is a admin
  1537. // FALSE if not
  1538. // Comments:
  1539. //
  1540. // History: Date Author Comment
  1541. // 7/25/95 ericflo Created
  1542. //
  1543. //*************************************************************
  1544. BOOL IsUserAnAdminMember(HANDLE hToken)
  1545. {
  1546. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  1547. NTSTATUS Status;
  1548. BOOL FoundAdmins = FALSE;
  1549. PSID AdminsDomainSid=NULL;
  1550. HANDLE hImpToken = NULL;
  1551. //
  1552. // Create Admins domain sid.
  1553. //
  1554. Status = RtlAllocateAndInitializeSid(
  1555. &authNT,
  1556. 2,
  1557. SECURITY_BUILTIN_DOMAIN_RID,
  1558. DOMAIN_ALIAS_RID_ADMINS,
  1559. 0, 0, 0, 0, 0, 0,
  1560. &AdminsDomainSid
  1561. );
  1562. if (Status == STATUS_SUCCESS) {
  1563. //
  1564. // Test if user is in the Admins domain
  1565. //
  1566. if (!DuplicateTokenEx(hToken, TOKEN_IMPERSONATE | TOKEN_QUERY,
  1567. NULL, SecurityImpersonation, TokenImpersonation,
  1568. &hImpToken)) {
  1569. DEBUGMSG((DM_WARNING, "IsUserAnAdminMember: DuplicateTokenEx failed with error %d", GetLastError()));
  1570. FoundAdmins = FALSE;
  1571. hImpToken = NULL;
  1572. goto Exit;
  1573. }
  1574. if (!CheckTokenMembership(hImpToken, AdminsDomainSid, &FoundAdmins)) {
  1575. DEBUGMSG((DM_WARNING, "IsUserAnAdminmember: CheckTokenMembership failed for AdminsDomainSid with error %d", GetLastError()));
  1576. FoundAdmins = FALSE;
  1577. }
  1578. }
  1579. //
  1580. // Tidy up
  1581. //
  1582. Exit:
  1583. if (hImpToken)
  1584. CloseHandle(hImpToken);
  1585. if (AdminsDomainSid)
  1586. RtlFreeSid(AdminsDomainSid);
  1587. return(FoundAdmins);
  1588. }