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.

1113 lines
26 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2001
  5. //
  6. // File: U T I L. C
  7. //
  8. // Contents: Utility functions
  9. //
  10. //
  11. //----------------------------------------------------------------------------
  12. #include "util.h"
  13. //+---------------------------------------------------------------------------
  14. //
  15. // EAPOL related util functions
  16. //
  17. //+---------------------------------------------------------------------------
  18. // EAP configuration registry definitions.
  19. static WCHAR REGKEY_Eap[] = L"System\\CurrentControlSet\\Services\\Rasman\\PPP\\EAP";
  20. static WCHAR REGVAL_szFriendlyName[] = L"FriendlyName";
  21. static WCHAR REGVAL_szConfigDll[] = L"ConfigUIPath";
  22. static WCHAR REGVAL_szIdentityDll[] = L"IdentityPath";
  23. static WCHAR REGVAL_fRequirePwd[] = L"InvokePasswordDialog";
  24. static WCHAR REGVAL_fRequireUser[] = L"InvokeUsernameDialog";
  25. static WCHAR REGVAL_pData[] = L"ConfigData";
  26. static WCHAR REGVAL_fForceConfig[] = L"RequireConfigUI";
  27. static WCHAR REGVAL_fMppeSupported[] = L"MPPEEncryptionSupported";
  28. // Location of User blob
  29. #define cwszEapKeyEapolUser L"Software\\Microsoft\\EAPOL\\UserEapInfo"
  30. #define cwszDefault L"Default"
  31. BYTE g_bDefaultSSID[MAX_SSID_LEN]={0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22};
  32. //
  33. // EAP configuration manipulation routines
  34. //
  35. //+---------------------------------------------------------------------------
  36. //
  37. // Returns a created, empty EAPCFG descriptor node, or NULL on error.
  38. //
  39. DTLNODE*
  40. CreateEapcfgNode (
  41. void
  42. )
  43. {
  44. DTLNODE* pNode = NULL;
  45. EAPCFG* pEapcfg = NULL;
  46. pNode = DtlCreateSizedNode( sizeof(EAPCFG), 0L );
  47. if (pNode)
  48. {
  49. pEapcfg = (EAPCFG* )DtlGetData( pNode );
  50. if (pEapcfg)
  51. {
  52. pEapcfg->dwKey = (DWORD )-1;
  53. pEapcfg->pszConfigDll = NULL;
  54. pEapcfg->pszIdentityDll = NULL;
  55. pEapcfg->dwStdCredentialFlags = 0;
  56. pEapcfg->fProvidesMppeKeys = FALSE;
  57. pEapcfg->fForceConfig = FALSE;
  58. pEapcfg->pData = NULL;
  59. pEapcfg->cbData = 0;
  60. pEapcfg->fConfigDllCalled = FALSE;
  61. }
  62. }
  63. return pNode;
  64. }
  65. //+---------------------------------------------------------------------------
  66. //
  67. // Release resources associated with EAPCFG node 'pNode'. See
  68. // DtlDestroyList.
  69. //
  70. VOID
  71. DestroyEapcfgNode (
  72. IN OUT DTLNODE* pNode
  73. )
  74. {
  75. EAPCFG* pEapcfg = NULL;
  76. pEapcfg = (EAPCFG* )DtlGetData( pNode );
  77. if (pEapcfg)
  78. {
  79. if (pEapcfg->pszConfigDll)
  80. FREE ( pEapcfg->pszConfigDll );
  81. if (pEapcfg->pszIdentityDll)
  82. FREE ( pEapcfg->pszIdentityDll );
  83. if (pEapcfg->pData)
  84. FREE ( pEapcfg->pData );
  85. if (pEapcfg->pszFriendlyName)
  86. FREE ( pEapcfg->pszFriendlyName );
  87. }
  88. DtlDestroyNode( pNode );
  89. }
  90. //+---------------------------------------------------------------------------
  91. //
  92. // Returns the EAPCFG node in list 'pList' with EAP key value of 'dwKey'
  93. // or NULL if not found.
  94. //
  95. DTLNODE*
  96. EapcfgNodeFromKey(
  97. IN DTLLIST* pList,
  98. IN DWORD dwKey
  99. )
  100. {
  101. DTLNODE* pNode = NULL;
  102. for (pNode = DtlGetFirstNode( pList );
  103. pNode;
  104. pNode = DtlGetNextNode( pNode ))
  105. {
  106. EAPCFG* pEapcfg = (EAPCFG* )DtlGetData( pNode );
  107. if (pEapcfg)
  108. {
  109. if (pEapcfg->dwKey == dwKey)
  110. {
  111. return pNode;
  112. }
  113. }
  114. }
  115. return NULL;
  116. }
  117. //+---------------------------------------------------------------------------
  118. //
  119. // Returns the address of a created list of installed custom
  120. // authentication packages or NULL if none could be read. On success, it
  121. // is caller's responsibility to eventually call DtlDestroyList on the
  122. // returned list.
  123. //
  124. DTLLIST*
  125. ReadEapcfgList (
  126. IN DWORD dwFlags
  127. )
  128. {
  129. DWORD dwErr = 0;
  130. BOOL fOk = FALSE;
  131. DTLLIST* pList = NULL;
  132. DTLNODE* pNode = NULL;
  133. EAPCFG* pEapcfg = NULL;
  134. HKEY hkeyLM = NULL;
  135. HKEY hkeyEap = NULL;
  136. HKEY hkeyPackage = NULL;
  137. CHAR szEapType[ 11 + 1 ];
  138. DWORD dwEapType = 0;
  139. TCHAR* psz = NULL;
  140. DWORD dw;
  141. DWORD cb;
  142. INT i;
  143. TCHAR* szCLSID = NULL;
  144. DWORD dwHidePEAPMSCHAPv2 = 0;
  145. HRESULT hr = S_OK;
  146. pList = DtlCreateList( 0L );
  147. if (!pList)
  148. {
  149. return NULL;
  150. }
  151. // Open the EAP key which contains a sub-key for each installed package.
  152. dwErr = RegOpenKeyEx(
  153. HKEY_LOCAL_MACHINE, (LPCTSTR)REGKEY_Eap, 0, KEY_READ, &hkeyEap );
  154. if (dwErr != NO_ERROR)
  155. {
  156. return pList;
  157. }
  158. // Display EAP-MSCHAPv2 as an EAP method?
  159. GetRegDword( hkeyEap, RAS_EAP_VALUENAME_HIDEPEAPMSCHAPv2, &dwHidePEAPMSCHAPv2 );
  160. // Open each sub-key and extract the package definition from it's values.
  161. // Problems with opening individual sub-keys result in that node only
  162. // being discarded.
  163. for (i = 0; TRUE; ++i)
  164. {
  165. cb = sizeof(szEapType);
  166. dwErr = RegEnumKeyExA(
  167. hkeyEap, i, szEapType, &cb, NULL, NULL, NULL, NULL );
  168. if (dwErr != 0)
  169. {
  170. // Includes "out of items", the normal loop termination.
  171. break;
  172. }
  173. dwEapType = atol (szEapType);
  174. if (dwHidePEAPMSCHAPv2 != 0)
  175. {
  176. if (dwEapType == EAP_TYPE_MSCHAPv2)
  177. {
  178. // ignore EAP-MSCHAPv2
  179. continue;
  180. }
  181. }
  182. // Ignored non-mutual-auth DLLs like EAP
  183. if (dwFlags & EAPOL_MUTUAL_AUTH_EAP_ONLY)
  184. {
  185. if (dwEapType == EAP_TYPE_MD5)
  186. {
  187. continue;
  188. }
  189. }
  190. dwErr = RegOpenKeyExA(
  191. hkeyEap, szEapType, 0, KEY_READ, &hkeyPackage );
  192. if (dwErr != 0)
  193. {
  194. continue;
  195. }
  196. do
  197. {
  198. // Roles Supported
  199. dw = RAS_EAP_ROLE_AUTHENTICATEE;
  200. GetRegDword( hkeyPackage, RAS_EAP_VALUENAME_ROLES_SUPPORTED, &dw );
  201. if (dw & RAS_EAP_ROLE_EXCLUDE_IN_EAP)
  202. {
  203. break;
  204. }
  205. if (!(dw & RAS_EAP_ROLE_AUTHENTICATEE))
  206. {
  207. break;
  208. }
  209. pNode = CreateEapcfgNode();
  210. if (!pNode)
  211. {
  212. break;
  213. }
  214. pEapcfg = (EAPCFG* )DtlGetData( pNode );
  215. if (!pEapcfg)
  216. {
  217. break;
  218. }
  219. // EAP type ID.
  220. pEapcfg->dwKey = (LONG )atol( szEapType );
  221. // Friendly display name.
  222. psz = NULL;
  223. dwErr = GetRegSz( hkeyPackage, REGVAL_szFriendlyName, &psz );
  224. if (dwErr != 0)
  225. {
  226. break;
  227. }
  228. pEapcfg->pszFriendlyName = psz;
  229. // Configuration DLL path.
  230. psz = NULL;
  231. dwErr = GetRegExpandSz( hkeyPackage, REGVAL_szConfigDll, &psz );
  232. if (dwErr != 0)
  233. {
  234. break;
  235. }
  236. if (*psz)
  237. {
  238. pEapcfg->pszConfigDll = psz;
  239. }
  240. else
  241. {
  242. FREE ( psz );
  243. }
  244. // Identity DLL path.
  245. psz = NULL;
  246. dwErr = GetRegExpandSz( hkeyPackage, REGVAL_szIdentityDll, &psz );
  247. if (dwErr != 0)
  248. {
  249. break;
  250. }
  251. if (*psz)
  252. {
  253. pEapcfg->pszIdentityDll = psz;
  254. }
  255. else
  256. {
  257. FREE ( psz );
  258. }
  259. // Prompt user name
  260. dw = 1;
  261. GetRegDword( hkeyPackage, REGVAL_fRequireUser, &dw );
  262. if (dw)
  263. pEapcfg->dwStdCredentialFlags |= EAPCFG_FLAG_RequireUsername;
  264. // Prompt password
  265. dw = 0;
  266. GetRegDword( hkeyPackage, REGVAL_fRequirePwd, &dw );
  267. if (dw)
  268. pEapcfg->dwStdCredentialFlags |= EAPCFG_FLAG_RequirePassword;
  269. // MPPE encryption keys flag.
  270. dw = 0;
  271. GetRegDword( hkeyPackage, REGVAL_fMppeSupported, &dw );
  272. pEapcfg->fProvidesMppeKeys = !!dw;
  273. // Force configuration API to run at least once.
  274. dw = FALSE;
  275. GetRegDword( hkeyPackage, REGVAL_fForceConfig, &dw );
  276. pEapcfg->fForceConfig = !!dw;
  277. // Configuration blob.
  278. GetRegBinary(
  279. hkeyPackage, REGVAL_pData,
  280. &pEapcfg->pData, &pEapcfg->cbData );
  281. // ConfigCLSID
  282. dwErr = GetRegSz( hkeyPackage, RAS_EAP_VALUENAME_CONFIG_CLSID,
  283. &szCLSID );
  284. if (dwErr != 0)
  285. {
  286. break;
  287. }
  288. // Ignore errors. Eg. EAP MD5-Challenge does not have a ConfigCLSID.
  289. //
  290. // hr = CLSIDFromString( szCLSID, &( pEapcfg->guidConfigCLSID ) );
  291. FREE ( szCLSID );
  292. // Add the completed node to the list.
  293. DtlAddNodeLast( pList, pNode );
  294. fOk = TRUE;
  295. } while (FALSE);
  296. if (!fOk && pNode)
  297. {
  298. DestroyEapcfgNode( pNode );
  299. }
  300. RegCloseKey( hkeyPackage );
  301. }
  302. RegCloseKey( hkeyEap );
  303. return pList;
  304. }
  305. //+---------------------------------------------------------------------------
  306. //
  307. // Allocates a sized node with space for 'lDataBytes' bytes of user data
  308. // built-in. The node is initialized to contain the address of the
  309. // built-in user data block (or NULL if of zero length) and the
  310. // user-defined node identification code 'lNodeId'. The user data block
  311. // is zeroed.
  312. //
  313. // Returns the address of the new node or NULL if out of memory.
  314. //
  315. DTLNODE*
  316. DtlCreateSizedNode (
  317. IN LONG lDataBytes,
  318. IN LONG_PTR lNodeId
  319. )
  320. {
  321. DTLNODE* pdtlnode = (DTLNODE *) MALLOC ( sizeof(DTLNODE) + lDataBytes );
  322. if (pdtlnode)
  323. {
  324. ZeroMemory( pdtlnode, sizeof(DTLNODE) + lDataBytes );
  325. if (lDataBytes)
  326. pdtlnode->pData = pdtlnode + 1;
  327. pdtlnode->lNodeId = lNodeId;
  328. }
  329. return pdtlnode;
  330. }
  331. //+---------------------------------------------------------------------------
  332. //
  333. // Deallocates node 'pdtlnode'. It is the caller's responsibility to free
  334. // the entry in an unsized node, if necessary.
  335. //
  336. VOID
  337. DtlDestroyNode (
  338. IN OUT DTLNODE* pdtlnode
  339. )
  340. {
  341. if (pdtlnode != NULL)
  342. {
  343. FREE ( pdtlnode );
  344. }
  345. }
  346. //+---------------------------------------------------------------------------
  347. //
  348. // Adds 'pdtlnode' at the end of list 'pdtllist'.
  349. //
  350. // Returns the address of the added node, i.e. 'pdtlnode'.
  351. //
  352. DTLNODE*
  353. DtlAddNodeLast (
  354. IN OUT DTLLIST* pdtllist,
  355. IN OUT DTLNODE* pdtlnode
  356. )
  357. {
  358. if (pdtllist->lNodes)
  359. {
  360. pdtlnode->pdtlnodePrev = pdtllist->pdtlnodeLast;
  361. pdtllist->pdtlnodeLast->pdtlnodeNext = pdtlnode;
  362. }
  363. else
  364. {
  365. pdtlnode->pdtlnodePrev = NULL;
  366. pdtllist->pdtlnodeFirst = pdtlnode;
  367. }
  368. pdtllist->pdtlnodeLast = pdtlnode;
  369. pdtlnode->pdtlnodeNext = NULL;
  370. ++pdtllist->lNodes;
  371. return pdtlnode;
  372. }
  373. //+---------------------------------------------------------------------------
  374. //
  375. // Removes node 'pdtlnodeInList' from list 'pdtllist'.
  376. //
  377. // Returns the address of the removed node, i.e. 'pdtlnodeInList'.
  378. //
  379. DTLNODE*
  380. DtlRemoveNode (
  381. IN OUT DTLLIST* pdtllist,
  382. IN OUT DTLNODE* pdtlnodeInList
  383. )
  384. {
  385. if (pdtlnodeInList->pdtlnodePrev)
  386. pdtlnodeInList->pdtlnodePrev->pdtlnodeNext = pdtlnodeInList->pdtlnodeNext;
  387. else
  388. pdtllist->pdtlnodeFirst = pdtlnodeInList->pdtlnodeNext;
  389. if (pdtlnodeInList->pdtlnodeNext)
  390. pdtlnodeInList->pdtlnodeNext->pdtlnodePrev = pdtlnodeInList->pdtlnodePrev;
  391. else
  392. pdtllist->pdtlnodeLast = pdtlnodeInList->pdtlnodePrev;
  393. --pdtllist->lNodes;
  394. return pdtlnodeInList;
  395. }
  396. //+---------------------------------------------------------------------------
  397. //
  398. // Allocates a list and initializes it to empty. The list is marked with
  399. // the user-defined list identification code 'lListId'.
  400. //
  401. // Returns the address of the list control block or NULL if out of memory.
  402. //
  403. DTLLIST*
  404. DtlCreateList (
  405. IN LONG lListId
  406. )
  407. {
  408. DTLLIST* pdtllist = MALLOC (sizeof(DTLLIST));
  409. if (pdtllist)
  410. {
  411. pdtllist->pdtlnodeFirst = NULL;
  412. pdtllist->pdtlnodeLast = NULL;
  413. pdtllist->lNodes = 0;
  414. pdtllist->lListId = lListId;
  415. }
  416. return pdtllist;
  417. }
  418. //+---------------------------------------------------------------------------
  419. //
  420. // Deallocates all nodes in list 'pdtllist' using the node deallocation
  421. // function 'pfuncDestroyNode' if non-NULL or DtlDestroyNode otherwise.
  422. // Won't GP-fault if passed a NULL list, e.g. if 'pdtllist', was never
  423. // allocated.
  424. //
  425. VOID
  426. DtlDestroyList (
  427. IN OUT DTLLIST* pdtllist,
  428. IN PDESTROYNODE pfuncDestroyNode
  429. )
  430. {
  431. if (pdtllist)
  432. {
  433. DTLNODE* pdtlnode;
  434. while (pdtlnode = DtlGetFirstNode( pdtllist ))
  435. {
  436. DtlRemoveNode( pdtllist, pdtlnode );
  437. if (pfuncDestroyNode)
  438. pfuncDestroyNode( pdtlnode );
  439. else
  440. DtlDestroyNode( pdtlnode );
  441. }
  442. FREE ( pdtllist );
  443. }
  444. }
  445. //+---------------------------------------------------------------------------
  446. //
  447. // Set '*ppbResult' to the BINARY registry value 'pszName' under key
  448. // 'hkey'. If the value does not exist *ppbResult' is set to NULL.
  449. // '*PcbResult' is the number of bytes in the returned '*ppbResult'. It
  450. // is caller's responsibility to Free the returned block.
  451. //
  452. VOID
  453. GetRegBinary (
  454. IN HKEY hkey,
  455. IN TCHAR* pszName,
  456. OUT BYTE** ppbResult,
  457. OUT DWORD* pcbResult
  458. )
  459. {
  460. DWORD dwErr;
  461. DWORD dwType;
  462. BYTE* pb;
  463. DWORD cb;
  464. *ppbResult = NULL;
  465. *pcbResult = 0;
  466. // Get result buffer size required.
  467. dwErr = RegQueryValueEx(
  468. hkey, pszName, NULL, &dwType, NULL, &cb );
  469. if (dwErr != NO_ERROR)
  470. {
  471. return;
  472. }
  473. // Allocate result buffer.
  474. pb = MALLOC (cb);
  475. if (!pb)
  476. {
  477. return;
  478. }
  479. // Get the result block.
  480. dwErr = RegQueryValueEx(
  481. hkey, pszName, NULL, &dwType, (LPBYTE )pb, &cb );
  482. if (dwErr == NO_ERROR)
  483. {
  484. *ppbResult = pb;
  485. *pcbResult = cb;
  486. }
  487. }
  488. //+---------------------------------------------------------------------------
  489. //
  490. // Set '*pdwResult' to the DWORD registry value 'pszName' under key
  491. // 'hkey'. If the value does not exist '*pdwResult' is unchanged.
  492. //
  493. VOID
  494. GetRegDword (
  495. IN HKEY hkey,
  496. IN TCHAR* pszName,
  497. OUT DWORD* pdwResult
  498. )
  499. {
  500. DWORD dwErr;
  501. DWORD dwType;
  502. DWORD dwResult;
  503. DWORD cb;
  504. cb = sizeof(DWORD);
  505. dwErr = RegQueryValueEx(
  506. hkey, pszName, NULL, &dwType, (LPBYTE )&dwResult, &cb );
  507. if ((dwErr == NO_ERROR) && dwType == REG_DWORD && cb == sizeof(DWORD))
  508. {
  509. *pdwResult = dwResult;
  510. }
  511. }
  512. //+---------------------------------------------------------------------------
  513. //
  514. // Set '*ppszResult' to the fully expanded EXPAND_SZ registry value
  515. // 'pszName' under key 'hkey'. If the value does not exist *ppszResult'
  516. // is set to empty string.
  517. //
  518. // Returns 0 if successful or an error code. It is caller's
  519. // responsibility to Free the returned string.
  520. //
  521. DWORD
  522. GetRegExpandSz(
  523. IN HKEY hkey,
  524. IN TCHAR* pszName,
  525. OUT TCHAR** ppszResult )
  526. {
  527. DWORD dwErr;
  528. DWORD cb;
  529. TCHAR* pszResult;
  530. // Get the unexpanded result string.
  531. //
  532. dwErr = GetRegSz( hkey, pszName, ppszResult );
  533. if (dwErr != 0)
  534. {
  535. return dwErr;
  536. }
  537. // Find out how big the expanded string will be.
  538. //
  539. cb = ExpandEnvironmentStrings( *ppszResult, NULL, 0 );
  540. if (cb == 0)
  541. {
  542. dwErr = GetLastError();
  543. FREE ( *ppszResult );
  544. return dwErr;
  545. }
  546. // Allocate a buffer for the expanded string.
  547. //
  548. pszResult = MALLOC ((cb + 1) * sizeof(TCHAR));
  549. if (!pszResult)
  550. {
  551. return ERROR_NOT_ENOUGH_MEMORY;
  552. }
  553. // Expand the environmant variables in the string, storing the result in
  554. // the allocated buffer.
  555. //
  556. cb = ExpandEnvironmentStrings( *ppszResult, pszResult, cb + 1 );
  557. if (cb == 0)
  558. {
  559. dwErr = GetLastError();
  560. if (*ppszResult != NULL)
  561. {
  562. FREE ( *ppszResult );
  563. }
  564. if (pszResult != NULL)
  565. {
  566. FREE ( pszResult );
  567. }
  568. return dwErr;
  569. }
  570. FREE ( *ppszResult );
  571. *ppszResult = pszResult;
  572. return 0;
  573. }
  574. //+---------------------------------------------------------------------------
  575. //
  576. // Set '*ppszResult' to the SZ registry value 'pszName' under key 'hkey'.
  577. // If the value does not exist *ppszResult' is set to empty string.
  578. //
  579. // Returns 0 if successful or an error code. It is caller's
  580. // responsibility to Free the returned string.
  581. //
  582. DWORD
  583. GetRegSz(
  584. IN HKEY hkey,
  585. IN TCHAR* pszName,
  586. OUT TCHAR** ppszResult )
  587. {
  588. DWORD dwErr = NO_ERROR;
  589. DWORD dwType;
  590. DWORD cb;
  591. TCHAR* pszResult;
  592. // Get result buffer size required.
  593. dwErr = RegQueryValueEx(
  594. hkey, pszName, NULL, &dwType, NULL, &cb );
  595. if (dwErr != NO_ERROR)
  596. {
  597. cb = sizeof(TCHAR);
  598. }
  599. // Allocate result buffer.
  600. pszResult = MALLOC (cb * sizeof(TCHAR));
  601. if (!pszResult)
  602. {
  603. return ERROR_NOT_ENOUGH_MEMORY;
  604. }
  605. *pszResult = TEXT('\0');
  606. *ppszResult = pszResult;
  607. // Get the result string. It's not an error if we can't get it.
  608. dwErr = RegQueryValueEx(
  609. hkey, pszName, NULL, &dwType, (LPBYTE )pszResult, &cb );
  610. return NO_ERROR;
  611. }
  612. //
  613. // WZCGetEapUserInfo
  614. //
  615. // Description:
  616. //
  617. // Function called to retrieve the user data for an interface for a
  618. // specific EAP type and SSID (if any). Data is retrieved from the HKCU hive
  619. //
  620. // Arguments:
  621. // pwszGUID - pointer to GUID string for the interface
  622. // dwEapTypeId - EAP type for which user data is to be stored
  623. // dwSizeOfSSID - Size of Special identifier if any for the EAP user blob
  624. // pbSSID - Special identifier if any for the EAP user blob
  625. // pbUserInfo - output: pointer to EAP user data blob
  626. // dwInfoSize - output: pointer to size of EAP user blob
  627. //
  628. // Return values:
  629. // NO_ERROR - success
  630. // non-zero - error
  631. //
  632. DWORD
  633. WZCGetEapUserInfo (
  634. IN WCHAR *pwszGUID,
  635. IN DWORD dwEapTypeId,
  636. IN DWORD dwSizeOfSSID,
  637. IN BYTE *pbSSID,
  638. IN OUT PBYTE pbUserInfo,
  639. IN OUT DWORD *pdwInfoSize
  640. )
  641. {
  642. HKEY hkey = NULL;
  643. HKEY hkey1 = NULL;
  644. HKEY hkey2 = NULL;
  645. DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwTempValueNameLen = 0, dwMaxValueLen = 0;
  646. DWORD dwIndex = 0, dwMaxValueName = 0;
  647. WCHAR *pwszValueName = NULL;
  648. BYTE *pbValueBuf = NULL;
  649. DWORD dwValueData = 0;
  650. BYTE *pbDefaultValue = NULL;
  651. DWORD dwDefaultValueLen = 0;
  652. BYTE *pbEapBlob = NULL;
  653. DWORD dwEapBlob = 0;
  654. BYTE *pbAuthData = NULL;
  655. DWORD dwAuthData = 0;
  656. BOOLEAN fFoundValue = FALSE;
  657. EAPOL_INTF_PARAMS *pRegParams = NULL;
  658. LONG lError = ERROR_SUCCESS;
  659. DWORD dwRetCode = ERROR_SUCCESS;
  660. do
  661. {
  662. // Validate input params
  663. if (pwszGUID == NULL)
  664. {
  665. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  666. break;
  667. }
  668. if (dwEapTypeId == 0)
  669. {
  670. dwRetCode = ERROR_CAN_NOT_COMPLETE;
  671. break;
  672. }
  673. // Get handle to HKCU\Software\...\UserEapInfo
  674. if ((lError = RegOpenKeyEx (
  675. HKEY_CURRENT_USER,
  676. cwszEapKeyEapolUser,
  677. 0,
  678. KEY_READ,
  679. &hkey1
  680. )) != ERROR_SUCCESS)
  681. {
  682. dwRetCode = (DWORD)lError;
  683. break;
  684. }
  685. // Get handle to HKCU\Software\...\UserEapInfo\<GUID>
  686. if ((lError = RegOpenKeyEx (
  687. hkey1,
  688. pwszGUID,
  689. 0,
  690. KEY_READ,
  691. &hkey2
  692. )) != ERROR_SUCCESS)
  693. {
  694. dwRetCode = (DWORD)lError;
  695. break;
  696. }
  697. // Set correct SSID
  698. if (dwSizeOfSSID == 0)
  699. {
  700. pbSSID = g_bDefaultSSID;
  701. dwSizeOfSSID = MAX_SSID_LEN;
  702. }
  703. if ((lError = RegQueryInfoKey (
  704. hkey2,
  705. NULL,
  706. NULL,
  707. NULL,
  708. NULL,
  709. NULL,
  710. NULL,
  711. &dwNumValues,
  712. &dwMaxValueNameLen,
  713. &dwMaxValueLen,
  714. NULL,
  715. NULL
  716. )) != NO_ERROR)
  717. {
  718. dwRetCode = (DWORD)lError;
  719. break;
  720. }
  721. if ((pwszValueName = MALLOC ((dwMaxValueNameLen + 1) * sizeof (WCHAR))) == NULL)
  722. {
  723. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  724. break;
  725. }
  726. dwMaxValueNameLen++;
  727. if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL)
  728. {
  729. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  730. break;
  731. }
  732. for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++)
  733. {
  734. dwValueData = dwMaxValueLen;
  735. dwTempValueNameLen = dwMaxValueNameLen;
  736. if ((lError = RegEnumValue (
  737. hkey2,
  738. dwIndex,
  739. pwszValueName,
  740. &dwTempValueNameLen,
  741. NULL,
  742. NULL,
  743. pbValueBuf,
  744. &dwValueData
  745. )) != ERROR_SUCCESS)
  746. {
  747. if (lError != ERROR_MORE_DATA)
  748. {
  749. break;
  750. }
  751. lError = ERROR_SUCCESS;
  752. }
  753. if (dwValueData < sizeof (EAPOL_INTF_PARAMS))
  754. {
  755. lError = ERROR_INVALID_DATA;
  756. break;
  757. }
  758. pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
  759. if (((DWORD)_wtol(pwszValueName)) > dwMaxValueName)
  760. {
  761. dwMaxValueName = _wtol (pwszValueName);
  762. }
  763. if (!memcmp (pRegParams->bSSID, pbSSID, dwSizeOfSSID))
  764. {
  765. fFoundValue = TRUE;
  766. break;
  767. }
  768. }
  769. if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS))
  770. {
  771. dwRetCode = (DWORD)lError;
  772. break;
  773. }
  774. else
  775. {
  776. lError = ERROR_SUCCESS;
  777. }
  778. if (!fFoundValue)
  779. {
  780. pbEapBlob = NULL;
  781. dwEapBlob = 0;
  782. }
  783. else
  784. {
  785. // Use pbValueBuf & dwValueData
  786. pbEapBlob = pbValueBuf;
  787. dwEapBlob = dwValueData;
  788. }
  789. // If default blob is not present, exit
  790. if ((pbEapBlob == NULL) && (dwEapBlob == 0))
  791. {
  792. *pdwInfoSize = 0;
  793. break;
  794. }
  795. if ((dwRetCode = WZCGetEapData (
  796. dwEapTypeId,
  797. dwEapBlob,
  798. pbEapBlob,
  799. sizeof (EAPOL_INTF_PARAMS),
  800. &dwAuthData,
  801. &pbAuthData
  802. )) != NO_ERROR)
  803. {
  804. break;
  805. }
  806. // Return the data if sufficient space allocated
  807. if ((pbUserInfo != NULL) && (*pdwInfoSize >= dwAuthData))
  808. {
  809. memcpy (pbUserInfo, pbAuthData, dwAuthData);
  810. }
  811. else
  812. {
  813. dwRetCode = ERROR_INSUFFICIENT_BUFFER;
  814. }
  815. *pdwInfoSize = dwAuthData;
  816. } while (FALSE);
  817. if (hkey != NULL)
  818. {
  819. RegCloseKey (hkey);
  820. }
  821. if (hkey1 != NULL)
  822. {
  823. RegCloseKey (hkey1);
  824. }
  825. if (hkey2 != NULL)
  826. {
  827. RegCloseKey (hkey2);
  828. }
  829. if (pbValueBuf != NULL)
  830. {
  831. FREE (pbValueBuf);
  832. }
  833. if (pbDefaultValue != NULL)
  834. {
  835. FREE (pbDefaultValue);
  836. }
  837. if (pwszValueName != NULL)
  838. {
  839. FREE (pwszValueName);
  840. }
  841. return dwRetCode;
  842. }
  843. //
  844. // WZCGetEapData
  845. //
  846. // Description:
  847. //
  848. // Function to extract Eap Data out of a blob containing many EAP data
  849. //
  850. // Arguments:
  851. // dwEapType -
  852. // dwSizeOfIn -
  853. // pbBufferIn -
  854. // dwOffset -
  855. // pdwSizeOfOut -
  856. // ppbBufferOut -
  857. //
  858. // Return values:
  859. //
  860. //
  861. DWORD
  862. WZCGetEapData (
  863. IN DWORD dwEapType,
  864. IN DWORD dwSizeOfIn,
  865. IN BYTE *pbBufferIn,
  866. IN DWORD dwOffset,
  867. IN DWORD *pdwSizeOfOut,
  868. IN PBYTE *ppbBufferOut
  869. )
  870. {
  871. DWORD dwRetCode = NO_ERROR;
  872. DWORD cbOffset = 0;
  873. EAPOL_AUTH_DATA *pCustomData = NULL;
  874. do
  875. {
  876. *pdwSizeOfOut = 0;
  877. *ppbBufferOut = NULL;
  878. if (pbBufferIn == NULL)
  879. {
  880. break;
  881. }
  882. // Align to start of EAP blob
  883. cbOffset = dwOffset;
  884. while (cbOffset < dwSizeOfIn)
  885. {
  886. pCustomData = (EAPOL_AUTH_DATA *)
  887. ((PBYTE) pbBufferIn + cbOffset);
  888. if (pCustomData->dwEapType == dwEapType)
  889. {
  890. break;
  891. }
  892. cbOffset += sizeof (EAPOL_AUTH_DATA) + pCustomData->dwSize;
  893. }
  894. if (cbOffset < dwSizeOfIn)
  895. {
  896. *pdwSizeOfOut = pCustomData->dwSize;
  897. *ppbBufferOut = pCustomData->bData;
  898. }
  899. }
  900. while (FALSE);
  901. return dwRetCode;
  902. }
  903. //
  904. // WZCEapolFreeState
  905. //
  906. // Description:
  907. //
  908. // Function to free EAPOL interface state information on the client side
  909. // obtained via RPC query
  910. //
  911. // Arguments:
  912. // pIntfState -
  913. //
  914. // Return values:
  915. //
  916. //
  917. DWORD
  918. WZCEapolFreeState (
  919. IN EAPOL_INTF_STATE *pIntfState
  920. )
  921. {
  922. DWORD dwRetCode = NO_ERROR;
  923. do
  924. {
  925. RpcFree(pIntfState->pwszLocalMACAddr);
  926. RpcFree(pIntfState->pwszRemoteMACAddr);
  927. RpcFree(pIntfState->pszEapIdentity);
  928. }
  929. while (FALSE);
  930. return dwRetCode;
  931. }