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.

7464 lines
167 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: certreq.cpp
  8. //
  9. // Contents: Cert Store API Tests: Create and Add a chain of certificates
  10. // and CRLs to the store.
  11. //
  12. // See Usage() for a list of test options.
  13. //
  14. //
  15. // Functions: main
  16. //
  17. // History: 07-Mar-96 philh created
  18. // 10-Oct-96 jerryk modified
  19. //
  20. //--------------------------------------------------------------------------
  21. #define __DIR__ "certreq"
  22. #define CMSG_SIGNER_ENCODE_INFO_HAS_CMS_FIELDS
  23. #define CMSG_SIGNED_ENCODE_INFO_HAS_CMS_FIELDS
  24. #include <windows.h>
  25. #include <stdlib.h>
  26. #include <locale.h>
  27. #include <io.h>
  28. #include <fcntl.h>
  29. #include <tchar.h>
  30. #include <assert.h>
  31. #include <wincrypt.h>
  32. #include "certlib.h"
  33. #include <certsrv.h>
  34. #include <certca.h>
  35. #include <commdlg.h>
  36. #include <xenroll.h>
  37. #include <common.ver>
  38. #include "resource.h"
  39. #include "csdisp.h"
  40. #include "cscsp.h"
  41. #include "csprop.h"
  42. #include "clibres.h"
  43. #include "csresstr.h"
  44. #define __dwFILE__ __dwFILE_CERTREQ_CERTREQ_CPP__
  45. #define CR_IN_CERT CR_IN_FORMATMASK
  46. #define wprintf myConsolePrintf
  47. #define WM_DOCERTREQDIALOGS WM_USER+0
  48. HINSTANCE g_hInstance;
  49. typedef struct _IDSUSAGE {
  50. DWORD idsVerb;
  51. DWORD idsOptions;
  52. WCHAR const *pwszVerb;
  53. } IDSUSAGE;
  54. #define cmdNONE MAXDWORD
  55. IDSUSAGE g_aidsUsage[] = {
  56. #define cmdSUBMITREQUEST 0
  57. { IDS_USAGE_VERB_DEFAULT, IDS_USAGE_OPTIONS_DEFAULT, L"Submit" },
  58. #define cmdRETRIEVEPENDING 1
  59. { IDS_USAGE_VERB_RETRIEVE, IDS_USAGE_OPTIONS_RETRIEVE, L"Retrieve" },
  60. #define cmdNEWREQUEST 2
  61. { IDS_USAGE_VERB_NEW, IDS_USAGE_OPTIONS_NEW, L"New" },
  62. #define cmdACCEPTRESPONSE 3
  63. { IDS_USAGE_VERB_ACCEPT, IDS_USAGE_OPTIONS_ACCEPT, L"Accept" },
  64. #define cmdQUALIFIEDREQUEST 4
  65. { IDS_USAGE_VERB_POLICY, IDS_USAGE_OPTIONS_POLICY, L"Policy" },
  66. #define cmdSIGNREQUEST 5
  67. { IDS_USAGE_VERB_SIGN, IDS_USAGE_OPTIONS_SIGN, L"Sign" },
  68. };
  69. WCHAR *g_apwszOptionStrings[] = {
  70. L"any", // %1
  71. L"attrib", // %2
  72. L"binary", // %3
  73. L"cert", // %4
  74. L"config", // %5
  75. L"crl", // %6
  76. L"f", // %7
  77. L"q", // %8
  78. L"rpc", // %9
  79. L"v", // %10
  80. L"?", // %11
  81. L"v1", // %12
  82. L"idispatch", // %13
  83. };
  84. DWORD g_dwCommand = cmdNONE;
  85. BOOL g_fAny = FALSE;
  86. BOOL g_fRPC = FALSE;
  87. BOOL g_fIDispatch = FALSE;
  88. BOOL g_fForce = FALSE;
  89. BOOL g_fQuiet = FALSE;
  90. BOOL g_fV1Interface = FALSE;
  91. BOOL g_fFullUsage = FALSE;
  92. BOOL g_fVerbose = FALSE;
  93. BOOL g_idError = 0;
  94. LONG g_dwOutFormat = CV_OUT_BASE64REQUESTHEADER;
  95. DWORD g_dwUIFlag = CC_UIPICKCONFIG;
  96. DWORD g_dwCRLIn = 0;
  97. DWORD g_dwCRLOut = 0;
  98. WCHAR *g_pwszInfErrorString = NULL;
  99. WCHAR *g_pwszErrorString = NULL;
  100. WCHAR *g_pwszUnreferencedSectionNames = NULL;
  101. WCHAR *g_pwszConfig = NULL;
  102. WCHAR *g_pwszCertCN = NULL;
  103. WCHAR const g_wszNewLine[] = L"\n";
  104. CHAR const *g_pszObjIdHash = szOID_OIWSEC_sha1;
  105. #define wszINFSECTION_NEWREQUEST L"NewRequest"
  106. #define wszINFKEY_SUBJECT L"Subject"
  107. #define wszINFKEY_PRIVATEKEYARCHIVE L"PrivateKeyArchive"
  108. #define wszINFKEY_KEYSPEC L"KeySpec"
  109. #define wszINFKEY_KEYLENGTH L"KeyLength"
  110. #define wszINFKEY_RENEWALCERT L"RenewalCert"
  111. #define wszINFKEY_SMIME L"SMIME"
  112. #define wszINFKEY_EXPORTABLE L"Exportable"
  113. #define wszINFKEY_USERPROTECTED L"UserProtected"
  114. #define wszINFKEY_KEYCONTAINER L"KeyContainer"
  115. #define wszINFKEY_HASHALGID L"HashAlgId"
  116. #define wszINFKEY_HASHALGORITHM L"HashAlgorithm"
  117. #define wszINFKEY_MACHINEKEYSET L"MachineKeySet"
  118. #define wszINFKEY_SILENT L"Silent"
  119. #define wszINFKEY_PROVIDERNAME L"ProviderName"
  120. #define wszINFKEY_PROVIDERTYPE L"ProviderType"
  121. #define wszINFKEY_USEEXISTINGKEYSET L"UseExistingKeySet"
  122. #define wszINFKEY_REQUESTERNAME wszPROPREQUESTERNAME
  123. #define wszINFKEY_REQUESTTYPE L"RequestType"
  124. #define wszINFKEY_KEYUSAGE L"KeyUsage"
  125. #define wszINFKEY_ENCIPHERONLY L"EncipherOnly"
  126. #define wszINFVALUE_REQUESTTYPE_PKCS101 L"PKCS10-"
  127. #define wszINFVALUE_REQUESTTYPE_PKCS10 L"PKCS10"
  128. #define wszINFVALUE_REQUESTTYPE_PKCS7 L"PKCS7"
  129. #define wszINFVALUE_REQUESTTYPE_CMC L"CMC"
  130. typedef struct _INFUSAGE
  131. {
  132. WCHAR const *pwszKey;
  133. } INFUSAGE;
  134. WCHAR const *g_apwszInfKeyNewRequest[] = {
  135. wszINFKEY_SUBJECT L" = \"CN=..,OU=...,DC=...\"",
  136. wszINFKEY_PRIVATEKEYARCHIVE L" = TRUE",
  137. wszINFKEY_KEYSPEC L" = 1",
  138. wszINFKEY_KEYLENGTH L" = 1024",
  139. wszINFKEY_RENEWALCERT L" = CertId",
  140. wszINFKEY_SMIME L" = TRUE",
  141. wszINFKEY_EXPORTABLE L" = TRUE",
  142. wszINFKEY_USERPROTECTED L" = TRUE",
  143. wszINFKEY_KEYCONTAINER L" = \"...\"",
  144. #if 0
  145. wszINFKEY_HASHALGID L" = ???",
  146. wszINFKEY_HASHALGORITHM L" = ???",
  147. #endif
  148. wszINFKEY_MACHINEKEYSET L" = TRUE",
  149. wszINFKEY_SILENT L" = TRUE",
  150. wszINFKEY_PROVIDERNAME L" = \"" MS_ENHANCED_PROV_W L"\"",
  151. wszINFKEY_PROVIDERTYPE L" = 1",
  152. wszINFKEY_USEEXISTINGKEYSET L" = TRUE",
  153. wszINFKEY_REQUESTERNAME L" = DOMAIN\\User",
  154. wszINFKEY_REQUESTTYPE L" = " wszINFVALUE_REQUESTTYPE_PKCS10
  155. L" | " wszINFVALUE_REQUESTTYPE_PKCS101
  156. L" | " wszINFVALUE_REQUESTTYPE_PKCS7
  157. L" | " wszINFVALUE_REQUESTTYPE_CMC,
  158. wszINFKEY_KEYUSAGE L" = 0x80",
  159. wszINFKEY_ENCIPHERONLY L" = TRUE",
  160. };
  161. HRESULT
  162. GetCMCTemplateName(
  163. IN BYTE const *pbIn,
  164. IN DWORD cbIn,
  165. IN OUT BOOL *pfCA,
  166. OUT WCHAR **ppwszTemplateName);
  167. // Save eror string: "foo.inf" or "foo.inf(key = "value", "value")"
  168. HRESULT
  169. SetErrorStringInf(
  170. IN WCHAR const *pwszString,
  171. OPTIONAL IN INFVALUES *pInfValues)
  172. {
  173. HRESULT hr;
  174. if (NULL == g_pwszErrorString && NULL != pwszString)
  175. {
  176. DWORD cwc = wcslen(pwszString);
  177. DWORD i;
  178. if (NULL != pInfValues && NULL != pInfValues->pwszKey)
  179. {
  180. cwc += 1 + wcslen(pInfValues->pwszKey) + 2 + 1;
  181. for (i = 0; i < pInfValues->cValues; i++)
  182. {
  183. if (NULL == pInfValues->rgpwszValues[i])
  184. {
  185. break;
  186. }
  187. if (0 != i)
  188. {
  189. cwc++;
  190. }
  191. cwc += 2 + wcslen(pInfValues->rgpwszValues[i]) + 1;
  192. }
  193. }
  194. g_pwszErrorString = (WCHAR *) LocalAlloc(
  195. LMEM_FIXED,
  196. (cwc + 1) * sizeof(WCHAR));
  197. if (NULL == g_pwszErrorString)
  198. {
  199. hr = E_OUTOFMEMORY;
  200. _JumpError(hr, error, "LocalAlloc");
  201. }
  202. wcscpy(g_pwszErrorString, pwszString);
  203. if (NULL != pInfValues && NULL != pInfValues->pwszKey)
  204. {
  205. wcscat(g_pwszErrorString, wszLPAREN);
  206. wcscat(g_pwszErrorString, pInfValues->pwszKey);
  207. wcscat(g_pwszErrorString, L" =");
  208. for (i = 0; i < pInfValues->cValues; i++)
  209. {
  210. if (NULL == pInfValues->rgpwszValues[i])
  211. {
  212. break;
  213. }
  214. if (0 != i)
  215. {
  216. wcscat(g_pwszErrorString, L",");
  217. }
  218. wcscat(g_pwszErrorString, L" \"");
  219. wcscat(g_pwszErrorString, pInfValues->rgpwszValues[i]);
  220. wcscat(g_pwszErrorString, L"\"");
  221. }
  222. wcscat(g_pwszErrorString, wszRPAREN);
  223. }
  224. }
  225. hr = S_OK;
  226. error:
  227. return(hr);
  228. }
  229. VOID
  230. SetErrorString(
  231. IN WCHAR const *pwszString)
  232. {
  233. SetErrorStringInf(pwszString, NULL);
  234. }
  235. HRESULT
  236. DisplayResourceString(
  237. IN DWORD idsMsg,
  238. OPTIONAL IN WCHAR const * const *papwszString,
  239. OPTIONAL OUT WCHAR **ppwszFormatted)
  240. {
  241. HRESULT hr;
  242. WCHAR *pwszRaw = NULL;
  243. WCHAR *pwszFormatted = NULL;
  244. if (NULL != ppwszFormatted)
  245. {
  246. *ppwszFormatted = NULL;
  247. }
  248. hr = myLoadRCString(g_hInstance, idsMsg, &pwszRaw);
  249. _JumpIfError(hr, error, "myLoadRCString");
  250. if (0 == FormatMessage(
  251. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  252. FORMAT_MESSAGE_FROM_STRING |
  253. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  254. (VOID *) pwszRaw,
  255. 0, // dwMessageID
  256. 0, // dwLanguageID
  257. (LPWSTR) &pwszFormatted,
  258. 0,
  259. (va_list *) papwszString))
  260. {
  261. hr = myHLastError();
  262. wprintf(pwszRaw);
  263. _JumpError(hr, error, "FormatMessage");
  264. }
  265. if (NULL != ppwszFormatted)
  266. {
  267. *ppwszFormatted = pwszFormatted;
  268. pwszFormatted = NULL;
  269. }
  270. else
  271. {
  272. wprintf(pwszFormatted);
  273. }
  274. error:
  275. if (NULL != pwszRaw)
  276. {
  277. LocalFree(pwszRaw);
  278. }
  279. if (NULL != pwszFormatted)
  280. {
  281. LocalFree(pwszFormatted);
  282. }
  283. return(hr);
  284. }
  285. DWORD g_aidsOptions[] =
  286. {
  287. IDS_USAGE_OPTION_ANY,
  288. IDS_USAGE_OPTION_ATTRIB,
  289. IDS_USAGE_OPTION_BINARY,
  290. IDS_USAGE_OPTION_CERT,
  291. IDS_USAGE_OPTION_CONFIG,
  292. IDS_USAGE_OPTION_CRL,
  293. IDS_USAGE_OPTION_F,
  294. IDS_USAGE_OPTION_Q,
  295. IDS_USAGE_OPTION_RPC,
  296. IDS_USAGE_OPTION_VERBOSE,
  297. IDS_USAGE_OPTION_QUESTION,
  298. };
  299. DWORD g_aidsOptionsFull[] =
  300. {
  301. IDS_USAGE_OPTION_V1,
  302. IDS_USAGE_OPTION_IDISPATCH,
  303. };
  304. // Option description formatting:
  305. // Resource string contains "%2 <Arg>\nDescription\nMore description\n"
  306. // To format:
  307. // insert " -" in front of the first line and skip the newline,
  308. // insert space to pad out to N-2 columns and "- " before the second line,
  309. // insert space to pad out to N columns before all additional lines.
  310. #define cwcINDENT 28 // ----+
  311. // |
  312. /* v
  313. -Optiom <Arg> - Description\n
  314. More description\n
  315. */
  316. VOID
  317. DisplayOptionList(
  318. IN DWORD cOpt,
  319. IN DWORD *aidsOpt)
  320. {
  321. DWORD i;
  322. for (i = 0; i < cOpt; i++)
  323. {
  324. WCHAR *pwszFormatted = NULL;
  325. WCHAR const *pwszPrefix;
  326. WCHAR *pwsz;
  327. DWORD j;
  328. DWORD iLine;
  329. DWORD cwc0;
  330. DisplayResourceString(aidsOpt[i], g_apwszOptionStrings, &pwszFormatted);
  331. if (NULL == pwszFormatted)
  332. {
  333. continue;
  334. }
  335. pwsz = pwszFormatted;
  336. iLine = 0;
  337. cwc0 = 0;
  338. while (L'\0' != *pwsz)
  339. {
  340. WCHAR const *pwszNewLine = L"\n";
  341. DWORD cwcPad;
  342. j = wcscspn(pwsz, L"\r\n");
  343. switch (iLine)
  344. {
  345. WCHAR wc;
  346. case 0:
  347. cwcPad = 2;
  348. pwszPrefix = L"-";
  349. wc = pwsz[j];
  350. pwsz[j] = L'\0';
  351. cwc0 = cwcPad +
  352. wcslen(pwszPrefix) +
  353. myGetDisplayLength(pwsz);
  354. pwsz[j] = wc;
  355. pwszNewLine = L"";
  356. break;
  357. case 1:
  358. cwcPad = 1;
  359. if (cwcINDENT > 2 + cwc0)
  360. {
  361. cwcPad = cwcINDENT - (2 + cwc0);
  362. }
  363. pwszPrefix = L"- ";
  364. break;
  365. default:
  366. cwcPad = cwcINDENT;
  367. pwszPrefix = L"";
  368. break;
  369. }
  370. wprintf(
  371. L"%*ws%ws%.*ws%ws",
  372. cwcPad,
  373. L"",
  374. pwszPrefix,
  375. j,
  376. pwsz,
  377. pwszNewLine);
  378. pwsz += j;
  379. if (L'\r' == *pwsz)
  380. {
  381. pwsz++;
  382. }
  383. if (L'\n' == *pwsz)
  384. {
  385. pwsz++;
  386. }
  387. iLine++;
  388. }
  389. LocalFree(pwszFormatted);
  390. }
  391. }
  392. VOID
  393. Usage(
  394. IN BOOL fError)
  395. {
  396. IDSUSAGE *pidsUsage;
  397. IDSUSAGE *pidsUsageEnd;
  398. BOOL fShowOptions;
  399. DisplayResourceString(IDS_USAGE_GENERAL, NULL, NULL);
  400. wprintf(L"\n");
  401. switch (g_dwCommand)
  402. {
  403. case cmdSUBMITREQUEST:
  404. case cmdRETRIEVEPENDING:
  405. case cmdNEWREQUEST:
  406. case cmdACCEPTRESPONSE:
  407. case cmdQUALIFIEDREQUEST:
  408. case cmdSIGNREQUEST:
  409. pidsUsage = &g_aidsUsage[g_dwCommand];
  410. pidsUsageEnd = &pidsUsage[1];
  411. fShowOptions = TRUE;
  412. break;
  413. case cmdNONE:
  414. default:
  415. pidsUsage = g_aidsUsage;
  416. pidsUsageEnd = &g_aidsUsage[ARRAYSIZE(g_aidsUsage)];
  417. fShowOptions = g_fVerbose;
  418. break;
  419. }
  420. if (fError)
  421. {
  422. fShowOptions = FALSE;
  423. }
  424. for ( ; pidsUsage < pidsUsageEnd; pidsUsage++)
  425. {
  426. DisplayResourceString(pidsUsage->idsVerb, &pidsUsage->pwszVerb, NULL);
  427. if (fShowOptions)
  428. {
  429. DisplayResourceString(pidsUsage->idsOptions, g_apwszOptionStrings, NULL);
  430. }
  431. wprintf(L"\n");
  432. }
  433. if (fShowOptions)
  434. {
  435. DisplayResourceString(IDS_USAGE_OPTIONS_DESCRIPTION, NULL, NULL);
  436. DisplayOptionList(ARRAYSIZE(g_aidsOptions), g_aidsOptions);
  437. if (g_fFullUsage)
  438. {
  439. DisplayOptionList(ARRAYSIZE(g_aidsOptionsFull), g_aidsOptionsFull);
  440. }
  441. wprintf(L"\n");
  442. DisplayResourceString(IDS_USAGE_DESCRIPTION, g_apwszOptionStrings, NULL);
  443. }
  444. if (!fError)
  445. {
  446. if ((cmdNEWREQUEST == g_dwCommand ||
  447. (cmdNONE == g_dwCommand && g_fVerbose)))
  448. {
  449. DWORD i;
  450. wprintf(L"[%ws]\n", wszINFSECTION_NEWREQUEST);
  451. for (i = 0; i < ARRAYSIZE(g_apwszInfKeyNewRequest); i++)
  452. {
  453. wprintf(L" %ws\n", g_apwszInfKeyNewRequest[i]);
  454. }
  455. }
  456. }
  457. exit(0);
  458. }
  459. VOID
  460. AppendAttributeString(
  461. IN OUT WCHAR *pwszOut,
  462. IN WCHAR const *pwszIn)
  463. {
  464. pwszOut += wcslen(pwszOut);
  465. while (L'\0' != *pwszIn)
  466. {
  467. switch (*pwszIn)
  468. {
  469. case L';':
  470. *pwszOut = L'\n';
  471. break;
  472. case L'\\':
  473. if (L'n' == pwszIn[1])
  474. {
  475. *pwszOut = L'\n';
  476. pwszIn++;
  477. break;
  478. }
  479. if (L'r' == pwszIn[1])
  480. {
  481. *pwszOut = L'\r';
  482. pwszIn++;
  483. break;
  484. }
  485. // else FALLTHROUGH
  486. default:
  487. *pwszOut = *pwszIn;
  488. break;
  489. }
  490. pwszOut++;
  491. pwszIn++;
  492. }
  493. *pwszOut = L'\0';
  494. }
  495. HRESULT
  496. crCombineAttributes(
  497. IN WCHAR const *pwszAttributesAdd,
  498. IN OUT WCHAR **ppwszAttributesExisting)
  499. {
  500. HRESULT hr;
  501. DWORD cwc;
  502. WCHAR *pwszAttributesExisting = *ppwszAttributesExisting;
  503. WCHAR *pwsz;
  504. cwc = wcslen(pwszAttributesAdd) + 1;
  505. if (NULL != pwszAttributesExisting)
  506. {
  507. cwc += wcslen(pwszAttributesExisting) + 1;
  508. }
  509. pwsz = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  510. if (NULL == pwsz)
  511. {
  512. hr = E_OUTOFMEMORY;
  513. _JumpError(hr, error, "LocalAlloc");
  514. }
  515. pwsz[0] = L'\0';
  516. if (NULL != pwszAttributesExisting)
  517. {
  518. AppendAttributeString(pwsz, pwszAttributesExisting);
  519. AppendAttributeString(pwsz, L"\\n");
  520. LocalFree(pwszAttributesExisting);
  521. }
  522. AppendAttributeString(pwsz, pwszAttributesAdd);
  523. *ppwszAttributesExisting = pwsz;
  524. hr = S_OK;
  525. error:
  526. return(hr);
  527. }
  528. VOID
  529. crMissingFileArg()
  530. {
  531. HRESULT hr;
  532. WCHAR *pwszMsg = NULL;
  533. hr = myLoadRCString(g_hInstance, IDS_ERROR_NO_FILENAME, &pwszMsg);
  534. _JumpIfError(hr, error, "myLoadRCString");
  535. CSASSERT(NULL != pwszMsg);
  536. wprintf(pwszMsg);
  537. wprintf(g_wszNewLine);
  538. error:
  539. if (NULL != pwszMsg)
  540. {
  541. LocalFree(pwszMsg);
  542. }
  543. }
  544. HRESULT
  545. crGetOpenFileName(
  546. IN HWND hWndOwner,
  547. IN UINT idsOpenTitle,
  548. IN UINT idsFileFilter,
  549. IN UINT idsFileDefExt,
  550. OUT WCHAR **ppwszOFN)
  551. {
  552. HRESULT hr;
  553. if (g_fQuiet)
  554. {
  555. crMissingFileArg();
  556. Usage(TRUE);
  557. }
  558. // Put up a file dialog to prompt the user for Inf File
  559. // 0 == hr means dialog was cancelled, we cheat because S_OK == 0
  560. hr = myGetOpenFileName(
  561. hWndOwner,
  562. NULL, // hInstance
  563. idsOpenTitle,
  564. idsFileFilter,
  565. idsFileDefExt,
  566. OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY,
  567. NULL, // no default file
  568. ppwszOFN);
  569. _JumpIfError(hr, error, "myGetOpenFileName");
  570. if (NULL == *ppwszOFN)
  571. {
  572. // cancelled:
  573. // see public\sdk\inc\cderr.h for real CommDlgExtendedError errors
  574. hr = myHError(CommDlgExtendedError());
  575. if (S_OK == hr)
  576. {
  577. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  578. }
  579. _JumpError(hr, error, "myGetOpenFileName");
  580. }
  581. hr = S_OK;
  582. error:
  583. return(hr);
  584. }
  585. HRESULT
  586. crOverwriteFileAllowed(
  587. IN HWND hWndOwner,
  588. IN WCHAR const *pwszfnOut)
  589. {
  590. HRESULT hr;
  591. int rc = IDCANCEL;
  592. WCHAR *pwszTitle = NULL;
  593. WCHAR *pwszMessage = NULL;
  594. WCHAR *pwsz = NULL;
  595. if (!g_fForce && myDoesFileExist(pwszfnOut))
  596. {
  597. if (!g_fQuiet)
  598. {
  599. DWORD cwc;
  600. hr = myLoadRCString(g_hInstance, IDS_CERTREQ_TITLE, &pwszTitle);
  601. _JumpIfError(hr, error, "myLoadRCString");
  602. hr = myLoadRCString(g_hInstance, IDS_OVERWRITE_FILE, &pwszMessage);
  603. _JumpIfError(hr, error, "myLoadRCString");
  604. cwc = wcslen(pwszMessage) + 2 + wcslen(pwszfnOut);
  605. pwsz = (WCHAR *) LocalAlloc(LMEM_FIXED, (1 + cwc) * sizeof(WCHAR));
  606. if (NULL == pwsz)
  607. {
  608. hr = E_OUTOFMEMORY;
  609. _JumpError(hr, error, "LocalAlloc");
  610. }
  611. wcscpy(pwsz, pwszMessage);
  612. wcscat(pwsz, L"\r\n");
  613. wcscat(pwsz, pwszfnOut);
  614. rc = MessageBox(
  615. hWndOwner,
  616. pwsz,
  617. pwszTitle,
  618. MB_OKCANCEL |
  619. MB_DEFBUTTON2 |
  620. MB_ICONWARNING |
  621. MB_SETFOREGROUND);
  622. }
  623. if (IDOK != rc)
  624. {
  625. SetErrorString(pwszfnOut);
  626. hr = g_fQuiet?
  627. HRESULT_FROM_WIN32(ERROR_FILE_EXISTS) :
  628. HRESULT_FROM_WIN32(ERROR_CANCELLED);
  629. _JumpErrorStr(hr, error, "File Exists", pwszfnOut);
  630. }
  631. }
  632. hr = S_OK;
  633. error:
  634. if (NULL != pwsz)
  635. {
  636. LocalFree(pwsz);
  637. }
  638. if (NULL != pwszTitle)
  639. {
  640. LocalFree(pwszTitle);
  641. }
  642. if (NULL != pwszMessage)
  643. {
  644. LocalFree(pwszMessage);
  645. }
  646. return(hr);
  647. }
  648. HRESULT
  649. WriteCertificateOrRequest(
  650. IN HWND hWndOwner,
  651. OPTIONAL IN DISPATCHINTERFACE *pdiRequest,
  652. OPTIONAL IN BYTE const *pbOut,
  653. IN DWORD cbOut,
  654. IN DWORD Flags,
  655. IN DWORD idsTitle,
  656. IN DWORD idsFilter,
  657. IN DWORD idsDefExt,
  658. OPTIONAL IN WCHAR const *pwszfnOut)
  659. {
  660. HRESULT hr;
  661. WCHAR *pwszOFN = NULL;
  662. BSTR strCert = NULL;
  663. CHAR *pszCert = NULL;
  664. DWORD decFlags = CRYPT_STRING_BINARY;
  665. BOOL fCheckFileOverwriteOK = TRUE; // careful not to overwrite without prompting user
  666. if (NULL == pwszfnOut)
  667. {
  668. if (g_fQuiet)
  669. {
  670. crMissingFileArg();
  671. Usage(TRUE);
  672. }
  673. // Put up a file dialog to prompt the user for Cert file
  674. // 0 == hr means dialog was cancelled, we cheat because S_OK == 0
  675. hr = myGetSaveFileName(
  676. hWndOwner,
  677. NULL, // hInstance
  678. idsTitle,
  679. idsFilter,
  680. idsDefExt,
  681. OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT,
  682. NULL, // no default file
  683. &pwszOFN);
  684. _JumpIfError(hr, error, "myGetSaveFileName");
  685. fCheckFileOverwriteOK = FALSE; // OFN_OVERWRITEPROMPT should have prompted if necessary
  686. if (NULL == pwszOFN)
  687. {
  688. // cancelled:
  689. // see public\sdk\inc\cderr.h for real CommDlgExtendedError errors
  690. hr = myHError(CommDlgExtendedError());
  691. _JumpError(hr, error, "myGetSaveFileName");
  692. }
  693. pwszfnOut = pwszOFN;
  694. hr = myIsDirWriteable(pwszfnOut, TRUE);
  695. if (S_OK != hr)
  696. {
  697. SetErrorString(pwszfnOut);
  698. _JumpErrorStr(hr, error, "IsDirWriteable", pwszfnOut);
  699. }
  700. }
  701. if (NULL == pbOut)
  702. {
  703. hr = Request_GetCertificate(pdiRequest, Flags, &strCert);
  704. _JumpIfError(hr, error, "Request_GetCertificate");
  705. if (CR_OUT_BINARY == (CR_OUT_ENCODEMASK & Flags))
  706. {
  707. cbOut = SysStringByteLen(strCert);
  708. pbOut = (BYTE const *) strCert;
  709. }
  710. else
  711. {
  712. if (!ConvertWszToSz(&pszCert, strCert, -1))
  713. {
  714. hr = E_OUTOFMEMORY;
  715. _JumpError(hr, error, "ConvertWszToSz(cert)");
  716. }
  717. cbOut = strlen(pszCert);
  718. pbOut = (BYTE const *) pszCert;
  719. }
  720. }
  721. else
  722. {
  723. decFlags = CR_OUT_ENCODEMASK & Flags;
  724. CSASSERT(CSExpr(CR_OUT_BASE64HEADER == CRYPT_STRING_BASE64HEADER));
  725. CSASSERT(CSExpr(CR_OUT_BINARY == CRYPT_STRING_BINARY));
  726. }
  727. if (fCheckFileOverwriteOK)
  728. {
  729. hr = crOverwriteFileAllowed(hWndOwner, pwszfnOut);
  730. _JumpIfError(hr, error, "crOverwriteFileAllowed");
  731. }
  732. hr = EncodeToFileW(
  733. pwszfnOut,
  734. pbOut,
  735. cbOut,
  736. DECF_FORCEOVERWRITE | decFlags);
  737. if (S_OK != hr)
  738. {
  739. SetErrorString(pwszfnOut);
  740. _JumpErrorStr(hr, error, "EncodeToFileW", pwszfnOut);
  741. }
  742. error:
  743. if (NULL != strCert)
  744. {
  745. SysFreeString(strCert);
  746. }
  747. if (NULL != pszCert)
  748. {
  749. LocalFree(pszCert);
  750. }
  751. if (NULL != pwszOFN)
  752. {
  753. LocalFree(pwszOFN);
  754. }
  755. return(hr);
  756. }
  757. HRESULT
  758. GetLong(
  759. WCHAR const *pwszIn,
  760. LONG *pLong)
  761. {
  762. HRESULT hr = E_INVALIDARG;
  763. WCHAR const *pwsz;
  764. LONG l;
  765. pwsz = pwszIn;
  766. if (NULL == pwsz)
  767. {
  768. _JumpError(hr, error, "NULL parm");
  769. }
  770. if (L'\0' == *pwsz)
  771. {
  772. _JumpError(hr, error, "empty string");
  773. }
  774. if (L'0' == *pwsz && (L'x' == pwsz[1] || L'X' == pwsz[1]))
  775. {
  776. l = 0;
  777. pwsz += 2;
  778. for ( ; L'\0' != *pwsz; pwsz++)
  779. {
  780. if (!iswxdigit(*pwsz))
  781. {
  782. _JumpErrorStr(hr, error, "Non-hex digit", pwszIn);
  783. }
  784. if (0xf0000000 & l)
  785. {
  786. _JumpErrorStr(hr, error, "overflow", pwszIn);
  787. }
  788. l <<= 4;
  789. if (iswdigit(*pwsz))
  790. {
  791. l |= *pwsz - L'0';
  792. }
  793. else if (L'A' <= *pwsz && L'F' >= *pwsz)
  794. {
  795. l |= *pwsz - L'A' + 10;
  796. }
  797. else
  798. {
  799. l |= *pwsz - L'a' + 10;
  800. }
  801. }
  802. *pLong = l;
  803. }
  804. else
  805. {
  806. LARGE_INTEGER li;
  807. li.QuadPart = 0;
  808. for ( ; L'\0' != *pwsz; pwsz++)
  809. {
  810. if (!iswdigit(*pwsz))
  811. {
  812. _JumpErrorStr2(hr, error, "Non-decimal digit", pwszIn, hr);
  813. }
  814. li.QuadPart *= 10;
  815. li.QuadPart += *pwsz - L'0';
  816. if (0 != li.HighPart || 0 > (LONG) li.LowPart)
  817. {
  818. _JumpErrorStr2(hr, error, "overflow", pwszIn, hr);
  819. }
  820. }
  821. *pLong = li.LowPart;
  822. }
  823. hr = S_OK;
  824. //wprintf(L"GetLong(%ws) --> %x (%d)\n", pwszIn, *pLong, *pLong);
  825. error:
  826. return(hr);
  827. }
  828. HRESULT
  829. IsSubjectTypeCA(
  830. IN CERT_EXTENSION const *pExt,
  831. OUT BOOL *pfCA)
  832. {
  833. HRESULT hr;
  834. CERT_BASIC_CONSTRAINTS2_INFO Constraints;
  835. DWORD cb;
  836. *pfCA = FALSE;
  837. cb = sizeof(Constraints);
  838. if (!CryptDecodeObject(
  839. X509_ASN_ENCODING,
  840. X509_BASIC_CONSTRAINTS2,
  841. pExt->Value.pbData,
  842. pExt->Value.cbData,
  843. 0,
  844. &Constraints,
  845. &cb))
  846. {
  847. hr = myHLastError();
  848. _JumpError(hr, error, "CryptDecodeObject");
  849. }
  850. if (Constraints.fCA)
  851. {
  852. *pfCA = TRUE;
  853. }
  854. hr = S_OK;
  855. error:
  856. return(hr);
  857. }
  858. HRESULT
  859. GetExtensionsTemplateName(
  860. IN CERT_EXTENSION const *rgExtension,
  861. IN DWORD cExtension,
  862. IN OUT BOOL *pfCA,
  863. IN OUT WCHAR **ppwszTemplateName)
  864. {
  865. HRESULT hr;
  866. CERT_EXTENSION const *pExt;
  867. CERT_EXTENSION const *pExtEnd;
  868. CERT_TEMPLATE_EXT *pTemplate = NULL;
  869. CERT_NAME_VALUE *pName = NULL;
  870. DWORD cb;
  871. pExtEnd = &rgExtension[cExtension];
  872. for (pExt = rgExtension; pExt < pExtEnd; pExt++)
  873. {
  874. if (NULL == *ppwszTemplateName)
  875. {
  876. if (0 == strcmp(pExt->pszObjId, szOID_CERTIFICATE_TEMPLATE))
  877. {
  878. // V2 template info extension
  879. if (!myDecodeObject(
  880. X509_ASN_ENCODING,
  881. X509_CERTIFICATE_TEMPLATE,
  882. pExt->Value.pbData,
  883. pExt->Value.cbData,
  884. CERTLIB_USE_LOCALALLOC,
  885. (VOID **) &pTemplate,
  886. &cb))
  887. {
  888. hr = myHLastError();
  889. _JumpError(hr, error, "Policy:myDecodeObject");
  890. }
  891. if (!myConvertSzToWsz(ppwszTemplateName, pTemplate->pszObjId, -1))
  892. {
  893. hr = E_OUTOFMEMORY;
  894. _JumpError(hr, error, "Policy:myConvertSzToBstr");
  895. }
  896. }
  897. else
  898. if (0 == strcmp(pExt->pszObjId, szOID_ENROLL_CERTTYPE_EXTENSION))
  899. {
  900. // V1 template name extension
  901. if (!myDecodeObject(
  902. X509_ASN_ENCODING,
  903. X509_UNICODE_ANY_STRING,
  904. pExt->Value.pbData,
  905. pExt->Value.cbData,
  906. CERTLIB_USE_LOCALALLOC,
  907. (VOID **) &pName,
  908. &cb))
  909. {
  910. hr = myHLastError();
  911. _JumpError(hr, error, "myDecodeObject");
  912. }
  913. hr = myDupString(
  914. (WCHAR const *) pName->Value.pbData,
  915. ppwszTemplateName);
  916. _JumpIfError(hr, error, "myDupString");
  917. }
  918. }
  919. if (!*pfCA)
  920. {
  921. if (0 == strcmp(pExt->pszObjId, szOID_BASIC_CONSTRAINTS2))
  922. {
  923. hr = IsSubjectTypeCA(pExt, pfCA);
  924. _JumpIfError(hr, error, "IsSubjectTypeCA");
  925. }
  926. }
  927. }
  928. hr = S_OK;
  929. error:
  930. if (NULL != pTemplate)
  931. {
  932. LocalFree(pTemplate);
  933. }
  934. if (NULL != pName)
  935. {
  936. LocalFree(pName);
  937. }
  938. return(hr);
  939. }
  940. HRESULT
  941. GetAttributesTemplateName(
  942. IN CRYPT_ATTRIBUTE const *rgAttrib,
  943. IN DWORD cAttrib,
  944. IN OUT BOOL *pfCA,
  945. IN OUT WCHAR **ppwszTemplateName)
  946. {
  947. HRESULT hr;
  948. CRYPT_ATTRIBUTE const *pAttrib;
  949. CRYPT_ATTRIBUTE const *pAttribEnd;
  950. CRYPT_ATTR_BLOB *pAttrBlob;
  951. CERT_EXTENSIONS *pCertExtensions = NULL;
  952. CRYPT_ENROLLMENT_NAME_VALUE_PAIR *pInfo = NULL;
  953. DWORD cb;
  954. DWORD i;
  955. pAttribEnd = &rgAttrib[cAttrib];
  956. for (pAttrib = rgAttrib; pAttrib < pAttribEnd; pAttrib++)
  957. {
  958. if (0 == strcmp(pAttrib->pszObjId, szOID_CERT_EXTENSIONS) ||
  959. 0 == strcmp(pAttrib->pszObjId, szOID_RSA_certExtensions))
  960. {
  961. if (1 != pAttrib->cValue)
  962. {
  963. hr = E_INVALIDARG;
  964. _JumpError(hr, error, "Attribute Value count != 1");
  965. }
  966. if (NULL != pCertExtensions)
  967. {
  968. LocalFree(pCertExtensions);
  969. pCertExtensions = NULL;
  970. }
  971. pAttrBlob = pAttrib->rgValue;
  972. if (!myDecodeObject(
  973. X509_ASN_ENCODING,
  974. X509_EXTENSIONS,
  975. pAttrBlob->pbData,
  976. pAttrBlob->cbData,
  977. CERTLIB_USE_LOCALALLOC,
  978. (VOID **) &pCertExtensions,
  979. &cb))
  980. {
  981. hr = myHLastError();
  982. _JumpError(hr, error, "myDecodeObject");
  983. }
  984. hr = GetExtensionsTemplateName(
  985. pCertExtensions->rgExtension,
  986. pCertExtensions->cExtension,
  987. pfCA,
  988. ppwszTemplateName);
  989. _JumpIfError(hr, error, "GetExtensionsTemplateName");
  990. }
  991. else
  992. if (0 == strcmp(pAttrib->pszObjId, szOID_ENROLLMENT_NAME_VALUE_PAIR))
  993. {
  994. for (i = 0; i < pAttrib->cValue; i++)
  995. {
  996. if (NULL != pInfo)
  997. {
  998. LocalFree(pInfo);
  999. pInfo = NULL;
  1000. }
  1001. pAttrBlob = &pAttrib->rgValue[i];
  1002. if (!myDecodeNameValuePair(
  1003. X509_ASN_ENCODING,
  1004. pAttrBlob->pbData,
  1005. pAttrBlob->cbData,
  1006. CERTLIB_USE_LOCALALLOC,
  1007. &pInfo,
  1008. &cb))
  1009. {
  1010. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1011. _JumpError(hr, error, "myDecodeNameValuePair");
  1012. // if the attribute name & value are both non-empty ...
  1013. }
  1014. if (0 == LSTRCMPIS(pInfo->pwszName, wszPROPCERTTEMPLATE))
  1015. {
  1016. if (NULL == *ppwszTemplateName)
  1017. {
  1018. hr = myDupString(pInfo->pwszValue, ppwszTemplateName);
  1019. _JumpIfError(hr, error, "myDupString");
  1020. }
  1021. }
  1022. }
  1023. }
  1024. }
  1025. hr = S_OK;
  1026. error:
  1027. if (NULL != pCertExtensions)
  1028. {
  1029. LocalFree(pCertExtensions);
  1030. }
  1031. if (NULL != pInfo)
  1032. {
  1033. LocalFree(pInfo);
  1034. }
  1035. return(hr);
  1036. }
  1037. HRESULT
  1038. GetPKCS10TemplateName(
  1039. IN BYTE const *pbIn,
  1040. IN DWORD cbIn,
  1041. IN OUT BOOL *pfCA,
  1042. IN OUT WCHAR **ppwszTemplateName)
  1043. {
  1044. HRESULT hr;
  1045. CERT_REQUEST_INFO *pRequestInfo = NULL;
  1046. DWORD cb;
  1047. if (!myDecodeObject(
  1048. X509_ASN_ENCODING,
  1049. X509_CERT_REQUEST_TO_BE_SIGNED,
  1050. pbIn,
  1051. cbIn,
  1052. CERTLIB_USE_LOCALALLOC,
  1053. (VOID **) &pRequestInfo,
  1054. &cb))
  1055. {
  1056. hr = myHLastError();
  1057. _JumpError(hr, error, "myDecodeObject");
  1058. }
  1059. hr = GetAttributesTemplateName(
  1060. pRequestInfo->rgAttribute,
  1061. pRequestInfo->cAttribute,
  1062. pfCA,
  1063. ppwszTemplateName);
  1064. _JumpIfError(hr, error, "GetAttributesTemplateName");
  1065. error:
  1066. if (NULL != pRequestInfo)
  1067. {
  1068. LocalFree(pRequestInfo);
  1069. }
  1070. return(hr);
  1071. }
  1072. HRESULT
  1073. GetCMCRequestTemplateName(
  1074. IN BYTE const *pbIn,
  1075. IN DWORD cbIn,
  1076. IN OUT BOOL *pfCA,
  1077. IN OUT WCHAR **ppwszTemplateName)
  1078. {
  1079. HRESULT hr;
  1080. BYTE *pbContents = NULL;
  1081. DWORD cbContents;
  1082. char *pszInnerContentObjId = NULL;
  1083. hr = myDecodePKCS7(
  1084. pbIn,
  1085. cbIn,
  1086. &pbContents,
  1087. &cbContents,
  1088. NULL, // pdwMsgType
  1089. &pszInnerContentObjId,
  1090. NULL, // pcSigner
  1091. NULL, // pcRecipient
  1092. NULL, // phStore
  1093. NULL); // phMsg
  1094. _JumpIfError(hr, error, "myDecodePKCS7");
  1095. if (NULL != pszInnerContentObjId &&
  1096. 0 == strcmp(pszInnerContentObjId, szOID_CT_PKI_DATA))
  1097. {
  1098. hr = GetCMCTemplateName(
  1099. pbContents,
  1100. cbContents,
  1101. pfCA,
  1102. ppwszTemplateName);
  1103. _JumpIfError(hr, error, "GetCMCTemplateName");
  1104. }
  1105. hr = S_OK;
  1106. error:
  1107. if (NULL != pszInnerContentObjId)
  1108. {
  1109. LocalFree(pszInnerContentObjId);
  1110. }
  1111. if (NULL != pbContents)
  1112. {
  1113. LocalFree(pbContents);
  1114. }
  1115. return(hr);
  1116. }
  1117. HRESULT
  1118. GetCMCExtensionsTemplateName(
  1119. IN BYTE const *pbIn,
  1120. IN DWORD cbIn,
  1121. IN OUT BOOL *pfCA,
  1122. IN OUT WCHAR **ppwszTemplateName)
  1123. {
  1124. HRESULT hr;
  1125. CMC_ADD_EXTENSIONS_INFO *pcmcExt = NULL;
  1126. DWORD cb;
  1127. *ppwszTemplateName = NULL;
  1128. // Decode CMC_ADD_EXTENSIONS_INFO from Attribute Blob
  1129. if (!myDecodeObject(
  1130. X509_ASN_ENCODING,
  1131. CMC_ADD_EXTENSIONS,
  1132. pbIn,
  1133. cbIn,
  1134. CERTLIB_USE_LOCALALLOC,
  1135. (VOID **) &pcmcExt,
  1136. &cb))
  1137. {
  1138. hr = myHLastError();
  1139. _JumpError(hr, error, "myDecodeObject");
  1140. }
  1141. hr = GetExtensionsTemplateName(
  1142. pcmcExt->rgExtension,
  1143. pcmcExt->cExtension,
  1144. pfCA,
  1145. ppwszTemplateName);
  1146. _JumpIfError(hr, error, "GetExtensionsTemplateName");
  1147. error:
  1148. if (NULL != pcmcExt)
  1149. {
  1150. LocalFree(pcmcExt);
  1151. }
  1152. return(hr);
  1153. }
  1154. HRESULT
  1155. GetCMCAttributesTemplateName(
  1156. IN BYTE const *pbIn,
  1157. IN DWORD cbIn,
  1158. IN OUT BOOL *pfCA,
  1159. IN OUT WCHAR **ppwszTemplateName)
  1160. {
  1161. HRESULT hr;
  1162. CMC_ADD_ATTRIBUTES_INFO *pcmcAttrib = NULL;
  1163. DWORD cb;
  1164. // Decode CMC_ADD_ATTRIBUTES_INFO from Attribute Blob
  1165. if (!myDecodeObject(
  1166. X509_ASN_ENCODING,
  1167. CMC_ADD_ATTRIBUTES,
  1168. pbIn,
  1169. cbIn,
  1170. CERTLIB_USE_LOCALALLOC,
  1171. (VOID **) &pcmcAttrib,
  1172. &cb))
  1173. {
  1174. hr = myHLastError();
  1175. _JumpError(hr, error, "myDecodeObject");
  1176. }
  1177. hr = GetAttributesTemplateName(
  1178. pcmcAttrib->rgAttribute,
  1179. pcmcAttrib->cAttribute,
  1180. pfCA,
  1181. ppwszTemplateName);
  1182. _JumpIfError(hr, error, "GetAttributesTemplateName");
  1183. error:
  1184. if (NULL != pcmcAttrib)
  1185. {
  1186. LocalFree(pcmcAttrib);
  1187. }
  1188. return(hr);
  1189. }
  1190. HRESULT
  1191. GetRequestAttributesTemplateName(
  1192. IN WCHAR const *pwszAttributes,
  1193. IN BOOL fRegInfo,
  1194. IN OUT WCHAR **ppwszTemplateName)
  1195. {
  1196. HRESULT hr;
  1197. WCHAR *pwszDup = NULL;
  1198. WCHAR *pwszBuf;
  1199. WCHAR const *pwszName;
  1200. WCHAR const *pwszValue;
  1201. WCHAR *pwszNameAlloc = NULL;
  1202. WCHAR *pwszValueAlloc = NULL;
  1203. if (NULL == pwszAttributes)
  1204. {
  1205. hr = S_OK;
  1206. goto error; // silently ignore empty string
  1207. }
  1208. hr = myDupString(pwszAttributes, &pwszDup);
  1209. _JumpIfError(hr, error, "myDupString");
  1210. pwszBuf = pwszDup;
  1211. for (;;)
  1212. {
  1213. hr = myParseNextAttribute(&pwszBuf, fRegInfo, &pwszName, &pwszValue);
  1214. if (S_FALSE == hr)
  1215. {
  1216. break;
  1217. }
  1218. _JumpIfError(hr, error, "myParseNextAttribute");
  1219. if (fRegInfo)
  1220. {
  1221. if (NULL != pwszNameAlloc)
  1222. {
  1223. LocalFree(pwszNameAlloc);
  1224. pwszNameAlloc = NULL;
  1225. }
  1226. if (NULL != pwszValueAlloc)
  1227. {
  1228. LocalFree(pwszValueAlloc);
  1229. pwszValueAlloc = NULL;
  1230. }
  1231. hr = myUncanonicalizeURLParm(pwszName, &pwszNameAlloc);
  1232. _JumpIfError(hr, error, "myUncanonicalizeURLParm");
  1233. hr = myUncanonicalizeURLParm(pwszValue, &pwszValueAlloc);
  1234. _JumpIfError(hr, error, "myUncanonicalizeURLParm");
  1235. pwszName = pwszNameAlloc;
  1236. pwszValue = pwszValueAlloc;
  1237. }
  1238. if (0 == LSTRCMPIS(pwszName, wszPROPCERTTEMPLATE))
  1239. {
  1240. if (NULL == *ppwszTemplateName)
  1241. {
  1242. hr = myDupString(pwszValue, ppwszTemplateName);
  1243. _JumpIfError(hr, error, "myDupString");
  1244. }
  1245. }
  1246. }
  1247. hr = S_OK;
  1248. error:
  1249. if (NULL != pwszNameAlloc)
  1250. {
  1251. LocalFree(pwszNameAlloc);
  1252. }
  1253. if (NULL != pwszValueAlloc)
  1254. {
  1255. LocalFree(pwszValueAlloc);
  1256. }
  1257. if (NULL != pwszDup)
  1258. {
  1259. LocalFree(pwszDup);
  1260. }
  1261. return(hr);
  1262. }
  1263. HRESULT
  1264. GetCMCRegInfoTemplateName(
  1265. IN BYTE const *pbIn,
  1266. IN DWORD cbIn,
  1267. OUT WCHAR **ppwszTemplateName)
  1268. {
  1269. HRESULT hr;
  1270. WCHAR *pwszRA = NULL;
  1271. hr = myDecodeCMCRegInfo(pbIn, cbIn, &pwszRA);
  1272. _JumpIfError(hr, error, "myDecodeCMCRegInfo");
  1273. hr = GetRequestAttributesTemplateName(pwszRA, TRUE, ppwszTemplateName);
  1274. _JumpIfError(hr, error, "GetRequestAttributesTemplateName");
  1275. error:
  1276. if (NULL != pwszRA)
  1277. {
  1278. LocalFree(pwszRA);
  1279. }
  1280. return(hr);
  1281. }
  1282. HRESULT
  1283. GetTaggedAttributeTemplateName(
  1284. IN CMC_TAGGED_ATTRIBUTE const *pTaggedAttribute,
  1285. IN OUT BOOL *pfCA,
  1286. IN OUT WCHAR **ppwszTemplateName)
  1287. {
  1288. HRESULT hr;
  1289. DWORD i;
  1290. CRYPT_ATTRIBUTE const *pAttribute = &pTaggedAttribute->Attribute;
  1291. for (i = 0; i < pAttribute->cValue; i++)
  1292. {
  1293. if (0 == strcmp(szOID_CMC_ADD_EXTENSIONS, pAttribute->pszObjId))
  1294. {
  1295. hr = GetCMCExtensionsTemplateName(
  1296. pAttribute->rgValue[i].pbData,
  1297. pAttribute->rgValue[i].cbData,
  1298. pfCA,
  1299. ppwszTemplateName);
  1300. _JumpIfError(hr, error, "GetCMCExtensionsTemplateName");
  1301. }
  1302. else
  1303. if (0 == strcmp(szOID_CMC_ADD_ATTRIBUTES, pAttribute->pszObjId))
  1304. {
  1305. hr = GetCMCAttributesTemplateName(
  1306. pAttribute->rgValue[i].pbData,
  1307. pAttribute->rgValue[i].cbData,
  1308. pfCA,
  1309. ppwszTemplateName);
  1310. _JumpIfError(hr, error, "GetCMCAttributesTemplateName");
  1311. }
  1312. else
  1313. if (0 == strcmp(szOID_CMC_REG_INFO, pAttribute->pszObjId))
  1314. {
  1315. hr = GetCMCRegInfoTemplateName(
  1316. pAttribute->rgValue[i].pbData,
  1317. pAttribute->rgValue[i].cbData,
  1318. ppwszTemplateName);
  1319. _JumpIfError(hr, error, "GetCMCRegInfoTemplateName");
  1320. }
  1321. }
  1322. hr = S_OK;
  1323. error:
  1324. return(hr);
  1325. }
  1326. // Just find the first template indicator available, and return it.
  1327. HRESULT
  1328. GetCMCTemplateName(
  1329. IN BYTE const *pbIn,
  1330. IN DWORD cbIn,
  1331. IN OUT BOOL *pfCA,
  1332. IN OUT WCHAR **ppwszTemplateName)
  1333. {
  1334. HRESULT hr;
  1335. DWORD cb;
  1336. CMC_DATA_INFO *pcmcData = NULL;
  1337. DWORD i;
  1338. if (!myDecodeObject(
  1339. X509_ASN_ENCODING,
  1340. CMC_DATA,
  1341. pbIn,
  1342. cbIn,
  1343. CERTLIB_USE_LOCALALLOC,
  1344. (VOID **) &pcmcData,
  1345. &cb))
  1346. {
  1347. hr = myHLastError();
  1348. _JumpError(hr, error, "myDecodeObject");
  1349. }
  1350. // Process extensions and attributes
  1351. for (i = 0; i < pcmcData->cTaggedAttribute; i++)
  1352. {
  1353. hr = GetTaggedAttributeTemplateName(
  1354. &pcmcData->rgTaggedAttribute[i],
  1355. pfCA,
  1356. ppwszTemplateName);
  1357. _JumpIfError(hr, error, "pkcsSetTaggedAttributes");
  1358. }
  1359. // Process nested CMC messages
  1360. if (0 != pcmcData->cTaggedContentInfo)
  1361. {
  1362. CMC_TAGGED_CONTENT_INFO const *pTaggedContentInfo;
  1363. // Recurse on the nested CMC message
  1364. // Only handle one request at a time for now.
  1365. pTaggedContentInfo = &pcmcData->rgTaggedContentInfo[0];
  1366. hr = GetCMCRequestTemplateName(
  1367. pTaggedContentInfo->EncodedContentInfo.pbData,
  1368. pTaggedContentInfo->EncodedContentInfo.cbData,
  1369. pfCA,
  1370. ppwszTemplateName);
  1371. _JumpIfError(hr, error, "GetCMCRequestTemplateName");
  1372. }
  1373. // Process nested PKCS10 requests
  1374. if (0 != pcmcData->cTaggedRequest)
  1375. {
  1376. CMC_TAGGED_REQUEST const *pTaggedRequest;
  1377. CMC_TAGGED_CERT_REQUEST const *pTaggedCertRequest;
  1378. // Only handle one request at a time for now.
  1379. pTaggedRequest = &pcmcData->rgTaggedRequest[0];
  1380. // The request must be a PKCS10 request
  1381. if (CMC_TAGGED_CERT_REQUEST_CHOICE ==
  1382. pTaggedRequest->dwTaggedRequestChoice)
  1383. {
  1384. pTaggedCertRequest = pTaggedRequest->pTaggedCertRequest;
  1385. hr = GetPKCS10TemplateName(
  1386. pTaggedCertRequest->SignedCertRequest.pbData,
  1387. pTaggedCertRequest->SignedCertRequest.cbData,
  1388. pfCA,
  1389. ppwszTemplateName);
  1390. _JumpIfError(hr, error, "GetPKCS10TemplateName");
  1391. }
  1392. }
  1393. hr = S_OK;
  1394. error:
  1395. if (NULL != pcmcData)
  1396. {
  1397. LocalFree(pcmcData);
  1398. }
  1399. return(hr);
  1400. }
  1401. HRESULT
  1402. CheckRequestType(
  1403. IN WCHAR const *pwszfnReq,
  1404. OUT BYTE **ppbReq,
  1405. OUT DWORD *pcbReq,
  1406. OUT LONG *pFlags,
  1407. OUT BOOL *pfSigned,
  1408. OPTIONAL OUT BOOL *pfCA,
  1409. OPTIONAL OUT WCHAR **ppwszTemplateName)
  1410. {
  1411. HRESULT hr;
  1412. BYTE *pbReq = NULL;
  1413. DWORD cbReq;
  1414. BYTE *pbContents = NULL;
  1415. DWORD cbContents;
  1416. DWORD cb;
  1417. LONG EncodingType;
  1418. LONG RequestType;
  1419. BYTE *pbDecoded = NULL;
  1420. char *pszInnerContentObjId = NULL;
  1421. CERT_CONTEXT const *pcc = NULL;
  1422. CERT_SIGNED_CONTENT_INFO *pcsci = NULL;
  1423. DWORD cbcsci;
  1424. DWORD cSigner;
  1425. DWORD cRecipient;
  1426. BOOL fCAT;
  1427. WCHAR *pwszTemplateNameT = NULL;
  1428. *ppbReq = NULL;
  1429. *pcbReq = NULL;
  1430. *pFlags = 0;
  1431. *pfSigned = FALSE;
  1432. if (NULL == pfCA)
  1433. {
  1434. pfCA = &fCAT;
  1435. }
  1436. *pfCA = FALSE;
  1437. if (NULL == ppwszTemplateName)
  1438. {
  1439. ppwszTemplateName = &pwszTemplateNameT;
  1440. }
  1441. *ppwszTemplateName = NULL;
  1442. EncodingType = CR_IN_BASE64HEADER;
  1443. hr = DecodeFileW(pwszfnReq, &pbReq, &cbReq, CRYPT_STRING_BASE64HEADER);
  1444. if (S_OK != hr)
  1445. {
  1446. //_PrintError(hr, "DecodeFileW(CRYPT_STRING_BASE64HEADER)");
  1447. CSASSERT(NULL == pbReq);
  1448. EncodingType = CR_IN_BASE64;
  1449. hr = DecodeFileW(pwszfnReq, &pbReq, &cbReq, CRYPT_STRING_BASE64);
  1450. if (S_OK != hr)
  1451. {
  1452. //_PrintError(hr, "DecodeFileW(CRYPT_STRING_BASE64)");
  1453. CSASSERT(NULL == pbReq);
  1454. EncodingType = CR_IN_BINARY;
  1455. hr = DecodeFileW(pwszfnReq, &pbReq, &cbReq, CRYPT_STRING_BINARY);
  1456. if (S_OK != hr)
  1457. {
  1458. SetErrorString(pwszfnReq);
  1459. _JumpErrorStr(hr, error, "DecodeFileW", pwszfnReq);
  1460. }
  1461. }
  1462. }
  1463. CSASSERT(NULL != pbReq);
  1464. RequestType = CR_IN_PKCS10;
  1465. if (!myDecodeObject(
  1466. X509_ASN_ENCODING,
  1467. X509_CERT_REQUEST_TO_BE_SIGNED,
  1468. pbReq,
  1469. cbReq,
  1470. CERTLIB_USE_LOCALALLOC,
  1471. (VOID **) &pbDecoded,
  1472. &cb))
  1473. {
  1474. //_PrintError(myHLastError(), "myDecodeObject(PKCS10)");
  1475. CSASSERT(NULL == pbDecoded);
  1476. RequestType = CR_IN_CERT;
  1477. if (!myDecodeObject(
  1478. X509_ASN_ENCODING,
  1479. X509_CERT_TO_BE_SIGNED,
  1480. pbReq,
  1481. cbReq,
  1482. CERTLIB_USE_LOCALALLOC,
  1483. (VOID **) &pbDecoded,
  1484. &cb))
  1485. {
  1486. //_PrintError(myHLastError(), "myDecodeObject(Cert)");
  1487. CSASSERT(NULL == pbDecoded);
  1488. RequestType = CR_IN_KEYGEN;
  1489. if (!myDecodeKeyGenRequest(
  1490. pbReq,
  1491. cbReq,
  1492. CERTLIB_USE_LOCALALLOC,
  1493. (CERT_KEYGEN_REQUEST_INFO **) &pbDecoded,
  1494. &cb))
  1495. {
  1496. //_PrintError(myHLastError(), "myDecodeKeyGenRequest");
  1497. CSASSERT(NULL == pbDecoded);
  1498. RequestType = CR_IN_PKCS7; // PKCS 7 renewal request?
  1499. hr = myDecodePKCS7(
  1500. pbReq,
  1501. cbReq,
  1502. &pbContents,
  1503. &cbContents,
  1504. NULL, // pdwMsgType
  1505. &pszInnerContentObjId,
  1506. &cSigner,
  1507. &cRecipient,
  1508. NULL, // phStore
  1509. NULL); // phMsg
  1510. _JumpIfError(hr, error, "myDecodePKCS7");
  1511. if (NULL != pszInnerContentObjId &&
  1512. 0 == strcmp(pszInnerContentObjId, szOID_CT_PKI_DATA))
  1513. {
  1514. RequestType = CR_IN_CMC;
  1515. hr = GetCMCTemplateName(
  1516. pbContents,
  1517. cbContents,
  1518. pfCA,
  1519. ppwszTemplateName);
  1520. _JumpIfError(hr, error, "GetCMCTemplateName");
  1521. DBGPRINT((
  1522. DBG_SS_CERTREQ,
  1523. "TemplateName = %ws\n",
  1524. *ppwszTemplateName));
  1525. }
  1526. if (0 < cSigner)
  1527. {
  1528. *pfSigned = TRUE;
  1529. }
  1530. }
  1531. }
  1532. }
  1533. if (CR_IN_CERT == RequestType ||
  1534. CR_IN_PKCS10 == RequestType ||
  1535. CR_IN_KEYGEN == RequestType)
  1536. {
  1537. if (CR_IN_CERT == RequestType)
  1538. {
  1539. pcc = CertCreateCertificateContext(
  1540. X509_ASN_ENCODING,
  1541. pbReq,
  1542. cbReq);
  1543. if (NULL == pcc)
  1544. {
  1545. hr = myHLastError();
  1546. _JumpError(hr, error, "CertCreateCertificateContext");
  1547. }
  1548. hr = GetExtensionsTemplateName(
  1549. pcc->pCertInfo->rgExtension,
  1550. pcc->pCertInfo->cExtension,
  1551. pfCA,
  1552. ppwszTemplateName);
  1553. _JumpIfError(hr, error, "GetExtensionsTemplateName");
  1554. }
  1555. else if (CR_IN_PKCS10 == RequestType)
  1556. {
  1557. hr = GetPKCS10TemplateName(pbReq, cbReq, pfCA, ppwszTemplateName);
  1558. _JumpIfError(hr, error, "GetPKCS10TemplateName");
  1559. }
  1560. if (!myDecodeObject(
  1561. X509_ASN_ENCODING,
  1562. X509_CERT,
  1563. pbReq,
  1564. cbReq,
  1565. CERTLIB_USE_LOCALALLOC,
  1566. (VOID **) &pcsci,
  1567. &cbcsci))
  1568. {
  1569. hr = myHLastError();
  1570. _PrintError2(hr, "myDecodeObject", CRYPT_E_ASN1_BADTAG);
  1571. }
  1572. else
  1573. {
  1574. *pfSigned = TRUE; // has a signature
  1575. }
  1576. }
  1577. *ppbReq = pbReq;
  1578. pbReq = NULL;
  1579. *pcbReq = cbReq;
  1580. *pFlags = EncodingType | RequestType;
  1581. hr = S_OK;
  1582. error:
  1583. if (NULL != pwszTemplateNameT)
  1584. {
  1585. LocalFree(pwszTemplateNameT);
  1586. }
  1587. if (NULL != pcc)
  1588. {
  1589. CertFreeCertificateContext(pcc);
  1590. }
  1591. if (NULL != pcsci)
  1592. {
  1593. LocalFree(pcsci);
  1594. }
  1595. if (NULL != pszInnerContentObjId)
  1596. {
  1597. LocalFree(pszInnerContentObjId);
  1598. }
  1599. if (NULL != pbDecoded)
  1600. {
  1601. LocalFree(pbDecoded);
  1602. }
  1603. if (NULL != pbContents)
  1604. {
  1605. LocalFree(pbContents);
  1606. }
  1607. if (NULL != pbReq)
  1608. {
  1609. LocalFree(pbReq);
  1610. }
  1611. return(hr);
  1612. }
  1613. WCHAR *
  1614. wszDisposition(
  1615. DWORD disposition)
  1616. {
  1617. HRESULT hr;
  1618. UINT iRsc = 0;
  1619. WCHAR *pwszDisposition = NULL;
  1620. switch (disposition)
  1621. {
  1622. case CR_DISP_INCOMPLETE:
  1623. iRsc = IDS_DISPOSITION_INCOMPLETE;
  1624. break;
  1625. case CR_DISP_ERROR:
  1626. iRsc = IDS_DISPOSITION_ERROR;
  1627. break;
  1628. case CR_DISP_DENIED:
  1629. iRsc = IDS_DISPOSITION_DENIED;
  1630. break;
  1631. case CR_DISP_ISSUED:
  1632. iRsc = IDS_DISPOSITION_ISSUED;
  1633. break;
  1634. case CR_DISP_ISSUED_OUT_OF_BAND:
  1635. iRsc = IDS_DISPOSITION_ISSUED_OOB;
  1636. break;
  1637. case CR_DISP_UNDER_SUBMISSION:
  1638. iRsc = IDS_DISPOSITION_UNDER_SUBMISSION;
  1639. break;
  1640. case CR_DISP_REVOKED:
  1641. iRsc = IDS_DISPOSITION_REVOKED;
  1642. break;
  1643. default:
  1644. iRsc = IDS_DISPOSITION_UNKNOWN;
  1645. break;
  1646. }
  1647. hr = myLoadRCString(g_hInstance, iRsc, &pwszDisposition);
  1648. _PrintIfError(hr, "myLoadRCString");
  1649. return(pwszDisposition);
  1650. }
  1651. VOID
  1652. DumpProperty(
  1653. IN DISPATCHINTERFACE *pdiRequest,
  1654. IN LONG PropId,
  1655. IN WCHAR const *pwszPropId,
  1656. IN LONG PropIndex,
  1657. IN LONG PropType,
  1658. OPTIONAL OUT LONG *pCount)
  1659. {
  1660. HRESULT hr;
  1661. LONG Flags;
  1662. VOID *pvOut;
  1663. BSTR str = NULL;
  1664. LONG val;
  1665. DATE date;
  1666. WCHAR wszInfo[128];
  1667. if (NULL != pCount)
  1668. {
  1669. *pCount = 0;
  1670. }
  1671. Flags = CV_OUT_BINARY;
  1672. val = 0;
  1673. date = 0.0;
  1674. pvOut = NULL;
  1675. switch (PropType)
  1676. {
  1677. case PROPTYPE_BINARY:
  1678. Flags = CV_OUT_BASE64HEADER;
  1679. pvOut = &str;
  1680. break;
  1681. case PROPTYPE_STRING:
  1682. pvOut = &str;
  1683. break;
  1684. case PROPTYPE_DATE:
  1685. pvOut = &date;
  1686. break;
  1687. case PROPTYPE_LONG:
  1688. pvOut = &val;
  1689. break;
  1690. }
  1691. wsprintf(wszInfo, L"%ws[%u] %u", pwszPropId, PropIndex, PropType);
  1692. hr = Request2_GetFullResponseProperty(
  1693. pdiRequest,
  1694. PropId,
  1695. PropIndex,
  1696. PropType,
  1697. Flags,
  1698. pvOut);
  1699. if (CERTSRV_E_PROPERTY_EMPTY == hr)
  1700. {
  1701. wprintf(L"%ws: CERTSRV_E_PROPERTY_EMPTY\n", wszInfo);
  1702. }
  1703. _JumpIfErrorStr2(
  1704. hr,
  1705. error,
  1706. "Request2_GetFullResponseProperty",
  1707. wszInfo,
  1708. CERTSRV_E_PROPERTY_EMPTY);
  1709. wprintf(L"%ws:", wszInfo);
  1710. switch (PropType)
  1711. {
  1712. case PROPTYPE_BINARY:
  1713. wprintf(L"\n%ws\n", str);
  1714. break;
  1715. case PROPTYPE_STRING:
  1716. wprintf(L" \"%ws\"\n", str);
  1717. break;
  1718. case PROPTYPE_DATE:
  1719. wprintf(L" %f\n", date);
  1720. break;
  1721. case PROPTYPE_LONG:
  1722. wprintf(L" 0x%x(%u)\n", val, val);
  1723. if (NULL != pCount)
  1724. {
  1725. *pCount = val;
  1726. }
  1727. break;
  1728. }
  1729. error:
  1730. if (NULL != str)
  1731. {
  1732. SysFreeString(str);
  1733. }
  1734. }
  1735. VOID
  1736. DumpIndexedProperty(
  1737. IN DISPATCHINTERFACE *pdiRequest,
  1738. IN LONG PropId,
  1739. IN WCHAR const *pwszPropId,
  1740. IN LONG PropType,
  1741. LONG Count)
  1742. {
  1743. LONG PropIndex;
  1744. for (PropIndex = 0; PropIndex < Count; PropIndex++)
  1745. {
  1746. DumpProperty(pdiRequest, PropId, pwszPropId, PropIndex, PropType, NULL);
  1747. }
  1748. }
  1749. typedef struct _FRPROP
  1750. {
  1751. LONG PropId;
  1752. WCHAR *pwszPropId;
  1753. LONG PropType;
  1754. } FRPROP;
  1755. #define _PROPARG(pt) (pt), L#pt
  1756. FRPROP s_afrp[] =
  1757. {
  1758. { _PROPARG(FR_PROP_BODYPARTSTRING), PROPTYPE_STRING },
  1759. { _PROPARG(FR_PROP_STATUS), PROPTYPE_LONG },
  1760. { _PROPARG(FR_PROP_STATUSSTRING), PROPTYPE_STRING },
  1761. { _PROPARG(FR_PROP_OTHERINFOCHOICE), PROPTYPE_LONG },
  1762. { _PROPARG(FR_PROP_FAILINFO), PROPTYPE_LONG },
  1763. { _PROPARG(FR_PROP_PENDINFOTOKEN), PROPTYPE_BINARY },
  1764. { _PROPARG(FR_PROP_PENDINFOTIME), PROPTYPE_DATE },
  1765. { _PROPARG(FR_PROP_ISSUEDCERTIFICATEHASH), PROPTYPE_BINARY },
  1766. { _PROPARG(FR_PROP_ENCRYPTEDKEYHASH), PROPTYPE_BINARY },
  1767. { _PROPARG(FR_PROP_ISSUEDCERTIFICATE), PROPTYPE_BINARY },
  1768. { _PROPARG(FR_PROP_ISSUEDCERTIFICATECHAIN), PROPTYPE_BINARY },
  1769. { _PROPARG(FR_PROP_ISSUEDCERTIFICATECRLCHAIN), PROPTYPE_BINARY },
  1770. };
  1771. VOID
  1772. DumpFullResponseProperties(
  1773. IN DISPATCHINTERFACE *pdiRequest)
  1774. {
  1775. LONG cResponse = 0;
  1776. DWORD i;
  1777. DumpProperty(
  1778. pdiRequest,
  1779. _PROPARG(FR_PROP_FULLRESPONSE),
  1780. 0,
  1781. PROPTYPE_BINARY,
  1782. NULL);
  1783. DumpProperty(
  1784. pdiRequest,
  1785. _PROPARG(FR_PROP_FULLRESPONSENOPKCS7),
  1786. 0,
  1787. PROPTYPE_BINARY,
  1788. NULL);
  1789. DumpProperty(
  1790. pdiRequest,
  1791. _PROPARG(FR_PROP_STATUSINFOCOUNT),
  1792. 0,
  1793. PROPTYPE_LONG,
  1794. &cResponse);
  1795. for (i = 0; i < ARRAYSIZE(s_afrp); i++)
  1796. {
  1797. DumpIndexedProperty(
  1798. pdiRequest,
  1799. s_afrp[i].PropId,
  1800. s_afrp[i].pwszPropId,
  1801. s_afrp[i].PropType,
  1802. cResponse);
  1803. }
  1804. }
  1805. HRESULT
  1806. SaveFullResponse(
  1807. IN HWND hWndOwner,
  1808. IN DISPATCHINTERFACE *pdiRequest,
  1809. IN WCHAR const *pwszfnFullResponse)
  1810. {
  1811. HRESULT hr;
  1812. BSTR strFullResponse = NULL;
  1813. hr = Request2_GetFullResponseProperty(
  1814. pdiRequest,
  1815. FR_PROP_FULLRESPONSENOPKCS7,
  1816. 0, // PropIndex
  1817. PROPTYPE_BINARY,
  1818. CV_OUT_BINARY,
  1819. &strFullResponse);
  1820. if (CERTSRV_E_PROPERTY_EMPTY != hr)
  1821. {
  1822. _JumpIfError(hr, error, "Request2_GetFullResponseProperty");
  1823. }
  1824. if (S_OK == hr)
  1825. {
  1826. hr = WriteCertificateOrRequest(
  1827. hWndOwner,
  1828. pdiRequest,
  1829. (BYTE const *) strFullResponse,
  1830. SysStringByteLen(strFullResponse),
  1831. g_dwOutFormat,
  1832. IDS_RESPONSE_OUTFILE_TITLE,
  1833. IDS_RESPONSE_FILE_FILTER,
  1834. IDS_RESPONSE_FILE_DEFEXT,
  1835. pwszfnFullResponse);
  1836. _JumpIfError(hr, error, "WriteCertificateOrRequest");
  1837. }
  1838. hr = S_OK;
  1839. goto error;
  1840. error:
  1841. if (NULL != strFullResponse)
  1842. {
  1843. SysFreeString(strFullResponse);
  1844. }
  1845. return(hr);
  1846. }
  1847. HRESULT
  1848. CallServerAndStoreCert(
  1849. IN HWND hWndOwner,
  1850. IN WCHAR const *pwszConfig,
  1851. IN DWORD RequestId,
  1852. OPTIONAL IN WCHAR const *pwszSerialNumber,
  1853. OPTIONAL IN WCHAR const *pwszAttributes,
  1854. OPTIONAL IN WCHAR const *pwszfnReq,
  1855. OPTIONAL IN WCHAR const *pwszfnCert,
  1856. OPTIONAL IN WCHAR const *pwszfnCertChain,
  1857. OPTIONAL IN WCHAR const *pwszfnFullResponse)
  1858. {
  1859. HRESULT hr;
  1860. HRESULT hr2;
  1861. BYTE *pbReq = NULL;
  1862. DWORD cbReq;
  1863. LONG dwFlags;
  1864. BOOL fSigned;
  1865. BSTR strRequest = NULL;
  1866. DISPATCHINTERFACE diRequest;
  1867. BOOL fMustRelease = FALSE;
  1868. BSTR strMessage = NULL;
  1869. WCHAR const *pwszMessage;
  1870. CERTSERVERENROLL csEnroll;
  1871. CERTSERVERENROLL *pcsEnroll = NULL;
  1872. WCHAR *pwszServer = NULL;
  1873. WCHAR *pwszAuthority = NULL;
  1874. WCHAR awchr[cwcHRESULTSTRING];
  1875. char const *pszMethod;
  1876. WCHAR *pwszMsg = NULL;
  1877. WCHAR *pwszDispMsg = NULL;
  1878. WCHAR *pwszConfigPlusSerial = NULL;
  1879. BOOL fV1 = g_fV1Interface;
  1880. // If submitting a new request:
  1881. cbReq = 0;
  1882. if (NULL != pwszfnReq)
  1883. {
  1884. // Read the request from a file, convert it to binary, and return
  1885. // dwFlags to indicate the orignal encoding and the detected format.
  1886. hr = CheckRequestType(
  1887. pwszfnReq,
  1888. &pbReq,
  1889. &cbReq,
  1890. &dwFlags,
  1891. &fSigned,
  1892. NULL, // pfCA
  1893. NULL); // ppwszTemplateName
  1894. _JumpIfError(hr, error, "CheckRequestType");
  1895. if (!fSigned || CR_IN_CERT == (CR_IN_FORMATMASK & dwFlags))
  1896. {
  1897. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1898. SetErrorString(pwszfnReq);
  1899. _JumpError(hr, error, "not a signed request");
  1900. }
  1901. }
  1902. pszMethod = "";
  1903. if (1 < g_fRPC)
  1904. {
  1905. hr = mySplitConfigString(pwszConfig, &pwszServer, &pwszAuthority);
  1906. _JumpIfError(hr, error, "mySplitConfigString");
  1907. if (NULL != pwszfnReq)
  1908. {
  1909. // Since CertServerSubmitRequest can only handle binary requests,
  1910. // pass the request in binary form, and set dwFlags to so indicate.
  1911. dwFlags = CR_IN_BINARY | (~CR_IN_ENCODEMASK & dwFlags);
  1912. pszMethod = "CertServerSubmitRequest";
  1913. hr = CertServerSubmitRequest(
  1914. dwFlags | g_dwCRLIn,
  1915. pbReq,
  1916. cbReq,
  1917. pwszAttributes,
  1918. pwszServer,
  1919. pwszAuthority,
  1920. &pcsEnroll);
  1921. _JumpIfError(hr, error, "CertServerSubmitRequest");
  1922. }
  1923. else
  1924. {
  1925. pszMethod = "CertServerRetrievePending";
  1926. hr = CertServerRetrievePending(
  1927. RequestId,
  1928. pwszSerialNumber,
  1929. pwszServer,
  1930. pwszAuthority,
  1931. &pcsEnroll);
  1932. _JumpIfError(hr, error, "CertServerRetrievePending");
  1933. }
  1934. CSASSERT(NULL != pcsEnroll);
  1935. pwszMessage = pcsEnroll->pwszDispositionMessage;
  1936. }
  1937. else
  1938. {
  1939. ZeroMemory(&csEnroll, sizeof(csEnroll));
  1940. hr = Request_Init(g_fIDispatch, &diRequest);
  1941. if (S_OK != hr)
  1942. {
  1943. _PrintError(hr, "Request_Init");
  1944. if (E_ACCESSDENIED == hr) // try for a clearer error message
  1945. {
  1946. hr = CO_E_REMOTE_COMMUNICATION_FAILURE;
  1947. }
  1948. _JumpError(hr, error, "Request_Init");
  1949. }
  1950. fMustRelease = TRUE;
  1951. if (NULL != pwszfnReq)
  1952. {
  1953. assert(NULL != pbReq && 0 != cbReq);
  1954. // We could always pass the binary ASN.1 encoded request, since
  1955. // we've already decoded it above, but in the interest of fully
  1956. // exercising the ICertRequest interface, we choose to submit the
  1957. // request in its original form.
  1958. if (CR_IN_BINARY == (CR_IN_ENCODEMASK & dwFlags))
  1959. {
  1960. // Convert the binary ASN.1 blob into a BSTR blob.
  1961. if (!ConvertWszToBstr(&strRequest, (WCHAR const *) pbReq, cbReq))
  1962. {
  1963. if (S_OK == myLoadRCString(
  1964. g_hInstance,
  1965. IDS_ERROR_STRCONVERSION,
  1966. &pwszMsg))
  1967. {
  1968. CSASSERT(NULL != pwszMsg);
  1969. wprintf(pwszMsg);
  1970. wprintf(g_wszNewLine);
  1971. }
  1972. hr = E_OUTOFMEMORY;
  1973. _JumpError(hr, error, "ConvertWszToBstr");
  1974. }
  1975. }
  1976. else // !CR_IN_BINARY
  1977. {
  1978. // Since ICertRequest::Submit can handle any encoding type,
  1979. // re-read the ansi base64 request from the file without
  1980. // decoding it to binary, then convert the ansi base64 text
  1981. // into a Unicode base64 text BSTR.
  1982. // Free the request's binary image first.
  1983. LocalFree(pbReq);
  1984. pbReq = NULL;
  1985. hr = DecodeFileW(pwszfnReq, &pbReq, &cbReq, CRYPT_STRING_BINARY);
  1986. if (S_OK != hr)
  1987. {
  1988. if (S_OK == myLoadRCString(
  1989. g_hInstance,
  1990. IDS_FORMATSTR_DECODE_ERR,
  1991. &pwszMsg))
  1992. {
  1993. CSASSERT(NULL != pwszMsg);
  1994. wprintf(pwszMsg, myHResultToString(awchr, hr));
  1995. wprintf(g_wszNewLine);
  1996. }
  1997. goto error;
  1998. }
  1999. if (!ConvertSzToBstr(&strRequest, (CHAR const *) pbReq, cbReq))
  2000. {
  2001. if (S_OK == myLoadRCString(
  2002. g_hInstance,
  2003. IDS_ERROR_STRCONVERSION,
  2004. &pwszMsg))
  2005. {
  2006. CSASSERT(NULL != pwszMsg);
  2007. wprintf(pwszMsg);
  2008. }
  2009. hr = E_OUTOFMEMORY;
  2010. _JumpError(hr, error, "ConvertSzToBstr");
  2011. }
  2012. }
  2013. pszMethod = "ICertRequest::Submit";
  2014. if (g_fRPC)
  2015. {
  2016. pszMethod = "ICertRequest::Submit+RPC";
  2017. dwFlags |= CR_IN_RPC;
  2018. }
  2019. if (g_fAny)
  2020. {
  2021. dwFlags = CR_IN_ENCODEANY |
  2022. CR_IN_FORMATANY |
  2023. (~(CR_IN_ENCODEMASK | CR_IN_FORMATMASK) & dwFlags);
  2024. }
  2025. hr = Request_Submit(
  2026. &diRequest,
  2027. dwFlags | g_dwCRLIn,
  2028. strRequest,
  2029. SysStringByteLen(strRequest),
  2030. pwszAttributes,
  2031. pwszConfig,
  2032. (LONG *) &csEnroll.Disposition);
  2033. }
  2034. else
  2035. {
  2036. if (!fV1)
  2037. {
  2038. pszMethod = "ICertRequest2::GetIssuedCertificate";
  2039. hr = Request2_GetIssuedCertificate(
  2040. &diRequest,
  2041. pwszConfig,
  2042. RequestId,
  2043. pwszSerialNumber,
  2044. (LONG *) &csEnroll.Disposition);
  2045. if (E_NOTIMPL == hr)
  2046. {
  2047. fV1 = TRUE;
  2048. }
  2049. }
  2050. if (fV1)
  2051. {
  2052. if (NULL != pwszSerialNumber)
  2053. {
  2054. CSASSERT(0 == RequestId);
  2055. pwszConfigPlusSerial = (WCHAR *) LocalAlloc(
  2056. LMEM_FIXED,
  2057. (wcslen(pwszConfig) +
  2058. 1 +
  2059. wcslen(pwszSerialNumber) +
  2060. 1) * sizeof(WCHAR));
  2061. if (NULL == pwszConfigPlusSerial)
  2062. {
  2063. hr = E_OUTOFMEMORY;
  2064. _JumpError(hr, error, "LocalAlloc");
  2065. }
  2066. wcscpy(pwszConfigPlusSerial, pwszConfig);
  2067. wcscat(pwszConfigPlusSerial, L"\\");
  2068. wcscat(pwszConfigPlusSerial, pwszSerialNumber);
  2069. pwszConfig = pwszConfigPlusSerial;
  2070. }
  2071. pszMethod = "ICertRequest::RetrievePending";
  2072. hr = Request_RetrievePending(
  2073. &diRequest,
  2074. RequestId,
  2075. pwszConfig,
  2076. (LONG *) &csEnroll.Disposition);
  2077. }
  2078. }
  2079. hr2 = Request_GetLastStatus(&diRequest, &csEnroll.hrLastStatus);
  2080. if (S_OK != hr2)
  2081. {
  2082. _PrintError(hr2, "Request_GetLastStatus");
  2083. if (S_OK == hr)
  2084. {
  2085. hr = hr2;
  2086. }
  2087. _JumpError(hr, error, "Request_GetLastStatus");
  2088. }
  2089. if (S_OK != hr)
  2090. {
  2091. _PrintError(hr, pszMethod);
  2092. if (E_ACCESSDENIED == hr) // try for a clearer error message
  2093. {
  2094. hr = CO_E_REMOTE_COMMUNICATION_FAILURE;
  2095. }
  2096. _JumpError(hr, error, pszMethod);
  2097. }
  2098. if (fMustRelease && !fV1)
  2099. {
  2100. if (g_fVerbose)
  2101. {
  2102. DumpFullResponseProperties(&diRequest);
  2103. }
  2104. if (NULL != pwszfnFullResponse)
  2105. {
  2106. hr = SaveFullResponse(
  2107. hWndOwner,
  2108. &diRequest,
  2109. pwszfnFullResponse);
  2110. _JumpIfError(hr, error, "SaveFullResponse");
  2111. }
  2112. }
  2113. hr = Request_GetDispositionMessage(&diRequest, &strMessage);
  2114. _JumpIfError(hr, error, "Request_GetDispositionMessage");
  2115. hr = Request_GetRequestId(&diRequest, (LONG *) &csEnroll.RequestId);
  2116. _JumpIfError(hr, error, "Request_GetRequestId");
  2117. pcsEnroll = &csEnroll;
  2118. pwszMessage = strMessage;
  2119. }
  2120. CSASSERT(NULL != pcsEnroll);
  2121. if (NULL == pwszMessage)
  2122. {
  2123. pwszMessage = L"";
  2124. }
  2125. if (0 != pcsEnroll->RequestId)
  2126. {
  2127. if (S_OK == myLoadRCString(
  2128. g_hInstance,
  2129. IDS_FORMATSTR_REQUESTID,
  2130. &pwszMsg))
  2131. {
  2132. CSASSERT(NULL != pwszMsg);
  2133. wprintf(pwszMsg, pcsEnroll->RequestId);
  2134. wprintf(g_wszNewLine);
  2135. LocalFree(pwszMsg);
  2136. pwszMsg = NULL;
  2137. }
  2138. }
  2139. if (CR_DISP_UNDER_SUBMISSION == pcsEnroll->Disposition)
  2140. {
  2141. if (S_OK == myLoadRCString(
  2142. g_hInstance,
  2143. IDS_FORMATSTR_CERTPENDING,
  2144. &pwszMsg))
  2145. {
  2146. CSASSERT(NULL != pwszMsg);
  2147. wprintf(
  2148. pwszMsg,
  2149. pwszMessage,
  2150. pcsEnroll->hrLastStatus);
  2151. wprintf(g_wszNewLine);
  2152. }
  2153. }
  2154. else if (CR_DISP_ISSUED == pcsEnroll->Disposition ||
  2155. CR_DISP_REVOKED == pcsEnroll->Disposition)
  2156. {
  2157. pwszDispMsg = wszDisposition(pcsEnroll->Disposition);
  2158. DBGPRINT((
  2159. DBG_SS_CERTREQ,
  2160. "%hs(%ws) --> %ws\n",
  2161. pszMethod,
  2162. NULL != pwszDispMsg ? pwszDispMsg : L"",
  2163. pwszMessage));
  2164. if (S_OK == myLoadRCString(
  2165. g_hInstance,
  2166. IDS_FORMATSTR_CERTRETRIEVED,
  2167. &pwszMsg))
  2168. {
  2169. wprintf(
  2170. pwszMsg,
  2171. NULL != pwszDispMsg ? pwszDispMsg : L"",
  2172. pwszMessage);
  2173. wprintf(g_wszNewLine);
  2174. }
  2175. hr = WriteCertificateOrRequest(
  2176. hWndOwner,
  2177. &diRequest,
  2178. pcsEnroll->pbCert,
  2179. pcsEnroll->cbCert,
  2180. g_dwOutFormat,
  2181. IDS_CERT_OUTFILE_TITLE,
  2182. IDS_CERT_FILE_FILTER,
  2183. IDS_CERT_FILE_DEFEXT,
  2184. pwszfnCert);
  2185. _JumpIfError(hr, error, "WriteCertificateOrRequest");
  2186. if (NULL != pwszfnCertChain)
  2187. {
  2188. hr = WriteCertificateOrRequest(
  2189. hWndOwner,
  2190. &diRequest,
  2191. pcsEnroll->pbCertChain,
  2192. pcsEnroll->cbCertChain,
  2193. CR_OUT_CHAIN | g_dwCRLOut | g_dwOutFormat,
  2194. 0,
  2195. 0,
  2196. 0,
  2197. pwszfnCertChain);
  2198. _JumpIfError(hr, error, "WriteCertificateOrRequest(chain)");
  2199. }
  2200. }
  2201. else
  2202. {
  2203. WCHAR const *pwszError = NULL;
  2204. if (S_OK != pcsEnroll->hrLastStatus)
  2205. {
  2206. pwszError = myGetErrorMessageText(pcsEnroll->hrLastStatus, TRUE);
  2207. }
  2208. SetErrorString(pwszMessage);
  2209. if (S_OK == myLoadRCString(
  2210. g_hInstance,
  2211. IDS_FORMATSTR_CERTNOTISSUED,
  2212. &pwszMsg))
  2213. {
  2214. pwszDispMsg = wszDisposition(pcsEnroll->Disposition);
  2215. wprintf(
  2216. pwszMsg,
  2217. NULL != pwszDispMsg ? pwszDispMsg : L"",
  2218. pwszMessage);
  2219. if (NULL != pwszError && NULL == wcsstr(pwszMessage, pwszError))
  2220. {
  2221. wprintf(L" %ws", pwszError);
  2222. }
  2223. wprintf(g_wszNewLine);
  2224. }
  2225. if (NULL != pwszError)
  2226. {
  2227. LocalFree(const_cast<WCHAR *>(pwszError));
  2228. }
  2229. hr = pcsEnroll->hrLastStatus;
  2230. _PrintIfError(hr, "Denied(LastStatus)");
  2231. goto error;
  2232. }
  2233. error:
  2234. if (NULL != pwszMsg)
  2235. {
  2236. LocalFree(pwszMsg);
  2237. }
  2238. if (NULL != pwszDispMsg)
  2239. {
  2240. LocalFree(pwszDispMsg);
  2241. }
  2242. if (NULL != pwszConfigPlusSerial)
  2243. {
  2244. LocalFree(pwszConfigPlusSerial);
  2245. }
  2246. if (NULL != pwszServer)
  2247. {
  2248. LocalFree(pwszServer);
  2249. }
  2250. if (NULL != pwszAuthority)
  2251. {
  2252. LocalFree(pwszAuthority);
  2253. }
  2254. if (NULL != pcsEnroll && &csEnroll != pcsEnroll)
  2255. {
  2256. CertServerFreeMemory(pcsEnroll);
  2257. }
  2258. if (NULL != strMessage)
  2259. {
  2260. SysFreeString(strMessage);
  2261. }
  2262. if (fMustRelease)
  2263. {
  2264. Request_Release(&diRequest);
  2265. }
  2266. if (NULL != strRequest)
  2267. {
  2268. SysFreeString(strRequest);
  2269. }
  2270. if (NULL != pbReq)
  2271. {
  2272. LocalFree(pbReq);
  2273. }
  2274. return(hr);
  2275. }
  2276. HRESULT
  2277. crGetConfig(
  2278. IN OUT BSTR *pstrConfig)
  2279. {
  2280. HRESULT hr;
  2281. WCHAR awchr[cwcHRESULTSTRING];
  2282. hr = ConfigGetConfig(g_fIDispatch, g_dwUIFlag, pstrConfig);
  2283. if (S_OK != hr)
  2284. {
  2285. WCHAR *pwszMsg = NULL;
  2286. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
  2287. {
  2288. g_idError = IDS_NOMORE_CAS;
  2289. }
  2290. if (HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr)
  2291. {
  2292. if (S_OK == myLoadRCString(
  2293. g_hInstance,
  2294. IDS_FORMATSTR_ERRCONFIG,
  2295. &pwszMsg))
  2296. {
  2297. CSASSERT(NULL != pwszMsg);
  2298. wprintf(
  2299. pwszMsg,
  2300. myHResultToString(awchr, hr));
  2301. wprintf(g_wszNewLine);
  2302. LocalFree(pwszMsg);
  2303. }
  2304. }
  2305. goto error;
  2306. }
  2307. hr = S_OK;
  2308. error:
  2309. return(hr);
  2310. }
  2311. HRESULT
  2312. SubmitRequest(
  2313. IN HWND hWndOwner,
  2314. IN LONG RequestId,
  2315. OPTIONAL IN WCHAR const *pwszSerialNumber,
  2316. OPTIONAL IN WCHAR const *pwszAttributes,
  2317. IN WCHAR const *pwszfnReq,
  2318. OPTIONAL IN WCHAR const *pwszfnCert,
  2319. OPTIONAL IN WCHAR const *pwszfnCertChain,
  2320. OPTIONAL IN WCHAR const *pwszfnFullResponse)
  2321. {
  2322. HRESULT hr;
  2323. BOOL fCoInit = FALSE;
  2324. WCHAR *pwszConfig;
  2325. BSTR strConfig = NULL;
  2326. hr = CoInitialize(NULL);
  2327. if (S_OK != hr && S_FALSE != hr)
  2328. {
  2329. _JumpError(hr, error, "CoInitialize");
  2330. }
  2331. fCoInit = TRUE;
  2332. pwszConfig = g_pwszConfig;
  2333. if (NULL == pwszConfig)
  2334. {
  2335. hr = crGetConfig(&strConfig);
  2336. _JumpIfError(hr, error, "crGetConfig");
  2337. pwszConfig = strConfig;
  2338. }
  2339. // If submitting a new request:
  2340. hr = CallServerAndStoreCert(
  2341. hWndOwner,
  2342. pwszConfig,
  2343. RequestId,
  2344. pwszSerialNumber,
  2345. pwszAttributes,
  2346. pwszfnReq,
  2347. pwszfnCert,
  2348. pwszfnCertChain,
  2349. pwszfnFullResponse);
  2350. _JumpIfError(hr, error, "CallServerAndStoreCert");
  2351. error:
  2352. if (NULL != strConfig)
  2353. {
  2354. SysFreeString(strConfig);
  2355. }
  2356. if (fCoInit)
  2357. {
  2358. CoUninitialize();
  2359. }
  2360. return(hr);
  2361. }
  2362. FNMYINFGETEXTENSION *g_apfnGetExtension[] = {
  2363. myInfGetPolicyConstraintsExtension,
  2364. myInfGetPolicyMappingExtension,
  2365. myInfGetPolicyStatementExtension,
  2366. myInfGetApplicationPolicyConstraintsExtension,
  2367. myInfGetApplicationPolicyMappingExtension,
  2368. myInfGetApplicationPolicyStatementExtension,
  2369. myInfGetNameConstraintsExtension,
  2370. myInfGetEnhancedKeyUsageExtension,
  2371. myInfGetBasicConstraints2CAExtension,
  2372. myInfGetCrossCertDistributionPointsExtension,
  2373. };
  2374. #define CINFEXT ARRAYSIZE(g_apfnGetExtension)
  2375. HRESULT
  2376. DumpRequestAttributeBlobs(
  2377. IN DWORD cAttribute,
  2378. IN CRYPT_ATTR_BLOB const *paAttribute)
  2379. {
  2380. HRESULT hr;
  2381. DWORD i;
  2382. CRYPT_ENROLLMENT_NAME_VALUE_PAIR *pNamePair = NULL;
  2383. DWORD cb;
  2384. if (g_fVerbose)
  2385. {
  2386. for (i = 0; i < cAttribute; i++)
  2387. {
  2388. if (NULL != paAttribute[i].pbData)
  2389. {
  2390. if (NULL != pNamePair)
  2391. {
  2392. LocalFree(pNamePair);
  2393. pNamePair = NULL;
  2394. }
  2395. if (!myDecodeObject(
  2396. X509_ASN_ENCODING,
  2397. //X509_ENROLLMENT_NAME_VALUE_PAIR,
  2398. szOID_ENROLLMENT_NAME_VALUE_PAIR,
  2399. paAttribute[i].pbData,
  2400. paAttribute[i].cbData,
  2401. CERTLIB_USE_LOCALALLOC,
  2402. (VOID **) &pNamePair,
  2403. &cb))
  2404. {
  2405. hr = myHLastError();
  2406. _JumpError(hr, error, "myDecodeObject");
  2407. }
  2408. wprintf(
  2409. L"%u: %ws = %ws\n",
  2410. i,
  2411. pNamePair->pwszName,
  2412. pNamePair->pwszValue);
  2413. }
  2414. }
  2415. }
  2416. hr = S_OK;
  2417. error:
  2418. if (NULL != pNamePair)
  2419. {
  2420. LocalFree(pNamePair);
  2421. }
  2422. return(hr);
  2423. }
  2424. VOID
  2425. FreeExtensions(
  2426. IN BOOL fFreeObjIds,
  2427. IN DWORD cExt,
  2428. IN OUT CERT_EXTENSION *rgExt)
  2429. {
  2430. IN DWORD i;
  2431. if (NULL != rgExt)
  2432. {
  2433. for (i = 0; i < cExt; i++)
  2434. {
  2435. if (fFreeObjIds && NULL != rgExt[i].pszObjId)
  2436. {
  2437. LocalFree(rgExt[i].pszObjId);
  2438. }
  2439. if (NULL != rgExt[i].Value.pbData)
  2440. {
  2441. LocalFree(rgExt[i].Value.pbData);
  2442. }
  2443. }
  2444. LocalFree(rgExt);
  2445. }
  2446. }
  2447. VOID
  2448. FreeAttributes(
  2449. IN DWORD cAttributes,
  2450. IN OUT CRYPT_ATTRIBUTES *rgAttributes)
  2451. {
  2452. DWORD i;
  2453. DWORD j;
  2454. if (NULL != rgAttributes)
  2455. {
  2456. for (i = 0; i < cAttributes; i++)
  2457. {
  2458. CRYPT_ATTRIBUTE *pAttribute = rgAttributes[i].rgAttr;
  2459. if (NULL != pAttribute)
  2460. {
  2461. if (NULL != pAttribute->rgValue)
  2462. {
  2463. for (j = 0; j < pAttribute->cValue; j++)
  2464. {
  2465. CRYPT_ATTR_BLOB *pValue = &pAttribute->rgValue[j];
  2466. if (NULL != pValue->pbData)
  2467. {
  2468. LocalFree(pValue->pbData);
  2469. }
  2470. }
  2471. LocalFree(pAttribute->rgValue);
  2472. }
  2473. LocalFree(pAttribute);
  2474. }
  2475. }
  2476. LocalFree(rgAttributes);
  2477. }
  2478. }
  2479. HRESULT
  2480. ParseInfFile(
  2481. IN WCHAR const *pwszfnPolicy,
  2482. OPTIONAL OUT INFVALUES **prgInfValues,
  2483. OPTIONAL OUT DWORD *pcInfValues,
  2484. OUT CRYPT_ATTR_BLOB **ppaAttribute,
  2485. OUT DWORD *pcAttribute,
  2486. OUT CERT_EXTENSION **ppExt,
  2487. OUT DWORD *pcExt,
  2488. OUT WCHAR **ppwszTemplateNameInf)
  2489. {
  2490. HRESULT hr;
  2491. HINF hInf = INVALID_HANDLE_VALUE;
  2492. DWORD ErrorLine;
  2493. DWORD i;
  2494. INFVALUES *rgInfValues = NULL;
  2495. DWORD cInfValues;
  2496. DWORD cExt = 0;
  2497. DWORD cAttribute = 0;
  2498. CRYPT_ATTR_BLOB *paAttribute = NULL;
  2499. CERT_EXTENSION aext[CINFEXT];
  2500. FNMYINFGETEXTENSION **ppfnGetExtension;
  2501. CERT_EXTENSION *rgExt = NULL;
  2502. DWORD cExtInf = 0;
  2503. CERT_EXTENSION *rgExtInf = NULL;
  2504. WCHAR *pwszInfError = NULL;
  2505. WCHAR *pwszzSectionNames;
  2506. if (NULL != prgInfValues)
  2507. {
  2508. *prgInfValues = NULL;
  2509. }
  2510. if (NULL != pcInfValues)
  2511. {
  2512. *pcInfValues = 0;
  2513. }
  2514. *ppaAttribute = NULL;
  2515. *pcAttribute = 0;
  2516. *ppExt = NULL;
  2517. *pcExt = 0;
  2518. *ppwszTemplateNameInf = NULL;
  2519. cInfValues = 0;
  2520. ZeroMemory(aext, sizeof(aext));
  2521. hr = myInfOpenFile(pwszfnPolicy, &hInf, &ErrorLine);
  2522. if (S_OK != hr)
  2523. {
  2524. SetErrorString(pwszfnPolicy);
  2525. _JumpError(hr, error, "myInfOpenFile");
  2526. }
  2527. if (NULL != prgInfValues && NULL != pcInfValues)
  2528. {
  2529. hr = myInfGetSectionValues(
  2530. hInf,
  2531. wszINFSECTION_NEWREQUEST,
  2532. &cInfValues,
  2533. &rgInfValues);
  2534. if (S_OK != hr)
  2535. {
  2536. SetErrorString(pwszfnPolicy);
  2537. _JumpError(hr, error, "myInfGetSectionValues");
  2538. }
  2539. }
  2540. for (ppfnGetExtension = g_apfnGetExtension;
  2541. ppfnGetExtension < &g_apfnGetExtension[CINFEXT];
  2542. ppfnGetExtension++)
  2543. {
  2544. hr = (**ppfnGetExtension)(hInf, &aext[cExt]);
  2545. CSASSERT((NULL == aext[cExt].Value.pbData) ^ (S_OK == hr));
  2546. if (S_OK != hr)
  2547. {
  2548. char achIndex[64];
  2549. if (NULL != pwszInfError)
  2550. {
  2551. LocalFree(pwszInfError);
  2552. pwszInfError = NULL;
  2553. }
  2554. sprintf(
  2555. achIndex,
  2556. "*ppfnGetExtension[%u]",
  2557. SAFE_SUBTRACT_POINTERS(ppfnGetExtension, g_apfnGetExtension));
  2558. pwszInfError = myInfGetError();
  2559. if (S_FALSE == hr || (HRESULT) ERROR_LINE_NOT_FOUND == hr)
  2560. {
  2561. //_PrintErrorStr2(hr, achIndex, pwszInfError, S_FALSE);
  2562. continue;
  2563. }
  2564. _JumpIfErrorStr(hr, error, achIndex, pwszInfError);
  2565. }
  2566. cExt++;
  2567. }
  2568. hr = myInfGetExtensions(hInf, &cExtInf, &rgExtInf);
  2569. if ((HRESULT) ERROR_LINE_NOT_FOUND != hr && S_FALSE != hr)
  2570. {
  2571. _JumpIfError(hr, error, "myInfGetExtensions");
  2572. }
  2573. hr = myInfGetRequestAttributes(
  2574. hInf,
  2575. &cAttribute,
  2576. &paAttribute,
  2577. ppwszTemplateNameInf);
  2578. if ((HRESULT) ERROR_LINE_NOT_FOUND != hr && S_FALSE != hr)
  2579. {
  2580. _JumpIfError(hr, error, "myInfGetRequestAttributes");
  2581. }
  2582. DumpRequestAttributeBlobs(cAttribute, paAttribute);
  2583. hr = myInfGetUnreferencedSectionNames(&pwszzSectionNames);
  2584. _JumpIfError(hr, error, "myInfGetUnreferencedSectionNames");
  2585. if (NULL != pwszzSectionNames)
  2586. {
  2587. WCHAR *pwsz;
  2588. pwsz = pwszzSectionNames;
  2589. while (L'\0' != *pwsz)
  2590. {
  2591. pwsz += wcslen(pwsz);
  2592. *pwsz++ = L'\n';
  2593. }
  2594. g_pwszUnreferencedSectionNames = pwszzSectionNames;
  2595. }
  2596. if (0 != cExt + cExtInf)
  2597. {
  2598. rgExt = (CERT_EXTENSION *) LocalAlloc(
  2599. LMEM_FIXED | LMEM_ZEROINIT,
  2600. (cExt + cExtInf) * sizeof(**ppExt));
  2601. if (NULL == rgExt)
  2602. {
  2603. hr = E_OUTOFMEMORY;
  2604. _JumpError(hr, error, "LocalAlloc");
  2605. }
  2606. if (0 != cExt)
  2607. {
  2608. CopyMemory(&rgExt[0], &aext[0], cExt * sizeof(rgExt[0]));
  2609. for (i = 0; i < cExt; i++)
  2610. {
  2611. rgExt[i].pszObjId = NULL;
  2612. }
  2613. for (i = 0; i < cExt; i++)
  2614. {
  2615. hr = myDupStringA(aext[i].pszObjId, &rgExt[i].pszObjId);
  2616. _JumpIfError(hr, error, "myDupStringA");
  2617. }
  2618. }
  2619. if (0 != cExtInf)
  2620. {
  2621. CopyMemory(&rgExt[cExt], rgExtInf, cExtInf * sizeof(rgExtInf[0]));
  2622. ZeroMemory(rgExtInf, cExtInf * sizeof(rgExtInf[0]));
  2623. }
  2624. if (g_fVerbose)
  2625. {
  2626. for (i = 0; i < cExt + cExtInf; i++)
  2627. {
  2628. WCHAR *pwszCritMsg = NULL;
  2629. myLoadRCString(
  2630. g_hInstance,
  2631. rgExt[i].fCritical? IDS_CRITICAL : IDS_NON_CRITICAL,
  2632. &pwszCritMsg);
  2633. wprintf(
  2634. L"%u: %hs(%ws) %ws cb=%x\n",
  2635. i,
  2636. rgExt[i].pszObjId,
  2637. myGetOIDNameA(rgExt[i].pszObjId),
  2638. pwszCritMsg,
  2639. rgExt[i].Value.cbData);
  2640. if (NULL != pwszCritMsg)
  2641. {
  2642. LocalFree(pwszCritMsg);
  2643. }
  2644. }
  2645. }
  2646. *pcExt = cExt + cExtInf;
  2647. *ppExt = rgExt;
  2648. rgExt = NULL;
  2649. }
  2650. if (NULL != prgInfValues && NULL != pcInfValues)
  2651. {
  2652. *prgInfValues = rgInfValues;
  2653. rgInfValues = NULL;
  2654. *pcInfValues = cInfValues;
  2655. }
  2656. *ppaAttribute = paAttribute;
  2657. *pcAttribute = cAttribute;
  2658. paAttribute = NULL;
  2659. hr = S_OK;
  2660. error:
  2661. if (NULL != rgInfValues)
  2662. {
  2663. myInfFreeSectionValues(cInfValues, rgInfValues);
  2664. }
  2665. if (NULL != pwszInfError)
  2666. {
  2667. LocalFree(pwszInfError);
  2668. }
  2669. if (S_OK != hr)
  2670. {
  2671. for (i = 0; i < ARRAYSIZE(aext); i++)
  2672. {
  2673. if (NULL != aext[i].Value.pbData)
  2674. {
  2675. LocalFree(aext[i].Value.pbData);
  2676. }
  2677. }
  2678. if (NULL != *ppwszTemplateNameInf)
  2679. {
  2680. LocalFree(*ppwszTemplateNameInf);
  2681. *ppwszTemplateNameInf = NULL;
  2682. }
  2683. if (NULL != rgExt)
  2684. {
  2685. FreeExtensions(TRUE, cExt, rgExt);
  2686. }
  2687. }
  2688. myInfFreeExtensions(cExtInf, rgExtInf);
  2689. if (NULL != paAttribute)
  2690. {
  2691. myInfFreeRequestAttributes(cAttribute, paAttribute);
  2692. }
  2693. if (INVALID_HANDLE_VALUE != hInf)
  2694. {
  2695. g_pwszInfErrorString = myInfGetError();
  2696. myInfCloseFile(hInf);
  2697. }
  2698. return(hr);
  2699. }
  2700. HRESULT
  2701. DeleteMsgCerts(
  2702. IN HCRYPTMSG hMsg)
  2703. {
  2704. HRESULT hr;
  2705. CERT_CONTEXT const *pCert = NULL;
  2706. BYTE *pbCert = NULL;
  2707. CSASSERT(NULL == pCert);
  2708. for (;;)
  2709. {
  2710. BOOL fFirst = FALSE;
  2711. DWORD cCert;
  2712. DWORD cb;
  2713. DWORD i;
  2714. cb = sizeof(cCert);
  2715. if (!CryptMsgGetParam(
  2716. hMsg,
  2717. CMSG_CERT_COUNT_PARAM,
  2718. 0,
  2719. &cCert,
  2720. &cb))
  2721. {
  2722. hr = myHLastError();
  2723. _JumpError(hr, error, "CryptMsgGetParam(Cert count)");
  2724. }
  2725. for (i = 0; i < cCert; i++)
  2726. {
  2727. CSASSERT(NULL == pbCert);
  2728. hr = myCryptMsgGetParam(
  2729. hMsg,
  2730. CMSG_CERT_PARAM,
  2731. i,
  2732. CERTLIB_USE_LOCALALLOC,
  2733. (VOID **) &pbCert,
  2734. &cb);
  2735. _JumpIfError(hr, error, "myCryptMsgGetParam");
  2736. CSASSERT(NULL == pCert);
  2737. pCert = CertCreateCertificateContext(
  2738. X509_ASN_ENCODING,
  2739. pbCert,
  2740. cb);
  2741. if (NULL == pCert)
  2742. {
  2743. hr = myHLastError();
  2744. _JumpError(hr, error, "CertCreateCertificateContext");
  2745. }
  2746. hr = myIsFirstSigner(&pCert->pCertInfo->Subject, &fFirst);
  2747. _JumpIfError(hr, error, "myIsFirstSigner");
  2748. LocalFree(pbCert);
  2749. pbCert = NULL;
  2750. CertFreeCertificateContext(pCert);
  2751. pCert = NULL;
  2752. if (!fFirst)
  2753. {
  2754. DWORD j = i;
  2755. if (!CryptMsgControl(
  2756. hMsg,
  2757. 0, // dwFlags
  2758. CMSG_CTRL_DEL_CERT,
  2759. &j))
  2760. {
  2761. hr = myHLastError();
  2762. _JumpError(hr, error, "CryptMsgControl(delCert)");
  2763. }
  2764. break;
  2765. }
  2766. }
  2767. if (i == cCert)
  2768. {
  2769. break;
  2770. }
  2771. }
  2772. hr = S_OK;
  2773. error:
  2774. if (NULL != pbCert)
  2775. {
  2776. LocalFree(pbCert);
  2777. }
  2778. if (NULL != pCert)
  2779. {
  2780. CertFreeCertificateContext(pCert);
  2781. }
  2782. return(hr);
  2783. }
  2784. HRESULT
  2785. DeleteMsgCRLs(
  2786. IN HCRYPTMSG hMsg)
  2787. {
  2788. HRESULT hr;
  2789. DWORD cCRLPrev;
  2790. for (cCRLPrev = MAXDWORD; ; )
  2791. {
  2792. DWORD cCRL;
  2793. DWORD cb;
  2794. DWORD i;
  2795. cb = sizeof(cCRL);
  2796. if (!CryptMsgGetParam(
  2797. hMsg,
  2798. CMSG_CRL_COUNT_PARAM,
  2799. 0,
  2800. &cCRL,
  2801. &cb))
  2802. {
  2803. hr = myHLastError();
  2804. _JumpError(hr, error, "CryptMsgGetParam(CRL count)");
  2805. }
  2806. if (0 == cCRL)
  2807. {
  2808. break; // we're done
  2809. }
  2810. i = 0; // delete the first CRL
  2811. if (!CryptMsgControl(
  2812. hMsg,
  2813. 0, // dwFlags
  2814. CMSG_CTRL_DEL_CRL,
  2815. &i))
  2816. {
  2817. hr = myHLastError();
  2818. _JumpError(hr, error, "CryptMsgControl(delCRL)");
  2819. }
  2820. if (cCRL >= cCRLPrev)
  2821. {
  2822. break; // give up after one retry
  2823. }
  2824. }
  2825. hr = S_OK;
  2826. error:
  2827. return(hr);
  2828. }
  2829. HRESULT
  2830. AddMsgCert(
  2831. IN HCRYPTMSG hMsg,
  2832. IN HCERTSTORE hStore,
  2833. IN CERT_CONTEXT const *pCertAdd)
  2834. {
  2835. HRESULT hr;
  2836. CERT_CONTEXT const *pCert = NULL;
  2837. for (;;)
  2838. {
  2839. pCert = CertEnumCertificatesInStore(hStore, pCert);
  2840. if (NULL == pCert)
  2841. {
  2842. break;
  2843. }
  2844. if (pCertAdd->cbCertEncoded == pCert->cbCertEncoded &&
  2845. 0 == memcmp(
  2846. pCertAdd->pbCertEncoded,
  2847. pCert->pbCertEncoded,
  2848. pCert->cbCertEncoded))
  2849. {
  2850. break;
  2851. }
  2852. }
  2853. if (NULL == pCert)
  2854. {
  2855. CERT_BLOB Blob;
  2856. Blob.pbData = pCertAdd->pbCertEncoded;
  2857. Blob.cbData = pCertAdd->cbCertEncoded;
  2858. if (!CryptMsgControl(
  2859. hMsg,
  2860. 0, // dwFlags
  2861. CMSG_CTRL_ADD_CERT,
  2862. &Blob))
  2863. {
  2864. hr = myHLastError();
  2865. _JumpError(hr, error, "CryptMsgControl(addCert)");
  2866. }
  2867. }
  2868. hr = S_OK;
  2869. error:
  2870. if (NULL != pCert)
  2871. {
  2872. CertFreeCertificateContext(pCert);
  2873. }
  2874. return(hr);
  2875. }
  2876. HRESULT
  2877. AddMsgCRL(
  2878. IN HCRYPTMSG hMsg,
  2879. IN HCERTSTORE hStore,
  2880. IN CRL_CONTEXT const *pCRLAdd)
  2881. {
  2882. HRESULT hr;
  2883. CRL_CONTEXT const *pCRL = NULL;
  2884. for (;;)
  2885. {
  2886. pCRL = CertEnumCRLsInStore(hStore, pCRL);
  2887. if (NULL == pCRL)
  2888. {
  2889. break;
  2890. }
  2891. if (pCRLAdd->cbCrlEncoded == pCRL->cbCrlEncoded &&
  2892. 0 == memcmp(
  2893. pCRLAdd->pbCrlEncoded,
  2894. pCRL->pbCrlEncoded,
  2895. pCRL->cbCrlEncoded))
  2896. {
  2897. break;
  2898. }
  2899. }
  2900. if (NULL == pCRL)
  2901. {
  2902. CERT_BLOB Blob;
  2903. Blob.pbData = pCRLAdd->pbCrlEncoded;
  2904. Blob.cbData = pCRLAdd->cbCrlEncoded;
  2905. if (!CryptMsgControl(
  2906. hMsg,
  2907. 0, // dwFlags
  2908. CMSG_CTRL_ADD_CRL,
  2909. &Blob))
  2910. {
  2911. hr = myHLastError();
  2912. _JumpError(hr, error, "CryptMsgControl(addCRL)");
  2913. }
  2914. }
  2915. hr = S_OK;
  2916. error:
  2917. if (NULL != pCRL)
  2918. {
  2919. CertFreeCRLContext(pCRL);
  2920. }
  2921. return(hr);
  2922. }
  2923. HRESULT
  2924. AddMsgCertsAndCRLs(
  2925. IN HCRYPTMSG hMsg,
  2926. IN HCERTSTORE hStore,
  2927. IN CERT_CHAIN_CONTEXT const *pChainContext,
  2928. IN BOOL fIncludeCRLs)
  2929. {
  2930. HRESULT hr;
  2931. DWORD cElement;
  2932. CERT_CHAIN_ELEMENT **ppElement;
  2933. DWORD i;
  2934. CSASSERT(NULL != pChainContext);
  2935. if (NULL == pChainContext ||
  2936. 0 == pChainContext->cChain ||
  2937. 0 == pChainContext->rgpChain[0]->cElement)
  2938. {
  2939. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  2940. _JumpError(hr, error, "no chain");
  2941. }
  2942. cElement = pChainContext->rgpChain[0]->cElement;
  2943. ppElement = pChainContext->rgpChain[0]->rgpElement;
  2944. for (i = 0; i < cElement; ppElement++, i++)
  2945. {
  2946. hr = AddMsgCert(hMsg, hStore, (*ppElement)->pCertContext);
  2947. _JumpIfError(hr, error, "AddMsgCert");
  2948. if (fIncludeCRLs)
  2949. {
  2950. CERT_REVOCATION_INFO *pRevocationInfo;
  2951. pRevocationInfo = (*ppElement)->pRevocationInfo;
  2952. if (NULL != pRevocationInfo &&
  2953. CCSIZEOF_STRUCT(CERT_REVOCATION_INFO, pCrlInfo) <=
  2954. pRevocationInfo->cbSize &&
  2955. NULL != pRevocationInfo->pCrlInfo)
  2956. {
  2957. CERT_REVOCATION_CRL_INFO *pCrlInfo;
  2958. pCrlInfo = pRevocationInfo->pCrlInfo;
  2959. if (NULL != pCrlInfo)
  2960. {
  2961. if (NULL != pCrlInfo->pBaseCrlContext)
  2962. {
  2963. hr = AddMsgCRL(
  2964. hMsg,
  2965. hStore,
  2966. pCrlInfo->pBaseCrlContext);
  2967. _JumpIfError(hr, error, "AddMsgCRL");
  2968. }
  2969. if (NULL != pCrlInfo->pDeltaCrlContext)
  2970. {
  2971. hr = AddMsgCRL(
  2972. hMsg,
  2973. hStore,
  2974. pCrlInfo->pDeltaCrlContext);
  2975. _JumpIfError(hr, error, "AddMsgCRL");
  2976. }
  2977. }
  2978. }
  2979. }
  2980. }
  2981. hr = S_OK;
  2982. error:
  2983. return(hr);
  2984. }
  2985. HRESULT
  2986. AddOrDeleteMsgCertsAndCRLs(
  2987. IN BYTE const *pbPKCS7,
  2988. IN DWORD cbPKCS7,
  2989. IN HCRYPTMSG hMsg,
  2990. IN BOOL fDelete, // else add Certs and CRLs
  2991. OPTIONAL IN CERT_CHAIN_CONTEXT const *pChainContext,
  2992. IN BOOL fIncludeCRLs)
  2993. {
  2994. HRESULT hr;
  2995. CRYPT_DATA_BLOB blobPKCS7;
  2996. HCERTSTORE hStore = NULL;
  2997. blobPKCS7.pbData = const_cast<BYTE *>(pbPKCS7);
  2998. blobPKCS7.cbData = cbPKCS7;
  2999. hStore = CertOpenStore(
  3000. CERT_STORE_PROV_PKCS7,
  3001. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  3002. NULL, // hCryptProv
  3003. 0, // dwFlags
  3004. &blobPKCS7);
  3005. if (NULL == hStore)
  3006. {
  3007. hr = myHLastError();
  3008. _JumpError(hr, error, "CertOpenStore");
  3009. }
  3010. if (fDelete)
  3011. {
  3012. CSASSERT(NULL == pChainContext);
  3013. hr = DeleteMsgCerts(hMsg);
  3014. _JumpIfError(hr, error, "DeleteMsgCerts");
  3015. hr = DeleteMsgCRLs(hMsg);
  3016. _JumpIfError(hr, error, "DeleteMsgCRLs");
  3017. }
  3018. else
  3019. {
  3020. CSASSERT(NULL != pChainContext);
  3021. hr = AddMsgCertsAndCRLs(hMsg, hStore, pChainContext, fIncludeCRLs);
  3022. _JumpIfError(hr, error, "AddMsgCertsAndCRLs");
  3023. }
  3024. hr = S_OK;
  3025. error:
  3026. if (NULL != hStore)
  3027. {
  3028. CertCloseStore(hStore, 0);
  3029. }
  3030. return(hr);
  3031. }
  3032. HRESULT
  3033. SignCMCContent(
  3034. OPTIONAL IN CERT_CONTEXT const *pCertSigner,
  3035. IN char const *pszInnerContentObjId,
  3036. IN BYTE const *pbPKCS7Old,
  3037. IN DWORD cbPKCS7Old,
  3038. IN BOOL fIncludeCRLs,
  3039. OUT BYTE **ppbPKCS7New,
  3040. OUT DWORD *pcbPKCS7New)
  3041. {
  3042. HRESULT hr;
  3043. HCRYPTPROV hProv = NULL;
  3044. DWORD dwKeySpec;
  3045. BOOL fCallerFreeProv;
  3046. DWORD cb;
  3047. HCRYPTMSG hMsg = NULL;
  3048. CMSG_SIGNER_ENCODE_INFO SignerEncodeInfo;
  3049. CRYPT_ATTRIBUTE AttributeRequestClient;
  3050. CRYPT_ATTR_BLOB BlobRequestClient;
  3051. CERT_BLOB SignerCertBlob;
  3052. DWORD cSigner;
  3053. DWORD i;
  3054. CERT_CONTEXT const *pCert = NULL;
  3055. CERT_CHAIN_CONTEXT const *pChainContext = NULL;
  3056. DWORD iElement;
  3057. CMSG_CMS_SIGNER_INFO *pcsi = NULL;
  3058. DWORD cFirstSigner;
  3059. BOOL fFirst;
  3060. CERT_REQUEST_INFO *pRequest = NULL;
  3061. BlobRequestClient.pbData = NULL;
  3062. fCallerFreeProv = FALSE;
  3063. // decode existing PKCS 7 wrapper, and add or delete signatures
  3064. hMsg = CryptMsgOpenToDecode(
  3065. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  3066. 0, // dwFlags
  3067. 0, // dwMsgType
  3068. //CMSG_SIGNED,
  3069. NULL, // hCryptProv
  3070. NULL, // pRecipientInfo
  3071. NULL); // pStreamInfo
  3072. if (NULL == hMsg)
  3073. {
  3074. hr = myHLastError();
  3075. _JumpError(hr, error, "CryptMsgOpenToDecode");
  3076. }
  3077. // Update the message with the old PKCS 7 signed message
  3078. if (!CryptMsgUpdate(hMsg, pbPKCS7Old, cbPKCS7Old, TRUE))
  3079. {
  3080. hr = myHLastError();
  3081. _JumpError(hr, error, "CryptMsgUpdate");
  3082. }
  3083. cb = sizeof(cSigner);
  3084. if (!CryptMsgGetParam(
  3085. hMsg,
  3086. CMSG_SIGNER_COUNT_PARAM,
  3087. 0,
  3088. &cSigner,
  3089. &cb))
  3090. {
  3091. hr = myHLastError();
  3092. _JumpError(hr, error, "CryptMsgGetParam(signer count)");
  3093. }
  3094. cFirstSigner = 0;
  3095. if (NULL != pCertSigner)
  3096. {
  3097. CERT_CHAIN_PARA ChainParams;
  3098. ZeroMemory(&SignerEncodeInfo, sizeof(SignerEncodeInfo));
  3099. SignerEncodeInfo.cbSize = sizeof(SignerEncodeInfo);
  3100. hr = myEncodeRequestClientAttributeFromClientId(
  3101. XECI_CERTREQ,
  3102. &BlobRequestClient.pbData,
  3103. &BlobRequestClient.cbData);
  3104. _JumpIfError(hr, error, "myEncodeRequestClientAttributeFromClientId");
  3105. AttributeRequestClient.pszObjId = szOID_REQUEST_CLIENT_INFO;
  3106. AttributeRequestClient.cValue = 1;
  3107. AttributeRequestClient.rgValue = &BlobRequestClient;
  3108. // Search for and load the cryptographic provider and private key.
  3109. hr = myLoadPrivateKey(
  3110. &pCertSigner->pCertInfo->SubjectPublicKeyInfo,
  3111. CUCS_MACHINESTORE | CUCS_USERSTORE | CUCS_MYSTORE | CUCS_ARCHIVED,
  3112. &hProv,
  3113. &dwKeySpec,
  3114. &fCallerFreeProv);
  3115. _JumpIfError(hr, error, "myLoadPrivateKey");
  3116. // Get the cert chain
  3117. ZeroMemory(&ChainParams, sizeof(ChainParams));
  3118. ChainParams.cbSize = sizeof(ChainParams);
  3119. ChainParams.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
  3120. //ChainParams.RequestedUsage.Usage.cUsageIdentifier = 0;
  3121. //ChainParams.RequestedUsage.Usage.rgpszUsageIdentifier = NULL;
  3122. if (!CertGetCertificateChain(
  3123. NULL, // hChainEngine
  3124. pCertSigner, // pCertContext
  3125. NULL, // pTime
  3126. NULL, // hAdditionalStore
  3127. &ChainParams, // pChainPara
  3128. CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
  3129. NULL, // pvReserved
  3130. &pChainContext)) // ppChainContext
  3131. {
  3132. hr = myHLastError();
  3133. _JumpError(hr, error, "CertGetCertificateChain");
  3134. }
  3135. // Initialize the CMSG_SIGNER_ENCODE_INFO structure.
  3136. // Note: handles only a single signer.
  3137. SignerCertBlob.cbData = pCertSigner->cbCertEncoded;
  3138. SignerCertBlob.pbData = pCertSigner->pbCertEncoded;
  3139. SignerEncodeInfo.pCertInfo = pCertSigner->pCertInfo;
  3140. SignerEncodeInfo.hCryptProv = hProv;
  3141. SignerEncodeInfo.dwKeySpec = dwKeySpec;
  3142. SignerEncodeInfo.HashAlgorithm.pszObjId = const_cast<CHAR *>(g_pszObjIdHash);
  3143. //SignerEncodeInfo.pvHashAuxInfo = NULL;
  3144. SignerEncodeInfo.cAuthAttr = 1;
  3145. SignerEncodeInfo.rgAuthAttr = &AttributeRequestClient;
  3146. // fail if any existing signing cert matches the new signing cert.
  3147. for (i = 0; i < cSigner; i++)
  3148. {
  3149. if (NULL != pcsi)
  3150. {
  3151. LocalFree(pcsi);
  3152. pcsi = NULL;
  3153. }
  3154. hr = myCryptMsgGetParam(
  3155. hMsg,
  3156. CMSG_CMS_SIGNER_INFO_PARAM,
  3157. i,
  3158. CERTLIB_USE_LOCALALLOC,
  3159. (VOID **) &pcsi,
  3160. &cb);
  3161. _JumpIfError(hr, error, "myCryptMsgGetParam");
  3162. if (CERT_ID_KEY_IDENTIFIER == pcsi->SignerId.dwIdChoice ||
  3163. (NULL != pcsi->HashEncryptionAlgorithm.pszObjId &&
  3164. 0 == strcmp(
  3165. szOID_PKIX_NO_SIGNATURE,
  3166. pcsi->HashEncryptionAlgorithm.pszObjId)))
  3167. {
  3168. CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA cvse;
  3169. ZeroMemory(&cvse, sizeof(cvse));
  3170. cvse.cbSize = sizeof(cvse);
  3171. cvse.dwSignerIndex = i;
  3172. if (CERT_ID_KEY_IDENTIFIER == pcsi->SignerId.dwIdChoice)
  3173. {
  3174. if (NULL == pRequest)
  3175. {
  3176. hr = myGetInnerPKCS10(
  3177. hMsg,
  3178. pszInnerContentObjId,
  3179. &pRequest);
  3180. _JumpIfError(hr, error, "myGetInnerPKCS10");
  3181. }
  3182. cvse.dwSignerType = CMSG_VERIFY_SIGNER_PUBKEY;
  3183. cvse.pvSigner = &pRequest->SubjectPublicKeyInfo;
  3184. }
  3185. else
  3186. {
  3187. cvse.dwSignerType = CMSG_VERIFY_SIGNER_NULL;
  3188. }
  3189. if (!CryptMsgControl(
  3190. hMsg,
  3191. 0, // dwFlags
  3192. CMSG_CTRL_VERIFY_SIGNATURE_EX,
  3193. &cvse))
  3194. {
  3195. hr = myHLastError();
  3196. _JumpError(hr, error, "CryptMsgControl(VerifySig)");
  3197. }
  3198. cFirstSigner++;
  3199. }
  3200. else
  3201. {
  3202. iElement = i;
  3203. if (!CryptMsgGetAndVerifySigner(
  3204. hMsg,
  3205. 0, // cSignerStore
  3206. NULL, // rghSignerStore
  3207. CMSG_USE_SIGNER_INDEX_FLAG,
  3208. &pCert,
  3209. &iElement))
  3210. {
  3211. hr = myHLastError();
  3212. _JumpError(hr, error, "CryptMsgGetAndVerifySigner");
  3213. }
  3214. if (pCertSigner->cbCertEncoded == pCert->cbCertEncoded &&
  3215. 0 == memcmp(
  3216. pCertSigner->pbCertEncoded,
  3217. pCert->pbCertEncoded,
  3218. pCert->cbCertEncoded))
  3219. {
  3220. hr = CRYPT_E_EXISTS;
  3221. _JumpError(hr, error, "duplicate signing cert");
  3222. }
  3223. hr = myIsFirstSigner(&pCert->pCertInfo->Subject, &fFirst);
  3224. _JumpIfError(hr, error, "myIsFirstSigner");
  3225. if (fFirst)
  3226. {
  3227. cFirstSigner++;
  3228. }
  3229. CertFreeCertificateContext(pCert);
  3230. pCert = NULL;
  3231. }
  3232. }
  3233. if (!CryptMsgControl(
  3234. hMsg,
  3235. 0, // dwFlags
  3236. CMSG_CTRL_ADD_SIGNER,
  3237. &SignerEncodeInfo))
  3238. {
  3239. hr = myHLastError();
  3240. _JumpError(hr, error, "CryptMsgControl(addSigner)");
  3241. }
  3242. }
  3243. else
  3244. {
  3245. // delete all existing signers -- except the first signer
  3246. for (;;)
  3247. {
  3248. BOOL fDeleteSigner = FALSE;
  3249. for (i = 0; i < cSigner; i++)
  3250. {
  3251. if (NULL != pcsi)
  3252. {
  3253. LocalFree(pcsi);
  3254. pcsi = NULL;
  3255. }
  3256. hr = myCryptMsgGetParam(
  3257. hMsg,
  3258. CMSG_CMS_SIGNER_INFO_PARAM,
  3259. i,
  3260. CERTLIB_USE_LOCALALLOC,
  3261. (VOID **) &pcsi,
  3262. &cb);
  3263. _JumpIfError(hr, error, "myCryptMsgGetParam");
  3264. if (CERT_ID_KEY_IDENTIFIER == pcsi->SignerId.dwIdChoice ||
  3265. (NULL != pcsi->HashEncryptionAlgorithm.pszObjId &&
  3266. 0 == strcmp(
  3267. szOID_PKIX_NO_SIGNATURE,
  3268. pcsi->HashEncryptionAlgorithm.pszObjId)))
  3269. {
  3270. cFirstSigner++;
  3271. continue;
  3272. }
  3273. iElement = i;
  3274. if (!CryptMsgGetAndVerifySigner(
  3275. hMsg,
  3276. 0, // cSignerStore
  3277. NULL, // rghSignerStore
  3278. CMSG_USE_SIGNER_INDEX_FLAG |
  3279. CMSG_SIGNER_ONLY_FLAG,
  3280. &pCert,
  3281. &iElement))
  3282. {
  3283. hr = myHLastError();
  3284. _JumpError(hr, error, "CryptMsgGetAndVerifySigner");
  3285. }
  3286. hr = myIsFirstSigner(&pCert->pCertInfo->Subject, &fFirst);
  3287. _JumpIfError(hr, error, "myIsFirstSigner");
  3288. CertFreeCertificateContext(pCert);
  3289. pCert = NULL;
  3290. if (!fFirst)
  3291. {
  3292. fDeleteSigner = TRUE;
  3293. break;
  3294. }
  3295. cFirstSigner++;
  3296. }
  3297. if (!fDeleteSigner)
  3298. {
  3299. break;
  3300. }
  3301. if (!CryptMsgControl(
  3302. hMsg,
  3303. 0, // dwFlags
  3304. CMSG_CTRL_DEL_SIGNER,
  3305. &iElement))
  3306. {
  3307. hr = myHLastError();
  3308. _JumpError(hr, error, "CryptMsgControl(delSigner)");
  3309. }
  3310. cb = sizeof(cSigner);
  3311. if (!CryptMsgGetParam(
  3312. hMsg,
  3313. CMSG_SIGNER_COUNT_PARAM,
  3314. 0,
  3315. &cSigner,
  3316. &cb))
  3317. {
  3318. hr = myHLastError();
  3319. _JumpError(hr, error, "CryptMsgGetParam(signer count)");
  3320. }
  3321. }
  3322. }
  3323. if (1 != cFirstSigner)
  3324. {
  3325. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  3326. _JumpError(hr, error, "cFirstSigner");
  3327. }
  3328. // Add or delete signing cert chain certs and CRLs in the message.
  3329. hr = AddOrDeleteMsgCertsAndCRLs(
  3330. pbPKCS7Old,
  3331. cbPKCS7Old,
  3332. hMsg,
  3333. NULL == pChainContext, // fDelete
  3334. pChainContext,
  3335. fIncludeCRLs);
  3336. _JumpIfError(hr, error, "AddOrDeleteMsgCertsAndCRLs");
  3337. // Get the signed message. Force reencoding with the changed signatures.
  3338. hr = myCryptMsgGetParam(
  3339. hMsg,
  3340. CMSG_ENCODED_MESSAGE,
  3341. 0,
  3342. CERTLIB_USE_LOCALALLOC,
  3343. (VOID **) ppbPKCS7New,
  3344. pcbPKCS7New);
  3345. _JumpIfError(hr, error, "myCryptMsgGetParam");
  3346. error:
  3347. if (NULL != pRequest)
  3348. {
  3349. LocalFree(pRequest);
  3350. }
  3351. if (NULL != pcsi)
  3352. {
  3353. LocalFree(pcsi);
  3354. }
  3355. if (NULL != BlobRequestClient.pbData)
  3356. {
  3357. LocalFree(BlobRequestClient.pbData);
  3358. }
  3359. if (NULL != pChainContext)
  3360. {
  3361. CertFreeCertificateChain(pChainContext);
  3362. }
  3363. if (NULL != pCert)
  3364. {
  3365. CertFreeCertificateContext(pCert);
  3366. }
  3367. if (NULL != hMsg)
  3368. {
  3369. CryptMsgClose(hMsg);
  3370. }
  3371. if (NULL != hProv && fCallerFreeProv)
  3372. {
  3373. CryptReleaseContext(hProv, 0);
  3374. }
  3375. return(hr);
  3376. }
  3377. BOOL
  3378. IsCATemplate(
  3379. IN WCHAR const *pwszExtensionName)
  3380. {
  3381. BOOL fCA;
  3382. DWORD i;
  3383. static WCHAR const * const s_apwszCATemplate[] = {
  3384. wszCERTTYPE_CA,
  3385. wszCERTTYPE_SUBORDINATE_CA,
  3386. wszCERTTYPE_CROSS_CA,
  3387. };
  3388. fCA = FALSE;
  3389. for (i = 0; i < ARRAYSIZE(s_apwszCATemplate); i++)
  3390. {
  3391. if (0 == mylstrcmpiL(pwszExtensionName, s_apwszCATemplate[i]))
  3392. {
  3393. fCA = TRUE;
  3394. break;
  3395. }
  3396. }
  3397. return(fCA);
  3398. }
  3399. // AddCAExtensions -- add Basic Constraints & KeyUsage extensions if missing
  3400. HRESULT
  3401. AddCAExtensions(
  3402. IN OUT CERT_EXTENSION **prgExt,
  3403. IN OUT DWORD *pcExt)
  3404. {
  3405. HRESULT hr;
  3406. DWORD cExt;
  3407. BOOL fAddBasicConstraints = TRUE;
  3408. BOOL fAddKeyUsage = TRUE;
  3409. if (NULL != *prgExt)
  3410. {
  3411. cExt = *pcExt;
  3412. if (NULL != CertFindExtension(
  3413. szOID_BASIC_CONSTRAINTS2,
  3414. cExt,
  3415. *prgExt))
  3416. {
  3417. fAddBasicConstraints = FALSE;
  3418. }
  3419. if (NULL == CertFindExtension(szOID_KEY_USAGE, cExt, *prgExt))
  3420. {
  3421. fAddKeyUsage = FALSE;
  3422. }
  3423. }
  3424. else
  3425. {
  3426. *pcExt = 0;
  3427. cExt = *pcExt;
  3428. }
  3429. if (fAddBasicConstraints || fAddKeyUsage)
  3430. {
  3431. CERT_EXTENSION *rgExt;
  3432. CERT_EXTENSION *pExt;
  3433. if (fAddBasicConstraints)
  3434. {
  3435. cExt++;
  3436. }
  3437. if (fAddKeyUsage)
  3438. {
  3439. cExt++;
  3440. }
  3441. rgExt = (CERT_EXTENSION *) LocalAlloc(
  3442. LMEM_FIXED | LMEM_ZEROINIT,
  3443. sizeof(rgExt[0]) * cExt);
  3444. if (NULL == rgExt)
  3445. {
  3446. hr = E_OUTOFMEMORY;
  3447. _JumpError(hr, error, "LocalAlloc");
  3448. }
  3449. if (NULL != *prgExt)
  3450. {
  3451. CopyMemory(rgExt, *prgExt, *pcExt * sizeof(rgExt[0]));
  3452. LocalFree(*prgExt);
  3453. }
  3454. *prgExt = rgExt;
  3455. pExt = &rgExt[*pcExt];
  3456. if (fAddBasicConstraints)
  3457. {
  3458. CERT_BASIC_CONSTRAINTS2_INFO Constraints;
  3459. Constraints.fCA = TRUE;
  3460. Constraints.fPathLenConstraint = FALSE;
  3461. Constraints.dwPathLenConstraint = 0;
  3462. (*pcExt)++; // increment now to free memory on error
  3463. hr = myDupStringA(szOID_BASIC_CONSTRAINTS2, &pExt->pszObjId);
  3464. _JumpIfError(hr, error, "myDupStringA");
  3465. pExt->fCritical = TRUE;
  3466. if (!myEncodeObject(
  3467. X509_ASN_ENCODING,
  3468. X509_BASIC_CONSTRAINTS2,
  3469. &Constraints,
  3470. 0,
  3471. CERTLIB_USE_LOCALALLOC,
  3472. &pExt->Value.pbData,
  3473. &pExt->Value.cbData))
  3474. {
  3475. hr = myHLastError();
  3476. _JumpError(hr, error, "myEncodeObject");
  3477. }
  3478. pExt++;
  3479. }
  3480. if (fAddKeyUsage)
  3481. {
  3482. CRYPT_BIT_BLOB KeyUsage;
  3483. BYTE bKeyUsage = myCASIGN_KEY_USAGE;
  3484. KeyUsage.cbData = sizeof(bKeyUsage);
  3485. KeyUsage.pbData = &bKeyUsage;
  3486. KeyUsage.cUnusedBits = 0;
  3487. (*pcExt)++; // increment now to free memory on error
  3488. hr = myDupStringA(szOID_KEY_USAGE, &pExt->pszObjId);
  3489. _JumpIfError(hr, error, "myDupStringA");
  3490. pExt->fCritical = FALSE;
  3491. if (!myEncodeObject(
  3492. X509_ASN_ENCODING,
  3493. X509_KEY_USAGE,
  3494. &KeyUsage,
  3495. 0,
  3496. CERTLIB_USE_LOCALALLOC,
  3497. &pExt->Value.pbData,
  3498. &pExt->Value.cbData))
  3499. {
  3500. hr = myHLastError();
  3501. _JumpError(hr, error, "Policy:myEncodeObject");
  3502. }
  3503. pExt++;
  3504. }
  3505. }
  3506. hr = S_OK;
  3507. error:
  3508. return(hr);
  3509. }
  3510. HRESULT
  3511. MergeAndEncodeExtensions(
  3512. IN BOOL fCA,
  3513. OPTIONAL IN CERT_EXTENSION *rgExtInf,
  3514. IN DWORD cExtInf,
  3515. OPTIONAL IN CERT_EXTENSION *rgExtReq,
  3516. IN DWORD cExtReq,
  3517. OUT BYTE **ppbOut,
  3518. OUT DWORD *pcbOut)
  3519. {
  3520. HRESULT hr;
  3521. CERT_EXTENSIONS Extensions;
  3522. CERT_EXTENSION *rgExtCA = NULL;
  3523. DWORD cExtCA;
  3524. CERT_EXTENSION *rgrgExt[3];
  3525. DWORD rgcExt[3];
  3526. DWORD cExt;
  3527. DWORD i;
  3528. Extensions.rgExtension = NULL;
  3529. *ppbOut = NULL;
  3530. cExtCA = 0;
  3531. if (fCA)
  3532. {
  3533. hr = AddCAExtensions(&rgExtCA, &cExtCA);
  3534. _JumpIfError(hr, error, "AddCAExtensions");
  3535. }
  3536. ZeroMemory(rgrgExt, sizeof(rgrgExt));
  3537. ZeroMemory(rgcExt, sizeof(rgcExt));
  3538. cExt = 0;
  3539. if (NULL != rgExtInf) // INF & template extensions take precedence
  3540. {
  3541. rgrgExt[0] = rgExtInf;
  3542. rgcExt[0] = cExtInf;
  3543. cExt += cExtInf;
  3544. }
  3545. if (NULL != rgExtReq) // Then come Cert & other request extensions
  3546. {
  3547. rgrgExt[1] = rgExtReq;
  3548. rgcExt[1] = cExtReq;
  3549. cExt += cExtReq;
  3550. }
  3551. if (NULL != rgExtCA) // Added CA extensions are lowest priority
  3552. {
  3553. rgrgExt[2] = rgExtCA;
  3554. rgcExt[2] = cExtCA;
  3555. cExt += cExtCA;
  3556. }
  3557. if (0 == cExt)
  3558. {
  3559. hr = S_FALSE; // no extensions to encode
  3560. goto error;
  3561. }
  3562. Extensions.cExtension = 0;
  3563. Extensions.rgExtension = (CERT_EXTENSION *) LocalAlloc(
  3564. LMEM_FIXED,
  3565. sizeof(Extensions.rgExtension[0]) * cExt);
  3566. if (NULL == Extensions.rgExtension)
  3567. {
  3568. hr = E_OUTOFMEMORY;
  3569. _JumpError(hr, error, "LocalAlloc");
  3570. }
  3571. for (i = 0; i < ARRAYSIZE(rgrgExt); i++)
  3572. {
  3573. CERT_EXTENSION *pExt = rgrgExt[i];
  3574. CERT_EXTENSION *pExtEnd;
  3575. for (pExtEnd = &pExt[rgcExt[i]]; pExt < pExtEnd; pExt++)
  3576. {
  3577. if (NULL == CertFindExtension(
  3578. pExt->pszObjId,
  3579. Extensions.cExtension,
  3580. Extensions.rgExtension))
  3581. {
  3582. Extensions.rgExtension[Extensions.cExtension] = *pExt;
  3583. Extensions.cExtension++;
  3584. }
  3585. }
  3586. }
  3587. CSASSERT(Extensions.cExtension <= cExt);
  3588. if (!myEncodeObject(
  3589. X509_ASN_ENCODING,
  3590. X509_EXTENSIONS,
  3591. &Extensions,
  3592. 0,
  3593. CERTLIB_USE_LOCALALLOC,
  3594. ppbOut,
  3595. pcbOut))
  3596. {
  3597. hr = myHLastError();
  3598. _JumpError(hr, error, "myEncodeObject");
  3599. }
  3600. hr = S_OK;
  3601. error:
  3602. if (NULL != rgExtCA)
  3603. {
  3604. FreeExtensions(TRUE, cExtCA, rgExtCA);
  3605. }
  3606. if (NULL != Extensions.rgExtension)
  3607. {
  3608. LocalFree(Extensions.rgExtension);
  3609. }
  3610. return(hr);
  3611. }
  3612. HRESULT
  3613. ConvertCertToPKCS10Request(
  3614. OPTIONAL IN WCHAR const *pwszExtensionName,
  3615. IN OUT BOOL *pfCA,
  3616. OPTIONAL IN CERT_EXTENSION *rgExtInf,
  3617. IN DWORD cExtInf,
  3618. IN OUT BYTE **ppbReq,
  3619. IN OUT DWORD *pcbReq)
  3620. {
  3621. HRESULT hr;
  3622. CERT_CONTEXT const *pCert = NULL;
  3623. BYTE *pbReqUnsigned = NULL;
  3624. DWORD cbReqUnsigned;
  3625. BYTE *pbReq = NULL;
  3626. DWORD cbReq;
  3627. CERT_REQUEST_INFO Request;
  3628. CRYPT_ATTR_BLOB ExtBlob;
  3629. CRYPT_ATTR_BLOB VersionBlob;
  3630. CERT_EXTENSIONS Extensions;
  3631. CRYPT_ATTRIBUTE aAttrib[2];
  3632. HCRYPTPROV hProv = NULL;
  3633. DWORD dwKeySpec;
  3634. BOOL fCallerFreeProv;
  3635. CERT_EXTENSION *pExt;
  3636. CERT_EXTENSION *pExtKeyId;
  3637. CHAR *pszObjId = NULL;
  3638. #define CEXT_ADD 4 // SKI, Template Name, Basic Constraints, KeyUsage
  3639. CERT_EXTENSION aExtAdd[CEXT_ADD];
  3640. DWORD i;
  3641. ZeroMemory(aExtAdd, sizeof(aExtAdd));
  3642. // Certificate extensions to strip out of the request:
  3643. static char const * const s_apszObjIdFilter[] = {
  3644. szOID_BASIC_CONSTRAINTS2, // must be first!
  3645. szOID_CERTSRV_CA_VERSION,
  3646. szOID_AUTHORITY_INFO_ACCESS,
  3647. szOID_CRL_DIST_POINTS,
  3648. szOID_AUTHORITY_KEY_IDENTIFIER2,
  3649. szOID_CERTSRV_PREVIOUS_CERT_HASH,
  3650. szOID_ENROLL_CERTTYPE_EXTENSION,
  3651. szOID_CERTIFICATE_TEMPLATE,
  3652. NULL
  3653. };
  3654. char const * const *apszObjIdFilter = &s_apszObjIdFilter[1];
  3655. ExtBlob.pbData = NULL;
  3656. VersionBlob.pbData = NULL;
  3657. Extensions.rgExtension = NULL;
  3658. fCallerFreeProv = FALSE;
  3659. pCert = CertCreateCertificateContext(
  3660. X509_ASN_ENCODING,
  3661. *ppbReq,
  3662. *pcbReq);
  3663. if (NULL == pCert)
  3664. {
  3665. hr = myHLastError();
  3666. _JumpError(hr, error, "CertCreateCertificateContext");
  3667. }
  3668. if (NULL != pwszExtensionName && IsCATemplate(pwszExtensionName))
  3669. {
  3670. *pfCA = TRUE;
  3671. }
  3672. pExt = CertFindExtension(
  3673. szOID_BASIC_CONSTRAINTS2,
  3674. pCert->pCertInfo->cExtension,
  3675. pCert->pCertInfo->rgExtension);
  3676. if (NULL != pExt)
  3677. {
  3678. BOOL fCAT;
  3679. hr = IsSubjectTypeCA(pExt, &fCAT);
  3680. _JumpIfError(hr, error, "IsSubjectTypeCA");
  3681. if (fCAT)
  3682. {
  3683. *pfCA = TRUE;
  3684. }
  3685. else if (*pfCA)
  3686. {
  3687. // filter out non-CA Basic Constraints -- add a new one below.
  3688. apszObjIdFilter = s_apszObjIdFilter;
  3689. }
  3690. }
  3691. ZeroMemory(&Request, sizeof(Request));
  3692. Request.dwVersion = CERT_REQUEST_V1;
  3693. Request.Subject = pCert->pCertInfo->Subject;
  3694. Request.SubjectPublicKeyInfo = pCert->pCertInfo->SubjectPublicKeyInfo;
  3695. Extensions.cExtension = 0;
  3696. Extensions.rgExtension = (CERT_EXTENSION *) LocalAlloc(
  3697. LMEM_FIXED,
  3698. sizeof(Extensions.rgExtension[0]) *
  3699. (CEXT_ADD + pCert->pCertInfo->cExtension));
  3700. if (NULL == Extensions.rgExtension)
  3701. {
  3702. hr = E_OUTOFMEMORY;
  3703. _JumpError(hr, error, "LocalAlloc");
  3704. }
  3705. pExtKeyId = NULL;
  3706. if (0 < pCert->pCertInfo->cExtension)
  3707. {
  3708. DWORD j;
  3709. pExt = pCert->pCertInfo->rgExtension;
  3710. for (i = 0; i < pCert->pCertInfo->cExtension; i++)
  3711. {
  3712. if (0 == strcmp(szOID_SUBJECT_KEY_IDENTIFIER, pExt->pszObjId))
  3713. {
  3714. pExtKeyId = pExt;
  3715. }
  3716. for (j = 0; ; j++)
  3717. {
  3718. if (NULL == apszObjIdFilter[j])
  3719. {
  3720. Extensions.rgExtension[Extensions.cExtension] =
  3721. pCert->pCertInfo->rgExtension[i];
  3722. Extensions.cExtension++;
  3723. break;
  3724. }
  3725. if (0 == strcmp(apszObjIdFilter[j], pExt->pszObjId))
  3726. {
  3727. break; // skip this extension
  3728. }
  3729. }
  3730. pExt++;
  3731. }
  3732. }
  3733. if (NULL == pExtKeyId)
  3734. {
  3735. BYTE abHash[CBMAX_CRYPT_HASH_LEN];
  3736. CRYPT_DATA_BLOB Blob;
  3737. Blob.pbData = abHash;
  3738. Blob.cbData = sizeof(abHash);
  3739. if (!CryptHashPublicKeyInfo(
  3740. NULL, // hCryptProv
  3741. CALG_SHA1,
  3742. 0, // dwFlags,
  3743. X509_ASN_ENCODING,
  3744. &Request.SubjectPublicKeyInfo,
  3745. Blob.pbData,
  3746. &Blob.cbData))
  3747. {
  3748. hr = myHLastError();
  3749. _JumpError(hr, error, "CryptHashPublicKeyInfo");
  3750. }
  3751. if (!myEncodeObject(
  3752. X509_ASN_ENCODING,
  3753. X509_OCTET_STRING,
  3754. &Blob,
  3755. 0,
  3756. CERTLIB_USE_LOCALALLOC,
  3757. &aExtAdd[0].Value.pbData,
  3758. &aExtAdd[0].Value.cbData))
  3759. {
  3760. hr = myHLastError();
  3761. _JumpError(hr, error, "myEncodeObject");
  3762. }
  3763. aExtAdd[0].pszObjId = szOID_SUBJECT_KEY_IDENTIFIER;
  3764. pExtKeyId = &Extensions.rgExtension[Extensions.cExtension];
  3765. *pExtKeyId = aExtAdd[0];
  3766. Extensions.cExtension++;
  3767. }
  3768. if (NULL != pwszExtensionName)
  3769. {
  3770. hr = myBuildCertTypeExtension(pwszExtensionName, &aExtAdd[1]);
  3771. _JumpIfError(hr, error, "myBuildCertTypeExtension");
  3772. Extensions.rgExtension[Extensions.cExtension] = aExtAdd[1];
  3773. Extensions.cExtension++;
  3774. }
  3775. // get the OS Version
  3776. hr = myBuildOSVersionAttribute(&VersionBlob.pbData, &VersionBlob.cbData);
  3777. _JumpIfError(hr, error, "myBuildOSVersionAttribute");
  3778. hr = MergeAndEncodeExtensions(
  3779. *pfCA,
  3780. rgExtInf,
  3781. cExtInf,
  3782. Extensions.rgExtension,
  3783. Extensions.cExtension,
  3784. &ExtBlob.pbData,
  3785. &ExtBlob.cbData);
  3786. if (S_FALSE != hr)
  3787. {
  3788. _JumpIfError(hr, error, "MergeAndEncodeExtensions");
  3789. }
  3790. Request.cAttribute = 0;
  3791. Request.rgAttribute = aAttrib;
  3792. if (NULL != ExtBlob.pbData)
  3793. {
  3794. aAttrib[Request.cAttribute].pszObjId = szOID_RSA_certExtensions;
  3795. aAttrib[Request.cAttribute].cValue = 1;
  3796. aAttrib[Request.cAttribute].rgValue = &ExtBlob;
  3797. Request.cAttribute++;
  3798. }
  3799. aAttrib[Request.cAttribute].pszObjId = szOID_OS_VERSION;
  3800. aAttrib[Request.cAttribute].cValue = 1;
  3801. aAttrib[Request.cAttribute].rgValue = &VersionBlob;
  3802. Request.cAttribute++;
  3803. if (!myEncodeObject(
  3804. X509_ASN_ENCODING,
  3805. X509_CERT_REQUEST_TO_BE_SIGNED,
  3806. &Request,
  3807. 0,
  3808. CERTLIB_USE_LOCALALLOC,
  3809. &pbReqUnsigned,
  3810. &cbReqUnsigned))
  3811. {
  3812. hr = myHLastError();
  3813. _JumpError(hr, error, "myEncodeObject");
  3814. }
  3815. // Search for and load the cryptographic provider and private key.
  3816. hr = myLoadPrivateKey(
  3817. &pCert->pCertInfo->SubjectPublicKeyInfo,
  3818. CUCS_MACHINESTORE | CUCS_USERSTORE | CUCS_MYSTORE | CUCS_ARCHIVED,
  3819. &hProv,
  3820. &dwKeySpec,
  3821. &fCallerFreeProv);
  3822. if (S_OK != hr)
  3823. {
  3824. _PrintError(hr, "myLoadPrivateKey");
  3825. CSASSERT(NULL == hProv);
  3826. // private key is unavailable -- sign the PKCS10 with a NULL signature.
  3827. hr = myDupStringA(g_pszObjIdHash, &pszObjId);
  3828. _JumpIfError(hr, error, "myDupStringA");
  3829. }
  3830. else
  3831. {
  3832. if (AT_SIGNATURE != dwKeySpec)
  3833. {
  3834. hr = NTE_BAD_KEY_STATE;
  3835. DBGPRINT((DBG_SS_CERTREQ, "dwKeySpec = %u\n", dwKeySpec));
  3836. _JumpError(hr, error, "dwKeySpec");
  3837. }
  3838. // The private key is available -- use it to sign the PKCS10.
  3839. hr = myGetSigningOID(hProv, NULL, 0, CALG_SHA1, &pszObjId);
  3840. _JumpIfError(hr, error, "myGetSigningOID");
  3841. }
  3842. // Sign the request and encode the signed info.
  3843. hr = myEncodeSignedContent(
  3844. hProv,
  3845. X509_ASN_ENCODING,
  3846. pszObjId,
  3847. pbReqUnsigned,
  3848. cbReqUnsigned,
  3849. CERTLIB_USE_LOCALALLOC,
  3850. &pbReq,
  3851. &cbReq);
  3852. _JumpIfError(hr, error, "myEncodeSignedContent");
  3853. LocalFree(*ppbReq);
  3854. *ppbReq = pbReq;
  3855. *pcbReq = cbReq;
  3856. pbReq = NULL;
  3857. hr = S_OK;
  3858. error:
  3859. if (NULL != pszObjId)
  3860. {
  3861. LocalFree(pszObjId);
  3862. }
  3863. if (NULL != hProv && fCallerFreeProv)
  3864. {
  3865. CryptReleaseContext(hProv, 0);
  3866. }
  3867. if (NULL != Extensions.rgExtension)
  3868. {
  3869. LocalFree(Extensions.rgExtension);
  3870. }
  3871. for (i = 0; i < CEXT_ADD; i++)
  3872. {
  3873. if (NULL != aExtAdd[i].Value.pbData)
  3874. {
  3875. LocalFree(aExtAdd[i].Value.pbData);
  3876. }
  3877. }
  3878. if (NULL != ExtBlob.pbData)
  3879. {
  3880. LocalFree(ExtBlob.pbData);
  3881. }
  3882. if (NULL != VersionBlob.pbData)
  3883. {
  3884. LocalFree(VersionBlob.pbData);
  3885. }
  3886. if (NULL != pCert)
  3887. {
  3888. CertFreeCertificateContext(pCert);
  3889. }
  3890. if (NULL != pbReq)
  3891. {
  3892. LocalFree(pbReq);
  3893. }
  3894. if (NULL != pbReqUnsigned)
  3895. {
  3896. LocalFree(pbReqUnsigned);
  3897. }
  3898. return(hr);
  3899. }
  3900. HRESULT
  3901. GetPKCS10PrivateKey(
  3902. IN BYTE const *pbReq,
  3903. IN DWORD cbReq,
  3904. OUT HCRYPTPROV *phProv,
  3905. OUT DWORD *pdwKeySpec,
  3906. OUT BOOL *pfCallerFreeProv,
  3907. OUT BYTE **ppbKeyId,
  3908. OUT DWORD *pcbKeyId)
  3909. {
  3910. HRESULT hr;
  3911. CERT_REQUEST_INFO *pRequest = NULL;
  3912. HCRYPTPROV hProv = NULL;
  3913. CERT_EXTENSIONS *pExtensions = NULL;
  3914. CRYPT_ATTRIBUTE *pAttr;
  3915. BYTE *pbKeyId = NULL;
  3916. DWORD cbKeyId;
  3917. DWORD dwKeySpec;
  3918. DWORD cb;
  3919. DWORD i;
  3920. *phProv = NULL;
  3921. *pdwKeySpec = 0;
  3922. *ppbKeyId = NULL;
  3923. *pcbKeyId = 0;
  3924. if (!myDecodeObject(
  3925. X509_ASN_ENCODING,
  3926. X509_CERT_REQUEST_TO_BE_SIGNED,
  3927. pbReq,
  3928. cbReq,
  3929. CERTLIB_USE_LOCALALLOC,
  3930. (VOID **) &pRequest,
  3931. &cb))
  3932. {
  3933. hr = myHLastError();
  3934. _JumpError(hr, error, "myDecodeObject");
  3935. }
  3936. // Search for and load the cryptographic provider and private key.
  3937. hr = myLoadPrivateKey(
  3938. &pRequest->SubjectPublicKeyInfo,
  3939. CUCS_MACHINESTORE | CUCS_USERSTORE | CUCS_MYSTORE | CUCS_ARCHIVED,
  3940. &hProv,
  3941. &dwKeySpec,
  3942. pfCallerFreeProv);
  3943. _JumpIfError(hr, error, "myLoadPrivateKey");
  3944. if (AT_SIGNATURE != dwKeySpec)
  3945. {
  3946. hr = NTE_BAD_KEY_STATE;
  3947. DBGPRINT((DBG_SS_CERTREQ, "dwKeySpec = %u\n", dwKeySpec));
  3948. _JumpError(hr, error, "dwKeySpec");
  3949. }
  3950. // Fetch or construct the KeyId hash
  3951. cbKeyId = 0;
  3952. pAttr = pRequest->rgAttribute;
  3953. for (i = 0; i < pRequest->cAttribute && NULL != pbKeyId; i++, pAttr++)
  3954. {
  3955. DWORD j;
  3956. if (0 == strcmp(szOID_RSA_certExtensions, pAttr->pszObjId) ||
  3957. 0 == strcmp(szOID_CERT_EXTENSIONS, pAttr->pszObjId))
  3958. {
  3959. for (j = 0; j < pAttr->cValue; j++)
  3960. {
  3961. DWORD k;
  3962. CERT_EXTENSION *pExt;
  3963. if (NULL != pExtensions)
  3964. {
  3965. LocalFree(pExtensions);
  3966. pExtensions = NULL;
  3967. }
  3968. if (!myDecodeObject(
  3969. X509_ASN_ENCODING,
  3970. X509_EXTENSIONS,
  3971. pAttr->rgValue[j].pbData,
  3972. pAttr->rgValue[j].cbData,
  3973. CERTLIB_USE_LOCALALLOC,
  3974. (VOID **) &pExtensions,
  3975. &cb))
  3976. {
  3977. hr = myHLastError();
  3978. _JumpError(hr, error, "myDecodeObject");
  3979. }
  3980. pExt = pExtensions->rgExtension;
  3981. for (k = 0; k < pExtensions->cExtension; k++, pExt++)
  3982. {
  3983. if (0 == strcmp(
  3984. pExt->pszObjId,
  3985. szOID_SUBJECT_KEY_IDENTIFIER))
  3986. {
  3987. if (!myDecodeObject(
  3988. X509_ASN_ENCODING,
  3989. X509_OCTET_STRING,
  3990. pExt->Value.pbData,
  3991. pExt->Value.cbData,
  3992. CERTLIB_USE_LOCALALLOC,
  3993. (VOID **) &pbKeyId,
  3994. &cbKeyId))
  3995. {
  3996. hr = myHLastError();
  3997. _JumpError(hr, error, "myDecodeObject");
  3998. }
  3999. break;
  4000. }
  4001. }
  4002. }
  4003. }
  4004. }
  4005. if (NULL == pbKeyId)
  4006. {
  4007. BYTE abHash[CBMAX_CRYPT_HASH_LEN];
  4008. cbKeyId = sizeof(abHash);
  4009. if (!CryptHashPublicKeyInfo(
  4010. NULL, // hCryptProv
  4011. CALG_SHA1,
  4012. 0, // dwFlags,
  4013. X509_ASN_ENCODING,
  4014. &pRequest->SubjectPublicKeyInfo,
  4015. abHash,
  4016. &cbKeyId))
  4017. {
  4018. hr = myHLastError();
  4019. _JumpError(hr, error, "CryptHashPublicKeyInfo");
  4020. }
  4021. pbKeyId = (BYTE *) LocalAlloc(LMEM_FIXED, cbKeyId);
  4022. if (NULL == pbKeyId)
  4023. {
  4024. hr = E_OUTOFMEMORY;
  4025. _JumpError(hr, error, "LocalAlloc");
  4026. }
  4027. CopyMemory(pbKeyId, abHash, cbKeyId);
  4028. }
  4029. *phProv = hProv;
  4030. hProv = NULL;
  4031. *ppbKeyId = pbKeyId;
  4032. pbKeyId = NULL;
  4033. *pcbKeyId = cbKeyId;
  4034. *pdwKeySpec = dwKeySpec;
  4035. hr = S_OK;
  4036. error:
  4037. if (NULL != hProv && *pfCallerFreeProv)
  4038. {
  4039. CryptReleaseContext(hProv, 0);
  4040. }
  4041. if (NULL != pRequest)
  4042. {
  4043. LocalFree(pRequest);
  4044. }
  4045. if (NULL != pExtensions)
  4046. {
  4047. LocalFree(pExtensions);
  4048. }
  4049. if (NULL != pbKeyId)
  4050. {
  4051. LocalFree(pbKeyId);
  4052. }
  4053. return(hr);
  4054. }
  4055. HRESULT
  4056. BuildNameValuePairs(
  4057. OPTIONAL IN WCHAR const *pwszAttributes,
  4058. IN OUT DWORD *pcValue,
  4059. OPTIONAL OUT CRYPT_ATTR_BLOB *pValue,
  4060. OPTIONAL OUT WCHAR **ppwszTemplateName)
  4061. {
  4062. HRESULT hr;
  4063. DWORD cValue = 0;
  4064. WCHAR *pwszDup = NULL;
  4065. WCHAR *pwszBuf;
  4066. WCHAR const *pwszName;
  4067. WCHAR const *pwszValue;
  4068. WCHAR *pwszTemplateName = NULL;
  4069. if (NULL != ppwszTemplateName)
  4070. {
  4071. *ppwszTemplateName = NULL;
  4072. }
  4073. if (NULL == pwszAttributes)
  4074. {
  4075. hr = S_OK;
  4076. goto error; // silently ignore empty string
  4077. }
  4078. hr = myDupString(pwszAttributes, &pwszDup);
  4079. _JumpIfError(hr, error, "myDupString");
  4080. pwszBuf = pwszDup;
  4081. for (;;)
  4082. {
  4083. hr = myParseNextAttribute(&pwszBuf, FALSE, &pwszName, &pwszValue);
  4084. if (S_FALSE == hr)
  4085. {
  4086. break;
  4087. }
  4088. _JumpIfError(hr, error, "myParseNextAttribute");
  4089. DBGPRINT((DBG_SS_CERTREQI, "'%ws' = '%ws'\n", pwszName, pwszValue));
  4090. if (NULL != pValue)
  4091. {
  4092. CRYPT_ENROLLMENT_NAME_VALUE_PAIR NamePair;
  4093. CSASSERT(cValue < *pcValue);
  4094. NamePair.pwszName = const_cast<WCHAR *>(pwszName);
  4095. NamePair.pwszValue = const_cast<WCHAR *>(pwszValue);
  4096. if (NULL != ppwszTemplateName &&
  4097. 0 == LSTRCMPIS(pwszName, wszPROPCERTTEMPLATE))
  4098. {
  4099. if (NULL != pwszTemplateName)
  4100. {
  4101. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  4102. _JumpError(hr, error, "Duplicate cert template");
  4103. }
  4104. hr = myDupString(pwszValue, &pwszTemplateName);
  4105. _JumpIfError(hr, error, "myDupString");
  4106. }
  4107. if (!myEncodeObject(
  4108. X509_ASN_ENCODING,
  4109. //X509_ENROLLMENT_NAME_VALUE_PAIR,
  4110. szOID_ENROLLMENT_NAME_VALUE_PAIR,
  4111. &NamePair,
  4112. 0,
  4113. CERTLIB_USE_LOCALALLOC,
  4114. &pValue[cValue].pbData,
  4115. &pValue[cValue].cbData))
  4116. {
  4117. hr = myHLastError();
  4118. _JumpError(hr, error, "myEncodeObject");
  4119. }
  4120. }
  4121. cValue++;
  4122. }
  4123. if (NULL != ppwszTemplateName)
  4124. {
  4125. *ppwszTemplateName = pwszTemplateName;
  4126. pwszTemplateName = NULL;
  4127. }
  4128. hr = S_OK;
  4129. error:
  4130. if (NULL != pwszTemplateName)
  4131. {
  4132. LocalFree(pwszTemplateName);
  4133. }
  4134. *pcValue = cValue;
  4135. if (NULL != pwszDup)
  4136. {
  4137. LocalFree(pwszDup);
  4138. }
  4139. return(hr);
  4140. }
  4141. ConvertPolicesToSz(
  4142. IN DWORD cPolicies,
  4143. IN WCHAR const * const *rgpwszPolicies,
  4144. OUT CHAR ***prgpszPolicies)
  4145. {
  4146. HRESULT hr;
  4147. DWORD i;
  4148. DWORD cch = 0;
  4149. CHAR **ppsz;
  4150. CHAR *pch;
  4151. *prgpszPolicies = NULL;
  4152. for (i = 0; i < cPolicies; i++)
  4153. {
  4154. cch += wcslen(rgpwszPolicies[i]) + 1;
  4155. }
  4156. ppsz = (CHAR **) LocalAlloc(
  4157. LMEM_FIXED,
  4158. cch + (cPolicies + 1) * sizeof(CHAR *));
  4159. if (NULL == ppsz)
  4160. {
  4161. hr = E_OUTOFMEMORY;
  4162. _JumpError(hr, error, "LocalAlloc");
  4163. }
  4164. *prgpszPolicies = ppsz;
  4165. pch = (CHAR *) &ppsz[cPolicies + 1];
  4166. for (i = 0; i < cPolicies; i++)
  4167. {
  4168. WCHAR const *pwc;
  4169. *ppsz++ = pch;
  4170. pwc = rgpwszPolicies[i];
  4171. while ('\0' != (*pch++ = (char) *pwc++))
  4172. ;
  4173. }
  4174. *ppsz = NULL;
  4175. hr = S_OK;
  4176. error:
  4177. return(hr);
  4178. }
  4179. HRESULT
  4180. PickCertAndSignRequest(
  4181. IN BYTE const *pbReq,
  4182. IN DWORD cbReq,
  4183. IN BOOL fSkipSignerDeletion,
  4184. OPTIONAL IN WCHAR const *pwszTemplateName,
  4185. OUT BYTE **ppbPKCS7Out,
  4186. OUT DWORD *pcbPKCS7Out)
  4187. {
  4188. HRESULT hr;
  4189. HCERTTYPE hCertType = NULL;
  4190. CERT_CONTEXT const *pCertSigner = NULL;
  4191. WCHAR **rgpwszPolicies = NULL;
  4192. CHAR **rgpszPolicies = NULL;
  4193. WCHAR **ppwsz;
  4194. DWORD cPolicies = 0;
  4195. if (NULL == g_pwszCertCN || !myIsMinusSignString(g_pwszCertCN))
  4196. {
  4197. if (!g_fQuiet || NULL != g_pwszCertCN)
  4198. {
  4199. WCHAR const *pwszCommonName;
  4200. if (NULL != pwszTemplateName)
  4201. {
  4202. hr = CAFindCertTypeByName(
  4203. pwszTemplateName,
  4204. NULL,
  4205. CT_FIND_LOCAL_SYSTEM |
  4206. CT_ENUM_MACHINE_TYPES |
  4207. CT_ENUM_USER_TYPES,
  4208. &hCertType);
  4209. if (S_OK != hr)
  4210. {
  4211. hr = CAFindCertTypeByName(
  4212. pwszTemplateName,
  4213. NULL,
  4214. CT_FIND_LOCAL_SYSTEM |
  4215. CT_ENUM_MACHINE_TYPES |
  4216. CT_ENUM_USER_TYPES |
  4217. CT_FIND_BY_OID,
  4218. &hCertType);
  4219. _PrintIfErrorStr(hr, "CAFindCertTypeByName", pwszTemplateName);
  4220. }
  4221. if (S_OK == hr)
  4222. {
  4223. DWORD cSig;
  4224. hr = CAGetCertTypePropertyEx(
  4225. hCertType,
  4226. CERTTYPE_PROP_RA_SIGNATURE,
  4227. &cSig);
  4228. if (S_OK != hr)
  4229. {
  4230. _PrintError(hr, "CAGetCertTypePropertyEx");
  4231. cSig = 0;
  4232. }
  4233. if (0 != cSig)
  4234. {
  4235. hr = CAGetCertTypePropertyEx(
  4236. hCertType,
  4237. CERTTYPE_PROP_RA_APPLICATION_POLICY,
  4238. &rgpwszPolicies);
  4239. if (S_OK != hr)
  4240. {
  4241. _PrintError(hr, "CAGetCertTypePropertyEx");
  4242. rgpwszPolicies = NULL;
  4243. }
  4244. }
  4245. if (NULL != rgpwszPolicies)
  4246. {
  4247. for (ppwsz = rgpwszPolicies; NULL != *ppwsz; ppwsz++)
  4248. {
  4249. cPolicies++;
  4250. }
  4251. }
  4252. }
  4253. }
  4254. pwszCommonName = NULL;
  4255. if (L'\0' != g_pwszCertCN && 0 != lstrcmp(L"*", g_pwszCertCN))
  4256. {
  4257. pwszCommonName = g_pwszCertCN;
  4258. }
  4259. if (0 != cPolicies)
  4260. {
  4261. hr = ConvertPolicesToSz(
  4262. cPolicies,
  4263. rgpwszPolicies,
  4264. &rgpszPolicies);
  4265. _JumpIfError(hr, error, "ConvertPolicesToSz");
  4266. hr = myGetCertificateFromPicker(
  4267. g_hInstance,
  4268. NULL, // hwndParent
  4269. IDS_GETERACERT_TITLE,
  4270. IDS_GETERACERT_SUBTITLE,
  4271. CUCS_MYSTORE |
  4272. CUCS_PRIVATEKEYREQUIRED |
  4273. CUCS_USAGEREQUIRED |
  4274. (g_fQuiet? CUCS_SILENT : 0),
  4275. pwszCommonName,
  4276. 0, // cStore
  4277. NULL, // rghStore
  4278. cPolicies, // cpszObjId
  4279. rgpszPolicies, // apszObjId
  4280. &pCertSigner);
  4281. _JumpIfError(hr, error, "myGetCertificateFromPicker");
  4282. }
  4283. else
  4284. {
  4285. hr = myGetERACertificateFromPicker(
  4286. g_hInstance,
  4287. NULL, // hwndParent
  4288. IDS_GETERACERT_TITLE,
  4289. IDS_GETERACERT_SUBTITLE,
  4290. pwszCommonName,
  4291. g_fQuiet,
  4292. &pCertSigner);
  4293. _JumpIfError(hr, error, "myGetERACertificateFromPicker");
  4294. }
  4295. }
  4296. // pCertSigner is NULL if the user cancelled out of the cert picker U/I.
  4297. // NULL pCertSigner means delete existing signatures.
  4298. if (NULL == pCertSigner)
  4299. {
  4300. if (fSkipSignerDeletion)
  4301. {
  4302. hr = S_FALSE;
  4303. _JumpError2(hr, error, "no signer selected", S_FALSE);
  4304. }
  4305. if (g_fQuiet || NULL != g_pwszCertCN)
  4306. {
  4307. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  4308. _JumpError(hr, error, "no matching signer CN");
  4309. }
  4310. }
  4311. else
  4312. {
  4313. DWORD dwCertValidityFlags;
  4314. // be sure the cert picked isn't already expired - that'd be silly
  4315. dwCertValidityFlags = CERT_STORE_TIME_VALIDITY_FLAG;
  4316. if (!CertVerifySubjectCertificateContext(
  4317. pCertSigner,
  4318. NULL,
  4319. &dwCertValidityFlags))
  4320. {
  4321. hr = myHLastError();
  4322. _JumpIfError(hr, error, "CertVerifySubjectCertificateContext");
  4323. }
  4324. if (0 != dwCertValidityFlags)
  4325. {
  4326. hr = HRESULT_FROM_WIN32(CERT_E_EXPIRED);
  4327. _JumpError(hr, error, "CertVerifySubjectCertificateContext");
  4328. }
  4329. }
  4330. }
  4331. hr = SignCMCContent(
  4332. pCertSigner,
  4333. szOID_CT_PKI_DATA,
  4334. pbReq,
  4335. cbReq,
  4336. 0 != (CR_OUT_CRLS & g_dwCRLOut),
  4337. ppbPKCS7Out,
  4338. pcbPKCS7Out);
  4339. _JumpIfError(hr, error, "SignCMCContent");
  4340. error:
  4341. if (NULL != rgpwszPolicies)
  4342. {
  4343. CAFreeCertTypeProperty(hCertType, rgpwszPolicies);
  4344. }
  4345. if (NULL != rgpszPolicies)
  4346. {
  4347. LocalFree(rgpszPolicies);
  4348. }
  4349. if (NULL != hCertType)
  4350. {
  4351. CACloseCertType(hCertType);
  4352. }
  4353. if (NULL != pCertSigner)
  4354. {
  4355. CertFreeCertificateContext(pCertSigner);
  4356. }
  4357. return(hr);
  4358. }
  4359. HRESULT
  4360. SignQualifiedRequest(
  4361. IN HWND hWndOwner,
  4362. IN WCHAR const *pwszfnReq,
  4363. OPTIONAL IN WCHAR const *pwszfnOut)
  4364. {
  4365. HRESULT hr;
  4366. BYTE *pbReq = NULL;
  4367. DWORD cbReq;
  4368. BYTE *pbPKCS7Out = NULL;
  4369. DWORD cbPKCS7Out;
  4370. LONG dwFlags;
  4371. BOOL fSigned;
  4372. WCHAR *pwszTemplateName = NULL;
  4373. // Read the request from a file, convert it to binary, and return
  4374. // dwFlags to indicate the orignal encoding and the detected format.
  4375. hr = CheckRequestType(
  4376. pwszfnReq,
  4377. &pbReq,
  4378. &cbReq,
  4379. &dwFlags,
  4380. &fSigned,
  4381. NULL, // pfCA
  4382. &pwszTemplateName);
  4383. _JumpIfError(hr, error, "CheckRequestType");
  4384. if (CR_IN_CMC != (CR_IN_FORMATMASK & dwFlags))
  4385. {
  4386. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  4387. SetErrorString(pwszfnReq);
  4388. _JumpError(hr, error, "not a CMC request");
  4389. }
  4390. hr = PickCertAndSignRequest(
  4391. pbReq,
  4392. cbReq,
  4393. FALSE,
  4394. pwszTemplateName,
  4395. &pbPKCS7Out,
  4396. &cbPKCS7Out);
  4397. _JumpIfError(hr, error, "PickCertAndSignRequest");
  4398. hr = WriteCertificateOrRequest(
  4399. hWndOwner,
  4400. NULL, // pdiRequest
  4401. pbPKCS7Out,
  4402. cbPKCS7Out,
  4403. g_dwOutFormat,
  4404. IDS_REQUEST_OUTFILE_TITLE,
  4405. IDS_REQUEST_FILE_FILTER,
  4406. IDS_REQUEST_FILE_DEFEXT,
  4407. pwszfnOut);
  4408. _JumpIfError(hr, error, "WriteCertificateOrRequest");
  4409. error:
  4410. if (NULL != pwszTemplateName)
  4411. {
  4412. LocalFree(pwszTemplateName);
  4413. }
  4414. if (NULL != pbReq)
  4415. {
  4416. LocalFree(pbReq);
  4417. }
  4418. if (NULL != pbPKCS7Out)
  4419. {
  4420. LocalFree(pbPKCS7Out);
  4421. }
  4422. return(hr);
  4423. }
  4424. HRESULT
  4425. ParseRequestInfo(
  4426. OPTIONAL IN WCHAR const *pwszAttributes,
  4427. IN WCHAR const *pwszfnPolicy,
  4428. OPTIONAL OUT INFVALUES **prgInfValues,
  4429. OPTIONAL OUT DWORD *pcInfValues,
  4430. OUT CRYPT_ATTRIBUTES **prgAttributes,
  4431. OUT DWORD *pcAttributes,
  4432. OUT CERT_EXTENSION **prgExt,
  4433. OUT DWORD *pcExt,
  4434. OUT WCHAR **ppwszTemplateName)
  4435. {
  4436. HRESULT hr;
  4437. CERT_EXTENSION *rgExtT;
  4438. CERT_EXTENSION *rgExt = NULL;
  4439. DWORD cExt;
  4440. CRYPT_ATTR_BLOB *argValue[2] = { NULL, NULL };
  4441. DWORD acValue[2];
  4442. DWORD i;
  4443. DWORD j;
  4444. CRYPT_ATTRIBUTES *rgAttributes = NULL;
  4445. DWORD cAttributes = 0;
  4446. WCHAR *pwszTemplateNameInf = NULL;
  4447. WCHAR *pwszTemplateName = NULL;
  4448. HCERTTYPE hCertType = NULL;
  4449. CERT_EXTENSIONS *pExtensions = NULL;
  4450. if (NULL != prgInfValues)
  4451. {
  4452. *prgInfValues = NULL;
  4453. }
  4454. if (NULL != pcInfValues)
  4455. {
  4456. *pcInfValues = 0;
  4457. }
  4458. *prgAttributes = NULL;
  4459. *pcAttributes = 0;
  4460. *prgExt = NULL;
  4461. *pcExt = 0;
  4462. *ppwszTemplateName = NULL;
  4463. hr = ParseInfFile(
  4464. pwszfnPolicy,
  4465. prgInfValues,
  4466. pcInfValues,
  4467. &argValue[0],
  4468. &acValue[0],
  4469. &rgExt,
  4470. &cExt,
  4471. &pwszTemplateNameInf);
  4472. if (S_OK != hr)
  4473. {
  4474. SetErrorString(pwszfnPolicy);
  4475. _JumpError(hr, error, "ParseInfFile");
  4476. }
  4477. if (0 != acValue[0])
  4478. {
  4479. cAttributes++;
  4480. }
  4481. // Count the command line request attributes
  4482. hr = BuildNameValuePairs(pwszAttributes, &acValue[1], NULL, NULL);
  4483. _JumpIfError(hr, error, "BuildNameValuePairs");
  4484. if (0 != acValue[1])
  4485. {
  4486. cAttributes++;
  4487. argValue[1] = (CRYPT_ATTR_BLOB *) LocalAlloc(
  4488. LMEM_FIXED | LMEM_ZEROINIT,
  4489. acValue[1] * sizeof(argValue[1][0]));
  4490. if (NULL == argValue[1])
  4491. {
  4492. hr = E_OUTOFMEMORY;
  4493. _JumpError(hr, error, "LocalAlloc");
  4494. }
  4495. hr = BuildNameValuePairs(
  4496. pwszAttributes,
  4497. &acValue[1],
  4498. argValue[1],
  4499. &pwszTemplateName);
  4500. _JumpIfError(hr, error, "BuildNameValuePairs");
  4501. }
  4502. if (0 != cAttributes)
  4503. {
  4504. rgAttributes = (CRYPT_ATTRIBUTES *) LocalAlloc(
  4505. LMEM_FIXED | LMEM_ZEROINIT,
  4506. cAttributes * sizeof(rgAttributes[0]));
  4507. if (NULL == rgAttributes)
  4508. {
  4509. hr = E_OUTOFMEMORY;
  4510. _JumpError(hr, error, "LocalAlloc");
  4511. }
  4512. for (i = j = 0; i < cAttributes; i++, j++)
  4513. {
  4514. CRYPT_ATTRIBUTE *rgAttr;
  4515. rgAttr = (CRYPT_ATTRIBUTE *) LocalAlloc(
  4516. LMEM_FIXED | LMEM_ZEROINIT,
  4517. sizeof(rgAttributes[i].rgAttr[0]));
  4518. if (NULL == rgAttr)
  4519. {
  4520. hr = E_OUTOFMEMORY;
  4521. _JumpError(hr, error, "LocalAlloc");
  4522. }
  4523. while (0 == acValue[j])
  4524. {
  4525. j++;
  4526. }
  4527. rgAttributes[i].cAttr = 1;
  4528. rgAttributes[i].rgAttr = rgAttr;
  4529. rgAttr[0].pszObjId = szOID_ENROLLMENT_NAME_VALUE_PAIR;
  4530. rgAttr[0].cValue = acValue[j];
  4531. rgAttr[0].rgValue = argValue[j];
  4532. argValue[j] = NULL;
  4533. }
  4534. }
  4535. if (NULL != pwszTemplateName || NULL != pwszTemplateNameInf)
  4536. {
  4537. WCHAR const *pwsz;
  4538. pwsz = pwszTemplateNameInf;
  4539. if (NULL == pwsz)
  4540. {
  4541. pwsz = pwszTemplateName;
  4542. CSASSERT(NULL != pwsz);
  4543. }
  4544. else if (NULL != pwszTemplateName &&
  4545. 0 != mylstrcmpiL(pwszTemplateName, pwszTemplateNameInf))
  4546. {
  4547. hr = CERTSRV_E_TEMPLATE_CONFLICT;
  4548. SetErrorString(wszPROPCERTTEMPLATE);
  4549. _JumpError(hr, error, "Template name conflict");
  4550. }
  4551. // Include the specified cert template's extensions
  4552. hr = CAFindCertTypeByName(
  4553. pwsz,
  4554. NULL,
  4555. CT_FIND_LOCAL_SYSTEM |
  4556. CT_ENUM_MACHINE_TYPES |
  4557. CT_ENUM_USER_TYPES,
  4558. &hCertType);
  4559. if (S_OK != hr)
  4560. {
  4561. hr = CAFindCertTypeByName(
  4562. pwsz,
  4563. NULL,
  4564. CT_FIND_LOCAL_SYSTEM |
  4565. CT_ENUM_MACHINE_TYPES |
  4566. CT_ENUM_USER_TYPES |
  4567. CT_FIND_BY_OID,
  4568. &hCertType);
  4569. _PrintIfErrorStr(hr, "CAFindCertTypeByName", pwsz);
  4570. }
  4571. if (S_OK == hr)
  4572. {
  4573. hr = CAGetCertTypeExtensions(hCertType, &pExtensions);
  4574. _PrintIfError(hr, "CAGetCertTypeExtensions");
  4575. }
  4576. if (S_OK == hr && NULL != pExtensions && 0 != pExtensions->cExtension)
  4577. {
  4578. CERT_EXTENSION *pExtSrc;
  4579. CERT_EXTENSION *pExtSrcEnd;
  4580. CERT_EXTENSION *pExtDst;
  4581. rgExtT = (CERT_EXTENSION *) LocalAlloc(
  4582. LMEM_FIXED | LMEM_ZEROINIT,
  4583. (pExtensions->cExtension + cExt) * sizeof(rgExtT[0]));
  4584. if (NULL == rgExtT)
  4585. {
  4586. hr = E_OUTOFMEMORY;
  4587. _JumpError(hr, error, "LocalAlloc");
  4588. }
  4589. if (NULL != rgExt)
  4590. {
  4591. CopyMemory(&rgExtT[0], &rgExt[0], cExt * sizeof(rgExtT[0]));
  4592. LocalFree(rgExt);
  4593. }
  4594. rgExt = rgExtT;
  4595. pExtSrc = pExtensions->rgExtension;
  4596. pExtSrcEnd = &pExtSrc[pExtensions->cExtension];
  4597. pExtDst = &rgExt[cExt];
  4598. for ( ; pExtSrc < pExtSrcEnd; pExtSrc++, pExtDst++)
  4599. {
  4600. pExtDst->fCritical = pExtSrc->fCritical;
  4601. pExtDst->Value.cbData = pExtSrc->Value.cbData;
  4602. hr = myDupStringA(pExtSrc->pszObjId, &pExtDst->pszObjId);
  4603. _JumpIfError(hr, error, "myDupStringA");
  4604. pExtDst->Value.pbData = (BYTE *) LocalAlloc(
  4605. LMEM_FIXED,
  4606. pExtSrc->Value.cbData);
  4607. if (NULL == pExtDst->Value.pbData)
  4608. {
  4609. hr = E_OUTOFMEMORY;
  4610. _JumpError(hr, error, "LocalAlloc");
  4611. }
  4612. CopyMemory(
  4613. pExtDst->Value.pbData,
  4614. pExtSrc->Value.pbData,
  4615. pExtSrc->Value.cbData);
  4616. }
  4617. cExt += pExtensions->cExtension;
  4618. }
  4619. else
  4620. {
  4621. CHAR const *pszObjId;
  4622. // Grow extension array to make room for the cert type extension
  4623. rgExtT = (CERT_EXTENSION *) LocalAlloc(
  4624. LMEM_FIXED | LMEM_ZEROINIT,
  4625. (cExt + 1) * sizeof(rgExtT[0]));
  4626. if (NULL == rgExtT)
  4627. {
  4628. hr = E_OUTOFMEMORY;
  4629. _JumpError(hr, error, "LocalAlloc");
  4630. }
  4631. if (0 != cExt)
  4632. {
  4633. CSASSERT(NULL != rgExt);
  4634. CopyMemory(&rgExtT[1], rgExt, cExt * sizeof(rgExt[0]));
  4635. LocalFree(rgExt);
  4636. }
  4637. rgExt = rgExtT;
  4638. cExt++;
  4639. hr = myBuildCertTypeExtension(pwsz, &rgExt[0]);
  4640. _JumpIfError(hr, error, "myBuildCertTypeExtension");
  4641. pszObjId = rgExt[0].pszObjId;
  4642. rgExt[0].pszObjId = NULL;
  4643. hr = myDupStringA(pszObjId, &rgExt[0].pszObjId);
  4644. _JumpIfError(hr, error, "myDupStringA");
  4645. }
  4646. }
  4647. myPackExtensionArray(TRUE, &cExt, &rgExt);
  4648. *prgAttributes = rgAttributes;
  4649. rgAttributes = NULL;
  4650. *pcAttributes = cAttributes;
  4651. *prgExt = rgExt;
  4652. rgExt = NULL;
  4653. *pcExt = cExt;
  4654. if (NULL != pwszTemplateNameInf)
  4655. {
  4656. *ppwszTemplateName = pwszTemplateNameInf;
  4657. pwszTemplateNameInf = NULL;
  4658. }
  4659. else
  4660. if (NULL != pwszTemplateName)
  4661. {
  4662. *ppwszTemplateName = pwszTemplateName;
  4663. pwszTemplateName = NULL;
  4664. }
  4665. hr = S_OK;
  4666. error:
  4667. if (S_OK != hr && NULL != prgInfValues)
  4668. {
  4669. myInfFreeSectionValues(*pcInfValues, *prgInfValues);
  4670. *prgInfValues = NULL;
  4671. *pcInfValues = 0;
  4672. }
  4673. if (NULL != rgAttributes)
  4674. {
  4675. FreeAttributes(cAttributes, rgAttributes);
  4676. }
  4677. for (i = 0; i < ARRAYSIZE(argValue); i++)
  4678. {
  4679. if (NULL != argValue[i])
  4680. {
  4681. myInfFreeRequestAttributes(acValue[i], argValue[i]);
  4682. }
  4683. }
  4684. if (NULL != rgExt)
  4685. {
  4686. FreeExtensions(TRUE, cExt, rgExt);
  4687. }
  4688. if (NULL != pwszTemplateNameInf)
  4689. {
  4690. LocalFree(pwszTemplateNameInf);
  4691. }
  4692. if (NULL != pwszTemplateName)
  4693. {
  4694. LocalFree(pwszTemplateName);
  4695. }
  4696. if (NULL != hCertType)
  4697. {
  4698. if (NULL != pExtensions)
  4699. {
  4700. CAFreeCertTypeExtensions(hCertType, pExtensions);
  4701. }
  4702. CACloseCertType(hCertType);
  4703. }
  4704. return(hr);
  4705. }
  4706. HRESULT
  4707. CreateQualifiedRequest(
  4708. IN HWND hWndOwner,
  4709. OPTIONAL IN WCHAR const *pwszAttributes,
  4710. IN WCHAR const *pwszfnReq,
  4711. IN WCHAR const *pwszfnPolicy,
  4712. OPTIONAL IN WCHAR const *pwszfnOut,
  4713. OPTIONAL IN WCHAR const *pwszfnPKCS10)
  4714. {
  4715. HRESULT hr;
  4716. BYTE *pbReq = NULL;
  4717. DWORD cbReq;
  4718. BYTE *pbKeyId = NULL;
  4719. DWORD cbKeyId = 0;
  4720. BYTE *pbReqCMCFirstSigned = NULL;
  4721. DWORD cbReqCMCFirstSigned;
  4722. BYTE *pbReqCMCOut = NULL;
  4723. DWORD cbReqCMCOut;
  4724. LONG dwFlags;
  4725. BOOL fNestedCMCRequest = FALSE;
  4726. BOOL fSigned;
  4727. CRYPT_ATTRIBUTES *rgAttributes = NULL;
  4728. DWORD cAttributes;
  4729. CERT_EXTENSION *rgExt = NULL;
  4730. DWORD cExt;
  4731. WCHAR *pwszTemplateName = NULL;
  4732. WCHAR *pwszTemplateNameRequest = NULL;
  4733. HCRYPTPROV hProv = NULL;
  4734. DWORD dwKeySpec = 0;
  4735. BOOL fCallerFreeProv;
  4736. BOOL fCA;
  4737. cAttributes = 0;
  4738. cExt = 0;
  4739. fCallerFreeProv = FALSE;
  4740. // Read the request from a file, convert it to binary, and return
  4741. // dwFlags to indicate the orignal encoding and the detected format.
  4742. hr = CheckRequestType(
  4743. pwszfnReq,
  4744. &pbReq,
  4745. &cbReq,
  4746. &dwFlags,
  4747. &fSigned,
  4748. &fCA,
  4749. &pwszTemplateNameRequest);
  4750. _JumpIfError(hr, error, "CheckRequestType");
  4751. hr = ParseRequestInfo(
  4752. pwszAttributes,
  4753. pwszfnPolicy,
  4754. NULL, // prgInfValues
  4755. NULL, // pcInfValues
  4756. &rgAttributes,
  4757. &cAttributes,
  4758. &rgExt,
  4759. &cExt,
  4760. &pwszTemplateName);
  4761. if (S_OK != hr)
  4762. {
  4763. SetErrorString(pwszfnPolicy);
  4764. _JumpError(hr, error, "ParseRequestInfo");
  4765. }
  4766. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  4767. switch (CR_IN_FORMATMASK & dwFlags)
  4768. {
  4769. case CR_IN_CMC:
  4770. fNestedCMCRequest = TRUE;
  4771. break;
  4772. case CR_IN_CERT:
  4773. hr = ConvertCertToPKCS10Request(
  4774. NULL != pwszTemplateName?
  4775. pwszTemplateName : pwszTemplateNameRequest,
  4776. &fCA,
  4777. rgExt,
  4778. cExt,
  4779. &pbReq,
  4780. &cbReq);
  4781. _JumpIfError(hr, error, "ConvertCertToPKCS10Request");
  4782. if (NULL != rgExt)
  4783. {
  4784. FreeExtensions(TRUE, cExt, rgExt);
  4785. rgExt = NULL;
  4786. cExt = 0;
  4787. }
  4788. dwFlags = CR_IN_PKCS10 | (~CR_IN_FORMATMASK & dwFlags);
  4789. break;
  4790. case CR_IN_PKCS10:
  4791. break;
  4792. default:
  4793. _JumpError(hr, error, "not a CMC or PKCS10 request");
  4794. }
  4795. fCallerFreeProv = FALSE;
  4796. if (CR_IN_PKCS10 == (CR_IN_FORMATMASK & dwFlags))
  4797. {
  4798. if (NULL != pwszfnPKCS10)
  4799. {
  4800. hr = crOverwriteFileAllowed(hWndOwner, pwszfnPKCS10);
  4801. _JumpIfError(hr, error, "crOverwriteFileAllowed");
  4802. hr = EncodeToFileW(
  4803. pwszfnPKCS10,
  4804. pbReq,
  4805. cbReq,
  4806. DECF_FORCEOVERWRITE | g_dwOutFormat);
  4807. if (S_OK != hr)
  4808. {
  4809. SetErrorString(pwszfnPKCS10);
  4810. _JumpErrorStr(hr, error, "EncodeToFileW", pwszfnPKCS10);
  4811. }
  4812. }
  4813. hr = GetPKCS10PrivateKey(
  4814. pbReq,
  4815. cbReq,
  4816. &hProv,
  4817. &dwKeySpec,
  4818. &fCallerFreeProv,
  4819. &pbKeyId,
  4820. &cbKeyId);
  4821. _PrintIfError(hr, "GetPKCS10PrivateKey");
  4822. }
  4823. if (fCA)
  4824. {
  4825. hr = AddCAExtensions(&rgExt, &cExt);
  4826. _JumpIfError(hr, error, "AddCAExtensions");
  4827. }
  4828. hr = BuildCMCRequest(
  4829. XECI_CERTREQ,
  4830. fNestedCMCRequest,
  4831. pbReq,
  4832. cbReq,
  4833. rgExt,
  4834. cExt,
  4835. rgAttributes,
  4836. cAttributes,
  4837. NULL, // rgAttributeUnauth
  4838. 0, // cAttributeUnauth
  4839. pbKeyId,
  4840. cbKeyId,
  4841. hProv,
  4842. dwKeySpec,
  4843. NULL == hProv? NULL : g_pszObjIdHash,
  4844. NULL, // pCertSigner
  4845. NULL, // hProvSigner
  4846. 0, // dwKeySpecSigner
  4847. NULL, // pszObjIdHashSigner
  4848. &pbReqCMCFirstSigned,
  4849. &cbReqCMCFirstSigned);
  4850. _JumpIfError(hr, error, "BuildCMCRequest");
  4851. hr = PickCertAndSignRequest(
  4852. pbReqCMCFirstSigned,
  4853. cbReqCMCFirstSigned,
  4854. TRUE,
  4855. NULL != pwszTemplateName?
  4856. pwszTemplateName : pwszTemplateNameRequest,
  4857. &pbReqCMCOut,
  4858. &cbReqCMCOut);
  4859. if (S_OK != hr)
  4860. {
  4861. _PrintError2(hr, "PickCertAndSignRequest", S_FALSE);
  4862. if (S_FALSE != hr)
  4863. {
  4864. goto error;
  4865. }
  4866. // The user cancelled out of the cert picker U/I, so just save the
  4867. // unsigned request.
  4868. pbReqCMCOut = pbReqCMCFirstSigned;
  4869. cbReqCMCOut = cbReqCMCFirstSigned;
  4870. }
  4871. hr = WriteCertificateOrRequest(
  4872. hWndOwner,
  4873. NULL, // pdiRequest
  4874. pbReqCMCOut,
  4875. cbReqCMCOut,
  4876. g_dwOutFormat,
  4877. IDS_REQUEST_OUTFILE_TITLE,
  4878. IDS_REQUEST_FILE_FILTER,
  4879. IDS_REQUEST_FILE_DEFEXT,
  4880. pwszfnOut);
  4881. _JumpIfError(hr, error, "WriteCertificateOrRequest");
  4882. error:
  4883. if (NULL != hProv && fCallerFreeProv)
  4884. {
  4885. CryptReleaseContext(hProv, 0);
  4886. }
  4887. if (NULL != pwszTemplateNameRequest)
  4888. {
  4889. LocalFree(pwszTemplateNameRequest);
  4890. }
  4891. if (NULL != pwszTemplateName)
  4892. {
  4893. LocalFree(pwszTemplateName);
  4894. }
  4895. if (NULL != rgExt)
  4896. {
  4897. FreeExtensions(TRUE, cExt, rgExt);
  4898. }
  4899. if (NULL != rgAttributes)
  4900. {
  4901. FreeAttributes(cAttributes, rgAttributes);
  4902. }
  4903. if (NULL != pbReqCMCOut && pbReqCMCFirstSigned != pbReqCMCOut)
  4904. {
  4905. LocalFree(pbReqCMCOut);
  4906. }
  4907. if (NULL != pbReqCMCFirstSigned)
  4908. {
  4909. LocalFree(pbReqCMCFirstSigned);
  4910. }
  4911. if (NULL != pbKeyId)
  4912. {
  4913. LocalFree(pbKeyId);
  4914. }
  4915. if (NULL != pbReq)
  4916. {
  4917. LocalFree(pbReq);
  4918. }
  4919. return(hr);
  4920. }
  4921. HRESULT
  4922. GetCAXchgCert(
  4923. IN WCHAR const *pwszValue,
  4924. OUT CERT_CONTEXT const **ppccXchg)
  4925. {
  4926. HRESULT hr;
  4927. BOOL fEnabled;
  4928. BSTR strConfig = NULL;
  4929. BSTR strCert = NULL;
  4930. WCHAR const *pwszConfig;
  4931. DISPATCHINTERFACE diRequest;
  4932. BOOL fMustRelease = FALSE;
  4933. *ppccXchg = NULL;
  4934. hr = myInfParseBooleanValue(pwszValue, &fEnabled);
  4935. _JumpIfError(hr, error, "myInfParseBooleanValue");
  4936. if (fEnabled)
  4937. {
  4938. pwszConfig = g_pwszConfig;
  4939. if (NULL == pwszConfig)
  4940. {
  4941. hr = crGetConfig(&strConfig);
  4942. _JumpIfError(hr, error, "crGetConfig");
  4943. pwszConfig = strConfig;
  4944. }
  4945. hr = Request_Init(g_fIDispatch, &diRequest);
  4946. if (S_OK != hr)
  4947. {
  4948. _PrintError(hr, "Request_Init");
  4949. if (E_ACCESSDENIED == hr) // try for a clearer error message
  4950. {
  4951. hr = CO_E_REMOTE_COMMUNICATION_FAILURE;
  4952. }
  4953. _JumpError(hr, error, "Request_Init");
  4954. }
  4955. fMustRelease = TRUE;
  4956. hr = Request2_GetCAProperty(
  4957. &diRequest,
  4958. pwszConfig,
  4959. CR_PROP_CAXCHGCERT,
  4960. 0, // Index
  4961. PROPTYPE_BINARY,
  4962. CV_OUT_BINARY,
  4963. (VOID *) &strCert);
  4964. _JumpIfError(hr, error, "Request2_GetCAProperty");
  4965. *ppccXchg = CertCreateCertificateContext(
  4966. X509_ASN_ENCODING,
  4967. (BYTE const *) strCert,
  4968. SysStringByteLen(strCert));
  4969. if (NULL == *ppccXchg)
  4970. {
  4971. hr = myHLastError();
  4972. _JumpError(hr, error, "CertCreateCertificateContext");
  4973. }
  4974. }
  4975. hr = S_OK;
  4976. error:
  4977. if (NULL != strConfig)
  4978. {
  4979. SysFreeString(strConfig);
  4980. }
  4981. if (NULL != strCert)
  4982. {
  4983. SysFreeString(strCert);
  4984. }
  4985. if (fMustRelease)
  4986. {
  4987. Request_Release(&diRequest);
  4988. }
  4989. return(hr);
  4990. }
  4991. HRESULT
  4992. GetRenewalCert(
  4993. IN WCHAR const *pwszValue,
  4994. OUT CERT_CONTEXT const **ppccRenewal)
  4995. {
  4996. HRESULT hr;
  4997. BSTR strConfig = NULL;
  4998. BSTR strCert = NULL;
  4999. DISPATCHINTERFACE diRequest;
  5000. BOOL fMustRelease = FALSE;
  5001. *ppccRenewal = NULL;
  5002. hr = myGetCertificateFromPicker(
  5003. g_hInstance,
  5004. NULL, // hwndParent
  5005. IDS_GETRENEWALCERT_TITLE,
  5006. IDS_GETRENEWALCERT_SUBTITLE,
  5007. CUCS_MYSTORE |
  5008. CUCS_MACHINESTORE | CUCS_USERSTORE |
  5009. CUCS_DSSTORE |
  5010. CUCS_PRIVATEKEYREQUIRED |
  5011. (g_fVerbose? CUCS_ARCHIVED : 0) |
  5012. (g_fQuiet? CUCS_SILENT : 0),
  5013. (L'\0' == pwszValue || 0 == lstrcmp(L"*", pwszValue))?
  5014. NULL : pwszValue, // pwszCommonName
  5015. 0, // cStore
  5016. NULL, // rghStore
  5017. 0, // cpszObjId
  5018. NULL, // apszObjId
  5019. ppccRenewal);
  5020. _JumpIfError(hr, error, "myGetCertificateFromPicker");
  5021. if (NULL == *ppccRenewal)
  5022. {
  5023. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  5024. _JumpError(hr, error, "myGetCertificateFromPicker");
  5025. }
  5026. error:
  5027. if (NULL != strConfig)
  5028. {
  5029. SysFreeString(strConfig);
  5030. }
  5031. if (NULL != strCert)
  5032. {
  5033. SysFreeString(strCert);
  5034. }
  5035. if (fMustRelease)
  5036. {
  5037. Request_Release(&diRequest);
  5038. }
  5039. return(hr);
  5040. }
  5041. HRESULT
  5042. CreateNewRequest(
  5043. IN HWND hWndOwner,
  5044. OPTIONAL IN WCHAR const *pwszAttributes,
  5045. IN WCHAR const *pwszfnPolicy,
  5046. OPTIONAL IN WCHAR const *pwszfnOut)
  5047. {
  5048. HRESULT hr;
  5049. BOOL fCoInit = FALSE;
  5050. IEnroll4 *pEnroll = NULL;
  5051. CRYPT_DATA_BLOB blobRequest;
  5052. WCHAR *pwszObjId = NULL;
  5053. DWORD cInfValues;
  5054. INFVALUES *rgInfValues = NULL;
  5055. CRYPT_ATTRIBUTES *rgAttributes = NULL;
  5056. DWORD cAttributes;
  5057. CERT_EXTENSION *rgExt = NULL;
  5058. WCHAR *pwszTemplateName = NULL;
  5059. CERT_CONTEXT const *pccXchg = NULL;
  5060. CERT_CONTEXT const *pccRenewal = NULL;
  5061. CERT_CONTEXT const *pccSigner = NULL;
  5062. CERT_NAME_BLOB NameBlob;
  5063. WCHAR *pwszDN = NULL;
  5064. DWORD cExt = 0;
  5065. DWORD i;
  5066. DWORD j;
  5067. DWORD k;
  5068. DWORD RequestTypeFlags;
  5069. BOOL fRequestTypeSet;
  5070. BOOL fKeyUsageSet;
  5071. blobRequest.pbData = NULL;
  5072. NameBlob.pbData = NULL;
  5073. cAttributes = 0;
  5074. hr = ParseRequestInfo(
  5075. pwszAttributes,
  5076. pwszfnPolicy,
  5077. &rgInfValues,
  5078. &cInfValues,
  5079. &rgAttributes,
  5080. &cAttributes,
  5081. &rgExt,
  5082. &cExt,
  5083. &pwszTemplateName);
  5084. if (S_OK != hr)
  5085. {
  5086. SetErrorString(pwszfnPolicy);
  5087. _JumpError(hr, error, "ParseRequestInfo");
  5088. }
  5089. hr = CoInitialize(NULL);
  5090. if (S_OK != hr && S_FALSE != hr)
  5091. {
  5092. _JumpError(hr, error, "CoInitialize");
  5093. }
  5094. fCoInit = TRUE;
  5095. hr = CoCreateInstance(
  5096. CLSID_CEnroll,
  5097. NULL, // pUnkOuter
  5098. CLSCTX_INPROC_SERVER,
  5099. IID_IEnroll4,
  5100. (VOID **) &pEnroll);
  5101. _JumpIfError(hr, error, "CoCreateInstance");
  5102. fKeyUsageSet = FALSE;
  5103. fRequestTypeSet = FALSE;
  5104. RequestTypeFlags = XECR_PKCS10_V2_0;
  5105. for (i = 0; i < cInfValues; i++)
  5106. {
  5107. INFVALUES *pInfValues = &rgInfValues[i];
  5108. WCHAR const *pwszInfValue;
  5109. LONG lFlagsT;
  5110. BOOL fT;
  5111. BOOL fValid;
  5112. if (1 != pInfValues->cValues)
  5113. {
  5114. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  5115. SetErrorStringInf(pwszfnPolicy, pInfValues);
  5116. _JumpError(hr, error, "Wrong value count");
  5117. }
  5118. pwszInfValue = pInfValues->rgpwszValues[0];
  5119. if (NULL == pwszDN &&
  5120. 0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_SUBJECT))
  5121. {
  5122. // Reverse the name for XEnroll!?
  5123. hr = myCertStrToName(
  5124. X509_ASN_ENCODING,
  5125. pwszInfValue, // pszX500
  5126. 0, // CERT_NAME_STR_REVERSE_FLAG,
  5127. NULL, // pvReserved
  5128. &NameBlob.pbData,
  5129. &NameBlob.cbData,
  5130. NULL); // ppszError
  5131. _JumpIfError(hr, error, "myCertStrToName");
  5132. hr = myCertNameToStr(
  5133. X509_ASN_ENCODING,
  5134. &NameBlob,
  5135. CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
  5136. &pwszDN);
  5137. _JumpIfError(hr, error, "myCertNameToStr");
  5138. }
  5139. else
  5140. if (NULL == pccXchg &&
  5141. 0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_PRIVATEKEYARCHIVE))
  5142. {
  5143. hr = GetCAXchgCert(pwszInfValue, &pccXchg);
  5144. _JumpIfError(hr, error, "GetCAXchgCert");
  5145. }
  5146. else
  5147. if (NULL == pccRenewal &&
  5148. 0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_RENEWALCERT))
  5149. {
  5150. hr = GetRenewalCert(pwszInfValue, &pccRenewal);
  5151. _JumpIfError(hr, error, "GetRenewalCert");
  5152. }
  5153. else
  5154. if (0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_KEYSPEC))
  5155. {
  5156. DWORD dwKeySpec;
  5157. dwKeySpec = myWtoI(pwszInfValue, &fValid);
  5158. if (!fValid ||
  5159. (AT_SIGNATURE != dwKeySpec && AT_KEYEXCHANGE != dwKeySpec))
  5160. {
  5161. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  5162. SetErrorStringInf(pwszfnPolicy, pInfValues);
  5163. _JumpError(hr, error, "Bad KeySpec value");
  5164. }
  5165. hr = pEnroll->put_KeySpec(dwKeySpec);
  5166. _JumpIfError(hr, error, "put_KeySpec");
  5167. }
  5168. else
  5169. if (0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_KEYLENGTH))
  5170. {
  5171. DWORD dwKeyLength;
  5172. dwKeyLength = myWtoI(pwszInfValue, &fValid);
  5173. if (!fValid || 0 == dwKeyLength || 64 * 1024 <= dwKeyLength)
  5174. {
  5175. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  5176. SetErrorStringInf(pwszfnPolicy, pInfValues);
  5177. _JumpError(hr, error, "Bad KeyLength value");
  5178. }
  5179. hr = pEnroll->get_GenKeyFlags(&lFlagsT);
  5180. _JumpIfError(hr, error, "get_GenKeyFlags");
  5181. lFlagsT &= ~KEY_LENGTH_MASK;
  5182. lFlagsT |= dwKeyLength << 16;
  5183. hr = pEnroll->put_GenKeyFlags(lFlagsT);
  5184. _JumpIfError(hr, error, "put_GenKeyFlags");
  5185. }
  5186. else
  5187. if (0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_EXPORTABLE))
  5188. {
  5189. hr = myInfParseBooleanValue(pwszInfValue, &fT);
  5190. _JumpIfError(hr, error, "myInfParseBooleanValue");
  5191. hr = pEnroll->get_GenKeyFlags(&lFlagsT);
  5192. _JumpIfError(hr, error, "get_GenKeyFlags");
  5193. lFlagsT &= ~CRYPT_EXPORTABLE;
  5194. lFlagsT |= fT? CRYPT_EXPORTABLE : 0;
  5195. hr = pEnroll->put_GenKeyFlags(lFlagsT);
  5196. _JumpIfError(hr, error, "put_GenKeyFlags");
  5197. }
  5198. else
  5199. if (0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_USERPROTECTED))
  5200. {
  5201. hr = myInfParseBooleanValue(pwszInfValue, &fT);
  5202. _JumpIfError(hr, error, "myInfParseBooleanValue");
  5203. hr = pEnroll->get_GenKeyFlags(&lFlagsT);
  5204. _JumpIfError(hr, error, "get_GenKeyFlags");
  5205. lFlagsT &= ~CRYPT_USER_PROTECTED;
  5206. lFlagsT |= fT? CRYPT_USER_PROTECTED : 0;
  5207. hr = pEnroll->put_GenKeyFlags(lFlagsT);
  5208. _JumpIfError(hr, error, "put_GenKeyFlags");
  5209. }
  5210. else
  5211. if (0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_KEYCONTAINER))
  5212. {
  5213. hr = pEnroll->put_ContainerNameWStr(
  5214. const_cast<WCHAR *>(pwszInfValue));
  5215. _JumpIfError(hr, error, "put_ContainerNameWStr");
  5216. }
  5217. #if 0
  5218. else
  5219. if (0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_HASHALGID))
  5220. {
  5221. hr = myInfParseBooleanValue(pwszInfValue, &fT);
  5222. _JumpIfError(hr, error, "myInfParseBooleanValue");
  5223. hr = pEnroll->get_GenKeyFlags(&lFlagsT);
  5224. _JumpIfError(hr, error, "get_GenKeyFlags");
  5225. lFlagsT &= ~CRYPT_EXPORTABLE;
  5226. lFlagsT |= fT? CRYPT_EXPORTABLE : 0;
  5227. hr = pEnroll->put_GenKeyFlags(lFlagsT);
  5228. _JumpIfError(hr, error, "put_GenKeyFlags");
  5229. }
  5230. else
  5231. if (0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_HASHALGORITHM))
  5232. {
  5233. hr = myInfParseBooleanValue(pwszInfValue, &fT);
  5234. _JumpIfError(hr, error, "myInfParseBooleanValue");
  5235. hr = pEnroll->get_GenKeyFlags(&lFlagsT);
  5236. _JumpIfError(hr, error, "get_GenKeyFlags");
  5237. lFlagsT &= ~CRYPT_EXPORTABLE;
  5238. lFlagsT |= fT? CRYPT_EXPORTABLE : 0;
  5239. hr = pEnroll->put_GenKeyFlags(lFlagsT);
  5240. _JumpIfError(hr, error, "put_GenKeyFlags");
  5241. }
  5242. #endif
  5243. else
  5244. if (0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_MACHINEKEYSET))
  5245. {
  5246. hr = myInfParseBooleanValue(pwszInfValue, &fT);
  5247. _JumpIfError(hr, error, "myInfParseBooleanValue");
  5248. hr = pEnroll->get_ProviderFlags(&lFlagsT);
  5249. _JumpIfError(hr, error, "get_ProviderFlags");
  5250. lFlagsT &= ~CRYPT_MACHINE_KEYSET;
  5251. lFlagsT |= fT? CRYPT_MACHINE_KEYSET : 0;
  5252. hr = pEnroll->put_ProviderFlags(lFlagsT);
  5253. _JumpIfError(hr, error, "put_ProviderFlags");
  5254. hr = pEnroll->get_MyStoreFlags(&lFlagsT);
  5255. _JumpIfError(hr, error, "get_MyStoreFlags");
  5256. lFlagsT &= ~(CERT_SYSTEM_STORE_CURRENT_USER |
  5257. CERT_SYSTEM_STORE_LOCAL_MACHINE);
  5258. lFlagsT |= fT? CERT_SYSTEM_STORE_LOCAL_MACHINE :
  5259. CERT_SYSTEM_STORE_CURRENT_USER;
  5260. hr = pEnroll->put_MyStoreFlags(lFlagsT);
  5261. _JumpIfError(hr, error, "put_MyStoreFlags");
  5262. }
  5263. else
  5264. if (0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_SILENT))
  5265. {
  5266. hr = myInfParseBooleanValue(pwszInfValue, &fT);
  5267. _JumpIfError(hr, error, "myInfParseBooleanValue");
  5268. hr = pEnroll->get_ProviderFlags(&lFlagsT);
  5269. _JumpIfError(hr, error, "get_ProviderFlags");
  5270. lFlagsT &= ~CRYPT_SILENT;
  5271. lFlagsT |= fT? CRYPT_SILENT : 0;
  5272. hr = pEnroll->put_ProviderFlags(lFlagsT);
  5273. _JumpIfError(hr, error, "put_ProviderFlags");
  5274. }
  5275. else
  5276. if (0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_PROVIDERNAME))
  5277. {
  5278. hr = pEnroll->put_ProviderNameWStr(
  5279. const_cast<WCHAR *>(pwszInfValue));
  5280. _JumpIfError(hr, error, "put_ProviderNameWStr");
  5281. }
  5282. else
  5283. if (0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_PROVIDERTYPE))
  5284. {
  5285. lFlagsT = myWtoI(pwszInfValue, &fValid);
  5286. if (!fValid)
  5287. {
  5288. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  5289. SetErrorStringInf(pwszfnPolicy, pInfValues);
  5290. _JumpError(hr, error, "Bad ProviderType value");
  5291. }
  5292. hr = pEnroll->put_ProviderType(lFlagsT);
  5293. _JumpIfError(hr, error, "put_ProviderType");
  5294. }
  5295. else
  5296. if (0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_USEEXISTINGKEYSET))
  5297. {
  5298. hr = myInfParseBooleanValue(pwszInfValue, &fT);
  5299. _JumpIfError(hr, error, "myInfParseBooleanValue");
  5300. hr = pEnroll->put_UseExistingKeySet(fT);
  5301. _JumpIfError(hr, error, "put_UseExistingKeySet");
  5302. }
  5303. else
  5304. if (0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_SMIME))
  5305. {
  5306. hr = myInfParseBooleanValue(pwszInfValue, &fT);
  5307. _JumpIfError(hr, error, "myInfParseBooleanValue");
  5308. hr = pEnroll->put_EnableSMIMECapabilities(fT);
  5309. _JumpIfError(hr, error, "put_EnableSMIMECapabilities");
  5310. }
  5311. else
  5312. if (0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_REQUESTERNAME))
  5313. {
  5314. hr = pEnroll->AddNameValuePairToSignatureWStr(
  5315. wszINFKEY_REQUESTERNAME,
  5316. const_cast<WCHAR *>(pwszInfValue));
  5317. _JumpIfError(hr, error, "AddNameValuePairToSignatureWStr");
  5318. }
  5319. else
  5320. if (0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_REQUESTTYPE))
  5321. {
  5322. if (0 == LSTRCMPIS(pwszInfValue, wszINFVALUE_REQUESTTYPE_PKCS101))
  5323. {
  5324. RequestTypeFlags = XECR_PKCS10_V1_5;
  5325. }
  5326. else
  5327. if (0 == LSTRCMPIS(pwszInfValue, wszINFVALUE_REQUESTTYPE_PKCS10))
  5328. {
  5329. RequestTypeFlags = XECR_PKCS10_V2_0;
  5330. }
  5331. else
  5332. if (0 == LSTRCMPIS(pwszInfValue, wszINFVALUE_REQUESTTYPE_PKCS7))
  5333. {
  5334. RequestTypeFlags = XECR_PKCS7;
  5335. }
  5336. else
  5337. if (0 == LSTRCMPIS(pwszInfValue, wszINFVALUE_REQUESTTYPE_CMC))
  5338. {
  5339. RequestTypeFlags = XECR_CMC;
  5340. }
  5341. else
  5342. {
  5343. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  5344. SetErrorStringInf(pwszfnPolicy, pInfValues);
  5345. _JumpErrorStr(hr, error, "Bad RequestType value", pwszInfValue);
  5346. }
  5347. fRequestTypeSet = TRUE;
  5348. }
  5349. else
  5350. if (0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_KEYUSAGE))
  5351. {
  5352. CRYPT_BIT_BLOB KeyUsage;
  5353. CRYPT_DATA_BLOB BlobKeyUsage;
  5354. lFlagsT = myWtoI(pwszInfValue, &fValid);
  5355. if (!fValid)
  5356. {
  5357. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  5358. SetErrorStringInf(pwszfnPolicy, pInfValues);
  5359. _JumpError(hr, error, "Bad KeyUsage value");
  5360. }
  5361. KeyUsage.cbData = sizeof(lFlagsT);
  5362. KeyUsage.pbData = (BYTE *) &lFlagsT;
  5363. KeyUsage.cUnusedBits = 0;
  5364. if (!myEncodeObject(
  5365. X509_ASN_ENCODING,
  5366. X509_KEY_USAGE,
  5367. &KeyUsage,
  5368. 0,
  5369. CERTLIB_USE_LOCALALLOC,
  5370. &BlobKeyUsage.pbData,
  5371. &BlobKeyUsage.cbData))
  5372. {
  5373. hr = myHLastError();
  5374. _JumpError(hr, error, "Policy:myEncodeObject");
  5375. }
  5376. hr = pEnroll->addExtensionToRequestWStr(
  5377. 0,
  5378. TEXT(szOID_KEY_USAGE),
  5379. &BlobKeyUsage);
  5380. LocalFree(BlobKeyUsage.pbData);
  5381. _JumpIfError(hr, error, "addExtensionToRequestWStr");
  5382. fKeyUsageSet = TRUE;
  5383. }
  5384. else
  5385. if (0 == LSTRCMPIS(pInfValues->pwszKey, wszINFKEY_ENCIPHERONLY))
  5386. {
  5387. BOOL fEnciperOnly;
  5388. hr = myInfParseBooleanValue(pwszInfValue, &fEnciperOnly);
  5389. _JumpIfError(hr, error, "myInfParseBooleanValue");
  5390. hr = pEnroll->put_LimitExchangeKeyToEncipherment(fEnciperOnly);
  5391. _JumpIfError(hr, error, "put_LimitExchangeKeyToEncipherment");
  5392. }
  5393. else
  5394. {
  5395. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  5396. SetErrorStringInf(pwszfnPolicy, pInfValues);
  5397. _JumpErrorStr(hr, error, "bad Inf key", pInfValues->pwszKey);
  5398. }
  5399. }
  5400. for (i = 0; i < cAttributes; i++)
  5401. {
  5402. CRYPT_ATTRIBUTES *pAttributes = &rgAttributes[i];
  5403. for (j = 0; j < pAttributes->cAttr; j++)
  5404. {
  5405. CRYPT_ATTRIBUTE *pAttr = &pAttributes->rgAttr[j];
  5406. if (NULL != pwszObjId)
  5407. {
  5408. LocalFree(pwszObjId);
  5409. pwszObjId = NULL;
  5410. }
  5411. if (!ConvertSzToWsz(&pwszObjId, pAttr->pszObjId, -1))
  5412. {
  5413. hr = E_OUTOFMEMORY;
  5414. _JumpError(hr, error, "ConvertSzToWsz");
  5415. }
  5416. for (k = 0; k < pAttr->cValue; k++)
  5417. {
  5418. hr = pEnroll->addAttributeToRequestWStr(
  5419. 0, // Flags
  5420. pwszObjId,
  5421. &pAttr->rgValue[k]);
  5422. _JumpIfError(hr, error, "addAttributeToRequestWStr");
  5423. }
  5424. }
  5425. }
  5426. for (i = 0; i < cExt; i++)
  5427. {
  5428. CERT_EXTENSION *pExt = &rgExt[i];
  5429. if (fKeyUsageSet && 0 == strcmp(szOID_KEY_USAGE, pExt->pszObjId))
  5430. {
  5431. continue;
  5432. }
  5433. if (NULL != pwszObjId)
  5434. {
  5435. LocalFree(pwszObjId);
  5436. pwszObjId = NULL;
  5437. }
  5438. if (!ConvertSzToWsz(&pwszObjId, pExt->pszObjId, -1))
  5439. {
  5440. hr = E_OUTOFMEMORY;
  5441. _JumpError(hr, error, "ConvertSzToWsz");
  5442. }
  5443. hr = pEnroll->addExtensionToRequestWStr(
  5444. pExt->fCritical,
  5445. pwszObjId,
  5446. &pExt->Value);
  5447. _JumpIfError(hr, error, "addExtensionToRequestWStr");
  5448. }
  5449. if (NULL != g_pwszCertCN)
  5450. {
  5451. if (!g_fQuiet || NULL != g_pwszCertCN)
  5452. {
  5453. hr = myGetCertificateFromPicker(
  5454. g_hInstance,
  5455. NULL, // hwndParent
  5456. IDS_GETSIGNINGCERT_TITLE,
  5457. IDS_GETSIGNINGCERT_SUBTITLE,
  5458. CUCS_MYSTORE |
  5459. CUCS_PRIVATEKEYREQUIRED |
  5460. (g_fQuiet? CUCS_SILENT : 0),
  5461. (L'\0' == g_pwszCertCN || 0 == lstrcmp(L"*", g_pwszCertCN))?
  5462. NULL : g_pwszCertCN, // pwszCommonName
  5463. 0, // cStore
  5464. NULL, // rghStore
  5465. 0, // cpszObjId
  5466. NULL, // apszObjId
  5467. &pccSigner);
  5468. _JumpIfError(hr, error, "myGetCertificateFromPicker");
  5469. }
  5470. // pccSigner is NULL if the user cancelled out of the cert picker U/I.
  5471. if (NULL == pccSigner)
  5472. {
  5473. if (g_fQuiet || NULL != g_pwszCertCN)
  5474. {
  5475. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  5476. _JumpError(hr, error, "no matching signer CN");
  5477. }
  5478. }
  5479. hr = pEnroll->SetSignerCertificate(pccSigner);
  5480. _JumpIfError(hr, error, "SetSignerCertificate");
  5481. }
  5482. if (NULL != pccXchg)
  5483. {
  5484. LONG lGenKeyFlags;
  5485. hr = pEnroll->SetPrivateKeyArchiveCertificate(pccXchg);
  5486. _JumpIfError(hr, error, "SetPrivateKeyArchiveCertificate");
  5487. hr = pEnroll->get_GenKeyFlags(&lGenKeyFlags);
  5488. _JumpIfError(hr, error, "getGenKeyFlags");
  5489. if (0 == (CRYPT_EXPORTABLE & lGenKeyFlags))
  5490. {
  5491. hr = pEnroll->put_GenKeyFlags(CRYPT_EXPORTABLE | lGenKeyFlags);
  5492. _JumpIfError(hr, error, "putGenKeyFlags");
  5493. }
  5494. }
  5495. if (NULL != pccRenewal)
  5496. {
  5497. hr = pEnroll->put_RenewalCertificate(pccRenewal);
  5498. _JumpIfError(hr, error, "put_RenewalCertificate");
  5499. }
  5500. if (!fRequestTypeSet)
  5501. {
  5502. if (NULL != pccXchg)
  5503. {
  5504. RequestTypeFlags = XECR_CMC;
  5505. }
  5506. else if (NULL != pccRenewal)
  5507. {
  5508. RequestTypeFlags = XECR_PKCS7;
  5509. }
  5510. }
  5511. hr = pEnroll->createRequestWStr(
  5512. RequestTypeFlags,
  5513. pwszDN,
  5514. NULL,
  5515. &blobRequest);
  5516. _JumpIfError(hr, error, "createRequestWStr");
  5517. myRegisterMemAlloc(blobRequest.pbData, blobRequest.cbData, CSM_LOCALALLOC);
  5518. hr = WriteCertificateOrRequest(
  5519. hWndOwner,
  5520. NULL, // pdiRequest
  5521. blobRequest.pbData,
  5522. blobRequest.cbData,
  5523. g_dwOutFormat,
  5524. IDS_REQUEST_OUTFILE_TITLE,
  5525. IDS_REQUEST_FILE_FILTER,
  5526. IDS_REQUEST_FILE_DEFEXT,
  5527. pwszfnOut);
  5528. _JumpIfError(hr, error, "WriteCertificateOrRequest");
  5529. error:
  5530. if (NULL != pwszDN)
  5531. {
  5532. LocalFree(pwszDN);
  5533. }
  5534. if (NULL != NameBlob.pbData)
  5535. {
  5536. LocalFree(NameBlob.pbData);
  5537. }
  5538. if (NULL != pccXchg)
  5539. {
  5540. CertFreeCertificateContext(pccXchg);
  5541. }
  5542. if (NULL != pccRenewal)
  5543. {
  5544. CertFreeCertificateContext(pccRenewal);
  5545. }
  5546. if (NULL != pccSigner)
  5547. {
  5548. CertFreeCertificateContext(pccSigner);
  5549. }
  5550. if (NULL != rgInfValues)
  5551. {
  5552. myInfFreeSectionValues(cInfValues, rgInfValues);
  5553. }
  5554. if (NULL != rgAttributes)
  5555. {
  5556. FreeAttributes(cAttributes, rgAttributes);
  5557. }
  5558. if (NULL != rgExt)
  5559. {
  5560. FreeExtensions(TRUE, cExt, rgExt);
  5561. }
  5562. if (NULL != pwszTemplateName)
  5563. {
  5564. LocalFree(pwszTemplateName);
  5565. }
  5566. if (NULL != pwszObjId)
  5567. {
  5568. LocalFree(pwszObjId);
  5569. }
  5570. if (NULL != blobRequest.pbData)
  5571. {
  5572. LocalFree(blobRequest.pbData);
  5573. }
  5574. if (NULL != pEnroll)
  5575. {
  5576. pEnroll->Release();
  5577. }
  5578. if (fCoInit)
  5579. {
  5580. CoUninitialize();
  5581. }
  5582. return(hr);
  5583. }
  5584. HRESULT
  5585. MakePKCS7FromCert(
  5586. IN BYTE const *pbCert,
  5587. IN DWORD cbCert,
  5588. OUT BYTE **ppbChain,
  5589. OUT DWORD *pcbChain)
  5590. {
  5591. HRESULT hr;
  5592. CERT_CONTEXT const *pcc = NULL;
  5593. CRYPT_SIGN_MESSAGE_PARA csmp;
  5594. CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm = { szOID_OIWSEC_sha1, 0, 0 };
  5595. *ppbChain = NULL;
  5596. pcc = CertCreateCertificateContext(X509_ASN_ENCODING, pbCert, cbCert);
  5597. if (NULL == pcc)
  5598. {
  5599. hr = myHLastError();
  5600. _JumpError(hr, error, "CertCreateCertificateContext");
  5601. }
  5602. // init csmp for empty signature
  5603. ZeroMemory(&csmp, sizeof(csmp));
  5604. csmp.cbSize = sizeof(csmp);
  5605. csmp.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
  5606. //csmp.pSigningCert = NULL;
  5607. csmp.HashAlgorithm = DigestAlgorithm;
  5608. csmp.cMsgCert = 1;
  5609. csmp.rgpMsgCert = &pcc;
  5610. //csmp.cMsgCrl = 0;
  5611. //csmp.rgpMsgCrl = NULL;
  5612. if (!myCryptSignMessage(
  5613. &csmp,
  5614. pbCert, // pbToBeSigned
  5615. cbCert, // cbToBeSigned
  5616. CERTLIB_USE_LOCALALLOC,
  5617. ppbChain,
  5618. pcbChain))
  5619. {
  5620. hr = myHLastError();
  5621. _JumpError(hr, error, "myCryptSignMessage");
  5622. }
  5623. hr = S_OK;
  5624. error:
  5625. if (NULL != pcc)
  5626. {
  5627. CertFreeCertificateContext(pcc);
  5628. }
  5629. return(hr);
  5630. }
  5631. HRESULT
  5632. AcceptResponse(
  5633. IN WCHAR const *pwszfnIn)
  5634. {
  5635. HRESULT hr;
  5636. WCHAR *pwszMsg = NULL;
  5637. WCHAR awchr[cwcHRESULTSTRING];
  5638. CRYPT_DATA_BLOB blobIn;
  5639. CRYPT_DATA_BLOB blobCert7;
  5640. char *pszInnerContentObjId = NULL;
  5641. DWORD dwType;
  5642. BYTE *pbDecoded = NULL;
  5643. DWORD cb;
  5644. BOOL fCoInit = FALSE;
  5645. IEnroll4 *pEnroll = NULL;
  5646. blobIn.pbData = NULL;
  5647. blobCert7.pbData = NULL;
  5648. hr = DecodeFileW(
  5649. pwszfnIn,
  5650. &blobIn.pbData,
  5651. &blobIn.cbData,
  5652. CRYPT_STRING_BASE64_ANY);
  5653. if (S_OK != hr)
  5654. {
  5655. if (S_OK == myLoadRCString(
  5656. g_hInstance,
  5657. IDS_FORMATSTR_DECODE_ERR,
  5658. &pwszMsg))
  5659. {
  5660. CSASSERT(NULL != pwszMsg);
  5661. wprintf(pwszMsg, myHResultToString(awchr, hr));
  5662. wprintf(g_wszNewLine);
  5663. }
  5664. goto error;
  5665. }
  5666. dwType = CR_IN_CERT;
  5667. if (!myDecodeObject(
  5668. X509_ASN_ENCODING,
  5669. X509_CERT_TO_BE_SIGNED,
  5670. blobIn.pbData,
  5671. blobIn.cbData,
  5672. CERTLIB_USE_LOCALALLOC,
  5673. (VOID **) &pbDecoded,
  5674. &cb))
  5675. {
  5676. //_PrintError(myHLastError(), "myDecodeObject(Cert)");
  5677. CSASSERT(NULL == pbDecoded);
  5678. dwType = CR_IN_PKCS7; // PKCS 7 renewal request?
  5679. hr = myDecodePKCS7(
  5680. blobIn.pbData,
  5681. blobIn.cbData,
  5682. NULL, // ppbContents
  5683. NULL, // pcbContents
  5684. NULL, // pdwMsgType
  5685. &pszInnerContentObjId,
  5686. NULL, // pcSigner
  5687. NULL, // pcRecipient
  5688. NULL, // phStore
  5689. NULL); // phMsg
  5690. _JumpIfError(hr, error, "myDecodePKCS7");
  5691. if (NULL != pszInnerContentObjId &&
  5692. 0 == strcmp(pszInnerContentObjId, szOID_CT_PKI_RESPONSE))
  5693. {
  5694. dwType = CR_IN_CMC;
  5695. }
  5696. }
  5697. if (CR_IN_CERT == dwType)
  5698. {
  5699. hr = MakePKCS7FromCert(
  5700. blobIn.pbData,
  5701. blobIn.cbData,
  5702. &blobCert7.pbData,
  5703. &blobCert7.cbData);
  5704. _JumpIfError(hr, error, "MakePKCS7FromCert");
  5705. }
  5706. hr = CoInitialize(NULL);
  5707. if (S_OK != hr && S_FALSE != hr)
  5708. {
  5709. _JumpError(hr, error, "CoInitialize");
  5710. }
  5711. fCoInit = TRUE;
  5712. hr = CoCreateInstance(
  5713. CLSID_CEnroll,
  5714. NULL, // pUnkOuter
  5715. CLSCTX_INPROC_SERVER,
  5716. IID_IEnroll4,
  5717. (VOID **) &pEnroll);
  5718. _JumpIfError(hr, error, "CoCreateInstance");
  5719. if (CR_IN_CMC == dwType)
  5720. {
  5721. hr = pEnroll->acceptResponseBlob(&blobIn);
  5722. _PrintIfError2(hr, "acceptResponseBlob", CRYPT_E_NOT_FOUND);
  5723. }
  5724. else
  5725. {
  5726. hr = pEnroll->acceptPKCS7Blob(
  5727. NULL != blobCert7.pbData? &blobCert7 : &blobIn);
  5728. _PrintIfError2(hr, "acceptPKCS7Blob", CRYPT_E_NOT_FOUND);
  5729. }
  5730. if (S_OK != hr)
  5731. {
  5732. HRESULT hr2 = hr;
  5733. LONG lFlagsT;
  5734. BOOL fT;
  5735. hr = pEnroll->get_ProviderFlags(&lFlagsT);
  5736. _JumpIfError(hr, error, "get_ProviderFlags");
  5737. fT = 0 == (CRYPT_MACHINE_KEYSET & lFlagsT);
  5738. lFlagsT &= ~CRYPT_MACHINE_KEYSET;
  5739. lFlagsT |= fT? CRYPT_MACHINE_KEYSET : 0;
  5740. hr = pEnroll->put_ProviderFlags(lFlagsT);
  5741. _JumpIfError(hr, error, "put_ProviderFlags");
  5742. hr = pEnroll->get_MyStoreFlags(&lFlagsT);
  5743. _JumpIfError(hr, error, "get_MyStoreFlags");
  5744. lFlagsT &= ~(CERT_SYSTEM_STORE_CURRENT_USER |
  5745. CERT_SYSTEM_STORE_LOCAL_MACHINE);
  5746. lFlagsT |= fT? CERT_SYSTEM_STORE_LOCAL_MACHINE :
  5747. CERT_SYSTEM_STORE_CURRENT_USER;
  5748. hr = pEnroll->put_MyStoreFlags(lFlagsT);
  5749. _JumpIfError(hr, error, "put_MyStoreFlags");
  5750. if (CR_IN_CMC == dwType)
  5751. {
  5752. hr = pEnroll->acceptResponseBlob(&blobIn);
  5753. _PrintIfError(hr, "acceptResponseBlob");
  5754. }
  5755. else
  5756. {
  5757. hr = pEnroll->acceptPKCS7Blob(
  5758. NULL != blobCert7.pbData? &blobCert7 : &blobIn);
  5759. _PrintIfError(hr, "acceptPKCS7Blob");
  5760. }
  5761. // If accepting the response in machine context didn't work, return the
  5762. // first error (the user context error).
  5763. if (S_OK != hr)
  5764. {
  5765. hr = hr2;
  5766. }
  5767. _JumpIfError(hr, error, "AcceptResponse");
  5768. }
  5769. error:
  5770. if (NULL != pwszMsg)
  5771. {
  5772. LocalFree(pwszMsg);
  5773. }
  5774. if (NULL != blobIn.pbData)
  5775. {
  5776. LocalFree(blobIn.pbData);
  5777. }
  5778. if (NULL != blobCert7.pbData)
  5779. {
  5780. LocalFree(blobCert7.pbData);
  5781. }
  5782. if (NULL != pszInnerContentObjId)
  5783. {
  5784. LocalFree(pszInnerContentObjId);
  5785. }
  5786. if (NULL != pbDecoded)
  5787. {
  5788. LocalFree(pbDecoded);
  5789. }
  5790. if (NULL != pEnroll)
  5791. {
  5792. pEnroll->Release();
  5793. }
  5794. if (fCoInit)
  5795. {
  5796. CoUninitialize();
  5797. }
  5798. return(hr);
  5799. }
  5800. HRESULT
  5801. ArgvMain(
  5802. int argc,
  5803. WCHAR *argv[],
  5804. HWND hWndOwner)
  5805. {
  5806. HRESULT hr;
  5807. WCHAR *pwszOFN = NULL;
  5808. WCHAR *pwszOFN2 = NULL;
  5809. WCHAR const *pwszfnIn;
  5810. WCHAR const *pwszfnOut;
  5811. WCHAR const *pwszfnPKCS10;
  5812. WCHAR const *pwszfnCertChain;
  5813. WCHAR const *pwszfnFullResponse;
  5814. WCHAR const *pwszfnPolicy;
  5815. LONG RequestId;
  5816. WCHAR *pwszAttributes = NULL;
  5817. WCHAR const *pwszSerialNumber = NULL;
  5818. DWORD cCommand = 0;
  5819. int cArgMax = 0;
  5820. WCHAR *rgpwszArg[4];
  5821. UINT idsFileFilter;
  5822. UINT idsFileDefExt;
  5823. myVerifyResourceStrings(g_hInstance);
  5824. while (1 < argc && myIsSwitchChar(argv[1][0]))
  5825. {
  5826. if (0 == LSTRCMPIS(&argv[1][1], L"config"))
  5827. {
  5828. if (2 >= argc)
  5829. {
  5830. _PrintError(E_INVALIDARG, "missing -config arg");
  5831. Usage(TRUE);
  5832. }
  5833. if (myIsMinusSignString(argv[2]) || 0 == wcscmp(argv[2], L"*"))
  5834. {
  5835. g_dwUIFlag = CC_LOCALACTIVECONFIG;
  5836. }
  5837. else
  5838. {
  5839. g_pwszConfig = argv[2];
  5840. }
  5841. argc--;
  5842. argv++;
  5843. }
  5844. else
  5845. if (0 == LSTRCMPIS(&argv[1][1], L"any"))
  5846. {
  5847. g_fAny = TRUE;
  5848. }
  5849. else
  5850. if (0 == LSTRCMPIS(&argv[1][1], L"crl"))
  5851. {
  5852. g_dwCRLIn = CR_IN_CRLS;
  5853. g_dwCRLOut = CR_OUT_CRLS;
  5854. }
  5855. else
  5856. if (0 == LSTRCMPIS(&argv[1][1], L"rpc"))
  5857. {
  5858. g_fRPC++;
  5859. if (0 == lstrcmp(&argv[1][1], L"RPC"))
  5860. {
  5861. g_fRPC++;
  5862. }
  5863. }
  5864. else
  5865. if (0 == LSTRCMPIS(&argv[1][1], L"binary"))
  5866. {
  5867. g_dwOutFormat = CR_OUT_BINARY;
  5868. }
  5869. else
  5870. if (0 == LSTRCMPIS(&argv[1][1], L"idispatch"))
  5871. {
  5872. g_fIDispatch = TRUE;
  5873. }
  5874. else
  5875. if (0 == LSTRCMPIS(&argv[1][1], L"submit"))
  5876. {
  5877. g_dwCommand = cmdSUBMITREQUEST;
  5878. cArgMax = 4;
  5879. cCommand++;
  5880. }
  5881. else
  5882. if (0 == LSTRCMPIS(&argv[1][1], L"retrieve"))
  5883. {
  5884. g_dwCommand = cmdRETRIEVEPENDING;
  5885. cArgMax = 4;
  5886. cCommand++;
  5887. }
  5888. else
  5889. if (0 == LSTRCMPIS(&argv[1][1], L"policy"))
  5890. {
  5891. g_dwCommand = cmdQUALIFIEDREQUEST;
  5892. cArgMax = 4;
  5893. cCommand++;
  5894. }
  5895. else
  5896. if (0 == LSTRCMPIS(&argv[1][1], L"new"))
  5897. {
  5898. g_dwCommand = cmdNEWREQUEST;
  5899. cArgMax = 2;
  5900. cCommand++;
  5901. }
  5902. else
  5903. if (0 == LSTRCMPIS(&argv[1][1], L"accept"))
  5904. {
  5905. g_dwCommand = cmdACCEPTRESPONSE;
  5906. cArgMax = 1;
  5907. cCommand++;
  5908. }
  5909. else
  5910. if (0 == LSTRCMPIS(&argv[1][1], L"sign"))
  5911. {
  5912. g_dwCommand = cmdSIGNREQUEST;
  5913. cArgMax = 2;
  5914. cCommand++;
  5915. }
  5916. else
  5917. if (0 == LSTRCMPIS(&argv[1][1], L"v1"))
  5918. {
  5919. g_fV1Interface = TRUE;
  5920. }
  5921. else
  5922. if (0 == LSTRCMPIS(&argv[1][1], L"v"))
  5923. {
  5924. g_fVerbose = TRUE;
  5925. }
  5926. else
  5927. if (0 == LSTRCMPIS(&argv[1][1], L"f"))
  5928. {
  5929. g_fForce++;
  5930. }
  5931. else
  5932. if (0 == LSTRCMPIS(&argv[1][1], L"q"))
  5933. {
  5934. g_fQuiet = TRUE;
  5935. g_dwUIFlag = CC_LOCALACTIVECONFIG;
  5936. }
  5937. else
  5938. if (0 == lstrcmp(&argv[1][1], L"?") ||
  5939. 0 == LSTRCMPIS(&argv[1][1], L"usage"))
  5940. {
  5941. g_fFullUsage = 0 == lstrcmp(&argv[1][1], L"uSAGE");
  5942. Usage(FALSE);
  5943. }
  5944. else
  5945. if (0 == LSTRCMPIS(&argv[1][1], L"attrib"))
  5946. {
  5947. if (2 >= argc)
  5948. {
  5949. _PrintError(E_INVALIDARG, "missing -attrib arg");
  5950. Usage(TRUE);
  5951. }
  5952. hr = crCombineAttributes(argv[2], &pwszAttributes);
  5953. _JumpIfError(hr, error, "crCombineAttributes");
  5954. argc--;
  5955. argv++;
  5956. }
  5957. else
  5958. if (0 == LSTRCMPIS(&argv[1][1], L"cert"))
  5959. {
  5960. if (2 >= argc)
  5961. {
  5962. _PrintError(E_INVALIDARG, "missing -cert arg");
  5963. Usage(TRUE);
  5964. }
  5965. g_pwszCertCN = argv[2];
  5966. argc--;
  5967. argv++;
  5968. }
  5969. else
  5970. {
  5971. _PrintError(E_INVALIDARG, "Unknown arg");
  5972. Usage(TRUE);
  5973. }
  5974. argc--;
  5975. argv++;
  5976. }
  5977. if (1 < cCommand)
  5978. {
  5979. _PrintError(E_INVALIDARG, "multiple commands");
  5980. Usage(TRUE);
  5981. }
  5982. if (cmdNONE == g_dwCommand)
  5983. {
  5984. g_dwCommand = cmdSUBMITREQUEST;
  5985. cArgMax = 4;
  5986. }
  5987. if (NULL != pwszAttributes &&
  5988. cmdSUBMITREQUEST != g_dwCommand &&
  5989. cmdNEWREQUEST != g_dwCommand &&
  5990. cmdQUALIFIEDREQUEST != g_dwCommand)
  5991. {
  5992. _PrintError(E_INVALIDARG, "unexpected -attrib arg");
  5993. Usage(TRUE);
  5994. }
  5995. if (NULL != g_pwszCertCN &&
  5996. cmdSIGNREQUEST != g_dwCommand &&
  5997. cmdQUALIFIEDREQUEST != g_dwCommand &&
  5998. cmdNEWREQUEST != g_dwCommand)
  5999. {
  6000. _PrintError(E_INVALIDARG, "unexpected -cert arg");
  6001. Usage(TRUE);
  6002. }
  6003. if (1 + cArgMax < argc)
  6004. {
  6005. _PrintError(E_INVALIDARG, "Extra args");
  6006. Usage(TRUE);
  6007. }
  6008. CSASSERT(ARRAYSIZE(rgpwszArg) >= cArgMax);
  6009. ZeroMemory(rgpwszArg, sizeof(rgpwszArg));
  6010. if (1 < argc)
  6011. {
  6012. rgpwszArg[0] = argv[1];
  6013. if (2 < argc)
  6014. {
  6015. rgpwszArg[1] = argv[2];
  6016. if (3 < argc)
  6017. {
  6018. rgpwszArg[2] = argv[3];
  6019. if (4 < argc)
  6020. {
  6021. rgpwszArg[3] = argv[4];
  6022. }
  6023. }
  6024. }
  6025. }
  6026. // cmdSUBMITREQUEST:
  6027. // [RequestFile [CertFile [CertChainFile [FullResponseFile]]]]
  6028. //
  6029. // cmdRETRIEVEPENDING:
  6030. // [RequestId [CertFile [CertChainFile [FullResponseFile]]]]
  6031. //
  6032. // cmdNEWREQUEST
  6033. // [PolicyFile [RequestFileOut]]
  6034. //
  6035. // cmdACCEPTRESPONSE
  6036. // [CertFile | CertChainFile | FullResponseFile]
  6037. //
  6038. // cmdQUALIFIEDREQUEST (accept RequestFile and PolicyFile in either order)
  6039. // [RequestFile [PolicyFile [RequestFileOut [PKCS10FileOut]]]
  6040. //
  6041. // cmdSIGNREQUEST:
  6042. // [RequestFile [RequestFileOut]]
  6043. //
  6044. pwszfnIn = NULL;
  6045. pwszfnOut = NULL;
  6046. pwszfnPKCS10 = NULL;
  6047. pwszfnCertChain = NULL;
  6048. pwszfnFullResponse = NULL;
  6049. pwszfnPolicy = NULL;
  6050. pwszfnIn = rgpwszArg[0];
  6051. idsFileFilter = IDS_REQUEST_FILE_FILTER;
  6052. idsFileDefExt = IDS_REQUEST_FILE_DEFEXT;
  6053. switch (g_dwCommand)
  6054. {
  6055. case cmdRETRIEVEPENDING:
  6056. idsFileFilter = 0; // disable file open dialog
  6057. // FALLTHROUGH
  6058. case cmdSUBMITREQUEST:
  6059. pwszfnOut = rgpwszArg[1];
  6060. pwszfnCertChain = rgpwszArg[2];
  6061. pwszfnFullResponse = rgpwszArg[3];
  6062. break;
  6063. case cmdNEWREQUEST:
  6064. pwszfnIn = NULL;
  6065. pwszfnPolicy = rgpwszArg[0];
  6066. pwszfnOut = rgpwszArg[1];
  6067. CSASSERT(NULL == rgpwszArg[2]);
  6068. idsFileFilter = 0; // disable file open dialog
  6069. break;
  6070. case cmdACCEPTRESPONSE:
  6071. CSASSERT(NULL == rgpwszArg[1]);
  6072. idsFileFilter = IDS_RESPONSE_FILE_FILTER;
  6073. idsFileDefExt = IDS_RESPONSE_FILE_DEFEXT;
  6074. break;
  6075. case cmdQUALIFIEDREQUEST:
  6076. pwszfnPolicy = rgpwszArg[1];
  6077. pwszfnOut = rgpwszArg[2];
  6078. pwszfnPKCS10 = rgpwszArg[3];
  6079. idsFileFilter = IDS_REQUEST_FILE_FILTER;
  6080. break;
  6081. default:
  6082. CSASSERT(cmdSIGNREQUEST == g_dwCommand);
  6083. pwszfnOut = rgpwszArg[1];
  6084. CSASSERT(NULL == rgpwszArg[2]);
  6085. CSASSERT(NULL == rgpwszArg[3]);
  6086. break;
  6087. }
  6088. RequestId = 0;
  6089. if (cmdRETRIEVEPENDING == g_dwCommand)
  6090. {
  6091. if (NULL == pwszfnIn)
  6092. {
  6093. WCHAR *pwszMsg = NULL;
  6094. hr = myLoadRCString(
  6095. g_hInstance,
  6096. IDS_ERROR_NO_REQUESTID,
  6097. &pwszMsg);
  6098. if (S_OK == hr)
  6099. {
  6100. CSASSERT(NULL != pwszMsg);
  6101. wprintf(pwszMsg);
  6102. wprintf(g_wszNewLine);
  6103. LocalFree(pwszMsg);
  6104. }
  6105. _PrintError(E_INVALIDARG, "missing RequestId");
  6106. Usage(TRUE);
  6107. }
  6108. hr = GetLong(pwszfnIn, &RequestId);
  6109. if (S_OK != hr || 0 == RequestId)
  6110. {
  6111. RequestId = 0;
  6112. pwszSerialNumber = pwszfnIn;
  6113. }
  6114. pwszfnIn = NULL;
  6115. }
  6116. else
  6117. if (NULL != pwszfnIn && cmdQUALIFIEDREQUEST == g_dwCommand)
  6118. {
  6119. BYTE *pbReq;
  6120. DWORD cbReq;
  6121. LONG dwFlags;
  6122. BOOL fSigned;
  6123. // accept RequestFile and PolicyFile in either order:
  6124. hr = CheckRequestType(
  6125. pwszfnIn,
  6126. &pbReq,
  6127. &cbReq,
  6128. &dwFlags,
  6129. &fSigned,
  6130. NULL, // pfCA
  6131. NULL); // ppwszTemplateName
  6132. if (S_OK != hr)
  6133. {
  6134. WCHAR const *pwsz = pwszfnPolicy;
  6135. pwszfnPolicy = pwszfnIn;
  6136. pwszfnIn = pwsz;
  6137. }
  6138. else
  6139. {
  6140. LocalFree(pbReq);
  6141. }
  6142. }
  6143. if (NULL == pwszfnIn && 0 != idsFileFilter)
  6144. {
  6145. // Put up a file open dialog to get Response, Request or cert file
  6146. hr = crGetOpenFileName(
  6147. hWndOwner,
  6148. IDS_REQUEST_OPEN_TITLE,
  6149. idsFileFilter,
  6150. idsFileDefExt,
  6151. &pwszOFN);
  6152. _JumpIfError(hr, error, "crGetOpenFileName");
  6153. pwszfnIn = pwszOFN;
  6154. }
  6155. if (NULL != pwszfnIn)
  6156. {
  6157. if (!myDoesFileExist(pwszfnIn))
  6158. {
  6159. SetErrorString(pwszfnIn);
  6160. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  6161. _JumpErrorStr(hr, error, "myDoesFileExist", pwszfnIn);
  6162. }
  6163. }
  6164. if (NULL != pwszfnOut)
  6165. {
  6166. hr = myIsDirWriteable(pwszfnOut, TRUE);
  6167. if (S_OK != hr)
  6168. {
  6169. SetErrorString(pwszfnOut);
  6170. _JumpErrorStr(hr, error, "IsDirWriteable", pwszfnOut);
  6171. }
  6172. }
  6173. switch (g_dwCommand)
  6174. {
  6175. case cmdRETRIEVEPENDING:
  6176. case cmdSUBMITREQUEST:
  6177. if (CV_OUT_BASE64REQUESTHEADER == g_dwOutFormat)
  6178. {
  6179. g_dwOutFormat = CV_OUT_BASE64HEADER;
  6180. }
  6181. if (NULL != pwszfnCertChain)
  6182. {
  6183. hr = myIsDirWriteable(pwszfnCertChain, TRUE);
  6184. if (S_OK != hr)
  6185. {
  6186. SetErrorString(pwszfnCertChain);
  6187. _JumpErrorStr(hr, error, "IsDirWriteable", pwszfnCertChain);
  6188. }
  6189. }
  6190. if (NULL != pwszfnFullResponse)
  6191. {
  6192. hr = myIsDirWriteable(pwszfnFullResponse, TRUE);
  6193. if (S_OK != hr)
  6194. {
  6195. SetErrorString(pwszfnFullResponse);
  6196. _JumpErrorStr(hr, error, "IsDirWriteable", pwszfnFullResponse);
  6197. }
  6198. }
  6199. hr = SubmitRequest(
  6200. hWndOwner,
  6201. RequestId,
  6202. pwszSerialNumber,
  6203. pwszAttributes,
  6204. pwszfnIn,
  6205. pwszfnOut,
  6206. pwszfnCertChain,
  6207. pwszfnFullResponse);
  6208. _JumpIfError(hr, error, "SubmitRequest");
  6209. break;
  6210. case cmdACCEPTRESPONSE:
  6211. hr = AcceptResponse(pwszfnIn);
  6212. _JumpIfError(hr, error, "AcceptResponse");
  6213. break;
  6214. case cmdNEWREQUEST:
  6215. case cmdQUALIFIEDREQUEST:
  6216. if (NULL != pwszfnPKCS10)
  6217. {
  6218. hr = myIsDirWriteable(pwszfnPKCS10, TRUE);
  6219. if (S_OK != hr)
  6220. {
  6221. SetErrorString(pwszfnPKCS10);
  6222. _JumpErrorStr(hr, error, "IsDirWriteable", pwszfnPKCS10);
  6223. }
  6224. }
  6225. if (NULL == pwszfnPolicy)
  6226. {
  6227. // Put up a file dialog to prompt the user for Inf File
  6228. hr = crGetOpenFileName(
  6229. hWndOwner,
  6230. IDS_INF_OPEN_TITLE,
  6231. IDS_INF_FILE_FILTER,
  6232. IDS_INF_FILE_DEFEXT,
  6233. &pwszOFN2);
  6234. _JumpIfError(hr, error, "crGetOpenFileName");
  6235. pwszfnPolicy = pwszOFN2;
  6236. }
  6237. CSASSERT(NULL != pwszfnPolicy);
  6238. if (!myDoesFileExist(pwszfnPolicy))
  6239. {
  6240. SetErrorString(pwszfnPolicy);
  6241. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  6242. _JumpErrorStr(hr, error, "myDoesFileExist", pwszfnPolicy);
  6243. }
  6244. if (cmdNEWREQUEST == g_dwCommand)
  6245. {
  6246. hr = CreateNewRequest(
  6247. hWndOwner,
  6248. pwszAttributes,
  6249. pwszfnPolicy,
  6250. pwszfnOut);
  6251. _JumpIfError(hr, error, "CreateNewRequest");
  6252. }
  6253. else
  6254. {
  6255. hr = CreateQualifiedRequest(
  6256. hWndOwner,
  6257. pwszAttributes,
  6258. pwszfnIn,
  6259. pwszfnPolicy,
  6260. pwszfnOut,
  6261. pwszfnPKCS10);
  6262. _JumpIfError(hr, error, "CreateQualifiedRequest");
  6263. }
  6264. break;
  6265. default:
  6266. CSASSERT(cmdSIGNREQUEST == g_dwCommand);
  6267. if (NULL != pwszfnFullResponse)
  6268. {
  6269. Usage(TRUE);
  6270. }
  6271. hr = SignQualifiedRequest(hWndOwner, pwszfnIn, pwszfnOut);
  6272. _JumpIfError(hr, error, "SignQualifiedRequest");
  6273. break;
  6274. }
  6275. error:
  6276. if (NULL != pwszAttributes)
  6277. {
  6278. LocalFree(pwszAttributes);
  6279. }
  6280. if (NULL != pwszOFN)
  6281. {
  6282. LocalFree(pwszOFN);
  6283. }
  6284. if (NULL != pwszOFN2)
  6285. {
  6286. LocalFree(pwszOFN2);
  6287. }
  6288. return(hr);
  6289. }
  6290. //**************************************************************************
  6291. // FUNCTION: CertReqPreMain
  6292. // NOTES: Based on vich's MkRootMain function; takes an LPSTR command
  6293. // line and chews it up into argc/argv form so that it can be
  6294. // passed on to a traditional C style main.
  6295. //**************************************************************************
  6296. #define ISBLANK(wc) (L' ' == (wc) || L'\t' == (wc))
  6297. HRESULT
  6298. CertReqPreMain(
  6299. LPTSTR pszCmdLine,
  6300. HWND hWndOwner)
  6301. {
  6302. WCHAR *pbuf;
  6303. LPTSTR apszArg[20];
  6304. int cArg = 0;
  6305. LPTSTR p;
  6306. WCHAR *pchQuote;
  6307. HRESULT hr;
  6308. pbuf = (WCHAR *) LocalAlloc(
  6309. LMEM_FIXED,
  6310. (wcslen(pszCmdLine) + 1) * sizeof(WCHAR));
  6311. if (NULL == pbuf)
  6312. {
  6313. hr = E_OUTOFMEMORY;
  6314. _JumpError(hr, error, "LocalAlloc");
  6315. }
  6316. p = pbuf;
  6317. apszArg[cArg++] = TEXT("CertReq");
  6318. while (*pszCmdLine != TEXT('\0'))
  6319. {
  6320. while (ISBLANK(*pszCmdLine))
  6321. {
  6322. pszCmdLine++;
  6323. }
  6324. if (*pszCmdLine != TEXT('\0'))
  6325. {
  6326. apszArg[cArg++] = p;
  6327. if (sizeof(apszArg)/sizeof(apszArg[0]) <= cArg)
  6328. {
  6329. hr = E_INVALIDARG;
  6330. _JumpError(hr, error, "Too many args");
  6331. }
  6332. pchQuote = NULL;
  6333. while (*pszCmdLine != L'\0')
  6334. {
  6335. if (NULL != pchQuote)
  6336. {
  6337. if (*pszCmdLine == *pchQuote)
  6338. {
  6339. pszCmdLine++;
  6340. pchQuote = NULL;
  6341. continue;
  6342. }
  6343. }
  6344. else
  6345. {
  6346. if (ISBLANK(*pszCmdLine))
  6347. {
  6348. break;
  6349. }
  6350. if (L'"' == *pszCmdLine)
  6351. {
  6352. pchQuote = pszCmdLine++;
  6353. continue;
  6354. }
  6355. }
  6356. *p++ = *pszCmdLine++;
  6357. }
  6358. *p++ = TEXT('\0');
  6359. if (*pszCmdLine != TEXT('\0'))
  6360. {
  6361. pszCmdLine++; // skip whitespace or quote character
  6362. }
  6363. }
  6364. }
  6365. apszArg[cArg] = NULL;
  6366. hr = ArgvMain(cArg, apszArg, hWndOwner);
  6367. _JumpIfError(hr, error, "ArgvMain");
  6368. error:
  6369. if (NULL != pbuf)
  6370. {
  6371. LocalFree(pbuf);
  6372. }
  6373. return(hr);
  6374. }
  6375. VOID
  6376. CertReqErrorDisplay(
  6377. IN HRESULT hr,
  6378. IN HWND hWnd)
  6379. {
  6380. WCHAR *pwszTitle = NULL;
  6381. WCHAR *pwszMessage = NULL;
  6382. WCHAR *pwszMessage2 = NULL;
  6383. WCHAR const *pwszError = NULL;
  6384. WCHAR *pwszCombinedError = NULL;
  6385. WCHAR const *pwsz;
  6386. myLoadRCString(g_hInstance, IDS_CERTREQ_TITLE, &pwszTitle);
  6387. if (g_idError)
  6388. {
  6389. myLoadRCString(g_hInstance, g_idError, &pwszMessage);
  6390. }
  6391. pwszError = myGetErrorMessageText(hr, S_OK != hr);
  6392. if (NULL != g_pwszUnreferencedSectionNames)
  6393. {
  6394. myLoadRCString(
  6395. g_hInstance,
  6396. IDS_UNREFERENCED_INF_SECTIONS,
  6397. &pwszMessage2);
  6398. }
  6399. // Eliminate redundant error message text. If the client and server
  6400. // localized error message text differ, both will still be displayed.
  6401. if (NULL != pwszError && NULL != g_pwszErrorString)
  6402. {
  6403. if (NULL != wcsstr(g_pwszErrorString, pwszError))
  6404. {
  6405. LocalFree(const_cast<WCHAR *>(pwszError));
  6406. pwszError = NULL;
  6407. }
  6408. }
  6409. pwsz = NULL;
  6410. if (NULL != pwszMessage ||
  6411. NULL != pwszError ||
  6412. NULL != g_pwszErrorString ||
  6413. NULL != g_pwszInfErrorString ||
  6414. NULL != g_pwszUnreferencedSectionNames)
  6415. {
  6416. DWORD cwc = 1;
  6417. if (NULL != pwszMessage)
  6418. {
  6419. cwc += wcslen(pwszMessage) + 1;
  6420. }
  6421. if (NULL != pwszError)
  6422. {
  6423. cwc += wcslen(pwszError) + 1;
  6424. }
  6425. if (NULL != g_pwszErrorString)
  6426. {
  6427. cwc += wcslen(g_pwszErrorString) + 1;
  6428. }
  6429. if (S_OK != hr && NULL != g_pwszInfErrorString)
  6430. {
  6431. cwc += wcslen(g_pwszInfErrorString) + 1;
  6432. }
  6433. if (NULL != pwszMessage2)
  6434. {
  6435. cwc += wcslen(pwszMessage2) + 1;
  6436. }
  6437. if (NULL != g_pwszUnreferencedSectionNames)
  6438. {
  6439. cwc += wcslen(g_pwszUnreferencedSectionNames) + 1;
  6440. }
  6441. pwszCombinedError = (WCHAR *) LocalAlloc(
  6442. LMEM_FIXED,
  6443. cwc * sizeof(WCHAR));
  6444. if (NULL != pwszCombinedError)
  6445. {
  6446. *pwszCombinedError = L'\0';
  6447. if (NULL != pwszMessage)
  6448. {
  6449. wcscat(pwszCombinedError, pwszMessage);
  6450. }
  6451. if (NULL != pwszError)
  6452. {
  6453. if (L'\0' != *pwszCombinedError)
  6454. {
  6455. wcscat(pwszCombinedError, g_wszNewLine);
  6456. }
  6457. wcscat(pwszCombinedError, pwszError);
  6458. }
  6459. if (NULL != g_pwszErrorString)
  6460. {
  6461. if (L'\0' != *pwszCombinedError)
  6462. {
  6463. wcscat(pwszCombinedError, g_wszNewLine);
  6464. }
  6465. wcscat(pwszCombinedError, g_pwszErrorString);
  6466. }
  6467. if (S_OK != hr && NULL != g_pwszInfErrorString)
  6468. {
  6469. if (L'\0' != *pwszCombinedError)
  6470. {
  6471. wcscat(pwszCombinedError, g_wszNewLine);
  6472. }
  6473. wcscat(pwszCombinedError, g_pwszInfErrorString);
  6474. }
  6475. if (NULL != pwszMessage2)
  6476. {
  6477. if (L'\0' != *pwszCombinedError)
  6478. {
  6479. wcscat(pwszCombinedError, g_wszNewLine);
  6480. }
  6481. wcscat(pwszCombinedError, pwszMessage2);
  6482. }
  6483. if (NULL != g_pwszUnreferencedSectionNames)
  6484. {
  6485. if (L'\0' != *pwszCombinedError)
  6486. {
  6487. wcscat(pwszCombinedError, g_wszNewLine);
  6488. }
  6489. wcscat(pwszCombinedError, g_pwszUnreferencedSectionNames);
  6490. }
  6491. pwsz = pwszCombinedError;
  6492. }
  6493. }
  6494. if (NULL == pwsz)
  6495. {
  6496. pwsz = pwszError;
  6497. if (NULL == pwsz)
  6498. {
  6499. pwsz = g_pwszErrorString;
  6500. if (NULL == pwsz)
  6501. {
  6502. pwsz = L"";
  6503. }
  6504. }
  6505. }
  6506. if (!g_fQuiet)
  6507. {
  6508. MessageBox(
  6509. hWnd,
  6510. pwsz,
  6511. pwszTitle,
  6512. MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
  6513. }
  6514. wprintf(L"%ws: %ws\n",
  6515. NULL != pwszTitle? pwszTitle : L"",
  6516. NULL != pwsz? pwsz : L"");
  6517. if (NULL != pwszCombinedError)
  6518. {
  6519. LocalFree(pwszCombinedError);
  6520. }
  6521. if (NULL != pwszError)
  6522. {
  6523. LocalFree(const_cast<WCHAR *>(pwszError));
  6524. }
  6525. if (NULL != pwszMessage)
  6526. {
  6527. LocalFree(pwszMessage);
  6528. }
  6529. if (NULL != pwszMessage2)
  6530. {
  6531. LocalFree(pwszMessage2);
  6532. }
  6533. if (NULL != pwszTitle)
  6534. {
  6535. LocalFree(pwszTitle);
  6536. }
  6537. }
  6538. //**************************************************************************
  6539. // FUNCTION: MainWndProc(...)
  6540. // ARGUMENTS:
  6541. //**************************************************************************
  6542. LRESULT APIENTRY
  6543. MainWndProc(
  6544. HWND hWnd,
  6545. UINT msg,
  6546. WPARAM wParam,
  6547. LPARAM lParam)
  6548. {
  6549. WCHAR *pwszCmdLine = NULL;
  6550. HRESULT hr;
  6551. LRESULT lr = 0;
  6552. switch(msg)
  6553. {
  6554. case WM_CREATE:
  6555. case WM_SIZE:
  6556. break;
  6557. case WM_DESTROY:
  6558. PostQuitMessage(0);
  6559. break;
  6560. case WM_DOCERTREQDIALOGS:
  6561. pwszCmdLine = (WCHAR*)lParam;
  6562. hr = CertReqPreMain(pwszCmdLine, hWnd);
  6563. if ((S_OK != hr && HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr) ||
  6564. NULL != g_pwszUnreferencedSectionNames)
  6565. {
  6566. CertReqErrorDisplay(hr, hWnd);
  6567. }
  6568. PostQuitMessage(hr);
  6569. break;
  6570. default:
  6571. lr = DefWindowProc(hWnd, msg, wParam, lParam);
  6572. break;
  6573. }
  6574. return(lr);
  6575. }
  6576. static BOOL s_fLogOpened = FALSE;
  6577. VOID
  6578. LogOpen(
  6579. IN BOOL fForceOpen)
  6580. {
  6581. BOOL fOpenLog;
  6582. DbgPrintfInit("+"); // reinitialize debug print mask first
  6583. fOpenLog = DbgIsSSActive(DBG_SS_OPENLOG);
  6584. if (fOpenLog || fForceOpen)
  6585. {
  6586. if (!s_fLogOpened)
  6587. {
  6588. DbgPrintfInit("+certreq.log"); // open the log file
  6589. s_fLogOpened = TRUE;
  6590. DbgLogFileVersion("certreq.exe", szCSVER_STR);
  6591. }
  6592. }
  6593. }
  6594. VOID
  6595. LogClose()
  6596. {
  6597. if (s_fLogOpened)
  6598. {
  6599. DbgPrintfInit("-"); // close the log file
  6600. s_fLogOpened = FALSE;
  6601. }
  6602. }
  6603. //+------------------------------------------------------------------------
  6604. //
  6605. // Function: wWinMain()
  6606. //
  6607. // Synopsis: Entry Point
  6608. //
  6609. // Arguments: [hInstance] -- Instance handle
  6610. // [hPrevInstance] -- Obsolete
  6611. // [pwszCmdLine] -- App command line
  6612. // [nCmdShow] -- Starting show state
  6613. //
  6614. // History: 12/07/96 JerryK Added this Comment
  6615. //
  6616. //-------------------------------------------------------------------------
  6617. extern "C" int APIENTRY
  6618. wWinMain(
  6619. HINSTANCE hInstance,
  6620. HINSTANCE, // hPrevInstance
  6621. LPWSTR pwszCmdLine,
  6622. int /* nCmdShow */ )
  6623. {
  6624. HRESULT hr;
  6625. MSG msg;
  6626. WNDCLASS wcApp;
  6627. HWND hWndMain;
  6628. WCHAR *pwszAppName = NULL;
  6629. WCHAR *pwszWindowName = NULL;
  6630. _setmode(_fileno(stdout), _O_TEXT);
  6631. _wsetlocale(LC_ALL, L".OCP");
  6632. mySetThreadUILanguage(0);
  6633. LogOpen(FALSE);
  6634. hr = myLoadRCString(hInstance, IDS_APP_NAME, &pwszAppName);
  6635. _PrintIfError(hr, "myLoadRCString(IDS_APP_NAME)");
  6636. hr = myLoadRCString(hInstance, IDS_WINDOW_NAME, &pwszWindowName);
  6637. _PrintIfError(hr, "myLoadRCString(IDS_WINDOW_NAME)");
  6638. // Save the current instance
  6639. g_hInstance = hInstance;
  6640. // Set up the application's window class
  6641. wcApp.style = 0;
  6642. wcApp.lpfnWndProc = MainWndProc;
  6643. wcApp.cbClsExtra = 0;
  6644. wcApp.cbWndExtra = 0;
  6645. wcApp.hInstance = hInstance;
  6646. wcApp.hIcon = LoadIcon(NULL,IDI_APPLICATION);
  6647. wcApp.hCursor = LoadCursor(NULL,IDC_ARROW);
  6648. wcApp.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  6649. wcApp.lpszMenuName = NULL;
  6650. wcApp.lpszClassName = pwszAppName;
  6651. if (!RegisterClass(&wcApp))
  6652. {
  6653. return(FALSE);
  6654. }
  6655. // Create Main Window
  6656. hWndMain = CreateWindow(
  6657. pwszAppName,
  6658. pwszWindowName,
  6659. WS_OVERLAPPEDWINDOW,
  6660. CW_USEDEFAULT,
  6661. CW_USEDEFAULT,
  6662. CW_USEDEFAULT,
  6663. CW_USEDEFAULT,
  6664. NULL,
  6665. NULL,
  6666. hInstance,
  6667. NULL);
  6668. if (NULL == hWndMain)
  6669. {
  6670. return(FALSE);
  6671. }
  6672. // Make window visible
  6673. // ShowWindow(hWndMain,nCmdShow);
  6674. // Update window client area
  6675. UpdateWindow(hWndMain);
  6676. // Send off the message to get things started
  6677. PostMessage(hWndMain,WM_DOCERTREQDIALOGS,0,(LPARAM)pwszCmdLine);
  6678. // Message Loop
  6679. while (GetMessage(&msg,NULL,0,0))
  6680. {
  6681. TranslateMessage(&msg);
  6682. DispatchMessage(&msg);
  6683. }
  6684. if (NULL != g_pwszErrorString)
  6685. {
  6686. LocalFree(g_pwszErrorString);
  6687. }
  6688. if (NULL != g_pwszInfErrorString)
  6689. {
  6690. LocalFree(g_pwszInfErrorString);
  6691. }
  6692. if (NULL != g_pwszUnreferencedSectionNames)
  6693. {
  6694. LocalFree(g_pwszUnreferencedSectionNames);
  6695. }
  6696. if (NULL != pwszAppName)
  6697. {
  6698. LocalFree(pwszAppName);
  6699. }
  6700. if (NULL != pwszWindowName)
  6701. {
  6702. LocalFree(pwszWindowName);
  6703. }
  6704. myInfClearError();
  6705. myFreeResourceStrings("certreq.exe");
  6706. myFreeColumnDisplayNames();
  6707. myRegisterMemDump();
  6708. LogClose();
  6709. return((int)msg.wParam);
  6710. }