Source code of Windows XP (NT5)
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.

1464 lines
44 KiB

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