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.

983 lines
35 KiB

  1. //#pragma title( "SDResolve.cpp - SDResolve: A Domain Migration Utility" )
  2. /*
  3. Copyright (c) 1995-1998, Mission Critical Software, Inc. All rights reserved.
  4. ===============================================================================
  5. Module - sdresolve.cpp
  6. System - SDResolve
  7. Author - Christy Boles
  8. Created - 97/07/11
  9. Description - Routines to iterate through files, shares, and printers
  10. when processing security on a machine.
  11. Updates -
  12. ===============================================================================
  13. */
  14. #include "stdafx.h"
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <iostream.h>
  18. #include <fstream.h>
  19. #include <assert.h>
  20. #include "Common.hpp"
  21. #include "ErrDct.hpp"
  22. #include "UString.hpp"
  23. #include "sd.hpp"
  24. #include "sidcache.hpp"
  25. #include "enumvols.hpp"
  26. #include "SecObj.hpp"
  27. #include "ealen.hpp"
  28. #include "BkupRstr.hpp"
  29. #include "TxtSid.h"
  30. #include "array.h"
  31. // this makes sure the funciton name IteratePathUnderlying is not mangled by C++
  32. extern "C" {
  33. #include "sdresolv_stkoflw.h"
  34. }
  35. #ifdef _DEBUG
  36. #define new DEBUG_NEW
  37. #undef THIS_FILE
  38. static char THIS_FILE[] = __FILE__;
  39. #endif
  40. bool enforce;
  41. extern TErrorDct err;
  42. extern bool silent;
  43. extern bool IsMachineName(const LPWSTR name);
  44. extern bool IsShareName(const LPWSTR name);
  45. extern bool ContainsWildcard( WCHAR const * name);
  46. struct SSeException
  47. {
  48. SSeException(UINT uCode) : uCode(uCode)
  49. {
  50. }
  51. UINT uCode;
  52. };
  53. void SeTranslator(unsigned int u, EXCEPTION_POINTERS* pepExceptions)
  54. {
  55. throw SSeException(u);
  56. }
  57. #define MAX_BUFFER_LENGTH 10000
  58. #define PRINT_BUFFER_SIZE 2000
  59. //******************************************************************************************************
  60. // Main routine for SDResolve
  61. // Iterates files and directories to be resolved
  62. void
  63. IteratePath(
  64. WCHAR * path, // in -path to start iterating from
  65. SecurityTranslatorArgs * args, // in -translation settings
  66. TSDResolveStats * stats, // in -stats (to display pathnames & pass to ResolveSD)
  67. TSecurableObject * LC, // in -last container
  68. TSecurableObject * LL, // in -last file
  69. bool haswc // in -indicates whether path contains a wc character
  70. )
  71. {
  72. _se_translator_function pfnSeTranslatorOld = _set_se_translator((_se_translator_function)SeTranslator);
  73. try
  74. {
  75. IteratePathUnderlying(path,(void*)args,(void*)stats,(void*)LC,(void*)LL,haswc ? TRUE : FALSE);
  76. }
  77. catch (SSeException sse)
  78. {
  79. _set_se_translator(pfnSeTranslatorOld);
  80. _com_issue_error(HRESULT_FROM_WIN32(sse.uCode));
  81. }
  82. catch (...)
  83. {
  84. _set_se_translator(pfnSeTranslatorOld);
  85. throw;
  86. }
  87. _set_se_translator(pfnSeTranslatorOld);
  88. }
  89. #define safecopy_wc_array(trg,src) ((src) ? UStrCpy((WCHAR*)trg,src,trg.size()) : *((WCHAR*)trg) = 0)
  90. void
  91. IteratePathUnderlying(
  92. WCHAR * path, // in -path to start iterating from
  93. void * argsC, // in -translation settings
  94. void * statsC, // in -stats (to display pathnames & pass to ResolveSD)
  95. void * LCC, // in -last container
  96. void * LLC, // in -last file
  97. BOOL haswc // in -indicates whether path contains a wc character
  98. )
  99. {
  100. SecurityTranslatorArgs *args = (SecurityTranslatorArgs *) argsC;
  101. TSDResolveStats *stats = (TSDResolveStats *) statsC;
  102. TSecurableObject *LC = (TSecurableObject*) LCC;
  103. TSecurableObject *LL = (TSecurableObject*) LLC;
  104. HANDLE hFind;
  105. WIN32_FIND_DATA findEntry;
  106. BOOL b;
  107. TFileSD * currSD;
  108. bool changeLastCont;
  109. bool changeLastLeaf;
  110. WCHAR * appendPath = NULL;
  111. c_array<WCHAR> safepath(LEN_Path + 10);
  112. TFileSD * LastContain = (TFileSD*) LC;
  113. TFileSD * LastLeaf = (TFileSD*) LL;
  114. c_array<WCHAR> localPath(LEN_Path);
  115. // this is the first (for this) dir
  116. safecopy_wc_array(safepath,path);
  117. safecopy_wc_array(localPath,path);
  118. // Check to see if path is longer than MAX_PATH
  119. // if so, add \\?\ to the beginning of it to
  120. // turn off path parsing
  121. if ( UStrLen(path) >= MAX_PATH && path[2] != L'?' )
  122. {
  123. WCHAR temp[LEN_Path];
  124. if ( (path[0] == L'\\') && (path[1] == L'\\') ) // UNC name
  125. {
  126. UStrCpy(temp,L"\\\\?\\UNC\\");
  127. }
  128. else
  129. {
  130. UStrCpy(temp,L"\\\\?\\");
  131. }
  132. UStrCpy(temp + UStrLen(temp),path);
  133. safecopy_wc_array(localPath,temp);
  134. }
  135. appendPath = (WCHAR*)localPath + UStrLen((WCHAR*)localPath);
  136. if ( *(appendPath-1) == L'\\' ) // if there's already a backslash on the end of the path, don't add another one
  137. appendPath--;
  138. if ( ! haswc )
  139. UStrCpy(appendPath, "\\*.*");
  140. if ( args->LogVerbose() )
  141. err.DbgMsgWrite(0,L"Starting IteratePath: %ls",path);
  142. for ( b = ((hFind = FindFirstFile((WCHAR*)localPath, &findEntry)) != INVALID_HANDLE_VALUE)
  143. ; b ; b = FindNextFile(hFind, &findEntry) )
  144. {
  145. if ( ! haswc)
  146. appendPath[1] = '\0'; // restore path -- remove \*.* append
  147. if ( ! UStrCmp((LPWSTR)findEntry.cFileName,L".") || ! UStrCmp((LPWSTR)findEntry.cFileName,L"..") )
  148. continue; // ignore names '.' and '..'
  149. if ( ! haswc )
  150. UStrCpy(appendPath+1, findEntry.cFileName);
  151. else
  152. {
  153. for ( WCHAR * ch = appendPath-1; ch >= path && *ch != L'\\' ; ch-- )
  154. ;
  155. UStrCpy(ch+1,findEntry.cFileName);
  156. }
  157. if ( ((TAccountCache *)args->Cache())->IsCancelled() )
  158. {
  159. break;
  160. }
  161. currSD = new TFileSD(localPath, (findEntry.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) != 0);
  162. stats->DisplayPath(localPath);
  163. if ( !currSD || !currSD->HasSecurity() )
  164. {
  165. //err.MsgWrite(0,"Error: Couldn't get the SD");
  166. }
  167. else
  168. {
  169. if ( findEntry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) // if dir
  170. {
  171. // resolve this container & iterate next container
  172. changeLastCont = currSD->ResolveSD(args,stats,directory,LastContain);
  173. if ( changeLastCont )
  174. {
  175. if ( LastContain && LastContain != LC )
  176. {
  177. delete LastContain;
  178. }
  179. LastContain = currSD;
  180. }
  181. else
  182. {
  183. delete currSD;
  184. }
  185. try
  186. {
  187. BOOL bLogError;
  188. UINT status = IteratePathUnderlyingNoObjUnwinding(localPath,(void*)args,(void*)stats,(void*)LastContain,(void*)LastLeaf,FALSE,&bLogError);
  189. if (bLogError)
  190. err.SysMsgWrite(ErrE,
  191. HRESULT_FROM_WIN32(STATUS_STACK_OVERFLOW),
  192. DCT_MSG_CANNOT_TRANSLATE_DIRECTORY_SD,
  193. (WCHAR*)localPath,
  194. HRESULT_FROM_WIN32(STATUS_STACK_OVERFLOW));
  195. if (status != 0)
  196. _com_issue_error(HRESULT_FROM_WIN32(status));
  197. }
  198. catch (SSeException sse)
  199. {
  200. err.SysMsgWrite(ErrE,
  201. HRESULT_FROM_WIN32(sse.uCode),
  202. DCT_MSG_CANNOT_TRANSLATE_DIRECTORY_SD,
  203. (WCHAR*)localPath,
  204. HRESULT_FROM_WIN32(sse.uCode));
  205. _com_issue_error(HRESULT_FROM_WIN32(sse.uCode));
  206. }
  207. }
  208. else
  209. {
  210. // iterate this file with last
  211. changeLastLeaf = currSD->ResolveSD(args,stats,file,LastLeaf);
  212. if ( changeLastLeaf )
  213. {
  214. if ( LastLeaf && LastLeaf != LL )
  215. {
  216. delete LastLeaf;
  217. }
  218. LastLeaf = currSD;
  219. }
  220. else
  221. {
  222. delete currSD;
  223. }
  224. }
  225. }
  226. }
  227. if ( LastContain && LastContain != LC )
  228. {
  229. delete LastContain;
  230. }
  231. if ( LastLeaf && LastLeaf != LL )
  232. {
  233. delete LastLeaf;
  234. }
  235. appendPath[0] = '\0';
  236. DWORD rc = GetLastError();
  237. if ( args->LogVerbose() )
  238. err.DbgMsgWrite(0,L"Closing IteratePath %S",(WCHAR*)safepath);
  239. FindClose(hFind);
  240. switch ( rc )
  241. {
  242. case ERROR_NO_MORE_FILES:
  243. case 0:
  244. break;
  245. default:
  246. err.SysMsgWrite(ErrE, rc, DCT_MSG_FIND_FILE_FAILED_SD, path, rc);
  247. }
  248. }
  249. DWORD
  250. ResolvePrinter(
  251. PRINTER_INFO_4 * pPrinter, // in - printer information
  252. SecurityTranslatorArgs * args, // in - translation settings
  253. TSDResolveStats * stats // in - stats
  254. )
  255. {
  256. DWORD rc = 0;
  257. // DWORD needed = 0;
  258. TPrintSD sd(pPrinter->pPrinterName);
  259. if ( sd.GetSecurity() )
  260. {
  261. sd.ResolveSD(args,stats,printer,NULL);
  262. }
  263. return rc;
  264. }
  265. int
  266. ServerResolvePrinters(
  267. WCHAR const * server, // in -translate the printers on this server
  268. SecurityTranslatorArgs * args, // in -translation settings
  269. TSDResolveStats * stats // in -stats
  270. )
  271. {
  272. DWORD rc = 0;
  273. PRINTER_INFO_4 * pInfo = NULL;
  274. BYTE * buffer = new BYTE[PRINT_BUFFER_SIZE];
  275. DWORD cbNeeded = PRINT_BUFFER_SIZE;
  276. DWORD nReturned = 0;
  277. if (!buffer)
  278. {
  279. rc = ERROR_NOT_ENOUGH_MEMORY;
  280. }
  281. if (!rc && !EnumPrinters(PRINTER_ENUM_LOCAL,NULL,4,buffer,PRINT_BUFFER_SIZE,&cbNeeded,&nReturned) )
  282. {
  283. rc = GetLastError();
  284. if ( rc == ERROR_INSUFFICIENT_BUFFER )
  285. {
  286. // try again with a bigger buffer size
  287. delete [] buffer;
  288. buffer = NULL;
  289. buffer = new BYTE[cbNeeded];
  290. if (!buffer)
  291. {
  292. rc = ERROR_NOT_ENOUGH_MEMORY;
  293. }
  294. else if (! EnumPrinters(PRINTER_ENUM_LOCAL,NULL,4,buffer,cbNeeded,&cbNeeded,&nReturned) )
  295. {
  296. rc = GetLastError();
  297. }
  298. else
  299. rc = ERROR_SUCCESS;
  300. }
  301. }
  302. if ( ! rc )
  303. {
  304. pInfo = (PRINTER_INFO_4 *)buffer;
  305. for ( DWORD i = 0 ; i < nReturned && !args->Cache()->IsCancelled(); i++ )
  306. {
  307. ResolvePrinter(&(pInfo[i]),args,stats);
  308. }
  309. }
  310. else
  311. {
  312. err.SysMsgWrite(ErrE,rc,DCT_MSG_ERROR_ENUMERATING_LOCAL_PRINTERS_D,rc);
  313. }
  314. if (args->Cache()->IsCancelled())
  315. err.MsgWrite(0, DCT_MSG_OPERATION_ABORTED_PRINTERS);
  316. delete [] buffer;
  317. return rc;
  318. }
  319. int
  320. ServerResolveShares(
  321. WCHAR const * server, // in -enumerate and translate the shares on this server
  322. SecurityTranslatorArgs * args, // in -translation settings
  323. TSDResolveStats * stats // in -stats (to display pathnames & pass to ResolveSD)
  324. )
  325. {
  326. DWORD rc = 0;
  327. DWORD numRead = 0;
  328. DWORD totalEntries = 0;
  329. DWORD resumeHandle = 0;
  330. SHARE_INFO_0 * bufPtr = NULL;
  331. WCHAR serverName[LEN_Computer];
  332. WCHAR fullPath[LEN_Path];
  333. WCHAR * pServerName = serverName;
  334. DWORD ttlRead = 0;
  335. if (!args->Cache()->IsCancelled())
  336. {
  337. if ( server )
  338. {
  339. safecopy(serverName,server);
  340. }
  341. else
  342. {
  343. pServerName = NULL;
  344. }
  345. do
  346. {
  347. if (args->Cache()->IsCancelled())
  348. break;
  349. rc = NetShareEnum(pServerName,0,(LPBYTE *)&bufPtr,MAX_BUFFER_LENGTH,&numRead,&totalEntries,&resumeHandle);
  350. if ( ! rc || rc == ERROR_MORE_DATA )
  351. {
  352. for ( UINT i = 0 ; i < numRead ; i++ )
  353. {
  354. // Process the SD
  355. if ( pServerName )
  356. {
  357. swprintf(fullPath,L"%s\\%s",pServerName,bufPtr[i].shi0_netname);
  358. }
  359. else
  360. {
  361. swprintf(fullPath,L"%s",bufPtr[i].shi0_netname);
  362. }
  363. TShareSD tSD(fullPath);
  364. if ( tSD.HasSecurity() )
  365. {
  366. stats->DisplayPath(fullPath,TRUE);
  367. tSD.ResolveSD(args,stats,share,NULL);
  368. }
  369. }
  370. ttlRead += numRead;
  371. resumeHandle = ttlRead;
  372. NetApiBufferFree(bufPtr);
  373. }
  374. } while ( rc == ERROR_MORE_DATA && numRead < totalEntries);
  375. if ( rc && rc != ERROR_MORE_DATA )
  376. err.SysMsgWrite(ErrE,rc,DCT_MSG_SHARE_ENUM_FAILED_SD,server,rc);
  377. }
  378. if (args->Cache()->IsCancelled())
  379. err.MsgWrite(0, DCT_MSG_OPERATION_ABORTED_SHARES);
  380. return rc;
  381. }
  382. void
  383. ResolveFilePath(
  384. SecurityTranslatorArgs * args, // in - translation options
  385. TSDResolveStats * Stats, // in - class to display stats
  386. WCHAR * path, // in - path name
  387. bool validAlone, // in - whether this object exists (false for share names and volume roots)
  388. bool containsWC, // in - true if path contains wildcard
  389. bool iscontainer // in - whether the starting path is a container
  390. )
  391. {
  392. TFileSD * pSD;
  393. if ( args->LogVerbose() )
  394. err.MsgWrite(0,DCT_MSG_PROCESSING_S,path);
  395. Stats->DisplayPath(path);
  396. if ( validAlone && ! containsWC )
  397. {
  398. pSD = new TFileSD(path);
  399. if (!pSD)
  400. return;
  401. if ( pSD->HasSecurity() )
  402. pSD->ResolveSD(args,
  403. Stats,
  404. iscontainer?directory:file,
  405. NULL);
  406. delete pSD;
  407. }
  408. if ( iscontainer || containsWC )
  409. {
  410. IteratePath(path,
  411. args,
  412. Stats,
  413. NULL,
  414. NULL,
  415. containsWC);
  416. }
  417. if (args->Cache()->IsCancelled())
  418. err.MsgWrite(0, DCT_MSG_OPERATION_ABORTED_FILES);
  419. }
  420. void WriteOptions(SecurityTranslatorArgs * args)
  421. {
  422. //* WCHAR cmd[1000] = L"SecurityTranslation ";;
  423. WCHAR cmd[1000];
  424. WCHAR arg[300];
  425. UStrCpy(cmd, GET_STRING(IDS_STOptions_Start));
  426. if ( args->NoChange() )
  427. {
  428. //* UStrCpy(cmd +UStrLen(cmd), L"WriteChanges:No ");
  429. UStrCpy(cmd +UStrLen(cmd), GET_STRING(IDS_STOptions_WriteChng));
  430. }
  431. if ( args->TranslateFiles() )
  432. {
  433. //* UStrCpy(cmd +UStrLen(cmd), L"Files:Yes ");
  434. UStrCpy(cmd +UStrLen(cmd), GET_STRING(IDS_STOptions_Files));
  435. }
  436. if ( args->TranslateShares() )
  437. {
  438. //* UStrCpy(cmd + UStrLen(cmd),L"Shares:Yes ");
  439. UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_Shares));
  440. }
  441. if ( args->TranslateLocalGroups() )
  442. {
  443. //* UStrCpy(cmd + UStrLen(cmd),L"LGroups:Yes ");
  444. UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_LocalGroup));
  445. }
  446. if ( args->TranslateUserRights() )
  447. {
  448. // UStrCpy(cmd + UStrLen(cmd),L"UserRights:Yes ");
  449. UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_URights));
  450. }
  451. if ( args->TranslatePrinters() )
  452. {
  453. // UStrCpy(cmd + UStrLen(cmd),L"UserRights:Yes ");
  454. UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_Printers));
  455. }
  456. if ( args->TranslateUserProfiles() )
  457. {
  458. //* UStrCpy(cmd + UStrLen(cmd),L"Profiles:Yes ");
  459. UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_Profiles));
  460. }
  461. if ( args->TranslateRecycler() )
  462. {
  463. //* UStrCpy(cmd + UStrLen(cmd),L"RecycleBin:Yes ");
  464. UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_RBin));
  465. }
  466. if ( *args->LogFile() )
  467. {
  468. //* wsprintf(arg,L"LogFile:%S ",args->LogFile());
  469. wsprintf(arg,GET_STRING(IDS_STOptions_LogName),args->LogFile());
  470. UStrCpy(cmd +UStrLen(cmd), arg);
  471. }
  472. if ( args->TranslationMode() == ADD_SECURITY )
  473. {
  474. //* UStrCpy(cmd +UStrLen(cmd), L"TranslationMode:Add ");
  475. UStrCpy(cmd +UStrLen(cmd), GET_STRING(IDS_STOptions_AddMode));
  476. }
  477. else if ( args->TranslationMode() == REMOVE_SECURITY )
  478. {
  479. //* UStrCpy(cmd +UStrLen(cmd), L"TranslationMode:Remove ");
  480. UStrCpy(cmd +UStrLen(cmd), GET_STRING(IDS_STOptions_RemoveMode));
  481. }
  482. else
  483. {
  484. //* UStrCpy(cmd + UStrLen(cmd),L"TranslationMode:Replace ");
  485. UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_ReplaceMode));
  486. }
  487. wsprintf(arg,L"%s %s ",args->Source(), args->Target());
  488. UStrCpy(cmd +UStrLen(cmd), arg);
  489. err.MsgWrite(0,DCT_MSG_GENERIC_S,&*cmd);
  490. }
  491. void
  492. TranslateRecycler(
  493. SecurityTranslatorArgs * args, // in - translation options
  494. TSDResolveStats * Stats, // in - class to display stats
  495. WCHAR * path // in - drive name
  496. )
  497. {
  498. err.MsgWrite(0,DCT_MSG_PROCESSING_RECYCLER_S,path);
  499. WCHAR folder[LEN_Path];
  500. WCHAR const * recycler = L"RECYCLER";
  501. WCHAR strSid[200];
  502. WCHAR srcPath[LEN_Path];
  503. WCHAR tgtPath[LEN_Path];
  504. DWORD lenStrSid = DIM(strSid);
  505. _wfinddata_t fData;
  506. // long hRecycler;
  507. LONG_PTR hRecycler;
  508. PSID pSidSrc = NULL, pSidTgt = NULL;
  509. TRidNode * pNode;
  510. DWORD rc = 0;
  511. BOOL bUseMapFile = args->UsingMapFile();
  512. swprintf(folder,L"%s\\%s\\*",path,recycler);
  513. long mode = args->TranslationMode();
  514. // Windows 2000 checks the SD for the recycle bin when the recycle bin is opened. If the SD does not match the
  515. // default template (permissions for user, admin, and system), Windows displays a message that the recycle bin is corrupt.
  516. // This change may also be in NT 4 SP 7. To avoid causing this corrupt recycle bin message, we will always translate the
  517. // recycle bins in replace mode. We will not change if we are doing a remove.
  518. if (args->TranslationMode() != REMOVE_SECURITY)
  519. args->SetTranslationMode(REPLACE_SECURITY);
  520. // use _wfind to look for hidden files in the folder
  521. for ( hRecycler = _wfindfirst(folder,&fData) ; hRecycler != -1 && ( rc == 0 ); rc = (DWORD)_wfindnext(hRecycler,&fData) )
  522. {
  523. pSidSrc = SidFromString(fData.name);
  524. if ( pSidSrc )
  525. {
  526. err.MsgWrite(0,DCT_MSG_PROCESSING_RECYCLE_FOLDER_S,fData.name);
  527. if (!bUseMapFile)
  528. pNode = (TRidNode*)args->Cache()->Lookup(pSidSrc);
  529. else
  530. pNode = (TRidNode*)args->Cache()->LookupWODomain(pSidSrc);
  531. if ( pNode && pNode != (TRidNode*)-1 )
  532. {
  533. if (!bUseMapFile)
  534. pSidTgt = args->Cache()->GetTgtSid(pNode);
  535. else
  536. pSidTgt = args->Cache()->GetTgtSidWODomain(pNode);
  537. // get the target directory name
  538. GetTextualSid(pSidTgt,strSid,&lenStrSid);
  539. if ( args->LogVerbose() )
  540. err.DbgMsgWrite(0,L"Target sid is: %ls",strSid);
  541. if ( ! args->NoChange() && args->TranslationMode() != REMOVE_SECURITY )
  542. {
  543. // rename the directory
  544. swprintf(srcPath,L"%s\\%s\\%s",path,recycler,fData.name);
  545. swprintf(tgtPath,L"%s\\%s\\%s",path,recycler,strSid);
  546. if ( ! MoveFile(srcPath,tgtPath) )
  547. {
  548. rc = GetLastError();
  549. if ( (rc == ERROR_ALREADY_EXISTS) && (args->TranslationMode() == REPLACE_SECURITY) )
  550. {
  551. // the target recycle bin already exists
  552. // attempt to rename it with a suffix, so we can rename the new bin to the SID
  553. WCHAR tmpPath[LEN_Path];
  554. long ndx = 0;
  555. do
  556. {
  557. swprintf(tmpPath,L"%ls%ls%ld",tgtPath,GET_STRING(IDS_RenamedRecyclerSuffix),ndx);
  558. if (! MoveFile(tgtPath,tmpPath) )
  559. {
  560. rc = GetLastError();
  561. ndx++;
  562. }
  563. else
  564. {
  565. rc = 0;
  566. err.MsgWrite(0,DCT_MSG_RECYCLER_RENAMED_SS,tgtPath,tmpPath);
  567. }
  568. } while ( rc == ERROR_ALREADY_EXISTS );
  569. if ( ! rc )
  570. {
  571. // we have moved the pre-existing target recycler out of the way
  572. // now retry the rename
  573. if (! MoveFile(srcPath,tgtPath) )
  574. {
  575. err.SysMsgWrite(ErrE,rc,DCT_MSG_RECYCLER_RENAME_FAILED_SD,pNode->GetAcctName(),rc);
  576. }
  577. else
  578. {
  579. err.MsgWrite(0,DCT_MSG_RECYCLER_RENAMED_SS,srcPath,tgtPath);
  580. // run security translation on the new folder
  581. ResolveFilePath(args,Stats,tgtPath,TRUE,FALSE,TRUE);
  582. }
  583. }
  584. else
  585. {
  586. err.SysMsgWrite(ErrE,rc,DCT_MSG_RECYCLER_RENAME_FAILED_SD,pNode->GetAcctName(),rc);
  587. }
  588. }
  589. else
  590. {
  591. err.SysMsgWrite(ErrE,rc,DCT_MSG_RECYCLER_RENAME_FAILED_SD,pNode->GetAcctName(),rc);
  592. }
  593. }
  594. else
  595. {
  596. err.MsgWrite(0,DCT_MSG_RECYCLER_RENAMED_SS,srcPath,tgtPath);
  597. // run security translation on the new folder
  598. ResolveFilePath(args,Stats,tgtPath,TRUE,FALSE,TRUE);
  599. }
  600. }
  601. free(pSidTgt);
  602. }
  603. FreeSid(pSidSrc);
  604. }
  605. }
  606. // set the translation mode back to its original value
  607. args->SetTranslationMode(mode);
  608. }
  609. // if the specified node is a normal share, this attempts to convert it to a path
  610. // using the administrative shares
  611. void
  612. BuildAdminPathForShare(
  613. TPathNode * tnode,
  614. WCHAR * adminShare
  615. )
  616. {
  617. // if all else fails, return the same name as specified in the node
  618. UStrCpy(adminShare,tnode->GetPathName());
  619. SHARE_INFO_502 * shInfo = NULL;
  620. DWORD rc = 0;
  621. WCHAR shareName[LEN_Path];
  622. WCHAR * slash = NULL;
  623. UStrCpy(shareName,tnode->GetPathName() + UStrLen(tnode->GetServerName()) +1);
  624. slash = wcschr(shareName,L'\\');
  625. if ( slash )
  626. *slash = 0;
  627. rc = NetShareGetInfo(tnode->GetServerName(),shareName,502,(LPBYTE*)&shInfo);
  628. if ( ! rc )
  629. {
  630. if ( *shInfo->shi502_path )
  631. {
  632. // build the administrative path name for the share
  633. UStrCpy(adminShare,tnode->GetServerName());
  634. UStrCpy(adminShare + UStrLen(adminShare),L"\\");
  635. UStrCpy(adminShare + UStrLen(adminShare),shInfo->shi502_path);
  636. WCHAR * colon = wcschr(adminShare,L':');
  637. if ( colon )
  638. {
  639. *colon = L'$';
  640. UStrCpy(adminShare + UStrLen(adminShare),L"\\");
  641. UStrCpy(adminShare + UStrLen(adminShare),slash+1);
  642. }
  643. else
  644. {
  645. // something went wrong -- revert to the given path
  646. UStrCpy(adminShare,tnode->GetPathName());
  647. }
  648. }
  649. NetApiBufferFree(shInfo);
  650. }
  651. }
  652. // Main routine for resolving file and directory SD's.
  653. int
  654. ResolveAll(
  655. SecurityTranslatorArgs * args, // in- translation settings
  656. TSDResolveStats * Stats // in- counts of examined, changed objects, etc.
  657. )
  658. {
  659. WCHAR * warg;
  660. WCHAR * machine;
  661. UINT errmode;
  662. int retcode = 0;
  663. TPathNode * tnode;
  664. errmode = SetErrorMode(SEM_FAILCRITICALERRORS);
  665. if ( ! retcode )
  666. {
  667. WriteOptions(args);
  668. Stats->InitDisplay(args->NoChange());
  669. err.MsgWrite(0,DCT_MSG_FST_STARTING);
  670. // Process Files and Directories
  671. if (! args->IsLocalSystem() )
  672. {
  673. TNodeListEnum tenum;
  674. for (tnode = (TPathNode *)tenum.OpenFirst((TNodeList *)args->PathList()) ; tnode && !args->Cache()->IsCancelled(); tnode = (TPathNode *)tenum.Next() )
  675. {
  676. DWORD rc;
  677. BOOL needToGetBR = FALSE;
  678. // BOOL abort = FALSE;
  679. // BOOL firstTime = TRUE;
  680. warg = tnode->GetPathName();
  681. machine = GetMachineName(warg);
  682. needToGetBR = ( args->TranslateFiles() );
  683. if ( *tnode->GetServerName() && ! args->IsLocalSystem() )
  684. {
  685. warg = tnode->GetPathName();
  686. err.MsgWrite(0,DCT_MSG_PROCESSING_S,warg);
  687. if ( args->TranslateFiles() && !args->Cache()->IsCancelled())
  688. {
  689. if ( needToGetBR )
  690. {
  691. //get needed privileges and keep them until the agent removes itself
  692. GetBkupRstrPriv(tnode->GetServerName());
  693. }
  694. if ( IsMachineName(warg) )
  695. {
  696. // need to process each drive on this machine
  697. TVolumeEnum vEnum;
  698. rc = vEnum.Open(warg,VERIFY_PERSISTENT_ACLS,args->LogVerbose());
  699. if ( rc )
  700. {
  701. err.SysMsgWrite(ErrE,rc,DCT_MSG_ERROR_ACCESSING_DRIVES_SD,warg,rc);
  702. }
  703. else
  704. {
  705. while ( (warg = vEnum.Next()) && !args->Cache()->IsCancelled())
  706. {
  707. ResolveFilePath(args,
  708. Stats,
  709. warg,
  710. false, // not valid alone
  711. false, // no wildcard
  712. true ); // container
  713. }
  714. warg = machine;
  715. }
  716. vEnum.Close();
  717. }
  718. else
  719. {
  720. WCHAR adminShare[LEN_Path];
  721. // Verify that the volume is NTFS
  722. rc = tnode->VerifyPersistentAcls();
  723. switch ( rc )
  724. {
  725. case ERROR_SUCCESS:
  726. // Process the path
  727. // if it's a share name, process the root of the share
  728. if( IsShareName(tnode->GetPathName()) )
  729. {
  730. WCHAR sharePath[LEN_Path];
  731. swprintf(sharePath,L"%s\\.",tnode->GetPathName());
  732. TFileSD sd(sharePath);
  733. if ( sd.HasSecurity() )
  734. {
  735. sd.ResolveSD(args,
  736. Stats,
  737. directory,
  738. NULL);
  739. }
  740. }
  741. // if this is a normal share, convert it to an administrative share
  742. // path, so that we can take advantage of backup/restore privileges
  743. BuildAdminPathForShare(tnode,adminShare);
  744. ResolveFilePath(args,
  745. Stats,
  746. adminShare,
  747. !IsShareName(tnode->GetPathName()),
  748. ContainsWildcard(tnode->GetPathName()),
  749. tnode->IsContainer() || IsShareName(tnode->GetPathName()));
  750. break;
  751. case ERROR_NO_SECURITY_ON_OBJECT:
  752. err.MsgWrite(ErrW,DCT_MSG_SKIPPING_FAT_VOLUME_S,warg);
  753. break;
  754. default:
  755. err.SysMsgWrite(ErrE,rc,DCT_MSG_SKIPPING_PATH_SD,warg,rc );
  756. break;
  757. }
  758. }
  759. }
  760. // Process the shares for this machine
  761. if ( args->TranslateShares() && !args->Cache()->IsCancelled())
  762. {
  763. if ( IsMachineName(warg) )
  764. {
  765. err.MsgWrite(0,DCT_MSG_PROCESSING_SHARES_S,tnode->GetServerName());
  766. ServerResolveShares(tnode->GetServerName(),args,Stats);
  767. }
  768. else if ( IsShareName(warg) )
  769. {
  770. TShareSD sd(warg);
  771. if ( sd.HasSecurity() )
  772. {
  773. if ( args->LogVerbose() )
  774. {
  775. err.MsgWrite(0,DCT_MSG_PROCESSING_SHARE_S,warg);
  776. }
  777. sd.ResolveSD(args,
  778. Stats,
  779. share,
  780. NULL);
  781. }
  782. }
  783. }
  784. }
  785. else
  786. {
  787. // this is a local path
  788. // Verify that the volume is NTFS
  789. DWORD rc2;
  790. //get needed privileges and keep them until the agent removes itself
  791. GetBkupRstrPriv((WCHAR*)NULL);
  792. rc2 = tnode->VerifyPersistentAcls();
  793. switch ( rc2 )
  794. {
  795. case ERROR_SUCCESS:
  796. // Process the path
  797. if ( args->TranslateFiles() )
  798. {
  799. ResolveFilePath(args,
  800. Stats,
  801. tnode->GetPathName(),
  802. true, // isValidAlone
  803. ContainsWildcard(tnode->GetPathName()),
  804. tnode->IsContainer() );
  805. }
  806. break;
  807. case ERROR_NO_SECURITY_ON_OBJECT:
  808. err.MsgWrite(ErrW,DCT_MSG_SKIPPING_FAT_VOLUME_S,warg);
  809. break;
  810. default:
  811. err.SysMsgWrite(ErrE,rc2,DCT_MSG_SKIPPING_PATH_SD,warg,rc2 );
  812. break;
  813. }
  814. }
  815. if ( machine )
  816. {
  817. delete machine;
  818. machine = NULL;
  819. }
  820. }
  821. tenum.Close();
  822. }
  823. else
  824. {
  825. // Translate the entire machine
  826. err.MsgWrite(0,DCT_MSG_LOCAL_TRANSLATION);
  827. if ((args->TranslateFiles() || args->TranslateRecycler()) && !args->Cache()->IsCancelled() )
  828. {
  829. //get needed privileges and keep them until the agent removes itself
  830. GetBkupRstrPriv((WCHAR const*)NULL);
  831. // need to process each drive on this machine
  832. TVolumeEnum vEnum;
  833. vEnum.SetLocalMode(TRUE);
  834. DWORD rc2 = vEnum.Open(NULL,VERIFY_PERSISTENT_ACLS,args->LogVerbose());
  835. if ( rc2 )
  836. {
  837. err.SysMsgWrite(ErrE,rc2,DCT_MSG_ERROR_ACCESSING_LOCAL_DRIVES_D,rc2);
  838. }
  839. else
  840. {
  841. while ( (warg = vEnum.Next()) && !args->Cache()->IsCancelled())
  842. {
  843. err.MsgWrite(0,DCT_MSG_PROCESSING_S,warg);
  844. if ( args->TranslateFiles() )
  845. {
  846. ResolveFilePath(args,
  847. Stats,
  848. warg,
  849. false, // not valid alone
  850. false, // no wildcard
  851. true ); // container
  852. }
  853. if ( args->TranslateRecycler() )
  854. {
  855. TranslateRecycler(args,Stats,warg);
  856. }
  857. }
  858. warg = NULL;
  859. }
  860. vEnum.Close();
  861. }
  862. if ( args->TranslateShares() && !args->Cache()->IsCancelled())
  863. {
  864. err.MsgWrite(0,DCT_MSG_PROCESSING_LOCAL_SHARES,NULL);
  865. ServerResolveShares(NULL,args,Stats);
  866. }
  867. if ( args->TranslatePrinters() && !args->Cache()->IsCancelled())
  868. {
  869. // for printer security translation, we also need to turn on the privilege
  870. if (GetBkupRstrPriv(NULL, TRUE) == FALSE)
  871. err.MsgWrite(ErrE, DCT_MSG_UNABLE_TO_OBTAIN_BACKUP_RESTORE_PRIVILEGES, GetLastError());
  872. err.MsgWrite(0,DCT_MSG_PROCESSING_LOCAL_PRINTERS,NULL);
  873. ServerResolvePrinters(NULL,args,Stats);
  874. // turn off the privilege
  875. if (GetBkupRstrPriv(NULL, FALSE) == FALSE)
  876. err.MsgWrite(ErrW, DCT_MSG_UNABLE_TO_RELEASE_BACKUP_RESTORE_PRIVILEGES, GetLastError());
  877. }
  878. }
  879. Stats->DisplayPath(L"");
  880. } // end if ( ! retcode)
  881. SetErrorMode(errmode);
  882. return retcode;
  883. }