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.

1159 lines
30 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. efscert.cxx
  5. Abstract:
  6. EFS Certificate management code
  7. Author:
  8. Robert Reichel (RobertRe) July 4, 1997
  9. Robert Gu (RobertG) Dec. 4, 1997
  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 <stdio.h>
  21. #include <wincrypt.h>
  22. #include <efsstruc.h>
  23. #include "lsasrvp.h"
  24. #include "debug.h"
  25. #include "efssrv.hxx"
  26. #include "userkey.h"
  27. }
  28. /////////////////////////////////////////////////////////////////////////////////////
  29. // /
  30. // /
  31. // Helper Functions /
  32. // /
  33. // /
  34. /////////////////////////////////////////////////////////////////////////////////////
  35. PCCERT_CONTEXT
  36. GetCertContextFromCertHash(
  37. IN PBYTE pbHash,
  38. IN DWORD cbHash,
  39. IN DWORD dwFlags
  40. )
  41. /*++
  42. Routine Description:
  43. Finds the cert with the passed cert hash in the user's MY store
  44. and returns a context pointer.
  45. Arguments:
  46. pbHash - Supplies a pointer to the hash to be matched.
  47. cbHash - Supplies the length in bytes of the passed hash.
  48. dwFlags - Supplies flags to CertOpenStore
  49. Return Value:
  50. Returns a pointer to a certificate context, or NULL.
  51. The returned context must be freed via CertFreeCertificateContext()
  52. --*/
  53. {
  54. CRYPT_HASH_BLOB hashBlob;
  55. PCCERT_CONTEXT pCertContext = NULL;
  56. //HCERTSTORE hStore = CertOpenSystemStoreW( NULL, L"MY");
  57. HCERTSTORE hStore = CertOpenStore(
  58. CERT_STORE_PROV_SYSTEM_REGISTRY_W,
  59. 0, // dwEncodingType
  60. 0, // hCryptProv,
  61. dwFlags,
  62. L"My"
  63. );
  64. if (hStore != NULL) {
  65. //
  66. // Find our cert via the hash
  67. //
  68. hashBlob.cbData = cbHash;
  69. hashBlob.pbData = pbHash;
  70. pCertContext = CertFindCertificateInStore( hStore,
  71. CRYPT_ASN_ENCODING,
  72. 0,
  73. CERT_FIND_HASH,
  74. &hashBlob,
  75. NULL
  76. );
  77. CertCloseStore( hStore, 0 );
  78. }
  79. return( pCertContext );
  80. }
  81. LPWSTR
  82. EfspGetCertDisplayInformation(
  83. IN PCCERT_CONTEXT pCertContext
  84. )
  85. /*++
  86. Routine Description:
  87. Returns the display string from the passed certificate context.
  88. Arguments:
  89. pCertContext - Supplies a pointer to an open certificate context.
  90. Return Value:
  91. On success, pointer to display string. Caller must call
  92. LsapFreeLsaHeap() to free.
  93. NULL on failure.
  94. --*/
  95. {
  96. DWORD rc;
  97. LPWSTR UserDispName = NULL;
  98. rc = EfsGetCertNameFromCertContext(
  99. pCertContext,
  100. &UserDispName
  101. );
  102. if (rc == ERROR_SUCCESS) {
  103. return UserDispName;
  104. } else {
  105. SetLastError(rc);
  106. return NULL;
  107. }
  108. }
  109. PBYTE
  110. GetCertHashFromCertContext(
  111. IN PCCERT_CONTEXT pCertContext,
  112. OUT PDWORD pcbHash
  113. )
  114. /*++
  115. Routine Description:
  116. Helper routine, takes a cert context and extracts the hash.
  117. Arguments:
  118. pCertContext - Supplies the cert context.
  119. pcbHash - Returns the length in bytes of the returned hash.
  120. Return Value:
  121. Returns a pointer to a hash block allocated out of heap memory,
  122. or NULL if either the attempt to get the hash failed or the attempt
  123. to allocate memory failed.
  124. Call GetLastError() for more details in case of failure.
  125. --*/
  126. {
  127. PBYTE pbHash = NULL;
  128. *pcbHash = 0;
  129. if (CertGetCertificateContextProperty(
  130. pCertContext,
  131. CERT_HASH_PROP_ID,
  132. NULL,
  133. pcbHash
  134. )) {
  135. pbHash = (PBYTE)LsapAllocateLsaHeap( *pcbHash );
  136. if (pbHash != NULL) {
  137. if (!CertGetCertificateContextProperty(
  138. pCertContext,
  139. CERT_HASH_PROP_ID,
  140. pbHash,
  141. pcbHash
  142. )) {
  143. LsapFreeLsaHeap( pbHash );
  144. pbHash = NULL;
  145. *pcbHash = 0;
  146. }
  147. } else {
  148. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  149. }
  150. }
  151. return( pbHash );
  152. }
  153. PCERT_PUBLIC_KEY_INFO
  154. ExportPublicKeyInfo(
  155. IN HCRYPTPROV hProv,
  156. IN DWORD dwKeySpec,
  157. IN DWORD dwCertEncodingType,
  158. IN OUT DWORD *pcbInfo
  159. )
  160. {
  161. PCERT_PUBLIC_KEY_INFO pPubKeyInfo = NULL;
  162. if ( CryptExportPublicKeyInfo(
  163. hProv,
  164. dwKeySpec,
  165. dwCertEncodingType,
  166. NULL,
  167. pcbInfo)) {
  168. pPubKeyInfo = (PCERT_PUBLIC_KEY_INFO) LsapAllocateLsaHeap(*pcbInfo);
  169. if (pPubKeyInfo) {
  170. if (!CryptExportPublicKeyInfo( hProv,
  171. dwKeySpec,
  172. dwCertEncodingType,
  173. pPubKeyInfo,
  174. pcbInfo)) {
  175. LsapFreeLsaHeap( pPubKeyInfo );
  176. pPubKeyInfo = NULL;
  177. *pcbInfo = 0;
  178. }
  179. }
  180. }
  181. return ( pPubKeyInfo );
  182. }
  183. BOOL
  184. EncodeAndAlloc(
  185. DWORD dwEncodingType,
  186. LPCSTR lpszStructType,
  187. const void * pvStructInfo,
  188. PBYTE * pbEncoded,
  189. PDWORD pcbEncoded
  190. )
  191. {
  192. BOOL b = FALSE;
  193. if (CryptEncodeObject(
  194. dwEncodingType,
  195. lpszStructType,
  196. pvStructInfo,
  197. NULL,
  198. pcbEncoded )) {
  199. *pbEncoded = (PBYTE)LsapAllocateLsaHeap( *pcbEncoded );
  200. if (*pbEncoded) {
  201. if (CryptEncodeObject(
  202. dwEncodingType,
  203. lpszStructType,
  204. pvStructInfo,
  205. *pbEncoded,
  206. pcbEncoded )) {
  207. b = TRUE;
  208. } else {
  209. LsapFreeLsaHeap( *pbEncoded );
  210. *pbEncoded = NULL;
  211. }
  212. } else {
  213. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  214. }
  215. }
  216. return( b );
  217. }
  218. DWORD
  219. EfsMakeCertNames(
  220. IN PEFS_USER_INFO pEfsUserInfo,
  221. OUT LPWSTR *DispInfo,
  222. OUT LPWSTR *SubjectName,
  223. OUT LPWSTR *UPNName
  224. )
  225. {
  226. DWORD rc = ERROR_SUCCESS;
  227. *DispInfo = NULL;
  228. *UPNName = NULL;
  229. if (pEfsUserInfo->bDomainAccount) {
  230. //
  231. // Domain Account
  232. //
  233. HRESULT hr;
  234. HANDLE hDS = NULL;
  235. DS_NAME_RESULT* UserName = NULL;
  236. hr = DsBind(NULL, NULL, &hDS);
  237. if (hr == NO_ERROR) {
  238. rc = DsCrackNames(
  239. hDS,
  240. DS_NAME_NO_FLAGS,
  241. DS_SID_OR_SID_HISTORY_NAME,
  242. DS_USER_PRINCIPAL_NAME,
  243. 1,
  244. &(pEfsUserInfo->lpUserSid),
  245. &UserName
  246. );
  247. if (ERROR_SUCCESS == rc) {
  248. if (UserName->rItems[0].status == DS_NAME_NO_ERROR) {
  249. *UPNName = (LPWSTR) LsapAllocateLsaHeap((wcslen(UserName->rItems[0].pName) + 1) * sizeof (WCHAR));
  250. *DispInfo = (LPWSTR) LsapAllocateLsaHeap(
  251. (wcslen(UserName->rItems[0].pName) +
  252. wcslen(pEfsUserInfo->lpUserName) +
  253. 3) * sizeof (WCHAR));
  254. *SubjectName = (LPWSTR) LsapAllocateLsaHeap((wcslen(pEfsUserInfo->lpUserName)+4) * sizeof (WCHAR));
  255. if (*UPNName && *DispInfo && *SubjectName ){
  256. wcscpy(*UPNName, UserName->rItems[0].pName);
  257. wcscpy(*DispInfo, pEfsUserInfo->lpUserName);
  258. wcscat(*DispInfo, L"(");
  259. wcscat(*DispInfo, *UPNName);
  260. wcscat(*DispInfo, L")");
  261. wcscpy(*SubjectName, L"CN=");
  262. wcscat(*SubjectName, pEfsUserInfo->lpUserName);
  263. } else {
  264. if (*UPNName) {
  265. LsapFreeLsaHeap( *UPNName );
  266. *UPNName = NULL;
  267. }
  268. if (*DispInfo) {
  269. LsapFreeLsaHeap( *DispInfo );
  270. *DispInfo = NULL;
  271. }
  272. if (*SubjectName) {
  273. LsapFreeLsaHeap( *SubjectName );
  274. *SubjectName = NULL;
  275. }
  276. rc = ERROR_NOT_ENOUGH_MEMORY;
  277. }
  278. }
  279. if (UserName){
  280. DsFreeNameResult(UserName);
  281. UserName = NULL;
  282. }
  283. }
  284. DsUnBindW( &hDS );
  285. }
  286. }
  287. if (NULL == *UPNName) {
  288. //
  289. // If Local Account, let the UPNNmae be User@Computer. DispInfo be User(User@Computer).
  290. // Else let the UPNName be User@Domain. DispInfo be User(User@Domain)
  291. //
  292. *UPNName = (LPWSTR) LsapAllocateLsaHeap(
  293. (wcslen(pEfsUserInfo->lpUserName) +
  294. wcslen(pEfsUserInfo->lpDomainName) +
  295. 2) * sizeof (WCHAR));
  296. *DispInfo = (LPWSTR) LsapAllocateLsaHeap(
  297. (wcslen(pEfsUserInfo->lpDomainName) +
  298. wcslen(pEfsUserInfo->lpUserName) * 2 +
  299. 4) * sizeof (WCHAR));
  300. *SubjectName = (LPWSTR) LsapAllocateLsaHeap(
  301. (wcslen(pEfsUserInfo->lpUserName)+
  302. 4) * sizeof (WCHAR));
  303. if (*UPNName && *DispInfo && *SubjectName){
  304. wcscpy(*UPNName, pEfsUserInfo->lpUserName);
  305. wcscat(*UPNName, L"@");
  306. wcscat(*UPNName, pEfsUserInfo->lpDomainName);
  307. wcscpy(*DispInfo, pEfsUserInfo->lpUserName);
  308. wcscat(*DispInfo, L"(");
  309. wcscat(*DispInfo, *UPNName);
  310. wcscat(*DispInfo, L")");
  311. wcscpy(*SubjectName, L"CN=");
  312. wcscat(*SubjectName, pEfsUserInfo->lpUserName);
  313. } else {
  314. if (*UPNName) {
  315. LsapFreeLsaHeap( *UPNName );
  316. *UPNName = NULL;
  317. }
  318. if (*DispInfo) {
  319. LsapFreeLsaHeap( *DispInfo );
  320. *DispInfo = NULL;
  321. }
  322. if (*SubjectName) {
  323. LsapFreeLsaHeap( *SubjectName );
  324. *SubjectName = NULL;
  325. }
  326. rc = ERROR_NOT_ENOUGH_MEMORY;
  327. }
  328. }
  329. return rc;
  330. }
  331. #if 0
  332. LPWSTR
  333. MakeDNName(
  334. BOOLEAN RecoveryKey,
  335. IN PEFS_USER_INFO pEfsUserInfo
  336. )
  337. /*++
  338. Routine Description:
  339. Fabricates a display name for a locally built self-signed cert
  340. Arguments:
  341. RecoveryKey - Specifies if this is a recovery key or not.
  342. Return Value:
  343. Returns a string containing a display name, or NULL.
  344. --*/
  345. {
  346. NTSTATUS Status;
  347. LPWSTR DNName = NULL;
  348. LPCWSTR DNNameTemplate = L"CN=%ws,L=EFS,OU=EFS File Encryption Certificate";
  349. DWORD cbDNName = 0;
  350. if (RecoveryKey) {
  351. cbDNName = (wcslen( DNNameTemplate ) + 1) * sizeof( WCHAR ) + (wcslen( EfsComputerName ) + 1) * sizeof( WCHAR );
  352. DNName = (LPWSTR)LsapAllocateLsaHeap( cbDNName );
  353. if (DNName) {
  354. swprintf( DNName, DNNameTemplate, EfsComputerName );
  355. } else {
  356. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  357. }
  358. } else {
  359. //
  360. // This will be an overestimate, but only by a little.
  361. //
  362. cbDNName = (wcslen( DNNameTemplate ) * sizeof( WCHAR )) + (wcslen( pEfsUserInfo->lpUserName ) + 1) * sizeof( WCHAR );
  363. DNName = (LPWSTR)LsapAllocateLsaHeap( cbDNName );
  364. if (DNName != NULL) {
  365. swprintf( DNName, DNNameTemplate, pEfsUserInfo->lpUserName );
  366. } else {
  367. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  368. }
  369. }
  370. return( DNName );
  371. }
  372. #endif
  373. DWORD
  374. EfsFindCertOid(
  375. IN LPSTR pEfsCertOid,
  376. IN PCCERT_CONTEXT pCertContext,
  377. OUT BOOL *OidFound
  378. )
  379. /*++
  380. Routine Description:
  381. This routine takes a cert context and an Efs Oid. It will check if the cert has the Efs Oid or not.
  382. Arguments:
  383. pEfsCertOid - Efs Oid to be searched for.
  384. pCertContext - The cert to be searched for.
  385. OidFound - The result. TRUE if the oid is found.
  386. Return Value:
  387. Win32 Error code.
  388. --*/
  389. {
  390. BOOL bRet;
  391. PCERT_ENHKEY_USAGE pUsage;
  392. DWORD pcbUsage = 0;
  393. DWORD rc = ERROR_SUCCESS;
  394. DWORD ii;
  395. *OidFound = FALSE;
  396. bRet = CertGetEnhancedKeyUsage(
  397. pCertContext,
  398. 0,
  399. NULL,
  400. &pcbUsage
  401. );
  402. if (bRet) {
  403. pUsage = (PCERT_ENHKEY_USAGE) LsapAllocateLsaHeap(pcbUsage);
  404. if (pUsage) {
  405. bRet = CertGetEnhancedKeyUsage(
  406. pCertContext,
  407. 0,
  408. pUsage,
  409. &pcbUsage
  410. );
  411. if (bRet){
  412. for (ii=0; ii<pUsage->cUsageIdentifier;ii++) {
  413. if (!strcmp(pUsage->rgpszUsageIdentifier[ii], pEfsCertOid)){
  414. //
  415. // We found the OID
  416. //
  417. *OidFound = TRUE;
  418. break;
  419. }
  420. }
  421. } else {
  422. rc = GetLastError();
  423. }
  424. LsapFreeLsaHeap(pUsage);
  425. } else {
  426. rc = ERROR_NOT_ENOUGH_MEMORY;
  427. }
  428. } else {
  429. rc = GetLastError();
  430. }
  431. return rc;
  432. }
  433. DWORD
  434. GetKeyInfoFromCertHash(
  435. IN OUT PEFS_USER_INFO pEfsUserInfo,
  436. IN PBYTE pbHash,
  437. IN DWORD cbHash,
  438. OUT HCRYPTKEY * hKey OPTIONAL,
  439. OUT HCRYPTPROV * hProv OPTIONAL,
  440. OUT LPWSTR * ContainerName OPTIONAL,
  441. OUT LPWSTR * ProviderName OPTIONAL,
  442. OUT LPWSTR * DisplayInformation OPTIONAL,
  443. OUT PBOOLEAN pbIsValid OPTIONAL
  444. )
  445. /*++
  446. Routine Description:
  447. This routine takes a certificate hash and extracts from it information
  448. about the key it represents. If the key information from this
  449. cert does not exist in the current context, it will return an error.
  450. Arguments:
  451. pEfsUserInfo - User Information
  452. pbHash - Takes a pointer to the certificate hash.
  453. cbHash - The length in bytes of the certificate hash.
  454. hKey - Returns the handle to the key corresponding to this
  455. certificate. Must be passed of hProv is passed.
  456. hProv - Returns the handle to the context corresponding to this
  457. certificate. Must be passed of hKey is passed.
  458. ContainerName - Returns a string with the name of the container of the
  459. key in this certificate.
  460. ProviderName - Returns a string with the name of the provider of the
  461. key in this certificate.
  462. DisplayInformation - Returns the display information for the certificate.
  463. pbIsValid - If present, causes the cert to be validity checked and the
  464. results returned.
  465. Return Value:
  466. ERROR_SUCCESS - The passed certificate is in the current user's MY
  467. store and the key it represents is in his context.
  468. !ERROR_SUCCESS - Either the certificate could not be found in the
  469. user's MY store, or the key in the certificate could not be
  470. instantiated.
  471. --*/
  472. {
  473. PCCERT_CONTEXT pCertContext;
  474. //
  475. // Don't trust CryptoAPI to set last error properly,
  476. // keep track of success and failure on our own.
  477. //
  478. BOOLEAN b = TRUE;
  479. BOOLEAN CreateCache = FALSE;
  480. BOOLEAN LocalCertValidated = FALSE;
  481. BOOLEAN DataNotCached = TRUE;
  482. DWORD rc = ERROR_SUCCESS;
  483. DWORD rc2 = ERROR_SUCCESS;
  484. HCRYPTKEY hLocalKey = NULL;
  485. HCRYPTPROV hLocalProv = NULL;
  486. LPWSTR LocalContainerName = NULL;
  487. LPWSTR LocalProviderName = NULL;
  488. LPWSTR LocalDisplayInformation = NULL;
  489. //
  490. // Output parameters
  491. //
  492. if (ARGUMENT_PRESENT(ContainerName)) {
  493. *ContainerName = NULL;
  494. }
  495. if (ARGUMENT_PRESENT(ProviderName)) {
  496. *ProviderName = NULL;
  497. }
  498. if (ARGUMENT_PRESENT(DisplayInformation)) {
  499. *DisplayInformation = NULL;
  500. }
  501. if (ARGUMENT_PRESENT(hProv)) {
  502. *hProv = NULL;
  503. }
  504. if (ARGUMENT_PRESENT(hKey)) {
  505. *hKey = NULL;
  506. }
  507. if (ARGUMENT_PRESENT( pbIsValid )){
  508. *pbIsValid = FALSE;
  509. }
  510. //
  511. // Check if a cache node is available
  512. //
  513. if (!pEfsUserInfo->UserCacheStop) {
  514. if (pEfsUserInfo->pUserCache) {
  515. //
  516. // The user has a cache, check if the Hash matches
  517. //
  518. if ( pEfsUserInfo->pUserCache->cbHash == cbHash ) {
  519. if(RtlEqualMemory( pEfsUserInfo->pUserCache->pbHash, pbHash, cbHash)){
  520. //
  521. // Cache is valid. Use the cache
  522. //
  523. if (ARGUMENT_PRESENT( pbIsValid )){
  524. *pbIsValid = (pEfsUserInfo->pUserCache->CertValidated == CERT_VALIDATED);
  525. }
  526. return ERROR_SUCCESS;
  527. }
  528. //
  529. // User might use an old key, do not put in the cache.
  530. //
  531. }
  532. } else {
  533. CreateCache = TRUE;
  534. }
  535. }
  536. //
  537. // Find our cert via the hash
  538. //
  539. pCertContext = GetCertContextFromCertHash(
  540. pbHash,
  541. cbHash,
  542. CERT_SYSTEM_STORE_CURRENT_USER
  543. );
  544. if (pCertContext != NULL) {
  545. PCRYPT_KEY_PROV_INFO pCryptKeyProvInfo = GetKeyProvInfo( pCertContext );
  546. if (pCryptKeyProvInfo != NULL) {
  547. //
  548. // Copy out the container name and provider name if requested.
  549. //
  550. if (pCryptKeyProvInfo->pwszContainerName) {
  551. LocalContainerName = (LPWSTR)LsapAllocateLsaHeap( wcslen(pCryptKeyProvInfo->pwszContainerName) * sizeof( WCHAR ) + sizeof( UNICODE_NULL ));
  552. if (LocalContainerName != NULL) {
  553. wcscpy( LocalContainerName, pCryptKeyProvInfo->pwszContainerName );
  554. } else {
  555. rc = ERROR_NOT_ENOUGH_MEMORY;
  556. b = FALSE;
  557. }
  558. }
  559. if (b && pCryptKeyProvInfo->pwszProvName) {
  560. LocalProviderName = (LPWSTR)LsapAllocateLsaHeap( wcslen(pCryptKeyProvInfo->pwszProvName) * sizeof( WCHAR ) + sizeof( UNICODE_NULL ));
  561. if (LocalProviderName != NULL) {
  562. wcscpy( LocalProviderName, pCryptKeyProvInfo->pwszProvName );
  563. }
  564. else {
  565. rc = ERROR_NOT_ENOUGH_MEMORY;
  566. b = FALSE;
  567. }
  568. }
  569. if (!(LocalDisplayInformation = EfspGetCertDisplayInformation( pCertContext ))) {
  570. //
  571. // At least for now, we do not accept Cert without display name
  572. //
  573. rc = GetLastError();
  574. b = FALSE;
  575. }
  576. //
  577. // Get the key information
  578. //
  579. if (b) {
  580. if (CryptAcquireContext( &hLocalProv, pCryptKeyProvInfo->pwszContainerName, pCryptKeyProvInfo->pwszProvName, PROV_RSA_FULL, CRYPT_SILENT)) {
  581. if (!CryptGetUserKey(hLocalProv, AT_KEYEXCHANGE, &hLocalKey)) {
  582. rc = GetLastError();
  583. b = FALSE;
  584. }
  585. } else {
  586. rc = GetLastError();
  587. b = FALSE;
  588. }
  589. }
  590. if (b) {
  591. if ( ARGUMENT_PRESENT( pbIsValid ) || CreateCache ) {
  592. //
  593. // Do cert validity checking. Check time and usage.
  594. //
  595. if ( CertVerifyTimeValidity(
  596. NULL,
  597. pCertContext->pCertInfo
  598. )){
  599. rc2 = CERT_E_EXPIRED;
  600. //b = FALSE;
  601. } else {
  602. //
  603. // Test the cert usage here.
  604. // CERT_E_WRONG_USAGE
  605. //
  606. BOOL OidFound;
  607. rc = EfsFindCertOid(
  608. szOID_KP_EFS,
  609. pCertContext,
  610. &OidFound
  611. );
  612. if (ERROR_SUCCESS == rc) {
  613. if (OidFound) {
  614. LocalCertValidated = TRUE;
  615. }
  616. } else {
  617. b = FALSE;
  618. }
  619. }
  620. if (ARGUMENT_PRESENT( pbIsValid )) {
  621. //
  622. // We need the validation info.
  623. //
  624. *pbIsValid = LocalCertValidated;
  625. }
  626. }
  627. if ( CreateCache ) {
  628. DWORD certFlag;
  629. //
  630. // Todetermine if we can put the data in cache.
  631. //
  632. if (CurrentHashOK(pEfsUserInfo, pbHash, cbHash, &certFlag)) {
  633. //
  634. // This pbHash is in the user's key or has been put in. Let's create the cache node.
  635. //
  636. PUSER_CACHE pCacheNode;
  637. PBYTE pbWkHash;
  638. DWORD ImpersonationError = 0;
  639. if (certFlag != CERTINLMTRUSTEDSTORE) {
  640. DWORD sevRc;
  641. //
  642. // The cert is not in the LM Trusted store. Upgrade system from Win2K, or Beta 1 Whistler.
  643. //
  644. if (ERROR_SUCCESS == (sevRc = EfsAddCertToTrustStoreStore(pCertContext, &ImpersonationError))) {
  645. EfsMarkCertAddedToStore(pEfsUserInfo);
  646. } else {
  647. if (ImpersonationError) {
  648. //
  649. // Got in trouble. We could not impersonate back.
  650. //
  651. ASSERT(FALSE);
  652. rc = sevRc;
  653. b = FALSE;
  654. }
  655. }
  656. }
  657. if (!ImpersonationError) {
  658. pCacheNode = (PUSER_CACHE) LsapAllocateLsaHeap(sizeof(USER_CACHE));
  659. pbWkHash = (PBYTE) LsapAllocateLsaHeap(cbHash);
  660. if (pCacheNode && pbWkHash) {
  661. memset( pCacheNode, 0, sizeof( USER_CACHE ));
  662. RtlCopyMemory(pbWkHash, pbHash, cbHash);
  663. if (NT_SUCCESS( NtQuerySystemTime(&(pCacheNode->TimeStamp)))){
  664. if (EfspInitUserCacheNode(
  665. pCacheNode,
  666. pbWkHash,
  667. cbHash,
  668. LocalContainerName,
  669. LocalProviderName,
  670. LocalDisplayInformation,
  671. pCertContext,
  672. hLocalKey,
  673. hLocalProv,
  674. &(pEfsUserInfo->AuthId),
  675. LocalCertValidated? CERT_VALIDATED:CERT_VALIDATION_FAILED
  676. )){
  677. //
  678. // Cache node created and ready for use. Do not delete or close the info
  679. // we just got.
  680. //
  681. LocalContainerName = NULL;
  682. LocalProviderName = NULL;
  683. LocalDisplayInformation = NULL;
  684. hLocalKey = NULL;
  685. hLocalProv = NULL;
  686. pEfsUserInfo->pUserCache = pCacheNode;
  687. pCertContext = NULL;
  688. DataNotCached = FALSE;
  689. rc = ERROR_SUCCESS;
  690. b = TRUE; // We can have a non-validated cache node for the use of open file
  691. } else {
  692. LsapFreeLsaHeap(pCacheNode);
  693. LsapFreeLsaHeap(pbWkHash);
  694. pbWkHash = NULL;
  695. pCacheNode = NULL;
  696. }
  697. } else {
  698. LsapFreeLsaHeap(pCacheNode);
  699. LsapFreeLsaHeap(pbWkHash);
  700. pbWkHash = NULL;
  701. pCacheNode = NULL;
  702. }
  703. } else {
  704. if (pCacheNode) {
  705. LsapFreeLsaHeap(pCacheNode);
  706. pCacheNode = NULL;
  707. }
  708. if (pbWkHash) {
  709. LsapFreeLsaHeap(pbWkHash);
  710. pbWkHash = NULL;
  711. }
  712. }
  713. }
  714. }
  715. }
  716. if (DataNotCached && b) {
  717. //
  718. // We need to returned the data to outside
  719. //
  720. if (ARGUMENT_PRESENT(ContainerName)) {
  721. *ContainerName = LocalContainerName;
  722. LocalContainerName = NULL;
  723. }
  724. if (ARGUMENT_PRESENT(ProviderName)) {
  725. *ProviderName = LocalProviderName;
  726. LocalProviderName = NULL;
  727. }
  728. if (ARGUMENT_PRESENT(DisplayInformation)) {
  729. *DisplayInformation = LocalDisplayInformation;
  730. LocalDisplayInformation = NULL;
  731. }
  732. if (ARGUMENT_PRESENT(hKey)) {
  733. *hKey = hLocalKey;
  734. hLocalKey = NULL;
  735. }
  736. if (ARGUMENT_PRESENT(hProv)) {
  737. *hProv = hLocalProv;
  738. hLocalProv = NULL;
  739. }
  740. }
  741. }
  742. LsapFreeLsaHeap( pCryptKeyProvInfo );
  743. } else {
  744. rc = GetLastError();
  745. b = FALSE;
  746. }
  747. if (pCertContext) {
  748. CertFreeCertificateContext( pCertContext );
  749. }
  750. } else {
  751. rc = GetLastError();
  752. b = FALSE;
  753. }
  754. if (!b) {
  755. ASSERT( rc != ERROR_SUCCESS );
  756. //
  757. // Something failed, cleanup the stuff we were going to return
  758. //
  759. if ( LocalContainerName) {
  760. LsapFreeLsaHeap( LocalContainerName );
  761. }
  762. if (LocalProviderName) {
  763. LsapFreeLsaHeap( LocalProviderName );
  764. }
  765. if (LocalDisplayInformation) {
  766. LsapFreeLsaHeap( LocalDisplayInformation );
  767. }
  768. if (hLocalKey) {
  769. CryptDestroyKey( hLocalKey );
  770. }
  771. if (hLocalProv) {
  772. CryptReleaseContext( hLocalProv, 0 );
  773. }
  774. }
  775. if (ARGUMENT_PRESENT( pbIsValid ) && !LocalCertValidated ) {
  776. if (rc == ERROR_SUCCESS) {
  777. rc = rc2;
  778. }
  779. }
  780. return( rc );
  781. }
  782. PCRYPT_KEY_PROV_INFO
  783. GetKeyProvInfo(
  784. PCCERT_CONTEXT pCertContext
  785. )
  786. /*++
  787. Routine Description:
  788. This routine will extract the Key Provider Information from
  789. the passed certificate context.
  790. Arguments:
  791. pCertContext - Supplies a pointer to a certificate context.
  792. Return Value:
  793. Returns a pointer to a PCRYPT_KEY_PROV_INFO structure on success,
  794. otherwise returns NULL, which usually means that the certificate
  795. did not have the context property we were looking for (meaning
  796. that it probably isn't an EFS certificate).
  797. --*/
  798. {
  799. DWORD cbData = 0;
  800. BOOL b;
  801. PCRYPT_KEY_PROV_INFO pCryptKeyProvInfo = NULL;
  802. b = CertGetCertificateContextProperty(
  803. pCertContext,
  804. CERT_KEY_PROV_INFO_PROP_ID,
  805. NULL,
  806. &cbData
  807. );
  808. if (b) {
  809. pCryptKeyProvInfo = (PCRYPT_KEY_PROV_INFO)LsapAllocateLsaHeap( cbData );
  810. if (pCryptKeyProvInfo != NULL) {
  811. b = CertGetCertificateContextProperty(
  812. pCertContext,
  813. CERT_KEY_PROV_INFO_PROP_ID,
  814. pCryptKeyProvInfo,
  815. &cbData
  816. );
  817. if (!b) {
  818. LsapFreeLsaHeap( pCryptKeyProvInfo );
  819. pCryptKeyProvInfo = NULL;
  820. }
  821. } else {
  822. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  823. }
  824. }
  825. return ( pCryptKeyProvInfo );
  826. }