Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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