Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5315 lines
139 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. #define SECURITY_WIN32
  19. #include <security.h> // For GetUserNameExA, CredHandle
  20. #include <schannel.h>
  21. #include <sspi.h> // For CredHandle
  22. #include <wincrypt.h> // Required by sclogon.h
  23. #include <winscard.h> // For SCardListReadersA
  24. #include <sclogon.h> // For ScHelperGetCertFromLogonInfo
  25. #include <cryptui.h>
  26. #include <stdlib.h>
  27. #include <raserror.h>
  28. #include <commctrl.h>
  29. #include <eaptypeid.h>
  30. #include <eaptls.h>
  31. #include <wincred.h>
  32. #define STRSAFE_NO_DEPRECATE
  33. #include <strsafe.h>
  34. extern CRITICAL_SECTION g_csProtectCachedCredentials;
  35. extern BOOL g_fCriticalSectionInitialized;
  36. /*
  37. Returns:
  38. void
  39. Notes:
  40. Used for printing EAP TLS trace statements.
  41. */
  42. VOID
  43. EapTlsTrace(
  44. IN CHAR* Format,
  45. ...
  46. )
  47. {
  48. va_list arglist;
  49. RTASSERT(NULL != Format);
  50. va_start(arglist, Format);
  51. TraceVprintfExA(g_dwEapTlsTraceId,
  52. 0x00010000 | TRACE_USE_MASK | TRACE_USE_MSEC,
  53. Format,
  54. arglist);
  55. va_end(arglist);
  56. }
  57. HINSTANCE
  58. GetResouceDLLHInstance(
  59. VOID
  60. )
  61. {
  62. static HINSTANCE hResourceModule = NULL;
  63. EapTlsTrace("GetResouceDLLHInstance");
  64. if ( !hResourceModule )
  65. {
  66. //
  67. // Change the name of this DLL as required for each service pack
  68. //
  69. hResourceModule = LoadLibrary ( L"xpsp1res.dll");
  70. if ( NULL == hResourceModule )
  71. {
  72. EapTlsTrace("LoadLibraryEx failed and returned %d",GetLastError());
  73. }
  74. }
  75. return(hResourceModule);
  76. }
  77. #if WINVER > 0x0500
  78. DWORD CheckCallerIdentity ( HANDLE hWVTStateData )
  79. {
  80. DWORD dwRetCode = ERROR_ACCESS_DENIED;
  81. PCRYPT_PROVIDER_DATA pProvData = NULL;
  82. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  83. PCRYPT_PROVIDER_SGNR pProvSigner = NULL;
  84. CERT_CHAIN_POLICY_PARA chainpolicyparams;
  85. CERT_CHAIN_POLICY_STATUS chainpolicystatus;
  86. if (!(pProvData = WTHelperProvDataFromStateData(hWVTStateData)))
  87. {
  88. goto done;
  89. }
  90. if (!(pProvSigner = WTHelperGetProvSignerFromChain(pProvData, 0, FALSE, 0)))
  91. {
  92. goto done;
  93. }
  94. chainpolicyparams.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
  95. //
  96. //
  97. // We do want to test for microsoft test root flags. and dont care
  98. // for revocation flags...
  99. //
  100. chainpolicyparams.dwFlags = CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG |
  101. CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG |
  102. CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS;
  103. pChainContext = pProvSigner->pChainContext;
  104. if (!CertVerifyCertificateChainPolicy (
  105. CERT_CHAIN_POLICY_MICROSOFT_ROOT,
  106. pChainContext,
  107. &chainpolicyparams,
  108. &chainpolicystatus))
  109. {
  110. goto done;
  111. }
  112. else
  113. {
  114. if ( S_OK == chainpolicystatus.dwError )
  115. {
  116. dwRetCode = NO_ERROR;
  117. }
  118. else
  119. {
  120. //
  121. // Check the base policy to see if this
  122. // is a Microsoft test root
  123. //
  124. if (!CertVerifyCertificateChainPolicy (
  125. CERT_CHAIN_POLICY_BASE,
  126. pChainContext,
  127. &chainpolicyparams,
  128. &chainpolicystatus))
  129. {
  130. goto done;
  131. }
  132. else
  133. {
  134. if ( S_OK == chainpolicystatus.dwError )
  135. {
  136. dwRetCode = NO_ERROR;
  137. }
  138. }
  139. }
  140. }
  141. done:
  142. return dwRetCode;
  143. }
  144. /*
  145. */
  146. DWORD VerifyCallerTrust ( void * callersAddress )
  147. {
  148. DWORD dwRetCode = NO_ERROR;
  149. HRESULT hr = S_OK;
  150. WINTRUST_DATA wtData;
  151. WINTRUST_FILE_INFO wtFileInfo;
  152. WINTRUST_CATALOG_INFO wtCatalogInfo;
  153. BOOL fRet = FALSE;
  154. HCATADMIN hCATAdmin = NULL;
  155. static BOOL fOKToUseTLS = FALSE;
  156. GUID guidPublishedSoftware = WINTRUST_ACTION_GENERIC_VERIFY_V2;
  157. //
  158. // Following GUID is Mirosoft's Catalog System Root
  159. //
  160. GUID guidCatSystemRoot = { 0xf750e6c3, 0x38ee, 0x11d1,{ 0x85, 0xe5, 0x0, 0xc0, 0x4f, 0xc2, 0x95, 0xee } };
  161. HCATINFO hCATInfo = NULL;
  162. CATALOG_INFO CatInfo;
  163. HANDLE hFile = INVALID_HANDLE_VALUE;
  164. BYTE bHash[40];
  165. DWORD cbHash = 40;
  166. MEMORY_BASIC_INFORMATION mbi;
  167. SIZE_T nbyte;
  168. DWORD nchar;
  169. wchar_t callersModule[MAX_PATH + 1];
  170. if ( fOKToUseTLS )
  171. {
  172. goto done;
  173. }
  174. EapTlsTrace("Verifying caller...");
  175. nbyte = VirtualQuery(
  176. callersAddress,
  177. &mbi,
  178. sizeof(mbi)
  179. );
  180. if (nbyte < sizeof(mbi))
  181. {
  182. dwRetCode = ERROR_ACCESS_DENIED;
  183. EapTlsTrace("Unauthorized use of TLS attempted");
  184. goto done;
  185. }
  186. nchar = GetModuleFileNameW(
  187. (HMODULE)(mbi.AllocationBase),
  188. callersModule,
  189. MAX_PATH
  190. );
  191. if (nchar == 0)
  192. {
  193. dwRetCode = GetLastError();
  194. EapTlsTrace("Unauthorized use of TLS attempted");
  195. goto done;
  196. }
  197. //
  198. //
  199. // Try and see if WinVerifyTrust will verify
  200. // the signature as a standalone file
  201. //
  202. //
  203. ZeroMemory ( &wtData, sizeof(wtData) );
  204. ZeroMemory ( &wtFileInfo, sizeof(wtFileInfo) );
  205. wtData.cbStruct = sizeof(wtData);
  206. wtData.dwUIChoice = WTD_UI_NONE;
  207. wtData.fdwRevocationChecks = WTD_REVOKE_NONE;
  208. wtData.dwStateAction = WTD_STATEACTION_VERIFY;
  209. wtData.dwUnionChoice = WTD_CHOICE_FILE;
  210. wtData.pFile = &wtFileInfo;
  211. wtFileInfo.cbStruct = sizeof( wtFileInfo );
  212. wtFileInfo.pcwszFilePath = callersModule;
  213. hr = WinVerifyTrust ( NULL,
  214. &guidPublishedSoftware,
  215. &wtData
  216. );
  217. if ( ERROR_SUCCESS == hr )
  218. {
  219. //
  220. // Check to see if this is indeed microsoft
  221. // signed caller
  222. //
  223. dwRetCode = CheckCallerIdentity( wtData.hWVTStateData);
  224. wtData.dwStateAction = WTD_STATEACTION_CLOSE;
  225. WinVerifyTrust(NULL, &guidPublishedSoftware, &wtData);
  226. goto done;
  227. }
  228. wtData.dwStateAction = WTD_STATEACTION_CLOSE;
  229. WinVerifyTrust(NULL, &guidPublishedSoftware, &wtData);
  230. //
  231. // We did not find the file was signed.
  232. // So check the system catalog to see if
  233. // the file is in the catalog and the catalog
  234. // is signed
  235. //
  236. //
  237. // Open the file
  238. //
  239. hFile = CreateFile ( callersModule,
  240. GENERIC_READ,
  241. FILE_SHARE_READ,
  242. NULL,
  243. OPEN_EXISTING,
  244. FILE_ATTRIBUTE_NORMAL,
  245. NULL
  246. );
  247. if ( INVALID_HANDLE_VALUE == hFile )
  248. {
  249. dwRetCode = GetLastError();
  250. goto done;
  251. }
  252. fRet = CryptCATAdminAcquireContext( &hCATAdmin,
  253. &guidCatSystemRoot,
  254. 0
  255. );
  256. if ( !fRet )
  257. {
  258. dwRetCode = GetLastError();
  259. goto done;
  260. }
  261. //
  262. // Get the hash of the file here
  263. //
  264. fRet = CryptCATAdminCalcHashFromFileHandle ( hFile,
  265. &cbHash,
  266. bHash,
  267. 0
  268. );
  269. if ( !fRet )
  270. {
  271. dwRetCode = GetLastError();
  272. goto done;
  273. }
  274. ZeroMemory(&CatInfo, sizeof(CatInfo));
  275. CatInfo.cbStruct = sizeof(CatInfo);
  276. ZeroMemory( &wtCatalogInfo, sizeof(wtCatalogInfo) );
  277. wtData.dwUnionChoice = WTD_CHOICE_CATALOG;
  278. wtData.dwStateAction = WTD_STATEACTION_VERIFY;
  279. wtData.pCatalog = &wtCatalogInfo;
  280. wtCatalogInfo.cbStruct = sizeof(wtCatalogInfo);
  281. wtCatalogInfo.hMemberFile = hFile;
  282. wtCatalogInfo.pbCalculatedFileHash = bHash;
  283. wtCatalogInfo.cbCalculatedFileHash = cbHash;
  284. while ( ( hCATInfo = CryptCATAdminEnumCatalogFromHash ( hCATAdmin,
  285. bHash,
  286. cbHash,
  287. 0,
  288. &hCATInfo
  289. )
  290. )
  291. )
  292. {
  293. if (!(CryptCATCatalogInfoFromContext(hCATInfo, &CatInfo, 0)))
  294. {
  295. // should do something (??)
  296. continue;
  297. }
  298. wtCatalogInfo.pcwszCatalogFilePath = CatInfo.wszCatalogFile;
  299. hr = WinVerifyTrust ( NULL,
  300. &guidPublishedSoftware,
  301. &wtData
  302. );
  303. if ( ERROR_SUCCESS == hr )
  304. {
  305. //
  306. // Verify that this file is trusted
  307. //
  308. dwRetCode = CheckCallerIdentity( wtData.hWVTStateData);
  309. wtData.dwStateAction = WTD_STATEACTION_CLOSE;
  310. WinVerifyTrust(NULL, &guidPublishedSoftware, &wtData);
  311. goto done;
  312. }
  313. }
  314. //
  315. // File not found in any of the catalogs
  316. //
  317. dwRetCode = ERROR_ACCESS_DENIED;
  318. done:
  319. if ( hCATInfo )
  320. {
  321. CryptCATAdminReleaseCatalogContext( hCATAdmin, hCATInfo, 0 );
  322. }
  323. if ( hCATAdmin )
  324. {
  325. CryptCATAdminReleaseContext( hCATAdmin, 0 );
  326. }
  327. if ( hFile )
  328. {
  329. CloseHandle(hFile);
  330. }
  331. if ( NO_ERROR == dwRetCode )
  332. fOKToUseTLS = TRUE;
  333. return dwRetCode;
  334. }
  335. #endif
  336. /*
  337. Returns:
  338. NO_ERROR: iff Success
  339. Notes:
  340. TraceRegister, RouterLogRegister, etc.
  341. */
  342. extern g_CachedCreds[];
  343. DWORD
  344. EapTlsInitialize2(
  345. IN BOOL fInitialize,
  346. IN BOOL fUI
  347. )
  348. {
  349. static DWORD dwRefCount = 0;
  350. DWORD dwRetCode = NO_ERROR;
  351. if (fInitialize)
  352. {
  353. if (0 == dwRefCount)
  354. {
  355. ZeroMemory ( &(g_CachedCreds[0]),
  356. sizeof(g_CachedCreds[0]) );
  357. ZeroMemory ( &(g_CachedCreds[1]),
  358. sizeof(g_CachedCreds[0]) );
  359. if (fUI)
  360. {
  361. g_dwEapTlsTraceId = TraceRegister(L"RASTLSUI");
  362. //
  363. // Initialize the common controls library for the controls we use.
  364. //
  365. {
  366. INITCOMMONCONTROLSEX icc;
  367. icc.dwSize = sizeof(icc);
  368. icc.dwICC = ICC_LISTVIEW_CLASSES;
  369. InitCommonControlsEx (&icc);
  370. }
  371. }
  372. else
  373. {
  374. g_dwEapTlsTraceId = TraceRegister(L"RASTLS");
  375. }
  376. InitializeCriticalSection( &g_csProtectCachedCredentials );
  377. g_fCriticalSectionInitialized = TRUE;
  378. EapTlsTrace("EapTlsInitialize2");
  379. }
  380. dwRefCount++;
  381. }
  382. else
  383. {
  384. dwRefCount--;
  385. if (0 == dwRefCount)
  386. {
  387. EapTlsTrace("EapTls[Un]Initialize2");
  388. if (INVALID_TRACEID != g_dwEapTlsTraceId)
  389. {
  390. TraceDeregister(g_dwEapTlsTraceId);
  391. g_dwEapTlsTraceId = INVALID_TRACEID;
  392. }
  393. if ( g_fCriticalSectionInitialized )
  394. {
  395. DeleteCriticalSection( &g_csProtectCachedCredentials );
  396. g_fCriticalSectionInitialized = FALSE;
  397. }
  398. FreeScardDlgDll();
  399. }
  400. }
  401. return(dwRetCode);
  402. }
  403. /*
  404. Returns:
  405. NO_ERROR: iff Success
  406. Notes:
  407. */
  408. DWORD
  409. EapTlsInitialize(
  410. IN BOOL fInitialize
  411. )
  412. {
  413. return EapTlsInitialize2(fInitialize, FALSE /* fUI */);
  414. }
  415. /*
  416. Returns:
  417. Notes:
  418. Obfuscate PIN in place to foil memory scans for PINs.
  419. */
  420. VOID
  421. EncodePin(
  422. IN EAPTLS_USER_PROPERTIES* pUserProp
  423. )
  424. {
  425. UNICODE_STRING UnicodeString;
  426. UCHAR ucSeed = 0;
  427. RtlInitUnicodeString(&UnicodeString, pUserProp->pwszPin);
  428. RtlRunEncodeUnicodeString(&ucSeed, &UnicodeString);
  429. pUserProp->usLength = UnicodeString.Length;
  430. pUserProp->usMaximumLength = UnicodeString.MaximumLength;
  431. pUserProp->ucSeed = ucSeed;
  432. }
  433. /*
  434. Returns:
  435. Notes:
  436. */
  437. VOID
  438. DecodePin(
  439. IN EAPTLS_USER_PROPERTIES* pUserProp
  440. )
  441. {
  442. UNICODE_STRING UnicodeString;
  443. UnicodeString.Length = pUserProp->usLength;
  444. UnicodeString.MaximumLength = pUserProp->usMaximumLength;
  445. UnicodeString.Buffer = pUserProp->pwszPin;
  446. RtlRunDecodeUnicodeString(pUserProp->ucSeed, &UnicodeString);
  447. }
  448. /*
  449. Returns:
  450. TRUE: Success
  451. FALSE: Failure
  452. Notes:
  453. Converts FileTime to a printable form in *ppwszTime. If the function returns
  454. TRUE, the caller must ultimately call LocalFree(*ppwszTime).
  455. */
  456. BOOL
  457. FFileTimeToStr(
  458. IN FILETIME FileTime,
  459. OUT WCHAR** ppwszTime
  460. )
  461. {
  462. SYSTEMTIME SystemTime;
  463. FILETIME LocalTime;
  464. int nBytesDate;
  465. int nBytesTime;
  466. WCHAR* pwszTemp = NULL;
  467. BOOL fRet = FALSE;
  468. RTASSERT(NULL != ppwszTime);
  469. if (!FileTimeToLocalFileTime(&FileTime, &LocalTime))
  470. {
  471. EapTlsTrace("FileTimeToLocalFileTime(%d %d) failed and returned %d",
  472. FileTime.dwLowDateTime, FileTime.dwHighDateTime,
  473. GetLastError());
  474. goto LDone;
  475. }
  476. if (!FileTimeToSystemTime(&LocalTime, &SystemTime))
  477. {
  478. EapTlsTrace("FileTimeToSystemTime(%d %d) failed and returned %d",
  479. LocalTime.dwLowDateTime, LocalTime.dwHighDateTime,
  480. GetLastError());
  481. goto LDone;
  482. }
  483. nBytesDate = GetDateFormat(LOCALE_USER_DEFAULT, 0, &SystemTime, NULL,
  484. NULL, 0);
  485. if (0 == nBytesDate)
  486. {
  487. EapTlsTrace("GetDateFormat(%d %d %d %d %d %d %d %d) failed and "
  488. "returned %d",
  489. SystemTime.wYear, SystemTime.wMonth, SystemTime.wDayOfWeek,
  490. SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute,
  491. SystemTime.wSecond, SystemTime.wMilliseconds,
  492. GetLastError());
  493. goto LDone;
  494. }
  495. nBytesTime = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &SystemTime, NULL,
  496. NULL, 0);
  497. if (0 == nBytesTime)
  498. {
  499. EapTlsTrace("GetTimeFormat(%d %d %d %d %d %d %d %d) failed and "
  500. "returned %d",
  501. SystemTime.wYear, SystemTime.wMonth, SystemTime.wDayOfWeek,
  502. SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute,
  503. SystemTime.wSecond, SystemTime.wMilliseconds,
  504. GetLastError());
  505. goto LDone;
  506. }
  507. pwszTemp = LocalAlloc(LPTR, (nBytesDate + nBytesTime)*sizeof(WCHAR));
  508. if (NULL == pwszTemp)
  509. {
  510. EapTlsTrace("LocalAlloc failed and returned %d", GetLastError());
  511. goto LDone;
  512. }
  513. if (0 == GetDateFormat(LOCALE_USER_DEFAULT, 0, &SystemTime, NULL,
  514. pwszTemp, nBytesDate))
  515. {
  516. EapTlsTrace("GetDateFormat(%d %d %d %d %d %d %d %d) failed and "
  517. "returned %d",
  518. SystemTime.wYear, SystemTime.wMonth, SystemTime.wDayOfWeek,
  519. SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute,
  520. SystemTime.wSecond, SystemTime.wMilliseconds,
  521. GetLastError());
  522. goto LDone;
  523. }
  524. pwszTemp[nBytesDate - 1] = L' ';
  525. if (0 == GetTimeFormat(LOCALE_USER_DEFAULT, 0, &SystemTime, NULL,
  526. pwszTemp + nBytesDate, nBytesTime))
  527. {
  528. EapTlsTrace("GetTimeFormat(%d %d %d %d %d %d %d %d) failed and "
  529. "returned %d",
  530. SystemTime.wYear, SystemTime.wMonth, SystemTime.wDayOfWeek,
  531. SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute,
  532. SystemTime.wSecond, SystemTime.wMilliseconds,
  533. GetLastError());
  534. goto LDone;
  535. }
  536. *ppwszTime = pwszTemp;
  537. pwszTemp = NULL;
  538. fRet = TRUE;
  539. LDone:
  540. LocalFree(pwszTemp);
  541. return(fRet);
  542. }
  543. BOOL FFormatMachineIdentity1 ( LPWSTR lpszMachineNameRaw, LPWSTR * lppszMachineNameFormatted )
  544. {
  545. BOOL fRetVal = FALSE;
  546. LPWSTR lpwszPrefix = L"host/";
  547. RTASSERT(NULL != lpszMachineNameRaw );
  548. RTASSERT(NULL != lppszMachineNameFormatted );
  549. //
  550. // Prepend host/ to the UPN name
  551. //
  552. *lppszMachineNameFormatted =
  553. (LPWSTR)LocalAlloc ( LPTR, ( wcslen ( lpszMachineNameRaw ) + wcslen ( lpwszPrefix ) + 2 ) * sizeof(WCHAR) );
  554. if ( NULL == *lppszMachineNameFormatted )
  555. {
  556. goto done;
  557. }
  558. wcscpy( *lppszMachineNameFormatted, lpwszPrefix );
  559. wcscat ( *lppszMachineNameFormatted, lpszMachineNameRaw );
  560. fRetVal = TRUE;
  561. done:
  562. return fRetVal;
  563. }
  564. /*
  565. Returns:
  566. TRUE: Success
  567. FALSE: Failure
  568. Notes:
  569. Gets the machine name from the cert as a fully qualified path hostname/path
  570. for example, hostname.redmond.microsoft.com and reformats it in the
  571. domain\hostname format.
  572. */
  573. BOOL FFormatMachineIdentity ( LPWSTR lpszMachineNameRaw, LPWSTR * lppszMachineNameFormatted )
  574. {
  575. BOOL fRetVal = TRUE;
  576. LPTSTR s1 = lpszMachineNameRaw;
  577. LPTSTR s2 = NULL;
  578. RTASSERT(NULL != lpszMachineNameRaw );
  579. RTASSERT(NULL != lppszMachineNameFormatted );
  580. //Need to add 2 more chars. One for NULL and other for $ sign
  581. *lppszMachineNameFormatted = (LPTSTR )LocalAlloc ( LPTR, (wcslen(lpszMachineNameRaw) + 2)* sizeof(WCHAR) );
  582. if ( NULL == *lppszMachineNameFormatted )
  583. {
  584. return FALSE;
  585. }
  586. //find the first "." and that is the identity of the machine.
  587. //the second "." is the domain.
  588. //check to see if there at least 2 dots. If not the raw string is
  589. //the output string
  590. while ( *s1 )
  591. {
  592. if ( *s1 == '.' )
  593. {
  594. if ( !s2 ) //First dot
  595. s2 = s1;
  596. else //second dot
  597. break;
  598. }
  599. s1++;
  600. }
  601. //can perform several additional checks here
  602. if ( *s1 != '.' ) //there are no 2 dots so raw = formatted
  603. {
  604. wcscpy ( *lppszMachineNameFormatted, lpszMachineNameRaw );
  605. goto done;
  606. }
  607. if ( s1-s2 < 2 )
  608. {
  609. wcscpy ( *lppszMachineNameFormatted, lpszMachineNameRaw );
  610. goto done;
  611. }
  612. memcpy ( *lppszMachineNameFormatted, s2+1, ( s1-s2-1) * sizeof(WCHAR));
  613. memcpy ( (*lppszMachineNameFormatted) + (s1-s2-1) , L"\\", sizeof(WCHAR));
  614. wcsncpy ( (*lppszMachineNameFormatted) + (s1-s2), lpszMachineNameRaw, s2-lpszMachineNameRaw );
  615. done:
  616. //Append the $ sign no matter what...
  617. wcscat ( *lppszMachineNameFormatted, L"$" );
  618. return fRetVal;
  619. }
  620. /*
  621. Returns:
  622. TRUE: Success
  623. FALSE: Failure
  624. Notes:
  625. Gets the name in the cert pointed to by pCertContext, and converts it to a
  626. printable form in *ppwszName. If the function returns TRUE, the caller must
  627. ultimately call LocalFree(*ppwszName).
  628. */
  629. BOOL
  630. FUserCertToStr(
  631. IN PCCERT_CONTEXT pCertContext,
  632. OUT WCHAR** ppwszName
  633. )
  634. {
  635. DWORD dwExtensionIndex;
  636. DWORD dwAltEntryIndex;
  637. CERT_EXTENSION* pCertExtension;
  638. CERT_ALT_NAME_INFO* pCertAltNameInfo;
  639. CERT_ALT_NAME_ENTRY* pCertAltNameEntry;
  640. CERT_NAME_VALUE* pCertNameValue;
  641. DWORD dwCertAltNameInfoSize;
  642. DWORD dwCertNameValueSize;
  643. WCHAR* pwszName = NULL;
  644. BOOL fExitOuterFor;
  645. BOOL fExitInnerFor;
  646. BOOL fRet = FALSE;
  647. // See if cert has UPN in AltSubjectName->otherName
  648. fExitOuterFor = FALSE;
  649. for (dwExtensionIndex = 0;
  650. dwExtensionIndex < pCertContext->pCertInfo->cExtension;
  651. dwExtensionIndex++)
  652. {
  653. pCertAltNameInfo = NULL;
  654. pCertExtension = pCertContext->pCertInfo->rgExtension+dwExtensionIndex;
  655. if (strcmp(pCertExtension->pszObjId, szOID_SUBJECT_ALT_NAME2) != 0)
  656. {
  657. goto LOuterForEnd;
  658. }
  659. dwCertAltNameInfoSize = 0;
  660. if (!CryptDecodeObjectEx(
  661. pCertContext->dwCertEncodingType,
  662. X509_ALTERNATE_NAME,
  663. pCertExtension->Value.pbData,
  664. pCertExtension->Value.cbData,
  665. CRYPT_DECODE_ALLOC_FLAG,
  666. NULL,
  667. (VOID*)&pCertAltNameInfo,
  668. &dwCertAltNameInfoSize))
  669. {
  670. goto LOuterForEnd;
  671. }
  672. fExitInnerFor = FALSE;
  673. for (dwAltEntryIndex = 0;
  674. dwAltEntryIndex < pCertAltNameInfo->cAltEntry;
  675. dwAltEntryIndex++)
  676. {
  677. pCertNameValue = NULL;
  678. pCertAltNameEntry = pCertAltNameInfo->rgAltEntry + dwAltEntryIndex;
  679. if ( (CERT_ALT_NAME_OTHER_NAME !=
  680. pCertAltNameEntry->dwAltNameChoice)
  681. || (NULL == pCertAltNameEntry->pOtherName)
  682. || (0 != strcmp(szOID_NT_PRINCIPAL_NAME,
  683. pCertAltNameEntry->pOtherName->pszObjId)))
  684. {
  685. goto LInnerForEnd;
  686. }
  687. // We found a UPN!
  688. dwCertNameValueSize = 0;
  689. if (!CryptDecodeObjectEx(
  690. pCertContext->dwCertEncodingType,
  691. X509_UNICODE_ANY_STRING,
  692. pCertAltNameEntry->pOtherName->Value.pbData,
  693. pCertAltNameEntry->pOtherName->Value.cbData,
  694. CRYPT_DECODE_ALLOC_FLAG,
  695. NULL,
  696. (VOID*)&pCertNameValue,
  697. &dwCertNameValueSize))
  698. {
  699. goto LInnerForEnd;
  700. }
  701. // One extra char for the terminating NULL.
  702. pwszName = LocalAlloc(LPTR, pCertNameValue->Value.cbData +
  703. sizeof(WCHAR));
  704. if (NULL == pwszName)
  705. {
  706. EapTlsTrace("LocalAlloc failed and returned %d",
  707. GetLastError());
  708. fExitInnerFor = TRUE;
  709. fExitOuterFor = TRUE;
  710. goto LInnerForEnd;
  711. }
  712. CopyMemory(pwszName, pCertNameValue->Value.pbData,
  713. pCertNameValue->Value.cbData);
  714. *ppwszName = pwszName;
  715. pwszName = NULL;
  716. fRet = TRUE;
  717. fExitInnerFor = TRUE;
  718. fExitOuterFor = TRUE;
  719. LInnerForEnd:
  720. LocalFree(pCertNameValue);
  721. if (fExitInnerFor)
  722. {
  723. break;
  724. }
  725. }
  726. LOuterForEnd:
  727. LocalFree(pCertAltNameInfo);
  728. if (fExitOuterFor)
  729. {
  730. break;
  731. }
  732. }
  733. LocalFree(pwszName);
  734. return(fRet);
  735. }
  736. /*
  737. Returns:
  738. TRUE: Success
  739. FALSE: Failure
  740. Notes:
  741. Gets the name in the cert pointed to by pCertContext, and converts it to a
  742. printable form in *ppwszName. If the function returns TRUE, the caller must
  743. ultimately call LocalFree(*ppwszName).
  744. */
  745. BOOL
  746. FOtherCertToStr(
  747. IN PCCERT_CONTEXT pCertContext,
  748. IN DWORD fFlags,
  749. OUT WCHAR** ppwszName
  750. )
  751. {
  752. WCHAR* pwszTemp = NULL;
  753. DWORD dwSize;
  754. BOOL fRet = FALSE;
  755. DWORD dwType = 0;
  756. RTASSERT(NULL != ppwszName);
  757. dwType = CERT_NAME_SIMPLE_DISPLAY_TYPE;
  758. dwSize = CertGetNameString(pCertContext,dwType ,
  759. fFlags, NULL, NULL, 0);
  760. // dwSize is the number of characters, including the terminating NULL.
  761. if (dwSize <= 1)
  762. {
  763. EapTlsTrace("CertGetNameString for CERT_NAME_SIMPLE_DISPLAY_TYPE failed.");
  764. goto LDone;
  765. }
  766. pwszTemp = LocalAlloc(LPTR, dwSize*sizeof(WCHAR));
  767. if (NULL == pwszTemp)
  768. {
  769. EapTlsTrace("LocalAlloc failed and returned %d", GetLastError());
  770. goto LDone;
  771. }
  772. dwSize = CertGetNameString(pCertContext, dwType,
  773. fFlags, NULL, pwszTemp, dwSize);
  774. if (dwSize <= 1)
  775. {
  776. EapTlsTrace("CertGetNameString failed.");
  777. goto LDone;
  778. }
  779. *ppwszName = pwszTemp;
  780. pwszTemp = NULL;
  781. fRet = TRUE;
  782. LDone:
  783. LocalFree(pwszTemp);
  784. return(fRet);
  785. }
  786. /*
  787. Returns:
  788. TRUE: Success
  789. FALSE: Failure
  790. Notes:
  791. Special function for getting the DNS machine name
  792. from the machine auth certificate
  793. */
  794. BOOL
  795. FMachineAuthCertToStr
  796. (
  797. IN PCCERT_CONTEXT pCertContext,
  798. OUT WCHAR ** ppwszName
  799. )
  800. {
  801. DWORD dwExtensionIndex;
  802. DWORD dwAltEntryIndex;
  803. CERT_EXTENSION* pCertExtension;
  804. CERT_ALT_NAME_INFO* pCertAltNameInfo;
  805. CERT_ALT_NAME_ENTRY* pCertAltNameEntry;
  806. DWORD dwCertAltNameInfoSize;
  807. WCHAR* pwszName = NULL;
  808. BOOL fExitOuterFor;
  809. BOOL fExitInnerFor;
  810. BOOL fRet = FALSE;
  811. // See if cert has UPN in AltSubjectName->otherName
  812. fExitOuterFor = FALSE;
  813. for (dwExtensionIndex = 0;
  814. dwExtensionIndex < pCertContext->pCertInfo->cExtension;
  815. dwExtensionIndex++)
  816. {
  817. pCertAltNameInfo = NULL;
  818. pCertExtension = pCertContext->pCertInfo->rgExtension+dwExtensionIndex;
  819. if (strcmp(pCertExtension->pszObjId, szOID_SUBJECT_ALT_NAME2) != 0)
  820. {
  821. goto LOuterForEnd;
  822. }
  823. dwCertAltNameInfoSize = 0;
  824. if (!CryptDecodeObjectEx(
  825. pCertContext->dwCertEncodingType,
  826. X509_ALTERNATE_NAME,
  827. pCertExtension->Value.pbData,
  828. pCertExtension->Value.cbData,
  829. CRYPT_DECODE_ALLOC_FLAG,
  830. NULL,
  831. (VOID*)&pCertAltNameInfo,
  832. &dwCertAltNameInfoSize))
  833. {
  834. goto LOuterForEnd;
  835. }
  836. fExitInnerFor = FALSE;
  837. for (dwAltEntryIndex = 0;
  838. dwAltEntryIndex < pCertAltNameInfo->cAltEntry;
  839. dwAltEntryIndex++)
  840. {
  841. pCertAltNameEntry = pCertAltNameInfo->rgAltEntry + dwAltEntryIndex;
  842. if ( (CERT_ALT_NAME_DNS_NAME !=
  843. pCertAltNameEntry->dwAltNameChoice)
  844. || (NULL == pCertAltNameEntry->pwszDNSName)
  845. )
  846. {
  847. goto LInnerForEnd;
  848. }
  849. // We found the DNS Name!
  850. // One extra char for the terminating NULL.
  851. pwszName = LocalAlloc(LPTR, wcslen( pCertAltNameEntry->pwszDNSName ) * sizeof(WCHAR) +
  852. sizeof(WCHAR));
  853. if (NULL == pwszName)
  854. {
  855. EapTlsTrace("LocalAlloc failed and returned %d",
  856. GetLastError());
  857. fExitInnerFor = TRUE;
  858. fExitOuterFor = TRUE;
  859. goto LInnerForEnd;
  860. }
  861. wcscpy (pwszName, pCertAltNameEntry->pwszDNSName );
  862. *ppwszName = pwszName;
  863. pwszName = NULL;
  864. fRet = TRUE;
  865. fExitInnerFor = TRUE;
  866. fExitOuterFor = TRUE;
  867. LInnerForEnd:
  868. if (fExitInnerFor)
  869. {
  870. break;
  871. }
  872. }
  873. LOuterForEnd:
  874. LocalFree(pCertAltNameInfo);
  875. if (fExitOuterFor)
  876. {
  877. break;
  878. }
  879. }
  880. LocalFree(pwszName);
  881. return(fRet);
  882. }
  883. /*
  884. Returns:
  885. TRUE: Success
  886. FALSE: Failure
  887. Notes:
  888. Gets the name in the cert pointed to by pCertContext, and converts it to a
  889. printable form in *ppwszName. If the function returns TRUE, the caller must
  890. ultimately call LocalFree(*ppwszName).
  891. */
  892. BOOL
  893. FCertToStr(
  894. IN PCCERT_CONTEXT pCertContext,
  895. IN DWORD fFlags,
  896. IN BOOL fMachineCert,
  897. OUT WCHAR** ppwszName
  898. )
  899. {
  900. if (!fMachineCert)
  901. {
  902. if (FUserCertToStr(pCertContext, ppwszName))
  903. {
  904. return(TRUE);
  905. }
  906. }
  907. return(FOtherCertToStr(pCertContext, fFlags, ppwszName));
  908. }
  909. #if 0
  910. BOOL
  911. FGetIssuerOrSubject ( IN PCCERT_CONTEXT pCertContext,
  912. IN DWORD dwFlags,
  913. OUT WCHAR ** ppszNameString
  914. )
  915. {
  916. BOOL fRet = TRUE;
  917. DWORD cbNameString =0;
  918. LPWSTR lpwszNameString = NULL;
  919. //
  920. // Get the issued to field here
  921. //
  922. cbNameString = CertGetNameString(pCertContext,
  923. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  924. dwFlags,
  925. NULL,
  926. lpwszNameString,
  927. 0
  928. );
  929. if ( 0 == cbNameString )
  930. {
  931. EapTlsTrace("Name String Item not found");
  932. fRet = FALSE;
  933. goto LDone;
  934. }
  935. lpwszNameString = (LPWSTR)LocalAlloc(LPTR, cbNameString );
  936. if ( NULL == lpwszNameString )
  937. {
  938. EapTlsTrace("Error allocing memory for name string");
  939. fRet = FALSE;
  940. goto LDone;
  941. }
  942. cbNameString = CertGetNameString(pCertContext,
  943. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  944. dwFlags,
  945. NULL,
  946. lpwszNameString,
  947. cbNameString
  948. );
  949. *ppszNameString = lpwszNameString;
  950. lpwszNameString = NULL;
  951. LDone:
  952. LocalFree(lpwszNameString);
  953. return fRet;
  954. }
  955. #endif
  956. /*
  957. Returns:
  958. TRUE: Success
  959. FALSE: Failure
  960. Notes:
  961. Stores the friendly name of the cert pointed to by pCertContext in
  962. *ppwszName. If the function returns TRUE, the caller must ultimately call
  963. LocalFree(*ppwszName).
  964. */
  965. BOOL
  966. FGetFriendlyName(
  967. IN PCCERT_CONTEXT pCertContext,
  968. OUT WCHAR** ppwszName
  969. )
  970. {
  971. WCHAR* pwszName = NULL;
  972. DWORD dwBytes;
  973. BOOL fRet = FALSE;
  974. RTASSERT(NULL != ppwszName);
  975. if (!CertGetCertificateContextProperty(pCertContext,
  976. CERT_FRIENDLY_NAME_PROP_ID, NULL, &dwBytes))
  977. {
  978. // If there is no Friendly Name property, don't print an error stmt.
  979. goto LDone;
  980. }
  981. pwszName = LocalAlloc(LPTR, dwBytes);
  982. if (NULL == pwszName)
  983. {
  984. EapTlsTrace("LocalAlloc failed and returned %d", GetLastError());
  985. goto LDone;
  986. }
  987. if (!CertGetCertificateContextProperty(pCertContext,
  988. CERT_FRIENDLY_NAME_PROP_ID, pwszName, &dwBytes))
  989. {
  990. EapTlsTrace("CertGetCertificateContextProperty failed and "
  991. "returned 0x%x", GetLastError());
  992. goto LDone;
  993. }
  994. *ppwszName = pwszName;
  995. pwszName = NULL;
  996. fRet = TRUE;
  997. LDone:
  998. LocalFree(pwszName);
  999. return(fRet);
  1000. }
  1001. /*
  1002. Returns:
  1003. TRUE iff there is a smart card reader installed.
  1004. Notes:
  1005. This function was provided by Doug Barlow.
  1006. If 0 is used as the SCARDCONTEXT parameter, it just looks in the registry
  1007. for defined readers. This will return a list of all readers ever installed
  1008. on the system. To actually detect the current state of the system, we have
  1009. to use a valid SCARDCONTEXT handle.
  1010. */
  1011. BOOL
  1012. FSmartCardReaderInstalled(
  1013. VOID
  1014. )
  1015. {
  1016. LONG lErr;
  1017. DWORD dwLen = 0;
  1018. SCARDCONTEXT hCtx = 0;
  1019. BOOL fReturn = FALSE;
  1020. lErr = SCardListReadersA(0, NULL, NULL, &dwLen);
  1021. fReturn = ( (NO_ERROR == lErr)
  1022. && (2 * sizeof(CHAR) < dwLen));
  1023. if (!fReturn)
  1024. {
  1025. goto LDone;
  1026. }
  1027. fReturn = FALSE;
  1028. lErr = SCardEstablishContext(SCARD_SCOPE_USER, 0, 0, &hCtx);
  1029. if (SCARD_S_SUCCESS != lErr)
  1030. {
  1031. goto LDone;
  1032. }
  1033. lErr = SCardListReadersA(hCtx, NULL, NULL, &dwLen);
  1034. fReturn = ( (NO_ERROR == lErr)
  1035. && (2 * sizeof(CHAR) < dwLen));
  1036. LDone:
  1037. if (0 != hCtx)
  1038. {
  1039. SCardReleaseContext(hCtx);
  1040. }
  1041. return(fReturn);
  1042. }
  1043. //Get EKU Usage Blob out of the certificate Context
  1044. DWORD DwGetEKUUsage (
  1045. IN PCCERT_CONTEXT pCertContext,
  1046. OUT PCERT_ENHKEY_USAGE * ppUsage
  1047. )
  1048. {
  1049. DWORD dwBytes = 0;
  1050. DWORD dwErr = ERROR_SUCCESS;
  1051. PCERT_ENHKEY_USAGE pUsage = NULL;
  1052. EapTlsTrace("FGetEKUUsage");
  1053. if (!CertGetEnhancedKeyUsage(pCertContext, 0, NULL, &dwBytes))
  1054. {
  1055. dwErr = GetLastError();
  1056. if (CRYPT_E_NOT_FOUND == dwErr)
  1057. {
  1058. EapTlsTrace("No usage in cert");
  1059. goto LDone;
  1060. }
  1061. EapTlsTrace("FGetEKUUsage failed and returned 0x%x", dwErr);
  1062. goto LDone;
  1063. }
  1064. pUsage = LocalAlloc(LPTR, dwBytes);
  1065. if (NULL == pUsage)
  1066. {
  1067. dwErr = GetLastError();
  1068. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  1069. goto LDone;
  1070. }
  1071. if (!CertGetEnhancedKeyUsage(pCertContext, 0, pUsage, &dwBytes))
  1072. {
  1073. dwErr = GetLastError();
  1074. EapTlsTrace("FGetEKUUsage failed and returned 0x%x", dwErr);
  1075. goto LDone;
  1076. }
  1077. *ppUsage = pUsage;
  1078. LDone:
  1079. return dwErr;
  1080. }
  1081. /*
  1082. * This functionw will check to see if the registry based cert is
  1083. * a smart card cert and if the context can be opened in silent
  1084. * mode.
  1085. */
  1086. BOOL
  1087. FCheckSCardCertAndCanOpenSilentContext ( IN PCCERT_CONTEXT pCertContext )
  1088. {
  1089. PCERT_ENHKEY_USAGE pUsageInternal = NULL;
  1090. BOOL fRet = TRUE;
  1091. DWORD dwIndex = 0;
  1092. CRYPT_KEY_PROV_INFO * pCryptKeyProvInfo = NULL;
  1093. HCRYPTPROV hProv = 0;
  1094. DWORD dwParam = 0;
  1095. DWORD dwDataLen = 0;
  1096. #if 0
  1097. //
  1098. // This is not required anymore. We use CertFindChainInStore
  1099. // which will make sure if private key exists...
  1100. //
  1101. HCRYPTPROV hProv1 = 0;
  1102. #endif
  1103. EapTlsTrace("FCheckSCardCertAndCanOpenSilentContext");
  1104. if ( DwGetEKUUsage ( pCertContext,
  1105. &pUsageInternal) != ERROR_SUCCESS
  1106. )
  1107. {
  1108. goto LDone;
  1109. }
  1110. for (dwIndex = 0; dwIndex < pUsageInternal->cUsageIdentifier; dwIndex++)
  1111. {
  1112. if ( !strcmp(pUsageInternal->rgpszUsageIdentifier[dwIndex],
  1113. szOID_KP_SMARTCARD_LOGON))
  1114. {
  1115. EapTlsTrace("Found SCard Cert in registey. Skipping...");
  1116. goto LDone;
  1117. }
  1118. }
  1119. //
  1120. //there is no scard logon oid in the cert
  1121. //So, now check to see if the csp is mixed mode
  1122. //
  1123. if (!CertGetCertificateContextProperty(
  1124. pCertContext,
  1125. CERT_KEY_PROV_INFO_PROP_ID,
  1126. NULL,
  1127. &dwDataLen))
  1128. {
  1129. EapTlsTrace("CertGetCertificateContextProperty failed: 0x%x", GetLastError());
  1130. goto LDone;
  1131. }
  1132. pCryptKeyProvInfo = LocalAlloc(LPTR, dwDataLen);
  1133. if (NULL == pCryptKeyProvInfo)
  1134. {
  1135. EapTlsTrace("Out of memory: 0x%x", GetLastError());
  1136. goto LDone;
  1137. }
  1138. if (!CertGetCertificateContextProperty(
  1139. pCertContext,
  1140. CERT_KEY_PROV_INFO_PROP_ID,
  1141. pCryptKeyProvInfo,
  1142. &dwDataLen))
  1143. {
  1144. EapTlsTrace("CertGetCertificateContextProperty failed: 0x%x", GetLastError());
  1145. goto LDone;
  1146. }
  1147. EapTlsTrace( "Acquiring Context for Container Name: %ws, ProvName: %ws, ProvType 0x%x",
  1148. pCryptKeyProvInfo->pwszContainerName,
  1149. pCryptKeyProvInfo->pwszProvName,
  1150. pCryptKeyProvInfo->dwProvType
  1151. );
  1152. if (!CryptAcquireContext(
  1153. &hProv,
  1154. pCryptKeyProvInfo->pwszContainerName,
  1155. pCryptKeyProvInfo->pwszProvName,
  1156. pCryptKeyProvInfo->dwProvType,
  1157. (pCryptKeyProvInfo->dwFlags &
  1158. ~CERT_SET_KEY_PROV_HANDLE_PROP_ID) |
  1159. CRYPT_SILENT))
  1160. {
  1161. DWORD dwErr = GetLastError();
  1162. /*
  1163. if ( SCARD_E_NO_SMARTCARD == dwErr )
  1164. {
  1165. //This CSP requires a smart card do this is a smart
  1166. //card cert in registry
  1167. fRet = TRUE;
  1168. }
  1169. */
  1170. EapTlsTrace("CryptAcquireContext failed. This CSP cannot be opened in silent mode. skipping cert.Err: 0x%x", dwErr);
  1171. goto LDone;
  1172. }
  1173. dwDataLen = sizeof(dwParam);
  1174. if ( !CryptGetProvParam ( hProv,
  1175. PP_IMPTYPE,
  1176. (BYTE *)&dwParam,
  1177. &dwDataLen,
  1178. 0
  1179. ))
  1180. {
  1181. EapTlsTrace("CryptGetProvParam failed: 0x%x", GetLastError());
  1182. goto LDone;
  1183. }
  1184. //now check to see if CSP is MIXED
  1185. if ( ( dwParam & (CRYPT_IMPL_MIXED | CRYPT_IMPL_REMOVABLE) ) ==
  1186. (CRYPT_IMPL_MIXED | CRYPT_IMPL_REMOVABLE)
  1187. )
  1188. {
  1189. EapTlsTrace("Found SCard Cert in registey. Skipping...");
  1190. goto LDone;
  1191. }
  1192. #if 0
  1193. //
  1194. // This is not required anymore. We use CertFindChainInStore
  1195. // which will make sure that private key exists...
  1196. //
  1197. //
  1198. // Check to see if we have the private
  1199. // key corresponding to this cert
  1200. // if not drop this cert.
  1201. if (!CryptAcquireCertificatePrivateKey(
  1202. pCertContext,
  1203. CRYPT_ACQUIRE_COMPARE_KEY_FLAG | CRYPT_SILENT,
  1204. NULL,
  1205. &hProv1,
  1206. NULL,
  1207. NULL
  1208. ))
  1209. {
  1210. EapTlsTrace("Found a certificate without private key. Skipping. Error 0x%x",GetLastError());
  1211. goto LDone;
  1212. }
  1213. CryptReleaseContext(hProv1, 0);
  1214. #endif
  1215. fRet = FALSE;
  1216. LDone:
  1217. if ( pUsageInternal )
  1218. LocalFree(pUsageInternal);
  1219. if ( pCryptKeyProvInfo )
  1220. LocalFree(pCryptKeyProvInfo);
  1221. if (0 != hProv)
  1222. {
  1223. CryptReleaseContext(hProv, 0);
  1224. }
  1225. return fRet;
  1226. }
  1227. /*
  1228. Add selected certs to the
  1229. */
  1230. VOID AddCertNodeToSelList ( EAPTLS_HASH * pHash,
  1231. DWORD dwNumHashes,
  1232. EAPTLS_CERT_NODE * pNode,
  1233. EAPTLS_CERT_NODE ** ppSelCertList, //This is an array of pointers
  1234. DWORD * pdwNextSelCert
  1235. )
  1236. {
  1237. DWORD dw = 0;
  1238. DWORD dw1 = 0;
  1239. RTASSERT(NULL != pNode);
  1240. EapTlsTrace("Add Selected Cert to List");
  1241. //No selected certificates
  1242. if ( 0 == dwNumHashes || !ppSelCertList )
  1243. goto done;
  1244. while ( dw < dwNumHashes )
  1245. {
  1246. if (!memcmp(&(pNode->Hash), (pHash+ dw), sizeof(EAPTLS_HASH)))
  1247. {
  1248. //
  1249. //check to see if the node's already in the list.
  1250. //iff not then add it. Looks like there is some
  1251. //problem with possible dup certs in the cert store
  1252. //
  1253. while ( dw1 < *pdwNextSelCert )
  1254. {
  1255. if ( ! memcmp( &(*(ppSelCertList+dw1))->Hash, &(pNode->Hash), sizeof(EAPTLS_HASH) ) )
  1256. {
  1257. //This is a dup node in mmc. So Skip it...
  1258. goto done;
  1259. }
  1260. dw1++;
  1261. }
  1262. *( ppSelCertList + *pdwNextSelCert ) = pNode;
  1263. *pdwNextSelCert = *pdwNextSelCert + 1;
  1264. break;
  1265. }
  1266. dw++;
  1267. }
  1268. done:
  1269. return;
  1270. }
  1271. /*
  1272. Returns:
  1273. TRUE if no enhanced key usages exist, or pCertContext has the
  1274. szOID_PKIX_KP_SERVER_AUTH or szOID_PKIX_KP_CLIENT_AUTH usage depending on
  1275. whether fMachine is TRUE or FALSE.
  1276. Notes:
  1277. */
  1278. BOOL
  1279. FCheckUsage(
  1280. IN PCCERT_CONTEXT pCertContext,
  1281. IN PCERT_ENHKEY_USAGE pUsage,
  1282. IN BOOL fMachine
  1283. )
  1284. {
  1285. DWORD dwIndex;
  1286. DWORD dwErr;
  1287. BOOL fRet = FALSE;
  1288. PCERT_ENHKEY_USAGE pUsageInternal = pUsage;
  1289. EapTlsTrace("FCheckUsage");
  1290. if ( NULL == pUsageInternal )
  1291. {
  1292. dwErr = DwGetEKUUsage ( pCertContext,
  1293. &pUsageInternal);
  1294. if ( dwErr != ERROR_SUCCESS )
  1295. goto LDone;
  1296. }
  1297. for (dwIndex = 0; dwIndex < pUsageInternal->cUsageIdentifier; dwIndex++)
  1298. {
  1299. if ( ( fMachine
  1300. && !strcmp(pUsageInternal->rgpszUsageIdentifier[dwIndex],
  1301. szOID_PKIX_KP_SERVER_AUTH))
  1302. || ( !fMachine
  1303. && !strcmp(pUsageInternal->rgpszUsageIdentifier[dwIndex],
  1304. szOID_PKIX_KP_CLIENT_AUTH)))
  1305. {
  1306. fRet = TRUE;
  1307. break;
  1308. }
  1309. }
  1310. LDone:
  1311. if ( NULL == pUsage )
  1312. {
  1313. if ( pUsageInternal )
  1314. LocalFree(pUsageInternal);
  1315. }
  1316. return(fRet);
  1317. }
  1318. DWORD DwCheckCertPolicy
  1319. (
  1320. IN PCCERT_CONTEXT pCertContext,
  1321. OUT PCCERT_CHAIN_CONTEXT * ppCertChainContext
  1322. )
  1323. {
  1324. DWORD dwRetCode = ERROR_SUCCESS;
  1325. LPSTR lpszEnhUsage = szOID_PKIX_KP_CLIENT_AUTH;
  1326. CERT_CHAIN_PARA ChainPara;
  1327. CERT_ENHKEY_USAGE EnhKeyUsage;
  1328. CERT_USAGE_MATCH CertUsage;
  1329. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  1330. CERT_CHAIN_POLICY_PARA PolicyPara;
  1331. CERT_CHAIN_POLICY_STATUS PolicyStatus;
  1332. EapTlsTrace("FCheckPolicy");
  1333. *ppCertChainContext = NULL;
  1334. ZeroMemory ( &ChainPara, sizeof(ChainPara) );
  1335. ZeroMemory ( &EnhKeyUsage, sizeof(EnhKeyUsage) );
  1336. ZeroMemory ( &CertUsage, sizeof(CertUsage) );
  1337. EnhKeyUsage.rgpszUsageIdentifier = &lpszEnhUsage;
  1338. EnhKeyUsage.cUsageIdentifier = 1;
  1339. EnhKeyUsage.rgpszUsageIdentifier = &lpszEnhUsage;
  1340. CertUsage.dwType = USAGE_MATCH_TYPE_AND;
  1341. CertUsage.Usage = EnhKeyUsage;
  1342. ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
  1343. ChainPara.RequestedUsage = CertUsage;
  1344. if(!CertGetCertificateChain(
  1345. NULL,
  1346. pCertContext,
  1347. NULL,
  1348. pCertContext->hCertStore,
  1349. &ChainPara,
  1350. 0,
  1351. NULL,
  1352. &pChainContext))
  1353. {
  1354. dwRetCode = GetLastError();
  1355. EapTlsTrace("CertGetCertificateChain failed and returned 0x%x", dwRetCode );
  1356. pChainContext = NULL;
  1357. goto LDone;
  1358. }
  1359. ZeroMemory( &PolicyPara, sizeof(PolicyPara) );
  1360. PolicyPara.cbSize = sizeof(PolicyPara);
  1361. PolicyPara.dwFlags = BASIC_CONSTRAINTS_CERT_CHAIN_POLICY_END_ENTITY_FLAG;
  1362. ZeroMemory( &PolicyStatus, sizeof(PolicyStatus) );
  1363. //
  1364. // The chain already has verified the policy.
  1365. // Chain context will have several bits set.
  1366. // To get one error out of it, call CErtVerifyCertificateChainPolicy
  1367. //
  1368. if ( !CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_NT_AUTH,
  1369. pChainContext,
  1370. &PolicyPara,
  1371. &PolicyStatus
  1372. )
  1373. )
  1374. {
  1375. dwRetCode = GetLastError();
  1376. EapTlsTrace( "CertVerifyCertificateChainPolicy failed. Continuing with root hash matching"
  1377. "GetLastError = 0x%x.", dwRetCode);
  1378. }
  1379. else
  1380. {
  1381. //
  1382. //Check to see if the policy status is good. If so,
  1383. //there is no need to check for connectoid hashes any more...
  1384. //
  1385. if ( PolicyStatus.dwError != 0 )
  1386. {
  1387. dwRetCode = PolicyStatus.dwError;
  1388. EapTlsTrace( "CertVerifyCertificateChainPolicy succeeded but policy check failed 0x%x."
  1389. , dwRetCode );
  1390. }
  1391. else
  1392. {
  1393. *ppCertChainContext = pChainContext;
  1394. }
  1395. }
  1396. LDone:
  1397. if ( dwRetCode != ERROR_SUCCESS && pChainContext )
  1398. {
  1399. CertFreeCertificateChain ( pChainContext );
  1400. }
  1401. EapTlsTrace("FCheckPolicy done.");
  1402. return dwRetCode;
  1403. }
  1404. /*
  1405. Returns:
  1406. TRUE iff the certificate is time valid.
  1407. Notes:
  1408. */
  1409. BOOL FCheckTimeValidity (
  1410. IN PCCERT_CONTEXT pCertContext
  1411. )
  1412. {
  1413. BOOL fRet = FALSE;
  1414. SYSTEMTIME SysTime;
  1415. FILETIME FileTime;
  1416. EapTlsTrace("FCheckTimeValidity");
  1417. GetSystemTime(&SysTime);
  1418. if ( !SystemTimeToFileTime ( &SysTime, &FileTime ) )
  1419. {
  1420. EapTlsTrace ("Error converting from system time to file time %ld", GetLastError());
  1421. goto done;
  1422. }
  1423. if ( CertVerifyTimeValidity ( &FileTime, pCertContext->pCertInfo ) )
  1424. {
  1425. //should return a 0 if the certificate is time valid.
  1426. EapTlsTrace ( "Non Time Valid Certificate was encountered");
  1427. goto done;
  1428. }
  1429. fRet = TRUE;
  1430. done:
  1431. return fRet;
  1432. }
  1433. /*
  1434. Returns:
  1435. TRUE iff the CSP is Microsoft RSA SChannel Cryptographic Provider.
  1436. Notes:
  1437. */
  1438. BOOL
  1439. FCheckCSP(
  1440. IN PCCERT_CONTEXT pCertContext
  1441. )
  1442. {
  1443. DWORD dwBytes;
  1444. CRYPT_KEY_PROV_INFO* pCryptKeyProvInfo = NULL;
  1445. BOOL fRet = FALSE;
  1446. EapTlsTrace("FCheckCSP");
  1447. if (!CertGetCertificateContextProperty(pCertContext,
  1448. CERT_KEY_PROV_INFO_PROP_ID, NULL, &dwBytes))
  1449. {
  1450. EapTlsTrace("CertGetCertificateContextProperty failed and "
  1451. "returned 0x%x", GetLastError());
  1452. goto LDone;
  1453. }
  1454. pCryptKeyProvInfo = LocalAlloc(LPTR, dwBytes);
  1455. if (NULL == pCryptKeyProvInfo)
  1456. {
  1457. EapTlsTrace("LocalAlloc failed and returned %d", GetLastError());
  1458. goto LDone;
  1459. }
  1460. if (!CertGetCertificateContextProperty(pCertContext,
  1461. CERT_KEY_PROV_INFO_PROP_ID, pCryptKeyProvInfo, &dwBytes))
  1462. {
  1463. EapTlsTrace("CertGetCertificateContextProperty failed and "
  1464. "returned 0x%x", GetLastError());
  1465. goto LDone;
  1466. }
  1467. fRet = (PROV_RSA_SCHANNEL == pCryptKeyProvInfo->dwProvType);
  1468. if ( !fRet )
  1469. {
  1470. EapTlsTrace("Did not find a cert with a provider RSA_SCHANNEL or RSA_FULL");
  1471. }
  1472. LDone:
  1473. LocalFree(pCryptKeyProvInfo);
  1474. return(fRet);
  1475. }
  1476. /*
  1477. Returns:
  1478. NO_ERROR: iff Success
  1479. Notes:
  1480. Gets the root cert hash of the cert represented by pCertContextServer.
  1481. */
  1482. DWORD
  1483. GetRootCertHashAndNameVerifyChain(
  1484. IN PCERT_CONTEXT pCertContextServer,
  1485. OUT EAPTLS_HASH* pHash,
  1486. OUT WCHAR** ppwszName,
  1487. IN BOOL fVerifyGP,
  1488. OUT BOOL * pfRootCheckRequired
  1489. )
  1490. {
  1491. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  1492. CERT_CHAIN_PARA ChainPara;
  1493. PCERT_SIMPLE_CHAIN pSimpleChain;
  1494. PCCERT_CONTEXT pCurrentCert;
  1495. DWORD dwIndex;
  1496. BOOL fRootCertFound = FALSE;
  1497. WCHAR* pwszName = NULL;
  1498. DWORD dwErr = NO_ERROR;
  1499. CERT_CHAIN_POLICY_PARA PolicyPara;
  1500. CERT_CHAIN_POLICY_STATUS PolicyStatus;
  1501. ZeroMemory(&ChainPara, sizeof(ChainPara));
  1502. ChainPara.cbSize = sizeof(ChainPara);
  1503. *pfRootCheckRequired = TRUE;
  1504. if(!CertGetCertificateChain(
  1505. NULL,
  1506. pCertContextServer,
  1507. NULL,
  1508. pCertContextServer->hCertStore,
  1509. &ChainPara,
  1510. 0,
  1511. NULL,
  1512. &pChainContext))
  1513. {
  1514. dwErr = GetLastError();
  1515. EapTlsTrace("CertGetCertificateChain failed and returned 0x%x", dwErr);
  1516. pChainContext = NULL;
  1517. goto LDone;
  1518. }
  1519. //Get the hash and root cert name etc anyways...
  1520. pSimpleChain = pChainContext->rgpChain[0];
  1521. for (dwIndex = 0; dwIndex < pSimpleChain->cElement; dwIndex++)
  1522. {
  1523. pCurrentCert = pSimpleChain->rgpElement[dwIndex]->pCertContext;
  1524. if (CertCompareCertificateName(pCurrentCert->dwCertEncodingType,
  1525. &pCurrentCert->pCertInfo->Issuer,
  1526. &pCurrentCert->pCertInfo->Subject))
  1527. {
  1528. fRootCertFound = TRUE;
  1529. break;
  1530. }
  1531. }
  1532. if (!fRootCertFound)
  1533. {
  1534. dwErr = ERROR_NOT_FOUND;
  1535. goto LDone;
  1536. }
  1537. pHash->cbHash = MAX_HASH_SIZE;
  1538. if (!CertGetCertificateContextProperty(pCurrentCert, CERT_HASH_PROP_ID,
  1539. pHash->pbHash, &(pHash->cbHash)))
  1540. {
  1541. dwErr = GetLastError();
  1542. EapTlsTrace("CertGetCertificateContextProperty failed and "
  1543. "returned 0x%x", dwErr);
  1544. goto LDone;
  1545. }
  1546. if (!FCertToStr(pCurrentCert, 0, TRUE, &pwszName))
  1547. {
  1548. dwErr = E_FAIL;
  1549. goto LDone;
  1550. }
  1551. *ppwszName = pwszName;
  1552. pwszName = NULL;
  1553. if ( fVerifyGP )
  1554. {
  1555. EapTlsTrace( "Checking against the NTAuth store to verify the certificate chain.");
  1556. ZeroMemory( &PolicyPara, sizeof(PolicyPara) );
  1557. PolicyPara.cbSize = sizeof(PolicyPara);
  1558. PolicyPara.dwFlags = BASIC_CONSTRAINTS_CERT_CHAIN_POLICY_END_ENTITY_FLAG;
  1559. ZeroMemory( &PolicyStatus, sizeof(PolicyStatus) );
  1560. //Authnticate against the NTAuth store and see if all's cool.
  1561. if ( !CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_NT_AUTH,
  1562. pChainContext,
  1563. &PolicyPara,
  1564. &PolicyStatus
  1565. )
  1566. )
  1567. {
  1568. EapTlsTrace( "CertVerifyCertificateChainPolicy failed. Continuing with root hash matching"
  1569. "GetLastError = 0x%x.", GetLastError());
  1570. }
  1571. else
  1572. {
  1573. //
  1574. //Check to see if the policy status is good. If so,
  1575. //there is no need to check for connectoid hashes any more...
  1576. //
  1577. if ( PolicyStatus.dwError != 0 )
  1578. {
  1579. EapTlsTrace( "CertVerifyCertificateChainPolicy succeeded but returned 0x%x."
  1580. "Continuing with root hash matching.", PolicyStatus.dwError);
  1581. }
  1582. else
  1583. {
  1584. *pfRootCheckRequired = FALSE;
  1585. }
  1586. }
  1587. }
  1588. LDone:
  1589. if (pChainContext)
  1590. {
  1591. CertFreeCertificateChain(pChainContext);
  1592. }
  1593. LocalFree(pwszName);
  1594. return(dwErr);
  1595. }
  1596. /*
  1597. Returns:
  1598. NO_ERROR: iff Success
  1599. Notes:
  1600. Opens the EAP-TLS registry key, and returns the result in *phKeyEapTls. If
  1601. the function returns NO_ERROR, the caller must ultimately call
  1602. RegCloseKey(*phKeyEapTls).
  1603. */
  1604. DWORD
  1605. OpenEapTlsRegistryKey(
  1606. IN WCHAR* pwszMachineName,
  1607. IN REGSAM samDesired,
  1608. OUT HKEY* phKeyEapTls
  1609. )
  1610. {
  1611. HKEY hKeyLocalMachine = NULL;
  1612. BOOL fHKeyLocalMachineOpened = FALSE;
  1613. BOOL fHKeyEapTlsOpened = FALSE;
  1614. LONG lRet;
  1615. DWORD dwErr = NO_ERROR;
  1616. RTASSERT(NULL != phKeyEapTls);
  1617. lRet = RegConnectRegistry(pwszMachineName, HKEY_LOCAL_MACHINE,
  1618. &hKeyLocalMachine);
  1619. if (ERROR_SUCCESS != lRet)
  1620. {
  1621. dwErr = lRet;
  1622. EapTlsTrace("RegConnectRegistry(%ws) failed and returned %d",
  1623. pwszMachineName ? pwszMachineName : L"NULL", dwErr);
  1624. goto LDone;
  1625. }
  1626. fHKeyLocalMachineOpened = TRUE;
  1627. lRet = RegOpenKeyEx(hKeyLocalMachine, EAPTLS_KEY_13, 0, samDesired,
  1628. phKeyEapTls);
  1629. if (ERROR_SUCCESS != lRet)
  1630. {
  1631. dwErr = lRet;
  1632. EapTlsTrace("RegOpenKeyEx(%ws) failed and returned %d",
  1633. EAPTLS_KEY_13, dwErr);
  1634. goto LDone;
  1635. }
  1636. fHKeyEapTlsOpened = TRUE;
  1637. LDone:
  1638. if ( fHKeyEapTlsOpened
  1639. && (ERROR_SUCCESS != dwErr))
  1640. {
  1641. RegCloseKey(*phKeyEapTls);
  1642. }
  1643. if (fHKeyLocalMachineOpened)
  1644. {
  1645. RegCloseKey(hKeyLocalMachine);
  1646. }
  1647. return(dwErr);
  1648. }
  1649. /*
  1650. Returns:
  1651. NO_ERROR: iff Success
  1652. Notes:
  1653. Reads/writes the server's config data.
  1654. If fRead is TRUE, and the function returns NO_ERROR, LocalFree(*ppUserProp)
  1655. must be called.
  1656. */
  1657. DWORD
  1658. ServerConfigDataIO(
  1659. IN BOOL fRead,
  1660. IN WCHAR* pwszMachineName,
  1661. IN OUT BYTE** ppData,
  1662. IN DWORD dwNumBytes
  1663. )
  1664. {
  1665. HKEY hKeyEapTls;
  1666. EAPTLS_USER_PROPERTIES* pUserProp;
  1667. BOOL fHKeyEapTlsOpened = FALSE;
  1668. BYTE* pData = NULL;
  1669. DWORD dwSize = 0;
  1670. LONG lRet;
  1671. DWORD dwType;
  1672. DWORD dwErr = NO_ERROR;
  1673. RTASSERT(NULL != ppData);
  1674. dwErr = OpenEapTlsRegistryKey(pwszMachineName,
  1675. fRead ? KEY_READ : KEY_WRITE, &hKeyEapTls);
  1676. if (ERROR_SUCCESS != dwErr)
  1677. {
  1678. goto LDone;
  1679. }
  1680. fHKeyEapTlsOpened = TRUE;
  1681. if (fRead)
  1682. {
  1683. lRet = RegQueryValueEx(hKeyEapTls, EAPTLS_VAL_SERVER_CONFIG_DATA, NULL,
  1684. &dwType, NULL, &dwSize);
  1685. if ( (ERROR_SUCCESS != lRet)
  1686. || (REG_BINARY != dwType)
  1687. || (sizeof(EAPTLS_USER_PROPERTIES) != dwSize))
  1688. {
  1689. pData = LocalAlloc(LPTR, sizeof(EAPTLS_USER_PROPERTIES));
  1690. if (NULL == pData)
  1691. {
  1692. dwErr = GetLastError();
  1693. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  1694. goto LDone;
  1695. }
  1696. pUserProp = (EAPTLS_USER_PROPERTIES*)pData;
  1697. pUserProp->dwVersion = 0;
  1698. }
  1699. else
  1700. {
  1701. pData = LocalAlloc(LPTR, dwSize);
  1702. if (NULL == pData)
  1703. {
  1704. dwErr = GetLastError();
  1705. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  1706. goto LDone;
  1707. }
  1708. lRet = RegQueryValueEx(hKeyEapTls, EAPTLS_VAL_SERVER_CONFIG_DATA,
  1709. NULL, &dwType, pData, &dwSize);
  1710. if (ERROR_SUCCESS != lRet)
  1711. {
  1712. dwErr = lRet;
  1713. EapTlsTrace("RegQueryValueEx(%ws) failed and returned %d",
  1714. EAPTLS_VAL_SERVER_CONFIG_DATA, dwErr);
  1715. goto LDone;
  1716. }
  1717. }
  1718. pUserProp = (EAPTLS_USER_PROPERTIES*)pData;
  1719. pUserProp->dwSize = sizeof(EAPTLS_USER_PROPERTIES);
  1720. pUserProp->awszString[0] = 0;
  1721. *ppData = pData;
  1722. pData = NULL;
  1723. }
  1724. else
  1725. {
  1726. lRet = RegSetValueEx(hKeyEapTls, EAPTLS_VAL_SERVER_CONFIG_DATA, 0,
  1727. REG_BINARY, *ppData, dwNumBytes);
  1728. if (ERROR_SUCCESS != lRet)
  1729. {
  1730. dwErr = lRet;
  1731. EapTlsTrace("RegSetValueEx(%ws) failed and returned %d",
  1732. EAPTLS_VAL_SERVER_CONFIG_DATA, dwErr);
  1733. goto LDone;
  1734. }
  1735. }
  1736. LDone:
  1737. if (fHKeyEapTlsOpened)
  1738. {
  1739. RegCloseKey(hKeyEapTls);
  1740. }
  1741. LocalFree(pData);
  1742. return(dwErr);
  1743. }
  1744. /*
  1745. Returns:
  1746. VOID
  1747. Notes:
  1748. */
  1749. VOID
  1750. FreeCertList(
  1751. IN EAPTLS_CERT_NODE* pNode
  1752. )
  1753. {
  1754. while (NULL != pNode)
  1755. {
  1756. LocalFree(pNode->pwszDisplayName);
  1757. LocalFree(pNode->pwszFriendlyName);
  1758. LocalFree(pNode->pwszIssuer);
  1759. LocalFree(pNode->pwszExpiration);
  1760. pNode = pNode->pNext;
  1761. }
  1762. }
  1763. /*
  1764. Returns:
  1765. VOID
  1766. Notes:
  1767. Creates a linked list of certs from the pwszStoreName store. This list is
  1768. created in *ppCertList. *ppCert is made to point to the cert whose hash is
  1769. the same as the hash in *pHash. The linked list must eventually be freed by
  1770. calling FreeCertList.
  1771. */
  1772. VOID
  1773. CreateCertList(
  1774. IN BOOL fServer,
  1775. IN BOOL fRouter,
  1776. IN BOOL fRoot,
  1777. OUT EAPTLS_CERT_NODE** ppCertList,
  1778. OUT EAPTLS_CERT_NODE** ppCert, //This is an array of pointers...
  1779. IN DWORD dwNumHashes,
  1780. IN EAPTLS_HASH* pHash, //This is an array of hashes...
  1781. IN WCHAR* pwszStoreName
  1782. )
  1783. {
  1784. HCERTSTORE hCertStore = NULL;
  1785. EAPTLS_CERT_NODE* pCertList = NULL;
  1786. EAPTLS_CERT_NODE* pCert = NULL;
  1787. EAPTLS_CERT_NODE* pLastNode = NULL;
  1788. PCCERT_CONTEXT pCertContext;
  1789. BOOL fExitWhile;
  1790. EAPTLS_CERT_NODE* pNode;
  1791. DWORD dwErr = NO_ERROR;
  1792. DWORD dwNextSelCert = 0;
  1793. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  1794. CERT_CHAIN_FIND_BY_ISSUER_PARA FindPara;
  1795. RTASSERT(NULL != ppCertList);
  1796. hCertStore = CertOpenStore(
  1797. CERT_STORE_PROV_SYSTEM,
  1798. 0,
  1799. 0,
  1800. CERT_STORE_READONLY_FLAG |
  1801. ((fServer || fRouter) ?
  1802. CERT_SYSTEM_STORE_LOCAL_MACHINE :
  1803. CERT_SYSTEM_STORE_CURRENT_USER),
  1804. pwszStoreName);
  1805. if (NULL == hCertStore)
  1806. {
  1807. dwErr = GetLastError();
  1808. EapTlsTrace("CertOpenSystemStore failed and returned 0x%x", dwErr);
  1809. goto LDone;
  1810. }
  1811. //Changed from fRoot||fServer to fRoot only.
  1812. if (fRoot)
  1813. {
  1814. pCertList = LocalAlloc(LPTR, sizeof(EAPTLS_CERT_NODE));
  1815. if (NULL == pCertList)
  1816. {
  1817. dwErr = GetLastError();
  1818. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  1819. goto LDone;
  1820. }
  1821. pLastNode = pCertList;
  1822. }
  1823. fExitWhile = FALSE;
  1824. pCertContext = NULL;
  1825. ZeroMemory ( &FindPara, sizeof(FindPara) );
  1826. FindPara.cbSize = sizeof(FindPara);
  1827. FindPara.pszUsageIdentifier = szOID_PKIX_KP_CLIENT_AUTH;
  1828. while (!fExitWhile)
  1829. {
  1830. dwErr = NO_ERROR;
  1831. pNode = NULL;
  1832. /*
  1833. The returned pointer is freed when passed as the pPrevCertContext on a
  1834. subsequent call. Otherwise, the pointer must be freed by calling
  1835. CertFreeCertificateContext. A pPrevCertContext that is not NULL is
  1836. always freed by this function (through a call to
  1837. CertFreeCertificateContext), even for an error.
  1838. */
  1839. if ( fRoot || fRouter || fServer )
  1840. {
  1841. pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext);
  1842. if (NULL == pCertContext)
  1843. {
  1844. fExitWhile = TRUE;
  1845. goto LWhileEnd;
  1846. }
  1847. if ( !fRoot
  1848. && !FCheckUsage(pCertContext, NULL, fServer))
  1849. {
  1850. goto LWhileEnd;
  1851. }
  1852. }
  1853. else
  1854. {
  1855. //
  1856. // Use CertFindChainInStore to get to the certificate
  1857. //
  1858. pChainContext = CertFindChainInStore ( hCertStore,
  1859. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1860. 0,
  1861. CERT_CHAIN_FIND_BY_ISSUER,
  1862. &FindPara,
  1863. pChainContext
  1864. );
  1865. if ( NULL == pChainContext )
  1866. {
  1867. fExitWhile = TRUE;
  1868. goto LWhileEnd;
  1869. }
  1870. //Set the cert context to appropriate value
  1871. pCertContext = pChainContext->rgpChain[0]->rgpElement[0]->pCertContext;
  1872. }
  1873. //
  1874. //Skip if it is smart card cached certificate
  1875. //or we cannot open this csp in silent mode
  1876. //This is done iff it is not root certs and server
  1877. //
  1878. if ( !fRoot
  1879. && !fServer
  1880. && FCheckSCardCertAndCanOpenSilentContext ( pCertContext ) )
  1881. {
  1882. goto LWhileEnd;
  1883. }
  1884. if ( !FCheckTimeValidity(pCertContext ) )
  1885. {
  1886. goto LWhileEnd;
  1887. }
  1888. if ( fServer
  1889. && !FCheckCSP(pCertContext))
  1890. {
  1891. goto LWhileEnd;
  1892. }
  1893. pNode = LocalAlloc(LPTR, sizeof(EAPTLS_CERT_NODE));
  1894. if (NULL == pNode)
  1895. {
  1896. dwErr = GetLastError();
  1897. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  1898. fExitWhile = TRUE;
  1899. goto LWhileEnd;
  1900. }
  1901. FGetFriendlyName(pCertContext, &(pNode->pwszFriendlyName));
  1902. //
  1903. // If there is no UPN name, this cert will be skipped here
  1904. //
  1905. if ( !FCertToStr(pCertContext, 0, fServer || fRouter,
  1906. &(pNode->pwszDisplayName))
  1907. || !FCertToStr(pCertContext, CERT_NAME_ISSUER_FLAG, TRUE,
  1908. &(pNode->pwszIssuer))
  1909. || !FFileTimeToStr(pCertContext->pCertInfo->NotAfter,
  1910. &(pNode->pwszExpiration)))
  1911. {
  1912. goto LWhileEnd;
  1913. }
  1914. pNode->Hash.cbHash = MAX_HASH_SIZE;
  1915. if (!CertGetCertificateContextProperty(
  1916. pCertContext, CERT_HASH_PROP_ID, pNode->Hash.pbHash,
  1917. &(pNode->Hash.cbHash)))
  1918. {
  1919. dwErr = GetLastError();
  1920. EapTlsTrace("CertGetCertificateContextProperty failed and "
  1921. "returned 0x%x", dwErr);
  1922. fExitWhile = TRUE;
  1923. goto LWhileEnd;
  1924. }
  1925. #if 0
  1926. // This is not being used anywhere. So dont worry about it.
  1927. //
  1928. // Get Issuer and subject information
  1929. //
  1930. FGetIssuerOrSubject ( pCertContext,
  1931. 0,
  1932. &(pNode->pwszIssuedTo)
  1933. );
  1934. FGetIssuerOrSubject ( pCertContext,
  1935. CERT_NAME_ISSUER_FLAG,
  1936. &(pNode->pwszIssuedBy)
  1937. );
  1938. #endif
  1939. //
  1940. // Finally copy the issued date into the structure
  1941. //
  1942. CopyMemory( &pNode->IssueDate,
  1943. &pCertContext->pCertInfo->NotBefore,
  1944. sizeof(FILETIME)
  1945. );
  1946. if (NULL == pLastNode)
  1947. {
  1948. pCertList = pLastNode = pNode;
  1949. }
  1950. else
  1951. {
  1952. pLastNode->pNext = pNode;
  1953. pLastNode = pNode;
  1954. }
  1955. //Check if the hash for current node is in the list
  1956. //that has been passed to us
  1957. AddCertNodeToSelList ( pHash,
  1958. dwNumHashes,
  1959. pNode,
  1960. ppCert, //This is an array of pointers
  1961. &dwNextSelCert
  1962. );
  1963. pNode = NULL;
  1964. LWhileEnd:
  1965. if (NULL != pNode)
  1966. {
  1967. LocalFree(pNode->pwszDisplayName);
  1968. LocalFree(pNode->pwszFriendlyName);
  1969. LocalFree(pNode->pwszIssuer);
  1970. LocalFree(pNode->pwszExpiration);
  1971. LocalFree(pNode);
  1972. pNode = NULL;
  1973. }
  1974. if ( fRoot || fRouter )
  1975. {
  1976. if ( fExitWhile
  1977. && (NULL != pCertContext))
  1978. {
  1979. CertFreeCertificateContext(pCertContext);
  1980. // Always returns TRUE;
  1981. }
  1982. }
  1983. else
  1984. {
  1985. if ( fExitWhile
  1986. && ( NULL != pChainContext )
  1987. )
  1988. {
  1989. CertFreeCertificateChain(pChainContext);
  1990. }
  1991. }
  1992. }
  1993. // If we couldn't find an appropriate default cert, make the first
  1994. // cert (if there is one) the default
  1995. if (NULL == pCert)
  1996. {
  1997. pCert = pCertList;
  1998. }
  1999. LDone:
  2000. if (NO_ERROR != dwErr)
  2001. {
  2002. FreeCertList(pCertList);
  2003. }
  2004. else
  2005. {
  2006. *ppCertList = pCertList;
  2007. }
  2008. if (NULL != hCertStore)
  2009. {
  2010. if (!CertCloseStore(hCertStore, 0))
  2011. {
  2012. EapTlsTrace("CertCloseStore failed and returned 0x%x",
  2013. GetLastError());
  2014. }
  2015. }
  2016. }
  2017. DWORD
  2018. GetLocalMachineName (
  2019. OUT WCHAR ** ppLocalMachineName
  2020. )
  2021. {
  2022. DWORD dwRetCode = NO_ERROR;
  2023. WCHAR * pLocalMachineName = NULL;
  2024. DWORD dwLocalMachineNameLen = 0;
  2025. if ( !GetComputerNameEx ( ComputerNameDnsFullyQualified,
  2026. pLocalMachineName,
  2027. &dwLocalMachineNameLen
  2028. )
  2029. )
  2030. {
  2031. dwRetCode = GetLastError();
  2032. if ( ERROR_MORE_DATA != dwRetCode )
  2033. goto LDone;
  2034. dwRetCode = NO_ERROR;
  2035. }
  2036. pLocalMachineName = (WCHAR *)LocalAlloc( LPTR, (dwLocalMachineNameLen * sizeof(WCHAR)) + sizeof(WCHAR) );
  2037. if ( NULL == pLocalMachineName )
  2038. {
  2039. dwRetCode = GetLastError();
  2040. goto LDone;
  2041. }
  2042. if ( !GetComputerNameEx ( ComputerNameDnsFullyQualified,
  2043. pLocalMachineName,
  2044. &dwLocalMachineNameLen
  2045. )
  2046. )
  2047. {
  2048. dwRetCode = GetLastError();
  2049. goto LDone;
  2050. }
  2051. *ppLocalMachineName = pLocalMachineName;
  2052. pLocalMachineName = NULL;
  2053. LDone:
  2054. LocalFree(pLocalMachineName);
  2055. return dwRetCode;
  2056. }
  2057. /*
  2058. Returns:
  2059. NO_ERROR: iff Success
  2060. Notes:
  2061. If this function returns NO_ERROR,
  2062. CertFreeCertificateContext(*ppCertContext) must be called.
  2063. */
  2064. DWORD
  2065. GetDefaultClientMachineCert(
  2066. IN HCERTSTORE hCertStore,
  2067. OUT PCCERT_CONTEXT* ppCertContext
  2068. )
  2069. {
  2070. CTL_USAGE CtlUsage;
  2071. CHAR* szUsageIdentifier;
  2072. PCCERT_CONTEXT pCertContext = NULL;
  2073. EAPTLS_HASH FirstCertHash; //This is the hash of first cert
  2074. //with client auth found in the store
  2075. PCCERT_CONTEXT pCertContextPrev = NULL; //Previous context in the search
  2076. EAPTLS_HASH SelectedCertHash; //Hash of the certificate last selected
  2077. FILETIME SelectedCertNotBefore; //Not Before date of last selected
  2078. EAPTLS_HASH TempHash; //Scratch variable
  2079. WCHAR * pwszIdentity = NULL; //Machine Name in the cert
  2080. WCHAR * pLocalMachineName = NULL; //Local Machine Name
  2081. DWORD dwErr = NO_ERROR;
  2082. BOOL fGotIdentity;
  2083. CRYPT_HASH_BLOB HashBlob;
  2084. EapTlsTrace("GetDefaultClientMachineCert");
  2085. RTASSERT(NULL != ppCertContext);
  2086. ZeroMemory( &SelectedCertHash, sizeof(SelectedCertHash) );
  2087. ZeroMemory( &SelectedCertNotBefore, sizeof(SelectedCertNotBefore) );
  2088. *ppCertContext = NULL;
  2089. dwErr = GetLocalMachineName ( &pLocalMachineName );
  2090. if ( NO_ERROR != dwErr )
  2091. {
  2092. EapTlsTrace("Error getting LocalMachine Name 0x%x",
  2093. dwErr);
  2094. goto LDone;
  2095. }
  2096. szUsageIdentifier = szOID_PKIX_KP_CLIENT_AUTH;
  2097. CtlUsage.cUsageIdentifier = 1;
  2098. CtlUsage.rgpszUsageIdentifier = &szUsageIdentifier;
  2099. pCertContext = CertFindCertificateInStore(hCertStore,
  2100. X509_ASN_ENCODING,
  2101. 0,
  2102. CERT_FIND_ENHKEY_USAGE,
  2103. &CtlUsage,
  2104. NULL);
  2105. if ( NULL == pCertContext )
  2106. {
  2107. dwErr = GetLastError();
  2108. EapTlsTrace("CertFindCertificateInStore failed and returned 0x%x",
  2109. dwErr);
  2110. if ( CRYPT_E_NOT_FOUND == dwErr )
  2111. {
  2112. dwErr = ERROR_NO_EAPTLS_CERTIFICATE;
  2113. }
  2114. goto LDone;
  2115. }
  2116. FirstCertHash.cbHash = MAX_HASH_SIZE;
  2117. //
  2118. //Store the hash of first cert. In case we dont find any cert that exactly matches
  2119. //the filtering, we need to use this.
  2120. if (!CertGetCertificateContextProperty( pCertContext,
  2121. CERT_HASH_PROP_ID,
  2122. FirstCertHash.pbHash,
  2123. &(FirstCertHash.cbHash)
  2124. )
  2125. )
  2126. {
  2127. dwErr = GetLastError();
  2128. EapTlsTrace("CertGetCertificateContextProperty failed and "
  2129. "returned 0x%x", dwErr);
  2130. goto LDone;
  2131. }
  2132. do
  2133. {
  2134. //Check time validity of the cert.
  2135. if ( !FCheckTimeValidity( pCertContext) )
  2136. {
  2137. //cert expired. So skip it
  2138. EapTlsTrace("Found expired Cert. Skipping this cert.");
  2139. goto LWhileEnd;
  2140. }
  2141. fGotIdentity = FALSE;
  2142. //
  2143. //Get the subject Alt Name
  2144. //
  2145. if ( FMachineAuthCertToStr(pCertContext, &pwszIdentity) )
  2146. {
  2147. fGotIdentity = TRUE;
  2148. }
  2149. else
  2150. {
  2151. EapTlsTrace("Could not get identity from subject alt name.");
  2152. if ( FCertToStr(pCertContext, 0, TRUE, &pwszIdentity))
  2153. {
  2154. fGotIdentity = TRUE;
  2155. }
  2156. }
  2157. if ( fGotIdentity )
  2158. {
  2159. //
  2160. //Check to see if this is the same identity as this machine
  2161. //
  2162. if ( !_wcsicmp ( pwszIdentity, pLocalMachineName ) )
  2163. {
  2164. //
  2165. //Store the hash of cert.
  2166. TempHash.cbHash = MAX_HASH_SIZE;
  2167. if (!CertGetCertificateContextProperty( pCertContext,
  2168. CERT_HASH_PROP_ID,
  2169. TempHash.pbHash,
  2170. &(TempHash.cbHash)
  2171. )
  2172. )
  2173. {
  2174. EapTlsTrace("CertGetCertificateContextProperty failed and "
  2175. "returned 0x%x. Skipping this certificate", GetLastError());
  2176. goto LWhileEnd;
  2177. }
  2178. //
  2179. //Got a cert so if there is already a cert selected,
  2180. //compare the file time of this cert with the one
  2181. //already selected. If this is more recent, use this
  2182. //one.
  2183. //
  2184. if ( SelectedCertHash.cbHash )
  2185. {
  2186. if ( CompareFileTime( &SelectedCertNotBefore,
  2187. &(pCertContext->pCertInfo->NotBefore)
  2188. ) < 0
  2189. )
  2190. {
  2191. //Got a newer cert so replace the old cert with new one
  2192. CopyMemory ( &SelectedCertHash,
  2193. &TempHash,
  2194. sizeof(SelectedCertHash)
  2195. );
  2196. CopyMemory ( &SelectedCertNotBefore,
  2197. &(pCertContext->pCertInfo->NotBefore),
  2198. sizeof( SelectedCertNotBefore )
  2199. );
  2200. }
  2201. }
  2202. else
  2203. {
  2204. //
  2205. //This is the first cert. So copy over the hash and
  2206. //file time.
  2207. CopyMemory ( &SelectedCertHash,
  2208. &TempHash,
  2209. sizeof(SelectedCertHash)
  2210. );
  2211. CopyMemory ( &SelectedCertNotBefore,
  2212. &(pCertContext->pCertInfo->NotBefore),
  2213. sizeof( SelectedCertNotBefore )
  2214. );
  2215. }
  2216. }
  2217. else
  2218. {
  2219. EapTlsTrace("Could not get identity from the cert. skipping this cert.");
  2220. }
  2221. }
  2222. else
  2223. {
  2224. EapTlsTrace("Could not get identity from the cert. skipping this cert.");
  2225. }
  2226. LWhileEnd:
  2227. pCertContextPrev = pCertContext;
  2228. if ( pwszIdentity )
  2229. {
  2230. LocalFree ( pwszIdentity );
  2231. pwszIdentity = NULL;
  2232. }
  2233. //Get the next certificate.
  2234. pCertContext = CertFindCertificateInStore(hCertStore,
  2235. X509_ASN_ENCODING,
  2236. 0,
  2237. CERT_FIND_ENHKEY_USAGE,
  2238. &CtlUsage,
  2239. pCertContextPrev );
  2240. }while ( pCertContext );
  2241. //
  2242. //Now that we have enumerated all the certs,
  2243. //check to see if we have a selected cert. If no selected
  2244. //cert is present, send back the first cert.
  2245. //
  2246. if ( SelectedCertHash.cbHash )
  2247. {
  2248. EapTlsTrace("Found Machine Cert based on machinename, client auth, time validity.");
  2249. HashBlob.cbData = SelectedCertHash.cbHash;
  2250. HashBlob.pbData = SelectedCertHash.pbHash;
  2251. }
  2252. else
  2253. {
  2254. EapTlsTrace("Did not find Machine Cert based on the given machinename, client auth, time validity. Using the first cert with Client Auth OID.");
  2255. HashBlob.cbData = FirstCertHash.cbHash;
  2256. HashBlob.pbData = FirstCertHash.pbHash;
  2257. }
  2258. *ppCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING,
  2259. 0, CERT_FIND_HASH, &HashBlob, NULL);
  2260. if (NULL == *ppCertContext)
  2261. {
  2262. dwErr = GetLastError();
  2263. EapTlsTrace("CertFindCertificateInStore failed with 0x%x.", dwErr);
  2264. if ( CRYPT_E_NOT_FOUND == dwErr )
  2265. {
  2266. dwErr = ERROR_NO_EAPTLS_CERTIFICATE;
  2267. }
  2268. }
  2269. LDone:
  2270. LocalFree (pLocalMachineName);
  2271. LocalFree (pwszIdentity);
  2272. if ( NO_ERROR != dwErr )
  2273. {
  2274. if ( pCertContext )
  2275. {
  2276. CertFreeCertificateContext( pCertContext );
  2277. }
  2278. }
  2279. EapTlsTrace("GetDefaultClientMachineCert done.");
  2280. return(dwErr);
  2281. }
  2282. /*
  2283. Returns:
  2284. NO_ERROR: iff Success
  2285. Notes:
  2286. If this function returns NO_ERROR,
  2287. CertFreeCertificateContext(*ppCertContext) must be called.
  2288. */
  2289. DWORD
  2290. GetDefaultMachineCert(
  2291. IN HCERTSTORE hCertStore,
  2292. OUT PCCERT_CONTEXT* ppCertContext
  2293. )
  2294. {
  2295. CTL_USAGE CtlUsage;
  2296. CHAR* szUsageIdentifier;
  2297. PCCERT_CONTEXT pCertContext;
  2298. DWORD dwErr = NO_ERROR;
  2299. EapTlsTrace("GetDefaultMachineCert");
  2300. RTASSERT(NULL != ppCertContext);
  2301. *ppCertContext = NULL;
  2302. szUsageIdentifier = szOID_PKIX_KP_SERVER_AUTH;
  2303. CtlUsage.cUsageIdentifier = 1;
  2304. CtlUsage.rgpszUsageIdentifier = &szUsageIdentifier;
  2305. pCertContext = CertFindCertificateInStore(hCertStore,
  2306. X509_ASN_ENCODING, 0, CERT_FIND_ENHKEY_USAGE,
  2307. &CtlUsage, NULL);
  2308. if (NULL == pCertContext)
  2309. {
  2310. dwErr = GetLastError();
  2311. EapTlsTrace("CertFindCertificateInStore failed and returned 0x%x",
  2312. dwErr);
  2313. goto LDone;
  2314. }
  2315. *ppCertContext = pCertContext;
  2316. LDone:
  2317. return(dwErr);
  2318. }
  2319. /*
  2320. Returns:
  2321. Notes:
  2322. Stolen from \private\windows\gina\msgina\wlsec.c
  2323. */
  2324. VOID
  2325. RevealPassword(
  2326. IN UNICODE_STRING* pHiddenPassword
  2327. )
  2328. {
  2329. SECURITY_SEED_AND_LENGTH* SeedAndLength;
  2330. UCHAR Seed;
  2331. SeedAndLength = (SECURITY_SEED_AND_LENGTH*)&pHiddenPassword->Length;
  2332. Seed = SeedAndLength->Seed;
  2333. SeedAndLength->Seed = 0;
  2334. RtlRunDecodeUnicodeString(Seed, pHiddenPassword);
  2335. }
  2336. DWORD GetMBytePIN ( WCHAR * pwszPIN, CHAR ** ppszPIN )
  2337. {
  2338. DWORD count = 0;
  2339. CHAR * pszPin = NULL;
  2340. DWORD dwErr = NO_ERROR;
  2341. count = WideCharToMultiByte(
  2342. CP_UTF8,
  2343. 0,
  2344. pwszPIN,
  2345. -1,
  2346. NULL,
  2347. 0,
  2348. NULL,
  2349. NULL);
  2350. if (0 == count)
  2351. {
  2352. dwErr = GetLastError();
  2353. EapTlsTrace("WideCharToMultiByte failed: %d", dwErr);
  2354. goto LDone;
  2355. }
  2356. pszPin = LocalAlloc(LPTR, count);
  2357. if (NULL == pszPin)
  2358. {
  2359. dwErr = GetLastError();
  2360. EapTlsTrace("LocalAlloc failed: 0x%x", dwErr);
  2361. goto LDone;
  2362. }
  2363. count = WideCharToMultiByte(
  2364. CP_UTF8,
  2365. 0,
  2366. pwszPIN,
  2367. -1,
  2368. pszPin,
  2369. count,
  2370. NULL,
  2371. NULL);
  2372. if (0 == count)
  2373. {
  2374. dwErr = GetLastError();
  2375. EapTlsTrace("WideCharToMultiByte failed: %d", dwErr);
  2376. goto LDone;
  2377. }
  2378. *ppszPIN = pszPin;
  2379. LDone:
  2380. if ( NO_ERROR != dwErr )
  2381. {
  2382. if ( pszPin )
  2383. LocalFree(pszPin);
  2384. }
  2385. return dwErr;
  2386. }
  2387. /*
  2388. Returns:
  2389. NO_ERROR: iff Success
  2390. Notes:
  2391. */
  2392. DWORD
  2393. GetCertFromLogonInfo(
  2394. IN BYTE* pUserDataIn,
  2395. IN DWORD dwSizeOfUserDataIn,
  2396. OUT PCCERT_CONTEXT* ppCertContext
  2397. )
  2398. {
  2399. EAPLOGONINFO* pEapLogonInfo = (EAPLOGONINFO*)pUserDataIn;
  2400. BYTE* pbLogonInfo = NULL;
  2401. BYTE* pbPinInfo;
  2402. WCHAR* wszPassword = NULL;
  2403. CHAR* pszPIN = NULL; //Multibyte Version of the PIN
  2404. UNICODE_STRING UnicodeString;
  2405. PCCERT_CONTEXT pCertContext = NULL;
  2406. BOOL fInitialized = FALSE;
  2407. NTSTATUS Status;
  2408. DWORD dwErr = NO_ERROR;
  2409. CERT_KEY_CONTEXT stckContext;
  2410. DWORD cbstckContext= sizeof(CERT_KEY_CONTEXT);
  2411. EapTlsTrace("GetCertFromLogonInfo");
  2412. RTASSERT(NULL != ppCertContext);
  2413. *ppCertContext = NULL;
  2414. if ( 0 == pEapLogonInfo->dwLogonInfoSize
  2415. || 0 == pEapLogonInfo->dwPINInfoSize
  2416. || 0 == dwSizeOfUserDataIn)
  2417. {
  2418. dwErr = E_FAIL;
  2419. goto LDone;
  2420. }
  2421. pbLogonInfo = LocalAlloc(LPTR, pEapLogonInfo->dwLogonInfoSize);
  2422. if (NULL == pbLogonInfo)
  2423. {
  2424. dwErr = GetLastError();
  2425. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  2426. goto LDone;
  2427. }
  2428. CopyMemory(pbLogonInfo,
  2429. (BYTE*)pEapLogonInfo + pEapLogonInfo->dwOffsetLogonInfo,
  2430. pEapLogonInfo->dwLogonInfoSize);
  2431. pbPinInfo = (BYTE*)pEapLogonInfo + pEapLogonInfo->dwOffsetPINInfo;
  2432. wszPassword = LocalAlloc(LPTR, pEapLogonInfo->dwPINInfoSize);
  2433. if (NULL == wszPassword)
  2434. {
  2435. dwErr = GetLastError();
  2436. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  2437. goto LDone;
  2438. }
  2439. CopyMemory(wszPassword, pbPinInfo + 2 * sizeof(USHORT),
  2440. pEapLogonInfo->dwPINInfoSize - 2 * sizeof(USHORT));
  2441. UnicodeString.Length = *((USHORT*)pbPinInfo);
  2442. UnicodeString.MaximumLength = *((USHORT*)pbPinInfo + 1);
  2443. UnicodeString.Buffer = wszPassword;
  2444. Status = ScHelperInitializeContext(pbLogonInfo,
  2445. pEapLogonInfo->dwLogonInfoSize);
  2446. if (STATUS_SUCCESS != Status)
  2447. {
  2448. dwErr = Status;
  2449. EapTlsTrace("ScHelperInitializeContext failed and returned 0x%x",
  2450. dwErr);
  2451. goto LDone;
  2452. }
  2453. fInitialized = TRUE;
  2454. RevealPassword(&UnicodeString);
  2455. Status = ScHelperGetCertFromLogonInfo(pbLogonInfo, &UnicodeString,
  2456. &pCertContext);
  2457. if (STATUS_SUCCESS != Status)
  2458. {
  2459. dwErr = Status;
  2460. EapTlsTrace("ScHelperGetCertFromLogonInfo failed and returned 0x%x",
  2461. dwErr);
  2462. goto LDone;
  2463. }
  2464. //BUGID: 260728 - ScHelperGetCertFromLogonInfo does not associate the PIN
  2465. // with certificate context. Hence the following lines of code are needed
  2466. // to do the needful.
  2467. if ( ! CertGetCertificateContextProperty ( pCertContext,
  2468. CERT_KEY_CONTEXT_PROP_ID,
  2469. &stckContext,
  2470. &cbstckContext
  2471. )
  2472. )
  2473. {
  2474. dwErr = Status = GetLastError();
  2475. EapTlsTrace ("CertGetCertificateContextProperty failed and returned 0x%x",
  2476. dwErr
  2477. );
  2478. goto LDone;
  2479. }
  2480. dwErr = GetMBytePIN ( wszPassword, &pszPIN );
  2481. if ( dwErr != NO_ERROR )
  2482. {
  2483. goto LDone;
  2484. }
  2485. if (!CryptSetProvParam(
  2486. stckContext.hCryptProv,
  2487. PP_KEYEXCHANGE_PIN,
  2488. pszPIN,
  2489. 0))
  2490. {
  2491. dwErr = GetLastError();
  2492. EapTlsTrace("CryptSetProvParam failed: 0x%x", dwErr);
  2493. ZeroMemory(pszPIN, strlen(pszPIN));
  2494. goto LDone;
  2495. }
  2496. // Zero the entire allocated buffer.
  2497. ZeroMemory(wszPassword, pEapLogonInfo->dwPINInfoSize);
  2498. ZeroMemory(pszPIN, strlen(pszPIN));
  2499. *ppCertContext = pCertContext;
  2500. pCertContext = NULL;
  2501. LDone:
  2502. if (fInitialized)
  2503. {
  2504. ScHelperRelease(pbLogonInfo);
  2505. }
  2506. if (NULL != pCertContext)
  2507. {
  2508. CertFreeCertificateContext(pCertContext);
  2509. // Always returns TRUE;
  2510. }
  2511. LocalFree(wszPassword);
  2512. LocalFree(pbLogonInfo);
  2513. if ( pszPIN )
  2514. LocalFree ( pszPIN );
  2515. return(dwErr);
  2516. }
  2517. /*
  2518. Returns:
  2519. NO_ERROR: iff Success
  2520. Notes:
  2521. If this function returns TRUE, LocalFree(*ppwszIdentity) must be called.
  2522. */
  2523. DWORD
  2524. GetIdentityFromLogonInfo(
  2525. IN BYTE* pUserDataIn,
  2526. IN DWORD dwSizeOfUserDataIn,
  2527. OUT WCHAR** ppwszIdentity
  2528. )
  2529. {
  2530. WCHAR* pwszIdentity = NULL;
  2531. PCCERT_CONTEXT pCertContext = NULL;
  2532. DWORD dwErr = NO_ERROR;
  2533. RTASSERT(NULL != pUserDataIn);
  2534. RTASSERT(NULL != ppwszIdentity);
  2535. *ppwszIdentity = NULL;
  2536. dwErr = GetCertFromLogonInfo(pUserDataIn, dwSizeOfUserDataIn,
  2537. &pCertContext);
  2538. if (NO_ERROR != dwErr)
  2539. {
  2540. goto LDone;
  2541. }
  2542. if (FCertToStr(pCertContext, 0, FALSE, &pwszIdentity))
  2543. {
  2544. EapTlsTrace("(logon info) The name in the certificate is: %ws",
  2545. pwszIdentity);
  2546. *ppwszIdentity = pwszIdentity;
  2547. pwszIdentity = NULL;
  2548. }
  2549. LDone:
  2550. LocalFree(pwszIdentity);
  2551. if (NULL != pCertContext)
  2552. {
  2553. CertFreeCertificateContext(pCertContext);
  2554. // Always returns TRUE;
  2555. }
  2556. return(dwErr);
  2557. }
  2558. /*
  2559. Returns:
  2560. NO_ERROR: iff Success
  2561. Notes:
  2562. There are two types of structures that can come in:
  2563. 1. Version 0 structure which comes in as a a part of
  2564. CM profile created on w2k or as a part of a
  2565. connectoid that gor upgraded from w2k
  2566. We change the data structure to new v1
  2567. data structure here
  2568. 2. Get a version 1 structure and it is all cool.
  2569. Note that the first x bytes of version 1 data structure
  2570. are exactly the same as version 0.
  2571. */
  2572. DWORD
  2573. ReadConnectionData(
  2574. IN BOOL fWireless,
  2575. IN BYTE* pConnectionDataIn,
  2576. IN DWORD dwSizeOfConnectionDataIn,
  2577. OUT EAPTLS_CONN_PROPERTIES** ppConnProp
  2578. )
  2579. {
  2580. DWORD dwErr = NO_ERROR;
  2581. EAPTLS_CONN_PROPERTIES* pConnProp = NULL;
  2582. EAPTLS_CONN_PROPERTIES* pConnPropv1 = NULL;
  2583. RTASSERT(NULL != ppConnProp);
  2584. if ( dwSizeOfConnectionDataIn < sizeof(EAPTLS_CONN_PROPERTIES) )
  2585. {
  2586. pConnProp = LocalAlloc(LPTR, sizeof(EAPTLS_CONN_PROPERTIES) + sizeof(EAPTLS_CONN_PROPERTIES_V1_EXTRA));
  2587. if (NULL == pConnProp)
  2588. {
  2589. dwErr = GetLastError();
  2590. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  2591. goto LDone;
  2592. }
  2593. //This is a new structure
  2594. pConnProp->dwVersion = 2;
  2595. pConnProp->dwSize = sizeof(EAPTLS_CONN_PROPERTIES);
  2596. if ( fWireless )
  2597. {
  2598. //
  2599. // Set the defaults appropriately
  2600. //
  2601. pConnProp->fFlags |= EAPTLS_CONN_FLAG_REGISTRY;
  2602. pConnProp->fFlags |= EAPTLS_CONN_FLAG_SIMPLE_CERT_SEL;
  2603. pConnProp->fFlags |= EAPTLS_CONN_FLAG_NO_VALIDATE_NAME;
  2604. }
  2605. }
  2606. else
  2607. {
  2608. RTASSERT(NULL != pConnectionDataIn);
  2609. //
  2610. //Check to see if this is a version 0 structure
  2611. //If it is a version 0 structure then we migrate it to version1
  2612. //
  2613. pConnProp = LocalAlloc(LPTR, dwSizeOfConnectionDataIn);
  2614. if (NULL == pConnProp)
  2615. {
  2616. dwErr = GetLastError();
  2617. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  2618. goto LDone;
  2619. }
  2620. // If the user has mucked with the phonebook, we mustn't be affected.
  2621. // The size must be correct.
  2622. CopyMemory(pConnProp, pConnectionDataIn, dwSizeOfConnectionDataIn);
  2623. pConnProp->dwSize = dwSizeOfConnectionDataIn;
  2624. //
  2625. // The Unicode string must be NULL terminated.
  2626. //
  2627. /*
  2628. ((BYTE*)pConnProp)[dwSizeOfConnectionDataIn - 2] = 0;
  2629. ((BYTE*)pConnProp)[dwSizeOfConnectionDataIn - 1] = 0;
  2630. */
  2631. pConnPropv1 = LocalAlloc(LPTR,
  2632. dwSizeOfConnectionDataIn +
  2633. sizeof(EAPTLS_CONN_PROPERTIES_V1_EXTRA)
  2634. );
  2635. if ( NULL == pConnPropv1 )
  2636. {
  2637. dwErr = GetLastError();
  2638. EapTlsTrace("LocalAlloc failed while allocating v1 structure and returned %d", dwErr );
  2639. goto LDone;
  2640. }
  2641. CopyMemory ( pConnPropv1, pConnProp, dwSizeOfConnectionDataIn);
  2642. //
  2643. //Check to see if the original struct has hash set
  2644. //
  2645. /*
  2646. if ( pConnProp->Hash.cbHash )
  2647. {
  2648. ConnPropSetNumHashes( pConnPropv1, 1 );
  2649. }
  2650. */
  2651. if ( 2 != pConnPropv1->dwVersion )
  2652. {
  2653. if ( pConnPropv1->fFlags & EAPTLS_CONN_FLAG_REGISTRY )
  2654. {
  2655. pConnPropv1->fFlags |= EAPTLS_CONN_FLAG_SIMPLE_CERT_SEL;
  2656. }
  2657. pConnPropv1->dwVersion = 2;
  2658. }
  2659. LocalFree ( pConnProp );
  2660. pConnProp = pConnPropv1;
  2661. pConnPropv1 = NULL;
  2662. }
  2663. *ppConnProp = pConnProp;
  2664. pConnProp = NULL;
  2665. LDone:
  2666. LocalFree(pConnProp);
  2667. LocalFree(pConnPropv1);
  2668. return(dwErr);
  2669. }
  2670. /*
  2671. Returns:
  2672. NO_ERROR: iff Success
  2673. Notes:
  2674. */
  2675. DWORD
  2676. ReadUserData(
  2677. IN BYTE* pUserDataIn,
  2678. IN DWORD dwSizeOfUserDataIn,
  2679. OUT EAPTLS_USER_PROPERTIES** ppUserProp
  2680. )
  2681. {
  2682. DWORD dwErr = NO_ERROR;
  2683. EAPTLS_USER_PROPERTIES* pUserProp = NULL;
  2684. RTASSERT(NULL != ppUserProp);
  2685. if (dwSizeOfUserDataIn < sizeof(EAPTLS_USER_PROPERTIES))
  2686. {
  2687. pUserProp = LocalAlloc(LPTR, sizeof(EAPTLS_USER_PROPERTIES));
  2688. if (NULL == pUserProp)
  2689. {
  2690. dwErr = GetLastError();
  2691. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  2692. goto LDone;
  2693. }
  2694. pUserProp->dwVersion = 0;
  2695. pUserProp->dwSize = sizeof(EAPTLS_USER_PROPERTIES);
  2696. pUserProp->pwszDiffUser = pUserProp->awszString;
  2697. pUserProp->dwPinOffset = 0;
  2698. pUserProp->pwszPin = pUserProp->awszString + pUserProp->dwPinOffset;
  2699. }
  2700. else
  2701. {
  2702. RTASSERT(NULL != pUserDataIn);
  2703. pUserProp = LocalAlloc(LPTR, dwSizeOfUserDataIn);
  2704. if (NULL == pUserProp)
  2705. {
  2706. dwErr = GetLastError();
  2707. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  2708. goto LDone;
  2709. }
  2710. CopyMemory(pUserProp, pUserDataIn, dwSizeOfUserDataIn);
  2711. // If someone has mucked with the registry, we mustn't
  2712. // be affected.
  2713. pUserProp->dwSize = dwSizeOfUserDataIn;
  2714. pUserProp->pwszDiffUser = pUserProp->awszString;
  2715. pUserProp->pwszPin = pUserProp->awszString + pUserProp->dwPinOffset;
  2716. }
  2717. *ppUserProp = pUserProp;
  2718. pUserProp = NULL;
  2719. LDone:
  2720. LocalFree(pUserProp);
  2721. return(dwErr);
  2722. }
  2723. /*
  2724. Returns:
  2725. NO_ERROR: iff Success
  2726. Notes:
  2727. */
  2728. DWORD
  2729. AllocUserDataWithNewIdentity(
  2730. IN EAPTLS_USER_PROPERTIES* pUserProp,
  2731. IN WCHAR* pwszIdentity,
  2732. OUT EAPTLS_USER_PROPERTIES** ppUserProp
  2733. )
  2734. {
  2735. DWORD dwNumChars;
  2736. EAPTLS_USER_PROPERTIES* pUserPropTemp = NULL;
  2737. DWORD dwSize;
  2738. DWORD dwErr = NO_ERROR;
  2739. *ppUserProp = NULL;
  2740. dwNumChars = wcslen(pwszIdentity);
  2741. dwSize = sizeof(EAPTLS_USER_PROPERTIES) +
  2742. (dwNumChars + wcslen(pUserProp->pwszPin) + 1) * sizeof(WCHAR);
  2743. pUserPropTemp = LocalAlloc(LPTR, dwSize);
  2744. if (NULL == pUserPropTemp)
  2745. {
  2746. dwErr = GetLastError();
  2747. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  2748. goto LDone;
  2749. }
  2750. CopyMemory(pUserPropTemp, pUserProp, sizeof(EAPTLS_USER_PROPERTIES));
  2751. pUserPropTemp->dwSize = dwSize;
  2752. pUserPropTemp->pwszDiffUser = pUserPropTemp->awszString;
  2753. wcscpy(pUserPropTemp->pwszDiffUser, pwszIdentity);
  2754. pUserPropTemp->dwPinOffset = dwNumChars + 1;
  2755. pUserPropTemp->pwszPin = pUserPropTemp->awszString +
  2756. pUserPropTemp->dwPinOffset;
  2757. wcscpy(pUserPropTemp->pwszPin, pUserProp->pwszPin);
  2758. *ppUserProp = pUserPropTemp;
  2759. pUserPropTemp = NULL;
  2760. ZeroMemory(pUserProp, pUserProp->dwSize);
  2761. LDone:
  2762. LocalFree(pUserPropTemp);
  2763. return(dwErr);
  2764. }
  2765. /*
  2766. Returns:
  2767. NO_ERROR: iff Success
  2768. Notes:
  2769. */
  2770. DWORD
  2771. AllocUserDataWithNewPin(
  2772. IN EAPTLS_USER_PROPERTIES* pUserProp,
  2773. IN PBYTE pbPin,
  2774. IN DWORD cbPin,
  2775. OUT EAPTLS_USER_PROPERTIES** ppUserProp
  2776. )
  2777. {
  2778. DWORD dwNumChars;
  2779. EAPTLS_USER_PROPERTIES* pUserPropTemp = NULL;
  2780. DWORD dwSize;
  2781. DWORD dwErr = NO_ERROR;
  2782. *ppUserProp = NULL;
  2783. dwNumChars = wcslen(pUserProp->pwszDiffUser);
  2784. dwSize = sizeof(EAPTLS_USER_PROPERTIES) +
  2785. (dwNumChars + 1 ) * sizeof(WCHAR) + cbPin;
  2786. pUserPropTemp = LocalAlloc(LPTR, dwSize);
  2787. if (NULL == pUserPropTemp)
  2788. {
  2789. dwErr = GetLastError();
  2790. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  2791. goto LDone;
  2792. }
  2793. CopyMemory(pUserPropTemp, pUserProp, sizeof(EAPTLS_USER_PROPERTIES));
  2794. pUserPropTemp->dwSize = dwSize;
  2795. pUserPropTemp->pwszDiffUser = pUserPropTemp->awszString;
  2796. wcscpy(pUserPropTemp->pwszDiffUser, pUserProp->pwszDiffUser);
  2797. pUserPropTemp->dwPinOffset = dwNumChars + 1;
  2798. pUserPropTemp->pwszPin = pUserPropTemp->awszString +
  2799. pUserPropTemp->dwPinOffset;
  2800. CopyMemory(pUserPropTemp->pwszPin, pbPin, cbPin);
  2801. *ppUserProp = pUserPropTemp;
  2802. pUserPropTemp = NULL;
  2803. ZeroMemory(pUserProp, pUserProp->dwSize);
  2804. LDone:
  2805. LocalFree(pUserPropTemp);
  2806. return(dwErr);
  2807. }
  2808. /*
  2809. Returns:
  2810. Notes:
  2811. String resource message loader routine. Returns the address of a string
  2812. corresponding to string resource dwStringId or NULL if error. It is caller's
  2813. responsibility to LocalFree the returned string.
  2814. */
  2815. WCHAR*
  2816. WszFromId(
  2817. IN HINSTANCE hInstance,
  2818. IN DWORD dwStringId
  2819. )
  2820. {
  2821. WCHAR* wszBuf = NULL;
  2822. int cchBuf = 256;
  2823. int cchGot;
  2824. for (;;)
  2825. {
  2826. wszBuf = LocalAlloc(LPTR, cchBuf * sizeof(WCHAR));
  2827. if (NULL == wszBuf)
  2828. {
  2829. break;
  2830. }
  2831. /*
  2832. LoadString wants to deal with character-counts rather than
  2833. byte-counts...weird. Oh, and if you're thinking I could FindResource
  2834. then SizeofResource to figure out the string size, be advised it
  2835. doesn't work. From perusing the LoadString source, it appears the
  2836. RT_STRING resource type requests a segment of 16 strings not an
  2837. individual string.
  2838. */
  2839. cchGot = LoadStringW(hInstance, (UINT)dwStringId, wszBuf, cchBuf);
  2840. if (cchGot < cchBuf - 1)
  2841. {
  2842. // Good, got the whole string.
  2843. break;
  2844. }
  2845. // Uh oh, LoadStringW filled the buffer entirely which could mean the
  2846. // string was truncated. Try again with a larger buffer to be sure it
  2847. // wasn't.
  2848. LocalFree(wszBuf);
  2849. cchBuf += 256;
  2850. }
  2851. return(wszBuf);
  2852. }
  2853. /*
  2854. Following functions are required around the
  2855. messy CONN_PROP structure to support v1/v0 etc.
  2856. This is really bad.
  2857. All the functions assume that version 1.0 format
  2858. is passed in.
  2859. */
  2860. EAPTLS_CONN_PROPERTIES_V1_EXTRA UNALIGNED * ConnPropGetExtraPointer (EAPTLS_CONN_PROPERTIES * pConnProp)
  2861. {
  2862. return (EAPTLS_CONN_PROPERTIES_V1_EXTRA UNALIGNED *)
  2863. ( pConnProp->awszServerName + wcslen(pConnProp->awszServerName) + 1);
  2864. }
  2865. DWORD ConnPropGetNumHashes(EAPTLS_CONN_PROPERTIES * pConnProp )
  2866. {
  2867. EAPTLS_CONN_PROPERTIES_V1_EXTRA UNALIGNED * pExtra = ConnPropGetExtraPointer(pConnProp);
  2868. return pExtra->dwNumHashes;
  2869. }
  2870. void ConnPropSetNumHashes(EAPTLS_CONN_PROPERTIES * pConnProp, DWORD dwNumHashes )
  2871. {
  2872. EAPTLS_CONN_PROPERTIES_V1_EXTRA UNALIGNED * pExtra = ConnPropGetExtraPointer(pConnProp);
  2873. pExtra->dwNumHashes = dwNumHashes;
  2874. return;
  2875. }
  2876. DWORD ConnPropGetV1Struct ( EAPTLS_CONN_PROPERTIES * pConnProp, EAPTLS_CONN_PROPERTIES_V1 ** ppConnPropv1 )
  2877. {
  2878. DWORD dwRetCode = NO_ERROR;
  2879. EAPTLS_CONN_PROPERTIES_V1 * pConnPropv1 = NULL;
  2880. EAPTLS_CONN_PROPERTIES_V1_EXTRA UNALIGNED * pExtra = ConnPropGetExtraPointer(pConnProp);
  2881. //
  2882. //This function assumes that the struct that comes in is at
  2883. //version 1. Which means at least sizeof(EAPTLS_CONN_PROPERTIES) +
  2884. //EAPTLS_CONN_PROPERTIES_V1_EXTRA in size.
  2885. //
  2886. //
  2887. //First get the amount of memory required to be allocated
  2888. //
  2889. pConnPropv1 = LocalAlloc ( LPTR,
  2890. sizeof( EAPTLS_CONN_PROPERTIES_V1 ) + //sizeof the basic struct
  2891. pExtra->dwNumHashes * sizeof( EAPTLS_HASH ) + //num hashes
  2892. wcslen( pConnProp->awszServerName ) * sizeof(WCHAR) + sizeof(WCHAR)//sizeof the string
  2893. );
  2894. if ( NULL == pConnPropv1 )
  2895. {
  2896. dwRetCode = GetLastError();
  2897. goto LDone;
  2898. }
  2899. //
  2900. //Convert the structure
  2901. //
  2902. if ( pConnProp->dwVersion <= 1 )
  2903. pConnPropv1->dwVersion = 1;
  2904. else
  2905. pConnPropv1->dwVersion = 2;
  2906. pConnPropv1->dwSize = sizeof( EAPTLS_CONN_PROPERTIES_V1 ) +
  2907. pExtra->dwNumHashes * sizeof( EAPTLS_HASH ) +
  2908. wcslen( pConnProp->awszServerName ) * sizeof(WCHAR) + sizeof(WCHAR);
  2909. pConnPropv1->fFlags = pConnProp->fFlags;
  2910. pConnPropv1->dwNumHashes = pExtra->dwNumHashes;
  2911. if ( pExtra->dwNumHashes )
  2912. {
  2913. CopyMemory( pConnPropv1->bData, &(pConnProp->Hash), sizeof(EAPTLS_HASH) );
  2914. if ( pExtra->dwNumHashes >1 )
  2915. {
  2916. CopyMemory ( pConnPropv1->bData + sizeof(EAPTLS_HASH),
  2917. pExtra->bData,
  2918. (pExtra->dwNumHashes -1 ) * sizeof(EAPTLS_HASH)
  2919. );
  2920. }
  2921. }
  2922. //Copy the server name
  2923. wcscpy( (WCHAR *)( pConnPropv1->bData + (pExtra->dwNumHashes * sizeof(EAPTLS_HASH) ) ),
  2924. pConnProp->awszServerName
  2925. );
  2926. *ppConnPropv1 = pConnPropv1;
  2927. pConnPropv1 = NULL;
  2928. LDone:
  2929. LocalFree(pConnPropv1);
  2930. return dwRetCode;
  2931. }
  2932. DWORD ConnPropGetV0Struct ( EAPTLS_CONN_PROPERTIES_V1 * pConnPropv1, EAPTLS_CONN_PROPERTIES ** ppConnProp )
  2933. {
  2934. DWORD dwRetCode = NO_ERROR;
  2935. EAPTLS_CONN_PROPERTIES * pConnProp = NULL;
  2936. DWORD dwSize = 0;
  2937. EAPTLS_CONN_PROPERTIES_V1_EXTRA UNALIGNED * pExtrav1 = NULL;
  2938. //
  2939. //First calulate the amount of memory to allocate
  2940. //
  2941. dwSize = sizeof(EAPTLS_CONN_PROPERTIES) +
  2942. (pConnPropv1->dwNumHashes?( pConnPropv1->dwNumHashes - 1 ) * sizeof(EAPTLS_HASH):0) +
  2943. ( wcslen( (LPWSTR) (pConnPropv1->bData + (pConnPropv1->dwNumHashes * sizeof(EAPTLS_HASH)) ) ) * sizeof(WCHAR) ) + sizeof(WCHAR);
  2944. pConnProp = LocalAlloc ( LPTR, dwSize );
  2945. if ( NULL == pConnProp )
  2946. {
  2947. dwRetCode = GetLastError();
  2948. goto LDone;
  2949. }
  2950. if ( pConnPropv1->dwVersion <= 1 )
  2951. pConnProp->dwVersion = 1;
  2952. else
  2953. pConnProp->dwVersion = 2;
  2954. pConnProp->dwSize = dwSize;
  2955. pConnProp->fFlags = pConnPropv1->fFlags;
  2956. if ( pConnPropv1->dwNumHashes > 0 )
  2957. {
  2958. CopyMemory( &(pConnProp->Hash), pConnPropv1->bData, sizeof(EAPTLS_HASH));
  2959. }
  2960. if ( pConnPropv1->bData )
  2961. {
  2962. wcscpy ( pConnProp->awszServerName,
  2963. (LPWSTR )(pConnPropv1->bData + sizeof( EAPTLS_HASH ) * pConnPropv1->dwNumHashes)
  2964. );
  2965. }
  2966. pExtrav1 = (EAPTLS_CONN_PROPERTIES_V1_EXTRA UNALIGNED *)(pConnProp->awszServerName +
  2967. wcslen( pConnProp->awszServerName) + 1);
  2968. pExtrav1->dwNumHashes = pConnPropv1->dwNumHashes;
  2969. if ( pExtrav1->dwNumHashes > 1 )
  2970. {
  2971. CopyMemory( pExtrav1->bData,
  2972. pConnPropv1->bData + sizeof(EAPTLS_HASH),
  2973. ( pConnPropv1->dwNumHashes - 1 ) * sizeof(EAPTLS_HASH)
  2974. );
  2975. }
  2976. *ppConnProp = pConnProp;
  2977. pConnProp = NULL;
  2978. LDone:
  2979. LocalFree(pConnProp);
  2980. return dwRetCode;
  2981. }
  2982. void ShowCertDetails ( HWND hWnd, HCERTSTORE hStore, PCCERT_CONTEXT pCertContext)
  2983. {
  2984. CRYPTUI_VIEWCERTIFICATE_STRUCT vcs;
  2985. BOOL fPropertiesChanged = FALSE;
  2986. ZeroMemory (&vcs, sizeof (vcs));
  2987. vcs.dwSize = sizeof (vcs);
  2988. vcs.hwndParent = hWnd;
  2989. vcs.pCertContext = pCertContext;
  2990. vcs.cStores = 1;
  2991. vcs.rghStores = &hStore;
  2992. vcs.dwFlags |= (CRYPTUI_DISABLE_EDITPROPERTIES|CRYPTUI_DISABLE_ADDTOSTORE);
  2993. CryptUIDlgViewCertificate (&vcs, &fPropertiesChanged);
  2994. return;
  2995. }
  2996. #if 0
  2997. // Location of policy parameters
  2998. #define cwszEAPOLPolicyParams L"Software\\Policies\\Microsoft\\Windows\\Network Connections\\8021X"
  2999. #define cszCARootHash "8021XCARootHash"
  3000. #define SIZE_OF_CA_CONV_STR 3
  3001. #define SIZE_OF_HASH 20
  3002. //
  3003. // ReadGPCARootHashes
  3004. //
  3005. // Description:
  3006. //
  3007. // Function to read parameters created by policy downloads
  3008. // Currently, 8021XCARootHash will be downloaded to the HKLM
  3009. //
  3010. // Arguments:
  3011. // pdwSizeOfRootHashBlob - Size of hash blob in bytes. Each root CA hash
  3012. // will be of SIZE_OF_HASH bytes
  3013. // ppbRootHashBlob - Pointer to hash blob. Caller should free it using
  3014. // LocalFree
  3015. //
  3016. // Return values:
  3017. // ERROR_SUCCESS - success
  3018. // !ERROR_SUCCESS - error
  3019. //
  3020. DWORD
  3021. ReadGPCARootHashes(
  3022. DWORD *pdwSizeOfRootHashBlob,
  3023. PBYTE *ppbRootHashBlob
  3024. )
  3025. {
  3026. HKEY hKey = NULL;
  3027. DWORD dwType = 0;
  3028. DWORD dwSize = 0;
  3029. CHAR *pszCARootHash = NULL;
  3030. DWORD i = 0;
  3031. CHAR cszCharConv[SIZE_OF_CA_CONV_STR];
  3032. BYTE *pbRootHashBlob = NULL;
  3033. DWORD dwSizeOfHashBlob = 0;
  3034. LONG lError = ERROR_SUCCESS;
  3035. lError = RegOpenKeyEx(
  3036. HKEY_LOCAL_MACHINE,
  3037. cwszEAPOLPolicyParams,
  3038. 0,
  3039. KEY_READ,
  3040. &hKey
  3041. );
  3042. if (lError != ERROR_SUCCESS)
  3043. {
  3044. EapTlsTrace("ReadCARootHashes: RegOpenKeyEx failed with error %ld",
  3045. lError);
  3046. goto LDone;
  3047. }
  3048. lError = RegQueryValueExA(
  3049. hKey,
  3050. cszCARootHash,
  3051. 0,
  3052. &dwType,
  3053. NULL,
  3054. &dwSize
  3055. );
  3056. if (lError == ERROR_SUCCESS)
  3057. {
  3058. // Each SHA1 hash will be 2*SIZE_OF_HASH chars
  3059. // Each BYTE in the hash will be represented by 2 CHARs,
  3060. // 1 for each nibble
  3061. // The hashblob should contain an integral number of hashes
  3062. if ((dwSize-1*sizeof(CHAR))%(2*SIZE_OF_HASH*sizeof(CHAR)))
  3063. {
  3064. EapTlsTrace("ReadCARootHashes: Invalid hash length (%ld)",
  3065. dwSize);
  3066. goto LDone;
  3067. }
  3068. pszCARootHash = (CHAR *)LocalAlloc(LPTR, dwSize);
  3069. if (pszCARootHash == NULL)
  3070. {
  3071. lError = GetLastError();
  3072. EapTlsTrace("ReadCARootHashes: LocalAlloc failed for pwszCARootHash");
  3073. goto LDone;
  3074. }
  3075. lError = RegQueryValueExA(
  3076. hKey,
  3077. cszCARootHash,
  3078. 0,
  3079. &dwType,
  3080. (BYTE *)pszCARootHash,
  3081. &dwSize
  3082. );
  3083. if (lError != ERROR_SUCCESS)
  3084. {
  3085. EapTlsTrace("ReadCARootHashes: RegQueryValueEx 2 failed with error (%ld)",
  3086. lError);
  3087. goto LDone;
  3088. }
  3089. dwSizeOfHashBlob = (dwSize-1*sizeof(CHAR))/(2*sizeof(CHAR));
  3090. if ((pbRootHashBlob = LocalAlloc ( LPTR, dwSizeOfHashBlob*sizeof(BYTE))) == NULL)
  3091. {
  3092. lError = GetLastError();
  3093. EapTlsTrace("ReadCARootHashes: LocalAlloc failed for pbRootHashBlob");
  3094. goto LDone;
  3095. }
  3096. for (i=0; i<dwSizeOfHashBlob; i++)
  3097. {
  3098. ZeroMemory(cszCharConv, SIZE_OF_CA_CONV_STR);
  3099. cszCharConv[0]=pszCARootHash[2*i];
  3100. cszCharConv[1]=pszCARootHash[2*i+1];
  3101. pbRootHashBlob[i] = (BYTE)strtol(cszCharConv, NULL, 16);
  3102. }
  3103. }
  3104. else
  3105. {
  3106. EapTlsTrace("ReadCARootHashes: 802.1X Policy Parameters RegQueryValueEx 1 failed with error (%ld)",
  3107. lError);
  3108. goto LDone;
  3109. }
  3110. LDone:
  3111. if (lError != ERROR_SUCCESS)
  3112. {
  3113. if (pbRootHashBlob != NULL)
  3114. {
  3115. LocalFree(pbRootHashBlob);
  3116. }
  3117. }
  3118. else
  3119. {
  3120. *ppbRootHashBlob = pbRootHashBlob;
  3121. *pdwSizeOfRootHashBlob = dwSizeOfHashBlob;
  3122. }
  3123. if (hKey != NULL)
  3124. {
  3125. RegCloseKey(hKey);
  3126. }
  3127. if (pszCARootHash != NULL)
  3128. {
  3129. LocalFree(pszCARootHash);
  3130. }
  3131. return lError;
  3132. }
  3133. #endif
  3134. /////////////////////// ALL PEAP related utils go here ///////////////////////////
  3135. DWORD
  3136. PeapGetFirstEntryUserProp ( PPEAP_USER_PROP pUserProp,
  3137. PEAP_ENTRY_USER_PROPERTIES UNALIGNED ** ppEntryProp
  3138. )
  3139. {
  3140. * ppEntryProp = &( pUserProp->UserProperties );
  3141. return NO_ERROR;
  3142. }
  3143. DWORD
  3144. PeapGetFirstEntryConnProp ( PPEAP_CONN_PROP pConnProp,
  3145. PEAP_ENTRY_CONN_PROPERTIES UNALIGNED ** ppEntryProp
  3146. )
  3147. {
  3148. DWORD dwRetCode = NO_ERROR;
  3149. PEAP_ENTRY_CONN_PROPERTIES UNALIGNED *pFirstEntryConnProp = NULL;
  3150. LPWSTR lpwszServerName;
  3151. RTASSERT ( NULL != pConnProp );
  3152. RTASSERT ( NULL != ppEntryProp );
  3153. lpwszServerName =
  3154. (LPWSTR )(pConnProp->EapTlsConnProp.bData +
  3155. sizeof( EAPTLS_HASH ) * pConnProp->EapTlsConnProp.dwNumHashes);
  3156. //Get the first entry in connprop
  3157. pFirstEntryConnProp = ( PEAP_ENTRY_CONN_PROPERTIES UNALIGNED *)
  3158. ( pConnProp->EapTlsConnProp.bData
  3159. + pConnProp->EapTlsConnProp.dwNumHashes * sizeof(EAPTLS_HASH) +
  3160. (lpwszServerName? wcslen(lpwszServerName) * sizeof(WCHAR):0) +
  3161. sizeof(WCHAR)
  3162. );
  3163. if (NULL == pFirstEntryConnProp )
  3164. {
  3165. dwRetCode = ERROR_NOT_FOUND;
  3166. goto LDone;
  3167. }
  3168. *ppEntryProp = pFirstEntryConnProp;
  3169. LDone:
  3170. return dwRetCode;
  3171. }
  3172. DWORD
  3173. PeapReadConnectionData(
  3174. IN BOOL fWireless,
  3175. IN BYTE* pConnectionDataIn,
  3176. IN DWORD dwSizeOfConnectionDataIn,
  3177. OUT PPEAP_CONN_PROP* ppConnProp
  3178. )
  3179. {
  3180. DWORD dwRetCode = NO_ERROR;
  3181. PPEAP_CONN_PROP pConnProp = NULL;
  3182. PEAP_ENTRY_CONN_PROPERTIES UNALIGNED * pEntryProp = NULL;
  3183. EapTlsTrace("PeapReadConnectionData");
  3184. RTASSERT(NULL != ppConnProp);
  3185. if ( dwSizeOfConnectionDataIn < sizeof(PEAP_CONN_PROP) )
  3186. {
  3187. pConnProp = LocalAlloc(LPTR, sizeof(PEAP_CONN_PROP) + sizeof(PEAP_ENTRY_CONN_PROPERTIES)+ sizeof(WCHAR));
  3188. if (NULL == pConnProp)
  3189. {
  3190. dwRetCode = GetLastError();
  3191. EapTlsTrace("LocalAlloc failed and returned %d", dwRetCode);
  3192. goto LDone;
  3193. }
  3194. //This is a new structure
  3195. pConnProp->dwVersion = 1;
  3196. pConnProp->dwSize = sizeof(PEAP_CONN_PROP) + sizeof(PEAP_ENTRY_CONN_PROPERTIES);
  3197. pConnProp->EapTlsConnProp.dwVersion = 1;
  3198. pConnProp->EapTlsConnProp.dwSize = sizeof(EAPTLS_CONN_PROPERTIES_V1);
  3199. pConnProp->EapTlsConnProp.fFlags |= EAPTLS_CONN_FLAG_REGISTRY;
  3200. pConnProp->EapTlsConnProp.fFlags |= EAPTLS_CONN_FLAG_SIMPLE_CERT_SEL;
  3201. pConnProp->dwNumPeapTypes = 1;
  3202. //pEntryProp = (PPEAP_ENTRY_CONN_PROPERTIES)(((PBYTE)(pConnProp)) + sizeof(PEAP_CONN_PROP) + sizeof(WCHAR));
  3203. pEntryProp = ( PEAP_ENTRY_CONN_PROPERTIES UNALIGNED *)
  3204. ( pConnProp->EapTlsConnProp.bData
  3205. + pConnProp->EapTlsConnProp.dwNumHashes * sizeof(EAPTLS_HASH) +
  3206. sizeof(WCHAR)
  3207. );
  3208. //
  3209. // Also setup the first peap entry conn prop and set it to
  3210. // eapmschapv2
  3211. //
  3212. if ( fWireless )
  3213. {
  3214. pConnProp->EapTlsConnProp.fFlags |= EAPTLS_CONN_FLAG_NO_VALIDATE_NAME;
  3215. }
  3216. pEntryProp->dwVersion = 1;
  3217. pEntryProp->dwSize = sizeof(PEAP_ENTRY_CONN_PROPERTIES);
  3218. pEntryProp->dwEapTypeId = PPP_EAP_MSCHAPv2;
  3219. }
  3220. else
  3221. {
  3222. RTASSERT(NULL != pConnectionDataIn);
  3223. //
  3224. //Check to see if this is a version 0 structure
  3225. //If it is a version 0 structure then we migrate it to version1
  3226. //
  3227. pConnProp = LocalAlloc(LPTR, dwSizeOfConnectionDataIn);
  3228. if (NULL == pConnProp)
  3229. {
  3230. dwRetCode = GetLastError();
  3231. EapTlsTrace("LocalAlloc failed and returned %d", dwRetCode);
  3232. goto LDone;
  3233. }
  3234. // If the user has mucked with the phonebook, we mustn't be affected.
  3235. // The size must be correct.
  3236. CopyMemory(pConnProp, pConnectionDataIn, dwSizeOfConnectionDataIn);
  3237. pConnProp->dwSize = dwSizeOfConnectionDataIn;
  3238. pConnProp->EapTlsConnProp.fFlags |= EAPTLS_CONN_FLAG_REGISTRY;
  3239. }
  3240. *ppConnProp = pConnProp;
  3241. pConnProp = NULL;
  3242. LDone:
  3243. LocalFree(pConnProp);
  3244. return dwRetCode;
  3245. }
  3246. DWORD
  3247. PeapReDoUserData (
  3248. IN DWORD dwNewTypeId,
  3249. OUT PPEAP_USER_PROP* ppNewUserProp
  3250. )
  3251. {
  3252. DWORD dwRetCode = NO_ERROR;
  3253. PPEAP_USER_PROP pUserProp = NULL;
  3254. EapTlsTrace("PeapReDoUserData");
  3255. pUserProp = LocalAlloc(LPTR, sizeof(PEAP_USER_PROP));
  3256. if (NULL == pUserProp)
  3257. {
  3258. dwRetCode = GetLastError();
  3259. EapTlsTrace("LocalAlloc failed and returned %d", dwRetCode);
  3260. goto LDone;
  3261. }
  3262. pUserProp->dwVersion = 1;
  3263. pUserProp->dwSize = sizeof(PEAP_USER_PROP);
  3264. //
  3265. // Setup the default user prop...
  3266. //
  3267. pUserProp->UserProperties.dwVersion = 1;
  3268. pUserProp->UserProperties.dwSize = sizeof(PEAP_ENTRY_USER_PROPERTIES);
  3269. pUserProp->UserProperties.dwEapTypeId = dwNewTypeId;
  3270. *ppNewUserProp = pUserProp;
  3271. LDone:
  3272. return dwRetCode;
  3273. }
  3274. DWORD
  3275. PeapReadUserData(
  3276. IN BYTE* pUserDataIn,
  3277. IN DWORD dwSizeOfUserDataIn,
  3278. OUT PPEAP_USER_PROP* ppUserProp
  3279. )
  3280. {
  3281. DWORD dwErr = NO_ERROR;
  3282. PPEAP_USER_PROP pUserProp;
  3283. EapTlsTrace("PeapReadUserData");
  3284. if (dwSizeOfUserDataIn < sizeof(PEAP_USER_PROP))
  3285. {
  3286. pUserProp = LocalAlloc(LPTR, sizeof(PEAP_USER_PROP));
  3287. if (NULL == pUserProp)
  3288. {
  3289. dwErr = GetLastError();
  3290. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  3291. goto LDone;
  3292. }
  3293. pUserProp->dwVersion = 1;
  3294. pUserProp->dwSize = sizeof(PEAP_USER_PROP);
  3295. //
  3296. // Setup the default user prop...
  3297. //
  3298. pUserProp->UserProperties.dwVersion = 1;
  3299. pUserProp->UserProperties.dwSize = sizeof(PEAP_ENTRY_USER_PROPERTIES);
  3300. pUserProp->UserProperties.dwEapTypeId = PPP_EAP_MSCHAPv2;
  3301. }
  3302. else
  3303. {
  3304. RTASSERT(NULL != pUserDataIn);
  3305. pUserProp = LocalAlloc(LPTR, dwSizeOfUserDataIn);
  3306. if (NULL == pUserProp)
  3307. {
  3308. dwErr = GetLastError();
  3309. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  3310. goto LDone;
  3311. }
  3312. CopyMemory(pUserProp, pUserDataIn, dwSizeOfUserDataIn);
  3313. pUserProp->dwVersion = 1;
  3314. pUserProp->dwSize = dwSizeOfUserDataIn;
  3315. }
  3316. *ppUserProp = pUserProp;
  3317. pUserProp = NULL;
  3318. LDone:
  3319. LocalFree(pUserProp);
  3320. return dwErr;
  3321. }
  3322. //
  3323. // Add node at the head
  3324. //
  3325. DWORD
  3326. PeapEapInfoAddListNode (PPEAP_EAP_INFO * ppEapInfo)
  3327. {
  3328. PPEAP_EAP_INFO pEapInfo = NULL;
  3329. DWORD dwRetCode = NO_ERROR;
  3330. pEapInfo = (PPEAP_EAP_INFO)LocalAlloc(LPTR, sizeof(PEAP_EAP_INFO));
  3331. if ( NULL == pEapInfo )
  3332. {
  3333. dwRetCode = ERROR_OUTOFMEMORY;
  3334. goto LDone;
  3335. }
  3336. if ( NULL == *ppEapInfo )
  3337. {
  3338. *ppEapInfo = pEapInfo;
  3339. }
  3340. else
  3341. {
  3342. pEapInfo->pNext = *ppEapInfo;
  3343. *ppEapInfo = pEapInfo;
  3344. }
  3345. LDone:
  3346. return dwRetCode;
  3347. }
  3348. DWORD
  3349. PeapEapInfoCopyListNode ( DWORD dwTypeId,
  3350. PPEAP_EAP_INFO pEapInfoList,
  3351. PPEAP_EAP_INFO * ppEapInfo )
  3352. {
  3353. DWORD dwRetCode = ERROR_NOT_FOUND;
  3354. PPEAP_EAP_INFO pEapInfoListInternal = pEapInfoList;
  3355. while ( pEapInfoListInternal )
  3356. {
  3357. if ( pEapInfoListInternal->dwTypeId == dwTypeId )
  3358. {
  3359. *ppEapInfo = LocalAlloc( LPTR, sizeof(PEAP_EAP_INFO) );
  3360. if ( NULL == *ppEapInfo )
  3361. {
  3362. dwRetCode = ERROR_OUTOFMEMORY;
  3363. goto LDone;
  3364. }
  3365. CopyMemory ( *ppEapInfo, pEapInfoListInternal, sizeof(PEAP_EAP_INFO) );
  3366. dwRetCode = NO_ERROR;
  3367. goto LDone;
  3368. }
  3369. pEapInfoListInternal = pEapInfoListInternal->pNext;
  3370. }
  3371. LDone:
  3372. return dwRetCode;
  3373. }
  3374. DWORD
  3375. PeapEapInfoFindListNode ( DWORD dwTypeId,
  3376. PPEAP_EAP_INFO pEapInfoList,
  3377. PPEAP_EAP_INFO * ppEapInfo )
  3378. {
  3379. DWORD dwRetCode = ERROR_NOT_FOUND;
  3380. PPEAP_EAP_INFO pEapInfoListInternal = pEapInfoList;
  3381. while ( pEapInfoListInternal )
  3382. {
  3383. if ( pEapInfoListInternal->dwTypeId == dwTypeId )
  3384. {
  3385. *ppEapInfo = pEapInfoListInternal;
  3386. dwRetCode = NO_ERROR;
  3387. goto LDone;
  3388. }
  3389. pEapInfoListInternal = pEapInfoListInternal->pNext;
  3390. }
  3391. LDone:
  3392. return dwRetCode;
  3393. }
  3394. VOID
  3395. PeapEapInfoFreeNodeData ( PPEAP_EAP_INFO pEapInfo )
  3396. {
  3397. LocalFree ( pEapInfo->lpwszFriendlyName );
  3398. LocalFree ( pEapInfo->lpwszConfigUIPath );
  3399. LocalFree ( pEapInfo->lpwszIdentityUIPath );
  3400. LocalFree ( pEapInfo->lpwszConfigClsId );
  3401. LocalFree ( pEapInfo->pbNewClientConfig );
  3402. LocalFree ( pEapInfo->lpwszInteractiveUIPath );
  3403. LocalFree ( pEapInfo->lpwszPath);
  3404. if ( pEapInfo->hEAPModule )
  3405. {
  3406. FreeLibrary(pEapInfo->hEAPModule);
  3407. }
  3408. }
  3409. VOID
  3410. PeapEapInfoRemoveHeadNode(PPEAP_EAP_INFO * ppEapInfo)
  3411. {
  3412. PPEAP_EAP_INFO pEapInfo = *ppEapInfo;
  3413. if ( pEapInfo )
  3414. {
  3415. *ppEapInfo = pEapInfo->pNext;
  3416. PeapEapInfoFreeNodeData(pEapInfo);
  3417. LocalFree ( pEapInfo );
  3418. }
  3419. }
  3420. VOID
  3421. PeapEapInfoFreeList ( PPEAP_EAP_INFO pEapInfo )
  3422. {
  3423. PPEAP_EAP_INFO pNext;
  3424. while ( pEapInfo )
  3425. {
  3426. pNext = pEapInfo->pNext;
  3427. PeapEapInfoFreeNodeData(pEapInfo);
  3428. LocalFree ( pEapInfo );
  3429. pEapInfo = pNext;
  3430. }
  3431. }
  3432. DWORD
  3433. PeapEapInfoReadSZ (HKEY hkeyPeapType,
  3434. LPWSTR pwszValue,
  3435. LPWSTR * ppValueData )
  3436. {
  3437. DWORD dwRetCode = NO_ERROR;
  3438. DWORD dwType = 0;
  3439. DWORD cbValueDataSize =0;
  3440. PBYTE pbValue = NULL;
  3441. dwRetCode = RegQueryValueEx(
  3442. hkeyPeapType,
  3443. pwszValue,
  3444. NULL,
  3445. &dwType,
  3446. pbValue,
  3447. &cbValueDataSize );
  3448. if ( dwRetCode != NO_ERROR )
  3449. {
  3450. goto LDone;
  3451. }
  3452. pbValue = (PBYTE)LocalAlloc ( LPTR, cbValueDataSize );
  3453. if ( NULL == pbValue )
  3454. {
  3455. dwRetCode = ERROR_OUTOFMEMORY;
  3456. goto LDone;
  3457. }
  3458. dwRetCode = RegQueryValueEx(
  3459. hkeyPeapType,
  3460. pwszValue,
  3461. NULL,
  3462. &dwType,
  3463. pbValue,
  3464. &cbValueDataSize );
  3465. if ( dwRetCode != NO_ERROR )
  3466. {
  3467. goto LDone;
  3468. }
  3469. *ppValueData = (LPWSTR)pbValue;
  3470. pbValue = NULL;
  3471. LDone:
  3472. LocalFree ( pbValue );
  3473. return dwRetCode;
  3474. }
  3475. DWORD
  3476. PeapEapInfoExpandSZ (HKEY hkeyPeapType,
  3477. LPWSTR pwszValue,
  3478. LPWSTR * ppValueData )
  3479. {
  3480. DWORD dwRetCode = NO_ERROR;
  3481. DWORD dwType = 0;
  3482. DWORD cbValueDataSize =0;
  3483. PBYTE pbValue = NULL;
  3484. PBYTE pbExpandedValue = NULL;
  3485. dwRetCode = RegQueryValueEx(
  3486. hkeyPeapType,
  3487. pwszValue,
  3488. NULL,
  3489. &dwType,
  3490. pbValue,
  3491. &cbValueDataSize );
  3492. if ( dwRetCode != NO_ERROR )
  3493. {
  3494. goto LDone;
  3495. }
  3496. pbValue = (PBYTE)LocalAlloc ( LPTR, cbValueDataSize );
  3497. if ( NULL == pbValue )
  3498. {
  3499. dwRetCode = ERROR_OUTOFMEMORY;
  3500. goto LDone;
  3501. }
  3502. dwRetCode = RegQueryValueEx(
  3503. hkeyPeapType,
  3504. pwszValue,
  3505. NULL,
  3506. &dwType,
  3507. pbValue,
  3508. &cbValueDataSize );
  3509. if ( dwRetCode != NO_ERROR )
  3510. {
  3511. goto LDone;
  3512. }
  3513. //now Expand the exvironment string
  3514. cbValueDataSize = ExpandEnvironmentStrings( (LPWSTR)pbValue, NULL, 0 );
  3515. pbExpandedValue = (PBYTE)LocalAlloc ( LPTR, cbValueDataSize * sizeof(WCHAR) );
  3516. if ( NULL == pbExpandedValue )
  3517. {
  3518. dwRetCode = ERROR_OUTOFMEMORY;
  3519. goto LDone;
  3520. }
  3521. cbValueDataSize = ExpandEnvironmentStrings( (LPWSTR)pbValue,
  3522. (LPWSTR)pbExpandedValue, sizeof(WCHAR) * cbValueDataSize );
  3523. if ( cbValueDataSize == 0 )
  3524. {
  3525. dwRetCode = GetLastError();
  3526. goto LDone;
  3527. }
  3528. *ppValueData = (LPWSTR)pbExpandedValue;
  3529. pbExpandedValue = NULL;
  3530. LDone:
  3531. LocalFree ( pbValue );
  3532. LocalFree ( pbExpandedValue );
  3533. return dwRetCode;
  3534. }
  3535. BOOL
  3536. IsPeapCrippled(HKEY hKeyLM)
  3537. {
  3538. BOOL fRetCode = FALSE;
  3539. DWORD dwRetCode = NO_ERROR;
  3540. HKEY hCripple = 0;
  3541. DWORD dwValue = 0;
  3542. DWORD dwType = 0;
  3543. DWORD cbValueDataSize = sizeof(DWORD);
  3544. dwRetCode = RegOpenKeyEx( hKeyLM,
  3545. PEAP_KEY_PEAP,
  3546. 0,
  3547. KEY_READ,
  3548. &hCripple
  3549. );
  3550. if (NO_ERROR != dwRetCode)
  3551. {
  3552. goto LDone;
  3553. }
  3554. dwRetCode = RegQueryValueEx(
  3555. hCripple,
  3556. PEAP_CRIPPLE_VALUE,
  3557. NULL,
  3558. &dwType,
  3559. (PBYTE)&dwValue,
  3560. &cbValueDataSize );
  3561. if ( dwRetCode != NO_ERROR )
  3562. {
  3563. goto LDone;
  3564. }
  3565. if ( dwValue != 0 )
  3566. {
  3567. fRetCode = TRUE;
  3568. }
  3569. LDone:
  3570. if ( hCripple )
  3571. RegCloseKey ( hCripple );
  3572. return fRetCode;
  3573. }
  3574. //
  3575. // Get a list of all EAP types configured for PEAP.
  3576. //
  3577. DWORD
  3578. PeapEapInfoGetList ( LPWSTR lpwszMachineName, PPEAP_EAP_INFO * ppEapInfo)
  3579. {
  3580. DWORD dwRetCode = NO_ERROR;
  3581. HKEY hKeyLM =0;
  3582. HKEY hKeyPeap = 0;
  3583. HKEY hkeyPeapType = 0;
  3584. DWORD dwIndex;
  3585. DWORD cb;
  3586. WCHAR wszPeapType[200];
  3587. DWORD dwEapTypeId = 0;
  3588. FARPROC pRasEapGetInfo;
  3589. dwRetCode = RegConnectRegistry ( lpwszMachineName,
  3590. HKEY_LOCAL_MACHINE,
  3591. &hKeyLM
  3592. );
  3593. if ( NO_ERROR != dwRetCode )
  3594. {
  3595. goto LDone;
  3596. }
  3597. dwRetCode = RegOpenKeyEx( hKeyLM,
  3598. PEAP_KEY_EAP,
  3599. 0,
  3600. KEY_READ,
  3601. &hKeyPeap
  3602. );
  3603. if (NO_ERROR != dwRetCode)
  3604. {
  3605. goto LDone;
  3606. }
  3607. for (dwIndex = 0; TRUE; ++dwIndex)
  3608. {
  3609. cb = sizeof(wszPeapType) / sizeof(WCHAR);
  3610. dwRetCode = RegEnumKeyEx( hKeyPeap,
  3611. dwIndex,
  3612. wszPeapType,
  3613. &cb,
  3614. NULL,
  3615. NULL,
  3616. NULL,
  3617. NULL
  3618. );
  3619. if (dwRetCode != NO_ERROR)
  3620. {
  3621. // Includes "out of items", the normal loop termination.
  3622. //
  3623. dwRetCode = NO_ERROR;
  3624. break;
  3625. }
  3626. dwRetCode = RegOpenKeyEx( hKeyPeap,
  3627. wszPeapType,
  3628. 0,
  3629. KEY_READ,
  3630. &hkeyPeapType
  3631. );
  3632. if (dwRetCode != NO_ERROR)
  3633. {
  3634. dwRetCode = NO_ERROR;
  3635. continue;
  3636. }
  3637. dwEapTypeId = _wtol(wszPeapType);
  3638. if ( dwEapTypeId == PPP_EAP_PEAP )
  3639. {
  3640. dwRetCode = NO_ERROR;
  3641. continue;
  3642. }
  3643. {
  3644. //
  3645. // Check to see if we support this in peap
  3646. // By default we do.
  3647. DWORD dwRolesSupported = 0;
  3648. DWORD cbValueSize = sizeof(dwRolesSupported);
  3649. DWORD dwType = 0;
  3650. dwRetCode = RegQueryValueEx(
  3651. hkeyPeapType,
  3652. PEAP_REGVAL_ROLESSUPPORTED,
  3653. NULL,
  3654. &dwType,
  3655. (PBYTE)&dwRolesSupported,
  3656. &cbValueSize );
  3657. if ( dwRetCode == NO_ERROR )
  3658. {
  3659. //
  3660. // We dont allow this method in PEAP.
  3661. //
  3662. if ( RAS_EAP_ROLE_EXCLUDE_IN_PEAP & dwRolesSupported )
  3663. {
  3664. continue;
  3665. }
  3666. }
  3667. }
  3668. //
  3669. // Read the required information and setup the node here
  3670. //
  3671. dwRetCode = PeapEapInfoAddListNode (ppEapInfo);
  3672. if ( NO_ERROR != dwRetCode )
  3673. {
  3674. goto LDone;
  3675. }
  3676. //
  3677. // Setup the list node - if any of these entries are not
  3678. // found skip the entry
  3679. //
  3680. (*ppEapInfo)->dwTypeId = dwEapTypeId;
  3681. dwRetCode = PeapEapInfoReadSZ ( hkeyPeapType,
  3682. PEAP_REGVAL_FRIENDLYNAME,
  3683. &((*ppEapInfo)->lpwszFriendlyName )
  3684. );
  3685. if ( NO_ERROR != dwRetCode )
  3686. {
  3687. if ( ERROR_FILE_NOT_FOUND == dwRetCode )
  3688. {
  3689. PeapEapInfoRemoveHeadNode(ppEapInfo);
  3690. dwRetCode = NO_ERROR;
  3691. continue;
  3692. }
  3693. goto LDone;
  3694. }
  3695. dwRetCode = PeapEapInfoExpandSZ ( hkeyPeapType,
  3696. PEAP_REGVAL_CONFIGDLL,
  3697. &((*ppEapInfo)->lpwszConfigUIPath )
  3698. );
  3699. if ( NO_ERROR != dwRetCode )
  3700. {
  3701. if ( ERROR_FILE_NOT_FOUND == dwRetCode )
  3702. {
  3703. // it is fine to have no config stuff any more.
  3704. // We show the default identity
  3705. dwRetCode = NO_ERROR;
  3706. }
  3707. else
  3708. {
  3709. goto LDone;
  3710. }
  3711. }
  3712. dwRetCode = PeapEapInfoExpandSZ ( hkeyPeapType,
  3713. PEAP_REGVAL_IDENTITYDLL,
  3714. &((*ppEapInfo)->lpwszIdentityUIPath )
  3715. );
  3716. if ( NO_ERROR != dwRetCode )
  3717. {
  3718. if ( ERROR_FILE_NOT_FOUND == dwRetCode )
  3719. {
  3720. //
  3721. // It is fine if we dont have any identity UI. Peap
  3722. // will provide a default identity UI
  3723. //
  3724. dwRetCode = NO_ERROR;
  3725. }
  3726. else
  3727. {
  3728. goto LDone;
  3729. }
  3730. }
  3731. dwRetCode = PeapEapInfoExpandSZ ( hkeyPeapType,
  3732. PEAP_REGVAL_INTERACTIVEUIDLL,
  3733. &((*ppEapInfo)->lpwszInteractiveUIPath )
  3734. );
  3735. if ( NO_ERROR != dwRetCode )
  3736. {
  3737. if ( ERROR_FILE_NOT_FOUND == dwRetCode )
  3738. {
  3739. //It is fine if we dont have interactive UI
  3740. //
  3741. dwRetCode = NO_ERROR;
  3742. }
  3743. else
  3744. {
  3745. goto LDone;
  3746. }
  3747. }
  3748. dwRetCode = PeapEapInfoReadSZ ( hkeyPeapType,
  3749. PEAP_REGVAL_CONFIGCLSID,
  3750. &((*ppEapInfo)->lpwszConfigClsId )
  3751. );
  3752. if ( NO_ERROR != dwRetCode )
  3753. {
  3754. if ( ERROR_FILE_NOT_FOUND == dwRetCode )
  3755. {
  3756. //
  3757. // Missing config clsid is also fine
  3758. dwRetCode = NO_ERROR;
  3759. }
  3760. else
  3761. {
  3762. goto LDone;
  3763. }
  3764. }
  3765. dwRetCode = PeapEapInfoExpandSZ ( hkeyPeapType,
  3766. PEAP_REGVAL_PATH,
  3767. &((*ppEapInfo)->lpwszPath )
  3768. );
  3769. if ( NO_ERROR != dwRetCode )
  3770. {
  3771. //
  3772. // This is not acceptable. So this is a problem.
  3773. //
  3774. if ( ERROR_FILE_NOT_FOUND == dwRetCode )
  3775. {
  3776. PeapEapInfoRemoveHeadNode(ppEapInfo);
  3777. dwRetCode = NO_ERROR;
  3778. continue;
  3779. }
  3780. goto LDone;
  3781. }
  3782. //
  3783. // Now get the EAP INFO from the DLL.
  3784. //
  3785. (*ppEapInfo)->hEAPModule = LoadLibrary( ( (*ppEapInfo)->lpwszPath ) );
  3786. if ( NULL == (*ppEapInfo)->hEAPModule )
  3787. {
  3788. dwRetCode = GetLastError();
  3789. goto LDone;
  3790. }
  3791. pRasEapGetInfo = GetProcAddress( (*ppEapInfo)->hEAPModule ,
  3792. "RasEapGetInfo"
  3793. );
  3794. if ( pRasEapGetInfo == (FARPROC)NULL )
  3795. {
  3796. dwRetCode = GetLastError();
  3797. goto LDone;
  3798. }
  3799. (*ppEapInfo)->RasEapGetCredentials = (DWORD (*) (
  3800. DWORD,VOID *, VOID **))
  3801. GetProcAddress((*ppEapInfo)->hEAPModule,
  3802. "RasEapGetCredentials");
  3803. (*ppEapInfo)->PppEapInfo.dwSizeInBytes = sizeof( PPP_EAP_INFO );
  3804. dwRetCode = (DWORD) (*pRasEapGetInfo)( dwEapTypeId,
  3805. &((*ppEapInfo)->PppEapInfo) );
  3806. if ( dwRetCode != NO_ERROR )
  3807. {
  3808. goto LDone;
  3809. }
  3810. //
  3811. // Call initialize function here
  3812. //
  3813. if ( (*ppEapInfo)->PppEapInfo.RasEapInitialize )
  3814. {
  3815. (*ppEapInfo)->PppEapInfo.RasEapInitialize(TRUE);
  3816. }
  3817. RegCloseKey(hkeyPeapType);
  3818. hkeyPeapType = 0;
  3819. }
  3820. LDone:
  3821. if ( hkeyPeapType )
  3822. RegCloseKey(hkeyPeapType);
  3823. if ( hKeyPeap )
  3824. RegCloseKey(hKeyPeap);
  3825. if ( hKeyLM )
  3826. RegCloseKey(hKeyLM);
  3827. if ( NO_ERROR != dwRetCode )
  3828. {
  3829. PeapEapInfoFreeList( *ppEapInfo );
  3830. }
  3831. return dwRetCode;
  3832. }
  3833. DWORD
  3834. PeapEapInfoSetConnData ( PPEAP_EAP_INFO pEapInfo, PPEAP_CONN_PROP pPeapConnProp )
  3835. {
  3836. DWORD dwRetCode = NO_ERROR;
  3837. PEAP_ENTRY_CONN_PROPERTIES UNALIGNED *pEntryProp = NULL;
  3838. PPEAP_EAP_INFO pEapInfoLocal;
  3839. DWORD dwCount;
  3840. RTASSERT(NULL != pPeapConnProp);
  3841. RTASSERT(NULL != pEapInfo);
  3842. if ( !pPeapConnProp->dwNumPeapTypes )
  3843. {
  3844. goto LDone;
  3845. }
  3846. //
  3847. // Right now there is only one EAP Type in the list
  3848. // So it should not be a problem with this stuff now
  3849. pEntryProp = ( PEAP_ENTRY_CONN_PROPERTIES*)
  3850. ( pPeapConnProp->EapTlsConnProp.bData
  3851. + pPeapConnProp->EapTlsConnProp.dwNumHashes * sizeof(EAPTLS_HASH) +
  3852. sizeof(WCHAR)
  3853. );
  3854. pEapInfoLocal = pEapInfo;
  3855. while( pEapInfoLocal )
  3856. {
  3857. if ( pEapInfoLocal->dwTypeId == pEntryProp->dwEapTypeId )
  3858. {
  3859. if ( pEntryProp->dwSize > sizeof(PEAP_ENTRY_CONN_PROPERTIES))
  3860. {
  3861. pEapInfoLocal->pbClientConfigOrig = pEntryProp->bData;
  3862. pEapInfoLocal->dwClientConfigOrigSize = pEntryProp->dwSize -
  3863. sizeof(PEAP_ENTRY_CONN_PROPERTIES) + 1;
  3864. }
  3865. else
  3866. {
  3867. pEapInfoLocal->pbClientConfigOrig = NULL;
  3868. pEapInfoLocal->dwClientConfigOrigSize = 0;
  3869. }
  3870. break;
  3871. }
  3872. pEapInfoLocal = pEapInfoLocal->pNext;
  3873. }
  3874. #if 0
  3875. for ( dwCount = 0; dwCount < pPeapConnProp->dwNumPeapTypes; dwCount ++ )
  3876. {
  3877. pEntryProp = (PEAP_ENTRY_CONN_PROPERTIES UNALIGNED * )(((BYTE UNALIGNED *)&(pPeapConnProp->EapTlsConnProp)) +
  3878. pPeapConnProp->EapTlsConnProp.dwSize +
  3879. sizeof(PEAP_ENTRY_CONN_PROPERTIES) * dwCount);
  3880. pEapInfoLocal = pEapInfo;
  3881. while( pEapInfoLocal )
  3882. {
  3883. if ( pEapInfoLocal->dwTypeId == pEntryProp->dwEapTypeId )
  3884. {
  3885. if ( pEntryProp->dwSize > sizeof(PEAP_ENTRY_CONN_PROPERTIES))
  3886. {
  3887. pEapInfoLocal->pbClientConfigOrig = pEntryProp->bData;
  3888. pEapInfoLocal->dwClientConfigOrigSize = pEntryProp->dwSize -
  3889. sizeof(PEAP_ENTRY_CONN_PROPERTIES) + 1;
  3890. }
  3891. else
  3892. {
  3893. pEapInfoLocal->pbClientConfigOrig = NULL;
  3894. pEapInfoLocal->dwClientConfigOrigSize = 0;
  3895. }
  3896. break;
  3897. }
  3898. pEapInfoLocal = pEapInfoLocal->pNext;
  3899. }
  3900. }
  3901. #endif
  3902. LDone:
  3903. return dwRetCode;
  3904. }
  3905. DWORD PeapEapInfoInvokeIdentityUI ( HWND hWndParent,
  3906. PPEAP_EAP_INFO pEapInfo,
  3907. const WCHAR * pwszPhoneBook,
  3908. const WCHAR * pwszEntry,
  3909. PBYTE pbUserDataIn, // Got when using Winlogon
  3910. DWORD cbUserDataIn, // Got when using Winlogon
  3911. WCHAR** ppwszIdentityOut,
  3912. DWORD fFlags)
  3913. {
  3914. DWORD dwRetCode = NO_ERROR;
  3915. PBYTE pbUserDataNew = NULL;
  3916. DWORD dwSizeOfUserDataNew = 0;
  3917. RASEAPGETIDENTITY pIdenFunc = NULL;
  3918. RASEAPFREE pFreeFunc = NULL;
  3919. RTASSERT ( NULL != pEapInfo );
  3920. RTASSERT ( NULL != pEapInfo->lpwszIdentityUIPath );
  3921. pIdenFunc = (RASEAPGETIDENTITY)
  3922. GetProcAddress(pEapInfo->hEAPModule, "RasEapGetIdentity");
  3923. if ( pIdenFunc == NULL)
  3924. {
  3925. dwRetCode = GetLastError();
  3926. goto LDone;
  3927. }
  3928. pFreeFunc = (RASEAPFREE) GetProcAddress(pEapInfo->hEAPModule, "RasEapFreeMemory");
  3929. if ( pFreeFunc == NULL )
  3930. {
  3931. dwRetCode = GetLastError();
  3932. goto LDone;
  3933. }
  3934. dwRetCode = pIdenFunc ( pEapInfo->dwTypeId,
  3935. hWndParent,
  3936. fFlags,
  3937. pwszPhoneBook,
  3938. pwszEntry,
  3939. pEapInfo->pbClientConfigOrig,
  3940. pEapInfo->dwClientConfigOrigSize,
  3941. ( fFlags & RAS_EAP_FLAG_LOGON ?
  3942. pbUserDataIn:
  3943. pEapInfo->pbUserConfigOrig
  3944. ),
  3945. ( fFlags & RAS_EAP_FLAG_LOGON ?
  3946. cbUserDataIn:
  3947. pEapInfo->dwUserConfigOrigSize
  3948. ),
  3949. &pbUserDataNew,
  3950. &dwSizeOfUserDataNew,
  3951. ppwszIdentityOut
  3952. );
  3953. if ( NO_ERROR != dwRetCode )
  3954. {
  3955. goto LDone;
  3956. }
  3957. if ( pbUserDataNew &&
  3958. dwSizeOfUserDataNew
  3959. )
  3960. {
  3961. //
  3962. // we have new user data
  3963. //
  3964. pEapInfo->pbUserConfigNew = (PBYTE)LocalAlloc (LPTR, dwSizeOfUserDataNew );
  3965. if ( NULL == pEapInfo->pbUserConfigNew )
  3966. {
  3967. dwRetCode = ERROR_OUTOFMEMORY;
  3968. goto LDone;
  3969. }
  3970. CopyMemory ( pEapInfo->pbUserConfigNew,
  3971. pbUserDataNew,
  3972. dwSizeOfUserDataNew
  3973. );
  3974. pEapInfo->dwNewUserConfigSize = dwSizeOfUserDataNew;
  3975. }
  3976. LDone:
  3977. pFreeFunc( pbUserDataNew );
  3978. return dwRetCode;
  3979. }
  3980. DWORD PeapEapInfoInvokeClientConfigUI ( HWND hWndParent,
  3981. PPEAP_EAP_INFO pEapInfo,
  3982. DWORD fFlags)
  3983. {
  3984. DWORD dwRetCode = NO_ERROR;
  3985. RASEAPINVOKECONFIGUI pInvokeConfigUI;
  3986. RASEAPFREE pFreeConfigUIData;
  3987. PBYTE pConnDataOut = NULL;
  3988. DWORD dwConnDataOut = 0;
  3989. RTASSERT ( NULL != pEapInfo );
  3990. RTASSERT ( NULL != pEapInfo->lpwszConfigUIPath );
  3991. if ( !(pInvokeConfigUI =
  3992. (RASEAPINVOKECONFIGUI )GetProcAddress(
  3993. pEapInfo->hEAPModule, "RasEapInvokeConfigUI" ))
  3994. || !(pFreeConfigUIData =
  3995. (RASEAPFREE) GetProcAddress(
  3996. pEapInfo->hEAPModule, "RasEapFreeMemory" ))
  3997. )
  3998. {
  3999. dwRetCode = GetLastError();
  4000. goto LDone;
  4001. }
  4002. dwRetCode = pInvokeConfigUI ( pEapInfo->dwTypeId,
  4003. hWndParent,
  4004. fFlags,
  4005. (pEapInfo->pbNewClientConfig?
  4006. pEapInfo->pbNewClientConfig:
  4007. pEapInfo->pbClientConfigOrig
  4008. ),
  4009. (pEapInfo->pbNewClientConfig?
  4010. pEapInfo->dwNewClientConfigSize:
  4011. pEapInfo->dwClientConfigOrigSize
  4012. ),
  4013. &pConnDataOut,
  4014. &dwConnDataOut
  4015. );
  4016. if ( NO_ERROR != dwRetCode )
  4017. {
  4018. goto LDone;
  4019. }
  4020. if ( pConnDataOut && dwConnDataOut )
  4021. {
  4022. if ( pEapInfo->pbNewClientConfig )
  4023. {
  4024. LocalFree(pEapInfo->pbNewClientConfig );
  4025. pEapInfo->pbNewClientConfig = NULL;
  4026. pEapInfo->dwNewClientConfigSize = 0;
  4027. }
  4028. pEapInfo->pbNewClientConfig = (PBYTE)LocalAlloc ( LPTR, dwConnDataOut );
  4029. if ( NULL == pEapInfo->pbNewClientConfig )
  4030. {
  4031. dwRetCode = ERROR_OUTOFMEMORY;
  4032. goto LDone;
  4033. }
  4034. CopyMemory( pEapInfo->pbNewClientConfig,
  4035. pConnDataOut,
  4036. dwConnDataOut
  4037. );
  4038. pEapInfo->dwNewClientConfigSize = dwConnDataOut;
  4039. }
  4040. LDone:
  4041. if ( pConnDataOut )
  4042. pFreeConfigUIData(pConnDataOut);
  4043. return dwRetCode;
  4044. }
  4045. DWORD
  4046. OpenPeapRegistryKey(
  4047. IN WCHAR* pwszMachineName,
  4048. IN REGSAM samDesired,
  4049. OUT HKEY* phKeyPeap
  4050. )
  4051. {
  4052. HKEY hKeyLocalMachine = NULL;
  4053. BOOL fHKeyLocalMachineOpened = FALSE;
  4054. BOOL fHKeyPeapOpened = FALSE;
  4055. LONG lRet;
  4056. DWORD dwErr = NO_ERROR;
  4057. RTASSERT(NULL != phKeyPeap);
  4058. lRet = RegConnectRegistry(pwszMachineName, HKEY_LOCAL_MACHINE,
  4059. &hKeyLocalMachine);
  4060. if (ERROR_SUCCESS != lRet)
  4061. {
  4062. dwErr = lRet;
  4063. EapTlsTrace("RegConnectRegistry(%ws) failed and returned %d",
  4064. pwszMachineName ? pwszMachineName : L"NULL", dwErr);
  4065. goto LDone;
  4066. }
  4067. fHKeyLocalMachineOpened = TRUE;
  4068. lRet = RegOpenKeyEx(hKeyLocalMachine, PEAP_KEY_25, 0, samDesired,
  4069. phKeyPeap);
  4070. if (ERROR_SUCCESS != lRet)
  4071. {
  4072. dwErr = lRet;
  4073. EapTlsTrace("RegOpenKeyEx(%ws) failed and returned %d",
  4074. PEAP_KEY_25, dwErr);
  4075. goto LDone;
  4076. }
  4077. fHKeyPeapOpened = TRUE;
  4078. LDone:
  4079. if ( fHKeyPeapOpened
  4080. && (ERROR_SUCCESS != dwErr))
  4081. {
  4082. RegCloseKey(*phKeyPeap);
  4083. }
  4084. if (fHKeyLocalMachineOpened)
  4085. {
  4086. RegCloseKey(hKeyLocalMachine);
  4087. }
  4088. return(dwErr);
  4089. }
  4090. DWORD
  4091. PeapServerConfigDataIO(
  4092. IN BOOL fRead,
  4093. IN WCHAR* pwszMachineName,
  4094. IN OUT BYTE** ppData,
  4095. IN DWORD dwNumBytes
  4096. )
  4097. {
  4098. HKEY hKeyPeap;
  4099. PEAP_USER_PROP* pUserProp;
  4100. BOOL fHKeyPeapOpened = FALSE;
  4101. BYTE* pData = NULL;
  4102. DWORD dwSize = 0;
  4103. LONG lRet;
  4104. DWORD dwType;
  4105. DWORD dwErr = NO_ERROR;
  4106. RTASSERT(NULL != ppData);
  4107. dwErr = OpenPeapRegistryKey(pwszMachineName,
  4108. fRead ? KEY_READ : KEY_WRITE, &hKeyPeap);
  4109. if (ERROR_SUCCESS != dwErr)
  4110. {
  4111. goto LDone;
  4112. }
  4113. fHKeyPeapOpened = TRUE;
  4114. if (fRead)
  4115. {
  4116. lRet = RegQueryValueEx(hKeyPeap, PEAP_VAL_SERVER_CONFIG_DATA, NULL,
  4117. &dwType, NULL, &dwSize);
  4118. if ( (ERROR_SUCCESS != lRet)
  4119. || (REG_BINARY != dwType)
  4120. || (sizeof(PEAP_USER_PROP) != dwSize))
  4121. {
  4122. pData = LocalAlloc(LPTR, sizeof(PEAP_USER_PROP));
  4123. if (NULL == pData)
  4124. {
  4125. dwErr = GetLastError();
  4126. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  4127. goto LDone;
  4128. }
  4129. pUserProp = (PEAP_USER_PROP*)pData;
  4130. pUserProp->dwVersion = 0;
  4131. }
  4132. else
  4133. {
  4134. pData = LocalAlloc(LPTR, dwSize);
  4135. if (NULL == pData)
  4136. {
  4137. dwErr = GetLastError();
  4138. EapTlsTrace("LocalAlloc failed and returned %d", dwErr);
  4139. goto LDone;
  4140. }
  4141. lRet = RegQueryValueEx(hKeyPeap, PEAP_VAL_SERVER_CONFIG_DATA,
  4142. NULL, &dwType, pData, &dwSize);
  4143. if (ERROR_SUCCESS != lRet)
  4144. {
  4145. dwErr = lRet;
  4146. EapTlsTrace("RegQueryValueEx(%ws) failed and returned %d",
  4147. EAPTLS_VAL_SERVER_CONFIG_DATA, dwErr);
  4148. goto LDone;
  4149. }
  4150. }
  4151. pUserProp = (PEAP_USER_PROP*)pData;
  4152. pUserProp->dwSize = sizeof(PEAP_USER_PROP);
  4153. *ppData = pData;
  4154. pData = NULL;
  4155. }
  4156. else
  4157. {
  4158. lRet = RegSetValueEx(hKeyPeap, PEAP_VAL_SERVER_CONFIG_DATA, 0,
  4159. REG_BINARY, *ppData, dwNumBytes);
  4160. if (ERROR_SUCCESS != lRet)
  4161. {
  4162. dwErr = lRet;
  4163. EapTlsTrace("RegSetValueEx(%ws) failed and returned %d",
  4164. PEAP_VAL_SERVER_CONFIG_DATA, dwErr);
  4165. goto LDone;
  4166. }
  4167. }
  4168. LDone:
  4169. if (fHKeyPeapOpened)
  4170. {
  4171. RegCloseKey(hKeyPeap);
  4172. }
  4173. LocalFree(pData);
  4174. return(dwErr);
  4175. }
  4176. DWORD
  4177. GetIdentityFromUserName (
  4178. LPWSTR lpszUserName,
  4179. LPWSTR lpszDomain,
  4180. LPWSTR * ppwszIdentity
  4181. )
  4182. {
  4183. DWORD dwRetCode = NO_ERROR;
  4184. DWORD dwNumBytes;
  4185. //domain+ user + '\' + null
  4186. dwNumBytes = (wcslen(lpszUserName) + wcslen(lpszDomain) + 1 + 1) * sizeof(WCHAR);
  4187. *ppwszIdentity = LocalAlloc ( LPTR, dwNumBytes);
  4188. if ( NULL == *ppwszIdentity )
  4189. {
  4190. dwRetCode = ERROR_OUTOFMEMORY;
  4191. goto LDone;
  4192. }
  4193. if ( *lpszDomain )
  4194. {
  4195. wcsncpy ( *ppwszIdentity, lpszDomain, DNLEN );
  4196. wcscat( *ppwszIdentity, L"\\");
  4197. }
  4198. wcscat ( *ppwszIdentity, lpszUserName );
  4199. LDone:
  4200. return dwRetCode;
  4201. }
  4202. //
  4203. // Format identity as domain\user. this is ok because our identity inside has not been
  4204. // tampered with
  4205. //
  4206. BOOL FFormatUserIdentity ( LPWSTR lpszUserNameRaw, LPWSTR * lppszUserNameFormatted )
  4207. {
  4208. BOOL fRetVal = TRUE;
  4209. LPTSTR s1 = NULL;
  4210. LPTSTR s2 = NULL;
  4211. RTASSERT(NULL != lpszUserNameRaw );
  4212. RTASSERT(NULL != lppszUserNameFormatted );
  4213. //Need to add 2 more chars. One for NULL and other for $ sign
  4214. *lppszUserNameFormatted = (LPTSTR )LocalAlloc ( LPTR, (wcslen(lpszUserNameRaw ) + 2)* sizeof(WCHAR) );
  4215. if ( NULL == *lppszUserNameFormatted )
  4216. {
  4217. return FALSE;
  4218. }
  4219. //find the first "@" and that is the identity of the machine.
  4220. //the second "." is the domain.
  4221. //check to see if there at least 2 dots. If not the raw string is
  4222. //the output string
  4223. s1 = wcschr ( lpszUserNameRaw, '@' );
  4224. if ( s1 )
  4225. {
  4226. //
  4227. // get the first .
  4228. //
  4229. s2 = wcschr ( s1, '.');
  4230. }
  4231. if ( s1 && s2 )
  4232. {
  4233. memcpy ( *lppszUserNameFormatted, s1+1, (s2-s1-1) * sizeof(WCHAR)) ;
  4234. memcpy ( (*lppszUserNameFormatted) + (s2-s1-1), L"\\", sizeof(WCHAR));
  4235. memcpy ( (*lppszUserNameFormatted)+ (s2-s1), lpszUserNameRaw, (s1-lpszUserNameRaw) * sizeof(WCHAR) );
  4236. }
  4237. else
  4238. {
  4239. wcscpy ( *lppszUserNameFormatted, lpszUserNameRaw );
  4240. }
  4241. return fRetVal;
  4242. }
  4243. VOID
  4244. GetMarshalledCredFromHash(
  4245. PBYTE pbHash,
  4246. DWORD cbHash,
  4247. CHAR *pszMarshalledCred,
  4248. DWORD cchCredSize)
  4249. {
  4250. CERT_CREDENTIAL_INFO CertCredInfo;
  4251. CHAR *pszMarshalledCredLocal = NULL;
  4252. CertCredInfo.cbSize = sizeof(CertCredInfo);
  4253. memcpy (CertCredInfo.rgbHashOfCert,
  4254. pbHash,
  4255. cbHash
  4256. );
  4257. if (CredMarshalCredentialA(CertCredential,
  4258. (PVOID) &CertCredInfo,
  4259. &pszMarshalledCredLocal
  4260. ))
  4261. {
  4262. //
  4263. // Got Marshalled Credential from the cert
  4264. // Set it in the username field
  4265. //
  4266. ASSERT( NULL != pszMarshalledCredLocal );
  4267. (VOID) StringCchCopyA (pszMarshalledCred,
  4268. cchCredSize,
  4269. pszMarshalledCredLocal );
  4270. CredFree ( pszMarshalledCredLocal );
  4271. }
  4272. else
  4273. {
  4274. EapTlsTrace("CredMarshalCredential Failed with Error:0x%x",
  4275. GetLastError());
  4276. }
  4277. }
  4278. DWORD
  4279. GetCredentialsFromUserProperties(
  4280. EAPTLSCB *pEapTlsCb,
  4281. VOID **ppCredentials)
  4282. {
  4283. DWORD dwRetCode = ERROR_SUCCESS;
  4284. RASMAN_CREDENTIALS *pCreds = NULL;
  4285. //
  4286. // Note: Its important that this allocation is made from
  4287. // the process heap. Ppp engine needs to change otherwise.
  4288. //
  4289. pCreds = LocalAlloc(LPTR, sizeof(RASMAN_CREDENTIALS));
  4290. if(NULL == pCreds)
  4291. {
  4292. dwRetCode = GetLastError();
  4293. goto done;
  4294. }
  4295. if( (NULL != pEapTlsCb->pSavedPin)
  4296. && (NULL != pEapTlsCb->pSavedPin->pwszPin))
  4297. {
  4298. UNICODE_STRING UnicodeString;
  4299. //
  4300. // Decode the saved pin
  4301. //
  4302. UnicodeString.Length = pEapTlsCb->pSavedPin->usLength;
  4303. UnicodeString.MaximumLength = pEapTlsCb->pSavedPin->usMaximumLength;
  4304. UnicodeString.Buffer = pEapTlsCb->pSavedPin->pwszPin;
  4305. RtlRunDecodeUnicodeString(pEapTlsCb->pSavedPin->ucSeed,
  4306. &UnicodeString);
  4307. (VOID)StringCchCopyW(pCreds->wszPassword,
  4308. PWLEN,
  4309. pEapTlsCb->pSavedPin->pwszPin);
  4310. ZeroMemory(pEapTlsCb->pSavedPin->pwszPin,
  4311. wcslen(pEapTlsCb->pSavedPin->pwszPin) * sizeof(WCHAR));
  4312. LocalFree(pEapTlsCb->pSavedPin->pwszPin);
  4313. LocalFree(pEapTlsCb->pSavedPin);
  4314. pEapTlsCb->pSavedPin = NULL;
  4315. }
  4316. if(NULL != pEapTlsCb->pUserProp)
  4317. {
  4318. GetMarshalledCredFromHash(
  4319. pEapTlsCb->pUserProp->Hash.pbHash,
  4320. pEapTlsCb->pUserProp->Hash.cbHash,
  4321. pCreds->szUserName,
  4322. UNLEN);
  4323. }
  4324. pCreds->dwFlags = RASCRED_EAP;
  4325. done:
  4326. *ppCredentials = (VOID *) pCreds;
  4327. return dwRetCode;
  4328. }