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.

2133 lines
55 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. #include "cryptui.h"
  14. // for certobj object
  15. #include "certobj.h"
  16. #define ISNUM(cChar) ((cChar >= _T('0')) && (cChar <= _T('9'))) ? (TRUE) : (FALSE)
  17. const CLSID CLSID_CCertConfig =
  18. {0x372fce38, 0x4324, 0x11d0, {0x88, 0x10, 0x00, 0xa0, 0xc9, 0x03, 0xb8, 0x3c}};
  19. const GUID IID_ICertConfig =
  20. {0x372fce34, 0x4324, 0x11d0, {0x88, 0x10, 0x00, 0xa0, 0xc9, 0x03, 0xb8, 0x3c}};
  21. #define CRYPTUI_MAX_STRING_SIZE 768
  22. #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
  23. BOOL
  24. GetOnlineCAList(CStringList& list, const CString& certType, HRESULT * phRes)
  25. {
  26. BOOL bRes = TRUE;
  27. HRESULT hr = S_OK;
  28. DWORD errBefore = GetLastError();
  29. DWORD dwCACount = 0;
  30. HCAINFO hCurCAInfo = NULL;
  31. HCAINFO hPreCAInfo = NULL;
  32. if (certType.IsEmpty())
  33. return FALSE;
  34. *phRes = CAFindByCertType(certType, NULL, 0, &hCurCAInfo);
  35. if (FAILED(*phRes) || NULL == hCurCAInfo)
  36. {
  37. if (S_OK == hr)
  38. hr=E_FAIL;
  39. return FALSE;
  40. }
  41. //get the CA count
  42. if (0 == (dwCACount = CACountCAs(hCurCAInfo)))
  43. {
  44. *phRes = E_FAIL;
  45. return FALSE;
  46. }
  47. WCHAR ** ppwstrName, ** ppwstrMachine;
  48. while (hCurCAInfo)
  49. {
  50. //get the CA information
  51. if ( SUCCEEDED(CAGetCAProperty(hCurCAInfo, CA_PROP_DISPLAY_NAME, &ppwstrName))
  52. && SUCCEEDED(CAGetCAProperty(hCurCAInfo, CA_PROP_DNSNAME, &ppwstrMachine))
  53. )
  54. {
  55. CString config;
  56. config = *ppwstrMachine;
  57. config += L"\\";
  58. config += *ppwstrName;
  59. list.AddTail(config);
  60. CAFreeCAProperty(hCurCAInfo, ppwstrName);
  61. CAFreeCAProperty(hCurCAInfo, ppwstrMachine);
  62. }
  63. else
  64. {
  65. bRes = FALSE;
  66. break;
  67. }
  68. hPreCAInfo = hCurCAInfo;
  69. if (FAILED(*phRes = CAEnumNextCA(hPreCAInfo, &hCurCAInfo)))
  70. {
  71. bRes = FALSE;
  72. break;
  73. }
  74. CACloseCA(hPreCAInfo);
  75. hPreCAInfo = NULL;
  76. }
  77. if (hPreCAInfo)
  78. CACloseCA(hPreCAInfo);
  79. if (hCurCAInfo)
  80. CACloseCA(hCurCAInfo);
  81. SetLastError(errBefore);
  82. return bRes;
  83. }
  84. PCCERT_CONTEXT
  85. GetRequestContext(CCryptBlob& pkcs7, HRESULT * phRes)
  86. {
  87. ASSERT(phRes != NULL);
  88. BOOL bRes = FALSE;
  89. HCERTSTORE hStoreMsg = NULL;
  90. PCCERT_CONTEXT pCertContextMsg = NULL;
  91. if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
  92. (PCERT_BLOB)pkcs7,
  93. (CERT_QUERY_CONTENT_FLAG_CERT |
  94. CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED |
  95. CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE |
  96. CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED) ,
  97. CERT_QUERY_FORMAT_FLAG_ALL,
  98. 0,
  99. NULL,
  100. NULL,
  101. NULL,
  102. &hStoreMsg,
  103. NULL,
  104. NULL)
  105. || NULL == (pCertContextMsg = CertFindCertificateInStore(
  106. hStoreMsg,
  107. X509_ASN_ENCODING,
  108. 0,
  109. CERT_FIND_ANY,
  110. NULL,
  111. NULL))
  112. )
  113. {
  114. *phRes = HRESULT_FROM_WIN32(GetLastError());
  115. }
  116. return pCertContextMsg;
  117. }
  118. BOOL GetRequestInfoFromPKCS10(CCryptBlob& pkcs10,
  119. PCERT_REQUEST_INFO * pReqInfo,
  120. HRESULT * phRes)
  121. {
  122. ASSERT(pReqInfo != NULL);
  123. ASSERT(phRes != NULL);
  124. BOOL bRes = FALSE;
  125. DWORD req_info_size;
  126. if (!(bRes = CryptDecodeObjectEx(
  127. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  128. X509_CERT_REQUEST_TO_BE_SIGNED,
  129. pkcs10.GetData(),
  130. pkcs10.GetSize(),
  131. CRYPT_DECODE_ALLOC_FLAG,
  132. NULL,
  133. pReqInfo,
  134. &req_info_size)))
  135. {
  136. TRACE(_T("Error from CryptDecodeObjectEx: %xd\n"), GetLastError());
  137. *phRes = HRESULT_FROM_WIN32(GetLastError());
  138. }
  139. return bRes;
  140. }
  141. #if 0
  142. // This function extracts data from pkcs7 format
  143. BOOL GetRequestInfoFromRenewalRequest(CCryptBlob& renewal_req,
  144. PCCERT_CONTEXT * pSignerCert,
  145. HCERTSTORE hStore,
  146. PCERT_REQUEST_INFO * pReqInfo,
  147. HRESULT * phRes)
  148. {
  149. BOOL bRes;
  150. CRYPT_DECRYPT_MESSAGE_PARA decr_para;
  151. CRYPT_VERIFY_MESSAGE_PARA ver_para;
  152. decr_para.cbSize = sizeof(decr_para);
  153. decr_para.dwMsgAndCertEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
  154. decr_para.cCertStore = 1;
  155. decr_para.rghCertStore = &hStore;
  156. ver_para.cbSize = sizeof(ver_para);
  157. ver_para.dwMsgAndCertEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
  158. ver_para.hCryptProv = 0;
  159. ver_para.pfnGetSignerCertificate = NULL;
  160. ver_para.pvGetArg = NULL;
  161. DWORD dwMsgType;
  162. DWORD dwInnerContentType;
  163. DWORD cbDecoded;
  164. if (bRes = CryptDecodeMessage(
  165. CMSG_SIGNED_FLAG,
  166. &decr_para,
  167. &ver_para,
  168. 0,
  169. renewal_req.GetData(),
  170. renewal_req.GetSize(),
  171. 0,
  172. &dwMsgType,
  173. &dwInnerContentType,
  174. NULL,
  175. &cbDecoded,
  176. NULL,
  177. pSignerCert))
  178. {
  179. CCryptBlobLocal decoded_req;
  180. decoded_req.Resize(cbDecoded);
  181. if (bRes = CryptDecodeMessage(
  182. CMSG_SIGNED_FLAG,
  183. &decr_para,
  184. &ver_para,
  185. 0,
  186. renewal_req.GetData(),
  187. renewal_req.GetSize(),
  188. 0,
  189. &dwMsgType,
  190. &dwInnerContentType,
  191. decoded_req.GetData(),
  192. &cbDecoded,
  193. NULL,
  194. pSignerCert))
  195. {
  196. bRes = GetRequestInfoFromPKCS10(decoded_req,
  197. pReqInfo, phRes);
  198. }
  199. }
  200. if (!bRes)
  201. {
  202. *phRes = HRESULT_FROM_WIN32(GetLastError());
  203. }
  204. return bRes;
  205. }
  206. #endif
  207. HCERTSTORE
  208. OpenRequestStore(IEnroll * pEnroll, HRESULT * phResult)
  209. {
  210. ASSERT(NULL != phResult);
  211. HCERTSTORE hStore = NULL;
  212. WCHAR * bstrStoreName, * bstrStoreType;
  213. long dwStoreFlags;
  214. VERIFY(SUCCEEDED(pEnroll->get_RequestStoreNameWStr(&bstrStoreName)));
  215. VERIFY(SUCCEEDED(pEnroll->get_RequestStoreTypeWStr(&bstrStoreType)));
  216. VERIFY(SUCCEEDED(pEnroll->get_RequestStoreFlags(&dwStoreFlags)));
  217. size_t store_type_len = _tcslen(bstrStoreType);
  218. char * szStoreProvider = (char *)_alloca(store_type_len + 1);
  219. ASSERT(szStoreProvider != NULL);
  220. size_t n = wcstombs(szStoreProvider, bstrStoreType, store_type_len);
  221. szStoreProvider[n] = '\0';
  222. hStore = CertOpenStore(
  223. szStoreProvider,
  224. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  225. NULL,
  226. dwStoreFlags,
  227. bstrStoreName
  228. );
  229. CoTaskMemFree(bstrStoreName);
  230. CoTaskMemFree(bstrStoreType);
  231. if (hStore == NULL)
  232. *phResult = HRESULT_FROM_WIN32(GetLastError());
  233. return hStore;
  234. }
  235. HCERTSTORE
  236. OpenMyStore(IEnroll * pEnroll, HRESULT * phResult)
  237. {
  238. ASSERT(NULL != phResult);
  239. HCERTSTORE hStore = NULL;
  240. BSTR bstrStoreName, bstrStoreType;
  241. long dwStoreFlags;
  242. VERIFY(SUCCEEDED(pEnroll->get_MyStoreNameWStr(&bstrStoreName)));
  243. VERIFY(SUCCEEDED(pEnroll->get_MyStoreTypeWStr(&bstrStoreType)));
  244. VERIFY(SUCCEEDED(pEnroll->get_MyStoreFlags(&dwStoreFlags)));
  245. size_t store_type_len = _tcslen(bstrStoreType);
  246. char * szStoreProvider = (char *)_alloca(store_type_len + 1);
  247. ASSERT(szStoreProvider != NULL);
  248. size_t n = wcstombs(szStoreProvider, bstrStoreType, store_type_len);
  249. ASSERT(n != -1);
  250. // this converter doesn't set zero byte!!!
  251. szStoreProvider[n] = '\0';
  252. hStore = CertOpenStore(
  253. szStoreProvider,
  254. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  255. NULL,
  256. dwStoreFlags,
  257. bstrStoreName
  258. );
  259. CoTaskMemFree(bstrStoreName);
  260. CoTaskMemFree(bstrStoreType);
  261. if (hStore == NULL)
  262. *phResult = HRESULT_FROM_WIN32(GetLastError());
  263. return hStore;
  264. }
  265. BOOL
  266. GetStringProperty(PCCERT_CONTEXT pCertContext,
  267. DWORD propId,
  268. CString& str,
  269. HRESULT * phRes)
  270. {
  271. BOOL bRes = FALSE;
  272. DWORD cb;
  273. BYTE * prop;
  274. // compare property value
  275. if ( CertGetCertificateContextProperty(pCertContext, propId, NULL, &cb)
  276. && (NULL != (prop = (BYTE *)_alloca(cb)))
  277. && CertGetCertificateContextProperty(pCertContext, propId, prop, &cb)
  278. )
  279. {
  280. // decode this instance name property
  281. DWORD cbData = 0;
  282. void * pData = NULL;
  283. if ( CryptDecodeObject(CRYPT_ASN_ENCODING, X509_UNICODE_ANY_STRING,
  284. prop, cb, 0, NULL, &cbData)
  285. && NULL != (pData = _alloca(cbData))
  286. && CryptDecodeObject(CRYPT_ASN_ENCODING, X509_UNICODE_ANY_STRING,
  287. prop, cb, 0, pData, &cbData)
  288. )
  289. {
  290. CERT_NAME_VALUE * pName = (CERT_NAME_VALUE *)pData;
  291. DWORD cch = pName->Value.cbData/sizeof(TCHAR);
  292. void * p = str.GetBuffer(cch);
  293. memcpy(p, pName->Value.pbData, pName->Value.cbData);
  294. str.ReleaseBuffer(cch);
  295. bRes = TRUE;
  296. }
  297. }
  298. if (!bRes)
  299. *phRes = HRESULT_FROM_WIN32(GetLastError());
  300. return bRes;
  301. }
  302. BOOL
  303. GetBlobProperty(PCCERT_CONTEXT pCertContext,
  304. DWORD propId,
  305. CCryptBlob& blob,
  306. HRESULT * phRes)
  307. {
  308. BOOL bRes = FALSE;
  309. DWORD cb;
  310. // compare property value
  311. if ( CertGetCertificateContextProperty(pCertContext, propId, NULL, &cb)
  312. && blob.Resize(cb)
  313. && CertGetCertificateContextProperty(pCertContext, propId, blob.GetData(), &cb)
  314. )
  315. {
  316. bRes = TRUE;
  317. }
  318. if (!bRes)
  319. *phRes = HRESULT_FROM_WIN32(GetLastError());
  320. return bRes;
  321. }
  322. PCCERT_CONTEXT
  323. GetPendingDummyCert(const CString& inst_name,
  324. IEnroll * pEnroll,
  325. HRESULT * phRes)
  326. {
  327. PCCERT_CONTEXT pRes = NULL;
  328. HCERTSTORE hStore = OpenRequestStore(pEnroll, phRes);
  329. if (hStore != NULL)
  330. {
  331. DWORD dwPropId = CERTWIZ_INSTANCE_NAME_PROP_ID;
  332. PCCERT_CONTEXT pDummyCert = NULL;
  333. while (NULL != (pDummyCert = CertFindCertificateInStore(hStore,
  334. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  335. 0, CERT_FIND_PROPERTY,
  336. (LPVOID)&dwPropId, pDummyCert)))
  337. {
  338. CString str;
  339. if (GetStringProperty(pDummyCert, dwPropId, str, phRes))
  340. {
  341. if (str.CompareNoCase(inst_name) == 0)
  342. {
  343. pRes = pDummyCert;
  344. break;
  345. }
  346. }
  347. }
  348. CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
  349. }
  350. return pRes;
  351. }
  352. PCCERT_CONTEXT
  353. GetReqCertByKey(IEnroll * pEnroll, CERT_PUBLIC_KEY_INFO * pKeyInfo, HRESULT * phResult)
  354. {
  355. PCCERT_CONTEXT pRes = NULL;
  356. HCERTSTORE hStore = OpenRequestStore(pEnroll, phResult);
  357. if (hStore != NULL)
  358. {
  359. if (NULL != (pRes = CertFindCertificateInStore(hStore,
  360. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  361. 0, CERT_FIND_PUBLIC_KEY, (LPVOID)pKeyInfo, NULL)))
  362. {
  363. *phResult = S_OK;
  364. }
  365. VERIFY(SUCCEEDED(CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG)));
  366. }
  367. return pRes;
  368. }
  369. #define CERT_QUERY_CONTENT_FLAGS\
  370. CERT_QUERY_CONTENT_FLAG_CERT\
  371. |CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED\
  372. |CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE\
  373. |CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
  374. PCCERT_CONTEXT
  375. GetCertContextFromPKCS7File(const CString& resp_file_name,
  376. CERT_PUBLIC_KEY_INFO * pKeyInfo,
  377. HRESULT * phResult)
  378. {
  379. ASSERT(phResult != NULL);
  380. PCCERT_CONTEXT pRes = NULL;
  381. HANDLE hFile;
  382. if (INVALID_HANDLE_VALUE != (hFile = CreateFile(resp_file_name,
  383. GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
  384. FILE_ATTRIBUTE_NORMAL, NULL)))
  385. {
  386. // find the length of the buffer
  387. DWORD cbData = GetFileSize(hFile, NULL);
  388. BYTE * pbData;
  389. // alloc temp buffer
  390. if ((pbData = (BYTE *)_alloca(cbData)) != NULL)
  391. {
  392. DWORD cb = 0;
  393. if (ReadFile(hFile, pbData, cbData, &cb, NULL))
  394. {
  395. ASSERT(cb == cbData);
  396. pRes = GetCertContextFromPKCS7(pbData, cb, pKeyInfo, phResult);
  397. }
  398. else
  399. *phResult = HRESULT_FROM_WIN32(GetLastError());
  400. }
  401. CloseHandle(hFile);
  402. }
  403. else
  404. *phResult = HRESULT_FROM_WIN32(GetLastError());
  405. return pRes;
  406. }
  407. PCCERT_CONTEXT
  408. GetCertContextFromPKCS7(const BYTE * pbData,
  409. DWORD cbData,
  410. CERT_PUBLIC_KEY_INFO * pKeyInfo,
  411. HRESULT * phResult)
  412. {
  413. ASSERT(phResult != NULL);
  414. PCCERT_CONTEXT pRes = NULL;
  415. CRYPT_DATA_BLOB blob;
  416. memset(&blob, 0, sizeof(CRYPT_DATA_BLOB));
  417. blob.cbData = cbData;
  418. blob.pbData = (BYTE *)pbData;
  419. HCERTSTORE hStoreMsg = NULL;
  420. if(CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
  421. &blob,
  422. (CERT_QUERY_CONTENT_FLAG_CERT |
  423. CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED |
  424. CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE |
  425. CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED) ,
  426. CERT_QUERY_FORMAT_FLAG_ALL,
  427. 0,
  428. NULL,
  429. NULL,
  430. NULL,
  431. &hStoreMsg,
  432. NULL,
  433. NULL))
  434. {
  435. if (pKeyInfo != NULL)
  436. pRes = CertFindCertificateInStore(hStoreMsg,
  437. X509_ASN_ENCODING,
  438. 0,
  439. CERT_FIND_PUBLIC_KEY,
  440. pKeyInfo,
  441. NULL);
  442. else
  443. pRes = CertFindCertificateInStore(hStoreMsg,
  444. X509_ASN_ENCODING,
  445. 0,
  446. CERT_FIND_ANY,
  447. NULL,
  448. NULL);
  449. if (pRes == NULL)
  450. *phResult = HRESULT_FROM_WIN32(GetLastError());
  451. CertCloseStore(hStoreMsg, CERT_CLOSE_STORE_CHECK_FLAG);
  452. }
  453. else
  454. *phResult = HRESULT_FROM_WIN32(GetLastError());
  455. return pRes;
  456. }
  457. BOOL
  458. FormatDateString(CString& str, FILETIME ft, BOOL fIncludeTime, BOOL fLongFormat)
  459. {
  460. int cch;
  461. int cch2;
  462. LPWSTR psz;
  463. SYSTEMTIME st;
  464. FILETIME localTime;
  465. if (!FileTimeToLocalFileTime(&ft, &localTime))
  466. {
  467. return FALSE;
  468. }
  469. if (!FileTimeToSystemTime(&localTime, &st))
  470. {
  471. //
  472. // if the conversion to local time failed, then just use the original time
  473. //
  474. if (!FileTimeToSystemTime(&ft, &st))
  475. {
  476. return FALSE;
  477. }
  478. }
  479. cch = (GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &st, NULL, NULL, 0) +
  480. GetDateFormat(LOCALE_SYSTEM_DEFAULT, fLongFormat ? DATE_LONGDATE : 0, &st, NULL, NULL, 0) + 5);
  481. if (NULL == (psz = str.GetBuffer((cch+5) * sizeof(WCHAR))))
  482. {
  483. return FALSE;
  484. }
  485. cch2 = GetDateFormat(LOCALE_SYSTEM_DEFAULT, fLongFormat ? DATE_LONGDATE : 0, &st, NULL, psz, cch);
  486. if (fIncludeTime)
  487. {
  488. psz[cch2-1] = ' ';
  489. GetTimeFormat(LOCALE_SYSTEM_DEFAULT, TIME_NOSECONDS, &st, NULL, &psz[cch2], cch-cch2);
  490. }
  491. str.ReleaseBuffer();
  492. return TRUE;
  493. }
  494. BOOL MyGetOIDInfo(LPWSTR string, DWORD stringSize, LPSTR pszObjId)
  495. {
  496. PCCRYPT_OID_INFO pOIDInfo;
  497. if (NULL != (pOIDInfo = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, pszObjId, 0)))
  498. {
  499. if ((DWORD)wcslen(pOIDInfo->pwszName)+1 <= stringSize)
  500. {
  501. wcscpy(string, pOIDInfo->pwszName);
  502. }
  503. else
  504. {
  505. return FALSE;
  506. }
  507. }
  508. else
  509. {
  510. return (MultiByteToWideChar(CP_ACP, 0, pszObjId, -1, string, stringSize) != 0);
  511. }
  512. return TRUE;
  513. }
  514. BOOL
  515. GetKeyUsageProperty(PCCERT_CONTEXT pCertContext,
  516. CERT_ENHKEY_USAGE ** pKeyUsage,
  517. BOOL fPropertiesOnly,
  518. HRESULT * phRes)
  519. {
  520. DWORD cb = 0;
  521. BOOL bRes = FALSE;
  522. if (!CertGetEnhancedKeyUsage(pCertContext,
  523. fPropertiesOnly ? CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG : 0,
  524. NULL,
  525. &cb))
  526. {
  527. *phRes = HRESULT_FROM_WIN32(GetLastError());
  528. goto ErrExit;
  529. }
  530. if (NULL == (*pKeyUsage = (CERT_ENHKEY_USAGE *)malloc(cb)))
  531. {
  532. *phRes = E_OUTOFMEMORY;
  533. goto ErrExit;
  534. }
  535. if (!CertGetEnhancedKeyUsage (pCertContext,
  536. fPropertiesOnly ? CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG : 0,
  537. *pKeyUsage,
  538. &cb))
  539. {
  540. free(*pKeyUsage);
  541. *phRes = HRESULT_FROM_WIN32(GetLastError());
  542. goto ErrExit;
  543. }
  544. *phRes = S_OK;
  545. bRes = TRUE;
  546. ErrExit:
  547. return bRes;
  548. }
  549. BOOL
  550. GetFriendlyName(PCCERT_CONTEXT pCertContext,
  551. CString& name,
  552. HRESULT * phRes)
  553. {
  554. BOOL bRes = FALSE;
  555. DWORD cb;
  556. BYTE * pName = NULL;
  557. if ( CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, NULL, &cb)
  558. && NULL != (pName = (BYTE *)name.GetBuffer((cb + 1)/sizeof(TCHAR)))
  559. && CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, pName, &cb)
  560. )
  561. {
  562. pName[cb] = 0;
  563. bRes = TRUE;
  564. }
  565. else
  566. {
  567. *phRes = HRESULT_FROM_WIN32(GetLastError());
  568. }
  569. if (pName != NULL && name.IsEmpty())
  570. {
  571. name.ReleaseBuffer();
  572. }
  573. return bRes;
  574. }
  575. BOOL
  576. GetNameString(PCCERT_CONTEXT pCertContext,
  577. DWORD type,
  578. DWORD flag,
  579. CString& name,
  580. HRESULT * phRes)
  581. {
  582. BOOL bRes = FALSE;
  583. LPTSTR pName;
  584. DWORD cchName = CertGetNameString(pCertContext, type, flag, NULL, NULL, 0);
  585. if (cchName > 1 && (NULL != (pName = name.GetBuffer(cchName))))
  586. {
  587. bRes = (1 != CertGetNameString(pCertContext, type, flag, NULL, pName, cchName));
  588. name.ReleaseBuffer();
  589. }
  590. else
  591. {
  592. *phRes = HRESULT_FROM_WIN32(GetLastError());
  593. }
  594. return bRes;
  595. }
  596. BOOL
  597. ContainsKeyUsageProperty(PCCERT_CONTEXT pCertContext,
  598. CArray<LPCSTR, LPCSTR>& uses,
  599. HRESULT * phRes
  600. )
  601. {
  602. BOOL bRes = FALSE;
  603. CERT_ENHKEY_USAGE * pKeyUsage = NULL;
  604. if ( uses.GetSize() > 0
  605. && GetKeyUsageProperty(pCertContext, &pKeyUsage, FALSE, phRes)
  606. )
  607. {
  608. if (pKeyUsage->cUsageIdentifier == 0)
  609. {
  610. bRes = FALSE;
  611. }
  612. else
  613. {
  614. for (DWORD i = 0; i < pKeyUsage->cUsageIdentifier; i++)
  615. {
  616. // Our friends from CAPI made this property ASCII even for
  617. // UNICODE program
  618. for (int n = 0; n < uses.GetSize(); n++)
  619. {
  620. if (strstr(pKeyUsage->rgpszUsageIdentifier[i], uses[n]) != NULL)
  621. {
  622. bRes = TRUE;
  623. break;
  624. }
  625. }
  626. }
  627. }
  628. free(pKeyUsage);
  629. }
  630. return bRes;
  631. }
  632. BOOL
  633. FormatEnhancedKeyUsageString(CString& str,
  634. PCCERT_CONTEXT pCertContext,
  635. BOOL fPropertiesOnly,
  636. BOOL fMultiline,
  637. HRESULT * phRes)
  638. {
  639. CERT_ENHKEY_USAGE * pKeyUsage = NULL;
  640. WCHAR szText[CRYPTUI_MAX_STRING_SIZE];
  641. BOOL bRes = FALSE;
  642. if (GetKeyUsageProperty(pCertContext, &pKeyUsage, fPropertiesOnly, phRes))
  643. {
  644. // loop for each usage and add it to the display string
  645. for (DWORD i = 0; i < pKeyUsage->cUsageIdentifier; i++)
  646. {
  647. if (!(bRes = MyGetOIDInfo(szText, ARRAYSIZE(szText), pKeyUsage->rgpszUsageIdentifier[i])))
  648. break;
  649. // add delimeter if not first iteration
  650. if (i != 0)
  651. {
  652. str += fMultiline ? L"\n" : L", ";
  653. }
  654. // add the enhanced key usage string
  655. str += szText;
  656. }
  657. free (pKeyUsage);
  658. }
  659. else
  660. {
  661. str.LoadString(IDS_ANY);
  662. bRes = TRUE;
  663. }
  664. return bRes;
  665. }
  666. BOOL
  667. GetServerComment(const CString& machine_name,
  668. const CString& server_name,
  669. CString& comment,
  670. HRESULT * phResult)
  671. {
  672. ASSERT(!machine_name.IsEmpty());
  673. ASSERT(!server_name.IsEmpty());
  674. *phResult = S_OK;
  675. CComAuthInfo auth(machine_name);
  676. CMetaKey key(&auth,
  677. server_name,
  678. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE
  679. );
  680. if (key.Succeeded())
  681. {
  682. return SUCCEEDED(*phResult = key.QueryValue(MD_SERVER_COMMENT, comment));
  683. }
  684. else
  685. {
  686. *phResult = key.QueryResult();
  687. return FALSE;
  688. }
  689. }
  690. /*
  691. GetInstalledCert
  692. Function reads cert hash attribute from metabase
  693. using machine_name and server name as server instance
  694. description, then looks in MY store for a certificate
  695. with hash equal found in metabase.
  696. Return is cert context pointer or NULL, if cert wasn't
  697. found or certificate store wasn't opened.
  698. On return HRESULT * is filled by error code.
  699. */
  700. PCCERT_CONTEXT
  701. GetInstalledCert(const CString& machine_name,
  702. const CString& server_name,
  703. IEnroll * pEnroll,
  704. HRESULT * phResult)
  705. {
  706. ASSERT(pEnroll != NULL);
  707. ASSERT(phResult != NULL);
  708. ASSERT(!machine_name.IsEmpty());
  709. ASSERT(!server_name.IsEmpty());
  710. PCCERT_CONTEXT pCert = NULL;
  711. *phResult = S_OK;
  712. CComAuthInfo auth(machine_name);
  713. CMetaKey key(&auth, server_name,
  714. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE
  715. );
  716. if (key.Succeeded())
  717. {
  718. CString store_name;
  719. CBlob hash;
  720. if ( SUCCEEDED(*phResult = key.QueryValue(MD_SSL_CERT_STORE_NAME, store_name))
  721. && SUCCEEDED(*phResult = key.QueryValue(MD_SSL_CERT_HASH, hash))
  722. )
  723. {
  724. // Open MY store. We assume that store type and flags
  725. // cannot be changed between installation and unistallation
  726. // of the sertificate.
  727. HCERTSTORE hStore = OpenMyStore(pEnroll, phResult);
  728. ASSERT(hStore != NULL);
  729. if (hStore != NULL)
  730. {
  731. // Now we need to find cert by hash
  732. CRYPT_HASH_BLOB crypt_hash;
  733. crypt_hash.cbData = hash.GetSize();
  734. crypt_hash.pbData = hash.GetData();
  735. pCert = CertFindCertificateInStore(hStore,
  736. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  737. 0, CERT_FIND_HASH, (LPVOID)&crypt_hash, NULL);
  738. if (pCert == NULL)
  739. *phResult = HRESULT_FROM_WIN32(GetLastError());
  740. VERIFY(CertCloseStore(hStore, 0));
  741. }
  742. }
  743. }
  744. else
  745. *phResult = key.QueryResult();
  746. return pCert;
  747. }
  748. /*
  749. GetInstalledCert
  750. Function reads cert hash attribute from metabase
  751. using machine_name and server name as server instance
  752. description, then looks in MY store for a certificate
  753. with hash equal found in metabase.
  754. Return is cert context pointer or NULL, if cert wasn't
  755. found or certificate store wasn't opened.
  756. On return HRESULT * is filled by error code.
  757. */
  758. CRYPT_HASH_BLOB *
  759. GetInstalledCertHash(const CString& machine_name,
  760. const CString& server_name,
  761. IEnroll * pEnroll,
  762. HRESULT * phResult)
  763. {
  764. ASSERT(pEnroll != NULL);
  765. ASSERT(phResult != NULL);
  766. ASSERT(!machine_name.IsEmpty());
  767. ASSERT(!server_name.IsEmpty());
  768. CRYPT_HASH_BLOB * pHashBlob = NULL;
  769. *phResult = S_OK;
  770. CComAuthInfo auth(machine_name);
  771. CMetaKey key(&auth, server_name,
  772. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE
  773. );
  774. if (key.Succeeded())
  775. {
  776. CString store_name;
  777. CBlob hash;
  778. if ( SUCCEEDED(*phResult = key.QueryValue(MD_SSL_CERT_STORE_NAME, store_name))
  779. && SUCCEEDED(*phResult = key.QueryValue(MD_SSL_CERT_HASH, hash))
  780. )
  781. {
  782. pHashBlob = new CRYPT_HASH_BLOB;
  783. if (pHashBlob)
  784. {
  785. pHashBlob->cbData = hash.GetSize();
  786. pHashBlob->pbData = (BYTE *) ::CoTaskMemAlloc(pHashBlob->cbData);
  787. if (pHashBlob->pbData)
  788. {
  789. memcpy(pHashBlob->pbData,hash.GetData(),pHashBlob->cbData);
  790. }
  791. }
  792. }
  793. }
  794. else
  795. {
  796. *phResult = key.QueryResult();
  797. }
  798. return pHashBlob;
  799. }
  800. /*
  801. InstallHashToMetabase
  802. Function writes hash array to metabase. After that IIS
  803. could use certificate with that hash from MY store.
  804. Function expects server_name in format lm\w3svc\<number>,
  805. i.e. from root node down to virtual server
  806. */
  807. BOOL
  808. InstallHashToMetabase(CRYPT_HASH_BLOB * pHash,
  809. const CString& machine_name,
  810. const CString& server_name,
  811. HRESULT * phResult)
  812. {
  813. BOOL bRes = FALSE;
  814. CComAuthInfo auth(machine_name);
  815. CMetaKey key(&auth, server_name,
  816. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE
  817. );
  818. if (key.Succeeded())
  819. {
  820. CBlob blob;
  821. blob.SetValue(pHash->cbData, pHash->pbData, TRUE);
  822. bRes = SUCCEEDED(*phResult = key.SetValue(MD_SSL_CERT_HASH, blob))
  823. && SUCCEEDED(*phResult = key.SetValue(MD_SSL_CERT_STORE_NAME, CString(L"MY")));
  824. }
  825. else
  826. {
  827. TRACE(_T("Failed to open metabase key. Error 0x%x\n"), key.QueryResult());
  828. *phResult = key.QueryResult();
  829. }
  830. return bRes;
  831. }
  832. /*
  833. InstallCertByHash
  834. Function looks in MY store for certificate which has hash
  835. equal to pHash parameter. If cert is found, it is installed
  836. to metabase.
  837. This function is used after xenroll accept() method, which
  838. puts certificate to store
  839. */
  840. BOOL
  841. InstallCertByHash(CRYPT_HASH_BLOB * pHash,
  842. const CString& machine_name,
  843. const CString& server_name,
  844. IEnroll * pEnroll,
  845. HRESULT * phResult)
  846. {
  847. BOOL bRes = FALSE;
  848. // we are looking to MY store only
  849. HCERTSTORE hStore = OpenMyStore(pEnroll, phResult);
  850. if (hStore != NULL)
  851. {
  852. PCCERT_CONTEXT pCert = CertFindCertificateInStore(hStore,
  853. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  854. 0, CERT_FIND_HASH, (LPVOID)pHash, NULL);
  855. // now install cert info to IIS MetaBase
  856. if (pCert != NULL)
  857. {
  858. bRes = InstallHashToMetabase(pHash,
  859. machine_name, server_name, phResult);
  860. CertFreeCertificateContext(pCert);
  861. }
  862. else
  863. {
  864. TRACE(_T("FAILED: certificate installation, error 0x%x\n"), GetLastError());
  865. // We definitely need to store the hash of the cert, so error out
  866. *phResult = HRESULT_FROM_WIN32(GetLastError());
  867. }
  868. VERIFY(CertCloseStore(hStore, 0));
  869. }
  870. return bRes;
  871. }
  872. HRESULT
  873. CreateRequest_Base64(const BSTR bstr_dn,
  874. IEnroll * pEnroll,
  875. BSTR csp_name,
  876. DWORD csp_type,
  877. BSTR * pOut)
  878. {
  879. ASSERT(pOut != NULL);
  880. ASSERT(bstr_dn != NULL);
  881. HRESULT hRes = S_OK;
  882. CString strUsage(szOID_PKIX_KP_SERVER_AUTH);
  883. CRYPT_DATA_BLOB request = {0, NULL};
  884. pEnroll->put_ProviderType(csp_type);
  885. pEnroll->put_ProviderNameWStr(csp_name);
  886. if (SUCCEEDED(hRes = pEnroll->createPKCS10WStr(
  887. bstr_dn,
  888. (LPTSTR)(LPCTSTR)strUsage,
  889. &request)))
  890. {
  891. WCHAR * wszRequestB64 = NULL;
  892. DWORD cch = 0;
  893. DWORD err = ERROR_SUCCESS;
  894. // BASE64 encode pkcs 10
  895. if ( (err = Base64EncodeW(request.pbData, request.cbData, NULL, &cch)) == ERROR_SUCCESS
  896. && (wszRequestB64 = (WCHAR *)_alloca(cch * sizeof(WCHAR))) != NULL
  897. && (err = Base64EncodeW(request.pbData, request.cbData, wszRequestB64, &cch)) == ERROR_SUCCESS
  898. )
  899. {
  900. if ((*pOut = SysAllocStringLen(wszRequestB64, cch)) == NULL )
  901. {
  902. hRes = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
  903. }
  904. }
  905. else
  906. hRes = HRESULT_FROM_WIN32(err);
  907. if (request.pbData != NULL)
  908. CoTaskMemFree(request.pbData);
  909. }
  910. return hRes;
  911. }
  912. BOOL
  913. AttachFriendlyName(PCCERT_CONTEXT pContext,
  914. const CString& name,
  915. HRESULT * phRes)
  916. {
  917. IISDebugOutput(_T("AttachFriendlyName:name=%s,start\n"),name);
  918. BOOL bRes = TRUE;
  919. CRYPT_DATA_BLOB blob_name;
  920. blob_name.pbData = (LPBYTE)(LPCTSTR)name;
  921. blob_name.cbData = (name.GetLength() + 1) * sizeof(WCHAR);
  922. if (!(bRes = CertSetCertificateContextProperty(pContext,
  923. CERT_FRIENDLY_NAME_PROP_ID, 0, &blob_name)))
  924. {
  925. ASSERT(phRes != NULL);
  926. *phRes = HRESULT_FROM_WIN32(GetLastError());
  927. }
  928. else
  929. {
  930. IISDebugOutput(_T("AttachFriendlyName:name=%s,SUCCESS\n"),name);
  931. }
  932. IISDebugOutput(_T("AttachFriendlyName:name=%s,end\n"),name);
  933. return bRes;
  934. }
  935. BOOL GetHashProperty(PCCERT_CONTEXT pCertContext,
  936. CCryptBlob& blob,
  937. HRESULT * phRes)
  938. {
  939. DWORD cb;
  940. if (CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, NULL, &cb))
  941. {
  942. if (blob.Resize(cb))
  943. {
  944. if (CertGetCertificateContextProperty(pCertContext,
  945. CERT_SHA1_HASH_PROP_ID, blob.GetData(), &cb))
  946. return TRUE;
  947. }
  948. }
  949. *phRes = HRESULT_FROM_WIN32(GetLastError());
  950. return FALSE;
  951. }
  952. BOOL
  953. EncodeString(CString& str,
  954. CCryptBlob& blob,
  955. HRESULT * phRes)
  956. {
  957. BOOL bRes = FALSE;
  958. DWORD cb;
  959. CERT_NAME_VALUE name_value;
  960. name_value.dwValueType = CERT_RDN_BMP_STRING;
  961. name_value.Value.cbData = 0;
  962. name_value.Value.pbData = (LPBYTE)(LPCTSTR)str;
  963. if ( CryptEncodeObject(CRYPT_ASN_ENCODING, X509_UNICODE_ANY_STRING,
  964. &name_value, NULL, &cb)
  965. && blob.Resize(cb)
  966. && CryptEncodeObject(CRYPT_ASN_ENCODING, X509_UNICODE_ANY_STRING,
  967. &name_value, blob.GetData(), &cb)
  968. )
  969. {
  970. bRes = TRUE;
  971. }
  972. else
  973. *phRes = HRESULT_FROM_WIN32(GetLastError());
  974. return bRes;
  975. }
  976. #define CERTWIZ_RENEWAL_DATA ((LPCSTR)1000)
  977. BOOL
  978. EncodeBlob(CCryptBlob& in,
  979. CCryptBlob& out,
  980. HRESULT * phRes)
  981. {
  982. BOOL bRes = FALSE;
  983. DWORD cb;
  984. if ( CryptEncodeObject(CRYPT_ASN_ENCODING, CERTWIZ_RENEWAL_DATA, in, NULL, &cb)
  985. && out.Resize(cb)
  986. && CryptEncodeObject(CRYPT_ASN_ENCODING, CERTWIZ_RENEWAL_DATA, in, out.GetData(), &cb)
  987. )
  988. {
  989. bRes = TRUE;
  990. }
  991. else
  992. *phRes = HRESULT_FROM_WIN32(GetLastError());
  993. return bRes;
  994. }
  995. BOOL
  996. DecodeBlob(CCryptBlob& in,
  997. CCryptBlob& out,
  998. HRESULT * phRes)
  999. {
  1000. BOOL bRes = FALSE;
  1001. DWORD cb;
  1002. if ( CryptDecodeObject(CRYPT_ASN_ENCODING, CERTWIZ_RENEWAL_DATA,
  1003. in.GetData(),
  1004. in.GetSize(),
  1005. 0,
  1006. NULL, &cb)
  1007. && out.Resize(cb)
  1008. && CryptDecodeObject(CRYPT_ASN_ENCODING, CERTWIZ_RENEWAL_DATA,
  1009. in.GetData(),
  1010. in.GetSize(),
  1011. 0,
  1012. out.GetData(),
  1013. &cb)
  1014. )
  1015. {
  1016. bRes = TRUE;
  1017. }
  1018. else
  1019. *phRes = HRESULT_FROM_WIN32(GetLastError());
  1020. return bRes;
  1021. }
  1022. BOOL
  1023. EncodeInteger(int number,
  1024. CCryptBlob& blob,
  1025. HRESULT * phRes)
  1026. {
  1027. BOOL bRes = FALSE;
  1028. DWORD cb;
  1029. if ( CryptEncodeObject(CRYPT_ASN_ENCODING, X509_INTEGER,
  1030. &number, NULL, &cb)
  1031. && blob.Resize(cb)
  1032. && CryptEncodeObject(CRYPT_ASN_ENCODING, X509_INTEGER,
  1033. &number, blob.GetData(), &cb)
  1034. )
  1035. {
  1036. bRes = TRUE;
  1037. }
  1038. else
  1039. *phRes = HRESULT_FROM_WIN32(GetLastError());
  1040. return bRes;
  1041. }
  1042. const WCHAR RgwchHex[] = {'0', '1', '2', '3', '4', '5', '6', '7',
  1043. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  1044. static BOOL
  1045. FormatMemBufToString(CString& str, LPBYTE pbData, DWORD cbData)
  1046. {
  1047. DWORD i = 0;
  1048. LPBYTE pb;
  1049. DWORD numCharsInserted = 0;
  1050. LPTSTR pString;
  1051. //
  1052. // calculate the size needed
  1053. //
  1054. pb = pbData;
  1055. while (pb <= &(pbData[cbData-1]))
  1056. {
  1057. if (numCharsInserted == 4)
  1058. {
  1059. i += sizeof(WCHAR);
  1060. numCharsInserted = 0;
  1061. }
  1062. else
  1063. {
  1064. i += 2 * sizeof(WCHAR);
  1065. pb++;
  1066. numCharsInserted += 2;
  1067. }
  1068. }
  1069. if (NULL == (pString = str.GetBuffer(i)))
  1070. {
  1071. return FALSE;
  1072. }
  1073. //
  1074. // copy to the buffer
  1075. //
  1076. i = 0;
  1077. numCharsInserted = 0;
  1078. pb = pbData;
  1079. while (pb <= &(pbData[cbData-1]))
  1080. {
  1081. if (numCharsInserted == 4)
  1082. {
  1083. pString[i++] = L' ';
  1084. numCharsInserted = 0;
  1085. }
  1086. else
  1087. {
  1088. pString[i++] = RgwchHex[(*pb & 0xf0) >> 4];
  1089. pString[i++] = RgwchHex[*pb & 0x0f];
  1090. pb++;
  1091. numCharsInserted += 2;
  1092. }
  1093. }
  1094. pString[i] = 0;
  1095. str.ReleaseBuffer();
  1096. return TRUE;
  1097. }
  1098. void FormatRdnAttr(CString& str, DWORD dwValueType, CRYPT_DATA_BLOB& blob, BOOL fAppend)
  1099. {
  1100. if ( CERT_RDN_ENCODED_BLOB == dwValueType
  1101. || CERT_RDN_OCTET_STRING == dwValueType
  1102. )
  1103. {
  1104. // translate the buffer to a text string
  1105. FormatMemBufToString(str, blob.pbData, blob.cbData);
  1106. }
  1107. else
  1108. {
  1109. // buffer is already a string so just copy/append to it
  1110. if (fAppend)
  1111. {
  1112. str += (LPTSTR)blob.pbData;
  1113. }
  1114. else
  1115. {
  1116. // don't concatenate these entries...
  1117. str = (LPTSTR)blob.pbData;
  1118. }
  1119. }
  1120. }
  1121. BOOL
  1122. CreateDirectoryFromPath(LPCTSTR szPath, LPSECURITY_ATTRIBUTES lpSA)
  1123. /*++
  1124. Routine Description:
  1125. Creates the directory specified in szPath and any other "higher"
  1126. directories in the specified path that don't exist.
  1127. Arguments:
  1128. IN LPCTSTR szPath
  1129. directory path to create (assumed to be a DOS path, not a UNC)
  1130. IN LPSECURITY_ATTRIBUTES lpSA
  1131. pointer to security attributes argument used by CreateDirectory
  1132. Return Value:
  1133. TRUE if directory(ies) created
  1134. FALSE if error (GetLastError to find out why)
  1135. --*/
  1136. {
  1137. LPTSTR pLeftHalf, pNext;
  1138. CString RightHalf;
  1139. // 1. We are supporting only absolute paths. Caller should decide which
  1140. // root to use and build the path
  1141. if (PathIsRelative(szPath))
  1142. {
  1143. ASSERT(FALSE);
  1144. return FALSE;
  1145. }
  1146. pLeftHalf = (LPTSTR)szPath;
  1147. pNext = PathSkipRoot(pLeftHalf);
  1148. do {
  1149. // copy the chunk between pLeftHalf and pNext to the
  1150. // local buffer
  1151. while (pLeftHalf < pNext)
  1152. RightHalf += *pLeftHalf++;
  1153. // check if new path exists
  1154. int index = RightHalf.GetLength() - 1;
  1155. BOOL bBackslash = FALSE, bContinue = FALSE;
  1156. if (bBackslash = (RightHalf[index] == L'\\'))
  1157. {
  1158. RightHalf.SetAt(index, 0);
  1159. }
  1160. bContinue = PathIsUNCServerShare(RightHalf);
  1161. if (bBackslash)
  1162. RightHalf.SetAt(index, L'\\');
  1163. if (bContinue || PathIsDirectory(RightHalf))
  1164. continue;
  1165. else if (PathFileExists(RightHalf))
  1166. {
  1167. // we cannot create this directory
  1168. // because file with this name already exists
  1169. SetLastError(ERROR_ALREADY_EXISTS);
  1170. return FALSE;
  1171. }
  1172. else
  1173. {
  1174. // no file no directory, create
  1175. if (!CreateDirectory(RightHalf, lpSA))
  1176. return FALSE;
  1177. }
  1178. }
  1179. while (NULL != (pNext = PathFindNextComponent(pLeftHalf)));
  1180. return TRUE;
  1181. }
  1182. BOOL
  1183. CompactPathToWidth(CWnd * pControl, CString& strPath)
  1184. {
  1185. BOOL bRes;
  1186. CRect rc;
  1187. CFont * pFont = pControl->GetFont(), * pFontTmp;
  1188. CDC * pdc = pControl->GetDC(), dc;
  1189. LPTSTR pPath = strPath.GetBuffer(MAX_PATH);
  1190. dc.CreateCompatibleDC(pdc);
  1191. pFontTmp = dc.SelectObject(pFont);
  1192. pControl->GetClientRect(&rc);
  1193. bRes = PathCompactPath(dc.GetSafeHdc(), pPath, rc.Width());
  1194. dc.SelectObject(pFontTmp);
  1195. pControl->ReleaseDC(pdc);
  1196. strPath.ReleaseBuffer();
  1197. return bRes;
  1198. }
  1199. BOOL
  1200. GetKeySizeLimits(IEnroll * pEnroll,
  1201. DWORD * min, DWORD * max, DWORD * def,
  1202. BOOL bGSC,
  1203. HRESULT * phRes)
  1204. {
  1205. HCRYPTPROV hProv = NULL;
  1206. long dwProviderType;
  1207. DWORD dwFlags, cbData;
  1208. BSTR bstrProviderName;
  1209. PROV_ENUMALGS_EX paramData;
  1210. BOOL bRes = FALSE;
  1211. VERIFY(SUCCEEDED(pEnroll->get_ProviderNameWStr(&bstrProviderName)));
  1212. VERIFY(SUCCEEDED(pEnroll->get_ProviderType(&dwProviderType)));
  1213. if (!CryptAcquireContext(
  1214. &hProv,
  1215. NULL,
  1216. bstrProviderName,
  1217. dwProviderType,
  1218. CRYPT_VERIFYCONTEXT))
  1219. {
  1220. *phRes = GetLastError();
  1221. return FALSE;
  1222. }
  1223. for (int i = 0; ; i++)
  1224. {
  1225. dwFlags = 0 == i ? CRYPT_FIRST : 0;
  1226. cbData = sizeof(paramData);
  1227. if (!CryptGetProvParam(hProv, PP_ENUMALGS_EX, (BYTE*)&paramData, &cbData, dwFlags))
  1228. {
  1229. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == GetLastError())
  1230. {
  1231. // out of for loop
  1232. *phRes = S_OK;
  1233. bRes = TRUE;
  1234. }
  1235. else
  1236. {
  1237. *phRes = GetLastError();
  1238. }
  1239. break;
  1240. }
  1241. if (ALG_CLASS_KEY_EXCHANGE == GET_ALG_CLASS(paramData.aiAlgid))
  1242. {
  1243. *min = paramData.dwMinLen;
  1244. *max = paramData.dwMaxLen;
  1245. *def = paramData.dwDefaultLen;
  1246. bRes = TRUE;
  1247. *phRes = S_OK;
  1248. break;
  1249. }
  1250. }
  1251. if (NULL != hProv)
  1252. {
  1253. CryptReleaseContext(hProv, 0);
  1254. }
  1255. return bRes;
  1256. }
  1257. HRESULT ShutdownSSL(CString& machine_name, CString& server_name)
  1258. {
  1259. CString str = server_name;
  1260. str += _T("/root");
  1261. CComAuthInfo auth(machine_name);
  1262. CMetaKey key(&auth, str,METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE);
  1263. DWORD dwSslAccess;
  1264. if ( key.Succeeded()
  1265. && SUCCEEDED(key.QueryValue(MD_SSL_ACCESS_PERM, dwSslAccess))
  1266. && dwSslAccess > 0
  1267. )
  1268. {
  1269. // bug356587 should remove SslAccessPerm property and not set to 0 when Cert Removed
  1270. key.SetValue(MD_SSL_ACCESS_PERM, 0);
  1271. key.DeleteValue(MD_SSL_ACCESS_PERM);
  1272. key.DeleteValue(MD_SECURE_BINDINGS);
  1273. }
  1274. // Now we need to remove SSL setting from any virtual directory below
  1275. CError err;
  1276. CStringListEx strlDataPaths;
  1277. DWORD dwMDIdentifier, dwMDAttributes, dwMDUserType,dwMDDataType;
  1278. VERIFY(CMetaKey::GetMDFieldDef(MD_SSL_ACCESS_PERM, dwMDIdentifier, dwMDAttributes, dwMDUserType,dwMDDataType));
  1279. err = key.GetDataPaths(strlDataPaths,dwMDIdentifier,dwMDDataType);
  1280. if (err.Succeeded() && !strlDataPaths.IsEmpty())
  1281. {
  1282. POSITION pos = strlDataPaths.GetHeadPosition();
  1283. while (pos)
  1284. {
  1285. CString& str = strlDataPaths.GetNext(pos);
  1286. if (SUCCEEDED(key.QueryValue(MD_SSL_ACCESS_PERM, dwSslAccess, NULL, str)) && dwSslAccess > 0)
  1287. {
  1288. key.SetValue(MD_SSL_ACCESS_PERM, 0, NULL, str);
  1289. key.DeleteValue(MD_SSL_ACCESS_PERM, str);
  1290. key.DeleteValue(MD_SECURE_BINDINGS, str);
  1291. }
  1292. }
  1293. }
  1294. return key.QueryResult();
  1295. }
  1296. BOOL
  1297. GetServerComment(const CString& machine_name,
  1298. const CString& user_name,
  1299. const CString& user_password,
  1300. CString& MetabaseNode,
  1301. CString& comment,
  1302. HRESULT * phResult
  1303. )
  1304. {
  1305. ASSERT(!machine_name.IsEmpty());
  1306. *phResult = S_OK;
  1307. if (user_name.IsEmpty())
  1308. {
  1309. CComAuthInfo auth(machine_name);
  1310. CMetaKey key(&auth,MetabaseNode,METADATA_PERMISSION_READ);
  1311. if (key.Succeeded())
  1312. {
  1313. return SUCCEEDED(*phResult = key.QueryValue(MD_SERVER_COMMENT, comment));
  1314. }
  1315. else
  1316. {
  1317. *phResult = key.QueryResult();
  1318. return FALSE;
  1319. }
  1320. }
  1321. else
  1322. {
  1323. CComAuthInfo auth(machine_name,user_name,user_password);
  1324. CMetaKey key(&auth,MetabaseNode,METADATA_PERMISSION_READ);
  1325. if (key.Succeeded())
  1326. {
  1327. return SUCCEEDED(*phResult = key.QueryValue(MD_SERVER_COMMENT, comment));
  1328. }
  1329. else
  1330. {
  1331. *phResult = key.QueryResult();
  1332. return FALSE;
  1333. }
  1334. }
  1335. }
  1336. BOOL IsSiteTypeMetabaseNode(CString & MetabasePath)
  1337. {
  1338. BOOL bReturn = FALSE;
  1339. INT iPos1 = 0;
  1340. CString PathCopy = MetabasePath;
  1341. CString PathCopy2;
  1342. TCHAR MyChar;
  1343. // check if ends with a slash...
  1344. // if it does, then cut it off
  1345. if (PathCopy.Right(1) == _T('/'))
  1346. {
  1347. iPos1 = PathCopy.ReverseFind(_T('/'));
  1348. if (iPos1 != -1)
  1349. {
  1350. PathCopy.SetAt(iPos1,_T('0'));
  1351. }
  1352. }
  1353. iPos1 = PathCopy.ReverseFind((TCHAR) _T('/'));
  1354. if (iPos1 == -1)
  1355. {
  1356. goto IsSiteTypeMetabaseNode_Exit;
  1357. }
  1358. PathCopy2 = PathCopy.Right(PathCopy.GetLength() - iPos1);
  1359. PathCopy2.TrimRight();
  1360. for (INT i = 0; i < PathCopy2.GetLength(); i++)
  1361. {
  1362. MyChar = PathCopy2.GetAt(i);
  1363. if (MyChar != _T(' ') && MyChar != _T('/'))
  1364. {
  1365. if (FALSE == ISNUM(MyChar))
  1366. {
  1367. goto IsSiteTypeMetabaseNode_Exit;
  1368. }
  1369. }
  1370. }
  1371. bReturn = TRUE;
  1372. IsSiteTypeMetabaseNode_Exit:
  1373. return bReturn;
  1374. }
  1375. HRESULT EnumSites(CString& machine_name,CString& user_name,CString& user_password,CStringListEx * MyStringList)
  1376. {
  1377. HRESULT hr = E_FAIL;
  1378. CString str = _T("LM/W3SVC");
  1379. CString strChildPath = _T("");
  1380. CString strServerComment;
  1381. CComAuthInfo auth(machine_name,user_name,user_password);
  1382. CMetaKey key(&auth,str,METADATA_PERMISSION_READ);
  1383. hr = key.QueryResult();
  1384. if (key.Succeeded())
  1385. {
  1386. // Do a Get data paths on this key.
  1387. CError err;
  1388. CStringListEx strlDataPaths;
  1389. CBlob hash;
  1390. DWORD dwMDIdentifier, dwMDAttributes, dwMDUserType,dwMDDataType;
  1391. VERIFY(CMetaKey::GetMDFieldDef(MD_SERVER_BINDINGS, dwMDIdentifier, dwMDAttributes, dwMDUserType,dwMDDataType));
  1392. err = key.GetDataPaths(strlDataPaths,dwMDIdentifier,dwMDDataType);
  1393. if (err.Succeeded() && !strlDataPaths.IsEmpty())
  1394. {
  1395. POSITION pos = strlDataPaths.GetHeadPosition();
  1396. while (pos)
  1397. {
  1398. CString& strJustTheEnd = strlDataPaths.GetNext(pos);
  1399. strChildPath = str + strJustTheEnd;
  1400. if (TRUE == IsSiteTypeMetabaseNode(strChildPath))
  1401. {
  1402. MyStringList->AddTail(strChildPath);
  1403. }
  1404. }
  1405. }
  1406. hr = key.QueryResult();
  1407. }
  1408. return hr;
  1409. }
  1410. HRESULT EnumSitesWithCertInstalled(CString& machine_name,CString& user_name,CString& user_password,CStringListEx * MyStringList)
  1411. {
  1412. HRESULT hr = E_FAIL;
  1413. CString str = _T("LM/W3SVC");
  1414. CString strChildPath = _T("");
  1415. CString strServerComment;
  1416. CComAuthInfo auth(machine_name,user_name,user_password);
  1417. CMetaKey key(&auth,str,METADATA_PERMISSION_READ);
  1418. hr = key.QueryResult();
  1419. if (key.Succeeded())
  1420. {
  1421. // Do a Get data paths on this key.
  1422. CError err;
  1423. CStringListEx strlDataPaths;
  1424. CBlob hash;
  1425. DWORD dwMDIdentifier, dwMDAttributes, dwMDUserType,dwMDDataType;
  1426. //MD_SSL_CERT_STORE_NAME
  1427. //MD_SSL_CERT_HASH, hash
  1428. VERIFY(CMetaKey::GetMDFieldDef(MD_SSL_CERT_HASH, dwMDIdentifier, dwMDAttributes, dwMDUserType,dwMDDataType));
  1429. err = key.GetDataPaths(strlDataPaths,dwMDIdentifier,dwMDDataType);
  1430. if (err.Succeeded() && !strlDataPaths.IsEmpty())
  1431. {
  1432. POSITION pos = strlDataPaths.GetHeadPosition();
  1433. while (pos)
  1434. {
  1435. CString& strJustTheEnd = strlDataPaths.GetNext(pos);
  1436. strChildPath = str + strJustTheEnd;
  1437. if (TRUE == IsSiteTypeMetabaseNode(strChildPath))
  1438. {
  1439. MyStringList->AddTail(strChildPath);
  1440. }
  1441. }
  1442. }
  1443. hr = key.QueryResult();
  1444. }
  1445. return hr;
  1446. }
  1447. HRESULT IsCertUsedBySSLBelowMe(CString& machine_name, CString& server_name, CStringList& listFillMe)
  1448. {
  1449. CString str = server_name;
  1450. str += _T("/root");
  1451. CComAuthInfo auth(machine_name);
  1452. CMetaKey key(&auth, str,METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE);
  1453. DWORD dwSslAccess;
  1454. if ( key.Succeeded()
  1455. && SUCCEEDED(key.QueryValue(MD_SSL_ACCESS_PERM, dwSslAccess))
  1456. && dwSslAccess > 0
  1457. )
  1458. {
  1459. // it's used on my node...
  1460. // return back something to say it's used...
  1461. listFillMe.AddTail(str);
  1462. }
  1463. // Now check if it's being used below me...
  1464. CError err;
  1465. CStringListEx strlDataPaths;
  1466. DWORD dwMDIdentifier, dwMDAttributes, dwMDUserType,dwMDDataType;
  1467. VERIFY(CMetaKey::GetMDFieldDef(MD_SSL_ACCESS_PERM, dwMDIdentifier, dwMDAttributes, dwMDUserType,dwMDDataType));
  1468. err = key.GetDataPaths(strlDataPaths,dwMDIdentifier,dwMDDataType);
  1469. if (err.Succeeded() && !strlDataPaths.IsEmpty())
  1470. {
  1471. POSITION pos = strlDataPaths.GetHeadPosition();
  1472. while (pos)
  1473. {
  1474. CString& str = strlDataPaths.GetNext(pos);
  1475. if (SUCCEEDED(key.QueryValue(MD_SSL_ACCESS_PERM, dwSslAccess, NULL, str)) && dwSslAccess > 0)
  1476. {
  1477. // yes, it's being used here...
  1478. // return back something to say it's used...
  1479. listFillMe.AddTail(str);
  1480. }
  1481. }
  1482. }
  1483. return key.QueryResult();
  1484. }
  1485. HRESULT
  1486. HereIsVtArrayGimmieBinary(
  1487. VARIANT * lpVarSrcObject,
  1488. DWORD * cbBinaryBufferSize,
  1489. char **pbBinaryBuffer,
  1490. BOOL bReturnBinaryAsVT_VARIANT
  1491. )
  1492. {
  1493. HRESULT hr = S_OK;
  1494. LONG dwSLBound = 0;
  1495. LONG dwSUBound = 0;
  1496. CHAR HUGEP *pArray = NULL;
  1497. if (NULL == cbBinaryBufferSize || NULL == pbBinaryBuffer)
  1498. {
  1499. hr = E_INVALIDARG;
  1500. goto HereIsVtArrayGimmieBinary_Exit;
  1501. }
  1502. if (bReturnBinaryAsVT_VARIANT)
  1503. {
  1504. hr = VariantChangeType(lpVarSrcObject,lpVarSrcObject,0,VT_ARRAY | VT_VARIANT);
  1505. }
  1506. else
  1507. {
  1508. hr = VariantChangeType(lpVarSrcObject,lpVarSrcObject,0,VT_ARRAY | VT_UI1);
  1509. }
  1510. if (FAILED(hr))
  1511. {
  1512. if (hr != E_OUTOFMEMORY)
  1513. {
  1514. hr = OLE_E_CANTCONVERT;
  1515. }
  1516. goto HereIsVtArrayGimmieBinary_Exit;
  1517. }
  1518. if (bReturnBinaryAsVT_VARIANT)
  1519. {
  1520. if( lpVarSrcObject->vt != (VT_ARRAY | VT_VARIANT))
  1521. {
  1522. hr = OLE_E_CANTCONVERT;
  1523. goto HereIsVtArrayGimmieBinary_Exit;
  1524. }
  1525. }
  1526. else
  1527. {
  1528. if( lpVarSrcObject->vt != (VT_ARRAY | VT_UI1))
  1529. {
  1530. hr = OLE_E_CANTCONVERT;
  1531. goto HereIsVtArrayGimmieBinary_Exit;
  1532. }
  1533. }
  1534. hr = SafeArrayGetLBound(V_ARRAY(lpVarSrcObject),1,(long FAR *) &dwSLBound );
  1535. if (FAILED(hr))
  1536. {goto HereIsVtArrayGimmieBinary_Exit;}
  1537. hr = SafeArrayGetUBound(V_ARRAY(lpVarSrcObject),1,(long FAR *) &dwSUBound );
  1538. if (FAILED(hr))
  1539. {goto HereIsVtArrayGimmieBinary_Exit;}
  1540. //*pbBinaryBuffer = (LPBYTE) AllocADsMem(dwSUBound - dwSLBound + 1);
  1541. *pbBinaryBuffer = (char *) ::CoTaskMemAlloc(dwSUBound - dwSLBound + 1);
  1542. if (*pbBinaryBuffer == NULL)
  1543. {
  1544. hr = E_OUTOFMEMORY;
  1545. goto HereIsVtArrayGimmieBinary_Exit;
  1546. }
  1547. *cbBinaryBufferSize = dwSUBound - dwSLBound + 1;
  1548. hr = SafeArrayAccessData( V_ARRAY(lpVarSrcObject),(void HUGEP * FAR *) &pArray );
  1549. if (FAILED(hr))
  1550. {goto HereIsVtArrayGimmieBinary_Exit;}
  1551. memcpy(*pbBinaryBuffer,pArray,dwSUBound-dwSLBound+1);
  1552. SafeArrayUnaccessData( V_ARRAY(lpVarSrcObject) );
  1553. HereIsVtArrayGimmieBinary_Exit:
  1554. return hr;
  1555. }
  1556. CERT_CONTEXT * GetInstalledCertFromHash(HRESULT * phResult,DWORD cbHashBlob, char * pHashBlob)
  1557. {
  1558. ATLASSERT(phResult != NULL);
  1559. CERT_CONTEXT * pCert = NULL;
  1560. *phResult = S_OK;
  1561. CString store_name = _T("MY");
  1562. HCERTSTORE hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,NULL,CERT_SYSTEM_STORE_LOCAL_MACHINE,store_name);
  1563. ASSERT(hStore != NULL);
  1564. if (hStore != NULL)
  1565. {
  1566. // Now we need to find cert by hash
  1567. CRYPT_HASH_BLOB crypt_hash;
  1568. crypt_hash.cbData = cbHashBlob;
  1569. crypt_hash.pbData = (BYTE *) pHashBlob;
  1570. pCert = (CERT_CONTEXT *)CertFindCertificateInStore(hStore,X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,0,CERT_FIND_HASH,(LPVOID)&crypt_hash,NULL);
  1571. if (pCert == NULL)
  1572. {
  1573. *phResult = HRESULT_FROM_WIN32(GetLastError());
  1574. }
  1575. VERIFY(CertCloseStore(hStore, 0));
  1576. }
  1577. else
  1578. {
  1579. *phResult = HRESULT_FROM_WIN32(GetLastError());
  1580. }
  1581. return pCert;
  1582. }
  1583. BOOL ViewCertificateDialog(CRYPT_HASH_BLOB* pcrypt_hash, HWND hWnd)
  1584. {
  1585. BOOL bReturn = FALSE;
  1586. HCERTSTORE hStore = NULL;
  1587. PCCERT_CONTEXT pCert = NULL;
  1588. CString store_name = _T("MY");
  1589. hStore = CertOpenStore(
  1590. CERT_STORE_PROV_SYSTEM,
  1591. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  1592. NULL,
  1593. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  1594. store_name
  1595. );
  1596. if (hStore != NULL)
  1597. {
  1598. // Now we need to find cert by hash
  1599. //CRYPT_HASH_BLOB crypt_hash;
  1600. //crypt_hash.cbData = hash.GetSize();
  1601. //crypt_hash.pbData = hash.GetData();
  1602. pCert = CertFindCertificateInStore(hStore,
  1603. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1604. 0, CERT_FIND_HASH, (LPVOID)pcrypt_hash, NULL);
  1605. }
  1606. if (pCert)
  1607. {
  1608. BOOL fPropertiesChanged;
  1609. CRYPTUI_VIEWCERTIFICATE_STRUCT vcs;
  1610. HCERTSTORE hCertStore = ::CertDuplicateStore(hStore);
  1611. ::ZeroMemory (&vcs, sizeof (vcs));
  1612. vcs.dwSize = sizeof (vcs);
  1613. vcs.hwndParent = hWnd;
  1614. vcs.dwFlags = 0;
  1615. vcs.cStores = 1;
  1616. vcs.rghStores = &hCertStore;
  1617. vcs.pCertContext = pCert;
  1618. ::CryptUIDlgViewCertificate(&vcs, &fPropertiesChanged);
  1619. ::CertCloseStore (hCertStore, 0);
  1620. bReturn = TRUE;
  1621. }
  1622. else
  1623. {
  1624. // it failed
  1625. }
  1626. if (pCert != NULL)
  1627. ::CertFreeCertificateContext(pCert);
  1628. if (hStore != NULL)
  1629. ::CertCloseStore(hStore, 0);
  1630. return bReturn;
  1631. }
  1632. /*
  1633. -----Original Message-----
  1634. From: Helle Vu (SPECTOR)
  1635. Sent: Friday, April 27, 2001 6:02 PM
  1636. To: Aaron Lee; Trevor Freeman
  1637. Cc: Sergei Antonov
  1638. Subject: RE: bug 31010
  1639. Perfect timing, I was just about to send you an update on this:
  1640. I talked to Trevor about this, and he suggested the best thing to do for IIS would be the following (Trevor, please double-check I got this right):
  1641. If there is an EKU, and it has serverauth, display it in the list to pick web server certs from
  1642. If no EKU, look at basic constraints:
  1643. * If we do not have basic constraints, do display it in the list to pick web server certs from
  1644. * If we do have basic constraints with Subject Type =CA, don't display it in the list to pick web server certs from (this will filter out CA certs)
  1645. * If we do have basic constraints with SubectType !=CA, do display it in the list to pick web server certs from
  1646. */
  1647. /*
  1648. ===== Opened by kshenoy on 11/13/2000 02:26PM =====
  1649. Add Existing certificate option in "Web Server Certificate Request wizard" should not list CA certificates in the filter
  1650. but only End entity certificates with "Server Authentication" EKU
  1651. Since CA certificates by default have all the EKUs the filter will list CA certificates apart from
  1652. end entity certificates with "Server Auth" EKU.
  1653. In order to check if a given certificate is a CA or end entity you can look at the Basic Constraints
  1654. extension of the certificate if present. This will be present in CA certificates and set to SubjectType=CA.
  1655. If present in end entity certificates it will be set to "ServerAuth"
  1656. */
  1657. int CheckCertConstraints(PCCERT_CONTEXT pCC)
  1658. {
  1659. PCERT_EXTENSION pCExt;
  1660. LPCSTR pszObjId;
  1661. DWORD i;
  1662. CERT_BASIC_CONSTRAINTS_INFO *pConstraints=NULL;
  1663. CERT_BASIC_CONSTRAINTS2_INFO *p2Constraints=NULL;
  1664. DWORD ConstraintSize=0;
  1665. int ReturnValue = FAILURE;
  1666. BOOL Using2=FALSE;
  1667. void* ConstraintBlob=NULL;
  1668. pszObjId = szOID_BASIC_CONSTRAINTS;
  1669. pCExt = CertFindExtension(pszObjId,pCC->pCertInfo->cExtension,pCC->pCertInfo->rgExtension);
  1670. if (pCExt == NULL)
  1671. {
  1672. pszObjId = szOID_BASIC_CONSTRAINTS2;
  1673. pCExt = CertFindExtension(pszObjId,pCC->pCertInfo->cExtension,pCC->pCertInfo->rgExtension);
  1674. Using2=TRUE;
  1675. }
  1676. if (pCExt == NULL)
  1677. {
  1678. ReturnValue = DID_NOT_FIND_CONSTRAINT;
  1679. goto CheckCertConstraints_Exit;
  1680. }
  1681. // Decode extension
  1682. if (!CryptDecodeObject(X509_ASN_ENCODING,pCExt->pszObjId,pCExt->Value.pbData,pCExt->Value.cbData,0,NULL,&ConstraintSize))
  1683. {
  1684. goto CheckCertConstraints_Exit;
  1685. }
  1686. ConstraintBlob = malloc(ConstraintSize);
  1687. if (ConstraintBlob == NULL)
  1688. {
  1689. goto CheckCertConstraints_Exit;
  1690. }
  1691. if (!CryptDecodeObject(X509_ASN_ENCODING,pCExt->pszObjId,pCExt->Value.pbData,pCExt->Value.cbData,0,(void*)ConstraintBlob,&ConstraintSize))
  1692. {
  1693. goto CheckCertConstraints_Exit;
  1694. }
  1695. if (Using2)
  1696. {
  1697. p2Constraints=(CERT_BASIC_CONSTRAINTS2_INFO*)ConstraintBlob;
  1698. if (!p2Constraints->fCA)
  1699. {
  1700. // there is a constraint, and it's not a CA
  1701. ReturnValue = FOUND_CONSTRAINT;
  1702. }
  1703. else
  1704. {
  1705. // This is a CA. CA cannot be used as a 'server auth'
  1706. ReturnValue = FOUND_CONSTRAINT_BUT_THIS_IS_A_CA_OR_ITS_NOT_AN_END_ENTITY;
  1707. }
  1708. }
  1709. else
  1710. {
  1711. pConstraints=(CERT_BASIC_CONSTRAINTS_INFO*)ConstraintBlob;
  1712. if (((pConstraints->SubjectType.cbData * 8) - pConstraints->SubjectType.cUnusedBits) >= 2)
  1713. {
  1714. if ((*pConstraints->SubjectType.pbData) & CERT_END_ENTITY_SUBJECT_FLAG)
  1715. {
  1716. // there is a valid constraint
  1717. ReturnValue = FOUND_CONSTRAINT;
  1718. }
  1719. else
  1720. {
  1721. // this is not an 'end entity' so hey -- we can't use it.
  1722. ReturnValue = FOUND_CONSTRAINT_BUT_THIS_IS_A_CA_OR_ITS_NOT_AN_END_ENTITY;
  1723. }
  1724. }
  1725. }
  1726. CheckCertConstraints_Exit:
  1727. if (ConstraintBlob){free(ConstraintBlob);}
  1728. return (ReturnValue);
  1729. }
  1730. BOOL IsCertExportable(PCCERT_CONTEXT pCertContext)
  1731. {
  1732. HCRYPTPROV hCryptProv = NULL;
  1733. DWORD dwKeySpec = 0;
  1734. BOOL fCallerFreeProv = FALSE;
  1735. BOOL fReturn = FALSE;
  1736. HCRYPTKEY hKey = NULL;
  1737. DWORD dwPermissions = 0;
  1738. DWORD dwSize = 0;
  1739. if (!pCertContext)
  1740. {
  1741. fReturn = FALSE;
  1742. goto IsCertExportable_Exit;
  1743. }
  1744. //
  1745. // first get the private key context
  1746. //
  1747. if (!CryptAcquireCertificatePrivateKey(
  1748. pCertContext,
  1749. CRYPT_ACQUIRE_USE_PROV_INFO_FLAG | CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
  1750. NULL,
  1751. &hCryptProv,
  1752. &dwKeySpec,
  1753. &fCallerFreeProv))
  1754. {
  1755. fReturn = FALSE;
  1756. goto IsCertExportable_Exit;
  1757. }
  1758. //
  1759. // get the handle to the key
  1760. //
  1761. if (!CryptGetUserKey(hCryptProv, dwKeySpec, &hKey))
  1762. {
  1763. fReturn = FALSE;
  1764. goto IsCertExportable_Exit;
  1765. }
  1766. //
  1767. // finally, get the permissions on the key and check if it is exportable
  1768. //
  1769. dwSize = sizeof(dwPermissions);
  1770. if (!CryptGetKeyParam(hKey, KP_PERMISSIONS, (PBYTE)&dwPermissions, &dwSize, 0))
  1771. {
  1772. fReturn = FALSE;
  1773. goto IsCertExportable_Exit;
  1774. }
  1775. fReturn = (dwPermissions & CRYPT_EXPORT) ? TRUE : FALSE;
  1776. IsCertExportable_Exit:
  1777. if (hKey != NULL){CryptDestroyKey(hKey);}
  1778. if (fCallerFreeProv){CryptReleaseContext(hCryptProv, 0);}
  1779. return fReturn;
  1780. }
  1781. BOOL IsCertExportableOnRemoteMachine(CString ServerName,CString UserName,CString UserPassword,CString InstanceName)
  1782. {
  1783. BOOL bRes = FALSE;
  1784. BOOL bPleaseDoCoUninit = FALSE;
  1785. HRESULT hResult = E_FAIL;
  1786. IIISCertObj *pTheObject = NULL;
  1787. VARIANT_BOOL varBool = VARIANT_FALSE;
  1788. BSTR bstrServerName = SysAllocString(ServerName);
  1789. BSTR bstrUserName = SysAllocString(UserName);
  1790. BSTR bstrUserPassword = SysAllocString(UserPassword);
  1791. BSTR bstrInstanceName = SysAllocString(InstanceName);
  1792. hResult = CoInitialize(NULL);
  1793. if(FAILED(hResult))
  1794. {
  1795. return bRes;
  1796. }
  1797. bPleaseDoCoUninit = TRUE;
  1798. // this one seems to work with surrogates..
  1799. hResult = CoCreateInstance(CLSID_IISCertObj,NULL,CLSCTX_SERVER,IID_IIISCertObj,(void **)&pTheObject);
  1800. if (FAILED(hResult))
  1801. {
  1802. goto InstallCopyMoveFromRemote_Exit;
  1803. }
  1804. // at this point we were able to instantiate the com object on the server (local or remote)
  1805. pTheObject->put_ServerName(bstrServerName);
  1806. pTheObject->put_UserName(bstrUserName);
  1807. pTheObject->put_UserPassword(bstrUserPassword);
  1808. pTheObject->put_InstanceName(bstrInstanceName);
  1809. hResult = pTheObject->IsExportable(&varBool);
  1810. if (FAILED(hResult))
  1811. {
  1812. goto InstallCopyMoveFromRemote_Exit;
  1813. }
  1814. if (varBool == VARIANT_FALSE)
  1815. {
  1816. bRes = FALSE;
  1817. }
  1818. else
  1819. {
  1820. bRes = TRUE;
  1821. }
  1822. InstallCopyMoveFromRemote_Exit:
  1823. if (pTheObject)
  1824. {
  1825. pTheObject->Release();
  1826. pTheObject = NULL;
  1827. }
  1828. if (bPleaseDoCoUninit)
  1829. {
  1830. CoUninitialize();
  1831. }
  1832. if (bstrServerName) {SysFreeString(bstrServerName);}
  1833. if (bstrUserName) {SysFreeString(bstrUserName);}
  1834. if (bstrUserPassword) {SysFreeString(bstrUserPassword);}
  1835. if (bstrInstanceName) {SysFreeString(bstrInstanceName);}
  1836. return bRes;
  1837. }
  1838. BOOL DumpCertDesc(char * pBlobInfo)
  1839. {
  1840. BOOL bRes = FALSE;
  1841. IISDebugOutput(_T("blob=%s\n"),pBlobInfo);
  1842. bRes = TRUE;
  1843. return bRes;
  1844. }
  1845. BOOL GetCertDescInfo(CString ServerName,CString UserName,CString UserPassword,CString InstanceName)
  1846. {
  1847. BOOL bReturn = FALSE;
  1848. HRESULT hResult = E_FAIL;
  1849. IIISCertObj *pTheObject = NULL;
  1850. DWORD cbBinaryBufferSize = 0;
  1851. char * pbBinaryBuffer = NULL;
  1852. BOOL bPleaseDoCoUninit = FALSE;
  1853. BSTR bstrServerName = SysAllocString(ServerName);
  1854. BSTR bstrUserName = SysAllocString(UserName);
  1855. BSTR bstrUserPassword = SysAllocString(UserPassword);
  1856. BSTR bstrInstanceName = SysAllocString(InstanceName);
  1857. VARIANT VtArray;
  1858. hResult = CoInitialize(NULL);
  1859. if(FAILED(hResult))
  1860. {
  1861. return bReturn;
  1862. }
  1863. bPleaseDoCoUninit = TRUE;
  1864. // this one seems to work with surrogates..
  1865. hResult = CoCreateInstance(CLSID_IISCertObj,NULL,CLSCTX_SERVER,IID_IIISCertObj,(void **)&pTheObject);
  1866. if (FAILED(hResult))
  1867. {
  1868. goto GetCertDescInfo_Exit;
  1869. }
  1870. pTheObject->put_ServerName(bstrServerName);
  1871. pTheObject->put_UserName(bstrUserName);
  1872. pTheObject->put_UserPassword(bstrUserPassword);
  1873. pTheObject->put_InstanceName(bstrInstanceName);
  1874. hResult = pTheObject->GetCertInfo(&VtArray);
  1875. if (FAILED(hResult))
  1876. {
  1877. goto GetCertDescInfo_Exit;
  1878. }
  1879. // we have a VtArray now.
  1880. // change it back to a binary blob
  1881. hResult = HereIsVtArrayGimmieBinary(&VtArray,&cbBinaryBufferSize,&pbBinaryBuffer,FALSE);
  1882. if (FAILED(hResult))
  1883. {
  1884. goto GetCertDescInfo_Exit;
  1885. }
  1886. // Dump it out!
  1887. DumpCertDesc(pbBinaryBuffer);
  1888. bReturn = TRUE;
  1889. GetCertDescInfo_Exit:
  1890. if (pTheObject)
  1891. {
  1892. pTheObject->Release();
  1893. pTheObject = NULL;
  1894. }
  1895. if (pbBinaryBuffer)
  1896. {
  1897. CoTaskMemFree(pbBinaryBuffer);
  1898. }
  1899. if (bPleaseDoCoUninit)
  1900. {
  1901. CoUninitialize();
  1902. }
  1903. return bReturn;
  1904. }
  1905. BOOL IsWhistlerWorkstation(void)
  1906. {
  1907. BOOL WorkstationSKU = FALSE;
  1908. OSVERSIONINFOEX osvi;
  1909. //
  1910. // Determine if we are installing Personal/Professional SKU
  1911. //
  1912. ZeroMemory( &osvi, sizeof( OSVERSIONINFOEX ) );
  1913. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  1914. GetVersionEx((OSVERSIONINFO *) &osvi);
  1915. if (osvi.wProductType == VER_NT_WORKSTATION)
  1916. {
  1917. WorkstationSKU = TRUE;
  1918. }
  1919. return WorkstationSKU;
  1920. }