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.

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