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.

955 lines
25 KiB

  1. //#--------------------------------------------------------------
  2. //
  3. // File: packetreceiver.cpp
  4. //
  5. // Synopsis: Implementation of CPacketReceiver class methods
  6. //
  7. //
  8. // History: 9/23/97 MKarki Created
  9. //
  10. // Copyright (C) 1997-98 Microsoft Corporation
  11. // All rights reserved.
  12. //
  13. //----------------------------------------------------------------
  14. #include "radcommon.h"
  15. #include "packetreceiver.h"
  16. #include <new>
  17. #include <iastlutl.h>
  18. #include <iasutil.h>
  19. //
  20. // this is the time we allow the worker thread to sleep
  21. //
  22. const DWORD MAX_SLEEP_TIME = 1000; //1000 milli-seconds
  23. extern LONG g_lPacketCount;
  24. extern LONG g_lThreadCount;
  25. ///////////////////////////////////////////////////////////////////////////////
  26. //
  27. // Retrieve the Auto-Reject User-Name pattern from the registry.
  28. //
  29. ///////////////////////////////////////////////////////////////////////////////
  30. BSTR
  31. WINAPI
  32. IASRadiusGetPingUserName( VOID )
  33. {
  34. LONG status;
  35. HKEY hKey;
  36. status = RegOpenKeyW(
  37. HKEY_LOCAL_MACHINE,
  38. L"SYSTEM\\CurrentControlSet\\Services\\IAS\\Parameters",
  39. &hKey
  40. );
  41. if (status != NO_ERROR) { return NULL; }
  42. BSTR val = NULL;
  43. DWORD cbData, type;
  44. status = RegQueryValueExW(
  45. hKey,
  46. L"Ping User-Name",
  47. NULL,
  48. &type,
  49. NULL,
  50. &cbData
  51. );
  52. if (status == NO_ERROR && type == REG_SZ)
  53. {
  54. PWSTR buf = (PWSTR)_alloca(cbData);
  55. status = RegQueryValueExW(
  56. hKey,
  57. L"Ping User-Name",
  58. NULL,
  59. &type,
  60. (PBYTE)buf,
  61. &cbData
  62. );
  63. if (status == NO_ERROR && type == REG_SZ)
  64. {
  65. val = SysAllocString(buf);
  66. }
  67. }
  68. RegCloseKey(hKey);
  69. return val;
  70. }
  71. ///////////////////////////////////////////////////////////////////////////////
  72. //
  73. // Handle ping packets.
  74. //
  75. ///////////////////////////////////////////////////////////////////////////////
  76. BOOL
  77. WINAPI
  78. IASRadiusIsPing(
  79. CPacketRadius& pkt,
  80. const RegularExpression& regexp
  81. ) throw ()
  82. {
  83. // Determine the ping response.
  84. PACKETTYPE outCode;
  85. switch (pkt.GetInCode())
  86. {
  87. case ACCESS_REQUEST:
  88. outCode = ACCESS_REJECT;
  89. break;
  90. case ACCOUNTING_REQUEST:
  91. outCode = ACCOUNTING_RESPONSE;
  92. break;
  93. default:
  94. return FALSE;
  95. }
  96. // Get the User-Name.
  97. PATTRIBUTE username = pkt.GetUserName();
  98. if (!username) { return FALSE; }
  99. // Convert to UNICODE and test against the pattern.
  100. IAS_OCTET_STRING oct = { username->byLength - 2, username->ValueStart };
  101. if (!regexp.testString(IAS_OCT2WIDE(oct))) { return FALSE; }
  102. // Build the empty out packet.
  103. HRESULT hr = pkt.BuildOutPacket(outCode, NULL, 0);
  104. if (SUCCEEDED(hr))
  105. {
  106. // Compute the Response-Authenticator.
  107. pkt.GenerateOutAuthenticator();
  108. // Get the packet ...
  109. PBYTE buf = pkt.GetOutPacket();
  110. WORD buflen = pkt.GetOutLength();
  111. // ... and address.
  112. SOCKADDR_IN sin;
  113. sin.sin_family = AF_INET;
  114. sin.sin_port = htons(pkt.GetOutPort());
  115. sin.sin_addr.s_addr = htonl(pkt.GetOutAddress());
  116. // Send the ping response.
  117. sendto(
  118. pkt.GetSocket(),
  119. (const char*)buf,
  120. buflen,
  121. 0,
  122. (PSOCKADDR)&sin,
  123. sizeof(sin)
  124. );
  125. }
  126. // This packet has been processed.
  127. InterlockedDecrement(&g_lPacketCount);
  128. return TRUE;
  129. }
  130. //+++-------------------------------------------------------------
  131. //
  132. // Function: CPacketReceiver
  133. //
  134. // Synopsis: This is the constructor of the CPacketReceiver class
  135. //
  136. // Arguments: NONE
  137. //
  138. // Returns: NONE
  139. //
  140. //
  141. // History: MKarki Created 9/26/97
  142. //
  143. //----------------------------------------------------------------
  144. CPacketReceiver::CPacketReceiver(
  145. VOID
  146. )
  147. : pingPattern(NULL),
  148. m_pCDictionary (NULL),
  149. m_pCPreValidator (NULL),
  150. m_pCHashMD5 (NULL),
  151. m_pCHashHmacMD5 (NULL),
  152. m_pCClients (NULL),
  153. m_pCReportEvent (NULL)
  154. {
  155. } // end of CPacketReceiver constructor
  156. //+++-------------------------------------------------------------
  157. //
  158. // Function: ~CPacketReceiver
  159. //
  160. // Synopsis: This is the destructor of the CPacketReceiver class
  161. //
  162. // Arguments: NONE
  163. //
  164. // Returns: NONE
  165. //
  166. // History: MKarki Created 9/23/97
  167. //
  168. //----------------------------------------------------------------
  169. CPacketReceiver::~CPacketReceiver(
  170. VOID
  171. )
  172. {
  173. SysFreeString(pingPattern);
  174. } // end of CPacketReceiver destructor
  175. //+++-------------------------------------------------------------
  176. //
  177. // Function: Init
  178. //
  179. // Synopsis: This is the method which initializes the
  180. // CPacketReceiver class object
  181. //
  182. // Arguments:
  183. // [in] CDictionary*
  184. // [in] CPreValidator*
  185. // [in] CHashMD5*
  186. // [in] CHashHmacMD5*
  187. // [in] CReportEvent*
  188. //
  189. // Returns: BOOL - status
  190. //
  191. //
  192. // History: MKarki Created 9/29/97
  193. //
  194. // Called By: CContoller class method
  195. //
  196. //----------------------------------------------------------------
  197. BOOL CPacketReceiver::Init(
  198. CDictionary *pCDictionary,
  199. CPreValidator *pCPreValidator,
  200. CHashMD5 *pCHashMD5,
  201. CHashHmacMD5 *pCHashHmacMD5,
  202. CClients *pCClients,
  203. CReportEvent *pCReportEvent
  204. )
  205. {
  206. _ASSERT (
  207. (NULL != pCDictionary) &&
  208. (NULL != pCPreValidator) &&
  209. (NULL != pCHashMD5) &&
  210. (NULL != pCHashHmacMD5) &&
  211. (NULL != pCClients) &&
  212. (NULL != pCReportEvent)
  213. );
  214. HRESULT hr = FinalConstruct();
  215. if (FAILED(hr))
  216. {
  217. return FALSE;
  218. }
  219. // Initialize the Auto-Reject pattern.
  220. if (pingPattern = IASRadiusGetPingUserName())
  221. {
  222. regexp.setGlobal(TRUE);
  223. regexp.setIgnoreCase(TRUE);
  224. regexp.setPattern(pingPattern);
  225. }
  226. m_pCDictionary = pCDictionary;
  227. m_pCPreValidator = pCPreValidator;
  228. m_pCHashMD5 = pCHashMD5;
  229. m_pCHashHmacMD5 = pCHashHmacMD5;
  230. m_pCClients = pCClients;
  231. m_pCReportEvent = pCReportEvent;
  232. if (m_AuthEvent.initialize() || m_AcctEvent.initialize())
  233. {
  234. return FALSE;
  235. }
  236. return (TRUE);
  237. } // end of CPacketReceiver::Init method
  238. //+++-------------------------------------------------------------
  239. //
  240. // Function: StartProcessing
  241. //
  242. // Synopsis: This is the method to start receiving inbound
  243. // data
  244. //
  245. // Arguments:
  246. // [in] fd_set - Authentication socket set
  247. // [in] fd_set - Accounting socket set
  248. //
  249. // Returns: BOOL - status
  250. //
  251. // History: MKarki Created 11/19/97
  252. //
  253. // Called By: CContoller::InternalInit method
  254. //
  255. //----------------------------------------------------------------
  256. BOOL
  257. CPacketReceiver::StartProcessing (
  258. /*[in]*/ fd_set& AuthSet,
  259. /*[in]*/ fd_set& AcctSet
  260. )
  261. {
  262. BOOL bStatus = FALSE;
  263. __try
  264. {
  265. //
  266. // enable
  267. //
  268. EnableProcessing ();
  269. m_AuthSet = AuthSet;
  270. m_AcctSet = AcctSet;
  271. // Make sure the events are clear ...
  272. m_AuthEvent.reset();
  273. m_AcctEvent.reset();
  274. // ... and add the to the fd_set.
  275. FD_SET (m_AuthEvent, &m_AuthSet);
  276. FD_SET (m_AcctEvent, &m_AcctSet);
  277. //
  278. // start a new thread to process authentication requests
  279. //
  280. bStatus = StartThreadIfNeeded (AUTH_PORTTYPE);
  281. if (FALSE == bStatus) { __leave; }
  282. //
  283. // start a new thread to process accounting requests
  284. //
  285. bStatus = StartThreadIfNeeded (ACCT_PORTTYPE);
  286. if (FALSE == bStatus) { __leave; }
  287. //
  288. // success
  289. //
  290. }
  291. __finally
  292. {
  293. if (FALSE == bStatus) { DisableProcessing (); }
  294. }
  295. return (bStatus);
  296. } // end of CPacketReceiver::StartProcessing method
  297. //+++-------------------------------------------------------------
  298. //
  299. // Function: StopProcessing
  300. //
  301. // Synopsis: This is the method to stop receiving inbound
  302. // data
  303. //
  304. // Arguments: none
  305. //
  306. // Returns: BOOL - status
  307. //
  308. //
  309. // History: MKarki Created 11/19/97
  310. //
  311. // Called By: CContoller::Suspend method
  312. //
  313. //----------------------------------------------------------------
  314. BOOL
  315. CPacketReceiver::StopProcessing (
  316. VOID
  317. )
  318. {
  319. DisableProcessing ();
  320. // Signal the SocketEvents to wake up the worker threads.
  321. m_AuthEvent.set();
  322. m_AcctEvent.set();
  323. return (TRUE);
  324. } // end of CPacketReceiver::StopProcessing method
  325. //+++-------------------------------------------------------------
  326. //
  327. // Function: ReceivePacket
  328. //
  329. // Synopsis: This is the method which receives the UDP packet
  330. // buffer and starts processing it.
  331. //
  332. // Arguments:
  333. // [in] PBYTE - in packet buffer
  334. // [in] DWORD - size of the packet
  335. // [in] DWORD - Client's IP address
  336. // [in] WORD - Client's UDP port
  337. //
  338. // Returns: HRESULT - status
  339. //
  340. // Called By: CPacketReceiver::WorkerRoutine private method
  341. //
  342. // History: MKarki Created 9/23/97
  343. //
  344. //----------------------------------------------------------------
  345. HRESULT
  346. CPacketReceiver::ReceivePacket(
  347. PBYTE pInBuffer,
  348. DWORD dwSize,
  349. DWORD dwIPaddress,
  350. WORD wPort,
  351. SOCKET sock,
  352. PORTTYPE portType
  353. )
  354. {
  355. BOOL bStatus = FALSE;
  356. HRESULT hr = S_OK;
  357. CPacketRadius *pCPacketRadius = NULL;
  358. CComPtr <IIasClient> pIIasClient;
  359. _ASSERT (pInBuffer);
  360. //
  361. // get client information for this RADIUS packet
  362. //
  363. bStatus = m_pCClients->FindObject (
  364. dwIPaddress,
  365. &pIIasClient
  366. );
  367. if (!bStatus)
  368. {
  369. //
  370. // free the allocated in buffer
  371. //
  372. CoTaskMemFree (pInBuffer);
  373. //
  374. // log error and generate audit event
  375. //
  376. WCHAR srcAddr[16];
  377. ias_inet_htow(dwIPaddress, srcAddr);
  378. PCWSTR strings[] = { srcAddr };
  379. IASReportEvent(
  380. RADIUS_E_INVALID_CLIENT,
  381. 1,
  382. 0,
  383. strings,
  384. NULL
  385. );
  386. //
  387. // generate an Audit Log
  388. //
  389. m_pCReportEvent->Process (
  390. RADIUS_INVALID_CLIENT,
  391. (AUTH_PORTTYPE == portType) ? ACCESS_REQUEST : ACCOUNTING_REQUEST,
  392. dwSize,
  393. dwIPaddress,
  394. 0,
  395. pInBuffer
  396. );
  397. return RADIUS_E_ERRORS_OCCURRED;
  398. }
  399. //
  400. // create packet radius object
  401. //
  402. pCPacketRadius = new (std::nothrow) CPacketRadius (
  403. m_pCHashMD5,
  404. m_pCHashHmacMD5,
  405. pIIasClient,
  406. m_pCReportEvent,
  407. pInBuffer,
  408. dwSize,
  409. dwIPaddress,
  410. wPort,
  411. sock,
  412. portType
  413. );
  414. if (NULL == pCPacketRadius)
  415. {
  416. //
  417. // free the allocated in buffer
  418. //
  419. CoTaskMemFree (pInBuffer);
  420. IASTracePrintf (
  421. "Unable to create Packet-Radius object during packet processing"
  422. );
  423. hr = E_OUTOFMEMORY;
  424. goto Cleanup;
  425. }
  426. //
  427. // now do the preliminary verification of the packet received
  428. //
  429. hr = pCPacketRadius->PrelimVerification (
  430. m_pCDictionary,
  431. dwSize
  432. );
  433. if (FAILED (hr)) { goto Cleanup; }
  434. // If the Ping User-Name pattern has been set, then we must test
  435. // this packet.
  436. if (pingPattern && IASRadiusIsPing(*pCPacketRadius, regexp))
  437. {
  438. // It was a ping packet, so we're done.
  439. delete pCPacketRadius;
  440. return S_OK;
  441. }
  442. //
  443. // now pass on this packet to the PreValidator
  444. //
  445. hr = m_pCPreValidator->StartInValidation (pCPacketRadius);
  446. if (FAILED (hr)) { goto Cleanup; }
  447. Cleanup:
  448. //
  449. // cleanup on error
  450. //
  451. if (FAILED (hr))
  452. {
  453. if (hr != RADIUS_E_ERRORS_OCCURRED)
  454. {
  455. IASReportEvent(
  456. RADIUS_E_INTERNAL_ERROR,
  457. 0,
  458. sizeof(hr),
  459. NULL,
  460. &hr
  461. );
  462. }
  463. //
  464. // also inform that the packet is being discarded
  465. //
  466. in_addr sin;
  467. sin.s_addr = htonl (dwIPaddress);
  468. IASTracePrintf (
  469. "Silently discarding packet received from:%s",
  470. inet_ntoa (sin)
  471. );
  472. //
  473. // inform that packet is being discarded
  474. //
  475. m_pCReportEvent->Process (
  476. RADIUS_DROPPED_PACKET,
  477. (AUTH_PORTTYPE == portType)?ACCESS_REQUEST:ACCOUNTING_REQUEST,
  478. dwSize,
  479. dwIPaddress,
  480. NULL,
  481. static_cast <LPVOID> (pInBuffer)
  482. );
  483. //
  484. // free the memory
  485. //
  486. if (pCPacketRadius) { delete pCPacketRadius; }
  487. }
  488. return (hr);
  489. } // end of CPacketReceiver::ReceivePacket method
  490. bool CPacketReceiver::WorkerRoutine(DWORD dwInfo) throw ()
  491. {
  492. // Return value from the function. Indicates whether or not the caller
  493. // should call WorkerRoutine again because we were unable to schedule a
  494. // replacement thread.
  495. bool shouldCallAgain = false;
  496. BOOL bSuccess = FALSE;
  497. DWORD dwPeerAddress = 0;
  498. WORD wPeerPort = 0;
  499. CPacketRadius *pCPacketRadius = NULL;
  500. PBYTE pBuffer = NULL;
  501. PBYTE pReAllocatedBuffer = NULL;
  502. DWORD dwSize = MAX_PACKET_SIZE;
  503. fd_set socketSet;
  504. SOCKET sock = INVALID_SOCKET;
  505. __try
  506. {
  507. if (AUTH_PORTTYPE == (PORTTYPE)dwInfo)
  508. {
  509. socketSet = m_AuthSet;
  510. }
  511. else
  512. {
  513. socketSet = m_AcctSet;
  514. }
  515. StartAgain:
  516. //
  517. // check if the processing is still going on
  518. //
  519. if (FALSE == IsProcessingEnabled ())
  520. {
  521. IASTracePrintf (
  522. "Worker Thread exiting as packet processing is not enabled"
  523. );
  524. __leave;
  525. }
  526. //
  527. // allocate a new inbound packet buffer
  528. //
  529. pBuffer = reinterpret_cast <PBYTE> (m_InBufferPool.allocate ());
  530. if (NULL == pBuffer)
  531. {
  532. IASTracePrintf (
  533. "unable to allocate memory from buffer pool for in-bound packet"
  534. );
  535. //
  536. // Sleep for a second, and try again
  537. // Fix for Bug #159140 - MKarki - 4/29/98
  538. //
  539. Sleep (MAX_SLEEP_TIME);
  540. //
  541. // we will have to check whether processing is still
  542. // enabled
  543. //
  544. goto StartAgain;
  545. }
  546. //
  547. // wait now on select
  548. //
  549. INT iRetVal = select (0, &socketSet, NULL, NULL, NULL);
  550. if (SOCKET_ERROR == iRetVal)
  551. {
  552. int iWsaError = ::WSAGetLastError();
  553. IASTracePrintf (
  554. "Worker Thread failed on select call with error:%d",
  555. iWsaError
  556. );
  557. if (WSAENOBUFS == iWsaError)
  558. {
  559. IASTraceString("WARNING: out of memory condition on select in CPacketReceiver::WorkerRoutine");
  560. // out of memory condition. Keep using this thread.
  561. shouldCallAgain = true;
  562. // to give a chance to the system to recover from a transient
  563. // condition
  564. Sleep(5);
  565. }
  566. __leave;
  567. }
  568. //
  569. // check if the processing is still going on
  570. //
  571. if (FALSE == IsProcessingEnabled ())
  572. {
  573. IASTracePrintf(
  574. "Worker Thread exiting as packet processing is not enabled"
  575. );
  576. __leave;
  577. }
  578. //
  579. // get a socket to recv data on
  580. //
  581. static size_t nextSocket;
  582. sock = socketSet.fd_array[++nextSocket % iRetVal];
  583. //
  584. // recv data now
  585. //
  586. SOCKADDR_IN sin;
  587. DWORD dwAddrSize = sizeof (SOCKADDR);
  588. dwSize = ::recvfrom (
  589. sock,
  590. (PCHAR)pBuffer,
  591. (INT)dwSize,
  592. (INT)0,
  593. (PSOCKADDR)&sin,
  594. (INT*)&dwAddrSize
  595. );
  596. // Request a new thread now
  597. if (!StartThreadIfNeeded(dwInfo))
  598. {
  599. // We were unable to create a replacement thread, so this thread
  600. // will have to keep receiving packets for now.
  601. IASTraceString("WARNING StartThreadIfNeeded failed in CPacketReceiver::WorkerRoutine");
  602. shouldCallAgain = true;
  603. }
  604. //
  605. // if failed to receive data, quit processing
  606. // MKarki 3/13/98 - Fix for Bug #147266
  607. // Fix Summary: check for dwSize == 0 too
  608. //
  609. if ( 0 == dwSize )
  610. {
  611. IASTraceString("WARNING failed to receive data, quit processing in CPacketReceiver::WorkerRoutine");
  612. __leave;
  613. }
  614. wPeerPort = ntohs (sin.sin_port);
  615. dwPeerAddress = ntohl (sin.sin_addr.s_addr);
  616. if ( dwSize == SOCKET_ERROR )
  617. {
  618. int error = WSAGetLastError();
  619. IASTracePrintf (
  620. "WARNING Worker Thread failed on recvfrom with error:%d",
  621. error
  622. );
  623. switch (error)
  624. {
  625. case WSAEMSGSIZE:
  626. {
  627. ProcessInvalidPacketSize(dwInfo, pBuffer, dwPeerAddress);
  628. __leave;
  629. }
  630. default:
  631. __leave;
  632. }
  633. }
  634. //
  635. // reallocate buffer to size
  636. //
  637. pReAllocatedBuffer = reinterpret_cast <PBYTE>
  638. (CoTaskMemAlloc (dwSize));
  639. if (NULL == pReAllocatedBuffer)
  640. {
  641. IASTracePrintf (
  642. "Unable to allocate memory for received Radius packet "
  643. "from Process Heap"
  644. );
  645. __leave;
  646. }
  647. //
  648. // copy the information into this buffer
  649. //
  650. CopyMemory (pReAllocatedBuffer, pBuffer, dwSize);
  651. //
  652. // free the memory from the pool
  653. //
  654. m_InBufferPool.deallocate (pBuffer);
  655. pBuffer = NULL;
  656. //
  657. // success
  658. //
  659. bSuccess = TRUE;
  660. }
  661. __finally
  662. {
  663. if (FALSE == bSuccess)
  664. {
  665. //
  666. // do Cleanup
  667. //
  668. if (pBuffer) { m_InBufferPool.deallocate (pBuffer); }
  669. }
  670. else
  671. {
  672. //
  673. // Increment the packet count here
  674. //
  675. InterlockedIncrement (&g_lPacketCount);
  676. //
  677. // start processing data
  678. //
  679. HRESULT hr = ReceivePacket (
  680. pReAllocatedBuffer,
  681. dwSize,
  682. dwPeerAddress,
  683. wPeerPort,
  684. sock,
  685. (PORTTYPE)dwInfo
  686. );
  687. if (FAILED (hr))
  688. {
  689. //
  690. // Decrement the packet count here
  691. //
  692. InterlockedDecrement (&g_lPacketCount);
  693. }
  694. }
  695. }
  696. return shouldCallAgain;
  697. }
  698. void WINAPI CPacketReceiver::CallbackRoutine(IAS_CALLBACK* context) throw ()
  699. {
  700. ReceiverCallback* cback = static_cast<ReceiverCallback*>(context);
  701. while (cback->self->WorkerRoutine(cback->dwInfo))
  702. {
  703. IASTraceString("WARNING: reusing WorkerRoutine");
  704. }
  705. CoTaskMemFree(cback);
  706. // decrement the global worker thread count
  707. InterlockedDecrement(&g_lThreadCount);
  708. }
  709. BOOL CPacketReceiver::StartThreadIfNeeded(DWORD dwInfo)
  710. {
  711. // check if the processing is still going on
  712. if (!IsProcessingEnabled())
  713. {
  714. return TRUE;
  715. }
  716. ReceiverCallback* cback = static_cast<ReceiverCallback*>(
  717. CoTaskMemAlloc(sizeof(ReceiverCallback))
  718. );
  719. if (cback == 0)
  720. {
  721. IASTraceString(
  722. "CoTaskMemAlloc failed in CPacketReceiver::StartThreadIfNeeded."
  723. );
  724. return FALSE;
  725. }
  726. cback->CallbackRoutine = CallbackRoutine;
  727. cback->self = this;
  728. cback->dwInfo = dwInfo;
  729. InterlockedIncrement(&g_lThreadCount);
  730. // Request a new thread now
  731. if (!IASRequestThread(cback))
  732. {
  733. InterlockedDecrement(&g_lThreadCount);
  734. CoTaskMemFree(cback);
  735. IASTraceString(
  736. "IASRequestThread failed in CPacketReceiver::StartThreadIfNeeded."
  737. );
  738. return FALSE;
  739. }
  740. return TRUE;
  741. }
  742. //+++-------------------------------------------------------------
  743. //
  744. // Function: ProcessInvalidPacketSize
  745. //
  746. // Synopsis: Process the UDP packets received when the size of the packet
  747. // is bigger than MAX_PACKET_SIZE (4096)
  748. // Log the error.
  749. //
  750. // Arguments: [in] DWORD - info to give to thread
  751. // (comes from WorkerRoutine)
  752. //
  753. // [in] const void* pBuffer - contains the 4096 first bytes
  754. // of the packet received
  755. // [in] DWORD address - source address (host order)
  756. //
  757. //
  758. // Called By: CPacketReceiver::WorkerRoutine
  759. //
  760. //----------------------------------------------------------------
  761. void CPacketReceiver::ProcessInvalidPacketSize(
  762. /*in*/ DWORD dwInfo,
  763. /*in*/ const void* pBuffer,
  764. /*in*/ DWORD address
  765. )
  766. {
  767. //
  768. // packet received bigger than max size.
  769. // log error and generate audit event
  770. //
  771. // extract the IP address
  772. WCHAR srcAddr[16];
  773. ias_inet_htow(address, srcAddr);
  774. IASTracePrintf(
  775. "Incorrect received packet from %S, size: greater than %d",
  776. srcAddr, MAX_PACKET_SIZE
  777. );
  778. //
  779. // get client information for this RADIUS packet
  780. //
  781. BOOL bStatus = m_pCClients->FindObject(address);
  782. if ( bStatus == FALSE )
  783. {
  784. //
  785. // Invalid Client
  786. // log error and generate audit event
  787. //
  788. IASTracePrintf(
  789. "No client with IP-Address:%S registered with server",
  790. srcAddr
  791. );
  792. PCWSTR strings[] = { srcAddr };
  793. IASReportEvent(
  794. RADIUS_E_INVALID_CLIENT,
  795. 1,
  796. 0,
  797. strings,
  798. NULL
  799. );
  800. //
  801. // generate an Audit Log
  802. //
  803. m_pCReportEvent->Process(
  804. RADIUS_INVALID_CLIENT,
  805. (AUTH_PORTTYPE == (PORTTYPE)dwInfo)?ACCESS_REQUEST:ACCOUNTING_REQUEST,
  806. MAX_PACKET_SIZE,
  807. address,
  808. NULL,
  809. const_cast<void*> (pBuffer)
  810. );
  811. }
  812. else
  813. {
  814. //
  815. // Valid client but packet received bigger than max size.
  816. // log error and generate audit event
  817. //
  818. PCWSTR strings[] = {srcAddr};
  819. IASReportEvent(
  820. RADIUS_E_MALFORMED_PACKET,
  821. 1,
  822. MAX_PACKET_SIZE,
  823. strings,
  824. const_cast<void*> (pBuffer)
  825. );
  826. //
  827. // generate an Audit Log
  828. //
  829. m_pCReportEvent->Process(
  830. RADIUS_MALFORMED_PACKET,
  831. (AUTH_PORTTYPE == (PORTTYPE)dwInfo)?ACCESS_REQUEST:ACCOUNTING_REQUEST,
  832. MAX_PACKET_SIZE,
  833. address,
  834. NULL,
  835. const_cast<void*> (pBuffer)
  836. );
  837. }
  838. }