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.

1458 lines
58 KiB

  1. /*****************************************************************************/
  2. /* Copyright (c) 1999-2001 Microsoft Corporation, All Rights Reserved /
  3. /*****************************************************************************/
  4. //=================================================================
  5. //
  6. // SecUtils.cpp -- Security utilities useful to wbem mof classes
  7. //
  8. // Copyright (c) 1999-2001 Microsoft Corporation, All Rights Reserved
  9. //
  10. // Revisions: 6/9/99 a-kevhu Created
  11. //
  12. //=================================================================
  13. #include "precomp.h"
  14. #include <assertbreak.h>
  15. #include "AccessEntry.h" // CAccessEntry class
  16. #include "AccessEntryList.h"
  17. #include "DACL.h" // CDACL class
  18. #include "SACL.h"
  19. #include "SecurityDescriptor.h"
  20. #include <accctrl.h>
  21. #include "AccessRights.h"
  22. #include "SecureFile.h"
  23. #include "SecureShare.h"
  24. #include "wbemnetapi32.h"
  25. #include "SecUtils.h"
  26. ///////////////////////////////////////////////////////////////////
  27. //
  28. // Function: FillTrusteeFromSid
  29. //
  30. // Default class constructor.
  31. //
  32. // Inputs:
  33. // None.
  34. //
  35. // Outputs:
  36. // None.
  37. //
  38. // Returns:
  39. // None.
  40. //
  41. // Comments:
  42. //
  43. ///////////////////////////////////////////////////////////////////
  44. void FillTrusteeFromSid (CInstance *pInstance, CSid &sid)
  45. {
  46. if (pInstance)
  47. {
  48. PSID pSid;
  49. CHString chstrName;
  50. CHString chstrDomain;
  51. VARIANT vValue;
  52. if (sid.IsValid())
  53. {
  54. pSid = sid.GetPSid();
  55. chstrName = sid.GetAccountName();
  56. chstrDomain = sid.GetDomainName();
  57. // set the UINT8 array for the pSid
  58. DWORD dwSidLength = sid.GetLength();
  59. // BYTE bByte;
  60. SAFEARRAY* sa;
  61. SAFEARRAYBOUND rgsabound[1];
  62. VariantInit(&vValue);
  63. rgsabound[0].cElements = dwSidLength;
  64. PSID pSidTrustee = NULL ;
  65. rgsabound[0].lLbound = 0;
  66. sa = SafeArrayCreate(VT_UI1, 1, rgsabound);
  67. // Get a pointer to read the data into
  68. SafeArrayAccessData(sa, &pSidTrustee);
  69. memcpy(pSidTrustee, pSid, rgsabound[0].cElements);
  70. SafeArrayUnaccessData(sa);
  71. // Put the safearray into a variant, and send it off
  72. V_VT(&vValue) = VT_UI1 | VT_ARRAY; V_ARRAY(&vValue) = sa;
  73. pInstance->SetVariant(IDS_Sid, vValue);
  74. VariantClear(&vValue);
  75. // fill in the rest of the stuff.
  76. if(!chstrName.IsEmpty())
  77. {
  78. pInstance->SetCHString(IDS_Name, chstrName);
  79. }
  80. if(!chstrDomain.IsEmpty())
  81. {
  82. pInstance->SetCHString(IDS_Domain, chstrDomain);
  83. }
  84. pInstance->SetDWORD(IDS_SidLength, dwSidLength);
  85. // Fill in the SIDString property...
  86. pInstance->SetCHString(IDS_SIDString, sid.GetSidString());
  87. }
  88. }
  89. }
  90. ///////////////////////////////////////////////////////////////////
  91. //
  92. // Function: FillInstanceDACL
  93. //
  94. // Default class constructor.
  95. //
  96. // Inputs:
  97. // None.
  98. //
  99. // Outputs:
  100. // None.
  101. //
  102. // Returns:
  103. // None.
  104. //
  105. // Comments:
  106. //
  107. ///////////////////////////////////////////////////////////////////
  108. void FillInstanceDACL(CInstance *pInstance, CDACL &dacl)
  109. {
  110. CAccessEntry ace;
  111. SAFEARRAY* saDACL;
  112. SAFEARRAYBOUND rgsabound[1];
  113. VARIANT vValue;
  114. if ( pInstance && !dacl.IsEmpty() )
  115. {
  116. // First need merged list...
  117. CAccessEntryList t_cael;
  118. if(dacl.GetMergedACL(t_cael))
  119. {
  120. DWORD dwSize;
  121. long ix[1];
  122. dwSize = t_cael.NumEntries();
  123. rgsabound[0].cElements = dwSize;
  124. rgsabound[0].lLbound = 0;
  125. saDACL = SafeArrayCreate(VT_UNKNOWN, 1, rgsabound);
  126. ix[0] = 0;
  127. ACLPOSITION pos;
  128. t_cael.BeginEnum(pos);
  129. while (t_cael.GetNext(pos, ace))
  130. {
  131. CInstancePtr pAce;
  132. CInstancePtr pTrustee;
  133. // now that we have the ACE, let's create a Win32_ACE object so we can
  134. // add it to the embedded object list.
  135. if (SUCCEEDED(CWbemProviderGlue::GetEmptyInstance(pInstance->GetMethodContext(), L"Win32_Ace", &pAce, IDS_CimWin32Namespace ) ) )
  136. {
  137. // fill trustee from SID
  138. CSid sid;
  139. ace.GetSID(sid);
  140. if (SUCCEEDED(CWbemProviderGlue::GetEmptyInstance(pInstance->GetMethodContext(), L"Win32_Trustee", &pTrustee, IDS_CimWin32Namespace )))
  141. {
  142. FillTrusteeFromSid(pTrustee, sid);
  143. pAce->SetEmbeddedObject(IDS_Trustee, *pTrustee);
  144. // pTrustee->Release() ;
  145. } // end if
  146. DWORD dwAceType = ace.GetACEType();
  147. DWORD dwAceFlags = ace.GetACEFlags();
  148. DWORD dwAccessMask = ace.GetAccessMask ();
  149. pAce->SetDWORD(IDS_AceType, dwAceType);
  150. pAce->SetDWORD(IDS_AceFlags, dwAceFlags);
  151. pAce->SetDWORD(IDS_AccessMask, dwAccessMask);
  152. #ifdef NTONLY
  153. #if NTONLY > 5
  154. // fill Guids
  155. GUID guidObjType, guidInhObjType;
  156. if(ace.GetObjType(guidObjType))
  157. {
  158. WCHAR wstrGuid[39];
  159. if(::StringFromGUID2(&guidObjType, wstrGuid, 39))
  160. {
  161. pAce->SetWCHARSplat(IDS_GuidObjectType, wstrGuid);
  162. }
  163. }
  164. if(ace.GetInhObjType(guidInhObjType))
  165. {
  166. WCHAR wstrGuid[39];
  167. if(::StringFromGUID2(&guidInhObjType, wstrGuid, 39))
  168. {
  169. pAce->SetWCHARSplat(IDS_GuidInheritedObjectType, wstrGuid);
  170. }
  171. }
  172. #endif
  173. #endif
  174. // Get the IUnknown of the Win32_ACE object. Convert it to a
  175. // variant of type VT_UNKNOWN. Then, add the variant to the
  176. // SafeArray. Eventually, to add the list to the actual
  177. // Win32_SecurityDescriptor object, we will be using SetVariant.
  178. // Note: it is intentional that we are not decrementing the Addref
  179. // done on pAce by the following call.
  180. IWbemClassObjectPtr pClassObject(pAce->GetClassObjectInterface());
  181. if ( pClassObject )
  182. {
  183. VARIANT v;
  184. VariantInit(&v);
  185. v.vt = VT_UNKNOWN;
  186. v.punkVal = pClassObject ;
  187. SafeArrayPutElement(saDACL, ix, pClassObject);
  188. VariantClear(&v);
  189. } // end if
  190. } // end if
  191. ix[0]++ ;
  192. } // end while
  193. VariantInit(&vValue);
  194. V_VT(&vValue) = VT_UNKNOWN | VT_ARRAY; V_ARRAY(&vValue) = saDACL;
  195. pInstance->SetVariant(IDS_DACL, vValue);
  196. VariantClear(&vValue);
  197. t_cael.EndEnum(pos);
  198. }
  199. }
  200. }
  201. ///////////////////////////////////////////////////////////////////
  202. //
  203. // Function: FillInstanceSACL
  204. //
  205. // Default class constructor.
  206. //
  207. // Inputs:
  208. // None.
  209. //
  210. // Outputs:
  211. // None.
  212. //
  213. // Returns:
  214. // None.
  215. //
  216. // Comments:
  217. //
  218. ///////////////////////////////////////////////////////////////////
  219. void FillInstanceSACL(CInstance *pInstance, CSACL &sacl)
  220. {
  221. CAccessEntry ace;
  222. CInstancePtr pAce;
  223. CInstancePtr pTrustee;
  224. SAFEARRAY* saSACL;
  225. SAFEARRAYBOUND rgsabound[1];
  226. VARIANT vValue;
  227. if ( pInstance && !sacl.IsEmpty() )
  228. {
  229. // First need merged list...
  230. CAccessEntryList t_cael;
  231. if(sacl.GetMergedACL(t_cael))
  232. {
  233. DWORD dwSize;
  234. long ix[1];
  235. dwSize = t_cael.NumEntries();
  236. rgsabound[0].cElements = dwSize;
  237. rgsabound[0].lLbound = 0;
  238. saSACL = SafeArrayCreate(VT_UNKNOWN, 1, rgsabound);
  239. ix[0] = 0;
  240. ACLPOSITION pos;
  241. t_cael.BeginEnum(pos);
  242. while (t_cael.GetNext(pos, ace))
  243. {
  244. // now that we have the ACE, let's create a Win32_ACE object so we can
  245. // add it to the embedded object list.
  246. if (SUCCEEDED(CWbemProviderGlue::GetEmptyInstance(pInstance->GetMethodContext(), L"Win32_Ace", &pAce, IDS_CimWin32Namespace)))
  247. {
  248. // fill trustee from SID
  249. CSid sid;
  250. ace.GetSID(sid);
  251. if (SUCCEEDED(CWbemProviderGlue::GetEmptyInstance(pInstance->GetMethodContext(), L"Win32_Trustee", &pTrustee, IDS_CimWin32Namespace )))
  252. {
  253. FillTrusteeFromSid(pTrustee, sid);
  254. pAce->SetEmbeddedObject(IDS_Trustee, *pTrustee);
  255. } // end if
  256. DWORD dwAceType = ace.GetACEType();
  257. DWORD dwAceFlags = ace.GetACEFlags();
  258. DWORD dwAccessMask = ace.GetAccessMask ();
  259. pAce->SetDWORD(IDS_AceType, dwAceType);
  260. pAce->SetDWORD(IDS_AceFlags, dwAceFlags);
  261. pAce->SetDWORD(IDS_AccessMask, dwAccessMask);
  262. #ifdef NTONLY
  263. #if NTONLY > 5
  264. // fill Guids
  265. GUID guidObjType, guidInhObjType;
  266. if(ace.GetObjType(guidObjType))
  267. {
  268. WCHAR wstrGuid[39];
  269. if(::StringFromGUID2(&guidObjType, wstrGuid, 39))
  270. {
  271. pAce->SetWCHARSplat(IDS_GuidObjectType, wstrGuid);
  272. }
  273. }
  274. if(ace.GetInhObjType(guidInhObjType))
  275. {
  276. WCHAR wstrGuid[39];
  277. if(::StringFromGUID2(&guidInhObjType, wstrGuid, 39))
  278. {
  279. pAce->SetWCHARSplat(IDS_GuidInheritedObjectType, wstrGuid);
  280. }
  281. }
  282. #endif
  283. #endif
  284. // Get the IUnknown of the Win32_ACE object. Convert it to a
  285. // variant of type VT_UNKNOWN. Then, add the variant to the
  286. // SafeArray. Eventually, to add the list to the actual
  287. // Win32_SecurityDescriptor object, we will be using SetVariant
  288. IWbemClassObjectPtr pClassObject(pAce->GetClassObjectInterface());
  289. if ( pClassObject )
  290. {
  291. VARIANT v;
  292. VariantInit(&v);
  293. v.vt = VT_UNKNOWN;
  294. v.punkVal = pClassObject ;
  295. SafeArrayPutElement(saSACL, ix, pClassObject);
  296. VariantClear(&v);
  297. } // end if
  298. } // end if
  299. ix[0]++ ;
  300. } // end while
  301. VariantInit(&vValue);
  302. V_VT(&vValue) = VT_UNKNOWN | VT_ARRAY; V_ARRAY(&vValue) = saSACL;
  303. pInstance->SetVariant(IDS_SACL, vValue);
  304. VariantClear(&vValue);
  305. t_cael.EndEnum(pos);
  306. }
  307. }
  308. }
  309. ///////////////////////////////////////////////////////////////////
  310. //
  311. // Function: FillDACLFromInstance
  312. //
  313. // Default class constructor.
  314. //
  315. // Inputs:
  316. // None.
  317. //
  318. // Outputs:
  319. // None.
  320. //
  321. // Returns:
  322. // None.
  323. //
  324. // Comments:
  325. //
  326. ///////////////////////////////////////////////////////////////////
  327. DWORD FillDACLFromInstance(CInstance *pInstance,
  328. CDACL &dacl,
  329. MethodContext *pMethodContext)
  330. {
  331. IWbemClassObjectPtr piClassObject;
  332. piClassObject.Attach(pInstance->GetClassObjectInterface());
  333. DWORD dwStatus = ERROR_SUCCESS ;
  334. if(piClassObject)
  335. {
  336. VARIANT vDacl ;
  337. if(GetArray(piClassObject,IDS_DACL, vDacl, VT_UNKNOWN|VT_ARRAY) )
  338. {
  339. if( vDacl.vt != VT_NULL && vDacl.parray != NULL )
  340. {
  341. // walk DACL
  342. LONG lDimension = 1 ;
  343. LONG lLowerBound ;
  344. SafeArrayGetLBound ( vDacl.parray , lDimension , &lLowerBound ) ;
  345. LONG lUpperBound ;
  346. SafeArrayGetUBound ( vDacl.parray , lDimension , &lUpperBound ) ;
  347. for ( LONG lIndex = lLowerBound ; lIndex <= lUpperBound ; lIndex++ )
  348. {
  349. if( dwStatus != ERROR_SUCCESS )
  350. {
  351. break ;
  352. }
  353. IWbemClassObjectPtr pACEObject;
  354. SafeArrayGetElement ( vDacl.parray , &lIndex , &pACEObject ) ;
  355. // take out IWbemClassObject and cast it to a Win32_ACE object.
  356. if(pACEObject)
  357. {
  358. CInstance ACEInstance(pACEObject, pMethodContext);
  359. // create an AccessEntry object from the Win32_ACE object.
  360. bool bExists =false ;
  361. VARTYPE eType ;
  362. // get Win32_Trustee object from Win32_ACE ...& decipher the ACE
  363. if ( ACEInstance.GetStatus ( IDS_Trustee, bExists , eType ) && bExists && eType == VT_UNKNOWN )
  364. {
  365. CInstancePtr pTrustee;
  366. if ( ACEInstance.GetEmbeddedObject ( IDS_Trustee, &pTrustee, ACEInstance.GetMethodContext() ) )
  367. {
  368. CSid sid ;
  369. if((dwStatus = FillSIDFromTrustee(pTrustee, sid)) == ERROR_SUCCESS)
  370. {
  371. DWORD dwAceType, dwAceFlags, dwAccessMask ;
  372. CHString chstrInhObjGuid;
  373. GUID *pguidInhObjGuid = NULL;
  374. CHString chstrObjGuid;
  375. GUID *pguidObjGuid = NULL;
  376. ACEInstance.GetDWORD(IDS_AceType, dwAceType);
  377. ACEInstance.GetDWORD(IDS_AceFlags, dwAceFlags);
  378. ACEInstance.GetDWORD(IDS_AccessMask, dwAccessMask);
  379. // The OS doesn't seem to support 0x01000000 or 0x02000000, so we won't either. We
  380. // will translate 0x02000000 into FILE_ALL_ACCESS, however (seems like the nice thing to do)
  381. // but only if that is the exact value they set.
  382. if(dwAccessMask == 0x02000000)
  383. {
  384. dwAccessMask = FILE_ALL_ACCESS;
  385. }
  386. #if NTONLY >= 5
  387. // On NT5 and greater, if the user specified an ACE with the Ace Flag bit INHERIT_ACE set,
  388. // the OS will make these local, not inherited ACE entries. However, the OS will not reorder
  389. // the DACL, possibly resulting in a situation in which denied ACEs (that had been inherited)
  390. // follow allowed ACEs.
  391. // So if the Ace flags specify INHERITED_ACE, we need to turn
  392. // off this bit...
  393. dwAceFlags &= ~INHERITED_ACE;
  394. #endif
  395. if(!(dwAceFlags & INHERITED_ACE))
  396. {
  397. switch (dwAceType)
  398. {
  399. case ACCESS_DENIED_ACE_TYPE:
  400. {
  401. dacl.AddDACLEntry( sid.GetPSid(), ENUM_ACCESS_DENIED_ACE_TYPE, dwAccessMask, dwAceFlags, NULL, NULL );
  402. break;
  403. }
  404. case ACCESS_ALLOWED_ACE_TYPE:
  405. {
  406. dacl.AddDACLEntry( sid.GetPSid(), ENUM_ACCESS_ALLOWED_ACE_TYPE, dwAccessMask, dwAceFlags, NULL, NULL );
  407. break;
  408. }
  409. #if NTONLY >= 5
  410. // Not yet supported under W2K
  411. //case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
  412. // {
  413. // dacl.AddDACLEntry( sid.GetPSid(), ENUM_ACCESS_ALLOWED_COMPOUND_ACE_TYPE, dwAccessMask, dwAceFlags, NULL, NULL );
  414. // break;
  415. // }
  416. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  417. {
  418. // Need to get the guids for this type...
  419. if(!ACEInstance.IsNull(IDS_ObjectTypeGUID) && ACEInstance.GetCHString(IDS_ObjectTypeGUID, chstrObjGuid))
  420. {
  421. if(chstrObjGuid.GetLength() != 0)
  422. {
  423. try
  424. {
  425. pguidObjGuid = new GUID;
  426. }
  427. catch(...)
  428. {
  429. if(pguidObjGuid != NULL)
  430. {
  431. delete pguidObjGuid;
  432. pguidObjGuid = NULL;
  433. }
  434. }
  435. CLSIDFromString((LPWSTR)(LPCWSTR)chstrObjGuid, pguidObjGuid);
  436. }
  437. }
  438. if(!ACEInstance.IsNull(IDS_InheritedObjectGUID) && ACEInstance.GetCHString(IDS_InheritedObjectGUID, chstrInhObjGuid))
  439. {
  440. if(chstrInhObjGuid.GetLength() != 0)
  441. {
  442. try
  443. {
  444. pguidInhObjGuid = new GUID;
  445. }
  446. catch(...)
  447. {
  448. if(pguidInhObjGuid != NULL)
  449. {
  450. delete pguidInhObjGuid;
  451. pguidInhObjGuid = NULL;
  452. }
  453. }
  454. CLSIDFromString((LPWSTR)(LPCWSTR)chstrInhObjGuid, pguidInhObjGuid);
  455. }
  456. }
  457. dacl.AddDACLEntry( sid.GetPSid(), ENUM_ACCESS_DENIED_OBJECT_ACE_TYPE, dwAccessMask, dwAceFlags, pguidObjGuid, pguidInhObjGuid);
  458. if(pguidObjGuid != NULL) delete pguidObjGuid;
  459. if(pguidInhObjGuid != NULL) delete pguidInhObjGuid;
  460. break;
  461. }
  462. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  463. {
  464. // Need to get the guids for this type...
  465. if(!ACEInstance.IsNull(IDS_ObjectTypeGUID) && ACEInstance.GetCHString(IDS_ObjectTypeGUID, chstrObjGuid))
  466. {
  467. if(chstrObjGuid.GetLength() != 0)
  468. {
  469. try
  470. {
  471. pguidObjGuid = new GUID;
  472. }
  473. catch(...)
  474. {
  475. if(pguidObjGuid != NULL)
  476. {
  477. delete pguidObjGuid;
  478. pguidObjGuid = NULL;
  479. }
  480. }
  481. CLSIDFromString((LPWSTR)(LPCWSTR)chstrObjGuid, pguidObjGuid);
  482. }
  483. }
  484. if(!ACEInstance.IsNull(IDS_InheritedObjectGUID) && ACEInstance.GetCHString(IDS_InheritedObjectGUID, chstrInhObjGuid))
  485. {
  486. if(chstrInhObjGuid.GetLength() != 0)
  487. {
  488. try
  489. {
  490. pguidInhObjGuid = new GUID;
  491. }
  492. catch(...)
  493. {
  494. if(pguidInhObjGuid != NULL)
  495. {
  496. delete pguidInhObjGuid;
  497. pguidInhObjGuid = NULL;
  498. }
  499. }
  500. CLSIDFromString((LPWSTR)(LPCWSTR)chstrInhObjGuid, pguidInhObjGuid);
  501. }
  502. }
  503. dacl.AddDACLEntry( sid.GetPSid(), ENUM_ACCESS_ALLOWED_OBJECT_ACE_TYPE, dwAccessMask, dwAceFlags, pguidObjGuid, pguidInhObjGuid);
  504. if(pguidObjGuid != NULL) delete pguidObjGuid;
  505. if(pguidInhObjGuid != NULL) delete pguidInhObjGuid;
  506. break;
  507. }
  508. #endif
  509. default:
  510. {
  511. dwStatus = ERROR_INVALID_PARAMETER ;
  512. break ;
  513. }
  514. }
  515. }
  516. else
  517. {
  518. switch (dwAceType)
  519. {
  520. case ACCESS_DENIED_ACE_TYPE:
  521. {
  522. dacl.AddDACLEntry( sid.GetPSid(), ENUM_INH_ACCESS_DENIED_ACE_TYPE, dwAccessMask, dwAceFlags, NULL, NULL );
  523. break;
  524. }
  525. case ACCESS_ALLOWED_ACE_TYPE:
  526. {
  527. dacl.AddDACLEntry( sid.GetPSid(), ENUM_INH_ACCESS_ALLOWED_ACE_TYPE, dwAccessMask, dwAceFlags, NULL, NULL );
  528. break;
  529. }
  530. #if NTONLY >= 5
  531. // Not yet supported under W2K
  532. //case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
  533. // {
  534. // dacl.AddDACLEntry( sid.GetPSid(), ENUM_INH_ACCESS_ALLOWED_COMPOUND_ACE_TYPE, dwAccessMask, dwAceFlags, NULL, NULL );
  535. // break;
  536. // }
  537. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  538. {
  539. // Need to get the guids for this type...
  540. if(!ACEInstance.IsNull(IDS_ObjectTypeGUID) && ACEInstance.GetCHString(IDS_ObjectTypeGUID, chstrObjGuid))
  541. {
  542. if(chstrObjGuid.GetLength() != 0)
  543. {
  544. try
  545. {
  546. pguidObjGuid = new GUID;
  547. }
  548. catch(...)
  549. {
  550. if(pguidObjGuid != NULL)
  551. {
  552. delete pguidObjGuid;
  553. pguidObjGuid = NULL;
  554. }
  555. }
  556. CLSIDFromString((LPWSTR)(LPCWSTR)chstrObjGuid, pguidObjGuid);
  557. }
  558. }
  559. if(!ACEInstance.IsNull(IDS_InheritedObjectGUID) && ACEInstance.GetCHString(IDS_InheritedObjectGUID, chstrInhObjGuid))
  560. {
  561. if(chstrInhObjGuid.GetLength() != 0)
  562. {
  563. try
  564. {
  565. pguidInhObjGuid = new GUID;
  566. }
  567. catch(...)
  568. {
  569. if(pguidInhObjGuid != NULL)
  570. {
  571. delete pguidInhObjGuid;
  572. pguidInhObjGuid = NULL;
  573. }
  574. }
  575. CLSIDFromString((LPWSTR)(LPCWSTR)chstrInhObjGuid, pguidInhObjGuid);
  576. }
  577. }
  578. dacl.AddDACLEntry( sid.GetPSid(), ENUM_INH_ACCESS_DENIED_OBJECT_ACE_TYPE, dwAccessMask, dwAceFlags, pguidObjGuid, pguidInhObjGuid );
  579. if(pguidObjGuid != NULL) delete pguidObjGuid;
  580. if(pguidInhObjGuid != NULL) delete pguidInhObjGuid;
  581. break;
  582. }
  583. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  584. {
  585. // Need to get the guids for this type...
  586. if(!ACEInstance.IsNull(IDS_ObjectTypeGUID) && ACEInstance.GetCHString(IDS_ObjectTypeGUID, chstrObjGuid))
  587. {
  588. if(chstrObjGuid.GetLength() != 0)
  589. {
  590. try
  591. {
  592. pguidObjGuid = new GUID;
  593. }
  594. catch(...)
  595. {
  596. if(pguidObjGuid != NULL)
  597. {
  598. delete pguidObjGuid;
  599. pguidObjGuid = NULL;
  600. }
  601. }
  602. CLSIDFromString((LPWSTR)(LPCWSTR)chstrObjGuid, pguidObjGuid);
  603. }
  604. }
  605. if(!ACEInstance.IsNull(IDS_InheritedObjectGUID) && ACEInstance.GetCHString(IDS_InheritedObjectGUID, chstrInhObjGuid))
  606. {
  607. if(chstrInhObjGuid.GetLength() != 0)
  608. {
  609. try
  610. {
  611. pguidInhObjGuid = new GUID;
  612. }
  613. catch(...)
  614. {
  615. if(pguidInhObjGuid != NULL)
  616. {
  617. delete pguidInhObjGuid;
  618. pguidInhObjGuid = NULL;
  619. }
  620. }
  621. CLSIDFromString((LPWSTR)(LPCWSTR)chstrInhObjGuid, pguidInhObjGuid);
  622. }
  623. }
  624. dacl.AddDACLEntry( sid.GetPSid(), ENUM_INH_ACCESS_ALLOWED_OBJECT_ACE_TYPE, dwAccessMask, dwAceFlags, pguidObjGuid, pguidInhObjGuid );
  625. if(pguidObjGuid != NULL) delete pguidObjGuid;
  626. if(pguidInhObjGuid != NULL) delete pguidInhObjGuid;
  627. break;
  628. }
  629. #endif
  630. default:
  631. {
  632. dwStatus = ERROR_INVALID_PARAMETER ;
  633. break ;
  634. }
  635. }
  636. }
  637. }
  638. else
  639. {
  640. dwStatus = ERROR_INVALID_PARAMETER;
  641. }
  642. //pTrustee->Release(); // smartpointer already releases when goes out of scope
  643. }
  644. } // get Win32_Trustee object from Win32_ACE ...& decipher the ACE
  645. }
  646. } // end for loop
  647. if(lLowerBound == 0 && lUpperBound == -1L)
  648. {
  649. // DACL was EMPTY - not necessarily wrong
  650. dwStatus = STATUS_EMPTY_DACL;
  651. }
  652. }
  653. VariantClear( &vDacl ) ;
  654. }
  655. else //DACL was NULL - not nescessarily wrong.
  656. {
  657. dwStatus = STATUS_NULL_DACL ;
  658. }
  659. }
  660. return dwStatus ;
  661. }
  662. ///////////////////////////////////////////////////////////////////
  663. //
  664. // Function: FillSACLFromInstance
  665. //
  666. // Default class constructor.
  667. //
  668. // Inputs:
  669. // None.
  670. //
  671. // Outputs:
  672. // None.
  673. //
  674. // Returns:
  675. // None.
  676. //
  677. // Comments:
  678. //
  679. ///////////////////////////////////////////////////////////////////
  680. DWORD FillSACLFromInstance(CInstance *pInstance,
  681. CSACL &sacl,
  682. MethodContext *pMethodContext)
  683. {
  684. IWbemClassObjectPtr piClassObject;
  685. piClassObject.Attach(pInstance->GetClassObjectInterface());
  686. DWORD dwStatus = ERROR_SUCCESS ;
  687. if(piClassObject)
  688. {
  689. VARIANT vSacl ;
  690. if(GetArray(piClassObject, IDS_SACL, vSacl, VT_UNKNOWN|VT_ARRAY ) )
  691. {
  692. if( vSacl.vt != VT_NULL && vSacl.parray != NULL )
  693. {
  694. // walk DACL
  695. LONG lDimension = 1 ;
  696. LONG lLowerBound ;
  697. SafeArrayGetLBound ( vSacl.parray , lDimension , &lLowerBound ) ;
  698. LONG lUpperBound ;
  699. SafeArrayGetUBound ( vSacl.parray , lDimension , &lUpperBound ) ;
  700. for ( LONG lIndex = lLowerBound ; lIndex <= lUpperBound ; lIndex++ )
  701. {
  702. if( dwStatus != ERROR_SUCCESS )
  703. {
  704. break ;
  705. }
  706. IWbemClassObjectPtr pACEObject;
  707. SafeArrayGetElement ( vSacl.parray , &lIndex , &pACEObject ) ;
  708. // take out IWbemClassObject and cast it to a Win32_ACE object.
  709. if(pACEObject)
  710. {
  711. CInstance ACEInstance(pACEObject, pMethodContext);
  712. // create an AccessEntry object from the Win32_ACE object.
  713. bool bExists =false ;
  714. VARTYPE eType ;
  715. // get Win32_Trustee object from Win32_ACE ...& decipher the ACE
  716. if ( ACEInstance.GetStatus ( IDS_Trustee, bExists , eType ) && bExists && eType == VT_UNKNOWN )
  717. {
  718. CInstancePtr pTrustee;
  719. if ( ACEInstance.GetEmbeddedObject ( IDS_Trustee, &pTrustee, ACEInstance.GetMethodContext() ) )
  720. {
  721. CSid sid ;
  722. if(FillSIDFromTrustee(pTrustee, sid) == ERROR_SUCCESS)
  723. {
  724. DWORD dwAceType, dwAceFlags, dwAccessMask ;
  725. CHString chstrInhObjGuid;
  726. GUID *pguidInhObjGuid = NULL;
  727. CHString chstrObjGuid;
  728. GUID *pguidObjGuid = NULL;
  729. ACEInstance.GetDWORD(IDS_AceType, dwAceType);
  730. ACEInstance.GetDWORD(IDS_AceFlags, dwAceFlags);
  731. ACEInstance.GetDWORD(IDS_AccessMask, dwAccessMask);
  732. switch(dwAceType)
  733. {
  734. case SYSTEM_AUDIT_ACE_TYPE:
  735. {
  736. sacl.AddSACLEntry( sid.GetPSid(), ENUM_SYSTEM_AUDIT_ACE_TYPE, dwAccessMask, dwAceFlags, NULL, NULL );
  737. break;
  738. }
  739. #if NTONLY >= 5
  740. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  741. {
  742. // Need to get the guids for this type...
  743. if(!ACEInstance.IsNull(IDS_ObjectTypeGUID) && ACEInstance.GetCHString(IDS_ObjectTypeGUID, chstrObjGuid))
  744. {
  745. if(chstrObjGuid.GetLength() != 0)
  746. {
  747. try
  748. {
  749. pguidObjGuid = new GUID;
  750. }
  751. catch(...)
  752. {
  753. if(pguidObjGuid != NULL)
  754. {
  755. delete pguidObjGuid;
  756. pguidObjGuid = NULL;
  757. }
  758. }
  759. CLSIDFromString((LPWSTR)(LPCWSTR)chstrObjGuid, pguidObjGuid);
  760. }
  761. }
  762. if(!ACEInstance.IsNull(IDS_InheritedObjectGUID) && ACEInstance.GetCHString(IDS_InheritedObjectGUID, chstrInhObjGuid))
  763. {
  764. if(chstrInhObjGuid.GetLength() != 0)
  765. {
  766. try
  767. {
  768. pguidInhObjGuid = new GUID;
  769. }
  770. catch(...)
  771. {
  772. if(pguidInhObjGuid != NULL)
  773. {
  774. delete pguidInhObjGuid;
  775. pguidInhObjGuid = NULL;
  776. }
  777. }
  778. CLSIDFromString((LPWSTR)(LPCWSTR)chstrInhObjGuid, pguidInhObjGuid);
  779. }
  780. }
  781. sacl.AddSACLEntry( sid.GetPSid(), ENUM_SYSTEM_AUDIT_OBJECT_ACE_TYPE, dwAccessMask, dwAceFlags, pguidObjGuid, pguidInhObjGuid );
  782. if(pguidObjGuid != NULL) delete pguidObjGuid;
  783. if(pguidInhObjGuid != NULL) delete pguidInhObjGuid;
  784. break;
  785. }
  786. /********************************* type not yet supported under w2k ********************************************
  787. case SYSTEM_ALARM_ACE_TYPE:
  788. {
  789. sacl.AddSACLEntry( sid.GetPSid(), ENUM_SYSTEM_ALARM_ACE_TYPE, dwAccessMask, dwAceFlags, NULL, NULL );
  790. break;
  791. }
  792. /********************************* type not yet supported under w2k ********************************************
  793. /********************************* type not yet supported under w2k ********************************************
  794. case SYSTEM_ALARM_OBJECT_ACE_TYPE:
  795. {
  796. // Need to get the guids for this type...
  797. if(!ACEInstance.IsNull(IDS_ObjectTypeGUID) && ACEInstance.GetCHString(IDS_ObjectTypeGUID, chstrObjGuid))
  798. {
  799. if(chstrObjGuid.GetLength() != 0)
  800. {
  801. try
  802. {
  803. pguidObjGuid = new GUID;
  804. }
  805. catch(...)
  806. {
  807. if(pguidObjGuid != NULL)
  808. {
  809. delete pguidObjGuid;
  810. pguidObjGuid = NULL;
  811. }
  812. }
  813. CLSIDFromString((LPWSTR)(LPCWSTR)chstrObjGuid, pguidObjGuid);
  814. }
  815. }
  816. if(!ACEInstance.IsNull(IDS_InheritedObjectGUID) && ACEInstance.GetCHString(IDS_InheritedObjectGUID, chstrInhObjGuid))
  817. {
  818. if(chstrInhObjGuid.GetLength() != 0)
  819. {
  820. try
  821. {
  822. pguidInhObjGuid = new GUID;
  823. }
  824. catch(...)
  825. {
  826. if(pguidInhObjGuid != NULL)
  827. {
  828. delete pguidInhObjGuid;
  829. pguidInhObjGuid = NULL;
  830. }
  831. }
  832. CLSIDFromString((LPWSTR)(LPCWSTR)chstrInhObjGuid, pguidInhObjGuid);
  833. }
  834. }
  835. sacl.AddSACLEntry( sid.GetPSid(), ENUM_SYSTEM_ALARM_OBJECT_ACE_TYPE, dwAccessMask, dwAceFlags, pguidObjGuid, pguidInhObjGuid );
  836. if(pguidObjGuid != NULL) delete pguidObjGuid;
  837. if(pguidInhObjGuid != NULL) delete pguidInhObjGuid;
  838. break;
  839. }
  840. /********************************* type not yet supported under w2k ********************************************/
  841. #endif
  842. default:
  843. {
  844. dwStatus = ERROR_INVALID_PARAMETER ;
  845. break;
  846. }
  847. }
  848. }
  849. else
  850. {
  851. dwStatus = ERROR_INVALID_PARAMETER;
  852. }
  853. //pTrustee->Release(); // smartpointer already releases when goes out of scope
  854. }
  855. } // get Win32_Trustee object from Win32_ACE ...& decipher the ACE
  856. } //if(pACEObject)
  857. } //for
  858. } //if(pSACL)
  859. VariantClear( &vSacl ) ;
  860. }
  861. else
  862. {
  863. dwStatus = ERROR_INVALID_PARAMETER ;
  864. }
  865. }
  866. return dwStatus ;
  867. }
  868. bool GetArray(IWbemClassObject *piClassObject,
  869. const CHString &name,
  870. VARIANT &v,
  871. VARTYPE eVariantType)
  872. {
  873. bool bRet = FALSE;
  874. VariantInit(&v);
  875. if (piClassObject)
  876. {
  877. BSTR pName = NULL;
  878. HRESULT hr;
  879. try
  880. {
  881. pName = name.AllocSysString();
  882. hr = piClassObject->Get(pName, 0, &v, NULL, NULL);
  883. SysFreeString(pName);
  884. }
  885. catch(...)
  886. {
  887. if(pName != NULL)
  888. {
  889. SysFreeString(pName);
  890. pName = NULL;
  891. }
  892. throw;
  893. }
  894. ASSERT_BREAK((SUCCEEDED(hr)) && ((v.vt == VT_NULL) || (v.vt == eVariantType )));
  895. if (bRet = (bool)SUCCEEDED(hr))
  896. {
  897. if ( v.vt != VT_NULL && v.parray != NULL )
  898. {
  899. if (v.vt == eVariantType )
  900. {
  901. bRet = TRUE ;
  902. }
  903. else
  904. {
  905. bRet = FALSE;
  906. }
  907. }
  908. else
  909. {
  910. bRet = FALSE;
  911. }
  912. }
  913. }
  914. if (!bRet)
  915. {
  916. VariantClear(&v);
  917. }
  918. return bRet;
  919. }
  920. DWORD FillSIDFromTrustee(CInstance *pTrustee, CSid &sid)
  921. {
  922. IWbemClassObjectPtr m_piClassObject;
  923. DWORD dwStatus = ERROR_SUCCESS ;
  924. if(pTrustee)
  925. {
  926. m_piClassObject.Attach(pTrustee->GetClassObjectInterface());
  927. VARIANT vtmp ;
  928. bool fSidObtained = false;
  929. if(GetArray(m_piClassObject,IDS_SID, vtmp, VT_UI1|VT_ARRAY ) )
  930. {
  931. if( vtmp.vt != VT_NULL && vtmp.parray != NULL )
  932. {
  933. if ( ::SafeArrayGetDim ( vtmp.parray ) == 1 )
  934. {
  935. long lLowerBound , lUpperBound = 0 ;
  936. ::SafeArrayGetLBound ( vtmp.parray, 1, & lLowerBound ) ;
  937. ::SafeArrayGetUBound ( vtmp.parray, 1, & lUpperBound ) ;
  938. PSID pSid = NULL ;
  939. PVOID pTmp = NULL ;
  940. if(SUCCEEDED(::SafeArrayAccessData(vtmp.parray, &pTmp) ) )
  941. {
  942. pSid = (PSID) malloc(lUpperBound - lLowerBound + 1) ;
  943. if(pSid)
  944. {
  945. try
  946. {
  947. memcpy(pSid,pTmp,lUpperBound - lLowerBound + 1) ;
  948. ::SafeArrayUnaccessData(vtmp.parray) ;
  949. sid = CSid(pSid);
  950. free(pSid) ;
  951. pSid = NULL;
  952. fSidObtained = true;
  953. }
  954. catch(...)
  955. {
  956. free(pSid) ;
  957. pSid = NULL;
  958. throw;
  959. }
  960. }
  961. else
  962. {
  963. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  964. }
  965. }
  966. else
  967. {
  968. dwStatus = ERROR_INVALID_PARAMETER ;
  969. }
  970. }
  971. else
  972. {
  973. dwStatus = ERROR_INVALID_PARAMETER ;
  974. }
  975. }
  976. ::VariantClear( &vtmp ) ;
  977. }
  978. if(!fSidObtained && (dwStatus == ERROR_SUCCESS))
  979. {
  980. // If we couldn't obtain the sid from the binary
  981. // representation, try to do so from the sid string
  982. // representation (the SIDString property)...
  983. CHString chstrSIDString;
  984. if(pTrustee->GetCHString(IDS_SIDString, chstrSIDString) &&
  985. chstrSIDString.GetLength() > 0)
  986. {
  987. PSID pSid = NULL;
  988. pSid = StrToSID(chstrSIDString);
  989. if(pSid)
  990. {
  991. try
  992. {
  993. sid = CSid(pSid);
  994. ::FreeSid(pSid);
  995. pSid = NULL;
  996. fSidObtained = true;
  997. }
  998. catch(...)
  999. {
  1000. ::FreeSid(pSid);
  1001. pSid = NULL;
  1002. throw;
  1003. }
  1004. }
  1005. else
  1006. {
  1007. dwStatus = ERROR_INVALID_PARAMETER;
  1008. }
  1009. }
  1010. // If we couldn't obtain the sid from either the binary
  1011. // representation or the SIDString representation, try to
  1012. // do so from the Domain and Name properties (attempting
  1013. // resolution on the local machine for lack of a better
  1014. // choice)...
  1015. if(!fSidObtained && (dwStatus == ERROR_SUCCESS))
  1016. {
  1017. CHString chstrDomain, chstrName;
  1018. pTrustee->GetCHString(IDS_Domain, chstrDomain);
  1019. // Although we don't care whether we were able
  1020. // to get the Domain above, we must at least have
  1021. // a Name property specified...
  1022. if(pTrustee->GetCHString(IDS_Name, chstrName) &&
  1023. chstrName.GetLength() > 0)
  1024. {
  1025. CSid csTmp(chstrDomain, chstrName, NULL);
  1026. if(csTmp.IsOK() && csTmp.IsValid())
  1027. {
  1028. sid = csTmp;
  1029. fSidObtained = true;
  1030. }
  1031. }
  1032. }
  1033. }
  1034. if(!fSidObtained && (dwStatus == ERROR_SUCCESS))
  1035. {
  1036. dwStatus = ERROR_INVALID_PARAMETER ;
  1037. }
  1038. }
  1039. else
  1040. {
  1041. dwStatus = ERROR_INVALID_PARAMETER;
  1042. }
  1043. return dwStatus ;
  1044. }
  1045. #ifdef NTONLY
  1046. // Handy utility to dump the contents of a descriptor to
  1047. // our log file.
  1048. void DumpWin32Descriptor(PSECURITY_DESCRIPTOR psd, LPCWSTR wstrFilename)
  1049. {
  1050. CSecurityDescriptor csd(psd);
  1051. csd.DumpDescriptor();
  1052. }
  1053. #endif
  1054. #ifdef NTONLY
  1055. void Output(LPCWSTR wstrOut, LPCWSTR wstrFilename)
  1056. {
  1057. // Single point where we can control where output from
  1058. // all security utility class Dump routines goes...
  1059. if(wstrFilename == NULL)
  1060. {
  1061. LogMessage(wstrOut);
  1062. }
  1063. else
  1064. {
  1065. FILE *fp = NULL;
  1066. if((fp = _wfopen(wstrFilename, L"at")) != NULL)
  1067. {
  1068. fwprintf(fp, wstrOut);
  1069. fwprintf(fp,L"\r\n");
  1070. fclose(fp);
  1071. }
  1072. fp = NULL;
  1073. }
  1074. }
  1075. #endif
  1076. // Returns true if the user associated with the current
  1077. // thread is either the owner or is a member of the group
  1078. // that is the owner - e.g., it returns true if said user
  1079. // has ownership of the object specified by chstrName.
  1080. #ifdef NTONLY
  1081. bool AmIAnOwner(const CHString &chstrName, SE_OBJECT_TYPE ObjectType)
  1082. {
  1083. bool fRet = false;
  1084. // ALGORITHM OVERVIEW
  1085. // 1) Get the sid of the user associated with the current thread.
  1086. // 2) Get the owner of the object.
  1087. // 3a) Compare the sid from #2 to that from #1. fRet is true if they are equal.
  1088. // 3b) If not, owner's sid may be that of a group, and the user might be a
  1089. // member of that group, or of a group (which would have to be a global group)
  1090. // within that group. Fortunately that doesnt't recurse indefinitely, since
  1091. // local groups can contain only global groups, and global groups can contain
  1092. // only users (they can't be a container for other global or local groups) - see
  1093. // "Windows NT Security" (Nik Okuntseff), pp. 34-35.
  1094. // So here we go...
  1095. // 1) Get the sid of the user associated with the current thread. Also filter out only object types we are equiped to deal with...
  1096. if(ObjectType == SE_FILE_OBJECT || ObjectType == SE_LMSHARE)
  1097. {
  1098. CAccessRights car(true); // true tells car to use the user associated with the current thread token
  1099. CSid csidCurrentUser;
  1100. if(car.GetCSid(csidCurrentUser, true)) // true signals that we want car to be initialized with the domain and name looked up
  1101. {
  1102. // 2) Get the owner of the object.
  1103. CSid csidOwner;
  1104. switch(ObjectType)
  1105. {
  1106. case SE_FILE_OBJECT:
  1107. {
  1108. CSecureFile csf;
  1109. if(csf.SetFileName(chstrName, FALSE) == ERROR_SUCCESS) //FALSE means we don't need the SACL
  1110. {
  1111. csf.GetOwner(csidOwner);
  1112. }
  1113. break;
  1114. }
  1115. case SE_LMSHARE:
  1116. {
  1117. CSecureShare css;
  1118. if(css.SetShareName(chstrName) == ERROR_SUCCESS)
  1119. {
  1120. css.GetOwner(csidOwner);
  1121. }
  1122. break;
  1123. }
  1124. default:
  1125. {
  1126. ASSERT_BREAK(0);
  1127. }
  1128. }
  1129. // Proceed as long as the owner sid is valid and 'ok'...
  1130. if(csidOwner.IsValid() && csidOwner.IsOK())
  1131. {
  1132. // 3a) Compare the sid from #2 to that from #1. fRet is true if they are equal.
  1133. if(csidCurrentUser == csidOwner)
  1134. {
  1135. fRet = true;
  1136. }
  1137. else // owner might be a group...
  1138. {
  1139. // 3b) If not, owner's sid may be that of a group, and the user might be a
  1140. // member of that group, or of a group (which would have to be a global group)
  1141. // within that group. Fortunately that doesnt't recurse indefinitely, since
  1142. // local groups can contain only global groups, and global groups can contain
  1143. // only users (they can't be a container for other global or local groups) - see
  1144. // "Windows NT Security" (Nik Okuntseff), pp. 34-35.
  1145. // Since this could be a pain, call a friendly helper...
  1146. SID_NAME_USE snuOwner = csidOwner.GetAccountType();
  1147. if(snuOwner == SidTypeGroup || snuOwner == SidTypeAlias || snuOwner == SidTypeWellKnownGroup)
  1148. {
  1149. if(IsUserInGroup(csidCurrentUser, csidOwner, snuOwner))
  1150. {
  1151. fRet = true;
  1152. }
  1153. }
  1154. }
  1155. }
  1156. } // we got the thread sid
  1157. } // its an object we like
  1158. return fRet;
  1159. }
  1160. #endif
  1161. // Helper to determine if a particular is a member of a group, or of one of the
  1162. // (global) groups that might be a member of that group.
  1163. #ifdef NTONLY
  1164. bool IsUserInGroup(const CSid &csidUser,
  1165. const CSid &csidGroup,
  1166. SID_NAME_USE snuGroup)
  1167. {
  1168. bool fRet = false;
  1169. CNetAPI32 netapi ;
  1170. if(netapi.Init() == ERROR_SUCCESS)
  1171. {
  1172. fRet = RecursiveFindUserInGroup(netapi,
  1173. csidGroup.GetDomainName(),
  1174. csidGroup.GetAccountName(),
  1175. snuGroup,
  1176. csidUser);
  1177. }
  1178. return fRet;
  1179. }
  1180. #endif
  1181. #ifdef NTONLY
  1182. bool RecursiveFindUserInGroup(CNetAPI32 &netapi,
  1183. const CHString &chstrDomainName,
  1184. const CHString &chstrGroupName,
  1185. SID_NAME_USE snuGroup,
  1186. const CSid &csidUser)
  1187. {
  1188. bool fRet = false;
  1189. NET_API_STATUS stat;
  1190. DWORD dwNumReturnedEntries = 0, dwIndex = 0, dwTotalEntries = 0;
  1191. DWORD_PTR dwptrResume = NULL;
  1192. // Domain Groups
  1193. if (snuGroup == SidTypeGroup)
  1194. {
  1195. GROUP_USERS_INFO_0 *pGroupMemberData = NULL;
  1196. CHString chstrDCName;
  1197. if (netapi.GetDCName(chstrDomainName, chstrDCName) == ERROR_SUCCESS)
  1198. {
  1199. do
  1200. {
  1201. // Accept up to 256k worth of data.
  1202. stat = netapi.NetGroupGetUsers(chstrDCName,
  1203. chstrGroupName,
  1204. 0,
  1205. (LPBYTE *)&pGroupMemberData,
  1206. 262144,
  1207. &dwNumReturnedEntries,
  1208. &dwTotalEntries,
  1209. &dwptrResume);
  1210. // If we got some data
  1211. if(ERROR_SUCCESS == stat || ERROR_MORE_DATA == stat)
  1212. {
  1213. try
  1214. {
  1215. // Walk through all the returned entries...
  1216. for(DWORD dwCtr = 0; dwCtr < dwNumReturnedEntries; dwCtr++)
  1217. {
  1218. // Get the sid type for this object...
  1219. CSid sid(chstrDomainName, CHString(pGroupMemberData[dwCtr].grui0_name), NULL);
  1220. if(sid == csidUser)
  1221. {
  1222. fRet = true;
  1223. }
  1224. }
  1225. }
  1226. catch ( ... )
  1227. {
  1228. netapi.NetApiBufferFree( pGroupMemberData );
  1229. throw ;
  1230. }
  1231. netapi.NetApiBufferFree( pGroupMemberData );
  1232. } // IF stat OK
  1233. } while ( ERROR_MORE_DATA == stat && !fRet);
  1234. }
  1235. // Local Groups
  1236. }
  1237. else if(snuGroup == SidTypeAlias || snuGroup == SidTypeWellKnownGroup)
  1238. {
  1239. LOCALGROUP_MEMBERS_INFO_1 *pGroupMemberData = NULL;
  1240. do
  1241. {
  1242. // Accept up to 256k worth of data.
  1243. stat = netapi.NetLocalGroupGetMembers(NULL,
  1244. chstrGroupName,
  1245. 1,
  1246. (LPBYTE *)&pGroupMemberData,
  1247. 262144,
  1248. &dwNumReturnedEntries,
  1249. &dwTotalEntries,
  1250. &dwptrResume);
  1251. // If we got some data
  1252. if ( ERROR_SUCCESS == stat || ERROR_MORE_DATA == stat )
  1253. {
  1254. try
  1255. {
  1256. // Walk through all the returned entries
  1257. for(DWORD dwCtr = 0; dwCtr < dwNumReturnedEntries && !fRet; dwCtr++)
  1258. {
  1259. // If this is a recognized type...
  1260. CSid sid(pGroupMemberData[dwCtr].lgrmi1_sid);
  1261. switch(pGroupMemberData[dwCtr].lgrmi1_sidusage)
  1262. {
  1263. case SidTypeUser:
  1264. {
  1265. if(sid == csidUser)
  1266. {
  1267. fRet = true;
  1268. }
  1269. break;
  1270. }
  1271. case SidTypeGroup:
  1272. {
  1273. // If the group contained a group (would be a global group),
  1274. // we need to recurse.
  1275. fRet = RecursiveFindUserInGroup(netapi,
  1276. sid.GetDomainName(),
  1277. sid.GetAccountName(),
  1278. pGroupMemberData[dwCtr].lgrmi1_sidusage,
  1279. csidUser);
  1280. break;
  1281. }
  1282. case SidTypeWellKnownGroup:
  1283. {
  1284. // If the group contained a group (would be a global group),
  1285. // we need to recurse.
  1286. fRet = RecursiveFindUserInGroup(netapi,
  1287. sid.GetDomainName(),
  1288. sid.GetAccountName(),
  1289. pGroupMemberData[dwCtr].lgrmi1_sidusage,
  1290. csidUser);
  1291. break;
  1292. }
  1293. default:
  1294. {
  1295. ASSERT_BREAK(0);
  1296. break;
  1297. }
  1298. }
  1299. }
  1300. }
  1301. catch ( ... )
  1302. {
  1303. netapi.NetApiBufferFree( pGroupMemberData );
  1304. throw ;
  1305. }
  1306. netapi.NetApiBufferFree( pGroupMemberData );
  1307. } // IF stat OK
  1308. } while ( ERROR_MORE_DATA == stat && !fRet);
  1309. }
  1310. else
  1311. {
  1312. // Unrecognized Group type
  1313. ASSERT_BREAK(0);
  1314. }
  1315. return fRet;
  1316. }
  1317. #endif