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.

1048 lines
28 KiB

  1. /*++
  2. Copyright (C) 1998-2001 Microsoft Corporation
  3. Module Name:
  4. OLDSEC.CPP
  5. Abstract:
  6. contains various routines and classes used providing backward security support.
  7. History:
  8. a-davj 02-sept-99 Created.
  9. --*/
  10. #include "precomp.h"
  11. #include <wbemcore.h>
  12. #include <oleauto.h>
  13. #include <genutils.h>
  14. #include <safearry.h>
  15. #include <oahelp.inl>
  16. #include "secure.h"
  17. #include <flexarry.h>
  18. #include <secure.h>
  19. #include <objpath.h>
  20. #include "oldsec.h"
  21. //***************************************************************************
  22. //
  23. // CreateTheInstance
  24. //
  25. // Takes a class object, and a CCombined entry and creates an instance.
  26. //
  27. // PARAMETERS:
  28. ///
  29. // ppObj used to pass back the created instance
  30. // pClass Class object used for spawning
  31. // pCombinedEntry Has the combined values for all the aces which mach
  32. // the user or group.
  33. // RETURN VALUES:
  34. //
  35. // S_OK if all is well, else an error code
  36. //
  37. //***************************************************************************
  38. HRESULT CreateTheInstance(IWbemClassObject ** ppObj, IWbemClassObject * pClass,
  39. CCombinedAce * pCombinedEntry)
  40. {
  41. if(ppObj == NULL || pCombinedEntry == NULL || pClass == NULL)
  42. return WBEM_E_INVALID_PARAMETER;
  43. // spawn the instance
  44. SCODE sc = pClass->SpawnInstance(0, ppObj);
  45. if(FAILED(sc))
  46. return sc;
  47. CReleaseMe rm(*ppObj); // we addref at end if all is well
  48. // populate the instance
  49. bool bEnabled=false, bEditSecurity=false, bExecMethods=false;
  50. DWORD dwMask = pCombinedEntry->m_dwDeny;
  51. if(dwMask == 0)
  52. dwMask = pCombinedEntry->m_dwAllow;
  53. if( (dwMask & WBEM_ENABLE) &&
  54. (dwMask & WBEM_REMOTE_ACCESS) &&
  55. (dwMask & WBEM_WRITE_PROVIDER) &&
  56. pCombinedEntry->m_dwAllow)
  57. bEnabled = true;
  58. if(dwMask & READ_CONTROL)
  59. bEditSecurity = true;
  60. if(dwMask & WBEM_METHOD_EXECUTE)
  61. bExecMethods = true;
  62. DWORD dwPermission = 0; // start at read
  63. if(dwMask & WBEM_PARTIAL_WRITE_REP)
  64. dwPermission = 1;
  65. if(dwMask & WBEM_FULL_WRITE_REP)
  66. dwPermission = 2;
  67. VARIANT var;
  68. var.vt = VT_I4;
  69. var.lVal = dwPermission;
  70. sc = (*ppObj)->Put(L"Permissions", 0, &var, 0);
  71. var.vt = VT_BOOL;
  72. var.boolVal = (bEnabled) ? VARIANT_TRUE : VARIANT_FALSE;
  73. sc = (*ppObj)->Put(L"Enabled", 0, &var, 0);
  74. var.boolVal = (bEditSecurity) ? VARIANT_TRUE : VARIANT_FALSE;
  75. sc = (*ppObj)->Put(L"EditSecurity", 0, &var, 0);
  76. var.boolVal = (bExecMethods) ? VARIANT_TRUE : VARIANT_FALSE;
  77. sc = (*ppObj)->Put(L"ExecuteMethods", 0, &var, 0);
  78. // Get the account and domain info
  79. LPWSTR pwszAccount = NULL;
  80. LPWSTR pwszDomain = NULL;
  81. sc = pCombinedEntry->GetNames(pwszAccount, pwszDomain);
  82. if(FAILED(sc))
  83. return sc;
  84. CDeleteMe<WCHAR> dm1(pwszAccount);
  85. CDeleteMe<WCHAR> dm2(pwszDomain);
  86. var.vt = VT_BSTR;
  87. if(pwszAccount && wcslen(pwszAccount) > 0) // SEC:REVIEWED 2002-03-22 : OK, <->GetNames() call assures valid strings>
  88. {
  89. BSTR bstr = SysAllocString(pwszAccount); // SEC:REVIEWED 2002-03-22 : OK
  90. if(bstr == NULL)
  91. return WBEM_E_OUT_OF_MEMORY;
  92. var.bstrVal = bstr;
  93. sc = (*ppObj)->Put(L"Name", 0, &var, 0);
  94. SysFreeString(bstr);
  95. }
  96. if(pwszDomain && wcslen(pwszDomain)) // SEC:REVIEWED 2002-03-22 : OK
  97. {
  98. BSTR bstr = SysAllocString(pwszDomain); // SEC:REVIEWED 2002-03-22 : OK
  99. if(bstr == NULL)
  100. return WBEM_E_OUT_OF_MEMORY;
  101. var.bstrVal = bstr;
  102. sc = (*ppObj)->Put(L"Authority", 0, &var, 0);
  103. SysFreeString(bstr);
  104. }
  105. (*ppObj)->AddRef(); // make up for the releaseme
  106. return S_OK;
  107. }
  108. //***************************************************************************
  109. //
  110. // GetAceStylePath
  111. //
  112. // Takes a parsed object path and converts it into "authority|name"
  113. // format.
  114. //
  115. // PARAMETERS:
  116. //
  117. // pOutput parsed path object
  118. // pToBeDeleted Set to newly allocated string. Call must free if
  119. // this routine return S_OK
  120. //
  121. // RETURN VALUES:
  122. //
  123. // S_OK if all is well, else an error code
  124. //
  125. //***************************************************************************
  126. HRESULT GetAceStylePath(ParsedObjectPath* pOutput, LPWSTR *pToBeDeleted)
  127. {
  128. LPWSTR pRet;
  129. int iLen;
  130. int iAuthLen = 0;
  131. int iNameLen = 0;
  132. KeyRef* pAuth;
  133. KeyRef* pName;
  134. if(pOutput == NULL || pToBeDeleted == NULL)
  135. return WBEM_E_INVALID_PARAMETER;
  136. if(wbem_wcsicmp(pOutput->m_pClass, L"__ntlmuser") &&
  137. wbem_wcsicmp(pOutput->m_pClass, L"__ntlmgroup"))
  138. return WBEM_E_INVALID_OBJECT_PATH;
  139. if(pOutput->m_bSingletonObj || pOutput->m_dwNumKeys < 1 ||
  140. pOutput->m_dwNumKeys > 2)
  141. return WBEM_E_INVALID_OBJECT_PATH;
  142. // The authority key is optional
  143. if(pOutput->m_dwNumKeys == 1)
  144. {
  145. pAuth = NULL;
  146. pName = pOutput->m_paKeys[0];
  147. }
  148. else
  149. {
  150. // Determine which order the keys are in
  151. pAuth = pOutput->m_paKeys[0];
  152. pName = pOutput->m_paKeys[1];
  153. if(wbem_wcsicmp(pAuth->m_pName, L"Authority"))
  154. {
  155. pAuth = pOutput->m_paKeys[1];
  156. pName = pOutput->m_paKeys[0];
  157. }
  158. }
  159. // do some more checking
  160. if((pAuth && wbem_wcsicmp(pAuth->m_pName, L"Authority")) ||
  161. wbem_wcsicmp(pName->m_pName, L"Name"))
  162. return WBEM_E_INVALID_OBJECT_PATH;
  163. if(pAuth && pAuth->m_vValue.vt == VT_BSTR && pAuth->m_vValue.bstrVal != 0)
  164. iAuthLen = wcslen(pAuth->m_vValue.bstrVal); // SEC:REVIEWED 2002-03-22 : OK, prior logic assures NULL
  165. else
  166. iAuthLen = 1; // assume a "."
  167. if(pName->m_vValue.vt == VT_BSTR && pName->m_vValue.bstrVal != 0)
  168. iNameLen = wcslen(pName->m_vValue.bstrVal); // SEC:REVIEWED 2002-03-22 : OK, prior logic assures NULL
  169. if(iNameLen == 0 || iAuthLen == 0)
  170. return WBEM_E_INVALID_OBJECT_PATH;
  171. // allocate some memory
  172. iLen = 2 + iNameLen + iAuthLen;
  173. pRet = new WCHAR[iLen];
  174. if(pRet == NULL)
  175. return WBEM_E_OUT_OF_MEMORY;
  176. if(pAuth && pAuth->m_vValue.vt == VT_BSTR && pAuth->m_vValue.bstrVal != 0)
  177. StringCchCopyW(pRet, iLen, pAuth->m_vValue.bstrVal);
  178. else
  179. StringCchCopyW(pRet, iLen, L".");
  180. StringCchCatW(pRet, iLen, L"|");
  181. StringCchCatW(pRet, iLen, pName->m_vValue.bstrVal);
  182. *pToBeDeleted = pRet;
  183. return S_OK;
  184. }
  185. //***************************************************************************
  186. //
  187. // CCombinedAce::CCombinedAce
  188. //
  189. // Constructor. Since there might be several ACEs for a single user or
  190. // group in the ACL, this structure is used to combine all the aces for a
  191. // sid into one.
  192. //
  193. // PARAMETERS:
  194. //
  195. // pwszName User/group name.
  196. //
  197. //***************************************************************************
  198. CCombinedAce::CCombinedAce(WCHAR *pwszName)
  199. {
  200. m_dwAllow = 0;
  201. m_dwDeny = 0;
  202. m_BadAce = false;
  203. m_wcFullName = NULL;
  204. if(pwszName)
  205. {
  206. DUP_STRING_NEW(m_wcFullName, pwszName);
  207. }
  208. }
  209. //***************************************************************************
  210. //
  211. // CCombinedAce::AddToMasks
  212. //
  213. // Since this class is used to combine possibly many ACEs into a single
  214. // entry, this is called each time an ACE needs to be "OR"ed in.
  215. //
  216. // PARAMETERS:
  217. //
  218. // pAce Pointer to the ace to be combined.
  219. //
  220. //***************************************************************************
  221. void CCombinedAce::AddToMasks(CBaseAce * pAce)
  222. {
  223. if(pAce == NULL)
  224. return;
  225. // Only aces with the container inherit bit can
  226. // be translated back.
  227. if(pAce->GetFlags() != CONTAINER_INHERIT_ACE)
  228. m_BadAce = true;
  229. if(pAce->GetType() == ACCESS_ALLOWED_ACE_TYPE)
  230. m_dwAllow |= pAce->GetAccessMask();
  231. else
  232. m_dwDeny |= pAce->GetAccessMask();
  233. return;
  234. }
  235. //***************************************************************************
  236. //
  237. // CCombinedAce::IsValidOldEntry
  238. //
  239. // Checks a combined ace and determines if it could be converted into
  240. // an old style object.
  241. //
  242. // PARAMETERS:
  243. //
  244. // bIsGroup Set to true if the entry is for a group.
  245. //
  246. // RETURN VALUES:
  247. //
  248. // TRUE if the entry would make a valid instance
  249. //
  250. //***************************************************************************
  251. bool CCombinedAce::IsValidOldEntry(bool bIsGroup)
  252. {
  253. // If we have detected incompatible flags, all is done!
  254. if(m_BadAce)
  255. return false;
  256. if(bIsGroup && m_dwDeny)
  257. return false; // group denies were not supported
  258. if(m_dwDeny && m_dwAllow)
  259. return false; // can not mix allows and denies in old system
  260. if(m_dwDeny)
  261. {
  262. return true;
  263. }
  264. DWORD dwOldAllow = WBEM_ENABLE | WBEM_REMOTE_ACCESS | WBEM_WRITE_PROVIDER;
  265. DWORD dwMask = m_dwDeny;
  266. if(dwMask == 0)
  267. dwMask = m_dwAllow;
  268. // all these must be set if it is an allow.
  269. DWORD dwTemp = dwMask;
  270. dwTemp &= dwOldAllow;
  271. if(m_dwAllow != 0 && dwTemp != dwOldAllow)
  272. return false;
  273. // cant have full repository write without partial
  274. if((dwMask & WBEM_FULL_WRITE_REP) != 0 && (dwMask & WBEM_PARTIAL_WRITE_REP) == 0)
  275. return false;
  276. return true;
  277. }
  278. //***************************************************************************
  279. //
  280. // CCombinedAce::GetNames
  281. //
  282. // Retrieves the account name and authority
  283. //
  284. // PARAMETERS:
  285. //
  286. // pwszAccount Set to newly allocated string, Caller must free if success
  287. // pwszDomain Set to newly allocated string, Caller must free if success
  288. //
  289. // RETURN VALUES:
  290. //
  291. // S_OK if all is well, else an error code
  292. //
  293. //***************************************************************************
  294. HRESULT CCombinedAce::GetNames(LPWSTR & pwszAccount, LPWSTR &pwszDomain)
  295. {
  296. pwszAccount = 0;
  297. pwszDomain = 0;
  298. // find the position of the '|'
  299. if(m_wcFullName == 0)
  300. return WBEM_E_FAILED;
  301. WCHAR * pwcSeparator;
  302. try
  303. {
  304. for(pwcSeparator = m_wcFullName; *pwcSeparator && *pwcSeparator != L'|'; pwcSeparator++); // SEC:REVIEWED 2002-03-22 : OK
  305. }
  306. catch(...)
  307. {
  308. return WBEM_E_FAILED;
  309. }
  310. DWORD dwLenDomain;
  311. DWORD dwLenUser;
  312. bool bUseDotDomain = false;
  313. if(*pwcSeparator == 0)
  314. {
  315. return WBEM_E_FAILED;
  316. }
  317. if(pwcSeparator == m_wcFullName)
  318. {
  319. bUseDotDomain = true;
  320. dwLenDomain = 2;
  321. }
  322. else
  323. {
  324. dwLenDomain = pwcSeparator - m_wcFullName + 1;
  325. }
  326. dwLenUser = wcslen(pwcSeparator); // SEC:REVIEWED 2002-03-22 : OK; prior logic assures NULL
  327. if(dwLenUser == 0)
  328. return WBEM_E_INVALID_OBJECT_PATH;
  329. // Allocate space for the two strings
  330. pwszAccount = new WCHAR[dwLenUser];
  331. if(pwszAccount == NULL)
  332. return WBEM_E_OUT_OF_MEMORY;
  333. StringCchCopyW(pwszAccount, dwLenUser, pwcSeparator+1);
  334. pwszDomain = new WCHAR[dwLenDomain];
  335. if(pwszDomain == NULL)
  336. {
  337. delete pwszAccount;
  338. pwszAccount = 0;
  339. return WBEM_E_OUT_OF_MEMORY;
  340. }
  341. if(bUseDotDomain)
  342. StringCchCopyW(pwszDomain, dwLenDomain, L".");
  343. else
  344. {
  345. StringCchCopyW(pwszDomain, dwLenDomain, m_wcFullName);
  346. }
  347. return S_OK;
  348. }
  349. //***************************************************************************
  350. //
  351. // RootSD::RootSD
  352. //
  353. // Constructor. This class contains a pointer to the root namespace and the
  354. // flex array of aces.
  355. //
  356. //***************************************************************************
  357. RootSD::RootSD()
  358. {
  359. m_bOK = false;
  360. m_pFlex = NULL;
  361. m_pRoot = CWbemNamespace::CreateInstance();
  362. if(m_pRoot == NULL)
  363. return;
  364. HRESULT hRes = m_pRoot->Initialize(L"root", L"Administrator",
  365. 0 ,
  366. FULL_RIGHTS, true, false, NULL, 0xFFFFFFFF,
  367. FALSE, NULL);
  368. if (FAILED(hRes))
  369. {
  370. m_pRoot->Release();
  371. m_pRoot = NULL;
  372. return;
  373. }
  374. else if (m_pRoot->GetStatus() != 0)
  375. {
  376. m_pRoot->Release();
  377. m_pRoot = NULL;
  378. return;
  379. }
  380. m_pRoot->AddRef();
  381. // Get the security descriptor
  382. m_pFlex = NULL;
  383. SCODE sc = m_pRoot->GetAceList(&m_pFlex);
  384. if(!FAILED(sc))
  385. m_bOK = true;
  386. }
  387. //***************************************************************************
  388. //
  389. // RootSD::~RootSD
  390. //
  391. // Destructor.
  392. //
  393. //***************************************************************************
  394. RootSD::~RootSD()
  395. {
  396. if(m_pRoot)
  397. m_pRoot->Release();
  398. if(m_pFlex)
  399. delete m_pFlex;
  400. }
  401. //***************************************************************************
  402. //
  403. // RootSD::StoreAceList()
  404. //
  405. // Stores the Ace list back into the db.
  406. //
  407. // RETURN VALUES:
  408. //
  409. // S_OK if all is well, else an error code
  410. //
  411. //***************************************************************************
  412. HRESULT RootSD::StoreAceList()
  413. {
  414. if(m_bOK && m_pFlex && m_pRoot)
  415. m_pRoot->PutAceList(m_pFlex);
  416. return S_OK;
  417. }
  418. //***************************************************************************
  419. //
  420. // RootSD::RemoveMatchingEntries
  421. //
  422. // Goes through the ACE list and removes all entries that match the name
  423. //
  424. // PARAMETERS:
  425. //
  426. // pwszAccountName Name of the account to be deleted
  427. //
  428. // RETURN VALUES:
  429. //
  430. // S_OK if all is well, else an error code
  431. //
  432. //***************************************************************************
  433. HRESULT RootSD::RemoveMatchingEntries(LPWSTR pwszAccountName)
  434. {
  435. if(!m_bOK || m_pFlex == NULL)
  436. return WBEM_E_FAILED;
  437. for(int iPos = m_pFlex->Size()-1; iPos >= 0; iPos--)
  438. {
  439. CBaseAce * pListAce = (CBaseAce *)m_pFlex->GetAt(iPos);
  440. WCHAR * pwszAceListUserName;
  441. if(pListAce == NULL)
  442. continue;
  443. HRESULT hr = pListAce->GetFullUserName2(&pwszAceListUserName);
  444. if(FAILED(hr))
  445. return hr;
  446. CDeleteMe<WCHAR> dm1(pwszAceListUserName);
  447. if(wbem_wcsicmp(pwszAceListUserName, pwszAccountName) == 0)
  448. {
  449. delete pListAce;
  450. m_pFlex->RemoveAt(iPos);
  451. }
  452. }
  453. return S_OK;
  454. }
  455. //***************************************************************************
  456. //
  457. // OldSecList::OldSecList
  458. //
  459. // Constructor. This class contains the list of combined entries for the
  460. // aces in the root namespace. Note that the list is of just the users,
  461. // or just the groups.
  462. //
  463. //***************************************************************************
  464. OldSecList::OldSecList(bool bGroups)
  465. {
  466. // Attach up to the root namespace
  467. RootSD rsd;
  468. if(!rsd.IsOK())
  469. return; // empty list
  470. // Get the Security namespace
  471. CFlexAceArray * pRootNsAceList = rsd.GetAceList();
  472. if(pRootNsAceList == NULL)
  473. return;
  474. // For each ACE in the root namespace list
  475. for(int iAce = 0; iAce < pRootNsAceList->Size(); iAce++)
  476. {
  477. // Search the entries in the combined list to see if there is already one for
  478. // this ace
  479. CBaseAce * pAce = (CBaseAce *)pRootNsAceList->GetAt(iAce);
  480. WCHAR * pwszAceListUserName;
  481. if(pAce == NULL)
  482. continue;
  483. CNtAce * pNtAce = (CNtAce *)pAce;
  484. CNtSid sid;
  485. pNtAce->GetSid(sid);
  486. DWORD dwUsage;
  487. LPWSTR pAccount = NULL;
  488. LPWSTR pDomain = NULL;
  489. if(sid.GetInfo(&pAccount, &pDomain, &dwUsage))
  490. continue;
  491. delete pAccount;
  492. delete pDomain;
  493. if(dwUsage == SidTypeUser && bGroups)
  494. continue;
  495. if(dwUsage != SidTypeUser && !bGroups)
  496. continue;
  497. HRESULT hr = pAce->GetFullUserName2(&pwszAceListUserName);
  498. if(FAILED(hr))
  499. continue;
  500. CDeleteMe<WCHAR> dm1(pwszAceListUserName);
  501. bool bExisting = false;
  502. for(int iMergedEntry = 0; iMergedEntry < m_MergedAceList.Size(); iMergedEntry++)
  503. {
  504. CCombinedAce * pCombinedEntry = (CCombinedAce *)m_MergedAceList.GetAt(iMergedEntry);
  505. if(pCombinedEntry)
  506. {
  507. if(wbem_wcsicmp(pwszAceListUserName, pCombinedEntry->m_wcFullName) == 0 )
  508. {
  509. bExisting = true;
  510. pCombinedEntry->AddToMasks(pAce);
  511. break;
  512. }
  513. }
  514. }
  515. // If necessary add a new entry
  516. if(!bExisting)
  517. {
  518. CCombinedAce * pCombinedEntry = new CCombinedAce(pwszAceListUserName);
  519. if(pCombinedEntry == NULL)
  520. return;
  521. pCombinedEntry->AddToMasks(pAce);
  522. if (CFlexArray::no_error != m_MergedAceList.Add((void *)pCombinedEntry))
  523. {
  524. //throw CX_Exception();
  525. }
  526. }
  527. }
  528. }
  529. //***************************************************************************
  530. //
  531. // OldSecList::~OldSecList()
  532. //
  533. // Destructor.
  534. //
  535. //***************************************************************************
  536. OldSecList::~OldSecList()
  537. {
  538. // Delete the stuff used in the entry list.
  539. for(int iCnt = m_MergedAceList.Size() - 1; iCnt >= 0; iCnt--)
  540. {
  541. CCombinedAce * pCombinedEntry = (CCombinedAce *)m_MergedAceList.GetAt(iCnt);
  542. delete pCombinedEntry;
  543. }
  544. }
  545. //***************************************************************************
  546. //
  547. // OldSecList::GetValidCombined
  548. //
  549. // Returns a combined entry at the specified index, but only if it is valid.
  550. //
  551. // PARAMETERS:
  552. //
  553. // iIndex Index into the array, 0 is the first
  554. // bGroup true if a group entry is desired.
  555. //
  556. // RETURN VALUES:
  557. //
  558. // If all is well, a pointer to the combined entry. NULL indicates failure.
  559. //
  560. //***************************************************************************
  561. CCombinedAce * OldSecList::GetValidCombined(int iIndex, bool bGroup)
  562. {
  563. if(iIndex < 0 || iIndex >= m_MergedAceList.Size())
  564. return NULL;
  565. // Get the entry
  566. CCombinedAce * pCombinedEntry = (CCombinedAce *)m_MergedAceList.GetAt(iIndex);
  567. if(pCombinedEntry == NULL)
  568. return NULL;
  569. // verify that the entry can be translated back into an old security setting
  570. if(pCombinedEntry->IsValidOldEntry(bGroup))
  571. return pCombinedEntry;
  572. else
  573. {
  574. DEBUGTRACE((LOG_WBEMCORE, "Invalid ace entry combination encountered, name = %S, "
  575. "allow=0x%x, deny=0x%x, flag validity=&d", pCombinedEntry->m_wcFullName,
  576. pCombinedEntry->m_dwAllow, pCombinedEntry->m_dwDeny, pCombinedEntry->m_BadAce));
  577. return NULL;
  578. }
  579. }
  580. //***************************************************************************
  581. //
  582. // OldSecList::GetValidCombined
  583. //
  584. // Returns a combined entry which matches the name, but only if it is valid.
  585. //
  586. // PARAMETERS:
  587. //
  588. // pName Name to be found. It is of the format "authority|name"
  589. // bGroup true if a group entry is desired.
  590. //
  591. // RETURN VALUES:
  592. //
  593. // If all is well, a pointer to the combined entry. NULL indicates failure.
  594. //
  595. //***************************************************************************
  596. CCombinedAce * OldSecList::GetValidCombined(LPWSTR pName, bool bGroup)
  597. {
  598. if(pName == NULL)
  599. return NULL;
  600. // Go through the list and look for the matching entry
  601. int iCnt;
  602. CCombinedAce * pCombinedEntry;
  603. for(iCnt = 0; iCnt < m_MergedAceList.Size(); iCnt++)
  604. {
  605. pCombinedEntry = (CCombinedAce *)m_MergedAceList.GetAt(iCnt);
  606. if(pCombinedEntry && !wbem_wcsicmp(pCombinedEntry->m_wcFullName, pName))
  607. break;
  608. }
  609. if(iCnt == m_MergedAceList.Size())
  610. return NULL;
  611. // verify that the entry can be translated back into an old security setting
  612. if(pCombinedEntry->IsValidOldEntry(bGroup))
  613. return pCombinedEntry;
  614. else
  615. {
  616. DEBUGTRACE((LOG_WBEMCORE, "Invalid ace entry combination encountered, name = %S, "
  617. "allow=0x%x, deny=0x%x, flag validity=&d", pCombinedEntry->m_wcFullName,
  618. pCombinedEntry->m_dwAllow, pCombinedEntry->m_dwDeny, pCombinedEntry->m_BadAce));
  619. return NULL;
  620. }
  621. }
  622. //***************************************************************************
  623. //
  624. // CWbemNamespace::EnumerateSecurityClassInstances
  625. //
  626. // Equivalent the a CreateInstanceEnumAsync call.
  627. //
  628. // PARAMETERS:
  629. //
  630. // wszClassName class name
  631. // pSink Where to indicate the value
  632. // pContext pointer to the context object.
  633. // lFlags flags.
  634. //
  635. // RETURN VALUES:
  636. //
  637. // S_OK if all is well, else an error code
  638. //
  639. //***************************************************************************
  640. HRESULT CWbemNamespace::EnumerateSecurityClassInstances(LPWSTR wszClassName,
  641. IWbemObjectSink* pSink, IWbemContext* pContext, long lFlags)
  642. {
  643. SCODE sc = WBEM_E_FAILED;
  644. IWbemClassObject FAR* pObj = NULL;
  645. // Do sanity check of arguments.
  646. if(pSink == NULL || wszClassName == NULL ) // Should not happen
  647. return WBEM_E_INVALID_PARAMETER;
  648. // Get the class object
  649. IWbemClassObject * pClass = NULL;
  650. sc = GetObject(wszClassName, 0, pContext, &pClass, NULL);
  651. if(sc != S_OK)
  652. {
  653. return sc;
  654. }
  655. CReleaseMe rm(pClass);
  656. bool bGroup = false;
  657. if(wbem_wcsicmp(L"__ntlmgroup", wszClassName) == 0)
  658. bGroup = true;
  659. OldSecList osl(bGroup);
  660. sc = S_OK;
  661. for(int i = 0; i < osl.Size(); i++)
  662. {
  663. IWbemClassObject * pObj = NULL;
  664. CCombinedAce * pCombinedEntry = osl.GetValidCombined(i, bGroup);
  665. if(pCombinedEntry)
  666. {
  667. sc = CreateTheInstance(&pObj, pClass, pCombinedEntry);
  668. if(sc == S_OK)
  669. {
  670. if (SUCCEEDED(sc = DecorateObject(pObj)))
  671. {
  672. pSink->Indicate(1,&pObj);
  673. }
  674. pObj->Release();
  675. }
  676. }
  677. }
  678. // Set status, all done
  679. return sc;
  680. }
  681. //***************************************************************************
  682. //
  683. // CWbemNamespace::PutSecurityClassInstances
  684. //
  685. // Equivalent to a PutInstanceAsync call.
  686. //
  687. // PARAMETERS:
  688. //
  689. // wszClassName class name
  690. // pObj Object to be "put"
  691. // pSink where to SetStatus
  692. // pContext pointer to the context object
  693. // lFlags flags
  694. //
  695. // RETURN VALUES:
  696. //
  697. // S_OK if all is well, else an error code
  698. //
  699. //***************************************************************************
  700. HRESULT CWbemNamespace::PutSecurityClassInstances(LPWSTR wszClassName, IWbemClassObject * pObj,
  701. IWbemObjectSink* pSink, IWbemContext* pContext, long lFlags)
  702. {
  703. // Check the args
  704. if(wszClassName == NULL || pObj == NULL || pSink == NULL)
  705. {
  706. pSink->SetStatus(0,WBEM_E_INVALID_PARAMETER,NULL,NULL);
  707. return S_OK;
  708. }
  709. RootSD rsd;
  710. if(!rsd.IsOK())
  711. {
  712. pSink->SetStatus(0,WBEM_E_FAILED,NULL,NULL);
  713. return S_OK;
  714. }
  715. // Get the Security namespace
  716. CFlexAceArray * pRootNsAceList = rsd.GetAceList();
  717. bool bGroup = false;
  718. if(wbem_wcsicmp(L"__ntlmgroup", wszClassName) == 0)
  719. bGroup = true;
  720. // Convert to new sid
  721. CBaseAce * pAce = ConvertOldObjectToAce(pObj, bGroup);
  722. if(pAce == NULL)
  723. {
  724. pSink->SetStatus(0,WBEM_E_INVALID_OBJECT,NULL,NULL);
  725. return S_OK;
  726. }
  727. // Delete all entries with the same name
  728. WCHAR * pwszAccountName;
  729. HRESULT hr = pAce->GetFullUserName2(&pwszAccountName);
  730. if(FAILED(hr))
  731. {
  732. pSink->SetStatus(0,hr,NULL,NULL);
  733. return S_OK;
  734. }
  735. CDeleteMe<WCHAR> dm1(pwszAccountName);
  736. rsd.RemoveMatchingEntries(pwszAccountName);
  737. // Add the new entries
  738. pRootNsAceList->Add(pAce);
  739. // Put Sid back
  740. hr = rsd.StoreAceList();
  741. pSink->SetStatus(0,hr,NULL,NULL);
  742. return S_OK;
  743. }
  744. //***************************************************************************
  745. //
  746. // CWbemNamespace::DeleteSecurityClassInstances
  747. //
  748. // Equivalent to a DeleteInstanceAsync routine
  749. //
  750. // PARAMETERS:
  751. //
  752. // pParsedPath parsed object path
  753. // pSink where to SetStatus
  754. // pContext pointer to the context object
  755. // lFlags flags
  756. //
  757. // RETURN VALUES:
  758. //
  759. // S_OK if all is well, else an error code
  760. //
  761. //***************************************************************************
  762. HRESULT CWbemNamespace::DeleteSecurityClassInstances(ParsedObjectPath* pParsedPath,
  763. IWbemObjectSink* pSink, IWbemContext* pContext, long lFlags)
  764. {
  765. // Check the args
  766. if(pParsedPath == NULL || pSink == NULL || pSink == NULL)
  767. return WBEM_E_INVALID_PARAMETER;
  768. // Parse the path and contruct the domain|user string
  769. LPWSTR pAcePath = NULL;
  770. HRESULT hr = GetAceStylePath(pParsedPath, &pAcePath);
  771. if(FAILED(hr))
  772. {
  773. pSink->SetStatus(0,hr,NULL,NULL);
  774. return S_OK;
  775. }
  776. CDeleteMe<WCHAR> dm(pAcePath);
  777. // Delete the entries
  778. RootSD rsd;
  779. if(!rsd.IsOK())
  780. hr = WBEM_E_FAILED;
  781. else
  782. {
  783. CFlexAceArray * pRootNsAceList = rsd.GetAceList();
  784. int iOriginalSize = pRootNsAceList->Size();
  785. // Delete all entries with the same name
  786. rsd.RemoveMatchingEntries(pAcePath);
  787. int iNewSize = pRootNsAceList->Size();
  788. if(iNewSize < iOriginalSize)
  789. hr = rsd.StoreAceList();
  790. else
  791. hr = WBEM_E_NOT_FOUND;
  792. }
  793. pSink->SetStatus(0,hr,NULL,NULL);
  794. return S_OK;
  795. }
  796. //***************************************************************************
  797. //
  798. // CWbemNamespace::GetSecurityClassInstances
  799. //
  800. // Equivalent to a GetObjectAsync call.
  801. //
  802. // PARAMETERS:
  803. //
  804. // pParsedPath parsed object path
  805. // pSink where to SetStatus
  806. // pContext pointer to the context object
  807. // lFlags flags
  808. //
  809. // RETURN VALUES:
  810. //
  811. // S_OK if all is well, else an error code
  812. //
  813. //***************************************************************************
  814. HRESULT CWbemNamespace::GetSecurityClassInstances(ParsedObjectPath* pParsedPath, CBasicObjectSink* pSink,
  815. IWbemContext* pContext,long lFlags)
  816. {
  817. // Check the args
  818. if(pParsedPath == NULL|| pSink == NULL)
  819. return WBEM_E_INVALID_PARAMETER;
  820. // Parse the path and contruct the domain|user string
  821. LPWSTR pAcePath = NULL;
  822. HRESULT hr = GetAceStylePath(pParsedPath, &pAcePath);
  823. if(FAILED(hr))
  824. {
  825. pSink->SetStatus(0,hr,NULL,NULL);
  826. return S_OK;
  827. }
  828. CDeleteMe<WCHAR> dm(pAcePath);
  829. IWbemClassObject * pClass = NULL;
  830. SCODE sc = GetObject(pParsedPath->m_pClass, 0, pContext, &pClass, NULL);
  831. if(sc != S_OK)
  832. {
  833. pSink->SetStatus(0,sc,NULL, NULL);
  834. return S_OK;
  835. }
  836. CReleaseMe rm(pClass);
  837. bool bGroup = false;
  838. if(wbem_wcsicmp(L"__ntlmgroup", pParsedPath->m_pClass) == 0)
  839. bGroup = true;
  840. OldSecList osl(bGroup);
  841. IWbemClassObject * pObj = NULL;
  842. CCombinedAce * pCombinedEntry = osl.GetValidCombined(pAcePath, bGroup);
  843. if(pCombinedEntry == NULL)
  844. {
  845. pSink->SetStatus(0, WBEM_E_INVALID_OBJECT_PATH, NULL, NULL);
  846. return S_OK;
  847. }
  848. sc = CreateTheInstance(&pObj, pClass, pCombinedEntry);
  849. if(sc == S_OK) // not all entries make for valid old entries, so failure is common
  850. {
  851. if (SUCCEEDED(sc = DecorateObject(pObj)))
  852. {
  853. pSink->Indicate(1,&pObj);
  854. }
  855. pObj->Release();
  856. }
  857. // Set status, all done
  858. pSink->SetStatus(0,sc,NULL, NULL);
  859. return S_OK;
  860. }
  861.