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.

4543 lines
99 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: inf.cpp
  7. //
  8. // Contents: Cert Server INF file processing routines
  9. //
  10. //---------------------------------------------------------------------------
  11. #include <pch.cpp>
  12. #pragma hdrstop
  13. #include <certca.h>
  14. #include "csdisp.h"
  15. #include "initcert.h"
  16. #include "clibres.h"
  17. #define __dwFILE__ __dwFILE_CERTLIB_INF_CPP__
  18. #define wszBSCAPOLICYFILE L"\\" wszCAPOLICYFILE
  19. #define wszINFKEY_CONTINUE L"_continue_"
  20. #define cwcVALUEMAX 1024
  21. static WCHAR *s_pwszSection = NULL;
  22. static WCHAR *s_pwszKey = NULL;
  23. static WCHAR *s_pwszValue = NULL;
  24. VOID
  25. infClearString(
  26. IN OUT WCHAR **ppwsz)
  27. {
  28. if (NULL != ppwsz && NULL != *ppwsz)
  29. {
  30. LocalFree(*ppwsz);
  31. *ppwsz = NULL;
  32. }
  33. }
  34. BOOL
  35. infCopyString(
  36. OPTIONAL IN WCHAR const *pwszIn,
  37. OPTIONAL OUT WCHAR **ppwszOut)
  38. {
  39. HRESULT hr;
  40. if (NULL != pwszIn && L'\0' != *pwszIn)
  41. {
  42. if (NULL == *ppwszOut)
  43. {
  44. if (NULL != *ppwszOut)
  45. {
  46. LocalFree(*ppwszOut);
  47. *ppwszOut = NULL;
  48. }
  49. hr = myDupString(pwszIn, ppwszOut);
  50. _JumpIfError(hr, error, "myDupString");
  51. }
  52. }
  53. hr = S_OK;
  54. error:
  55. return(S_OK == hr);
  56. }
  57. #define INFSTRINGSELECT(pwsz) (NULL != (pwsz)? (pwsz) : L"")
  58. #if DBG_CERTSRV
  59. # define INFSETERROR(hr, pwszSection, pwszKey, pwszValue) \
  60. { \
  61. _PrintError3(hr, "infSetError", ERROR_LINE_NOT_FOUND, S_FALSE); \
  62. infSetError(hr, pwszSection, pwszKey, pwszValue, __LINE__); \
  63. }
  64. #else
  65. # define INFSETERROR infSetError
  66. #endif
  67. VOID
  68. infSetError(
  69. IN HRESULT hr,
  70. OPTIONAL IN WCHAR const *pwszSection,
  71. OPTIONAL IN WCHAR const *pwszKey,
  72. OPTIONAL IN WCHAR const *pwszValue
  73. DBGPARM(IN DWORD dwLine))
  74. {
  75. DBGPRINT((
  76. DBG_SS_CERTLIBI,
  77. "inf.cpp(%u): infSetError Begin: [%ws] %ws = %ws\n",
  78. dwLine,
  79. INFSTRINGSELECT(pwszSection),
  80. INFSTRINGSELECT(pwszKey),
  81. INFSTRINGSELECT(pwszValue)));
  82. infCopyString(pwszSection, &s_pwszSection);
  83. infCopyString(pwszKey, &s_pwszKey);
  84. infCopyString(pwszValue, &s_pwszValue);
  85. DBGPRINT((
  86. DBG_SS_CERTLIBI,
  87. "inf.cpp(%u): infSetError End: [%ws] %ws = %ws\n",
  88. dwLine,
  89. INFSTRINGSELECT(s_pwszSection),
  90. INFSTRINGSELECT(s_pwszKey),
  91. INFSTRINGSELECT(s_pwszValue)));
  92. }
  93. WCHAR *
  94. myInfGetError()
  95. {
  96. DWORD cwc = 1;
  97. WCHAR *pwsz = NULL;
  98. if (NULL != s_pwszSection)
  99. {
  100. cwc += wcslen(s_pwszSection) + 2;
  101. }
  102. if (NULL != s_pwszKey)
  103. {
  104. cwc += wcslen(s_pwszKey) + 1;
  105. }
  106. if (NULL != s_pwszValue)
  107. {
  108. cwc += wcslen(s_pwszValue) + 3;
  109. }
  110. if (1 == cwc)
  111. {
  112. goto error;
  113. }
  114. pwsz = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  115. if (NULL == pwsz)
  116. {
  117. goto error;
  118. }
  119. *pwsz = L'\0';
  120. if (NULL != s_pwszSection)
  121. {
  122. wcscat(pwsz, wszLBRACKET);
  123. wcscat(pwsz, s_pwszSection);
  124. wcscat(pwsz, wszRBRACKET);
  125. }
  126. if (NULL != s_pwszKey)
  127. {
  128. if (L'\0' != *pwsz)
  129. {
  130. wcscat(pwsz, L" ");
  131. }
  132. wcscat(pwsz, s_pwszKey);
  133. }
  134. if (NULL != s_pwszValue)
  135. {
  136. wcscat(pwsz, L" = ");
  137. wcscat(pwsz, s_pwszValue);
  138. }
  139. error:
  140. return(pwsz);
  141. }
  142. VOID
  143. myInfClearError()
  144. {
  145. infClearString(&s_pwszSection);
  146. infClearString(&s_pwszKey);
  147. infClearString(&s_pwszValue);
  148. }
  149. HRESULT
  150. infSetupFindFirstLine(
  151. IN HINF hInf,
  152. IN WCHAR const *pwszSection,
  153. OPTIONAL IN WCHAR const *pwszKey,
  154. OUT INFCONTEXT *pInfContext)
  155. {
  156. HRESULT hr;
  157. if (!SetupFindFirstLine(hInf, pwszSection, pwszKey, pInfContext))
  158. {
  159. hr = myHLastError();
  160. if ((HRESULT) ERROR_LINE_NOT_FOUND == hr &&
  161. SetupFindFirstLine(hInf, pwszSection, wszINFKEY_EMPTY, pInfContext))
  162. {
  163. hr = S_FALSE; // Section exists, but Key doesn't
  164. }
  165. _JumpErrorStr3(
  166. hr,
  167. error,
  168. "SetupFindFirstLine",
  169. pwszSection,
  170. ERROR_LINE_NOT_FOUND,
  171. S_FALSE);
  172. }
  173. hr = S_OK;
  174. error:
  175. return(hr);
  176. }
  177. HRESULT
  178. infBuildPolicyElement(
  179. IN OUT INFCONTEXT *pInfContext,
  180. OPTIONAL OUT CERT_POLICY_QUALIFIER_INFO *pcpqi)
  181. {
  182. HRESULT hr;
  183. DWORD i;
  184. WCHAR wszKey[MAX_PATH];
  185. BOOL fURL = FALSE;
  186. BOOL fNotice = FALSE;
  187. DWORD cwc;
  188. WCHAR *pwszValue = NULL;
  189. WCHAR *pwszURL = NULL;
  190. BYTE *pbData = NULL;
  191. DWORD cbData;
  192. wszKey[0] = L'\0';
  193. if (!SetupGetStringField(
  194. pInfContext,
  195. 0,
  196. wszKey,
  197. ARRAYSIZE(wszKey),
  198. NULL))
  199. {
  200. hr = myHLastError();
  201. _JumpError(hr, error, "SetupGetStringField");
  202. }
  203. DBGPRINT((DBG_SS_CERTLIBI, "Element = %ws\n", wszKey));
  204. if (0 == lstrcmpi(wszINFKEY_URL, wszKey))
  205. {
  206. fURL = TRUE;
  207. }
  208. else
  209. if (0 == lstrcmpi(wszINFKEY_NOTICE, wszKey))
  210. {
  211. fNotice = TRUE;
  212. }
  213. else
  214. {
  215. if (0 != lstrcmpi(wszINFKEY_OID, wszKey))
  216. {
  217. _PrintErrorStr(E_INVALIDARG, "Skipping unknown key", wszKey);
  218. }
  219. hr = S_FALSE; // Skip this key
  220. }
  221. if (fURL || fNotice)
  222. {
  223. if (!SetupGetStringField(pInfContext, 1, NULL, 0, &cwc))
  224. {
  225. hr = myHLastError();
  226. _JumpError(hr, error, "SetupGetStringField");
  227. }
  228. pwszValue = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  229. if (NULL == pwszValue)
  230. {
  231. hr = E_OUTOFMEMORY;
  232. _JumpError(hr, error, "LocalAlloc");
  233. }
  234. if (!SetupGetStringField(pInfContext, 1, pwszValue, cwc, NULL))
  235. {
  236. hr = myHLastError();
  237. _JumpError(hr, error, "SetupGetStringField");
  238. }
  239. DBGPRINT((DBG_SS_CERTLIBI, "SetupGetStringField = %ws\n", pwszValue));
  240. if (fURL)
  241. {
  242. CERT_NAME_VALUE NameValue;
  243. hr = myInternetCanonicalizeUrl(pwszValue, &pwszURL);
  244. _JumpIfError(hr, error, "myInternetCanonicalizeUrl");
  245. NameValue.dwValueType = CERT_RDN_IA5_STRING;
  246. NameValue.Value.pbData = (BYTE *) pwszURL;
  247. NameValue.Value.cbData = 0;
  248. if (NULL != pcpqi)
  249. {
  250. CSILOG(S_OK, IDS_ILOG_CAPOLICY_ELEMENT, pwszURL, NULL, NULL);
  251. }
  252. if (!myEncodeObject(
  253. X509_ASN_ENCODING,
  254. X509_UNICODE_NAME_VALUE,
  255. &NameValue,
  256. 0,
  257. CERTLIB_USE_LOCALALLOC,
  258. &pbData,
  259. &cbData))
  260. {
  261. hr = myHLastError();
  262. _JumpError(hr, error, "myEncodeObject");
  263. }
  264. }
  265. else
  266. {
  267. CERT_POLICY_QUALIFIER_USER_NOTICE UserNotice;
  268. ZeroMemory(&UserNotice, sizeof(UserNotice));
  269. UserNotice.pszDisplayText = pwszValue;
  270. if (NULL != pcpqi)
  271. {
  272. CSILOG(S_OK, IDS_ILOG_CAPOLICY_ELEMENT, pwszValue, NULL, NULL);
  273. }
  274. if (!myEncodeObject(
  275. X509_ASN_ENCODING,
  276. X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
  277. &UserNotice,
  278. 0,
  279. CERTLIB_USE_LOCALALLOC,
  280. &pbData,
  281. &cbData))
  282. {
  283. hr = myHLastError();
  284. _JumpError(hr, error, "myEncodeObject");
  285. }
  286. }
  287. if (NULL != pcpqi)
  288. {
  289. pcpqi->pszPolicyQualifierId = fURL?
  290. szOID_PKIX_POLICY_QUALIFIER_CPS :
  291. szOID_PKIX_POLICY_QUALIFIER_USERNOTICE;
  292. pcpqi->Qualifier.pbData = pbData;
  293. pcpqi->Qualifier.cbData = cbData;
  294. pbData = NULL;
  295. }
  296. hr = S_OK;
  297. }
  298. error:
  299. if (S_OK != hr && S_FALSE != hr)
  300. {
  301. INFSETERROR(hr, NULL, wszKey, pwszValue);
  302. }
  303. if (NULL != pwszValue)
  304. {
  305. LocalFree(pwszValue);
  306. }
  307. if (NULL != pwszURL)
  308. {
  309. LocalFree(pwszURL);
  310. }
  311. if (NULL != pbData)
  312. {
  313. LocalFree(pbData);
  314. }
  315. return(hr);
  316. }
  317. HRESULT
  318. infBuildPolicy(
  319. IN HINF hInf,
  320. IN WCHAR const *pwszSection,
  321. IN OUT CERT_POLICY_INFO *pcpi)
  322. {
  323. HRESULT hr;
  324. INFCONTEXT InfContext;
  325. DWORD i;
  326. WCHAR wszValue[cwcVALUEMAX];
  327. CSASSERT(NULL != hInf && INVALID_HANDLE_VALUE != hInf);
  328. wszValue[0] = L'\0';
  329. hr = infSetupFindFirstLine(hInf, pwszSection, wszINFKEY_OID, &InfContext);
  330. if (S_OK != hr)
  331. {
  332. INFSETERROR(hr, NULL, wszINFKEY_OID, NULL);
  333. _JumpErrorStr(hr, error, "infSetupFindFirstLine", pwszSection);
  334. }
  335. if (!SetupGetStringField(
  336. &InfContext,
  337. 1,
  338. wszValue,
  339. ARRAYSIZE(wszValue),
  340. NULL))
  341. {
  342. hr = myHLastError();
  343. INFSETERROR(hr, NULL, wszINFKEY_OID, NULL);
  344. _JumpError(hr, error, "SetupGetStringField");
  345. }
  346. if (!ConvertWszToSz(&pcpi->pszPolicyIdentifier, wszValue, -1))
  347. {
  348. hr = E_OUTOFMEMORY;
  349. _JumpError(hr, error, "ConvertWszToSz");
  350. }
  351. DBGPRINT((DBG_SS_CERTLIBI, "OID = %hs\n", pcpi->pszPolicyIdentifier));
  352. hr = infSetupFindFirstLine(hInf, pwszSection, NULL, &InfContext);
  353. _JumpIfErrorStr(hr, error, "infSetupFindFirstLine", pwszSection);
  354. for (i = 0; ; )
  355. {
  356. hr = infBuildPolicyElement(&InfContext, NULL);
  357. if (S_FALSE != hr)
  358. {
  359. _JumpIfErrorStr(hr, error, "infBuildPolicyElement", pwszSection);
  360. i++;
  361. }
  362. if (!SetupFindNextLine(&InfContext, &InfContext))
  363. {
  364. hr = myHLastError();
  365. _PrintErrorStr2(hr, "SetupFindNextLine", pwszSection, hr);
  366. break;
  367. }
  368. }
  369. pcpi->cPolicyQualifier = i;
  370. pcpi->rgPolicyQualifier = (CERT_POLICY_QUALIFIER_INFO *) LocalAlloc(
  371. LMEM_FIXED | LMEM_ZEROINIT,
  372. pcpi->cPolicyQualifier *
  373. sizeof(pcpi->rgPolicyQualifier[0]));
  374. if (NULL == pcpi->rgPolicyQualifier)
  375. {
  376. hr = E_OUTOFMEMORY;
  377. _JumpError(hr, error, "LocalAlloc");
  378. }
  379. hr = infSetupFindFirstLine(hInf, pwszSection, NULL, &InfContext);
  380. _JumpIfErrorStr(hr, error, "infSetupFindFirstLine", pwszSection);
  381. for (i = 0; ; )
  382. {
  383. // handle one URL or text message
  384. hr = infBuildPolicyElement(&InfContext, &pcpi->rgPolicyQualifier[i]);
  385. if (S_FALSE != hr)
  386. {
  387. _JumpIfErrorStr(hr, error, "infBuildPolicyElement", pwszSection);
  388. i++;
  389. }
  390. if (!SetupFindNextLine(&InfContext, &InfContext))
  391. {
  392. hr = myHLastError();
  393. _PrintErrorStr2(hr, "SetupFindNextLine", pwszSection, hr);
  394. break;
  395. }
  396. }
  397. CSASSERT(i == pcpi->cPolicyQualifier);
  398. hr = S_OK;
  399. error:
  400. if (S_OK != hr && S_FALSE != hr)
  401. {
  402. INFSETERROR(hr, pwszSection, NULL, L"???");
  403. }
  404. CSILOG(
  405. hr,
  406. IDS_ILOG_CAPOLICY_BUILD,
  407. pwszSection,
  408. S_OK == hr || L'\0' == wszValue[0]? NULL : wszValue,
  409. NULL);
  410. return(hr);
  411. }
  412. VOID
  413. infFreePolicy(
  414. IN OUT CERT_POLICY_INFO *pcpi)
  415. {
  416. DWORD i;
  417. CERT_POLICY_QUALIFIER_INFO *pcpqi;
  418. if (NULL != pcpi->pszPolicyIdentifier)
  419. {
  420. LocalFree(pcpi->pszPolicyIdentifier);
  421. }
  422. if (NULL != pcpi->rgPolicyQualifier)
  423. {
  424. for (i = 0; i < pcpi->cPolicyQualifier; i++)
  425. {
  426. pcpqi = &pcpi->rgPolicyQualifier[i];
  427. if (NULL != pcpqi->Qualifier.pbData)
  428. {
  429. LocalFree(pcpqi->Qualifier.pbData);
  430. }
  431. }
  432. LocalFree(pcpi->rgPolicyQualifier);
  433. }
  434. }
  435. HRESULT
  436. myInfOpenFile(
  437. OPTIONAL IN WCHAR const *pwszfnPolicy,
  438. OUT HINF *phInf,
  439. OUT DWORD *pErrorLine)
  440. {
  441. HRESULT hr;
  442. HINF hInf;
  443. WCHAR wszPath[MAX_PATH];
  444. UINT ErrorLine;
  445. DWORD Flags;
  446. *phInf = INVALID_HANDLE_VALUE;
  447. *pErrorLine = 0;
  448. myInfClearError();
  449. if (NULL == pwszfnPolicy)
  450. {
  451. if (0 == GetEnvironmentVariable(
  452. L"SystemRoot",
  453. wszPath,
  454. ARRAYSIZE(wszPath) - ARRAYSIZE(wszBSCAPOLICYFILE)))
  455. {
  456. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  457. _JumpError(hr, error, "GetEnvironmentVariable");
  458. }
  459. wcscat(wszPath, wszBSCAPOLICYFILE);
  460. pwszfnPolicy = wszPath;
  461. }
  462. else
  463. {
  464. if (NULL == wcschr(pwszfnPolicy, L'\\'))
  465. {
  466. if (ARRAYSIZE(wszPath) <= 2 + wcslen(pwszfnPolicy))
  467. {
  468. hr = HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE);
  469. _JumpErrorStr(hr, error, "filename too long", pwszfnPolicy);
  470. }
  471. wcscpy(wszPath, L".\\");
  472. wcscat(wszPath, pwszfnPolicy);
  473. pwszfnPolicy = wszPath;
  474. }
  475. }
  476. Flags = INF_STYLE_WIN4;
  477. while (TRUE)
  478. {
  479. ErrorLine = 0;
  480. *phInf = SetupOpenInfFile(
  481. pwszfnPolicy,
  482. NULL,
  483. Flags,
  484. &ErrorLine);
  485. *pErrorLine = ErrorLine;
  486. if (INVALID_HANDLE_VALUE != *phInf)
  487. {
  488. break;
  489. }
  490. hr = myHLastError();
  491. if ((HRESULT) ERROR_WRONG_INF_STYLE == hr && INF_STYLE_WIN4 == Flags)
  492. {
  493. Flags = INF_STYLE_OLDNT;
  494. continue;
  495. }
  496. CSILOG(
  497. hr,
  498. IDS_ILOG_CAPOLICY_OPEN_FAILED,
  499. pwszfnPolicy,
  500. NULL,
  501. 0 == *pErrorLine? NULL : pErrorLine);
  502. _JumpErrorStr(hr, error, "SetupOpenInfFile", pwszfnPolicy);
  503. }
  504. CSILOG(S_OK, IDS_ILOG_CAPOLICY_OPEN, pwszfnPolicy, NULL, NULL);
  505. hr = S_OK;
  506. error:
  507. DBGPRINT((
  508. DBG_SS_CERTLIBI,
  509. "myInfOpenFile(%ws) hr=%x --> h=%x\n",
  510. pwszfnPolicy,
  511. hr,
  512. *phInf));
  513. return(hr);
  514. }
  515. VOID
  516. myInfCloseFile(
  517. IN HINF hInf)
  518. {
  519. if (NULL != hInf && INVALID_HANDLE_VALUE != hInf)
  520. {
  521. WCHAR *pwszInfError = myInfGetError();
  522. SetupCloseInfFile(hInf);
  523. CSILOG(S_OK, IDS_ILOG_CAPOLICY_CLOSE, pwszInfError, NULL, NULL);
  524. if (NULL != pwszInfError)
  525. {
  526. LocalFree(pwszInfError);
  527. }
  528. }
  529. DBGPRINT((DBG_SS_CERTLIBI, "myInfCloseFile(%x)\n", hInf));
  530. }
  531. HRESULT
  532. myInfParseBooleanValue(
  533. IN WCHAR const *pwszValue,
  534. OUT BOOL *pfValue)
  535. {
  536. HRESULT hr;
  537. DWORD i;
  538. static WCHAR const * const s_apwszTrue[] = { L"True", L"Yes", L"On", L"1" };
  539. static WCHAR const * const s_apwszFalse[] = { L"False", L"No", L"Off", L"0" };
  540. *pfValue = FALSE;
  541. for (i = 0; i < ARRAYSIZE(s_apwszTrue); i++)
  542. {
  543. if (0 == lstrcmpi(pwszValue, s_apwszTrue[i]))
  544. {
  545. *pfValue = TRUE;
  546. break;
  547. }
  548. }
  549. if (i == ARRAYSIZE(s_apwszTrue))
  550. {
  551. for (i = 0; i < ARRAYSIZE(s_apwszFalse); i++)
  552. {
  553. if (0 == lstrcmpi(pwszValue, s_apwszFalse[i]))
  554. {
  555. break;
  556. }
  557. }
  558. if (i == ARRAYSIZE(s_apwszFalse))
  559. {
  560. hr = E_INVALIDARG;
  561. _JumpErrorStr(hr, error, "bad boolean value string", pwszValue);
  562. }
  563. }
  564. hr = S_OK;
  565. error:
  566. if (S_OK != hr)
  567. {
  568. INFSETERROR(hr, NULL, NULL, pwszValue);
  569. }
  570. return(hr);
  571. }
  572. HRESULT
  573. myInfGetBooleanValue(
  574. IN HINF hInf,
  575. IN WCHAR const *pwszSection,
  576. IN WCHAR const *pwszKey,
  577. IN BOOL fIgnoreMissingKey,
  578. OUT BOOL *pfValue)
  579. {
  580. HRESULT hr;
  581. INFCONTEXT InfContext;
  582. DWORD i;
  583. WCHAR wszValue[cwcVALUEMAX];
  584. *pfValue = FALSE;
  585. myInfClearError();
  586. CSASSERT(NULL != hInf && INVALID_HANDLE_VALUE != hInf);
  587. hr = infSetupFindFirstLine(hInf, pwszSection, pwszKey, &InfContext);
  588. _PrintIfErrorStr3(
  589. hr,
  590. "infSetupFindFirstLine",
  591. pwszSection,
  592. ERROR_LINE_NOT_FOUND,
  593. S_FALSE);
  594. _JumpIfErrorStr3(
  595. hr,
  596. error,
  597. "infSetupFindFirstLine",
  598. pwszKey,
  599. ERROR_LINE_NOT_FOUND,
  600. S_FALSE);
  601. if (!SetupGetStringField(
  602. &InfContext,
  603. 1,
  604. wszValue,
  605. ARRAYSIZE(wszValue),
  606. NULL))
  607. {
  608. hr = myHLastError();
  609. _JumpErrorStr(hr, error, "SetupGetStringField", pwszKey);
  610. }
  611. DBGPRINT((
  612. DBG_SS_CERTLIBI,
  613. "myInfGetBooleanValue --> '%ws'\n",
  614. wszValue));
  615. hr = myInfParseBooleanValue(wszValue, pfValue);
  616. _JumpIfError(hr, error, "myInfParseBooleanValue");
  617. error:
  618. if (S_OK != hr &&
  619. ((HRESULT) ERROR_LINE_NOT_FOUND != hr || !fIgnoreMissingKey))
  620. {
  621. INFSETERROR(hr, pwszSection, pwszKey, NULL);
  622. }
  623. DBGPRINT((
  624. DBG_SS_CERTLIBI,
  625. "myInfGetBooleanValue(%ws, %ws) hr=%x --> f=%d\n",
  626. pwszSection,
  627. pwszKey,
  628. hr,
  629. *pfValue));
  630. return(hr);
  631. }
  632. HRESULT
  633. infGetCriticalFlag(
  634. IN HINF hInf,
  635. IN WCHAR const *pwszSection,
  636. IN BOOL fDefault,
  637. OUT BOOL *pfCritical)
  638. {
  639. HRESULT hr;
  640. hr = myInfGetBooleanValue(
  641. hInf,
  642. pwszSection,
  643. wszINFKEY_CRITICAL,
  644. TRUE,
  645. pfCritical);
  646. if (S_OK != hr)
  647. {
  648. *pfCritical = fDefault;
  649. if ((HRESULT) ERROR_LINE_NOT_FOUND != hr && S_FALSE != hr)
  650. {
  651. _JumpErrorStr(hr, error, "myInfGetBooleanValue", pwszSection);
  652. }
  653. hr = S_OK;
  654. }
  655. error:
  656. DBGPRINT((
  657. DBG_SS_CERTLIBI,
  658. "infGetCriticalFlag(%ws) hr=%x --> f=%d\n",
  659. pwszSection,
  660. hr,
  661. *pfCritical));
  662. return(hr);
  663. }
  664. //+------------------------------------------------------------------------
  665. // infGetPolicyStatementExtensionSub -- build policy extension from INF file
  666. //
  667. // [pwszSection]
  668. // Policies = LegalPolicy, LimitedUsePolicy, ExtraPolicy
  669. //
  670. // [LegalPolicy]
  671. // OID = 1.3.6.1.4.1.311.21.43
  672. // Notice = "Legal policy statement text."
  673. //
  674. // [LimitedUsePolicy]
  675. // OID = 1.3.6.1.4.1.311.21.47
  676. // URL = "http://http.site.com/some where/default.asp"
  677. // URL = "ftp://ftp.site.com/some where else/default.asp"
  678. // Notice = "Limited use policy statement text."
  679. // URL = "ldap://ldap.site.com/some where else again/default.asp"
  680. //
  681. // [ExtraPolicy]
  682. // OID = 1.3.6.1.4.1.311.21.53
  683. // URL = http://extra.site.com/Extra Policy/default.asp
  684. //
  685. // Return S_OK if extension has been constructed from the INF file
  686. // Return S_FALSE if empty section detected in INF file
  687. // Return other error if no section detected in INF file
  688. //-------------------------------------------------------------------------
  689. HRESULT
  690. infGetPolicyStatementExtensionSub(
  691. IN HINF hInf,
  692. IN WCHAR const *pwszSection,
  693. IN char const *pszObjId,
  694. OUT CERT_EXTENSION *pext)
  695. {
  696. HRESULT hr;
  697. CERT_POLICIES_INFO PoliciesInfo;
  698. INFCONTEXT InfContext;
  699. DWORD i;
  700. WCHAR wszValue[cwcVALUEMAX];
  701. wszValue[0] = L'\0';
  702. ZeroMemory(&PoliciesInfo, sizeof(PoliciesInfo));
  703. ZeroMemory(pext, sizeof(*pext));
  704. CSASSERT(NULL != hInf && INVALID_HANDLE_VALUE != hInf);
  705. hr = infSetupFindFirstLine(
  706. hInf,
  707. pwszSection,
  708. wszINFKEY_POLICIES,
  709. &InfContext);
  710. if (S_OK != hr)
  711. {
  712. CSILOG(
  713. hr,
  714. IDS_ILOG_CAPOLICY_NOKEY,
  715. pwszSection,
  716. wszINFKEY_POLICIES,
  717. NULL);
  718. _JumpErrorStr3(
  719. hr,
  720. error,
  721. "infSetupFindFirstLine",
  722. pwszSection,
  723. S_FALSE,
  724. ERROR_LINE_NOT_FOUND);
  725. }
  726. // First, count the policies.
  727. PoliciesInfo.cPolicyInfo = SetupGetFieldCount(&InfContext);
  728. if (0 == PoliciesInfo.cPolicyInfo)
  729. {
  730. hr = S_FALSE;
  731. _JumpError(hr, error, "SetupGetFieldCount");
  732. }
  733. // Next, allocate memory.
  734. PoliciesInfo.rgPolicyInfo = (CERT_POLICY_INFO *) LocalAlloc(
  735. LMEM_FIXED | LMEM_ZEROINIT,
  736. PoliciesInfo.cPolicyInfo * sizeof(PoliciesInfo.rgPolicyInfo[0]));
  737. if (NULL == PoliciesInfo.rgPolicyInfo)
  738. {
  739. hr = E_OUTOFMEMORY;
  740. _JumpError(hr, error, "LocalAlloc");
  741. }
  742. // Finally! Fill in the policies data.
  743. for (i = 0; i < PoliciesInfo.cPolicyInfo; i++)
  744. {
  745. if (!SetupGetStringField(
  746. &InfContext,
  747. i + 1,
  748. wszValue,
  749. ARRAYSIZE(wszValue),
  750. NULL))
  751. {
  752. hr = myHLastError();
  753. _JumpErrorStr2(hr, error, "SetupGetStringField", wszINFKEY_POLICIES, hr);
  754. }
  755. DBGPRINT((DBG_SS_CERTLIBI, "%ws[%u] = %ws\n", wszINFKEY_POLICIES, i, wszValue));
  756. hr = infBuildPolicy(hInf, wszValue, &PoliciesInfo.rgPolicyInfo[i]);
  757. _JumpIfErrorStr(hr, error, "infBuildPolicy", wszValue);
  758. }
  759. hr = infGetCriticalFlag(hInf, pwszSection, FALSE, &pext->fCritical);
  760. _JumpIfError(hr, error, "infGetCriticalFlag");
  761. if (!myEncodeObject(
  762. X509_ASN_ENCODING,
  763. X509_CERT_POLICIES,
  764. &PoliciesInfo,
  765. 0,
  766. CERTLIB_USE_LOCALALLOC,
  767. &pext->Value.pbData,
  768. &pext->Value.cbData))
  769. {
  770. hr = myHLastError();
  771. _JumpError(hr, error, "myEncodeObject");
  772. }
  773. error:
  774. if (S_OK != hr && S_FALSE != hr)
  775. {
  776. INFSETERROR(hr, pwszSection, wszINFKEY_POLICIES, wszValue);
  777. }
  778. pext->pszObjId = const_cast<char *>(pszObjId); // on error, too!
  779. if (NULL != PoliciesInfo.rgPolicyInfo)
  780. {
  781. for (i = 0; i < PoliciesInfo.cPolicyInfo; i++)
  782. {
  783. infFreePolicy(&PoliciesInfo.rgPolicyInfo[i]);
  784. }
  785. LocalFree(PoliciesInfo.rgPolicyInfo);
  786. }
  787. CSILOG(
  788. hr,
  789. IDS_ILOG_CAPOLICY_EXTENSION,
  790. S_OK == hr || L'\0' == wszValue[0]? NULL : wszValue,
  791. NULL,
  792. NULL);
  793. return(hr);
  794. }
  795. //+------------------------------------------------------------------------
  796. // myInfGetPolicyStatementExtension -- build policy extension from INF file
  797. //
  798. // [PolicyStatementExtension]
  799. // Policies = LegalPolicy, LimitedUsePolicy, ExtraPolicy
  800. // ...
  801. //
  802. // OR
  803. //
  804. // [CAPolicy]
  805. // Policies = LegalPolicy, LimitedUsePolicy, ExtraPolicy
  806. // ...
  807. //
  808. // Return S_OK if extension has been constructed from the INF file
  809. // Return S_FALSE if empty section detected in INF file
  810. // Return other error if no section detected in INF file
  811. //-------------------------------------------------------------------------
  812. FNMYINFGETEXTENSION myInfGetPolicyStatementExtension;
  813. HRESULT
  814. myInfGetPolicyStatementExtension(
  815. IN HINF hInf,
  816. OUT CERT_EXTENSION *pext)
  817. {
  818. HRESULT hr;
  819. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  820. {
  821. hr = E_HANDLE;
  822. _JumpError2(hr, error, "hInf", hr);
  823. }
  824. myInfClearError();
  825. hr = infGetPolicyStatementExtensionSub(
  826. hInf,
  827. wszINFSECTION_POLICYSTATEMENT,
  828. szOID_CERT_POLICIES,
  829. pext);
  830. if (S_OK != hr)
  831. {
  832. HRESULT hr2;
  833. hr2 = infGetPolicyStatementExtensionSub(
  834. hInf,
  835. wszINFSECTION_CAPOLICY,
  836. szOID_CERT_POLICIES,
  837. pext);
  838. if (S_FALSE == hr2 && (HRESULT) ERROR_LINE_NOT_FOUND == hr)
  839. {
  840. hr = hr2;
  841. }
  842. }
  843. _JumpIfErrorStr3(
  844. hr,
  845. error,
  846. "infGetPolicyStatementExtensionSub",
  847. wszINFSECTION_POLICYSTATEMENT,
  848. ERROR_LINE_NOT_FOUND,
  849. S_FALSE);
  850. error:
  851. DBGPRINT((
  852. DBG_SS_CERTLIBI,
  853. "myInfGetPolicyStatementExtension hr=%x --> f=%d, cb=%x\n",
  854. hr,
  855. pext->fCritical,
  856. pext->Value.cbData));
  857. return(hr);
  858. }
  859. //+------------------------------------------------------------------------
  860. // myInfGetApplicationPolicyStatementExtension -- build application policy
  861. // extension from INF file
  862. //
  863. // [ApplicationPolicyStatementExtension]
  864. // Policies = LegalPolicy, LimitedUsePolicy, ExtraPolicy
  865. // ...
  866. //
  867. // Return S_OK if extension has been constructed from the INF file
  868. // Return S_FALSE if empty section detected in INF file
  869. // Return other error if no section detected in INF file
  870. //-------------------------------------------------------------------------
  871. FNMYINFGETEXTENSION myInfGetApplicationPolicyStatementExtension;
  872. HRESULT
  873. myInfGetApplicationPolicyStatementExtension(
  874. IN HINF hInf,
  875. OUT CERT_EXTENSION *pext)
  876. {
  877. HRESULT hr;
  878. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  879. {
  880. hr = E_HANDLE;
  881. _JumpError2(hr, error, "hInf", hr);
  882. }
  883. myInfClearError();
  884. hr = infGetPolicyStatementExtensionSub(
  885. hInf,
  886. wszINFSECTION_APPLICATIONPOLICYSTATEMENT,
  887. szOID_APPLICATION_CERT_POLICIES,
  888. pext);
  889. _JumpIfErrorStr3(
  890. hr,
  891. error,
  892. "infGetPolicyStatementExtensionSub",
  893. wszINFSECTION_APPLICATIONPOLICYSTATEMENT,
  894. S_FALSE,
  895. ERROR_LINE_NOT_FOUND);
  896. error:
  897. DBGPRINT((
  898. DBG_SS_CERTLIBI,
  899. "myInfGetApplicationPolicyStatementExtension hr=%x --> f=%d, cb=%x\n",
  900. hr,
  901. pext->fCritical,
  902. pext->Value.cbData));
  903. return(hr);
  904. }
  905. HRESULT
  906. infGetCurrentKeyValue(
  907. IN OUT INFCONTEXT *pInfContext,
  908. IN DWORD Index,
  909. OUT WCHAR **ppwszValue)
  910. {
  911. HRESULT hr;
  912. WCHAR wszValue[1024];
  913. *ppwszValue = NULL;
  914. wszValue[0] = L'\0';
  915. if (!SetupGetStringField(
  916. pInfContext,
  917. Index,
  918. wszValue,
  919. ARRAYSIZE(wszValue),
  920. NULL))
  921. {
  922. hr = myHLastError();
  923. _JumpError(hr, error, "SetupGetStringField");
  924. }
  925. hr = myDupString(wszValue, ppwszValue);
  926. _JumpIfError(hr, error, "myDupString");
  927. error:
  928. return(hr);
  929. }
  930. HRESULT
  931. myinfGetCRLPublicationParams(
  932. IN HINF hInf,
  933. IN LPCWSTR szInfSection_CRLPeriod,
  934. IN LPCWSTR szInfSection_CRLCount,
  935. OUT LPWSTR* ppwszCRLPeriod,
  936. OUT DWORD* pdwCRLCount)
  937. {
  938. HRESULT hr;
  939. // Retrieve units count and string. If either fails, both are discarded.
  940. *ppwszCRLPeriod = NULL;
  941. hr = myInfGetNumericKeyValue(
  942. hInf,
  943. FALSE,
  944. wszINFSECTION_CERTSERVER,
  945. szInfSection_CRLCount,
  946. pdwCRLCount);
  947. _JumpIfErrorStr2(
  948. hr,
  949. error,
  950. "myInfGetNumericKeyValue",
  951. szInfSection_CRLCount,
  952. ERROR_LINE_NOT_FOUND);
  953. hr = myInfGetKeyValue(
  954. hInf,
  955. FALSE,
  956. wszINFSECTION_CERTSERVER,
  957. szInfSection_CRLPeriod,
  958. ppwszCRLPeriod);
  959. _JumpIfErrorStr2(
  960. hr,
  961. error,
  962. "myInfGetKeyValue",
  963. szInfSection_CRLPeriod,
  964. ERROR_LINE_NOT_FOUND);
  965. error:
  966. return hr;
  967. }
  968. //+------------------------------------------------------------------------
  969. // myInfGetKeyValue -- fetch a string value from INF file
  970. //
  971. // [pwszSection]
  972. // pwszKey = string
  973. //
  974. // Returns: allocated string key value
  975. //-------------------------------------------------------------------------
  976. HRESULT
  977. myInfGetKeyValue(
  978. IN HINF hInf,
  979. IN BOOL fLog,
  980. IN WCHAR const *pwszSection,
  981. IN WCHAR const *pwszKey,
  982. OUT WCHAR **ppwszValue)
  983. {
  984. HRESULT hr;
  985. INFCONTEXT InfContext;
  986. WCHAR *pwszValue = NULL;
  987. WCHAR *pwszT = NULL;
  988. *ppwszValue = NULL;
  989. myInfClearError();
  990. CSASSERT(NULL != hInf && INVALID_HANDLE_VALUE != hInf);
  991. hr = infSetupFindFirstLine(hInf, pwszSection, pwszKey, &InfContext);
  992. if (S_OK != hr)
  993. {
  994. if (fLog)
  995. {
  996. CSILOG(hr, IDS_ILOG_CAPOLICY_NOKEY, pwszSection, pwszKey, NULL);
  997. }
  998. _JumpErrorStr2(
  999. hr,
  1000. error,
  1001. "infSetupFindFirstLine",
  1002. pwszKey,
  1003. ERROR_LINE_NOT_FOUND);
  1004. }
  1005. hr = infGetCurrentKeyValue(&InfContext, 1, &pwszValue);
  1006. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  1007. while (TRUE)
  1008. {
  1009. DWORD cwc;
  1010. WCHAR *pwsz;
  1011. if (!SetupFindNextLine(&InfContext, &InfContext))
  1012. {
  1013. break;
  1014. }
  1015. hr = infGetCurrentKeyValue(&InfContext, 0, &pwszT);
  1016. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  1017. if (0 != lstrcmpi(wszINFKEY_CONTINUE, pwszT))
  1018. {
  1019. break;
  1020. }
  1021. LocalFree(pwszT);
  1022. pwszT = NULL;
  1023. hr = infGetCurrentKeyValue(&InfContext, 1, &pwszT);
  1024. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  1025. cwc = wcslen(pwszValue) + wcslen(pwszT);
  1026. pwsz = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR));
  1027. if (NULL == pwsz)
  1028. {
  1029. hr = E_OUTOFMEMORY;
  1030. _JumpError(hr, error, "LocalAlloc");
  1031. }
  1032. wcscpy(pwsz, pwszValue);
  1033. wcscat(pwsz, pwszT);
  1034. LocalFree(pwszValue);
  1035. pwszValue = pwsz;
  1036. LocalFree(pwszT);
  1037. pwszT = NULL;
  1038. }
  1039. *ppwszValue = pwszValue;
  1040. pwszValue = NULL;
  1041. hr = S_OK;
  1042. //wprintf(L"%ws = %ws\n", pwszKey, *ppwszValue);
  1043. error:
  1044. if (NULL != pwszValue)
  1045. {
  1046. LocalFree(pwszValue);
  1047. }
  1048. if (NULL != pwszT)
  1049. {
  1050. LocalFree(pwszT);
  1051. }
  1052. if (S_OK != hr && fLog)
  1053. {
  1054. INFSETERROR(hr, pwszSection, pwszKey, NULL);
  1055. }
  1056. return(hr);
  1057. }
  1058. //+------------------------------------------------------------------------
  1059. // myInfGetNumericKeyValue -- fetch a numeric value from INF file
  1060. //
  1061. // [pwszSection]
  1062. // pwszKey = 2048
  1063. //
  1064. // Returns: DWORD key value
  1065. //-------------------------------------------------------------------------
  1066. HRESULT
  1067. myInfGetNumericKeyValue(
  1068. IN HINF hInf,
  1069. IN BOOL fLog,
  1070. IN WCHAR const *pwszSection,
  1071. IN WCHAR const *pwszKey,
  1072. OUT DWORD *pdwValue)
  1073. {
  1074. HRESULT hr;
  1075. INFCONTEXT InfContext;
  1076. INT Value;
  1077. myInfClearError();
  1078. CSASSERT(NULL != hInf && INVALID_HANDLE_VALUE != hInf);
  1079. if (!SetupFindFirstLine(hInf, pwszSection, pwszKey, &InfContext))
  1080. {
  1081. hr = myHLastError();
  1082. if (fLog)
  1083. {
  1084. CSILOG(hr, IDS_ILOG_CAPOLICY_NOKEY, pwszSection, pwszKey, NULL);
  1085. }
  1086. _PrintErrorStr2(
  1087. hr,
  1088. "SetupFindFirstLine",
  1089. pwszKey,
  1090. ERROR_LINE_NOT_FOUND);
  1091. _JumpErrorStr2(
  1092. hr,
  1093. error,
  1094. "SetupFindFirstLine",
  1095. pwszSection,
  1096. ERROR_LINE_NOT_FOUND);
  1097. }
  1098. if (!SetupGetIntField(&InfContext, 1, &Value))
  1099. {
  1100. hr = myHLastError();
  1101. if (fLog)
  1102. {
  1103. CSILOG(hr, IDS_ILOG_BAD_NUMERICFIELD, pwszSection, pwszKey, NULL);
  1104. }
  1105. _JumpErrorStr(hr, error, "SetupGetIntField", pwszKey);
  1106. }
  1107. *pdwValue = Value;
  1108. DBGPRINT((DBG_SS_CERTLIBI, "%ws = %u\n", pwszKey, *pdwValue));
  1109. hr = S_OK;
  1110. error:
  1111. if (S_OK != hr && fLog)
  1112. {
  1113. INFSETERROR(hr, pwszSection, pwszKey, NULL);
  1114. }
  1115. return(hr);
  1116. }
  1117. //+------------------------------------------------------------------------
  1118. // myInfGetKeyLength -- fetch the renewal key length from CAPolicy.inf
  1119. //
  1120. // [certsrv_server]
  1121. // RenewalKeyLength = 2048
  1122. //
  1123. // Returns: DWORD key kength
  1124. //-------------------------------------------------------------------------
  1125. HRESULT
  1126. myInfGetKeyLength(
  1127. IN HINF hInf,
  1128. OUT DWORD *pdwKeyLength)
  1129. {
  1130. HRESULT hr;
  1131. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  1132. {
  1133. hr = E_HANDLE;
  1134. _JumpError2(hr, error, "hInf", hr);
  1135. }
  1136. myInfClearError();
  1137. hr = myInfGetNumericKeyValue(
  1138. hInf,
  1139. TRUE, // fLog
  1140. wszINFSECTION_CERTSERVER,
  1141. wszINFKEY_RENEWALKEYLENGTH,
  1142. pdwKeyLength);
  1143. _JumpIfErrorStr2(
  1144. hr,
  1145. error,
  1146. "myInfGetNumericKeyValue",
  1147. wszINFKEY_RENEWALKEYLENGTH,
  1148. ERROR_LINE_NOT_FOUND);
  1149. error:
  1150. DBGPRINT((
  1151. DBG_SS_CERTLIBI,
  1152. "myInfGetKeyLength hr=%x --> len=%x\n",
  1153. hr,
  1154. *pdwKeyLength));
  1155. return(hr);
  1156. }
  1157. //+------------------------------------------------------------------------
  1158. // infGetValidityPeriodSub -- fetch validity period & units from CAPolicy.inf
  1159. //
  1160. // [certsrv_server]
  1161. // xxxxValidityPeriod = 8 (count)
  1162. // xxxxValidityPeriodUnits = Years (string)
  1163. //
  1164. // Returns: validity period count and enum
  1165. //-------------------------------------------------------------------------
  1166. HRESULT
  1167. infGetValidityPeriodSub(
  1168. IN HINF hInf,
  1169. IN BOOL fLog,
  1170. IN WCHAR const *pwszInfKeyNameCount,
  1171. IN WCHAR const *pwszInfKeyNameString,
  1172. OPTIONAL IN WCHAR const *pwszValidityPeriodCount,
  1173. OPTIONAL IN WCHAR const *pwszValidityPeriodString,
  1174. OUT DWORD *pdwValidityPeriodCount,
  1175. OUT ENUM_PERIOD *penumValidityPeriod)
  1176. {
  1177. HRESULT hr;
  1178. INFCONTEXT InfContext;
  1179. WCHAR *pwszStringValue = NULL;
  1180. BOOL fValidCount = TRUE;
  1181. UINT idsLog = IDS_ILOG_BAD_VALIDITY_STRING;
  1182. *pdwValidityPeriodCount = 0;
  1183. *penumValidityPeriod = ENUM_PERIOD_INVALID;
  1184. if (NULL == pwszValidityPeriodCount && NULL == pwszValidityPeriodString)
  1185. {
  1186. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  1187. {
  1188. hr = E_HANDLE;
  1189. _JumpError2(hr, error, "hInf", hr);
  1190. }
  1191. hr = myInfGetNumericKeyValue(
  1192. hInf,
  1193. fLog,
  1194. wszINFSECTION_CERTSERVER,
  1195. pwszInfKeyNameCount,
  1196. pdwValidityPeriodCount);
  1197. _JumpIfErrorStr2(
  1198. hr,
  1199. error,
  1200. "myInfGetNumericKeyValue",
  1201. pwszInfKeyNameCount,
  1202. ERROR_LINE_NOT_FOUND);
  1203. hr = myInfGetKeyValue(
  1204. hInf,
  1205. fLog,
  1206. wszINFSECTION_CERTSERVER,
  1207. pwszInfKeyNameString,
  1208. &pwszStringValue);
  1209. if (S_OK != hr && fLog)
  1210. {
  1211. INFSETERROR(hr, wszINFSECTION_CERTSERVER, pwszInfKeyNameString, NULL);
  1212. }
  1213. _JumpIfErrorStr(hr, error, "myInfGetKeyValue", pwszInfKeyNameString);
  1214. pwszValidityPeriodString = pwszStringValue;
  1215. }
  1216. else
  1217. {
  1218. if (NULL != pwszValidityPeriodCount)
  1219. {
  1220. *pdwValidityPeriodCount = myWtoI(
  1221. pwszValidityPeriodCount,
  1222. &fValidCount);
  1223. }
  1224. idsLog = IDS_ILOG_BAD_VALIDITY_STRING_UNATTEND;
  1225. }
  1226. DBGPRINT((
  1227. DBG_SS_CERTLIBI,
  1228. "%ws = %u -- %ws = %ws\n",
  1229. pwszInfKeyNameCount,
  1230. *pdwValidityPeriodCount,
  1231. pwszInfKeyNameString,
  1232. pwszValidityPeriodString));
  1233. if (NULL != pwszValidityPeriodString)
  1234. {
  1235. if (0 == lstrcmpi(wszPERIODYEARS, pwszValidityPeriodString))
  1236. {
  1237. *penumValidityPeriod = ENUM_PERIOD_YEARS;
  1238. }
  1239. else if (0 == lstrcmpi(wszPERIODMONTHS, pwszValidityPeriodString))
  1240. {
  1241. *penumValidityPeriod = ENUM_PERIOD_MONTHS;
  1242. }
  1243. else if (0 == lstrcmpi(wszPERIODWEEKS, pwszValidityPeriodString))
  1244. {
  1245. *penumValidityPeriod = ENUM_PERIOD_WEEKS;
  1246. }
  1247. else if (0 == lstrcmpi(wszPERIODDAYS, pwszValidityPeriodString))
  1248. {
  1249. *penumValidityPeriod = ENUM_PERIOD_DAYS;
  1250. }
  1251. else if (fLog)
  1252. {
  1253. INFSETERROR(
  1254. hr,
  1255. wszINFSECTION_CERTSERVER,
  1256. pwszInfKeyNameString,
  1257. pwszValidityPeriodString);
  1258. }
  1259. }
  1260. DBGPRINT((
  1261. DBG_SS_CERTLIBI,
  1262. "%ws = %u (%ws)\n",
  1263. pwszInfKeyNameString,
  1264. *penumValidityPeriod,
  1265. pwszValidityPeriodString));
  1266. if (!fValidCount ||
  1267. (ENUM_PERIOD_YEARS == *penumValidityPeriod &&
  1268. fValidCount && 9999 < *pdwValidityPeriodCount))
  1269. {
  1270. hr = E_INVALIDARG;
  1271. if (fLog)
  1272. {
  1273. WCHAR awcCount[20];
  1274. if (NULL == pwszValidityPeriodCount)
  1275. {
  1276. wsprintf(awcCount, L"%d", *pdwValidityPeriodCount);
  1277. }
  1278. INFSETERROR(
  1279. hr,
  1280. wszINFSECTION_CERTSERVER,
  1281. pwszInfKeyNameCount,
  1282. NULL != pwszValidityPeriodCount?
  1283. pwszValidityPeriodCount : awcCount);
  1284. CSILOG(
  1285. hr,
  1286. idsLog,
  1287. wszINFSECTION_CERTSERVER,
  1288. NULL == pwszValidityPeriodCount? pwszInfKeyNameCount : NULL,
  1289. pdwValidityPeriodCount);
  1290. }
  1291. _JumpIfErrorStr(
  1292. hr,
  1293. error,
  1294. "bad ValidityPeriod count value",
  1295. pwszValidityPeriodCount);
  1296. }
  1297. hr = S_OK;
  1298. error:
  1299. if (NULL != pwszStringValue)
  1300. {
  1301. LocalFree(pwszStringValue);
  1302. }
  1303. return(hr);
  1304. }
  1305. //+------------------------------------------------------------------------
  1306. // infGetValidityPeriod -- fetch renewal period & units from CAPolicy.inf
  1307. //
  1308. // [certsrv_server]
  1309. // xxxxValidityPeriod = 8
  1310. // xxxxValidityPeriodUnits = Years
  1311. //
  1312. // Returns: validity period count and enum
  1313. //-------------------------------------------------------------------------
  1314. HRESULT
  1315. myInfGetValidityPeriod(
  1316. IN HINF hInf,
  1317. OPTIONAL IN WCHAR const *pwszValidityPeriodCount,
  1318. OPTIONAL IN WCHAR const *pwszValidityPeriodString,
  1319. OUT DWORD *pdwValidityPeriodCount,
  1320. OUT ENUM_PERIOD *penumValidityPeriod,
  1321. OPTIONAL OUT BOOL *pfSwap)
  1322. {
  1323. HRESULT hr;
  1324. if ((NULL == hInf || INVALID_HANDLE_VALUE == hInf) &&
  1325. NULL == pwszValidityPeriodCount &&
  1326. NULL == pwszValidityPeriodString)
  1327. {
  1328. hr = E_HANDLE;
  1329. _JumpError2(hr, error, "hInf", hr);
  1330. }
  1331. myInfClearError();
  1332. if (NULL != pfSwap)
  1333. {
  1334. *pfSwap = FALSE;
  1335. }
  1336. // Try correct order:
  1337. // [certsrv_server]
  1338. // xxxxValidityPeriod = 8 (count)
  1339. // xxxxValidityPeriodUnits = Years (string)
  1340. hr = infGetValidityPeriodSub(
  1341. hInf,
  1342. TRUE,
  1343. wszINFKEY_RENEWALVALIDITYPERIODCOUNT,
  1344. wszINFKEY_RENEWALVALIDITYPERIODSTRING,
  1345. pwszValidityPeriodCount,
  1346. pwszValidityPeriodString,
  1347. pdwValidityPeriodCount,
  1348. penumValidityPeriod);
  1349. _PrintIfError2(hr, "infGetValidityPeriodSub", ERROR_LINE_NOT_FOUND);
  1350. if (S_OK != hr)
  1351. {
  1352. // Try backwards:
  1353. // [certsrv_server]
  1354. // xxxxValidityPeriodUnits = 8 (count)
  1355. // xxxxValidityPeriod = Years (string)
  1356. hr = infGetValidityPeriodSub(
  1357. hInf,
  1358. FALSE,
  1359. wszINFKEY_RENEWALVALIDITYPERIODSTRING,
  1360. wszINFKEY_RENEWALVALIDITYPERIODCOUNT,
  1361. pwszValidityPeriodString,
  1362. pwszValidityPeriodCount,
  1363. pdwValidityPeriodCount,
  1364. penumValidityPeriod);
  1365. _JumpIfError2(
  1366. hr,
  1367. error,
  1368. "infGetValidityPeriodSub",
  1369. ERROR_LINE_NOT_FOUND);
  1370. if (NULL != pfSwap)
  1371. {
  1372. *pfSwap = TRUE;
  1373. }
  1374. }
  1375. error:
  1376. DBGPRINT((
  1377. DBG_SS_CERTLIBI,
  1378. "myInfGetValidityPeriod hr=%x --> c=%d, enum=%d\n",
  1379. hr,
  1380. *pdwValidityPeriodCount,
  1381. *penumValidityPeriod));
  1382. return(hr);
  1383. }
  1384. HRESULT
  1385. infFindNextKey(
  1386. IN WCHAR const *pwszKey,
  1387. IN OUT INFCONTEXT *pInfContext)
  1388. {
  1389. HRESULT hr;
  1390. DWORD cwc;
  1391. WCHAR wszKey[MAX_PATH];
  1392. while (TRUE)
  1393. {
  1394. if (!SetupFindNextLine(pInfContext, pInfContext))
  1395. {
  1396. hr = myHLastError();
  1397. _PrintErrorStr2(hr, "SetupFindNextLine", pwszKey, hr);
  1398. if ((HRESULT) ERROR_LINE_NOT_FOUND == hr)
  1399. {
  1400. hr = S_FALSE;
  1401. }
  1402. _JumpError2(hr, error, "SetupFindNextLine", hr);
  1403. }
  1404. if (!SetupGetStringField(
  1405. pInfContext,
  1406. 0,
  1407. wszKey,
  1408. ARRAYSIZE(wszKey),
  1409. NULL))
  1410. {
  1411. hr = myHLastError();
  1412. _JumpError(hr, error, "SetupGetStringField");
  1413. }
  1414. if (0 == lstrcmpi(pwszKey, wszKey))
  1415. {
  1416. break;
  1417. }
  1418. }
  1419. hr = S_OK;
  1420. error:
  1421. return(hr);
  1422. }
  1423. //+------------------------------------------------------------------------
  1424. // myInfGetKeyList -- fetch a list of key values from CAPolicy.inf
  1425. //
  1426. // [pwszSection]
  1427. // pwszKey = Value1
  1428. // pwszKey = Value2
  1429. //
  1430. // Returns: double null terminated list of values
  1431. //-------------------------------------------------------------------------
  1432. HRESULT
  1433. myInfGetKeyList(
  1434. IN HINF hInf,
  1435. IN WCHAR const *pwszSection,
  1436. IN WCHAR const *pwszKey,
  1437. OUT BOOL *pfCritical,
  1438. OUT WCHAR **ppwszz)
  1439. {
  1440. HRESULT hr;
  1441. INFCONTEXT InfContext;
  1442. DWORD iVal;
  1443. DWORD cwc;
  1444. WCHAR *pwsz;
  1445. WCHAR **apwszVal = NULL;
  1446. DWORD cVal;
  1447. WCHAR *pwszBuf = NULL;
  1448. DWORD cwcBuf = 0;
  1449. *ppwszz = NULL;
  1450. *pfCritical = FALSE;
  1451. myInfClearError();
  1452. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  1453. {
  1454. hr = E_HANDLE;
  1455. _JumpError2(hr, error, "hInf", hr);
  1456. }
  1457. hr = infSetupFindFirstLine(hInf, pwszSection, pwszKey, &InfContext);
  1458. if (S_OK != hr)
  1459. {
  1460. CSILOG(hr, IDS_ILOG_CAPOLICY_NOKEY, pwszSection, pwszKey, NULL);
  1461. _JumpErrorStr3(
  1462. hr,
  1463. error,
  1464. "infSetupFindFirstLine",
  1465. pwszSection,
  1466. S_FALSE,
  1467. ERROR_LINE_NOT_FOUND);
  1468. }
  1469. cVal = 0;
  1470. while (TRUE)
  1471. {
  1472. if (!SetupGetStringField(&InfContext, 1, NULL, 0, &cwc))
  1473. {
  1474. hr = myHLastError();
  1475. _JumpErrorStr(hr, error, "SetupGetStringField", pwszKey);
  1476. }
  1477. cVal++;
  1478. if (cwcBuf < cwc)
  1479. {
  1480. cwcBuf = cwc;
  1481. }
  1482. hr = infFindNextKey(pwszKey, &InfContext);
  1483. if (S_FALSE == hr)
  1484. {
  1485. break;
  1486. }
  1487. _JumpIfErrorStr(hr, error, "infFindNextKey", pwszKey);
  1488. }
  1489. pwszBuf = (WCHAR *) LocalAlloc(LMEM_FIXED, cwcBuf * sizeof(WCHAR));
  1490. if (NULL == pwszBuf)
  1491. {
  1492. hr = E_OUTOFMEMORY;
  1493. _JumpError(hr, error, "LocalAlloc");
  1494. }
  1495. apwszVal = (WCHAR **) LocalAlloc(
  1496. LMEM_FIXED | LMEM_ZEROINIT,
  1497. cVal * sizeof(apwszVal[0]));
  1498. if (NULL == apwszVal)
  1499. {
  1500. hr = E_OUTOFMEMORY;
  1501. _JumpError(hr, error, "LocalAlloc");
  1502. }
  1503. hr = infSetupFindFirstLine(hInf, pwszSection, pwszKey, &InfContext);
  1504. _JumpIfErrorStr(hr, error, "infSetupFindFirstLine", pwszSection);
  1505. cwc = 1;
  1506. iVal = 0;
  1507. while (TRUE)
  1508. {
  1509. if (!SetupGetStringField(&InfContext, 1, pwszBuf, cwcBuf, NULL))
  1510. {
  1511. hr = myHLastError();
  1512. _JumpErrorStr(hr, error, "SetupGetStringField", pwszKey);
  1513. }
  1514. hr = myDupString(pwszBuf, &apwszVal[iVal]);
  1515. _JumpIfError(hr, error, "myDupString");
  1516. DBGPRINT((DBG_SS_CERTLIBI, "%ws = %ws\n", pwszKey, apwszVal[iVal]));
  1517. cwc += wcslen(apwszVal[iVal]) + 1;
  1518. iVal++;
  1519. hr = infFindNextKey(pwszKey, &InfContext);
  1520. if (S_FALSE == hr)
  1521. {
  1522. break;
  1523. }
  1524. _JumpIfErrorStr(hr, error, "infFindNextKey", pwszKey);
  1525. }
  1526. CSASSERT(iVal == cVal);
  1527. *ppwszz = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  1528. if (NULL == *ppwszz)
  1529. {
  1530. hr = E_OUTOFMEMORY;
  1531. _JumpError(hr, error, "LocalAlloc");
  1532. }
  1533. pwsz = *ppwszz;
  1534. for (iVal = 0; iVal < cVal; iVal++)
  1535. {
  1536. wcscpy(pwsz, apwszVal[iVal]);
  1537. pwsz += wcslen(pwsz) + 1;
  1538. }
  1539. *pwsz = L'\0';
  1540. CSASSERT(cwc == 1 + SAFE_SUBTRACT_POINTERS(pwsz, *ppwszz));
  1541. if (NULL != pfCritical)
  1542. {
  1543. hr = infGetCriticalFlag(hInf, pwszSection, FALSE, pfCritical);
  1544. _JumpIfError(hr, error, "infGetCriticalFlag");
  1545. }
  1546. hr = S_OK;
  1547. error:
  1548. if (S_OK != hr)
  1549. {
  1550. INFSETERROR(hr, pwszSection, pwszKey, NULL);
  1551. }
  1552. if (NULL != apwszVal)
  1553. {
  1554. for (iVal = 0; iVal < cVal; iVal++)
  1555. {
  1556. if (NULL != apwszVal[iVal])
  1557. {
  1558. LocalFree(apwszVal[iVal]);
  1559. }
  1560. }
  1561. LocalFree(apwszVal);
  1562. }
  1563. if (NULL != pwszBuf)
  1564. {
  1565. LocalFree(pwszBuf);
  1566. }
  1567. return(hr);
  1568. }
  1569. //+------------------------------------------------------------------------
  1570. // myInfGetCRLDistributionPoints -- fetch CDP URLs from CAPolicy.inf
  1571. //
  1572. // [CRLDistributionPoint]
  1573. // URL = http://CRLhttp.site.com/Public/MyCA.crl
  1574. // URL = ftp://CRLftp.site.com/Public/MyCA.crl
  1575. //
  1576. // Returns: double null terminated list of CDP URLs
  1577. //-------------------------------------------------------------------------
  1578. HRESULT
  1579. myInfGetCRLDistributionPoints(
  1580. IN HINF hInf,
  1581. OUT BOOL *pfCritical,
  1582. OUT WCHAR **ppwszz)
  1583. {
  1584. HRESULT hr;
  1585. hr = myInfGetKeyList(
  1586. hInf,
  1587. wszINFSECTION_CDP,
  1588. wszINFKEY_URL,
  1589. pfCritical,
  1590. ppwszz);
  1591. _JumpIfErrorStr4(
  1592. hr,
  1593. error,
  1594. "myInfGetKeyList",
  1595. wszINFSECTION_CDP,
  1596. ERROR_LINE_NOT_FOUND,
  1597. S_FALSE,
  1598. E_HANDLE);
  1599. error:
  1600. DBGPRINT((
  1601. DBG_SS_CERTLIBI,
  1602. "myInfGetCRLDistributionPoints hr=%x --> f=%d\n",
  1603. hr,
  1604. *pfCritical));
  1605. return(hr);
  1606. }
  1607. //+------------------------------------------------------------------------
  1608. // myInfGetAuthorityInformationAccess -- fetch AIA URLs from CAPolicy.inf
  1609. //
  1610. // [AuthorityInformationAccess]
  1611. // URL = http://CRThttp.site.com/Public/MyCA.crt
  1612. // URL = ftp://CRTftp.site.com/Public/MyCA.crt
  1613. //
  1614. // Returns: double null terminated list of AIA URLs
  1615. //-------------------------------------------------------------------------
  1616. HRESULT
  1617. myInfGetAuthorityInformationAccess(
  1618. IN HINF hInf,
  1619. OUT BOOL *pfCritical,
  1620. OUT WCHAR **ppwszz)
  1621. {
  1622. HRESULT hr;
  1623. hr = myInfGetKeyList(
  1624. hInf,
  1625. wszINFSECTION_AIA,
  1626. wszINFKEY_URL,
  1627. pfCritical,
  1628. ppwszz);
  1629. _JumpIfErrorStr4(
  1630. hr,
  1631. error,
  1632. "myInfGetKeyList",
  1633. wszINFSECTION_AIA,
  1634. ERROR_LINE_NOT_FOUND,
  1635. S_FALSE,
  1636. E_HANDLE);
  1637. error:
  1638. DBGPRINT((
  1639. DBG_SS_CERTLIBI,
  1640. "myInfGetAuthorityInformationAccess hr=%x --> f=%d\n",
  1641. hr,
  1642. *pfCritical));
  1643. return(hr);
  1644. }
  1645. //+------------------------------------------------------------------------
  1646. // myInfGetEnhancedKeyUsage -- fetch EKU OIDS from CAPolicy.inf
  1647. //
  1648. // [EnhancedKeyUsage]
  1649. // OID = 1.2.3.4.5
  1650. // OID = 1.2.3.4.6
  1651. //
  1652. // Returns: double null terminated list of EKU OIDs
  1653. //-------------------------------------------------------------------------
  1654. HRESULT
  1655. myInfGetEnhancedKeyUsage(
  1656. IN HINF hInf,
  1657. OUT BOOL *pfCritical,
  1658. OUT WCHAR **ppwszz)
  1659. {
  1660. HRESULT hr;
  1661. hr = myInfGetKeyList(
  1662. hInf,
  1663. wszINFSECTION_EKU,
  1664. wszINFKEY_OID,
  1665. pfCritical,
  1666. ppwszz);
  1667. _JumpIfErrorStr4(
  1668. hr,
  1669. error,
  1670. "myInfGetKeyList",
  1671. wszINFSECTION_EKU,
  1672. ERROR_LINE_NOT_FOUND,
  1673. S_FALSE,
  1674. E_HANDLE);
  1675. error:
  1676. DBGPRINT((
  1677. DBG_SS_CERTLIBI,
  1678. "myInfGetEnhancedKeyUsage hr=%x --> f=%d\n",
  1679. hr,
  1680. *pfCritical));
  1681. return(hr);
  1682. }
  1683. //+--------------------------------------------------------------------------
  1684. // infGetBasicConstraints2CAExtension -- fetch basic constraints extension
  1685. // from INF file, setting the SubjectType flag to CA
  1686. //
  1687. // If the INF handle is bad, or if the INF section does not exist, construct
  1688. // a default extension only if fDefault is set, otherwise fail.
  1689. //
  1690. // [BasicConstraintsExtension]
  1691. // ; Subject Type is not supported -- always set to CA
  1692. // ; maximum subordinate CA path length
  1693. // PathLength = 3
  1694. //
  1695. // Return S_OK if extension has been constructed from INF file.
  1696. //
  1697. // Returns: encoded basic constraints extension
  1698. //+--------------------------------------------------------------------------
  1699. HRESULT
  1700. infGetBasicConstraints2CAExtension(
  1701. IN BOOL fDefault,
  1702. IN HINF hInf,
  1703. OUT CERT_EXTENSION *pext)
  1704. {
  1705. HRESULT hr;
  1706. CERT_BASIC_CONSTRAINTS2_INFO bc2i;
  1707. INFCONTEXT InfContext;
  1708. ZeroMemory(pext, sizeof(*pext));
  1709. ZeroMemory(&bc2i, sizeof(bc2i));
  1710. myInfClearError();
  1711. pext->fCritical = TRUE; // default value for both INF and default cases
  1712. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  1713. {
  1714. if (!fDefault)
  1715. {
  1716. hr = E_HANDLE;
  1717. _JumpError2(hr, error, "hInf", hr);
  1718. }
  1719. }
  1720. else
  1721. {
  1722. hr = infSetupFindFirstLine(
  1723. hInf,
  1724. wszINFSECTION_BASICCONSTRAINTS,
  1725. NULL,
  1726. &InfContext);
  1727. if (S_OK != hr)
  1728. {
  1729. if (!fDefault)
  1730. {
  1731. _JumpErrorStr3(
  1732. hr,
  1733. error,
  1734. "infSetupFindFirstLine",
  1735. wszINFSECTION_BASICCONSTRAINTS,
  1736. S_FALSE,
  1737. ERROR_LINE_NOT_FOUND);
  1738. }
  1739. }
  1740. else
  1741. {
  1742. hr = infGetCriticalFlag(
  1743. hInf,
  1744. wszINFSECTION_BASICCONSTRAINTS,
  1745. pext->fCritical, // fDefault
  1746. &pext->fCritical);
  1747. _JumpIfError(hr, error, "infGetCriticalFlag");
  1748. bc2i.fPathLenConstraint = TRUE;
  1749. hr = myInfGetNumericKeyValue(
  1750. hInf,
  1751. TRUE, // fLog
  1752. wszINFSECTION_BASICCONSTRAINTS,
  1753. wszINFKEY_PATHLENGTH,
  1754. &bc2i.dwPathLenConstraint);
  1755. if (S_OK != hr)
  1756. {
  1757. _PrintErrorStr2(
  1758. hr,
  1759. "myInfGetNumericKeyValue",
  1760. wszINFKEY_PATHLENGTH,
  1761. ERROR_LINE_NOT_FOUND);
  1762. if ((HRESULT) ERROR_LINE_NOT_FOUND != hr)
  1763. {
  1764. goto error;
  1765. }
  1766. bc2i.dwPathLenConstraint = 0;
  1767. bc2i.fPathLenConstraint = FALSE;
  1768. }
  1769. }
  1770. }
  1771. bc2i.fCA = TRUE;
  1772. if (!myEncodeObject(
  1773. X509_ASN_ENCODING,
  1774. X509_BASIC_CONSTRAINTS2,
  1775. &bc2i,
  1776. 0,
  1777. CERTLIB_USE_LOCALALLOC,
  1778. &pext->Value.pbData,
  1779. &pext->Value.cbData))
  1780. {
  1781. hr = myHLastError();
  1782. _JumpError(hr, error, "myEncodeObject");
  1783. }
  1784. hr = S_OK;
  1785. error:
  1786. if (S_OK != hr)
  1787. {
  1788. INFSETERROR(hr, wszINFSECTION_BASICCONSTRAINTS, NULL, NULL);
  1789. }
  1790. pext->pszObjId = szOID_BASIC_CONSTRAINTS2; // on error, too!
  1791. DBGPRINT((
  1792. DBG_SS_CERTLIBI,
  1793. "myInfGetBasicConstraints2CAExtension hr=%x --> f=%d, cb=%x\n",
  1794. hr,
  1795. pext->fCritical,
  1796. pext->Value.cbData));
  1797. return(hr);
  1798. }
  1799. //+--------------------------------------------------------------------------
  1800. // myInfGetBasicConstraints2CAExtension -- fetch basic constraints extension
  1801. // from INF file, setting the SubjectType flag to CA
  1802. //
  1803. // [BasicConstraintsExtension]
  1804. // ; Subject Type is not supported -- always set to CA
  1805. // ; maximum subordinate CA path length
  1806. // PathLength = 3
  1807. //
  1808. // Return S_OK if extension has been constructed from INF file.
  1809. //
  1810. // Returns: encoded basic constraints extension
  1811. //+--------------------------------------------------------------------------
  1812. FNMYINFGETEXTENSION myInfGetBasicConstraints2CAExtension;
  1813. HRESULT
  1814. myInfGetBasicConstraints2CAExtension(
  1815. IN HINF hInf,
  1816. OUT CERT_EXTENSION *pext)
  1817. {
  1818. HRESULT hr;
  1819. hr = infGetBasicConstraints2CAExtension(FALSE, hInf, pext);
  1820. _JumpIfError3(
  1821. hr,
  1822. error,
  1823. "infGetBasicConstraints2CAExtension",
  1824. S_FALSE,
  1825. ERROR_LINE_NOT_FOUND);
  1826. error:
  1827. return(hr);
  1828. }
  1829. FNMYINFGETEXTENSION myInfGetBasicConstraints2CAExtensionOrDefault;
  1830. HRESULT
  1831. myInfGetBasicConstraints2CAExtensionOrDefault(
  1832. IN HINF hInf,
  1833. OUT CERT_EXTENSION *pext)
  1834. {
  1835. HRESULT hr;
  1836. hr = infGetBasicConstraints2CAExtension(TRUE, hInf, pext);
  1837. _JumpIfError(hr, error, "infGetBasicConstraints2CAExtension");
  1838. error:
  1839. return(hr);
  1840. }
  1841. //+--------------------------------------------------------------------------
  1842. // myInfGetEnhancedKeyUsageExtension -- fetch EKU extension from INF file
  1843. //
  1844. // [EnhancedKeyUsageExtension]
  1845. // OID = 1.2.3.4.5
  1846. // OID = 1.2.3.4.6
  1847. //
  1848. // Return S_OK if extension has been constructed from INF file.
  1849. // Return S_FALSE if empty section detected in INF file
  1850. // Return other error if no section detected in INF file
  1851. //
  1852. // Returns: encoded enhanced key usage extension
  1853. //+--------------------------------------------------------------------------
  1854. FNMYINFGETEXTENSION myInfGetEnhancedKeyUsageExtension;
  1855. HRESULT
  1856. myInfGetEnhancedKeyUsageExtension(
  1857. IN HINF hInf,
  1858. OUT CERT_EXTENSION *pext)
  1859. {
  1860. HRESULT hr;
  1861. DWORD i;
  1862. DWORD cEKU = 0;
  1863. WCHAR *pwszzEKU = NULL;
  1864. WCHAR *pwszCurrentEKU;
  1865. CERT_ENHKEY_USAGE ceku;
  1866. ceku.rgpszUsageIdentifier = NULL;
  1867. ZeroMemory(pext, sizeof(*pext));
  1868. myInfClearError();
  1869. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  1870. {
  1871. hr = E_HANDLE;
  1872. _JumpError2(hr, error, "hInf", hr);
  1873. }
  1874. hr = myInfGetEnhancedKeyUsage(hInf, &pext->fCritical, &pwszzEKU);
  1875. _JumpIfError3(
  1876. hr,
  1877. error,
  1878. "myInfGetEnhancedKeyUsage",
  1879. S_FALSE,
  1880. ERROR_LINE_NOT_FOUND);
  1881. pwszCurrentEKU = pwszzEKU;
  1882. if (NULL != pwszCurrentEKU)
  1883. {
  1884. while (L'\0' != *pwszCurrentEKU)
  1885. {
  1886. cEKU++;
  1887. pwszCurrentEKU += wcslen(pwszCurrentEKU) + 1;
  1888. }
  1889. }
  1890. if (0 == cEKU)
  1891. {
  1892. hr = S_FALSE;
  1893. goto error;
  1894. }
  1895. ceku.cUsageIdentifier = cEKU;
  1896. ceku.rgpszUsageIdentifier = (char **) LocalAlloc(
  1897. LMEM_FIXED | LMEM_ZEROINIT,
  1898. sizeof(ceku.rgpszUsageIdentifier[0]) * cEKU);
  1899. if (NULL == ceku.rgpszUsageIdentifier)
  1900. {
  1901. hr = E_OUTOFMEMORY;
  1902. _JumpIfError(hr, error, "LocalAlloc");
  1903. }
  1904. cEKU = 0;
  1905. pwszCurrentEKU = pwszzEKU;
  1906. while (L'\0' != *pwszCurrentEKU)
  1907. {
  1908. if (!ConvertWszToSz(&ceku.rgpszUsageIdentifier[cEKU], pwszCurrentEKU, -1))
  1909. {
  1910. hr = E_OUTOFMEMORY;
  1911. _JumpError(hr, error, "ConvertWszToSz");
  1912. }
  1913. cEKU++;
  1914. pwszCurrentEKU += wcslen(pwszCurrentEKU) + 1;
  1915. }
  1916. CSASSERT(ceku.cUsageIdentifier == cEKU);
  1917. if (!myEncodeObject(
  1918. X509_ASN_ENCODING,
  1919. X509_ENHANCED_KEY_USAGE,
  1920. &ceku,
  1921. 0,
  1922. CERTLIB_USE_LOCALALLOC,
  1923. &pext->Value.pbData,
  1924. &pext->Value.cbData))
  1925. {
  1926. hr = myHLastError();
  1927. _JumpIfError(hr, error, "myEncodeObject");
  1928. }
  1929. error:
  1930. if (S_OK != hr && E_HANDLE != hr)
  1931. {
  1932. INFSETERROR(hr, wszINFSECTION_EKU, NULL, NULL);
  1933. }
  1934. pext->pszObjId = szOID_ENHANCED_KEY_USAGE; // on error, too!
  1935. DBGPRINT((
  1936. DBG_SS_CERTLIBI,
  1937. "myInfGetEnhancedKeyUsageExtension hr=%x --> f=%d, cb=%x\n",
  1938. hr,
  1939. pext->fCritical,
  1940. pext->Value.cbData));
  1941. if (NULL != ceku.rgpszUsageIdentifier)
  1942. {
  1943. for (i = 0; i < ceku.cUsageIdentifier; i++)
  1944. {
  1945. if (NULL != ceku.rgpszUsageIdentifier[i])
  1946. {
  1947. LocalFree(ceku.rgpszUsageIdentifier[i]);
  1948. }
  1949. }
  1950. LocalFree(ceku.rgpszUsageIdentifier);
  1951. }
  1952. if (NULL != pwszzEKU)
  1953. {
  1954. LocalFree(pwszzEKU);
  1955. }
  1956. return(hr);
  1957. }
  1958. HRESULT
  1959. infAddAttribute(
  1960. IN CRYPT_ATTR_BLOB const *pAttribute,
  1961. IN OUT DWORD *pcAttribute,
  1962. IN OUT CRYPT_ATTR_BLOB **ppaAttribute)
  1963. {
  1964. HRESULT hr;
  1965. CRYPT_ATTR_BLOB *pAttribT;
  1966. if (NULL == *ppaAttribute)
  1967. {
  1968. CSASSERT(0 == *pcAttribute);
  1969. pAttribT = (CRYPT_ATTR_BLOB *) LocalAlloc(
  1970. LMEM_FIXED,
  1971. sizeof(**ppaAttribute));
  1972. }
  1973. else
  1974. {
  1975. CSASSERT(0 != *pcAttribute);
  1976. pAttribT = (CRYPT_ATTR_BLOB *) LocalReAlloc(
  1977. *ppaAttribute,
  1978. (*pcAttribute + 1) * sizeof(**ppaAttribute),
  1979. LMEM_MOVEABLE);
  1980. }
  1981. if (NULL == pAttribT)
  1982. {
  1983. hr = E_OUTOFMEMORY;
  1984. _JumpError(
  1985. hr,
  1986. error,
  1987. NULL == *ppaAttribute? "LocalAlloc" : "LocalReAlloc");
  1988. }
  1989. *ppaAttribute = pAttribT;
  1990. pAttribT[(*pcAttribute)++] = *pAttribute;
  1991. hr = S_OK;
  1992. error:
  1993. return(hr);
  1994. }
  1995. VOID
  1996. myInfFreeRequestAttributes(
  1997. IN DWORD cAttribute,
  1998. IN OUT CRYPT_ATTR_BLOB *paAttribute)
  1999. {
  2000. if (NULL != paAttribute)
  2001. {
  2002. DWORD i;
  2003. for (i = 0; i < cAttribute; i++)
  2004. {
  2005. if (NULL != paAttribute[i].pbData)
  2006. {
  2007. LocalFree(paAttribute[i].pbData);
  2008. }
  2009. }
  2010. LocalFree(paAttribute);
  2011. }
  2012. }
  2013. //+------------------------------------------------------------------------
  2014. // myInfGetRequestAttributes -- fetch request attributes from INF file
  2015. //
  2016. // [RequestAttributes]
  2017. // AttributeName1 = AttributeValue1
  2018. // AttributeName2 = AttributeValue2
  2019. // ...
  2020. // AttributeNameN = AttributeValueN
  2021. //
  2022. // Returns: array of encoded attribute blobs
  2023. //-------------------------------------------------------------------------
  2024. HRESULT
  2025. myInfGetRequestAttributes(
  2026. IN HINF hInf,
  2027. OUT DWORD *pcAttribute,
  2028. OUT CRYPT_ATTR_BLOB **ppaAttribute,
  2029. OUT WCHAR **ppwszTemplateName)
  2030. {
  2031. HRESULT hr;
  2032. INFCONTEXT InfContext;
  2033. WCHAR wszName[MAX_PATH];
  2034. WCHAR wszValue[cwcVALUEMAX];
  2035. DWORD i;
  2036. DWORD cAttribute = 0;
  2037. CRYPT_ATTR_BLOB Attribute;
  2038. WCHAR *pwszTemplateName = NULL;
  2039. *ppwszTemplateName = NULL;
  2040. *pcAttribute = 0;
  2041. *ppaAttribute = NULL;
  2042. Attribute.pbData = NULL;
  2043. wszName[0] = L'\0';
  2044. wszValue[0] = L'\0';
  2045. myInfClearError();
  2046. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  2047. {
  2048. hr = E_HANDLE;
  2049. _JumpError2(hr, error, "hInf", hr);
  2050. }
  2051. hr = infSetupFindFirstLine(
  2052. hInf,
  2053. wszINFSECTION_REQUESTATTRIBUTES,
  2054. NULL, // Key
  2055. &InfContext);
  2056. _JumpIfErrorStr(
  2057. hr,
  2058. error,
  2059. "infSetupFindFirstLine",
  2060. wszINFSECTION_REQUESTATTRIBUTES);
  2061. while (TRUE)
  2062. {
  2063. CRYPT_ENROLLMENT_NAME_VALUE_PAIR NamePair;
  2064. wszName[0] = L'\0';
  2065. wszValue[0] = L'\0';
  2066. if (!SetupGetStringField(
  2067. &InfContext,
  2068. 0,
  2069. wszName,
  2070. ARRAYSIZE(wszName),
  2071. NULL))
  2072. {
  2073. hr = myHLastError();
  2074. _JumpError(hr, error, "SetupGetStringField");
  2075. }
  2076. if (!SetupGetStringField(
  2077. &InfContext,
  2078. 1,
  2079. wszValue,
  2080. ARRAYSIZE(wszValue),
  2081. NULL))
  2082. {
  2083. hr = myHLastError();
  2084. _JumpError(hr, error, "SetupGetStringField");
  2085. }
  2086. //wprintf(L"%ws = %ws\n", wszName, wszValue);
  2087. NamePair.pwszName = wszName;
  2088. NamePair.pwszValue = wszValue;
  2089. if (0 == lstrcmpi(wszPROPCERTTEMPLATE, wszName))
  2090. {
  2091. if (NULL != pwszTemplateName)
  2092. {
  2093. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  2094. _JumpError(hr, error, "Duplicate cert template");
  2095. }
  2096. hr = myDupString(wszValue, &pwszTemplateName);
  2097. _JumpIfError(hr, error, "myDupString");
  2098. }
  2099. if (!myEncodeObject(
  2100. X509_ASN_ENCODING,
  2101. // X509__ENROLLMENT_NAME_VALUE_PAIR
  2102. szOID_ENROLLMENT_NAME_VALUE_PAIR,
  2103. &NamePair,
  2104. 0,
  2105. CERTLIB_USE_LOCALALLOC,
  2106. &Attribute.pbData,
  2107. &Attribute.cbData))
  2108. {
  2109. hr = myHLastError();
  2110. _JumpError(hr, error, "myEncodeObject");
  2111. }
  2112. hr = infAddAttribute(&Attribute, &cAttribute, ppaAttribute);
  2113. _JumpIfError(hr, error, "infAddAttribute");
  2114. Attribute.pbData = NULL;
  2115. if (!SetupFindNextLine(&InfContext, &InfContext))
  2116. {
  2117. hr = myHLastError();
  2118. _PrintError2(hr, "SetupFindNextLine(end)", hr);
  2119. break;
  2120. }
  2121. }
  2122. *pcAttribute = cAttribute;
  2123. cAttribute = 0;
  2124. *ppwszTemplateName = pwszTemplateName;
  2125. pwszTemplateName = NULL;
  2126. hr = S_OK;
  2127. error:
  2128. if (S_OK != hr)
  2129. {
  2130. INFSETERROR(hr, wszINFSECTION_REQUESTATTRIBUTES, wszName, wszValue);
  2131. }
  2132. if (NULL != pwszTemplateName)
  2133. {
  2134. LocalFree(pwszTemplateName);
  2135. }
  2136. if (NULL != Attribute.pbData)
  2137. {
  2138. LocalFree(Attribute.pbData);
  2139. }
  2140. if (0 != cAttribute)
  2141. {
  2142. myInfFreeRequestAttributes(cAttribute, *ppaAttribute);
  2143. *ppaAttribute = NULL;
  2144. }
  2145. DBGPRINT((
  2146. DBG_SS_CERTLIBI,
  2147. "myInfGetRequestAttributes hr=%x --> c=%d\n",
  2148. hr,
  2149. *pcAttribute));
  2150. return(hr);
  2151. }
  2152. typedef struct _SUBTREEINFO
  2153. {
  2154. BOOL fEmptyDefault;
  2155. DWORD dwInfMinMaxIndexBase;
  2156. DWORD dwAltNameChoice;
  2157. WCHAR const *pwszKey;
  2158. } SUBTREEINFO;
  2159. SUBTREEINFO g_aSubTreeInfo[] = {
  2160. { TRUE, 2, CERT_ALT_NAME_OTHER_NAME, wszINFKEY_UPN },
  2161. { TRUE, 2, CERT_ALT_NAME_RFC822_NAME, wszINFKEY_EMAIL },
  2162. { TRUE, 2, CERT_ALT_NAME_DNS_NAME, wszINFKEY_DNS },
  2163. { TRUE, 2, CERT_ALT_NAME_DIRECTORY_NAME, wszINFKEY_DIRECTORYNAME },
  2164. { TRUE, 2, CERT_ALT_NAME_URL, wszINFKEY_URL },
  2165. { TRUE, 3, CERT_ALT_NAME_IP_ADDRESS, wszINFKEY_IPADDRESS },
  2166. { FALSE, 2, CERT_ALT_NAME_REGISTERED_ID, wszINFKEY_REGISTEREDID },
  2167. };
  2168. #define CSUBTREEINFO ARRAYSIZE(g_aSubTreeInfo)
  2169. #define STII_UPNOTHERNAME 0 // CERT_ALT_NAME_OTHER_NAME pOtherName
  2170. #define STII_RFC822NAME 1 // CERT_ALT_NAME_RFC822_NAME pwszRfc822Name
  2171. #define STII_DNSNAME 2 // CERT_ALT_NAME_DNS_NAME pwszDNSName
  2172. #define STII_DIRECTORYNAME 3 // CERT_ALT_NAME_DIRECTORY_NAME DirectoryName
  2173. #define STII_URL 4 // CERT_ALT_NAME_URL pwszURL
  2174. #define STII_IPADDRESS 5 // CERT_ALT_NAME_IP_ADDRESS IPAddress
  2175. #define STII_REGISTEREDID 6 // CERT_ALT_NAME_REGISTERED_ID pszRegisteredID
  2176. VOID
  2177. infFreeGeneralSubTreeElement(
  2178. IN OUT CERT_GENERAL_SUBTREE *pSubTree)
  2179. {
  2180. CERT_ALT_NAME_ENTRY *pName = &pSubTree->Base;
  2181. VOID **ppv = NULL;
  2182. DBGPRINT((
  2183. DBG_SS_CERTLIBI,
  2184. "infFreeGeneralSubTreeElement: p=%x, choice=%x\n",
  2185. pSubTree,
  2186. pName->dwAltNameChoice));
  2187. switch (pName->dwAltNameChoice)
  2188. {
  2189. case CERT_ALT_NAME_OTHER_NAME:
  2190. ppv = (VOID **) &pName->pOtherName;
  2191. if (NULL != pName->pOtherName &&
  2192. NULL != pName->pOtherName->Value.pbData)
  2193. {
  2194. DBGPRINT((
  2195. DBG_SS_CERTLIBI,
  2196. "infFreeGeneralSubTreeElement: p=%x, Free(other.pbData=%x\n)",
  2197. pSubTree,
  2198. pName->pOtherName->Value.pbData));
  2199. LocalFree(pName->pOtherName->Value.pbData);
  2200. }
  2201. break;
  2202. case CERT_ALT_NAME_RFC822_NAME:
  2203. ppv = (VOID **) &pName->pwszRfc822Name;
  2204. break;
  2205. case CERT_ALT_NAME_DNS_NAME:
  2206. ppv = (VOID **) &pName->pwszDNSName;
  2207. break;
  2208. case CERT_ALT_NAME_DIRECTORY_NAME:
  2209. ppv = (VOID **) &pName->DirectoryName.pbData;
  2210. break;
  2211. case CERT_ALT_NAME_URL:
  2212. ppv = (VOID **) &pName->pwszURL;
  2213. break;
  2214. case CERT_ALT_NAME_IP_ADDRESS:
  2215. ppv = (VOID **) &pName->IPAddress.pbData;
  2216. break;
  2217. case CERT_ALT_NAME_REGISTERED_ID:
  2218. ppv = (VOID **) &pName->pszRegisteredID;
  2219. break;
  2220. }
  2221. if (NULL != ppv && NULL != *ppv)
  2222. {
  2223. DBGPRINT((
  2224. DBG_SS_CERTLIBI,
  2225. "infFreeGeneralSubTreeElement: p=%x, Free(pv=%x)\n",
  2226. pSubTree,
  2227. *ppv));
  2228. LocalFree(*ppv);
  2229. }
  2230. }
  2231. VOID
  2232. infFreeGeneralSubTree(
  2233. IN DWORD cSubTree,
  2234. IN OUT CERT_GENERAL_SUBTREE *pSubTree)
  2235. {
  2236. if (NULL != pSubTree)
  2237. {
  2238. DWORD i;
  2239. DBGPRINT((
  2240. DBG_SS_CERTLIBI,
  2241. "infFreeGeneralSubTree: p=%x, c=%x\n",
  2242. pSubTree,
  2243. cSubTree));
  2244. for (i = 0; i < cSubTree; i++)
  2245. {
  2246. infFreeGeneralSubTreeElement(&pSubTree[i]);
  2247. }
  2248. LocalFree(pSubTree);
  2249. }
  2250. }
  2251. // Destructively parse an old-style 4 byte IP Address.
  2252. #define CB_IPV4ADDRESS 4
  2253. HRESULT
  2254. infParseIPV4Address(
  2255. IN WCHAR *pwszValue,
  2256. OUT BYTE *pb,
  2257. IN OUT DWORD *pcb)
  2258. {
  2259. HRESULT hr;
  2260. DWORD cb;
  2261. DBGPRINT((DBG_SS_CERTLIBI, "infParseIPV4Address(%ws)\n", pwszValue));
  2262. if (CB_IPV4ADDRESS > *pcb)
  2263. {
  2264. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  2265. _JumpError(hr, error, "buffer too small");
  2266. }
  2267. for (cb = 0; cb < CB_IPV4ADDRESS; cb++)
  2268. {
  2269. WCHAR *pwszNext;
  2270. BOOL fValid;
  2271. DWORD dw;
  2272. pwszNext = &pwszValue[wcscspn(pwszValue, L".")];
  2273. if (L'.' == *pwszNext)
  2274. {
  2275. *pwszNext++ = L'\0';
  2276. }
  2277. dw = myWtoI(pwszValue, &fValid);
  2278. if (!fValid || 255 < dw)
  2279. {
  2280. hr = E_INVALIDARG;
  2281. _JumpErrorStr(hr, error, "bad IP Address digit string", pwszValue);
  2282. }
  2283. pb[cb] = (BYTE) dw;
  2284. pwszValue = pwszNext;
  2285. }
  2286. if (L'\0' != *pwszValue)
  2287. {
  2288. hr = E_INVALIDARG;
  2289. _JumpError(hr, error, "extra data");
  2290. }
  2291. *pcb = cb;
  2292. DBGPRINT((
  2293. DBG_SS_CERTLIBI,
  2294. "infParseIPV4Address: %u.%u.%u.%u\n",
  2295. pb[0],
  2296. pb[1],
  2297. pb[2],
  2298. pb[3]));
  2299. hr = S_OK;
  2300. error:
  2301. return(hr);
  2302. }
  2303. // Destructively parse a new-style 16 byte IP Address.
  2304. #define CB_IPV6ADDRESS 16
  2305. #define MAKE16(b0, b1) (((b0) << 8) | (b1))
  2306. HRESULT
  2307. infParseIPV6AddressSub(
  2308. IN WCHAR *pwszValue,
  2309. OUT BYTE *pb,
  2310. IN OUT DWORD *pcb)
  2311. {
  2312. HRESULT hr;
  2313. DWORD cbMax = *pcb;
  2314. DWORD cb;
  2315. WCHAR *pwsz;
  2316. DBGPRINT((DBG_SS_CERTLIBI, "infParseIPV6AddressSub(%ws)\n", pwszValue));
  2317. ZeroMemory(pb, cbMax);
  2318. for (cb = 0; cb < cbMax; cb += 2)
  2319. {
  2320. WCHAR *pwszNext;
  2321. BOOL fValid;
  2322. DWORD dw;
  2323. WCHAR awc[7];
  2324. pwszNext = &pwszValue[wcscspn(pwszValue, L":")];
  2325. if (L':' == *pwszNext)
  2326. {
  2327. *pwszNext++ = L'\0';
  2328. }
  2329. if (L'\0' == *pwszValue)
  2330. {
  2331. break;
  2332. }
  2333. if (4 < wcslen(pwszValue))
  2334. {
  2335. hr = E_INVALIDARG;
  2336. _JumpErrorStr(hr, error, "too many IP Address digits", pwszValue);
  2337. }
  2338. wcscpy(awc, L"0x");
  2339. wcscat(awc, pwszValue);
  2340. CSASSERT(wcslen(awc) < ARRAYSIZE(awc));
  2341. dw = myWtoI(awc, &fValid);
  2342. if (!fValid || 64 * 1024 <= dw)
  2343. {
  2344. hr = E_INVALIDARG;
  2345. _JumpErrorStr(hr, error, "bad IP Address digit string", pwszValue);
  2346. }
  2347. pb[cb] = (BYTE) (dw >> 8);
  2348. pb[cb + 1] = (BYTE) dw;
  2349. pwszValue = pwszNext;
  2350. }
  2351. if (L'\0' != *pwszValue)
  2352. {
  2353. hr = E_INVALIDARG;
  2354. _JumpErrorStr(hr, error, "extra data", pwszValue);
  2355. }
  2356. *pcb = cb;
  2357. hr = S_OK;
  2358. error:
  2359. return(hr);
  2360. }
  2361. // Destructively parse a new-style 16 byte IP Address.
  2362. HRESULT
  2363. infParseIPV6Address(
  2364. IN WCHAR *pwszValue,
  2365. OUT BYTE *pb,
  2366. IN OUT DWORD *pcb)
  2367. {
  2368. HRESULT hr;
  2369. DWORD cbMax;
  2370. WCHAR *pwsz;
  2371. WCHAR *pwszLeft;
  2372. WCHAR *pwszRight;
  2373. BYTE abRight[CB_IPV6ADDRESS];
  2374. DWORD cbLeft;
  2375. DWORD cbRight;
  2376. DWORD i;
  2377. BOOL fV4Compat;
  2378. DBGPRINT((DBG_SS_CERTLIBI, "infParseIPV6Address(%ws)\n", pwszValue));
  2379. if (CB_IPV6ADDRESS > *pcb)
  2380. {
  2381. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  2382. _JumpError(hr, error, "buffer too small");
  2383. }
  2384. ZeroMemory(pb, CB_IPV6ADDRESS);
  2385. cbMax = CB_IPV6ADDRESS;
  2386. // If there's a period after the last colon, an IP V4 Address is attached.
  2387. // Parse it as an IP V4 Address, and reduce the expected size of the IP V6
  2388. // Address to be parsed from eight to six 16-bit address chunks.
  2389. pwsz = wcsrchr(pwszValue, L':');
  2390. if (NULL != pwsz)
  2391. {
  2392. if (NULL != wcschr(pwsz, L'.'))
  2393. {
  2394. DWORD cb = CB_IPV4ADDRESS;
  2395. hr = infParseIPV4Address(
  2396. &pwsz[1],
  2397. &pb[CB_IPV6ADDRESS - CB_IPV4ADDRESS],
  2398. &cb);
  2399. _JumpIfError(hr, error, "infParseIPV4Address");
  2400. CSASSERT(CB_IPV4ADDRESS == cb);
  2401. pwsz[1] = L'\0'; // get rid of the trailing IP V4 Address
  2402. // drop the trailing colon -- if it's not part of a double colon.
  2403. if (pwsz > pwszValue && L':' != *--pwsz)
  2404. {
  2405. pwsz[1] = L'\0';
  2406. }
  2407. cbMax -= CB_IPV4ADDRESS;
  2408. }
  2409. }
  2410. cbLeft = 0;
  2411. cbRight = 0;
  2412. pwszLeft = pwszValue;
  2413. pwszRight = wcsstr(pwszValue, L"::");
  2414. if (NULL != pwszRight)
  2415. {
  2416. *pwszRight = L'\0';
  2417. pwszRight += 2;
  2418. if (L'\0' != *pwszRight)
  2419. {
  2420. cbRight = cbMax;
  2421. hr = infParseIPV6AddressSub(pwszRight, abRight, &cbRight);
  2422. _JumpIfError(hr, error, "infParseIPV6AddressSub");
  2423. }
  2424. }
  2425. if (L'\0' != *pwszLeft)
  2426. {
  2427. cbLeft = cbMax;
  2428. hr = infParseIPV6AddressSub(pwszLeft, pb, &cbLeft);
  2429. _JumpIfError(hr, error, "infParseIPV6AddressSub");
  2430. }
  2431. if (NULL == pwszRight && cbLeft != cbMax)
  2432. {
  2433. hr = E_INVALIDARG;
  2434. _JumpError(hr, error, "too few IP Address chunks");
  2435. }
  2436. if (cbLeft + cbRight + (NULL != pwszRight? 1 : 0) > cbMax)
  2437. {
  2438. hr = E_INVALIDARG;
  2439. _JumpError(hr, error, "too many IP Address chunks");
  2440. }
  2441. if (0 != cbRight)
  2442. {
  2443. CopyMemory(&pb[cbMax - cbRight], abRight, cbRight);
  2444. }
  2445. *pcb = CB_IPV6ADDRESS;
  2446. fV4Compat = TRUE;
  2447. for (i = 0; i < CB_IPV6ADDRESS - CB_IPV4ADDRESS - 2; i++)
  2448. {
  2449. if (0 != pb[i])
  2450. {
  2451. fV4Compat = FALSE;
  2452. break;
  2453. }
  2454. }
  2455. if (fV4Compat)
  2456. {
  2457. CSASSERT(i == CB_IPV6ADDRESS - CB_IPV4ADDRESS - 2);
  2458. fV4Compat = (0 == pb[i] && 0 == pb[i + 1]) ||
  2459. (0xff == pb[i] && 0xff == pb[i + 1]);
  2460. }
  2461. if (fV4Compat)
  2462. {
  2463. CSASSERT(i == CB_IPV6ADDRESS - CB_IPV4ADDRESS - 2);
  2464. DBGPRINT((
  2465. DBG_SS_CERTLIB,
  2466. "infParseIPV6Address: ::%hs%u.%u.%u.%u\n",
  2467. 0 == pb[i]? "" : "ffff:",
  2468. pb[12],
  2469. pb[13],
  2470. pb[14],
  2471. pb[15]));
  2472. }
  2473. else
  2474. {
  2475. DBGPRINT((
  2476. DBG_SS_CERTLIB,
  2477. "infParseIPV6Address: %x:%x:%x:%x:%x:%x:%x:%x\n",
  2478. MAKE16(pb[0], pb[1]),
  2479. MAKE16(pb[2], pb[3]),
  2480. MAKE16(pb[4], pb[5]),
  2481. MAKE16(pb[6], pb[7]),
  2482. MAKE16(pb[8], pb[9]),
  2483. MAKE16(pb[10], pb[11]),
  2484. MAKE16(pb[12], pb[13]),
  2485. MAKE16(pb[14], pb[15])));
  2486. }
  2487. hr = S_OK;
  2488. error:
  2489. return(hr);
  2490. }
  2491. HRESULT
  2492. infParseIPAddress(
  2493. IN WCHAR const *pwszValue,
  2494. OUT BYTE *pbData,
  2495. OUT DWORD *pcbData)
  2496. {
  2497. HRESULT hr;
  2498. DWORD cb = *pcbData;
  2499. WCHAR *pwszDup = NULL;
  2500. WCHAR *pwsz;
  2501. // if pwszValue is an empty string, return zero length.
  2502. *pcbData = 0;
  2503. if (L'\0' != *pwszValue)
  2504. {
  2505. hr = myDupString(pwszValue, &pwszDup);
  2506. _JumpIfError(hr, error, "myDupString");
  2507. if (NULL == wcschr(pwszDup, L':'))
  2508. {
  2509. hr = infParseIPV4Address(pwszDup, pbData, &cb);
  2510. _JumpIfError(hr, error, "infParseIPV4Address");
  2511. }
  2512. else
  2513. {
  2514. hr = infParseIPV6Address(pwszDup, pbData, &cb);
  2515. _JumpIfError(hr, error, "infParseIPV6Address");
  2516. }
  2517. *pcbData = cb;
  2518. DBGDUMPHEX((
  2519. DBG_SS_CERTLIBI,
  2520. DH_NOADDRESS | DH_NOTABPREFIX | 8,
  2521. pbData,
  2522. *pcbData));
  2523. }
  2524. hr = S_OK;
  2525. error:
  2526. if (S_OK != hr)
  2527. {
  2528. INFSETERROR(hr, NULL, NULL, pwszValue);
  2529. }
  2530. if (NULL != pwszDup)
  2531. {
  2532. LocalFree(pwszDup);
  2533. }
  2534. return(hr);
  2535. }
  2536. HRESULT
  2537. infParseIPAddressAndMask(
  2538. IN WCHAR const *pwszIPAddress,
  2539. IN WCHAR const *pwszIPAddressMask,
  2540. OUT BYTE **ppbData,
  2541. OUT DWORD *pcbData)
  2542. {
  2543. HRESULT hr;
  2544. BYTE ab[2 * CB_IPV6ADDRESS];
  2545. DWORD cb;
  2546. DWORD cbAddress;
  2547. DWORD cbMask;
  2548. WCHAR *pwsz;
  2549. *ppbData = NULL;
  2550. *pcbData = 0;
  2551. // if pwszValue is an empty string, encode zero length blob.
  2552. cb = 0;
  2553. if (L'\0' != *pwszIPAddress && L'\0' != *pwszIPAddressMask)
  2554. {
  2555. cbAddress = sizeof(ab) / 2;
  2556. hr = infParseIPAddress(pwszIPAddress, ab, &cbAddress);
  2557. _JumpIfError(hr, error, "infParseIPAddress");
  2558. if (L'\0' != *pwszIPAddressMask)
  2559. {
  2560. cbMask = sizeof(ab) / 2;
  2561. hr = infParseIPAddress(pwszIPAddressMask, &ab[cbAddress], &cbMask);
  2562. _JumpIfError(hr, error, "infParseIPMask");
  2563. }
  2564. if (cbAddress != cbMask)
  2565. {
  2566. hr = E_INVALIDARG;
  2567. _JumpError(hr, error, "address and mask lengths differ");
  2568. }
  2569. cb = cbAddress + cbMask;
  2570. }
  2571. else if (L'\0' != *pwszIPAddress || L'\0' != *pwszIPAddressMask)
  2572. {
  2573. hr = E_INVALIDARG;
  2574. _JumpError(hr, error, "address or mask missing");
  2575. }
  2576. *ppbData = (BYTE *) LocalAlloc(LMEM_FIXED, cb);
  2577. if (NULL == *ppbData)
  2578. {
  2579. hr = E_OUTOFMEMORY;
  2580. _JumpError(hr, error, "LocalAlloc");
  2581. }
  2582. *pcbData = cb;
  2583. CopyMemory(*ppbData, ab, cb);
  2584. DBGDUMPHEX((
  2585. DBG_SS_CERTLIBI,
  2586. DH_NOADDRESS | DH_NOTABPREFIX | 8,
  2587. *ppbData,
  2588. *pcbData));
  2589. hr = S_OK;
  2590. error:
  2591. return(hr);
  2592. }
  2593. // [NameConstraintsPermitted]/[NameConstraintsExcluded]
  2594. // ; the numeric second and third arguments are optional
  2595. // ; when present, the second argument is the minimum depth
  2596. // ; when present, the third argument is the maximum depth
  2597. // ; The IETF recommends against specifying dwMinimum & dwMaximum
  2598. // DNS = [email protected]
  2599. // DNS = domain1.domain.com, 3, 6
  2600. HRESULT
  2601. infBuildSubTreeElement(
  2602. IN OUT INFCONTEXT *pInfContext,
  2603. OPTIONAL IN WCHAR const *pwszEmptyEntry, // NULL means read INF file
  2604. IN DWORD iSubTreeInfo,
  2605. OPTIONAL OUT CERT_GENERAL_SUBTREE *pSubTree)
  2606. {
  2607. HRESULT hr;
  2608. SUBTREEINFO const *pSubTreeInfo = &g_aSubTreeInfo[iSubTreeInfo];
  2609. CERT_GENERAL_SUBTREE SubTree;
  2610. WCHAR *pwszValueRead = NULL;
  2611. WCHAR *pwszValueRead2 = NULL;
  2612. WCHAR const *pwszValue = NULL;
  2613. WCHAR const *pwszValue2;
  2614. ZeroMemory(&SubTree, sizeof(SubTree));
  2615. if (NULL != pSubTree)
  2616. {
  2617. ZeroMemory(pSubTree, sizeof(*pSubTree));
  2618. }
  2619. // If pwszEmptyEntry is NULL, read the value from the INF file.
  2620. // Otherwise, encode the specified (empty string) value.
  2621. if (NULL == pwszEmptyEntry)
  2622. {
  2623. INT Value;
  2624. hr = infGetCurrentKeyValue(pInfContext, 1, &pwszValueRead);
  2625. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  2626. pwszValue = pwszValueRead;
  2627. if (!SetupGetIntField(
  2628. pInfContext,
  2629. pSubTreeInfo->dwInfMinMaxIndexBase,
  2630. &Value))
  2631. {
  2632. hr = myHLastError();
  2633. _PrintError2(hr, "SetupGetIntField:2", hr);
  2634. Value = 0;
  2635. }
  2636. SubTree.dwMinimum = Value;
  2637. SubTree.fMaximum = TRUE;
  2638. if (!SetupGetIntField(
  2639. pInfContext,
  2640. pSubTreeInfo->dwInfMinMaxIndexBase + 1,
  2641. &Value))
  2642. {
  2643. hr = myHLastError();
  2644. _PrintError2(hr, "SetupGetIntField:3", hr);
  2645. Value = 0;
  2646. SubTree.fMaximum = FALSE;
  2647. }
  2648. SubTree.dwMaximum = Value;
  2649. }
  2650. else
  2651. {
  2652. pwszValue = pwszEmptyEntry;
  2653. }
  2654. SubTree.Base.dwAltNameChoice = pSubTreeInfo->dwAltNameChoice;
  2655. if (NULL != pSubTree)
  2656. {
  2657. WCHAR **ppwsz = NULL;
  2658. CSASSERT(CSUBTREEINFO > iSubTreeInfo);
  2659. switch (iSubTreeInfo)
  2660. {
  2661. case STII_UPNOTHERNAME:
  2662. {
  2663. CERT_NAME_VALUE nameUpn;
  2664. SubTree.Base.pOtherName = (CERT_OTHER_NAME *) LocalAlloc(
  2665. LMEM_FIXED | LMEM_ZEROINIT,
  2666. sizeof(*SubTree.Base.pOtherName));
  2667. if (NULL == SubTree.Base.pOtherName)
  2668. {
  2669. hr = E_OUTOFMEMORY;
  2670. _JumpError(hr, error, "LocalAlloc");
  2671. }
  2672. SubTree.Base.pOtherName->pszObjId = szOID_NT_PRINCIPAL_NAME;
  2673. nameUpn.dwValueType = CERT_RDN_UTF8_STRING;
  2674. nameUpn.Value.pbData = (BYTE *) pwszValue;
  2675. nameUpn.Value.cbData = 0;
  2676. if (!myEncodeObject(
  2677. X509_ASN_ENCODING,
  2678. X509_UNICODE_ANY_STRING,
  2679. &nameUpn,
  2680. 0,
  2681. CERTLIB_USE_LOCALALLOC,
  2682. &SubTree.Base.pOtherName->Value.pbData,
  2683. &SubTree.Base.pOtherName->Value.cbData))
  2684. {
  2685. hr = myHLastError();
  2686. _JumpError(hr, error, "myEncodeObject");
  2687. }
  2688. DBGPRINT((
  2689. DBG_SS_CERTLIBI,
  2690. "infFreeGeneralSubTreeElement: p=%x, otherUPN=%x,%x\n",
  2691. pSubTree,
  2692. SubTree.Base.pOtherName,
  2693. SubTree.Base.pOtherName->Value.pbData));
  2694. break;
  2695. }
  2696. case STII_RFC822NAME:
  2697. ppwsz = &SubTree.Base.pwszRfc822Name;
  2698. break;
  2699. case STII_DNSNAME:
  2700. ppwsz = &SubTree.Base.pwszDNSName;
  2701. break;
  2702. case STII_DIRECTORYNAME:
  2703. hr = myCertStrToName(
  2704. X509_ASN_ENCODING,
  2705. pwszValue, // pszX500
  2706. CERT_NAME_STR_REVERSE_FLAG,
  2707. NULL, // pvReserved
  2708. &SubTree.Base.DirectoryName.pbData,
  2709. &SubTree.Base.DirectoryName.cbData,
  2710. NULL); // ppszError
  2711. _JumpIfError(hr, error, "myCertStrToName");
  2712. break;
  2713. case STII_URL:
  2714. ppwsz = &SubTree.Base.pwszURL;
  2715. break;
  2716. case STII_IPADDRESS:
  2717. // convert INF string value to binary IP Address
  2718. if (NULL == pwszEmptyEntry)
  2719. {
  2720. hr = infGetCurrentKeyValue(pInfContext, 2, &pwszValueRead2);
  2721. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  2722. pwszValue2 = pwszValueRead2;
  2723. }
  2724. else
  2725. {
  2726. pwszValue2 = pwszEmptyEntry;
  2727. }
  2728. hr = infParseIPAddressAndMask(
  2729. pwszValue,
  2730. pwszValue2,
  2731. &SubTree.Base.IPAddress.pbData,
  2732. &SubTree.Base.IPAddress.cbData);
  2733. _JumpIfError(hr, error, "infParseIPAddressAndMask");
  2734. break;
  2735. case STII_REGISTEREDID:
  2736. if (!myConvertWszToSz(
  2737. &SubTree.Base.pszRegisteredID,
  2738. pwszValue,
  2739. -1))
  2740. {
  2741. hr = E_OUTOFMEMORY;
  2742. _JumpError(hr, error, "ConvertWszToSz");
  2743. }
  2744. DBGPRINT((
  2745. DBG_SS_CERTLIBI,
  2746. "infFreeGeneralSubTreeElement: p=%x, psz=%x\n",
  2747. pSubTree,
  2748. SubTree.Base.pszRegisteredID));
  2749. break;
  2750. }
  2751. if (NULL != ppwsz)
  2752. {
  2753. hr = myDupString(pwszValue, ppwsz);
  2754. _JumpIfError(hr, error, "myDupString");
  2755. DBGPRINT((
  2756. DBG_SS_CERTLIBI,
  2757. "infFreeGeneralSubTreeElement: p=%x, pwsz=%x\n",
  2758. pSubTree,
  2759. *ppwsz));
  2760. }
  2761. *pSubTree = SubTree;
  2762. ZeroMemory(&SubTree, sizeof(SubTree));
  2763. }
  2764. hr = S_OK;
  2765. error:
  2766. if (S_OK != hr)
  2767. {
  2768. INFSETERROR(hr, NULL, NULL, pwszValue);
  2769. }
  2770. infFreeGeneralSubTreeElement(&SubTree);
  2771. if (NULL != pwszValueRead)
  2772. {
  2773. LocalFree(pwszValueRead);
  2774. }
  2775. if (NULL != pwszValueRead2)
  2776. {
  2777. LocalFree(pwszValueRead2);
  2778. }
  2779. return(hr);
  2780. }
  2781. HRESULT
  2782. infGetGeneralSubTreeByType(
  2783. IN HINF hInf,
  2784. IN WCHAR const *pwszSection,
  2785. OPTIONAL IN WCHAR const *pwszEmptyEntry,
  2786. IN DWORD iSubTreeInfo,
  2787. IN OUT DWORD *pcName,
  2788. OPTIONAL OUT CERT_GENERAL_SUBTREE *pSubTree)
  2789. {
  2790. HRESULT hr;
  2791. SUBTREEINFO const *pSubTreeInfo = &g_aSubTreeInfo[iSubTreeInfo];
  2792. INFCONTEXT InfContext;
  2793. DWORD iName;
  2794. DWORD cName = MAXDWORD;
  2795. BOOL fIgnore = FALSE;
  2796. if (NULL == pSubTree)
  2797. {
  2798. *pcName = 0;
  2799. }
  2800. else
  2801. {
  2802. cName = *pcName;
  2803. }
  2804. // If pwszEmptyEntry is NULL, read the value from the INF file.
  2805. // Otherwise, encode the specified (empty string) value.
  2806. if (!SetupFindFirstLine(
  2807. hInf,
  2808. pwszSection,
  2809. pSubTreeInfo->pwszKey,
  2810. &InfContext))
  2811. {
  2812. hr = myHLastError();
  2813. _PrintErrorStr2(
  2814. hr,
  2815. "SetupFindFirstLine",
  2816. pwszSection,
  2817. ERROR_LINE_NOT_FOUND);
  2818. // INF file entry does not exist. Create an empty name constraints
  2819. // entry only if asked to do so (if pwszEmptyEntry is non-NULL).
  2820. if (NULL == pwszEmptyEntry)
  2821. {
  2822. fIgnore = (HRESULT) ERROR_LINE_NOT_FOUND == hr;
  2823. goto error;
  2824. }
  2825. }
  2826. else
  2827. {
  2828. // INF file entry exists; don't create an empty name constraints entry.
  2829. pwszEmptyEntry = NULL;
  2830. }
  2831. for (iName = 0; ; )
  2832. {
  2833. CSASSERT(NULL == pSubTree || iName < cName);
  2834. hr = infBuildSubTreeElement(
  2835. &InfContext,
  2836. pwszEmptyEntry,
  2837. iSubTreeInfo,
  2838. pSubTree);
  2839. _JumpIfErrorStr(hr, error, "infBuildSubTreeElement", pSubTreeInfo->pwszKey);
  2840. DBGPRINT((
  2841. DBG_SS_CERTLIBI,
  2842. "infBuildSubTreeElement: &p[%u]=%x, type=%ws\n",
  2843. iName,
  2844. pSubTree,
  2845. pSubTreeInfo->pwszKey));
  2846. iName++;
  2847. if (NULL != pSubTree)
  2848. {
  2849. pSubTree++;
  2850. }
  2851. if (NULL == pwszEmptyEntry)
  2852. {
  2853. hr = infFindNextKey(pSubTreeInfo->pwszKey, &InfContext);
  2854. }
  2855. else
  2856. {
  2857. hr = S_FALSE;
  2858. }
  2859. if (S_FALSE == hr)
  2860. {
  2861. break;
  2862. }
  2863. _JumpIfErrorStr(hr, error, "infFindNextKey", pSubTreeInfo->pwszKey);
  2864. }
  2865. DBGPRINT((
  2866. DBG_SS_CERTLIBI,
  2867. "infGetGeneralSubTreeByType: i=%x, c=%x\n",
  2868. iName,
  2869. cName));
  2870. CSASSERT(NULL == pSubTree || iName <= cName);
  2871. *pcName = iName;
  2872. hr = S_OK;
  2873. error:
  2874. if (S_OK != hr && !fIgnore)
  2875. {
  2876. INFSETERROR(hr, pwszSection, pSubTreeInfo->pwszKey, NULL);
  2877. }
  2878. return(hr);
  2879. }
  2880. HRESULT
  2881. infGetGeneralSubTree(
  2882. IN HINF hInf,
  2883. IN WCHAR const *pwszSection,
  2884. IN WCHAR const *pwszKey, // key value is sub-section name
  2885. OPTIONAL IN WCHAR const *pwszEmptyEntry,
  2886. OUT DWORD *pcSubTree,
  2887. OUT CERT_GENERAL_SUBTREE **ppSubTree)
  2888. {
  2889. HRESULT hr;
  2890. WCHAR *pwszSubTreeSection = NULL;
  2891. DWORD cSubTree = 0;
  2892. CERT_GENERAL_SUBTREE *rgSubTree = NULL;
  2893. CERT_GENERAL_SUBTREE *pSubTree;
  2894. DWORD iSubTreeInfo;
  2895. DWORD count;
  2896. DWORD cRemain;
  2897. SUBTREEINFO const *pSubTreeInfo;
  2898. *pcSubTree = 0;
  2899. *ppSubTree = NULL;
  2900. CSASSERT(NULL != hInf && INVALID_HANDLE_VALUE != hInf);
  2901. hr = myInfGetKeyValue(
  2902. hInf,
  2903. TRUE, // fLog
  2904. pwszSection,
  2905. pwszKey,
  2906. &pwszSubTreeSection);
  2907. _JumpIfErrorStr2(
  2908. hr,
  2909. error,
  2910. "myInfGetKeyValue",
  2911. pwszKey,
  2912. ERROR_LINE_NOT_FOUND);
  2913. for (iSubTreeInfo = 0; iSubTreeInfo < CSUBTREEINFO; iSubTreeInfo++)
  2914. {
  2915. pSubTreeInfo = &g_aSubTreeInfo[iSubTreeInfo];
  2916. hr = infGetGeneralSubTreeByType(
  2917. hInf,
  2918. pwszSubTreeSection,
  2919. pSubTreeInfo->fEmptyDefault? pwszEmptyEntry : NULL,
  2920. iSubTreeInfo,
  2921. &count,
  2922. NULL);
  2923. DBGPRINT((
  2924. DBG_SS_CERTLIBI,
  2925. "infGetGeneralSubTreeByType(%ws, %ws, NULL) -> hr=%x, c=%x\n",
  2926. pwszSubTreeSection,
  2927. pSubTreeInfo->pwszKey,
  2928. hr,
  2929. count));
  2930. if (S_OK != hr)
  2931. {
  2932. _PrintErrorStr2(
  2933. hr,
  2934. "infGetGeneralSubTreeByType",
  2935. pSubTreeInfo->pwszKey,
  2936. ERROR_LINE_NOT_FOUND);
  2937. if ((HRESULT) ERROR_LINE_NOT_FOUND != hr)
  2938. {
  2939. _JumpErrorStr(
  2940. hr,
  2941. error,
  2942. "infGetGeneralSubTreeByType",
  2943. pSubTreeInfo->pwszKey);
  2944. }
  2945. count = 0;
  2946. }
  2947. cSubTree += count;
  2948. }
  2949. rgSubTree = (CERT_GENERAL_SUBTREE *) LocalAlloc(
  2950. LMEM_FIXED | LMEM_ZEROINIT,
  2951. cSubTree * sizeof(rgSubTree[0]));
  2952. if (NULL == rgSubTree)
  2953. {
  2954. hr = E_OUTOFMEMORY;
  2955. _JumpError(hr, error, "LocalAlloc");
  2956. }
  2957. DBGPRINT((
  2958. DBG_SS_CERTLIBI,
  2959. "infGetGeneralSubTree: rg=%x, total=%x\n",
  2960. rgSubTree,
  2961. cSubTree));
  2962. pSubTree = rgSubTree;
  2963. cRemain = cSubTree;
  2964. for (iSubTreeInfo = 0; iSubTreeInfo < CSUBTREEINFO; iSubTreeInfo++)
  2965. {
  2966. pSubTreeInfo = &g_aSubTreeInfo[iSubTreeInfo];
  2967. count = cRemain;
  2968. hr = infGetGeneralSubTreeByType(
  2969. hInf,
  2970. pwszSubTreeSection,
  2971. pSubTreeInfo->fEmptyDefault? pwszEmptyEntry : NULL,
  2972. iSubTreeInfo,
  2973. &count,
  2974. pSubTree);
  2975. DBGPRINT((
  2976. DBG_SS_CERTLIBI,
  2977. "infGetGeneralSubTreeByType(%ws, %ws, &p[%x]=%x) -> hr=%x, c=%x\n",
  2978. pwszSubTreeSection,
  2979. pSubTreeInfo->pwszKey,
  2980. SAFE_SUBTRACT_POINTERS(pSubTree, rgSubTree),
  2981. pSubTree,
  2982. hr,
  2983. count));
  2984. if (S_OK != hr)
  2985. {
  2986. _PrintErrorStr2(
  2987. hr,
  2988. "infGetGeneralSubTreeByType",
  2989. pSubTreeInfo->pwszKey,
  2990. ERROR_LINE_NOT_FOUND);
  2991. if ((HRESULT) ERROR_LINE_NOT_FOUND != hr)
  2992. {
  2993. _JumpErrorStr(
  2994. hr,
  2995. error,
  2996. "infGetGeneralSubTreeByType",
  2997. pSubTreeInfo->pwszKey);
  2998. }
  2999. if (0 < cRemain)
  3000. {
  3001. ZeroMemory(pSubTree, sizeof(*pSubTree));
  3002. }
  3003. count = 0;
  3004. }
  3005. cRemain -= count;
  3006. pSubTree += count;
  3007. }
  3008. CSASSERT(0 == cRemain);
  3009. *pcSubTree = cSubTree;
  3010. *ppSubTree = rgSubTree;
  3011. rgSubTree = NULL;
  3012. hr = S_OK;
  3013. error:
  3014. if (S_OK != hr)
  3015. {
  3016. INFSETERROR(hr, pwszSection, pwszKey, pwszSubTreeSection);
  3017. }
  3018. if (NULL != pwszSubTreeSection)
  3019. {
  3020. LocalFree(pwszSubTreeSection);
  3021. }
  3022. if (NULL != rgSubTree)
  3023. {
  3024. infFreeGeneralSubTree(cSubTree, rgSubTree);
  3025. }
  3026. return(hr);
  3027. }
  3028. //+------------------------------------------------------------------------
  3029. // myInfGetNameConstraintsExtension -- fetch name constraints extension from INF file
  3030. //
  3031. // [NameConstraintsExtension]
  3032. // Include = NameConstraintsPermitted
  3033. // Exclude = NameConstraintsExcluded
  3034. //
  3035. // [NameConstraintsPermitted]
  3036. // ; the numeric second and third arguments are optional
  3037. // ; when present, the second argument is the minimum depth
  3038. // ; when present, the third argument is the maximum depth
  3039. // ; The IETF recommends against specifying dwMinimum & dwMaximum
  3040. // DNS = [email protected]
  3041. // DNS = domain1.domain.com, 3, 6
  3042. //
  3043. // [NameConstraintsExcluded]
  3044. // DNS = domain.com
  3045. // DNS = domain2.com
  3046. //
  3047. // Returns: encoded name constraints extension
  3048. //-------------------------------------------------------------------------
  3049. FNMYINFGETEXTENSION myInfGetNameConstraintsExtension;
  3050. HRESULT
  3051. myInfGetNameConstraintsExtension(
  3052. IN HINF hInf,
  3053. OUT CERT_EXTENSION *pext)
  3054. {
  3055. HRESULT hr;
  3056. WCHAR const *pwszKey = NULL;
  3057. CERT_NAME_CONSTRAINTS_INFO NameConstraints;
  3058. ZeroMemory(&NameConstraints, sizeof(NameConstraints));
  3059. ZeroMemory(pext, sizeof(*pext));
  3060. myInfClearError();
  3061. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  3062. {
  3063. hr = E_HANDLE;
  3064. _JumpError2(hr, error, "hInf", hr);
  3065. }
  3066. pwszKey = wszINFKEY_INCLUDE;
  3067. hr = infGetGeneralSubTree(
  3068. hInf,
  3069. wszINFSECTION_NAMECONSTRAINTS,
  3070. pwszKey,
  3071. L"",
  3072. &NameConstraints.cPermittedSubtree,
  3073. &NameConstraints.rgPermittedSubtree);
  3074. _PrintIfErrorStr2(
  3075. hr,
  3076. "infGetGeneralSubTree",
  3077. pwszKey,
  3078. ERROR_LINE_NOT_FOUND);
  3079. if (S_OK != hr && (HRESULT) ERROR_LINE_NOT_FOUND != hr)
  3080. {
  3081. goto error;
  3082. }
  3083. pwszKey = wszINFKEY_EXCLUDE;
  3084. hr = infGetGeneralSubTree(
  3085. hInf,
  3086. wszINFSECTION_NAMECONSTRAINTS,
  3087. pwszKey,
  3088. NULL,
  3089. &NameConstraints.cExcludedSubtree,
  3090. &NameConstraints.rgExcludedSubtree);
  3091. _PrintIfErrorStr2(
  3092. hr,
  3093. "infGetGeneralSubTree",
  3094. pwszKey,
  3095. ERROR_LINE_NOT_FOUND);
  3096. if (S_OK != hr && (HRESULT) ERROR_LINE_NOT_FOUND != hr)
  3097. {
  3098. goto error;
  3099. }
  3100. pwszKey = NULL;
  3101. if (NULL == NameConstraints.rgPermittedSubtree &&
  3102. NULL == NameConstraints.rgExcludedSubtree)
  3103. {
  3104. hr = S_FALSE;
  3105. _JumpError2(hr, error, "no data", hr);
  3106. }
  3107. hr = infGetCriticalFlag(
  3108. hInf,
  3109. wszINFSECTION_NAMECONSTRAINTS,
  3110. FALSE,
  3111. &pext->fCritical);
  3112. _JumpIfError(hr, error, "infGetCriticalFlag");
  3113. if (!myEncodeObject(
  3114. X509_ASN_ENCODING,
  3115. X509_NAME_CONSTRAINTS,
  3116. &NameConstraints,
  3117. 0,
  3118. CERTLIB_USE_LOCALALLOC,
  3119. &pext->Value.pbData,
  3120. &pext->Value.cbData))
  3121. {
  3122. hr = myHLastError();
  3123. _JumpError(hr, error, "myEncodeObject");
  3124. }
  3125. error:
  3126. if (S_OK != hr && S_FALSE != hr)
  3127. {
  3128. INFSETERROR(hr, wszINFSECTION_NAMECONSTRAINTS, pwszKey, NULL);
  3129. }
  3130. pext->pszObjId = szOID_NAME_CONSTRAINTS; // on error, too!
  3131. if (NULL != NameConstraints.rgPermittedSubtree)
  3132. {
  3133. infFreeGeneralSubTree(
  3134. NameConstraints.cPermittedSubtree,
  3135. NameConstraints.rgPermittedSubtree);
  3136. }
  3137. if (NULL != NameConstraints.rgExcludedSubtree)
  3138. {
  3139. infFreeGeneralSubTree(
  3140. NameConstraints.cExcludedSubtree,
  3141. NameConstraints.rgExcludedSubtree);
  3142. }
  3143. DBGPRINT((
  3144. DBG_SS_CERTLIBI,
  3145. "myInfGetNameConstraintsExtension hr=%x --> f=%d, cb=%x\n",
  3146. hr,
  3147. pext->fCritical,
  3148. pext->Value.cbData));
  3149. return(hr);
  3150. }
  3151. VOID
  3152. infFreePolicyMappings(
  3153. IN DWORD cPolicyMapping,
  3154. IN OUT CERT_POLICY_MAPPING *pPolicyMapping)
  3155. {
  3156. if (NULL != pPolicyMapping)
  3157. {
  3158. DWORD i;
  3159. for (i = 0; i < cPolicyMapping; i++)
  3160. {
  3161. CERT_POLICY_MAPPING *pMap = &pPolicyMapping[i];
  3162. if (NULL != pMap->pszIssuerDomainPolicy)
  3163. {
  3164. LocalFree(pMap->pszIssuerDomainPolicy);
  3165. }
  3166. if (NULL != pMap->pszSubjectDomainPolicy)
  3167. {
  3168. LocalFree(pMap->pszSubjectDomainPolicy);
  3169. }
  3170. }
  3171. LocalFree(pPolicyMapping);
  3172. }
  3173. }
  3174. HRESULT
  3175. infGetPolicyMappingsSub(
  3176. IN HINF hInf,
  3177. IN WCHAR const *pwszSection,
  3178. IN OUT DWORD *pcPolicyMapping,
  3179. OPTIONAL OUT CERT_POLICY_MAPPING *pPolicyMapping)
  3180. {
  3181. HRESULT hr;
  3182. INFCONTEXT InfContext;
  3183. WCHAR wszIssuer[cwcVALUEMAX];
  3184. WCHAR wszSubject[cwcVALUEMAX];
  3185. DWORD i;
  3186. DWORD cPolicyMappingIn;
  3187. DWORD cPolicyMapping = 0;
  3188. cPolicyMappingIn = MAXDWORD;
  3189. if (NULL != pPolicyMapping)
  3190. {
  3191. cPolicyMappingIn = *pcPolicyMapping;
  3192. }
  3193. *pcPolicyMapping = 0;
  3194. wszIssuer[0] = L'\0';
  3195. wszSubject[0] = L'\0';
  3196. CSASSERT(NULL != hInf && INVALID_HANDLE_VALUE != hInf);
  3197. cPolicyMapping = 0;
  3198. hr = infSetupFindFirstLine(hInf, pwszSection, NULL, &InfContext);
  3199. _JumpIfErrorStr3(
  3200. hr,
  3201. error,
  3202. "infSetupFindFirstLine",
  3203. pwszSection,
  3204. S_FALSE,
  3205. ERROR_LINE_NOT_FOUND);
  3206. while (TRUE)
  3207. {
  3208. wszIssuer[0] = L'\0';
  3209. wszSubject[0] = L'\0';
  3210. if (!SetupGetStringField(
  3211. &InfContext,
  3212. 0,
  3213. wszIssuer,
  3214. ARRAYSIZE(wszIssuer),
  3215. NULL))
  3216. {
  3217. hr = myHLastError();
  3218. _JumpError(hr, error, "SetupGetStringField");
  3219. }
  3220. if (iswdigit(wszIssuer[0]))
  3221. {
  3222. if (!SetupGetStringField(
  3223. &InfContext,
  3224. 1,
  3225. wszSubject,
  3226. ARRAYSIZE(wszSubject),
  3227. NULL))
  3228. {
  3229. hr = myHLastError();
  3230. _JumpError(hr, error, "SetupGetStringField");
  3231. }
  3232. if (!iswdigit(wszSubject[0]))
  3233. {
  3234. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  3235. _JumpErrorStr(hr, error, "bad OID", wszSubject);
  3236. }
  3237. if (NULL != pPolicyMapping)
  3238. {
  3239. CERT_POLICY_MAPPING *pMap;
  3240. if (cPolicyMappingIn <= cPolicyMapping)
  3241. {
  3242. hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  3243. _JumpError(hr, error, "*pcPolicyMapping");
  3244. }
  3245. pMap = &pPolicyMapping[cPolicyMapping];
  3246. if (!ConvertWszToSz(&pMap->pszIssuerDomainPolicy, wszIssuer, -1) ||
  3247. !ConvertWszToSz(&pMap->pszSubjectDomainPolicy, wszSubject, -1))
  3248. {
  3249. hr = E_OUTOFMEMORY;
  3250. _JumpError(hr, error, "ConvertWszToSz");
  3251. }
  3252. }
  3253. DBGPRINT((
  3254. DBG_SS_CERTLIBI,
  3255. "Map[%u]: %ws = %ws\n",
  3256. cPolicyMapping,
  3257. wszIssuer,
  3258. wszSubject));
  3259. cPolicyMapping++;
  3260. }
  3261. if (!SetupFindNextLine(&InfContext, &InfContext))
  3262. {
  3263. hr = myHLastError();
  3264. _PrintError2(hr, "SetupFindNextLine", hr);
  3265. break;
  3266. }
  3267. }
  3268. *pcPolicyMapping = cPolicyMapping;
  3269. hr = S_OK;
  3270. error:
  3271. if (S_OK != hr)
  3272. {
  3273. INFSETERROR(hr, pwszSection, wszIssuer, wszSubject);
  3274. }
  3275. return(hr);
  3276. }
  3277. HRESULT
  3278. infGetPolicyMappings(
  3279. IN HINF hInf,
  3280. IN WCHAR const *pwszSection,
  3281. OUT DWORD *pcPolicyMapping,
  3282. OUT CERT_POLICY_MAPPING **ppPolicyMapping)
  3283. {
  3284. HRESULT hr;
  3285. INFCONTEXT InfContext;
  3286. WCHAR wszIssuer[cwcVALUEMAX];
  3287. WCHAR wszSubject[cwcVALUEMAX];
  3288. DWORD i;
  3289. DWORD cPolicyMapping = 0;
  3290. CERT_POLICY_MAPPING *pPolicyMapping = NULL;
  3291. *pcPolicyMapping = 0;
  3292. *ppPolicyMapping = NULL;
  3293. CSASSERT(NULL != hInf && INVALID_HANDLE_VALUE != hInf);
  3294. cPolicyMapping = 0;
  3295. hr = infGetPolicyMappingsSub(
  3296. hInf,
  3297. pwszSection,
  3298. &cPolicyMapping,
  3299. NULL);
  3300. _JumpIfError3(
  3301. hr,
  3302. error,
  3303. "infGetPolicyMappingsSub",
  3304. S_FALSE,
  3305. ERROR_LINE_NOT_FOUND);
  3306. *pcPolicyMapping = cPolicyMapping;
  3307. pPolicyMapping = (CERT_POLICY_MAPPING *) LocalAlloc(
  3308. LMEM_FIXED | LMEM_ZEROINIT,
  3309. cPolicyMapping * sizeof(*pPolicyMapping));
  3310. if (NULL == pPolicyMapping)
  3311. {
  3312. hr = E_OUTOFMEMORY;
  3313. _JumpError(hr, error, "LocalAlloc");
  3314. }
  3315. hr = infGetPolicyMappingsSub(
  3316. hInf,
  3317. pwszSection,
  3318. &cPolicyMapping,
  3319. pPolicyMapping);
  3320. _JumpIfError(hr, error, "infGetPolicyMappingsSub");
  3321. CSASSERT(*pcPolicyMapping == cPolicyMapping);
  3322. *ppPolicyMapping = pPolicyMapping;
  3323. pPolicyMapping = NULL;
  3324. hr = S_OK;
  3325. error:
  3326. if (NULL != pPolicyMapping)
  3327. {
  3328. infFreePolicyMappings(*pcPolicyMapping, pPolicyMapping);
  3329. }
  3330. return(hr);
  3331. }
  3332. //+------------------------------------------------------------------------
  3333. // infGetPolicyMappingSub -- fetch policy mapping extension from INF file
  3334. //
  3335. // [pwszSection]
  3336. // ; list of user defined policy mappings
  3337. // ; The first OID is for the Issuer Domain Policy, the second is for the
  3338. // ; Subject Domain Policy. Each entry maps one Issuer Domain policy OID
  3339. // ; to a Subject Domain policy OID
  3340. //
  3341. // 1.3.6.1.4.1.311.21.53 = 1.2.3.4.87
  3342. // 1.3.6.1.4.1.311.21.53 = 1.2.3.4.89
  3343. //
  3344. // Returns: encoded policy mapping extension
  3345. //-------------------------------------------------------------------------
  3346. HRESULT
  3347. infGetPolicyMappingExtensionSub(
  3348. IN HINF hInf,
  3349. IN WCHAR const *pwszSection,
  3350. IN char const *pszObjId,
  3351. OUT CERT_EXTENSION *pext)
  3352. {
  3353. HRESULT hr;
  3354. CERT_POLICY_MAPPINGS_INFO PolicyMappings;
  3355. ZeroMemory(&PolicyMappings, sizeof(PolicyMappings));
  3356. ZeroMemory(pext, sizeof(*pext));
  3357. myInfClearError();
  3358. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  3359. {
  3360. hr = E_HANDLE;
  3361. _JumpError2(hr, error, "hInf", hr);
  3362. }
  3363. hr = infGetPolicyMappings(
  3364. hInf,
  3365. pwszSection,
  3366. &PolicyMappings.cPolicyMapping,
  3367. &PolicyMappings.rgPolicyMapping);
  3368. _JumpIfErrorStr3(
  3369. hr,
  3370. error,
  3371. "infGetPolicyMappings",
  3372. pwszSection,
  3373. S_FALSE,
  3374. ERROR_LINE_NOT_FOUND);
  3375. hr = infGetCriticalFlag(
  3376. hInf,
  3377. pwszSection,
  3378. FALSE,
  3379. &pext->fCritical);
  3380. _JumpIfError(hr, error, "infGetCriticalFlag");
  3381. if (!myEncodeObject(
  3382. X509_ASN_ENCODING,
  3383. X509_POLICY_MAPPINGS,
  3384. &PolicyMappings,
  3385. 0,
  3386. CERTLIB_USE_LOCALALLOC,
  3387. &pext->Value.pbData,
  3388. &pext->Value.cbData))
  3389. {
  3390. hr = myHLastError();
  3391. _JumpError(hr, error, "myEncodeObject");
  3392. }
  3393. error:
  3394. if (S_OK != hr && S_FALSE != hr)
  3395. {
  3396. INFSETERROR(hr, pwszSection, NULL, NULL);
  3397. }
  3398. pext->pszObjId = const_cast<char *>(pszObjId); // on error, too!
  3399. if (NULL != PolicyMappings.rgPolicyMapping)
  3400. {
  3401. infFreePolicyMappings(
  3402. PolicyMappings.cPolicyMapping,
  3403. PolicyMappings.rgPolicyMapping);
  3404. }
  3405. return(hr);
  3406. }
  3407. //+------------------------------------------------------------------------
  3408. // myInfGetPolicyMapping -- fetch policy mapping extension from INF file
  3409. //
  3410. // [PolicyMappingExtension]
  3411. // ; list of user defined policy mappings
  3412. // ; The first OID is for the Issuer Domain Policy, the second is for the
  3413. // ; Subject Domain Policy. Each entry maps one Issuer Domain policy OID
  3414. // ; to a Subject Domain policy OID
  3415. //
  3416. // 1.3.6.1.4.1.311.21.53 = 1.2.3.4.87
  3417. // 1.3.6.1.4.1.311.21.53 = 1.2.3.4.89
  3418. //
  3419. // Returns: encoded policy mapping extension
  3420. //-------------------------------------------------------------------------
  3421. FNMYINFGETEXTENSION myInfGetPolicyMappingExtension;
  3422. HRESULT
  3423. myInfGetPolicyMappingExtension(
  3424. IN HINF hInf,
  3425. OUT CERT_EXTENSION *pext)
  3426. {
  3427. HRESULT hr;
  3428. hr = infGetPolicyMappingExtensionSub(
  3429. hInf,
  3430. wszINFSECTION_POLICYMAPPINGS,
  3431. szOID_POLICY_MAPPINGS,
  3432. pext);
  3433. _JumpIfErrorStr3(
  3434. hr,
  3435. error,
  3436. "infGetPolicyMappingExtensionSub",
  3437. wszINFSECTION_POLICYMAPPINGS,
  3438. S_FALSE,
  3439. ERROR_LINE_NOT_FOUND);
  3440. error:
  3441. DBGPRINT((
  3442. DBG_SS_CERTLIBI,
  3443. "myInfGetPolicyMappingExtension hr=%x --> f=%d, cb=%x\n",
  3444. hr,
  3445. pext->fCritical,
  3446. pext->Value.cbData));
  3447. return(hr);
  3448. }
  3449. //+------------------------------------------------------------------------
  3450. // myInfGetApplicationPolicyMapping -- fetch application policy mapping
  3451. // extension from INF file
  3452. //
  3453. // [ApplicationPolicyMappingExtension]
  3454. // ; list of user defined policy mappings
  3455. // ; The first OID is for the Issuer Domain Policy, the second is for the
  3456. // ; Subject Domain Policy. Each entry maps one Issuer Domain policy OID
  3457. // ; to a Subject Domain policy OID
  3458. //
  3459. // 1.3.6.1.4.1.311.21.53 = 1.2.3.4.87
  3460. // 1.3.6.1.4.1.311.21.53 = 1.2.3.4.89
  3461. //
  3462. // Returns: encoded policy mapping extension
  3463. //-------------------------------------------------------------------------
  3464. FNMYINFGETEXTENSION myInfGetApplicationPolicyMappingExtension;
  3465. HRESULT
  3466. myInfGetApplicationPolicyMappingExtension(
  3467. IN HINF hInf,
  3468. OUT CERT_EXTENSION *pext)
  3469. {
  3470. HRESULT hr;
  3471. hr = infGetPolicyMappingExtensionSub(
  3472. hInf,
  3473. wszINFSECTION_APPLICATIONPOLICYMAPPINGS,
  3474. szOID_APPLICATION_POLICY_MAPPINGS,
  3475. pext);
  3476. _JumpIfErrorStr3(
  3477. hr,
  3478. error,
  3479. "infGetPolicyMappingExtensionSub",
  3480. wszINFSECTION_APPLICATIONPOLICYMAPPINGS,
  3481. S_FALSE,
  3482. ERROR_LINE_NOT_FOUND);
  3483. error:
  3484. DBGPRINT((
  3485. DBG_SS_CERTLIBI,
  3486. "myInfGetApplicationPolicyMappingExtension hr=%x --> f=%d, cb=%x\n",
  3487. hr,
  3488. pext->fCritical,
  3489. pext->Value.cbData));
  3490. return(hr);
  3491. }
  3492. //+------------------------------------------------------------------------
  3493. // infGetPolicyConstraintsExtensionSub -- get policy constraints ext from INF
  3494. //
  3495. // [pwszSection]
  3496. // ; consists of two optional DWORDs
  3497. // ; They refer to the depth of the CA hierarchy that requires and inhibits
  3498. // ; Policy Mapping
  3499. // RequireExplicitPolicy = 3
  3500. // InhibitPolicyMapping = 5
  3501. //
  3502. // Returns: encoded policy constraints extension
  3503. //-------------------------------------------------------------------------
  3504. HRESULT
  3505. infGetPolicyConstraintsExtensionSub(
  3506. IN HINF hInf,
  3507. IN WCHAR const *pwszSection,
  3508. IN char const *pszObjId,
  3509. OUT CERT_EXTENSION *pext)
  3510. {
  3511. HRESULT hr;
  3512. CERT_POLICY_CONSTRAINTS_INFO PolicyConstraints;
  3513. WCHAR const *pwszKey = NULL;
  3514. ZeroMemory(&PolicyConstraints, sizeof(PolicyConstraints));
  3515. ZeroMemory(pext, sizeof(*pext));
  3516. myInfClearError();
  3517. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  3518. {
  3519. hr = E_HANDLE;
  3520. _JumpError2(hr, error, "hInf", hr);
  3521. }
  3522. PolicyConstraints.fRequireExplicitPolicy = TRUE;
  3523. pwszKey = wszINFKEY_REQUIREEXPLICITPOLICY;
  3524. hr = myInfGetNumericKeyValue(
  3525. hInf,
  3526. TRUE, // fLog
  3527. pwszSection,
  3528. pwszKey,
  3529. &PolicyConstraints.dwRequireExplicitPolicySkipCerts);
  3530. if (S_OK != hr)
  3531. {
  3532. _PrintErrorStr2(
  3533. hr,
  3534. "myInfGetNumericKeyValue",
  3535. wszINFKEY_REQUIREEXPLICITPOLICY,
  3536. ERROR_LINE_NOT_FOUND);
  3537. PolicyConstraints.dwRequireExplicitPolicySkipCerts = 0;
  3538. PolicyConstraints.fRequireExplicitPolicy = FALSE;
  3539. }
  3540. PolicyConstraints.fInhibitPolicyMapping = TRUE;
  3541. pwszKey = wszINFKEY_INHIBITPOLICYMAPPING;
  3542. hr = myInfGetNumericKeyValue(
  3543. hInf,
  3544. TRUE, // fLog
  3545. pwszSection,
  3546. pwszKey,
  3547. &PolicyConstraints.dwInhibitPolicyMappingSkipCerts);
  3548. if (S_OK != hr)
  3549. {
  3550. _PrintErrorStr2(
  3551. hr,
  3552. "myInfGetNumericKeyValue",
  3553. wszINFKEY_INHIBITPOLICYMAPPING,
  3554. ERROR_LINE_NOT_FOUND);
  3555. PolicyConstraints.dwInhibitPolicyMappingSkipCerts = 0;
  3556. PolicyConstraints.fInhibitPolicyMapping = FALSE;
  3557. }
  3558. pwszKey = NULL;
  3559. if (!PolicyConstraints.fRequireExplicitPolicy &&
  3560. !PolicyConstraints.fInhibitPolicyMapping)
  3561. {
  3562. hr = S_FALSE;
  3563. _JumpError2(hr, error, "no policy constraints", hr);
  3564. }
  3565. hr = infGetCriticalFlag(
  3566. hInf,
  3567. pwszSection,
  3568. FALSE,
  3569. &pext->fCritical);
  3570. _JumpIfError(hr, error, "infGetCriticalFlag");
  3571. if (!myEncodeObject(
  3572. X509_ASN_ENCODING,
  3573. X509_POLICY_CONSTRAINTS,
  3574. &PolicyConstraints,
  3575. 0,
  3576. CERTLIB_USE_LOCALALLOC,
  3577. &pext->Value.pbData,
  3578. &pext->Value.cbData))
  3579. {
  3580. hr = myHLastError();
  3581. _JumpError(hr, error, "myEncodeObject");
  3582. }
  3583. error:
  3584. if (S_OK != hr && S_FALSE != hr)
  3585. {
  3586. INFSETERROR(hr, pwszSection, pwszKey, NULL);
  3587. }
  3588. pext->pszObjId = const_cast<char *>(pszObjId); // on error, too!
  3589. return(hr);
  3590. }
  3591. //+------------------------------------------------------------------------
  3592. // myInfGetPolicyConstraintsExtension -- get policy constraints ext from INF
  3593. //
  3594. // [PolicyConstraintsExtension]
  3595. // ; consists of two optional DWORDs
  3596. // ; They refer to the depth of the CA hierarchy that requires and inhibits
  3597. // ; Policy Mapping
  3598. // RequireExplicitPolicy = 3
  3599. // InhibitPolicyMapping = 5
  3600. //
  3601. // Returns: encoded policy constraints extension
  3602. //-------------------------------------------------------------------------
  3603. FNMYINFGETEXTENSION myInfGetPolicyConstraintsExtension;
  3604. HRESULT
  3605. myInfGetPolicyConstraintsExtension(
  3606. IN HINF hInf,
  3607. OUT CERT_EXTENSION *pext)
  3608. {
  3609. HRESULT hr;
  3610. hr = infGetPolicyConstraintsExtensionSub(
  3611. hInf,
  3612. wszINFSECTION_POLICYCONSTRAINTS,
  3613. szOID_POLICY_CONSTRAINTS,
  3614. pext);
  3615. _JumpIfErrorStr2(
  3616. hr,
  3617. error,
  3618. "infGetPolicyConstraintsExtensionSub",
  3619. wszINFSECTION_POLICYCONSTRAINTS,
  3620. S_FALSE);
  3621. error:
  3622. DBGPRINT((
  3623. DBG_SS_CERTLIBI,
  3624. "myInfGetPolicyConstraintsExtension hr=%x --> f=%d, cb=%x\n",
  3625. hr,
  3626. pext->fCritical,
  3627. pext->Value.cbData));
  3628. return(hr);
  3629. }
  3630. //+------------------------------------------------------------------------
  3631. // myInfGetApplicationPolicyConstraintsExtension -- get application policy
  3632. // constraints extension from INF
  3633. //
  3634. // [ApplicationPolicyConstraintsExtension]
  3635. // ; consists of two optional DWORDs
  3636. // ; They refer to the depth of the CA hierarchy that requires and inhibits
  3637. // ; Policy Mapping
  3638. // RequireExplicitPolicy = 3
  3639. // InhibitPolicyMapping = 5
  3640. //
  3641. // Returns: encoded policy constraints extension
  3642. //-------------------------------------------------------------------------
  3643. FNMYINFGETEXTENSION myInfGetApplicationPolicyConstraintsExtension;
  3644. HRESULT
  3645. myInfGetApplicationPolicyConstraintsExtension(
  3646. IN HINF hInf,
  3647. OUT CERT_EXTENSION *pext)
  3648. {
  3649. HRESULT hr;
  3650. hr = infGetPolicyConstraintsExtensionSub(
  3651. hInf,
  3652. wszINFSECTION_APPLICATIONPOLICYCONSTRAINTS,
  3653. szOID_APPLICATION_POLICY_CONSTRAINTS,
  3654. pext);
  3655. _JumpIfErrorStr2(
  3656. hr,
  3657. error,
  3658. "infGetPolicyConstraintsExtensionSub",
  3659. wszINFSECTION_APPLICATIONPOLICYCONSTRAINTS,
  3660. S_FALSE);
  3661. error:
  3662. DBGPRINT((
  3663. DBG_SS_CERTLIBI,
  3664. "myInfGetApplicationPolicyConstraintsExtension hr=%x --> f=%d, cb=%x\n",
  3665. hr,
  3666. pext->fCritical,
  3667. pext->Value.cbData));
  3668. return(hr);
  3669. }
  3670. //+------------------------------------------------------------------------
  3671. // myInfGetCrossCertDistributionPointsExtension -- fetch Cross CertDist Point
  3672. // URLs from CAPolicy.inf
  3673. //
  3674. // [CrossCertificateDistributionPointsExtension]
  3675. // SyncDeltaTime = 24
  3676. // URL = http://CRLhttp.site.com/Public/MyCA.crt
  3677. // URL = ftp://CRLftp.site.com/Public/MyCA.crt
  3678. //
  3679. // Returns: encoded cross cert dist points extension
  3680. //-------------------------------------------------------------------------
  3681. FNMYINFGETEXTENSION myInfGetCrossCertDistributionPointsExtension;
  3682. HRESULT
  3683. myInfGetCrossCertDistributionPointsExtension(
  3684. IN HINF hInf,
  3685. OUT CERT_EXTENSION *pext)
  3686. {
  3687. HRESULT hr;
  3688. INFCONTEXT InfContext;
  3689. CROSS_CERT_DIST_POINTS_INFO ccdpi;
  3690. CERT_ALT_NAME_INFO AltNameInfo;
  3691. CERT_ALT_NAME_ENTRY *rgAltEntry = NULL;
  3692. WCHAR const *pwsz;
  3693. WCHAR *pwszzURL = NULL;
  3694. BYTE *pbData = NULL;
  3695. DWORD cbData;
  3696. DWORD i;
  3697. WCHAR const *pwszKey = NULL;
  3698. ZeroMemory(&ccdpi, sizeof(ccdpi));
  3699. ZeroMemory(&AltNameInfo, sizeof(AltNameInfo));
  3700. ZeroMemory(pext, sizeof(*pext));
  3701. myInfClearError();
  3702. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  3703. {
  3704. hr = E_HANDLE;
  3705. _JumpError2(hr, error, "hInf", hr);
  3706. }
  3707. hr = infSetupFindFirstLine(hInf, wszINFSECTION_CCDP, NULL, &InfContext);
  3708. _JumpIfErrorStr3(
  3709. hr,
  3710. error,
  3711. "infSetupFindFirstLine",
  3712. wszINFSECTION_CCDP,
  3713. S_FALSE,
  3714. ERROR_LINE_NOT_FOUND);
  3715. pwszKey = wszINFKEY_CCDPSYNCDELTATIME;
  3716. hr = myInfGetNumericKeyValue(
  3717. hInf,
  3718. TRUE, // fLog
  3719. wszINFSECTION_CCDP,
  3720. pwszKey,
  3721. &ccdpi.dwSyncDeltaTime);
  3722. if (S_OK != hr)
  3723. {
  3724. _PrintErrorStr2(
  3725. hr,
  3726. "myInfGetNumericKeyValue",
  3727. pwszKey,
  3728. ERROR_LINE_NOT_FOUND);
  3729. ccdpi.dwSyncDeltaTime = 0;
  3730. }
  3731. pwszKey = wszINFKEY_URL;
  3732. hr = myInfGetKeyList(
  3733. hInf,
  3734. wszINFSECTION_CCDP,
  3735. pwszKey,
  3736. &pext->fCritical,
  3737. &pwszzURL);
  3738. _JumpIfErrorStr3(
  3739. hr,
  3740. error,
  3741. "myInfGetKeyList",
  3742. pwszKey,
  3743. ERROR_LINE_NOT_FOUND,
  3744. S_FALSE);
  3745. pwszKey = NULL;
  3746. if (NULL != pwszzURL)
  3747. {
  3748. for (pwsz = pwszzURL; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  3749. {
  3750. AltNameInfo.cAltEntry++;
  3751. }
  3752. }
  3753. if (0 != AltNameInfo.cAltEntry)
  3754. {
  3755. ccdpi.cDistPoint = 1;
  3756. ccdpi.rgDistPoint = &AltNameInfo;
  3757. AltNameInfo.rgAltEntry = (CERT_ALT_NAME_ENTRY *) LocalAlloc(
  3758. LMEM_FIXED | LMEM_ZEROINIT,
  3759. AltNameInfo.cAltEntry * sizeof(AltNameInfo.rgAltEntry[0]));
  3760. if (NULL == AltNameInfo.rgAltEntry)
  3761. {
  3762. hr = E_OUTOFMEMORY;
  3763. _JumpError(hr, error, "LocalAlloc");
  3764. }
  3765. i = 0;
  3766. for (pwsz = pwszzURL; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  3767. {
  3768. AltNameInfo.rgAltEntry[i].pwszURL = const_cast<WCHAR *>(pwsz);
  3769. AltNameInfo.rgAltEntry[i].dwAltNameChoice = CERT_ALT_NAME_URL;
  3770. i++;
  3771. }
  3772. CSASSERT(i == AltNameInfo.cAltEntry);
  3773. }
  3774. if (!myEncodeObject(
  3775. X509_ASN_ENCODING,
  3776. X509_CROSS_CERT_DIST_POINTS,
  3777. &ccdpi,
  3778. 0,
  3779. CERTLIB_USE_LOCALALLOC,
  3780. &pext->Value.pbData,
  3781. &pext->Value.cbData))
  3782. {
  3783. hr = myHLastError();
  3784. _JumpError(hr, error, "myEncodeObject");
  3785. }
  3786. error:
  3787. if (S_OK != hr && S_FALSE != hr)
  3788. {
  3789. INFSETERROR(hr, wszINFSECTION_CCDP, pwszKey, NULL);
  3790. }
  3791. pext->pszObjId = szOID_CROSS_CERT_DIST_POINTS; // on error, too!
  3792. DBGPRINT((
  3793. DBG_SS_CERTLIBI,
  3794. "myInfGetCrossCertDistributionPointsExtension hr=%x --> f=%d, cb=%x\n",
  3795. hr,
  3796. pext->fCritical,
  3797. pext->Value.cbData));
  3798. if (NULL != AltNameInfo.rgAltEntry)
  3799. {
  3800. LocalFree(AltNameInfo.rgAltEntry);
  3801. }
  3802. if (NULL != pwszzURL)
  3803. {
  3804. LocalFree(pwszzURL);
  3805. }
  3806. if (NULL != rgAltEntry)
  3807. {
  3808. LocalFree(rgAltEntry);
  3809. }
  3810. return(hr);
  3811. }
  3812. HRESULT
  3813. infAddKey(
  3814. IN WCHAR const *pwszName,
  3815. IN OUT DWORD *pcValues,
  3816. IN OUT INFVALUES **prgInfValues,
  3817. OUT INFVALUES **ppInfValues)
  3818. {
  3819. HRESULT hr;
  3820. INFVALUES *rgInfValues;
  3821. WCHAR *pwszKeyT = NULL;
  3822. hr = myDupString(pwszName, &pwszKeyT);
  3823. _JumpIfError(hr, error, "myDupString");
  3824. if (NULL == *prgInfValues)
  3825. {
  3826. CSASSERT(0 == *pcValues);
  3827. rgInfValues = (INFVALUES *) LocalAlloc(
  3828. LMEM_FIXED | LMEM_ZEROINIT,
  3829. sizeof(**prgInfValues));
  3830. }
  3831. else
  3832. {
  3833. CSASSERT(0 != *pcValues);
  3834. rgInfValues = (INFVALUES *) LocalReAlloc(
  3835. *prgInfValues,
  3836. (*pcValues + 1) * sizeof(**prgInfValues),
  3837. LMEM_MOVEABLE | LMEM_ZEROINIT);
  3838. }
  3839. if (NULL == rgInfValues)
  3840. {
  3841. hr = E_OUTOFMEMORY;
  3842. _JumpError(
  3843. hr,
  3844. error,
  3845. NULL == *prgInfValues? "LocalAlloc" : "LocalReAlloc");
  3846. }
  3847. *prgInfValues = rgInfValues;
  3848. *ppInfValues = &rgInfValues[*pcValues];
  3849. (*pcValues)++;
  3850. (*ppInfValues)->pwszKey = pwszKeyT;
  3851. pwszKeyT = NULL;
  3852. hr = S_OK;
  3853. error:
  3854. if (NULL != pwszKeyT)
  3855. {
  3856. LocalFree(pwszKeyT);
  3857. }
  3858. return(hr);
  3859. }
  3860. HRESULT
  3861. infAddValue(
  3862. IN WCHAR const *pwszValue,
  3863. IN OUT INFVALUES *pInfValues)
  3864. {
  3865. HRESULT hr;
  3866. WCHAR *pwszValueT = NULL;
  3867. WCHAR **rgpwszValues = NULL;
  3868. hr = myDupString(pwszValue, &pwszValueT);
  3869. _JumpIfError(hr, error, "myDupString");
  3870. if (NULL == pInfValues->rgpwszValues)
  3871. {
  3872. CSASSERT(0 == pInfValues->cValues);
  3873. rgpwszValues = (WCHAR **) LocalAlloc(
  3874. LMEM_FIXED,
  3875. sizeof(*pInfValues->rgpwszValues));
  3876. }
  3877. else
  3878. {
  3879. CSASSERT(0 != pInfValues->cValues);
  3880. rgpwszValues = (WCHAR **) LocalReAlloc(
  3881. pInfValues->rgpwszValues,
  3882. (pInfValues->cValues + 1) * sizeof(*pInfValues->rgpwszValues),
  3883. LMEM_MOVEABLE);
  3884. }
  3885. if (NULL == rgpwszValues)
  3886. {
  3887. hr = E_OUTOFMEMORY;
  3888. _JumpError(
  3889. hr,
  3890. error,
  3891. NULL == pInfValues->rgpwszValues? "LocalAlloc" : "LocalReAlloc");
  3892. }
  3893. pInfValues->rgpwszValues = rgpwszValues;
  3894. pInfValues->rgpwszValues[pInfValues->cValues] = pwszValueT;
  3895. pInfValues->cValues++;
  3896. pwszValueT = NULL;
  3897. hr = S_OK;
  3898. error:
  3899. if (NULL != pwszValueT)
  3900. {
  3901. LocalFree(pwszValueT);
  3902. }
  3903. return(hr);
  3904. }
  3905. VOID
  3906. myInfFreeSectionValues(
  3907. IN DWORD cInfValues,
  3908. IN OUT INFVALUES *rgInfValues)
  3909. {
  3910. DWORD i;
  3911. DWORD ival;
  3912. INFVALUES *pInfValues;
  3913. if (NULL != rgInfValues)
  3914. {
  3915. for (i = 0; i < cInfValues; i++)
  3916. {
  3917. pInfValues = &rgInfValues[i];
  3918. if (NULL != pInfValues->pwszKey)
  3919. {
  3920. LocalFree(pInfValues->pwszKey);
  3921. }
  3922. if (NULL != pInfValues->rgpwszValues)
  3923. {
  3924. for (ival = 0; ival < pInfValues->cValues; ival++)
  3925. {
  3926. if (NULL != pInfValues->rgpwszValues[ival])
  3927. {
  3928. LocalFree(pInfValues->rgpwszValues[ival]);
  3929. }
  3930. }
  3931. LocalFree(pInfValues->rgpwszValues);
  3932. }
  3933. }
  3934. LocalFree(rgInfValues);
  3935. }
  3936. }
  3937. //+------------------------------------------------------------------------
  3938. // myInfGetSectionValues -- fetch all section values from INF file
  3939. //
  3940. // [pwszSection]
  3941. // KeyName1 = KeyValue1a, KeyValue1b, ...
  3942. // KeyName2 = KeyValue2a, KeyValue2b, ...
  3943. // ...
  3944. // KeyNameN = KeyValueNa, KeyValueNb, ...
  3945. //
  3946. // Returns: array of key names and values
  3947. //-------------------------------------------------------------------------
  3948. HRESULT
  3949. myInfGetSectionValues(
  3950. IN HINF hInf,
  3951. IN WCHAR const *pwszSection,
  3952. OUT DWORD *pcInfValues,
  3953. OUT INFVALUES **prgInfValues)
  3954. {
  3955. HRESULT hr;
  3956. INFCONTEXT InfContext;
  3957. WCHAR wszName[MAX_PATH];
  3958. WCHAR wszValue[cwcVALUEMAX];
  3959. DWORD i;
  3960. DWORD cInfValues = 0;
  3961. INFVALUES *rgInfValues = NULL;
  3962. INFVALUES *pInfValues;
  3963. *pcInfValues = 0;
  3964. *prgInfValues = NULL;
  3965. wszName[0] = L'\0';
  3966. wszValue[0] = L'\0';
  3967. myInfClearError();
  3968. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  3969. {
  3970. hr = E_HANDLE;
  3971. _JumpError2(hr, error, "hInf", hr);
  3972. }
  3973. hr = infSetupFindFirstLine(hInf, pwszSection, NULL, &InfContext);
  3974. _JumpIfErrorStr(hr, error, "infSetupFindFirstLine", pwszSection);
  3975. while (TRUE)
  3976. {
  3977. wszName[0] = L'\0';
  3978. wszValue[0] = L'\0';
  3979. if (!SetupGetStringField(
  3980. &InfContext,
  3981. 0,
  3982. wszName,
  3983. ARRAYSIZE(wszName),
  3984. NULL))
  3985. {
  3986. hr = myHLastError();
  3987. _JumpError(hr, error, "SetupGetStringField");
  3988. }
  3989. //wprintf(L"%ws[0]:\n", wszName);
  3990. hr = infAddKey(wszName, &cInfValues, &rgInfValues, &pInfValues);
  3991. _JumpIfError(hr, error, "infAddKey");
  3992. for (i = 1; ; i++)
  3993. {
  3994. wszValue[0] = L'\0';
  3995. if (!SetupGetStringField(
  3996. &InfContext,
  3997. i,
  3998. wszValue,
  3999. ARRAYSIZE(wszValue),
  4000. NULL))
  4001. {
  4002. hr = myHLastError();
  4003. if (1 == i)
  4004. {
  4005. _JumpError(hr, error, "SetupGetStringField");
  4006. }
  4007. break;
  4008. }
  4009. //wprintf(L"%ws[%u] = %ws\n", wszName, i, wszValue);
  4010. hr = infAddValue(wszValue, pInfValues);
  4011. _JumpIfError(hr, error, "infAddValue");
  4012. }
  4013. if (!SetupFindNextLine(&InfContext, &InfContext))
  4014. {
  4015. hr = myHLastError();
  4016. _PrintError2(hr, "SetupFindNextLine(end)", hr);
  4017. break;
  4018. }
  4019. }
  4020. *pcInfValues = cInfValues;
  4021. *prgInfValues = rgInfValues;
  4022. rgInfValues = NULL;
  4023. hr = S_OK;
  4024. error:
  4025. if (S_OK != hr && S_FALSE != hr)
  4026. {
  4027. INFSETERROR(hr, pwszSection, wszName, wszValue);
  4028. }
  4029. if (NULL != rgInfValues)
  4030. {
  4031. myInfFreeSectionValues(cInfValues, rgInfValues);
  4032. }
  4033. DBGPRINT((
  4034. DBG_SS_CERTLIBI,
  4035. "myInfGetSectionValues hr=%x --> c=%d\n",
  4036. hr,
  4037. *pcInfValues));
  4038. return(hr);
  4039. }