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.

702 lines
16 KiB

  1. //#--------------------------------------------------------------
  2. //
  3. // File: client.cpp
  4. //
  5. // Synopsis: Implementation of CClient 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 "client.h"
  16. #include "iasevent.h"
  17. #include <iasutil.h>
  18. #include <memory>
  19. inline BOOL IsDottedDecimal(PCWSTR sz) throw ()
  20. {
  21. return wcsspn(sz, L"0123456789./") == wcslen(sz);
  22. }
  23. //++--------------------------------------------------------------
  24. //
  25. // Function: CClient
  26. //
  27. // Synopsis: This is the constructor of the Client class
  28. //
  29. // Arguments: NONE
  30. //
  31. // Returns: NONE
  32. //
  33. // History: MKarki Created 9/26/97
  34. //
  35. //----------------------------------------------------------------
  36. CClient::CClient (
  37. VOID
  38. )
  39. : m_adwAddrList (m_adwAddressBuffer),
  40. m_lVendorType (0),
  41. m_bSignatureCheck (FALSE)
  42. {
  43. m_adwAddressBuffer[0].ipAddress = INADDR_NONE;
  44. ZeroMemory (m_szSecret, MAX_SECRET_SIZE + 1);
  45. } // end of CClient constructor
  46. //++--------------------------------------------------------------
  47. //
  48. // Function: ~CClient
  49. //
  50. // Synopsis: This is the destructor of the Client class
  51. //
  52. // Arguments: NONE
  53. //
  54. // Returns: NONE
  55. //
  56. // History: MKarki Created 9/26/97
  57. //
  58. //----------------------------------------------------------------
  59. CClient::~CClient(
  60. VOID
  61. )
  62. {
  63. ClearAddress();
  64. } // end of CClient constructor
  65. //++--------------------------------------------------------------
  66. //
  67. // Function: Init
  68. //
  69. // Synopsis: This is the CClient public method used
  70. // to initialize the object with the
  71. // ISdo interface
  72. //
  73. // Arguments:
  74. // [in] ISdo*
  75. //
  76. // Returns: NONE
  77. //
  78. // History: MKarki Created 9/26/97
  79. //
  80. // Called By: CClients::SetClients public method
  81. //
  82. //----------------------------------------------------------------
  83. STDMETHODIMP
  84. CClient::Init (
  85. ISdo *pISdo
  86. )
  87. {
  88. BOOL bStatus = FALSE;
  89. HRESULT hr = S_OK;
  90. CComVariant varClient;
  91. _ASSERT (pISdo);
  92. //
  93. // get the client address first
  94. //
  95. hr = pISdo->GetProperty (PROPERTY_CLIENT_ADDRESS, &varClient);
  96. if (FAILED (hr))
  97. {
  98. IASTracePrintf (
  99. "Unable to obtain Client Address Property "
  100. "during Client object initialization"
  101. );
  102. hr = E_FAIL;
  103. return (hr);
  104. }
  105. //
  106. // store the address
  107. //
  108. bStatus = SetAddress (varClient);
  109. if (FALSE == bStatus)
  110. {
  111. hr = E_FAIL;
  112. return (hr);
  113. }
  114. varClient.Clear ();
  115. //
  116. // get the client address first
  117. //
  118. hr = pISdo->GetProperty (PROPERTY_CLIENT_SHARED_SECRET, &varClient);
  119. if (FAILED (hr))
  120. {
  121. IASTracePrintf (
  122. "Unable to obtain Client shared secret Property "
  123. "during Client object initialization"
  124. );
  125. return (hr);
  126. }
  127. //
  128. // now store away the shared secret
  129. //
  130. bStatus = SetSecret (varClient);
  131. if (FALSE == bStatus)
  132. {
  133. hr = E_FAIL;
  134. return (hr);
  135. }
  136. varClient.Clear ();
  137. //
  138. // get signature information
  139. //
  140. hr = pISdo->GetProperty (PROPERTY_CLIENT_REQUIRE_SIGNATURE, &varClient);
  141. if (FAILED (hr))
  142. {
  143. IASTracePrintf (
  144. "Unable to obtain Client Signature Property "
  145. "during Client object initialization"
  146. );
  147. return (hr);
  148. }
  149. //
  150. // store away the signature information
  151. //
  152. bStatus = SetSignatureFlag (varClient);
  153. if (FALSE == bStatus)
  154. {
  155. hr = E_FAIL;
  156. return (hr);
  157. }
  158. varClient.Clear ();
  159. //
  160. // get the client NAS Manufacturer information
  161. //
  162. hr = pISdo->GetProperty (PROPERTY_CLIENT_NAS_MANUFACTURER, &varClient);
  163. if (FAILED (hr))
  164. {
  165. IASTracePrintf (
  166. "Unable to obtain Client NAS Manufacturer Property "
  167. "during Client object initialization"
  168. );
  169. return (hr);
  170. }
  171. //
  172. // store away the Nas Manufacturer information
  173. //
  174. bStatus = SetVendorType (varClient);
  175. if (FALSE == bStatus)
  176. {
  177. hr = E_FAIL;
  178. return (hr);
  179. }
  180. varClient.Clear ();
  181. //
  182. // get the client name
  183. //
  184. hr = pISdo->GetProperty (PROPERTY_SDO_NAME, &varClient);
  185. if (FAILED (hr))
  186. {
  187. IASTracePrintf (
  188. "Unable to obtain SDO Name Property "
  189. "during Client object initialization"
  190. );
  191. return (hr);
  192. }
  193. //
  194. // store away the client name information
  195. //
  196. bStatus = SetClientName (varClient);
  197. if (FALSE == bStatus)
  198. {
  199. hr = E_FAIL;
  200. return (hr);
  201. }
  202. varClient.Clear ();
  203. return (hr);
  204. } // end of CClient::Init method
  205. void CClient::ClearAddress() throw ()
  206. {
  207. if (m_adwAddrList != m_adwAddressBuffer)
  208. {
  209. delete[] m_adwAddrList;
  210. }
  211. m_adwAddressBuffer[0].ipAddress = INADDR_NONE;
  212. m_adwAddrList = m_adwAddressBuffer;
  213. }
  214. //++--------------------------------------------------------------
  215. //
  216. // Function: SetAddress
  217. //
  218. // Synopsis: This is the CClient private method used
  219. // to set the Client IP address
  220. //
  221. // Arguments: VARIANT - holds the IP address
  222. //
  223. // Returns: status
  224. //
  225. // History: MKarki Created 2/3/98
  226. //
  227. // Called By: CClient::Init method
  228. //
  229. //----------------------------------------------------------------
  230. BOOL
  231. CClient::SetAddress (
  232. VARIANT varAddress
  233. )
  234. {
  235. _ASSERT (VT_BSTR == varAddress.vt);
  236. //
  237. // copy the address into the CClient Object
  238. //
  239. lstrcpy (
  240. m_wszClientAddress,
  241. reinterpret_cast <LPCWSTR> (varAddress.pbstrVal)
  242. );
  243. return (TRUE);
  244. } // end of CClient::SetAddress method
  245. //++--------------------------------------------------------------
  246. //
  247. // Function: ResolveAddress
  248. //
  249. // Synopsis: This is the CClient public method used
  250. // to resolve the Client IP address obtained previously
  251. // which could be a DNS name or dotted octed
  252. //
  253. // Arguments: VOID
  254. //
  255. // Returns: HRESULT
  256. //
  257. // History: MKarki Created 2/3/98
  258. //
  259. // Called By: CClient::Init method
  260. //
  261. //----------------------------------------------------------------
  262. STDMETHODIMP
  263. CClient::ResolveAddress (
  264. VOID
  265. )
  266. {
  267. INT iRetVal = 0;
  268. PHOSTENT pHostent = NULL;
  269. BOOL bDNSName = FALSE;
  270. BOOL bRetVal = TRUE;
  271. CHAR szClient[MAX_CLIENT_SIZE +1];
  272. HRESULT hr = S_OK;
  273. // Clear any existing addresses.
  274. ClearAddress();
  275. __try
  276. {
  277. //
  278. // check if this address is dotted octet or DNS name
  279. //
  280. if (!IsDottedDecimal(m_wszClientAddress))
  281. {
  282. //
  283. // we probably have a DNS name so
  284. // get the address information
  285. //
  286. pHostent = IASGetHostByName (m_wszClientAddress);
  287. if (NULL == pHostent)
  288. {
  289. IASTracePrintf (
  290. "Unable to get client IP Address through IASGetHostByName () "
  291. "during client address resolution"
  292. );
  293. //
  294. // log an event here
  295. //
  296. PCWSTR strings[] = { m_wszClientAddress, m_wszClientName };
  297. int data = WSAGetLastError();
  298. IASReportEvent(
  299. RADIUS_E_CANT_RESOLVE_CLIENT_NAME,
  300. 2,
  301. sizeof(data),
  302. strings,
  303. &data
  304. );
  305. hr = E_FAIL;
  306. __leave;
  307. }
  308. //
  309. // store addresses in host byte order
  310. //
  311. size_t count;
  312. for (count = 0; pHostent->h_addr_list[count]; ++count) { }
  313. if (count > 1)
  314. {
  315. m_adwAddrList = new (std::nothrow) Address[count + 1];
  316. if (!m_adwAddrList)
  317. {
  318. m_adwAddrList = m_adwAddressBuffer;
  319. hr = E_OUTOFMEMORY;
  320. __leave;
  321. }
  322. }
  323. for (count = 0; pHostent->h_addr_list[count]; ++count)
  324. {
  325. m_adwAddrList[count].ipAddress =
  326. ntohl(*(PDWORD)pHostent->h_addr_list[count]);
  327. m_adwAddrList[count].width = 32;
  328. }
  329. m_adwAddrList[count].ipAddress = INADDR_NONE;
  330. }
  331. else
  332. {
  333. //
  334. // this could be a dotted-octet address
  335. //
  336. ULONG width;
  337. m_adwAddressBuffer[0].ipAddress = IASStringToSubNetW(
  338. m_wszClientAddress,
  339. &m_adwAddressBuffer[0].width
  340. );
  341. if (INADDR_NONE == m_adwAddressBuffer[0].ipAddress)
  342. {
  343. IASTracePrintf (
  344. "Unable to get client IP Address through inet_addr () "
  345. "during client address resolution"
  346. );
  347. //
  348. // log an event here
  349. //
  350. PCWSTR strings[] = { m_wszClientAddress, m_wszClientName };
  351. IASReportEvent(
  352. RADIUS_E_INVALID_CLIENT_ADDRESS,
  353. 2,
  354. 0,
  355. strings,
  356. NULL
  357. );
  358. hr = E_FAIL;
  359. __leave;
  360. }
  361. // Terminate the array.
  362. m_adwAddressBuffer[1].ipAddress = INADDR_NONE;
  363. }
  364. }
  365. __finally
  366. {
  367. if (bRetVal)
  368. {
  369. IASTracePrintf (
  370. "Resolved Client:%S, to IP address:%ul", m_wszClientAddress, m_adwAddrList[0].ipAddress
  371. );
  372. }
  373. if (pHostent) { LocalFree(pHostent); }
  374. }
  375. return (hr);
  376. } // end of CClient::ResolveAddress method
  377. //++--------------------------------------------------------------
  378. //
  379. // Function: SetSecret
  380. //
  381. // Synopsis: This is the CClient private method used
  382. // to set the shared secret
  383. //
  384. // Arguments: VARIANT - holds the secret as a BSTR
  385. //
  386. // Returns: status
  387. //
  388. // History: MKarki Created 2/3/98
  389. //
  390. // Called By: CClient::Init method
  391. //
  392. //----------------------------------------------------------------
  393. BOOL
  394. CClient::SetSecret (
  395. VARIANT varSecret
  396. )
  397. {
  398. INT iRetVal = 0;
  399. _ASSERT (VT_BSTR == varSecret.vt);
  400. iRetVal = ::WideCharToMultiByte (
  401. CP_ACP,
  402. 0,
  403. reinterpret_cast <LPCWSTR> (varSecret.pbstrVal),
  404. -1,
  405. m_szSecret,
  406. MAX_SECRET_SIZE,
  407. NULL,
  408. NULL
  409. );
  410. if (0 == iRetVal)
  411. {
  412. IASTracePrintf (
  413. "Unable to convert client shared secret to multi-byte string "
  414. "during Client processing"
  415. );
  416. return (FALSE);
  417. }
  418. //
  419. // set secret size
  420. //
  421. m_dwSecretSize = strlen (m_szSecret);
  422. return (TRUE);
  423. } // end of CClient::SetSecret method
  424. //++--------------------------------------------------------------
  425. //
  426. // Function: SetClientName
  427. //
  428. // Synopsis: This is the CClient private method used
  429. // to set the Client SDO Name
  430. //
  431. // Arguments: VARIANT - holds the secret as a BSTR
  432. //
  433. // Returns: status
  434. //
  435. // History: MKarki Created 2/3/98
  436. //
  437. // Called By: CClient::Init method
  438. //
  439. //----------------------------------------------------------------
  440. BOOL
  441. CClient::SetClientName (
  442. VARIANT varClientName
  443. )
  444. {
  445. INT iRetVal = 0;
  446. _ASSERT (VT_BSTR == varClientName.vt);
  447. lstrcpy (m_wszClientName, (const PWCHAR)(varClientName.pbstrVal));
  448. return (TRUE);
  449. } // end of CClient::SetSecret method
  450. //++--------------------------------------------------------------
  451. //
  452. // Function: SetSignatureFlag
  453. //
  454. // Synopsis: This is the CClient private method used
  455. // to set the Client Signature flag
  456. //
  457. // Arguments: VARIANT - holds the signature as a boolean
  458. //
  459. // Returns: status
  460. //
  461. // History: MKarki Created 2/3/98
  462. //
  463. // Called By: CClient::Init method
  464. //
  465. //----------------------------------------------------------------
  466. BOOL
  467. CClient::SetSignatureFlag (
  468. VARIANT varSigFlag
  469. )
  470. {
  471. _ASSERT (VT_BOOL == varSigFlag.vt);
  472. if (0 == varSigFlag.boolVal)
  473. {
  474. m_bSignatureCheck = FALSE;
  475. }
  476. else
  477. {
  478. m_bSignatureCheck = TRUE;
  479. }
  480. return (TRUE);
  481. } // end of CClient::SetSignatureFlag method
  482. //++--------------------------------------------------------------
  483. //
  484. // Function: SetVendorType
  485. //
  486. // Synopsis: This is the CClient private method used
  487. // to set the Client Vendor Type
  488. //
  489. // Arguments: VARIANT - holds the Vendor Type
  490. //
  491. // Returns: status
  492. //
  493. // History: MKarki Created 3/16/98
  494. //
  495. // Called By: CClient::Init method
  496. //
  497. //----------------------------------------------------------------
  498. BOOL
  499. CClient::SetVendorType (
  500. VARIANT varVendorType
  501. )
  502. {
  503. _ASSERT (VT_I4 == varVendorType.vt);
  504. m_lVendorType = varVendorType.lVal;
  505. return (TRUE);
  506. } // end of CClient::SetVendorType method
  507. //++--------------------------------------------------------------
  508. //
  509. // Function: GetSecret
  510. //
  511. // Synopsis: This is the CClient public method used
  512. // to get the shared secret
  513. //
  514. // Arguments:
  515. // [out] PBYTE - Secret
  516. // [in/out] - buffer size
  517. //
  518. // Returns: HRESULT
  519. //
  520. // History: MKarki Created 9/26/97
  521. //
  522. //----------------------------------------------------------------
  523. STDMETHODIMP
  524. CClient::GetSecret(
  525. PBYTE pbySecret,
  526. PDWORD pdwSecretSize
  527. )
  528. {
  529. HRESULT hr = S_OK;
  530. _ASSERT (pdwSecretSize != NULL);
  531. //
  532. // check if there is enough space in the array
  533. // provided
  534. //
  535. if (*pdwSecretSize >= m_dwSecretSize)
  536. {
  537. _ASSERT (pbySecret != NULL);
  538. ::CopyMemory (pbySecret, m_szSecret, m_dwSecretSize);
  539. }
  540. else
  541. {
  542. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  543. }
  544. *pdwSecretSize = m_dwSecretSize;
  545. return (hr);
  546. } // end of CClient::GetSecret method
  547. //++--------------------------------------------------------------
  548. //
  549. // Function: GetAddress
  550. //
  551. // Synopsis: This is the CClient public method used
  552. // to get the address from the object
  553. //
  554. // Arguments: PDWORD
  555. //
  556. // Returns: HRESULT
  557. //
  558. // History: MKarki Created 3/20/98
  559. //
  560. // Called By: CClients::SetClients method
  561. //
  562. //----------------------------------------------------------------
  563. STDMETHODIMP
  564. CClient::GetAddress (
  565. PDWORD pdwAddress
  566. )
  567. {
  568. _ASSERT (pdwAddress);
  569. *pdwAddress = m_adwAddrList[0].ipAddress;
  570. return (S_OK);
  571. } // end of CClient::GetAddress method
  572. //++--------------------------------------------------------------
  573. //
  574. // Function: NeedSignatureCheck
  575. //
  576. // Synopsis: This is the CClient public method used
  577. // to check if signature is required
  578. //
  579. // Arguments: PBOOL
  580. //
  581. // Returns: HRESULT
  582. //
  583. // History: MKarki Created 3/20/98
  584. //
  585. // Called By:
  586. //
  587. //----------------------------------------------------------------
  588. STDMETHODIMP
  589. CClient::NeedSignatureCheck (
  590. PBOOL pbCheckNeeded
  591. )
  592. {
  593. _ASSERT (pbCheckNeeded);
  594. *pbCheckNeeded = m_bSignatureCheck;
  595. return (S_OK);
  596. } // end of CClient::NeedSignatureCheck method
  597. //++--------------------------------------------------------------
  598. //
  599. // Function: GetVendorType
  600. //
  601. // Synopsis: This is the CClient public method used
  602. // to get the VendorType from the object
  603. //
  604. // Arguments: PLONG
  605. //
  606. // Returns: HRESULT
  607. //
  608. // History: MKarki Created 3/20/98
  609. //
  610. // Called By:
  611. //
  612. //----------------------------------------------------------------
  613. STDMETHODIMP
  614. CClient::GetVendorType (
  615. PLONG plVendorType
  616. )
  617. {
  618. _ASSERT (plVendorType);
  619. *plVendorType = m_lVendorType;
  620. return (S_OK);
  621. } // end of CClient::GetAddress method