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.

985 lines
22 KiB

  1. //////////////////////////////////////////////////////////////////////
  2. // NetSecProv.cpp : Implementation of CNetSecProv
  3. // Copyright (c)1997-2001 Microsoft Corporation
  4. //
  5. // this is the Network Security WMI provider for IPSec
  6. // Original Create Date: 2/19/2001
  7. // Original Author: shawnwu
  8. //////////////////////////////////////////////////////////////////////
  9. #include "NetSecProv.h"
  10. #include "globals.h"
  11. #include "IPSecBase.h"
  12. #include "TranxMgr.h"
  13. #include "PolicyQM.h"
  14. //
  15. // These are our global variables:
  16. // (1) g_CS. We will generally speaking use one critical section. This is it.
  17. //
  18. // (2) g_varRollbackGuid. This is the rollback guid. If an action is taken and this
  19. // variable is set to a valid string, then we tied that action to this token.
  20. // Even though we say it is a guid (string), any string will work for us.
  21. //
  22. //CCriticalSection g_CS;
  23. //CComVariant g_varRollbackGuid;
  24. /*
  25. Routine Description:
  26. Name:
  27. UpdateGlobals
  28. Functionality:
  29. Update the global variables.
  30. Virtual:
  31. No.
  32. Arguments:
  33. pNamespace - COM interface pointer representing ourselves.
  34. pCtx - COM interface pointer given by WMI and needed for various WMI APIs.
  35. Return Value:
  36. None. We don't plan to allow any failure of this function to stop our normal
  37. execution.
  38. Notes:
  39. void
  40. UpdateGlobals (
  41. IN IWbemServices * pNamespace,
  42. IN IWbemContext * pCtx
  43. )
  44. {
  45. //
  46. // We don't want any exception to cause a critical section leak. But all our function
  47. // calls are COM interface functions and they should never throw an exception.
  48. // But is that guaranteed? Chances are it is not. So, we will play safe here and put
  49. // a try-catch block around it
  50. //
  51. g_CS.Enter();
  52. try
  53. {
  54. g_varRollbackGuid.Clear();
  55. HRESULT hr = WBEM_NO_ERROR;
  56. //
  57. // update the transaction token, which is made available when SCE provider goes
  58. // into a Configure loop and made unavailable when SCE's configure loop ends.
  59. // So, we need to ask SCE provider.
  60. //
  61. //
  62. // Try to locate the SCE provider. Need the locator first.
  63. //
  64. CComPtr<IWbemLocator> srpLocator;
  65. hr = ::CoCreateInstance(CLSID_WbemLocator,
  66. 0,
  67. CLSCTX_INPROC_SERVER,
  68. IID_IWbemLocator,
  69. (LPVOID *) &srpLocator
  70. );
  71. if (SUCCEEDED(hr) && srpLocator)
  72. {
  73. //
  74. // Ask the locator to find the SCE provider.
  75. //
  76. CComPtr<IWbemServices> srpNamespace;
  77. CComBSTR bstrSce(L"\\\\.\\root\\Security\\SCE");
  78. hr = srpLocator->ConnectServer(bstrSce, NULL, NULL, NULL, 0, NULL, NULL, &srpNamespace);
  79. if (SUCCEEDED(hr) && srpNamespace)
  80. {
  81. //
  82. // SCE provider is found, then ask it for the transaction token object
  83. //
  84. CComBSTR bstrQuery(L"select * from Sce_TransactionToken");
  85. CComPtr<IEnumWbemClassObject> srpEnum;
  86. hr = srpNamespace->ExecQuery(L"WQL",
  87. bstrQuery,
  88. WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
  89. NULL,
  90. &srpEnum
  91. );
  92. if (SUCCEEDED(hr))
  93. {
  94. //
  95. // if the transaction token object is found, then get the rollback guid of the object
  96. //
  97. CComPtr<IWbemClassObject> srpObj;
  98. ULONG nEnum = 0;
  99. hr = srpEnum->Next(WBEM_INFINITE, 1, &srpObj, &nEnum);
  100. if (srpObj)
  101. {
  102. srpObj->Get(L"TranxGuid", 0, &g_varRollbackGuid, NULL, NULL);
  103. //
  104. // if what we got is not what we are prepared to accept, then toss it away
  105. //
  106. if (g_varRollbackGuid.vt != VT_BSTR)
  107. {
  108. g_varRollbackGuid.Clear();
  109. }
  110. }
  111. //
  112. // Somehow, the following simpler code doesn't work:
  113. //
  114. // CComBSTR bstrTranxToken(L"Sce_TransactionToken=@");
  115. // CComPtr<IWbemClassObject> srpObj;
  116. // hr = srpNamespace->GetObject(bstrTranxToken, WBEM_FLAG_RETURN_WBEM_COMPLETE, pCtx, &srpObj, NULL);
  117. // if (SUCCEEDED(hr) && srpObj)
  118. // {
  119. // srpObj->Get(L"TranxGuid", 0, &g_varRollbackGuid, NULL, NULL);
  120. // }
  121. //
  122. }
  123. }
  124. }
  125. }
  126. catch (...)
  127. {
  128. g_CS.Leave();
  129. //
  130. // We don't want to eat up any throw here. Such violations of COM programming, or
  131. // our own bug, should be exposed here to correction. So, re-throw the exception
  132. //
  133. throw;
  134. }
  135. g_CS.Leave();
  136. }
  137. */
  138. /////////////////////////////////////////////////////////////////////////////
  139. // CNetSecProv
  140. /*
  141. Routine Description:
  142. Name:
  143. CNetSecProv::Initialize
  144. Functionality:
  145. Called by WMI to let us initialize.
  146. Virtual:
  147. Yes (part of IWbemServices).
  148. Arguments:
  149. pszUser - The name of the user
  150. lFlags - Not in use.
  151. pszNamespace - Our provider's namespace string.
  152. pszLocale - Locale string.
  153. pNamespace - COM interface given by WMI that represents our provider.
  154. pCtx - COM interface pointer give to us by WMI and needed for various WMI APIs.
  155. pInitSink - COM interface pointer to notify WMI of any results.
  156. Return Value:
  157. Success:
  158. WBEM_NO_ERROR.
  159. Failure:
  160. Various error codes.
  161. Notes:
  162. Don't assume that this function will be called only once. I have seen
  163. this to be called multiple times by WMI.
  164. */
  165. STDMETHODIMP
  166. CNetSecProv::Initialize (
  167. IN LPWSTR pszUser,
  168. IN LONG lFlags,
  169. IN LPWSTR pszNamespace,
  170. IN LPWSTR pszLocale,
  171. IN IWbemServices * pNamespace,
  172. IN IWbemContext * pCtx,
  173. IN IWbemProviderInitSink * pInitSink
  174. )
  175. {
  176. HRESULT hr = ::CheckImpersonationLevel();
  177. if (FAILED(hr))
  178. {
  179. return hr;
  180. }
  181. if (pNamespace == NULL)
  182. {
  183. return WBEM_E_INVALID_PARAMETER;
  184. }
  185. m_srpNamespace = pNamespace;
  186. //::UpdateGlobals(pNamespace, pCtx);
  187. //
  188. //Let CIMOM know you are initialized
  189. //
  190. pInitSink->SetStatus(WBEM_S_INITIALIZED, 0);
  191. return WBEM_NO_ERROR;
  192. }
  193. /*
  194. Routine Description:
  195. Name:
  196. CNetSecProv::CreateInstanceEnumAsync
  197. Functionality:
  198. Given a class name (WMI class name), we will return all its instances to WMI.
  199. Virtual:
  200. Yes (part of IWbemServices).
  201. Arguments:
  202. strClass - The name of the WMI class.
  203. lFlags - Not in use.
  204. pCtx - COM interface pointer give to us by WMI and needed for various WMI APIs.
  205. pSink - COM interface pointer to notify WMI of any results.
  206. Return Value:
  207. Success:
  208. Various success codes.
  209. Failure:
  210. Various error codes.
  211. Notes:
  212. */
  213. STDMETHODIMP
  214. CNetSecProv::CreateInstanceEnumAsync (
  215. IN const BSTR bstrClass,
  216. IN long lFlags,
  217. IN IWbemContext * pCtx,
  218. IN IWbemObjectSink * pSink
  219. )
  220. {
  221. if (pSink == NULL)
  222. {
  223. return WBEM_E_INVALID_PARAMETER;
  224. }
  225. HRESULT hr = CheckImpersonationLevel();
  226. if(FAILED(hr))
  227. {
  228. return hr;
  229. }
  230. //
  231. // we will borrow our query implementation to deal with this class enumeration.
  232. // So, we will create a query like this: "select * from <bstrClass>"
  233. //
  234. CComPtr<IIPSecKeyChain> srpKeyChain;
  235. CComBSTR bstrQuery(L"SELECT * FROM ");
  236. bstrQuery += bstrClass;
  237. //
  238. // create a key chain that parses information from this class.
  239. // Again, we don't care about the where clause (actually, there is none)
  240. // "Name" is just a place holder. It requires a non-NULL value.
  241. //
  242. hr = GetKeyChainFromQuery(bstrQuery, L"Name", &srpKeyChain);
  243. if (FAILED(hr))
  244. {
  245. return hr;
  246. }
  247. //
  248. // Now we know which class we class it will create to respond to the request.
  249. //
  250. CComPtr<IIPSecObjectImpl> srpObj;
  251. hr = CIPSecBase::CreateObject(m_srpNamespace, srpKeyChain, pCtx, &srpObj);
  252. if (SUCCEEDED(hr))
  253. {
  254. hr = srpObj->QueryInstance(bstrQuery, pCtx, pSink);
  255. }
  256. pSink->SetStatus(WBEM_STATUS_COMPLETE, hr , NULL, NULL);
  257. return hr;
  258. }
  259. /*
  260. Routine Description:
  261. Name:
  262. CNetSecProv::GetObjectAsync
  263. Functionality:
  264. Given a path, we will create the wbem object representing it. Since most of our classes
  265. represent SPD objects, this path must contain the correct information (like the correct
  266. filter name, etc.) in order for us to create an wbem object to represent it. Bottom line:
  267. we won't create a wbem object unless we know our SPD has the corresponding object.
  268. Virtual:
  269. Yes (part of IWbemServices).
  270. Arguments:
  271. bstrObjectPath - The path.
  272. lFlags - Not in use.
  273. pCtx - COM interface pointer give to us by WMI and needed for various WMI APIs.
  274. pSink - COM interface pointer to notify WMI of any results.
  275. Return Value:
  276. Success:
  277. Various success codes.
  278. Failure:
  279. Various error codes.
  280. Notes:
  281. */
  282. STDMETHODIMP
  283. CNetSecProv::GetObjectAsync (
  284. IN const BSTR bstrObjectPath,
  285. IN long lFlags,
  286. IN IWbemContext * pCtx,
  287. IN IWbemObjectSink * pSink
  288. )
  289. {
  290. if (pSink == NULL)
  291. {
  292. return WBEM_E_INVALID_PARAMETER;
  293. }
  294. HRESULT hr = CheckImpersonationLevel();
  295. if(FAILED(hr))
  296. {
  297. return hr;
  298. }
  299. CComPtr<IIPSecKeyChain> srpKC;
  300. hr = GetKeyChainByPath(bstrObjectPath, &srpKC);
  301. if (SUCCEEDED(hr))
  302. {
  303. //
  304. // now create the class and ask it to delete itself
  305. //
  306. CComPtr<IIPSecObjectImpl> srpObj;
  307. hr = CIPSecBase::CreateObject(m_srpNamespace, srpKC, pCtx, &srpObj);
  308. if (SUCCEEDED(hr))
  309. {
  310. hr = srpObj->GetInstance(pCtx, pSink);
  311. }
  312. }
  313. pSink->SetStatus(WBEM_STATUS_COMPLETE ,hr , NULL, NULL);
  314. return hr;
  315. }
  316. /*
  317. Routine Description:
  318. Name:
  319. CNetSecProv::PutInstanceAsync
  320. Functionality:
  321. Given the object, we will put the instance in our namespace, which effectively
  322. translate into the corresponding semantics. For example, for IPSec object,
  323. this means that we will put the the object into SPD.
  324. Virtual:
  325. Yes (part of IWbemServices).
  326. Arguments:
  327. pInst - The object.
  328. lFlags - Not in use.
  329. pCtx - COM interface pointer give to us by WMI and needed for various WMI APIs.
  330. pInParams - COM interface pointer to the in parameter object.
  331. pSink - COM interface pointer to notify WMI of any results.
  332. Return Value:
  333. Success:
  334. Various success codes.
  335. Failure:
  336. Various error codes.
  337. Notes:
  338. */
  339. STDMETHODIMP
  340. CNetSecProv::PutInstanceAsync (
  341. IN IWbemClassObject * pInst,
  342. IN long lFlags,
  343. IN IWbemContext * pCtx,
  344. IN IWbemObjectSink * pSink
  345. )
  346. {
  347. if (pSink == NULL)
  348. {
  349. return WBEM_E_INVALID_PARAMETER;
  350. }
  351. HRESULT hr = CheckImpersonationLevel();
  352. if(FAILED(hr))
  353. {
  354. return hr;
  355. }
  356. //
  357. // we need to create our C++ class to represent this wbem object.
  358. // First, we need the path, which contains key property information.
  359. //
  360. CComVariant varObjPath;
  361. hr = pInst->Get(L"__Relpath", 0, &varObjPath, NULL, NULL);
  362. if (SUCCEEDED(hr) && varObjPath.vt == VT_BSTR)
  363. {
  364. CComPtr<IIPSecKeyChain> srpKC;
  365. hr = GetKeyChainByPath(varObjPath.bstrVal, &srpKC);
  366. if (SUCCEEDED(hr))
  367. {
  368. //
  369. // now create the class and ask it to delete itself
  370. //
  371. CComPtr<IIPSecObjectImpl> srpObj;
  372. hr = CIPSecBase::CreateObject(m_srpNamespace, srpKC, pCtx, &srpObj);
  373. if (SUCCEEDED(hr))
  374. {
  375. hr = srpObj->PutInstance(pInst, pCtx, pSink);
  376. }
  377. }
  378. }
  379. pSink->SetStatus(WBEM_STATUS_COMPLETE ,hr , NULL, NULL);
  380. return hr;
  381. }
  382. /*
  383. Routine Description:
  384. Name:
  385. CNetSecProv::ExecMethodAsync
  386. Functionality:
  387. Given the object's path, we will execute the method on the object.
  388. Virtual:
  389. Yes (part of IWbemServices).
  390. Arguments:
  391. bstrObjectPath - The path of the object.
  392. bstrMethod - The method name.
  393. lFlags - Not in use.
  394. pCtx - COM interface pointer give to us by WMI and needed for various WMI APIs.
  395. pInParams - COM interface pointer to the in parameter object.
  396. pSink - COM interface pointer to notify WMI of any results.
  397. Return Value:
  398. Success:
  399. Various success codes.
  400. Failure:
  401. Various error codes.
  402. Notes:
  403. */
  404. STDMETHODIMP
  405. CNetSecProv::ExecMethodAsync (
  406. IN const BSTR bstrObjectPath,
  407. IN const BSTR bstrMethod,
  408. IN long lFlags,
  409. IN IWbemContext * pCtx,
  410. IN IWbemClassObject * pInParams,
  411. IN IWbemObjectSink * pSink
  412. )
  413. {
  414. if (pSink == NULL)
  415. {
  416. return WBEM_E_INVALID_PARAMETER;
  417. }
  418. HRESULT hr = CheckImpersonationLevel();
  419. if(FAILED(hr))
  420. {
  421. return hr;
  422. }
  423. //
  424. // we are doing rolling back
  425. //
  426. //
  427. // we only have Nsp_TranxManager and Nsp_QMPolicySettings supporting methods.
  428. //
  429. if (_wcsicmp(bstrObjectPath, pszNspTranxManager) == 0)
  430. {
  431. //::UpdateGlobals(m_srpNamespace, pCtx);
  432. hr = CTranxManager::ExecMethod(m_srpNamespace, bstrMethod, pCtx, pInParams, pSink);
  433. }
  434. else if (_wcsicmp(bstrObjectPath, pszNspQMPolicy) == 0)
  435. {
  436. //::UpdateGlobals(m_srpNamespace, pCtx);
  437. hr = CQMPolicy::ExecMethod(m_srpNamespace, bstrMethod, pCtx, pInParams, pSink);
  438. }
  439. pSink->SetStatus(WBEM_STATUS_COMPLETE ,hr , NULL, NULL);
  440. return hr;
  441. }
  442. /*
  443. Routine Description:
  444. Name:
  445. CNetSecProv::DeleteInstanceAsync
  446. Functionality:
  447. Given the object's path, we will delete the the object.
  448. Virtual:
  449. Yes (part of IWbemServices).
  450. Arguments:
  451. bstrObjectPath - The path of the object.
  452. lFlags - Not in use.
  453. pCtx - The COM interface pointer give to us by WMI and needed for various WMI APIs.
  454. pSink - The COM interface pointer to notify WMI of any results.
  455. Return Value:
  456. Success:
  457. Various success codes.
  458. Failure:
  459. Various error codes.
  460. Notes:
  461. */
  462. STDMETHODIMP
  463. CNetSecProv::DeleteInstanceAsync (
  464. IN const BSTR bstrObjectPath,
  465. IN long lFlags,
  466. IN IWbemContext * pCtx,
  467. IN IWbemObjectSink * pSink
  468. )
  469. {
  470. if (pSink == NULL)
  471. {
  472. return WBEM_E_INVALID_PARAMETER;
  473. }
  474. HRESULT hr = CheckImpersonationLevel();
  475. if(FAILED(hr))
  476. {
  477. return hr;
  478. }
  479. CComPtr<IIPSecKeyChain> srpKC;
  480. hr = GetKeyChainByPath(bstrObjectPath, &srpKC);
  481. if (SUCCEEDED(hr))
  482. {
  483. //
  484. // now create the class and ask it to delete the WMI object it represents
  485. //
  486. CComPtr<IIPSecObjectImpl> srpObj;
  487. hr = CIPSecBase::CreateObject(m_srpNamespace, srpKC, pCtx, &srpObj);
  488. if (SUCCEEDED(hr))
  489. {
  490. hr = srpObj->DeleteInstance(pCtx, pSink);
  491. }
  492. }
  493. pSink->SetStatus(WBEM_STATUS_COMPLETE ,hr , NULL, NULL);
  494. return hr;
  495. }
  496. /*
  497. Routine Description:
  498. Name:
  499. CNetSecProv::ExecQueryAsync
  500. Functionality:
  501. Given the query, we will return the results to WMI. Each of our C++ classes knows
  502. how to process a query.
  503. Virtual:
  504. Yes (part of IWbemServices).
  505. Arguments:
  506. bstrQueryLanguage - The query language. We don't really care about it now.
  507. bstrQuery - The query.
  508. lFlags - Not in use.
  509. pCtx - The COM interface pointer give to us by WMI and needed for various WMI APIs.
  510. pSink - The COM interface pointer to notify WMI of any results.
  511. Return Value:
  512. Success:
  513. Various success codes.
  514. Failure:
  515. Various error codes.
  516. Notes:
  517. */
  518. STDMETHODIMP
  519. CNetSecProv::ExecQueryAsync (
  520. IN const BSTR bstrQueryLanguage,
  521. IN const BSTR bstrQuery,
  522. IN long lFlags,
  523. IN IWbemContext * pCtx,
  524. IN IWbemObjectSink * pSink
  525. )
  526. {
  527. if (pSink == NULL)
  528. {
  529. return WBEM_E_INVALID_PARAMETER;
  530. }
  531. HRESULT hr = CheckImpersonationLevel();
  532. if(FAILED(hr))
  533. {
  534. return hr;
  535. }
  536. //
  537. // For query, we really don't know what to expect inside the where clause.
  538. // So, we just give "Name" which we really don't care about.
  539. // Subclasses knows which property it will look for.
  540. //
  541. CComPtr<IIPSecKeyChain> srpKeyChain;
  542. hr = GetKeyChainFromQuery(bstrQuery, L"Name", &srpKeyChain);
  543. if (FAILED(hr))
  544. {
  545. return hr;
  546. }
  547. CComPtr<IIPSecObjectImpl> srpObj;
  548. hr = CIPSecBase::CreateObject(m_srpNamespace, srpKeyChain, pCtx, &srpObj);
  549. if (SUCCEEDED(hr))
  550. {
  551. hr = srpObj->QueryInstance(bstrQuery, pCtx, pSink);
  552. }
  553. pSink->SetStatus(WBEM_STATUS_COMPLETE, hr , NULL, NULL);
  554. return hr;
  555. }
  556. /*
  557. Routine Description:
  558. Name:
  559. CNetSecProv::GetKeyChainByPath
  560. Functionality:
  561. Given a path, we create a key chain from the path. This key chain
  562. contains key property information encoded in the path.
  563. Virtual:
  564. No.
  565. Arguments:
  566. pszPath - The object's path.
  567. ppKeyChain - Out parameter that receives the successfully created the key chain.
  568. Return Value:
  569. Success:
  570. WBEM_NO_ERROR
  571. Failure:
  572. Various error codes.
  573. Notes:
  574. */
  575. HRESULT
  576. CNetSecProv::GetKeyChainByPath (
  577. IN LPCWSTR pszPath,
  578. OUT IIPSecKeyChain ** ppKeyChain
  579. )
  580. {
  581. if (ppKeyChain == NULL)
  582. {
  583. return WBEM_E_INVALID_PARAMETER;
  584. }
  585. *ppKeyChain = NULL;
  586. CComPtr<IIPSecPathParser> srpPathParser;
  587. HRESULT hr = ::CoCreateInstance(CLSID_IPSecPathParser, NULL, CLSCTX_INPROC_SERVER, IID_IIPSecPathParser, (void**)&srpPathParser);
  588. if (SUCCEEDED(hr))
  589. {
  590. hr = srpPathParser->ParsePath(pszPath);
  591. if (SUCCEEDED(hr))
  592. {
  593. hr = srpPathParser->QueryInterface(IID_IIPSecKeyChain, (void**)ppKeyChain);
  594. //
  595. // S_FALSE means the object doesn't support the requested interface
  596. //
  597. if (S_FALSE == hr)
  598. {
  599. //
  600. // $undone:shawnwu, we need a more specific error
  601. //
  602. WBEM_E_FAILED;
  603. }
  604. }
  605. }
  606. return SUCCEEDED(hr) ? WBEM_NO_ERROR : hr;
  607. }
  608. /*
  609. Routine Description:
  610. Name:
  611. CNetSecProv::GetKeyChainFromQuery
  612. Functionality:
  613. Given a query, we create a key chain from the query to parse it.
  614. pszWhereProp is the concerned property of the where clause. Currently,
  615. our parser only cares about one property. This would be improved.
  616. Virtual:
  617. No.
  618. Arguments:
  619. pszQuery - The query.
  620. pszWhereProp - The property in the where clause that we care about.
  621. ppKeyChain - Out parameter that receives the successfully created the key chain.
  622. Return Value:
  623. Success:
  624. WBEM_NO_ERROR
  625. Failure:
  626. Various error codes.
  627. Notes:
  628. */
  629. HRESULT
  630. CNetSecProv::GetKeyChainFromQuery (
  631. IN LPCWSTR pszQuery,
  632. IN LPCWSTR pszWhereProp,
  633. OUT IIPSecKeyChain ** ppKeyChain // must not be NULL
  634. )
  635. {
  636. if (ppKeyChain == NULL)
  637. {
  638. return WBEM_E_INVALID_PARAMETER;
  639. }
  640. *ppKeyChain = NULL;
  641. CComPtr<IIPSecQueryParser> srpQueryParser;
  642. HRESULT hr = ::CoCreateInstance(CLSID_IPSecQueryParser, NULL, CLSCTX_INPROC_SERVER, IID_IIPSecQueryParser, (void**)&srpQueryParser);
  643. if (SUCCEEDED(hr))
  644. {
  645. //
  646. // this ParseQuery may fail because the where clause property may not be present at all.
  647. // we will thus ignore this hr
  648. //
  649. hr = srpQueryParser->ParseQuery(pszQuery, pszWhereProp);
  650. if (SUCCEEDED(hr))
  651. {
  652. hr = srpQueryParser->QueryInterface(IID_IIPSecKeyChain, (void**)ppKeyChain);
  653. //
  654. // S_FALSE means the object doesn't support the requested interface
  655. //
  656. if (S_FALSE == hr)
  657. {
  658. //
  659. // $undone:shawnwu, we need a more specific error
  660. //
  661. WBEM_E_FAILED;
  662. }
  663. }
  664. }
  665. return hr;
  666. }