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

5890 lines
126 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 "resource.h"
  38. #include "csdisp.h"
  39. #include "cscsp.h"
  40. #include "csprop.h"
  41. #include "clibres.h"
  42. #include "csresstr.h"
  43. #define CR_IN_CERT CR_IN_FORMATMASK
  44. #define wprintf myConsolePrintf
  45. #define WM_DOCERTREQDIALOGS WM_USER+0
  46. HINSTANCE g_hInstance;
  47. typedef struct _IDSUSAGE {
  48. DWORD idsVerb;
  49. DWORD idsOptions;
  50. WCHAR const *pwszVerb;
  51. } IDSUSAGE;
  52. #define cmdNONE MAXDWORD
  53. IDSUSAGE g_aidsUsage[] = {
  54. #define cmdSUBMITREQUEST 0
  55. { IDS_USAGE_VERB_DEFAULT, IDS_USAGE_OPTIONS_DEFAULT, L"Submit" },
  56. #define cmdRETRIEVEPENDING 1
  57. { IDS_USAGE_VERB_RETRIEVE, IDS_USAGE_OPTIONS_RETRIEVE, L"Retrieve" },
  58. #define cmdNEWREQUEST 2
  59. { IDS_USAGE_VERB_NEW, IDS_USAGE_OPTIONS_NEW, L"New" },
  60. #define cmdACCEPTRESPONSE 3
  61. { IDS_USAGE_VERB_ACCEPT, IDS_USAGE_OPTIONS_ACCEPT, L"Accept" },
  62. #define cmdQUALIFIEDREQUEST 4
  63. { IDS_USAGE_VERB_POLICY, IDS_USAGE_OPTIONS_POLICY, L"Policy" },
  64. #define cmdSIGNREQUEST 5
  65. { IDS_USAGE_VERB_SIGN, IDS_USAGE_OPTIONS_SIGN, L"Sign" },
  66. };
  67. WCHAR *g_apwszOptionStrings[] = {
  68. L"any", // %1
  69. L"attrib", // %2
  70. L"binary", // %3
  71. L"cert", // %4
  72. L"config", // %5
  73. L"crl", // %6
  74. L"f", // %7
  75. L"q", // %8
  76. L"rpc", // %9
  77. L"v", // %10
  78. L"?", // %11
  79. L"v1", // %12
  80. L"idispatch", // %13
  81. };
  82. DWORD g_dwCommand = cmdNONE;
  83. BOOL g_fAny = FALSE;
  84. BOOL g_fRPC = FALSE;
  85. BOOL g_fIDispatch = FALSE;
  86. BOOL g_fForce = FALSE;
  87. BOOL g_fQuiet = FALSE;
  88. BOOL g_fV1Interface = FALSE;
  89. BOOL g_fFullUsage = FALSE;
  90. BOOL g_fVerbose = FALSE;
  91. BOOL g_idError = 0;
  92. LONG g_dwOutFormat = CV_OUT_BASE64REQUESTHEADER;
  93. DWORD g_dwUIFlag = CC_UIPICKCONFIG;
  94. DWORD g_dwCRLIn = 0;
  95. DWORD g_dwCRLOut = 0;
  96. WCHAR *g_pwszErrorString = NULL;
  97. WCHAR *g_pwszConfig = NULL;
  98. WCHAR *g_pwszCertCN = NULL;
  99. WCHAR const g_wszNewLine[] = L"\n";
  100. CHAR const *g_pszObjIdHash = szOID_OIWSEC_sha1;
  101. #define wszINFSECTION_NEWREQUEST L"NewRequest"
  102. #define wszINFKEY_SUBJECT L"Subject"
  103. #define wszINFKEY_PRIVATEKEYARCHIVE L"PrivateKeyArchive"
  104. #define wszINFKEY_KEYSPEC L"KeySpec"
  105. #define wszINFKEY_KEYLENGTH L"KeyLength"
  106. #define wszINFKEY_RENEWALCERT L"RenewalCert"
  107. #define wszINFKEY_SMIME L"SMIME"
  108. #define wszINFKEY_EXPORTABLE L"Exportable"
  109. #define wszINFKEY_USERPROTECTED L"UserProtected"
  110. #define wszINFKEY_KEYCONTAINER L"KeyContainer"
  111. #define wszINFKEY_HASHALGID L"HashAlgId"
  112. #define wszINFKEY_HASHALGORITHM L"HashAlgorithm"
  113. #define wszINFKEY_MACHINEKEYSET L"MachineKeySet"
  114. #define wszINFKEY_SILENT L"Silent"
  115. #define wszINFKEY_PROVIDERNAME L"ProviderName"
  116. #define wszINFKEY_PROVIDERTYPE L"ProviderType"
  117. #define wszINFKEY_USEEXISTINHKEYSET L"UseExistingKeySet"
  118. #define wszINFKEY_REQUESTERNAME wszPROPREQUESTERNAME
  119. #define wszINFKEY_REQUESTTYPE L"RequestType"
  120. #define wszINFVALUE_REQUESTTYPE_PKCS101 L"PKCS10-"
  121. #define wszINFVALUE_REQUESTTYPE_PKCS10 L"PKCS10"
  122. #define wszINFVALUE_REQUESTTYPE_PKCS7 L"PKCS7"
  123. #define wszINFVALUE_REQUESTTYPE_CMC L"CMC"
  124. typedef struct _INFUSAGE
  125. {
  126. WCHAR const *pwszKey;
  127. } INFUSAGE;
  128. WCHAR const *g_apwszInfKeyNewRequest[] = {
  129. wszINFKEY_SUBJECT L" = \"CN=..,OU=...,DC=...\"",
  130. wszINFKEY_PRIVATEKEYARCHIVE L" = TRUE",
  131. wszINFKEY_KEYSPEC L" = 1",
  132. wszINFKEY_KEYLENGTH L" = 1024",
  133. wszINFKEY_RENEWALCERT L" = CertId",
  134. wszINFKEY_SMIME L" = TRUE",
  135. wszINFKEY_EXPORTABLE L" = TRUE",
  136. wszINFKEY_USERPROTECTED L" = TRUE",
  137. wszINFKEY_KEYCONTAINER L" = \"...\"",
  138. #if 0
  139. wszINFKEY_HASHALGID L" = ???",
  140. wszINFKEY_HASHALGORITHM L" = ???",
  141. #endif
  142. wszINFKEY_MACHINEKEYSET L" = TRUE",
  143. wszINFKEY_SILENT L" = TRUE",
  144. wszINFKEY_PROVIDERNAME L" = \"" MS_ENHANCED_PROV_W L"\"",
  145. wszINFKEY_PROVIDERTYPE L" = 1",
  146. wszINFKEY_USEEXISTINHKEYSET L" = TRUE",
  147. wszINFKEY_REQUESTERNAME L" = DOMAIN\\User",
  148. wszINFKEY_REQUESTTYPE L" = " wszINFVALUE_REQUESTTYPE_PKCS7,
  149. };
  150. // Save eror string: "foo.inf" or "foo.inf(key = "value", "value")"
  151. HRESULT
  152. SetErrorStringInf(
  153. IN WCHAR const *pwszString,
  154. OPTIONAL IN INFVALUES *pInfValues)
  155. {
  156. HRESULT hr;
  157. if (NULL == g_pwszErrorString && NULL != pwszString)
  158. {
  159. DWORD cwc = wcslen(pwszString);
  160. DWORD i;
  161. if (NULL != pInfValues && NULL != pInfValues->pwszKey)
  162. {
  163. cwc += 1 + wcslen(pInfValues->pwszKey) + 2 + 1;
  164. for (i = 0; i < pInfValues->cValues; i++)
  165. {
  166. if (NULL == pInfValues->rgpwszValues[i])
  167. {
  168. break;
  169. }
  170. if (0 != i)
  171. {
  172. cwc++;
  173. }
  174. cwc += 2 + wcslen(pInfValues->rgpwszValues[i]) + 1;
  175. }
  176. }
  177. g_pwszErrorString = (WCHAR *) LocalAlloc(
  178. LMEM_FIXED,
  179. (cwc + 1) * sizeof(WCHAR));
  180. if (NULL == g_pwszErrorString)
  181. {
  182. hr = E_OUTOFMEMORY;
  183. _JumpError(hr, error, "LocalAlloc");
  184. }
  185. wcscpy(g_pwszErrorString, pwszString);
  186. if (NULL != pInfValues && NULL != pInfValues->pwszKey)
  187. {
  188. wcscat(g_pwszErrorString, wszLPAREN);
  189. wcscat(g_pwszErrorString, pInfValues->pwszKey);
  190. wcscat(g_pwszErrorString, L" =");
  191. for (i = 0; i < pInfValues->cValues; i++)
  192. {
  193. if (NULL == pInfValues->rgpwszValues[i])
  194. {
  195. break;
  196. }
  197. if (0 != i)
  198. {
  199. wcscat(g_pwszErrorString, L",");
  200. }
  201. wcscat(g_pwszErrorString, L" \"");
  202. wcscat(g_pwszErrorString, pInfValues->rgpwszValues[i]);
  203. wcscat(g_pwszErrorString, L"\"");
  204. }
  205. wcscat(g_pwszErrorString, wszRPAREN);
  206. }
  207. }
  208. hr = S_OK;
  209. error:
  210. return(hr);
  211. }
  212. VOID
  213. SetErrorString(
  214. IN WCHAR const *pwszString)
  215. {
  216. SetErrorStringInf(pwszString, NULL);
  217. }
  218. HRESULT
  219. DisplayResourceString(
  220. IN DWORD idsMsg,
  221. OPTIONAL IN WCHAR const * const *papwszString,
  222. OPTIONAL OUT WCHAR **ppwszFormatted)
  223. {
  224. HRESULT hr;
  225. WCHAR *pwszRaw = NULL;
  226. WCHAR *pwszFormatted = NULL;
  227. if (NULL != ppwszFormatted)
  228. {
  229. *ppwszFormatted = NULL;
  230. }
  231. hr = myLoadRCString(g_hInstance, idsMsg, &pwszRaw);
  232. _JumpIfError(hr, error, "myLoadRCString");
  233. if (0 == FormatMessage(
  234. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  235. FORMAT_MESSAGE_FROM_STRING |
  236. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  237. (VOID *) pwszRaw,
  238. 0, // dwMessageID
  239. 0, // dwLanguageID
  240. (LPWSTR) &pwszFormatted,
  241. 0,
  242. (va_list *) papwszString))
  243. {
  244. hr = myHLastError();
  245. wprintf(pwszRaw);
  246. _JumpError(hr, error, "FormatMessage");
  247. }
  248. if (NULL != ppwszFormatted)
  249. {
  250. *ppwszFormatted = pwszFormatted;
  251. pwszFormatted = NULL;
  252. }
  253. else
  254. {
  255. wprintf(pwszFormatted);
  256. }
  257. error:
  258. if (NULL != pwszRaw)
  259. {
  260. LocalFree(pwszRaw);
  261. }
  262. if (NULL != pwszFormatted)
  263. {
  264. LocalFree(pwszFormatted);
  265. }
  266. return(hr);
  267. }
  268. DWORD g_aidsOptions[] =
  269. {
  270. IDS_USAGE_OPTION_ANY,
  271. IDS_USAGE_OPTION_ATTRIB,
  272. IDS_USAGE_OPTION_BINARY,
  273. IDS_USAGE_OPTION_CERT,
  274. IDS_USAGE_OPTION_CONFIG,
  275. IDS_USAGE_OPTION_CRL,
  276. IDS_USAGE_OPTION_F,
  277. IDS_USAGE_OPTION_Q,
  278. IDS_USAGE_OPTION_RPC,
  279. IDS_USAGE_OPTION_VERBOSE,
  280. IDS_USAGE_OPTION_QUESTION,
  281. };
  282. DWORD g_aidsOptionsFull[] =
  283. {
  284. IDS_USAGE_OPTION_V1,
  285. IDS_USAGE_OPTION_IDISPATCH,
  286. };
  287. // Option description formatting:
  288. // Resource string contains "%2 <Arg>\nDescription\nMore description\n"
  289. // To format:
  290. // insert " -" in front of the first line and skip the newline,
  291. // insert space to pad out to N-2 columns and "- " before the second line,
  292. // insert space to pad out to N columns before all additional lines.
  293. #define cwcINDENT 28 // ----+
  294. // |
  295. /* v
  296. -Optiom <Arg> - Description\n
  297. More description\n
  298. */
  299. VOID
  300. DisplayOptionList(
  301. IN DWORD cOpt,
  302. IN DWORD *aidsOpt)
  303. {
  304. HRESULT hr;
  305. DWORD i;
  306. for (i = 0; i < cOpt; i++)
  307. {
  308. WCHAR *pwszFormatted = NULL;
  309. WCHAR const *pwszPrefix;
  310. WCHAR *pwsz;
  311. DWORD j;
  312. DWORD iLine;
  313. DWORD cwc0;
  314. DisplayResourceString(aidsOpt[i], g_apwszOptionStrings, &pwszFormatted);
  315. if (NULL == pwszFormatted)
  316. {
  317. continue;
  318. }
  319. pwsz = pwszFormatted;
  320. iLine = 0;
  321. while (L'\0' != *pwsz)
  322. {
  323. WCHAR const *pwszNewLine = L"\n";
  324. DWORD cwcPad;
  325. j = wcscspn(pwsz, L"\r\n");
  326. switch (iLine)
  327. {
  328. WCHAR wc;
  329. case 0:
  330. cwcPad = 2;
  331. pwszPrefix = L"-";
  332. wc = pwsz[j];
  333. pwsz[j] = L'\0';
  334. cwc0 = cwcPad +
  335. wcslen(pwszPrefix) +
  336. myGetDisplayLength(pwsz);
  337. pwsz[j] = wc;
  338. pwszNewLine = L"";
  339. break;
  340. case 1:
  341. cwcPad = 1;
  342. if (cwcINDENT > 2 + cwc0)
  343. {
  344. cwcPad = cwcINDENT - (2 + cwc0);
  345. }
  346. pwszPrefix = L"- ";
  347. break;
  348. default:
  349. cwcPad = cwcINDENT;
  350. pwszPrefix = L"";
  351. break;
  352. }
  353. wprintf(
  354. L"%*ws%ws%.*ws%ws",
  355. cwcPad,
  356. L"",
  357. pwszPrefix,
  358. j,
  359. pwsz,
  360. pwszNewLine);
  361. pwsz += j;
  362. if (L'\r' == *pwsz)
  363. {
  364. pwsz++;
  365. }
  366. if (L'\n' == *pwsz)
  367. {
  368. pwsz++;
  369. }
  370. iLine++;
  371. }
  372. LocalFree(pwszFormatted);
  373. }
  374. }
  375. VOID
  376. Usage(
  377. IN BOOL fError)
  378. {
  379. HRESULT hr;
  380. WCHAR *pwszUsage = NULL;
  381. IDSUSAGE *pidsUsage;
  382. IDSUSAGE *pidsUsageEnd;
  383. BOOL fShowOptions;
  384. DisplayResourceString(IDS_USAGE_GENERAL, NULL, NULL);
  385. wprintf(L"\n");
  386. switch (g_dwCommand)
  387. {
  388. case cmdSUBMITREQUEST:
  389. case cmdRETRIEVEPENDING:
  390. case cmdNEWREQUEST:
  391. case cmdACCEPTRESPONSE:
  392. case cmdQUALIFIEDREQUEST:
  393. case cmdSIGNREQUEST:
  394. pidsUsage = &g_aidsUsage[g_dwCommand];
  395. pidsUsageEnd = &pidsUsage[1];
  396. fShowOptions = TRUE;
  397. break;
  398. case cmdNONE:
  399. default:
  400. pidsUsage = g_aidsUsage;
  401. pidsUsageEnd = &g_aidsUsage[ARRAYSIZE(g_aidsUsage)];
  402. fShowOptions = g_fVerbose;
  403. break;
  404. }
  405. if (fError)
  406. {
  407. fShowOptions = FALSE;
  408. }
  409. for ( ; pidsUsage < pidsUsageEnd; pidsUsage++)
  410. {
  411. DisplayResourceString(pidsUsage->idsVerb, &pidsUsage->pwszVerb, NULL);
  412. if (fShowOptions)
  413. {
  414. DisplayResourceString(pidsUsage->idsOptions, g_apwszOptionStrings, NULL);
  415. }
  416. wprintf(L"\n");
  417. }
  418. if (fShowOptions)
  419. {
  420. DisplayResourceString(IDS_USAGE_OPTIONS_DESCRIPTION, NULL, NULL);
  421. DisplayOptionList(ARRAYSIZE(g_aidsOptions), g_aidsOptions);
  422. if (g_fFullUsage)
  423. {
  424. DisplayOptionList(ARRAYSIZE(g_aidsOptionsFull), g_aidsOptionsFull);
  425. }
  426. wprintf(L"\n");
  427. DisplayResourceString(IDS_USAGE_DESCRIPTION, g_apwszOptionStrings, NULL);
  428. }
  429. if (!fError)
  430. {
  431. if ((cmdNEWREQUEST == g_dwCommand ||
  432. (cmdNONE == g_dwCommand && g_fVerbose)))
  433. {
  434. DWORD i;
  435. wprintf(L"[%ws]\n", wszINFSECTION_NEWREQUEST);
  436. for (i = 0; i < ARRAYSIZE(g_apwszInfKeyNewRequest); i++)
  437. {
  438. wprintf(L" %ws\n", g_apwszInfKeyNewRequest[i]);
  439. }
  440. }
  441. }
  442. exit(0);
  443. }
  444. VOID
  445. AppendAttributeString(
  446. IN OUT WCHAR *pwszOut,
  447. IN WCHAR const *pwszIn)
  448. {
  449. pwszOut += wcslen(pwszOut);
  450. while (L'\0' != *pwszIn)
  451. {
  452. switch (*pwszIn)
  453. {
  454. case L';':
  455. *pwszOut = L'\n';
  456. break;
  457. case L'\\':
  458. if (L'n' == pwszIn[1])
  459. {
  460. *pwszOut = L'\n';
  461. pwszIn++;
  462. break;
  463. }
  464. if (L'r' == pwszIn[1])
  465. {
  466. *pwszOut = L'\r';
  467. pwszIn++;
  468. break;
  469. }
  470. // else FALLTHROUGH
  471. default:
  472. *pwszOut = *pwszIn;
  473. break;
  474. }
  475. pwszOut++;
  476. pwszIn++;
  477. }
  478. *pwszOut = L'\0';
  479. }
  480. HRESULT
  481. crCombineAttributes(
  482. IN WCHAR const *pwszAttributesAdd,
  483. IN OUT WCHAR **ppwszAttributesExisting)
  484. {
  485. HRESULT hr;
  486. DWORD cwc;
  487. WCHAR *pwszAttributesExisting = *ppwszAttributesExisting;
  488. WCHAR *pwsz;
  489. cwc = wcslen(pwszAttributesAdd) + 1;
  490. if (NULL != pwszAttributesExisting)
  491. {
  492. cwc += wcslen(pwszAttributesExisting) + 1;
  493. }
  494. pwsz = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  495. if (NULL == pwsz)
  496. {
  497. hr = E_OUTOFMEMORY;
  498. _JumpError(hr, error, "LocalAlloc");
  499. }
  500. pwsz[0] = L'\0';
  501. if (NULL != pwszAttributesExisting)
  502. {
  503. AppendAttributeString(pwsz, pwszAttributesExisting);
  504. AppendAttributeString(pwsz, L"\\n");
  505. LocalFree(pwszAttributesExisting);
  506. }
  507. AppendAttributeString(pwsz, pwszAttributesAdd);
  508. *ppwszAttributesExisting = pwsz;
  509. hr = S_OK;
  510. error:
  511. return(hr);
  512. }
  513. VOID
  514. crMissingFileArg()
  515. {
  516. HRESULT hr;
  517. WCHAR *pwszMsg = NULL;
  518. hr = myLoadRCString(g_hInstance, IDS_ERROR_NO_FILENAME, &pwszMsg);
  519. _JumpIfError(hr, error, "myLoadRCString");
  520. CSASSERT(NULL != pwszMsg);
  521. wprintf(pwszMsg);
  522. wprintf(g_wszNewLine);
  523. error:
  524. if (NULL != pwszMsg)
  525. {
  526. LocalFree(pwszMsg);
  527. }
  528. }
  529. HRESULT
  530. crGetOpenFileName(
  531. IN HWND hWndOwner,
  532. IN UINT idsOpenTitle,
  533. IN UINT idsFileFilter,
  534. IN UINT idsFileDefExt,
  535. OUT WCHAR **ppwszOFN)
  536. {
  537. HRESULT hr;
  538. if (g_fQuiet)
  539. {
  540. crMissingFileArg();
  541. Usage(TRUE);
  542. }
  543. // Put up a file dialog to prompt the user for Inf File
  544. // 0 == hr means dialog was cancelled, we cheat because S_OK == 0
  545. hr = myGetOpenFileName(
  546. hWndOwner,
  547. NULL, // hInstance
  548. idsOpenTitle,
  549. idsFileFilter,
  550. idsFileDefExt,
  551. OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY,
  552. NULL, // no default file
  553. ppwszOFN);
  554. _JumpIfError(hr, error, "myGetOpenFileName");
  555. if (NULL == *ppwszOFN)
  556. {
  557. // cancelled:
  558. // see public\sdk\inc\cderr.h for real CommDlgExtendedError errors
  559. hr = myHError(CommDlgExtendedError());
  560. if (S_OK == hr)
  561. {
  562. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  563. }
  564. _JumpError(hr, error, "myGetOpenFileName");
  565. }
  566. hr = S_OK;
  567. error:
  568. return(hr);
  569. }
  570. HRESULT
  571. crOverwriteFileAllowed(
  572. IN HWND hWndOwner,
  573. IN WCHAR const *pwszfnOut)
  574. {
  575. HRESULT hr;
  576. int rc = IDCANCEL;
  577. WCHAR *pwszTitle = NULL;
  578. WCHAR *pwszMessage = NULL;
  579. WCHAR *pwsz = NULL;
  580. if (!g_fForce && myDoesFileExist(pwszfnOut))
  581. {
  582. if (!g_fQuiet)
  583. {
  584. DWORD cwc;
  585. hr = myLoadRCString(g_hInstance, IDS_CERTREQ_TITLE, &pwszTitle);
  586. _JumpIfError(hr, error, "myLoadRCString");
  587. hr = myLoadRCString(g_hInstance, IDS_OVERWRITE_FILE, &pwszMessage);
  588. _JumpIfError(hr, error, "myLoadRCString");
  589. cwc = wcslen(pwszMessage) + 2 + wcslen(pwszfnOut);
  590. pwsz = (WCHAR *) LocalAlloc(LMEM_FIXED, (1 + cwc) * sizeof(WCHAR));
  591. if (NULL == pwsz)
  592. {
  593. hr = E_OUTOFMEMORY;
  594. _JumpError(hr, error, "LocalAlloc");
  595. }
  596. wcscpy(pwsz, pwszMessage);
  597. wcscat(pwsz, L"\r\n");
  598. wcscat(pwsz, pwszfnOut);
  599. rc = MessageBox(
  600. hWndOwner,
  601. pwsz,
  602. pwszTitle,
  603. MB_OKCANCEL |
  604. MB_DEFBUTTON2 |
  605. MB_ICONWARNING |
  606. MB_SETFOREGROUND);
  607. }
  608. if (IDOK != rc)
  609. {
  610. SetErrorString(pwszfnOut);
  611. hr = g_fQuiet?
  612. HRESULT_FROM_WIN32(ERROR_FILE_EXISTS) :
  613. HRESULT_FROM_WIN32(ERROR_CANCELLED);
  614. _JumpErrorStr(hr, error, "File Exists", pwszfnOut);
  615. }
  616. }
  617. hr = S_OK;
  618. error:
  619. if (NULL != pwsz)
  620. {
  621. LocalFree(pwsz);
  622. }
  623. if (NULL != pwszTitle)
  624. {
  625. LocalFree(pwszTitle);
  626. }
  627. if (NULL != pwszMessage)
  628. {
  629. LocalFree(pwszMessage);
  630. }
  631. return(hr);
  632. }
  633. HRESULT
  634. WriteCertificateOrRequest(
  635. IN HWND hWndOwner,
  636. OPTIONAL IN DISPATCHINTERFACE *pdiRequest,
  637. OPTIONAL IN BYTE const *pbOut,
  638. IN DWORD cbOut,
  639. IN DWORD Flags,
  640. OPTIONAL IN WCHAR const *pwszfnOut)
  641. {
  642. HRESULT hr;
  643. WCHAR *pwszOFN = NULL;
  644. BSTR strCert = NULL;
  645. CHAR *pszCert = NULL;
  646. DWORD decFlags = CRYPT_STRING_BINARY;
  647. WCHAR const *pwszTitle;
  648. WCHAR const *pwszMessage;
  649. BOOL fCheckFileOverwriteOK = TRUE; // careful not to overwrite without prompting user
  650. if (NULL == pwszfnOut)
  651. {
  652. if (g_fQuiet)
  653. {
  654. crMissingFileArg();
  655. Usage(TRUE);
  656. }
  657. // Put up a file dialog to prompt the user for Cert file
  658. // 0 == hr means dialog was cancelled, we cheat because S_OK == 0
  659. hr = myGetSaveFileName(
  660. hWndOwner,
  661. NULL, // hInstance
  662. IDS_REQUEST_OUTFILE_TITLE,
  663. IDS_REQUEST_FILTER2,
  664. 0, //no def ext
  665. OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT,
  666. NULL, // no default file
  667. &pwszOFN);
  668. _JumpIfError(hr, error, "myGetSaveFileName");
  669. fCheckFileOverwriteOK = FALSE; // OFN_OVERWRITEPROMPT should have prompted if necessary
  670. if (NULL == pwszOFN)
  671. {
  672. // cancelled:
  673. // see public\sdk\inc\cderr.h for real CommDlgExtendedError errors
  674. hr = myHError(CommDlgExtendedError());
  675. _JumpError(hr, error, "myGetSaveFileName");
  676. }
  677. pwszfnOut = pwszOFN;
  678. hr = myIsDirWriteable(pwszfnOut, TRUE);
  679. if (S_OK != hr)
  680. {
  681. SetErrorString(pwszfnOut);
  682. _JumpErrorStr(hr, error, "IsDirWriteable", pwszfnOut);
  683. }
  684. }
  685. if (NULL == pbOut)
  686. {
  687. hr = Request_GetCertificate(pdiRequest, Flags, &strCert);
  688. _JumpIfError(hr, error, "Request_GetCertificate");
  689. if (CR_OUT_BINARY == (CR_OUT_ENCODEMASK & Flags))
  690. {
  691. cbOut = SysStringByteLen(strCert);
  692. pbOut = (BYTE const *) strCert;
  693. }
  694. else
  695. {
  696. if (!ConvertWszToSz(&pszCert, strCert, -1))
  697. {
  698. hr = E_OUTOFMEMORY;
  699. _JumpError(hr, error, "ConvertWszToSz(cert)");
  700. }
  701. cbOut = strlen(pszCert);
  702. pbOut = (BYTE const *) pszCert;
  703. }
  704. }
  705. else
  706. {
  707. decFlags = CR_OUT_ENCODEMASK & Flags;
  708. CSASSERT(CR_OUT_BASE64HEADER == CRYPT_STRING_BASE64HEADER);
  709. CSASSERT(CR_OUT_BINARY == CRYPT_STRING_BINARY);
  710. }
  711. if (fCheckFileOverwriteOK)
  712. {
  713. hr = crOverwriteFileAllowed(hWndOwner, pwszfnOut);
  714. _JumpIfError(hr, error, "crOverwriteFileAllowed");
  715. }
  716. hr = EncodeToFileW(
  717. pwszfnOut,
  718. pbOut,
  719. cbOut,
  720. DECF_FORCEOVERWRITE | decFlags);
  721. if (S_OK != hr)
  722. {
  723. SetErrorString(pwszfnOut);
  724. _JumpErrorStr(hr, error, "EncodeToFileW", pwszfnOut);
  725. }
  726. error:
  727. if (NULL != strCert)
  728. {
  729. SysFreeString(strCert);
  730. }
  731. if (NULL != pszCert)
  732. {
  733. LocalFree(pszCert);
  734. }
  735. if (NULL != pwszOFN)
  736. {
  737. LocalFree(pwszOFN);
  738. }
  739. return(hr);
  740. }
  741. HRESULT
  742. GetLong(
  743. WCHAR const *pwszIn,
  744. LONG *pLong)
  745. {
  746. HRESULT hr = E_INVALIDARG;
  747. WCHAR const *pwsz;
  748. LONG l;
  749. pwsz = pwszIn;
  750. if (NULL == pwsz)
  751. {
  752. _JumpError(hr, error, "NULL parm");
  753. }
  754. if (L'\0' == *pwsz)
  755. {
  756. _JumpError(hr, error, "empty string");
  757. }
  758. if (L'0' == *pwsz && (L'x' == pwsz[1] || L'X' == pwsz[1]))
  759. {
  760. l = 0;
  761. pwsz += 2;
  762. for ( ; L'\0' != *pwsz; pwsz++)
  763. {
  764. if (!iswxdigit(*pwsz))
  765. {
  766. _JumpErrorStr(hr, error, "Non-hex digit", pwszIn);
  767. }
  768. if (0xf0000000 & l)
  769. {
  770. _JumpErrorStr(hr, error, "overflow", pwszIn);
  771. }
  772. l <<= 4;
  773. if (iswdigit(*pwsz))
  774. {
  775. l |= *pwsz - L'0';
  776. }
  777. else if (L'A' <= *pwsz && L'F' >= *pwsz)
  778. {
  779. l |= *pwsz - L'A' + 10;
  780. }
  781. else
  782. {
  783. l |= *pwsz - L'a' + 10;
  784. }
  785. }
  786. *pLong = l;
  787. }
  788. else
  789. {
  790. LARGE_INTEGER li;
  791. li.QuadPart = 0;
  792. for ( ; L'\0' != *pwsz; pwsz++)
  793. {
  794. if (!iswdigit(*pwsz))
  795. {
  796. _JumpErrorStr2(hr, error, "Non-decimal digit", pwszIn, hr);
  797. }
  798. li.QuadPart *= 10;
  799. li.QuadPart += *pwsz - L'0';
  800. if (0 != li.HighPart || 0 > (LONG) li.LowPart)
  801. {
  802. _JumpErrorStr2(hr, error, "overflow", pwszIn, hr);
  803. }
  804. }
  805. *pLong = li.LowPart;
  806. }
  807. hr = S_OK;
  808. //wprintf(L"GetLong(%ws) --> %x (%d)\n", pwszIn, *pLong, *pLong);
  809. error:
  810. return(hr);
  811. }
  812. HRESULT
  813. CheckRequestType(
  814. IN WCHAR const *pwszfnReq,
  815. OUT BYTE **ppbReq,
  816. OUT DWORD *pcbReq,
  817. OUT LONG *pFlags,
  818. OUT BOOL *pfSigned)
  819. {
  820. HRESULT hr;
  821. BYTE *pbReq = NULL;
  822. DWORD cbReq;
  823. DWORD cb;
  824. LONG EncodingType;
  825. LONG RequestType;
  826. BYTE *pbDecoded = NULL;
  827. HCRYPTMSG hMsg = NULL;
  828. char *pszInnerContentObjId = NULL;
  829. CERT_SIGNED_CONTENT_INFO *pcsci = NULL;
  830. DWORD cbcsci;
  831. DWORD dwMsgType;
  832. DWORD cSigner;
  833. DWORD cRecipient;
  834. *ppbReq = NULL;
  835. *pcbReq = NULL;
  836. *pFlags = 0;
  837. *pfSigned = FALSE;
  838. EncodingType = CR_IN_BASE64HEADER;
  839. hr = DecodeFileW(pwszfnReq, &pbReq, &cbReq, CRYPT_STRING_BASE64HEADER);
  840. if (S_OK != hr)
  841. {
  842. //_PrintError(hr, "DecodeFileW(CRYPT_STRING_BASE64HEADER)");
  843. CSASSERT(NULL == pbReq);
  844. EncodingType = CR_IN_BASE64;
  845. hr = DecodeFileW(pwszfnReq, &pbReq, &cbReq, CRYPT_STRING_BASE64);
  846. if (S_OK != hr)
  847. {
  848. //_PrintError(hr, "DecodeFileW(CRYPT_STRING_BASE64)");
  849. CSASSERT(NULL == pbReq);
  850. EncodingType = CR_IN_BINARY;
  851. hr = DecodeFileW(pwszfnReq, &pbReq, &cbReq, CRYPT_STRING_BINARY);
  852. if (S_OK != hr)
  853. {
  854. SetErrorString(pwszfnReq);
  855. _JumpErrorStr(hr, error, "DecodeFileW", pwszfnReq);
  856. }
  857. }
  858. }
  859. CSASSERT(NULL != pbReq);
  860. RequestType = CR_IN_PKCS10;
  861. if (!myDecodeObject(
  862. X509_ASN_ENCODING,
  863. X509_CERT_REQUEST_TO_BE_SIGNED,
  864. pbReq,
  865. cbReq,
  866. CERTLIB_USE_LOCALALLOC,
  867. (VOID **) &pbDecoded,
  868. &cb))
  869. {
  870. //_PrintError(myHLastError(), "myDecodeObject(PKCS10)");
  871. CSASSERT(NULL == pbDecoded);
  872. RequestType = CR_IN_CERT;
  873. if (!myDecodeObject(
  874. X509_ASN_ENCODING,
  875. X509_CERT_TO_BE_SIGNED,
  876. pbReq,
  877. cbReq,
  878. CERTLIB_USE_LOCALALLOC,
  879. (VOID **) &pbDecoded,
  880. &cb))
  881. {
  882. //_PrintError(myHLastError(), "myDecodeObject(Cert)");
  883. CSASSERT(NULL == pbDecoded);
  884. RequestType = CR_IN_KEYGEN;
  885. if (!myDecodeKeyGenRequest(
  886. pbReq,
  887. cbReq,
  888. CERTLIB_USE_LOCALALLOC,
  889. (CERT_KEYGEN_REQUEST_INFO **) &pbDecoded,
  890. &cb))
  891. {
  892. //_PrintError(myHLastError(), "myDecodeKeyGenRequest");
  893. CSASSERT(NULL == pbDecoded);
  894. RequestType = CR_IN_PKCS7; // PKCS 7 renewal request?
  895. hr = myDecodePKCS7(
  896. pbReq,
  897. cbReq,
  898. NULL, // ppbContents
  899. NULL, // pcbContents
  900. &dwMsgType,
  901. &pszInnerContentObjId,
  902. &cSigner,
  903. &cRecipient,
  904. NULL, // phStore
  905. &hMsg);
  906. _JumpIfError(hr, error, "myDecodePKCS7");
  907. if (NULL != pszInnerContentObjId &&
  908. 0 == strcmp(pszInnerContentObjId, szOID_CT_PKI_DATA))
  909. {
  910. RequestType = CR_IN_CMC;
  911. }
  912. if (0 < cSigner)
  913. {
  914. *pfSigned = TRUE;
  915. }
  916. }
  917. }
  918. }
  919. if (CR_IN_CERT == RequestType ||
  920. CR_IN_PKCS10 == RequestType ||
  921. CR_IN_KEYGEN == RequestType)
  922. {
  923. if (!myDecodeObject(
  924. X509_ASN_ENCODING,
  925. X509_CERT,
  926. pbReq,
  927. cbReq,
  928. CERTLIB_USE_LOCALALLOC,
  929. (VOID **) &pcsci,
  930. &cbcsci))
  931. {
  932. hr = myHLastError();
  933. _PrintError2(hr, "myDecodeObject", CRYPT_E_ASN1_BADTAG);
  934. }
  935. else
  936. {
  937. *pfSigned = TRUE; // has a signature
  938. }
  939. }
  940. *ppbReq = pbReq;
  941. pbReq = NULL;
  942. *pcbReq = cbReq;
  943. *pFlags = EncodingType | RequestType;
  944. error:
  945. if (NULL != pcsci)
  946. {
  947. LocalFree(pcsci);
  948. }
  949. if (NULL != pszInnerContentObjId)
  950. {
  951. LocalFree(pszInnerContentObjId);
  952. }
  953. if (NULL != hMsg)
  954. {
  955. CryptMsgClose(hMsg);
  956. }
  957. if (NULL != pbDecoded)
  958. {
  959. LocalFree(pbDecoded);
  960. }
  961. if (NULL != pbReq)
  962. {
  963. LocalFree(pbReq);
  964. }
  965. return(hr);
  966. }
  967. WCHAR *
  968. wszDisposition(
  969. DWORD disposition)
  970. {
  971. HRESULT hr;
  972. UINT iRsc = 0;
  973. WCHAR *pwszDisposition = NULL;
  974. switch (disposition)
  975. {
  976. case CR_DISP_INCOMPLETE:
  977. iRsc = IDS_DISPOSITION_INCOMPLETE;
  978. break;
  979. case CR_DISP_ERROR:
  980. iRsc = IDS_DISPOSITION_ERROR;
  981. break;
  982. case CR_DISP_DENIED:
  983. iRsc = IDS_DISPOSITION_DENIED;
  984. break;
  985. case CR_DISP_ISSUED:
  986. iRsc = IDS_DISPOSITION_ISSUED;
  987. break;
  988. case CR_DISP_ISSUED_OUT_OF_BAND:
  989. iRsc = IDS_DISPOSITION_ISSUED_OOB;
  990. break;
  991. case CR_DISP_UNDER_SUBMISSION:
  992. iRsc = IDS_DISPOSITION_UNDER_SUBMISSION;
  993. break;
  994. case CR_DISP_REVOKED:
  995. iRsc = IDS_DISPOSITION_REVOKED;
  996. break;
  997. default:
  998. iRsc = IDS_DISPOSITION_UNKNOWN;
  999. break;
  1000. }
  1001. hr = myLoadRCString(g_hInstance, iRsc, &pwszDisposition);
  1002. _PrintIfError(hr, "myLoadRCString");
  1003. return(pwszDisposition);
  1004. }
  1005. VOID
  1006. DumpProperty(
  1007. IN DISPATCHINTERFACE *pdiRequest,
  1008. IN LONG PropId,
  1009. IN WCHAR const *pwszPropId,
  1010. IN LONG PropIndex,
  1011. IN LONG PropType,
  1012. OPTIONAL OUT LONG *pCount)
  1013. {
  1014. HRESULT hr;
  1015. LONG Flags;
  1016. VOID *pvOut;
  1017. BSTR str = NULL;
  1018. LONG val;
  1019. DATE date;
  1020. WCHAR wszInfo[128];
  1021. if (NULL != pCount)
  1022. {
  1023. *pCount = 0;
  1024. }
  1025. Flags = CV_OUT_BINARY;
  1026. switch (PropType)
  1027. {
  1028. case PROPTYPE_BINARY:
  1029. Flags = CV_OUT_BASE64HEADER;
  1030. pvOut = &str;
  1031. break;
  1032. case PROPTYPE_STRING:
  1033. pvOut = &str;
  1034. break;
  1035. case PROPTYPE_DATE:
  1036. pvOut = &date;
  1037. break;
  1038. case PROPTYPE_LONG:
  1039. pvOut = &val;
  1040. break;
  1041. }
  1042. wsprintf(wszInfo, L"%ws[%u] %u", pwszPropId, PropIndex, PropType);
  1043. hr = Request2_GetFullResponseProperty(
  1044. pdiRequest,
  1045. PropId,
  1046. PropIndex,
  1047. PropType,
  1048. Flags,
  1049. pvOut);
  1050. if (CERTSRV_E_PROPERTY_EMPTY == hr)
  1051. {
  1052. wprintf(L"%ws: CERTSRV_E_PROPERTY_EMPTY\n", wszInfo);
  1053. }
  1054. _JumpIfErrorStr2(
  1055. hr,
  1056. error,
  1057. "Request2_GetFullResponseProperty",
  1058. wszInfo,
  1059. CERTSRV_E_PROPERTY_EMPTY);
  1060. wprintf(L"%ws:", wszInfo);
  1061. switch (PropType)
  1062. {
  1063. case PROPTYPE_BINARY:
  1064. wprintf(L"\n%ws\n", str);
  1065. break;
  1066. case PROPTYPE_STRING:
  1067. wprintf(L" \"%ws\"\n", str);
  1068. break;
  1069. case PROPTYPE_DATE:
  1070. wprintf(L" %f\n", date);
  1071. break;
  1072. case PROPTYPE_LONG:
  1073. wprintf(L" 0x%x(%u)\n", val, val);
  1074. if (NULL != pCount)
  1075. {
  1076. *pCount = val;
  1077. }
  1078. break;
  1079. }
  1080. error:
  1081. if (NULL != str)
  1082. {
  1083. SysFreeString(str);
  1084. }
  1085. }
  1086. VOID
  1087. DumpIndexedProperty(
  1088. IN DISPATCHINTERFACE *pdiRequest,
  1089. IN LONG PropId,
  1090. IN WCHAR const *pwszPropId,
  1091. IN LONG PropType,
  1092. LONG Count)
  1093. {
  1094. LONG PropIndex;
  1095. for (PropIndex = 0; PropIndex < Count; PropIndex++)
  1096. {
  1097. DumpProperty(pdiRequest, PropId, pwszPropId, PropIndex, PropType, NULL);
  1098. }
  1099. }
  1100. typedef struct _FRPROP
  1101. {
  1102. LONG PropId;
  1103. WCHAR *pwszPropId;
  1104. LONG PropType;
  1105. } FRPROP;
  1106. #define _PROPARG(pt) (pt), L#pt
  1107. FRPROP s_afrp[] =
  1108. {
  1109. { _PROPARG(FR_PROP_BODYPARTSTRING), PROPTYPE_STRING },
  1110. { _PROPARG(FR_PROP_STATUS), PROPTYPE_LONG },
  1111. { _PROPARG(FR_PROP_STATUSSTRING), PROPTYPE_STRING },
  1112. { _PROPARG(FR_PROP_OTHERINFOCHOICE), PROPTYPE_LONG },
  1113. { _PROPARG(FR_PROP_FAILINFO), PROPTYPE_LONG },
  1114. { _PROPARG(FR_PROP_PENDINFOTOKEN), PROPTYPE_BINARY },
  1115. { _PROPARG(FR_PROP_PENDINFOTIME), PROPTYPE_DATE },
  1116. { _PROPARG(FR_PROP_ISSUEDCERTIFICATEHASH), PROPTYPE_BINARY },
  1117. { _PROPARG(FR_PROP_ENCRYPTEDKEYHASH), PROPTYPE_BINARY },
  1118. { _PROPARG(FR_PROP_ISSUEDCERTIFICATE), PROPTYPE_BINARY },
  1119. { _PROPARG(FR_PROP_ISSUEDCERTIFICATECHAIN), PROPTYPE_BINARY },
  1120. { _PROPARG(FR_PROP_ISSUEDCERTIFICATECRLCHAIN), PROPTYPE_BINARY },
  1121. { _PROPARG(FR_PROP_ENCRYPTEDKEYHASH), PROPTYPE_BINARY },
  1122. };
  1123. VOID
  1124. DumpFullResponseProperties(
  1125. IN DISPATCHINTERFACE *pdiRequest)
  1126. {
  1127. LONG cResponse = 0;
  1128. DWORD i;
  1129. DumpProperty(
  1130. pdiRequest,
  1131. _PROPARG(FR_PROP_FULLRESPONSE),
  1132. 0,
  1133. PROPTYPE_BINARY,
  1134. NULL);
  1135. DumpProperty(
  1136. pdiRequest,
  1137. _PROPARG(FR_PROP_FULLRESPONSENOPKCS7),
  1138. 0,
  1139. PROPTYPE_BINARY,
  1140. NULL);
  1141. DumpProperty(
  1142. pdiRequest,
  1143. _PROPARG(FR_PROP_STATUSINFOCOUNT),
  1144. 0,
  1145. PROPTYPE_LONG,
  1146. &cResponse);
  1147. for (i = 0; i < ARRAYSIZE(s_afrp); i++)
  1148. {
  1149. DumpIndexedProperty(
  1150. pdiRequest,
  1151. s_afrp[i].PropId,
  1152. s_afrp[i].pwszPropId,
  1153. s_afrp[i].PropType,
  1154. cResponse);
  1155. }
  1156. }
  1157. HRESULT
  1158. SaveFullResponse(
  1159. IN HWND hWndOwner,
  1160. IN DISPATCHINTERFACE *pdiRequest,
  1161. IN WCHAR const *pwszfnFullResponse)
  1162. {
  1163. HRESULT hr;
  1164. BSTR strFullResponse = NULL;
  1165. hr = Request2_GetFullResponseProperty(
  1166. pdiRequest,
  1167. FR_PROP_FULLRESPONSENOPKCS7,
  1168. 0, // PropIndex
  1169. PROPTYPE_BINARY,
  1170. CV_OUT_BINARY,
  1171. &strFullResponse);
  1172. if (CERTSRV_E_PROPERTY_EMPTY != hr)
  1173. {
  1174. _JumpIfError(hr, error, "Request2_GetFullResponseProperty");
  1175. }
  1176. if (S_OK == hr)
  1177. {
  1178. hr = WriteCertificateOrRequest(
  1179. hWndOwner,
  1180. pdiRequest,
  1181. (BYTE const *) strFullResponse,
  1182. SysStringByteLen(strFullResponse),
  1183. g_dwOutFormat,
  1184. pwszfnFullResponse);
  1185. _JumpIfError(hr, error, "WriteCertificateOrRequest");
  1186. }
  1187. hr = S_OK;
  1188. goto error;
  1189. error:
  1190. if (NULL != strFullResponse)
  1191. {
  1192. SysFreeString(strFullResponse);
  1193. }
  1194. return(hr);
  1195. }
  1196. HRESULT
  1197. CallServerAndStoreCert(
  1198. IN HWND hWndOwner,
  1199. IN WCHAR const *pwszConfig,
  1200. IN DWORD RequestId,
  1201. OPTIONAL IN WCHAR const *pwszSerialNumber,
  1202. OPTIONAL IN WCHAR const *pwszAttributes,
  1203. OPTIONAL IN WCHAR const *pwszfnReq,
  1204. OPTIONAL IN WCHAR const *pwszfnCert,
  1205. OPTIONAL IN WCHAR const *pwszfnCertChain,
  1206. OPTIONAL IN WCHAR const *pwszfnFullResponse)
  1207. {
  1208. HRESULT hr;
  1209. HRESULT hr2;
  1210. BYTE *pbReq = NULL;
  1211. DWORD cbReq;
  1212. LONG dwFlags;
  1213. BOOL fSigned;
  1214. BSTR strRequest = NULL;
  1215. DISPATCHINTERFACE diRequest;
  1216. BOOL fMustRelease = FALSE;
  1217. BSTR strMessage = NULL;
  1218. WCHAR const *pwszMessage;
  1219. CERTSERVERENROLL csEnroll;
  1220. CERTSERVERENROLL *pcsEnroll = NULL;
  1221. WCHAR *pwszServer = NULL;
  1222. WCHAR *pwszAuthority = NULL;
  1223. WCHAR awchr[cwcHRESULTSTRING];
  1224. char const *pszMethod;
  1225. WCHAR *pwszMsg = NULL;
  1226. WCHAR *pwszDispMsg = NULL;
  1227. WCHAR *pwszConfigPlusSerial = NULL;
  1228. BOOL fV1 = g_fV1Interface;
  1229. // If submitting a new request:
  1230. if (NULL != pwszfnReq)
  1231. {
  1232. // Read the request from a file, convert it to binary, and return
  1233. // dwFlags to indicate the orignal encoding and the detected format.
  1234. hr = CheckRequestType(pwszfnReq, &pbReq, &cbReq, &dwFlags, &fSigned);
  1235. _JumpIfError(hr, error, "CheckRequestType");
  1236. if (!fSigned || CR_IN_CERT == (CR_IN_FORMATMASK & dwFlags))
  1237. {
  1238. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1239. SetErrorString(pwszfnReq);
  1240. _JumpError(hr, error, "not a signed request");
  1241. }
  1242. }
  1243. if (1 < g_fRPC)
  1244. {
  1245. hr = mySplitConfigString(pwszConfig, &pwszServer, &pwszAuthority);
  1246. _JumpIfError(hr, error, "mySplitConfigString");
  1247. if (NULL != pwszfnReq)
  1248. {
  1249. // Since CertServerSubmitRequest can only handle binary requests,
  1250. // pass the request in binary form, and set dwFlags to so indicate.
  1251. dwFlags = CR_IN_BINARY | (~CR_IN_ENCODEMASK & dwFlags);
  1252. pszMethod = "CertServerSubmitRequest";
  1253. hr = CertServerSubmitRequest(
  1254. dwFlags | g_dwCRLIn,
  1255. pbReq,
  1256. cbReq,
  1257. pwszAttributes,
  1258. pwszServer,
  1259. pwszAuthority,
  1260. &pcsEnroll);
  1261. _JumpIfError(hr, error, "CertServerSubmitRequest");
  1262. }
  1263. else
  1264. {
  1265. pszMethod = "CertServerRetrievePending";
  1266. hr = CertServerRetrievePending(
  1267. RequestId,
  1268. pwszSerialNumber,
  1269. pwszServer,
  1270. pwszAuthority,
  1271. &pcsEnroll);
  1272. _JumpIfError(hr, error, "CertServerRetrievePending");
  1273. }
  1274. CSASSERT(NULL != pcsEnroll);
  1275. pwszMessage = pcsEnroll->pwszDispositionMessage;
  1276. }
  1277. else
  1278. {
  1279. ZeroMemory(&csEnroll, sizeof(csEnroll));
  1280. hr = Request_Init(g_fIDispatch, &diRequest);
  1281. if (S_OK != hr)
  1282. {
  1283. _PrintError(hr, "Request_Init");
  1284. if (E_ACCESSDENIED == hr) // try for a clearer error message
  1285. {
  1286. hr = CO_E_REMOTE_COMMUNICATION_FAILURE;
  1287. }
  1288. _JumpError(hr, error, "Request_Init");
  1289. }
  1290. fMustRelease = TRUE;
  1291. if (NULL != pwszfnReq)
  1292. {
  1293. assert(NULL != pbReq && 0 != cbReq);
  1294. // We could always pass the binary ASN.1 encoded request, since
  1295. // we've already decoded it above, but in the interest of fully
  1296. // exercising the ICertRequest interface, we choose to submit the
  1297. // request in its original form.
  1298. if (CR_IN_BINARY == (CR_IN_ENCODEMASK & dwFlags))
  1299. {
  1300. // Convert the binary ASN.1 blob into a BSTR blob.
  1301. if (!ConvertWszToBstr(&strRequest, (WCHAR const *) pbReq, cbReq))
  1302. {
  1303. if (S_OK == myLoadRCString(
  1304. g_hInstance,
  1305. IDS_ERROR_STRCONVERSION,
  1306. &pwszMsg))
  1307. {
  1308. CSASSERT(NULL != pwszMsg);
  1309. wprintf(pwszMsg);
  1310. wprintf(g_wszNewLine);
  1311. }
  1312. hr = E_OUTOFMEMORY;
  1313. _JumpError(hr, error, "ConvertWszToBstr");
  1314. }
  1315. }
  1316. else // !CR_IN_BINARY
  1317. {
  1318. // Since ICertRequest::Submit can handle any encoding type,
  1319. // re-read the ansi base64 request from the file without
  1320. // decoding it to binary, then convert the ansi base64 text
  1321. // into a Unicode base64 text BSTR.
  1322. // Free the request's binary image first.
  1323. LocalFree(pbReq);
  1324. pbReq = NULL;
  1325. hr = DecodeFileW(pwszfnReq, &pbReq, &cbReq, CRYPT_STRING_BINARY);
  1326. if (S_OK != hr)
  1327. {
  1328. if (S_OK == myLoadRCString(
  1329. g_hInstance,
  1330. IDS_FORMATSTR_DECODE_ERR,
  1331. &pwszMsg))
  1332. {
  1333. CSASSERT(NULL != pwszMsg);
  1334. wprintf(pwszMsg, myHResultToString(awchr, hr));
  1335. wprintf(g_wszNewLine);
  1336. }
  1337. goto error;
  1338. }
  1339. if (!ConvertSzToBstr(&strRequest, (CHAR const *) pbReq, cbReq))
  1340. {
  1341. if (S_OK == myLoadRCString(
  1342. g_hInstance,
  1343. IDS_ERROR_STRCONVERSION,
  1344. &pwszMsg))
  1345. {
  1346. CSASSERT(NULL != pwszMsg);
  1347. wprintf(pwszMsg);
  1348. }
  1349. hr = E_OUTOFMEMORY;
  1350. _JumpError(hr, error, "ConvertSzToBstr");
  1351. }
  1352. }
  1353. pszMethod = "ICertRequest::Submit";
  1354. if (g_fRPC)
  1355. {
  1356. pszMethod = "ICertRequest::Submit+RPC";
  1357. dwFlags |= CR_IN_RPC;
  1358. }
  1359. if (g_fAny)
  1360. {
  1361. dwFlags = CR_IN_ENCODEANY |
  1362. CR_IN_FORMATANY |
  1363. (~(CR_IN_ENCODEMASK | CR_IN_FORMATMASK) & dwFlags);
  1364. }
  1365. hr = Request_Submit(
  1366. &diRequest,
  1367. dwFlags | g_dwCRLIn,
  1368. strRequest,
  1369. SysStringByteLen(strRequest),
  1370. pwszAttributes,
  1371. pwszConfig,
  1372. (LONG *) &csEnroll.Disposition);
  1373. }
  1374. else
  1375. {
  1376. if (!fV1)
  1377. {
  1378. pszMethod = "ICertRequest2::GetIssuedCertificate";
  1379. hr = Request2_GetIssuedCertificate(
  1380. &diRequest,
  1381. pwszConfig,
  1382. RequestId,
  1383. pwszSerialNumber,
  1384. (LONG *) &csEnroll.Disposition);
  1385. if (E_NOTIMPL == hr)
  1386. {
  1387. fV1 = TRUE;
  1388. }
  1389. }
  1390. if (fV1)
  1391. {
  1392. if (NULL != pwszSerialNumber)
  1393. {
  1394. CSASSERT(0 == RequestId);
  1395. pwszConfigPlusSerial = (WCHAR *) LocalAlloc(
  1396. LMEM_FIXED,
  1397. (wcslen(pwszConfig) +
  1398. 1 +
  1399. wcslen(pwszSerialNumber) +
  1400. 1) * sizeof(WCHAR));
  1401. if (NULL == pwszConfigPlusSerial)
  1402. {
  1403. hr = E_OUTOFMEMORY;
  1404. _JumpError(hr, error, "LocalAlloc");
  1405. }
  1406. wcscpy(pwszConfigPlusSerial, pwszConfig);
  1407. wcscat(pwszConfigPlusSerial, L"\\");
  1408. wcscat(pwszConfigPlusSerial, pwszSerialNumber);
  1409. pwszConfig = pwszConfigPlusSerial;
  1410. }
  1411. pszMethod = "ICertRequest::RetrievePending";
  1412. hr = Request_RetrievePending(
  1413. &diRequest,
  1414. RequestId,
  1415. pwszConfig,
  1416. (LONG *) &csEnroll.Disposition);
  1417. }
  1418. }
  1419. hr2 = Request_GetLastStatus(&diRequest, &csEnroll.hrLastStatus);
  1420. if (S_OK != hr2)
  1421. {
  1422. _PrintError(hr2, "Request_GetLastStatus");
  1423. if (S_OK == hr)
  1424. {
  1425. hr = hr2;
  1426. }
  1427. _JumpError(hr, error, "Request_GetLastStatus");
  1428. }
  1429. if (S_OK != hr)
  1430. {
  1431. _PrintError(hr, pszMethod);
  1432. if (E_ACCESSDENIED == hr) // try for a clearer error message
  1433. {
  1434. hr = CO_E_REMOTE_COMMUNICATION_FAILURE;
  1435. }
  1436. _JumpError(hr, error, pszMethod);
  1437. }
  1438. if (fMustRelease && !fV1)
  1439. {
  1440. if (g_fVerbose)
  1441. {
  1442. DumpFullResponseProperties(&diRequest);
  1443. }
  1444. if (NULL != pwszfnFullResponse)
  1445. {
  1446. hr = SaveFullResponse(
  1447. hWndOwner,
  1448. &diRequest,
  1449. pwszfnFullResponse);
  1450. _JumpIfError(hr, error, "SaveFullResponse");
  1451. }
  1452. }
  1453. hr = Request_GetDispositionMessage(&diRequest, &strMessage);
  1454. _JumpIfError(hr, error, "Request_GetDispositionMessage");
  1455. hr = Request_GetRequestId(&diRequest, (LONG *) &csEnroll.RequestId);
  1456. _JumpIfError(hr, error, "Request_GetRequestId");
  1457. pcsEnroll = &csEnroll;
  1458. pwszMessage = strMessage;
  1459. }
  1460. CSASSERT(NULL != pcsEnroll);
  1461. if (NULL == pwszMessage)
  1462. {
  1463. pwszMessage = L"";
  1464. }
  1465. if (0 != pcsEnroll->RequestId)
  1466. {
  1467. if (S_OK == myLoadRCString(
  1468. g_hInstance,
  1469. IDS_FORMATSTR_REQUESTID,
  1470. &pwszMsg))
  1471. {
  1472. CSASSERT(NULL != pwszMsg);
  1473. wprintf(pwszMsg, pcsEnroll->RequestId);
  1474. wprintf(g_wszNewLine);
  1475. LocalFree(pwszMsg);
  1476. pwszMsg = NULL;
  1477. }
  1478. }
  1479. if (CR_DISP_UNDER_SUBMISSION == pcsEnroll->Disposition)
  1480. {
  1481. if (S_OK == myLoadRCString(
  1482. g_hInstance,
  1483. IDS_FORMATSTR_CERTPENDING,
  1484. &pwszMsg))
  1485. {
  1486. CSASSERT(NULL != pwszMsg);
  1487. wprintf(
  1488. pwszMsg,
  1489. pwszMessage,
  1490. pcsEnroll->hrLastStatus);
  1491. wprintf(g_wszNewLine);
  1492. }
  1493. }
  1494. else if (CR_DISP_ISSUED == pcsEnroll->Disposition ||
  1495. CR_DISP_REVOKED == pcsEnroll->Disposition)
  1496. {
  1497. pwszDispMsg = wszDisposition(pcsEnroll->Disposition);
  1498. DBGPRINT((
  1499. DBG_SS_CERTREQ,
  1500. "%hs(%ws) --> %ws\n",
  1501. pszMethod,
  1502. NULL != pwszDispMsg ? pwszDispMsg : L"",
  1503. pwszMessage));
  1504. if (S_OK == myLoadRCString(
  1505. g_hInstance,
  1506. IDS_FORMATSTR_CERTRETRIEVED,
  1507. &pwszMsg))
  1508. {
  1509. wprintf(
  1510. pwszMsg,
  1511. NULL != pwszDispMsg ? pwszDispMsg : L"",
  1512. pwszMessage);
  1513. wprintf(g_wszNewLine);
  1514. }
  1515. hr = WriteCertificateOrRequest(
  1516. hWndOwner,
  1517. &diRequest,
  1518. pcsEnroll->pbCert,
  1519. pcsEnroll->cbCert,
  1520. g_dwOutFormat,
  1521. pwszfnCert);
  1522. _JumpIfError(hr, error, "WriteCertificateOrRequest");
  1523. if (NULL != pwszfnCertChain)
  1524. {
  1525. hr = WriteCertificateOrRequest(
  1526. hWndOwner,
  1527. &diRequest,
  1528. pcsEnroll->pbCertChain,
  1529. pcsEnroll->cbCertChain,
  1530. CR_OUT_CHAIN | g_dwCRLOut | g_dwOutFormat,
  1531. pwszfnCertChain);
  1532. _JumpIfError(hr, error, "WriteCertificateOrRequest(chain)");
  1533. }
  1534. }
  1535. else
  1536. {
  1537. WCHAR const *pwszError = NULL;
  1538. if (S_OK != pcsEnroll->hrLastStatus)
  1539. {
  1540. pwszError = myGetErrorMessageText(pcsEnroll->hrLastStatus, TRUE);
  1541. }
  1542. SetErrorString(pwszMessage);
  1543. if (S_OK == myLoadRCString(
  1544. g_hInstance,
  1545. IDS_FORMATSTR_CERTNOTISSUED,
  1546. &pwszMsg))
  1547. {
  1548. pwszDispMsg = wszDisposition(pcsEnroll->Disposition);
  1549. wprintf(
  1550. pwszMsg,
  1551. NULL != pwszDispMsg ? pwszDispMsg : L"",
  1552. pwszMessage);
  1553. if (NULL != pwszError && NULL == wcsstr(pwszMessage, pwszError))
  1554. {
  1555. wprintf(L" %ws", pwszError);
  1556. }
  1557. wprintf(g_wszNewLine);
  1558. }
  1559. if (NULL != pwszError)
  1560. {
  1561. LocalFree(const_cast<WCHAR *>(pwszError));
  1562. }
  1563. hr = pcsEnroll->hrLastStatus;
  1564. _PrintIfError(hr, "Denied(LastStatus)");
  1565. goto error;
  1566. }
  1567. error:
  1568. if (NULL != pwszMsg)
  1569. {
  1570. LocalFree(pwszMsg);
  1571. }
  1572. if (NULL != pwszDispMsg)
  1573. {
  1574. LocalFree(pwszDispMsg);
  1575. }
  1576. if (NULL != pwszConfigPlusSerial)
  1577. {
  1578. LocalFree(pwszConfigPlusSerial);
  1579. }
  1580. if (NULL != pwszServer)
  1581. {
  1582. LocalFree(pwszServer);
  1583. }
  1584. if (NULL != pwszAuthority)
  1585. {
  1586. LocalFree(pwszAuthority);
  1587. }
  1588. if (NULL != pcsEnroll && &csEnroll != pcsEnroll)
  1589. {
  1590. CertServerFreeMemory(pcsEnroll);
  1591. }
  1592. if (NULL != strMessage)
  1593. {
  1594. SysFreeString(strMessage);
  1595. }
  1596. if (fMustRelease)
  1597. {
  1598. Request_Release(&diRequest);
  1599. }
  1600. if (NULL != strRequest)
  1601. {
  1602. SysFreeString(strRequest);
  1603. }
  1604. if (NULL != pbReq)
  1605. {
  1606. LocalFree(pbReq);
  1607. }
  1608. return(hr);
  1609. }
  1610. HRESULT
  1611. crGetConfig(
  1612. IN OUT BSTR *pstrConfig)
  1613. {
  1614. HRESULT hr;
  1615. WCHAR awchr[cwcHRESULTSTRING];
  1616. hr = ConfigGetConfig(g_fIDispatch, g_dwUIFlag, pstrConfig);
  1617. if (S_OK != hr)
  1618. {
  1619. WCHAR *pwszMsg = NULL;
  1620. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
  1621. {
  1622. g_idError = IDS_NOMORE_CAS;
  1623. }
  1624. if (S_OK == myLoadRCString(
  1625. g_hInstance,
  1626. IDS_FORMATSTR_ERRCONFIG,
  1627. &pwszMsg))
  1628. {
  1629. CSASSERT(NULL != pwszMsg);
  1630. wprintf(
  1631. pwszMsg,
  1632. myHResultToString(awchr, hr));
  1633. wprintf(g_wszNewLine);
  1634. LocalFree(pwszMsg);
  1635. }
  1636. goto error;
  1637. }
  1638. hr = S_OK;
  1639. error:
  1640. return(hr);
  1641. }
  1642. HRESULT
  1643. SubmitRequest(
  1644. IN HWND hWndOwner,
  1645. IN LONG RequestId,
  1646. OPTIONAL IN WCHAR const *pwszSerialNumber,
  1647. OPTIONAL IN WCHAR const *pwszAttributes,
  1648. IN WCHAR const *pwszfnReq,
  1649. OPTIONAL IN WCHAR const *pwszfnCert,
  1650. OPTIONAL IN WCHAR const *pwszfnCertChain,
  1651. OPTIONAL IN WCHAR const *pwszfnFullResponse)
  1652. {
  1653. HRESULT hr;
  1654. BOOL fCoInit = FALSE;
  1655. WCHAR *pwszConfig;
  1656. BSTR strConfig = NULL;
  1657. hr = CoInitialize(NULL);
  1658. if (S_OK != hr && S_FALSE != hr)
  1659. {
  1660. _JumpError(hr, error, "CoInitialize");
  1661. }
  1662. fCoInit = TRUE;
  1663. pwszConfig = g_pwszConfig;
  1664. if (NULL == pwszConfig)
  1665. {
  1666. hr = crGetConfig(&strConfig);
  1667. _JumpIfError(hr, error, "crGetConfig");
  1668. pwszConfig = strConfig;
  1669. }
  1670. // If submitting a new request:
  1671. hr = CallServerAndStoreCert(
  1672. hWndOwner,
  1673. pwszConfig,
  1674. RequestId,
  1675. pwszSerialNumber,
  1676. pwszAttributes,
  1677. pwszfnReq,
  1678. pwszfnCert,
  1679. pwszfnCertChain,
  1680. pwszfnFullResponse);
  1681. _JumpIfError(hr, error, "CallServerAndStoreCert");
  1682. error:
  1683. if (NULL != strConfig)
  1684. {
  1685. SysFreeString(strConfig);
  1686. }
  1687. if (fCoInit)
  1688. {
  1689. CoUninitialize();
  1690. }
  1691. return(hr);
  1692. }
  1693. FNMYINFGETEXTENSION *g_apfnGetExtension[] = {
  1694. myInfGetPolicyConstraintsExtension,
  1695. myInfGetPolicyMappingExtension,
  1696. myInfGetPolicyStatementExtension,
  1697. myInfGetApplicationPolicyConstraintsExtension,
  1698. myInfGetApplicationPolicyMappingExtension,
  1699. myInfGetApplicationPolicyStatementExtension,
  1700. myInfGetNameConstraintsExtension,
  1701. myInfGetEnhancedKeyUsageExtension,
  1702. myInfGetBasicConstraints2CAExtension,
  1703. myInfGetCrossCertDistributionPointsExtension,
  1704. };
  1705. #define CINFEXT ARRAYSIZE(g_apfnGetExtension)
  1706. HRESULT
  1707. DumpRequestAttributeBlobs(
  1708. IN DWORD cAttribute,
  1709. IN CRYPT_ATTR_BLOB const *paAttribute)
  1710. {
  1711. HRESULT hr;
  1712. DWORD i;
  1713. CRYPT_ENROLLMENT_NAME_VALUE_PAIR *pNamePair = NULL;
  1714. DWORD cb;
  1715. if (g_fVerbose)
  1716. {
  1717. for (i = 0; i < cAttribute; i++)
  1718. {
  1719. if (NULL != paAttribute[i].pbData)
  1720. {
  1721. if (NULL != pNamePair)
  1722. {
  1723. LocalFree(pNamePair);
  1724. pNamePair = NULL;
  1725. }
  1726. if (!myDecodeObject(
  1727. X509_ASN_ENCODING,
  1728. //X509_ENROLLMENT_NAME_VALUE_PAIR,
  1729. szOID_ENROLLMENT_NAME_VALUE_PAIR,
  1730. paAttribute[i].pbData,
  1731. paAttribute[i].cbData,
  1732. CERTLIB_USE_LOCALALLOC,
  1733. (VOID **) &pNamePair,
  1734. &cb))
  1735. {
  1736. hr = myHLastError();
  1737. _JumpError(hr, error, "myDecodeObject");
  1738. }
  1739. wprintf(
  1740. L"%u: %ws = %ws\n",
  1741. i,
  1742. pNamePair->pwszName,
  1743. pNamePair->pwszValue);
  1744. }
  1745. }
  1746. }
  1747. hr = S_OK;
  1748. error:
  1749. if (NULL != pNamePair)
  1750. {
  1751. LocalFree(pNamePair);
  1752. }
  1753. return(hr);
  1754. }
  1755. VOID
  1756. FreeExtensions(
  1757. IN BOOL fFreeObjIds,
  1758. IN DWORD cExt,
  1759. IN OUT CERT_EXTENSION *rgExt)
  1760. {
  1761. IN DWORD i;
  1762. if (NULL != rgExt)
  1763. {
  1764. for (i = 0; i < cExt; i++)
  1765. {
  1766. if (fFreeObjIds && NULL != rgExt[i].pszObjId)
  1767. {
  1768. LocalFree(rgExt[i].pszObjId);
  1769. }
  1770. if (NULL != rgExt[i].Value.pbData)
  1771. {
  1772. LocalFree(rgExt[i].Value.pbData);
  1773. }
  1774. }
  1775. LocalFree(rgExt);
  1776. }
  1777. }
  1778. VOID
  1779. FreeAttributes(
  1780. IN DWORD cAttributes,
  1781. IN OUT CRYPT_ATTRIBUTES *rgAttributes)
  1782. {
  1783. DWORD i;
  1784. DWORD j;
  1785. if (NULL != rgAttributes)
  1786. {
  1787. for (i = 0; i < cAttributes; i++)
  1788. {
  1789. CRYPT_ATTRIBUTE *pAttribute = rgAttributes[i].rgAttr;
  1790. if (NULL != pAttribute)
  1791. {
  1792. if (NULL != pAttribute->rgValue)
  1793. {
  1794. for (j = 0; j < pAttribute->cValue; j++)
  1795. {
  1796. CRYPT_ATTR_BLOB *pValue = &pAttribute->rgValue[j];
  1797. if (NULL != pValue->pbData)
  1798. {
  1799. LocalFree(pValue->pbData);
  1800. }
  1801. }
  1802. LocalFree(pAttribute->rgValue);
  1803. }
  1804. LocalFree(pAttribute);
  1805. }
  1806. }
  1807. LocalFree(rgAttributes);
  1808. }
  1809. }
  1810. HRESULT
  1811. ParseInfFile(
  1812. IN WCHAR const *pwszfnPolicy,
  1813. OPTIONAL OUT INFVALUES **prgInfValues,
  1814. OPTIONAL OUT DWORD *pcInfValues,
  1815. OUT CRYPT_ATTR_BLOB **ppaAttribute,
  1816. OUT DWORD *pcAttribute,
  1817. OUT CERT_EXTENSION **ppExt,
  1818. OUT DWORD *pcExt,
  1819. OUT WCHAR **ppwszTemplateNameInf)
  1820. {
  1821. HRESULT hr;
  1822. HINF hInf = INVALID_HANDLE_VALUE;
  1823. DWORD ErrorLine;
  1824. DWORD i;
  1825. INFVALUES *rgInfValues = NULL;
  1826. DWORD cInfValues;
  1827. DWORD cExt = 0;
  1828. DWORD cAttribute = 0;
  1829. CRYPT_ATTR_BLOB *paAttribute = NULL;
  1830. CERT_EXTENSION aext[CINFEXT];
  1831. FNMYINFGETEXTENSION **ppfnGetExtension;
  1832. CERT_EXTENSION *rgExt = NULL;
  1833. if (NULL != prgInfValues)
  1834. {
  1835. *prgInfValues = NULL;
  1836. }
  1837. if (NULL != pcInfValues)
  1838. {
  1839. *pcInfValues = 0;
  1840. }
  1841. *ppaAttribute = NULL;
  1842. *pcAttribute = 0;
  1843. *ppExt = NULL;
  1844. *pcExt = 0;
  1845. *ppwszTemplateNameInf = NULL;
  1846. ZeroMemory(&aext, sizeof(aext));
  1847. hr = myInfOpenFile(pwszfnPolicy, &hInf, &ErrorLine);
  1848. if (S_OK != hr)
  1849. {
  1850. SetErrorString(pwszfnPolicy);
  1851. _JumpError(hr, error, "myInfOpenFile");
  1852. }
  1853. if (NULL != prgInfValues && NULL != pcInfValues)
  1854. {
  1855. hr = myInfGetSectionValues(
  1856. hInf,
  1857. wszINFSECTION_NEWREQUEST,
  1858. &cInfValues,
  1859. &rgInfValues);
  1860. if (S_OK != hr)
  1861. {
  1862. SetErrorString(pwszfnPolicy);
  1863. _JumpError(hr, error, "myInfGetSectionValues");
  1864. }
  1865. }
  1866. for (ppfnGetExtension = g_apfnGetExtension;
  1867. ppfnGetExtension < &g_apfnGetExtension[CINFEXT];
  1868. ppfnGetExtension++)
  1869. {
  1870. hr = (**ppfnGetExtension)(hInf, &aext[cExt]);
  1871. CSASSERT((NULL == aext[cExt].Value.pbData) ^ (S_OK == hr));
  1872. if (S_OK != hr)
  1873. {
  1874. char achIndex[64];
  1875. sprintf(
  1876. achIndex,
  1877. "*ppfnGetExtension[%u]",
  1878. SAFE_SUBTRACT_POINTERS(ppfnGetExtension, g_apfnGetExtension));
  1879. if (S_FALSE == hr || (HRESULT) ERROR_LINE_NOT_FOUND == hr)
  1880. {
  1881. _PrintError2(hr, achIndex, hr);
  1882. continue;
  1883. }
  1884. _JumpIfError(hr, error, achIndex);
  1885. }
  1886. cExt++;
  1887. }
  1888. hr = myInfGetRequestAttributes(
  1889. hInf,
  1890. &cAttribute,
  1891. &paAttribute,
  1892. ppwszTemplateNameInf);
  1893. _PrintIfError(hr, "myInfGetRequestAttributes");
  1894. DumpRequestAttributeBlobs(cAttribute, paAttribute);
  1895. if (0 != cExt)
  1896. {
  1897. rgExt = (CERT_EXTENSION *) LocalAlloc(
  1898. LMEM_FIXED | LMEM_ZEROINIT,
  1899. cExt * sizeof(**ppExt));
  1900. if (NULL == rgExt)
  1901. {
  1902. hr = E_OUTOFMEMORY;
  1903. _JumpError(hr, error, "LocalAlloc");
  1904. }
  1905. CopyMemory(&rgExt[0], &aext[0], cExt * sizeof(rgExt[0]));
  1906. for (i = 0; i < cExt; i++)
  1907. {
  1908. rgExt[i].pszObjId = NULL;
  1909. }
  1910. for (i = 0; i < cExt; i++)
  1911. {
  1912. hr = myDupStringA(aext[i].pszObjId, &rgExt[i].pszObjId);
  1913. _JumpIfError(hr, error, "myDupStringA");
  1914. if (g_fVerbose)
  1915. {
  1916. wprintf(
  1917. L"%u: %hs(%ws) %ws cb=%x pb=%x\n",
  1918. i,
  1919. rgExt[i].pszObjId,
  1920. myGetOIDNameA(rgExt[i].pszObjId),
  1921. rgExt[i].fCritical? L"critical" : L"non-critical",
  1922. rgExt[i].Value.cbData,
  1923. rgExt[i].Value.pbData);
  1924. }
  1925. }
  1926. *pcExt = cExt;
  1927. *ppExt = rgExt;
  1928. rgExt = NULL;
  1929. }
  1930. if (NULL != prgInfValues && NULL != pcInfValues)
  1931. {
  1932. *prgInfValues = rgInfValues;
  1933. rgInfValues = NULL;
  1934. *pcInfValues = cInfValues;
  1935. }
  1936. *ppaAttribute = paAttribute;
  1937. *pcAttribute = cAttribute;
  1938. paAttribute = NULL;
  1939. hr = S_OK;
  1940. error:
  1941. if (NULL != rgInfValues)
  1942. {
  1943. myInfFreeSectionValues(cInfValues, rgInfValues);
  1944. }
  1945. if (S_OK != hr)
  1946. {
  1947. for (i = 0; i < ARRAYSIZE(aext); i++)
  1948. {
  1949. if (NULL != aext[i].Value.pbData)
  1950. {
  1951. LocalFree(aext[i].Value.pbData);
  1952. }
  1953. }
  1954. if (NULL != *ppwszTemplateNameInf)
  1955. {
  1956. LocalFree(*ppwszTemplateNameInf);
  1957. *ppwszTemplateNameInf = NULL;
  1958. }
  1959. if (NULL != rgExt)
  1960. {
  1961. FreeExtensions(TRUE, cExt, rgExt);
  1962. }
  1963. }
  1964. if (NULL != paAttribute)
  1965. {
  1966. myInfFreeRequestAttributes(cAttribute, paAttribute);
  1967. }
  1968. if (INVALID_HANDLE_VALUE != hInf)
  1969. {
  1970. myInfCloseFile(hInf);
  1971. }
  1972. return(hr);
  1973. }
  1974. HRESULT
  1975. DeleteMsgCerts(
  1976. IN HCRYPTMSG hMsg,
  1977. IN HCERTSTORE hStore)
  1978. {
  1979. HRESULT hr;
  1980. CERT_CONTEXT const *pCert = NULL;
  1981. BYTE *pbCert = NULL;
  1982. CSASSERT(NULL == pCert);
  1983. while (TRUE)
  1984. {
  1985. BOOL fFirst = FALSE;
  1986. DWORD cCert;
  1987. DWORD cb;
  1988. DWORD i;
  1989. cb = sizeof(cCert);
  1990. if (!CryptMsgGetParam(
  1991. hMsg,
  1992. CMSG_CERT_COUNT_PARAM,
  1993. 0,
  1994. &cCert,
  1995. &cb))
  1996. {
  1997. hr = myHLastError();
  1998. _JumpError(hr, error, "CryptMsgGetParam(Cert count)");
  1999. }
  2000. for (i = 0; i < cCert; i++)
  2001. {
  2002. CSASSERT(NULL == pbCert);
  2003. hr = myCryptMsgGetParam(
  2004. hMsg,
  2005. CMSG_CERT_PARAM,
  2006. i,
  2007. CERTLIB_USE_LOCALALLOC,
  2008. (VOID **) &pbCert,
  2009. &cb);
  2010. _JumpIfError(hr, error, "myCryptMsgGetParam");
  2011. CSASSERT(NULL == pCert);
  2012. pCert = CertCreateCertificateContext(
  2013. X509_ASN_ENCODING,
  2014. pbCert,
  2015. cb);
  2016. if (NULL == pCert)
  2017. {
  2018. hr = myHLastError();
  2019. _JumpError(hr, error, "CertCreateCertificateContext");
  2020. }
  2021. hr = myIsFirstSigner(&pCert->pCertInfo->Subject, &fFirst);
  2022. _JumpIfError(hr, error, "myIsFirstSigner");
  2023. LocalFree(pbCert);
  2024. pbCert = NULL;
  2025. CertFreeCertificateContext(pCert);
  2026. pCert = NULL;
  2027. if (!fFirst)
  2028. {
  2029. if (!CryptMsgControl(
  2030. hMsg,
  2031. 0, // dwFlags
  2032. CMSG_CTRL_DEL_CERT,
  2033. &i))
  2034. {
  2035. hr = myHLastError();
  2036. _JumpError(hr, error, "CryptMsgControl(delCert)");
  2037. }
  2038. break;
  2039. }
  2040. }
  2041. if (i == cCert)
  2042. {
  2043. break;
  2044. }
  2045. }
  2046. hr = S_OK;
  2047. error:
  2048. if (NULL != pbCert)
  2049. {
  2050. LocalFree(pbCert);
  2051. }
  2052. if (NULL != pCert)
  2053. {
  2054. CertFreeCertificateContext(pCert);
  2055. }
  2056. return(hr);
  2057. }
  2058. HRESULT
  2059. DeleteMsgCRLs(
  2060. IN HCRYPTMSG hMsg)
  2061. {
  2062. HRESULT hr;
  2063. while (TRUE)
  2064. {
  2065. DWORD cCRL;
  2066. DWORD cb;
  2067. DWORD i;
  2068. cb = sizeof(cCRL);
  2069. if (!CryptMsgGetParam(
  2070. hMsg,
  2071. CMSG_CRL_COUNT_PARAM,
  2072. 0,
  2073. &cCRL,
  2074. &cb))
  2075. {
  2076. hr = myHLastError();
  2077. _JumpError(hr, error, "CryptMsgGetParam(CRL count)");
  2078. }
  2079. for (i = 0; i < cCRL; i++)
  2080. {
  2081. if (!CryptMsgControl(
  2082. hMsg,
  2083. 0, // dwFlags
  2084. CMSG_CTRL_DEL_CRL,
  2085. &i))
  2086. {
  2087. hr = myHLastError();
  2088. _JumpError(hr, error, "CryptMsgControl(delCRL)");
  2089. }
  2090. break;
  2091. }
  2092. if (i == cCRL)
  2093. {
  2094. break;
  2095. }
  2096. }
  2097. hr = S_OK;
  2098. error:
  2099. return(hr);
  2100. }
  2101. HRESULT
  2102. AddMsgCert(
  2103. IN HCRYPTMSG hMsg,
  2104. IN HCERTSTORE hStore,
  2105. IN CERT_CONTEXT const *pCertAdd)
  2106. {
  2107. HRESULT hr;
  2108. CERT_CONTEXT const *pCert = NULL;
  2109. while (TRUE)
  2110. {
  2111. pCert = CertEnumCertificatesInStore(hStore, pCert);
  2112. if (NULL == pCert)
  2113. {
  2114. break;
  2115. }
  2116. if (pCertAdd->cbCertEncoded == pCert->cbCertEncoded &&
  2117. 0 == memcmp(
  2118. pCertAdd->pbCertEncoded,
  2119. pCert->pbCertEncoded,
  2120. pCert->cbCertEncoded))
  2121. {
  2122. break;
  2123. }
  2124. }
  2125. if (NULL == pCert)
  2126. {
  2127. CERT_BLOB Blob;
  2128. Blob.pbData = pCertAdd->pbCertEncoded;
  2129. Blob.cbData = pCertAdd->cbCertEncoded;
  2130. if (!CryptMsgControl(
  2131. hMsg,
  2132. 0, // dwFlags
  2133. CMSG_CTRL_ADD_CERT,
  2134. &Blob))
  2135. {
  2136. hr = myHLastError();
  2137. _JumpError(hr, error, "CryptMsgControl(addCert)");
  2138. }
  2139. }
  2140. hr = S_OK;
  2141. error:
  2142. if (NULL != pCert)
  2143. {
  2144. CertFreeCertificateContext(pCert);
  2145. }
  2146. return(hr);
  2147. }
  2148. HRESULT
  2149. AddMsgCRL(
  2150. IN HCRYPTMSG hMsg,
  2151. IN HCERTSTORE hStore,
  2152. IN CRL_CONTEXT const *pCRLAdd)
  2153. {
  2154. HRESULT hr;
  2155. CRL_CONTEXT const *pCRL = NULL;
  2156. while (TRUE)
  2157. {
  2158. pCRL = CertEnumCRLsInStore(hStore, pCRL);
  2159. if (NULL == pCRL)
  2160. {
  2161. break;
  2162. }
  2163. if (pCRLAdd->cbCrlEncoded == pCRL->cbCrlEncoded &&
  2164. 0 == memcmp(
  2165. pCRLAdd->pbCrlEncoded,
  2166. pCRL->pbCrlEncoded,
  2167. pCRL->cbCrlEncoded))
  2168. {
  2169. break;
  2170. }
  2171. }
  2172. if (NULL == pCRL)
  2173. {
  2174. CERT_BLOB Blob;
  2175. Blob.pbData = pCRLAdd->pbCrlEncoded;
  2176. Blob.cbData = pCRLAdd->cbCrlEncoded;
  2177. if (!CryptMsgControl(
  2178. hMsg,
  2179. 0, // dwFlags
  2180. CMSG_CTRL_ADD_CRL,
  2181. &Blob))
  2182. {
  2183. hr = myHLastError();
  2184. _JumpError(hr, error, "CryptMsgControl(addCRL)");
  2185. }
  2186. }
  2187. hr = S_OK;
  2188. error:
  2189. if (NULL != pCRL)
  2190. {
  2191. CertFreeCRLContext(pCRL);
  2192. }
  2193. return(hr);
  2194. }
  2195. HRESULT
  2196. AddMsgCertsAndCRLs(
  2197. IN HCRYPTMSG hMsg,
  2198. IN HCERTSTORE hStore,
  2199. IN CERT_CHAIN_CONTEXT const *pChainContext,
  2200. IN BOOL fIncludeCRLs)
  2201. {
  2202. HRESULT hr;
  2203. DWORD cElement;
  2204. CERT_CHAIN_ELEMENT **ppElement;
  2205. DWORD i;
  2206. CSASSERT(NULL != pChainContext);
  2207. if (NULL == pChainContext ||
  2208. 0 == pChainContext->cChain ||
  2209. 0 == pChainContext->rgpChain[0]->cElement)
  2210. {
  2211. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  2212. _JumpError(hr, error, "no chain");
  2213. }
  2214. cElement = pChainContext->rgpChain[0]->cElement;
  2215. ppElement = pChainContext->rgpChain[0]->rgpElement;
  2216. for (i = 0; i < cElement; ppElement++, i++)
  2217. {
  2218. hr = AddMsgCert(hMsg, hStore, (*ppElement)->pCertContext);
  2219. _JumpIfError(hr, error, "AddMsgCert");
  2220. if (fIncludeCRLs)
  2221. {
  2222. CERT_REVOCATION_INFO *pRevocationInfo;
  2223. pRevocationInfo = (*ppElement)->pRevocationInfo;
  2224. if (NULL != pRevocationInfo &&
  2225. CCSIZEOF_STRUCT(CERT_REVOCATION_INFO, pCrlInfo) <=
  2226. pRevocationInfo->cbSize &&
  2227. NULL != pRevocationInfo->pCrlInfo)
  2228. {
  2229. CERT_REVOCATION_CRL_INFO *pCrlInfo;
  2230. pCrlInfo = pRevocationInfo->pCrlInfo;
  2231. if (NULL != pCrlInfo)
  2232. {
  2233. if (NULL != pCrlInfo->pBaseCrlContext)
  2234. {
  2235. hr = AddMsgCRL(
  2236. hMsg,
  2237. hStore,
  2238. pCrlInfo->pBaseCrlContext);
  2239. _JumpIfError(hr, error, "AddMsgCRL");
  2240. }
  2241. if (NULL != pCrlInfo->pDeltaCrlContext)
  2242. {
  2243. hr = AddMsgCRL(
  2244. hMsg,
  2245. hStore,
  2246. pCrlInfo->pDeltaCrlContext);
  2247. _JumpIfError(hr, error, "AddMsgCRL");
  2248. }
  2249. }
  2250. }
  2251. }
  2252. }
  2253. hr = S_OK;
  2254. error:
  2255. return(hr);
  2256. }
  2257. HRESULT
  2258. AddOrDeleteMsgCertsAndCRLs(
  2259. IN BYTE const *pbPKCS7,
  2260. IN DWORD cbPKCS7,
  2261. IN HCRYPTMSG hMsg,
  2262. IN BOOL fDelete, // else add Certs and CRLs
  2263. OPTIONAL IN CERT_CHAIN_CONTEXT const *pChainContext,
  2264. IN BOOL fIncludeCRLs)
  2265. {
  2266. HRESULT hr;
  2267. CRYPT_DATA_BLOB blobPKCS7;
  2268. HCERTSTORE hStore = NULL;
  2269. DWORD i;
  2270. blobPKCS7.pbData = const_cast<BYTE *>(pbPKCS7);
  2271. blobPKCS7.cbData = cbPKCS7;
  2272. hStore = CertOpenStore(
  2273. CERT_STORE_PROV_PKCS7,
  2274. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  2275. NULL, // hCryptProv
  2276. 0, // dwFlags
  2277. &blobPKCS7);
  2278. if (NULL == hStore)
  2279. {
  2280. hr = myHLastError();
  2281. _JumpError(hr, error, "CertOpenStore");
  2282. }
  2283. if (fDelete)
  2284. {
  2285. CSASSERT(NULL == pChainContext);
  2286. hr = DeleteMsgCerts(hMsg, hStore);
  2287. _JumpIfError(hr, error, "DeleteMsgCerts");
  2288. hr = DeleteMsgCRLs(hMsg);
  2289. _JumpIfError(hr, error, "DeleteMsgCRLs");
  2290. }
  2291. else
  2292. {
  2293. CSASSERT(NULL != pChainContext);
  2294. hr = AddMsgCertsAndCRLs(hMsg, hStore, pChainContext, fIncludeCRLs);
  2295. _JumpIfError(hr, error, "AddMsgCertsAndCRLs");
  2296. }
  2297. hr = S_OK;
  2298. error:
  2299. if (NULL != hStore)
  2300. {
  2301. CertCloseStore(hStore, 0);
  2302. }
  2303. return(hr);
  2304. }
  2305. HRESULT
  2306. SignCMCContent(
  2307. OPTIONAL IN CERT_CONTEXT const *pCertSigner,
  2308. IN char const *pszInnerContentObjId,
  2309. IN BYTE const *pbPKCS7Old,
  2310. IN DWORD cbPKCS7Old,
  2311. IN BOOL fIncludeCRLs,
  2312. OUT BYTE **ppbPKCS7New,
  2313. OUT DWORD *pcbPKCS7New)
  2314. {
  2315. HRESULT hr;
  2316. HCRYPTPROV hProv = NULL;
  2317. DWORD dwKeySpec;
  2318. BOOL fCallerFreeProv;
  2319. DWORD cb;
  2320. HCRYPTMSG hMsg = NULL;
  2321. CMSG_SIGNER_ENCODE_INFO SignerEncodeInfo;
  2322. CRYPT_ATTRIBUTE AttributeRequestClient;
  2323. CRYPT_ATTR_BLOB BlobRequestClient;
  2324. CERT_BLOB SignerCertBlob;
  2325. DWORD cSigner;
  2326. DWORD dwContentParamType;
  2327. DWORD i;
  2328. CERT_CONTEXT const *pCert = NULL;
  2329. CERT_CHAIN_CONTEXT const *pChainContext = NULL;
  2330. DWORD iElement;
  2331. CMSG_CMS_SIGNER_INFO *pcsi = NULL;
  2332. DWORD cFirstSigner;
  2333. BOOL fFirst;
  2334. CERT_REQUEST_INFO *pRequest = NULL;
  2335. BlobRequestClient.pbData = NULL;
  2336. // decode existing PKCS 7 wrapper, and add or delete signatures
  2337. hMsg = CryptMsgOpenToDecode(
  2338. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  2339. 0, // dwFlags
  2340. 0, // dwMsgType
  2341. //CMSG_SIGNED,
  2342. NULL, // hCryptProv
  2343. NULL, // pRecipientInfo
  2344. NULL); // pStreamInfo
  2345. if (NULL == hMsg)
  2346. {
  2347. hr = myHLastError();
  2348. _JumpError(hr, error, "CryptMsgOpenToDecode");
  2349. }
  2350. // Update the message with the old PKCS 7 signed message
  2351. if (!CryptMsgUpdate(hMsg, pbPKCS7Old, cbPKCS7Old, TRUE))
  2352. {
  2353. hr = myHLastError();
  2354. _JumpError(hr, error, "CryptMsgUpdate");
  2355. }
  2356. cb = sizeof(cSigner);
  2357. if (!CryptMsgGetParam(
  2358. hMsg,
  2359. CMSG_SIGNER_COUNT_PARAM,
  2360. 0,
  2361. &cSigner,
  2362. &cb))
  2363. {
  2364. hr = myHLastError();
  2365. _JumpError(hr, error, "CryptMsgGetParam(signer count)");
  2366. }
  2367. cFirstSigner = 0;
  2368. if (NULL != pCertSigner)
  2369. {
  2370. CERT_CHAIN_PARA ChainParams;
  2371. ZeroMemory(&SignerEncodeInfo, sizeof(SignerEncodeInfo));
  2372. SignerEncodeInfo.cbSize = sizeof(SignerEncodeInfo);
  2373. hr = myEncodeRequestClientAttributeFromClientId(
  2374. XECI_CERTREQ,
  2375. &BlobRequestClient.pbData,
  2376. &BlobRequestClient.cbData);
  2377. _JumpIfError(hr, error, "myEncodeRequestClientAttributeFromClientId");
  2378. AttributeRequestClient.pszObjId = szOID_REQUEST_CLIENT_INFO;
  2379. AttributeRequestClient.cValue = 1;
  2380. AttributeRequestClient.rgValue = &BlobRequestClient;
  2381. // Search for and load the cryptographic provider and private key.
  2382. hr = myLoadPrivateKey(
  2383. &pCertSigner->pCertInfo->SubjectPublicKeyInfo,
  2384. CUCS_MACHINESTORE | CUCS_USERSTORE | CUCS_MYSTORE | CUCS_ARCHIVED,
  2385. &hProv,
  2386. &dwKeySpec,
  2387. &fCallerFreeProv);
  2388. _JumpIfError(hr, error, "myLoadPrivateKey");
  2389. // Get the cert chain
  2390. ZeroMemory(&ChainParams, sizeof(ChainParams));
  2391. ChainParams.cbSize = sizeof(ChainParams);
  2392. ChainParams.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
  2393. //ChainParams.RequestedUsage.Usage.cUsageIdentifier = 0;
  2394. //ChainParams.RequestedUsage.Usage.rgpszUsageIdentifier = NULL;
  2395. if (!CertGetCertificateChain(
  2396. NULL, // hChainEngine
  2397. pCertSigner, // pCertContext
  2398. NULL, // pTime
  2399. NULL, // hAdditionalStore
  2400. &ChainParams, // pChainPara
  2401. CERT_CHAIN_REVOCATION_CHECK_END_CERT |
  2402. CERT_CHAIN_REVOCATION_CHECK_CHAIN,
  2403. NULL, // pvReserved
  2404. &pChainContext)) // ppChainContext
  2405. {
  2406. hr = myHLastError();
  2407. _JumpError(hr, error, "CertGetCertificateChain");
  2408. }
  2409. // Initialize the CMSG_SIGNER_ENCODE_INFO structure.
  2410. // Note: handles only a single signer.
  2411. SignerCertBlob.cbData = pCertSigner->cbCertEncoded;
  2412. SignerCertBlob.pbData = pCertSigner->pbCertEncoded;
  2413. SignerEncodeInfo.pCertInfo = pCertSigner->pCertInfo;
  2414. SignerEncodeInfo.hCryptProv = hProv;
  2415. SignerEncodeInfo.dwKeySpec = dwKeySpec;
  2416. SignerEncodeInfo.HashAlgorithm.pszObjId = const_cast<CHAR *>(g_pszObjIdHash);
  2417. //SignerEncodeInfo.pvHashAuxInfo = NULL;
  2418. SignerEncodeInfo.cAuthAttr = 1;
  2419. SignerEncodeInfo.rgAuthAttr = &AttributeRequestClient;
  2420. // fail if any existing signing cert matches the new signing cert.
  2421. for (i = 0; i < cSigner; i++)
  2422. {
  2423. if (NULL != pcsi)
  2424. {
  2425. LocalFree(pcsi);
  2426. pcsi = NULL;
  2427. }
  2428. hr = myCryptMsgGetParam(
  2429. hMsg,
  2430. CMSG_CMS_SIGNER_INFO_PARAM,
  2431. i,
  2432. CERTLIB_USE_LOCALALLOC,
  2433. (VOID **) &pcsi,
  2434. &cb);
  2435. _JumpIfError(hr, error, "myCryptMsgGetParam");
  2436. if (CERT_ID_KEY_IDENTIFIER == pcsi->SignerId.dwIdChoice ||
  2437. (NULL != pcsi->HashEncryptionAlgorithm.pszObjId &&
  2438. 0 == strcmp(
  2439. szOID_PKIX_NO_SIGNATURE,
  2440. pcsi->HashEncryptionAlgorithm.pszObjId)))
  2441. {
  2442. CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA cvse;
  2443. ZeroMemory(&cvse, sizeof(cvse));
  2444. cvse.cbSize = sizeof(cvse);
  2445. cvse.dwSignerIndex = i;
  2446. if (CERT_ID_KEY_IDENTIFIER == pcsi->SignerId.dwIdChoice)
  2447. {
  2448. if (NULL == pRequest)
  2449. {
  2450. hr = myGetInnerPKCS10(
  2451. hMsg,
  2452. pszInnerContentObjId,
  2453. &pRequest);
  2454. _JumpIfError(hr, error, "myGetInnerPKCS10");
  2455. }
  2456. cvse.dwSignerType = CMSG_VERIFY_SIGNER_PUBKEY;
  2457. cvse.pvSigner = &pRequest->SubjectPublicKeyInfo;
  2458. }
  2459. else
  2460. {
  2461. cvse.dwSignerType = CMSG_VERIFY_SIGNER_NULL;
  2462. }
  2463. if (!CryptMsgControl(
  2464. hMsg,
  2465. 0, // dwFlags
  2466. CMSG_CTRL_VERIFY_SIGNATURE_EX,
  2467. &cvse))
  2468. {
  2469. hr = myHLastError();
  2470. _JumpError(hr, error, "CryptMsgControl(VerifySig)");
  2471. }
  2472. cFirstSigner++;
  2473. }
  2474. else
  2475. {
  2476. iElement = i;
  2477. if (!CryptMsgGetAndVerifySigner(
  2478. hMsg,
  2479. 0, // cSignerStore
  2480. NULL, // rghSignerStore
  2481. CMSG_USE_SIGNER_INDEX_FLAG,
  2482. &pCert,
  2483. &iElement))
  2484. {
  2485. hr = myHLastError();
  2486. _JumpError(hr, error, "CryptMsgGetAndVerifySigner");
  2487. }
  2488. if (pCertSigner->cbCertEncoded == pCert->cbCertEncoded &&
  2489. 0 == memcmp(
  2490. pCertSigner->pbCertEncoded,
  2491. pCert->pbCertEncoded,
  2492. pCert->cbCertEncoded))
  2493. {
  2494. hr = CRYPT_E_EXISTS;
  2495. _JumpError(hr, error, "duplicate signing cert");
  2496. }
  2497. hr = myIsFirstSigner(&pCert->pCertInfo->Subject, &fFirst);
  2498. _JumpIfError(hr, error, "myIsFirstSigner");
  2499. if (fFirst)
  2500. {
  2501. cFirstSigner++;
  2502. }
  2503. CertFreeCertificateContext(pCert);
  2504. pCert = NULL;
  2505. }
  2506. }
  2507. if (!CryptMsgControl(
  2508. hMsg,
  2509. 0, // dwFlags
  2510. CMSG_CTRL_ADD_SIGNER,
  2511. &SignerEncodeInfo))
  2512. {
  2513. hr = myHLastError();
  2514. _JumpError(hr, error, "CryptMsgControl(addSigner)");
  2515. }
  2516. }
  2517. else
  2518. {
  2519. // delete all existing signers -- except the first signer
  2520. while (TRUE)
  2521. {
  2522. BOOL fDeleteSigner = FALSE;
  2523. for (i = 0; i < cSigner; i++)
  2524. {
  2525. if (NULL != pcsi)
  2526. {
  2527. LocalFree(pcsi);
  2528. pcsi = NULL;
  2529. }
  2530. hr = myCryptMsgGetParam(
  2531. hMsg,
  2532. CMSG_CMS_SIGNER_INFO_PARAM,
  2533. i,
  2534. CERTLIB_USE_LOCALALLOC,
  2535. (VOID **) &pcsi,
  2536. &cb);
  2537. _JumpIfError(hr, error, "myCryptMsgGetParam");
  2538. if (CERT_ID_KEY_IDENTIFIER == pcsi->SignerId.dwIdChoice ||
  2539. (NULL != pcsi->HashEncryptionAlgorithm.pszObjId &&
  2540. 0 == strcmp(
  2541. szOID_PKIX_NO_SIGNATURE,
  2542. pcsi->HashEncryptionAlgorithm.pszObjId)))
  2543. {
  2544. cFirstSigner++;
  2545. continue;
  2546. }
  2547. iElement = i;
  2548. if (!CryptMsgGetAndVerifySigner(
  2549. hMsg,
  2550. 0, // cSignerStore
  2551. NULL, // rghSignerStore
  2552. CMSG_USE_SIGNER_INDEX_FLAG |
  2553. CMSG_SIGNER_ONLY_FLAG,
  2554. &pCert,
  2555. &iElement))
  2556. {
  2557. hr = myHLastError();
  2558. _JumpError(hr, error, "CryptMsgGetAndVerifySigner");
  2559. }
  2560. hr = myIsFirstSigner(&pCert->pCertInfo->Subject, &fFirst);
  2561. _JumpIfError(hr, error, "myIsFirstSigner");
  2562. CertFreeCertificateContext(pCert);
  2563. pCert = NULL;
  2564. if (!fFirst)
  2565. {
  2566. fDeleteSigner = TRUE;
  2567. break;
  2568. }
  2569. cFirstSigner++;
  2570. }
  2571. if (!fDeleteSigner)
  2572. {
  2573. break;
  2574. }
  2575. if (!CryptMsgControl(
  2576. hMsg,
  2577. 0, // dwFlags
  2578. CMSG_CTRL_DEL_SIGNER,
  2579. &iElement))
  2580. {
  2581. hr = myHLastError();
  2582. _JumpError(hr, error, "CryptMsgControl(delSigner)");
  2583. }
  2584. cb = sizeof(cSigner);
  2585. if (!CryptMsgGetParam(
  2586. hMsg,
  2587. CMSG_SIGNER_COUNT_PARAM,
  2588. 0,
  2589. &cSigner,
  2590. &cb))
  2591. {
  2592. hr = myHLastError();
  2593. _JumpError(hr, error, "CryptMsgGetParam(signer count)");
  2594. }
  2595. }
  2596. }
  2597. if (1 != cFirstSigner)
  2598. {
  2599. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  2600. _JumpError(hr, error, "cFirstSigner");
  2601. }
  2602. // Add or delete signing cert chain certs and CRLs in the message.
  2603. hr = AddOrDeleteMsgCertsAndCRLs(
  2604. pbPKCS7Old,
  2605. cbPKCS7Old,
  2606. hMsg,
  2607. NULL == pChainContext, // fDelete
  2608. pChainContext,
  2609. fIncludeCRLs);
  2610. _JumpIfError(hr, error, "AddOrDeleteMsgCertsAndCRLs");
  2611. // Get the signed message. Force reencoding with the changed signatures.
  2612. hr = myCryptMsgGetParam(
  2613. hMsg,
  2614. CMSG_ENCODED_MESSAGE,
  2615. 0,
  2616. CERTLIB_USE_LOCALALLOC,
  2617. (VOID **) ppbPKCS7New,
  2618. pcbPKCS7New);
  2619. _JumpIfError(hr, error, "myCryptMsgGetParam");
  2620. error:
  2621. if (NULL != pRequest)
  2622. {
  2623. LocalFree(pRequest);
  2624. }
  2625. if (NULL != pcsi)
  2626. {
  2627. LocalFree(pcsi);
  2628. }
  2629. if (NULL != BlobRequestClient.pbData)
  2630. {
  2631. LocalFree(BlobRequestClient.pbData);
  2632. }
  2633. if (NULL != pChainContext)
  2634. {
  2635. CertFreeCertificateChain(pChainContext);
  2636. }
  2637. if (NULL != pCert)
  2638. {
  2639. CertFreeCertificateContext(pCert);
  2640. }
  2641. if (NULL != hMsg)
  2642. {
  2643. CryptMsgClose(hMsg);
  2644. }
  2645. if (NULL != hProv && fCallerFreeProv)
  2646. {
  2647. CryptReleaseContext(hProv, 0);
  2648. }
  2649. return(hr);
  2650. }
  2651. HRESULT
  2652. ConvertCertToPKCS10Request(
  2653. IN OUT BYTE **ppbReq,
  2654. IN OUT DWORD *pcbReq)
  2655. {
  2656. HRESULT hr;
  2657. CERT_CONTEXT const *pCert = NULL;
  2658. BYTE *pbReqUnsigned = NULL;
  2659. DWORD cbReqUnsigned;
  2660. BYTE *pbReq = NULL;
  2661. DWORD cbReq;
  2662. CERT_REQUEST_INFO Request;
  2663. CRYPT_ATTR_BLOB ExtBlob;
  2664. CRYPT_ATTR_BLOB VersionBlob;
  2665. CERT_EXTENSIONS Extensions;
  2666. CRYPT_ATTRIBUTE aAttrib[2];
  2667. HCRYPTPROV hProv = NULL;
  2668. DWORD dwKeySpec;
  2669. BOOL fCallerFreeProv;
  2670. CERT_EXTENSION *pExt;
  2671. CERT_EXTENSION *pExtKeyId;
  2672. CERT_EXTENSION ExtKeyId;
  2673. CHAR *pszObjId = NULL;
  2674. ZeroMemory(&ExtKeyId, sizeof(ExtKeyId));
  2675. // Certificate extensions to strip out of the request:
  2676. static char const * const apszObjIdFilter[] = {
  2677. szOID_CERTSRV_CA_VERSION,
  2678. szOID_AUTHORITY_INFO_ACCESS,
  2679. szOID_CRL_DIST_POINTS,
  2680. szOID_AUTHORITY_KEY_IDENTIFIER2,
  2681. szOID_CERTSRV_PREVIOUS_CERT_HASH,
  2682. szOID_ENROLL_CERTTYPE_EXTENSION,
  2683. szOID_CERTIFICATE_TEMPLATE,
  2684. };
  2685. ExtBlob.pbData = NULL;
  2686. VersionBlob.pbData = NULL;
  2687. Extensions.rgExtension = NULL;
  2688. pCert = CertCreateCertificateContext(
  2689. X509_ASN_ENCODING,
  2690. *ppbReq,
  2691. *pcbReq);
  2692. if (NULL == pCert)
  2693. {
  2694. hr = myHLastError();
  2695. _JumpError(hr, error, "CertCreateCertificateContext");
  2696. }
  2697. ZeroMemory(&Request, sizeof(Request));
  2698. Request.dwVersion = CERT_REQUEST_V1;
  2699. Request.Subject = pCert->pCertInfo->Subject;
  2700. Request.SubjectPublicKeyInfo = pCert->pCertInfo->SubjectPublicKeyInfo;
  2701. Extensions.cExtension = 0;
  2702. Extensions.rgExtension = (CERT_EXTENSION *) LocalAlloc(
  2703. LMEM_FIXED,
  2704. sizeof(Extensions.rgExtension[0]) *
  2705. (1 + pCert->pCertInfo->cExtension));
  2706. if (NULL == Extensions.rgExtension)
  2707. {
  2708. hr = E_OUTOFMEMORY;
  2709. _JumpError(hr, error, "LocalAlloc");
  2710. }
  2711. pExtKeyId = NULL;
  2712. if (0 < pCert->pCertInfo->cExtension)
  2713. {
  2714. DWORD i;
  2715. DWORD j;
  2716. pExt = pCert->pCertInfo->rgExtension;
  2717. for (i = 0; i < pCert->pCertInfo->cExtension; i++)
  2718. {
  2719. if (0 == strcmp(szOID_SUBJECT_KEY_IDENTIFIER, pExt->pszObjId))
  2720. {
  2721. pExtKeyId = pExt;
  2722. }
  2723. for (j = 0; ; j++)
  2724. {
  2725. if (j >= ARRAYSIZE(apszObjIdFilter))
  2726. {
  2727. Extensions.rgExtension[Extensions.cExtension] =
  2728. pCert->pCertInfo->rgExtension[i];
  2729. Extensions.cExtension++;
  2730. break;
  2731. }
  2732. if (0 == strcmp(apszObjIdFilter[j], pExt->pszObjId))
  2733. {
  2734. break; // skip this extension
  2735. }
  2736. }
  2737. pExt++;
  2738. }
  2739. }
  2740. if (NULL == pExtKeyId)
  2741. {
  2742. BYTE abHash[CBMAX_CRYPT_HASH_LEN];
  2743. CRYPT_DATA_BLOB Blob;
  2744. Blob.pbData = abHash;
  2745. Blob.cbData = sizeof(abHash);
  2746. if (!CryptHashPublicKeyInfo(
  2747. NULL, // hCryptProv
  2748. CALG_SHA1,
  2749. 0, // dwFlags,
  2750. X509_ASN_ENCODING,
  2751. &Request.SubjectPublicKeyInfo,
  2752. Blob.pbData,
  2753. &Blob.cbData))
  2754. {
  2755. hr = myHLastError();
  2756. _JumpError(hr, error, "CryptHashPublicKeyInfo");
  2757. }
  2758. if (!myEncodeObject(
  2759. X509_ASN_ENCODING,
  2760. X509_OCTET_STRING,
  2761. &Blob,
  2762. 0,
  2763. CERTLIB_USE_LOCALALLOC,
  2764. &ExtKeyId.Value.pbData,
  2765. &ExtKeyId.Value.cbData))
  2766. {
  2767. hr = myHLastError();
  2768. _JumpError(hr, error, "myEncodeObject");
  2769. }
  2770. ExtKeyId.pszObjId = szOID_SUBJECT_KEY_IDENTIFIER;
  2771. pExtKeyId = &Extensions.rgExtension[Extensions.cExtension];
  2772. *pExtKeyId = ExtKeyId;
  2773. Extensions.cExtension++;
  2774. }
  2775. if (!myEncodeObject(
  2776. X509_ASN_ENCODING,
  2777. X509_EXTENSIONS,
  2778. &Extensions,
  2779. 0,
  2780. CERTLIB_USE_LOCALALLOC,
  2781. &ExtBlob.pbData,
  2782. &ExtBlob.cbData))
  2783. {
  2784. hr = myHLastError();
  2785. _JumpError(hr, error, "myEncodeObject");
  2786. }
  2787. // get the OS Version
  2788. hr = myBuildOSVersionAttribute(&VersionBlob.pbData, &VersionBlob.cbData);
  2789. _JumpIfError(hr, error, "myBuildOSVersionAttribute");
  2790. Request.cAttribute = 0;
  2791. Request.rgAttribute = aAttrib;
  2792. if (NULL != ExtBlob.pbData)
  2793. {
  2794. aAttrib[Request.cAttribute].pszObjId = szOID_RSA_certExtensions;
  2795. aAttrib[Request.cAttribute].cValue = 1;
  2796. aAttrib[Request.cAttribute].rgValue = &ExtBlob;
  2797. Request.cAttribute++;
  2798. }
  2799. aAttrib[Request.cAttribute].pszObjId = szOID_OS_VERSION;
  2800. aAttrib[Request.cAttribute].cValue = 1;
  2801. aAttrib[Request.cAttribute].rgValue = &VersionBlob;
  2802. Request.cAttribute++;
  2803. if (!myEncodeObject(
  2804. X509_ASN_ENCODING,
  2805. X509_CERT_REQUEST_TO_BE_SIGNED,
  2806. &Request,
  2807. 0,
  2808. CERTLIB_USE_LOCALALLOC,
  2809. &pbReqUnsigned,
  2810. &cbReqUnsigned))
  2811. {
  2812. hr = myHLastError();
  2813. _JumpError(hr, error, "myEncodeObject");
  2814. }
  2815. // Search for and load the cryptographic provider and private key.
  2816. hr = myLoadPrivateKey(
  2817. &pCert->pCertInfo->SubjectPublicKeyInfo,
  2818. CUCS_MACHINESTORE | CUCS_USERSTORE | CUCS_MYSTORE | CUCS_ARCHIVED,
  2819. &hProv,
  2820. &dwKeySpec,
  2821. &fCallerFreeProv);
  2822. if (S_OK != hr)
  2823. {
  2824. _PrintError(hr, "myLoadPrivateKey");
  2825. CSASSERT(NULL == hProv);
  2826. // private key is unavailable -- sign the PKCS10 with a NULL signature.
  2827. hr = myDupStringA(g_pszObjIdHash, &pszObjId);
  2828. _JumpIfError(hr, error, "myDupStringA");
  2829. }
  2830. else
  2831. {
  2832. if (AT_SIGNATURE != dwKeySpec)
  2833. {
  2834. hr = NTE_BAD_KEY_STATE;
  2835. DBGPRINT((DBG_SS_CERTREQ, "dwKeySpec = %u\n", dwKeySpec));
  2836. _JumpError(hr, error, "dwKeySpec");
  2837. }
  2838. // The private key is available -- use it to sign the PKCS10.
  2839. hr = myGetSigningOID(hProv, NULL, 0, CALG_SHA1, &pszObjId);
  2840. _JumpIfError(hr, error, "myGetSigningOID");
  2841. }
  2842. // Sign the request and encode the signed info.
  2843. hr = myEncodeSignedContent(
  2844. hProv,
  2845. X509_ASN_ENCODING,
  2846. pszObjId,
  2847. pbReqUnsigned,
  2848. cbReqUnsigned,
  2849. CERTLIB_USE_LOCALALLOC,
  2850. &pbReq,
  2851. &cbReq);
  2852. _JumpIfError(hr, error, "myEncodeSignedContent");
  2853. LocalFree(*ppbReq);
  2854. *ppbReq = pbReq;
  2855. *pcbReq = cbReq;
  2856. pbReq = NULL;
  2857. hr = S_OK;
  2858. error:
  2859. if (NULL != pszObjId)
  2860. {
  2861. LocalFree(pszObjId);
  2862. }
  2863. if (NULL != hProv && fCallerFreeProv)
  2864. {
  2865. CryptReleaseContext(hProv, 0);
  2866. }
  2867. if (NULL != Extensions.rgExtension)
  2868. {
  2869. LocalFree(Extensions.rgExtension);
  2870. }
  2871. if (NULL != ExtKeyId.Value.pbData)
  2872. {
  2873. LocalFree(ExtKeyId.Value.pbData);
  2874. }
  2875. if (NULL != ExtBlob.pbData)
  2876. {
  2877. LocalFree(ExtBlob.pbData);
  2878. }
  2879. if (NULL != VersionBlob.pbData)
  2880. {
  2881. LocalFree(VersionBlob.pbData);
  2882. }
  2883. if (NULL != pCert)
  2884. {
  2885. CertFreeCertificateContext(pCert);
  2886. }
  2887. if (NULL != pbReq)
  2888. {
  2889. LocalFree(pbReq);
  2890. }
  2891. if (NULL != pbReqUnsigned)
  2892. {
  2893. LocalFree(pbReqUnsigned);
  2894. }
  2895. return(hr);
  2896. }
  2897. HRESULT
  2898. GetPKCS10PrivateKey(
  2899. IN BYTE const *pbReq,
  2900. IN DWORD cbReq,
  2901. OUT HCRYPTPROV *phProv,
  2902. OUT DWORD *pdwKeySpec,
  2903. OUT BOOL *pfCallerFreeProv,
  2904. OUT BYTE **ppbKeyId,
  2905. OUT DWORD *pcbKeyId)
  2906. {
  2907. HRESULT hr;
  2908. CERT_REQUEST_INFO *pRequest = NULL;
  2909. HCRYPTPROV hProv = NULL;
  2910. CERT_EXTENSIONS *pExtensions = NULL;
  2911. CRYPT_ATTRIBUTE *pAttr;
  2912. BYTE *pbKeyId = NULL;
  2913. DWORD cbKeyId;
  2914. DWORD dwKeySpec;
  2915. DWORD cb;
  2916. DWORD i;
  2917. *phProv = NULL;
  2918. *pdwKeySpec = 0;
  2919. *ppbKeyId = NULL;
  2920. *pcbKeyId = 0;
  2921. if (!myDecodeObject(
  2922. X509_ASN_ENCODING,
  2923. X509_CERT_REQUEST_TO_BE_SIGNED,
  2924. pbReq,
  2925. cbReq,
  2926. CERTLIB_USE_LOCALALLOC,
  2927. (VOID **) &pRequest,
  2928. &cb))
  2929. {
  2930. hr = myHLastError();
  2931. _JumpError(hr, error, "myDecodeObject");
  2932. }
  2933. // Search for and load the cryptographic provider and private key.
  2934. hr = myLoadPrivateKey(
  2935. &pRequest->SubjectPublicKeyInfo,
  2936. CUCS_MACHINESTORE | CUCS_USERSTORE | CUCS_MYSTORE | CUCS_ARCHIVED,
  2937. &hProv,
  2938. &dwKeySpec,
  2939. pfCallerFreeProv);
  2940. _JumpIfError(hr, error, "myLoadPrivateKey");
  2941. if (AT_SIGNATURE != dwKeySpec)
  2942. {
  2943. hr = NTE_BAD_KEY_STATE;
  2944. DBGPRINT((DBG_SS_CERTREQ, "dwKeySpec = %u\n", dwKeySpec));
  2945. _JumpError(hr, error, "dwKeySpec");
  2946. }
  2947. // Fetch or construct the KeyId hash
  2948. pAttr = pRequest->rgAttribute;
  2949. for (i = 0; i < pRequest->cAttribute && NULL != pbKeyId; i++, pAttr++)
  2950. {
  2951. DWORD j;
  2952. if (0 == strcmp(szOID_RSA_certExtensions, pAttr->pszObjId) ||
  2953. 0 == strcmp(szOID_CERT_EXTENSIONS, pAttr->pszObjId))
  2954. {
  2955. for (j = 0; j < pAttr->cValue; j++)
  2956. {
  2957. DWORD k;
  2958. CERT_EXTENSION *pExt;
  2959. if (NULL != pExtensions)
  2960. {
  2961. LocalFree(pExtensions);
  2962. pExtensions = NULL;
  2963. }
  2964. if (!myDecodeObject(
  2965. X509_ASN_ENCODING,
  2966. X509_EXTENSIONS,
  2967. pAttr->rgValue[j].pbData,
  2968. pAttr->rgValue[j].cbData,
  2969. CERTLIB_USE_LOCALALLOC,
  2970. (VOID **) &pExtensions,
  2971. &cb))
  2972. {
  2973. hr = myHLastError();
  2974. _JumpError(hr, error, "myDecodeObject");
  2975. }
  2976. pExt = pExtensions->rgExtension;
  2977. for (k = 0; k < pExtensions->cExtension; k++, pExt++)
  2978. {
  2979. if (0 == strcmp(
  2980. pExt->pszObjId,
  2981. szOID_SUBJECT_KEY_IDENTIFIER))
  2982. {
  2983. if (!myDecodeObject(
  2984. X509_ASN_ENCODING,
  2985. X509_OCTET_STRING,
  2986. pExt->Value.pbData,
  2987. pExt->Value.cbData,
  2988. CERTLIB_USE_LOCALALLOC,
  2989. (VOID **) &pbKeyId,
  2990. &cbKeyId))
  2991. {
  2992. hr = myHLastError();
  2993. _JumpError(hr, error, "myDecodeObject");
  2994. }
  2995. break;
  2996. }
  2997. }
  2998. }
  2999. }
  3000. }
  3001. if (NULL == pbKeyId)
  3002. {
  3003. BYTE abHash[CBMAX_CRYPT_HASH_LEN];
  3004. cbKeyId = sizeof(abHash);
  3005. if (!CryptHashPublicKeyInfo(
  3006. NULL, // hCryptProv
  3007. CALG_SHA1,
  3008. 0, // dwFlags,
  3009. X509_ASN_ENCODING,
  3010. &pRequest->SubjectPublicKeyInfo,
  3011. abHash,
  3012. &cbKeyId))
  3013. {
  3014. hr = myHLastError();
  3015. _JumpError(hr, error, "CryptHashPublicKeyInfo");
  3016. }
  3017. pbKeyId = (BYTE *) LocalAlloc(LMEM_FIXED, cbKeyId);
  3018. if (NULL == pbKeyId)
  3019. {
  3020. hr = E_OUTOFMEMORY;
  3021. _JumpError(hr, error, "LocalAlloc");
  3022. }
  3023. CopyMemory(pbKeyId, abHash, cbKeyId);
  3024. }
  3025. *phProv = hProv;
  3026. hProv = NULL;
  3027. *ppbKeyId = pbKeyId;
  3028. pbKeyId = NULL;
  3029. *pcbKeyId = cbKeyId;
  3030. *pdwKeySpec = dwKeySpec;
  3031. hr = S_OK;
  3032. error:
  3033. if (NULL != hProv && *pfCallerFreeProv)
  3034. {
  3035. CryptReleaseContext(hProv, 0);
  3036. }
  3037. if (NULL != pExtensions)
  3038. {
  3039. LocalFree(pExtensions);
  3040. }
  3041. if (NULL != pbKeyId)
  3042. {
  3043. LocalFree(pbKeyId);
  3044. }
  3045. return(hr);
  3046. }
  3047. HRESULT
  3048. BuildNameValuePairs(
  3049. OPTIONAL IN WCHAR const *pwszAttributes,
  3050. IN OUT DWORD *pcValue,
  3051. OPTIONAL OUT CRYPT_ATTR_BLOB *pValue,
  3052. OPTIONAL OUT WCHAR **ppwszTemplateName)
  3053. {
  3054. HRESULT hr;
  3055. DWORD cValue = 0;
  3056. WCHAR *pwszDup = NULL;
  3057. WCHAR *pwszBuf;
  3058. WCHAR const *pwszName;
  3059. WCHAR const *pwszValue;
  3060. WCHAR *pwszTemplateName = NULL;
  3061. if (NULL != ppwszTemplateName)
  3062. {
  3063. *ppwszTemplateName = NULL;
  3064. }
  3065. if (NULL == pwszAttributes)
  3066. {
  3067. hr = S_OK;
  3068. goto error; // silently ignore empty string
  3069. }
  3070. hr = myDupString(pwszAttributes, &pwszDup);
  3071. _JumpIfError(hr, error, "myDupString");
  3072. pwszBuf = pwszDup;
  3073. while (TRUE)
  3074. {
  3075. hr = myParseNextAttribute(&pwszBuf, FALSE, &pwszName, &pwszValue);
  3076. if (S_FALSE == hr)
  3077. {
  3078. break;
  3079. }
  3080. _JumpIfError(hr, error, "myParseNextAttribute");
  3081. DBGPRINT((DBG_SS_CERTREQI, "'%ws' = '%ws'\n", pwszName, pwszValue));
  3082. if (NULL != pValue)
  3083. {
  3084. CRYPT_ENROLLMENT_NAME_VALUE_PAIR NamePair;
  3085. CSASSERT(cValue < *pcValue);
  3086. NamePair.pwszName = const_cast<WCHAR *>(pwszName);
  3087. NamePair.pwszValue = const_cast<WCHAR *>(pwszValue);
  3088. if (NULL != ppwszTemplateName &&
  3089. 0 == lstrcmpi(wszPROPCERTTEMPLATE, pwszName))
  3090. {
  3091. if (NULL != pwszTemplateName)
  3092. {
  3093. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  3094. _JumpError(hr, error, "Duplicate cert template");
  3095. }
  3096. hr = myDupString(pwszValue, &pwszTemplateName);
  3097. _JumpIfError(hr, error, "myDupString");
  3098. }
  3099. if (!myEncodeObject(
  3100. X509_ASN_ENCODING,
  3101. //X509_ENROLLMENT_NAME_VALUE_PAIR,
  3102. szOID_ENROLLMENT_NAME_VALUE_PAIR,
  3103. &NamePair,
  3104. 0,
  3105. CERTLIB_USE_LOCALALLOC,
  3106. &pValue[cValue].pbData,
  3107. &pValue[cValue].cbData))
  3108. {
  3109. hr = myHLastError();
  3110. _JumpError(hr, error, "myEncodeObject");
  3111. }
  3112. }
  3113. cValue++;
  3114. }
  3115. if (NULL != ppwszTemplateName)
  3116. {
  3117. *ppwszTemplateName = pwszTemplateName;
  3118. pwszTemplateName = NULL;
  3119. }
  3120. hr = S_OK;
  3121. error:
  3122. if (NULL != pwszTemplateName)
  3123. {
  3124. LocalFree(pwszTemplateName);
  3125. }
  3126. *pcValue = cValue;
  3127. if (NULL != pwszDup)
  3128. {
  3129. LocalFree(pwszDup);
  3130. }
  3131. return(hr);
  3132. }
  3133. HRESULT
  3134. PickCertAndSignRequest(
  3135. IN HWND hWndOwner,
  3136. IN BYTE const *pbReq,
  3137. IN DWORD cbReq,
  3138. IN BOOL fSkipSignerDeletion,
  3139. OUT BYTE **ppbPKCS7Out,
  3140. OUT DWORD *pcbPKCS7Out)
  3141. {
  3142. HRESULT hr;
  3143. CERT_CONTEXT const *pCertSigner = NULL;
  3144. if (NULL == g_pwszCertCN || 0 != lstrcmp(L"-", g_pwszCertCN))
  3145. {
  3146. if (!g_fQuiet || NULL != g_pwszCertCN)
  3147. {
  3148. hr = myGetERACertificateFromPicker(
  3149. g_hInstance,
  3150. NULL, // hwndParent
  3151. IDS_GETERACERT_TITLE,
  3152. IDS_GETERACERT_SUBTITLE,
  3153. (L'\0' == g_pwszCertCN || 0 == lstrcmp(L"*", g_pwszCertCN))?
  3154. NULL : g_pwszCertCN, // pwszCommonName
  3155. g_fQuiet,
  3156. &pCertSigner);
  3157. _JumpIfError(hr, error, "myGetERACertificateFromPicker");
  3158. }
  3159. // pCertSigner is NULL if the user cancelled out of the cert picker U/I.
  3160. // NULL pCertSigner means delete existing signatures.
  3161. if (NULL == pCertSigner)
  3162. {
  3163. if (fSkipSignerDeletion)
  3164. {
  3165. hr = S_FALSE;
  3166. _JumpError2(hr, error, "no signer selected", S_FALSE);
  3167. }
  3168. if (g_fQuiet || NULL != g_pwszCertCN)
  3169. {
  3170. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  3171. _JumpError(hr, error, "no matching signer CN");
  3172. }
  3173. }
  3174. }
  3175. hr = SignCMCContent(
  3176. pCertSigner,
  3177. szOID_CT_PKI_DATA,
  3178. pbReq,
  3179. cbReq,
  3180. 0 != (CR_OUT_CRLS & g_dwCRLOut),
  3181. ppbPKCS7Out,
  3182. pcbPKCS7Out);
  3183. _JumpIfError(hr, error, "SignCMCContent");
  3184. error:
  3185. if (NULL != pCertSigner)
  3186. {
  3187. CertFreeCertificateContext(pCertSigner);
  3188. }
  3189. return(hr);
  3190. }
  3191. HRESULT
  3192. SignQualifiedRequest(
  3193. IN HWND hWndOwner,
  3194. IN WCHAR const *pwszfnReq,
  3195. OPTIONAL IN WCHAR const *pwszfnOut)
  3196. {
  3197. HRESULT hr;
  3198. BYTE *pbReq = NULL;
  3199. DWORD cbReq;
  3200. BYTE *pbPKCS7Out = NULL;
  3201. DWORD cbPKCS7Out;
  3202. LONG dwFlags;
  3203. BOOL fSigned;
  3204. // Read the request from a file, convert it to binary, and return
  3205. // dwFlags to indicate the orignal encoding and the detected format.
  3206. hr = CheckRequestType(pwszfnReq, &pbReq, &cbReq, &dwFlags, &fSigned);
  3207. _JumpIfError(hr, error, "CheckRequestType");
  3208. if (CR_IN_CMC != (CR_IN_FORMATMASK & dwFlags))
  3209. {
  3210. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  3211. SetErrorString(pwszfnReq);
  3212. _JumpError(hr, error, "not a CMC request");
  3213. }
  3214. hr = PickCertAndSignRequest(
  3215. hWndOwner,
  3216. pbReq,
  3217. cbReq,
  3218. FALSE,
  3219. &pbPKCS7Out,
  3220. &cbPKCS7Out);
  3221. _JumpIfError(hr, error, "PickCertAndSignRequest");
  3222. hr = WriteCertificateOrRequest(
  3223. hWndOwner,
  3224. NULL, // pdiRequest
  3225. pbPKCS7Out,
  3226. cbPKCS7Out,
  3227. g_dwOutFormat,
  3228. pwszfnOut);
  3229. _JumpIfError(hr, error, "WriteCertificateOrRequest");
  3230. error:
  3231. if (NULL != pbReq)
  3232. {
  3233. LocalFree(pbReq);
  3234. }
  3235. if (NULL != pbPKCS7Out)
  3236. {
  3237. LocalFree(pbPKCS7Out);
  3238. }
  3239. return(hr);
  3240. }
  3241. HRESULT
  3242. ParseRequestInfo(
  3243. OPTIONAL IN WCHAR const *pwszAttributes,
  3244. IN WCHAR const *pwszfnPolicy,
  3245. OPTIONAL OUT INFVALUES **prgInfValues,
  3246. OPTIONAL OUT DWORD *pcInfValues,
  3247. OUT CRYPT_ATTRIBUTES **prgAttributes,
  3248. OUT DWORD *pcAttributes,
  3249. OUT CERT_EXTENSION **prgExt,
  3250. OUT DWORD *pcExt)
  3251. {
  3252. HRESULT hr;
  3253. CERT_EXTENSION *rgExtT;
  3254. CERT_EXTENSION *rgExt = NULL;
  3255. DWORD cExt;
  3256. CRYPT_ATTR_BLOB *argValue[2] = { NULL, NULL };
  3257. DWORD acValue[2];
  3258. DWORD i;
  3259. DWORD j;
  3260. CRYPT_ATTRIBUTES *rgAttributes = NULL;
  3261. DWORD cAttributes = 0;
  3262. WCHAR *pwszTemplateNameInf = NULL;
  3263. WCHAR *pwszTemplateName = NULL;
  3264. HCERTTYPE hCertType = NULL;
  3265. CERT_EXTENSIONS *pExtensions = NULL;
  3266. if (NULL != prgInfValues)
  3267. {
  3268. *prgInfValues = NULL;
  3269. }
  3270. if (NULL != pcInfValues)
  3271. {
  3272. *pcInfValues = 0;
  3273. }
  3274. *prgAttributes = NULL;
  3275. *pcAttributes = 0;
  3276. *prgExt = NULL;
  3277. *pcExt = 0;
  3278. hr = ParseInfFile(
  3279. pwszfnPolicy,
  3280. prgInfValues,
  3281. pcInfValues,
  3282. &argValue[0],
  3283. &acValue[0],
  3284. &rgExt,
  3285. &cExt,
  3286. &pwszTemplateNameInf);
  3287. if (S_OK != hr)
  3288. {
  3289. SetErrorString(pwszfnPolicy);
  3290. _JumpError(hr, error, "ParseInfFile");
  3291. }
  3292. if (0 != acValue[0])
  3293. {
  3294. cAttributes++;
  3295. }
  3296. // Count the command line request attributes
  3297. hr = BuildNameValuePairs(pwszAttributes, &acValue[1], NULL, NULL);
  3298. _JumpIfError(hr, error, "BuildNameValuePairs");
  3299. if (0 != acValue[1])
  3300. {
  3301. cAttributes++;
  3302. argValue[1] = (CRYPT_ATTR_BLOB *) LocalAlloc(
  3303. LMEM_FIXED | LMEM_ZEROINIT,
  3304. acValue[1] * sizeof(argValue[1][0]));
  3305. if (NULL == argValue[1])
  3306. {
  3307. hr = E_OUTOFMEMORY;
  3308. _JumpError(hr, error, "LocalAlloc");
  3309. }
  3310. hr = BuildNameValuePairs(
  3311. pwszAttributes,
  3312. &acValue[1],
  3313. argValue[1],
  3314. &pwszTemplateName);
  3315. _JumpIfError(hr, error, "BuildNameValuePairs");
  3316. }
  3317. if (0 != cAttributes)
  3318. {
  3319. rgAttributes = (CRYPT_ATTRIBUTES *) LocalAlloc(
  3320. LMEM_FIXED | LMEM_ZEROINIT,
  3321. cAttributes * sizeof(rgAttributes[0]));
  3322. if (NULL == rgAttributes)
  3323. {
  3324. hr = E_OUTOFMEMORY;
  3325. _JumpError(hr, error, "LocalAlloc");
  3326. }
  3327. for (i = j = 0; i < cAttributes; i++, j++)
  3328. {
  3329. CRYPT_ATTRIBUTE *rgAttr;
  3330. rgAttr = (CRYPT_ATTRIBUTE *) LocalAlloc(
  3331. LMEM_FIXED | LMEM_ZEROINIT,
  3332. sizeof(rgAttributes[i].rgAttr[0]));
  3333. if (NULL == rgAttr)
  3334. {
  3335. hr = E_OUTOFMEMORY;
  3336. _JumpError(hr, error, "LocalAlloc");
  3337. }
  3338. while (0 == acValue[j])
  3339. {
  3340. j++;
  3341. }
  3342. rgAttributes[i].cAttr = 1;
  3343. rgAttributes[i].rgAttr = rgAttr;
  3344. rgAttr[0].pszObjId = szOID_ENROLLMENT_NAME_VALUE_PAIR;
  3345. rgAttr[0].cValue = acValue[j];
  3346. rgAttr[0].rgValue = argValue[j];
  3347. argValue[j] = NULL;
  3348. }
  3349. }
  3350. if (NULL != pwszTemplateName || NULL != pwszTemplateNameInf)
  3351. {
  3352. WCHAR const *pwsz;
  3353. pwsz = pwszTemplateNameInf;
  3354. if (NULL == pwsz)
  3355. {
  3356. pwsz = pwszTemplateName;
  3357. CSASSERT(NULL != pwsz);
  3358. }
  3359. else if (NULL != pwszTemplateName &&
  3360. 0 != lstrcmpi(pwszTemplateName, pwszTemplateNameInf))
  3361. {
  3362. hr = CERTSRV_E_TEMPLATE_CONFLICT;
  3363. SetErrorString(wszPROPCERTTEMPLATE);
  3364. _JumpError(hr, error, "Template name conflict");
  3365. }
  3366. // Include the specified cert template's extensions
  3367. hr = CAFindCertTypeByName(
  3368. pwsz,
  3369. NULL,
  3370. CT_FIND_LOCAL_SYSTEM |
  3371. CT_ENUM_MACHINE_TYPES |
  3372. CT_ENUM_USER_TYPES,
  3373. &hCertType);
  3374. if (S_OK != hr)
  3375. {
  3376. hr = CAFindCertTypeByName(
  3377. pwsz,
  3378. NULL,
  3379. CT_FIND_LOCAL_SYSTEM |
  3380. CT_ENUM_MACHINE_TYPES |
  3381. CT_ENUM_USER_TYPES |
  3382. CT_FIND_BY_OID,
  3383. &hCertType);
  3384. _PrintIfErrorStr(hr, "CAFindCertTypeByName", pwsz);
  3385. }
  3386. if (S_OK == hr)
  3387. {
  3388. hr = CAGetCertTypeExtensions(hCertType, &pExtensions);
  3389. _PrintIfError(hr, "CAGetCertTypeExtensions");
  3390. }
  3391. if (S_OK == hr && NULL != pExtensions && 0 != pExtensions->cExtension)
  3392. {
  3393. CERT_EXTENSION *pExtSrc;
  3394. CERT_EXTENSION *pExtSrcEnd;
  3395. CERT_EXTENSION *pExtDst;
  3396. rgExtT = (CERT_EXTENSION *) LocalAlloc(
  3397. LMEM_FIXED | LMEM_ZEROINIT,
  3398. (pExtensions->cExtension + cExt) * sizeof(rgExtT[0]));
  3399. if (NULL == rgExtT)
  3400. {
  3401. hr = E_OUTOFMEMORY;
  3402. _JumpError(hr, error, "LocalAlloc");
  3403. }
  3404. if (NULL != rgExt)
  3405. {
  3406. CopyMemory(&rgExtT[0], &rgExt[0], cExt * sizeof(rgExtT[0]));
  3407. LocalFree(rgExt);
  3408. }
  3409. rgExt = rgExtT;
  3410. pExtSrc = pExtensions->rgExtension;
  3411. pExtSrcEnd = &pExtSrc[pExtensions->cExtension];
  3412. pExtDst = &rgExt[cExt];
  3413. for ( ; pExtSrc < pExtSrcEnd; pExtSrc++, pExtDst++)
  3414. {
  3415. pExtDst->fCritical = pExtSrc->fCritical;
  3416. pExtDst->Value.cbData = pExtSrc->Value.cbData;
  3417. hr = myDupStringA(pExtSrc->pszObjId, &pExtDst->pszObjId);
  3418. _JumpIfError(hr, error, "myDupStringA");
  3419. pExtDst->Value.pbData = (BYTE *) LocalAlloc(
  3420. LMEM_FIXED,
  3421. pExtSrc->Value.cbData);
  3422. if (NULL == pExtDst->Value.pbData)
  3423. {
  3424. hr = E_OUTOFMEMORY;
  3425. _JumpError(hr, error, "LocalAlloc");
  3426. }
  3427. CopyMemory(
  3428. pExtDst->Value.pbData,
  3429. pExtSrc->Value.pbData,
  3430. pExtSrc->Value.cbData);
  3431. }
  3432. cExt += pExtensions->cExtension;
  3433. }
  3434. else
  3435. {
  3436. CHAR const *pszObjId;
  3437. // Grow extension array to make room for the cert type extension
  3438. rgExtT = (CERT_EXTENSION *) LocalAlloc(
  3439. LMEM_FIXED | LMEM_ZEROINIT,
  3440. (cExt + 1) * sizeof(rgExtT[0]));
  3441. if (NULL == rgExtT)
  3442. {
  3443. hr = E_OUTOFMEMORY;
  3444. _JumpError(hr, error, "LocalAlloc");
  3445. }
  3446. if (0 != cExt)
  3447. {
  3448. CSASSERT(NULL != rgExt);
  3449. CopyMemory(&rgExtT[1], rgExt, cExt * sizeof(rgExt[0]));
  3450. LocalFree(rgExt);
  3451. }
  3452. rgExt = rgExtT;
  3453. cExt++;
  3454. hr = myBuildCertTypeExtension(pwsz, &rgExt[0]);
  3455. _JumpIfError(hr, error, "myBuildCertTypeExtension");
  3456. pszObjId = rgExt[0].pszObjId;
  3457. rgExt[0].pszObjId = NULL;
  3458. hr = myDupStringA(pszObjId, &rgExt[0].pszObjId);
  3459. _JumpIfError(hr, error, "myDupStringA");
  3460. }
  3461. }
  3462. *prgAttributes = rgAttributes;
  3463. rgAttributes = NULL;
  3464. *pcAttributes = cAttributes;
  3465. *prgExt = rgExt;
  3466. rgExt = NULL;
  3467. *pcExt = cExt;
  3468. hr = S_OK;
  3469. error:
  3470. if (S_OK != hr && NULL != prgInfValues)
  3471. {
  3472. myInfFreeSectionValues(*pcInfValues, *prgInfValues);
  3473. *prgInfValues = NULL;
  3474. *pcInfValues = 0;
  3475. }
  3476. if (NULL != rgAttributes)
  3477. {
  3478. FreeAttributes(cAttributes, rgAttributes);
  3479. }
  3480. for (i = 0; i < ARRAYSIZE(argValue); i++)
  3481. {
  3482. if (NULL != argValue[i])
  3483. {
  3484. myInfFreeRequestAttributes(acValue[i], argValue[i]);
  3485. }
  3486. }
  3487. if (NULL != rgExt)
  3488. {
  3489. FreeExtensions(TRUE, cExt, rgExt);
  3490. }
  3491. if (NULL != pwszTemplateNameInf)
  3492. {
  3493. LocalFree(pwszTemplateNameInf);
  3494. }
  3495. if (NULL != pwszTemplateName)
  3496. {
  3497. LocalFree(pwszTemplateName);
  3498. }
  3499. if (NULL != hCertType)
  3500. {
  3501. if (NULL != pExtensions)
  3502. {
  3503. CAFreeCertTypeExtensions(hCertType, pExtensions);
  3504. }
  3505. CACloseCertType(hCertType);
  3506. }
  3507. return(hr);
  3508. }
  3509. HRESULT
  3510. CreateQualifiedRequest(
  3511. IN HWND hWndOwner,
  3512. OPTIONAL IN WCHAR const *pwszAttributes,
  3513. IN WCHAR const *pwszfnReq,
  3514. IN WCHAR const *pwszfnPolicy,
  3515. OPTIONAL IN WCHAR const *pwszfnOut,
  3516. OPTIONAL IN WCHAR const *pwszfnPKCS10)
  3517. {
  3518. HRESULT hr;
  3519. BYTE *pbReq = NULL;
  3520. DWORD cbReq;
  3521. BYTE *pbKeyId = NULL;
  3522. DWORD cbKeyId = 0;
  3523. BYTE *pbReqCMCFirstSigned = NULL;
  3524. DWORD cbReqCMCFirstSigned;
  3525. BYTE *pbReqCMCOut = NULL;
  3526. DWORD cbReqCMCOut;
  3527. LONG dwFlags;
  3528. BOOL fNestedCMCRequest = FALSE;
  3529. BOOL fSigned;
  3530. CRYPT_ATTRIBUTES *rgAttributes = NULL;
  3531. DWORD cAttributes;
  3532. CERT_EXTENSION *rgExt = NULL;
  3533. DWORD cExt;
  3534. DWORD i;
  3535. HCRYPTPROV hProv = NULL;
  3536. DWORD dwKeySpec = 0;
  3537. BOOL fCallerFreeProv;
  3538. cAttributes = 0;
  3539. // Read the request from a file, convert it to binary, and return
  3540. // dwFlags to indicate the orignal encoding and the detected format.
  3541. hr = CheckRequestType(pwszfnReq, &pbReq, &cbReq, &dwFlags, &fSigned);
  3542. _JumpIfError(hr, error, "CheckRequestType");
  3543. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  3544. switch (CR_IN_FORMATMASK & dwFlags)
  3545. {
  3546. case CR_IN_CMC:
  3547. fNestedCMCRequest = TRUE;
  3548. break;
  3549. case CR_IN_CERT:
  3550. hr = ConvertCertToPKCS10Request(&pbReq, &cbReq);
  3551. _JumpIfError(hr, error, "ConvertCertToPKCS10Request");
  3552. dwFlags = CR_IN_PKCS10 | (~CR_IN_FORMATMASK & dwFlags);
  3553. break;
  3554. case CR_IN_PKCS10:
  3555. break;
  3556. default:
  3557. _JumpError(hr, error, "not a CMC or PKCS10 request");
  3558. }
  3559. if (CR_IN_PKCS10 == (CR_IN_FORMATMASK & dwFlags))
  3560. {
  3561. if (NULL != pwszfnPKCS10)
  3562. {
  3563. hr = crOverwriteFileAllowed(hWndOwner, pwszfnPKCS10);
  3564. _JumpIfError(hr, error, "crOverwriteFileAllowed");
  3565. hr = EncodeToFileW(
  3566. pwszfnPKCS10,
  3567. pbReq,
  3568. cbReq,
  3569. DECF_FORCEOVERWRITE | g_dwOutFormat);
  3570. if (S_OK != hr)
  3571. {
  3572. SetErrorString(pwszfnPKCS10);
  3573. _JumpErrorStr(hr, error, "EncodeToFileW", pwszfnPKCS10);
  3574. }
  3575. }
  3576. hr = GetPKCS10PrivateKey(
  3577. pbReq,
  3578. cbReq,
  3579. &hProv,
  3580. &dwKeySpec,
  3581. &fCallerFreeProv,
  3582. &pbKeyId,
  3583. &cbKeyId);
  3584. _PrintIfError(hr, "GetPKCS10PrivateKey");
  3585. }
  3586. hr = ParseRequestInfo(
  3587. pwszAttributes,
  3588. pwszfnPolicy,
  3589. NULL, // prgInfValues
  3590. NULL, // pcInfValues
  3591. &rgAttributes,
  3592. &cAttributes,
  3593. &rgExt,
  3594. &cExt);
  3595. if (S_OK != hr)
  3596. {
  3597. SetErrorString(pwszfnPolicy);
  3598. _JumpError(hr, error, "ParseRequestInfo");
  3599. }
  3600. hr = BuildCMCRequest(
  3601. XECI_CERTREQ,
  3602. fNestedCMCRequest,
  3603. pbReq,
  3604. cbReq,
  3605. rgExt,
  3606. cExt,
  3607. rgAttributes,
  3608. cAttributes,
  3609. NULL, // rgAttributeUnauth
  3610. 0, // cAttributeUnauth
  3611. pbKeyId,
  3612. cbKeyId,
  3613. hProv,
  3614. dwKeySpec,
  3615. NULL == hProv? NULL : g_pszObjIdHash,
  3616. NULL, // pCertSigner
  3617. NULL, // hProvSigner
  3618. 0, // dwKeySpecSigner
  3619. NULL, // pszObjIdHashSigner
  3620. &pbReqCMCFirstSigned,
  3621. &cbReqCMCFirstSigned);
  3622. _JumpIfError(hr, error, "BuildCMCRequest");
  3623. hr = PickCertAndSignRequest(
  3624. hWndOwner,
  3625. pbReqCMCFirstSigned,
  3626. cbReqCMCFirstSigned,
  3627. TRUE,
  3628. &pbReqCMCOut,
  3629. &cbReqCMCOut);
  3630. if (S_OK != hr)
  3631. {
  3632. _PrintError2(hr, "PickCertAndSignRequest", S_FALSE);
  3633. if (S_FALSE != hr)
  3634. {
  3635. goto error;
  3636. }
  3637. // The user cancelled out of the cert picker U/I, so just save the
  3638. // unsigned request.
  3639. pbReqCMCOut = pbReqCMCFirstSigned;
  3640. cbReqCMCOut = cbReqCMCFirstSigned;
  3641. }
  3642. hr = WriteCertificateOrRequest(
  3643. hWndOwner,
  3644. NULL, // pdiRequest
  3645. pbReqCMCOut,
  3646. cbReqCMCOut,
  3647. g_dwOutFormat,
  3648. pwszfnOut);
  3649. _JumpIfError(hr, error, "WriteCertificateOrRequest");
  3650. error:
  3651. if (NULL != hProv && fCallerFreeProv)
  3652. {
  3653. CryptReleaseContext(hProv, 0);
  3654. }
  3655. if (NULL != rgExt)
  3656. {
  3657. FreeExtensions(TRUE, cExt, rgExt);
  3658. }
  3659. if (NULL != rgAttributes)
  3660. {
  3661. FreeAttributes(cAttributes, rgAttributes);
  3662. }
  3663. if (NULL != pbReqCMCOut && pbReqCMCFirstSigned != pbReqCMCOut)
  3664. {
  3665. LocalFree(pbReqCMCOut);
  3666. }
  3667. if (NULL != pbReqCMCFirstSigned)
  3668. {
  3669. LocalFree(pbReqCMCFirstSigned);
  3670. }
  3671. if (NULL != pbKeyId)
  3672. {
  3673. LocalFree(pbKeyId);
  3674. }
  3675. if (NULL != pbReq)
  3676. {
  3677. LocalFree(pbReq);
  3678. }
  3679. return(hr);
  3680. }
  3681. HRESULT
  3682. GetCAXchgCert(
  3683. IN WCHAR const *pwszValue,
  3684. OUT CERT_CONTEXT const **ppccXchg)
  3685. {
  3686. HRESULT hr;
  3687. BOOL fEnabled;
  3688. BSTR strConfig = NULL;
  3689. BSTR strCert = NULL;
  3690. WCHAR const *pwszConfig;
  3691. DISPATCHINTERFACE diRequest;
  3692. BOOL fMustRelease = FALSE;
  3693. *ppccXchg = NULL;
  3694. hr = myInfParseBooleanValue(pwszValue, &fEnabled);
  3695. _JumpIfError(hr, error, "myInfParseBooleanValue");
  3696. if (fEnabled)
  3697. {
  3698. pwszConfig = g_pwszConfig;
  3699. if (NULL == pwszConfig)
  3700. {
  3701. hr = crGetConfig(&strConfig);
  3702. _JumpIfError(hr, error, "crGetConfig");
  3703. pwszConfig = strConfig;
  3704. }
  3705. hr = Request_Init(g_fIDispatch, &diRequest);
  3706. if (S_OK != hr)
  3707. {
  3708. _PrintError(hr, "Request_Init");
  3709. if (E_ACCESSDENIED == hr) // try for a clearer error message
  3710. {
  3711. hr = CO_E_REMOTE_COMMUNICATION_FAILURE;
  3712. }
  3713. _JumpError(hr, error, "Request_Init");
  3714. }
  3715. fMustRelease = TRUE;
  3716. hr = Request2_GetCAProperty(
  3717. &diRequest,
  3718. pwszConfig,
  3719. CR_PROP_CAXCHGCERT,
  3720. 0, // Index
  3721. PROPTYPE_BINARY,
  3722. CV_OUT_BINARY,
  3723. (VOID *) &strCert);
  3724. _JumpIfError(hr, error, "Request2_GetCAProperty");
  3725. *ppccXchg = CertCreateCertificateContext(
  3726. X509_ASN_ENCODING,
  3727. (BYTE const *) strCert,
  3728. SysStringByteLen(strCert));
  3729. if (NULL == *ppccXchg)
  3730. {
  3731. hr = myHLastError();
  3732. _JumpError(hr, error, "CertCreateCertificateContext");
  3733. }
  3734. }
  3735. hr = S_OK;
  3736. error:
  3737. if (NULL != strConfig)
  3738. {
  3739. SysFreeString(strConfig);
  3740. }
  3741. if (NULL != strCert)
  3742. {
  3743. SysFreeString(strCert);
  3744. }
  3745. if (fMustRelease)
  3746. {
  3747. Request_Release(&diRequest);
  3748. }
  3749. return(hr);
  3750. }
  3751. HRESULT
  3752. GetRenewalCert(
  3753. IN WCHAR const *pwszValue,
  3754. OUT CERT_CONTEXT const **ppccRenewal)
  3755. {
  3756. HRESULT hr;
  3757. BOOL fEnabled;
  3758. BSTR strConfig = NULL;
  3759. BSTR strCert = NULL;
  3760. WCHAR const *pwszConfig;
  3761. DISPATCHINTERFACE diRequest;
  3762. BOOL fMustRelease = FALSE;
  3763. *ppccRenewal = NULL;
  3764. hr = myGetCertificateFromPicker(
  3765. g_hInstance,
  3766. NULL, // hwndParent
  3767. IDS_GETRENEWALCERT_TITLE,
  3768. IDS_GETRENEWALCERT_SUBTITLE,
  3769. CUCS_MYSTORE |
  3770. CUCS_MACHINESTORE | CUCS_USERSTORE |
  3771. CUCS_DSSTORE |
  3772. CUCS_PRIVATEKEYREQUIRED |
  3773. (g_fVerbose? CUCS_ARCHIVED : 0) |
  3774. (g_fQuiet? CUCS_SILENT : 0),
  3775. (L'\0' == pwszValue || 0 == lstrcmp(L"*", pwszValue))?
  3776. NULL : pwszValue, // pwszCommonName
  3777. 0, // cStore
  3778. NULL, // rghStore
  3779. 0, // cpszObjId
  3780. NULL, // apszObjId
  3781. ppccRenewal);
  3782. _JumpIfError(hr, error, "myGetCertificateFromPicker");
  3783. error:
  3784. if (NULL != strConfig)
  3785. {
  3786. SysFreeString(strConfig);
  3787. }
  3788. if (NULL != strCert)
  3789. {
  3790. SysFreeString(strCert);
  3791. }
  3792. if (fMustRelease)
  3793. {
  3794. Request_Release(&diRequest);
  3795. }
  3796. return(hr);
  3797. }
  3798. HRESULT
  3799. CreateNewRequest(
  3800. IN HWND hWndOwner,
  3801. OPTIONAL IN WCHAR const *pwszAttributes,
  3802. IN WCHAR const *pwszfnPolicy,
  3803. OPTIONAL IN WCHAR const *pwszfnOut)
  3804. {
  3805. HRESULT hr;
  3806. BOOL fCoInit = FALSE;
  3807. IEnroll4 *pEnroll = NULL;
  3808. CRYPT_DATA_BLOB blobRequest;
  3809. WCHAR *pwszObjId = NULL;
  3810. DWORD cInfValues;
  3811. INFVALUES *rgInfValues = NULL;
  3812. CRYPT_ATTRIBUTES *rgAttributes = NULL;
  3813. DWORD cAttributes;
  3814. CERT_EXTENSION *rgExtT;
  3815. CERT_EXTENSION *rgExt = NULL;
  3816. CERT_CONTEXT const *pccXchg = NULL;
  3817. CERT_CONTEXT const *pccRenewal = NULL;
  3818. CERT_CONTEXT const *pccSigner = NULL;
  3819. CERT_NAME_BLOB NameBlob;
  3820. WCHAR *pwszDN = NULL;
  3821. DWORD cExt = 0;
  3822. DWORD i;
  3823. DWORD j;
  3824. DWORD k;
  3825. DWORD RequestTypeFlags;
  3826. BOOL fReqestTypeSet;
  3827. blobRequest.pbData = NULL;
  3828. NameBlob.pbData = NULL;
  3829. cAttributes = 0;
  3830. hr = ParseRequestInfo(
  3831. pwszAttributes,
  3832. pwszfnPolicy,
  3833. &rgInfValues,
  3834. &cInfValues,
  3835. &rgAttributes,
  3836. &cAttributes,
  3837. &rgExt,
  3838. &cExt);
  3839. if (S_OK != hr)
  3840. {
  3841. SetErrorString(pwszfnPolicy);
  3842. _JumpError(hr, error, "ParseRequestInfo");
  3843. }
  3844. hr = CoInitialize(NULL);
  3845. if (S_OK != hr && S_FALSE != hr)
  3846. {
  3847. _JumpError(hr, error, "CoInitialize");
  3848. }
  3849. fCoInit = TRUE;
  3850. hr = CoCreateInstance(
  3851. CLSID_CEnroll,
  3852. NULL, // pUnkOuter
  3853. CLSCTX_INPROC_SERVER,
  3854. IID_IEnroll4,
  3855. (VOID **) &pEnroll);
  3856. _JumpIfError(hr, error, "CoCreateInstance");
  3857. for (i = 0; i < cAttributes; i++)
  3858. {
  3859. CRYPT_ATTRIBUTES *pAttributes = &rgAttributes[i];
  3860. for (j = 0; j < pAttributes->cAttr; j++)
  3861. {
  3862. CRYPT_ATTRIBUTE *pAttr = &pAttributes->rgAttr[j];
  3863. if (NULL != pwszObjId)
  3864. {
  3865. LocalFree(pwszObjId);
  3866. pwszObjId = NULL;
  3867. }
  3868. if (!ConvertSzToWsz(&pwszObjId, pAttr->pszObjId, -1))
  3869. {
  3870. hr = E_OUTOFMEMORY;
  3871. _JumpError(hr, error, "ConvertSzToWsz");
  3872. }
  3873. for (k = 0; k < pAttr->cValue; k++)
  3874. {
  3875. hr = pEnroll->addAttributeToRequestWStr(
  3876. 0, // Flags
  3877. pwszObjId,
  3878. &pAttr->rgValue[k]);
  3879. _JumpIfError(hr, error, "addAttributeToRequestWStr");
  3880. }
  3881. }
  3882. }
  3883. for (i = 0; i < cExt; i++)
  3884. {
  3885. CERT_EXTENSION *pExt = &rgExt[i];
  3886. if (NULL != pwszObjId)
  3887. {
  3888. LocalFree(pwszObjId);
  3889. pwszObjId = NULL;
  3890. }
  3891. if (!ConvertSzToWsz(&pwszObjId, pExt->pszObjId, -1))
  3892. {
  3893. hr = E_OUTOFMEMORY;
  3894. _JumpError(hr, error, "ConvertSzToWsz");
  3895. }
  3896. hr = pEnroll->addExtensionToRequestWStr(
  3897. pExt->fCritical,
  3898. pwszObjId,
  3899. &pExt->Value);
  3900. _JumpIfError(hr, error, "addExtensionToRequestWStr");
  3901. }
  3902. fReqestTypeSet = FALSE;
  3903. for (i = 0; i < cInfValues; i++)
  3904. {
  3905. INFVALUES *pInfValues = &rgInfValues[i];
  3906. WCHAR const *pwszInfValue;
  3907. LONG lFlagsT;
  3908. BOOL fT;
  3909. BOOL fValid;
  3910. if (1 != pInfValues->cValues)
  3911. {
  3912. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  3913. SetErrorStringInf(pwszfnPolicy, pInfValues);
  3914. _JumpError(hr, error, "Wrong value count");
  3915. }
  3916. pwszInfValue = pInfValues->rgpwszValues[0];
  3917. if (NULL == pwszDN &&
  3918. 0 == lstrcmpi(wszINFKEY_SUBJECT, pInfValues->pwszKey))
  3919. {
  3920. // Reverse the name for XEnroll!?
  3921. hr = myCertStrToName(
  3922. X509_ASN_ENCODING,
  3923. pwszInfValue, // pszX500
  3924. 0, // CERT_NAME_STR_REVERSE_FLAG,
  3925. NULL, // pvReserved
  3926. &NameBlob.pbData,
  3927. &NameBlob.cbData,
  3928. NULL); // ppszError
  3929. _JumpIfError(hr, error, "myCertStrToName");
  3930. hr = myCertNameToStr(
  3931. X509_ASN_ENCODING,
  3932. &NameBlob,
  3933. CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
  3934. &pwszDN);
  3935. _JumpIfError(hr, error, "myCertNameToStr");
  3936. }
  3937. else
  3938. if (NULL == pccXchg &&
  3939. 0 == lstrcmpi(wszINFKEY_PRIVATEKEYARCHIVE, pInfValues->pwszKey))
  3940. {
  3941. hr = GetCAXchgCert(pwszInfValue, &pccXchg);
  3942. _JumpIfError(hr, error, "GetCAXchgCert");
  3943. }
  3944. else
  3945. if (NULL == pccRenewal &&
  3946. 0 == lstrcmpi(wszINFKEY_RENEWALCERT, pInfValues->pwszKey))
  3947. {
  3948. hr = GetRenewalCert(pwszInfValue, &pccRenewal);
  3949. _JumpIfError(hr, error, "GetRenewalCert");
  3950. }
  3951. else
  3952. if (0 == lstrcmpi(wszINFKEY_KEYSPEC, pInfValues->pwszKey))
  3953. {
  3954. DWORD dwKeySpec;
  3955. dwKeySpec = myWtoI(pwszInfValue, &fValid);
  3956. if (!fValid ||
  3957. (AT_SIGNATURE != dwKeySpec && AT_KEYEXCHANGE != dwKeySpec))
  3958. {
  3959. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  3960. SetErrorStringInf(pwszfnPolicy, pInfValues);
  3961. _JumpError(hr, error, "Bad KeySpec value");
  3962. }
  3963. hr = pEnroll->put_KeySpec(dwKeySpec);
  3964. _JumpIfError(hr, error, "put_KeySpec");
  3965. }
  3966. else
  3967. if (0 == lstrcmpi(wszINFKEY_KEYLENGTH, pInfValues->pwszKey))
  3968. {
  3969. DWORD dwKeyLength;
  3970. dwKeyLength = myWtoI(pwszInfValue, &fValid);
  3971. if (!fValid || 0 == dwKeyLength || 64 * 1024 <= dwKeyLength)
  3972. {
  3973. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  3974. SetErrorStringInf(pwszfnPolicy, pInfValues);
  3975. _JumpError(hr, error, "Bad KeyLength value");
  3976. }
  3977. hr = pEnroll->get_GenKeyFlags(&lFlagsT);
  3978. _JumpIfError(hr, error, "get_GenKeyFlags");
  3979. lFlagsT &= ~KEY_LENGTH_MASK;
  3980. lFlagsT |= dwKeyLength << 16;
  3981. hr = pEnroll->put_GenKeyFlags(lFlagsT);
  3982. _JumpIfError(hr, error, "put_GenKeyFlags");
  3983. }
  3984. else
  3985. if (0 == lstrcmpi(wszINFKEY_EXPORTABLE, pInfValues->pwszKey))
  3986. {
  3987. hr = myInfParseBooleanValue(pwszInfValue, &fT);
  3988. _JumpIfError(hr, error, "myInfParseBooleanValue");
  3989. hr = pEnroll->get_GenKeyFlags(&lFlagsT);
  3990. _JumpIfError(hr, error, "get_GenKeyFlags");
  3991. lFlagsT &= ~CRYPT_EXPORTABLE;
  3992. lFlagsT |= fT? CRYPT_EXPORTABLE : 0;
  3993. hr = pEnroll->put_GenKeyFlags(lFlagsT);
  3994. _JumpIfError(hr, error, "put_GenKeyFlags");
  3995. }
  3996. else
  3997. if (0 == lstrcmpi(wszINFKEY_USERPROTECTED, pInfValues->pwszKey))
  3998. {
  3999. hr = myInfParseBooleanValue(pwszInfValue, &fT);
  4000. _JumpIfError(hr, error, "myInfParseBooleanValue");
  4001. hr = pEnroll->get_GenKeyFlags(&lFlagsT);
  4002. _JumpIfError(hr, error, "get_GenKeyFlags");
  4003. lFlagsT &= ~CRYPT_USER_PROTECTED;
  4004. lFlagsT |= fT? CRYPT_USER_PROTECTED : 0;
  4005. hr = pEnroll->put_GenKeyFlags(lFlagsT);
  4006. _JumpIfError(hr, error, "put_GenKeyFlags");
  4007. }
  4008. else
  4009. if (0 == lstrcmpi(wszINFKEY_KEYCONTAINER, pInfValues->pwszKey))
  4010. {
  4011. hr = pEnroll->put_ContainerNameWStr(
  4012. const_cast<WCHAR *>(pwszInfValue));
  4013. _JumpIfError(hr, error, "put_ContainerNameWStr");
  4014. }
  4015. #if 0
  4016. else
  4017. if (0 == lstrcmpi(wszINFKEY_HASHALGID, pInfValues->pwszKey))
  4018. {
  4019. hr = myInfParseBooleanValue(pwszInfValue, &fT);
  4020. _JumpIfError(hr, error, "myInfParseBooleanValue");
  4021. hr = pEnroll->get_GenKeyFlags(&lFlagsT);
  4022. _JumpIfError(hr, error, "get_GenKeyFlags");
  4023. lFlagsT &= ~CRYPT_EXPORTABLE;
  4024. lFlagsT |= fT? CRYPT_EXPORTABLE : 0;
  4025. hr = pEnroll->put_GenKeyFlags(lFlagsT);
  4026. _JumpIfError(hr, error, "put_GenKeyFlags");
  4027. }
  4028. else
  4029. if (0 == lstrcmpi(wszINFKEY_HASHALGORITHM, pInfValues->pwszKey))
  4030. {
  4031. hr = myInfParseBooleanValue(pwszInfValue, &fT);
  4032. _JumpIfError(hr, error, "myInfParseBooleanValue");
  4033. hr = pEnroll->get_GenKeyFlags(&lFlagsT);
  4034. _JumpIfError(hr, error, "get_GenKeyFlags");
  4035. lFlagsT &= ~CRYPT_EXPORTABLE;
  4036. lFlagsT |= fT? CRYPT_EXPORTABLE : 0;
  4037. hr = pEnroll->put_GenKeyFlags(lFlagsT);
  4038. _JumpIfError(hr, error, "put_GenKeyFlags");
  4039. }
  4040. #endif
  4041. else
  4042. if (0 == lstrcmpi(wszINFKEY_MACHINEKEYSET, pInfValues->pwszKey))
  4043. {
  4044. hr = myInfParseBooleanValue(pwszInfValue, &fT);
  4045. _JumpIfError(hr, error, "myInfParseBooleanValue");
  4046. hr = pEnroll->get_ProviderFlags(&lFlagsT);
  4047. _JumpIfError(hr, error, "get_ProviderFlags");
  4048. lFlagsT &= ~CRYPT_MACHINE_KEYSET;
  4049. lFlagsT |= fT? CRYPT_MACHINE_KEYSET : 0;
  4050. hr = pEnroll->put_ProviderFlags(lFlagsT);
  4051. _JumpIfError(hr, error, "put_ProviderFlags");
  4052. hr = pEnroll->get_MyStoreFlags(&lFlagsT);
  4053. _JumpIfError(hr, error, "get_MyStoreFlags");
  4054. lFlagsT &= ~(CERT_SYSTEM_STORE_CURRENT_USER |
  4055. CERT_SYSTEM_STORE_LOCAL_MACHINE);
  4056. lFlagsT |= fT? CERT_SYSTEM_STORE_LOCAL_MACHINE :
  4057. CERT_SYSTEM_STORE_CURRENT_USER;
  4058. hr = pEnroll->put_MyStoreFlags(lFlagsT);
  4059. _JumpIfError(hr, error, "put_MyStoreFlags");
  4060. }
  4061. else
  4062. if (0 == lstrcmpi(wszINFKEY_SILENT, pInfValues->pwszKey))
  4063. {
  4064. hr = myInfParseBooleanValue(pwszInfValue, &fT);
  4065. _JumpIfError(hr, error, "myInfParseBooleanValue");
  4066. hr = pEnroll->get_ProviderFlags(&lFlagsT);
  4067. _JumpIfError(hr, error, "get_ProviderFlags");
  4068. lFlagsT &= ~CRYPT_SILENT;
  4069. lFlagsT |= fT? CRYPT_SILENT : 0;
  4070. hr = pEnroll->put_ProviderFlags(lFlagsT);
  4071. _JumpIfError(hr, error, "put_ProviderFlags");
  4072. }
  4073. else
  4074. if (0 == lstrcmpi(wszINFKEY_PROVIDERNAME, pInfValues->pwszKey))
  4075. {
  4076. hr = pEnroll->put_ProviderNameWStr(
  4077. const_cast<WCHAR *>(pwszInfValue));
  4078. _JumpIfError(hr, error, "put_ProviderNameWStr");
  4079. }
  4080. else
  4081. if (0 == lstrcmpi(wszINFKEY_PROVIDERTYPE, pInfValues->pwszKey))
  4082. {
  4083. lFlagsT = myWtoI(pwszInfValue, &fValid);
  4084. if (!fValid)
  4085. {
  4086. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  4087. SetErrorStringInf(pwszfnPolicy, pInfValues);
  4088. _JumpError(hr, error, "Bad ProviderType value");
  4089. }
  4090. hr = pEnroll->put_ProviderType(lFlagsT);
  4091. _JumpIfError(hr, error, "put_ProviderType");
  4092. }
  4093. else
  4094. if (0 == lstrcmpi(wszINFKEY_USEEXISTINHKEYSET, pInfValues->pwszKey))
  4095. {
  4096. hr = myInfParseBooleanValue(pwszInfValue, &fT);
  4097. _JumpIfError(hr, error, "myInfParseBooleanValue");
  4098. hr = pEnroll->put_UseExistingKeySet(lFlagsT);
  4099. _JumpIfError(hr, error, "put_UseExistingKeySet");
  4100. }
  4101. else
  4102. if (0 == lstrcmpi(wszINFKEY_SMIME, pInfValues->pwszKey))
  4103. {
  4104. BOOL fSMIME;
  4105. hr = myInfParseBooleanValue(pwszInfValue, &fSMIME);
  4106. _JumpIfError(hr, error, "myInfParseBooleanValue");
  4107. hr = pEnroll->put_EnableSMIMECapabilities(fSMIME);
  4108. _JumpIfError(hr, error, "put_EnableSMIMECapabilities");
  4109. }
  4110. else
  4111. if (0 == lstrcmpi(wszINFKEY_REQUESTERNAME, pInfValues->pwszKey))
  4112. {
  4113. hr = pEnroll->AddNameValuePairToSignatureWStr(
  4114. wszINFKEY_REQUESTERNAME,
  4115. const_cast<WCHAR *>(pwszInfValue));
  4116. _JumpIfError(hr, error, "AddNameValuePairToSignatureWStr");
  4117. }
  4118. else
  4119. if (0 == lstrcmpi(wszINFKEY_REQUESTTYPE, pInfValues->pwszKey))
  4120. {
  4121. if (0 == lstrcmpi(wszINFVALUE_REQUESTTYPE_PKCS101, pwszInfValue))
  4122. {
  4123. RequestTypeFlags = XECR_PKCS10_V1_5;
  4124. }
  4125. else
  4126. if (0 == lstrcmpi(wszINFVALUE_REQUESTTYPE_PKCS10, pwszInfValue))
  4127. {
  4128. RequestTypeFlags = XECR_PKCS10_V2_0;
  4129. }
  4130. else
  4131. if (0 == lstrcmpi(wszINFVALUE_REQUESTTYPE_PKCS7, pwszInfValue))
  4132. {
  4133. RequestTypeFlags = XECR_PKCS7;
  4134. }
  4135. else
  4136. if (0 == lstrcmpi(wszINFVALUE_REQUESTTYPE_CMC, pwszInfValue))
  4137. {
  4138. RequestTypeFlags = XECR_CMC;
  4139. }
  4140. else
  4141. {
  4142. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  4143. SetErrorStringInf(pwszfnPolicy, pInfValues);
  4144. _JumpErrorStr(hr, error, "Bad RequestType value", pwszInfValue);
  4145. }
  4146. fReqestTypeSet = TRUE;
  4147. }
  4148. else
  4149. {
  4150. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  4151. SetErrorStringInf(pwszfnPolicy, pInfValues);
  4152. _JumpErrorStr(hr, error, "bad Inf key", pInfValues->pwszKey);
  4153. }
  4154. }
  4155. if (NULL != g_pwszCertCN)
  4156. {
  4157. if (!g_fQuiet || NULL != g_pwszCertCN)
  4158. {
  4159. hr = myGetCertificateFromPicker(
  4160. g_hInstance,
  4161. NULL, // hwndParent
  4162. IDS_GETSIGNINGCERT_TITLE,
  4163. IDS_GETSIGNINGCERT_SUBTITLE,
  4164. CUCS_MYSTORE |
  4165. CUCS_PRIVATEKEYREQUIRED |
  4166. (g_fQuiet? CUCS_SILENT : 0),
  4167. (L'\0' == g_pwszCertCN || 0 == lstrcmp(L"*", g_pwszCertCN))?
  4168. NULL : g_pwszCertCN, // pwszCommonName
  4169. 0, // cStore
  4170. NULL, // rghStore
  4171. 0, // cpszObjId
  4172. NULL, // apszObjId
  4173. &pccSigner);
  4174. _JumpIfError(hr, error, "myGetCertificateFromPicker");
  4175. }
  4176. // pccSigner is NULL if the user cancelled out of the cert picker U/I.
  4177. if (NULL == pccSigner)
  4178. {
  4179. if (g_fQuiet || NULL != g_pwszCertCN)
  4180. {
  4181. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  4182. _JumpError(hr, error, "no matching signer CN");
  4183. }
  4184. }
  4185. hr = pEnroll->SetSignerCertificate(pccSigner);
  4186. _JumpIfError(hr, error, "SetSignerCertificate");
  4187. }
  4188. if (NULL != pccXchg)
  4189. {
  4190. LONG lGenKeyFlags;
  4191. hr = pEnroll->SetPrivateKeyArchiveCertificate(pccXchg);
  4192. _JumpIfError(hr, error, "SetPrivateKeyArchiveCertificate");
  4193. hr = pEnroll->get_GenKeyFlags(&lGenKeyFlags);
  4194. _JumpIfError(hr, error, "getGenKeyFlags");
  4195. if (0 == (CRYPT_EXPORTABLE & lGenKeyFlags))
  4196. {
  4197. hr = pEnroll->put_GenKeyFlags(CRYPT_EXPORTABLE | lGenKeyFlags);
  4198. _JumpIfError(hr, error, "putGenKeyFlags");
  4199. }
  4200. }
  4201. if (NULL != pccRenewal)
  4202. {
  4203. hr = pEnroll->put_RenewalCertificate(pccRenewal);
  4204. _JumpIfError(hr, error, "put_RenewalCertificate");
  4205. }
  4206. if (!fReqestTypeSet)
  4207. {
  4208. RequestTypeFlags = XECR_PKCS10_V2_0;
  4209. if (NULL != pccXchg)
  4210. {
  4211. RequestTypeFlags = XECR_CMC;
  4212. }
  4213. else if (NULL != pccRenewal)
  4214. {
  4215. RequestTypeFlags = XECR_PKCS7;
  4216. }
  4217. }
  4218. hr = pEnroll->createRequestWStr(
  4219. RequestTypeFlags,
  4220. pwszDN,
  4221. NULL,
  4222. &blobRequest);
  4223. _JumpIfError(hr, error, "createRequestWStr");
  4224. myRegisterMemAlloc(blobRequest.pbData, blobRequest.cbData, CSM_LOCALALLOC);
  4225. hr = WriteCertificateOrRequest(
  4226. hWndOwner,
  4227. NULL, // pdiRequest
  4228. blobRequest.pbData,
  4229. blobRequest.cbData,
  4230. g_dwOutFormat,
  4231. pwszfnOut);
  4232. _JumpIfError(hr, error, "WriteCertificateOrRequest");
  4233. error:
  4234. if (NULL != pwszDN)
  4235. {
  4236. LocalFree(pwszDN);
  4237. }
  4238. if (NULL != NameBlob.pbData)
  4239. {
  4240. LocalFree(NameBlob.pbData);
  4241. }
  4242. if (NULL != pccXchg)
  4243. {
  4244. CertFreeCertificateContext(pccXchg);
  4245. }
  4246. if (NULL != pccRenewal)
  4247. {
  4248. CertFreeCertificateContext(pccRenewal);
  4249. }
  4250. if (NULL != pccSigner)
  4251. {
  4252. CertFreeCertificateContext(pccSigner);
  4253. }
  4254. if (NULL != rgInfValues)
  4255. {
  4256. myInfFreeSectionValues(cInfValues, rgInfValues);
  4257. }
  4258. if (NULL != rgAttributes)
  4259. {
  4260. FreeAttributes(cAttributes, rgAttributes);
  4261. }
  4262. if (NULL != rgExt)
  4263. {
  4264. FreeExtensions(TRUE, cExt, rgExt);
  4265. }
  4266. if (NULL != pwszObjId)
  4267. {
  4268. LocalFree(pwszObjId);
  4269. }
  4270. if (NULL != blobRequest.pbData)
  4271. {
  4272. LocalFree(blobRequest.pbData);
  4273. }
  4274. if (NULL != pEnroll)
  4275. {
  4276. pEnroll->Release();
  4277. }
  4278. if (fCoInit)
  4279. {
  4280. CoUninitialize();
  4281. }
  4282. return(hr);
  4283. }
  4284. HRESULT
  4285. MakePKCS7FromCert(
  4286. IN BYTE const *pbCert,
  4287. IN DWORD cbCert,
  4288. OUT BYTE **ppbChain,
  4289. OUT DWORD *pcbChain)
  4290. {
  4291. HRESULT hr;
  4292. CERT_CONTEXT const *pcc = NULL;
  4293. CRYPT_SIGN_MESSAGE_PARA csmp;
  4294. CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm = { szOID_OIWSEC_sha1, 0, 0 };
  4295. *ppbChain = NULL;
  4296. pcc = CertCreateCertificateContext(X509_ASN_ENCODING, pbCert, cbCert);
  4297. if (NULL == pcc)
  4298. {
  4299. hr = myHLastError();
  4300. _JumpError(hr, error, "CertCreateCertificateContext");
  4301. }
  4302. // init csmp for empty signature
  4303. ZeroMemory(&csmp, sizeof(csmp));
  4304. csmp.cbSize = sizeof(csmp);
  4305. csmp.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
  4306. //csmp.pSigningCert = NULL;
  4307. csmp.HashAlgorithm = DigestAlgorithm;
  4308. csmp.cMsgCert = 1;
  4309. csmp.rgpMsgCert = &pcc;
  4310. //csmp.cMsgCrl = 0;
  4311. //csmp.rgpMsgCrl = NULL;
  4312. if (!myCryptSignMessage(
  4313. &csmp,
  4314. pbCert, // pbToBeSigned
  4315. cbCert, // cbToBeSigned
  4316. CERTLIB_USE_LOCALALLOC,
  4317. ppbChain,
  4318. pcbChain))
  4319. {
  4320. hr = myHLastError();
  4321. _JumpError(hr, error, "myCryptSignMessage");
  4322. }
  4323. hr = S_OK;
  4324. error:
  4325. if (NULL != pcc)
  4326. {
  4327. CertFreeCertificateContext(pcc);
  4328. }
  4329. return(hr);
  4330. }
  4331. HRESULT
  4332. AcceptResponse(
  4333. IN HWND hWndOwner,
  4334. IN WCHAR const *pwszfnIn)
  4335. {
  4336. HRESULT hr;
  4337. WCHAR *pwszMsg = NULL;
  4338. WCHAR awchr[cwcHRESULTSTRING];
  4339. CRYPT_DATA_BLOB blobIn;
  4340. CRYPT_DATA_BLOB blobCert7;
  4341. char *pszInnerContentObjId = NULL;
  4342. DWORD dwType;
  4343. DWORD dwMsgType;
  4344. BYTE *pbDecoded;
  4345. DWORD cb;
  4346. BOOL fCoInit = FALSE;
  4347. IEnroll4 *pEnroll = NULL;
  4348. blobIn.pbData = NULL;
  4349. blobCert7.pbData = NULL;
  4350. hr = DecodeFileW(
  4351. pwszfnIn,
  4352. &blobIn.pbData,
  4353. &blobIn.cbData,
  4354. CRYPT_STRING_BASE64_ANY);
  4355. if (S_OK != hr)
  4356. {
  4357. if (S_OK == myLoadRCString(
  4358. g_hInstance,
  4359. IDS_FORMATSTR_DECODE_ERR,
  4360. &pwszMsg))
  4361. {
  4362. CSASSERT(NULL != pwszMsg);
  4363. wprintf(pwszMsg, myHResultToString(awchr, hr));
  4364. wprintf(g_wszNewLine);
  4365. }
  4366. goto error;
  4367. }
  4368. dwType = CR_IN_CERT;
  4369. if (!myDecodeObject(
  4370. X509_ASN_ENCODING,
  4371. X509_CERT_TO_BE_SIGNED,
  4372. blobIn.pbData,
  4373. blobIn.cbData,
  4374. CERTLIB_USE_LOCALALLOC,
  4375. (VOID **) &pbDecoded,
  4376. &cb))
  4377. {
  4378. //_PrintError(myHLastError(), "myDecodeObject(Cert)");
  4379. CSASSERT(NULL == pbDecoded);
  4380. dwType = CR_IN_PKCS7; // PKCS 7 renewal request?
  4381. hr = myDecodePKCS7(
  4382. blobIn.pbData,
  4383. blobIn.cbData,
  4384. NULL, // ppbContents
  4385. NULL, // pcbContents
  4386. NULL, // pdwMsgType
  4387. &pszInnerContentObjId,
  4388. NULL, // pcSigner
  4389. NULL, // pcRecipient
  4390. NULL, // phStore
  4391. NULL); // phMsg
  4392. _JumpIfError(hr, error, "myDecodePKCS7");
  4393. if (NULL != pszInnerContentObjId &&
  4394. 0 == strcmp(pszInnerContentObjId, szOID_CT_PKI_RESPONSE))
  4395. {
  4396. dwType = CR_IN_CMC;
  4397. }
  4398. }
  4399. if (CR_IN_CERT == dwType)
  4400. {
  4401. hr = MakePKCS7FromCert(
  4402. blobIn.pbData,
  4403. blobIn.cbData,
  4404. &blobCert7.pbData,
  4405. &blobCert7.cbData);
  4406. _JumpIfError(hr, error, "MakePKCS7FromCert");
  4407. }
  4408. hr = CoInitialize(NULL);
  4409. if (S_OK != hr && S_FALSE != hr)
  4410. {
  4411. _JumpError(hr, error, "CoInitialize");
  4412. }
  4413. fCoInit = TRUE;
  4414. hr = CoCreateInstance(
  4415. CLSID_CEnroll,
  4416. NULL, // pUnkOuter
  4417. CLSCTX_INPROC_SERVER,
  4418. IID_IEnroll4,
  4419. (VOID **) &pEnroll);
  4420. _JumpIfError(hr, error, "CoCreateInstance");
  4421. if (CR_IN_CMC == dwType)
  4422. {
  4423. hr = pEnroll->acceptResponseBlob(&blobIn);
  4424. _JumpIfError(hr, error, "acceptResponseBlob");
  4425. }
  4426. else
  4427. {
  4428. hr = pEnroll->acceptPKCS7Blob(
  4429. NULL != blobCert7.pbData? &blobCert7 : &blobIn);
  4430. _JumpIfError(hr, error, "acceptPKCS7Blob");
  4431. }
  4432. error:
  4433. if (NULL != pwszMsg)
  4434. {
  4435. LocalFree(pwszMsg);
  4436. }
  4437. if (NULL != blobIn.pbData)
  4438. {
  4439. LocalFree(blobIn.pbData);
  4440. }
  4441. if (NULL != blobCert7.pbData)
  4442. {
  4443. LocalFree(blobCert7.pbData);
  4444. }
  4445. if (NULL != pszInnerContentObjId)
  4446. {
  4447. LocalFree(pszInnerContentObjId);
  4448. }
  4449. if (NULL != pEnroll)
  4450. {
  4451. pEnroll->Release();
  4452. }
  4453. if (fCoInit)
  4454. {
  4455. CoUninitialize();
  4456. }
  4457. return(hr);
  4458. }
  4459. HRESULT
  4460. ArgvMain(
  4461. int argc,
  4462. WCHAR *argv[],
  4463. HWND hWndOwner)
  4464. {
  4465. HRESULT hr;
  4466. WCHAR *pwszOFN = NULL;
  4467. WCHAR *pwszOFN2 = NULL;
  4468. WCHAR const *pwszfnIn;
  4469. WCHAR const *pwszfnOut;
  4470. WCHAR const *pwszfnPKCS10;
  4471. WCHAR const *pwszfnCertChain;
  4472. WCHAR const *pwszfnFullResponse;
  4473. WCHAR const *pwszfnPolicy;
  4474. LONG RequestId;
  4475. WCHAR *pwszAttributes = NULL;
  4476. WCHAR const *pwszSerialNumber = NULL;
  4477. DWORD cCommand = 0;
  4478. int cArgMax = 0;
  4479. WCHAR *rgpwszArg[4];
  4480. UINT idsFileFilter;
  4481. UINT idsFileDefExt;
  4482. myVerifyResourceStrings(g_hInstance);
  4483. while (1 < argc && (L'-' == argv[1][0] || L'/' == argv[1][0]))
  4484. {
  4485. if (0 == lstrcmpi(&argv[1][1], L"config"))
  4486. {
  4487. if (2 >= argc)
  4488. {
  4489. _PrintError(E_INVALIDARG, "missing -config arg");
  4490. Usage(TRUE);
  4491. }
  4492. if (0 == wcscmp(argv[2], L"-") || 0 == wcscmp(argv[2], L"*"))
  4493. {
  4494. g_dwUIFlag = CC_LOCALACTIVECONFIG;
  4495. }
  4496. else
  4497. {
  4498. g_pwszConfig = argv[2];
  4499. }
  4500. argc--;
  4501. argv++;
  4502. }
  4503. else
  4504. if (0 == lstrcmpi(&argv[1][1], L"any"))
  4505. {
  4506. g_fAny = TRUE;
  4507. }
  4508. else
  4509. if (0 == lstrcmpi(&argv[1][1], L"crl"))
  4510. {
  4511. g_dwCRLIn = CR_IN_CRLS;
  4512. g_dwCRLOut = CR_OUT_CRLS;
  4513. }
  4514. else
  4515. if (0 == lstrcmpi(&argv[1][1], L"rpc"))
  4516. {
  4517. g_fRPC++;
  4518. if (0 == lstrcmp(&argv[1][1], L"RPC"))
  4519. {
  4520. g_fRPC++;
  4521. }
  4522. }
  4523. else
  4524. if (0 == lstrcmpi(&argv[1][1], L"binary"))
  4525. {
  4526. g_dwOutFormat = CR_OUT_BINARY;
  4527. }
  4528. else
  4529. if (0 == lstrcmpi(&argv[1][1], L"idispatch"))
  4530. {
  4531. g_fIDispatch = TRUE;
  4532. }
  4533. else
  4534. if (0 == lstrcmpi(&argv[1][1], L"submit"))
  4535. {
  4536. g_dwCommand = cmdSUBMITREQUEST;
  4537. cArgMax = 4;
  4538. cCommand++;
  4539. }
  4540. else
  4541. if (0 == lstrcmpi(&argv[1][1], L"retrieve"))
  4542. {
  4543. g_dwCommand = cmdRETRIEVEPENDING;
  4544. cArgMax = 4;
  4545. cCommand++;
  4546. }
  4547. else
  4548. if (0 == lstrcmpi(&argv[1][1], L"policy"))
  4549. {
  4550. g_dwCommand = cmdQUALIFIEDREQUEST;
  4551. cArgMax = 4;
  4552. cCommand++;
  4553. }
  4554. else
  4555. if (0 == lstrcmpi(&argv[1][1], L"new"))
  4556. {
  4557. g_dwCommand = cmdNEWREQUEST;
  4558. cArgMax = 2;
  4559. cCommand++;
  4560. }
  4561. else
  4562. if (0 == lstrcmpi(&argv[1][1], L"accept"))
  4563. {
  4564. g_dwCommand = cmdACCEPTRESPONSE;
  4565. cArgMax = 1;
  4566. cCommand++;
  4567. }
  4568. else
  4569. if (0 == lstrcmpi(&argv[1][1], L"sign"))
  4570. {
  4571. g_dwCommand = cmdSIGNREQUEST;
  4572. cArgMax = 2;
  4573. cCommand++;
  4574. }
  4575. else
  4576. if (0 == lstrcmpi(&argv[1][1], L"v1"))
  4577. {
  4578. g_fV1Interface = TRUE;
  4579. }
  4580. else
  4581. if (0 == lstrcmpi(&argv[1][1], L"v"))
  4582. {
  4583. g_fVerbose = TRUE;
  4584. }
  4585. else
  4586. if (0 == lstrcmpi(&argv[1][1], L"f"))
  4587. {
  4588. g_fForce++;
  4589. }
  4590. else
  4591. if (0 == lstrcmpi(&argv[1][1], L"q"))
  4592. {
  4593. g_fQuiet = TRUE;
  4594. g_dwUIFlag = CC_LOCALACTIVECONFIG;
  4595. }
  4596. else
  4597. if (0 == lstrcmpi(&argv[1][1], L"?") ||
  4598. 0 == lstrcmpi(&argv[1][1], L"usage"))
  4599. {
  4600. g_fFullUsage = 0 == lstrcmp(&argv[1][1], L"uSAGE");
  4601. Usage(FALSE);
  4602. }
  4603. else
  4604. if (0 == lstrcmpi(&argv[1][1], L"attrib"))
  4605. {
  4606. if (2 >= argc)
  4607. {
  4608. _PrintError(E_INVALIDARG, "missing -attrib arg");
  4609. Usage(TRUE);
  4610. }
  4611. hr = crCombineAttributes(argv[2], &pwszAttributes);
  4612. _JumpIfError(hr, error, "crCombineAttributes");
  4613. argc--;
  4614. argv++;
  4615. }
  4616. else
  4617. if (0 == lstrcmpi(&argv[1][1], L"cert"))
  4618. {
  4619. if (2 >= argc)
  4620. {
  4621. _PrintError(E_INVALIDARG, "missing -cert arg");
  4622. Usage(TRUE);
  4623. }
  4624. g_pwszCertCN = argv[2];
  4625. argc--;
  4626. argv++;
  4627. }
  4628. else
  4629. {
  4630. _PrintError(E_INVALIDARG, "Unknown arg");
  4631. Usage(TRUE);
  4632. }
  4633. argc--;
  4634. argv++;
  4635. }
  4636. if (1 < cCommand)
  4637. {
  4638. _PrintError(E_INVALIDARG, "multiple commands");
  4639. Usage(TRUE);
  4640. }
  4641. if (cmdNONE == g_dwCommand)
  4642. {
  4643. g_dwCommand = cmdSUBMITREQUEST;
  4644. cArgMax = 4;
  4645. }
  4646. if (NULL != pwszAttributes &&
  4647. (cmdRETRIEVEPENDING == g_dwCommand &&
  4648. cmdSUBMITREQUEST == g_dwCommand))
  4649. {
  4650. _PrintError(E_INVALIDARG, "unexpected -attrib arg");
  4651. Usage(TRUE);
  4652. }
  4653. if (NULL != g_pwszCertCN &&
  4654. cmdSIGNREQUEST != g_dwCommand &&
  4655. cmdQUALIFIEDREQUEST != g_dwCommand &&
  4656. cmdNEWREQUEST != g_dwCommand)
  4657. {
  4658. _PrintError(E_INVALIDARG, "unexpected -cert arg");
  4659. Usage(TRUE);
  4660. }
  4661. if (1 + cArgMax < argc)
  4662. {
  4663. _PrintError(E_INVALIDARG, "Extra args");
  4664. Usage(TRUE);
  4665. }
  4666. CSASSERT(ARRAYSIZE(rgpwszArg) >= cArgMax);
  4667. ZeroMemory(rgpwszArg, sizeof(rgpwszArg));
  4668. if (1 < argc)
  4669. {
  4670. rgpwszArg[0] = argv[1];
  4671. if (2 < argc)
  4672. {
  4673. rgpwszArg[1] = argv[2];
  4674. if (3 < argc)
  4675. {
  4676. rgpwszArg[2] = argv[3];
  4677. if (4 < argc)
  4678. {
  4679. rgpwszArg[3] = argv[4];
  4680. }
  4681. }
  4682. }
  4683. }
  4684. // cmdSUBMITREQUEST:
  4685. // [RequestFile [CertFile [CertChainFile [FullResponseFile]]]]
  4686. //
  4687. // cmdRETRIEVEPENDING:
  4688. // [RequestId [CertFile [CertChainFile [FullResponseFile]]]]
  4689. //
  4690. // cmdNEWREQUEST
  4691. // [PolicyFile [RequestFileOut]]
  4692. //
  4693. // cmdACCEPTRESPONSE
  4694. // [CertFile | CertChainFile | FullResponseFile]
  4695. //
  4696. // cmdQUALIFIEDREQUEST (accept RequestFile and PolicyFile in either order)
  4697. // [RequestFile [PolicyFile [RequestFileOut [PKCS10FileOut]]]
  4698. //
  4699. // cmdSIGNREQUEST:
  4700. // [RequestFile [RequestFileOut]]
  4701. //
  4702. pwszfnIn = NULL;
  4703. pwszfnOut = NULL;
  4704. pwszfnPKCS10 = NULL;
  4705. pwszfnCertChain = NULL;
  4706. pwszfnFullResponse = NULL;
  4707. pwszfnPolicy = NULL;
  4708. pwszfnIn = rgpwszArg[0];
  4709. idsFileFilter = IDS_REQUEST_FILE_FILTER;
  4710. idsFileDefExt = IDS_REQUEST_FILE_DEFEXT;
  4711. switch (g_dwCommand)
  4712. {
  4713. case cmdRETRIEVEPENDING:
  4714. idsFileFilter = 0; // disable file open dialog
  4715. // FALLTHROUGH
  4716. case cmdSUBMITREQUEST:
  4717. pwszfnOut = rgpwszArg[1];
  4718. pwszfnCertChain = rgpwszArg[2];
  4719. pwszfnFullResponse = rgpwszArg[3];
  4720. break;
  4721. case cmdNEWREQUEST:
  4722. pwszfnIn = NULL;
  4723. pwszfnPolicy = rgpwszArg[0];
  4724. pwszfnOut = rgpwszArg[1];
  4725. CSASSERT(NULL == rgpwszArg[2]);
  4726. idsFileFilter = 0; // disable file open dialog
  4727. break;
  4728. case cmdACCEPTRESPONSE:
  4729. CSASSERT(NULL == rgpwszArg[1]);
  4730. idsFileFilter = IDS_RESPONSE_FILE_FILTER;
  4731. idsFileDefExt = IDS_RESPONSE_FILE_DEFEXT;
  4732. break;
  4733. case cmdQUALIFIEDREQUEST:
  4734. pwszfnPolicy = rgpwszArg[1];
  4735. pwszfnOut = rgpwszArg[2];
  4736. pwszfnPKCS10 = rgpwszArg[3];
  4737. idsFileFilter = IDS_REQUEST_OR_CERT_FILE_FILTER;
  4738. break;
  4739. default:
  4740. CSASSERT(cmdSIGNREQUEST == g_dwCommand);
  4741. pwszfnOut = rgpwszArg[1];
  4742. CSASSERT(NULL == rgpwszArg[2]);
  4743. CSASSERT(NULL == rgpwszArg[3]);
  4744. break;
  4745. }
  4746. if (cmdRETRIEVEPENDING == g_dwCommand)
  4747. {
  4748. if (NULL == pwszfnIn)
  4749. {
  4750. WCHAR *pwszMsg = NULL;
  4751. hr = myLoadRCString(
  4752. g_hInstance,
  4753. IDS_ERROR_NO_REQUESTID,
  4754. &pwszMsg);
  4755. if (S_OK == hr)
  4756. {
  4757. CSASSERT(NULL != pwszMsg);
  4758. wprintf(pwszMsg);
  4759. wprintf(g_wszNewLine);
  4760. LocalFree(pwszMsg);
  4761. }
  4762. _PrintError(E_INVALIDARG, "missing RequestId");
  4763. Usage(TRUE);
  4764. }
  4765. hr = GetLong(pwszfnIn, &RequestId);
  4766. if (S_OK != hr || 0 == RequestId)
  4767. {
  4768. RequestId = 0;
  4769. pwszSerialNumber = pwszfnIn;
  4770. }
  4771. pwszfnIn = NULL;
  4772. }
  4773. else
  4774. if (NULL != pwszfnIn && cmdQUALIFIEDREQUEST == g_dwCommand)
  4775. {
  4776. BYTE *pbReq;
  4777. DWORD cbReq;
  4778. LONG dwFlags;
  4779. BOOL fSigned;
  4780. // accept RequestFile and PolicyFile in either order:
  4781. hr = CheckRequestType(pwszfnIn, &pbReq, &cbReq, &dwFlags, &fSigned);
  4782. if (S_OK != hr)
  4783. {
  4784. WCHAR const *pwsz = pwszfnPolicy;
  4785. pwszfnPolicy = pwszfnIn;
  4786. pwszfnIn = pwsz;
  4787. }
  4788. else
  4789. {
  4790. LocalFree(pbReq);
  4791. }
  4792. }
  4793. if (NULL == pwszfnIn && 0 != idsFileFilter)
  4794. {
  4795. // Put up a file open dialog to get Response, Request or cert file
  4796. hr = crGetOpenFileName(
  4797. hWndOwner,
  4798. IDS_REQUEST_OPEN_TITLE,
  4799. idsFileFilter,
  4800. idsFileDefExt,
  4801. &pwszOFN);
  4802. _JumpIfError(hr, error, "crGetOpenFileName");
  4803. pwszfnIn = pwszOFN;
  4804. }
  4805. if (NULL != pwszfnIn)
  4806. {
  4807. if (!myDoesFileExist(pwszfnIn))
  4808. {
  4809. SetErrorString(pwszfnIn);
  4810. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  4811. _JumpErrorStr(hr, error, "myDoesFileExist", pwszfnIn);
  4812. }
  4813. }
  4814. if (NULL != pwszfnOut)
  4815. {
  4816. hr = myIsDirWriteable(pwszfnOut, TRUE);
  4817. if (S_OK != hr)
  4818. {
  4819. SetErrorString(pwszfnOut);
  4820. _JumpErrorStr(hr, error, "IsDirWriteable", pwszfnOut);
  4821. }
  4822. }
  4823. switch (g_dwCommand)
  4824. {
  4825. case cmdRETRIEVEPENDING:
  4826. case cmdSUBMITREQUEST:
  4827. if (CV_OUT_BASE64REQUESTHEADER == g_dwOutFormat)
  4828. {
  4829. g_dwOutFormat = CV_OUT_BASE64HEADER;
  4830. }
  4831. if (NULL != pwszfnCertChain)
  4832. {
  4833. hr = myIsDirWriteable(pwszfnCertChain, TRUE);
  4834. if (S_OK != hr)
  4835. {
  4836. SetErrorString(pwszfnCertChain);
  4837. _JumpErrorStr(hr, error, "IsDirWriteable", pwszfnCertChain);
  4838. }
  4839. }
  4840. if (NULL != pwszfnFullResponse)
  4841. {
  4842. hr = myIsDirWriteable(pwszfnFullResponse, TRUE);
  4843. if (S_OK != hr)
  4844. {
  4845. SetErrorString(pwszfnFullResponse);
  4846. _JumpErrorStr(hr, error, "IsDirWriteable", pwszfnFullResponse);
  4847. }
  4848. }
  4849. hr = SubmitRequest(
  4850. hWndOwner,
  4851. RequestId,
  4852. pwszSerialNumber,
  4853. pwszAttributes,
  4854. pwszfnIn,
  4855. pwszfnOut,
  4856. pwszfnCertChain,
  4857. pwszfnFullResponse);
  4858. _JumpIfError(hr, error, "SubmitRequest");
  4859. break;
  4860. case cmdACCEPTRESPONSE:
  4861. hr = AcceptResponse(hWndOwner, pwszfnIn);
  4862. _JumpIfError(hr, error, "AcceptResponse");
  4863. break;
  4864. case cmdNEWREQUEST:
  4865. case cmdQUALIFIEDREQUEST:
  4866. if (NULL != pwszfnPKCS10)
  4867. {
  4868. hr = myIsDirWriteable(pwszfnPKCS10, TRUE);
  4869. if (S_OK != hr)
  4870. {
  4871. SetErrorString(pwszfnPKCS10);
  4872. _JumpErrorStr(hr, error, "IsDirWriteable", pwszfnPKCS10);
  4873. }
  4874. }
  4875. if (NULL == pwszfnPolicy)
  4876. {
  4877. // Put up a file dialog to prompt the user for Inf File
  4878. hr = crGetOpenFileName(
  4879. hWndOwner,
  4880. IDS_INF_OPEN_TITLE,
  4881. IDS_INF_FILE_FILTER,
  4882. IDS_INF_FILE_DEFEXT,
  4883. &pwszOFN2);
  4884. _JumpIfError(hr, error, "crGetOpenFileName");
  4885. pwszfnPolicy = pwszOFN2;
  4886. }
  4887. CSASSERT(NULL != pwszfnPolicy);
  4888. if (!myDoesFileExist(pwszfnPolicy))
  4889. {
  4890. SetErrorString(pwszfnPolicy);
  4891. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  4892. _JumpErrorStr(hr, error, "myDoesFileExist", pwszfnPolicy);
  4893. }
  4894. if (cmdNEWREQUEST == g_dwCommand)
  4895. {
  4896. hr = CreateNewRequest(
  4897. hWndOwner,
  4898. pwszAttributes,
  4899. pwszfnPolicy,
  4900. pwszfnOut);
  4901. _JumpIfError(hr, error, "CreateNewRequest");
  4902. }
  4903. else
  4904. {
  4905. hr = CreateQualifiedRequest(
  4906. hWndOwner,
  4907. pwszAttributes,
  4908. pwszfnIn,
  4909. pwszfnPolicy,
  4910. pwszfnOut,
  4911. pwszfnPKCS10);
  4912. _JumpIfError(hr, error, "CreateQualifiedRequest");
  4913. }
  4914. break;
  4915. default:
  4916. CSASSERT(cmdSIGNREQUEST == g_dwCommand);
  4917. if (NULL != pwszfnFullResponse)
  4918. {
  4919. Usage(TRUE);
  4920. }
  4921. hr = SignQualifiedRequest(hWndOwner, pwszfnIn, pwszfnOut);
  4922. _JumpIfError(hr, error, "SignQualifiedRequest");
  4923. break;
  4924. }
  4925. error:
  4926. if (NULL != pwszAttributes)
  4927. {
  4928. LocalFree(pwszAttributes);
  4929. }
  4930. if (NULL != pwszOFN)
  4931. {
  4932. LocalFree(pwszOFN);
  4933. }
  4934. if (NULL != pwszOFN2)
  4935. {
  4936. LocalFree(pwszOFN2);
  4937. }
  4938. return(hr);
  4939. }
  4940. //**************************************************************************
  4941. // FUNCTION: CertReqPreMain
  4942. // NOTES: Based on vich's MkRootMain function; takes an LPSTR command
  4943. // line and chews it up into argc/argv form so that it can be
  4944. // passed on to a traditional C style main.
  4945. //**************************************************************************
  4946. #define ISBLANK(wc) (L' ' == (wc) || L'\t' == (wc))
  4947. HRESULT
  4948. CertReqPreMain(
  4949. LPTSTR pszCmdLine,
  4950. HWND hWndOwner)
  4951. {
  4952. WCHAR *pbuf;
  4953. LPTSTR apszArg[20];
  4954. int cArg = 0;
  4955. LPTSTR p;
  4956. WCHAR *pchQuote;
  4957. HRESULT hr;
  4958. pbuf = (WCHAR *) LocalAlloc(
  4959. LMEM_FIXED,
  4960. (wcslen(pszCmdLine) + 1) * sizeof(WCHAR));
  4961. if (NULL == pbuf)
  4962. {
  4963. hr = E_OUTOFMEMORY;
  4964. _JumpError(hr, error, "LocalAlloc");
  4965. }
  4966. p = pbuf;
  4967. apszArg[cArg++] = TEXT("CertReq");
  4968. while (*pszCmdLine != TEXT('\0'))
  4969. {
  4970. while (ISBLANK(*pszCmdLine))
  4971. {
  4972. pszCmdLine++;
  4973. }
  4974. if (*pszCmdLine != TEXT('\0'))
  4975. {
  4976. apszArg[cArg++] = p;
  4977. if (sizeof(apszArg)/sizeof(apszArg[0]) <= cArg)
  4978. {
  4979. hr = E_INVALIDARG;
  4980. _JumpIfError(hr, error, "Too many args");
  4981. }
  4982. pchQuote = NULL;
  4983. while (*pszCmdLine != L'\0')
  4984. {
  4985. if (NULL != pchQuote)
  4986. {
  4987. if (*pszCmdLine == *pchQuote)
  4988. {
  4989. pszCmdLine++;
  4990. pchQuote = NULL;
  4991. continue;
  4992. }
  4993. }
  4994. else
  4995. {
  4996. if (ISBLANK(*pszCmdLine))
  4997. {
  4998. break;
  4999. }
  5000. if (L'"' == *pszCmdLine)
  5001. {
  5002. pchQuote = pszCmdLine++;
  5003. continue;
  5004. }
  5005. }
  5006. *p++ = *pszCmdLine++;
  5007. }
  5008. *p++ = TEXT('\0');
  5009. if (*pszCmdLine != TEXT('\0'))
  5010. {
  5011. pszCmdLine++; // skip whitespace or quote character
  5012. }
  5013. }
  5014. }
  5015. apszArg[cArg] = NULL;
  5016. hr = ArgvMain(cArg, apszArg, hWndOwner);
  5017. _JumpIfError(hr, error, "ArgvMain");
  5018. error:
  5019. if (NULL != pbuf)
  5020. {
  5021. LocalFree(pbuf);
  5022. }
  5023. return(hr);
  5024. }
  5025. VOID
  5026. CertReqErrorDisplay(
  5027. IN HRESULT hr,
  5028. IN HWND hWnd)
  5029. {
  5030. WCHAR *pwszTitle = NULL;
  5031. WCHAR *pwszMessage = NULL;
  5032. WCHAR const *pwszError = NULL;
  5033. WCHAR *pwszInfError = NULL;
  5034. WCHAR *pwszCombinedError = NULL;
  5035. WCHAR const *pwsz;
  5036. myLoadRCString(g_hInstance, IDS_CERTREQ_TITLE, &pwszTitle);
  5037. if (g_idError)
  5038. {
  5039. myLoadRCString(g_hInstance, g_idError, &pwszMessage);
  5040. }
  5041. pwszError = myGetErrorMessageText(hr, TRUE);
  5042. // Eliminate redundant error message text. If the client and server
  5043. // localized error message text differ, both will still be displayed.
  5044. if (NULL != pwszError && NULL != g_pwszErrorString)
  5045. {
  5046. if (NULL != wcsstr(g_pwszErrorString, pwszError))
  5047. {
  5048. LocalFree(const_cast<WCHAR *>(pwszError));
  5049. pwszError = NULL;
  5050. }
  5051. }
  5052. pwszInfError = myInfGetError();
  5053. pwsz = NULL;
  5054. if (NULL != pwszMessage ||
  5055. NULL != pwszError ||
  5056. NULL != g_pwszErrorString ||
  5057. NULL != pwszInfError)
  5058. {
  5059. DWORD cwc = 1;
  5060. if (NULL != pwszMessage)
  5061. {
  5062. cwc += wcslen(pwszMessage) + 1;
  5063. }
  5064. if (NULL != pwszError)
  5065. {
  5066. cwc += wcslen(pwszError) + 1;
  5067. }
  5068. if (NULL != g_pwszErrorString)
  5069. {
  5070. cwc += wcslen(g_pwszErrorString) + 1;
  5071. }
  5072. if (NULL != pwszInfError)
  5073. {
  5074. cwc += wcslen(pwszInfError) + 1;
  5075. }
  5076. pwszCombinedError = (WCHAR *) LocalAlloc(
  5077. LMEM_FIXED,
  5078. cwc * sizeof(WCHAR));
  5079. if (NULL != pwszCombinedError)
  5080. {
  5081. *pwszCombinedError = L'\0';
  5082. if (NULL != pwszMessage)
  5083. {
  5084. wcscat(pwszCombinedError, pwszMessage);
  5085. }
  5086. if (NULL != pwszError)
  5087. {
  5088. if (L'\0' != *pwszCombinedError)
  5089. {
  5090. wcscat(pwszCombinedError, g_wszNewLine);
  5091. }
  5092. wcscat(pwszCombinedError, pwszError);
  5093. }
  5094. if (NULL != g_pwszErrorString)
  5095. {
  5096. if (L'\0' != *pwszCombinedError)
  5097. {
  5098. wcscat(pwszCombinedError, g_wszNewLine);
  5099. }
  5100. wcscat(pwszCombinedError, g_pwszErrorString);
  5101. }
  5102. if (NULL != pwszInfError)
  5103. {
  5104. if (L'\0' != *pwszCombinedError)
  5105. {
  5106. wcscat(pwszCombinedError, g_wszNewLine);
  5107. }
  5108. wcscat(pwszCombinedError, pwszInfError);
  5109. }
  5110. pwsz = pwszCombinedError;
  5111. }
  5112. }
  5113. if (NULL == pwsz)
  5114. {
  5115. pwsz = pwszError;
  5116. if (NULL == pwsz)
  5117. {
  5118. pwsz = g_pwszErrorString;
  5119. if (NULL == pwsz)
  5120. {
  5121. pwsz = L"";
  5122. }
  5123. }
  5124. }
  5125. if (!g_fQuiet)
  5126. {
  5127. MessageBox(
  5128. hWnd,
  5129. pwsz,
  5130. pwszTitle,
  5131. MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
  5132. }
  5133. wprintf(L"%ws: %ws\n",
  5134. NULL != pwszTitle? pwszTitle : L"",
  5135. NULL != pwsz? pwsz : L"");
  5136. if (NULL != pwszCombinedError)
  5137. {
  5138. LocalFree(pwszCombinedError);
  5139. }
  5140. if (NULL != pwszInfError)
  5141. {
  5142. LocalFree(pwszInfError);
  5143. }
  5144. if (NULL != pwszError)
  5145. {
  5146. LocalFree(const_cast<WCHAR *>(pwszError));
  5147. }
  5148. if (NULL != pwszMessage)
  5149. {
  5150. LocalFree(pwszMessage);
  5151. }
  5152. if (NULL != pwszTitle)
  5153. {
  5154. LocalFree(pwszTitle);
  5155. }
  5156. }
  5157. //**************************************************************************
  5158. // FUNCTION: MainWndProc(...)
  5159. // ARGUMENTS:
  5160. //**************************************************************************
  5161. LRESULT APIENTRY
  5162. MainWndProc(
  5163. HWND hWnd,
  5164. UINT msg,
  5165. WPARAM wParam,
  5166. LPARAM lParam)
  5167. {
  5168. int cwc;
  5169. WCHAR *pwszCmdLine = NULL;
  5170. HRESULT hr;
  5171. LRESULT lr = 0;
  5172. switch(msg)
  5173. {
  5174. case WM_CREATE:
  5175. case WM_SIZE:
  5176. break;
  5177. case WM_DESTROY:
  5178. PostQuitMessage(0);
  5179. break;
  5180. case WM_DOCERTREQDIALOGS:
  5181. pwszCmdLine = (WCHAR*)lParam;
  5182. hr = CertReqPreMain(pwszCmdLine, hWnd);
  5183. if (S_OK != hr && HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr)
  5184. {
  5185. CertReqErrorDisplay(hr, hWnd);
  5186. }
  5187. PostQuitMessage(hr);
  5188. break;
  5189. default:
  5190. lr = DefWindowProc(hWnd, msg, wParam, lParam);
  5191. break;
  5192. }
  5193. return(lr);
  5194. }
  5195. //+------------------------------------------------------------------------
  5196. //
  5197. // Function: wWinMain()
  5198. //
  5199. // Synopsis: Entry Point
  5200. //
  5201. // Arguments: [hInstance] -- Instance handle
  5202. // [hPrevInstance] -- Obsolete
  5203. // [pwszCmdLine] -- App command line
  5204. // [nCmdShow] -- Starting show state
  5205. //
  5206. // History: 12/07/96 JerryK Added this Comment
  5207. //
  5208. //-------------------------------------------------------------------------
  5209. extern "C" int APIENTRY
  5210. wWinMain(
  5211. HINSTANCE hInstance,
  5212. HINSTANCE hPrevInstance,
  5213. LPWSTR pwszCmdLine,
  5214. int nCmdShow)
  5215. {
  5216. HRESULT hr;
  5217. MSG msg;
  5218. WNDCLASS wcApp;
  5219. HWND hWndMain;
  5220. WCHAR *pwszAppName = NULL;
  5221. WCHAR *pwszWindowName = NULL;
  5222. _setmode(_fileno(stdout), _O_TEXT);
  5223. _wsetlocale(LC_ALL, L".OCP");
  5224. hr = myLoadRCString(hInstance, IDS_APP_NAME, &pwszAppName);
  5225. _PrintIfError(hr, "myLoadRCString(IDS_APP_NAME)");
  5226. hr = myLoadRCString(hInstance, IDS_WINDOW_NAME, &pwszWindowName);
  5227. _PrintIfError(hr, "myLoadRCString(IDS_WINDOW_NAME)");
  5228. // Save the current instance
  5229. g_hInstance = hInstance;
  5230. // Set up the application's window class
  5231. wcApp.style = 0;
  5232. wcApp.lpfnWndProc = MainWndProc;
  5233. wcApp.cbClsExtra = 0;
  5234. wcApp.cbWndExtra = 0;
  5235. wcApp.hInstance = hInstance;
  5236. wcApp.hIcon = LoadIcon(NULL,IDI_APPLICATION);
  5237. wcApp.hCursor = LoadCursor(NULL,IDC_ARROW);
  5238. wcApp.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  5239. wcApp.lpszMenuName = NULL;
  5240. wcApp.lpszClassName = pwszAppName;
  5241. if (!RegisterClass(&wcApp))
  5242. {
  5243. return(FALSE);
  5244. }
  5245. // Create Main Window
  5246. hWndMain = CreateWindow(
  5247. pwszAppName,
  5248. pwszWindowName,
  5249. WS_OVERLAPPEDWINDOW,
  5250. CW_USEDEFAULT,
  5251. CW_USEDEFAULT,
  5252. CW_USEDEFAULT,
  5253. CW_USEDEFAULT,
  5254. NULL,
  5255. NULL,
  5256. hInstance,
  5257. NULL);
  5258. if (NULL == hWndMain)
  5259. {
  5260. return(FALSE);
  5261. }
  5262. // Make window visible
  5263. // ShowWindow(hWndMain,nCmdShow);
  5264. // Update window client area
  5265. UpdateWindow(hWndMain);
  5266. // Send off the message to get things started
  5267. PostMessage(hWndMain,WM_DOCERTREQDIALOGS,0,(LPARAM)pwszCmdLine);
  5268. // Message Loop
  5269. while (GetMessage(&msg,NULL,0,0))
  5270. {
  5271. TranslateMessage(&msg);
  5272. DispatchMessage(&msg);
  5273. }
  5274. if (NULL != g_pwszErrorString)
  5275. {
  5276. LocalFree(g_pwszErrorString);
  5277. }
  5278. if (NULL != pwszAppName)
  5279. {
  5280. LocalFree(pwszAppName);
  5281. }
  5282. if (NULL != pwszWindowName)
  5283. {
  5284. LocalFree(pwszWindowName);
  5285. }
  5286. myInfClearError();
  5287. myFreeResourceStrings("certreq.exe");
  5288. myFreeColumnDisplayNames();
  5289. myRegisterMemDump();
  5290. return((int)msg.wParam);
  5291. }