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

779 lines
17 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. _Cleanup();
  372. m_fConstructing = TRUE;
  373. if (CENCODEMAX < NameCount || 0 > NameCount)
  374. {
  375. hr = E_INVALIDARG;
  376. ceERRORPRINTLINE("bad count parameter", hr);
  377. goto error;
  378. }
  379. m_aValue = (CERT_ALT_NAME_ENTRY *) LocalAlloc(
  380. LMEM_FIXED | LMEM_ZEROINIT,
  381. NameCount * sizeof(m_aValue[0]));
  382. if (NULL == m_aValue)
  383. {
  384. hr = E_OUTOFMEMORY;
  385. ceERRORPRINTLINE("LocalAlloc", hr);
  386. goto error;
  387. }
  388. m_cValue = NameCount;
  389. error:
  390. if (S_OK != hr)
  391. {
  392. _Cleanup();
  393. }
  394. return(_SetErrorInfo(hr, L"CCertEncodeAltName::Reset"));
  395. }
  396. //+--------------------------------------------------------------------------
  397. // CCertEncodeAltName::SetNameEntry -- Set a Name Netry
  398. //
  399. // Returns S_OK on success.
  400. //+--------------------------------------------------------------------------
  401. STDMETHODIMP
  402. CCertEncodeAltName::SetNameEntry(
  403. /* [in] */ LONG NameIndex, // NameIndex | EAN_*
  404. /* [in] */ LONG NameChoice,
  405. /* [in] */ BSTR const strName)
  406. {
  407. HRESULT hr;
  408. CERT_ALT_NAME_ENTRY *pName;
  409. DATA_BLOB *pBlob = NULL;
  410. CCertEncodeAltName::enumNameType enumT;
  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. enumT = enumUnknown;
  430. if (CERT_ALT_NAME_OTHER_NAME == pName->dwAltNameChoice &&
  431. 0 == (EAN_NAMEOBJECTID & NameIndex))
  432. {
  433. enumT = enumOther;
  434. }
  435. if (_NameType(pName->dwAltNameChoice) != enumT)
  436. {
  437. hr = E_INVALIDARG;
  438. ceERRORPRINTLINE("bad parameter", hr);
  439. goto error;
  440. }
  441. if (CERT_ALT_NAME_OTHER_NAME != pName->dwAltNameChoice ||
  442. 0 == (EAN_NAMEOBJECTID & NameIndex))
  443. {
  444. hr = ceVerifyAltNameString(NameChoice, strName);
  445. if (S_OK != hr)
  446. {
  447. ceERRORPRINTLINE("ceVerifyAltNameString", hr);
  448. goto error;
  449. }
  450. }
  451. switch (_NameType(NameChoice))
  452. {
  453. case enumUnicode:
  454. pName->pwszURL = ceDuplicateString(strName);
  455. if (NULL == pName->pwszURL)
  456. {
  457. hr = E_OUTOFMEMORY;
  458. ceERRORPRINTLINE("ceDuplicateString", hr);
  459. goto error;
  460. }
  461. break;
  462. case enumAnsi:
  463. if (CERT_ALT_NAME_REGISTERED_ID == NameChoice)
  464. {
  465. hr = ceVerifyObjId(strName);
  466. if (S_OK != hr)
  467. {
  468. ceERRORPRINTLINE("ceVerifyObjId", hr);
  469. goto error;
  470. }
  471. }
  472. if (!ceConvertWszToSz(&pName->pszRegisteredID, strName, -1))
  473. {
  474. hr = E_OUTOFMEMORY;
  475. ceERRORPRINTLINE("ceConvertWszToSz", hr);
  476. goto error;
  477. }
  478. break;
  479. case enumBlob:
  480. pBlob = &pName->DirectoryName;
  481. break;
  482. case enumOther:
  483. if (NULL == pName->pOtherName)
  484. {
  485. pName->pOtherName = (CERT_OTHER_NAME *) LocalAlloc(
  486. LMEM_FIXED | LMEM_ZEROINIT,
  487. sizeof(*pName->pOtherName));
  488. if (NULL == pName->pOtherName)
  489. {
  490. hr = E_OUTOFMEMORY;
  491. _JumpError(hr, error, "LocalAlloc");
  492. }
  493. }
  494. else if (CERT_ALT_NAME_OTHER_NAME != pName->dwAltNameChoice)
  495. {
  496. hr = E_INVALIDARG;
  497. _JumpError(hr, error, "NameChoice conflict");
  498. }
  499. if (EAN_NAMEOBJECTID & NameIndex)
  500. {
  501. if (NULL != pName->pOtherName->pszObjId)
  502. {
  503. hr = E_INVALIDARG;
  504. _JumpError(hr, error, "pszObjId already set");
  505. }
  506. hr = ceVerifyObjId(strName);
  507. if (S_OK != hr)
  508. {
  509. ceERRORPRINTLINE("ceVerifyObjId", hr);
  510. goto error;
  511. }
  512. if (!ceConvertWszToSz(&pName->pOtherName->pszObjId, strName, -1))
  513. {
  514. hr = E_OUTOFMEMORY;
  515. _JumpError(hr, error, "ceConvertWszToSz");
  516. }
  517. }
  518. else
  519. {
  520. pBlob = &pName->pOtherName->Value;
  521. }
  522. break;
  523. default:
  524. hr = E_INVALIDARG;
  525. ceERRORPRINTLINE("bad NameChoice parameter", hr);
  526. goto error;
  527. break;
  528. }
  529. if (NULL != pBlob)
  530. {
  531. if (NULL != pBlob->pbData)
  532. {
  533. hr = E_INVALIDARG;
  534. _JumpError(hr, error, "pbData already set");
  535. }
  536. pBlob->cbData = SysStringByteLen(strName);
  537. pBlob->pbData = (BYTE *) LocalAlloc(LMEM_FIXED, pBlob->cbData);
  538. if (NULL == pBlob->pbData)
  539. {
  540. hr = E_OUTOFMEMORY;
  541. _JumpError(hr, error, "LocalAlloc");
  542. }
  543. CopyMemory(pBlob->pbData, strName, pBlob->cbData);
  544. }
  545. pName->dwAltNameChoice = NameChoice;
  546. error:
  547. return(_SetErrorInfo(hr, L"CCertEncodeAltName::SetNameEntry"));
  548. }
  549. //+--------------------------------------------------------------------------
  550. // CCertEncodeAltName::_VerifyName -- Verify name
  551. //
  552. // Returns S_OK on success.
  553. //+--------------------------------------------------------------------------
  554. BOOL
  555. CCertEncodeAltName::_VerifyName(
  556. IN LONG NameIndex)
  557. {
  558. HRESULT hr;
  559. BOOL fOk = FALSE;
  560. CERT_ALT_NAME_ENTRY *pName;
  561. assert(m_fConstructing);
  562. hr = _MapName(TRUE, NameIndex, &pName);
  563. if (S_OK != hr)
  564. {
  565. ceERRORPRINTLINE("_MapName", hr);
  566. goto error;
  567. }
  568. assert(NULL != pName);
  569. switch (_NameType(pName->dwAltNameChoice))
  570. {
  571. case enumOther:
  572. if (NULL != pName->pOtherName &&
  573. NULL != pName->pOtherName->pszObjId &&
  574. NULL != pName->pOtherName->Value.pbData)
  575. {
  576. break;
  577. }
  578. // FALLTHROUGH
  579. case enumUnknown:
  580. hr = E_INVALIDARG;
  581. ceERRORPRINTLINE("uninitialized name", hr);
  582. goto error;
  583. }
  584. fOk = TRUE;
  585. error:
  586. return(fOk);
  587. }
  588. //+--------------------------------------------------------------------------
  589. // CCertEncodeAltName::Encode -- Encode AltName
  590. //
  591. // Returns S_OK on success.
  592. //+--------------------------------------------------------------------------
  593. STDMETHODIMP
  594. CCertEncodeAltName::Encode(
  595. /* [out, retval] */ BSTR __RPC_FAR *pstrBinary)
  596. {
  597. HRESULT hr = S_OK;
  598. CERT_ALT_NAME_INFO AltName;
  599. BYTE *pbEncoded = NULL;
  600. DWORD cbEncoded;
  601. LONG i;
  602. if (NULL == pstrBinary)
  603. {
  604. hr = E_POINTER;
  605. ceERRORPRINTLINE("NULL parm", hr);
  606. goto error;
  607. }
  608. AltName.cAltEntry = m_cValue;
  609. AltName.rgAltEntry = m_aValue;
  610. ceFreeBstr(pstrBinary);
  611. if (!m_fConstructing || NULL == m_aValue)
  612. {
  613. hr = E_INVALIDARG;
  614. ceERRORPRINTLINE("bad parameter", hr);
  615. goto error;
  616. }
  617. for (i = 0; i < m_cValue; i++)
  618. {
  619. // Verify all entries are initialized:
  620. if (!_VerifyName(i))
  621. {
  622. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  623. ceERRORPRINTLINE("uninitialized name", hr);
  624. goto error;
  625. }
  626. }
  627. // Encode CERT_ALT_NAME_INFO:
  628. if (!ceEncodeObject(
  629. X509_ASN_ENCODING,
  630. X509_ALTERNATE_NAME,
  631. &AltName,
  632. 0,
  633. FALSE,
  634. &pbEncoded,
  635. &cbEncoded))
  636. {
  637. hr = ceHLastError();
  638. ceERRORPRINTLINE("ceEncodeObject", hr);
  639. goto error;
  640. }
  641. if (!ceConvertWszToBstr(pstrBinary, (WCHAR const *) pbEncoded, cbEncoded))
  642. {
  643. hr = E_OUTOFMEMORY;
  644. ceERRORPRINTLINE("ceConvertWszToBstr", hr);
  645. goto error;
  646. }
  647. error:
  648. if (NULL != pbEncoded)
  649. {
  650. LocalFree(pbEncoded);
  651. }
  652. return(_SetErrorInfo(hr, L"CCertEncodeAltName::Encode"));
  653. }
  654. //+--------------------------------------------------------------------------
  655. // CCertEncodeAltName::_SetErrorInfo -- set error object information
  656. //
  657. // Returns passed HRESULT
  658. //+--------------------------------------------------------------------------
  659. HRESULT
  660. CCertEncodeAltName::_SetErrorInfo(
  661. IN HRESULT hrError,
  662. IN WCHAR const *pwszDescription)
  663. {
  664. assert(FAILED(hrError) || S_OK == hrError || S_FALSE == hrError);
  665. if (FAILED(hrError))
  666. {
  667. HRESULT hr;
  668. hr = ceDispatchSetErrorInfo(
  669. hrError,
  670. pwszDescription,
  671. wszCLASS_CERTENCODEALTNAME,
  672. &IID_ICertEncodeAltName);
  673. assert(hr == hrError);
  674. }
  675. return(hrError);
  676. }