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.

1865 lines
48 KiB

  1. /*===================================================================
  2. Microsoft Denali
  3. Microsoft Confidential.
  4. Copyright 1996 Microsoft Corporation. All Rights Reserved.
  5. Component: Request, Response objects
  6. File: clcert.cpp
  7. Owner: DGottner
  8. This file contains the code for the implementation of the
  9. Request.ClientCertificate
  10. ===================================================================*/
  11. #include "denpre.h"
  12. #pragma hdrstop
  13. #include <schnlsp.h>
  14. #include "objbase.h"
  15. #include "request.h"
  16. #include "clcert.h"
  17. #include "memchk.h"
  18. #pragma warning (disable: 4355) // ignore: "'this' used in base member init
  19. #define UUENCODEDSIZE(a) ((((a)+3)*4)/3+1)
  20. #define BLOB_AS_ARRAY
  21. HRESULT
  22. SetVariantAsByteArray(
  23. VARIANT* pvarReturn,
  24. DWORD cbLen,
  25. LPBYTE pbIn
  26. );
  27. //
  28. // Taken from NCSA HTTP and wwwlib.
  29. //
  30. // NOTE: These conform to RFC1113, which is slightly different then the Unix
  31. // uuencode and uudecode!
  32. //
  33. const int _pr2six[256]={
  34. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  35. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63,
  36. 52,53,54,55,56,57,58,59,60,61,64,64,64,64,64,64,64,0,1,2,3,4,5,6,7,8,9,
  37. 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27,
  38. 28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
  39. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  40. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  41. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  42. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  43. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  44. 64,64,64,64,64,64,64,64,64,64,64,64,64
  45. };
  46. char _six2pr[64] = {
  47. 'A','B','C','D','E','F','G','H','I','J','K','L','M',
  48. 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
  49. 'a','b','c','d','e','f','g','h','i','j','k','l','m',
  50. 'n','o','p','q','r','s','t','u','v','w','x','y','z',
  51. '0','1','2','3','4','5','6','7','8','9','+','/'
  52. };
  53. const int _pr2six64[256]={
  54. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  55. 64,64,64,64,64,64,64,64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
  56. 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,
  57. 40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
  58. 0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  59. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  60. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  61. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  62. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  63. 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  64. 64,64,64,64,64,64,64,64,64,64,64,64,64
  65. };
  66. char _six2pr64[64] = {
  67. '`','!','"','#','$','%','&','\'','(',')','*','+',',',
  68. '-','.','/','0','1','2','3','4','5','6','7','8','9',
  69. ':',';','<','=','>','?','@','A','B','C','D','E','F',
  70. 'G','H','I','J','K','L','M','N','O','P','Q','R','S',
  71. 'T','U','V','W','X','Y','Z','[','\\',']','^','_'
  72. };
  73. /*------------------------------------------------------------------
  74. * X B F
  75. */
  76. BOOL XBF::Extend( int cA )
  77. {
  78. if ( cA > m_cAlloc )
  79. {
  80. int cNew = (( cA + XBF_EXTEND )/XBF_EXTEND)*XBF_EXTEND;
  81. LPSTR pN = (LPSTR)malloc( cNew );
  82. if ( pN == NULL )
  83. {
  84. return FALSE;
  85. }
  86. if ( m_cSize )
  87. {
  88. memcpy( pN, m_pV, m_cSize );
  89. }
  90. if ( m_cAlloc )
  91. {
  92. free( m_pV );
  93. }
  94. m_pV = pN;
  95. m_cAlloc = cNew;
  96. }
  97. return TRUE;
  98. }
  99. /*------------------------------------------------------------------
  100. * C C l C e r t S u p p o r t E r r
  101. */
  102. /*===================================================================
  103. CClCertSupportErr::CClCertSupportErr
  104. constructor
  105. ===================================================================*/
  106. CClCertSupportErr::CClCertSupportErr(CClCert *pClCert)
  107. {
  108. m_pClCert = pClCert;
  109. }
  110. /*===================================================================
  111. CClCertSupportErr::QueryInterface
  112. CClCertSupportErr::AddRef
  113. CClCertSupportErr::Release
  114. Delegating IUnknown members for CClCertSupportErr object.
  115. ===================================================================*/
  116. STDMETHODIMP CClCertSupportErr::QueryInterface(const IID &idInterface, void **ppvObj)
  117. {
  118. return m_pClCert->QueryInterface(idInterface, ppvObj);
  119. }
  120. STDMETHODIMP_(ULONG) CClCertSupportErr::AddRef()
  121. {
  122. return m_pClCert->AddRef();
  123. }
  124. STDMETHODIMP_(ULONG) CClCertSupportErr::Release()
  125. {
  126. return m_pClCert->Release();
  127. }
  128. /*===================================================================
  129. CClCertSupportErr::InterfaceSupportsErrorInfo
  130. Report back to OA about which interfaces we support that return
  131. error information
  132. ===================================================================*/
  133. STDMETHODIMP CClCertSupportErr::InterfaceSupportsErrorInfo(const GUID &idInterface)
  134. {
  135. if (idInterface == IID_IDispatch)
  136. return S_OK;
  137. return S_FALSE;
  138. }
  139. /*------------------------------------------------------------------
  140. * C R e a d C l C e r t
  141. */
  142. /*===================================================================
  143. CReadClCert::CReadClCert
  144. constructor
  145. ===================================================================*/
  146. CReadClCert::CReadClCert(CClCert *pClCert)
  147. {
  148. m_pClCert = pClCert;
  149. CDispatch::Init(IID_IRequestDictionary);
  150. }
  151. /*===================================================================
  152. CReadClCert::QueryInterface
  153. CReadClCert::AddRef
  154. CReadClCert::Release
  155. Delegating IUnknown members for CReadClCert object.
  156. ===================================================================*/
  157. STDMETHODIMP CReadClCert::QueryInterface(const IID &idInterface, void **ppvObj)
  158. {
  159. return m_pClCert->QueryInterface(idInterface, ppvObj);
  160. }
  161. STDMETHODIMP_(ULONG) CReadClCert::AddRef()
  162. {
  163. return m_pClCert->AddRef();
  164. }
  165. STDMETHODIMP_(ULONG) CReadClCert::Release()
  166. {
  167. return m_pClCert->Release();
  168. }
  169. /*===================================================================
  170. CReadClCert::get_Item
  171. Retrieve a value in the clcert dictionary.
  172. ===================================================================*/
  173. STDMETHODIMP CReadClCert::get_Item(VARIANT varKey, VARIANT *pVarReturn)
  174. {
  175. VariantInit(pVarReturn); // default return value is Empty
  176. VARIANT *pvarKey = &varKey;
  177. HRESULT hres;
  178. // BUG 937: VBScript passes VT_VARIANT|VT_BYREF when passing obect
  179. // produced by IEnumVariant
  180. //
  181. // Use VariantResolveDispatch which will:
  182. //
  183. // * Copy BYREF variants for us using VariantCopyInd
  184. // * handle E_OUTOFMEMORY for us
  185. // * get the default value from an IDispatch, which seems
  186. // like an appropriate conversion.
  187. //
  188. VARIANT varKeyCopy;
  189. VariantInit(&varKeyCopy);
  190. if (V_VT(pvarKey) != VT_BSTR) {
  191. if (FAILED(VariantResolveDispatch(&varKeyCopy, &varKey, IID_IRequestDictionary, IDE_REQUEST)))
  192. goto LExit;
  193. pvarKey = &varKeyCopy;
  194. }
  195. switch (V_VT(pvarKey)) {
  196. case VT_BSTR:
  197. break;
  198. case VT_ERROR:
  199. if (V_ERROR(pvarKey) == DISP_E_PARAMNOTFOUND) {
  200. // simple value, URLEncoding NOT a good idea in this case
  201. if (m_pClCert->m_szValue) {
  202. V_VT(pVarReturn) = VT_BSTR;
  203. switch( m_pClCert->m_veType ) {
  204. case VT_BSTR: {
  205. BSTR bstrT;
  206. if ( FAILED(SysAllocStringFromSz(m_pClCert->m_szValue, 0, &bstrT )) ) {
  207. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  208. VariantClear(&varKeyCopy);
  209. return E_FAIL;
  210. }
  211. V_BSTR(pVarReturn) = bstrT;
  212. break;
  213. }
  214. case VT_DATE:
  215. V_VT(pVarReturn) = VT_DATE;
  216. V_DATE(pVarReturn) = *(UNALIGNED64 DATE*)m_pClCert->m_szValue;
  217. break;
  218. case VT_I4:
  219. V_VT(pVarReturn) = VT_I4;
  220. V_I4(pVarReturn) = *(UNALIGNED64 DWORD*)m_pClCert->m_szValue;
  221. break;
  222. case VT_BLOB:
  223. #if defined(BLOB_AS_ARRAY)
  224. if ( FAILED( hres = SetVariantAsByteArray( pVarReturn,
  225. m_pClCert->m_cLen,
  226. (LPBYTE)m_pClCert->m_szValue ) ) ) {
  227. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  228. VariantClear(&varKeyCopy);
  229. return hres;
  230. }
  231. #else
  232. V_BSTR(pVarReturn) = SysAllocStringByteLen(m_pClCert->m_szValue, m_pClCert->m_cLen );
  233. #endif
  234. break;
  235. default:
  236. Assert( FALSE );
  237. }
  238. }
  239. // dictionary value, must URLEncode to prevent '&', '=' from being misinterpreted
  240. else {
  241. }
  242. VariantClear(&varKeyCopy);
  243. return S_OK;
  244. }
  245. default:
  246. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_EXPECTING_STR);
  247. VariantClear(&varKeyCopy);
  248. return E_FAIL;
  249. }
  250. LExit:
  251. VariantClear(&varKeyCopy);
  252. return S_OK;
  253. }
  254. /*===================================================================
  255. CReadClCert::get_Key
  256. Function called from DispInvoke to get keys from the QueryString collection.
  257. Parameters:
  258. vKey VARIANT [in], which parameter to get the key of
  259. pvarReturn VARIANT *, [out] value of the requested parameter
  260. Returns:
  261. S_OK on success, E_FAIL on failure.
  262. ===================================================================*/
  263. HRESULT CReadClCert::get_Key(VARIANT varKey, VARIANT *pVar)
  264. {
  265. return E_NOTIMPL;
  266. }
  267. /*===================================================================
  268. CReadClCert::get_Count
  269. Parameters:
  270. pcValues - count is stored in *pcValues
  271. ===================================================================*/
  272. STDMETHODIMP CReadClCert::get_Count(int *pcValues)
  273. {
  274. HRESULT hrReturn = S_OK;
  275. *pcValues = 0;
  276. return hrReturn;
  277. }
  278. /*===================================================================
  279. CReadClCert::get__NewEnum
  280. Return an enumerator object.
  281. ===================================================================*/
  282. STDMETHODIMP CReadClCert::get__NewEnum(IUnknown **ppEnum)
  283. {
  284. *ppEnum = NULL;
  285. return E_NOTIMPL;
  286. }
  287. /*------------------------------------------------------------------
  288. * C C l C e r t
  289. */
  290. /*===================================================================
  291. CClCert::CClCert
  292. constructor
  293. ===================================================================*/
  294. CClCert::CClCert(IUnknown *pUnkOuter, PFNDESTROYED pfnDestroy)
  295. : m_ReadClCertInterface(this),
  296. m_ClCertSupportErrorInfo(this)
  297. {
  298. m_szValue = NULL;
  299. m_veType = VT_BSTR;
  300. m_pfnDestroy = pfnDestroy;
  301. m_cRefs = 1;
  302. }
  303. /*===================================================================
  304. CClCert::~CClCert
  305. Destructor
  306. ===================================================================*/
  307. CClCert::~CClCert()
  308. {
  309. }
  310. /*===================================================================
  311. CClCert::Init
  312. initialize the clcert. This initializes the clcert's value hashing
  313. table
  314. ===================================================================*/
  315. HRESULT CClCert::Init()
  316. {
  317. return S_OK;
  318. }
  319. /*===================================================================
  320. CClCert::QueryInterface
  321. CClCert::AddRef
  322. CClCert::Release
  323. IUnknown members for CClCert object.
  324. Note on CClCert::QueryInterface: The Query for IDispatch is
  325. ambiguous because it can either refer to DIRequestDictionary or
  326. DIWriteClCert. To resolve this, we resolve requests for IDispatch
  327. to IRequestDictionary.
  328. ===================================================================*/
  329. STDMETHODIMP CClCert::QueryInterface(const IID &idInterface, void **ppvObj)
  330. {
  331. if (idInterface == IID_IUnknown)
  332. *ppvObj = this;
  333. else if (idInterface == IID_IRequestDictionary || idInterface == IID_IDispatch)
  334. *ppvObj = &m_ReadClCertInterface;
  335. else if (idInterface == IID_ISupportErrorInfo)
  336. *ppvObj = &m_ClCertSupportErrorInfo;
  337. else
  338. *ppvObj = NULL;
  339. if (*ppvObj != NULL)
  340. {
  341. static_cast<IUnknown *>(*ppvObj)->AddRef();
  342. return S_OK;
  343. }
  344. return ResultFromScode(E_NOINTERFACE);
  345. }
  346. STDMETHODIMP_(ULONG) CClCert::AddRef()
  347. {
  348. return ++m_cRefs;
  349. }
  350. STDMETHODIMP_(ULONG) CClCert::Release(void)
  351. {
  352. if (--m_cRefs != 0)
  353. return m_cRefs;
  354. if (m_pfnDestroy != NULL)
  355. (*m_pfnDestroy)();
  356. delete this;
  357. return 0;
  358. }
  359. /*===================================================================
  360. CClCert::AddValue
  361. Set the clcert's primary value. One you set the primary value,
  362. you can't reset it.
  363. ===================================================================*/
  364. HRESULT CClCert::AddValue(char *szValue, VARENUM ve, UINT l )
  365. {
  366. if (m_szValue != NULL) // clcert already is marked as single-valued
  367. return E_FAIL;
  368. m_szValue = szValue;
  369. m_veType = ve;
  370. m_cLen = l;
  371. return S_OK;
  372. }
  373. /*===================================================================
  374. CClCert::GetHTTPClCertSize
  375. Return the number of bytes required for the expansion of the clcert
  376. ===================================================================*/
  377. size_t CClCert::GetHTTPClCertSize()
  378. {
  379. if (m_szValue)
  380. return URLEncodeLen(m_szValue);
  381. else
  382. return 1;
  383. }
  384. /*===================================================================
  385. CClCert::GetHTTPClCert
  386. Return the URL Encoded value a single clcert
  387. Parameters:
  388. szBuffer - pointer to the destination buffer to store the
  389. URL encoded value
  390. Returns:
  391. Returns a pointer to the terminating NUL character.
  392. ===================================================================*/
  393. char *CClCert::GetHTTPClCert(char *szBuffer)
  394. {
  395. if (m_szValue)
  396. return URLEncode(szBuffer, m_szValue);
  397. else
  398. {
  399. char *szDest = szBuffer;
  400. *szDest = '\0';
  401. return szDest;
  402. }
  403. }
  404. /*===================================================================
  405. CClCert::GetClCertHeaderSize
  406. Return the number of bytes required to allocate for the "Set-ClCert" header.
  407. Parameters:
  408. szName - the name of the cookie (the size of the name is added to the value)
  409. Returns:
  410. Returns 0 if *this does not contain a cookie value.
  411. ===================================================================*/
  412. size_t CClCert::GetClCertHeaderSize(const char *szName)
  413. {
  414. int cbClCert = sizeof "Set-ClCert: "; // initialize and add NUL terminator now
  415. // Add size of the URL Encoded name, a character for the '=', and the size
  416. // of the URL Encoded cookie value. URLEncodeLen, and GetHttpClCertSize
  417. // compensate for the NUL terminator, so we actually SUBTRACT 1. (-2 for
  418. // these two function calls, +1 for the '=' sign
  419. //
  420. cbClCert += URLEncodeLen(szName) + GetHTTPClCertSize() - 1;
  421. return cbClCert;
  422. }
  423. /*===================================================================
  424. CClCert::GetClCertHeader
  425. Construct the appropriate "Set-ClCert" header for a clcert.
  426. Parameters:
  427. szName - the name of the clcert (the size of the name is added to the value)
  428. Returns:
  429. Returns 0 if *this does not contain a clcert value.
  430. ===================================================================*/
  431. char *CClCert::GetClCertHeader(const char *szName, char *szBuffer)
  432. {
  433. // write out the clcert name and value
  434. //
  435. char *szDest = strcpyExA(szBuffer, "Set-ClCert: ");
  436. szDest = URLEncode(szDest, szName);
  437. szDest = strcpyExA(szDest, "=");
  438. szDest = GetHTTPClCert(szDest);
  439. return szDest;
  440. }
  441. /*------------------------------------------------------------------
  442. * C C e r t R e q u e s t
  443. */
  444. /*===================================================================
  445. CCertRequest::AddStringPair
  446. Add a string element in the collection
  447. Parameters:
  448. Source - variable type ( CLCERT, COOKIE, ... )
  449. szName - name of element
  450. szValue - ptr to value as string
  451. pxbf - ptr to buffer where to store name
  452. Returns:
  453. S_OK if success, E_OUTOFMEMORY or E_FAIL otherwise
  454. ===================================================================*/
  455. HRESULT
  456. CCertRequest::AddStringPair(
  457. CollectionType Source,
  458. LPSTR szName,
  459. LPSTR szValue,
  460. XBF *pxbf,
  461. BOOL fDuplicate,
  462. UINT lCodePage
  463. )
  464. {
  465. HRESULT hResult;
  466. CRequestHit *pReqHit;
  467. if ( fDuplicate )
  468. {
  469. if ( (szValue = pxbf->AddStringZ( szValue )) == NULL )
  470. {
  471. return E_OUTOFMEMORY;
  472. }
  473. }
  474. if (FAILED(hResult = AddName( szName, &pReqHit, pxbf)))
  475. {
  476. if ( hResult == E_FAIL )
  477. {
  478. // assume duplicate value found
  479. // if out of memore, OUT_OF_MEMORY would have been returned
  480. hResult = S_OK;
  481. }
  482. return hResult;
  483. }
  484. if (FAILED(hResult = pReqHit->AddValue( Source, szValue, NULL, lCodePage )))
  485. {
  486. return hResult;
  487. }
  488. return S_OK;
  489. }
  490. /*===================================================================
  491. CCertRequest::AddDatePair
  492. Add a date element in the collection
  493. Parameters:
  494. Source - variable type ( CLCERT, COOKIE, ... )
  495. szName - name of element
  496. pValue - ptr to date as FILETIME
  497. pxbf - ptr to buffer where to store name
  498. Returns:
  499. S_OK if success, E_OUTOFMEMORY or E_FAIL otherwise
  500. ===================================================================*/
  501. HRESULT
  502. CCertRequest::AddDatePair(
  503. CollectionType Source,
  504. LPSTR szName,
  505. FILETIME* pValue,
  506. XBF *pxbf
  507. )
  508. {
  509. HRESULT hResult;
  510. CRequestHit *pReqHit;
  511. DATE Date;
  512. SYSTEMTIME st;
  513. LPBYTE pVal;
  514. if ( !FileTimeToSystemTime( pValue, &st ) )
  515. {
  516. return E_FAIL;
  517. }
  518. SystemTimeToVariantTime( &st, &Date );
  519. if ( (pVal = (LPBYTE)pxbf->AddBlob( (LPSTR)&Date, sizeof(Date) )) == NULL )
  520. {
  521. return E_OUTOFMEMORY;
  522. }
  523. if (FAILED(hResult = AddName( szName, &pReqHit, pxbf)))
  524. {
  525. return hResult;
  526. }
  527. if (FAILED(hResult = pReqHit->AddCertValue( VT_DATE, pVal, sizeof(Date) )))
  528. {
  529. return hResult;
  530. }
  531. return S_OK;
  532. }
  533. /*===================================================================
  534. CCertRequest::AddDwordPair
  535. Add a DWORD element in the collection
  536. Parameters:
  537. Source - variable type ( CLCERT, COOKIE, ... )
  538. szName - name of element
  539. pValue - ptr to date as DWORD
  540. pxbf - ptr to buffer where to store name
  541. Returns:
  542. S_OK if success, E_OUTOFMEMORY or E_FAIL otherwise
  543. ===================================================================*/
  544. HRESULT
  545. CCertRequest::AddDwordPair(
  546. CollectionType Source,
  547. LPSTR szName,
  548. DWORD* pValue,
  549. XBF *pxbf
  550. )
  551. {
  552. HRESULT hResult;
  553. CRequestHit *pReqHit;
  554. LPBYTE pVal;
  555. if ( (pVal = (LPBYTE)pxbf->AddBlob( (LPSTR)pValue, sizeof(DWORD) )) == NULL )
  556. {
  557. return E_OUTOFMEMORY;
  558. }
  559. if (FAILED(hResult = AddName( szName, &pReqHit, pxbf)))
  560. {
  561. return hResult;
  562. }
  563. if (FAILED(hResult = pReqHit->AddCertValue( VT_I4, pVal, sizeof(DWORD) )))
  564. {
  565. return hResult;
  566. }
  567. return S_OK;
  568. }
  569. /*===================================================================
  570. CCertRequest::AddBinaryPair
  571. Add a binary element in the collection
  572. Each byte is converted to UNICODE character so that mid() & asc() work
  573. Parameters:
  574. Source - variable type ( CLCERT, COOKIE, ... )
  575. szName - name of element
  576. pValue - ptr to value as byte array
  577. cValue - # of bytes pointed to by pValue
  578. pxbf - ptr to buffer where to store name
  579. Returns:
  580. S_OK if success, E_OUTOFMEMORY or E_FAIL otherwise
  581. ===================================================================*/
  582. HRESULT
  583. CCertRequest::AddBinaryPair(
  584. CollectionType Source,
  585. LPSTR szName,
  586. LPBYTE pValue,
  587. DWORD cValue,
  588. XBF *pxbf,
  589. UINT lCodePage
  590. )
  591. {
  592. HRESULT hResult;
  593. CRequestHit *pReqHit;
  594. LPBYTE pVal;
  595. #if defined(BLOB_AS_ARRAY)
  596. if ( (pVal = (LPBYTE)pxbf->ReserveRange( cValue )) == NULL )
  597. {
  598. return E_OUTOFMEMORY;
  599. }
  600. memcpy( pVal, pValue, cValue );
  601. pxbf->SkipRange( cValue );
  602. if (FAILED(hResult = AddName( szName, &pReqHit, pxbf)))
  603. {
  604. return hResult;
  605. }
  606. if (FAILED(hResult = pReqHit->AddCertValue( VT_BLOB, pVal, cValue )))
  607. {
  608. return hResult;
  609. }
  610. #else
  611. if ( (pVal = (LPBYTE)pxbf->ReserveRange( cValue * sizeof(WCHAR), sizeof(WCHAR))) == NULL )
  612. {
  613. return E_OUTOFMEMORY;
  614. }
  615. if ( !(cValue = MultiByteToWideChar( lCodePage, 0, (LPSTR)pValue, cValue, (WCHAR*)pVal, cValue)) )
  616. {
  617. return E_FAIL;
  618. }
  619. pxbf->SkipRange( cValue * sizeof(WCHAR), sizeof(WCHAR));
  620. if (FAILED(hResult = AddName( szName, &pReqHit, pxbf)))
  621. {
  622. return hResult;
  623. }
  624. if (FAILED(hResult = pReqHit->AddCertValue( VT_BLOB, pVal, cValue * sizeof(WCHAR) )))
  625. {
  626. return hResult;
  627. }
  628. #endif
  629. return S_OK;
  630. }
  631. BOOL IISuuencode( BYTE * bufin,
  632. DWORD nbytes,
  633. BYTE * outptr,
  634. BOOL fBase64 )
  635. {
  636. unsigned int i;
  637. char *six2pr = fBase64 ? _six2pr64 : _six2pr;
  638. for (i=0; i<nbytes; i += 3) {
  639. *(outptr++) = six2pr[*bufin >> 2]; /* c1 */
  640. *(outptr++) = six2pr[((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)]; /*c2*/
  641. *(outptr++) = six2pr[((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03)];/*c3*/
  642. *(outptr++) = six2pr[bufin[2] & 077]; /* c4 */
  643. bufin += 3;
  644. }
  645. /* If nbytes was not a multiple of 3, then we have encoded too
  646. * many characters. Adjust appropriately.
  647. */
  648. if(i == nbytes+1) {
  649. /* There were only 2 bytes in that last group */
  650. outptr[-1] = '=';
  651. } else if(i == nbytes+2) {
  652. /* There was only 1 byte in that last group */
  653. outptr[-1] = '=';
  654. outptr[-2] = '=';
  655. }
  656. *outptr = '\0';
  657. return TRUE;
  658. }
  659. /*===================================================================
  660. CCertRequest::AddUuBinaryPair
  661. Add a binary element in the collection
  662. buffer is uuencoded then converted to UNICODE character so that mid() & asc() work
  663. Parameters:
  664. Source - variable type ( CLCERT, COOKIE, ... )
  665. szName - name of element
  666. pValue - ptr to value as byte array
  667. cValue - # of bytes pointed to by pValue
  668. pxbf - ptr to buffer where to store name
  669. Returns:
  670. S_OK if success, E_OUTOFMEMORY or E_FAIL otherwise
  671. ===================================================================*/
  672. HRESULT
  673. CCertRequest::AddUuBinaryPair(
  674. CollectionType Source,
  675. LPSTR szName,
  676. LPBYTE pValue,
  677. DWORD cValue,
  678. XBF *pxbf,
  679. UINT lCodePage
  680. )
  681. {
  682. HRESULT hResult;
  683. CRequestHit *pReqHit;
  684. LPBYTE pVal;
  685. if ( (pVal = (LPBYTE)pxbf->ReserveRange( UUENCODEDSIZE(cValue) )) == NULL )
  686. {
  687. return E_OUTOFMEMORY;
  688. }
  689. if ( !IISuuencode( (LPBYTE)pValue, cValue, pVal, FALSE ) )
  690. {
  691. return E_FAIL;
  692. }
  693. Assert( (strlen((LPSTR)pVal)+1) <= UUENCODEDSIZE(cValue) );
  694. pxbf->SkipRange( strlen((LPSTR)pVal)+1 );
  695. if (FAILED(hResult = AddName( szName, &pReqHit, pxbf)))
  696. {
  697. return hResult;
  698. }
  699. if (FAILED(hResult = pReqHit->AddValue( Source, (LPSTR)pVal, NULL, lCodePage )))
  700. {
  701. return hResult;
  702. }
  703. return S_OK;
  704. }
  705. /*===================================================================
  706. CCertRequest::AddName
  707. Add a named entry to the collection
  708. Parameters:
  709. szName - name of entry
  710. ppReqHit - updated with ptr to created entry
  711. pxbf - ptr to buffer where to store name
  712. Returns:
  713. S_OK if success, E_OUTOFMEMORY or E_FAIL otherwise
  714. ===================================================================*/
  715. HRESULT
  716. CCertRequest::AddName(
  717. LPSTR szName,
  718. CRequestHit **ppReqHit,
  719. XBF *pxbf
  720. )
  721. {
  722. if ( (szName = pxbf->AddStringZ( szName )) == NULL )
  723. {
  724. return E_OUTOFMEMORY;
  725. }
  726. // Add this object to the Request
  727. CRequestHit *pRequestHit = (CRequestHit *)(pReq->CertStoreFindElem(szName, strlen(szName)));
  728. if (pRequestHit == NULL)
  729. {
  730. pRequestHit = new CRequestHit;
  731. if (pRequestHit == NULL)
  732. {
  733. return E_OUTOFMEMORY;
  734. }
  735. if (FAILED(pRequestHit->Init(szName)))
  736. {
  737. delete pRequestHit;
  738. return E_FAIL;
  739. }
  740. pReq->CertStoreAddElem( (CLinkElem*) pRequestHit );
  741. }
  742. else if (pRequestHit->m_pClCertData) // a clcert by this name already exists
  743. {
  744. return E_FAIL;
  745. }
  746. if (!pReq->m_pData->m_ClCerts.AddRequestHit(pRequestHit))
  747. {
  748. return E_OUTOFMEMORY;
  749. }
  750. *ppReqHit = pRequestHit;
  751. return S_OK;
  752. }
  753. typedef struct _MAP_ASN {
  754. LPSTR pAsnName;
  755. LPSTR pTextName;
  756. } MAP_ASN;
  757. //
  758. // definition of ASN.1 <> X.509 name conversion
  759. //
  760. MAP_ASN aMapAsn[] = {
  761. { szOID_COUNTRY_NAME, "C" },
  762. { szOID_ORGANIZATION_NAME, "O" },
  763. { szOID_ORGANIZATIONAL_UNIT_NAME, "OU" },
  764. { szOID_COMMON_NAME, "CN" },
  765. { szOID_LOCALITY_NAME, "L" },
  766. { szOID_STATE_OR_PROVINCE_NAME, "S" },
  767. { szOID_TITLE, "T" },
  768. { szOID_GIVEN_NAME, "GN" },
  769. { szOID_INITIALS, "I" },
  770. { "1.2.840.113549.1.9.1", "EMAIL" },
  771. } ;
  772. LPSTR MapAsnName(
  773. LPSTR pAsnName
  774. )
  775. /*++
  776. Routine Description:
  777. Convert ASN.1 name ( as ANSI string ) to X.509 member name
  778. Arguments:
  779. pAsnName - ASN.1 name
  780. Return Value:
  781. ptr to converted name if ASN.1 name was recognized, else ASN.1 name
  782. --*/
  783. {
  784. UINT x;
  785. for ( x = 0 ; x < sizeof(aMapAsn)/sizeof(MAP_ASN) ; ++x )
  786. {
  787. if ( !strcmp( pAsnName, aMapAsn[x].pAsnName ) )
  788. {
  789. return aMapAsn[x].pTextName;
  790. }
  791. }
  792. return pAsnName;
  793. }
  794. BOOL
  795. DecodeRdn(
  796. CERT_NAME_BLOB* pNameBlob,
  797. PCERT_NAME_INFO* ppNameInfo
  798. )
  799. /*++
  800. Routine Description:
  801. Create a PNAME_INFO from PNAME_BLOB
  802. Arguments:
  803. pNameBlob - ptr to name blob to decode
  804. ppNameInfo - updated with ptr to name info
  805. Return Value:
  806. TRUE on success, FALSE on failure
  807. --*/
  808. {
  809. PCERT_NAME_INFO pNameInfo = NULL;
  810. DWORD cbNameInfo;
  811. if (!CryptDecodeObject(X509_ASN_ENCODING,
  812. (LPCSTR)X509_NAME,
  813. pNameBlob->pbData,
  814. pNameBlob->cbData,
  815. 0,
  816. NULL,
  817. &cbNameInfo))
  818. {
  819. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_CERTIFICATE_BAD_CERT);
  820. return FALSE;
  821. }
  822. if (NULL == (pNameInfo = (PCERT_NAME_INFO)malloc(cbNameInfo)))
  823. {
  824. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  825. return FALSE;
  826. }
  827. if (!CryptDecodeObject(X509_ASN_ENCODING,
  828. (LPCSTR)X509_NAME,
  829. pNameBlob->pbData,
  830. pNameBlob->cbData,
  831. 0,
  832. pNameInfo,
  833. &cbNameInfo))
  834. {
  835. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_CERTIFICATE_BAD_CERT);
  836. free( pNameInfo );
  837. return FALSE;
  838. }
  839. *ppNameInfo = pNameInfo;
  840. return TRUE;
  841. }
  842. VOID
  843. FreeDecodedRdn(
  844. PCERT_NAME_INFO pNameInfo
  845. )
  846. /*++
  847. Routine Description:
  848. Free a PNAME_BLOB created by DecodeRdn()
  849. Arguments:
  850. pNameInfo - ptr to name info created by DecodeRdn()
  851. Return Value:
  852. None
  853. --*/
  854. {
  855. free( pNameInfo );
  856. }
  857. BOOL
  858. BuildRdnList(
  859. PCERT_NAME_INFO pNameInfo,
  860. XBF* pxbf,
  861. BOOL fXt
  862. )
  863. /*++
  864. Routine Description:
  865. Build a clear text representation of the Rdn list in pNameInfo
  866. Format as "C=US, O=Ms, CN=name"
  867. Arguments:
  868. pNameInfo - ptr to name info
  869. pxbf - ptr to buffer receiving output
  870. fXt - TRUE if buffer to be extended, FALSE does not extend ( buffer
  871. must be big enough before calling this function or FALSE will
  872. be returned )
  873. Return Value:
  874. TRUE on success, FALSE on failure
  875. --*/
  876. {
  877. DWORD cRDN;
  878. DWORD cAttr;
  879. PCERT_RDN pRDN;
  880. PCERT_RDN_ATTR pAttr;
  881. BOOL fFirst = TRUE;
  882. for (cRDN = pNameInfo->cRDN, pRDN = pNameInfo->rgRDN; cRDN > 0; cRDN--, pRDN++)
  883. {
  884. for ( cAttr = pRDN->cRDNAttr, pAttr = pRDN->rgRDNAttr ; cAttr > 0 ; cAttr--, ++pAttr )
  885. {
  886. if ( !fFirst )
  887. {
  888. if ( !pxbf->AddBlob( ", ", sizeof(", ")-1, fXt ) )
  889. {
  890. return FALSE;
  891. }
  892. }
  893. else
  894. {
  895. fFirst = FALSE;
  896. }
  897. if ( pAttr->dwValueType == CERT_RDN_UNICODE_STRING )
  898. {
  899. INT iRet;
  900. BYTE abBuffer[ 512 ];
  901. DWORD cbNameBuffer;
  902. PBYTE pNameBuffer = NULL;
  903. //
  904. // Need to convert unicode string to MBCS :(
  905. //
  906. iRet = WideCharToMultiByte( CP_ACP,
  907. 0,
  908. (LPWSTR) pAttr->Value.pbData,
  909. -1,
  910. NULL,
  911. 0,
  912. NULL,
  913. NULL );
  914. if ( !iRet )
  915. {
  916. return FALSE;
  917. }
  918. else
  919. {
  920. cbNameBuffer = (DWORD) iRet;
  921. if ( (DWORD) iRet > sizeof( abBuffer ) )
  922. {
  923. pNameBuffer = (PBYTE) LocalAlloc( LPTR,
  924. (DWORD) iRet );
  925. if ( !pNameBuffer )
  926. {
  927. return FALSE;
  928. }
  929. }
  930. else
  931. {
  932. pNameBuffer = abBuffer;
  933. }
  934. }
  935. iRet = WideCharToMultiByte( CP_ACP,
  936. 0,
  937. (LPWSTR) pAttr->Value.pbData,
  938. -1,
  939. (LPSTR) pNameBuffer,
  940. cbNameBuffer,
  941. NULL,
  942. NULL );
  943. if ( !iRet )
  944. {
  945. if ( pNameBuffer != abBuffer )
  946. {
  947. LocalFree( pNameBuffer );
  948. }
  949. return FALSE;
  950. }
  951. //
  952. // Now stuff the MBCS string back into the blob. I do this
  953. // because there is other code that re-reads and re-processes
  954. // the CRYPTAPI blob.
  955. //
  956. if ( cbNameBuffer <= pAttr->Value.cbData )
  957. {
  958. memcpy( pAttr->Value.pbData,
  959. pNameBuffer,
  960. cbNameBuffer );
  961. pAttr->Value.cbData = cbNameBuffer;
  962. pAttr->dwValueType = CERT_RDN_OCTET_STRING;
  963. }
  964. if ( pNameBuffer != abBuffer )
  965. {
  966. LocalFree( pNameBuffer );
  967. pNameBuffer = NULL;
  968. }
  969. }
  970. if ( !pxbf->AddString( MapAsnName( pAttr->pszObjId ), fXt ) ||
  971. !pxbf->AddBlob( "=", sizeof("=")-1, fXt ) ||
  972. !pxbf->AddString( (LPSTR) pAttr->Value.pbData, fXt ) )
  973. {
  974. return FALSE;
  975. }
  976. }
  977. }
  978. return pxbf->AddBlob( "", sizeof(""), fXt ) != NULL;
  979. }
  980. /*===================================================================
  981. CCertRequest::ParseRDNS
  982. Function called to parse a certificate into a OA collection
  983. Parameters:
  984. pNameInfo - ptr to name structure ( cf. CAPI 2 )
  985. pszPrefix - prefix to prepend to members name
  986. pxbf - ptr to buffer to hold result
  987. Returns:
  988. S_OK on success, E_OUTOFMEMORY if out of memory or E_FAIL for
  989. other errors
  990. ===================================================================*/
  991. HRESULT
  992. CCertRequest::ParseRDNS(
  993. PCERT_NAME_INFO pNameInfo,
  994. LPSTR pszPrefix,
  995. XBF *pxbf,
  996. UINT lCodePage
  997. )
  998. {
  999. DWORD cRDN;
  1000. DWORD cAttr;
  1001. PCERT_RDN pRDN;
  1002. PCERT_RDN_ATTR pAttr;
  1003. DWORD cRDNs;
  1004. DWORD cAttrs;
  1005. PCERT_RDN pRDNs;
  1006. PCERT_RDN_ATTR pAttrs;
  1007. LPSTR pszFullName = NULL;
  1008. HRESULT hRes = S_OK;
  1009. LPSTR pName;
  1010. UINT cL;
  1011. LPSTR pVal = NULL;
  1012. for (cRDN = pNameInfo->cRDN, pRDN = pNameInfo->rgRDN; cRDN > 0; cRDN--, pRDN++)
  1013. {
  1014. for ( cAttr = pRDN->cRDNAttr, pAttr = pRDN->rgRDNAttr ; cAttr > 0 ; cAttr--, ++pAttr )
  1015. {
  1016. if ( pAttr->dwValueType & 0x80000000 )
  1017. {
  1018. continue;
  1019. }
  1020. // scan for attr of same name
  1021. pAttr->dwValueType |= 0x80000000;
  1022. cL = 0;
  1023. pVal = NULL;
  1024. for ( cRDNs = cRDN, pRDNs = pRDN;
  1025. cRDNs > 0;
  1026. cRDNs--, pRDNs++)
  1027. {
  1028. for ( cAttrs = pRDNs->cRDNAttr, pAttrs = pRDNs->rgRDNAttr ;
  1029. cAttrs > 0 ;
  1030. cAttrs--, ++pAttrs )
  1031. {
  1032. if ( !(pAttrs->dwValueType & 0x80000000) &&
  1033. !strcmp( pAttr->pszObjId, pAttrs->pszObjId ) )
  1034. {
  1035. cL += strlen( (LPSTR)pAttrs->Value.pbData ) + 1;
  1036. }
  1037. }
  1038. }
  1039. //
  1040. // if attributes of the same name found, concatenate their
  1041. // values separated by ';'
  1042. //
  1043. if ( cL )
  1044. {
  1045. pVal = (LPSTR)malloc( cL + strlen((LPSTR)pAttr->Value.pbData) + 1 );
  1046. if ( pVal == NULL )
  1047. {
  1048. return E_OUTOFMEMORY;
  1049. }
  1050. strcpy( pVal, (LPSTR)pAttr->Value.pbData );
  1051. for ( cRDNs = cRDN, pRDNs = pRDN;
  1052. cRDNs > 0;
  1053. cRDNs--, pRDNs++)
  1054. {
  1055. for ( cAttrs = pRDNs->cRDNAttr, pAttrs = pRDNs->rgRDNAttr ;
  1056. cAttrs > 0 ;
  1057. cAttrs--, ++pAttrs )
  1058. {
  1059. if ( !(pAttrs->dwValueType & 0x80000000) &&
  1060. !strcmp( pAttr->pszObjId, pAttrs->pszObjId ) )
  1061. {
  1062. strcat( pVal, ";" );
  1063. strcat( pVal, (LPSTR)pAttrs->Value.pbData );
  1064. pAttrs->dwValueType |= 0x80000000;
  1065. }
  1066. }
  1067. }
  1068. }
  1069. pName = MapAsnName( pAttr->pszObjId );
  1070. if ( (pszFullName = (LPSTR)malloc( strlen(pszPrefix)+strlen(pName)+1 )) == NULL )
  1071. {
  1072. hRes = E_OUTOFMEMORY;
  1073. goto cleanup;
  1074. }
  1075. strcpy( pszFullName, pszPrefix );
  1076. strcat( pszFullName, pName );
  1077. if ( (hRes = AddStringPair( CLCERT,
  1078. pszFullName,
  1079. pVal ? pVal : (LPSTR)pAttr->Value.pbData,
  1080. pxbf,
  1081. TRUE,
  1082. lCodePage )) != S_OK )
  1083. {
  1084. if ( pVal != NULL )
  1085. {
  1086. free( pVal );
  1087. }
  1088. goto cleanup;
  1089. }
  1090. if ( pVal != NULL )
  1091. {
  1092. free( pVal );
  1093. pVal = NULL;
  1094. }
  1095. free( pszFullName );
  1096. pszFullName = NULL;
  1097. }
  1098. }
  1099. cleanup:
  1100. if ( pszFullName != NULL )
  1101. {
  1102. free( pszFullName );
  1103. }
  1104. return hRes;
  1105. }
  1106. /*===================================================================
  1107. CCertRequest::ParseCertificate
  1108. Function called to parse a certificate into a OA collection
  1109. Parameters:
  1110. pspcRCI - client certificate structure
  1111. Returns:
  1112. S_OK on success, E_OUTOFMEMORY if out of memory or E_FAIL for
  1113. other errors
  1114. ===================================================================*/
  1115. HRESULT
  1116. CCertRequest::ParseCertificate(
  1117. LPBYTE pbCert,
  1118. DWORD cCert,
  1119. DWORD dwEncoding,
  1120. DWORD dwFlags,
  1121. UINT lCodePage
  1122. )
  1123. {
  1124. XBF xbf( pReq->GetCertStoreBuf(), pReq->GetCertStoreSize() );
  1125. HRESULT hRes = S_OK;
  1126. PCERT_NAME_INFO pNameInfo = NULL;
  1127. UINT cStore;
  1128. UINT x;
  1129. LPSTR pVal;
  1130. PCCERT_CONTEXT pCert;
  1131. if (NULL == (pCert = CertCreateCertificateContext(dwEncoding,
  1132. pbCert,
  1133. cCert))) {
  1134. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1135. hRes = E_FAIL;
  1136. goto cleanup;
  1137. }
  1138. // estimate size of buffer holding values
  1139. cStore = pCert->cbCertEncoded + // for clear text format
  1140. sizeof("ISSUER") +
  1141. sizeof("BINARYISSUER") + (UUENCODEDSIZE(pCert->pCertInfo->Issuer.cbData)*sizeof(WCHAR)) +
  1142. sizeof("BINARYSUBJECT") + (UUENCODEDSIZE(pCert->pCertInfo->Subject.cbData)*sizeof(WCHAR)) +
  1143. sizeof("SUBJECT") + ((pCert->cbCertEncoded + 2) * 2 * sizeof(WCHAR)) + // store fields
  1144. sizeof("CERTIFICATE") + ((pCert->cbCertEncoded +2)* sizeof(WCHAR)) +
  1145. sizeof("SERIALNUMBER") + (pCert->pCertInfo->SerialNumber.cbData * 3) +
  1146. sizeof("PUBLICKEY") + ((pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData+2) * sizeof(WCHAR)) +
  1147. sizeof("VALIDFROM") + sizeof(DATE) +
  1148. sizeof("VALIDUNTIL") + sizeof(DATE) +
  1149. sizeof("FLAGS") + sizeof(DWORD) +
  1150. sizeof("ENCODING") + sizeof(DWORD);
  1151. ;
  1152. if ( !xbf.Extend( cStore ) ) {
  1153. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1154. hRes = E_OUTOFMEMORY;
  1155. goto cleanup;
  1156. }
  1157. //
  1158. // Build Issuer clear text format & fields collection
  1159. //
  1160. if ( !DecodeRdn( &pCert->pCertInfo->Issuer, &pNameInfo ) )
  1161. {
  1162. hRes = E_FAIL;
  1163. goto cleanup;
  1164. }
  1165. pVal = xbf.ReserveRange( 0 );
  1166. if ( !BuildRdnList( pNameInfo, &xbf, FALSE ) )
  1167. {
  1168. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1169. hRes = E_FAIL;
  1170. goto cleanup;
  1171. }
  1172. if ( (hRes = AddStringPair( CLCERT, "ISSUER", pVal, &xbf, FALSE, lCodePage ))
  1173. != S_OK )
  1174. {
  1175. goto cleanup;
  1176. }
  1177. if ( (hRes=AddUuBinaryPair( CLCERT,
  1178. "BINARYISSUER",
  1179. pCert->pCertInfo->Issuer.pbData,
  1180. pCert->pCertInfo->Issuer.cbData,
  1181. &xbf,
  1182. lCodePage ))!=S_OK ) {
  1183. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1184. goto cleanup;
  1185. }
  1186. if ( (hRes=ParseRDNS( pNameInfo, "ISSUER", &xbf, lCodePage )) != S_OK ) {
  1187. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1188. goto cleanup;
  1189. }
  1190. FreeDecodedRdn( pNameInfo );
  1191. //
  1192. // Build Subject clear text format & fields collection
  1193. //
  1194. if ( !DecodeRdn( &pCert->pCertInfo->Subject, &pNameInfo ) )
  1195. {
  1196. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1197. return E_FAIL;
  1198. }
  1199. pVal = xbf.ReserveRange( 0 );
  1200. if ( !BuildRdnList( pNameInfo, &xbf, FALSE ) )
  1201. {
  1202. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1203. hRes = E_FAIL;
  1204. goto cleanup;
  1205. }
  1206. if ( (hRes = AddStringPair( CLCERT, "SUBJECT", pVal, &xbf, FALSE, lCodePage ))
  1207. != S_OK )
  1208. {
  1209. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1210. goto cleanup;
  1211. }
  1212. if ( (hRes=AddUuBinaryPair( CLCERT,
  1213. "BINARYSUBJECT",
  1214. pCert->pCertInfo->Subject.pbData,
  1215. pCert->pCertInfo->Subject.cbData,
  1216. &xbf,
  1217. lCodePage ))!=S_OK )
  1218. {
  1219. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1220. goto cleanup;
  1221. }
  1222. if ( (hRes=ParseRDNS( pNameInfo, "SUBJECT", &xbf, lCodePage )) != S_OK )
  1223. {
  1224. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1225. goto cleanup;
  1226. }
  1227. FreeDecodedRdn( pNameInfo );
  1228. if ( (hRes=AddBinaryPair( CLCERT, "CERTIFICATE", pCert->pbCertEncoded, pCert->cbCertEncoded, &xbf, lCodePage ))!=S_OK )
  1229. {
  1230. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1231. goto cleanup;
  1232. }
  1233. //
  1234. // SerialNumber
  1235. // The certificate's serial number. (Decoded as a multiple byte integer.
  1236. // SerialNumber.pbData[0] is the least significant byte. SerialNumber.pbData[
  1237. // SerialNumber.cbData - 1] is the most significant byte.)
  1238. //
  1239. char achSerNum[128];
  1240. UINT cbSN;
  1241. DBG_ASSERT(pCert->pCertInfo->SerialNumber.cbData > 1);
  1242. cbSN = pCert->pCertInfo->SerialNumber.cbData;
  1243. if (cbSN > 0)
  1244. {
  1245. cbSN--;
  1246. }
  1247. else
  1248. {
  1249. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1250. goto cleanup;
  1251. }
  1252. UINT iOffSet;
  1253. for ( x = 0, iOffSet = 0; x < pCert->pCertInfo->SerialNumber.cbData ; ++x )
  1254. {
  1255. iOffSet = (cbSN-x)*3; // start with the least significant byte
  1256. achSerNum[iOffSet] = "0123456789abcdef"[((LPBYTE)pCert->pCertInfo->SerialNumber.pbData)[x]>>4];
  1257. achSerNum[iOffSet+1] = "0123456789abcdef"[pCert->pCertInfo->SerialNumber.pbData[x]&0x0f];
  1258. if ( x != 0 ) {
  1259. achSerNum[iOffSet+2] = '-';
  1260. }
  1261. else
  1262. {
  1263. achSerNum[iOffSet+2] = '\0';
  1264. }
  1265. }
  1266. if ( (hRes=AddStringPair( CLCERT, "SERIALNUMBER", achSerNum, &xbf, TRUE, lCodePage ))!=S_OK )
  1267. {
  1268. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1269. goto cleanup;
  1270. }
  1271. if ( (hRes=AddBinaryPair( CLCERT, "PUBLICKEY", pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData, pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData, &xbf, lCodePage ))!=S_OK )
  1272. {
  1273. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1274. goto cleanup;
  1275. }
  1276. if ( (hRes=AddDatePair( CLCERT, "VALIDFROM", &pCert->pCertInfo->NotBefore, &xbf ))!=S_OK )
  1277. {
  1278. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1279. goto cleanup;
  1280. }
  1281. if ( (hRes=AddDatePair( CLCERT, "VALIDUNTIL", &pCert->pCertInfo->NotAfter, &xbf ))!=S_OK )
  1282. {
  1283. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1284. goto cleanup;
  1285. }
  1286. if ( (hRes=AddDwordPair( CLCERT, "FLAGS", &dwFlags, &xbf ))!=S_OK )
  1287. {
  1288. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1289. goto cleanup;
  1290. }
  1291. if ( (hRes=AddDwordPair( CLCERT, "ENCODING", &dwEncoding, &xbf ))!=S_OK )
  1292. {
  1293. ExceptionId(IID_IRequestDictionary, IDE_REQUEST, IDE_OOM);
  1294. goto cleanup;
  1295. }
  1296. cleanup:
  1297. if ( pCert )
  1298. {
  1299. CertFreeCertificateContext( pCert );
  1300. }
  1301. pReq->SetCertStore( xbf.QueryBuf(), xbf.QueryAllocSize() );
  1302. xbf.Reset();
  1303. return hRes;
  1304. }
  1305. /*===================================================================
  1306. CCertRequest::NoCertificate
  1307. Function called to create NULL certificate info into a OA collection
  1308. Parameters:
  1309. None
  1310. Returns:
  1311. S_OK on success, E_OUTOFMEMORY if out of memory or E_FAIL for
  1312. other errors
  1313. ===================================================================*/
  1314. HRESULT
  1315. CCertRequest::NoCertificate(
  1316. )
  1317. {
  1318. #if 1
  1319. return S_OK;
  1320. #else
  1321. XBF xbf( pReq->GetCertStoreBuf(), pReq->GetCertStoreSize() );
  1322. HRESULT hRes = S_OK;
  1323. UINT cStore;
  1324. FILETIME ft;
  1325. // estimate size of buffer holding values
  1326. cStore =
  1327. sizeof("ISSUER") + 2*sizeof(WCHAR) +
  1328. sizeof("BINARYISSUER") + 2*sizeof(WCHAR) +
  1329. sizeof("BINARYSUBJECT") + 2*sizeof(WCHAR) +
  1330. sizeof("SUBJECT") + 2*sizeof(WCHAR) +
  1331. sizeof("CERTIFICATE") + 2 * sizeof(WCHAR) +
  1332. sizeof("SERIALNUMBER") + 2 * sizeof(WCHAR) +
  1333. sizeof("PUBLICKEY") + 2 * sizeof(WCHAR) +
  1334. sizeof("VALIDFROM") + sizeof(DATE) +
  1335. sizeof("VALIDUNTIL") + sizeof(DATE)
  1336. ;
  1337. if ( !xbf.Extend( cStore ) )
  1338. {
  1339. hRes = E_OUTOFMEMORY;
  1340. goto cleanup;
  1341. }
  1342. ft.dwLowDateTime = 0;
  1343. ft.dwHighDateTime = 0;
  1344. //
  1345. // Build Issuer clear text format & fields collection
  1346. //
  1347. if ( (hRes = AddStringPair( CLCERT, "ISSUER", "", &xbf, FALSE, lCodePage ))
  1348. != S_OK )
  1349. {
  1350. goto cleanup;
  1351. }
  1352. if ( (hRes = AddStringPair( CLCERT, "BINARYISSUER", "", &xbf, FALSE, lCodePage ))
  1353. != S_OK )
  1354. {
  1355. goto cleanup;
  1356. }
  1357. if ( (hRes = AddStringPair( CLCERT, "SUBJECT", "", &xbf, FALSE, lCodePage ))
  1358. != S_OK )
  1359. {
  1360. goto cleanup;
  1361. }
  1362. if ( (hRes = AddStringPair( CLCERT, "BINARYSUBJECT", "", &xbf, FALSE, lCodePage ))
  1363. != S_OK )
  1364. {
  1365. goto cleanup;
  1366. }
  1367. if ( (hRes = AddStringPair( CLCERT, "CERTIFICATE", "", &xbf, FALSE, lCodePage ))
  1368. != S_OK )
  1369. {
  1370. goto cleanup;
  1371. }
  1372. if ( (hRes=AddStringPair( CLCERT, "SERIALNUMBER", "", &xbf, TRUE, lCodePage ))!=S_OK )
  1373. {
  1374. goto cleanup;
  1375. }
  1376. if ( (hRes=AddStringPair( CLCERT, "PUBLICKEY", "", &xbf, TRUE, lCodePage ))!=S_OK )
  1377. {
  1378. goto cleanup;
  1379. }
  1380. if ( (hRes=AddDatePair( CLCERT, "VALIDFROM", &ft, &xbf ))!=S_OK )
  1381. {
  1382. goto cleanup;
  1383. }
  1384. if ( (hRes=AddDatePair( CLCERT, "VALIDUNTIL", &ft, &xbf ))!=S_OK )
  1385. {
  1386. goto cleanup;
  1387. }
  1388. cleanup:
  1389. pReq->SetCertStore( xbf.QueryBuf(), xbf.QueryAllocSize() );
  1390. xbf.Reset();
  1391. return hRes;
  1392. #endif
  1393. }
  1394. /*===================================================================
  1395. RequestSupportTerminate
  1396. Function called to initialize certificate support
  1397. Parameters:
  1398. None
  1399. Returns:
  1400. TRUE on success, otherwise FALSE
  1401. ===================================================================*/
  1402. BOOL
  1403. RequestSupportInit(
  1404. )
  1405. {
  1406. return TRUE;
  1407. }
  1408. /*===================================================================
  1409. RequestSupportTerminate
  1410. Function called to terminate certificate support
  1411. Parameters:
  1412. None
  1413. Returns:
  1414. Nothing
  1415. ===================================================================*/
  1416. VOID
  1417. RequestSupportTerminate(
  1418. )
  1419. {
  1420. }
  1421. HRESULT
  1422. SetVariantAsByteArray(
  1423. VARIANT* pvarReturn,
  1424. DWORD cbLen,
  1425. LPBYTE pbIn
  1426. )
  1427. /*++
  1428. Routine Description:
  1429. Create variant as byte array
  1430. Arguments:
  1431. pVarReturn - ptr to created variant
  1432. cbLen - byte count
  1433. pbIn - byte array
  1434. Returns:
  1435. COM status
  1436. --*/
  1437. {
  1438. HRESULT hr;
  1439. SAFEARRAYBOUND rgsabound[1];
  1440. BYTE * pbData = NULL;
  1441. // Set the variant type of the output parameter
  1442. V_VT(pvarReturn) = VT_ARRAY|VT_UI1;
  1443. V_ARRAY(pvarReturn) = NULL;
  1444. // Allocate a SafeArray for the data
  1445. rgsabound[0].lLbound = 0;
  1446. rgsabound[0].cElements = cbLen;
  1447. V_ARRAY(pvarReturn) = SafeArrayCreate(VT_UI1, 1, rgsabound);
  1448. if (V_ARRAY(pvarReturn) == NULL)
  1449. {
  1450. return E_OUTOFMEMORY;
  1451. }
  1452. if (FAILED(SafeArrayAccessData(V_ARRAY(pvarReturn), (void **) &pbData)))
  1453. {
  1454. return E_UNEXPECTED;
  1455. }
  1456. memcpy(pbData, pbIn, cbLen );
  1457. SafeArrayUnaccessData(V_ARRAY(pvarReturn));
  1458. return S_OK;
  1459. }