Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2019 lines
57 KiB

  1. /*++
  2. Copyright (c) 2000, Microsoft Corporation
  3. Module Name:
  4. eleap.c
  5. Abstract:
  6. Module that will do interfacing between the EAPOL engine and the EAP
  7. implementations
  8. Revision History:
  9. sachins, May 04 2000, Created
  10. --*/
  11. #include "pcheapol.h"
  12. #pragma hdrstop
  13. #include <ntlsa.h>
  14. #include <ntmsv1_0.h>
  15. #include <ntsamp.h>
  16. #include <crypt.h>
  17. #include <raseapif.h>
  18. //
  19. // ElLoadEapDlls
  20. //
  21. // Description:
  22. //
  23. // Function called to load all the EAP dlls installed in the PPP
  24. // configuration in the registry
  25. //
  26. // Arguments:
  27. //
  28. // Return values:
  29. // NO_ERROR - success
  30. // non-zero - error
  31. //
  32. DWORD
  33. ElLoadEapDlls (
  34. VOID
  35. )
  36. {
  37. HKEY hKeyEap = (HKEY)NULL;
  38. LPWSTR pEapDllPath = (LPWSTR)NULL;
  39. LPWSTR pEapDllExpandedPath = (LPWSTR)NULL;
  40. HKEY hKeyEapDll = (HKEY)NULL;
  41. DWORD dwRetCode;
  42. DWORD dwNumSubKeys;
  43. DWORD dwMaxSubKeySize;
  44. DWORD dwNumValues;
  45. DWORD cbMaxValNameLen;
  46. DWORD cbMaxValueDataSize;
  47. DWORD dwRolesSupported = 0;
  48. DWORD dwSizeOfRolesSupported = 0;
  49. DWORD dwKeyIndex;
  50. WCHAR wchSubKeyName[200];
  51. HINSTANCE hInstance;
  52. FARPROC pRasEapGetInfo;
  53. PPP_EAP_INFO RasEapInfo = {0};
  54. DWORD cbSubKeyName;
  55. DWORD dwSecDescLen;
  56. DWORD cbSize;
  57. DWORD dwType;
  58. DWORD dwEapTypeId;
  59. //
  60. // Open the EAP key
  61. //
  62. dwRetCode = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  63. RAS_EAP_REGISTRY_LOCATION,
  64. 0,
  65. KEY_READ,
  66. &hKeyEap);
  67. if (dwRetCode != NO_ERROR)
  68. {
  69. TRACE1 (EAP,"ElLoadEapDlls: RegOpenKeyEx failed for HKLM\\RAS_EAP_REGISTRY_LOCATION with error = %ld",
  70. dwRetCode);
  71. return dwRetCode;
  72. }
  73. //
  74. // Find out how many EAP DLLs there are
  75. //
  76. dwRetCode = RegQueryInfoKey (
  77. hKeyEap,
  78. NULL,
  79. NULL,
  80. NULL,
  81. &dwNumSubKeys,
  82. &dwMaxSubKeySize,
  83. NULL,
  84. &dwNumValues,
  85. &cbMaxValNameLen,
  86. &cbMaxValueDataSize,
  87. NULL,
  88. NULL);
  89. if (dwRetCode != NO_ERROR)
  90. {
  91. TRACE1 (EAP,"ElLoadEapDlls: RegQueryInfoKey failed for HKLM\\RAS_EAP_REGISTRY_LOCATION with error = %ld",
  92. dwRetCode);
  93. RegCloseKey (hKeyEap);
  94. return dwRetCode;
  95. }
  96. //
  97. // Allocate space in the table to hold information for each one
  98. //
  99. g_pEapTable= (EAP_INFO*) MALLOC (sizeof(EAP_INFO)*dwNumSubKeys);
  100. if (g_pEapTable == NULL)
  101. {
  102. RegCloseKey (hKeyEap);
  103. return(GetLastError());
  104. }
  105. //
  106. // Read the registry to find out the various EAPs to load.
  107. //
  108. for (dwKeyIndex = 0; dwKeyIndex < dwNumSubKeys; dwKeyIndex++)
  109. {
  110. cbSubKeyName = sizeof(wchSubKeyName)/sizeof(WCHAR);
  111. dwRetCode = RegEnumKeyEx (
  112. hKeyEap,
  113. dwKeyIndex,
  114. wchSubKeyName,
  115. &cbSubKeyName,
  116. NULL,
  117. NULL,
  118. NULL,
  119. NULL);
  120. if ((dwRetCode != NO_ERROR) &&
  121. (dwRetCode != ERROR_NO_MORE_ITEMS))
  122. {
  123. TRACE1 (EAP,"ElLoadEapDlls: RegEnumKeyEx failed for HKLM\\RAS_EAP_REGISTRY_LOCATION with error = %ld",
  124. dwRetCode);
  125. break;
  126. }
  127. else
  128. {
  129. if (dwRetCode == ERROR_NO_MORE_ITEMS)
  130. {
  131. dwRetCode = NO_ERROR;
  132. break;
  133. }
  134. }
  135. do
  136. {
  137. dwRetCode = RegOpenKeyEx (
  138. hKeyEap,
  139. wchSubKeyName,
  140. 0,
  141. KEY_QUERY_VALUE,
  142. &hKeyEapDll);
  143. if (dwRetCode != NO_ERROR)
  144. {
  145. TRACE1 (EAP,"ElLoadEapDlls: RegOpenKeyEx failed for HKLM\\RAS_EAP_REGISTRY_LOCATION\\dll with error = %ld",
  146. dwRetCode);
  147. break;
  148. }
  149. //
  150. // Read in the role of the dll
  151. //
  152. dwRolesSupported = RAS_EAP_ROLE_AUTHENTICATEE;
  153. dwSizeOfRolesSupported = sizeof(DWORD);
  154. dwRetCode = RegQueryValueEx (
  155. hKeyEapDll,
  156. RAS_EAP_VALUENAME_ROLES_SUPPORTED,
  157. NULL,
  158. &dwType,
  159. (LPBYTE)&dwRolesSupported,
  160. &dwSizeOfRolesSupported);
  161. if (dwRetCode != NO_ERROR)
  162. {
  163. // If no key, then it is an old dll, assume it will work
  164. // for client
  165. if (dwRetCode == ERROR_FILE_NOT_FOUND)
  166. {
  167. dwRetCode = NO_ERROR;
  168. dwRolesSupported = RAS_EAP_ROLE_AUTHENTICATEE;
  169. }
  170. else
  171. {
  172. TRACE1 (EAP,"ElLoadEapDlls: RegQueryValueEx failed for hKeyEapDll\\RAS_EAP_VALUENAME_ROLES_SUPPORTED with error = %ld",
  173. dwRetCode);
  174. break;
  175. }
  176. }
  177. if (!(dwRolesSupported & RAS_EAP_ROLE_AUTHENTICATEE))
  178. {
  179. TRACE1 (EAP, "ElLoadEapDlls: RolesSupported = (%0lx), not Authenticatee type, ignoring dll",
  180. dwRolesSupported);
  181. break;
  182. }
  183. dwEapTypeId = _wtol (wchSubKeyName);
  184. //
  185. // Find out the size of the path value.
  186. //
  187. dwRetCode = RegQueryInfoKey (
  188. hKeyEapDll,
  189. NULL,
  190. NULL,
  191. NULL,
  192. NULL,
  193. NULL,
  194. NULL,
  195. NULL,
  196. &cbMaxValNameLen,
  197. &cbMaxValueDataSize,
  198. NULL,
  199. NULL
  200. );
  201. if (dwRetCode != NO_ERROR)
  202. {
  203. TRACE1 (EAP,"ElLoadEapDlls: RegQueryInfoKey failed for hKeyEapDll with error = %ld",
  204. dwRetCode);
  205. break;
  206. }
  207. //
  208. // Allocate space for path and add one for NULL terminator
  209. //
  210. cbMaxValueDataSize += sizeof (WCHAR);
  211. pEapDllPath = (LPWSTR) MALLOC (cbMaxValueDataSize);
  212. if (pEapDllPath == (LPWSTR)NULL)
  213. {
  214. dwRetCode = GetLastError();
  215. break;
  216. }
  217. //
  218. // Read in the path
  219. //
  220. dwRetCode = RegQueryValueEx (
  221. hKeyEapDll,
  222. RAS_EAP_VALUENAME_PATH,
  223. NULL,
  224. &dwType,
  225. (LPBYTE)pEapDllPath,
  226. &cbMaxValueDataSize);
  227. if (dwRetCode != NO_ERROR)
  228. {
  229. TRACE1 (EAP,"ElLoadEapDlls: RegQueryValueEx failed for hKeyEapDll\\RAS_EAP_VALUENAME_PATH with error = %ld",
  230. dwRetCode);
  231. break;
  232. }
  233. if ((dwType != REG_EXPAND_SZ) && (dwType != REG_SZ))
  234. {
  235. dwRetCode = ERROR_REGISTRY_CORRUPT;
  236. TRACE1 (EAP,"ElLoadEapDlls: Registry corrupt for hKeyEapDll\\RAS_EAP_VALUENAME_PATH with error = %ld",
  237. dwRetCode);
  238. break;
  239. }
  240. //
  241. // Replace the %SystemRoot% with the actual path.
  242. //
  243. cbSize = ExpandEnvironmentStrings (pEapDllPath, NULL, 0);
  244. if (cbSize == 0)
  245. {
  246. dwRetCode = GetLastError();
  247. break;
  248. }
  249. pEapDllExpandedPath = (LPWSTR) MALLOC (cbSize*sizeof(WCHAR));
  250. if (pEapDllExpandedPath == (LPWSTR)NULL)
  251. {
  252. dwRetCode = GetLastError();
  253. break;
  254. }
  255. cbSize = ExpandEnvironmentStrings (pEapDllPath,
  256. pEapDllExpandedPath,
  257. cbSize);
  258. if ( cbSize == 0 )
  259. {
  260. dwRetCode = GetLastError();
  261. break;
  262. }
  263. hInstance = LoadLibrary (pEapDllExpandedPath);
  264. if (hInstance == (HINSTANCE)NULL)
  265. {
  266. dwRetCode = GetLastError();
  267. TRACE2 (EAP,"ElLoadEapDlls: LoadLibrary for (%ws) failed with error = %ld",
  268. pEapDllExpandedPath, dwRetCode);
  269. break;
  270. }
  271. pRasEapGetInfo = GetProcAddress (hInstance, "RasEapGetInfo");
  272. if (pRasEapGetInfo == (FARPROC)NULL)
  273. {
  274. dwRetCode = GetLastError();
  275. TRACE1 (EAP,"ElLoadEapDlls: GetProcAddress failed with error = %ld",
  276. dwRetCode);
  277. break;
  278. }
  279. dwRetCode = (DWORD) (*pRasEapGetInfo) (dwEapTypeId,
  280. &RasEapInfo);
  281. if (dwRetCode != NO_ERROR)
  282. {
  283. TRACE1 (EAP,"ElLoadEapDlls: pRasEapGetInfo failed with error = %ld",
  284. dwRetCode);
  285. break;
  286. }
  287. if (RasEapInfo.RasEapInitialize != NULL)
  288. {
  289. dwRetCode = RasEapInfo.RasEapInitialize (
  290. TRUE);
  291. if (dwRetCode != NO_ERROR)
  292. {
  293. TRACE1 (EAP,"ElLoadEapDlls: RasEapInitialize failed with error = %ld",
  294. dwRetCode);
  295. break;
  296. }
  297. }
  298. g_pEapTable[g_dwNumEapProtocols].hInstance = hInstance;
  299. memcpy ((PVOID)&(g_pEapTable[g_dwNumEapProtocols].RasEapInfo),
  300. (PVOID)&RasEapInfo,
  301. sizeof(PPP_EAP_INFO));
  302. ZeroMemory ((PVOID)&RasEapInfo, sizeof(PPP_EAP_INFO));
  303. g_pEapTable[g_dwNumEapProtocols].RasEapInfo.dwSizeInBytes =
  304. sizeof(PPP_EAP_INFO);
  305. g_dwNumEapProtocols++;
  306. TRACE1 (EAP,"ElLoadEapDlls: Successfully loaded EAP DLL type id = %d",
  307. dwEapTypeId );
  308. } while (FALSE);
  309. if (dwRetCode != NO_ERROR)
  310. {
  311. if (hInstance != NULL)
  312. {
  313. FreeLibrary (hInstance);
  314. }
  315. hInstance = NULL;
  316. }
  317. if (hKeyEapDll != NULL)
  318. {
  319. RegCloseKey (hKeyEapDll);
  320. hKeyEapDll = (HKEY)NULL;
  321. }
  322. if (pEapDllExpandedPath != NULL)
  323. {
  324. FREE( pEapDllExpandedPath );
  325. pEapDllExpandedPath = NULL;
  326. }
  327. if (pEapDllPath != NULL)
  328. {
  329. FREE (pEapDllPath);
  330. pEapDllPath = (LPWSTR)NULL;
  331. }
  332. // Reset error code and continue loading next EAP Dll
  333. dwRetCode = NO_ERROR;
  334. }
  335. if (hKeyEap != (HKEY)NULL)
  336. {
  337. RegCloseKey (hKeyEap);
  338. }
  339. if (hKeyEapDll != (HKEY)NULL)
  340. {
  341. RegCloseKey (hKeyEapDll);
  342. }
  343. if (pEapDllPath != (LPWSTR)NULL)
  344. {
  345. FREE (pEapDllPath);
  346. }
  347. if (pEapDllExpandedPath != NULL)
  348. {
  349. FREE (pEapDllExpandedPath);
  350. }
  351. return dwRetCode;
  352. }
  353. //
  354. // ElEapInit
  355. //
  356. // Description:
  357. // Function called to initialize/uninitialize EAP module.
  358. // In the former case, fInitialize will be TRUE; in the latter case,
  359. // it will be FALSE.
  360. //
  361. // Arguments:
  362. // fInitialize - TRUE - initialize EAP
  363. // FALSE - uninitialize EAP
  364. //
  365. // Return values:
  366. // NO_ERROR - success
  367. // non-zero - error
  368. //
  369. DWORD
  370. ElEapInit (
  371. IN BOOL fInitialize
  372. )
  373. {
  374. DWORD dwRetCode = NO_ERROR;
  375. if (fInitialize)
  376. {
  377. // Initialize EAP globals
  378. g_dwNumEapProtocols = 0;
  379. g_pEapTable = NULL;
  380. g_dwEAPUIInvocationId = 1;
  381. if ((dwRetCode = ElLoadEapDlls()) != NO_ERROR)
  382. {
  383. if (g_pEapTable != NULL)
  384. {
  385. FREE (g_pEapTable);
  386. g_pEapTable = NULL;
  387. }
  388. g_dwNumEapProtocols = 0;
  389. return dwRetCode;
  390. }
  391. }
  392. else
  393. {
  394. if (g_pEapTable != NULL)
  395. {
  396. DWORD dwIndex;
  397. //
  398. // Unload loaded DLLs
  399. //
  400. for (dwIndex = 0; dwIndex < g_dwNumEapProtocols; dwIndex++)
  401. {
  402. if (g_pEapTable[dwIndex].hInstance != NULL)
  403. {
  404. if (g_pEapTable[dwIndex].RasEapInfo.RasEapInitialize !=
  405. NULL)
  406. {
  407. dwRetCode = g_pEapTable[dwIndex].RasEapInfo.
  408. RasEapInitialize (
  409. FALSE);
  410. if (dwRetCode != NO_ERROR)
  411. {
  412. TRACE2 (EAP,
  413. "RasEapInitialize(%d) failed and returned %d",
  414. g_pEapTable[dwIndex].RasEapInfo.dwEapTypeId,
  415. dwRetCode);
  416. }
  417. }
  418. FreeLibrary (g_pEapTable[dwIndex].hInstance);
  419. g_pEapTable[dwIndex].hInstance = NULL;
  420. }
  421. }
  422. FREE(g_pEapTable);
  423. g_pEapTable = NULL;
  424. }
  425. g_dwNumEapProtocols = 0;
  426. g_dwEAPUIInvocationId = 1;
  427. }
  428. return (NO_ERROR);
  429. }
  430. //
  431. // EapBegin
  432. //
  433. // Description:
  434. //
  435. // Function called by the EAPOL engine to initialize an EAP session for
  436. // a particular port.
  437. //
  438. // Arguments:
  439. // pPCB - Pointer to PCB for port on which EAP is to be initialized
  440. //
  441. // Return values:
  442. // NO_ERROR - success
  443. // non-zero - error
  444. //
  445. DWORD
  446. ElEapBegin (
  447. IN EAPOL_PCB *pPCB
  448. )
  449. {
  450. DWORD dwRetCode = NO_ERROR;
  451. TRACE0 (EAP,"ElEapBegin entered");
  452. if (pPCB->dwEapTypeToBeUsed != -1)
  453. {
  454. //
  455. // First check if we support this EAP type
  456. //
  457. if (ElGetEapTypeIndex((BYTE)(pPCB->dwEapTypeToBeUsed)) == -1)
  458. {
  459. TRACE0 (EAP, "ElEapBegin: EAPType not supported");
  460. return (ERROR_NOT_SUPPORTED);
  461. }
  462. }
  463. pPCB->fEapInitialized = TRUE;
  464. TRACE0 (EAP,"ElEapBegin done");
  465. return (NO_ERROR);
  466. }
  467. //
  468. // ElEapEnd
  469. //
  470. // Description:
  471. //
  472. // Function called to end the Eap session initiated by an ElEapBegin.
  473. // Called when port goes down
  474. //
  475. // Arguments:
  476. // pPCB - Pointer to the PCB for the port on which EAP session is to be
  477. // shut-down.
  478. //
  479. // Return values:
  480. // NO_ERROR - success
  481. // non-zero - error
  482. //
  483. DWORD
  484. ElEapEnd (
  485. IN EAPOL_PCB *pPCB
  486. )
  487. {
  488. DWORD dwRetCode = NO_ERROR;
  489. TRACE0 (EAP,"ElEapEnd entered");
  490. if ((pPCB == NULL) || (!(pPCB->fEapInitialized)))
  491. {
  492. return( NO_ERROR );
  493. }
  494. if ((dwRetCode = ElEapDllEnd (pPCB)) != NO_ERROR)
  495. {
  496. TRACE1 (EAP, "ElEapEnd: Error in ElEapDllEnd %ld", dwRetCode);
  497. }
  498. if (pPCB->EapUIData.pEapUIData != NULL)
  499. {
  500. FREE( pPCB->EapUIData.pEapUIData );
  501. pPCB->EapUIData.pEapUIData = NULL;
  502. }
  503. pPCB->fEapInitialized = FALSE;
  504. return (NO_ERROR);
  505. }
  506. //
  507. // ElEapExtractMessage
  508. //
  509. // Description:
  510. //
  511. // If there is any message in the Request/Notification packet, then
  512. // save the string in pResult->pszReplyMessage
  513. //
  514. // Arguments:
  515. // pReceiveBuf - Pointer to EAP packet received
  516. // pResult - Pointer to result structure
  517. //
  518. // Return values:
  519. //
  520. VOID
  521. ElEapExtractMessage (
  522. IN PPP_EAP_PACKET *pReceiveBuf,
  523. OUT ELEAP_RESULT *pResult
  524. )
  525. {
  526. DWORD dwNumBytes = 0;
  527. CHAR* pszReplyMessage = NULL;
  528. WORD cbPacket;
  529. do
  530. {
  531. cbPacket = WireToHostFormat16 (pReceiveBuf->Length);
  532. if (PPP_EAP_PACKET_HDR_LEN + 1 >= cbPacket)
  533. {
  534. TRACE2 (EAP, "ElEapExtractMessage: Packet length %ld less than minimum %ld",
  535. cbPacket, PPP_EAP_PACKET_HDR_LEN+1);
  536. break;
  537. }
  538. dwNumBytes = cbPacket - PPP_EAP_PACKET_HDR_LEN - 1;
  539. //
  540. // One more for the terminating NULL.
  541. //
  542. pszReplyMessage = (CHAR *) MALLOC (dwNumBytes+1);
  543. if (pszReplyMessage == NULL)
  544. {
  545. TRACE0 (EAP, "ElEapExtractMessage: MALLOC failed. Cannot extract server's message." );
  546. break;
  547. }
  548. CopyMemory (pszReplyMessage, pReceiveBuf->Data + 1, dwNumBytes);
  549. pszReplyMessage[dwNumBytes] = '\0';
  550. // FREE( pResult->pszReplyMessage );
  551. pResult->pszReplyMessage = pszReplyMessage;
  552. pszReplyMessage = NULL;
  553. } while (FALSE);
  554. return;
  555. }
  556. //
  557. // ElParseIdentityString
  558. //
  559. // Description:
  560. // Parse the identity string
  561. //
  562. // Arguments:
  563. // pReceiveBuf - Pointer to EAP packet received
  564. // pPCB - Pointer to PCB for port on which data is being processed
  565. //
  566. // Return values:
  567. //
  568. DWORD
  569. ElParseIdentityString (
  570. IN PPP_EAP_PACKET *pReceiveBuf,
  571. IN OUT EAPOL_PCB *pPCB
  572. )
  573. {
  574. DWORD dwNumBytes = 0;
  575. WORD cbPacket = 0;
  576. CHAR *pszLocalIdString = NULL;
  577. WCHAR *pwszLocalIdString = NULL;
  578. WCHAR *pwszDisplayString = NULL;
  579. WCHAR *pwszDisplayStringEnd = NULL;
  580. WCHAR *pwszTupleValueStart = NULL;
  581. WCHAR *pwszTupleTypeStart = NULL;
  582. WCHAR *pwszTupleTypeEnd = NULL;
  583. WCHAR *pwszTupleValueEnd = NULL;
  584. WCHAR *pwszNetworkId = NULL;
  585. DWORD dwNetworkIdLen = 0;
  586. WCHAR *pwszNASId = NULL;
  587. WCHAR *pwszPortId = NULL;
  588. WCHAR *pwczNetworkId = L"NetworkId";
  589. WCHAR *pwczNASId = L"NASId";
  590. WCHAR *pwczPortId = L"PortId";
  591. LOCATION_802_1X location;
  592. EAPOL_INTF_PARAMS EapolIntfParams;
  593. DWORD dwRetCode = NO_ERROR;
  594. do
  595. {
  596. cbPacket = WireToHostFormat16 (pReceiveBuf->Length);
  597. if (PPP_EAP_PACKET_HDR_LEN + 1 >= cbPacket)
  598. {
  599. TRACE2 (EAP, "ElParseIdentityString: Packet length %ld less than minimum %ld",
  600. cbPacket, PPP_EAP_PACKET_HDR_LEN+1);
  601. break;
  602. }
  603. dwNumBytes = cbPacket - PPP_EAP_PACKET_HDR_LEN - 1;
  604. pszLocalIdString = MALLOC (dwNumBytes + 2);
  605. if (pszLocalIdString == NULL)
  606. {
  607. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  608. TRACE0 (EAP, "ElParseIdentityString: MALLOC failed for pszLocalIdString");
  609. break;
  610. }
  611. pwszLocalIdString = MALLOC ((dwNumBytes + 2)*sizeof(WCHAR));
  612. if (pwszLocalIdString == NULL)
  613. {
  614. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  615. TRACE0 (EAP, "ElParseIdentityString: MALLOC failed for pwszLocalIdString");
  616. break;
  617. }
  618. memcpy (pszLocalIdString, pReceiveBuf->Data + 1, dwNumBytes);
  619. pszLocalIdString[dwNumBytes] = '\0';
  620. if (0 == MultiByteToWideChar (
  621. CP_ACP,
  622. 0,
  623. pszLocalIdString,
  624. dwNumBytes+1,
  625. pwszLocalIdString,
  626. dwNumBytes + 2))
  627. {
  628. dwRetCode = GetLastError();
  629. TRACE2 (EAP,"ElParseIdentityString: MultiByteToWideChar(%s) failed for pszLocalIdString with error (%ld)",
  630. pszLocalIdString,
  631. dwRetCode);
  632. break;
  633. }
  634. pwszDisplayStringEnd = wcschr (pwszLocalIdString, L'\0');
  635. if (pwszDisplayStringEnd == NULL)
  636. {
  637. dwRetCode = ERROR_INVALID_DATA;
  638. TRACE0 (EAP, "ElParseIdentityString: Identity string does not contain mandatory NULL character");
  639. break;
  640. }
  641. pwszDisplayString = MALLOC ((pwszDisplayStringEnd - pwszLocalIdString + 1) * sizeof(WCHAR));
  642. if (pwszDisplayString == NULL)
  643. {
  644. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  645. TRACE0 (EAP, "ElParseIdentityString: MALLOC failed for pwszDisplayString");
  646. break;
  647. }
  648. wcscpy (pwszDisplayString, pwszLocalIdString);
  649. TRACE1 (EAP, "ElParseIdentityString: DisplayString = %ws",
  650. pwszDisplayString);
  651. TRACE1 (EAP, "ElParseIdentityString: LocalIdString = %ws",
  652. pwszDisplayStringEnd+1);
  653. TRACE1 (EAP, "ElParseIdentityString: LocalIdString Length = %ld",
  654. dwNumBytes);
  655. // If only Display String is received, bail out
  656. if (pwszDisplayStringEnd == (pwszLocalIdString+dwNumBytes))
  657. {
  658. dwRetCode = NO_ERROR;
  659. TRACE0 (EAP, "ElParseIdentityString: Identity string does not contain tuples");
  660. break;
  661. }
  662. pwszTupleTypeStart = pwszDisplayStringEnd + 1;
  663. while (TRUE)
  664. {
  665. pwszTupleTypeEnd = wcschr (pwszTupleTypeStart, L'=');
  666. if (!(_wcsnicmp (pwszTupleTypeStart, pwczNetworkId, wcslen(pwczNetworkId))))
  667. {
  668. pwszTupleValueStart = pwszTupleTypeEnd + 1;
  669. pwszTupleValueEnd = wcschr (pwszTupleValueStart, L',');
  670. if (pwszTupleValueEnd == NULL)
  671. {
  672. // End-of-string
  673. pwszTupleValueEnd = &pwszLocalIdString[dwNumBytes];
  674. }
  675. TRACE1 (ANY, "ElParseIdentityString: NetworkID Size = %ld",
  676. pwszTupleValueEnd - pwszTupleValueStart + 1);
  677. pwszNetworkId =
  678. MALLOC ((pwszTupleValueEnd - pwszTupleValueStart + 1)*sizeof(WCHAR));
  679. if (pwszNetworkId == NULL)
  680. {
  681. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  682. TRACE0 (EAP, "ElParseIdentityString: MALLOC failed for pwszNetworkId");
  683. break;
  684. }
  685. memcpy ((VOID *)pwszNetworkId, (VOID *)pwszTupleValueStart, (pwszTupleValueEnd - pwszTupleValueStart)*sizeof(WCHAR));
  686. pwszNetworkId[pwszTupleValueEnd - pwszTupleValueStart] = L'\0';
  687. dwNetworkIdLen = (DWORD)(pwszTupleValueEnd - pwszTupleValueStart);
  688. TRACE1 (EAP, "Got NetworkId = %ws", pwszNetworkId);
  689. }
  690. else
  691. {
  692. if (!(_wcsnicmp (pwszTupleTypeStart, pwczNASId, wcslen (pwczNASId))))
  693. {
  694. pwszTupleValueStart = pwszTupleTypeEnd + 1;
  695. pwszTupleValueEnd = wcschr (pwszTupleValueStart, L',');
  696. if (pwszTupleValueEnd == NULL)
  697. {
  698. // End-of-string
  699. pwszTupleValueEnd = &pwszLocalIdString[dwNumBytes];
  700. }
  701. pwszNASId = MALLOC ((pwszTupleValueEnd - pwszTupleValueStart + 1) * sizeof(WCHAR));
  702. if (pwszNASId == NULL)
  703. {
  704. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  705. TRACE0 (EAP, "ElParseIdentityString: MALLOC failed for pwszNASId");
  706. break;
  707. }
  708. memcpy ((VOID *)pwszNASId, (VOID *)pwszTupleValueStart, (pwszTupleValueEnd - pwszTupleValueStart)*sizeof(WCHAR));
  709. pwszNASId[(pwszTupleValueEnd - pwszTupleValueStart)] = L'\0';
  710. TRACE1 (EAP, "Got NASId = %ws", pwszNASId);
  711. }
  712. else
  713. {
  714. if (!(_wcsnicmp (pwszTupleTypeStart, pwczPortId, wcslen (pwczPortId))))
  715. {
  716. pwszTupleValueStart = pwszTupleTypeEnd + 1;
  717. pwszTupleValueEnd = wcschr (pwszTupleValueStart, L',');
  718. if (pwszTupleValueEnd == NULL)
  719. {
  720. // End-of-string
  721. pwszTupleValueEnd = &pwszLocalIdString[dwNumBytes];
  722. }
  723. TRACE1 (EAP, "ElParseIdentityString: For PortId, length = %ld",
  724. pwszTupleValueEnd - pwszTupleValueStart);
  725. pwszPortId = MALLOC ((pwszTupleValueEnd - pwszTupleValueStart + 1) * sizeof(WCHAR));
  726. if (pwszPortId == NULL)
  727. {
  728. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  729. TRACE0 (EAP, "ElParseIdentityString: MALLOC failed for pwszPortId");
  730. break;
  731. }
  732. memcpy ((VOID *)pwszPortId, (VOID *)pwszTupleValueStart, (pwszTupleValueEnd - pwszTupleValueStart)*sizeof(WCHAR));
  733. pwszPortId[pwszTupleValueEnd - pwszTupleValueStart] = L'\0';
  734. TRACE1 (EAP, "Got PortId = %ws", pwszPortId);
  735. }
  736. else
  737. {
  738. dwRetCode = ERROR_INVALID_DATA;
  739. TRACE0 (EAP, "ElParseIdentityString: Invalid tuple type");
  740. break;
  741. }
  742. }
  743. }
  744. if (*pwszTupleValueEnd == L'\0')
  745. {
  746. TRACE0 (EAP, "ElParseIdentityString: End of String reached");
  747. break;
  748. }
  749. else
  750. {
  751. // Position pointer beyond ','
  752. pwszTupleTypeStart = pwszTupleValueEnd+1;
  753. }
  754. }
  755. TRACE0 (EAP, "ElParseIdentityString: Out of while loop");
  756. if (dwRetCode != NO_ERROR)
  757. {
  758. break;
  759. }
  760. TRACE0 (EAP, "ElParseIdentityString: Out of while loop: NO ERROR");
  761. // Mandatory tuples
  762. if (pwszNetworkId == NULL)
  763. {
  764. dwRetCode = ERROR_INVALID_DATA;
  765. TRACE0 (EAP, "ElParseIdentityString: Invalid NetworkId = NULL");
  766. break;
  767. }
  768. // Network is the SSID for wired networks
  769. if (pPCB->PhysicalMediumType != NdisPhysicalMediumWirelessLan)
  770. {
  771. pPCB->fAuthenticationOnNewNetwork = FALSE;
  772. // Free previous instance of SSID if any
  773. if (pPCB->pwszSSID != NULL)
  774. {
  775. // Verify if NetworkId has changed i.e. we are on a new network
  776. if (wcscmp (pPCB->pwszSSID, pwszNetworkId))
  777. {
  778. pPCB->fAuthenticationOnNewNetwork = TRUE;
  779. TRACE2 (EAP, "ElParseIdentityString: SSIDs are different, old= %ws, new= %ws",
  780. pPCB->pwszSSID, pwszNetworkId);
  781. }
  782. FREE (pPCB->pwszSSID);
  783. pPCB->pwszSSID = NULL;
  784. }
  785. // New instance of SSID will be freed either on receipt of next SSID
  786. // or user logoff
  787. pPCB->pwszSSID =
  788. (WCHAR *) MALLOC((wcslen(pwszNetworkId) + 1)*sizeof(WCHAR));
  789. if (pPCB->pwszSSID == NULL)
  790. {
  791. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  792. TRACE0 (EAP, "ElParseIdentityString: MALLOC failed. Cannot extract SSID" );
  793. break;
  794. }
  795. if (pPCB->pSSID)
  796. {
  797. FREE (pPCB->pSSID);
  798. pPCB->pSSID = NULL;
  799. }
  800. if ((dwNetworkIdLen > 0) && (dwNetworkIdLen <= MAX_SSID_LEN))
  801. {
  802. if ((pPCB->pSSID = MALLOC (NDIS_802_11_SSID_LEN)) == NULL)
  803. {
  804. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  805. TRACE0 (PORT, "ElParseIdentityString: MALLOC failed for pSSID");
  806. break;
  807. }
  808. if (0 == WideCharToMultiByte (
  809. CP_ACP,
  810. 0,
  811. pwszNetworkId,
  812. dwNetworkIdLen,
  813. pPCB->pSSID->Ssid,
  814. dwNetworkIdLen,
  815. NULL,
  816. NULL ))
  817. {
  818. dwRetCode = GetLastError();
  819. TRACE2 (ANY, "ElParseIdentityString: WideCharToMultiByte (%ws) failed for SSID: (%ld)",
  820. pwszNetworkId, dwRetCode);
  821. break;
  822. }
  823. pPCB->pSSID->SsidLength = dwNetworkIdLen;
  824. wcscpy (pPCB->pwszSSID, pwszNetworkId);
  825. }
  826. // Retrieve the current interface params
  827. ZeroMemory ((BYTE *)&EapolIntfParams, sizeof(EAPOL_INTF_PARAMS));
  828. EapolIntfParams.dwEapFlags = DEFAULT_EAP_STATE;
  829. EapolIntfParams.dwEapType = DEFAULT_EAP_TYPE;
  830. if (pPCB->pSSID != NULL)
  831. {
  832. memcpy (EapolIntfParams.bSSID, pPCB->pSSID->Ssid, pPCB->pSSID->SsidLength);
  833. EapolIntfParams.dwSizeOfSSID = pPCB->pSSID->SsidLength;
  834. }
  835. if ((dwRetCode = ElGetInterfaceParams (
  836. pPCB->pwszDeviceGUID,
  837. &EapolIntfParams
  838. )) != NO_ERROR)
  839. {
  840. TRACE1 (PORT, "ElParseIdentityString: ElGetInterfaceParams failed with error %ld",
  841. dwRetCode);
  842. if (dwRetCode == ERROR_FILE_NOT_FOUND)
  843. {
  844. pPCB->dwEapFlags = DEFAULT_EAPOL_STATE;
  845. pPCB->dwEapTypeToBeUsed = DEFAULT_EAP_TYPE;
  846. dwRetCode = NO_ERROR;
  847. }
  848. else
  849. {
  850. break;
  851. }
  852. }
  853. else
  854. {
  855. pPCB->dwEapFlags = EapolIntfParams.dwEapFlags;
  856. pPCB->dwEapTypeToBeUsed = EapolIntfParams.dwEapType;
  857. }
  858. if (!IS_EAPOL_ENABLED(pPCB->dwEapFlags))
  859. {
  860. TRACE0 (PORT, "ElParseIdentityString: Marking port as disabled");
  861. pPCB->dwFlags &= ~EAPOL_PORT_FLAG_ACTIVE;
  862. pPCB->dwFlags |= EAPOL_PORT_FLAG_DISABLED;
  863. }
  864. TRACE1 (EAP, "ElParseIdentityString: Got SSID %ws", pPCB->pwszSSID);
  865. }
  866. //
  867. // Send type=value tuple string to NLA for processing
  868. //
  869. RtlZeroMemory(&location, sizeof(location));
  870. if (0 == WideCharToMultiByte (
  871. CP_ACP,
  872. 0,
  873. pPCB->pwszDeviceGUID,
  874. -1,
  875. location.adapterName,
  876. wcslen(pPCB->pwszDeviceGUID)+1,
  877. NULL,
  878. NULL ))
  879. {
  880. dwRetCode = GetLastError();
  881. TRACE2 (ANY, "ElParseIdentityString: WideCharToMultiByte (%ws) failed: (%ld)",
  882. pPCB->pwszDeviceGUID, dwRetCode);
  883. break;
  884. }
  885. location.adapterName[wcslen(pPCB->pwszDeviceGUID)] = '\0';
  886. wcsncpy (location.information, pwszDisplayStringEnd + 1, 2048);
  887. TRACE2 (EAP, "ElParseIdentityString: Calling NLARegister_802_1X with params %ws and %ws",
  888. pPCB->pwszDeviceGUID, location.information);
  889. ElNLARegister_802_1X(&location);
  890. TRACE0 (EAP, "ElParseIdentityString: Returned after calling NLARegister_802_1X");
  891. } while (FALSE);
  892. if (pszLocalIdString != NULL)
  893. {
  894. FREE (pszLocalIdString);
  895. }
  896. if (pwszLocalIdString != NULL)
  897. {
  898. FREE (pwszLocalIdString);
  899. }
  900. if (pwszDisplayString != NULL)
  901. {
  902. FREE (pwszDisplayString);
  903. }
  904. if (pwszNetworkId != NULL)
  905. {
  906. FREE (pwszNetworkId);
  907. }
  908. if (pwszNASId != NULL)
  909. {
  910. FREE (pwszNASId);
  911. }
  912. if (pwszPortId != NULL)
  913. {
  914. FREE (pwszPortId);
  915. }
  916. return dwRetCode;
  917. }
  918. //
  919. // ElEapMakeMessage
  920. //
  921. // Description:
  922. //
  923. // Function called to process a received EAP packet and/or to send
  924. // out an EAP packet.
  925. //
  926. // Arguments:
  927. // pPCB - Pointer to PCB for the port on which data is being processed
  928. // pReceiveBuf - Pointer to EAP Packet that was received
  929. // pSendBuf - output: Pointer to buffer created to hold output EAP packet
  930. // dwSizeOfSendBuf - Number of bytes pSendBuf is allocated
  931. // pResult - output: result structure containing various results of EAP
  932. // processing
  933. //
  934. // Return values:
  935. // NO_ERROR - success
  936. // non-zero - error
  937. //
  938. DWORD
  939. ElEapMakeMessage (
  940. IN EAPOL_PCB *pPCB,
  941. IN PPP_EAP_PACKET *pReceiveBuf,
  942. IN OUT PPP_EAP_PACKET *pSendBuf,
  943. IN DWORD dwSizeOfSendBuf,
  944. OUT ELEAP_RESULT *pResult
  945. )
  946. {
  947. DWORD dwIdentityLength = 0;
  948. DWORD dwRetCode = NO_ERROR;
  949. TRACE0 (EAP,"ElEapMakeMessage entered");
  950. if ((pReceiveBuf != NULL) && (pReceiveBuf->Code == EAPCODE_Request))
  951. {
  952. //
  953. // Always respond to notitication request, with a notification response
  954. //
  955. if (pReceiveBuf->Data[0] == EAPTYPE_Notification)
  956. {
  957. pSendBuf->Code = EAPCODE_Response;
  958. pSendBuf->Id = pReceiveBuf->Id;
  959. HostToWireFormat16 (PPP_EAP_PACKET_HDR_LEN + 1, pSendBuf->Length);
  960. pSendBuf->Data[0] = EAPTYPE_Notification;
  961. pResult->Action = ELEAP_Send;
  962. // Indicate to EAPOL what is length of the EAP packet
  963. pResult->wSizeOfEapPkt = PPP_EAP_PACKET_HDR_LEN + 1;
  964. // Extract the notification message from server and save
  965. // it in the result struct for display to the user
  966. ElEapExtractMessage (pReceiveBuf, pResult);
  967. return (NO_ERROR);
  968. }
  969. //
  970. // Always respond to Identity request, with an Identity response
  971. //
  972. if (pReceiveBuf->Data[0] == EAPTYPE_Identity)
  973. {
  974. // Extract SSID out of the body of the received packet
  975. // and save it in the SSID field of the PCB
  976. // Also, save the SSID received as the last used SSID
  977. if ((dwRetCode = ElParseIdentityString (
  978. pReceiveBuf,
  979. pPCB)) != NO_ERROR)
  980. {
  981. TRACE1 (EAP, "ElEapMakeMessage: Error in ElParseIdentityString = %ld",
  982. dwRetCode);
  983. return dwRetCode;
  984. }
  985. // Check if Identity is being fetched for same EAP-Id
  986. if ((pReceiveBuf->Id == pPCB->bCurrentEAPId) &&
  987. (pPCB->EapUIState == EAPUISTATE_WAITING_FOR_IDENTITY))
  988. {
  989. // Restart PCB timer since authtimer has already been set
  990. RESTART_TIMER (pPCB->hTimer,
  991. INFINITE_SECONDS,
  992. "PCB",
  993. &dwRetCode);
  994. if (dwRetCode != NO_ERROR)
  995. {
  996. TRACE1 (EAP, "ElEapMakeMessage: RESTART_TIMER during re-xmit failed with error %ld",
  997. dwRetCode);
  998. }
  999. TRACE0 (EAP, "ElEapMakeMessage: Ignoring re-transmit while waiting for Identity UI");
  1000. return (dwRetCode);
  1001. };
  1002. pPCB->bCurrentEAPId = pReceiveBuf->Id;
  1003. if ((dwRetCode = ElGetIdentity (
  1004. pPCB)) != NO_ERROR)
  1005. {
  1006. TRACE1 (EAP, "ElEapMakeMessage: Error in ElGetIdentity %ld",
  1007. dwRetCode);
  1008. return dwRetCode;
  1009. }
  1010. pSendBuf->Code = EAPCODE_Response;
  1011. pSendBuf->Id = pReceiveBuf->Id;
  1012. if (pPCB->pszIdentity != NULL)
  1013. {
  1014. dwIdentityLength = strlen (pPCB->pszIdentity);
  1015. }
  1016. else
  1017. {
  1018. dwIdentityLength = 0;
  1019. }
  1020. HostToWireFormat16 (
  1021. (WORD)(PPP_EAP_PACKET_HDR_LEN+1+dwIdentityLength),
  1022. pSendBuf->Length );
  1023. strncpy ((CHAR *)pSendBuf->Data+1, (CHAR *)pPCB->pszIdentity,
  1024. dwIdentityLength);
  1025. TRACE1 (EAPOL, "Identity sent out = %s", pPCB->pszIdentity);
  1026. pSendBuf->Data[0] = EAPTYPE_Identity;
  1027. pResult->Action = ELEAP_Send;
  1028. // Indicate to EAPOL what is length of the EAP packet
  1029. pResult->wSizeOfEapPkt = (WORD)(PPP_EAP_PACKET_HDR_LEN+
  1030. 1+dwIdentityLength);
  1031. return( NO_ERROR );
  1032. }
  1033. }
  1034. return
  1035. ElMakeSupplicantMessage (
  1036. pPCB, pReceiveBuf, pSendBuf, dwSizeOfSendBuf, pResult);
  1037. }
  1038. //
  1039. // ElMakeSupplicantMessage
  1040. //
  1041. // Description:
  1042. //
  1043. // EAP Supplicant engine. Can be part of ElEapMakeMessage, but separated for
  1044. // readability
  1045. //
  1046. // Arguments:
  1047. // pPCB - Pointer to PCB for the port on which data is being processed
  1048. // pReceiveBuf - Pointer to EAP Packet that was received
  1049. // pSendBuf - output: Pointer to buffer created to hold output EAP packet
  1050. // dwSizeOfSendBuf - Number of bytes pSendBuf is allocated
  1051. // pResult - output: result structure containing various results of EAP
  1052. // processing
  1053. //
  1054. // Return values:
  1055. // NO_ERROR - success
  1056. // non-zero - error
  1057. //
  1058. DWORD
  1059. ElMakeSupplicantMessage (
  1060. IN EAPOL_PCB *pPCB,
  1061. IN PPP_EAP_PACKET* pReceiveBuf,
  1062. IN OUT PPP_EAP_PACKET* pSendBuf,
  1063. IN DWORD dwSizeOfSendBuf,
  1064. IN OUT ELEAP_RESULT* pResult
  1065. )
  1066. {
  1067. DWORD dwEapIndex;
  1068. DWORD dwRetCode = NO_ERROR;
  1069. TRACE0 (EAP,"ElMakeSupplicantMessage entered");
  1070. switch (pPCB->EapState)
  1071. {
  1072. case EAPSTATE_Initial:
  1073. TRACE0 (EAP,"EAPSTATE_Initial");
  1074. if (pReceiveBuf == NULL)
  1075. {
  1076. //
  1077. // Do nothing. Wait for request from authenticator
  1078. //
  1079. TRACE0 (EAP, "ElMakeSupplicantMessage: Received NULL EAP pkt, No Action");
  1080. pResult->Action = ELEAP_NoAction;
  1081. break;
  1082. }
  1083. else
  1084. {
  1085. if (pReceiveBuf->Code != EAPCODE_Request)
  1086. {
  1087. //
  1088. // We are authenticatee side so drop everything other than
  1089. // requests, since we do not send requests
  1090. //
  1091. pResult->Action = ELEAP_NoAction;
  1092. break;
  1093. }
  1094. //
  1095. // We got a packet, see if we support this EAP type, also that
  1096. // we are authorized to use it
  1097. //
  1098. dwEapIndex = ElGetEapTypeIndex (pReceiveBuf->Data[0]);
  1099. if ((dwEapIndex == -1) ||
  1100. ((pPCB->dwEapTypeToBeUsed != -1) &&
  1101. (dwEapIndex != ElGetEapTypeIndex (pPCB->dwEapTypeToBeUsed))))
  1102. {
  1103. //
  1104. // We do not support this type or we are not authorized to use
  1105. // it so we NAK with a type we support
  1106. //
  1107. pSendBuf->Code = EAPCODE_Response;
  1108. pSendBuf->Id = pReceiveBuf->Id;
  1109. HostToWireFormat16 (PPP_EAP_PACKET_HDR_LEN + 2,
  1110. pSendBuf->Length);
  1111. pSendBuf->Data[0] = EAPTYPE_Nak;
  1112. if (pPCB->dwEapTypeToBeUsed != -1)
  1113. {
  1114. pSendBuf->Data[1] = (BYTE)pPCB->dwEapTypeToBeUsed;
  1115. }
  1116. else
  1117. {
  1118. pSendBuf->Data[1] =
  1119. (BYTE)g_pEapTable[0].RasEapInfo.dwEapTypeId;
  1120. }
  1121. pResult->Action = ELEAP_Send;
  1122. TRACE2 (EAP, "ElMakeSupplicantMessage: Send NAK, Got EAP type (%ld), Expected (%ld)",
  1123. pReceiveBuf->Data[0], pPCB->dwEapTypeToBeUsed);
  1124. DbLogPCBEvent (DBLOG_CATEG_ERR, pPCB,
  1125. EAPOL_INVALID_EAP_TYPE,
  1126. pReceiveBuf->Data[0], pPCB->dwEapTypeToBeUsed);
  1127. break;
  1128. }
  1129. else
  1130. {
  1131. //
  1132. // The EAP type is acceptable to us so we begin authentication
  1133. //
  1134. if ((dwRetCode = ElEapDllBegin (pPCB, dwEapIndex)) != NO_ERROR)
  1135. {
  1136. break;
  1137. }
  1138. pPCB->EapState = EAPSTATE_Working;
  1139. //
  1140. // Fall thru
  1141. //
  1142. }
  1143. }
  1144. case EAPSTATE_Working:
  1145. TRACE0 (EAP,"EAPSTATE_Working");
  1146. if (pReceiveBuf != NULL)
  1147. {
  1148. if ((pReceiveBuf->Code != EAPCODE_Request) &&
  1149. (pReceiveBuf->Code != EAPCODE_Success) &&
  1150. (pReceiveBuf->Code != EAPCODE_Failure))
  1151. {
  1152. //
  1153. // We are supplicant side so drop everything other than
  1154. // request/success/failure
  1155. //
  1156. TRACE0 (EAP,"ElMakeSupplicantMessage: Dropping invalid packet not request/success/failure");
  1157. pResult->Action = ELEAP_NoAction;
  1158. break;
  1159. }
  1160. if ((pReceiveBuf->Code == EAPCODE_Request) &&
  1161. (pReceiveBuf->Data[0] !=
  1162. g_pEapTable[pPCB->dwEapIndex].RasEapInfo.dwEapTypeId))
  1163. {
  1164. TRACE0 (EAP,"ElMakeSupplicantMessage: Dropping invalid request packet with unknown Id");
  1165. pResult->Action = ELEAP_NoAction;
  1166. break;
  1167. }
  1168. }
  1169. dwRetCode = ElEapDllWork (pPCB,
  1170. pReceiveBuf,
  1171. pSendBuf,
  1172. dwSizeOfSendBuf,
  1173. pResult
  1174. );
  1175. break;
  1176. default:
  1177. TRACE0 (EAP, "ElMakeSupplicantMessage: Invalid EAP State");
  1178. break;
  1179. }
  1180. return dwRetCode;
  1181. }
  1182. //
  1183. //
  1184. // ElEapDllBegin
  1185. //
  1186. // Description:
  1187. //
  1188. // Function called to initiate an EAP session for a certain EAP type
  1189. //
  1190. // Arguments:
  1191. // pPCB - Pointer to PCB for the port in context
  1192. // dwEapIndex - EAP type for which a session has to be started
  1193. //
  1194. // Return values:
  1195. // NO_ERROR - success
  1196. // non-zero - error
  1197. //
  1198. //
  1199. DWORD
  1200. ElEapDllBegin (
  1201. IN EAPOL_PCB *pPCB,
  1202. IN DWORD dwEapIndex
  1203. )
  1204. {
  1205. PPP_EAP_INPUT PppEapInput;
  1206. WCHAR *pwszIdentity = NULL;
  1207. DWORD dwIdentityLength = 0;
  1208. WCHAR *pwszPassword = NULL;
  1209. BOOLEAN fRevertToSelf = FALSE;
  1210. DWORD dwPasswordLen = 0;
  1211. DWORD dwRetCode = NO_ERROR;
  1212. TRACE1 (EAP,"ElEapDllBegin called for EAP Type %d",
  1213. g_pEapTable[dwEapIndex].RasEapInfo.dwEapTypeId);
  1214. do
  1215. {
  1216. // Format the identity string correctly.
  1217. // For EAP-TLS, it will be the identity on the chosen certificate
  1218. // For EAP-CHAP, it will be domain\username
  1219. if (pPCB->pszIdentity != NULL)
  1220. {
  1221. dwIdentityLength = strlen (pPCB->pszIdentity);
  1222. }
  1223. else
  1224. {
  1225. dwIdentityLength = 0;
  1226. }
  1227. pwszIdentity = MALLOC ((dwIdentityLength+2) * sizeof(WCHAR));
  1228. if (pwszIdentity == NULL)
  1229. {
  1230. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1231. TRACE0 (EAP, "ElEapDllBegin: MALLOC failed for pwszIdentity");
  1232. break;
  1233. }
  1234. if (dwIdentityLength > 0)
  1235. {
  1236. if (0 == MultiByteToWideChar (
  1237. CP_ACP,
  1238. 0,
  1239. pPCB->pszIdentity,
  1240. -1,
  1241. pwszIdentity,
  1242. dwIdentityLength+2))
  1243. {
  1244. dwRetCode = GetLastError();
  1245. TRACE2 (EAP,"MultiByteToWideChar(%s) failed: %d",
  1246. pPCB->pszIdentity,
  1247. dwRetCode);
  1248. break;
  1249. }
  1250. }
  1251. else
  1252. {
  1253. pwszIdentity[0] = L'\0';
  1254. }
  1255. // Unhash password stored locally
  1256. if (pPCB->PasswordBlob.cbData > 0)
  1257. {
  1258. // Impersonate the user first, since the password has been
  1259. // encrypted using the password
  1260. if (!ImpersonateLoggedOnUser (pPCB->hUserToken))
  1261. {
  1262. dwRetCode = GetLastError ();
  1263. TRACE1 (EAP, "ElEapDllBegin: ImpersonateLoggedOnUser failed with error %ld",
  1264. dwRetCode);
  1265. break;
  1266. }
  1267. fRevertToSelf = TRUE;
  1268. if ((dwRetCode = ElSecureDecodePw (
  1269. &(pPCB->PasswordBlob),
  1270. &((BYTE *)pwszPassword),
  1271. &dwPasswordLen
  1272. )) != NO_ERROR)
  1273. {
  1274. TRACE1 (EAP, "ElEapDllBegin: ElSecureDecodePw failed with error %ld",
  1275. dwRetCode);
  1276. break;
  1277. }
  1278. fRevertToSelf = FALSE;
  1279. if (!RevertToSelf ())
  1280. {
  1281. dwRetCode = GetLastError ();
  1282. TRACE1 (EAP, "ElEapDllBegin: RevertToSelf failed with error %ld",
  1283. dwRetCode);
  1284. dwRetCode = ERROR_BAD_IMPERSONATION_LEVEL;
  1285. break;
  1286. }
  1287. }
  1288. else
  1289. {
  1290. pwszPassword = MALLOC (sizeof(WCHAR));
  1291. if (pwszPassword == NULL)
  1292. {
  1293. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1294. TRACE0 (EAP, "ElEapDllBegin: MALLOC failed for pwszPassword");
  1295. break;
  1296. }
  1297. pwszPassword[0] = L'\0';
  1298. }
  1299. ZeroMemory (&PppEapInput, sizeof (PppEapInput));
  1300. PppEapInput.dwSizeInBytes = sizeof (PPP_EAP_INPUT);
  1301. if (IS_MACHINE_AUTH_ENABLED(pPCB->dwEapFlags))
  1302. {
  1303. // Set flag to indicate machine cert is to be picked up for machine
  1304. // authentication
  1305. if (pPCB->PreviousAuthenticationType ==
  1306. EAPOL_MACHINE_AUTHENTICATION)
  1307. {
  1308. TRACE0 (EAP, "ElEapDllBegin: Going for machine authentication");
  1309. PppEapInput.fFlags |= RAS_EAP_FLAG_MACHINE_AUTH;
  1310. }
  1311. }
  1312. if (IS_GUEST_AUTH_ENABLED(pPCB->dwEapFlags))
  1313. {
  1314. if (pPCB->pszIdentity == NULL)
  1315. {
  1316. PppEapInput.fFlags |= RAS_EAP_FLAG_GUEST_ACCESS;
  1317. }
  1318. }
  1319. PppEapInput.fFlags |= RAS_EAP_FLAG_8021X_AUTH;
  1320. PppEapInput.fAuthenticator = FALSE; // Always supplicant
  1321. PppEapInput.pwszIdentity = pwszIdentity;
  1322. PppEapInput.pwszPassword = pwszPassword;
  1323. PppEapInput.hTokenImpersonateUser = pPCB->hUserToken;
  1324. PppEapInput.fAuthenticationComplete = FALSE;
  1325. PppEapInput.dwAuthResultCode = NO_ERROR;
  1326. if (pPCB->pCustomAuthConnData != NULL)
  1327. {
  1328. if (pPCB->pCustomAuthConnData->dwSizeOfCustomAuthData != 0)
  1329. {
  1330. PppEapInput.pConnectionData =
  1331. pPCB->pCustomAuthConnData->pbCustomAuthData;
  1332. PppEapInput.dwSizeOfConnectionData =
  1333. pPCB->pCustomAuthConnData->dwSizeOfCustomAuthData;
  1334. }
  1335. }
  1336. if (pPCB->pCustomAuthUserData != NULL)
  1337. {
  1338. if (pPCB->pCustomAuthUserData->dwSizeOfCustomAuthData != 0)
  1339. {
  1340. PppEapInput.pUserData =
  1341. pPCB->pCustomAuthUserData->pbCustomAuthData;
  1342. PppEapInput.dwSizeOfUserData =
  1343. pPCB->pCustomAuthUserData->dwSizeOfCustomAuthData;
  1344. }
  1345. }
  1346. if (pPCB->EapUIData.pEapUIData != NULL)
  1347. {
  1348. PppEapInput.pDataFromInteractiveUI =
  1349. pPCB->EapUIData.pEapUIData;
  1350. PppEapInput.dwSizeOfDataFromInteractiveUI =
  1351. pPCB->EapUIData.dwSizeOfEapUIData;
  1352. }
  1353. if (pPCB->dwEapTypeToBeUsed == EAP_TYPE_TLS)
  1354. {
  1355. if ((dwRetCode = ElLogCertificateDetails (pPCB))
  1356. == ERROR_BAD_IMPERSONATION_LEVEL)
  1357. {
  1358. TRACE0 (EAP, "ElEapDllBegin: ElLogCertificateDetails failed with RevertToSelf error");
  1359. break;
  1360. }
  1361. dwRetCode = NO_ERROR;
  1362. }
  1363. // Call the RasEapBegin API
  1364. dwRetCode = g_pEapTable[dwEapIndex].RasEapInfo.RasEapBegin (
  1365. &pPCB->lpEapDllWorkBuffer,
  1366. &PppEapInput);
  1367. if (pwszPassword != NULL)
  1368. {
  1369. FREE (pwszPassword);
  1370. pwszPassword = NULL;
  1371. }
  1372. if (dwRetCode == NO_ERROR)
  1373. {
  1374. pPCB->dwEapIndex = dwEapIndex;
  1375. }
  1376. else
  1377. {
  1378. TRACE1 (EAP, "ElEapDllBegin: RasEapBegin failed with error %ld",
  1379. dwRetCode);
  1380. DbLogPCBEvent (DBLOG_CATEG_ERR, pPCB,
  1381. EAPOL_ERROR_AUTH_PROCESSING, dwRetCode);
  1382. pPCB->dwEapIndex = (DWORD)-1;
  1383. }
  1384. }
  1385. while (FALSE);
  1386. if (fRevertToSelf)
  1387. {
  1388. if (!RevertToSelf ())
  1389. {
  1390. dwRetCode = GetLastError ();
  1391. TRACE1 (EAP, "ElEapDllBegin: RevertToSelf failed with error %ld",
  1392. dwRetCode);
  1393. dwRetCode = ERROR_BAD_IMPERSONATION_LEVEL;
  1394. }
  1395. }
  1396. if (pwszPassword != NULL)
  1397. {
  1398. FREE (pwszPassword);
  1399. }
  1400. if (pwszIdentity != NULL)
  1401. {
  1402. FREE (pwszIdentity);
  1403. }
  1404. return dwRetCode;
  1405. }
  1406. //
  1407. // ElEapDllEnd
  1408. //
  1409. // Description:
  1410. //
  1411. // Function called to end an EAP session
  1412. //
  1413. // Arguments:
  1414. // pPCB - Pointer to the PCB for the port in context
  1415. //
  1416. // Return values:
  1417. // NO_ERROR - success
  1418. // non-zero - error
  1419. //
  1420. DWORD
  1421. ElEapDllEnd (
  1422. EAPOL_PCB *pPCB
  1423. )
  1424. {
  1425. DWORD dwRetCode = NO_ERROR;
  1426. TRACE1 (EAP, "ElEapDllEnd called for EAP Index %d", pPCB->dwEapIndex );
  1427. if (pPCB->lpEapDllWorkBuffer != NULL)
  1428. {
  1429. if (pPCB->dwEapIndex != (DWORD)-1)
  1430. {
  1431. dwRetCode = g_pEapTable[pPCB->dwEapIndex].RasEapInfo.RasEapEnd (
  1432. pPCB->lpEapDllWorkBuffer);
  1433. }
  1434. pPCB->lpEapDllWorkBuffer = NULL;
  1435. }
  1436. pPCB->dwEapIndex = (DWORD)-1;
  1437. pPCB->EapState = EAPSTATE_Initial;
  1438. return dwRetCode;
  1439. }
  1440. //
  1441. // ElEapDllWork
  1442. //
  1443. // Description:
  1444. //
  1445. // Function called to process an incoming packet or timeout etc
  1446. // The RasEapMakeMessage entrypoint in the appropriate EAP DLL is called
  1447. // to process the packet.
  1448. //
  1449. // Arguments:
  1450. // pPCB - Pointer to PCB for the port on which data is being processed
  1451. // pReceiveBuf - Pointer to EAP Packet that was received
  1452. // pSendBuf - output: Pointer to buffer created to hold output EAP packet
  1453. // dwSizeOfSendBuf - Number of bytes pSendBuf is allocated
  1454. // pResult - output: result structure containing various results of EAP
  1455. // processing
  1456. //
  1457. // Return values:
  1458. // NO_ERROR - success
  1459. // non-zero - error
  1460. //
  1461. DWORD
  1462. ElEapDllWork (
  1463. IN EAPOL_PCB *pPCB,
  1464. IN PPP_EAP_PACKET *pReceiveBuf,
  1465. IN OUT PPP_EAP_PACKET *pSendBuf,
  1466. IN DWORD dwSizeOfSendBuf,
  1467. IN OUT ELEAP_RESULT *pResult
  1468. )
  1469. {
  1470. PPP_EAP_OUTPUT PppEapOutput;
  1471. PPP_EAP_INPUT PppEapInput;
  1472. CHAR * pChar = NULL;
  1473. DWORD dwRetCode = NO_ERROR;
  1474. TRACE1 (EAP, "ElEapDllWork called for EAP Type %d",
  1475. g_pEapTable[pPCB->dwEapIndex].RasEapInfo.dwEapTypeId);
  1476. ZeroMemory (&PppEapOutput, sizeof (PppEapOutput));
  1477. PppEapOutput.dwSizeInBytes = sizeof (PppEapOutput);
  1478. ZeroMemory (&PppEapInput, sizeof (PppEapInput));
  1479. PppEapInput.dwSizeInBytes = sizeof (PPP_EAP_INPUT);
  1480. PppEapInput.fAuthenticator = FALSE; // We are always supplicant
  1481. PppEapInput.hTokenImpersonateUser = pPCB->hUserToken;
  1482. if (pPCB->fEapUIDataReceived)
  1483. {
  1484. if (pPCB->EapUIData.dwContextId != pPCB->dwUIInvocationId)
  1485. {
  1486. // Ignore this data received
  1487. pPCB->fEapUIDataReceived = FALSE;
  1488. TRACE0 (EAP,"ElEapDllWork: Out of date data received from UI");
  1489. return(NO_ERROR);
  1490. }
  1491. PppEapInput.fDataReceivedFromInteractiveUI = TRUE;
  1492. PppEapInput.pDataFromInteractiveUI =
  1493. pPCB->EapUIData.pEapUIData;
  1494. PppEapInput.dwSizeOfDataFromInteractiveUI =
  1495. pPCB->EapUIData.dwSizeOfEapUIData;
  1496. pPCB->fEapUIDataReceived = FALSE;
  1497. }
  1498. dwRetCode = g_pEapTable[pPCB->dwEapIndex].RasEapInfo.RasEapMakeMessage (
  1499. pPCB->lpEapDllWorkBuffer,
  1500. (PPP_EAP_PACKET *)pReceiveBuf,
  1501. (PPP_EAP_PACKET *)pSendBuf,
  1502. dwSizeOfSendBuf,
  1503. &PppEapOutput,
  1504. &PppEapInput);
  1505. // Free InvokeInteractive UI data since we no longer need it
  1506. if (pPCB->EapUIData.pEapUIData != NULL)
  1507. {
  1508. FREE (pPCB->EapUIData.pEapUIData);
  1509. pPCB->EapUIData.pEapUIData = NULL;
  1510. }
  1511. if (dwRetCode != NO_ERROR)
  1512. {
  1513. switch (dwRetCode)
  1514. {
  1515. case ERROR_PPP_INVALID_PACKET:
  1516. TRACE0 (EAP,"Silently discarding invalid EAP packet");
  1517. pResult->Action = ELEAP_NoAction;
  1518. return (NO_ERROR);
  1519. default:
  1520. DbLogPCBEvent (DBLOG_CATEG_ERR, pPCB,
  1521. EAPOL_ERROR_AUTH_PROCESSING, dwRetCode);
  1522. TRACE2 (EAP,"EapDLLMakeMessage for type %d returned %d",
  1523. g_pEapTable[pPCB->dwEapIndex].RasEapInfo.dwEapTypeId,
  1524. dwRetCode );
  1525. break;
  1526. }
  1527. return dwRetCode;
  1528. }
  1529. switch (PppEapOutput.Action)
  1530. {
  1531. case EAPACTION_NoAction:
  1532. pResult->Action = ELEAP_NoAction;
  1533. TRACE0 (EAP, "EAP Dll returned Action=EAPACTION_NoAction" );
  1534. break;
  1535. case EAPACTION_Send:
  1536. pResult->Action = ELEAP_Send;
  1537. TRACE0 (EAP, "EAP Dll returned Action=EAPACTION_Send" );
  1538. break;
  1539. case EAPACTION_Done:
  1540. case EAPACTION_SendAndDone:
  1541. if (PppEapOutput.Action == EAPACTION_SendAndDone)
  1542. {
  1543. pResult->Action = ELEAP_SendAndDone;
  1544. TRACE0 (EAP, "EAP Dll returned Action=EAPACTION_SendAndDone" );
  1545. }
  1546. else
  1547. {
  1548. pResult->Action = ELEAP_Done;
  1549. TRACE0 (EAP, "EAP Dll returned Action=EAPACTION_Done" );
  1550. }
  1551. // These are the attributes that are filled in by the EAP-DLL
  1552. // e.g in EAP-TLS it will be MPPE Keys
  1553. pResult->dwError = PppEapOutput.dwAuthResultCode;
  1554. pResult->pUserAttributes = PppEapOutput.pUserAttributes;
  1555. if (pPCB->pszIdentity != NULL)
  1556. {
  1557. strncpy (pResult->szUserName, pPCB->pszIdentity, UNLEN);
  1558. pResult->szUserName[UNLEN] = '\0';
  1559. }
  1560. else
  1561. {
  1562. pResult->szUserName[0] = '\0';
  1563. }
  1564. break;
  1565. case EAPACTION_SendWithTimeout:
  1566. case EAPACTION_SendWithTimeoutInteractive:
  1567. case EAPACTION_Authenticate:
  1568. TRACE1 (EAP, "EAP Dll returned disallowed Action=%d",
  1569. PppEapOutput.Action);
  1570. break;
  1571. default:
  1572. TRACE1 (EAP, "EAP Dll returned unknown Action=%d", PppEapOutput.Action);
  1573. break;
  1574. }
  1575. //
  1576. // Check to see if EAP dll wants to bring up UI
  1577. //
  1578. if (PppEapOutput.fInvokeInteractiveUI)
  1579. {
  1580. if (PppEapOutput.pUIContextData != NULL)
  1581. {
  1582. pResult->InvokeEapUIData.dwSizeOfUIContextData =
  1583. PppEapOutput.dwSizeOfUIContextData;
  1584. // The context data memory is freed after the InvokeUI entrypoint
  1585. // in the EAP DLL is called
  1586. pResult->InvokeEapUIData.pbUIContextData
  1587. = MALLOC (PppEapOutput.dwSizeOfUIContextData);
  1588. if (pResult->InvokeEapUIData.pbUIContextData == NULL)
  1589. {
  1590. return (ERROR_NOT_ENOUGH_MEMORY);
  1591. }
  1592. CopyMemory (pResult->InvokeEapUIData.pbUIContextData,
  1593. PppEapOutput.pUIContextData,
  1594. pResult->InvokeEapUIData.dwSizeOfUIContextData);
  1595. }
  1596. else
  1597. {
  1598. pResult->InvokeEapUIData.pbUIContextData = NULL;
  1599. pResult->InvokeEapUIData.dwSizeOfUIContextData = 0;
  1600. }
  1601. pResult->fInvokeEapUI = TRUE;
  1602. pPCB->dwUIInvocationId =
  1603. InterlockedIncrement(&(g_dwEAPUIInvocationId));
  1604. pResult->InvokeEapUIData.dwContextId = pPCB->dwUIInvocationId;
  1605. pResult->InvokeEapUIData.dwEapTypeId =
  1606. g_pEapTable[pPCB->dwEapIndex].RasEapInfo.dwEapTypeId;
  1607. TRACE0 (EAP, "EAP Dll wants to invoke interactive UI" );
  1608. DbLogPCBEvent (DBLOG_CATEG_INFO, pPCB, EAPOL_DESKTOP_REQUIRED_LOGON);
  1609. }
  1610. pResult->dwEapTypeId = pPCB->dwEapTypeToBeUsed;
  1611. pResult->fSaveUserData = PppEapOutput.fSaveUserData;
  1612. pResult->pUserData = PppEapOutput.pUserData;
  1613. pResult->dwSizeOfUserData = PppEapOutput.dwSizeOfUserData;
  1614. pResult->fSaveConnectionData = PppEapOutput.fSaveConnectionData;
  1615. pResult->SetCustomAuthData.pConnectionData =
  1616. PppEapOutput.pConnectionData;
  1617. pResult->SetCustomAuthData.dwSizeOfConnectionData =
  1618. PppEapOutput.dwSizeOfConnectionData;
  1619. TRACE2 (EAP,"ElEapDllWork finished for EAP Type %d with error %ld",
  1620. g_pEapTable[pPCB->dwEapIndex].RasEapInfo.dwEapTypeId,
  1621. dwRetCode);
  1622. return dwRetCode;
  1623. }
  1624. //
  1625. // ElGetEapIndex
  1626. //
  1627. // Description:
  1628. //
  1629. // Function called to get the index into the global EAP dll table for the
  1630. // specified EAP type
  1631. //
  1632. // Arguments:
  1633. // dwEapTypeId - Index into the EAP table for the input EAP type
  1634. // e.g. TLS = 13, MD5 = 4
  1635. //
  1636. DWORD
  1637. ElGetEapTypeIndex (
  1638. IN DWORD dwEapTypeId
  1639. )
  1640. {
  1641. DWORD dwIndex;
  1642. for (dwIndex = 0; dwIndex < g_dwNumEapProtocols; dwIndex++)
  1643. {
  1644. if (g_pEapTable[dwIndex].RasEapInfo.dwEapTypeId == dwEapTypeId)
  1645. {
  1646. return(dwIndex);
  1647. }
  1648. }
  1649. return((DWORD)-1);
  1650. }