Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1340 lines
32 KiB

  1. //
  2. // CertUtil.cpp
  3. //
  4. #include "StdAfx.h"
  5. #include "CertUtil.h"
  6. #include "base64.h"
  7. #include <malloc.h>
  8. #include "Certificat.h"
  9. #include <wincrypt.h>
  10. #include "Resource.h"
  11. #include "Shlwapi.h"
  12. #include "CertCA.h"
  13. const CLSID CLSID_CCertConfig =
  14. {0x372fce38, 0x4324, 0x11d0, {0x88, 0x10, 0x00, 0xa0, 0xc9, 0x03, 0xb8, 0x3c}};
  15. const GUID IID_ICertConfig =
  16. {0x372fce34, 0x4324, 0x11d0, {0x88, 0x10, 0x00, 0xa0, 0xc9, 0x03, 0xb8, 0x3c}};
  17. #define CRYPTUI_MAX_STRING_SIZE 768
  18. #define ARRAYSIZE(x)\
  19. (sizeof(x)/sizeof(x[0]))
  20. BOOL
  21. GetOnlineCAList(CStringList& list, const CString& certType, HRESULT * phRes)
  22. {
  23. BOOL bRes = TRUE;
  24. HRESULT hr = S_OK;
  25. DWORD errBefore = GetLastError();
  26. DWORD dwCACount = 0;
  27. HCAINFO hCurCAInfo = NULL;
  28. HCAINFO hPreCAInfo = NULL;
  29. if (certType.IsEmpty())
  30. return FALSE;
  31. *phRes = CAFindByCertType(certType, NULL, 0, &hCurCAInfo);
  32. if (FAILED(*phRes) || NULL == hCurCAInfo)
  33. {
  34. if (S_OK == hr)
  35. hr=E_FAIL;
  36. return FALSE;
  37. }
  38. //get the CA count
  39. if (0 == (dwCACount = CACountCAs(hCurCAInfo)))
  40. {
  41. *phRes = E_FAIL;
  42. return FALSE;
  43. }
  44. WCHAR ** ppwstrName, ** ppwstrMachine;
  45. while (hCurCAInfo)
  46. {
  47. //get the CA information
  48. if ( SUCCEEDED(CAGetCAProperty(hCurCAInfo, CA_PROP_DISPLAY_NAME, &ppwstrName))
  49. && SUCCEEDED(CAGetCAProperty(hCurCAInfo, CA_PROP_DNSNAME, &ppwstrMachine))
  50. )
  51. {
  52. CString config;
  53. config = *ppwstrMachine;
  54. config += L"\\";
  55. config += *ppwstrName;
  56. list.AddTail(config);
  57. CAFreeCAProperty(hCurCAInfo, ppwstrName);
  58. CAFreeCAProperty(hCurCAInfo, ppwstrMachine);
  59. }
  60. else
  61. {
  62. bRes = FALSE;
  63. break;
  64. }
  65. hPreCAInfo = hCurCAInfo;
  66. if (FAILED(*phRes = CAEnumNextCA(hPreCAInfo, &hCurCAInfo)))
  67. {
  68. bRes = FALSE;
  69. break;
  70. }
  71. CACloseCA(hPreCAInfo);
  72. hPreCAInfo = NULL;
  73. }
  74. if (hPreCAInfo)
  75. CACloseCA(hPreCAInfo);
  76. if (hCurCAInfo)
  77. CACloseCA(hCurCAInfo);
  78. SetLastError(errBefore);
  79. return bRes;
  80. }
  81. PCCERT_CONTEXT
  82. GetRequestContext(CCryptBlob& pkcs7, HRESULT * phRes)
  83. {
  84. ASSERT(phRes != NULL);
  85. BOOL bRes = FALSE;
  86. HCERTSTORE hStoreMsg = NULL;
  87. PCCERT_CONTEXT pCertContextMsg = NULL;
  88. if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
  89. (PCERT_BLOB)pkcs7,
  90. (CERT_QUERY_CONTENT_FLAG_CERT |
  91. CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED |
  92. CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE |
  93. CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED) ,
  94. CERT_QUERY_FORMAT_FLAG_ALL,
  95. 0,
  96. NULL,
  97. NULL,
  98. NULL,
  99. &hStoreMsg,
  100. NULL,
  101. NULL)
  102. || NULL == (pCertContextMsg = CertFindCertificateInStore(
  103. hStoreMsg,
  104. X509_ASN_ENCODING,
  105. 0,
  106. CERT_FIND_ANY,
  107. NULL,
  108. NULL))
  109. )
  110. {
  111. *phRes = HRESULT_FROM_WIN32(GetLastError());
  112. }
  113. return pCertContextMsg;
  114. }
  115. BOOL GetRequestInfoFromPKCS10(CCryptBlob& pkcs10,
  116. PCERT_REQUEST_INFO * pReqInfo,
  117. HRESULT * phRes)
  118. {
  119. ASSERT(pReqInfo != NULL);
  120. ASSERT(phRes != NULL);
  121. BOOL bRes = FALSE;
  122. DWORD req_info_size;
  123. if (!(bRes = CryptDecodeObjectEx(
  124. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  125. X509_CERT_REQUEST_TO_BE_SIGNED,
  126. pkcs10.GetData(),
  127. pkcs10.GetSize(),
  128. CRYPT_DECODE_ALLOC_FLAG,
  129. NULL,
  130. pReqInfo,
  131. &req_info_size)))
  132. {
  133. TRACE(_T("Error from CryptDecodeObjectEx: %xd\n"), GetLastError());
  134. *phRes = HRESULT_FROM_WIN32(GetLastError());
  135. }
  136. return bRes;
  137. }
  138. #if 0
  139. // This function extracts data from pkcs7 format
  140. BOOL GetRequestInfoFromRenewalRequest(CCryptBlob& renewal_req,
  141. PCCERT_CONTEXT * pSignerCert,
  142. HCERTSTORE hStore,
  143. PCERT_REQUEST_INFO * pReqInfo,
  144. HRESULT * phRes)
  145. {
  146. BOOL bRes;
  147. CRYPT_DECRYPT_MESSAGE_PARA decr_para;
  148. CRYPT_VERIFY_MESSAGE_PARA ver_para;
  149. decr_para.cbSize = sizeof(decr_para);
  150. decr_para.dwMsgAndCertEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
  151. decr_para.cCertStore = 1;
  152. decr_para.rghCertStore = &hStore;
  153. ver_para.cbSize = sizeof(ver_para);
  154. ver_para.dwMsgAndCertEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
  155. ver_para.hCryptProv = 0;
  156. ver_para.pfnGetSignerCertificate = NULL;
  157. ver_para.pvGetArg = NULL;
  158. DWORD dwMsgType;
  159. DWORD dwInnerContentType;
  160. DWORD cbDecoded;
  161. if (bRes = CryptDecodeMessage(
  162. CMSG_SIGNED_FLAG,
  163. &decr_para,
  164. &ver_para,
  165. 0,
  166. renewal_req.GetData(),
  167. renewal_req.GetSize(),
  168. 0,
  169. &dwMsgType,
  170. &dwInnerContentType,
  171. NULL,
  172. &cbDecoded,
  173. NULL,
  174. pSignerCert))
  175. {
  176. CCryptBlobLocal decoded_req;
  177. decoded_req.Resize(cbDecoded);
  178. if (bRes = CryptDecodeMessage(
  179. CMSG_SIGNED_FLAG,
  180. &decr_para,
  181. &ver_para,
  182. 0,
  183. renewal_req.GetData(),
  184. renewal_req.GetSize(),
  185. 0,
  186. &dwMsgType,
  187. &dwInnerContentType,
  188. decoded_req.GetData(),
  189. &cbDecoded,
  190. NULL,
  191. pSignerCert))
  192. {
  193. bRes = GetRequestInfoFromPKCS10(decoded_req,
  194. pReqInfo, phRes);
  195. }
  196. }
  197. if (!bRes)
  198. {
  199. *phRes = HRESULT_FROM_WIN32(GetLastError());
  200. }
  201. return bRes;
  202. }
  203. #endif
  204. HCERTSTORE
  205. OpenRequestStore(IEnroll * pEnroll, HRESULT * phResult)
  206. {
  207. ASSERT(NULL != phResult);
  208. HCERTSTORE hStore = NULL;
  209. WCHAR * bstrStoreName, * bstrStoreType;
  210. long dwStoreFlags;
  211. VERIFY(SUCCEEDED(pEnroll->get_RequestStoreNameWStr(&bstrStoreName)));
  212. VERIFY(SUCCEEDED(pEnroll->get_RequestStoreTypeWStr(&bstrStoreType)));
  213. VERIFY(SUCCEEDED(pEnroll->get_RequestStoreFlags(&dwStoreFlags)));
  214. size_t store_type_len = _tcslen(bstrStoreType);
  215. char * szStoreProvider = (char *)_alloca(store_type_len + 1);
  216. ASSERT(szStoreProvider != NULL);
  217. size_t n = wcstombs(szStoreProvider, bstrStoreType, store_type_len);
  218. szStoreProvider[n] = '\0';
  219. hStore = CertOpenStore(
  220. szStoreProvider,
  221. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  222. NULL,
  223. dwStoreFlags,
  224. bstrStoreName
  225. );
  226. CoTaskMemFree(bstrStoreName);
  227. CoTaskMemFree(bstrStoreType);
  228. if (hStore == NULL)
  229. *phResult = HRESULT_FROM_WIN32(GetLastError());
  230. return hStore;
  231. }
  232. HCERTSTORE
  233. OpenMyStore(IEnroll * pEnroll, HRESULT * phResult)
  234. {
  235. ASSERT(NULL != phResult);
  236. HCERTSTORE hStore = NULL;
  237. BSTR bstrStoreName, bstrStoreType;
  238. long dwStoreFlags;
  239. VERIFY(SUCCEEDED(pEnroll->get_MyStoreNameWStr(&bstrStoreName)));
  240. VERIFY(SUCCEEDED(pEnroll->get_MyStoreTypeWStr(&bstrStoreType)));
  241. VERIFY(SUCCEEDED(pEnroll->get_MyStoreFlags(&dwStoreFlags)));
  242. size_t store_type_len = _tcslen(bstrStoreType);
  243. char * szStoreProvider = (char *)_alloca(store_type_len + 1);
  244. ASSERT(szStoreProvider != NULL);
  245. size_t n = wcstombs(szStoreProvider, bstrStoreType, store_type_len);
  246. ASSERT(n != -1);
  247. // this converter doesn't set zero byte!!!
  248. szStoreProvider[n] = '\0';
  249. hStore = CertOpenStore(
  250. szStoreProvider,
  251. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  252. NULL,
  253. dwStoreFlags,
  254. bstrStoreName
  255. );
  256. CoTaskMemFree(bstrStoreName);
  257. CoTaskMemFree(bstrStoreType);
  258. if (hStore == NULL)
  259. *phResult = HRESULT_FROM_WIN32(GetLastError());
  260. return hStore;
  261. }
  262. BOOL
  263. GetStringProperty(PCCERT_CONTEXT pCertContext,
  264. DWORD propId,
  265. CString& str,
  266. HRESULT * phRes)
  267. {
  268. BOOL bRes = FALSE;
  269. DWORD cb;
  270. BYTE * prop;
  271. // compare property value
  272. if ( CertGetCertificateContextProperty(pCertContext, propId, NULL, &cb)
  273. && (NULL != (prop = (BYTE *)_alloca(cb)))
  274. && CertGetCertificateContextProperty(pCertContext, propId, prop, &cb)
  275. )
  276. {
  277. // decode this instance name property
  278. DWORD cbData = 0;
  279. void * pData = NULL;
  280. if ( CryptDecodeObject(CRYPT_ASN_ENCODING, X509_UNICODE_ANY_STRING,
  281. prop, cb, 0, NULL, &cbData)
  282. && NULL != (pData = _alloca(cbData))
  283. && CryptDecodeObject(CRYPT_ASN_ENCODING, X509_UNICODE_ANY_STRING,
  284. prop, cb, 0, pData, &cbData)
  285. )
  286. {
  287. CERT_NAME_VALUE * pName = (CERT_NAME_VALUE *)pData;
  288. DWORD cch = pName->Value.cbData/sizeof(TCHAR);
  289. void * p = str.GetBuffer(cch);
  290. memcpy(p, pName->Value.pbData, pName->Value.cbData);
  291. str.ReleaseBuffer(cch);
  292. bRes = TRUE;
  293. }
  294. }
  295. if (!bRes)
  296. *phRes = HRESULT_FROM_WIN32(GetLastError());
  297. return bRes;
  298. }
  299. BOOL
  300. GetBlobProperty(PCCERT_CONTEXT pCertContext,
  301. DWORD propId,
  302. CCryptBlob& blob,
  303. HRESULT * phRes)
  304. {
  305. BOOL bRes = FALSE;
  306. DWORD cb;
  307. // compare property value
  308. if ( CertGetCertificateContextProperty(pCertContext, propId, NULL, &cb)
  309. && blob.Resize(cb)
  310. && CertGetCertificateContextProperty(pCertContext, propId, blob.GetData(), &cb)
  311. )
  312. {
  313. bRes = TRUE;
  314. }
  315. if (!bRes)
  316. *phRes = HRESULT_FROM_WIN32(GetLastError());
  317. return bRes;
  318. }
  319. PCCERT_CONTEXT
  320. GetPendingDummyCert(const CString& inst_name,
  321. IEnroll * pEnroll,
  322. HRESULT * phRes)
  323. {
  324. PCCERT_CONTEXT pRes = NULL;
  325. HCERTSTORE hStore = OpenRequestStore(pEnroll, phRes);
  326. if (hStore != NULL)
  327. {
  328. DWORD dwPropId = CERTWIZ_INSTANCE_NAME_PROP_ID;
  329. PCCERT_CONTEXT pDummyCert = NULL;
  330. while (NULL != (pDummyCert = CertFindCertificateInStore(hStore,
  331. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  332. 0, CERT_FIND_PROPERTY,
  333. (LPVOID)&dwPropId, pDummyCert)))
  334. {
  335. CString str;
  336. if (GetStringProperty(pDummyCert, dwPropId, str, phRes))
  337. {
  338. if (str.CompareNoCase(inst_name) == 0)
  339. {
  340. pRes = pDummyCert;
  341. break;
  342. }
  343. }
  344. }
  345. CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
  346. }
  347. return pRes;
  348. }
  349. PCCERT_CONTEXT
  350. GetReqCertByKey(IEnroll * pEnroll, CERT_PUBLIC_KEY_INFO * pKeyInfo, HRESULT * phResult)
  351. {
  352. PCCERT_CONTEXT pRes = NULL;
  353. HCERTSTORE hStore = OpenRequestStore(pEnroll, phResult);
  354. if (hStore != NULL)
  355. {
  356. if (NULL != (pRes = CertFindCertificateInStore(hStore,
  357. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  358. 0, CERT_FIND_PUBLIC_KEY, (LPVOID)pKeyInfo, NULL)))
  359. {
  360. *phResult = S_OK;
  361. }
  362. VERIFY(SUCCEEDED(CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG)));
  363. }
  364. return pRes;
  365. }
  366. #define CERT_QUERY_CONTENT_FLAGS\
  367. CERT_QUERY_CONTENT_FLAG_CERT\
  368. |CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED\
  369. |CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE\
  370. |CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
  371. PCCERT_CONTEXT
  372. GetCertContextFromPKCS7File(const CString& resp_file_name,
  373. CERT_PUBLIC_KEY_INFO * pKeyInfo,
  374. HRESULT * phResult)
  375. {
  376. ASSERT(phResult != NULL);
  377. PCCERT_CONTEXT pRes = NULL;
  378. HANDLE hFile;
  379. if (INVALID_HANDLE_VALUE != (hFile = CreateFile(resp_file_name,
  380. GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
  381. FILE_ATTRIBUTE_NORMAL, NULL)))
  382. {
  383. // find the length of the buffer
  384. DWORD cbData = GetFileSize(hFile, NULL);
  385. BYTE * pbData;
  386. // alloc temp buffer
  387. if ((pbData = (BYTE *)_alloca(cbData)) != NULL)
  388. {
  389. DWORD cb = 0;
  390. if (ReadFile(hFile, pbData, cbData, &cb, NULL))
  391. {
  392. ASSERT(cb == cbData);
  393. pRes = GetCertContextFromPKCS7(pbData, cb, pKeyInfo, phResult);
  394. }
  395. else
  396. *phResult = HRESULT_FROM_WIN32(GetLastError());
  397. }
  398. CloseHandle(hFile);
  399. }
  400. else
  401. *phResult = HRESULT_FROM_WIN32(GetLastError());
  402. return pRes;
  403. }
  404. PCCERT_CONTEXT
  405. GetCertContextFromPKCS7(const BYTE * pbData,
  406. DWORD cbData,
  407. CERT_PUBLIC_KEY_INFO * pKeyInfo,
  408. HRESULT * phResult)
  409. {
  410. ASSERT(phResult != NULL);
  411. PCCERT_CONTEXT pRes = NULL;
  412. CRYPT_DATA_BLOB blob;
  413. memset(&blob, 0, sizeof(CRYPT_DATA_BLOB));
  414. blob.cbData = cbData;
  415. blob.pbData = (BYTE *)pbData;
  416. HCERTSTORE hStoreMsg = NULL;
  417. if(CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
  418. &blob,
  419. (CERT_QUERY_CONTENT_FLAG_CERT |
  420. CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED |
  421. CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE |
  422. CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED) ,
  423. CERT_QUERY_FORMAT_FLAG_ALL,
  424. 0,
  425. NULL,
  426. NULL,
  427. NULL,
  428. &hStoreMsg,
  429. NULL,
  430. NULL))
  431. {
  432. if (pKeyInfo != NULL)
  433. pRes = CertFindCertificateInStore(hStoreMsg,
  434. X509_ASN_ENCODING,
  435. 0,
  436. CERT_FIND_PUBLIC_KEY,
  437. pKeyInfo,
  438. NULL);
  439. else
  440. pRes = CertFindCertificateInStore(hStoreMsg,
  441. X509_ASN_ENCODING,
  442. 0,
  443. CERT_FIND_ANY,
  444. NULL,
  445. NULL);
  446. if (pRes == NULL)
  447. *phResult = HRESULT_FROM_WIN32(GetLastError());
  448. CertCloseStore(hStoreMsg, CERT_CLOSE_STORE_CHECK_FLAG);
  449. }
  450. else
  451. *phResult = HRESULT_FROM_WIN32(GetLastError());
  452. return pRes;
  453. }
  454. BOOL
  455. FormatDateString(CString& str, FILETIME ft, BOOL fIncludeTime, BOOL fLongFormat)
  456. {
  457. int cch;
  458. int cch2;
  459. LPWSTR psz;
  460. SYSTEMTIME st;
  461. FILETIME localTime;
  462. if (!FileTimeToLocalFileTime(&ft, &localTime))
  463. {
  464. return FALSE;
  465. }
  466. if (!FileTimeToSystemTime(&localTime, &st))
  467. {
  468. //
  469. // if the conversion to local time failed, then just use the original time
  470. //
  471. if (!FileTimeToSystemTime(&ft, &st))
  472. {
  473. return FALSE;
  474. }
  475. }
  476. cch = (GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &st, NULL, NULL, 0) +
  477. GetDateFormat(LOCALE_SYSTEM_DEFAULT, fLongFormat ? DATE_LONGDATE : 0, &st, NULL, NULL, 0) + 5);
  478. if (NULL == (psz = str.GetBuffer((cch+5) * sizeof(WCHAR))))
  479. {
  480. return FALSE;
  481. }
  482. cch2 = GetDateFormat(LOCALE_SYSTEM_DEFAULT, fLongFormat ? DATE_LONGDATE : 0, &st, NULL, psz, cch);
  483. if (fIncludeTime)
  484. {
  485. psz[cch2-1] = ' ';
  486. GetTimeFormat(LOCALE_SYSTEM_DEFAULT, TIME_NOSECONDS, &st, NULL, &psz[cch2], cch-cch2);
  487. }
  488. str.ReleaseBuffer();
  489. return TRUE;
  490. }
  491. BOOL MyGetOIDInfo(LPWSTR string, DWORD stringSize, LPSTR pszObjId)
  492. {
  493. PCCRYPT_OID_INFO pOIDInfo;
  494. if (NULL != (pOIDInfo = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, pszObjId, 0)))
  495. {
  496. if ((DWORD)wcslen(pOIDInfo->pwszName)+1 <= stringSize)
  497. {
  498. wcscpy(string, pOIDInfo->pwszName);
  499. }
  500. else
  501. {
  502. return FALSE;
  503. }
  504. }
  505. else
  506. {
  507. return (MultiByteToWideChar(CP_ACP, 0, pszObjId, -1, string, stringSize) != 0);
  508. }
  509. return TRUE;
  510. }
  511. BOOL
  512. GetKeyUsageProperty(PCCERT_CONTEXT pCertContext,
  513. CERT_ENHKEY_USAGE ** pKeyUsage,
  514. BOOL fPropertiesOnly,
  515. HRESULT * phRes)
  516. {
  517. DWORD cb = 0;
  518. BOOL bRes = FALSE;
  519. if (!CertGetEnhancedKeyUsage(pCertContext,
  520. fPropertiesOnly ? CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG : 0,
  521. NULL,
  522. &cb))
  523. {
  524. *phRes = HRESULT_FROM_WIN32(GetLastError());
  525. goto ErrExit;
  526. }
  527. if (NULL == (*pKeyUsage = (CERT_ENHKEY_USAGE *)malloc(cb)))
  528. {
  529. *phRes = E_OUTOFMEMORY;
  530. goto ErrExit;
  531. }
  532. if (!CertGetEnhancedKeyUsage (pCertContext,
  533. fPropertiesOnly ? CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG : 0,
  534. *pKeyUsage,
  535. &cb))
  536. {
  537. free(*pKeyUsage);
  538. *phRes = HRESULT_FROM_WIN32(GetLastError());
  539. goto ErrExit;
  540. }
  541. *phRes = S_OK;
  542. bRes = TRUE;
  543. ErrExit:
  544. return bRes;
  545. }
  546. BOOL
  547. GetFriendlyName(PCCERT_CONTEXT pCertContext,
  548. CString& name,
  549. HRESULT * phRes)
  550. {
  551. BOOL bRes = FALSE;
  552. DWORD cb;
  553. BYTE * pName = NULL;
  554. if ( CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, NULL, &cb)
  555. && NULL != (pName = (BYTE *)name.GetBuffer((cb + 1)/sizeof(TCHAR)))
  556. && CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, pName, &cb)
  557. )
  558. {
  559. pName[cb] = 0;
  560. bRes = TRUE;
  561. }
  562. else
  563. {
  564. *phRes = HRESULT_FROM_WIN32(GetLastError());
  565. }
  566. if (pName != NULL && name.IsEmpty())
  567. {
  568. name.ReleaseBuffer();
  569. }
  570. return bRes;
  571. }
  572. BOOL
  573. GetNameString(PCCERT_CONTEXT pCertContext,
  574. DWORD type,
  575. DWORD flag,
  576. CString& name,
  577. HRESULT * phRes)
  578. {
  579. BOOL bRes = FALSE;
  580. LPTSTR pName;
  581. DWORD cchName = CertGetNameString(pCertContext, type, flag, NULL, NULL, 0);
  582. if (cchName > 1 && (NULL != (pName = name.GetBuffer(cchName))))
  583. {
  584. bRes = (1 != CertGetNameString(pCertContext, type, flag, NULL, pName, cchName));
  585. name.ReleaseBuffer();
  586. }
  587. else
  588. {
  589. *phRes = HRESULT_FROM_WIN32(GetLastError());
  590. }
  591. return bRes;
  592. }
  593. BOOL
  594. ContainsKeyUsageProperty(PCCERT_CONTEXT pCertContext,
  595. CArray<LPCSTR, LPCSTR>& uses,
  596. HRESULT * phRes
  597. )
  598. {
  599. BOOL bRes = FALSE;
  600. CERT_ENHKEY_USAGE * pKeyUsage = NULL;
  601. if ( uses.GetSize() > 0
  602. && GetKeyUsageProperty(pCertContext, &pKeyUsage, FALSE, phRes)
  603. )
  604. {
  605. if (pKeyUsage->cUsageIdentifier == 0)
  606. {
  607. bRes = TRUE;
  608. }
  609. else
  610. {
  611. for (DWORD i = 0; i < pKeyUsage->cUsageIdentifier; i++)
  612. {
  613. // Our friends from CAPI made this property ASCII even for
  614. // UNICODE program
  615. for (int n = 0; n < uses.GetSize(); n++)
  616. {
  617. if (strstr(pKeyUsage->rgpszUsageIdentifier[i], uses[n]) != NULL)
  618. {
  619. bRes = TRUE;
  620. break;
  621. }
  622. }
  623. }
  624. }
  625. free(pKeyUsage);
  626. }
  627. return bRes;
  628. }
  629. BOOL
  630. FormatEnhancedKeyUsageString(CString& str,
  631. PCCERT_CONTEXT pCertContext,
  632. BOOL fPropertiesOnly,
  633. BOOL fMultiline,
  634. HRESULT * phRes)
  635. {
  636. CERT_ENHKEY_USAGE * pKeyUsage = NULL;
  637. WCHAR szText[CRYPTUI_MAX_STRING_SIZE];
  638. BOOL bRes = FALSE;
  639. if (GetKeyUsageProperty(pCertContext, &pKeyUsage, fPropertiesOnly, phRes))
  640. {
  641. // loop for each usage and add it to the display string
  642. for (DWORD i = 0; i < pKeyUsage->cUsageIdentifier; i++)
  643. {
  644. if (!(bRes = MyGetOIDInfo(szText, ARRAYSIZE(szText), pKeyUsage->rgpszUsageIdentifier[i])))
  645. break;
  646. // add delimeter if not first iteration
  647. if (i != 0)
  648. {
  649. str += fMultiline ? L"\n" : L", ";
  650. }
  651. // add the enhanced key usage string
  652. str += szText;
  653. }
  654. free (pKeyUsage);
  655. }
  656. else
  657. {
  658. str.LoadString(IDS_ANY);
  659. bRes = TRUE;
  660. }
  661. return bRes;
  662. }
  663. BOOL
  664. GetServerComment(const CString& machine_name,
  665. const CString& server_name,
  666. CString& comment,
  667. HRESULT * phResult)
  668. {
  669. ASSERT(!machine_name.IsEmpty());
  670. ASSERT(!server_name.IsEmpty());
  671. *phResult = S_OK;
  672. CMetaKey key(machine_name,
  673. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  674. METADATA_MASTER_ROOT_HANDLE,
  675. server_name);
  676. if (key.Succeeded())
  677. {
  678. return SUCCEEDED(*phResult = key.QueryValue(MD_SERVER_COMMENT, comment));
  679. }
  680. else
  681. {
  682. *phResult = key.QueryResult();
  683. return FALSE;
  684. }
  685. }
  686. /*
  687. GetInstalledCert
  688. Function reads cert hash attribute from metabase
  689. using machine_name and server name as server instance
  690. description, then looks in MY store for a certificate
  691. with hash equal found in metabase.
  692. Return is cert context pointer or NULL, if cert wasn't
  693. found or certificate store wasn't opened.
  694. On return HRESULT * is filled by error code.
  695. */
  696. PCCERT_CONTEXT
  697. GetInstalledCert(const CString& machine_name,
  698. const CString& server_name,
  699. IEnroll * pEnroll,
  700. HRESULT * phResult)
  701. {
  702. ASSERT(pEnroll != NULL);
  703. ASSERT(phResult != NULL);
  704. ASSERT(!machine_name.IsEmpty());
  705. ASSERT(!server_name.IsEmpty());
  706. PCCERT_CONTEXT pCert = NULL;
  707. *phResult = S_OK;
  708. CMetaKey key(machine_name,
  709. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  710. METADATA_MASTER_ROOT_HANDLE,
  711. server_name);
  712. if (key.Succeeded())
  713. {
  714. CString store_name;
  715. CBlob hash;
  716. if ( SUCCEEDED(*phResult = key.QueryValue(MD_SSL_CERT_STORE_NAME, store_name))
  717. && SUCCEEDED(*phResult = key.QueryValue(MD_SSL_CERT_HASH, hash))
  718. )
  719. {
  720. // Open MY store. We assume that store type and flags
  721. // cannot be changed between installation and unistallation
  722. // of the sertificate.
  723. HCERTSTORE hStore = OpenMyStore(pEnroll, phResult);
  724. ASSERT(hStore != NULL);
  725. if (hStore != NULL)
  726. {
  727. // Now we need to find cert by hash
  728. CRYPT_HASH_BLOB crypt_hash;
  729. crypt_hash.cbData = hash.GetSize();
  730. crypt_hash.pbData = hash.GetData();
  731. pCert = CertFindCertificateInStore(hStore,
  732. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  733. 0, CERT_FIND_HASH, (LPVOID)&crypt_hash, NULL);
  734. if (pCert == NULL)
  735. *phResult = HRESULT_FROM_WIN32(GetLastError());
  736. VERIFY(CertCloseStore(hStore, 0));
  737. }
  738. }
  739. }
  740. else
  741. *phResult = key.QueryResult();
  742. return pCert;
  743. }
  744. /*
  745. InstallHashToMetabase
  746. Function writes hash array to metabase. After that IIS
  747. could use certificate with that hash from MY store.
  748. Function expects server_name in format lm\w3svc\<number>,
  749. i.e. from root node down to virtual server
  750. */
  751. BOOL
  752. InstallHashToMetabase(CRYPT_HASH_BLOB * pHash,
  753. const CString& machine_name,
  754. const CString& server_name,
  755. HRESULT * phResult)
  756. {
  757. BOOL bRes = FALSE;
  758. CMetaKey key(machine_name,
  759. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  760. METADATA_MASTER_ROOT_HANDLE,
  761. server_name);
  762. if (key.Succeeded())
  763. {
  764. CBlob blob;
  765. blob.SetValue(pHash->cbData, pHash->pbData, TRUE);
  766. bRes = SUCCEEDED(*phResult = key.SetValue(MD_SSL_CERT_HASH, blob))
  767. && SUCCEEDED(*phResult = key.SetValue(MD_SSL_CERT_STORE_NAME, CString(L"MY")));
  768. }
  769. else
  770. {
  771. TRACE(_T("Failed to open metabase key. Error 0x%x\n"), key.QueryResult());
  772. *phResult = key.QueryResult();
  773. }
  774. return bRes;
  775. }
  776. /*
  777. InstallCertByHash
  778. Function looks in MY store for certificate which has hash
  779. equal to pHash parameter. If cert is found, it is installed
  780. to metabase.
  781. This function is used after xenroll accept() method, which
  782. puts certificate to store
  783. */
  784. BOOL
  785. InstallCertByHash(CRYPT_HASH_BLOB * pHash,
  786. const CString& machine_name,
  787. const CString& server_name,
  788. IEnroll * pEnroll,
  789. HRESULT * phResult)
  790. {
  791. BOOL bRes = FALSE;
  792. // we are looking to MY store only
  793. HCERTSTORE hStore = OpenMyStore(pEnroll, phResult);
  794. if (hStore != NULL)
  795. {
  796. PCCERT_CONTEXT pCert = CertFindCertificateInStore(hStore,
  797. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  798. 0, CERT_FIND_HASH, (LPVOID)pHash, NULL);
  799. // now install cert info to IIS MetaBase
  800. if (pCert != NULL)
  801. {
  802. bRes = InstallHashToMetabase(pHash,
  803. machine_name, server_name, phResult);
  804. CertFreeCertificateContext(pCert);
  805. }
  806. else
  807. {
  808. TRACE(_T("FAILED: certificate installation, error 0x%x\n"), GetLastError());
  809. // We definitely need to store the hash of the cert, so error out
  810. *phResult = HRESULT_FROM_WIN32(GetLastError());
  811. }
  812. VERIFY(CertCloseStore(hStore, 0));
  813. }
  814. return bRes;
  815. }
  816. HRESULT
  817. CreateRequest_Base64(const BSTR bstr_dn,
  818. IEnroll * pEnroll,
  819. BSTR csp_name,
  820. DWORD csp_type,
  821. BSTR * pOut)
  822. {
  823. ASSERT(pOut != NULL);
  824. ASSERT(bstr_dn != NULL);
  825. HRESULT hRes = S_OK;
  826. CString strUsage(szOID_PKIX_KP_SERVER_AUTH);
  827. CRYPT_DATA_BLOB request = {0, NULL};
  828. pEnroll->put_ProviderType(csp_type);
  829. pEnroll->put_ProviderNameWStr(csp_name);
  830. if (SUCCEEDED(hRes = pEnroll->createPKCS10WStr(
  831. bstr_dn,
  832. (LPTSTR)(LPCTSTR)strUsage,
  833. &request)))
  834. {
  835. WCHAR * wszRequestB64 = NULL;
  836. DWORD cch = 0;
  837. DWORD err = ERROR_SUCCESS;
  838. // BASE64 encode pkcs 10
  839. if ( (err = Base64EncodeW(request.pbData, request.cbData, NULL, &cch)) == ERROR_SUCCESS
  840. && (wszRequestB64 = (WCHAR *)_alloca(cch * sizeof(WCHAR))) != NULL
  841. && (err = Base64EncodeW(request.pbData, request.cbData, wszRequestB64, &cch)) == ERROR_SUCCESS
  842. )
  843. {
  844. if ((*pOut = SysAllocStringLen(wszRequestB64, cch)) == NULL )
  845. {
  846. hRes = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
  847. }
  848. }
  849. else
  850. hRes = HRESULT_FROM_WIN32(err);
  851. if (request.pbData != NULL)
  852. CoTaskMemFree(request.pbData);
  853. }
  854. return hRes;
  855. }
  856. BOOL
  857. AttachFriendlyName(PCCERT_CONTEXT pContext,
  858. const CString& name,
  859. HRESULT * phRes)
  860. {
  861. BOOL bRes = TRUE;
  862. CRYPT_DATA_BLOB blob_name;
  863. blob_name.pbData = (LPBYTE)(LPCTSTR)name;
  864. blob_name.cbData = (name.GetLength() + 1) * sizeof(WCHAR);
  865. if (!(bRes = CertSetCertificateContextProperty(pContext,
  866. CERT_FRIENDLY_NAME_PROP_ID, 0, &blob_name)))
  867. {
  868. ASSERT(phRes != NULL);
  869. *phRes = HRESULT_FROM_WIN32(GetLastError());
  870. }
  871. return bRes;
  872. }
  873. BOOL GetHashProperty(PCCERT_CONTEXT pCertContext,
  874. CCryptBlob& blob,
  875. HRESULT * phRes)
  876. {
  877. DWORD cb;
  878. if (CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, NULL, &cb))
  879. {
  880. if (blob.Resize(cb))
  881. {
  882. if (CertGetCertificateContextProperty(pCertContext,
  883. CERT_SHA1_HASH_PROP_ID, blob.GetData(), &cb))
  884. return TRUE;
  885. }
  886. }
  887. *phRes = HRESULT_FROM_WIN32(GetLastError());
  888. return FALSE;
  889. }
  890. BOOL
  891. EncodeString(CString& str,
  892. CCryptBlob& blob,
  893. HRESULT * phRes)
  894. {
  895. BOOL bRes = FALSE;
  896. DWORD cb;
  897. CERT_NAME_VALUE name_value;
  898. name_value.dwValueType = CERT_RDN_BMP_STRING;
  899. name_value.Value.cbData = 0;
  900. name_value.Value.pbData = (LPBYTE)(LPCTSTR)str;
  901. if ( CryptEncodeObject(CRYPT_ASN_ENCODING, X509_UNICODE_ANY_STRING,
  902. &name_value, NULL, &cb)
  903. && blob.Resize(cb)
  904. && CryptEncodeObject(CRYPT_ASN_ENCODING, X509_UNICODE_ANY_STRING,
  905. &name_value, blob.GetData(), &cb)
  906. )
  907. {
  908. bRes = TRUE;
  909. }
  910. else
  911. *phRes = HRESULT_FROM_WIN32(GetLastError());
  912. return bRes;
  913. }
  914. #define CERTWIZ_RENEWAL_DATA ((LPCSTR)1000)
  915. BOOL
  916. EncodeBlob(CCryptBlob& in,
  917. CCryptBlob& out,
  918. HRESULT * phRes)
  919. {
  920. BOOL bRes = FALSE;
  921. DWORD cb;
  922. if ( CryptEncodeObject(CRYPT_ASN_ENCODING, CERTWIZ_RENEWAL_DATA, in, NULL, &cb)
  923. && out.Resize(cb)
  924. && CryptEncodeObject(CRYPT_ASN_ENCODING, CERTWIZ_RENEWAL_DATA, in, out.GetData(), &cb)
  925. )
  926. {
  927. bRes = TRUE;
  928. }
  929. else
  930. *phRes = HRESULT_FROM_WIN32(GetLastError());
  931. return bRes;
  932. }
  933. BOOL
  934. DecodeBlob(CCryptBlob& in,
  935. CCryptBlob& out,
  936. HRESULT * phRes)
  937. {
  938. BOOL bRes = FALSE;
  939. DWORD cb;
  940. if ( CryptDecodeObject(CRYPT_ASN_ENCODING, CERTWIZ_RENEWAL_DATA,
  941. in.GetData(),
  942. in.GetSize(),
  943. 0,
  944. NULL, &cb)
  945. && out.Resize(cb)
  946. && CryptDecodeObject(CRYPT_ASN_ENCODING, CERTWIZ_RENEWAL_DATA,
  947. in.GetData(),
  948. in.GetSize(),
  949. 0,
  950. out.GetData(),
  951. &cb)
  952. )
  953. {
  954. bRes = TRUE;
  955. }
  956. else
  957. *phRes = HRESULT_FROM_WIN32(GetLastError());
  958. return bRes;
  959. }
  960. BOOL
  961. EncodeInteger(int number,
  962. CCryptBlob& blob,
  963. HRESULT * phRes)
  964. {
  965. BOOL bRes = FALSE;
  966. DWORD cb;
  967. if ( CryptEncodeObject(CRYPT_ASN_ENCODING, X509_INTEGER,
  968. &number, NULL, &cb)
  969. && blob.Resize(cb)
  970. && CryptEncodeObject(CRYPT_ASN_ENCODING, X509_INTEGER,
  971. &number, blob.GetData(), &cb)
  972. )
  973. {
  974. bRes = TRUE;
  975. }
  976. else
  977. *phRes = HRESULT_FROM_WIN32(GetLastError());
  978. return bRes;
  979. }
  980. const WCHAR RgwchHex[] = {'0', '1', '2', '3', '4', '5', '6', '7',
  981. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  982. static BOOL
  983. FormatMemBufToString(CString& str, LPBYTE pbData, DWORD cbData)
  984. {
  985. DWORD i = 0;
  986. LPBYTE pb;
  987. DWORD numCharsInserted = 0;
  988. LPTSTR pString;
  989. //
  990. // calculate the size needed
  991. //
  992. pb = pbData;
  993. while (pb <= &(pbData[cbData-1]))
  994. {
  995. if (numCharsInserted == 4)
  996. {
  997. i += sizeof(WCHAR);
  998. numCharsInserted = 0;
  999. }
  1000. else
  1001. {
  1002. i += 2 * sizeof(WCHAR);
  1003. pb++;
  1004. numCharsInserted += 2;
  1005. }
  1006. }
  1007. if (NULL == (pString = str.GetBuffer(i)))
  1008. {
  1009. return FALSE;
  1010. }
  1011. //
  1012. // copy to the buffer
  1013. //
  1014. i = 0;
  1015. numCharsInserted = 0;
  1016. pb = pbData;
  1017. while (pb <= &(pbData[cbData-1]))
  1018. {
  1019. if (numCharsInserted == 4)
  1020. {
  1021. pString[i++] = L' ';
  1022. numCharsInserted = 0;
  1023. }
  1024. else
  1025. {
  1026. pString[i++] = RgwchHex[(*pb & 0xf0) >> 4];
  1027. pString[i++] = RgwchHex[*pb & 0x0f];
  1028. pb++;
  1029. numCharsInserted += 2;
  1030. }
  1031. }
  1032. pString[i] = 0;
  1033. str.ReleaseBuffer();
  1034. return TRUE;
  1035. }
  1036. void FormatRdnAttr(CString& str, DWORD dwValueType, CRYPT_DATA_BLOB& blob)
  1037. {
  1038. if ( CERT_RDN_ENCODED_BLOB == dwValueType
  1039. || CERT_RDN_OCTET_STRING == dwValueType
  1040. )
  1041. {
  1042. // translate the buffer to a text string
  1043. FormatMemBufToString(str, blob.pbData, blob.cbData);
  1044. }
  1045. else
  1046. {
  1047. // buffer is already a string so just copy it
  1048. str += (LPTSTR)blob.pbData;
  1049. }
  1050. }
  1051. BOOL
  1052. CreateDirectoryFromPath(LPCTSTR szPath, LPSECURITY_ATTRIBUTES lpSA)
  1053. /*++
  1054. Routine Description:
  1055. Creates the directory specified in szPath and any other "higher"
  1056. directories in the specified path that don't exist.
  1057. Arguments:
  1058. IN LPCTSTR szPath
  1059. directory path to create (assumed to be a DOS path, not a UNC)
  1060. IN LPSECURITY_ATTRIBUTES lpSA
  1061. pointer to security attributes argument used by CreateDirectory
  1062. Return Value:
  1063. TRUE if directory(ies) created
  1064. FALSE if error (GetLastError to find out why)
  1065. --*/
  1066. {
  1067. LPTSTR pLeftHalf, pNext;
  1068. CString RightHalf;
  1069. // 1. We are supporting only absolute paths. Caller should decide which
  1070. // root to use and build the path
  1071. if (PathIsRelative(szPath))
  1072. {
  1073. ASSERT(FALSE);
  1074. return FALSE;
  1075. }
  1076. pLeftHalf = (LPTSTR)szPath;
  1077. pNext = PathSkipRoot(pLeftHalf);
  1078. do {
  1079. // copy the chunk between pLeftHalf and pNext to the
  1080. // local buffer
  1081. while (pLeftHalf < pNext)
  1082. RightHalf += *pLeftHalf++;
  1083. // check if new path exists
  1084. int index = RightHalf.GetLength() - 1;
  1085. BOOL bBackslash = FALSE, bContinue = FALSE;
  1086. if (bBackslash = (RightHalf[index] == L'\\'))
  1087. {
  1088. RightHalf.SetAt(index, 0);
  1089. }
  1090. bContinue = PathIsUNCServerShare(RightHalf);
  1091. if (bBackslash)
  1092. RightHalf.SetAt(index, L'\\');
  1093. if (bContinue || PathIsDirectory(RightHalf))
  1094. continue;
  1095. else if (PathFileExists(RightHalf))
  1096. {
  1097. // we cannot create this directory
  1098. // because file with this name already exists
  1099. SetLastError(ERROR_ALREADY_EXISTS);
  1100. return FALSE;
  1101. }
  1102. else
  1103. {
  1104. // no file no directory, create
  1105. if (!CreateDirectory(RightHalf, lpSA))
  1106. return FALSE;
  1107. }
  1108. }
  1109. while (NULL != (pNext = PathFindNextComponent(pLeftHalf)));
  1110. return TRUE;
  1111. }
  1112. BOOL
  1113. CompactPathToWidth(CWnd * pControl, CString& strPath)
  1114. {
  1115. BOOL bRes;
  1116. CRect rc;
  1117. CFont * pFont = pControl->GetFont(), * pFontTmp;
  1118. CDC * pdc = pControl->GetDC(), dc;
  1119. LPTSTR pPath = strPath.GetBuffer(MAX_PATH);
  1120. dc.CreateCompatibleDC(pdc);
  1121. pFontTmp = dc.SelectObject(pFont);
  1122. pControl->GetClientRect(&rc);
  1123. bRes = PathCompactPath(dc.GetSafeHdc(), pPath, rc.Width());
  1124. dc.SelectObject(pFontTmp);
  1125. pControl->ReleaseDC(pdc);
  1126. strPath.ReleaseBuffer();
  1127. return bRes;
  1128. }
  1129. BOOL
  1130. GetKeySizeLimits(IEnroll * pEnroll,
  1131. DWORD * min, DWORD * max, DWORD * def,
  1132. BOOL bGSC,
  1133. HRESULT * phRes)
  1134. {
  1135. HCRYPTPROV hProv = NULL;
  1136. long dwProviderType;
  1137. DWORD dwFlags, cbData;
  1138. BSTR bstrProviderName;
  1139. PROV_ENUMALGS_EX paramData;
  1140. BOOL bRes = FALSE;
  1141. VERIFY(SUCCEEDED(pEnroll->get_ProviderNameWStr(&bstrProviderName)));
  1142. VERIFY(SUCCEEDED(pEnroll->get_ProviderType(&dwProviderType)));
  1143. if (!CryptAcquireContext(
  1144. &hProv,
  1145. NULL,
  1146. bstrProviderName,
  1147. dwProviderType,
  1148. CRYPT_VERIFYCONTEXT))
  1149. {
  1150. *phRes = GetLastError();
  1151. return FALSE;
  1152. }
  1153. for (int i = 0; ; i++)
  1154. {
  1155. dwFlags = 0 == i ? CRYPT_FIRST : 0;
  1156. cbData = sizeof(paramData);
  1157. if (!CryptGetProvParam(hProv, PP_ENUMALGS_EX, (BYTE*)&paramData, &cbData, dwFlags))
  1158. {
  1159. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == GetLastError())
  1160. {
  1161. // out of for loop
  1162. *phRes = S_OK;
  1163. bRes = TRUE;
  1164. }
  1165. else
  1166. {
  1167. *phRes = GetLastError();
  1168. }
  1169. break;
  1170. }
  1171. if (ALG_CLASS_KEY_EXCHANGE == GET_ALG_CLASS(paramData.aiAlgid))
  1172. {
  1173. *min = paramData.dwMinLen;
  1174. *max = paramData.dwMaxLen;
  1175. *def = paramData.dwDefaultLen;
  1176. bRes = TRUE;
  1177. *phRes = S_OK;
  1178. break;
  1179. }
  1180. }
  1181. if (NULL != hProv)
  1182. {
  1183. CryptReleaseContext(hProv, 0);
  1184. }
  1185. return bRes;
  1186. }
  1187. HRESULT ShutdownSSL(CString& machine_name, CString& server_name)
  1188. {
  1189. CString str = server_name;
  1190. str += _T("/root");
  1191. CMetaKey key(machine_name,
  1192. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  1193. METADATA_MASTER_ROOT_HANDLE,
  1194. str);
  1195. DWORD dwSslAccess;
  1196. if ( key.Succeeded()
  1197. && SUCCEEDED(key.QueryValue(MD_SSL_ACCESS_PERM, dwSslAccess))
  1198. && dwSslAccess > 0
  1199. )
  1200. {
  1201. key.SetValue(MD_SSL_ACCESS_PERM, 0);
  1202. key.DeleteValue(MD_SECURE_BINDINGS);
  1203. }
  1204. // Now we need to remove SSL setting from any virtual directory below
  1205. CError err;
  1206. CStringListEx strlDataPaths;
  1207. DWORD
  1208. dwMDIdentifier,
  1209. dwMDAttributes,
  1210. dwMDUserType,
  1211. dwMDDataType;
  1212. VERIFY(CMetaKey::GetMDFieldDef(
  1213. MD_SSL_ACCESS_PERM,
  1214. dwMDIdentifier,
  1215. dwMDAttributes,
  1216. dwMDUserType,
  1217. dwMDDataType
  1218. ));
  1219. err = key.GetDataPaths(
  1220. strlDataPaths,
  1221. dwMDIdentifier,
  1222. dwMDDataType
  1223. );
  1224. if (err.Succeeded() && !strlDataPaths.IsEmpty())
  1225. {
  1226. POSITION pos = strlDataPaths.GetHeadPosition();
  1227. while (pos)
  1228. {
  1229. CString& str = strlDataPaths.GetNext(pos);
  1230. if ( SUCCEEDED(key.QueryValue(MD_SSL_ACCESS_PERM,
  1231. dwSslAccess, NULL, str))
  1232. && dwSslAccess > 0
  1233. )
  1234. {
  1235. key.SetValue(MD_SSL_ACCESS_PERM, 0, NULL, str);
  1236. key.DeleteValue(MD_SECURE_BINDINGS, str);
  1237. }
  1238. }
  1239. }
  1240. return key.QueryResult();
  1241. }