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.

2126 lines
70 KiB

  1. /*Copyright (c) 1995-1999, Mission Critical Software, Inc. All rights reserved.
  2. ===============================================================================
  3. Module - SecTranslator.cpp
  4. System - Domain Consolidation Toolkit.
  5. Author - Christy Boles
  6. Created - 97/06/27
  7. Description - COM object that controls the security translation process.
  8. Reads the settings for the translation and performs the necessary
  9. operations.
  10. Updates -
  11. ===============================================================================
  12. */
  13. // SecTranslator.cpp : Implementation of CSecTranslator
  14. #include "stdafx.h"
  15. #include "WorkObj.h"
  16. #include "SecTrans.h"
  17. #include "Mcs.h"
  18. #include "EaLen.hpp"
  19. #include "BkupRstr.hpp"
  20. #include "exchange.hpp"
  21. #include "ErrDct.hpp"
  22. #include "SDStat.hpp"
  23. #include "sd.hpp"
  24. #include "SecObj.hpp"
  25. #include "LGTrans.h"
  26. #include "RightsTr.h"
  27. #include "RegTrans.h"
  28. #include "BkupRstr.hpp"
  29. #include "TReg.hpp"
  30. #include "TxtSid.h"
  31. #include "GetDcName.h"
  32. #include "folders.h"
  33. using namespace nsFolders;
  34. #include "LSAUtils.h"
  35. #include "Checker.h"
  36. //#import "\bin\DBManager.tlb" no_namespace, named_guids
  37. #import "DBMgr.tlb" no_namespace, named_guids
  38. #import "WorkObj.tlb"
  39. #include "varset_i.c"
  40. #ifdef _DEBUG
  41. #define new DEBUG_NEW
  42. #undef THIS_FILE
  43. static char THIS_FILE[] = __FILE__;
  44. #endif
  45. #if (_WIN32_WINNT < 0x0500)
  46. #define LOGON32_LOGON_NEW_CREDENTIALS 9
  47. #define LOGON32_PROVIDER_WINNT50 3
  48. #endif
  49. #ifndef IStatusObjPtr
  50. _COM_SMARTPTR_TYPEDEF(IStatusObj, __uuidof(IStatusObj));
  51. #endif
  52. /////////////////////////////////////////////////////////////////////////////
  53. // CSecTranslator
  54. #define BACKUP_FAILED 5
  55. #define BAD_PATH 6
  56. #define BAD_LOG 2
  57. #define LEN_SID 200
  58. extern TErrorDct err;
  59. extern TErrorDct errAlt; // this is used for logging errors that occur after dispatcher is launched; use migration.log
  60. extern bool useErrAlt; // whether to use errAlt
  61. // Defined in EnumVols.cpp
  62. bool // ret -true if name begins with "\\" has at least 3 total chars, and no other '\'
  63. IsMachineName(
  64. const LPWSTR name // in -possible machine name to check
  65. );
  66. DWORD // ret- OS return code
  67. GetProgramFilesDirectory(
  68. WCHAR * directory, // out- location of program files directory
  69. WCHAR const * computer // in - computer to find PF directory on
  70. )
  71. {
  72. TRegKey hklm;
  73. TRegKey key;
  74. DWORD rc;
  75. rc = hklm.Connect(HKEY_LOCAL_MACHINE,computer);
  76. if ( ! rc )
  77. {
  78. rc = key.Open(REGKEY_CURRENT_VERSION,&hklm);
  79. }
  80. if ( !rc )
  81. {
  82. rc = key.ValueGetStr(REGVAL_PROGRAM_FILES_DIRECTORY,directory,MAX_PATH * (sizeof WCHAR));
  83. }
  84. return rc;
  85. }
  86. BOOL
  87. IsLocallyInstalled()
  88. {
  89. BOOL bFound;
  90. TRegKey key;
  91. DWORD rc;
  92. rc = key.Open(GET_STRING(IDS_HKLM_DomainAdmin_Key));
  93. if ( ! rc )
  94. {
  95. bFound = TRUE;
  96. }
  97. else
  98. {
  99. bFound = FALSE;
  100. }
  101. return bFound;
  102. }
  103. DWORD // ret- OS return code
  104. GetLocalMachineName(WCHAR * computer)
  105. {
  106. DWORD rc = 0;
  107. WKSTA_INFO_100 * buf = NULL;
  108. rc = NetWkstaGetInfo(NULL,100,(LPBYTE*)&buf);
  109. if ( ! rc )
  110. {
  111. UStrCpy(computer,L"\\\\");
  112. UStrCpy(computer+2,buf->wki100_computername);
  113. NetApiBufferFree(buf);
  114. }
  115. return rc;
  116. }
  117. BOOL
  118. IsThisDispatcherMachine(IVarSet * pVarSet)
  119. {
  120. BOOL bIsIt = FALSE;
  121. _bstr_t dispatcher = pVarSet->get(GET_BSTR(DCTVS_Options_Credentials_Server));
  122. WCHAR localComputer[LEN_Computer] = L"";
  123. GetLocalMachineName(localComputer);
  124. if ( ! UStrICmp(dispatcher,localComputer) )
  125. {
  126. bIsIt = TRUE;
  127. }
  128. return bIsIt;
  129. }
  130. class TSession : public TNode
  131. {
  132. WCHAR server[LEN_Computer];
  133. public:
  134. TSession(WCHAR const * s) { safecopy(server,s); }
  135. WCHAR const * ServerName() { return server;}
  136. };
  137. BOOL
  138. CSecTranslator::EstablishASession(
  139. WCHAR const * serverName // in - computer to establish a session to
  140. )
  141. {
  142. BOOL bSuccess = TRUE;
  143. TSession * pSession = new TSession(serverName);
  144. if (!pSession)
  145. return FALSE;
  146. if ( EstablishSession(serverName,m_domain,m_username,m_password,TRUE) )
  147. {
  148. m_ConnectionList.InsertBottom(pSession);
  149. }
  150. else
  151. {
  152. delete pSession;
  153. bSuccess = FALSE;
  154. err.SysMsgWrite(ErrW,GetLastError(),DCT_MSG_NO_SESSION_SD,serverName,GetLastError());
  155. }
  156. return bSuccess;
  157. }
  158. void
  159. CSecTranslator::CleanupSessions()
  160. {
  161. TNodeListEnum e;
  162. TSession * s;
  163. TSession * snext;
  164. for ( s = (TSession*)e.OpenFirst(&m_ConnectionList) ; s ; s = snext )
  165. {
  166. snext = (TSession*) e.Next();
  167. m_ConnectionList.Remove(s);
  168. // close the session
  169. EstablishSession(s->ServerName(),NULL,NULL,NULL,FALSE);
  170. delete s;
  171. }
  172. e.Close();
  173. }
  174. STDMETHODIMP
  175. CSecTranslator::Process(
  176. IUnknown * pWorkItem // in - varset describing translation options
  177. )
  178. {
  179. HRESULT hr = S_OK;
  180. try
  181. {
  182. IVarSetPtr pVarSet = pWorkItem;
  183. IStatusObjPtr pStatus = pVarSet->get(GET_BSTR(DCTVS_StatusObject));
  184. BOOL bReallyDoEverything = FALSE; // this (though not implemented yet) can be used
  185. // to provide a way to override the default behavior
  186. // of only processing file, etc. security when running as
  187. // local system. This would allow selective translation of items
  188. // on the local machine
  189. _bstr_t text = pVarSet->get(GET_BSTR(DCTVS_Options_Logfile));
  190. _bstr_t text1 = pVarSet->get(GET_BSTR(DCTVS_Options_AlternativeLogfile));
  191. m_Args.LogFile(text);
  192. // Open the log file
  193. // use append mode since other processes may also be using this file
  194. if ( ! err.LogOpen(m_Args.LogFile(),1 /*append*/,0) )
  195. {
  196. return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  197. }
  198. // open the alternative log file if necessary
  199. useErrAlt = false;
  200. if (!text1 == false && text1.length() != 0)
  201. {
  202. if (!errAlt.LogOpen(text1, 1, 0))
  203. return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  204. useErrAlt = true;
  205. }
  206. LoadSettingsFromVarSet(pVarSet);
  207. // Set up the cache
  208. TSDResolveStats stat(m_Args.Cache(),m_Args.PathList(),pVarSet);
  209. if ( pStatus )
  210. {
  211. m_Args.Cache()->SetStatusObject(pStatus);
  212. }
  213. if ( m_Args.Cache()->IsTree() )
  214. {
  215. m_Args.Cache()->ToSorted();
  216. }
  217. m_Args.Cache()->SortedToScrambledTree();
  218. m_Args.Cache()->Sort(&RidComp);
  219. m_Args.Cache()->Balance();
  220. m_Args.Cache()->UnCancel();
  221. //
  222. // Verify that the Cache got the source and target domain information it needs
  223. //
  224. // Note that source and target domain sids are not initialized when using a sid
  225. // mapping file therefore do not need to check the initialized status as the
  226. // initialized status is only checking whether the source and target domain
  227. // sids have been set to a non null value.
  228. //
  229. if ( !m_Args.UsingMapFile() && !m_Args.Cache()->IsInitialized() )
  230. {
  231. err.MsgWrite(ErrS,DCT_MSG_NO_CACHE_INFO);
  232. if (useErrAlt)
  233. errAlt.MsgWrite(ErrS,DCT_MSG_NO_CACHE_INFO);
  234. }
  235. else
  236. {
  237. if ( m_Args.IsLocalSystem() || bReallyDoEverything )
  238. {// Do the required translations
  239. if ( (m_Args.TranslateFiles() || m_Args.TranslateShares() || m_Args.TranslatePrinters() || m_Args.TranslateRecycler())
  240. && !m_Args.Cache()->IsCancelled())
  241. {
  242. // This runs the old FST code
  243. pVarSet->put(GET_BSTR(DCTVS_CurrentOperation),GET_BSTR(IDS_FST_OPERATION_TEXT));
  244. DoResolution(&stat);
  245. }
  246. if ( m_Args.TranslateLocalGroups() && !m_Args.Cache()->IsCancelled() )
  247. {
  248. pVarSet->put(GET_BSTR(DCTVS_CurrentOperation),GET_BSTR(IDS_LGST_OPERATION_TEXT));
  249. DoLocalGroupResolution(&stat);
  250. }
  251. if ( m_Args.TranslateUserRights() && !m_Args.Cache()->IsCancelled() )
  252. {
  253. pVarSet->put(GET_BSTR(DCTVS_CurrentOperation),GET_BSTR(IDS_URST_OPERATION_TEXT));
  254. DoUserRightsTranslation(&stat);
  255. }
  256. if ( m_Args.TranslateRegistry() && !m_Args.Cache()->IsCancelled() )
  257. {
  258. pVarSet->put(GET_BSTR(DCTVS_CurrentOperation),GET_BSTR(IDS_REGST_OPERATION_TEXT));
  259. //get needed privileges and keep them until the agent removes itself
  260. GetBkupRstrPriv((WCHAR*)NULL);
  261. GetPrivilege((WCHAR*)NULL,SE_SECURITY_NAME);
  262. TranslateRegistry(NULL,&m_Args,m_Args.Cache(),&stat);
  263. }
  264. if ( m_Args.TranslateUserProfiles() && !m_Args.Cache()->IsCancelled() )
  265. {
  266. // set the flag to indicate whether we want to allow switching from REPLACE to ADD
  267. // mode for profile translation while the user is logged on
  268. _bstr_t bstrFlag = pVarSet->get(GET_BSTR(DCTVS_Options_AllowSwitchingFromReplaceToAddInProfileTranslation));
  269. if (!bstrFlag == false && !UStrICmp(bstrFlag, GET_STRING(IDS_No)))
  270. {
  271. m_Args.SetAllowingToSwitchFromReplaceToAddModeInProfileTranslation(FALSE);
  272. }
  273. //get needed privileges and keep them until the agent removes itself
  274. GetBkupRstrPriv((WCHAR*)NULL);
  275. GetPrivilege((WCHAR*)NULL,SE_SECURITY_NAME);
  276. TranslateLocalProfiles(&m_Args,m_Args.Cache(),&stat);
  277. }
  278. }
  279. else
  280. {
  281. // do exchange translation
  282. if ( (m_Args.TranslateMailboxes() || m_Args.TranslateContainers()) && !m_Args.Cache()->IsCancelled() )
  283. {
  284. // This will run the old EST code
  285. pVarSet->put(GET_BSTR(DCTVS_CurrentOperation),GET_BSTR(IDS_EST_OPERATION_TEXT));
  286. DoExchangeResolution(&stat,pVarSet);
  287. }
  288. }
  289. }
  290. // indicate the operation is aborted if necessary
  291. if (m_Args.Cache()->IsCancelled())
  292. err.MsgWrite(0, DCT_MSG_OPERATION_ABORTED);
  293. pVarSet->put(GET_BSTR(DCTVS_CurrentOperation),"");
  294. ExportStatsToVarSet(pVarSet,&stat);
  295. if ( *m_CacheFile )
  296. {
  297. BuildCacheFile(m_CacheFile);
  298. }
  299. // Record whether errors occurred
  300. long level = pVarSet->get(GET_BSTR(DCTVS_Results_ErrorLevel));
  301. if ( level < err.GetMaxSeverityLevel() )
  302. {
  303. pVarSet->put(GET_BSTR(DCTVS_Results_ErrorLevel),(LONG)err.GetMaxSeverityLevel());
  304. }
  305. err.LogClose();
  306. if (useErrAlt)
  307. {
  308. errAlt.LogClose();
  309. useErrAlt = false;
  310. }
  311. CleanupSessions();
  312. }
  313. catch (_com_error& ce)
  314. {
  315. hr = ce.Error();
  316. err.SysMsgWrite(ErrS, hr, DCT_MSG_SECURITY_TRANSLATOR_UNABLE_TO_CONTINUE);
  317. }
  318. catch (...)
  319. {
  320. hr = E_UNEXPECTED;
  321. err.SysMsgWrite(ErrS, hr, DCT_MSG_SECURITY_TRANSLATOR_UNABLE_TO_CONTINUE);
  322. }
  323. return hr;
  324. }
  325. void
  326. CSecTranslator::LoadSettingsFromVarSet(
  327. IVarSet * pVarSet // in - varset containing settings
  328. )
  329. {
  330. MCSASSERT(pVarSet);
  331. _bstr_t text;
  332. _bstr_t text2;
  333. DWORD val;
  334. try
  335. {
  336. m_Args.Reset();
  337. text = pVarSet->get(GET_BSTR(DCTVS_Options_LocalProcessingOnly));
  338. if ( !text == false && !UStrICmp(text,GET_STRING(IDS_YES)) )
  339. {
  340. err.MsgWrite(0,DCT_MSG_LOCAL_MODE);
  341. m_LocalOnly = TRUE;
  342. m_Args.SetLocalMode(TRUE);
  343. text = pVarSet->get(GET_BSTR(DCTVS_Options_SourceDomainSid));
  344. safecopy(m_SourceSid,(WCHAR const *)text);
  345. text = pVarSet->get(GET_BSTR(DCTVS_Options_TargetDomainSid));
  346. safecopy(m_TargetSid,(WCHAR const *)text);
  347. }
  348. text = pVarSet->get(GET_BSTR(DCTVS_Options_SourceDomain));
  349. m_Args.Source(text);
  350. text = pVarSet->get(GET_BSTR(DCTVS_Options_TargetDomain));
  351. m_Args.Target(text);
  352. val = (LONG)pVarSet->get(GET_BSTR(DCTVS_Options_LogLevel));
  353. if ( val )
  354. m_Args.SetLogging(val);
  355. val = (LONG)pVarSet->get(L"Security.DebugLogLevel");
  356. if ( val )
  357. m_Args.SetLogging(val);
  358. text = pVarSet->get(GET_BSTR(DCTVS_Options_NoChange));
  359. if ( ! UStrICmp(text,GET_STRING(IDS_YES)) )
  360. {
  361. m_Args.SetWriteChanges(FALSE);
  362. }
  363. else
  364. {
  365. m_Args.SetWriteChanges(TRUE);
  366. }
  367. text = pVarSet->get(GET_BSTR(DCTVS_Security_TranslationMode));
  368. if ( !UStrICmp(text,GET_STRING(IDS_Add)) )
  369. {
  370. m_Args.SetTranslationMode(ADD_SECURITY);
  371. }
  372. else if (! UStrICmp(text,GET_STRING(IDS_Replace)) )
  373. {
  374. m_Args.SetTranslationMode(REPLACE_SECURITY);
  375. }
  376. else if ( ! UStrICmp(text,GET_STRING(IDS_Remove)) )
  377. {
  378. m_Args.SetTranslationMode(REMOVE_SECURITY);
  379. }
  380. else
  381. {
  382. // Incorrect value - don't need to log this, just use replace
  383. // the log will show replace as the translation mode
  384. // err.MsgWrite(ErrE,DCT_MSG_BAD_TRANSLATION_MODE_S,(WCHAR*)text);
  385. }
  386. text = pVarSet->get(GET_BSTR(DCTVS_Security_TranslateFiles));
  387. if ( !UStrICmp(text,GET_STRING(IDS_YES)) )
  388. {
  389. m_Args.TranslateFiles(TRUE);
  390. }
  391. else
  392. {
  393. m_Args.TranslateFiles(FALSE);
  394. }
  395. text = pVarSet->get(GET_BSTR(DCTVS_Security_TranslateShares));
  396. if ( ! UStrICmp(text,GET_STRING(IDS_YES)) )
  397. {
  398. m_Args.TranslateShares(TRUE);
  399. }
  400. else
  401. {
  402. m_Args.TranslateShares(FALSE);
  403. }
  404. text = pVarSet->get(GET_BSTR(DCTVS_Security_TranslatePrinters));
  405. if ( ! UStrICmp(text,GET_STRING(IDS_YES)) )
  406. {
  407. m_Args.TranslatePrinters(TRUE);
  408. }
  409. else
  410. {
  411. m_Args.TranslatePrinters(FALSE);
  412. }
  413. text = pVarSet->get(GET_BSTR(DCTVS_Security_TranslateUserProfiles));
  414. if ( ! UStrICmp(text,GET_STRING(IDS_YES)) )
  415. {
  416. m_Args.TranslateUserProfiles(TRUE);
  417. m_Args.TranslateRecycler(TRUE);
  418. }
  419. else
  420. {
  421. m_Args.TranslateUserProfiles(FALSE);
  422. m_Args.TranslateRecycler(FALSE);
  423. }
  424. text = pVarSet->get(GET_BSTR(DCTVS_Security_TranslateLocalGroups));
  425. if ( !UStrICmp(text,GET_STRING(IDS_YES)) )
  426. {
  427. m_Args.TranslateLocalGroups(TRUE);
  428. }
  429. else
  430. {
  431. m_Args.TranslateLocalGroups(FALSE);
  432. }
  433. text = pVarSet->get(GET_BSTR(DCTVS_Security_TranslateRegistry));
  434. if (! UStrICmp(text,GET_STRING(IDS_YES)) )
  435. {
  436. m_Args.TranslateRegistry(TRUE);
  437. }
  438. else
  439. {
  440. m_Args.TranslateRegistry(FALSE);
  441. }
  442. val = (LONG)pVarSet->get(GET_BSTR(DCTVS_Servers_NumItems));
  443. for ( int i = 0 ; i < (int)val ; i++ )
  444. {
  445. WCHAR key[MAX_PATH];
  446. DWORD flags = 0;
  447. _bstr_t bStr;
  448. swprintf(key,GET_STRING(DCTVSFmt_Servers_D),i);
  449. bStr = key;
  450. text = pVarSet->get(bStr);
  451. if ( text.length() )
  452. {
  453. m_Args.PathList()->AddPath(text,flags);
  454. }
  455. }
  456. text = pVarSet->get(GET_BSTR(DCTVS_Security_GatherInformation));
  457. if ( !UStrICmp(text,GET_STRING(IDS_YES)) )
  458. {
  459. m_Args.Cache()->AddIfNotFound(TRUE);
  460. m_Args.SetWriteChanges(FALSE);
  461. m_Args.SetLogging(m_Args.LogSettings() & ~FILESTATS);
  462. }
  463. else
  464. {
  465. m_Args.Cache()->AddIfNotFound(FALSE);
  466. }
  467. // Exchange Security Translation settings
  468. text = pVarSet->get(GET_BSTR(DCTVS_Security_TranslateMailboxes));
  469. if ( text.length() )
  470. {
  471. m_Args.TranslateMailboxes(TRUE);
  472. safecopy(m_Container,(WCHAR*)text);
  473. text = pVarSet->get(GET_BSTR(DCTVS_Security_MapiProfile));
  474. safecopy(m_Profile,(WCHAR*)text);
  475. }
  476. else
  477. {
  478. m_Args.TranslateMailboxes(FALSE);
  479. }
  480. text = pVarSet->get(GET_BSTR(DCTVS_Security_TranslateContainers));
  481. if ( text.length() )
  482. {
  483. m_Args.TranslateContainers(TRUE);
  484. if ( ((WCHAR*)text)[0] == L'\\' && ((WCHAR*)text)[1] == L'\\' )
  485. safecopy(m_exchServer,(WCHAR*)text+2);
  486. else
  487. safecopy(m_exchServer,(WCHAR*)text);
  488. }
  489. else
  490. {
  491. m_Args.TranslateContainers(FALSE);
  492. }
  493. text = pVarSet->get(GET_BSTR(DCTVS_Security_TranslateUserRights));
  494. if ( !UStrICmp(text,GET_STRING(IDS_YES)) )
  495. {
  496. m_Args.TranslateUserRights(TRUE);
  497. }
  498. text = pVarSet->get(GET_BSTR(DCTVS_Security_BuildCacheFile));
  499. if ( text.length() )
  500. {
  501. safecopy(m_CacheFile,(WCHAR*)text);
  502. }
  503. // Check for inconsistent arguments
  504. // Load the cache
  505. // There are 4 possible ways to populate the cache
  506. // 1. Use the list from the migrated objects table in our database
  507. // 2. We are given a list of accounts in the VarSet, under "Accounts.". This allows for renaming, but requires the most space
  508. // 3. We are given an input file that was generated by AR, in "Accounts.InputFile". This also allows for renaming, with less overall memory use.
  509. // 4. We are given a sid mapping, comma-seperated, file with source and target sids.
  510. text = pVarSet->get(GET_BSTR(DCTVS_Security_BuildCacheFile));
  511. text2 = pVarSet->get(GET_BSTR(DCTVS_AccountOptions_SecurityInputMOT));
  512. //if list is in the migrated objects table
  513. if ((!m_LocalOnly) && (!UStrICmp(text2,GET_STRING(IDS_YES))))
  514. {
  515. LoadMigratedObjects(pVarSet);
  516. }
  517. //else if a sid mapping file is being used
  518. else if ((!m_LocalOnly) && (UStrICmp(text2,GET_STRING(IDS_YES))))
  519. {
  520. m_Args.SetUsingMapFile(TRUE); //set the arg flag to indicate use of map file
  521. text2 = pVarSet->get(GET_BSTR(DCTVS_AccountOptions_SecurityMapFile));
  522. if (!LoadCacheFromMapFile(text2, pVarSet))
  523. _com_issue_error(E_FAIL);
  524. }
  525. // took out the not because gather information sets this to false.
  526. //else if ( !m_Args.Cache()->AddIfNotFound() ) // skip loading the cache if we're gathering information
  527. else if ( m_Args.Cache()->AddIfNotFound() ) // skip loading the cache if we're gathering information
  528. {
  529. if ( m_LocalOnly )
  530. {
  531. m_Args.Cache()->SetSourceAndTargetDomainsWithSids(m_Args.Source(),m_SourceSid,m_Args.Target(),m_TargetSid);
  532. }
  533. else
  534. {
  535. m_Args.Cache()->SetSourceAndTargetDomains(m_Args.Source(),m_Args.Target());
  536. }
  537. }
  538. else
  539. {
  540. text = pVarSet->get(GET_BSTR(DCTVS_Accounts_InputFile));
  541. if ( text.length() )
  542. {
  543. LoadCacheFromFile(text,pVarSet);
  544. }
  545. else
  546. {
  547. LoadCacheFromVarSet(pVarSet);
  548. }
  549. }
  550. }
  551. catch ( ... )
  552. {
  553. err.MsgWrite(ErrS,DCT_MSG_EXCEPTION_READING_VARSET);
  554. throw;
  555. }
  556. }
  557. void
  558. CSecTranslator::ExportStatsToVarSet(
  559. IVarSet * pVarSet, // in - varset to write stats to
  560. TSDResolveStats * stat // in - object containing stats
  561. )
  562. {
  563. _bstr_t filename;
  564. filename = pVarSet->get(GET_BSTR(DCTVS_Security_ReportAccountReferences));
  565. stat->Report(m_Args.LogSummary(),m_Args.LogAccountDetails(),m_Args.LogPathDetails());
  566. if ( m_Args.NoChange() )
  567. {
  568. err.MsgWrite(0,DCT_MSG_NO_CHANGE_MODE);
  569. }
  570. stat->ReportToVarSet(pVarSet,m_Args.LogSettings() & SUMMARYSTATS);
  571. if ( filename.length() )
  572. {
  573. err.MsgWrite(0,DCT_MSG_EXPORTING_ACCOUNT_REFS_S,(WCHAR*)filename);
  574. m_Args.Cache()->ReportAccountReferences((WCHAR*)filename);
  575. }
  576. long level = pVarSet->get(GET_BSTR(DCTVS_Results_ErrorLevel));
  577. if ( level < err.GetMaxSeverityLevel() )
  578. {
  579. pVarSet->put(GET_BSTR(DCTVS_Results_ErrorLevel),(LONG)err.GetMaxSeverityLevel());
  580. }
  581. }
  582. void
  583. CSecTranslator::DoResolution(
  584. TSDResolveStats * stat // in - object to write translation stats to
  585. )
  586. {
  587. // display confirmation message if writing changes
  588. int result;
  589. if (!m_Args.Cache()->IsCancelled())
  590. result = ResolveAll(&m_Args,stat);
  591. }
  592. void
  593. CSecTranslator::DoLocalGroupResolution(
  594. TSDResolveStats * stat // in - object to write translation stats to
  595. )
  596. {
  597. DWORD rc;
  598. TNodeListEnum tenum;
  599. TPathNode * tnode;
  600. if (!m_Args.Cache()->IsCancelled())
  601. {
  602. if ( m_LocalOnly )
  603. {
  604. err.MsgWrite(0,DCT_MSG_TRANSLATING_LOCAL_GROUPS);
  605. rc = TranslateLocalGroups(NULL,&m_Args,m_Args.Cache(),stat);
  606. }
  607. else
  608. { // Enumerate the machines in the pathlist
  609. for (tnode = (TPathNode *)tenum.OpenFirst((TNodeList *)m_Args.PathList())
  610. ; tnode && !m_Args.Cache()->IsCancelled()
  611. ; tnode = (TPathNode *)tenum.Next() )
  612. {
  613. if ( IsMachineName(tnode->GetPathName()) )
  614. {
  615. err.MsgWrite(0,DCT_MSG_TRANSLATING_LOCAL_GROUPS_ON_S,tnode->GetPathName());
  616. rc = TranslateLocalGroups(tnode->GetPathName(),&m_Args,m_Args.Cache(),stat);
  617. }
  618. }
  619. }
  620. }
  621. if (m_Args.Cache()->IsCancelled())
  622. err.MsgWrite(0, DCT_MSG_OPERATION_ABORTED_LOCAL_GROUPS);
  623. tenum.Close();
  624. }
  625. void
  626. CSecTranslator::DoUserRightsTranslation(
  627. TSDResolveStats * stat // in - object to write stats to
  628. )
  629. {
  630. DWORD rc;
  631. TNodeListEnum tenum;
  632. TPathNode * tnode;
  633. if (!m_Args.Cache()->IsCancelled())
  634. {
  635. if ( m_LocalOnly )
  636. {
  637. err.MsgWrite(0,DCT_MSG_TRANSLATING_USER_RIGHTS);
  638. rc = TranslateUserRights(NULL,&m_Args,m_Args.Cache(),stat);
  639. }
  640. else
  641. { // Enumerate the machines in the pathlist
  642. for (tnode = (TPathNode *)tenum.OpenFirst((TNodeList *)m_Args.PathList())
  643. ; tnode && !m_Args.Cache()->IsCancelled()
  644. ; tnode = (TPathNode *)tenum.Next() )
  645. {
  646. if ( IsMachineName(tnode->GetPathName()) )
  647. {
  648. err.MsgWrite(0,DCT_MSG_TRANSLATING_RIGHTS_ON_S,tnode->GetPathName());
  649. rc = TranslateUserRights(tnode->GetPathName(),&m_Args,m_Args.Cache(),stat);
  650. }
  651. }
  652. }
  653. }
  654. if (m_Args.Cache()->IsCancelled())
  655. err.MsgWrite(0, DCT_MSG_OPERATION_ABORTED_USER_RIGHTS);
  656. tenum.Close();
  657. }
  658. BOOL
  659. CSecTranslator::LoadCacheFromVarSet(
  660. IVarSet * pVarSet // in - varset containing account mapping
  661. )
  662. {
  663. BOOL bSuccess = TRUE;
  664. _bstr_t text;
  665. if ( m_LocalOnly )
  666. {
  667. m_Args.Cache()->SetSourceAndTargetDomainsWithSids(m_Args.Source(),m_SourceSid,m_Args.Target(),m_TargetSid);
  668. }
  669. else
  670. {
  671. m_Args.Cache()->SetSourceAndTargetDomains(m_Args.Source(),m_Args.Target());
  672. }
  673. m_Args.Cache()->ToSorted();
  674. // no wildcard filter specified. Use the explicit list of accounts
  675. long numAccounts = pVarSet->get(GET_BSTR(DCTVS_Accounts_NumItems));
  676. for ( int i = 0 ; i < numAccounts ; i++ )
  677. {
  678. WCHAR key[LEN_Path];
  679. WCHAR name[LEN_Account];
  680. WCHAR targetName[LEN_Account];
  681. WCHAR type[LEN_Path];
  682. short sType;
  683. swprintf(key,GET_STRING(DCTVSFmt_Accounts_D),i);
  684. text = pVarSet->get(key);
  685. safecopy(name,(WCHAR*)text);
  686. swprintf(key,GET_STRING(DCTVSFmt_Accounts_TargetName_D),i);
  687. text = pVarSet->get(key);
  688. safecopy(targetName,(WCHAR*)text);
  689. swprintf(key,GET_STRING(DCTVSFmt_Accounts_Type_D),i);
  690. text = pVarSet->get(key);
  691. safecopy(type,(WCHAR*)text);
  692. if (!UStrICmp(type,L"user") || !UStrICmp(type,L"inetOrgPerson"))
  693. sType = EA_AccountUser;
  694. else if (! UStrICmp(type,L"group") )
  695. sType = EA_AccountGroup;
  696. else
  697. sType = 0;
  698. m_Args.Cache()->InsertLast(name,0,targetName,0,sType);
  699. }
  700. if ( bSuccess && ! m_LocalOnly )
  701. {
  702. bSuccess = GetRIDsFromEA();
  703. }
  704. m_Args.Cache()->VerifyTargetSids();
  705. return bSuccess;
  706. }
  707. // this reads the migrated objects table from the database, and
  708. // constructs a mapping file to be used for security translation
  709. HRESULT CSecTranslator::LoadMigratedObjects(IVarSet* pVarSetIn)
  710. {
  711. HRESULT hr = S_OK;
  712. if ( m_LocalOnly )
  713. {
  714. m_Args.Cache()->SetSourceAndTargetDomainsWithSids(m_Args.Source(),m_SourceSid,m_Args.Target(),m_TargetSid);
  715. }
  716. else
  717. {
  718. m_Args.Cache()->SetSourceAndTargetDomains(m_Args.Source(),m_Args.Target());
  719. }
  720. m_Args.Cache()->ToSorted();
  721. //
  722. // Create instance of database manager.
  723. //
  724. IIManageDBPtr spDB;
  725. hr = spDB.CreateInstance(CLSID_IManageDB);
  726. if (SUCCEEDED(hr))
  727. {
  728. //
  729. // Retrieve objects that have been migrated from the source domain to the target domain.
  730. //
  731. IVarSetPtr spVarSet(CLSID_VarSet);
  732. hr = spDB->raw_GetMigratedObjectsForSecurityTranslation(
  733. _bstr_t(m_Args.Source()),
  734. _bstr_t(m_Args.Target()),
  735. IUnknownPtr(spVarSet)
  736. );
  737. if (SUCCEEDED(hr))
  738. {
  739. //
  740. // Retrieve data for each object and insert into cache.
  741. //
  742. WCHAR szKey[MAX_PATH];
  743. long lCount = spVarSet->get(L"MigratedObjects");
  744. for (long lIndex = 0; lIndex < lCount; lIndex++)
  745. {
  746. // retrieve object's data from VarSet
  747. swprintf(szKey, L"MigratedObjects.%ld.SourceSamName", lIndex);
  748. _bstr_t strSrcSam = spVarSet->get(szKey);
  749. swprintf(szKey, L"MigratedObjects.%ld.TargetSamName", lIndex);
  750. _bstr_t strTgtSam = spVarSet->get(szKey);
  751. swprintf(szKey, L"MigratedObjects.%ld.Type", lIndex);
  752. _bstr_t strType = spVarSet->get(szKey);
  753. swprintf(szKey, L"MigratedObjects.%ld.SourceRid", lIndex);
  754. long lSrcRid = spVarSet->get(szKey);
  755. swprintf(szKey, L"MigratedObjects.%ld.TargetRid", lIndex);
  756. long lTgtRid = spVarSet->get(szKey);
  757. // convert type to cache specific type
  758. short sType;
  759. if (UStrICmp(strType, L"user") == 0)
  760. {
  761. sType = EA_AccountUser;
  762. }
  763. else if (UStrICmp(strType, L"group") == 0)
  764. {
  765. sType = EA_AccountGroup;
  766. }
  767. else
  768. {
  769. sType = 0;
  770. }
  771. // insert object's data into cache
  772. m_Args.Cache()->InsertLast(strSrcSam, lSrcRid, strTgtSam, lTgtRid, sType);
  773. }
  774. }
  775. }
  776. m_Args.Cache()->VerifyTargetSids();
  777. return hr;
  778. }
  779. BOOL
  780. CSecTranslator::BuildCacheFile(
  781. WCHAR const * filename // in - file to write account mapping to
  782. )
  783. {
  784. BOOL bSuccess = TRUE;
  785. FILE * pFile;
  786. m_Args.Cache()->ToSorted();
  787. TNodeListEnum e;
  788. TRidNode * node;
  789. WCHAR type[LEN_Path];
  790. pFile = _wfopen(filename,L"wb");
  791. if ( pFile )
  792. {
  793. for ( node = (TRidNode*) e.OpenFirst(m_Args.Cache() ); node ; node = (TRidNode*)e.Next() )
  794. {
  795. switch ( node->Type() )
  796. {
  797. case EA_AccountUser:
  798. safecopy(type,L"user");
  799. break;
  800. case EA_AccountGroup:
  801. case EA_AccountGGroup:
  802. case EA_AccountLGroup:
  803. safecopy(type,L"group");
  804. break;
  805. default:
  806. type[0] = 0;
  807. break;
  808. }
  809. // if (!UStrICmp(node->GetAcctName(),node->GetTargetAcctName()))
  810. if ((UStrICmp(node->GetSrcDomSid(),L"")) && (UStrICmp(node->GetTgtDomSid(),L"")))
  811. {
  812. //account and domain names could be empty when using a sid
  813. //mapping file for security translation. A later scanf by
  814. //the agent will fail on a NULL name, so we will store "(UnKnown)"
  815. //instead and deal with that on the scanf-side
  816. WCHAR ssname[MAX_PATH];
  817. wcscpy(ssname, node->GetAcctName());
  818. if (!wcslen(ssname))
  819. wcscpy(ssname, GET_STRING(IDS_UnknownSid));
  820. WCHAR stname[MAX_PATH];
  821. wcscpy(stname, node->GetTargetAcctName());
  822. if (!wcslen(stname))
  823. wcscpy(stname, GET_STRING(IDS_UnknownSid));
  824. WCHAR ssdname[MAX_PATH];
  825. wcscpy(ssdname, node->GetSrcDomName());
  826. if (!wcslen(ssdname))
  827. wcscpy(ssdname, GET_STRING(IDS_UnknownSid));
  828. WCHAR stdname[MAX_PATH];
  829. wcscpy(stdname, node->GetTgtDomName());
  830. if (!wcslen(stdname))
  831. wcscpy(stdname, GET_STRING(IDS_UnknownSid));
  832. fwprintf(pFile,L"%s\t%s\t%s\t%lx\t%lx\t%lx\t%s\t%s\t%s\t%s\r\n",ssname,stname,type,
  833. node->GetStatus(), node->SrcRid(), node->TgtRid(), node->GetSrcDomSid(), node->GetTgtDomSid(),
  834. ssdname, stdname);
  835. }
  836. else
  837. {
  838. fwprintf(pFile,L"%s\t%s\t%s\t%lx\t%lx\t%lx\r\n",node->GetAcctName(),node->GetTargetAcctName(),type,
  839. (DWORD)node->GetStatus(), node->SrcRid(), node->TgtRid());
  840. }
  841. }
  842. e.Close();
  843. fclose(pFile);
  844. }
  845. else
  846. {
  847. bSuccess = FALSE;
  848. // DWORD rc = GetLastError();
  849. }
  850. return bSuccess;
  851. }
  852. BOOL
  853. CSecTranslator::LoadCacheFromFile(
  854. WCHAR const * filename, // in - file to read account mapping from
  855. IVarSet * pVarSet // in - pointer to varset
  856. )
  857. {
  858. BOOL bSuccess = TRUE;
  859. _bstr_t text;
  860. FILE * pFile;
  861. WCHAR sourceName[LEN_Account];
  862. WCHAR targetName[LEN_Account];
  863. WCHAR sourceDomSid[MAX_PATH];
  864. WCHAR targetDomSid[MAX_PATH];
  865. WCHAR sourceDomName[MAX_PATH];
  866. WCHAR targetDomName[MAX_PATH];
  867. WCHAR type[LEN_Account];
  868. DWORD status;
  869. int count = 0;
  870. BOOL bNeedRids = FALSE;
  871. WCHAR path[MAX_PATH];
  872. WCHAR temp[MAX_PATH];
  873. BOOL bUseMapFile = FALSE;
  874. WCHAR* pFullPathBuffer = NULL;
  875. text = pVarSet->get(GET_BSTR(DCTVS_AccountOptions_SecurityInputMOT));
  876. if (!text || UStrICmp(text,GET_STRING(IDS_YES)))
  877. {
  878. m_Args.SetUsingMapFile(TRUE); //set the arg flag to indicate use of map file
  879. bUseMapFile = TRUE;
  880. }
  881. if ( m_LocalOnly )
  882. {
  883. // we need to set source and target domain information for the cache
  884. // if we're not using migrated object table
  885. if (!bUseMapFile)
  886. m_Args.Cache()->SetSourceAndTargetDomainsWithSids(m_Args.Source(),m_SourceSid,m_Args.Target(),m_TargetSid);
  887. // find the module path
  888. DWORD rc = GetModuleFileName(NULL,temp,DIM(temp));
  889. if ( rc )
  890. {
  891. // Generally, our DCTCache file will be in the same directory as our EXE.
  892. // This is true 1) when agent is dispatched to clean machine (all will be in OnePointDomainAgent directory)
  893. // and also 2) when agent is dispatched to the local ADMT machine (all will be in Program Files\ADMT directory)
  894. // The exception is when the agent is dispatched to a remote machine where ADMT is also installed.
  895. WCHAR * slash = wcsrchr(temp,L'\\');
  896. UStrCpy(slash+1,filename);
  897. // Check whether ADMT is locally installed here
  898. if ( IsLocallyInstalled() && !IsThisDispatcherMachine(pVarSet) )
  899. {
  900. // ADMT is installed here, so we're running from the binaries
  901. // in the Program files\ADMT directory
  902. // However, our cache file should be in %Program Files%\\OnePOintDomainAgent
  903. GetProgramFilesDirectory(temp,NULL);
  904. UStrCpy(temp+UStrLen(temp),L"\\OnePointDomainAgent\\");
  905. UStrCpy(temp+UStrLen(temp),filename);
  906. }
  907. }
  908. else
  909. {
  910. rc = GetLastError();
  911. err.DbgMsgWrite(0,L"Couldn't get the module filename, rc=%ld",rc);
  912. swprintf(temp,L"..\\OnePointDomainAgent\\%ls",filename);
  913. }
  914. pFullPathBuffer = _wfullpath(path,temp,MAX_PATH);
  915. if(!pFullPathBuffer)
  916. {
  917. // we should bail out here, since we could not get the file path name
  918. err.MsgWrite(0, DCT_MSG_GET_FULL_PATH_FAILED, temp);
  919. return FALSE;
  920. }
  921. }
  922. else
  923. {
  924. // we need to set source and target domain information for the cache
  925. // if we're not using migrated object table
  926. if (!bUseMapFile)
  927. m_Args.Cache()->SetSourceAndTargetDomains(m_Args.Source(),m_Args.Target());
  928. pFullPathBuffer = _wfullpath(path,filename,MAX_PATH);
  929. if(!pFullPathBuffer)
  930. {
  931. // we should bail out here, since we could not get the file path name
  932. err.MsgWrite(0, DCT_MSG_GET_FULL_PATH_FAILED, filename);
  933. return FALSE;
  934. }
  935. }
  936. m_Args.Cache()->ToSorted();
  937. // The input file should have the format:
  938. // SourceName, TargetName, Type, Status [,rid1, rid2]
  939. pFile = _wfopen(path,L"rb");
  940. if ( pFile )
  941. {
  942. int result;
  943. do
  944. {
  945. DWORD rid1 = 0;
  946. DWORD rid2 = 0;
  947. if (!bUseMapFile)
  948. {
  949. result = fwscanf(pFile,L"%[^\t]\t%[^\t]\t%[^\t]\t%lx\t%lx\t%lx\r\n",
  950. sourceName,targetName,type,&status,&rid1,&rid2);
  951. if ( result < 4 )
  952. break;
  953. }
  954. else
  955. {
  956. result = fwscanf(pFile,L"%[^\t]\t%[^\t]\t%[^\t]\t%lx\t%lx\t%lx\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\r]\r\n",
  957. sourceName,targetName,type,&status,&rid1,&rid2,sourceDomSid,targetDomSid,
  958. sourceDomName, targetDomName);
  959. if ( result < 8 )
  960. break;
  961. }
  962. short lType = 0;
  963. if ( !UStrICmp(type,L"user") )
  964. lType = EA_AccountUser;
  965. else if ( ! UStrICmp(type,L"group") )
  966. lType = EA_AccountGroup;
  967. if (!bUseMapFile)
  968. m_Args.Cache()->InsertLast(sourceName,rid1,targetName,rid2,lType, status);
  969. else
  970. m_Args.Cache()->InsertLastWithSid(sourceName,sourceDomSid,sourceDomName,rid1,
  971. targetName,targetDomSid,targetDomName,rid2,lType, status);
  972. count++;
  973. if ( ! rid1 | ! rid2 )
  974. {
  975. bNeedRids = TRUE;
  976. }
  977. } while ( result >= 4 ); // 4 fields read and assigned
  978. if ( result )
  979. {
  980. err.MsgWrite(ErrS,DCT_MSG_ERROR_READING_INPUT_FILE_S,path);
  981. }
  982. err.MsgWrite(0,DCT_MSG_ACCOUNTS_READ_FROM_FILE_DS,count,path);
  983. fclose(pFile);
  984. }
  985. else
  986. {
  987. err.MsgWrite(ErrS,DCT_MSG_ERROR_OPENING_FILE_S,path);
  988. bSuccess = FALSE;
  989. }
  990. if ( bSuccess && bNeedRids && ! m_LocalOnly)
  991. {
  992. bSuccess = GetRIDsFromEA();
  993. }
  994. return bSuccess;
  995. }
  996. // This doesn't get RIDs from EA any more, since we have removed dependencies on MCS products.
  997. // Instead, we use the Net APIs to get this information
  998. BOOL CSecTranslator::GetRIDsFromEA()
  999. {
  1000. BOOL bSuccess = TRUE;
  1001. // set the cache to a tree sorted by name
  1002. m_Args.Cache()->SortedToScrambledTree();
  1003. m_Args.Cache()->Sort(&CompN);
  1004. // do NQDI to get RIDS for accounts
  1005. DWORD rc = 0;
  1006. NET_DISPLAY_USER * pUser = NULL;
  1007. NET_DISPLAY_GROUP * pGroup = NULL;
  1008. DWORD count = 0;
  1009. DWORD resume = 0;
  1010. TRidNode * pNode = NULL;
  1011. // Get source rids for users
  1012. do
  1013. {
  1014. rc = NetQueryDisplayInformation(m_Args.Cache()->GetSourceDCName(),1,resume,5000,100000,&count,(void**)&pUser);
  1015. if ( 0 == rc || ERROR_MORE_DATA == rc )
  1016. {
  1017. for ( DWORD i = 0 ; i < count ; i++ )
  1018. {
  1019. // see if this account is in the cache
  1020. pNode = (TRidNode*)m_Args.Cache()->Find(&vNameComp,pUser[i].usri1_name);
  1021. if ( pNode )
  1022. {
  1023. pNode->SrcRid(pUser[i].usri1_user_id);
  1024. }
  1025. }
  1026. if ( count )
  1027. {
  1028. resume = pUser[count-1].usri1_next_index;
  1029. }
  1030. else
  1031. {
  1032. // no items were returned - get out of here
  1033. break;
  1034. }
  1035. NetApiBufferFree(pUser);
  1036. }
  1037. } while ( rc == ERROR_MORE_DATA );
  1038. count = 0;
  1039. resume = 0;
  1040. // Get source rids for global groups
  1041. do
  1042. {
  1043. rc = NetQueryDisplayInformation(m_Args.Cache()->GetSourceDCName(),3,resume,5000,100000,&count,(void**)&pGroup);
  1044. if ( 0 == rc || ERROR_MORE_DATA == rc )
  1045. {
  1046. for ( DWORD i = 0 ; i < count ; i++ )
  1047. {
  1048. // see if this account is in the cache
  1049. pNode = (TRidNode*)m_Args.Cache()->Find(&vNameComp,pGroup[i].grpi3_name);
  1050. if ( pNode )
  1051. {
  1052. pNode->SrcRid(pGroup[i].grpi3_group_id);
  1053. }
  1054. }
  1055. if ( count )
  1056. {
  1057. resume = pGroup[count-1].grpi3_next_index;
  1058. }
  1059. else
  1060. {
  1061. // no items were returned - get out of here
  1062. break;
  1063. }
  1064. NetApiBufferFree(pGroup);
  1065. }
  1066. } while ( rc == ERROR_MORE_DATA );
  1067. count = 0;
  1068. resume = 0;
  1069. // Get target rids for users
  1070. // set the cache to a tree sorted by target name
  1071. m_Args.Cache()->ToSorted();
  1072. m_Args.Cache()->SortedToScrambledTree();
  1073. m_Args.Cache()->Sort(&CompTargetN);
  1074. do
  1075. {
  1076. rc = NetQueryDisplayInformation(m_Args.Cache()->GetTargetDCName(),1,resume,5000,100000,&count,(void**)&pUser);
  1077. if ( 0 == rc || ERROR_MORE_DATA == rc )
  1078. {
  1079. for ( DWORD i = 0 ; i < count ; i++ )
  1080. {
  1081. // see if this account is in the cache
  1082. pNode = (TRidNode*)m_Args.Cache()->Find(&vTargetNameComp,pUser[i].usri1_name);
  1083. if ( pNode )
  1084. {
  1085. pNode->TgtRid(pUser[i].usri1_user_id);
  1086. }
  1087. }
  1088. if ( count )
  1089. {
  1090. resume = pUser[count-1].usri1_next_index;
  1091. }
  1092. else
  1093. {
  1094. // no items were returned - get out of here
  1095. break;
  1096. }
  1097. NetApiBufferFree(pUser);
  1098. }
  1099. } while ( rc == ERROR_MORE_DATA );
  1100. // TODO: Add error message if rc != 0
  1101. count = 0;
  1102. resume = 0;
  1103. // Get target rids for global groups
  1104. do
  1105. {
  1106. rc = NetQueryDisplayInformation(m_Args.Cache()->GetTargetDCName(),3,resume,5000,100000,&count,(void**)&pGroup);
  1107. if ( 0 == rc || ERROR_MORE_DATA == rc )
  1108. {
  1109. for ( DWORD i = 0 ; i < count ; i++ )
  1110. {
  1111. // see if this account is in the cache
  1112. pNode = (TRidNode*)m_Args.Cache()->Find(&vTargetNameComp,pGroup[i].grpi3_name);
  1113. if ( pNode )
  1114. {
  1115. pNode->TgtRid(pGroup[i].grpi3_group_id);
  1116. }
  1117. }
  1118. if ( count )
  1119. {
  1120. resume = pGroup[count-1].grpi3_next_index;
  1121. }
  1122. else
  1123. {
  1124. // no items were returned - get out of here
  1125. break;
  1126. }
  1127. NetApiBufferFree(pGroup);
  1128. }
  1129. } while ( rc == ERROR_MORE_DATA );
  1130. // sort back to regular source name order
  1131. m_Args.Cache()->ToSorted();
  1132. m_Args.Cache()->SortedToScrambledTree();
  1133. m_Args.Cache()->Sort(&CompN);
  1134. // get source and target rids for local groups
  1135. TNodeTreeEnum tEnum;
  1136. BYTE sid[LEN_SID];
  1137. DWORD lenSid;
  1138. WCHAR domain[LEN_Domain];
  1139. DWORD lenDomain;
  1140. SID_NAME_USE snu;
  1141. for ( pNode = (TRidNode*)tEnum.OpenFirst(m_Args.Cache()) ; pNode ; pNode = (TRidNode*) tEnum.Next() )
  1142. {
  1143. if ( ! pNode->SrcRid() )
  1144. {
  1145. // we don't have a rid for this account, possibly because it is a local group
  1146. lenSid = DIM(sid);
  1147. lenDomain = DIM(domain);
  1148. if ( LookupAccountName(m_Args.Cache()->GetSourceDCName(),pNode->GetAcctName(),sid,&lenSid,domain,&lenDomain,&snu) )
  1149. {
  1150. if (! UStrICmp(m_Args.Source(),domain) )
  1151. {
  1152. // found the source SID
  1153. // get the last sub-id
  1154. PUCHAR pCount = GetSidSubAuthorityCount(&sid);
  1155. if ( pCount )
  1156. {
  1157. LPDWORD pRid = GetSidSubAuthority(&sid,(*pCount) - 1 );
  1158. if ( pRid )
  1159. {
  1160. pNode->SrcRid(*pRid);
  1161. }
  1162. }
  1163. }
  1164. }
  1165. }
  1166. if ( pNode->SrcRid() && !pNode->TgtRid() )
  1167. {
  1168. // we got the source RID, now try to get the target RID
  1169. lenSid = DIM(sid);
  1170. lenDomain = DIM(domain);
  1171. if ( LookupAccountName(m_Args.Cache()->GetTargetDCName(),pNode->GetTargetAcctName(),sid,&lenSid,domain,&lenDomain,&snu) )
  1172. {
  1173. if (! UStrICmp(m_Args.Target(),domain) )
  1174. {
  1175. // found the source SID
  1176. // get the last sub-id
  1177. PUCHAR pCount = GetSidSubAuthorityCount(&sid);
  1178. if ( pCount )
  1179. {
  1180. LPDWORD pRid = GetSidSubAuthority(&sid,(*pCount) - 1 );
  1181. if ( pRid )
  1182. {
  1183. pNode->TgtRid(*pRid);
  1184. }
  1185. }
  1186. }
  1187. }
  1188. }
  1189. }
  1190. tEnum.Close();
  1191. return bSuccess;
  1192. }
  1193. // We remove the Exchange server service accont from the cache before translating,
  1194. // since it is not recommended to change the service account from exchange
  1195. // in any event, the service account for exchange cannot be changed simply by granting
  1196. // exchange permissions to the new account. It also requires configuration changes within
  1197. // exchange that must be performed manually
  1198. BOOL
  1199. CSecTranslator::RemoveExchangeServiceAccountFromCache()
  1200. {
  1201. WCHAR const * exServiceName = L"MSExchangeDS";
  1202. SC_HANDLE hSCM;
  1203. DWORD rc = 0; // return code
  1204. BOOL result = FALSE;
  1205. BOOL bUseMapFile = m_Args.UsingMapFile();
  1206. if ( m_Args.TranslateContainers() )
  1207. {
  1208. // get the service account name for the exchange directory service on exchServer
  1209. // BOOL retval=FALSE; // returned value
  1210. SC_HANDLE hSvc; // Service handle
  1211. DWORD lenQsc; // required qsc info len
  1212. union
  1213. {
  1214. QUERY_SERVICE_CONFIG qsc; // Exchange Directory service information
  1215. BYTE padding[1000];
  1216. } bufQsc;
  1217. hSCM = OpenSCManager( m_exchServer, NULL, GENERIC_READ );
  1218. if ( !hSCM )
  1219. {
  1220. rc = GetLastError();
  1221. err.SysMsgWrite( ErrW, rc,
  1222. DCT_MSG_SCM_OPEN_FAILED_SD, m_exchServer,rc );
  1223. }
  1224. else
  1225. {
  1226. hSvc = OpenService( hSCM, exServiceName, SERVICE_QUERY_CONFIG );
  1227. if ( !hSvc )
  1228. {
  1229. rc = GetLastError();
  1230. switch ( rc )
  1231. {
  1232. case ERROR_SERVICE_DOES_NOT_EXIST: // 1060
  1233. default:
  1234. err.SysMsgWrite( ErrW, rc, DCT_MSG_OPEN_SERVICE_FAILED_SSD,
  1235. m_exchServer , exServiceName, rc );
  1236. break;
  1237. }
  1238. }
  1239. else
  1240. {
  1241. if ( !QueryServiceConfig( hSvc, &bufQsc.qsc, sizeof bufQsc, &lenQsc ) )
  1242. {
  1243. rc = GetLastError();
  1244. err.SysMsgWrite( ErrW, rc, DCT_MSG_QUERY_SERVICE_CONFIG_FAILED_SSD,
  1245. m_exchServer, exServiceName, rc );
  1246. }
  1247. else
  1248. {
  1249. // We've found the account
  1250. result = TRUE;
  1251. // bufQsc.qsc.lpServiceStartName is DOMAIN\Account or .\Account
  1252. WCHAR * domAcct = bufQsc.qsc.lpServiceStartName;
  1253. WCHAR * domName; // domain-name
  1254. WCHAR * acctName; // account-name
  1255. for ( domName = domAcct ; *domName && *domName != _T('\\') ; domName++ )
  1256. ;
  1257. if ( *domName == _T('\\') )
  1258. {
  1259. *domName = 0;
  1260. acctName = domName+1;
  1261. domName = domAcct;
  1262. }
  1263. // Is the account from the source domain?
  1264. WCHAR szSourceDomain[LEN_Domain];
  1265. WCHAR wszAccountName[LEN_Account];
  1266. safecopy(wszAccountName,acctName);
  1267. //use the domain name from the cache if we are not using a sID mapping
  1268. //file
  1269. if (!bUseMapFile)
  1270. {
  1271. safecopy(szSourceDomain,m_Args.Cache()->GetSourceDomainName());
  1272. if ( !UStrICmp(domName,szSourceDomain ) )
  1273. {
  1274. // if so, is it in the cache?
  1275. TAcctNode * tnode;
  1276. TNodeTreeEnum tEnum;
  1277. // the cache is a tree, sorted by RID
  1278. for ( tnode = (TAcctNode *)tEnum.OpenFirst(m_Args.Cache()) ; tnode ; tnode = (TAcctNode *)tEnum.Next() )
  1279. {
  1280. if ( !UStrICmp(tnode->GetAcctName(),wszAccountName) )
  1281. {
  1282. // remove it from the cache, and notify the user
  1283. err.MsgWrite(ErrW,DCT_MSG_SKIPPING_EXCHANGE_ACCOUNT_SS,domName,acctName);
  1284. m_Args.Cache()->Remove(tnode);
  1285. }
  1286. }
  1287. tEnum.Close();
  1288. }
  1289. }//end if not using mapping file
  1290. else //else using sID mapping file, get the source domain name from the
  1291. { //node itself
  1292. //is this account in the cache?
  1293. TAcctNode * tnode;
  1294. TNodeTreeEnum tEnum;
  1295. // the cache is a tree, sorted by RID
  1296. for ( tnode = (TAcctNode *)tEnum.OpenFirst(m_Args.Cache()) ; tnode ; tnode = (TAcctNode *)tEnum.Next() )
  1297. {
  1298. if (( !UStrICmp(tnode->GetAcctName(),wszAccountName) ) &&
  1299. ( !UStrICmp(((TRidNode*)tnode)->GetSrcDomName(),domName) ))
  1300. {
  1301. // remove it from the cache, and notify the user
  1302. err.MsgWrite(ErrW,DCT_MSG_SKIPPING_EXCHANGE_ACCOUNT_SS,domName,acctName);
  1303. m_Args.Cache()->Remove(tnode);
  1304. }
  1305. }
  1306. tEnum.Close();
  1307. }//end if using mapping file
  1308. CloseServiceHandle( hSvc );
  1309. }
  1310. }
  1311. CloseServiceHandle(hSCM);
  1312. }
  1313. }
  1314. if ( !result )
  1315. {
  1316. // couldn't get the service account name
  1317. err.SysMsgWrite(ErrW,rc,DCT_MSG_CANT_FIND_EXCHANGE_ACCOUNT_SD,
  1318. m_exchServer,rc);
  1319. }
  1320. return result;
  1321. }
  1322. void
  1323. CSecTranslator::DoExchangeResolution(
  1324. TSDResolveStats * stat, // in - stats object to record stats
  1325. IVarSet * pVarSet
  1326. )
  1327. {
  1328. if (!m_Args.Cache()->IsCancelled())
  1329. {
  1330. TGlobalDirectory m_exDir;
  1331. _bstr_t domain = pVarSet->get(GET_BSTR(DCTVS_AccountOptions_SidHistoryCredentials_Domain));
  1332. _bstr_t username = pVarSet->get(GET_BSTR(DCTVS_AccountOptions_SidHistoryCredentials_UserName));
  1333. _bstr_t password = pVarSet->get(GET_BSTR(DCTVS_AccountOptions_SidHistoryCredentials_Password));
  1334. _bstr_t mode = pVarSet->get(GET_BSTR(DCTVS_Security_TranslationMode));
  1335. _bstr_t mbquery = pVarSet->get(L"ExchangeMigration.LdapQuery");
  1336. WCHAR query[LEN_Path] = L"(objectClass=*)";
  1337. if ( m_exchServer[0] )
  1338. {
  1339. if (! RemoveExchangeServiceAccountFromCache() )
  1340. goto end;
  1341. }
  1342. if ( mbquery.length() )
  1343. {
  1344. UStrCpy(query,(WCHAR*)mbquery);
  1345. }
  1346. if ( m_Args.TranslateMailboxes() || m_Args.TranslateContainers() )
  1347. {
  1348. // make sure we have some accts in the cache
  1349. m_exDir.SetStats(stat);
  1350. m_Args.Cache()->UnCancel();
  1351. err.MsgWrite(0,DCT_MSG_EXCHANGE_TRANSLATION_MODE_S,(WCHAR*)mode);
  1352. m_exDir.DoLdapTranslation(m_exchServer,domain,username,password,&m_Args,NULL,query);
  1353. stat->DisplayPath(L"");
  1354. }
  1355. }
  1356. if (m_Args.Cache()->IsCancelled())
  1357. err.MsgWrite(0, DCT_MSG_OPERATION_ABORTED_EXCHANGE);
  1358. end:
  1359. return;
  1360. }
  1361. //----------------------------------------------------------------------------
  1362. // GetLine Function
  1363. //
  1364. // Retrieves a single line from a SID mapping file.
  1365. //
  1366. // Author
  1367. // moluper 2001-10-08
  1368. //
  1369. // Arguments
  1370. // IN fp - pointer to stream i/o file structure
  1371. // IN pszLine - pointer to buffer in which a null terminated line from file
  1372. // will be written
  1373. // IN cchLine - size of buffer in characters
  1374. //
  1375. // Return Value
  1376. // The return value is true if a valid line from the file was retrived
  1377. // otherwise the return value is false.
  1378. //----------------------------------------------------------------------------
  1379. inline bool __stdcall GetLine(FILE* fp, PTSTR pszLine, int cchLine)
  1380. {
  1381. bool bGet = false;
  1382. //
  1383. // until a valid line is retrieved
  1384. //
  1385. while (bGet == false)
  1386. {
  1387. //
  1388. // retrieve line from file
  1389. //
  1390. if (_fgetts(pszLine, cchLine, fp) == NULL)
  1391. {
  1392. break;
  1393. }
  1394. //
  1395. // check if line length is valid
  1396. //
  1397. int cch = _tcslen(pszLine);
  1398. if ((cch < (cchLine - 1)) || (pszLine[cch - 1] == L'\r') || (pszLine[cch - 1] == L'\n'))
  1399. {
  1400. //
  1401. // the line is less than or equal to the maximum length
  1402. // remove carriage return and linefeed characters from end of line
  1403. //
  1404. while ((cch > 0) && ((pszLine[cch - 1] == L'\r') || (pszLine[cch - 1] == L'\n')))
  1405. {
  1406. pszLine[--cch] = _T('\0');
  1407. }
  1408. bGet = true;
  1409. }
  1410. else
  1411. {
  1412. //
  1413. // the line is greater than maximum length
  1414. //
  1415. // only display beginning of line with trailing ...
  1416. //
  1417. int ich = cchLine / 4;
  1418. pszLine[ich++] = _T('.');
  1419. pszLine[ich++] = _T('.');
  1420. pszLine[ich++] = _T('.');
  1421. pszLine[ich++] = _T('\0');
  1422. err.MsgWrite(ErrW, DCT_MSG_SID_MAPPING_FILE_LINE_TOO_LONG_S, pszLine);
  1423. if (useErrAlt)
  1424. {
  1425. errAlt.MsgWrite(ErrW, DCT_MSG_SID_MAPPING_FILE_LINE_TOO_LONG_S, pszLine);
  1426. }
  1427. // skip rest of line
  1428. do
  1429. {
  1430. if (_fgetts(pszLine, cchLine, fp) != NULL)
  1431. {
  1432. cch = _tcslen(pszLine);
  1433. }
  1434. else
  1435. {
  1436. break;
  1437. }
  1438. }
  1439. while ((pszLine[cch - 1] != L'\r') && (pszLine[cch - 1] != L'\n'));
  1440. }
  1441. }
  1442. return bGet;
  1443. }
  1444. //----------------------------------------------------------------------------
  1445. // TrimTrailingSpaces
  1446. //
  1447. // Removes white space characters from end of string.
  1448. //
  1449. // Author
  1450. // moluper 2001-10-08
  1451. //
  1452. // Arguments
  1453. // IN psz - pointer to buffer in which trailing whitespace characters are
  1454. // replaced with null characters in place
  1455. //----------------------------------------------------------------------------
  1456. inline void __stdcall TrimTrailingSpaces(PTSTR psz)
  1457. {
  1458. for (PTSTR pch = psz + _tcslen(psz) - 1; (pch >= psz) && _istspace(*pch); pch--)
  1459. {
  1460. *pch = L'\0';
  1461. }
  1462. }
  1463. /*********************************************************************
  1464. * *
  1465. * Written by: Paul Thompson *
  1466. * Date: 4 OCT 2000 *
  1467. * *
  1468. * This function is responsible for retrieving account sIDs from *
  1469. * the given sID mapping file and adding these sids to the cache. *
  1470. * *
  1471. *********************************************************************/
  1472. //BEGIN LoadCacheFromMapFile
  1473. BOOL
  1474. CSecTranslator::LoadCacheFromMapFile(
  1475. WCHAR const * filename, // in - file to read sid mapping from
  1476. IVarSet * pVarSet // in - pointer to varset
  1477. )
  1478. {
  1479. FILE * pFile = NULL;
  1480. WCHAR szLine[2 * MAX_PATH];
  1481. WCHAR path[MAX_PATH];
  1482. WCHAR szFmt1[64];
  1483. WCHAR szFmt2[64];
  1484. WCHAR sourceSid[MAX_PATH];
  1485. WCHAR targetSid[MAX_PATH];
  1486. int count = 0;
  1487. BOOL bSuccess = TRUE;
  1488. if (useErrAlt)
  1489. errAlt.MsgWrite(0, DCT_MSG_PROCESSING_SID_MAPPING_FILE, filename);
  1490. _wfullpath(path,filename,MAX_PATH);
  1491. m_Args.Cache()->ToSorted();
  1492. // The input file should have the format:
  1493. // srcSid,tgtSid
  1494. pFile = OpenMappingFile(path);
  1495. if ( pFile )
  1496. {
  1497. //
  1498. // initialize format strings so that scanf does not exceed
  1499. // size of sourceSid and targetSid buffers
  1500. //
  1501. wsprintf(szFmt1, L" %%%d[^,\r\n]", MAX_PATH - 1);
  1502. wsprintf(szFmt2, L" %%%d[^,] , %%%d[^\r\n]", MAX_PATH - 1, MAX_PATH - 1);
  1503. //
  1504. // read account mapping entries until the end of the file is reached
  1505. //
  1506. bool bRemoveMode = (m_Args.TranslationMode() == REMOVE_SECURITY);
  1507. for (;;)
  1508. {
  1509. //
  1510. // retrieve line from file
  1511. //
  1512. if (GetLine(pFile, szLine, sizeof(szLine) / sizeof(szLine[0]) - 1) == false)
  1513. {
  1514. // if an error reading the file occurred log an error message
  1515. // and set return value to unsuccessful
  1516. int nError = ferror(pFile);
  1517. if (nError != 0)
  1518. {
  1519. err.MsgWrite(ErrE, DCT_MSG_ERROR_READING_INPUT_FILE_S, path);
  1520. if (useErrAlt)
  1521. errAlt.MsgWrite(ErrE, DCT_MSG_ERROR_READING_INPUT_FILE_S, path);
  1522. bSuccess = FALSE;
  1523. }
  1524. break;
  1525. }
  1526. //
  1527. // parse account name(s) or SID(s)
  1528. // the comma character is the only valid separator between the source and target accounts
  1529. //
  1530. int cFields = 0;
  1531. if (bRemoveMode)
  1532. {
  1533. //
  1534. // remove mode only requires source account
  1535. //
  1536. cFields = swscanf(szLine, szFmt1, sourceSid);
  1537. if (cFields >= 1)
  1538. {
  1539. TrimTrailingSpaces(sourceSid);
  1540. targetSid[0] = L'\0';
  1541. }
  1542. else
  1543. {
  1544. continue;
  1545. }
  1546. }
  1547. else
  1548. {
  1549. //
  1550. // add and replace modes require both source and target accounts
  1551. //
  1552. cFields = swscanf(szLine, szFmt2, sourceSid, targetSid);
  1553. if (cFields >= 2)
  1554. {
  1555. TrimTrailingSpaces(sourceSid);
  1556. TrimTrailingSpaces(targetSid);
  1557. }
  1558. else
  1559. {
  1560. // only log error if not blank line
  1561. if (cFields == 1)
  1562. {
  1563. err.MsgWrite(ErrW, DCT_MSG_SID_MAPPING_FILE_UNABLE_TO_PARSE_S, szLine);
  1564. if (useErrAlt)
  1565. errAlt.MsgWrite(ErrW, DCT_MSG_SID_MAPPING_FILE_UNABLE_TO_PARSE_S, szLine);
  1566. }
  1567. continue;
  1568. }
  1569. }
  1570. short lType = EA_AccountUser;
  1571. //divide the sids into domain sids and rids
  1572. WCHAR srcDomainSid[MAX_PATH] = L"";
  1573. WCHAR tgtDomainSid[MAX_PATH] = L"";
  1574. _bstr_t srcDomainName = L"";
  1575. _bstr_t tgtDomainName = L"";
  1576. DWORD srcRid = 0;
  1577. DWORD tgtRid = 0;
  1578. _bstr_t srcName = L"";
  1579. _bstr_t tgtName = L"";
  1580. WCHAR userName[MAX_PATH] = L"";
  1581. WCHAR domainName[MAX_PATH] = L"";
  1582. DWORD cb = MAX_PATH;
  1583. DWORD cbDomain = MAX_PATH;
  1584. SID_NAME_USE sid_Use;
  1585. PSID srcSid = NULL;
  1586. PSID tgtSid = NULL;
  1587. WCHAR * slash;
  1588. _bstr_t DCName;
  1589. BYTE ssid[200];
  1590. BYTE tsid[200];
  1591. DWORD lenSid = DIM(ssid);
  1592. BOOL bNeedToFreeSrc = FALSE;
  1593. BOOL bNeedToFreeTgt = FALSE;
  1594. //see if the source is given by domain\account format or
  1595. //decimal-style sid format
  1596. if (wcschr(sourceSid,L'\\'))
  1597. {
  1598. //seperate domain and account names
  1599. srcDomainName = sourceSid;
  1600. srcName = sourceSid;
  1601. slash = wcschr((WCHAR*)srcDomainName,L'\\');
  1602. if ( slash )
  1603. *slash = 0;
  1604. //get a DC for the given domain
  1605. DCName = GetADC(srcDomainName);
  1606. if (!DCName.length())
  1607. {
  1608. err.MsgWrite(0,DCT_MSG_SRC_ACCOUNT_NOT_READ_FROM_FILE_DS, sourceSid, targetSid, path, sourceSid);
  1609. if (useErrAlt)
  1610. errAlt.MsgWrite(ErrW,DCT_MSG_SRC_ACCOUNT_NOT_READ_FROM_FILE_DS, sourceSid, targetSid, path, sourceSid);
  1611. continue;
  1612. }
  1613. //get the sid for this account
  1614. if(!LookupAccountName(DCName,srcName,(PSID)ssid,&lenSid,domainName,&cbDomain,&sid_Use))
  1615. {
  1616. err.MsgWrite(0,DCT_MSG_SRC_ACCOUNT_NOT_READ_FROM_FILE_DS, sourceSid, targetSid, path, sourceSid);
  1617. if (useErrAlt)
  1618. errAlt.MsgWrite(ErrW,DCT_MSG_SRC_ACCOUNT_NOT_READ_FROM_FILE_DS, sourceSid, targetSid, path, sourceSid);
  1619. continue;
  1620. }
  1621. srcSid = (PSID)ssid;
  1622. if (sid_Use == SidTypeGroup)
  1623. lType = EA_AccountGroup;
  1624. else
  1625. lType = EA_AccountUser;
  1626. }//end if domain\account format
  1627. else
  1628. {
  1629. srcSid = SidFromString(sourceSid);
  1630. if (!srcSid)
  1631. {
  1632. err.MsgWrite(0,DCT_MSG_SRC_ACCOUNT_NOT_READ_FROM_FILE_DS, sourceSid, targetSid, path, sourceSid);
  1633. if (useErrAlt)
  1634. errAlt.MsgWrite(ErrW,DCT_MSG_SRC_ACCOUNT_NOT_READ_FROM_FILE_DS, sourceSid, targetSid, path, sourceSid);
  1635. continue;
  1636. }
  1637. bNeedToFreeSrc = TRUE;
  1638. if (LookupAccountSid(NULL, srcSid, userName, &cb, domainName, &cbDomain, &sid_Use))
  1639. {
  1640. srcName = userName;
  1641. srcDomainName = domainName;
  1642. if (sid_Use == SidTypeGroup)
  1643. lType = EA_AccountGroup;
  1644. else
  1645. lType = EA_AccountUser;
  1646. }
  1647. }//end else sid format
  1648. //if target given
  1649. if (cFields > 1)
  1650. {
  1651. //see if the target is given by domain\account format or
  1652. //decimal-style sid format
  1653. lenSid = DIM(tsid);
  1654. cb = cbDomain = MAX_PATH;
  1655. if (wcschr(targetSid,L'\\'))
  1656. {
  1657. //seperate domain and account names
  1658. tgtDomainName = targetSid;
  1659. tgtName = targetSid;
  1660. slash = wcschr((WCHAR*)tgtDomainName,L'\\');
  1661. if ( slash )
  1662. *slash = 0;
  1663. //get a DC for the given domain
  1664. DCName = GetADC(tgtDomainName);
  1665. if (!DCName.length())
  1666. {
  1667. if (bNeedToFreeSrc)
  1668. FreeSid(srcSid);
  1669. err.MsgWrite(0,DCT_MSG_TGT_ACCOUNT_NOT_READ_FROM_FILE_DS, sourceSid, targetSid, path, targetSid);
  1670. if (useErrAlt)
  1671. errAlt.MsgWrite(ErrW,DCT_MSG_TGT_ACCOUNT_NOT_READ_FROM_FILE_DS, sourceSid, targetSid, path, targetSid);
  1672. continue;
  1673. }
  1674. //get the sid for this account
  1675. if(!LookupAccountName(DCName,tgtName,(PSID)tsid,&lenSid,domainName,&cbDomain,&sid_Use))
  1676. {
  1677. if (bNeedToFreeSrc)
  1678. FreeSid(srcSid);
  1679. err.MsgWrite(0,DCT_MSG_TGT_ACCOUNT_NOT_READ_FROM_FILE_DS, sourceSid, targetSid, path, targetSid);
  1680. if (useErrAlt)
  1681. errAlt.MsgWrite(ErrW,DCT_MSG_TGT_ACCOUNT_NOT_READ_FROM_FILE_DS, sourceSid, targetSid, path, targetSid);
  1682. continue;
  1683. }
  1684. tgtSid = (PSID)tsid;
  1685. if (sid_Use == SidTypeGroup)
  1686. lType = EA_AccountGroup;
  1687. else
  1688. lType = EA_AccountUser;
  1689. }//end if domain\account format
  1690. else
  1691. {
  1692. tgtSid = SidFromString(targetSid);
  1693. if (!tgtSid)
  1694. {
  1695. if (bNeedToFreeSrc)
  1696. FreeSid(srcSid);
  1697. err.MsgWrite(0,DCT_MSG_TGT_ACCOUNT_NOT_READ_FROM_FILE_DS, sourceSid, targetSid, path, targetSid);
  1698. if (useErrAlt)
  1699. errAlt.MsgWrite(ErrW,DCT_MSG_TGT_ACCOUNT_NOT_READ_FROM_FILE_DS, sourceSid, targetSid, path, targetSid);
  1700. continue;
  1701. }
  1702. bNeedToFreeTgt = TRUE;
  1703. if (LookupAccountSid(NULL, tgtSid, userName, &cb, domainName, &cbDomain, &sid_Use))
  1704. {
  1705. tgtName = userName;
  1706. tgtDomainName = domainName;
  1707. if (sid_Use == SidTypeGroup)
  1708. lType = EA_AccountGroup;
  1709. else
  1710. lType = EA_AccountUser;
  1711. }
  1712. }//end else sid format
  1713. }//end if given target account
  1714. else if (m_Args.TranslationMode() == REMOVE_SECURITY) //else if REMOVE mode set target to use source
  1715. {
  1716. tgtSid = srcSid;
  1717. bNeedToFreeTgt = FALSE;
  1718. wcscpy(targetSid, sourceSid);
  1719. tgtName = srcName;
  1720. tgtDomainName = srcDomainName;
  1721. }
  1722. //if the source account is not already in the cache, then add it
  1723. if ((m_Args.Cache()->GetNumAccts() == 0) || (m_Args.Cache()->LookupWODomain(srcSid) == NULL))
  1724. {
  1725. //get the domain sids and account rids from the account sids
  1726. SplitAccountSids(srcSid, srcDomainSid, &srcRid, tgtSid, tgtDomainSid, &tgtRid);
  1727. //insert this node into the cache
  1728. m_Args.Cache()->InsertLastWithSid(srcName,srcDomainSid,srcDomainName,srcRid,tgtName,
  1729. tgtDomainSid,tgtDomainName,tgtRid,lType);
  1730. count++;
  1731. }
  1732. else
  1733. err.MsgWrite(0,DCT_MSG_SRC_ACCOUNT_DUPLICATE_IN_FILE_DS, sourceSid, targetSid, path, sourceSid);
  1734. if (bNeedToFreeSrc)
  1735. FreeSid(srcSid);
  1736. if (bNeedToFreeTgt)
  1737. FreeSid(tgtSid);
  1738. }
  1739. err.MsgWrite(0,DCT_MSG_ACCOUNTS_READ_FROM_FILE_DS,count,path);
  1740. fclose(pFile);
  1741. }
  1742. else
  1743. {
  1744. err.MsgWrite(ErrS,DCT_MSG_ERROR_OPENING_FILE_S,path);
  1745. if (useErrAlt)
  1746. errAlt.MsgWrite(ErrS,DCT_MSG_ERROR_OPENING_FILE_S,path);
  1747. bSuccess = FALSE;
  1748. }
  1749. return bSuccess;
  1750. }
  1751. //END LoadCacheFromMapFile
  1752. /*********************************************************************
  1753. * *
  1754. * Written by: Paul Thompson *
  1755. * Date: 11 OCT 2000 *
  1756. * *
  1757. * This function is responsible for opening the sid mapping file *
  1758. * whether it is anm ANSI or UNICODE file and return the file *
  1759. * pointer. *
  1760. * *
  1761. *********************************************************************/
  1762. //BEGIN OpenMappingFile
  1763. FILE* CSecTranslator::OpenMappingFile(LPCTSTR pszFileName)
  1764. {
  1765. // open in binary mode first in order to check for UNICODE byte order
  1766. // mark if the file is UNICODE then it must be read in binary mode
  1767. // with the stream i/o functions
  1768. FILE* fp = _tfopen(pszFileName, _T("rb"));
  1769. if (fp == NULL)
  1770. {
  1771. return NULL;
  1772. // _com_issue_error(E_INVALIDARG);
  1773. }
  1774. // check if file is ANSI or UNICODE or UTF-8
  1775. BYTE byteSignature[3];
  1776. if (fread(byteSignature, sizeof(BYTE), 3, fp) == 3)
  1777. {
  1778. static BYTE byteUtf8[] = { 0xEF, 0xBB, 0xBF };
  1779. static BYTE byteUnicodeLE[] = { 0xFF, 0xFE };
  1780. static BYTE byteUnicodeBE[] = { 0xFE, 0xFF };
  1781. // check for signature or byte order mark
  1782. if (memcmp(byteSignature, byteUtf8, sizeof(byteUtf8)) == 0)
  1783. {
  1784. // UTF-8 signature
  1785. // TODO: not currently supported
  1786. return NULL;
  1787. // _com_issue_error(E_INVALIDARG);
  1788. }
  1789. else if (memcmp(byteSignature, byteUnicodeLE, sizeof(byteUnicodeLE)) == 0)
  1790. {
  1791. // UNICODE Little Endian Byte Order Mark
  1792. // supported
  1793. // must read in binary mode
  1794. // move file pointer back one byte because we read 3 bytes
  1795. if (fseek(fp, -1, SEEK_CUR))
  1796. {
  1797. // if unable to move file pointer back, we bail
  1798. fclose(fp);
  1799. fp = NULL;
  1800. }
  1801. }
  1802. else if (memcmp(byteSignature, byteUnicodeBE, sizeof(byteUnicodeBE)) == 0)
  1803. {
  1804. // UNICODE Big Endian Byte Order Mark
  1805. // TODO: not currently supported
  1806. return NULL;
  1807. // _com_issue_error(E_INVALIDARG);
  1808. }
  1809. else
  1810. {
  1811. // assume ANSI
  1812. // re-open file in text mode as the stream i/o functions will
  1813. // treat the file as multi-byte characters and will convert them
  1814. // to UNICODE
  1815. fclose(fp);
  1816. fp = _tfopen(pszFileName, _T("rt"));
  1817. }
  1818. }
  1819. else
  1820. {
  1821. return NULL;
  1822. // _com_issue_error(E_INVALIDARG);
  1823. }
  1824. return fp;
  1825. }
  1826. //END OpenMappingFile
  1827. /*********************************************************************
  1828. * *
  1829. * Written by: Paul Thompson *
  1830. * Date: 10 JUNE 2001 *
  1831. * *
  1832. * This function is responsible for retrieving a DC from the *
  1833. * given domain. *
  1834. * This function returns the DCName, if retrieved, or an empty *
  1835. * string. *
  1836. * *
  1837. *********************************************************************/
  1838. //BEGIN GetADC
  1839. _bstr_t CSecTranslator::GetADC(_bstr_t sDomainName)
  1840. {
  1841. _bstr_t strDcName;
  1842. DWORD dwError = GetDcName4(sDomainName, DS_DIRECTORY_SERVICE_PREFERRED, strDcName);
  1843. return (dwError == ERROR_SUCCESS) ? strDcName : _T("");
  1844. }
  1845. //END GetADC