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.

464 lines
15 KiB

  1. /*++
  2. Copyright (c) 2001, Microsoft Corporation
  3. Module Name:
  4. eloptimize.c
  5. Abstract:
  6. The module deals with functions related to user identity
  7. selection optimization
  8. Revision History:
  9. sachins, July 26 2001, Created
  10. --*/
  11. #include "pcheapol.h"
  12. #pragma hdrstop
  13. //
  14. // ElGetUserIdentityOptimized
  15. //
  16. // Description:
  17. //
  18. // Function called to fetch identity of the user
  19. // If UI is required then send identity request to user module
  20. //
  21. // Arguments:
  22. // pPCB - Current interface context
  23. //
  24. // Return values:
  25. // ERROR_REQUIRE_INTERACTIVE_WORKSTATION - User interaction required
  26. // Other - can send out user identity without user interaction
  27. //
  28. //
  29. DWORD
  30. ElGetUserIdentityOptimized (
  31. IN EAPOL_PCB *pPCB
  32. )
  33. {
  34. DWORD dwIndex = 0;
  35. CHAR *pszIdentity = NULL;
  36. BYTE *pUserDataOut = NULL;
  37. DWORD dwSizeOfUserDataOut = 0;
  38. LPWSTR lpwszIdentity = NULL;
  39. HWND hwndOwner = NULL;
  40. PBYTE pbUserIn = NULL;
  41. DWORD cbData = 0;
  42. DWORD dwInSize = 0;
  43. PBYTE pbAuthData = NULL;
  44. HANDLE hLib = NULL;
  45. RASEAPFREE pFreeFunc = NULL;
  46. RASEAPGETIDENTITY pIdenFunc = NULL;
  47. BYTE *pbSSID = NULL;
  48. DWORD dwSizeOfSSID = 0;
  49. BOOLEAN fVerifyPhase = TRUE;
  50. DWORD dwRetCode1 = NO_ERROR;
  51. DWORD dwRetCode = NO_ERROR;
  52. do
  53. {
  54. if (pPCB->pSSID)
  55. {
  56. pbSSID = pPCB->pSSID->Ssid;
  57. dwSizeOfSSID = pPCB->pSSID->SsidLength;
  58. }
  59. // Get the size of the user blob
  60. if ((dwRetCode = ElGetEapUserInfo (
  61. pPCB->hUserToken,
  62. pPCB->pwszDeviceGUID,
  63. pPCB->dwEapTypeToBeUsed,
  64. dwSizeOfSSID,
  65. pbSSID,
  66. NULL,
  67. &dwInSize
  68. )) != NO_ERROR)
  69. {
  70. if (dwRetCode == ERROR_BUFFER_TOO_SMALL)
  71. {
  72. if (dwInSize <= 0)
  73. {
  74. // No blob stored in the registry
  75. // Continue processing
  76. TRACE0 (USER, "ElGetUserIdentityOptimized: NULL sized user data");
  77. pbUserIn = NULL;
  78. }
  79. else
  80. {
  81. // Allocate memory to hold the blob
  82. pbUserIn = MALLOC (dwInSize);
  83. if (pbUserIn == NULL)
  84. {
  85. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  86. TRACE0 (USER, "ElGetUserIdentityOptimized: Error in memory allocation for User data");
  87. break;
  88. }
  89. if ((dwRetCode = ElGetEapUserInfo (
  90. pPCB->hUserToken,
  91. pPCB->pwszDeviceGUID,
  92. pPCB->dwEapTypeToBeUsed,
  93. dwSizeOfSSID,
  94. pbSSID,
  95. pbUserIn,
  96. &dwInSize
  97. )) != NO_ERROR)
  98. {
  99. TRACE1 (USER, "ElGetUserIdentityOptimized: ElGetEapUserInfo failed with %ld",
  100. dwRetCode);
  101. break;
  102. }
  103. }
  104. }
  105. else
  106. {
  107. // User info may not have been created till now
  108. // which is valid condition to proceed
  109. if (dwRetCode != ERROR_FILE_NOT_FOUND)
  110. {
  111. TRACE1 (USER, "ElGetUserIdentityOptimized: ElGetEapUserInfo size estimation failed with error %ld",
  112. dwRetCode);
  113. break;
  114. }
  115. else
  116. {
  117. dwRetCode = NO_ERROR;
  118. }
  119. }
  120. }
  121. // The EAP dll has already been loaded by the state machine
  122. // Retrieve the handle to the dll from the global EAP table
  123. if ((dwIndex = ElGetEapTypeIndex (pPCB->dwEapTypeToBeUsed)) == -1)
  124. {
  125. TRACE1 (USER, "ElGetUserIdentityOptimized: ElGetEapTypeIndex finds no dll for EAP index %ld",
  126. pPCB->dwEapTypeToBeUsed);
  127. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  128. break;
  129. }
  130. hLib = g_pEapTable[dwIndex].hInstance;
  131. pIdenFunc = (RASEAPGETIDENTITY)GetProcAddress(hLib,
  132. "RasEapGetIdentity");
  133. pFreeFunc = (RASEAPFREE)GetProcAddress(hLib, "RasEapFreeMemory");
  134. if ((pFreeFunc == NULL) || (pIdenFunc == NULL))
  135. {
  136. TRACE0 (USER, "ElGetUserIdentityOptimized: pIdenFunc or pFreeFunc does not exist in the EAP implementation");
  137. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  138. break;
  139. }
  140. // Get the size of the EAP blob
  141. if ((dwRetCode = ElGetCustomAuthData (
  142. pPCB->pwszDeviceGUID,
  143. pPCB->dwEapTypeToBeUsed,
  144. dwSizeOfSSID,
  145. pbSSID,
  146. NULL,
  147. &cbData
  148. )) != NO_ERROR)
  149. {
  150. if (dwRetCode == ERROR_BUFFER_TOO_SMALL)
  151. {
  152. if (cbData == 0)
  153. {
  154. // No EAP blob stored in the registry
  155. TRACE0 (USER, "ElGetUserIdentityOptimized: NULL sized EAP blob");
  156. pbAuthData = NULL;
  157. }
  158. else
  159. {
  160. // Allocate memory to hold the blob
  161. pbAuthData = MALLOC (cbData);
  162. if (pbAuthData == NULL)
  163. {
  164. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  165. TRACE0 (USER, "ElGetUserIdentityOptimized: Error in memory allocation for EAP blob");
  166. break;
  167. }
  168. if ((dwRetCode = ElGetCustomAuthData (
  169. pPCB->pwszDeviceGUID,
  170. pPCB->dwEapTypeToBeUsed,
  171. dwSizeOfSSID,
  172. pbSSID,
  173. pbAuthData,
  174. &cbData
  175. )) != NO_ERROR)
  176. {
  177. TRACE1 (USER, "ElGetUserIdentityOptimized: ElGetCustomAuthData failed with %ld",
  178. dwRetCode);
  179. break;
  180. }
  181. }
  182. }
  183. else
  184. {
  185. // CustomAuthData for "Default" is always created for an
  186. // interface when EAPOL starts up
  187. TRACE1 (USER, "ElGetUserIdentityOptimized: ElGetCustomAuthData size estimation failed with error %ld",
  188. dwRetCode);
  189. break;
  190. }
  191. }
  192. if (!ImpersonateLoggedOnUser (pPCB->hUserToken))
  193. {
  194. dwRetCode = GetLastError();
  195. TRACE1 (USER, "ElGetUserIdentityOptimized: ImpersonateLoggedOnUser failed with error %ld",
  196. dwRetCode);
  197. break;
  198. }
  199. if (pIdenFunc)
  200. if ((dwRetCode = (*(pIdenFunc))(
  201. pPCB->dwEapTypeToBeUsed,
  202. fVerifyPhase?NULL:hwndOwner, // hwndOwner
  203. ((fVerifyPhase?RAS_EAP_FLAG_NON_INTERACTIVE:0) | RAS_EAP_FLAG_8021X_AUTH), // dwFlags
  204. NULL, // lpszPhonebook
  205. pPCB->pwszFriendlyName, // lpszEntry
  206. pbAuthData, // Connection data
  207. cbData, // Count of pbAuthData
  208. pbUserIn, // User data for port
  209. dwInSize, // Size of user data
  210. &pUserDataOut,
  211. &dwSizeOfUserDataOut,
  212. &lpwszIdentity
  213. )) != NO_ERROR)
  214. {
  215. TRACE1 (USER, "ElGetUserIdentityOptimized: Error in calling GetIdentity = %ld",
  216. dwRetCode);
  217. if (!RevertToSelf())
  218. {
  219. dwRetCode = GetLastError();
  220. TRACE1 (USER, "ElGetUserIdentity: Error in RevertToSelf = %ld",
  221. dwRetCode);
  222. dwRetCode = ERROR_BAD_IMPERSONATION_LEVEL;
  223. break;
  224. }
  225. if (fVerifyPhase)
  226. {
  227. if (dwRetCode == ERROR_NO_EAPTLS_CERTIFICATE)
  228. {
  229. DbLogPCBEvent (DBLOG_CATEG_ERR, pPCB, EAPOL_NO_CERTIFICATE_USER);
  230. }
  231. if (dwRetCode == ERROR_INTERACTIVE_MODE)
  232. {
  233. DbLogPCBEvent (DBLOG_CATEG_INFO, pPCB, EAPOL_DESKTOP_REQUIRED_IDENTITY);
  234. }
  235. // If interactive mode is required, return error accordingly
  236. if ((dwRetCode == ERROR_INTERACTIVE_MODE) ||
  237. (dwRetCode == ERROR_NO_EAPTLS_CERTIFICATE) ||
  238. (dwRetCode == ERROR_NO_SMART_CARD_READER))
  239. {
  240. dwRetCode = ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION;
  241. break;
  242. }
  243. DbLogPCBEvent (DBLOG_CATEG_ERR, pPCB, EAPOL_ERROR_GET_IDENTITY,
  244. EAPOLAuthTypes[EAPOL_USER_AUTHENTICATION], dwRetCode);
  245. }
  246. break;
  247. }
  248. if (!RevertToSelf())
  249. {
  250. dwRetCode = GetLastError();
  251. TRACE1 (USER, "ElGetUserIdentityOptimized: Error in RevertToSelf = %ld",
  252. dwRetCode);
  253. dwRetCode = ERROR_BAD_IMPERSONATION_LEVEL;
  254. break;
  255. }
  256. // Fill in the returned information into the PCB fields for
  257. // later authentication
  258. if (pPCB->pCustomAuthUserData != NULL)
  259. {
  260. FREE (pPCB->pCustomAuthUserData);
  261. pPCB->pCustomAuthUserData = NULL;
  262. }
  263. pPCB->pCustomAuthUserData = MALLOC (dwSizeOfUserDataOut + sizeof (DWORD));
  264. if (pPCB->pCustomAuthUserData == NULL)
  265. {
  266. TRACE1 (USER, "ElGetUserIdentityOptimized: Error in allocating memory for UserInfo = %ld",
  267. dwRetCode);
  268. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  269. break;
  270. }
  271. pPCB->pCustomAuthUserData->dwSizeOfCustomAuthData = dwSizeOfUserDataOut;
  272. if ((dwSizeOfUserDataOut != 0) && (pUserDataOut != NULL))
  273. {
  274. memcpy ((BYTE *)pPCB->pCustomAuthUserData->pbCustomAuthData,
  275. (BYTE *)pUserDataOut,
  276. dwSizeOfUserDataOut);
  277. }
  278. if (lpwszIdentity != NULL)
  279. {
  280. pszIdentity = MALLOC (wcslen(lpwszIdentity)*sizeof(CHAR) + sizeof(CHAR));
  281. if (pszIdentity == NULL)
  282. {
  283. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  284. TRACE0 (USER, "ElGetUserIdentityOptimized: MALLOC failed for pszIdentity");
  285. break;
  286. }
  287. if (0 == WideCharToMultiByte (
  288. CP_ACP,
  289. 0,
  290. lpwszIdentity,
  291. -1,
  292. pszIdentity,
  293. wcslen(lpwszIdentity)*sizeof(CHAR)+sizeof(CHAR),
  294. NULL,
  295. NULL ))
  296. {
  297. dwRetCode = GetLastError();
  298. TRACE2 (USER, "ElGetUserIdentityOptimized: WideCharToMultiByte (%ws) failed: %ld",
  299. lpwszIdentity, dwRetCode);
  300. break;
  301. }
  302. TRACE1 (USER, "ElGetUserIdentityOptimized: Got identity = %s",
  303. pszIdentity);
  304. if (pPCB->pszIdentity != NULL)
  305. {
  306. FREE (pPCB->pszIdentity);
  307. pPCB->pszIdentity = NULL;
  308. }
  309. pPCB->pszIdentity = MALLOC (strlen(pszIdentity) + sizeof(CHAR));
  310. if (pPCB->pszIdentity == NULL)
  311. {
  312. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  313. TRACE0 (USER, "ElGetUserIdentityOptimized: MALLOC failed for pPCB->pszIdentity");
  314. break;
  315. }
  316. memcpy (pPCB->pszIdentity, pszIdentity, strlen (pszIdentity));
  317. pPCB->pszIdentity[strlen(pszIdentity)] = '\0';
  318. }
  319. if (pPCB->pCustomAuthConnData != NULL)
  320. {
  321. FREE (pPCB->pCustomAuthConnData);
  322. pPCB->pCustomAuthConnData = NULL;
  323. }
  324. pPCB->pCustomAuthConnData = MALLOC (cbData + sizeof (DWORD));
  325. if (pPCB->pCustomAuthConnData == NULL)
  326. {
  327. TRACE1 (USER, "ElGetUserIdentityOptimized: Error in allocating memory for AuthInfo = %ld",
  328. dwRetCode);
  329. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  330. break;
  331. }
  332. pPCB->pCustomAuthConnData->dwSizeOfCustomAuthData = cbData;
  333. if ((cbData != 0) && (pbAuthData != NULL))
  334. {
  335. memcpy ((BYTE *)pPCB->pCustomAuthConnData->pbCustomAuthData,
  336. (BYTE *)pbAuthData,
  337. cbData);
  338. }
  339. // Mark the identity has been obtained for this PCB
  340. pPCB->fGotUserIdentity = TRUE;
  341. }
  342. while (FALSE);
  343. if (dwRetCode != NO_ERROR)
  344. {
  345. if (pPCB->pCustomAuthUserData != NULL)
  346. {
  347. FREE (pPCB->pCustomAuthUserData);
  348. pPCB->pCustomAuthUserData = NULL;
  349. }
  350. if (pPCB->pszIdentity != NULL)
  351. {
  352. FREE (pPCB->pszIdentity);
  353. pPCB->pszIdentity = NULL;
  354. }
  355. }
  356. #if 0
  357. if ((dwRetCode != NO_ERROR) &&
  358. (dwRetCode != ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION))
  359. {
  360. // Delete User Data stored in registry since RasEapGetIdentity
  361. // is failing
  362. if ((dwRetCode = ElDeleteEapUserInfo (
  363. pPCB->hUserToken,
  364. pPCB->pwszDeviceGUID,
  365. pPCB->dwEapTypeToBeUsed,
  366. pPCB->pSSID?pPCB->pSSID->SsidLength:0,
  367. pPCB->pSSID?pPCB->pSSID->Ssid:NULL
  368. )) != NO_ERROR)
  369. {
  370. TRACE1 (EAPOL, "ElGetUserIdentityOptimized: ElDeleteEapUserInfo failed with error %ld",
  371. dwRetCode);
  372. // Mark that identity is not obtained, since it has been cleaned
  373. // up now
  374. pPCB->fGotUserIdentity = FALSE;
  375. dwRetCode = ERROR_INVALID_DATA;
  376. }
  377. }
  378. #endif
  379. if (pbUserIn != NULL)
  380. {
  381. FREE (pbUserIn);
  382. }
  383. if (pbAuthData != NULL)
  384. {
  385. FREE (pbAuthData);
  386. }
  387. if (pszIdentity != NULL)
  388. {
  389. FREE (pszIdentity);
  390. }
  391. if (pFreeFunc != NULL)
  392. {
  393. if (lpwszIdentity != NULL)
  394. {
  395. if (( dwRetCode1 = (*(pFreeFunc)) ((BYTE *)lpwszIdentity)) != NO_ERROR)
  396. {
  397. TRACE1 (USER, "ElGetUserIdentityOptimized: Error in pFreeFunc = %ld",
  398. dwRetCode1);
  399. }
  400. }
  401. if (pUserDataOut != NULL)
  402. {
  403. if (( dwRetCode1 = (*(pFreeFunc)) ((BYTE *)pUserDataOut)) != NO_ERROR)
  404. {
  405. TRACE1 (USER, "ElGetUserIdentityOptimized: Error in pFreeFunc = %ld",
  406. dwRetCode1);
  407. }
  408. }
  409. }
  410. return dwRetCode;
  411. }