Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1609 lines
45 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. //#define ProfilingEfs
  29. /////////////////////////////////////////////////////////////////////////////////////
  30. // /
  31. // /
  32. // Helper Functions /
  33. // /
  34. // /
  35. /////////////////////////////////////////////////////////////////////////////////////
  36. PCCERT_CONTEXT
  37. GetCertContextFromCertHash(
  38. IN PBYTE pbHash,
  39. IN DWORD cbHash,
  40. IN DWORD dwFlags,
  41. IN DWORD dwOpen
  42. )
  43. /*++
  44. Routine Description:
  45. Finds the cert with the passed cert hash in the user's MY store
  46. and returns a context pointer.
  47. Arguments:
  48. pbHash - Supplies a pointer to the hash to be matched.
  49. cbHash - Supplies the length in bytes of the passed hash.
  50. dwFlags - Supplies flags to CertOpenStore
  51. dwOpen - 0 if not in the file open path
  52. Return Value:
  53. Returns a pointer to a certificate context, or NULL.
  54. The returned context must be freed via CertFreeCertificateContext()
  55. --*/
  56. {
  57. CRYPT_HASH_BLOB hashBlob;
  58. BOOL OidFound;
  59. PCCERT_CONTEXT pCertContext = NULL;
  60. DWORD rc = ERROR_SUCCESS;
  61. //HCERTSTORE hStore = CertOpenSystemStoreW( NULL, L"MY");
  62. #ifdef ProfilingEfs
  63. LARGE_INTEGER StartTime;
  64. LARGE_INTEGER StopTime;
  65. NtQuerySystemTime(&StartTime);
  66. #endif
  67. HCERTSTORE hStore = CertOpenStore(
  68. CERT_STORE_PROV_SYSTEM_REGISTRY_W,
  69. 0, // dwEncodingType
  70. 0, // hCryptProv,
  71. dwFlags,
  72. L"My"
  73. );
  74. #ifdef ProfilingEfs
  75. NtQuerySystemTime(&StopTime);
  76. DbgPrint("OpenStore:%lu\tHashHead:%lu\n", (ULONG)(StopTime.QuadPart - StartTime.QuadPart)/1000, *((PULONG)pbHash));
  77. #endif
  78. if (hStore != NULL) {
  79. //
  80. // Find our cert via the hash
  81. //
  82. hashBlob.cbData = cbHash;
  83. hashBlob.pbData = pbHash;
  84. pCertContext = CertFindCertificateInStore( hStore,
  85. CRYPT_ASN_ENCODING,
  86. 0,
  87. CERT_FIND_HASH,
  88. &hashBlob,
  89. NULL
  90. );
  91. //
  92. // Let's make sure we have the right EFS OID
  93. //
  94. if (pCertContext) {
  95. rc = EfsFindCertOid(
  96. szOID_KP_EFS,
  97. pCertContext,
  98. &OidFound
  99. );
  100. if ((ERROR_SUCCESS != rc) || !OidFound) {
  101. if (dwOpen) {
  102. //
  103. // Let's try recovery cert
  104. //
  105. rc = EfsFindCertOid(
  106. szOID_EFS_RECOVERY,
  107. pCertContext,
  108. &OidFound
  109. );
  110. }
  111. if ((ERROR_SUCCESS != rc) || !OidFound) {
  112. //
  113. // Could not get the EFS OID. Same as not finding the cert.
  114. //
  115. CertFreeCertificateContext(pCertContext);
  116. pCertContext = NULL;
  117. if ((rc != ERROR_SUCCESS) && (rc != CERTSRV_E_KEY_LENGTH)){
  118. rc = CERT_E_WRONG_USAGE;
  119. }
  120. }
  121. }
  122. } else {
  123. rc = GetLastError();
  124. }
  125. CertCloseStore( hStore, 0 );
  126. }
  127. if (rc != ERROR_SUCCESS) {
  128. SetLastError(rc);
  129. }
  130. return( pCertContext );
  131. }
  132. LPWSTR
  133. EfspGetCertDisplayInformation(
  134. IN PCCERT_CONTEXT pCertContext
  135. )
  136. /*++
  137. Routine Description:
  138. Returns the display string from the passed certificate context.
  139. Arguments:
  140. pCertContext - Supplies a pointer to an open certificate context.
  141. Return Value:
  142. On success, pointer to display string. Caller must call
  143. LsapFreeLsaHeap() to free.
  144. NULL on failure.
  145. --*/
  146. {
  147. DWORD rc;
  148. LPWSTR UserDispName = NULL;
  149. rc = EfsGetCertNameFromCertContext(
  150. pCertContext,
  151. &UserDispName
  152. );
  153. if (rc == ERROR_SUCCESS) {
  154. return UserDispName;
  155. } else {
  156. SetLastError(rc);
  157. return NULL;
  158. }
  159. }
  160. PBYTE
  161. GetCertHashFromCertContext(
  162. IN PCCERT_CONTEXT pCertContext,
  163. OUT PDWORD pcbHash
  164. )
  165. /*++
  166. Routine Description:
  167. Helper routine, takes a cert context and extracts the hash.
  168. Arguments:
  169. pCertContext - Supplies the cert context.
  170. pcbHash - Returns the length in bytes of the returned hash.
  171. Return Value:
  172. Returns a pointer to a hash block allocated out of heap memory,
  173. or NULL if either the attempt to get the hash failed or the attempt
  174. to allocate memory failed.
  175. Call GetLastError() for more details in case of failure.
  176. --*/
  177. {
  178. PBYTE pbHash = NULL;
  179. *pcbHash = 0;
  180. if (CertGetCertificateContextProperty(
  181. pCertContext,
  182. CERT_HASH_PROP_ID,
  183. NULL,
  184. pcbHash
  185. )) {
  186. pbHash = (PBYTE)LsapAllocateLsaHeap( *pcbHash );
  187. if (pbHash != NULL) {
  188. if (!CertGetCertificateContextProperty(
  189. pCertContext,
  190. CERT_HASH_PROP_ID,
  191. pbHash,
  192. pcbHash
  193. )) {
  194. LsapFreeLsaHeap( pbHash );
  195. pbHash = NULL;
  196. *pcbHash = 0;
  197. }
  198. } else {
  199. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  200. }
  201. }
  202. return( pbHash );
  203. }
  204. PCERT_PUBLIC_KEY_INFO
  205. ExportPublicKeyInfo(
  206. IN HCRYPTPROV hProv,
  207. IN DWORD dwKeySpec,
  208. IN DWORD dwCertEncodingType,
  209. IN OUT DWORD *pcbInfo
  210. )
  211. {
  212. PCERT_PUBLIC_KEY_INFO pPubKeyInfo = NULL;
  213. if ( CryptExportPublicKeyInfo(
  214. hProv,
  215. dwKeySpec,
  216. dwCertEncodingType,
  217. NULL,
  218. pcbInfo)) {
  219. pPubKeyInfo = (PCERT_PUBLIC_KEY_INFO) LsapAllocateLsaHeap(*pcbInfo);
  220. if (pPubKeyInfo) {
  221. if (!CryptExportPublicKeyInfo( hProv,
  222. dwKeySpec,
  223. dwCertEncodingType,
  224. pPubKeyInfo,
  225. pcbInfo)) {
  226. LsapFreeLsaHeap( pPubKeyInfo );
  227. pPubKeyInfo = NULL;
  228. *pcbInfo = 0;
  229. }
  230. }
  231. }
  232. return ( pPubKeyInfo );
  233. }
  234. BOOL
  235. EncodeAndAlloc(
  236. DWORD dwEncodingType,
  237. LPCSTR lpszStructType,
  238. const void * pvStructInfo,
  239. PBYTE * pbEncoded,
  240. PDWORD pcbEncoded
  241. )
  242. {
  243. BOOL b = FALSE;
  244. if (CryptEncodeObject(
  245. dwEncodingType,
  246. lpszStructType,
  247. pvStructInfo,
  248. NULL,
  249. pcbEncoded )) {
  250. *pbEncoded = (PBYTE)LsapAllocateLsaHeap( *pcbEncoded );
  251. if (*pbEncoded) {
  252. if (CryptEncodeObject(
  253. dwEncodingType,
  254. lpszStructType,
  255. pvStructInfo,
  256. *pbEncoded,
  257. pcbEncoded )) {
  258. b = TRUE;
  259. } else {
  260. LsapFreeLsaHeap( *pbEncoded );
  261. *pbEncoded = NULL;
  262. }
  263. } else {
  264. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  265. }
  266. }
  267. return( b );
  268. }
  269. DWORD
  270. EfsMakeCertNames(
  271. IN PEFS_USER_INFO pEfsUserInfo,
  272. OUT LPWSTR *DispInfo,
  273. OUT LPWSTR *SubjectName,
  274. OUT LPWSTR *UPNName
  275. )
  276. {
  277. DWORD rc = ERROR_SUCCESS;
  278. *DispInfo = NULL;
  279. *UPNName = NULL;
  280. if (pEfsUserInfo->bDomainAccount) {
  281. //
  282. // Domain Account
  283. //
  284. HRESULT hr;
  285. HANDLE hDS = NULL;
  286. DS_NAME_RESULT* UserName = NULL;
  287. hr = DsBind(NULL, NULL, &hDS);
  288. if (hr == NO_ERROR) {
  289. rc = DsCrackNames(
  290. hDS,
  291. DS_NAME_NO_FLAGS,
  292. DS_SID_OR_SID_HISTORY_NAME,
  293. DS_USER_PRINCIPAL_NAME,
  294. 1,
  295. &(pEfsUserInfo->lpUserSid),
  296. &UserName
  297. );
  298. if (ERROR_SUCCESS == rc) {
  299. if (UserName->rItems[0].status == DS_NAME_NO_ERROR) {
  300. *UPNName = (LPWSTR) LsapAllocateLsaHeap((wcslen(UserName->rItems[0].pName) + 1) * sizeof (WCHAR));
  301. *DispInfo = (LPWSTR) LsapAllocateLsaHeap(
  302. (wcslen(UserName->rItems[0].pName) +
  303. wcslen(pEfsUserInfo->lpUserName) +
  304. 3) * sizeof (WCHAR));
  305. *SubjectName = (LPWSTR) LsapAllocateLsaHeap((wcslen(pEfsUserInfo->lpUserName)+4) * sizeof (WCHAR));
  306. if (*UPNName && *DispInfo && *SubjectName ){
  307. wcscpy(*UPNName, UserName->rItems[0].pName);
  308. wcscpy(*DispInfo, pEfsUserInfo->lpUserName);
  309. wcscat(*DispInfo, L"(");
  310. wcscat(*DispInfo, *UPNName);
  311. wcscat(*DispInfo, L")");
  312. wcscpy(*SubjectName, L"CN=");
  313. wcscat(*SubjectName, pEfsUserInfo->lpUserName);
  314. } else {
  315. if (*UPNName) {
  316. LsapFreeLsaHeap( *UPNName );
  317. *UPNName = NULL;
  318. }
  319. if (*DispInfo) {
  320. LsapFreeLsaHeap( *DispInfo );
  321. *DispInfo = NULL;
  322. }
  323. if (*SubjectName) {
  324. LsapFreeLsaHeap( *SubjectName );
  325. *SubjectName = NULL;
  326. }
  327. rc = ERROR_NOT_ENOUGH_MEMORY;
  328. }
  329. }
  330. if (UserName){
  331. DsFreeNameResult(UserName);
  332. UserName = NULL;
  333. }
  334. }
  335. DsUnBindW( &hDS );
  336. }
  337. }
  338. if (NULL == *UPNName) {
  339. //
  340. // If Local Account, let the UPNNmae be User@Computer. DispInfo be User(User@Computer).
  341. // Else let the UPNName be User@Domain. DispInfo be User(User@Domain)
  342. //
  343. *UPNName = (LPWSTR) LsapAllocateLsaHeap(
  344. (wcslen(pEfsUserInfo->lpUserName) +
  345. wcslen(pEfsUserInfo->lpDomainName) +
  346. 2) * sizeof (WCHAR));
  347. *DispInfo = (LPWSTR) LsapAllocateLsaHeap(
  348. (wcslen(pEfsUserInfo->lpDomainName) +
  349. wcslen(pEfsUserInfo->lpUserName) * 2 +
  350. 4) * sizeof (WCHAR));
  351. *SubjectName = (LPWSTR) LsapAllocateLsaHeap(
  352. (wcslen(pEfsUserInfo->lpUserName)+
  353. 4) * sizeof (WCHAR));
  354. if (*UPNName && *DispInfo && *SubjectName){
  355. wcscpy(*UPNName, pEfsUserInfo->lpUserName);
  356. wcscat(*UPNName, L"@");
  357. wcscat(*UPNName, pEfsUserInfo->lpDomainName);
  358. wcscpy(*DispInfo, pEfsUserInfo->lpUserName);
  359. wcscat(*DispInfo, L"(");
  360. wcscat(*DispInfo, *UPNName);
  361. wcscat(*DispInfo, L")");
  362. wcscpy(*SubjectName, L"CN=");
  363. wcscat(*SubjectName, pEfsUserInfo->lpUserName);
  364. } else {
  365. if (*UPNName) {
  366. LsapFreeLsaHeap( *UPNName );
  367. *UPNName = NULL;
  368. }
  369. if (*DispInfo) {
  370. LsapFreeLsaHeap( *DispInfo );
  371. *DispInfo = NULL;
  372. }
  373. if (*SubjectName) {
  374. LsapFreeLsaHeap( *SubjectName );
  375. *SubjectName = NULL;
  376. }
  377. rc = ERROR_NOT_ENOUGH_MEMORY;
  378. }
  379. }
  380. return rc;
  381. }
  382. DWORD
  383. EfsFindCertOid(
  384. IN LPSTR pEfsCertOid,
  385. IN PCCERT_CONTEXT pCertContext,
  386. OUT BOOL *OidFound
  387. )
  388. /*++
  389. Routine Description:
  390. This routine takes a cert context and an Efs Oid. It will check if the cert has the Efs Oid or not.
  391. Arguments:
  392. pEfsCertOid - Efs Oid to be searched for.
  393. pCertContext - The cert to be searched for.
  394. OidFound - The result. TRUE if the oid is found.
  395. Return Value:
  396. Win32 Error code.
  397. --*/
  398. {
  399. BOOL bRet;
  400. PCERT_ENHKEY_USAGE pUsage;
  401. DWORD pcbUsage = 0;
  402. DWORD rc = ERROR_SUCCESS;
  403. DWORD ii;
  404. DWORD KeyLength;
  405. *OidFound = FALSE;
  406. //
  407. // Let's check the key length first
  408. //
  409. KeyLength = CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &(pCertContext->pCertInfo->SubjectPublicKeyInfo));
  410. if (!KeyLength) {
  411. return GetLastError();
  412. }
  413. if (KeyLength < (RSA1024BIT_KEY >> 17)) {
  414. //
  415. // Key length too short ( 512 ), We actually don't generate less than 1024.
  416. //
  417. return CERTSRV_E_KEY_LENGTH;
  418. }
  419. bRet = CertGetEnhancedKeyUsage(
  420. pCertContext,
  421. 0,
  422. NULL,
  423. &pcbUsage
  424. );
  425. if (bRet) {
  426. SafeAllocaAllocate(pUsage, pcbUsage);
  427. if (pUsage) {
  428. bRet = CertGetEnhancedKeyUsage(
  429. pCertContext,
  430. 0,
  431. pUsage,
  432. &pcbUsage
  433. );
  434. if (bRet){
  435. for (ii=0; ii<pUsage->cUsageIdentifier;ii++) {
  436. if (!strcmp(pUsage->rgpszUsageIdentifier[ii], pEfsCertOid)){
  437. //
  438. // We found the OID
  439. //
  440. *OidFound = TRUE;
  441. break;
  442. }
  443. }
  444. } else {
  445. rc = GetLastError();
  446. }
  447. SafeAllocaFree(pUsage);
  448. } else {
  449. rc = ERROR_NOT_ENOUGH_MEMORY;
  450. }
  451. } else {
  452. rc = GetLastError();
  453. }
  454. return rc;
  455. }
  456. LONG
  457. EfsTimeExp(
  458. IN LPFILETIME CertExpTime
  459. )
  460. /*++
  461. Routine Description:
  462. This routine takes a time to see if it has passed.
  463. Arguments:
  464. CertExpTime - time to be checked
  465. Return Value:
  466. Non zero if passed.
  467. --*/
  468. {
  469. SYSTEMTIME SystemTime;
  470. FILETIME FileTime;
  471. GetSystemTime(&SystemTime);
  472. SystemTimeToFileTime(&SystemTime, &FileTime);
  473. if (CompareFileTime(&FileTime, CertExpTime) <= 0)
  474. return 0;
  475. else
  476. return 1;
  477. }
  478. DWORD
  479. GetKeyInfoFromCertHash(
  480. IN OUT PEFS_USER_INFO pEfsUserInfo,
  481. IN PBYTE pbHash,
  482. IN DWORD cbHash,
  483. OUT HCRYPTKEY * hKey OPTIONAL,
  484. OUT HCRYPTPROV * hProv OPTIONAL,
  485. OUT LPWSTR * ContainerName OPTIONAL,
  486. OUT LPWSTR * ProviderName OPTIONAL,
  487. OUT LPWSTR * DisplayInformation OPTIONAL,
  488. OUT PBOOLEAN pbIsValid OPTIONAL
  489. )
  490. /*++
  491. Routine Description:
  492. This routine takes a certificate hash and extracts from it information
  493. about the key it represents. If the key information from this
  494. cert does not exist in the current context, it will return an error.
  495. Arguments:
  496. pEfsUserInfo - User Information
  497. pbHash - Takes a pointer to the certificate hash.
  498. cbHash - The length in bytes of the certificate hash.
  499. hKey - Returns the handle to the key corresponding to this
  500. certificate. Must be passed of hProv is passed.
  501. hProv - Returns the handle to the context corresponding to this
  502. certificate. Must be passed of hKey is passed.
  503. ContainerName - Returns a string with the name of the container of the
  504. key in this certificate.
  505. ProviderName - Returns a string with the name of the provider of the
  506. key in this certificate.
  507. DisplayInformation - Returns the display information for the certificate.
  508. pbIsValid - If present, causes the cert to be validity checked and the
  509. results returned.
  510. Return Value:
  511. ERROR_SUCCESS - The passed certificate is in the current user's MY
  512. store and the key it represents is in his context.
  513. !ERROR_SUCCESS - Either the certificate could not be found in the
  514. user's MY store, or the key in the certificate could not be
  515. instantiated.
  516. --*/
  517. {
  518. PCCERT_CONTEXT pCertContext;
  519. IN PBYTE pbLocalHash = NULL;
  520. IN DWORD cbLocalHash = 0;
  521. //
  522. // Don't trust CryptoAPI to set last error properly,
  523. // keep track of success and failure on our own.
  524. //
  525. BOOLEAN b = TRUE;
  526. BOOLEAN CreateCache = FALSE;
  527. BOOLEAN LocalCertValidated = FALSE;
  528. BOOLEAN DataNotCached = TRUE;
  529. DWORD rc = ERROR_SUCCESS;
  530. DWORD rc2 = ERROR_SUCCESS;
  531. HCRYPTKEY hLocalKey = NULL;
  532. HCRYPTPROV hLocalProv = NULL;
  533. LPWSTR LocalContainerName = NULL;
  534. LPWSTR LocalProviderName = NULL;
  535. LPWSTR LocalDisplayInformation = NULL;
  536. //
  537. // Output parameters
  538. //
  539. if (ARGUMENT_PRESENT(ContainerName)) {
  540. *ContainerName = NULL;
  541. }
  542. if (ARGUMENT_PRESENT(ProviderName)) {
  543. *ProviderName = NULL;
  544. }
  545. if (ARGUMENT_PRESENT(DisplayInformation)) {
  546. *DisplayInformation = NULL;
  547. }
  548. if (ARGUMENT_PRESENT(hProv)) {
  549. *hProv = NULL;
  550. }
  551. if (ARGUMENT_PRESENT(hKey)) {
  552. *hKey = NULL;
  553. }
  554. if (ARGUMENT_PRESENT( pbIsValid )){
  555. *pbIsValid = FALSE;
  556. }
  557. //
  558. // Check if a cache node is available
  559. //
  560. if (!pEfsUserInfo->UserCacheStop) {
  561. if (pEfsUserInfo->pUserCache) {
  562. //
  563. // The user has a cache, check if the Hash matches
  564. //
  565. if ( pEfsUserInfo->pUserCache->cbHash == cbHash ) {
  566. if(RtlEqualMemory( pEfsUserInfo->pUserCache->pbHash, pbHash, cbHash)){
  567. //
  568. // Cache is valid. Use the cache
  569. //
  570. if (ARGUMENT_PRESENT( pbIsValid )){
  571. *pbIsValid = (pEfsUserInfo->pUserCache->CertValidated == CERT_VALIDATED);
  572. }
  573. return ERROR_SUCCESS;
  574. }
  575. //
  576. // User might use an old key, do not put in the cache.
  577. //
  578. }
  579. } else {
  580. CreateCache = TRUE;
  581. }
  582. }
  583. //
  584. // Well, cert is not in the cache. The profile could be not loaded. Let's try to load the profile.
  585. // If the profile is already loaded, it will return success without calling LoadUserProfile().
  586. // We don't need to unload here. It will be unload at the very outside.
  587. //
  588. if (!EfspLoadUserProfile( pEfsUserInfo, TRUE )){
  589. //
  590. // Profile Load Failure
  591. //
  592. return GetLastError();
  593. }
  594. //
  595. // Find our cert via the hash
  596. //
  597. pCertContext = GetCertContextFromCertHash(
  598. pbHash,
  599. cbHash,
  600. CERT_SYSTEM_STORE_CURRENT_USER,
  601. ARGUMENT_PRESENT( pbIsValid )? 0:1
  602. );
  603. if (pCertContext != NULL) {
  604. pbLocalHash = pbHash;
  605. cbLocalHash = cbHash;
  606. //
  607. // Let's check if the cert points to a new cert or not. If it is, the current reg value
  608. // will be changed.
  609. //
  610. PCCERT_CONTEXT pNewCertContext = NULL;
  611. if (ARGUMENT_PRESENT( pbIsValid ) || pEfsUserInfo->pUserCache == NULL) {
  612. //
  613. // Create path or the first open
  614. //
  615. rc = EfsTryRenewCert(
  616. pEfsUserInfo,
  617. pCertContext,
  618. &pNewCertContext
  619. );
  620. if (ERROR_SUCCESS == rc) {
  621. if (ARGUMENT_PRESENT( pbIsValid )) {
  622. //
  623. // Not an open path. Let's switch the certificate
  624. //
  625. pbLocalHash = GetCertHashFromCertContext(
  626. pNewCertContext,
  627. &cbLocalHash
  628. );
  629. if (pbLocalHash) {
  630. CertFreeCertificateContext( pCertContext );
  631. pCertContext = pNewCertContext;
  632. pNewCertContext = NULL;
  633. } else {
  634. //
  635. // Forget about the new cert
  636. //
  637. pbLocalHash = pbHash;
  638. cbLocalHash = cbHash;
  639. CertFreeCertificateContext( pNewCertContext );
  640. pNewCertContext = NULL;
  641. }
  642. } else {
  643. //
  644. // Let's create the new cache for the new cert.
  645. //
  646. EfsCreateNewCache(pEfsUserInfo, pNewCertContext);
  647. CertFreeCertificateContext( pNewCertContext );
  648. pNewCertContext = NULL;
  649. CreateCache = FALSE;
  650. }
  651. } else {
  652. rc = ERROR_SUCCESS;
  653. }
  654. }
  655. PCRYPT_KEY_PROV_INFO pCryptKeyProvInfo = GetKeyProvInfo( pCertContext );
  656. if (pCryptKeyProvInfo != NULL) {
  657. //
  658. // Copy out the container name and provider name if requested.
  659. //
  660. if (pCryptKeyProvInfo->pwszContainerName) {
  661. LocalContainerName = (LPWSTR)LsapAllocateLsaHeap( wcslen(pCryptKeyProvInfo->pwszContainerName) * sizeof( WCHAR ) + sizeof( UNICODE_NULL ));
  662. if (LocalContainerName != NULL) {
  663. wcscpy( LocalContainerName, pCryptKeyProvInfo->pwszContainerName );
  664. } else {
  665. rc = ERROR_NOT_ENOUGH_MEMORY;
  666. b = FALSE;
  667. }
  668. }
  669. if (b && pCryptKeyProvInfo->pwszProvName) {
  670. LocalProviderName = (LPWSTR)LsapAllocateLsaHeap( wcslen(pCryptKeyProvInfo->pwszProvName) * sizeof( WCHAR ) + sizeof( UNICODE_NULL ));
  671. if (LocalProviderName != NULL) {
  672. wcscpy( LocalProviderName, pCryptKeyProvInfo->pwszProvName );
  673. }
  674. else {
  675. rc = ERROR_NOT_ENOUGH_MEMORY;
  676. b = FALSE;
  677. }
  678. }
  679. if (!(LocalDisplayInformation = EfspGetCertDisplayInformation( pCertContext ))) {
  680. //
  681. // At least for now, we do not accept Cert without display name
  682. //
  683. rc = GetLastError();
  684. b = FALSE;
  685. }
  686. //
  687. // Get the key information
  688. //
  689. if (b) {
  690. #ifdef ProfilingEfs
  691. LARGE_INTEGER StartTime;
  692. LARGE_INTEGER StopTime;
  693. NtQuerySystemTime(&StartTime);
  694. #endif
  695. if (CryptAcquireContext( &hLocalProv, pCryptKeyProvInfo->pwszContainerName, pCryptKeyProvInfo->pwszProvName, PROV_RSA_FULL, CRYPT_SILENT)) {
  696. #ifdef ProfilingEfs
  697. NtQuerySystemTime(&StopTime);
  698. DbgPrint("CryptAcquireContext:%lu\tSessionID:%lu\tHashHead:%lu\n", (ULONG)(StopTime.QuadPart - StartTime.QuadPart)/1000, pEfsUserInfo->AuthId.LowPart, *((ULONG *)pbHash));
  699. #endif
  700. if (!CryptGetUserKey(hLocalProv, AT_KEYEXCHANGE, &hLocalKey)) {
  701. rc = GetLastError();
  702. b = FALSE;
  703. }
  704. } else {
  705. rc = GetLastError();
  706. if (pEfsUserInfo->NonKerberos && (ERROR_OUTOFMEMORY != rc)) {
  707. EfsLogEntry(
  708. EVENTLOG_ERROR_TYPE,
  709. 0,
  710. EFS_NTLM_ERROR,
  711. 0,
  712. sizeof(DWORD),
  713. NULL,
  714. &rc
  715. );
  716. rc = ERROR_BAD_LOGON_SESSION_STATE;
  717. }
  718. b = FALSE;
  719. }
  720. }
  721. if (b) {
  722. if ( ARGUMENT_PRESENT( pbIsValid ) || CreateCache ) {
  723. //
  724. // Do cert validity checking. Check time and usage.
  725. //
  726. if ( CertVerifyTimeValidity(
  727. NULL,
  728. pCertContext->pCertInfo
  729. )){
  730. rc2 = CERT_E_EXPIRED;
  731. //b = FALSE;
  732. } else {
  733. LocalCertValidated = TRUE;
  734. }
  735. if (ARGUMENT_PRESENT( pbIsValid )) {
  736. //
  737. // We need the validation info.
  738. //
  739. *pbIsValid = LocalCertValidated;
  740. }
  741. }
  742. if ( CreateCache ) {
  743. DWORD certFlag;
  744. //
  745. // To determine if we can put the data in cache.
  746. //
  747. if (CurrentHashOK(pEfsUserInfo, pbLocalHash, cbLocalHash, &certFlag)) {
  748. //
  749. // This pbHash is in the user's key or has been put in. Let's create the cache node.
  750. //
  751. PUSER_CACHE pCacheNode;
  752. PBYTE pbWkHash;
  753. DWORD ImpersonationError = 0;
  754. if ( 0 == (certFlag & CERTSTOREIDMASK) ) {
  755. DWORD sevRc;
  756. //
  757. // The cert is not in the LM Trusted or Other store. Upgrade system from Win2K, or Beta 1 Whistler.
  758. //
  759. if (ERROR_SUCCESS == (sevRc = EfsAddCertToCertStore(pCertContext, OTHERPEOPLE, &ImpersonationError))) {
  760. EfsMarkCertAddedToStore(pEfsUserInfo, CERTINLMOTHERSTORE);
  761. } else {
  762. if (ImpersonationError) {
  763. //
  764. // Got in trouble. We could not impersonate back.
  765. //
  766. ASSERT(FALSE);
  767. rc = sevRc;
  768. b = FALSE;
  769. }
  770. }
  771. }
  772. if (!ImpersonationError) {
  773. PSID pUserID = NULL;
  774. ULONG SidLength = 0;
  775. pCacheNode = (PUSER_CACHE) LsapAllocateLsaHeap(sizeof(USER_CACHE));
  776. pbWkHash = (PBYTE) LsapAllocateLsaHeap(cbLocalHash);
  777. if (pEfsUserInfo->InterActiveUser != USER_INTERACTIVE) {
  778. SidLength = RtlLengthSid(pEfsUserInfo->pTokenUser->User.Sid);
  779. pUserID = (PSID) LsapAllocateLsaHeap(SidLength);
  780. }
  781. if (pCacheNode && pbWkHash && ((SidLength == 0) || (pUserID))) {
  782. NTSTATUS Status = STATUS_SUCCESS;
  783. memset( pCacheNode, 0, sizeof( USER_CACHE ));
  784. RtlCopyMemory(pbWkHash, pbLocalHash, cbLocalHash);
  785. if (pUserID) {
  786. Status = RtlCopySid(
  787. SidLength,
  788. pUserID,
  789. pEfsUserInfo->pTokenUser->User.Sid
  790. );
  791. }
  792. if (NT_SUCCESS( Status ) && NT_SUCCESS( NtQuerySystemTime(&(pCacheNode->TimeStamp)))){
  793. if (EfspInitUserCacheNode(
  794. pCacheNode,
  795. pUserID,
  796. pbWkHash,
  797. cbLocalHash,
  798. LocalContainerName,
  799. LocalProviderName,
  800. LocalDisplayInformation,
  801. &(pCertContext->pCertInfo->NotAfter),
  802. hLocalKey,
  803. hLocalProv,
  804. pUserID? NULL: &(pEfsUserInfo->AuthId),
  805. LocalCertValidated? CERT_VALIDATED:CERT_VALIDATION_FAILED
  806. )){
  807. //
  808. // Cache node created and ready for use. Do not delete or close the info
  809. // we just got.
  810. //
  811. LocalContainerName = NULL;
  812. LocalProviderName = NULL;
  813. LocalDisplayInformation = NULL;
  814. hLocalKey = NULL;
  815. hLocalProv = NULL;
  816. pEfsUserInfo->pUserCache = pCacheNode;
  817. DataNotCached = FALSE;
  818. rc = ERROR_SUCCESS;
  819. b = TRUE; // We can have a non-validated cache node for the use of open file
  820. } else {
  821. LsapFreeLsaHeap(pCacheNode);
  822. LsapFreeLsaHeap(pbWkHash);
  823. pbWkHash = NULL;
  824. pCacheNode = NULL;
  825. if (pUserID) {
  826. LsapFreeLsaHeap(pUserID);
  827. pUserID = NULL;
  828. }
  829. }
  830. } else {
  831. LsapFreeLsaHeap(pCacheNode);
  832. LsapFreeLsaHeap(pbWkHash);
  833. pbWkHash = NULL;
  834. pCacheNode = NULL;
  835. if (pUserID) {
  836. LsapFreeLsaHeap(pUserID);
  837. pUserID = NULL;
  838. }
  839. }
  840. } else {
  841. if (pCacheNode) {
  842. LsapFreeLsaHeap(pCacheNode);
  843. pCacheNode = NULL;
  844. }
  845. if (pbWkHash) {
  846. LsapFreeLsaHeap(pbWkHash);
  847. pbWkHash = NULL;
  848. }
  849. if (pUserID) {
  850. LsapFreeLsaHeap(pUserID);
  851. pUserID = NULL;
  852. }
  853. }
  854. }
  855. }
  856. }
  857. if (DataNotCached && b) {
  858. //
  859. // We need to returned the data to outside
  860. //
  861. if (ARGUMENT_PRESENT(ContainerName)) {
  862. *ContainerName = LocalContainerName;
  863. LocalContainerName = NULL;
  864. } else {
  865. LsapFreeLsaHeap( LocalContainerName );
  866. LocalContainerName = NULL;
  867. }
  868. if (ARGUMENT_PRESENT(ProviderName)) {
  869. *ProviderName = LocalProviderName;
  870. LocalProviderName = NULL;
  871. } else {
  872. LsapFreeLsaHeap( LocalProviderName );
  873. LocalProviderName = NULL;
  874. }
  875. if (ARGUMENT_PRESENT(DisplayInformation)) {
  876. *DisplayInformation = LocalDisplayInformation;
  877. LocalDisplayInformation = NULL;
  878. } else {
  879. LsapFreeLsaHeap( LocalDisplayInformation );
  880. LocalDisplayInformation = NULL;
  881. }
  882. if (ARGUMENT_PRESENT(hKey)) {
  883. *hKey = hLocalKey;
  884. hLocalKey = NULL;
  885. }
  886. if (ARGUMENT_PRESENT(hProv)) {
  887. *hProv = hLocalProv;
  888. hLocalProv = NULL;
  889. }
  890. }
  891. }
  892. LsapFreeLsaHeap( pCryptKeyProvInfo );
  893. if (pbLocalHash && (pbLocalHash != pbHash)) {
  894. LsapFreeLsaHeap( pbLocalHash );
  895. }
  896. } else {
  897. rc = GetLastError();
  898. b = FALSE;
  899. }
  900. if (pCertContext) {
  901. CertFreeCertificateContext( pCertContext );
  902. }
  903. } else {
  904. rc = GetLastError();
  905. b = FALSE;
  906. }
  907. if (!b) {
  908. ASSERT( rc != ERROR_SUCCESS );
  909. //
  910. // Something failed, cleanup the stuff we were going to return
  911. //
  912. if ( LocalContainerName) {
  913. LsapFreeLsaHeap( LocalContainerName );
  914. }
  915. if (LocalProviderName) {
  916. LsapFreeLsaHeap( LocalProviderName );
  917. }
  918. if (LocalDisplayInformation) {
  919. LsapFreeLsaHeap( LocalDisplayInformation );
  920. }
  921. if (hLocalKey) {
  922. CryptDestroyKey( hLocalKey );
  923. }
  924. if (hLocalProv) {
  925. CryptReleaseContext( hLocalProv, 0 );
  926. }
  927. }
  928. if (ARGUMENT_PRESENT( pbIsValid ) && !LocalCertValidated ) {
  929. if (rc == ERROR_SUCCESS) {
  930. rc = rc2;
  931. }
  932. }
  933. return( rc );
  934. }
  935. PCRYPT_KEY_PROV_INFO
  936. GetKeyProvInfo(
  937. PCCERT_CONTEXT pCertContext
  938. )
  939. /*++
  940. Routine Description:
  941. This routine will extract the Key Provider Information from
  942. the passed certificate context.
  943. Arguments:
  944. pCertContext - Supplies a pointer to a certificate context.
  945. Return Value:
  946. Returns a pointer to a PCRYPT_KEY_PROV_INFO structure on success,
  947. otherwise returns NULL, which usually means that the certificate
  948. did not have the context property we were looking for (meaning
  949. that it probably isn't an EFS certificate).
  950. --*/
  951. {
  952. DWORD cbData = 0;
  953. BOOL b;
  954. PCRYPT_KEY_PROV_INFO pCryptKeyProvInfo = NULL;
  955. b = CertGetCertificateContextProperty(
  956. pCertContext,
  957. CERT_KEY_PROV_INFO_PROP_ID,
  958. NULL,
  959. &cbData
  960. );
  961. if (b) {
  962. pCryptKeyProvInfo = (PCRYPT_KEY_PROV_INFO)LsapAllocateLsaHeap( cbData );
  963. if (pCryptKeyProvInfo != NULL) {
  964. b = CertGetCertificateContextProperty(
  965. pCertContext,
  966. CERT_KEY_PROV_INFO_PROP_ID,
  967. pCryptKeyProvInfo,
  968. &cbData
  969. );
  970. if (!b) {
  971. LsapFreeLsaHeap( pCryptKeyProvInfo );
  972. pCryptKeyProvInfo = NULL;
  973. }
  974. } else {
  975. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  976. }
  977. }
  978. return ( pCryptKeyProvInfo );
  979. }
  980. DWORD
  981. EfsCreateNewCache(
  982. IN OUT PEFS_USER_INFO pEfsUserInfo,
  983. IN PCCERT_CONTEXT pCertContext
  984. )
  985. /*++
  986. Routine Description:
  987. This routine will create a cache node.
  988. Arguments:
  989. pEfsUserInfo - User Information
  990. pCertContext - Supplies a pointer to a certificate context.
  991. Return Value:
  992. Returns Win32 error code.
  993. --*/
  994. {
  995. PBYTE pbHash;
  996. DWORD cbHash;
  997. HCRYPTKEY hLocalKey = NULL;
  998. HCRYPTPROV hLocalProv = NULL;
  999. DWORD rc = ERROR_SUCCESS;
  1000. LPWSTR LocalContainerName = NULL;
  1001. LPWSTR LocalProviderName = NULL;
  1002. LPWSTR LocalDisplayInformation = NULL;
  1003. PUSER_CACHE pCacheNode;
  1004. PCRYPT_KEY_PROV_INFO pCryptKeyProvInfo = GetKeyProvInfo( pCertContext );
  1005. if (pCryptKeyProvInfo != NULL) {
  1006. //
  1007. // Copy out the container name and provider name if requested.
  1008. //
  1009. if (pCryptKeyProvInfo->pwszContainerName) {
  1010. LocalContainerName = (LPWSTR)LsapAllocateLsaHeap( wcslen(pCryptKeyProvInfo->pwszContainerName) * sizeof( WCHAR ) + sizeof( UNICODE_NULL ));
  1011. if (LocalContainerName != NULL) {
  1012. wcscpy( LocalContainerName, pCryptKeyProvInfo->pwszContainerName );
  1013. } else {
  1014. rc = ERROR_NOT_ENOUGH_MEMORY;
  1015. }
  1016. }
  1017. if ((ERROR_SUCCESS == rc) && pCryptKeyProvInfo->pwszProvName) {
  1018. LocalProviderName = (LPWSTR)LsapAllocateLsaHeap( wcslen(pCryptKeyProvInfo->pwszProvName) * sizeof( WCHAR ) + sizeof( UNICODE_NULL ));
  1019. if (LocalProviderName != NULL) {
  1020. wcscpy( LocalProviderName, pCryptKeyProvInfo->pwszProvName );
  1021. }
  1022. else {
  1023. rc = ERROR_NOT_ENOUGH_MEMORY;
  1024. }
  1025. }
  1026. if ((ERROR_SUCCESS == rc) && !(LocalDisplayInformation = EfspGetCertDisplayInformation( pCertContext ))) {
  1027. //
  1028. // At least for now, we do not accept Cert without display name
  1029. //
  1030. rc = GetLastError();
  1031. }
  1032. //
  1033. // Get the key information
  1034. //
  1035. if (ERROR_SUCCESS == rc) {
  1036. if (CryptAcquireContext( &hLocalProv, pCryptKeyProvInfo->pwszContainerName, pCryptKeyProvInfo->pwszProvName, PROV_RSA_FULL, CRYPT_SILENT)) {
  1037. if (!CryptGetUserKey(hLocalProv, AT_KEYEXCHANGE, &hLocalKey)) {
  1038. rc = GetLastError();
  1039. }
  1040. } else {
  1041. rc = GetLastError();
  1042. }
  1043. }
  1044. if (ERROR_SUCCESS == rc) {
  1045. DWORD ImpersonationError = 0;
  1046. DWORD sevRc;
  1047. //
  1048. // The cert may not be in the LM Trusted or OtherPeople store.
  1049. //
  1050. if (ERROR_SUCCESS == (sevRc = EfsAddCertToCertStore(pCertContext, OTHERPEOPLE, &ImpersonationError))) {
  1051. EfsMarkCertAddedToStore(pEfsUserInfo, CERTINLMOTHERSTORE);
  1052. } else {
  1053. if (ImpersonationError) {
  1054. //
  1055. // Got in trouble. We could not impersonate back.
  1056. //
  1057. ASSERT(FALSE);
  1058. rc = sevRc;
  1059. }
  1060. }
  1061. if (!ImpersonationError) {
  1062. PSID pUserID = NULL;
  1063. ULONG SidLength = 0;
  1064. pCacheNode = (PUSER_CACHE) LsapAllocateLsaHeap(sizeof(USER_CACHE));
  1065. pbHash = GetCertHashFromCertContext(
  1066. pCertContext,
  1067. &cbHash
  1068. );
  1069. if (pEfsUserInfo->InterActiveUser != USER_INTERACTIVE) {
  1070. SidLength = RtlLengthSid(pEfsUserInfo->pTokenUser->User.Sid);
  1071. pUserID = (PSID) LsapAllocateLsaHeap(SidLength);
  1072. }
  1073. if (pCacheNode && pbHash && ((SidLength == 0) || (pUserID))) {
  1074. NTSTATUS Status = STATUS_SUCCESS;
  1075. memset( pCacheNode, 0, sizeof( USER_CACHE ));
  1076. if (pUserID) {
  1077. Status = RtlCopySid(
  1078. SidLength,
  1079. pUserID,
  1080. pEfsUserInfo->pTokenUser->User.Sid
  1081. );
  1082. }
  1083. if (NT_SUCCESS( Status ) && NT_SUCCESS( Status = NtQuerySystemTime(&(pCacheNode->TimeStamp)))){
  1084. if (EfspInitUserCacheNode(
  1085. pCacheNode,
  1086. pUserID,
  1087. pbHash,
  1088. cbHash,
  1089. LocalContainerName,
  1090. LocalProviderName,
  1091. LocalDisplayInformation,
  1092. &(pCertContext->pCertInfo->NotAfter),
  1093. hLocalKey,
  1094. hLocalProv,
  1095. pUserID? NULL: &(pEfsUserInfo->AuthId),
  1096. CERT_VALIDATED
  1097. )){
  1098. //
  1099. // Cache node created and ready for use. Do not delete or close the info
  1100. // we just got.
  1101. //
  1102. LocalContainerName = NULL;
  1103. LocalProviderName = NULL;
  1104. LocalDisplayInformation = NULL;
  1105. hLocalKey = NULL;
  1106. hLocalProv = NULL;
  1107. pEfsUserInfo->pUserCache = pCacheNode;
  1108. pCacheNode = NULL;
  1109. } else {
  1110. rc = GetLastError();
  1111. }
  1112. } else {
  1113. rc = RtlNtStatusToDosError( Status );
  1114. }
  1115. } else {
  1116. rc = ERROR_NOT_ENOUGH_MEMORY;
  1117. }
  1118. if (ERROR_SUCCESS != rc) {
  1119. if (pCacheNode) {
  1120. LsapFreeLsaHeap(pCacheNode);
  1121. pCacheNode = NULL;
  1122. }
  1123. if (pbHash) {
  1124. LsapFreeLsaHeap(pbHash);
  1125. pbHash = NULL;
  1126. }
  1127. if (pUserID) {
  1128. LsapFreeLsaHeap(pUserID);
  1129. pUserID = NULL;
  1130. }
  1131. }
  1132. }
  1133. }
  1134. if (ERROR_SUCCESS != rc) {
  1135. if (LocalContainerName) {
  1136. LsapFreeLsaHeap(LocalContainerName);
  1137. }
  1138. if (LocalProviderName) {
  1139. LsapFreeLsaHeap(LocalProviderName);
  1140. }
  1141. if (LocalDisplayInformation) {
  1142. LsapFreeLsaHeap(LocalDisplayInformation);
  1143. }
  1144. if (hLocalKey) {
  1145. CryptDestroyKey( hLocalKey );
  1146. }
  1147. if (hLocalProv) {
  1148. CryptReleaseContext( hLocalProv, 0 );
  1149. }
  1150. }
  1151. LsapFreeLsaHeap( pCryptKeyProvInfo );
  1152. }
  1153. return rc;
  1154. }