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.

1481 lines
46 KiB

  1. //#--------------------------------------------------------------
  2. //
  3. // File: recvfrompipe.cpp
  4. //
  5. // Synopsis: Implementation of CRecvFromPip class methods
  6. //
  7. // Copyright (C) Microsoft Corporation All rights reserved.
  8. //
  9. //----------------------------------------------------------------
  10. #include "radcommon.h"
  11. #include "preprocessor.h"
  12. #include "recvfrompipe.h"
  13. #include "logresult.h"
  14. #include <new>
  15. #include <iastlutl.h>
  16. const CHAR NUL = '\0';
  17. extern LONG g_lPacketCount;
  18. //++--------------------------------------------------------------
  19. //
  20. // Function: CRecvFromPipe
  21. //
  22. // Synopsis: This is the constructor of the CRecvFromPipe
  23. // class
  24. //
  25. // Arguments: none
  26. //
  27. // Returns: none
  28. //
  29. //
  30. // History: MKarki Created 10/22/97
  31. //
  32. //----------------------------------------------------------------
  33. CRecvFromPipe::CRecvFromPipe(
  34. CPreProcessor *pCPreProcessor,
  35. CHashMD5 *pCHashMD5,
  36. CHashHmacMD5 *pCHashHmacMD5,
  37. CClients *pCClients,
  38. VSAFilter *pCVSAFilter,
  39. CTunnelPassword *pCTunnelPassword,
  40. CReportEvent *pCReportEvent
  41. )
  42. :m_pCPreProcessor (pCPreProcessor),
  43. m_pCHashMD5 (pCHashMD5),
  44. m_pCHashHmacMD5 (pCHashHmacMD5),
  45. m_pCClients (pCClients),
  46. m_pCVSAFilter (pCVSAFilter),
  47. m_pCTunnelPassword (pCTunnelPassword),
  48. m_pCReportEvent (pCReportEvent)
  49. {
  50. _ASSERT (
  51. (NULL != pCPreProcessor) &&
  52. (NULL != pCHashMD5) &&
  53. (NULL != pCHashHmacMD5) &&
  54. (NULL != pCClients) &&
  55. (NULL != pCVSAFilter) &&
  56. (NULL != pCTunnelPassword) &&
  57. (NULL != pCReportEvent)
  58. );
  59. } // end of CRecvFromPipe constructor
  60. //++--------------------------------------------------------------
  61. //
  62. // Function: ~CRecvFromPipe
  63. //
  64. // Synopsis: This is the destructor of the CRecvFromPipe
  65. // class
  66. //
  67. // Arguments: none
  68. //
  69. // Returns: none
  70. //
  71. //
  72. // History: MKarki Created 10/22/97
  73. //
  74. //----------------------------------------------------------------
  75. CRecvFromPipe::~CRecvFromPipe()
  76. {
  77. } // end of CRecvFromPipe destructor
  78. //++--------------------------------------------------------------
  79. //
  80. // Function: Process
  81. //
  82. // Synopsis: This is the CRecvFromPipe class public method
  83. // to start processing the packet on its way out
  84. //
  85. // Arguments:
  86. // [in] CPacketRadius*
  87. //
  88. // Returns: HRESULT
  89. //
  90. //
  91. // History: MKarki Created 10/22/97
  92. //
  93. // Called By:
  94. // 1) CController::CRequestSource::OnRequest Method
  95. //
  96. //----------------------------------------------------------------
  97. HRESULT
  98. CRecvFromPipe::Process (
  99. IRequest *pIRequest
  100. )
  101. {
  102. BOOL bStatus = FALSE;
  103. HRESULT hr = S_OK;
  104. DWORD dwCode = 0;
  105. DWORD dwCount = 0;
  106. DWORD dwAttribCount = 0;
  107. IAttributesRaw *pIAttributesRaw = NULL;
  108. IRequestState *pIRequestState = NULL;
  109. CPacketRadius *pCPacketRadius = NULL;
  110. LONG iasResponse, iasReason = 0;
  111. PACKETTYPE ePacketType;
  112. PATTRIBUTEPOSITION pAttribPosition = NULL;
  113. unsigned hyper uhyPacketAddress = 0;
  114. RADIUSLOGTYPE RadiusError = RADIUS_DROPPED_PACKET;
  115. _ASSERT (pIRequest);
  116. __try
  117. {
  118. // We have to retrieve the CPacketRadius object first, so we can clean
  119. // it up even in the error cases.
  120. hr = pIRequest->QueryInterface (
  121. __uuidof(IRequestState),
  122. reinterpret_cast <PVOID*> (&pIRequestState)
  123. );
  124. if (FAILED (hr))
  125. {
  126. IASTracePrintf (
  127. "Unable to obtain request state in request received from "
  128. "backend"
  129. );
  130. __leave;
  131. }
  132. //
  133. // get the CPacketRadius class object
  134. //
  135. hr = pIRequestState->Pop (
  136. reinterpret_cast <unsigned hyper*> (&uhyPacketAddress)
  137. );
  138. if (FAILED (hr))
  139. {
  140. IASTracePrintf (
  141. "Unable to obtain information from request state received "
  142. "from backend"
  143. );
  144. __leave;
  145. }
  146. pCPacketRadius = reinterpret_cast <CPacketRadius*> (uhyPacketAddress);
  147. //
  148. // if this Request object has been generated by the backend then we
  149. // don't have a CPacketRadius class object
  150. //
  151. if (NULL == pCPacketRadius)
  152. {
  153. //
  154. // we most probably are sending out an EAP-Challenge
  155. //
  156. hr= GeneratePacketRadius (
  157. &pCPacketRadius,
  158. pIAttributesRaw
  159. );
  160. if (FAILED (hr)) { __leave; }
  161. }
  162. //
  163. // get the IAttributesRaw interface now
  164. //
  165. hr = pIRequest->QueryInterface (
  166. __uuidof(IAttributesRaw),
  167. reinterpret_cast <PVOID*> (&pIAttributesRaw)
  168. );
  169. if (FAILED (hr))
  170. {
  171. IASTracePrintf (
  172. "Unable to obtain Attributes interface in request "
  173. "received from backend"
  174. );
  175. __leave;
  176. }
  177. //
  178. // split the attributes which can not fit in a radius packet
  179. //
  180. hr = SplitAttributes (pIAttributesRaw);
  181. if (FAILED (hr))
  182. {
  183. IASTracePrintf (
  184. "Unable to split IAS attribute received from backend"
  185. );
  186. __leave;
  187. }
  188. //
  189. // convert the IAS VSA attributes to RADIUS format
  190. //
  191. hr = m_pCVSAFilter->radiusFromIAS (pIAttributesRaw);
  192. if (FAILED (hr))
  193. {
  194. IASTracePrintf (
  195. "Unable to convert IAS attribute to Radius VSAs in request "
  196. "received from backend"
  197. );
  198. __leave;
  199. }
  200. //
  201. // get the outbound packet code
  202. //
  203. hr = pIRequest->get_Response (&iasResponse);
  204. if (FAILED (hr))
  205. {
  206. IASTracePrintf (
  207. "Unable to obtain response code in request recieved from "
  208. "backend"
  209. );
  210. __leave;
  211. }
  212. //
  213. // get the outbound reason code
  214. //
  215. hr = pIRequest->get_Reason (&iasReason);
  216. if (FAILED (hr))
  217. {
  218. IASTracePrintf (
  219. "Unable to obtain reason code in request recieved from "
  220. "backend"
  221. );
  222. __leave;
  223. }
  224. // Log the result of the request.
  225. IASRadiusLogResult(pIRequest, pIAttributesRaw);
  226. // If it failed convert the reason code.
  227. if (iasReason != S_OK)
  228. {
  229. ConvertReasonToRadiusError (iasReason, &RadiusError);
  230. }
  231. //
  232. // convert the IASRESPONSE type to RADIUS type
  233. //
  234. hr = ConvertResponseToRadiusCode (
  235. iasResponse,
  236. &ePacketType,
  237. pCPacketRadius
  238. );
  239. if (FAILED (hr)) { __leave; }
  240. //
  241. // check if we have Tunnel-Password attribute, if yes
  242. // then encrypt it
  243. //
  244. hr = m_pCTunnelPassword->Process (
  245. ePacketType,
  246. pIAttributesRaw,
  247. pCPacketRadius
  248. );
  249. if (FAILED (hr)) { __leave; }
  250. //
  251. // inject Signature Attribute if needed
  252. //
  253. hr = InjectSignatureIfNeeded (
  254. ePacketType,
  255. pIAttributesRaw,
  256. pCPacketRadius
  257. );
  258. if (FAILED (hr)) { __leave; }
  259. //
  260. // get the count of number of request
  261. //
  262. hr = pIAttributesRaw->GetAttributeCount (&dwAttribCount);
  263. if (FAILED (hr))
  264. {
  265. IASTracePrintf (
  266. "Unable to obtain attribute count in request received from "
  267. "backend"
  268. );
  269. __leave;
  270. }
  271. //
  272. // allocate the attribposition structures
  273. //
  274. pAttribPosition = reinterpret_cast <PATTRIBUTEPOSITION> (
  275. CoTaskMemAlloc (
  276. sizeof (ATTRIBUTEPOSITION)*dwAttribCount
  277. ));
  278. if (NULL == pAttribPosition)
  279. {
  280. IASTracePrintf (
  281. "Unable to allocate memory for attribute postion array "
  282. "while processing request recieved from backend"
  283. );
  284. hr = E_OUTOFMEMORY;
  285. __leave;
  286. }
  287. //
  288. // get the attributes from the collection
  289. //
  290. hr = pIAttributesRaw->GetAttributes (
  291. &dwAttribCount,
  292. pAttribPosition,
  293. 0,
  294. NULL
  295. );
  296. if (FAILED (hr))
  297. {
  298. IASTracePrintf (
  299. "Unable to get attribute in request received from backend"
  300. );
  301. __leave;
  302. }
  303. //
  304. // remove the attributes from the collection now
  305. //
  306. hr = pIAttributesRaw->RemoveAttributes (
  307. dwAttribCount,
  308. pAttribPosition
  309. );
  310. if (FAILED (hr))
  311. {
  312. IASTracePrintf (
  313. "Unable to remove attribute in request received from backend"
  314. );
  315. __leave;
  316. }
  317. //
  318. // carry out the generic packet building here
  319. //
  320. hr = pCPacketRadius->BuildOutPacket (
  321. ePacketType,
  322. pAttribPosition,
  323. dwAttribCount
  324. );
  325. if (FAILED (hr)) { __leave; }
  326. //
  327. // sending out packet now
  328. //
  329. hr = m_pCPreProcessor->StartOutProcessing (pCPacketRadius);
  330. if (FAILED (hr)) { __leave; }
  331. }
  332. __finally
  333. {
  334. //
  335. // log event in case of both success and failure
  336. //
  337. if (SUCCEEDED (hr))
  338. {
  339. //
  340. // log an event that inbound packet has been processed
  341. // successfully
  342. //
  343. m_pCReportEvent->Process (
  344. RADIUS_LOG_PACKET,
  345. pCPacketRadius->GetInCode (),
  346. pCPacketRadius->GetInLength (),
  347. pCPacketRadius->GetInAddress (),
  348. NULL,
  349. static_cast <LPVOID> (pCPacketRadius->GetInPacket())
  350. );
  351. //
  352. // log an event for the outbound packet successfully send
  353. // out
  354. //
  355. m_pCReportEvent->Process (
  356. RADIUS_LOG_PACKET,
  357. pCPacketRadius->GetOutCode (),
  358. pCPacketRadius->GetOutLength (),
  359. pCPacketRadius->GetOutAddress (),
  360. NULL,
  361. static_cast <LPVOID> (pCPacketRadius->GetOutPacket())
  362. );
  363. }
  364. else
  365. {
  366. if (hr != RADIUS_E_ERRORS_OCCURRED)
  367. {
  368. IASReportEvent(
  369. RADIUS_E_INTERNAL_ERROR,
  370. 0,
  371. sizeof(hr),
  372. NULL,
  373. &hr
  374. );
  375. }
  376. else if (pCPacketRadius != 0)
  377. {
  378. //
  379. // generate event that inbound packet has been dropped
  380. //
  381. m_pCReportEvent->Process (
  382. RadiusError,
  383. pCPacketRadius->GetInCode (),
  384. pCPacketRadius->GetInLength (),
  385. pCPacketRadius->GetInAddress (),
  386. NULL,
  387. static_cast <LPVOID> (pCPacketRadius->GetInPacket())
  388. );
  389. }
  390. else
  391. {
  392. IASReportEvent(
  393. RADIUS_E_INTERNAL_ERROR,
  394. 0,
  395. sizeof(hr),
  396. NULL,
  397. &hr
  398. );
  399. }
  400. }
  401. //
  402. // now delete the dynamically allocated memory
  403. //
  404. if (NULL != pAttribPosition)
  405. {
  406. //
  407. // release the attributes first
  408. //
  409. for (dwCount = 0; dwCount < dwAttribCount; dwCount++)
  410. {
  411. ::IASAttributeRelease (pAttribPosition[dwCount].pAttribute);
  412. }
  413. CoTaskMemFree (pAttribPosition);
  414. }
  415. if (pIRequestState) { pIRequestState->Release (); }
  416. if (pIAttributesRaw) { pIAttributesRaw->Release (); }
  417. //
  418. // delete the packet
  419. //
  420. if (pCPacketRadius) { delete pCPacketRadius; }
  421. //
  422. // now decrement the global packet reference count
  423. //
  424. InterlockedDecrement (&g_lPacketCount);
  425. }
  426. return (hr);
  427. } // end of CRecvFromPipe::Process method
  428. //++--------------------------------------------------------------
  429. //
  430. // Function: ConvertResponseToRadiusCode
  431. //
  432. // Synopsis: This is the CRecvFromPipe class private method
  433. // that converts the IASRESPONSE code to RADIUS
  434. // packet type
  435. //
  436. // Arguments:
  437. // [in] IASRESPONSE
  438. // [out] PPACKETTYPE
  439. //
  440. // Returns: HRESULT - status
  441. //
  442. // History: MKarki Created 12/12/97
  443. //
  444. // Called By: CRecvFromPipe::Process method
  445. //
  446. //----------------------------------------------------------------
  447. HRESULT
  448. CRecvFromPipe::ConvertResponseToRadiusCode (
  449. LONG iasResponse,
  450. PPACKETTYPE pPacketType,
  451. CPacketRadius *pCPacketRadius
  452. )
  453. {
  454. HRESULT hr = S_OK;
  455. _ASSERT (pPacketType && pCPacketRadius);
  456. switch (iasResponse)
  457. {
  458. case IAS_RESPONSE_ACCESS_ACCEPT:
  459. *pPacketType = ACCESS_ACCEPT;
  460. break;
  461. case IAS_RESPONSE_ACCESS_REJECT:
  462. *pPacketType = ACCESS_REJECT;
  463. break;
  464. case IAS_RESPONSE_ACCESS_CHALLENGE:
  465. *pPacketType = ACCESS_CHALLENGE;
  466. break;
  467. case IAS_RESPONSE_ACCOUNTING:
  468. *pPacketType = ACCOUNTING_RESPONSE;
  469. break;
  470. case IAS_RESPONSE_FORWARD_PACKET:
  471. //
  472. // if we are forwarding this packet
  473. // the the packet type remains the same
  474. //
  475. *pPacketType = pCPacketRadius->GetInCode ();
  476. break;
  477. case IAS_RESPONSE_DISCARD_PACKET:
  478. hr = RADIUS_E_ERRORS_OCCURRED;
  479. break;
  480. case IAS_RESPONSE_INVALID:
  481. default:
  482. hr = E_FAIL;
  483. break;
  484. }
  485. return (hr);
  486. } // end of CRecvFromPipe::ConvertResponseToRadiusCode method
  487. //++--------------------------------------------------------------
  488. //
  489. // Function: GetOutPacketInfo
  490. //
  491. // Synopsis: This is the CRecvFromPipe class private method
  492. // that is used to used to get out bound packet
  493. // information from the IAS attribute collection
  494. //
  495. // Arguments:
  496. // [out] PDWORD - IP address
  497. // [out] PWORD - UDP port
  498. // [out] Client** - reference to CClient object
  499. // [out] PBYTE - packet header
  500. // [in] IAttributesRaw*
  501. //
  502. // Returns: BOOL status
  503. //
  504. // History: MKarki Created 1/9/97
  505. //
  506. // Called By: CRecvFromPipe::Process method
  507. //
  508. //----------------------------------------------------------------
  509. HRESULT
  510. CRecvFromPipe::GetOutPacketInfo (
  511. PDWORD pdwIPAddress,
  512. PWORD pwPort,
  513. IIasClient **ppIIasClient,
  514. PBYTE pPacketHeader,
  515. IAttributesRaw *pIAttributesRaw
  516. )
  517. {
  518. BOOL bStatus = TRUE;
  519. HRESULT hr = S_OK;
  520. DWORD dwCount = 0;
  521. PIASATTRIBUTE pIasAttribute = NULL;
  522. DWORD dwAttribPosCount = COMPONENT_SPECIFIC_ATTRIBUTE_COUNT;
  523. DWORD dwAttribIDCount = COMPONENT_SPECIFIC_ATTRIBUTE_COUNT;
  524. ATTRIBUTEPOSITION AttribPos[COMPONENT_SPECIFIC_ATTRIBUTE_COUNT];
  525. static DWORD AttribIDs [] =
  526. {
  527. IAS_ATTRIBUTE_CLIENT_IP_ADDRESS,
  528. IAS_ATTRIBUTE_CLIENT_UDP_PORT,
  529. IAS_ATTRIBUTE_CLIENT_PACKET_HEADER
  530. };
  531. _ASSERT (
  532. (NULL != pdwIPAddress) &&
  533. (NULL != pwPort) &&
  534. (NULL != pPacketHeader) &&
  535. (NULL != ppIIasClient) &&
  536. (NULL != pIAttributesRaw)
  537. );
  538. __try
  539. {
  540. //
  541. // get client info
  542. //
  543. // get the attributes from the collection
  544. //
  545. hr = pIAttributesRaw->GetAttributes (
  546. &dwAttribPosCount,
  547. AttribPos,
  548. dwAttribIDCount,
  549. reinterpret_cast <LPDWORD> (AttribIDs)
  550. );
  551. if (FAILED (hr))
  552. {
  553. IASTracePrintf (
  554. "Unable to get attributes while obtaining out-bound packet "
  555. "information"
  556. );
  557. __leave;
  558. }
  559. else if (COMPONENT_SPECIFIC_ATTRIBUTE_COUNT != dwAttribPosCount)
  560. {
  561. IASTracePrintf (
  562. "Request received from backend does not have all the "
  563. "all the required attributes"
  564. );
  565. hr = E_FAIL;
  566. __leave;
  567. }
  568. //
  569. // go through the attributes and get values out
  570. //
  571. for (dwCount = 0; dwCount < dwAttribPosCount; dwCount++)
  572. {
  573. pIasAttribute = AttribPos[dwCount].pAttribute;
  574. switch (pIasAttribute->dwId)
  575. {
  576. case IAS_ATTRIBUTE_CLIENT_IP_ADDRESS:
  577. _ASSERT (IASTYPE_INET_ADDR == pIasAttribute->Value.itType),
  578. *pdwIPAddress = pIasAttribute->Value.InetAddr;
  579. break;
  580. case IAS_ATTRIBUTE_CLIENT_UDP_PORT:
  581. _ASSERT (IASTYPE_INTEGER == pIasAttribute->Value.itType);
  582. *pwPort = pIasAttribute->Value.Integer;
  583. break;
  584. case IAS_ATTRIBUTE_CLIENT_PACKET_HEADER:
  585. _ASSERT (
  586. (IASTYPE_OCTET_STRING == pIasAttribute->Value.itType) &&
  587. (PACKET_HEADER_SIZE == pIasAttribute->Value.OctetString.dwLength)
  588. );
  589. //
  590. // copy the value into the buffer provided
  591. //
  592. CopyMemory (
  593. pPacketHeader,
  594. pIasAttribute->Value.OctetString.lpValue,
  595. PACKET_HEADER_SIZE
  596. );
  597. break;
  598. default:
  599. _ASSERT (0);
  600. IASTracePrintf (
  601. "Attribute:%d, not requested, is present "
  602. "in request received from backend",
  603. pIasAttribute->dwId
  604. );
  605. hr = E_FAIL;
  606. __leave;
  607. break;
  608. }
  609. } // end of for loop
  610. //
  611. // get client information for this RADIUS packet
  612. //
  613. bStatus = m_pCClients->FindObject (
  614. *pdwIPAddress,
  615. ppIIasClient
  616. );
  617. if (FALSE == bStatus)
  618. {
  619. in_addr sin;
  620. sin.s_addr = *pdwIPAddress;
  621. IASTracePrintf (
  622. "Unable to get information for client:%s "
  623. "while processing request received from backend",
  624. inet_ntoa (sin)
  625. );
  626. hr = E_FAIL;
  627. __leave;
  628. }
  629. }
  630. __finally
  631. {
  632. if (SUCCEEDED (hr))
  633. {
  634. for (dwCount = 0; dwCount < dwAttribPosCount; dwCount++)
  635. {
  636. //
  637. // now release the reference to the attributes
  638. //
  639. ::IASAttributeRelease (AttribPos[dwCount].pAttribute);
  640. }
  641. }
  642. }
  643. return (hr);
  644. } // end of CPacketRadius::GetOutPacketInfo method
  645. //++--------------------------------------------------------------
  646. //
  647. // Function: GeneratePacketRadius
  648. //
  649. // Synopsis: This is the CRecvFromPipe class private method
  650. // that is used generate a new CPacketRadius
  651. // class object and initialize it
  652. //
  653. // Arguments:
  654. // [out] CPacketRadius**
  655. // [in] IAttributesRaw*
  656. //
  657. // Returns: HRESULT - status
  658. //
  659. // History: MKarki Created 2/6/98
  660. //
  661. // Called By: CRecvFromPipe::Process method
  662. //
  663. //----------------------------------------------------------------
  664. HRESULT
  665. CRecvFromPipe:: GeneratePacketRadius (
  666. CPacketRadius **ppCPacketRadius,
  667. IAttributesRaw *pIAttributesRaw
  668. )
  669. {
  670. PBYTE pPacketHeader = NULL;
  671. DWORD dwAddress = 0;
  672. WORD wPort = 0;
  673. IIasClient *pIIasClient = NULL;
  674. HRESULT hr = S_OK;
  675. PATTRIBUTEPOSITION pAttribPosition = NULL;
  676. _ASSERT (ppCPacketRadius && pIAttributesRaw);
  677. //
  678. // allocate memory for packet header
  679. //
  680. pPacketHeader =
  681. reinterpret_cast <PBYTE> (CoTaskMemAlloc (PACKET_HEADER_SIZE));
  682. if (NULL == pPacketHeader)
  683. {
  684. IASTracePrintf (
  685. "Unable to allocate memory for packet header information "
  686. "while generating out-bound packet"
  687. );
  688. hr = E_OUTOFMEMORY;
  689. goto Cleanup;
  690. }
  691. //
  692. // we need to gather information from the attribute collection
  693. // needed to get create and initialize a CPacketRadius class
  694. // object
  695. //
  696. hr = GetOutPacketInfo (
  697. &dwAddress,
  698. &wPort,
  699. &pIIasClient,
  700. pPacketHeader,
  701. pIAttributesRaw
  702. );
  703. if (FAILED (hr)) { goto Cleanup; }
  704. //
  705. // create a new CPacketRadius class object
  706. //
  707. *ppCPacketRadius = new (std::nothrow) CPacketRadius (
  708. m_pCHashMD5,
  709. m_pCHashHmacMD5,
  710. pIIasClient,
  711. m_pCReportEvent,
  712. pPacketHeader,
  713. PACKET_HEADER_SIZE,
  714. dwAddress,
  715. wPort,
  716. INVALID_SOCKET,
  717. AUTH_PORTTYPE
  718. );
  719. if (NULL == *ppCPacketRadius)
  720. {
  721. IASTracePrintf (
  722. "Unable to create a Packet-Radius object "
  723. "while generating an out-bound packet"
  724. );
  725. pIIasClient->Release ();
  726. hr = E_OUTOFMEMORY;
  727. goto Cleanup;
  728. }
  729. Cleanup:
  730. if ((FAILED (hr)) && (pPacketHeader))
  731. {
  732. CoTaskMemFree (pPacketHeader);
  733. }
  734. return (hr);
  735. } // end of CRecvFromPipe::GeneratePacketRadius method
  736. //++--------------------------------------------------------------
  737. //
  738. // Function: InjectSignatureIfNeeded
  739. //
  740. // Synopsis: This method is used to add a blank Signature attribute
  741. // into the response if we see an EAP-Message attribute
  742. // present
  743. //
  744. // Arguments:
  745. // [in] PACKETTYPE
  746. // [in] IAttributesRaw*
  747. // [in] CPacketRadius*
  748. //
  749. // Returns: HRESULT - status
  750. //
  751. // History: MKarki Created 11/17/98
  752. //
  753. // Called By: CRecvFromPipe::Process method
  754. //
  755. //----------------------------------------------------------------
  756. HRESULT CRecvFromPipe::InjectSignatureIfNeeded (
  757. /*[in]*/ PACKETTYPE ePacketType,
  758. /*[in]*/ IAttributesRaw *pIAttributesRaw,
  759. /*[in]*/ CPacketRadius *pCPacketRadius
  760. )
  761. {
  762. HRESULT hr = S_OK;
  763. PATTRIBUTEPOSITION pAttribPos = NULL;
  764. PIASATTRIBUTE pIasAttrib = NULL;
  765. _ASSERT (pIAttributesRaw && pCPacketRadius);
  766. __try
  767. {
  768. if (
  769. (ACCESS_ACCEPT != ePacketType) &&
  770. (ACCESS_REJECT != ePacketType) &&
  771. (ACCESS_CHALLENGE != ePacketType)
  772. )
  773. {__leave;}
  774. //
  775. // get the count of the total attributes in the collection
  776. //
  777. DWORD dwAttributeCount = 0;
  778. hr = pIAttributesRaw->GetAttributeCount (&dwAttributeCount);
  779. if (FAILED (hr))
  780. {
  781. IASTracePrintf (
  782. "Unable to obtain attribute count in request while "
  783. "processing message authenticator attribute in out-bound packet "
  784. );
  785. __leave;
  786. }
  787. else if (0 == dwAttributeCount)
  788. {
  789. __leave;
  790. }
  791. //
  792. // allocate memory for the ATTRIBUTEPOSITION array
  793. //
  794. pAttribPos = reinterpret_cast <PATTRIBUTEPOSITION> (
  795. CoTaskMemAlloc (
  796. sizeof (ATTRIBUTEPOSITION)*dwAttributeCount));
  797. if (NULL == pAttribPos)
  798. {
  799. IASTracePrintf (
  800. "Unable to allocate memory for attribute position array "
  801. "while processing message authenticator attribute in out-bound packet"
  802. );
  803. hr = E_OUTOFMEMORY;
  804. __leave;
  805. }
  806. //
  807. // get the EAP-Message attribute from the interface
  808. //
  809. DWORD dwAttrId = RADIUS_ATTRIBUTE_EAP_MESSAGE;
  810. hr = pIAttributesRaw->GetAttributes (
  811. &dwAttributeCount,
  812. pAttribPos,
  813. 1,
  814. &dwAttrId
  815. );
  816. if (FAILED (hr))
  817. {
  818. IASTracePrintf (
  819. "Unable to obtain information about EAP-Message attribute "
  820. "while processing out-bound RADIUS packet"
  821. );
  822. }
  823. else if (0 == dwAttributeCount)
  824. {
  825. __leave;
  826. }
  827. bool bFound = false;
  828. for (DWORD dwCount = 0; dwCount < dwAttributeCount; dwCount++)
  829. {
  830. if (
  831. (!bFound) &&
  832. (pCPacketRadius->IsOutBoundAttribute (
  833. ePacketType,
  834. pAttribPos[dwCount].pAttribute
  835. ))
  836. )
  837. {
  838. bFound = true;
  839. }
  840. ::IASAttributeRelease (pAttribPos[dwCount].pAttribute);
  841. }
  842. if (bFound)
  843. {
  844. //
  845. // if we have an out-bound EAP-Message attribute then
  846. // we need to insert a Signature attribute too
  847. //
  848. //
  849. // create a new blank attribute
  850. //
  851. DWORD dwRetVal = ::IASAttributeAlloc ( 1, &pIasAttrib);
  852. if (0 != dwRetVal)
  853. {
  854. IASTracePrintf (
  855. "Unable to allocate IAS attribute for message authenticator "
  856. "while processing out-bound RADIUS packet"
  857. );
  858. hr = HRESULT_FROM_WIN32 (dwRetVal);
  859. __leave;
  860. }
  861. //
  862. // allocate dynamic memory for the Signature
  863. //
  864. pIasAttrib->Value.OctetString.lpValue =
  865. reinterpret_cast <PBYTE>
  866. (CoTaskMemAlloc (SIGNATURE_SIZE));
  867. if (NULL == pIasAttrib->Value.OctetString.lpValue)
  868. {
  869. IASTracePrintf (
  870. "Unable to allocate dynamic memory for message authenticator "
  871. "attribute value while processing out-bound RADIUS packet"
  872. );
  873. hr = E_OUTOFMEMORY;
  874. __leave;
  875. }
  876. else
  877. {
  878. //
  879. // put the signature attribute with no value
  880. // but correct size
  881. //
  882. pIasAttrib->dwId = RADIUS_ATTRIBUTE_SIGNATURE;
  883. pIasAttrib->Value.itType = IASTYPE_OCTET_STRING;
  884. pIasAttrib->Value.OctetString.dwLength = SIGNATURE_SIZE;
  885. pIasAttrib->dwFlags = IAS_INCLUDE_IN_RESPONSE;
  886. //
  887. // add the attribute to the collection now
  888. //
  889. ATTRIBUTEPOSITION attrPos;
  890. attrPos.pAttribute = pIasAttrib;
  891. hr = pIAttributesRaw->AddAttributes (1, &attrPos);
  892. if (FAILED (hr))
  893. {
  894. IASTracePrintf (
  895. "Unable to add message authenticator attribute to request while "
  896. "processing out-bound RADIUS packet"
  897. );
  898. __leave;
  899. }
  900. IASTracePrintf (
  901. "message authenticator Attribute added to out-bound RADIUS packet"
  902. );
  903. }
  904. }
  905. }
  906. __finally
  907. {
  908. if (pAttribPos) { CoTaskMemFree (pAttribPos); }
  909. if (pIasAttrib) { ::IASAttributeRelease(pIasAttrib);}
  910. }
  911. return (hr);
  912. } // end of CRecvFromPipe::InjectSignatureIfNeeded method
  913. //++--------------------------------------------------------------
  914. //
  915. // Function: SplitAttributes
  916. //
  917. // Synopsis: This method is used to split up the following
  918. // out-bound attributes:
  919. // 1) Reply-Message attribute
  920. // 2) MS-Filter-VSA attribute
  921. // 3) MS QuarantineIpFilter attribute (VSA)
  922. //
  923. // Arguments:
  924. // [in] IAttributesRaw*
  925. //
  926. // Returns: HRESULT - status
  927. //
  928. // History: MKarki Created 1/19/99
  929. //
  930. // Called By: CRecvFromPipe::Process method
  931. //
  932. //----------------------------------------------------------------
  933. HRESULT CRecvFromPipe::SplitAttributes (
  934. /*[in]*/ IAttributesRaw *pIAttributesRaw
  935. )
  936. {
  937. const DWORD SPLIT_ATTRIBUTE_COUNT = 3;
  938. static DWORD AttribIds [] = {
  939. RADIUS_ATTRIBUTE_REPLY_MESSAGE,
  940. MS_ATTRIBUTE_FILTER,
  941. MS_ATTRIBUTE_QUARANTINE_IPFILTER
  942. };
  943. HRESULT hr = S_OK;
  944. DWORD dwAttributesFound = 0;
  945. PATTRIBUTEPOSITION pAttribPos = NULL;
  946. _ASSERT (pIAttributesRaw);
  947. __try
  948. {
  949. //
  950. // get the count of the total attributes in the collection
  951. //
  952. DWORD dwAttributeCount = 0;
  953. hr = pIAttributesRaw->GetAttributeCount (&dwAttributeCount);
  954. if (FAILED (hr))
  955. {
  956. IASTracePrintf (
  957. "Unable to obtain attribute count in request while "
  958. "splitting attributes in out-bound packet "
  959. );
  960. __leave;
  961. }
  962. else if (0 == dwAttributeCount)
  963. {
  964. __leave;
  965. }
  966. //
  967. // allocate memory for the ATTRIBUTEPOSITION array
  968. //
  969. pAttribPos = reinterpret_cast <PATTRIBUTEPOSITION> (
  970. CoTaskMemAlloc (
  971. sizeof (ATTRIBUTEPOSITION)*dwAttributeCount)
  972. );
  973. if (NULL == pAttribPos)
  974. {
  975. IASTracePrintf (
  976. "Unable to allocate memory for attribute position array "
  977. "while splitting attributes in out-bound packet"
  978. );
  979. hr = E_OUTOFMEMORY;
  980. __leave;
  981. }
  982. //
  983. // get the attributes we are interested in from the interface
  984. //
  985. hr = pIAttributesRaw->GetAttributes (
  986. &dwAttributeCount,
  987. pAttribPos,
  988. SPLIT_ATTRIBUTE_COUNT,
  989. static_cast <PDWORD> (AttribIds)
  990. );
  991. if (FAILED (hr))
  992. {
  993. IASTracePrintf (
  994. "Unable to obtain information about attributes"
  995. "while splitting attributes in out-bound RADIUS packet"
  996. );
  997. __leave;
  998. }
  999. else if (0 == dwAttributeCount)
  1000. {
  1001. __leave;
  1002. }
  1003. //
  1004. // save the count of attributes returned
  1005. //
  1006. dwAttributesFound = dwAttributeCount;
  1007. DWORD dwAttribLength = 0;
  1008. DWORD dwMaxPossibleLength = 0;
  1009. IASTYPE iasType = IASTYPE_INVALID;
  1010. //
  1011. // evaluate each attribute now
  1012. //
  1013. for (DWORD dwCount = 0; dwCount < dwAttributeCount; dwCount++)
  1014. {
  1015. if ((pAttribPos[dwCount].pAttribute)->dwFlags &
  1016. IAS_INCLUDE_IN_RESPONSE)
  1017. {
  1018. //
  1019. // get attribute type and length
  1020. //
  1021. if (
  1022. (iasType = (pAttribPos[dwCount].pAttribute)->Value.itType) ==
  1023. IASTYPE_STRING
  1024. )
  1025. {
  1026. DWORD dwErr = ::IASAttributeAnsiAlloc(pAttribPos[dwCount].pAttribute);
  1027. if (dwErr != NO_ERROR)
  1028. {
  1029. hr = HRESULT_FROM_WIN32(dwErr);
  1030. IASTracePrintf (
  1031. "Unable to allocate memory for string attribute "
  1032. "while splitting attributes in out-bound packet"
  1033. );
  1034. __leave;
  1035. }
  1036. dwAttribLength =
  1037. strlen (
  1038. (pAttribPos[dwCount].pAttribute)->Value.String.pszAnsi);
  1039. }
  1040. else if (
  1041. (iasType = (pAttribPos[dwCount].pAttribute)->Value.itType) ==
  1042. IASTYPE_OCTET_STRING
  1043. )
  1044. {
  1045. dwAttribLength =
  1046. (pAttribPos[dwCount].pAttribute)->Value.OctetString.dwLength;
  1047. }
  1048. else
  1049. {
  1050. //
  1051. // only string values need to be split
  1052. //
  1053. continue;
  1054. }
  1055. //
  1056. // get max possible attribute length
  1057. //
  1058. if ((pAttribPos[dwCount].pAttribute)->dwId > MAX_ATTRIBUTE_TYPE)
  1059. {
  1060. dwMaxPossibleLength = MAX_VSA_ATTRIBUTE_LENGTH;
  1061. }
  1062. else
  1063. {
  1064. dwMaxPossibleLength = MAX_ATTRIBUTE_LENGTH;
  1065. }
  1066. //
  1067. // check if we need to split this attribute
  1068. //
  1069. if (dwAttribLength <= dwMaxPossibleLength) {continue;}
  1070. //
  1071. // split the attribute now
  1072. //
  1073. hr = SplitAndAdd (
  1074. pIAttributesRaw,
  1075. pAttribPos[dwCount].pAttribute,
  1076. iasType,
  1077. dwAttribLength,
  1078. dwMaxPossibleLength
  1079. );
  1080. if (SUCCEEDED (hr))
  1081. {
  1082. //
  1083. // remove this attribute from the collection now
  1084. //
  1085. hr = pIAttributesRaw->RemoveAttributes (
  1086. 1,
  1087. &(pAttribPos[dwCount])
  1088. );
  1089. if (FAILED (hr))
  1090. {
  1091. IASTracePrintf (
  1092. "Unable to remove attribute from collection"
  1093. "while splitting out-bound attributes"
  1094. );
  1095. }
  1096. }
  1097. }
  1098. }
  1099. }
  1100. __finally
  1101. {
  1102. if (pAttribPos)
  1103. {
  1104. for (DWORD dwCount = 0; dwCount < dwAttributesFound; dwCount++)
  1105. {
  1106. ::IASAttributeRelease (pAttribPos[dwCount].pAttribute);
  1107. }
  1108. CoTaskMemFree (pAttribPos);
  1109. }
  1110. }
  1111. return (hr);
  1112. } // end of CRecvFromPipe::SplitAttributes method
  1113. //++--------------------------------------------------------------
  1114. //
  1115. // Function: SplitAndAdd
  1116. //
  1117. // Synopsis: This method is used to remove the original attribute
  1118. // and add new ones
  1119. // Arguments:
  1120. // [in] IAttributesRaw*
  1121. // [in] PIASATTRIBUTE
  1122. // [in] IASTYPE
  1123. // [in] DWORD - attribute length
  1124. // [in] DWORD - max attribute length
  1125. //
  1126. // Returns: HRESULT - status
  1127. //
  1128. // History: MKarki Created 1/19/99
  1129. //
  1130. // Called By: CRecvFromPipe::SplitAttributes method
  1131. //
  1132. //----------------------------------------------------------------
  1133. HRESULT CRecvFromPipe::SplitAndAdd (
  1134. /*[in]*/ IAttributesRaw *pIAttributesRaw,
  1135. /*[in]*/ PIASATTRIBUTE pIasAttribute,
  1136. /*[in]*/ IASTYPE iasType,
  1137. /*[in]*/ DWORD dwAttributeLength,
  1138. /*[in]*/ DWORD dwMaxLength
  1139. )
  1140. {
  1141. HRESULT hr = S_OK;
  1142. DWORD dwPacketsNeeded = 0;
  1143. DWORD dwFailed = 0;
  1144. PIASATTRIBUTE *ppAttribArray = NULL;
  1145. PATTRIBUTEPOSITION pAttribPos = NULL;
  1146. _ASSERT (pIAttributesRaw && pIasAttribute);
  1147. __try
  1148. {
  1149. dwPacketsNeeded = dwAttributeLength / dwMaxLength;
  1150. if (dwAttributeLength % dwMaxLength) {++dwPacketsNeeded;}
  1151. //
  1152. // allocate memory for the ATTRIBUTEPOSITION array
  1153. //
  1154. pAttribPos = reinterpret_cast <PATTRIBUTEPOSITION> (
  1155. CoTaskMemAlloc (
  1156. sizeof (ATTRIBUTEPOSITION)*dwPacketsNeeded));
  1157. if (NULL == pAttribPos)
  1158. {
  1159. IASTracePrintf (
  1160. "Unable to allocate memory for attribute position array "
  1161. "while split and add of attributese in out-bound packet"
  1162. );
  1163. hr = E_OUTOFMEMORY;
  1164. __leave;
  1165. }
  1166. //
  1167. // allocate array to store the attributes in
  1168. //
  1169. ppAttribArray =
  1170. reinterpret_cast <PIASATTRIBUTE*> (
  1171. CoTaskMemAlloc (sizeof (PIASATTRIBUTE)*dwPacketsNeeded));
  1172. if (NULL == ppAttribArray)
  1173. {
  1174. IASTracePrintf (
  1175. "Unable to allocate memory"
  1176. "while split and add of out-bound attribues"
  1177. );
  1178. hr = E_OUTOFMEMORY;
  1179. __leave;
  1180. }
  1181. DWORD dwFailed =
  1182. ::IASAttributeAlloc (dwPacketsNeeded, ppAttribArray);
  1183. if (0 != dwFailed)
  1184. {
  1185. IASTracePrintf (
  1186. "Unable to allocate attributes while splitting out-bound"
  1187. "attributes"
  1188. );
  1189. hr = HRESULT_FROM_WIN32 (dwFailed);
  1190. __leave;
  1191. }
  1192. if (IASTYPE_STRING == iasType)
  1193. {
  1194. PCHAR pStart = (pIasAttribute->Value).String.pszAnsi;
  1195. DWORD dwCopySize = dwMaxLength;
  1196. //
  1197. // set value in each of the new attributes
  1198. //
  1199. for (DWORD dwCount1 = 0; dwCount1 < dwPacketsNeeded; dwCount1++)
  1200. {
  1201. (ppAttribArray[dwCount1])->Value.String.pszWide = NULL;
  1202. (ppAttribArray[dwCount1])->Value.String.pszAnsi =
  1203. reinterpret_cast <PCHAR>
  1204. (CoTaskMemAlloc ((dwCopySize + 1)*sizeof (CHAR)));
  1205. if (NULL == (ppAttribArray[dwCount1])->Value.String.pszAnsi)
  1206. {
  1207. IASTracePrintf (
  1208. "Unable to allocate memory for new attribute values"
  1209. "while split and add of out-bound attribues"
  1210. );
  1211. hr = E_OUTOFMEMORY;
  1212. __leave;
  1213. }
  1214. //
  1215. // set the value now
  1216. //
  1217. ::CopyMemory (
  1218. (ppAttribArray[dwCount1])->Value.String.pszAnsi,
  1219. pStart,
  1220. dwCopySize
  1221. );
  1222. //
  1223. // nul terminate the values
  1224. //
  1225. ((ppAttribArray[dwCount1])->Value.String.pszAnsi)[dwCopySize]=NUL;
  1226. (ppAttribArray[dwCount1])->Value.itType = iasType;
  1227. (ppAttribArray[dwCount1])->dwId = pIasAttribute->dwId;
  1228. (ppAttribArray[dwCount1])->dwFlags = pIasAttribute->dwFlags;
  1229. //
  1230. // calculate for next attribute
  1231. //
  1232. pStart = pStart + dwCopySize;
  1233. dwAttributeLength -= dwCopySize;
  1234. dwCopySize = (dwAttributeLength > dwMaxLength) ?
  1235. dwMaxLength : dwAttributeLength;
  1236. //
  1237. // add attribute to position array
  1238. //
  1239. pAttribPos[dwCount1].pAttribute = ppAttribArray[dwCount1];
  1240. }
  1241. }
  1242. else
  1243. {
  1244. PBYTE pStart = (pIasAttribute->Value).OctetString.lpValue;
  1245. DWORD dwCopySize = dwMaxLength;
  1246. //
  1247. // fill the new attributes now
  1248. //
  1249. for (DWORD dwCount1 = 0; dwCount1 < dwPacketsNeeded; dwCount1++)
  1250. {
  1251. (ppAttribArray[dwCount1])->Value.OctetString.lpValue =
  1252. reinterpret_cast <PBYTE> (CoTaskMemAlloc (dwCopySize));
  1253. if (NULL ==(ppAttribArray[dwCount1])->Value.OctetString.lpValue)
  1254. {
  1255. IASTracePrintf (
  1256. "Unable to allocate memory for new attribute values"
  1257. "while split and add of out-bound attribues"
  1258. );
  1259. hr = E_OUTOFMEMORY;
  1260. __leave;
  1261. }
  1262. //
  1263. // set the value now
  1264. //
  1265. ::CopyMemory (
  1266. (ppAttribArray[dwCount1])->Value.OctetString.lpValue,
  1267. pStart,
  1268. dwCopySize
  1269. );
  1270. (ppAttribArray[dwCount1])->Value.OctetString.dwLength = dwCopySize;
  1271. (ppAttribArray[dwCount1])->Value.itType = iasType;
  1272. (ppAttribArray[dwCount1])->dwId = pIasAttribute->dwId;
  1273. (ppAttribArray[dwCount1])->dwFlags = pIasAttribute->dwFlags;
  1274. //
  1275. // calculate for next attribute
  1276. //
  1277. pStart = pStart + dwCopySize;
  1278. dwAttributeLength -= dwCopySize;
  1279. dwCopySize = (dwAttributeLength > dwMaxLength) ?
  1280. dwMaxLength :
  1281. dwAttributeLength;
  1282. //
  1283. // add attribute to position array
  1284. //
  1285. pAttribPos[dwCount1].pAttribute = ppAttribArray[dwCount1];
  1286. }
  1287. }
  1288. //
  1289. // add the attribute to the collection
  1290. //
  1291. hr = pIAttributesRaw->AddAttributes (dwPacketsNeeded, pAttribPos);
  1292. if (FAILED (hr))
  1293. {
  1294. IASTracePrintf (
  1295. "Failed to add attributes to the collection"
  1296. "on split and add out-bound attributes"
  1297. );
  1298. __leave;
  1299. }
  1300. }
  1301. __finally
  1302. {
  1303. if (ppAttribArray && !dwFailed)
  1304. {
  1305. for (DWORD dwCount = 0; dwCount < dwPacketsNeeded; dwCount++)
  1306. {
  1307. ::IASAttributeRelease (ppAttribArray[dwCount]);
  1308. }
  1309. }
  1310. if (ppAttribArray) {CoTaskMemFree (ppAttribArray);}
  1311. if (pAttribPos) {CoTaskMemFree (pAttribPos);}
  1312. }
  1313. return (hr);
  1314. } // end of CRecvFromPipe::SplitAndAdd method
  1315. //++--------------------------------------------------------------
  1316. //
  1317. // Function: ConvertReasonToRadiusError
  1318. //
  1319. // Synopsis:
  1320. //
  1321. // Arguments:
  1322. // [in] iasReason
  1323. // [out] Radius Error
  1324. //
  1325. // Returns: HRESULT - status
  1326. //
  1327. // History: MKarki Created 12/31/98
  1328. //
  1329. // Called By: CRecvFromPipe::Process method
  1330. //
  1331. //----------------------------------------------------------------
  1332. HRESULT
  1333. CRecvFromPipe::ConvertReasonToRadiusError (
  1334. /*[in]*/ LONG iasReason,
  1335. /*[out]*/ PRADIUSLOGTYPE pRadError
  1336. )
  1337. {
  1338. HRESULT hr = S_OK;
  1339. _ASSERT (pRadError);
  1340. switch (iasReason)
  1341. {
  1342. case IAS_NO_RECORD:
  1343. *pRadError = RADIUS_NO_RECORD;
  1344. break;
  1345. case IAS_MALFORMED_REQUEST:
  1346. *pRadError = RADIUS_MALFORMED_PACKET;
  1347. break;
  1348. default:
  1349. hr = E_FAIL;
  1350. break;
  1351. }
  1352. return (hr);
  1353. } // end of CRecvFromPipe::ConvertReasonToRadiusError method