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.

762 lines
25 KiB

  1. #include "StdAfx.h"
  2. #include "base64.h"
  3. #include <malloc.h>
  4. #include <wincrypt.h>
  5. #ifndef USE_LOCAL_IMPLEMENTATION
  6. HRESULT ImportCertFromFile(BSTR FileName, BSTR Password, BSTR bstrInstanceName){return HRESULT_FROM_WIN32(ERROR_CALL_NOT_IMPLEMENTED);}
  7. HRESULT ExportCertToFile(BSTR bstrInstanceName, BSTR FileName,BSTR Password,BOOL bPrivateKey,BOOL bCertChain){return HRESULT_FROM_WIN32(ERROR_CALL_NOT_IMPLEMENTED);}
  8. #else
  9. CString ReturnGoodMetabasePath(CString csInstanceName)
  10. {
  11. CString key_path_lm = _T("");
  12. CString key_path = _T("");
  13. // csInstanceName will come in looking like
  14. // w3svc/1
  15. // or /lm/w3svc/1
  16. //
  17. // we want to it to go out as /lm/w3svc/1
  18. key_path_lm = SZ_MBN_SEP_STR SZ_MBN_MACHINE SZ_MBN_SEP_STR;// SZ_MBN_WEB SZ_MBN_SEP_STR;
  19. if (csInstanceName.GetLength() >= 4)
  20. {
  21. if (csInstanceName.Left(4) == key_path_lm)
  22. {
  23. key_path = csInstanceName;
  24. }
  25. else
  26. {
  27. key_path_lm = SZ_MBN_MACHINE SZ_MBN_SEP_STR;
  28. if (csInstanceName.Left(3) == key_path_lm)
  29. {
  30. key_path = csInstanceName;
  31. }
  32. else
  33. {
  34. key_path = key_path_lm;
  35. key_path += csInstanceName;
  36. }
  37. }
  38. }
  39. else
  40. {
  41. key_path = key_path_lm;
  42. key_path += csInstanceName;
  43. }
  44. return key_path;
  45. }
  46. CERT_CONTEXT * GetInstalledCert(HRESULT * phResult, CString csKeyPath)
  47. {
  48. ATLASSERT(phResult != NULL);
  49. CERT_CONTEXT * pCert = NULL;
  50. *phResult = S_OK;
  51. CComAuthInfo auth;
  52. CString key_path = ReturnGoodMetabasePath(csKeyPath);
  53. CMetaKey key(&auth, key_path, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE);
  54. if (key.Succeeded())
  55. {
  56. CString store_name;
  57. CBlob hash;
  58. if (SUCCEEDED(*phResult = key.QueryValue(MD_SSL_CERT_STORE_NAME, store_name)) &&
  59. SUCCEEDED(*phResult = key.QueryValue(MD_SSL_CERT_HASH, hash)))
  60. {
  61. // Open MY store. We assume that store type and flags
  62. // cannot be changed between installation and unistallation
  63. // of the sertificate.
  64. HCERTSTORE hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,NULL,CERT_SYSTEM_STORE_LOCAL_MACHINE,store_name);
  65. ASSERT(hStore != NULL);
  66. if (hStore != NULL)
  67. {
  68. // Now we need to find cert by hash
  69. CRYPT_HASH_BLOB crypt_hash;
  70. crypt_hash.cbData = hash.GetSize();
  71. crypt_hash.pbData = hash.GetData();
  72. pCert = (CERT_CONTEXT *)CertFindCertificateInStore(hStore,X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,0,CERT_FIND_HASH,(LPVOID)&crypt_hash,NULL);
  73. if (pCert == NULL)
  74. {
  75. *phResult = HRESULT_FROM_WIN32(GetLastError());
  76. }
  77. VERIFY(CertCloseStore(hStore, 0));
  78. }
  79. else
  80. {
  81. *phResult = HRESULT_FROM_WIN32(GetLastError());
  82. }
  83. }
  84. }
  85. else
  86. {
  87. *phResult = key.QueryResult();
  88. }
  89. return pCert;
  90. }
  91. BOOL AddChainToStore(HCERTSTORE hCertStore,PCCERT_CONTEXT pCertContext,DWORD cStores,HCERTSTORE * rghStores,BOOL fDontAddRootCert,CERT_TRUST_STATUS * pChainTrustStatus)
  92. {
  93. DWORD i;
  94. CERT_CHAIN_ENGINE_CONFIG CertChainEngineConfig;
  95. HCERTCHAINENGINE hCertChainEngine = NULL;
  96. PCCERT_CHAIN_CONTEXT pCertChainContext = NULL;
  97. CERT_CHAIN_PARA CertChainPara;
  98. BOOL fRet = TRUE;
  99. PCCERT_CONTEXT pTempCertContext = NULL;
  100. //
  101. // create a new chain engine, then build the chain
  102. //
  103. memset(&CertChainEngineConfig, 0, sizeof(CertChainEngineConfig));
  104. CertChainEngineConfig.cbSize = sizeof(CertChainEngineConfig);
  105. CertChainEngineConfig.cAdditionalStore = cStores;
  106. CertChainEngineConfig.rghAdditionalStore = rghStores;
  107. CertChainEngineConfig.dwFlags = CERT_CHAIN_USE_LOCAL_MACHINE_STORE;
  108. if (!CertCreateCertificateChainEngine(&CertChainEngineConfig, &hCertChainEngine))
  109. {
  110. goto AddChainToStore_Error;
  111. }
  112. memset(&CertChainPara, 0, sizeof(CertChainPara));
  113. CertChainPara.cbSize = sizeof(CertChainPara);
  114. if (!CertGetCertificateChain(hCertChainEngine,pCertContext,NULL,NULL,&CertChainPara,0,NULL,&pCertChainContext))
  115. {
  116. goto AddChainToStore_Error;
  117. }
  118. //
  119. // make sure there is atleast 1 simple chain
  120. //
  121. if (pCertChainContext->cChain != 0)
  122. {
  123. i = 0;
  124. while (i < pCertChainContext->rgpChain[0]->cElement)
  125. {
  126. //
  127. // if we are supposed to skip the root cert,
  128. // and we are on the root cert, then continue
  129. //
  130. if (fDontAddRootCert && (pCertChainContext->rgpChain[0]->rgpElement[i]->TrustStatus.dwInfoStatus & CERT_TRUST_IS_SELF_SIGNED))
  131. {
  132. i++;
  133. continue;
  134. }
  135. CertAddCertificateContextToStore(hCertStore,pCertChainContext->rgpChain[0]->rgpElement[i]->pCertContext,CERT_STORE_ADD_REPLACE_EXISTING,&pTempCertContext);
  136. //
  137. // remove any private key property the certcontext may have on it.
  138. //
  139. if (pTempCertContext)
  140. {
  141. CertSetCertificateContextProperty(pTempCertContext, CERT_KEY_PROV_INFO_PROP_ID, 0, NULL);
  142. CertFreeCertificateContext(pTempCertContext);
  143. }
  144. i++;
  145. }
  146. }
  147. else
  148. {
  149. goto AddChainToStore_Error;
  150. }
  151. //
  152. // if the caller wants the status, then set it
  153. //
  154. if (pChainTrustStatus != NULL)
  155. {
  156. pChainTrustStatus->dwErrorStatus = pCertChainContext->TrustStatus.dwErrorStatus;
  157. pChainTrustStatus->dwInfoStatus = pCertChainContext->TrustStatus.dwInfoStatus;
  158. }
  159. AddChainToStore_Exit:
  160. if (pCertChainContext != NULL)
  161. {
  162. CertFreeCertificateChain(pCertChainContext);
  163. }
  164. if (hCertChainEngine != NULL)
  165. {
  166. CertFreeCertificateChainEngine(hCertChainEngine);
  167. }
  168. return fRet;
  169. AddChainToStore_Error:
  170. fRet = FALSE;
  171. goto AddChainToStore_Exit;
  172. }
  173. HRESULT ExportToBlob(BSTR InstanceName,BSTR Password,BOOL bPrivateKey,BOOL bCertChain,DWORD *cbBufferSize,char **pbBuffer)
  174. {
  175. HRESULT hr = E_FAIL;
  176. PCCERT_CONTEXT pCertContext = NULL;
  177. BOOL bStatus = FALSE;
  178. HCERTSTORE hStore = NULL;
  179. DWORD dwOpenFlags = CERT_STORE_READONLY_FLAG | CERT_STORE_ENUM_ARCHIVED_FLAG;
  180. CRYPT_DATA_BLOB DataBlob;
  181. ZeroMemory(&DataBlob, sizeof(CRYPT_DATA_BLOB));
  182. char *pszB64Out = NULL;
  183. DWORD pcchB64Out = 0;
  184. DWORD err;
  185. //
  186. // get the certificate from the server
  187. //
  188. pCertContext = GetInstalledCert(&hr,InstanceName);
  189. if (NULL == pCertContext)
  190. {
  191. *cbBufferSize = 0;
  192. pbBuffer = NULL;
  193. goto ExportToBlob_Exit;
  194. }
  195. //
  196. // Export cert
  197. //
  198. // Open a temporary store to stick the cert in.
  199. hStore = CertOpenStore(CERT_STORE_PROV_MEMORY,X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,0,dwOpenFlags,NULL);
  200. if(NULL == hStore)
  201. {
  202. *cbBufferSize = 0;
  203. pbBuffer = NULL;
  204. hr = HRESULT_FROM_WIN32(GetLastError());
  205. goto ExportToBlob_Exit;
  206. }
  207. //
  208. // get all the certs in the chain if we need to
  209. //
  210. if (bCertChain)
  211. {
  212. AddChainToStore(hStore, pCertContext, 0, 0, FALSE, NULL);
  213. }
  214. if(!CertAddCertificateContextToStore(hStore,pCertContext,CERT_STORE_ADD_REPLACE_EXISTING,NULL))
  215. {
  216. *cbBufferSize = 0;
  217. pbBuffer = NULL;
  218. hr = HRESULT_FROM_WIN32(GetLastError());
  219. goto ExportToBlob_Exit;
  220. }
  221. // free cert context since we no longer need to hold it
  222. if (pCertContext)
  223. {
  224. CertFreeCertificateContext(pCertContext);pCertContext=NULL;
  225. }
  226. DataBlob.cbData = 0;
  227. DataBlob.pbData = NULL;
  228. if (!PFXExportCertStoreEx(hStore,&DataBlob,Password,NULL,bPrivateKey ? EXPORT_PRIVATE_KEYS : 0))
  229. {
  230. hr = HRESULT_FROM_WIN32(GetLastError());
  231. goto ExportToBlob_Exit;
  232. }
  233. if(DataBlob.cbData <= 0)
  234. {
  235. hr = HRESULT_FROM_WIN32(GetLastError());
  236. goto ExportToBlob_Exit;
  237. }
  238. if(NULL == (DataBlob.pbData = (PBYTE) ::CoTaskMemAlloc(DataBlob.cbData)))
  239. {
  240. hr = E_OUTOFMEMORY;
  241. goto ExportToBlob_Exit;
  242. }
  243. //
  244. // at this point they have allocated enough memory
  245. // let's go and get the cert and put it into DataBlob
  246. //
  247. if(!PFXExportCertStoreEx(hStore,&DataBlob,Password,NULL,bPrivateKey ? EXPORT_PRIVATE_KEYS : 0))
  248. {
  249. if (DataBlob.pbData){CoTaskMemFree(DataBlob.pbData);DataBlob.pbData = NULL;}
  250. hr = HRESULT_FROM_WIN32(GetLastError());
  251. goto ExportToBlob_Exit;
  252. }
  253. // Encode it so that it can be passed back as a string (there are no Nulls in it)
  254. err = Base64EncodeA(DataBlob.pbData,DataBlob.cbData,NULL,&pcchB64Out);
  255. if (err != ERROR_SUCCESS)
  256. {
  257. hr = E_FAIL;
  258. goto ExportToBlob_Exit;
  259. }
  260. // allocate some space and then try it.
  261. pcchB64Out = pcchB64Out * sizeof(char);
  262. pszB64Out = (char *) ::CoTaskMemAlloc(pcchB64Out);
  263. if (NULL == pszB64Out)
  264. {
  265. hr = E_OUTOFMEMORY;
  266. goto ExportToBlob_Exit;
  267. }
  268. err = Base64EncodeA(DataBlob.pbData,DataBlob.cbData,pszB64Out,&pcchB64Out);
  269. if (err != ERROR_SUCCESS)
  270. {
  271. if (NULL != pszB64Out){CoTaskMemFree(pszB64Out);pszB64Out = NULL;}
  272. hr = E_FAIL;
  273. goto ExportToBlob_Exit;
  274. }
  275. // copy the new memory to pass back
  276. *cbBufferSize = pcchB64Out;
  277. *pbBuffer = pszB64Out;
  278. hr = ERROR_SUCCESS;
  279. ExportToBlob_Exit:
  280. if (NULL != DataBlob.pbData)
  281. {
  282. // perhaspse will this up with zeros...
  283. ZeroMemory(DataBlob.pbData, DataBlob.cbData);
  284. ::CoTaskMemFree(DataBlob.pbData);DataBlob.pbData = NULL;
  285. }
  286. if (NULL != hStore){CertCloseStore(hStore, 0);hStore=NULL;}
  287. if (NULL != pCertContext) {CertFreeCertificateContext(pCertContext);pCertContext=NULL;}
  288. return hr;
  289. }
  290. HRESULT ExportCertToFile(BSTR bstrInstanceName, BSTR FileName,BSTR Password,BOOL bPrivateKey,BOOL bCertChain)
  291. {
  292. HRESULT hr = S_OK;
  293. DWORD cbEncodedSize = 0;
  294. char * pszEncodedString = NULL;
  295. DWORD blob_cbData = 0;
  296. BYTE * blob_pbData = NULL;
  297. BOOL blob_freeme = FALSE;
  298. // Check mandatory properties
  299. if ( FileName == NULL || *FileName == 0
  300. || Password == NULL || *Password == 0
  301. || bstrInstanceName == NULL || *bstrInstanceName == 0)
  302. {
  303. return ERROR_INVALID_PARAMETER;
  304. }
  305. // Call function go get data from the remote/local iis store
  306. // and return it back as a blob. the blob could be returned back as Base64 encoded
  307. // so check that flag
  308. hr = ExportToBlob(bstrInstanceName,Password,bPrivateKey,bCertChain,&cbEncodedSize, &pszEncodedString);
  309. if (FAILED(hr))
  310. {
  311. goto Export_Exit;
  312. }
  313. if (SUCCEEDED(hr))
  314. {
  315. int err;
  316. // The data we got back was Base64 encoded to remove nulls.
  317. // we need to decode it back to it's original format.
  318. if( (err = Base64DecodeA(pszEncodedString,cbEncodedSize,NULL,&blob_cbData)) != ERROR_SUCCESS ||
  319. (blob_pbData = (BYTE *) malloc(blob_cbData)) == NULL ||
  320. (err = Base64DecodeA(pszEncodedString,cbEncodedSize,blob_pbData,&blob_cbData)) != ERROR_SUCCESS )
  321. {
  322. SetLastError(err);
  323. hr = HRESULT_FROM_WIN32(err);
  324. return hr;
  325. }
  326. blob_freeme = TRUE;
  327. HANDLE hFile = CreateFile(FileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  328. if (INVALID_HANDLE_VALUE == hFile)
  329. {
  330. hr = HRESULT_FROM_WIN32(GetLastError());
  331. return hr;
  332. }
  333. DWORD written = 0;
  334. if (!WriteFile(hFile, blob_pbData, blob_cbData, &written, NULL))
  335. {
  336. hr = HRESULT_FROM_WIN32(GetLastError());
  337. }
  338. else
  339. {
  340. hr = S_OK;
  341. }
  342. CloseHandle(hFile);
  343. }
  344. Export_Exit:
  345. if (blob_freeme)
  346. {
  347. if (blob_pbData != NULL)
  348. {
  349. // Erase the memory that the private key used to be in!!!
  350. ZeroMemory(blob_pbData, blob_cbData);
  351. free(blob_pbData);blob_pbData=NULL;
  352. }
  353. }
  354. if (pszEncodedString != NULL)
  355. {
  356. // Erase the memory that the private key used to be in!!!
  357. ZeroMemory(pszEncodedString, cbEncodedSize);
  358. CoTaskMemFree(pszEncodedString);pszEncodedString=NULL;
  359. }
  360. return hr;
  361. }
  362. BOOL InstallHashToMetabase(CRYPT_HASH_BLOB * pHash,BSTR InstanceName,HRESULT * phResult)
  363. {
  364. BOOL bRes = FALSE;
  365. CComAuthInfo auth;
  366. CString key_path = ReturnGoodMetabasePath(InstanceName);
  367. CMetaKey key(&auth, key_path, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE);
  368. if (key.Succeeded())
  369. {
  370. CBlob blob;
  371. blob.SetValue(pHash->cbData, pHash->pbData, TRUE);
  372. bRes = SUCCEEDED(*phResult = key.SetValue(MD_SSL_CERT_HASH, blob))
  373. && SUCCEEDED(*phResult = key.SetValue(MD_SSL_CERT_STORE_NAME, CString(L"MY")));
  374. }
  375. else
  376. {
  377. *phResult = key.QueryResult();
  378. }
  379. return bRes;
  380. }
  381. // This function is borrowed from trustapi.cpp
  382. BOOL TrustIsCertificateSelfSigned(PCCERT_CONTEXT pContext,DWORD dwEncoding, DWORD dwFlags)
  383. {
  384. if (!(pContext) || (dwFlags != 0))
  385. {
  386. SetLastError(ERROR_INVALID_PARAMETER);
  387. return(FALSE);
  388. }
  389. if (!(CertCompareCertificateName(dwEncoding,&pContext->pCertInfo->Issuer,&pContext->pCertInfo->Subject)))
  390. {
  391. return(FALSE);
  392. }
  393. DWORD dwFlag;
  394. dwFlag = CERT_STORE_SIGNATURE_FLAG;
  395. if (!(CertVerifySubjectCertificateContext(pContext, pContext, &dwFlag)) ||
  396. (dwFlag & CERT_STORE_SIGNATURE_FLAG))
  397. {
  398. return(FALSE);
  399. }
  400. return(TRUE);
  401. }
  402. HRESULT ImportFromBlobHash(BSTR InstanceName,BSTR Password,BOOL bInstallToMetabase,DWORD count,char *pData,DWORD *cbHashBufferSize,char **pbHashBuffer)
  403. {
  404. HRESULT hr = S_OK;
  405. CRYPT_DATA_BLOB blob;
  406. ZeroMemory(&blob, sizeof(CRYPT_DATA_BLOB));
  407. LPTSTR pPass = Password;
  408. BOOL blob_freeme = FALSE;
  409. int err;
  410. // The data we got back was Base64 encoded to remove nulls.
  411. // we need to decode it back to it's original format.
  412. if( (err = Base64DecodeA(pData,count,NULL,&blob.cbData)) != ERROR_SUCCESS ||
  413. (blob.pbData = (BYTE *) malloc(blob.cbData)) == NULL ||
  414. (err = Base64DecodeA(pData,count,blob.pbData,&blob.cbData)) != ERROR_SUCCESS )
  415. {
  416. SetLastError(err);
  417. hr = HRESULT_FROM_WIN32(err);
  418. return hr;
  419. }
  420. blob_freeme = TRUE;
  421. if (!PFXVerifyPassword(&blob, pPass, 0))
  422. {
  423. // Try empty password
  424. if (pPass == NULL)
  425. {
  426. if (!PFXVerifyPassword(&blob, pPass = L'\0', 0))
  427. {
  428. hr = ERROR_INVALID_PARAMETER;
  429. }
  430. }
  431. else
  432. {
  433. hr = ERROR_INVALID_PARAMETER;
  434. }
  435. }
  436. if (SUCCEEDED(hr))
  437. {
  438. HCERTSTORE hStore = PFXImportCertStore(&blob, pPass, CRYPT_MACHINE_KEYSET|CRYPT_EXPORTABLE);
  439. if (hStore != NULL)
  440. {
  441. //add the certificate with private key to my store; and the rest
  442. //to the ca store
  443. PCCERT_CONTEXT pCertContext = NULL;
  444. PCCERT_CONTEXT pCertPre = NULL;
  445. while ( SUCCEEDED(hr)
  446. && NULL != (pCertContext = CertEnumCertificatesInStore(hStore, pCertPre))
  447. )
  448. {
  449. //check if the certificate has the property on it
  450. //make sure the private key matches the certificate
  451. //search for both machine key and user keys
  452. DWORD dwData = 0;
  453. if (CertGetCertificateContextProperty(pCertContext,CERT_KEY_PROV_INFO_PROP_ID, NULL, &dwData) && CryptFindCertificateKeyProvInfo(pCertContext, 0, NULL))
  454. {
  455. // This certificate should go to the My store
  456. HCERTSTORE hDestStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,NULL,CERT_SYSTEM_STORE_LOCAL_MACHINE,L"MY");
  457. if (hDestStore != NULL)
  458. {
  459. // Put it to store
  460. if (CertAddCertificateContextToStore(hDestStore,pCertContext,CERT_STORE_ADD_REPLACE_EXISTING,NULL))
  461. {
  462. // Succeeded to put it to the storage
  463. hr = S_OK;
  464. // Install to metabase
  465. CRYPT_HASH_BLOB hash;
  466. hash.pbData = NULL;
  467. if ( CertGetCertificateContextProperty(pCertContext,CERT_SHA1_HASH_PROP_ID, NULL, &hash.cbData))
  468. {
  469. hash.pbData = (BYTE *) LocalAlloc(LPTR,hash.cbData);
  470. if (hash.pbData)
  471. {
  472. if (CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, hash.pbData, &hash.cbData)))
  473. {
  474. if (TRUE == bInstallToMetabase)
  475. {
  476. // returns error code in hr
  477. InstallHashToMetabase(&hash, InstanceName, &hr);
  478. }
  479. // check if we need to return back the hash
  480. if (NULL != pbHashBuffer)
  481. {
  482. *pbHashBuffer = (char *) ::CoTaskMemAlloc(hash.cbData);
  483. if (NULL == *pbHashBuffer)
  484. {
  485. hr = E_OUTOFMEMORY;
  486. *pbHashBuffer = NULL;
  487. *cbHashBufferSize = 0;
  488. }
  489. else
  490. {
  491. *cbHashBufferSize = hash.cbData;
  492. memcpy(*pbHashBuffer,hash.pbData,hash.cbData);
  493. }
  494. }
  495. }
  496. else
  497. {
  498. hr = HRESULT_FROM_WIN32(GetLastError());
  499. }
  500. if (hash.pbData)
  501. {
  502. LocalFree(hash.pbData);hash.pbData=NULL;
  503. }
  504. }
  505. else
  506. {
  507. hr = HRESULT_FROM_WIN32(GetLastError());
  508. }
  509. }
  510. else
  511. {
  512. hr = HRESULT_FROM_WIN32(GetLastError());
  513. }
  514. }
  515. else
  516. {
  517. hr = HRESULT_FROM_WIN32(GetLastError());
  518. }
  519. CertCloseStore(hDestStore, 0);
  520. }
  521. else
  522. {
  523. hr = HRESULT_FROM_WIN32(GetLastError());
  524. }
  525. } // my store certificate
  526. //see if the certificate is self-signed.
  527. //if it is selfsigned, goes to the root store
  528. else if (TrustIsCertificateSelfSigned(pCertContext,pCertContext->dwCertEncodingType, 0))
  529. {
  530. //Put it to the root store
  531. HCERTSTORE hDestStore=CertOpenStore(CERT_STORE_PROV_SYSTEM,PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,NULL,CERT_SYSTEM_STORE_LOCAL_MACHINE,L"ROOT");
  532. if (hDestStore != NULL)
  533. {
  534. // Put it to store
  535. if (!CertAddCertificateContextToStore(hDestStore,pCertContext,CERT_STORE_ADD_REPLACE_EXISTING,NULL))
  536. {
  537. hr = HRESULT_FROM_WIN32(GetLastError());
  538. }
  539. CertCloseStore(hDestStore, 0);
  540. }
  541. else
  542. {
  543. hr = HRESULT_FROM_WIN32(GetLastError());
  544. }
  545. }
  546. else
  547. {
  548. //Put it to the CA store
  549. HCERTSTORE hDestStore=CertOpenStore(CERT_STORE_PROV_SYSTEM,PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,NULL,CERT_SYSTEM_STORE_LOCAL_MACHINE,L"CA");
  550. if (hDestStore != NULL)
  551. {
  552. // Put it to store
  553. if (!CertAddCertificateContextToStore(hDestStore,pCertContext,CERT_STORE_ADD_REPLACE_EXISTING,NULL))
  554. {
  555. hr = HRESULT_FROM_WIN32(GetLastError());
  556. }
  557. CertCloseStore(hDestStore, 0);
  558. }
  559. else
  560. {
  561. hr = HRESULT_FROM_WIN32(GetLastError());
  562. }
  563. }
  564. pCertPre = pCertContext;
  565. } //while
  566. CertCloseStore(hStore, 0);
  567. }
  568. else
  569. {
  570. hr = HRESULT_FROM_WIN32(GetLastError());
  571. }
  572. }
  573. //ImportFromBlobHash_Exit:
  574. if (blob_freeme)
  575. {
  576. if (blob.pbData != NULL)
  577. {
  578. ZeroMemory(blob.pbData, blob.cbData);
  579. free(blob.pbData);blob.pbData=NULL;
  580. }
  581. }
  582. return hr;
  583. }
  584. HRESULT ImportFromBlobProxy(BSTR InstanceName,BSTR Password,BOOL bInstallToMetabase,DWORD actual,BYTE *pData,DWORD *cbHashBufferSize,char **pbHashBuffer)
  585. {
  586. HRESULT hr = E_FAIL;
  587. char *pszB64Out = NULL;
  588. DWORD pcchB64Out = 0;
  589. // base64 encode the data for transfer to the remote machine
  590. DWORD err;
  591. pcchB64Out = 0;
  592. // Encode it so that it can be passed back as a string (there are no Nulls in it)
  593. err = Base64EncodeA(pData,actual,NULL,&pcchB64Out);
  594. if (err != ERROR_SUCCESS)
  595. {
  596. hr = E_FAIL;
  597. goto ImportFromBlobProxy_Exit;
  598. }
  599. // allocate some space and then try it.
  600. pcchB64Out = pcchB64Out * sizeof(char);
  601. pszB64Out = (char *) ::CoTaskMemAlloc(pcchB64Out);
  602. if (NULL == pszB64Out)
  603. {
  604. hr = E_OUTOFMEMORY;
  605. goto ImportFromBlobProxy_Exit;
  606. }
  607. err = Base64EncodeA(pData,actual,pszB64Out,&pcchB64Out);
  608. if (err != ERROR_SUCCESS)
  609. {
  610. hr = E_FAIL;
  611. goto ImportFromBlobProxy_Exit;
  612. }
  613. // the data to send are now in these variables
  614. // pcchB64Out
  615. // pszB64Out
  616. if (NULL != pbHashBuffer)
  617. {
  618. hr = ImportFromBlobHash(InstanceName,Password,bInstallToMetabase,pcchB64Out,pszB64Out,cbHashBufferSize,pbHashBuffer);
  619. }
  620. if (SUCCEEDED(hr))
  621. {
  622. // otherwise hey, The data was imported!
  623. hr = S_OK;
  624. }
  625. ImportFromBlobProxy_Exit:
  626. if (NULL != pszB64Out)
  627. {
  628. ZeroMemory(pszB64Out,pcchB64Out);
  629. CoTaskMemFree(pszB64Out);
  630. }
  631. return hr;
  632. }
  633. HRESULT ImportCertFromFile(BSTR FileName, BSTR Password, BSTR bstrInstanceName)
  634. {
  635. HRESULT hr = S_OK;
  636. BYTE * pbData = NULL;
  637. DWORD actual = 0, cbData = 0;
  638. // Check mandatory properties
  639. if ( FileName == NULL || *FileName == 0
  640. || Password == NULL || *Password == 0
  641. || bstrInstanceName == NULL || *bstrInstanceName == 0)
  642. {
  643. return ERROR_INVALID_PARAMETER;
  644. }
  645. HANDLE hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  646. if (hFile == INVALID_HANDLE_VALUE)
  647. {
  648. hr = HRESULT_FROM_WIN32(GetLastError());
  649. hFile = NULL;
  650. goto Import_Exit;
  651. }
  652. if (-1 == (cbData = ::GetFileSize(hFile, NULL)))
  653. {
  654. hr = HRESULT_FROM_WIN32(GetLastError());
  655. goto Import_Exit;
  656. }
  657. if (NULL == (pbData = (BYTE *)::CoTaskMemAlloc(cbData)))
  658. {
  659. hr = E_OUTOFMEMORY;
  660. goto Import_Exit;
  661. }
  662. if (ReadFile(hFile, pbData, cbData, &actual, NULL))
  663. {
  664. hr = ImportFromBlobProxy(bstrInstanceName, Password, TRUE, actual, pbData, 0, NULL);
  665. }
  666. else
  667. {
  668. hr = HRESULT_FROM_WIN32(GetLastError());
  669. goto Import_Exit;
  670. }
  671. Import_Exit:
  672. if (pbData != NULL)
  673. {
  674. ZeroMemory(pbData, cbData);
  675. ::CoTaskMemFree(pbData);
  676. }
  677. if (hFile != NULL){CloseHandle(hFile);}
  678. return hr;
  679. }
  680. #endif