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.

1175 lines
41 KiB

  1. /*---------------------------------------------------------------------------
  2. File: RegTranslator.cpp
  3. Comments: Routines for translating security on the registry keys and files
  4. that form a user profile.
  5. (c) Copyright 1999, Mission Critical Software, Inc., All Rights Reserved
  6. Proprietary and confidential to Mission Critical Software, Inc.
  7. REVISION LOG ENTRY
  8. Revision By: Christy Boles
  9. Revised on 05/12/99 11:11:46
  10. ---------------------------------------------------------------------------
  11. */
  12. #include "stdafx.h"
  13. #include "stargs.hpp"
  14. #include "sd.hpp"
  15. #include "SecObj.hpp"
  16. #include "sidcache.hpp"
  17. #include "sdstat.hpp"
  18. #include "Common.hpp"
  19. #include "UString.hpp"
  20. #include "ErrDct.hpp"
  21. #include "TReg.hpp"
  22. #include "TxtSid.h"
  23. #include "RegTrans.h"
  24. #include <WinBase.h>
  25. //#import "\bin\McsDctWorkerObjects.tlb"
  26. #import "WorkObj.tlb"
  27. #include "CommaLog.hpp"
  28. #ifdef _DEBUG
  29. #define new DEBUG_NEW
  30. #undef THIS_FILE
  31. static char THIS_FILE[] = __FILE__;
  32. #endif
  33. extern TErrorDct err;
  34. #define LEN_SID 200
  35. #define REGKEY_ADD_LIMIT 15
  36. DWORD
  37. TranslateRegHive(
  38. HKEY hKeyRoot, // in - root of registry hive to translate
  39. const LPWSTR keyName, // in - name of registry key
  40. SecurityTranslatorArgs * stArgs, // in - translation settings
  41. TSDRidCache * cache, // in - translation table
  42. TSDResolveStats * stat, // in - stats on items modified
  43. BOOL bWin2K // in - flag, whether the machine is Win2K
  44. )
  45. {
  46. DWORD rc = 0;
  47. // Translate the permissions on the root key
  48. TRegSD sd(keyName,hKeyRoot);
  49. if ( sd.HasDacl() )
  50. {
  51. TSD * pSD = sd.GetSecurity();
  52. // if there are more than 15 aces in a registry entry, and we are re-ACLing in Add Mode,
  53. // skip the entry. There seems to be a problem in Windows 2000 RC2 where if there are more than
  54. // 30 or so ACEs, some of them never get resolved. If this happens to the Administrator account,
  55. // (This may only happen if there are 30 or so ACEs alphabetically ahead of the Administrator account)
  56. // The Administrator account never gets resolved, and the machine is effectively trashed.
  57. if ( bWin2K && ( stArgs->TranslationMode() == ADD_SECURITY ) && (pSD->GetNumDaclAces() >= REGKEY_ADD_LIMIT) )
  58. {
  59. err.MsgWrite(0,DCT_MSG_SKIPPING_REGKEY_TRANSLATION_SDD,keyName,pSD->GetNumDaclAces(),REGKEY_ADD_LIMIT);
  60. }
  61. else
  62. {
  63. sd.ResolveSD(stArgs,stat,regkey ,NULL);
  64. }
  65. }
  66. // Recursively process any subkeys
  67. int n = 0;
  68. FILETIME writeTime;
  69. WCHAR name[MAX_PATH];
  70. DWORD lenName = DIM(name);
  71. WCHAR fullName[2000];
  72. HKEY hKey;
  73. do
  74. {
  75. lenName = DIM(name);
  76. rc = RegEnumKeyEx(hKeyRoot,n,name,&lenName,NULL,NULL,NULL,&writeTime);
  77. if ( rc && rc != ERROR_MORE_DATA )
  78. break;
  79. swprintf(fullName,L"%s\\%s",keyName,name);
  80. // Open the subkey
  81. rc = RegCreateKeyEx(hKeyRoot,name,0,L"",REG_OPTION_BACKUP_RESTORE,KEY_ALL_ACCESS | READ_CONTROL | ACCESS_SYSTEM_SECURITY,NULL,&hKey,NULL);
  82. if (! rc )
  83. {
  84. // Process the subkey
  85. TranslateRegHive(hKey,fullName,stArgs,cache,stat,bWin2K);
  86. RegCloseKey(hKey);
  87. }
  88. else
  89. {
  90. if ( (rc != ERROR_FILE_NOT_FOUND) && (rc != ERROR_INVALID_HANDLE) )
  91. {
  92. err.SysMsgWrite(ErrS,rc,DCT_MSG_REG_KEY_OPEN_FAILED_SD,fullName,rc);
  93. }
  94. }
  95. n++;
  96. } while ( rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA);
  97. if ( rc != ERROR_NO_MORE_ITEMS && rc != ERROR_FILE_NOT_FOUND && rc != ERROR_INVALID_HANDLE )
  98. {
  99. err.SysMsgWrite(ErrS,rc,DCT_MSG_REGKEYENUM_FAILED_D,rc);
  100. }
  101. return rc;
  102. }
  103. DWORD
  104. TranslateRegistry(
  105. WCHAR const * computer, // in - computername to translate, or NULL
  106. SecurityTranslatorArgs * stArgs, // in - translation settings
  107. TSDRidCache * cache, // in - translation account mapping
  108. TSDResolveStats * stat // in - stats for items examined and modified
  109. )
  110. {
  111. DWORD rc = 0;
  112. WCHAR comp[LEN_Computer];
  113. if ( ! computer )
  114. {
  115. comp[0] = 0;
  116. }
  117. else
  118. {
  119. safecopy(comp,computer);
  120. }
  121. MCSDCTWORKEROBJECTSLib::IAccessCheckerPtr pAccess(__uuidof(MCSDCTWORKEROBJECTSLib::AccessChecker));
  122. TRegKey hKey;
  123. DWORD verMaj,verMin,verSP;
  124. BOOL bWin2K = TRUE; // assume win2k unless we're sure it's not
  125. // get the OS version - we need to know the OS version because Win2K can fail when registry keys
  126. // have many entries
  127. HRESULT hr = pAccess->raw_GetOsVersion(SysAllocString(comp),&verMaj,&verMin,&verSP);
  128. if ( SUCCEEDED(hr) )
  129. {
  130. if ( verMaj < 5 )
  131. bWin2K = FALSE;
  132. }
  133. err.MsgWrite(0,DCT_MSG_TRANSLATING_REGISTRY);
  134. rc = hKey.Connect(HKEY_CLASSES_ROOT,computer);
  135. if ( ! rc )
  136. {
  137. rc = TranslateRegHive(hKey.KeyGet(),L"HKEY_CLASSES_ROOT",stArgs,cache,stat,bWin2K);
  138. hKey.Close();
  139. }
  140. rc = hKey.Connect(HKEY_LOCAL_MACHINE,computer);
  141. if ( ! rc )
  142. {
  143. rc = TranslateRegHive(hKey.KeyGet(),L"HKEY_LOCAL_MACHINE",stArgs,cache,stat,bWin2K);
  144. hKey.Close();
  145. }
  146. rc = hKey.Connect(HKEY_USERS,computer);
  147. if (! rc )
  148. {
  149. rc = TranslateRegHive(hKey.KeyGet(),L"HKEY_USERS",stArgs,cache,stat,bWin2K);
  150. hKey.Close();
  151. }
  152. rc = hKey.Connect(HKEY_PERFORMANCE_DATA,computer);
  153. if ( ! rc )
  154. {
  155. rc = TranslateRegHive(hKey.KeyGet(),L"HKEY_PERFORMANCE_DATA",stArgs,cache,stat,bWin2K);
  156. hKey.Close();
  157. }
  158. rc = hKey.Connect(HKEY_CURRENT_CONFIG,computer);
  159. if ( ! rc )
  160. {
  161. rc = TranslateRegHive(hKey.KeyGet(),L"HKEY_CURRENT_CONFIG",stArgs,cache,stat,bWin2K);
  162. hKey.Close();
  163. }
  164. rc = hKey.Connect(HKEY_DYN_DATA,computer);
  165. if ( ! rc )
  166. {
  167. rc = TranslateRegHive(hKey.KeyGet(),L"HKEY_DYN_DATA",stArgs,cache,stat,bWin2K);
  168. hKey.Close();
  169. }
  170. return rc;
  171. }
  172. DWORD
  173. TranslateUserProfile(
  174. WCHAR const * profileName, // in - name of file containing user profile
  175. SecurityTranslatorArgs * stArgs, // in - translation settings
  176. TSDRidCache * cache, // in - translation table
  177. TSDResolveStats * stat, // in - stats on items modified
  178. WCHAR * sSourceName, // in - Source account name
  179. WCHAR * sSourceDomainName // in - Source domain name
  180. )
  181. {
  182. DWORD rc = 0;
  183. WCHAR oldName[MAX_PATH];
  184. WCHAR newName[MAX_PATH];
  185. WCHAR otherName[MAX_PATH];
  186. HKEY hKey;
  187. HRESULT hr = S_OK;
  188. BOOL bWin2K = TRUE;
  189. MCSDCTWORKEROBJECTSLib::IAccessCheckerPtr pAccess(__uuidof(MCSDCTWORKEROBJECTSLib::AccessChecker));
  190. safecopy(oldName,profileName);
  191. safecopy(newName,profileName);
  192. UStrCpy(newName+UStrLen(newName),".temp");
  193. safecopy(otherName,profileName);
  194. UStrCpy(otherName + UStrLen(otherName),".premigration");
  195. // check the OS version of the computer
  196. // if UNC name is specified, get the computer name
  197. if ( profileName[0] == L'\\' && profileName[1] == L'\\' )
  198. {
  199. bWin2K = TRUE; // if the profile is specified in UNC format (roaming profile) it can be used
  200. // from multiple machines. There is no guarantee that the profile will not be loaded on a win2000 machine
  201. }
  202. else
  203. {
  204. DWORD verMaj;
  205. DWORD verMin;
  206. DWORD verSP;
  207. HRESULT hr = pAccess->raw_GetOsVersion(SysAllocString(L""),&verMaj,&verMin,&verSP);
  208. if ( SUCCEEDED(hr) )
  209. {
  210. if ( verMaj < 5 )
  211. {
  212. bWin2K = FALSE;
  213. }
  214. }
  215. }
  216. // Load the registry hive into the registry
  217. rc = RegLoadKey(HKEY_USERS,L"OnePointTranslation",profileName);
  218. if ( ! rc )
  219. {
  220. // Open the key
  221. rc = RegOpenKeyEx(HKEY_USERS,L"OnePointTranslation",0,KEY_ALL_ACCESS | READ_CONTROL | ACCESS_SYSTEM_SECURITY,&hKey);
  222. if ( ! rc )
  223. {
  224. // Process the registry hive
  225. rc = TranslateRegHive(hKey,L"",stArgs,cache,stat,bWin2K);
  226. // Unload the registry hive
  227. if ( ! stArgs->NoChange() )
  228. {
  229. DeleteFile(newName);
  230. hr = UpdateMappedDrives(sSourceName, sSourceDomainName, L"OnePointTranslation");
  231. rc = RegSaveKey(hKey,newName,NULL);
  232. }
  233. else
  234. {
  235. rc = 0;
  236. }
  237. if ( rc )
  238. {
  239. err.SysMsgWrite(ErrS,rc,DCT_MSG_SAVE_HIVE_FAILED_SD,newName,rc);
  240. }
  241. RegCloseKey(hKey);
  242. }
  243. rc = RegUnLoadKey(HKEY_USERS,L"OnePointTranslation");
  244. if ( rc )
  245. {
  246. err.SysMsgWrite(ErrE,rc,DCT_MSG_KEY_UNLOADKEY_FAILED_SD,profileName,rc);
  247. }
  248. }
  249. else
  250. {
  251. err.SysMsgWrite(ErrS,rc,DCT_MSG_PROFILE_LOAD_FAILED_SD,profileName,rc);
  252. }
  253. if ( ! rc )
  254. {
  255. if (! stArgs->NoChange() )
  256. {
  257. // Switch out the filenames
  258. if ( MoveFileEx(oldName,otherName,MOVEFILE_REPLACE_EXISTING) )
  259. {
  260. if ( ! MoveFileEx(newName,oldName,0) )
  261. {
  262. rc = GetLastError();
  263. err.SysMsgWrite(ErrS,rc,DCT_MSG_RENAME_DIR_FAILED_SSD,newName,oldName,rc);
  264. }
  265. }
  266. else
  267. {
  268. rc = GetLastError();
  269. if ( rc == ERROR_ACCESS_DENIED )
  270. {
  271. // we do not have access to the directory
  272. // temporarily grant ourselves access
  273. // Set NTFS permissions for the results directory
  274. WCHAR dirName[LEN_Path];
  275. safecopy(dirName,oldName);
  276. WCHAR * slash = wcsrchr(dirName,L'\\');
  277. if ( slash )
  278. {
  279. (*slash) = 0;
  280. }
  281. TFileSD fsdDirBefore(dirName);
  282. TFileSD fsdDirTemp(dirName);
  283. TFileSD fsdDatBefore(oldName);
  284. TFileSD fsdDatTemp(oldName);
  285. TFileSD fsdNewBefore(newName);
  286. TFileSD fsdNewTemp(newName);
  287. BOOL dirChanged = FALSE;
  288. BOOL datChanged = FALSE;
  289. BOOL newChanged = FALSE;
  290. // Temporarily reset the permissions on the directory and the appropriate files
  291. if ( fsdDirTemp.GetSecurity() != NULL )
  292. {
  293. TACE ace(ACCESS_ALLOWED_ACE_TYPE,0,DACL_FULLCONTROL_MASK,
  294. GetWellKnownSid(stArgs->IsLocalSystem() ? 7/*SYSTEM*/ : 1/*ADMINISTRATORS*/));
  295. PACL acl = NULL;
  296. fsdDirTemp.GetSecurity()->ACLAddAce(&acl,&ace,0);
  297. if (acl)
  298. {
  299. fsdDirTemp.GetSecurity()->SetDacl(acl,TRUE);
  300. fsdDirTemp.WriteSD();
  301. dirChanged = TRUE;
  302. }
  303. }
  304. if ( fsdDatTemp.GetSecurity() != NULL )
  305. {
  306. TACE ace(ACCESS_ALLOWED_ACE_TYPE,0,DACL_FULLCONTROL_MASK,
  307. GetWellKnownSid(stArgs->IsLocalSystem() ? 7/*SYSTEM*/ : 1/*ADMINISTRATORS*/));
  308. PACL acl = NULL;
  309. fsdDatTemp.GetSecurity()->ACLAddAce(&acl,&ace,0);
  310. if (acl)
  311. {
  312. fsdDatTemp.GetSecurity()->SetDacl(acl,TRUE);
  313. fsdDatTemp.WriteSD();
  314. datChanged = TRUE;
  315. }
  316. }
  317. if ( fsdNewTemp.GetSecurity() != NULL )
  318. {
  319. TACE ace(ACCESS_ALLOWED_ACE_TYPE,0,DACL_FULLCONTROL_MASK,
  320. GetWellKnownSid(stArgs->IsLocalSystem() ? 7/*SYSTEM*/ : 1/*ADMINISTRATORS*/));
  321. PACL acl = NULL;
  322. fsdNewTemp.GetSecurity()->ACLAddAce(&acl,&ace,0);
  323. if (acl)
  324. {
  325. fsdNewTemp.GetSecurity()->SetDacl(acl,TRUE);
  326. fsdNewTemp.WriteSD();
  327. newChanged = TRUE;
  328. }
  329. }
  330. rc = 0;
  331. // Now retry the operations
  332. if ( MoveFileEx(oldName,otherName,MOVEFILE_REPLACE_EXISTING) )
  333. {
  334. if ( ! MoveFileEx(newName,oldName,0) )
  335. {
  336. rc = GetLastError();
  337. err.SysMsgWrite(ErrS,rc,DCT_MSG_RENAME_DIR_FAILED_SSD,newName,oldName,rc);
  338. }
  339. }
  340. else
  341. {
  342. rc = GetLastError();
  343. err.SysMsgWrite(ErrS,rc,DCT_MSG_RENAME_DIR_FAILED_SSD,oldName,otherName,rc);
  344. }
  345. // now that we're done, set the permissions back to what they were
  346. if ( dirChanged )
  347. {
  348. fsdDirBefore.Changed(TRUE);
  349. fsdDirBefore.WriteSD();
  350. }
  351. if ( datChanged )
  352. {
  353. fsdDatBefore.Changed(TRUE);
  354. fsdDatBefore.WriteSD();
  355. }
  356. if ( newChanged )
  357. {
  358. fsdNewBefore.Changed(TRUE);
  359. fsdNewBefore.WriteSD();
  360. }
  361. }
  362. else
  363. {
  364. err.SysMsgWrite(ErrS,rc,DCT_MSG_RENAME_DIR_FAILED_SSD,oldName,otherName,rc);
  365. }
  366. }
  367. }
  368. }
  369. return rc;
  370. }
  371. DWORD
  372. CopyDirectoryTree(
  373. WCHAR const * targetDirectory, // in - target to copy files/dirs to
  374. WCHAR const * sourceDirectory // in - source directory to copy files/dirs from
  375. )
  376. {
  377. DWORD rc = 0;
  378. HANDLE hFind;
  379. WIN32_FIND_DATA fDat;
  380. WCHAR sourceWC[MAX_PATH];
  381. WCHAR sourceFile[MAX_PATH];
  382. WCHAR targetFile[MAX_PATH];
  383. safecopy(sourceWC,sourceDirectory);
  384. UStrCpy(sourceWC + UStrLen(sourceWC),L"\\*.*");
  385. // Loop through the items in the source directory
  386. hFind = FindFirstFile(sourceWC,&fDat);
  387. if ( hFind != INVALID_HANDLE_VALUE )
  388. {
  389. do {
  390. if ( UStrICmp(fDat.cFileName,L".") && UStrICmp(fDat.cFileName,L"..") )
  391. {
  392. //build the source and target filenames
  393. swprintf(sourceFile,L"%s\\%s",sourceDirectory,fDat.cFileName);
  394. swprintf(targetFile,L"%s\\%s",targetDirectory,fDat.cFileName);
  395. TFileSD fileSD(sourceFile);
  396. if ( fDat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
  397. {
  398. // copy the directory, update its SD
  399. SECURITY_ATTRIBUTES sAttr;
  400. sAttr.nLength = (sizeof sAttr);
  401. sAttr.bInheritHandle = FALSE;
  402. sAttr.lpSecurityDescriptor = NULL;
  403. if ( fileSD.GetSecurity() )
  404. {
  405. sAttr.lpSecurityDescriptor = fileSD.GetSecurity()->MakeRelSD();
  406. }
  407. if (! CreateDirectoryEx(sourceFile,targetFile,&sAttr) )
  408. {
  409. err.SysMsgWrite(ErrE,rc,DCT_MSG_COPY_DIR_FAILED_SSD,sourceFile,targetFile,rc);
  410. }
  411. else
  412. {
  413. // Recursively process the contents of the directory
  414. CopyDirectoryTree(targetFile,sourceFile);
  415. }
  416. }
  417. else
  418. {
  419. // Copy the file
  420. if (! CopyFile(sourceFile,targetFile,TRUE) )
  421. {
  422. rc = GetLastError();
  423. err.SysMsgWrite(ErrW,rc,DCT_MSG_COPY_FILE_FAILED_SSD,sourceFile,targetFile,rc);
  424. }
  425. else
  426. {
  427. // copy the security descriptor for the file
  428. TFileSD targetSD(targetFile);
  429. targetSD.CopyAccessData(&fileSD);
  430. targetSD.WriteSD();
  431. }
  432. }
  433. }
  434. if (! FindNextFile(hFind,&fDat) )
  435. {
  436. rc = GetLastError();
  437. }
  438. } while ( ! rc );
  439. if ( rc != ERROR_NO_MORE_FILES )
  440. {
  441. err.SysMsgWrite(ErrE,rc,DCT_MSG_FILE_ENUM_FAILED_SD,sourceDirectory,rc);
  442. }
  443. FindClose(hFind);
  444. }
  445. return rc;
  446. }
  447. DWORD
  448. CreateNewProfileDirectory(
  449. WCHAR const * oldDirectoryName, // in - directory name for old profile path
  450. WCHAR const * newAccountName, // in - target account name for new profile directory
  451. WCHAR * profileDirectory // out- directory name created for new profile directory
  452. )
  453. {
  454. DWORD rc = 0;
  455. WCHAR targetDir[MAX_PATH];
  456. WCHAR targetDirWithSuffix[MAX_PATH];
  457. WCHAR * slashNdx;
  458. TFileSD fileSD(const_cast<WCHAR*>(oldDirectoryName));
  459. SECURITY_ATTRIBUTES sAttr;
  460. sAttr.nLength = (sizeof sAttr);
  461. sAttr.bInheritHandle = FALSE;
  462. sAttr.lpSecurityDescriptor = NULL;
  463. if ( fileSD.GetSecurity() )
  464. {
  465. sAttr.lpSecurityDescriptor = fileSD.GetSecurity()->MakeRelSD();
  466. }
  467. safecopy(targetDir,oldDirectoryName);
  468. if ( targetDir[UStrLen(targetDir)-1] == L'\\' )
  469. targetDir[UStrLen(targetDir)-1] = 0;
  470. slashNdx = wcsrchr(targetDir,L'\\');
  471. if ( slashNdx )
  472. {
  473. UStrCpy(slashNdx+1,newAccountName);
  474. // try to create the directory
  475. if ( ! CreateDirectory(targetDir,NULL) )
  476. {
  477. rc = GetLastError();
  478. int ndx = 0;
  479. do {
  480. if ( ndx >= 1000 ) // abort
  481. {
  482. rc = ERROR_ALREADY_EXISTS;
  483. break;
  484. }
  485. if ( rc != ERROR_ALREADY_EXISTS )
  486. break;
  487. swprintf(targetDirWithSuffix,L"%s[%03d]",targetDir,ndx);
  488. if ( ! CreateDirectoryEx(oldDirectoryName,targetDirWithSuffix,&sAttr) )
  489. {
  490. rc = GetLastError();
  491. }
  492. else
  493. {
  494. rc = 0;
  495. }
  496. ndx++;
  497. } while ( rc == ERROR_ALREADY_EXISTS );
  498. if (! rc )
  499. UStrCpy(profileDirectory,targetDirWithSuffix);
  500. }
  501. else
  502. {
  503. UStrCpy(profileDirectory,targetDir);
  504. }
  505. }
  506. else
  507. {
  508. rc = ERROR_INVALID_NAME;
  509. }
  510. return rc;
  511. }
  512. DWORD
  513. UpdateProfilePermissions(
  514. WCHAR const * path, // in - path for directory to update
  515. SecurityTranslatorArgs * globalArgs, // in - path for overall job
  516. TRidNode * pNode // in - account to translate
  517. )
  518. {
  519. DWORD rc = 0;
  520. SecurityTranslatorArgs localArgs;
  521. TSDResolveStats stat(localArgs.Cache());
  522. BOOL bUseMapFile = globalArgs->UsingMapFile();
  523. // set-up the parameters for the translation
  524. localArgs.Cache()->CopyDomainInfo(globalArgs->Cache());
  525. localArgs.Cache()->ToSorted();
  526. if (!bUseMapFile)
  527. {
  528. localArgs.SetUsingMapFile(FALSE);
  529. localArgs.Cache()->InsertLast(pNode->GetAcctName(),pNode->SrcRid(),pNode->GetTargetAcctName(),pNode->TgtRid(),pNode->Type());
  530. }
  531. else
  532. {
  533. localArgs.SetUsingMapFile(TRUE);
  534. localArgs.Cache()->InsertLastWithSid(pNode->GetAcctName(),pNode->GetSrcDomSid(),pNode->GetSrcDomName(),pNode->SrcRid(),
  535. pNode->GetTargetAcctName(),pNode->GetTgtDomSid(),pNode->GetTgtDomName(),pNode->TgtRid(),pNode->Type());
  536. }
  537. localArgs.TranslateFiles(TRUE);
  538. localArgs.SetTranslationMode(globalArgs->TranslationMode());
  539. localArgs.SetWriteChanges(!globalArgs->NoChange());
  540. localArgs.PathList()->AddPath(const_cast<WCHAR*>(path),0);
  541. rc = ResolveAll(&localArgs,&stat);
  542. return rc;
  543. }
  544. // if the specified node is a normal share, this attempts to convert it to a path
  545. // using the administrative shares
  546. void
  547. BuildAdminPathForShare(
  548. WCHAR const * sharePath, // in -
  549. WCHAR * adminShare
  550. )
  551. {
  552. // if all else fails, return the same name as specified in the node
  553. UStrCpy(adminShare,sharePath);
  554. SHARE_INFO_502 * shInfo = NULL;
  555. DWORD rc = 0;
  556. WCHAR shareName[LEN_Path];
  557. WCHAR * slash = NULL;
  558. WCHAR server[LEN_Path];
  559. safecopy(server,sharePath);
  560. // split out just the server name
  561. slash = wcschr(server+3,L'\\');
  562. if ( slash )
  563. {
  564. (*slash) = 0;
  565. }
  566. // now get just the share name
  567. UStrCpy(shareName,sharePath + UStrLen(server) +1);
  568. slash = wcschr(shareName,L'\\');
  569. if ( slash )
  570. *slash = 0;
  571. rc = NetShareGetInfo(server,shareName,502,(LPBYTE*)&shInfo);
  572. if ( ! rc )
  573. {
  574. if ( *shInfo->shi502_path )
  575. {
  576. // build the administrative path name for the share
  577. UStrCpy(adminShare,server);
  578. UStrCpy(adminShare + UStrLen(adminShare),L"\\");
  579. UStrCpy(adminShare + UStrLen(adminShare),shInfo->shi502_path);
  580. WCHAR * colon = wcschr(adminShare,L':');
  581. if ( colon )
  582. {
  583. *colon = L'$';
  584. UStrCpy(adminShare + UStrLen(adminShare),L"\\");
  585. UStrCpy(adminShare + UStrLen(adminShare),slash+1);
  586. }
  587. else
  588. {
  589. // something went wrong -- revert to the given path
  590. UStrCpy(adminShare,sharePath);
  591. }
  592. }
  593. NetApiBufferFree(shInfo);
  594. }
  595. }
  596. DWORD
  597. CopyProfileDirectoryAndTranslate(
  598. WCHAR const * directory, // in - directory path for profile
  599. WCHAR * directoryOut, // out- new Profile Path (including environment variables)
  600. TRidNode * pNode, // in - node for account being translated
  601. SecurityTranslatorArgs * stArgs, // in - translation settings
  602. TSDResolveStats * stat // in - stats on items modified
  603. )
  604. {
  605. DWORD rc = 0;
  606. WCHAR fullPath[MAX_PATH];
  607. WCHAR targetPath[MAX_PATH];
  608. WCHAR profileName[MAX_PATH];
  609. WCHAR targetAcctName[MAX_PATH];
  610. WCHAR sourceDomName[MAX_PATH];
  611. HANDLE hFind;
  612. WIN32_FIND_DATA fDat;
  613. BOOL bTranslateDirOnly = FALSE;
  614. rc = ExpandEnvironmentStrings(directory,fullPath,DIM(fullPath));
  615. if ( !rc )
  616. {
  617. rc = GetLastError();
  618. err.SysMsgWrite(ErrE,rc,DCT_MSG_EXPAND_STRINGS_FAILED_SD,directory,rc);
  619. }
  620. else
  621. {
  622. // Create a new directory for the target profile
  623. // Get the account name for target user
  624. wcscpy(targetAcctName, pNode->GetTargetAcctName());
  625. if ( wcslen(targetAcctName) == 0 )
  626. {
  627. // if target user name not specified then use the source name.
  628. wcscpy(targetAcctName, pNode->GetAcctName());
  629. }
  630. //stArgs->SetTranslationMode(ADD_SECURITY);
  631. // We are changing our stratergy. We are not going to copy the profile directories anymore.
  632. // we will be reACLing the directories and the Registry instead.
  633. /*
  634. rc = CreateNewProfileDirectory(fullPath, targetAcctName,targetPath);
  635. if ( ! rc )
  636. {
  637. rc = CopyDirectoryTree(targetPath,fullPath);
  638. }
  639. */
  640. BuildAdminPathForShare(fullPath,targetPath);
  641. wcscpy(sourceDomName, const_cast<WCHAR*>(stArgs->Cache()->GetSourceDomainName()));
  642. //if we are using a sID mapping file, try to get the src domain name from this node's information
  643. wcscpy(sourceDomName, pNode->GetSrcDomName());
  644. // Look for profile files in the target directory
  645. // look for NTUser.MAN
  646. swprintf(profileName,L"%s\\NTUser.MAN",targetPath);
  647. hFind = FindFirstFile(profileName,&fDat);
  648. if ( hFind != INVALID_HANDLE_VALUE )
  649. {
  650. err.MsgWrite(0,DCT_MSG_TRANSLATING_NTUSER_MAN_S,targetAcctName);
  651. rc = TranslateUserProfile(profileName,stArgs,stArgs->Cache(),stat, pNode->GetAcctName(), sourceDomName);
  652. FindClose(hFind);
  653. }
  654. else
  655. {
  656. // check for NTUser.DAT
  657. swprintf(profileName,L"%s\\NTUser.DAT",targetPath);
  658. hFind = FindFirstFile(profileName,&fDat);
  659. if ( hFind != INVALID_HANDLE_VALUE )
  660. {
  661. err.MsgWrite(0,DCT_MSG_TRANSLATING_NTUSER_BAT_S,targetAcctName);
  662. rc = TranslateUserProfile(profileName,stArgs,stArgs->Cache(),stat,pNode->GetAcctName(), sourceDomName);
  663. FindClose(hFind);
  664. }
  665. else
  666. {
  667. err.MsgWrite(ErrS,DCT_MSG_PROFILE_REGHIVE_NOT_FOUND_SS,targetAcctName,targetPath);
  668. bTranslateDirOnly = TRUE; //set falg to atleast change permissins on the share dir
  669. rc = 2; // File not found
  670. }
  671. }
  672. if ((!rc) || (bTranslateDirOnly))
  673. rc = UpdateProfilePermissions(targetPath,stArgs,pNode);
  674. wcscpy(directoryOut, fullPath);
  675. }
  676. return rc;
  677. }
  678. DWORD
  679. TranslateLocalProfiles(
  680. SecurityTranslatorArgs * stArgs, // in - translation settings
  681. TSDRidCache * cache, // in - translation table
  682. TSDResolveStats * stat // in - stats on items modified
  683. )
  684. {
  685. DWORD rc = 0;
  686. WCHAR keyName[MAX_PATH];
  687. DWORD lenKeyName = DIM(keyName);
  688. TRegKey keyProfiles;
  689. BOOL bUseMapFile = stArgs->UsingMapFile();
  690. rc = keyProfiles.Open(L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",HKEY_LOCAL_MACHINE);
  691. if ( ! rc )
  692. {
  693. // get the number of subkeys
  694. // enumerate the subkeys
  695. DWORD ndx;
  696. DWORD nSubKeys = 0;
  697. rc = RegQueryInfoKey(keyProfiles.KeyGet(),NULL,0,NULL,&nSubKeys,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  698. if ( ! rc )
  699. {
  700. // construct a list containing the sub-keys
  701. PSID * pSids = new PSID[nSubKeys];
  702. for ( ndx = nSubKeys - 1 ; (long)ndx >= 0 ; ndx-- )
  703. {
  704. rc = keyProfiles.SubKeyEnum(ndx,keyName,lenKeyName);
  705. if ( rc )
  706. break;
  707. pSids[ndx] = SidFromString(keyName);
  708. }
  709. if ( ! rc )
  710. {
  711. // process each profile
  712. for ( ndx = 0 ; ndx < nSubKeys ; ndx++ )
  713. {
  714. do // once
  715. {
  716. if ( ! pSids[ndx] )
  717. continue;
  718. // see if this user needs to be translated
  719. TRidNode * pNode = NULL;
  720. if (!bUseMapFile)
  721. pNode = (TRidNode*)cache->Lookup(pSids[ndx]);
  722. else
  723. pNode = (TRidNode*)cache->LookupWODomain(pSids[ndx]);
  724. if ( pNode == (TRidNode *)-1 )
  725. pNode = NULL;
  726. if ( pNode && pNode->IsValidOnTgt() ) // need to translate this one
  727. {
  728. PSID pSidTgt = NULL;
  729. WCHAR strSourceSid[200];
  730. WCHAR strTargetSid[200];
  731. DWORD dimSid = DIM(strSourceSid);
  732. TRegKey srcKey;
  733. TRegKey tgtKey;
  734. DWORD disposition;
  735. WCHAR keyPath[MAX_PATH];
  736. WCHAR targetPath[MAX_PATH];
  737. DWORD lenValue;
  738. DWORD typeValue;
  739. if (!bUseMapFile)
  740. pSidTgt = cache->GetTgtSid(pSids[ndx]);
  741. else
  742. pSidTgt = cache->GetTgtSidWODomain(pSids[ndx]);
  743. GetTextualSid(pSids[ndx],strSourceSid,&dimSid);
  744. dimSid = DIM(strTargetSid);
  745. GetTextualSid(pSidTgt,strTargetSid,&dimSid);
  746. rc = srcKey.Open(strSourceSid,&keyProfiles);
  747. if ( rc )
  748. {
  749. err.SysMsgWrite(ErrS,rc,DCT_MSG_PROFILE_ENTRY_OPEN_FAILED_SD,pNode->GetAcctName(),rc );
  750. break;
  751. }
  752. if ( (stArgs->TranslationMode() == ADD_SECURITY) || (stArgs->TranslationMode() == REPLACE_SECURITY) )
  753. {
  754. // make a copy of this registry key, so the profile will refer to the new user
  755. if ( ! stArgs->NoChange() )
  756. {
  757. rc = tgtKey.Create(strTargetSid,&keyProfiles,&disposition);
  758. }
  759. else
  760. {
  761. // We need to see if the key already exists or not and set the DISPOSITION accordingly.
  762. rc = tgtKey.OpenRead(strTargetSid, &keyProfiles);
  763. if ( rc )
  764. {
  765. disposition = REG_CREATED_NEW_KEY;
  766. rc = 0;
  767. }
  768. tgtKey.Close();
  769. }
  770. if ( rc )
  771. {
  772. err.SysMsgWrite(ErrS,rc,DCT_MSG_PROFILE_CREATE_ENTRY_FAILED_SD,pNode->GetTargetAcctName(),rc);
  773. break;
  774. }
  775. if ( disposition == REG_CREATED_NEW_KEY || (stArgs->TranslationMode() == REPLACE_SECURITY))
  776. {
  777. // copy the entries from the source key
  778. if ( ! stArgs->NoChange() )
  779. {
  780. rc = tgtKey.HiveCopy(&srcKey);
  781. }
  782. else
  783. {
  784. rc = 0;
  785. tgtKey = srcKey;
  786. }
  787. if ( rc )
  788. {
  789. err.SysMsgWrite(ErrS,rc,DCT_MSG_COPY_PROFILE_FAILED_SSD,pNode->GetAcctName(),pNode->GetTargetAcctName(),rc);
  790. break;
  791. }
  792. // now get the profile path ...
  793. lenValue = (sizeof keyPath);
  794. rc = tgtKey.ValueGet(L"ProfileImagePath",(void *)keyPath,&lenValue,&typeValue);
  795. if ( rc )
  796. {
  797. err.SysMsgWrite(ErrS,rc,DCT_MSG_GET_PROFILE_PATH_FAILED_SD,pNode->GetAcctName(),rc);
  798. break;
  799. }
  800. //copy the profile directory and its contents, and translate the profile registry hive itself
  801. rc = CopyProfileDirectoryAndTranslate(keyPath,targetPath,pNode,stArgs,stat);
  802. if ( rc )
  803. {
  804. // Since the translation failed and we created the key we should delete it.
  805. if ( disposition == REG_CREATED_NEW_KEY )
  806. {
  807. if ( ! stArgs->NoChange() )
  808. keyProfiles.SubKeyDel(strTargetSid);
  809. }
  810. break;
  811. }
  812. // Update the ProfileImagePath key
  813. if ( !stArgs->NoChange() )
  814. rc = tgtKey.ValueSet(L"ProfileImagePath",(void*)targetPath,(1+UStrLen(targetPath)) * (sizeof WCHAR),typeValue);
  815. else
  816. rc = 0;
  817. if ( rc )
  818. {
  819. err.SysMsgWrite(ErrS,rc,DCT_MSG_SET_PROFILE_PATH_FAILED_SD,pNode->GetTargetAcctName(),rc);
  820. break;
  821. }
  822. // update the SID property
  823. if ( !stArgs->NoChange() )
  824. rc = tgtKey.ValueSet(L"Sid",(void*)pSidTgt,GetLengthSid(pSidTgt),REG_BINARY);
  825. else
  826. rc = 0;
  827. if ( rc )
  828. {
  829. rc = GetLastError();
  830. err.SysMsgWrite(ErrS,rc,DCT_MSG_UPDATE_PROFILE_SID_FAILED_SD,pNode->GetTargetAcctName(),rc);
  831. break;
  832. }
  833. }
  834. else
  835. {
  836. err.MsgWrite(ErrW,DCT_MSG_PROFILE_EXISTS_S,pNode->GetTargetAcctName());
  837. break;
  838. }
  839. }
  840. if ( stArgs->TranslationMode() != ADD_SECURITY )
  841. {
  842. // delete the old registry key
  843. if ( ! stArgs->NoChange() )
  844. rc = keyProfiles.SubKeyDel(strSourceSid);
  845. else
  846. rc = 0;
  847. if ( rc )
  848. {
  849. err.SysMsgWrite(ErrS,rc,DCT_MSG_DELETE_PROFILE_FAILED_SD,pNode->GetAcctName(),rc);
  850. break;
  851. }
  852. else
  853. {
  854. err.MsgWrite(0, DCT_MSG_DELETED_PROFILE_S, pNode->GetAcctName());
  855. }
  856. }
  857. }
  858. } while ( FALSE );
  859. }
  860. // clean up the list
  861. for ( ndx = 0 ; ndx < nSubKeys ; ndx++ )
  862. {
  863. if ( pSids[ndx] )
  864. FreeSid(pSids[ndx]);
  865. pSids[ndx] = NULL;
  866. }
  867. delete [] pSids;
  868. }
  869. }
  870. if ( rc && rc != ERROR_NO_MORE_ITEMS )
  871. {
  872. err.SysMsgWrite(ErrS,rc,DCT_MSG_ENUM_PROFILES_FAILED_D,rc);
  873. }
  874. }
  875. else
  876. {
  877. err.SysMsgWrite(ErrS,rc,DCT_MSG_OPEN_PROFILELIST_FAILED_D,rc);
  878. }
  879. return rc;
  880. }
  881. DWORD
  882. TranslateRemoteProfile(
  883. WCHAR const * sourceProfilePath, // in - source profile path
  884. WCHAR * targetProfilePath, // out- new profile path for target account
  885. WCHAR const * sourceName, // in - name of source account
  886. WCHAR const * targetName, // in - name of target account
  887. WCHAR const * srcDomain, // in - source domain
  888. WCHAR const * tgtDomain, // in - target domain
  889. IIManageDB * pDb, // in - pointer to DB object
  890. long lActionID, // in - action ID of this migration
  891. PSID sourceSid, // in - source sid from MoveObj2K
  892. BOOL bNoWriteChanges // in - No Change mode.
  893. )
  894. {
  895. DWORD rc = 0;
  896. BYTE srcSid[LEN_SID];
  897. PSID tgtSid[LEN_SID];
  898. SecurityTranslatorArgs stArgs;
  899. TSDResolveStats stat(stArgs.Cache());
  900. TRidNode * pNode = NULL;
  901. WCHAR domain[LEN_Domain];
  902. DWORD lenDomain = DIM(domain);
  903. DWORD lenSid = DIM(srcSid);
  904. DWORD srcRid=0;
  905. DWORD tgtRid=0;
  906. SID_NAME_USE snu;
  907. IVarSetPtr pVs(__uuidof(VarSet));
  908. IUnknown * pUnk = NULL;
  909. HRESULT hr = S_OK;
  910. WCHAR sActionInfo[MAX_PATH];
  911. _bstr_t sSSam;
  912. long lrid;
  913. stArgs.Cache()->SetSourceAndTargetDomains(srcDomain,tgtDomain);
  914. if ( stArgs.Cache()->IsInitialized() )
  915. {
  916. // Get the source account's rid
  917. if (! LookupAccountName(stArgs.Cache()->GetSourceDCName(),sourceName,srcSid,&lenSid,domain,&lenDomain,&snu) )
  918. {
  919. rc = GetLastError();
  920. }
  921. else
  922. {
  923. if ( !UStrICmp(domain,srcDomain) )
  924. {
  925. PUCHAR pCount = GetSidSubAuthorityCount(srcSid);
  926. if ( pCount )
  927. {
  928. DWORD nSub = (DWORD)(*pCount) - 1;
  929. DWORD * pRid = GetSidSubAuthority(srcSid,nSub);
  930. if ( pRid )
  931. {
  932. srcRid = *pRid;
  933. }
  934. }
  935. }
  936. }
  937. //if we couldn't get the src Rid, we are likely doing an intra-forest migration.
  938. //In this case we will lookup the src Rid in the Migrated Objects table
  939. if (!srcRid)
  940. {
  941. CopySid(GetLengthSid(srcSid), srcSid , sourceSid);
  942. hr = pVs->QueryInterface(IID_IUnknown, (void**)&pUnk);
  943. if ( SUCCEEDED(hr) )
  944. hr = pDb->raw_GetMigratedObjects(lActionID, &pUnk);
  945. if ( SUCCEEDED(hr) )
  946. {
  947. long lCnt = pVs->get("MigratedObjects");
  948. bool bFound = false;
  949. for ( long l = 0; (l < lCnt) && (!bFound); l++)
  950. {
  951. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", l, GET_STRING(DB_SourceSamName));
  952. sSSam = pVs->get(sActionInfo);
  953. if (_wcsicmp(sourceName, (WCHAR*)sSSam) == 0)
  954. {
  955. wsprintf(sActionInfo, L"MigratedObjects.%d.%s", l, GET_STRING(DB_SourceRid));
  956. lrid = pVs->get(sActionInfo);
  957. srcRid = (DWORD)lrid;
  958. bFound = true;
  959. }
  960. }
  961. }
  962. }
  963. lenSid = DIM(tgtSid);
  964. lenDomain = DIM(domain);
  965. // Get the target account's rid
  966. if (! LookupAccountName(stArgs.Cache()->GetTargetDCName(),targetName,tgtSid,&lenSid,domain,&lenDomain,&snu) )
  967. {
  968. rc = GetLastError();
  969. }
  970. else
  971. {
  972. if ( !UStrICmp(domain,tgtDomain) )
  973. {
  974. PUCHAR pCount = GetSidSubAuthorityCount(tgtSid);
  975. if ( pCount )
  976. {
  977. DWORD nSub = (DWORD)(*pCount) - 1;
  978. DWORD * pRid = GetSidSubAuthority(tgtSid,nSub);
  979. if ( pRid )
  980. {
  981. tgtRid = *pRid;
  982. }
  983. }
  984. }
  985. }
  986. }
  987. if ( ((srcRid && tgtRid) || !stArgs.NoChange()) && (!bNoWriteChanges) )
  988. {
  989. stArgs.Cache()->InsertLast(const_cast<WCHAR * const>(sourceName), srcRid, const_cast<WCHAR * const>(targetName), tgtRid);
  990. pNode = (TRidNode*)stArgs.Cache()->Lookup(srcSid);
  991. if ( pNode )
  992. {
  993. // Set up the security translation parameters
  994. stArgs.SetTranslationMode(ADD_SECURITY);
  995. stArgs.TranslateFiles(FALSE);
  996. stArgs.TranslateUserProfiles(TRUE);
  997. stArgs.SetWriteChanges(!bNoWriteChanges);
  998. //copy the profile directory and its contents, and translate the profile registry hive itself
  999. rc = CopyProfileDirectoryAndTranslate(sourceProfilePath,targetProfilePath,pNode,&stArgs,&stat);
  1000. }
  1001. }
  1002. return rc;
  1003. }
  1004. HRESULT UpdateMappedDrives(WCHAR * sSourceSam, WCHAR * sSourceDomain, WCHAR * sRegistryKey)
  1005. {
  1006. TRegKey reg;
  1007. TRegKey regDrive;
  1008. DWORD rc = 0;
  1009. WCHAR netKey[LEN_Path];
  1010. int len = LEN_Path;
  1011. int ndx = 0;
  1012. HRESULT hr = S_OK;
  1013. WCHAR sValue[LEN_Path];
  1014. WCHAR sAcct[LEN_Path];
  1015. WCHAR keyname[LEN_Path];
  1016. // Build the account name string that we need to check for
  1017. wsprintf(sAcct, L"%s\\%s", (WCHAR*) sSourceDomain, (WCHAR*) sSourceSam);
  1018. // Get the path to the Network subkey for this users profile.
  1019. wsprintf(netKey, L"%s\\%s", (WCHAR*) sRegistryKey, L"Network");
  1020. rc = reg.Open(netKey, HKEY_USERS);
  1021. if ( !rc )
  1022. {
  1023. while ( !reg.SubKeyEnum(ndx, keyname, len) )
  1024. {
  1025. rc = regDrive.Open(keyname, reg.KeyGet());
  1026. if ( !rc )
  1027. {
  1028. // Get the user name value that we need to check.
  1029. rc = regDrive.ValueGetStr(L"UserName", sValue, LEN_Path);
  1030. if ( !rc )
  1031. {
  1032. if ( !_wcsicmp(sAcct, sValue) )
  1033. {
  1034. // Found this account name in the mapped drive user name.so we will set the key to ""
  1035. regDrive.ValueSetStr(L"UserName", L"");
  1036. err.MsgWrite(0, DCT_MSG_RESET_MAPPED_CREDENTIAL_S, sValue);
  1037. }
  1038. }
  1039. else
  1040. hr = HRESULT_FROM_WIN32(GetLastError());
  1041. regDrive.Close();
  1042. }
  1043. else
  1044. hr = HRESULT_FROM_WIN32(GetLastError());
  1045. ndx++;
  1046. }
  1047. reg.Close();
  1048. }
  1049. else
  1050. hr = HRESULT_FROM_WIN32(GetLastError());
  1051. return hr;
  1052. }