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.

1642 lines
52 KiB

  1. //#pragma title ("SidCache.hpp -- Cache, Tree of SIDs")
  2. /*
  3. Copyright (c) 1995-1998, Mission Critical Software, Inc. All rights reserved.
  4. ===============================================================================
  5. Module - sidcache.cpp
  6. System - SDResolve
  7. Author - Christy Boles
  8. Created - 97/06/27
  9. Description - Cache of SIDs. Implemented using TNode derived classes, Cache is
  10. organized as a tree, sorted by Domain B RID. Each node contains
  11. Domain A RID, Domain B RID, Account Name, and counters for stats.
  12. Updates -
  13. ===============================================================================
  14. */
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include "stdafx.h"
  19. #include <malloc.h>
  20. #include <winbase.h>
  21. #include <lm.h>
  22. #include <lmaccess.h>
  23. #include <assert.h>
  24. #include "common.hpp"
  25. #include "ErrDct.hpp"
  26. #include "Ustring.hpp"
  27. #include "sidcache.hpp"
  28. #include "CommaLog.hpp"
  29. #include "TxtSid.h"
  30. #include "ResStr.h"
  31. #include "EaLen.hpp"
  32. #include "GetDcName.h"
  33. // from sdresolve.hpp
  34. extern BOOL BuiltinRid(DWORD rid);
  35. extern DWORD OpenDomain(WCHAR const * domain);
  36. extern TErrorDct err;
  37. extern TErrorDct errAlt;
  38. extern bool useErrAlt;
  39. extern bool silent;
  40. /***************************************************************************************************/
  41. /* vRidComp is used as a compare function for TSidNode Trees
  42. // It searches for v1 in the ridA field. The Tree must be sorted with RidComp before using this
  43. // search fn.
  44. // Return values: 0 tn->ridA == v1
  45. // 1 tn->ridA < v1
  46. // -1 tn->ridA > v1
  47. //
  48. /**************************************************************************************************/
  49. int
  50. vRidComp(
  51. const TNode * tn, // in -TSidNode
  52. const void * v1 // in -DWORD ridA value to look for
  53. )
  54. {
  55. DWORD rid1;
  56. DWORD rid2;
  57. TRidNode * n2;
  58. int retval;
  59. assert( tn ); // we should always be given valid inputs
  60. assert( v1 );
  61. n2 = (TRidNode *)tn;
  62. rid1 = n2->SrcRid();
  63. rid2 = *(DWORD *)v1;
  64. if ( rid1 < rid2 )
  65. {
  66. retval = -1;
  67. }
  68. if (rid1 > rid2)
  69. {
  70. retval = 1;
  71. }
  72. if ( rid1 == rid2) // ( rid1 == rid2 )
  73. {
  74. retval = 0;
  75. }
  76. return retval;
  77. }
  78. /***************************************************************************************************/
  79. /* RidComp: used as a compare function for TSidNode Trees
  80. It compares the ridA fields of SIDTNodes
  81. Return Values:
  82. 0 t1->ridA == t2->ridA
  83. 1 t1->ridA > t2->ridA
  84. -1 t1->ridA < t2->ridA
  85. /***************************************************************************************************/
  86. int RidComp(
  87. const TNode * t1, //in -first node to compare
  88. const TNode * t2 //in -second node to compare
  89. )
  90. {
  91. assert( t1 );
  92. assert( t2 );
  93. TRidNode * st1 = (TRidNode *) t1;
  94. TRidNode * st2 = (TRidNode *) t2;
  95. DWORD rid1 = st1->SrcRid();
  96. DWORD rid2 = st2->SrcRid();
  97. int retval;
  98. if ( rid1 < rid2 )
  99. {
  100. retval = -1;
  101. }
  102. if (rid1 > rid2)
  103. {
  104. retval = 1;
  105. }
  106. if ( rid1 == rid2 ) // (rid1 == rid2)
  107. {
  108. retval = 0;
  109. }
  110. return retval;
  111. }
  112. /***************************************************************************************************
  113. vNameComp: used as a compare function for TSidNode trees
  114. It compares a UNICODE string, with the acct_name field in the node
  115. Return Values:
  116. 0 tn->acct_name == actname
  117. 1 tn->acct_name < actname
  118. -1 tn->acct_name > actname
  119. /***************************************************************************************************/
  120. int
  121. vNameComp(
  122. const TNode * tn, //in -tree node
  123. const void * actname //in -name to look for
  124. )
  125. {
  126. assert( tn );
  127. assert( actname );
  128. LPWSTR str1 = ((TRidNode *)tn)->GetAcctName();
  129. LPWSTR str2 = (LPWSTR) actname;
  130. return UStrICmp(str1,str2);
  131. }
  132. /***************************************************************************************************/
  133. /* CompN: used as a compare function for TSidNode Trees
  134. It compares the acct_name fields of SIDTNodes
  135. Return Values:
  136. 0 t1->acct_name == t2->acct_name
  137. 1 t1->acct_name > t2->acct_name
  138. -1 t1->acct_name < t2->acct_name
  139. Error Handling:
  140. if given bad inputs, CompN displays an error message and returns 0
  141. /***************************************************************************************************/
  142. int
  143. CompN(
  144. const TNode * v1, //in -first node to compare
  145. const TNode * v2 //in -second node to compare
  146. )
  147. {
  148. assert( v1 );
  149. assert( v2 );
  150. TRidNode * t1 = (TRidNode *)v1;
  151. TRidNode * t2 = (TRidNode *)v2;
  152. return UStrICmp(t1->GetAcctName(),t2->GetAcctName());
  153. }
  154. int
  155. vTargetNameComp(
  156. const TNode * tn, //in -tree node
  157. const void * actname //in -name to look for
  158. )
  159. {
  160. assert( tn );
  161. assert( actname );
  162. LPWSTR str1 = ((TRidNode *)tn)->GetTargetAcctName();
  163. LPWSTR str2 = (LPWSTR) actname;
  164. return UStrICmp(str1,str2);
  165. }
  166. int
  167. CompTargetN(
  168. const TNode * v1, //in -first node to compare
  169. const TNode * v2 //in -second node to compare
  170. )
  171. {
  172. assert( v1 );
  173. assert( v2 );
  174. TRidNode * t1 = (TRidNode *)v1;
  175. TRidNode * t2 = (TRidNode *)v2;
  176. return UStrICmp(t1->GetTargetAcctName(),t2->GetTargetAcctName());
  177. }
  178. int
  179. TSidCompare(
  180. PSID const sid1, // in - first sid to compare
  181. PSID const sid2 // in - second sid to compare
  182. )
  183. {
  184. DWORD len1,
  185. len2;
  186. int retval = 0;
  187. len1 = GetLengthSid(sid1);
  188. len2 = GetLengthSid(sid2);
  189. if ( len1 < len2 )
  190. {
  191. retval = -1;
  192. }
  193. if ( len1 > len2 )
  194. {
  195. retval = 1;
  196. }
  197. if ( len1 == len2 )
  198. {
  199. retval = memcmp(sid1,sid2,len1);
  200. }
  201. return retval;
  202. }
  203. /**************************************************************************************************
  204. vSidComp: used as a compare function for TSidNode trees
  205. It compares a UNICODE string, with the acct_name field in the node
  206. Return Values:
  207. 0 tn->acct_name == actname
  208. 1 tn->acct_name < actname
  209. -1 tn->acct_name > actname
  210. /***************************************************************************************************/
  211. int
  212. vSidComp(
  213. const TNode * tn, //in -tree node
  214. const void * val //in -sid to look for
  215. )
  216. {
  217. PSID sid1 = ((TGeneralSidNode *)tn)->SrcSid();
  218. PSID sid2 = (PSID)val;
  219. return TSidCompare(sid1,sid2);
  220. }
  221. int
  222. nSidComp(
  223. const TNode * v1, //in -first node to compare
  224. const TNode * v2 //in -second node to compare
  225. )
  226. {
  227. TGeneralSidNode * t1 = (TGeneralSidNode *)v1;
  228. TGeneralSidNode * t2 = (TGeneralSidNode *)v2;
  229. return TSidCompare(t1->SrcSid(), t2->SrcSid());
  230. }
  231. /*******************************************************************************************************/
  232. // TSidNode Implementation
  233. /*******************************************************************************************************/
  234. TGeneralCache::TGeneralCache()
  235. {
  236. CompareSet(&nSidComp);
  237. TypeSetTree();
  238. }
  239. TGeneralCache::~TGeneralCache()
  240. {
  241. DeleteAllListItems(TGeneralSidNode);
  242. }
  243. void * TRidNode::operator new(size_t sz, const LPWSTR oldname, const LPWSTR newname)
  244. {
  245. int nlen = UStrLen(newname) + UStrLen(oldname) + 1;
  246. void * node = malloc(sz + nlen * (sizeof WCHAR) );
  247. return node;
  248. }
  249. TAcctNode::TAcctNode()
  250. {
  251. owner_changes = 0;
  252. group_changes = 0;
  253. ace_changes = 0;
  254. sace_changes = 0;
  255. }
  256. WCHAR * // ret- domain part of name
  257. GetDomainName(
  258. WCHAR * name // in - domain\\account name
  259. )
  260. {
  261. assert (name);
  262. int i;
  263. int len = UStrLen(name);
  264. WCHAR * domain;
  265. for (i = 2 ; name[i] != '\\' && i < len ; i++ )
  266. ;
  267. if ( i < len )
  268. {
  269. domain = new WCHAR[i+1];
  270. if (!domain)
  271. return NULL;
  272. UStrCpy(domain,name,i);
  273. }
  274. else
  275. {
  276. domain = NULL;
  277. }
  278. return domain;
  279. }
  280. TGeneralSidNode::TGeneralSidNode(
  281. const LPWSTR name1, // in - account name on source domain
  282. const LPWSTR name2 // in - account name on target domain
  283. )
  284. {
  285. assert (name1 && name2);
  286. assert (*name1 && *name2);
  287. WCHAR * domname = NULL;
  288. memset(&ownerStats,0,(sizeof ownerStats));
  289. memset(&groupStats,0,(sizeof ownerStats));
  290. memset(&daclStats,0,(sizeof ownerStats));
  291. memset(&saclStats,0,(sizeof ownerStats));
  292. src_acct_name = new WCHAR[UStrLen(name1)+1];
  293. if (!src_acct_name)
  294. return;
  295. safecopy(src_acct_name,name1);
  296. tgt_acct_name = new WCHAR[UStrLen(name2) + 1];
  297. if (!tgt_acct_name)
  298. return;
  299. safecopy(tgt_acct_name,name2);
  300. SDRDomainInfo info;
  301. domname = GetDomainName(name1);
  302. if (!domname)
  303. return;
  304. SetDomainInfoStruct(domname,&info);
  305. if ( info.valid )
  306. {
  307. src_domain = new WCHAR[UStrLen(info.domain_name)];
  308. if (!src_domain)
  309. return;
  310. safecopy(src_domain, info.domain_name);
  311. // src_dc = info.dc_name;
  312. src_nsubs = info.nsubs;
  313. src_sid = info.domain_sid;
  314. }
  315. else
  316. {
  317. err.MsgWrite(ErrE,DCT_MSG_DOMAIN_NOT_FOUND_S,domname);
  318. src_domain = NULL;
  319. // src_dc = NULL;
  320. src_nsubs = 0;
  321. src_sid = NULL;
  322. }
  323. if(domname)
  324. {
  325. delete [] domname;
  326. }
  327. domname = NULL;
  328. domname = GetDomainName(name2);
  329. if (!domname)
  330. return;
  331. SetDomainInfoStruct(domname,&info);
  332. if ( info.valid )
  333. {
  334. tgt_domain = new WCHAR[UStrLen(info.domain_name)];
  335. if (!tgt_domain)
  336. return;
  337. safecopy(tgt_domain, info.domain_name);
  338. tgt_nsubs = info.nsubs;
  339. tgt_sid = info.domain_sid;
  340. }
  341. else
  342. {
  343. err.MsgWrite(ErrE,DCT_MSG_DOMAIN_NOT_FOUND_S,domname);
  344. tgt_domain = NULL;
  345. tgt_nsubs = 0;
  346. tgt_sid = NULL;
  347. }
  348. sizediff = GetSidLengthRequired(tgt_nsubs) - GetSidLengthRequired(src_nsubs);
  349. if(domname)
  350. {
  351. delete [] domname;
  352. }
  353. }
  354. WCHAR * // ret- textual representation of sid
  355. BuildSidString(
  356. PSID pSid // in - sid
  357. )
  358. {
  359. WCHAR * buf = NULL;
  360. DWORD bufLen = 0;
  361. GetTextualSid(pSid,NULL,&bufLen);
  362. buf = new WCHAR[bufLen+1];
  363. if (!buf)
  364. return NULL;
  365. if ( ! GetTextualSid(pSid,buf,&bufLen) )
  366. {
  367. wcscpy(buf,L"<Unknown>");
  368. }
  369. return buf;
  370. }
  371. TGeneralSidNode::TGeneralSidNode(
  372. const PSID pSid1, // in - source domain sid
  373. const PSID pSid2 // in - target domain sid
  374. )
  375. {
  376. WCHAR domain[LEN_Domain];
  377. WCHAR account[LEN_Account];
  378. DWORD lenDomain = DIM(domain);
  379. DWORD lenAccount = DIM(account);
  380. SID_NAME_USE snu;
  381. DWORD nBytes;
  382. memset(&ownerStats,0,(sizeof ownerStats));
  383. memset(&groupStats,0,(sizeof ownerStats));
  384. memset(&daclStats,0,(sizeof ownerStats));
  385. memset(&saclStats,0,(sizeof ownerStats));
  386. // Source domain
  387. if ( pSid1 )
  388. {
  389. // Make a copy of the SID
  390. src_nsubs = *GetSidSubAuthorityCount(pSid1);
  391. nBytes = GetSidLengthRequired(src_nsubs);
  392. src_sid = new BYTE[nBytes];
  393. if (!src_sid)
  394. return;
  395. CopySid(nBytes,src_sid,pSid1);
  396. // Look up name for source SID
  397. if ( LookupAccountSid(NULL,pSid1,account,&lenAccount,domain,&lenDomain,&snu) )
  398. {
  399. if ( lenAccount == 0 && snu == SidTypeDeletedAccount )
  400. {
  401. WCHAR * buf = BuildSidString(pSid1);
  402. if (!buf)
  403. return;
  404. swprintf(account,L"<Deleted Account (%s)>",buf);
  405. delete [] buf;
  406. }
  407. src_acct_name = new WCHAR[UStrLen(domain) + 1 + UStrLen(account)+1];
  408. if (!src_acct_name)
  409. return;
  410. swprintf(src_acct_name,L"%s\\%s",domain,account);
  411. src_domain = NULL;
  412. }
  413. else
  414. {
  415. src_acct_name = BuildSidString(pSid1);
  416. if (!src_acct_name)
  417. return;
  418. src_domain = NULL;
  419. }
  420. }
  421. else
  422. {
  423. src_nsubs = 0;
  424. src_sid = NULL;
  425. src_acct_name = NULL;
  426. src_domain = NULL;
  427. }
  428. // Target domain
  429. if ( pSid2 )
  430. {
  431. tgt_nsubs = *GetSidSubAuthorityCount(pSid2);
  432. nBytes = GetSidLengthRequired(tgt_nsubs);
  433. tgt_sid = new BYTE[nBytes];
  434. if (!tgt_sid)
  435. return;
  436. CopySid(nBytes,tgt_sid,pSid2);
  437. if ( LookupAccountSid(NULL,pSid2,account,&lenAccount,domain,&lenDomain,&snu) )
  438. {
  439. tgt_acct_name = new WCHAR[UStrLen(domain) + 1 + UStrLen(account)+1];
  440. if (!tgt_acct_name)
  441. return;
  442. swprintf(tgt_acct_name,L"%s\\%s",domain,account);
  443. tgt_domain = NULL;
  444. }
  445. else
  446. {
  447. tgt_acct_name = NULL;
  448. tgt_domain = NULL;
  449. }
  450. }
  451. else
  452. {
  453. tgt_nsubs = 0;
  454. tgt_sid = NULL;
  455. tgt_acct_name = NULL;
  456. tgt_domain = NULL;
  457. }
  458. sizediff = GetSidLengthRequired(src_nsubs) - GetSidLengthRequired(tgt_nsubs);
  459. }
  460. TGeneralSidNode::~TGeneralSidNode()
  461. {
  462. if ( src_acct_name )
  463. delete [] src_acct_name;
  464. if ( tgt_acct_name )
  465. delete [] tgt_acct_name;
  466. if ( src_sid )
  467. delete [] src_sid;
  468. if ( tgt_sid )
  469. delete [] tgt_sid;
  470. if ( src_domain )
  471. delete [] src_domain;
  472. if ( tgt_domain )
  473. delete [] tgt_domain;
  474. }
  475. TRidNode::TRidNode(
  476. const LPWSTR oldacctname, // in -source account name
  477. const LPWSTR newacctname // in -target account name
  478. )
  479. {
  480. assert(tgtDomSid.c_str() == NULL);
  481. srcRid = 0;
  482. tgtRid = 0;
  483. status = DEFAULT;
  484. if ( ! newacctname )
  485. {
  486. acct_len = -1;
  487. swprintf(acct_name,L"%s",oldacctname);
  488. acct_name[UStrLen(acct_name)+1] = 0;
  489. }
  490. else
  491. {
  492. acct_len = UStrLen(oldacctname);
  493. swprintf(acct_name,L"%s:%s",oldacctname,newacctname);
  494. acct_name[acct_len] = 0;
  495. }
  496. }
  497. TRidNode::~TRidNode()
  498. {
  499. }
  500. /*******************************************************************************************************/
  501. // TSidCache Implementation
  502. /*******************************************************************************************************/
  503. void
  504. TSDRidCache::ReportAccountReferences(
  505. WCHAR const * filename // in - filename to record account references
  506. )
  507. {
  508. if ( m_otherAccounts )
  509. {
  510. CommaDelimitedLog resultLog;
  511. if ( resultLog.LogOpen(filename,FALSE) )
  512. {
  513. TGeneralSidNode * gnode;
  514. TNodeTreeEnum tEnum;
  515. for ( gnode = (TGeneralSidNode *)tEnum.OpenFirst(m_otherAccounts) ; gnode ; gnode = (TGeneralSidNode*)tEnum.Next() )
  516. {
  517. TSDFileDirCell * pOwner = gnode->GetOwnerStats();
  518. TSDFileDirCell * pGroup = gnode->GetGroupStats();
  519. TSDFileDirCell * pDacl = gnode->GetDaclStats();
  520. TSDFileDirCell * pSacl = gnode->GetSaclStats();
  521. WCHAR * sAccountSid = BuildSidString(gnode->SrcSid());
  522. if (!sAccountSid)
  523. return;
  524. resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
  525. sAccountSid,
  526. GET_STRING(IDS_STReference_File),
  527. pOwner->file,
  528. pGroup->file,
  529. pDacl->file,
  530. pSacl->file );
  531. resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
  532. sAccountSid,
  533. GET_STRING(IDS_STReference_Dir),
  534. pOwner->dir,
  535. pGroup->dir,
  536. pDacl->dir,
  537. pSacl->dir );
  538. resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
  539. sAccountSid,
  540. GET_STRING(IDS_STReference_Share),
  541. pOwner->share,
  542. pGroup->share,
  543. pDacl->share,
  544. pSacl->share );
  545. resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
  546. sAccountSid,
  547. GET_STRING(IDS_STReference_Mailbox),
  548. pOwner->mailbox,
  549. pGroup->mailbox,
  550. pDacl->mailbox,
  551. pSacl->mailbox );
  552. resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
  553. sAccountSid,
  554. GET_STRING(IDS_STReference_Container),
  555. pOwner->container,
  556. pGroup->container,
  557. pDacl->container,
  558. pSacl->container );
  559. resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
  560. sAccountSid,
  561. GET_STRING(IDS_STReference_Member),
  562. pOwner->member,
  563. pGroup->member,
  564. pDacl->member,
  565. pSacl->member );
  566. resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
  567. sAccountSid,
  568. GET_STRING(IDS_STReference_UserRight),
  569. pOwner->userright,
  570. pGroup->userright,
  571. pDacl->userright,
  572. pSacl->userright );
  573. resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
  574. sAccountSid,
  575. GET_STRING(IDS_STReference_RegKey),
  576. pOwner->regkey,
  577. pGroup->regkey,
  578. pDacl->regkey,
  579. pSacl->regkey );
  580. resultLog.MsgWrite(L"%s,%s,%s,%ld,%ld,%ld,%ld",gnode->GetAcctName(),
  581. sAccountSid,
  582. GET_STRING(IDS_STReference_Printer),
  583. pOwner->printer,
  584. pGroup->printer,
  585. pDacl->printer,
  586. pSacl->printer );
  587. if (sAccountSid)
  588. delete sAccountSid;
  589. }
  590. tEnum.Close();
  591. resultLog.LogClose();
  592. }
  593. else
  594. {
  595. err.MsgWrite(ErrE,DCT_MSG_COULD_NOT_OPEN_RESULT_FILE_S,filename);
  596. }
  597. }
  598. }
  599. //----------------------------------------------------------------------------
  600. // Function: VerifyTargetSids
  601. //
  602. // Synopsis: This function checks all target sids in the cache. If a target sid is not valid,
  603. // the particular TRidNode will be marked with TRidNode::TARGETSIDISINVALID.
  604. // We only concern about the case where the target domain sid is defined in
  605. // the TSDRidCache.
  606. //
  607. // Arguments: none
  608. //
  609. // Returns: none
  610. //
  611. // Modifies: mark the TRidNode status to TRidNode::TARGETSIDISINVALID
  612. // if the target sid is not valid
  613. //
  614. //----------------------------------------------------------------------------
  615. void TSDRidCache::VerifyTargetSids()
  616. {
  617. TNodeListEnum cacheEnumerator;
  618. TRidNode* aRidNode;
  619. // We only concern about the case where the target domain sid is defined in TSDRidCache
  620. // If it is not defined, TRidNode's are probably inserted with InsertLastWithSid, which
  621. // means the sid has been verified to be valid already (sid mapping file).
  622. if (to_sid != NULL)
  623. {
  624. DWORD dwSidSize = GetSidLengthRequired(to_nsubs);
  625. PSID targetSid = (PSID) new byte[dwSidSize];
  626. if (targetSid == NULL)
  627. _com_issue_error(E_OUTOFMEMORY);
  628. CopySid(dwSidSize, targetSid, to_sid); // copy the target domain sid
  629. PDWORD rid = GetSidSubAuthority(targetSid,to_nsubs -1);
  630. // go through each Node to check the target sid
  631. for (aRidNode = (TRidNode *) cacheEnumerator.OpenFirst(this);
  632. aRidNode != NULL && aRidNode->TgtRid() != 0;
  633. aRidNode = (TRidNode *) cacheEnumerator.Next())
  634. {
  635. // make sure that the TRidNode object is not using its own target domain sid
  636. // if it is using its own, we assume that the target sid has been verified
  637. // if target domain sid string is not empty, the TRidNode object uses its own target domain sid
  638. PCWSTR pszRidNodeOwnTgtDomSid = aRidNode->GetTgtDomSid();
  639. if (pszRidNodeOwnTgtDomSid != NULL && *pszRidNodeOwnTgtDomSid != L'\0')
  640. continue;
  641. (*rid) = aRidNode->TgtRid(); // replace last sub with this node's RID
  642. // look up the sid
  643. BOOL bIsTargetSidValid = TRUE;
  644. if (!aRidNode->IsValidOnTgt())
  645. {
  646. // if target rid is 0 or already verified before, we don't need to verify it again
  647. bIsTargetSidValid = FALSE;
  648. }
  649. else
  650. {
  651. WCHAR name[MAX_PATH];
  652. WCHAR domainName[MAX_PATH];
  653. DWORD cbName = MAX_PATH;
  654. DWORD cbDomainName = MAX_PATH;
  655. SID_NAME_USE sid_use;
  656. if (!LookupAccountSid(NULL, targetSid, name, &cbName, domainName, &cbDomainName, &sid_use))
  657. {
  658. bIsTargetSidValid = FALSE;
  659. aRidNode->SetStatus(aRidNode->GetStatus() | TRidNode::TARGETSIDISINVALID);
  660. }
  661. }
  662. }
  663. if (targetSid)
  664. delete[] ((byte*)targetSid);
  665. }
  666. }
  667. void
  668. TSDRidCache::ReportToVarSet(
  669. IVarSet * pVarSet, // in -varset to write information to
  670. bool summary, // in -flag: whether to print summary information
  671. bool detail // in -flag: whether to print detailed stats
  672. )
  673. {
  674. TNodeTreeEnum tEnum;
  675. TRidNode * tnode;
  676. long users=0;
  677. long lgroups=0;
  678. long ggroups=0;
  679. long other=0;
  680. long unres_users=0;
  681. long unres_lg=0;
  682. long unres_gg=0;
  683. long unres_other=0;
  684. long total=0;
  685. long n = 0;
  686. // sort the cache by names before printing the report
  687. if (IsTree())
  688. {
  689. ToSorted();
  690. }
  691. SortedToScrambledTree();
  692. Sort(&CompN);
  693. Balance();
  694. if ( detail )
  695. {
  696. for ( tnode = (TRidNode *)tEnum.OpenFirst(this) ; tnode ; tnode = (TRidNode *)tEnum.Next() )
  697. {
  698. if( tnode->ReportToVarSet(pVarSet,n) )
  699. {
  700. n++;
  701. }
  702. switch ( tnode->Type() )
  703. {
  704. case EA_AccountGroup: ggroups++; break;
  705. case EA_AccountGGroup: ggroups++; break;
  706. case EA_AccountLGroup: lgroups++; break;
  707. case EA_AccountUser: users++; break;
  708. default:
  709. other++;
  710. err.MsgWrite(0,DCT_MSG_BAD_ACCOUNT_TYPE_SD,tnode->GetAcctName(),tnode->Type() );
  711. }
  712. }
  713. tEnum.Close();
  714. if ( m_otherAccounts )
  715. {
  716. TGeneralSidNode * gnode;
  717. for ( gnode = (TGeneralSidNode *)tEnum.OpenFirst(m_otherAccounts) ; gnode ; gnode = (TGeneralSidNode*)tEnum.Next() )
  718. {
  719. if( gnode->ReportToVarSet(pVarSet,n) )
  720. {
  721. n++;
  722. }
  723. other++;
  724. }
  725. }
  726. total = users+lgroups+ggroups+other + unres_gg + unres_lg + unres_users + unres_other;
  727. pVarSet->put(GET_BSTR(DCTVS_Stats_Accounts_NumUsers),users);
  728. pVarSet->put(GET_BSTR(DCTVS_Stats_Accounts_NumGlobalGroups),ggroups);
  729. pVarSet->put(GET_BSTR(DCTVS_Stats_Accounts_NumLocalGroups),lgroups);
  730. pVarSet->put(GET_BSTR(DCTVS_Stats_Accounts_NumOther),other);
  731. }
  732. // re-sort by rid after printing the report
  733. if (IsTree())
  734. {
  735. ToSorted();
  736. }
  737. SortedToScrambledTree();
  738. Sort(&RidComp);
  739. Balance();
  740. }
  741. /***************************************************************************************************/
  742. /* TSidCache::Display: Displays the summary information, and/or contents of the TSidCache tree
  743. /***************************************************************************************************/
  744. void
  745. TSDRidCache::Display(
  746. bool summary, // in -flag: whether to print summary information
  747. bool detail // in -flag: whether to print detailed stats
  748. )
  749. {
  750. TNodeTreeEnum tEnum;
  751. TRidNode * tnode;
  752. long users=0;
  753. long lgroups=0;
  754. long ggroups=0;
  755. long other=0;
  756. long unres_users=0;
  757. long unres_lg=0;
  758. long unres_gg=0;
  759. long unres_other=0;
  760. long total=0;
  761. //
  762. // sort the cache by names before printing the report
  763. //
  764. // Note that the tree generated during the Sort method may become grossly un-balanced if
  765. // the data is already in the same order that the Sort method sorts the data. A stack
  766. // overflow may occur in the Balance method when it tries to convert the un-balanced tree
  767. // into a linked list before generating a balanced tree.
  768. //
  769. // Therefore it is necessary to generate a random 'scrambled' tree before re-sorting. If
  770. // already a tree the data must be converted to a list before generating the random tree.
  771. //
  772. if (IsTree())
  773. {
  774. ToSorted();
  775. }
  776. SortedToScrambledTree();
  777. Sort(&CompN);
  778. Balance();
  779. if ( detail )
  780. {
  781. err.MsgWrite(0,DCT_MSG_ACCOUNT_DETAIL_HEADER);
  782. err.MsgWrite(0, DCT_MSG_ACCOUNT_DETAIL_FORMAT);
  783. for ( tnode = (TRidNode *)tEnum.OpenFirst(this) ; tnode ; tnode = (TRidNode *)tEnum.Next() )
  784. {
  785. tnode->DisplayStats();
  786. switch ( tnode->Type() )
  787. {
  788. case EA_AccountGroup: ggroups++; break;
  789. case EA_AccountGGroup: ggroups++; break;
  790. case EA_AccountLGroup: lgroups++; break;
  791. case EA_AccountUser: users++; break;
  792. default:
  793. other++;
  794. err.MsgWrite(0,DCT_MSG_BAD_ACCOUNT_TYPE_SD,tnode->GetAcctName(),tnode->Type() );
  795. }
  796. }
  797. total = users+lgroups+ggroups+other + unres_gg + unres_lg + unres_users + unres_other;
  798. err.MsgWrite(0,DCT_MSG_ACCOUNT_DETAIL_FOOTER);
  799. }
  800. if ( summary )
  801. {
  802. err.MsgWrite(0,DCT_MSG_ACCOUNT_USER_GROUP_COUNT_DD,users+unres_users,ggroups+unres_gg+lgroups+unres_lg);
  803. err.MsgWrite(0,DCT_MSG_ACCOUNT_STATUS_COUNT_DDD,accts,accts_resolved,accts - accts_resolved);
  804. }
  805. // re-sort by rid after printing the report
  806. if (IsTree())
  807. {
  808. ToSorted();
  809. }
  810. SortedToScrambledTree();
  811. Sort(&RidComp);
  812. Balance();
  813. }
  814. /***************************************************************************************************/
  815. /* GetSidB:
  816. Builds a sid containing the Identifier Authority from the target-domain SID, along with the
  817. RID from the ridB field of the supplied node.
  818. /***************************************************************************************************/
  819. PSID // ret -the domain B sid for the account referenced in tnode
  820. TSDRidCache::GetTgtSid(
  821. const TAcctNode * anode // in -node to copy RID from
  822. )
  823. {
  824. TRidNode * tnode = (TRidNode *)anode;
  825. assert( tnode );
  826. assert( tnode->TgtRid() != 0);
  827. assert( to_sid ); // we can't resolve if we don't have domain B sid
  828. PDWORD rid;
  829. DWORD sidsize = GetSidLengthRequired(to_nsubs);
  830. PSID newsid = malloc(sidsize);
  831. if (newsid)
  832. {
  833. CopySid(sidsize,newsid,to_sid); // copy the domain B sid
  834. rid = GetSidSubAuthority(newsid,to_nsubs -1);
  835. assert( (*rid) == -1 ); // FillCache makes sure to_sid always ends with -1(f...f)
  836. (*rid)=tnode->TgtRid(); // replace last sub with this node's RID
  837. }
  838. return newsid;
  839. }
  840. // GetTgtSidWODomain:
  841. // Returns the target sid for this node without having the target domain information
  842. // filled in (like when we reACl using a sID mapping file).
  843. PSID // ret -the domain B sid for the account referenced in tnode
  844. TSDRidCache::GetTgtSidWODomain(
  845. const TAcctNode * anode // in -node to copy RID from
  846. )
  847. {
  848. TRidNode * tnode = (TRidNode *)anode;
  849. assert( tnode );
  850. assert( tnode->TgtRid() != 0);
  851. PDWORD rid;
  852. //get and convert the target domain sid stored in the node to a PSID
  853. PSID pTgtSid = MallocedSidFromString(tnode->GetTgtDomSid());
  854. if (pTgtSid)
  855. {
  856. PUCHAR pCount = GetSidSubAuthorityCount(pTgtSid);
  857. DWORD nSub = (DWORD)(*pCount) - 1;
  858. rid = GetSidSubAuthority(pTgtSid,nSub);
  859. assert( (*rid) == -1 ); // FillCache makes sure to_sid always ends with -1(f...f)
  860. (*rid)=tnode->TgtRid(); // replace last sub with this node's RID
  861. }
  862. return pTgtSid;
  863. }
  864. // GetTgtSidWODomain:
  865. // Returns the target sid for this node without having the target domain information
  866. // filled in (like when we reACl using a sID mapping file).
  867. PSID
  868. TSDRidCache::GetTgtSidWODomain(
  869. const PSID psid // in - the source sid
  870. )
  871. {
  872. TAcctNode* tn = LookupWODomain(psid);
  873. if (tn)
  874. return GetTgtSidWODomain(tn);
  875. else
  876. return NULL;
  877. }
  878. /***************************************************************************************************/
  879. /* Display sid - Displays the contents of a SID.
  880. The sid given is assumed to be a valid SID
  881. /***************************************************************************************************/
  882. void
  883. DisplaySid(
  884. const PSID ps // in -pointer to the sid to display
  885. )
  886. {
  887. assert( ps );
  888. PUCHAR ch = GetSidSubAuthorityCount(ps);
  889. DWORD nsubs = *ch;
  890. DWORD i;
  891. PSID_IDENTIFIER_AUTHORITY ida = GetSidIdentifierAuthority(ps);
  892. for ( i = 0 ; i < 6 ; i++ ) // 6 value fields in IA
  893. {
  894. printf("%ld, ",ida->Value[i]);
  895. }
  896. printf("\n%ld Subs: ",nsubs);
  897. for ( i = 0 ; i < nsubs ; i++ ) // print subauthority values
  898. {
  899. printf("\nS[%d]= %ld ",i,*GetSidSubAuthority(ps,i));
  900. }
  901. printf("\n");
  902. }
  903. /***************************************************************************************************/
  904. /* DisplaySid: If the sid is found in the cache, display the associated name, otherwise display
  905. the sid contents.
  906. ps and C are assumed to be valid.
  907. /***************************************************************************************************/
  908. void
  909. DisplaySid(
  910. const PSID ps, // in- sid to display
  911. TAccountCache * C // in- TSidCache to look for sid in
  912. )
  913. {
  914. assert ( ps );
  915. if ( !C )
  916. {
  917. DisplaySid(ps);
  918. }
  919. else
  920. {
  921. WCHAR * name = C->GetName(ps);
  922. if ( name )
  923. {
  924. err.MsgWrite(0,DCT_MSG_GENERIC_S,name);
  925. }
  926. else
  927. {
  928. DisplaySid(ps);
  929. }
  930. }
  931. }
  932. /***************************************************************************************************/
  933. //DispSidInfo: Displays contents of the TSidNode
  934. /***************************************************************************************************/
  935. void
  936. TRidNode::DisplaySidInfo() const
  937. {
  938. err.DbgMsgWrite(0,L"\nRid A= %ld \nName= %S \nRid B= %ld\n",srcRid,acct_name,tgtRid);
  939. err.DbgMsgWrite(0,L"Owner changes: %ld\n",owner_changes);
  940. err.DbgMsgWrite(0,L"Group changes: %ld\n",group_changes);
  941. err.DbgMsgWrite(0,L"ACE changes: %ld\n",ace_changes);
  942. err.DbgMsgWrite(0,L"SACE changes: %ld\n",sace_changes);
  943. if ( !IsValidOnTgt() )
  944. err.DbgMsgWrite(0,L"Target RID is not valid\n");
  945. }
  946. void
  947. TAcctNode::DisplayStats() const
  948. {
  949. LPWSTR res;
  950. if ( IsValidOnTgt() )
  951. res = L"";
  952. else
  953. res = (WCHAR*)GET_BSTR(IDS_UNRESOLVED);
  954. if (owner_changes || group_changes || ace_changes || sace_changes)
  955. err.MsgWrite(0,DCT_MSG_ACCOUNT_REFS_DATA_SDDDDS,owner_changes,group_changes,ace_changes,sace_changes,res);
  956. }
  957. void
  958. TRidNode::DisplayStats() const
  959. {
  960. LPWSTR res;
  961. if ( IsValidOnTgt() )
  962. res = L"";
  963. else
  964. res = (WCHAR*)GET_BSTR(IDS_UNRESOLVED);
  965. #ifndef _DEBUG
  966. if (owner_changes || group_changes || ace_changes || sace_changes )
  967. err.MsgWrite(0,DCT_MSG_ACCOUNT_REFS_DATA_SDDDDS,acct_name,owner_changes,group_changes,ace_changes,sace_changes,res);
  968. #else
  969. if (owner_changes || group_changes || ace_changes || sace_changes || true)
  970. err.DbgMsgWrite(0,L"%-35ls (%ld, %ld, %ld, %ld) %ls [%ld,%ld]",acct_name,owner_changes,group_changes,ace_changes,sace_changes,res,srcRid,tgtRid);
  971. #endif
  972. }
  973. BOOL // ret- TRUE if details reported, FALSE if skipped blank record
  974. TAcctNode::ReportToVarSet(
  975. IVarSet * pVarSet ,// in - VarSet to write data to
  976. DWORD n // in - index of account in varset
  977. )
  978. {
  979. BOOL bRecorded = FALSE;
  980. if ( owner_changes || group_changes || ace_changes || sace_changes )
  981. {
  982. WCHAR key[200];
  983. swprintf(key,L"Stats.Accounts.%ld.Name",n);
  984. pVarSet->put(key,GetAcctName());
  985. swprintf(key,L"Stats.Accounts.%ld.Owners",n);
  986. pVarSet->put(key,(LONG)owner_changes);
  987. swprintf(key,L"Stats.Accounts.%ld.Groups",n);
  988. pVarSet->put(key,(LONG)group_changes);
  989. swprintf(key,L"Stats.Accounts.%ld.ACEs",n);
  990. pVarSet->put(key,(LONG)ace_changes);
  991. swprintf(key,L"Stats.Accounts.%ld.SACEs",n);
  992. pVarSet->put(key,(LONG)sace_changes);
  993. swprintf(key,L"Stats.Accounts.%ld.Resolved",n);
  994. if ( IsValidOnTgt() )
  995. {
  996. pVarSet->put(key,L"Yes");
  997. }
  998. else
  999. {
  1000. pVarSet->put(key,L"No");
  1001. }
  1002. bRecorded = TRUE;
  1003. }
  1004. return bRecorded;
  1005. }
  1006. /****************************************************************************************************/
  1007. /* SIDTCache Implementation */
  1008. /***************************************************************************************************/
  1009. TSDRidCache::TSDRidCache()
  1010. {
  1011. from_sid = NULL;
  1012. to_sid = NULL;
  1013. from_domain[0] = 0;
  1014. to_domain[0] = 0;
  1015. from_dc[0] = 0;
  1016. to_dc[0] = 0;
  1017. from_nsubs = 0;
  1018. to_nsubs = 0;
  1019. accts = 0;
  1020. accts_resolved = 0;
  1021. m_otherAccounts = NULL;
  1022. CompareSet(&CompN); //start with an empty tree, to be sorted by acct_name
  1023. TypeSetTree();
  1024. }
  1025. void
  1026. TSDRidCache::CopyDomainInfo(
  1027. TSDRidCache const * other
  1028. )
  1029. {
  1030. from_nsubs = other->from_nsubs;
  1031. to_nsubs = other->to_nsubs;
  1032. from_sid = NULL;
  1033. to_sid = NULL;
  1034. if ( other->from_sid )
  1035. from_sid = malloc(GetSidLengthRequired(from_nsubs));
  1036. if ( other->to_sid )
  1037. to_sid = malloc(GetSidLengthRequired(to_nsubs));
  1038. if ( from_sid )
  1039. CopySid(GetSidLengthRequired(from_nsubs),from_sid,other->from_sid);
  1040. if ( to_sid )
  1041. CopySid(GetSidLengthRequired(to_nsubs),to_sid,other->to_sid);
  1042. safecopy(from_domain,other->from_domain);
  1043. safecopy(to_domain,other->to_domain);
  1044. safecopy(from_dc,other->from_dc);
  1045. safecopy(to_dc,other->to_dc);
  1046. }
  1047. void
  1048. TSDRidCache::Clear()
  1049. {
  1050. TRidNode * node;
  1051. for ( node = (TRidNode *)Head() ; node ; Remove(node) , free(node), node = (TRidNode *)Head() )
  1052. ;
  1053. accts = 0;
  1054. accts_resolved = 0;
  1055. }
  1056. TSDRidCache::~TSDRidCache()
  1057. {
  1058. if ( from_sid )
  1059. {
  1060. free(from_sid);
  1061. from_sid = NULL;
  1062. }
  1063. if ( to_sid )
  1064. {
  1065. free(to_sid);
  1066. to_sid = NULL;
  1067. }
  1068. // empty the list, and free each node
  1069. TRidNode * node;
  1070. for ( node = (TRidNode *)Head() ; node ; Remove(node) , free(node), node = (TRidNode *)Head() )
  1071. ;
  1072. if ( m_otherAccounts )
  1073. delete m_otherAccounts;
  1074. }
  1075. /***************************************************************************************************/
  1076. /* SizeDiff:
  1077. Returns (Length of Domain B SID) - (Length of Domain A SID)
  1078. if Domain B sids are longer, otherwise returns 0
  1079. This is used to figure out how much space to allocate for new SIDs in the ACEs
  1080. This function assumes that from_sid and to_sid (from_nsubs and to_nsubs) are valid
  1081. /***************************************************************************************************/
  1082. DWORD
  1083. TSDRidCache::SizeDiff(
  1084. const TAcctNode * tnode // in -this parameter is not used for TSDRidCache
  1085. ) const
  1086. {
  1087. assert( from_sid ); // not having from_sid or to_sid should abort the program
  1088. assert( to_sid );
  1089. DWORD fromsize = GetSidLengthRequired(from_nsubs);
  1090. DWORD tosize = GetSidLengthRequired(to_nsubs);
  1091. DWORD retval;
  1092. if ( fromsize >= tosize )
  1093. {
  1094. retval = 0;
  1095. }
  1096. else
  1097. {
  1098. retval = tosize - fromsize;
  1099. }
  1100. return retval;
  1101. }
  1102. /*****************************************************************************************************/
  1103. /* DomainizeSidFst:
  1104. Takes a domain sid, and verifies that its last subauthority value is -1. If the RID is not
  1105. -1, DomainizeSid adds a -1 to the end.
  1106. /*****************************************************************************************************/
  1107. PSID // ret -the sid with RID = -1
  1108. DomainizeSidFst(
  1109. PSID psid, // in -sid to check and possibly fix
  1110. BOOL freeOldSid // in -whether to free the old sid
  1111. )
  1112. {
  1113. assert (psid);
  1114. UCHAR len = (* GetSidSubAuthorityCount(psid));
  1115. PDWORD sub = GetSidSubAuthority(psid,len-1);
  1116. if ( *sub != -1 )
  1117. {
  1118. DWORD sdsize = GetSidLengthRequired(len+1); // sid doesn't already have -1 as rid
  1119. PSID newsid = (SID *)malloc(sdsize); // copy the sid, and add -1 to the end
  1120. if (!newsid)
  1121. {
  1122. assert(false);
  1123. return psid;
  1124. }
  1125. if ( ! InitializeSid(newsid,GetSidIdentifierAuthority(psid),len+1) ) // make a bigger sid w/same IA
  1126. {
  1127. err.SysMsgWrite(ErrU,GetLastError(),DCT_MSG_INITIALIZE_SID_FAILED_D,GetLastError());
  1128. assert (false);
  1129. }
  1130. for ( DWORD i = 0 ; i < len ; i++ )
  1131. {
  1132. sub = GetSidSubAuthority(newsid,i); // copy subauthorities
  1133. (*sub) = (*GetSidSubAuthority(psid,i));
  1134. }
  1135. sub = GetSidSubAuthority(newsid,len);
  1136. *sub = -1; // set rid =-1
  1137. if ( freeOldSid )
  1138. {
  1139. free(psid);
  1140. }
  1141. psid = newsid;
  1142. len++;
  1143. }
  1144. return psid;
  1145. }
  1146. void
  1147. SetDomainInfoStructFromSid(
  1148. PSID pSid, // in -sid for domain
  1149. SDRDomainInfo * info // out-struct containing information
  1150. )
  1151. {
  1152. // if ( (pSid) )
  1153. if ( IsValidSid(pSid) )
  1154. {
  1155. info->domain_name[0] = 0;
  1156. info->dc_name[0] = 0;
  1157. info->domain_sid = DomainizeSidFst(pSid,FALSE/*don't free old sid*/);
  1158. info->nsubs = *GetSidSubAuthorityCount(info->domain_sid);
  1159. info->valid = TRUE;
  1160. }
  1161. else
  1162. {
  1163. // info->domain_name[0] = 0;
  1164. // info->dc_name[0] = 0;
  1165. // info->valid = TRUE;
  1166. err.MsgWrite(ErrE,DCT_MSG_INVALID_DOMAIN_SID);
  1167. info->valid = FALSE;
  1168. }
  1169. }
  1170. void
  1171. SetDomainInfoStruct(
  1172. WCHAR const * domname, // in -name of domain
  1173. SDRDomainInfo * info // in -struct to put info into
  1174. )
  1175. {
  1176. DWORD rc = 0;
  1177. WCHAR domain[LEN_Computer];
  1178. BOOL found = FALSE;
  1179. _bstr_t computer;
  1180. safecopy(domain,domname);
  1181. info->valid = FALSE;
  1182. safecopy(info->domain_name, domname);
  1183. // get the domain controller name
  1184. rc = GetAnyDcName4(domain, computer);
  1185. if ( rc == ERROR_SUCCESS )
  1186. {
  1187. safecopy(info->dc_name,(PCWSTR)computer);
  1188. }
  1189. if ( ! rc )
  1190. {
  1191. // Get the SID for the domain
  1192. WCHAR strDomain[LEN_Domain];
  1193. DWORD lenStrDomain = DIM(strDomain);
  1194. SID_NAME_USE snu;
  1195. BYTE sid[200];
  1196. DWORD lenSid = DIM(sid);
  1197. if ( LookupAccountName(info->dc_name,info->domain_name,sid,&lenSid,strDomain,&lenStrDomain,&snu) )
  1198. {
  1199. info->domain_sid = DomainizeSidFst(sid, FALSE /*don't free sid*/);
  1200. info->nsubs = *GetSidSubAuthorityCount(info->domain_sid);
  1201. info->valid = TRUE;
  1202. found = TRUE;
  1203. }
  1204. else
  1205. {
  1206. rc = GetLastError();
  1207. }
  1208. }
  1209. if ( rc )
  1210. {
  1211. err.SysMsgWrite(ErrE,rc,DCT_MSG_DOMAIN_GET_INFO_FAILED_S,domain);
  1212. }
  1213. }
  1214. int
  1215. TSDRidCache::SetDomainInfoWithSid(
  1216. WCHAR const * strDomain, // in -domain name
  1217. WCHAR const * strSid, // in -textual representation of sid
  1218. bool firstdom // in -flag: (true => source domain), (false => target domain)
  1219. )
  1220. {
  1221. SDRDomainInfo info;
  1222. PSID pSid = SidFromString(strSid);
  1223. SetDomainInfoStructFromSid(pSid,&info);
  1224. if ( info.valid )
  1225. {
  1226. if ( firstdom )
  1227. {
  1228. safecopy(from_domain,strDomain);
  1229. from_sid = info.domain_sid;
  1230. from_dc[0] = 0;
  1231. from_nsubs = info.nsubs;
  1232. }
  1233. else
  1234. {
  1235. safecopy(to_domain,strDomain);
  1236. to_sid = info.domain_sid;
  1237. to_dc[0] =0;
  1238. to_nsubs = info.nsubs;
  1239. }
  1240. }
  1241. FreeSid(pSid);
  1242. return info.valid;
  1243. }
  1244. /*****************************************************************************************************/
  1245. /* SetDomainInfo:
  1246. sets either ( from_domain, from_sid, from_dc, from_nsubs) if ( firstdom )
  1247. or ( to_domain, to_sid, to_dc, to_nsubs) if ( ! firstdom)
  1248. /*****************************************************************************************************/
  1249. int // ret -true if members were set, false otherwise
  1250. TSDRidCache::SetDomainInfo(
  1251. WCHAR const * domname, // in -name of domain
  1252. bool firstdom // in -flag: (true => source domain), (false => target domain)
  1253. )
  1254. {
  1255. SDRDomainInfo info;
  1256. SetDomainInfoStruct(domname,&info);
  1257. if ( info.valid ) // we have good information to store
  1258. {
  1259. if ( firstdom )
  1260. {
  1261. safecopy(from_domain,info.domain_name);
  1262. from_sid = info.domain_sid;
  1263. safecopy(from_dc,info.dc_name);
  1264. from_nsubs = info.nsubs;
  1265. }
  1266. else
  1267. {
  1268. safecopy(to_domain,info.domain_name);
  1269. to_sid = info.domain_sid;
  1270. safecopy(to_dc,info.dc_name);
  1271. to_nsubs = info.nsubs;
  1272. }
  1273. }
  1274. return info.valid;
  1275. }
  1276. LPWSTR
  1277. TGeneralCache::GetName(
  1278. const PSID psid // in - SID to lookup account name for
  1279. )
  1280. {
  1281. TGeneralSidNode * tn = (TGeneralSidNode*)Lookup(psid);
  1282. if ( tn )
  1283. return tn->GetAcctName();
  1284. else
  1285. return NULL;
  1286. }
  1287. TAcctNode *
  1288. TGeneralCache::Lookup(
  1289. const PSID psid // in - SID to lookup account name for
  1290. )
  1291. {
  1292. TGeneralSidNode * tn = (TGeneralSidNode*)Find(&vSidComp,psid);
  1293. return (TAcctNode *)tn;
  1294. }
  1295. /***************************************************************************************************/
  1296. /* Lookup: takes a sid, checks whether it came from domain A. If so, it finds the corresponding entry
  1297. in the cache, and returns that node.
  1298. Returns: Pointer to TSidNode whose domain A rid matches asid's rid,
  1299. or NULL if not a domain A sid, or not found in the cache
  1300. /***************************************************************************************************/
  1301. TAcctNode *
  1302. TSDRidCache::Lookup(
  1303. const PSID psid // in -sid to search for
  1304. )
  1305. {
  1306. TRidNode * tn = NULL;
  1307. DWORD rid = 0;
  1308. BOOL bFromSourceDomain;
  1309. UCHAR * pNsubs;
  1310. DWORD nsubs;
  1311. TAcctNode * anode = NULL;
  1312. assert( IsValidSid(psid) );
  1313. assert ( IsValidSid(from_sid) );
  1314. pNsubs = GetSidSubAuthorityCount(psid);
  1315. if ( pNsubs )
  1316. {
  1317. nsubs = (*pNsubs);
  1318. }
  1319. else
  1320. {
  1321. assert(false);
  1322. return NULL;
  1323. }
  1324. rid = (* GetSidSubAuthority(psid,nsubs - 1) );
  1325. // if ((!from_sid) || (EqualPrefixSid(psid,from_sid))) // first check whether asid matches the from-domain
  1326. if ( EqualPrefixSid(psid,from_sid) ) // first check whether asid matches the from-domain
  1327. {
  1328. bFromSourceDomain = TRUE;
  1329. tn = (TRidNode *)Find(&vRidComp,&rid);
  1330. anode = tn;
  1331. }
  1332. else
  1333. {
  1334. bFromSourceDomain = FALSE;
  1335. }
  1336. if (! tn )
  1337. {
  1338. tn = (TRidNode *)-1;
  1339. if ( AddIfNotFound() && ! BuiltinRid(rid) ) // Don't lookup builtin accounts
  1340. {
  1341. if ( ! m_otherAccounts )
  1342. {
  1343. m_otherAccounts = new TGeneralCache();
  1344. if (!m_otherAccounts)
  1345. {
  1346. assert(false);
  1347. return NULL;
  1348. }
  1349. }
  1350. TGeneralSidNode * sn = (TGeneralSidNode *)m_otherAccounts->Lookup(psid);
  1351. if ( ! sn )
  1352. {
  1353. sn = new TGeneralSidNode(psid,NULL);
  1354. if (!sn)
  1355. {
  1356. assert(false);
  1357. return NULL;
  1358. }
  1359. m_otherAccounts->TreeInsert(sn);
  1360. }
  1361. anode = (TAcctNode*)sn;
  1362. }
  1363. }
  1364. return anode;
  1365. }
  1366. /***************************************************************************************************/
  1367. /* GetName: Calls SidCache::Lookup, and returns the acct name from the resulting node
  1368. /***************************************************************************************************/
  1369. LPWSTR // ret -acct_name, or NULL if not found
  1370. TSDRidCache::GetName(
  1371. const PSID psid // in -sid to look for
  1372. )
  1373. {
  1374. TAcctNode * tn = Lookup(psid);
  1375. LPWSTR retval;
  1376. if ( tn )
  1377. retval = tn->GetAcctName();
  1378. else
  1379. retval = NULL;
  1380. return retval;
  1381. }
  1382. /***************************************************************************************************/
  1383. /* LookupWODomain: takes a sid, checks whether it came from domain A. If so, it finds the corresponding entry
  1384. in the cache, and returns that node. This lookup function is used if the
  1385. src domain sid has not been recorded (like in the case of using a sID mapping file).
  1386. Returns: Pointer to TSidNode whose domain A rid matches asid's rid,
  1387. or NULL if not a domain A sid, or not found in the cache
  1388. /***************************************************************************************************/
  1389. TAcctNode* TSDRidCache::LookupWODomain(const PSID psid)
  1390. {
  1391. TAcctNode* pAcctNode = NULL;
  1392. // if map is empty then construct rid to node map
  1393. if (m_mapRidToNode.empty())
  1394. {
  1395. TNodeTreeEnum nte(this);
  1396. for (TRidNode* pNode = (TRidNode*)nte.First(); pNode; pNode = (TRidNode*)nte.Next())
  1397. {
  1398. m_mapRidToNode.insert(CRidToNodeMap::value_type(pNode->SrcRid(), pNode));
  1399. }
  1400. }
  1401. // retrieve RID from given SID
  1402. assert(IsValidSid(psid));
  1403. PUCHAR pCount = GetSidSubAuthorityCount(psid);
  1404. if (pCount)
  1405. {
  1406. DWORD rid = (*GetSidSubAuthority(psid, *pCount - 1));
  1407. // retrieve range of nodes with matching RID
  1408. CRidToNodeMap::_Pairii pairii = m_mapRidToNode.equal_range(rid);
  1409. // for each node in range...
  1410. for (CRidToNodeMap::iterator it = pairii.first; it != pairii.second; it++)
  1411. {
  1412. // retrieve RID node and compare domain SIDs
  1413. TRidNode* pNode = it->second;
  1414. if (pNode)
  1415. {
  1416. PSID psidSrc = SidFromString(pNode->GetSrcDomSid());
  1417. if (psidSrc)
  1418. {
  1419. // if domain SIDs are equal...
  1420. if (EqualPrefixSid(psid, psidSrc))
  1421. {
  1422. // a match has been found
  1423. pAcctNode = pNode;
  1424. }
  1425. FreeSid(psidSrc);
  1426. if (pAcctNode)
  1427. {
  1428. break;
  1429. }
  1430. }
  1431. }
  1432. }
  1433. }
  1434. return pAcctNode;
  1435. }