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.

764 lines
16 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: crldist.cpp
  7. //
  8. // Contents: Cert Server Extension Encoding/Decoding implementation
  9. //
  10. //---------------------------------------------------------------------------
  11. #include "pch.cpp"
  12. #pragma hdrstop
  13. #include <assert.h>
  14. #include "resource.h"
  15. #include "altname.h"
  16. #include "celib.h"
  17. #ifndef EAN_NAMEOBJECTID
  18. #define EAN_NAMEOBJECTID ( 0x80000000 )
  19. #endif EAN_NAMEOBJECTID
  20. //+--------------------------------------------------------------------------
  21. // CCertEncodeAltName::CCertEncodeAltName -- constructor
  22. //
  23. // initialize class
  24. //+--------------------------------------------------------------------------
  25. CCertEncodeAltName::CCertEncodeAltName()
  26. {
  27. m_aValue = NULL;
  28. m_DecodeInfo = NULL;
  29. m_fConstructing = FALSE;
  30. }
  31. //+--------------------------------------------------------------------------
  32. // CCertEncodeAltName::~CCertEncodeAltName -- destructor
  33. //
  34. // free memory associated with this instance
  35. //+--------------------------------------------------------------------------
  36. CCertEncodeAltName::~CCertEncodeAltName()
  37. {
  38. _Cleanup();
  39. }
  40. //+--------------------------------------------------------------------------
  41. // CCertEncodeAltName::_NameType -- determine name type tag
  42. //
  43. //+--------------------------------------------------------------------------
  44. CCertEncodeAltName::enumNameType
  45. CCertEncodeAltName::_NameType(
  46. IN DWORD NameChoice)
  47. {
  48. enumNameType Type = enumUnknown;
  49. switch (NameChoice)
  50. {
  51. case CERT_ALT_NAME_RFC822_NAME:
  52. case CERT_ALT_NAME_DNS_NAME:
  53. case CERT_ALT_NAME_URL:
  54. Type = enumUnicode;
  55. break;
  56. case CERT_ALT_NAME_REGISTERED_ID:
  57. Type = enumAnsi;
  58. break;
  59. case CERT_ALT_NAME_DIRECTORY_NAME:
  60. case CERT_ALT_NAME_IP_ADDRESS:
  61. Type = enumBlob;
  62. break;
  63. case CERT_ALT_NAME_OTHER_NAME:
  64. Type = enumOther;
  65. break;
  66. //case CERT_ALT_NAME_X400_ADDRESS:
  67. //case CERT_ALT_NAME_EDI_PARTY_NAME:
  68. }
  69. return(Type);
  70. }
  71. //+--------------------------------------------------------------------------
  72. // CCertEncodeAltName::_Cleanup -- release all resources
  73. //
  74. // free memory associated with this instance
  75. //+--------------------------------------------------------------------------
  76. VOID
  77. CCertEncodeAltName::_Cleanup()
  78. {
  79. if (NULL != m_aValue)
  80. {
  81. if (!m_fConstructing)
  82. {
  83. if (NULL != m_DecodeInfo)
  84. {
  85. LocalFree(m_DecodeInfo);
  86. m_DecodeInfo = NULL;
  87. }
  88. }
  89. else
  90. {
  91. CERT_ALT_NAME_ENTRY *pName;
  92. CERT_ALT_NAME_ENTRY *pNameEnd;
  93. for (pName = m_aValue, pNameEnd = &m_aValue[m_cValue];
  94. pName < pNameEnd;
  95. pName++)
  96. {
  97. BYTE **ppb;
  98. ppb = NULL;
  99. switch (_NameType(pName->dwAltNameChoice))
  100. {
  101. case enumUnicode:
  102. case enumAnsi:
  103. ppb = (BYTE **) &pName->pwszURL;
  104. break;
  105. case enumBlob:
  106. ppb = (BYTE **) &pName->DirectoryName.pbData;
  107. break;
  108. case enumOther:
  109. {
  110. CERT_OTHER_NAME *pOther = pName->pOtherName;
  111. if (NULL != pOther)
  112. {
  113. if (NULL != pOther->pszObjId)
  114. {
  115. LocalFree(pOther->pszObjId);
  116. }
  117. if (NULL != pOther->Value.pbData)
  118. {
  119. LocalFree(pOther->Value.pbData);
  120. }
  121. }
  122. ppb = (BYTE **) &pName->pOtherName;
  123. break;
  124. }
  125. }
  126. if (NULL != ppb && NULL != *ppb)
  127. {
  128. LocalFree(*ppb);
  129. }
  130. }
  131. LocalFree(m_aValue);
  132. }
  133. m_aValue = NULL;
  134. }
  135. assert(NULL == m_DecodeInfo);
  136. m_fConstructing = FALSE;
  137. }
  138. //+--------------------------------------------------------------------------
  139. // CCertEncodeAltName::_MapName -- map a distribution point
  140. //
  141. //+--------------------------------------------------------------------------
  142. HRESULT
  143. CCertEncodeAltName::_MapName(
  144. IN BOOL fEncode,
  145. IN LONG NameIndex, // NameIndex | EAN_*
  146. OUT CERT_ALT_NAME_ENTRY **ppName)
  147. {
  148. HRESULT hr = S_OK;
  149. CERT_ALT_NAME_ENTRY *pName;
  150. if (fEncode)
  151. {
  152. pName = m_fConstructing? m_aValue : NULL;
  153. }
  154. else
  155. {
  156. pName = m_aValue;
  157. }
  158. if (NULL == pName)
  159. {
  160. hr = E_INVALIDARG;
  161. ceERRORPRINTLINE("bad parameter", hr);
  162. goto error;
  163. }
  164. NameIndex &= ~EAN_NAMEOBJECTID;
  165. if (m_cValue <= NameIndex)
  166. {
  167. ceERRORPRINTLINE("bad NameIndex parameter", hr);
  168. hr = E_INVALIDARG;
  169. goto error;
  170. }
  171. *ppName = &pName[NameIndex];
  172. error:
  173. return(hr);
  174. }
  175. //+--------------------------------------------------------------------------
  176. // CCertEncodeAltName::Decode -- Decode AltName
  177. //
  178. // Returns S_OK on success.
  179. //+--------------------------------------------------------------------------
  180. STDMETHODIMP
  181. CCertEncodeAltName::Decode(
  182. /* [in] */ BSTR const strBinary)
  183. {
  184. HRESULT hr = S_OK;
  185. _Cleanup();
  186. if (NULL == strBinary)
  187. {
  188. hr = E_POINTER;
  189. ceERRORPRINTLINE("NULL parm", hr);
  190. goto error;
  191. }
  192. // Decode CERT_ALT_NAME_INFO:
  193. if (!ceDecodeObject(
  194. X509_ASN_ENCODING,
  195. X509_ALTERNATE_NAME,
  196. (BYTE *) strBinary,
  197. SysStringByteLen(strBinary),
  198. FALSE,
  199. (VOID **) &m_DecodeInfo,
  200. &m_DecodeLength))
  201. {
  202. hr = ceHLastError();
  203. ceERRORPRINTLINE("ceDecodeObject", hr);
  204. goto error;
  205. }
  206. m_aValue = m_DecodeInfo->rgAltEntry;
  207. m_cValue = m_DecodeInfo->cAltEntry;
  208. error:
  209. if (S_OK != hr)
  210. {
  211. _Cleanup();
  212. }
  213. return(_SetErrorInfo(hr, L"CCertEncodeAltName::Decode"));
  214. }
  215. //+--------------------------------------------------------------------------
  216. // CCertEncodeAltName::GetNameCount -- Get the Distribution Name Count
  217. //
  218. // Returns S_OK on success.
  219. //+--------------------------------------------------------------------------
  220. STDMETHODIMP
  221. CCertEncodeAltName::GetNameCount(
  222. /* [out, retval] */ LONG __RPC_FAR *pNameCount)
  223. {
  224. HRESULT hr = E_INVALIDARG;
  225. if (NULL == pNameCount)
  226. {
  227. hr = E_POINTER;
  228. ceERRORPRINTLINE("NULL parm", hr);
  229. goto error;
  230. }
  231. if (NULL == m_aValue)
  232. {
  233. ceERRORPRINTLINE("bad parameter", hr);
  234. goto error;
  235. }
  236. *pNameCount = m_cValue;
  237. hr = S_OK;
  238. error:
  239. return(_SetErrorInfo(hr, L"CCertEncodeAltName::GetNameCount"));
  240. }
  241. //+--------------------------------------------------------------------------
  242. // CCertEncodeAltName::GetNameChoice -- Get a Name Choice
  243. //
  244. // Returns S_OK on success.
  245. //+--------------------------------------------------------------------------
  246. STDMETHODIMP
  247. CCertEncodeAltName::GetNameChoice(
  248. /* [in] */ LONG NameIndex,
  249. /* [out, retval] */ LONG __RPC_FAR *pNameChoice)
  250. {
  251. HRESULT hr;
  252. CERT_ALT_NAME_ENTRY *pName;
  253. if (NULL == pNameChoice)
  254. {
  255. hr = E_POINTER;
  256. ceERRORPRINTLINE("NULL parm", hr);
  257. goto error;
  258. }
  259. hr = _MapName(FALSE, NameIndex, &pName);
  260. if (S_OK != hr)
  261. {
  262. ceERRORPRINTLINE("_MapName", hr);
  263. goto error;
  264. }
  265. if (enumUnknown == _NameType(pName->dwAltNameChoice))
  266. {
  267. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  268. ceERRORPRINTLINE("uninitialized", hr);
  269. goto error;
  270. }
  271. *pNameChoice = pName->dwAltNameChoice;
  272. error:
  273. return(_SetErrorInfo(hr, L"CCertEncodeAltName::GetNameChoice"));
  274. }
  275. //+--------------------------------------------------------------------------
  276. // CCertEncodeAltName::GetName -- Get a Name
  277. //
  278. // Returns S_OK on success.
  279. //+--------------------------------------------------------------------------
  280. STDMETHODIMP
  281. CCertEncodeAltName::GetName(
  282. /* [in] */ LONG NameIndex, // NameIndex | EAN_*
  283. /* [out, retval] */ BSTR __RPC_FAR *pstrName)
  284. {
  285. HRESULT hr;
  286. CERT_ALT_NAME_ENTRY *pName;
  287. if (NULL == pstrName)
  288. {
  289. hr = E_POINTER;
  290. ceERRORPRINTLINE("NULL parm", hr);
  291. goto error;
  292. }
  293. ceFreeBstr(pstrName);
  294. hr = _MapName(FALSE, NameIndex, &pName);
  295. if (S_OK != hr)
  296. {
  297. ceERRORPRINTLINE("_MapName", hr);
  298. goto error;
  299. }
  300. hr = E_OUTOFMEMORY;
  301. switch (_NameType(pName->dwAltNameChoice))
  302. {
  303. case enumUnicode:
  304. if (!ceConvertWszToBstr(pstrName, pName->pwszURL, -1))
  305. {
  306. ceERRORPRINTLINE("no memory", hr);
  307. goto error;
  308. }
  309. break;
  310. case enumAnsi:
  311. if (!ceConvertSzToBstr(pstrName, pName->pszRegisteredID, -1))
  312. {
  313. ceERRORPRINTLINE("no memory", hr);
  314. goto error;
  315. }
  316. break;
  317. case enumBlob:
  318. if (!ceConvertWszToBstr(
  319. pstrName,
  320. (WCHAR const *) pName->DirectoryName.pbData,
  321. pName->DirectoryName.cbData))
  322. {
  323. ceERRORPRINTLINE("no memory", hr);
  324. goto error;
  325. }
  326. break;
  327. case enumOther:
  328. if (EAN_NAMEOBJECTID & NameIndex)
  329. {
  330. if (!ceConvertSzToBstr(
  331. pstrName,
  332. pName->pOtherName->pszObjId,
  333. -1))
  334. {
  335. ceERRORPRINTLINE("no memory", hr);
  336. goto error;
  337. }
  338. }
  339. else
  340. {
  341. if (!ceConvertWszToBstr(
  342. pstrName,
  343. (WCHAR const *) pName->pOtherName->Value.pbData,
  344. pName->pOtherName->Value.cbData))
  345. {
  346. ceERRORPRINTLINE("no memory", hr);
  347. goto error;
  348. }
  349. }
  350. break;
  351. default:
  352. assert(enumUnknown == _NameType(pName->dwAltNameChoice));
  353. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  354. ceERRORPRINTLINE("uninitialized", hr);
  355. goto error;
  356. }
  357. hr = S_OK;
  358. error:
  359. return(_SetErrorInfo(hr, L"CCertEncodeAltName::GetName"));
  360. }
  361. //+--------------------------------------------------------------------------
  362. // CCertEncodeAltName::Reset -- clear out data
  363. //
  364. // Returns S_OK on success.
  365. //+--------------------------------------------------------------------------
  366. STDMETHODIMP
  367. CCertEncodeAltName::Reset(
  368. /* [in] */ LONG NameCount)
  369. {
  370. HRESULT hr = S_OK;
  371. CERT_NAME_VALUE *aNameValue = NULL;
  372. _Cleanup();
  373. m_fConstructing = TRUE;
  374. if (CENCODEMAX < NameCount || 0 > NameCount)
  375. {
  376. hr = E_INVALIDARG;
  377. ceERRORPRINTLINE("bad count parameter", hr);
  378. goto error;
  379. }
  380. m_aValue = (CERT_ALT_NAME_ENTRY *) LocalAlloc(
  381. LMEM_FIXED | LMEM_ZEROINIT,
  382. NameCount * sizeof(m_aValue[0]));
  383. if (NULL == m_aValue)
  384. {
  385. hr = E_OUTOFMEMORY;
  386. ceERRORPRINTLINE("LocalAlloc", hr);
  387. goto error;
  388. }
  389. m_cValue = NameCount;
  390. error:
  391. if (S_OK != hr)
  392. {
  393. _Cleanup();
  394. }
  395. return(_SetErrorInfo(hr, L"CCertEncodeAltName::Reset"));
  396. }
  397. //+--------------------------------------------------------------------------
  398. // CCertEncodeAltName::SetNameEntry -- Set a Name Netry
  399. //
  400. // Returns S_OK on success.
  401. //+--------------------------------------------------------------------------
  402. STDMETHODIMP
  403. CCertEncodeAltName::SetNameEntry(
  404. /* [in] */ LONG NameIndex, // NameIndex | EAN_*
  405. /* [in] */ LONG NameChoice,
  406. /* [in] */ BSTR const strName)
  407. {
  408. HRESULT hr;
  409. CERT_ALT_NAME_ENTRY *pName;
  410. DATA_BLOB *pBlob = NULL;
  411. if (NULL == strName)
  412. {
  413. hr = E_POINTER;
  414. ceERRORPRINTLINE("NULL parm", hr);
  415. goto error;
  416. }
  417. if (!m_fConstructing)
  418. {
  419. hr = E_INVALIDARG;
  420. ceERRORPRINTLINE("bad parameter", hr);
  421. goto error;
  422. }
  423. hr = _MapName(TRUE, NameIndex, &pName);
  424. if (S_OK != hr)
  425. {
  426. ceERRORPRINTLINE("_MapName", hr);
  427. goto error;
  428. }
  429. if (enumUnknown != _NameType(pName->dwAltNameChoice))
  430. {
  431. hr = E_INVALIDARG;
  432. ceERRORPRINTLINE("bad parameter", hr);
  433. goto error;
  434. }
  435. hr = ceVerifyAltNameString(NameChoice, strName);
  436. if (S_OK != hr)
  437. {
  438. ceERRORPRINTLINE("ceVerifyAltNameString", hr);
  439. goto error;
  440. }
  441. switch (_NameType(NameChoice))
  442. {
  443. case enumUnicode:
  444. pName->pwszURL = ceDuplicateString(strName);
  445. if (NULL == pName->pwszURL)
  446. {
  447. hr = E_OUTOFMEMORY;
  448. ceERRORPRINTLINE("ceDuplicateString", hr);
  449. goto error;
  450. }
  451. break;
  452. case enumAnsi:
  453. if (CERT_ALT_NAME_REGISTERED_ID == NameChoice)
  454. {
  455. hr = ceVerifyObjId(strName);
  456. if (S_OK != hr)
  457. {
  458. ceERRORPRINTLINE("ceVerifyObjId", hr);
  459. goto error;
  460. }
  461. }
  462. if (!ceConvertWszToSz(&pName->pszRegisteredID, strName, -1))
  463. {
  464. hr = E_OUTOFMEMORY;
  465. ceERRORPRINTLINE("ceConvertWszToSz", hr);
  466. goto error;
  467. }
  468. break;
  469. case enumBlob:
  470. pBlob = &pName->DirectoryName;
  471. break;
  472. case enumOther:
  473. if (NULL == pName->pOtherName)
  474. {
  475. pName->pOtherName = (CERT_OTHER_NAME *) LocalAlloc(
  476. LMEM_FIXED | LMEM_ZEROINIT,
  477. sizeof(*pName->pOtherName));
  478. if (NULL == pName->pOtherName)
  479. {
  480. hr = E_OUTOFMEMORY;
  481. _JumpError(hr, error, "LocalAlloc");
  482. }
  483. }
  484. else if (CERT_ALT_NAME_OTHER_NAME != pName->dwAltNameChoice)
  485. {
  486. hr = E_INVALIDARG;
  487. _JumpError(hr, error, "NameChoice conflict");
  488. }
  489. if (EAN_NAMEOBJECTID & NameIndex)
  490. {
  491. if (NULL != pName->pOtherName->pszObjId)
  492. {
  493. hr = E_INVALIDARG;
  494. _JumpError(hr, error, "pszObjId already set");
  495. }
  496. if (!ceConvertWszToSz(&pName->pOtherName->pszObjId, strName, -1))
  497. {
  498. hr = E_OUTOFMEMORY;
  499. _JumpError(hr, error, "ceConvertWszToSz");
  500. }
  501. }
  502. else
  503. {
  504. pBlob = &pName->pOtherName->Value;
  505. }
  506. break;
  507. default:
  508. hr = E_INVALIDARG;
  509. ceERRORPRINTLINE("bad NameChoice parameter", hr);
  510. goto error;
  511. break;
  512. }
  513. if (NULL != pBlob)
  514. {
  515. if (NULL != pBlob->pbData)
  516. {
  517. hr = E_INVALIDARG;
  518. _JumpError(hr, error, "pbData already set");
  519. }
  520. pBlob->cbData = SysStringByteLen(strName);
  521. pBlob->pbData = (BYTE *) LocalAlloc(LMEM_FIXED, pBlob->cbData);
  522. if (NULL == pBlob->pbData)
  523. {
  524. hr = E_OUTOFMEMORY;
  525. _JumpError(hr, error, "LocalAlloc");
  526. }
  527. CopyMemory(pBlob->pbData, strName, pBlob->cbData);
  528. }
  529. pName->dwAltNameChoice = NameChoice;
  530. error:
  531. return(_SetErrorInfo(hr, L"CCertEncodeAltName::SetNameEntry"));
  532. }
  533. //+--------------------------------------------------------------------------
  534. // CCertEncodeAltName::_VerifyName -- Verify name
  535. //
  536. // Returns S_OK on success.
  537. //+--------------------------------------------------------------------------
  538. BOOL
  539. CCertEncodeAltName::_VerifyName(
  540. IN LONG NameIndex)
  541. {
  542. HRESULT hr;
  543. BOOL fOk = FALSE;
  544. CERT_ALT_NAME_ENTRY *pName;
  545. assert(m_fConstructing);
  546. hr = _MapName(TRUE, NameIndex, &pName);
  547. if (S_OK != hr)
  548. {
  549. ceERRORPRINTLINE("_MapName", hr);
  550. goto error;
  551. }
  552. assert(NULL != pName);
  553. switch (_NameType(pName->dwAltNameChoice))
  554. {
  555. case enumOther:
  556. if (NULL != pName->pOtherName &&
  557. NULL != pName->pOtherName->pszObjId &&
  558. NULL != pName->pOtherName->Value.pbData)
  559. {
  560. break;
  561. }
  562. // FALLTHROUGH
  563. case enumUnknown:
  564. hr = E_INVALIDARG;
  565. ceERRORPRINTLINE("uninitialized name", hr);
  566. goto error;
  567. }
  568. fOk = TRUE;
  569. error:
  570. return(fOk);
  571. }
  572. //+--------------------------------------------------------------------------
  573. // CCertEncodeAltName::Encode -- Encode AltName
  574. //
  575. // Returns S_OK on success.
  576. //+--------------------------------------------------------------------------
  577. STDMETHODIMP
  578. CCertEncodeAltName::Encode(
  579. /* [out, retval] */ BSTR __RPC_FAR *pstrBinary)
  580. {
  581. HRESULT hr = S_OK;
  582. CERT_ALT_NAME_INFO AltName;
  583. BYTE *pbEncoded = NULL;
  584. DWORD cbEncoded;
  585. LONG i;
  586. if (NULL == pstrBinary)
  587. {
  588. hr = E_POINTER;
  589. ceERRORPRINTLINE("NULL parm", hr);
  590. goto error;
  591. }
  592. AltName.cAltEntry = m_cValue;
  593. AltName.rgAltEntry = m_aValue;
  594. ceFreeBstr(pstrBinary);
  595. if (!m_fConstructing || NULL == m_aValue)
  596. {
  597. hr = E_INVALIDARG;
  598. ceERRORPRINTLINE("bad parameter", hr);
  599. goto error;
  600. }
  601. for (i = 0; i < m_cValue; i++)
  602. {
  603. // Verify all entries are initialized:
  604. if (!_VerifyName(i))
  605. {
  606. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  607. ceERRORPRINTLINE("uninitialized name", hr);
  608. goto error;
  609. }
  610. }
  611. // Encode CERT_ALT_NAME_INFO:
  612. if (!ceEncodeObject(
  613. X509_ASN_ENCODING,
  614. X509_ALTERNATE_NAME,
  615. &AltName,
  616. 0,
  617. FALSE,
  618. &pbEncoded,
  619. &cbEncoded))
  620. {
  621. hr = ceHLastError();
  622. ceERRORPRINTLINE("ceEncodeObject", hr);
  623. goto error;
  624. }
  625. if (!ceConvertWszToBstr(pstrBinary, (WCHAR const *) pbEncoded, cbEncoded))
  626. {
  627. hr = E_OUTOFMEMORY;
  628. ceERRORPRINTLINE("ceConvertWszToBstr", hr);
  629. goto error;
  630. }
  631. error:
  632. if (NULL != pbEncoded)
  633. {
  634. LocalFree(pbEncoded);
  635. }
  636. return(_SetErrorInfo(hr, L"CCertEncodeAltName::Encode"));
  637. }
  638. //+--------------------------------------------------------------------------
  639. // CCertEncodeAltName::_SetErrorInfo -- set error object information
  640. //
  641. // Returns passed HRESULT
  642. //+--------------------------------------------------------------------------
  643. HRESULT
  644. CCertEncodeAltName::_SetErrorInfo(
  645. IN HRESULT hrError,
  646. IN WCHAR const *pwszDescription)
  647. {
  648. assert(FAILED(hrError) || S_OK == hrError || S_FALSE == hrError);
  649. if (FAILED(hrError))
  650. {
  651. HRESULT hr;
  652. hr = ceDispatchSetErrorInfo(
  653. hrError,
  654. pwszDescription,
  655. wszCLASS_CERTENCODEALTNAME,
  656. &IID_ICertEncodeAltName);
  657. assert(hr == hrError);
  658. }
  659. return(hrError);
  660. }