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.

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