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.

792 lines
19 KiB

  1. #include <windows.h>
  2. #include <wincrypt.h>
  3. #include <autoenr.h>
  4. #include <cryptui.h>
  5. #include <stdio.h>
  6. #include <certca.h>
  7. #include <stdlib.h>
  8. #define SHA1_HASH_LEN 20
  9. #define MSG_ERROR_S 1
  10. #define MSG_ERROR_C 2
  11. #define MSG_WARNING_S 4
  12. #define MSG_WARNING_C 8
  13. #define MSG_INFO_S 16
  14. #define MSG_INFO_C 32
  15. #define szOID_WINDOWS_SYSTEM_COMPONENT_VERIFICATION "1.3.6.1.4.1.311.10.3.6"
  16. #define wszCERTTYPE_WINDOWS_TEST_BUILD_SIGNING L"WindowsTestBuildSigning"
  17. PWCHAR mySanitizeName(IN WCHAR const *pwszName);
  18. DWORD dwMsgLevel = MSG_ERROR_S | MSG_ERROR_C | MSG_INFO_S | MSG_INFO_C;
  19. #define PrintMessage(MsgType, Msg) \
  20. if (MsgType & dwMsgLevel & MSG_ERROR_S) _PrintMessage(L"csenroll: error: "); \
  21. else if (MsgType & dwMsgLevel & MSG_ERROR_C) _PrintMessage(L" "); \
  22. else if (MsgType & dwMsgLevel & MSG_WARNING_S) _PrintMessage(L"csenroll: warning: "); \
  23. else if (MsgType & dwMsgLevel & MSG_WARNING_C) _PrintMessage(L" "); \
  24. else if (MsgType & dwMsgLevel & MSG_INFO_S) _PrintMessage(L"csenroll: "); \
  25. else if (MsgType & dwMsgLevel & MSG_INFO_C) _PrintMessage(L" "); \
  26. if (MsgType & dwMsgLevel) _PrintMessage Msg
  27. void
  28. _PrintMessage(
  29. LPWSTR pwszFormat,
  30. ...
  31. )
  32. {
  33. WCHAR rgwszBuffer[1024];
  34. va_list argList;
  35. va_start(argList, pwszFormat);
  36. vswprintf(rgwszBuffer, pwszFormat, argList);
  37. fwprintf(stderr, rgwszBuffer);
  38. }
  39. BOOL
  40. EnrollForCodeSigningCertificate(
  41. IN LPWSTR pwszCAName,
  42. IN LPWSTR pwszDNSName,
  43. PCERT_CONTEXT pOldCert
  44. )
  45. {
  46. CRYPTUI_WIZ_CERT_REQUEST_INFO CertRequestInfo;
  47. CRYPTUI_WIZ_CERT_REQUEST_PVK_NEW NewKeyInfo;
  48. CRYPTUI_WIZ_CERT_TYPE CertType;
  49. CRYPT_KEY_PROV_INFO ProviderInfo;
  50. PCCERT_CONTEXT pCertContext = NULL;
  51. PCCERT_CONTEXT pCert = NULL;
  52. DWORD dwCAStatus;
  53. DWORD dwAcquireFlags = 0;
  54. LPWSTR pwszProvName = NULL;
  55. WCHAR rgwszMachineName[MAX_COMPUTERNAME_LENGTH + 1];
  56. DWORD cMachineName = MAX_COMPUTERNAME_LENGTH + 1;
  57. CRYPT_DATA_BLOB CryptData;
  58. DWORD dwErr = 0;
  59. BOOL fRet = FALSE;
  60. LPWSTR rgwszCertType[2];
  61. memset(&CertRequestInfo, 0, sizeof(CertRequestInfo));
  62. memset(&NewKeyInfo, 0, sizeof(NewKeyInfo));
  63. memset(&ProviderInfo, 0, sizeof(ProviderInfo));
  64. memset(&rgwszMachineName, 0, sizeof(rgwszMachineName));
  65. memset(&CryptData, 0, sizeof(CryptData));
  66. memset(&CertType, 0, sizeof(CertType));
  67. // set up the provider info
  68. ProviderInfo.dwProvType = 0; // pInfo->dwProvType;
  69. ProviderInfo.pwszProvName = NULL; // The wizard will choose one based
  70. // on the cert type
  71. // set the acquire context flags
  72. // UNDONE - need to add silent flag
  73. ProviderInfo.dwFlags = 0; // dwAcquireFlags;
  74. // set the key specification
  75. ProviderInfo.dwKeySpec = 0; // pInfo->dwKeySpec;
  76. // set up the new key info
  77. NewKeyInfo.dwSize = sizeof(NewKeyInfo);
  78. NewKeyInfo.pKeyProvInfo = &ProviderInfo;
  79. // set the flags to be passed when calling CryptGenKey
  80. NewKeyInfo.dwGenKeyFlags = 0; // pInfo->dwGenKeyFlags;
  81. // set the request info
  82. CertRequestInfo.dwSize = sizeof(CertRequestInfo);
  83. // cert exists then check if expired (if so do renewal)
  84. if (pOldCert)
  85. {
  86. CertRequestInfo.dwPurpose = CRYPTUI_WIZ_CERT_RENEW;
  87. CertRequestInfo.pRenewCertContext = pOldCert;
  88. }
  89. else
  90. {
  91. CertRequestInfo.dwPurpose = CRYPTUI_WIZ_CERT_ENROLL;
  92. CertRequestInfo.pRenewCertContext = NULL;
  93. }
  94. // UNDONE - for now always gen a new key, later may allow using existing key
  95. // for things like renewal
  96. CertRequestInfo.dwPvkChoice = CRYPTUI_WIZ_CERT_REQUEST_PVK_CHOICE_NEW;
  97. CertRequestInfo.pPvkNew = &NewKeyInfo;
  98. // destination cert store is the MY store (!!!! hard coded !!!!)
  99. CertRequestInfo.pwszDesStore = L"MY";
  100. // set algorithm for hashing
  101. CertRequestInfo.pszHashAlg = NULL;
  102. // set the cert type
  103. rgwszCertType[0] = wszCERTTYPE_WINDOWS_TEST_BUILD_SIGNING;
  104. rgwszCertType[1] = NULL;
  105. CertRequestInfo.dwCertChoice = CRYPTUI_WIZ_CERT_REQUEST_CERT_TYPE;
  106. CertType.dwSize = sizeof(CertType);
  107. CertType.cCertType = 1;
  108. CertType.rgwszCertType = rgwszCertType;
  109. CertRequestInfo.pCertType = &CertType;
  110. // set the Cert Server machine and authority
  111. CertRequestInfo.pwszCALocation = pwszDNSName;
  112. CertRequestInfo.pwszCAName = mySanitizeName(pwszCAName);
  113. // certify and create a key at the same time
  114. if (!CryptUIWizCertRequest(
  115. CRYPTUI_WIZ_NO_UI,
  116. 0,
  117. NULL,
  118. &CertRequestInfo,
  119. &pCertContext,
  120. &dwCAStatus))
  121. {
  122. PrintMessage(MSG_ERROR_S, (L"CyptUIWizCertRequest failed with %lxh\n", GetLastError()));
  123. goto Ret;
  124. }
  125. if (dwCAStatus != CRYPTUI_WIZ_CERT_REQUEST_STATUS_SUCCEEDED) {
  126. PrintMessage(MSG_ERROR_S, (L"CyptUIWizCertRequest failed to issue certificate\n"));
  127. goto Ret;
  128. }
  129. fRet = TRUE;
  130. Ret:
  131. if (CertRequestInfo.pwszCAName)
  132. LocalFree((PVOID) CertRequestInfo.pwszCAName);
  133. if (pCertContext)
  134. CertFreeCertificateContext(pCertContext);
  135. if (pCert)
  136. CertFreeCertificateContext(pCert);
  137. if (pwszProvName)
  138. LocalFree(pwszProvName);
  139. return fRet;
  140. }
  141. BOOL
  142. ExportCertificateHash(
  143. PCERT_CONTEXT pCertContext
  144. )
  145. {
  146. BYTE bSHA1Hash[SHA1_HASH_LEN], bPrintHash[SHA1_HASH_LEN * 2 + 1];
  147. DWORD cbHashLen = sizeof(bSHA1Hash), i;
  148. if (CertGetCertificateContextProperty(
  149. pCertContext,
  150. CERT_SHA1_HASH_PROP_ID,
  151. bSHA1Hash,
  152. &cbHashLen
  153. ) == FALSE) {
  154. return FALSE;
  155. }
  156. for (i = 0; i < SHA1_HASH_LEN; i++) {
  157. BYTE dwVal = bSHA1Hash[i];
  158. bPrintHash[i * 2] = ((dwVal >> 4) >= 10 ? (dwVal >> 4) + 'A' - 10 : (dwVal >> 4) + '0');
  159. bPrintHash[i * 2 + 1] = ((dwVal & 0xf) >= 10 ? (dwVal & 0xf) + 'A' - 10 : (dwVal & 0xf) + '0');
  160. }
  161. bPrintHash[SHA1_HASH_LEN * 2] = '\0';
  162. printf(bPrintHash);
  163. return TRUE;
  164. }
  165. PCERT_CONTEXT
  166. FindCodeSigningCertificate(
  167. HCERTSTORE hCertStore,
  168. LPWSTR pwszCAName,
  169. BYTE *pbSHA1Hash
  170. )
  171. {
  172. PCERT_CONTEXT pRootContext = NULL, pCertContext = NULL;
  173. PCERT_CONTEXT pPrevCertContext = NULL, pReturnCertContext = NULL;
  174. PCERT_CHAIN_CONTEXT pChainContext = NULL;
  175. CERT_CHAIN_PARA ChainPara;
  176. CERT_ENHKEY_USAGE EnhKeyUsage, *pEnhKeyUsage;
  177. LPSTR rgpszOids[2];
  178. DWORD cElement, cbHashLen, cbUsageLen, i;
  179. BOOL bFound = FALSE, bFoundCodeSigning, bFoundWindowsVerification;
  180. BYTE rgbHashBuffer[SHA1_HASH_LEN];
  181. BYTE rgbUsage[1024];
  182. ULARGE_INTEGER CertTime, PrevCertTime;
  183. PrevCertTime.QuadPart = 0;
  184. __try {
  185. for (pPrevCertContext = NULL; ;pPrevCertContext = pCertContext) {
  186. pCertContext = (PCERT_CONTEXT) CertFindCertificateInStore(
  187. hCertStore,
  188. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  189. 0,
  190. CERT_FIND_ISSUER_STR,
  191. pwszCAName,
  192. pPrevCertContext
  193. );
  194. if (pCertContext == NULL) {
  195. __leave;
  196. }
  197. cbUsageLen = sizeof(rgbUsage);
  198. pEnhKeyUsage = (PCERT_ENHKEY_USAGE) rgbUsage;
  199. if (CertGetEnhancedKeyUsage(
  200. pCertContext,
  201. 0,
  202. pEnhKeyUsage,
  203. &cbUsageLen
  204. ) == FALSE) {
  205. PrintMessage(MSG_ERROR_S, (L"Can't get certificate usage\n"));
  206. __leave;
  207. }
  208. bFoundCodeSigning = FALSE;
  209. bFoundWindowsVerification = FALSE;
  210. for (i = 0; i < pEnhKeyUsage->cUsageIdentifier; i++) {
  211. if (strcmp(
  212. pEnhKeyUsage->rgpszUsageIdentifier[i],
  213. szOID_PKIX_KP_CODE_SIGNING) == 0) {
  214. bFoundCodeSigning = TRUE;
  215. }
  216. if (strcmp(
  217. pEnhKeyUsage->rgpszUsageIdentifier[i],
  218. szOID_WINDOWS_SYSTEM_COMPONENT_VERIFICATION) == 0) {
  219. bFoundWindowsVerification = TRUE;
  220. }
  221. if (bFoundCodeSigning && bFoundWindowsVerification) {
  222. break;
  223. }
  224. }
  225. if (bFoundCodeSigning == FALSE || bFoundWindowsVerification == FALSE) {
  226. PrintMessage(MSG_WARNING_S, (L"Certificate issued by CA %s in 'MY store' can't be used for Windows build signing\n", pwszCAName));
  227. continue;
  228. }
  229. bFound = FALSE;
  230. memset(rgbHashBuffer, 0, sizeof(rgbHashBuffer));
  231. // the user specified a hash for the root cert
  232. // check if this cert chains up to this root.
  233. if (memcmp(pbSHA1Hash, rgbHashBuffer, sizeof(rgbHashBuffer)) != 0) {
  234. rgpszOids[0] = szOID_PKIX_KP_CODE_SIGNING;
  235. rgpszOids[1] = szOID_WINDOWS_SYSTEM_COMPONENT_VERIFICATION;
  236. ChainPara.cbSize = sizeof(ChainPara);
  237. ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
  238. ChainPara.RequestedUsage.Usage.cUsageIdentifier = 2;
  239. ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = rgpszOids;
  240. if (CertGetCertificateChain(
  241. NULL,
  242. pCertContext,
  243. NULL,
  244. NULL,
  245. &ChainPara,
  246. 0,
  247. NULL,
  248. (CERT_CHAIN_CONTEXT const **) &pChainContext
  249. ) == FALSE) {
  250. __leave;
  251. }
  252. // get to the root cert of this chain
  253. cElement = pChainContext->rgpChain[0]->cElement;
  254. pRootContext = (PCERT_CONTEXT)
  255. pChainContext->rgpChain[0]->rgpElement[cElement - 1]->pCertContext;
  256. cbHashLen = sizeof(rgbHashBuffer);
  257. if (CertGetCertificateContextProperty(
  258. pRootContext,
  259. CERT_SHA1_HASH_PROP_ID,
  260. rgbHashBuffer,
  261. &cbHashLen
  262. ) == FALSE) {
  263. PrintMessage(MSG_ERROR_S, (L"Can't get SHA1 hash for Windows build signing certificate\n"));
  264. __leave;
  265. }
  266. // check if this is the root cert we want
  267. if (memcmp(rgbHashBuffer, pbSHA1Hash, cbHashLen) != 0) {
  268. PrintMessage(MSG_WARNING_S, (L"Found Windows build signing certificate does not chain up to"));
  269. PrintMessage(MSG_WARNING_C, (L"requested root cert (wrong hash provided with -roothash?)\n"));
  270. continue;
  271. __leave;
  272. }
  273. bFound = TRUE;
  274. break;
  275. }
  276. // check the cert time of this cert against the time of the prev. valid cert.
  277. memcpy(&CertTime, &pCertContext->pCertInfo->NotAfter, sizeof(CertTime));
  278. if (CertTime.QuadPart > PrevCertTime.QuadPart) {
  279. if (pReturnCertContext) {
  280. CertFreeCertificateContext(pReturnCertContext);
  281. }
  282. pReturnCertContext = (PCERT_CONTEXT) CertDuplicateCertificateContext(pCertContext);
  283. PrevCertTime.QuadPart = CertTime.QuadPart;
  284. }
  285. }
  286. }
  287. __finally {
  288. if (pChainContext) {
  289. CertFreeCertificateChain(pChainContext);
  290. }
  291. if (bFound == FALSE) {
  292. CertFreeCertificateContext(pCertContext);
  293. pCertContext = NULL;
  294. }
  295. }
  296. return pReturnCertContext;
  297. }
  298. HCAINFO
  299. CheckCA(
  300. LPWSTR pwszCAName
  301. )
  302. {
  303. LPWSTR *pwszCertTypes = NULL, pwszSanitizeName = NULL;
  304. HCAINFO hCAInfo = NULL;
  305. BOOL bFoundCodeSigningCA = FALSE;
  306. int i;
  307. __try {
  308. if ((pwszSanitizeName = mySanitizeName(pwszCAName)) == NULL) {
  309. __leave;
  310. }
  311. // scan through the list of CAs to find a valid CA name
  312. if (CAFindByName(
  313. pwszSanitizeName,
  314. NULL,
  315. 0,
  316. &hCAInfo
  317. ) != S_OK) {
  318. PrintMessage(MSG_WARNING_S, (L"Can't find CA %s\n", pwszCAName));
  319. __leave;
  320. }
  321. // get the list of certificate templates that this CA can issue
  322. if (CAGetCAProperty(
  323. hCAInfo,
  324. CA_PROP_CERT_TYPES,
  325. &pwszCertTypes
  326. ) != S_OK) {
  327. PrintMessage(MSG_ERROR_S, (L"Unable to retrieve certificate template list from CA %s\n", pwszCAName));
  328. __leave;
  329. }
  330. for (i = 0; pwszCertTypes[i]; i++) {
  331. if (wcscmp (pwszCertTypes[i], wszCERTTYPE_CODE_SIGNING) == 0) {
  332. bFoundCodeSigningCA = TRUE;
  333. break;
  334. }
  335. }
  336. }
  337. __finally {
  338. if (pwszCertTypes) {
  339. CAFreeCAProperty(hCAInfo, pwszCertTypes);
  340. }
  341. if (bFoundCodeSigningCA == FALSE && hCAInfo) {
  342. CACloseCA(hCAInfo);
  343. hCAInfo = NULL;
  344. }
  345. if (pwszSanitizeName != NULL) {
  346. LocalFree(pwszSanitizeName);
  347. }
  348. }
  349. return hCAInfo;
  350. }
  351. void
  352. PrintHelp(
  353. void
  354. )
  355. {
  356. printf("Usage: csenroll -ca CAName [-ca CAName] [-d Days] [-h] [-roothash Hash]\n");
  357. printf(" Enroll for a Windows build signing certificate\n");
  358. printf("\n");
  359. printf(" Options:\n");
  360. printf(" -ca <CAName> Name of CA from where to get a certificate\n");
  361. printf(" For backup purposes you can specify multiple names.\n");
  362. printf("\n");
  363. printf(" -d <days> Number of days before expiration of current certificate\n");
  364. printf(" when an attempt is made to renew current certificate.\n");
  365. printf("\n");
  366. printf(" -h Show this help.\n");
  367. printf("\n");
  368. printf(" -roothash <Hash> Specifiy the hash of the root certificate that the current\n");
  369. printf(" Windows build signing certficate has to chain up to.\n");
  370. printf(" Use this option to ensure that your Windows build signing\n");
  371. printf(" certificate chains up to the correct root certificate\n");
  372. printf("\n");
  373. printf("\n");
  374. }
  375. int
  376. __cdecl
  377. main(int argc, char **argv)
  378. {
  379. PCERT_CONTEXT pCertContext = NULL;
  380. HCAINFO hCAInfo = NULL;
  381. HCERTSTORE hCertStore = NULL;
  382. LPWSTR pwszCAName = NULL, *pwszCAList = NULL, *pwszDNSName = NULL;
  383. BYTE rgbRootHash[SHA1_HASH_LEN];
  384. BOOL bRootHash = FALSE, bRet = FALSE;
  385. int i, dwNumCA = 0, dwDaysValid = 0, dwDays = 10;
  386. memset(rgbRootHash, 0, sizeof(rgbRootHash));
  387. __try {
  388. while (--argc) {
  389. argv += 1;
  390. if (_stricmp(*argv, "-ca") == 0) {
  391. int dwLen;
  392. argc -= 1;
  393. argv += 1;
  394. dwLen = (strlen(*argv) + 1) * sizeof(WCHAR);
  395. if (pwszCAList == NULL) {
  396. pwszCAList = (LPWSTR *) malloc(sizeof(LPWSTR) * (dwNumCA + 2));
  397. } else {
  398. pwszCAList = (LPWSTR *) realloc(pwszCAList, sizeof(LPWSTR) * (dwNumCA + 2));
  399. }
  400. if (pwszCAList == NULL) {
  401. PrintMessage(MSG_ERROR_S, (L"Failed to allocate memory\n"));
  402. __leave;
  403. }
  404. pwszCAList[dwNumCA + 1] = NULL;
  405. pwszCAList[dwNumCA] = (LPWSTR) malloc(dwLen);
  406. if (pwszCAList[dwNumCA] == NULL) {
  407. PrintMessage(MSG_ERROR_S, (L"Failed to allocate memory\n"));
  408. __leave;
  409. }
  410. MultiByteToWideChar(
  411. CP_UTF8,
  412. 0,
  413. *argv,
  414. -1,
  415. pwszCAList[dwNumCA],
  416. dwLen
  417. );
  418. dwNumCA += 1;
  419. }
  420. if (_stricmp(*argv, "-roothash") == 0) {
  421. argv += 1;
  422. argc -= 1;
  423. if (strlen(*argv) != SHA1_HASH_LEN * 2) {
  424. PrintMessage(MSG_ERROR_S, (L"Hash must have a length of 40 bytes\n"));
  425. __leave;
  426. }
  427. _strupr(*argv);
  428. for (i = 0; i < SHA1_HASH_LEN * 2; i++) {
  429. BYTE bNum;
  430. if ((*argv)[i] >= '0' && (*argv)[i] <= '9') {
  431. bNum = (*argv)[i] - '0';
  432. } else if ((*argv)[i] >= 'A' && (*argv)[i] <= 'F') {
  433. bNum = (*argv)[i] - 'A' + 10;
  434. } else {
  435. PrintMessage(MSG_ERROR_S, (L"Illegal hexdecimal number in hash\n"));
  436. __leave;
  437. }
  438. rgbRootHash[i / 2] |= (i % 2 ? bNum : bNum << 4);
  439. }
  440. bRootHash = TRUE;
  441. }
  442. if (_stricmp(*argv, "-v") == 0) {
  443. dwMsgLevel |= MSG_WARNING_S | MSG_WARNING_C;
  444. }
  445. if (_stricmp(*argv, "-d") == 0) {
  446. argv += 1;
  447. argc -= 1;
  448. dwDays = atoi(*argv);
  449. }
  450. if (_stricmp(*argv, "-h") == 0) {
  451. PrintHelp();
  452. __leave;
  453. }
  454. }
  455. if (dwNumCA == 0) {
  456. PrintHelp();
  457. __leave;
  458. }
  459. hCertStore = CertOpenSystemStore(
  460. 0,
  461. L"MY"
  462. );
  463. if (hCertStore == NULL) {
  464. PrintMessage(MSG_ERROR_S, (L"Can't open 'MY store'\n"));
  465. __leave;
  466. }
  467. if (bRootHash == FALSE) {
  468. PrintMessage(MSG_WARNING_S, (L"Certificate chain can't be verified (no -roothash specified)\n"));
  469. }
  470. for (i = 0; i < dwNumCA; i++) {
  471. //
  472. // now try to find a Windows build signing cert that was issued
  473. // from a known ca and that chains up to a known root
  474. //
  475. pCertContext = FindCodeSigningCertificate(
  476. hCertStore,
  477. pwszCAList[i],
  478. rgbRootHash
  479. );
  480. if (pCertContext) {
  481. pwszCAName = pwszCAList[i];
  482. break;
  483. }
  484. }
  485. if (pCertContext) {
  486. // check how long the current cert is valid
  487. ULARGE_INTEGER CertTime, CurrentTime, days;
  488. FILETIME SystemTime, LocalTime;
  489. memcpy(&CertTime, &pCertContext->pCertInfo->NotAfter, sizeof(CertTime));
  490. GetSystemTimeAsFileTime(&SystemTime);
  491. memcpy(&CurrentTime, &SystemTime, sizeof(CurrentTime));
  492. if (CertTime.QuadPart > CurrentTime.QuadPart) {
  493. dwDaysValid = (DWORD)
  494. ((CertTime.QuadPart - CurrentTime.QuadPart) /
  495. (10000000i64 * 24 * 60 * 60));
  496. }
  497. //
  498. // now check if the CA that originally issued
  499. // the cert is still available
  500. //
  501. if ((hCAInfo = CheckCA(pwszCAName)) == NULL) {
  502. PrintMessage(MSG_WARNING_S, (L"Can't find CA %s to renew certificate\n", pwszCAName));
  503. if (dwDaysValid < (dwDays / 2)) {
  504. // since we won't be able to renew this cert, just get a new one.
  505. CertFreeCertificateContext(pCertContext);
  506. pCertContext = NULL;
  507. }
  508. }
  509. }
  510. if (pCertContext == NULL) {
  511. // find a CA that can issue a windows build signing cert
  512. for (i = 0; i < dwNumCA; i++) {
  513. if (hCAInfo = CheckCA(pwszCAList[i])) {
  514. pwszCAName = pwszCAList[i];
  515. break;
  516. }
  517. }
  518. }
  519. if (pCertContext == NULL && hCAInfo == NULL) {
  520. PrintMessage(MSG_ERROR_S, (L"Can't find Windows build signing CA\n"));
  521. __leave;
  522. }
  523. if (hCAInfo && (pCertContext == NULL || dwDaysValid < dwDays)) {
  524. PrintMessage(
  525. MSG_INFO_S,
  526. (L"%s build signing certificate. Please wait...\n", pCertContext ? L"Renewing" : L"Enrolling for")
  527. );
  528. // get DNS name of CA
  529. if (CAGetCAProperty(
  530. hCAInfo,
  531. CA_PROP_DNSNAME,
  532. &pwszDNSName
  533. ) != S_OK) {
  534. PrintMessage(MSG_ERROR_S, (L"Unable to retrieve DNS name for %s\n", pwszCAName));
  535. __leave;
  536. }
  537. if (EnrollForCodeSigningCertificate(
  538. pwszCAName,
  539. *pwszDNSName,
  540. pCertContext
  541. ) == FALSE) {
  542. PrintMessage(MSG_ERROR_S, (L"Enrollment for Windows build signing certificate failed\n"));
  543. PrintMessage(MSG_ERROR_C, (L"Check access rights to CA %s and\n", pwszCAName));
  544. PrintMessage(MSG_ERROR_C, (L"Windows build signing certificate template\n"));
  545. __leave;
  546. }
  547. // now make sure that we really have a cert in the store
  548. if (pCertContext) {
  549. CertFreeCertificateContext(pCertContext);
  550. pCertContext = NULL;
  551. }
  552. if (CertControlStore(
  553. hCertStore,
  554. 0,
  555. CERT_STORE_CTRL_RESYNC,
  556. NULL
  557. ) == FALSE) {
  558. PrintMessage(MSG_ERROR_S, (L"Failed to resync the 'MY store'\n"));
  559. __leave;
  560. }
  561. pCertContext = FindCodeSigningCertificate(
  562. hCertStore,
  563. pwszCAName,
  564. rgbRootHash
  565. );
  566. if (pCertContext == NULL) {
  567. PrintMessage(MSG_ERROR_S, (L"Can't find valid Windows build signing certificate in 'MY store'\n"));
  568. __leave;
  569. }
  570. }
  571. if (ExportCertificateHash(pCertContext) == FALSE) {
  572. PrintMessage(MSG_ERROR_S, (L"Export of Windows build signing certificate has failed\n"));
  573. __leave;
  574. }
  575. bRet = TRUE;
  576. }
  577. __finally {
  578. if (pwszDNSName) {
  579. CAFreeCAProperty(hCAInfo, pwszDNSName);
  580. }
  581. if (hCAInfo) {
  582. CACloseCA(hCAInfo);
  583. }
  584. if (pCertContext) {
  585. CertFreeCertificateContext(pCertContext);
  586. }
  587. if (hCertStore) {
  588. CertCloseStore(hCertStore, 0);
  589. }
  590. }
  591. return (bRet ? 0 : -1);
  592. }