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

529 lines
17 KiB

  1. /*++
  2. Copyright (c) 2000, Microsoft Corporation
  3. Module Name:
  4. eapolutil.c
  5. Abstract:
  6. Tools and ends
  7. Revision History:
  8. sachins, Apr 23 2001, Created
  9. --*/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. //
  13. // EAPOLUI function mapping
  14. //
  15. EAPOLUIFUNCMAP EapolUIFuncMap[NUM_EAPOL_DLG_MSGS]=
  16. {
  17. {EAPOLUI_GET_USERIDENTITY, ElGetUserIdentityDlgWorker, ElGetUserIdentityDlgWorker, TRUE, SID_GetUserIdentity},
  18. {EAPOLUI_GET_USERNAMEPASSWORD, ElGetUserNamePasswordDlgWorker, NULL, TRUE, SID_GetUserNamePassword},
  19. {EAPOLUI_INVOKEINTERACTIVEUI, ElInvokeInteractiveUIDlgWorker, NULL, TRUE, SID_InvokeInteractiveUI},
  20. {EAPOLUI_EAP_NOTIFICATION, NULL, NULL, TRUE, 0},
  21. {EAPOLUI_REAUTHENTICATE, NULL, NULL, FALSE, 0},
  22. {EAPOLUI_CREATEBALLOON, NULL, NULL, TRUE, SID_AuthenticationFailed},
  23. {EAPOLUI_CLEANUP, NULL, NULL, FALSE, 0},
  24. {EAPOLUI_DUMMY, NULL, NULL, FALSE, 0}
  25. };
  26. //
  27. // ElCanShowBalloon
  28. //
  29. // Description:
  30. // Function called by netshell, to query if balloon is to be displayed
  31. //
  32. // Arguments:
  33. // pGUIDConn - Interface GUID string
  34. // pszConnectionName - Connection Name
  35. // pszBalloonText - Pointer to text to be display
  36. // pszCookie - EAPOL specific information
  37. //
  38. // Return values:
  39. // S_OK - Display balloon
  40. // S_FALSE - Do not display balloon
  41. //
  42. HRESULT
  43. ElCanShowBalloon (
  44. IN const GUID * pGUIDConn,
  45. IN const WCHAR * pszConnectionName,
  46. IN OUT BSTR * pszBalloonText,
  47. IN OUT BSTR * pszCookie
  48. )
  49. {
  50. EAPOL_EAP_UI_CONTEXT *pEapolUIContext = NULL;
  51. DWORD dwIndex = 0;
  52. DWORD dwSessionId = 0;
  53. WCHAR cwszBuffer[MAX_BALLOON_MSG_LEN];
  54. WCHAR wsSSID[MAX_SSID_LEN+1];
  55. DWORD dwSizeOfSSID = 0;
  56. BYTE *bSSID = NULL;
  57. WCHAR *pszFinalBalloonText = NULL;
  58. DWORD dwFinalStringId = 0;
  59. DWORD dwRetCode = NO_ERROR;
  60. DWORD dwRetCode1 = NO_ERROR;
  61. HRESULT hr = S_OK;
  62. do
  63. {
  64. pEapolUIContext = (EAPOL_EAP_UI_CONTEXT *)(*pszCookie);
  65. if (!ProcessIdToSessionId (GetCurrentProcessId (), &dwSessionId))
  66. {
  67. dwRetCode = GetLastError ();
  68. break;
  69. }
  70. if (pEapolUIContext->dwSessionId != dwSessionId)
  71. {
  72. // Not intended for this session
  73. dwRetCode = ERROR_INVALID_PARAMETER;
  74. break;
  75. }
  76. dwSizeOfSSID = pEapolUIContext->dwSizeOfSSID;
  77. bSSID = pEapolUIContext->bSSID;
  78. for (dwIndex=0; dwIndex < NUM_EAPOL_DLG_MSGS; dwIndex++)
  79. {
  80. if (pEapolUIContext->dwEAPOLUIMsgType ==
  81. EapolUIFuncMap[dwIndex].dwEAPOLUIMsgType)
  82. {
  83. if (EapolUIFuncMap[dwIndex].fShowBalloon)
  84. {
  85. TRACE1 (RPC, "ElCanShowBalloon: Response function found, msg (%ld)",
  86. EapolUIContext->dwEAPOLUIMsgType);
  87. dwFinalStringId = EapolUIFuncMap[dwIndex].dwStringID;
  88. // Verify is balloon indeed needs to be popped up OR
  89. // can purpose be achieved without user involvement
  90. if (EapolUIFuncMap[dwIndex].EapolUIVerify != NULL)
  91. {
  92. // Indicate that it is verification cycle, by passing
  93. // NULL connection name, to indicate no display !
  94. dwRetCode1 = EapolUIFuncMap[dwIndex].EapolUIVerify (
  95. NULL,
  96. pEapolUIContext
  97. );
  98. if (dwRetCode1 == ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION)
  99. {
  100. // Continue with show balloon
  101. dwRetCode = NO_ERROR;
  102. }
  103. else
  104. {
  105. if (dwRetCode1 != NO_ERROR)
  106. {
  107. switch (dwRetCode1)
  108. {
  109. case ERROR_NO_EAPTLS_CERTIFICATE:
  110. // No certificate found
  111. // Pop balloon accordingly
  112. dwFinalStringId = SID_NoCertificateFound;
  113. // Since we wont take action on this
  114. // balloon being clicked, flag it as
  115. // EAPOLUI_DUMMY
  116. pEapolUIContext->dwEAPOLUIMsgType = EAPOLUI_DUMMY;
  117. dwRetCode = NO_ERROR;
  118. break;
  119. case ERROR_NO_SMART_CARD_READER:
  120. // No smartcard reader found
  121. dwFinalStringId = SID_NoSmartCardReaderFound;
  122. // Since we wont take action on this
  123. // balloon being clicked, flag it as
  124. // EAPOLUI_DUMMY
  125. pEapolUIContext->dwEAPOLUIMsgType = EAPOLUI_DUMMY;
  126. dwRetCode = NO_ERROR;
  127. break;
  128. default:
  129. // Continue with show balloon for any
  130. // error in verification function
  131. dwRetCode = NO_ERROR;
  132. break;
  133. }
  134. }
  135. else
  136. {
  137. // No need to process more.
  138. // Response has been sent successfully
  139. // without user intervention
  140. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  141. break;
  142. }
  143. }
  144. }
  145. if (dwFinalStringId != 0)
  146. {
  147. // Load string based on Id
  148. if (LoadString (GetModuleHandle(cszModuleName), dwFinalStringId, cwszBuffer, MAX_BALLOON_MSG_LEN) == 0)
  149. {
  150. dwRetCode = GetLastError ();
  151. break;
  152. }
  153. // Append the network-name / SSID
  154. if (dwSizeOfSSID != 0)
  155. {
  156. if (0 == MultiByteToWideChar (
  157. CP_ACP,
  158. 0,
  159. bSSID,
  160. dwSizeOfSSID,
  161. wsSSID,
  162. MAX_SSID_LEN+1))
  163. {
  164. dwRetCode = GetLastError();
  165. break;
  166. }
  167. if ((pszFinalBalloonText = MALLOC ((wcslen(cwszBuffer)+1+ dwSizeOfSSID)*sizeof(WCHAR))) == NULL)
  168. {
  169. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  170. break;
  171. }
  172. wcscpy (pszFinalBalloonText, cwszBuffer);
  173. memcpy ((BYTE *)(pszFinalBalloonText + wcslen(cwszBuffer)), (BYTE *)wsSSID, dwSizeOfSSID*sizeof(WCHAR));
  174. pszFinalBalloonText[wcslen(cwszBuffer)+dwSizeOfSSID] = L'\0';
  175. }
  176. else
  177. {
  178. // Append a "." (period)
  179. if ((pszFinalBalloonText = MALLOC ((wcslen(cwszBuffer) + 3)*sizeof(WCHAR))) == NULL)
  180. {
  181. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  182. break;
  183. }
  184. wcscpy (pszFinalBalloonText, cwszBuffer);
  185. pszFinalBalloonText[wcslen(cwszBuffer)+1] = L'.';
  186. pszFinalBalloonText[wcslen(cwszBuffer)+2] = L'\0';
  187. }
  188. if (*pszBalloonText)
  189. {
  190. if (!SysReAllocString (pszBalloonText, pszFinalBalloonText))
  191. {
  192. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  193. break;
  194. }
  195. }
  196. else
  197. {
  198. *pszBalloonText = SysAllocString (pszFinalBalloonText);
  199. if (*pszBalloonText == NULL)
  200. {
  201. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  202. break;
  203. }
  204. }
  205. }
  206. else
  207. {
  208. // Display the string that was passed
  209. }
  210. // If notification message, check to see if explorer
  211. // needs to be started off
  212. if (pEapolUIContext->dwEAPOLUIMsgType == EAPOLUI_EAP_NOTIFICATION)
  213. {
  214. // Parse text message
  215. // Attach to cookie
  216. }
  217. }
  218. else
  219. {
  220. TRACE1 (RPC, "ElCanShowBalloon: No balloon display, msg (%ld)",
  221. EapolUIContext.dwEAPOLUIMsgType);
  222. }
  223. }
  224. }
  225. }
  226. while (FALSE);
  227. if (pszFinalBalloonText != NULL)
  228. {
  229. FREE (pszFinalBalloonText);
  230. }
  231. if (dwRetCode != NO_ERROR)
  232. {
  233. hr = S_FALSE;
  234. }
  235. return hr;
  236. }
  237. //
  238. // ElOnBalloonClick
  239. //
  240. // Description:
  241. //
  242. // Function called by netshell, in response to a balloon click
  243. //
  244. // Arguments:
  245. // pGUIDConn - Interface GUID string
  246. // szCookie - EAPOL specific information
  247. //
  248. // Return values:
  249. // S_OK - No error
  250. // S_FALSE - Error
  251. //
  252. HRESULT
  253. ElOnBalloonClick (
  254. IN const GUID * pGUIDConn,
  255. IN const WCHAR * pszConnectionName,
  256. IN const BSTR szCookie
  257. )
  258. {
  259. EAPOL_EAP_UI_CONTEXT *pEapolUIContext = NULL;
  260. DWORD dwIndex = 0;
  261. DWORD dwSessionId = 0;
  262. DWORD dwRetCode = NO_ERROR;
  263. WCHAR *pwszConnectionName = NULL;
  264. HRESULT hr = S_OK;
  265. do
  266. {
  267. pEapolUIContext = (EAPOL_EAP_UI_CONTEXT *)szCookie;
  268. pwszConnectionName = (WCHAR *)pszConnectionName;
  269. for (dwIndex=0; dwIndex < NUM_EAPOL_DLG_MSGS; dwIndex++)
  270. {
  271. if (pEapolUIContext->dwEAPOLUIMsgType ==
  272. EapolUIFuncMap[dwIndex].dwEAPOLUIMsgType)
  273. {
  274. if (EapolUIFuncMap[dwIndex].EapolUIFunc)
  275. {
  276. TRACE1 (RPC, "ElOnBalloonClick: Response function found, msg (%ld)",
  277. EapolUIContext->dwEAPOLUIMsgType);
  278. // Cleanup any previous dialogs for this interface
  279. if ((dwRetCode =
  280. ElDialogCleanup (
  281. (WCHAR *)pszConnectionName,
  282. szCookie
  283. )) != NO_ERROR)
  284. {
  285. TRACE0 (RPC, "ElOnBalloonClick: Error in dialog cleanup");
  286. break;
  287. }
  288. if ((dwRetCode =
  289. EapolUIFuncMap[dwIndex].EapolUIFunc (
  290. pwszConnectionName,
  291. pEapolUIContext
  292. )) != NO_ERROR)
  293. {
  294. TRACE1 (RPC, "ElOnBalloonClick: Response function failed with error %ld",
  295. dwRetCode);
  296. }
  297. }
  298. else
  299. {
  300. TRACE1 (RPC, "ElOnBalloonClick: No response function, msg (%ld)",
  301. EapolUIContext.dwEAPOLUIMsgType);
  302. }
  303. break;
  304. }
  305. }
  306. }
  307. while (FALSE);
  308. hr = HRESULT_FROM_NT (dwRetCode);
  309. return hr;
  310. }
  311. //
  312. // ElSecureEncodePw
  313. //
  314. // Description:
  315. //
  316. // Encrypt password locally using user-ACL
  317. //
  318. DWORD
  319. ElSecureEncodePw (
  320. IN PWCHAR *ppwszPassword,
  321. OUT DATA_BLOB *pDataBlob
  322. )
  323. {
  324. DWORD dwRetCode = NO_ERROR;
  325. DATA_BLOB blobIn, blobOut;
  326. do
  327. {
  328. blobIn.cbData = (wcslen (*ppwszPassword) + 1)*sizeof(WCHAR);
  329. blobIn.pbData = (BYTE *)*ppwszPassword;
  330. if (!CryptProtectData (
  331. &blobIn,
  332. L"",
  333. NULL,
  334. NULL,
  335. NULL,
  336. 0,
  337. &blobOut))
  338. {
  339. dwRetCode = GetLastError ();
  340. break;
  341. }
  342. // copy over blob to password
  343. if (pDataBlob->pbData != NULL)
  344. {
  345. FREE (pDataBlob->pbData);
  346. pDataBlob->pbData = NULL;
  347. pDataBlob->cbData = 0;
  348. }
  349. pDataBlob->pbData = MALLOC (blobOut.cbData);
  350. if (pDataBlob->pbData == NULL)
  351. {
  352. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  353. break;
  354. }
  355. memcpy (pDataBlob->pbData, blobOut.pbData, blobOut.cbData);
  356. pDataBlob->cbData = blobOut.cbData;
  357. }
  358. while (FALSE);
  359. if (blobOut.pbData != NULL)
  360. {
  361. LocalFree (blobOut.pbData);
  362. }
  363. if (dwRetCode != NO_ERROR)
  364. {
  365. if (pDataBlob->pbData != NULL)
  366. {
  367. FREE (pDataBlob->pbData);
  368. pDataBlob->pbData = NULL;
  369. pDataBlob->cbData = 0;
  370. }
  371. }
  372. return dwRetCode;
  373. }
  374. //
  375. // ElQueryConnectionStatusText
  376. //
  377. // Description:
  378. //
  379. // Function called by netshell, to query appropriate text for 802.1X states
  380. //
  381. // Arguments:
  382. // pGUIDConn - Interface GUID string
  383. // ncs - NETCON_STATUS for the interface
  384. // pszStatusText - Detailed 802.1X status to be displayed
  385. //
  386. // Return values:
  387. // S_OK - No error
  388. // S_FALSE - Error
  389. //
  390. HRESULT
  391. ElQueryConnectionStatusText (
  392. IN const GUID * pGUIDConn,
  393. IN const NETCON_STATUS ncs,
  394. IN OUT BSTR * pszStatusText
  395. )
  396. {
  397. WCHAR wszGuid[GUID_STRING_LEN_WITH_TERM];
  398. WCHAR cwszBuffer[MAX_BALLOON_MSG_LEN];
  399. EAPOL_INTF_STATE EapolIntfState = {0};
  400. DWORD dwStringId = 0;
  401. DWORD dwRetCode = NO_ERROR;
  402. HRESULT hr = S_OK;
  403. do
  404. {
  405. ZeroMemory ((PVOID)&EapolIntfState, sizeof(EAPOL_INTF_STATE));
  406. StringFromGUID2 (pGUIDConn, wszGuid, GUID_STRING_LEN_WITH_TERM);
  407. // Query current EAPOL state
  408. if ((dwRetCode = WZCEapolQueryState (
  409. NULL,
  410. wszGuid,
  411. &EapolIntfState
  412. )) != NO_ERROR)
  413. {
  414. break;
  415. }
  416. // Assign appropriate display string
  417. switch (EapolIntfState.dwEapUIState)
  418. {
  419. case 0:
  420. if (EapolIntfState.dwState == EAPOLSTATE_ACQUIRED)
  421. {
  422. dwStringId = SID_ContactingServer;
  423. }
  424. break;
  425. case EAPUISTATE_WAITING_FOR_IDENTITY:
  426. dwStringId = SID_AcquiringIdentity;
  427. break;
  428. case EAPUISTATE_WAITING_FOR_UI_RESPONSE:
  429. dwStringId = SID_UserResponse;
  430. break;
  431. }
  432. if (dwStringId != 0)
  433. {
  434. if (LoadString (GetModuleHandle(cszModuleName), dwStringId, cwszBuffer, MAX_BALLOON_MSG_LEN) == 0)
  435. {
  436. dwRetCode = GetLastError ();
  437. break;
  438. }
  439. if (*pszStatusText)
  440. {
  441. if (!SysReAllocString (pszStatusText, cwszBuffer))
  442. {
  443. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  444. break;
  445. }
  446. }
  447. else
  448. {
  449. *pszStatusText = SysAllocString (cwszBuffer);
  450. if (*pszStatusText == NULL)
  451. {
  452. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  453. break;
  454. }
  455. }
  456. }
  457. else
  458. {
  459. // Indicate to netshell that it need not process this response
  460. hr = S_FALSE;
  461. }
  462. }
  463. while (FALSE);
  464. if (dwRetCode != NO_ERROR)
  465. hr = HRESULT_FROM_NT (dwRetCode);
  466. WZCEapolFreeState (&EapolIntfState);
  467. return hr;
  468. }