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.

2204 lines
53 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1997-1999 Microsoft Corporation
  4. //
  5. // File: tlscert.cpp
  6. //
  7. // Contents: Certificate routines
  8. //
  9. // History:
  10. //
  11. //---------------------------------------------------------------------------
  12. #include "pch.cpp"
  13. #include "server.h"
  14. #include "globals.h"
  15. #include "tlscert.h"
  16. #include "gencert.h"
  17. #define MAX_KEY_CONTAINER_LENGTH 25
  18. #ifdef IGNORE_EXPIRATION
  19. #define LICENSE_EXPIRATION_IGNORE L"SOFTWARE\\Microsoft\\TermServLicensing\\IgnoreLicenseExpiration"
  20. #endif
  21. //////////////////////////////////////////////////////////////////
  22. BOOL
  23. VerifyCertValidity(
  24. IN PCCERT_CONTEXT pCertContext
  25. )
  26. /*++
  27. --*/
  28. {
  29. BOOL bValid;
  30. FILETIME ft;
  31. #ifdef IGNORE_EXPIRATION
  32. LONG lRet;
  33. HKEY hKey = NULL;
  34. lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  35. LICENSE_EXPIRATION_IGNORE ,
  36. 0,
  37. KEY_READ ,
  38. &hKey );
  39. if( ERROR_SUCCESS == lRet )
  40. {
  41. bValid = TRUE;
  42. goto cleanup;
  43. }
  44. #endif
  45. GetSystemTimeAsFileTime(&ft);
  46. bValid = (CompareFileTime(
  47. &ft,
  48. &(pCertContext->pCertInfo->NotAfter)
  49. ) < 0);
  50. #ifdef IGNORE_EXPIRATION
  51. cleanup:
  52. if(hKey)
  53. {
  54. RegCloseKey(hKey);
  55. }
  56. #endif
  57. return bValid;
  58. }
  59. //////////////////////////////////////////////////////////////////
  60. void
  61. DeleteBadIssuerCertFromStore(
  62. IN HCERTSTORE hCertStore,
  63. IN PCCERT_CONTEXT pSubjectContext
  64. )
  65. /*++
  66. --*/
  67. {
  68. PCCERT_CONTEXT pCertIssuer = NULL;
  69. DWORD dwFlags;
  70. DWORD dwStatus;
  71. BOOL bExpiredCert = FALSE;
  72. do {
  73. dwFlags = CERT_STORE_SIGNATURE_FLAG;
  74. pCertIssuer = CertGetIssuerCertificateFromStore(
  75. hCertStore,
  76. pSubjectContext,
  77. NULL,
  78. &dwFlags
  79. );
  80. if(pCertIssuer == NULL)
  81. {
  82. // can't find issuer certificate
  83. break;
  84. }
  85. bExpiredCert = (VerifyCertValidity(pCertIssuer) == FALSE);
  86. if(dwFlags != 0 || bExpiredCert == TRUE)
  87. {
  88. CertDeleteCertificateFromStore(pCertIssuer);
  89. }
  90. else
  91. {
  92. break;
  93. }
  94. } while(TRUE);
  95. return;
  96. }
  97. //////////////////////////////////////////////////////////////////
  98. PCCERT_CONTEXT
  99. GetIssuerCertificateFromStore(
  100. IN HCERTSTORE hCertStore,
  101. IN PCCERT_CONTEXT pSubjectContext,
  102. IN BOOL bDelBadIssuerCert
  103. )
  104. /*++
  105. --*/
  106. {
  107. PCCERT_CONTEXT pCertIssuer = NULL;
  108. DWORD dwFlags;
  109. BOOL bExpiredCert = FALSE;
  110. SetLastError(ERROR_SUCCESS);
  111. do {
  112. dwFlags = CERT_STORE_SIGNATURE_FLAG;
  113. pCertIssuer = CertGetIssuerCertificateFromStore(
  114. hCertStore,
  115. pSubjectContext,
  116. pCertIssuer,
  117. &dwFlags
  118. );
  119. if(pCertIssuer == NULL)
  120. {
  121. // can't find issuer certificate
  122. break;
  123. }
  124. bExpiredCert = (VerifyCertValidity(pCertIssuer) == FALSE);
  125. if(dwFlags == 0 && bExpiredCert == FALSE)
  126. {
  127. //
  128. // find a good issuer's certificate
  129. //
  130. break;
  131. }
  132. //if(pCertIssuer != NULL)
  133. //{
  134. // CertFreeCertificateContext(pCertIssuer);
  135. //}
  136. } while(TRUE);
  137. if(bDelBadIssuerCert == TRUE && pCertIssuer)
  138. {
  139. //
  140. // Only delete bad certificate if we can't find a good one.
  141. //
  142. DeleteBadIssuerCertFromStore(
  143. hCertStore,
  144. pSubjectContext
  145. );
  146. }
  147. if(bExpiredCert == TRUE && pCertIssuer == NULL)
  148. {
  149. SetLastError(TLS_E_EXPIRE_CERT);
  150. }
  151. return pCertIssuer;
  152. }
  153. //////////////////////////////////////////////////////////////////////////
  154. DWORD
  155. TLSVerifyCertChain(
  156. IN HCRYPTPROV hCryptProv,
  157. IN HCERTSTORE hCertStore,
  158. IN PCCERT_CONTEXT pSubjectContext,
  159. OUT FILETIME* pftMinExpireTime
  160. )
  161. /*++
  162. --*/
  163. {
  164. DWORD dwStatus = ERROR_SUCCESS;
  165. PCCERT_CONTEXT pCertIssuer = NULL;
  166. PCCERT_CONTEXT pCurrentSubject;
  167. //
  168. // Increase reference count on Subject context.
  169. pCurrentSubject = CertDuplicateCertificateContext(
  170. pSubjectContext
  171. );
  172. while( TRUE )
  173. {
  174. pCertIssuer = GetIssuerCertificateFromStore(
  175. hCertStore,
  176. pCurrentSubject,
  177. FALSE
  178. );
  179. if(!pCertIssuer)
  180. {
  181. // Could not find issuer's certificate or
  182. // a good issuer's certificate
  183. dwStatus = GetLastError();
  184. break;
  185. }
  186. if(CompareFileTime(pftMinExpireTime, &(pCertIssuer->pCertInfo->NotAfter)) > 0)
  187. {
  188. *pftMinExpireTime = pCertIssuer->pCertInfo->NotAfter;
  189. }
  190. if(pCurrentSubject != NULL)
  191. {
  192. CertFreeCertificateContext(pCurrentSubject);
  193. }
  194. pCurrentSubject = pCertIssuer;
  195. }
  196. if(dwStatus == CRYPT_E_SELF_SIGNED)
  197. {
  198. dwStatus = ERROR_SUCCESS;
  199. }
  200. if(pCertIssuer != NULL)
  201. {
  202. CertFreeCertificateContext(pCertIssuer);
  203. }
  204. if(pCurrentSubject != NULL)
  205. {
  206. CertFreeCertificateContext(pCurrentSubject);
  207. }
  208. SetLastError(dwStatus);
  209. return dwStatus;
  210. }
  211. //////////////////////////////////////////////////////////////////
  212. DWORD
  213. VerifyLicenseServerCertificate(
  214. IN HCRYPTPROV hCryptProv,
  215. IN PCCERT_CONTEXT pCertContext,
  216. IN DWORD dwCertType
  217. )
  218. /*++
  219. --*/
  220. {
  221. BOOL bFound=FALSE;
  222. PCERT_INFO pCertInfo = pCertContext->pCertInfo;
  223. PCERT_EXTENSION pCertExtension=pCertInfo->rgExtension;
  224. PCERT_PUBLIC_KEY_INFO pbPublicKey=NULL;
  225. DWORD dwStatus = ERROR_SUCCESS;
  226. DWORD dwSize = 0;
  227. //
  228. // Must have a CH root extension.
  229. //
  230. for(DWORD i=0;
  231. i < pCertInfo->cExtension && bFound == FALSE;
  232. i++, pCertExtension++)
  233. {
  234. bFound=(strcmp(pCertExtension->pszObjId, szOID_PKIX_HYDRA_CERT_ROOT) == 0);
  235. }
  236. if(bFound == TRUE)
  237. {
  238. //
  239. // Public Key must be the same
  240. //
  241. dwStatus = TLSExportPublicKey(
  242. hCryptProv,
  243. dwCertType,
  244. &dwSize,
  245. &pbPublicKey
  246. );
  247. if(dwStatus == ERROR_SUCCESS)
  248. {
  249. bFound = CertComparePublicKeyInfo(
  250. X509_ASN_ENCODING,
  251. pbPublicKey,
  252. &(pCertContext->pCertInfo->SubjectPublicKeyInfo)
  253. );
  254. if(bFound == FALSE)
  255. {
  256. dwStatus = TLS_E_MISMATCHPUBLICKEY;
  257. }
  258. }
  259. }
  260. else
  261. {
  262. dwStatus = TLS_E_INVALIDLSCERT;
  263. }
  264. FreeMemory(pbPublicKey);
  265. return dwStatus;
  266. }
  267. //////////////////////////////////////////////////////////////////////
  268. DWORD
  269. TLSVerifyServerCertAndChain(
  270. IN HCRYPTPROV hCryptProv,
  271. IN HCERTSTORE hCertStore,
  272. IN DWORD dwCertType,
  273. IN PBYTE pbCert,
  274. IN DWORD cbCert,
  275. IN OUT FILETIME* pExpiredTime
  276. )
  277. /*++
  278. --*/
  279. {
  280. DWORD dwStatus = ERROR_SUCCESS;
  281. PCCERT_CONTEXT pCertContext = NULL;
  282. //
  283. // Verify License Server's own certificate
  284. //
  285. pCertContext = CertCreateCertificateContext(
  286. X509_ASN_ENCODING,
  287. pbCert,
  288. cbCert
  289. );
  290. if(pCertContext == NULL)
  291. {
  292. dwStatus = GetLastError();
  293. goto cleanup;
  294. }
  295. //
  296. // Verify License Server's certificate first
  297. //
  298. dwStatus = VerifyLicenseServerCertificate(
  299. hCryptProv,
  300. pCertContext,
  301. dwCertType
  302. );
  303. if(dwStatus != ERROR_SUCCESS)
  304. {
  305. goto cleanup;
  306. }
  307. //
  308. // Verify Certificate Chain
  309. //
  310. dwStatus = TLSVerifyCertChain(
  311. hCryptProv,
  312. hCertStore,
  313. pCertContext,
  314. pExpiredTime
  315. );
  316. if(dwStatus != ERROR_SUCCESS)
  317. {
  318. goto cleanup;
  319. }
  320. cleanup:
  321. if(pCertContext != NULL)
  322. {
  323. CertFreeCertificateContext(pCertContext);
  324. }
  325. return dwStatus;
  326. }
  327. //////////////////////////////////////////////////////////////////
  328. DWORD
  329. TLSValidateServerCertficates(
  330. IN HCRYPTPROV hCryptProv,
  331. IN HCERTSTORE hCertStore,
  332. IN PBYTE pbSignCert,
  333. IN DWORD cbSignCert,
  334. IN PBYTE pbExchCert,
  335. IN DWORD cbExchCert,
  336. OUT FILETIME* pftExpireTime
  337. )
  338. /*++
  339. --*/
  340. {
  341. #if ENFORCE_LICENSING
  342. DWORD dwStatus;
  343. pftExpireTime->dwLowDateTime = 0xFFFFFFFF;
  344. pftExpireTime->dwHighDateTime = 0xFFFFFFFF;
  345. dwStatus = TLSVerifyServerCertAndChain(
  346. hCryptProv,
  347. hCertStore,
  348. AT_SIGNATURE,
  349. pbSignCert,
  350. cbSignCert,
  351. pftExpireTime
  352. );
  353. if(TLS_ERROR(dwStatus) == TRUE)
  354. {
  355. goto cleanup;
  356. }
  357. dwStatus = TLSVerifyServerCertAndChain(
  358. hCryptProv,
  359. hCertStore,
  360. AT_KEYEXCHANGE,
  361. pbExchCert,
  362. cbExchCert,
  363. pftExpireTime
  364. );
  365. cleanup:
  366. return dwStatus;
  367. #else
  368. return ERROR_SUCCESS;
  369. #endif
  370. }
  371. //////////////////////////////////////////////////////////////////
  372. DWORD
  373. TLSDestroyCryptContext(
  374. HCRYPTPROV hCryptProv
  375. )
  376. /*++
  377. --*/
  378. {
  379. DWORD dwStatus = E_FAIL;
  380. BOOL bSuccess;
  381. PBYTE pbData = NULL;
  382. DWORD cbData = 0;
  383. if(hCryptProv == NULL)
  384. {
  385. SetLastError(dwStatus = ERROR_INVALID_PARAMETER);
  386. goto cleanup;
  387. }
  388. //
  389. // Get the container name.
  390. //
  391. bSuccess = CryptGetProvParam(
  392. hCryptProv,
  393. PP_CONTAINER,
  394. NULL,
  395. &cbData,
  396. 0
  397. );
  398. if(bSuccess != FALSE)
  399. {
  400. dwStatus = GetLastError();
  401. goto cleanup;
  402. }
  403. pbData = (PBYTE)AllocateMemory(cbData + sizeof(TCHAR));
  404. if(pbData == NULL)
  405. {
  406. dwStatus = GetLastError();
  407. goto cleanup;
  408. }
  409. bSuccess = CryptGetProvParam(
  410. hCryptProv,
  411. PP_CONTAINER,
  412. pbData,
  413. &cbData,
  414. 0
  415. );
  416. if(bSuccess == FALSE)
  417. {
  418. dwStatus = GetLastError();
  419. goto cleanup;
  420. }
  421. //
  422. // Release the context
  423. //
  424. bSuccess = CryptReleaseContext(
  425. hCryptProv,
  426. 0
  427. );
  428. if(bSuccess == FALSE)
  429. {
  430. dwStatus = GetLastError();
  431. goto cleanup;
  432. }
  433. //
  434. // Delete key set
  435. //
  436. bSuccess = CryptAcquireContext(
  437. &hCryptProv,
  438. (LPCTSTR)pbData,
  439. DEFAULT_CSP,
  440. PROVIDER_TYPE,
  441. CRYPT_DELETEKEYSET
  442. );
  443. if(bSuccess == FALSE)
  444. {
  445. dwStatus = GetLastError();
  446. }
  447. cleanup:
  448. FreeMemory(pbData);
  449. return dwStatus;
  450. }
  451. //////////////////////////////////////////////////////////////////
  452. DWORD
  453. InitCryptoProv(
  454. LPCTSTR pszKeyContainer,
  455. HCRYPTPROV* phCryptProv
  456. )
  457. /*++
  458. --*/
  459. {
  460. DWORD dwStatus = ERROR_SUCCESS;
  461. TCHAR szKeyContainer[MAX_KEY_CONTAINER_LENGTH+1];
  462. LPCTSTR pszContainer;
  463. if(pszKeyContainer == NULL)
  464. {
  465. //
  466. // Randomly create a key container
  467. //
  468. memset(szKeyContainer, 0, sizeof(szKeyContainer));
  469. _sntprintf(
  470. szKeyContainer,
  471. MAX_KEY_CONTAINER_LENGTH,
  472. _TEXT("TlsContainer%d"),
  473. GetCurrentThreadId()
  474. );
  475. pszContainer = szKeyContainer;
  476. }
  477. else
  478. {
  479. pszContainer = pszKeyContainer;
  480. }
  481. //
  482. // Delete the key container, ignore error here
  483. //
  484. CryptAcquireContext(
  485. phCryptProv,
  486. pszContainer,
  487. DEFAULT_CSP,
  488. PROVIDER_TYPE,
  489. CRYPT_DELETEKEYSET
  490. );
  491. //
  492. // Re-create key container
  493. //
  494. if(!CryptAcquireContext(
  495. phCryptProv,
  496. pszContainer,
  497. DEFAULT_CSP,
  498. PROVIDER_TYPE,
  499. 0))
  500. {
  501. // Create default key container.
  502. if(!CryptAcquireContext(
  503. phCryptProv,
  504. pszContainer,
  505. DEFAULT_CSP,
  506. PROVIDER_TYPE,
  507. CRYPT_NEWKEYSET))
  508. {
  509. dwStatus = GetLastError();
  510. }
  511. }
  512. return dwStatus;
  513. }
  514. //////////////////////////////////////////////////////////////////
  515. DWORD
  516. TLSLoadSavedCryptKeyFromLsa(
  517. OUT PBYTE* ppbSignKey,
  518. OUT PDWORD pcbSignKey,
  519. OUT PBYTE* ppbExchKey,
  520. OUT PDWORD pcbExchKey
  521. )
  522. /*++
  523. ++*/
  524. {
  525. DWORD dwStatus;
  526. PBYTE pbSKey = NULL;
  527. DWORD cbSKey = 0;
  528. PBYTE pbEKey = NULL;
  529. DWORD cbEKey = 0;
  530. dwStatus = RetrieveKey(
  531. LSERVER_LSA_PRIVATEKEY_EXCHANGE,
  532. &pbEKey,
  533. &cbEKey
  534. );
  535. if(dwStatus == ERROR_SUCCESS)
  536. {
  537. dwStatus = RetrieveKey(
  538. LSERVER_LSA_PRIVATEKEY_SIGNATURE,
  539. &pbSKey,
  540. &cbSKey
  541. );
  542. }
  543. if(dwStatus != ERROR_SUCCESS)
  544. {
  545. if(pbEKey != NULL)
  546. {
  547. LocalFree(pbEKey);
  548. }
  549. if(pbSKey != NULL)
  550. {
  551. LocalFree(pbSKey);
  552. }
  553. }
  554. else
  555. {
  556. *ppbSignKey = pbSKey;
  557. *pcbSignKey = cbEKey;
  558. *ppbExchKey = pbEKey;
  559. *pcbExchKey = cbEKey;
  560. }
  561. return dwStatus;
  562. }
  563. //////////////////////////////////////////////////////////////////
  564. DWORD
  565. TLSSaveCryptKeyToLsa(
  566. IN PBYTE pbSignKey,
  567. IN DWORD cbSignKey,
  568. IN PBYTE pbExchKey,
  569. IN DWORD cbExchKey
  570. )
  571. /*++
  572. --*/
  573. {
  574. DWORD dwStatus;
  575. //
  576. // Save the key to LSA.
  577. //
  578. dwStatus = StoreKey(
  579. LSERVER_LSA_PRIVATEKEY_SIGNATURE,
  580. pbSignKey,
  581. cbSignKey
  582. );
  583. if(dwStatus == ERROR_SUCCESS)
  584. {
  585. dwStatus = StoreKey(
  586. LSERVER_LSA_PRIVATEKEY_EXCHANGE,
  587. pbExchKey,
  588. cbExchKey
  589. );
  590. }
  591. return dwStatus;
  592. }
  593. /////////////////////////////////////////////////////////////////////////////
  594. DWORD
  595. TLSCryptGenerateNewKeys(
  596. OUT PBYTE* pbSignKey,
  597. OUT DWORD* cbSignKey,
  598. OUT PBYTE* pbExchKey,
  599. OUT DWORD* cbExchKey
  600. )
  601. /*++
  602. Abstract:
  603. Generate a new pair of public/private key. First randomly create
  604. a key container and use it to create new keys.
  605. Parameters:
  606. *pbSignKey : Pointer to PBYTE to receive new signature key.
  607. *cbSignKey : Pointer to DWORD to receive size of new sign. key.
  608. *pbExchKey : Pointer to PBYTE to receive new exchange key.
  609. *cbExchKey : Pointer to DWORD to receive size of new exchange key.
  610. Return:
  611. ERROR_SUCCESS or CRYPTO Error Code.
  612. --*/
  613. {
  614. TCHAR szKeyContainer[MAX_KEY_CONTAINER_LENGTH+1];
  615. HCRYPTPROV hCryptProv = NULL;
  616. HCRYPTKEY hSignKey = NULL;
  617. HCRYPTKEY hExchKey = NULL;
  618. DWORD dwStatus;
  619. *pbSignKey = NULL;
  620. *pbExchKey = NULL;
  621. //
  622. // Randomly create a key container
  623. //
  624. memset(szKeyContainer, 0, sizeof(szKeyContainer));
  625. _sntprintf(
  626. szKeyContainer,
  627. MAX_KEY_CONTAINER_LENGTH,
  628. _TEXT("TlsContainer%d"),
  629. GetCurrentThreadId()
  630. );
  631. //
  632. // Delete this key container, ignore error.
  633. //
  634. CryptAcquireContext(
  635. &hCryptProv,
  636. szKeyContainer,
  637. DEFAULT_CSP,
  638. PROVIDER_TYPE,
  639. CRYPT_DELETEKEYSET
  640. );
  641. //
  642. // Open a default key container
  643. //
  644. if(!CryptAcquireContext(
  645. &hCryptProv,
  646. szKeyContainer,
  647. DEFAULT_CSP,
  648. PROVIDER_TYPE,
  649. CRYPT_NEWKEYSET
  650. ))
  651. {
  652. TLSLogEvent(
  653. EVENTLOG_ERROR_TYPE,
  654. TLS_E_GENERATEKEYS,
  655. TLS_E_CRYPT_ACQUIRE_CONTEXT,
  656. dwStatus = GetLastError()
  657. );
  658. goto cleanup;
  659. }
  660. //
  661. // Generate a signature public/private key pair
  662. //
  663. if(!CryptGetUserKey(hCryptProv, AT_SIGNATURE, &hSignKey))
  664. {
  665. dwStatus=GetLastError();
  666. if( GetLastError() != NTE_NO_KEY ||
  667. !CryptGenKey(hCryptProv, AT_SIGNATURE, CRYPT_EXPORTABLE, &hSignKey))
  668. {
  669. TLSLogEvent(
  670. EVENTLOG_ERROR_TYPE,
  671. TLS_E_GENERATEKEYS,
  672. TLS_E_CRYPT_CREATE_KEY,
  673. dwStatus=GetLastError()
  674. );
  675. goto cleanup;
  676. }
  677. }
  678. dwStatus = ERROR_SUCCESS;
  679. //
  680. // export the public/private key of signature key
  681. //
  682. if( !CryptExportKey(hSignKey, NULL, PRIVATEKEYBLOB, 0, *pbSignKey, cbSignKey) &&
  683. GetLastError() != ERROR_MORE_DATA)
  684. {
  685. TLSLogEvent(
  686. EVENTLOG_ERROR_TYPE,
  687. TLS_E_GENERATEKEYS,
  688. TLS_E_EXPORT_KEY,
  689. dwStatus=GetLastError()
  690. );
  691. goto cleanup;
  692. }
  693. *pbSignKey=(PBYTE)AllocateMemory(*cbSignKey);
  694. if(*pbSignKey == NULL)
  695. {
  696. TLSLogErrorEvent(TLS_E_ALLOCATE_MEMORY);
  697. dwStatus=GetLastError();
  698. goto cleanup;
  699. }
  700. if(!CryptExportKey(hSignKey, NULL, PRIVATEKEYBLOB, 0, *pbSignKey, cbSignKey))
  701. {
  702. TLSLogEvent(
  703. EVENTLOG_ERROR_TYPE,
  704. TLS_E_GENERATEKEYS,
  705. TLS_E_EXPORT_KEY,
  706. dwStatus=GetLastError()
  707. );
  708. goto cleanup;
  709. }
  710. //
  711. // Generate a exchange public/private key pair
  712. if(!CryptGetUserKey(hCryptProv, AT_KEYEXCHANGE, &hExchKey))
  713. {
  714. dwStatus=GetLastError();
  715. if( GetLastError() != NTE_NO_KEY ||
  716. !CryptGenKey(hCryptProv, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, &hExchKey))
  717. {
  718. TLSLogEvent(
  719. EVENTLOG_ERROR_TYPE,
  720. TLS_E_GENERATEKEYS,
  721. TLS_E_CRYPT_CREATE_KEY,
  722. dwStatus=GetLastError()
  723. );
  724. goto cleanup;
  725. }
  726. }
  727. dwStatus = ERROR_SUCCESS;
  728. //
  729. // export the public/private key of exchange key
  730. //
  731. if( !CryptExportKey(hExchKey, NULL, PRIVATEKEYBLOB, 0, *pbExchKey, cbExchKey) &&
  732. GetLastError() != ERROR_MORE_DATA)
  733. {
  734. TLSLogEvent(
  735. EVENTLOG_ERROR_TYPE,
  736. TLS_E_GENERATEKEYS,
  737. TLS_E_EXPORT_KEY,
  738. dwStatus=GetLastError()
  739. );
  740. goto cleanup;
  741. }
  742. *pbExchKey=(PBYTE)AllocateMemory(*cbExchKey);
  743. if(*pbExchKey == NULL)
  744. {
  745. TLSLogErrorEvent(TLS_E_ALLOCATE_MEMORY);
  746. dwStatus = GetLastError();
  747. goto cleanup;
  748. }
  749. if(!CryptExportKey(hExchKey, NULL, PRIVATEKEYBLOB, 0, *pbExchKey, cbExchKey))
  750. {
  751. TLSLogEvent(
  752. EVENTLOG_ERROR_TYPE,
  753. TLS_E_GENERATEKEYS,
  754. TLS_E_EXPORT_KEY,
  755. dwStatus=GetLastError()
  756. );
  757. goto cleanup;
  758. }
  759. cleanup:
  760. if(hSignKey != NULL)
  761. {
  762. CryptDestroyKey(hSignKey);
  763. }
  764. if(hExchKey != NULL)
  765. {
  766. CryptDestroyKey(hExchKey);
  767. }
  768. if(hCryptProv)
  769. {
  770. CryptReleaseContext(hCryptProv, 0);
  771. }
  772. hCryptProv=NULL;
  773. //
  774. // Delete key container and ignore error
  775. //
  776. CryptAcquireContext(
  777. &hCryptProv,
  778. szKeyContainer,
  779. DEFAULT_CSP,
  780. PROVIDER_TYPE,
  781. CRYPT_DELETEKEYSET
  782. );
  783. if(dwStatus != ERROR_SUCCESS)
  784. {
  785. FreeMemory(*pbSignKey);
  786. FreeMemory(*pbExchKey);
  787. }
  788. return dwStatus;
  789. }
  790. /////////////////////////////////////////////////////////////////////////////
  791. DWORD
  792. TLSImportSavedKey(
  793. IN HCRYPTPROV hCryptProv,
  794. IN PBYTE pbSignKey,
  795. IN DWORD cbSignKey,
  796. IN PBYTE pbExchKey,
  797. IN DWORD cbExchKey,
  798. OUT HCRYPTKEY* pSignKey,
  799. OUT HCRYPTKEY* pExchKey
  800. )
  801. /*
  802. */
  803. {
  804. DWORD status=ERROR_SUCCESS;
  805. if(!CryptImportKey(
  806. hCryptProv,
  807. pbSignKey,
  808. cbSignKey,
  809. NULL,
  810. 0,
  811. pSignKey
  812. ))
  813. {
  814. status = GetLastError();
  815. goto cleanup;
  816. }
  817. if(!CryptImportKey(
  818. hCryptProv,
  819. pbExchKey,
  820. cbExchKey,
  821. NULL,
  822. 0,
  823. pExchKey
  824. ))
  825. {
  826. status = GetLastError();
  827. }
  828. cleanup:
  829. if(status != ERROR_SUCCESS)
  830. {
  831. TLSLogEvent(
  832. EVENTLOG_ERROR_TYPE,
  833. TLS_E_SERVICEINIT,
  834. TLS_E_CRYPT_IMPORT_KEY,
  835. status
  836. );
  837. }
  838. return status;
  839. }
  840. /////////////////////////////////////////////////////////////////////////////
  841. DWORD
  842. TLSLoadSelfSignCertificates(
  843. IN HCRYPTPROV hCryptProv,
  844. IN PBYTE pbSPK,
  845. IN DWORD cbSPK,
  846. OUT PDWORD pcbSignCert,
  847. OUT PBYTE* ppbSignCert,
  848. OUT PDWORD pcbExchCert,
  849. OUT PBYTE* ppbExchCert
  850. )
  851. /*
  852. Abstract:
  853. Create a self-signed signature/exchange certificate.
  854. Parameters:
  855. pcbSignCert : Pointer to DWORD to receive size of sign. certificate.
  856. ppbSignCert : Pointer to PBYTE to receive self-signed sign. certificate.
  857. pcbExchCert : Pointer to DWORD to receive size of exch. certificate.
  858. ppbExchCert : Pointer to PBYTE to receive self-signed exch. certificate.
  859. Returns:
  860. */
  861. {
  862. DWORD status;
  863. DWORD dwDisposition;
  864. DWORD cbSign=0;
  865. PBYTE pbSign=NULL;
  866. DWORD cbExch=0;
  867. PBYTE pbExch=NULL;
  868. do {
  869. //
  870. // Create Signature and Exchange certificate
  871. //
  872. status=TLSCreateSelfSignCertificate(
  873. hCryptProv,
  874. AT_SIGNATURE,
  875. pbSPK,
  876. cbSPK,
  877. 0,
  878. NULL,
  879. &cbSign,
  880. &pbSign
  881. );
  882. if(status != ERROR_SUCCESS)
  883. {
  884. status=TLS_E_CREATE_SELFSIGN_CERT;
  885. break;
  886. }
  887. status=TLSCreateSelfSignCertificate(
  888. hCryptProv,
  889. AT_KEYEXCHANGE,
  890. pbSPK,
  891. cbSPK,
  892. 0,
  893. NULL,
  894. &cbExch,
  895. &pbExch
  896. );
  897. if(status != ERROR_SUCCESS)
  898. {
  899. status=TLS_E_CREATE_SELFSIGN_CERT;
  900. break;
  901. }
  902. } while(FALSE);
  903. if(status == ERROR_SUCCESS)
  904. {
  905. *pcbSignCert = cbSign;
  906. *ppbSignCert = pbSign;
  907. *pcbExchCert = cbExch;
  908. *ppbExchCert = pbExch;
  909. }
  910. else
  911. {
  912. FreeMemory(pbExch);
  913. FreeMemory(pbSign);
  914. }
  915. return status;
  916. }
  917. ////////////////////////////////////////////////////////////////
  918. DWORD
  919. TLSLoadCHEndosedCertificate(
  920. PDWORD pcbSignCert,
  921. PBYTE* ppbSignCert,
  922. PDWORD pcbExchCert,
  923. PBYTE* ppbExchCert
  924. )
  925. /*
  926. */
  927. {
  928. LONG status;
  929. #if ENFORCE_LICENSING
  930. DWORD cbSign=0;
  931. PBYTE pbSign=NULL;
  932. DWORD cbExch=0;
  933. PBYTE pbExch=NULL;
  934. //
  935. // look into registry to see if our certificate is there
  936. //
  937. HKEY hKey=NULL;
  938. LPTSTR lpSubkey=LSERVER_SERVER_CERTIFICATE_REGKEY;
  939. do {
  940. status=RegOpenKeyEx(
  941. HKEY_LOCAL_MACHINE,
  942. lpSubkey,
  943. 0,
  944. KEY_ALL_ACCESS,
  945. &hKey
  946. );
  947. if(status != ERROR_SUCCESS)
  948. {
  949. break;
  950. }
  951. //
  952. // Load Signature certificate
  953. //
  954. status = RegQueryValueEx(
  955. hKey,
  956. LSERVER_SIGNATURE_CERT_KEY,
  957. NULL,
  958. NULL,
  959. NULL,
  960. &cbSign
  961. );
  962. if(status != ERROR_MORE_DATA && status != ERROR_SUCCESS)
  963. {
  964. break;
  965. }
  966. if(!(pbSign=(PBYTE)AllocateMemory(cbSign)))
  967. {
  968. status = GetLastError();
  969. break;
  970. }
  971. status = RegQueryValueEx(
  972. hKey,
  973. LSERVER_SIGNATURE_CERT_KEY,
  974. NULL,
  975. NULL,
  976. pbSign,
  977. &cbSign
  978. );
  979. if(status != ERROR_SUCCESS)
  980. {
  981. break;
  982. }
  983. //
  984. // Load Exchange certificate
  985. //
  986. status = RegQueryValueEx(
  987. hKey,
  988. LSERVER_EXCHANGE_CERT_KEY,
  989. NULL,
  990. NULL,
  991. NULL,
  992. &cbExch
  993. );
  994. if(status != ERROR_MORE_DATA && status != ERROR_SUCCESS)
  995. {
  996. break;
  997. }
  998. if(!(pbExch=(PBYTE)AllocateMemory(cbExch)))
  999. {
  1000. status = GetLastError();
  1001. break;
  1002. }
  1003. status = RegQueryValueEx(
  1004. hKey,
  1005. LSERVER_EXCHANGE_CERT_KEY,
  1006. NULL,
  1007. NULL,
  1008. pbExch,
  1009. &cbExch
  1010. );
  1011. if(status != ERROR_SUCCESS)
  1012. {
  1013. break;
  1014. }
  1015. } while(FALSE);
  1016. //
  1017. // Must have both certificate
  1018. //
  1019. if(status == ERROR_SUCCESS && pbExch && pbSign)
  1020. {
  1021. *pcbSignCert = cbSign;
  1022. *ppbSignCert = pbSign;
  1023. *pcbExchCert = cbExch;
  1024. *ppbExchCert = pbExch;
  1025. }
  1026. else
  1027. {
  1028. FreeMemory(pbExch);
  1029. FreeMemory(pbSign);
  1030. status = TLS_E_NO_CERTIFICATE;
  1031. }
  1032. if(hKey)
  1033. {
  1034. RegCloseKey(hKey);
  1035. }
  1036. #else
  1037. //
  1038. // Non enfoce version always return no certificate
  1039. //
  1040. status = TLS_E_NO_CERTIFICATE;
  1041. #endif
  1042. return status;
  1043. }
  1044. /////////////////////////////////////////////////////////////////////////////
  1045. DWORD
  1046. TLSInstallLsCertificate(
  1047. DWORD cbLsSignCert,
  1048. PBYTE pbLsSignCert,
  1049. DWORD cbLsExchCert,
  1050. PBYTE pbLsExchCert
  1051. )
  1052. /*
  1053. */
  1054. {
  1055. HKEY hKey=NULL;
  1056. LONG status=ERROR_SUCCESS;
  1057. DWORD dwDisposition;
  1058. PCCERT_CONTEXT pCertContext=NULL;
  1059. DWORD cbNameBlob=0;
  1060. LPTSTR pbNameBlob=NULL;
  1061. #if ENFORCE_LICENSING
  1062. do {
  1063. status = RegCreateKeyEx(
  1064. HKEY_LOCAL_MACHINE,
  1065. LSERVER_SERVER_CERTIFICATE_REGKEY,
  1066. 0,
  1067. NULL,
  1068. REG_OPTION_NON_VOLATILE,
  1069. KEY_ALL_ACCESS,
  1070. NULL,
  1071. &hKey,
  1072. &dwDisposition
  1073. );
  1074. if(status != ERROR_SUCCESS)
  1075. {
  1076. TLSLogEvent(
  1077. EVENTLOG_ERROR_TYPE,
  1078. TLS_E_STORELSCERTIFICATE,
  1079. TLS_E_ACCESS_REGISTRY,
  1080. status
  1081. );
  1082. break;
  1083. }
  1084. if(pbLsExchCert)
  1085. {
  1086. status = RegSetValueEx(
  1087. hKey,
  1088. LSERVER_EXCHANGE_CERT_KEY,
  1089. 0,
  1090. REG_BINARY,
  1091. pbLsExchCert,
  1092. cbLsExchCert
  1093. );
  1094. if(status != ERROR_SUCCESS)
  1095. {
  1096. TLSLogEvent(
  1097. EVENTLOG_ERROR_TYPE,
  1098. TLS_E_STORELSCERTIFICATE,
  1099. TLS_E_ACCESS_REGISTRY,
  1100. status
  1101. );
  1102. break;
  1103. }
  1104. }
  1105. if(pbLsSignCert)
  1106. {
  1107. status = RegSetValueEx(
  1108. hKey,
  1109. LSERVER_SIGNATURE_CERT_KEY,
  1110. 0,
  1111. REG_BINARY,
  1112. pbLsSignCert,
  1113. cbLsSignCert
  1114. );
  1115. if(status != ERROR_SUCCESS)
  1116. {
  1117. TLSLogEvent(
  1118. EVENTLOG_ERROR_TYPE,
  1119. TLS_E_STORELSCERTIFICATE,
  1120. TLS_E_ACCESS_REGISTRY,
  1121. status
  1122. );
  1123. break;
  1124. }
  1125. //
  1126. // extract Subject field in exchange certificate and save i registry
  1127. // When issuing new license, we need to use this as Issuer.
  1128. //
  1129. pCertContext = CertCreateCertificateContext(
  1130. X509_ASN_ENCODING,
  1131. pbLsSignCert,
  1132. cbLsSignCert
  1133. );
  1134. cbNameBlob=CertNameToStr(
  1135. X509_ASN_ENCODING,
  1136. &pCertContext->pCertInfo->Subject,
  1137. CERT_X500_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
  1138. NULL,
  1139. 0
  1140. );
  1141. if(cbNameBlob)
  1142. {
  1143. pbNameBlob=(LPTSTR)AllocateMemory((cbNameBlob+1) * sizeof(TCHAR));
  1144. if(pbNameBlob)
  1145. {
  1146. CertNameToStr(
  1147. X509_ASN_ENCODING,
  1148. &pCertContext->pCertInfo->Subject,
  1149. CERT_X500_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
  1150. pbNameBlob,
  1151. cbNameBlob
  1152. );
  1153. }
  1154. }
  1155. status = RegSetValueEx(
  1156. hKey,
  1157. LSERVER_CLIENT_CERTIFICATE_ISSUER,
  1158. 0,
  1159. REG_BINARY,
  1160. (PBYTE)pbNameBlob,
  1161. cbNameBlob+sizeof(TCHAR)
  1162. );
  1163. if(status != ERROR_SUCCESS)
  1164. {
  1165. TLSLogEvent(
  1166. EVENTLOG_ERROR_TYPE,
  1167. TLS_E_STORELSCERTIFICATE,
  1168. TLS_E_ACCESS_REGISTRY,
  1169. status
  1170. );
  1171. break;
  1172. }
  1173. }
  1174. if(hKey)
  1175. {
  1176. //
  1177. // Close registry, got error while try to load it again???
  1178. //
  1179. RegCloseKey(hKey);
  1180. hKey = NULL;
  1181. }
  1182. //
  1183. // Only reload certificate when we have both
  1184. //
  1185. if(pbLsSignCert && pbLsExchCert)
  1186. {
  1187. //
  1188. // All RPC calls are blocked.
  1189. //
  1190. FreeMemory(g_pbSignatureEncodedCert);
  1191. FreeMemory(g_pbExchangeEncodedCert);
  1192. g_cbSignatureEncodedCert = 0;
  1193. g_cbExchangeEncodedCert = 0;
  1194. //TLSLoadServerCertificate();
  1195. }
  1196. } while(FALSE);
  1197. FreeMemory(pbNameBlob);
  1198. if(pCertContext)
  1199. {
  1200. CertFreeCertificateContext(pCertContext);
  1201. }
  1202. if(hKey)
  1203. {
  1204. RegCloseKey(hKey);
  1205. }
  1206. #endif
  1207. return status;
  1208. }
  1209. ////////////////////////////////////////////////////////////////
  1210. DWORD
  1211. TLSUninstallLsCertificate()
  1212. {
  1213. HKEY hKey=NULL;
  1214. DWORD status;
  1215. status=RegOpenKeyEx(
  1216. HKEY_LOCAL_MACHINE,
  1217. LSERVER_SERVER_CERTIFICATE_REGKEY,
  1218. 0,
  1219. KEY_ALL_ACCESS,
  1220. &hKey
  1221. );
  1222. if(status == ERROR_SUCCESS)
  1223. {
  1224. //
  1225. // Ignore error
  1226. RegDeleteValue(
  1227. hKey,
  1228. LSERVER_SIGNATURE_CERT_KEY
  1229. );
  1230. RegDeleteValue(
  1231. hKey,
  1232. LSERVER_EXCHANGE_CERT_KEY
  1233. );
  1234. RegDeleteValue(
  1235. hKey,
  1236. LSERVER_CLIENT_CERTIFICATE_ISSUER
  1237. );
  1238. }
  1239. if(hKey != NULL)
  1240. {
  1241. RegCloseKey(hKey);
  1242. }
  1243. //
  1244. // Delete all certificate in registry store including all backup
  1245. // ignore error on deleting backup store.
  1246. //
  1247. TLSRegDeleteKey(
  1248. HKEY_LOCAL_MACHINE,
  1249. LSERVER_SERVER_CERTIFICATE_REGKEY_BACKUP1
  1250. );
  1251. TLSRegDeleteKey(
  1252. HKEY_LOCAL_MACHINE,
  1253. LSERVER_SERVER_CERTIFICATE_REGKEY_BACKUP2
  1254. );
  1255. status = TLSRegDeleteKey(
  1256. HKEY_LOCAL_MACHINE,
  1257. LSERVER_SERVER_CERTIFICATE_REGKEY
  1258. );
  1259. return status;
  1260. }
  1261. /////////////////////////////////////////////////////////////////////////////
  1262. DWORD
  1263. TLSInitCryptoProv(
  1264. IN LPCTSTR pszKeyContainer,
  1265. IN PBYTE pbSignKey,
  1266. IN DWORD cbSignKey,
  1267. IN PBYTE pbExchKey,
  1268. IN DWORD cbExchKey,
  1269. OUT HCRYPTPROV* phCryptProv,
  1270. OUT HCRYPTKEY* phSignKey,
  1271. OUT HCRYPTKEY* phExchKey
  1272. )
  1273. /*
  1274. Abstract:
  1275. Routine to create a clean Crypto. Prov, generate a new pair of keys and
  1276. import these keys into newly created Crypt. prov.
  1277. Parameters:
  1278. pszKeyContainer : Name of the key container.
  1279. phCryptProv : Pointer to HCRYPTPROV to receive new handle to Crypto. prov.
  1280. */
  1281. {
  1282. DWORD dwStatus;
  1283. if( pbSignKey == NULL || cbSignKey == NULL ||
  1284. pbExchKey == NULL || cbExchKey == NULL ||
  1285. phCryptProv == NULL || phSignKey == NULL ||
  1286. phExchKey == NULL )
  1287. {
  1288. SetLastError(dwStatus = ERROR_INVALID_PARAMETER);
  1289. }
  1290. else
  1291. {
  1292. //
  1293. // Initialize a clean Crypt.
  1294. //
  1295. dwStatus = InitCryptoProv(
  1296. pszKeyContainer,
  1297. phCryptProv
  1298. );
  1299. if(dwStatus == ERROR_SUCCESS)
  1300. {
  1301. //
  1302. // Import Key into Crypt.
  1303. //
  1304. dwStatus = TLSImportSavedKey(
  1305. *phCryptProv,
  1306. pbSignKey,
  1307. cbSignKey,
  1308. pbExchKey,
  1309. cbExchKey,
  1310. phSignKey,
  1311. phExchKey
  1312. );
  1313. }
  1314. }
  1315. return dwStatus;
  1316. }
  1317. //-----------------------------------------------------------
  1318. DWORD
  1319. TLSVerifyCertChainInMomory(
  1320. IN HCRYPTPROV hCryptProv,
  1321. IN PBYTE pbData,
  1322. IN DWORD cbData
  1323. )
  1324. /*++
  1325. Abstract:
  1326. Verify PKCS7 certificate chain in memory.
  1327. Parameters:
  1328. pbData : Input PKCS7 ceritifcate chain.
  1329. cbData : size of pbData
  1330. Returns:
  1331. ++*/
  1332. {
  1333. PCCERT_CONTEXT pCertContext=NULL;
  1334. PCCERT_CONTEXT pCertPrevContext=NULL;
  1335. HCERTSTORE hCertStore=NULL;
  1336. DWORD dwStatus=ERROR_SUCCESS;
  1337. DWORD dwLastVerification;
  1338. CRYPT_DATA_BLOB Serialized;
  1339. FILETIME ft;
  1340. if(hCryptProv == NULL || pbData == NULL || cbData == NULL)
  1341. {
  1342. SetLastError(dwStatus = ERROR_INVALID_PARAMETER);
  1343. goto cleanup;
  1344. }
  1345. Serialized.pbData = pbData;
  1346. Serialized.cbData = cbData;
  1347. hCertStore=CertOpenStore(
  1348. szLICENSE_BLOB_SAVEAS_TYPE,
  1349. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1350. hCryptProv,
  1351. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  1352. &Serialized
  1353. );
  1354. if(!hCertStore)
  1355. {
  1356. dwStatus=GetLastError();
  1357. goto cleanup;
  1358. }
  1359. //
  1360. // Enumerate all certificates.
  1361. //
  1362. dwStatus = ERROR_SUCCESS;
  1363. do {
  1364. pCertPrevContext = pCertContext;
  1365. pCertContext = CertEnumCertificatesInStore(
  1366. hCertStore,
  1367. pCertPrevContext
  1368. );
  1369. if(pCertContext == NULL)
  1370. {
  1371. dwStatus = GetLastError();
  1372. if(dwStatus == CRYPT_E_NOT_FOUND)
  1373. {
  1374. dwStatus = ERROR_SUCCESS;
  1375. break;
  1376. }
  1377. }
  1378. dwStatus = TLSVerifyCertChain(
  1379. hCryptProv,
  1380. hCertStore,
  1381. pCertContext,
  1382. &ft
  1383. );
  1384. } while (pCertContext != NULL && dwStatus == ERROR_SUCCESS);
  1385. cleanup:
  1386. if(pCertContext != NULL)
  1387. {
  1388. CertFreeCertificateContext(pCertContext);
  1389. }
  1390. if(hCertStore)
  1391. {
  1392. CertCloseStore(
  1393. hCertStore,
  1394. CERT_CLOSE_STORE_FORCE_FLAG
  1395. );
  1396. }
  1397. return dwStatus;
  1398. }
  1399. /////////////////////////////////////////////////////////////////////////////
  1400. DWORD
  1401. TLSRegDeleteKey(
  1402. IN HKEY hRegKey,
  1403. IN LPCTSTR pszSubKey
  1404. )
  1405. /*++
  1406. Abstract:
  1407. Recursively delete entire registry key.
  1408. Parameter:
  1409. HKEY :
  1410. pszSubKey :
  1411. Returns:
  1412. ERROR_SUCCESS or error code.
  1413. ++*/
  1414. {
  1415. DWORD dwStatus;
  1416. HKEY hSubKey = NULL;
  1417. int index;
  1418. DWORD dwNumSubKeys;
  1419. DWORD dwMaxSubKeyLength;
  1420. DWORD dwSubKeyLength;
  1421. LPTSTR pszSubKeyName = NULL;
  1422. DWORD dwMaxValueNameLen;
  1423. LPTSTR pszValueName = NULL;
  1424. DWORD dwValueNameLength;
  1425. dwStatus = RegOpenKeyEx(
  1426. hRegKey,
  1427. pszSubKey,
  1428. 0,
  1429. KEY_ALL_ACCESS,
  1430. &hSubKey
  1431. );
  1432. if(dwStatus != ERROR_SUCCESS)
  1433. {
  1434. // key does not exist
  1435. return dwStatus;
  1436. }
  1437. //
  1438. // Query number of subkeys
  1439. //
  1440. dwStatus = RegQueryInfoKey(
  1441. hSubKey,
  1442. NULL,
  1443. NULL,
  1444. NULL,
  1445. &dwNumSubKeys,
  1446. &dwMaxSubKeyLength,
  1447. NULL,
  1448. NULL,
  1449. &dwMaxValueNameLen,
  1450. NULL,
  1451. NULL,
  1452. NULL
  1453. );
  1454. if(dwStatus != ERROR_SUCCESS)
  1455. {
  1456. goto cleanup;
  1457. }
  1458. dwMaxValueNameLen++;
  1459. pszValueName = (LPTSTR)AllocateMemory(dwMaxValueNameLen * sizeof(TCHAR));
  1460. if(pszValueName == NULL)
  1461. {
  1462. goto cleanup;
  1463. }
  1464. if(dwNumSubKeys > 0)
  1465. {
  1466. // allocate buffer for subkeys.
  1467. dwMaxSubKeyLength++;
  1468. pszSubKeyName = (LPTSTR)AllocateMemory(dwMaxSubKeyLength * sizeof(TCHAR));
  1469. if(pszSubKeyName == NULL)
  1470. {
  1471. goto cleanup;
  1472. }
  1473. //for(index = 0; index < dwNumSubKeys; index++)
  1474. for(;dwStatus == ERROR_SUCCESS;)
  1475. {
  1476. // delete this subkey.
  1477. dwSubKeyLength = dwMaxSubKeyLength;
  1478. memset(pszSubKeyName, 0, dwMaxSubKeyLength * sizeof(TCHAR));
  1479. // retrieve subkey name
  1480. dwStatus = RegEnumKeyEx(
  1481. hSubKey,
  1482. (DWORD)0,
  1483. pszSubKeyName,
  1484. &dwSubKeyLength,
  1485. NULL,
  1486. NULL,
  1487. NULL,
  1488. NULL
  1489. );
  1490. if(dwStatus == ERROR_SUCCESS)
  1491. {
  1492. dwStatus = TLSRegDeleteKey( hSubKey, pszSubKeyName );
  1493. }
  1494. // ignore any error and continue on
  1495. }
  1496. }
  1497. cleanup:
  1498. for(dwStatus = ERROR_SUCCESS; pszValueName != NULL && dwStatus == ERROR_SUCCESS;)
  1499. {
  1500. dwValueNameLength = dwMaxValueNameLen;
  1501. memset(pszValueName, 0, dwMaxValueNameLen * sizeof(TCHAR));
  1502. dwStatus = RegEnumValue(
  1503. hSubKey,
  1504. 0,
  1505. pszValueName,
  1506. &dwValueNameLength,
  1507. NULL,
  1508. NULL,
  1509. NULL,
  1510. NULL
  1511. );
  1512. if(dwStatus == ERROR_SUCCESS)
  1513. {
  1514. RegDeleteValue(hSubKey, pszValueName);
  1515. }
  1516. }
  1517. // close the key before trying to delete it.
  1518. if(hSubKey != NULL)
  1519. {
  1520. RegCloseKey(hSubKey);
  1521. }
  1522. // try to delete this key, will fail if any of the subkey
  1523. // failed to delete in loop
  1524. dwStatus = RegDeleteKey(
  1525. hRegKey,
  1526. pszSubKey
  1527. );
  1528. if(pszValueName != NULL)
  1529. {
  1530. FreeMemory(pszValueName);
  1531. }
  1532. if(pszSubKeyName != NULL)
  1533. {
  1534. FreeMemory(pszSubKeyName);
  1535. }
  1536. return dwStatus;
  1537. }
  1538. /////////////////////////////////////////////////////////////////////////////
  1539. DWORD
  1540. TLSTreeCopyRegKey(
  1541. IN HKEY hSourceRegKey,
  1542. IN LPCTSTR pszSourceSubKey,
  1543. IN HKEY hDestRegKey,
  1544. IN LPCTSTR pszDestSubKey
  1545. )
  1546. /*++
  1547. Abstract:
  1548. Tree copy of a registry key to another.
  1549. Parameters:
  1550. hSourceRegKey : Source registry key.
  1551. pszSourceSubKey : Source subkey name.
  1552. hDestRegKey : Destination key.
  1553. pszDestSubKey : Destination key name
  1554. Returns:
  1555. ERROR_SUCCESS or WIN32 error code.
  1556. Note:
  1557. This routine doesn't deal with security...
  1558. ++*/
  1559. {
  1560. DWORD dwStatus;
  1561. HKEY hSourceSubKey = NULL;
  1562. HKEY hDestSubKey = NULL;
  1563. int index;
  1564. DWORD dwNumSubKeys;
  1565. DWORD dwMaxSubKeyLength;
  1566. DWORD dwSubKeyLength;
  1567. LPTSTR pszSubKeyName = NULL;
  1568. DWORD dwMaxValueNameLen;
  1569. LPTSTR pszValueName = NULL;
  1570. DWORD dwValueNameLength;
  1571. DWORD dwNumValues = 0;
  1572. DWORD dwMaxValueLength;
  1573. PBYTE pbValue = NULL;
  1574. DWORD dwDisposition;
  1575. DWORD cbSecurityDescriptor;
  1576. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  1577. //
  1578. // Open source registry key, must exist
  1579. //
  1580. dwStatus = RegOpenKeyEx(
  1581. hSourceRegKey,
  1582. pszSourceSubKey,
  1583. 0,
  1584. KEY_ALL_ACCESS,
  1585. &hSourceSubKey
  1586. );
  1587. if(dwStatus != ERROR_SUCCESS)
  1588. {
  1589. // key does not exist
  1590. goto cleanup;
  1591. }
  1592. //
  1593. // Query number of subkeys
  1594. //
  1595. dwStatus = RegQueryInfoKey(
  1596. hSourceSubKey,
  1597. NULL,
  1598. NULL,
  1599. NULL,
  1600. &dwNumSubKeys, // number of subkey
  1601. &dwMaxSubKeyLength, // max. subkey length
  1602. NULL,
  1603. &dwNumValues,
  1604. &dwMaxValueNameLen, // max. value length
  1605. &dwMaxValueLength, // max. value size.
  1606. &cbSecurityDescriptor, // size of security descriptor
  1607. NULL
  1608. );
  1609. if(dwStatus != ERROR_SUCCESS)
  1610. {
  1611. goto cleanup;
  1612. }
  1613. #if 0
  1614. //
  1615. // TODO - get this to work, currently, we don't need security
  1616. //
  1617. if(cbSecurityDescriptor > 0)
  1618. {
  1619. //
  1620. // Retrieve security descriptor for this key.
  1621. //
  1622. pSecurityDescriptor = (PSECURITY_DESCRIPTOR)AllocateMemory(cbSecurityDescriptor * sizeof(BYTE));
  1623. if(pSecurityDescriptor == NULL)
  1624. {
  1625. dwStatus = GetLastError();
  1626. goto cleanup;
  1627. }
  1628. dwStatus = RegGetKeySecurity(
  1629. hSourceSubKey,
  1630. OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
  1631. pSecurityDescriptor,
  1632. &cbSecurityDescriptor
  1633. );
  1634. if(dwStatus != ERROR_SUCCESS)
  1635. {
  1636. goto cleanup;
  1637. }
  1638. }
  1639. #endif
  1640. //
  1641. // Create destination key
  1642. //
  1643. dwStatus = RegCreateKeyEx(
  1644. hDestRegKey,
  1645. pszDestSubKey,
  1646. 0,
  1647. NULL,
  1648. REG_OPTION_NON_VOLATILE,
  1649. KEY_ALL_ACCESS,
  1650. NULL,
  1651. &hDestSubKey,
  1652. &dwDisposition
  1653. );
  1654. if(dwStatus != ERROR_SUCCESS)
  1655. {
  1656. goto cleanup;
  1657. }
  1658. #if 0
  1659. //
  1660. // TODO - get this to work, currently, we don't need security.
  1661. //
  1662. if(pSecurityDescriptor != NULL)
  1663. {
  1664. dwStatus = RegSetKeySecurity(
  1665. hDestRegKey,
  1666. OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
  1667. pSecurityDescriptor
  1668. );
  1669. if(dwStatus != ERROR_SUCCESS)
  1670. {
  1671. goto cleanup;
  1672. }
  1673. if(pSecurityDescriptor != NULL)
  1674. {
  1675. FreeMemory(pSecurityDescriptor);
  1676. pSecurityDescriptor = NULL;
  1677. }
  1678. }
  1679. #endif
  1680. //
  1681. // Copy all subkeys first, we are doing recursive so copy subkey first will
  1682. // save us some memory.
  1683. //
  1684. if(dwNumSubKeys > 0)
  1685. {
  1686. // allocate buffer for subkeys.
  1687. dwMaxSubKeyLength++;
  1688. pszSubKeyName = (LPTSTR)AllocateMemory(dwMaxSubKeyLength * sizeof(TCHAR));
  1689. if(pszSubKeyName == NULL)
  1690. {
  1691. dwStatus = GetLastError();
  1692. goto cleanup;
  1693. }
  1694. for(index = 0, dwStatus = ERROR_SUCCESS;
  1695. dwStatus == ERROR_SUCCESS;
  1696. index++)
  1697. {
  1698. dwSubKeyLength = dwMaxSubKeyLength;
  1699. memset(pszSubKeyName, 0, dwMaxSubKeyLength * sizeof(TCHAR));
  1700. // retrieve subkey name
  1701. dwStatus = RegEnumKeyEx(
  1702. hSourceSubKey,
  1703. (DWORD)index,
  1704. pszSubKeyName,
  1705. &dwSubKeyLength,
  1706. NULL,
  1707. NULL,
  1708. NULL,
  1709. NULL
  1710. );
  1711. if(dwStatus == ERROR_SUCCESS)
  1712. {
  1713. dwStatus = TLSTreeCopyRegKey(
  1714. hSourceSubKey,
  1715. pszSubKeyName,
  1716. hDestSubKey,
  1717. pszSubKeyName
  1718. );
  1719. }
  1720. }
  1721. if(dwStatus == ERROR_NO_MORE_ITEMS)
  1722. {
  1723. dwStatus = ERROR_SUCCESS;
  1724. }
  1725. }
  1726. if(pszSubKeyName != NULL)
  1727. {
  1728. FreeMemory(pszSubKeyName);
  1729. pszSubKeyName = NULL;
  1730. }
  1731. if(dwNumValues > 0)
  1732. {
  1733. //
  1734. // allocate space for value name.
  1735. //
  1736. dwMaxValueNameLen++;
  1737. pszValueName = (LPTSTR)AllocateMemory(dwMaxValueNameLen * sizeof(TCHAR));
  1738. if(pszValueName == NULL)
  1739. {
  1740. dwStatus = GetLastError();
  1741. goto cleanup;
  1742. }
  1743. //
  1744. // allocate buffer for value
  1745. //
  1746. dwMaxValueLength += 2 * sizeof(TCHAR); // in case of string
  1747. pbValue = (PBYTE)AllocateMemory(dwMaxValueLength * sizeof(BYTE));
  1748. if(pbValue == NULL)
  1749. {
  1750. dwStatus = GetLastError();
  1751. goto cleanup;
  1752. }
  1753. //
  1754. // Copy all value first
  1755. //
  1756. for(index=0, dwStatus = ERROR_SUCCESS;
  1757. pszValueName != NULL && dwStatus == ERROR_SUCCESS;
  1758. index ++)
  1759. {
  1760. DWORD dwValueType = 0;
  1761. DWORD cbValue = dwMaxValueLength;
  1762. dwValueNameLength = dwMaxValueNameLen;
  1763. memset(pszValueName, 0, dwMaxValueNameLen * sizeof(TCHAR));
  1764. dwStatus = RegEnumValue(
  1765. hSourceSubKey,
  1766. index,
  1767. pszValueName,
  1768. &dwValueNameLength,
  1769. NULL,
  1770. &dwValueType,
  1771. pbValue,
  1772. &cbValue
  1773. );
  1774. if(dwStatus == ERROR_SUCCESS)
  1775. {
  1776. //
  1777. // Copy value
  1778. //
  1779. dwStatus = RegSetValueEx(
  1780. hDestSubKey,
  1781. pszValueName,
  1782. 0,
  1783. dwValueType,
  1784. pbValue,
  1785. cbValue
  1786. );
  1787. }
  1788. }
  1789. if(dwStatus == ERROR_NO_MORE_ITEMS)
  1790. {
  1791. dwStatus = ERROR_SUCCESS;
  1792. }
  1793. if(dwStatus != ERROR_SUCCESS)
  1794. {
  1795. goto cleanup;
  1796. }
  1797. }
  1798. cleanup:
  1799. // close the key before trying to delete it.
  1800. if(hSourceSubKey != NULL)
  1801. {
  1802. RegCloseKey(hSourceSubKey);
  1803. }
  1804. if(hDestSubKey != NULL)
  1805. {
  1806. RegCloseKey(hDestSubKey);
  1807. }
  1808. if(pszValueName != NULL)
  1809. {
  1810. FreeMemory(pszValueName);
  1811. }
  1812. if(pszSubKeyName != NULL)
  1813. {
  1814. FreeMemory(pszSubKeyName);
  1815. }
  1816. if(pbValue != NULL)
  1817. {
  1818. FreeMemory(pbValue);
  1819. }
  1820. if(pSecurityDescriptor != NULL)
  1821. {
  1822. FreeMemory(pSecurityDescriptor);
  1823. pSecurityDescriptor = NULL;
  1824. }
  1825. return dwStatus;
  1826. }