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.

3714 lines
112 KiB

  1. /*++
  2. Copyright (c) 1997 - 1999 Microsoft Corporation
  3. Module Name:
  4. userkey.cxx
  5. Abstract:
  6. EFS (Encrypting File System) Server
  7. Author:
  8. Robert Reichel (RobertRe) July 4, 1997
  9. Robert Gu (RobertG) January 23, 1998
  10. Environment:
  11. Revision History:
  12. --*/
  13. #include <lsapch.hxx>
  14. extern "C" {
  15. #include <nt.h>
  16. #include <ntdef.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #include <windows.h>
  20. #include <wincrypt.h>
  21. #include <cryptui.h>
  22. #include <stdio.h>
  23. #include <malloc.h>
  24. #include <certca.h>
  25. #include "lsasrvp.h"
  26. #include "efssrv.hxx"
  27. #include "userkey.h"
  28. }
  29. #define PROVIDER TEXT("Provider")
  30. #define CONTAINER TEXT("Container")
  31. #define PROVIDER_TYPE TEXT("Type")
  32. #define CERT_HASH TEXT("CertificateHash")
  33. #define CERT_FLAG TEXT("Flag")
  34. #define KEYPATH TEXT("%ws\\Software\\Microsoft\\Windows NT\\CurrentVersion\\EFS\\CurrentKeys")
  35. #define KEYPATHROOT HKEY_USERS
  36. #define YEARCOUNT (LONGLONG) 10000000*3600*24*365 // One Year's tick count
  37. #ifndef wszCERTTYPE_EFS
  38. #define wszCERTTYPE_EFS L"EFS"
  39. #endif
  40. #ifndef wszCERTTYPE_EFS_RECOVERY
  41. #define wszCERTTYPE_EFS_RECOVERY L"EFSRecovery"
  42. #endif
  43. LONG UserCertIsValidating = 0;
  44. //
  45. // Forward references
  46. //
  47. BOOL
  48. EfspCreateSelfSignedCert(
  49. OUT HCRYPTKEY * hKey,
  50. OUT HCRYPTPROV * hProv,
  51. OUT LPWSTR * lpContainerName,
  52. OUT LPWSTR * lpProviderName,
  53. IN PEFS_USER_INFO pEfsUserInfo,
  54. OUT PBYTE * pbHash,
  55. OUT PDWORD cbHash,
  56. OUT LPWSTR * lpDisplayInfo,
  57. OUT PCCERT_CONTEXT *pCertContext
  58. );
  59. DWORD
  60. GenerateUserKey (
  61. IN PEFS_USER_INFO pEfsUserInfo,
  62. OUT HCRYPTKEY * hKey OPTIONAL,
  63. OUT HCRYPTPROV * hProv OPTIONAL,
  64. OUT LPWSTR * ContainerName,
  65. OUT LPWSTR * ProviderName,
  66. OUT PDWORD ProviderType,
  67. OUT LPWSTR * DisplayInfo,
  68. OUT PBYTE * pbHash,
  69. OUT PDWORD cbHash
  70. );
  71. PWCHAR
  72. ConstructKeyPath(
  73. PWCHAR SidString
  74. )
  75. /*++
  76. Routine Description:
  77. This routine constructs the path to the current user key, in the form
  78. <user-sid>\Software\Microsoft\Windows NT\CurrentVersion\EFS\CurrentKeys
  79. Arguments:
  80. None.
  81. Return Value:
  82. Returns the path the the current user keyset
  83. --*/
  84. {
  85. PWCHAR KeyPath = NULL;
  86. if (SidString) {
  87. DWORD KeyPathLength = wcslen( KEYPATH );
  88. //
  89. // Subtract 3 for %ws and add 1 for NULL
  90. //
  91. DWORD StringLength = ( KeyPathLength - 3 + wcslen( SidString ) + 1) * sizeof( WCHAR );
  92. KeyPath = (PWCHAR)LsapAllocateLsaHeap( StringLength );
  93. if (KeyPath) {
  94. swprintf( KeyPath, KEYPATH, SidString );
  95. KeyPath[StringLength/sizeof( WCHAR ) - 1] = UNICODE_NULL;
  96. }
  97. }
  98. return( KeyPath );
  99. }
  100. NTSTATUS
  101. EfspGetTokenUser(
  102. IN OUT PEFS_USER_INFO pEfsUserInfo
  103. )
  104. /*++
  105. Routine Description:
  106. This routine returns the TOKEN_USER structure for the
  107. current user, and optionally, the AuthenticationId from his
  108. token.
  109. Arguments:
  110. pEfsUserInfo - User Info.
  111. Return Value:
  112. NtStatus code
  113. --*/
  114. {
  115. NTSTATUS Status;
  116. HANDLE TokenHandle;
  117. ULONG ReturnLength;
  118. TOKEN_STATISTICS TokenStats;
  119. PTOKEN_USER pTokenUser = NULL;
  120. BOOLEAN b = FALSE;
  121. BYTE PefBuffer[1024];
  122. Status = NtOpenThreadToken(
  123. NtCurrentThread(),
  124. TOKEN_QUERY,
  125. TRUE, // OpenAsSelf
  126. &TokenHandle
  127. );
  128. if (NT_SUCCESS( Status )) {
  129. Status = NtQueryInformationToken (
  130. TokenHandle,
  131. TokenUser,
  132. PefBuffer,
  133. sizeof (PefBuffer),
  134. &ReturnLength
  135. );
  136. if ( NT_SUCCESS( Status ) || (Status == STATUS_BUFFER_TOO_SMALL)) {
  137. pEfsUserInfo->pTokenUser = (PTOKEN_USER)LsapAllocateLsaHeap( ReturnLength );
  138. if (pEfsUserInfo->pTokenUser) {
  139. if (NT_SUCCESS( Status )) {
  140. RtlCopyMemory(pEfsUserInfo->pTokenUser, PefBuffer, ReturnLength);
  141. //
  142. // Fix the SID pointer
  143. //
  144. pEfsUserInfo->pTokenUser->User.Sid = (PSID)((PBYTE)(pEfsUserInfo->pTokenUser) + sizeof(SID_AND_ATTRIBUTES));
  145. ASSERT(RtlValidSid(pEfsUserInfo->pTokenUser->User.Sid));
  146. } else {
  147. //
  148. // The stack performance buffer is not bigger enough
  149. //
  150. Status = NtQueryInformationToken (
  151. TokenHandle,
  152. TokenUser,
  153. pEfsUserInfo->pTokenUser,
  154. ReturnLength,
  155. &ReturnLength
  156. );
  157. }
  158. if ( NT_SUCCESS( Status )) {
  159. Status = NtQueryInformationToken (
  160. TokenHandle,
  161. TokenStatistics,
  162. (PVOID)&TokenStats,
  163. sizeof( TOKEN_STATISTICS ),
  164. &ReturnLength
  165. );
  166. if ( NT_SUCCESS( Status )) {
  167. NTSTATUS Status1;
  168. pEfsUserInfo->AuthId = TokenStats.AuthenticationId;
  169. b = TRUE;
  170. //
  171. // If we failed to get the group info, we assume the user is not interactively logged on.
  172. // The fail should not stop us, we could go without cache at the worst.
  173. //
  174. Status1 = NtQueryInformationToken (
  175. TokenHandle,
  176. TokenGroups,
  177. PefBuffer,
  178. sizeof (PefBuffer),
  179. &ReturnLength
  180. );
  181. if (NT_SUCCESS( Status1 ) || (Status1 == STATUS_BUFFER_TOO_SMALL)) {
  182. PTOKEN_GROUPS pGroups = NULL;
  183. PTOKEN_GROUPS pAllocGroups = NULL;
  184. if ( NT_SUCCESS( Status1 ) ) {
  185. pGroups = (PTOKEN_GROUPS) PefBuffer;
  186. } else {
  187. pAllocGroups = (PTOKEN_GROUPS)LsapAllocateLsaHeap( ReturnLength );
  188. Status1 = NtQueryInformationToken (
  189. TokenHandle,
  190. TokenGroups,
  191. pAllocGroups,
  192. ReturnLength,
  193. &ReturnLength
  194. );
  195. if ( NT_SUCCESS( Status1 )) {
  196. pGroups = pAllocGroups;
  197. }
  198. }
  199. if (pGroups) {
  200. //
  201. // Search the interactive SID. Looks like this SID tends to appear at the
  202. // end of the list. We search from back to the first.
  203. //
  204. int SidIndex;
  205. for ( SidIndex = (int)(pGroups->GroupCount - 1); SidIndex >= 0; SidIndex--) {
  206. if (RtlEqualSid(LsapInteractiveSid, pGroups->Groups[SidIndex].Sid)) {
  207. pEfsUserInfo->InterActiveUser = USER_INTERACTIVE;
  208. break;
  209. }
  210. }
  211. if (pEfsUserInfo->InterActiveUser != USER_INTERACTIVE) {
  212. pEfsUserInfo->InterActiveUser = USER_REMOTE;
  213. }
  214. }
  215. if (pAllocGroups) {
  216. LsapFreeLsaHeap( pAllocGroups );
  217. }
  218. }
  219. // LsapInteractiveSid
  220. }
  221. }
  222. if (!b) {
  223. //
  224. // Something failed, clean up what we were going to return
  225. //
  226. LsapFreeLsaHeap( pEfsUserInfo->pTokenUser );
  227. pEfsUserInfo->pTokenUser = NULL;
  228. }
  229. } else {
  230. Status = STATUS_INSUFFICIENT_RESOURCES;
  231. }
  232. }
  233. NtClose( TokenHandle );
  234. }
  235. return( Status );
  236. }
  237. PWCHAR
  238. ConvertSidToWideCharString(
  239. PSID Sid
  240. )
  241. /*++
  242. Routine Description:
  243. This function generates a printable unicode string representation
  244. of a SID.
  245. The resulting string will take one of two forms. If the
  246. IdentifierAuthority value is not greater than 2^32, then
  247. the SID will be in the form:
  248. S-1-281736-12-72-9-110
  249. ^ ^^ ^^ ^ ^^^
  250. | | | | |
  251. +-----+--+-+--+---- Decimal
  252. Otherwise it will take the form:
  253. S-1-0x173495281736-12-72-9-110
  254. ^^^^^^^^^^^^^^ ^^ ^^ ^ ^^^
  255. Hexidecimal | | | |
  256. +--+-+--+---- Decimal
  257. Arguments:
  258. UnicodeString - Returns a unicode string that is equivalent to
  259. the SID. The maximum length field is only set if
  260. AllocateDestinationString is TRUE.
  261. Sid - Supplies the SID that is to be converted to unicode.
  262. AllocateDestinationString - Supplies a flag that controls whether or
  263. not this API allocates the buffer space for the destination
  264. string. If it does, then the buffer must be deallocated using
  265. RtlFreeUnicodeString (note that only storage for
  266. DestinationString->Buffer is allocated by this API).
  267. Return Value:
  268. SUCCESS - The conversion was successful
  269. STATUS_INVALID_SID - The sid provided does not have a valid structure,
  270. or has too many sub-authorities (more than SID_MAX_SUB_AUTHORITIES).
  271. STATUS_NO_MEMORY - There was not sufficient memory to allocate the
  272. target string. This is returned only if AllocateDestinationString
  273. is specified as TRUE.
  274. STATUS_BUFFER_OVERFLOW - This is returned only if
  275. AllocateDestinationString is specified as FALSE.
  276. --*/
  277. {
  278. UNICODE_STRING Result;
  279. if ( STATUS_SUCCESS != RtlConvertSidToUnicodeString( &Result, Sid, TRUE )) {
  280. return NULL;
  281. }
  282. return Result.Buffer;
  283. }
  284. BOOLEAN
  285. EfspIsSystem(
  286. PEFS_USER_INFO pEfsUserInfo,
  287. OUT PBOOLEAN System
  288. )
  289. /*++
  290. Routine Description:
  291. Determines if the current user is running in system context or not.
  292. Arguments:
  293. System - Receives whether or not the current user is system.
  294. Return Value:
  295. TRUE on success, FALSE on failure.
  296. --*/
  297. {
  298. *System = RtlEqualSid(LsapLocalSystemSid, pEfsUserInfo->pTokenUser->User.Sid);
  299. return( TRUE );
  300. }
  301. BOOL
  302. EfspIsDomainUser(
  303. IN LPWSTR lpDomainName,
  304. OUT PBOOLEAN IsDomain
  305. )
  306. /*++
  307. Routine Description:
  308. Determines if the current user is logged on to a domain account
  309. or a local machine account.
  310. Arguments:
  311. lpDomainName - Supplies the domain name.
  312. IsDomain - Returns TRUE if the current user is logged on to a domain
  313. account, FALSE otherwise.
  314. Return Value:
  315. TRUE on success, FALSE on failure.
  316. --*/
  317. {
  318. *IsDomain = (wcscmp( EfsComputerName, lpDomainName ) != 0);
  319. return( TRUE );
  320. }
  321. BOOL
  322. EnrollKeyPair(
  323. IN PEFS_USER_INFO pEfsUserInfo,
  324. OUT HCRYPTKEY * hKey,
  325. OUT HCRYPTPROV * hProv,
  326. OUT LPWSTR * lpContainerName,
  327. OUT LPWSTR * lpProviderName,
  328. IN DWORD dwProviderType,
  329. OUT PBYTE * pbHash,
  330. OUT PDWORD cbHash,
  331. OUT LPWSTR * lpDisplayInfo
  332. )
  333. /*++
  334. Routine Description:
  335. This routine takes a keypair and attempts to enroll it.
  336. Arguments:
  337. hKey - Optionally returns a handle to the user's key.
  338. hProv - Optionally returns a handle to the user's key's provider.
  339. lpContainerName - Returns the name of the user's key container.
  340. lpProviderName - Returns the name of the user's key provider.
  341. ProviderType - Returns the type of the provider.
  342. pbHash - Returns the hash of the user's certificate.
  343. cbHash - Returns the length in bytes of the certificate hash.
  344. DisplayInfo - Returns the display information associated with this
  345. certificate.
  346. Return Value:
  347. TRUE on success, FALSE on failure. Call GetLastError() for details.
  348. --*/
  349. {
  350. BOOL b = FALSE;
  351. BOOL fResult = FALSE;
  352. NTSTATUS Status;
  353. DWORD rc = ERROR_SUCCESS;
  354. DWORD ImpersonationError;
  355. HCRYPTKEY hLocalKey = NULL;
  356. HCRYPTPROV hLocalProv = NULL;
  357. PCCERT_CONTEXT pCertContext = NULL ;
  358. //
  359. // Initialize OUT parameters
  360. //
  361. *pbHash = NULL;
  362. *lpDisplayInfo = NULL;
  363. *lpContainerName = NULL;
  364. *lpProviderName = NULL;
  365. *cbHash = 0;
  366. *hKey = NULL;
  367. *hProv = NULL;
  368. //
  369. // Initialize output parameters
  370. //
  371. if (pEfsUserInfo->bDomainAccount) {
  372. HRESULT AutoEnrollSuccess = S_OK;
  373. //
  374. // Attempt to create the auto-enroll object so that this cert re-enrolls.
  375. //
  376. // DLL is demand load.
  377. //
  378. __try {
  379. AutoEnrollSuccess = CACreateLocalAutoEnrollmentObject(
  380. wszCERTTYPE_EFS,
  381. NULL,
  382. NULL,
  383. CERT_SYSTEM_STORE_CURRENT_USER
  384. );
  385. } __except (EXCEPTION_EXECUTE_HANDLER) {
  386. rc = GetExceptionCode();
  387. AutoEnrollSuccess = (HRESULT)rc;
  388. }
  389. if (S_OK == AutoEnrollSuccess) {
  390. HCERTTYPE hCertType = 0;
  391. CRYPTUI_WIZ_CERT_REQUEST_INFO CertRequest;
  392. CRYPTUI_WIZ_CERT_REQUEST_PVK_NEW NewKeyInfo;
  393. CRYPT_KEY_PROV_INFO KeyProvInfo;
  394. CRYPTUI_WIZ_CERT_TYPE CertType;
  395. memset( &CertRequest, 0, sizeof( CRYPTUI_WIZ_CERT_REQUEST_INFO ));
  396. KeyProvInfo.pwszContainerName = NULL;
  397. KeyProvInfo.pwszProvName = NULL;
  398. KeyProvInfo.dwProvType = dwProviderType;
  399. KeyProvInfo.dwFlags = 0;
  400. KeyProvInfo.cProvParam = 0;
  401. KeyProvInfo.rgProvParam = NULL;
  402. KeyProvInfo.dwKeySpec = AT_KEYEXCHANGE;
  403. memset( &NewKeyInfo, 0, sizeof( CRYPTUI_WIZ_CERT_REQUEST_PVK_NEW ));
  404. NewKeyInfo.dwSize = sizeof( CRYPTUI_WIZ_CERT_REQUEST_PVK_NEW );
  405. NewKeyInfo.pKeyProvInfo = &KeyProvInfo;
  406. NewKeyInfo.dwGenKeyFlags = RSA1024BIT_KEY | CRYPT_EXPORTABLE;
  407. LPWSTR lpwstr = wszCERTTYPE_EFS;
  408. CertType.dwSize = sizeof( CRYPTUI_WIZ_CERT_TYPE );
  409. CertType.cCertType = 1;
  410. CertType.rgwszCertType = &lpwstr;
  411. //
  412. // Fill in the fields of the CertRequest structure
  413. //
  414. CertRequest.dwSize = sizeof( CRYPTUI_WIZ_CERT_REQUEST_INFO ); // required
  415. CertRequest.dwPurpose = CRYPTUI_WIZ_CERT_ENROLL; // enroll the certificate
  416. CertRequest.pwszMachineName = NULL;
  417. CertRequest.pwszAccountName = NULL;
  418. CertRequest.pAuthentication = NULL; // must be NULL
  419. CertRequest.pCertRequestString = NULL; // Reserved, must be NULL
  420. CertRequest.pwszDesStore = NULL; // defaults to MY store
  421. CertRequest.pszHashAlg = NULL;
  422. CertRequest.pRenewCertContext = NULL; // We're enrolling, not renewing
  423. CertRequest.dwPvkChoice = CRYPTUI_WIZ_CERT_REQUEST_PVK_CHOICE_NEW; // Create keyset
  424. CertRequest.pPvkNew = &NewKeyInfo;
  425. CertRequest.pwszCALocation = NULL;
  426. CertRequest.pwszCAName = NULL;
  427. CertRequest.dwPostOption = 0;
  428. CertRequest.pCertRequestExtensions = NULL;
  429. CertRequest.dwCertChoice = CRYPTUI_WIZ_CERT_REQUEST_CERT_TYPE;
  430. CertRequest.pCertType = &CertType;
  431. CertRequest.pwszCertDNName = L"CN=EFS";
  432. CertRequest.pwszFriendlyName = NULL; // Optional if CRYPTUI_WIZ_CERT_ENROLL is set in dwPurpose
  433. CertRequest.pwszDescription = NULL; // Optional if CRYPTUI_WIZ_CERT_ENROLL is set in dwPurpose
  434. DWORD CAdwStatus = 0 ;
  435. BOOL CryptUiResult ;
  436. __try {
  437. CryptUiResult = CryptUIWizCertRequest(
  438. CRYPTUI_WIZ_NO_UI,
  439. NULL,
  440. NULL,
  441. &CertRequest,
  442. &pCertContext,
  443. &CAdwStatus
  444. );
  445. }
  446. __except (EXCEPTION_EXECUTE_HANDLER) {
  447. CryptUiResult = FALSE ;
  448. SetLastError( GetExceptionCode() );
  449. }
  450. if (CryptUiResult) {
  451. //
  452. // Got back success, see if we got a cert back
  453. //
  454. if (CAdwStatus == CRYPTUI_WIZ_CERT_REQUEST_STATUS_SUCCEEDED) {
  455. //
  456. // We got back a valid Cert Context.
  457. // Get the hash out of it.
  458. //
  459. *pbHash = GetCertHashFromCertContext(
  460. pCertContext,
  461. cbHash
  462. );
  463. *lpDisplayInfo = EfspGetCertDisplayInformation( pCertContext );
  464. if (*pbHash && *lpDisplayInfo) {
  465. PCRYPT_KEY_PROV_INFO pCryptKeyProvInfo = GetKeyProvInfo( pCertContext );
  466. if (pCryptKeyProvInfo) {
  467. //
  468. // According to Xiaohong, we always get back container name and provider name here.
  469. // There is no need for us to check NULL here.
  470. //
  471. *lpContainerName = (LPWSTR)LsapAllocateLsaHeap( wcslen(pCryptKeyProvInfo->pwszContainerName) * sizeof( WCHAR ) + sizeof( UNICODE_NULL ));
  472. *lpProviderName = (LPWSTR)LsapAllocateLsaHeap( wcslen(pCryptKeyProvInfo->pwszProvName) * sizeof( WCHAR ) + sizeof( UNICODE_NULL ));
  473. if (*lpContainerName && *lpProviderName) {
  474. wcscpy( *lpContainerName, pCryptKeyProvInfo->pwszContainerName );
  475. wcscpy( *lpProviderName, pCryptKeyProvInfo->pwszProvName );
  476. if (CryptAcquireContext( hProv, *lpContainerName, *lpProviderName, PROV_RSA_FULL, CRYPT_SILENT )) {
  477. if (CryptGetUserKey(*hProv, AT_KEYEXCHANGE, hKey)) {
  478. fResult = TRUE;
  479. } else {
  480. rc = GetLastError();
  481. }
  482. } else {
  483. rc = GetLastError();
  484. }
  485. } else {
  486. rc = ERROR_NOT_ENOUGH_MEMORY;
  487. }
  488. LsapFreeLsaHeap( pCryptKeyProvInfo );
  489. } else {
  490. rc = GetLastError();
  491. }
  492. } else {
  493. rc = GetLastError();
  494. }
  495. // CertFreeCertificateContext( pCertContext );
  496. } else {
  497. //
  498. // We failed. Get the error. This error will be overwritten in the following code.
  499. // It only helps debug for now.
  500. //
  501. rc = GetLastError();
  502. }
  503. } else {
  504. rc = GetLastError();
  505. }
  506. if (!fResult) {
  507. //
  508. // We failed to get one from the CA. Issue a self-signed cert.
  509. //
  510. //
  511. // Free the memory allocated above first
  512. //
  513. if (*pbHash) {
  514. LsapFreeLsaHeap( *pbHash );
  515. *pbHash = NULL;
  516. }
  517. if (*lpDisplayInfo) {
  518. LsapFreeLsaHeap( *lpDisplayInfo );
  519. *lpDisplayInfo = NULL;
  520. }
  521. if (*lpContainerName) {
  522. LsapFreeLsaHeap( *lpContainerName );
  523. *lpContainerName = NULL;
  524. }
  525. if (*lpProviderName) {
  526. LsapFreeLsaHeap( *lpProviderName );
  527. *lpProviderName = NULL;
  528. }
  529. if (pCertContext) {
  530. CertFreeCertificateContext( pCertContext );
  531. }
  532. if ( *hKey) {
  533. CryptDestroyKey( *hKey );
  534. *hKey = NULL;
  535. }
  536. if ( *hProv) {
  537. CryptReleaseContext( *hProv, 0 );
  538. *hProv = NULL;
  539. }
  540. if (EfspCreateSelfSignedCert( hKey,
  541. hProv,
  542. lpContainerName,
  543. lpProviderName,
  544. pEfsUserInfo,
  545. pbHash,
  546. cbHash,
  547. lpDisplayInfo,
  548. &pCertContext
  549. )) {
  550. fResult = TRUE;
  551. } else {
  552. rc = GetLastError();
  553. }
  554. }
  555. } else {
  556. DebugLog((DEB_WARN, "Unable to create auto-enrollment object, error = %x\n" , AutoEnrollSuccess));
  557. rc = AutoEnrollSuccess;
  558. }
  559. } else {
  560. //
  561. // It's not a domain account, which means we can't get to the CA.
  562. // Issue a self-signed cert.
  563. //
  564. if (EfspCreateSelfSignedCert( hKey,
  565. hProv,
  566. lpContainerName,
  567. lpProviderName,
  568. pEfsUserInfo,
  569. pbHash,
  570. cbHash,
  571. lpDisplayInfo,
  572. &pCertContext
  573. )) {
  574. fResult = TRUE;
  575. } else {
  576. rc = GetLastError();
  577. }
  578. }
  579. //
  580. // Let's add this cert to the local store
  581. //
  582. if (fResult) {
  583. rc = EfsAddCertToTrustStoreStore(
  584. pCertContext,
  585. &ImpersonationError
  586. );
  587. if ( ERROR_SUCCESS != rc ) {
  588. DebugLog((DEB_ERROR, "Failed to add the cert to LM CA store, error = %x\n" , rc));
  589. if (ImpersonationError) {
  590. //
  591. // We got serious error. We reverted but could not impersonate back.
  592. // Quit the procedure. This should not happen.
  593. //
  594. DebugLog((DEB_ERROR, "Failed to impersonate after revert.\n"));
  595. fResult = FALSE;
  596. } else {
  597. //
  598. // Fail to add the cert to the store should not prevent us continue.
  599. //
  600. rc = ERROR_SUCCESS;
  601. }
  602. } else {
  603. //
  604. // Let's update the registry. This is the best effort. No need to see if succeed or not.
  605. //
  606. EfsMarkCertAddedToStore(pEfsUserInfo);
  607. }
  608. }
  609. //
  610. // Now check if we need create the cache
  611. //
  612. //
  613. // Create the cache node.
  614. // We could have a cache node which is not validated or no cache at all.
  615. // We could also have a valid cache but was not allowed to use since it
  616. // is being freed.
  617. //
  618. if (fResult && !pEfsUserInfo->UserCacheStop) {
  619. //
  620. // Cache is allowed now
  621. //
  622. if (!pEfsUserInfo->pUserCache || (pEfsUserInfo->pUserCache->CertValidated != CERT_VALIDATED)) {
  623. //
  624. // Let's create the cache
  625. //
  626. PUSER_CACHE pCacheNode;
  627. pCacheNode = (PUSER_CACHE) LsapAllocateLsaHeap(sizeof(USER_CACHE));
  628. if (pCacheNode) {
  629. memset( pCacheNode, 0, sizeof( USER_CACHE ));
  630. if (NT_SUCCESS( NtQuerySystemTime(&(pCacheNode->TimeStamp)))){
  631. if (EfspInitUserCacheNode(
  632. pCacheNode,
  633. *pbHash,
  634. *cbHash,
  635. *lpContainerName,
  636. *lpProviderName,
  637. *lpDisplayInfo,
  638. pCertContext,
  639. *hKey,
  640. *hProv,
  641. &(pEfsUserInfo->AuthId),
  642. CERT_VALIDATED
  643. )){
  644. //
  645. // Cache node created and ready for use. Do not delete or close the info
  646. // we just got.
  647. //
  648. *lpContainerName = NULL;
  649. *lpProviderName = NULL;
  650. *lpDisplayInfo = NULL;
  651. *pbHash = NULL;
  652. *cbHash = NULL;
  653. *hProv = NULL;
  654. *hKey = NULL;
  655. if (pEfsUserInfo->pUserCache) {
  656. //
  657. // We had a not validated cache
  658. //
  659. EfspReleaseUserCache(pEfsUserInfo->pUserCache);
  660. }
  661. pEfsUserInfo->pUserCache = pCacheNode;
  662. pCertContext = NULL;
  663. } else {
  664. LsapFreeLsaHeap(pCacheNode);
  665. pCacheNode = NULL;
  666. }
  667. } else {
  668. LsapFreeLsaHeap(pCacheNode);
  669. pCacheNode = NULL;
  670. }
  671. }
  672. }
  673. //
  674. // Even if cache failed to create, but we can proceed without cache
  675. //
  676. }
  677. if (pCertContext) {
  678. CertFreeCertificateContext( pCertContext );
  679. pCertContext = NULL;
  680. }
  681. if (!fResult) {
  682. //
  683. // Something failed, free all the OUT parameters
  684. // that were allocated.
  685. //
  686. if (*pbHash) {
  687. LsapFreeLsaHeap( *pbHash );
  688. *pbHash = NULL;
  689. }
  690. if (*lpDisplayInfo) {
  691. LsapFreeLsaHeap( *lpDisplayInfo );
  692. *lpDisplayInfo = NULL;
  693. }
  694. if (*lpContainerName) {
  695. LsapFreeLsaHeap( *lpContainerName );
  696. *lpContainerName = NULL;
  697. }
  698. if (*lpProviderName) {
  699. LsapFreeLsaHeap( *lpProviderName );
  700. *lpProviderName = NULL;
  701. }
  702. if ( *hKey) {
  703. CryptDestroyKey( *hKey );
  704. *hKey = NULL;
  705. }
  706. if ( *hProv) {
  707. CryptReleaseContext( *hProv, 0 );
  708. *hProv = NULL;
  709. }
  710. }
  711. SetLastError( rc );
  712. return ( fResult );
  713. }
  714. BOOL
  715. EfspCreateSelfSignedCert(
  716. OUT HCRYPTKEY * hKey,
  717. OUT HCRYPTPROV * hProv,
  718. OUT LPWSTR * lpContainerName,
  719. OUT LPWSTR * lpProviderName,
  720. IN PEFS_USER_INFO pEfsUserInfo,
  721. OUT PBYTE * pbHash,
  722. OUT PDWORD cbHash,
  723. OUT LPWSTR * lpDisplayInfo,
  724. OUT PCCERT_CONTEXT *pCertContext
  725. )
  726. /*++
  727. Routine Description:
  728. This routine sets up and creates a self-signed certificate.
  729. Arguments:
  730. lpContainerName - Returns the container name of the new certificate.
  731. lpProviderName - Returns the provider name of the new certificate.
  732. pbHash - Returns the hash of the new certificate.
  733. cbHash - Returns the length in bytes of the new certificate hash.
  734. lpDisplayInfo - Returns the display string for the new certificate.
  735. Return Value:
  736. TRUE on success, FALSE on failure. Call GetLastError() for more details.
  737. --*/
  738. {
  739. BOOL b = FALSE;
  740. DWORD rc = ERROR_SUCCESS;
  741. //
  742. // Initialize OUT parameters
  743. //
  744. *lpContainerName = NULL;
  745. *lpProviderName = NULL;
  746. *pbHash = NULL;
  747. *lpDisplayInfo = NULL;
  748. *pCertContext = NULL;
  749. *hKey = NULL;
  750. *hProv = NULL;
  751. //
  752. // Croft up a key pair
  753. //
  754. //
  755. // Container name
  756. //
  757. GUID guidContainerName;
  758. UuidCreate(&guidContainerName);
  759. LPWSTR TmpContainerName;
  760. if (ERROR_SUCCESS == UuidToStringW(&guidContainerName, &TmpContainerName )) {
  761. //
  762. // Copy the container name into LSA heap memory
  763. //
  764. *lpContainerName = (LPWSTR)LsapAllocateLsaHeap( (wcslen( TmpContainerName ) + 1) * sizeof( WCHAR ) );
  765. if (*lpContainerName) {
  766. wcscpy( *lpContainerName, TmpContainerName );
  767. *lpProviderName = (PWCHAR)LsapAllocateLsaHeap( (wcslen( MS_DEF_PROV ) + 1) * sizeof( WCHAR ) );
  768. if (*lpProviderName == NULL) {
  769. rc = ERROR_NOT_ENOUGH_MEMORY;
  770. } else {
  771. wcscpy( *lpProviderName, MS_DEF_PROV );
  772. //
  773. // Create the key container
  774. //
  775. if (CryptAcquireContext(hProv, *lpContainerName, *lpProviderName, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_SILENT )) {
  776. if (CryptGenKey(*hProv, AT_KEYEXCHANGE, RSA1024BIT_KEY | CRYPT_EXPORTABLE, hKey)) {
  777. //
  778. // Construct the subject name information
  779. //
  780. LPWSTR UPNName = NULL;
  781. LPWSTR SubName = NULL;
  782. //*lpDisplayInfo = MakeDNName( FALSE, pEfsUserInfo);
  783. rc = EfsMakeCertNames(
  784. pEfsUserInfo,
  785. lpDisplayInfo,
  786. &SubName,
  787. &UPNName
  788. );
  789. if (ERROR_SUCCESS == rc) {
  790. //
  791. // Use this piece of code to create the PCERT_NAME_BLOB going into CertCreateSelfSignCertificate()
  792. //
  793. CERT_NAME_BLOB SubjectName;
  794. SubjectName.cbData = 0;
  795. if(CertStrToNameW(
  796. CRYPT_ASN_ENCODING,
  797. SubName,
  798. 0,
  799. NULL,
  800. NULL,
  801. &SubjectName.cbData,
  802. NULL)) {
  803. SubjectName.pbData = (BYTE *) LsapAllocateLsaHeap(SubjectName.cbData);
  804. if (SubjectName.pbData) {
  805. if (CertStrToNameW(
  806. CRYPT_ASN_ENCODING,
  807. SubName,
  808. 0,
  809. NULL,
  810. SubjectName.pbData,
  811. &SubjectName.cbData,
  812. NULL) ) {
  813. //
  814. // Make the UPN Name
  815. //
  816. PCERT_EXTENSION altNameExt = NULL;
  817. if (EfsGetAltNameExt(&altNameExt, UPNName)) {
  818. //
  819. // Make the basic restrain extension
  820. //
  821. PCERT_EXTENSION basicRestraint = NULL;
  822. if (EfsGetBasicConstraintExt(&basicRestraint)) {
  823. //
  824. // Make the enhanced key usage
  825. //
  826. CERT_ENHKEY_USAGE certEnhKeyUsage;
  827. LPSTR lpstr;
  828. CERT_EXTENSION certExt[3];
  829. lpstr = szOID_EFS_CRYPTO;
  830. certEnhKeyUsage.cUsageIdentifier = 1;
  831. certEnhKeyUsage.rgpszUsageIdentifier = &lpstr;
  832. // now call CryptEncodeObject to encode the enhanced key usage into the extension struct
  833. certExt[0].Value.cbData = 0;
  834. certExt[0].Value.pbData = NULL;
  835. certExt[0].fCritical = FALSE;
  836. certExt[0].pszObjId = szOID_ENHANCED_KEY_USAGE;
  837. //
  838. // Encode it
  839. //
  840. if (EncodeAndAlloc(
  841. CRYPT_ASN_ENCODING,
  842. X509_ENHANCED_KEY_USAGE,
  843. &certEnhKeyUsage,
  844. &certExt[0].Value.pbData,
  845. &certExt[0].Value.cbData
  846. )) {
  847. //
  848. // finally, set up the array of extensions in the certInfo struct
  849. // any further extensions need to be added to this array.
  850. //
  851. CERT_EXTENSIONS certExts;
  852. certExts.cExtension = sizeof(certExt) / sizeof(CERT_EXTENSION);
  853. certExts.rgExtension = &certExt[0];
  854. certExt[1] = *altNameExt;
  855. certExt[2] = *basicRestraint;
  856. CRYPT_KEY_PROV_INFO KeyProvInfo;
  857. memset( &KeyProvInfo, 0, sizeof( CRYPT_KEY_PROV_INFO ));
  858. KeyProvInfo.pwszContainerName = *lpContainerName;
  859. KeyProvInfo.pwszProvName = *lpProviderName;
  860. KeyProvInfo.dwProvType = PROV_RSA_FULL;
  861. KeyProvInfo.dwKeySpec = AT_KEYEXCHANGE;
  862. //
  863. // Make the expiration time very very long (100 years)
  864. //
  865. SYSTEMTIME StartTime;
  866. FILETIME FileTime;
  867. LARGE_INTEGER TimeData;
  868. SYSTEMTIME EndTime;
  869. GetSystemTime(&StartTime);
  870. SystemTimeToFileTime(&StartTime, &FileTime);
  871. TimeData.LowPart = FileTime.dwLowDateTime;
  872. TimeData.HighPart = (LONG) FileTime.dwHighDateTime;
  873. TimeData.QuadPart += YEARCOUNT * 100;
  874. FileTime.dwLowDateTime = TimeData.LowPart;
  875. FileTime.dwHighDateTime = (DWORD) TimeData.HighPart;
  876. FileTimeToSystemTime(&FileTime, &EndTime);
  877. *pCertContext = CertCreateSelfSignCertificate(
  878. *hProv,
  879. &SubjectName,
  880. 0,
  881. &KeyProvInfo,
  882. NULL,
  883. &StartTime,
  884. &EndTime,
  885. &certExts
  886. );
  887. if (*pCertContext) {
  888. *pbHash = GetCertHashFromCertContext(
  889. *pCertContext,
  890. cbHash
  891. );
  892. if (*pbHash) {
  893. HCERTSTORE hStore;
  894. // hStore = CertOpenSystemStoreW( NULL, L"MY" );
  895. hStore = CertOpenStore(
  896. CERT_STORE_PROV_SYSTEM_REGISTRY_W,
  897. 0, // dwEncodingType
  898. 0, // hCryptProv,
  899. CERT_SYSTEM_STORE_CURRENT_USER,
  900. L"My"
  901. );
  902. if (hStore) {
  903. //
  904. // save the temp cert
  905. //
  906. if(CertAddCertificateContextToStore(
  907. hStore,
  908. *pCertContext,
  909. CERT_STORE_ADD_NEW,
  910. NULL) ) {
  911. b = TRUE;
  912. } else {
  913. rc = GetLastError();
  914. }
  915. CertCloseStore( hStore, 0 );
  916. } else {
  917. rc = GetLastError();
  918. }
  919. } else {
  920. rc = GetLastError();
  921. }
  922. } else {
  923. rc = GetLastError();
  924. }
  925. LsapFreeLsaHeap( certExt[0].Value.pbData );
  926. } else {
  927. rc = GetLastError();
  928. }
  929. LsapFreeLsaHeap(basicRestraint->Value.pbData);
  930. LsapFreeLsaHeap(basicRestraint);
  931. } else {
  932. rc = GetLastError();
  933. }
  934. LsapFreeLsaHeap(altNameExt->Value.pbData);
  935. LsapFreeLsaHeap(altNameExt);
  936. } else {
  937. rc = GetLastError();
  938. }
  939. } else {
  940. rc = GetLastError();
  941. }
  942. LsapFreeLsaHeap( SubjectName.pbData );
  943. } else {
  944. rc = ERROR_NOT_ENOUGH_MEMORY;
  945. }
  946. } else {
  947. rc = GetLastError();
  948. }
  949. }
  950. LsapFreeLsaHeap(UPNName);
  951. LsapFreeLsaHeap(SubName);
  952. } else {
  953. //
  954. // We create the container but failed to get the keys. We need to
  955. // clean up the useless container here.
  956. //
  957. rc = GetLastError();
  958. CryptReleaseContext( *hProv, 0 );
  959. CryptAcquireContext(hProv, *lpContainerName, *lpProviderName, PROV_RSA_FULL, CRYPT_DELETEKEYSET | CRYPT_SILENT );
  960. //
  961. // No need to call CryptReleaseContext any more.
  962. //
  963. *hProv = NULL;
  964. }
  965. } else {
  966. rc = GetLastError();
  967. }
  968. }
  969. } else {
  970. rc = ERROR_NOT_ENOUGH_MEMORY;
  971. }
  972. RpcStringFree( &TmpContainerName );
  973. } else {
  974. rc = ERROR_NOT_ENOUGH_MEMORY;
  975. }
  976. if (!b) {
  977. //
  978. // Something failed, clean up whatever we allocated
  979. //
  980. if (*pbHash) {
  981. LsapFreeLsaHeap( *pbHash );
  982. *pbHash = NULL;
  983. }
  984. if (*lpDisplayInfo) {
  985. LsapFreeLsaHeap( *lpDisplayInfo );
  986. *lpDisplayInfo = NULL;
  987. }
  988. if (*lpContainerName) {
  989. LsapFreeLsaHeap( *lpContainerName );
  990. *lpContainerName = NULL;
  991. }
  992. if (*lpProviderName) {
  993. LsapFreeLsaHeap( *lpProviderName );
  994. *lpProviderName = NULL;
  995. }
  996. if ( *pCertContext ) {
  997. CertFreeCertificateContext( *pCertContext );
  998. *pCertContext = NULL;
  999. }
  1000. if (*hKey) {
  1001. CryptDestroyKey( *hKey );
  1002. *hKey = NULL;
  1003. }
  1004. if (*hProv) {
  1005. CryptReleaseContext( *hProv, 0 );
  1006. *hProv = NULL;
  1007. }
  1008. }
  1009. SetLastError( rc );
  1010. return( b );
  1011. }
  1012. DWORD
  1013. GenerateUserKey (
  1014. IN PEFS_USER_INFO pEfsUserInfo,
  1015. OUT HCRYPTKEY * hKey OPTIONAL,
  1016. OUT HCRYPTPROV * hProv OPTIONAL,
  1017. OUT LPWSTR * lpContainerName,
  1018. OUT LPWSTR * lpProviderName,
  1019. OUT PDWORD ProviderType,
  1020. OUT LPWSTR * DisplayInfo,
  1021. OUT PBYTE * pbHash,
  1022. OUT PDWORD cbHash
  1023. )
  1024. /*++
  1025. Routine Description:
  1026. This routine will construct a default user key for the current user
  1027. and install it in the registry. The constructed key takes the form
  1028. <UserName>_<MachineName>_EFS_<i>
  1029. Where i is increased as necessary to construct a valid key name.
  1030. Arguments:
  1031. hKey - Optionally returns a handle to the new key. This key must
  1032. be destroyed by the caller via CryptDestroyKey().
  1033. hProv - Optionally returns a handle to the provider of the new key.
  1034. This handle must be closed by the user via CryptReleaseContext().
  1035. lpContainerName - Returns a pointer to the name of the new key. This
  1036. buffer must be freed via LsapFreeHeap().
  1037. lpProviderName - Returns a pointer to the provider of the new key. This
  1038. buffer must be freed via LsapFreeHeap().
  1039. ProviderType - Returns the type of the provider of the new key.
  1040. pbHash - Returns a pointer to the certificate hash for this key.
  1041. cbHash - Returns the size fo the pbHash buffer.
  1042. Return Value:
  1043. ERROR_SUCCESS for succeed.
  1044. --*/
  1045. {
  1046. BOOL fSuccess = FALSE;
  1047. DWORD Disposition = 0;
  1048. DWORD dwDataLength = 0;
  1049. HCRYPTKEY LocalhKey = 0;
  1050. HCRYPTPROV LocalhProv = 0;
  1051. HKEY KeyHandle = NULL;
  1052. LONG rc = ERROR_SUCCESS;
  1053. //
  1054. // Initialize our output parameters
  1055. //
  1056. *ProviderType = PROV_RSA_FULL;
  1057. *lpProviderName = NULL;
  1058. *lpContainerName = NULL;
  1059. *DisplayInfo = NULL;
  1060. *pbHash = NULL;
  1061. if (ARGUMENT_PRESENT(hKey)) {
  1062. *hKey = NULL;
  1063. }
  1064. if (ARGUMENT_PRESENT(hProv)) {
  1065. *hProv = NULL;
  1066. }
  1067. //
  1068. // Use the user name as a mutex name to synchronize access to the following
  1069. // code. This way we don't hang up every thread to come through here, only
  1070. // ones from this user.
  1071. //
  1072. HANDLE hMutex = CreateMutex( NULL, TRUE, pEfsUserInfo->lpUserName );
  1073. if (hMutex != NULL) {
  1074. if (GetLastError() == ERROR_SUCCESS) {
  1075. //
  1076. // If we're here, we have the mutex, so we can proceed.
  1077. //
  1078. // Note that it is possible for some other thread to have
  1079. // come through here and created keys for the user while
  1080. // we were busy doing all of this. We will attempt to create
  1081. // the registry key where we will store the key information,
  1082. // and if it's already there, we will assume that someone
  1083. // came in and did all this while we were on our way.
  1084. //
  1085. //
  1086. // Create the registry path, if it does not already exist.
  1087. //
  1088. rc = RegCreateKeyEx( KEYPATHROOT,
  1089. pEfsUserInfo->lpKeyPath,
  1090. 0,
  1091. TEXT("REG_SZ"),
  1092. REG_OPTION_NON_VOLATILE,
  1093. KEY_READ | KEY_WRITE,
  1094. NULL,
  1095. &KeyHandle,
  1096. &Disposition
  1097. );
  1098. if (rc == ERROR_SUCCESS) {
  1099. //
  1100. // The key didn't exist. Create a cert
  1101. //
  1102. if (EnrollKeyPair( pEfsUserInfo,
  1103. &LocalhKey,
  1104. &LocalhProv,
  1105. lpContainerName,
  1106. lpProviderName,
  1107. PROV_RSA_FULL,
  1108. pbHash,
  1109. cbHash,
  1110. DisplayInfo
  1111. )) {
  1112. PBYTE pbLocalHash;
  1113. DWORD cbLocalHash;
  1114. //
  1115. // Write the hash value to the registry
  1116. //
  1117. if (*pbHash) {
  1118. pbLocalHash = *pbHash;
  1119. cbLocalHash = *cbHash;
  1120. } else {
  1121. ASSERT(pEfsUserInfo->pUserCache);
  1122. pbLocalHash = pEfsUserInfo->pUserCache->pbHash;
  1123. cbLocalHash = pEfsUserInfo->pUserCache->cbHash;
  1124. }
  1125. rc = RegSetValueEx(
  1126. KeyHandle, // handle of key to set value for
  1127. CERT_HASH,
  1128. 0,
  1129. REG_BINARY,
  1130. pbLocalHash,
  1131. cbLocalHash
  1132. );
  1133. if (rc == ERROR_SUCCESS) {
  1134. //
  1135. // Mark entire operation as successful
  1136. //
  1137. fSuccess = TRUE;
  1138. }
  1139. } else {
  1140. rc = GetLastError();
  1141. }
  1142. RegCloseKey( KeyHandle );
  1143. } else {
  1144. KeyHandle = NULL; // paranoia
  1145. //
  1146. // We couldn't create the registry key for some reason,
  1147. // fail the entire operation.
  1148. //
  1149. }
  1150. } else {
  1151. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  1152. DebugLog((DEB_TRACE_EFS, "KeyGen mutex %ws exists\n", pEfsUserInfo->lpUserName ));
  1153. //
  1154. // Some other thread is in here trying to create the keys.
  1155. // Wait on this mutex, and assume that once we come back,
  1156. // the other thread is done and we can just leave and
  1157. // try to get the keys again.
  1158. //
  1159. WaitForSingleObject( hMutex, INFINITE );
  1160. } else {
  1161. //
  1162. // If we're here, then CreateMutex did not fail, but GetLastError is
  1163. // set to something other than success or ERROR_ALREADY_EXISTS. Is
  1164. // this an error?
  1165. //
  1166. ASSERT(FALSE);
  1167. }
  1168. rc = ERROR_RETRY;
  1169. }
  1170. DebugLog((DEB_TRACE_EFS, "Closing mutex handle\n" ));
  1171. ReleaseMutex( hMutex );
  1172. CloseHandle( hMutex );
  1173. } else {
  1174. DebugLog((DEB_ERROR, "CreateMutex failed, error = %x\n", GetLastError() ));
  1175. rc = GetLastError();
  1176. }
  1177. if (fSuccess) {
  1178. //
  1179. // Return these to the caller
  1180. //
  1181. if (ARGUMENT_PRESENT( hKey ) && ARGUMENT_PRESENT( hProv )) {
  1182. //
  1183. // If the caller passed this in, he wants
  1184. // the key and provider passed back
  1185. //
  1186. *hKey = LocalhKey;
  1187. *hProv = LocalhProv;
  1188. } else {
  1189. if ( LocalhKey ) {
  1190. CryptDestroyKey( LocalhKey );
  1191. }
  1192. if ( LocalhProv ) {
  1193. CryptReleaseContext( LocalhProv, 0 );
  1194. }
  1195. }
  1196. } else {
  1197. //
  1198. // We failed somewhere, free what we were going
  1199. // to return.
  1200. //
  1201. if (*lpProviderName != NULL) {
  1202. LsapFreeLsaHeap( *lpProviderName );
  1203. *lpProviderName = NULL;
  1204. }
  1205. if (*lpContainerName != NULL) {
  1206. LsapFreeLsaHeap( *lpContainerName );
  1207. *lpContainerName = NULL;
  1208. }
  1209. if (*DisplayInfo != NULL) {
  1210. LsapFreeLsaHeap( *DisplayInfo );
  1211. *DisplayInfo = NULL;
  1212. }
  1213. if (*pbHash) {
  1214. LsapFreeLsaHeap( *pbHash );
  1215. *pbHash = NULL;
  1216. }
  1217. if (LocalhKey != 0) {
  1218. CryptDestroyKey( LocalhKey );
  1219. }
  1220. if (LocalhProv != 0) {
  1221. CryptReleaseContext(LocalhProv, 0);
  1222. }
  1223. }
  1224. return( rc );
  1225. }
  1226. BOOL
  1227. EqualCertPublicKeys(
  1228. PCERT_PUBLIC_KEY_INFO pKey1,
  1229. PCERT_PUBLIC_KEY_INFO pKey2
  1230. )
  1231. /*++
  1232. Routine Description:
  1233. Helper routine to compare the public key portions of two certificates.
  1234. Arguments:
  1235. pKey1 - One of the public key info structures.
  1236. pKey2 - The other one.
  1237. Return Value:
  1238. TRUE on match, FALSE on failure.
  1239. --*/
  1240. {
  1241. CRYPT_BIT_BLOB * PublicKey1 = &pKey1->PublicKey;
  1242. CRYPT_BIT_BLOB * PublicKey2 = &pKey2->PublicKey;
  1243. if (PublicKey1->cbData == PublicKey2->cbData) {
  1244. if (memcmp(PublicKey1->pbData, PublicKey2->pbData, PublicKey2->cbData) == 0) {
  1245. return( TRUE );
  1246. }
  1247. }
  1248. return( FALSE );
  1249. }
  1250. LONG
  1251. SearchMyStoreForEFSCert(
  1252. IN PEFS_USER_INFO pEfsUserInfo,
  1253. OUT HCRYPTKEY * hKey OPTIONAL,
  1254. OUT HCRYPTPROV * hProv OPTIONAL,
  1255. OUT LPWSTR * ContainerName,
  1256. OUT LPWSTR * ProviderName,
  1257. OUT LPWSTR * DisplayInfo,
  1258. OUT PBYTE * pbHash,
  1259. OUT PDWORD cbHash
  1260. )
  1261. /*++
  1262. Routine Description:
  1263. description-of-function.
  1264. Arguments:
  1265. argument-name - Supplies | Returns description of argument.
  1266. .
  1267. .
  1268. Return Value:
  1269. return-value - Description of conditions needed to return value. - or -
  1270. None.
  1271. --*/
  1272. {
  1273. DWORD rc = ERROR_NO_USER_KEYS;
  1274. HKEY hRegKey;
  1275. DWORD Disposition = 0;
  1276. HCRYPTPROV hLocalProv = NULL;
  1277. NTSTATUS status;
  1278. //
  1279. // Initialize required return values.
  1280. //
  1281. *ProviderName = NULL;
  1282. *ContainerName = NULL;
  1283. *DisplayInfo = NULL;
  1284. *pbHash = NULL;
  1285. *cbHash = 0;
  1286. //
  1287. // Initialize optional return values
  1288. //
  1289. if (ARGUMENT_PRESENT(hKey)) {
  1290. *hKey = NULL;
  1291. }
  1292. if (ARGUMENT_PRESENT(hProv)) {
  1293. *hProv = NULL;
  1294. }
  1295. //
  1296. // Assume that there's no current EFS information
  1297. // for this guy. Create the registry key.
  1298. //
  1299. rc = RegCreateKeyEx(
  1300. KEYPATHROOT,
  1301. pEfsUserInfo->lpKeyPath,
  1302. 0,
  1303. TEXT("REG_SZ"),
  1304. REG_OPTION_NON_VOLATILE,
  1305. KEY_ALL_ACCESS,
  1306. NULL,
  1307. &hRegKey,
  1308. &Disposition // address of disposition value buffer
  1309. );
  1310. //
  1311. // Open up the user's MY store and see if there's an EFS
  1312. // certificate floating around in there somewhere.
  1313. //
  1314. if (rc == ERROR_SUCCESS) {
  1315. CERT_ENHKEY_USAGE certEnhKeyUsage;
  1316. LPSTR lpstr = szOID_EFS_CRYPTO;
  1317. certEnhKeyUsage.cUsageIdentifier = 1;
  1318. certEnhKeyUsage.rgpszUsageIdentifier = &lpstr;
  1319. PCCERT_CONTEXT pCertContext = NULL;
  1320. //
  1321. // If this fails, there's no cert that matches.
  1322. //
  1323. HCERTSTORE hStore = CertOpenStore(
  1324. CERT_STORE_PROV_SYSTEM_REGISTRY_W,
  1325. 0, // dwEncodingType
  1326. 0, // hCryptProv,
  1327. CERT_SYSTEM_STORE_CURRENT_USER,
  1328. L"My"
  1329. );
  1330. // hStore = CertOpenSystemStoreW( NULL, L"MY");
  1331. if (hStore) {
  1332. do {
  1333. //
  1334. // This will go to success if everything works...
  1335. //
  1336. rc = ERROR_NO_USER_KEYS;
  1337. pCertContext = CertFindCertificateInStore(
  1338. hStore,
  1339. X509_ASN_ENCODING,
  1340. 0, //CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
  1341. CERT_FIND_ENHKEY_USAGE,
  1342. &certEnhKeyUsage,
  1343. pCertContext
  1344. );
  1345. if (pCertContext) {
  1346. DebugLog((DEB_TRACE_EFS, "Found matching cert in MY store\n" ));
  1347. //
  1348. // Do cert validity checking.
  1349. //
  1350. if ( CertVerifyTimeValidity(
  1351. NULL,
  1352. pCertContext->pCertInfo
  1353. )){
  1354. rc = CERT_E_EXPIRED;
  1355. } else {
  1356. //
  1357. // Test the cert usage here.
  1358. // CERT_E_WRONG_USAGE
  1359. //
  1360. BOOL OidFound;
  1361. rc = EfsFindCertOid(
  1362. szOID_KP_EFS,
  1363. pCertContext,
  1364. &OidFound
  1365. );
  1366. if (ERROR_SUCCESS == rc) {
  1367. rc = ERROR_NO_USER_KEYS;
  1368. if (OidFound) {
  1369. *pbHash = GetCertHashFromCertContext(
  1370. pCertContext,
  1371. cbHash
  1372. );
  1373. if (*pbHash) {
  1374. //
  1375. // See if we can get container and provider info.
  1376. //
  1377. // Once we've got them, make sure we can call CryptAcquireContext
  1378. // and have it work. That guarantees there's a private key available.
  1379. //
  1380. PCRYPT_KEY_PROV_INFO pCryptKeyProvInfo = GetKeyProvInfo( pCertContext );
  1381. if (pCryptKeyProvInfo) {
  1382. if (!wcscmp(pCryptKeyProvInfo->pwszProvName, MS_DEF_PROV_W) ||
  1383. !wcscmp(pCryptKeyProvInfo->pwszProvName, MS_ENHANCED_PROV_W) ||
  1384. !wcscmp(pCryptKeyProvInfo->pwszProvName, MS_STRONG_PROV_W)) {
  1385. if (CryptAcquireContext(
  1386. &hLocalProv,
  1387. pCryptKeyProvInfo->pwszContainerName,
  1388. pCryptKeyProvInfo->pwszProvName,
  1389. pCryptKeyProvInfo->dwProvType,
  1390. pCryptKeyProvInfo->dwFlags | CRYPT_SILENT
  1391. )) {
  1392. //
  1393. // Make sure the public key in the cert matches the one
  1394. // that's in this context.
  1395. //
  1396. DWORD cbPubKeyInfo = 0;
  1397. PCERT_PUBLIC_KEY_INFO pPubKeyInfo = ExportPublicKeyInfo(
  1398. hLocalProv,
  1399. pCryptKeyProvInfo->dwKeySpec,
  1400. X509_ASN_ENCODING,
  1401. &cbPubKeyInfo
  1402. );
  1403. if (pPubKeyInfo) {
  1404. //
  1405. // Get the public key from the cert context
  1406. //
  1407. PCERT_INFO pCertInfo = pCertContext->pCertInfo;
  1408. PCERT_PUBLIC_KEY_INFO pSubjectPublicKeyInfo = &pCertInfo->SubjectPublicKeyInfo;
  1409. if (EqualCertPublicKeys( pPubKeyInfo, pSubjectPublicKeyInfo )) {
  1410. //
  1411. // They match. We want to make sure not to return
  1412. // an error indicating that we didn't find a key.
  1413. // The next call will reset the value of rc
  1414. //
  1415. rc = RegSetValueEx(
  1416. hRegKey, // handle of key to set value for
  1417. CERT_HASH,
  1418. 0,
  1419. REG_BINARY,
  1420. *pbHash,
  1421. *cbHash
  1422. );
  1423. if (rc == ERROR_SUCCESS) {
  1424. if (pCryptKeyProvInfo->pwszProvName) {
  1425. *ProviderName = (LPWSTR)LsapAllocateLsaHeap( wcslen(pCryptKeyProvInfo->pwszProvName) * sizeof( WCHAR ) + sizeof(L'\0') );
  1426. if (*ProviderName) {
  1427. wcscpy( *ProviderName, pCryptKeyProvInfo->pwszProvName );
  1428. } else {
  1429. rc = ERROR_NOT_ENOUGH_MEMORY;
  1430. }
  1431. }
  1432. if (pCryptKeyProvInfo->pwszContainerName) {
  1433. *ContainerName = (LPWSTR)LsapAllocateLsaHeap( wcslen(pCryptKeyProvInfo->pwszContainerName) * sizeof( WCHAR ) + sizeof(L'\0') );
  1434. if (*ContainerName) {
  1435. wcscpy( *ContainerName, pCryptKeyProvInfo->pwszContainerName );
  1436. } else {
  1437. rc = ERROR_NOT_ENOUGH_MEMORY;
  1438. }
  1439. }
  1440. if (rc == ERROR_SUCCESS) {
  1441. if (!(*DisplayInfo = EfspGetCertDisplayInformation( pCertContext ))) {
  1442. //
  1443. // At least for now, we do not accept Cert without display name
  1444. //
  1445. rc = GetLastError();
  1446. }
  1447. }
  1448. //
  1449. // Create the cache node.
  1450. // We could have a cache node which is not validated or no cache at all.
  1451. // We could also have a valid cache but was not allowed to use since it
  1452. // is being freed.
  1453. //
  1454. if ((rc == ERROR_SUCCESS) && !pEfsUserInfo->UserCacheStop) {
  1455. //
  1456. // Cache is allowed now
  1457. //
  1458. if (!pEfsUserInfo->pUserCache || (pEfsUserInfo->pUserCache->CertValidated != CERT_VALIDATED)) {
  1459. //
  1460. // Let's create the cache
  1461. //
  1462. PUSER_CACHE pCacheNode;
  1463. pCacheNode = (PUSER_CACHE) LsapAllocateLsaHeap(sizeof(USER_CACHE));
  1464. if (pCacheNode) {
  1465. memset( pCacheNode, 0, sizeof( USER_CACHE ));
  1466. if (NT_SUCCESS( status = NtQuerySystemTime(&(pCacheNode->TimeStamp)))){
  1467. HCRYPTKEY hLocalKey;
  1468. if (CryptGetUserKey( hLocalProv, AT_KEYEXCHANGE, &hLocalKey )){
  1469. if (EfspInitUserCacheNode(
  1470. pCacheNode,
  1471. *pbHash,
  1472. *cbHash,
  1473. *ContainerName,
  1474. *ProviderName,
  1475. *DisplayInfo,
  1476. pCertContext,
  1477. hLocalKey,
  1478. hLocalProv,
  1479. &(pEfsUserInfo->AuthId),
  1480. CERT_VALIDATED
  1481. )){
  1482. //
  1483. // Cache node created and ready for use. Do not delete or close the info
  1484. // we just got.
  1485. //
  1486. *ContainerName = NULL;
  1487. *ProviderName = NULL;
  1488. *DisplayInfo = NULL;
  1489. *pbHash = NULL;
  1490. *cbHash = NULL;
  1491. hLocalProv = NULL;
  1492. if (pEfsUserInfo->pUserCache) {
  1493. //
  1494. // We had a not validated cache
  1495. //
  1496. EfspReleaseUserCache(pEfsUserInfo->pUserCache);
  1497. }
  1498. pEfsUserInfo->pUserCache = pCacheNode;
  1499. pCertContext = NULL;
  1500. } else {
  1501. if (hLocalKey) {
  1502. CryptDestroyKey( hLocalKey );
  1503. }
  1504. LsapFreeLsaHeap(pCacheNode);
  1505. pCacheNode = NULL;
  1506. }
  1507. } else {
  1508. rc = GetLastError();
  1509. LsapFreeLsaHeap(pCacheNode);
  1510. pCacheNode = NULL;
  1511. }
  1512. } else {
  1513. rc = RtlNtStatusToDosError( status );
  1514. LsapFreeLsaHeap(pCacheNode);
  1515. pCacheNode = NULL;
  1516. }
  1517. }
  1518. }
  1519. }
  1520. }
  1521. } else {
  1522. rc = ERROR_NO_USER_KEYS;
  1523. }
  1524. LsapFreeLsaHeap( pPubKeyInfo );
  1525. }
  1526. }
  1527. }
  1528. LsapFreeLsaHeap( pCryptKeyProvInfo );
  1529. }
  1530. if (rc != ERROR_SUCCESS) {
  1531. LsapFreeLsaHeap( *pbHash );
  1532. *pbHash = NULL;
  1533. }
  1534. } else {
  1535. //
  1536. // If we failed for any reason other than running
  1537. // out of memory, assume that there is no key of
  1538. // use to us and return an appropriate error.
  1539. //
  1540. rc = GetLastError();
  1541. }
  1542. }
  1543. }
  1544. }
  1545. }
  1546. //
  1547. // We want to keep trying until we're out of certificates or we get
  1548. // an unexpected error (like out of memory).
  1549. //
  1550. if (rc != ERROR_SUCCESS) {
  1551. //
  1552. // Something failed, clean up anything we allocated that
  1553. // we were going to return.
  1554. //
  1555. if (*ProviderName) {
  1556. LsapFreeLsaHeap( *ProviderName );
  1557. *ProviderName = NULL;
  1558. }
  1559. if (*ContainerName) {
  1560. LsapFreeLsaHeap( *ContainerName );
  1561. *ContainerName = NULL;
  1562. }
  1563. if (*DisplayInfo) {
  1564. LsapFreeLsaHeap( *DisplayInfo );
  1565. *DisplayInfo = NULL;
  1566. }
  1567. if (*pbHash) {
  1568. LsapFreeLsaHeap( *pbHash );
  1569. *pbHash = NULL;
  1570. }
  1571. if (hLocalProv) {
  1572. CryptReleaseContext( hLocalProv, 0 );
  1573. hLocalProv = NULL;
  1574. }
  1575. }
  1576. } while ( pCertContext && rc != ERROR_SUCCESS );
  1577. if (pCertContext) {
  1578. CertFreeCertificateContext( pCertContext );
  1579. }
  1580. CertCloseStore( hStore, 0 );
  1581. if (ARGUMENT_PRESENT(hKey) && ARGUMENT_PRESENT(hProv) && (rc == ERROR_SUCCESS) && (*pbHash)) {
  1582. *hProv = hLocalProv;
  1583. CryptGetUserKey( *hProv, AT_KEYEXCHANGE, hKey );
  1584. } else {
  1585. if (hLocalProv) {
  1586. CryptReleaseContext( hLocalProv, 0 );
  1587. }
  1588. }
  1589. } else {
  1590. //
  1591. // If we couldn't open the store, return
  1592. // no user keys and continue.
  1593. //
  1594. rc = ERROR_NO_USER_KEYS;
  1595. }
  1596. RegCloseKey( hRegKey );
  1597. }
  1598. return( rc );
  1599. }
  1600. LONG
  1601. GetInfoFromCertHash(
  1602. IN PEFS_USER_INFO pEfsUserInfo,
  1603. OUT HCRYPTKEY * hKey OPTIONAL,
  1604. OUT HCRYPTPROV * hProv OPTIONAL,
  1605. OUT LPWSTR * ContainerName,
  1606. OUT LPWSTR * ProviderName,
  1607. OUT LPWSTR * DisplayInfo,
  1608. OUT PBYTE * pbHash,
  1609. OUT PDWORD cbHash
  1610. )
  1611. /*++
  1612. Routine Description:
  1613. This routine will query the cert hash from the registry for this user and
  1614. return the useful information from the corresponding cert.
  1615. Arguments:
  1616. KeyPath - Supplies the fully formed path to the user's EFS key.
  1617. hKey - Optionally returns a handle to a key context.
  1618. hProv - Optionally returns a handle to a provider context.
  1619. ContainerName - Returns the name of the key container for this key.
  1620. ProviderName - Returns the name of the provider for this key.
  1621. DisplayInfo - Returns the display information from this certificate.
  1622. pbHash - Returns the hash found in the registry.
  1623. cbHash - Returns the size of the hash in bytes.
  1624. Return Value:
  1625. return-value - Description of conditions needed to return value. - or -
  1626. None.
  1627. --*/
  1628. {
  1629. DWORD rc;
  1630. HKEY hRegKey = NULL;
  1631. BOOLEAN bIsValid = TRUE;
  1632. //
  1633. // Initialize non-optional parameters
  1634. //
  1635. *ProviderName = NULL;
  1636. *ContainerName = NULL;
  1637. *DisplayInfo = NULL;
  1638. *pbHash = NULL;
  1639. *cbHash = 0;
  1640. //
  1641. // Initialize optional parameters
  1642. //
  1643. if (hKey) {
  1644. *hKey = NULL;
  1645. }
  1646. if (hProv) {
  1647. *hProv = NULL;
  1648. }
  1649. rc = RegOpenKeyEx(
  1650. KEYPATHROOT,
  1651. pEfsUserInfo->lpKeyPath,
  1652. 0,
  1653. GENERIC_READ | KEY_SET_VALUE,
  1654. &hRegKey
  1655. );
  1656. if (rc == ERROR_SUCCESS) {
  1657. /* It is time to close this.
  1658. (VOID) RegSetValueEx(
  1659. hRegKey, // handle of key to set value for
  1660. TEXT("EfsInUse"),
  1661. 0,
  1662. REG_BINARY,
  1663. NULL,
  1664. 0
  1665. );
  1666. */
  1667. //
  1668. // If there's a certificate thumbprint there, get it and use it.
  1669. //
  1670. DWORD Type;
  1671. rc = RegQueryValueEx(
  1672. hRegKey,
  1673. CERT_HASH,
  1674. NULL,
  1675. &Type,
  1676. NULL,
  1677. cbHash
  1678. );
  1679. if (rc == ERROR_SUCCESS) {
  1680. //
  1681. // Query out the thumbprint, find the cert, and return the key information.
  1682. //
  1683. if (*pbHash = (PBYTE)LsapAllocateLsaHeap( *cbHash )) {
  1684. rc = RegQueryValueEx(
  1685. hRegKey,
  1686. CERT_HASH,
  1687. NULL,
  1688. &Type,
  1689. *pbHash,
  1690. cbHash
  1691. );
  1692. if (rc == ERROR_SUCCESS) {
  1693. rc = GetKeyInfoFromCertHash(
  1694. pEfsUserInfo,
  1695. *pbHash,
  1696. *cbHash,
  1697. hKey,
  1698. hProv,
  1699. ContainerName,
  1700. ProviderName,
  1701. DisplayInfo,
  1702. &bIsValid
  1703. );
  1704. if (((*hKey == NULL) && (pEfsUserInfo->pUserCache) && (pEfsUserInfo->pUserCache->CertValidated != CERT_VALIDATED))
  1705. || !bIsValid) {
  1706. rc = ERROR_NO_USER_KEYS;
  1707. }
  1708. if ((rc == ERROR_SUCCESS) && (*hKey == NULL)) {
  1709. //
  1710. // The key in the cache is current. Free the pbHash
  1711. //
  1712. if (*pbHash) {
  1713. LsapFreeLsaHeap( *pbHash );
  1714. *pbHash = NULL;
  1715. }
  1716. }
  1717. }
  1718. } else {
  1719. rc = ERROR_NOT_ENOUGH_MEMORY;
  1720. }
  1721. }
  1722. RegCloseKey( hRegKey );
  1723. }
  1724. if (rc != ERROR_SUCCESS) {
  1725. //
  1726. // Something failed, clean up anything we allocated that
  1727. // we were going to return.
  1728. //
  1729. if (*ProviderName) {
  1730. LsapFreeLsaHeap( *ProviderName );
  1731. *ProviderName = NULL;
  1732. }
  1733. if (*ContainerName) {
  1734. LsapFreeLsaHeap( *ContainerName );
  1735. *ContainerName = NULL;
  1736. }
  1737. if (*DisplayInfo) {
  1738. LsapFreeLsaHeap( *DisplayInfo );
  1739. *DisplayInfo = NULL;
  1740. }
  1741. if (*pbHash) {
  1742. LsapFreeLsaHeap( *pbHash );
  1743. *pbHash = NULL;
  1744. }
  1745. if (hKey && *hKey) {
  1746. CryptDestroyKey( *hKey );
  1747. *hKey = NULL;
  1748. }
  1749. if (hProv && *hProv) {
  1750. CryptReleaseContext( *hProv, 0 );
  1751. *hProv = NULL;
  1752. }
  1753. //
  1754. // If anything other out out of memory failed, assume that there are no keys
  1755. // for this user.
  1756. //
  1757. if (rc != ERROR_NOT_ENOUGH_MEMORY) {
  1758. rc = ERROR_NO_USER_KEYS;
  1759. }
  1760. }
  1761. return( rc );
  1762. }
  1763. LONG
  1764. GetCurrentKey(
  1765. IN PEFS_USER_INFO pEfsUserInfo,
  1766. OUT HCRYPTKEY * hKey OPTIONAL,
  1767. OUT HCRYPTPROV * hProv OPTIONAL,
  1768. OUT LPWSTR * ContainerName,
  1769. OUT LPWSTR * ProviderName,
  1770. OUT PDWORD ProviderType,
  1771. OUT LPWSTR * DisplayInfo,
  1772. OUT PBYTE * pbHash,
  1773. OUT PDWORD cbHash
  1774. )
  1775. /*++
  1776. Routine Description:
  1777. This is the top level routine to get the user's current EFS key.
  1778. It will do the following, in order:
  1779. 1) Open the registry and attempt to find a certificate hash for
  1780. the user. If it finds one, it will attempt to find this hash
  1781. in the user's MY store and obtain all the useful information
  1782. with it.
  1783. 2) If that fails, it will check to see if there's old key data
  1784. (beta 1 and before) in the registry, and if it finds it, it
  1785. will convert that key data into a certificate and return
  1786. all the needed information.
  1787. 3) If that doesn't work, it will search the user's MY store for
  1788. an EFS certificate. If it finds one, it will install this as
  1789. the user's current EFS key.
  1790. 4) If that doesn't work, it will generate a new user key from scratch.
  1791. If that doesn't work, the operation fails.
  1792. Arguments:
  1793. hKey - Optionally returns a handle to the user's key.
  1794. hProv - Optionally returns a handle to the user's key's provider.
  1795. ContainerName - Returns the name of the user's key container.
  1796. ProviderName - Returns the name of the user's key provider.
  1797. ProviderType - Returns the type of the provider.
  1798. DisplayInfo - Returns the display information associated with this
  1799. certificate.
  1800. pbHash - Returns the hash of the user's certificate.
  1801. cbHash - Returns the length in bytes of the certificate hash.
  1802. Return Value:
  1803. ERROR_SUCCESS or Win32 error.
  1804. --*/
  1805. {
  1806. DWORD rc;
  1807. //
  1808. // There are four places we can get key information:
  1809. //
  1810. // 1) There's a hash in the registry. This is the typical
  1811. // case and the one we're going to try first.
  1812. //
  1813. // 2) Previous stuff left over from the last release of the
  1814. // system.
  1815. //
  1816. // 3) There's a cert in the user's MY store.
  1817. //
  1818. // 4) There's nothing.
  1819. //
  1820. //
  1821. // First, look for a hash.
  1822. //
  1823. rc = GetInfoFromCertHash(
  1824. pEfsUserInfo,
  1825. hKey,
  1826. hProv,
  1827. ContainerName,
  1828. ProviderName,
  1829. DisplayInfo,
  1830. pbHash,
  1831. cbHash
  1832. );
  1833. if ((ERROR_SUCCESS == rc) && ( NULL == *pbHash)) {
  1834. LARGE_INTEGER TimeStamp;
  1835. //
  1836. // We are using the cache
  1837. //
  1838. ASSERT( pEfsUserInfo->pUserCache );
  1839. ASSERT( pEfsUserInfo->pUserCache->pCertContext);
  1840. //
  1841. // Check if we need to validate the cert again
  1842. //
  1843. if (NT_SUCCESS( NtQuerySystemTime(&TimeStamp)) &&
  1844. (TimeStamp.QuadPart - pEfsUserInfo->pUserCache->TimeStamp.QuadPart > CACHE_CERT_VALID_TIME )){
  1845. //
  1846. // It is due to check the certificate.
  1847. // Do cert validity checking.
  1848. //
  1849. LONG IsCertBeingValidated;
  1850. IsCertBeingValidated = InterlockedExchange(&UserCertIsValidating, 1);
  1851. if (IsCertBeingValidated != 1) {
  1852. if ( CertVerifyTimeValidity(
  1853. NULL,
  1854. pEfsUserInfo->pUserCache->pCertContext->pCertInfo
  1855. )){
  1856. rc = ERROR_NO_USER_KEYS;
  1857. pEfsUserInfo->pUserCache->CertValidated = CERT_NOT_VALIDATED;
  1858. EfspReleaseUserCache(pEfsUserInfo->pUserCache);
  1859. pEfsUserInfo->pUserCache = NULL;
  1860. } else {
  1861. //
  1862. // Test the cert usage here.
  1863. // CERT_E_WRONG_USAGE
  1864. //
  1865. BOOL OidFound;
  1866. rc = EfsFindCertOid(
  1867. szOID_KP_EFS,
  1868. pEfsUserInfo->pUserCache->pCertContext,
  1869. &OidFound
  1870. );
  1871. if (ERROR_SUCCESS == rc) {
  1872. if (OidFound) {
  1873. //
  1874. // Reset the time stamp.
  1875. // Do I need the sync object to protect this?
  1876. // Mixing the high word and low word is not a big problem here.
  1877. //
  1878. pEfsUserInfo->pUserCache->TimeStamp = TimeStamp;
  1879. }
  1880. } else {
  1881. rc = ERROR_NO_USER_KEYS;
  1882. pEfsUserInfo->pUserCache->CertValidated = CERT_NOT_VALIDATED;
  1883. EfspReleaseUserCache(pEfsUserInfo->pUserCache);
  1884. pEfsUserInfo->pUserCache = NULL;
  1885. }
  1886. }
  1887. if (IsCertBeingValidated != 1) {
  1888. InterlockedExchange(&UserCertIsValidating, IsCertBeingValidated);
  1889. }
  1890. }
  1891. }
  1892. }
  1893. if (rc == ERROR_NO_USER_KEYS) {
  1894. //
  1895. // That didn't work. Look for a cert in the
  1896. // user's MY store and use it.
  1897. //
  1898. rc = SearchMyStoreForEFSCert(
  1899. pEfsUserInfo,
  1900. hKey,
  1901. hProv,
  1902. ContainerName,
  1903. ProviderName,
  1904. DisplayInfo,
  1905. pbHash,
  1906. cbHash
  1907. );
  1908. if (rc == ERROR_NO_USER_KEYS) {
  1909. //
  1910. // That didn't work. Last resort:
  1911. // generate a new keyset for the user.
  1912. //
  1913. rc = GenerateUserKey(
  1914. pEfsUserInfo,
  1915. hKey,
  1916. hProv,
  1917. ContainerName,
  1918. ProviderName,
  1919. ProviderType,
  1920. DisplayInfo,
  1921. pbHash,
  1922. cbHash
  1923. );
  1924. if (rc == ERROR_RETRY) {
  1925. //
  1926. // There was another thread creating keys.
  1927. // Try one more time to get them.
  1928. // If this fails, fail the entire attempt.
  1929. //
  1930. rc = GetInfoFromCertHash(
  1931. pEfsUserInfo,
  1932. hKey,
  1933. hProv,
  1934. ContainerName,
  1935. ProviderName,
  1936. DisplayInfo,
  1937. pbHash,
  1938. cbHash
  1939. );
  1940. }
  1941. }
  1942. }
  1943. return( rc );
  1944. }
  1945. NTSTATUS
  1946. EfspGetUserName(
  1947. IN OUT PEFS_USER_INFO pEfsUserInfo
  1948. )
  1949. /*++
  1950. Routine Description:
  1951. This routine is the LSA Server worker routine for the LsaGetUserName
  1952. API.
  1953. WARNING: This routine allocates memory for its output. The caller is
  1954. responsible for freeing this memory after use. See description of the
  1955. Names parameter.
  1956. Arguments:
  1957. UserName - Receives name of the current user.
  1958. DomainName - Optionally receives domain name of the current user.
  1959. Return Values:
  1960. NTSTATUS - Standard Nt Result Code
  1961. STATUS_SUCCESS - The call completed successfully and all Sids have
  1962. been translated to names.
  1963. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources
  1964. such as memory to complete the call.
  1965. --*/
  1966. {
  1967. PUNICODE_STRING AccountName = NULL;
  1968. PUNICODE_STRING AuthorityName = NULL;
  1969. PUNICODE_STRING ProfilePath = NULL;
  1970. PLSAP_LOGON_SESSION LogonSession;
  1971. NTSTATUS Status;
  1972. //
  1973. // Let's see if we're trying to look up the currently logged on
  1974. // user.
  1975. //
  1976. //
  1977. // TokenUserInformation from this call must be freed by calling
  1978. // LsapFreeLsaHeap().
  1979. //
  1980. Status = EfspGetTokenUser( pEfsUserInfo );
  1981. if ( NT_SUCCESS( Status ) ) {
  1982. pEfsUserInfo->lpUserSid = ConvertSidToWideCharString( pEfsUserInfo->pTokenUser->User.Sid );
  1983. if (pEfsUserInfo->lpUserSid) {
  1984. //
  1985. // If the user ID is Anonymous then there is no name and domain in the
  1986. // logon session
  1987. //
  1988. if (RtlEqualSid(
  1989. pEfsUserInfo->pTokenUser->User.Sid,
  1990. LsapAnonymousSid
  1991. )) {
  1992. DebugLog((DEB_WARN, "Current user is Anonymous\n" ));
  1993. AccountName = &WellKnownSids[LsapAnonymousSidIndex].Name;
  1994. AuthorityName = &WellKnownSids[LsapAnonymousSidIndex].DomainName;
  1995. ProfilePath = NULL;
  1996. } else {
  1997. LogonSession = LsapLocateLogonSession ( &(pEfsUserInfo->AuthId) );
  1998. //
  1999. // During setup, we may get NULL returned for the logon session.
  2000. //
  2001. if (LogonSession != NULL) {
  2002. //
  2003. // Got a match. Get the username and domain information
  2004. // from the LogonId
  2005. //
  2006. AccountName = &LogonSession->AccountName;
  2007. AuthorityName = &LogonSession->AuthorityName;
  2008. ProfilePath = &LogonSession->ProfilePath;
  2009. LsapReleaseLogonSession( LogonSession );
  2010. } else {
  2011. Status = STATUS_NO_SUCH_LOGON_SESSION;
  2012. }
  2013. }
  2014. if (Status == STATUS_SUCCESS) {
  2015. pEfsUserInfo->lpUserName = (PWSTR)LsapAllocateLsaHeap(AccountName->Length + sizeof(UNICODE_NULL));
  2016. if (pEfsUserInfo->lpUserName != NULL) {
  2017. memcpy( pEfsUserInfo->lpUserName, AccountName->Buffer, AccountName->Length );
  2018. (pEfsUserInfo->lpUserName)[AccountName->Length/sizeof(WCHAR)] = UNICODE_NULL;
  2019. pEfsUserInfo->lpDomainName = (PWSTR)LsapAllocateLsaHeap(AuthorityName->Length + sizeof(UNICODE_NULL));
  2020. if (pEfsUserInfo->lpDomainName != NULL) {
  2021. memcpy( pEfsUserInfo->lpDomainName, AuthorityName->Buffer, AuthorityName->Length );
  2022. (pEfsUserInfo->lpDomainName)[AuthorityName->Length/sizeof(WCHAR)] = UNICODE_NULL;
  2023. } else {
  2024. Status = STATUS_INSUFFICIENT_RESOURCES;
  2025. }
  2026. if ((ProfilePath != NULL) && (ProfilePath->Length != 0)) {
  2027. pEfsUserInfo->lpProfilePath = (PWSTR)LsapAllocateLsaHeap(ProfilePath->Length + sizeof(UNICODE_NULL));
  2028. if (pEfsUserInfo->lpProfilePath != NULL) {
  2029. memcpy( pEfsUserInfo->lpProfilePath, ProfilePath->Buffer, ProfilePath->Length );
  2030. (pEfsUserInfo->lpProfilePath)[ProfilePath->Length/sizeof(WCHAR)] = UNICODE_NULL;
  2031. } else {
  2032. Status = STATUS_INSUFFICIENT_RESOURCES;
  2033. }
  2034. }
  2035. pEfsUserInfo->lpKeyPath = ConstructKeyPath(pEfsUserInfo->lpUserSid);
  2036. if ( pEfsUserInfo->lpKeyPath == NULL ) {
  2037. Status = STATUS_INSUFFICIENT_RESOURCES;
  2038. }
  2039. } else {
  2040. Status = STATUS_INSUFFICIENT_RESOURCES;
  2041. }
  2042. }
  2043. } else {
  2044. Status = STATUS_INSUFFICIENT_RESOURCES;
  2045. }
  2046. }
  2047. if (!NT_SUCCESS( Status )) {
  2048. //
  2049. // Something failed, clean up what we were going to return
  2050. //
  2051. EfspFreeUserInfo( pEfsUserInfo );
  2052. memset( pEfsUserInfo, 0, sizeof( EFS_USER_INFO ));
  2053. }
  2054. return(Status);
  2055. }
  2056. DWORD
  2057. EfspReplaceUserKeyInformation(
  2058. PEFS_USER_INFO pEfsUserInfo
  2059. )
  2060. /*++
  2061. Routine Description:
  2062. Forces the regeneration of the user's EFS key.
  2063. Arguments:
  2064. None.
  2065. Return Value:
  2066. Win32 error or ERROR_SUCCESS
  2067. --*/
  2068. {
  2069. LPWSTR ProviderName;
  2070. LPWSTR ContainerName;
  2071. LPWSTR DisplayInfo;
  2072. DWORD ProviderType;
  2073. DWORD cbHash;
  2074. PBYTE pbHash;
  2075. DWORD rc;
  2076. if (pEfsUserInfo->pUserCache) {
  2077. //
  2078. // We are going to create a new key. The current cache is going away.
  2079. // We will insert a new cache node in the header.
  2080. //
  2081. EfspReleaseUserCache(pEfsUserInfo->pUserCache);
  2082. pEfsUserInfo->pUserCache = NULL;
  2083. }
  2084. rc = RegDeleteKey(
  2085. KEYPATHROOT,
  2086. pEfsUserInfo->lpKeyPath
  2087. );
  2088. if (rc == ERROR_SUCCESS) {
  2089. rc = GenerateUserKey(
  2090. pEfsUserInfo,
  2091. NULL,
  2092. NULL,
  2093. &ContainerName,
  2094. &ProviderName,
  2095. &ProviderType,
  2096. &DisplayInfo,
  2097. &pbHash,
  2098. &cbHash
  2099. );
  2100. if (rc == ERROR_SUCCESS) {
  2101. if (ContainerName) {
  2102. LsapFreeLsaHeap( ContainerName );
  2103. }
  2104. if (ProviderName) {
  2105. LsapFreeLsaHeap( ProviderName );
  2106. }
  2107. if (DisplayInfo) {
  2108. LsapFreeLsaHeap( DisplayInfo );
  2109. }
  2110. if (pbHash) {
  2111. LsapFreeLsaHeap( pbHash );
  2112. }
  2113. }
  2114. }
  2115. return( rc );
  2116. }
  2117. DWORD
  2118. EfspInstallCertAsUserKey(
  2119. PEFS_USER_INFO pEfsUserInfo,
  2120. PENCRYPTION_CERTIFICATE pEncryptionCertificate
  2121. )
  2122. {
  2123. //
  2124. // Find the passed certificate in the user's MY store.
  2125. // If it's not there, we don't use the cert.
  2126. //
  2127. DWORD rc = ERROR_SUCCESS;
  2128. PCCERT_CONTEXT pCertContext;
  2129. DWORD cbHash = 0;
  2130. PBYTE pbHash;
  2131. BOOLEAN bIsValid;
  2132. //
  2133. // If this fails, there's no cert that matches.
  2134. //
  2135. pCertContext = CertCreateCertificateContext(
  2136. pEncryptionCertificate->pCertBlob->dwCertEncodingType,
  2137. pEncryptionCertificate->pCertBlob->pbData,
  2138. pEncryptionCertificate->pCertBlob->cbData
  2139. );
  2140. if (pCertContext) {
  2141. if (CertGetCertificateContextProperty(
  2142. pCertContext,
  2143. CERT_SHA1_HASH_PROP_ID,
  2144. NULL,
  2145. &cbHash
  2146. )) {
  2147. pbHash = (PBYTE)LsapAllocateLsaHeap( cbHash );
  2148. if (pbHash) {
  2149. if (CertGetCertificateContextProperty(
  2150. pCertContext,
  2151. CERT_SHA1_HASH_PROP_ID,
  2152. pbHash,
  2153. &cbHash
  2154. )) {
  2155. HCRYPTKEY hKey;
  2156. HCRYPTPROV hProv;
  2157. LPWSTR ContainerName;
  2158. LPWSTR ProviderName;
  2159. LPWSTR DisplayInfo;
  2160. if (pEfsUserInfo->pUserCache) {
  2161. //
  2162. // We are going to create a new key. The current cache is going away.
  2163. // We will insert a new cache node in the header.
  2164. //
  2165. EfspReleaseUserCache(pEfsUserInfo->pUserCache);
  2166. pEfsUserInfo->pUserCache = NULL;
  2167. }
  2168. rc = GetKeyInfoFromCertHash(
  2169. pEfsUserInfo,
  2170. pbHash,
  2171. cbHash,
  2172. &hKey,
  2173. &hProv,
  2174. &ContainerName,
  2175. &ProviderName,
  2176. &DisplayInfo,
  2177. &bIsValid
  2178. );
  2179. if (ERROR_SUCCESS == rc) {
  2180. //
  2181. // We don't care about any of the stuff that came back,
  2182. // all we care about is that it was all found, meaning
  2183. // that the key exists and can be used. Now that we know
  2184. // that, we can jam the hash into the registry.
  2185. //
  2186. HKEY KeyHandle;
  2187. DWORD Disposition;
  2188. rc = RegCreateKeyEx(
  2189. KEYPATHROOT,
  2190. pEfsUserInfo->lpKeyPath,
  2191. 0,
  2192. TEXT("REG_SZ"),
  2193. REG_OPTION_NON_VOLATILE,
  2194. KEY_READ | KEY_WRITE,
  2195. NULL,
  2196. &KeyHandle,
  2197. &Disposition // address of disposition value buffer
  2198. );
  2199. if (ERROR_SUCCESS == rc) {
  2200. rc = RegSetValueEx(
  2201. KeyHandle, // handle of key to set value for
  2202. CERT_HASH,
  2203. 0,
  2204. REG_BINARY,
  2205. pbHash,
  2206. cbHash
  2207. );
  2208. RegCloseKey( KeyHandle );
  2209. }
  2210. if (hKey) {
  2211. //
  2212. // hKey not NULL means we have not put the data in the cache.
  2213. //
  2214. CryptDestroyKey( hKey );
  2215. CryptReleaseContext( hProv, 0 );
  2216. LsapFreeLsaHeap( ContainerName );
  2217. LsapFreeLsaHeap( ProviderName );
  2218. LsapFreeLsaHeap( DisplayInfo );
  2219. }
  2220. }
  2221. } else {
  2222. rc = GetLastError();
  2223. }
  2224. LsapFreeLsaHeap( pbHash );
  2225. } else {
  2226. rc = ERROR_NOT_ENOUGH_MEMORY;
  2227. }
  2228. } else {
  2229. rc = GetLastError();
  2230. }
  2231. CertFreeCertificateContext( pCertContext );
  2232. } else {
  2233. rc = GetLastError();
  2234. }
  2235. return( rc );
  2236. }
  2237. BOOLEAN
  2238. CurrentHashOK(
  2239. IN PEFS_USER_INFO pEfsUserInfo,
  2240. IN PBYTE pbHash,
  2241. IN DWORD cbHash,
  2242. OUT DWORD *dFlag
  2243. )
  2244. /*++
  2245. Routine Description:
  2246. See if the value pbHash is already in the user's key. If not, try to see if we can add it back.
  2247. Arguments:
  2248. pEfsUserInfo -- User Info
  2249. pbHash -- Hash value
  2250. cbHash -- Hash length
  2251. dFlag -- Cert Flag to indicate if the cert has been added to the LM intermediate store
  2252. Return Value:
  2253. TRUE if the pbHash found or added successfully
  2254. --*/
  2255. {
  2256. DWORD rc;
  2257. BOOLEAN b = FALSE;
  2258. HKEY hRegKey = NULL;
  2259. PBYTE pbLocalHash;
  2260. DWORD cbLocalHash;
  2261. rc = RegOpenKeyEx(
  2262. KEYPATHROOT,
  2263. pEfsUserInfo->lpKeyPath,
  2264. 0,
  2265. GENERIC_READ,
  2266. &hRegKey
  2267. );
  2268. *dFlag = 0;
  2269. if (rc == ERROR_SUCCESS) {
  2270. //
  2271. // If there's a certificate thumbprint there, get it and use it.
  2272. //
  2273. DWORD Type;
  2274. rc = RegQueryValueEx(
  2275. hRegKey,
  2276. CERT_HASH,
  2277. NULL,
  2278. &Type,
  2279. NULL,
  2280. &cbLocalHash
  2281. );
  2282. if (rc == ERROR_SUCCESS) {
  2283. if (cbLocalHash == cbHash) {
  2284. //
  2285. // Query out the thumbprint, find the cert, and return the key information.
  2286. //
  2287. if (pbLocalHash = (PBYTE)LsapAllocateLsaHeap( cbLocalHash )) {
  2288. rc = RegQueryValueEx(
  2289. hRegKey,
  2290. CERT_HASH,
  2291. NULL,
  2292. &Type,
  2293. pbLocalHash,
  2294. &cbLocalHash
  2295. );
  2296. if (rc == ERROR_SUCCESS) {
  2297. //
  2298. // Check if the hash value matches
  2299. //
  2300. if (RtlEqualMemory( pbLocalHash, pbHash, cbHash)){
  2301. b = TRUE;
  2302. cbLocalHash = sizeof (DWORD);
  2303. if (RegQueryValueEx(
  2304. hRegKey,
  2305. CERT_FLAG,
  2306. NULL,
  2307. &Type,
  2308. (LPBYTE) dFlag,
  2309. &cbLocalHash
  2310. )){
  2311. //
  2312. // Make sure dFlag set to 0 if error occurs. This may not be needed.
  2313. //
  2314. *dFlag = 0;
  2315. }
  2316. }
  2317. }
  2318. LsapFreeLsaHeap(pbLocalHash);
  2319. }
  2320. }
  2321. }
  2322. RegCloseKey( hRegKey );
  2323. }
  2324. if (rc != ERROR_SUCCESS) {
  2325. //
  2326. // Let's see if we can create one
  2327. //
  2328. DWORD Disposition = 0;
  2329. //
  2330. // Assume that there's no current EFS information
  2331. // for this guy. Create the registry key.
  2332. //
  2333. rc = RegCreateKeyEx(
  2334. KEYPATHROOT,
  2335. pEfsUserInfo->lpKeyPath,
  2336. 0,
  2337. TEXT("REG_SZ"),
  2338. REG_OPTION_NON_VOLATILE,
  2339. KEY_ALL_ACCESS,
  2340. NULL,
  2341. &hRegKey,
  2342. &Disposition // address of disposition value buffer
  2343. );
  2344. if (rc == ERROR_SUCCESS) {
  2345. rc = RegSetValueEx(
  2346. hRegKey, // handle of key to set value for
  2347. CERT_HASH,
  2348. 0,
  2349. REG_BINARY,
  2350. pbHash,
  2351. cbHash
  2352. );
  2353. if (rc == ERROR_SUCCESS) {
  2354. b = TRUE;
  2355. }
  2356. RegCloseKey( hRegKey );
  2357. }
  2358. }
  2359. return b;
  2360. }
  2361. DWORD
  2362. GetCurrentHash(
  2363. IN PEFS_USER_INFO pEfsUserInfo,
  2364. OUT PBYTE *pbHash,
  2365. OUT DWORD *cbHash
  2366. )
  2367. {
  2368. HKEY hRegKey = NULL;
  2369. DWORD rc;
  2370. ASSERT(pbHash);
  2371. ASSERT(cbHash);
  2372. *pbHash = NULL;
  2373. rc = RegOpenKeyEx(
  2374. KEYPATHROOT,
  2375. pEfsUserInfo->lpKeyPath,
  2376. 0,
  2377. GENERIC_READ,
  2378. &hRegKey
  2379. );
  2380. if (rc == ERROR_SUCCESS) {
  2381. DWORD Type;
  2382. rc = RegQueryValueEx(
  2383. hRegKey,
  2384. CERT_HASH,
  2385. NULL,
  2386. &Type,
  2387. NULL,
  2388. cbHash
  2389. );
  2390. if (rc == ERROR_SUCCESS) {
  2391. if (*pbHash = (PBYTE)LsapAllocateLsaHeap( *cbHash )) {
  2392. rc = RegQueryValueEx(
  2393. hRegKey,
  2394. CERT_HASH,
  2395. NULL,
  2396. &Type,
  2397. *pbHash,
  2398. cbHash
  2399. );
  2400. if (rc != ERROR_SUCCESS) {
  2401. LsapFreeLsaHeap(*pbHash);
  2402. *pbHash = NULL;
  2403. }
  2404. } else {
  2405. rc = GetLastError();
  2406. }
  2407. }
  2408. RegCloseKey( hRegKey );
  2409. }
  2410. return rc;
  2411. }
  2412. BOOLEAN
  2413. EfspInitUserCacheNode(
  2414. IN OUT PUSER_CACHE pCacheNode,
  2415. IN PBYTE pbHash,
  2416. IN DWORD cbHash,
  2417. IN LPWSTR ContainerName,
  2418. IN LPWSTR ProviderName,
  2419. IN LPWSTR DisplayInformation,
  2420. IN PCCERT_CONTEXT pCertContext,
  2421. IN HCRYPTKEY hKey,
  2422. IN HCRYPTPROV hProv,
  2423. IN LUID *AuthId,
  2424. IN LONG CertValidated
  2425. )
  2426. /*++
  2427. Routine Description:
  2428. Initialize the cache node and insert it into the list.
  2429. Arguments:
  2430. pCacheNode -- Node to be inserted
  2431. pbHash -- User Cert Hash
  2432. cbHash -- Length of the hash data
  2433. ContainerName -- Container name
  2434. ProviderName -- Provider name
  2435. DisplayInformation -- Display information
  2436. pCertContext -- Cert Context
  2437. hKey -- User Key
  2438. hProv -- Provider handle
  2439. AuthId -- Authentication ID
  2440. CertValidated -- Cert validation info
  2441. Return Value:
  2442. TRUE if successful
  2443. --*/
  2444. {
  2445. if (!pCacheNode) {
  2446. return FALSE;
  2447. }
  2448. pCacheNode->pbHash = pbHash;
  2449. pCacheNode->cbHash = cbHash;
  2450. pCacheNode->ContainerName = ContainerName;
  2451. pCacheNode->ProviderName = ProviderName;
  2452. pCacheNode->DisplayInformation = DisplayInformation;
  2453. pCacheNode->pCertContext = pCertContext;
  2454. pCacheNode->hUserKey = hKey;
  2455. pCacheNode->hProv = hProv;
  2456. pCacheNode->CertValidated = CertValidated;
  2457. pCacheNode->UseRefCount = 1; // The caller's hold on this node
  2458. pCacheNode->StopUseCount = 0;
  2459. pCacheNode->AuthId = *AuthId;
  2460. return (EfspAddUserCache(pCacheNode));
  2461. }
  2462. BOOL
  2463. EfsGetBasicConstraintExt(
  2464. IN OUT PCERT_EXTENSION *basicRestraint
  2465. )
  2466. {
  2467. BOOL bRet = TRUE;
  2468. CERT_BASIC_CONSTRAINTS2_INFO CertConstraints2;
  2469. DWORD rc = ERROR_SUCCESS;
  2470. RtlZeroMemory( &CertConstraints2, sizeof(CERT_BASIC_CONSTRAINTS2_INFO) );
  2471. *basicRestraint = (PCERT_EXTENSION) LsapAllocateLsaHeap(sizeof(CERT_EXTENSION));
  2472. if (*basicRestraint) {
  2473. bRet = CryptEncodeObject(
  2474. X509_ASN_ENCODING,
  2475. X509_BASIC_CONSTRAINTS2,
  2476. &CertConstraints2,
  2477. NULL,
  2478. &((*basicRestraint)->Value.cbData)
  2479. );
  2480. if (bRet) {
  2481. (*basicRestraint)->Value.pbData = (PBYTE) LsapAllocateLsaHeap( (*basicRestraint)->Value.cbData );
  2482. if ((*basicRestraint)->Value.pbData) {
  2483. bRet = CryptEncodeObject(
  2484. X509_ASN_ENCODING,
  2485. X509_BASIC_CONSTRAINTS2,
  2486. &CertConstraints2,
  2487. (*basicRestraint)->Value.pbData,
  2488. &((*basicRestraint)->Value.cbData)
  2489. );
  2490. if (bRet) {
  2491. (*basicRestraint)->pszObjId = szOID_BASIC_CONSTRAINTS2;
  2492. (*basicRestraint)->fCritical = FALSE;
  2493. } else {
  2494. rc = GetLastError();
  2495. LsapFreeLsaHeap((*basicRestraint)->Value.pbData);
  2496. SetLastError(rc);
  2497. }
  2498. } else {
  2499. bRet = FALSE;
  2500. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2501. }
  2502. }
  2503. if (!bRet) {
  2504. rc = GetLastError();
  2505. LsapFreeLsaHeap(*basicRestraint);
  2506. SetLastError(rc);
  2507. *basicRestraint = NULL;
  2508. }
  2509. } else {
  2510. bRet = FALSE;
  2511. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2512. }
  2513. return bRet;
  2514. }
  2515. BOOL
  2516. EfsGetAltNameExt(
  2517. IN OUT PCERT_EXTENSION *altNameExt,
  2518. IN LPWSTR UPNName
  2519. )
  2520. {
  2521. BOOL bRet = TRUE;
  2522. DWORD cbData = 0;
  2523. DWORD rc = ERROR_SUCCESS;
  2524. CERT_NAME_VALUE prnName;
  2525. CERT_OTHER_NAME certOtherName;
  2526. CERT_ALT_NAME_ENTRY altName;
  2527. CERT_ALT_NAME_INFO nameInfo;
  2528. *altNameExt = (PCERT_EXTENSION) LsapAllocateLsaHeap(sizeof(CERT_EXTENSION));
  2529. if (*altNameExt) {
  2530. prnName.dwValueType = CERT_RDN_UTF8_STRING;
  2531. prnName.Value.cbData = (wcslen(UPNName) + 1) * sizeof(WCHAR);
  2532. prnName.Value.pbData = (BYTE *)UPNName;
  2533. bRet = CryptEncodeObject(
  2534. X509_ASN_ENCODING,
  2535. X509_UNICODE_ANY_STRING,
  2536. &prnName,
  2537. NULL,
  2538. &certOtherName.Value.cbData
  2539. );
  2540. if (bRet) {
  2541. certOtherName.Value.pbData = (PBYTE)LsapAllocateLsaHeap( certOtherName.Value.cbData );
  2542. if (certOtherName.Value.pbData) {
  2543. bRet = CryptEncodeObject(
  2544. X509_ASN_ENCODING,
  2545. X509_UNICODE_ANY_STRING,
  2546. &prnName,
  2547. certOtherName.Value.pbData,
  2548. &certOtherName.Value.cbData
  2549. );
  2550. if (bRet) {
  2551. altName.dwAltNameChoice = CERT_ALT_NAME_OTHER_NAME;
  2552. certOtherName.pszObjId = szOID_NT_PRINCIPAL_NAME;
  2553. altName.pOtherName = &certOtherName;
  2554. nameInfo.cAltEntry = 1;
  2555. nameInfo.rgAltEntry = &altName;
  2556. bRet = CryptEncodeObject(
  2557. X509_ASN_ENCODING,
  2558. szOID_SUBJECT_ALT_NAME,
  2559. &nameInfo,
  2560. NULL,
  2561. &((*altNameExt)->Value.cbData)
  2562. );
  2563. if (bRet) {
  2564. (*altNameExt)->Value.pbData = (PBYTE) LsapAllocateLsaHeap( (*altNameExt)->Value.cbData );
  2565. if ((*altNameExt)->Value.pbData) {
  2566. bRet = CryptEncodeObject(
  2567. X509_ASN_ENCODING,
  2568. szOID_SUBJECT_ALT_NAME,
  2569. &nameInfo,
  2570. (*altNameExt)->Value.pbData,
  2571. &((*altNameExt)->Value.cbData)
  2572. );
  2573. if (bRet) {
  2574. (*altNameExt)->pszObjId = szOID_SUBJECT_ALT_NAME2;
  2575. (*altNameExt)->fCritical = FALSE;
  2576. } else {
  2577. DWORD rc = GetLastError();
  2578. LsapFreeLsaHeap((*altNameExt)->Value.pbData);
  2579. SetLastError(rc);
  2580. }
  2581. } else {
  2582. bRet = FALSE;
  2583. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2584. }
  2585. }
  2586. }
  2587. rc = GetLastError();
  2588. LsapFreeLsaHeap(certOtherName.Value.pbData);
  2589. SetLastError(rc);
  2590. } else {
  2591. bRet = FALSE;
  2592. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2593. }
  2594. }
  2595. if (!bRet) {
  2596. GetLastError();
  2597. LsapFreeLsaHeap(*altNameExt);
  2598. SetLastError(rc);
  2599. *altNameExt = NULL;
  2600. }
  2601. } else {
  2602. bRet = FALSE;
  2603. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2604. }
  2605. return bRet;
  2606. }
  2607. VOID
  2608. EfsMarkCertAddedToStore(
  2609. IN PEFS_USER_INFO pEfsUserInfo
  2610. )
  2611. /*++
  2612. Routine Description:
  2613. Mark in the registry that we have add the cert to the LM store.
  2614. Arguments:
  2615. pEfsUserInfo -- User Info
  2616. Return Value:
  2617. None.
  2618. --*/
  2619. {
  2620. HKEY hRegKey = NULL;
  2621. DWORD rc;
  2622. rc = RegOpenKeyEx(
  2623. KEYPATHROOT,
  2624. pEfsUserInfo->lpKeyPath,
  2625. 0,
  2626. GENERIC_READ | GENERIC_WRITE,
  2627. &hRegKey
  2628. );
  2629. if (rc == ERROR_SUCCESS) {
  2630. rc = CERTINLMTRUSTEDSTORE;
  2631. RegSetValueEx(
  2632. hRegKey, // handle of key to set value for
  2633. CERT_FLAG,
  2634. 0,
  2635. REG_DWORD,
  2636. (LPBYTE)&rc,
  2637. sizeof (DWORD)
  2638. );
  2639. RegCloseKey( hRegKey );
  2640. }
  2641. return;
  2642. }