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.

2318 lines
56 KiB

  1. // PolicyQM.cpp: implementation for the WMI class Nsp_QMPolicySettings
  2. //
  3. // Copyright (c)1997-2001 Microsoft Corporation
  4. //
  5. //////////////////////////////////////////////////////////////////////
  6. #include "precomp.h"
  7. #include "PolicyQM.h"
  8. #include "NetSecProv.h"
  9. #include "TranxMgr.h"
  10. const DWORD DefQMPolicyOfferFlag = 1;
  11. const IID guidDefQMPolicy_Neg_None = {0xed0d7a90,0x7d11,0x488f,{0x8a,0xd8,0x93,0x86,0xec,0xf6,0x59,0x6f}};
  12. const IID guidDefQMPolicy_Neg_Request = {0xb01536ca,0x9959,0x49e3,{0xa7,0x1a,0xb5,0x14,0x15,0xf5,0xff,0x63}};
  13. const IID guidDefQMPolicy_Neg_Require = {0x8853278b,0xc8e9,0x4265,{0xa9,0xfc,0xf2,0x92,0x81,0x2b,0xc6,0x60}};
  14. const IID guidDefQMPolicy_Neg_MAX = {0xfe048c67,0x1876,0x41c5,{0xae,0xec,0x7f,0x4d,0x62,0xa6,0x33,0xf8}};
  15. /*
  16. Routine Description:
  17. Name:
  18. CQMPolicy::QueryInstance
  19. Functionality:
  20. Given the query, it returns to WMI (using pSink) all the instances that satisfy the query.
  21. Actually, what we give back to WMI may contain extra instances. WMI will do the final filtering.
  22. Virtual:
  23. Yes (part of IIPSecObjectImpl)
  24. Arguments:
  25. None.
  26. Return Value:
  27. Success:
  28. (1) WBEM_NO_ERROR if instances are returned;
  29. (2) WBEM_S_NO_MORE_DATA if no instances are returned.
  30. Failure:
  31. Various errors may occur. We return various error code to indicate such errors.
  32. Notes:
  33. */
  34. STDMETHODIMP
  35. CQMPolicy::QueryInstance (
  36. IN LPCWSTR pszQuery,
  37. IN IWbemContext * pCtx,
  38. IN IWbemObjectSink * pSink
  39. )
  40. {
  41. //
  42. // get the filter name from the query
  43. // the key chain doesn't know anything about where clause property (policy name),
  44. // so let's create a better one.
  45. //
  46. m_srpKeyChain.Release();
  47. HRESULT hr = CNetSecProv::GetKeyChainFromQuery(pszQuery, g_pszPolicyName, &m_srpKeyChain);
  48. if (FAILED(hr))
  49. {
  50. return hr;
  51. }
  52. CComVariant varPolicyName;
  53. //
  54. // If the key property can't be found, it will return WBEM_S_FALSE,
  55. // and we are fine with that because a query may not have the key at all.
  56. //
  57. hr = m_srpKeyChain->GetKeyPropertyValue(g_pszPolicyName, &varPolicyName);
  58. LPCWSTR pszPolicyName = (varPolicyName.vt == VT_BSTR) ? varPolicyName.bstrVal : NULL;
  59. //
  60. // first, let's enumerate all MM filters
  61. //
  62. DWORD dwResumeHandle = 0;
  63. PIPSEC_QM_POLICY pQMPolicy = NULL;
  64. hr = FindPolicyByName(pszPolicyName, &pQMPolicy, &dwResumeHandle);
  65. while (SUCCEEDED(hr))
  66. {
  67. CComPtr<IWbemClassObject> srpObj;
  68. hr = CreateWbemObjFromQMPolicy(pQMPolicy, &srpObj);
  69. //
  70. // we created our wbem object, now give it to WMI
  71. //
  72. if (SUCCEEDED(hr))
  73. {
  74. pSink->Indicate(1, &srpObj);
  75. }
  76. ::SPDApiBufferFree(pQMPolicy);
  77. pQMPolicy = NULL;
  78. hr = FindPolicyByName(pszPolicyName, &pQMPolicy, &dwResumeHandle);
  79. }
  80. //
  81. // we are querying, so if not found, it's not an error
  82. //
  83. if (WBEM_E_NOT_FOUND == hr)
  84. {
  85. hr = WBEM_S_NO_MORE_DATA;
  86. }
  87. return hr;
  88. }
  89. /*
  90. Routine Description:
  91. Name:
  92. CQMPolicy::DeleteInstance
  93. Functionality:
  94. Will delete the wbem object, which will cause the quick mode policy to be deleted.
  95. Virtual:
  96. Yes (part of IIPSecObjectImpl)
  97. Arguments:
  98. pCtx - COM interface pointer given by WMI and needed for various WMI APIs.
  99. pSink - COM interface pointer to notify WMI of any created objects.
  100. Return Value:
  101. Success:
  102. WBEM_NO_ERROR;
  103. Failure:
  104. (1) WBEM_E_NOT_FOUND. Whether or not this should be considered an error
  105. depends on context.
  106. (2) Other errors indicating the cause.
  107. Notes:
  108. */
  109. STDMETHODIMP CQMPolicy::DeleteInstance (
  110. IN IWbemContext * pCtx,
  111. IN IWbemObjectSink * pSink
  112. )
  113. {
  114. CComVariant varPolicyName;
  115. HRESULT hr = m_srpKeyChain->GetKeyPropertyValue(g_pszPolicyName, &varPolicyName);
  116. if (FAILED(hr))
  117. {
  118. return hr;
  119. }
  120. else if (varPolicyName.vt != VT_BSTR || varPolicyName.bstrVal == NULL || varPolicyName.bstrVal[0] == L'\0')
  121. {
  122. return WBEM_E_NOT_FOUND;
  123. }
  124. return DeletePolicy(varPolicyName.bstrVal);
  125. }
  126. /*
  127. Routine Description:
  128. Name:
  129. CQMPolicy::ExecMethod
  130. Functionality:
  131. Quick mode policy implements two functions (See mof file) and so we need to implement this virtual function
  132. Virtual:
  133. Yes (part of IIPSecObjectImpl)
  134. Arguments:
  135. pNamespace - our namespace.
  136. pszMethod - The name of the method.
  137. pCtx - COM interface pointer by WMI and needed for various WMI APIs
  138. pInParams - COM interface pointer to the input parameter object.
  139. pSink - COM interface pointer for notifying WMI about results.
  140. Return Value:
  141. Success:
  142. Various success codes indicating the result.
  143. Failure:
  144. Various errors may occur. We return various error code to indicate such errors.
  145. Notes:
  146. */
  147. HRESULT
  148. CQMPolicy::ExecMethod (
  149. IN IWbemServices * pNamespace,
  150. IN LPCWSTR pszMethod,
  151. IN IWbemContext * pCtx,
  152. IN IWbemClassObject * pInParams,
  153. IN IWbemObjectSink * pSink
  154. )
  155. {
  156. if (pszMethod == NULL || *pszMethod == L'\0')
  157. {
  158. return WBEM_E_INVALID_PARAMETER;
  159. }
  160. bool bCreateDefPol = (_wcsicmp(pszMethod, pszCreateDefaultPolicy) == 0);
  161. bool bGetDefPolName= (_wcsicmp(pszMethod, pszGetDefaultPolicyName) == 0);
  162. HRESULT hr = WBEM_E_NOT_SUPPORTED;
  163. if (bCreateDefPol || bGetDefPolName)
  164. {
  165. CComVariant varEncryption;
  166. hr = pInParams->Get(g_pszEncryption, 0, &varEncryption, NULL, NULL);
  167. if (SUCCEEDED(hr) && varEncryption.vt == VT_I4 &&
  168. varEncryption.lVal >= RAS_L2TP_NO_ENCRYPTION &&
  169. varEncryption.lVal <= RAS_L2TP_REQUIRE_ENCRYPTION )
  170. {
  171. LPCWSTR pszRetNames[2] = {L"ReturnValue", L"Name"};
  172. VARIANT varValues[2];
  173. ::VariantInit(&(varValues[0]));
  174. ::VariantInit(&(varValues[1]));
  175. //
  176. // Let's assume it is a CreateDefaultPolicy call. So there is only one value to pass back
  177. //
  178. DWORD dwCount = 1;
  179. if (bCreateDefPol)
  180. {
  181. hr = CreateDefaultPolicy((EnumEncryption)varEncryption.lVal);
  182. }
  183. else
  184. {
  185. varValues[1].vt = VT_BSTR;
  186. varValues[1].bstrVal = ::SysAllocString(GetDefaultPolicyName((EnumEncryption)varEncryption.lVal));
  187. //
  188. // just in case, no memory can be allocated for the bstr, reset the var to empty
  189. //
  190. if (varValues[1].bstrVal == NULL)
  191. {
  192. hr = WBEM_E_OUT_OF_MEMORY;
  193. varValues[1].vt = VT_EMPTY;
  194. }
  195. else
  196. {
  197. //
  198. // we have two values to pass back: one for the return value and one for the out parameter "Name"
  199. //
  200. dwCount = 2;
  201. }
  202. }
  203. //
  204. // pack the values (out parameter and return value) to pass back to WMI.
  205. // Return value = 1 means success. Regardless of success or failure, we need to do this.
  206. //
  207. varValues[0].vt = VT_I4;
  208. varValues[0].lVal = SUCCEEDED(hr) ? 1 : 0;
  209. HRESULT hrDoReturn = DoReturn(pNamespace, pszMethod, dwCount, pszRetNames, varValues, pCtx, pSink);
  210. //
  211. // now clean up the vars
  212. //
  213. ::VariantClear(&(varValues[0]));
  214. ::VariantClear(&(varValues[1]));
  215. if (SUCCEEDED(hr) && FAILED(hrDoReturn))
  216. {
  217. hr = hrDoReturn;
  218. }
  219. }
  220. else
  221. {
  222. hr = WBEM_E_INVALID_PARAMETER;
  223. }
  224. }
  225. return hr;
  226. }
  227. /*
  228. Routine Description:
  229. Name:
  230. CQMPolicy::PutInstance
  231. Functionality:
  232. Put a quick mode policy into SPD whose properties are represented by the
  233. wbem object.
  234. Virtual:
  235. Yes (part of IIPSecObjectImpl)
  236. Arguments:
  237. pInst - The wbem object.
  238. pCtx - COM interface pointer given by WMI and needed for various WMI APIs.
  239. pSink - COM interface pointer to notify WMI of results.
  240. Return Value:
  241. Success:
  242. WBEM_NO_ERROR
  243. Failure:
  244. Various error codes specifying the error.
  245. Notes:
  246. */
  247. STDMETHODIMP
  248. CQMPolicy::PutInstance (
  249. IN IWbemClassObject * pInst,
  250. IN IWbemContext * pCtx,
  251. IN IWbemObjectSink * pSink
  252. )
  253. {
  254. if (pInst == NULL || pSink == NULL)
  255. {
  256. return WBEM_E_INVALID_PARAMETER;
  257. }
  258. bool bPreExist = false;
  259. //
  260. // for those policies that are created by ourselves (bPreExist == true)
  261. // we have our own way of allocating the buffer, need to free it in our corresponding way
  262. //
  263. PIPSEC_QM_POLICY pPolicy = NULL;
  264. HRESULT hr = GetQMPolicyFromWbemObj(pInst, &pPolicy, &bPreExist);
  265. //
  266. // if policy is successfully returned, then use it
  267. //
  268. if (SUCCEEDED(hr) && pPolicy)
  269. {
  270. hr = AddPolicy(bPreExist, pPolicy);
  271. //
  272. // deposit info about this action so that rollback can be done.
  273. //
  274. if (SUCCEEDED(hr))
  275. {
  276. hr = OnAfterAddPolicy(pPolicy->pszPolicyName, QuickMode_Policy);
  277. }
  278. FreePolicy(&pPolicy, bPreExist);
  279. }
  280. return hr;
  281. }
  282. /*
  283. Routine Description:
  284. Name:
  285. CQMPolicy::GetInstance
  286. Functionality:
  287. Create a wbem object by the given key properties (already captured by our key chain object)..
  288. Virtual:
  289. Yes (part of IIPSecObjectImpl)
  290. Arguments:
  291. pCtx - COM interface pointer given by WMI and needed for various WMI APIs.
  292. pSink - COM interface pointer to notify WMI of any created objects.
  293. Return Value:
  294. Success:
  295. Success code. Use SUCCEEDED(hr) to test.
  296. Failure:
  297. (1) WBEM_E_NOT_FOUND if the auth method can't be found. Depending on
  298. the context, this may not be an error
  299. (2) Other various errors indicated by the returned error codes.
  300. Notes:
  301. */
  302. STDMETHODIMP
  303. CQMPolicy::GetInstance (
  304. IN IWbemContext * pCtx,
  305. IN IWbemObjectSink * pSink
  306. )
  307. {
  308. CComVariant varPolicyName;
  309. //
  310. // since policy name is a key property, it must have policy name property in the path and thus in the key chain
  311. //
  312. HRESULT hr = m_srpKeyChain->GetKeyPropertyValue(g_pszPolicyName, &varPolicyName);
  313. if (FAILED(hr))
  314. {
  315. return hr;
  316. }
  317. else if (varPolicyName.vt != VT_BSTR || varPolicyName.bstrVal == NULL || varPolicyName.bstrVal[0] == L'\0')
  318. {
  319. return WBEM_E_NOT_FOUND;
  320. }
  321. PIPSEC_QM_POLICY pQMPolicy = NULL;
  322. DWORD dwResumeHandle = 0;
  323. hr = FindPolicyByName(varPolicyName.bstrVal, &pQMPolicy, &dwResumeHandle);
  324. if (SUCCEEDED(hr))
  325. {
  326. CComPtr<IWbemClassObject> srpObj;
  327. hr = CreateWbemObjFromQMPolicy(pQMPolicy, &srpObj);
  328. if (SUCCEEDED(hr))
  329. {
  330. hr = pSink->Indicate(1, &srpObj);
  331. }
  332. ::SPDApiBufferFree(pQMPolicy);
  333. }
  334. return hr;
  335. }
  336. /*
  337. Routine Description:
  338. Name:
  339. CQMPolicy::CreateWbemObjFromMMPolicy
  340. Functionality:
  341. Given a SPD's quick mode policy, we will create a wbem object representing it.
  342. Virtual:
  343. No.
  344. Arguments:
  345. pPolicy - The SPD's quick mode policy object.
  346. ppObj - Receives the wbem object.
  347. Return Value:
  348. Success:
  349. WBEM_NO_ERROR
  350. Failure:
  351. (1) various errors indicated by the returned error codes.
  352. Notes:
  353. */
  354. HRESULT
  355. CQMPolicy::CreateWbemObjFromQMPolicy (
  356. IN PIPSEC_QM_POLICY pPolicy,
  357. OUT IWbemClassObject ** ppObj
  358. )
  359. {
  360. if (pPolicy == NULL || ppObj == NULL)
  361. {
  362. return WBEM_E_INVALID_PARAMETER;
  363. }
  364. *ppObj = NULL;
  365. //
  366. // create a wbem object of this class that can be used to fill in properties
  367. //
  368. HRESULT hr = SpawnObjectInstance(ppObj);
  369. //
  370. // fill in base class members (CIPSecPolicy)
  371. //
  372. if (SUCCEEDED(hr))
  373. {
  374. hr = CreateWbemObjFromPolicy(pPolicy, *ppObj);
  375. }
  376. if (SUCCEEDED(hr))
  377. {
  378. //
  379. // deal with all those arrays
  380. //
  381. CComVariant var;
  382. var.vt = VT_ARRAY | VT_I4;
  383. SAFEARRAYBOUND rgsabound[1];
  384. rgsabound[0].lLbound = 0;
  385. rgsabound[0].cElements = pPolicy->dwOfferCount;
  386. var.parray = ::SafeArrayCreate(VT_I4, 1, rgsabound);
  387. if (var.parray == NULL)
  388. {
  389. hr = WBEM_E_OUT_OF_MEMORY;
  390. }
  391. else
  392. {
  393. long lIndecies[1];
  394. //
  395. //$undone:shawnwu, we need to write some generic routine to do this repeatitive array
  396. // put (and get). That routine can only be based on memory offset!
  397. //
  398. //
  399. // put bPFSRequired, array of boolean
  400. //
  401. CComVariant varBoolArray;
  402. varBoolArray.vt = VT_ARRAY | VT_BOOL;
  403. varBoolArray.parray = ::SafeArrayCreate(VT_BOOL, 1, rgsabound);
  404. VARIANT varBool;
  405. varBool.vt = VT_BOOL;
  406. for (DWORD dwIndex = 0; SUCCEEDED(hr) && dwIndex < pPolicy->dwOfferCount; dwIndex++)
  407. {
  408. lIndecies[0] = dwIndex;
  409. varBool.boolVal = (pPolicy->pOffers[dwIndex].bPFSRequired) ? VARIANT_TRUE : VARIANT_FALSE;
  410. hr = ::SafeArrayPutElement(varBoolArray.parray, lIndecies, &(varBool.boolVal));
  411. }
  412. if (SUCCEEDED(hr))
  413. {
  414. hr = (*ppObj)->Put(g_pszPFSRequired, 0, &varBoolArray, CIM_EMPTY);
  415. }
  416. //
  417. // put dwPFSGroup, array of VT_I4. var has been created with the right count
  418. // for VT_I4 array
  419. //
  420. for (dwIndex = 0; SUCCEEDED(hr) && dwIndex < pPolicy->dwOfferCount; dwIndex++)
  421. {
  422. lIndecies[0] = dwIndex;
  423. hr = ::SafeArrayPutElement(var.parray, lIndecies, &(pPolicy->pOffers[dwIndex].dwPFSGroup) );
  424. }
  425. if (SUCCEEDED(hr))
  426. {
  427. hr = (*ppObj)->Put(g_pszPFSGroup, 0, &var, CIM_EMPTY);
  428. }
  429. //
  430. // put dwNumAlgos, array of VT_I4.
  431. //
  432. for (dwIndex = 0; SUCCEEDED(hr) && dwIndex < pPolicy->dwOfferCount; dwIndex++)
  433. {
  434. lIndecies[0] = dwIndex;
  435. hr = ::SafeArrayPutElement(var.parray, lIndecies, &(pPolicy->pOffers[dwIndex].dwNumAlgos) );
  436. }
  437. if (SUCCEEDED(hr))
  438. {
  439. hr = (*ppObj)->Put(g_pszNumAlgos, 0, &var, CIM_EMPTY);
  440. }
  441. //
  442. // for each individual Algo, we have to fill up all reserved elements (QM_MAX_ALGOS)
  443. // even though the actual offer count is less. See PIPSEC_QM_OFFER for details.
  444. //
  445. //
  446. // Now the array size has changed to count the QM_MAX_ALGOS,
  447. // which is different from what var is created. So, re-create a different array!
  448. //
  449. if (SUCCEEDED(hr))
  450. {
  451. var.Clear();
  452. var.vt = VT_ARRAY | VT_I4;
  453. rgsabound[0].cElements = pPolicy->dwOfferCount * QM_MAX_ALGOS;
  454. var.parray = ::SafeArrayCreate(VT_I4, 1, rgsabound);
  455. if (var.parray == NULL)
  456. {
  457. hr = WBEM_E_OUT_OF_MEMORY;
  458. }
  459. else
  460. {
  461. DWORD dwSub;
  462. //
  463. // put Algos[i].Operation.
  464. //
  465. for (dwIndex = 0; SUCCEEDED(hr) && dwIndex < pPolicy->dwOfferCount; dwIndex++)
  466. {
  467. for (dwSub = 0; SUCCEEDED(hr) && dwSub < QM_MAX_ALGOS; dwSub++)
  468. {
  469. lIndecies[0] = dwIndex * QM_MAX_ALGOS + dwSub;
  470. hr = ::SafeArrayPutElement(var.parray, lIndecies, &(pPolicy->pOffers[dwIndex].Algos[dwSub].Operation) );
  471. }
  472. }
  473. if (SUCCEEDED(hr))
  474. {
  475. hr = (*ppObj)->Put(g_pszAlgoOp, 0, &var, CIM_EMPTY);
  476. }
  477. //
  478. // put Algos[i].uAlgoIdentifier.
  479. //
  480. for (dwIndex = 0; SUCCEEDED(hr) && dwIndex < pPolicy->dwOfferCount; dwIndex++)
  481. {
  482. for (dwSub = 0; SUCCEEDED(hr) && dwSub < QM_MAX_ALGOS; dwSub++)
  483. {
  484. lIndecies[0] = dwIndex * QM_MAX_ALGOS + dwSub;
  485. hr = ::SafeArrayPutElement(var.parray, lIndecies, &(pPolicy->pOffers[dwIndex].Algos[dwSub].uAlgoIdentifier) );
  486. }
  487. }
  488. if (SUCCEEDED(hr))
  489. {
  490. hr = (*ppObj)->Put(g_pszAlgoID, 0, &var, CIM_EMPTY);
  491. }
  492. //
  493. // put Algos[i].uSecAlgoIdentifier.
  494. //
  495. for (dwIndex = 0; SUCCEEDED(hr) && dwIndex < pPolicy->dwOfferCount; dwIndex++)
  496. {
  497. for (dwSub = 0; SUCCEEDED(hr) && dwSub < QM_MAX_ALGOS; dwSub++)
  498. {
  499. lIndecies[0] = dwIndex * QM_MAX_ALGOS + dwSub;
  500. hr = ::SafeArrayPutElement(var.parray, lIndecies, &(pPolicy->pOffers[dwIndex].Algos[dwSub].uSecAlgoIdentifier) );
  501. }
  502. }
  503. if (SUCCEEDED(hr))
  504. {
  505. hr = (*ppObj)->Put(g_pszAlgoSecID, 0, &var, CIM_EMPTY);
  506. }
  507. }
  508. }
  509. }
  510. }
  511. //
  512. // we may have created the object, but some mid steps have failed,
  513. // so let's release the object.
  514. //
  515. if (FAILED(hr) && *ppObj != NULL)
  516. {
  517. (*ppObj)->Release();
  518. *ppObj = NULL;
  519. }
  520. return SUCCEEDED(hr) ? WBEM_NO_ERROR : hr;
  521. }
  522. /*
  523. Routine Description:
  524. Name:
  525. CQMPolicy::GetQMPolicyFromWbemObj
  526. Functionality:
  527. Will try to get the quick mode policy if such policy already exists.
  528. Otherwise, we will create a new one.
  529. Virtual:
  530. No.
  531. Arguments:
  532. pInst - The wbem object object.
  533. ppPolicy - Receives the quick mode policy.
  534. pbPreExist - Receives the information whether this object memory is allocated by SPD or not.
  535. Return Value:
  536. Success:
  537. WBEM_NO_ERROR
  538. Failure:
  539. (1) various errors indicated by the returned error codes.
  540. Notes:
  541. if some property is missing from the wbem object, we will supply the default value.
  542. */
  543. HRESULT
  544. CQMPolicy::GetQMPolicyFromWbemObj (
  545. IN IWbemClassObject * pInst,
  546. OUT PIPSEC_QM_POLICY * ppPolicy,
  547. OUT bool * pbPreExist
  548. )
  549. {
  550. if (pInst == NULL || ppPolicy == NULL || pbPreExist == NULL)
  551. {
  552. return WBEM_E_INVALID_PARAMETER;
  553. }
  554. *ppPolicy = NULL;
  555. *pbPreExist = false;
  556. //
  557. // get the policy (if new, then it will fill up the common (MM and QM) properties
  558. //
  559. HRESULT hr = GetPolicyFromWbemObj(pInst, ppPolicy, pbPreExist);
  560. //
  561. // we don't support modification on existing policies
  562. //
  563. if (SUCCEEDED(hr) && *pbPreExist == false)
  564. {
  565. CComVariant var;
  566. //
  567. // wbem object may not have all the properties, we will use default when a property is not present.
  568. // as a result, we don't keep the HRESULT and return it the caller
  569. //
  570. //
  571. // for readability
  572. //
  573. DWORD dwOfferCount = (*ppPolicy)->dwOfferCount;
  574. //
  575. // These four members are for each offer. Our safe array size will be thus of dwOfferCount number of
  576. // dwFlags; bPFSRequired; dwPFSGroup; dwNumAlgos;
  577. // But for each offer, its Algos is an array of size QM_MAX_ALGOS (currently defined as 2).
  578. // See PIPSEC_QM_POLICY for details.
  579. //
  580. //
  581. // dwFlags; We don't have a member for this flag. Hardcode it.
  582. //
  583. for (long l = 0; l < dwOfferCount; l++)
  584. {
  585. (*ppPolicy)->pOffers[l].dwFlags = DefaultQMPolicyOfferFlag;
  586. }
  587. //
  588. // need to delete the memory
  589. //
  590. DWORD* pdwValues = new DWORD[dwOfferCount * QM_MAX_ALGOS];
  591. if (pdwValues == NULL)
  592. {
  593. hr = WBEM_E_OUT_OF_MEMORY;
  594. }
  595. else
  596. {
  597. var.Clear();
  598. //
  599. // If the property is missing from wbem object, we will initialize them to default values.
  600. //
  601. bool bInitialized = false;
  602. //
  603. // set bPFSRequired
  604. //
  605. if ( SUCCEEDED(pInst->Get(g_pszPFSRequired, 0, &var, NULL, NULL)) && (var.vt & VT_ARRAY) == VT_ARRAY )
  606. {
  607. if (SUCCEEDED(::GetDWORDSafeArrayElements(&var, dwOfferCount, pdwValues)))
  608. {
  609. //
  610. // we are guaranteed to get values after this point.
  611. //
  612. bInitialized = true;
  613. for (l = 0; l < dwOfferCount; l++)
  614. {
  615. (*ppPolicy)->pOffers[l].bPFSRequired = pdwValues[l];
  616. }
  617. }
  618. }
  619. if (!bInitialized)
  620. {
  621. //
  622. // property is missing, initialize to default values
  623. //
  624. for (l = 0; l < dwOfferCount; l++)
  625. {
  626. (*ppPolicy)->pOffers[l].bPFSRequired = DefaultPFSRequired;
  627. }
  628. }
  629. //
  630. // Reset for next property
  631. //
  632. bInitialized = false;
  633. var.Clear();
  634. //
  635. // set bPFSRequired
  636. //
  637. if ( SUCCEEDED(pInst->Get(g_pszPFSGroup, 0, &var, NULL, NULL)) && (var.vt & VT_ARRAY) == VT_ARRAY )
  638. {
  639. if (SUCCEEDED(::GetDWORDSafeArrayElements(&var, dwOfferCount, pdwValues)))
  640. {
  641. //
  642. // we are guaranteed to get values after this point.
  643. //
  644. bInitialized = true;
  645. for (l = 0; l < dwOfferCount; l++)
  646. {
  647. (*ppPolicy)->pOffers[l].dwPFSGroup = pdwValues[l];
  648. }
  649. }
  650. }
  651. if (!bInitialized)
  652. {
  653. //
  654. // property is missing, initialize to default values
  655. //
  656. for (l = 0; l < dwOfferCount; l++)
  657. {
  658. (*ppPolicy)->pOffers[l].dwPFSGroup = DefaultPFSGroup;
  659. }
  660. }
  661. //
  662. // Reset for next property
  663. //
  664. bInitialized = false;
  665. var.Clear();
  666. //
  667. // set dwNumAlgos
  668. //
  669. if ( SUCCEEDED(pInst->Get(g_pszNumAlgos, 0, &var, NULL, NULL)) && (var.vt & VT_ARRAY) == VT_ARRAY )
  670. {
  671. if (SUCCEEDED(::GetDWORDSafeArrayElements(&var, dwOfferCount, pdwValues)))
  672. {
  673. //
  674. // we are guaranteed to get values after this point.
  675. //
  676. bInitialized = true;
  677. for (l = 0; l < dwOfferCount; l++)
  678. {
  679. (*ppPolicy)->pOffers[l].dwNumAlgos = pdwValues[l];
  680. }
  681. }
  682. }
  683. if (!bInitialized)
  684. {
  685. //
  686. // property is missing, initialize to default values
  687. //
  688. for (l = 0; l < dwOfferCount; l++)
  689. {
  690. (*ppPolicy)->pOffers[l].dwNumAlgos = DefaultNumAlgos;
  691. }
  692. }
  693. //
  694. // Reset for next property
  695. //
  696. bInitialized = false;
  697. var.Clear();
  698. //
  699. // set individual IPSEC_QM_ALGO. For each offer, there are QM_MAX_ALGOS reserved IPSEC_QM_ALGO's
  700. // even though there might be less than that number of IPSEC_QM_ALGO's (determined by pOffers[l].dwNumAlgos)
  701. //
  702. //
  703. // lSub is for index of the second dimension.
  704. //
  705. long lSub;
  706. //
  707. // set Operation
  708. //
  709. if ( SUCCEEDED(pInst->Get(g_pszAlgoOp, 0, &var, NULL, NULL)) && (var.vt & VT_ARRAY) == VT_ARRAY )
  710. {
  711. if (SUCCEEDED(::GetDWORDSafeArrayElements(&var, dwOfferCount * QM_MAX_ALGOS, pdwValues)))
  712. {
  713. //
  714. // we are guaranteed to get values after this point.
  715. //
  716. bInitialized = true;
  717. for (l = 0; l < dwOfferCount; l++)
  718. {
  719. for (lSub = 0; lSub < (*ppPolicy)->pOffers[l].dwNumAlgos; lSub++)
  720. {
  721. IPSEC_OPERATION op = (IPSEC_OPERATION)pdwValues[l * QM_MAX_ALGOS + lSub];
  722. if (op <= NONE || op > SA_DELETE)
  723. {
  724. (*ppPolicy)->pOffers[l].Algos[lSub].Operation = DefaultQMAlgoOperation;
  725. }
  726. else
  727. {
  728. (*ppPolicy)->pOffers[l].Algos[lSub].Operation = op;
  729. }
  730. }
  731. }
  732. }
  733. }
  734. if (!bInitialized)
  735. {
  736. for (l = 0; l < dwOfferCount; l++)
  737. {
  738. for (lSub = 0; lSub < (*ppPolicy)->pOffers[l].dwNumAlgos; lSub++)
  739. {
  740. (*ppPolicy)->pOffers[l].Algos[lSub].Operation = DefaultQMAlgoOperation;
  741. }
  742. }
  743. }
  744. //
  745. // set uAlgoIdentifier
  746. //
  747. bInitialized = false;
  748. if ( SUCCEEDED(pInst->Get(g_pszAlgoID, 0, &var, NULL, NULL)) && (var.vt & VT_ARRAY) == VT_ARRAY )
  749. {
  750. if (SUCCEEDED(::GetDWORDSafeArrayElements(&var, dwOfferCount * QM_MAX_ALGOS, pdwValues)))
  751. {
  752. //
  753. // we are guaranteed to get values after this point.
  754. //
  755. bInitialized = true;
  756. for (l = 0; l < dwOfferCount; l++)
  757. {
  758. for (lSub = 0; lSub < (*ppPolicy)->pOffers[l].dwNumAlgos; lSub++)
  759. {
  760. (*ppPolicy)->pOffers[l].Algos[lSub].uAlgoIdentifier = pdwValues[l * QM_MAX_ALGOS + lSub];
  761. }
  762. }
  763. }
  764. }
  765. //
  766. // in case no values have been set
  767. //
  768. if (!bInitialized)
  769. {
  770. for (l = 0; l < dwOfferCount; l++)
  771. {
  772. for (lSub = 0; lSub < (*ppPolicy)->pOffers[l].dwNumAlgos; lSub++)
  773. {
  774. (*ppPolicy)->pOffers[l].Algos[lSub].uAlgoIdentifier = DefaultAlgoID;
  775. }
  776. }
  777. }
  778. //
  779. // set uSecAlgoIdentifier
  780. //
  781. bInitialized = false;
  782. if ( SUCCEEDED(pInst->Get(g_pszAlgoSecID, 0, &var, NULL, NULL)) && (var.vt & VT_ARRAY) == VT_ARRAY )
  783. {
  784. if (SUCCEEDED(::GetDWORDSafeArrayElements(&var, dwOfferCount * QM_MAX_ALGOS, pdwValues)))
  785. {
  786. //
  787. // we are guaranteed to get values after this point.
  788. //
  789. bInitialized = true;
  790. for (l = 0; l < dwOfferCount; l++)
  791. {
  792. for (lSub = 0; lSub < (*ppPolicy)->pOffers[l].dwNumAlgos; lSub++)
  793. {
  794. HMAC_AH_ALGO ag = (HMAC_AH_ALGO)pdwValues[l * QM_MAX_ALGOS + lSub];
  795. if (ag <= HMAC_AH_NONE || ag >= HMAC_AH_MAX)
  796. {
  797. (*ppPolicy)->pOffers[l].Algos[lSub].uSecAlgoIdentifier = DefaultAlgoSecID;
  798. }
  799. else
  800. {
  801. (*ppPolicy)->pOffers[l].Algos[lSub].uSecAlgoIdentifier = ag;
  802. }
  803. }
  804. }
  805. }
  806. }
  807. //
  808. // in case no values have been set
  809. //
  810. if (!bInitialized)
  811. {
  812. for (l = 0; l < dwOfferCount; l++)
  813. {
  814. for (lSub = 0; lSub < (*ppPolicy)->pOffers[l].dwNumAlgos; lSub++)
  815. {
  816. (*ppPolicy)->pOffers[l].Algos[lSub].uSecAlgoIdentifier = DefaultAlgoSecID;
  817. }
  818. }
  819. }
  820. }
  821. //
  822. // free memory
  823. //
  824. delete [] pdwValues;
  825. }
  826. if (FAILED(hr) && *ppPolicy != NULL)
  827. {
  828. FreePolicy(ppPolicy, *pbPreExist);
  829. }
  830. return SUCCEEDED(hr) ? WBEM_NO_ERROR : hr;
  831. }
  832. /*
  833. Routine Description:
  834. Name:
  835. CQMPolicy::AddPolicy
  836. Functionality:
  837. Add the given quick mode policy to SPD.
  838. Virtual:
  839. No.
  840. Arguments:
  841. bPreExist - Flag whether the main mode auth method already exists in SPD
  842. pQMPolicy - The quick mode policy to add.
  843. Return Value:
  844. Success:
  845. WBEM_NO_ERROR.
  846. Failure:
  847. WBEM_E_FAILED.
  848. Notes:
  849. */
  850. HRESULT
  851. CQMPolicy::AddPolicy (
  852. IN bool bPreExist,
  853. IN PIPSEC_QM_POLICY pQMPolicy
  854. )
  855. {
  856. DWORD dwResult = ERROR_SUCCESS;
  857. HRESULT hr = WBEM_NO_ERROR;
  858. if (bPreExist)
  859. {
  860. dwResult = ::SetQMPolicy(NULL, pQMPolicy->pszPolicyName, pQMPolicy);
  861. }
  862. else
  863. {
  864. dwResult = ::AddQMPolicy(NULL, 1, pQMPolicy);
  865. }
  866. if (dwResult != ERROR_SUCCESS)
  867. {
  868. hr = ::IPSecErrorToWbemError(dwResult);
  869. }
  870. //
  871. // $undone:shawnwu, need better error code for failures.
  872. //
  873. return hr;
  874. }
  875. /*
  876. Routine Description:
  877. Name:
  878. CQMPolicy::DeletePolicy
  879. Functionality:
  880. Delete given quick mode policy from SPD.
  881. Virtual:
  882. No.
  883. Arguments:
  884. pszPolicyName - The name of the policy to delete.
  885. Return Value:
  886. Success:
  887. WBEM_NO_ERROR.
  888. Failure:
  889. (1) WBEM_E_INVALID_PARAMETER: if pszPolicyName == NULL or *pszPolicyName == L'\0'.
  890. (2) WBEM_E_VETO_DELETE: if we are not allowed to delete the policy by SPD.
  891. Notes:
  892. */
  893. HRESULT
  894. CQMPolicy::DeletePolicy (
  895. IN LPCWSTR pszPolicyName
  896. )
  897. {
  898. if (pszPolicyName == NULL || *pszPolicyName == L'\0')
  899. {
  900. return WBEM_E_INVALID_PARAMETER;
  901. }
  902. HRESULT hr = WBEM_NO_ERROR;
  903. //
  904. // casting to LPWSTR is due to IPSec API's mistake
  905. //
  906. DWORD dwStatus = ::DeleteQMPolicy(NULL, (LPWSTR)pszPolicyName);
  907. if (dwStatus != ERROR_SUCCESS)
  908. {
  909. hr = IPSecErrorToWbemError(dwStatus);
  910. }
  911. return hr;
  912. }
  913. /*
  914. Routine Description:
  915. Name:
  916. CQMPolicy::GetDefaultQMPolicyName
  917. Functionality:
  918. return to the caller the default quick mode policy name that we will
  919. create upon request (CreateDefaultQMPolicy).
  920. Virtual:
  921. No.
  922. Arguments:
  923. eEncryption - The type of encryption the quick mode policy wants.
  924. Return Value:
  925. Our default policy's name if the encryption is recognized. Otherwise, it returns NULL;
  926. Notes:
  927. */
  928. LPCWSTR
  929. CQMPolicy::GetDefaultPolicyName (
  930. EnumEncryption eEncryption
  931. )
  932. {
  933. switch (eEncryption)
  934. {
  935. case RAS_L2TP_NO_ENCRYPTION:
  936. return g_pszDefQMPolicyNegNone;
  937. break;
  938. case RAS_L2TP_OPTIONAL_ENCRYPTION:
  939. return g_pszDefQMPolicyNegRequest;
  940. break;
  941. case RAS_L2TP_REQUIRE_ENCRYPTION:
  942. return g_pszDefQMPolicyNegRequire;
  943. break;
  944. case RAS_L2TP_REQUIRE_MAX_ENCRYPTION:
  945. return g_pszDefQMPolicyNegMax;
  946. break;
  947. default:
  948. return NULL;
  949. }
  950. }
  951. /*
  952. Routine Description:
  953. Name:
  954. CQMPolicy::CreateDefaultPolicy
  955. Functionality:
  956. Will create the default qm policy with the requested encryption.
  957. Virtual:
  958. No.
  959. Arguments:
  960. eEncryption - The type of encryption the quick mode policy wants.
  961. Return Value:
  962. Success:
  963. WBEM_NO_ERROR.
  964. Failure:
  965. (1) WBEM_E_INVALID_PARAMETER: if pszPolicyName == NULL or *pszPolicyName == L'\0'.
  966. (2) WBEM_E_NOT_SUPPORTED: the requested encryption is not supported
  967. (3) WBEM_E_OUT_OF_MEMORY.
  968. Notes:
  969. */
  970. HRESULT
  971. CQMPolicy::CreateDefaultPolicy (
  972. EnumEncryption eEncryption
  973. )
  974. {
  975. PIPSEC_QM_POLICY pDefQMPolicy = NULL;
  976. DWORD dwResumeHandle = 0;
  977. HRESULT hr = FindPolicyByName(GetDefaultPolicyName(eEncryption), &pDefQMPolicy, &dwResumeHandle);
  978. if (SUCCEEDED(hr))
  979. {
  980. //
  981. // already there, don't need to create and add
  982. //
  983. ::SPDApiBufferFree(pDefQMPolicy);
  984. return hr;
  985. }
  986. //
  987. // otherwise, this default policy is not there, then we need to create it and add it to SPD
  988. //
  989. IPSEC_QM_OFFER Offers[20];
  990. IPSEC_QM_POLICY QMPolicy;
  991. memset(Offers, 0, sizeof(IPSEC_QM_OFFER)*20);
  992. DWORD dwOfferCount = 0;
  993. DWORD dwFlags = 0;
  994. DWORD dwStatus = ::BuildOffers(
  995. eEncryption,
  996. Offers,
  997. &dwOfferCount,
  998. &dwFlags
  999. );
  1000. if (dwStatus == ERROR_SUCCESS)
  1001. {
  1002. BuildQMPolicy(
  1003. &QMPolicy,
  1004. eEncryption,
  1005. Offers,
  1006. dwOfferCount,
  1007. dwFlags
  1008. );
  1009. return AddPolicy(false, &QMPolicy);
  1010. }
  1011. else
  1012. {
  1013. return WBEM_E_INVALID_PARAMETER;
  1014. }
  1015. }
  1016. /*
  1017. Routine Description:
  1018. Name:
  1019. CQMPolicy::DeleteDefaultPolicies
  1020. Functionality:
  1021. Remove from SPD all the default quick mode policies.
  1022. Virtual:
  1023. No.
  1024. Arguments:
  1025. None.
  1026. Return Value:
  1027. Success:
  1028. WBEM_NO_ERROR.
  1029. Failure:
  1030. various errors translated by IPSecErrorToWbemError
  1031. Notes:
  1032. */
  1033. HRESULT
  1034. CQMPolicy::DeleteDefaultPolicies()
  1035. {
  1036. HRESULT hr = WBEM_NO_ERROR;
  1037. //
  1038. // if the policy is not found, that is certainly ok
  1039. //
  1040. DWORD dwStatus = ::DeleteQMPolicy(NULL, (LPWSTR)g_pszDefQMPolicyNegNone);
  1041. if (ERROR_SUCCESS != dwStatus && ERROR_IPSEC_QM_POLICY_NOT_FOUND != dwStatus)
  1042. {
  1043. hr = IPSecErrorToWbemError(dwStatus);
  1044. }
  1045. dwStatus = ::DeleteQMPolicy(NULL, (LPWSTR)g_pszDefQMPolicyNegRequest);
  1046. if (ERROR_SUCCESS != dwStatus && ERROR_IPSEC_QM_POLICY_NOT_FOUND != dwStatus)
  1047. {
  1048. hr = IPSecErrorToWbemError(dwStatus);
  1049. }
  1050. dwStatus = ::DeleteQMPolicy(NULL, (LPWSTR)g_pszDefQMPolicyNegRequire);
  1051. if (ERROR_SUCCESS != dwStatus && ERROR_IPSEC_QM_POLICY_NOT_FOUND != dwStatus)
  1052. {
  1053. hr = IPSecErrorToWbemError(dwStatus);
  1054. }
  1055. dwStatus = ::DeleteQMPolicy(NULL, (LPWSTR)g_pszDefQMPolicyNegMax);
  1056. if (ERROR_SUCCESS != dwStatus && ERROR_IPSEC_QM_POLICY_NOT_FOUND != dwStatus)
  1057. {
  1058. hr = IPSecErrorToWbemError(dwStatus);
  1059. }
  1060. return hr;
  1061. }
  1062. /*
  1063. Routine Description:
  1064. Name:
  1065. CQMPolicy::DoReturn
  1066. Functionality:
  1067. Will create the return result object and pass it back to WMI
  1068. Virtual:
  1069. No.
  1070. Arguments:
  1071. pNamespace - our namespace.
  1072. pszMethod - The name of the method.
  1073. dwCount - The count of values to be passed back
  1074. pszValueNames - The names of the values to be passed back. It is of size (dwCount)
  1075. varValues - Values to be passed back (in the same order as of pszValueNames). It is of size (dwCount)
  1076. pCtx - COM interface pointer by WMI and needed for various WMI APIs
  1077. pReturnObj - Receives the WBEM object that contains the return result value.
  1078. Return Value:
  1079. Success:
  1080. Various success codes indicating the result.
  1081. Failure:
  1082. Various errors may occur. We return various error code to indicate such errors.
  1083. Notes:
  1084. This is just for testing.
  1085. */
  1086. HRESULT
  1087. CQMPolicy::DoReturn (
  1088. IN IWbemServices * pNamespace,
  1089. IN LPCWSTR pszMethod,
  1090. IN DWORD dwCount,
  1091. IN LPCWSTR * pszValueNames,
  1092. IN VARIANT * varValues,
  1093. IN IWbemContext * pCtx,
  1094. IN IWbemObjectSink * pSink
  1095. )
  1096. {
  1097. CComPtr<IWbemClassObject> srpClass;
  1098. CComBSTR bstrClsName(pszNspQMPolicy);
  1099. HRESULT hr = pNamespace->GetObject(bstrClsName, 0, pCtx, &srpClass, NULL);
  1100. if (FAILED(hr))
  1101. {
  1102. return hr;
  1103. }
  1104. //
  1105. // creates an instance of the output argument class.
  1106. //
  1107. CComPtr<IWbemClassObject> srpOutClass;
  1108. hr = srpClass->GetMethod(pszMethod, 0, NULL, &srpOutClass);
  1109. if (FAILED(hr))
  1110. {
  1111. return hr;
  1112. }
  1113. CComPtr<IWbemClassObject> srpOutParam;
  1114. hr = srpOutClass->SpawnInstance(0, &srpOutParam);
  1115. if (SUCCEEDED(hr))
  1116. {
  1117. for (DWORD dwIndex = 0; SUCCEEDED(hr) && (dwIndex < dwCount); dwIndex++)
  1118. {
  1119. CComBSTR bstrRetValName(pszValueNames[dwIndex]);
  1120. //
  1121. // Put the return value as a property
  1122. //
  1123. hr = srpOutParam->Put(bstrRetValName , 0, &(varValues[dwIndex]), 0);
  1124. }
  1125. }
  1126. //
  1127. // Send the output object back to the client by the sink.
  1128. //
  1129. if (SUCCEEDED(hr))
  1130. {
  1131. hr = pSink->Indicate(1, &srpOutParam);
  1132. }
  1133. return hr;
  1134. }
  1135. //
  1136. // The following functions are used to create default QM policies
  1137. // We copied it from IPSec's test code located at \nt\net\rras\ras\rasman\rasman
  1138. //
  1139. #define L2TP_IPSEC_DEFAULT_BYTES 250000
  1140. #define L2TP_IPSEC_DEFAULT_TIME 3600
  1141. DWORD
  1142. BuildOffers(
  1143. EnumEncryption eEncryption,
  1144. PIPSEC_QM_OFFER pOffers,
  1145. PDWORD pdwNumOffers,
  1146. PDWORD pdwFlags
  1147. )
  1148. {
  1149. DWORD dwStatus = ERROR_SUCCESS;
  1150. switch (eEncryption) {
  1151. case RAS_L2TP_NO_ENCRYPTION:
  1152. *pdwFlags = 0;
  1153. dwStatus = BuildNoEncryption(
  1154. pOffers,
  1155. pdwNumOffers
  1156. );
  1157. break;
  1158. case RAS_L2TP_OPTIONAL_ENCRYPTION:
  1159. dwStatus = BuildOptEncryption(
  1160. pOffers,
  1161. pdwNumOffers
  1162. );
  1163. break;
  1164. case RAS_L2TP_REQUIRE_ENCRYPTION:
  1165. *pdwFlags = 0;
  1166. dwStatus = BuildRequireEncryption(
  1167. pOffers,
  1168. pdwNumOffers
  1169. );
  1170. break;
  1171. case RAS_L2TP_REQUIRE_MAX_ENCRYPTION:
  1172. *pdwFlags = 0;
  1173. dwStatus = BuildStrongEncryption(
  1174. pOffers,
  1175. pdwNumOffers
  1176. );
  1177. break;
  1178. default:
  1179. dwStatus = ERROR_BAD_ARGUMENTS;
  1180. }
  1181. return(dwStatus);
  1182. }
  1183. /*++
  1184. Negotiation Policy Name: L2TP server any encryption default
  1185. ISAKMP quick mode PFS: off (accepts if requested)
  1186. Bi-directional passthrough filter: no
  1187. Inbound passthrough filter,
  1188. normal outbound filter: no
  1189. Fall back to clear if no response: no
  1190. Secure Using Security Method List: yes
  1191. 1. ESP 3_DES MD5
  1192. 2. ESP 3_DES SHA
  1193. 3. AH SHA1 with ESP 3_DES with null HMAC
  1194. 4. AH MD5 with ESP 3_DES with null HMAC, no lifetimes proposed
  1195. 5. AH SHA1 with ESP 3_DES SHA1, no lifetimes
  1196. 6. AH MD5 with ESP 3_DES MD5, no lifetimes
  1197. 7. ESP DES MD5
  1198. 8. ESP DES SHA1, no lifetimes
  1199. 9. AH SHA1 with ESP DES null HMAC, no lifetimes proposed
  1200. 10. AH MD5 with ESP DES null HMAC, no lifetimes proposed
  1201. 11. AH SHA1 with ESP DES SHA1, no lifetimes
  1202. 12. AH MD5 with ESP DES MD5, no lifetimes
  1203. --*/
  1204. DWORD
  1205. BuildOptEncryption(
  1206. PIPSEC_QM_OFFER pOffers,
  1207. PDWORD pdwNumOffers
  1208. )
  1209. {
  1210. DWORD dwStatus = ERROR_SUCCESS;
  1211. PIPSEC_QM_OFFER pOffer = pOffers;
  1212. // 1. ESP 3_DES MD5, no lifetimes
  1213. BuildOffer(
  1214. pOffer, 1,
  1215. ENCRYPTION, IPSEC_DOI_ESP_3_DES, HMAC_AH_MD5,
  1216. 0, 0, 0,
  1217. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1218. );
  1219. pOffer++;
  1220. // 2. ESP 3_DES SHA, no lifetimes
  1221. BuildOffer(
  1222. pOffer, 1,
  1223. ENCRYPTION, IPSEC_DOI_ESP_3_DES, HMAC_AH_SHA1,
  1224. 0, 0, 0,
  1225. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1226. );
  1227. pOffer++;
  1228. // 3. AH SHA1 with ESP 3_DES with null HMAC, no lifetimes proposed
  1229. BuildOffer(
  1230. pOffer, 2,
  1231. AUTHENTICATION, IPSEC_DOI_AH_SHA1, 0,
  1232. ENCRYPTION, IPSEC_DOI_ESP_3_DES, 0,
  1233. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1234. );
  1235. pOffer++;
  1236. // 4. AH MD5 with ESP 3_DES with null HMAC, no lifetimes proposed
  1237. BuildOffer(
  1238. pOffer, 2,
  1239. AUTHENTICATION, IPSEC_DOI_AH_MD5, 0,
  1240. ENCRYPTION, IPSEC_DOI_ESP_3_DES, 0,
  1241. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1242. );
  1243. pOffer++;
  1244. // 5. AH SHA1 with ESP 3_DES SHA1, no lifetimes
  1245. BuildOffer(
  1246. pOffer, 2,
  1247. AUTHENTICATION, IPSEC_DOI_AH_SHA1, 0,
  1248. ENCRYPTION, IPSEC_DOI_ESP_3_DES, HMAC_AH_SHA1,
  1249. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1250. );
  1251. pOffer++;
  1252. // 6. AH MD5 with ESP 3_DES MD5, no lifetimes
  1253. BuildOffer(
  1254. pOffer, 2,
  1255. AUTHENTICATION, IPSEC_DOI_AH_MD5, 0,
  1256. ENCRYPTION, IPSEC_DOI_ESP_3_DES, HMAC_AH_MD5,
  1257. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1258. );
  1259. pOffer++;
  1260. // 7. ESP DES MD5, no lifetimes
  1261. BuildOffer(
  1262. pOffer, 1,
  1263. ENCRYPTION, IPSEC_DOI_ESP_DES, HMAC_AH_MD5,
  1264. 0, 0, 0,
  1265. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1266. );
  1267. pOffer++;
  1268. // 8. ESP DES SHA1, no lifetimes
  1269. BuildOffer(
  1270. pOffer, 1,
  1271. ENCRYPTION, IPSEC_DOI_ESP_DES, HMAC_AH_SHA1,
  1272. 0, 0, 0,
  1273. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1274. );
  1275. pOffer++;
  1276. // 9. AH SHA1 with ESP DES null HMAC, no lifetimes proposed
  1277. BuildOffer(
  1278. pOffer, 2,
  1279. AUTHENTICATION, IPSEC_DOI_AH_SHA1, 0,
  1280. ENCRYPTION, IPSEC_DOI_ESP_DES, 0,
  1281. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1282. );
  1283. pOffer++;
  1284. // 10. AH MD5 with ESP DES null HMAC, no lifetimes proposed
  1285. BuildOffer(
  1286. pOffer, 2,
  1287. AUTHENTICATION, IPSEC_DOI_AH_MD5, 0,
  1288. ENCRYPTION, IPSEC_DOI_ESP_DES, 0,
  1289. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1290. );
  1291. pOffer++;
  1292. // 11. AH SHA1 with ESP DES SHA1, no lifetimes
  1293. BuildOffer(
  1294. pOffer, 2,
  1295. AUTHENTICATION, IPSEC_DOI_AH_SHA1, 0,
  1296. ENCRYPTION, IPSEC_DOI_ESP_DES, HMAC_AH_SHA1,
  1297. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1298. );
  1299. pOffer++;
  1300. // 12. AH MD5 with ESP DES MD5, no lifetimes
  1301. BuildOffer(
  1302. pOffer, 2,
  1303. AUTHENTICATION, IPSEC_DOI_AH_MD5, 0,
  1304. ENCRYPTION, IPSEC_DOI_ESP_DES, HMAC_AH_MD5,
  1305. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1306. );
  1307. pOffer++;
  1308. // 13. ESP 3_DES MD5, no lifetimes
  1309. BuildOffer(
  1310. pOffer, 1,
  1311. ENCRYPTION, 0, HMAC_AH_SHA1,
  1312. 0, 0, 0,
  1313. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1314. );
  1315. pOffer++;
  1316. // 14. ESP 3_DES SHA, no lifetimes
  1317. BuildOffer(
  1318. pOffer, 1,
  1319. ENCRYPTION, 0, HMAC_AH_MD5,
  1320. 0, 0, 0,
  1321. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1322. );
  1323. pOffer++;
  1324. // 15. AH SHA
  1325. BuildOffer(
  1326. pOffer, 1,
  1327. AUTHENTICATION, IPSEC_DOI_AH_SHA1, 0,
  1328. 0, 0, 0,
  1329. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1330. );
  1331. pOffer++;
  1332. // 16. AH MD5
  1333. BuildOffer(
  1334. pOffer, 1,
  1335. AUTHENTICATION, IPSEC_DOI_AH_MD5, 0,
  1336. 0, 0, 0,
  1337. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1338. );
  1339. pOffer++;
  1340. *pdwNumOffers = 16;
  1341. return(dwStatus);
  1342. }
  1343. /*++
  1344. Negotiation Policy Name: L2TP server strong encryption default
  1345. ISAKMP quick mode PFS: off (accepts if requested)
  1346. Bi-directional passthrough filter: no
  1347. Inbound passthrough filter,
  1348. normal outbound filter: no
  1349. Fall back to clear if no response: no
  1350. Secure Using Security Method List: yes
  1351. 1. ESP 3_DES MD5, no lifetimes
  1352. 2. ESP 3_DES SHA, no lifetimes
  1353. 3. AH SHA1 with ESP 3_DES with null HMAC, no lifetimes proposed
  1354. 4. AH MD5 with ESP 3_DES with null HMAC, no lifetimes proposed
  1355. 5. AH SHA1 with ESP 3_DES SHA1, no lifetimes
  1356. 6. AH MD5 with ESP 3_DES MD5, no lifetimes
  1357. --*/
  1358. DWORD
  1359. BuildStrongEncryption(
  1360. PIPSEC_QM_OFFER pOffers,
  1361. PDWORD pdwNumOffers
  1362. )
  1363. {
  1364. DWORD dwStatus = ERROR_SUCCESS;
  1365. PIPSEC_QM_OFFER pOffer = pOffers;
  1366. // 1. ESP 3_DES MD5, no lifetimes
  1367. BuildOffer(
  1368. pOffer, 1,
  1369. ENCRYPTION, IPSEC_DOI_ESP_3_DES, HMAC_AH_MD5,
  1370. 0, 0, 0,
  1371. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1372. );
  1373. pOffer++;
  1374. // 2. ESP 3_DES SHA, no lifetimes;
  1375. BuildOffer(
  1376. pOffer, 1,
  1377. ENCRYPTION, IPSEC_DOI_ESP_3_DES, HMAC_AH_MD5,
  1378. 0, 0, 0,
  1379. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1380. );
  1381. pOffer++;
  1382. // 3. AH SHA1 with ESP 3_DES with null HMAC, no lifetimes proposed
  1383. BuildOffer(
  1384. pOffer, 2,
  1385. AUTHENTICATION, IPSEC_DOI_AH_SHA1, 0,
  1386. ENCRYPTION, IPSEC_DOI_ESP_3_DES, 0,
  1387. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1388. );
  1389. pOffer++;
  1390. // 4. AH MD5 with ESP 3_DES with null HMAC, no lifetimes proposed
  1391. BuildOffer(
  1392. pOffer, 2,
  1393. AUTHENTICATION, IPSEC_DOI_AH_MD5, 0,
  1394. ENCRYPTION, IPSEC_DOI_ESP_3_DES, 0,
  1395. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1396. );
  1397. pOffer++;
  1398. // 5. AH SHA1 with ESP 3_DES SHA1, no lifetimes
  1399. BuildOffer(
  1400. pOffer, 2,
  1401. AUTHENTICATION, IPSEC_DOI_AH_SHA1, 0,
  1402. ENCRYPTION, IPSEC_DOI_ESP_3_DES, HMAC_AH_SHA1,
  1403. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1404. );
  1405. pOffer++;
  1406. // 6. AH MD5 with ESP 3_DES MD5, no lifetimes
  1407. BuildOffer(
  1408. pOffer, 2,
  1409. AUTHENTICATION, IPSEC_DOI_AH_MD5, 0,
  1410. ENCRYPTION, IPSEC_DOI_ESP_3_DES, HMAC_AH_MD5,
  1411. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1412. );
  1413. *pdwNumOffers = 6;
  1414. return(dwStatus);
  1415. }
  1416. void
  1417. BuildOffer(
  1418. PIPSEC_QM_OFFER pOffer,
  1419. DWORD dwNumAlgos,
  1420. DWORD dwFirstOperation,
  1421. DWORD dwFirstAlgoIdentifier,
  1422. DWORD dwFirstAlgoSecIdentifier,
  1423. DWORD dwSecondOperation,
  1424. DWORD dwSecondAlgoIdentifier,
  1425. DWORD dwSecondAlgoSecIdentifier,
  1426. DWORD dwKeyExpirationBytes,
  1427. DWORD dwKeyExpirationTime
  1428. )
  1429. {
  1430. memset(pOffer, 0, sizeof(IPSEC_QM_OFFER));
  1431. pOffer->Lifetime.uKeyExpirationKBytes = dwKeyExpirationBytes;
  1432. pOffer->Lifetime.uKeyExpirationTime = dwKeyExpirationTime;
  1433. pOffer->dwFlags = 0; // No flags.
  1434. pOffer->bPFSRequired = FALSE; // Phase 2 PFS not required.
  1435. pOffer->dwPFSGroup = PFS_GROUP_NONE;
  1436. pOffer->dwNumAlgos = dwNumAlgos;
  1437. if (dwNumAlgos >= 1) {
  1438. pOffer->Algos[0].Operation = (IPSEC_OPERATION)dwFirstOperation;
  1439. pOffer->Algos[0].uAlgoIdentifier = dwFirstAlgoIdentifier;
  1440. pOffer->Algos[0].uAlgoKeyLen = 64;
  1441. pOffer->Algos[0].uAlgoRounds = 8;
  1442. pOffer->Algos[0].uSecAlgoIdentifier = (HMAC_AH_ALGO)dwFirstAlgoSecIdentifier;
  1443. pOffer->Algos[0].MySpi = 0;
  1444. pOffer->Algos[0].PeerSpi = 0;
  1445. }
  1446. if (dwNumAlgos == 2) {
  1447. pOffer->Algos[1].Operation = (IPSEC_OPERATION)dwSecondOperation;
  1448. pOffer->Algos[1].uAlgoIdentifier = dwSecondAlgoIdentifier;
  1449. pOffer->Algos[1].uAlgoKeyLen = 64;
  1450. pOffer->Algos[1].uAlgoRounds = 8;
  1451. pOffer->Algos[1].uSecAlgoIdentifier = (HMAC_AH_ALGO)dwSecondAlgoSecIdentifier;
  1452. pOffer->Algos[1].MySpi = 0;
  1453. pOffer->Algos[1].PeerSpi = 0;
  1454. }
  1455. }
  1456. /*++
  1457. Negotiation Policy Name: L2TP server any encryption default
  1458. ISAKMP quick mode PFS: off (accepts if requested)
  1459. Bi-directional passthrough filter: no
  1460. Inbound passthrough filter,
  1461. normal outbound filter: no
  1462. Fall back to clear if no response: no
  1463. Secure Using Security Method List: yes
  1464. 1. AH SHA1
  1465. 2. AH MD5
  1466. --*/
  1467. DWORD
  1468. BuildNoEncryption(
  1469. PIPSEC_QM_OFFER pOffers,
  1470. PDWORD pdwNumOffers
  1471. )
  1472. {
  1473. DWORD dwStatus = ERROR_SUCCESS;
  1474. PIPSEC_QM_OFFER pOffer = pOffers;
  1475. // 1. ESP 3_DES MD5, no lifetimes
  1476. BuildOffer(
  1477. pOffer, 1,
  1478. ENCRYPTION, 0, HMAC_AH_SHA1,
  1479. 0, 0, 0,
  1480. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1481. );
  1482. pOffer++;
  1483. // 2. ESP 3_DES SHA, no lifetimes
  1484. BuildOffer(
  1485. pOffer, 1,
  1486. ENCRYPTION, 0, HMAC_AH_MD5,
  1487. 0, 0, 0,
  1488. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1489. );
  1490. pOffer++;
  1491. // 3. AH SHA
  1492. BuildOffer(
  1493. pOffer, 1,
  1494. AUTHENTICATION, IPSEC_DOI_AH_SHA1, 0,
  1495. 0, 0, 0,
  1496. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1497. );
  1498. pOffer++;
  1499. // 4. AH MD5
  1500. BuildOffer(
  1501. pOffer, 1,
  1502. AUTHENTICATION, IPSEC_DOI_AH_MD5, 0,
  1503. 0, 0, 0,
  1504. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1505. );
  1506. pOffer++;
  1507. *pdwNumOffers = 4;
  1508. return(dwStatus);
  1509. }
  1510. /*++
  1511. Negotiation Policy Name: L2TP server any encryption default
  1512. ISAKMP quick mode PFS: off (accepts if requested)
  1513. Bi-directional passthrough filter: no
  1514. Inbound passthrough filter,
  1515. normal outbound filter: no
  1516. Fall back to clear if no response: no
  1517. Secure Using Security Method List: yes
  1518. 1. ESP 3_DES MD5
  1519. 2. ESP 3_DES SHA
  1520. 3. AH SHA1 with ESP 3_DES with null HMAC
  1521. 4. AH MD5 with ESP 3_DES with null HMAC, no lifetimes proposed
  1522. 5. AH SHA1 with ESP 3_DES SHA1, no lifetimes
  1523. 6. AH MD5 with ESP 3_DES MD5, no lifetimes
  1524. 7. ESP DES MD5
  1525. 8. ESP DES SHA1, no lifetimes
  1526. 9. AH SHA1 with ESP DES null HMAC, no lifetimes proposed
  1527. 10. AH MD5 with ESP DES null HMAC, no lifetimes proposed
  1528. 11. AH SHA1 with ESP DES SHA1, no lifetimes
  1529. 12. AH MD5 with ESP DES MD5, no lifetimes
  1530. --*/
  1531. DWORD
  1532. BuildRequireEncryption(
  1533. PIPSEC_QM_OFFER pOffers,
  1534. PDWORD pdwNumOffers
  1535. )
  1536. {
  1537. DWORD dwStatus = ERROR_SUCCESS;
  1538. PIPSEC_QM_OFFER pOffer = pOffers;
  1539. // 1. ESP 3_DES MD5, no lifetimes
  1540. BuildOffer(
  1541. pOffer, 1,
  1542. ENCRYPTION, IPSEC_DOI_ESP_3_DES, HMAC_AH_MD5,
  1543. 0, 0, 0,
  1544. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1545. );
  1546. pOffer++;
  1547. // 2. ESP 3_DES SHA, no lifetimes
  1548. BuildOffer(
  1549. pOffer, 1,
  1550. ENCRYPTION, IPSEC_DOI_ESP_3_DES, HMAC_AH_SHA1,
  1551. 0, 0, 0,
  1552. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1553. );
  1554. pOffer++;
  1555. // 3. AH SHA1 with ESP 3_DES with null HMAC, no lifetimes proposed
  1556. BuildOffer(
  1557. pOffer, 2,
  1558. AUTHENTICATION, IPSEC_DOI_AH_SHA1, 0,
  1559. ENCRYPTION, IPSEC_DOI_ESP_3_DES, 0,
  1560. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1561. );
  1562. pOffer++;
  1563. // 4. AH MD5 with ESP 3_DES with null HMAC, no lifetimes proposed
  1564. BuildOffer(
  1565. pOffer, 2,
  1566. AUTHENTICATION, IPSEC_DOI_AH_MD5, 0,
  1567. ENCRYPTION, IPSEC_DOI_ESP_3_DES, 0,
  1568. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1569. );
  1570. pOffer++;
  1571. // 5. AH SHA1 with ESP 3_DES SHA1, no lifetimes
  1572. BuildOffer(
  1573. pOffer, 2,
  1574. AUTHENTICATION, IPSEC_DOI_AH_SHA1, 0,
  1575. ENCRYPTION, IPSEC_DOI_ESP_3_DES, HMAC_AH_SHA1,
  1576. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1577. );
  1578. pOffer++;
  1579. // 6. AH MD5 with ESP 3_DES MD5, no lifetimes
  1580. BuildOffer(
  1581. pOffer, 2,
  1582. AUTHENTICATION, IPSEC_DOI_AH_MD5, 0,
  1583. ENCRYPTION, IPSEC_DOI_ESP_3_DES, HMAC_AH_MD5,
  1584. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1585. );
  1586. pOffer++;
  1587. // 7. ESP DES MD5, no lifetimes
  1588. BuildOffer(
  1589. pOffer, 1,
  1590. ENCRYPTION, IPSEC_DOI_ESP_DES, HMAC_AH_MD5,
  1591. 0, 0, 0,
  1592. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1593. );
  1594. pOffer++;
  1595. // 8. ESP DES SHA1, no lifetimes
  1596. BuildOffer(
  1597. pOffer, 1,
  1598. ENCRYPTION, IPSEC_DOI_ESP_DES, HMAC_AH_SHA1,
  1599. 0, 0, 0,
  1600. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1601. );
  1602. pOffer++;
  1603. // 9. AH SHA1 with ESP DES null HMAC, no lifetimes proposed
  1604. BuildOffer(
  1605. pOffer, 2,
  1606. AUTHENTICATION, IPSEC_DOI_AH_SHA1, 0,
  1607. ENCRYPTION, IPSEC_DOI_ESP_DES, 0,
  1608. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1609. );
  1610. pOffer++;
  1611. // 10. AH MD5 with ESP DES null HMAC, no lifetimes proposed
  1612. BuildOffer(
  1613. pOffer, 2,
  1614. AUTHENTICATION, IPSEC_DOI_AH_MD5, 0,
  1615. ENCRYPTION, IPSEC_DOI_ESP_DES, 0,
  1616. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1617. );
  1618. pOffer++;
  1619. // 11. AH SHA1 with ESP DES SHA1, no lifetimes
  1620. BuildOffer(
  1621. pOffer, 2,
  1622. AUTHENTICATION, IPSEC_DOI_AH_SHA1, 0,
  1623. ENCRYPTION, IPSEC_DOI_ESP_DES, HMAC_AH_SHA1,
  1624. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1625. );
  1626. pOffer++;
  1627. // 12. AH MD5 with ESP DES MD5, no lifetimes
  1628. BuildOffer(
  1629. pOffer, 2,
  1630. AUTHENTICATION, IPSEC_DOI_AH_MD5, 0,
  1631. ENCRYPTION, IPSEC_DOI_ESP_DES, HMAC_AH_MD5,
  1632. L2TP_IPSEC_DEFAULT_BYTES, L2TP_IPSEC_DEFAULT_TIME
  1633. );
  1634. pOffer++;
  1635. *pdwNumOffers = 12;
  1636. return(dwStatus);
  1637. }
  1638. VOID
  1639. BuildQMPolicy(
  1640. PIPSEC_QM_POLICY pQMPolicy,
  1641. EnumEncryption eEncryption,
  1642. PIPSEC_QM_OFFER pOffers,
  1643. DWORD dwNumOffers,
  1644. DWORD dwFlags
  1645. )
  1646. {
  1647. switch (eEncryption)
  1648. {
  1649. case RAS_L2TP_NO_ENCRYPTION:
  1650. pQMPolicy->pszPolicyName = (LPWSTR)g_pszDefQMPolicyNegNone;
  1651. pQMPolicy->gPolicyID = guidDefQMPolicy_Neg_None;
  1652. break;
  1653. case RAS_L2TP_OPTIONAL_ENCRYPTION:
  1654. pQMPolicy->pszPolicyName = (LPWSTR)g_pszDefQMPolicyNegRequest;
  1655. pQMPolicy->gPolicyID = guidDefQMPolicy_Neg_Request;
  1656. break;
  1657. case RAS_L2TP_REQUIRE_ENCRYPTION:
  1658. pQMPolicy->pszPolicyName = (LPWSTR)g_pszDefQMPolicyNegRequire;
  1659. pQMPolicy->gPolicyID = guidDefQMPolicy_Neg_Require;
  1660. break;
  1661. case RAS_L2TP_REQUIRE_MAX_ENCRYPTION:
  1662. pQMPolicy->pszPolicyName = (LPWSTR)g_pszDefQMPolicyNegMax;
  1663. pQMPolicy->gPolicyID = guidDefQMPolicy_Neg_MAX;
  1664. break;
  1665. }
  1666. pQMPolicy->dwFlags = dwFlags;
  1667. pQMPolicy->pOffers = pOffers;
  1668. pQMPolicy->dwOfferCount = dwNumOffers;
  1669. }