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.

2205 lines
66 KiB

  1. /*++
  2. Copyright (c) 2000, Microsoft Corporation
  3. Module Name:
  4. eluser.c
  5. Abstract:
  6. The module deals with functions related to user interaction, user logon
  7. Revision History:
  8. sachins, Apr 23 2000, Created
  9. --*/
  10. #include "pcheapol.h"
  11. #pragma hdrstop
  12. //
  13. // Test code declarations for EAP-MD5CHAP
  14. //
  15. // This function is not defined in any header file. Located in
  16. // $(SDK_LIB_PATH)\irnotif.lib
  17. extern HANDLE
  18. GetCurrentUserTokenW (
  19. WCHAR Winsta[],
  20. DWORD DesiredAccess
  21. );
  22. extern BOOL
  23. GetWinStationUserToken(ULONG, PHANDLE);
  24. extern ULONG
  25. GetClientLogonId ();
  26. #define cszEapKeyRas TEXT("Software\\Microsoft\\RAS EAP\\UserEapInfo")
  27. #define cszEapValue TEXT("EapInfo")
  28. #ifndef EAPOL_SERVICE
  29. #define cszModuleName TEXT("netman.dll")
  30. #else
  31. #define cszModuleName TEXT("eapol.exe")
  32. #endif
  33. //
  34. // ElGetUserIdentity
  35. //
  36. // Description:
  37. //
  38. // Function called to initiate and get user identity on a particular
  39. // interface. The RasEapGetIdentity in the appropriate DLL is called
  40. // with the necessary arguments.
  41. //
  42. // Arguments:
  43. // pPCB - Pointer to PCB for the specific port/interface
  44. //
  45. // Return values:
  46. // NO_ERROR - success
  47. // non-zero - error
  48. //
  49. DWORD
  50. ElGetUserIdentity (
  51. IN EAPOL_PCB *pPCB
  52. )
  53. {
  54. HANDLE hUserToken;
  55. HANDLE hLib = NULL;
  56. EAPOLEAPFREE pFreeFunc = NULL;
  57. EAPOLEAPGETIDENTITY pIdenFunc = NULL;
  58. DWORD dwIndex = -1;
  59. DWORD cbData = 0;
  60. PBYTE pbAuthData = NULL;
  61. PBYTE pbUserIn = NULL;
  62. DWORD dwInSize = 0;
  63. BYTE *pUserDataOut;
  64. DWORD dwSizeOfUserDataOut;
  65. LPWSTR lpwszIdentity = NULL;
  66. HWND hwndOwner = NULL;
  67. HWINSTA hwinstaSave;
  68. HDESK hdeskSave;
  69. HWINSTA hwinstaUser;
  70. HDESK hdeskUser;
  71. DWORD dwThreadId;
  72. UNICODE_STRING IdentityUnicodeString;
  73. ANSI_STRING IdentityAnsiString;
  74. CHAR Buffer[256];
  75. WCHAR wszFriendlyName[256]; // Friendly name max 255 char
  76. CHAR *pszUserName = NULL;
  77. DWORD dwFlags = 0;
  78. DWORD dwRetCode = NO_ERROR;
  79. do
  80. {
  81. // If machine auth not enabled
  82. TRACE0 (USER, "ElGetUserIdentity entered");
  83. //
  84. // NOTE:
  85. // Optimize pPCB->rwLock lock holding time
  86. //
  87. ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
  88. if (pPCB->PreviousAuthenticationType != EAPOL_MACHINE_AUTHENTICATION)
  89. {
  90. if (!EAPOL_PORT_ACTIVE(pPCB))
  91. {
  92. TRACE1 (PORT, "ElGetUserIdentity: Port %s not active",
  93. pPCB->pszDeviceGUID);
  94. // Port is not active, cannot do further processing on this port
  95. break;
  96. }
  97. //
  98. // Get Access Token for user logged on interactively
  99. //
  100. // Call Terminal Services API
  101. if (GetWinStationUserToken (GetClientLogonId(), &hUserToken)
  102. != NO_ERROR)
  103. {
  104. TRACE0 (USER, "ElGetUserIdentity: Terminal Services API GetWinStationUserToken failed !!! ");
  105. // Call private API
  106. hUserToken = GetCurrentUserTokenW (L"WinSta0",
  107. TOKEN_QUERY |
  108. TOKEN_DUPLICATE |
  109. TOKEN_ASSIGN_PRIMARY);
  110. if (hUserToken == NULL)
  111. {
  112. dwRetCode = GetLastError ();
  113. TRACE1 (USER, "ElGetUserIdentity: Error in GetCurrentUserTokenW = %ld",
  114. dwRetCode);
  115. dwRetCode = ERROR_NO_TOKEN;
  116. break;
  117. }
  118. }
  119. if (hUserToken == NULL)
  120. {
  121. dwRetCode = GetLastError ();
  122. TRACE0 (USER, "ElGetUserIdentity: Error in getting current user token");
  123. dwRetCode = ERROR_NO_TOKEN;
  124. break;
  125. }
  126. pPCB->hUserToken = hUserToken;
  127. // Get the size of the user blob
  128. if ((dwRetCode = ElGetEapUserInfo (
  129. pPCB->hUserToken,
  130. pPCB->pszDeviceGUID,
  131. pPCB->dwEapTypeToBeUsed,
  132. pPCB->pszSSID,
  133. NULL,
  134. &dwInSize
  135. )) != NO_ERROR)
  136. {
  137. if (dwRetCode == ERROR_BUFFER_TOO_SMALL)
  138. {
  139. if (dwInSize <= 0)
  140. {
  141. // No blob stored in the registry
  142. // Continue processing
  143. TRACE0 (USER, "ElGetUserIdentity: NULL sized user data");
  144. pbUserIn = NULL;
  145. }
  146. else
  147. {
  148. // Allocate memory to hold the blob
  149. pbUserIn = MALLOC (dwInSize);
  150. if (pbUserIn == NULL)
  151. {
  152. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  153. TRACE0 (USER, "ElGetUserIdentity: Error in memory allocation for User data");
  154. break;
  155. }
  156. if ((dwRetCode = ElGetEapUserInfo (
  157. pPCB->hUserToken,
  158. pPCB->pszDeviceGUID,
  159. pPCB->dwEapTypeToBeUsed,
  160. pPCB->pszSSID,
  161. pbUserIn,
  162. &dwInSize
  163. )) != NO_ERROR)
  164. {
  165. TRACE1 (USER, "ElGetUserIdentity: ElGetEapUserInfo failed with %ld",
  166. dwRetCode);
  167. break;
  168. }
  169. }
  170. }
  171. else
  172. {
  173. // User info may not have been created till now
  174. // which is valid condition to proceed
  175. if (dwRetCode != ERROR_FILE_NOT_FOUND)
  176. {
  177. TRACE1 (USER, "ElGetUserIdentity: ElGetEapUserInfo size estimation failed with error %ld",
  178. dwRetCode);
  179. break;
  180. }
  181. }
  182. }
  183. // The EAP dll will have already been loaded by the state machine
  184. // Retrieve the handle to the dll from the global EAP table
  185. if ((dwIndex = ElGetEapTypeIndex (pPCB->dwEapTypeToBeUsed)) == -1)
  186. {
  187. TRACE1 (USER, "ElGetUserIdentity: ElGetEapTypeIndex finds no dll for EAP index %ld",
  188. pPCB->dwEapTypeToBeUsed);
  189. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  190. break;
  191. }
  192. hLib = g_pEapTable[dwIndex].hInstance;
  193. pIdenFunc = (EAPOLEAPGETIDENTITY)GetProcAddress(hLib,
  194. "RasEapGetIdentity");
  195. pFreeFunc = (EAPOLEAPFREE)GetProcAddress(hLib, "RasEapFreeMemory");
  196. if ((pFreeFunc == NULL) || (pIdenFunc == NULL))
  197. {
  198. TRACE0 (USER, "ElGetUserIdentity: pIdenFunc or pFreeFunc does not exist in the EAP implementation");
  199. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  200. break;
  201. }
  202. // Get the size of the EAP blob
  203. if ((dwRetCode = ElGetCustomAuthData (
  204. pPCB->pszDeviceGUID,
  205. pPCB->dwEapTypeToBeUsed,
  206. pPCB->pszSSID,
  207. NULL,
  208. &cbData
  209. )) != NO_ERROR)
  210. {
  211. if (dwRetCode == ERROR_BUFFER_TOO_SMALL)
  212. {
  213. if (cbData <= 0)
  214. {
  215. // No EAP blob stored in the registry
  216. TRACE0 (USER, "ElGetUserIdentity: NULL sized EAP blob, cannot continue");
  217. pbAuthData = NULL;
  218. // Every port should have connection data !!!
  219. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  220. break;
  221. }
  222. else
  223. {
  224. // Allocate memory to hold the blob
  225. pbAuthData = MALLOC (cbData);
  226. if (pbAuthData == NULL)
  227. {
  228. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  229. TRACE0 (USER, "ElGetUserIdentity: Error in memory allocation for EAP blob");
  230. break;
  231. }
  232. if ((dwRetCode = ElGetCustomAuthData (
  233. pPCB->pszDeviceGUID,
  234. pPCB->dwEapTypeToBeUsed,
  235. pPCB->pszSSID,
  236. pbAuthData,
  237. &cbData
  238. )) != NO_ERROR)
  239. {
  240. TRACE1 (USER, "ElGetUserIdentity: ElGetCustomAuthData failed with %ld",
  241. dwRetCode);
  242. break;
  243. }
  244. }
  245. }
  246. else
  247. {
  248. // CustomAuthData for "Default" is always created for an
  249. // interface when EAPOL starts up
  250. TRACE1 (USER, "ElGetUserIdentity: ElGetCustomAuthData size estimation failed with error %ld",
  251. dwRetCode);
  252. break;
  253. }
  254. }
  255. // Save handles to service window
  256. hwinstaSave = GetProcessWindowStation();
  257. if (hwinstaSave == NULL)
  258. {
  259. dwRetCode = GetLastError ();
  260. TRACE1 (USER, "OpenWindowStation: GetProcessWindowStation failed with error %ld",
  261. dwRetCode);
  262. break;
  263. }
  264. dwThreadId = GetCurrentThreadId ();
  265. hdeskSave = GetThreadDesktop (dwThreadId);
  266. if (hdeskSave == NULL)
  267. {
  268. dwRetCode = GetLastError ();
  269. TRACE1 (USER, "OpenWindowStation: GetThreadDesktop failed with error %ld",
  270. dwRetCode);
  271. break;
  272. }
  273. if (!ImpersonateLoggedOnUser (pPCB->hUserToken))
  274. {
  275. dwRetCode = GetLastError();
  276. TRACE1 (USER, "ElGetUserIdentity: ImpersonateLoggedOnUse failed with error %ld",
  277. dwRetCode);
  278. break;
  279. }
  280. // Impersonate the client and connect to the User's window station
  281. // and desktop. This will be the interactively logged-on user
  282. hwinstaUser = OpenWindowStation (L"WinSta0", FALSE, MAXIMUM_ALLOWED);
  283. if (hwinstaUser == NULL)
  284. {
  285. dwRetCode = GetLastError ();
  286. TRACE1 (USER, "OpenWindowStation: OpenWindowStation failed with error %ld",
  287. dwRetCode);
  288. break;
  289. }
  290. if (!SetProcessWindowStation(hwinstaUser))
  291. TRACE1 (USER, "ElGetUserIdentity: SetProcessWindowStation failed with error = %ld",
  292. (dwRetCode = GetLastError()));
  293. hdeskUser = OpenDesktop (L"Default", 0, FALSE, MAXIMUM_ALLOWED);
  294. if (hdeskUser == NULL)
  295. {
  296. if (!SetProcessWindowStation (hwinstaSave))
  297. TRACE1 (USER, "ElGetUserIdentity: SetProcessWindowStation failed with error = %ld",
  298. (dwRetCode = GetLastError()));
  299. if (!CloseWindowStation (hwinstaUser))
  300. TRACE1 (USER, "ElGetUserIdentity: CloseWindowStation failed with error = %ld",
  301. (dwRetCode = GetLastError()));
  302. dwRetCode = ERROR_INVALID_WORKSTATION;
  303. break;
  304. }
  305. if (!SetThreadDesktop (hdeskUser))
  306. TRACE1 (USER, "ElGetUserIdentity: SetThreadDesktop failed with error = %ld",
  307. (dwRetCode = GetLastError()));
  308. // Get handle to desktop window
  309. hwndOwner = GetDesktopWindow ();
  310. ZeroMemory (wszFriendlyName, 256*sizeof(WCHAR));
  311. // Convert the friendly name of the adapter to a display ready
  312. // form
  313. if (pPCB->pszFriendlyName)
  314. {
  315. if (0 == MultiByteToWideChar(
  316. CP_ACP,
  317. 0,
  318. pPCB->pszFriendlyName,
  319. -1,
  320. wszFriendlyName,
  321. 256 ) )
  322. {
  323. dwRetCode = GetLastError();
  324. TRACE2 (USER, "ElGetUserIdentity: MultiByteToWideChar(%s) failed: %d",
  325. pPCB->pszFriendlyName,
  326. dwRetCode);
  327. break;
  328. }
  329. }
  330. if (pIdenFunc)
  331. if ((dwRetCode = (*(pIdenFunc))(
  332. pPCB->dwEapTypeToBeUsed,
  333. hwndOwner, // hwndOwner
  334. 0, // dwFlags
  335. NULL, // lpszPhonebook
  336. wszFriendlyName, // lpszEntry
  337. pbAuthData, // Connection data
  338. cbData, // Count of pbAuthData
  339. pbUserIn, // User data for port
  340. dwInSize, // Size of user data
  341. &pUserDataOut,
  342. &dwSizeOfUserDataOut,
  343. &lpwszIdentity
  344. )) != NO_ERROR)
  345. {
  346. TRACE1 (USER, "ElGetUserIdentity: Error in calling GetIdentity = %ld",
  347. dwRetCode);
  348. // Revert impersonation
  349. if (!RevertToSelf())
  350. {
  351. dwRetCode = GetLastError();
  352. TRACE1 (USER, "ElGetUserIdentity: Error in RevertToSelf = %ld",
  353. dwRetCode);
  354. }
  355. // Restore window station and desktop
  356. if (!SetThreadDesktop (hdeskSave))
  357. TRACE1 (USER, "ElGetUserIdentity: SetThreadDesktop failed with error = %ld",
  358. (dwRetCode = GetLastError()));
  359. if (!SetProcessWindowStation (hwinstaSave))
  360. TRACE1 (USER, "ElGetUserIdentity: SetProcessWindowStation failed with error = %ld",
  361. (dwRetCode = GetLastError()));
  362. if (!CloseDesktop(hdeskUser))
  363. TRACE1 (USER, "ElGetUserIdentity: CloseDesktop failed with error = %ld",
  364. (dwRetCode = GetLastError()));
  365. if (!CloseWindowStation(hwinstaUser))
  366. TRACE1 (USER, "ElGetUserIdentity: CloseWindowStation failed with error = %ld",
  367. (dwRetCode = GetLastError()));
  368. break;
  369. }
  370. // Revert impersonation
  371. if (!RevertToSelf())
  372. {
  373. dwRetCode = GetLastError();
  374. TRACE1 (USER, "ElGetUserIdentity: Error in RevertToSelf = %ld",
  375. dwRetCode);
  376. // Restore window station and desktop
  377. if (!SetThreadDesktop (hdeskSave))
  378. TRACE1 (USER, "ElGetUserIdentity: SetThreadDesktop failed with error = %ld",
  379. (dwRetCode = GetLastError()));
  380. if (!SetProcessWindowStation (hwinstaSave))
  381. TRACE1 (USER, "ElGetUserIdentity: SetProcessWindowStation failed with error = %ld",
  382. (dwRetCode = GetLastError()));
  383. if (!CloseDesktop(hdeskUser))
  384. TRACE1 (USER, "ElGetUserIdentity: CloseDesktop failed with error = %ld",
  385. (dwRetCode = GetLastError()));
  386. if (!CloseWindowStation(hwinstaUser))
  387. TRACE1 (USER, "ElGetUserIdentity: CloseWindowStation failed with error = %ld",
  388. (dwRetCode = GetLastError()));
  389. break;
  390. }
  391. // Restore window station and desktop settings
  392. if (!SetThreadDesktop (hdeskSave))
  393. TRACE1 (USER, "ElGetUserIdentity: SetThreadDesktop failed with error = %ld",
  394. (dwRetCode = GetLastError()));
  395. if (!SetProcessWindowStation (hwinstaSave))
  396. TRACE1 (USER, "ElGetUserIdentity: SetProcessWindowStation failed with error = %ld",
  397. (dwRetCode = GetLastError()));
  398. if (!CloseDesktop(hdeskUser))
  399. TRACE1 (USER, "ElGetUserIdentity: CloseDesktop failed with error = %ld",
  400. (dwRetCode = GetLastError()));
  401. if (!CloseWindowStation(hwinstaUser))
  402. TRACE1 (USER, "ElGetUserIdentity: CloseWindowStation failed with error = %ld",
  403. (dwRetCode = GetLastError()));
  404. // Fill in the returned information into the PCB fields for
  405. // later authentication
  406. if (pPCB->pCustomAuthUserData != NULL)
  407. {
  408. FREE (pPCB->pCustomAuthUserData);
  409. pPCB->pCustomAuthUserData = NULL;
  410. }
  411. pPCB->pCustomAuthUserData = MALLOC (dwSizeOfUserDataOut + sizeof (DWORD));
  412. if (pPCB->pCustomAuthUserData == NULL)
  413. {
  414. TRACE1 (USER, "ElGetUserIdentity: Error in allocating memory for UserInfo = %ld",
  415. dwRetCode);
  416. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  417. break;
  418. }
  419. pPCB->pCustomAuthUserData->dwSizeOfCustomAuthData = dwSizeOfUserDataOut;
  420. if ((dwSizeOfUserDataOut != 0) && (pUserDataOut != NULL))
  421. {
  422. memcpy ((BYTE *)pPCB->pCustomAuthUserData->pbCustomAuthData,
  423. (BYTE *)pUserDataOut,
  424. dwSizeOfUserDataOut);
  425. }
  426. if (lpwszIdentity != NULL)
  427. {
  428. // NOTE:
  429. // Assuming 256 character identity maximum
  430. // Convert wchar Identity to char string
  431. RtlInitUnicodeString (&IdentityUnicodeString, lpwszIdentity);
  432. IdentityAnsiString.MaximumLength = sizeof(Buffer);
  433. IdentityAnsiString.Buffer = Buffer;
  434. IdentityAnsiString.Length = 0;
  435. if ((dwRetCode = RtlUnicodeStringToAnsiString (
  436. &IdentityAnsiString,
  437. &IdentityUnicodeString,
  438. FALSE)) != NO_ERROR)
  439. {
  440. TRACE1 (USER, "ElGetUserIdentity: Error in RtlConvertUnicodeStringToAnsiString = %ld",
  441. dwRetCode);
  442. break;
  443. }
  444. pszUserName = MALLOC (IdentityAnsiString.Length + 1);
  445. if (pszUserName == NULL)
  446. {
  447. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  448. TRACE0 (USER, "ElGetUserIdentity: MALLOC failed for pszUserName");
  449. break;
  450. }
  451. memcpy (pszUserName,
  452. IdentityAnsiString.Buffer,
  453. IdentityAnsiString.Length);
  454. pszUserName[IdentityAnsiString.Length] = '\0';
  455. if (pPCB->pszIdentity != NULL)
  456. {
  457. FREE (pPCB->pszIdentity);
  458. pPCB->pszIdentity = NULL;
  459. }
  460. pPCB->pszIdentity = MALLOC (IdentityAnsiString.Length + 1);
  461. if (pPCB->pszIdentity == NULL)
  462. {
  463. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  464. TRACE0 (USER, "ElGetUserIdentity: MALLOC failed for pPCB->pszIdentity");
  465. break;
  466. }
  467. memcpy (pPCB->pszIdentity,
  468. IdentityAnsiString.Buffer,
  469. IdentityAnsiString.Length);
  470. pPCB->pszIdentity[IdentityAnsiString.Length] = '\0';
  471. TRACE1 (USER, "ElGetUserIdentity: Got username = %s",
  472. pszUserName);
  473. }
  474. if (pPCB->pCustomAuthConnData != NULL)
  475. {
  476. FREE (pPCB->pCustomAuthConnData);
  477. pPCB->pCustomAuthConnData = NULL;
  478. }
  479. // Memory for pCustomAuthConnData and pCustomAuthUserData
  480. // is released from the PCB when user logs off and during
  481. // port deletion
  482. pPCB->pCustomAuthConnData = MALLOC (cbData + sizeof (DWORD));
  483. if (pPCB->pCustomAuthConnData == NULL)
  484. {
  485. TRACE1 (USER, "ElGetUserIdentity: Error in allocating memory for AuthInfo = %ld",
  486. dwRetCode);
  487. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  488. break;
  489. }
  490. pPCB->pCustomAuthConnData->dwSizeOfCustomAuthData = cbData;
  491. if ((cbData != 0) && (pbAuthData != NULL))
  492. {
  493. memcpy ((BYTE *)pPCB->pCustomAuthConnData->pbCustomAuthData,
  494. (BYTE *)pbAuthData,
  495. cbData);
  496. }
  497. // Mark the identity has been obtained for this PCB
  498. pPCB->fGotUserIdentity = TRUE;
  499. }
  500. else // MACHINE_AUTHENTICATION
  501. {
  502. TRACE0 (USER, "ElGetUserIdentity entered");
  503. if (!EAPOL_PORT_ACTIVE(pPCB))
  504. {
  505. TRACE1 (PORT, "ElGetUserIdentity: Port %s not active",
  506. pPCB->pszDeviceGUID);
  507. // Port is not active, cannot do further processing on this port
  508. break;
  509. }
  510. // The EAP dll will have already been loaded by the state machine
  511. // Retrieve the handle to the dll from the global EAP table
  512. if ((dwIndex = ElGetEapTypeIndex (pPCB->dwEapTypeToBeUsed)) == -1)
  513. {
  514. TRACE1 (USER, "ElGetUserIdentity: ElGetEapTypeIndex finds no dll for EAP index %ld",
  515. pPCB->dwEapTypeToBeUsed);
  516. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  517. break;
  518. }
  519. hLib = g_pEapTable[dwIndex].hInstance;
  520. pIdenFunc = (EAPOLEAPGETIDENTITY)GetProcAddress(hLib,
  521. "RasEapGetIdentity");
  522. pFreeFunc = (EAPOLEAPFREE)GetProcAddress(hLib, "RasEapFreeMemory");
  523. if ((pFreeFunc == NULL) || (pIdenFunc == NULL))
  524. {
  525. TRACE0 (USER, "ElGetUserIdentity: pIdenFunc or pFreeFunc does not exist in the EAP implementation");
  526. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  527. break;
  528. }
  529. // Get the size of the EAP blob
  530. if ((dwRetCode = ElGetCustomAuthData (
  531. pPCB->pszDeviceGUID,
  532. pPCB->dwEapTypeToBeUsed,
  533. pPCB->pszSSID,
  534. NULL,
  535. &cbData
  536. )) != NO_ERROR)
  537. {
  538. if (dwRetCode == ERROR_BUFFER_TOO_SMALL)
  539. {
  540. if (cbData <= 0)
  541. {
  542. // No EAP blob stored in the registry
  543. TRACE0 (USER, "ElGetUserIdentity: NULL sized EAP blob, cannot continue");
  544. pbAuthData = NULL;
  545. // Every port should have connection data !!!
  546. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  547. break;
  548. }
  549. else
  550. {
  551. // Allocate memory to hold the blob
  552. pbAuthData = MALLOC (cbData);
  553. if (pbAuthData == NULL)
  554. {
  555. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  556. TRACE0 (USER, "ElGetUserIdentity: Error in memory allocation for EAP blob");
  557. break;
  558. }
  559. if ((dwRetCode = ElGetCustomAuthData (
  560. pPCB->pszDeviceGUID,
  561. pPCB->dwEapTypeToBeUsed,
  562. pPCB->pszSSID,
  563. pbAuthData,
  564. &cbData
  565. )) != NO_ERROR)
  566. {
  567. TRACE1 (USER, "ElGetUserIdentity: ElGetCustomAuthData failed with %ld",
  568. dwRetCode);
  569. break;
  570. }
  571. }
  572. }
  573. else
  574. {
  575. // CustomAuthData for "Default" is always created for an
  576. // interface when EAPOL starts up
  577. TRACE1 (USER, "ElGetUserIdentity: ElGetCustomAuthData size estimation failed with error %ld",
  578. dwRetCode);
  579. break;
  580. }
  581. }
  582. if (pIdenFunc)
  583. if ((dwRetCode = (*(pIdenFunc))(
  584. pPCB->dwEapTypeToBeUsed,
  585. hwndOwner, // hwndOwner
  586. RAS_EAP_FLAG_MACHINE_AUTH, // dwFlags
  587. NULL, // lpszPhonebook
  588. wszFriendlyName, // lpszEntry
  589. pbAuthData, // Connection data
  590. cbData, // Count of pbAuthData
  591. pbUserIn, // User data for port
  592. dwInSize, // Size of user data
  593. &pUserDataOut,
  594. &dwSizeOfUserDataOut,
  595. &lpwszIdentity
  596. )) != NO_ERROR)
  597. {
  598. TRACE1 (USER, "ElGetUserIdentity: Error in calling GetIdentity = %ld",
  599. dwRetCode);
  600. break;
  601. }
  602. // Fill in the returned information into the PCB fields for
  603. // later authentication
  604. if (pPCB->pCustomAuthUserData != NULL)
  605. {
  606. FREE (pPCB->pCustomAuthUserData);
  607. pPCB->pCustomAuthUserData = NULL;
  608. }
  609. pPCB->pCustomAuthUserData = MALLOC (dwSizeOfUserDataOut + sizeof (DWORD));
  610. if (pPCB->pCustomAuthUserData == NULL)
  611. {
  612. TRACE1 (USER, "ElGetUserIdentity: Error in allocating memory for UserInfo = %ld",
  613. dwRetCode);
  614. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  615. break;
  616. }
  617. pPCB->pCustomAuthUserData->dwSizeOfCustomAuthData = dwSizeOfUserDataOut;
  618. if ((dwSizeOfUserDataOut != 0) && (pUserDataOut != NULL))
  619. {
  620. memcpy ((BYTE *)pPCB->pCustomAuthUserData->pbCustomAuthData,
  621. (BYTE *)pUserDataOut,
  622. dwSizeOfUserDataOut);
  623. }
  624. if (lpwszIdentity != NULL)
  625. {
  626. // NOTE:
  627. // Assuming 256 character identity maximum
  628. // Convert wchar Identity to char string
  629. RtlInitUnicodeString (&IdentityUnicodeString, lpwszIdentity);
  630. IdentityAnsiString.MaximumLength = sizeof(Buffer);
  631. IdentityAnsiString.Buffer = Buffer;
  632. IdentityAnsiString.Length = 0;
  633. if ((dwRetCode = RtlUnicodeStringToAnsiString (
  634. &IdentityAnsiString,
  635. &IdentityUnicodeString,
  636. FALSE)) != NO_ERROR)
  637. {
  638. TRACE1 (USER, "ElGetUserIdentity: Error in RtlConvertUnicodeStringToAnsiString = %ld",
  639. dwRetCode);
  640. break;
  641. }
  642. TRACE1 (USER, "lpwszIdentity = %ws", lpwszIdentity);
  643. pszUserName = MALLOC (IdentityAnsiString.Length + 1);
  644. if (pszUserName == NULL)
  645. {
  646. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  647. TRACE0 (USER, "ElGetUserIdentity: MALLOC failed for pszUserName");
  648. break;
  649. }
  650. memcpy (pszUserName,
  651. IdentityAnsiString.Buffer,
  652. IdentityAnsiString.Length);
  653. pszUserName[IdentityAnsiString.Length] = '\0';
  654. TRACE1 (USER, "pszUserName = %s", pszUserName);
  655. if (pPCB->pszIdentity != NULL)
  656. {
  657. FREE (pPCB->pszIdentity);
  658. pPCB->pszIdentity = NULL;
  659. }
  660. pPCB->pszIdentity = MALLOC (IdentityAnsiString.Length + 1);
  661. if (pPCB->pszIdentity == NULL)
  662. {
  663. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  664. TRACE0 (USER, "ElGetUserIdentity: MALLOC failed for pPCB->pszIdentity");
  665. break;
  666. }
  667. memcpy (pPCB->pszIdentity,
  668. IdentityAnsiString.Buffer,
  669. IdentityAnsiString.Length);
  670. pPCB->pszIdentity[IdentityAnsiString.Length] = '\0';
  671. TRACE1 (USER, "ElGetUserIdentity: Got username = %s",
  672. pszUserName);
  673. }
  674. if (pPCB->pCustomAuthConnData != NULL)
  675. {
  676. FREE (pPCB->pCustomAuthConnData);
  677. pPCB->pCustomAuthConnData = NULL;
  678. }
  679. // Memory for pCustomAuthConnData and pCustomAuthUserData
  680. // is released from the PCB when user logs off and during
  681. // port deletion
  682. pPCB->pCustomAuthConnData = MALLOC (cbData + sizeof (DWORD));
  683. if (pPCB->pCustomAuthConnData == NULL)
  684. {
  685. TRACE1 (USER, "ElGetUserIdentity: Error in allocating memory for AuthInfo = %ld",
  686. dwRetCode);
  687. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  688. break;
  689. }
  690. pPCB->pCustomAuthConnData->dwSizeOfCustomAuthData = cbData;
  691. if ((cbData != 0) && (pbAuthData != NULL))
  692. {
  693. memcpy ((BYTE *)pPCB->pCustomAuthConnData->pbCustomAuthData,
  694. (BYTE *)pbAuthData,
  695. cbData);
  696. }
  697. // Mark the identity has been obtained for this PCB
  698. pPCB->fGotUserIdentity = TRUE;
  699. }
  700. // Release the per-interface lock
  701. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  702. } while (FALSE);
  703. // Cleanup
  704. if (dwRetCode != NO_ERROR)
  705. {
  706. // Release the per-interface lock
  707. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  708. if (pPCB->pCustomAuthUserData != NULL)
  709. {
  710. FREE (pPCB->pCustomAuthUserData);
  711. pPCB->pCustomAuthUserData = NULL;
  712. }
  713. if (pPCB->pCustomAuthConnData != NULL)
  714. {
  715. FREE (pPCB->pCustomAuthConnData);
  716. pPCB->pCustomAuthConnData = NULL;
  717. }
  718. if (pPCB->pszIdentity != NULL)
  719. {
  720. FREE (pPCB->pszIdentity);
  721. pPCB->pszIdentity = NULL;
  722. }
  723. }
  724. if (pbUserIn != NULL)
  725. {
  726. FREE (pbUserIn);
  727. }
  728. if (pbAuthData != NULL)
  729. {
  730. FREE (pbAuthData);
  731. }
  732. if (pszUserName != NULL)
  733. {
  734. FREE (pszUserName);
  735. }
  736. if (pFreeFunc != NULL)
  737. {
  738. if (lpwszIdentity != NULL)
  739. {
  740. if (( dwRetCode = (*(pFreeFunc)) ((BYTE *)lpwszIdentity)) != NO_ERROR)
  741. {
  742. TRACE1 (USER, "ElGetUserIdentity: Error in pFreeFunc = %ld",
  743. dwRetCode);
  744. }
  745. }
  746. if (pUserDataOut != NULL)
  747. {
  748. if (( dwRetCode = (*(pFreeFunc)) ((BYTE *)pUserDataOut)) != NO_ERROR)
  749. {
  750. TRACE1 (USER, "ElGetUserIdentity: Error in pFreeFunc = %ld",
  751. dwRetCode);
  752. }
  753. }
  754. }
  755. TRACE1 (USER, "ElGetUserIdentity completed with error %ld", dwRetCode);
  756. return dwRetCode;
  757. }
  758. //
  759. // ElUserLogonCallback
  760. //
  761. // Description:
  762. //
  763. // Callback function invoked whenever a user logs in
  764. // Will initiate authentication process on all ports of LAN class
  765. // Credentials for the user in case of EAP-TLS can be obtained by
  766. // acquiring user token
  767. // For EAP-CHAP, WinLogon cerdentials will need to be supplied
  768. //
  769. // Arguments:
  770. // None.
  771. //
  772. VOID
  773. ElUserLogonCallback (
  774. PVOID pvContext,
  775. BOOLEAN fTimerOfWaitFired
  776. )
  777. {
  778. DWORD dwIndex = 0;
  779. EAPOL_PCB *pPCB = NULL;
  780. BOOL fSetCONNECTINGState = FALSE;
  781. DWORD dwRetCode = NO_ERROR;
  782. // Set global flag to indicate the user logged on
  783. TRACE1 (USER, "ElUserLogonCallback: UserloggedOn = %ld",
  784. g_fUserLoggedOn);
  785. g_fUserLoggedOn = InterlockedIncrement (&(g_fUserLoggedOn));
  786. do
  787. {
  788. ACQUIRE_WRITE_LOCK (&(g_PCBLock));
  789. for (dwIndex = 0; dwIndex < PORT_TABLE_BUCKETS; dwIndex++)
  790. {
  791. for (pPCB = g_PCBTable.pPCBBuckets[dwIndex].pPorts;
  792. pPCB != NULL;
  793. pPCB = pPCB->pNext)
  794. {
  795. #ifdef DRAFT7
  796. if (g_dwMachineAuthEnabled)
  797. {
  798. #endif
  799. fSetCONNECTINGState = FALSE;
  800. ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
  801. switch (pPCB->State)
  802. {
  803. case EAPOLSTATE_CONNECTING:
  804. case EAPOLSTATE_ACQUIRED:
  805. case EAPOLSTATE_AUTHENTICATING:
  806. // Reset AuthFailCount conditionally
  807. pPCB->dwAuthFailCount = 0;
  808. // fall through
  809. case EAPOLSTATE_HELD:
  810. // End EAP session
  811. (VOID) ElEapEnd (pPCB);
  812. fSetCONNECTINGState = TRUE;
  813. break;
  814. case EAPOLSTATE_AUTHENTICATED:
  815. if (pPCB->PreviousAuthenticationType ==
  816. EAPOL_UNAUTHENTICATED_ACCESS)
  817. {
  818. // Reset AuthFailCount
  819. pPCB->dwAuthFailCount = 0;
  820. fSetCONNECTINGState = TRUE;
  821. }
  822. break;
  823. default:
  824. break;
  825. }
  826. if (!EAPOL_PORT_ACTIVE(pPCB))
  827. {
  828. TRACE1 (USER, "ElUserLogonCallback: Port %s not active",
  829. pPCB->pszDeviceGUID);
  830. fSetCONNECTINGState = FALSE;
  831. }
  832. // Set port to EAPOLSTATE_CONNECTING
  833. if (fSetCONNECTINGState)
  834. {
  835. pPCB->dwAuthFailCount = 0;
  836. // With unauthenticated access flag set, port will always
  837. // reauthenticate for logged on user
  838. pPCB->PreviousAuthenticationType =
  839. EAPOL_UNAUTHENTICATED_ACCESS;
  840. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  841. // Restart authentication on the port
  842. if ((dwRetCode = ElReStartPort (pPCB)) != NO_ERROR)
  843. {
  844. TRACE1 (USER, "ElUserLogonCallback: MachineAuth: Error in ElReStartPort = %ld",
  845. dwRetCode);
  846. continue;
  847. }
  848. }
  849. else
  850. {
  851. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  852. continue;
  853. }
  854. #ifdef DRAFT7
  855. }
  856. else
  857. {
  858. ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
  859. // If the port is already authenticated due to non-secure
  860. // LAN, authentication can be skipped for this port
  861. if (pPCB->State == EAPOLSTATE_AUTHENTICATED)
  862. {
  863. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  864. TRACE0 (USER, "ElUserLogonCallback: Port already authenticated, continuing with next port");
  865. continue;
  866. }
  867. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  868. // Restart authentication on the port
  869. if ((dwRetCode = ElReStartPort (pPCB)) != NO_ERROR)
  870. {
  871. TRACE1 (USER, "ElUserLogonCallback: Error in ElReStartPort = %ld",
  872. dwRetCode);
  873. break;
  874. }
  875. TRACE1 (USER, "ElUserLogonCallback: = Authentication restarted on port %p",
  876. pPCB);
  877. } // g_dwMachineAuthEnabled
  878. #endif
  879. }
  880. }
  881. RELEASE_WRITE_LOCK (&(g_PCBLock));
  882. if (dwRetCode != NO_ERROR)
  883. {
  884. break;
  885. }
  886. } while (FALSE);
  887. TRACE1 (USER, "ElUserLogonCallback: completed with error %ld", dwRetCode);
  888. return;
  889. }
  890. //
  891. // ElUserLogoffCallback
  892. //
  893. // Description:
  894. //
  895. // Callback function invoked whenever a user logs off
  896. // Will logoff from all ports which have authentication enabled
  897. //
  898. // Arguments:
  899. // None.
  900. //
  901. VOID
  902. ElUserLogoffCallback (
  903. PVOID pvContext,
  904. BOOLEAN fTimerOfWaitFired
  905. )
  906. {
  907. DWORD dwIndex = 0;
  908. EAPOL_PCB *pPCB = NULL;
  909. BOOL fSetCONNECTINGState = FALSE;
  910. DWORD dwRetCode = NO_ERROR;
  911. // Reset global flag to indicate the user logged on
  912. g_fUserLoggedOn = 0;
  913. TRACE1 (USER, "ElUserLogoffCallback: UserloggedOff = %ld",
  914. g_fUserLoggedOn);
  915. ACQUIRE_WRITE_LOCK (&(g_PCBLock));
  916. for (dwIndex = 0; dwIndex < PORT_TABLE_BUCKETS; dwIndex++)
  917. {
  918. for (pPCB = g_PCBTable.pPCBBuckets[dwIndex].pPorts;
  919. pPCB != NULL;
  920. pPCB = pPCB->pNext)
  921. {
  922. #ifdef DRAFT7
  923. if (g_dwMachineAuthEnabled)
  924. {
  925. #endif
  926. fSetCONNECTINGState = FALSE;
  927. ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
  928. switch (pPCB->State)
  929. {
  930. case EAPOLSTATE_CONNECTING:
  931. case EAPOLSTATE_ACQUIRED:
  932. case EAPOLSTATE_AUTHENTICATING:
  933. // Reset AuthFailCount conditionally
  934. pPCB->dwAuthFailCount = 0;
  935. // fall through
  936. case EAPOLSTATE_HELD:
  937. // End EAP session
  938. (VOID) ElEapEnd (pPCB);
  939. fSetCONNECTINGState = TRUE;
  940. break;
  941. case EAPOLSTATE_AUTHENTICATED:
  942. if (pPCB->PreviousAuthenticationType ==
  943. EAPOL_USER_AUTHENTICATION)
  944. {
  945. // Reset AuthFailCount
  946. pPCB->dwAuthFailCount = 0;
  947. fSetCONNECTINGState = TRUE;
  948. }
  949. break;
  950. default:
  951. break;
  952. }
  953. // Set port to EAPOLSTATE_CONNECTING
  954. if (fSetCONNECTINGState)
  955. {
  956. pPCB->dwAuthFailCount = 0;
  957. // With Unauthenticated_access, port will always
  958. // reauthenticate
  959. pPCB->PreviousAuthenticationType =
  960. EAPOL_UNAUTHENTICATED_ACCESS;
  961. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  962. // Restart authentication on the port
  963. if ((dwRetCode = ElReStartPort (pPCB)) != NO_ERROR)
  964. {
  965. TRACE1 (USER, "ElUserLogoffCallback: MachineAuth: Error in ElReStartPort = %ld",
  966. dwRetCode);
  967. continue;
  968. }
  969. }
  970. else
  971. {
  972. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  973. continue;
  974. }
  975. #ifdef DRAFT7
  976. }
  977. else
  978. {
  979. ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
  980. // If remote end has sent responses earlier and if EAPOL_Logoff
  981. // was not sent out on this port, send out EAPOL_Logoff
  982. if ((pPCB->fIsRemoteEndEAPOLAware) && (!(pPCB->dwLogoffSent)))
  983. {
  984. // End EAP session
  985. // Will always return NO_ERROR, so no check on return value
  986. (VOID) ElEapEnd (pPCB);
  987. // Send out EAPOL_Logoff on the port
  988. if ((dwRetCode = FSMLogoff (pPCB)) != NO_ERROR)
  989. {
  990. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  991. TRACE1 (USER, "ElUserLogoffCallback: Error in FSMLogoff = %ld",
  992. dwRetCode);
  993. continue;
  994. }
  995. }
  996. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  997. TRACE1 (USER, "ElUserLogoffCallback: = Logoff sent out on port %p",
  998. pPCB);
  999. } // g_dwMachineAuthEnabled
  1000. #endif
  1001. }
  1002. }
  1003. RELEASE_WRITE_LOCK (&(g_PCBLock));
  1004. TRACE0 (USER, "ElUserLogonCallback: completed");
  1005. return;
  1006. }
  1007. //
  1008. // ElGetUserNamePassword
  1009. //
  1010. // Description:
  1011. //
  1012. // Function called to get username, domain (if any) and password using
  1013. // an interactive dialog. Called if EAP-type is MD5
  1014. //
  1015. // Arguments:
  1016. // pPCB - Pointer to PCB for the port/interface on which credentials
  1017. // are to be obtained
  1018. //
  1019. // Return values:
  1020. // NO_ERROR - success
  1021. // non-zero - error
  1022. //
  1023. //
  1024. // NOTE: Could be done in a better way. Require EAP config structures
  1025. // as in ..\ras\ui\rasdlg\dial.c
  1026. //
  1027. DWORD
  1028. ElGetUserNamePassword (
  1029. IN EAPOL_PCB *pPCB
  1030. )
  1031. {
  1032. HANDLE hUserToken;
  1033. DWORD dwIndex = -1;
  1034. DWORD dwInSize = 0;
  1035. HWND hwndOwner = NULL;
  1036. HWINSTA hwinstaSave;
  1037. HDESK hdeskSave;
  1038. HWINSTA hwinstaUser;
  1039. HDESK hdeskUser;
  1040. DWORD dwThreadId;
  1041. DWORD dwRetCode = NO_ERROR;
  1042. do
  1043. {
  1044. TRACE0 (USER, "ElGetUserNamePassword entered");
  1045. //
  1046. // NOTE:
  1047. // Optimize pPCB->rwLock lock holding time
  1048. //
  1049. ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
  1050. if (!EAPOL_PORT_ACTIVE(pPCB))
  1051. {
  1052. TRACE1 (PORT, "ElGetUserNamePassword: Port %s not active",
  1053. pPCB->pszDeviceGUID);
  1054. // Port is not active, cannot do further processing on this port
  1055. break;
  1056. }
  1057. //
  1058. // Get Access Token for user logged on interactively
  1059. //
  1060. // Call Terminal Services API
  1061. if (GetWinStationUserToken (GetClientLogonId(), &hUserToken)
  1062. != NO_ERROR)
  1063. {
  1064. TRACE0 (USER, "ElGetUserNamePassword: Terminal Services API GetWinStationUserToken failed !!! ");
  1065. // Call private API
  1066. hUserToken = GetCurrentUserTokenW (L"WinSta0",
  1067. TOKEN_QUERY |
  1068. TOKEN_DUPLICATE |
  1069. TOKEN_ASSIGN_PRIMARY);
  1070. if (hUserToken == NULL)
  1071. {
  1072. dwRetCode = GetLastError ();
  1073. TRACE1 (USER, "ElGetUserNamePassword: Error in GetCurrentUserTokenW = %ld",
  1074. dwRetCode);
  1075. dwRetCode = ERROR_NO_TOKEN;
  1076. break;
  1077. }
  1078. }
  1079. if (hUserToken == NULL)
  1080. {
  1081. dwRetCode = GetLastError ();
  1082. TRACE0 (USER, "ElGetUserNamePassword: Error in getting current user token");
  1083. dwRetCode = ERROR_NO_TOKEN;
  1084. break;
  1085. }
  1086. pPCB->hUserToken = hUserToken;
  1087. // The EAP dll will have already been loaded by the state machine
  1088. // Retrieve the handle to the dll from the global EAP table
  1089. if ((dwIndex = ElGetEapTypeIndex (pPCB->dwEapTypeToBeUsed)) == -1)
  1090. {
  1091. TRACE1 (USER, "ElGetUserNamePassword: ElGetEapTypeIndex finds no dll for EAP index %ld",
  1092. pPCB->dwEapTypeToBeUsed);
  1093. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  1094. break;
  1095. }
  1096. // Save handles to service window
  1097. hwinstaSave = GetProcessWindowStation();
  1098. if (hwinstaSave == NULL)
  1099. {
  1100. dwRetCode = GetLastError ();
  1101. TRACE1 (USER, "ElGetUserNamePassword: GetProcessWindowStation failed with error %ld",
  1102. dwRetCode);
  1103. break;
  1104. }
  1105. dwThreadId = GetCurrentThreadId ();
  1106. hdeskSave = GetThreadDesktop (dwThreadId);
  1107. if (hdeskSave == NULL)
  1108. {
  1109. dwRetCode = GetLastError ();
  1110. TRACE1 (USER, "ElGetUserNamePassword: GetThreadDesktop failed with error %ld",
  1111. dwRetCode);
  1112. break;
  1113. }
  1114. if (!ImpersonateLoggedOnUser (pPCB->hUserToken))
  1115. {
  1116. dwRetCode = GetLastError();
  1117. TRACE1 (USER, "ElGetUserNamePassword: ImpersonateLoggedOnUse failed with error %ld",
  1118. dwRetCode);
  1119. break;
  1120. }
  1121. // Impersonate the client and connect to the User's window station
  1122. // and desktop. This will be the interactively logged-on user
  1123. hwinstaUser = OpenWindowStation (L"WinSta0", FALSE, MAXIMUM_ALLOWED);
  1124. if (hwinstaUser == NULL)
  1125. {
  1126. dwRetCode = GetLastError ();
  1127. TRACE1 (USER, "ElGetUserNamePassword: OpenWindowStation failed with error %ld",
  1128. dwRetCode);
  1129. break;
  1130. }
  1131. SetProcessWindowStation(hwinstaUser);
  1132. hdeskUser = OpenDesktop (L"Default", 0, FALSE, MAXIMUM_ALLOWED);
  1133. if (hdeskUser == NULL)
  1134. {
  1135. SetProcessWindowStation (hwinstaSave);
  1136. CloseWindowStation (hwinstaUser);
  1137. dwRetCode = ERROR_INVALID_WORKSTATION;
  1138. break;
  1139. }
  1140. SetThreadDesktop (hdeskUser);
  1141. // Get handle to desktop window
  1142. hwndOwner = GetDesktopWindow ();
  1143. //
  1144. // Call the user dialog for obtaining the username and password
  1145. //
  1146. if ((dwRetCode = ElUserDlg (hwndOwner, pPCB)) != NO_ERROR)
  1147. {
  1148. TRACE0 (USER, "ElGetUserNamePassword: ElUserDlg failed");
  1149. RevertToSelf();
  1150. // Restore window station and desktop
  1151. SetThreadDesktop (hdeskSave);
  1152. SetProcessWindowStation (hwinstaSave);
  1153. CloseDesktop(hdeskUser);
  1154. CloseWindowStation(hwinstaUser);
  1155. break;
  1156. }
  1157. // Revert impersonation
  1158. if (!RevertToSelf())
  1159. {
  1160. dwRetCode = GetLastError();
  1161. TRACE1 (USER, "ElGetUserNamePassword: Error in RevertToSelf = %ld",
  1162. dwRetCode);
  1163. // Restore window station and desktop
  1164. SetThreadDesktop (hdeskSave);
  1165. SetProcessWindowStation (hwinstaSave);
  1166. CloseDesktop(hdeskUser);
  1167. CloseWindowStation(hwinstaUser);
  1168. break;
  1169. }
  1170. // Restore window station and desktop settings
  1171. SetThreadDesktop (hdeskSave);
  1172. SetProcessWindowStation (hwinstaSave);
  1173. CloseDesktop(hdeskUser);
  1174. CloseWindowStation(hwinstaUser);
  1175. // Mark the identity has been obtained for this PCB
  1176. pPCB->fGotUserIdentity = TRUE;
  1177. // Release the per-interface lock
  1178. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  1179. } while (FALSE);
  1180. // Cleanup
  1181. if (dwRetCode != NO_ERROR)
  1182. {
  1183. // Release the per-interface lock
  1184. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  1185. if (pPCB->pCustomAuthUserData != NULL)
  1186. {
  1187. FREE (pPCB->pCustomAuthUserData);
  1188. }
  1189. if (pPCB->pCustomAuthConnData != NULL)
  1190. {
  1191. FREE (pPCB->pCustomAuthConnData);
  1192. }
  1193. }
  1194. TRACE1 (USER, "ElGetUserNamePassword completed with error %ld", dwRetCode);
  1195. return dwRetCode;
  1196. }
  1197. //
  1198. // ElUserDlg
  1199. //
  1200. // Description:
  1201. //
  1202. // Function called to pop dialog box to user to enter username, password,
  1203. // domainname etc.
  1204. //
  1205. // Arguments:
  1206. // hwndOwner - handle to user desktop
  1207. // pPCB - Pointer to PCB for the port/interface on which credentials
  1208. // are to be obtained
  1209. //
  1210. // Return values:
  1211. // NO_ERROR - success
  1212. // non-zero - error
  1213. //
  1214. DWORD
  1215. ElUserDlg (
  1216. IN HWND hwndOwner,
  1217. IN EAPOL_PCB *pPCB
  1218. )
  1219. {
  1220. USERDLGARGS args;
  1221. DWORD dwRetCode = NO_ERROR;
  1222. TRACE0 (USER, "ElUserDlg: Entered");
  1223. args.pPCB = pPCB;
  1224. if ( DialogBoxParam (
  1225. GetModuleHandle(cszModuleName),
  1226. MAKEINTRESOURCE (DID_DR_DialerUD),
  1227. hwndOwner,
  1228. ElUserDlgProc,
  1229. (LPARAM)&args ) == -1)
  1230. {
  1231. dwRetCode = GetLastError ();
  1232. TRACE1 (USER, "ElUserDlg: DialogBoxParam failed with error %ld",
  1233. dwRetCode);
  1234. }
  1235. return dwRetCode;
  1236. }
  1237. //
  1238. // ElUserDlgProc
  1239. //
  1240. // Description:
  1241. //
  1242. // Function handling all events for username/password/... dialog box
  1243. //
  1244. // Arguments:
  1245. // hwnd -
  1246. // unMsg -
  1247. // wparam -
  1248. // lparam -
  1249. //
  1250. // Return values:
  1251. // NO_ERROR - success
  1252. // non-zero - error
  1253. //
  1254. INT_PTR
  1255. ElUserDlgProc (
  1256. IN HWND hwnd,
  1257. IN UINT unMsg,
  1258. IN WPARAM wparam,
  1259. IN LPARAM lparam )
  1260. {
  1261. switch (unMsg)
  1262. {
  1263. case WM_INITDIALOG:
  1264. {
  1265. return ElUserDlgInit( hwnd, (USERDLGARGS* )lparam );
  1266. break;
  1267. }
  1268. case WM_HELP:
  1269. case WM_CONTEXTMENU:
  1270. {
  1271. break;
  1272. }
  1273. case WM_COMMAND:
  1274. {
  1275. USERDLGINFO* pInfo = (USERDLGINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  1276. ASSERT( pInfo );
  1277. return ElUserDlgCommand (
  1278. pInfo, HIWORD(wparam), LOWORD(wparam), (HWND)lparam );
  1279. break;
  1280. }
  1281. case WM_DESTROY:
  1282. {
  1283. USERDLGINFO* pInfo = (USERDLGINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  1284. ElUserDlgTerm (hwnd, pInfo);
  1285. break;
  1286. }
  1287. }
  1288. return FALSE;
  1289. }
  1290. BOOL
  1291. ElUserDlgInit (
  1292. IN HWND hwndDlg,
  1293. IN USERDLGARGS *pArgs
  1294. )
  1295. {
  1296. USERDLGINFO *pInfo = NULL;
  1297. WCHAR wszFriendlyName[256];
  1298. DWORD dwRetCode = NO_ERROR;
  1299. TRACE0 (USER, "ElUserDlgInit entered");
  1300. do
  1301. {
  1302. pInfo = MALLOC (sizeof (USERDLGINFO));
  1303. if (pInfo == NULL)
  1304. {
  1305. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1306. TRACE0 (USER, "ElUserDlgInit: MALLOC failed for pInfo");
  1307. break;
  1308. }
  1309. pInfo->pArgs = pArgs;
  1310. pInfo->hwndDlg = hwndDlg;
  1311. SetWindowLongPtr (hwndDlg, DWLP_USER, (ULONG_PTR)pInfo);
  1312. #if 0
  1313. if (!SetWindowLongPtr (hwndDlg, DWLP_USER, (ULONG_PTR)pInfo))
  1314. {
  1315. dwRetCode = GetLastError ();
  1316. TRACE1 (USER, "ElUserDlgInit: SetWindowLongPtr failed with error %ld",
  1317. dwRetCode);
  1318. break;
  1319. }
  1320. #endif
  1321. TRACE0 (USER, "ElUserDlgInit: Context Set");
  1322. //
  1323. // Set the title
  1324. //
  1325. ZeroMemory (wszFriendlyName, 256*sizeof(WCHAR));
  1326. // Convert the friendly name of the adapter to a display ready
  1327. // form
  1328. if (pArgs->pPCB->pszFriendlyName)
  1329. {
  1330. if (0 == MultiByteToWideChar(
  1331. CP_ACP,
  1332. 0,
  1333. pArgs->pPCB->pszFriendlyName,
  1334. -1,
  1335. wszFriendlyName,
  1336. 256 ) )
  1337. {
  1338. dwRetCode = GetLastError();
  1339. TRACE2 (USER, "ElUserDlgInit: MultiByteToWideChar(%s) failed: %d",
  1340. pArgs->pPCB->pszFriendlyName,
  1341. dwRetCode);
  1342. }
  1343. if (!SetWindowText (hwndDlg, wszFriendlyName))
  1344. {
  1345. dwRetCode = GetLastError ();
  1346. TRACE1 (USER, "ElUserDlgInit: SetWindowText failed with error %ld",
  1347. dwRetCode);
  1348. break;
  1349. }
  1350. }
  1351. else
  1352. {
  1353. if (!SetWindowText (hwndDlg, NULL))
  1354. {
  1355. dwRetCode = GetLastError ();
  1356. TRACE1 (USER, "ElUserDlgInit: SetWindowText - NULL failed with error %ld",
  1357. dwRetCode);
  1358. break;
  1359. }
  1360. }
  1361. pInfo->hwndEbUser = GetDlgItem( hwndDlg, CID_DR_EB_User );
  1362. ASSERT (pInfo->hwndEbUser);
  1363. pInfo->hwndEbPw = GetDlgItem( hwndDlg, CID_DR_EB_Password );
  1364. ASSERT (pInfo->hwndEbPw);
  1365. pInfo->hwndEbDomain = GetDlgItem( hwndDlg, CID_DR_EB_Domain );
  1366. ASSERT (pInfo->hwndEbDomain);
  1367. }
  1368. while (FALSE);
  1369. if (dwRetCode != NO_ERROR)
  1370. {
  1371. return FALSE;
  1372. }
  1373. else
  1374. {
  1375. return TRUE;
  1376. }
  1377. }
  1378. //
  1379. // ElUserDlgCommand
  1380. //
  1381. // Description:
  1382. //
  1383. // Function called on WM_COMMAND
  1384. // domainname etc.
  1385. //
  1386. // Arguments:
  1387. // PInfo - dialog context
  1388. // WNotification - notification code of the command
  1389. // wId - control/menu identifier of the command
  1390. // HwndCtrl - control window handle the command.
  1391. //
  1392. // Return values:
  1393. // TRUE - success
  1394. // FALSE - error
  1395. //
  1396. BOOL
  1397. ElUserDlgCommand (
  1398. IN USERDLGINFO *pInfo,
  1399. IN WORD wNotification,
  1400. IN WORD wId,
  1401. IN HWND hwndCtrl
  1402. )
  1403. {
  1404. TRACE3 (USER, "ElUserDlgCommand: n=%d, i=%d, c=%x",
  1405. (DWORD)wNotification, (DWORD)wId, (ULONG_PTR)hwndCtrl);
  1406. switch (wId)
  1407. {
  1408. case IDOK:
  1409. case CID_DR_PB_DialConnect:
  1410. {
  1411. ElUserDlgSave (pInfo);
  1412. EndDialog (pInfo->hwndDlg, TRUE);
  1413. return TRUE;
  1414. }
  1415. case IDCANCEL:
  1416. case CID_DR_PB_Cancel:
  1417. {
  1418. EndDialog (pInfo->hwndDlg, TRUE);
  1419. return TRUE;
  1420. }
  1421. default:
  1422. {
  1423. TRACE0 (USER, "ElUserDlgCommand: Got something we are not interested in");
  1424. break;
  1425. }
  1426. }
  1427. return FALSE;
  1428. }
  1429. VOID
  1430. ElUserDlgSave (
  1431. IN USERDLGINFO *pInfo
  1432. )
  1433. {
  1434. EAPOL_PCB *pPCB = NULL;
  1435. int iError;
  1436. CHAR szUserName[UNLEN + 1];
  1437. CHAR szDomain[DNLEN + 1];
  1438. CHAR szPassword[DNLEN + 1];
  1439. DWORD dwRetCode = NO_ERROR;
  1440. pPCB = (EAPOL_PCB *)pInfo->pArgs->pPCB;
  1441. do
  1442. {
  1443. // Username
  1444. if ((iError =
  1445. GetWindowTextA(
  1446. pInfo->hwndEbUser,
  1447. &(szUserName[0]),
  1448. UNLEN + 1 )) == 0)
  1449. {
  1450. dwRetCode = GetLastError ();
  1451. TRACE1 (USER, "ElUserDlgSave: GetWindowText - Username failed with error %ld",
  1452. dwRetCode);
  1453. }
  1454. szUserName[iError] = '\0';
  1455. TRACE1 (USER, "ElUserDlgSave: Get Username %s", szUserName);
  1456. // Password
  1457. if ((iError =
  1458. GetWindowTextA(
  1459. pInfo->hwndEbPw,
  1460. &(szPassword[0]),
  1461. PWLEN + 1 )) == 0)
  1462. {
  1463. dwRetCode = GetLastError ();
  1464. TRACE1 (USER, "ElUserDlgSave: GetWindowText - Password failed with error %ld",
  1465. dwRetCode);
  1466. }
  1467. szPassword[iError] = '\0';
  1468. if (pPCB->pszPassword != NULL)
  1469. {
  1470. FREE (pPCB->pszPassword);
  1471. pPCB->pszPassword = NULL;
  1472. }
  1473. pPCB->pszPassword = MALLOC (strlen(szPassword) + 1);
  1474. if (pPCB->pszPassword == NULL)
  1475. {
  1476. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1477. TRACE0 (USER, "ElUserDlgSave: MALLOC failed for pPCB->pszPassword");
  1478. break;
  1479. }
  1480. memcpy (pPCB->pszPassword, szPassword, strlen(szPassword) + 1);
  1481. // Uncomment only if absolutely required
  1482. // Security issue, since we are writing trace to file
  1483. // TRACE1 (USER, "ElUserDlgSave: Got Password %s", pPCB->pszPassword);
  1484. // Domain
  1485. if ((iError =
  1486. GetWindowTextA(
  1487. pInfo->hwndEbDomain,
  1488. &(szDomain[0]),
  1489. DNLEN + 1 )) == 0)
  1490. {
  1491. dwRetCode = GetLastError ();
  1492. TRACE1 (USER, "ElUserDlgSave: GetWindowText - Domain failed with error %ld",
  1493. dwRetCode);
  1494. }
  1495. szDomain[iError] = '\0';
  1496. TRACE1 (USER, "ElUserDlgSave: Got Domain %s", szDomain);
  1497. if (pPCB->pszIdentity != NULL)
  1498. {
  1499. FREE (pPCB->pszIdentity);
  1500. pPCB->pszIdentity = NULL;
  1501. }
  1502. if ((szDomain != NULL) &&
  1503. (szDomain[0] != (CHAR)NULL))
  1504. {
  1505. pPCB->pszIdentity =
  1506. MALLOC (strlen(szDomain)+strlen(szUserName)+2);
  1507. if (pPCB->pszIdentity == NULL)
  1508. {
  1509. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1510. TRACE0 (USER, "ElUserDlgSave: MALLOC failed for pPCB->pszIdentity 1");
  1511. break;
  1512. }
  1513. strcpy (pPCB->pszIdentity, szDomain);
  1514. strcat( pPCB->pszIdentity, "\\" );
  1515. strcat (pPCB->pszIdentity, szUserName);
  1516. }
  1517. else
  1518. {
  1519. pPCB->pszIdentity =
  1520. MALLOC (strlen(szUserName)+1);
  1521. if (pPCB->pszIdentity == NULL)
  1522. {
  1523. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1524. TRACE0 (USER, "ElUserDlgSave: MALLOC failed for pPCB->pszIdentity 2");
  1525. break;
  1526. }
  1527. strcpy (pPCB->pszIdentity, szUserName);
  1528. }
  1529. TRACE1 (USER, "ElUserDlgSave: Got identity %s", pPCB->pszIdentity);
  1530. TRACE1 (USER, "ElUserDlgSave: PCB->GUID = %s", pPCB->pszDeviceGUID);
  1531. // Hash-up password while storing locally
  1532. ElEncodePw (pPCB->pszPassword);
  1533. }
  1534. while (FALSE);
  1535. if (dwRetCode != NO_ERROR)
  1536. {
  1537. if (pPCB->pszIdentity != NULL)
  1538. {
  1539. FREE (pPCB->pszIdentity);
  1540. pPCB->pszIdentity = NULL;
  1541. }
  1542. if (pPCB->pszPassword != NULL)
  1543. {
  1544. FREE (pPCB->pszPassword);
  1545. pPCB->pszPassword = NULL;
  1546. }
  1547. }
  1548. return;
  1549. }
  1550. VOID
  1551. ElUserDlgTerm (
  1552. IN HWND hwndDlg,
  1553. IN USERDLGINFO *pInfo
  1554. )
  1555. {
  1556. EndDialog (hwndDlg, TRUE);
  1557. FREE (pInfo);
  1558. }
  1559. //
  1560. // ElInvokeInteractiveUI
  1561. //
  1562. // Description:
  1563. //
  1564. // Function called to invoke RasEapInvokeInteractiveUI for an EAP on a
  1565. // particular interface
  1566. //
  1567. // Arguments:
  1568. // pPCB - Pointer to PCB for the specific interface
  1569. // pInvokeEapUIIn - Data to be supplied to the InvokeInteractiveUI entrypoint
  1570. // provided by the EAP dll through PPP_EAP_OUTPUT structure
  1571. //
  1572. DWORD
  1573. ElInvokeInteractiveUI (
  1574. IN EAPOL_PCB *pPCB,
  1575. IN ELEAP_INVOKE_EAP_UI *pInvokeEapUIIn
  1576. )
  1577. {
  1578. HANDLE hUserToken = NULL;
  1579. HANDLE hLib = NULL;
  1580. EAPOLEAPFREE pFreeFunc = NULL;
  1581. EAPOLEAPINVOKEINTERACTIVEUI pEapInvokeUI = NULL;
  1582. DWORD dwIndex = -1;
  1583. BYTE *pUIDataOut = NULL;
  1584. DWORD dwSizeOfUIDataOut;
  1585. HWND hwndOwner = NULL;
  1586. HWINSTA hwinstaSave = NULL;
  1587. HDESK hdeskSave = NULL;
  1588. HWINSTA hwinstaUser = NULL;
  1589. HDESK hdeskUser = NULL;
  1590. DWORD dwThreadId = 0;
  1591. DWORD dwRetCode = NO_ERROR;
  1592. do
  1593. {
  1594. TRACE0 (USER, "ElInvokeInteractiveUI entered");
  1595. // The EAP dll will have already been loaded by the state machine
  1596. // Retrieve the handle to the dll from the global EAP table
  1597. if ((dwIndex = ElGetEapTypeIndex (pPCB->dwEapTypeToBeUsed)) == -1)
  1598. {
  1599. TRACE1 (USER, "ElInvokeInteractiveUI: ElGetEapTypeIndex finds no dll for EAP index %ld",
  1600. pPCB->dwEapTypeToBeUsed);
  1601. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  1602. break;
  1603. }
  1604. hLib = g_pEapTable[dwIndex].hInstance;
  1605. pEapInvokeUI = (EAPOLEAPINVOKEINTERACTIVEUI) GetProcAddress
  1606. (hLib, "RasEapInvokeInteractiveUI");
  1607. pFreeFunc = (EAPOLEAPFREE) GetProcAddress (hLib, "RasEapFreeMemory");
  1608. if ((pFreeFunc == NULL) || (pEapInvokeUI == NULL))
  1609. {
  1610. TRACE0 (USER, "ElInvokeInteractiveUI: pEapInvokeUI or pFreeFunc does not exist in the EAP implementation");
  1611. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  1612. break;
  1613. }
  1614. // Get Access Token for user logged on interactively
  1615. // Call Terminal Services API
  1616. if (GetWinStationUserToken (GetClientLogonId(), &hUserToken)
  1617. != NO_ERROR)
  1618. {
  1619. TRACE0 (USER, "ElInvokeInteractiveUI: Terminal Services API GetWinStationUserToken failed !!! ");
  1620. // Call private API
  1621. hUserToken = GetCurrentUserTokenW (L"WinSta0",
  1622. TOKEN_QUERY |
  1623. TOKEN_DUPLICATE |
  1624. TOKEN_ASSIGN_PRIMARY);
  1625. if (hUserToken == NULL)
  1626. {
  1627. dwRetCode = GetLastError ();
  1628. TRACE1 (USER, "ElInvokeInteractiveUI: Error in GetCurrentUserTokenW = %ld",
  1629. dwRetCode);
  1630. dwRetCode = ERROR_NO_TOKEN;
  1631. break;
  1632. }
  1633. }
  1634. if (hUserToken == NULL)
  1635. {
  1636. dwRetCode = GetLastError ();
  1637. TRACE0 (USER, "ElInvokeInteractiveUI: Error in getting current user token");
  1638. dwRetCode = ERROR_NO_TOKEN;
  1639. break;
  1640. }
  1641. pPCB->hUserToken = hUserToken;
  1642. // Save handles to service window
  1643. hwinstaSave = GetProcessWindowStation();
  1644. if (hwinstaSave == NULL)
  1645. {
  1646. dwRetCode = GetLastError ();
  1647. TRACE1 (USER, "ElInvokeInteractiveUI: GetProcessWindowStation failed with error %ld",
  1648. dwRetCode);
  1649. break;
  1650. }
  1651. dwThreadId = GetCurrentThreadId ();
  1652. hdeskSave = GetThreadDesktop (dwThreadId);
  1653. if (hdeskSave == NULL)
  1654. {
  1655. dwRetCode = GetLastError ();
  1656. TRACE1 (USER, "ElInvokeInteractiveUI: GetThreadDesktop failed with error %ld",
  1657. dwRetCode);
  1658. break;
  1659. }
  1660. if (!ImpersonateLoggedOnUser (pPCB->hUserToken))
  1661. {
  1662. dwRetCode = GetLastError();
  1663. TRACE1 (USER, "ElInvokeInteractiveUI: ImpersonateLoggedOnUse failed with error %ld",
  1664. dwRetCode);
  1665. break;
  1666. }
  1667. // Impersonate the client and connect to the User's window station
  1668. // and desktop. This will be the interactively logged-on user
  1669. hwinstaUser = OpenWindowStation (L"WinSta0", FALSE, MAXIMUM_ALLOWED);
  1670. if (hwinstaUser == NULL)
  1671. {
  1672. dwRetCode = GetLastError ();
  1673. TRACE1 (USER, "OpenWindowStation: OpenWindowStation failed with error %ld",
  1674. dwRetCode);
  1675. break;
  1676. }
  1677. SetProcessWindowStation(hwinstaUser);
  1678. hdeskUser = OpenDesktop (L"Default", 0, FALSE, MAXIMUM_ALLOWED);
  1679. if (hdeskUser == NULL)
  1680. {
  1681. SetProcessWindowStation (hwinstaSave);
  1682. CloseWindowStation (hwinstaUser);
  1683. dwRetCode = ERROR_INVALID_WORKSTATION;
  1684. break;
  1685. }
  1686. SetThreadDesktop (hdeskUser);
  1687. // Get handle to desktop window
  1688. hwndOwner = GetDesktopWindow ();
  1689. if ((dwRetCode = (*(pEapInvokeUI))(
  1690. pPCB->dwEapTypeToBeUsed,
  1691. hwndOwner, // hwndOwner
  1692. // Context data from EAP
  1693. pInvokeEapUIIn->pbUIContextData,
  1694. // Size of context data
  1695. pInvokeEapUIIn->dwSizeOfUIContextData,
  1696. &pUIDataOut,
  1697. &dwSizeOfUIDataOut
  1698. )) != NO_ERROR)
  1699. {
  1700. TRACE1 (USER, "ElInvokeInteractiveUI: Error in calling InvokeInteractiveUI = %ld",
  1701. dwRetCode);
  1702. // Revert impersonation
  1703. if (!RevertToSelf())
  1704. {
  1705. dwRetCode = GetLastError();
  1706. TRACE1 (USER, "ElInvokeInteractiveUI: Error in RevertToSelf = %ld",
  1707. dwRetCode);
  1708. }
  1709. // Restore window station and desktop
  1710. SetThreadDesktop (hdeskSave);
  1711. SetProcessWindowStation (hwinstaSave);
  1712. CloseDesktop(hdeskUser);
  1713. CloseWindowStation(hwinstaUser);
  1714. break;
  1715. }
  1716. // Revert impersonation
  1717. if (!RevertToSelf())
  1718. {
  1719. dwRetCode = GetLastError();
  1720. TRACE1 (USER, "ElInvokeInteractiveUI: Error in RevertToSelf = %ld",
  1721. dwRetCode);
  1722. // Restore window station and desktop
  1723. SetThreadDesktop (hdeskSave);
  1724. SetProcessWindowStation (hwinstaSave);
  1725. CloseDesktop(hdeskUser);
  1726. CloseWindowStation(hwinstaUser);
  1727. break;
  1728. }
  1729. // Restore window station and desktop settings
  1730. SetThreadDesktop (hdeskSave);
  1731. SetProcessWindowStation (hwinstaSave);
  1732. CloseDesktop(hdeskUser);
  1733. CloseWindowStation(hwinstaUser);
  1734. // Free the context we passed to the dll
  1735. if (pInvokeEapUIIn->pbUIContextData != NULL)
  1736. {
  1737. FREE (pInvokeEapUIIn->pbUIContextData);
  1738. pInvokeEapUIIn->pbUIContextData = NULL;
  1739. pInvokeEapUIIn->dwSizeOfUIContextData = 0;
  1740. }
  1741. // Fill in the returned information into the PCB fields for
  1742. // later authentication
  1743. if (pPCB->EapUIData.pEapUIData != NULL)
  1744. {
  1745. FREE (pPCB->EapUIData.pEapUIData);
  1746. pPCB->EapUIData.pEapUIData = NULL;
  1747. pPCB->EapUIData.dwSizeOfEapUIData = 0;
  1748. }
  1749. pPCB->EapUIData.pEapUIData = MALLOC (dwSizeOfUIDataOut + sizeof (DWORD));
  1750. if (pPCB->EapUIData.pEapUIData == NULL)
  1751. {
  1752. TRACE1 (USER, "ElInvokeInteractiveUI: Error in allocating memory for UIData = %ld",
  1753. dwRetCode);
  1754. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1755. break;
  1756. }
  1757. pPCB->EapUIData.dwSizeOfEapUIData = dwSizeOfUIDataOut;
  1758. if ((dwSizeOfUIDataOut != 0) && (pUIDataOut != NULL))
  1759. {
  1760. memcpy ((BYTE *)pPCB->EapUIData.pEapUIData,
  1761. (BYTE *)pUIDataOut,
  1762. dwSizeOfUIDataOut);
  1763. }
  1764. pPCB->fEapUIDataReceived = TRUE;
  1765. TRACE0 (USER, "ElInvokeInteractiveUI: Calling ElEapWork");
  1766. // Provide UI data to EAP Dll for processing
  1767. // EAP will send out response if required
  1768. if ((dwRetCode = ElEapWork (
  1769. pPCB,
  1770. NULL)) != NO_ERROR)
  1771. {
  1772. TRACE1 (USER, "ElInvokeInteractiveUI: ElEapWork failed with error = %ld",
  1773. dwRetCode);
  1774. break;
  1775. }
  1776. TRACE0 (USER, "ElInvokeInteractiveUI: ElEapWork completed successfully");
  1777. } while (FALSE);
  1778. // Cleanup
  1779. if (dwRetCode != NO_ERROR)
  1780. {
  1781. if (pPCB->EapUIData.pEapUIData != NULL)
  1782. {
  1783. FREE (pPCB->EapUIData.pEapUIData);
  1784. pPCB->EapUIData.pEapUIData = NULL;
  1785. pPCB->EapUIData.dwSizeOfEapUIData = 0;
  1786. }
  1787. }
  1788. if (pInvokeEapUIIn->pbUIContextData != NULL)
  1789. {
  1790. FREE (pInvokeEapUIIn->pbUIContextData);
  1791. pInvokeEapUIIn->pbUIContextData = NULL;
  1792. pInvokeEapUIIn->dwSizeOfUIContextData = 0;
  1793. }
  1794. if (pFreeFunc != NULL)
  1795. {
  1796. if (pUIDataOut != NULL)
  1797. {
  1798. if (( dwRetCode = (*(pFreeFunc)) ((BYTE *)pUIDataOut)) != NO_ERROR)
  1799. {
  1800. TRACE1 (USER, "ElInvokeInteractiveUI: Error in pFreeFunc = %ld",
  1801. dwRetCode);
  1802. }
  1803. }
  1804. }
  1805. TRACE1 (USER, "ElInvokeInteractiveUI completed with error %ld", dwRetCode);
  1806. return dwRetCode;
  1807. }