Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1540 lines
43 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. cert.c
  5. Abstract:
  6. Implements the certificates type module, which abstracts physical access to
  7. certificates
  8. Author:
  9. Calin Negreanu (calinn) 03 Oct 2001
  10. Revision History:
  11. --*/
  12. //
  13. // Includes
  14. //
  15. #include "pch.h"
  16. #include "v1p.h"
  17. #include "logmsg.h"
  18. #include <wincrypt.h>
  19. #define DBG_CERT "Certificates"
  20. //
  21. // Strings
  22. //
  23. #define S_CERT_POOL_NAME "Certificates"
  24. #define S_CERT_NAME TEXT("Certificates")
  25. //
  26. // Constants
  27. //
  28. // None
  29. //
  30. // Macros
  31. //
  32. // None
  33. //
  34. // Types
  35. //
  36. typedef struct {
  37. HCERTSTORE StoreHandle;
  38. PCTSTR CertStore;
  39. PCTSTR CertPattern;
  40. PCCERT_CONTEXT CertContext;
  41. } CERT_ENUM, *PCERT_ENUM;
  42. // Certificate APIs
  43. // NT4 SP3
  44. // Win95 OSR2
  45. typedef HCERTSTORE(WINAPI CERTOPENSTORE) (
  46. IN LPCSTR lpszStoreProvider,
  47. IN DWORD dwMsgAndCertEncodingType,
  48. IN HCRYPTPROV hCryptProv,
  49. IN DWORD dwFlags,
  50. IN const void *pvPara
  51. );
  52. typedef CERTOPENSTORE *PCERTOPENSTORE;
  53. // NT4 SP3
  54. // Win95 OSR2
  55. typedef PCCERT_CONTEXT(WINAPI CERTENUMCERTIFICATESINSTORE) (
  56. IN HCERTSTORE hCertStore,
  57. IN PCCERT_CONTEXT pPrevCertContext
  58. );
  59. typedef CERTENUMCERTIFICATESINSTORE *PCERTENUMCERTIFICATESINSTORE;
  60. // NT4 SP3
  61. // Win95 OSR2
  62. typedef BOOL(WINAPI CERTGETCERTIFICATECONTEXTPROPERTY) (
  63. IN PCCERT_CONTEXT pCertContext,
  64. IN DWORD dwPropId,
  65. OUT void *pvData,
  66. IN OUT DWORD *pcbData
  67. );
  68. typedef CERTGETCERTIFICATECONTEXTPROPERTY *PCERTGETCERTIFICATECONTEXTPROPERTY;
  69. // NT4 SP3
  70. // Win95 OSR2
  71. typedef BOOL(WINAPI CERTCLOSESTORE) (
  72. IN HCERTSTORE hCertStore,
  73. IN DWORD dwFlags
  74. );
  75. typedef CERTCLOSESTORE *PCERTCLOSESTORE;
  76. // NT4 SP3
  77. typedef BOOL(WINAPI CRYPTACQUIRECERTIFICATEPRIVATEKEY) (
  78. IN PCCERT_CONTEXT pCert,
  79. IN DWORD dwFlags,
  80. IN void *pvReserved,
  81. OUT HCRYPTPROV *phCryptProv,
  82. OUT DWORD *pdwKeySpec,
  83. OUT BOOL *pfCallerFreeProv
  84. );
  85. typedef CRYPTACQUIRECERTIFICATEPRIVATEKEY *PCRYPTACQUIRECERTIFICATEPRIVATEKEY;
  86. // NT4 SP3
  87. // Win95 OSR2
  88. typedef BOOL(WINAPI CERTADDCERTIFICATECONTEXTTOSTORE) (
  89. IN HCERTSTORE hCertStore,
  90. IN PCCERT_CONTEXT pCertContext,
  91. IN DWORD dwAddDisposition,
  92. OUT PCCERT_CONTEXT *ppStoreContext
  93. );
  94. typedef CERTADDCERTIFICATECONTEXTTOSTORE *PCERTADDCERTIFICATECONTEXTTOSTORE;
  95. // NT4 SP3
  96. // Win95 OSR2
  97. typedef BOOL(WINAPI CERTFREECERTIFICATECONTEXT) (
  98. IN PCCERT_CONTEXT pCertContext
  99. );
  100. typedef CERTFREECERTIFICATECONTEXT *PCERTFREECERTIFICATECONTEXT;
  101. // NT4 SP3
  102. // Win95 OSR2
  103. typedef BOOL(WINAPI CERTDELETECERTIFICATEFROMSTORE) (
  104. IN PCCERT_CONTEXT pCertContext
  105. );
  106. typedef CERTDELETECERTIFICATEFROMSTORE *PCERTDELETECERTIFICATEFROMSTORE;
  107. // Win2k?
  108. // Win98?
  109. typedef BOOL(WINAPI PFXEXPORTCERTSTORE) (
  110. IN HCERTSTORE hStore,
  111. IN OUT CRYPT_DATA_BLOB* pPFX,
  112. IN LPCWSTR szPassword,
  113. IN DWORD dwFlags
  114. );
  115. typedef PFXEXPORTCERTSTORE *PPFXEXPORTCERTSTORE;
  116. // Win2k?
  117. // Win98?
  118. typedef HCERTSTORE(WINAPI PFXIMPORTCERTSTORE) (
  119. IN CRYPT_DATA_BLOB* pPFX,
  120. IN PCWSTR szPassword,
  121. IN DWORD dwFlags
  122. );
  123. typedef PFXIMPORTCERTSTORE *PPFXIMPORTCERTSTORE;
  124. //
  125. // Globals
  126. //
  127. PMHANDLE g_CertPool = NULL;
  128. BOOL g_DelayCertOp;
  129. MIG_OBJECTTYPEID g_CertType = 0;
  130. GROWBUFFER g_CertConversionBuff = INIT_GROWBUFFER;
  131. PCERTOPENSTORE g_CertOpenStore = NULL;
  132. PCERTENUMCERTIFICATESINSTORE g_CertEnumCertificatesInStore = NULL;
  133. PCERTGETCERTIFICATECONTEXTPROPERTY g_CertGetCertificateContextProperty = NULL;
  134. PCERTCLOSESTORE g_CertCloseStore = NULL;
  135. PCRYPTACQUIRECERTIFICATEPRIVATEKEY g_CryptAcquireCertificatePrivateKey = NULL;
  136. PCERTADDCERTIFICATECONTEXTTOSTORE g_CertAddCertificateContextToStore = NULL;
  137. PCERTFREECERTIFICATECONTEXT g_CertFreeCertificateContext = NULL;
  138. PCERTDELETECERTIFICATEFROMSTORE g_CertDeleteCertificateFromStore = NULL;
  139. PPFXEXPORTCERTSTORE g_PFXExportCertStore = NULL;
  140. PPFXIMPORTCERTSTORE g_PFXImportCertStore = NULL;
  141. //
  142. // Types
  143. //
  144. // None
  145. //
  146. // Macro expansion list
  147. //
  148. // None
  149. //
  150. // Private function prototypes
  151. //
  152. // None
  153. //
  154. // Macro expansion definition
  155. //
  156. // None
  157. //
  158. // Private prototypes
  159. //
  160. TYPE_ENUMFIRSTPHYSICALOBJECT EnumFirstCertificate;
  161. TYPE_ENUMNEXTPHYSICALOBJECT EnumNextCertificate;
  162. TYPE_ABORTENUMPHYSICALOBJECT AbortCertificateEnum;
  163. TYPE_CONVERTOBJECTTOMULTISZ ConvertCertificateToMultiSz;
  164. TYPE_CONVERTMULTISZTOOBJECT ConvertMultiSzToCertificate;
  165. TYPE_GETNATIVEOBJECTNAME GetNativeCertificateName;
  166. TYPE_ACQUIREPHYSICALOBJECT AcquireCertificate;
  167. TYPE_RELEASEPHYSICALOBJECT ReleaseCertificate;
  168. TYPE_DOESPHYSICALOBJECTEXIST DoesCertificateExist;
  169. TYPE_REMOVEPHYSICALOBJECT RemoveCertificate;
  170. TYPE_CREATEPHYSICALOBJECT CreateCertificate;
  171. TYPE_CONVERTOBJECTCONTENTTOUNICODE ConvertCertificateContentToUnicode;
  172. TYPE_CONVERTOBJECTCONTENTTOANSI ConvertCertificateContentToAnsi;
  173. TYPE_FREECONVERTEDOBJECTCONTENT FreeConvertedCertificateContent;
  174. //
  175. // Code
  176. //
  177. BOOL
  178. CertificatesInitialize (
  179. VOID
  180. )
  181. /*++
  182. Routine Description:
  183. CertificateInitialize is the ModuleInitialize entry point for the certificates
  184. module.
  185. Arguments:
  186. None.
  187. Return Value:
  188. TRUE if init succeeded, FALSE otherwise.
  189. --*/
  190. {
  191. g_CertPool = PmCreateNamedPool (S_CERT_POOL_NAME);
  192. return (g_CertPool != NULL);
  193. }
  194. VOID
  195. CertificatesTerminate (
  196. VOID
  197. )
  198. /*++
  199. Routine Description:
  200. CertificatesTerminate is the ModuleTerminate entry point for the certificates module.
  201. Arguments:
  202. None.
  203. Return Value:
  204. None.
  205. --*/
  206. {
  207. GbFree (&g_CertConversionBuff);
  208. if (g_CertPool) {
  209. PmDestroyPool (g_CertPool);
  210. g_CertPool = NULL;
  211. }
  212. }
  213. VOID
  214. WINAPI
  215. CertificatesEtmNewUserCreated (
  216. IN PCTSTR UserName,
  217. IN PCTSTR DomainName,
  218. IN PCTSTR UserProfileRoot,
  219. IN PSID UserSid
  220. )
  221. /*++
  222. Routine Description:
  223. CertificatesEtmNewUserCreated is a callback that gets called when a new user
  224. account is created. In this case, we must delay the apply of certificates,
  225. because we can only apply to the current user.
  226. Arguments:
  227. UserName - Specifies the name of the user being created
  228. DomainName - Specifies the NT domain name for the user (or NULL for no
  229. domain)
  230. UserProfileRoot - Specifies the root path to the user profile directory
  231. UserSid - Specifies the user's SID
  232. Return Value:
  233. None.
  234. --*/
  235. {
  236. // a new user was created, the certificate operations need to be delayed
  237. g_DelayCertOp = TRUE;
  238. }
  239. BOOL
  240. pLoadCertEntries (
  241. VOID
  242. )
  243. {
  244. HMODULE cryptDll = NULL;
  245. BOOL result = FALSE;
  246. __try {
  247. cryptDll = LoadLibrary (TEXT("CRYPT32.DLL"));
  248. }
  249. __except (EXCEPTION_EXECUTE_HANDLER) {
  250. cryptDll = NULL;
  251. }
  252. if (cryptDll) {
  253. g_CertOpenStore = (PCERTOPENSTORE) GetProcAddress (cryptDll, "CertOpenStore");
  254. g_CertEnumCertificatesInStore = (PCERTENUMCERTIFICATESINSTORE) GetProcAddress (cryptDll, "CertEnumCertificatesInStore");
  255. g_CertGetCertificateContextProperty = (PCERTGETCERTIFICATECONTEXTPROPERTY) GetProcAddress (cryptDll, "CertGetCertificateContextProperty");
  256. g_CertCloseStore = (PCERTCLOSESTORE) GetProcAddress (cryptDll, "CertCloseStore");
  257. g_CryptAcquireCertificatePrivateKey = (PCRYPTACQUIRECERTIFICATEPRIVATEKEY) GetProcAddress (cryptDll, "CryptAcquireCertificatePrivateKey");
  258. g_CertAddCertificateContextToStore = (PCERTADDCERTIFICATECONTEXTTOSTORE) GetProcAddress (cryptDll, "CertAddCertificateContextToStore");
  259. g_CertFreeCertificateContext = (PCERTFREECERTIFICATECONTEXT) GetProcAddress (cryptDll, "CertFreeCertificateContext");
  260. g_PFXExportCertStore = (PPFXEXPORTCERTSTORE) GetProcAddress (cryptDll, "PFXExportCertStore");
  261. g_CertDeleteCertificateFromStore = (PCERTDELETECERTIFICATEFROMSTORE) GetProcAddress (cryptDll, "CertDeleteCertificateFromStore");
  262. g_PFXImportCertStore = (PPFXIMPORTCERTSTORE) GetProcAddress (cryptDll, "PFXImportCertStore");
  263. // BUGBUG - verify that all functions are installed
  264. } else {
  265. DEBUGMSG ((DBG_CERT, "Crypt APIs are not installed on this computer."));
  266. }
  267. return result;
  268. }
  269. BOOL
  270. WINAPI
  271. CertificatesEtmInitialize (
  272. IN MIG_PLATFORMTYPEID Platform,
  273. IN PMIG_LOGCALLBACK LogCallback,
  274. IN PVOID Reserved
  275. )
  276. /*++
  277. Routine Description:
  278. CertificatesEtmInitialize initializes the physical type module aspect of this
  279. code. The ETM module is responsible for abstracting all access to certificates.
  280. Arguments:
  281. Platform - Specifies the platform that the type is running on
  282. (PLATFORM_SOURCE or PLATFORM_DESTINATION)
  283. LogCallback - Specifies the arg to pass to the central logging mechanism
  284. Reserved - Unused
  285. Return Value:
  286. TRUE if initialization succeeded, FALSE otherwise.
  287. --*/
  288. {
  289. TYPE_REGISTER certTypeData;
  290. LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback);
  291. //
  292. // Register the type module callbacks
  293. //
  294. ZeroMemory (&certTypeData, sizeof (TYPE_REGISTER));
  295. certTypeData.Priority = PRIORITY_CERTIFICATES;
  296. if (Platform != PLATFORM_SOURCE) {
  297. certTypeData.RemovePhysicalObject = RemoveCertificate;
  298. certTypeData.CreatePhysicalObject = CreateCertificate;
  299. }
  300. certTypeData.DoesPhysicalObjectExist = DoesCertificateExist;
  301. certTypeData.EnumFirstPhysicalObject = EnumFirstCertificate;
  302. certTypeData.EnumNextPhysicalObject = EnumNextCertificate;
  303. certTypeData.AbortEnumPhysicalObject = AbortCertificateEnum;
  304. certTypeData.ConvertObjectToMultiSz = ConvertCertificateToMultiSz;
  305. certTypeData.ConvertMultiSzToObject = ConvertMultiSzToCertificate;
  306. certTypeData.GetNativeObjectName = GetNativeCertificateName;
  307. certTypeData.AcquirePhysicalObject = AcquireCertificate;
  308. certTypeData.ReleasePhysicalObject = ReleaseCertificate;
  309. certTypeData.ConvertObjectContentToUnicode = ConvertCertificateContentToUnicode;
  310. certTypeData.ConvertObjectContentToAnsi = ConvertCertificateContentToAnsi;
  311. certTypeData.FreeConvertedObjectContent = FreeConvertedCertificateContent;
  312. g_CertType = IsmRegisterObjectType (
  313. S_CERT_NAME,
  314. TRUE,
  315. FALSE,
  316. &certTypeData
  317. );
  318. MYASSERT (g_CertType);
  319. pLoadCertEntries ();
  320. return TRUE;
  321. }
  322. BOOL
  323. pFillCertEnumPtr (
  324. IN OUT PMIG_TYPEOBJECTENUM EnumPtr,
  325. IN PCERT_ENUM CertEnum,
  326. IN PCTSTR CertName
  327. )
  328. {
  329. BOOL result = FALSE;
  330. if (EnumPtr->ObjectName) {
  331. IsmDestroyObjectHandle (EnumPtr->ObjectName);
  332. EnumPtr->ObjectName = NULL;
  333. }
  334. if (EnumPtr->ObjectLeaf) {
  335. IsmReleaseMemory (EnumPtr->ObjectLeaf);
  336. EnumPtr->ObjectLeaf = NULL;
  337. }
  338. if (EnumPtr->NativeObjectName) {
  339. IsmReleaseMemory (EnumPtr->NativeObjectName);
  340. EnumPtr->NativeObjectName = NULL;
  341. }
  342. EnumPtr->ObjectLeaf = IsmDuplicateString (CertName);
  343. EnumPtr->ObjectName = IsmCreateObjectHandle (CertEnum->CertStore, EnumPtr->ObjectLeaf);
  344. EnumPtr->ObjectNode = CertEnum->CertStore;
  345. EnumPtr->NativeObjectName = GetNativeCertificateName (EnumPtr->ObjectName);
  346. GetNodePatternMinMaxLevels (CertEnum->CertStore, NULL, &EnumPtr->Level, NULL);
  347. EnumPtr->SubLevel = 0;
  348. EnumPtr->IsLeaf = TRUE;
  349. EnumPtr->IsNode = TRUE;
  350. EnumPtr->Details.DetailsSize = 0;
  351. EnumPtr->Details.DetailsData = NULL;
  352. return TRUE;
  353. }
  354. PCTSTR
  355. pGetCertName (
  356. IN PCCERT_CONTEXT CertContext
  357. )
  358. {
  359. PTSTR result = NULL;
  360. PTSTR resultPtr = NULL;
  361. UINT i;
  362. if (!CertContext) {
  363. return NULL;
  364. }
  365. if (!CertContext->pCertInfo) {
  366. return NULL;
  367. }
  368. if (!CertContext->pCertInfo->SerialNumber.cbData) {
  369. return NULL;
  370. }
  371. result = PmGetMemory (g_CertPool, CertContext->pCertInfo->SerialNumber.cbData * 3 * sizeof (TCHAR));
  372. if (result) {
  373. resultPtr = result;
  374. *resultPtr = 0;
  375. for (i = CertContext->pCertInfo->SerialNumber.cbData; i > 0; i--) {
  376. wsprintf (resultPtr, TEXT("%02x"), CertContext->pCertInfo->SerialNumber.pbData[i - 1]);
  377. resultPtr = GetEndOfString (resultPtr);
  378. if (i > 1) {
  379. _tcscat (resultPtr, TEXT(" "));
  380. resultPtr = GetEndOfString (resultPtr);
  381. }
  382. }
  383. }
  384. return result;
  385. }
  386. BOOL
  387. pGetNextCertFromStore (
  388. IN OUT PMIG_TYPEOBJECTENUM EnumPtr,
  389. IN PCERT_ENUM CertEnum
  390. )
  391. {
  392. PCTSTR name = NULL;
  393. DWORD nameSize = 0;
  394. BOOL result = FALSE;
  395. do {
  396. // do we have the API?
  397. if (g_CertEnumCertificatesInStore == NULL) {
  398. return FALSE;
  399. }
  400. CertEnum->CertContext = g_CertEnumCertificatesInStore (CertEnum->StoreHandle, CertEnum->CertContext);
  401. if (!CertEnum->CertContext) {
  402. return FALSE;
  403. }
  404. // let's get the certificate "name". This is actually the serial number made
  405. // into a string. This is the only unique thing that I could see.
  406. name = pGetCertName (CertEnum->CertContext);
  407. if (!name) {
  408. return FALSE;
  409. }
  410. if (IsPatternMatchEx (CertEnum->CertPattern, name)) {
  411. break;
  412. }
  413. } while (TRUE);
  414. result = pFillCertEnumPtr (EnumPtr, CertEnum, name);
  415. PmReleaseMemory (g_CertPool, name);
  416. name = NULL;
  417. return result;
  418. }
  419. HCERTSTORE
  420. pOpenCertStore (
  421. IN PCTSTR CertStore,
  422. IN BOOL Create
  423. )
  424. {
  425. PCWSTR certStoreW = NULL;
  426. HCERTSTORE result = NULL;
  427. __try {
  428. // let's do the UNICODE conversion if needed
  429. #ifndef UNICODE
  430. certStoreW = ConvertAtoW (CertStore);
  431. #endif
  432. // do we have the API?
  433. if (g_CertOpenStore != NULL) {
  434. // now let's understand what kind of store is this
  435. // First we try to see if this is a file
  436. if (DoesFileExist (CertStore)) {
  437. // it is a file, open it
  438. // first we try current user
  439. result = g_CertOpenStore (
  440. CERT_STORE_PROV_FILENAME,
  441. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  442. 0,
  443. Create?CERT_SYSTEM_STORE_CURRENT_USER:CERT_SYSTEM_STORE_CURRENT_USER|CERT_STORE_OPEN_EXISTING_FLAG,
  444. #ifdef UNICODE
  445. CertStore
  446. #else
  447. certStoreW
  448. #endif
  449. );
  450. } else {
  451. // we assume it's a system store
  452. result = g_CertOpenStore (
  453. CERT_STORE_PROV_SYSTEM,
  454. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  455. 0,
  456. Create?CERT_SYSTEM_STORE_CURRENT_USER:CERT_SYSTEM_STORE_CURRENT_USER|CERT_STORE_OPEN_EXISTING_FLAG,
  457. #ifdef UNICODE
  458. CertStore
  459. #else
  460. certStoreW
  461. #endif
  462. );
  463. if (result == NULL) {
  464. // now we try HKLM
  465. result = g_CertOpenStore (
  466. CERT_STORE_PROV_SYSTEM,
  467. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  468. 0,
  469. Create?CERT_SYSTEM_STORE_LOCAL_MACHINE:CERT_SYSTEM_STORE_LOCAL_MACHINE|CERT_STORE_OPEN_EXISTING_FLAG,
  470. #ifdef UNICODE
  471. CertStore
  472. #else
  473. certStoreW
  474. #endif
  475. );
  476. }
  477. }
  478. }
  479. }
  480. __finally {
  481. if (certStoreW) {
  482. FreeConvertedStr (certStoreW);
  483. certStoreW = NULL;
  484. }
  485. }
  486. return result;
  487. }
  488. BOOL
  489. EnumFirstCertificate (
  490. IN OUT PMIG_TYPEOBJECTENUM EnumPtr, CALLER_INITIALIZED
  491. IN MIG_OBJECTSTRINGHANDLE Pattern,
  492. IN UINT MaxLevel
  493. )
  494. {
  495. PCTSTR certStore, certPattern;
  496. PCWSTR certStoreW = NULL;
  497. PCERT_ENUM certEnum = NULL;
  498. BOOL result = FALSE;
  499. if (!IsmCreateObjectStringsFromHandle (
  500. Pattern,
  501. &certStore,
  502. &certPattern
  503. )) {
  504. return FALSE;
  505. }
  506. if (certStore && certPattern) {
  507. __try {
  508. certEnum = (PCERT_ENUM) PmGetMemory (g_CertPool, sizeof (CERT_ENUM));
  509. if (!certEnum) {
  510. __leave;
  511. }
  512. ZeroMemory (certEnum, sizeof (CERT_ENUM));
  513. certEnum->CertStore = PmDuplicateString (g_CertPool, certStore);
  514. certEnum->CertPattern = PmDuplicateString (g_CertPool, certPattern);
  515. EnumPtr->EtmHandle = (LONG_PTR) certEnum;
  516. certEnum->StoreHandle = pOpenCertStore (certStore, FALSE);
  517. if (certEnum->StoreHandle == NULL) {
  518. __leave;
  519. }
  520. result = pGetNextCertFromStore (EnumPtr, certEnum);
  521. }
  522. __finally {
  523. if (certStoreW) {
  524. FreeConvertedStr (certStoreW);
  525. certStoreW = NULL;
  526. }
  527. }
  528. }
  529. IsmDestroyObjectString (certStore);
  530. IsmDestroyObjectString (certPattern);
  531. if (!result) {
  532. AbortCertificateEnum (EnumPtr);
  533. }
  534. return result;
  535. }
  536. BOOL
  537. EnumNextCertificate (
  538. IN OUT PMIG_TYPEOBJECTENUM EnumPtr
  539. )
  540. {
  541. PCERT_ENUM certEnum = NULL;
  542. BOOL result = FALSE;
  543. certEnum = (PCERT_ENUM)(EnumPtr->EtmHandle);
  544. if (!certEnum) {
  545. return FALSE;
  546. }
  547. result = pGetNextCertFromStore (EnumPtr, certEnum);
  548. return result;
  549. }
  550. VOID
  551. AbortCertificateEnum (
  552. IN PMIG_TYPEOBJECTENUM EnumPtr ZEROED
  553. )
  554. {
  555. PCERT_ENUM certEnum;
  556. if (EnumPtr->ObjectName) {
  557. IsmDestroyObjectHandle (EnumPtr->ObjectName);
  558. EnumPtr->ObjectName = NULL;
  559. }
  560. if (EnumPtr->ObjectLeaf) {
  561. IsmReleaseMemory (EnumPtr->ObjectLeaf);
  562. EnumPtr->ObjectLeaf = NULL;
  563. }
  564. if (EnumPtr->NativeObjectName) {
  565. IsmReleaseMemory (EnumPtr->NativeObjectName);
  566. EnumPtr->NativeObjectName = NULL;
  567. }
  568. certEnum = (PCERT_ENUM)(EnumPtr->EtmHandle);
  569. if (certEnum) {
  570. if (certEnum->StoreHandle && g_CertCloseStore) {
  571. g_CertCloseStore (certEnum->StoreHandle, CERT_CLOSE_STORE_FORCE_FLAG);
  572. }
  573. if (certEnum->CertStore) {
  574. PmReleaseMemory (g_CertPool, certEnum->CertStore);
  575. certEnum->CertStore = NULL;
  576. }
  577. if (certEnum->CertPattern) {
  578. PmReleaseMemory (g_CertPool, certEnum->CertPattern);
  579. certEnum->CertPattern = NULL;
  580. }
  581. if (certEnum->CertContext) {
  582. if (g_CertFreeCertificateContext) {
  583. g_CertFreeCertificateContext (certEnum->CertContext);
  584. }
  585. }
  586. PmReleaseMemory (g_CertPool, certEnum);
  587. }
  588. ZeroMemory (EnumPtr, sizeof (MIG_TYPEOBJECTENUM));
  589. }
  590. /*++
  591. The next set of functions implement the ETM entry points to acquire, test,
  592. create and remove certificates.
  593. --*/
  594. BOOL
  595. pDoesPrivateKeyExist (
  596. IN PCCERT_CONTEXT CertContext
  597. )
  598. {
  599. DWORD data = 0;
  600. BOOL result = FALSE;
  601. // do we have the API?
  602. if (!g_CertGetCertificateContextProperty) {
  603. return FALSE;
  604. }
  605. result = g_CertGetCertificateContextProperty (
  606. CertContext,
  607. CERT_KEY_PROV_INFO_PROP_ID,
  608. NULL,
  609. &data
  610. );
  611. return result;
  612. }
  613. BOOL
  614. pIsPrivateKeyExportable (
  615. IN PCCERT_CONTEXT CertContext
  616. )
  617. {
  618. HCRYPTPROV cryptProv = 0;
  619. DWORD keySpec = 0;
  620. HCRYPTKEY keyHandle = 0;
  621. BOOL callerFreeProv = FALSE;
  622. DWORD permissions = 0;
  623. DWORD size = 0;
  624. BOOL result = FALSE;
  625. // do we have the API?
  626. if (!g_CryptAcquireCertificatePrivateKey) {
  627. // we don't have the API, let's assume it is
  628. // exportable.
  629. return TRUE;
  630. }
  631. if (g_CryptAcquireCertificatePrivateKey (
  632. CertContext,
  633. CRYPT_ACQUIRE_USE_PROV_INFO_FLAG | CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
  634. NULL,
  635. &cryptProv,
  636. &keySpec,
  637. &callerFreeProv
  638. )) {
  639. if (CryptGetUserKey (cryptProv, keySpec, &keyHandle)) {
  640. size = sizeof (permissions);
  641. if (CryptGetKeyParam (keyHandle, KP_PERMISSIONS, (PBYTE)&permissions, &size, 0)) {
  642. result = ((permissions & CRYPT_EXPORT) != 0);
  643. }
  644. if (keyHandle != 0) {
  645. CryptDestroyKey(keyHandle);
  646. keyHandle = 0;
  647. }
  648. }
  649. if (callerFreeProv != 0) {
  650. CryptReleaseContext(cryptProv, 0);
  651. cryptProv = 0;
  652. }
  653. }
  654. return result;
  655. }
  656. PCBYTE
  657. pGetCertificateData (
  658. IN PCCERT_CONTEXT CertContext,
  659. IN BOOL ExportPrivateKey,
  660. IN PCWSTR Password,
  661. OUT PDWORD DataSize
  662. )
  663. {
  664. HCERTSTORE memoryStore;
  665. CRYPT_DATA_BLOB dataBlob;
  666. PCBYTE result = NULL;
  667. if (!DataSize) {
  668. return NULL;
  669. }
  670. __try {
  671. // do we have the API?
  672. if (!g_CertOpenStore) {
  673. __leave;
  674. }
  675. // first we create a memory store and put this certificate there
  676. memoryStore = g_CertOpenStore(
  677. CERT_STORE_PROV_MEMORY,
  678. 0,
  679. 0,
  680. 0,
  681. NULL
  682. );
  683. if (memoryStore == NULL) {
  684. __leave;
  685. }
  686. // do we have the API?
  687. if (!g_CertAddCertificateContextToStore) {
  688. __leave;
  689. }
  690. if (!g_CertAddCertificateContextToStore (
  691. memoryStore,
  692. CertContext,
  693. CERT_STORE_ADD_REPLACE_EXISTING,
  694. NULL
  695. )) {
  696. __leave;
  697. }
  698. // now we export the store using PFXExportCertStore
  699. ZeroMemory (&dataBlob, sizeof (CRYPT_DATA_BLOB));
  700. // do we have the API?
  701. if (!g_PFXExportCertStore) {
  702. __leave;
  703. }
  704. // get the needed size
  705. if (!g_PFXExportCertStore (
  706. memoryStore,
  707. &dataBlob,
  708. Password,
  709. ExportPrivateKey?EXPORT_PRIVATE_KEYS:0
  710. )) {
  711. __leave;
  712. }
  713. dataBlob.pbData = PmGetMemory (g_CertPool, dataBlob.cbData);
  714. if (!dataBlob.pbData) {
  715. SetLastError (ERROR_NOT_ENOUGH_MEMORY);
  716. __leave;
  717. }
  718. // now get the actual data
  719. if (!g_PFXExportCertStore (
  720. memoryStore,
  721. &dataBlob,
  722. Password,
  723. ExportPrivateKey?EXPORT_PRIVATE_KEYS:0
  724. )) {
  725. __leave;
  726. }
  727. // now we have the data
  728. *DataSize = dataBlob.cbData;
  729. result = dataBlob.pbData;
  730. }
  731. __finally {
  732. PushError ();
  733. if (memoryStore && g_CertCloseStore) {
  734. g_CertCloseStore (memoryStore, CERT_CLOSE_STORE_FORCE_FLAG);
  735. memoryStore = NULL;
  736. }
  737. if (!result) {
  738. if (dataBlob.pbData) {
  739. PmReleaseMemory (g_CertPool, dataBlob.pbData);
  740. dataBlob.pbData = NULL;
  741. }
  742. }
  743. PopError ();
  744. }
  745. return result;
  746. }
  747. PCCERT_CONTEXT
  748. pGetCertContext (
  749. IN HCERTSTORE StoreHandle,
  750. IN PCTSTR CertName
  751. )
  752. {
  753. PCTSTR certName;
  754. PCCERT_CONTEXT result = NULL;
  755. // do we have the API?
  756. if (!g_CertEnumCertificatesInStore) {
  757. return FALSE;
  758. }
  759. // basically we are going to enumerate the certificates until we find the one
  760. // that we need
  761. result = g_CertEnumCertificatesInStore (StoreHandle, result);
  762. while (result) {
  763. certName = pGetCertName (result);
  764. if (StringIMatch (CertName, certName)) {
  765. PmReleaseMemory (g_CertPool, certName);
  766. break;
  767. }
  768. PmReleaseMemory (g_CertPool, certName);
  769. result = g_CertEnumCertificatesInStore (StoreHandle, result);
  770. }
  771. return result;
  772. }
  773. BOOL
  774. pAcquireCertFromStore (
  775. IN HCERTSTORE StoreHandle,
  776. IN PCTSTR CertName,
  777. OUT PMIG_CONTENT ObjectContent,
  778. IN UINT MemoryContentLimit
  779. )
  780. {
  781. PCCERT_CONTEXT certContext = NULL;
  782. PCTSTR certName;
  783. BOOL exportPrivateKey = FALSE;
  784. DWORD dataSize = 0;
  785. PCBYTE dataBytes = NULL;
  786. BOOL result = FALSE;
  787. certContext = pGetCertContext (StoreHandle, CertName);
  788. if (!certContext) {
  789. return FALSE;
  790. }
  791. // we found it. Let's build the data.
  792. exportPrivateKey = pDoesPrivateKeyExist (certContext) && pIsPrivateKeyExportable (certContext);
  793. dataBytes = pGetCertificateData (certContext, exportPrivateKey, L"USMT", &dataSize);
  794. if (dataBytes) {
  795. // let's build the object content
  796. ObjectContent->MemoryContent.ContentSize = dataSize;
  797. ObjectContent->MemoryContent.ContentBytes = dataBytes;
  798. result = TRUE;
  799. }
  800. if (g_CertFreeCertificateContext) {
  801. g_CertFreeCertificateContext (certContext);
  802. }
  803. return result;
  804. }
  805. BOOL
  806. AcquireCertificate (
  807. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  808. OUT PMIG_CONTENT ObjectContent, CALLER_INITIALIZED
  809. IN MIG_CONTENTTYPE ContentType,
  810. IN UINT MemoryContentLimit
  811. )
  812. {
  813. HCERTSTORE storeHandle = NULL;
  814. PCTSTR certStore = NULL, certName = NULL;
  815. PCCERT_CONTEXT certContext;
  816. BOOL result = FALSE;
  817. if (!ObjectContent) {
  818. return FALSE;
  819. }
  820. if (ContentType == CONTENTTYPE_FILE) {
  821. // nobody should request this as a file
  822. MYASSERT (FALSE);
  823. return FALSE;
  824. }
  825. if (!IsmCreateObjectStringsFromHandle (
  826. ObjectName,
  827. &certStore,
  828. &certName
  829. )) {
  830. return FALSE;
  831. }
  832. if (certStore && certName) {
  833. __try {
  834. storeHandle = pOpenCertStore (certStore, FALSE);
  835. if (!storeHandle) {
  836. __leave;
  837. }
  838. result = pAcquireCertFromStore (storeHandle, certName, ObjectContent, MemoryContentLimit);
  839. }
  840. __finally {
  841. if (storeHandle && g_CertCloseStore) {
  842. g_CertCloseStore (storeHandle, CERT_CLOSE_STORE_FORCE_FLAG);
  843. storeHandle = NULL;
  844. }
  845. }
  846. }
  847. IsmDestroyObjectString (certStore);
  848. IsmDestroyObjectString (certName);
  849. return result;
  850. }
  851. BOOL
  852. ReleaseCertificate (
  853. IN PMIG_CONTENT ObjectContent ZEROED
  854. )
  855. {
  856. if (ObjectContent) {
  857. if (ObjectContent->MemoryContent.ContentBytes) {
  858. PmReleaseMemory (g_CertPool, ObjectContent->MemoryContent.ContentBytes);
  859. }
  860. ZeroMemory (ObjectContent, sizeof (MIG_CONTENT));
  861. }
  862. return TRUE;
  863. }
  864. BOOL
  865. DoesCertificateExist (
  866. IN MIG_OBJECTSTRINGHANDLE ObjectName
  867. )
  868. {
  869. HCERTSTORE storeHandle = NULL;
  870. PCCERT_CONTEXT certContext = NULL;
  871. PCTSTR certStore = NULL, certName = NULL;
  872. BOOL result = FALSE;
  873. if (g_DelayCertOp) {
  874. return FALSE;
  875. }
  876. if (!IsmCreateObjectStringsFromHandle (
  877. ObjectName,
  878. &certStore,
  879. &certName
  880. )) {
  881. return FALSE;
  882. }
  883. if (certStore && certName) {
  884. __try {
  885. storeHandle = pOpenCertStore (certStore, FALSE);
  886. if (!storeHandle) {
  887. __leave;
  888. }
  889. certContext = pGetCertContext (storeHandle, certName);
  890. if (!certContext) {
  891. __leave;
  892. }
  893. result = TRUE;
  894. }
  895. __finally {
  896. if (certContext && g_CertFreeCertificateContext) {
  897. g_CertFreeCertificateContext (certContext);
  898. certContext = NULL;
  899. }
  900. if (storeHandle && g_CertCloseStore) {
  901. g_CertCloseStore (storeHandle, CERT_CLOSE_STORE_FORCE_FLAG);
  902. storeHandle = NULL;
  903. }
  904. }
  905. }
  906. IsmDestroyObjectString (certStore);
  907. IsmDestroyObjectString (certName);
  908. return result;
  909. }
  910. BOOL
  911. RemoveCertificate (
  912. IN MIG_OBJECTSTRINGHANDLE ObjectName
  913. )
  914. {
  915. HCERTSTORE storeHandle = NULL;
  916. PCCERT_CONTEXT certContext;
  917. PCTSTR certStore = NULL, certName = NULL;
  918. BOOL result = FALSE;
  919. if (g_DelayCertOp) {
  920. //
  921. // delay this certificate create because cert apis do not work
  922. // for non-logged on users
  923. //
  924. IsmRecordDelayedOperation (
  925. JRNOP_DELETE,
  926. g_CertType,
  927. ObjectName,
  928. NULL
  929. );
  930. result = TRUE;
  931. } else {
  932. //
  933. // add journal entry, then perform certificate deletion
  934. //
  935. IsmRecordOperation (
  936. JRNOP_DELETE,
  937. g_CertType,
  938. ObjectName
  939. );
  940. if (IsmCreateObjectStringsFromHandle (
  941. ObjectName,
  942. &certStore,
  943. &certName
  944. )) {
  945. if (certStore && certName) {
  946. __try {
  947. storeHandle = pOpenCertStore (certStore, FALSE);
  948. if (!storeHandle) {
  949. __leave;
  950. }
  951. certContext = pGetCertContext (storeHandle, certName);
  952. if (!certContext) {
  953. __leave;
  954. }
  955. if (g_CertDeleteCertificateFromStore &&
  956. g_CertDeleteCertificateFromStore (certContext)
  957. ) {
  958. // certContext is not valid any more
  959. certContext = NULL;
  960. result = TRUE;
  961. }
  962. }
  963. __finally {
  964. if (certContext && g_CertFreeCertificateContext) {
  965. g_CertFreeCertificateContext (certContext);
  966. certContext = NULL;
  967. }
  968. if (storeHandle && g_CertCloseStore) {
  969. g_CertCloseStore (storeHandle, CERT_CLOSE_STORE_FORCE_FLAG);
  970. storeHandle = NULL;
  971. }
  972. }
  973. }
  974. IsmDestroyObjectString (certStore);
  975. IsmDestroyObjectString (certName);
  976. }
  977. }
  978. return result;
  979. }
  980. HCERTSTORE
  981. pBuildStoreFromData (
  982. PCRYPT_DATA_BLOB DataBlob,
  983. PCWSTR Password
  984. )
  985. {
  986. HCERTSTORE result;
  987. // Do we have the API?
  988. if (!g_PFXImportCertStore) {
  989. return NULL;
  990. }
  991. result = g_PFXImportCertStore (
  992. DataBlob,
  993. Password,
  994. CRYPT_EXPORTABLE
  995. );
  996. return result;
  997. }
  998. BOOL
  999. CreateCertificate (
  1000. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  1001. IN PMIG_CONTENT ObjectContent
  1002. )
  1003. {
  1004. CRYPT_DATA_BLOB dataBlob;
  1005. HCERTSTORE srcStoreHandle = NULL;
  1006. HCERTSTORE destStoreHandle = NULL;
  1007. PCCERT_CONTEXT certContext = NULL;
  1008. PCTSTR certStore = NULL, certName = NULL;
  1009. PTSTR certFile = NULL, certFileNode, certFilePtr;
  1010. MIG_OBJECTSTRINGHANDLE certFileHandle, destCertFileHandle;
  1011. BOOL result = FALSE;
  1012. if (g_DelayCertOp) {
  1013. //
  1014. // delay this certificate create because cert apis do not work
  1015. // for non-logged on users
  1016. //
  1017. IsmRecordDelayedOperation (
  1018. JRNOP_CREATE,
  1019. g_CertType,
  1020. ObjectName,
  1021. ObjectContent
  1022. );
  1023. result = TRUE;
  1024. } else {
  1025. //
  1026. // add journal entry, then create the certificate
  1027. //
  1028. IsmRecordOperation (
  1029. JRNOP_CREATE,
  1030. g_CertType,
  1031. ObjectName
  1032. );
  1033. if (ObjectContent && ObjectContent->MemoryContent.ContentSize && ObjectContent->MemoryContent.ContentBytes) {
  1034. if (!IsmCreateObjectStringsFromHandle (
  1035. ObjectName,
  1036. &certStore,
  1037. &certName
  1038. )) {
  1039. return FALSE;
  1040. }
  1041. if (certStore && certName) {
  1042. __try {
  1043. // let's create the store from this data
  1044. dataBlob.cbData = ObjectContent->MemoryContent.ContentSize;
  1045. dataBlob.pbData = (PBYTE)ObjectContent->MemoryContent.ContentBytes;
  1046. srcStoreHandle = pBuildStoreFromData (&dataBlob, L"USMT");
  1047. if (!srcStoreHandle) {
  1048. __leave;
  1049. }
  1050. // now we need to figure out where the destination store is
  1051. // If it's a file we will filter it out and find out where
  1052. // the file is supposed to go.
  1053. if (IsValidFileSpec (certStore)) {
  1054. // looks like a file.
  1055. certFile = PmDuplicateString (g_CertPool, certStore);
  1056. if (certFile) {
  1057. certFilePtr = _tcsrchr (certFile, TEXT('\\'));
  1058. if (certFilePtr) {
  1059. *certFilePtr = 0;
  1060. certFilePtr ++;
  1061. certFileHandle = IsmCreateObjectHandle (certFile, certFilePtr);
  1062. if (certFileHandle) {
  1063. destCertFileHandle = IsmFilterObject (MIG_FILE_TYPE, certFileHandle, NULL, NULL, NULL);
  1064. if (destCertFileHandle) {
  1065. PmReleaseMemory (g_CertPool, certFile);
  1066. certFile = NULL;
  1067. if (IsmCreateObjectStringsFromHandle (destCertFileHandle, &certFileNode, &certFilePtr)) {
  1068. certFile = JoinPaths (certFileNode, certFilePtr);
  1069. IsmDestroyObjectString (certFileNode);
  1070. IsmDestroyObjectString (certFilePtr);
  1071. }
  1072. }
  1073. IsmDestroyObjectHandle (certFileHandle);
  1074. } else {
  1075. PmReleaseMemory (g_CertPool, certFile);
  1076. certFile = NULL;
  1077. }
  1078. } else {
  1079. PmReleaseMemory (g_CertPool, certFile);
  1080. certFile = NULL;
  1081. }
  1082. }
  1083. }
  1084. destStoreHandle = pOpenCertStore (certFile?certFile:certStore, TRUE);
  1085. if (!destStoreHandle) {
  1086. __leave;
  1087. }
  1088. // Do we have the APIs?
  1089. if (g_CertEnumCertificatesInStore && g_CertAddCertificateContextToStore) {
  1090. // now let's enumerate the store and add the certificates into the
  1091. // system store
  1092. certContext = g_CertEnumCertificatesInStore (srcStoreHandle, certContext);
  1093. while (certContext) {
  1094. if (!g_CertAddCertificateContextToStore (
  1095. destStoreHandle,
  1096. certContext,
  1097. CERT_STORE_ADD_REPLACE_EXISTING,
  1098. NULL
  1099. )) {
  1100. __leave;
  1101. }
  1102. certContext = g_CertEnumCertificatesInStore (srcStoreHandle, certContext);
  1103. }
  1104. result = TRUE;
  1105. }
  1106. }
  1107. __finally {
  1108. if (certContext && g_CertFreeCertificateContext) {
  1109. g_CertFreeCertificateContext (certContext);
  1110. certContext = NULL;
  1111. }
  1112. if (srcStoreHandle && g_CertCloseStore) {
  1113. g_CertCloseStore (srcStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG);
  1114. srcStoreHandle = NULL;
  1115. }
  1116. if (destStoreHandle && g_CertCloseStore) {
  1117. g_CertCloseStore (destStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG);
  1118. destStoreHandle = NULL;
  1119. }
  1120. }
  1121. }
  1122. IsmDestroyObjectString (certStore);
  1123. IsmDestroyObjectString (certName);
  1124. }
  1125. }
  1126. return result;
  1127. }
  1128. /*++
  1129. The next group of functions converts a certificate object into a string format,
  1130. suitable for output to an INF file. The reverse conversion is also
  1131. implemented.
  1132. --*/
  1133. PCTSTR
  1134. ConvertCertificateToMultiSz (
  1135. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  1136. IN PMIG_CONTENT ObjectContent
  1137. )
  1138. {
  1139. PCTSTR certStore = NULL, certName = NULL;
  1140. TCHAR tmpStr[3];
  1141. UINT index;
  1142. PTSTR result = NULL;
  1143. if (IsmCreateObjectStringsFromHandle (ObjectName, &certStore, &certName)) {
  1144. g_CertConversionBuff.End = 0;
  1145. GbCopyQuotedString (&g_CertConversionBuff, certStore);
  1146. GbCopyQuotedString (&g_CertConversionBuff, certName);
  1147. if (ObjectContent && (!ObjectContent->ContentInFile) && ObjectContent->MemoryContent.ContentBytes) {
  1148. index = 0;
  1149. while (index < ObjectContent->MemoryContent.ContentSize) {
  1150. wsprintf (tmpStr, TEXT("%02X"), ObjectContent->MemoryContent.ContentBytes [index]);
  1151. GbCopyString (&g_CertConversionBuff, tmpStr);
  1152. index ++;
  1153. }
  1154. GbCopyString (&g_CertConversionBuff, TEXT(""));
  1155. result = IsmGetMemory (g_CertConversionBuff.End);
  1156. CopyMemory (result, g_CertConversionBuff.Buf, g_CertConversionBuff.End);
  1157. }
  1158. }
  1159. return result;
  1160. }
  1161. BOOL
  1162. ConvertMultiSzToCertificate (
  1163. IN PCTSTR ObjectMultiSz,
  1164. OUT MIG_OBJECTSTRINGHANDLE *ObjectName,
  1165. OUT PMIG_CONTENT ObjectContent OPTIONAL CALLER_INITIALIZED
  1166. )
  1167. {
  1168. MULTISZ_ENUM multiSzEnum;
  1169. PCTSTR certStore = NULL;
  1170. PCTSTR certName = NULL;
  1171. DWORD dummy;
  1172. UINT index;
  1173. g_CertConversionBuff.End = 0;
  1174. if (ObjectContent) {
  1175. ZeroMemory (ObjectContent, sizeof (MIG_CONTENT));
  1176. }
  1177. if (EnumFirstMultiSz (&multiSzEnum, ObjectMultiSz)) {
  1178. index = 0;
  1179. do {
  1180. if (index == 0) {
  1181. certStore = multiSzEnum.CurrentString;
  1182. }
  1183. if (index == 1) {
  1184. certName = multiSzEnum.CurrentString;
  1185. }
  1186. if (index >= 2) {
  1187. _stscanf (multiSzEnum.CurrentString, TEXT("%lx"), &dummy);
  1188. *((PBYTE)GbGrow (&g_CertConversionBuff, sizeof (BYTE))) = (BYTE)dummy;
  1189. }
  1190. index ++;
  1191. } while (EnumNextMultiSz (&multiSzEnum));
  1192. }
  1193. if (!certStore) {
  1194. return FALSE;
  1195. }
  1196. if (!certName) {
  1197. return FALSE;
  1198. }
  1199. if (ObjectContent) {
  1200. ObjectContent->ObjectTypeId = g_CertType;
  1201. ObjectContent->ContentInFile = FALSE;
  1202. ObjectContent->MemoryContent.ContentSize = g_CertConversionBuff.End;
  1203. if (ObjectContent->MemoryContent.ContentSize) {
  1204. ObjectContent->MemoryContent.ContentBytes = IsmGetMemory (ObjectContent->MemoryContent.ContentSize);
  1205. CopyMemory (
  1206. (PBYTE)ObjectContent->MemoryContent.ContentBytes,
  1207. g_CertConversionBuff.Buf,
  1208. ObjectContent->MemoryContent.ContentSize
  1209. );
  1210. g_CertConversionBuff.End = 0;
  1211. }
  1212. }
  1213. *ObjectName = IsmCreateObjectHandle (certStore, certName);
  1214. return TRUE;
  1215. }
  1216. PCTSTR
  1217. GetNativeCertificateName (
  1218. IN MIG_OBJECTSTRINGHANDLE ObjectName
  1219. )
  1220. /*++
  1221. Routine Description:
  1222. GetNativeCertificateName converts the standard Cobra object into a more friendly
  1223. format. The Cobra object comes in the form of ^a<node>^b^c<leaf>, where
  1224. <node> is the URL, and <leaf> is the certificate name. The Certificate native name is
  1225. in the format of <CertificateStore>:<CertificateName>.
  1226. Arguments:
  1227. ObjectName - Specifies the encoded object name
  1228. Return Value:
  1229. A string that is equivalent to ObjectName, but is in a friendly format.
  1230. This string must be freed with IsmReleaseMemory.
  1231. --*/
  1232. {
  1233. PCTSTR certStore, certName, tmp;
  1234. PCTSTR result = NULL;
  1235. if (IsmCreateObjectStringsFromHandle (ObjectName, &certStore, &certName)) {
  1236. if (certStore && certName) {
  1237. tmp = JoinTextEx (NULL, certStore, certName, TEXT(":"), 0, NULL);
  1238. if (tmp) {
  1239. result = IsmDuplicateString (tmp);
  1240. FreeText (tmp);
  1241. }
  1242. }
  1243. IsmDestroyObjectString (certStore);
  1244. IsmDestroyObjectString (certName);
  1245. }
  1246. return result;
  1247. }
  1248. PMIG_CONTENT
  1249. ConvertCertificateContentToUnicode (
  1250. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  1251. IN PMIG_CONTENT ObjectContent
  1252. )
  1253. {
  1254. // we don't need to convert the content
  1255. return NULL;
  1256. }
  1257. PMIG_CONTENT
  1258. ConvertCertificateContentToAnsi (
  1259. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  1260. IN PMIG_CONTENT ObjectContent
  1261. )
  1262. {
  1263. // we don't need to convert the content
  1264. return NULL;
  1265. }
  1266. BOOL
  1267. FreeConvertedCertificateContent (
  1268. IN PMIG_CONTENT ObjectContent
  1269. )
  1270. {
  1271. // there is nothing to do
  1272. return TRUE;
  1273. }