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.

923 lines
26 KiB

  1. #include "stdafx.h"
  2. #include "CertObj.h"
  3. #include "common.h"
  4. //////////////////////////////////////////////////////////////////
  5. CString ReturnGoodMetabasePath(CString csInstanceName)
  6. {
  7. CString key_path_lm = _T("");
  8. CString key_path = _T("");
  9. // csInstanceName will come in looking like
  10. // w3svc/1
  11. // or /lm/w3svc/1
  12. //
  13. // we want to it to go out as /lm/w3svc/1
  14. key_path_lm = SZ_MBN_SEP_STR SZ_MBN_MACHINE SZ_MBN_SEP_STR;// SZ_MBN_WEB SZ_MBN_SEP_STR;
  15. if (csInstanceName.GetLength() >= 4)
  16. {
  17. if (csInstanceName.Left(4) == key_path_lm)
  18. {
  19. key_path = csInstanceName;
  20. }
  21. else
  22. {
  23. key_path_lm = SZ_MBN_MACHINE SZ_MBN_SEP_STR;
  24. if (csInstanceName.Left(3) == key_path_lm)
  25. {
  26. key_path = csInstanceName;
  27. }
  28. else
  29. {
  30. key_path = key_path_lm;
  31. key_path += csInstanceName;
  32. }
  33. }
  34. }
  35. else
  36. {
  37. key_path = key_path_lm;
  38. key_path += csInstanceName;
  39. }
  40. return key_path;
  41. }
  42. HRESULT ShutdownSSL(CString& server_name)
  43. {
  44. CComAuthInfo auth;
  45. CString str = server_name;
  46. str += _T("/root");
  47. CMetaKey key(&auth, str,
  48. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE);
  49. DWORD dwSslAccess;
  50. if (!key.Succeeded())
  51. {
  52. return key.QueryResult();
  53. }
  54. if (SUCCEEDED(key.QueryValue(MD_SSL_ACCESS_PERM, dwSslAccess)) && dwSslAccess > 0)
  55. {
  56. key.SetValue(MD_SSL_ACCESS_PERM, 0);
  57. }
  58. // Now we need to remove SSL setting from any virtual directory below
  59. CError err;
  60. CStringListEx data_paths;
  61. DWORD dwMDIdentifier, dwMDAttributes, dwMDUserType,dwMDDataType;
  62. VERIFY(CMetaKey::GetMDFieldDef(MD_SSL_ACCESS_PERM, dwMDIdentifier, dwMDAttributes, dwMDUserType,dwMDDataType));
  63. err = key.GetDataPaths( data_paths,dwMDIdentifier,dwMDDataType);
  64. if (err.Succeeded() && !data_paths.empty())
  65. {
  66. CStringListEx::iterator it = data_paths.begin();
  67. while (it != data_paths.end())
  68. {
  69. CString& str = (*it++);
  70. if (SUCCEEDED(key.QueryValue(MD_SSL_ACCESS_PERM, dwSslAccess, NULL, str)) && dwSslAccess > 0)
  71. {
  72. key.SetValue(MD_SSL_ACCESS_PERM, 0, NULL, str);
  73. }
  74. }
  75. }
  76. return key.QueryResult();
  77. }
  78. BOOL AddChainToStore(HCERTSTORE hCertStore,PCCERT_CONTEXT pCertContext,DWORD cStores,HCERTSTORE * rghStores,BOOL fDontAddRootCert,CERT_TRUST_STATUS * pChainTrustStatus)
  79. {
  80. DWORD i;
  81. CERT_CHAIN_ENGINE_CONFIG CertChainEngineConfig;
  82. HCERTCHAINENGINE hCertChainEngine = NULL;
  83. PCCERT_CHAIN_CONTEXT pCertChainContext = NULL;
  84. CERT_CHAIN_PARA CertChainPara;
  85. BOOL fRet = TRUE;
  86. PCCERT_CONTEXT pTempCertContext = NULL;
  87. //
  88. // create a new chain engine, then build the chain
  89. //
  90. memset(&CertChainEngineConfig, 0, sizeof(CertChainEngineConfig));
  91. CertChainEngineConfig.cbSize = sizeof(CertChainEngineConfig);
  92. CertChainEngineConfig.cAdditionalStore = cStores;
  93. CertChainEngineConfig.rghAdditionalStore = rghStores;
  94. CertChainEngineConfig.dwFlags = CERT_CHAIN_USE_LOCAL_MACHINE_STORE;
  95. if (!CertCreateCertificateChainEngine(&CertChainEngineConfig, &hCertChainEngine))
  96. {
  97. goto AddChainToStore_Error;
  98. }
  99. memset(&CertChainPara, 0, sizeof(CertChainPara));
  100. CertChainPara.cbSize = sizeof(CertChainPara);
  101. if (!CertGetCertificateChain(hCertChainEngine,pCertContext,NULL,NULL,&CertChainPara,0,NULL,&pCertChainContext))
  102. {
  103. goto AddChainToStore_Error;
  104. }
  105. //
  106. // make sure there is atleast 1 simple chain
  107. //
  108. if (pCertChainContext->cChain != 0)
  109. {
  110. i = 0;
  111. while (i < pCertChainContext->rgpChain[0]->cElement)
  112. {
  113. //
  114. // if we are supposed to skip the root cert,
  115. // and we are on the root cert, then continue
  116. //
  117. if (fDontAddRootCert && (pCertChainContext->rgpChain[0]->rgpElement[i]->TrustStatus.dwInfoStatus & CERT_TRUST_IS_SELF_SIGNED))
  118. {
  119. i++;
  120. continue;
  121. }
  122. CertAddCertificateContextToStore(hCertStore,pCertChainContext->rgpChain[0]->rgpElement[i]->pCertContext,CERT_STORE_ADD_REPLACE_EXISTING,&pTempCertContext);
  123. //
  124. // remove any private key property the certcontext may have on it.
  125. //
  126. if (pTempCertContext)
  127. {
  128. CertSetCertificateContextProperty(pTempCertContext, CERT_KEY_PROV_INFO_PROP_ID, 0, NULL);
  129. CertFreeCertificateContext(pTempCertContext);
  130. }
  131. i++;
  132. }
  133. }
  134. else
  135. {
  136. goto AddChainToStore_Error;
  137. }
  138. //
  139. // if the caller wants the status, then set it
  140. //
  141. if (pChainTrustStatus != NULL)
  142. {
  143. pChainTrustStatus->dwErrorStatus = pCertChainContext->TrustStatus.dwErrorStatus;
  144. pChainTrustStatus->dwInfoStatus = pCertChainContext->TrustStatus.dwInfoStatus;
  145. }
  146. AddChainToStore_Exit:
  147. if (pCertChainContext != NULL)
  148. {
  149. CertFreeCertificateChain(pCertChainContext);
  150. }
  151. if (hCertChainEngine != NULL)
  152. {
  153. CertFreeCertificateChainEngine(hCertChainEngine);
  154. }
  155. return fRet;
  156. AddChainToStore_Error:
  157. fRet = FALSE;
  158. goto AddChainToStore_Exit;
  159. }
  160. // This function is borrowed from trustapi.cpp
  161. BOOL TrustIsCertificateSelfSigned(PCCERT_CONTEXT pContext,DWORD dwEncoding, DWORD dwFlags)
  162. {
  163. if (!(pContext) || (dwFlags != 0))
  164. {
  165. SetLastError(ERROR_INVALID_PARAMETER);
  166. return(FALSE);
  167. }
  168. if (!(CertCompareCertificateName(dwEncoding,&pContext->pCertInfo->Issuer,&pContext->pCertInfo->Subject)))
  169. {
  170. return(FALSE);
  171. }
  172. DWORD dwFlag;
  173. dwFlag = CERT_STORE_SIGNATURE_FLAG;
  174. if (!(CertVerifySubjectCertificateContext(pContext, pContext, &dwFlag)) ||
  175. (dwFlag & CERT_STORE_SIGNATURE_FLAG))
  176. {
  177. return(FALSE);
  178. }
  179. return(TRUE);
  180. }
  181. HRESULT UninstallCert(CString csInstanceName)
  182. {
  183. CComAuthInfo auth;
  184. CString key_path = ReturnGoodMetabasePath(csInstanceName);
  185. CMetaKey key(&auth, key_path, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE);
  186. if (key.Succeeded())
  187. {
  188. CString store_name;
  189. key.QueryValue(MD_SSL_CERT_STORE_NAME, store_name);
  190. if (SUCCEEDED(key.DeleteValue(MD_SSL_CERT_HASH)))
  191. {
  192. key.DeleteValue(MD_SSL_CERT_STORE_NAME);
  193. }
  194. }
  195. return key.QueryResult();
  196. }
  197. CERT_CONTEXT * GetInstalledCert(HRESULT * phResult, CString csKeyPath)
  198. {
  199. // ATLASSERT(GetEnroll() != NULL);
  200. ATLASSERT(phResult != NULL);
  201. CERT_CONTEXT * pCert = NULL;
  202. *phResult = S_OK;
  203. CComAuthInfo auth;
  204. CString key_path = ReturnGoodMetabasePath(csKeyPath);
  205. CMetaKey key(&auth, key_path, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE);
  206. if (key.Succeeded())
  207. {
  208. CString store_name;
  209. CBlob hash;
  210. if (SUCCEEDED(*phResult = key.QueryValue(MD_SSL_CERT_STORE_NAME, store_name)) &&
  211. SUCCEEDED(*phResult = key.QueryValue(MD_SSL_CERT_HASH, hash)))
  212. {
  213. // Open MY store. We assume that store type and flags
  214. // cannot be changed between installation and unistallation
  215. // of the sertificate.
  216. HCERTSTORE hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,NULL,CERT_SYSTEM_STORE_LOCAL_MACHINE,store_name);
  217. ASSERT(hStore != NULL);
  218. if (hStore != NULL)
  219. {
  220. // Now we need to find cert by hash
  221. CRYPT_HASH_BLOB crypt_hash;
  222. crypt_hash.cbData = hash.GetSize();
  223. crypt_hash.pbData = hash.GetData();
  224. pCert = (CERT_CONTEXT *)CertFindCertificateInStore(hStore,X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,0,CERT_FIND_HASH,(LPVOID)&crypt_hash,NULL);
  225. if (pCert == NULL)
  226. {
  227. *phResult = HRESULT_FROM_WIN32(GetLastError());
  228. }
  229. VERIFY(CertCloseStore(hStore, 0));
  230. }
  231. else
  232. {
  233. *phResult = HRESULT_FROM_WIN32(GetLastError());
  234. }
  235. }
  236. }
  237. else
  238. {
  239. *phResult = key.QueryResult();
  240. }
  241. return pCert;
  242. }
  243. CERT_CONTEXT * GetInstalledCert(HRESULT * phResult,DWORD cbHashBlob, char * pHashBlob)
  244. {
  245. ATLASSERT(phResult != NULL);
  246. CERT_CONTEXT * pCert = NULL;
  247. *phResult = S_OK;
  248. CString store_name = _T("MY");
  249. HCERTSTORE hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,NULL,CERT_SYSTEM_STORE_LOCAL_MACHINE,store_name);
  250. ASSERT(hStore != NULL);
  251. if (hStore != NULL)
  252. {
  253. // Now we need to find cert by hash
  254. CRYPT_HASH_BLOB crypt_hash;
  255. crypt_hash.cbData = cbHashBlob;
  256. crypt_hash.pbData = (BYTE *) pHashBlob;
  257. pCert = (CERT_CONTEXT *)CertFindCertificateInStore(hStore,X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,0,CERT_FIND_HASH,(LPVOID)&crypt_hash,NULL);
  258. if (pCert == NULL)
  259. {
  260. *phResult = HRESULT_FROM_WIN32(GetLastError());
  261. }
  262. VERIFY(CertCloseStore(hStore, 0));
  263. }
  264. else
  265. {
  266. *phResult = HRESULT_FROM_WIN32(GetLastError());
  267. }
  268. return pCert;
  269. }
  270. /*
  271. InstallHashToMetabase
  272. Function writes hash array to metabase. After that IIS
  273. could use certificate with that hash from MY store.
  274. Function expects server_name in format lm\w3svc\<number>,
  275. i.e. from root node down to virtual server
  276. */
  277. BOOL InstallHashToMetabase(CRYPT_HASH_BLOB * pHash,BSTR InstanceName,HRESULT * phResult)
  278. {
  279. BOOL bRes = FALSE;
  280. CComAuthInfo auth;
  281. CString key_path = ReturnGoodMetabasePath(InstanceName);
  282. CMetaKey key(&auth, key_path, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE);
  283. if (key.Succeeded())
  284. {
  285. CBlob blob;
  286. blob.SetValue(pHash->cbData, pHash->pbData, TRUE);
  287. bRes = SUCCEEDED(*phResult = key.SetValue(MD_SSL_CERT_HASH, blob))
  288. && SUCCEEDED(*phResult = key.SetValue(MD_SSL_CERT_STORE_NAME, CString(L"MY")));
  289. }
  290. else
  291. {
  292. *phResult = key.QueryResult();
  293. }
  294. return bRes;
  295. }
  296. HRESULT HereIsBinaryGimmieVtArray(DWORD cbBinaryBufferSize,char *pbBinaryBuffer,VARIANT * lpVarDestObject,BOOL bReturnBinaryAsVT_VARIANT)
  297. {
  298. HRESULT hr = S_OK;
  299. SAFEARRAY *aList = NULL;
  300. SAFEARRAYBOUND aBound;
  301. CHAR HUGEP *pArray = NULL;
  302. aBound.lLbound = 0;
  303. aBound.cElements = cbBinaryBufferSize;
  304. if (bReturnBinaryAsVT_VARIANT)
  305. {
  306. aList = SafeArrayCreate( VT_VARIANT, 1, &aBound );
  307. }
  308. else
  309. {
  310. aList = SafeArrayCreate( VT_UI1, 1, &aBound );
  311. }
  312. aList = SafeArrayCreate( VT_UI1, 1, &aBound );
  313. if ( aList == NULL )
  314. {
  315. hr = E_OUTOFMEMORY;
  316. goto HereIsBinaryGimmieVtArray_Exit;
  317. }
  318. hr = SafeArrayAccessData( aList, (void HUGEP * FAR *) &pArray );
  319. if (FAILED(hr))
  320. {
  321. goto HereIsBinaryGimmieVtArray_Exit;
  322. }
  323. memcpy( pArray, pbBinaryBuffer, aBound.cElements );
  324. SafeArrayUnaccessData( aList );
  325. if (bReturnBinaryAsVT_VARIANT)
  326. {
  327. V_VT(lpVarDestObject) = VT_ARRAY | VT_VARIANT;
  328. }
  329. else
  330. {
  331. V_VT(lpVarDestObject) = VT_ARRAY | VT_UI1;
  332. }
  333. V_ARRAY(lpVarDestObject) = aList;
  334. return hr;
  335. HereIsBinaryGimmieVtArray_Exit:
  336. if (aList)
  337. {SafeArrayDestroy( aList );}
  338. return hr;
  339. }
  340. HRESULT
  341. HereIsVtArrayGimmieBinary(
  342. VARIANT * lpVarSrcObject,
  343. DWORD * cbBinaryBufferSize,
  344. char **pbBinaryBuffer,
  345. BOOL bReturnBinaryAsVT_VARIANT
  346. )
  347. {
  348. HRESULT hr = S_OK;
  349. LONG dwSLBound = 0;
  350. LONG dwSUBound = 0;
  351. CHAR HUGEP *pArray = NULL;
  352. if (NULL == cbBinaryBufferSize || NULL == pbBinaryBuffer)
  353. {
  354. hr = E_INVALIDARG;
  355. goto HereIsVtArrayGimmieBinary_Exit;
  356. }
  357. if (bReturnBinaryAsVT_VARIANT)
  358. {
  359. hr = VariantChangeType(lpVarSrcObject,lpVarSrcObject,0,VT_ARRAY | VT_VARIANT);
  360. }
  361. else
  362. {
  363. hr = VariantChangeType(lpVarSrcObject,lpVarSrcObject,0,VT_ARRAY | VT_UI1);
  364. }
  365. if (FAILED(hr))
  366. {
  367. if (hr != E_OUTOFMEMORY)
  368. {
  369. hr = OLE_E_CANTCONVERT;
  370. }
  371. goto HereIsVtArrayGimmieBinary_Exit;
  372. }
  373. if (bReturnBinaryAsVT_VARIANT)
  374. {
  375. if( lpVarSrcObject->vt != (VT_ARRAY | VT_VARIANT))
  376. {
  377. hr = OLE_E_CANTCONVERT;
  378. goto HereIsVtArrayGimmieBinary_Exit;
  379. }
  380. }
  381. else
  382. {
  383. if( lpVarSrcObject->vt != (VT_ARRAY | VT_UI1))
  384. {
  385. hr = OLE_E_CANTCONVERT;
  386. goto HereIsVtArrayGimmieBinary_Exit;
  387. }
  388. }
  389. hr = SafeArrayGetLBound(V_ARRAY(lpVarSrcObject),1,(long FAR *) &dwSLBound );
  390. if (FAILED(hr))
  391. {goto HereIsVtArrayGimmieBinary_Exit;}
  392. hr = SafeArrayGetUBound(V_ARRAY(lpVarSrcObject),1,(long FAR *) &dwSUBound );
  393. if (FAILED(hr))
  394. {goto HereIsVtArrayGimmieBinary_Exit;}
  395. //*pbBinaryBuffer = (LPBYTE) AllocADsMem(dwSUBound - dwSLBound + 1);
  396. *pbBinaryBuffer = (char *) ::CoTaskMemAlloc(dwSUBound - dwSLBound + 1);
  397. if (*pbBinaryBuffer == NULL)
  398. {
  399. hr = E_OUTOFMEMORY;
  400. goto HereIsVtArrayGimmieBinary_Exit;
  401. }
  402. *cbBinaryBufferSize = dwSUBound - dwSLBound + 1;
  403. hr = SafeArrayAccessData( V_ARRAY(lpVarSrcObject),(void HUGEP * FAR *) &pArray );
  404. if (FAILED(hr))
  405. {goto HereIsVtArrayGimmieBinary_Exit;}
  406. memcpy(*pbBinaryBuffer,pArray,dwSUBound-dwSLBound+1);
  407. SafeArrayUnaccessData( V_ARRAY(lpVarSrcObject) );
  408. HereIsVtArrayGimmieBinary_Exit:
  409. return hr;
  410. }
  411. BOOL IsCertExportable(PCCERT_CONTEXT pCertContext)
  412. {
  413. HCRYPTPROV hCryptProv = NULL;
  414. DWORD dwKeySpec = 0;
  415. BOOL fCallerFreeProv = FALSE;
  416. BOOL fReturn = FALSE;
  417. HCRYPTKEY hKey = NULL;
  418. DWORD dwPermissions = 0;
  419. DWORD dwSize = 0;
  420. if (!pCertContext)
  421. {
  422. fReturn = FALSE;
  423. goto IsCertExportable_Exit;
  424. }
  425. //
  426. // first get the private key context
  427. //
  428. if (!CryptAcquireCertificatePrivateKey(
  429. pCertContext,
  430. CRYPT_ACQUIRE_USE_PROV_INFO_FLAG | CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
  431. NULL,
  432. &hCryptProv,
  433. &dwKeySpec,
  434. &fCallerFreeProv))
  435. {
  436. fReturn = FALSE;
  437. goto IsCertExportable_Exit;
  438. }
  439. //
  440. // get the handle to the key
  441. //
  442. if (!CryptGetUserKey(hCryptProv, dwKeySpec, &hKey))
  443. {
  444. fReturn = FALSE;
  445. goto IsCertExportable_Exit;
  446. }
  447. //
  448. // finally, get the permissions on the key and check if it is exportable
  449. //
  450. dwSize = sizeof(dwPermissions);
  451. if (!CryptGetKeyParam(hKey, KP_PERMISSIONS, (PBYTE)&dwPermissions, &dwSize, 0))
  452. {
  453. fReturn = FALSE;
  454. goto IsCertExportable_Exit;
  455. }
  456. fReturn = (dwPermissions & CRYPT_EXPORT) ? TRUE : FALSE;
  457. IsCertExportable_Exit:
  458. if (hKey != NULL){CryptDestroyKey(hKey);}
  459. if (fCallerFreeProv){CryptReleaseContext(hCryptProv, 0);}
  460. return fReturn;
  461. }
  462. BOOL FormatDateString(LPWSTR * pszReturn, FILETIME ft, BOOL fIncludeTime, BOOL fLongFormat)
  463. {
  464. int cch;
  465. int cch2;
  466. SYSTEMTIME st;
  467. FILETIME localTime;
  468. LPWSTR psz = NULL;
  469. if (!FileTimeToLocalFileTime(&ft, &localTime))
  470. {
  471. return FALSE;
  472. }
  473. if (!FileTimeToSystemTime(&localTime, &st))
  474. {
  475. //
  476. // if the conversion to local time failed, then just use the original time
  477. //
  478. if (!FileTimeToSystemTime(&ft, &st))
  479. {
  480. return FALSE;
  481. }
  482. }
  483. cch = (GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &st, NULL, NULL, 0) +
  484. GetDateFormat(LOCALE_SYSTEM_DEFAULT, fLongFormat ? DATE_LONGDATE : 0, &st, NULL, NULL, 0) + 5);
  485. if (NULL == (psz = (LPWSTR) malloc((cch+5) * sizeof(WCHAR))))
  486. {
  487. return FALSE;
  488. }
  489. cch2 = GetDateFormat(LOCALE_SYSTEM_DEFAULT, fLongFormat ? DATE_LONGDATE : 0, &st, NULL, psz, cch);
  490. if (fIncludeTime)
  491. {
  492. psz[cch2-1] = ' ';
  493. GetTimeFormat(LOCALE_SYSTEM_DEFAULT, TIME_NOSECONDS, &st, NULL, &psz[cch2], cch-cch2);
  494. }
  495. if (psz)
  496. {
  497. *pszReturn = psz;
  498. return TRUE;
  499. }
  500. else
  501. {
  502. return FALSE;
  503. }
  504. }
  505. const WCHAR RgwchHex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  506. BOOL FormatMemBufToString(LPWSTR *ppString, LPBYTE pbData, DWORD cbData)
  507. {
  508. DWORD i = 0;
  509. LPBYTE pb;
  510. DWORD numCharsInserted = 0;
  511. //
  512. // calculate the size needed
  513. //
  514. pb = pbData;
  515. while (pb <= &(pbData[cbData-1]))
  516. {
  517. if (numCharsInserted == 4)
  518. {
  519. i += sizeof(WCHAR);
  520. numCharsInserted = 0;
  521. }
  522. else
  523. {
  524. i += 2 * sizeof(WCHAR);
  525. pb++;
  526. numCharsInserted += 2;
  527. }
  528. }
  529. if (NULL == (*ppString = (LPWSTR) malloc(i+sizeof(WCHAR))))
  530. {
  531. return FALSE;
  532. }
  533. //
  534. // copy to the buffer
  535. //
  536. i = 0;
  537. numCharsInserted = 0;
  538. pb = pbData;
  539. while (pb <= &(pbData[cbData-1]))
  540. {
  541. if (numCharsInserted == 4)
  542. {
  543. (*ppString)[i++] = L' ';
  544. numCharsInserted = 0;
  545. }
  546. else
  547. {
  548. (*ppString)[i++] = RgwchHex[(*pb & 0xf0) >> 4];
  549. (*ppString)[i++] = RgwchHex[*pb & 0x0f];
  550. pb++;
  551. numCharsInserted += 2;
  552. }
  553. }
  554. (*ppString)[i] = 0;
  555. return TRUE;
  556. }
  557. BOOL MyGetOIDInfo(LPWSTR string, DWORD stringSize, LPSTR pszObjId)
  558. {
  559. /*
  560. PCCRYPT_OID_INFO pOIDInfo;
  561. pOIDInfo = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, pszObjId, 0);
  562. if (pOIDInfo != NULL)
  563. {
  564. if ((DWORD)wcslen(pOIDInfo->pwszName)+1 <= stringSize)
  565. {
  566. wcscpy(string, pOIDInfo->pwszName);
  567. }
  568. else
  569. {
  570. return FALSE;
  571. }
  572. }
  573. else
  574. {
  575. */
  576. return (MultiByteToWideChar(CP_ACP, 0, pszObjId, -1, string, stringSize) != 0);
  577. /*
  578. }
  579. return TRUE;
  580. */
  581. }
  582. #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
  583. #define STRING_ALLOCATION_SIZE 128
  584. BOOL GetCertDescription(PCCERT_CONTEXT pCert, LPWSTR *ppString, DWORD * cbReturn, BOOL fMultiline)
  585. {
  586. CERT_NAME_INFO *pNameInfo;
  587. DWORD cbNameInfo;
  588. WCHAR szText[256];
  589. LPWSTR pwszText;
  590. int i,j;
  591. DWORD numChars = 1; // 1 for the terminating 0
  592. DWORD numAllocations = 1;
  593. void *pTemp;
  594. //
  595. // decode the dnname into a CERT_NAME_INFO struct
  596. //
  597. if (!CryptDecodeObject(
  598. X509_ASN_ENCODING,
  599. X509_UNICODE_NAME,
  600. pCert->pCertInfo->Subject.pbData,
  601. pCert->pCertInfo->Subject.cbData,
  602. 0,
  603. NULL,
  604. &cbNameInfo))
  605. {
  606. return FALSE;
  607. }
  608. if (NULL == (pNameInfo = (CERT_NAME_INFO *) malloc(cbNameInfo)))
  609. {
  610. return FALSE;
  611. }
  612. if (!CryptDecodeObject(
  613. X509_ASN_ENCODING,
  614. X509_UNICODE_NAME,
  615. pCert->pCertInfo->Subject.pbData,
  616. pCert->pCertInfo->Subject.cbData,
  617. 0,
  618. pNameInfo,
  619. &cbNameInfo))
  620. {
  621. free (pNameInfo);
  622. return FALSE;
  623. }
  624. //
  625. // allocate an initial buffer for the DN name string, then if it grows larger
  626. // than the initial amount just grow as needed
  627. //
  628. *ppString = (LPWSTR) malloc(STRING_ALLOCATION_SIZE * sizeof(WCHAR));
  629. if (*ppString == NULL)
  630. {
  631. free (pNameInfo);
  632. return FALSE;
  633. }
  634. (*ppString)[0] = 0;
  635. //
  636. // loop for each rdn and add it to the string
  637. //
  638. for (i=pNameInfo->cRDN-1; i>=0; i--)
  639. {
  640. // if this is not the first iteration, then add a eol or a ", "
  641. if (i != (int)pNameInfo->cRDN-1)
  642. {
  643. if (numChars+2 >= (numAllocations * STRING_ALLOCATION_SIZE))
  644. {
  645. pTemp = realloc(*ppString, ++numAllocations * STRING_ALLOCATION_SIZE * sizeof(WCHAR));
  646. if (pTemp == NULL)
  647. {
  648. free (pNameInfo);
  649. free (*ppString);
  650. return FALSE;
  651. }
  652. *ppString = (LPWSTR) pTemp;
  653. }
  654. if (fMultiline)
  655. wcscat(*ppString, L"\n");
  656. else
  657. wcscat(*ppString, L", ");
  658. numChars += 2;
  659. }
  660. for (j=pNameInfo->rgRDN[i].cRDNAttr-1; j>=0; j--)
  661. {
  662. // if this is not the first iteration, then add a eol or a ", "
  663. if (j != (int)pNameInfo->rgRDN[i].cRDNAttr-1)
  664. {
  665. if (numChars+2 >= (numAllocations * STRING_ALLOCATION_SIZE))
  666. {
  667. pTemp = realloc(*ppString, ++numAllocations * STRING_ALLOCATION_SIZE * sizeof(WCHAR));
  668. if (pTemp == NULL)
  669. {
  670. free (pNameInfo);
  671. free (*ppString);
  672. return FALSE;
  673. }
  674. *ppString = (LPWSTR) pTemp;
  675. }
  676. if (fMultiline)
  677. wcscat(*ppString, L"\n");
  678. else
  679. wcscat(*ppString, L", ");
  680. numChars += 2;
  681. }
  682. //
  683. // add the field name to the string if it is Multiline display
  684. //
  685. if (fMultiline)
  686. {
  687. if (!MyGetOIDInfo(szText, ARRAYSIZE(szText), pNameInfo->rgRDN[i].rgRDNAttr[j].pszObjId))
  688. {
  689. free (pNameInfo);
  690. return FALSE;
  691. }
  692. if ((numChars + wcslen(szText) + 3) >= (numAllocations * STRING_ALLOCATION_SIZE))
  693. {
  694. // increment the number of allocation blocks until it is large enough
  695. while ((numChars + wcslen(szText) + 3) >= (++numAllocations * STRING_ALLOCATION_SIZE));
  696. pTemp = realloc(*ppString, numAllocations * STRING_ALLOCATION_SIZE * sizeof(WCHAR));
  697. if (pTemp == NULL)
  698. {
  699. free (pNameInfo);
  700. free (*ppString);
  701. return FALSE;
  702. }
  703. *ppString = (LPWSTR) pTemp;
  704. }
  705. numChars += wcslen(szText) + 1;
  706. wcscat(*ppString, szText);
  707. wcscat(*ppString, L"="); // delimiter
  708. }
  709. //
  710. // add the value to the string
  711. //
  712. if (CERT_RDN_ENCODED_BLOB == pNameInfo->rgRDN[i].rgRDNAttr[j].dwValueType ||
  713. CERT_RDN_OCTET_STRING == pNameInfo->rgRDN[i].rgRDNAttr[j].dwValueType)
  714. {
  715. // translate the buffer to a text string and display it that way
  716. if (FormatMemBufToString(
  717. &pwszText,
  718. pNameInfo->rgRDN[i].rgRDNAttr[j].Value.pbData,
  719. pNameInfo->rgRDN[i].rgRDNAttr[j].Value.cbData))
  720. {
  721. if ((numChars + wcslen(pwszText)) >= (numAllocations * STRING_ALLOCATION_SIZE))
  722. {
  723. // increment the number of allocation blocks until it is large enough
  724. while ((numChars + wcslen(pwszText)) >= (++numAllocations * STRING_ALLOCATION_SIZE));
  725. pTemp = realloc(*ppString, numAllocations * STRING_ALLOCATION_SIZE * sizeof(WCHAR));
  726. if (pTemp == NULL)
  727. {
  728. free (pwszText);
  729. free (pNameInfo);
  730. free (*ppString);
  731. return FALSE;
  732. }
  733. *ppString = (LPWSTR) pTemp;
  734. }
  735. wcscat(*ppString, pwszText);
  736. numChars += wcslen(pwszText);
  737. free (pwszText);
  738. }
  739. }
  740. else
  741. {
  742. // buffer is already a string so just copy it
  743. if ((numChars + (pNameInfo->rgRDN[i].rgRDNAttr[j].Value.cbData/sizeof(WCHAR)))
  744. >= (numAllocations * STRING_ALLOCATION_SIZE))
  745. {
  746. // increment the number of allocation blocks until it is large enough
  747. while ((numChars + (pNameInfo->rgRDN[i].rgRDNAttr[j].Value.cbData/sizeof(WCHAR)))
  748. >= (++numAllocations * STRING_ALLOCATION_SIZE));
  749. pTemp = realloc(*ppString, numAllocations * STRING_ALLOCATION_SIZE * sizeof(WCHAR));
  750. if (pTemp == NULL)
  751. {
  752. free (pNameInfo);
  753. free (*ppString);
  754. return FALSE;
  755. }
  756. *ppString = (LPWSTR) pTemp;
  757. }
  758. wcscat(*ppString, (LPWSTR) pNameInfo->rgRDN[i].rgRDNAttr[j].Value.pbData);
  759. numChars += (pNameInfo->rgRDN[i].rgRDNAttr[j].Value.cbData/sizeof(WCHAR));
  760. }
  761. }
  762. }
  763. {
  764. // issued to
  765. LPWSTR pwName = NULL;
  766. DWORD cchName = CertGetNameString(pCert, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, NULL, 0);
  767. if (cchName > 1 && (NULL != ( pwName = (LPWSTR) malloc (cchName * sizeof(WCHAR) ))))
  768. {
  769. BOOL bRes = FALSE;
  770. bRes = (1 != CertGetNameString(pCert, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, pwName, cchName));
  771. if (bRes)
  772. {
  773. wcscat(*ppString, (LPWSTR) L"\n");
  774. numChars += 2;
  775. // append it on to the string.
  776. //#define CERT_INFO_ISSUER_FLAG 4
  777. wcscat(*ppString, (LPWSTR) L"4=");
  778. numChars += 2;
  779. // append it on to the string.
  780. wcscat(*ppString, (LPWSTR) pwName);
  781. numChars += (cchName);
  782. }
  783. if (pwName) {free(pwName);pwName=NULL;}
  784. }
  785. // expiration date
  786. if (FormatDateString(&pwName, pCert->pCertInfo->NotAfter, FALSE, FALSE))
  787. {
  788. wcscat(*ppString, (LPWSTR) L"\n");
  789. numChars += 2;
  790. // append it on to the string.
  791. //#define CERT_INFO_NOT_AFTER_FLAG 6
  792. wcscat(*ppString, (LPWSTR) L"6=");
  793. numChars += 2;
  794. // append it on to the string.
  795. wcscat(*ppString, (LPWSTR) pwName);
  796. numChars += wcslen(pwName);
  797. if (pwName) {free(pwName);pwName = NULL;}
  798. }
  799. }
  800. *cbReturn = numChars;
  801. free (pNameInfo);
  802. return TRUE;
  803. }