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.

4534 lines
127 KiB

  1. /*++
  2. Copyright (c) 2000, Microsoft Corporation
  3. Module Name:
  4. eapolutil.c
  5. Abstract:
  6. Tools and ends
  7. Revision History:
  8. sachins, Apr 23 2000, Created
  9. --*/
  10. #include "pcheapol.h"
  11. #pragma hdrstop
  12. //
  13. // Definitions used to read/write to registry
  14. //
  15. #define MAX_REGISTRY_VALUE_LENGTH ((64*1024) - 1)
  16. // Location of User blob
  17. #define cszEapKeyEapolUser "Software\\Microsoft\\EAPOL\\UserEapInfo"
  18. // Location of Connection blob
  19. #define cszEapKeyEapolConn "Software\\Microsoft\\EAPOL\\Parameters\\Interfaces"
  20. // Location of EAPOL Parameters Service
  21. #define cszEapKeyEapolServiceParams "Software\\Microsoft\\EAPOL\\Parameters\\General"
  22. // Location of EAPOL Global state machine params
  23. #define cszEAPOLGlobalParams "Software\\Microsoft\\EAPOL\\Parameters\\General\\Global"
  24. // Location of EAPOL Global Workspace
  25. #define cszEAPOLWorkspace "Software\\Microsoft\\EAPOL\\Parameters\\General\\Workspace"
  26. #define cszDefault "Default"
  27. #define cszDefault "Default"
  28. #define cszEapolEnabled "EapolEnabled"
  29. #define cszDefaultEAPType "DefaultEAPType"
  30. #define cszLastUsedSSID "LastUsedSSID"
  31. #define cszInterfaceList "InterfaceList"
  32. #define cszAuthPeriod "authPeriod"
  33. #define cszHeldPeriod "heldPeriod"
  34. #define cszStartPeriod "startPeriod"
  35. #define cszMaxStart "maxStart"
  36. #define cszLastModifiedGUID "LastModifiedGUID"
  37. //
  38. // Definitions and structures used in creating default EAP-TLS connection
  39. // blob in the registry
  40. //
  41. #define EAPTLS_CONN_FLAG_REGISTRY 0x00000001
  42. #define EAPTLS_CONN_FLAG_NO_VALIDATE_CERT 0x00000002
  43. #define EAPTLS_CONN_FLAG_NO_VALIDATE_NAME 0x00000004
  44. typedef struct _EAPTLS_CONN_PROPERTIES
  45. {
  46. DWORD dwVersion;
  47. DWORD dwSize;
  48. DWORD fFlags;
  49. //EAPTLS_HASH Hash;
  50. DWORD cbHash;
  51. BYTE pbHash[20]; // MAX_HASH_SIZE = 20
  52. WCHAR awszServerName[1];
  53. } EAPTLS_CONN_PROPERTIES, *PEAPTLS_CONN_PROPERTIES;
  54. #define PASSWORDMAGIC 0xA5
  55. //
  56. // HostToWireFormat16
  57. //
  58. // Description:
  59. //
  60. // Will convert a 16 bit integer from host format to wire format
  61. //
  62. VOID
  63. HostToWireFormat16 (
  64. IN WORD wHostFormat,
  65. IN OUT PBYTE pWireFormat
  66. )
  67. {
  68. *((PBYTE)(pWireFormat)+0) = (BYTE) ((DWORD)(wHostFormat) >> 8);
  69. *((PBYTE)(pWireFormat)+1) = (BYTE) (wHostFormat);
  70. }
  71. //
  72. // WireToHostFormat16
  73. //
  74. // Description:
  75. //
  76. // Will convert a 16 bit integer from wire format to host format
  77. //
  78. WORD
  79. WireToHostFormat16 (
  80. IN PBYTE pWireFormat
  81. )
  82. {
  83. WORD wHostFormat = ((*((PBYTE)(pWireFormat)+0) << 8) +
  84. (*((PBYTE)(pWireFormat)+1)));
  85. return( wHostFormat );
  86. }
  87. //
  88. // HostToWireFormat32
  89. //
  90. // Description:
  91. //
  92. // Will convert a 32 bit integer from host format to wire format
  93. //
  94. VOID
  95. HostToWireFormat32 (
  96. IN DWORD dwHostFormat,
  97. IN OUT PBYTE pWireFormat
  98. )
  99. {
  100. *((PBYTE)(pWireFormat)+0) = (BYTE) ((DWORD)(dwHostFormat) >> 24);
  101. *((PBYTE)(pWireFormat)+1) = (BYTE) ((DWORD)(dwHostFormat) >> 16);
  102. *((PBYTE)(pWireFormat)+2) = (BYTE) ((DWORD)(dwHostFormat) >> 8);
  103. *((PBYTE)(pWireFormat)+3) = (BYTE) (dwHostFormat);
  104. }
  105. //
  106. // WireToHostFormat32
  107. //
  108. // Description:
  109. //
  110. // Will convert a 32 bit integer from wire format to host format
  111. //
  112. DWORD
  113. WireToHostFormat32 (
  114. IN PBYTE pWireFormat
  115. )
  116. {
  117. DWORD dwHostFormat = ((*((PBYTE)(pWireFormat)+0) << 24) +
  118. (*((PBYTE)(pWireFormat)+1) << 16) +
  119. (*((PBYTE)(pWireFormat)+2) << 8) +
  120. (*((PBYTE)(pWireFormat)+3) ));
  121. return( dwHostFormat );
  122. }
  123. //
  124. // ElSetCustomAuthData
  125. //
  126. // Description:
  127. //
  128. // Function called to set the connection data for an interface for a specific
  129. // EAP type and SSID (if any). Data will be stored in the HKLM hive
  130. //
  131. // Arguments:
  132. // pszGUID - pointer to GUID string for the interface
  133. // dwEapTypeId - EAP type for which connection data is to be stored
  134. // pszSSID - Special identifier, if any, for the EAP blob
  135. // pbConnInfo - pointer to EAP connection data blob
  136. // dwInfoSize - Size of EAP connection blob
  137. //
  138. // Return values:
  139. // NO_ERROR - success
  140. // non-zero - error
  141. //
  142. // ISSUE:
  143. // Can we optimize the key openings??? Only open 1 key somehow?
  144. DWORD
  145. ElSetCustomAuthData (
  146. IN CHAR *pszGUID,
  147. IN DWORD dwEapTypeId,
  148. IN CHAR *pszSSID,
  149. IN PBYTE pbConnInfo,
  150. IN DWORD dwInfoSize
  151. )
  152. {
  153. HKEY hkey = NULL;
  154. HKEY hkey1 = NULL;
  155. HKEY hkey2 = NULL;
  156. DWORD dwDisposition;
  157. CHAR szEapTypeId[4]; // EapTypeId can be max 256 + 1 for null char
  158. LONG lError = ERROR_SUCCESS;
  159. DWORD dwRetCode = ERROR_SUCCESS;
  160. do
  161. {
  162. // Validate input params
  163. if (pszGUID == NULL)
  164. {
  165. TRACE0 (ANY, "ElSetCustomAuthData: GUID = NULL");
  166. break;
  167. }
  168. if (dwEapTypeId == 0)
  169. {
  170. TRACE0 (ANY, "ElSetCustomAuthData: GUID = NULL");
  171. break;
  172. }
  173. if ((pbConnInfo == NULL) || (dwInfoSize <= 0))
  174. {
  175. TRACE0 (ANY, "ElSetCustomAuthData: Invalid blob data");
  176. break;
  177. }
  178. // Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
  179. if ((lError = RegCreateKeyExA (
  180. HKEY_LOCAL_MACHINE,
  181. cszEapKeyEapolConn,
  182. 0,
  183. NULL,
  184. REG_OPTION_NON_VOLATILE,
  185. KEY_WRITE,
  186. NULL,
  187. &hkey,
  188. &dwDisposition)) != ERROR_SUCCESS)
  189. {
  190. TRACE1 (ANY, "ElSetCustomAuthData: Error in RegCreateKeyExA for base key, %ld",
  191. lError);
  192. dwRetCode = (DWORD)lError;
  193. break;
  194. }
  195. // Get handle to HKLM\Software\...\Interfaces\<GUID>
  196. if ((lError = RegCreateKeyExA (
  197. hkey,
  198. pszGUID,
  199. 0,
  200. NULL,
  201. REG_OPTION_NON_VOLATILE,
  202. KEY_WRITE,
  203. NULL,
  204. &hkey1,
  205. &dwDisposition)) != ERROR_SUCCESS)
  206. {
  207. TRACE1 (ANY, "ElSetCustomAuthData: Error in RegCreateKeyExA for GUID, %ld",
  208. lError);
  209. dwRetCode = (DWORD)lError;
  210. break;
  211. }
  212. _ltoa(dwEapTypeId, szEapTypeId, 10);
  213. // Get handle to HKLM\Software\...\Interfaces\<GUID>\<EapTypeId>
  214. if ((lError = RegCreateKeyExA (
  215. hkey1,
  216. szEapTypeId,
  217. 0,
  218. NULL,
  219. REG_OPTION_NON_VOLATILE,
  220. KEY_WRITE,
  221. NULL,
  222. &hkey2,
  223. &dwDisposition)) != ERROR_SUCCESS)
  224. {
  225. TRACE1 (ANY, "ElSetCustomAuthData: Error in RegCreateKeyExA for EapTypeId, %ld",
  226. lError);
  227. dwRetCode = (DWORD)lError;
  228. break;
  229. }
  230. // If no SSID is supplied, set the blob as value for "Default"
  231. if (pszSSID == NULL)
  232. {
  233. pszSSID = cszDefault;
  234. }
  235. //
  236. // Set the value of ..\Interfaces\GUID\<EAPTypeId>\(<SSID> or default)
  237. // key
  238. if ((lError = RegSetValueExA (
  239. hkey2,
  240. pszSSID,
  241. 0,
  242. REG_BINARY,
  243. pbConnInfo,
  244. dwInfoSize)) != ERROR_SUCCESS)
  245. {
  246. TRACE1 (ANY, "ElSetCustomAuthData: Error in RegSetValueExA for SSID, %ld",
  247. lError);
  248. dwRetCode = (DWORD)lError;
  249. break;
  250. }
  251. TRACE0 (ANY, "ElSetCustomAuthData: Set value succeeded");
  252. } while (FALSE);
  253. if (hkey != NULL)
  254. {
  255. RegCloseKey (hkey);
  256. }
  257. if (hkey1 != NULL)
  258. {
  259. RegCloseKey (hkey1);
  260. }
  261. if (hkey2 != NULL)
  262. {
  263. RegCloseKey (hkey2);
  264. }
  265. return dwRetCode;
  266. }
  267. //
  268. // ElGetCustomAuthData
  269. //
  270. // Description:
  271. //
  272. // Function called to retrieve the connection data for an interface for a
  273. // specific EAP type and SSID (if any). Data is retrieved from the HKLM hive
  274. //
  275. // Arguments:
  276. //
  277. // pszGUID - pointer to GUID string for the interface
  278. // dwEapTypeId - EAP type for which connection data is to be retrieved
  279. // pszSSID - Special identifier if any for the EAP blob
  280. // pbUserInfo - output: pointer to EAP connection data blob
  281. // dwInfoSize - output: pointer to size of EAP connection blob
  282. //
  283. // Return values:
  284. //
  285. // NO_ERROR - success
  286. // non-zero - error
  287. //
  288. DWORD
  289. ElGetCustomAuthData (
  290. IN CHAR *pszGUID,
  291. IN DWORD dwEapTypeId,
  292. IN CHAR *pszSSID,
  293. IN OUT BYTE *pbConnInfo,
  294. IN OUT DWORD *pdwInfoSize
  295. )
  296. {
  297. HKEY hkey = NULL;
  298. HKEY hkey1 = NULL;
  299. HKEY hkey2 = NULL;
  300. PBYTE pbInfo = NULL;
  301. DWORD dwInfoSize = 0;
  302. DWORD dwType = 0;
  303. CHAR szEapTypeId[4]; // EapTypeId can be max 256 + 1 for null char
  304. LONG lError = ERROR_SUCCESS;
  305. DWORD dwRetCode = ERROR_SUCCESS;
  306. do
  307. {
  308. // Validate input params
  309. if (pszGUID == NULL)
  310. {
  311. TRACE0 (ANY, "ElGetCustomAuthData: GUID = NULL");
  312. break;
  313. }
  314. if (dwEapTypeId == 0)
  315. {
  316. TRACE0 (ANY, "ElGetCustomAuthData: GUID = NULL");
  317. break;
  318. }
  319. // Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
  320. if ((lError = RegOpenKeyExA (
  321. HKEY_LOCAL_MACHINE,
  322. cszEapKeyEapolConn,
  323. 0,
  324. KEY_READ,
  325. &hkey
  326. )) != ERROR_SUCCESS)
  327. {
  328. TRACE1 (ANY, "ElGetCustomAuthData: Error in RegOpenKeyExA for base key, %ld",
  329. lError);
  330. dwRetCode = (DWORD)lError;
  331. break;
  332. }
  333. // Get handle to HKLM\Software\...\Interfaces\<GUID>
  334. if ((lError = RegOpenKeyExA (
  335. hkey,
  336. pszGUID,
  337. 0,
  338. KEY_READ,
  339. &hkey1
  340. )) != ERROR_SUCCESS)
  341. {
  342. TRACE1 (ANY, "ElGetCustomAuthData: Error in RegOpenKeyExA for GUID, %ld",
  343. lError);
  344. dwRetCode = (DWORD)lError;
  345. break;
  346. }
  347. _ltoa(dwEapTypeId, szEapTypeId, 10);
  348. // Get handle to HKLM\Software\...\Interfaces\<GUID>\<EapTypeId>
  349. if ((lError = RegOpenKeyExA (
  350. hkey1,
  351. szEapTypeId,
  352. 0,
  353. KEY_READ,
  354. &hkey2
  355. )) != ERROR_SUCCESS)
  356. {
  357. TRACE1 (ANY, "ElGetCustomAuthData: Error in RegOpenKeyExA for EapTypeId, %ld",
  358. lError);
  359. dwRetCode = (DWORD)lError;
  360. break;
  361. }
  362. // If no SSID is supplied, set the blob as value for "Default"
  363. if (pszSSID == NULL)
  364. {
  365. pszSSID = cszDefault;
  366. }
  367. // Get the value of ..\Interfaces\GUID\<EAPType>\(<SSID> or default)
  368. // key
  369. if ((lError = RegQueryValueExA (
  370. hkey2,
  371. pszSSID,
  372. 0,
  373. &dwType,
  374. NULL,
  375. &dwInfoSize)) != ERROR_SUCCESS)
  376. {
  377. TRACE1 (ANY, "ElGetCustomAuthData: Error in RegQueryValueExA for size estimation for SSID, %ld",
  378. lError);
  379. // If pszSSID is "Default" and we cannot read the value for
  380. // the key, bail out
  381. if (!strcmp(pszSSID, cszDefault))
  382. {
  383. dwRetCode = (DWORD)lError;
  384. break;
  385. }
  386. else
  387. {
  388. // Second try with pszSSID = cszDefault
  389. TRACE0 (ANY, "ElGetCustomAuthData: Second try for size estimation with SSID = Default");
  390. pszSSID = cszDefault;
  391. if ((lError = RegQueryValueExA (
  392. hkey2,
  393. pszSSID,
  394. 0,
  395. &dwType,
  396. NULL,
  397. &dwInfoSize)) != ERROR_SUCCESS)
  398. {
  399. TRACE1 (ANY, "ElGetCustomAuthData: Error in RegQueryValueExA for SSID=Default, 2nd try , %ld",
  400. lError);
  401. dwRetCode = (DWORD)lError;
  402. break;
  403. }
  404. }
  405. }
  406. // Data can be read
  407. pbInfo = MALLOC (dwInfoSize);
  408. if (pbInfo == NULL)
  409. {
  410. TRACE0 (ANY, "ElGetCustomAuthData: Error in memory allocation");
  411. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  412. break;
  413. }
  414. if ((lError = RegQueryValueExA (
  415. hkey2,
  416. pszSSID,
  417. 0,
  418. &dwType,
  419. pbInfo,
  420. &dwInfoSize)) != ERROR_SUCCESS)
  421. {
  422. TRACE2 (ANY, "ElGetCustomAuthData: Error in RegQueryValueExA for SSID = %s, %ld",
  423. pszSSID, lError);
  424. dwRetCode = (DWORD)lError;
  425. break;
  426. }
  427. TRACE1 (ANY, "ElGetCustomAuthData: Succeeded: Data size = %ld",
  428. dwInfoSize);
  429. } while (FALSE);
  430. if (hkey != NULL)
  431. {
  432. RegCloseKey (hkey);
  433. }
  434. if (hkey1 != NULL)
  435. {
  436. RegCloseKey (hkey1);
  437. }
  438. if (hkey2 != NULL)
  439. {
  440. RegCloseKey (hkey2);
  441. }
  442. // check if caller has allocated enough memory
  443. // to hold the info
  444. if ((pbConnInfo != NULL) && (*pdwInfoSize >= dwInfoSize))
  445. {
  446. memcpy ((VOID *)pbConnInfo, (VOID *)pbInfo, dwInfoSize);
  447. }
  448. else
  449. {
  450. dwRetCode = ERROR_BUFFER_TOO_SMALL;
  451. }
  452. *pdwInfoSize = dwInfoSize;
  453. // Free the memory allocated for holding blob
  454. if (pbInfo != NULL)
  455. {
  456. FREE (pbInfo);
  457. pbInfo = NULL;
  458. }
  459. return dwRetCode;
  460. }
  461. //
  462. // ElSetEapUserInfo
  463. //
  464. // Description:
  465. //
  466. // Function called to store the user data for an interface for a
  467. // specific EAP type and SSID (if any). Data is stored in the HKCU hive.
  468. // In case of EAP-TLS, this data will be the hash blob of the certificate
  469. // chosen for the last successful authentication.
  470. //
  471. // Arguments:
  472. //
  473. // hToken - Handle to token for the logged on user
  474. // pszGUID - pointer to GUID string for the interface
  475. // dwEapTypeId - EAP type for which user data is to be stored
  476. // pszSSID - Special identifier if any for the EAP user blob
  477. // pbUserInfo - pointer to EAP user data blob
  478. // dwInfoSize - Size of EAP user blob
  479. //
  480. //
  481. // Return values:
  482. // NO_ERROR - success
  483. // non-zero - error
  484. //
  485. DWORD
  486. ElSetEapUserInfo (
  487. IN HANDLE hToken,
  488. IN CHAR *pszGUID,
  489. IN DWORD dwEapTypeId,
  490. IN CHAR *pszSSID,
  491. IN PBYTE pbUserInfo,
  492. IN DWORD dwInfoSize
  493. )
  494. {
  495. HKEY hkey = NULL;
  496. HKEY hkey1 = NULL;
  497. HKEY hkey2 = NULL;
  498. HKEY hkey3 = NULL;
  499. DWORD dwDisposition;
  500. CHAR szEapTypeId[4]; // EapTypeId can be max 256 + 1 for null char
  501. LONG lError = ERROR_SUCCESS;
  502. DWORD dwRetCode = ERROR_SUCCESS;
  503. do
  504. {
  505. // Validate input params
  506. if (hToken == NULL)
  507. {
  508. TRACE0 (ANY, "ElSetEapUserInfo: User Token = NULL");
  509. break;
  510. }
  511. if (pszGUID == NULL)
  512. {
  513. TRACE0 (ANY, "ElSetEapUserInfo: GUID = NULL");
  514. break;
  515. }
  516. if (dwEapTypeId == 0)
  517. {
  518. TRACE0 (ANY, "ElSetEapUserInfo: GUID = NULL");
  519. break;
  520. }
  521. if ((pbUserInfo == NULL) || (dwInfoSize <= 0))
  522. {
  523. TRACE0 (ANY, "ElSetEapUserInfo: Invalid blob data");
  524. break;
  525. }
  526. // Get handle to HKCU
  527. if ((dwRetCode = ElGetEapKeyFromToken (
  528. hToken,
  529. &hkey)) != NO_ERROR)
  530. {
  531. TRACE1 (ANY, "ElSetEapUserInfo: Error in ElGetEapKeyFromToken %ld",
  532. dwRetCode);
  533. break;
  534. }
  535. if ((lError = RegCreateKeyExA (
  536. hkey,
  537. cszEapKeyEapolUser,
  538. 0,
  539. NULL,
  540. REG_OPTION_NON_VOLATILE,
  541. KEY_WRITE,
  542. NULL,
  543. &hkey1,
  544. &dwDisposition)) != ERROR_SUCCESS)
  545. {
  546. TRACE1 (ANY, "ElSetEapUserInfo: Error in RegCreateKeyExA for base key, %ld",
  547. lError);
  548. dwRetCode = (DWORD)lError;
  549. break;
  550. }
  551. // Get handle to HKCU\Software\...\UserEapInfo\<GUID>
  552. if ((lError = RegCreateKeyExA (
  553. hkey1,
  554. pszGUID,
  555. 0,
  556. NULL,
  557. REG_OPTION_NON_VOLATILE,
  558. KEY_WRITE,
  559. NULL,
  560. &hkey2,
  561. &dwDisposition)) != ERROR_SUCCESS)
  562. {
  563. TRACE1 (ANY, "ElSetEapUserInfo: Error in RegCreateKeyExA for GUID, %ld",
  564. lError);
  565. dwRetCode = (DWORD)lError;
  566. break;
  567. }
  568. _ltoa(dwEapTypeId, szEapTypeId, 10);
  569. // Get handle to HKCU\Software\...\UserEapInfo\<GUID>\<EAPTypeId>
  570. if ((lError = RegCreateKeyExA (
  571. hkey2,
  572. szEapTypeId,
  573. 0,
  574. NULL,
  575. REG_OPTION_NON_VOLATILE,
  576. KEY_WRITE,
  577. NULL,
  578. &hkey3,
  579. &dwDisposition)) != ERROR_SUCCESS)
  580. {
  581. TRACE1 (ANY, "ElSetEapUserInfo: Error in RegCreateKeyExA for EapTypeId, %ld",
  582. lError);
  583. dwRetCode = (DWORD)lError;
  584. break;
  585. }
  586. // If no SSID is supplied, set the blob as value for "Default"
  587. if (pszSSID == NULL)
  588. {
  589. pszSSID = cszDefault;
  590. }
  591. // Set value of ...\UserEapInfo\<GUID>\<EAPTypeId>\(<SSID> or default)
  592. // key
  593. if ((lError = RegSetValueExA (
  594. hkey3,
  595. pszSSID,
  596. 0,
  597. REG_BINARY,
  598. pbUserInfo,
  599. dwInfoSize)) != ERROR_SUCCESS)
  600. {
  601. TRACE2 (ANY, "ElSetEapUserInfo: Error in RegSetValueExA for SSID = %s, %ld",
  602. pszSSID, lError);
  603. dwRetCode = (DWORD)lError;
  604. break;
  605. }
  606. TRACE0 (ANY, "ElSetEapUserInfo: Set value succeeded");
  607. } while (FALSE);
  608. if (hkey != NULL)
  609. {
  610. RegCloseKey (hkey);
  611. }
  612. if (hkey1 != NULL)
  613. {
  614. RegCloseKey (hkey1);
  615. }
  616. if (hkey2 != NULL)
  617. {
  618. RegCloseKey (hkey2);
  619. }
  620. if (hkey3 != NULL)
  621. {
  622. RegCloseKey (hkey3);
  623. }
  624. return dwRetCode;
  625. }
  626. //
  627. // ElGetEapUserInfo
  628. //
  629. // Description:
  630. //
  631. // Function called to retrieve the user data for an interface for a
  632. // specific EAP type and SSID (if any). Data is retrieved from the HKCU hive
  633. //
  634. // Arguments:
  635. // hToken - Handle to token for the logged on user
  636. // pszGUID - pointer to GUID string for the interface
  637. // dwEapTypeId - EAP type for which user data is to be stored
  638. // pszSSID - Special identifier if any for the EAP user blob
  639. // pbUserInfo - output: pointer to EAP user data blob
  640. // dwInfoSize - output: pointer to size of EAP user blob
  641. //
  642. // Return values:
  643. // NO_ERROR - success
  644. // non-zero - error
  645. //
  646. DWORD
  647. ElGetEapUserInfo (
  648. IN HANDLE hToken,
  649. IN CHAR *pszGUID,
  650. IN DWORD dwEapTypeId,
  651. IN CHAR *pszSSID,
  652. IN OUT PBYTE pbUserInfo,
  653. IN OUT DWORD *pdwInfoSize
  654. )
  655. {
  656. HKEY hkey = NULL;
  657. HKEY hkey1 = NULL;
  658. HKEY hkey2 = NULL;
  659. HKEY hkey3 = NULL;
  660. PBYTE pbInfo = NULL;
  661. DWORD dwInfoSize = 0;
  662. DWORD dwType = 0;
  663. CHAR szEapTypeId[4]; // EapTypeId can be max 256 + 1 for null char
  664. LONG lError = ERROR_SUCCESS;
  665. DWORD dwRetCode = ERROR_SUCCESS;
  666. do
  667. {
  668. // Validate input params
  669. if (pszGUID == NULL)
  670. {
  671. TRACE0 (ANY, "ElGetEapUserInfo: GUID = NULL");
  672. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  673. break;
  674. }
  675. if (dwEapTypeId == 0)
  676. {
  677. TRACE0 (ANY, "ElGetEapUserInfo: GUID = NULL");
  678. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  679. break;
  680. }
  681. // Get handle to HKCU
  682. if ((dwRetCode = ElGetEapKeyFromToken (
  683. hToken,
  684. &hkey)) != NO_ERROR)
  685. {
  686. TRACE1 (ANY, "ElGetEapUserInfo: Error in ElGetEapKeyFromToken %ld",
  687. dwRetCode);
  688. break;
  689. }
  690. // Get handle to HKCU\Software\...\UserEapInfo\<GUID>
  691. if ((lError = RegOpenKeyExA (
  692. hkey,
  693. cszEapKeyEapolUser,
  694. 0,
  695. KEY_READ,
  696. &hkey1
  697. )) != ERROR_SUCCESS)
  698. {
  699. TRACE1 (ANY, "ElGetEapUserInfo: Error in RegOpenKeyExA for base key, %ld",
  700. lError);
  701. dwRetCode = (DWORD)lError;
  702. break;
  703. }
  704. // Get handle to HKCU\Software\...\UserEapInfo\<GUID>
  705. if ((lError = RegOpenKeyExA (
  706. hkey1,
  707. pszGUID,
  708. 0,
  709. KEY_READ,
  710. &hkey2
  711. )) != ERROR_SUCCESS)
  712. {
  713. TRACE1 (ANY, "ElGetEapUserInfo: Error in RegOpenKeyExA for GUID, %ld",
  714. lError);
  715. dwRetCode = (DWORD)lError;
  716. break;
  717. }
  718. _ltoa(dwEapTypeId, szEapTypeId, 10);
  719. // Get handle to HKCU\Software\...\UserEapInfo\<GUID>\<EAPTypeId>
  720. if ((lError = RegOpenKeyExA (
  721. hkey2,
  722. szEapTypeId,
  723. 0,
  724. KEY_READ,
  725. &hkey3
  726. )) != ERROR_SUCCESS)
  727. {
  728. TRACE1 (ANY, "ElGetEapUserInfo: Error in RegOpenKeyExA for EapTypeId, %ld",
  729. lError);
  730. dwRetCode = (DWORD)lError;
  731. break;
  732. }
  733. // If no SSID is supplied, set the blob as value for "Default"
  734. if (pszSSID == NULL)
  735. {
  736. pszSSID = cszDefault;
  737. }
  738. // Get value of ...\UserEapInfo\<GUID>\<EAPTypeId>\(<SSID> or default)
  739. // key
  740. if ((lError = RegQueryValueExA (
  741. hkey3,
  742. pszSSID,
  743. 0,
  744. &dwType,
  745. NULL,
  746. &dwInfoSize)) != ERROR_SUCCESS)
  747. {
  748. TRACE1 (ANY, "ElGetEapUserInfo: Error in RegQueryValueExA for size estimation for SSID, %ld",
  749. lError);
  750. // If pszSSID is "Default" and we cannot read the value for
  751. // the key, bail out
  752. if (!strcmp(pszSSID, cszDefault))
  753. {
  754. dwRetCode = (DWORD)lError;
  755. break;
  756. }
  757. else
  758. {
  759. // Second try with pszSSID = cszDefault
  760. TRACE0 (ANY, "ElGetEapUserInfo: Second try for size estimation with SSID = Default");
  761. pszSSID = cszDefault;
  762. if ((lError = RegQueryValueExA (
  763. hkey3,
  764. pszSSID,
  765. 0,
  766. &dwType,
  767. NULL,
  768. &dwInfoSize)) != ERROR_SUCCESS)
  769. {
  770. TRACE1 (ANY, "ElGetEapUserInfo: Error in RegOpenKeyExA for SSID=Default in 2nd try , %ld",
  771. lError);
  772. dwRetCode = (DWORD)lError;
  773. break;
  774. }
  775. }
  776. }
  777. // Data can be read
  778. pbInfo = MALLOC (dwInfoSize);
  779. if (pbInfo == NULL)
  780. {
  781. TRACE0 (ANY, "ElGetEapUserInfo: Error in memory allocation");
  782. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  783. break;
  784. }
  785. if ((lError = RegQueryValueExA (
  786. hkey3,
  787. pszSSID,
  788. 0,
  789. &dwType,
  790. pbInfo,
  791. &dwInfoSize)) != ERROR_SUCCESS)
  792. {
  793. TRACE1 (ANY, "ElGetEapUserInfo: Error in RegQueryValueExA, %ld",
  794. lError);
  795. dwRetCode = (DWORD)lError;
  796. break;
  797. }
  798. TRACE0 (ANY, "ElGetEapUserInfo: Get value succeeded");
  799. } while (FALSE);
  800. // Close all the open registry keys
  801. if (hkey != NULL)
  802. {
  803. RegCloseKey (hkey);
  804. }
  805. if (hkey1 != NULL)
  806. {
  807. RegCloseKey (hkey1);
  808. }
  809. if (hkey2 != NULL)
  810. {
  811. RegCloseKey (hkey2);
  812. }
  813. if (hkey3 != NULL)
  814. {
  815. RegCloseKey (hkey3);
  816. }
  817. if (dwRetCode == ERROR_SUCCESS)
  818. {
  819. // check if caller has allocated enough memory
  820. // to hold the info
  821. if ((pbUserInfo != NULL) && (*pdwInfoSize >= dwInfoSize))
  822. {
  823. memcpy ((VOID *)pbUserInfo, (VOID *)pbInfo, dwInfoSize);
  824. }
  825. else
  826. {
  827. // Else just return the size of the blob but not the blob
  828. dwRetCode = ERROR_BUFFER_TOO_SMALL;
  829. }
  830. *pdwInfoSize = dwInfoSize;
  831. }
  832. // Free the memory allocated for holding blob
  833. if (pbInfo != NULL)
  834. {
  835. FREE (pbInfo);
  836. }
  837. return dwRetCode;
  838. }
  839. //
  840. // ElGetInterfaceParams
  841. //
  842. // Description:
  843. //
  844. // Function called to retrieve the EAPOL parameters for an interface, stored
  845. // in the HKLM hive.
  846. //
  847. // Arguments:
  848. //
  849. // pszGUID - pointer to GUID string for the interface
  850. // pdwDefaultEAPType - output: Pointer to default EAP type for interface
  851. // pszLastUsedSSID - output: Pointer to last used SSID for the interface
  852. // pdwEapolEnabled - output: Is EAPOL enabled for the interface?
  853. //
  854. // Return values:
  855. // NO_ERROR - success
  856. // non-zero - error
  857. //
  858. DWORD
  859. ElGetInterfaceParams (
  860. IN CHAR *pszGUID,
  861. IN OUT DWORD *pdwDefaultEAPType,
  862. IN OUT CHAR *pszLastUsedSSID,
  863. IN OUT DWORD *pdwEapolEnabled
  864. )
  865. {
  866. HKEY hkey = NULL;
  867. HKEY hkey1 = NULL;
  868. DWORD dwInfoSize = 0;
  869. DWORD dwType = 0;
  870. BYTE bValueBuffer[256];
  871. LONG lError = ERROR_SUCCESS;
  872. DWORD dwRetCode = ERROR_SUCCESS;
  873. do
  874. {
  875. // Validate input params
  876. if (pszGUID == NULL)
  877. {
  878. TRACE0 (ANY, "ElGetInterfaceParams: GUID = NULL");
  879. break;
  880. }
  881. TRACE1 (ANY, "ElGetInterfaceParams: Getting stuff from registry for %s", pszGUID);
  882. // Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
  883. if ((lError = RegOpenKeyExA (
  884. HKEY_LOCAL_MACHINE,
  885. cszEapKeyEapolConn,
  886. 0,
  887. KEY_READ,
  888. &hkey
  889. )) != ERROR_SUCCESS)
  890. {
  891. TRACE1 (ANY, "ElGetInterfaceParams: Error in RegOpenKeyExA for base key, %ld",
  892. lError);
  893. dwRetCode = (DWORD)lError;
  894. break;
  895. }
  896. // Get handle to HKLM\Software\...\Interfaces\<GUID>
  897. if ((lError = RegOpenKeyExA (
  898. hkey,
  899. pszGUID,
  900. 0,
  901. KEY_READ,
  902. &hkey1
  903. )) != ERROR_SUCCESS)
  904. {
  905. TRACE1 (ANY, "ElGetInterfaceParams: Error in RegOpenKeyExA for GUID, %ld",
  906. lError);
  907. dwRetCode = (DWORD)lError;
  908. break;
  909. }
  910. // Get the value of ..\Interfaces\GUID\EapolEnabled
  911. dwInfoSize = sizeof(DWORD);
  912. if ((lError = RegQueryValueExA (
  913. hkey1,
  914. cszEapolEnabled,
  915. 0,
  916. &dwType,
  917. (BYTE *)pdwEapolEnabled,
  918. &dwInfoSize)) != ERROR_SUCCESS)
  919. {
  920. TRACE2 (ANY, "ElGetInterfaceParams: Error in RegQueryValueExA for EapolEnabled, %ld, InfoSize=%ld",
  921. lError, dwInfoSize);
  922. *pdwEapolEnabled = DEFAULT_EAPOL_STATE;
  923. }
  924. TRACE1 (ANY, "ElGetInterfaceParams: Got EapolEnabled = %ld", *pdwEapolEnabled);
  925. // Get the value of ..\Interfaces\GUID\DefaultEAPType
  926. dwInfoSize = sizeof(DWORD);
  927. if ((lError = RegQueryValueExA (
  928. hkey1,
  929. cszDefaultEAPType,
  930. 0,
  931. &dwType,
  932. (BYTE *)pdwDefaultEAPType,
  933. &dwInfoSize)) != ERROR_SUCCESS)
  934. {
  935. TRACE2 (ANY, "ElGetInterfaceParams: Error in RegQueryValueExA for DefaultEAPType, %ld, InfoSize=%ld",
  936. lError, dwInfoSize);
  937. *pdwDefaultEAPType = DEFAULT_EAP_TYPE;
  938. }
  939. TRACE1 (ANY, "ElGetInterfaceParams: Got DefaultEAPType = %ld", *pdwDefaultEAPType);
  940. // Get the value of ..\Interfaces\GUID\LastUsedSSID
  941. dwInfoSize = 256;
  942. if ((lError = RegQueryValueExA (
  943. hkey1,
  944. cszLastUsedSSID,
  945. 0,
  946. &dwType,
  947. (PUCHAR)pszLastUsedSSID,
  948. &dwInfoSize)) != ERROR_SUCCESS)
  949. {
  950. TRACE1 (ANY, "ElGetInterfaceParams: Error in RegQueryValueExA for LastUsedSSID, %ld",
  951. lError);
  952. pszLastUsedSSID = NULL;
  953. }
  954. } while (FALSE);
  955. if (hkey != NULL)
  956. {
  957. RegCloseKey (hkey);
  958. }
  959. if (hkey1 != NULL)
  960. {
  961. RegCloseKey (hkey1);
  962. }
  963. return dwRetCode;
  964. }
  965. //
  966. // ElSetInterfaceParams
  967. //
  968. // Description:
  969. //
  970. // Function called to set the EAPOL parameters for an interface, in the HKLM
  971. // hive
  972. //
  973. // Arguments:
  974. //
  975. // pszGUID - Pointer to GUID string for the interface
  976. // pdwDefaultEAPType - default EAP type for interface
  977. // pszLastUsedSSID - SSID that was received in the last EAP-Request/Identity
  978. // packet
  979. // pdwEapolEnabled - Is EAPOL enabled for the interface
  980. //
  981. // Return values:
  982. // NO_ERROR - success
  983. // non-zero - error
  984. //
  985. //
  986. DWORD
  987. ElSetInterfaceParams (
  988. IN CHAR *pszGUID,
  989. IN DWORD *pdwDefaultEAPType,
  990. IN CHAR *pszLastUsedSSID,
  991. IN DWORD *pdwEapolEnabled
  992. )
  993. {
  994. HKEY hkey = NULL;
  995. HKEY hkey1 = NULL;
  996. DWORD dwInfoSize = 0;
  997. DWORD dwType = 0;
  998. LONG lError = ERROR_SUCCESS;
  999. DWORD dwRetCode = ERROR_SUCCESS;
  1000. do
  1001. {
  1002. // Validate input params
  1003. if (pszGUID == NULL)
  1004. {
  1005. TRACE0 (ANY, "ElSetInterfaceParams: GUID = NULL");
  1006. break;
  1007. }
  1008. TRACE1 (ANY, "Setting stuff from registry for %s", pszGUID);
  1009. // Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
  1010. if ((lError = RegOpenKeyExA (
  1011. HKEY_LOCAL_MACHINE,
  1012. cszEapKeyEapolConn,
  1013. 0,
  1014. KEY_WRITE,
  1015. &hkey
  1016. )) != ERROR_SUCCESS)
  1017. {
  1018. TRACE1 (ANY, "ElSetInterfaceParams: Error in RegOpenKeyExA for base key, %ld",
  1019. lError);
  1020. dwRetCode = (DWORD)lError;
  1021. break;
  1022. }
  1023. // Get handle to HKLM\Software\...\Interfaces\<GUID>
  1024. if ((lError = RegOpenKeyExA (
  1025. hkey,
  1026. pszGUID,
  1027. 0,
  1028. KEY_WRITE,
  1029. &hkey1
  1030. )) != ERROR_SUCCESS)
  1031. {
  1032. TRACE1 (ANY, "ElSetInterfaceParams: Error in RegOpenKeyExA for GUID, %ld",
  1033. lError);
  1034. dwRetCode = (DWORD)lError;
  1035. break;
  1036. }
  1037. // Set the value of ..\Interfaces\GUID\EapolEnabled
  1038. if ((lError = RegSetValueExA (
  1039. hkey1,
  1040. cszEapolEnabled,
  1041. 0,
  1042. REG_DWORD,
  1043. (BYTE *)pdwEapolEnabled,
  1044. sizeof(DWORD))) != ERROR_SUCCESS)
  1045. {
  1046. TRACE1 (ANY, "ElSetInterfaceParams: Error in RegSetValueExA for EapolEnabled, %ld",
  1047. lError);
  1048. }
  1049. // Set the value of ..\Interfaces\GUID\DefaultEAPType
  1050. if ((lError = RegSetValueExA (
  1051. hkey1,
  1052. cszDefaultEAPType,
  1053. 0,
  1054. REG_DWORD,
  1055. (BYTE *)pdwDefaultEAPType,
  1056. sizeof(DWORD))) != ERROR_SUCCESS)
  1057. {
  1058. TRACE1 (ANY, "ElSetInterfaceParams: Error in RegSetValueExA for DefaultEAPType, %ld",
  1059. lError);
  1060. }
  1061. // Set the value of ..\Interfaces\GUID\LastUsedSSID
  1062. if ((lError = RegSetValueExA (
  1063. hkey1,
  1064. cszLastUsedSSID,
  1065. 0,
  1066. REG_SZ,
  1067. pszLastUsedSSID,
  1068. strlen(pszLastUsedSSID))) != ERROR_SUCCESS)
  1069. {
  1070. TRACE1 (ANY, "ElGetInterfaceParams: Error in RegSetValueExA for LastUsedSSID, %ld",
  1071. lError);
  1072. }
  1073. } while (FALSE);
  1074. if (hkey != NULL)
  1075. {
  1076. RegCloseKey (hkey);
  1077. }
  1078. if (hkey1 != NULL)
  1079. {
  1080. RegCloseKey (hkey1);
  1081. }
  1082. return dwRetCode;
  1083. }
  1084. //
  1085. // ElGetEapKeyFromToken
  1086. //
  1087. // Description:
  1088. //
  1089. // Function to get handle to User hive from User Token
  1090. //
  1091. // Arguments:
  1092. // hUserToken - handle to user token
  1093. // phkey - output: pointer to handle to user hive
  1094. //
  1095. // Return values:
  1096. // NO_ERROR - success
  1097. // non-zero - error
  1098. //
  1099. DWORD
  1100. ElGetEapKeyFromToken (
  1101. IN HANDLE hUserToken,
  1102. OUT HKEY *phkey
  1103. )
  1104. {
  1105. DWORD dwSizeNeeded;
  1106. TOKEN_USER *pTokenData = NULL;
  1107. UNICODE_STRING UnicodeSidString;
  1108. WCHAR wsUnicodeBuffer[256];
  1109. HKEY hUserKey;
  1110. HKEY hkeyEap;
  1111. DWORD dwDisposition;
  1112. NTSTATUS Status = STATUS_SUCCESS;
  1113. PBYTE pbInfo = NULL;
  1114. CHAR *pszInfo = NULL;
  1115. DWORD dwType;
  1116. DWORD dwInfoSize = 0;
  1117. LONG lRetVal;
  1118. EAPOL_PCB *pPCB;
  1119. DWORD i;
  1120. LONG lError = ERROR_SUCCESS;
  1121. DWORD dwRetCode = NO_ERROR;
  1122. do
  1123. {
  1124. if (hUserToken != NULL)
  1125. {
  1126. if (!GetTokenInformation(hUserToken, TokenUser, 0, 0, &dwSizeNeeded))
  1127. {
  1128. if ((dwRetCode = GetLastError()) == ERROR_INSUFFICIENT_BUFFER)
  1129. {
  1130. pTokenData = (TOKEN_USER *) MALLOC (dwSizeNeeded);
  1131. if (pTokenData == NULL)
  1132. {
  1133. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1134. TRACE0 (ANY,"ElGetEapKeyFromToken: Allocation for TokenData failed");
  1135. break;
  1136. }
  1137. // Reset error code since we are continuing processing
  1138. // This was a valid scenario
  1139. dwRetCode = NO_ERROR;
  1140. }
  1141. else
  1142. {
  1143. TRACE1 (ANY,"ElGetEapKeyFromToken: Error in GetTokenInformation = %ld",
  1144. dwRetCode);
  1145. break;
  1146. }
  1147. if (!GetTokenInformation (hUserToken,
  1148. TokenUser,
  1149. pTokenData,
  1150. dwSizeNeeded,
  1151. &dwSizeNeeded))
  1152. {
  1153. dwRetCode = GetLastError ();
  1154. TRACE1 (ANY,"ElGetEapKeyFromToken: GetTokenInformation failed with error %ld",
  1155. dwRetCode);
  1156. break;
  1157. }
  1158. UnicodeSidString.Buffer = wsUnicodeBuffer;
  1159. UnicodeSidString.Length = 0;
  1160. UnicodeSidString.MaximumLength = sizeof(wsUnicodeBuffer);
  1161. Status = RtlConvertSidToUnicodeString (
  1162. &UnicodeSidString,
  1163. pTokenData->User.Sid,
  1164. FALSE);
  1165. if (!NT_SUCCESS(Status))
  1166. {
  1167. dwRetCode = GetLastError ();
  1168. TRACE1 (ANY, "ElGetEapKeyFromToken: RtlconvertSidToUnicodeString failed with error %ld",
  1169. dwRetCode);
  1170. break;
  1171. }
  1172. UnicodeSidString.Buffer[UnicodeSidString.Length] = 0;
  1173. // Open the user's key
  1174. if ((lError = RegOpenKeyEx(HKEY_USERS,
  1175. UnicodeSidString.Buffer,
  1176. 0,
  1177. KEY_ALL_ACCESS,
  1178. &hUserKey)) != ERROR_SUCCESS)
  1179. {
  1180. dwRetCode = (DWORD)lError;
  1181. TRACE1 (USER, "ElGetEapKeyFromToken: RegOpenKeyExA failed with error %ld",
  1182. dwRetCode);
  1183. break;
  1184. }
  1185. else
  1186. {
  1187. TRACE0 (ANY, "ElGetEapKeyFromToken: RegOpenKeyExA succeeded");
  1188. }
  1189. }
  1190. else
  1191. {
  1192. TRACE0 (ANY,"ElGetEapKeyFromToken: GetTokenInformation succeeded when it should have failed");
  1193. break;
  1194. }
  1195. }
  1196. else
  1197. {
  1198. TRACE0 (ANY, "ElGetEapKeyFromToken: Error, hUserToken == NULL ");
  1199. break;
  1200. }
  1201. *phkey = hUserKey;
  1202. } while (FALSE);
  1203. if (pTokenData != NULL)
  1204. {
  1205. FREE (pTokenData);
  1206. }
  1207. return dwRetCode;
  1208. }
  1209. //
  1210. // ElInitRegPortData
  1211. //
  1212. // Description:
  1213. //
  1214. // Function to verify existence of connection data for the port
  1215. // If no data exists, initialize with default values
  1216. // For EAP-TLS, default settings are no server certificate authentication,
  1217. // registry certificates
  1218. //
  1219. // Arguments:
  1220. // pszDeviceGUID - Pointer to GUID string for the port for which data is being
  1221. // initialized
  1222. //
  1223. // Return values:
  1224. // NO_ERROR - success
  1225. // non-zero - error
  1226. //
  1227. DWORD
  1228. ElInitRegPortData (
  1229. CHAR *pszDeviceGUID
  1230. )
  1231. {
  1232. PBYTE pbInfo = NULL;
  1233. DWORD dwInfoSize = 0;
  1234. EAPTLS_CONN_PROPERTIES *pConnProp = NULL;
  1235. DWORD dwRetCode = NO_ERROR;
  1236. do
  1237. {
  1238. // Get the size of the Eap data first
  1239. if ((dwRetCode = ElGetCustomAuthData (
  1240. pszDeviceGUID,
  1241. EAPCFG_DefaultKey,
  1242. NULL, // SSID
  1243. NULL, // pbInfo
  1244. &dwInfoSize
  1245. )) != NO_ERROR)
  1246. {
  1247. TRACE1 (ANY, "ElInitRegPortData: ElGetCustomAuthData returned error %ld",
  1248. dwRetCode);
  1249. if ((dwRetCode == ERROR_BUFFER_TOO_SMALL) && (dwInfoSize != 0))
  1250. {
  1251. // There is valid data in the default key in the registry
  1252. dwRetCode = NO_ERROR;
  1253. TRACE1 (ANY, "ElInitRegPortData: ElGetCustomAuthData returned blob size = %ld",
  1254. dwInfoSize);
  1255. break;
  1256. }
  1257. // Initialize port place with default data
  1258. pConnProp = MALLOC (sizeof (EAPTLS_CONN_PROPERTIES));
  1259. if (pConnProp == NULL)
  1260. {
  1261. TRACE0 (ANY, "ElInitRegPortData: Failed allocation for Conn Prop");
  1262. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1263. break;
  1264. }
  1265. // Registry certs, No server cert validation, No server name
  1266. // comparison
  1267. pConnProp->fFlags = (EAPTLS_CONN_FLAG_REGISTRY |
  1268. EAPTLS_CONN_FLAG_NO_VALIDATE_CERT |
  1269. EAPTLS_CONN_FLAG_NO_VALIDATE_NAME);
  1270. #if REG_CERT_VALIDATE
  1271. pConnProp->fFlags = EAPTLS_CONN_FLAG_REGISTRY;
  1272. pConnProp->fFlags &= ~EAPTLS_CONN_FLAG_NO_VALIDATE_CERT;
  1273. pConnProp->fFlags &= ~EAPTLS_CONN_FLAG_NO_VALIDATE_NAME;
  1274. #endif
  1275. pConnProp->dwSize = sizeof (EAPTLS_CONN_PROPERTIES);
  1276. // Set this blob into the registry for the port
  1277. if ((dwRetCode = ElSetCustomAuthData (
  1278. pszDeviceGUID,
  1279. EAPCFG_DefaultKey,
  1280. NULL,
  1281. (BYTE *)pConnProp,
  1282. pConnProp->dwSize
  1283. )) != NO_ERROR)
  1284. {
  1285. TRACE1 (ANY, "ElInitRegPortData: ElSetCustomAuthData failed with %ld",
  1286. dwRetCode);
  1287. break;
  1288. }
  1289. }
  1290. } while (FALSE);
  1291. if (pConnProp != NULL)
  1292. {
  1293. FREE (pConnProp);
  1294. pConnProp = NULL;
  1295. }
  1296. TRACE1 (ANY, "ElInitRegPortData: completed with error %ld", dwRetCode);
  1297. return dwRetCode;
  1298. }
  1299. //
  1300. // ElAuthAttributeGetVendorSpecific
  1301. //
  1302. //
  1303. // Description:
  1304. // Helper function used to extract MPPE Key out of Attrribute.
  1305. //
  1306. RAS_AUTH_ATTRIBUTE *
  1307. ElAuthAttributeGetVendorSpecific (
  1308. IN DWORD dwVendorId,
  1309. IN DWORD dwVendorType,
  1310. IN RAS_AUTH_ATTRIBUTE * pAttributes
  1311. )
  1312. {
  1313. HANDLE hAttribute;
  1314. RAS_AUTH_ATTRIBUTE * pAttribute;
  1315. //
  1316. // First search for the vendor specific attribute
  1317. //
  1318. pAttribute = ElAuthAttributeGetFirst ( raatVendorSpecific,
  1319. pAttributes,
  1320. &hAttribute );
  1321. while ( pAttribute != NULL )
  1322. {
  1323. //
  1324. // If this attribute is of at least size to hold vendor Id/Type
  1325. //
  1326. if ( pAttribute->dwLength >= 8 )
  1327. {
  1328. //
  1329. // Does this have the correct VendorId
  1330. //
  1331. if (WireToHostFormat32( (PBYTE)(pAttribute->Value) ) == dwVendorId)
  1332. {
  1333. //
  1334. // Does this have the correct Vendor Type
  1335. //
  1336. if ( *(((PBYTE)(pAttribute->Value))+4) == dwVendorType )
  1337. {
  1338. return( pAttribute );
  1339. }
  1340. }
  1341. }
  1342. pAttribute = ElAuthAttributeGetNext ( &hAttribute,
  1343. raatVendorSpecific );
  1344. }
  1345. return( NULL );
  1346. }
  1347. //
  1348. // ElAuthAttributeGetFirst
  1349. //
  1350. // Description:
  1351. // Helper function used to extract MPPE Key out of Attrribute.
  1352. //
  1353. RAS_AUTH_ATTRIBUTE *
  1354. ElAuthAttributeGetFirst (
  1355. IN RAS_AUTH_ATTRIBUTE_TYPE raaType,
  1356. IN RAS_AUTH_ATTRIBUTE * pAttributes,
  1357. OUT HANDLE * phAttribute
  1358. )
  1359. {
  1360. DWORD dwIndex;
  1361. RAS_AUTH_ATTRIBUTE * pRequiredAttribute;
  1362. pRequiredAttribute = ElAuthAttributeGet ( raaType, pAttributes );
  1363. if ( pRequiredAttribute == NULL )
  1364. {
  1365. *phAttribute = NULL;
  1366. return( NULL );
  1367. }
  1368. *phAttribute = pRequiredAttribute;
  1369. return( pRequiredAttribute );
  1370. }
  1371. //
  1372. // ElAuthAttributeGetNext
  1373. //
  1374. // Description:
  1375. // Helper function used to extract MPPE Key out of Attrribute.
  1376. //
  1377. RAS_AUTH_ATTRIBUTE *
  1378. ElAuthAttributeGetNext (
  1379. IN OUT HANDLE * phAttribute,
  1380. IN RAS_AUTH_ATTRIBUTE_TYPE raaType
  1381. )
  1382. {
  1383. DWORD dwIndex;
  1384. RAS_AUTH_ATTRIBUTE * pAttributes = (RAS_AUTH_ATTRIBUTE *)*phAttribute;
  1385. if ( pAttributes == NULL )
  1386. {
  1387. return( NULL );
  1388. }
  1389. pAttributes++;
  1390. while( pAttributes->raaType != raatMinimum )
  1391. {
  1392. if ( pAttributes->raaType == raaType )
  1393. {
  1394. *phAttribute = pAttributes;
  1395. return( pAttributes );
  1396. }
  1397. pAttributes++;
  1398. }
  1399. *phAttribute = NULL;
  1400. return( NULL );
  1401. }
  1402. //
  1403. // ElAuthAttributeGet
  1404. //
  1405. // Description:
  1406. // Helper function used to extract MPPE Key out of Attrribute.
  1407. //
  1408. RAS_AUTH_ATTRIBUTE *
  1409. ElAuthAttributeGet (
  1410. IN RAS_AUTH_ATTRIBUTE_TYPE raaType,
  1411. IN RAS_AUTH_ATTRIBUTE * pAttributes
  1412. )
  1413. {
  1414. DWORD dwIndex;
  1415. if ( pAttributes == NULL )
  1416. {
  1417. return( NULL );
  1418. }
  1419. for( dwIndex = 0; pAttributes[dwIndex].raaType != raatMinimum; dwIndex++ )
  1420. {
  1421. if ( pAttributes[dwIndex].raaType == raaType )
  1422. {
  1423. return( &(pAttributes[dwIndex]) );
  1424. }
  1425. }
  1426. return( NULL );
  1427. }
  1428. //
  1429. // ElReverseString
  1430. //
  1431. // Description:
  1432. // Reverses order of characters in 'psz'
  1433. //
  1434. VOID
  1435. ElReverseString (
  1436. CHAR* psz
  1437. )
  1438. {
  1439. CHAR* pszBegin;
  1440. CHAR* pszEnd;
  1441. for (pszBegin = psz, pszEnd = psz + strlen( psz ) - 1;
  1442. pszBegin < pszEnd;
  1443. ++pszBegin, --pszEnd)
  1444. {
  1445. CHAR ch = *pszBegin;
  1446. *pszBegin = *pszEnd;
  1447. *pszEnd = ch;
  1448. }
  1449. }
  1450. //
  1451. // ElEncodePw
  1452. //
  1453. // Description:
  1454. //
  1455. // Obfuscate 'pszPassword' in place to foil memory scans for passwords.
  1456. // Returns the address of 'pszPassword'.
  1457. //
  1458. CHAR*
  1459. ElEncodePw (
  1460. IN OUT CHAR* pszPassword
  1461. )
  1462. {
  1463. if (pszPassword)
  1464. {
  1465. CHAR* psz;
  1466. ElReverseString (pszPassword);
  1467. for (psz = pszPassword; *psz != '\0'; ++psz)
  1468. {
  1469. if (*psz != (CHAR)PASSWORDMAGIC)
  1470. *psz ^= PASSWORDMAGIC;
  1471. }
  1472. }
  1473. return pszPassword;
  1474. }
  1475. //
  1476. // ElDecodePw
  1477. //
  1478. // Description:
  1479. //
  1480. // Un-obfuscate 'pszPassword' in place.
  1481. // Returns the address of 'pszPassword'.
  1482. //
  1483. CHAR*
  1484. ElDecodePw (
  1485. IN OUT CHAR* pszPassword
  1486. )
  1487. {
  1488. return ElEncodePw (pszPassword);
  1489. }
  1490. //
  1491. // Call: ElEncryptKeyUsingMD5
  1492. //
  1493. // Description:
  1494. // Given a secret, encrypt a given blob
  1495. //
  1496. //
  1497. //
  1498. VOID
  1499. ElEncryptBlockUsingMD5 (
  1500. IN BYTE *pbSecret,
  1501. IN ULONG ulSecretLen,
  1502. IN OUT BYTE *pbBuf,
  1503. IN ULONG ulBufLen
  1504. )
  1505. {
  1506. MD5_CTX MD5Context;
  1507. BYTE bcipherText[MD5DIGESTLEN];
  1508. BYTE *pbWork = NULL, *pbEnd = NULL;
  1509. BYTE *pbEndBlock = NULL, *pbSrc = NULL;
  1510. //
  1511. // Compute the beginning and end of the data to be crypted
  1512. //
  1513. pbWork = pbBuf;
  1514. pbEnd = pbBuf + ulBufLen;
  1515. //
  1516. // Loop through the buffer
  1517. //
  1518. while (pbWork < pbEnd)
  1519. {
  1520. // Compute the digest
  1521. MD5Init (&MD5Context);
  1522. MD5Update (&MD5Context, pbSecret, ulSecretLen);
  1523. MD5Final (&MD5Context);
  1524. // Find the end of the block to be decrypted
  1525. pbEndBlock = pbWork + MD5DIGESTLEN;
  1526. if (pbEndBlock >= pbEnd)
  1527. {
  1528. // We've reached the end of the buffer
  1529. pbEndBlock = pbEnd;
  1530. }
  1531. else
  1532. {
  1533. // ISSUE: Save the ciphertext for the next pass?
  1534. }
  1535. // Crypt the block
  1536. for (pbSrc = MD5Context.digest; pbWork < pbEndBlock; ++pbWork, ++pbSrc)
  1537. {
  1538. *pbWork ^= *pbSrc;
  1539. }
  1540. }
  1541. }
  1542. //
  1543. // ElDecryptKeyUsingMD5
  1544. //
  1545. // Description:
  1546. // Given a secret, decrypt a given blob
  1547. //
  1548. //
  1549. //
  1550. VOID
  1551. ElDecryptBlockUsingMD5 (
  1552. IN BYTE *pbSecret,
  1553. IN ULONG ulSecretLen,
  1554. IN OUT BYTE *pbBuf,
  1555. IN ULONG ulBufLen
  1556. )
  1557. {
  1558. MD5_CTX MD5Context;
  1559. BYTE bcipherText[MD5DIGESTLEN];
  1560. BYTE *pbWork = NULL, *pbEnd = NULL;
  1561. BYTE *pbEndBlock = NULL, *pbSrc = NULL;
  1562. DWORD dwNumBlocks = 0;
  1563. DWORD dwBlock = 0;
  1564. DWORD dwIndex = 0;
  1565. dwNumBlocks = ( ulBufLen - 2 ) / MD5DIGESTLEN;
  1566. //
  1567. // Walk through the blocks
  1568. //
  1569. for (dwBlock = 0; dwBlock < dwNumBlocks; dwBlock++ )
  1570. {
  1571. MD5Init ( &MD5Context);
  1572. MD5Update ( &MD5Context, (PBYTE)pbSecret, ulSecretLen);
  1573. //
  1574. // ISSUE:
  1575. // Do we use any part of the ciphertext at all to generate
  1576. // the digest
  1577. //
  1578. MD5Final ( &MD5Context);
  1579. for ( dwIndex = 0; dwIndex < MD5DIGESTLEN; dwIndex++ )
  1580. {
  1581. *pbBuf ^= MD5Context.digest[dwIndex];
  1582. pbBuf++;
  1583. }
  1584. }
  1585. }
  1586. //
  1587. // ElGetHMACMD5Digest
  1588. //
  1589. // Description:
  1590. //
  1591. // Given a secret, generate a MD5 digest
  1592. //
  1593. // Arguments:
  1594. // pbBuf - pointer to data stream
  1595. // dwBufLen - length of data stream
  1596. // pbKey - pointer to authentication key
  1597. // dwKeyLen - length of authentication key
  1598. // pvDigest - caller digest to be filled in
  1599. //
  1600. // Return values:
  1601. // None
  1602. //
  1603. VOID
  1604. ElGetHMACMD5Digest (
  1605. IN BYTE *pbBuf,
  1606. IN DWORD dwBufLen,
  1607. IN BYTE *pbKey,
  1608. IN DWORD dwKeyLen,
  1609. IN OUT VOID *pvDigest
  1610. )
  1611. {
  1612. MD5_CTX MD5context;
  1613. UCHAR k_ipad[65]; /* inner padding - key XORd with ipad */
  1614. UCHAR k_opad[65]; /* outer padding - key XORd with opad */
  1615. UCHAR tk[16];
  1616. DWORD dwIndex = 0;
  1617. //
  1618. // the HMAC_MD5 transform looks like:
  1619. //
  1620. // MD5(K XOR opad, MD5(K XOR ipad, text))
  1621. //
  1622. // where K is an n byte key
  1623. // ipad is the byte 0x36 repeated 64 times
  1624. // opad is the byte 0x5c repeated 64 times
  1625. // and text is the data being protected
  1626. //
  1627. // start out by storing key in pads
  1628. ZeroMemory ( k_ipad, sizeof k_ipad);
  1629. ZeroMemory ( k_opad, sizeof k_opad);
  1630. memcpy ( k_ipad, pbKey, dwKeyLen);
  1631. memcpy ( k_opad, pbKey, dwKeyLen);
  1632. // XOR key with ipad and opad values
  1633. for (dwIndex=0; dwIndex<64; dwIndex++)
  1634. {
  1635. k_ipad[dwIndex] ^= 0x36;
  1636. k_opad[dwIndex] ^= 0x5c;
  1637. }
  1638. //
  1639. // perform inner MD5
  1640. //
  1641. // init context for 1st pass
  1642. MD5Init(&MD5context);
  1643. // start with inner pad
  1644. MD5Update(&MD5context, k_ipad, 64);
  1645. // then text of datagram
  1646. MD5Update(&MD5context, pbBuf, dwBufLen);
  1647. // finish up 1st pass
  1648. MD5Final(&MD5context);
  1649. memcpy (pvDigest, MD5context.digest, MD5DIGESTLEN);
  1650. //
  1651. // perform outer MD5
  1652. //
  1653. // init context for 2nd pass
  1654. MD5Init(&MD5context);
  1655. // start with outer pad
  1656. MD5Update(&MD5context, k_opad, 64);
  1657. // then results of 1st hash
  1658. MD5Update(&MD5context, pvDigest, 16);
  1659. // finish up 2nd pass
  1660. MD5Final(&MD5context);
  1661. memcpy (pvDigest, MD5context.digest, MD5DIGESTLEN);
  1662. }
  1663. //
  1664. // ElWmiGetValue
  1665. //
  1666. // Description:
  1667. //
  1668. // Get a value for a GUID instance through WMI
  1669. //
  1670. // Arguments:
  1671. // pGuid - Pointer to guid for which value is to be fetched
  1672. // pszInstanceName - Friendly name for the interface
  1673. // pbInputBuffer - Pointer to data
  1674. // dwInputBufferSize - Size of data
  1675. //
  1676. // Return values:
  1677. // NO_ERROR - success
  1678. // non-zero - error
  1679. //
  1680. DWORD
  1681. ElWmiGetValue (
  1682. IN GUID *pGuid,
  1683. IN CHAR *pszInstanceName,
  1684. IN OUT BYTE *pbOutputBuffer,
  1685. IN OUT DWORD *pdwOutputBufferSize
  1686. )
  1687. {
  1688. WMIHANDLE WmiHandle = NULL;
  1689. PWNODE_SINGLE_INSTANCE pWnode;
  1690. ULONG ulBufferSize = 0;
  1691. WCHAR *pwszInstanceName = NULL;
  1692. BYTE *pbLocalBuffer = NULL;
  1693. DWORD dwLocalBufferSize = 0;
  1694. LONG lStatus = ERROR_SUCCESS;
  1695. do
  1696. {
  1697. if ((pwszInstanceName = MALLOC ((strlen(pszInstanceName)+1) * sizeof (WCHAR))) == NULL)
  1698. {
  1699. TRACE2 (ANY, "ElWmiGetValue: MALLOC failed for pwszInstanceName, Friendlyname =%s, len= %ld",
  1700. pszInstanceName, strlen(pszInstanceName));
  1701. lStatus = ERROR_NOT_ENOUGH_MEMORY;
  1702. break;
  1703. }
  1704. if (0 == MultiByteToWideChar(
  1705. CP_ACP,
  1706. 0,
  1707. pszInstanceName,
  1708. -1,
  1709. pwszInstanceName,
  1710. strlen(pszInstanceName)+1 ) )
  1711. {
  1712. lStatus = GetLastError();
  1713. TRACE2 (ANY, "ElWmiGetValue: MultiByteToWideChar(%s) failed: %ld",
  1714. pszInstanceName, lStatus);
  1715. break;
  1716. }
  1717. pwszInstanceName[strlen(pszInstanceName)] = L'\0';
  1718. TRACE1 (ANY, "ElWmiGetValue: MultiByteToWideChar succeeded: %S",
  1719. pwszInstanceName);
  1720. if ((lStatus = WmiOpenBlock (pGuid, 0, &WmiHandle)) != ERROR_SUCCESS)
  1721. {
  1722. TRACE1 (ANY, "ElWmiGetValue: WmiOpenBlock failed with error %ld",
  1723. lStatus);
  1724. break;
  1725. }
  1726. if ((lStatus = WmiQuerySingleInstance (WmiHandle,
  1727. pwszInstanceName,
  1728. &dwLocalBufferSize,
  1729. NULL)) != ERROR_SUCCESS)
  1730. {
  1731. if (lStatus == ERROR_INSUFFICIENT_BUFFER)
  1732. {
  1733. TRACE1 (ANY, "ElWmiGetValue: Size Required = %ld",
  1734. dwLocalBufferSize);
  1735. if ((pbLocalBuffer = MALLOC (dwLocalBufferSize)) == NULL)
  1736. {
  1737. TRACE0 (ANY, "ElWmiGetValue: MALLOC failed for pbLocalBuffer");
  1738. lStatus = ERROR_NOT_ENOUGH_MEMORY;
  1739. break;
  1740. }
  1741. if ((lStatus = WmiQuerySingleInstance (WmiHandle,
  1742. pwszInstanceName,
  1743. &dwLocalBufferSize,
  1744. pbLocalBuffer))
  1745. != ERROR_SUCCESS)
  1746. {
  1747. TRACE1 (ANY, "ElWmiGetValue: WmiQuerySingleInstance failed with error %ld",
  1748. lStatus);
  1749. break;
  1750. }
  1751. pWnode = (PWNODE_SINGLE_INSTANCE)pbLocalBuffer;
  1752. // If enough space in the output buffer, copy the data block
  1753. if (*pdwOutputBufferSize >= pWnode->SizeDataBlock)
  1754. {
  1755. memcpy (pbOutputBuffer,
  1756. (PBYTE)((BYTE *)pWnode + pWnode->DataBlockOffset),
  1757. pWnode->SizeDataBlock
  1758. );
  1759. }
  1760. else
  1761. {
  1762. lStatus = ERROR_INSUFFICIENT_BUFFER;
  1763. TRACE0 (ANY, "ElWmiGetValue: Not sufficient space to copy DataBlock");
  1764. *pdwOutputBufferSize = pWnode->SizeDataBlock;
  1765. break;
  1766. }
  1767. *pdwOutputBufferSize = pWnode->SizeDataBlock;
  1768. TRACE0 (ANY, "ElWmiGetValue: Got values from Wmi");
  1769. TRACE1 (ANY, "SizeofDataBlock = %ld", pWnode->SizeDataBlock);
  1770. EAPOL_DUMPBA (pbOutputBuffer, *pdwOutputBufferSize);
  1771. }
  1772. else
  1773. {
  1774. TRACE1 (ANY, "ElWmiGetValue: WmiQuerySingleInstance failed with error %ld",
  1775. lStatus);
  1776. break;
  1777. }
  1778. }
  1779. } while (FALSE);
  1780. if (WmiHandle != NULL)
  1781. {
  1782. if ((lStatus = WmiCloseBlock (WmiHandle)) != ERROR_SUCCESS)
  1783. {
  1784. TRACE1 (ANY, "ElWmiGetValue: WmiOpenBlock failed with error %ld",
  1785. lStatus);
  1786. }
  1787. }
  1788. if (pbLocalBuffer != NULL)
  1789. {
  1790. FREE (pbLocalBuffer);
  1791. }
  1792. if (pwszInstanceName != NULL)
  1793. {
  1794. FREE (pwszInstanceName);
  1795. }
  1796. return (DWORD)lStatus;
  1797. }
  1798. //
  1799. // ElWmiSetValue
  1800. //
  1801. // Description:
  1802. //
  1803. // Set a value for a GUID instance through WMI
  1804. //
  1805. // Arguments:
  1806. // pGuid - Pointer to guid for which value is to be set
  1807. // pszInstanceName - Friendly name for the interface
  1808. // pbInputBuffer - Pointer to data
  1809. // dwInputBufferSize - Size of data
  1810. //
  1811. // Return values:
  1812. // NO_ERROR - success
  1813. // non-zero - error
  1814. //
  1815. DWORD
  1816. ElWmiSetValue (
  1817. IN GUID *pGuid,
  1818. IN CHAR *pszInstanceName,
  1819. IN BYTE *pbInputBuffer,
  1820. IN DWORD dwInputBufferSize
  1821. )
  1822. {
  1823. WMIHANDLE WmiHandle = NULL;
  1824. PWNODE_SINGLE_INSTANCE pWnode;
  1825. ULONG ulBufferSize = 0;
  1826. WCHAR *pwszInstanceName = NULL;
  1827. BYTE bBuffer[4096];
  1828. LONG lStatus = ERROR_SUCCESS;
  1829. do
  1830. {
  1831. if ((pwszInstanceName = MALLOC ((strlen(pszInstanceName)+1) * sizeof (WCHAR))) == NULL)
  1832. {
  1833. TRACE0 (ANY, "ElWmiSetValue: MALLOC failed for pwszInstanceName");
  1834. lStatus = ERROR_NOT_ENOUGH_MEMORY;
  1835. break;
  1836. }
  1837. if (0 == MultiByteToWideChar (
  1838. CP_ACP,
  1839. 0,
  1840. pszInstanceName,
  1841. -1,
  1842. pwszInstanceName,
  1843. strlen(pszInstanceName)+1 ) )
  1844. {
  1845. lStatus = GetLastError();
  1846. TRACE2 (ANY, "ElWmiSetValue: MultiByteToWideChar(%s) failed: %d",
  1847. pszInstanceName,
  1848. lStatus);
  1849. break;
  1850. }
  1851. pwszInstanceName[strlen(pszInstanceName)] = L'\0';
  1852. if ((lStatus = WmiOpenBlock (pGuid, 0, &WmiHandle)) != ERROR_SUCCESS)
  1853. {
  1854. TRACE1 (ANY, "ElWmiSetValue: WmiOpenBlock failed with error %ld",
  1855. lStatus);
  1856. break;
  1857. }
  1858. if ((lStatus = WmiSetSingleInstance (WmiHandle,
  1859. pwszInstanceName,
  1860. 1,
  1861. dwInputBufferSize,
  1862. pbInputBuffer))
  1863. != ERROR_SUCCESS)
  1864. {
  1865. TRACE1 (ANY, "ElWmiSetValue: WmiSetSingleInstance failed with error %ld",
  1866. lStatus);
  1867. break;
  1868. }
  1869. TRACE0 (ANY, "ElWmiSetValue: Successful !!!");
  1870. } while (FALSE);
  1871. if (WmiHandle != NULL)
  1872. {
  1873. if ((lStatus = WmiCloseBlock (WmiHandle)) != ERROR_SUCCESS)
  1874. {
  1875. TRACE1 (ANY, "ElWmiSetValue: WmiOpenBlock failed with error %ld",
  1876. lStatus);
  1877. }
  1878. }
  1879. if (pwszInstanceName != NULL)
  1880. {
  1881. FREE (pwszInstanceName);
  1882. }
  1883. return (DWORD)lStatus;
  1884. }
  1885. //
  1886. // ElNdisuioSetOIDValue
  1887. //
  1888. // Description:
  1889. //
  1890. // Set a value for an OID for an interface using Ndisuio
  1891. //
  1892. // Arguments:
  1893. // hInterface - Ndisuio handle to interface
  1894. // Oid - Oid for which value needs to be set
  1895. // pbOidData - Pointer to Oid data
  1896. // ulOidDataLength - Oid data length
  1897. //
  1898. // Return values:
  1899. // NO_ERROR - success
  1900. // non-zero - error
  1901. //
  1902. DWORD
  1903. ElNdisuioSetOIDValue (
  1904. IN HANDLE hInterface,
  1905. IN NDIS_OID Oid,
  1906. IN BYTE *pbOidData,
  1907. IN ULONG ulOidDataLength
  1908. )
  1909. {
  1910. PNDISUIO_SET_OID pSetOid = NULL;
  1911. DWORD BytesReturned = 0;
  1912. BOOLEAN fSuccess = TRUE;
  1913. DWORD dwRetCode = NO_ERROR;
  1914. do
  1915. {
  1916. pSetOid = (PNDISUIO_SET_OID) MALLOC (ulOidDataLength + sizeof(NDISUIO_SET_OID));
  1917. if (pSetOid == NULL)
  1918. {
  1919. TRACE0 (ANY, "ElNdisuioSetOIDValue: MALLOC failed for pSetOid");
  1920. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1921. break;
  1922. }
  1923. pSetOid->Oid = Oid;
  1924. memcpy(&pSetOid->Data[0], pbOidData, ulOidDataLength);
  1925. fSuccess = (BOOLEAN) DeviceIoControl (
  1926. hInterface,
  1927. IOCTL_NDISUIO_SET_OID_VALUE,
  1928. (LPVOID)pSetOid,
  1929. FIELD_OFFSET(NDISUIO_SET_OID, Data) + ulOidDataLength,
  1930. (LPVOID)pSetOid,
  1931. 0,
  1932. &BytesReturned,
  1933. NULL);
  1934. if (!fSuccess)
  1935. {
  1936. TRACE1 (ANY, "ElNdisuioSetOIDValue: DeviceIoControl failed with error %ld",
  1937. (dwRetCode = GetLastError()));
  1938. break;
  1939. }
  1940. else
  1941. {
  1942. TRACE0 (ANY, "ElNdisuioSetOIDValue: DeviceIoControl succeeded");
  1943. }
  1944. }
  1945. while (FALSE);
  1946. if (pSetOid != NULL)
  1947. {
  1948. FREE (pSetOid);
  1949. }
  1950. return dwRetCode;
  1951. }
  1952. //
  1953. // ElNdisuioQueryOIDValue
  1954. //
  1955. // Description:
  1956. //
  1957. // Query the value for an OID for an interface using Ndisuio
  1958. //
  1959. // Arguments:
  1960. // hInterface - Ndisuio handle to interface
  1961. // Oid - Oid for which value needs to be set
  1962. // pbOidValue - Pointer to Oid value
  1963. // pulOidDataLength - Pointer to Oid data length
  1964. //
  1965. // Return values:
  1966. // NO_ERROR - success
  1967. // non-zero - error
  1968. //
  1969. DWORD
  1970. ElNdisuioQueryOIDValue (
  1971. IN HANDLE hInterface,
  1972. IN NDIS_OID Oid,
  1973. IN BYTE *pbOidData,
  1974. IN ULONG *pulOidDataLength
  1975. )
  1976. {
  1977. PNDISUIO_QUERY_OID pQueryOid = NULL;
  1978. DWORD BytesReturned = 0;
  1979. BOOLEAN fSuccess = TRUE;
  1980. DWORD dwRetCode = NO_ERROR;
  1981. do
  1982. {
  1983. pQueryOid = (PNDISUIO_QUERY_OID) MALLOC (*pulOidDataLength + sizeof(NDISUIO_QUERY_OID));
  1984. if (pQueryOid == NULL)
  1985. {
  1986. TRACE0 (ANY, "ElNdisuioQueryOIDValue: MALLOC failed for pQueryOid");
  1987. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1988. break;
  1989. }
  1990. pQueryOid->Oid = Oid;
  1991. fSuccess = (BOOLEAN) DeviceIoControl (
  1992. hInterface,
  1993. IOCTL_NDISUIO_QUERY_OID_VALUE,
  1994. (LPVOID)pQueryOid,
  1995. FIELD_OFFSET(NDISUIO_QUERY_OID, Data) + *pulOidDataLength,
  1996. (LPVOID)pQueryOid,
  1997. FIELD_OFFSET(NDISUIO_QUERY_OID, Data) + *pulOidDataLength,
  1998. &BytesReturned,
  1999. NULL);
  2000. if (!fSuccess)
  2001. {
  2002. dwRetCode = GetLastError();
  2003. TRACE2 (ANY, "ElNdisuioQueryOIDValue: DeviceIoControl failed with error %ld, BytesReturned = %ld",
  2004. dwRetCode, BytesReturned);
  2005. *pulOidDataLength = BytesReturned;
  2006. break;
  2007. }
  2008. else
  2009. {
  2010. TRACE0 (ANY, "ElNdisuioQueryOIDValue: DeviceIoControl succeeded");
  2011. if (BytesReturned >= *pulOidDataLength)
  2012. {
  2013. TRACE2 (ANY, "ElNdisuioQueryOIDValue: BytesRet (%ld) >= SizeofInput (%ld); truncating data",
  2014. BytesReturned, *pulOidDataLength);
  2015. BytesReturned = *pulOidDataLength;
  2016. }
  2017. else
  2018. {
  2019. dwRetCode = ERROR_INVALID_DATA;
  2020. TRACE2 (ANY, "ElNdisuioQueryOIDValue: BytesRet (%ld) < SizeofInput (%ld)",
  2021. BytesReturned, *pulOidDataLength);
  2022. *pulOidDataLength = BytesReturned;
  2023. }
  2024. memcpy(pbOidData, &pQueryOid->Data[0], BytesReturned);
  2025. }
  2026. }
  2027. while (FALSE);
  2028. if (pQueryOid != NULL)
  2029. {
  2030. FREE (pQueryOid);
  2031. }
  2032. return dwRetCode;
  2033. }
  2034. #if 0
  2035. //
  2036. // ElGuidFromString
  2037. //
  2038. // Description:
  2039. //
  2040. // Convert a GUID-string to GUID
  2041. //
  2042. // Arguments:
  2043. // pGuid - pointer to GUID
  2044. // pszGuidString - pointer to string version of GUID
  2045. //
  2046. // Return values:
  2047. // NO_ERROR - success
  2048. // non-zero - error
  2049. //
  2050. DWORD
  2051. ElGuidFromString (
  2052. IN OUT GUID *pGuid,
  2053. IN CHAR *pszGuidString
  2054. )
  2055. {
  2056. DWORD dwGuidLen = 0;
  2057. WCHAR wszGuidString[64];
  2058. LPWSTR lpwszWithBraces = NULL;
  2059. DWORD dwRetCode = NO_ERROR;
  2060. do
  2061. {
  2062. if (pszGuidString == NULL)
  2063. {
  2064. break;
  2065. }
  2066. ZeroMemory (pGuid, sizeof(GUID));
  2067. dwGuidLen = strlen (pszGuidString);
  2068. if (dwGuidLen != 36)
  2069. {
  2070. TRACE0 (ANY, "GuidFromString: Guid Length != required 36");
  2071. break;
  2072. }
  2073. if (0 == MultiByteToWideChar(
  2074. CP_ACP,
  2075. 0,
  2076. pszGuidString,
  2077. -1,
  2078. wszGuidString,
  2079. dwGuidLen ) )
  2080. {
  2081. dwRetCode = GetLastError();
  2082. TRACE2 (ANY, "GuidFromString: MultiByteToWideChar(%s) failed: %d",
  2083. pszGuidString,
  2084. dwRetCode);
  2085. break;
  2086. }
  2087. wszGuidString[dwGuidLen] = L'\0';
  2088. // add the braces
  2089. lpwszWithBraces = (LPWSTR) MALLOC ((dwGuidLen + 1 + 2) * sizeof(WCHAR));
  2090. wsprintf (lpwszWithBraces, L"{%s}", wszGuidString);
  2091. CLSIDFromString (lpwszWithBraces, pGuid);
  2092. } while (FALSE);
  2093. return dwRetCode;
  2094. }
  2095. #endif
  2096. //
  2097. // ElGetLoggedOnUserName
  2098. //
  2099. // Description:
  2100. //
  2101. // Get the Username and Domain of the currently logged in user
  2102. //
  2103. // Arguments:
  2104. // pPCB - Pointer to port on which logged-on user's name is to be
  2105. // obtained
  2106. //
  2107. // Return values:
  2108. // NO_ERROR - success
  2109. // non-zero - error
  2110. //
  2111. //
  2112. DWORD
  2113. ElGetLoggedOnUserName (
  2114. IN EAPOL_PCB *pPCB
  2115. )
  2116. {
  2117. HANDLE hUserToken;
  2118. WCHAR *pwszUserNameBuffer = NULL;
  2119. DWORD dwBufferSize = 0;
  2120. BOOL fNeedToRevertToSelf = FALSE;
  2121. DWORD dwRetCode = NO_ERROR;
  2122. do
  2123. {
  2124. hUserToken = pPCB->hUserToken;
  2125. if (hUserToken != NULL)
  2126. {
  2127. if (!ImpersonateLoggedOnUser (hUserToken))
  2128. {
  2129. dwRetCode = GetLastError();
  2130. TRACE1 (USER, "ElGetLoggedOnUserName: ImpersonateLoggedOnUser failed with error %ld",
  2131. dwRetCode);
  2132. break;
  2133. }
  2134. fNeedToRevertToSelf = TRUE;
  2135. dwBufferSize = 0;
  2136. if (!GetUserNameEx (NameSamCompatible,
  2137. NULL,
  2138. &dwBufferSize))
  2139. {
  2140. dwRetCode = GetLastError ();
  2141. if (dwRetCode == ERROR_MORE_DATA)
  2142. {
  2143. if ((pwszUserNameBuffer = MALLOC (dwBufferSize*sizeof(WCHAR))) == NULL)
  2144. {
  2145. TRACE0 (ANY, "ElGetLoggedOnUserName: MALLOC failed for pwszUserNameBuffer");
  2146. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  2147. break;
  2148. }
  2149. if (!GetUserNameEx (NameSamCompatible,
  2150. pwszUserNameBuffer,
  2151. &dwBufferSize))
  2152. {
  2153. dwRetCode = GetLastError ();
  2154. TRACE1 (ANY, "ElGetLoggedOnUserName: GetUserNameEx failed with error %ld",
  2155. dwRetCode);
  2156. break;
  2157. }
  2158. pwszUserNameBuffer[dwBufferSize]=L'\0';
  2159. TRACE1 (ANY, "ElGetLoggedOnUserName: Got User Name %S",
  2160. pwszUserNameBuffer);
  2161. }
  2162. else
  2163. {
  2164. TRACE1 (ANY, "ElGetLoggedOnUserName: GetUserNameEx failed with error %ld",
  2165. dwRetCode);
  2166. break;
  2167. }
  2168. }
  2169. }
  2170. else
  2171. {
  2172. TRACE0 (ANY, "ElGetLoggedOnUserName: UserToken is NULL");
  2173. break;
  2174. }
  2175. } while (FALSE);
  2176. if (pwszUserNameBuffer != NULL)
  2177. {
  2178. FREE (pwszUserNameBuffer);
  2179. }
  2180. // Revert impersonation
  2181. if (fNeedToRevertToSelf)
  2182. {
  2183. if (!RevertToSelf())
  2184. {
  2185. dwRetCode = GetLastError();
  2186. TRACE1 (USER, "ElGetLoggedOnUserName: Error in RevertToSelf = %ld",
  2187. dwRetCode);
  2188. }
  2189. }
  2190. return dwRetCode;
  2191. }
  2192. //
  2193. // ElGetMachineName
  2194. //
  2195. // Description:
  2196. //
  2197. // Get the machine name of the computer the service is currently running on
  2198. //
  2199. // Arguments:
  2200. // pPCB - Pointer to PCB for the port on which machine name is to
  2201. // to be obtained
  2202. //
  2203. // Return values:
  2204. // NO_ERROR - success
  2205. // non-zero - error
  2206. //
  2207. //
  2208. DWORD
  2209. ElGetMachineName (
  2210. IN EAPOL_PCB *pPCB
  2211. )
  2212. {
  2213. WCHAR *pwszComputerNameBuffer = NULL;
  2214. CHAR *pszComputerNameBuffer = NULL;
  2215. WCHAR *pwszComputerDomainBuffer = NULL;
  2216. CHAR *pszComputerDomainBuffer = NULL;
  2217. DWORD dwBufferSize = 0;
  2218. DWORD dwRetCode = NO_ERROR;
  2219. do
  2220. {
  2221. dwBufferSize = 0;
  2222. if (!GetComputerNameEx (ComputerNamePhysicalNetBIOS,
  2223. NULL,
  2224. &dwBufferSize))
  2225. {
  2226. dwRetCode = GetLastError ();
  2227. if (dwRetCode == ERROR_MORE_DATA)
  2228. {
  2229. // Reset error
  2230. dwRetCode = NO_ERROR;
  2231. if ((pwszComputerNameBuffer = MALLOC (dwBufferSize*sizeof(WCHAR))) == NULL)
  2232. {
  2233. TRACE0 (ANY, "ElGetMachineName: MALLOC failed for pwszComputerNameBuffer");
  2234. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  2235. break;
  2236. }
  2237. if (!GetComputerNameEx (ComputerNamePhysicalNetBIOS,
  2238. pwszComputerNameBuffer,
  2239. &dwBufferSize))
  2240. {
  2241. dwRetCode = GetLastError ();
  2242. TRACE1 (ANY, "ElGetMachineName: GetComputerNameEx failed with error %ld",
  2243. dwRetCode);
  2244. break;
  2245. }
  2246. TRACE1 (ANY, "ElGetMachineName: Got Computer Name %S",
  2247. pwszComputerNameBuffer);
  2248. pszComputerNameBuffer =
  2249. MALLOC (wcslen(pwszComputerNameBuffer) + 1);
  2250. if (pszComputerNameBuffer == NULL)
  2251. {
  2252. TRACE0 (ANY, "ElGetMachineName: MALLOC failed for pszComputerNameBuffer");
  2253. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  2254. break;
  2255. }
  2256. if (0 == WideCharToMultiByte (
  2257. CP_ACP,
  2258. 0,
  2259. pwszComputerNameBuffer,
  2260. -1,
  2261. pszComputerNameBuffer,
  2262. wcslen(pwszComputerNameBuffer)+1,
  2263. NULL,
  2264. NULL ))
  2265. {
  2266. dwRetCode = GetLastError();
  2267. TRACE2 (ANY, "ElGetMachineName: WideCharToMultiByte (%ws) failed: %ld",
  2268. pwszComputerNameBuffer, dwRetCode);
  2269. break;
  2270. }
  2271. pszComputerNameBuffer[wcslen(pwszComputerNameBuffer)] = L'\0';
  2272. }
  2273. else
  2274. {
  2275. TRACE1 (ANY, "ElGetMachineName: GetComputerNameEx failed with error %ld",
  2276. dwRetCode);
  2277. break;
  2278. }
  2279. }
  2280. dwBufferSize = 0;
  2281. if (!GetComputerNameEx (ComputerNamePhysicalDnsDomain,
  2282. NULL,
  2283. &dwBufferSize))
  2284. {
  2285. dwRetCode = GetLastError ();
  2286. if (dwRetCode == ERROR_MORE_DATA)
  2287. {
  2288. // Reset error
  2289. dwRetCode = NO_ERROR;
  2290. if ((pwszComputerDomainBuffer = MALLOC (dwBufferSize*sizeof(WCHAR))) == NULL)
  2291. {
  2292. TRACE0 (ANY, "ElGetMachineName: MALLOC failed for pwszComputerDomainBuffer");
  2293. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  2294. break;
  2295. }
  2296. if (!GetComputerNameEx (ComputerNamePhysicalDnsDomain,
  2297. pwszComputerDomainBuffer,
  2298. &dwBufferSize))
  2299. {
  2300. dwRetCode = GetLastError ();
  2301. TRACE1 (ANY, "ElGetMachineName: GetComputerNameEx Domain failed with error %ld",
  2302. dwRetCode);
  2303. break;
  2304. }
  2305. TRACE1 (ANY, "ElGetMachineName: Got Computer Domain %S",
  2306. pwszComputerDomainBuffer);
  2307. pszComputerDomainBuffer =
  2308. MALLOC (wcslen(pwszComputerDomainBuffer) + 1);
  2309. if (pszComputerDomainBuffer == NULL)
  2310. {
  2311. TRACE0 (ANY, "ElGetMachineName: MALLOC failed for pszComputerDomainBuffer");
  2312. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  2313. break;
  2314. }
  2315. if (0 == WideCharToMultiByte (
  2316. CP_ACP,
  2317. 0,
  2318. pwszComputerDomainBuffer,
  2319. -1,
  2320. pszComputerDomainBuffer,
  2321. wcslen(pwszComputerDomainBuffer)+1,
  2322. NULL,
  2323. NULL ))
  2324. {
  2325. dwRetCode = GetLastError();
  2326. TRACE2 (ANY, "ElGetMachineName: WideCharToMultiByte (%ws) failed: %ld",
  2327. pwszComputerDomainBuffer, dwRetCode);
  2328. break;
  2329. }
  2330. pszComputerDomainBuffer[wcslen(pwszComputerDomainBuffer)] = L'\0';
  2331. *(strrchr (pszComputerDomainBuffer, '.')) = '\0';
  2332. if (pPCB->pszIdentity != NULL)
  2333. {
  2334. FREE (pPCB->pszIdentity);
  2335. pPCB->pszIdentity = NULL;
  2336. }
  2337. pPCB->pszIdentity = MALLOC (strlen(pszComputerDomainBuffer) +
  2338. strlen(pszComputerNameBuffer) + 3);
  2339. if (pPCB->pszIdentity == NULL)
  2340. {
  2341. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  2342. TRACE0 (ANY, "ElGetMachineName: MALLOC failed for pPCB->pszIdentity");
  2343. break;
  2344. }
  2345. memcpy (pPCB->pszIdentity,
  2346. pszComputerDomainBuffer,
  2347. strlen(pszComputerDomainBuffer));
  2348. pPCB->pszIdentity[strlen(pszComputerDomainBuffer)] = '\\';
  2349. memcpy (&pPCB->pszIdentity[strlen(pszComputerDomainBuffer)+1],
  2350. pszComputerNameBuffer,
  2351. strlen(pszComputerNameBuffer));
  2352. pPCB->pszIdentity[strlen(pszComputerDomainBuffer)+1+strlen(pszComputerNameBuffer)] = '$';
  2353. pPCB->pszIdentity[strlen(pszComputerDomainBuffer)+1+strlen(pszComputerNameBuffer)+1] = '\0';
  2354. }
  2355. else
  2356. {
  2357. TRACE1 (ANY, "ElGetMachineName: GetComputerNameEx failed with error %ld",
  2358. dwRetCode);
  2359. break;
  2360. }
  2361. }
  2362. } while (FALSE);
  2363. if (pwszComputerNameBuffer != NULL)
  2364. {
  2365. FREE (pwszComputerNameBuffer);
  2366. }
  2367. if (pszComputerNameBuffer != NULL)
  2368. {
  2369. FREE (pszComputerNameBuffer);
  2370. }
  2371. if (pwszComputerDomainBuffer != NULL)
  2372. {
  2373. FREE (pwszComputerDomainBuffer);
  2374. }
  2375. if (pszComputerDomainBuffer != NULL)
  2376. {
  2377. FREE (pszComputerDomainBuffer);
  2378. }
  2379. return dwRetCode;
  2380. }
  2381. //
  2382. // ElUpdateRegistryInterfaceList
  2383. //
  2384. // Description:
  2385. //
  2386. // Write the interface list to which NDISUIO is bound to, to the registry
  2387. //
  2388. // Arguments:
  2389. // Interfaces - Interface list containing Device Name and Description
  2390. //
  2391. // Return values:
  2392. // NO_ERROR - success
  2393. // non-zero - error
  2394. //
  2395. //
  2396. DWORD
  2397. ElUpdateRegistryInterfaceList (
  2398. IN PNDIS_ENUM_INTF Interfaces
  2399. )
  2400. {
  2401. CHAR *pszRegInterfaceList = NULL;
  2402. HKEY hkey = NULL;
  2403. DWORD dwDisposition = 0;
  2404. LONG lError = ERROR_SUCCESS;
  2405. DWORD dwRetCode = NO_ERROR;
  2406. do
  2407. {
  2408. ANSI_STRING InterfaceName;
  2409. UCHAR ucBuffer[256];
  2410. DWORD i;
  2411. DWORD dwSizeOfList = 0;
  2412. // Determine the number of bytes in the list
  2413. for (i=0; i < Interfaces->TotalInterfaces; i++)
  2414. {
  2415. ZeroMemory (ucBuffer, 256);
  2416. InterfaceName.Length = 0;
  2417. InterfaceName.MaximumLength = 256;
  2418. InterfaceName.Buffer = ucBuffer;
  2419. if (Interfaces->Interface[i].DeviceName.Buffer != NULL)
  2420. {
  2421. if (RtlUnicodeStringToAnsiString(&InterfaceName,
  2422. &(Interfaces->Interface[i].DeviceName), FALSE) != STATUS_SUCCESS)
  2423. {
  2424. TRACE1 (ANY, "ElUpdateRegistryInterfaceList: Error in RtlUnicodeStringToAnsiString for DeviceName %ws",
  2425. Interfaces->Interface[i].DeviceName.Buffer);
  2426. }
  2427. InterfaceName.Buffer[InterfaceName.Length] = '\0';
  2428. dwSizeOfList += (strlen(InterfaceName.Buffer) + 1);
  2429. }
  2430. else
  2431. {
  2432. TRACE0(INIT, "ElUpdateRegistryInterfaceList: Device Name was NULL");
  2433. continue;
  2434. }
  2435. TRACE1(INIT, "Device: %s", InterfaceName.Buffer);
  2436. }
  2437. // One extra char for terminating NULL char
  2438. pszRegInterfaceList = (CHAR *) MALLOC ( dwSizeOfList + 1 );
  2439. if ( pszRegInterfaceList == NULL )
  2440. {
  2441. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  2442. TRACE0 (ANY, "ElUpdateRegistryInterfaceList: MALLOC failed for pszRegInterfaceList");
  2443. break;
  2444. }
  2445. // Start again
  2446. dwSizeOfList = 0;
  2447. // Create the string in REG_SZ format
  2448. for (i=0; i < Interfaces->TotalInterfaces; i++)
  2449. {
  2450. ZeroMemory (ucBuffer, 256);
  2451. InterfaceName.Length = 0;
  2452. InterfaceName.MaximumLength = 256;
  2453. InterfaceName.Buffer = ucBuffer;
  2454. if (Interfaces->Interface[i].DeviceName.Buffer != NULL)
  2455. {
  2456. if (RtlUnicodeStringToAnsiString(&InterfaceName,
  2457. &Interfaces->Interface[i].DeviceName, FALSE) !=
  2458. STATUS_SUCCESS)
  2459. {
  2460. TRACE0 (ANY, "ElUpdateRegistryInterfaceList: Error in RtlUnicodeStringToAnsiString for DeviceName");
  2461. }
  2462. InterfaceName.Buffer[InterfaceName.Length] = '\0';
  2463. memcpy (&pszRegInterfaceList[dwSizeOfList],
  2464. InterfaceName.Buffer,
  2465. (strlen(InterfaceName.Buffer) ));
  2466. dwSizeOfList += (strlen(InterfaceName.Buffer));
  2467. }
  2468. else
  2469. {
  2470. TRACE0(INIT, "ElUpdateRegistryInterfaceList: Device Name was NULL");
  2471. continue;
  2472. }
  2473. }
  2474. // Final NULL character
  2475. pszRegInterfaceList[dwSizeOfList++] = '\0';
  2476. // Write the string as a REG_SZ value
  2477. // Get handle to
  2478. // HKLM\Software\Microsoft\EAPOL\Parameters\General
  2479. if ((lError = RegCreateKeyExA (
  2480. HKEY_LOCAL_MACHINE,
  2481. cszEapKeyEapolServiceParams,
  2482. 0,
  2483. NULL,
  2484. REG_OPTION_NON_VOLATILE,
  2485. KEY_WRITE,
  2486. NULL,
  2487. &hkey,
  2488. &dwDisposition)) != ERROR_SUCCESS)
  2489. {
  2490. TRACE1 (ANY, "ElUpdateRegistryInterfaceList: Error in RegCreateKeyExA for base key, %ld",
  2491. lError);
  2492. dwRetCode = (DWORD)lError;
  2493. break;
  2494. }
  2495. //
  2496. // Set the value of
  2497. // ...\EAPOL\Parameters\General\InterfaceList key
  2498. //
  2499. if ((lError = RegSetValueExA (
  2500. hkey,
  2501. cszInterfaceList,
  2502. 0,
  2503. REG_SZ,
  2504. pszRegInterfaceList,
  2505. dwSizeOfList)) != ERROR_SUCCESS)
  2506. {
  2507. TRACE1 (ANY, "ElUpdateRegistryInterfaceList: Error in RegSetValueExA for InterfaceList, %ld",
  2508. lError);
  2509. dwRetCode = (DWORD)lError;
  2510. break;
  2511. }
  2512. TRACE0 (ANY, "ElUpdateRegistryInterfaceList: Set value succeeded");
  2513. } while (FALSE);
  2514. if (hkey != NULL)
  2515. {
  2516. RegCloseKey (hkey);
  2517. }
  2518. if (pszRegInterfaceList != NULL)
  2519. {
  2520. FREE (pszRegInterfaceList);
  2521. }
  2522. return dwRetCode;
  2523. }
  2524. //
  2525. // ElWatchGlobalRegistryParams
  2526. //
  2527. // Description:
  2528. //
  2529. // Watch the registry for changes for global params. Update in-memory values
  2530. //
  2531. // Arguments:
  2532. // Unused
  2533. //
  2534. // Return values:
  2535. //
  2536. //
  2537. VOID
  2538. ElWatchGlobalRegistryParams (
  2539. IN PVOID pvContext
  2540. )
  2541. {
  2542. HKEY hKey = NULL;
  2543. HANDLE hRegChangeEvent = NULL;
  2544. HANDLE hEvents[2];
  2545. BOOL fExitThread = FALSE;
  2546. DWORD dwDisposition = 0;
  2547. DWORD dwStatus = 0;
  2548. LONG lError = 0;
  2549. DWORD dwRetCode = NO_ERROR;
  2550. TRACE0 (ANY, "ElWatchGlobalRegistryParams: Entered");
  2551. do
  2552. {
  2553. // Get handle to
  2554. // HKLM\Software\Microsoft\EAPOL\Parameters\General\Global
  2555. if ((lError = RegCreateKeyExA (
  2556. HKEY_LOCAL_MACHINE,
  2557. cszEAPOLGlobalParams,
  2558. 0,
  2559. NULL,
  2560. REG_OPTION_NON_VOLATILE,
  2561. KEY_READ,
  2562. NULL,
  2563. &hKey,
  2564. &dwDisposition)) != ERROR_SUCCESS)
  2565. {
  2566. TRACE1 (ANY, "ElWatchGlobalRegistryParams: Error in RegCreateKeyExA for base key, %ld",
  2567. lError);
  2568. dwRetCode = (DWORD)lError;
  2569. break;
  2570. }
  2571. // Open a handle to a event to perform wait on that event
  2572. hRegChangeEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
  2573. if (hRegChangeEvent == NULL)
  2574. {
  2575. dwRetCode = GetLastError ();
  2576. TRACE1 (ANY, "ElWatchGlobalRegistryParams: Error in CreateEvent for hRegChangeEvent = %ld",
  2577. dwRetCode);
  2578. break;
  2579. }
  2580. // Register to notify change in registry value
  2581. if ((lError = RegNotifyChangeKeyValue (
  2582. hKey,
  2583. TRUE, // watch entire sub-tree
  2584. REG_NOTIFY_CHANGE_LAST_SET, // detect value add/delete
  2585. hRegChangeEvent,
  2586. TRUE // asynchronous
  2587. )) != ERROR_SUCCESS)
  2588. {
  2589. dwRetCode = (DWORD)lError;
  2590. TRACE1 (ANY, "ElWatchGlobalRegistryParams: RegNotifyChangeKeyValue failed with error %ld",
  2591. dwRetCode);
  2592. break;
  2593. }
  2594. do
  2595. {
  2596. // Wait for Registry changes or service termination
  2597. hEvents[0] = hRegChangeEvent;
  2598. hEvents[1] = g_hEventTerminateEAPOL;
  2599. if ((dwStatus = WaitForMultipleObjects(
  2600. 2,
  2601. hEvents,
  2602. FALSE,
  2603. INFINITE
  2604. )) == WAIT_FAILED)
  2605. {
  2606. dwRetCode = GetLastError ();
  2607. TRACE1 (ANY, "ElWatchGlobalRegistryParams: WaitForMultipleObjects failed with error %ld",
  2608. dwRetCode);
  2609. break;
  2610. }
  2611. switch (dwStatus)
  2612. {
  2613. case WAIT_OBJECT_0:
  2614. // Registry values changed
  2615. // Update in-memory values
  2616. if ((dwRetCode = ElReadGlobalRegistryParams ()) != NO_ERROR)
  2617. {
  2618. TRACE1 (ANY, "ElWatchGlobalRegistryParams: ElReadGlobalRegistryParams failed with error %ld",
  2619. dwRetCode);
  2620. // continue processing since this is not a critical error
  2621. dwRetCode = NO_ERROR;
  2622. }
  2623. if (!ResetEvent(hRegChangeEvent))
  2624. {
  2625. dwRetCode = GetLastError ();
  2626. TRACE1 (ANY, "ElWatchGlobalRegistryParams: ResetEvent failed with error %ld",
  2627. dwRetCode);
  2628. break;
  2629. }
  2630. break;
  2631. case WAIT_OBJECT_0+1:
  2632. // Service shutdown detected
  2633. fExitThread = TRUE;
  2634. break;
  2635. default:
  2636. TRACE1 (ANY, "ElWatchGlobalRegistryParams: No such event = %ld",
  2637. dwStatus);
  2638. break;
  2639. }
  2640. if ((dwRetCode != NO_ERROR) || (fExitThread))
  2641. {
  2642. break;
  2643. }
  2644. } while (TRUE);
  2645. } while (FALSE);
  2646. TRACE1 (ANY, "ElWatchGlobalRegistryParams: Completed with error %ld",
  2647. dwRetCode);
  2648. if (hKey != NULL)
  2649. {
  2650. RegCloseKey(hKey);
  2651. }
  2652. return;
  2653. }
  2654. //
  2655. // ElReadGlobalRegistryParams
  2656. //
  2657. // Description:
  2658. //
  2659. // Read registry parameters global to EAPOL state machine
  2660. // i.e. maxStart, startPeriod, authPeriod, heldPeriod
  2661. //
  2662. // Arguments:
  2663. // Unused
  2664. //
  2665. // Return values:
  2666. //
  2667. // NO_ERROR - success
  2668. // non-zero - error
  2669. //
  2670. DWORD
  2671. ElReadGlobalRegistryParams ()
  2672. {
  2673. HKEY hKey = NULL;
  2674. DWORD dwDisposition = 0;
  2675. DWORD dwType = 0;
  2676. DWORD dwInfoSize = 0;
  2677. DWORD lError = 0;
  2678. DWORD dwmaxStart=0, dwstartPeriod=0, dwauthPeriod=0, dwheldPeriod=0;
  2679. DWORD dwRetCode = NO_ERROR;
  2680. do
  2681. {
  2682. // Get handle to
  2683. // HKLM\Software\Microsoft\EAPOL\Parameters\General\Global
  2684. if ((lError = RegCreateKeyExA (
  2685. HKEY_LOCAL_MACHINE,
  2686. cszEAPOLGlobalParams,
  2687. 0,
  2688. NULL,
  2689. REG_OPTION_NON_VOLATILE,
  2690. KEY_READ,
  2691. NULL,
  2692. &hKey,
  2693. &dwDisposition)) != ERROR_SUCCESS)
  2694. {
  2695. TRACE1 (ANY, "ElReadGlobalRegistryParams: Error in RegCreateKeyExA for base key, %ld",
  2696. lError);
  2697. break;
  2698. }
  2699. ACQUIRE_WRITE_LOCK (&g_EAPOLConfig);
  2700. // If setting values for the first time, initialize values
  2701. if (!(g_dwmaxStart || g_dwstartPeriod || g_dwauthPeriod || g_dwheldPeriod))
  2702. {
  2703. g_dwmaxStart = EAPOL_MAX_START;
  2704. g_dwstartPeriod = EAPOL_START_PERIOD;
  2705. g_dwauthPeriod = EAPOL_AUTH_PERIOD;
  2706. g_dwheldPeriod = EAPOL_HELD_PERIOD;
  2707. }
  2708. RELEASE_WRITE_LOCK (&g_EAPOLConfig);
  2709. dwmaxStart = g_dwmaxStart;
  2710. dwstartPeriod = g_dwstartPeriod;
  2711. dwauthPeriod = g_dwauthPeriod;
  2712. dwheldPeriod = g_dwheldPeriod;
  2713. // Get the value of ..\General\EAPOLGlobal\authPeriod
  2714. dwInfoSize = sizeof(DWORD);
  2715. if ((lError = RegQueryValueExA (
  2716. hKey,
  2717. cszAuthPeriod,
  2718. 0,
  2719. &dwType,
  2720. (BYTE *)&dwauthPeriod,
  2721. &dwInfoSize)) != ERROR_SUCCESS)
  2722. {
  2723. TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueExA for cszAuthPeriod, %ld, InfoSize=%ld",
  2724. lError, dwInfoSize);
  2725. dwauthPeriod = g_dwauthPeriod;
  2726. lError = ERROR_SUCCESS;
  2727. }
  2728. // Get the value of ..\General\EAPOLGlobal\heldPeriod
  2729. dwInfoSize = sizeof(DWORD);
  2730. if ((lError = RegQueryValueExA (
  2731. hKey,
  2732. cszHeldPeriod,
  2733. 0,
  2734. &dwType,
  2735. (BYTE *)&dwheldPeriod,
  2736. &dwInfoSize)) != ERROR_SUCCESS)
  2737. {
  2738. TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueExA for cszHeldPeriod, %ld, InfoSize=%ld",
  2739. lError, dwInfoSize);
  2740. dwheldPeriod = g_dwheldPeriod;
  2741. lError = ERROR_SUCCESS;
  2742. }
  2743. // Get the value of ..\General\EAPOLGlobal\startPeriod
  2744. dwInfoSize = sizeof(DWORD);
  2745. if ((lError = RegQueryValueExA (
  2746. hKey,
  2747. cszStartPeriod,
  2748. 0,
  2749. &dwType,
  2750. (BYTE *)&dwstartPeriod,
  2751. &dwInfoSize)) != ERROR_SUCCESS)
  2752. {
  2753. TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueExA for cszStartPeriod, %ld, InfoSize=%ld",
  2754. lError, dwInfoSize);
  2755. dwstartPeriod = g_dwstartPeriod;
  2756. lError = ERROR_SUCCESS;
  2757. }
  2758. // Get the value of ..\General\EAPOLGlobal\maxStart
  2759. dwInfoSize = sizeof(DWORD);
  2760. if ((lError = RegQueryValueExA (
  2761. hKey,
  2762. cszMaxStart,
  2763. 0,
  2764. &dwType,
  2765. (BYTE *)&dwmaxStart,
  2766. &dwInfoSize)) != ERROR_SUCCESS)
  2767. {
  2768. TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueExA for cszMaxStart, %ld, InfoSize=%ld",
  2769. lError, dwInfoSize);
  2770. dwmaxStart = g_dwmaxStart;
  2771. lError = ERROR_SUCCESS;
  2772. }
  2773. // Successful in reading all parameters
  2774. ACQUIRE_WRITE_LOCK (&g_EAPOLConfig);
  2775. g_dwmaxStart = dwmaxStart;
  2776. g_dwstartPeriod = dwstartPeriod;
  2777. g_dwauthPeriod = dwauthPeriod;
  2778. g_dwheldPeriod = dwheldPeriod;
  2779. RELEASE_WRITE_LOCK (&g_EAPOLConfig);
  2780. } while (FALSE);
  2781. dwRetCode = (DWORD)lError;
  2782. if (dwRetCode != NO_ERROR)
  2783. {
  2784. TRACE1 (ANY, "ElReadGlobalRegistryParams: failed with error %ld",
  2785. dwRetCode);
  2786. }
  2787. if (hKey != NULL)
  2788. {
  2789. RegCloseKey(hKey);
  2790. }
  2791. return dwRetCode;
  2792. }
  2793. //
  2794. // ElWatchEapConfigRegistryParams
  2795. //
  2796. // Description:
  2797. //
  2798. // Watch the registry for changes in EAP config
  2799. // - HKLM - EAP type
  2800. // - HKLM - EAPOLEnabled
  2801. //
  2802. // Restart the state machine if the params change
  2803. //
  2804. // Arguments:
  2805. //
  2806. // Return values:
  2807. //
  2808. //
  2809. VOID
  2810. ElWatchEapConfigRegistryParams (
  2811. IN PVOID pvContext
  2812. )
  2813. {
  2814. HKEY hUserKey = NULL;
  2815. HKEY hWorkspaceKey = NULL;
  2816. HKEY hRegChangeKey = NULL;
  2817. HANDLE hRegChangeEvent = NULL;
  2818. HANDLE hEvents[2];
  2819. HANDLE hUserToken = NULL;
  2820. DWORD dwDisposition = 0;
  2821. BOOL fExitThread = FALSE;
  2822. DWORD dwStatus = 0;
  2823. LONG lError = 0;
  2824. DWORD dwRetCode = NO_ERROR;
  2825. TRACE0 (ANY, "ElWatchEapConfigRegistryParams: Entered");
  2826. do
  2827. {
  2828. // Get handle to
  2829. // HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
  2830. if ((lError = RegCreateKeyExA (
  2831. HKEY_LOCAL_MACHINE,
  2832. cszEapKeyEapolConn,
  2833. 0,
  2834. NULL,
  2835. REG_OPTION_NON_VOLATILE,
  2836. KEY_READ,
  2837. NULL,
  2838. &hWorkspaceKey,
  2839. &dwDisposition)) != ERROR_SUCCESS)
  2840. {
  2841. TRACE1 (ANY, "ElWatchEapConfigRegistryParams: Error in RegCreateKeyExA for cszEapKeyEapolConn, %ld",
  2842. lError);
  2843. dwRetCode = (DWORD)lError;
  2844. break;
  2845. }
  2846. // Open a handle to a event to perform wait on that event
  2847. hRegChangeEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
  2848. if (hRegChangeEvent == NULL)
  2849. {
  2850. dwRetCode = GetLastError ();
  2851. TRACE1 (ANY, "ElWatchEapConfigRegistryParams: Error in CreateEvent for hRegChangeEvent = %ld",
  2852. dwRetCode);
  2853. break;
  2854. }
  2855. do
  2856. {
  2857. // Register to notify change in registry value
  2858. if ((lError = RegNotifyChangeKeyValue (
  2859. hWorkspaceKey,
  2860. TRUE, // watch entire sub-tree
  2861. REG_NOTIFY_CHANGE_LAST_SET, // detect value add/delete
  2862. hRegChangeEvent,
  2863. TRUE // asynchronous
  2864. )) != ERROR_SUCCESS)
  2865. {
  2866. dwRetCode = (DWORD)lError;
  2867. TRACE1 (ANY, "ElWatchEapConfigRegistryParams: RegNotifyChangeKeyValue failed with error %ld",
  2868. dwRetCode);
  2869. break;
  2870. }
  2871. // Wait for Registry changes, service termination
  2872. hEvents[0] = hRegChangeEvent;
  2873. hEvents[1] = g_hEventTerminateEAPOL;
  2874. if ((dwStatus = WaitForMultipleObjects(
  2875. 2,
  2876. hEvents,
  2877. FALSE,
  2878. INFINITE
  2879. )) == WAIT_FAILED)
  2880. {
  2881. dwRetCode = GetLastError ();
  2882. TRACE1 (ANY, "ElWatchEapConfigRegistryParams: WaitForMultipleObjects failed with error %ld",
  2883. dwRetCode);
  2884. break;
  2885. }
  2886. switch (dwStatus)
  2887. {
  2888. case WAIT_OBJECT_0:
  2889. TRACE0 (ANY, "ElWatchEapConfigRegistryParams: Got reg change event !!! ");
  2890. // Registry values changed
  2891. // Update in memory values
  2892. if ((dwRetCode = ElProcessEapConfigChange ()) != NO_ERROR)
  2893. {
  2894. TRACE1 (ANY, "ElWatchEapConfigRegistryParams: ElProcessEapConfigChange failed with error %ld",
  2895. dwRetCode);
  2896. // log
  2897. // continue processing since this is not a critical error
  2898. dwRetCode = NO_ERROR;
  2899. }
  2900. if (!ResetEvent(hRegChangeEvent))
  2901. {
  2902. dwRetCode = GetLastError ();
  2903. TRACE1 (ANY, "ElWatchEapConfigRegistryParams: ResetEvent failed with error %ld",
  2904. dwRetCode);
  2905. break;
  2906. }
  2907. break;
  2908. case WAIT_OBJECT_0+1:
  2909. // Service shutdown detected
  2910. fExitThread = TRUE;
  2911. TRACE0 (ANY, "ElWatchEapConfigRegistryParams: Service shutdonw");
  2912. break;
  2913. default:
  2914. TRACE1 (ANY, "ElWatchEapConfigRegistryParams: No such event = %ld",
  2915. dwStatus);
  2916. break;
  2917. }
  2918. if ((dwRetCode != NO_ERROR) || (fExitThread))
  2919. {
  2920. break;
  2921. }
  2922. TRACE0 (ANY, "ElWatchEapConfigRegistryParams: RegNotifyChangeKeyValue being reposted !!!");
  2923. } while (TRUE);
  2924. } while (FALSE);
  2925. TRACE1 (ANY, "ElWatchEapConfigRegistryParams: Completed with error %ld",
  2926. dwRetCode);
  2927. if (hUserKey != NULL)
  2928. {
  2929. RegCloseKey(hUserKey);
  2930. }
  2931. if (hWorkspaceKey != NULL)
  2932. {
  2933. RegCloseKey(hWorkspaceKey);
  2934. }
  2935. if (!CloseHandle(hRegChangeEvent))
  2936. {
  2937. TRACE1 (ANY, "ElWatchEapConfigRegistryParams: Error in closing event handle", (dwRetCode = GetLastError()));
  2938. }
  2939. return;
  2940. }
  2941. //
  2942. // ElProcessEapConfigChange
  2943. //
  2944. // Description:
  2945. //
  2946. // Read EAP config changes made in registry. Restart EAPOL on the particular
  2947. // interface or stop EAPOL
  2948. //
  2949. // Arguments:
  2950. //
  2951. // Return values:
  2952. //
  2953. // NO_ERROR - success
  2954. // non-zero - error
  2955. //
  2956. DWORD
  2957. ElProcessEapConfigChange ()
  2958. {
  2959. DWORD dwEapolEnabled = 0;
  2960. DWORD dwDefaultEAPType = 0;
  2961. CHAR szLastUsedSSID[256];
  2962. HKEY hWorkspaceKey = NULL;
  2963. HKEY hKey = NULL, hKey1 = NULL;
  2964. DWORD dwType = 0;
  2965. DWORD dwInfoSize = 0;
  2966. DWORD dwDisposition = 0;
  2967. CHAR *pszLastModifiedGUID = NULL;
  2968. DWORD dwbData = 0;
  2969. PBYTE pbAuthData = NULL;
  2970. EAPOL_PCB *pPCB = NULL;
  2971. BOOL fReStartAuthentication = FALSE;
  2972. LONG lError = 0;
  2973. DWORD dwRetCode = NO_ERROR;
  2974. do
  2975. {
  2976. // Get the GUID for the interface for which EAP config was modified
  2977. // Get handle to
  2978. // HKLM\Software\Microsoft\EAPOL\Parameters\General\EAPOLGlobal
  2979. if ((lError = RegCreateKeyExA (
  2980. HKEY_LOCAL_MACHINE,
  2981. cszEAPOLWorkspace,
  2982. 0,
  2983. NULL,
  2984. REG_OPTION_NON_VOLATILE,
  2985. KEY_READ,
  2986. NULL,
  2987. &hWorkspaceKey,
  2988. &dwDisposition)) != ERROR_SUCCESS)
  2989. {
  2990. TRACE1 (ANY, "ElProcessEapConfigChange: Error in RegCreateKeyExA for cszEAPOLWorkspace key, %ld",
  2991. lError);
  2992. dwRetCode = (DWORD)lError;
  2993. break;
  2994. }
  2995. // Get the value of ..\General\EAPOLGlobal\LastModifiedGUID
  2996. dwInfoSize = 0;
  2997. if ((lError = RegQueryValueExA (
  2998. hWorkspaceKey,
  2999. cszLastModifiedGUID,
  3000. 0,
  3001. &dwType,
  3002. NULL,
  3003. &dwInfoSize)) == ERROR_SUCCESS)
  3004. {
  3005. if ((pszLastModifiedGUID = (CHAR *) MALLOC ( dwInfoSize ))
  3006. == NULL)
  3007. {
  3008. TRACE0 (ANY, "ElProcessEapConfigChange: Error in MALLOC for pszLastModifiedGUID");
  3009. lError = (ULONG) ERROR_NOT_ENOUGH_MEMORY;
  3010. dwRetCode = (DWORD)lError;
  3011. break;
  3012. }
  3013. if ((lError = RegQueryValueExA (
  3014. hWorkspaceKey,
  3015. cszLastModifiedGUID,
  3016. 0,
  3017. &dwType,
  3018. pszLastModifiedGUID,
  3019. &dwInfoSize)) != ERROR_SUCCESS)
  3020. {
  3021. TRACE1 (ANY, "ElProcessEapConfigChange: RegQueryValueExA failed for pszLastModifiedGUID with error %ld",
  3022. lError);
  3023. dwRetCode = (DWORD)lError;
  3024. break;
  3025. }
  3026. }
  3027. else
  3028. {
  3029. TRACE1 (ANY, "ElProcessEapConfigChange: Error in estimating size fo cszLastModifiedGUID = %ld",
  3030. lError);
  3031. break;
  3032. }
  3033. // Check the value of EAPOLEnabled for that interface
  3034. // Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
  3035. if ((lError = RegOpenKeyExA (
  3036. HKEY_LOCAL_MACHINE,
  3037. cszEapKeyEapolConn,
  3038. 0,
  3039. KEY_READ,
  3040. &hKey
  3041. )) != ERROR_SUCCESS)
  3042. {
  3043. TRACE1 (ANY, "ElProcessEapConfigChange: Error in RegOpenKeyExA for base key, %ld",
  3044. lError);
  3045. dwRetCode = (DWORD)lError;
  3046. break;
  3047. }
  3048. // Get handle to HKLM\Software\...\Interfaces\<GUID>
  3049. if ((lError = RegOpenKeyExA (
  3050. hKey,
  3051. pszLastModifiedGUID,
  3052. 0,
  3053. KEY_READ,
  3054. &hKey1
  3055. )) != ERROR_SUCCESS)
  3056. {
  3057. TRACE1 (ANY, "ElProcessEapConfigChange: Error in RegOpenKeyExA for GUID, %ld",
  3058. lError);
  3059. dwRetCode = (DWORD)lError;
  3060. break;
  3061. }
  3062. // Get the value of ..\Interfaces\GUID\EapolEnabled
  3063. // This value should exist since it will always be set from UI
  3064. dwInfoSize = sizeof(DWORD);
  3065. if ((lError = RegQueryValueExA (
  3066. hKey1,
  3067. cszEapolEnabled,
  3068. 0,
  3069. &dwType,
  3070. (BYTE *)&dwEapolEnabled,
  3071. &dwInfoSize)) != ERROR_SUCCESS)
  3072. {
  3073. TRACE2 (ANY, "ElProcessEapConfigChange: Error in RegQueryValueExA for EapolEnabled, %ld, InfoSize=%ld",
  3074. lError, dwInfoSize);
  3075. dwRetCode = (DWORD)lError;
  3076. break;
  3077. }
  3078. TRACE1 (ANY, "ElProcessEapConfigChange: Got EapolEnabled = %ld", dwEapolEnabled);
  3079. // Get the value of ..\Interfaces\GUID\DefaultEAPType
  3080. // This value should exist since it will always be set from UI
  3081. dwInfoSize = sizeof(DWORD);
  3082. if ((lError = RegQueryValueExA (
  3083. hKey1,
  3084. cszDefaultEAPType,
  3085. 0,
  3086. &dwType,
  3087. (BYTE *)&dwDefaultEAPType,
  3088. &dwInfoSize)) != ERROR_SUCCESS)
  3089. {
  3090. TRACE2 (ANY, "ElProcessEapConfigChange: Error in RegQueryValueExA for DefaultEAPType, %ld, InfoSize=%ld",
  3091. lError, dwInfoSize);
  3092. dwRetCode = (DWORD)lError;
  3093. break;
  3094. }
  3095. // Get the value of ..\Interfaces\GUID\LastUsedSSID
  3096. dwInfoSize = 256;
  3097. ZeroMemory ((BYTE *)szLastUsedSSID, 256);
  3098. if ((lError = RegQueryValueExA (
  3099. hKey1,
  3100. cszLastUsedSSID,
  3101. 0,
  3102. &dwType,
  3103. (PUCHAR)szLastUsedSSID,
  3104. &dwInfoSize)) != ERROR_SUCCESS)
  3105. {
  3106. TRACE1 (ANY, "ElProcessEapConfigChange: Error in RegQueryValueExA for LastUsedSSID, %ld",
  3107. lError);
  3108. dwRetCode = (DWORD)lError;
  3109. if (dwRetCode == ERROR_FILE_NOT_FOUND)
  3110. {
  3111. // SSID may not be received as yet from AP/switch
  3112. // Changes will be made stored for "Default" SSID
  3113. dwRetCode = NO_ERROR;
  3114. }
  3115. else
  3116. {
  3117. break;
  3118. }
  3119. }
  3120. // Check existence/absence of PCB i.e. if EAPOL state machine was
  3121. // started on the interface, and take appropriate action based on
  3122. // EAPOLEnabled value
  3123. if (dwEapolEnabled == 0)
  3124. {
  3125. ACQUIRE_WRITE_LOCK (&(g_PCBLock));
  3126. if ((pPCB = ElGetPCBPointerFromPortGUID (pszLastModifiedGUID))
  3127. != NULL)
  3128. {
  3129. RELEASE_WRITE_LOCK (&(g_PCBLock));
  3130. // Found PCB for interface, where EAPOLEnabled = 0
  3131. // Stop EAPOL on the port and remove the port from the module
  3132. if ((dwRetCode = ElShutdownInterface (pszLastModifiedGUID))
  3133. != NO_ERROR)
  3134. {
  3135. TRACE1 (ANY, "ElProcessEapConfigChange: ElShutdownInterface failed with error %ld",
  3136. dwRetCode);
  3137. break;
  3138. }
  3139. }
  3140. else
  3141. {
  3142. // No PCB found for interface, valid condition,
  3143. // continue processing
  3144. RELEASE_WRITE_LOCK (&(g_PCBLock));
  3145. }
  3146. }
  3147. else
  3148. {
  3149. ACQUIRE_WRITE_LOCK (&(g_PCBLock));
  3150. if ((pPCB = ElGetPCBPointerFromPortGUID (pszLastModifiedGUID))
  3151. == NULL)
  3152. {
  3153. RELEASE_WRITE_LOCK (&(g_PCBLock));
  3154. // Did not find PCB for interface, where EAPOLEnabled = 1
  3155. // Start EAPOL on the port
  3156. ACQUIRE_WRITE_LOCK (&g_ITFLock);
  3157. if ((dwRetCode = ElEnumAndOpenInterfaces (NULL,
  3158. pszLastModifiedGUID))
  3159. != NO_ERROR)
  3160. {
  3161. RELEASE_WRITE_LOCK (&g_ITFLock);
  3162. TRACE1 (ANY, "ElProcessEapConfigChange: ElEnumAndOpenInterfaces returned error %ld",
  3163. dwRetCode);
  3164. break;
  3165. }
  3166. RELEASE_WRITE_LOCK (&g_ITFLock);
  3167. }
  3168. else
  3169. {
  3170. ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
  3171. if (pPCB->dwEapTypeToBeUsed != dwDefaultEAPType)
  3172. {
  3173. // Default EAP Type has changed
  3174. fReStartAuthentication = TRUE;
  3175. }
  3176. else
  3177. {
  3178. // Default EAP Type is the same
  3179. // Check if the CustomAuthData is the same
  3180. // If not the same, do further processing
  3181. // Else, no change occured, same config was reapplied
  3182. // Get the size of the EAP blob
  3183. if ((dwRetCode = ElGetCustomAuthData (
  3184. pszLastModifiedGUID,
  3185. dwDefaultEAPType,
  3186. szLastUsedSSID,
  3187. NULL,
  3188. &dwbData
  3189. )) != NO_ERROR)
  3190. {
  3191. if (dwRetCode == ERROR_BUFFER_TOO_SMALL)
  3192. {
  3193. if (dwbData <= 0)
  3194. {
  3195. if (pPCB->pCustomAuthConnData->pbCustomAuthData)
  3196. {
  3197. // No EAP blob stored in the registry
  3198. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  3199. RELEASE_WRITE_LOCK (&(g_PCBLock));
  3200. TRACE0 (ANY, "ElProcessEapConfigChange: NULL sized EAP blob, cannot continue");
  3201. pbAuthData = NULL;
  3202. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  3203. break;
  3204. }
  3205. }
  3206. else
  3207. {
  3208. // Allocate memory to hold the blob
  3209. pbAuthData = MALLOC (dwbData);
  3210. if (pbAuthData == NULL)
  3211. {
  3212. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  3213. RELEASE_WRITE_LOCK (&(g_PCBLock));
  3214. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  3215. TRACE0 (ANY, "ElProcessEapConfigChange: Error in memory allocation for EAP blob");
  3216. break;
  3217. }
  3218. if ((dwRetCode = ElGetCustomAuthData (
  3219. pszLastModifiedGUID,
  3220. dwDefaultEAPType,
  3221. szLastUsedSSID,
  3222. pbAuthData,
  3223. &dwbData
  3224. )) != NO_ERROR)
  3225. {
  3226. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  3227. RELEASE_WRITE_LOCK (&(g_PCBLock));
  3228. TRACE1 (ANY, "ElProcessEapConfigChange: ElGetCustomAuthData failed with %ld",
  3229. dwRetCode);
  3230. break;
  3231. }
  3232. }
  3233. }
  3234. else
  3235. {
  3236. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  3237. RELEASE_WRITE_LOCK (&(g_PCBLock));
  3238. TRACE1 (ANY, "ElProcessEapConfigChange: ElGetCustomAuthData failed in size estimation with error %ld",
  3239. dwRetCode);
  3240. break;
  3241. }
  3242. }
  3243. if (pPCB->pCustomAuthConnData == NULL)
  3244. {
  3245. if (dwbData > 0)
  3246. {
  3247. fReStartAuthentication = TRUE;
  3248. }
  3249. }
  3250. else
  3251. {
  3252. if (pPCB->pCustomAuthConnData->dwSizeOfCustomAuthData
  3253. != dwbData)
  3254. {
  3255. // Same EAP Type, but different lengths
  3256. fReStartAuthentication = TRUE;
  3257. }
  3258. else
  3259. {
  3260. if (memcmp (
  3261. pPCB->pCustomAuthConnData->pbCustomAuthData,
  3262. pbAuthData, dwbData) != 0)
  3263. {
  3264. // Same EAP Type, same data length, but
  3265. // different contents
  3266. fReStartAuthentication = TRUE;
  3267. }
  3268. else
  3269. {
  3270. // No change in EAP config data for this
  3271. // interface
  3272. }
  3273. }
  3274. }
  3275. }
  3276. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  3277. if (fReStartAuthentication)
  3278. {
  3279. if ((dwRetCode = ElReStartPort (pPCB)) != NO_ERROR)
  3280. {
  3281. RELEASE_WRITE_LOCK (&(g_PCBLock));
  3282. TRACE1 (ANY, "ElProcessEapConfigChange: Error in ElReStartPort = %d",
  3283. dwRetCode);
  3284. break;
  3285. }
  3286. }
  3287. RELEASE_WRITE_LOCK (&(g_PCBLock));
  3288. }
  3289. }
  3290. } while (FALSE);
  3291. if (hWorkspaceKey != NULL)
  3292. {
  3293. RegCloseKey(hWorkspaceKey);
  3294. }
  3295. if (hKey != NULL)
  3296. {
  3297. RegCloseKey(hKey);
  3298. }
  3299. if (hKey1 != NULL)
  3300. {
  3301. RegCloseKey(hKey1);
  3302. }
  3303. if (pszLastModifiedGUID != NULL)
  3304. {
  3305. FREE (pszLastModifiedGUID);
  3306. }
  3307. if (pbAuthData != NULL)
  3308. {
  3309. FREE (pbAuthData);
  3310. }
  3311. return dwRetCode;
  3312. }
  3313. //
  3314. // ElStringToGuid
  3315. //
  3316. // Description:
  3317. //
  3318. // Function to convert a Guid-String to a GUID
  3319. //
  3320. // Arguments:
  3321. // psGuid - String-ized Guid
  3322. // pGuid - Pointer to Guid
  3323. //
  3324. // Return values:
  3325. // None
  3326. //
  3327. VOID
  3328. ElStringToGuid (
  3329. IN CHAR * psGuid,
  3330. OUT LPGUID pGuid
  3331. )
  3332. {
  3333. CHAR c;
  3334. DWORD i=0;
  3335. //
  3336. // If the first character is a '{', skip it.
  3337. //
  3338. if ( psGuid[0] == L'{' )
  3339. psGuid++;
  3340. //
  3341. // Convert string to guid
  3342. // (since psGuid may be used again below, no permanent modification to
  3343. // it may be made)
  3344. //
  3345. c = psGuid[8];
  3346. psGuid[8] = 0;
  3347. pGuid->Data1 = strtoul ( &psGuid[0], 0, 16 );
  3348. psGuid[8] = c;
  3349. c = psGuid[13];
  3350. psGuid[13] = 0;
  3351. pGuid->Data2 = (USHORT)strtoul ( &psGuid[9], 0, 16 );
  3352. psGuid[13] = c;
  3353. c = psGuid[18];
  3354. psGuid[18] = 0;
  3355. pGuid->Data3 = (USHORT)strtoul ( &psGuid[14], 0, 16 );
  3356. psGuid[18] = c;
  3357. c = psGuid[21];
  3358. psGuid[21] = 0;
  3359. pGuid->Data4[0] = (unsigned char)strtoul ( &psGuid[19], 0, 16 );
  3360. psGuid[21] = c;
  3361. c = psGuid[23];
  3362. psGuid[23] = 0;
  3363. pGuid->Data4[1] = (unsigned char)strtoul ( &psGuid[21], 0, 16 );
  3364. psGuid[23] = c;
  3365. for ( i=0; i < 6; i++ )
  3366. {
  3367. c = psGuid[26+i*2];
  3368. psGuid[26+i*2] = 0;
  3369. pGuid->Data4[2+i] = (unsigned char)strtoul ( &psGuid[24+i*2], 0, 16 );
  3370. psGuid[26+i*2] = c;
  3371. }
  3372. return;
  3373. }
  3374. //
  3375. // ElGetIdentity
  3376. //
  3377. // Description:
  3378. //
  3379. // Get the identity depending on the authentication type being used
  3380. //
  3381. // Arguments:
  3382. // pPCB - Pointer to PCB for the port
  3383. //
  3384. // Return values:
  3385. //
  3386. // NO_ERROR - success
  3387. // non-zero - error
  3388. //
  3389. DWORD
  3390. ElGetIdentity (
  3391. IN EAPOL_PCB *pPCB
  3392. )
  3393. {
  3394. DWORD dwRetCode = NO_ERROR;
  3395. do
  3396. {
  3397. // Get user's identity if it has not been obtained till now
  3398. if ((g_fUserLoggedOn) &&
  3399. (pPCB->dwAuthFailCount <= EAPOL_MAX_AUTH_FAIL_COUNT) &&
  3400. (pPCB->PreviousAuthenticationType != EAPOL_MACHINE_AUTHENTICATION))
  3401. {
  3402. TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth");
  3403. if (!(pPCB->fGotUserIdentity))
  3404. {
  3405. // NOTE: Hardcoding for now
  3406. // Needs to be solved
  3407. if (pPCB->dwEapTypeToBeUsed == EAP_TYPE_MD5)
  3408. {
  3409. TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth: MD5");
  3410. // EAP-MD5CHAP
  3411. if ((dwRetCode = ElGetUserNamePassword (
  3412. pPCB)) != NO_ERROR)
  3413. {
  3414. TRACE1 (ANY, "ElEapMakeMessage: Error in ElGetUserNamePassword %ld",
  3415. dwRetCode);
  3416. }
  3417. }
  3418. else
  3419. {
  3420. TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth: !MD5");
  3421. // All other EAP Types
  3422. if ((dwRetCode = ElGetUserIdentity (
  3423. pPCB)) != NO_ERROR)
  3424. {
  3425. TRACE1 (ANY, "ElEapMakeMessage: Error in ElGetUserIdentity %ld",
  3426. dwRetCode);
  3427. }
  3428. }
  3429. if (dwRetCode == NO_ERROR)
  3430. {
  3431. TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth: No Error: User Auth fine");
  3432. pPCB->PreviousAuthenticationType = EAPOL_USER_AUTHENTICATION;
  3433. }
  3434. else
  3435. {
  3436. TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth: Error");
  3437. // No UI required
  3438. if ((pPCB->dwEapTypeToBeUsed != EAP_TYPE_MD5) &&
  3439. (g_dwMachineAuthEnabled))
  3440. {
  3441. TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth: Error: !MD5, Machine Auth");
  3442. // Get Machine name
  3443. dwRetCode = NO_ERROR;
  3444. pPCB->PreviousAuthenticationType =
  3445. EAPOL_MACHINE_AUTHENTICATION;
  3446. dwRetCode = ElGetUserIdentity (pPCB);
  3447. if (dwRetCode != NO_ERROR)
  3448. {
  3449. TRACE1 (ANY, "ElGetIdentity: ElGetUserIdentity failed with error %ld",
  3450. dwRetCode);
  3451. }
  3452. }
  3453. if ((dwRetCode != NO_ERROR) ||
  3454. (!g_dwMachineAuthEnabled) ||
  3455. (pPCB->dwEapTypeToBeUsed == EAP_TYPE_MD5))
  3456. {
  3457. TRACE3 (ANY, "ElGetIdentity: Userlogged, <Maxauth, !Machine auth: Error: Error=%ld, Machauth=%ld, MD5=%ld",
  3458. dwRetCode?1:0,
  3459. g_dwMachineAuthEnabled?1:0,
  3460. (pPCB->dwEapTypeToBeUsed == EAP_TYPE_MD5)?1:0);
  3461. if (pPCB->pszIdentity != NULL)
  3462. {
  3463. FREE (pPCB->pszIdentity);
  3464. pPCB->pszIdentity = NULL;
  3465. }
  3466. pPCB->PreviousAuthenticationType = EAPOL_UNAUTHENTICATED_ACCESS;
  3467. dwRetCode = NO_ERROR;
  3468. }
  3469. }
  3470. }
  3471. }
  3472. else
  3473. {
  3474. TRACE2 (ANY, "ElGetIdentity: Userlogged=%ld, auth>max, Machine auth=%ld",
  3475. g_fUserLoggedOn?1:0,
  3476. (pPCB->PreviousAuthenticationType==EAPOL_MACHINE_AUTHENTICATION)?1:0 );
  3477. // No UI required
  3478. if ((pPCB->dwEapTypeToBeUsed != EAP_TYPE_MD5) &&
  3479. (g_dwMachineAuthEnabled))
  3480. {
  3481. TRACE0 (ANY, "ElGetIdentity: !MD5, Machine auth");
  3482. pPCB->PreviousAuthenticationType = EAPOL_MACHINE_AUTHENTICATION;
  3483. // Get Machine credentials
  3484. dwRetCode = ElGetUserIdentity (pPCB);
  3485. if (dwRetCode != NO_ERROR)
  3486. {
  3487. TRACE1 (ANY, "ElGetIdentity: ElGetUserIdentity failed with error %ld",
  3488. dwRetCode);
  3489. }
  3490. }
  3491. if ((dwRetCode != NO_ERROR) ||
  3492. (!g_dwMachineAuthEnabled) ||
  3493. (pPCB->dwEapTypeToBeUsed == EAP_TYPE_MD5))
  3494. {
  3495. TRACE3 (ANY, "ElGetIdentity: Error=%ld, Machine auth=%ld, MD5=%ld",
  3496. dwRetCode?1:0,
  3497. g_dwMachineAuthEnabled?1:0,
  3498. (pPCB->dwEapTypeToBeUsed == EAP_TYPE_MD5)?1:0);
  3499. if (pPCB->pszIdentity != NULL)
  3500. {
  3501. FREE (pPCB->pszIdentity);
  3502. pPCB->pszIdentity = NULL;
  3503. }
  3504. pPCB->PreviousAuthenticationType = EAPOL_UNAUTHENTICATED_ACCESS;
  3505. dwRetCode = NO_ERROR;
  3506. }
  3507. }
  3508. }
  3509. while (FALSE);
  3510. return dwRetCode;
  3511. }
  3512. //
  3513. // ElNLAConnectLPC
  3514. //
  3515. // Description:
  3516. //
  3517. // Function called to connect to the LPC port for NLA service
  3518. //
  3519. // Arguments:
  3520. // None
  3521. //
  3522. // Return values:
  3523. // Non-NULL - valid handle
  3524. // NULL - error
  3525. //
  3526. HANDLE
  3527. ElNLAConnectLPC ()
  3528. {
  3529. HANDLE h = NULL;
  3530. LARGE_INTEGER sectionSize;
  3531. UNICODE_STRING portName;
  3532. SECURITY_QUALITY_OF_SERVICE dynamicQoS =
  3533. {
  3534. sizeof(SECURITY_QUALITY_OF_SERVICE),
  3535. SecurityAnonymous,
  3536. SECURITY_DYNAMIC_TRACKING,
  3537. FALSE
  3538. };
  3539. WSM_LPC_DATA data;
  3540. ULONG dataLength;
  3541. NTSTATUS status = STATUS_SUCCESS;
  3542. do
  3543. {
  3544. TRACE0 (EAP, "NLAConnectLPC: Entered");
  3545. // Create a shared section for passing the large-size LPC messages.
  3546. RtlZeroMemory(&g_ClientView, sizeof(g_ClientView));
  3547. g_ClientView.Length = sizeof(g_ClientView);
  3548. g_ClientView.ViewSize = sizeof(LOCATION_802_1X);
  3549. sectionSize.QuadPart = sizeof(LOCATION_802_1X);
  3550. status = NtCreateSection (&g_ClientView.SectionHandle,
  3551. (SECTION_MAP_READ | SECTION_MAP_WRITE),
  3552. NULL,
  3553. &sectionSize,
  3554. PAGE_READWRITE,
  3555. SEC_COMMIT,
  3556. NULL
  3557. );
  3558. if (!NT_SUCCESS(status))
  3559. {
  3560. h = NULL;
  3561. TRACE1 (EAP, "NLAConnectLPC: NtCreateSection failed with error",
  3562. status);
  3563. break;
  3564. }
  3565. // Connect via LPC to the Network Location Awareness (NLA) service.
  3566. RtlInitUnicodeString (&portName, WSM_PRIVATE_PORT_NAME);
  3567. RtlZeroMemory (&data, sizeof (data));
  3568. data.signature = WSM_SIGNATURE;
  3569. data.connect.version.major = WSM_VERSION_MAJOR;
  3570. data.connect.version.minor = WSM_VERSION_MINOR;
  3571. dataLength = sizeof (data);
  3572. status = NtConnectPort (&h,
  3573. &portName,
  3574. &dynamicQoS,
  3575. &g_ClientView,
  3576. NULL,
  3577. NULL,
  3578. &data,
  3579. &dataLength
  3580. );
  3581. // If NtConnectPort() succeeded, LPC will maintain a reference
  3582. // to the section, otherwise we no longer need it.
  3583. NtClose (g_ClientView.SectionHandle);
  3584. g_ClientView.SectionHandle = NULL;
  3585. if (!NT_SUCCESS(status)) {
  3586. TRACE1 (EAP, "NLAConnectLPC: NtConnectPort failed with error %ld",
  3587. status);
  3588. ASSERT (h == NULL);
  3589. }
  3590. }
  3591. while (FALSE);
  3592. return (h);
  3593. }
  3594. //
  3595. // ElNLACleanupLPC
  3596. //
  3597. // Description:
  3598. //
  3599. // Function called to close the LPC port for NLA service
  3600. //
  3601. // Arguments:
  3602. // None
  3603. //
  3604. // Return values:
  3605. // None
  3606. //
  3607. VOID
  3608. ElNLACleanupLPC ()
  3609. {
  3610. if (g_hNLA_LPC_Port != NULL) {
  3611. NtClose (g_hNLA_LPC_Port);
  3612. g_hNLA_LPC_Port = NULL;
  3613. }
  3614. }
  3615. //
  3616. // ElNLARegister_802_1X
  3617. //
  3618. // Description:
  3619. //
  3620. // Function called to register 802.1X information with NLA
  3621. //
  3622. // Arguments:
  3623. // plocation - Pointer to data needed to be registered with NLA
  3624. //
  3625. // Return values:
  3626. // None
  3627. //
  3628. VOID
  3629. ElNLARegister_802_1X (
  3630. IN PLOCATION_802_1X plocation
  3631. )
  3632. {
  3633. WSM_LPC_MESSAGE message;
  3634. NTSTATUS status;
  3635. ACQUIRE_WRITE_LOCK (&g_NLALock);
  3636. do
  3637. {
  3638. TRACE0 (EAP, "NLARegister_802_1X: Entered");
  3639. // Connect to the Network Location Awareness (NLA) service if
  3640. // necessary.
  3641. if (g_hNLA_LPC_Port == NULL) {
  3642. if ((g_hNLA_LPC_Port = ElNLAConnectLPC ()) == NULL) {
  3643. RELEASE_WRITE_LOCK (&g_NLALock);
  3644. return;
  3645. }
  3646. }
  3647. TRACE0 (EAP, "NLARegister_802_1X: g_hNLA_LPC_Port != NULL");
  3648. // Send information to the NLA service.
  3649. RtlZeroMemory (&message, sizeof (message));
  3650. message.portMsg.u1.s1.TotalLength = sizeof (message);
  3651. message.portMsg.u1.s1.DataLength = sizeof (message.data);
  3652. message.data.signature = WSM_SIGNATURE;
  3653. message.data.request.type = LOCATION_802_1X_REGISTER;
  3654. __try {
  3655. RtlCopyMemory (g_ClientView.ViewBase,
  3656. plocation, sizeof(LOCATION_802_1X));
  3657. }
  3658. __except (EXCEPTION_EXECUTE_HANDLER) {
  3659. return;
  3660. }
  3661. status = NtRequestWaitReplyPort ( g_hNLA_LPC_Port, (PPORT_MESSAGE)&message, (PPORT_MESSAGE)&message);
  3662. if (status != STATUS_SUCCESS) {
  3663. TRACE1 (EAP, "NLARegister_802_1X: NtWaitReplyPort failed with error",
  3664. status);
  3665. // It's possible the service was stopped and restarted.
  3666. // Ditch the old LPC connection.
  3667. CloseHandle (g_hNLA_LPC_Port);
  3668. // Create a new LPC connection.
  3669. if ((g_hNLA_LPC_Port = ElNLAConnectLPC ()) == NULL) {
  3670. RELEASE_WRITE_LOCK (&g_NLALock);
  3671. TRACE0 (EAP, "NLARegister_802_1X: NLAConnectLPC failed");
  3672. return;
  3673. }
  3674. // Try the send one last time.
  3675. status = NtRequestWaitReplyPort (g_hNLA_LPC_Port,
  3676. (PPORT_MESSAGE)&message, (PPORT_MESSAGE)&message);
  3677. TRACE1 (EAP, "NLARegister_802_1X: NtWaitReplyPort, try 2, failed with error",
  3678. status);
  3679. }
  3680. TRACE1 (EAP, "NLARegister_802_1X: Completed with status = %ld",
  3681. status);
  3682. }
  3683. while (FALSE);
  3684. RELEASE_WRITE_LOCK (&g_NLALock);
  3685. }
  3686. //
  3687. // ElNLADelete_802_1X
  3688. //
  3689. // Description:
  3690. //
  3691. // Function called to de-register 802.1X information registered with NLA
  3692. //
  3693. // Arguments:
  3694. // plocation - Pointer to data to be de-registered from NLA
  3695. //
  3696. // Return values:
  3697. // None
  3698. //
  3699. VOID
  3700. ElNLADelete_802_1X (
  3701. IN PLOCATION_802_1X plocation
  3702. )
  3703. {
  3704. WSM_LPC_MESSAGE message;
  3705. NTSTATUS status;
  3706. ACQUIRE_WRITE_LOCK (&g_NLALock);
  3707. do
  3708. {
  3709. // Connect to the NLA service if necessary.
  3710. if (g_hNLA_LPC_Port == NULL)
  3711. {
  3712. if ((g_hNLA_LPC_Port = ElNLAConnectLPC ()) == NULL)
  3713. {
  3714. RELEASE_WRITE_LOCK (&g_NLALock);
  3715. return;
  3716. }
  3717. }
  3718. // Send information to the NLA service.
  3719. RtlZeroMemory (&message, sizeof(message));
  3720. message.portMsg.u1.s1.TotalLength = sizeof (message);
  3721. message.portMsg.u1.s1.DataLength = sizeof (message.data);
  3722. message.data.signature = WSM_SIGNATURE;
  3723. message.data.request.type = LOCATION_802_1X_DELETE;
  3724. __try {
  3725. RtlCopyMemory (g_ClientView.ViewBase,
  3726. plocation, sizeof(plocation->adapterName));
  3727. }
  3728. __except (EXCEPTION_EXECUTE_HANDLER) {
  3729. return;
  3730. }
  3731. status = NtRequestWaitReplyPort (g_hNLA_LPC_Port,
  3732. (PPORT_MESSAGE)&message, (PPORT_MESSAGE)&message);
  3733. if (status != STATUS_SUCCESS)
  3734. {
  3735. // If the service was stopped (and possibly restarted), we don't
  3736. // care ... it won't have this information in its list for us
  3737. // to bother deleting.
  3738. CloseHandle (g_hNLA_LPC_Port);
  3739. g_hNLA_LPC_Port = NULL;
  3740. }
  3741. }
  3742. while (FALSE);
  3743. RELEASE_WRITE_LOCK (&g_NLALock);
  3744. }
  3745. //
  3746. // ElGetInterfaceNdisStatistics
  3747. //
  3748. // Function to query NDIS NIC_STATISTICS parameters for an interface
  3749. //
  3750. // Input arguments:
  3751. // pszInterfaceName - Interface Name
  3752. //
  3753. // Return values:
  3754. // pStats - NIC_STATISTICS structure
  3755. //
  3756. //
  3757. DWORD
  3758. ElGetInterfaceNdisStatistics (
  3759. IN CHAR *pszInterfaceName,
  3760. IN OUT NIC_STATISTICS *pStats
  3761. )
  3762. {
  3763. WCHAR *pwszInterfaceName = NULL;
  3764. UNICODE_STRING UInterfaceName;
  3765. DWORD dwRetCode = NO_ERROR;
  3766. do
  3767. {
  3768. pwszInterfaceName = MALLOC ((strlen (pszInterfaceName)+12)*sizeof(WCHAR));
  3769. if (pwszInterfaceName == NULL)
  3770. {
  3771. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  3772. TRACE0 (ANY, "ElGetInterfaceNdisStatistics: MALLOC failed for pwszInterfaceName");
  3773. break;
  3774. }
  3775. wcscpy (pwszInterfaceName, L"\\Device\\{");
  3776. if (0 == MultiByteToWideChar(
  3777. CP_ACP,
  3778. 0,
  3779. pszInterfaceName,
  3780. -1,
  3781. &pwszInterfaceName[9],
  3782. (strlen(pszInterfaceName)+12)*sizeof(WCHAR)))
  3783. {
  3784. dwRetCode = GetLastError();
  3785. TRACE2 (ANY, "ElGetInterfaceNdisStatistics: MultiByteToWideChar(%s) failed: %ld",
  3786. pszInterfaceName, dwRetCode);
  3787. break;
  3788. }
  3789. pwszInterfaceName[strlen(pszInterfaceName) + 9] = L'\0';
  3790. wcscat (pwszInterfaceName, L"}");
  3791. TRACE1 (ANY, "ElGetInterfaceNdisStatistics: pwszInterfaceName = (%ws)",
  3792. pwszInterfaceName);
  3793. RtlInitUnicodeString (&UInterfaceName, pwszInterfaceName);
  3794. pStats->Size = sizeof(NIC_STATISTICS);
  3795. if (NdisQueryStatistics (&UInterfaceName, pStats))
  3796. {
  3797. }
  3798. else
  3799. {
  3800. dwRetCode = GetLastError ();
  3801. TRACE2 (ANY, "ElGetInterfaceNdisStatistics: NdisQueryStatistics failed with error (%ld), Interface=%ws",
  3802. dwRetCode, UInterfaceName.Buffer);
  3803. }
  3804. }
  3805. while (FALSE);
  3806. if (pwszInterfaceName != NULL)
  3807. {
  3808. FREE (pwszInterfaceName);
  3809. }
  3810. return dwRetCode;
  3811. }