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

751 lines
22 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1996
  6. //
  7. // File: makerootctl.cpp
  8. //
  9. // Contents: Makes a CTL used for the Auto Update of the "AuthRoot" store.
  10. //
  11. // See Usage() for list of options.
  12. //
  13. //
  14. // Functions: main
  15. //
  16. // History: 08-Sep-00 philh created
  17. //
  18. //--------------------------------------------------------------------------
  19. #include <windows.h>
  20. #include "wincrypt.h"
  21. #include "unicode.h"
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <memory.h>
  26. #include <time.h>
  27. #define SHA1_HASH_LEN 20
  28. #define SHA1_HASH_NAME_LEN (2 * SHA1_HASH_LEN)
  29. void PrintLastError(LPCSTR pszMsg)
  30. {
  31. DWORD dwErr = GetLastError();
  32. printf("%s failed => 0x%x (%d) \n", pszMsg, dwErr, dwErr);
  33. }
  34. void Usage(void)
  35. {
  36. printf("Usage: makerootctl [options] [<CtlFilename>]\n");
  37. printf("Options are:\n");
  38. printf(" -h - This message\n");
  39. printf(" -c - Include certs in the CTL\n");
  40. printf(" -C <Directory> - Write certs into directory\n");
  41. printf(" -a <AddStoreFilename> - Add\n");
  42. printf(" -d <DeleteStoreFilename> - Delete\n");
  43. printf(" -t <Number> - Timeout hint in SequenceNumber (secs)\n");
  44. printf("\n");
  45. printf("Supports multiple -a and/or -d options\n");
  46. printf("\n");
  47. printf("The -c and -C options are ignored for deleted roots\n");
  48. printf("\n");
  49. printf("For -C option, defaults to authroot.stl. Also writes authrootseq.txt\n");
  50. printf("\n");
  51. }
  52. //+-------------------------------------------------------------------------
  53. // Allocate and convert a multi-byte string to a wide string
  54. //--------------------------------------------------------------------------
  55. LPWSTR AllocAndSzToWsz(LPCSTR psz)
  56. {
  57. size_t cb;
  58. LPWSTR pwsz = NULL;
  59. if (-1 == (cb = mbstowcs( NULL, psz, strlen(psz))))
  60. goto bad_param;
  61. cb += 1; // terminating NULL
  62. if (NULL == (pwsz = (LPWSTR) malloc( cb * sizeof(WCHAR)))) {
  63. PrintLastError("AllocAndSzToWsz");
  64. goto failed;
  65. }
  66. if (-1 == mbstowcs( pwsz, psz, cb))
  67. goto bad_param;
  68. goto common_return;
  69. bad_param:
  70. printf("Failed, bad AllocAndSzToWsz\n");
  71. failed:
  72. if (pwsz) {
  73. free(pwsz);
  74. pwsz = NULL;
  75. }
  76. common_return:
  77. return pwsz;
  78. }
  79. BOOL OpenAndAddStoreToCollection(
  80. IN LPCSTR pszStoreFilename,
  81. IN OUT HCERTSTORE hCollectionStore
  82. )
  83. {
  84. BOOL fResult;
  85. HCERTSTORE hStore;
  86. hStore = CertOpenStore(
  87. CERT_STORE_PROV_FILENAME_A,
  88. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  89. 0, // hCryptProv
  90. 0,
  91. (const void *) pszStoreFilename
  92. );
  93. if (NULL == hStore) {
  94. PrintLastError("Open StoreFilename");
  95. return FALSE;
  96. }
  97. fResult = CertAddStoreToCollection(
  98. hCollectionStore,
  99. hStore,
  100. CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG,
  101. 0 // dwPriority
  102. );
  103. if (!fResult)
  104. PrintLastError("CertAddStoreToCollection");
  105. CertCloseStore(hStore, 0);
  106. return fResult;
  107. }
  108. //+-------------------------------------------------------------------------
  109. // Converts the bytes into UNICODE ASCII HEX
  110. //
  111. // Needs (cb * 2 + 1) * sizeof(WCHAR) bytes of space in wsz
  112. //--------------------------------------------------------------------------
  113. void BytesToWStr(DWORD cb, void* pv, LPWSTR wsz)
  114. {
  115. BYTE* pb = (BYTE*) pv;
  116. for (DWORD i = 0; i<cb; i++) {
  117. int b;
  118. b = (*pb & 0xF0) >> 4;
  119. *wsz++ = (b <= 9) ? b + L'0' : (b - 10) + L'A';
  120. b = *pb & 0x0F;
  121. *wsz++ = (b <= 9) ? b + L'0' : (b - 10) + L'A';
  122. pb++;
  123. }
  124. *wsz++ = 0;
  125. }
  126. //+-------------------------------------------------------------------------
  127. // Converts the bytes into ASCII HEX
  128. //
  129. // Needs (cb * 2 + 1) * sizeof(char) bytes of space in sz
  130. //--------------------------------------------------------------------------
  131. void BytesToStr(DWORD cb, void* pv, LPSTR sz)
  132. {
  133. BYTE* pb = (BYTE*) pv;
  134. for (DWORD i = 0; i<cb; i++) {
  135. int b;
  136. b = (*pb & 0xF0) >> 4;
  137. *sz++ = (b <= 9) ? b + '0' : (b - 10) + 'A';
  138. b = *pb & 0x0F;
  139. *sz++ = (b <= 9) ? b + '0' : (b - 10) + 'A';
  140. pb++;
  141. }
  142. *sz++ = 0;
  143. }
  144. BOOL
  145. WriteCertToDirectory(
  146. IN LPCWSTR pwszCertDirectory,
  147. IN PCCERT_CONTEXT pCert
  148. )
  149. {
  150. BOOL fResult;
  151. DWORD cchDir;
  152. LPWSTR pwszFilename = NULL;
  153. DWORD cchFilename;
  154. DWORD cbData;
  155. BYTE rgbSha1Hash[SHA1_HASH_LEN];
  156. HANDLE hFile = NULL;
  157. DWORD cbBytesWritten;
  158. // Get cert's SHA1 hash
  159. cbData = SHA1_HASH_LEN;
  160. if (!CertGetCertificateContextProperty(
  161. pCert,
  162. CERT_SHA1_HASH_PROP_ID,
  163. rgbSha1Hash,
  164. &cbData
  165. ) || SHA1_HASH_LEN != cbData) {
  166. PrintLastError("GetCertificate SHA1 Hash Property");
  167. goto ErrorReturn;
  168. }
  169. // Format filename:
  170. // L"CertDirectory" L"\\" L"AsciiHexHash" L".cer"
  171. // For example:
  172. // L"c:\\authroot\\216B2A29E62A00CE820146D8244141B92511B279.cer"
  173. cchDir = wcslen(pwszCertDirectory);
  174. cchFilename =
  175. cchDir + 1 + SHA1_HASH_NAME_LEN + wcslen(CERT_AUTH_ROOT_CERT_EXT) + 1;
  176. if (NULL == (pwszFilename = (LPWSTR) malloc(sizeof(WCHAR) * cchFilename)))
  177. goto OutOfMemory;
  178. wcscpy(pwszFilename, pwszCertDirectory);
  179. pwszFilename[cchDir] = L'\\';
  180. BytesToWStr(SHA1_HASH_LEN, rgbSha1Hash, pwszFilename + cchDir + 1);
  181. wcscpy(pwszFilename + cchDir + 1 + SHA1_HASH_NAME_LEN,
  182. CERT_AUTH_ROOT_CERT_EXT);
  183. hFile = CreateFileU(
  184. pwszFilename,
  185. GENERIC_WRITE,
  186. 0, // fdwShareMode
  187. NULL, // lpsa
  188. CREATE_ALWAYS,
  189. 0, // fdwAttrsAndFlags
  190. 0); // TemplateFile
  191. if (INVALID_HANDLE_VALUE == hFile) {
  192. PrintLastError("Create File");
  193. printf("failed for: %S\n", pwszFilename);
  194. goto ErrorReturn;
  195. }
  196. if (!WriteFile(
  197. hFile,
  198. pCert->pbCertEncoded,
  199. pCert->cbCertEncoded,
  200. &cbBytesWritten,
  201. NULL // lpOverlapped
  202. )) {
  203. PrintLastError("Write File");
  204. printf("failed for: %S\n", pwszFilename);
  205. goto ErrorReturn;
  206. }
  207. fResult = TRUE;
  208. CommonReturn:
  209. if (NULL != hFile && INVALID_HANDLE_VALUE != hFile)
  210. CloseHandle(hFile);
  211. if (pwszFilename)
  212. free(pwszFilename);
  213. return fResult;
  214. ErrorReturn:
  215. fResult = FALSE;
  216. goto CommonReturn;
  217. OutOfMemory:
  218. printf("Failed:: out of memory\n");
  219. goto ErrorReturn;
  220. }
  221. // Sequence Number consists of FileTime, Timeout hint byte
  222. #define SEQ_LEN (sizeof(FILETIME) + 1)
  223. int _cdecl main(int argc, char * argv[])
  224. {
  225. int ReturnStatus = 0;
  226. LPWSTR pwszCtlFilename = NULL; // malloc'ed
  227. LPWSTR pwszSeqFilename = NULL; // malloc'ed
  228. HCERTSTORE hAddStore = NULL;
  229. HCERTSTORE hDeleteStore = NULL;
  230. BOOL fIncludeCerts = FALSE;
  231. LPWSTR pwszCertDirectory = NULL; // malloc'ed
  232. BYTE bTimeout = 20; // default to 20 seconds
  233. DWORD cCert = 0;
  234. LPSTR pszSubjectUsage = szOID_ROOT_LIST_SIGNER;
  235. BYTE rgbDelete[] = {0x02, 0x01, 0x1}; // 0x02 - INTEGER tag
  236. CRYPT_ATTR_BLOB DeleteValue = {sizeof(rgbDelete), rgbDelete};
  237. CRYPT_ATTRIBUTE rgDeleteAttr[1] = {
  238. szOID_REMOVE_CERTIFICATE, 1, &DeleteValue
  239. };
  240. BYTE rgbSequenceNumber[SEQ_LEN];
  241. CTL_INFO CtlInfo;
  242. PCTL_ENTRY pCtlEntry = NULL;
  243. PCTL_ENTRY *ppCtlEntry = NULL;
  244. CMSG_SIGNED_ENCODE_INFO SignInfo;
  245. PCERT_BLOB pCertEncoded = NULL;
  246. BYTE *pbEncoded = NULL;
  247. DWORD cbEncoded;
  248. PCCERT_CONTEXT pCert;
  249. HANDLE hCtlFile = NULL;
  250. DWORD cbBytesWritten = 0;
  251. PCCTL_CONTEXT pCtl = NULL;
  252. HANDLE hSeqFile = NULL;
  253. // Create the add and delete collection stores
  254. hAddStore = CertOpenStore(
  255. CERT_STORE_PROV_COLLECTION,
  256. 0, // dwEncodingType
  257. 0, // hCryptProv
  258. 0, // dwFlags
  259. NULL // pvPara
  260. );
  261. if (NULL == hAddStore) {
  262. PrintLastError("CertOpenStore(Add Collection)");
  263. goto ErrorReturn;
  264. }
  265. hDeleteStore = CertOpenStore(
  266. CERT_STORE_PROV_COLLECTION,
  267. 0, // dwEncodingType
  268. 0, // hCryptProv
  269. 0, // dwFlags
  270. NULL // pvPara
  271. );
  272. if (NULL == hDeleteStore) {
  273. PrintLastError("CertOpenStore(Delete Collection)");
  274. goto ErrorReturn;
  275. }
  276. while (--argc>0)
  277. {
  278. if (**++argv == '-')
  279. {
  280. switch(argv[0][1])
  281. {
  282. case 'c':
  283. fIncludeCerts = TRUE;
  284. break;
  285. case 'C':
  286. if (argc < 2 || argv[1][0] == '-') {
  287. printf("-C : missing Directory argument\n");
  288. goto BadUsage;
  289. }
  290. argc--;
  291. argv++;
  292. pwszCertDirectory = AllocAndSzToWsz(argv[0]);
  293. break;
  294. case 'a':
  295. if (argc < 2 || argv[1][0] == '-') {
  296. printf("-a : missing AddStoreFilename argument\n");
  297. goto BadUsage;
  298. }
  299. argc--;
  300. argv++;
  301. if (!OpenAndAddStoreToCollection(argv[0], hAddStore))
  302. goto ErrorReturn;
  303. break;
  304. case 'd':
  305. if (argc < 2 || argv[1][0] == '-') {
  306. printf("-a : missing DeleteStoreFilename argument\n");
  307. goto BadUsage;
  308. }
  309. argc--;
  310. argv++;
  311. if (!OpenAndAddStoreToCollection(argv[0], hDeleteStore))
  312. goto ErrorReturn;
  313. break;
  314. case 't':
  315. if (argc < 2 || argv[1][0] == '-') {
  316. printf("-t : missing timeout number argument\n");
  317. goto BadUsage;
  318. }
  319. argc--;
  320. argv++;
  321. {
  322. DWORD dwTimeout;
  323. dwTimeout = (DWORD) strtoul(argv[0], NULL, 0);
  324. if (dwTimeout > 0xFF)
  325. dwTimeout = 0xFF;
  326. bTimeout = (BYTE) dwTimeout;
  327. }
  328. break;
  329. case 'h':
  330. default:
  331. goto BadUsage;
  332. }
  333. } else {
  334. if (pwszCtlFilename == NULL)
  335. pwszCtlFilename = AllocAndSzToWsz(argv[0]);
  336. else {
  337. printf("too many CTL filenames\n");
  338. goto BadUsage;
  339. }
  340. }
  341. }
  342. if (NULL == pwszCtlFilename && NULL == pwszCertDirectory) {
  343. printf("missing CTL filename\n");
  344. goto BadUsage;
  345. }
  346. // Get count of the add and delete certs
  347. pCert = NULL;
  348. cCert = 0;
  349. while (pCert = CertEnumCertificatesInStore(hAddStore, pCert))
  350. cCert++;
  351. pCert = NULL;
  352. while (pCert = CertEnumCertificatesInStore(hDeleteStore, pCert))
  353. cCert++;
  354. if (cCert) {
  355. DWORD i;
  356. if (NULL == (pCtlEntry = (PCTL_ENTRY) malloc(
  357. cCert * sizeof(CTL_ENTRY))))
  358. goto OutOfMemory;
  359. memset(pCtlEntry, 0, cCert * sizeof(CTL_ENTRY));
  360. if (NULL == (ppCtlEntry = (PCTL_ENTRY *) malloc(
  361. cCert * sizeof(PCTL_ENTRY))))
  362. goto OutOfMemory;
  363. memset(ppCtlEntry, 0, cCert * sizeof(PCTL_ENTRY));
  364. if (fIncludeCerts) {
  365. if (NULL == (pCertEncoded = (PCERT_BLOB) malloc(
  366. cCert * sizeof(CERT_BLOB))))
  367. goto OutOfMemory;
  368. memset(pCertEncoded, 0, cCert * sizeof(CERT_BLOB));
  369. }
  370. // Create CTL and add CTL entry for each certificate. If enabled,
  371. // add to list of encoded certificates
  372. //
  373. i = 0;
  374. pCert = NULL;
  375. while (pCert = CertEnumCertificatesInStore(hAddStore, pCert)) {
  376. DWORD cbCtlEntry;
  377. if (i >= cCert) {
  378. printf("Unexpected error, too many add certs\n");
  379. goto ErrorReturn;
  380. }
  381. cbCtlEntry = 0;
  382. if (!CertCreateCTLEntryFromCertificateContextProperties(
  383. pCert,
  384. 0, // cOptAttr
  385. NULL, // pOptAttr
  386. CTL_ENTRY_FROM_PROP_CHAIN_FLAG,
  387. NULL, // pvReserved
  388. NULL, // pCtlEntry
  389. &cbCtlEntry
  390. )) {
  391. PrintLastError("CreateCTLEntry");
  392. goto ErrorReturn;
  393. }
  394. if (NULL == (ppCtlEntry[i] = (PCTL_ENTRY) malloc(cbCtlEntry)))
  395. goto OutOfMemory;
  396. if (!CertCreateCTLEntryFromCertificateContextProperties(
  397. pCert,
  398. 0, // cOptAttr
  399. NULL, // pOptAttr
  400. CTL_ENTRY_FROM_PROP_CHAIN_FLAG,
  401. NULL, // pvReserved
  402. ppCtlEntry[i],
  403. &cbCtlEntry
  404. )) {
  405. PrintLastError("CreateCTLEntry");
  406. goto ErrorReturn;
  407. }
  408. pCtlEntry[i] = *ppCtlEntry[i];
  409. if (fIncludeCerts) {
  410. pCertEncoded[i].cbData = pCert->cbCertEncoded;
  411. pCertEncoded[i].pbData = pCert->pbCertEncoded;
  412. }
  413. if (pwszCertDirectory) {
  414. if (!WriteCertToDirectory(pwszCertDirectory, pCert))
  415. goto ErrorReturn;
  416. }
  417. i++;
  418. }
  419. pCert = NULL;
  420. while (pCert = CertEnumCertificatesInStore(hDeleteStore, pCert)) {
  421. DWORD cbCtlEntry;
  422. if (i >= cCert) {
  423. printf("Unexpected error, too many delete certs\n");
  424. goto ErrorReturn;
  425. }
  426. cbCtlEntry = 0;
  427. if (!CertCreateCTLEntryFromCertificateContextProperties(
  428. pCert,
  429. 1, // cOptAttr
  430. rgDeleteAttr,
  431. 0, // dwFlags
  432. NULL, // pvReserved
  433. NULL, // pCtlEntry
  434. &cbCtlEntry
  435. )) {
  436. PrintLastError("CreateCTLEntry");
  437. goto ErrorReturn;
  438. }
  439. if (NULL == (ppCtlEntry[i] = (PCTL_ENTRY) malloc(cbCtlEntry)))
  440. goto OutOfMemory;
  441. if (!CertCreateCTLEntryFromCertificateContextProperties(
  442. pCert,
  443. 1, // cOptAttr
  444. rgDeleteAttr,
  445. 0, // dwFlags
  446. NULL, // pvReserved
  447. ppCtlEntry[i],
  448. &cbCtlEntry
  449. )) {
  450. PrintLastError("CreateCTLEntry");
  451. goto ErrorReturn;
  452. }
  453. pCtlEntry[i] = *ppCtlEntry[i];
  454. i++;
  455. }
  456. if (i != cCert) {
  457. printf("Unexpected error, didn't process all the certs\n");
  458. goto ErrorReturn;
  459. }
  460. }
  461. memset(&CtlInfo, 0, sizeof(CtlInfo));
  462. CtlInfo.dwVersion = CTL_V1;
  463. CtlInfo.SubjectUsage.cUsageIdentifier = 1;
  464. CtlInfo.SubjectUsage.rgpszUsageIdentifier = &pszSubjectUsage;
  465. // CtlInfo.ListIdentifier =
  466. GetSystemTimeAsFileTime(&CtlInfo.ThisUpdate);
  467. // Use the 8 byte filetime, 1 byte timeout for the sequence number.
  468. memcpy(rgbSequenceNumber, (BYTE *) &CtlInfo.ThisUpdate, sizeof(FILETIME));
  469. rgbSequenceNumber[sizeof(FILETIME)] = bTimeout;
  470. CtlInfo.SequenceNumber.pbData = rgbSequenceNumber;
  471. CtlInfo.SequenceNumber.cbData = sizeof(rgbSequenceNumber);
  472. // CtlInfo.NextUpdate =
  473. CtlInfo.SubjectAlgorithm.pszObjId = szOID_OIWSEC_sha1;
  474. CtlInfo.cCTLEntry = cCert;
  475. CtlInfo.rgCTLEntry = pCtlEntry;
  476. // CtlInfo.cExtension =
  477. // CtlInfo.rgExtension =
  478. memset(&SignInfo, 0, sizeof(SignInfo));
  479. SignInfo.cbSize = sizeof(SignInfo);
  480. // SignInfo.cSigners =
  481. // SignInfo.rgSigners =
  482. if (fIncludeCerts) {
  483. SignInfo.cCertEncoded = cCert;
  484. SignInfo.rgCertEncoded = pCertEncoded;
  485. }
  486. // SignInfo.cCrlEncoded =
  487. // SignInfo.rgCrlEncoded =
  488. cbEncoded = 0;
  489. if (!CryptMsgEncodeAndSignCTL(
  490. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  491. &CtlInfo,
  492. &SignInfo,
  493. 0, // dwFlags
  494. NULL, // pbEncoded
  495. &cbEncoded
  496. )) {
  497. PrintLastError("EncodeAndSignCTL");
  498. goto ErrorReturn;
  499. }
  500. if (NULL == (pbEncoded = (BYTE *) malloc(cbEncoded)))
  501. goto OutOfMemory;
  502. if (!CryptMsgEncodeAndSignCTL(
  503. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  504. &CtlInfo,
  505. &SignInfo,
  506. 0, // dwFlags
  507. pbEncoded,
  508. &cbEncoded
  509. )) {
  510. PrintLastError("EncodeAndSignCTL");
  511. goto ErrorReturn;
  512. }
  513. if (NULL == pwszCtlFilename) {
  514. DWORD cchDir;
  515. DWORD cchFilename;
  516. cchDir = wcslen(pwszCertDirectory);
  517. cchFilename = cchDir + 1 + wcslen(CERT_AUTH_ROOT_CTL_FILENAME) + 1;
  518. if (NULL == (pwszCtlFilename = (LPWSTR) malloc(
  519. sizeof(WCHAR) * cchFilename)))
  520. goto OutOfMemory;
  521. wcscpy(pwszCtlFilename, pwszCertDirectory);
  522. pwszCtlFilename[cchDir] = L'\\';
  523. wcscpy(pwszCtlFilename + cchDir + 1, CERT_AUTH_ROOT_CTL_FILENAME);
  524. }
  525. hCtlFile = CreateFileU(
  526. pwszCtlFilename,
  527. GENERIC_WRITE,
  528. 0, // fdwShareMode
  529. NULL, // lpsa
  530. CREATE_ALWAYS,
  531. 0, // fdwAttrsAndFlags
  532. 0); // TemplateFile
  533. if (INVALID_HANDLE_VALUE == hCtlFile) {
  534. PrintLastError("Create Ctl File");
  535. goto ErrorReturn;
  536. }
  537. if (!WriteFile(
  538. hCtlFile,
  539. pbEncoded,
  540. cbEncoded,
  541. &cbBytesWritten,
  542. NULL // lpOverlapped
  543. )) {
  544. PrintLastError("Write Ctl File");
  545. goto ErrorReturn;
  546. }
  547. if (pwszCertDirectory) {
  548. // Create the authroot.seq file containing the CTL's SequenceNumber.
  549. // Write to the file as big endian. The decoded value is little
  550. // endian.
  551. BYTE rgbSeq[SEQ_LEN];
  552. char szSeq[SEQ_LEN * 2 + 1]; // Ascii Hex
  553. DWORD cbSeq;
  554. DWORD i;
  555. DWORD cchDir;
  556. DWORD cchFilename;
  557. // Decode the encoded CTL to get the "real" sequence number.
  558. pCtl = CertCreateCTLContext(
  559. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  560. pbEncoded,
  561. cbEncoded
  562. );
  563. if (NULL == pCtl) {
  564. PrintLastError("CreateCTLContext");
  565. goto ErrorReturn;
  566. }
  567. cbSeq = pCtl->pCtlInfo->SequenceNumber.cbData;
  568. if (0 == cbSeq || sizeof(rgbSeq) < cbSeq) {
  569. printf("failed, invalid SequenceNumber\n");
  570. goto ErrorReturn;
  571. }
  572. // Convert the SequenceNumber to big endian ascii hex before writing to
  573. // the file.
  574. for (i = 0; i < cbSeq; i++)
  575. rgbSeq[i] = pCtl->pCtlInfo->SequenceNumber.pbData[cbSeq - 1 - i];
  576. BytesToStr(cbSeq, rgbSeq, szSeq);
  577. cchDir = wcslen(pwszCertDirectory);
  578. cchFilename = cchDir + 1 + wcslen(CERT_AUTH_ROOT_SEQ_FILENAME) + 1;
  579. if (NULL == (pwszSeqFilename = (LPWSTR) malloc(
  580. sizeof(WCHAR) * cchFilename)))
  581. goto OutOfMemory;
  582. wcscpy(pwszSeqFilename, pwszCertDirectory);
  583. pwszSeqFilename[cchDir] = L'\\';
  584. wcscpy(pwszSeqFilename + cchDir + 1, CERT_AUTH_ROOT_SEQ_FILENAME);
  585. hSeqFile = CreateFileU(
  586. pwszSeqFilename,
  587. GENERIC_WRITE,
  588. 0, // fdwShareMode
  589. NULL, // lpsa
  590. CREATE_ALWAYS,
  591. 0, // fdwAttrsAndFlags
  592. 0); // TemplateFile
  593. if (INVALID_HANDLE_VALUE == hSeqFile) {
  594. PrintLastError("Create Seq File");
  595. goto ErrorReturn;
  596. }
  597. if (!WriteFile(
  598. hSeqFile,
  599. szSeq,
  600. cbSeq * 2,
  601. &cbBytesWritten,
  602. NULL // lpOverlapped
  603. )) {
  604. PrintLastError("Write Seq File");
  605. goto ErrorReturn;
  606. }
  607. }
  608. ReturnStatus = 0;
  609. printf("Succeeded\n");
  610. CommonReturn:
  611. if (pwszCtlFilename)
  612. free(pwszCtlFilename);
  613. if (pwszSeqFilename)
  614. free(pwszSeqFilename);
  615. if (pwszCertDirectory)
  616. free(pwszCertDirectory);
  617. if (pCtl)
  618. CertFreeCTLContext(pCtl);
  619. if (hAddStore)
  620. CertCloseStore(hAddStore, 0);
  621. if (hDeleteStore)
  622. CertCloseStore(hDeleteStore, 0);
  623. if (pCtlEntry)
  624. free(pCtlEntry);
  625. if (ppCtlEntry) {
  626. DWORD i;
  627. for (i = 0; i < cCert; i++)
  628. free(ppCtlEntry[i]);
  629. free(ppCtlEntry);
  630. }
  631. if (pCertEncoded)
  632. free(pCertEncoded);
  633. if (pbEncoded)
  634. free(pbEncoded);
  635. if (NULL != hCtlFile && INVALID_HANDLE_VALUE != hCtlFile)
  636. CloseHandle(hCtlFile);
  637. if (NULL != hSeqFile && INVALID_HANDLE_VALUE != hSeqFile)
  638. CloseHandle(hSeqFile);
  639. return ReturnStatus;
  640. BadUsage:
  641. Usage();
  642. ErrorReturn:
  643. ReturnStatus = -1;
  644. goto CommonReturn;
  645. OutOfMemory:
  646. printf("Failed:: out of memory\n");
  647. goto ErrorReturn;
  648. }