Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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