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.

6760 lines
179 KiB

  1. /*
  2. Copyright (c) 1997, Microsoft Corporation, all rights reserved
  3. Description:
  4. History:
  5. Nov 1997: Vijay Baliga created original version.
  6. Sep 1998: Vijay Baliga moved functions from eaptls.c and dialog.c to util.c
  7. */
  8. #include <nt.h> // Required by windows.h
  9. #include <ntrtl.h> // Required by windows.h
  10. #include <nturtl.h> // Required by windows.h
  11. #include <windows.h> // Win32 base API's
  12. #include <rasauth.h> // Required by raseapif.h
  13. #include <rtutils.h> // For RTASSERT
  14. #include <rasman.h> // For EAPLOGONINFO
  15. #include <wintrust.h>
  16. #include <softpub.h>
  17. #include <mscat.h>
  18. #include <wincred.h>
  19. #define STRSAFE_NO_DEPRECATE
  20. #include <strsafe.h>
  21. #define SECURITY_WIN32
  22. #include <security.h> // For GetUserNameExA, CredHandle
  23. #include <schannel.h>
  24. #include <sspi.h> // For CredHandle
  25. #include <wincrypt.h> // Required by sclogon.h
  26. #include <winscard.h> // For SCardListReadersA
  27. #include <sclogon.h> // For ScHelperGetCertFromLogonInfo
  28. #include <cryptui.h>
  29. #include <stdlib.h>
  30. #include <raserror.h>
  31. #include <commctrl.h>
  32. #include <eaptypeid.h>
  33. #include <eaptls.h>
  34. #define INCL_RASAUTHATTRIBUTES
  35. #include <ppputil.h>
  36. extern CRITICAL_SECTION g_csProtectCachedCredentials;
  37. extern BOOL g_fCriticalSectionInitialized;
  38. extern HANDLE g_hStoreChangeNotificationEvt;
  39. extern HANDLE g_hWaitonStoreChangeEvt;
  40. extern HCERTSTORE g_hLocalMachineStore;
  41. extern BOOL g_fChangeNotificationSetup;
  42. /*
  43. Returns:
  44. void
  45. Notes:
  46. Used for printing EAP TLS trace statements.
  47. */
  48. VOID
  49. EapTlsTrace(
  50. IN CHAR* Format,
  51. ...
  52. )
  53. {
  54. va_list arglist;
  55. RTASSERT(NULL != Format);
  56. va_start(arglist, Format);
  57. TraceVprintfExA(g_dwEapTlsTraceId,
  58. 0x00010000 | TRACE_USE_MASK | TRACE_USE_MSEC,
  59. Format,
  60. arglist);
  61. va_end(arglist);
  62. }
  63. #if WINVER > 0x0500
  64. DWORD CheckCallerIdentity ( HANDLE hWVTStateData )
  65. {
  66. DWORD dwRetCode = ERROR_ACCESS_DENIED;
  67. PCRYPT_PROVIDER_DATA pProvData = NULL;
  68. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  69. PCRYPT_PROVIDER_SGNR pProvSigner = NULL;
  70. CERT_CHAIN_POLICY_PARA chainpolicyparams;
  71. CERT_CHAIN_POLICY_STATUS chainpolicystatus;
  72. if (!(pProvData = WTHelperProvDataFromStateData(hWVTStateData)))
  73. {
  74. goto done;
  75. }
  76. if (!(pProvSigner = WTHelperGetProvSignerFromChain(pProvData, 0, FALSE, 0)))
  77. {
  78. goto done;
  79. }
  80. chainpolicyparams.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
  81. //
  82. //
  83. // We do want to test for microsoft test root flags. and dont care
  84. // for revocation flags...
  85. //
  86. chainpolicyparams.dwFlags = CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG |
  87. CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG |
  88. CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS;
  89. pChainContext = pProvSigner->pChainContext;
  90. if (!CertVerifyCertificateChainPolicy (
  91. CERT_CHAIN_POLICY_MICROSOFT_ROOT,
  92. pChainContext,
  93. &chainpolicyparams,
  94. &chainpolicystatus))
  95. {
  96. goto done;
  97. }
  98. else
  99. {
  100. if ( S_OK == chainpolicystatus.dwError )
  101. {
  102. dwRetCode = NO_ERROR;
  103. }
  104. else
  105. {
  106. //
  107. // Check the base policy to see if this
  108. // is a Microsoft test root
  109. //
  110. if (!CertVerifyCertificateChainPolicy (
  111. CERT_CHAIN_POLICY_BASE,
  112. pChainContext,
  113. &chainpolicyparams,
  114. &chainpolicystatus))
  115. {
  116. goto done;
  117. }
  118. else
  119. {
  120. if ( S_OK == chainpolicystatus.dwError )
  121. {
  122. dwRetCode = NO_ERROR;
  123. }
  124. }
  125. }
  126. }
  127. done:
  128. return dwRetCode;
  129. }
  130. DWORD SetupMachineChangeNotification ()
  131. {
  132. DWORD dwRetCode = NO_ERROR;
  133. EapTlsTrace ("SetupMachineChangeNotification");
  134. if ( g_fChangeNotificationSetup )
  135. return dwRetCode;
  136. EnterCriticalSection ( &g_csProtectCachedCredentials );
  137. if ( !g_fChangeNotificationSetup )
  138. {
  139. //
  140. // Create and event and register the callback
  141. // to monitor the changes in the machine store
  142. // and handle cached credentials.
  143. //
  144. g_hStoreChangeNotificationEvt = CreateEvent(NULL,
  145. FALSE,
  146. FALSE,
  147. NULL);
  148. if ( NULL == g_hStoreChangeNotificationEvt )
  149. {
  150. dwRetCode = GetLastError();
  151. EapTlsTrace("Error creating Change notification event 0x%x",dwRetCode );
  152. }
  153. else
  154. {
  155. //Register call back
  156. //and call certcontrolstore api.
  157. //
  158. if ( !RegisterWaitForSingleObject ( &(g_hWaitonStoreChangeEvt),
  159. g_hStoreChangeNotificationEvt ,
  160. MachineStoreChangeNotification,
  161. NULL,
  162. INFINITE,
  163. WT_EXECUTEDEFAULT|WT_EXECUTELONGFUNCTION
  164. )
  165. )
  166. {
  167. dwRetCode = GetLastError();
  168. EapTlsTrace("Error Registering Wait function. 0x%x", dwRetCode );
  169. }
  170. else
  171. {
  172. //
  173. // Call cert control store api
  174. //
  175. // Open the "MY" certificate store.
  176. g_hLocalMachineStore = CertOpenStore(
  177. CERT_STORE_PROV_SYSTEM_A,
  178. X509_ASN_ENCODING,
  179. 0,
  180. (CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG),
  181. "MY");
  182. if (NULL == g_hLocalMachineStore)
  183. {
  184. dwRetCode = GetLastError();
  185. EapTlsTrace("CertOpenStore failed and returned 0x%x", dwRetCode);
  186. }
  187. else
  188. {
  189. if ( ! CertControlStore ( g_hLocalMachineStore,
  190. 0,
  191. CERT_STORE_CTRL_NOTIFY_CHANGE,
  192. &g_hStoreChangeNotificationEvt
  193. )
  194. )
  195. {
  196. dwRetCode = GetLastError();
  197. EapTlsTrace ("CertControlStore failed and returned 0x%x",dwRetCode);
  198. }
  199. else
  200. {
  201. g_fChangeNotificationSetup = TRUE;
  202. }
  203. }
  204. }
  205. }
  206. }
  207. LeaveCriticalSection ( &g_csProtectCachedCredentials );
  208. return dwRetCode;
  209. }
  210. DWORD g_dwVerifyCallerTrustLock = 0;
  211. /*
  212. */
  213. DWORD VerifyCallerTrust ( void * callersAddress )
  214. {
  215. DWORD dwRetCode = NO_ERROR;
  216. HRESULT hr = S_OK;
  217. WINTRUST_DATA wtData;
  218. WINTRUST_FILE_INFO wtFileInfo;
  219. WINTRUST_CATALOG_INFO wtCatalogInfo;
  220. BOOL fRet = FALSE;
  221. HCATADMIN hCATAdmin = NULL;
  222. static BOOL fOKToUseTLS = FALSE;
  223. GUID guidPublishedSoftware = WINTRUST_ACTION_GENERIC_VERIFY_V2;
  224. //
  225. // Following GUID is Mirosoft's Catalog System Root
  226. //
  227. GUID guidCatSystemRoot = { 0xf750e6c3, 0x38ee, 0x11d1,{ 0x85, 0xe5, 0x0, 0xc0, 0x4f, 0xc2, 0x95, 0xee } };
  228. HCATINFO hCATInfo = NULL;
  229. CATALOG_INFO CatInfo;
  230. HANDLE hFile = INVALID_HANDLE_VALUE;
  231. BYTE bHash[40];
  232. DWORD cbHash = 40;
  233. MEMORY_BASIC_INFORMATION mbi;
  234. SIZE_T nbyte;
  235. DWORD nchar;
  236. wchar_t callersModule[MAX_PATH + 1];
  237. if ( fOKToUseTLS )
  238. {
  239. goto done;
  240. }
  241. //
  242. // Allow only one thread to go and do this
  243. //
  244. while (InterlockedIncrement(&g_dwVerifyCallerTrustLock) > 1)
  245. {
  246. InterlockedDecrement(&g_dwVerifyCallerTrustLock);
  247. Sleep(500);
  248. }
  249. if ( fOKToUseTLS )
  250. {
  251. goto decountanddone;
  252. }
  253. EapTlsTrace("Verifying caller...");
  254. nbyte = VirtualQuery(
  255. callersAddress,
  256. &mbi,
  257. sizeof(mbi)
  258. );
  259. if (nbyte < sizeof(mbi))
  260. {
  261. dwRetCode = ERROR_ACCESS_DENIED;
  262. EapTlsTrace("Unauthorized use of TLS attempted");
  263. goto decountanddone;
  264. }
  265. nchar = GetModuleFileNameW(
  266. (HMODULE)(mbi.AllocationBase),
  267. callersModule,
  268. MAX_PATH
  269. );
  270. if (nchar == 0)
  271. {
  272. dwRetCode = GetLastError();
  273. EapTlsTrace("Unauthorized use of TLS attempted");
  274. goto decountanddone;
  275. }
  276. //
  277. //
  278. // Try and see if WinVerifyTrust will verify
  279. // the signature as a standalone file
  280. //
  281. //
  282. ZeroMemory ( &wtData, sizeof(wtData) );
  283. ZeroMemory ( &wtFileInfo, sizeof(wtFileInfo) );
  284. wtData.cbStruct = sizeof(wtData);
  285. wtData.dwUIChoice = WTD_UI_NONE;
  286. wtData.fdwRevocationChecks = WTD_REVOKE_NONE;
  287. wtData.dwStateAction = WTD_STATEACTION_VERIFY;
  288. wtData.dwUnionChoice = WTD_CHOICE_FILE;
  289. wtData.pFile = &wtFileInfo;
  290. wtFileInfo.cbStruct = sizeof( wtFileInfo );
  291. wtFileInfo.pcwszFilePath = callersModule;
  292. hr = WinVerifyTrust ( NULL,
  293. &guidPublishedSoftware,
  294. &wtData
  295. );
  296. if ( ERROR_SUCCESS == hr )
  297. {
  298. //
  299. // Check to see if this is indeed microsoft
  300. // signed caller
  301. //
  302. dwRetCode = CheckCallerIdentity( wtData.hWVTStateData);
  303. wtData.dwStateAction = WTD_STATEACTION_CLOSE;
  304. WinVerifyTrust(NULL, &guidPublishedSoftware, &wtData);
  305. fOKToUseTLS = TRUE;
  306. goto decountanddone;
  307. }
  308. wtData.dwStateAction = WTD_STATEACTION_CLOSE;
  309. WinVerifyTrust(NULL, &guidPublishedSoftware, &wtData);
  310. //
  311. // We did not find the file was signed.
  312. // So check the system catalog to see if
  313. // the file is in the catalog and the catalog
  314. // is signed
  315. //
  316. //
  317. // Open the file
  318. //
  319. hFile = CreateFile ( callersModule,
  320. GENERIC_READ,
  321. FILE_SHARE_READ,
  322. NULL,
  323. OPEN_EXISTING,
  324. FILE_ATTRIBUTE_NORMAL,
  325. NULL
  326. );
  327. if ( INVALID_HANDLE_VALUE == hFile )
  328. {
  329. dwRetCode = GetLastError();
  330. goto decountanddone;
  331. }
  332. fRet = CryptCATAdminAcquireContext( &hCATAdmin,
  333. &guidCatSystemRoot,
  334. 0
  335. );
  336. if ( !fRet )
  337. {
  338. dwRetCode = GetLastError();
  339. goto decountanddone;
  340. }
  341. //
  342. // Get the hash of the file here
  343. //
  344. fRet = CryptCATAdminCalcHashFromFileHandle ( hFile,
  345. &cbHash,
  346. bHash,
  347. 0
  348. );
  349. if ( !fRet )
  350. {
  351. dwRetCode = GetLastError();
  352. goto decountanddone;
  353. }
  354. ZeroMemory(&CatInfo, sizeof(CatInfo));
  355. CatInfo.cbStruct = sizeof(CatInfo);
  356. ZeroMemory( &wtCatalogInfo, sizeof(wtCatalogInfo) );
  357. wtData.dwUnionChoice = WTD_CHOICE_CATALOG;
  358. wtData.dwStateAction = WTD_STATEACTION_VERIFY;
  359. wtData.pCatalog = &wtCatalogInfo;
  360. wtCatalogInfo.cbStruct = sizeof(wtCatalogInfo);
  361. wtCatalogInfo.hMemberFile = hFile;
  362. wtCatalogInfo.pbCalculatedFileHash = bHash;
  363. wtCatalogInfo.cbCalculatedFileHash = cbHash;
  364. while ( ( hCATInfo = CryptCATAdminEnumCatalogFromHash ( hCATAdmin,
  365. bHash,
  366. cbHash,
  367. 0,
  368. &hCATInfo
  369. )
  370. )
  371. )
  372. {
  373. if (!(CryptCATCatalogInfoFromContext(hCATInfo, &CatInfo, 0)))
  374. {
  375. // should do something (??)
  376. continue;
  377. }
  378. wtCatalogInfo.pcwszCatalogFilePath = CatInfo.wszCatalogFile;
  379. hr = WinVerifyTrust ( NULL,
  380. &guidPublishedSoftware,
  381. &wtData
  382. );
  383. if ( ERROR_SUCCESS == hr )
  384. {
  385. //
  386. // Verify that this file is trusted
  387. //
  388. dwRetCode = CheckCallerIdentity( wtData.hWVTStateData);
  389. wtData.dwStateAction = WTD_STATEACTION_CLOSE;
  390. WinVerifyTrust(NULL, &guidPublishedSoftware, &wtData);
  391. fOKToUseTLS = TRUE;
  392. goto decountanddone;
  393. }
  394. }
  395. //
  396. // File not found in any of the catalogs
  397. //
  398. dwRetCode = ERROR_ACCESS_DENIED;
  399. decountanddone:
  400. InterlockedDecrement(&g_dwVerifyCallerTrustLock);
  401. done:
  402. if ( hCATInfo )
  403. {
  404. CryptCATAdminReleaseCatalogContext( hCATAdmin, hCATInfo, 0 );
  405. }
  406. if ( hCATAdmin )
  407. {
  408. CryptCATAdminReleaseContext( hCATAdmin, 0 );
  409. }
  410. if ( hFile )
  411. {
  412. CloseHandle(hFile);
  413. }
  414. return dwRetCode;
  415. }
  416. #endif
  417. /*
  418. Returns:
  419. NO_ERROR: iff Success
  420. Notes:
  421. TraceRegister, RouterLogRegister, etc.
  422. */
  423. DWORD g_EapTlsInitializeLock = 0;
  424. DWORD
  425. EapTlsInitialize2(
  426. IN BOOL fInitialize,
  427. IN BOOL fUI
  428. )
  429. {
  430. static DWORD dwRefCount = 0;
  431. DWORD dwRetCode = NO_ERROR;
  432. //
  433. // This will make sure that only one thread is
  434. // in this function. Stolen from rasipcp/helper.c
  435. //
  436. while (InterlockedIncrement(&g_EapTlsInitializeLock) > 1)
  437. {
  438. InterlockedDecrement(&g_EapTlsInitializeLock);
  439. Sleep(1000);
  440. }
  441. if (fInitialize)
  442. {
  443. if (0 == dwRefCount)
  444. {
  445. InitializeCriticalSection( &g_csProtectCachedCredentials );
  446. g_fCriticalSectionInitialized = TRUE;
  447. if (fUI)
  448. {
  449. g_dwEapTlsTraceId = TraceRegister(L"RASTLSUI");
  450. //
  451. // Initialize the common controls library for the controls we use.
  452. //
  453. {
  454. INITCOMMONCONTROLSEX icc;
  455. icc.dwSize = sizeof(icc);
  456. icc.dwICC = ICC_LISTVIEW_CLASSES;
  457. InitCommonControlsEx (&icc);
  458. }
  459. }
  460. else
  461. {
  462. g_dwEapTlsTraceId = TraceRegister(L"RASTLS");
  463. }
  464. EapTlsTrace("EapTlsInitialize2");
  465. }
  466. dwRefCount++;
  467. }
  468. else
  469. {
  470. dwRefCount--;
  471. if (0 == dwRefCount)
  472. {
  473. EapTlsTrace("EapTls[Un]Initialize2");
  474. if ( !fUI )
  475. {
  476. if ( g_fChangeNotificationSetup)
  477. {
  478. //
  479. // Call in to cleanup the change events.
  480. //
  481. if ( ! UnregisterWaitEx ( g_hWaitonStoreChangeEvt,
  482. INVALID_HANDLE_VALUE
  483. )
  484. )
  485. {
  486. dwRetCode = GetLastError();
  487. EapTlsTrace("Error in UnregisterWaitEx 0x%x",dwRetCode );
  488. }
  489. #if 0
  490. if ( g_hWaitonStoreChangeEvt )
  491. {
  492. CloseHandle(g_hWaitonStoreChangeEvt);
  493. g_hWaitonStoreChangeEvt = NULL;
  494. }
  495. #endif
  496. if ( g_hStoreChangeNotificationEvt )
  497. {
  498. CloseHandle(g_hStoreChangeNotificationEvt);
  499. g_hStoreChangeNotificationEvt = NULL;
  500. }
  501. if (g_hLocalMachineStore)
  502. {
  503. CertCloseStore( g_hLocalMachineStore,
  504. CERT_CLOSE_STORE_CHECK_FLAG
  505. );
  506. g_hLocalMachineStore = NULL;
  507. }
  508. g_fChangeNotificationSetup = FALSE;
  509. }
  510. }
  511. if (INVALID_TRACEID != g_dwEapTlsTraceId)
  512. {
  513. TraceDeregister(g_dwEapTlsTraceId);
  514. g_dwEapTlsTraceId = INVALID_TRACEID;
  515. }
  516. if ( g_fCriticalSectionInitialized )
  517. {
  518. DeleteCriticalSection( &g_csProtectCachedCredentials );
  519. g_fCriticalSectionInitialized = FALSE;
  520. }
  521. FreeScardDlgDll();
  522. }
  523. }
  524. InterlockedDecrement(&g_EapTlsInitializeLock);
  525. return(dwRetCode);
  526. }
  527. /*
  528. Returns:
  529. NO_ERROR: iff Success
  530. Notes:
  531. */
  532. DWORD
  533. EapTlsInitialize(
  534. IN BOOL fInitialize
  535. )
  536. {
  537. return EapTlsInitialize2(fInitialize, FALSE /* fUI */);
  538. }
  539. /*
  540. Returns:
  541. Notes:
  542. Obfuscate PIN in place to foil memory scans for PINs.
  543. */
  544. VOID
  545. EncodePin(
  546. IN EAPTLS_USER_PROPERTIES* pUserProp
  547. )
  548. {
  549. UNICODE_STRING UnicodeString;
  550. UCHAR ucSeed = 0;
  551. RtlInitUnicodeString(&UnicodeString, pUserProp->pwszPin);
  552. RtlRunEncodeUnicodeString(&ucSeed, &UnicodeString);
  553. pUserProp->usLength = UnicodeString.Length;
  554. pUserProp->usMaximumLength = UnicodeString.MaximumLength;
  555. pUserProp->ucSeed = ucSeed;
  556. }
  557. /*
  558. Returns:
  559. Notes:
  560. */
  561. VOID
  562. DecodePin(
  563. IN EAPTLS_USER_PROPERTIES* pUserProp
  564. )
  565. {
  566. UNICODE_STRING UnicodeString;
  567. UnicodeString.Length = pUserProp->usLength;
  568. UnicodeString.MaximumLength = pUserProp->usMaximumLength;
  569. UnicodeString.Buffer = pUserProp->pwszPin;
  570. RtlRunDecodeUnicodeString(pUserProp->ucSeed, &UnicodeString);
  571. }
  572. /*
  573. Returns:
  574. TRUE: Success
  575. FALSE: Failure
  576. Notes:
  577. Converts FileTime to a printable form in *ppwszTime. If the function returns
  578. TRUE, the caller must ultimately call LocalFree(*ppwszTime).
  579. */
  580. BOOL
  581. FFileTimeToStr(
  582. IN FILETIME FileTime,
  583. OUT WCHAR** ppwszTime
  584. )
  585. {
  586. SYSTEMTIME SystemTime;
  587. FILETIME LocalTime;
  588. int nBytesDate;
  589. int nBytesTime;
  590. WCHAR* pwszTemp = NULL;
  591. BOOL fRet = FALSE;
  592. RTASSERT(NULL != ppwszTime);
  593. if (!FileTimeToLocalFileTime(&FileTime, &LocalTime))
  594. {
  595. EapTlsTrace("FileTimeToLocalFileTime(%d %d) failed and returned %d",
  596. FileTime.dwLowDateTime, FileTime.dwHighDateTime,
  597. GetLastError());
  598. goto LDone;
  599. }
  600. if (!FileTimeToSystemTime(&LocalTime, &SystemTime))
  601. {
  602. EapTlsTrace("FileTimeToSystemTime(%d %d) failed and returned %d",
  603. LocalTime.dwLowDateTime, LocalTime.dwHighDateTime,
  604. GetLastError());
  605. goto LDone;
  606. }
  607. nBytesDate = GetDateFormat(LOCALE_USER_DEFAULT, 0, &SystemTime, NULL,
  608. NULL, 0);
  609. if (0 == nBytesDate)
  610. {
  611. EapTlsTrace("GetDateFormat(%d %d %d %d %d %d %d %d) failed and "
  612. "returned %d",
  613. SystemTime.wYear, SystemTime.wMonth, SystemTime.wDayOfWeek,
  614. SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute,
  615. SystemTime.wSecond, SystemTime.wMilliseconds,
  616. GetLastError());
  617. goto LDone;
  618. }
  619. nBytesTime = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &SystemTime, NULL,
  620. NULL, 0);
  621. if (0 == nBytesTime)
  622. {
  623. EapTlsTrace("GetTimeFormat(%d %d %d %d %d %d %d %d) failed and "
  624. "returned %d",
  625. SystemTime.wYear, SystemTime.wMonth, SystemTime.wDayOfWeek,
  626. SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute,
  627. SystemTime.wSecond, SystemTime.wMilliseconds,
  628. GetLastError());
  629. goto LDone;
  630. }
  631. pwszTemp = LocalAlloc(LPTR, (nBytesDate + nBytesTime)*sizeof(WCHAR));
  632. if (NULL == pwszTemp)
  633. {
  634. EapTlsTrace("LocalAlloc failed and returned %d", GetLastError());
  635. goto LDone;
  636. }
  637. if (0 == GetDateFormat(LOCALE_USER_DEFAULT, 0, &SystemTime, NULL,
  638. pwszTemp, nBytesDate))
  639. {
  640. EapTlsTrace("GetDateFormat(%d %d %d %d %d %d %d %d) failed and "
  641. "returned %d",
  642. SystemTime.wYear, SystemTime.wMonth, SystemTime.wDayOfWeek,
  643. SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute,
  644. SystemTime.wSecond, SystemTime.wMilliseconds,
  645. GetLastError());
  646. goto LDone;
  647. }
  648. pwszTemp[nBytesDate - 1] = L' ';
  649. if (0 == GetTimeFormat(LOCALE_USER_DEFAULT, 0, &SystemTime, NULL,
  650. pwszTemp + nBytesDate, nBytesTime))
  651. {
  652. EapTlsTrace("GetTimeFormat(%d %d %d %d %d %d %d %d) failed and "
  653. "returned %d",
  654. SystemTime.wYear, SystemTime.wMonth, SystemTime.wDayOfWeek,
  655. SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute,
  656. SystemTime.wSecond, SystemTime.wMilliseconds,
  657. GetLastError());
  658. goto LDone;
  659. }
  660. *ppwszTime = pwszTemp;
  661. pwszTemp = NULL;
  662. fRet = TRUE;
  663. LDone:
  664. LocalFree(pwszTemp);
  665. return(fRet);
  666. }
  667. BOOL FFormatMachineIdentity1 ( LPWSTR lpszMachineNameRaw, LPWSTR * lppszMachineNameFormatted )
  668. {
  669. BOOL fRetVal = FALSE;
  670. LPWSTR lpwszPrefix = L"host/";
  671. RTASSERT(NULL != lpszMachineNameRaw );
  672. RTASSERT(NULL != lppszMachineNameFormatted );
  673. //
  674. // Prepend host/ to the UPN name
  675. //
  676. *lppszMachineNameFormatted =
  677. (LPWSTR)LocalAlloc ( LPTR, ( wcslen ( lpszMachineNameRaw ) + wcslen ( lpwszPrefix ) + 2 ) * sizeof(WCHAR) );
  678. if ( NULL == *lppszMachineNameFormatted )
  679. {
  680. goto done;
  681. }
  682. wcscpy( *lppszMachineNameFormatted, lpwszPrefix );
  683. wcscat ( *lppszMachineNameFormatted, lpszMachineNameRaw );
  684. fRetVal = TRUE;
  685. done:
  686. return fRetVal;
  687. }
  688. /*
  689. Returns:
  690. TRUE: Success
  691. FALSE: Failure
  692. Notes:
  693. Gets the machine name from the cert as a fully qualified path hostname/path
  694. for example, hostname.redmond.microsoft.com and reformats it in the
  695. domain\hostname format.
  696. */
  697. BOOL FFormatMachineIdentity ( LPWSTR lpszMachineNameRaw, LPWSTR * lppszMachineNameFormatted )
  698. {
  699. BOOL fRetVal = TRUE;
  700. LPTSTR s1 = lpszMachineNameRaw;
  701. LPTSTR s2 = NULL;
  702. RTASSERT(NULL != lpszMachineNameRaw );
  703. RTASSERT(NULL != lppszMachineNameFormatted );
  704. //Need to add 2 more chars. One for NULL and other for $ sign
  705. *lppszMachineNameFormatted = (LPTSTR )LocalAlloc ( LPTR, (wcslen(lpszMachineNameRaw) + 2)* sizeof(WCHAR) );
  706. if ( NULL == *lppszMachineNameFormatted )
  707. {
  708. return FALSE;
  709. }
  710. //find the first "." and that is the identity of the machine.
  711. //the second "." is the domain.
  712. //check to see if there at least 2 dots. If not the raw string is
  713. //the output string
  714. while ( *s1 )
  715. {
  716. if ( *s1 == '.' )
  717. {
  718. if ( !s2 ) //First dot
  719. s2 = s1;
  720. else //second dot
  721. break;
  722. }
  723. s1++;
  724. }
  725. //can perform several additional checks here
  726. if ( *s1 != '.' ) //there are no 2 dots so raw = formatted
  727. {
  728. wcscpy ( *lppszMachineNameFormatted, lpszMachineNameRaw );
  729. goto done;
  730. }
  731. if ( s1-s2 < 2 )
  732. {
  733. wcscpy ( *lppszMachineNameFormatted, lpszMachineNameRaw );
  734. goto done;
  735. }
  736. memcpy ( *lppszMachineNameFormatted, s2+1, ( s1-s2-1) * sizeof(WCHAR));
  737. memcpy ( (*lppszMachineNameFormatted) + (s1-s2-1) , L"\\", sizeof(WCHAR));
  738. wcsncpy ( (*lppszMachineNameFormatted) + (s1-s2), lpszMachineNameRaw, s2-lpszMachineNameRaw );
  739. done:
  740. //Append the $ sign no matter what...
  741. wcscat ( *lppszMachineNameFormatted, L"$" );
  742. return fRetVal;
  743. }
  744. /*
  745. Returns:
  746. TRUE: Success
  747. FALSE: Failure
  748. Notes:
  749. Gets the name in the cert pointed to by pCertContext, and converts it to a
  750. printable form in *ppwszName. If the function returns TRUE, the caller must
  751. ultimately call LocalFree(*ppwszName).
  752. */
  753. BOOL
  754. FUserCertToStr(
  755. IN PCCERT_CONTEXT pCertContext,
  756. OUT WCHAR** ppwszName
  757. )
  758. {
  759. DWORD dwExtensionIndex;
  760. DWORD dwAltEntryIndex;
  761. CERT_EXTENSION* pCertExtension;
  762. CERT_ALT_NAME_INFO* pCertAltNameInfo;
  763. CERT_ALT_NAME_ENTRY* pCertAltNameEntry;
  764. CERT_NAME_VALUE* pCertNameValue;
  765. DWORD dwCertAltNameInfoSize;
  766. DWORD dwCertNameValueSize;
  767. WCHAR* pwszName = NULL;
  768. BOOL fExitOuterFor;
  769. BOOL fExitInnerFor;
  770. BOOL fRet = FALSE;
  771. // See if cert has UPN in AltSubjectName->otherName
  772. fExitOuterFor = FALSE;
  773. for (dwExtensionIndex = 0;
  774. dwExtensionIndex < pCertContext->pCertInfo->cExtension;
  775. dwExtensionIndex++)
  776. {
  777. pCertAltNameInfo = NULL;
  778. pCertExtension = pCertContext->pCertInfo->rgExtension+dwExtensionIndex;
  779. if (strcmp(pCertExtension->pszObjId, szOID_SUBJECT_ALT_NAME2) != 0)
  780. {
  781. goto LOuterForEnd;
  782. }
  783. dwCertAltNameInfoSize = 0;
  784. if (!CryptDecodeObjectEx(
  785. pCertContext->dwCertEncodingType,
  786. X509_ALTERNATE_NAME,
  787. pCertExtension->Value.pbData,
  788. pCertExtension->Value.cbData,
  789. CRYPT_DECODE_ALLOC_FLAG,
  790. NULL,
  791. (VOID*)&pCertAltNameInfo,
  792. &dwCertAltNameInfoSize))
  793. {
  794. goto LOuterForEnd;
  795. }
  796. fExitInnerFor = FALSE;
  797. for (dwAltEntryIndex = 0;
  798. dwAltEntryIndex < pCertAltNameInfo->cAltEntry;
  799. dwAltEntryIndex++)
  800. {
  801. pCertNameValue = NULL;
  802. pCertAltNameEntry = pCertAltNameInfo->rgAltEntry + dwAltEntryIndex;
  803. if ( (CERT_ALT_NAME_OTHER_NAME !=
  804. pCertAltNameEntry->dwAltNameChoice)
  805. || (NULL == pCertAltNameEntry->pOtherName)
  806. || (0 != strcmp(szOID_NT_PRINCIPAL_NAME,
  807. pCertAltNameEntry->pOtherName->pszObjId)))
  808. {
  809. goto LInnerForEnd;
  810. }
  811. // We found a UPN!
  812. dwCertNameValueSize = 0;
  813. if (!CryptDecodeObjectEx(
  814. pCertContext->dwCertEncodingType,
  815. X509_UNICODE_ANY_STRING,
  816. pCertAltNameEntry->pOtherName->Value.pbData,
  817. pCertAltNameEntry->pOtherName->Value.cbData,
  818. CRYPT_DECODE_ALLOC_FLAG,
  819. NULL,
  820. (VOID*)&pCertNameValue,
  821. &dwCertNameValueSize))
  822. {
  823. goto LInnerForEnd;
  824. }
  825. // One extra char for the terminating NULL.
  826. pwszName = LocalAlloc(LPTR, pCertNameValue->Value.cbData +
  827. sizeof(WCHAR));
  828. if (NULL == pwszName)
  829. {
  830. EapTlsTrace("LocalAlloc failed and returned %d",
  831. GetLastError());
  832. fExitInnerFor = TRUE;
  833. fExitOuterFor = TRUE;
  834. goto LInnerForEnd;
  835. }
  836. CopyMemory(pwszName, pCertNameValue->Value.pbData,
  837. pCertNameValue->Value.cbData);
  838. *ppwszName = pwszName;
  839. pwszName = NULL;
  840. fRet = TRUE;
  841. fExitInnerFor = TRUE;
  842. fExitOuterFor = TRUE;
  843. LInnerForEnd:
  844. LocalFree(pCertNameValue);
  845. if (fExitInnerFor)
  846. {
  847. break;
  848. }
  849. }
  850. LOuterForEnd:
  851. LocalFree(pCertAltNameInfo);
  852. if (fExitOuterFor)
  853. {
  854. break;
  855. }
  856. }
  857. LocalFree(pwszName);
  858. return(fRet);
  859. }
  860. /*
  861. Returns:
  862. TRUE: Success
  863. FALSE: Failure
  864. Notes:
  865. Gets the name in the cert pointed to by pCertContext, and converts it to a
  866. printable form in *ppwszName. If the function returns TRUE, the caller must
  867. ultimately call LocalFree(*ppwszName).
  868. */
  869. BOOL
  870. FOtherCertToStr(
  871. IN PCCERT_CONTEXT pCertContext,
  872. IN DWORD fFlags,
  873. OUT WCHAR** ppwszName
  874. )
  875. {
  876. WCHAR* pwszTemp = NULL;
  877. DWORD dwSize;
  878. BOOL fRet = FALSE;
  879. DWORD dwType = 0;
  880. RTASSERT(NULL != ppwszName);
  881. dwType = CERT_NAME_SIMPLE_DISPLAY_TYPE;
  882. dwSize = CertGetNameString(pCertContext,dwType ,
  883. fFlags, NULL, NULL, 0);
  884. // dwSize is the number of characters, including the terminating NULL.
  885. if (dwSize <= 1)
  886. {
  887. EapTlsTrace("CertGetNameString for CERT_NAME_SIMPLE_DISPLAY_TYPE failed.");
  888. goto LDone;
  889. }
  890. pwszTemp = LocalAlloc(LPTR, dwSize*sizeof(WCHAR));
  891. if (NULL == pwszTemp)
  892. {
  893. EapTlsTrace("LocalAlloc failed and returned %d", GetLastError());
  894. goto LDone;
  895. }
  896. dwSize = CertGetNameString(pCertContext, dwType,
  897. fFlags, NULL, pwszTemp, dwSize);
  898. if (dwSize <= 1)
  899. {
  900. EapTlsTrace("CertGetNameString failed.");
  901. goto LDone;
  902. }
  903. *ppwszName = pwszTemp;
  904. pwszTemp = NULL;
  905. fRet = TRUE;
  906. LDone:
  907. LocalFree(pwszTemp);
  908. return(fRet);
  909. }
  910. /*
  911. Returns:
  912. TRUE: Success
  913. FALSE: Failure
  914. Notes:
  915. Special function for getting the DNS machine name
  916. from the machine auth certificate
  917. */
  918. BOOL
  919. FMachineAuthCertToStr
  920. (
  921. IN PCCERT_CONTEXT pCertContext,
  922. OUT WCHAR ** ppwszName
  923. )
  924. {
  925. DWORD dwExtensionIndex;
  926. DWORD dwAltEntryIndex;
  927. CERT_EXTENSION* pCertExtension;
  928. CERT_ALT_NAME_INFO* pCertAltNameInfo;
  929. CERT_ALT_NAME_ENTRY* pCertAltNameEntry;
  930. DWORD dwCertAltNameInfoSize;
  931. WCHAR* pwszName = NULL;
  932. BOOL fExitOuterFor;
  933. BOOL fExitInnerFor;
  934. BOOL fRet = FALSE;
  935. // See if cert has UPN in AltSubjectName->otherName
  936. fExitOuterFor = FALSE;
  937. for (dwExtensionIndex = 0;
  938. dwExtensionIndex < pCertContext->pCertInfo->cExtension;
  939. dwExtensionIndex++)
  940. {
  941. pCertAltNameInfo = NULL;
  942. pCertExtension = pCertContext->pCertInfo->rgExtension+dwExtensionIndex;
  943. if (strcmp(pCertExtension->pszObjId, szOID_SUBJECT_ALT_NAME2) != 0)
  944. {
  945. goto LOuterForEnd;
  946. }
  947. dwCertAltNameInfoSize = 0;
  948. if (!CryptDecodeObjectEx(
  949. pCertContext->dwCertEncodingType,
  950. X509_ALTERNATE_NAME,
  951. pCertExtension->Value.pbData,
  952. pCertExtension->Value.cbData,
  953. CRYPT_DECODE_ALLOC_FLAG,
  954. NULL,
  955. (VOID*)&pCertAltNameInfo,
  956. &dwCertAltNameInfoSize))
  957. {
  958. goto LOuterForEnd;
  959. }
  960. fExitInnerFor = FALSE;
  961. for (dwAltEntryIndex = 0;
  962. dwAltEntryIndex < pCertAltNameInfo->cAltEntry;
  963. dwAltEntryIndex++)
  964. {
  965. pCertAltNameEntry = pCertAltNameInfo->rgAltEntry + dwAltEntryIndex;
  966. if ( (CERT_ALT_NAME_DNS_NAME !=
  967. pCertAltNameEntry->dwAltNameChoice)
  968. || (NULL == pCertAltNameEntry->pwszDNSName)
  969. )
  970. {
  971. goto LInnerForEnd;
  972. }
  973. // We found the DNS Name!
  974. // One extra char for the terminating NULL.
  975. pwszName = LocalAlloc(LPTR, wcslen( pCertAltNameEntry->pwszDNSName ) * sizeof(WCHAR) +
  976. sizeof(WCHAR));
  977. if (NULL == pwszName)
  978. {
  979. EapTlsTrace("LocalAlloc failed and returned %d",
  980. GetLastError());
  981. fExitInnerFor = TRUE;
  982. fExitOuterFor = TRUE;
  983. goto LInnerForEnd;
  984. }
  985. wcscpy (pwszName, pCertAltNameEntry->pwszDNSName );
  986. *ppwszName = pwszName;
  987. pwszName = NULL;
  988. fRet = TRUE;
  989. fExitInnerFor = TRUE;
  990. fExitOuterFor = TRUE;
  991. LInnerForEnd:
  992. if (fExitInnerFor)
  993. {
  994. break;
  995. }
  996. }
  997. LOuterForEnd:
  998. LocalFree(pCertAltNameInfo);
  999. if (fExitOuterFor)
  1000. {
  1001. break;
  1002. }
  1003. }
  1004. LocalFree(pwszName);
  1005. return(fRet);
  1006. }
  1007. /*
  1008. Returns:
  1009. TRUE: Success
  1010. FALSE: Failure
  1011. Notes:
  1012. Gets the name in the cert pointed to by pCertContext, and converts it to a
  1013. printable form in *ppwszName. If the function returns TRUE, the caller must
  1014. ultimately call LocalFree(*ppwszName).
  1015. */
  1016. BOOL
  1017. FCertToStr(
  1018. IN PCCERT_CONTEXT pCertContext,
  1019. IN DWORD fFlags,
  1020. IN BOOL fMachineCert,
  1021. OUT WCHAR** ppwszName
  1022. )
  1023. {
  1024. if (!fMachineCert)
  1025. {
  1026. if (FUserCertToStr(pCertContext, ppwszName))
  1027. {
  1028. return(TRUE);
  1029. }
  1030. }
  1031. return(FOtherCertToStr(pCertContext, fFlags, ppwszName));
  1032. }
  1033. #if 0
  1034. BOOL
  1035. FGetIssuerOrSubject ( IN PCCERT_CONTEXT pCertContext,
  1036. IN DWORD dwFlags,
  1037. OUT WCHAR ** ppszNameString
  1038. )
  1039. {
  1040. BOOL fRet = TRUE;
  1041. DWORD cbNameString =0;
  1042. LPWSTR lpwszNameString = NULL;
  1043. //
  1044. // Get the issued to field here
  1045. //
  1046. cbNameString = CertGetNameString(pCertContext,
  1047. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  1048. dwFlags,
  1049. NULL,
  1050. lpwszNameString,
  1051. 0
  1052. );
  1053. if ( 0 == cbNameString )
  1054. {
  1055. EapTlsTrace("Name String Item not found");
  1056. fRet = FALSE;
  1057. goto LDone;
  1058. }
  1059. lpwszNameString = (LPWSTR)LocalAlloc(LPTR, cbNameString );
  1060. if ( NULL == lpwszNameString )
  1061. {
  1062. EapTlsTrace("Error allocing memory for name string");
  1063. fRet = FALSE;
  1064. goto LDone;
  1065. }
  1066. cbNameString = CertGetNameString(pCertContext,
  1067. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  1068. dwFlags,
  1069. NULL,
  1070. lpwszNameString,
  1071. cbNameString
  1072. );
  1073. *ppszNameString = lpwszNameString;
  1074. lpwszNameString = NULL;
  1075. LDone:
  1076. LocalFree(lpwszNameString);
  1077. return fRet;
  1078. }
  1079. #endif
  1080. /*
  1081. Returns:
  1082. TRUE: Success
  1083. FALSE: Failure
  1084. Notes:
  1085. Stores the friendly name of the cert pointed to by pCertContext in
  1086. *ppwszName. If the function returns TRUE, the caller must ultimately call
  1087. LocalFree(*ppwszName).
  1088. */
  1089. BOOL
  1090. FGetFriendlyName(
  1091. IN PCCERT_CONTEXT pCertContext,
  1092. OUT WCHAR** ppwszName
  1093. )
  1094. {
  1095. WCHAR* pwszName = NULL;
  1096. DWORD dwBytes;
  1097. BOOL fRet = FALSE;
  1098. RTASSERT(NULL != ppwszName);
  1099. if (!CertGetCertificateContextProperty(pCertContext,
  1100. CERT_FRIENDLY_NAME_PROP_ID, NULL, &dwBytes))
  1101. {
  1102. // If there is no Friendly Name property, don't print an error stmt.
  1103. goto LDone;
  1104. }
  1105. pwszName = LocalAlloc(LPTR, dwBytes);
  1106. if (NULL == pwszName)
  1107. {
  1108. EapTlsTrace("LocalAlloc failed and returned %d", GetLastError());
  1109. goto LDone;
  1110. }
  1111. if (!CertGetCertificateContextProperty(pCertContext,
  1112. CERT_FRIENDLY_NAME_PROP_ID, pwszName, &dwBytes))
  1113. {
  1114. EapTlsTrace("CertGetCertificateContextProperty failed and "
  1115. "returned 0x%x", GetLastError());
  1116. goto LDone;
  1117. }
  1118. *ppwszName = pwszName;
  1119. pwszName = NULL;
  1120. fRet = TRUE;
  1121. LDone:
  1122. LocalFree(pwszName);
  1123. return(fRet);
  1124. }
  1125. /*
  1126. Returns:
  1127. TRUE iff there is a smart card reader installed.
  1128. Notes:
  1129. This function was provided by Doug Barlow.
  1130. If 0 is used as the SCARDCONTEXT parameter, it just looks in the registry
  1131. for defined readers. This will return a list of all readers ever installed
  1132. on the system. To actually detect the current state of the system, we have
  1133. to use a valid SCARDCONTEXT handle.
  1134. */
  1135. BOOL
  1136. FSmartCardReaderInstalled(
  1137. VOID
  1138. )
  1139. {
  1140. LONG lErr;
  1141. DWORD dwLen = 0;
  1142. SCARDCONTEXT hCtx = 0;
  1143. BOOL fReturn = FALSE;
  1144. lErr = SCardListReadersA(0, NULL, NULL, &dwLen);
  1145. fReturn = ( (NO_ERROR == lErr)
  1146. && (2 * sizeof(CHAR) < dwLen));
  1147. if (!fReturn)
  1148. {
  1149. goto LDone;
  1150. }
  1151. fReturn = FALSE;
  1152. lErr = SCardEstablishContext(SCARD_SCOPE_USER, 0, 0, &hCtx);
  1153. if (SCARD_S_SUCCESS != lErr)
  1154. {
  1155. goto LDone;
  1156. }
  1157. lErr = SCardListReadersA(hCtx, NULL, NULL, &dwLen);
  1158. fReturn = ( (NO_ERROR == lErr)
  1159. && (2 * sizeof(CHAR) < dwLen));
  1160. LDone:
  1161. if (0 != hCtx)
  1162. {
  1163. SCardReleaseContext(hCtx);
  1164. }
  1165. return(fReturn);
  1166. }
  1167. //Get EKU Usage Blob out of the certificate Context
  1168. DWORD DwGetEKUUsage (
  1169. IN PCCERT_CONTEXT pCertContext,
  1170. OUT PCERT_ENHKEY_USAGE * ppUsage
  1171. )
  1172. {
  1173. DWORD dwBytes = 0;
  1174. DWORD dwErr = ERROR_SUCCESS;
  1175. PCERT_ENHKEY_USAGE pUsage = NULL;
  1176. EapTlsTrace("FGetEKUUsage");
  1177. if (!CertGetEnhancedKeyUsage(pCertContext, 0, NULL, &dwBytes))
  1178. {
  1179. dwErr = GetLastError();
  1180. if (CRYPT_E_NOT_FOUND == dwErr)
  1181. {
  1182. EapTlsTrace("No usage in cert");
  1183. goto LDone;
  1184. }
  1185. EapTlsTrace("FGetEKUUsage failed and returned 0x%x", dwErr);
  1186. goto LDone;
  1187. }
  1188. pUsage = LocalAlloc(LPTR, dwBytes);
  1189. if (NULL == pUsage)
  1190. {
  1191. dwErr = GetLastError();
  1192. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  1193. goto LDone;
  1194. }
  1195. if (!CertGetEnhancedKeyUsage(pCertContext, 0, pUsage, &dwBytes))
  1196. {
  1197. dwErr = GetLastError();
  1198. EapTlsTrace("FGetEKUUsage failed and returned 0x%x", dwErr);
  1199. goto LDone;
  1200. }
  1201. *ppUsage = pUsage;
  1202. LDone:
  1203. return dwErr;
  1204. }
  1205. /*
  1206. * This functionw will check to see if the registry based cert is
  1207. * a smart card cert and if the context can be opened in silent
  1208. * mode.
  1209. */
  1210. BOOL
  1211. FCheckSCardCertAndCanOpenSilentContext ( IN PCCERT_CONTEXT pCertContext )
  1212. {
  1213. PCERT_ENHKEY_USAGE pUsageInternal = NULL;
  1214. BOOL fRet = TRUE;
  1215. DWORD dwIndex = 0;
  1216. CRYPT_KEY_PROV_INFO * pCryptKeyProvInfo = NULL;
  1217. HCRYPTPROV hProv = 0;
  1218. DWORD dwParam = 0;
  1219. DWORD dwDataLen = 0;
  1220. #if 0
  1221. //
  1222. // This is not required anymore. We use CertFindChainInStore
  1223. // which will make sure if private key exists...
  1224. //
  1225. HCRYPTPROV hProv1 = 0;
  1226. #endif
  1227. EapTlsTrace("FCheckSCardCertAndCanOpenSilentContext");
  1228. if ( DwGetEKUUsage ( pCertContext,
  1229. &pUsageInternal) != ERROR_SUCCESS
  1230. )
  1231. {
  1232. goto LDone;
  1233. }
  1234. for (dwIndex = 0; dwIndex < pUsageInternal->cUsageIdentifier; dwIndex++)
  1235. {
  1236. if ( !strcmp(pUsageInternal->rgpszUsageIdentifier[dwIndex],
  1237. szOID_KP_SMARTCARD_LOGON))
  1238. {
  1239. EapTlsTrace("Found SCard Cert in registey. Skipping...");
  1240. goto LDone;
  1241. }
  1242. }
  1243. //
  1244. //there is no scard logon oid in the cert
  1245. //So, now check to see if the csp is mixed mode
  1246. //
  1247. if (!CertGetCertificateContextProperty(
  1248. pCertContext,
  1249. CERT_KEY_PROV_INFO_PROP_ID,
  1250. NULL,
  1251. &dwDataLen))
  1252. {
  1253. EapTlsTrace("CertGetCertificateContextProperty failed: 0x%x", GetLastError());
  1254. goto LDone;
  1255. }
  1256. pCryptKeyProvInfo = LocalAlloc(LPTR, dwDataLen);
  1257. if (NULL == pCryptKeyProvInfo)
  1258. {
  1259. EapTlsTrace("Out of memory: 0x%x", GetLastError());
  1260. goto LDone;
  1261. }
  1262. if (!CertGetCertificateContextProperty(
  1263. pCertContext,
  1264. CERT_KEY_PROV_INFO_PROP_ID,
  1265. pCryptKeyProvInfo,
  1266. &dwDataLen))
  1267. {
  1268. EapTlsTrace("CertGetCertificateContextProperty failed: 0x%x", GetLastError());
  1269. goto LDone;
  1270. }
  1271. EapTlsTrace( "Acquiring Context for Container Name: %ws, ProvName: %ws, ProvType 0x%x",
  1272. pCryptKeyProvInfo->pwszContainerName,
  1273. pCryptKeyProvInfo->pwszProvName,
  1274. pCryptKeyProvInfo->dwProvType
  1275. );
  1276. if (!CryptAcquireContext(
  1277. &hProv,
  1278. pCryptKeyProvInfo->pwszContainerName,
  1279. pCryptKeyProvInfo->pwszProvName,
  1280. pCryptKeyProvInfo->dwProvType,
  1281. (pCryptKeyProvInfo->dwFlags &
  1282. ~CERT_SET_KEY_PROV_HANDLE_PROP_ID) |
  1283. CRYPT_SILENT))
  1284. {
  1285. DWORD dwErr = GetLastError();
  1286. /*
  1287. if ( SCARD_E_NO_SMARTCARD == dwErr )
  1288. {
  1289. //This CSP requires a smart card do this is a smart
  1290. //card cert in registry
  1291. fRet = TRUE;
  1292. }
  1293. */
  1294. EapTlsTrace("CryptAcquireContext failed. This CSP cannot be opened in silent mode. skipping cert.Err: 0x%x", dwErr);
  1295. goto LDone;
  1296. }
  1297. dwDataLen = sizeof(dwParam);
  1298. if ( !CryptGetProvParam ( hProv,
  1299. PP_IMPTYPE,
  1300. (BYTE *)&dwParam,
  1301. &dwDataLen,
  1302. 0
  1303. ))
  1304. {
  1305. EapTlsTrace("CryptGetProvParam failed: 0x%x", GetLastError());
  1306. goto LDone;
  1307. }
  1308. //now check to see if CSP is MIXED
  1309. if ( ( dwParam & (CRYPT_IMPL_MIXED | CRYPT_IMPL_REMOVABLE) ) ==
  1310. (CRYPT_IMPL_MIXED | CRYPT_IMPL_REMOVABLE)
  1311. )
  1312. {
  1313. EapTlsTrace("Found SCard Cert in registey. Skipping...");
  1314. goto LDone;
  1315. }
  1316. #if 0
  1317. //
  1318. // This is not required anymore. We use CertFindChainInStore
  1319. // which will make sure that private key exists...
  1320. //
  1321. //
  1322. // Check to see if we have the private
  1323. // key corresponding to this cert
  1324. // if not drop this cert.
  1325. if (!CryptAcquireCertificatePrivateKey(
  1326. pCertContext,
  1327. CRYPT_ACQUIRE_COMPARE_KEY_FLAG | CRYPT_SILENT,
  1328. NULL,
  1329. &hProv1,
  1330. NULL,
  1331. NULL
  1332. ))
  1333. {
  1334. EapTlsTrace("Found a certificate without private key. Skipping. Error 0x%x",GetLastError());
  1335. goto LDone;
  1336. }
  1337. CryptReleaseContext(hProv1, 0);
  1338. #endif
  1339. fRet = FALSE;
  1340. LDone:
  1341. if ( pUsageInternal )
  1342. LocalFree(pUsageInternal);
  1343. if ( pCryptKeyProvInfo )
  1344. LocalFree(pCryptKeyProvInfo);
  1345. if (0 != hProv)
  1346. {
  1347. CryptReleaseContext(hProv, 0);
  1348. }
  1349. return fRet;
  1350. }
  1351. /*
  1352. Add selected certs to the
  1353. */
  1354. VOID AddCertNodeToSelList ( EAPTLS_HASH * pHash,
  1355. DWORD dwNumHashes,
  1356. EAPTLS_CERT_NODE * pNode,
  1357. EAPTLS_CERT_NODE ** ppSelCertList, //This is an array of pointers
  1358. DWORD * pdwNextSelCert
  1359. )
  1360. {
  1361. DWORD dw = 0;
  1362. DWORD dw1 = 0;
  1363. RTASSERT(NULL != pNode);
  1364. EapTlsTrace("Add Selected Cert to List");
  1365. //No selected certificates
  1366. if ( 0 == dwNumHashes || !ppSelCertList )
  1367. goto done;
  1368. while ( dw < dwNumHashes )
  1369. {
  1370. if (!memcmp(&(pNode->Hash), (pHash+ dw), sizeof(EAPTLS_HASH)))
  1371. {
  1372. //
  1373. //check to see if the node's already in the list.
  1374. //iff not then add it. Looks like there is some
  1375. //problem with possible dup certs in the cert store
  1376. //
  1377. while ( dw1 < *pdwNextSelCert )
  1378. {
  1379. if ( ! memcmp( &(*(ppSelCertList+dw1))->Hash, &(pNode->Hash), sizeof(EAPTLS_HASH) ) )
  1380. {
  1381. //This is a dup node in mmc. So Skip it...
  1382. goto done;
  1383. }
  1384. dw1++;
  1385. }
  1386. *( ppSelCertList + *pdwNextSelCert ) = pNode;
  1387. *pdwNextSelCert = *pdwNextSelCert + 1;
  1388. break;
  1389. }
  1390. dw++;
  1391. }
  1392. done:
  1393. return;
  1394. }
  1395. /*
  1396. Returns:
  1397. TRUE if no enhanced key usages exist, or pCertContext has the
  1398. szOID_PKIX_KP_SERVER_AUTH or szOID_PKIX_KP_CLIENT_AUTH usage depending on
  1399. whether fMachine is TRUE or FALSE.
  1400. Notes:
  1401. */
  1402. BOOL
  1403. FCheckUsage(
  1404. IN PCCERT_CONTEXT pCertContext,
  1405. IN PCERT_ENHKEY_USAGE pUsage,
  1406. IN BOOL fMachine
  1407. )
  1408. {
  1409. DWORD dwIndex;
  1410. DWORD dwErr;
  1411. BOOL fRet = FALSE;
  1412. PCERT_ENHKEY_USAGE pUsageInternal = pUsage;
  1413. EapTlsTrace("FCheckUsage");
  1414. if ( NULL == pUsageInternal )
  1415. {
  1416. dwErr = DwGetEKUUsage ( pCertContext,
  1417. &pUsageInternal);
  1418. if ( dwErr != ERROR_SUCCESS )
  1419. goto LDone;
  1420. }
  1421. for (dwIndex = 0; dwIndex < pUsageInternal->cUsageIdentifier; dwIndex++)
  1422. {
  1423. if ( ( fMachine
  1424. && !strcmp(pUsageInternal->rgpszUsageIdentifier[dwIndex],
  1425. szOID_PKIX_KP_SERVER_AUTH))
  1426. || ( !fMachine
  1427. && !strcmp(pUsageInternal->rgpszUsageIdentifier[dwIndex],
  1428. szOID_PKIX_KP_CLIENT_AUTH)))
  1429. {
  1430. fRet = TRUE;
  1431. break;
  1432. }
  1433. }
  1434. LDone:
  1435. if ( NULL == pUsage )
  1436. {
  1437. if ( pUsageInternal )
  1438. LocalFree(pUsageInternal);
  1439. }
  1440. return(fRet);
  1441. }
  1442. DWORD DwCheckCertPolicy
  1443. (
  1444. IN PCCERT_CONTEXT pCertContext,
  1445. OUT PCCERT_CHAIN_CONTEXT * ppCertChainContext
  1446. )
  1447. {
  1448. DWORD dwRetCode = ERROR_SUCCESS;
  1449. LPSTR lpszEnhUsage = szOID_PKIX_KP_CLIENT_AUTH;
  1450. CERT_CHAIN_PARA ChainPara;
  1451. CERT_ENHKEY_USAGE EnhKeyUsage;
  1452. CERT_USAGE_MATCH CertUsage;
  1453. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  1454. CERT_CHAIN_POLICY_PARA PolicyPara;
  1455. CERT_CHAIN_POLICY_STATUS PolicyStatus;
  1456. EapTlsTrace("FCheckPolicy");
  1457. *ppCertChainContext = NULL;
  1458. ZeroMemory ( &ChainPara, sizeof(ChainPara) );
  1459. ZeroMemory ( &EnhKeyUsage, sizeof(EnhKeyUsage) );
  1460. ZeroMemory ( &CertUsage, sizeof(CertUsage) );
  1461. EnhKeyUsage.rgpszUsageIdentifier = &lpszEnhUsage;
  1462. EnhKeyUsage.cUsageIdentifier = 1;
  1463. EnhKeyUsage.rgpszUsageIdentifier = &lpszEnhUsage;
  1464. CertUsage.dwType = USAGE_MATCH_TYPE_AND;
  1465. CertUsage.Usage = EnhKeyUsage;
  1466. ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
  1467. ChainPara.RequestedUsage = CertUsage;
  1468. if(!CertGetCertificateChain(
  1469. NULL,
  1470. pCertContext,
  1471. NULL,
  1472. pCertContext->hCertStore,
  1473. &ChainPara,
  1474. 0,
  1475. NULL,
  1476. &pChainContext))
  1477. {
  1478. dwRetCode = GetLastError();
  1479. EapTlsTrace("CertGetCertificateChain failed and returned 0x%x", dwRetCode );
  1480. pChainContext = NULL;
  1481. goto LDone;
  1482. }
  1483. ZeroMemory( &PolicyPara, sizeof(PolicyPara) );
  1484. PolicyPara.cbSize = sizeof(PolicyPara);
  1485. PolicyPara.dwFlags = BASIC_CONSTRAINTS_CERT_CHAIN_POLICY_END_ENTITY_FLAG;
  1486. ZeroMemory( &PolicyStatus, sizeof(PolicyStatus) );
  1487. //
  1488. // The chain already has verified the policy.
  1489. // Chain context will have several bits set.
  1490. // To get one error out of it, call CErtVerifyCertificateChainPolicy
  1491. //
  1492. if ( !CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_NT_AUTH,
  1493. pChainContext,
  1494. &PolicyPara,
  1495. &PolicyStatus
  1496. )
  1497. )
  1498. {
  1499. dwRetCode = GetLastError();
  1500. EapTlsTrace( "CertVerifyCertificateChainPolicy failed. Continuing with root hash matching"
  1501. "GetLastError = 0x%x.", dwRetCode);
  1502. }
  1503. else
  1504. {
  1505. //
  1506. //Check to see if the policy status is good. If so,
  1507. //there is no need to check for connectoid hashes any more...
  1508. //
  1509. if ( PolicyStatus.dwError != 0 )
  1510. {
  1511. dwRetCode = PolicyStatus.dwError;
  1512. EapTlsTrace( "CertVerifyCertificateChainPolicy succeeded but policy check failed 0x%x."
  1513. , dwRetCode );
  1514. }
  1515. else
  1516. {
  1517. *ppCertChainContext = pChainContext;
  1518. }
  1519. }
  1520. LDone:
  1521. if ( dwRetCode != ERROR_SUCCESS && pChainContext )
  1522. {
  1523. CertFreeCertificateChain ( pChainContext );
  1524. }
  1525. EapTlsTrace("FCheckPolicy done.");
  1526. return dwRetCode;
  1527. }
  1528. /*
  1529. Returns:
  1530. TRUE iff the certificate is time valid.
  1531. Notes:
  1532. */
  1533. BOOL FCheckTimeValidity (
  1534. IN PCCERT_CONTEXT pCertContext
  1535. )
  1536. {
  1537. BOOL fRet = FALSE;
  1538. SYSTEMTIME SysTime;
  1539. FILETIME FileTime;
  1540. EapTlsTrace("FCheckTimeValidity");
  1541. GetSystemTime(&SysTime);
  1542. if ( !SystemTimeToFileTime ( &SysTime, &FileTime ) )
  1543. {
  1544. EapTlsTrace ("Error converting from system time to file time %ld", GetLastError());
  1545. goto done;
  1546. }
  1547. if ( CertVerifyTimeValidity ( &FileTime, pCertContext->pCertInfo ) )
  1548. {
  1549. //should return a 0 if the certificate is time valid.
  1550. EapTlsTrace ( "Non Time Valid Certificate was encountered");
  1551. goto done;
  1552. }
  1553. fRet = TRUE;
  1554. done:
  1555. return fRet;
  1556. }
  1557. /*
  1558. Returns:
  1559. TRUE iff the CSP is Microsoft RSA SChannel Cryptographic Provider.
  1560. Notes:
  1561. */
  1562. BOOL
  1563. FCheckCSP(
  1564. IN PCCERT_CONTEXT pCertContext
  1565. )
  1566. {
  1567. DWORD dwBytes;
  1568. CRYPT_KEY_PROV_INFO* pCryptKeyProvInfo = NULL;
  1569. BOOL fRet = FALSE;
  1570. EapTlsTrace("FCheckCSP");
  1571. if (!CertGetCertificateContextProperty(pCertContext,
  1572. CERT_KEY_PROV_INFO_PROP_ID, NULL, &dwBytes))
  1573. {
  1574. EapTlsTrace("CertGetCertificateContextProperty failed and "
  1575. "returned 0x%x", GetLastError());
  1576. goto LDone;
  1577. }
  1578. pCryptKeyProvInfo = LocalAlloc(LPTR, dwBytes);
  1579. if (NULL == pCryptKeyProvInfo)
  1580. {
  1581. EapTlsTrace("LocalAlloc failed and returned %d", GetLastError());
  1582. goto LDone;
  1583. }
  1584. if (!CertGetCertificateContextProperty(pCertContext,
  1585. CERT_KEY_PROV_INFO_PROP_ID, pCryptKeyProvInfo, &dwBytes))
  1586. {
  1587. EapTlsTrace("CertGetCertificateContextProperty failed and "
  1588. "returned 0x%x", GetLastError());
  1589. goto LDone;
  1590. }
  1591. fRet = (PROV_RSA_SCHANNEL == pCryptKeyProvInfo->dwProvType);
  1592. if ( !fRet )
  1593. {
  1594. EapTlsTrace("Did not find a cert with a provider RSA_SCHANNEL or RSA_FULL");
  1595. }
  1596. LDone:
  1597. LocalFree(pCryptKeyProvInfo);
  1598. return(fRet);
  1599. }
  1600. /*
  1601. Returns:
  1602. NO_ERROR: iff Success
  1603. Notes:
  1604. Gets the root cert hash of the cert represented by pCertContextServer.
  1605. */
  1606. DWORD
  1607. GetRootCertHashAndNameVerifyChain(
  1608. IN PCERT_CONTEXT pCertContextServer,
  1609. OUT EAPTLS_HASH* pHash,
  1610. OUT WCHAR** ppwszName,
  1611. IN BOOL fVerifyGP,
  1612. OUT BOOL * pfRootCheckRequired
  1613. )
  1614. {
  1615. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  1616. CERT_CHAIN_PARA ChainPara;
  1617. PCERT_SIMPLE_CHAIN pSimpleChain;
  1618. PCCERT_CONTEXT pCurrentCert;
  1619. DWORD dwIndex;
  1620. BOOL fRootCertFound = FALSE;
  1621. WCHAR* pwszName = NULL;
  1622. DWORD dwErr = NO_ERROR;
  1623. CERT_CHAIN_POLICY_PARA PolicyPara;
  1624. CERT_CHAIN_POLICY_STATUS PolicyStatus;
  1625. ZeroMemory(&ChainPara, sizeof(ChainPara));
  1626. ChainPara.cbSize = sizeof(ChainPara);
  1627. *pfRootCheckRequired = TRUE;
  1628. if(!CertGetCertificateChain(
  1629. NULL,
  1630. pCertContextServer,
  1631. NULL,
  1632. pCertContextServer->hCertStore,
  1633. &ChainPara,
  1634. 0,
  1635. NULL,
  1636. &pChainContext))
  1637. {
  1638. dwErr = GetLastError();
  1639. EapTlsTrace("CertGetCertificateChain failed and returned 0x%x", dwErr);
  1640. pChainContext = NULL;
  1641. goto LDone;
  1642. }
  1643. //Get the hash and root cert name etc anyways...
  1644. pSimpleChain = pChainContext->rgpChain[0];
  1645. for (dwIndex = 0; dwIndex < pSimpleChain->cElement; dwIndex++)
  1646. {
  1647. pCurrentCert = pSimpleChain->rgpElement[dwIndex]->pCertContext;
  1648. if (CertCompareCertificateName(pCurrentCert->dwCertEncodingType,
  1649. &pCurrentCert->pCertInfo->Issuer,
  1650. &pCurrentCert->pCertInfo->Subject))
  1651. {
  1652. fRootCertFound = TRUE;
  1653. break;
  1654. }
  1655. }
  1656. if (!fRootCertFound)
  1657. {
  1658. dwErr = ERROR_NOT_FOUND;
  1659. goto LDone;
  1660. }
  1661. pHash->cbHash = MAX_HASH_SIZE;
  1662. if (!CertGetCertificateContextProperty(pCurrentCert, CERT_HASH_PROP_ID,
  1663. pHash->pbHash, &(pHash->cbHash)))
  1664. {
  1665. dwErr = GetLastError();
  1666. EapTlsTrace("CertGetCertificateContextProperty failed and "
  1667. "returned 0x%x", dwErr);
  1668. goto LDone;
  1669. }
  1670. if (!FCertToStr(pCurrentCert, 0, TRUE, &pwszName))
  1671. {
  1672. dwErr = E_FAIL;
  1673. goto LDone;
  1674. }
  1675. *ppwszName = pwszName;
  1676. pwszName = NULL;
  1677. if ( fVerifyGP )
  1678. {
  1679. EapTlsTrace( "Checking against the NTAuth store to verify the certificate chain.");
  1680. ZeroMemory( &PolicyPara, sizeof(PolicyPara) );
  1681. PolicyPara.cbSize = sizeof(PolicyPara);
  1682. PolicyPara.dwFlags = BASIC_CONSTRAINTS_CERT_CHAIN_POLICY_END_ENTITY_FLAG;
  1683. ZeroMemory( &PolicyStatus, sizeof(PolicyStatus) );
  1684. //Authnticate against the NTAuth store and see if all's cool.
  1685. if ( !CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_NT_AUTH,
  1686. pChainContext,
  1687. &PolicyPara,
  1688. &PolicyStatus
  1689. )
  1690. )
  1691. {
  1692. EapTlsTrace( "CertVerifyCertificateChainPolicy failed. Continuing with root hash matching"
  1693. "GetLastError = 0x%x.", GetLastError());
  1694. }
  1695. else
  1696. {
  1697. //
  1698. //Check to see if the policy status is good. If so,
  1699. //there is no need to check for connectoid hashes any more...
  1700. //
  1701. if ( PolicyStatus.dwError != 0 )
  1702. {
  1703. EapTlsTrace( "CertVerifyCertificateChainPolicy succeeded but returned 0x%x."
  1704. "Continuing with root hash matching.", PolicyStatus.dwError);
  1705. }
  1706. else
  1707. {
  1708. *pfRootCheckRequired = FALSE;
  1709. }
  1710. }
  1711. }
  1712. LDone:
  1713. if (pChainContext)
  1714. {
  1715. CertFreeCertificateChain(pChainContext);
  1716. }
  1717. LocalFree(pwszName);
  1718. return(dwErr);
  1719. }
  1720. /*
  1721. Returns:
  1722. NO_ERROR: iff Success
  1723. Notes:
  1724. Opens the EAP-TLS registry key, and returns the result in *phKeyEapTls. If
  1725. the function returns NO_ERROR, the caller must ultimately call
  1726. RegCloseKey(*phKeyEapTls).
  1727. */
  1728. DWORD
  1729. OpenEapTlsRegistryKey(
  1730. IN WCHAR* pwszMachineName,
  1731. IN REGSAM samDesired,
  1732. OUT HKEY* phKeyEapTls
  1733. )
  1734. {
  1735. HKEY hKeyLocalMachine = NULL;
  1736. BOOL fHKeyLocalMachineOpened = FALSE;
  1737. BOOL fHKeyEapTlsOpened = FALSE;
  1738. LONG lRet;
  1739. DWORD dwErr = NO_ERROR;
  1740. RTASSERT(NULL != phKeyEapTls);
  1741. lRet = RegConnectRegistry(pwszMachineName, HKEY_LOCAL_MACHINE,
  1742. &hKeyLocalMachine);
  1743. if (ERROR_SUCCESS != lRet)
  1744. {
  1745. dwErr = lRet;
  1746. EapTlsTrace("RegConnectRegistry(%ws) failed and returned %d",
  1747. pwszMachineName ? pwszMachineName : L"NULL", dwErr);
  1748. goto LDone;
  1749. }
  1750. fHKeyLocalMachineOpened = TRUE;
  1751. lRet = RegOpenKeyEx(hKeyLocalMachine, EAPTLS_KEY_13, 0, samDesired,
  1752. phKeyEapTls);
  1753. if (ERROR_SUCCESS != lRet)
  1754. {
  1755. dwErr = lRet;
  1756. EapTlsTrace("RegOpenKeyEx(%ws) failed and returned %d",
  1757. EAPTLS_KEY_13, dwErr);
  1758. goto LDone;
  1759. }
  1760. fHKeyEapTlsOpened = TRUE;
  1761. LDone:
  1762. if ( fHKeyEapTlsOpened
  1763. && (ERROR_SUCCESS != dwErr))
  1764. {
  1765. RegCloseKey(*phKeyEapTls);
  1766. }
  1767. if (fHKeyLocalMachineOpened)
  1768. {
  1769. RegCloseKey(hKeyLocalMachine);
  1770. }
  1771. return(dwErr);
  1772. }
  1773. /*
  1774. Returns:
  1775. NO_ERROR: iff Success
  1776. Notes:
  1777. Reads/writes the server's config data.
  1778. If fRead is TRUE, and the function returns NO_ERROR, LocalFree(*ppUserProp)
  1779. must be called.
  1780. */
  1781. DWORD
  1782. ServerConfigDataIO(
  1783. IN BOOL fRead,
  1784. IN WCHAR* pwszMachineName,
  1785. IN OUT BYTE** ppData,
  1786. IN DWORD dwNumBytes
  1787. )
  1788. {
  1789. HKEY hKeyEapTls;
  1790. EAPTLS_USER_PROPERTIES* pUserProp;
  1791. BOOL fHKeyEapTlsOpened = FALSE;
  1792. BYTE* pData = NULL;
  1793. DWORD dwSize = 0;
  1794. LONG lRet;
  1795. DWORD dwType;
  1796. DWORD dwErr = NO_ERROR;
  1797. RTASSERT(NULL != ppData);
  1798. dwErr = OpenEapTlsRegistryKey(pwszMachineName,
  1799. fRead ? KEY_READ : KEY_WRITE, &hKeyEapTls);
  1800. if (ERROR_SUCCESS != dwErr)
  1801. {
  1802. goto LDone;
  1803. }
  1804. fHKeyEapTlsOpened = TRUE;
  1805. if (fRead)
  1806. {
  1807. lRet = RegQueryValueEx(hKeyEapTls, EAPTLS_VAL_SERVER_CONFIG_DATA, NULL,
  1808. &dwType, NULL, &dwSize);
  1809. if ( (ERROR_SUCCESS != lRet)
  1810. || (REG_BINARY != dwType)
  1811. || (sizeof(EAPTLS_USER_PROPERTIES) != dwSize))
  1812. {
  1813. pData = LocalAlloc(LPTR, sizeof(EAPTLS_USER_PROPERTIES));
  1814. if (NULL == pData)
  1815. {
  1816. dwErr = GetLastError();
  1817. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  1818. goto LDone;
  1819. }
  1820. pUserProp = (EAPTLS_USER_PROPERTIES*)pData;
  1821. pUserProp->dwVersion = 0;
  1822. }
  1823. else
  1824. {
  1825. pData = LocalAlloc(LPTR, dwSize);
  1826. if (NULL == pData)
  1827. {
  1828. dwErr = GetLastError();
  1829. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  1830. goto LDone;
  1831. }
  1832. lRet = RegQueryValueEx(hKeyEapTls, EAPTLS_VAL_SERVER_CONFIG_DATA,
  1833. NULL, &dwType, pData, &dwSize);
  1834. if (ERROR_SUCCESS != lRet)
  1835. {
  1836. dwErr = lRet;
  1837. EapTlsTrace("RegQueryValueEx(%ws) failed and returned %d",
  1838. EAPTLS_VAL_SERVER_CONFIG_DATA, dwErr);
  1839. goto LDone;
  1840. }
  1841. }
  1842. pUserProp = (EAPTLS_USER_PROPERTIES*)pData;
  1843. pUserProp->dwSize = sizeof(EAPTLS_USER_PROPERTIES);
  1844. pUserProp->awszString[0] = 0;
  1845. *ppData = pData;
  1846. pData = NULL;
  1847. }
  1848. else
  1849. {
  1850. lRet = RegSetValueEx(hKeyEapTls, EAPTLS_VAL_SERVER_CONFIG_DATA, 0,
  1851. REG_BINARY, *ppData, dwNumBytes);
  1852. if (ERROR_SUCCESS != lRet)
  1853. {
  1854. dwErr = lRet;
  1855. EapTlsTrace("RegSetValueEx(%ws) failed and returned %d",
  1856. EAPTLS_VAL_SERVER_CONFIG_DATA, dwErr);
  1857. goto LDone;
  1858. }
  1859. }
  1860. LDone:
  1861. if (fHKeyEapTlsOpened)
  1862. {
  1863. RegCloseKey(hKeyEapTls);
  1864. }
  1865. LocalFree(pData);
  1866. return(dwErr);
  1867. }
  1868. /*
  1869. Returns:
  1870. VOID
  1871. Notes:
  1872. */
  1873. VOID
  1874. FreeCertList(
  1875. IN EAPTLS_CERT_NODE* pNode
  1876. )
  1877. {
  1878. while (NULL != pNode)
  1879. {
  1880. LocalFree(pNode->pwszDisplayName);
  1881. LocalFree(pNode->pwszFriendlyName);
  1882. LocalFree(pNode->pwszIssuer);
  1883. LocalFree(pNode->pwszExpiration);
  1884. pNode = pNode->pNext;
  1885. }
  1886. }
  1887. /*
  1888. Returns:
  1889. VOID
  1890. Notes:
  1891. Creates a linked list of certs from the pwszStoreName store. This list is
  1892. created in *ppCertList. *ppCert is made to point to the cert whose hash is
  1893. the same as the hash in *pHash. The linked list must eventually be freed by
  1894. calling FreeCertList.
  1895. */
  1896. VOID
  1897. CreateCertList(
  1898. IN BOOL fServer,
  1899. IN BOOL fRouter,
  1900. IN BOOL fRoot,
  1901. OUT EAPTLS_CERT_NODE** ppCertList,
  1902. OUT EAPTLS_CERT_NODE** ppCert, //This is an array of pointers...
  1903. IN DWORD dwNumHashes,
  1904. IN EAPTLS_HASH* pHash, //This is an array of hashes...
  1905. IN WCHAR* pwszStoreName
  1906. )
  1907. {
  1908. HCERTSTORE hCertStore = NULL;
  1909. EAPTLS_CERT_NODE* pCertList = NULL;
  1910. EAPTLS_CERT_NODE* pCert = NULL;
  1911. EAPTLS_CERT_NODE* pLastNode = NULL;
  1912. PCCERT_CONTEXT pCertContext;
  1913. BOOL fExitWhile;
  1914. EAPTLS_CERT_NODE* pNode;
  1915. DWORD dwErr = NO_ERROR;
  1916. DWORD dwNextSelCert = 0;
  1917. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  1918. CERT_CHAIN_FIND_BY_ISSUER_PARA FindPara;
  1919. RTASSERT(NULL != ppCertList);
  1920. hCertStore = CertOpenStore(
  1921. CERT_STORE_PROV_SYSTEM,
  1922. 0,
  1923. 0,
  1924. CERT_STORE_READONLY_FLAG |
  1925. ((fServer || fRouter) ?
  1926. CERT_SYSTEM_STORE_LOCAL_MACHINE :
  1927. CERT_SYSTEM_STORE_CURRENT_USER),
  1928. pwszStoreName);
  1929. if (NULL == hCertStore)
  1930. {
  1931. dwErr = GetLastError();
  1932. EapTlsTrace("CertOpenSystemStore failed and returned 0x%x", dwErr);
  1933. goto LDone;
  1934. }
  1935. //Changed from fRoot||fServer to fRoot only.
  1936. if (fRoot)
  1937. {
  1938. pCertList = LocalAlloc(LPTR, sizeof(EAPTLS_CERT_NODE));
  1939. if (NULL == pCertList)
  1940. {
  1941. dwErr = GetLastError();
  1942. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  1943. goto LDone;
  1944. }
  1945. pLastNode = pCertList;
  1946. }
  1947. fExitWhile = FALSE;
  1948. pCertContext = NULL;
  1949. ZeroMemory ( &FindPara, sizeof(FindPara) );
  1950. FindPara.cbSize = sizeof(FindPara);
  1951. FindPara.pszUsageIdentifier = szOID_PKIX_KP_CLIENT_AUTH;
  1952. while (!fExitWhile)
  1953. {
  1954. dwErr = NO_ERROR;
  1955. pNode = NULL;
  1956. /*
  1957. The returned pointer is freed when passed as the pPrevCertContext on a
  1958. subsequent call. Otherwise, the pointer must be freed by calling
  1959. CertFreeCertificateContext. A pPrevCertContext that is not NULL is
  1960. always freed by this function (through a call to
  1961. CertFreeCertificateContext), even for an error.
  1962. */
  1963. if ( fRoot || fRouter || fServer )
  1964. {
  1965. pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext);
  1966. if (NULL == pCertContext)
  1967. {
  1968. fExitWhile = TRUE;
  1969. goto LWhileEnd;
  1970. }
  1971. if ( !fRoot
  1972. && !FCheckUsage(pCertContext, NULL, fServer))
  1973. {
  1974. goto LWhileEnd;
  1975. }
  1976. }
  1977. else
  1978. {
  1979. //
  1980. // Use CertFindChainInStore to get to the certificate
  1981. //
  1982. pChainContext = CertFindChainInStore ( hCertStore,
  1983. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1984. 0,
  1985. CERT_CHAIN_FIND_BY_ISSUER,
  1986. &FindPara,
  1987. pChainContext
  1988. );
  1989. if ( NULL == pChainContext )
  1990. {
  1991. fExitWhile = TRUE;
  1992. goto LWhileEnd;
  1993. }
  1994. //Set the cert context to appropriate value
  1995. pCertContext = pChainContext->rgpChain[0]->rgpElement[0]->pCertContext;
  1996. }
  1997. //
  1998. //Skip if it is smart card cached certificate
  1999. //or we cannot open this csp in silent mode
  2000. //This is done iff it is not root certs and server
  2001. //
  2002. if ( !fRoot
  2003. && !fServer
  2004. && FCheckSCardCertAndCanOpenSilentContext ( pCertContext ) )
  2005. {
  2006. goto LWhileEnd;
  2007. }
  2008. if ( !FCheckTimeValidity(pCertContext ) )
  2009. {
  2010. goto LWhileEnd;
  2011. }
  2012. if ( fServer
  2013. && !FCheckCSP(pCertContext))
  2014. {
  2015. goto LWhileEnd;
  2016. }
  2017. pNode = LocalAlloc(LPTR, sizeof(EAPTLS_CERT_NODE));
  2018. if (NULL == pNode)
  2019. {
  2020. dwErr = GetLastError();
  2021. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  2022. fExitWhile = TRUE;
  2023. goto LWhileEnd;
  2024. }
  2025. FGetFriendlyName(pCertContext, &(pNode->pwszFriendlyName));
  2026. //
  2027. // If there is no UPN name, this cert will be skipped here
  2028. //
  2029. if ( !FCertToStr(pCertContext, 0, fServer || fRouter,
  2030. &(pNode->pwszDisplayName))
  2031. || !FCertToStr(pCertContext, CERT_NAME_ISSUER_FLAG, TRUE,
  2032. &(pNode->pwszIssuer))
  2033. || !FFileTimeToStr(pCertContext->pCertInfo->NotAfter,
  2034. &(pNode->pwszExpiration)))
  2035. {
  2036. goto LWhileEnd;
  2037. }
  2038. pNode->Hash.cbHash = MAX_HASH_SIZE;
  2039. if (!CertGetCertificateContextProperty(
  2040. pCertContext, CERT_HASH_PROP_ID, pNode->Hash.pbHash,
  2041. &(pNode->Hash.cbHash)))
  2042. {
  2043. dwErr = GetLastError();
  2044. EapTlsTrace("CertGetCertificateContextProperty failed and "
  2045. "returned 0x%x", dwErr);
  2046. fExitWhile = TRUE;
  2047. goto LWhileEnd;
  2048. }
  2049. #if 0
  2050. // This is not being used anywhere. So dont worry about it.
  2051. //
  2052. // Get Issuer and subject information
  2053. //
  2054. FGetIssuerOrSubject ( pCertContext,
  2055. 0,
  2056. &(pNode->pwszIssuedTo)
  2057. );
  2058. FGetIssuerOrSubject ( pCertContext,
  2059. CERT_NAME_ISSUER_FLAG,
  2060. &(pNode->pwszIssuedBy)
  2061. );
  2062. #endif
  2063. //
  2064. // Finally copy the issued date into the structure
  2065. //
  2066. CopyMemory( &pNode->IssueDate,
  2067. &pCertContext->pCertInfo->NotBefore,
  2068. sizeof(FILETIME)
  2069. );
  2070. if (NULL == pLastNode)
  2071. {
  2072. pCertList = pLastNode = pNode;
  2073. }
  2074. else
  2075. {
  2076. pLastNode->pNext = pNode;
  2077. pLastNode = pNode;
  2078. }
  2079. //Check if the hash for current node is in the list
  2080. //that has been passed to us
  2081. AddCertNodeToSelList ( pHash,
  2082. dwNumHashes,
  2083. pNode,
  2084. ppCert, //This is an array of pointers
  2085. &dwNextSelCert
  2086. );
  2087. pNode = NULL;
  2088. LWhileEnd:
  2089. if (NULL != pNode)
  2090. {
  2091. LocalFree(pNode->pwszDisplayName);
  2092. LocalFree(pNode->pwszFriendlyName);
  2093. LocalFree(pNode->pwszIssuer);
  2094. LocalFree(pNode->pwszExpiration);
  2095. LocalFree(pNode);
  2096. pNode = NULL;
  2097. }
  2098. if ( fRoot || fRouter )
  2099. {
  2100. if ( fExitWhile
  2101. && (NULL != pCertContext))
  2102. {
  2103. CertFreeCertificateContext(pCertContext);
  2104. // Always returns TRUE;
  2105. }
  2106. }
  2107. else
  2108. {
  2109. if ( fExitWhile
  2110. && ( NULL != pChainContext )
  2111. )
  2112. {
  2113. CertFreeCertificateChain(pChainContext);
  2114. }
  2115. }
  2116. }
  2117. // If we couldn't find an appropriate default cert, make the first
  2118. // cert (if there is one) the default
  2119. if (NULL == pCert)
  2120. {
  2121. pCert = pCertList;
  2122. }
  2123. LDone:
  2124. if (NO_ERROR != dwErr)
  2125. {
  2126. FreeCertList(pCertList);
  2127. }
  2128. else
  2129. {
  2130. *ppCertList = pCertList;
  2131. }
  2132. if (NULL != hCertStore)
  2133. {
  2134. if (!CertCloseStore(hCertStore, 0))
  2135. {
  2136. EapTlsTrace("CertCloseStore failed and returned 0x%x",
  2137. GetLastError());
  2138. }
  2139. }
  2140. }
  2141. DWORD
  2142. GetLocalMachineName (
  2143. OUT WCHAR ** ppLocalMachineName
  2144. )
  2145. {
  2146. DWORD dwRetCode = NO_ERROR;
  2147. WCHAR * pLocalMachineName = NULL;
  2148. DWORD dwLocalMachineNameLen = 0;
  2149. if ( !GetComputerNameEx ( ComputerNameDnsFullyQualified,
  2150. pLocalMachineName,
  2151. &dwLocalMachineNameLen
  2152. )
  2153. )
  2154. {
  2155. dwRetCode = GetLastError();
  2156. if ( ERROR_MORE_DATA != dwRetCode )
  2157. goto LDone;
  2158. dwRetCode = NO_ERROR;
  2159. }
  2160. pLocalMachineName = (WCHAR *)LocalAlloc( LPTR, (dwLocalMachineNameLen * sizeof(WCHAR)) + sizeof(WCHAR) );
  2161. if ( NULL == pLocalMachineName )
  2162. {
  2163. dwRetCode = GetLastError();
  2164. goto LDone;
  2165. }
  2166. if ( !GetComputerNameEx ( ComputerNameDnsFullyQualified,
  2167. pLocalMachineName,
  2168. &dwLocalMachineNameLen
  2169. )
  2170. )
  2171. {
  2172. dwRetCode = GetLastError();
  2173. goto LDone;
  2174. }
  2175. *ppLocalMachineName = pLocalMachineName;
  2176. pLocalMachineName = NULL;
  2177. LDone:
  2178. LocalFree(pLocalMachineName);
  2179. return dwRetCode;
  2180. }
  2181. /*
  2182. Returns:
  2183. NO_ERROR: iff Success
  2184. Notes:
  2185. If this function returns NO_ERROR,
  2186. CertFreeCertificateContext(*ppCertContext) must be called.
  2187. */
  2188. DWORD
  2189. GetDefaultClientMachineCert(
  2190. IN HCERTSTORE hCertStore,
  2191. OUT PCCERT_CONTEXT* ppCertContext
  2192. )
  2193. {
  2194. CTL_USAGE CtlUsage;
  2195. CHAR* szUsageIdentifier;
  2196. PCCERT_CONTEXT pCertContext = NULL;
  2197. EAPTLS_HASH FirstCertHash; //This is the hash of first cert
  2198. //with client auth found in the store
  2199. PCCERT_CONTEXT pCertContextPrev = NULL; //Previous context in the search
  2200. EAPTLS_HASH SelectedCertHash; //Hash of the certificate last selected
  2201. FILETIME SelectedCertNotBefore; //Not Before date of last selected
  2202. EAPTLS_HASH TempHash; //Scratch variable
  2203. WCHAR * pwszIdentity = NULL; //Machine Name in the cert
  2204. WCHAR * pLocalMachineName = NULL; //Local Machine Name
  2205. DWORD dwErr = NO_ERROR;
  2206. BOOL fGotIdentity;
  2207. CRYPT_HASH_BLOB HashBlob;
  2208. EapTlsTrace("GetDefaultClientMachineCert");
  2209. RTASSERT(NULL != ppCertContext);
  2210. ZeroMemory( &SelectedCertHash, sizeof(SelectedCertHash) );
  2211. ZeroMemory( &SelectedCertNotBefore, sizeof(SelectedCertNotBefore) );
  2212. *ppCertContext = NULL;
  2213. dwErr = GetLocalMachineName ( &pLocalMachineName );
  2214. if ( NO_ERROR != dwErr )
  2215. {
  2216. EapTlsTrace("Error getting LocalMachine Name 0x%x",
  2217. dwErr);
  2218. goto LDone;
  2219. }
  2220. szUsageIdentifier = szOID_PKIX_KP_CLIENT_AUTH;
  2221. CtlUsage.cUsageIdentifier = 1;
  2222. CtlUsage.rgpszUsageIdentifier = &szUsageIdentifier;
  2223. pCertContext = CertFindCertificateInStore(hCertStore,
  2224. X509_ASN_ENCODING,
  2225. 0,
  2226. CERT_FIND_ENHKEY_USAGE,
  2227. &CtlUsage,
  2228. NULL);
  2229. if ( NULL == pCertContext )
  2230. {
  2231. dwErr = GetLastError();
  2232. EapTlsTrace("CertFindCertificateInStore failed and returned 0x%x",
  2233. dwErr);
  2234. if ( CRYPT_E_NOT_FOUND == dwErr )
  2235. {
  2236. dwErr = ERROR_NO_EAPTLS_CERTIFICATE;
  2237. }
  2238. goto LDone;
  2239. }
  2240. FirstCertHash.cbHash = MAX_HASH_SIZE;
  2241. //
  2242. //Store the hash of first cert. In case we dont find any cert that exactly matches
  2243. //the filtering, we need to use this.
  2244. if (!CertGetCertificateContextProperty( pCertContext,
  2245. CERT_HASH_PROP_ID,
  2246. FirstCertHash.pbHash,
  2247. &(FirstCertHash.cbHash)
  2248. )
  2249. )
  2250. {
  2251. dwErr = GetLastError();
  2252. EapTlsTrace("CertGetCertificateContextProperty failed and "
  2253. "returned 0x%x", dwErr);
  2254. goto LDone;
  2255. }
  2256. do
  2257. {
  2258. //Check time validity of the cert.
  2259. if ( !FCheckTimeValidity( pCertContext) )
  2260. {
  2261. //cert expired. So skip it
  2262. EapTlsTrace("Found expired Cert. Skipping this cert.");
  2263. goto LWhileEnd;
  2264. }
  2265. fGotIdentity = FALSE;
  2266. //
  2267. //Get the subject Alt Name
  2268. //
  2269. if ( FMachineAuthCertToStr(pCertContext, &pwszIdentity) )
  2270. {
  2271. fGotIdentity = TRUE;
  2272. }
  2273. else
  2274. {
  2275. EapTlsTrace("Could not get identity from subject alt name.");
  2276. if ( FCertToStr(pCertContext, 0, TRUE, &pwszIdentity))
  2277. {
  2278. fGotIdentity = TRUE;
  2279. }
  2280. }
  2281. if ( fGotIdentity )
  2282. {
  2283. //
  2284. //Check to see if this is the same identity as this machine
  2285. //
  2286. if ( !_wcsicmp ( pwszIdentity, pLocalMachineName ) )
  2287. {
  2288. //
  2289. //Store the hash of cert.
  2290. TempHash.cbHash = MAX_HASH_SIZE;
  2291. if (!CertGetCertificateContextProperty( pCertContext,
  2292. CERT_HASH_PROP_ID,
  2293. TempHash.pbHash,
  2294. &(TempHash.cbHash)
  2295. )
  2296. )
  2297. {
  2298. EapTlsTrace("CertGetCertificateContextProperty failed and "
  2299. "returned 0x%x. Skipping this certificate", GetLastError());
  2300. goto LWhileEnd;
  2301. }
  2302. //
  2303. //Got a cert so if there is already a cert selected,
  2304. //compare the file time of this cert with the one
  2305. //already selected. If this is more recent, use this
  2306. //one.
  2307. //
  2308. if ( SelectedCertHash.cbHash )
  2309. {
  2310. if ( CompareFileTime( &SelectedCertNotBefore,
  2311. &(pCertContext->pCertInfo->NotBefore)
  2312. ) < 0
  2313. )
  2314. {
  2315. //Got a newer cert so replace the old cert with new one
  2316. CopyMemory ( &SelectedCertHash,
  2317. &TempHash,
  2318. sizeof(SelectedCertHash)
  2319. );
  2320. CopyMemory ( &SelectedCertNotBefore,
  2321. &(pCertContext->pCertInfo->NotBefore),
  2322. sizeof( SelectedCertNotBefore )
  2323. );
  2324. }
  2325. }
  2326. else
  2327. {
  2328. //
  2329. //This is the first cert. So copy over the hash and
  2330. //file time.
  2331. CopyMemory ( &SelectedCertHash,
  2332. &TempHash,
  2333. sizeof(SelectedCertHash)
  2334. );
  2335. CopyMemory ( &SelectedCertNotBefore,
  2336. &(pCertContext->pCertInfo->NotBefore),
  2337. sizeof( SelectedCertNotBefore )
  2338. );
  2339. }
  2340. }
  2341. else
  2342. {
  2343. EapTlsTrace("Could not get identity from the cert. skipping this cert.");
  2344. }
  2345. }
  2346. else
  2347. {
  2348. EapTlsTrace("Could not get identity from the cert. skipping this cert.");
  2349. }
  2350. LWhileEnd:
  2351. pCertContextPrev = pCertContext;
  2352. if ( pwszIdentity )
  2353. {
  2354. LocalFree ( pwszIdentity );
  2355. pwszIdentity = NULL;
  2356. }
  2357. //Get the next certificate.
  2358. pCertContext = CertFindCertificateInStore(hCertStore,
  2359. X509_ASN_ENCODING,
  2360. 0,
  2361. CERT_FIND_ENHKEY_USAGE,
  2362. &CtlUsage,
  2363. pCertContextPrev );
  2364. }while ( pCertContext );
  2365. //
  2366. //Now that we have enumerated all the certs,
  2367. //check to see if we have a selected cert. If no selected
  2368. //cert is present, send back the first cert.
  2369. //
  2370. if ( SelectedCertHash.cbHash )
  2371. {
  2372. EapTlsTrace("Found Machine Cert based on machinename, client auth, time validity.");
  2373. HashBlob.cbData = SelectedCertHash.cbHash;
  2374. HashBlob.pbData = SelectedCertHash.pbHash;
  2375. }
  2376. else
  2377. {
  2378. EapTlsTrace("Did not find Machine Cert based on the given machinename, client auth, time validity. Using the first cert with Client Auth OID.");
  2379. HashBlob.cbData = FirstCertHash.cbHash;
  2380. HashBlob.pbData = FirstCertHash.pbHash;
  2381. }
  2382. *ppCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING,
  2383. 0, CERT_FIND_HASH, &HashBlob, NULL);
  2384. if (NULL == *ppCertContext)
  2385. {
  2386. dwErr = GetLastError();
  2387. EapTlsTrace("CertFindCertificateInStore failed with 0x%x.", dwErr);
  2388. if ( CRYPT_E_NOT_FOUND == dwErr )
  2389. {
  2390. dwErr = ERROR_NO_EAPTLS_CERTIFICATE;
  2391. }
  2392. }
  2393. LDone:
  2394. LocalFree (pLocalMachineName);
  2395. LocalFree (pwszIdentity);
  2396. if ( NO_ERROR != dwErr )
  2397. {
  2398. if ( pCertContext )
  2399. {
  2400. CertFreeCertificateContext( pCertContext );
  2401. }
  2402. }
  2403. EapTlsTrace("GetDefaultClientMachineCert done.");
  2404. return(dwErr);
  2405. }
  2406. /*
  2407. Returns:
  2408. NO_ERROR: iff Success
  2409. Notes:
  2410. If this function returns NO_ERROR,
  2411. CertFreeCertificateContext(*ppCertContext) must be called.
  2412. */
  2413. DWORD
  2414. GetDefaultMachineCert(
  2415. IN HCERTSTORE hCertStore,
  2416. OUT PCCERT_CONTEXT* ppCertContext
  2417. )
  2418. {
  2419. CTL_USAGE CtlUsage;
  2420. CHAR* szUsageIdentifier;
  2421. PCCERT_CONTEXT pCertContext;
  2422. DWORD dwErr = NO_ERROR;
  2423. EapTlsTrace("GetDefaultMachineCert");
  2424. RTASSERT(NULL != ppCertContext);
  2425. *ppCertContext = NULL;
  2426. szUsageIdentifier = szOID_PKIX_KP_SERVER_AUTH;
  2427. CtlUsage.cUsageIdentifier = 1;
  2428. CtlUsage.rgpszUsageIdentifier = &szUsageIdentifier;
  2429. pCertContext = CertFindCertificateInStore(hCertStore,
  2430. X509_ASN_ENCODING, 0, CERT_FIND_ENHKEY_USAGE,
  2431. &CtlUsage, NULL);
  2432. if (NULL == pCertContext)
  2433. {
  2434. dwErr = GetLastError();
  2435. EapTlsTrace("CertFindCertificateInStore failed and returned 0x%x",
  2436. dwErr);
  2437. goto LDone;
  2438. }
  2439. *ppCertContext = pCertContext;
  2440. LDone:
  2441. return(dwErr);
  2442. }
  2443. /*
  2444. Returns:
  2445. Notes:
  2446. Stolen from \private\windows\gina\msgina\wlsec.c
  2447. */
  2448. VOID
  2449. RevealPassword(
  2450. IN UNICODE_STRING* pHiddenPassword
  2451. )
  2452. {
  2453. SECURITY_SEED_AND_LENGTH* SeedAndLength;
  2454. UCHAR Seed;
  2455. SeedAndLength = (SECURITY_SEED_AND_LENGTH*)&pHiddenPassword->Length;
  2456. Seed = SeedAndLength->Seed;
  2457. SeedAndLength->Seed = 0;
  2458. RtlRunDecodeUnicodeString(Seed, pHiddenPassword);
  2459. }
  2460. DWORD GetMBytePIN ( WCHAR * pwszPIN, CHAR ** ppszPIN )
  2461. {
  2462. DWORD count = 0;
  2463. CHAR * pszPin = NULL;
  2464. DWORD dwErr = NO_ERROR;
  2465. count = WideCharToMultiByte(
  2466. CP_UTF8,
  2467. 0,
  2468. pwszPIN,
  2469. -1,
  2470. NULL,
  2471. 0,
  2472. NULL,
  2473. NULL);
  2474. if (0 == count)
  2475. {
  2476. dwErr = GetLastError();
  2477. EapTlsTrace("WideCharToMultiByte failed: %d", dwErr);
  2478. goto LDone;
  2479. }
  2480. pszPin = LocalAlloc(LPTR, count);
  2481. if (NULL == pszPin)
  2482. {
  2483. dwErr = GetLastError();
  2484. EapTlsTrace("LocalAlloc failed: 0x%x", dwErr);
  2485. goto LDone;
  2486. }
  2487. count = WideCharToMultiByte(
  2488. CP_UTF8,
  2489. 0,
  2490. pwszPIN,
  2491. -1,
  2492. pszPin,
  2493. count,
  2494. NULL,
  2495. NULL);
  2496. if (0 == count)
  2497. {
  2498. dwErr = GetLastError();
  2499. EapTlsTrace("WideCharToMultiByte failed: %d", dwErr);
  2500. goto LDone;
  2501. }
  2502. *ppszPIN = pszPin;
  2503. LDone:
  2504. if ( NO_ERROR != dwErr )
  2505. {
  2506. if ( pszPin )
  2507. LocalFree(pszPin);
  2508. }
  2509. return dwErr;
  2510. }
  2511. /*
  2512. Returns:
  2513. NO_ERROR: iff Success
  2514. Notes:
  2515. */
  2516. DWORD
  2517. GetCertFromLogonInfo(
  2518. IN BYTE* pUserDataIn,
  2519. IN DWORD dwSizeOfUserDataIn,
  2520. OUT PCCERT_CONTEXT* ppCertContext
  2521. )
  2522. {
  2523. EAPLOGONINFO* pEapLogonInfo = (EAPLOGONINFO*)pUserDataIn;
  2524. BYTE* pbLogonInfo = NULL;
  2525. BYTE* pbPinInfo;
  2526. WCHAR* wszPassword = NULL;
  2527. CHAR* pszPIN = NULL; //Multibyte Version of the PIN
  2528. UNICODE_STRING UnicodeString;
  2529. PCCERT_CONTEXT pCertContext = NULL;
  2530. BOOL fInitialized = FALSE;
  2531. NTSTATUS Status;
  2532. DWORD dwErr = NO_ERROR;
  2533. CERT_KEY_CONTEXT stckContext;
  2534. DWORD cbstckContext= sizeof(CERT_KEY_CONTEXT);
  2535. EapTlsTrace("GetCertFromLogonInfo");
  2536. RTASSERT(NULL != ppCertContext);
  2537. *ppCertContext = NULL;
  2538. if ( 0 == pEapLogonInfo->dwLogonInfoSize
  2539. || 0 == pEapLogonInfo->dwPINInfoSize
  2540. || 0 == dwSizeOfUserDataIn)
  2541. {
  2542. dwErr = E_FAIL;
  2543. goto LDone;
  2544. }
  2545. pbLogonInfo = LocalAlloc(LPTR, pEapLogonInfo->dwLogonInfoSize);
  2546. if (NULL == pbLogonInfo)
  2547. {
  2548. dwErr = GetLastError();
  2549. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  2550. goto LDone;
  2551. }
  2552. CopyMemory(pbLogonInfo,
  2553. (BYTE*)pEapLogonInfo + pEapLogonInfo->dwOffsetLogonInfo,
  2554. pEapLogonInfo->dwLogonInfoSize);
  2555. pbPinInfo = (BYTE*)pEapLogonInfo + pEapLogonInfo->dwOffsetPINInfo;
  2556. wszPassword = LocalAlloc(LPTR, pEapLogonInfo->dwPINInfoSize);
  2557. if (NULL == wszPassword)
  2558. {
  2559. dwErr = GetLastError();
  2560. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  2561. goto LDone;
  2562. }
  2563. CopyMemory(wszPassword, pbPinInfo + 2 * sizeof(USHORT),
  2564. pEapLogonInfo->dwPINInfoSize - 2 * sizeof(USHORT));
  2565. UnicodeString.Length = *((USHORT*)pbPinInfo);
  2566. UnicodeString.MaximumLength = *((USHORT*)pbPinInfo + 1);
  2567. UnicodeString.Buffer = wszPassword;
  2568. Status = ScHelperInitializeContext(pbLogonInfo,
  2569. pEapLogonInfo->dwLogonInfoSize);
  2570. if (STATUS_SUCCESS != Status)
  2571. {
  2572. dwErr = Status;
  2573. EapTlsTrace("ScHelperInitializeContext failed and returned 0x%x",
  2574. dwErr);
  2575. goto LDone;
  2576. }
  2577. fInitialized = TRUE;
  2578. RevealPassword(&UnicodeString);
  2579. Status = ScHelperGetCertFromLogonInfo(pbLogonInfo, &UnicodeString,
  2580. &pCertContext);
  2581. if (STATUS_SUCCESS != Status)
  2582. {
  2583. dwErr = Status;
  2584. EapTlsTrace("ScHelperGetCertFromLogonInfo failed and returned 0x%x",
  2585. dwErr);
  2586. goto LDone;
  2587. }
  2588. //BUGID: 260728 - ScHelperGetCertFromLogonInfo does not associate the PIN
  2589. // with certificate context. Hence the following lines of code are needed
  2590. // to do the needful.
  2591. if ( ! CertGetCertificateContextProperty ( pCertContext,
  2592. CERT_KEY_CONTEXT_PROP_ID,
  2593. &stckContext,
  2594. &cbstckContext
  2595. )
  2596. )
  2597. {
  2598. dwErr = Status = GetLastError();
  2599. EapTlsTrace ("CertGetCertificateContextProperty failed and returned 0x%x",
  2600. dwErr
  2601. );
  2602. goto LDone;
  2603. }
  2604. dwErr = GetMBytePIN ( wszPassword, &pszPIN );
  2605. if ( dwErr != NO_ERROR )
  2606. {
  2607. goto LDone;
  2608. }
  2609. if (!CryptSetProvParam(
  2610. stckContext.hCryptProv,
  2611. PP_KEYEXCHANGE_PIN,
  2612. pszPIN,
  2613. 0))
  2614. {
  2615. dwErr = GetLastError();
  2616. EapTlsTrace("CryptSetProvParam failed: 0x%x", dwErr);
  2617. ZeroMemory(pszPIN, strlen(pszPIN));
  2618. goto LDone;
  2619. }
  2620. // Zero the entire allocated buffer.
  2621. ZeroMemory(wszPassword, pEapLogonInfo->dwPINInfoSize);
  2622. ZeroMemory(pszPIN, strlen(pszPIN));
  2623. *ppCertContext = pCertContext;
  2624. pCertContext = NULL;
  2625. LDone:
  2626. if (fInitialized)
  2627. {
  2628. ScHelperRelease(pbLogonInfo);
  2629. }
  2630. if (NULL != pCertContext)
  2631. {
  2632. CertFreeCertificateContext(pCertContext);
  2633. // Always returns TRUE;
  2634. }
  2635. LocalFree(wszPassword);
  2636. LocalFree(pbLogonInfo);
  2637. if ( pszPIN )
  2638. LocalFree ( pszPIN );
  2639. return(dwErr);
  2640. }
  2641. /*
  2642. Returns:
  2643. NO_ERROR: iff Success
  2644. Notes:
  2645. If this function returns TRUE, LocalFree(*ppwszIdentity) must be called.
  2646. */
  2647. DWORD
  2648. GetIdentityFromLogonInfo(
  2649. IN BYTE* pUserDataIn,
  2650. IN DWORD dwSizeOfUserDataIn,
  2651. OUT WCHAR** ppwszIdentity
  2652. )
  2653. {
  2654. WCHAR* pwszIdentity = NULL;
  2655. PCCERT_CONTEXT pCertContext = NULL;
  2656. DWORD dwErr = NO_ERROR;
  2657. RTASSERT(NULL != pUserDataIn);
  2658. RTASSERT(NULL != ppwszIdentity);
  2659. *ppwszIdentity = NULL;
  2660. dwErr = GetCertFromLogonInfo(pUserDataIn, dwSizeOfUserDataIn,
  2661. &pCertContext);
  2662. if (NO_ERROR != dwErr)
  2663. {
  2664. goto LDone;
  2665. }
  2666. if (FCertToStr(pCertContext, 0, FALSE, &pwszIdentity))
  2667. {
  2668. EapTlsTrace("(logon info) The name in the certificate is: %ws",
  2669. pwszIdentity);
  2670. *ppwszIdentity = pwszIdentity;
  2671. pwszIdentity = NULL;
  2672. }
  2673. LDone:
  2674. LocalFree(pwszIdentity);
  2675. if (NULL != pCertContext)
  2676. {
  2677. CertFreeCertificateContext(pCertContext);
  2678. // Always returns TRUE;
  2679. }
  2680. return(dwErr);
  2681. }
  2682. /*
  2683. Returns:
  2684. NO_ERROR: iff Success
  2685. Notes:
  2686. There are two types of structures that can come in:
  2687. 1. Version 0 structure which comes in as a a part of
  2688. CM profile created on w2k or as a part of a
  2689. connectoid that gor upgraded from w2k
  2690. We change the data structure to new v1
  2691. data structure here
  2692. 2. Get a version 1 structure and it is all cool.
  2693. Note that the first x bytes of version 1 data structure
  2694. are exactly the same as version 0.
  2695. */
  2696. DWORD
  2697. ReadConnectionData(
  2698. IN BOOL fWireless,
  2699. IN BYTE* pConnectionDataIn,
  2700. IN DWORD dwSizeOfConnectionDataIn,
  2701. OUT EAPTLS_CONN_PROPERTIES** ppConnProp
  2702. )
  2703. {
  2704. DWORD dwErr = NO_ERROR;
  2705. EAPTLS_CONN_PROPERTIES* pConnProp = NULL;
  2706. EAPTLS_CONN_PROPERTIES* pConnPropv1 = NULL;
  2707. RTASSERT(NULL != ppConnProp);
  2708. if ( dwSizeOfConnectionDataIn < sizeof(EAPTLS_CONN_PROPERTIES) )
  2709. {
  2710. pConnProp = LocalAlloc(LPTR, sizeof(EAPTLS_CONN_PROPERTIES) + sizeof(EAPTLS_CONN_PROPERTIES_V1_EXTRA));
  2711. if (NULL == pConnProp)
  2712. {
  2713. dwErr = GetLastError();
  2714. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  2715. goto LDone;
  2716. }
  2717. //This is a new structure
  2718. pConnProp->dwVersion = 2;
  2719. pConnProp->dwSize = sizeof(EAPTLS_CONN_PROPERTIES);
  2720. if ( fWireless )
  2721. {
  2722. //
  2723. // Set the defaults appropriately
  2724. //
  2725. pConnProp->fFlags |= EAPTLS_CONN_FLAG_REGISTRY;
  2726. pConnProp->fFlags |= EAPTLS_CONN_FLAG_SIMPLE_CERT_SEL;
  2727. pConnProp->fFlags |= EAPTLS_CONN_FLAG_NO_VALIDATE_NAME;
  2728. }
  2729. }
  2730. else
  2731. {
  2732. RTASSERT(NULL != pConnectionDataIn);
  2733. //
  2734. //Check to see if this is a version 0 structure
  2735. //If it is a version 0 structure then we migrate it to version1
  2736. //
  2737. pConnProp = LocalAlloc(LPTR, dwSizeOfConnectionDataIn);
  2738. if (NULL == pConnProp)
  2739. {
  2740. dwErr = GetLastError();
  2741. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  2742. goto LDone;
  2743. }
  2744. // If the user has mucked with the phonebook, we mustn't be affected.
  2745. // The size must be correct.
  2746. CopyMemory(pConnProp, pConnectionDataIn, dwSizeOfConnectionDataIn);
  2747. pConnProp->dwSize = dwSizeOfConnectionDataIn;
  2748. //
  2749. // The Unicode string must be NULL terminated.
  2750. //
  2751. /*
  2752. ((BYTE*)pConnProp)[dwSizeOfConnectionDataIn - 2] = 0;
  2753. ((BYTE*)pConnProp)[dwSizeOfConnectionDataIn - 1] = 0;
  2754. */
  2755. pConnPropv1 = LocalAlloc(LPTR,
  2756. dwSizeOfConnectionDataIn +
  2757. sizeof(EAPTLS_CONN_PROPERTIES_V1_EXTRA)
  2758. );
  2759. if ( NULL == pConnPropv1 )
  2760. {
  2761. dwErr = GetLastError();
  2762. EapTlsTrace("LocalAlloc failed while allocating v1 structure and returned %d", dwErr );
  2763. goto LDone;
  2764. }
  2765. CopyMemory ( pConnPropv1, pConnProp, dwSizeOfConnectionDataIn);
  2766. //
  2767. //Check to see if the original struct has hash set
  2768. //
  2769. /*
  2770. if ( pConnProp->Hash.cbHash )
  2771. {
  2772. ConnPropSetNumHashes( pConnPropv1, 1 );
  2773. }
  2774. */
  2775. if ( 2 != pConnPropv1->dwVersion )
  2776. {
  2777. if ( pConnPropv1->fFlags & EAPTLS_CONN_FLAG_REGISTRY )
  2778. {
  2779. pConnPropv1->fFlags |= EAPTLS_CONN_FLAG_SIMPLE_CERT_SEL;
  2780. }
  2781. pConnPropv1->dwVersion = 2;
  2782. }
  2783. LocalFree ( pConnProp );
  2784. pConnProp = pConnPropv1;
  2785. pConnPropv1 = NULL;
  2786. }
  2787. *ppConnProp = pConnProp;
  2788. pConnProp = NULL;
  2789. LDone:
  2790. LocalFree(pConnProp);
  2791. LocalFree(pConnPropv1);
  2792. return(dwErr);
  2793. }
  2794. /*
  2795. Returns:
  2796. NO_ERROR: iff Success
  2797. Notes:
  2798. */
  2799. DWORD
  2800. ReadUserData(
  2801. IN BYTE* pUserDataIn,
  2802. IN DWORD dwSizeOfUserDataIn,
  2803. OUT EAPTLS_USER_PROPERTIES** ppUserProp
  2804. )
  2805. {
  2806. DWORD dwErr = NO_ERROR;
  2807. EAPTLS_USER_PROPERTIES* pUserProp = NULL;
  2808. RTASSERT(NULL != ppUserProp);
  2809. if (dwSizeOfUserDataIn < sizeof(EAPTLS_USER_PROPERTIES))
  2810. {
  2811. pUserProp = LocalAlloc(LPTR, sizeof(EAPTLS_USER_PROPERTIES));
  2812. if (NULL == pUserProp)
  2813. {
  2814. dwErr = GetLastError();
  2815. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  2816. goto LDone;
  2817. }
  2818. pUserProp->dwVersion = 0;
  2819. pUserProp->dwSize = sizeof(EAPTLS_USER_PROPERTIES);
  2820. pUserProp->pwszDiffUser = pUserProp->awszString;
  2821. pUserProp->dwPinOffset = 0;
  2822. pUserProp->pwszPin = pUserProp->awszString + pUserProp->dwPinOffset;
  2823. }
  2824. else
  2825. {
  2826. RTASSERT(NULL != pUserDataIn);
  2827. pUserProp = LocalAlloc(LPTR, dwSizeOfUserDataIn);
  2828. if (NULL == pUserProp)
  2829. {
  2830. dwErr = GetLastError();
  2831. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  2832. goto LDone;
  2833. }
  2834. CopyMemory(pUserProp, pUserDataIn, dwSizeOfUserDataIn);
  2835. // If someone has mucked with the registry, we mustn't
  2836. // be affected.
  2837. pUserProp->dwSize = dwSizeOfUserDataIn;
  2838. pUserProp->pwszDiffUser = pUserProp->awszString;
  2839. pUserProp->pwszPin = pUserProp->awszString + pUserProp->dwPinOffset;
  2840. }
  2841. *ppUserProp = pUserProp;
  2842. pUserProp = NULL;
  2843. LDone:
  2844. LocalFree(pUserProp);
  2845. return(dwErr);
  2846. }
  2847. /*
  2848. Returns:
  2849. NO_ERROR: iff Success
  2850. Notes:
  2851. */
  2852. DWORD
  2853. AllocUserDataWithNewIdentity(
  2854. IN EAPTLS_USER_PROPERTIES* pUserProp,
  2855. IN WCHAR* pwszIdentity,
  2856. OUT EAPTLS_USER_PROPERTIES** ppUserProp
  2857. )
  2858. {
  2859. DWORD dwNumChars;
  2860. EAPTLS_USER_PROPERTIES* pUserPropTemp = NULL;
  2861. DWORD dwSize;
  2862. DWORD dwErr = NO_ERROR;
  2863. *ppUserProp = NULL;
  2864. dwNumChars = wcslen(pwszIdentity);
  2865. dwSize = sizeof(EAPTLS_USER_PROPERTIES) +
  2866. (dwNumChars + wcslen(pUserProp->pwszPin) + 1) * sizeof(WCHAR);
  2867. pUserPropTemp = LocalAlloc(LPTR, dwSize);
  2868. if (NULL == pUserPropTemp)
  2869. {
  2870. dwErr = GetLastError();
  2871. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  2872. goto LDone;
  2873. }
  2874. CopyMemory(pUserPropTemp, pUserProp, sizeof(EAPTLS_USER_PROPERTIES));
  2875. pUserPropTemp->dwSize = dwSize;
  2876. pUserPropTemp->pwszDiffUser = pUserPropTemp->awszString;
  2877. wcscpy(pUserPropTemp->pwszDiffUser, pwszIdentity);
  2878. pUserPropTemp->dwPinOffset = dwNumChars + 1;
  2879. pUserPropTemp->pwszPin = pUserPropTemp->awszString +
  2880. pUserPropTemp->dwPinOffset;
  2881. wcscpy(pUserPropTemp->pwszPin, pUserProp->pwszPin);
  2882. *ppUserProp = pUserPropTemp;
  2883. pUserPropTemp = NULL;
  2884. ZeroMemory(pUserProp, pUserProp->dwSize);
  2885. LDone:
  2886. LocalFree(pUserPropTemp);
  2887. return(dwErr);
  2888. }
  2889. /*
  2890. Returns:
  2891. NO_ERROR: iff Success
  2892. Notes:
  2893. */
  2894. DWORD
  2895. AllocUserDataWithNewPin(
  2896. IN EAPTLS_USER_PROPERTIES* pUserProp,
  2897. IN PBYTE pbPin,
  2898. IN DWORD cbPin,
  2899. OUT EAPTLS_USER_PROPERTIES** ppUserProp
  2900. )
  2901. {
  2902. DWORD dwNumChars;
  2903. EAPTLS_USER_PROPERTIES* pUserPropTemp = NULL;
  2904. DWORD dwSize;
  2905. DWORD dwErr = NO_ERROR;
  2906. *ppUserProp = NULL;
  2907. dwNumChars = wcslen(pUserProp->pwszDiffUser);
  2908. dwSize = sizeof(EAPTLS_USER_PROPERTIES) +
  2909. (dwNumChars + 1 ) * sizeof(WCHAR) + cbPin;
  2910. pUserPropTemp = LocalAlloc(LPTR, dwSize);
  2911. if (NULL == pUserPropTemp)
  2912. {
  2913. dwErr = GetLastError();
  2914. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  2915. goto LDone;
  2916. }
  2917. CopyMemory(pUserPropTemp, pUserProp, sizeof(EAPTLS_USER_PROPERTIES));
  2918. pUserPropTemp->dwSize = dwSize;
  2919. pUserPropTemp->pwszDiffUser = pUserPropTemp->awszString;
  2920. wcscpy(pUserPropTemp->pwszDiffUser, pUserProp->pwszDiffUser);
  2921. pUserPropTemp->dwPinOffset = dwNumChars + 1;
  2922. pUserPropTemp->pwszPin = pUserPropTemp->awszString +
  2923. pUserPropTemp->dwPinOffset;
  2924. CopyMemory(pUserPropTemp->pwszPin, pbPin, cbPin);
  2925. *ppUserProp = pUserPropTemp;
  2926. pUserPropTemp = NULL;
  2927. RtlSecureZeroMemory(pUserProp, pUserProp->dwSize);
  2928. LDone:
  2929. LocalFree(pUserPropTemp);
  2930. return(dwErr);
  2931. }
  2932. /*
  2933. Returns:
  2934. Notes:
  2935. String resource message loader routine. Returns the address of a string
  2936. corresponding to string resource dwStringId or NULL if error. It is caller's
  2937. responsibility to LocalFree the returned string.
  2938. */
  2939. WCHAR*
  2940. WszFromId(
  2941. IN HINSTANCE hInstance,
  2942. IN DWORD dwStringId
  2943. )
  2944. {
  2945. WCHAR* wszBuf = NULL;
  2946. int cchBuf = 256;
  2947. int cchGot;
  2948. for (;;)
  2949. {
  2950. wszBuf = LocalAlloc(LPTR, cchBuf * sizeof(WCHAR));
  2951. if (NULL == wszBuf)
  2952. {
  2953. break;
  2954. }
  2955. /*
  2956. LoadString wants to deal with character-counts rather than
  2957. byte-counts...weird. Oh, and if you're thinking I could FindResource
  2958. then SizeofResource to figure out the string size, be advised it
  2959. doesn't work. From perusing the LoadString source, it appears the
  2960. RT_STRING resource type requests a segment of 16 strings not an
  2961. individual string.
  2962. */
  2963. cchGot = LoadStringW(hInstance, (UINT)dwStringId, wszBuf, cchBuf);
  2964. if (cchGot < cchBuf - 1)
  2965. {
  2966. // Good, got the whole string.
  2967. break;
  2968. }
  2969. // Uh oh, LoadStringW filled the buffer entirely which could mean the
  2970. // string was truncated. Try again with a larger buffer to be sure it
  2971. // wasn't.
  2972. LocalFree(wszBuf);
  2973. cchBuf += 256;
  2974. }
  2975. return(wszBuf);
  2976. }
  2977. /*
  2978. Following functions are required around the
  2979. messy CONN_PROP structure to support v1/v0 etc.
  2980. This is really bad.
  2981. All the functions assume that version 1.0 format
  2982. is passed in.
  2983. */
  2984. EAPTLS_CONN_PROPERTIES_V1_EXTRA UNALIGNED * ConnPropGetExtraPointer (EAPTLS_CONN_PROPERTIES * pConnProp)
  2985. {
  2986. return (EAPTLS_CONN_PROPERTIES_V1_EXTRA UNALIGNED *)
  2987. ( pConnProp->awszServerName + wcslen(pConnProp->awszServerName) + 1);
  2988. }
  2989. DWORD ConnPropGetNumHashes(EAPTLS_CONN_PROPERTIES * pConnProp )
  2990. {
  2991. EAPTLS_CONN_PROPERTIES_V1_EXTRA UNALIGNED * pExtra = ConnPropGetExtraPointer(pConnProp);
  2992. return pExtra->dwNumHashes;
  2993. }
  2994. void ConnPropSetNumHashes(EAPTLS_CONN_PROPERTIES * pConnProp, DWORD dwNumHashes )
  2995. {
  2996. EAPTLS_CONN_PROPERTIES_V1_EXTRA UNALIGNED * pExtra = ConnPropGetExtraPointer(pConnProp);
  2997. pExtra->dwNumHashes = dwNumHashes;
  2998. return;
  2999. }
  3000. DWORD ConnPropGetV1Struct ( EAPTLS_CONN_PROPERTIES * pConnProp, EAPTLS_CONN_PROPERTIES_V1 ** ppConnPropv1 )
  3001. {
  3002. DWORD dwRetCode = NO_ERROR;
  3003. EAPTLS_CONN_PROPERTIES_V1 * pConnPropv1 = NULL;
  3004. EAPTLS_CONN_PROPERTIES_V1_EXTRA UNALIGNED * pExtra = ConnPropGetExtraPointer(pConnProp);
  3005. //
  3006. //This function assumes that the struct that comes in is at
  3007. //version 1. Which means at least sizeof(EAPTLS_CONN_PROPERTIES) +
  3008. //EAPTLS_CONN_PROPERTIES_V1_EXTRA in size.
  3009. //
  3010. //
  3011. //First get the amount of memory required to be allocated
  3012. //
  3013. pConnPropv1 = LocalAlloc ( LPTR,
  3014. sizeof( EAPTLS_CONN_PROPERTIES_V1 ) + //sizeof the basic struct
  3015. pExtra->dwNumHashes * sizeof( EAPTLS_HASH ) + //num hashes
  3016. wcslen( pConnProp->awszServerName ) * sizeof(WCHAR) + sizeof(WCHAR)//sizeof the string
  3017. );
  3018. if ( NULL == pConnPropv1 )
  3019. {
  3020. dwRetCode = GetLastError();
  3021. goto LDone;
  3022. }
  3023. //
  3024. //Convert the structure
  3025. //
  3026. if ( pConnProp->dwVersion <= 1 )
  3027. pConnPropv1->dwVersion = 1;
  3028. else
  3029. pConnPropv1->dwVersion = 2;
  3030. pConnPropv1->dwSize = sizeof( EAPTLS_CONN_PROPERTIES_V1 ) +
  3031. pExtra->dwNumHashes * sizeof( EAPTLS_HASH ) +
  3032. wcslen( pConnProp->awszServerName ) * sizeof(WCHAR) + sizeof(WCHAR);
  3033. pConnPropv1->fFlags = pConnProp->fFlags;
  3034. pConnPropv1->dwNumHashes = pExtra->dwNumHashes;
  3035. if ( pExtra->dwNumHashes )
  3036. {
  3037. CopyMemory( pConnPropv1->bData, &(pConnProp->Hash), sizeof(EAPTLS_HASH) );
  3038. if ( pExtra->dwNumHashes >1 )
  3039. {
  3040. CopyMemory ( pConnPropv1->bData + sizeof(EAPTLS_HASH),
  3041. pExtra->bData,
  3042. (pExtra->dwNumHashes -1 ) * sizeof(EAPTLS_HASH)
  3043. );
  3044. }
  3045. }
  3046. //Copy the server name
  3047. wcscpy( (WCHAR *)( pConnPropv1->bData + (pExtra->dwNumHashes * sizeof(EAPTLS_HASH) ) ),
  3048. pConnProp->awszServerName
  3049. );
  3050. *ppConnPropv1 = pConnPropv1;
  3051. pConnPropv1 = NULL;
  3052. LDone:
  3053. LocalFree(pConnPropv1);
  3054. return dwRetCode;
  3055. }
  3056. DWORD ConnPropGetV0Struct ( EAPTLS_CONN_PROPERTIES_V1 * pConnPropv1, EAPTLS_CONN_PROPERTIES ** ppConnProp )
  3057. {
  3058. DWORD dwRetCode = NO_ERROR;
  3059. EAPTLS_CONN_PROPERTIES * pConnProp = NULL;
  3060. DWORD dwSize = 0;
  3061. EAPTLS_CONN_PROPERTIES_V1_EXTRA UNALIGNED * pExtrav1 = NULL;
  3062. //
  3063. //First calulate the amount of memory to allocate
  3064. //
  3065. dwSize = sizeof(EAPTLS_CONN_PROPERTIES) +
  3066. (pConnPropv1->dwNumHashes?( pConnPropv1->dwNumHashes - 1 ) * sizeof(EAPTLS_HASH):0) +
  3067. ( wcslen( (LPWSTR) (pConnPropv1->bData + (pConnPropv1->dwNumHashes * sizeof(EAPTLS_HASH)) ) ) * sizeof(WCHAR) ) + sizeof(WCHAR);
  3068. pConnProp = LocalAlloc ( LPTR, dwSize );
  3069. if ( NULL == pConnProp )
  3070. {
  3071. dwRetCode = GetLastError();
  3072. goto LDone;
  3073. }
  3074. if ( pConnPropv1->dwVersion <= 1 )
  3075. pConnProp->dwVersion = 1;
  3076. else
  3077. pConnProp->dwVersion = 2;
  3078. pConnProp->dwSize = dwSize;
  3079. pConnProp->fFlags = pConnPropv1->fFlags;
  3080. if ( pConnPropv1->dwNumHashes > 0 )
  3081. {
  3082. CopyMemory( &(pConnProp->Hash), pConnPropv1->bData, sizeof(EAPTLS_HASH));
  3083. }
  3084. if ( pConnPropv1->bData )
  3085. {
  3086. wcscpy ( pConnProp->awszServerName,
  3087. (LPWSTR )(pConnPropv1->bData + sizeof( EAPTLS_HASH ) * pConnPropv1->dwNumHashes)
  3088. );
  3089. }
  3090. pExtrav1 = (EAPTLS_CONN_PROPERTIES_V1_EXTRA UNALIGNED *)(pConnProp->awszServerName +
  3091. wcslen( pConnProp->awszServerName) + 1);
  3092. pExtrav1->dwNumHashes = pConnPropv1->dwNumHashes;
  3093. if ( pExtrav1->dwNumHashes > 1 )
  3094. {
  3095. CopyMemory( pExtrav1->bData,
  3096. pConnPropv1->bData + sizeof(EAPTLS_HASH),
  3097. ( pConnPropv1->dwNumHashes - 1 ) * sizeof(EAPTLS_HASH)
  3098. );
  3099. }
  3100. *ppConnProp = pConnProp;
  3101. pConnProp = NULL;
  3102. LDone:
  3103. LocalFree(pConnProp);
  3104. return dwRetCode;
  3105. }
  3106. void ShowCertDetails ( HWND hWnd, HCERTSTORE hStore, PCCERT_CONTEXT pCertContext)
  3107. {
  3108. CRYPTUI_VIEWCERTIFICATE_STRUCT vcs;
  3109. BOOL fPropertiesChanged = FALSE;
  3110. ZeroMemory (&vcs, sizeof (vcs));
  3111. vcs.dwSize = sizeof (vcs);
  3112. vcs.hwndParent = hWnd;
  3113. vcs.pCertContext = pCertContext;
  3114. vcs.cStores = 1;
  3115. vcs.rghStores = &hStore;
  3116. vcs.dwFlags |= (CRYPTUI_DISABLE_EDITPROPERTIES|CRYPTUI_DISABLE_ADDTOSTORE);
  3117. CryptUIDlgViewCertificate (&vcs, &fPropertiesChanged);
  3118. return;
  3119. }
  3120. #if 0
  3121. // Location of policy parameters
  3122. #define cwszEAPOLPolicyParams L"Software\\Policies\\Microsoft\\Windows\\Network Connections\\8021X"
  3123. #define cszCARootHash "8021XCARootHash"
  3124. #define SIZE_OF_CA_CONV_STR 3
  3125. #define SIZE_OF_HASH 20
  3126. //
  3127. // ReadGPCARootHashes
  3128. //
  3129. // Description:
  3130. //
  3131. // Function to read parameters created by policy downloads
  3132. // Currently, 8021XCARootHash will be downloaded to the HKLM
  3133. //
  3134. // Arguments:
  3135. // pdwSizeOfRootHashBlob - Size of hash blob in bytes. Each root CA hash
  3136. // will be of SIZE_OF_HASH bytes
  3137. // ppbRootHashBlob - Pointer to hash blob. Caller should free it using
  3138. // LocalFree
  3139. //
  3140. // Return values:
  3141. // ERROR_SUCCESS - success
  3142. // !ERROR_SUCCESS - error
  3143. //
  3144. DWORD
  3145. ReadGPCARootHashes(
  3146. DWORD *pdwSizeOfRootHashBlob,
  3147. PBYTE *ppbRootHashBlob
  3148. )
  3149. {
  3150. HKEY hKey = NULL;
  3151. DWORD dwType = 0;
  3152. DWORD dwSize = 0;
  3153. CHAR *pszCARootHash = NULL;
  3154. DWORD i = 0;
  3155. CHAR cszCharConv[SIZE_OF_CA_CONV_STR];
  3156. BYTE *pbRootHashBlob = NULL;
  3157. DWORD dwSizeOfHashBlob = 0;
  3158. LONG lError = ERROR_SUCCESS;
  3159. lError = RegOpenKeyEx(
  3160. HKEY_LOCAL_MACHINE,
  3161. cwszEAPOLPolicyParams,
  3162. 0,
  3163. KEY_READ,
  3164. &hKey
  3165. );
  3166. if (lError != ERROR_SUCCESS)
  3167. {
  3168. EapTlsTrace("ReadCARootHashes: RegOpenKeyEx failed with error %ld",
  3169. lError);
  3170. goto LDone;
  3171. }
  3172. lError = RegQueryValueExA(
  3173. hKey,
  3174. cszCARootHash,
  3175. 0,
  3176. &dwType,
  3177. NULL,
  3178. &dwSize
  3179. );
  3180. if (lError == ERROR_SUCCESS)
  3181. {
  3182. // Each SHA1 hash will be 2*SIZE_OF_HASH chars
  3183. // Each BYTE in the hash will be represented by 2 CHARs,
  3184. // 1 for each nibble
  3185. // The hashblob should contain an integral number of hashes
  3186. if ((dwSize-1*sizeof(CHAR))%(2*SIZE_OF_HASH*sizeof(CHAR)))
  3187. {
  3188. EapTlsTrace("ReadCARootHashes: Invalid hash length (%ld)",
  3189. dwSize);
  3190. goto LDone;
  3191. }
  3192. pszCARootHash = (CHAR *)LocalAlloc(LPTR, dwSize);
  3193. if (pszCARootHash == NULL)
  3194. {
  3195. lError = GetLastError();
  3196. EapTlsTrace("ReadCARootHashes: LocalAlloc failed for pwszCARootHash");
  3197. goto LDone;
  3198. }
  3199. lError = RegQueryValueExA(
  3200. hKey,
  3201. cszCARootHash,
  3202. 0,
  3203. &dwType,
  3204. (BYTE *)pszCARootHash,
  3205. &dwSize
  3206. );
  3207. if (lError != ERROR_SUCCESS)
  3208. {
  3209. EapTlsTrace("ReadCARootHashes: RegQueryValueEx 2 failed with error (%ld)",
  3210. lError);
  3211. goto LDone;
  3212. }
  3213. dwSizeOfHashBlob = (dwSize-1*sizeof(CHAR))/(2*sizeof(CHAR));
  3214. if ((pbRootHashBlob = LocalAlloc ( LPTR, dwSizeOfHashBlob*sizeof(BYTE))) == NULL)
  3215. {
  3216. lError = GetLastError();
  3217. EapTlsTrace("ReadCARootHashes: LocalAlloc failed for pbRootHashBlob");
  3218. goto LDone;
  3219. }
  3220. for (i=0; i<dwSizeOfHashBlob; i++)
  3221. {
  3222. ZeroMemory(cszCharConv, SIZE_OF_CA_CONV_STR);
  3223. cszCharConv[0]=pszCARootHash[2*i];
  3224. cszCharConv[1]=pszCARootHash[2*i+1];
  3225. pbRootHashBlob[i] = (BYTE)strtol(cszCharConv, NULL, 16);
  3226. }
  3227. }
  3228. else
  3229. {
  3230. EapTlsTrace("ReadCARootHashes: 802.1X Policy Parameters RegQueryValueEx 1 failed with error (%ld)",
  3231. lError);
  3232. goto LDone;
  3233. }
  3234. LDone:
  3235. if (lError != ERROR_SUCCESS)
  3236. {
  3237. if (pbRootHashBlob != NULL)
  3238. {
  3239. LocalFree(pbRootHashBlob);
  3240. }
  3241. }
  3242. else
  3243. {
  3244. *ppbRootHashBlob = pbRootHashBlob;
  3245. *pdwSizeOfRootHashBlob = dwSizeOfHashBlob;
  3246. }
  3247. if (hKey != NULL)
  3248. {
  3249. RegCloseKey(hKey);
  3250. }
  3251. if (pszCARootHash != NULL)
  3252. {
  3253. LocalFree(pszCARootHash);
  3254. }
  3255. return lError;
  3256. }
  3257. #endif
  3258. /////////////////////// ALL PEAP related utils go here ///////////////////////////
  3259. PEAP_ENTRY_USER_PROPERTIES UNALIGNED *
  3260. PeapFindEntryUserProp ( PPEAP_USER_PROP pUserProp,
  3261. DWORD dwTypeId
  3262. )
  3263. {
  3264. PEAP_ENTRY_USER_PROPERTIES UNALIGNED * pEntryProp = NULL;
  3265. DWORD dwCount = 0;
  3266. PeapGetFirstEntryUserProp ( pUserProp,
  3267. &pEntryProp
  3268. );
  3269. for ( dwCount = 0; dwCount < pUserProp->dwNumberOfEntries;dwCount++)
  3270. {
  3271. if ( pEntryProp->dwEapTypeId == dwTypeId )
  3272. {
  3273. return pEntryProp;
  3274. }
  3275. PeapGetNextEntryUserProp ( pEntryProp,
  3276. &pEntryProp
  3277. );
  3278. }
  3279. return NULL;
  3280. }
  3281. DWORD
  3282. PeapGetFirstEntryUserProp ( PPEAP_USER_PROP pUserProp,
  3283. PEAP_ENTRY_USER_PROPERTIES UNALIGNED ** ppEntryProp
  3284. )
  3285. {
  3286. * ppEntryProp = &( pUserProp->UserProperties );
  3287. return NO_ERROR;
  3288. }
  3289. DWORD
  3290. PeapGetNextEntryUserProp ( PEAP_ENTRY_USER_PROPERTIES UNALIGNED * pCurrentProp,
  3291. PEAP_ENTRY_USER_PROPERTIES UNALIGNED ** ppEntryProp
  3292. )
  3293. {
  3294. *ppEntryProp =
  3295. (PPEAP_ENTRY_USER_PROPERTIES)(((PBYTE) ( pCurrentProp ) )+ pCurrentProp->dwSize);
  3296. return NO_ERROR;
  3297. }
  3298. DWORD
  3299. PeapRemoveEntryUserProp ( PPEAP_USER_PROP pUserProp,
  3300. PPEAP_EAP_INFO pEapInfo,
  3301. PPEAP_USER_PROP * ppNewUserProp
  3302. )
  3303. {
  3304. DWORD dwRetCode = NO_ERROR;
  3305. PEAP_ENTRY_USER_PROPERTIES UNALIGNED * pEntryUserProp = NULL;
  3306. PEAP_ENTRY_USER_PROPERTIES UNALIGNED * pNewEntryUserProp = NULL;
  3307. PPEAP_USER_PROP pNewUserProp = NULL;
  3308. DWORD dwCount = 0;
  3309. DWORD dwNewCount = 0;
  3310. //
  3311. // Check to see if this entry prop is in the list
  3312. //
  3313. PeapGetFirstEntryUserProp ( pUserProp,
  3314. &pEntryUserProp
  3315. );
  3316. for ( dwCount = 0; dwCount < pUserProp->dwNumberOfEntries;dwCount++)
  3317. {
  3318. if ( pEntryUserProp->dwEapTypeId == pEapInfo->dwTypeId )
  3319. {
  3320. //
  3321. // Re allocate the blob
  3322. //
  3323. pNewUserProp = LocalAlloc ( LPTR, pUserProp->dwSize - pEntryUserProp->dwSize );
  3324. if ( NULL == pNewUserProp )
  3325. {
  3326. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  3327. goto LDone;
  3328. }
  3329. break;
  3330. }
  3331. PeapGetNextEntryUserProp ( pEntryUserProp,
  3332. &pEntryUserProp
  3333. );
  3334. }
  3335. if ( pNewUserProp )
  3336. {
  3337. //We have found the entry to delete
  3338. //copy over everything but for the entry that needs deletion
  3339. pNewUserProp->dwVersion = 2;
  3340. pNewUserProp->dwSize = pUserProp->dwSize - pEntryUserProp->dwSize;
  3341. pNewUserProp->dwFlags = pUserProp->dwFlags;
  3342. CopyMemory ( &(pNewUserProp->CertHash),
  3343. &(pUserProp->CertHash),
  3344. sizeof(pNewUserProp->CertHash)
  3345. );
  3346. pNewUserProp->dwNumberOfEntries = pUserProp->dwNumberOfEntries - 1;
  3347. PeapGetFirstEntryUserProp ( pUserProp,
  3348. &pEntryUserProp
  3349. );
  3350. PeapGetFirstEntryUserProp ( pNewUserProp,
  3351. &pNewEntryUserProp
  3352. );
  3353. for ( dwNewCount = 0; dwNewCount < pUserProp->dwNumberOfEntries; dwNewCount ++ )
  3354. {
  3355. if ( pEntryUserProp->dwEapTypeId != pEapInfo->dwTypeId )
  3356. {
  3357. CopyMemory ( pNewEntryUserProp,
  3358. pEntryUserProp,
  3359. pEntryUserProp->dwSize
  3360. );
  3361. PeapGetNextEntryUserProp ( pNewEntryUserProp,
  3362. &pNewEntryUserProp
  3363. );
  3364. }
  3365. PeapGetNextEntryUserProp ( pEntryUserProp,
  3366. &pEntryUserProp
  3367. );
  3368. }
  3369. *ppNewUserProp = pNewUserProp;
  3370. pNewUserProp = NULL;
  3371. goto LDone;
  3372. }
  3373. dwRetCode = ERROR_NOT_FOUND;
  3374. LDone:
  3375. LocalFree ( pNewUserProp );
  3376. return dwRetCode;
  3377. }
  3378. //
  3379. // Add a new entry at the end in the list and return the
  3380. // new UserProp back.
  3381. //
  3382. DWORD
  3383. PeapAddEntryUserProp ( PPEAP_USER_PROP pUserProp,
  3384. PPEAP_EAP_INFO pEapInfo,
  3385. PPEAP_USER_PROP * ppNewUserProp
  3386. )
  3387. {
  3388. DWORD dwRetCode = NO_ERROR;
  3389. PEAP_ENTRY_USER_PROPERTIES UNALIGNED * pEntryUserProp = NULL;
  3390. DWORD dwCount = 0;
  3391. PPEAP_USER_PROP pNewUserProp = NULL;
  3392. PeapGetFirstEntryUserProp ( pUserProp,
  3393. &pEntryUserProp
  3394. );
  3395. for ( dwCount = 0; dwCount < pUserProp->dwNumberOfEntries;dwCount++)
  3396. {
  3397. if ( pEntryUserProp->dwEapTypeId == pEapInfo->dwTypeId )
  3398. {
  3399. //
  3400. // This should never happen. The EAP type supplied is
  3401. // already configured...
  3402. //
  3403. RTASSERT(FALSE);
  3404. dwRetCode = ERROR_INTERNAL_ERROR;
  3405. goto LDone;
  3406. }
  3407. PeapGetNextEntryUserProp ( pEntryUserProp,
  3408. &pEntryUserProp
  3409. );
  3410. }
  3411. //
  3412. // EapInfo does not exist add it to the UserProp.
  3413. //
  3414. pNewUserProp =
  3415. (PPEAP_USER_PROP)LocalAlloc(LPTR,
  3416. pUserProp->dwSize +
  3417. FIELD_OFFSET(PEAP_ENTRY_USER_PROPERTIES, bData));
  3418. if ( NULL == pNewUserProp )
  3419. {
  3420. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  3421. goto LDone;
  3422. }
  3423. CopyMemory ( pNewUserProp,
  3424. pUserProp,
  3425. pUserProp->dwSize
  3426. );
  3427. pNewUserProp->dwNumberOfEntries =
  3428. pUserProp->dwNumberOfEntries+1;
  3429. pNewUserProp->dwSize =
  3430. pUserProp->dwSize + FIELD_OFFSET(PEAP_ENTRY_USER_PROPERTIES, bData);
  3431. pEntryUserProp = (PEAP_ENTRY_USER_PROPERTIES UNALIGNED *)
  3432. (((PBYTE)pNewUserProp)+pUserProp->dwSize);
  3433. pEntryUserProp->dwVersion = 1;
  3434. pEntryUserProp->dwSize = FIELD_OFFSET(PEAP_ENTRY_USER_PROPERTIES, bData);
  3435. pEntryUserProp->dwEapTypeId = pEapInfo->dwTypeId;
  3436. pEntryUserProp->fUsingPeapDefault = !(pEapInfo->lpwszIdentityUIPath);
  3437. *ppNewUserProp = pNewUserProp;
  3438. pNewUserProp = NULL;
  3439. LDone:
  3440. LocalFree(pNewUserProp );
  3441. return dwRetCode;
  3442. }
  3443. //
  3444. // Move a User Prop Entry up or down in the list
  3445. // and return the new struct.
  3446. //
  3447. DWORD
  3448. PeapMoveEntryUserProp ( PPEAP_USER_PROP pUserProp,
  3449. DWORD dwEntryIndex,
  3450. BOOL fDirectionUp
  3451. )
  3452. {
  3453. DWORD dwRetCode = NO_ERROR;
  3454. DWORD dwSwapEntryIndex = 0;
  3455. DWORD dwCount = 0;
  3456. PEAP_ENTRY_USER_PROPERTIES UNALIGNED * pEntryUserProp = NULL;
  3457. PEAP_ENTRY_USER_PROPERTIES UNALIGNED * pEntryUserProp1 = NULL;
  3458. PEAP_ENTRY_USER_PROPERTIES UNALIGNED * pEntryUserProp2 = NULL;
  3459. if ( 0 == dwEntryIndex && fDirectionUp )
  3460. {
  3461. dwRetCode = ERROR_INVALID_PARAMETER;
  3462. goto LDone;
  3463. }
  3464. if ( pUserProp->dwNumberOfEntries -1 == dwEntryIndex && !fDirectionUp )
  3465. {
  3466. dwRetCode = ERROR_INVALID_PARAMETER;
  3467. goto LDone;
  3468. }
  3469. //
  3470. // Swap the two entries in question
  3471. //
  3472. if ( fDirectionUp )
  3473. {
  3474. dwSwapEntryIndex = dwEntryIndex;
  3475. dwEntryIndex = dwEntryIndex-1;
  3476. }
  3477. else
  3478. {
  3479. dwSwapEntryIndex = dwEntryIndex +1;
  3480. }
  3481. PeapGetFirstEntryUserProp ( pUserProp,
  3482. &pEntryUserProp
  3483. );
  3484. for ( dwCount = 0; dwCount < pUserProp->dwNumberOfEntries; dwCount ++ )
  3485. {
  3486. if ( dwCount == dwEntryIndex )
  3487. {
  3488. pEntryUserProp1 = pEntryUserProp;
  3489. }
  3490. if ( dwCount == dwSwapEntryIndex )
  3491. {
  3492. pEntryUserProp2 = pEntryUserProp;
  3493. }
  3494. PeapGetNextEntryUserProp ( pEntryUserProp,
  3495. &pEntryUserProp
  3496. );
  3497. }
  3498. if ( NULL == pEntryUserProp1 )
  3499. {
  3500. dwRetCode = ERROR_NOT_FOUND;
  3501. goto LDone;
  3502. }
  3503. //Swap these 2 entries
  3504. pEntryUserProp = (PEAP_ENTRY_USER_PROPERTIES UNALIGNED *)
  3505. LocalAlloc(LPTR, pEntryUserProp1->dwSize);
  3506. if ( NULL == pEntryUserProp)
  3507. {
  3508. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  3509. goto LDone;
  3510. }
  3511. CopyMemory ( pEntryUserProp,
  3512. pEntryUserProp1,
  3513. pEntryUserProp1->dwSize
  3514. );
  3515. CopyMemory ( pEntryUserProp1,
  3516. pEntryUserProp2,
  3517. pEntryUserProp2->dwSize
  3518. );
  3519. pEntryUserProp2 = (PEAP_ENTRY_USER_PROPERTIES UNALIGNED *)
  3520. ( (PBYTE)pEntryUserProp1 + pEntryUserProp1->dwSize ) ;
  3521. CopyMemory ( pEntryUserProp2,
  3522. pEntryUserProp,
  3523. pEntryUserProp->dwSize
  3524. );
  3525. LocalFree ( pEntryUserProp);
  3526. LDone:
  3527. return dwRetCode;
  3528. }
  3529. DWORD
  3530. PeapGetFirstEntryConnProp ( PPEAP_CONN_PROP pConnProp,
  3531. PEAP_ENTRY_CONN_PROPERTIES UNALIGNED ** ppEntryProp
  3532. )
  3533. {
  3534. DWORD dwRetCode = NO_ERROR;
  3535. PEAP_ENTRY_CONN_PROPERTIES UNALIGNED *pFirstEntryConnProp = NULL;
  3536. LPWSTR lpwszServerName;
  3537. RTASSERT ( NULL != pConnProp );
  3538. RTASSERT ( NULL != ppEntryProp );
  3539. lpwszServerName =
  3540. (LPWSTR )(pConnProp->EapTlsConnProp.bData +
  3541. sizeof( EAPTLS_HASH ) * pConnProp->EapTlsConnProp.dwNumHashes);
  3542. //Get the first entry in connprop
  3543. pFirstEntryConnProp = ( PEAP_ENTRY_CONN_PROPERTIES UNALIGNED *)
  3544. ( pConnProp->EapTlsConnProp.bData
  3545. + pConnProp->EapTlsConnProp.dwNumHashes * sizeof(EAPTLS_HASH) +
  3546. (lpwszServerName? wcslen(lpwszServerName) * sizeof(WCHAR):0) +
  3547. sizeof(WCHAR)
  3548. );
  3549. if (NULL == pFirstEntryConnProp )
  3550. {
  3551. dwRetCode = ERROR_NOT_FOUND;
  3552. goto LDone;
  3553. }
  3554. *ppEntryProp = pFirstEntryConnProp;
  3555. LDone:
  3556. return dwRetCode;
  3557. }
  3558. DWORD
  3559. PeapReadConnectionData(
  3560. IN BOOL fWireless,
  3561. IN BYTE* pConnectionDataIn,
  3562. IN DWORD dwSizeOfConnectionDataIn,
  3563. OUT PPEAP_CONN_PROP* ppConnProp
  3564. )
  3565. {
  3566. DWORD dwRetCode = NO_ERROR;
  3567. PPEAP_CONN_PROP pConnProp = NULL;
  3568. PEAP_ENTRY_CONN_PROPERTIES UNALIGNED * pEntryProp = NULL;
  3569. EapTlsTrace("PeapReadConnectionData");
  3570. RTASSERT(NULL != ppConnProp);
  3571. if ( dwSizeOfConnectionDataIn < sizeof(PEAP_CONN_PROP) )
  3572. {
  3573. pConnProp = LocalAlloc(LPTR, sizeof(PEAP_CONN_PROP) + sizeof(PEAP_ENTRY_CONN_PROPERTIES)+ sizeof(WCHAR));
  3574. if (NULL == pConnProp)
  3575. {
  3576. dwRetCode = GetLastError();
  3577. EapTlsTrace("LocalAlloc failed and returned %d", dwRetCode);
  3578. goto LDone;
  3579. }
  3580. //This is a new structure
  3581. pConnProp->dwVersion = 1;
  3582. pConnProp->dwSize = sizeof(PEAP_CONN_PROP) + sizeof(PEAP_ENTRY_CONN_PROPERTIES);
  3583. pConnProp->EapTlsConnProp.dwVersion = 1;
  3584. pConnProp->EapTlsConnProp.dwSize = sizeof(EAPTLS_CONN_PROPERTIES_V1);
  3585. pConnProp->EapTlsConnProp.fFlags |= EAPTLS_CONN_FLAG_REGISTRY;
  3586. pConnProp->dwNumPeapTypes = 1;
  3587. //pEntryProp = (PPEAP_ENTRY_CONN_PROPERTIES)(((PBYTE)(pConnProp)) + sizeof(PEAP_CONN_PROP) + sizeof(WCHAR));
  3588. pEntryProp = ( PEAP_ENTRY_CONN_PROPERTIES UNALIGNED *)
  3589. ( pConnProp->EapTlsConnProp.bData
  3590. + pConnProp->EapTlsConnProp.dwNumHashes * sizeof(EAPTLS_HASH) +
  3591. sizeof(WCHAR)
  3592. );
  3593. //
  3594. // Also setup the first peap entry conn prop and set it to
  3595. // eapmschapv2
  3596. //
  3597. if ( fWireless )
  3598. {
  3599. pConnProp->EapTlsConnProp.fFlags |= EAPTLS_CONN_FLAG_NO_VALIDATE_NAME;
  3600. }
  3601. pEntryProp->dwVersion = 1;
  3602. pEntryProp->dwSize = sizeof(PEAP_ENTRY_CONN_PROPERTIES);
  3603. pEntryProp->dwEapTypeId = PPP_EAP_MSCHAPv2;
  3604. }
  3605. else
  3606. {
  3607. RTASSERT(NULL != pConnectionDataIn);
  3608. //
  3609. //Check to see if this is a version 0 structure
  3610. //If it is a version 0 structure then we migrate it to version1
  3611. //
  3612. pConnProp = LocalAlloc(LPTR, dwSizeOfConnectionDataIn);
  3613. if (NULL == pConnProp)
  3614. {
  3615. dwRetCode = GetLastError();
  3616. EapTlsTrace("LocalAlloc failed and returned %d", dwRetCode);
  3617. goto LDone;
  3618. }
  3619. // If the user has mucked with the phonebook, we mustn't be affected.
  3620. // The size must be correct.
  3621. CopyMemory(pConnProp, pConnectionDataIn, dwSizeOfConnectionDataIn);
  3622. pConnProp->dwSize = dwSizeOfConnectionDataIn;
  3623. pConnProp->EapTlsConnProp.fFlags |= EAPTLS_CONN_FLAG_REGISTRY;
  3624. }
  3625. *ppConnProp = pConnProp;
  3626. pConnProp = NULL;
  3627. LDone:
  3628. LocalFree(pConnProp);
  3629. return dwRetCode;
  3630. }
  3631. DWORD
  3632. PeapReDoUserData (
  3633. IN DWORD dwNewTypeId,
  3634. OUT PPEAP_USER_PROP* ppNewUserProp
  3635. )
  3636. {
  3637. DWORD dwRetCode = NO_ERROR;
  3638. PPEAP_USER_PROP pUserProp = NULL;
  3639. EapTlsTrace("PeapReDoUserData");
  3640. pUserProp = LocalAlloc(LPTR, sizeof(PEAP_USER_PROP));
  3641. if (NULL == pUserProp)
  3642. {
  3643. dwRetCode = GetLastError();
  3644. EapTlsTrace("LocalAlloc failed and returned %d", dwRetCode);
  3645. goto LDone;
  3646. }
  3647. pUserProp->dwVersion = 1;
  3648. pUserProp->dwSize = sizeof(PEAP_USER_PROP);
  3649. //
  3650. // Setup the default user prop...
  3651. //
  3652. pUserProp->UserProperties.dwVersion = 1;
  3653. pUserProp->UserProperties.dwSize = sizeof(PEAP_ENTRY_USER_PROPERTIES);
  3654. pUserProp->UserProperties.dwEapTypeId = dwNewTypeId;
  3655. *ppNewUserProp = pUserProp;
  3656. LDone:
  3657. return dwRetCode;
  3658. }
  3659. PEAP_ENTRY_USER_PROPERTIES *
  3660. PeapGetEapConfigInfo(
  3661. PEAP_USER_PROP* pUserProp,
  3662. DWORD dwTypeId,
  3663. PBYTE* ppConfigData,
  3664. DWORD* pdwSizeOfConfigData)
  3665. {
  3666. DWORD i;
  3667. PEAP_ENTRY_USER_PROPERTIES *pEntry;
  3668. ASSERT(NULL != pUserProp);
  3669. ASSERT(NULL != ppConfigData);
  3670. ASSERT(NULL != pdwSizeOfConfigData);
  3671. pEntry = &pUserProp->UserProperties;
  3672. *ppConfigData = NULL;
  3673. *pdwSizeOfConfigData = 0;
  3674. //
  3675. // Find the config data for this eap in the
  3676. // user properties that was passed in.
  3677. //
  3678. for(i = 0; i < pUserProp->dwNumberOfEntries; i++)
  3679. {
  3680. ASSERT((BYTE *)pEntry < (BYTE *) pUserProp + pUserProp->dwSize);
  3681. if(pEntry->dwEapTypeId == dwTypeId)
  3682. {
  3683. //
  3684. // Assert that the size is valid here
  3685. //
  3686. ASSERT(pEntry->dwSize >=
  3687. FIELD_OFFSET(PEAP_ENTRY_USER_PROPERTIES, bData));
  3688. *pdwSizeOfConfigData = pEntry->dwSize -
  3689. FIELD_OFFSET(PEAP_ENTRY_USER_PROPERTIES,bData);
  3690. if(*pdwSizeOfConfigData != 0)
  3691. {
  3692. *ppConfigData = pEntry->bData;
  3693. }
  3694. break;
  3695. }
  3696. //
  3697. // Go on to the next entry. Assert that the pointer is still valid.
  3698. //
  3699. pEntry = (PEAP_ENTRY_USER_PROPERTIES *)
  3700. ((BYTE *)pEntry + pEntry->dwSize);
  3701. }
  3702. if(i == pUserProp->dwNumberOfEntries)
  3703. {
  3704. return NULL;
  3705. }
  3706. return pEntry;
  3707. }
  3708. //
  3709. // This function will verify that the UserProps blob
  3710. // matches the EAPTypes. If an eaptype is unusable
  3711. // due to unavailability then it will remove
  3712. // it from the blob. This is used only on the server
  3713. // side.
  3714. //
  3715. DWORD
  3716. PeapVerifyUserData(
  3717. PPEAP_EAP_INFO pEapInfo,
  3718. PPEAP_USER_PROP pUserProp,
  3719. PPEAP_USER_PROP * ppNewUserProp
  3720. )
  3721. {
  3722. DWORD dwRetCode = NO_ERROR;
  3723. PPEAP_USER_PROP pTempUserProp = NULL;
  3724. PEAP_ENTRY_USER_PROPERTIES UNALIGNED * pEntryUserProp = NULL;
  3725. PPEAP_EAP_INFO pEapInfoNode = NULL;
  3726. PEAP_EAP_INFO TempNode;
  3727. DWORD dwCount = 0;
  3728. if ( NULL == pUserProp )
  3729. {
  3730. goto done;
  3731. }
  3732. PeapGetFirstEntryUserProp ( pUserProp,
  3733. &pEntryUserProp
  3734. );
  3735. for ( dwCount =0; dwCount < pUserProp->dwNumberOfEntries; dwCount++)
  3736. {
  3737. //
  3738. // Check to see if the configured entry is present in
  3739. // the list of entries that are legal on this machine
  3740. //
  3741. PeapEapInfoFindListNode ( pEntryUserProp->dwEapTypeId,
  3742. pEapInfo,
  3743. &pEapInfoNode
  3744. );
  3745. if ( !pEapInfoNode )
  3746. {
  3747. if ( pTempUserProp )
  3748. {
  3749. LocalFree (pTempUserProp);
  3750. pTempUserProp = NULL;
  3751. }
  3752. //
  3753. // This node is not in our list of configured EAP Types.
  3754. //
  3755. ZeroMemory( &TempNode, sizeof(TempNode) );
  3756. TempNode.dwTypeId = pEntryUserProp->dwEapTypeId;
  3757. PeapRemoveEntryUserProp( pUserProp,
  3758. &TempNode,
  3759. &pTempUserProp
  3760. );
  3761. }
  3762. pEapInfoNode = NULL;
  3763. PeapGetNextEntryUserProp ( pEntryUserProp,
  3764. &pEntryUserProp
  3765. );
  3766. }
  3767. *ppNewUserProp = pTempUserProp;
  3768. done:
  3769. return dwRetCode;
  3770. }
  3771. DWORD
  3772. PeapReadUserData(
  3773. IN BOOL fServer,
  3774. IN BYTE* pUserDataIn,
  3775. IN DWORD dwSizeOfUserDataIn,
  3776. OUT PPEAP_USER_PROP* ppUserProp
  3777. )
  3778. {
  3779. DWORD dwErr = NO_ERROR;
  3780. PPEAP_USER_PROP pUserProp = NULL;
  3781. PPEAP_USER_PROP_V1 pUserPropv1 = NULL;
  3782. EapTlsTrace("PeapReadUserData");
  3783. if (( fServer && ( dwSizeOfUserDataIn <
  3784. FIELD_OFFSET(PEAP_USER_PROP,UserProperties) +
  3785. FIELD_OFFSET(PEAP_ENTRY_USER_PROPERTIES ,bData ) )
  3786. )
  3787. || ( !fServer && (dwSizeOfUserDataIn < sizeof(PEAP_USER_PROP)) )
  3788. )
  3789. {
  3790. pUserProp = LocalAlloc(LPTR, sizeof(PEAP_USER_PROP));
  3791. if (NULL == pUserProp)
  3792. {
  3793. dwErr = GetLastError();
  3794. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  3795. goto LDone;
  3796. }
  3797. pUserProp->dwVersion = 2;
  3798. pUserProp->dwNumberOfEntries = 1;
  3799. //
  3800. // Setup the default user prop...
  3801. //
  3802. pUserProp->UserProperties.dwVersion = 1;
  3803. if ( fServer )
  3804. {
  3805. pUserProp->UserProperties.dwSize =
  3806. FIELD_OFFSET(PEAP_ENTRY_USER_PROPERTIES,bData);
  3807. pUserProp->dwSize =
  3808. FIELD_OFFSET(PEAP_USER_PROP,UserProperties) +
  3809. pUserProp->UserProperties.dwSize;
  3810. }
  3811. else
  3812. {
  3813. pUserProp->UserProperties.dwSize = sizeof(PEAP_ENTRY_USER_PROPERTIES);
  3814. pUserProp->dwSize = sizeof(PEAP_USER_PROP);
  3815. }
  3816. pUserProp->UserProperties.dwEapTypeId = PPP_EAP_MSCHAPv2;
  3817. }
  3818. else
  3819. {
  3820. RTASSERT(NULL != pUserDataIn);
  3821. if ( *((DWORD *)pUserDataIn) <= 1 )
  3822. {
  3823. pUserPropv1 = LocalAlloc(LPTR, dwSizeOfUserDataIn);
  3824. if (NULL == pUserPropv1 )
  3825. {
  3826. dwErr = GetLastError();
  3827. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  3828. goto LDone;
  3829. }
  3830. CopyMemory(pUserPropv1 , pUserDataIn, dwSizeOfUserDataIn);
  3831. //
  3832. // Allocate the new version 2 structure here and convert
  3833. // the version 1 to version 2
  3834. //
  3835. pUserProp = LocalAlloc (LPTR, dwSizeOfUserDataIn + sizeof(DWORD) );
  3836. if ( NULL == pUserProp )
  3837. {
  3838. dwErr = GetLastError();
  3839. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  3840. goto LDone;
  3841. }
  3842. pUserProp->dwVersion = 2;
  3843. pUserProp->dwSize = dwSizeOfUserDataIn + sizeof(DWORD);
  3844. pUserProp->dwFlags = pUserPropv1->dwFlags;
  3845. CopyMemory ( &(pUserProp->CertHash),
  3846. &(pUserPropv1->CertHash),
  3847. sizeof(EAPTLS_HASH)
  3848. );
  3849. pUserProp->dwNumberOfEntries = 1;
  3850. CopyMemory ( &(pUserProp->UserProperties),
  3851. &(pUserPropv1->UserProperties),
  3852. pUserPropv1->UserProperties.dwSize
  3853. );
  3854. LocalFree (pUserPropv1);
  3855. pUserPropv1 = NULL;
  3856. }
  3857. else
  3858. {
  3859. pUserProp = LocalAlloc(LPTR, dwSizeOfUserDataIn);
  3860. if (NULL == pUserProp )
  3861. {
  3862. dwErr = GetLastError();
  3863. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  3864. goto LDone;
  3865. }
  3866. CopyMemory(pUserProp , pUserDataIn, dwSizeOfUserDataIn);
  3867. }
  3868. }
  3869. *ppUserProp = pUserProp;
  3870. pUserProp = NULL;
  3871. LDone:
  3872. LocalFree(pUserPropv1);
  3873. LocalFree(pUserProp);
  3874. return dwErr;
  3875. }
  3876. //
  3877. // Add node at the head
  3878. //
  3879. DWORD
  3880. PeapEapInfoAddListNode (PPEAP_EAP_INFO * ppEapInfo)
  3881. {
  3882. PPEAP_EAP_INFO pEapInfo = NULL;
  3883. DWORD dwRetCode = NO_ERROR;
  3884. pEapInfo = (PPEAP_EAP_INFO)LocalAlloc(LPTR, sizeof(PEAP_EAP_INFO));
  3885. if ( NULL == pEapInfo )
  3886. {
  3887. dwRetCode = ERROR_OUTOFMEMORY;
  3888. goto LDone;
  3889. }
  3890. if ( NULL == *ppEapInfo )
  3891. {
  3892. *ppEapInfo = pEapInfo;
  3893. }
  3894. else
  3895. {
  3896. pEapInfo->pNext = *ppEapInfo;
  3897. *ppEapInfo = pEapInfo;
  3898. }
  3899. LDone:
  3900. return dwRetCode;
  3901. }
  3902. DWORD
  3903. PeapEapInfoCopyListNode ( DWORD dwTypeId,
  3904. PPEAP_EAP_INFO pEapInfoList,
  3905. PPEAP_EAP_INFO * ppEapInfo )
  3906. {
  3907. DWORD dwRetCode = ERROR_NOT_FOUND;
  3908. PPEAP_EAP_INFO pEapInfoListInternal = pEapInfoList;
  3909. while ( pEapInfoListInternal )
  3910. {
  3911. if ( pEapInfoListInternal->dwTypeId == dwTypeId )
  3912. {
  3913. *ppEapInfo = LocalAlloc( LPTR, sizeof(PEAP_EAP_INFO) );
  3914. if ( NULL == *ppEapInfo )
  3915. {
  3916. dwRetCode = ERROR_OUTOFMEMORY;
  3917. goto LDone;
  3918. }
  3919. CopyMemory ( *ppEapInfo, pEapInfoListInternal, sizeof(PEAP_EAP_INFO) );
  3920. dwRetCode = NO_ERROR;
  3921. goto LDone;
  3922. }
  3923. pEapInfoListInternal = pEapInfoListInternal->pNext;
  3924. }
  3925. LDone:
  3926. return dwRetCode;
  3927. }
  3928. DWORD
  3929. PeapEapInfoFindListNode ( DWORD dwTypeId,
  3930. PPEAP_EAP_INFO pEapInfoList,
  3931. PPEAP_EAP_INFO * ppEapInfo )
  3932. {
  3933. DWORD dwRetCode = ERROR_NOT_FOUND;
  3934. PPEAP_EAP_INFO pEapInfoListInternal = pEapInfoList;
  3935. while ( pEapInfoListInternal )
  3936. {
  3937. if ( pEapInfoListInternal->dwTypeId == dwTypeId )
  3938. {
  3939. *ppEapInfo = pEapInfoListInternal;
  3940. dwRetCode = NO_ERROR;
  3941. goto LDone;
  3942. }
  3943. pEapInfoListInternal = pEapInfoListInternal->pNext;
  3944. }
  3945. LDone:
  3946. return dwRetCode;
  3947. }
  3948. VOID
  3949. PeapEapInfoFreeNodeData ( PPEAP_EAP_INFO pEapInfo )
  3950. {
  3951. LocalFree ( pEapInfo->lpwszFriendlyName );
  3952. LocalFree ( pEapInfo->lpwszConfigUIPath );
  3953. LocalFree ( pEapInfo->lpwszIdentityUIPath );
  3954. LocalFree ( pEapInfo->lpwszConfigClsId );
  3955. LocalFree ( pEapInfo->pbNewClientConfig );
  3956. LocalFree ( pEapInfo->lpwszInteractiveUIPath );
  3957. LocalFree ( pEapInfo->lpwszPath);
  3958. if ( pEapInfo->hEAPModule )
  3959. {
  3960. FreeLibrary(pEapInfo->hEAPModule);
  3961. }
  3962. }
  3963. VOID
  3964. PeapEapInfoRemoveHeadNode(PPEAP_EAP_INFO * ppEapInfo)
  3965. {
  3966. PPEAP_EAP_INFO pEapInfo = *ppEapInfo;
  3967. if ( pEapInfo )
  3968. {
  3969. *ppEapInfo = pEapInfo->pNext;
  3970. PeapEapInfoFreeNodeData(pEapInfo);
  3971. LocalFree ( pEapInfo );
  3972. }
  3973. }
  3974. VOID
  3975. PeapEapInfoFreeList ( PPEAP_EAP_INFO pEapInfo )
  3976. {
  3977. PPEAP_EAP_INFO pNext;
  3978. while ( pEapInfo )
  3979. {
  3980. if ( pEapInfo->PppEapInfo.RasEapInitialize )
  3981. pEapInfo->PppEapInfo.RasEapInitialize (FALSE);
  3982. pNext = pEapInfo->pNext;
  3983. PeapEapInfoFreeNodeData(pEapInfo);
  3984. LocalFree ( pEapInfo );
  3985. pEapInfo = pNext;
  3986. }
  3987. }
  3988. DWORD
  3989. PeapEapInfoReadSZ (HKEY hkeyPeapType,
  3990. LPWSTR pwszValue,
  3991. LPWSTR * ppValueData )
  3992. {
  3993. DWORD dwRetCode = NO_ERROR;
  3994. DWORD dwType = 0;
  3995. DWORD cbValueDataSize =0;
  3996. PBYTE pbValue = NULL;
  3997. dwRetCode = RegQueryValueEx(
  3998. hkeyPeapType,
  3999. pwszValue,
  4000. NULL,
  4001. &dwType,
  4002. pbValue,
  4003. &cbValueDataSize );
  4004. if ( dwRetCode != NO_ERROR )
  4005. {
  4006. goto LDone;
  4007. }
  4008. pbValue = (PBYTE)LocalAlloc ( LPTR, cbValueDataSize );
  4009. if ( NULL == pbValue )
  4010. {
  4011. dwRetCode = ERROR_OUTOFMEMORY;
  4012. goto LDone;
  4013. }
  4014. dwRetCode = RegQueryValueEx(
  4015. hkeyPeapType,
  4016. pwszValue,
  4017. NULL,
  4018. &dwType,
  4019. pbValue,
  4020. &cbValueDataSize );
  4021. if ( dwRetCode != NO_ERROR )
  4022. {
  4023. goto LDone;
  4024. }
  4025. *ppValueData = (LPWSTR)pbValue;
  4026. pbValue = NULL;
  4027. LDone:
  4028. LocalFree ( pbValue );
  4029. return dwRetCode;
  4030. }
  4031. DWORD
  4032. PeapEapInfoExpandSZ (HKEY hkeyPeapType,
  4033. LPWSTR pwszValue,
  4034. LPWSTR * ppValueData )
  4035. {
  4036. DWORD dwRetCode = NO_ERROR;
  4037. DWORD dwType = 0;
  4038. DWORD cbValueDataSize =0;
  4039. PBYTE pbValue = NULL;
  4040. PBYTE pbExpandedValue = NULL;
  4041. dwRetCode = RegQueryValueEx(
  4042. hkeyPeapType,
  4043. pwszValue,
  4044. NULL,
  4045. &dwType,
  4046. pbValue,
  4047. &cbValueDataSize );
  4048. if ( dwRetCode != NO_ERROR )
  4049. {
  4050. goto LDone;
  4051. }
  4052. pbValue = (PBYTE)LocalAlloc ( LPTR, cbValueDataSize );
  4053. if ( NULL == pbValue )
  4054. {
  4055. dwRetCode = ERROR_OUTOFMEMORY;
  4056. goto LDone;
  4057. }
  4058. dwRetCode = RegQueryValueEx(
  4059. hkeyPeapType,
  4060. pwszValue,
  4061. NULL,
  4062. &dwType,
  4063. pbValue,
  4064. &cbValueDataSize );
  4065. if ( dwRetCode != NO_ERROR )
  4066. {
  4067. goto LDone;
  4068. }
  4069. //now Expand the exvironment string
  4070. cbValueDataSize = ExpandEnvironmentStrings( (LPWSTR)pbValue, NULL, 0 );
  4071. pbExpandedValue = (PBYTE)LocalAlloc ( LPTR, cbValueDataSize * sizeof(WCHAR) );
  4072. if ( NULL == pbExpandedValue )
  4073. {
  4074. dwRetCode = ERROR_OUTOFMEMORY;
  4075. goto LDone;
  4076. }
  4077. cbValueDataSize = ExpandEnvironmentStrings( (LPWSTR)pbValue,
  4078. (LPWSTR)pbExpandedValue, sizeof(WCHAR) * cbValueDataSize );
  4079. if ( cbValueDataSize == 0 )
  4080. {
  4081. dwRetCode = GetLastError();
  4082. goto LDone;
  4083. }
  4084. *ppValueData = (LPWSTR)pbExpandedValue;
  4085. pbExpandedValue = NULL;
  4086. LDone:
  4087. LocalFree ( pbValue );
  4088. LocalFree ( pbExpandedValue );
  4089. return dwRetCode;
  4090. }
  4091. //
  4092. // Get a list of all EAP types configured for PEAP.
  4093. //
  4094. DWORD
  4095. PeapEapInfoGetList ( LPWSTR lpwszMachineName,
  4096. BOOL fCheckDomainMembership,
  4097. PPEAP_EAP_INFO * ppEapInfo)
  4098. {
  4099. DWORD dwRetCode = NO_ERROR;
  4100. HKEY hKeyLM =0;
  4101. HKEY hKeyPeap = 0;
  4102. HKEY hkeyPeapType = 0;
  4103. DWORD dwIndex;
  4104. DWORD cb;
  4105. WCHAR wszPeapType[200];
  4106. DWORD dwEapTypeId = 0;
  4107. FARPROC pRasEapGetInfo;
  4108. BOOL fStandAloneServer = FALSE;
  4109. fStandAloneServer = IsStandaloneServer(lpwszMachineName);
  4110. dwRetCode = RegConnectRegistry ( lpwszMachineName,
  4111. HKEY_LOCAL_MACHINE,
  4112. &hKeyLM
  4113. );
  4114. if ( NO_ERROR != dwRetCode )
  4115. {
  4116. goto LDone;
  4117. }
  4118. dwRetCode = RegOpenKeyEx( hKeyLM,
  4119. PEAP_KEY_EAP,
  4120. 0,
  4121. KEY_READ,
  4122. &hKeyPeap
  4123. );
  4124. if (NO_ERROR != dwRetCode)
  4125. {
  4126. goto LDone;
  4127. }
  4128. for (dwIndex = 0; TRUE; ++dwIndex)
  4129. {
  4130. cb = sizeof(wszPeapType) / sizeof(WCHAR);
  4131. dwRetCode = RegEnumKeyEx( hKeyPeap,
  4132. dwIndex,
  4133. wszPeapType,
  4134. &cb,
  4135. NULL,
  4136. NULL,
  4137. NULL,
  4138. NULL
  4139. );
  4140. if (dwRetCode != NO_ERROR)
  4141. {
  4142. // Includes "out of items", the normal loop termination.
  4143. //
  4144. dwRetCode = NO_ERROR;
  4145. break;
  4146. }
  4147. dwRetCode = RegOpenKeyEx( hKeyPeap,
  4148. wszPeapType,
  4149. 0,
  4150. KEY_READ,
  4151. &hkeyPeapType
  4152. );
  4153. if (dwRetCode != NO_ERROR)
  4154. {
  4155. dwRetCode = NO_ERROR;
  4156. continue;
  4157. }
  4158. dwEapTypeId = _wtol(wszPeapType);
  4159. if ( dwEapTypeId == PPP_EAP_PEAP )
  4160. {
  4161. dwRetCode = NO_ERROR;
  4162. continue;
  4163. }
  4164. {
  4165. //
  4166. // Check to see if we support this in peap
  4167. // By default we do.
  4168. DWORD dwRolesSupported = 0;
  4169. DWORD cbValueSize = sizeof(dwRolesSupported);
  4170. DWORD dwType = 0;
  4171. dwRetCode = RegQueryValueEx(
  4172. hkeyPeapType,
  4173. PEAP_REGVAL_ROLESSUPPORTED,
  4174. NULL,
  4175. &dwType,
  4176. (PBYTE)&dwRolesSupported,
  4177. &cbValueSize );
  4178. if ( dwRetCode == NO_ERROR )
  4179. {
  4180. //
  4181. // We dont allow this method in PEAP.
  4182. //
  4183. if ( RAS_EAP_ROLE_EXCLUDE_IN_PEAP & dwRolesSupported )
  4184. {
  4185. continue;
  4186. }
  4187. }
  4188. }
  4189. //
  4190. // Read the required information and setup the node here
  4191. //
  4192. dwRetCode = PeapEapInfoAddListNode (ppEapInfo);
  4193. if ( NO_ERROR != dwRetCode )
  4194. {
  4195. goto LDone;
  4196. }
  4197. //
  4198. // Setup the list node - if any of these entries are not
  4199. // found skip the entry
  4200. //
  4201. (*ppEapInfo)->dwTypeId = dwEapTypeId;
  4202. {
  4203. //Get the stand alone supported flag here
  4204. DWORD cbValueSize = sizeof( ((*ppEapInfo)->dwStandAloneSupported ) );
  4205. DWORD dwType = 0;
  4206. dwRetCode = RegQueryValueEx(
  4207. hkeyPeapType,
  4208. PEAP_REGVAL_STANDALONESUPPORTED,
  4209. NULL,
  4210. &dwType,
  4211. (PBYTE)&((*ppEapInfo)->dwStandAloneSupported),
  4212. &cbValueSize );
  4213. if ( dwRetCode != NO_ERROR )
  4214. {
  4215. (*ppEapInfo)->dwStandAloneSupported = 1;
  4216. dwRetCode = NO_ERROR;
  4217. }
  4218. }
  4219. //
  4220. // Check to see if we need to check for domain membership
  4221. //
  4222. if ( fCheckDomainMembership )
  4223. {
  4224. //
  4225. // We need to check for domain membership.
  4226. //
  4227. if ( fStandAloneServer )
  4228. {
  4229. if ( !((*ppEapInfo)->dwStandAloneSupported ))
  4230. {
  4231. //
  4232. //We are a stand alone server and
  4233. //the EAP type does not support
  4234. //stnadalone mode.
  4235. //
  4236. PeapEapInfoRemoveHeadNode ( ppEapInfo );
  4237. dwRetCode = NO_ERROR;
  4238. continue;
  4239. }
  4240. }
  4241. }
  4242. //
  4243. //
  4244. //
  4245. dwRetCode = PeapEapInfoReadSZ ( hkeyPeapType,
  4246. PEAP_REGVAL_FRIENDLYNAME,
  4247. &((*ppEapInfo)->lpwszFriendlyName )
  4248. );
  4249. if ( NO_ERROR != dwRetCode )
  4250. {
  4251. if ( ERROR_FILE_NOT_FOUND == dwRetCode )
  4252. {
  4253. PeapEapInfoRemoveHeadNode(ppEapInfo);
  4254. dwRetCode = NO_ERROR;
  4255. continue;
  4256. }
  4257. goto LDone;
  4258. }
  4259. dwRetCode = PeapEapInfoExpandSZ ( hkeyPeapType,
  4260. PEAP_REGVAL_CONFIGDLL,
  4261. &((*ppEapInfo)->lpwszConfigUIPath )
  4262. );
  4263. if ( NO_ERROR != dwRetCode )
  4264. {
  4265. if ( ERROR_FILE_NOT_FOUND == dwRetCode )
  4266. {
  4267. // it is fine to have no config stuff any more.
  4268. // We show the default identity
  4269. dwRetCode = NO_ERROR;
  4270. }
  4271. else
  4272. {
  4273. goto LDone;
  4274. }
  4275. }
  4276. dwRetCode = PeapEapInfoExpandSZ ( hkeyPeapType,
  4277. PEAP_REGVAL_IDENTITYDLL,
  4278. &((*ppEapInfo)->lpwszIdentityUIPath )
  4279. );
  4280. if ( NO_ERROR != dwRetCode )
  4281. {
  4282. if ( ERROR_FILE_NOT_FOUND == dwRetCode )
  4283. {
  4284. //
  4285. // It is fine if we dont have any identity UI. Peap
  4286. // will provide a default identity UI
  4287. //
  4288. dwRetCode = NO_ERROR;
  4289. }
  4290. else
  4291. {
  4292. goto LDone;
  4293. }
  4294. }
  4295. dwRetCode = PeapEapInfoExpandSZ ( hkeyPeapType,
  4296. PEAP_REGVAL_INTERACTIVEUIDLL,
  4297. &((*ppEapInfo)->lpwszInteractiveUIPath )
  4298. );
  4299. if ( NO_ERROR != dwRetCode )
  4300. {
  4301. if ( ERROR_FILE_NOT_FOUND == dwRetCode )
  4302. {
  4303. //It is fine if we dont have interactive UI
  4304. //
  4305. dwRetCode = NO_ERROR;
  4306. }
  4307. else
  4308. {
  4309. goto LDone;
  4310. }
  4311. }
  4312. dwRetCode = PeapEapInfoReadSZ ( hkeyPeapType,
  4313. PEAP_REGVAL_CONFIGCLSID,
  4314. &((*ppEapInfo)->lpwszConfigClsId )
  4315. );
  4316. if ( NO_ERROR != dwRetCode )
  4317. {
  4318. if ( ERROR_FILE_NOT_FOUND == dwRetCode )
  4319. {
  4320. //
  4321. // Missing config clsid is also fine
  4322. dwRetCode = NO_ERROR;
  4323. }
  4324. else
  4325. {
  4326. goto LDone;
  4327. }
  4328. }
  4329. dwRetCode = PeapEapInfoExpandSZ ( hkeyPeapType,
  4330. PEAP_REGVAL_PATH,
  4331. &((*ppEapInfo)->lpwszPath )
  4332. );
  4333. if ( NO_ERROR != dwRetCode )
  4334. {
  4335. //
  4336. // This is not acceptable. So this is a problem.
  4337. //
  4338. if ( ERROR_FILE_NOT_FOUND == dwRetCode )
  4339. {
  4340. PeapEapInfoRemoveHeadNode(ppEapInfo);
  4341. dwRetCode = NO_ERROR;
  4342. continue;
  4343. }
  4344. goto LDone;
  4345. }
  4346. //
  4347. // Now get the EAP INFO from the DLL.
  4348. //
  4349. (*ppEapInfo)->hEAPModule = LoadLibrary( ( (*ppEapInfo)->lpwszPath ) );
  4350. if ( NULL == (*ppEapInfo)->hEAPModule )
  4351. {
  4352. dwRetCode = GetLastError();
  4353. goto LDone;
  4354. }
  4355. pRasEapGetInfo = GetProcAddress( (*ppEapInfo)->hEAPModule ,
  4356. "RasEapGetInfo"
  4357. );
  4358. if ( pRasEapGetInfo == (FARPROC)NULL )
  4359. {
  4360. dwRetCode = GetLastError();
  4361. goto LDone;
  4362. }
  4363. (*ppEapInfo)->RasEapGetCredentials = (DWORD (*) (
  4364. DWORD,VOID *, VOID **))
  4365. GetProcAddress((*ppEapInfo)->hEAPModule,
  4366. "RasEapGetCredentials");
  4367. (*ppEapInfo)->PppEapInfo.dwSizeInBytes = sizeof( PPP_EAP_INFO );
  4368. dwRetCode = (DWORD) (*pRasEapGetInfo)( dwEapTypeId,
  4369. &((*ppEapInfo)->PppEapInfo) );
  4370. if ( dwRetCode != NO_ERROR )
  4371. {
  4372. goto LDone;
  4373. }
  4374. //
  4375. // Call initialize function here
  4376. //
  4377. if ( (*ppEapInfo)->PppEapInfo.RasEapInitialize )
  4378. {
  4379. (*ppEapInfo)->PppEapInfo.RasEapInitialize(TRUE);
  4380. }
  4381. RegCloseKey(hkeyPeapType);
  4382. hkeyPeapType = 0;
  4383. }
  4384. LDone:
  4385. if ( hkeyPeapType )
  4386. RegCloseKey(hkeyPeapType);
  4387. if ( hKeyPeap )
  4388. RegCloseKey(hKeyPeap);
  4389. if ( hKeyLM )
  4390. RegCloseKey(hKeyLM);
  4391. if ( NO_ERROR != dwRetCode )
  4392. {
  4393. PeapEapInfoFreeList( *ppEapInfo );
  4394. }
  4395. return dwRetCode;
  4396. }
  4397. DWORD
  4398. PeapEapInfoGetItemCount ( PPEAP_EAP_INFO pEapInfo )
  4399. {
  4400. DWORD dwCount = 0;
  4401. PPEAP_EAP_INFO pEapInfoLocal = pEapInfo;
  4402. while (pEapInfoLocal)
  4403. {
  4404. dwCount++;
  4405. pEapInfoLocal = pEapInfoLocal->pNext;
  4406. }
  4407. return dwCount;
  4408. }
  4409. DWORD
  4410. PeapEapInfoSetConnData ( PPEAP_EAP_INFO pEapInfo, PPEAP_CONN_PROP pPeapConnProp )
  4411. {
  4412. DWORD dwRetCode = NO_ERROR;
  4413. PEAP_ENTRY_CONN_PROPERTIES UNALIGNED *pEntryProp = NULL;
  4414. PPEAP_EAP_INFO pEapInfoLocal;
  4415. DWORD dwCount;
  4416. RTASSERT(NULL != pPeapConnProp);
  4417. RTASSERT(NULL != pEapInfo);
  4418. if ( !pPeapConnProp->dwNumPeapTypes )
  4419. {
  4420. goto LDone;
  4421. }
  4422. //
  4423. // Right now there is only one EAP Type in the list
  4424. // So it should not be a problem with this stuff now
  4425. pEntryProp = ( PEAP_ENTRY_CONN_PROPERTIES*)
  4426. ( pPeapConnProp->EapTlsConnProp.bData
  4427. + pPeapConnProp->EapTlsConnProp.dwNumHashes * sizeof(EAPTLS_HASH) +
  4428. sizeof(WCHAR)
  4429. );
  4430. pEapInfoLocal = pEapInfo;
  4431. while( pEapInfoLocal )
  4432. {
  4433. if ( pEapInfoLocal->dwTypeId == pEntryProp->dwEapTypeId )
  4434. {
  4435. if ( pEntryProp->dwSize > sizeof(PEAP_ENTRY_CONN_PROPERTIES))
  4436. {
  4437. pEapInfoLocal->pbClientConfigOrig = pEntryProp->bData;
  4438. pEapInfoLocal->dwClientConfigOrigSize = pEntryProp->dwSize -
  4439. sizeof(PEAP_ENTRY_CONN_PROPERTIES) + 1;
  4440. }
  4441. else
  4442. {
  4443. pEapInfoLocal->pbClientConfigOrig = NULL;
  4444. pEapInfoLocal->dwClientConfigOrigSize = 0;
  4445. }
  4446. break;
  4447. }
  4448. pEapInfoLocal = pEapInfoLocal->pNext;
  4449. }
  4450. #if 0
  4451. for ( dwCount = 0; dwCount < pPeapConnProp->dwNumPeapTypes; dwCount ++ )
  4452. {
  4453. pEntryProp = (PEAP_ENTRY_CONN_PROPERTIES UNALIGNED * )(((BYTE UNALIGNED *)&(pPeapConnProp->EapTlsConnProp)) +
  4454. pPeapConnProp->EapTlsConnProp.dwSize +
  4455. sizeof(PEAP_ENTRY_CONN_PROPERTIES) * dwCount);
  4456. pEapInfoLocal = pEapInfo;
  4457. while( pEapInfoLocal )
  4458. {
  4459. if ( pEapInfoLocal->dwTypeId == pEntryProp->dwEapTypeId )
  4460. {
  4461. if ( pEntryProp->dwSize > sizeof(PEAP_ENTRY_CONN_PROPERTIES))
  4462. {
  4463. pEapInfoLocal->pbClientConfigOrig = pEntryProp->bData;
  4464. pEapInfoLocal->dwClientConfigOrigSize = pEntryProp->dwSize -
  4465. sizeof(PEAP_ENTRY_CONN_PROPERTIES) + 1;
  4466. }
  4467. else
  4468. {
  4469. pEapInfoLocal->pbClientConfigOrig = NULL;
  4470. pEapInfoLocal->dwClientConfigOrigSize = 0;
  4471. }
  4472. break;
  4473. }
  4474. pEapInfoLocal = pEapInfoLocal->pNext;
  4475. }
  4476. }
  4477. #endif
  4478. LDone:
  4479. return dwRetCode;
  4480. }
  4481. DWORD PeapEapInfoInvokeIdentityUI ( HWND hWndParent,
  4482. PPEAP_EAP_INFO pEapInfo,
  4483. const WCHAR * pwszPhoneBook,
  4484. const WCHAR * pwszEntry,
  4485. PBYTE pbUserDataIn, // Got when using Winlogon
  4486. DWORD cbUserDataIn, // Got when using Winlogon
  4487. WCHAR** ppwszIdentityOut,
  4488. DWORD fFlags)
  4489. {
  4490. DWORD dwRetCode = NO_ERROR;
  4491. PBYTE pbUserDataNew = NULL;
  4492. DWORD dwSizeOfUserDataNew = 0;
  4493. RASEAPGETIDENTITY pIdenFunc = NULL;
  4494. RASEAPFREE pFreeFunc = NULL;
  4495. RTASSERT ( NULL != pEapInfo );
  4496. RTASSERT ( NULL != pEapInfo->lpwszIdentityUIPath );
  4497. pIdenFunc = (RASEAPGETIDENTITY)
  4498. GetProcAddress(pEapInfo->hEAPModule, "RasEapGetIdentity");
  4499. if ( pIdenFunc == NULL)
  4500. {
  4501. dwRetCode = GetLastError();
  4502. goto LDone;
  4503. }
  4504. pFreeFunc = (RASEAPFREE) GetProcAddress(pEapInfo->hEAPModule, "RasEapFreeMemory");
  4505. if ( pFreeFunc == NULL )
  4506. {
  4507. dwRetCode = GetLastError();
  4508. goto LDone;
  4509. }
  4510. dwRetCode = pIdenFunc ( pEapInfo->dwTypeId,
  4511. hWndParent,
  4512. fFlags,
  4513. pwszPhoneBook,
  4514. pwszEntry,
  4515. pEapInfo->pbClientConfigOrig,
  4516. pEapInfo->dwClientConfigOrigSize,
  4517. ( fFlags & RAS_EAP_FLAG_LOGON ?
  4518. pbUserDataIn:
  4519. pEapInfo->pbUserConfigOrig
  4520. ),
  4521. ( fFlags & RAS_EAP_FLAG_LOGON ?
  4522. cbUserDataIn:
  4523. pEapInfo->dwUserConfigOrigSize
  4524. ),
  4525. &pbUserDataNew,
  4526. &dwSizeOfUserDataNew,
  4527. ppwszIdentityOut
  4528. );
  4529. if ( NO_ERROR != dwRetCode )
  4530. {
  4531. goto LDone;
  4532. }
  4533. if ( pbUserDataNew &&
  4534. dwSizeOfUserDataNew
  4535. )
  4536. {
  4537. //
  4538. // we have new user data
  4539. //
  4540. pEapInfo->pbUserConfigNew = (PBYTE)LocalAlloc (LPTR, dwSizeOfUserDataNew );
  4541. if ( NULL == pEapInfo->pbUserConfigNew )
  4542. {
  4543. dwRetCode = ERROR_OUTOFMEMORY;
  4544. goto LDone;
  4545. }
  4546. CopyMemory ( pEapInfo->pbUserConfigNew,
  4547. pbUserDataNew,
  4548. dwSizeOfUserDataNew
  4549. );
  4550. pEapInfo->dwNewUserConfigSize = dwSizeOfUserDataNew;
  4551. }
  4552. LDone:
  4553. if ( pFreeFunc )
  4554. pFreeFunc( pbUserDataNew );
  4555. return dwRetCode;
  4556. }
  4557. DWORD PeapEapInfoInvokeClientConfigUI ( HWND hWndParent,
  4558. PPEAP_EAP_INFO pEapInfo,
  4559. DWORD fFlags)
  4560. {
  4561. DWORD dwRetCode = NO_ERROR;
  4562. RASEAPINVOKECONFIGUI pInvokeConfigUI;
  4563. RASEAPFREE pFreeConfigUIData;
  4564. PBYTE pConnDataOut = NULL;
  4565. DWORD dwConnDataOut = 0;
  4566. RTASSERT ( NULL != pEapInfo );
  4567. RTASSERT ( NULL != pEapInfo->lpwszConfigUIPath );
  4568. if ( !(pInvokeConfigUI =
  4569. (RASEAPINVOKECONFIGUI )GetProcAddress(
  4570. pEapInfo->hEAPModule, "RasEapInvokeConfigUI" ))
  4571. || !(pFreeConfigUIData =
  4572. (RASEAPFREE) GetProcAddress(
  4573. pEapInfo->hEAPModule, "RasEapFreeMemory" ))
  4574. )
  4575. {
  4576. dwRetCode = GetLastError();
  4577. goto LDone;
  4578. }
  4579. dwRetCode = pInvokeConfigUI ( pEapInfo->dwTypeId,
  4580. hWndParent,
  4581. fFlags,
  4582. (pEapInfo->pbNewClientConfig?
  4583. pEapInfo->pbNewClientConfig:
  4584. pEapInfo->pbClientConfigOrig
  4585. ),
  4586. (pEapInfo->pbNewClientConfig?
  4587. pEapInfo->dwNewClientConfigSize:
  4588. pEapInfo->dwClientConfigOrigSize
  4589. ),
  4590. &pConnDataOut,
  4591. &dwConnDataOut
  4592. );
  4593. if ( NO_ERROR != dwRetCode )
  4594. {
  4595. goto LDone;
  4596. }
  4597. if ( pConnDataOut && dwConnDataOut )
  4598. {
  4599. if ( pEapInfo->pbNewClientConfig )
  4600. {
  4601. LocalFree(pEapInfo->pbNewClientConfig );
  4602. pEapInfo->pbNewClientConfig = NULL;
  4603. pEapInfo->dwNewClientConfigSize = 0;
  4604. }
  4605. pEapInfo->pbNewClientConfig = (PBYTE)LocalAlloc ( LPTR, dwConnDataOut );
  4606. if ( NULL == pEapInfo->pbNewClientConfig )
  4607. {
  4608. dwRetCode = ERROR_OUTOFMEMORY;
  4609. goto LDone;
  4610. }
  4611. CopyMemory( pEapInfo->pbNewClientConfig,
  4612. pConnDataOut,
  4613. dwConnDataOut
  4614. );
  4615. pEapInfo->dwNewClientConfigSize = dwConnDataOut;
  4616. }
  4617. LDone:
  4618. if ( pConnDataOut )
  4619. pFreeConfigUIData(pConnDataOut);
  4620. return dwRetCode;
  4621. }
  4622. DWORD
  4623. OpenPeapRegistryKey(
  4624. IN WCHAR* pwszMachineName,
  4625. IN REGSAM samDesired,
  4626. OUT HKEY* phKeyPeap
  4627. )
  4628. {
  4629. HKEY hKeyLocalMachine = NULL;
  4630. BOOL fHKeyLocalMachineOpened = FALSE;
  4631. BOOL fHKeyPeapOpened = FALSE;
  4632. LONG lRet;
  4633. DWORD dwErr = NO_ERROR;
  4634. RTASSERT(NULL != phKeyPeap);
  4635. lRet = RegConnectRegistry(pwszMachineName, HKEY_LOCAL_MACHINE,
  4636. &hKeyLocalMachine);
  4637. if (ERROR_SUCCESS != lRet)
  4638. {
  4639. dwErr = lRet;
  4640. EapTlsTrace("RegConnectRegistry(%ws) failed and returned %d",
  4641. pwszMachineName ? pwszMachineName : L"NULL", dwErr);
  4642. goto LDone;
  4643. }
  4644. fHKeyLocalMachineOpened = TRUE;
  4645. lRet = RegOpenKeyEx(hKeyLocalMachine, PEAP_KEY_25, 0, samDesired,
  4646. phKeyPeap);
  4647. if (ERROR_SUCCESS != lRet)
  4648. {
  4649. dwErr = lRet;
  4650. EapTlsTrace("RegOpenKeyEx(%ws) failed and returned %d",
  4651. PEAP_KEY_25, dwErr);
  4652. goto LDone;
  4653. }
  4654. fHKeyPeapOpened = TRUE;
  4655. LDone:
  4656. if ( fHKeyPeapOpened
  4657. && (ERROR_SUCCESS != dwErr))
  4658. {
  4659. RegCloseKey(*phKeyPeap);
  4660. }
  4661. if (fHKeyLocalMachineOpened)
  4662. {
  4663. RegCloseKey(hKeyLocalMachine);
  4664. }
  4665. return(dwErr);
  4666. }
  4667. DWORD
  4668. PeapServerConfigDataIO(
  4669. IN BOOL fRead,
  4670. IN WCHAR* pwszMachineName,
  4671. IN OUT BYTE** ppData,
  4672. IN DWORD dwNumBytes
  4673. )
  4674. {
  4675. HKEY hKeyPeap;
  4676. PEAP_USER_PROP* pUserProp;
  4677. BOOL fHKeyPeapOpened = FALSE;
  4678. BYTE* pData = NULL;
  4679. DWORD dwSize = 0;
  4680. LONG lRet;
  4681. DWORD dwType;
  4682. DWORD dwErr = NO_ERROR;
  4683. RTASSERT(NULL != ppData);
  4684. dwErr = OpenPeapRegistryKey(pwszMachineName,
  4685. fRead ? KEY_READ : KEY_WRITE, &hKeyPeap);
  4686. if (ERROR_SUCCESS != dwErr)
  4687. {
  4688. goto LDone;
  4689. }
  4690. fHKeyPeapOpened = TRUE;
  4691. if (fRead)
  4692. {
  4693. lRet = RegQueryValueEx(hKeyPeap, PEAP_VAL_SERVER_CONFIG_DATA, NULL,
  4694. &dwType, NULL, &dwSize);
  4695. if ( (ERROR_SUCCESS != lRet)
  4696. || (REG_BINARY != dwType)
  4697. )
  4698. {
  4699. dwErr = PeapReadUserData( TRUE,NULL, 0, &pUserProp );
  4700. }
  4701. else
  4702. {
  4703. pData = LocalAlloc(LPTR, dwSize);
  4704. if (NULL == pData)
  4705. {
  4706. dwErr = GetLastError();
  4707. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  4708. goto LDone;
  4709. }
  4710. lRet = RegQueryValueEx(hKeyPeap, PEAP_VAL_SERVER_CONFIG_DATA,
  4711. NULL, &dwType, pData, &dwSize);
  4712. if (ERROR_SUCCESS != lRet)
  4713. {
  4714. dwErr = lRet;
  4715. EapTlsTrace("RegQueryValueEx(%ws) failed and returned %d",
  4716. EAPTLS_VAL_SERVER_CONFIG_DATA, dwErr);
  4717. goto LDone;
  4718. }
  4719. dwErr = PeapReadUserData(TRUE, pData, dwSize, &pUserProp);
  4720. }
  4721. *ppData = (PBYTE)pUserProp;
  4722. }
  4723. else
  4724. {
  4725. //
  4726. // Write the blob back out.
  4727. //
  4728. lRet = RegSetValueEx(hKeyPeap, PEAP_VAL_SERVER_CONFIG_DATA, 0,
  4729. REG_BINARY, *ppData, dwNumBytes);
  4730. if (ERROR_SUCCESS != lRet)
  4731. {
  4732. dwErr = lRet;
  4733. EapTlsTrace("RegSetValueEx(%ws) failed and returned %d",
  4734. PEAP_VAL_SERVER_CONFIG_DATA, dwErr);
  4735. goto LDone;
  4736. }
  4737. }
  4738. LDone:
  4739. if (fHKeyPeapOpened)
  4740. {
  4741. RegCloseKey(hKeyPeap);
  4742. }
  4743. LocalFree(pData);
  4744. return(dwErr);
  4745. }
  4746. DWORD
  4747. GetIdentityFromUserName (
  4748. LPWSTR lpszUserName,
  4749. LPWSTR lpszDomain,
  4750. LPWSTR * ppwszIdentity
  4751. )
  4752. {
  4753. DWORD dwRetCode = NO_ERROR;
  4754. DWORD dwNumBytes;
  4755. //domain+ user + '\' + null
  4756. dwNumBytes = (wcslen(lpszUserName) + wcslen(lpszDomain) + 1 + 1) * sizeof(WCHAR);
  4757. *ppwszIdentity = LocalAlloc ( LPTR, dwNumBytes);
  4758. if ( NULL == *ppwszIdentity )
  4759. {
  4760. dwRetCode = ERROR_OUTOFMEMORY;
  4761. goto LDone;
  4762. }
  4763. if ( *lpszDomain )
  4764. {
  4765. wcsncpy ( *ppwszIdentity, lpszDomain, DNLEN );
  4766. wcscat( *ppwszIdentity, L"\\");
  4767. }
  4768. wcscat ( *ppwszIdentity, lpszUserName );
  4769. LDone:
  4770. return dwRetCode;
  4771. }
  4772. //
  4773. // Format identity as domain\user. this is ok because our identity inside has not been
  4774. // tampered with
  4775. //
  4776. BOOL FFormatUserIdentity ( LPWSTR lpszUserNameRaw, LPWSTR * lppszUserNameFormatted )
  4777. {
  4778. BOOL fRetVal = TRUE;
  4779. LPTSTR s1 = NULL;
  4780. LPTSTR s2 = NULL;
  4781. RTASSERT(NULL != lpszUserNameRaw );
  4782. RTASSERT(NULL != lppszUserNameFormatted );
  4783. //Need to add 2 more chars. One for NULL and other for $ sign
  4784. *lppszUserNameFormatted = (LPTSTR )LocalAlloc ( LPTR, (wcslen(lpszUserNameRaw ) + 2)* sizeof(WCHAR) );
  4785. if ( NULL == *lppszUserNameFormatted )
  4786. {
  4787. return FALSE;
  4788. }
  4789. //find the first "@" and that is the identity of the machine.
  4790. //the second "." is the domain.
  4791. //check to see if there at least 2 dots. If not the raw string is
  4792. //the output string
  4793. s1 = wcschr ( lpszUserNameRaw, '@' );
  4794. if ( s1 )
  4795. {
  4796. //
  4797. // get the first .
  4798. //
  4799. s2 = wcschr ( s1, '.');
  4800. }
  4801. if ( s1 && s2 )
  4802. {
  4803. memcpy ( *lppszUserNameFormatted, s1+1, (s2-s1-1) * sizeof(WCHAR)) ;
  4804. memcpy ( (*lppszUserNameFormatted) + (s2-s1-1), L"\\", sizeof(WCHAR));
  4805. memcpy ( (*lppszUserNameFormatted)+ (s2-s1), lpszUserNameRaw, (s1-lpszUserNameRaw) * sizeof(WCHAR) );
  4806. }
  4807. else
  4808. {
  4809. wcscpy ( *lppszUserNameFormatted, lpszUserNameRaw );
  4810. }
  4811. return fRetVal;
  4812. }
  4813. VOID
  4814. GetMarshalledCredFromHash(
  4815. PBYTE pbHash,
  4816. DWORD cbHash,
  4817. CHAR *pszMarshalledCred,
  4818. DWORD cchCredSize)
  4819. {
  4820. CERT_CREDENTIAL_INFO CertCredInfo;
  4821. CHAR *pszMarshalledCredLocal = NULL;
  4822. CertCredInfo.cbSize = sizeof(CertCredInfo);
  4823. memcpy (CertCredInfo.rgbHashOfCert,
  4824. pbHash,
  4825. CERT_HASH_LENGTH
  4826. );
  4827. if (CredMarshalCredentialA(CertCredential,
  4828. (PVOID) &CertCredInfo,
  4829. &pszMarshalledCredLocal
  4830. ))
  4831. {
  4832. //
  4833. // Got Marshalled Credential from the cert
  4834. // Set it in the username field
  4835. //
  4836. ASSERT( NULL != pszMarshalledCredLocal );
  4837. (VOID) StringCchCopyA (pszMarshalledCred,
  4838. cchCredSize,
  4839. pszMarshalledCredLocal );
  4840. CredFree ( pszMarshalledCredLocal );
  4841. }
  4842. else
  4843. {
  4844. EapTlsTrace("CredMarshalCredential Failed with Error:0x%x",
  4845. GetLastError());
  4846. }
  4847. }
  4848. DWORD
  4849. GetCredentialsFromUserProperties(
  4850. EAPTLSCB *pEapTlsCb,
  4851. VOID **ppCredentials)
  4852. {
  4853. DWORD dwRetCode = ERROR_SUCCESS;
  4854. RASMAN_CREDENTIALS *pCreds = NULL;
  4855. //
  4856. // Note: Its important that this allocation is made from
  4857. // the process heap. Ppp engine needs to change otherwise.
  4858. //
  4859. pCreds = LocalAlloc(LPTR, sizeof(RASMAN_CREDENTIALS));
  4860. if(NULL == pCreds)
  4861. {
  4862. dwRetCode = GetLastError();
  4863. goto done;
  4864. }
  4865. if( (NULL != pEapTlsCb->pSavedPin)
  4866. && (NULL != pEapTlsCb->pSavedPin->pwszPin))
  4867. {
  4868. UNICODE_STRING UnicodeString;
  4869. //
  4870. // Decode the saved pin
  4871. //
  4872. UnicodeString.Length = pEapTlsCb->pSavedPin->usLength;
  4873. UnicodeString.MaximumLength = pEapTlsCb->pSavedPin->usMaximumLength;
  4874. UnicodeString.Buffer = pEapTlsCb->pSavedPin->pwszPin;
  4875. RtlRunDecodeUnicodeString(pEapTlsCb->pSavedPin->ucSeed,
  4876. &UnicodeString);
  4877. (VOID)StringCchCopyW(pCreds->wszPassword,
  4878. PWLEN,
  4879. pEapTlsCb->pSavedPin->pwszPin);
  4880. ZeroMemory(pEapTlsCb->pSavedPin->pwszPin,
  4881. wcslen(pEapTlsCb->pSavedPin->pwszPin) * sizeof(WCHAR));
  4882. LocalFree(pEapTlsCb->pSavedPin->pwszPin);
  4883. LocalFree(pEapTlsCb->pSavedPin);
  4884. pEapTlsCb->pSavedPin = NULL;
  4885. }
  4886. if(NULL != pEapTlsCb->pUserProp)
  4887. {
  4888. GetMarshalledCredFromHash(
  4889. pEapTlsCb->pUserProp->Hash.pbHash,
  4890. pEapTlsCb->pUserProp->Hash.cbHash,
  4891. pCreds->szUserName,
  4892. UNLEN);
  4893. }
  4894. pCreds->dwFlags = RASCRED_EAP;
  4895. done:
  4896. *ppCredentials = (VOID *) pCreds;
  4897. return dwRetCode;
  4898. }
  4899. DWORD
  4900. DwGetGlobalConfig(DWORD dwEapTypeId,
  4901. PBYTE *ppbData,
  4902. DWORD *pdwSizeofData)
  4903. {
  4904. DWORD dwErr = NO_ERROR;
  4905. if(PPP_EAP_TLS == dwEapTypeId)
  4906. {
  4907. dwErr = ServerConfigDataIO(
  4908. TRUE,
  4909. NULL,
  4910. ppbData,
  4911. 0);
  4912. if( (NO_ERROR != dwErr)
  4913. || (NULL == *ppbData))
  4914. {
  4915. goto done;
  4916. }
  4917. *pdwSizeofData = ((EAPTLS_USER_PROPERTIES *)*ppbData)->dwSize;
  4918. }
  4919. else
  4920. {
  4921. //
  4922. // Since peap is available only from .net, its fine to not
  4923. // call the underlying eap for now. This will get a v1 version
  4924. // of PEAP_USER_PROP and when InvokeServerConfigUI2 is called
  4925. // it will be automatically upgraded.
  4926. //
  4927. dwErr = PeapServerConfigDataIO(
  4928. TRUE,
  4929. NULL,
  4930. ppbData,
  4931. 0);
  4932. if( (NO_ERROR != dwErr)
  4933. || (NULL == *ppbData))
  4934. {
  4935. goto done;
  4936. }
  4937. *pdwSizeofData = ((PEAP_USER_PROP *)*ppbData)->dwSize;
  4938. }
  4939. done:
  4940. return dwErr;
  4941. }
  4942. /*
  4943. * Concat pAttr2 list to pAttr1 forming pAttrOut
  4944. */
  4945. DWORD
  4946. RasAuthAttributeConcat (
  4947. IN RAS_AUTH_ATTRIBUTE * pAttr1,
  4948. IN RAS_AUTH_ATTRIBUTE * pAttr2,
  4949. OUT RAS_AUTH_ATTRIBUTE ** ppAttrOut
  4950. )
  4951. {
  4952. DWORD dwRetCode = NO_ERROR;
  4953. RAS_AUTH_ATTRIBUTE * pAttrTemp = NULL;
  4954. DWORD dwIndex = 0;
  4955. EapTlsTrace("RasAuthAttributeConcat");
  4956. if (NULL != pAttr2)
  4957. {
  4958. for( dwIndex = 0;
  4959. pAttr2[dwIndex].raaType != raatMinimum;
  4960. dwIndex++ );
  4961. pAttrTemp = RasAuthAttributeCopyWithAlloc ( pAttr1, dwIndex );
  4962. if (NULL == pAttrTemp )
  4963. {
  4964. dwRetCode = GetLastError();
  4965. EapTlsTrace("RasAuthAttributeCopyWithAlloc failed and returned %d",
  4966. dwRetCode);
  4967. goto done;
  4968. }
  4969. for ( dwIndex =0;
  4970. pAttr2[dwIndex].raaType != raatMinimum;
  4971. dwIndex++ )
  4972. {
  4973. //
  4974. dwRetCode = RasAuthAttributeInsert( dwIndex ,
  4975. pAttrTemp,
  4976. pAttr2[dwIndex].raaType,
  4977. FALSE,
  4978. pAttr2[dwIndex].dwLength,
  4979. pAttr2[dwIndex].Value );
  4980. if ( dwRetCode != NO_ERROR )
  4981. {
  4982. EapTlsTrace ("RasAuthAttributeInsert failed and returned 0x%x", dwRetCode );
  4983. goto done;
  4984. }
  4985. }
  4986. }
  4987. else
  4988. {
  4989. pAttrTemp = RasAuthAttributeCopyWithAlloc ( pAttr1, 0 );
  4990. if (NULL == pAttrTemp )
  4991. {
  4992. dwRetCode = GetLastError();
  4993. EapTlsTrace("RasAuthAttributeCopyWithAlloc failed and returned %d",
  4994. dwRetCode);
  4995. goto done;
  4996. }
  4997. }
  4998. *ppAttrOut = pAttrTemp;
  4999. pAttrTemp = NULL;
  5000. done:
  5001. if ( NULL != pAttrTemp )
  5002. {
  5003. RasAuthAttributeDestroy(pAttrTemp);
  5004. }
  5005. return dwRetCode;
  5006. }
  5007. /*
  5008. This routine adds PEAP attributes to the
  5009. array of attribs to be returned back to
  5010. the caller.
  5011. */
  5012. DWORD
  5013. PeapAddContextAttributes(
  5014. IN PEAPCB* pPeapCb
  5015. )
  5016. {
  5017. DWORD dwErr = NO_ERROR;
  5018. RAS_AUTH_ATTRIBUTE * pAttrTemp = NULL;
  5019. EapTlsTrace("PeapAddContextAttributes");
  5020. pAttrTemp = RasAuthAttributeCopyWithAlloc ( pPeapCb->pTlsUserAttributes, 2 );
  5021. if (NULL == pAttrTemp )
  5022. {
  5023. dwErr = GetLastError();
  5024. EapTlsTrace("RasAuthAttributeCopyWithAlloc failed and returned %d",
  5025. dwErr);
  5026. goto LDone;
  5027. }
  5028. if ( pPeapCb->pTlsUserAttributes )
  5029. {
  5030. RasAuthAttributeDestroy ( pPeapCb->pTlsUserAttributes );
  5031. }
  5032. pPeapCb->pTlsUserAttributes = pAttrTemp;
  5033. //
  5034. // This is important so that we dont crash at End time.
  5035. //
  5036. pPeapCb->pEapTlsCB->pAttributes = pPeapCb->pTlsUserAttributes;
  5037. //
  5038. // Add Embedded Eap Type used and If the session was a fast reconnect
  5039. // attribs here. raatPEAPEmbeddedEAPTypeId and raatPEAPFastRoamedSession
  5040. //
  5041. dwErr = RasAuthAttributeInsert(
  5042. 0,
  5043. pPeapCb->pTlsUserAttributes,
  5044. raatPEAPFastRoamedSession,
  5045. FALSE,
  5046. sizeof(DWORD),
  5047. (PVOID)ULongToPtr(pPeapCb->fFastReconnectedSession));
  5048. if ( NO_ERROR != dwErr )
  5049. {
  5050. EapTlsTrace("RasAuthAttributeInsert failed and returned %d", dwErr);
  5051. goto LDone;
  5052. }
  5053. dwErr = RasAuthAttributeInsert(
  5054. 1,
  5055. pPeapCb->pTlsUserAttributes,
  5056. raatPEAPEmbeddedEAPTypeId,
  5057. FALSE,
  5058. sizeof(DWORD),
  5059. (PVOID)ULongToPtr(pPeapCb->pEapInfo->dwTypeId));
  5060. if ( NO_ERROR != dwErr )
  5061. {
  5062. EapTlsTrace("RasAuthAttributeInsert failed and returned %d", dwErr);
  5063. goto LDone;
  5064. }
  5065. LDone:
  5066. return(dwErr);
  5067. }
  5068. //
  5069. // Check to see if the cert has been renewed
  5070. // - Stolen from IIS Admin tool. Needs to be
  5071. // cleaned up in future releases.
  5072. //
  5073. #define CB_SHA_DIGEST_LEN 20
  5074. BOOL
  5075. CheckForCertificateRenewal(
  5076. DWORD dwProtocol,
  5077. PCCERT_CONTEXT pCertContext,
  5078. PCCERT_CONTEXT *ppNewCertificate)
  5079. {
  5080. BYTE rgbThumbprint[CB_SHA_DIGEST_LEN];
  5081. DWORD cbThumbprint = sizeof(rgbThumbprint);
  5082. CRYPT_HASH_BLOB HashBlob;
  5083. PCCERT_CONTEXT pNewCert;
  5084. BOOL fMachineCert;
  5085. PCRYPT_KEY_PROV_INFO pProvInfo = NULL;
  5086. DWORD cbSize;
  5087. HCERTSTORE hMyCertStore = 0;
  5088. BOOL fRenewed = FALSE;
  5089. HCERTSTORE g_hMyCertStore;
  5090. if(dwProtocol & SP_PROT_SERVERS)
  5091. {
  5092. fMachineCert = TRUE;
  5093. }
  5094. else
  5095. {
  5096. fMachineCert = FALSE;
  5097. }
  5098. //
  5099. // Loop through the linked list of renewed certificates, looking
  5100. // for the last one.
  5101. //
  5102. while(TRUE)
  5103. {
  5104. //
  5105. // Check for renewal property.
  5106. //
  5107. if(!CertGetCertificateContextProperty(pCertContext,
  5108. CERT_RENEWAL_PROP_ID,
  5109. rgbThumbprint,
  5110. &cbThumbprint))
  5111. {
  5112. // Certificate has not been renewed.
  5113. break;
  5114. }
  5115. //DebugLog((DEB_TRACE, "Certificate has renewal property\n"));
  5116. //
  5117. // Determine whether to look in the local machine MY store
  5118. // or the current user MY store.
  5119. //
  5120. if(!hMyCertStore)
  5121. {
  5122. if(CertGetCertificateContextProperty(pCertContext,
  5123. CERT_KEY_PROV_INFO_PROP_ID,
  5124. NULL,
  5125. &cbSize))
  5126. {
  5127. //SafeAllocaAllocate(pProvInfo, cbSize);
  5128. pProvInfo = (PCRYPT_KEY_PROV_INFO) LocalAlloc(LPTR,cbSize);
  5129. if(pProvInfo == NULL)
  5130. {
  5131. break;
  5132. }
  5133. if(CertGetCertificateContextProperty(pCertContext,
  5134. CERT_KEY_PROV_INFO_PROP_ID,
  5135. pProvInfo,
  5136. &cbSize))
  5137. {
  5138. if(pProvInfo->dwFlags & CRYPT_MACHINE_KEYSET)
  5139. {
  5140. fMachineCert = TRUE;
  5141. }
  5142. else
  5143. {
  5144. fMachineCert = FALSE;
  5145. }
  5146. }
  5147. if (pProvInfo)
  5148. {
  5149. LocalFree(pProvInfo);pProvInfo=NULL;
  5150. }
  5151. //SafeAllocaFree(pProvInfo);
  5152. }
  5153. }
  5154. //
  5155. // Open up the appropriate MY store, and attempt to find
  5156. // the new certificate.
  5157. //
  5158. if(!hMyCertStore)
  5159. {
  5160. if(fMachineCert)
  5161. {
  5162. g_hMyCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,X509_ASN_ENCODING,0,CERT_SYSTEM_STORE_LOCAL_MACHINE,L"MY");
  5163. if(g_hMyCertStore)
  5164. {
  5165. hMyCertStore = g_hMyCertStore;
  5166. }
  5167. }
  5168. else
  5169. {
  5170. hMyCertStore = CertOpenSystemStore(0, L"MY");
  5171. }
  5172. if(!hMyCertStore)
  5173. {
  5174. //DebugLog((DEB_ERROR, "Error 0x%x opening %s MY certificate store!\n", GetLastError(),(fMachineCert ? "local machine" : "current user") ));
  5175. break;
  5176. }
  5177. }
  5178. HashBlob.cbData = cbThumbprint;
  5179. HashBlob.pbData = rgbThumbprint;
  5180. pNewCert = CertFindCertificateInStore(hMyCertStore,
  5181. X509_ASN_ENCODING,
  5182. 0,
  5183. CERT_FIND_HASH,
  5184. &HashBlob,
  5185. NULL);
  5186. if(pNewCert == NULL)
  5187. {
  5188. // Certificate has been renewed, but the new certificate
  5189. // cannot be found.
  5190. //DebugLog((DEB_ERROR, "New certificate cannot be found: 0x%x\n", GetLastError()));
  5191. break;
  5192. }
  5193. //
  5194. // Return the new certificate, but first loop back and see if it's been
  5195. // renewed itself.
  5196. //
  5197. pCertContext = pNewCert;
  5198. *ppNewCertificate = pNewCert;
  5199. //DebugLog((DEB_TRACE, "Certificate has been renewed\n"));
  5200. fRenewed = TRUE;
  5201. }
  5202. //
  5203. // Cleanup.
  5204. //
  5205. if(hMyCertStore && hMyCertStore != g_hMyCertStore)
  5206. {
  5207. CertCloseStore(hMyCertStore, 0);
  5208. }
  5209. return fRenewed;
  5210. }
  5211. //
  5212. // Match public key in the certificate context with
  5213. // private key
  5214. //
  5215. DWORD MatchPublicPrivateKeys
  5216. (
  5217. PCCERT_CONTEXT pCertContext,
  5218. BOOL fSmartCardCert, // Is this a scard cert?
  5219. LPWSTR lpwszPin
  5220. )
  5221. {
  5222. DWORD dwRetCode = NO_ERROR;
  5223. CRYPT_KEY_PROV_INFO* pCryptKeyProvInfo = NULL;
  5224. //
  5225. // Provider context
  5226. //
  5227. HCRYPTPROV hProv = 0;
  5228. HCRYPTHASH hHash = 0;
  5229. HCRYPTKEY hPubKey = 0;
  5230. //
  5231. // Verification Context
  5232. //
  5233. HCRYPTPROV hProvVerification = 0;
  5234. BYTE bDataBuf[128] = {0};
  5235. DWORD dwDataLen = sizeof(bDataBuf)/sizeof(BYTE);
  5236. DWORD cbData = 0;
  5237. CHAR* pszPin = NULL;
  5238. DWORD count = 0;
  5239. DWORD dwSignLen =0;
  5240. PBYTE pbSignature = NULL;
  5241. EapTlsTrace ("MatchPublicPrivateKeys");
  5242. // Following steps are followed to match public and
  5243. // private keys:
  5244. //
  5245. // Create a random blob of data
  5246. // Open the crypto context for the cert context passed in
  5247. // Export the public key blob from the cert and save it
  5248. // Create Hash
  5249. // Hash Random Data
  5250. // Sign Hash. And save signature
  5251. // Create a new verification crypto context
  5252. // Import public key got from the cert
  5253. // Create a new hash
  5254. // Hash Random Data
  5255. // Verify the signature to make sure that public key
  5256. // matches private key.
  5257. //
  5258. if (!CertGetCertificateContextProperty(
  5259. pCertContext,
  5260. CERT_KEY_PROV_INFO_PROP_ID,
  5261. NULL,
  5262. &cbData))
  5263. {
  5264. dwRetCode = GetLastError();
  5265. EapTlsTrace("CertGetCertificateContextProperty failed: 0x%x", dwRetCode);
  5266. goto LDone;
  5267. }
  5268. pCryptKeyProvInfo = LocalAlloc(LPTR, cbData);
  5269. if (NULL == pCryptKeyProvInfo)
  5270. {
  5271. dwRetCode = GetLastError();
  5272. EapTlsTrace("Out of memory");
  5273. goto LDone;
  5274. }
  5275. if (!CertGetCertificateContextProperty(
  5276. pCertContext,
  5277. CERT_KEY_PROV_INFO_PROP_ID,
  5278. pCryptKeyProvInfo,
  5279. &cbData))
  5280. {
  5281. dwRetCode = GetLastError();
  5282. EapTlsTrace("CertGetCertificateContextProperty failed: 0x%x", dwRetCode);
  5283. goto LDone;
  5284. }
  5285. if (!CryptAcquireContext(
  5286. &hProv,
  5287. pCryptKeyProvInfo->pwszContainerName,
  5288. pCryptKeyProvInfo->pwszProvName,
  5289. pCryptKeyProvInfo->dwProvType,
  5290. (pCryptKeyProvInfo->dwFlags &
  5291. ~CERT_SET_KEY_PROV_HANDLE_PROP_ID) |
  5292. CRYPT_SILENT))
  5293. {
  5294. dwRetCode = GetLastError();
  5295. EapTlsTrace("CryptAcquireContext failed: 0x%x", dwRetCode);
  5296. goto LDone;
  5297. }
  5298. //
  5299. // set the pin with prov param if needed
  5300. //
  5301. if ( fSmartCardCert && lpwszPin )
  5302. {
  5303. count = WideCharToMultiByte(
  5304. CP_UTF8,
  5305. 0,
  5306. lpwszPin,
  5307. -1,
  5308. NULL,
  5309. 0,
  5310. NULL,
  5311. NULL);
  5312. if (0 == count)
  5313. {
  5314. dwRetCode = GetLastError();
  5315. EapTlsTrace("WideCharToMultiByte failed: %d", dwRetCode);
  5316. goto LDone;
  5317. }
  5318. pszPin = LocalAlloc(LPTR, count);
  5319. if (NULL == pszPin)
  5320. {
  5321. dwRetCode = GetLastError();
  5322. EapTlsTrace("LocalAlloc failed: 0x%x", dwRetCode);
  5323. goto LDone;
  5324. }
  5325. count = WideCharToMultiByte(
  5326. CP_UTF8,
  5327. 0,
  5328. lpwszPin,
  5329. -1,
  5330. pszPin,
  5331. count,
  5332. NULL,
  5333. NULL);
  5334. if (0 == count)
  5335. {
  5336. dwRetCode = GetLastError();
  5337. EapTlsTrace("WideCharToMultiByte failed: %d", dwRetCode);
  5338. goto LDone;
  5339. }
  5340. if (!CryptSetProvParam(
  5341. hProv,
  5342. PP_KEYEXCHANGE_PIN,
  5343. pszPin,
  5344. 0))
  5345. {
  5346. dwRetCode = GetLastError();
  5347. EapTlsTrace("CryptSetProvParam failed: 0x%x", dwRetCode);
  5348. if ( dwRetCode != SCARD_W_WRONG_CHV
  5349. && dwRetCode != SCARD_E_INVALID_CHV
  5350. )
  5351. {
  5352. dwRetCode = SCARD_E_INVALID_CHV;
  5353. }
  5354. goto LDone;
  5355. }
  5356. }
  5357. //
  5358. // Acquire the verification context
  5359. //
  5360. if ( !CryptAcquireContext(
  5361. &hProvVerification,
  5362. NULL,
  5363. NULL,
  5364. PROV_RSA_FULL,
  5365. CRYPT_VERIFYCONTEXT| CRYPT_SILENT
  5366. )
  5367. )
  5368. {
  5369. dwRetCode = GetLastError();
  5370. EapTlsTrace("CryptAcquireContext for verification failed: 0x%x", dwRetCode);
  5371. goto LDone;
  5372. }
  5373. if (!CryptGenRandom ( hProvVerification,
  5374. dwDataLen,
  5375. bDataBuf
  5376. )
  5377. )
  5378. {
  5379. dwRetCode = GetLastError();
  5380. EapTlsTrace ("CryptGenRandom failed: 0x%x", dwRetCode );
  5381. goto LDone;
  5382. }
  5383. if ( !CryptCreateHash( hProv,
  5384. CALG_MD5,
  5385. 0,
  5386. 0,
  5387. &hHash
  5388. )
  5389. )
  5390. {
  5391. dwRetCode = GetLastError();
  5392. EapTlsTrace("CryptCreateHash failed: 0x%x", dwRetCode );
  5393. goto LDone;
  5394. }
  5395. if(!CryptHashData(hHash,
  5396. bDataBuf,
  5397. dwDataLen,
  5398. 0
  5399. )
  5400. )
  5401. {
  5402. dwRetCode = GetLastError();
  5403. EapTlsTrace("CryptHashData failed: 0x%x", dwRetCode );
  5404. goto LDone;
  5405. }
  5406. if(!CryptSignHash(hHash,
  5407. AT_KEYEXCHANGE,
  5408. NULL,
  5409. 0,
  5410. NULL,
  5411. &dwSignLen)
  5412. )
  5413. {
  5414. dwRetCode = GetLastError();
  5415. EapTlsTrace("CryptSignHash failed: 0x%x", dwRetCode );
  5416. goto LDone;
  5417. }
  5418. //--------------------------------------------------------------------
  5419. // Allocate memory for the signature buffer.
  5420. pbSignature = (BYTE *)LocalAlloc(LPTR, dwSignLen);
  5421. if (NULL == pCryptKeyProvInfo)
  5422. {
  5423. dwRetCode = GetLastError();
  5424. EapTlsTrace("Out of memory");
  5425. goto LDone;
  5426. }
  5427. if(! CryptSignHash( hHash,
  5428. AT_KEYEXCHANGE,
  5429. NULL,
  5430. 0,
  5431. pbSignature,
  5432. &dwSignLen)
  5433. )
  5434. {
  5435. dwRetCode = GetLastError();
  5436. EapTlsTrace("CryptSignHash failed: 0x%x", dwRetCode );
  5437. goto LDone;
  5438. }
  5439. if (hHash)
  5440. {
  5441. CryptDestroyHash(hHash);
  5442. hHash = 0;
  5443. }
  5444. //
  5445. // Import the public key info from the cert into
  5446. // the verification context
  5447. //
  5448. if ( !CryptImportPublicKeyInfo ( hProvVerification,
  5449. X509_ASN_ENCODING|PKCS_7_ASN_ENCODING,
  5450. &(pCertContext->pCertInfo->SubjectPublicKeyInfo),
  5451. &hPubKey
  5452. )
  5453. )
  5454. {
  5455. dwRetCode = GetLastError();
  5456. EapTlsTrace("CryptImportPublicKeyInfo failed: 0x%x", dwRetCode );
  5457. goto LDone;
  5458. }
  5459. if ( !CryptCreateHash(hProvVerification,
  5460. CALG_MD5,
  5461. 0,
  5462. 0,
  5463. &hHash )
  5464. )
  5465. {
  5466. dwRetCode = GetLastError();
  5467. EapTlsTrace("CryptCreateHash on verification context failed: 0x%x", dwRetCode );
  5468. goto LDone;
  5469. }
  5470. if(!CryptHashData(hHash,
  5471. bDataBuf,
  5472. dwDataLen,
  5473. 0
  5474. )
  5475. )
  5476. {
  5477. dwRetCode = GetLastError();
  5478. EapTlsTrace("CryptHashData failed: 0x%x", dwRetCode );
  5479. goto LDone;
  5480. }
  5481. if(!CryptVerifySignature(hHash,
  5482. pbSignature,
  5483. dwSignLen,
  5484. hPubKey,
  5485. NULL,
  5486. 0)
  5487. )
  5488. {
  5489. dwRetCode = GetLastError();
  5490. EapTlsTrace("CryptVerifySignature failed: 0x%x", dwRetCode );
  5491. goto LDone;
  5492. }
  5493. // Yohoo...public and private keys match...
  5494. LDone:
  5495. if ( pszPin )
  5496. LocalFree(pszPin);
  5497. if ( pCryptKeyProvInfo )
  5498. LocalFree (pCryptKeyProvInfo);
  5499. if ( pbSignature )
  5500. LocalFree( pbSignature );
  5501. if ( hHash )
  5502. CryptDestroyHash(hHash);
  5503. if ( hPubKey )
  5504. CryptDestroyKey(hPubKey);
  5505. if ( hProv )
  5506. CryptReleaseContext(hProv,0);
  5507. if ( hProvVerification )
  5508. CryptReleaseContext(hProvVerification ,0);
  5509. return dwRetCode;
  5510. }
  5511. //
  5512. // Set the type attributes in the PEAP CONTROL BLOCK
  5513. // filter out the MPPE keys if any returned by the embedded
  5514. // EAP method.
  5515. //
  5516. DWORD
  5517. PeapSetTypeUserAttributes (
  5518. IN PEAPCB * pPeapCb,
  5519. RAS_AUTH_ATTRIBUTE * pAttr)
  5520. {
  5521. DWORD dwRetCode = NO_ERROR;
  5522. DWORD dwIndex = 0;
  5523. DWORD dwAttributeCount = 0;
  5524. DWORD dwAttribIndex;
  5525. EapTlsTrace("PeapSetTypeUserAttributes");
  5526. if ( pAttr )
  5527. {
  5528. for( dwIndex = 0;
  5529. pAttr[dwIndex].raaType != raatMinimum;
  5530. dwIndex++ )
  5531. {
  5532. if ( pAttr[dwIndex].raaType == raatVendorSpecific )
  5533. {
  5534. //Check to see if this is MPPE Key attribute
  5535. if ( ((PBYTE)(pAttr[dwIndex].Value))[4] != 16 &&
  5536. ((PBYTE)(pAttr[dwIndex].Value))[4] != 17
  5537. )
  5538. {
  5539. dwAttributeCount++;
  5540. }
  5541. }
  5542. else
  5543. {
  5544. dwAttributeCount++;
  5545. }
  5546. }
  5547. pPeapCb->pTypeUserAttributes =
  5548. RasAuthAttributeCreate ( dwAttributeCount );
  5549. if (NULL == pPeapCb->pTypeUserAttributes )
  5550. {
  5551. dwRetCode = GetLastError();
  5552. EapTlsTrace("RasAutAttributeCreate failed and returned %d",
  5553. dwRetCode);
  5554. goto done;
  5555. }
  5556. dwAttribIndex = 0;
  5557. for ( dwIndex =0;
  5558. pAttr[dwIndex].raaType != raatMinimum;
  5559. dwIndex++ )
  5560. {
  5561. //
  5562. if ( pAttr[dwIndex].raaType == raatVendorSpecific )
  5563. {
  5564. if ( ((PBYTE)(pAttr[dwIndex].Value))[4] != 16 &&
  5565. ((PBYTE)(pAttr[dwIndex].Value))[4] != 17
  5566. )
  5567. {
  5568. dwRetCode = RasAuthAttributeInsert( dwAttribIndex ,
  5569. pPeapCb->pTypeUserAttributes,
  5570. pAttr[dwIndex].raaType,
  5571. FALSE,
  5572. pAttr[dwIndex].dwLength,
  5573. pAttr[dwIndex].Value );
  5574. if ( dwRetCode != NO_ERROR )
  5575. {
  5576. EapTlsTrace ("RasAuthAttributeInsert failed and returned 0x%x", dwRetCode );
  5577. goto done;
  5578. }
  5579. dwAttribIndex ++;
  5580. }
  5581. }
  5582. else
  5583. {
  5584. dwRetCode = RasAuthAttributeInsert( dwAttribIndex ,
  5585. pPeapCb->pTypeUserAttributes,
  5586. pAttr[dwIndex].raaType,
  5587. FALSE,
  5588. pAttr[dwIndex].dwLength,
  5589. pAttr[dwIndex].Value );
  5590. if ( dwRetCode != NO_ERROR )
  5591. {
  5592. EapTlsTrace ("RasAuthAttributeInsert failed and returned 0x%x", dwRetCode );
  5593. goto done;
  5594. }
  5595. dwAttribIndex ++;
  5596. }
  5597. }
  5598. }
  5599. done:
  5600. if ( NO_ERROR != dwRetCode )
  5601. {
  5602. if ( pPeapCb->pTypeUserAttributes )
  5603. {
  5604. RasAuthAttributeDestroy ( pPeapCb->pTypeUserAttributes );
  5605. pPeapCb->pTypeUserAttributes = NULL;
  5606. }
  5607. }
  5608. return dwRetCode;
  5609. }