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.

7931 lines
223 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 cwszEapKeyEapolUser L"Software\\Microsoft\\EAPOL\\UserEapInfo"
  18. // Location of Connection blob
  19. #define cwszEapKeyEapolConn L"Software\\Microsoft\\EAPOL\\Parameters\\Interfaces"
  20. // Location of EAPOL Parameters Service
  21. #define cwszEapKeyEapolServiceParams L"Software\\Microsoft\\EAPOL\\Parameters\\General"
  22. // Location of EAPOL Global state machine params
  23. #define cwszEAPOLGlobalParams L"Software\\Microsoft\\EAPOL\\Parameters\\General\\Global"
  24. // Location of policy parameters
  25. #define cwszEAPOLPolicyParams L"Software\\Policies\\Microsoft\\Windows\\Network Connections\\8021X"
  26. // Location of netman dll
  27. #define NETMAN_DLL_PATH L"%SystemRoot%\\system32\\netman.dll"
  28. #define cwszEapolEnabled L"EapolEnabled"
  29. #define cwszDefaultEAPType L"DefaultEAPType"
  30. #define cwszLastUsedSSID L"LastUsedSSID"
  31. #define cwszInterfaceList L"InterfaceList"
  32. #define cwszAuthPeriod L"authPeriod"
  33. #define cwszHeldPeriod L"heldPeriod"
  34. #define cwszStartPeriod L"startPeriod"
  35. #define cwszMaxStart L"maxStart"
  36. #define cwszSupplicantMode L"SupplicantMode"
  37. #define cwszAuthMode L"AuthMode"
  38. #define cszCARootHash "8021XCARootHash"
  39. #define SIZE_OF_CA_CONV_STR 3
  40. #define PASSWORDMAGIC 0xA5
  41. #define WZCSVC_SERVICE_NAME L"WZCSVC"
  42. //
  43. // EAPOLRESPUI function mapping
  44. //
  45. EAPOLUIRESPFUNCMAP EapolUIRespFuncMap[NUM_EAPOL_DLG_MSGS]=
  46. {
  47. {EAPOLUI_GET_USERIDENTITY, ElProcessUserIdentityResponse, 3},
  48. {EAPOLUI_GET_USERNAMEPASSWORD, ElProcessUserNamePasswordResponse, 2},
  49. {EAPOLUI_INVOKEINTERACTIVEUI, ElProcessInvokeInteractiveUIResponse, 1},
  50. {EAPOLUI_EAP_NOTIFICATION, NULL, 0},
  51. {EAPOLUI_REAUTHENTICATE, ElProcessReauthResponse, 0},
  52. {EAPOLUI_CREATEBALLOON, NULL, 0},
  53. {EAPOLUI_CLEANUP, NULL, 0}
  54. };
  55. BYTE g_bDefaultSSID[MAX_SSID_LEN]={0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22};
  56. #define MAX_VALUENAME_LEN 33
  57. //
  58. // HostToWireFormat16
  59. //
  60. // Description:
  61. //
  62. // Will convert a 16 bit integer from host format to wire format
  63. //
  64. VOID
  65. HostToWireFormat16 (
  66. IN WORD wHostFormat,
  67. IN OUT PBYTE pWireFormat
  68. )
  69. {
  70. *((PBYTE)(pWireFormat)+0) = (BYTE) ((DWORD)(wHostFormat) >> 8);
  71. *((PBYTE)(pWireFormat)+1) = (BYTE) (wHostFormat);
  72. }
  73. //
  74. // WireToHostFormat16
  75. //
  76. // Description:
  77. //
  78. // Will convert a 16 bit integer from wire format to host format
  79. //
  80. WORD
  81. WireToHostFormat16 (
  82. IN PBYTE pWireFormat
  83. )
  84. {
  85. WORD wHostFormat = ((*((PBYTE)(pWireFormat)+0) << 8) +
  86. (*((PBYTE)(pWireFormat)+1)));
  87. return( wHostFormat );
  88. }
  89. //
  90. // HostToWireFormat32
  91. //
  92. // Description:
  93. //
  94. // Will convert a 32 bit integer from host format to wire format
  95. //
  96. VOID
  97. HostToWireFormat32 (
  98. IN DWORD dwHostFormat,
  99. IN OUT PBYTE pWireFormat
  100. )
  101. {
  102. *((PBYTE)(pWireFormat)+0) = (BYTE) ((DWORD)(dwHostFormat) >> 24);
  103. *((PBYTE)(pWireFormat)+1) = (BYTE) ((DWORD)(dwHostFormat) >> 16);
  104. *((PBYTE)(pWireFormat)+2) = (BYTE) ((DWORD)(dwHostFormat) >> 8);
  105. *((PBYTE)(pWireFormat)+3) = (BYTE) (dwHostFormat);
  106. }
  107. //
  108. // WireToHostFormat32
  109. //
  110. // Description:
  111. //
  112. // Will convert a 32 bit integer from wire format to host format
  113. //
  114. DWORD
  115. WireToHostFormat32 (
  116. IN PBYTE pWireFormat
  117. )
  118. {
  119. DWORD dwHostFormat = ((*((PBYTE)(pWireFormat)+0) << 24) +
  120. (*((PBYTE)(pWireFormat)+1) << 16) +
  121. (*((PBYTE)(pWireFormat)+2) << 8) +
  122. (*((PBYTE)(pWireFormat)+3) ));
  123. return( dwHostFormat );
  124. }
  125. //
  126. // ElSetCustomAuthData
  127. //
  128. // Description:
  129. //
  130. // Function called to set the connection data for an interface for a specific
  131. // EAP type and SSID (if any). Data will be stored in the HKLM hive
  132. //
  133. // Arguments:
  134. // pwszGUID - pointer to GUID string for the interface
  135. // dwEapTypeId - EAP type for which connection data is to be stored
  136. // dwSizeOfSSID - Size of special identifier, if any, for the EAP blob
  137. // pwszSSID - Special identifier, if any, for the EAP blob
  138. // pbConnInfo - pointer to EAP connection data blob
  139. // pdwInfoSize - Size of EAP connection blob
  140. //
  141. // Return values:
  142. // NO_ERROR - success
  143. // non-zero - error
  144. //
  145. DWORD
  146. ElSetCustomAuthData (
  147. IN WCHAR *pwszGUID,
  148. IN DWORD dwEapTypeId,
  149. IN DWORD dwSizeOfSSID,
  150. IN BYTE *pbSSID,
  151. IN PBYTE pbConnInfo,
  152. IN DWORD *pdwInfoSize
  153. )
  154. {
  155. HKEY hkey = NULL;
  156. HKEY hkey1 = NULL;
  157. DWORD dwDisposition;
  158. DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwMaxValueLen = 0;
  159. DWORD dwIndex = 0, dwMaxValueName = 0;
  160. BYTE *pbValueBuf = NULL;
  161. DWORD dwValueData = 0;
  162. WCHAR *pwszValueName = NULL;
  163. WCHAR wcszValueName[MAX_VALUENAME_LEN];
  164. BYTE *pbDefaultValue = NULL;
  165. DWORD dwDefaultValueLen = 0;
  166. BYTE *pbEapBlob = NULL, *pbEapBlobIn = NULL;
  167. DWORD dwEapBlob = 0;
  168. BOOLEAN fFoundValue = FALSE;
  169. EAPOL_INTF_PARAMS *pRegParams = NULL;
  170. EAPOL_INTF_PARAMS *pDefIntfParams = NULL;
  171. LONG lError = ERROR_SUCCESS;
  172. DWORD dwRetCode = ERROR_SUCCESS;
  173. do
  174. {
  175. // Validate input params
  176. if (pwszGUID == NULL)
  177. {
  178. TRACE0 (ANY, "ElSetCustomAuthData: GUID = NULL");
  179. dwRetCode = ERROR_INVALID_PARAMETER;
  180. break;
  181. }
  182. if (dwEapTypeId == 0)
  183. {
  184. TRACE0 (ANY, "ElSetCustomAuthData: GUID = NULL");
  185. dwRetCode = ERROR_INVALID_PARAMETER;
  186. break;
  187. }
  188. if (dwSizeOfSSID > MAX_SSID_LEN)
  189. {
  190. TRACE1 (ANY, "ElSetCustomAuthData: Invalid SSID length = (%ld)",
  191. dwSizeOfSSID);
  192. dwRetCode = ERROR_INVALID_PARAMETER;
  193. break;
  194. }
  195. // Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
  196. if ((lError = RegCreateKeyEx (
  197. HKEY_LOCAL_MACHINE,
  198. cwszEapKeyEapolConn,
  199. 0,
  200. NULL,
  201. REG_OPTION_NON_VOLATILE,
  202. KEY_ALL_ACCESS,
  203. NULL,
  204. &hkey,
  205. &dwDisposition)) != ERROR_SUCCESS)
  206. {
  207. TRACE1 (ANY, "ElSetCustomAuthData: Error in RegCreateKeyEx for base key, %ld",
  208. lError);
  209. dwRetCode = (DWORD)lError;
  210. break;
  211. }
  212. // Get handle to HKLM\Software\...\Interfaces\<GUID>
  213. if ((lError = RegCreateKeyEx (
  214. hkey,
  215. pwszGUID,
  216. 0,
  217. NULL,
  218. REG_OPTION_NON_VOLATILE,
  219. KEY_ALL_ACCESS,
  220. NULL,
  221. &hkey1,
  222. &dwDisposition)) != ERROR_SUCCESS)
  223. {
  224. TRACE1 (ANY, "ElSetCustomAuthData: Error in RegCreateKeyEx for GUID, %ld",
  225. lError);
  226. dwRetCode = (DWORD)lError;
  227. break;
  228. }
  229. // Work with appropriate SSID
  230. if ((dwSizeOfSSID == 0) || (pbSSID == NULL))
  231. {
  232. pbSSID = g_bDefaultSSID;
  233. dwSizeOfSSID = MAX_SSID_LEN;
  234. }
  235. if ((lError = RegQueryInfoKey (
  236. hkey1,
  237. NULL,
  238. NULL,
  239. NULL,
  240. NULL,
  241. NULL,
  242. NULL,
  243. &dwNumValues,
  244. &dwMaxValueNameLen,
  245. &dwMaxValueLen,
  246. NULL,
  247. NULL
  248. )) != NO_ERROR)
  249. {
  250. dwRetCode = (DWORD)lError;
  251. TRACE1 (ANY, "ElSetCustomAuthData: RegQueryInfoKey failed with error %ld",
  252. dwRetCode);
  253. break;
  254. }
  255. if (dwMaxValueNameLen > MAX_VALUENAME_LEN)
  256. {
  257. TRACE1 (ANY, "ElSetCustomAuthData: Valuename too long (%ld)",
  258. dwMaxValueLen);
  259. break;
  260. }
  261. if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL)
  262. {
  263. TRACE0 (ANY, "ElSetCustomAuthData: MALLOC failed for pbValueBuf");
  264. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  265. break;
  266. }
  267. for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++)
  268. {
  269. dwValueData = dwMaxValueLen;
  270. dwMaxValueNameLen = MAX_VALUENAME_LEN;
  271. ZeroMemory (&wcszValueName, MAX_VALUENAME_LEN*sizeof(WCHAR));
  272. if ((lError = RegEnumValue (
  273. hkey1,
  274. dwIndex,
  275. wcszValueName,
  276. &dwMaxValueNameLen,
  277. NULL,
  278. NULL,
  279. pbValueBuf,
  280. &dwValueData
  281. )) != ERROR_SUCCESS)
  282. {
  283. if (lError != ERROR_MORE_DATA)
  284. {
  285. break;
  286. }
  287. lError = ERROR_SUCCESS;
  288. }
  289. if (dwValueData < sizeof (EAPOL_INTF_PARAMS))
  290. {
  291. TRACE0 (ANY, "ElSetCustomAuthData: dwValueData < sizeof (EAPOL_INTF_PARAMS");
  292. lError = ERROR_INVALID_DATA;
  293. break;
  294. }
  295. pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
  296. if (((DWORD)_wtol(wcszValueName)) > dwMaxValueName)
  297. {
  298. dwMaxValueName = _wtol (wcszValueName);
  299. }
  300. if (!memcmp (pRegParams->bSSID, pbSSID, dwSizeOfSSID))
  301. {
  302. fFoundValue = TRUE;
  303. break;
  304. }
  305. if (!memcmp (pRegParams->bSSID, g_bDefaultSSID, MAX_SSID_LEN))
  306. {
  307. if ((pbDefaultValue = MALLOC (dwValueData)) == NULL)
  308. {
  309. TRACE0 (ANY, "ElSetCustomAuthData: MALLOC failed for pbDefaultValue");
  310. lError = ERROR_NOT_ENOUGH_MEMORY;
  311. break;
  312. }
  313. memcpy (pbDefaultValue, pbValueBuf, dwValueData);
  314. dwDefaultValueLen = dwValueData;
  315. }
  316. }
  317. if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS))
  318. {
  319. dwRetCode = (DWORD)lError;
  320. TRACE1 (ANY, "ElSetCustomAuthData: RegQueryInfoKey failed with error %ld",
  321. dwRetCode);
  322. break;
  323. }
  324. else
  325. {
  326. lError = ERROR_SUCCESS;
  327. }
  328. if (!fFoundValue)
  329. {
  330. DWORD dwNewValueName = (dwMaxValueName >= dwNumValues)?(++dwMaxValueName):dwNumValues;
  331. _ltow (dwNewValueName, wcszValueName, 10);
  332. if ((pbDefaultValue = MALLOC (sizeof(EAPOL_INTF_PARAMS))) == NULL)
  333. {
  334. TRACE0 (ANY, "ElSetCustomAuthData: MALLOC failed for pbDefaultValue");
  335. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  336. break;
  337. }
  338. pDefIntfParams = (EAPOL_INTF_PARAMS *)pbDefaultValue;
  339. pDefIntfParams->dwEapFlags = DEFAULT_EAP_STATE;
  340. pDefIntfParams->dwEapType = dwEapTypeId;
  341. pDefIntfParams->dwVersion = EAPOL_CURRENT_VERSION;
  342. pDefIntfParams->dwSizeOfSSID = dwSizeOfSSID;
  343. memcpy (pDefIntfParams->bSSID, pbSSID, dwSizeOfSSID);
  344. dwEapBlob = sizeof(EAPOL_INTF_PARAMS);
  345. pbEapBlob = pbDefaultValue;
  346. }
  347. else
  348. {
  349. // Use pbValueBuf & dwValueData
  350. pbEapBlob = pbValueBuf;
  351. dwEapBlob = dwValueData;
  352. }
  353. pbEapBlobIn = pbEapBlob;
  354. if ((dwRetCode = ElSetEapData (
  355. dwEapTypeId,
  356. &dwEapBlob,
  357. &pbEapBlob,
  358. sizeof (EAPOL_INTF_PARAMS),
  359. *pdwInfoSize,
  360. pbConnInfo
  361. )) != NO_ERROR)
  362. {
  363. TRACE1 (ANY, "ElSetCustomAuthData: ElSetEapData failed with error %ld",
  364. dwRetCode);
  365. break;
  366. }
  367. // Overwrite/Create new value
  368. if ((lError = RegSetValueEx (
  369. hkey1,
  370. wcszValueName,
  371. 0,
  372. REG_BINARY,
  373. pbEapBlob,
  374. dwEapBlob)) != ERROR_SUCCESS)
  375. {
  376. TRACE1 (ANY, "ElSetCustomAuthData: Error in RegSetValueEx for SSID, %ld",
  377. lError);
  378. dwRetCode = (DWORD)lError;
  379. break;
  380. }
  381. TRACE0 (ANY, "ElSetCustomAuthData: Set value succeeded");
  382. } while (FALSE);
  383. if (hkey != NULL)
  384. {
  385. RegCloseKey (hkey);
  386. }
  387. if (hkey1 != NULL)
  388. {
  389. RegCloseKey (hkey1);
  390. }
  391. if ((pbEapBlob != pbEapBlobIn) && (pbEapBlob != NULL))
  392. {
  393. FREE (pbEapBlob);
  394. }
  395. if (pbValueBuf != NULL)
  396. {
  397. FREE (pbValueBuf);
  398. }
  399. if (pbDefaultValue != NULL)
  400. {
  401. FREE (pbDefaultValue);
  402. }
  403. return dwRetCode;
  404. }
  405. //
  406. // ElGetCustomAuthData
  407. //
  408. // Description:
  409. //
  410. // Function called to retrieve the connection data for an interface for a
  411. // specific EAP type and SSID (if any). Data is retrieved from the HKLM hive
  412. //
  413. // Arguments:
  414. //
  415. // pwszGUID - pointer to GUID string for the interface
  416. // dwEapTypeId - EAP type for which connection data is to be retrieved
  417. // dwSizeOfSSID - Size of Special identifier if any for the EAP blob
  418. // pbSSID - Special identifier if any for the EAP blob
  419. // pbConnInfo - output: pointer to EAP connection data blob
  420. // pdwInfoSize - output: pointer to size of EAP connection blob
  421. //
  422. // Return values:
  423. //
  424. // NO_ERROR - success
  425. // non-zero - error
  426. //
  427. DWORD
  428. ElGetCustomAuthData (
  429. IN WCHAR *pwszGUID,
  430. IN DWORD dwEapTypeId,
  431. IN DWORD dwSizeOfSSID,
  432. IN BYTE *pbSSID,
  433. IN OUT BYTE *pbConnInfo,
  434. IN OUT DWORD *pdwInfoSize
  435. )
  436. {
  437. HKEY hkey = NULL;
  438. HKEY hkey1 = NULL;
  439. DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwTempValueNameLen = 0, dwMaxValueLen = 0;
  440. DWORD dwIndex = 0, dwMaxValueName = 0;
  441. WCHAR *pwszValueName = NULL;
  442. BYTE *pbValueBuf = NULL;
  443. DWORD dwValueData = 0;
  444. BYTE *pbDefaultValue = NULL;
  445. DWORD dwDefaultValueLen = 0;
  446. BYTE *pbEapBlob = NULL;
  447. DWORD dwEapBlob = 0;
  448. BYTE *pbAuthData = NULL;
  449. DWORD dwAuthData = 0;
  450. BYTE *pbAuthDataIn = NULL;
  451. DWORD dwAuthDataIn = 0;
  452. BOOLEAN fFreeAuthData = FALSE;
  453. BOOLEAN fFoundValue = FALSE;
  454. EAPOL_INTF_PARAMS *pRegParams = NULL;
  455. LONG lError = ERROR_SUCCESS;
  456. DWORD dwRetCode = ERROR_SUCCESS;
  457. do
  458. {
  459. // Validate input params
  460. if (pwszGUID == NULL)
  461. {
  462. TRACE0 (ANY, "ElGetCustomAuthData: GUID = NULL");
  463. dwRetCode = ERROR_INVALID_PARAMETER;
  464. break;
  465. }
  466. if (dwEapTypeId == 0)
  467. {
  468. TRACE0 (ANY, "ElGetCustomAuthData: EapTypeId invalid");
  469. dwRetCode = ERROR_INVALID_PARAMETER;
  470. break;
  471. }
  472. if (dwSizeOfSSID > MAX_SSID_LEN)
  473. {
  474. TRACE1 (ANY, "ElGetCustomAuthData: Invalid SSID length = (%ld)",
  475. dwSizeOfSSID);
  476. dwRetCode = ERROR_INVALID_PARAMETER;
  477. break;
  478. }
  479. // Work with appropriate SSID
  480. if ((dwSizeOfSSID == 0) || (pbSSID == NULL))
  481. {
  482. pbSSID = g_bDefaultSSID;
  483. dwSizeOfSSID = MAX_SSID_LEN;
  484. }
  485. // Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
  486. if ((lError = RegOpenKeyEx (
  487. HKEY_LOCAL_MACHINE,
  488. cwszEapKeyEapolConn,
  489. 0,
  490. KEY_READ,
  491. &hkey
  492. )) != ERROR_SUCCESS)
  493. {
  494. // Assume no value is found and proceed ahead
  495. if (lError == ERROR_FILE_NOT_FOUND)
  496. {
  497. lError = ERROR_SUCCESS;
  498. fFoundValue = FALSE;
  499. goto LNotFoundValue;
  500. }
  501. else
  502. {
  503. TRACE1 (ANY, "ElGetCustomAuthData: Error in RegOpenKeyEx for base key, %ld",
  504. lError);
  505. dwRetCode = (DWORD)lError;
  506. break;
  507. }
  508. }
  509. // Get handle to HKLM\Software\...\Interfaces\<GUID>
  510. if ((lError = RegOpenKeyEx (
  511. hkey,
  512. pwszGUID,
  513. 0,
  514. KEY_READ,
  515. &hkey1
  516. )) != ERROR_SUCCESS)
  517. {
  518. // Assume no value is found and proceed ahead
  519. if (lError == ERROR_FILE_NOT_FOUND)
  520. {
  521. lError = ERROR_SUCCESS;
  522. fFoundValue = FALSE;
  523. goto LNotFoundValue;
  524. }
  525. else
  526. {
  527. TRACE1 (ANY, "ElGetCustomAuthData: Error in RegOpenKeyEx for GUID, %ld",
  528. lError);
  529. dwRetCode = (DWORD)lError;
  530. break;
  531. }
  532. }
  533. if ((lError = RegQueryInfoKey (
  534. hkey1,
  535. NULL,
  536. NULL,
  537. NULL,
  538. NULL,
  539. NULL,
  540. NULL,
  541. &dwNumValues,
  542. &dwMaxValueNameLen,
  543. &dwMaxValueLen,
  544. NULL,
  545. NULL
  546. )) != NO_ERROR)
  547. {
  548. dwRetCode = (DWORD)lError;
  549. TRACE1 (ANY, "ElGetCustomAuthData: RegQueryInfoKey failed with error %ld",
  550. dwRetCode);
  551. break;
  552. }
  553. if ((pwszValueName = MALLOC ((dwMaxValueNameLen + 1) * sizeof (WCHAR))) == NULL)
  554. {
  555. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  556. TRACE0 (ANY, "ElGetCustomAuthData: MALLOC failed for pwszValueName");
  557. break;
  558. }
  559. dwMaxValueNameLen++;
  560. if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL)
  561. {
  562. TRACE0 (ANY, "ElGetCustomAuthData: MALLOC failed for pbValueBuf");
  563. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  564. break;
  565. }
  566. for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++)
  567. {
  568. dwTempValueNameLen = dwMaxValueNameLen;
  569. dwValueData = dwMaxValueLen;
  570. ZeroMemory ((VOID *)pwszValueName, dwMaxValueNameLen*sizeof(WCHAR));
  571. ZeroMemory ((VOID *)pbValueBuf, dwMaxValueLen);
  572. if ((lError = RegEnumValue (
  573. hkey1,
  574. dwIndex,
  575. pwszValueName,
  576. &dwTempValueNameLen,
  577. NULL,
  578. NULL,
  579. pbValueBuf,
  580. &dwValueData
  581. )) != ERROR_SUCCESS)
  582. {
  583. if (lError != ERROR_MORE_DATA)
  584. {
  585. break;
  586. }
  587. lError = ERROR_SUCCESS;
  588. }
  589. if (dwValueData < sizeof (EAPOL_INTF_PARAMS))
  590. {
  591. lError = ERROR_INVALID_DATA;
  592. TRACE0 (ANY, "ElGetCustomAuthData: dwValueData < sizeof (EAPOL_INTF_PARAMS)");
  593. break;
  594. }
  595. pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
  596. if (((DWORD)_wtol(pwszValueName)) > dwMaxValueName)
  597. {
  598. dwMaxValueName = _wtol (pwszValueName);
  599. }
  600. if (!memcmp (pRegParams->bSSID, pbSSID, dwSizeOfSSID))
  601. {
  602. fFoundValue = TRUE;
  603. break;
  604. }
  605. }
  606. if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS))
  607. {
  608. dwRetCode = (DWORD)lError;
  609. TRACE1 (ANY, "ElGetCustomAuthData: RegEnumValue 2 failed with error %ld",
  610. dwRetCode);
  611. break;
  612. }
  613. else
  614. {
  615. lError = ERROR_SUCCESS;
  616. }
  617. LNotFoundValue:
  618. // For SSIDs for which there is no blob stored, create default blob
  619. // For default SSID, there should have been a blob created
  620. if (!fFoundValue)
  621. {
  622. if ((dwRetCode = ElCreateDefaultEapData (&dwDefaultValueLen, NULL)) == ERROR_BUFFER_TOO_SMALL)
  623. {
  624. EAPOL_INTF_PARAMS IntfParams;
  625. IntfParams.dwVersion = EAPOL_CURRENT_VERSION;
  626. if ((pbDefaultValue = MALLOC (dwDefaultValueLen)) == NULL)
  627. {
  628. TRACE0 (ANY, "ElGetCustomAuthData: MALLOC failed for Conn Prop");
  629. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  630. break;
  631. }
  632. if ((dwRetCode = ElCreateDefaultEapData (&dwDefaultValueLen, pbDefaultValue)) != NO_ERROR)
  633. {
  634. TRACE1 (ANY, "ElGetCustomAuthData: ElCreateDefaultEapData failed with error (%ld)",
  635. dwRetCode);
  636. break;
  637. }
  638. pbEapBlob = (BYTE *)&IntfParams;
  639. dwEapBlob = sizeof (EAPOL_INTF_PARAMS);
  640. if ((dwRetCode = ElSetEapData (
  641. DEFAULT_EAP_TYPE,
  642. &dwEapBlob,
  643. &pbEapBlob,
  644. sizeof (EAPOL_INTF_PARAMS),
  645. dwDefaultValueLen,
  646. pbDefaultValue
  647. )) != NO_ERROR)
  648. {
  649. TRACE1 (ANY, "ElGetCustomAuthData: ElSetEapData failed with error %ld",
  650. dwRetCode);
  651. break;
  652. }
  653. // Assign to pbDefaultValue for freeing later on
  654. FREE (pbDefaultValue);
  655. pbDefaultValue = pbEapBlob;
  656. dwDefaultValueLen = dwEapBlob;
  657. }
  658. else
  659. {
  660. TRACE0 (ANY, "ElGetCustomAuthData: ElCreateDefaultEapData should have failed !!!");
  661. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  662. break;
  663. }
  664. // Use pbDefaultValue & dwDefaultValueLen
  665. pbEapBlob = pbDefaultValue;
  666. dwEapBlob = dwDefaultValueLen;
  667. }
  668. else
  669. {
  670. if (fFoundValue)
  671. {
  672. // Use pbValueBuf & dwValueData
  673. pbEapBlob = pbValueBuf;
  674. dwEapBlob = dwValueData;
  675. }
  676. }
  677. // If default blob is not present, exit
  678. if ((pbEapBlob == NULL) && (dwEapBlob == 0))
  679. {
  680. TRACE0 (ANY, "ElGetCustomAuthData: (pbEapBlob == NULL) && (dwEapBlob == 0)");
  681. dwRetCode = ERROR_INVALID_DATA;
  682. break;
  683. }
  684. if ((dwRetCode = ElGetEapData (
  685. dwEapTypeId,
  686. dwEapBlob,
  687. pbEapBlob,
  688. sizeof (EAPOL_INTF_PARAMS),
  689. &dwAuthData,
  690. &pbAuthData
  691. )) != NO_ERROR)
  692. {
  693. TRACE1 (ANY, "ElGetCustomAuthData: ElGetEapData failed with error %ld",
  694. dwRetCode);
  695. break;
  696. }
  697. pbAuthDataIn = pbAuthData;
  698. dwAuthDataIn = dwAuthData;
  699. // Get the policy data, if any
  700. // If there is policy data use it instead of the registry setting
  701. if ((dwRetCode = ElGetPolicyCustomAuthData (
  702. dwEapTypeId,
  703. dwSizeOfSSID,
  704. pbSSID,
  705. &pbAuthDataIn,
  706. &dwAuthDataIn,
  707. &pbAuthData,
  708. &dwAuthData
  709. )) == NO_ERROR)
  710. {
  711. TRACE0 (ANY, "ElGetCustomAuthData: POLICY: Initialized with Policy data");
  712. fFreeAuthData = TRUE;
  713. }
  714. else
  715. {
  716. if (dwRetCode != ERROR_FILE_NOT_FOUND)
  717. {
  718. TRACE1 (ANY, "ElGetCustomAuthData: ElGetPolicyCustomAuthData returned error %ld",
  719. dwRetCode);
  720. }
  721. dwRetCode = NO_ERROR;
  722. }
  723. // Return the data if sufficient space allocated
  724. if ((pbConnInfo != NULL) && (*pdwInfoSize >= dwAuthData))
  725. {
  726. memcpy (pbConnInfo, pbAuthData, dwAuthData);
  727. }
  728. else
  729. {
  730. dwRetCode = ERROR_BUFFER_TOO_SMALL;
  731. }
  732. *pdwInfoSize = dwAuthData;
  733. } while (FALSE);
  734. if (hkey != NULL)
  735. {
  736. RegCloseKey (hkey);
  737. }
  738. if (hkey1 != NULL)
  739. {
  740. RegCloseKey (hkey1);
  741. }
  742. if (pbValueBuf != NULL)
  743. {
  744. FREE (pbValueBuf);
  745. }
  746. if (pbDefaultValue != NULL)
  747. {
  748. FREE (pbDefaultValue);
  749. }
  750. if (pwszValueName != NULL)
  751. {
  752. FREE (pwszValueName);
  753. }
  754. if (fFreeAuthData)
  755. {
  756. if (pbAuthData != NULL)
  757. {
  758. FREE (pbAuthData);
  759. }
  760. }
  761. return dwRetCode;
  762. }
  763. //
  764. // ElReAuthenticateInterface
  765. //
  766. // Description:
  767. //
  768. // Function called to reinitiate authentication on an interface
  769. //
  770. // Arguments:
  771. //
  772. // pwszGUID - pointer to GUID string for the interface
  773. //
  774. // Return values:
  775. //
  776. // NO_ERROR - success
  777. // non-zero - error
  778. //
  779. DWORD
  780. ElReAuthenticateInterface (
  781. IN WCHAR *pwszGUID
  782. )
  783. {
  784. BYTE *pbData = NULL;
  785. DWORD dwEventStatus = 0;
  786. BOOLEAN fDecrWorkerThreadCount = FALSE;
  787. DWORD dwRetCode = NO_ERROR;
  788. do
  789. {
  790. if (g_hEventTerminateEAPOL == NULL)
  791. {
  792. dwRetCode = NO_ERROR;
  793. break;
  794. }
  795. if (( dwEventStatus = WaitForSingleObject (
  796. g_hEventTerminateEAPOL,
  797. 0)) == WAIT_FAILED)
  798. {
  799. dwRetCode = GetLastError ();
  800. break;
  801. }
  802. if (dwEventStatus == WAIT_OBJECT_0)
  803. {
  804. dwRetCode = NO_ERROR;
  805. break;
  806. }
  807. fDecrWorkerThreadCount = TRUE;
  808. InterlockedIncrement (&g_lWorkerThreads);
  809. pbData = (BYTE *) MALLOC ((wcslen(pwszGUID)+1)*sizeof(WCHAR));
  810. if (pbData == NULL)
  811. {
  812. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  813. break;
  814. }
  815. wcscpy ((WCHAR *)pbData, pwszGUID);
  816. if (!QueueUserWorkItem (
  817. (LPTHREAD_START_ROUTINE)ElReAuthenticateInterfaceWorker,
  818. (PVOID)pbData,
  819. WT_EXECUTELONGFUNCTION))
  820. {
  821. dwRetCode = GetLastError();
  822. TRACE1 (DEVICE, "ElPostEapConfigChanged: QueueUserWorkItem failed with error %ld",
  823. dwRetCode);
  824. break;
  825. }
  826. else
  827. {
  828. fDecrWorkerThreadCount = FALSE;
  829. }
  830. }
  831. while (FALSE);
  832. if (dwRetCode != NO_ERROR)
  833. {
  834. if (pbData != NULL)
  835. {
  836. FREE (pbData);
  837. }
  838. }
  839. if (fDecrWorkerThreadCount)
  840. {
  841. InterlockedDecrement (&g_lWorkerThreads);
  842. }
  843. return dwRetCode;
  844. }
  845. //
  846. // ElReAuthenticateInterfaceWorker
  847. //
  848. // Description:
  849. //
  850. // Worker function called to reinitiate authentication on an interface
  851. //
  852. // Arguments:
  853. //
  854. // pwszGUID - pointer to GUID string for the interface
  855. //
  856. // Return values:
  857. //
  858. // NO_ERROR - success
  859. // non-zero - error
  860. //
  861. DWORD
  862. WINAPI
  863. ElReAuthenticateInterfaceWorker (
  864. IN PVOID pvContext
  865. )
  866. {
  867. PWCHAR pwszGUID = NULL;
  868. DWORD dwRetCode = NO_ERROR;
  869. do
  870. {
  871. pwszGUID = (PWCHAR)pvContext;
  872. // Do not shutdown interface, merely restart authentication
  873. #if 0
  874. if ((dwRetCode = ElShutdownInterface (pwszGUID)) != NO_ERROR)
  875. {
  876. TRACE1 (ANY, "ElReAuthenticateInterface: ElShutdownInterface failed with error %ld",
  877. dwRetCode);
  878. break;
  879. }
  880. #endif
  881. if ((dwRetCode = ElEnumAndOpenInterfaces (
  882. NULL, pwszGUID, 0, NULL))
  883. != NO_ERROR)
  884. {
  885. TRACE1 (ANY, "ElReAuthenticateInterface: ElEnumAndOpenInterfaces returned error %ld",
  886. dwRetCode);
  887. }
  888. }
  889. while (FALSE);
  890. if (pvContext != NULL)
  891. {
  892. FREE (pvContext);
  893. }
  894. InterlockedDecrement (&g_lWorkerThreads);
  895. return dwRetCode;
  896. }
  897. //
  898. // ElQueryInterfaceState
  899. //
  900. // Description:
  901. //
  902. // Function called to query the EAPOL state for an interface
  903. //
  904. // Arguments:
  905. //
  906. // pwszGUID - pointer to GUID string for the interface
  907. // pIntfState - pointer to interface state structure
  908. //
  909. // Return values:
  910. //
  911. // NO_ERROR - success
  912. // non-zero - error
  913. //
  914. DWORD
  915. ElQueryInterfaceState (
  916. IN WCHAR *pwszGUID,
  917. IN OUT EAPOL_INTF_STATE *pIntfState
  918. )
  919. {
  920. EAPOL_PCB *pPCB = NULL;
  921. BOOLEAN fPortReferenced = FALSE;
  922. BOOLEAN fPCBLocked = FALSE;
  923. DWORD dwRetCode = NO_ERROR;
  924. do
  925. {
  926. ACQUIRE_WRITE_LOCK (&g_PCBLock);
  927. if ((pPCB = ElGetPCBPointerFromPortGUID (pwszGUID)) != NULL)
  928. {
  929. if (EAPOL_REFERENCE_PORT (pPCB))
  930. {
  931. fPortReferenced = TRUE;
  932. }
  933. else
  934. {
  935. pPCB = NULL;
  936. }
  937. }
  938. RELEASE_WRITE_LOCK (&g_PCBLock);
  939. if (pPCB == NULL)
  940. {
  941. break;
  942. }
  943. ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
  944. fPCBLocked = TRUE;
  945. if (pPCB->pSSID)
  946. {
  947. pIntfState->dwSizeOfSSID = pPCB->pSSID->SsidLength;
  948. memcpy (pIntfState->bSSID, pPCB->pSSID->Ssid,
  949. NDIS_802_11_SSID_LEN-sizeof(ULONG));
  950. }
  951. else
  952. {
  953. pIntfState->dwSizeOfSSID = 0;
  954. }
  955. if (pPCB->pszIdentity)
  956. {
  957. if ((pIntfState->pszEapIdentity = RpcCAlloc((strlen(pPCB->pszIdentity)+1)*sizeof(CHAR))) == NULL)
  958. {
  959. dwRetCode = GetLastError ();
  960. break;
  961. }
  962. strcpy (pIntfState->pszEapIdentity, (LPSTR)pPCB->pszIdentity);
  963. }
  964. if ((pIntfState->pwszLocalMACAddr = RpcCAlloc(3*SIZE_MAC_ADDR*sizeof(WCHAR))) == NULL)
  965. {
  966. dwRetCode = GetLastError ();
  967. break;
  968. }
  969. ZeroMemory ((PVOID)pIntfState->pwszLocalMACAddr, 3*SIZE_MAC_ADDR*sizeof(WCHAR));
  970. MACADDR_BYTE_TO_WSTR(pPCB->bSrcMacAddr, pIntfState->pwszLocalMACAddr);
  971. if ((pIntfState->pwszRemoteMACAddr = RpcCAlloc(3*SIZE_MAC_ADDR*sizeof(WCHAR))) == NULL)
  972. {
  973. dwRetCode = GetLastError ();
  974. break;
  975. }
  976. ZeroMemory ((PVOID)pIntfState->pwszRemoteMACAddr, 3*SIZE_MAC_ADDR*sizeof(WCHAR));
  977. MACADDR_BYTE_TO_WSTR(pPCB->bDestMacAddr, pIntfState->pwszRemoteMACAddr);
  978. pIntfState->dwState = pPCB->State;
  979. pIntfState->dwEapUIState = pPCB->EapUIState;
  980. pIntfState->dwEAPOLAuthMode = pPCB->dwEAPOLAuthMode;
  981. pIntfState->dwEAPOLAuthenticationType = pPCB->PreviousAuthenticationType;
  982. pIntfState->dwEapType = pPCB->dwEapTypeToBeUsed;
  983. pIntfState->dwFailCount = pPCB->dwAuthFailCount;
  984. pIntfState->dwPhysicalMediumType = pPCB->PhysicalMediumType;
  985. }
  986. while (FALSE);
  987. if (fPCBLocked)
  988. {
  989. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  990. }
  991. if (fPortReferenced)
  992. {
  993. EAPOL_DEREFERENCE_PORT (pPCB);
  994. }
  995. if (dwRetCode != NO_ERROR)
  996. {
  997. RpcFree (pIntfState->pwszLocalMACAddr);
  998. RpcFree (pIntfState->pwszRemoteMACAddr);
  999. RpcFree (pIntfState->pszEapIdentity);
  1000. pIntfState->pwszLocalMACAddr = NULL;
  1001. pIntfState->pwszRemoteMACAddr = NULL;
  1002. pIntfState->pszEapIdentity = NULL;
  1003. }
  1004. return dwRetCode;
  1005. }
  1006. //
  1007. // ElSetEapUserInfo
  1008. //
  1009. // Description:
  1010. //
  1011. // Function called to store the user data for an interface for a
  1012. // specific EAP type and SSID (if any). Data is stored in the HKCU hive.
  1013. // In case of EAP-TLS, this data will be the hash blob of the certificate
  1014. // chosen for the last successful authentication.
  1015. //
  1016. // Arguments:
  1017. //
  1018. // hToken - Handle to token for the logged on user
  1019. // pwszGUID - pointer to GUID string for the interface
  1020. // dwEapTypeId - EAP type for which user data is to be stored
  1021. // dwSizeOfSSID - Size of Special identifier if any for the EAP user blob
  1022. // pbSSID - Special identifier if any for the EAP user blob
  1023. // pbUserInfo - pointer to EAP user data blob
  1024. // dwInfoSize - Size of EAP user blob
  1025. //
  1026. //
  1027. // Return values:
  1028. // NO_ERROR - success
  1029. // non-zero - error
  1030. //
  1031. DWORD
  1032. ElSetEapUserInfo (
  1033. IN HANDLE hToken,
  1034. IN WCHAR *pwszGUID,
  1035. IN DWORD dwEapTypeId,
  1036. IN DWORD dwSizeOfSSID,
  1037. IN BYTE *pbSSID,
  1038. IN PBYTE pbUserInfo,
  1039. IN DWORD dwInfoSize
  1040. )
  1041. {
  1042. HKEY hkey = NULL;
  1043. HKEY hkey1 = NULL;
  1044. HKEY hkey2 = NULL;
  1045. DWORD dwDisposition;
  1046. DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwMaxValueLen = 0;
  1047. DWORD dwIndex = 0, dwMaxValueName = 0;
  1048. BYTE *pbValueBuf = NULL;
  1049. DWORD dwValueData = 0;
  1050. WCHAR wcszValueName[MAX_VALUENAME_LEN];
  1051. WCHAR *pwszValueName = NULL;
  1052. BYTE *pbDefaultValue = NULL;
  1053. DWORD dwDefaultValueLen = 0;
  1054. BYTE *pbEapBlob = NULL, *pbEapBlobIn = NULL;
  1055. DWORD dwEapBlob = 0;
  1056. BOOLEAN fFoundValue = FALSE;
  1057. EAPOL_INTF_PARAMS *pRegParams = NULL;
  1058. EAPOL_INTF_PARAMS *pDefIntfParams = NULL;
  1059. LONG lError = ERROR_SUCCESS;
  1060. DWORD dwRetCode = ERROR_SUCCESS;
  1061. do
  1062. {
  1063. // Validate input params
  1064. if (hToken == NULL)
  1065. {
  1066. TRACE0 (ANY, "ElSetEapUserInfo: User Token = NULL");
  1067. break;
  1068. }
  1069. if (pwszGUID == NULL)
  1070. {
  1071. TRACE0 (ANY, "ElSetEapUserInfo: GUID = NULL");
  1072. break;
  1073. }
  1074. if (dwEapTypeId == 0)
  1075. {
  1076. TRACE0 (ANY, "ElSetEapUserInfo: GUID = NULL");
  1077. break;
  1078. }
  1079. if ((pbUserInfo == NULL) || (dwInfoSize <= 0))
  1080. {
  1081. TRACE0 (ANY, "ElSetEapUserInfo: Invalid blob data");
  1082. break;
  1083. }
  1084. // Get handle to HKCU
  1085. if ((dwRetCode = ElGetEapKeyFromToken (
  1086. hToken,
  1087. &hkey)) != NO_ERROR)
  1088. {
  1089. TRACE1 (ANY, "ElSetEapUserInfo: Error in ElGetEapKeyFromToken %ld",
  1090. dwRetCode);
  1091. break;
  1092. }
  1093. if ((lError = RegCreateKeyEx (
  1094. hkey,
  1095. cwszEapKeyEapolUser,
  1096. 0,
  1097. NULL,
  1098. REG_OPTION_NON_VOLATILE,
  1099. KEY_WRITE | KEY_READ,
  1100. NULL,
  1101. &hkey1,
  1102. &dwDisposition)) != ERROR_SUCCESS)
  1103. {
  1104. TRACE1 (ANY, "ElSetEapUserInfo: Error in RegCreateKeyEx for base key, %ld",
  1105. lError);
  1106. dwRetCode = (DWORD)lError;
  1107. break;
  1108. }
  1109. // Get handle to HKCU\Software\...\UserEapInfo\<GUID>
  1110. if ((lError = RegCreateKeyEx (
  1111. hkey1,
  1112. pwszGUID,
  1113. 0,
  1114. NULL,
  1115. REG_OPTION_NON_VOLATILE,
  1116. KEY_WRITE | KEY_READ,
  1117. NULL,
  1118. &hkey2,
  1119. &dwDisposition)) != ERROR_SUCCESS)
  1120. {
  1121. TRACE1 (ANY, "ElSetEapUserInfo: Error in RegCreateKeyEx for GUID, %ld",
  1122. lError);
  1123. dwRetCode = (DWORD)lError;
  1124. break;
  1125. }
  1126. if ((lError = RegQueryInfoKey (
  1127. hkey2,
  1128. NULL,
  1129. NULL,
  1130. NULL,
  1131. NULL,
  1132. NULL,
  1133. NULL,
  1134. &dwNumValues,
  1135. &dwMaxValueNameLen,
  1136. &dwMaxValueLen,
  1137. NULL,
  1138. NULL
  1139. )) != NO_ERROR)
  1140. {
  1141. dwRetCode = (DWORD)lError;
  1142. TRACE1 (ANY, "ElSetEapUserInfo: RegQueryInfoKey failed with error %ld",
  1143. dwRetCode);
  1144. break;
  1145. }
  1146. if (dwMaxValueNameLen > MAX_VALUENAME_LEN)
  1147. {
  1148. TRACE1 (ANY, "ElSetEapUserInfo: dwMaxValueNameLen too long (%ld)",
  1149. dwMaxValueNameLen);
  1150. }
  1151. dwMaxValueNameLen = MAX_VALUENAME_LEN;
  1152. if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL)
  1153. {
  1154. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1155. TRACE0 (ANY, "ElSetEapUserInfo: MALLOC failed for pbValueBuf");
  1156. break;
  1157. }
  1158. // Set correct SSID
  1159. if ((dwSizeOfSSID == 0) || (dwSizeOfSSID > MAX_SSID_LEN) ||
  1160. (pbSSID == NULL))
  1161. {
  1162. pbSSID = g_bDefaultSSID;
  1163. dwSizeOfSSID = MAX_SSID_LEN;
  1164. }
  1165. for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++)
  1166. {
  1167. dwValueData = dwMaxValueLen;
  1168. dwMaxValueNameLen = MAX_VALUENAME_LEN;
  1169. ZeroMemory (wcszValueName, MAX_VALUENAME_LEN*sizeof(WCHAR));
  1170. if ((lError = RegEnumValue (
  1171. hkey2,
  1172. dwIndex,
  1173. wcszValueName,
  1174. &dwMaxValueNameLen,
  1175. NULL,
  1176. NULL,
  1177. pbValueBuf,
  1178. &dwValueData
  1179. )) != ERROR_SUCCESS)
  1180. {
  1181. if (lError != ERROR_MORE_DATA)
  1182. {
  1183. break;
  1184. }
  1185. lError = ERROR_SUCCESS;
  1186. }
  1187. if (dwValueData < sizeof (EAPOL_INTF_PARAMS))
  1188. {
  1189. lError = ERROR_INVALID_DATA;
  1190. TRACE2 (ANY, "ElSetEapUserInfo: dwValueData (%ld) < sizeof (EAPOL_INTF_PARAMS) (%ld)",
  1191. dwValueData, sizeof (EAPOL_INTF_PARAMS));
  1192. break;
  1193. }
  1194. pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
  1195. if (((DWORD)_wtol(wcszValueName)) > dwMaxValueName)
  1196. {
  1197. dwMaxValueName = _wtol (wcszValueName);
  1198. }
  1199. if (!memcmp (pRegParams->bSSID, pbSSID, dwSizeOfSSID))
  1200. {
  1201. fFoundValue = TRUE;
  1202. break;
  1203. }
  1204. }
  1205. if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS))
  1206. {
  1207. dwRetCode = (DWORD)lError;
  1208. TRACE1 (ANY, "ElSetEapUserInfo: RegEnumValue 2 failed with error %ld",
  1209. dwRetCode);
  1210. break;
  1211. }
  1212. else
  1213. {
  1214. lError = ERROR_SUCCESS;
  1215. }
  1216. if (!fFoundValue)
  1217. {
  1218. DWORD dwNewValueName = (dwMaxValueName >= dwNumValues)?(++dwMaxValueName):dwNumValues;
  1219. _ltow (dwNewValueName, wcszValueName, 10);
  1220. if ((pbDefaultValue = MALLOC (sizeof(EAPOL_INTF_PARAMS))) == NULL)
  1221. {
  1222. TRACE0 (ANY, "ElSetEapUserInfo: MALLOC failed for pbDefaultValue");
  1223. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1224. break;
  1225. }
  1226. // Mark that SSID for this entry
  1227. // Rest of the parameters are dummy for UserEapInfo
  1228. pDefIntfParams = (EAPOL_INTF_PARAMS *)pbDefaultValue;
  1229. pDefIntfParams->dwSizeOfSSID = dwSizeOfSSID;
  1230. memcpy (pDefIntfParams->bSSID, pbSSID, dwSizeOfSSID);
  1231. dwEapBlob = sizeof(EAPOL_INTF_PARAMS);
  1232. pbEapBlob = pbDefaultValue;
  1233. }
  1234. else
  1235. {
  1236. // Use pbValueBuf & dwValueData
  1237. pbEapBlob = pbValueBuf;
  1238. dwEapBlob = dwValueData;
  1239. }
  1240. pbEapBlobIn = pbEapBlob;
  1241. if ((dwRetCode = ElSetEapData (
  1242. dwEapTypeId,
  1243. &dwEapBlob,
  1244. &pbEapBlob,
  1245. sizeof (EAPOL_INTF_PARAMS),
  1246. dwInfoSize,
  1247. pbUserInfo
  1248. )) != NO_ERROR)
  1249. {
  1250. TRACE1 (ANY, "ElSetEapUserInfo: ElSetEapData failed with error %ld",
  1251. dwRetCode);
  1252. break;
  1253. }
  1254. // Overwrite/Create new value
  1255. if ((lError = RegSetValueEx (
  1256. hkey2,
  1257. wcszValueName,
  1258. 0,
  1259. REG_BINARY,
  1260. pbEapBlob,
  1261. dwEapBlob)) != ERROR_SUCCESS)
  1262. {
  1263. TRACE1 (ANY, "ElSetEapUserInfo: Error in RegSetValueEx for SSID, %ld",
  1264. lError);
  1265. dwRetCode = (DWORD)lError;
  1266. break;
  1267. }
  1268. TRACE0 (ANY, "ElSetEapUserInfo: Set value succeeded");
  1269. } while (FALSE);
  1270. if (hkey != NULL)
  1271. {
  1272. RegCloseKey (hkey);
  1273. }
  1274. if (hkey1 != NULL)
  1275. {
  1276. RegCloseKey (hkey1);
  1277. }
  1278. if (hkey2 != NULL)
  1279. {
  1280. RegCloseKey (hkey2);
  1281. }
  1282. if ((pbEapBlob != pbEapBlobIn) && (pbEapBlob != NULL))
  1283. {
  1284. FREE (pbEapBlob);
  1285. }
  1286. if (pbValueBuf != NULL)
  1287. {
  1288. FREE (pbValueBuf);
  1289. }
  1290. if (pbDefaultValue != NULL)
  1291. {
  1292. FREE (pbDefaultValue);
  1293. }
  1294. return dwRetCode;
  1295. }
  1296. //
  1297. // ElGetEapUserInfo
  1298. //
  1299. // Description:
  1300. //
  1301. // Function called to retrieve the user data for an interface for a
  1302. // specific EAP type and SSID (if any). Data is retrieved from the HKCU hive
  1303. //
  1304. // Arguments:
  1305. // hToken - Handle to token for the logged on user
  1306. // pwszGUID - pointer to GUID string for the interface
  1307. // dwEapTypeId - EAP type for which user data is to be stored
  1308. // dwSizeOfSSID - Size of Special identifier if any for the EAP user blob
  1309. // pbSSID - Special identifier if any for the EAP user blob
  1310. // pbUserInfo - output: pointer to EAP user data blob
  1311. // dwInfoSize - output: pointer to size of EAP user blob
  1312. //
  1313. // Return values:
  1314. // NO_ERROR - success
  1315. // non-zero - error
  1316. //
  1317. DWORD
  1318. ElGetEapUserInfo (
  1319. IN HANDLE hToken,
  1320. IN WCHAR *pwszGUID,
  1321. IN DWORD dwEapTypeId,
  1322. IN DWORD dwSizeOfSSID,
  1323. IN BYTE *pbSSID,
  1324. IN OUT PBYTE pbUserInfo,
  1325. IN OUT DWORD *pdwInfoSize
  1326. )
  1327. {
  1328. HKEY hkey = NULL;
  1329. HKEY hkey1 = NULL;
  1330. HKEY hkey2 = NULL;
  1331. DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwTempValueNameLen = 0, dwMaxValueLen = 0;
  1332. DWORD dwIndex = 0, dwMaxValueName = 0;
  1333. WCHAR *pwszValueName = NULL;
  1334. BYTE *pbValueBuf = NULL;
  1335. DWORD dwValueData = 0;
  1336. BYTE *pbDefaultValue = NULL;
  1337. DWORD dwDefaultValueLen = 0;
  1338. BYTE *pbEapBlob = NULL;
  1339. DWORD dwEapBlob = 0;
  1340. BYTE *pbAuthData = NULL;
  1341. DWORD dwAuthData = 0;
  1342. BOOLEAN fFoundValue = FALSE;
  1343. EAPOL_INTF_PARAMS *pRegParams = NULL;
  1344. LONG lError = ERROR_SUCCESS;
  1345. DWORD dwRetCode = ERROR_SUCCESS;
  1346. do
  1347. {
  1348. // Validate input params
  1349. if (hToken == NULL)
  1350. {
  1351. TRACE0 (ANY, "ElGetEapUserInfo: User Token = NULL");
  1352. break;
  1353. }
  1354. if (pwszGUID == NULL)
  1355. {
  1356. TRACE0 (ANY, "ElGetEapUserInfo: GUID = NULL");
  1357. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  1358. break;
  1359. }
  1360. if (dwEapTypeId == 0)
  1361. {
  1362. TRACE0 (ANY, "ElGetEapUserInfo: GUID = NULL");
  1363. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  1364. break;
  1365. }
  1366. // Get handle to HKCU
  1367. if ((dwRetCode = ElGetEapKeyFromToken (
  1368. hToken,
  1369. &hkey)) != NO_ERROR)
  1370. {
  1371. TRACE1 (ANY, "ElGetEapUserInfo: Error in ElGetEapKeyFromToken %ld",
  1372. dwRetCode);
  1373. break;
  1374. }
  1375. // Get handle to HKCU\Software\...\UserEapInfo\<GUID>
  1376. if ((lError = RegOpenKeyEx (
  1377. hkey,
  1378. cwszEapKeyEapolUser,
  1379. 0,
  1380. KEY_READ,
  1381. &hkey1
  1382. )) != ERROR_SUCCESS)
  1383. {
  1384. TRACE1 (ANY, "ElGetEapUserInfo: Error in RegOpenKeyEx for base key, %ld",
  1385. lError);
  1386. dwRetCode = (DWORD)lError;
  1387. break;
  1388. }
  1389. // Get handle to HKCU\Software\...\UserEapInfo\<GUID>
  1390. if ((lError = RegOpenKeyEx (
  1391. hkey1,
  1392. pwszGUID,
  1393. 0,
  1394. KEY_READ,
  1395. &hkey2
  1396. )) != ERROR_SUCCESS)
  1397. {
  1398. TRACE1 (ANY, "ElGetEapUserInfo: Error in RegOpenKeyEx for GUID, %ld",
  1399. lError);
  1400. dwRetCode = (DWORD)lError;
  1401. break;
  1402. }
  1403. // Set correct SSID
  1404. if ((dwSizeOfSSID == 0) || (dwSizeOfSSID > MAX_SSID_LEN) ||
  1405. (pbSSID == NULL))
  1406. {
  1407. pbSSID = g_bDefaultSSID;
  1408. dwSizeOfSSID = MAX_SSID_LEN;
  1409. }
  1410. if ((lError = RegQueryInfoKey (
  1411. hkey2,
  1412. NULL,
  1413. NULL,
  1414. NULL,
  1415. NULL,
  1416. NULL,
  1417. NULL,
  1418. &dwNumValues,
  1419. &dwMaxValueNameLen,
  1420. &dwMaxValueLen,
  1421. NULL,
  1422. NULL
  1423. )) != NO_ERROR)
  1424. {
  1425. dwRetCode = (DWORD)lError;
  1426. TRACE1 (ANY, "ElGetEapUserInfo: RegQueryInfoKey failed with error %ld",
  1427. dwRetCode);
  1428. break;
  1429. }
  1430. if ((pwszValueName = MALLOC ((dwMaxValueNameLen + 1) * sizeof (WCHAR))) == NULL)
  1431. {
  1432. TRACE0 (ANY, "ElGetEapUserInfo: MALLOC failed for pwszValueName");
  1433. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1434. break;
  1435. }
  1436. dwMaxValueNameLen++;
  1437. if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL)
  1438. {
  1439. TRACE0 (ANY, "ElGetEapUserInfo: MALLOC failed for pbValueBuf");
  1440. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1441. break;
  1442. }
  1443. for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++)
  1444. {
  1445. dwValueData = dwMaxValueLen;
  1446. dwTempValueNameLen = dwMaxValueNameLen;
  1447. if ((lError = RegEnumValue (
  1448. hkey2,
  1449. dwIndex,
  1450. pwszValueName,
  1451. &dwTempValueNameLen,
  1452. NULL,
  1453. NULL,
  1454. pbValueBuf,
  1455. &dwValueData
  1456. )) != ERROR_SUCCESS)
  1457. {
  1458. if (lError != ERROR_MORE_DATA)
  1459. {
  1460. break;
  1461. }
  1462. lError = ERROR_SUCCESS;
  1463. }
  1464. if (dwValueData < sizeof (EAPOL_INTF_PARAMS))
  1465. {
  1466. TRACE0 (ANY, "ElGetEapUserInfo: dwValueData < sizeof (EAPOL_INTF_PARAMS)");
  1467. lError = ERROR_INVALID_DATA;
  1468. break;
  1469. }
  1470. pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
  1471. if (((DWORD)_wtol(pwszValueName)) > dwMaxValueName)
  1472. {
  1473. dwMaxValueName = _wtol (pwszValueName);
  1474. }
  1475. if (!memcmp (pRegParams->bSSID, pbSSID, dwSizeOfSSID))
  1476. {
  1477. fFoundValue = TRUE;
  1478. break;
  1479. }
  1480. }
  1481. if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS))
  1482. {
  1483. dwRetCode = (DWORD)lError;
  1484. TRACE1 (ANY, "ElGetEapUserInfo: RegEnumValue 2 failed with error %ld",
  1485. dwRetCode);
  1486. break;
  1487. }
  1488. else
  1489. {
  1490. lError = ERROR_SUCCESS;
  1491. }
  1492. if (!fFoundValue)
  1493. {
  1494. pbEapBlob = NULL;
  1495. dwEapBlob = 0;
  1496. }
  1497. else
  1498. {
  1499. // Use pbValueBuf & dwValueData
  1500. pbEapBlob = pbValueBuf;
  1501. dwEapBlob = dwValueData;
  1502. }
  1503. // If blob is not present, exit
  1504. if ((pbEapBlob == NULL) && (dwEapBlob == 0))
  1505. {
  1506. TRACE0 (ANY, "ElGetEapUserInfo: (pbEapBlob == NULL) && (dwEapBlob == 0)");
  1507. *pdwInfoSize = 0;
  1508. break;
  1509. }
  1510. if ((dwRetCode = ElGetEapData (
  1511. dwEapTypeId,
  1512. dwEapBlob,
  1513. pbEapBlob,
  1514. sizeof (EAPOL_INTF_PARAMS),
  1515. &dwAuthData,
  1516. &pbAuthData
  1517. )) != NO_ERROR)
  1518. {
  1519. TRACE1 (ANY, "ElGetEapUserInfo: ElGetEapData failed with error %ld",
  1520. dwRetCode);
  1521. break;
  1522. }
  1523. // Return the data if sufficient space allocated
  1524. if ((pbUserInfo != NULL) && (*pdwInfoSize >= dwAuthData))
  1525. {
  1526. memcpy (pbUserInfo, pbAuthData, dwAuthData);
  1527. }
  1528. else
  1529. {
  1530. dwRetCode = ERROR_BUFFER_TOO_SMALL;
  1531. }
  1532. *pdwInfoSize = dwAuthData;
  1533. TRACE0 (ANY, "ElGetEapUserInfo: Get value succeeded");
  1534. } while (FALSE);
  1535. if (hkey != NULL)
  1536. {
  1537. RegCloseKey (hkey);
  1538. }
  1539. if (hkey1 != NULL)
  1540. {
  1541. RegCloseKey (hkey1);
  1542. }
  1543. if (hkey2 != NULL)
  1544. {
  1545. RegCloseKey (hkey2);
  1546. }
  1547. if (pbValueBuf != NULL)
  1548. {
  1549. FREE (pbValueBuf);
  1550. }
  1551. if (pbDefaultValue != NULL)
  1552. {
  1553. FREE (pbDefaultValue);
  1554. }
  1555. if (pwszValueName != NULL)
  1556. {
  1557. FREE (pwszValueName);
  1558. }
  1559. return dwRetCode;
  1560. }
  1561. //
  1562. // ElDeleteEapUserInfo
  1563. //
  1564. // Description:
  1565. //
  1566. // Function called to delete the user data for an interface for a
  1567. // specific EAP type and SSID (if any). Data is stored in the HKCU hive.
  1568. // In case of EAP-TLS, this data will be the hash blob of the certificate
  1569. // chosen for the last successful authentication.
  1570. //
  1571. // Arguments:
  1572. //
  1573. // hToken - Handle to token for the logged on user
  1574. // pwszGUID - pointer to GUID string for the interface
  1575. // dwEapTypeId - EAP type for which user data is to be stored
  1576. // dwSizeOfSSID - Size of Special identifier if any for the EAP user blob
  1577. // pbSSID - Special identifier if any for the EAP user blob
  1578. //
  1579. // Return values:
  1580. // NO_ERROR - success
  1581. // non-zero - error
  1582. //
  1583. DWORD
  1584. ElDeleteEapUserInfo (
  1585. IN HANDLE hToken,
  1586. IN WCHAR *pwszGUID,
  1587. IN DWORD dwEapTypeId,
  1588. IN DWORD dwSizeOfSSID,
  1589. IN BYTE *pbSSID
  1590. )
  1591. {
  1592. HKEY hkey = NULL;
  1593. HKEY hkey1 = NULL;
  1594. HKEY hkey2 = NULL;
  1595. DWORD dwDisposition;
  1596. DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwTempValueNameLen = 0, dwMaxValueLen = 0;
  1597. DWORD dwIndex = 0, dwMaxValueName = 0;
  1598. BYTE *pbValueBuf = NULL;
  1599. DWORD dwValueData = 0;
  1600. WCHAR *pwszValueName = NULL;
  1601. DWORD dwDefaultValueLen = 0;
  1602. BYTE *pbEapBlob = NULL, *pbEapBlobIn = NULL;
  1603. DWORD dwEapBlob = 0;
  1604. BOOLEAN fFoundValue = FALSE;
  1605. EAPOL_INTF_PARAMS *pRegParams = NULL;
  1606. EAPOL_INTF_PARAMS *pDefIntfParams = NULL;
  1607. LONG lError = ERROR_SUCCESS;
  1608. DWORD dwRetCode = ERROR_SUCCESS;
  1609. do
  1610. {
  1611. // Validate input params
  1612. if (hToken == NULL)
  1613. {
  1614. TRACE0 (ANY, "ElDeleteEapUserInfo: User Token = NULL");
  1615. break;
  1616. }
  1617. if (pwszGUID == NULL)
  1618. {
  1619. TRACE0 (ANY, "ElDeleteEapUserInfo: GUID = NULL");
  1620. break;
  1621. }
  1622. if (dwEapTypeId == 0)
  1623. {
  1624. TRACE0 (ANY, "ElDeleteEapUserInfo: GUID = NULL");
  1625. break;
  1626. }
  1627. // Get handle to HKCU
  1628. if ((dwRetCode = ElGetEapKeyFromToken (
  1629. hToken,
  1630. &hkey)) != NO_ERROR)
  1631. {
  1632. TRACE1 (ANY, "ElDeleteEapUserInfo: Error in ElGetEapKeyFromToken %ld",
  1633. dwRetCode);
  1634. break;
  1635. }
  1636. if ((lError = RegOpenKeyEx (
  1637. hkey,
  1638. cwszEapKeyEapolUser,
  1639. 0,
  1640. KEY_ALL_ACCESS,
  1641. &hkey1)) != ERROR_SUCCESS)
  1642. {
  1643. TRACE1 (ANY, "ElDeleteEapUserInfo: Error in RegOpenKeyEx for base key, %ld",
  1644. lError);
  1645. dwRetCode = (DWORD)lError;
  1646. break;
  1647. }
  1648. // Get handle to HKCU\Software\...\UserEapInfo\<GUID>
  1649. if ((lError = RegOpenKeyEx (
  1650. hkey1,
  1651. pwszGUID,
  1652. 0,
  1653. KEY_ALL_ACCESS,
  1654. &hkey2)) != ERROR_SUCCESS)
  1655. {
  1656. TRACE1 (ANY, "ElDeleteEapUserInfo: Error in RegOpenKeyEx for GUID, %ld",
  1657. lError);
  1658. dwRetCode = (DWORD)lError;
  1659. break;
  1660. }
  1661. if ((lError = RegQueryInfoKey (
  1662. hkey2,
  1663. NULL,
  1664. NULL,
  1665. NULL,
  1666. NULL,
  1667. NULL,
  1668. NULL,
  1669. &dwNumValues,
  1670. &dwMaxValueNameLen,
  1671. &dwMaxValueLen,
  1672. NULL,
  1673. NULL
  1674. )) != NO_ERROR)
  1675. {
  1676. dwRetCode = (DWORD)lError;
  1677. TRACE1 (ANY, "ElDeleteEapUserInfo: RegQueryInfoKey failed with error %ld",
  1678. dwRetCode);
  1679. break;
  1680. }
  1681. if ((pwszValueName = MALLOC ((dwMaxValueNameLen + 1) * sizeof (WCHAR))) == NULL)
  1682. {
  1683. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1684. TRACE0 (ANY, "ElDeleteEapUserInfo: MALLOC failed for pwszValueName");
  1685. break;
  1686. }
  1687. dwMaxValueNameLen++;
  1688. if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL)
  1689. {
  1690. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1691. TRACE0 (ANY, "ElDeleteEapUserInfo: MALLOC failed for pbValueBuf");
  1692. break;
  1693. }
  1694. // Set correct SSID
  1695. if ((dwSizeOfSSID == 0) || (dwSizeOfSSID > MAX_SSID_LEN) ||
  1696. (pbSSID == NULL))
  1697. {
  1698. pbSSID = g_bDefaultSSID;
  1699. dwSizeOfSSID = MAX_SSID_LEN;
  1700. }
  1701. for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++)
  1702. {
  1703. dwValueData = dwMaxValueLen;
  1704. dwTempValueNameLen = dwMaxValueNameLen;
  1705. if ((lError = RegEnumValue (
  1706. hkey2,
  1707. dwIndex,
  1708. pwszValueName,
  1709. &dwTempValueNameLen,
  1710. NULL,
  1711. NULL,
  1712. pbValueBuf,
  1713. &dwValueData
  1714. )) != ERROR_SUCCESS)
  1715. {
  1716. if (lError != ERROR_MORE_DATA)
  1717. {
  1718. break;
  1719. }
  1720. lError = ERROR_SUCCESS;
  1721. }
  1722. if (dwValueData < sizeof (EAPOL_INTF_PARAMS))
  1723. {
  1724. lError = ERROR_INVALID_DATA;
  1725. TRACE0 (ANY, "ElDeleteEapUserInfo: dwValueData < sizeof (EAPOL_INTF_PARAMS)");
  1726. break;
  1727. }
  1728. pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
  1729. if (((DWORD)_wtol(pwszValueName)) > dwMaxValueName)
  1730. {
  1731. dwMaxValueName = _wtol (pwszValueName);
  1732. }
  1733. if (!memcmp (pRegParams->bSSID, pbSSID, dwSizeOfSSID))
  1734. {
  1735. fFoundValue = TRUE;
  1736. break;
  1737. }
  1738. }
  1739. if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS))
  1740. {
  1741. dwRetCode = (DWORD)lError;
  1742. TRACE1 (ANY, "ElDeleteEapUserInfo: RegEnumValue 2 failed with error %ld",
  1743. dwRetCode);
  1744. break;
  1745. }
  1746. else
  1747. {
  1748. lError = ERROR_SUCCESS;
  1749. }
  1750. if (!fFoundValue)
  1751. {
  1752. break;
  1753. }
  1754. else
  1755. {
  1756. // Use pbValueBuf & dwValueData
  1757. pbEapBlob = pbValueBuf;
  1758. dwEapBlob = dwValueData;
  1759. }
  1760. pbEapBlobIn = pbEapBlob;
  1761. if ((dwRetCode = ElSetEapData (
  1762. dwEapTypeId,
  1763. &dwEapBlob,
  1764. &pbEapBlob,
  1765. sizeof(EAPOL_INTF_PARAMS),
  1766. 0,
  1767. NULL
  1768. )) != NO_ERROR)
  1769. {
  1770. TRACE1 (ANY, "ElDeleteEapUserInfo: ElSetEapData failed with error %ld",
  1771. dwRetCode);
  1772. break;
  1773. }
  1774. // Overwrite value
  1775. if ((lError = RegSetValueEx (
  1776. hkey2,
  1777. pwszValueName,
  1778. 0,
  1779. REG_BINARY,
  1780. pbEapBlob,
  1781. dwEapBlob)) != ERROR_SUCCESS)
  1782. {
  1783. TRACE1 (ANY, "ElDeleteEapUserInfo: Error in RegSetValueEx for SSID, %ld",
  1784. lError);
  1785. dwRetCode = (DWORD)lError;
  1786. break;
  1787. }
  1788. TRACE0 (ANY, "ElDeleteEapUserInfo: Delete value succeeded");
  1789. } while (FALSE);
  1790. if (hkey != NULL)
  1791. {
  1792. RegCloseKey (hkey);
  1793. }
  1794. if (hkey1 != NULL)
  1795. {
  1796. RegCloseKey (hkey1);
  1797. }
  1798. if (hkey2 != NULL)
  1799. {
  1800. RegCloseKey (hkey2);
  1801. }
  1802. if ((pbEapBlob != pbEapBlobIn) && (pbEapBlob != NULL))
  1803. {
  1804. FREE (pbEapBlob);
  1805. }
  1806. if (pbValueBuf != NULL)
  1807. {
  1808. FREE (pbValueBuf);
  1809. }
  1810. if (pwszValueName != NULL)
  1811. {
  1812. FREE (pwszValueName);
  1813. }
  1814. return dwRetCode;
  1815. }
  1816. //
  1817. // ElGetInterfaceParams
  1818. //
  1819. // Description:
  1820. //
  1821. // Function called to retrieve the EAPOL parameters for an interface, stored
  1822. // in the HKLM hive.
  1823. //
  1824. // Arguments:
  1825. //
  1826. // pwszGUID - pointer to GUID string for the interface
  1827. // pIntfParams - pointer to interface parameter structure
  1828. //
  1829. // Return values:
  1830. // NO_ERROR - success
  1831. // non-zero - error
  1832. //
  1833. DWORD
  1834. ElGetInterfaceParams (
  1835. IN WCHAR *pwszGUID,
  1836. IN OUT EAPOL_INTF_PARAMS *pIntfParams
  1837. )
  1838. {
  1839. HKEY hkey = NULL;
  1840. HKEY hkey1 = NULL;
  1841. BYTE *pbSSID = NULL;
  1842. BYTE bSSID[MAX_SSID_LEN];
  1843. DWORD dwSizeOfSSID = 0;
  1844. DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwTempValueNameLen = 0, dwMaxValueLen = 0;
  1845. DWORD dwIndex = 0, dwMaxValueName = 0;
  1846. WCHAR *pwszValueName = NULL;
  1847. BYTE *pbValueBuf = NULL;
  1848. DWORD dwValueData = 0;
  1849. BYTE *pbDefaultValue = NULL;
  1850. DWORD dwDefaultValueLen = 0;
  1851. BYTE *pbEapBlob = NULL;
  1852. DWORD dwEapBlob = 0;
  1853. BOOLEAN fFoundValue = FALSE;
  1854. EAPOL_INTF_PARAMS *pRegParams = NULL;
  1855. EAPOL_POLICY_PARAMS EAPOLPolicyParams = {0};
  1856. LONG lError = ERROR_SUCCESS;
  1857. EAPOL_PCB *pPCB = NULL;
  1858. DWORD dwRetCode = NO_ERROR;
  1859. do
  1860. {
  1861. // Validate input params
  1862. if (pwszGUID == NULL)
  1863. {
  1864. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  1865. TRACE0 (ANY, "ElGetInterfaceParams: GUID = NULL");
  1866. break;
  1867. }
  1868. if (pIntfParams == NULL)
  1869. {
  1870. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  1871. break;
  1872. }
  1873. // Work with appropriate SSID
  1874. if (pIntfParams->dwSizeOfSSID != 0)
  1875. {
  1876. dwSizeOfSSID = pIntfParams->dwSizeOfSSID;
  1877. if (dwSizeOfSSID > MAX_SSID_LEN)
  1878. {
  1879. dwRetCode = ERROR_INVALID_PARAMETER;
  1880. TRACE2 (ANY, "ElGetInterfaceParams: dwSizeOfSSID (%ld) > MAX_SSID_LEN (%ld)",
  1881. dwSizeOfSSID, MAX_SSID_LEN);
  1882. break;
  1883. }
  1884. pbSSID = pIntfParams->bSSID;
  1885. }
  1886. else
  1887. {
  1888. ACQUIRE_WRITE_LOCK (&g_PCBLock);
  1889. if ((pPCB = ElGetPCBPointerFromPortGUID (pwszGUID)) != NULL)
  1890. {
  1891. ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
  1892. if ((pPCB->pSSID != NULL) && (pPCB->MediaState != MEDIA_STATE_DISCONNECTED))
  1893. {
  1894. dwSizeOfSSID = pPCB->pSSID->SsidLength;
  1895. ZeroMemory (bSSID, MAX_SSID_LEN);
  1896. memcpy (bSSID, pPCB->pSSID->Ssid, pPCB->pSSID->SsidLength);
  1897. pbSSID = bSSID;
  1898. }
  1899. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  1900. }
  1901. RELEASE_WRITE_LOCK (&g_PCBLock);
  1902. if (dwSizeOfSSID == 0)
  1903. {
  1904. dwSizeOfSSID = MAX_SSID_LEN;
  1905. pbSSID = g_bDefaultSSID;
  1906. }
  1907. }
  1908. // Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
  1909. if ((lError = RegOpenKeyEx (
  1910. HKEY_LOCAL_MACHINE,
  1911. cwszEapKeyEapolConn,
  1912. 0,
  1913. KEY_READ,
  1914. &hkey
  1915. )) != ERROR_SUCCESS)
  1916. {
  1917. // Assume no value is found and proceed ahead
  1918. if (lError == ERROR_FILE_NOT_FOUND)
  1919. {
  1920. lError = ERROR_SUCCESS;
  1921. fFoundValue = FALSE;
  1922. goto LNotFoundValue;
  1923. }
  1924. else
  1925. {
  1926. TRACE1 (ANY, "ElGetInterfaceParams: Error in RegOpenKeyEx for base key, %ld",
  1927. lError);
  1928. dwRetCode = (DWORD)lError;
  1929. break;
  1930. }
  1931. }
  1932. // Get handle to HKLM\Software\...\Interfaces\<GUID>
  1933. if ((lError = RegOpenKeyEx (
  1934. hkey,
  1935. pwszGUID,
  1936. 0,
  1937. KEY_READ,
  1938. &hkey1
  1939. )) != ERROR_SUCCESS)
  1940. {
  1941. // Assume no value is found and proceed ahead
  1942. if (lError == ERROR_FILE_NOT_FOUND)
  1943. {
  1944. lError = ERROR_SUCCESS;
  1945. fFoundValue = FALSE;
  1946. goto LNotFoundValue;
  1947. }
  1948. else
  1949. {
  1950. TRACE1 (ANY, "ElGetInterfaceParams: Error in RegOpenKeyEx for GUID, %ld",
  1951. lError);
  1952. dwRetCode = (DWORD)lError;
  1953. break;
  1954. }
  1955. }
  1956. if ((lError = RegQueryInfoKey (
  1957. hkey1,
  1958. NULL,
  1959. NULL,
  1960. NULL,
  1961. NULL,
  1962. NULL,
  1963. NULL,
  1964. &dwNumValues,
  1965. &dwMaxValueNameLen,
  1966. &dwMaxValueLen,
  1967. NULL,
  1968. NULL
  1969. )) != NO_ERROR)
  1970. {
  1971. dwRetCode = (DWORD)lError;
  1972. TRACE1 (ANY, "ElGetInterfaceParams: RegQueryInfoKey failed with error %ld",
  1973. dwRetCode);
  1974. break;
  1975. }
  1976. if ((pwszValueName = MALLOC ((dwMaxValueNameLen + 1) * sizeof (WCHAR))) == NULL)
  1977. {
  1978. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1979. TRACE0 (ANY, "ElGetInterfaceParams: MALLOC failed for pwszValueName");
  1980. break;
  1981. }
  1982. dwMaxValueNameLen++;
  1983. if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL)
  1984. {
  1985. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1986. TRACE0 (ANY, "ElGetInterfaceParams: MALLOC failed for pbValueBuf");
  1987. break;
  1988. }
  1989. for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++)
  1990. {
  1991. dwValueData = dwMaxValueLen;
  1992. dwTempValueNameLen = dwMaxValueNameLen;
  1993. if ((lError = RegEnumValue (
  1994. hkey1,
  1995. dwIndex,
  1996. pwszValueName,
  1997. &dwTempValueNameLen,
  1998. NULL,
  1999. NULL,
  2000. pbValueBuf,
  2001. &dwValueData
  2002. )) != ERROR_SUCCESS)
  2003. {
  2004. if (lError != ERROR_MORE_DATA)
  2005. {
  2006. break;
  2007. }
  2008. lError = ERROR_SUCCESS;
  2009. }
  2010. if (dwValueData < sizeof (EAPOL_INTF_PARAMS))
  2011. {
  2012. TRACE0 (ANY, "ElGetInterfaceParams: dwValueData < sizeof (EAPOL_INTF_PARAMS)");
  2013. lError = ERROR_INVALID_DATA;
  2014. break;
  2015. }
  2016. pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
  2017. if (((DWORD)_wtol(pwszValueName)) > dwMaxValueName)
  2018. {
  2019. dwMaxValueName = _wtol (pwszValueName);
  2020. }
  2021. if (!memcmp (pRegParams->bSSID, pbSSID, dwSizeOfSSID))
  2022. {
  2023. fFoundValue = TRUE;
  2024. break;
  2025. }
  2026. }
  2027. if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS))
  2028. {
  2029. dwRetCode = (DWORD)lError;
  2030. break;
  2031. }
  2032. else
  2033. {
  2034. lError = ERROR_SUCCESS;
  2035. }
  2036. LNotFoundValue:
  2037. if (!fFoundValue)
  2038. {
  2039. if ((pbDefaultValue = MALLOC (sizeof (EAPOL_INTF_PARAMS))) == NULL)
  2040. {
  2041. lError = ERROR_NOT_ENOUGH_MEMORY;
  2042. TRACE0 (ANY, "ElGetInterfaceParams: MALLOC failed for pbDefaultValue");
  2043. break;
  2044. }
  2045. pRegParams = (EAPOL_INTF_PARAMS *)pbDefaultValue;
  2046. pRegParams->dwEapType = DEFAULT_EAP_TYPE;
  2047. pRegParams->dwEapFlags = DEFAULT_EAP_STATE;
  2048. pRegParams->dwVersion = EAPOL_CURRENT_VERSION;
  2049. pRegParams->dwSizeOfSSID = dwSizeOfSSID;
  2050. memcpy (pRegParams->bSSID, pbSSID, dwSizeOfSSID);
  2051. dwDefaultValueLen = sizeof(EAPOL_INTF_PARAMS);
  2052. // Use pbDefaultValue & dwDefaultValueLen
  2053. pbEapBlob = pbDefaultValue;
  2054. dwEapBlob = dwDefaultValueLen;
  2055. }
  2056. else
  2057. {
  2058. if (dwSizeOfSSID == MAX_SSID_LEN)
  2059. {
  2060. if (!memcmp (pbSSID, g_bDefaultSSID, MAX_SSID_LEN))
  2061. {
  2062. pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
  2063. if ((pRegParams->dwVersion != EAPOL_CURRENT_VERSION) &&
  2064. (pRegParams->dwEapType == EAP_TYPE_TLS))
  2065. {
  2066. pRegParams->dwVersion = EAPOL_CURRENT_VERSION;
  2067. pRegParams->dwEapFlags |= DEFAULT_MACHINE_AUTH_STATE;
  2068. pRegParams->dwEapFlags &= ~EAPOL_GUEST_AUTH_ENABLED;
  2069. }
  2070. }
  2071. }
  2072. // Use pbValueBuf & dwValueData
  2073. pbEapBlob = pbValueBuf;
  2074. dwEapBlob = dwValueData;
  2075. }
  2076. if ((dwRetCode = ElGetPolicyInterfaceParams (
  2077. dwSizeOfSSID,
  2078. pbSSID,
  2079. &EAPOLPolicyParams
  2080. )) == NO_ERROR)
  2081. {
  2082. TRACE0 (ANY, "ElGetInterfaceParams: POLICY: ElGetPolicyInterfaceParams found relevant data");
  2083. pbEapBlob = (PBYTE)(&(EAPOLPolicyParams.IntfParams));
  2084. dwEapBlob = sizeof(EAPOL_INTF_PARAMS);
  2085. }
  2086. else
  2087. {
  2088. if (dwRetCode != ERROR_FILE_NOT_FOUND)
  2089. {
  2090. TRACE1 (ANY, "ElGetInterfaceParams: ElGetPolicyInterfaceParams failed with error (%ld)",
  2091. dwRetCode);
  2092. }
  2093. dwRetCode = NO_ERROR;
  2094. }
  2095. // Existing blob is not valid
  2096. if ((dwEapBlob < sizeof(EAPOL_INTF_PARAMS)))
  2097. {
  2098. dwRetCode = ERROR_FILE_NOT_FOUND;
  2099. TRACE0 (ANY, "ElGetInterfaceParams: (dwEapBlob < sizeof(EAPOL_INTF_PARAMS)) || (pbEapBlob == NULL)");
  2100. break;
  2101. }
  2102. memcpy ((BYTE *)pIntfParams, (BYTE *)pbEapBlob, sizeof(EAPOL_INTF_PARAMS));
  2103. } while (FALSE);
  2104. if (hkey != NULL)
  2105. {
  2106. RegCloseKey (hkey);
  2107. }
  2108. if (hkey1 != NULL)
  2109. {
  2110. RegCloseKey (hkey1);
  2111. }
  2112. if (pbValueBuf != NULL)
  2113. {
  2114. FREE (pbValueBuf);
  2115. }
  2116. if (pbDefaultValue != NULL)
  2117. {
  2118. FREE (pbDefaultValue);
  2119. }
  2120. if (pwszValueName != NULL)
  2121. {
  2122. FREE (pwszValueName);
  2123. }
  2124. return dwRetCode;
  2125. }
  2126. //
  2127. // ElSetInterfaceParams
  2128. //
  2129. // Description:
  2130. //
  2131. // Function called to set the EAPOL parameters for an interface, in the HKLM
  2132. // hive
  2133. //
  2134. // Arguments:
  2135. //
  2136. // pwszGUID - Pointer to GUID string for the interface
  2137. // pIntfParams - pointer to interface parameter structure
  2138. //
  2139. // Return values:
  2140. // NO_ERROR - success
  2141. // non-zero - error
  2142. //
  2143. //
  2144. DWORD
  2145. ElSetInterfaceParams (
  2146. IN WCHAR *pwszGUID,
  2147. IN OUT EAPOL_INTF_PARAMS *pIntfParams
  2148. )
  2149. {
  2150. HKEY hkey = NULL;
  2151. HKEY hkey1 = NULL;
  2152. DWORD dwDisposition;
  2153. BYTE *pbSSID = NULL;
  2154. DWORD dwSizeOfSSID = 0;
  2155. DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwMaxValueLen = 0;
  2156. DWORD dwIndex = 0, dwMaxValueName = 0;
  2157. WCHAR wcszValueName[MAX_VALUENAME_LEN];
  2158. BYTE *pbValueBuf = NULL;
  2159. DWORD dwValueData = 0;
  2160. BYTE *pbDefaultValue = NULL;
  2161. DWORD dwDefaultValueLen = 0;
  2162. BYTE *pbEapBlob = NULL;
  2163. DWORD dwEapBlob = 0;
  2164. BOOLEAN fFoundValue = FALSE;
  2165. EAPOL_INTF_PARAMS *pRegParams = NULL;
  2166. LONG lError = ERROR_SUCCESS;
  2167. DWORD dwRetCode = NO_ERROR;
  2168. do
  2169. {
  2170. // Validate input params
  2171. if (pwszGUID == NULL)
  2172. {
  2173. TRACE0 (ANY, "ElSetInterfaceParams: GUID = NULL");
  2174. break;
  2175. }
  2176. if (pIntfParams == NULL)
  2177. {
  2178. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  2179. break;
  2180. }
  2181. TRACE1 (ANY, "Setting stuff in registry for %ws", pwszGUID);
  2182. // Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
  2183. if ((lError = RegCreateKeyEx (
  2184. HKEY_LOCAL_MACHINE,
  2185. cwszEapKeyEapolConn,
  2186. 0,
  2187. NULL,
  2188. REG_OPTION_NON_VOLATILE,
  2189. KEY_WRITE | KEY_READ,
  2190. NULL,
  2191. &hkey,
  2192. &dwDisposition)) != ERROR_SUCCESS)
  2193. {
  2194. TRACE1 (ANY, "ElSetInterfaceParams: Error in RegCreateKeyEx for base key, %ld",
  2195. lError);
  2196. dwRetCode = (DWORD)lError;
  2197. break;
  2198. }
  2199. // Get handle to HKLM\Software\...\Interfaces\<GUID>
  2200. if ((lError = RegCreateKeyEx (
  2201. hkey,
  2202. pwszGUID,
  2203. 0,
  2204. NULL,
  2205. REG_OPTION_NON_VOLATILE,
  2206. KEY_WRITE | KEY_READ,
  2207. NULL,
  2208. &hkey1,
  2209. &dwDisposition)) != ERROR_SUCCESS)
  2210. {
  2211. TRACE1 (ANY, "ElSetInterfaceParams: Error in RegCreateKeyEx for GUID, %ld",
  2212. lError);
  2213. dwRetCode = (DWORD)lError;
  2214. break;
  2215. }
  2216. // Select correct SSID value
  2217. if (pIntfParams->dwSizeOfSSID != 0)
  2218. {
  2219. dwSizeOfSSID = pIntfParams->dwSizeOfSSID;
  2220. if (dwSizeOfSSID > MAX_SSID_LEN)
  2221. {
  2222. dwRetCode = ERROR_INVALID_PARAMETER;
  2223. TRACE2 (ANY, "ElSetInterfaceParams: dwSizeOfSSID (%ld) > MAX_SSID_LEN (%ld)",
  2224. dwSizeOfSSID, MAX_SSID_LEN);
  2225. break;
  2226. }
  2227. pbSSID = pIntfParams->bSSID;
  2228. }
  2229. else
  2230. {
  2231. dwSizeOfSSID = MAX_SSID_LEN;
  2232. pbSSID = g_bDefaultSSID;
  2233. }
  2234. if ((lError = RegQueryInfoKey (
  2235. hkey1,
  2236. NULL,
  2237. NULL,
  2238. NULL,
  2239. NULL,
  2240. NULL,
  2241. NULL,
  2242. &dwNumValues,
  2243. &dwMaxValueNameLen,
  2244. &dwMaxValueLen,
  2245. NULL,
  2246. NULL
  2247. )) != NO_ERROR)
  2248. {
  2249. dwRetCode = (DWORD)lError;
  2250. break;
  2251. }
  2252. if (dwMaxValueNameLen > MAX_VALUENAME_LEN)
  2253. {
  2254. dwRetCode = ERROR_INVALID_DATA;
  2255. TRACE1 (ANY, "ElSetInterfaceParams: dwMaxValueNameLen too long (%ld)",
  2256. dwMaxValueNameLen);
  2257. break;
  2258. }
  2259. if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL)
  2260. {
  2261. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  2262. break;
  2263. }
  2264. for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++)
  2265. {
  2266. dwValueData = dwMaxValueLen;
  2267. dwMaxValueNameLen = MAX_VALUENAME_LEN;
  2268. ZeroMemory (wcszValueName, MAX_VALUENAME_LEN*sizeof(WCHAR));
  2269. if ((lError = RegEnumValue (
  2270. hkey1,
  2271. dwIndex,
  2272. wcszValueName,
  2273. &dwMaxValueNameLen,
  2274. NULL,
  2275. NULL,
  2276. pbValueBuf,
  2277. &dwValueData
  2278. )) != ERROR_SUCCESS)
  2279. {
  2280. if (lError != ERROR_MORE_DATA)
  2281. {
  2282. break;
  2283. }
  2284. lError = ERROR_SUCCESS;
  2285. }
  2286. if (dwValueData < sizeof (EAPOL_INTF_PARAMS))
  2287. {
  2288. lError = ERROR_INVALID_DATA;
  2289. TRACE0 (ANY, "ElSetInterfaceParams: dwValueData < sizeof (EAPOL_INTF_PARAMS)");
  2290. break;
  2291. }
  2292. pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
  2293. if (((DWORD)_wtol(wcszValueName)) > dwMaxValueName)
  2294. {
  2295. dwMaxValueName = _wtol (wcszValueName);
  2296. }
  2297. if (!memcmp (pRegParams->bSSID, pbSSID, dwSizeOfSSID))
  2298. {
  2299. fFoundValue = TRUE;
  2300. break;
  2301. }
  2302. }
  2303. if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS))
  2304. {
  2305. dwRetCode = (DWORD)lError;
  2306. TRACE1 (ANY, "ElSetInterfaceParams: RegEnumValue 2 failed with error %ld",
  2307. dwRetCode);
  2308. break;
  2309. }
  2310. else
  2311. {
  2312. lError = ERROR_SUCCESS;
  2313. }
  2314. if (!fFoundValue)
  2315. {
  2316. DWORD dwNewValueName = (dwMaxValueName >= dwNumValues)?(++dwMaxValueName):dwNumValues;
  2317. _ltow (dwNewValueName, wcszValueName, 10);
  2318. }
  2319. else
  2320. {
  2321. // Use pbValueBuf & dwValueData
  2322. pbEapBlob = pbValueBuf;
  2323. dwEapBlob = dwValueData;
  2324. }
  2325. if ((dwEapBlob < sizeof(EAPOL_INTF_PARAMS)) && (pbEapBlob != NULL))
  2326. {
  2327. TRACE0 (ANY, "ElSetInterfaceParams: (dwEapBlob < sizeof(EAPOL_INTF_PARAMS)) && (pbEapBlob != NULL)");
  2328. break;
  2329. }
  2330. if (pbEapBlob != NULL)
  2331. {
  2332. memcpy ((BYTE *)pbEapBlob, (BYTE *)pIntfParams, sizeof(EAPOL_INTF_PARAMS));
  2333. }
  2334. else
  2335. {
  2336. pbEapBlob = (BYTE *)pIntfParams;
  2337. dwEapBlob = sizeof(EAPOL_INTF_PARAMS);
  2338. }
  2339. pRegParams = (EAPOL_INTF_PARAMS *)pbEapBlob;
  2340. pRegParams->dwVersion = EAPOL_CURRENT_VERSION;
  2341. pRegParams->dwSizeOfSSID = dwSizeOfSSID;
  2342. memcpy (pRegParams->bSSID, pbSSID, dwSizeOfSSID);
  2343. // Overwrite/Create new value
  2344. if ((lError = RegSetValueEx (
  2345. hkey1,
  2346. wcszValueName,
  2347. 0,
  2348. REG_BINARY,
  2349. pbEapBlob,
  2350. dwEapBlob)) != ERROR_SUCCESS)
  2351. {
  2352. TRACE1 (ANY, "ElSetInterfaceParams: Error in RegSetValueEx for SSID, %ld",
  2353. lError);
  2354. dwRetCode = (DWORD)lError;
  2355. break;
  2356. }
  2357. TRACE0 (ANY, "ElSetInterfaceParams: Succeeded");
  2358. } while (FALSE);
  2359. if (hkey != NULL)
  2360. {
  2361. RegCloseKey (hkey);
  2362. }
  2363. if (hkey1 != NULL)
  2364. {
  2365. RegCloseKey (hkey1);
  2366. }
  2367. if (pbValueBuf != NULL)
  2368. {
  2369. FREE (pbValueBuf);
  2370. }
  2371. if (pbDefaultValue != NULL)
  2372. {
  2373. FREE (pbDefaultValue);
  2374. }
  2375. return dwRetCode;
  2376. }
  2377. //
  2378. // ElGetEapData
  2379. //
  2380. // Description:
  2381. //
  2382. // Function to extract Eap Data out of a blob containing many EAP data
  2383. //
  2384. // Arguments:
  2385. // dwEapType -
  2386. // dwSizeOfIn -
  2387. // pbBufferIn -
  2388. // dwOffset -
  2389. // pdwSizeOfOut -
  2390. // ppbBufferOut -
  2391. //
  2392. // Return values:
  2393. //
  2394. //
  2395. DWORD
  2396. ElGetEapData (
  2397. IN DWORD dwEapType,
  2398. IN DWORD dwSizeOfIn,
  2399. IN BYTE *pbBufferIn,
  2400. IN DWORD dwOffset,
  2401. IN DWORD *pdwSizeOfOut,
  2402. IN PBYTE *ppbBufferOut
  2403. )
  2404. {
  2405. DWORD dwRetCode = NO_ERROR;
  2406. DWORD cbOffset = 0;
  2407. EAPOL_AUTH_DATA *pCustomData = NULL;
  2408. do
  2409. {
  2410. *pdwSizeOfOut = 0;
  2411. *ppbBufferOut = NULL;
  2412. if (pbBufferIn == NULL)
  2413. {
  2414. break;
  2415. }
  2416. // Align to start of EAP blob
  2417. cbOffset = dwOffset;
  2418. while (cbOffset < dwSizeOfIn)
  2419. {
  2420. pCustomData = (EAPOL_AUTH_DATA *)
  2421. ((PBYTE) pbBufferIn + cbOffset);
  2422. if (pCustomData->dwEapType == dwEapType)
  2423. {
  2424. break;
  2425. }
  2426. cbOffset += sizeof (EAPOL_AUTH_DATA) + pCustomData->dwSize;
  2427. }
  2428. if (cbOffset < dwSizeOfIn)
  2429. {
  2430. *pdwSizeOfOut = pCustomData->dwSize;
  2431. *ppbBufferOut = pCustomData->bData;
  2432. }
  2433. }
  2434. while (FALSE);
  2435. return dwRetCode;
  2436. }
  2437. //
  2438. // ElSetEapData
  2439. //
  2440. // Description:
  2441. //
  2442. // Function to set Eap Data in a blob containing many EAP data
  2443. //
  2444. // Arguments:
  2445. // dwEapType -
  2446. // dwSizeOfIn -
  2447. // pbBufferIn -
  2448. // dwOffset -
  2449. // pdwSizeOfOut -
  2450. // ppbBufferOut -
  2451. //
  2452. // Return values:
  2453. //
  2454. //
  2455. DWORD
  2456. ElSetEapData (
  2457. IN DWORD dwEapType,
  2458. IN DWORD *pdwSizeOfIn,
  2459. IN PBYTE *ppbBufferIn,
  2460. IN DWORD dwOffset,
  2461. IN DWORD dwAuthData,
  2462. IN PBYTE pbAuthData
  2463. )
  2464. {
  2465. DWORD cbOffset = 0;
  2466. EAPOL_AUTH_DATA *pCustomData = NULL;
  2467. BYTE *pbNewAuthData = NULL;
  2468. DWORD dwSize = 0;
  2469. DWORD dwRetCode = NO_ERROR;
  2470. do
  2471. {
  2472. // Align to start of EAP blob
  2473. cbOffset = dwOffset;
  2474. // Find the old EAP Data
  2475. while (cbOffset < *pdwSizeOfIn)
  2476. {
  2477. pCustomData = (EAPOL_AUTH_DATA *)
  2478. ((PBYTE) *ppbBufferIn + cbOffset);
  2479. if (pCustomData->dwEapType == dwEapType)
  2480. {
  2481. break;
  2482. }
  2483. cbOffset += sizeof (EAPOL_AUTH_DATA) + pCustomData->dwSize;
  2484. }
  2485. if (cbOffset < *pdwSizeOfIn)
  2486. {
  2487. dwSize = sizeof (EAPOL_AUTH_DATA) + pCustomData->dwSize;
  2488. MoveMemory (*ppbBufferIn + cbOffset,
  2489. *ppbBufferIn + cbOffset + dwSize,
  2490. *pdwSizeOfIn - cbOffset - dwSize);
  2491. *pdwSizeOfIn -= dwSize;
  2492. }
  2493. if ((*pdwSizeOfIn == 0) && (*ppbBufferIn != NULL))
  2494. {
  2495. // FREE (*ppbBufferIn);
  2496. *ppbBufferIn = NULL;
  2497. }
  2498. if ((dwAuthData == 0) || (pbAuthData == NULL))
  2499. {
  2500. break;
  2501. }
  2502. #ifdef _WIN64
  2503. dwSize = ((dwAuthData+7) & 0xfffffff8) + *pdwSizeOfIn + sizeof (EAPOL_AUTH_DATA);
  2504. #else
  2505. dwSize = dwAuthData + *pdwSizeOfIn + sizeof (EAPOL_AUTH_DATA);
  2506. #endif
  2507. if ((pbNewAuthData = MALLOC (dwSize)) == NULL)
  2508. {
  2509. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  2510. break;
  2511. }
  2512. CopyMemory (pbNewAuthData, *ppbBufferIn, *pdwSizeOfIn);
  2513. pCustomData = (EAPOL_AUTH_DATA *) (pbNewAuthData + *pdwSizeOfIn);
  2514. pCustomData->dwEapType = dwEapType;
  2515. CopyMemory (pCustomData->bData, pbAuthData, dwAuthData);
  2516. #ifdef _WIN64
  2517. pCustomData->dwSize = (dwAuthData+7) & 0xfffffff8;
  2518. #else
  2519. pCustomData->dwSize = dwAuthData;
  2520. #endif
  2521. if (*ppbBufferIn != NULL)
  2522. {
  2523. // FREE (*ppbBufferIn);
  2524. }
  2525. *ppbBufferIn = pbNewAuthData;
  2526. *pdwSizeOfIn = dwSize;
  2527. }
  2528. while (FALSE);
  2529. return dwRetCode;
  2530. }
  2531. //
  2532. // ElGetEapKeyFromToken
  2533. //
  2534. // Description:
  2535. //
  2536. // Function to get handle to User hive from User Token
  2537. //
  2538. // Arguments:
  2539. // hUserToken - handle to user token
  2540. // phkey - output: pointer to handle to user hive
  2541. //
  2542. // Return values:
  2543. // NO_ERROR - success
  2544. // non-zero - error
  2545. //
  2546. DWORD
  2547. ElGetEapKeyFromToken (
  2548. IN HANDLE hUserToken,
  2549. OUT HKEY *phkey
  2550. )
  2551. {
  2552. DWORD dwSizeNeeded;
  2553. TOKEN_USER *pTokenData = NULL;
  2554. UNICODE_STRING UnicodeSidString;
  2555. WCHAR wsUnicodeBuffer[256];
  2556. HKEY hUserKey;
  2557. HKEY hkeyEap;
  2558. DWORD dwDisposition;
  2559. NTSTATUS Status = STATUS_SUCCESS;
  2560. PBYTE pbInfo = NULL;
  2561. CHAR *pszInfo = NULL;
  2562. DWORD dwType;
  2563. DWORD dwInfoSize = 0;
  2564. LONG lRetVal;
  2565. EAPOL_PCB *pPCB;
  2566. DWORD i;
  2567. LONG lError = ERROR_SUCCESS;
  2568. DWORD dwRetCode = NO_ERROR;
  2569. do
  2570. {
  2571. if (hUserToken != NULL)
  2572. {
  2573. if (!GetTokenInformation(hUserToken, TokenUser, 0, 0, &dwSizeNeeded))
  2574. {
  2575. if ((dwRetCode = GetLastError()) == ERROR_INSUFFICIENT_BUFFER)
  2576. {
  2577. pTokenData = (TOKEN_USER *) MALLOC (dwSizeNeeded);
  2578. if (pTokenData == NULL)
  2579. {
  2580. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  2581. TRACE0 (ANY,"ElGetEapKeyFromToken: Allocation for TokenData failed");
  2582. break;
  2583. }
  2584. // Reset error code since we are continuing processing
  2585. // This was a valid scenario
  2586. dwRetCode = NO_ERROR;
  2587. }
  2588. else
  2589. {
  2590. TRACE1 (ANY,"ElGetEapKeyFromToken: Error in GetTokenInformation = %ld",
  2591. dwRetCode);
  2592. break;
  2593. }
  2594. if (!GetTokenInformation (hUserToken,
  2595. TokenUser,
  2596. pTokenData,
  2597. dwSizeNeeded,
  2598. &dwSizeNeeded))
  2599. {
  2600. dwRetCode = GetLastError ();
  2601. TRACE1 (ANY,"ElGetEapKeyFromToken: GetTokenInformation failed with error %ld",
  2602. dwRetCode);
  2603. break;
  2604. }
  2605. UnicodeSidString.Buffer = wsUnicodeBuffer;
  2606. UnicodeSidString.Length = 0;
  2607. UnicodeSidString.MaximumLength = sizeof(wsUnicodeBuffer);
  2608. Status = RtlConvertSidToUnicodeString (
  2609. &UnicodeSidString,
  2610. pTokenData->User.Sid,
  2611. FALSE);
  2612. if (!NT_SUCCESS(Status))
  2613. {
  2614. dwRetCode = GetLastError ();
  2615. TRACE1 (ANY, "ElGetEapKeyFromToken: RtlconvertSidToUnicodeString failed with error %ld",
  2616. dwRetCode);
  2617. break;
  2618. }
  2619. UnicodeSidString.Buffer[UnicodeSidString.Length] = 0;
  2620. // Open the user's key
  2621. if ((lError = RegOpenKeyEx(HKEY_USERS,
  2622. UnicodeSidString.Buffer,
  2623. 0,
  2624. KEY_ALL_ACCESS,
  2625. &hUserKey)) != ERROR_SUCCESS)
  2626. {
  2627. dwRetCode = (DWORD)lError;
  2628. TRACE1 (USER, "ElGetEapKeyFromToken: RegOpenKeyEx failed with error %ld",
  2629. dwRetCode);
  2630. break;
  2631. }
  2632. else
  2633. {
  2634. TRACE0 (ANY, "ElGetEapKeyFromToken: RegOpenKeyEx succeeded");
  2635. }
  2636. }
  2637. else
  2638. {
  2639. TRACE0 (ANY,"ElGetEapKeyFromToken: GetTokenInformation succeeded when it should have failed");
  2640. break;
  2641. }
  2642. }
  2643. else
  2644. {
  2645. TRACE0 (ANY, "ElGetEapKeyFromToken: Error, hUserToken == NULL ");
  2646. dwRetCode = ERROR_NO_TOKEN;
  2647. break;
  2648. }
  2649. *phkey = hUserKey;
  2650. } while (FALSE);
  2651. if (pTokenData != NULL)
  2652. {
  2653. FREE (pTokenData);
  2654. }
  2655. return dwRetCode;
  2656. }
  2657. //
  2658. // ElInitRegPortData
  2659. //
  2660. // Description:
  2661. //
  2662. // Function to verify existence of connection data for the port
  2663. // If no data exists, initialize with default values
  2664. // For EAP-TLS, default settings are no server certificate authentication,
  2665. // registry certificates
  2666. //
  2667. // Arguments:
  2668. // pwszDeviceGUID - Pointer to GUID string for the port for which data is being
  2669. // initiialized
  2670. //
  2671. // Return values:
  2672. // NO_ERROR - success
  2673. // non-zero - error
  2674. //
  2675. DWORD
  2676. ElInitRegPortData (
  2677. WCHAR *pwszDeviceGUID
  2678. )
  2679. {
  2680. DWORD dwAuthData = 0;
  2681. BYTE *pConnProp = NULL;
  2682. DWORD dwSizeOfConnProp = 0;
  2683. DWORD dwRetCode = NO_ERROR;
  2684. do
  2685. {
  2686. // Get the size of the Eap data first
  2687. if ((dwRetCode = ElGetCustomAuthData (
  2688. pwszDeviceGUID,
  2689. DEFAULT_EAP_TYPE,
  2690. 0,
  2691. NULL,
  2692. NULL,
  2693. &dwAuthData
  2694. )) != NO_ERROR)
  2695. {
  2696. TRACE1 (ANY, "ElInitRegPortData: ElGetCustomAuthData returned error %ld",
  2697. dwRetCode);
  2698. // There is data in the registry
  2699. if (dwRetCode == ERROR_BUFFER_TOO_SMALL)
  2700. {
  2701. dwRetCode = NO_ERROR;
  2702. break;
  2703. }
  2704. if ((dwRetCode = ElCreateDefaultEapData (&dwSizeOfConnProp, NULL)) == ERROR_BUFFER_TOO_SMALL)
  2705. {
  2706. if ((pConnProp = MALLOC (dwSizeOfConnProp)) == NULL)
  2707. {
  2708. TRACE0 (ANY, "ElInitRegPortData: MALLOC failed for Conn Prop");
  2709. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  2710. break;
  2711. }
  2712. if ((dwRetCode = ElCreateDefaultEapData (&dwSizeOfConnProp, pConnProp)) != NO_ERROR)
  2713. {
  2714. TRACE1 (ANY, "ElInitRegPortData: ElCreateDefaultEapData failed with error (%ld)",
  2715. dwRetCode);
  2716. break;
  2717. }
  2718. }
  2719. // Set this blob into the registry for the port
  2720. if ((dwRetCode = ElSetCustomAuthData (
  2721. pwszDeviceGUID,
  2722. DEFAULT_EAP_TYPE,
  2723. 0,
  2724. NULL,
  2725. pConnProp,
  2726. &dwSizeOfConnProp
  2727. )) != NO_ERROR)
  2728. {
  2729. TRACE1 (ANY, "ElInitRegPortData: ElSetCustomAuthData failed with %ld",
  2730. dwRetCode);
  2731. break;
  2732. }
  2733. }
  2734. } while (FALSE);
  2735. if (pConnProp != NULL)
  2736. {
  2737. FREE (pConnProp);
  2738. pConnProp = NULL;
  2739. }
  2740. TRACE1 (ANY, "ElInitRegPortData: completed with error %ld", dwRetCode);
  2741. return dwRetCode;
  2742. }
  2743. //
  2744. // ElCreateDefaultEapData
  2745. //
  2746. // Description:
  2747. //
  2748. // Function to create default EAP data for a connection
  2749. // Current default EAP type is EAP-TLS.
  2750. // For EAP-TLS, default settings are no server certificate authentication,
  2751. // registry certificates
  2752. //
  2753. // Arguments:
  2754. // *pdwSizeOfEapData -
  2755. // pbEapData -
  2756. //
  2757. // Return values:
  2758. // NO_ERROR - success
  2759. // non-zero - error
  2760. //
  2761. DWORD
  2762. ElCreateDefaultEapData (
  2763. IN OUT DWORD *pdwSizeOfEapData,
  2764. IN OUT BYTE *pbEapData
  2765. )
  2766. {
  2767. EAPTLS_CONN_PROPERTIES ConnProp;
  2768. DWORD dwRetCode = NO_ERROR;
  2769. do
  2770. {
  2771. if (*pdwSizeOfEapData < sizeof (EAPTLS_CONN_PROPERTIES))
  2772. {
  2773. *pdwSizeOfEapData = sizeof (EAPTLS_CONN_PROPERTIES);
  2774. dwRetCode = ERROR_BUFFER_TOO_SMALL;
  2775. break;
  2776. }
  2777. ZeroMemory ((VOID *)&ConnProp, sizeof (EAPTLS_CONN_PROPERTIES));
  2778. // Registry certs, Server cert validation, No server name
  2779. // comparison
  2780. ConnProp.fFlags = (EAPTLS_CONN_FLAG_REGISTRY |
  2781. EAPTLS_CONN_FLAG_NO_VALIDATE_CERT |
  2782. EAPTLS_CONN_FLAG_NO_VALIDATE_NAME);
  2783. ConnProp.fFlags &= ~EAPTLS_CONN_FLAG_NO_VALIDATE_CERT;
  2784. ConnProp.dwSize = sizeof (EAPTLS_CONN_PROPERTIES);
  2785. memcpy ((VOID *)pbEapData, (VOID *)&ConnProp, sizeof (EAPTLS_CONN_PROPERTIES));
  2786. *pdwSizeOfEapData = sizeof (EAPTLS_CONN_PROPERTIES);
  2787. } while (FALSE);
  2788. return dwRetCode;
  2789. }
  2790. //
  2791. // ElAuthAttributeGetVendorSpecific
  2792. //
  2793. //
  2794. // Description:
  2795. // Helper function used to extract MPPE Key out of Attrribute.
  2796. //
  2797. RAS_AUTH_ATTRIBUTE *
  2798. ElAuthAttributeGetVendorSpecific (
  2799. IN DWORD dwVendorId,
  2800. IN DWORD dwVendorType,
  2801. IN RAS_AUTH_ATTRIBUTE * pAttributes
  2802. )
  2803. {
  2804. HANDLE hAttribute;
  2805. RAS_AUTH_ATTRIBUTE * pAttribute;
  2806. //
  2807. // First search for the vendor specific attribute
  2808. //
  2809. pAttribute = ElAuthAttributeGetFirst ( raatVendorSpecific,
  2810. pAttributes,
  2811. &hAttribute );
  2812. while ( pAttribute != NULL )
  2813. {
  2814. //
  2815. // If this attribute is of at least size to hold vendor Id/Type
  2816. //
  2817. if ( pAttribute->dwLength >= 8 )
  2818. {
  2819. //
  2820. // Does this have the correct VendorId
  2821. //
  2822. if (WireToHostFormat32( (PBYTE)(pAttribute->Value) ) == dwVendorId)
  2823. {
  2824. //
  2825. // Does this have the correct Vendor Type
  2826. //
  2827. if ( *(((PBYTE)(pAttribute->Value))+4) == dwVendorType )
  2828. {
  2829. return( pAttribute );
  2830. }
  2831. }
  2832. }
  2833. pAttribute = ElAuthAttributeGetNext ( &hAttribute,
  2834. raatVendorSpecific );
  2835. }
  2836. return( NULL );
  2837. }
  2838. //
  2839. // ElAuthAttributeGetFirst
  2840. //
  2841. // Description:
  2842. // Helper function used to extract MPPE Key out of Attrribute.
  2843. //
  2844. RAS_AUTH_ATTRIBUTE *
  2845. ElAuthAttributeGetFirst (
  2846. IN RAS_AUTH_ATTRIBUTE_TYPE raaType,
  2847. IN RAS_AUTH_ATTRIBUTE * pAttributes,
  2848. OUT HANDLE * phAttribute
  2849. )
  2850. {
  2851. DWORD dwIndex;
  2852. RAS_AUTH_ATTRIBUTE * pRequiredAttribute;
  2853. pRequiredAttribute = ElAuthAttributeGet ( raaType, pAttributes );
  2854. if ( pRequiredAttribute == NULL )
  2855. {
  2856. *phAttribute = NULL;
  2857. return( NULL );
  2858. }
  2859. *phAttribute = pRequiredAttribute;
  2860. return( pRequiredAttribute );
  2861. }
  2862. //
  2863. // ElAuthAttributeGetNext
  2864. //
  2865. // Description:
  2866. // Helper function used to extract MPPE Key out of Attrribute.
  2867. //
  2868. RAS_AUTH_ATTRIBUTE *
  2869. ElAuthAttributeGetNext (
  2870. IN OUT HANDLE * phAttribute,
  2871. IN RAS_AUTH_ATTRIBUTE_TYPE raaType
  2872. )
  2873. {
  2874. DWORD dwIndex;
  2875. RAS_AUTH_ATTRIBUTE * pAttributes = (RAS_AUTH_ATTRIBUTE *)*phAttribute;
  2876. if ( pAttributes == NULL )
  2877. {
  2878. return( NULL );
  2879. }
  2880. pAttributes++;
  2881. while( pAttributes->raaType != raatMinimum )
  2882. {
  2883. if ( pAttributes->raaType == raaType )
  2884. {
  2885. *phAttribute = pAttributes;
  2886. return( pAttributes );
  2887. }
  2888. pAttributes++;
  2889. }
  2890. *phAttribute = NULL;
  2891. return( NULL );
  2892. }
  2893. //
  2894. // ElAuthAttributeGet
  2895. //
  2896. // Description:
  2897. // Helper function used to extract MPPE Key out of Attrribute.
  2898. //
  2899. RAS_AUTH_ATTRIBUTE *
  2900. ElAuthAttributeGet (
  2901. IN RAS_AUTH_ATTRIBUTE_TYPE raaType,
  2902. IN RAS_AUTH_ATTRIBUTE * pAttributes
  2903. )
  2904. {
  2905. DWORD dwIndex;
  2906. if ( pAttributes == NULL )
  2907. {
  2908. return( NULL );
  2909. }
  2910. for( dwIndex = 0; pAttributes[dwIndex].raaType != raatMinimum; dwIndex++ )
  2911. {
  2912. if ( pAttributes[dwIndex].raaType == raaType )
  2913. {
  2914. return( &(pAttributes[dwIndex]) );
  2915. }
  2916. }
  2917. return( NULL );
  2918. }
  2919. //
  2920. // ElReverseString
  2921. //
  2922. // Description:
  2923. // Reverses order of characters in 'psz'
  2924. //
  2925. VOID
  2926. ElReverseString (
  2927. CHAR* psz
  2928. )
  2929. {
  2930. CHAR* pszBegin;
  2931. CHAR* pszEnd;
  2932. for (pszBegin = psz, pszEnd = psz + strlen( psz ) - 1;
  2933. pszBegin < pszEnd;
  2934. ++pszBegin, --pszEnd)
  2935. {
  2936. CHAR ch = *pszBegin;
  2937. *pszBegin = *pszEnd;
  2938. *pszEnd = ch;
  2939. }
  2940. }
  2941. //
  2942. // ElEncodePw
  2943. //
  2944. // Description:
  2945. //
  2946. // Obfuscate 'pszPassword' in place to foil memory scans for passwords.
  2947. // Returns the address of 'pszPassword'.
  2948. //
  2949. CHAR*
  2950. ElEncodePw (
  2951. IN OUT CHAR* pszPassword
  2952. )
  2953. {
  2954. if (pszPassword)
  2955. {
  2956. CHAR* psz;
  2957. ElReverseString (pszPassword);
  2958. for (psz = pszPassword; *psz != '\0'; ++psz)
  2959. {
  2960. if (*psz != (CHAR)PASSWORDMAGIC)
  2961. *psz ^= PASSWORDMAGIC;
  2962. }
  2963. }
  2964. return pszPassword;
  2965. }
  2966. //
  2967. // ElDecodePw
  2968. //
  2969. // Description:
  2970. //
  2971. // Un-obfuscate 'pszPassword' in place.
  2972. // Returns the address of 'pszPassword'.
  2973. //
  2974. CHAR*
  2975. ElDecodePw (
  2976. IN OUT CHAR* pszPassword
  2977. )
  2978. {
  2979. return ElEncodePw (pszPassword);
  2980. }
  2981. //
  2982. // ElSecureEncodePw
  2983. //
  2984. // Description:
  2985. //
  2986. // Encrypt password locally using user-ACL
  2987. //
  2988. DWORD
  2989. ElSecureEncodePw (
  2990. IN BYTE *pbPassword,
  2991. IN DWORD dwSizeOfPassword,
  2992. OUT DATA_BLOB *pDataBlob
  2993. )
  2994. {
  2995. DWORD dwRetCode = NO_ERROR;
  2996. DATA_BLOB blobIn = {0}, blobOut = {0};
  2997. do
  2998. {
  2999. blobIn.cbData = dwSizeOfPassword;
  3000. blobIn.pbData = pbPassword;
  3001. if (!CryptProtectData (
  3002. &blobIn,
  3003. L"",
  3004. NULL,
  3005. NULL,
  3006. NULL,
  3007. 0,
  3008. &blobOut))
  3009. {
  3010. dwRetCode = GetLastError ();
  3011. break;
  3012. }
  3013. // copy over blob to password
  3014. if (pDataBlob->pbData != NULL)
  3015. {
  3016. FREE (pDataBlob->pbData);
  3017. pDataBlob->pbData = NULL;
  3018. pDataBlob->cbData = 0;
  3019. }
  3020. pDataBlob->pbData = MALLOC (blobOut.cbData);
  3021. if (pDataBlob->pbData == NULL)
  3022. {
  3023. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  3024. break;
  3025. }
  3026. memcpy (pDataBlob->pbData, blobOut.pbData, blobOut.cbData);
  3027. pDataBlob->cbData = blobOut.cbData;
  3028. }
  3029. while (FALSE);
  3030. if (blobOut.pbData != NULL)
  3031. {
  3032. LocalFree (blobOut.pbData);
  3033. }
  3034. if (dwRetCode != NO_ERROR)
  3035. {
  3036. if (pDataBlob->pbData != NULL)
  3037. {
  3038. FREE (pDataBlob->pbData);
  3039. pDataBlob->pbData = NULL;
  3040. pDataBlob->cbData = 0;
  3041. }
  3042. }
  3043. return dwRetCode;
  3044. }
  3045. //
  3046. // ElDecodePw
  3047. //
  3048. // Description:
  3049. //
  3050. // Decrypt password locally using user-ACL
  3051. //
  3052. DWORD
  3053. ElSecureDecodePw (
  3054. IN DATA_BLOB *pDataBlob,
  3055. OUT PBYTE *ppbPassword,
  3056. OUT DWORD *pdwSizeOfPassword
  3057. )
  3058. {
  3059. DWORD dwRetCode = NO_ERROR;
  3060. DATA_BLOB blobOut = {0};
  3061. LPWSTR pDescrOut = NULL; // NULL;
  3062. do
  3063. {
  3064. if (!CryptUnprotectData (
  3065. pDataBlob,
  3066. &pDescrOut,
  3067. NULL,
  3068. NULL,
  3069. NULL,
  3070. 0,
  3071. &blobOut))
  3072. {
  3073. dwRetCode = GetLastError ();
  3074. break;
  3075. }
  3076. // copy over blob to password
  3077. if (*ppbPassword != NULL)
  3078. {
  3079. FREE (*ppbPassword);
  3080. *ppbPassword = NULL;
  3081. }
  3082. *ppbPassword = MALLOC (blobOut.cbData);
  3083. if (*ppbPassword == NULL)
  3084. {
  3085. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  3086. break;
  3087. }
  3088. *pdwSizeOfPassword = blobOut.cbData;
  3089. memcpy ((BYTE *)*ppbPassword, blobOut.pbData, blobOut.cbData);
  3090. // TRACE1 (ANY, "SecureDecode: Password = %ws", *ppbPassword);
  3091. }
  3092. while (FALSE);
  3093. if (blobOut.pbData != NULL)
  3094. {
  3095. LocalFree (blobOut.pbData);
  3096. }
  3097. if (pDescrOut)
  3098. {
  3099. LocalFree (pDescrOut);
  3100. }
  3101. if (dwRetCode != NO_ERROR)
  3102. {
  3103. if (*ppbPassword != NULL)
  3104. {
  3105. FREE (*ppbPassword);
  3106. *ppbPassword = NULL;
  3107. }
  3108. }
  3109. return dwRetCode;
  3110. }
  3111. //
  3112. // Call: ElEncryptKeyUsingMD5
  3113. //
  3114. // Description:
  3115. // Given a secret, encrypt a given blob
  3116. //
  3117. //
  3118. //
  3119. VOID
  3120. ElEncryptBlockUsingMD5 (
  3121. IN BYTE *pbSecret,
  3122. IN ULONG ulSecretLen,
  3123. IN OUT BYTE *pbBuf,
  3124. IN ULONG ulBufLen
  3125. )
  3126. {
  3127. MD5_CTX MD5Context;
  3128. BYTE bcipherText[MD5DIGESTLEN];
  3129. BYTE *pbWork = NULL, *pbEnd = NULL;
  3130. BYTE *pbEndBlock = NULL, *pbSrc = NULL;
  3131. //
  3132. // Compute the beginning and end of the data to be crypted
  3133. //
  3134. pbWork = pbBuf;
  3135. pbEnd = pbBuf + ulBufLen;
  3136. //
  3137. // Loop through the buffer
  3138. //
  3139. while (pbWork < pbEnd)
  3140. {
  3141. // Compute the digest
  3142. MD5Init (&MD5Context);
  3143. MD5Update (&MD5Context, pbSecret, ulSecretLen);
  3144. MD5Final (&MD5Context);
  3145. // Find the end of the block to be decrypted
  3146. pbEndBlock = pbWork + MD5DIGESTLEN;
  3147. if (pbEndBlock >= pbEnd)
  3148. {
  3149. // We've reached the end of the buffer
  3150. pbEndBlock = pbEnd;
  3151. }
  3152. else
  3153. {
  3154. // ISSUE: Save the ciphertext for the next pass?
  3155. }
  3156. // Crypt the block
  3157. for (pbSrc = MD5Context.digest; pbWork < pbEndBlock; ++pbWork, ++pbSrc)
  3158. {
  3159. *pbWork ^= *pbSrc;
  3160. }
  3161. }
  3162. }
  3163. //
  3164. // ElDecryptKeyUsingMD5
  3165. //
  3166. // Description:
  3167. // Given a secret, decrypt a given blob
  3168. //
  3169. //
  3170. //
  3171. VOID
  3172. ElDecryptBlockUsingMD5 (
  3173. IN BYTE *pbSecret,
  3174. IN ULONG ulSecretLen,
  3175. IN OUT BYTE *pbBuf,
  3176. IN ULONG ulBufLen
  3177. )
  3178. {
  3179. MD5_CTX MD5Context;
  3180. BYTE bcipherText[MD5DIGESTLEN];
  3181. BYTE *pbWork = NULL, *pbEnd = NULL;
  3182. BYTE *pbEndBlock = NULL, *pbSrc = NULL;
  3183. DWORD dwNumBlocks = 0;
  3184. DWORD dwBlock = 0;
  3185. DWORD dwIndex = 0;
  3186. dwNumBlocks = ( ulBufLen - 2 ) / MD5DIGESTLEN;
  3187. //
  3188. // Walk through the blocks
  3189. //
  3190. for (dwBlock = 0; dwBlock < dwNumBlocks; dwBlock++ )
  3191. {
  3192. MD5Init ( &MD5Context);
  3193. MD5Update ( &MD5Context, (PBYTE)pbSecret, ulSecretLen);
  3194. //
  3195. // ISSUE:
  3196. // Do we use any part of the ciphertext at all to generate
  3197. // the digest
  3198. //
  3199. MD5Final ( &MD5Context);
  3200. for ( dwIndex = 0; dwIndex < MD5DIGESTLEN; dwIndex++ )
  3201. {
  3202. *pbBuf ^= MD5Context.digest[dwIndex];
  3203. pbBuf++;
  3204. }
  3205. }
  3206. }
  3207. //
  3208. // ElGetHMACMD5Digest
  3209. //
  3210. // Description:
  3211. //
  3212. // Given a secret, generate a MD5 digest
  3213. //
  3214. // Arguments:
  3215. // pbBuf - pointer to data stream
  3216. // dwBufLen - length of data stream
  3217. // pbKey - pointer to authentication key
  3218. // dwKeyLen - length of authentication key
  3219. // pvDigest - caller digest to be filled in
  3220. //
  3221. // Return values:
  3222. // None
  3223. //
  3224. VOID
  3225. ElGetHMACMD5Digest (
  3226. IN BYTE *pbBuf,
  3227. IN DWORD dwBufLen,
  3228. IN BYTE *pbKey,
  3229. IN DWORD dwKeyLen,
  3230. IN OUT VOID *pvDigest
  3231. )
  3232. {
  3233. MD5_CTX MD5context;
  3234. UCHAR k_ipad[65]; /* inner padding - key XORd with ipad */
  3235. UCHAR k_opad[65]; /* outer padding - key XORd with opad */
  3236. UCHAR tk[16];
  3237. DWORD dwIndex = 0;
  3238. // if key is longer than 64 bytes reset it to key=MD5(key)
  3239. if (dwKeyLen > 64)
  3240. {
  3241. MD5_CTX tctx;
  3242. MD5Init (&tctx);
  3243. MD5Update (&tctx, pbKey, dwKeyLen);
  3244. MD5Final (&tctx);
  3245. memcpy (tk, tctx.digest, 16);
  3246. pbKey = tk;
  3247. dwKeyLen = 16;
  3248. }
  3249. //
  3250. // the HMAC_MD5 transform looks like:
  3251. //
  3252. // MD5(K XOR opad, MD5(K XOR ipad, text))
  3253. //
  3254. // where K is an n byte key
  3255. // ipad is the byte 0x36 repeated 64 times
  3256. // opad is the byte 0x5c repeated 64 times
  3257. // and text is the data being protected
  3258. //
  3259. // start out by storing key in pads
  3260. ZeroMemory ( k_ipad, sizeof k_ipad);
  3261. ZeroMemory ( k_opad, sizeof k_opad);
  3262. memcpy ( k_ipad, pbKey, dwKeyLen);
  3263. memcpy ( k_opad, pbKey, dwKeyLen);
  3264. // XOR key with ipad and opad values
  3265. for (dwIndex=0; dwIndex<64; dwIndex++)
  3266. {
  3267. k_ipad[dwIndex] ^= 0x36;
  3268. k_opad[dwIndex] ^= 0x5c;
  3269. }
  3270. //
  3271. // perform inner MD5
  3272. //
  3273. // init context for 1st pass
  3274. MD5Init(&MD5context);
  3275. // start with inner pad
  3276. MD5Update(&MD5context, k_ipad, 64);
  3277. // then text of datagram
  3278. MD5Update(&MD5context, pbBuf, dwBufLen);
  3279. // finish up 1st pass
  3280. MD5Final(&MD5context);
  3281. memcpy (pvDigest, MD5context.digest, MD5DIGESTLEN);
  3282. //
  3283. // perform outer MD5
  3284. //
  3285. // init context for 2nd pass
  3286. MD5Init(&MD5context);
  3287. // start with outer pad
  3288. MD5Update(&MD5context, k_opad, 64);
  3289. // then results of 1st hash
  3290. MD5Update(&MD5context, pvDigest, 16);
  3291. // finish up 2nd pass
  3292. MD5Final(&MD5context);
  3293. memcpy (pvDigest, MD5context.digest, MD5DIGESTLEN);
  3294. }
  3295. //
  3296. // ElWmiGetValue
  3297. //
  3298. // Description:
  3299. //
  3300. // Get a value for a GUID instance through WMI
  3301. //
  3302. // Arguments:
  3303. // pGuid - Pointer to guid for which value is to be fetched
  3304. // pszInstanceName - Friendly name for the interface
  3305. // pbInputBuffer - Pointer to data
  3306. // dwInputBufferSize - Size of data
  3307. //
  3308. // Return values:
  3309. // NO_ERROR - success
  3310. // non-zero - error
  3311. //
  3312. DWORD
  3313. ElWmiGetValue (
  3314. IN GUID *pGuid,
  3315. IN CHAR *pszInstanceName,
  3316. IN OUT BYTE *pbOutputBuffer,
  3317. IN OUT DWORD *pdwOutputBufferSize
  3318. )
  3319. {
  3320. WMIHANDLE WmiHandle = NULL;
  3321. PWNODE_SINGLE_INSTANCE pWnode;
  3322. ULONG ulBufferSize = 0;
  3323. WCHAR *pwszInstanceName = NULL;
  3324. BYTE *pbLocalBuffer = NULL;
  3325. DWORD dwLocalBufferSize = 0;
  3326. LONG lStatus = ERROR_SUCCESS;
  3327. do
  3328. {
  3329. if ((pwszInstanceName = MALLOC ((strlen(pszInstanceName)+1) * sizeof (WCHAR))) == NULL)
  3330. {
  3331. TRACE2 (ANY, "ElWmiGetValue: MALLOC failed for pwszInstanceName, Friendlyname =%s, len= %ld",
  3332. pszInstanceName, strlen(pszInstanceName));
  3333. lStatus = ERROR_NOT_ENOUGH_MEMORY;
  3334. break;
  3335. }
  3336. if (0 == MultiByteToWideChar(
  3337. CP_ACP,
  3338. 0,
  3339. pszInstanceName,
  3340. -1,
  3341. pwszInstanceName,
  3342. strlen(pszInstanceName)+1 ) )
  3343. {
  3344. lStatus = GetLastError();
  3345. TRACE2 (ANY, "ElWmiGetValue: MultiByteToWideChar(%s) failed: %ld",
  3346. pszInstanceName, lStatus);
  3347. break;
  3348. }
  3349. pwszInstanceName[strlen(pszInstanceName)] = L'\0';
  3350. TRACE1 (ANY, "ElWmiGetValue: MultiByteToWideChar succeeded: %ws",
  3351. pwszInstanceName);
  3352. if ((lStatus = WmiOpenBlock (pGuid, 0, &WmiHandle)) != ERROR_SUCCESS)
  3353. {
  3354. TRACE1 (ANY, "ElWmiGetValue: WmiOpenBlock failed with error %ld",
  3355. lStatus);
  3356. break;
  3357. }
  3358. if ((lStatus = WmiQuerySingleInstance (WmiHandle,
  3359. pwszInstanceName,
  3360. &dwLocalBufferSize,
  3361. NULL)) != ERROR_SUCCESS)
  3362. {
  3363. if (lStatus == ERROR_INSUFFICIENT_BUFFER)
  3364. {
  3365. TRACE1 (ANY, "ElWmiGetValue: Size Required = %ld",
  3366. dwLocalBufferSize);
  3367. if ((pbLocalBuffer = MALLOC (dwLocalBufferSize)) == NULL)
  3368. {
  3369. TRACE0 (ANY, "ElWmiGetValue: MALLOC failed for pbLocalBuffer");
  3370. lStatus = ERROR_NOT_ENOUGH_MEMORY;
  3371. break;
  3372. }
  3373. if ((lStatus = WmiQuerySingleInstance (WmiHandle,
  3374. pwszInstanceName,
  3375. &dwLocalBufferSize,
  3376. pbLocalBuffer))
  3377. != ERROR_SUCCESS)
  3378. {
  3379. TRACE1 (ANY, "ElWmiGetValue: WmiQuerySingleInstance failed with error %ld",
  3380. lStatus);
  3381. break;
  3382. }
  3383. pWnode = (PWNODE_SINGLE_INSTANCE)pbLocalBuffer;
  3384. // If enough space in the output buffer, copy the data block
  3385. if (*pdwOutputBufferSize >= pWnode->SizeDataBlock)
  3386. {
  3387. memcpy (pbOutputBuffer,
  3388. (PBYTE)((BYTE *)pWnode + pWnode->DataBlockOffset),
  3389. pWnode->SizeDataBlock
  3390. );
  3391. }
  3392. else
  3393. {
  3394. lStatus = ERROR_INSUFFICIENT_BUFFER;
  3395. TRACE0 (ANY, "ElWmiGetValue: Not sufficient space to copy DataBlock");
  3396. *pdwOutputBufferSize = pWnode->SizeDataBlock;
  3397. break;
  3398. }
  3399. *pdwOutputBufferSize = pWnode->SizeDataBlock;
  3400. TRACE0 (ANY, "ElWmiGetValue: Got values from Wmi");
  3401. TRACE1 (ANY, "SizeofDataBlock = %ld", pWnode->SizeDataBlock);
  3402. EAPOL_DUMPBA (pbOutputBuffer, *pdwOutputBufferSize);
  3403. }
  3404. else
  3405. {
  3406. TRACE1 (ANY, "ElWmiGetValue: WmiQuerySingleInstance failed with error %ld",
  3407. lStatus);
  3408. break;
  3409. }
  3410. }
  3411. } while (FALSE);
  3412. if (WmiHandle != NULL)
  3413. {
  3414. if ((lStatus = WmiCloseBlock (WmiHandle)) != ERROR_SUCCESS)
  3415. {
  3416. TRACE1 (ANY, "ElWmiGetValue: WmiOpenBlock failed with error %ld",
  3417. lStatus);
  3418. }
  3419. }
  3420. if (pbLocalBuffer != NULL)
  3421. {
  3422. FREE (pbLocalBuffer);
  3423. }
  3424. if (pwszInstanceName != NULL)
  3425. {
  3426. FREE (pwszInstanceName);
  3427. }
  3428. return (DWORD)lStatus;
  3429. }
  3430. //
  3431. // ElWmiSetValue
  3432. //
  3433. // Description:
  3434. //
  3435. // Set a value for a GUID instance through WMI
  3436. //
  3437. // Arguments:
  3438. // pGuid - Pointer to guid for which value is to be set
  3439. // pszInstanceName - Friendly name for the interface
  3440. // pbInputBuffer - Pointer to data
  3441. // dwInputBufferSize - Size of data
  3442. //
  3443. // Return values:
  3444. // NO_ERROR - success
  3445. // non-zero - error
  3446. //
  3447. DWORD
  3448. ElWmiSetValue (
  3449. IN GUID *pGuid,
  3450. IN CHAR *pszInstanceName,
  3451. IN BYTE *pbInputBuffer,
  3452. IN DWORD dwInputBufferSize
  3453. )
  3454. {
  3455. WMIHANDLE WmiHandle = NULL;
  3456. PWNODE_SINGLE_INSTANCE pWnode;
  3457. ULONG ulBufferSize = 0;
  3458. WCHAR *pwszInstanceName = NULL;
  3459. BYTE bBuffer[4096];
  3460. LONG lStatus = ERROR_SUCCESS;
  3461. do
  3462. {
  3463. if ((pwszInstanceName = MALLOC ((strlen(pszInstanceName)+1) * sizeof (WCHAR))) == NULL)
  3464. {
  3465. TRACE0 (ANY, "ElWmiSetValue: MALLOC failed for pwszInstanceName");
  3466. lStatus = ERROR_NOT_ENOUGH_MEMORY;
  3467. break;
  3468. }
  3469. if (0 == MultiByteToWideChar(
  3470. CP_ACP,
  3471. 0,
  3472. pszInstanceName,
  3473. -1,
  3474. pwszInstanceName,
  3475. strlen(pszInstanceName)+1 ) )
  3476. {
  3477. lStatus = GetLastError();
  3478. TRACE2 (ANY, "ElWmiSetValue: MultiByteToWideChar(%s) failed: %d",
  3479. pszInstanceName,
  3480. lStatus);
  3481. break;
  3482. }
  3483. pwszInstanceName[strlen(pszInstanceName)] = L'\0';
  3484. if ((lStatus = WmiOpenBlock (pGuid, 0, &WmiHandle)) != ERROR_SUCCESS)
  3485. {
  3486. TRACE1 (ANY, "ElWmiSetValue: WmiOpenBlock failed with error %ld",
  3487. lStatus);
  3488. break;
  3489. }
  3490. if ((lStatus = WmiSetSingleInstance (WmiHandle,
  3491. pwszInstanceName,
  3492. 1,
  3493. dwInputBufferSize,
  3494. pbInputBuffer))
  3495. != ERROR_SUCCESS)
  3496. {
  3497. TRACE1 (ANY, "ElWmiSetValue: WmiSetSingleInstance failed with error %ld",
  3498. lStatus);
  3499. break;
  3500. }
  3501. TRACE0 (ANY, "ElWmiSetValue: Successful !!!");
  3502. } while (FALSE);
  3503. if (WmiHandle != NULL)
  3504. {
  3505. if ((lStatus = WmiCloseBlock (WmiHandle)) != ERROR_SUCCESS)
  3506. {
  3507. TRACE1 (ANY, "ElWmiSetValue: WmiOpenBlock failed with error %ld",
  3508. lStatus);
  3509. }
  3510. }
  3511. if (pwszInstanceName != NULL)
  3512. {
  3513. FREE (pwszInstanceName);
  3514. }
  3515. return (DWORD)lStatus;
  3516. }
  3517. //
  3518. // ElNdisuioSetOIDValue
  3519. //
  3520. // Description:
  3521. //
  3522. // Set a value for an OID for an interface using Ndisuio
  3523. //
  3524. // Arguments:
  3525. // hInterface - Ndisuio handle to interface
  3526. // Oid - Oid for which value needs to be set
  3527. // pbOidData - Pointer to Oid data
  3528. // ulOidDataLength - Oid data length
  3529. //
  3530. // Return values:
  3531. // NO_ERROR - success
  3532. // non-zero - error
  3533. //
  3534. DWORD
  3535. ElNdisuioSetOIDValue (
  3536. IN HANDLE hInterface,
  3537. IN NDIS_OID Oid,
  3538. IN BYTE *pbOidData,
  3539. IN ULONG ulOidDataLength
  3540. )
  3541. {
  3542. PNDISUIO_SET_OID pSetOid = NULL;
  3543. DWORD BytesReturned = 0;
  3544. BOOLEAN fSuccess = TRUE;
  3545. DWORD dwRetCode = NO_ERROR;
  3546. do
  3547. {
  3548. pSetOid = (PNDISUIO_SET_OID) MALLOC (ulOidDataLength + sizeof(NDISUIO_SET_OID));
  3549. if (pSetOid == NULL)
  3550. {
  3551. TRACE0 (ANY, "ElNdisuioSetOIDValue: MALLOC failed for pSetOid");
  3552. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  3553. break;
  3554. }
  3555. pSetOid->Oid = Oid;
  3556. memcpy(&pSetOid->Data[0], pbOidData, ulOidDataLength);
  3557. fSuccess = (BOOLEAN) DeviceIoControl (
  3558. hInterface,
  3559. IOCTL_NDISUIO_SET_OID_VALUE,
  3560. (LPVOID)pSetOid,
  3561. FIELD_OFFSET(NDISUIO_SET_OID, Data) + ulOidDataLength,
  3562. (LPVOID)pSetOid,
  3563. 0,
  3564. &BytesReturned,
  3565. NULL);
  3566. if (!fSuccess)
  3567. {
  3568. TRACE1 (ANY, "ElNdisuioSetOIDValue: DeviceIoControl failed with error %ld",
  3569. (dwRetCode = GetLastError()));
  3570. break;
  3571. }
  3572. else
  3573. {
  3574. TRACE0 (ANY, "ElNdisuioSetOIDValue: DeviceIoControl succeeded");
  3575. }
  3576. }
  3577. while (FALSE);
  3578. if (pSetOid != NULL)
  3579. {
  3580. FREE (pSetOid);
  3581. }
  3582. return dwRetCode;
  3583. }
  3584. //
  3585. // ElNdisuioQueryOIDValue
  3586. //
  3587. // Description:
  3588. //
  3589. // Query the value for an OID for an interface using Ndisuio
  3590. //
  3591. // Arguments:
  3592. // hInterface - Ndisuio handle to interface
  3593. // Oid - Oid for which value needs to be set
  3594. // pbOidValue - Pointer to Oid value
  3595. // pulOidDataLength - Pointer to Oid data length
  3596. //
  3597. // Return values:
  3598. // NO_ERROR - success
  3599. // non-zero - error
  3600. //
  3601. DWORD
  3602. ElNdisuioQueryOIDValue (
  3603. IN HANDLE hInterface,
  3604. IN NDIS_OID Oid,
  3605. IN BYTE *pbOidData,
  3606. IN ULONG *pulOidDataLength
  3607. )
  3608. {
  3609. PNDISUIO_QUERY_OID pQueryOid = NULL;
  3610. DWORD BytesReturned = 0;
  3611. BOOLEAN fSuccess = TRUE;
  3612. DWORD dwRetCode = NO_ERROR;
  3613. do
  3614. {
  3615. pQueryOid = (PNDISUIO_QUERY_OID) MALLOC (*pulOidDataLength + sizeof(NDISUIO_QUERY_OID));
  3616. if (pQueryOid == NULL)
  3617. {
  3618. TRACE0 (ANY, "ElNdisuioQueryOIDValue: MALLOC failed for pQueryOid");
  3619. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  3620. break;
  3621. }
  3622. pQueryOid->Oid = Oid;
  3623. fSuccess = (BOOLEAN) DeviceIoControl (
  3624. hInterface,
  3625. IOCTL_NDISUIO_QUERY_OID_VALUE,
  3626. (LPVOID)pQueryOid,
  3627. FIELD_OFFSET(NDISUIO_QUERY_OID, Data) + *pulOidDataLength,
  3628. (LPVOID)pQueryOid,
  3629. FIELD_OFFSET(NDISUIO_QUERY_OID, Data) + *pulOidDataLength,
  3630. &BytesReturned,
  3631. NULL);
  3632. if (!fSuccess)
  3633. {
  3634. dwRetCode = GetLastError();
  3635. TRACE2 (ANY, "ElNdisuioQueryOIDValue: DeviceIoControl failed with error %ld, BytesReturned = %ld",
  3636. dwRetCode, BytesReturned);
  3637. *pulOidDataLength = BytesReturned;
  3638. break;
  3639. }
  3640. else
  3641. {
  3642. BytesReturned -= FIELD_OFFSET(NDISUIO_QUERY_OID, Data);
  3643. if (BytesReturned > *pulOidDataLength)
  3644. {
  3645. BytesReturned = *pulOidDataLength;
  3646. }
  3647. else
  3648. {
  3649. *pulOidDataLength = BytesReturned;
  3650. }
  3651. memcpy(pbOidData, &pQueryOid->Data[0], BytesReturned);
  3652. }
  3653. }
  3654. while (FALSE);
  3655. if (pQueryOid != NULL)
  3656. {
  3657. FREE (pQueryOid);
  3658. }
  3659. return dwRetCode;
  3660. }
  3661. //
  3662. // ElGuidFromString
  3663. //
  3664. // Description:
  3665. //
  3666. // Convert a GUID-string to GUID
  3667. //
  3668. // Arguments:
  3669. // pGuid - pointer to GUID
  3670. // pwszGuidString - pointer to string version of GUID
  3671. //
  3672. // Return values:
  3673. // NO_ERROR - success
  3674. // non-zero - error
  3675. //
  3676. DWORD
  3677. ElGuidFromString (
  3678. IN OUT GUID *pGuid,
  3679. IN WCHAR *pwszGuidString
  3680. )
  3681. {
  3682. DWORD dwGuidLen = 0;
  3683. WCHAR wszGuidString[64];
  3684. LPWSTR lpwszWithBraces = NULL;
  3685. HRESULT hr = S_OK;
  3686. DWORD dwRetCode = NO_ERROR;
  3687. do
  3688. {
  3689. if (pwszGuidString == NULL)
  3690. {
  3691. break;
  3692. }
  3693. ZeroMemory (pGuid, sizeof(GUID));
  3694. if ((hr = CLSIDFromString (pwszGuidString, pGuid)) != NOERROR)
  3695. {
  3696. TRACE1 (ANY, "ElGuidFromString: CLSIDFromString failed with error %0lx",
  3697. hr);
  3698. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  3699. }
  3700. } while (FALSE);
  3701. return dwRetCode;
  3702. }
  3703. //
  3704. // ElGetLoggedOnUserName
  3705. //
  3706. // Description:
  3707. //
  3708. // Get the Username and Domain of the currently logged in user
  3709. //
  3710. // Arguments:
  3711. // hToken - User token
  3712. //
  3713. // Return values:
  3714. // NO_ERROR - success
  3715. // non-zero - error
  3716. //
  3717. //
  3718. DWORD
  3719. ElGetLoggedOnUserName (
  3720. IN HANDLE hToken,
  3721. OUT PWCHAR *ppwszActiveUserName
  3722. )
  3723. {
  3724. HANDLE hUserToken;
  3725. WCHAR *pwszUserNameBuffer = NULL;
  3726. DWORD dwBufferSize = 0;
  3727. BOOL fNeedToRevertToSelf = FALSE;
  3728. DWORD dwRetCode = NO_ERROR;
  3729. do
  3730. {
  3731. hUserToken = hToken;
  3732. if (hUserToken != NULL)
  3733. {
  3734. if (!ImpersonateLoggedOnUser (hUserToken))
  3735. {
  3736. dwRetCode = GetLastError();
  3737. TRACE1 (USER, "ElGetLoggedOnUserName: ImpersonateLoggedOnUser failed with error %ld",
  3738. dwRetCode);
  3739. break;
  3740. }
  3741. fNeedToRevertToSelf = TRUE;
  3742. dwBufferSize = 0;
  3743. if (!GetUserNameEx (NameSamCompatible,
  3744. NULL,
  3745. &dwBufferSize))
  3746. {
  3747. dwRetCode = GetLastError ();
  3748. if (dwRetCode == ERROR_MORE_DATA)
  3749. {
  3750. dwRetCode = NO_ERROR;
  3751. if ((pwszUserNameBuffer = MALLOC (dwBufferSize*sizeof(WCHAR))) == NULL)
  3752. {
  3753. TRACE0 (ANY, "ElGetLoggedOnUserName: MALLOC failed for pwszUserNameBuffer");
  3754. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  3755. break;
  3756. }
  3757. if (!GetUserNameEx (NameSamCompatible,
  3758. pwszUserNameBuffer,
  3759. &dwBufferSize))
  3760. {
  3761. dwRetCode = GetLastError ();
  3762. TRACE1 (ANY, "ElGetLoggedOnUserName: GetUserNameEx failed with error %ld",
  3763. dwRetCode);
  3764. break;
  3765. }
  3766. TRACE1 (ANY, "ElGetLoggedOnUserName: Got User Name %ws",
  3767. pwszUserNameBuffer);
  3768. }
  3769. else
  3770. {
  3771. TRACE1 (ANY, "ElGetLoggedOnUserName: GetUserNameEx failed with error %ld",
  3772. dwRetCode);
  3773. break;
  3774. }
  3775. }
  3776. }
  3777. else
  3778. {
  3779. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  3780. TRACE0 (ANY, "ElGetLoggedOnUserName: UserToken is NULL");
  3781. break;
  3782. }
  3783. } while (FALSE);
  3784. if (pwszUserNameBuffer != NULL)
  3785. {
  3786. *ppwszActiveUserName = pwszUserNameBuffer;
  3787. }
  3788. // Revert impersonation
  3789. if (fNeedToRevertToSelf)
  3790. {
  3791. if (!RevertToSelf())
  3792. {
  3793. DWORD dwRetCode1 = NO_ERROR;
  3794. dwRetCode1 = GetLastError();
  3795. TRACE1 (USER, "ElGetLoggedOnUserName: Error in RevertToSelf = %ld",
  3796. dwRetCode1);
  3797. dwRetCode = ERROR_BAD_IMPERSONATION_LEVEL;
  3798. }
  3799. }
  3800. return dwRetCode;
  3801. }
  3802. //
  3803. // ElGetMachineName
  3804. //
  3805. // Description:
  3806. //
  3807. // Get the machine name of the computer the service is currently running on
  3808. //
  3809. // Arguments:
  3810. // pPCB - Pointer to PCB for the port on which machine name is to
  3811. // to be obtained
  3812. //
  3813. // Return values:
  3814. // NO_ERROR - success
  3815. // non-zero - error
  3816. //
  3817. //
  3818. DWORD
  3819. ElGetMachineName (
  3820. IN EAPOL_PCB *pPCB
  3821. )
  3822. {
  3823. WCHAR *pwszComputerNameBuffer = NULL;
  3824. CHAR *pszComputerNameBuffer = NULL;
  3825. WCHAR *pwszComputerDomainBuffer = NULL;
  3826. CHAR *pszComputerDomainBuffer = NULL;
  3827. DWORD dwBufferSize = 0;
  3828. DWORD dwRetCode = NO_ERROR;
  3829. do
  3830. {
  3831. dwBufferSize = 0;
  3832. if (!GetComputerNameEx (ComputerNamePhysicalNetBIOS,
  3833. NULL,
  3834. &dwBufferSize))
  3835. {
  3836. dwRetCode = GetLastError ();
  3837. if (dwRetCode == ERROR_MORE_DATA)
  3838. {
  3839. // Reset error
  3840. dwRetCode = NO_ERROR;
  3841. if ((pwszComputerNameBuffer = MALLOC (dwBufferSize*sizeof(WCHAR))) == NULL)
  3842. {
  3843. TRACE0 (ANY, "ElGetMachineName: MALLOC failed for pwszComputerNameBuffer");
  3844. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  3845. break;
  3846. }
  3847. if (!GetComputerNameEx (ComputerNamePhysicalNetBIOS,
  3848. pwszComputerNameBuffer,
  3849. &dwBufferSize))
  3850. {
  3851. dwRetCode = GetLastError ();
  3852. TRACE1 (ANY, "ElGetMachineName: GetComputerNameEx failed with error %ld",
  3853. dwRetCode);
  3854. break;
  3855. }
  3856. TRACE1 (ANY, "ElGetMachineName: Got Computer Name %ws",
  3857. pwszComputerNameBuffer);
  3858. pszComputerNameBuffer =
  3859. MALLOC (wcslen(pwszComputerNameBuffer) + 1);
  3860. if (pszComputerNameBuffer == NULL)
  3861. {
  3862. TRACE0 (ANY, "ElGetMachineName: MALLOC failed for pszComputerNameBuffer");
  3863. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  3864. break;
  3865. }
  3866. if (0 == WideCharToMultiByte (
  3867. CP_ACP,
  3868. 0,
  3869. pwszComputerNameBuffer,
  3870. -1,
  3871. pszComputerNameBuffer,
  3872. wcslen(pwszComputerNameBuffer)+1,
  3873. NULL,
  3874. NULL ))
  3875. {
  3876. dwRetCode = GetLastError();
  3877. TRACE2 (ANY, "ElGetMachineName: WideCharToMultiByte (%ws) failed: %ld",
  3878. pwszComputerNameBuffer, dwRetCode);
  3879. break;
  3880. }
  3881. pszComputerNameBuffer[wcslen(pwszComputerNameBuffer)] = L'\0';
  3882. }
  3883. else
  3884. {
  3885. TRACE1 (ANY, "ElGetMachineName: GetComputerNameEx failed with error %ld",
  3886. dwRetCode);
  3887. break;
  3888. }
  3889. }
  3890. dwBufferSize = 0;
  3891. if (!GetComputerNameEx (ComputerNamePhysicalDnsDomain,
  3892. NULL,
  3893. &dwBufferSize))
  3894. {
  3895. dwRetCode = GetLastError ();
  3896. if (dwRetCode == ERROR_MORE_DATA)
  3897. {
  3898. // Reset error
  3899. dwRetCode = NO_ERROR;
  3900. if ((pwszComputerDomainBuffer = MALLOC (dwBufferSize*sizeof(WCHAR))) == NULL)
  3901. {
  3902. TRACE0 (ANY, "ElGetMachineName: MALLOC failed for pwszComputerDomainBuffer");
  3903. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  3904. break;
  3905. }
  3906. if (!GetComputerNameEx (ComputerNamePhysicalDnsDomain,
  3907. pwszComputerDomainBuffer,
  3908. &dwBufferSize))
  3909. {
  3910. dwRetCode = GetLastError ();
  3911. TRACE1 (ANY, "ElGetMachineName: GetComputerNameEx Domain failed with error %ld",
  3912. dwRetCode);
  3913. break;
  3914. }
  3915. TRACE1 (ANY, "ElGetMachineName: Got Computer Domain %ws",
  3916. pwszComputerDomainBuffer);
  3917. pszComputerDomainBuffer =
  3918. MALLOC (wcslen(pwszComputerDomainBuffer) + 1);
  3919. if (pszComputerDomainBuffer == NULL)
  3920. {
  3921. TRACE0 (ANY, "ElGetMachineName: MALLOC failed for pszComputerDomainBuffer");
  3922. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  3923. break;
  3924. }
  3925. if (0 == WideCharToMultiByte (
  3926. CP_ACP,
  3927. 0,
  3928. pwszComputerDomainBuffer,
  3929. -1,
  3930. pszComputerDomainBuffer,
  3931. wcslen(pwszComputerDomainBuffer)+1,
  3932. NULL,
  3933. NULL ))
  3934. {
  3935. dwRetCode = GetLastError();
  3936. TRACE2 (ANY, "ElGetMachineName: WideCharToMultiByte (%ws) failed: %ld",
  3937. pwszComputerDomainBuffer, dwRetCode);
  3938. break;
  3939. }
  3940. pszComputerDomainBuffer[wcslen(pwszComputerDomainBuffer)] = L'\0';
  3941. *(strrchr (pszComputerDomainBuffer, '.')) = '\0';
  3942. if (pPCB->pszIdentity != NULL)
  3943. {
  3944. FREE (pPCB->pszIdentity);
  3945. pPCB->pszIdentity = NULL;
  3946. }
  3947. pPCB->pszIdentity = MALLOC (strlen(pszComputerDomainBuffer) +
  3948. strlen(pszComputerNameBuffer) + 3);
  3949. if (pPCB->pszIdentity == NULL)
  3950. {
  3951. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  3952. TRACE0 (ANY, "ElGetMachineName: MALLOC failed for pPCB->pszIdentity");
  3953. break;
  3954. }
  3955. memcpy (pPCB->pszIdentity,
  3956. pszComputerDomainBuffer,
  3957. strlen(pszComputerDomainBuffer));
  3958. pPCB->pszIdentity[strlen(pszComputerDomainBuffer)] = '\\';
  3959. memcpy (&pPCB->pszIdentity[strlen(pszComputerDomainBuffer)+1],
  3960. pszComputerNameBuffer,
  3961. strlen(pszComputerNameBuffer));
  3962. pPCB->pszIdentity[strlen(pszComputerDomainBuffer)+1+strlen(pszComputerNameBuffer)] = '$';
  3963. pPCB->pszIdentity[strlen(pszComputerDomainBuffer)+1+strlen(pszComputerNameBuffer)+1] = '\0';
  3964. }
  3965. else
  3966. {
  3967. TRACE1 (ANY, "ElGetMachineName: GetComputerNameEx failed with error %ld",
  3968. dwRetCode);
  3969. break;
  3970. }
  3971. }
  3972. } while (FALSE);
  3973. if (pwszComputerNameBuffer != NULL)
  3974. {
  3975. FREE (pwszComputerNameBuffer);
  3976. }
  3977. if (pszComputerNameBuffer != NULL)
  3978. {
  3979. FREE (pszComputerNameBuffer);
  3980. }
  3981. if (pwszComputerDomainBuffer != NULL)
  3982. {
  3983. FREE (pwszComputerDomainBuffer);
  3984. }
  3985. if (pszComputerDomainBuffer != NULL)
  3986. {
  3987. FREE (pszComputerDomainBuffer);
  3988. }
  3989. return dwRetCode;
  3990. }
  3991. //
  3992. // ElUpdateRegistryInterfaceList
  3993. //
  3994. // Description:
  3995. //
  3996. // Write the interface list to which NDISUIO is bound to, to the registry
  3997. //
  3998. // Arguments:
  3999. // Interfaces - Interface list containing Device Name and Description
  4000. //
  4001. // Return values:
  4002. // NO_ERROR - success
  4003. // non-zero - error
  4004. //
  4005. //
  4006. DWORD
  4007. ElUpdateRegistryInterfaceList (
  4008. IN PNDIS_ENUM_INTF Interfaces
  4009. )
  4010. {
  4011. WCHAR *pwszRegInterfaceList = NULL;
  4012. HKEY hkey = NULL;
  4013. DWORD dwDisposition = 0;
  4014. LONG lError = ERROR_SUCCESS;
  4015. DWORD dwRetCode = NO_ERROR;
  4016. do
  4017. {
  4018. ANSI_STRING InterfaceName;
  4019. UCHAR ucBuffer[256];
  4020. DWORD i;
  4021. DWORD dwSizeOfList = 0;
  4022. // Determine the number of bytes in the list
  4023. for (i=0; i < Interfaces->TotalInterfaces; i++)
  4024. {
  4025. if (Interfaces->Interface[i].DeviceName.Buffer != NULL)
  4026. {
  4027. dwSizeOfList += wcslen(Interfaces->Interface[i].DeviceName.Buffer);
  4028. }
  4029. else
  4030. {
  4031. TRACE0 (ANY, "ElUpdateRegistryInterfaceList: Device Name was NULL");
  4032. continue;
  4033. }
  4034. }
  4035. // One extra char for terminating NULL char
  4036. pwszRegInterfaceList =
  4037. (WCHAR *) MALLOC ((dwSizeOfList + 1)*sizeof(WCHAR));
  4038. if ( pwszRegInterfaceList == NULL )
  4039. {
  4040. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  4041. TRACE0 (ANY, "ElUpdateRegistryInterfaceList: MALLOC failed for pwszRegInterfaceList");
  4042. break;
  4043. }
  4044. // Start again
  4045. dwSizeOfList = 0;
  4046. // Create the string in REG_SZ format
  4047. for (i=0; i < Interfaces->TotalInterfaces; i++)
  4048. {
  4049. if (Interfaces->Interface[i].DeviceName.Buffer != NULL)
  4050. {
  4051. wcscat (pwszRegInterfaceList,
  4052. Interfaces->Interface[i].DeviceName.Buffer);
  4053. dwSizeOfList +=
  4054. (wcslen(Interfaces->Interface[i].DeviceName.Buffer));
  4055. }
  4056. else
  4057. {
  4058. TRACE0 (ANY, "ElUpdateRegistryInterfaceList: Device Name was NULL");
  4059. continue;
  4060. }
  4061. }
  4062. // Final NULL character
  4063. pwszRegInterfaceList[dwSizeOfList++] = L'\0';
  4064. // Write the string as a REG_SZ value
  4065. // Get handle to
  4066. // HKLM\Software\Microsoft\EAPOL\Parameters\General
  4067. if ((lError = RegCreateKeyEx (
  4068. HKEY_LOCAL_MACHINE,
  4069. cwszEapKeyEapolServiceParams,
  4070. 0,
  4071. NULL,
  4072. REG_OPTION_NON_VOLATILE,
  4073. KEY_WRITE,
  4074. NULL,
  4075. &hkey,
  4076. &dwDisposition)) != ERROR_SUCCESS)
  4077. {
  4078. TRACE1 (ANY, "ElUpdateRegistryInterfaceList: Error in RegCreateKeyEx for base key, %ld",
  4079. lError);
  4080. dwRetCode = (DWORD)lError;
  4081. break;
  4082. }
  4083. //
  4084. // Set the value of
  4085. // ...\EAPOL\Parameters\General\InterfaceList key
  4086. //
  4087. if ((lError = RegSetValueEx (
  4088. hkey,
  4089. cwszInterfaceList,
  4090. 0,
  4091. REG_SZ,
  4092. (BYTE *)pwszRegInterfaceList,
  4093. dwSizeOfList*sizeof(WCHAR)))
  4094. != ERROR_SUCCESS)
  4095. {
  4096. TRACE1 (ANY, "ElUpdateRegistryInterfaceList: Error in RegSetValueEx for InterfaceList, %ld",
  4097. lError);
  4098. dwRetCode = (DWORD)lError;
  4099. break;
  4100. }
  4101. } while (FALSE);
  4102. if (hkey != NULL)
  4103. {
  4104. RegCloseKey (hkey);
  4105. }
  4106. if (pwszRegInterfaceList != NULL)
  4107. {
  4108. FREE (pwszRegInterfaceList);
  4109. }
  4110. return dwRetCode;
  4111. }
  4112. //
  4113. // ElEnumAndUpdateRegistryInterfaceList
  4114. //
  4115. // Description:
  4116. //
  4117. // Enumerate the interface list to which NDISUIO is bound to.
  4118. // Write the interface list to the registry
  4119. //
  4120. // Arguments:
  4121. // None
  4122. //
  4123. // Return values:
  4124. // NO_ERROR - success
  4125. // non-zero - error
  4126. //
  4127. //
  4128. DWORD
  4129. ElEnumAndUpdateRegistryInterfaceList (
  4130. )
  4131. {
  4132. CHAR EnumerateBuffer[256];
  4133. PNDIS_ENUM_INTF Interfaces = NULL;
  4134. BYTE *pbNdisuioEnumBuffer = NULL;
  4135. DWORD dwNdisuioEnumBufferSize = 0;
  4136. DWORD dwAvailableInterfaces = 0;
  4137. WCHAR *pwszRegInterfaceList = NULL;
  4138. HKEY hkey = NULL;
  4139. DWORD dwDisposition = 0;
  4140. ANSI_STRING InterfaceName;
  4141. UCHAR ucBuffer[256];
  4142. DWORD i;
  4143. DWORD dwSizeOfList = 0;
  4144. LONG lError = ERROR_SUCCESS;
  4145. DWORD dwRetCode = NO_ERROR;
  4146. do
  4147. {
  4148. ZeroMemory (EnumerateBuffer, 256);
  4149. Interfaces = (PNDIS_ENUM_INTF)EnumerateBuffer;
  4150. // Allocate amount of memory as instructed by NdisEnumerateInterfaces
  4151. // once the API allows querying of bytes required
  4152. if (!NdisEnumerateInterfaces(Interfaces, 256))
  4153. {
  4154. dwRetCode = GetLastError ();
  4155. TRACE1 (ANY, "ElEnumAndUpdateRegistryInterfaceList: NdisEnumerateInterfaces failed with error %ld",
  4156. dwRetCode);
  4157. break;
  4158. }
  4159. dwNdisuioEnumBufferSize = (Interfaces->BytesNeeded + 7) & 0xfffffff8;
  4160. dwAvailableInterfaces = Interfaces->AvailableInterfaces;
  4161. if (dwNdisuioEnumBufferSize == 0)
  4162. {
  4163. TRACE0 (ANY, "ElEnumAndUpdateRegistryInterfaceList: MALLOC skipped for pbNdisuioEnumBuffer as dwNdisuioEnumBufferSize == 0");
  4164. dwRetCode = NO_ERROR;
  4165. break;
  4166. }
  4167. pbNdisuioEnumBuffer = (BYTE *) MALLOC (4*dwNdisuioEnumBufferSize);
  4168. if (pbNdisuioEnumBuffer == NULL)
  4169. {
  4170. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  4171. TRACE0 (ANY, "ElEnumAndUpdateRegistryInterfaceList: MALLOC failed for pbNdisuioEnumBuffer");
  4172. break;
  4173. }
  4174. Interfaces = (PNDIS_ENUM_INTF)pbNdisuioEnumBuffer;
  4175. // Enumerate all the interfaces present on the machine
  4176. if ((dwRetCode = ElNdisuioEnumerateInterfaces (
  4177. Interfaces,
  4178. dwAvailableInterfaces,
  4179. 4*dwNdisuioEnumBufferSize)) != NO_ERROR)
  4180. {
  4181. TRACE1(ANY, "ElEnumAndUpdateRegistryInterfaceList: ElNdisuioEnumerateInterfaces failed with error %d",
  4182. dwRetCode);
  4183. break;
  4184. }
  4185. // Update the interface list in the registry that NDISUIO has bound to.
  4186. // The current interface list is just overwritten into the registry.
  4187. // Determine the number of bytes in the list
  4188. for (i=0; i < Interfaces->TotalInterfaces; i++)
  4189. {
  4190. if (Interfaces->Interface[i].DeviceName.Buffer != NULL)
  4191. {
  4192. dwSizeOfList += wcslen(Interfaces->Interface[i].DeviceName.Buffer);
  4193. }
  4194. else
  4195. {
  4196. TRACE0 (ANY, "ElEnumAndUpdateRegistryInterfaceList: Device Name was NULL");
  4197. continue;
  4198. }
  4199. }
  4200. // One extra char for terminating NULL char
  4201. pwszRegInterfaceList =
  4202. (WCHAR *) MALLOC ((dwSizeOfList + 1)*sizeof(WCHAR));
  4203. if ( pwszRegInterfaceList == NULL )
  4204. {
  4205. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  4206. TRACE0 (ANY, "ElEnumAndUpdateRegistryInterfaceList: MALLOC failed for pwszRegInterfaceList");
  4207. break;
  4208. }
  4209. // Start again
  4210. dwSizeOfList = 0;
  4211. // Create the string in REG_SZ format
  4212. for (i=0; i < Interfaces->TotalInterfaces; i++)
  4213. {
  4214. if (Interfaces->Interface[i].DeviceName.Buffer != NULL)
  4215. {
  4216. wcscat (pwszRegInterfaceList,
  4217. Interfaces->Interface[i].DeviceName.Buffer);
  4218. dwSizeOfList +=
  4219. (wcslen(Interfaces->Interface[i].DeviceName.Buffer));
  4220. }
  4221. else
  4222. {
  4223. TRACE0 (ANY, "ElEnumAndUpdateRegistryInterfaceList: Device Name was NULL");
  4224. continue;
  4225. }
  4226. }
  4227. // Final NULL character
  4228. pwszRegInterfaceList[dwSizeOfList++] = L'\0';
  4229. // Write the string as a REG_SZ value
  4230. // Get handle to
  4231. // HKLM\Software\Microsoft\EAPOL\Parameters\General
  4232. if ((lError = RegCreateKeyEx (
  4233. HKEY_LOCAL_MACHINE,
  4234. cwszEapKeyEapolServiceParams,
  4235. 0,
  4236. NULL,
  4237. REG_OPTION_NON_VOLATILE,
  4238. KEY_WRITE,
  4239. NULL,
  4240. &hkey,
  4241. &dwDisposition)) != ERROR_SUCCESS)
  4242. {
  4243. TRACE1 (ANY, "ElEnumAndUpdateRegistryInterfaceList: Error in RegCreateKeyEx for base key, %ld",
  4244. lError);
  4245. dwRetCode = (DWORD)lError;
  4246. break;
  4247. }
  4248. //
  4249. // Set the value of
  4250. // ...\EAPOL\Parameters\General\InterfaceList key
  4251. //
  4252. if ((lError = RegSetValueEx (
  4253. hkey,
  4254. cwszInterfaceList,
  4255. 0,
  4256. REG_SZ,
  4257. (BYTE *)pwszRegInterfaceList,
  4258. dwSizeOfList*sizeof(WCHAR)))
  4259. != ERROR_SUCCESS)
  4260. {
  4261. TRACE1 (ANY, "ElEnumAndUpdateRegistryInterfaceList: Error in RegSetValueEx for InterfaceList, %ld",
  4262. lError);
  4263. dwRetCode = (DWORD)lError;
  4264. break;
  4265. }
  4266. } while (FALSE);
  4267. if (pbNdisuioEnumBuffer != NULL)
  4268. {
  4269. FREE(pbNdisuioEnumBuffer);
  4270. }
  4271. if (hkey != NULL)
  4272. {
  4273. RegCloseKey (hkey);
  4274. }
  4275. if (pwszRegInterfaceList != NULL)
  4276. {
  4277. FREE (pwszRegInterfaceList);
  4278. }
  4279. return dwRetCode;
  4280. }
  4281. //
  4282. // ElReadGlobalRegistryParams
  4283. //
  4284. // Description:
  4285. //
  4286. // Read registry parameters global to EAPOL state machine
  4287. // i.e. maxStart, startPeriod, authPeriod, heldPeriod
  4288. //
  4289. // Arguments:
  4290. // Unused
  4291. //
  4292. // Return values:
  4293. //
  4294. // NO_ERROR - success
  4295. // non-zero - error
  4296. //
  4297. DWORD
  4298. ElReadGlobalRegistryParams ()
  4299. {
  4300. HKEY hKey = NULL;
  4301. DWORD dwDisposition = 0;
  4302. DWORD dwType = 0;
  4303. DWORD dwInfoSize = 0;
  4304. DWORD lError = 0;
  4305. DWORD dwmaxStart=0, dwstartPeriod=0, dwauthPeriod=0, dwheldPeriod=0;
  4306. DWORD dwSupplicantMode = EAPOL_DEFAULT_SUPPLICANT_MODE;
  4307. DWORD dwEAPOLAuthMode = EAPOL_DEFAULT_AUTH_MODE;
  4308. DWORD dwRetCode = NO_ERROR;
  4309. do
  4310. {
  4311. // Get handle to
  4312. // HKLM\Software\Microsoft\EAPOL\Parameters\General\Global
  4313. if ((lError = RegCreateKeyEx (
  4314. HKEY_LOCAL_MACHINE,
  4315. cwszEAPOLGlobalParams,
  4316. 0,
  4317. NULL,
  4318. REG_OPTION_NON_VOLATILE,
  4319. KEY_READ,
  4320. NULL,
  4321. &hKey,
  4322. &dwDisposition)) != ERROR_SUCCESS)
  4323. {
  4324. if (lError != ERROR_FILE_NOT_FOUND)
  4325. {
  4326. TRACE1 (ANY, "ElReadGlobalRegistryParams: Error in RegCreateKeyEx for base key, %ld",
  4327. lError);
  4328. }
  4329. break;
  4330. }
  4331. ACQUIRE_WRITE_LOCK (&g_EAPOLConfig);
  4332. // If setting values for the first time, initialize values
  4333. if (!(g_dwmaxStart || g_dwstartPeriod || g_dwauthPeriod || g_dwheldPeriod || g_dwSupplicantMode))
  4334. {
  4335. g_dwmaxStart = EAPOL_MAX_START;
  4336. g_dwstartPeriod = EAPOL_START_PERIOD;
  4337. g_dwauthPeriod = EAPOL_AUTH_PERIOD;
  4338. g_dwheldPeriod = EAPOL_HELD_PERIOD;
  4339. g_dwSupplicantMode = EAPOL_DEFAULT_SUPPLICANT_MODE;
  4340. }
  4341. RELEASE_WRITE_LOCK (&g_EAPOLConfig);
  4342. dwmaxStart = g_dwmaxStart;
  4343. dwstartPeriod = g_dwstartPeriod;
  4344. dwauthPeriod = g_dwauthPeriod;
  4345. dwheldPeriod = g_dwheldPeriod;
  4346. // Get the value of ..\General\EAPOLGlobal\authPeriod
  4347. dwInfoSize = sizeof(DWORD);
  4348. if ((lError = RegQueryValueEx (
  4349. hKey,
  4350. cwszAuthPeriod,
  4351. 0,
  4352. &dwType,
  4353. (BYTE *)&dwauthPeriod,
  4354. &dwInfoSize)) != ERROR_SUCCESS)
  4355. {
  4356. if (lError != ERROR_FILE_NOT_FOUND)
  4357. {
  4358. TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueEx for cszAuthPeriod, %ld, InfoSize=%ld",
  4359. lError, dwInfoSize);
  4360. }
  4361. dwauthPeriod = g_dwauthPeriod;
  4362. lError = ERROR_SUCCESS;
  4363. }
  4364. // Get the value of ..\General\EAPOLGlobal\heldPeriod
  4365. dwInfoSize = sizeof(DWORD);
  4366. if ((lError = RegQueryValueEx (
  4367. hKey,
  4368. cwszHeldPeriod,
  4369. 0,
  4370. &dwType,
  4371. (BYTE *)&dwheldPeriod,
  4372. &dwInfoSize)) != ERROR_SUCCESS)
  4373. {
  4374. if (lError != ERROR_FILE_NOT_FOUND)
  4375. {
  4376. TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueEx for cszHeldPeriod, %ld, InfoSize=%ld",
  4377. lError, dwInfoSize);
  4378. }
  4379. dwheldPeriod = g_dwheldPeriod;
  4380. lError = ERROR_SUCCESS;
  4381. }
  4382. // Get the value of ..\General\EAPOLGlobal\startPeriod
  4383. dwInfoSize = sizeof(DWORD);
  4384. if ((lError = RegQueryValueEx (
  4385. hKey,
  4386. cwszStartPeriod,
  4387. 0,
  4388. &dwType,
  4389. (BYTE *)&dwstartPeriod,
  4390. &dwInfoSize)) != ERROR_SUCCESS)
  4391. {
  4392. if (lError != ERROR_FILE_NOT_FOUND)
  4393. {
  4394. TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueEx for cszStartPeriod, %ld, InfoSize=%ld",
  4395. lError, dwInfoSize);
  4396. }
  4397. dwstartPeriod = g_dwstartPeriod;
  4398. lError = ERROR_SUCCESS;
  4399. }
  4400. // Get the value of ..\General\EAPOLGlobal\maxStart
  4401. dwInfoSize = sizeof(DWORD);
  4402. if ((lError = RegQueryValueEx (
  4403. hKey,
  4404. cwszMaxStart,
  4405. 0,
  4406. &dwType,
  4407. (BYTE *)&dwmaxStart,
  4408. &dwInfoSize)) != ERROR_SUCCESS)
  4409. {
  4410. if (lError != ERROR_FILE_NOT_FOUND)
  4411. {
  4412. TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueEx for cszMaxStart, %ld, InfoSize=%ld",
  4413. lError, dwInfoSize);
  4414. }
  4415. dwmaxStart = g_dwmaxStart;
  4416. lError = ERROR_SUCCESS;
  4417. }
  4418. // Get the value of ..\General\EAPOLGlobal\SupplicantMode
  4419. dwInfoSize = sizeof(DWORD);
  4420. if ((lError = RegQueryValueEx (
  4421. hKey,
  4422. cwszSupplicantMode,
  4423. 0,
  4424. &dwType,
  4425. (BYTE *)&dwSupplicantMode,
  4426. &dwInfoSize)) != ERROR_SUCCESS)
  4427. {
  4428. TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueEx for cwszSupplicantMode, %ld, InfoSize=%ld",
  4429. lError, dwInfoSize);
  4430. dwSupplicantMode = g_dwSupplicantMode;
  4431. lError = ERROR_SUCCESS;
  4432. }
  4433. if (dwSupplicantMode > MAX_SUPPLICANT_MODE)
  4434. {
  4435. dwSupplicantMode = EAPOL_DEFAULT_SUPPLICANT_MODE;
  4436. }
  4437. g_dwSupplicantMode = dwSupplicantMode;
  4438. // Get the value of ..\General\EAPOLGlobal\AuthMode
  4439. dwInfoSize = sizeof(DWORD);
  4440. if ((lError = RegQueryValueEx (
  4441. hKey,
  4442. cwszAuthMode,
  4443. 0,
  4444. &dwType,
  4445. (BYTE *)&dwEAPOLAuthMode,
  4446. &dwInfoSize)) != ERROR_SUCCESS)
  4447. {
  4448. TRACE2 (ANY, "ElReadGlobalRegistryParams: Error in RegQueryValueEx for cwszAuthMode, %ld, InfoSize=%ld",
  4449. lError, dwInfoSize);
  4450. dwEAPOLAuthMode = g_dwEAPOLAuthMode;
  4451. lError = ERROR_SUCCESS;
  4452. }
  4453. if (dwEAPOLAuthMode > MAX_EAPOL_AUTH_MODE)
  4454. {
  4455. dwEAPOLAuthMode = EAPOL_DEFAULT_AUTH_MODE;
  4456. }
  4457. g_dwEAPOLAuthMode = dwEAPOLAuthMode;
  4458. // Successful in reading all parameters
  4459. ACQUIRE_WRITE_LOCK (&g_EAPOLConfig);
  4460. g_dwmaxStart = dwmaxStart;
  4461. g_dwstartPeriod = dwstartPeriod;
  4462. g_dwauthPeriod = dwauthPeriod;
  4463. g_dwheldPeriod = dwheldPeriod;
  4464. RELEASE_WRITE_LOCK (&g_EAPOLConfig);
  4465. } while (FALSE);
  4466. dwRetCode = (DWORD)lError;
  4467. if (dwRetCode != NO_ERROR)
  4468. {
  4469. TRACE1 (ANY, "ElReadGlobalRegistryParams: failed with error %ld",
  4470. dwRetCode);
  4471. }
  4472. if (hKey != NULL)
  4473. {
  4474. RegCloseKey(hKey);
  4475. }
  4476. return dwRetCode;
  4477. }
  4478. //
  4479. // ElPostEapConfigChanged
  4480. //
  4481. // Description:
  4482. //
  4483. // Watch the registry for changes in EAP config
  4484. // - HKLM - EAP type
  4485. // - HKLM - EAPOLEnabled
  4486. //
  4487. // Restart the state machine if the params change
  4488. //
  4489. // Arguments:
  4490. // pwszGuid - Interface GUID string
  4491. //
  4492. // Return values:
  4493. // NO_ERROR - success
  4494. // !NO_ERROR - error
  4495. //
  4496. //
  4497. DWORD
  4498. ElPostEapConfigChanged (
  4499. IN WCHAR *pwszGuid,
  4500. IN EAPOL_INTF_PARAMS *pIntfParams
  4501. )
  4502. {
  4503. DWORD dwEventStatus = 0;
  4504. BYTE *pbData = NULL;
  4505. BOOLEAN fDecrWorkerThreadCount = FALSE;
  4506. DWORD dwRetCode = NO_ERROR;
  4507. do
  4508. {
  4509. if (g_hEventTerminateEAPOL == NULL)
  4510. {
  4511. dwRetCode = NO_ERROR;
  4512. break;
  4513. }
  4514. if (( dwEventStatus = WaitForSingleObject (
  4515. g_hEventTerminateEAPOL,
  4516. 0)) == WAIT_FAILED)
  4517. {
  4518. dwRetCode = GetLastError ();
  4519. break;
  4520. }
  4521. if (dwEventStatus == WAIT_OBJECT_0)
  4522. {
  4523. dwRetCode = NO_ERROR;
  4524. break;
  4525. }
  4526. fDecrWorkerThreadCount = TRUE;
  4527. InterlockedIncrement (&g_lWorkerThreads);
  4528. pbData = (BYTE *) MALLOC ((((wcslen(pwszGuid)+1)*sizeof(WCHAR) + 7) & 0xfffffff8) + sizeof (EAPOL_INTF_PARAMS));
  4529. if (pbData == NULL)
  4530. {
  4531. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  4532. break;
  4533. }
  4534. wcscpy ((WCHAR *)pbData, pwszGuid);
  4535. memcpy (pbData + (((wcslen(pwszGuid)+1)*sizeof(WCHAR) + 7) & 0xfffffff8), (BYTE *)pIntfParams, sizeof(EAPOL_INTF_PARAMS));
  4536. if (!QueueUserWorkItem (
  4537. (LPTHREAD_START_ROUTINE)ElProcessEapConfigChange,
  4538. (PVOID)pbData,
  4539. WT_EXECUTELONGFUNCTION))
  4540. {
  4541. dwRetCode = GetLastError();
  4542. TRACE1 (DEVICE, "ElPostEapConfigChanged: QueueUserWorkItem failed with error %ld",
  4543. dwRetCode);
  4544. break;
  4545. }
  4546. else
  4547. {
  4548. fDecrWorkerThreadCount = FALSE;
  4549. }
  4550. }
  4551. while (FALSE);
  4552. if (dwRetCode != NO_ERROR)
  4553. {
  4554. if (pbData != NULL)
  4555. {
  4556. FREE (pbData);
  4557. }
  4558. }
  4559. if (fDecrWorkerThreadCount)
  4560. {
  4561. InterlockedDecrement (&g_lWorkerThreads);
  4562. }
  4563. return dwRetCode;
  4564. }
  4565. //
  4566. // ElProcessEapConfigChange
  4567. //
  4568. // Description:
  4569. //
  4570. // Read EAP config changes made in registry. Restart EAPOL on the particular
  4571. // interface or stop EAPOL
  4572. //
  4573. // Arguments:
  4574. // pvContext - GUID String
  4575. //
  4576. // Return values:
  4577. //
  4578. // NO_ERROR - success
  4579. // non-zero - error
  4580. //
  4581. DWORD
  4582. WINAPI
  4583. ElProcessEapConfigChange (
  4584. IN PVOID pvContext
  4585. )
  4586. {
  4587. DWORD dwEapFlags = 0;
  4588. DWORD dwEapTypeToBeUsed = 0;
  4589. WCHAR *pwszModifiedGUID = NULL;
  4590. DWORD dwSizeOfAuthData = 0;
  4591. PBYTE pbAuthData = NULL;
  4592. EAPOL_PCB *pPCB = NULL;
  4593. BOOL fReStartPort = FALSE;
  4594. EAPOL_ZC_INTF ZCData;
  4595. EAPOL_INTF_PARAMS EapolIntfParams, *pTmpIntfParams = NULL;
  4596. BYTE *pbModifiedSSID = NULL;
  4597. DWORD dwSizeOfModifiedSSID = 0;
  4598. BOOLEAN fPCBReferenced = FALSE;
  4599. BOOLEAN fPCBLocked = FALSE;
  4600. LONG lError = 0;
  4601. DWORD dwRetCode = NO_ERROR;
  4602. do
  4603. {
  4604. // Get the GUID for the interface for which EAP config was modified
  4605. pwszModifiedGUID = (WCHAR *)pvContext;
  4606. pTmpIntfParams = (EAPOL_INTF_PARAMS *)((BYTE *)pvContext + (((wcslen(pwszModifiedGUID)+1)*sizeof(WCHAR) + 7 ) & 0xfffffff8));
  4607. pbModifiedSSID = (BYTE *)(&pTmpIntfParams->bSSID[0]);
  4608. dwSizeOfModifiedSSID = pTmpIntfParams->dwSizeOfSSID;
  4609. // Get interface-wide parameters
  4610. ZeroMemory ((BYTE *)&EapolIntfParams, sizeof(EAPOL_INTF_PARAMS));
  4611. EapolIntfParams.dwEapFlags = DEFAULT_EAP_STATE;
  4612. EapolIntfParams.dwEapType = DEFAULT_EAP_TYPE;
  4613. if ((dwRetCode = ElGetInterfaceParams (
  4614. pwszModifiedGUID,
  4615. &EapolIntfParams
  4616. )) != NO_ERROR)
  4617. {
  4618. if (dwRetCode == ERROR_FILE_NOT_FOUND)
  4619. {
  4620. TRACE1 (PORT, "ElProcessEapConfigChange: ElGetInterfaceParams failed with error %ld",
  4621. dwRetCode);
  4622. dwRetCode = NO_ERROR;
  4623. }
  4624. else
  4625. {
  4626. break;
  4627. }
  4628. }
  4629. dwEapTypeToBeUsed = EapolIntfParams.dwEapType;
  4630. dwEapFlags = EapolIntfParams.dwEapFlags;
  4631. // Check if PCB exists
  4632. ACQUIRE_WRITE_LOCK (&(g_PCBLock));
  4633. if ((pPCB = ElGetPCBPointerFromPortGUID (pwszModifiedGUID))
  4634. != NULL)
  4635. {
  4636. EAPOL_REFERENCE_PORT (pPCB);
  4637. fPCBReferenced = TRUE;
  4638. }
  4639. RELEASE_WRITE_LOCK (&(g_PCBLock));
  4640. if (!fPCBReferenced)
  4641. {
  4642. if (IS_EAPOL_ENABLED(dwEapFlags))
  4643. {
  4644. TRACE0 (ANY, "ElProcessEapConfigChange: PCB not started, enabled, starting PCB");
  4645. fReStartPort = TRUE;
  4646. }
  4647. else
  4648. {
  4649. TRACE0 (ANY, "ElProcessEapConfigChange: PCB not started, not enabled");
  4650. }
  4651. break;
  4652. }
  4653. else
  4654. {
  4655. if (!IS_EAPOL_ENABLED(dwEapFlags))
  4656. {
  4657. // Found PCB for interface, where EAPOLEnabled = 0
  4658. // Stop EAPOL on the port and remove the port from the module
  4659. TRACE0 (ANY, "ElProcessEapConfigChange: PCB ref'd, need to disable");
  4660. #if 0
  4661. pPCB->dwFlags &= ~EAPOL_PORT_FLAG_ACTIVE;
  4662. pPCB->dwFlags |= EAPOL_PORT_FLAG_DISABLED;
  4663. #endif
  4664. fReStartPort = TRUE;
  4665. if ((dwRetCode = ElShutdownInterface (pwszModifiedGUID)) != NO_ERROR)
  4666. {
  4667. TRACE1 (ANY, "ElProcessEapConfigChange: ElShutdownInterface failed with error %ld",
  4668. dwRetCode);
  4669. break;
  4670. }
  4671. break;
  4672. }
  4673. else
  4674. {
  4675. TRACE0 (ANY, "ElProcessEapConfigChange: PCB ref and enabled, continue check");
  4676. }
  4677. }
  4678. ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
  4679. fPCBLocked = TRUE;
  4680. // If SSID changed != current SSID of PCB, do not worry
  4681. if (pPCB->pSSID != NULL)
  4682. {
  4683. if (dwSizeOfModifiedSSID != pPCB->pSSID->SsidLength)
  4684. {
  4685. TRACE0 (ANY, "ElProcessEapConfigChange: Set for different SSID, ignore");
  4686. break;
  4687. }
  4688. else
  4689. {
  4690. if (memcmp (pPCB->pSSID->Ssid, pbModifiedSSID, pPCB->pSSID->SsidLength))
  4691. {
  4692. TRACE0 (ANY, "ElProcessEapConfigChange: Same non-NULL length, diff SSID, ignoring");
  4693. break;
  4694. }
  4695. }
  4696. }
  4697. else
  4698. {
  4699. // No SSID on current PCB
  4700. if (dwSizeOfModifiedSSID != 0)
  4701. {
  4702. // Only if default SSID, should we proceed for further checks
  4703. if (dwSizeOfModifiedSSID == MAX_SSID_LEN)
  4704. {
  4705. if (memcmp (pbModifiedSSID, g_bDefaultSSID, MAX_SSID_LEN))
  4706. {
  4707. TRACE0 (ANY, "ElProcessEapConfigChange: Modified SSID MAX_SSID_LEN, not default SSID");
  4708. break;
  4709. }
  4710. }
  4711. else
  4712. {
  4713. TRACE0 (ANY, "ElProcessEapConfigChange: Modified SSID non-NULL, PCB SSID NULL");
  4714. break;
  4715. }
  4716. }
  4717. }
  4718. // Restart port for the following cases:
  4719. // EAPOL_INTF_PARAMS for SSID changed
  4720. // CustomAuthData for default EAP type changed
  4721. if ((dwEapFlags != pPCB->dwEapFlags) ||
  4722. (dwEapTypeToBeUsed != pPCB->dwEapTypeToBeUsed))
  4723. {
  4724. TRACE0 (ANY, "ElProcessEapConfigChange: dwEapFlags != pPCB->dwEapFlags || dwEapTypeToBeUsed != pPCB->dwEapTypeToBeUsed");
  4725. fReStartPort = TRUE;
  4726. break;
  4727. }
  4728. // Get Custom auth data for the current default EAP Type
  4729. // Get the size of the EAP blob
  4730. if ((dwRetCode = ElGetCustomAuthData (
  4731. pwszModifiedGUID,
  4732. dwEapTypeToBeUsed,
  4733. dwSizeOfModifiedSSID,
  4734. pbModifiedSSID,
  4735. NULL,
  4736. &dwSizeOfAuthData
  4737. )) != NO_ERROR)
  4738. {
  4739. if (dwRetCode == ERROR_BUFFER_TOO_SMALL)
  4740. {
  4741. if (dwSizeOfAuthData <= 0)
  4742. {
  4743. // No EAP blob stored in the registry
  4744. pbAuthData = NULL;
  4745. if (pPCB->pCustomAuthConnData)
  4746. {
  4747. if (pPCB->pCustomAuthConnData->dwSizeOfCustomAuthData > 0)
  4748. {
  4749. TRACE0 (ANY, "ElProcessEapConfigChange: Current customauthdata = 0; PCB != 0");
  4750. fReStartPort = TRUE;
  4751. }
  4752. }
  4753. dwRetCode = NO_ERROR;
  4754. break;
  4755. }
  4756. else
  4757. {
  4758. pbAuthData = MALLOC (dwSizeOfAuthData);
  4759. if (pbAuthData == NULL)
  4760. {
  4761. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  4762. TRACE0 (ANY, "ElProcessEapConfigChange: MALLOC failed for pbAuthData");
  4763. break;
  4764. }
  4765. if ((dwRetCode = ElGetCustomAuthData (
  4766. pwszModifiedGUID,
  4767. dwEapTypeToBeUsed,
  4768. dwSizeOfModifiedSSID,
  4769. pbModifiedSSID,
  4770. pbAuthData,
  4771. &dwSizeOfAuthData
  4772. )) != NO_ERROR)
  4773. {
  4774. TRACE1 (ANY, "ElProcessEapConfigChange: ElGetCustomAuthData failed with %ld",
  4775. dwRetCode);
  4776. break;
  4777. }
  4778. }
  4779. }
  4780. else
  4781. {
  4782. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  4783. // CustomAuthData for "Default" is always created for an
  4784. // interface when EAPOL starts up
  4785. TRACE1 (ANY, "ElProcessEapConfigChange: ElGetCustomAuthData size estimation failed with error %ld",
  4786. dwRetCode);
  4787. break;
  4788. }
  4789. }
  4790. if (pPCB->pCustomAuthConnData == NULL)
  4791. {
  4792. if (dwSizeOfAuthData > 0)
  4793. {
  4794. fReStartPort = TRUE;
  4795. break;
  4796. }
  4797. }
  4798. else
  4799. {
  4800. if (pPCB->pCustomAuthConnData->dwSizeOfCustomAuthData
  4801. != dwSizeOfAuthData)
  4802. {
  4803. // Same EAP Type, but different lengths
  4804. fReStartPort = TRUE;
  4805. break;
  4806. }
  4807. else
  4808. {
  4809. if (memcmp (
  4810. pPCB->pCustomAuthConnData->pbCustomAuthData,
  4811. pbAuthData, dwSizeOfAuthData) != 0)
  4812. {
  4813. // Same EAP Type, same auth data length, but
  4814. // different contents
  4815. fReStartPort = TRUE;
  4816. break;
  4817. }
  4818. else
  4819. {
  4820. // No change in EAP config data for this
  4821. // interface
  4822. TRACE0 (ANY, "ElProcessEapConfigChange: Same SSID, EAPType, CustomAuth, No content change");
  4823. }
  4824. }
  4825. }
  4826. } while (FALSE);
  4827. if (fPCBLocked && fPCBReferenced && fReStartPort)
  4828. {
  4829. // Reset connection to go through full authentication
  4830. if (pPCB->pSSID != NULL)
  4831. {
  4832. FREE (pPCB->pSSID);
  4833. pPCB->pSSID = NULL;
  4834. }
  4835. }
  4836. if (fPCBLocked)
  4837. {
  4838. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  4839. }
  4840. if (fPCBReferenced)
  4841. {
  4842. EAPOL_DEREFERENCE_PORT (pPCB);
  4843. }
  4844. if (fReStartPort)
  4845. {
  4846. #ifdef ZEROCONFIG_LINKED
  4847. // Indicate hard-reset to WZC
  4848. ZeroMemory ((PVOID)&ZCData, sizeof(EAPOL_ZC_INTF));
  4849. ZCData.dwAuthFailCount = 0;
  4850. ZCData.PreviousAuthenticationType = 0;
  4851. if ((dwRetCode = ElZeroConfigNotify (
  4852. 0,
  4853. WZCCMD_HARD_RESET,
  4854. pwszModifiedGUID,
  4855. &ZCData
  4856. )) != NO_ERROR)
  4857. {
  4858. TRACE1 (EAPOL, "ElProcessEapConfigChange: ElZeroConfigNotify failed with error %ld",
  4859. dwRetCode);
  4860. dwRetCode = NO_ERROR;
  4861. }
  4862. #endif // ZEROCONFIG_LINKED
  4863. DbLogPCBEvent (DBLOG_CATEG_INFO, NULL, EAPOL_PARAMS_CHANGE, pwszModifiedGUID);
  4864. if ((dwRetCode = ElEnumAndOpenInterfaces (
  4865. NULL, pwszModifiedGUID, 0, NULL))
  4866. != NO_ERROR)
  4867. {
  4868. TRACE1 (ANY, "ElProcessEapConfigChange: ElEnumAndOpenInterfaces returned error %ld",
  4869. dwRetCode);
  4870. dwRetCode = NO_ERROR;
  4871. }
  4872. }
  4873. TRACE1 (ANY, "ElProcessEapConfigChange: Finished with error %ld",
  4874. dwRetCode);
  4875. if (pvContext != NULL)
  4876. {
  4877. FREE (pvContext);
  4878. }
  4879. if (pbAuthData != NULL)
  4880. {
  4881. FREE (pbAuthData);
  4882. }
  4883. InterlockedDecrement (&g_lWorkerThreads);
  4884. return 0;
  4885. }
  4886. //
  4887. // ElStringToGuid
  4888. //
  4889. // Description:
  4890. //
  4891. // Function to convert a Guid-String to a GUID
  4892. //
  4893. // Arguments:
  4894. // psGuid - String-ized Guid
  4895. // pGuid - Pointer to Guid
  4896. //
  4897. // Return values:
  4898. // None
  4899. //
  4900. VOID
  4901. ElStringToGuid (
  4902. IN WCHAR *pwsGuid,
  4903. OUT LPGUID pGuid
  4904. )
  4905. {
  4906. WCHAR wc;
  4907. DWORD i=0;
  4908. //
  4909. // If the first character is a '{', skip it.
  4910. //
  4911. if ( pwsGuid[0] == L'{' )
  4912. pwsGuid++;
  4913. //
  4914. // Convert string to guid
  4915. // (since pwsGuid may be used again below, no permanent modification to
  4916. // it may be made)
  4917. //
  4918. wc = pwsGuid[8];
  4919. pwsGuid[8] = 0;
  4920. pGuid->Data1 = wcstoul ( &pwsGuid[0], 0, 16 );
  4921. pwsGuid[8] = wc;
  4922. wc = pwsGuid[13];
  4923. pwsGuid[13] = 0;
  4924. pGuid->Data2 = (USHORT)wcstoul ( &pwsGuid[9], 0, 16 );
  4925. pwsGuid[13] = wc;
  4926. wc = pwsGuid[18];
  4927. pwsGuid[18] = 0;
  4928. pGuid->Data3 = (USHORT)wcstoul ( &pwsGuid[14], 0, 16 );
  4929. pwsGuid[18] = wc;
  4930. wc = pwsGuid[21];
  4931. pwsGuid[21] = 0;
  4932. pGuid->Data4[0] = (unsigned char)wcstoul ( &pwsGuid[19], 0, 16 );
  4933. pwsGuid[21] = wc;
  4934. wc = pwsGuid[23];
  4935. pwsGuid[23] = 0;
  4936. pGuid->Data4[1] = (unsigned char)wcstoul ( &pwsGuid[21], 0, 16 );
  4937. pwsGuid[23] = wc;
  4938. for ( i=0; i < 6; i++ )
  4939. {
  4940. wc = pwsGuid[26+i*2];
  4941. pwsGuid[26+i*2] = 0;
  4942. pGuid->Data4[2+i] = (unsigned char)wcstoul ( &pwsGuid[24+i*2], 0, 16 );
  4943. pwsGuid[26+i*2] = wc;
  4944. }
  4945. return;
  4946. }
  4947. //
  4948. // ElGetIdentity
  4949. //
  4950. // Description:
  4951. //
  4952. // Get the identity depending on the authentication type being used
  4953. //
  4954. // Arguments:
  4955. // pPCB - Pointer to PCB for the port
  4956. //
  4957. // Return values:
  4958. //
  4959. // NO_ERROR - success
  4960. // non-zero - error
  4961. //
  4962. DWORD
  4963. ElGetIdentity (
  4964. IN EAPOL_PCB *pPCB
  4965. )
  4966. {
  4967. BOOLEAN fUserLogonAllowed = FALSE;
  4968. DWORD dwRetCode = NO_ERROR;
  4969. do
  4970. {
  4971. switch (pPCB->dwEAPOLAuthMode)
  4972. {
  4973. case EAPOL_AUTH_MODE_0:
  4974. fUserLogonAllowed = TRUE;
  4975. break;
  4976. case EAPOL_AUTH_MODE_1:
  4977. fUserLogonAllowed = TRUE;
  4978. break;
  4979. case EAPOL_AUTH_MODE_2:
  4980. fUserLogonAllowed = FALSE;
  4981. break;
  4982. }
  4983. // Get user's identity if it has not been obtained till now
  4984. if ((g_fUserLoggedOn)
  4985. && (fUserLogonAllowed)
  4986. && (pPCB->PreviousAuthenticationType != EAPOL_MACHINE_AUTHENTICATION))
  4987. {
  4988. TRACE0 (ANY, "ElGetIdentity: Userlogged, Prev !Machine auth");
  4989. if (!(pPCB->fGotUserIdentity))
  4990. {
  4991. if (pPCB->dwAuthFailCount < EAPOL_MAX_AUTH_FAIL_COUNT)
  4992. {
  4993. pPCB->PreviousAuthenticationType = EAPOL_USER_AUTHENTICATION;
  4994. if (pPCB->dwEapTypeToBeUsed == EAP_TYPE_MD5)
  4995. {
  4996. TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth: MD5");
  4997. // EAP-MD5CHAP
  4998. if ((dwRetCode = ElGetUserNamePassword (
  4999. pPCB)) != NO_ERROR)
  5000. {
  5001. TRACE1 (ANY, "ElGetIdentity: Error in ElGetUserNamePassword %ld",
  5002. dwRetCode);
  5003. }
  5004. }
  5005. else
  5006. {
  5007. TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth: !MD5");
  5008. // All other EAP Types
  5009. if ((dwRetCode = ElGetUserIdentity (
  5010. pPCB)) != NO_ERROR)
  5011. {
  5012. TRACE1 (ANY, "ElGetIdentity: Error in ElGetUserIdentity %ld",
  5013. dwRetCode);
  5014. }
  5015. }
  5016. if ((dwRetCode == NO_ERROR) || (dwRetCode == ERROR_IO_PENDING))
  5017. {
  5018. TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth: No Error: User Auth fine");
  5019. break;
  5020. }
  5021. else
  5022. {
  5023. pPCB->PreviousAuthenticationType = EAPOL_UNAUTHENTICATED_ACCESS;
  5024. TRACE0 (ANY, "ElGetIdentity: Userlogged, <Maxauth, Prev !Machine auth: ERROR");
  5025. }
  5026. }
  5027. else
  5028. {
  5029. TRACE0 (ANY, "ElGetIdentity: Userlogged, >Maxauth, Prev !Machine auth");
  5030. if (!IS_GUEST_AUTH_ENABLED(pPCB->dwEapFlags))
  5031. {
  5032. TRACE0 (ANY, "ElGetIdentity: Userlogged, Prev !Machine auth:>MaxAuth: Guest disabled");
  5033. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  5034. break;
  5035. }
  5036. if (pPCB->pszIdentity != NULL)
  5037. {
  5038. FREE (pPCB->pszIdentity);
  5039. pPCB->pszIdentity = NULL;
  5040. }
  5041. pPCB->PreviousAuthenticationType = EAPOL_UNAUTHENTICATED_ACCESS;
  5042. dwRetCode = NO_ERROR;
  5043. TRACE0 (ANY, "ElGetIdentity: Userlogged, Prev !Machine auth:>MaxAuth OR Error: Guest identity sent");
  5044. }
  5045. }
  5046. else
  5047. {
  5048. TRACE0 (ANY, "ElGetIdentity: Already got identity");
  5049. }
  5050. }
  5051. else
  5052. {
  5053. if (pPCB->hUserToken != NULL)
  5054. {
  5055. CloseHandle (pPCB->hUserToken);
  5056. pPCB->hUserToken = NULL;
  5057. }
  5058. TRACE3 (ANY, "ElGetIdentity: Userlogged=%ld, AuthMode=%ld, Prev Machine auth?=%ld",
  5059. g_fUserLoggedOn?1:0,
  5060. pPCB->dwEAPOLAuthMode,
  5061. (pPCB->PreviousAuthenticationType==EAPOL_MACHINE_AUTHENTICATION)?1:0 );
  5062. // No UI required
  5063. if ((pPCB->dwEapTypeToBeUsed != EAP_TYPE_MD5) &&
  5064. (IS_MACHINE_AUTH_ENABLED(pPCB->dwEapFlags)) &&
  5065. (pPCB->dwAuthFailCount < EAPOL_MAX_AUTH_FAIL_COUNT))
  5066. {
  5067. TRACE0 (ANY, "ElGetIdentity: !MD5, <MaxAuth, Machine auth");
  5068. pPCB->PreviousAuthenticationType = EAPOL_MACHINE_AUTHENTICATION;
  5069. // Get Machine credentials
  5070. dwRetCode = ElGetUserIdentity (pPCB);
  5071. if (dwRetCode != NO_ERROR)
  5072. {
  5073. TRACE1 (ANY, "ElGetIdentity: ElGetUserIdentity, Machine auth, failed with error %ld",
  5074. dwRetCode);
  5075. pPCB->PreviousAuthenticationType = EAPOL_UNAUTHENTICATED_ACCESS;
  5076. }
  5077. break;
  5078. }
  5079. if ((!IS_MACHINE_AUTH_ENABLED(pPCB->dwEapFlags)) ||
  5080. (pPCB->dwAuthFailCount >= EAPOL_MAX_AUTH_FAIL_COUNT) ||
  5081. (pPCB->dwEapTypeToBeUsed == EAP_TYPE_MD5))
  5082. {
  5083. TRACE5 (ANY, "ElGetIdentity: Error=%ld, Machine auth enabled=%ld, MD5=%ld, auth fail (%ld), max fail (%ld)",
  5084. dwRetCode?1:0,
  5085. IS_MACHINE_AUTH_ENABLED(pPCB->dwEapFlags)?1:0,
  5086. (pPCB->dwEapTypeToBeUsed == EAP_TYPE_MD5)?1:0,
  5087. pPCB->dwAuthFailCount,
  5088. EAPOL_MAX_AUTH_FAIL_COUNT);
  5089. if (!IS_GUEST_AUTH_ENABLED (pPCB->dwEapFlags))
  5090. {
  5091. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  5092. break;
  5093. }
  5094. if (pPCB->pszIdentity != NULL)
  5095. {
  5096. FREE (pPCB->pszIdentity);
  5097. pPCB->pszIdentity = NULL;
  5098. }
  5099. pPCB->PreviousAuthenticationType = EAPOL_UNAUTHENTICATED_ACCESS;
  5100. dwRetCode = NO_ERROR;
  5101. TRACE0 (ANY, "ElGetIdentity: machine auth, Guest identity sent");
  5102. }
  5103. }
  5104. }
  5105. while (FALSE);
  5106. return dwRetCode;
  5107. }
  5108. //
  5109. // ElNLAConnectLPC
  5110. //
  5111. // Description:
  5112. //
  5113. // Function called to connect to the LPC port for NLA service
  5114. //
  5115. // Arguments:
  5116. // None
  5117. //
  5118. // Return values:
  5119. // Non-NULL - valid handle
  5120. // NULL - error
  5121. //
  5122. HANDLE
  5123. ElNLAConnectLPC ()
  5124. {
  5125. HANDLE h = NULL;
  5126. LARGE_INTEGER sectionSize;
  5127. UNICODE_STRING portName;
  5128. SECURITY_QUALITY_OF_SERVICE dynamicQoS =
  5129. {
  5130. sizeof(SECURITY_QUALITY_OF_SERVICE),
  5131. SecurityAnonymous,
  5132. SECURITY_DYNAMIC_TRACKING,
  5133. FALSE
  5134. };
  5135. WSM_LPC_DATA data;
  5136. ULONG dataLength;
  5137. NTSTATUS status = STATUS_SUCCESS;
  5138. do
  5139. {
  5140. TRACE0 (EAP, "NLAConnectLPC: Entered");
  5141. // Create a shared section for passing the large-size LPC messages.
  5142. RtlZeroMemory(&g_ClientView, sizeof(g_ClientView));
  5143. g_ClientView.Length = sizeof(g_ClientView);
  5144. g_ClientView.ViewSize = sizeof(LOCATION_802_1X);
  5145. sectionSize.QuadPart = sizeof(LOCATION_802_1X);
  5146. status = NtCreateSection (&g_ClientView.SectionHandle,
  5147. (SECTION_MAP_READ | SECTION_MAP_WRITE),
  5148. NULL,
  5149. &sectionSize,
  5150. PAGE_READWRITE,
  5151. SEC_COMMIT,
  5152. NULL
  5153. );
  5154. if (!NT_SUCCESS(status))
  5155. {
  5156. h = NULL;
  5157. TRACE1 (EAP, "NLAConnectLPC: NtCreateSection failed with error",
  5158. status);
  5159. break;
  5160. }
  5161. // Connect via LPC to the Network Location Awareness (NLA) service.
  5162. RtlInitUnicodeString (&portName, WSM_PRIVATE_PORT_NAME);
  5163. RtlZeroMemory (&data, sizeof (data));
  5164. data.signature = WSM_SIGNATURE;
  5165. data.connect.version.major = WSM_VERSION_MAJOR;
  5166. data.connect.version.minor = WSM_VERSION_MINOR;
  5167. dataLength = sizeof (data);
  5168. status = NtConnectPort (&h,
  5169. &portName,
  5170. &dynamicQoS,
  5171. &g_ClientView,
  5172. NULL,
  5173. NULL,
  5174. &data,
  5175. &dataLength
  5176. );
  5177. // If NtConnectPort() succeeded, LPC will maintain a reference
  5178. // to the section, otherwise we no longer need it.
  5179. NtClose (g_ClientView.SectionHandle);
  5180. g_ClientView.SectionHandle = NULL;
  5181. if (!NT_SUCCESS(status)) {
  5182. TRACE1 (EAP, "NLAConnectLPC: NtConnectPort failed with error %ld",
  5183. status);
  5184. }
  5185. }
  5186. while (FALSE);
  5187. return (h);
  5188. }
  5189. //
  5190. // ElNLACleanupLPC
  5191. //
  5192. // Description:
  5193. //
  5194. // Function called to close the LPC port for NLA service
  5195. //
  5196. // Arguments:
  5197. // None
  5198. //
  5199. // Return values:
  5200. // None
  5201. //
  5202. VOID
  5203. ElNLACleanupLPC ()
  5204. {
  5205. if (g_hNLA_LPC_Port != NULL) {
  5206. NtClose (g_hNLA_LPC_Port);
  5207. g_hNLA_LPC_Port = NULL;
  5208. }
  5209. }
  5210. //
  5211. // ElNLARegister_802_1X
  5212. //
  5213. // Description:
  5214. //
  5215. // Function called to register 802.1X information with NLA
  5216. //
  5217. // Arguments:
  5218. // plocation - Pointer to data needed to be registered with NLA
  5219. //
  5220. // Return values:
  5221. // None
  5222. //
  5223. VOID
  5224. ElNLARegister_802_1X (
  5225. IN PLOCATION_802_1X plocation
  5226. )
  5227. {
  5228. WSM_LPC_MESSAGE message;
  5229. NTSTATUS status;
  5230. ACQUIRE_WRITE_LOCK (&g_NLALock);
  5231. do
  5232. {
  5233. TRACE0 (EAP, "NLARegister_802_1X: Entered");
  5234. // Connect to the Network Location Awareness (NLA) service if
  5235. // necessary.
  5236. if (g_hNLA_LPC_Port == NULL) {
  5237. if ((g_hNLA_LPC_Port = ElNLAConnectLPC ()) == NULL) {
  5238. RELEASE_WRITE_LOCK (&g_NLALock);
  5239. return;
  5240. }
  5241. }
  5242. TRACE0 (EAP, "NLARegister_802_1X: g_hNLA_LPC_Port != NULL");
  5243. // Send information to the NLA service.
  5244. RtlZeroMemory (&message, sizeof (message));
  5245. message.portMsg.u1.s1.TotalLength = sizeof (message);
  5246. message.portMsg.u1.s1.DataLength = sizeof (message.data);
  5247. message.data.signature = WSM_SIGNATURE;
  5248. message.data.request.type = LOCATION_802_1X_REGISTER;
  5249. __try {
  5250. RtlCopyMemory (g_ClientView.ViewBase,
  5251. plocation, sizeof(LOCATION_802_1X));
  5252. }
  5253. __except (EXCEPTION_EXECUTE_HANDLER)
  5254. {
  5255. RELEASE_WRITE_LOCK (&g_NLALock);
  5256. return;
  5257. }
  5258. status = NtRequestWaitReplyPort ( g_hNLA_LPC_Port, (PPORT_MESSAGE)&message, (PPORT_MESSAGE)&message);
  5259. if (status != STATUS_SUCCESS) {
  5260. TRACE1 (EAP, "NLARegister_802_1X: NtWaitReplyPort failed with error",
  5261. status);
  5262. // It's possible the service was stopped and restarted.
  5263. // Ditch the old LPC connection.
  5264. CloseHandle (g_hNLA_LPC_Port);
  5265. // Create a new LPC connection.
  5266. if ((g_hNLA_LPC_Port = ElNLAConnectLPC ()) == NULL) {
  5267. RELEASE_WRITE_LOCK (&g_NLALock);
  5268. TRACE0 (EAP, "NLARegister_802_1X: NLAConnectLPC failed");
  5269. return;
  5270. }
  5271. // Try the send one last time.
  5272. status = NtRequestWaitReplyPort (g_hNLA_LPC_Port,
  5273. (PPORT_MESSAGE)&message, (PPORT_MESSAGE)&message);
  5274. TRACE1 (EAP, "NLARegister_802_1X: NtWaitReplyPort, try 2, failed with error",
  5275. status);
  5276. }
  5277. TRACE1 (EAP, "NLARegister_802_1X: Completed with status = %ld",
  5278. status);
  5279. }
  5280. while (FALSE);
  5281. RELEASE_WRITE_LOCK (&g_NLALock);
  5282. }
  5283. //
  5284. // ElNLADelete_802_1X
  5285. //
  5286. // Description:
  5287. //
  5288. // Function called to de-register 802.1X information registered with NLA
  5289. //
  5290. // Arguments:
  5291. // plocation - Pointer to data to be de-registered from NLA
  5292. //
  5293. // Return values:
  5294. // None
  5295. //
  5296. VOID
  5297. ElNLADelete_802_1X (
  5298. IN PLOCATION_802_1X plocation
  5299. )
  5300. {
  5301. WSM_LPC_MESSAGE message;
  5302. NTSTATUS status;
  5303. ACQUIRE_WRITE_LOCK (&g_NLALock);
  5304. do
  5305. {
  5306. // Connect to the NLA service if necessary.
  5307. if (g_hNLA_LPC_Port == NULL)
  5308. {
  5309. if ((g_hNLA_LPC_Port = ElNLAConnectLPC ()) == NULL)
  5310. {
  5311. RELEASE_WRITE_LOCK (&g_NLALock);
  5312. return;
  5313. }
  5314. }
  5315. // Send information to the NLA service.
  5316. RtlZeroMemory (&message, sizeof(message));
  5317. message.portMsg.u1.s1.TotalLength = sizeof (message);
  5318. message.portMsg.u1.s1.DataLength = sizeof (message.data);
  5319. message.data.signature = WSM_SIGNATURE;
  5320. message.data.request.type = LOCATION_802_1X_DELETE;
  5321. __try {
  5322. RtlCopyMemory (g_ClientView.ViewBase,
  5323. plocation, sizeof(plocation->adapterName));
  5324. }
  5325. __except (EXCEPTION_EXECUTE_HANDLER)
  5326. {
  5327. RELEASE_WRITE_LOCK (&g_NLALock);
  5328. return;
  5329. }
  5330. status = NtRequestWaitReplyPort (g_hNLA_LPC_Port,
  5331. (PPORT_MESSAGE)&message, (PPORT_MESSAGE)&message);
  5332. if (status != STATUS_SUCCESS)
  5333. {
  5334. // If the service was stopped (and possibly restarted), we don't
  5335. // care ... it won't have this information in its list for us
  5336. // to bother deleting.
  5337. CloseHandle (g_hNLA_LPC_Port);
  5338. g_hNLA_LPC_Port = NULL;
  5339. }
  5340. }
  5341. while (FALSE);
  5342. RELEASE_WRITE_LOCK (&g_NLALock);
  5343. }
  5344. //
  5345. // ElGetInterfaceNdisStatistics
  5346. //
  5347. // Function to query NDIS NIC_STATISTICS parameters for an interface
  5348. //
  5349. // Input arguments:
  5350. // pszInterfaceName - Interface Name
  5351. //
  5352. // Return values:
  5353. // pStats - NIC_STATISTICS structure
  5354. //
  5355. //
  5356. DWORD
  5357. ElGetInterfaceNdisStatistics (
  5358. IN WCHAR *pwszInterfaceName,
  5359. IN OUT NIC_STATISTICS *pStats
  5360. )
  5361. {
  5362. WCHAR *pwszDeviceInterfaceName = NULL;
  5363. UNICODE_STRING UInterfaceName;
  5364. DWORD dwRetCode = NO_ERROR;
  5365. do
  5366. {
  5367. pwszDeviceInterfaceName =
  5368. MALLOC ((wcslen (pwszInterfaceName)+12)*sizeof(WCHAR));
  5369. if (pwszDeviceInterfaceName == NULL)
  5370. {
  5371. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  5372. TRACE0 (ANY, "ElGetInterfaceNdisStatistics: MALLOC failed for pwszDeviceInterfaceName");
  5373. break;
  5374. }
  5375. wcscpy (pwszDeviceInterfaceName, L"\\Device\\");
  5376. wcscat (pwszDeviceInterfaceName, pwszInterfaceName);
  5377. TRACE1 (ANY, "ElGetInterfaceNdisStatistics: pwszDeviceInterfaceName = (%ws)",
  5378. pwszDeviceInterfaceName);
  5379. RtlInitUnicodeString (&UInterfaceName, pwszDeviceInterfaceName);
  5380. pStats->Size = sizeof(NIC_STATISTICS);
  5381. if (NdisQueryStatistics (&UInterfaceName, pStats))
  5382. {
  5383. }
  5384. else
  5385. {
  5386. dwRetCode = GetLastError ();
  5387. TRACE2 (ANY, "ElGetInterfaceNdisStatistics: NdisQueryStatistics failed with error (%ld), Interface=(%ws)",
  5388. dwRetCode, UInterfaceName.Buffer);
  5389. }
  5390. }
  5391. while (FALSE);
  5392. if (pwszDeviceInterfaceName != NULL)
  5393. {
  5394. FREE (pwszDeviceInterfaceName);
  5395. }
  5396. return dwRetCode;
  5397. }
  5398. //
  5399. // ElCheckUserLoggedOn
  5400. //
  5401. // Function to query if interactive user has logged on prior to service start
  5402. //
  5403. // Input arguments:
  5404. // None
  5405. //
  5406. // Return values:
  5407. // NO_ERROR - success
  5408. // non-zero - error
  5409. //
  5410. DWORD
  5411. ElCheckUserLoggedOn (
  5412. )
  5413. {
  5414. BOOLEAN fDecrWorkerThreadCount = TRUE;
  5415. HANDLE hUserToken = NULL;
  5416. PWTS_SESSION_INFO pSessionInfo = NULL;
  5417. WTS_SESSION_INFO SessionInfo;
  5418. BOOL fFoundActiveConsoleId = FALSE;
  5419. DWORD dwCount = 0;
  5420. DWORD dwSession;
  5421. PVOID pvBuffer = NULL;
  5422. DWORD dwRetCode = NO_ERROR;
  5423. InterlockedIncrement (&g_lWorkerThreads);
  5424. do
  5425. {
  5426. TRACE1 (ANY, "ElCheckUserLoggedOn: ActiveConsoleId = (%ld)",
  5427. USER_SHARED_DATA->ActiveConsoleId);
  5428. if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &dwCount))
  5429. {
  5430. TRACE1 (ANY, "ElCheckUserLoggedOn: WTSEnumerateSessions, count = (%ld)",
  5431. dwCount);
  5432. for (dwSession = 0; dwSession < dwCount; dwSession++)
  5433. {
  5434. SessionInfo = pSessionInfo[dwSession];
  5435. TRACE2 (ANY, "ElCheckUserLoggedOn: WTSEnumerateSessions: enumerating SessionId =(%ld), State =(%ld)",
  5436. SessionInfo.SessionId, SessionInfo.State);
  5437. // Check if the user is active or connected
  5438. if ((SessionInfo.State != WTSActive) && (SessionInfo.State != WTSConnected))
  5439. {
  5440. continue;
  5441. }
  5442. // Check if user has actually logged in
  5443. if (ElGetWinStationUserToken (dwSession, &hUserToken) != NO_ERROR)
  5444. {
  5445. continue;
  5446. }
  5447. if (dwSession == USER_SHARED_DATA->ActiveConsoleId)
  5448. {
  5449. fFoundActiveConsoleId = TRUE;
  5450. g_dwCurrentSessionId = dwSession;
  5451. g_fUserLoggedOn = TRUE;
  5452. TRACE1 (ANY, "ElCheckUserLoggedOn: Session (%ld) is active console id",
  5453. dwSession);
  5454. break;
  5455. }
  5456. else
  5457. {
  5458. if (hUserToken != NULL)
  5459. {
  5460. CloseHandle (hUserToken);
  5461. hUserToken = NULL;
  5462. }
  5463. }
  5464. }
  5465. WTSFreeMemory(pSessionInfo);
  5466. }
  5467. else
  5468. {
  5469. dwRetCode = GetLastError ();
  5470. if (dwRetCode == RPC_S_INVALID_BINDING) //Due to Terminal Services Disabled
  5471. {
  5472. // Check if we can get user token for SessionId 0
  5473. if (ElGetWinStationUserToken (0, &hUserToken) == NO_ERROR)
  5474. {
  5475. fFoundActiveConsoleId = TRUE;
  5476. g_dwCurrentSessionId = 0;
  5477. g_fUserLoggedOn = TRUE;
  5478. TRACE0 (ANY, "ElCheckUserLoggedOn: Session 0 is active console id");
  5479. }
  5480. }
  5481. else
  5482. {
  5483. TRACE1 (ANY, "ElCheckUserLoggedOn: WTSEnumerateSessions failed with error (%ld)",
  5484. dwRetCode);
  5485. }
  5486. }
  5487. }
  5488. while (FALSE);
  5489. if (hUserToken != NULL)
  5490. {
  5491. CloseHandle (hUserToken);
  5492. }
  5493. if (dwRetCode != NO_ERROR)
  5494. {
  5495. if (pvBuffer != NULL)
  5496. {
  5497. FREE (pvBuffer);
  5498. }
  5499. }
  5500. if (fDecrWorkerThreadCount)
  5501. {
  5502. InterlockedDecrement (&g_lWorkerThreads);
  5503. }
  5504. return dwRetCode;
  5505. }
  5506. typedef HRESULT (APIENTRY *GETCLIENTADVISES)(LPWSTR**, LPDWORD);
  5507. //
  5508. // ElCheckUserModuleReady
  5509. //
  5510. // Function to query if interactive user context for current
  5511. // interactive session is ready to be notified
  5512. //
  5513. // Input arguments:
  5514. // None
  5515. //
  5516. // Return values:
  5517. // NO_ERROR - success
  5518. // non-zero - error
  5519. //
  5520. DWORD
  5521. ElCheckUserModuleReady (
  5522. )
  5523. {
  5524. HANDLE hToken = NULL;
  5525. WCHAR *pwszActiveUserName = NULL;
  5526. LPWSTR *ppwszAdviseUsers = NULL;
  5527. DWORD dwCount = 0, dwIndex = 0;
  5528. HMODULE hLib = NULL;
  5529. PWCHAR pwszNetmanDllExpandedPath = NULL;
  5530. DWORD cbSize = 0;
  5531. GETCLIENTADVISES pGetClientAdvises = NULL;
  5532. HRESULT hr = S_OK;
  5533. DWORD dwRetCode = NO_ERROR;
  5534. do
  5535. {
  5536. // Try only if user has logged on
  5537. if (g_dwCurrentSessionId != 0xffffffff)
  5538. {
  5539. if ((dwRetCode = ElGetWinStationUserToken (g_dwCurrentSessionId, &hToken))
  5540. != NO_ERROR)
  5541. {
  5542. TRACE1 (NOTIFY, "ElCheckUserModuleReady: ElGetWinStationUserToken failed with error %ld",
  5543. dwRetCode);
  5544. break;
  5545. }
  5546. if ((dwRetCode = ElGetLoggedOnUserName (hToken, &pwszActiveUserName))
  5547. != NO_ERROR)
  5548. {
  5549. TRACE1 (NOTIFY, "ElCheckUserModuleReady: ElGetLoggedOnUserName failed with error %ld",
  5550. dwRetCode);
  5551. break;
  5552. }
  5553. // Replace the %SystemRoot% with the actual path.
  5554. cbSize = ExpandEnvironmentStrings (NETMAN_DLL_PATH, NULL, 0);
  5555. if (cbSize == 0)
  5556. {
  5557. dwRetCode = GetLastError();
  5558. break;
  5559. }
  5560. pwszNetmanDllExpandedPath = (LPWSTR) MALLOC (cbSize*sizeof(WCHAR));
  5561. if (pwszNetmanDllExpandedPath == (LPWSTR)NULL)
  5562. {
  5563. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  5564. break;
  5565. }
  5566. cbSize = ExpandEnvironmentStrings (NETMAN_DLL_PATH,
  5567. pwszNetmanDllExpandedPath,
  5568. cbSize);
  5569. if (cbSize == 0)
  5570. {
  5571. dwRetCode = GetLastError();
  5572. break;
  5573. }
  5574. hLib = LoadLibrary (pwszNetmanDllExpandedPath);
  5575. if (hLib == NULL)
  5576. {
  5577. dwRetCode = GetLastError ();
  5578. TRACE2 (NOTIFY, "ElCheckUserModuleReady: LoadLibrary for (%ws) failed with error %ld",
  5579. NETMAN_DLL_PATH, dwRetCode);
  5580. break;
  5581. }
  5582. if ((pGetClientAdvises = (GETCLIENTADVISES)GetProcAddress (hLib, "GetClientAdvises")) == NULL)
  5583. {
  5584. dwRetCode = GetLastError ();
  5585. TRACE1 (NOTIFY, "ElCheckUserModuleReady: GetProcAddress failed with error %ld",
  5586. dwRetCode);
  5587. break;
  5588. }
  5589. hr = (* pGetClientAdvises) (&ppwszAdviseUsers, &dwCount);
  5590. if (FAILED(hr))
  5591. {
  5592. TRACE1 (NOTIFY, "ElCheckUserModuleReady: GetClientAdvises failed with error %0lx",
  5593. hr);
  5594. break;
  5595. }
  5596. for (dwIndex = 0; dwIndex < dwCount; dwIndex++)
  5597. {
  5598. TRACE2 (NOTIFY, "ElCheckUserModuleReady: Advise[%ld] = %ws", dwIndex, ppwszAdviseUsers[dwIndex]);
  5599. if (!wcscmp (ppwszAdviseUsers[dwIndex], pwszActiveUserName))
  5600. {
  5601. TRACE1 (NOTIFY, "ElCheckUserModuleReady: Tray icon ready for username %ws",
  5602. ppwszAdviseUsers[dwIndex]);
  5603. g_fTrayIconReady = TRUE;
  5604. break;
  5605. }
  5606. }
  5607. if (!g_fTrayIconReady)
  5608. {
  5609. TRACE0 (NOTIFY, "ElCheckUserModuleReady: No appropriate advise found");
  5610. }
  5611. }
  5612. else
  5613. {
  5614. TRACE0 (NOTIFY, "ElCheckUserModuleReady: No user logged on");
  5615. }
  5616. }
  5617. while (FALSE);
  5618. if (hToken != NULL)
  5619. {
  5620. CloseHandle (hToken);
  5621. }
  5622. if (hLib != NULL)
  5623. {
  5624. FreeLibrary (hLib);
  5625. }
  5626. if (pwszNetmanDllExpandedPath != NULL)
  5627. {
  5628. FREE (pwszNetmanDllExpandedPath);
  5629. }
  5630. if (pwszActiveUserName != NULL)
  5631. {
  5632. FREE (pwszActiveUserName);
  5633. pwszActiveUserName = NULL;
  5634. }
  5635. if (ppwszAdviseUsers != NULL)
  5636. {
  5637. CoTaskMemFree (ppwszAdviseUsers);
  5638. }
  5639. return dwRetCode;
  5640. }
  5641. //
  5642. // ElGetWinStationUserToken
  5643. //
  5644. // Function to get the user token for specified session id
  5645. //
  5646. // Input arguments:
  5647. // dwSessionId - Session Id
  5648. // pUserToken - Pointer to user token
  5649. //
  5650. // Return values:
  5651. // NO_ERROR - success
  5652. // non-zero - error
  5653. //
  5654. DWORD
  5655. ElGetWinStationUserToken (
  5656. IN DWORD dwSessionId,
  5657. IN OUT PHANDLE pUserToken
  5658. )
  5659. {
  5660. HANDLE hUserToken = NULL;
  5661. HANDLE hImpersonationToken = NULL;
  5662. DWORD dwRetCode = NO_ERROR;
  5663. do
  5664. {
  5665. *pUserToken = NULL;
  5666. if (GetWinStationUserToken (dwSessionId, pUserToken))
  5667. {
  5668. // TRACE0 (ANY, "ElGetWinStationUserToken: GetWinStationUserToken successful");
  5669. }
  5670. else
  5671. {
  5672. dwRetCode = GetLastError();
  5673. TRACE2 (ANY, "ElGetWinStationUserToken: GetWinStationUserToken failed for SessionId (%ld) with error (%ld)",
  5674. dwSessionId, dwRetCode);
  5675. // if ((dwRetCode == RPC_S_INVALID_BINDING) && (dwSessionId == 0))
  5676. if (dwSessionId == 0)
  5677. {
  5678. dwRetCode = NO_ERROR;
  5679. *pUserToken = NULL;
  5680. hUserToken = GetCurrentUserTokenW (
  5681. L"WinSta0", TOKEN_ALL_ACCESS);
  5682. if (hUserToken == NULL)
  5683. {
  5684. dwRetCode = GetLastError();
  5685. TRACE1 (ANY, "ElGetWinStationUserToken: GetCurrentUserTokenW failed with error (%ld)",
  5686. dwRetCode);
  5687. break;
  5688. }
  5689. else
  5690. {
  5691. if (!DuplicateTokenEx (hUserToken, 0, NULL, SecurityImpersonation, TokenImpersonation, &hImpersonationToken))
  5692. {
  5693. dwRetCode = GetLastError();
  5694. TRACE1 (ANY, "ElGetWinStationUserToken: DuplicateTokenEx for sessionid 0 failed with error (%ld)",
  5695. dwRetCode);
  5696. break;
  5697. }
  5698. *pUserToken = hImpersonationToken;
  5699. // TRACE0 (ANY, "ElGetWinStationUserToken: GetCurrentUserTokenW succeeded");
  5700. }
  5701. }
  5702. else // (dwSessionId == 0)
  5703. {
  5704. TRACE2 (ANY, "ElGetWinStationUserToken: GetWinStationUserToken failed for session= (%ld) with error= (%ld)",
  5705. dwSessionId, dwRetCode);
  5706. }
  5707. }
  5708. if (pUserToken == NULL)
  5709. {
  5710. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  5711. TRACE0 (ANY, "ElGetWinStationUserToken: UserToken = NULL after fetching successfully\n");
  5712. break;
  5713. }
  5714. }
  5715. while (FALSE);
  5716. return dwRetCode;
  5717. }
  5718. #ifdef ZEROCONFIG_LINKED
  5719. //
  5720. // ElZeroConfigEvent
  5721. //
  5722. // Description:
  5723. //
  5724. // Callback function called by Zero-Config on media events
  5725. //
  5726. // Arguments:
  5727. // dwHandle - unique transaction id
  5728. // pwzcDeviceNotif - media specific identifier
  5729. // ndSSID - SSID of network currently associated to
  5730. // prdUserData - 802.1X data stored with zero-config
  5731. //
  5732. // Return values:
  5733. // NO_ERROR - Success
  5734. // non-zero - Error
  5735. //
  5736. DWORD
  5737. ElZeroConfigEvent (
  5738. IN DWORD dwHandle,
  5739. IN WCHAR *pwszGuid,
  5740. IN NDIS_802_11_SSID ndSSID,
  5741. IN PRAW_DATA prdUserData
  5742. )
  5743. {
  5744. WCHAR *pDummyPtr = NULL;
  5745. WCHAR cwsDummyBuffer[256];
  5746. DWORD dwEapTypeToBeUsed = DEFAULT_EAP_TYPE;
  5747. DWORD dwEapolEnabled = DEFAULT_EAPOL_STATE;
  5748. EAPOL_ZC_INTF ZCData, *pZCData = NULL;
  5749. DWORD dwEventStatus = 0;
  5750. EAPOL_INTF_PARAMS EapolIntfParams;
  5751. DWORD dwRetCode = NO_ERROR;
  5752. do
  5753. {
  5754. if (g_hEventTerminateEAPOL == NULL)
  5755. {
  5756. break;
  5757. }
  5758. if (!(g_dwModulesStarted & ALL_MODULES_STARTED))
  5759. {
  5760. TRACE0 (DEVICE, "ElZeroConfigEvent: Received notification before module started");
  5761. break;
  5762. }
  5763. if (( dwEventStatus = WaitForSingleObject (
  5764. g_hEventTerminateEAPOL,
  5765. 0)) == WAIT_FAILED)
  5766. {
  5767. dwRetCode = GetLastError ();
  5768. TRACE1 (ANY, "ElZeroConfigEvent: WaitForSingleObject failed with error %ld, Terminating !!!",
  5769. dwRetCode);
  5770. break;
  5771. }
  5772. if (dwEventStatus == WAIT_OBJECT_0)
  5773. {
  5774. dwRetCode = NO_ERROR;
  5775. TRACE0 (ANY, "ElZeroConfigEvent: g_hEventTerminateEAPOL already signaled, returning");
  5776. break;
  5777. }
  5778. // Verify if 802.1X can start on this interface
  5779. ZeroMemory ((BYTE *)&EapolIntfParams, sizeof(EAPOL_INTF_PARAMS));
  5780. if (prdUserData != NULL)
  5781. {
  5782. if ((prdUserData->dwDataLen >= sizeof (EAPOL_ZC_INTF))
  5783. && (prdUserData->pData != NULL))
  5784. {
  5785. // Extract information stored with Zero-Config
  5786. pZCData = (EAPOL_ZC_INTF *)prdUserData->pData;
  5787. }
  5788. }
  5789. memcpy (EapolIntfParams.bSSID, ndSSID.Ssid, ndSSID.SsidLength);
  5790. EapolIntfParams.dwSizeOfSSID = ndSSID.SsidLength;
  5791. EapolIntfParams.dwEapFlags = DEFAULT_EAP_STATE;
  5792. if ((dwRetCode = ElGetInterfaceParams (
  5793. pwszGuid,
  5794. &EapolIntfParams
  5795. )) != NO_ERROR)
  5796. {
  5797. TRACE2 (DEVICE, "ElZeroConfigEvent: ElGetInterfaceParams failed with error %ld for interface %ws",
  5798. dwRetCode, pwszGuid);
  5799. if (dwRetCode == ERROR_FILE_NOT_FOUND)
  5800. {
  5801. EapolIntfParams.dwEapFlags = DEFAULT_EAP_STATE;
  5802. EapolIntfParams.dwEapType = DEFAULT_EAP_TYPE;
  5803. }
  5804. else
  5805. {
  5806. break;
  5807. }
  5808. }
  5809. // Start 802.1X state machine
  5810. if ((dwRetCode = ElEnumAndOpenInterfaces (
  5811. 0,
  5812. pwszGuid,
  5813. dwHandle,
  5814. prdUserData
  5815. )) != NO_ERROR)
  5816. {
  5817. TRACE1 (DEVICE, "ElZeroConfigEvent: ElEnumAndOpenInterfaces failed with error %ld",
  5818. dwRetCode);
  5819. break;
  5820. }
  5821. if (!IS_EAPOL_ENABLED(EapolIntfParams.dwEapFlags))
  5822. {
  5823. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  5824. break;
  5825. }
  5826. }
  5827. while (FALSE);
  5828. // If not possible send RpcCmdInterface - WZCCMD_AUTH_DISABLED to
  5829. // Zero Config
  5830. if (dwRetCode != NO_ERROR)
  5831. {
  5832. ZeroMemory ((PVOID)&ZCData, sizeof(EAPOL_ZC_INTF));
  5833. ElZeroConfigNotify (
  5834. dwHandle,
  5835. WZCCMD_CFG_NOOP,
  5836. pwszGuid,
  5837. &ZCData
  5838. );
  5839. }
  5840. return dwRetCode;
  5841. }
  5842. //
  5843. // ElZeroConfigNotify
  5844. //
  5845. // Description:
  5846. //
  5847. // Function called to notify Zero-Config about 802.1X events
  5848. //
  5849. // Arguments:
  5850. // dwHandle - unique transaction id
  5851. // dwCmdCode -
  5852. // pwszGuid - Interface GUID
  5853. // pZCData - Data to be stored with ZC for next retry
  5854. //
  5855. // Return values:
  5856. // NO_ERROR - Success
  5857. // non-zero - Error
  5858. //
  5859. DWORD
  5860. ElZeroConfigNotify (
  5861. IN DWORD dwHandle,
  5862. IN DWORD dwCmdCode,
  5863. IN WCHAR *pwszGuid,
  5864. IN EAPOL_ZC_INTF *pZCData
  5865. )
  5866. {
  5867. RAW_DATA rdUserData;
  5868. DWORD dwRetCode = NO_ERROR;
  5869. TRACE3 (ANY, "ElZeroConfigNotify: Handle=(%ld), failcount=(%ld), lastauthtype=(%ld)",
  5870. dwHandle, pZCData->dwAuthFailCount, pZCData->PreviousAuthenticationType);
  5871. do
  5872. {
  5873. ZeroMemory ((PVOID)&rdUserData, sizeof (RAW_DATA));
  5874. rdUserData.dwDataLen = sizeof (EAPOL_ZC_INTF);
  5875. rdUserData.pData = MALLOC (rdUserData.dwDataLen);
  5876. if (rdUserData.pData == NULL)
  5877. {
  5878. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  5879. TRACE0 (ANY, "ElZeroConfigNotify: MALLOC failed for rdUserData.pData");
  5880. break;
  5881. }
  5882. memcpy (rdUserData.pData, (BYTE *)pZCData, sizeof (EAPOL_ZC_INTF));
  5883. if ((dwRetCode = RpcCmdInterface (
  5884. dwHandle,
  5885. dwCmdCode,
  5886. pwszGuid,
  5887. &rdUserData
  5888. )) != NO_ERROR)
  5889. {
  5890. TRACE1 (ANY, "ElZeroConfigNotify: RpcCmdInterface failed with error %ld",
  5891. dwRetCode);
  5892. break;
  5893. }
  5894. }
  5895. while (FALSE);
  5896. if (rdUserData.pData != NULL)
  5897. {
  5898. FREE (rdUserData.pData);
  5899. }
  5900. return dwRetCode;
  5901. }
  5902. #endif // ZEROCONFIG_LINKED
  5903. //
  5904. // ElNetmanNotify
  5905. //
  5906. // Description:
  5907. //
  5908. // Function to update status and display balloon with netman
  5909. //
  5910. // Arguments:
  5911. // pPCB - Pointer to PCB
  5912. //
  5913. // Return values:
  5914. // NO_ERROR - Success
  5915. // non-zero - Error
  5916. //
  5917. DWORD
  5918. ElNetmanNotify (
  5919. IN EAPOL_PCB *pPCB,
  5920. IN EAPOL_NCS_STATUS Status,
  5921. IN WCHAR *pwszDisplayMessage
  5922. )
  5923. {
  5924. GUID DeviceGuid;
  5925. WCHAR wcszDummy[]=L"EAPOL";
  5926. WCHAR * pwszBalloonMessage = NULL;
  5927. BSTR pwszDummy = NULL;
  5928. NETCON_STATUS ncsStatus = 0;
  5929. EAPOL_EAP_UI_CONTEXT *pEAPUIContext = NULL;
  5930. HRESULT hr = S_OK;
  5931. DWORD dwRetCode = NO_ERROR;
  5932. do
  5933. {
  5934. ElStringToGuid (pPCB->pwszDeviceGUID, &DeviceGuid);
  5935. if ((Status == EAPOL_NCS_NOTIFICATION) ||
  5936. (Status == EAPOL_NCS_AUTHENTICATION_FAILED))
  5937. {
  5938. if (Status == EAPOL_NCS_NOTIFICATION)
  5939. {
  5940. pwszBalloonMessage = pPCB->pwszEapReplyMessage;
  5941. }
  5942. pEAPUIContext = MALLOC (sizeof(EAPOL_EAP_UI_CONTEXT));
  5943. if (pEAPUIContext == NULL)
  5944. {
  5945. TRACE0 (USER, "ElNetmanNotify: MALLOC failed for pEAPUIContext");
  5946. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  5947. break;
  5948. }
  5949. if (Status == EAPOL_NCS_NOTIFICATION)
  5950. {
  5951. pEAPUIContext->dwEAPOLUIMsgType = EAPOLUI_EAP_NOTIFICATION;
  5952. }
  5953. else
  5954. {
  5955. pEAPUIContext->dwEAPOLUIMsgType = EAPOLUI_CREATEBALLOON;
  5956. }
  5957. wcsncpy (pEAPUIContext->wszGUID, pPCB->pwszDeviceGUID,
  5958. sizeof(pEAPUIContext->wszGUID));
  5959. // Do not increment invocation id, since these are notification
  5960. // balloons
  5961. pEAPUIContext->dwSessionId = g_dwCurrentSessionId;
  5962. pEAPUIContext->dwContextId = pPCB->dwUIInvocationId;
  5963. pEAPUIContext->dwEapId = pPCB->bCurrentEAPId;
  5964. pEAPUIContext->dwEapTypeId = pPCB->dwEapTypeToBeUsed;
  5965. if (pPCB->pwszSSID)
  5966. {
  5967. wcscpy (pEAPUIContext->wszSSID, pPCB->pwszSSID);
  5968. }
  5969. if (pPCB->pSSID)
  5970. {
  5971. pEAPUIContext->dwSizeOfSSID = pPCB->pSSID->SsidLength;
  5972. memcpy ((BYTE *)pEAPUIContext->bSSID, (BYTE *)pPCB->pSSID->Ssid,
  5973. NDIS_802_11_SSID_LEN-sizeof(ULONG));
  5974. }
  5975. // Post the message to netman
  5976. if ((dwRetCode = ElPostShowBalloonMessage (
  5977. pPCB,
  5978. sizeof(EAPOL_EAP_UI_CONTEXT),
  5979. (BYTE *)pEAPUIContext,
  5980. pwszBalloonMessage?(wcslen(pwszBalloonMessage)*sizeof(WCHAR)):0,
  5981. pwszBalloonMessage
  5982. )) != NO_ERROR)
  5983. {
  5984. TRACE1 (USER, "ElGetUserIdentity: ElPostShowBalloonMessage failed with error %ld",
  5985. dwRetCode);
  5986. break;
  5987. }
  5988. }
  5989. hr = S_OK;
  5990. if (Status != EAPOL_NCS_NOTIFICATION)
  5991. {
  5992. switch (pPCB->State)
  5993. {
  5994. case EAPOLSTATE_LOGOFF:
  5995. hr = S_FALSE;
  5996. break;
  5997. case EAPOLSTATE_DISCONNECTED:
  5998. hr = S_FALSE;
  5999. break;
  6000. case EAPOLSTATE_CONNECTING:
  6001. hr = S_FALSE;
  6002. break;
  6003. case EAPOLSTATE_ACQUIRED:
  6004. ncsStatus = NCS_CREDENTIALS_REQUIRED;
  6005. break;
  6006. case EAPOLSTATE_AUTHENTICATING:
  6007. ncsStatus = NCS_AUTHENTICATING;
  6008. break;
  6009. case EAPOLSTATE_HELD:
  6010. ncsStatus = NCS_AUTHENTICATION_FAILED;
  6011. break;
  6012. case EAPOLSTATE_AUTHENTICATED:
  6013. ncsStatus = NCS_AUTHENTICATION_SUCCEEDED;
  6014. break;
  6015. default:
  6016. hr = S_FALSE;
  6017. break;
  6018. }
  6019. if (SUCCEEDED (hr))
  6020. {
  6021. hr = WZCNetmanConnectionStatusChanged (
  6022. &DeviceGuid,
  6023. ncsStatus);
  6024. }
  6025. if (FAILED (hr))
  6026. {
  6027. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  6028. break;
  6029. }
  6030. }
  6031. }
  6032. while (FALSE);
  6033. if (pwszDummy != NULL)
  6034. {
  6035. SysFreeString (pwszDummy);
  6036. }
  6037. if (pEAPUIContext != NULL)
  6038. {
  6039. FREE (pEAPUIContext);
  6040. }
  6041. return dwRetCode;
  6042. }
  6043. //
  6044. // ElPostShowBalloonMessage
  6045. //
  6046. // Description:
  6047. //
  6048. // Function to display balloon on tray icon
  6049. //
  6050. // Arguments:
  6051. // pPCB - Pointer to PCB
  6052. // cbCookieLen - Cookie Length
  6053. // pbCookie - Pointer to cookie
  6054. // cbMessageLen - Message Length
  6055. // pbMessage - Pointer to message
  6056. //
  6057. // Return values:
  6058. // NO_ERROR - Success
  6059. // non-zero - Error
  6060. //
  6061. DWORD
  6062. ElPostShowBalloonMessage (
  6063. IN EAPOL_PCB *pPCB,
  6064. IN DWORD cbCookieLen,
  6065. IN BYTE *pbCookie,
  6066. IN DWORD cbMessageLen,
  6067. IN WCHAR *pwszMessage
  6068. )
  6069. {
  6070. GUID DeviceGuid;
  6071. BSTR pwszBalloonMessage = NULL;
  6072. WCHAR wcszDummy[] = L"Dummy";
  6073. BSTR pwszCookie = NULL;
  6074. HRESULT hr = S_OK;
  6075. DWORD dwRetCode = NO_ERROR;
  6076. do
  6077. {
  6078. ElStringToGuid (pPCB->pwszDeviceGUID, &DeviceGuid);
  6079. pwszCookie = SysAllocStringByteLen (pbCookie, cbCookieLen);
  6080. if (pwszCookie == NULL)
  6081. {
  6082. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  6083. break;
  6084. }
  6085. if (cbMessageLen != 0)
  6086. {
  6087. pwszBalloonMessage = SysAllocString (pwszMessage);
  6088. }
  6089. else
  6090. {
  6091. pwszBalloonMessage = SysAllocString (wcszDummy);
  6092. }
  6093. if (pwszBalloonMessage == NULL)
  6094. {
  6095. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  6096. break;
  6097. }
  6098. hr = WZCNetmanShowBalloon (
  6099. &DeviceGuid,
  6100. pwszCookie,
  6101. pwszBalloonMessage);
  6102. if (FAILED (hr))
  6103. {
  6104. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  6105. break;
  6106. }
  6107. }
  6108. while (FALSE);
  6109. if (pwszBalloonMessage != NULL)
  6110. {
  6111. SysFreeString (pwszBalloonMessage);
  6112. }
  6113. if (pwszCookie != NULL)
  6114. {
  6115. SysFreeString (pwszCookie);
  6116. }
  6117. return dwRetCode;
  6118. }
  6119. //
  6120. // ElProcessReauthResponse
  6121. //
  6122. // Description:
  6123. //
  6124. // Function to handle UI response for initiating re-auth
  6125. //
  6126. // Arguments:
  6127. //
  6128. // Return values:
  6129. //
  6130. //
  6131. DWORD
  6132. ElProcessReauthResponse (
  6133. IN EAPOL_EAP_UI_CONTEXT EapolUIContext,
  6134. IN EAPOLUI_RESP EapolUIResp
  6135. )
  6136. {
  6137. DWORD dwRetCode = NO_ERROR;
  6138. do
  6139. {
  6140. }
  6141. while (FALSE);
  6142. return dwRetCode;
  6143. }
  6144. //
  6145. // ElIPPnpWorker
  6146. //
  6147. // Description:
  6148. //
  6149. // Function to renew address on a particular interface
  6150. //
  6151. // Arguments:
  6152. // pvContext - GUID string for the intended interface
  6153. //
  6154. // Return values:
  6155. //
  6156. //
  6157. DWORD
  6158. WINAPI
  6159. ElIPPnPWorker (
  6160. IN PVOID pvContext
  6161. )
  6162. {
  6163. DHCP_PNP_CHANGE DhcpPnpChange;
  6164. WCHAR *pwszGUID = NULL;
  6165. DWORD dwRetCode = NO_ERROR;
  6166. do
  6167. {
  6168. if (pvContext == NULL)
  6169. {
  6170. break;
  6171. }
  6172. pwszGUID = (WCHAR *)pvContext;
  6173. // Call DHCP to do PnP
  6174. ZeroMemory(&DhcpPnpChange, sizeof(DHCP_PNP_CHANGE));
  6175. DhcpPnpChange.Version = DHCP_PNP_CHANGE_VERSION_0;
  6176. if ((dwRetCode = DhcpHandlePnPEvent(
  6177. 0,
  6178. DHCP_CALLER_TCPUI,
  6179. pwszGUID,
  6180. &DhcpPnpChange,
  6181. NULL)) != NO_ERROR)
  6182. {
  6183. TRACE1 (ANY, "ElIPPnPWorker: DHCPHandlePnPEvent returned error %ld",
  6184. dwRetCode);
  6185. // Ignore DHCP error, it's outside 802.1X logic
  6186. dwRetCode = NO_ERROR;
  6187. }
  6188. else
  6189. {
  6190. TRACE0 (EAPOL, "ElIPPnPWorker: DHCPHandlePnPEvent successful");
  6191. }
  6192. // Call IPv6 to renew this interface
  6193. dwRetCode = Ip6RenewInterface(pwszGUID);
  6194. if (dwRetCode != NO_ERROR)
  6195. {
  6196. TRACE1(EAPOL, "ElIPPnPWorker: Ip6RenewInterface returned error %ld",
  6197. dwRetCode);
  6198. // Failure not fatal! Stack might be uninstalled.
  6199. // Ignore IPv6 error, it's outside the 802.1x logic.
  6200. dwRetCode = NO_ERROR;
  6201. }
  6202. else
  6203. {
  6204. TRACE0(EAPOL, "ElIPPnPWorker: Ip6RenewInterface successful");
  6205. }
  6206. }
  6207. while (FALSE);
  6208. if (pvContext != NULL)
  6209. {
  6210. FREE (pvContext);
  6211. }
  6212. InterlockedDecrement (&g_lWorkerThreads);
  6213. return dwRetCode;
  6214. }
  6215. //
  6216. // ElUpdateRegistry
  6217. //
  6218. // Description:
  6219. //
  6220. // Function to modify keys left behind in earlier versions
  6221. //
  6222. // Arguments:
  6223. // None
  6224. //
  6225. // Return values:
  6226. // NO_ERROR - success
  6227. // !NO_ERROR - error
  6228. //
  6229. DWORD
  6230. ElUpdateRegistry (
  6231. )
  6232. {
  6233. DWORD dwRetCode = NO_ERROR;
  6234. do
  6235. {
  6236. if ((dwRetCode = ElRegistryUpdateXPBeta2 ()) != NO_ERROR)
  6237. {
  6238. TRACE1 (ANY, "ElUpdateRegistry: ElRegistryUpdateXPBeta2 failed with error %ld",
  6239. dwRetCode);
  6240. dwRetCode = NO_ERROR;
  6241. }
  6242. if ((dwRetCode = ElRegistryUpdateXPSP1 ()) != NO_ERROR)
  6243. {
  6244. TRACE1 (ANY, "ElUpdateRegistry: ElRegistryUpdateXPSP1 failed with error %ld",
  6245. dwRetCode);
  6246. dwRetCode = NO_ERROR;
  6247. }
  6248. }
  6249. while (FALSE);
  6250. return dwRetCode;
  6251. }
  6252. //
  6253. // ElRegistryUpdateXPBeta2
  6254. //
  6255. // Description:
  6256. //
  6257. // Function to cleanup keys left behind prior 2 Beta2
  6258. //
  6259. // Arguments:
  6260. // None
  6261. //
  6262. // Return values:
  6263. // NO_ERROR - success
  6264. // !NO_ERROR - error
  6265. //
  6266. DWORD
  6267. ElRegistryUpdateXPBeta2 (
  6268. )
  6269. {
  6270. HKEY hkey = NULL;
  6271. HKEY hkey1 = NULL;
  6272. DWORD dwDisposition;
  6273. DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwMaxValueLen = 0;
  6274. DWORD dwNumSubKeys = 0, dwMaxSubKeyLen = 0;
  6275. DWORD dwMaxValueName = 0;
  6276. DWORD dwNumValues1 = 0, dwMaxValueNameLen1 = 0, dwMaxValueLen1 = 0;
  6277. DWORD dwNumSubKeys1 = 0, dwMaxSubKeyLen1 = 0;
  6278. DWORD dwMaxValueName1 = 0;
  6279. LONG lIndex = 0, lIndex1 = 0;
  6280. BYTE *pbKeyBuf = NULL;
  6281. DWORD dwKeyBufLen = 0;
  6282. BYTE *pbKeyBuf1 = NULL;
  6283. DWORD dwKeyBufLen1 = 0;
  6284. WCHAR *pwszValueName = NULL;
  6285. LONG lError = ERROR_SUCCESS;
  6286. DWORD dwRetCode = ERROR_SUCCESS;
  6287. do
  6288. {
  6289. // Delete keys in HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
  6290. // with no "{"
  6291. // Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
  6292. if ((lError = RegOpenKeyEx (
  6293. HKEY_LOCAL_MACHINE,
  6294. cwszEapKeyEapolConn,
  6295. 0,
  6296. KEY_ALL_ACCESS,
  6297. &hkey
  6298. )) != ERROR_SUCCESS)
  6299. {
  6300. TRACE1 (ANY, "ElRegistryUpdateXPBeta2: Error in RegOpenKeyEx for base key, %ld",
  6301. lError);
  6302. dwRetCode = (DWORD)lError;
  6303. break;
  6304. }
  6305. if ((lError = RegQueryInfoKey (
  6306. hkey,
  6307. NULL,
  6308. NULL,
  6309. NULL,
  6310. &dwNumSubKeys,
  6311. &dwMaxSubKeyLen,
  6312. NULL,
  6313. NULL,
  6314. NULL,
  6315. NULL,
  6316. NULL,
  6317. NULL
  6318. )) != NO_ERROR)
  6319. {
  6320. dwRetCode = (DWORD)lError;
  6321. TRACE1 (ANY, "ElRegistryUpdateXPBeta2: RegQueryInfoKey failed with error %ld",
  6322. dwRetCode);
  6323. break;
  6324. }
  6325. dwMaxSubKeyLen++;
  6326. if ((pbKeyBuf = MALLOC (dwMaxSubKeyLen*sizeof(WCHAR))) == NULL)
  6327. {
  6328. TRACE0 (ANY, "ElRegistryUpdateXPBeta2: MALLOC failed for dwMaxSubKeyLen");
  6329. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  6330. break;
  6331. }
  6332. for (lIndex = (dwNumSubKeys-1); lIndex >= 0, dwNumSubKeys > 0; lIndex--)
  6333. {
  6334. dwKeyBufLen = dwMaxSubKeyLen;
  6335. ZeroMemory (pbKeyBuf, dwMaxSubKeyLen*sizeof(WCHAR));
  6336. if ((lError = RegEnumKey (
  6337. hkey,
  6338. lIndex,
  6339. (WCHAR *)pbKeyBuf,
  6340. dwKeyBufLen
  6341. )) != ERROR_SUCCESS)
  6342. {
  6343. TRACE1 (ANY, "ElRegistryUpdateXPBeta2: RegEnumValue failed with error %ld",
  6344. lError);
  6345. break;
  6346. }
  6347. // If the first character in the key is not a '{' delete it
  6348. if (wcsncmp ((WCHAR *)pbKeyBuf, L"{", 1))
  6349. {
  6350. if ((dwRetCode = SHDeleteKey (
  6351. hkey,
  6352. (WCHAR *)pbKeyBuf
  6353. )) != ERROR_SUCCESS)
  6354. {
  6355. TRACE2 (ANY, "ElRegistryUpdateXPBeta2: RegDelete of (%ws) failed with error %ld",
  6356. (WCHAR *)pbKeyBuf, dwRetCode);
  6357. dwRetCode = ERROR_SUCCESS;
  6358. }
  6359. continue;
  6360. }
  6361. // This is a "{GUID}" type key
  6362. // Delete all sub-keys under this
  6363. if ((lError = RegOpenKeyEx (
  6364. hkey,
  6365. (WCHAR *)pbKeyBuf,
  6366. 0,
  6367. KEY_ALL_ACCESS,
  6368. &hkey1
  6369. )) != ERROR_SUCCESS)
  6370. {
  6371. TRACE1 (ANY, "ElRegistryUpdateXPBeta2: Error in RegOpenKeyEx for hkey1, %ld",
  6372. lError);
  6373. dwRetCode = (DWORD)lError;
  6374. break;
  6375. }
  6376. do
  6377. {
  6378. if ((lError = RegQueryInfoKey (
  6379. hkey1,
  6380. NULL,
  6381. NULL,
  6382. NULL,
  6383. &dwNumSubKeys1,
  6384. &dwMaxSubKeyLen1,
  6385. NULL,
  6386. &dwNumValues1,
  6387. &dwMaxValueNameLen1,
  6388. &dwMaxValueLen1,
  6389. NULL,
  6390. NULL
  6391. )) != NO_ERROR)
  6392. {
  6393. dwRetCode = (DWORD)lError;
  6394. TRACE1 (ANY, "ElRegistryUpdateXPBeta2: RegQueryInfoKey failed with error %ld",
  6395. dwRetCode);
  6396. break;
  6397. }
  6398. dwMaxSubKeyLen1++;
  6399. if ((pbKeyBuf1 = MALLOC (dwMaxSubKeyLen1*sizeof(WCHAR))) == NULL)
  6400. {
  6401. TRACE0 (ANY, "ElRegistryUpdateXPBeta2: MALLOC failed for dwMaxSubKeyLen");
  6402. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  6403. break;
  6404. }
  6405. for (lIndex1 = (dwNumSubKeys1-1); lIndex1 >= 0, dwNumSubKeys1 > 0; lIndex1--)
  6406. {
  6407. dwKeyBufLen1 = dwMaxSubKeyLen1;
  6408. ZeroMemory (pbKeyBuf1, dwMaxSubKeyLen1*sizeof(WCHAR));
  6409. if ((lError = RegEnumKey (
  6410. hkey1,
  6411. lIndex1,
  6412. (WCHAR *)pbKeyBuf1,
  6413. dwKeyBufLen1
  6414. )) != ERROR_SUCCESS)
  6415. {
  6416. TRACE1 (ANY, "ElRegistryUpdateXPBeta2: RegEnumValue failed with error %ld",
  6417. lError);
  6418. break;
  6419. }
  6420. // Delete all sub-keys
  6421. if ((dwRetCode = SHDeleteKey (
  6422. hkey1,
  6423. (WCHAR *)pbKeyBuf1
  6424. )) != ERROR_SUCCESS)
  6425. {
  6426. TRACE2 (ANY, "ElRegistryUpdateXPBeta2: RegDelete of (%ws) failed with error %ld",
  6427. (WCHAR *)pbKeyBuf1, dwRetCode);
  6428. dwRetCode = ERROR_SUCCESS;
  6429. }
  6430. }
  6431. if (pbKeyBuf1 != NULL)
  6432. {
  6433. FREE (pbKeyBuf1);
  6434. pbKeyBuf1 = NULL;
  6435. }
  6436. if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS))
  6437. {
  6438. dwRetCode = (DWORD)lError;
  6439. TRACE1 (ANY, "ElRegistryUpdateXPBeta2: RegEnumKey failed with error %ld",
  6440. dwRetCode);
  6441. break;
  6442. }
  6443. else
  6444. {
  6445. lError = ERROR_SUCCESS;
  6446. }
  6447. // Delete all values with names "DefaultEapType", "EapolEnabled",
  6448. // "LastModifiedSSID"
  6449. dwMaxValueNameLen1++;
  6450. if ((pwszValueName = MALLOC (dwMaxValueNameLen1*sizeof(WCHAR))) == NULL)
  6451. {
  6452. TRACE0 (ANY, "ElRegistryUpdateXPBeta2: MALLOC failed for pwszValueName");
  6453. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  6454. break;
  6455. }
  6456. for (lIndex1 = (dwNumValues1-1); lIndex1 >= 0, dwNumValues1 > 0; lIndex1--)
  6457. {
  6458. dwMaxValueNameLen = dwMaxValueNameLen1;
  6459. ZeroMemory (pwszValueName, dwMaxValueNameLen1*sizeof(WCHAR));
  6460. if ((lError = RegEnumValue (
  6461. hkey1,
  6462. lIndex1,
  6463. pwszValueName,
  6464. &dwMaxValueNameLen,
  6465. NULL,
  6466. NULL,
  6467. NULL,
  6468. NULL
  6469. )) != ERROR_SUCCESS)
  6470. {
  6471. if (lError != ERROR_MORE_DATA)
  6472. {
  6473. break;
  6474. }
  6475. lError = ERROR_SUCCESS;
  6476. }
  6477. if ((!wcscmp (pwszValueName, cwszDefaultEAPType)) ||
  6478. (!wcscmp (pwszValueName, cwszEapolEnabled)) ||
  6479. (!wcscmp (pwszValueName, cwszLastUsedSSID)))
  6480. {
  6481. if ((lError = RegDeleteValue (
  6482. hkey1,
  6483. pwszValueName
  6484. )) != ERROR_SUCCESS)
  6485. {
  6486. TRACE1 (ANY, "ElRegistryUpdateXPBeta2: RegDeleteValue failed with error %ld",
  6487. lError);
  6488. lError = ERROR_SUCCESS;
  6489. }
  6490. }
  6491. }
  6492. if (pwszValueName != NULL)
  6493. {
  6494. FREE (pwszValueName);
  6495. pwszValueName = NULL;
  6496. }
  6497. if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS))
  6498. {
  6499. dwRetCode = (DWORD)lError;
  6500. TRACE1 (ANY, "ElRegistryUpdateXPBeta2: RegEnumValue failed with error %ld",
  6501. dwRetCode);
  6502. break;
  6503. }
  6504. else
  6505. {
  6506. lError = ERROR_SUCCESS;
  6507. }
  6508. }
  6509. while (FALSE);
  6510. if (hkey1 != NULL)
  6511. {
  6512. RegCloseKey (hkey1);
  6513. hkey1 = NULL;
  6514. }
  6515. }
  6516. if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS))
  6517. {
  6518. dwRetCode = (DWORD)lError;
  6519. TRACE1 (ANY, "ElRegistryUpdateXPBeta2: RegQueryInfoKey failed with error %ld",
  6520. dwRetCode);
  6521. break;
  6522. }
  6523. else
  6524. {
  6525. lError = ERROR_SUCCESS;
  6526. }
  6527. } while (FALSE);
  6528. if (hkey != NULL)
  6529. {
  6530. RegCloseKey (hkey);
  6531. }
  6532. if (hkey1 != NULL)
  6533. {
  6534. RegCloseKey (hkey1);
  6535. }
  6536. if (pbKeyBuf != NULL)
  6537. {
  6538. FREE (pbKeyBuf);
  6539. }
  6540. return dwRetCode;
  6541. }
  6542. BOOLEAN
  6543. IsSSIDPresentInWZCList (
  6544. PEAPOL_INTF_PARAMS pIntfParams,
  6545. PWZC_802_11_CONFIG_LIST pwzcCfgList
  6546. )
  6547. {
  6548. DWORD dwIndex = 0;
  6549. BOOLEAN fFound = FALSE;
  6550. do
  6551. {
  6552. for (dwIndex=0; dwIndex<pwzcCfgList->NumberOfItems; dwIndex++)
  6553. {
  6554. if (pwzcCfgList->Config[dwIndex].Ssid.SsidLength ==
  6555. pIntfParams->dwSizeOfSSID)
  6556. {
  6557. if (memcmp(pwzcCfgList->Config[dwIndex].Ssid.Ssid,
  6558. pIntfParams->bSSID,
  6559. pIntfParams->dwSizeOfSSID) == 0)
  6560. {
  6561. fFound = TRUE;
  6562. break;
  6563. }
  6564. }
  6565. }
  6566. }
  6567. while (FALSE);
  6568. return fFound;
  6569. }
  6570. DWORD
  6571. ElWZCCfgChangeHandler (
  6572. IN LPWSTR pwszGUID,
  6573. PWZC_802_11_CONFIG_LIST pwzcCfgList
  6574. )
  6575. {
  6576. HKEY hkey = NULL;
  6577. HKEY hkey1 = NULL;
  6578. DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwMaxValueLen = 0;
  6579. WCHAR *pwszValueName = NULL;
  6580. BYTE *pbValueBuf = NULL;
  6581. LONG lError = ERROR_SUCCESS;
  6582. LONG lIndex = 0;
  6583. DWORD dwValueData = 0;
  6584. EAPOL_INTF_PARAMS *pRegParams = NULL;
  6585. DWORD dwTempValueNameLen = 0;
  6586. BOOLEAN fFreeWZCCfgList = FALSE;
  6587. DWORD dwRetCode = NO_ERROR;
  6588. do
  6589. {
  6590. // Enumerate registry blobs
  6591. if (pwzcCfgList == NULL)
  6592. {
  6593. // Create structure with zero items in list
  6594. pwzcCfgList = (PWZC_802_11_CONFIG_LIST) MALLOC (sizeof(WZC_802_11_CONFIG_LIST));
  6595. if (pwzcCfgList == NULL)
  6596. {
  6597. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  6598. TRACE0 (ANY, "ElWZCCfgChangeHandler: pwzcCfgList = NULL");
  6599. break;
  6600. }
  6601. else
  6602. {
  6603. fFreeWZCCfgList = TRUE;
  6604. }
  6605. }
  6606. // Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
  6607. if ((lError = RegOpenKeyEx (
  6608. HKEY_LOCAL_MACHINE,
  6609. cwszEapKeyEapolConn,
  6610. 0,
  6611. KEY_ALL_ACCESS,
  6612. &hkey
  6613. )) != ERROR_SUCCESS)
  6614. {
  6615. TRACE1 (ANY, "ElWZCCfgChangeHandler: Error in RegOpenKeyEx for base key, %ld",
  6616. lError);
  6617. dwRetCode = (DWORD)lError;
  6618. break;
  6619. }
  6620. // Get handle to HKLM\Software\...\Interfaces\<GUID>
  6621. if ((lError = RegOpenKeyEx (
  6622. hkey,
  6623. pwszGUID,
  6624. 0,
  6625. KEY_ALL_ACCESS,
  6626. &hkey1
  6627. )) != ERROR_SUCCESS)
  6628. {
  6629. TRACE1 (ANY, "ElWZCCfgChangeHandler: Error in RegOpenKeyEx for GUID, %ld",
  6630. lError);
  6631. dwRetCode = (DWORD)lError;
  6632. break;
  6633. }
  6634. if ((lError = RegQueryInfoKey (
  6635. hkey1,
  6636. NULL,
  6637. NULL,
  6638. NULL,
  6639. NULL,
  6640. NULL,
  6641. NULL,
  6642. &dwNumValues,
  6643. &dwMaxValueNameLen,
  6644. &dwMaxValueLen,
  6645. NULL,
  6646. NULL
  6647. )) != NO_ERROR)
  6648. {
  6649. dwRetCode = (DWORD)lError;
  6650. TRACE1 (ANY, "ElWZCCfgChangeHandler: RegQueryInfoKey failed with error %ld",
  6651. dwRetCode);
  6652. break;
  6653. }
  6654. if ((pwszValueName = MALLOC ((dwMaxValueNameLen + 1) * sizeof (WCHAR))) == NULL)
  6655. {
  6656. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  6657. TRACE0 (ANY, "ElWZCCfgChangeHandler: MALLOC failed for pwszValueName");
  6658. break;
  6659. }
  6660. dwMaxValueNameLen++;
  6661. if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL)
  6662. {
  6663. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  6664. TRACE0 (ANY, "ElWZCCfgChangeHandler: MALLOC failed for pbValueBuf");
  6665. break;
  6666. }
  6667. for (lIndex = (dwNumValues-1); lIndex >= 0, dwNumValues > 0; lIndex--)
  6668. {
  6669. dwValueData = dwMaxValueLen;
  6670. dwTempValueNameLen = dwMaxValueNameLen;
  6671. if ((lError = RegEnumValue (
  6672. hkey1,
  6673. lIndex,
  6674. pwszValueName,
  6675. &dwTempValueNameLen,
  6676. NULL,
  6677. NULL,
  6678. pbValueBuf,
  6679. &dwValueData
  6680. )) != ERROR_SUCCESS)
  6681. {
  6682. break;
  6683. }
  6684. if (dwValueData < sizeof (EAPOL_INTF_PARAMS))
  6685. {
  6686. TRACE0 (ANY, "ElWZCCfgChangeHandler: dwValueData < sizeof (EAPOL_INTF_PARAMS)");
  6687. lError = ERROR_INVALID_DATA;
  6688. break;
  6689. }
  6690. pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
  6691. // Ignore default setting since this is needed
  6692. if ((memcmp (pRegParams->bSSID, g_bDefaultSSID, MAX_SSID_LEN)) == 0)
  6693. {
  6694. continue;
  6695. }
  6696. // If SSID corresponding to registry blob is not found in
  6697. // WZC list, delete it
  6698. if (!IsSSIDPresentInWZCList (pRegParams,
  6699. pwzcCfgList
  6700. ))
  6701. {
  6702. // Delete Registry Value
  6703. if ((lError = RegDeleteValue (
  6704. hkey1,
  6705. pwszValueName
  6706. )) != ERROR_SUCCESS)
  6707. {
  6708. TRACE1 (ANY, "ElWZCCfgChangeHandler: RegDeleteValue failed with error (%ld)",
  6709. lError);
  6710. lError = ERROR_SUCCESS;
  6711. }
  6712. }
  6713. }
  6714. if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS))
  6715. {
  6716. dwRetCode = (DWORD)lError;
  6717. break;
  6718. }
  6719. else
  6720. {
  6721. lError = ERROR_SUCCESS;
  6722. }
  6723. }
  6724. while (FALSE);
  6725. if (hkey != NULL)
  6726. {
  6727. RegCloseKey (hkey);
  6728. }
  6729. if (hkey1 != NULL)
  6730. {
  6731. RegCloseKey (hkey1);
  6732. }
  6733. if (pbValueBuf != NULL)
  6734. {
  6735. FREE (pbValueBuf);
  6736. }
  6737. if (pwszValueName != NULL)
  6738. {
  6739. FREE (pwszValueName);
  6740. }
  6741. if (fFreeWZCCfgList)
  6742. {
  6743. FREE (pwzcCfgList);
  6744. }
  6745. return dwRetCode;
  6746. }
  6747. //
  6748. // ElRegistryUpdateXPSP1
  6749. //
  6750. // Description:
  6751. //
  6752. // Function to modify 802.1X settings created prior to SP1. This will disable
  6753. // 802.1x on all existing configurations. 802.1x, if required, will have to
  6754. // be enabled by the user on the existing connection.
  6755. //
  6756. // Arguments:
  6757. // None
  6758. //
  6759. // Return values:
  6760. // NO_ERROR - success
  6761. // !NO_ERROR - error
  6762. //
  6763. DWORD
  6764. ElRegistryUpdateXPSP1 (
  6765. )
  6766. {
  6767. HKEY hkey = NULL;
  6768. HKEY hkey1 = NULL;
  6769. DWORD dwNumValues=0, dwMaxValueNameLen=0, dwMaxValueLen=0;
  6770. WCHAR *pwszValueName=NULL;
  6771. WCHAR wszGUID[GUID_STRING_LEN_WITH_TERM];
  6772. WCHAR *pwszGUID = NULL;
  6773. DWORD dwSubKeys=0, dwSubKeyLen = 0;
  6774. BYTE *pbValueBuf = NULL;
  6775. LONG lError = ERROR_SUCCESS;
  6776. LONG lKey=0, lIndex=0;
  6777. DWORD dwValueData=0;
  6778. EAPOL_INTF_PARAMS *pRegParams = NULL;
  6779. DWORD dwTempValueNameLen=0;
  6780. DWORD dwRetCode = NO_ERROR;
  6781. do
  6782. {
  6783. // Enumerate registry blobs
  6784. // Get handle to HKLM\Software\Microsoft\EAPOL\Parameters\Interfaces
  6785. if ((lError = RegOpenKeyEx (
  6786. HKEY_LOCAL_MACHINE,
  6787. cwszEapKeyEapolConn,
  6788. 0,
  6789. KEY_ALL_ACCESS,
  6790. &hkey
  6791. )) != ERROR_SUCCESS)
  6792. {
  6793. TRACE1 (ANY, "ElRegistryUpdateXPSP1: Error in RegOpenKeyEx for base key, %ld",
  6794. lError);
  6795. dwRetCode = (DWORD)lError;
  6796. break;
  6797. }
  6798. if ((lError = RegQueryInfoKey (
  6799. hkey,
  6800. NULL,
  6801. NULL,
  6802. NULL,
  6803. &dwSubKeys,
  6804. &dwSubKeyLen,
  6805. NULL,
  6806. NULL,
  6807. NULL,
  6808. NULL,
  6809. NULL,
  6810. NULL
  6811. )) != NO_ERROR)
  6812. {
  6813. dwRetCode = (DWORD)lError;
  6814. TRACE1 (ANY, "ElRegistryUpdateXPSP1: RegQueryInfoKey hkey failed with error %ld",
  6815. dwRetCode);
  6816. break;
  6817. }
  6818. for (lKey = (dwSubKeys-1); lKey >= 0, dwSubKeys > 0; lKey--)
  6819. {
  6820. ZeroMemory (&wszGUID[0], GUID_STRING_LEN_WITH_TERM*sizeof(WCHAR));
  6821. pwszGUID = &wszGUID[0];
  6822. dwSubKeyLen = GUID_STRING_LEN_WITH_TERM;
  6823. if ((lError = RegEnumKeyEx (
  6824. hkey,
  6825. lKey,
  6826. pwszGUID,
  6827. &dwSubKeyLen,
  6828. NULL,
  6829. NULL,
  6830. NULL,
  6831. NULL
  6832. )) != ERROR_SUCCESS)
  6833. {
  6834. break;
  6835. }
  6836. if (dwSubKeyLen < (GUID_STRING_LEN_WITH_TERM - 1))
  6837. {
  6838. TRACE0 (ANY, "ElRegistryUpdateXPSP1: dwValueData < sizeof (EAPOL_INTF_PARAMS)");
  6839. lError = ERROR_INVALID_DATA;
  6840. break;
  6841. }
  6842. if (hkey1)
  6843. {
  6844. RegCloseKey (hkey1);
  6845. hkey1 = NULL;
  6846. }
  6847. // Get handle to HKLM\Software\...\Interfaces\<GUID>
  6848. if ((lError = RegOpenKeyEx (
  6849. hkey,
  6850. pwszGUID,
  6851. 0,
  6852. KEY_ALL_ACCESS,
  6853. &hkey1
  6854. )) != ERROR_SUCCESS)
  6855. {
  6856. TRACE1 (ANY, "ElRegistryUpdateXPSP1: Error in RegOpenKeyEx for GUID, %ld",
  6857. lError);
  6858. break;
  6859. }
  6860. dwNumValues = 0;
  6861. dwMaxValueNameLen = 0;
  6862. if ((lError = RegQueryInfoKey (
  6863. hkey1,
  6864. NULL,
  6865. NULL,
  6866. NULL,
  6867. NULL,
  6868. NULL,
  6869. NULL,
  6870. &dwNumValues,
  6871. &dwMaxValueNameLen,
  6872. &dwMaxValueLen,
  6873. NULL,
  6874. NULL
  6875. )) != NO_ERROR)
  6876. {
  6877. TRACE1 (ANY, "ElRegistryUpdateXPSP1: RegQueryInfoKey failed with error %ld",
  6878. lError);
  6879. break;
  6880. }
  6881. if (pwszValueName)
  6882. {
  6883. FREE (pwszValueName);
  6884. pwszValueName = NULL;
  6885. }
  6886. if (pbValueBuf)
  6887. {
  6888. FREE (pbValueBuf);
  6889. pbValueBuf = NULL;
  6890. }
  6891. if ((pwszValueName = MALLOC ((dwMaxValueNameLen + 1) * sizeof (WCHAR))) == NULL)
  6892. {
  6893. lError = dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  6894. TRACE0 (ANY, "ElRegistryUpdateXPSP1: MALLOC failed for pwszValueName");
  6895. break;
  6896. }
  6897. dwMaxValueNameLen++;
  6898. if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL)
  6899. {
  6900. lError = dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  6901. TRACE0 (ANY, "ElRegistryUpdateXPSP1: MALLOC failed for pbValueBuf");
  6902. break;
  6903. }
  6904. for (lIndex = (dwNumValues-1); lIndex >= 0, dwNumValues > 0; lIndex--)
  6905. {
  6906. dwValueData = dwMaxValueLen;
  6907. dwTempValueNameLen = dwMaxValueNameLen;
  6908. if ((lError = RegEnumValue (
  6909. hkey1,
  6910. lIndex,
  6911. pwszValueName,
  6912. &dwTempValueNameLen,
  6913. NULL,
  6914. NULL,
  6915. pbValueBuf,
  6916. &dwValueData
  6917. )) != ERROR_SUCCESS)
  6918. {
  6919. break;
  6920. }
  6921. if (dwValueData < sizeof (EAPOL_INTF_PARAMS))
  6922. {
  6923. TRACE0 (ANY, "ElRegistryUpdateXPSP1: dwValueData < sizeof (EAPOL_INTF_PARAMS)");
  6924. lError = ERROR_INVALID_DATA;
  6925. break;
  6926. }
  6927. pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
  6928. if (pRegParams->dwVersion != EAPOL_CURRENT_VERSION)
  6929. {
  6930. pRegParams->dwVersion = EAPOL_CURRENT_VERSION;
  6931. if ((dwRetCode = ElSetInterfaceParams (
  6932. pwszGUID,
  6933. pRegParams
  6934. )) != NO_ERROR)
  6935. {
  6936. TRACE1 (PORT, "ElRegistryUpdateXPSP1: ElSetInterfaceParams failed with error %ld, continuing",
  6937. dwRetCode);
  6938. dwRetCode = NO_ERROR;
  6939. }
  6940. }
  6941. }
  6942. if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS))
  6943. {
  6944. TRACE1 (ANY, "ElRegistryUpdateXPSP1: RegEnumValue hkey1 failed with error (%ld)",
  6945. lError);
  6946. dwRetCode = (DWORD)lError;
  6947. break;
  6948. }
  6949. else
  6950. {
  6951. lError = ERROR_SUCCESS;
  6952. }
  6953. }
  6954. if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS))
  6955. {
  6956. dwRetCode = (DWORD)lError;
  6957. break;
  6958. }
  6959. else
  6960. {
  6961. lError = ERROR_SUCCESS;
  6962. }
  6963. }
  6964. while (FALSE);
  6965. if (hkey != NULL)
  6966. {
  6967. RegCloseKey (hkey);
  6968. }
  6969. if (hkey1 != NULL)
  6970. {
  6971. RegCloseKey (hkey1);
  6972. }
  6973. if (pbValueBuf != NULL)
  6974. {
  6975. FREE (pbValueBuf);
  6976. }
  6977. if (pwszValueName != NULL)
  6978. {
  6979. FREE (pwszValueName);
  6980. }
  6981. return dwRetCode;
  6982. }