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.

2804 lines
67 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: cmc.cpp
  8. //
  9. // Contents: CMC request creation code shared between xenroll and CA
  10. //
  11. // History: 03-2000 vich created
  12. // 03-2000 xtan moved from ca
  13. // 05-2000 xtan moved from xenroll\xcertlib
  14. //--------------------------------------------------------------------------
  15. #define CMSG_SIGNER_ENCODE_INFO_HAS_CMS_FIELDS
  16. #include <windows.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <tchar.h>
  20. #include <assert.h>
  21. #include <wincrypt.h>
  22. #include <dbgdef.h>
  23. #include <unicode.h>
  24. #include "xelib.h"
  25. #include "xenroll.h"
  26. //#define USE_OLD_DUMMY_SIGNER
  27. #ifndef SAVE_DUMMY_SIGNER
  28. # define SAVE_DUMMY_SIGNER FALSE
  29. #endif
  30. #ifdef _XENROLL_SRC_
  31. #define CryptAcquireContextW CryptAcquireContextU
  32. #endif //_XENROLL_SRC_
  33. HRESULT
  34. GenerateKeys(
  35. IN WCHAR const *pwszContainer,
  36. IN DWORD dwProvType,
  37. OUT HCRYPTPROV *phProv)
  38. {
  39. HRESULT hr;
  40. HCRYPTKEY hKey = NULL;
  41. *phProv = NULL;
  42. // see if the container already exists
  43. // if (CryptAcquireContext(
  44. if (CryptAcquireContextW(
  45. phProv,
  46. pwszContainer,
  47. NULL, // pwszProvName
  48. dwProvType,
  49. 0)) // dwFlags
  50. {
  51. if (NULL != *phProv)
  52. {
  53. CryptReleaseContext(*phProv, 0);
  54. *phProv = NULL;
  55. }
  56. // container exists -- remove old keys and generate new ones.
  57. // if (!CryptAcquireContext(
  58. if (!CryptAcquireContextW(
  59. phProv,
  60. pwszContainer,
  61. NULL, // pwszProvName
  62. dwProvType,
  63. CRYPT_DELETEKEYSET))
  64. {
  65. hr = myHLastError();
  66. _JumpError(hr, error, "CryptAcquireContext");
  67. }
  68. }
  69. // create new container
  70. // if (!CryptAcquireContext(
  71. if (!CryptAcquireContextW(
  72. phProv,
  73. pwszContainer,
  74. NULL, // pwszProvName
  75. dwProvType,
  76. CRYPT_NEWKEYSET)) // force new container
  77. {
  78. hr = myHLastError();
  79. _JumpError(hr, error, "CryptAcquireContext");
  80. }
  81. // create signature keys
  82. if (!CryptGenKey(*phProv, AT_SIGNATURE, 0, &hKey))
  83. {
  84. hr = myHLastError();
  85. _JumpError(hr, error, "CryptGenKey");
  86. }
  87. hr = S_OK;
  88. error:
  89. if (NULL != hKey)
  90. {
  91. CryptDestroyKey(hKey);
  92. }
  93. return(hr);
  94. }
  95. #define wszDUMMYSIGNER L"Dummy Signer"
  96. #ifdef USE_OLD_DUMMY_SIGNER
  97. HRESULT
  98. CreateDummySignerNameInfo(
  99. OUT BYTE **ppbEncodedName,
  100. OUT DWORD *pcbEncodedName)
  101. {
  102. HRESULT hr;
  103. CERT_RDN_ATTR rgRDNAttr[2];
  104. CERT_RDN rgRDN[2];
  105. CERT_NAME_INFO NameInfo;
  106. DWORD i;
  107. CSASSERT(NULL != ppbEncodedName && NULL != pcbEncodedName);
  108. NameInfo.cRDN = ARRAYSIZE(rgRDN);
  109. NameInfo.rgRDN = rgRDN;
  110. for (i = 0; i < ARRAYSIZE(rgRDN); i++)
  111. {
  112. rgRDN[i].cRDNAttr = 1;
  113. rgRDN[i].rgRDNAttr = &rgRDNAttr[i];
  114. rgRDNAttr[i].pszObjId = (0 == i)?
  115. szOID_RDN_DUMMY_SIGNER : szOID_COMMON_NAME;
  116. rgRDNAttr[i].dwValueType = 0;
  117. rgRDNAttr[i].Value.pbData = (BYTE *) wszDUMMYSIGNER;
  118. rgRDNAttr[i].Value.cbData = 0;
  119. }
  120. // if (!myEncodeName(
  121. if (!myEncodeObject(
  122. X509_ASN_ENCODING,
  123. X509_UNICODE_NAME,
  124. &NameInfo,
  125. 0,
  126. CERTLIB_USE_LOCALALLOC,
  127. ppbEncodedName,
  128. pcbEncodedName))
  129. {
  130. hr = myHLastError();
  131. // _JumpError(hr, error, "myEncodeName");
  132. _JumpError(hr, error, "myEncodeObject");
  133. }
  134. hr = S_OK;
  135. error:
  136. return(hr);
  137. }
  138. HRESULT
  139. EncodeCertAndSign(
  140. IN HCRYPTPROV hProv,
  141. IN CERT_INFO *pCert,
  142. IN char const *pszAlgId,
  143. OUT BYTE **ppbSigned,
  144. OUT DWORD *pcbSigned)
  145. {
  146. HRESULT hr;
  147. BYTE *pbEncoded = NULL;
  148. DWORD cbEncoded;
  149. *ppbSigned = NULL;
  150. // if (!myEncodeToBeSigned(
  151. if (!myEncodeObject(
  152. X509_ASN_ENCODING,
  153. X509_CERT_TO_BE_SIGNED,
  154. pCert,
  155. 0,
  156. CERTLIB_USE_LOCALALLOC,
  157. &pbEncoded,
  158. &cbEncoded))
  159. {
  160. hr = myHLastError();
  161. // _JumpError(hr, error, "myEncodeToBeSigned");
  162. _JumpError(hr, error, "myEncodeObject");
  163. }
  164. hr = myEncodeSignedContent(
  165. hProv,
  166. X509_ASN_ENCODING,
  167. pszAlgId,
  168. pbEncoded,
  169. cbEncoded,
  170. CERTLIB_USE_LOCALALLOC,
  171. ppbSigned,
  172. pcbSigned);
  173. _JumpIfError(hr, error, "myEncodeSignedContent");
  174. error:
  175. if (NULL != pbEncoded)
  176. {
  177. LocalFree(pbEncoded);
  178. }
  179. return(hr);
  180. }
  181. VOID
  182. GenerateSerialNumber(
  183. UUID *puuidSerialNumber)
  184. {
  185. HRESULT hr;
  186. BYTE *pb;
  187. ZeroMemory(puuidSerialNumber, sizeof(*puuidSerialNumber));
  188. hr = UuidCreate(puuidSerialNumber);
  189. if (S_OK != hr)
  190. {
  191. BYTE *pbEnd;
  192. CSASSERT(RPC_S_UUID_LOCAL_ONLY == hr);
  193. // No net card? Fake up a GUID:
  194. pb = (BYTE *) puuidSerialNumber;
  195. pbEnd = (BYTE *) pb + sizeof(*puuidSerialNumber);
  196. GetSystemTimeAsFileTime((FILETIME *) pb);
  197. pb += sizeof(FILETIME);
  198. while (pb < pbEnd)
  199. {
  200. *(DWORD *) pb = GetTickCount();
  201. pb += sizeof(DWORD);
  202. }
  203. CSASSERT(pb == pbEnd);
  204. }
  205. pb = &((BYTE *) puuidSerialNumber)[sizeof(*puuidSerialNumber) - 1];
  206. // make sure the last byte is never zero
  207. if (0 == *pb)
  208. {
  209. *pb = 'z';
  210. }
  211. // Some clients can't handle negative serial numbers:
  212. *pb &= 0x7f;
  213. }
  214. HRESULT
  215. CreateKPI(
  216. IN CERT_CONTEXT const *pCert,
  217. IN BSTR strKeyContainer)
  218. {
  219. HRESULT hr;
  220. HCERTSTORE hStore = NULL;
  221. CRYPT_KEY_PROV_INFO kpi;
  222. CERT_CONTEXT const *pCertStore = NULL;
  223. hStore = CertOpenStore(
  224. CERT_STORE_PROV_SYSTEM_W,
  225. X509_ASN_ENCODING,
  226. NULL, // hProv
  227. CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_CURRENT_USER,
  228. L"My");
  229. if (NULL == hStore)
  230. {
  231. hr = myHLastError();
  232. _JumpError(hr, error, "CertOpenStore");
  233. }
  234. if (!CertAddCertificateContextToStore(
  235. hStore,
  236. pCert,
  237. CERT_STORE_ADD_REPLACE_EXISTING,
  238. &pCertStore))
  239. {
  240. hr = myHLastError();
  241. _JumpError(hr, error, "CertAddCertificateContextToStore");
  242. }
  243. ZeroMemory(&kpi, sizeof(kpi));
  244. kpi.pwszContainerName = strKeyContainer;
  245. kpi.pwszProvName = MS_DEF_PROV_W;
  246. kpi.dwProvType = PROV_RSA_FULL;
  247. kpi.dwKeySpec = AT_SIGNATURE;
  248. if (!CertSetCertificateContextProperty(
  249. pCertStore,
  250. CERT_KEY_PROV_INFO_PROP_ID,
  251. 0,
  252. &kpi))
  253. {
  254. hr = myHLastError();
  255. _JumpError(hr, error, "CertSetCertificateContextProperty");
  256. }
  257. hr = S_OK;
  258. error:
  259. if (NULL != pCertStore)
  260. {
  261. CertFreeCertificateContext(pCertStore);
  262. }
  263. if (NULL != hStore)
  264. {
  265. CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
  266. }
  267. return(hr);
  268. }
  269. VOID
  270. DestroyDummyCert(
  271. IN HCRYPTPROV hProv,
  272. IN BSTR strKeyContainer,
  273. IN CERT_CONTEXT const *pCert,
  274. IN BOOL fSaveDummySignerCert)
  275. {
  276. HRESULT hr;
  277. if (NULL != hProv)
  278. {
  279. CryptReleaseContext(hProv, 0);
  280. }
  281. if (NULL != strKeyContainer)
  282. {
  283. if (fSaveDummySignerCert && NULL != pCert)
  284. {
  285. CreateKPI(pCert, strKeyContainer);
  286. }
  287. else
  288. {
  289. // if (!CryptAcquireContext(
  290. if (!CryptAcquireContextW(
  291. &hProv,
  292. strKeyContainer,
  293. NULL, // pwszProvName
  294. PROV_RSA_FULL,
  295. CRYPT_DELETEKEYSET))
  296. {
  297. hr = myHLastError();
  298. _PrintError(hr, "CryptAcquireContext");
  299. }
  300. }
  301. SysFreeString(strKeyContainer);
  302. }
  303. if (NULL != pCert)
  304. {
  305. CertFreeCertificateContext(pCert);
  306. }
  307. }
  308. HRESULT
  309. EncodeDummyCert(
  310. OUT HCRYPTPROV *phProv,
  311. OUT BSTR *pstrKeyContainer,
  312. OUT CERT_CONTEXT const **ppCert)
  313. {
  314. HRESULT hr;
  315. HCRYPTPROV hProv = NULL;
  316. CERT_PUBLIC_KEY_INFO *pPubKey = NULL;
  317. DWORD cbPubKey;
  318. CERT_NAME_BLOB NameBlob;
  319. CERT_INFO Cert;
  320. char *pszAlgId = szOID_RSA_SHA1RSA;
  321. UUID uuidSerialNumber;
  322. BSTR strKeyContainer = NULL;
  323. BYTE *pbEncoded = NULL;
  324. DWORD cbEncoded;
  325. //ZeroMemory(aext, sizeof(aext));
  326. NameBlob.pbData = NULL;
  327. *phProv = NULL;
  328. *pstrKeyContainer = NULL;
  329. *ppCert = NULL;
  330. // Use a GUID for the serial number and the key container name
  331. GenerateSerialNumber(&uuidSerialNumber);
  332. hr = MultiByteIntegerToBstr(
  333. FALSE,
  334. sizeof(uuidSerialNumber),
  335. (BYTE const *) &uuidSerialNumber,
  336. &strKeyContainer);
  337. _JumpIfError(hr, error, "MultiByteIntegerToBstr");
  338. hr = GenerateKeys(strKeyContainer, PROV_RSA_FULL, &hProv);
  339. _JumpIfError(hr, error, "GenerateKeys");
  340. // SUBJECT & ISSUER:
  341. hr = CreateDummySignerNameInfo(&NameBlob.pbData, &NameBlob.cbData);
  342. _JumpIfError(hr, error, "CreateDummySignerNameInfo");
  343. if (!myCryptExportPublicKeyInfo(
  344. hProv,
  345. AT_SIGNATURE,
  346. CERTLIB_USE_LOCALALLOC,
  347. &pPubKey,
  348. &cbPubKey))
  349. {
  350. hr = myHLastError();
  351. _JumpError(hr, error, "myCryptExportPublicKeyInfo");
  352. }
  353. // CERT:
  354. ZeroMemory(&Cert, sizeof(Cert));
  355. Cert.dwVersion = CERT_V1;
  356. Cert.SerialNumber.pbData = (BYTE *) &uuidSerialNumber;
  357. Cert.SerialNumber.cbData = sizeof(uuidSerialNumber);
  358. Cert.SignatureAlgorithm.pszObjId = pszAlgId;
  359. Cert.Issuer = NameBlob; // Structure assignment
  360. GetSystemTimeAsFileTime(&Cert.NotBefore);
  361. Cert.NotAfter = Cert.NotBefore;
  362. myMakeExprDateTime(
  363. &Cert.NotBefore,
  364. -CCLOCKSKEWMINUTESDEFAULT,
  365. ENUM_PERIOD_MINUTES);
  366. myMakeExprDateTime(&Cert.NotAfter, 1, ENUM_PERIOD_MONTHS);
  367. Cert.Subject = NameBlob; // Structure assignment
  368. Cert.SubjectPublicKeyInfo = *pPubKey; // Structure assignment
  369. //Cert.cExtension = 0;
  370. //Cert.rgExtension = NULL;
  371. hr = EncodeCertAndSign(
  372. hProv,
  373. &Cert,
  374. pszAlgId,
  375. &pbEncoded,
  376. &cbEncoded);
  377. _JumpIfError(hr, error, "EncodeCertAndSign");
  378. *ppCert = CertCreateCertificateContext(
  379. X509_ASN_ENCODING,
  380. pbEncoded,
  381. cbEncoded);
  382. if (NULL == *ppCert)
  383. {
  384. hr = myHLastError();
  385. _JumpError(hr, error, "CertCreateCertificateContext");
  386. }
  387. *phProv = hProv;
  388. hProv = NULL;
  389. *pstrKeyContainer = strKeyContainer;
  390. strKeyContainer = NULL;
  391. error:
  392. if (NULL != hProv)
  393. {
  394. CryptReleaseContext(hProv, 0);
  395. }
  396. if (NULL != strKeyContainer)
  397. {
  398. SysFreeString(strKeyContainer);
  399. }
  400. if (NULL != pbEncoded)
  401. {
  402. LocalFree(pbEncoded);
  403. }
  404. if (NULL != NameBlob.pbData)
  405. {
  406. LocalFree(NameBlob.pbData);
  407. }
  408. if (NULL != pPubKey)
  409. {
  410. LocalFree(pPubKey);
  411. }
  412. return(hr);
  413. }
  414. #endif // USE_OLD_DUMMY_SIGNER
  415. HRESULT
  416. BuildCMCExtensions(
  417. IN DWORD cExt,
  418. IN CERT_EXTENSION const *rgExt,
  419. IN DWORD dwCMCDataReference,
  420. IN DWORD dwBodyPartIdOfRequest,
  421. IN DWORD dwBodyPartId,
  422. OUT CMC_TAGGED_ATTRIBUTE *pTaggedAttribute,
  423. OUT CRYPT_ATTR_BLOB *pBlob)
  424. {
  425. HRESULT hr;
  426. CMC_ADD_EXTENSIONS_INFO cmcExt;
  427. ZeroMemory(&cmcExt, sizeof(cmcExt));
  428. cmcExt.dwCmcDataReference = dwCMCDataReference;
  429. if (0 != dwBodyPartIdOfRequest)
  430. {
  431. cmcExt.cCertReference = 1;
  432. cmcExt.rgdwCertReference = &dwBodyPartIdOfRequest;
  433. }
  434. cmcExt.cExtension = cExt;
  435. cmcExt.rgExtension = const_cast<CERT_EXTENSION *>(rgExt);
  436. pTaggedAttribute->dwBodyPartID = dwBodyPartId;
  437. pTaggedAttribute->Attribute.pszObjId = szOID_CMC_ADD_EXTENSIONS;
  438. pTaggedAttribute->Attribute.cValue = 1;
  439. pTaggedAttribute->Attribute.rgValue = pBlob;
  440. // Encode CMC_ADD_EXTENSIONS_INFO --> Extensions Blob
  441. if (!myEncodeObject(
  442. X509_ASN_ENCODING,
  443. CMC_ADD_EXTENSIONS,
  444. &cmcExt,
  445. 0,
  446. CERTLIB_USE_LOCALALLOC,
  447. &pBlob->pbData,
  448. &pBlob->cbData))
  449. {
  450. hr = myHLastError();
  451. _JumpError(hr, error, "myEncodeObject");
  452. }
  453. hr = S_OK;
  454. error:
  455. return(hr);
  456. }
  457. HRESULT
  458. BuildCMCAttributes(
  459. IN DWORD cAttribute,
  460. IN CRYPT_ATTRIBUTE const *rgAttribute,
  461. IN DWORD dwCMCDataReference,
  462. IN DWORD dwBodyPartIdOfRequest,
  463. IN DWORD dwBodyPartId,
  464. OUT CMC_TAGGED_ATTRIBUTE *pTaggedAttribute,
  465. OUT CRYPT_ATTR_BLOB *pBlob)
  466. {
  467. HRESULT hr;
  468. CMC_ADD_ATTRIBUTES_INFO cmcAttrib;
  469. ZeroMemory(&cmcAttrib, sizeof(cmcAttrib));
  470. cmcAttrib.dwCmcDataReference = dwCMCDataReference;
  471. if (0 != dwBodyPartIdOfRequest)
  472. {
  473. cmcAttrib.cCertReference = 1;
  474. cmcAttrib.rgdwCertReference = &dwBodyPartIdOfRequest;
  475. }
  476. cmcAttrib.cAttribute = cAttribute;
  477. cmcAttrib.rgAttribute = const_cast<CRYPT_ATTRIBUTE *>(rgAttribute);
  478. //for (DWORD i = 0; i < cAttribute; i++)
  479. //{
  480. //DBGPRINT((DBG_SS_CERTLIBI, "Attr[%d]: %d values\n", i, rgAttribute[i].cValue));
  481. //}
  482. pTaggedAttribute->dwBodyPartID = dwBodyPartId;
  483. // MS proprietary OID: encoded attribute name, value pairs
  484. pTaggedAttribute->Attribute.pszObjId = szOID_CMC_ADD_ATTRIBUTES;
  485. pTaggedAttribute->Attribute.cValue = 1;
  486. pTaggedAttribute->Attribute.rgValue = pBlob;
  487. // Encode CMC_ADD_ATTRIBUTES_INFO --> Attribute Blob
  488. if (!myEncodeObject(
  489. X509_ASN_ENCODING,
  490. CMC_ADD_ATTRIBUTES,
  491. &cmcAttrib,
  492. 0,
  493. CERTLIB_USE_LOCALALLOC,
  494. &pBlob->pbData,
  495. &pBlob->cbData))
  496. {
  497. hr = myHLastError();
  498. _JumpError(hr, error, "myEncodeObject");
  499. }
  500. hr = S_OK;
  501. error:
  502. return(hr);
  503. }
  504. HRESULT
  505. BuildCMCRegInfo(
  506. IN CHAR const *pszNameValuePairs,
  507. //IN DWORD dwCMCDataReference,
  508. //IN DWORD dwBodyPartIdOfRequest,
  509. IN DWORD dwBodyPartId,
  510. OUT CMC_TAGGED_ATTRIBUTE *pTaggedAttribute,
  511. OUT CRYPT_ATTR_BLOB *pBlob)
  512. {
  513. HRESULT hr;
  514. BYTE *pbOctet = NULL;
  515. CRYPT_DATA_BLOB Blob;
  516. pTaggedAttribute->dwBodyPartID = dwBodyPartId;
  517. pTaggedAttribute->Attribute.pszObjId = szOID_CMC_REG_INFO;
  518. pTaggedAttribute->Attribute.cValue = 1;
  519. pTaggedAttribute->Attribute.rgValue = pBlob;
  520. // Encode CMC_REG_INFO --> Octet string Blob
  521. Blob.pbData = (BYTE *) pszNameValuePairs;
  522. Blob.cbData = strlen(pszNameValuePairs);
  523. if (!myEncodeObject(
  524. X509_ASN_ENCODING,
  525. X509_OCTET_STRING,
  526. &Blob,
  527. 0,
  528. CERTLIB_USE_LOCALALLOC,
  529. &pBlob->pbData,
  530. &pBlob->cbData))
  531. {
  532. hr = myHLastError();
  533. _JumpError(hr, error, "myEncodeObject");
  534. }
  535. hr = S_OK;
  536. error:
  537. if (NULL != pbOctet)
  538. {
  539. LocalFree(pbOctet);
  540. }
  541. return(hr);
  542. }
  543. #ifndef WSZARRAYSIZE
  544. #define WSZARRAYSIZE(a) ((sizeof(a)/sizeof((a)[0])) - 1)
  545. #endif
  546. HRESULT
  547. CanonicalizeURLParm(
  548. IN WCHAR const *pwszParmIn,
  549. OUT WCHAR **ppwszParmOut)
  550. {
  551. HRESULT hr;
  552. WCHAR *pwszUncanon = NULL;
  553. WCHAR *pwszCanon = NULL;
  554. static const WCHAR s_wszLdap[] = L"ldap:///";
  555. *ppwszParmOut = NULL;
  556. pwszUncanon = (WCHAR *) LocalAlloc(
  557. LMEM_FIXED,
  558. (WSZARRAYSIZE(s_wszLdap) + wcslen(pwszParmIn) + 1) * sizeof(WCHAR));
  559. if (NULL == pwszUncanon)
  560. {
  561. hr = E_OUTOFMEMORY;
  562. _JumpError(hr, error, "LocalAlloc");
  563. }
  564. wcscpy(pwszUncanon, s_wszLdap);
  565. wcscat(pwszUncanon, pwszParmIn);
  566. hr = myInternetCanonicalizeUrl(pwszUncanon, &pwszCanon);
  567. _JumpIfError(hr, error, "myInternetCanonicalizeUrl");
  568. hr = myDupString(&pwszCanon[WSZARRAYSIZE(s_wszLdap)], ppwszParmOut);
  569. _JumpIfError(hr, error, "myDupString");
  570. error:
  571. if (NULL != pwszUncanon)
  572. {
  573. LocalFree(pwszUncanon);
  574. }
  575. if (NULL != pwszCanon)
  576. {
  577. LocalFree(pwszCanon);
  578. }
  579. return(hr);
  580. }
  581. // SeparateNameValuePairs
  582. //
  583. // Separate szOID_ENROLLMENT_NAME_VALUE_PAIR attributes from the rest,
  584. // and construct a URL-style, UTF8-encoded parameter string.
  585. HRESULT
  586. SeparateNameValuePairs(
  587. IN CRYPT_ATTRIBUTES const *rgAttributes,
  588. IN DWORD cAttributes,
  589. OUT CRYPT_ATTRIBUTE **prgAttr,
  590. OUT DWORD *pcAttr,
  591. OUT CHAR **ppszNameValuePairs)
  592. {
  593. HRESULT hr;
  594. DWORD i;
  595. DWORD j;
  596. DWORD k;
  597. DWORD cAttr;
  598. DWORD iAttr;
  599. CRYPT_ATTRIBUTE *rgAttr = NULL;
  600. CRYPT_ATTRIBUTE *pAttr;
  601. DWORD cNameValuePair;
  602. DWORD iNameValuePair;
  603. CRYPT_ENROLLMENT_NAME_VALUE_PAIR *pNameValuePair = NULL;
  604. CRYPT_ENROLLMENT_NAME_VALUE_PAIR *rgNameValuePair = NULL;
  605. CRYPT_ENROLLMENT_NAME_VALUE_PAIR *pnvp;
  606. DWORD cb;
  607. WCHAR *pwszNameValuePairs = NULL;
  608. CHAR *pszNameValuePairs = NULL;
  609. DWORD cwc;
  610. *prgAttr = NULL;
  611. *ppszNameValuePairs = NULL;
  612. // Count the name/value pairs, as well as the rest of the attributes
  613. cAttr = 0;
  614. cNameValuePair = 0;
  615. for (i = 0; i < cAttributes; i++)
  616. {
  617. for (j = 0; j < rgAttributes[i].cAttr; j++)
  618. {
  619. pAttr = &rgAttributes[i].rgAttr[j];
  620. if (0 == strcmp(szOID_ENROLLMENT_NAME_VALUE_PAIR, pAttr->pszObjId))
  621. {
  622. cNameValuePair += pAttr->cValue;
  623. }
  624. else
  625. {
  626. cAttr++;
  627. }
  628. }
  629. }
  630. // Allocate an array of name/value pair pointers, and an array for the rest
  631. // of the attributes.
  632. if (0 != cAttr)
  633. {
  634. rgAttr = (CRYPT_ATTRIBUTE *) LocalAlloc(
  635. LMEM_FIXED,
  636. cAttr * sizeof(rgAttr[0]));
  637. if (NULL == rgAttr)
  638. {
  639. hr = E_OUTOFMEMORY;
  640. _JumpError(hr, error, "LocalAlloc");
  641. }
  642. }
  643. if (0 != cNameValuePair)
  644. {
  645. rgNameValuePair = (CRYPT_ENROLLMENT_NAME_VALUE_PAIR *) LocalAlloc(
  646. LMEM_FIXED | LMEM_ZEROINIT,
  647. cNameValuePair * sizeof(rgNameValuePair[0]));
  648. if (NULL == rgNameValuePair)
  649. {
  650. hr = E_OUTOFMEMORY;
  651. _JumpError(hr, error, "LocalAlloc");
  652. }
  653. }
  654. // Decode name/values pairs, canonicalize each URL token, and compute
  655. // total string length. Copy other attributes to the allocated array.
  656. iAttr = 0;
  657. iNameValuePair = 0;
  658. cwc = 0;
  659. for (i = 0; i < cAttributes; i++)
  660. {
  661. for (j = 0; j < rgAttributes[i].cAttr; j++)
  662. {
  663. pAttr = &rgAttributes[i].rgAttr[j];
  664. if (0 == strcmp(szOID_ENROLLMENT_NAME_VALUE_PAIR, pAttr->pszObjId))
  665. {
  666. for (k = 0; k < pAttr->cValue; k++)
  667. {
  668. if (NULL != pNameValuePair)
  669. {
  670. LocalFree(pNameValuePair);
  671. pNameValuePair = NULL;
  672. }
  673. cb = 0;
  674. if (!myDecodeObject(
  675. X509_ASN_ENCODING,
  676. szOID_ENROLLMENT_NAME_VALUE_PAIR,
  677. pAttr->rgValue[k].pbData,
  678. pAttr->rgValue[k].cbData,
  679. CERTLIB_USE_LOCALALLOC,
  680. (VOID **) &pNameValuePair,
  681. &cb))
  682. {
  683. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  684. _JumpError(hr, error, "myDecodeObject");
  685. }
  686. if (NULL != pNameValuePair->pwszName &&
  687. L'\0' != pNameValuePair->pwszName &&
  688. NULL != pNameValuePair->pwszValue &&
  689. L'\0' != pNameValuePair->pwszValue)
  690. {
  691. pnvp = &rgNameValuePair[iNameValuePair];
  692. hr = CanonicalizeURLParm(
  693. pNameValuePair->pwszName,
  694. &pnvp->pwszName);
  695. _JumpIfError(hr, error, "CanonicalizeURLParm");
  696. hr = CanonicalizeURLParm(
  697. pNameValuePair->pwszValue,
  698. &pnvp->pwszValue);
  699. _JumpIfError(hr, error, "CanonicalizeURLParm");
  700. cwc +=
  701. wcslen(pnvp->pwszName) +
  702. 1 +
  703. wcslen(pnvp->pwszValue) +
  704. 1;
  705. iNameValuePair++;
  706. }
  707. }
  708. }
  709. else // copy other attributes
  710. {
  711. rgAttr[iAttr++] = *pAttr;
  712. }
  713. }
  714. }
  715. CSASSERT(cAttr == iAttr);
  716. CSASSERT(cNameValuePair >= iNameValuePair);
  717. cNameValuePair = iNameValuePair;
  718. if (0 != cwc)
  719. {
  720. pwszNameValuePairs = (WCHAR *) LocalAlloc(
  721. LMEM_FIXED,
  722. (cwc + 1) * sizeof(WCHAR));
  723. if (NULL == pwszNameValuePairs)
  724. {
  725. hr = E_OUTOFMEMORY;
  726. _JumpError(hr, error, "LocalAlloc");
  727. }
  728. *pwszNameValuePairs = L'\0';
  729. for (i = 0; i < cNameValuePair; i++)
  730. {
  731. pnvp = &rgNameValuePair[i];
  732. wcscat(pwszNameValuePairs, pnvp->pwszName);
  733. wcscat(pwszNameValuePairs, L"=");
  734. wcscat(pwszNameValuePairs, pnvp->pwszValue);
  735. wcscat(pwszNameValuePairs, L"&");
  736. }
  737. CSASSERT(wcslen(pwszNameValuePairs) == cwc);
  738. // and construct a URL-style, UTF8-encoded parameter string.
  739. if (!myConvertWszToUTF8(&pszNameValuePairs, pwszNameValuePairs, -1))
  740. {
  741. hr = myHLastError();
  742. _JumpError(hr, error, "myConvertWszToUTF8");
  743. }
  744. }
  745. *prgAttr = rgAttr;
  746. rgAttr = NULL;
  747. *pcAttr = cAttr;
  748. *ppszNameValuePairs = pszNameValuePairs;
  749. pszNameValuePairs = NULL;
  750. hr = S_OK;
  751. error:
  752. if (NULL != pszNameValuePairs)
  753. {
  754. LocalFree(pszNameValuePairs);
  755. }
  756. if (NULL != pwszNameValuePairs)
  757. {
  758. LocalFree(pwszNameValuePairs);
  759. }
  760. if (NULL != rgAttr)
  761. {
  762. LocalFree(rgAttr);
  763. }
  764. if (NULL != pNameValuePair)
  765. {
  766. LocalFree(pNameValuePair);
  767. }
  768. if (NULL != rgNameValuePair)
  769. {
  770. for (i = 0; i < cNameValuePair; i++)
  771. {
  772. if (NULL != rgNameValuePair[i].pwszName)
  773. {
  774. LocalFree(rgNameValuePair[i].pwszName);
  775. }
  776. if (NULL != rgNameValuePair[i].pwszValue)
  777. {
  778. LocalFree(rgNameValuePair[i].pwszValue);
  779. }
  780. }
  781. LocalFree(rgNameValuePair);
  782. }
  783. return(hr);
  784. }
  785. HRESULT
  786. BuildCMCRequest(
  787. IN DWORD dwClientId,
  788. IN BOOL fNestedCMCRequest,
  789. IN BYTE const *pbReq,
  790. IN DWORD cbReq,
  791. OPTIONAL IN CERT_EXTENSION const *rgExt,
  792. IN DWORD cExt,
  793. OPTIONAL IN CRYPT_ATTRIBUTES const *rgAttributes,
  794. IN DWORD cAttributes,
  795. OPTIONAL IN CRYPT_ATTRIBUTE const *rgAttributeUnauth,
  796. IN DWORD cAttributeUnauth,
  797. OPTIONAL IN BYTE const *pbKeyIdRequest,
  798. IN DWORD cbKeyIdRequest,
  799. OPTIONAL IN HCRYPTPROV hProvRequest,
  800. IN DWORD dwKeySpecRequest,
  801. OPTIONAL IN LPCSTR pszObjIdHashRequest,
  802. OPTIONAL IN CERT_CONTEXT const *pCertSigner,
  803. OPTIONAL IN HCRYPTPROV hProvSigner,
  804. IN DWORD dwKeySpecSigner,
  805. OPTIONAL IN LPCSTR pszObjIdHashSigner,
  806. OUT BYTE **ppbReqCMC,
  807. OUT DWORD *pcbReqCMC)
  808. {
  809. HRESULT hr;
  810. CMC_DATA_INFO cmcData;
  811. CRYPT_ATTRIBUTE *rgAttr = NULL;
  812. DWORD cAttr;
  813. CHAR *pszNameValuePairs = NULL;
  814. CMC_TAGGED_ATTRIBUTE *rgTaggedAttribute = NULL;
  815. CMC_TAGGED_ATTRIBUTE *pTaggedAttribute;
  816. CRYPT_ATTR_BLOB *rgBlob = NULL;
  817. CRYPT_ATTR_BLOB *pBlob;
  818. CMC_TAGGED_CERT_REQUEST cmcTaggedCertRequest;
  819. CMC_TAGGED_REQUEST cmcTaggedRequest;
  820. CMC_TAGGED_CONTENT_INFO cmcTaggedContentInfo;
  821. DWORD dwBodyPartId = 1;
  822. DWORD dwBodyPartIdOfRequest = 0;
  823. DWORD dwCMCDataReference = 0;
  824. BYTE *pbCMCContent = NULL;
  825. DWORD cbCMCContent;
  826. DWORD i;
  827. CMSG_SIGNER_ENCODE_INFO aSignerEncodeInfo[2];
  828. CMSG_SIGNED_ENCODE_INFO SignedMsgEncodeInfo;
  829. CERT_BLOB aSignerCertBlob[2];
  830. HCRYPTMSG hMsg = NULL;
  831. HCRYPTPROV hProvVerify = NULL;
  832. CRYPT_ATTRIBUTE AttributeRequestClient;
  833. CRYPT_ATTR_BLOB BlobRequestClient;
  834. CERT_ISSUER_SERIAL_NUMBER IssuerSerial;
  835. ZeroMemory(&IssuerSerial, sizeof(IssuerSerial));
  836. BYTE Zero = 0;
  837. #define BCR_CTAGGEDATTR 3
  838. #define BCR_CBLOB 3
  839. #ifdef USE_OLD_DUMMY_SIGNER
  840. HCRYPTPROV hProvDummy = NULL;
  841. BSTR strContainerDummy = NULL;
  842. CERT_CONTEXT const *pCertDummy = NULL;
  843. BOOL fSaveDummySignerCert = SAVE_DUMMY_SIGNER;
  844. #endif // USE_OLD_DUMMY_SIGNER
  845. CERT_CONTEXT const *pCert;
  846. HCRYPTPROV hProv;
  847. DWORD dwKeySpec;
  848. CHAR const *pszObjIdHash;
  849. CERT_PUBLIC_KEY_INFO *pPubKey = NULL;
  850. DWORD cbPubKey;
  851. *ppbReqCMC = NULL;
  852. ZeroMemory(&cmcData, sizeof(cmcData));
  853. BlobRequestClient.pbData = NULL;
  854. if ((NULL == pbKeyIdRequest) ^
  855. (0 == cbKeyIdRequest) ^
  856. (NULL == hProvRequest) ^
  857. (0 == dwKeySpecRequest))
  858. {
  859. hr = E_INVALIDARG;
  860. _JumpError(hr, error, "request parms inconsistent");
  861. }
  862. if (NULL != pszObjIdHashRequest && NULL == hProvRequest)
  863. {
  864. hr = E_INVALIDARG;
  865. _JumpError(hr, error, "request signing OID parm inconsistent");
  866. }
  867. if ((NULL == pCertSigner) ^ (NULL == hProvSigner))
  868. {
  869. hr = E_INVALIDARG;
  870. _JumpError(hr, error, "signer parms inconsistent");
  871. }
  872. rgTaggedAttribute = (CMC_TAGGED_ATTRIBUTE *) LocalAlloc(
  873. LMEM_FIXED,
  874. BCR_CTAGGEDATTR * sizeof(rgTaggedAttribute[0]));
  875. if (NULL == rgTaggedAttribute)
  876. {
  877. hr = E_OUTOFMEMORY;
  878. _JumpError(hr, error, "LocalAlloc");
  879. }
  880. cmcData.rgTaggedAttribute = rgTaggedAttribute;
  881. pTaggedAttribute = rgTaggedAttribute;
  882. rgBlob = (CRYPT_ATTR_BLOB *) LocalAlloc(
  883. LMEM_FIXED | LMEM_ZEROINIT,
  884. BCR_CBLOB * sizeof(rgBlob[0]));
  885. if (NULL == rgBlob)
  886. {
  887. hr = E_OUTOFMEMORY;
  888. _JumpError(hr, error, "LocalAlloc");
  889. }
  890. pBlob = rgBlob;
  891. if (fNestedCMCRequest)
  892. {
  893. dwCMCDataReference = dwBodyPartId++;
  894. // cmcData.rgTaggedContentInfo[0] = Nested CMC request
  895. ZeroMemory(&cmcTaggedContentInfo, sizeof(cmcTaggedContentInfo));
  896. cmcData.cTaggedContentInfo = 1;
  897. cmcData.rgTaggedContentInfo = &cmcTaggedContentInfo;
  898. cmcTaggedContentInfo.dwBodyPartID = dwCMCDataReference;
  899. cmcTaggedContentInfo.EncodedContentInfo.pbData = const_cast<BYTE *>(pbReq);
  900. cmcTaggedContentInfo.EncodedContentInfo.cbData = cbReq;
  901. }
  902. else
  903. {
  904. // possibly unsigned PKCS10
  905. dwBodyPartIdOfRequest = dwBodyPartId++;
  906. // cmcData.rgTaggedRequest[0] = PKCS10 request
  907. ZeroMemory(&cmcTaggedRequest, sizeof(cmcTaggedRequest));
  908. ZeroMemory(&cmcTaggedCertRequest, sizeof(cmcTaggedCertRequest));
  909. cmcData.cTaggedRequest = 1;
  910. cmcData.rgTaggedRequest = &cmcTaggedRequest;
  911. cmcTaggedRequest.dwTaggedRequestChoice = CMC_TAGGED_CERT_REQUEST_CHOICE;
  912. cmcTaggedRequest.pTaggedCertRequest = &cmcTaggedCertRequest;
  913. cmcTaggedCertRequest.dwBodyPartID = dwBodyPartIdOfRequest;
  914. cmcTaggedCertRequest.SignedCertRequest.pbData = const_cast<BYTE *>(pbReq);
  915. cmcTaggedCertRequest.SignedCertRequest.cbData = cbReq;
  916. }
  917. // *pTaggedAttribute++ = Collected Extensions
  918. if (0 != cExt)
  919. {
  920. CSASSERT(
  921. pTaggedAttribute <
  922. &rgTaggedAttribute[BCR_CTAGGEDATTR + cAttributes);
  923. CSASSERT(pBlob < &rgBlob[BCR_CBLOB + cAttributes);
  924. hr = BuildCMCExtensions(
  925. cExt,
  926. rgExt,
  927. dwCMCDataReference,
  928. dwBodyPartIdOfRequest,
  929. dwBodyPartId,
  930. pTaggedAttribute,
  931. pBlob);
  932. _JumpIfError(hr, error, "BuildCMCExtensions");
  933. dwBodyPartId++;
  934. cmcData.cTaggedAttribute++;
  935. pTaggedAttribute++;
  936. pBlob++;
  937. }
  938. // *pTaggedAttribute++ = Collected Request Attributes
  939. if (0 != cAttributes)
  940. {
  941. hr = SeparateNameValuePairs(
  942. rgAttributes,
  943. cAttributes,
  944. &rgAttr,
  945. &cAttr,
  946. &pszNameValuePairs);
  947. _JumpIfError(hr, error, "SeparateNameValuePairs");
  948. if (0 != cAttr)
  949. {
  950. CSASSERT(
  951. pTaggedAttribute <
  952. &rgTaggedAttribute[BCR_CTAGGEDATTR + cAttributes);
  953. CSASSERT(pBlob < &rgBlob[BCR_CBLOB + cAttributes);
  954. hr = BuildCMCAttributes(
  955. cAttr,
  956. rgAttr,
  957. dwCMCDataReference,
  958. dwBodyPartIdOfRequest,
  959. dwBodyPartId,
  960. pTaggedAttribute,
  961. pBlob);
  962. _JumpIfError(hr, error, "BuildCMCAttributes");
  963. dwBodyPartId++;
  964. cmcData.cTaggedAttribute++;
  965. pTaggedAttribute++;
  966. pBlob++;
  967. }
  968. if (NULL != pszNameValuePairs)
  969. {
  970. CSASSERT(
  971. pTaggedAttribute <
  972. &rgTaggedAttribute[BCR_CTAGGEDATTR + cAttributes);
  973. CSASSERT(pBlob < &rgBlob[BCR_CBLOB + cAttributes);
  974. hr = BuildCMCRegInfo(
  975. pszNameValuePairs,
  976. //dwCMCDataReference,
  977. //dwBodyPartIdOfRequest,
  978. dwBodyPartId,
  979. pTaggedAttribute,
  980. pBlob);
  981. _JumpIfError(hr, error, "BuildCMCRegInfo");
  982. dwBodyPartId++;
  983. cmcData.cTaggedAttribute++;
  984. pTaggedAttribute++;
  985. pBlob++;
  986. }
  987. }
  988. // Encode CMC_DATA_INFO --> CMC Request Blob
  989. if (!myEncodeObject(
  990. X509_ASN_ENCODING,
  991. CMC_DATA,
  992. &cmcData,
  993. 0,
  994. CERTLIB_USE_LOCALALLOC,
  995. &pbCMCContent,
  996. &cbCMCContent))
  997. {
  998. hr = myHLastError();
  999. _JumpError(hr, error, "myEncodeObject");
  1000. }
  1001. if (XECI_DISABLE != dwClientId)
  1002. {
  1003. hr = myEncodeRequestClientAttributeFromClientId(
  1004. dwClientId,
  1005. &BlobRequestClient.pbData,
  1006. &BlobRequestClient.cbData);
  1007. _JumpIfError(hr, error, "myEncodeRequestClientAttributeFromClientId");
  1008. AttributeRequestClient.pszObjId = szOID_REQUEST_CLIENT_INFO;
  1009. AttributeRequestClient.cValue = 1;
  1010. AttributeRequestClient.rgValue = &BlobRequestClient;
  1011. }
  1012. pCert = NULL;
  1013. hProv = hProvRequest;
  1014. dwKeySpec = dwKeySpecRequest;
  1015. pszObjIdHash = pszObjIdHashRequest;
  1016. if (NULL == hProvRequest && NULL == pbKeyIdRequest)
  1017. {
  1018. #ifdef USE_OLD_DUMMY_SIGNER
  1019. hr = EncodeDummyCert(&hProvDummy, &strContainerDummy, &pCertDummy);
  1020. _JumpIfError(hr, error, "EncodeDummyCert");
  1021. pCert = pCertDummy;
  1022. hProv = hProvDummy;
  1023. dwKeySpec = AT_SIGNATURE;
  1024. pszObjIdHash = pszObjIdHashSigner;
  1025. #else
  1026. // Fake up the NULL signature Signer info
  1027. CERT_RDN_ATTR rdnAttr;
  1028. CERT_RDN rdn;
  1029. CERT_NAME_INFO NameInfo;
  1030. NameInfo.cRDN = 1;
  1031. NameInfo.rgRDN = &rdn;
  1032. rdn.cRDNAttr = 1;
  1033. rdn.rgRDNAttr = &rdnAttr;
  1034. rdnAttr.pszObjId = szOID_RDN_DUMMY_SIGNER;
  1035. rdnAttr.dwValueType = 0;
  1036. rdnAttr.Value.pbData = (BYTE *) wszDUMMYSIGNER;
  1037. rdnAttr.Value.cbData = 0;
  1038. if (!myEncodeObject(
  1039. X509_ASN_ENCODING,
  1040. X509_UNICODE_NAME,
  1041. &NameInfo,
  1042. 0,
  1043. CERTLIB_USE_LOCALALLOC,
  1044. &IssuerSerial.Issuer.pbData,
  1045. &IssuerSerial.Issuer.cbData))
  1046. {
  1047. hr = myHLastError();
  1048. _JumpError(hr, error, "myEncodeObject");
  1049. }
  1050. IssuerSerial.SerialNumber.pbData = &Zero;
  1051. IssuerSerial.SerialNumber.cbData = sizeof(Zero);
  1052. #endif // USE_OLD_DUMMY_SIGNER
  1053. }
  1054. ZeroMemory(aSignerEncodeInfo, sizeof(aSignerEncodeInfo));
  1055. ZeroMemory(&SignedMsgEncodeInfo, sizeof(SignedMsgEncodeInfo));
  1056. SignedMsgEncodeInfo.cbSize = sizeof(SignedMsgEncodeInfo);
  1057. SignedMsgEncodeInfo.rgSigners = aSignerEncodeInfo;
  1058. //SignedMsgEncodeInfo.cCrlEncoded = 0;
  1059. //SignedMsgEncodeInfo.rgCrlEncoded = NULL;
  1060. // Encode CMC content into a PKCS 7, signed by the request's private key
  1061. // if available, otherwise use a NULL signature.
  1062. // Initialize the CMSG_SIGNER_ENCODE_INFO structure for one signer.
  1063. // If the optional pCertSigner is non-NULL, add a second signature.
  1064. for (i = 0; i < 2; i++)
  1065. {
  1066. CMSG_SIGNER_ENCODE_INFO *pSignerEncodeInfo = &aSignerEncodeInfo[i];
  1067. CRYPT_OID_INFO const *pOIDInfo;
  1068. CHAR const *pszObjIdPubKey;
  1069. BOOL fDSSKey;
  1070. pSignerEncodeInfo->cbSize = sizeof(*pSignerEncodeInfo);
  1071. if (NULL != pCert)
  1072. {
  1073. pSignerEncodeInfo->pCertInfo = pCert->pCertInfo;
  1074. aSignerCertBlob[SignedMsgEncodeInfo.cCertEncoded].cbData = pCert->cbCertEncoded;
  1075. aSignerCertBlob[SignedMsgEncodeInfo.cCertEncoded].pbData = pCert->pbCertEncoded;
  1076. SignedMsgEncodeInfo.rgCertEncoded = aSignerCertBlob;
  1077. SignedMsgEncodeInfo.cCertEncoded++;
  1078. }
  1079. if (XECI_DISABLE != dwClientId)
  1080. {
  1081. pSignerEncodeInfo->cAuthAttr = 1;
  1082. pSignerEncodeInfo->rgAuthAttr = &AttributeRequestClient;
  1083. }
  1084. pSignerEncodeInfo->HashAlgorithm.pszObjId =
  1085. NULL != pszObjIdHash?
  1086. const_cast<CHAR *>(pszObjIdHash) : szOID_OIWSEC_sha1;
  1087. if (NULL != pCert)
  1088. {
  1089. pszObjIdPubKey = pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId;
  1090. }
  1091. else if (NULL != hProv)
  1092. {
  1093. CSASSERT(0 == i);
  1094. CSASSERT(NULL == pPubKey);
  1095. if (!myCryptExportPublicKeyInfo(
  1096. hProv,
  1097. dwKeySpec,
  1098. CERTLIB_USE_LOCALALLOC,
  1099. &pPubKey,
  1100. &cbPubKey))
  1101. {
  1102. hr = myHLastError();
  1103. _JumpError(hr, error, "myCryptExportPublicKeyInfo");
  1104. }
  1105. pszObjIdPubKey = pPubKey->Algorithm.pszObjId;
  1106. }
  1107. else
  1108. {
  1109. pszObjIdPubKey = szOID_PKIX_NO_SIGNATURE;
  1110. if (NULL == hProvVerify)
  1111. {
  1112. if (!CryptAcquireContextW(
  1113. &hProvVerify,
  1114. NULL, // pwszContainer
  1115. NULL, // pwszProvName
  1116. PROV_RSA_FULL,
  1117. CRYPT_VERIFYCONTEXT)) // dwFlags
  1118. {
  1119. hr = myHLastError();
  1120. _JumpError(hr, error, "CryptAcquireContextW");
  1121. }
  1122. }
  1123. hProv = hProvVerify;
  1124. dwKeySpec = AT_SIGNATURE;
  1125. }
  1126. pSignerEncodeInfo->hCryptProv = hProv;
  1127. pSignerEncodeInfo->dwKeySpec = dwKeySpec;
  1128. fDSSKey = FALSE;
  1129. #ifdef _XENROLL_SRC_
  1130. pOIDInfo = xeCryptFindOIDInfo(
  1131. #else
  1132. pOIDInfo = CryptFindOIDInfo(
  1133. #endif
  1134. CRYPT_OID_INFO_OID_KEY,
  1135. const_cast<CHAR *>(pszObjIdPubKey),
  1136. CRYPT_PUBKEY_ALG_OID_GROUP_ID);
  1137. if (NULL != pOIDInfo && CALG_DSS_SIGN == pOIDInfo->Algid)
  1138. {
  1139. pszObjIdPubKey = szOID_X957_SHA1DSA;
  1140. fDSSKey = TRUE;
  1141. }
  1142. if (NULL == pCert || fDSSKey)
  1143. {
  1144. pSignerEncodeInfo->HashEncryptionAlgorithm.pszObjId = const_cast<CHAR *>(pszObjIdPubKey);
  1145. }
  1146. if (NULL == pCert)
  1147. {
  1148. if (NULL == pbKeyIdRequest)
  1149. {
  1150. pSignerEncodeInfo->SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
  1151. pSignerEncodeInfo->SignerId.IssuerSerialNumber = IssuerSerial;
  1152. }
  1153. else
  1154. {
  1155. pSignerEncodeInfo->SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
  1156. pSignerEncodeInfo->SignerId.KeyId.cbData = cbKeyIdRequest;
  1157. pSignerEncodeInfo->SignerId.KeyId.pbData = const_cast<BYTE *>(pbKeyIdRequest);
  1158. }
  1159. }
  1160. SignedMsgEncodeInfo.cSigners++;
  1161. if (NULL == pCertSigner)
  1162. {
  1163. break;
  1164. }
  1165. pCert = pCertSigner;
  1166. hProv = hProvSigner;
  1167. dwKeySpec = dwKeySpecSigner;
  1168. pszObjIdHash = pszObjIdHashSigner;
  1169. }
  1170. // Unauthenticated attributes are attached to the first signature ONLY!
  1171. aSignerEncodeInfo[0].cUnauthAttr = cAttributeUnauth;
  1172. aSignerEncodeInfo[0].rgUnauthAttr = const_cast<CRYPT_ATTRIBUTE *>(rgAttributeUnauth);
  1173. hMsg = CryptMsgOpenToEncode(
  1174. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  1175. CMSG_CMS_ENCAPSULATED_CONTENT_FLAG, // dwFlags
  1176. CMSG_SIGNED,
  1177. &SignedMsgEncodeInfo,
  1178. szOID_CT_PKI_DATA,
  1179. NULL); // pStreamInfo
  1180. if (NULL == hMsg)
  1181. {
  1182. hr = myHLastError();
  1183. _JumpError(hr, error, "CryptMsgOpenToEncode");
  1184. }
  1185. // Update the message with the CMC content
  1186. if (!CryptMsgUpdate(hMsg, pbCMCContent, cbCMCContent, TRUE))
  1187. {
  1188. hr = myHLastError();
  1189. _JumpError(hr, error, "CryptMsgUpdate");
  1190. }
  1191. // Return the encoded and signed content.
  1192. // Use CMSG_CONTENT_PARAM to get the signed message.
  1193. hr = myCryptMsgGetParam(
  1194. hMsg,
  1195. CMSG_CONTENT_PARAM,
  1196. 0,
  1197. CERTLIB_USE_LOCALALLOC,
  1198. (VOID **) ppbReqCMC,
  1199. pcbReqCMC);
  1200. _JumpIfError(hr, error, "myCryptMsgGetParam");
  1201. error:
  1202. if (NULL != hMsg)
  1203. {
  1204. CryptMsgClose(hMsg); //make sure close before hProv release
  1205. }
  1206. if (NULL != rgAttr)
  1207. {
  1208. LocalFree(rgAttr);
  1209. }
  1210. if (NULL != pszNameValuePairs)
  1211. {
  1212. LocalFree(pszNameValuePairs);
  1213. }
  1214. if (NULL != IssuerSerial.Issuer.pbData)
  1215. {
  1216. LocalFree(IssuerSerial.Issuer.pbData);
  1217. }
  1218. if (NULL != hProvVerify)
  1219. {
  1220. CryptReleaseContext(hProvVerify, 0);
  1221. }
  1222. if (NULL != BlobRequestClient.pbData)
  1223. {
  1224. LocalFree(BlobRequestClient.pbData);
  1225. }
  1226. #ifdef USE_OLD_DUMMY_SIGNER
  1227. DestroyDummyCert(
  1228. hProvDummy,
  1229. strContainerDummy,
  1230. pCertDummy,
  1231. fSaveDummySignerCert);
  1232. #endif // USE_OLD_DUMMY_SIGNER
  1233. if (NULL != rgBlob)
  1234. {
  1235. for (i = 0; i < BCR_CBLOB; i++)
  1236. {
  1237. if (NULL != rgBlob[i].pbData)
  1238. {
  1239. LocalFree(rgBlob[i].pbData);
  1240. }
  1241. }
  1242. LocalFree(rgBlob);
  1243. }
  1244. if (NULL != rgTaggedAttribute)
  1245. {
  1246. LocalFree(rgTaggedAttribute);
  1247. }
  1248. if (NULL != pbCMCContent)
  1249. {
  1250. LocalFree(pbCMCContent);
  1251. }
  1252. if (NULL != pPubKey)
  1253. {
  1254. LocalFree(pPubKey);
  1255. }
  1256. return(hr);
  1257. }
  1258. VOID
  1259. FreeCMCResponse(
  1260. IN XCMCRESPONSE *rgResponse,
  1261. IN DWORD cResponse)
  1262. {
  1263. DWORD i;
  1264. if (NULL != rgResponse)
  1265. {
  1266. for (i = 0; i < cResponse; i++)
  1267. {
  1268. XCMCRESPONSE *pResponse = &rgResponse[i];
  1269. if (CMC_OTHER_INFO_PEND_CHOICE ==
  1270. pResponse->StatusInfo.dwOtherInfoChoice &&
  1271. NULL != pResponse->StatusInfo.pPendInfo)
  1272. {
  1273. if (NULL != pResponse->StatusInfo.pPendInfo->PendToken.pbData)
  1274. {
  1275. LocalFree(pResponse->StatusInfo.pPendInfo->PendToken.pbData);
  1276. }
  1277. LocalFree(pResponse->StatusInfo.pPendInfo);
  1278. }
  1279. if (NULL != pResponse->StatusInfo.pwszStatusString)
  1280. {
  1281. LocalFree(pResponse->StatusInfo.pwszStatusString);
  1282. }
  1283. if (NULL != pResponse->pbCertHash)
  1284. {
  1285. LocalFree(pResponse->pbCertHash);
  1286. }
  1287. if (NULL != pResponse->pbEncryptedKeyHash)
  1288. {
  1289. LocalFree(pResponse->pbEncryptedKeyHash);
  1290. }
  1291. if (NULL != pResponse->pwszBodyPart)
  1292. {
  1293. LocalFree(pResponse->pwszBodyPart);
  1294. }
  1295. }
  1296. LocalFree(rgResponse);
  1297. }
  1298. }
  1299. HRESULT
  1300. _AppendBodyPart(
  1301. IN OUT WCHAR *pwszBodyPartBuffer,
  1302. IN DWORD cwcBodyPartBuffer,
  1303. IN DWORD cwcPrefix,
  1304. IN DWORD dwBodyPart)
  1305. {
  1306. HRESULT hr;
  1307. WCHAR awc[14]; // L".%u"
  1308. if (cwcBodyPartBuffer <=
  1309. cwcPrefix +
  1310. wsprintfW(awc, L".%u", dwBodyPart))
  1311. // wsprintf(awc, L".%u", dwBodyPart))
  1312. {
  1313. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  1314. _JumpError(hr, error, "pwszBodyPartBuffer");
  1315. }
  1316. wcscpy(&pwszBodyPartBuffer[cwcPrefix], awc);
  1317. // DBGPRINT((DBG_SS_CERTLIBI, "BodyPartString: %ws\n", &pwszBodyPartBuffer[1]));
  1318. hr = S_OK;
  1319. error:
  1320. return(hr);
  1321. }
  1322. //+--------------------------------------------------------------------------
  1323. // _SaveCMCStatus -- Save CMC Status Info
  1324. //
  1325. // Returns S_OK on success.
  1326. //+--------------------------------------------------------------------------
  1327. HRESULT
  1328. _SaveCMCStatus(
  1329. IN BYTE *pbIn,
  1330. IN DWORD cbIn,
  1331. IN OUT WCHAR *pwszBodyPartBuffer,
  1332. IN DWORD cwcBodyPartBuffer,
  1333. IN OUT XCMCRESPONSE **prgResponse,
  1334. IN OUT DWORD *pcResponse)
  1335. {
  1336. HRESULT hr;
  1337. DWORD i;
  1338. DWORD cwcPrefix;
  1339. CMC_STATUS_INFO *pcmcStatus = NULL;
  1340. XCMCRESPONSE *pResponse;
  1341. DWORD cb;
  1342. WCHAR *pwszBodyPartT = NULL;
  1343. WCHAR *pwszStatusStringT = NULL;
  1344. BYTE *pbToken = NULL;
  1345. cwcPrefix = wcslen(pwszBodyPartBuffer);
  1346. // Decode CMC_STATUS_INFO from Attribute Blob
  1347. CSASSERT(NULL == pcmcStatus);
  1348. if (!myDecodeObject(
  1349. X509_ASN_ENCODING,
  1350. CMC_STATUS,
  1351. pbIn,
  1352. cbIn,
  1353. CERTLIB_USE_LOCALALLOC,
  1354. (VOID **) &pcmcStatus,
  1355. &cb))
  1356. {
  1357. hr = myHLastError();
  1358. _JumpError(hr, error, "myDecodeObject");
  1359. }
  1360. for (i = 0; i < pcmcStatus->cBodyList; i++)
  1361. {
  1362. hr = _AppendBodyPart(
  1363. pwszBodyPartBuffer,
  1364. cwcBodyPartBuffer,
  1365. cwcPrefix,
  1366. pcmcStatus->rgdwBodyList[i]);
  1367. _JumpIfError(hr, error, "_AppendBodyPart");
  1368. #if 0
  1369. DBGPRINT((
  1370. DBG_SS_CERTLIBI,
  1371. " Status: %u\n",
  1372. pcmcStatus->dwStatus));
  1373. if (NULL != pcmcStatus->pwszStatusString)
  1374. {
  1375. DBGPRINT((
  1376. DBG_SS_CERTLIBI,
  1377. " StatusString: %ws\n",
  1378. pcmcStatus->pwszStatusString));
  1379. }
  1380. DBGPRINT((
  1381. DBG_SS_CERTLIBI,
  1382. " OtherInfoChoice: %u\n",
  1383. pcmcStatus->dwOtherInfoChoice));
  1384. #endif //0
  1385. if (CMC_OTHER_INFO_PEND_CHOICE == pcmcStatus->dwOtherInfoChoice)
  1386. {
  1387. //pcmcStatus->pPendInfo->PendToken.pbData
  1388. //pcmcStatus->pPendInfo->PendToken.cbData
  1389. //pcmcStatus->pPendInfo->PendTime
  1390. }
  1391. if (0 == *pcResponse)
  1392. {
  1393. pResponse = (XCMCRESPONSE *) LocalAlloc(
  1394. LMEM_FIXED | LMEM_ZEROINIT,
  1395. sizeof(**prgResponse));
  1396. }
  1397. else
  1398. {
  1399. pResponse = (XCMCRESPONSE *) LocalReAlloc(
  1400. *prgResponse,
  1401. (1 + *pcResponse) * sizeof(**prgResponse),
  1402. LMEM_MOVEABLE | LMEM_ZEROINIT);
  1403. }
  1404. if (NULL == pResponse)
  1405. {
  1406. hr = E_OUTOFMEMORY;
  1407. _JumpError(hr, error, 0 == *pcResponse? "LocalAlloc" : "LocalReAlloc");
  1408. }
  1409. *prgResponse = pResponse;
  1410. pResponse += *pcResponse;
  1411. pResponse->StatusInfo.dwStatus = pcmcStatus->dwStatus;
  1412. pResponse->StatusInfo.cBodyList = pcmcStatus->rgdwBodyList[i];
  1413. pResponse->StatusInfo.dwOtherInfoChoice = pcmcStatus->dwOtherInfoChoice;
  1414. if (CMC_OTHER_INFO_FAIL_CHOICE == pcmcStatus->dwOtherInfoChoice)
  1415. {
  1416. pResponse->StatusInfo.dwFailInfo = pcmcStatus->dwFailInfo;
  1417. }
  1418. hr = myDupString(&pwszBodyPartBuffer[1], &pwszBodyPartT);
  1419. _JumpIfError(hr, error, "myDupString");
  1420. if (NULL != pcmcStatus->pwszStatusString)
  1421. {
  1422. hr = myDupString(pcmcStatus->pwszStatusString, &pwszStatusStringT);
  1423. _JumpIfError(hr, error, "myDupString");
  1424. }
  1425. if (CMC_OTHER_INFO_PEND_CHOICE == pcmcStatus->dwOtherInfoChoice &&
  1426. NULL != pcmcStatus->pPendInfo)
  1427. {
  1428. if (NULL != pcmcStatus->pPendInfo->PendToken.pbData &&
  1429. 0 != pcmcStatus->pPendInfo->PendToken.cbData)
  1430. {
  1431. pbToken = (BYTE *) LocalAlloc(
  1432. LMEM_FIXED,
  1433. pcmcStatus->pPendInfo->PendToken.cbData);
  1434. if (NULL == pbToken)
  1435. {
  1436. hr = E_OUTOFMEMORY;
  1437. _JumpError(hr, error, "LocalAlloc");
  1438. }
  1439. CopyMemory(
  1440. pbToken,
  1441. pcmcStatus->pPendInfo->PendToken.pbData,
  1442. pcmcStatus->pPendInfo->PendToken.cbData);
  1443. }
  1444. pResponse->StatusInfo.pPendInfo = (CMC_PEND_INFO *) LocalAlloc(
  1445. LMEM_FIXED | LMEM_ZEROINIT,
  1446. sizeof(*pResponse->StatusInfo.pPendInfo));
  1447. if (NULL == pResponse->StatusInfo.pPendInfo)
  1448. {
  1449. hr = E_OUTOFMEMORY;
  1450. _JumpError(hr, error, "LocalAlloc");
  1451. }
  1452. // Can't fail now.
  1453. pResponse->StatusInfo.pPendInfo->PendTime =
  1454. pcmcStatus->pPendInfo->PendTime;
  1455. if (NULL != pbToken)
  1456. {
  1457. pResponse->StatusInfo.pPendInfo->PendToken.pbData = pbToken;
  1458. pResponse->StatusInfo.pPendInfo->PendToken.cbData =
  1459. pcmcStatus->pPendInfo->PendToken.cbData;
  1460. pbToken = NULL;
  1461. }
  1462. }
  1463. pResponse->pwszBodyPart = pwszBodyPartT;
  1464. pwszBodyPartT = NULL;
  1465. pResponse->StatusInfo.pwszStatusString = pwszStatusStringT;
  1466. pwszStatusStringT = NULL;
  1467. (*pcResponse)++;
  1468. }
  1469. hr = S_OK;
  1470. error:
  1471. pwszBodyPartBuffer[cwcPrefix] = L'\0';
  1472. if (NULL != pwszBodyPartT)
  1473. {
  1474. LocalFree(pwszBodyPartT);
  1475. }
  1476. if (NULL != pwszStatusStringT)
  1477. {
  1478. LocalFree(pwszStatusStringT);
  1479. }
  1480. if (NULL != pbToken)
  1481. {
  1482. LocalFree(pbToken);
  1483. }
  1484. if (NULL != pcmcStatus)
  1485. {
  1486. LocalFree(pcmcStatus);
  1487. }
  1488. return(hr);
  1489. }
  1490. //+--------------------------------------------------------------------------
  1491. // _SaveCertHashInResponse -- Save cert hash to response array
  1492. //
  1493. // Returns S_OK on success.
  1494. //+--------------------------------------------------------------------------
  1495. HRESULT
  1496. _SaveCertHashInResponse(
  1497. IN BYTE const *pbCertHash,
  1498. IN DWORD cbCertHash,
  1499. IN WCHAR const *pwszBodyPart,
  1500. IN OUT XCMCRESPONSE *rgResponse,
  1501. IN DWORD cResponse,
  1502. IN BOOL fCertHash)
  1503. {
  1504. HRESULT hr;
  1505. DWORD i;
  1506. for (i = 0; i < cResponse; i++)
  1507. {
  1508. XCMCRESPONSE *pResponse = &rgResponse[i];
  1509. if (0 == lstrcmpW(pwszBodyPart, pResponse->pwszBodyPart))
  1510. {
  1511. BYTE **ppbHash = fCertHash?
  1512. &pResponse->pbCertHash : &pResponse->pbEncryptedKeyHash;
  1513. DWORD *pcbHash = fCertHash?
  1514. &pResponse->cbCertHash : &pResponse->cbEncryptedKeyHash;
  1515. if (NULL != *ppbHash)
  1516. {
  1517. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1518. _JumpError(hr, error, "hash already set");
  1519. }
  1520. *ppbHash = (BYTE *) LocalAlloc(LMEM_FIXED, cbCertHash);
  1521. if (NULL == *ppbHash)
  1522. {
  1523. hr = E_OUTOFMEMORY;
  1524. _JumpError(hr, error, "LocalAlloc");
  1525. }
  1526. *pcbHash = cbCertHash;
  1527. CopyMemory(*ppbHash, pbCertHash, cbCertHash);
  1528. break;
  1529. }
  1530. }
  1531. if (i >= cResponse)
  1532. {
  1533. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1534. _JumpError(hr, error, "unknown hash");
  1535. }
  1536. hr = S_OK;
  1537. error:
  1538. return(hr);
  1539. }
  1540. //+--------------------------------------------------------------------------
  1541. // _SaveCMCCertHash -- Save CMC cert hash from attributes
  1542. //
  1543. // Returns S_OK on success.
  1544. //+--------------------------------------------------------------------------
  1545. #define BLOB_ROUND(cb) \
  1546. (((cb) + sizeof(CRYPT_DATA_BLOB) - 1) / sizeof(CRYPT_DATA_BLOB))
  1547. HRESULT
  1548. _SaveCMCCertHash(
  1549. IN BYTE *pbIn,
  1550. IN DWORD cbIn,
  1551. IN OUT WCHAR *pwszBodyPartBuffer,
  1552. IN DWORD cwcBodyPartBuffer,
  1553. IN OUT XCMCRESPONSE *rgResponse,
  1554. IN OUT DWORD cResponse)
  1555. {
  1556. HRESULT hr;
  1557. CMC_ADD_ATTRIBUTES_INFO *pcmcAttrib = NULL;
  1558. CRYPT_ATTRIBUTE const *pAttr;
  1559. CRYPT_ATTRIBUTE const *pAttrEnd;
  1560. CRYPT_DATA_BLOB aBlob[1 + BLOB_ROUND(CBMAX_CRYPT_HASH_LEN)];
  1561. DWORD cb;
  1562. DWORD cwcPrefix;
  1563. cwcPrefix = wcslen(pwszBodyPartBuffer);
  1564. // Decode CMC_ADD_ATTRIBUTES_INFO from Attribute Blob
  1565. CSASSERT(NULL == pcmcAttrib);
  1566. if (!myDecodeObject(
  1567. X509_ASN_ENCODING,
  1568. CMC_ADD_ATTRIBUTES,
  1569. pbIn,
  1570. cbIn,
  1571. CERTLIB_USE_LOCALALLOC,
  1572. (VOID **) &pcmcAttrib,
  1573. &cb))
  1574. {
  1575. hr = myHLastError();
  1576. _JumpError(hr, error, "myDecodeObject");
  1577. }
  1578. if (0 != pcmcAttrib->dwCmcDataReference)
  1579. {
  1580. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1581. _JumpError(hr, error, "pcmcAttrib->dwCmcDataReference");
  1582. }
  1583. pAttrEnd = &pcmcAttrib->rgAttribute[pcmcAttrib->cAttribute];
  1584. for (pAttr = pcmcAttrib->rgAttribute; pAttr < pAttrEnd; pAttr++)
  1585. {
  1586. BOOL fCertHash = 0 == strcmp(pAttr->pszObjId, szOID_ISSUED_CERT_HASH);
  1587. if (fCertHash ||
  1588. 0 == strcmp(pAttr->pszObjId, szOID_ENCRYPTED_KEY_HASH))
  1589. {
  1590. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1591. if (1 != pAttr->cValue)
  1592. {
  1593. _JumpError(hr, error, "pAttr->cValue");
  1594. }
  1595. if (1 != pcmcAttrib->cCertReference)
  1596. {
  1597. _JumpError(hr, error, "pcmcAttrib->dwCmcDataReference");
  1598. }
  1599. hr = _AppendBodyPart(
  1600. pwszBodyPartBuffer,
  1601. cwcBodyPartBuffer,
  1602. cwcPrefix,
  1603. pcmcAttrib->rgdwCertReference[0]);
  1604. _JumpIfError(hr, error, "_AppendBodyPart");
  1605. cb = sizeof(aBlob);
  1606. if (!CryptDecodeObject(
  1607. X509_ASN_ENCODING,
  1608. X509_OCTET_STRING,
  1609. pAttr->rgValue[0].pbData,
  1610. pAttr->rgValue[0].cbData,
  1611. 0,
  1612. aBlob,
  1613. &cb))
  1614. {
  1615. hr = myHLastError();
  1616. _JumpError(hr, error, "myDecodeObject");
  1617. }
  1618. hr = _SaveCertHashInResponse(
  1619. aBlob[0].pbData,
  1620. aBlob[0].cbData,
  1621. &pwszBodyPartBuffer[1],
  1622. rgResponse,
  1623. cResponse,
  1624. fCertHash);
  1625. _JumpIfError(hr, error, "SaveCertHashInResponse");
  1626. }
  1627. }
  1628. hr = S_OK;
  1629. error:
  1630. pwszBodyPartBuffer[cwcPrefix] = L'\0';
  1631. if (NULL != pcmcAttrib)
  1632. {
  1633. LocalFree(pcmcAttrib);
  1634. }
  1635. return(hr);
  1636. }
  1637. //+--------------------------------------------------------------------------
  1638. // _DecodeCMCTaggedAttributes -- Decode CMC Tagged Attributes
  1639. //
  1640. // Returns S_OK on success.
  1641. //+--------------------------------------------------------------------------
  1642. HRESULT
  1643. _DecodeCMCTaggedAttributes(
  1644. IN DWORD cTaggedAttribute,
  1645. IN CMC_TAGGED_ATTRIBUTE const *rgTaggedAttribute,
  1646. IN OUT WCHAR *pwszBodyPartBuffer,
  1647. IN DWORD cwcBodyPartBuffer,
  1648. IN OUT XCMCRESPONSE **prgResponse,
  1649. IN OUT DWORD *pcResponse)
  1650. {
  1651. HRESULT hr;
  1652. DWORD i;
  1653. CRYPT_ATTRIBUTE const *pAttribute;
  1654. DWORD j;
  1655. for (i = 0; i < cTaggedAttribute; i++)
  1656. {
  1657. pAttribute = &rgTaggedAttribute[i].Attribute;
  1658. for (j = 0; j < pAttribute->cValue; j++)
  1659. {
  1660. if (0 == strcmp(szOID_CMC_STATUS_INFO, pAttribute->pszObjId))
  1661. {
  1662. hr = _SaveCMCStatus(
  1663. pAttribute->rgValue[j].pbData,
  1664. pAttribute->rgValue[j].cbData,
  1665. pwszBodyPartBuffer,
  1666. cwcBodyPartBuffer,
  1667. prgResponse,
  1668. pcResponse);
  1669. _JumpIfError(hr, error, "_SaveCMCStatus");
  1670. }
  1671. }
  1672. }
  1673. for (i = 0; i < cTaggedAttribute; i++)
  1674. {
  1675. pAttribute = &rgTaggedAttribute[i].Attribute;
  1676. for (j = 0; j < pAttribute->cValue; j++)
  1677. {
  1678. if (0 == strcmp(szOID_CMC_ADD_ATTRIBUTES, pAttribute->pszObjId))
  1679. {
  1680. hr = _SaveCMCCertHash(
  1681. pAttribute->rgValue[j].pbData,
  1682. pAttribute->rgValue[j].cbData,
  1683. pwszBodyPartBuffer,
  1684. cwcBodyPartBuffer,
  1685. *prgResponse,
  1686. *pcResponse);
  1687. _JumpIfError(hr, error, "_SaveCMCCertHash");
  1688. }
  1689. }
  1690. }
  1691. hr = S_OK;
  1692. error:
  1693. return(hr);
  1694. }
  1695. //+--------------------------------------------------------------------------
  1696. // _DecodeCMCResponse -- Decode a CMC Response Message
  1697. //
  1698. // Returns S_OK on success.
  1699. //+--------------------------------------------------------------------------
  1700. HRESULT
  1701. _DecodeCMCResponse(
  1702. IN BYTE *pbIn,
  1703. IN DWORD cbIn,
  1704. IN OUT WCHAR *pwszBodyPartBuffer,
  1705. IN DWORD cwcBodyPartBuffer,
  1706. IN OUT XCMCRESPONSE **prgResponse,
  1707. IN OUT DWORD *pcResponse)
  1708. {
  1709. HRESULT hr;
  1710. CMC_RESPONSE_INFO *pcmcResponse = NULL;
  1711. DWORD cbcmcResponse;
  1712. if (!myDecodeObject(
  1713. X509_ASN_ENCODING,
  1714. CMC_RESPONSE,
  1715. pbIn,
  1716. cbIn,
  1717. CERTLIB_USE_LOCALALLOC,
  1718. (VOID **) &pcmcResponse,
  1719. &cbcmcResponse))
  1720. {
  1721. hr = myHLastError();
  1722. _JumpError(hr, error, "myDecodeObject");
  1723. }
  1724. hr = _DecodeCMCTaggedAttributes(
  1725. pcmcResponse->cTaggedAttribute,
  1726. pcmcResponse->rgTaggedAttribute,
  1727. pwszBodyPartBuffer,
  1728. cwcBodyPartBuffer,
  1729. prgResponse,
  1730. pcResponse);
  1731. _JumpIfError(hr, error, "_DecodeTaggedAttributes");
  1732. #if 0
  1733. hr = _DecodeTaggedContent(
  1734. pcmcResponse->cTaggedContentInfo,
  1735. pcmcResponse->rgTaggedContentInfo);
  1736. _JumpIfError(hr, error, "_DecodeTaggedContent");
  1737. hr = _DecodeTaggedOther(
  1738. pcmcResponse->cTaggedOtherMsg,
  1739. pcmcResponse->rgTaggedOtherMsg);
  1740. _JumpIfError(hr, error, "_DecodeTaggedOther");
  1741. #endif
  1742. error:
  1743. if (NULL != pcmcResponse)
  1744. {
  1745. LocalFree(pcmcResponse);
  1746. }
  1747. return(hr);
  1748. }
  1749. //+--------------------------------------------------------------------------
  1750. // ParseCMCResponse -- Decode a Full Response Message
  1751. //
  1752. // Returns S_OK on success.
  1753. //+--------------------------------------------------------------------------
  1754. HRESULT
  1755. ParseCMCResponse(
  1756. IN BYTE *pbResponse,
  1757. IN DWORD cbResponse,
  1758. OPTIONAL OUT HCERTSTORE *phStoreResponse,
  1759. OUT XCMCRESPONSE **prgResponse,
  1760. OUT DWORD *pcResponse)
  1761. {
  1762. HRESULT hr;
  1763. DWORD dwMsgType;
  1764. char *pszInnerContentObjId = NULL;
  1765. BYTE *pbContents = NULL;
  1766. DWORD cbContents;
  1767. HCERTSTORE hStore = NULL;
  1768. WCHAR awcBodyPartBuffer[MAX_PATH];
  1769. if (NULL != phStoreResponse)
  1770. {
  1771. *phStoreResponse = NULL;
  1772. }
  1773. *prgResponse = NULL;
  1774. *pcResponse = 0;
  1775. // Decode outer PKCS 7 signed message, which contains all of the certs.
  1776. hr = myDecodePKCS7(
  1777. pbResponse,
  1778. cbResponse,
  1779. &pbContents,
  1780. &cbContents,
  1781. &dwMsgType,
  1782. &pszInnerContentObjId,
  1783. NULL, // &cSigner,
  1784. NULL, // &cRecipient,
  1785. &hStore,
  1786. NULL); // phMsg
  1787. _JumpIfError(hr, error, "myDecodePKCS7(outer)");
  1788. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1789. if (CMSG_SIGNED != dwMsgType)
  1790. {
  1791. _JumpError(hr, error, "dwMsgType");
  1792. }
  1793. if (NULL == pszInnerContentObjId ||
  1794. 0 != strcmp(pszInnerContentObjId, szOID_CT_PKI_RESPONSE))
  1795. {
  1796. _JumpError(hr, error, "pszInnerContentObjId");
  1797. }
  1798. awcBodyPartBuffer[0] = L'\0';
  1799. hr = _DecodeCMCResponse(
  1800. pbContents,
  1801. cbContents,
  1802. awcBodyPartBuffer,
  1803. ARRAYSIZE(awcBodyPartBuffer),
  1804. prgResponse,
  1805. pcResponse);
  1806. _JumpIfError(hr, error, "_DecodeCMCResponse");
  1807. if (NULL != phStoreResponse)
  1808. {
  1809. *phStoreResponse = hStore;
  1810. hStore = NULL;
  1811. }
  1812. hr = S_OK;
  1813. error:
  1814. if (NULL != pbContents)
  1815. {
  1816. LocalFree(pbContents);
  1817. }
  1818. if (NULL != pszInnerContentObjId)
  1819. {
  1820. LocalFree(pszInnerContentObjId);
  1821. }
  1822. if (NULL != hStore)
  1823. {
  1824. CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
  1825. }
  1826. return(hr);
  1827. }
  1828. HRESULT
  1829. myCryptMsgGetParam(
  1830. IN HCRYPTMSG hMsg,
  1831. IN DWORD dwParamType,
  1832. IN DWORD dwIndex,
  1833. IN CERTLIB_ALLOCATOR allocType,
  1834. OUT VOID **ppvData,
  1835. OUT DWORD *pcbData)
  1836. {
  1837. HRESULT hr;
  1838. VOID *pvData = NULL;
  1839. *ppvData = NULL;
  1840. *pcbData = 0;
  1841. if (!CryptMsgGetParam(
  1842. hMsg,
  1843. dwParamType,
  1844. dwIndex,
  1845. NULL,
  1846. pcbData))
  1847. {
  1848. hr = myHLastError();
  1849. if (CRYPT_E_ATTRIBUTES_MISSING == hr || CRYPT_E_INVALID_INDEX == hr)
  1850. {
  1851. hr = S_FALSE;
  1852. }
  1853. // _JumpError2(hr, error, "CryptMsgGetParam", S_FALSE);
  1854. _JumpError(hr, error, "CryptMsgGetParam");
  1855. }
  1856. pvData = myAlloc(*pcbData, allocType);
  1857. if (NULL == pvData)
  1858. {
  1859. hr = E_OUTOFMEMORY;
  1860. _JumpError(hr, error, "LocalAlloc");
  1861. }
  1862. ZeroMemory(pvData, *pcbData);
  1863. if (!CryptMsgGetParam(
  1864. hMsg,
  1865. dwParamType,
  1866. dwIndex,
  1867. pvData,
  1868. pcbData))
  1869. {
  1870. hr = myHLastError();
  1871. _JumpError(hr, error, "CryptMsgGetParam");
  1872. }
  1873. *ppvData = pvData;
  1874. pvData = NULL;
  1875. hr = S_OK;
  1876. error:
  1877. if (NULL != pvData)
  1878. {
  1879. LocalFree(pvData);
  1880. }
  1881. return(hr);
  1882. }
  1883. HRESULT
  1884. myEncodeUTF8String(
  1885. IN WCHAR const *pwszIn,
  1886. OUT BYTE **ppbOut,
  1887. OUT DWORD *pcbOut)
  1888. {
  1889. HRESULT hr;
  1890. CERT_NAME_VALUE cnv;
  1891. *ppbOut = NULL;
  1892. cnv.dwValueType = CERT_RDN_UTF8_STRING;
  1893. cnv.Value.pbData = (BYTE *) pwszIn;
  1894. cnv.Value.cbData = 0;
  1895. if (!myEncodeObject(
  1896. X509_ASN_ENCODING,
  1897. X509_UNICODE_ANY_STRING,
  1898. &cnv,
  1899. 0,
  1900. CERTLIB_USE_LOCALALLOC,
  1901. ppbOut,
  1902. pcbOut))
  1903. {
  1904. hr = myHLastError();
  1905. _JumpIfError(hr, error, "myEncodeObject");
  1906. }
  1907. hr = S_OK;
  1908. error:
  1909. return(hr);
  1910. }
  1911. HRESULT
  1912. myDecodeUTF8String(
  1913. IN BYTE const *pbIn,
  1914. IN DWORD cbIn,
  1915. OUT WCHAR **ppwszOut)
  1916. {
  1917. HRESULT hr;
  1918. CERT_NAME_VALUE *pNameValue = NULL;
  1919. DWORD cb;
  1920. *ppwszOut = NULL;
  1921. if (!myDecodeObject(
  1922. X509_ASN_ENCODING,
  1923. X509_UNICODE_ANY_STRING,
  1924. pbIn,
  1925. cbIn,
  1926. CERTLIB_USE_LOCALALLOC,
  1927. (VOID **) &pNameValue,
  1928. &cb))
  1929. {
  1930. hr = myHLastError();
  1931. _JumpError(hr, error, "myDecodeObject");
  1932. }
  1933. if (NULL != pNameValue->Value.pbData)
  1934. {
  1935. hr = myDupString((WCHAR *) pNameValue->Value.pbData, ppwszOut);
  1936. _JumpIfError(hr, error, "myDupString");
  1937. }
  1938. hr = S_OK;
  1939. error:
  1940. if (NULL != pNameValue)
  1941. {
  1942. LocalFree(pNameValue);
  1943. }
  1944. return(hr);
  1945. }
  1946. HRESULT
  1947. myEncodeRequestClientAttribute(
  1948. IN CRYPT_REQUEST_CLIENT_INFO const *pcrci,
  1949. OUT BYTE **ppbOut,
  1950. OUT DWORD *pcbOut)
  1951. {
  1952. HRESULT hr;
  1953. CRYPT_DER_BLOB aBlob[4];
  1954. CRYPT_SEQUENCE_OF_ANY Sequence;
  1955. DWORD i;
  1956. ZeroMemory(aBlob, sizeof(aBlob));
  1957. Sequence.cValue = ARRAYSIZE(aBlob);
  1958. Sequence.rgValue = aBlob;
  1959. if (!myEncodeObject(
  1960. X509_ASN_ENCODING,
  1961. X509_INTEGER,
  1962. &pcrci->dwClientId,
  1963. 0,
  1964. CERTLIB_USE_LOCALALLOC,
  1965. &aBlob[0].pbData,
  1966. &aBlob[0].cbData))
  1967. {
  1968. hr = myHLastError();
  1969. _JumpIfError(hr, error, "myEncodeObject");
  1970. }
  1971. hr = myEncodeUTF8String(
  1972. pcrci->pwszMachine,
  1973. &aBlob[1].pbData,
  1974. &aBlob[1].cbData);
  1975. _JumpIfError(hr, error, "myEncodeUTF8String");
  1976. hr = myEncodeUTF8String(
  1977. pcrci->pwszUser,
  1978. &aBlob[2].pbData,
  1979. &aBlob[2].cbData);
  1980. _JumpIfError(hr, error, "myEncodeUTF8String");
  1981. hr = myEncodeUTF8String(
  1982. pcrci->pwszProcess,
  1983. &aBlob[3].pbData,
  1984. &aBlob[3].cbData);
  1985. _JumpIfError(hr, error, "myEncodeUTF8String");
  1986. if (!myEncodeObject(
  1987. X509_ASN_ENCODING,
  1988. X509_SEQUENCE_OF_ANY,
  1989. &Sequence,
  1990. 0,
  1991. CERTLIB_USE_LOCALALLOC,
  1992. ppbOut,
  1993. pcbOut))
  1994. {
  1995. hr = myHLastError();
  1996. _JumpIfError(hr, error, "myEncodeObject");
  1997. }
  1998. hr = S_OK;
  1999. error:
  2000. for (i = 0; i < ARRAYSIZE(aBlob); i++)
  2001. {
  2002. if (NULL != aBlob[i].pbData)
  2003. {
  2004. LocalFree(aBlob[i].pbData);
  2005. }
  2006. }
  2007. return(hr);
  2008. }
  2009. HRESULT
  2010. myDecodeRequestClientAttribute(
  2011. IN BYTE const *pbIn,
  2012. IN DWORD cbIn,
  2013. OUT CRYPT_REQUEST_CLIENT_INFO **ppcrci)
  2014. {
  2015. HRESULT hr;
  2016. CRYPT_SEQUENCE_OF_ANY *pSequence = NULL;
  2017. CRYPT_REQUEST_CLIENT_INFO crci;
  2018. DWORD cb;
  2019. BYTE *pb;
  2020. ZeroMemory(&crci, sizeof(crci));
  2021. *ppcrci = NULL;
  2022. if (!myDecodeObject(
  2023. X509_ASN_ENCODING,
  2024. X509_SEQUENCE_OF_ANY,
  2025. pbIn,
  2026. cbIn,
  2027. CERTLIB_USE_LOCALALLOC,
  2028. (VOID **) &pSequence,
  2029. &cb))
  2030. {
  2031. hr = myHLastError();
  2032. _JumpError(hr, error, "myDecodeObject");
  2033. }
  2034. if (4 != pSequence->cValue)
  2035. {
  2036. hr = E_INVALIDARG;
  2037. _JumpError(hr, error, "incomplete structure");
  2038. }
  2039. cb = sizeof(crci.dwClientId);
  2040. if (!CryptDecodeObject(
  2041. X509_ASN_ENCODING,
  2042. X509_INTEGER,
  2043. pSequence->rgValue[0].pbData,
  2044. pSequence->rgValue[0].cbData,
  2045. 0, // dwFlags
  2046. (VOID *) &crci.dwClientId,
  2047. &cb))
  2048. {
  2049. hr = myHLastError();
  2050. _JumpError(hr, error, "myDecodeObject");
  2051. }
  2052. hr = myDecodeUTF8String(
  2053. pSequence->rgValue[1].pbData,
  2054. pSequence->rgValue[1].cbData,
  2055. &crci.pwszMachine);
  2056. _JumpIfError(hr, error, "myDecodeUTF8String");
  2057. hr = myDecodeUTF8String(
  2058. pSequence->rgValue[2].pbData,
  2059. pSequence->rgValue[2].cbData,
  2060. &crci.pwszUser);
  2061. _JumpIfError(hr, error, "myDecodeUTF8String");
  2062. hr = myDecodeUTF8String(
  2063. pSequence->rgValue[3].pbData,
  2064. pSequence->rgValue[3].cbData,
  2065. &crci.pwszProcess);
  2066. _JumpIfError(hr, error, "myDecodeUTF8String");
  2067. cb = sizeof(crci);
  2068. if (NULL != crci.pwszMachine)
  2069. {
  2070. cb += DWORDROUND(sizeof(WCHAR) * (wcslen(crci.pwszMachine) + 1));
  2071. }
  2072. if (NULL != crci.pwszUser)
  2073. {
  2074. cb += DWORDROUND(sizeof(WCHAR) * (wcslen(crci.pwszUser) + 1));
  2075. }
  2076. if (NULL != crci.pwszProcess)
  2077. {
  2078. cb += DWORDROUND(sizeof(WCHAR) * (wcslen(crci.pwszProcess) + 1));
  2079. }
  2080. *ppcrci = (CRYPT_REQUEST_CLIENT_INFO *) LocalAlloc(
  2081. LMEM_FIXED | LMEM_ZEROINIT,
  2082. cb);
  2083. if (NULL == *ppcrci)
  2084. {
  2085. hr = E_OUTOFMEMORY;
  2086. _JumpError(hr, error, "LocalAlloc");
  2087. }
  2088. pb = (BYTE *) (*ppcrci + 1);
  2089. (*ppcrci)->dwClientId = crci.dwClientId;
  2090. if (NULL != crci.pwszMachine)
  2091. {
  2092. (*ppcrci)->pwszMachine = (WCHAR *) pb;
  2093. wcscpy((*ppcrci)->pwszMachine, crci.pwszMachine);
  2094. pb += DWORDROUND(sizeof(WCHAR) * (wcslen(crci.pwszMachine) + 1));
  2095. }
  2096. if (NULL != crci.pwszUser)
  2097. {
  2098. (*ppcrci)->pwszUser = (WCHAR *) pb;
  2099. wcscpy((*ppcrci)->pwszUser, crci.pwszUser);
  2100. pb += DWORDROUND(sizeof(WCHAR) * (wcslen(crci.pwszUser) + 1));
  2101. }
  2102. if (NULL != crci.pwszProcess)
  2103. {
  2104. (*ppcrci)->pwszProcess = (WCHAR *) pb;
  2105. wcscpy((*ppcrci)->pwszProcess, crci.pwszProcess);
  2106. pb += DWORDROUND(sizeof(WCHAR) * (wcslen(crci.pwszProcess) + 1));
  2107. }
  2108. hr = S_OK;
  2109. error:
  2110. if (NULL != pSequence)
  2111. {
  2112. LocalFree(pSequence);
  2113. }
  2114. if (NULL != crci.pwszMachine)
  2115. {
  2116. LocalFree(crci.pwszMachine);
  2117. }
  2118. if (NULL != crci.pwszUser)
  2119. {
  2120. LocalFree(crci.pwszUser);
  2121. }
  2122. if (NULL != crci.pwszProcess)
  2123. {
  2124. LocalFree(crci.pwszProcess);
  2125. }
  2126. return(hr);
  2127. }
  2128. HRESULT
  2129. myEncodeRequestClientAttributeFromClientId(
  2130. IN DWORD dwClientId,
  2131. OUT BYTE **ppbOut,
  2132. OUT DWORD *pcbOut)
  2133. {
  2134. HRESULT hr;
  2135. CRYPT_REQUEST_CLIENT_INFO crci;
  2136. *ppbOut = NULL;
  2137. ZeroMemory(&crci, sizeof(crci));
  2138. crci.dwClientId = dwClientId;
  2139. //crci.pwszMachine = NULL;
  2140. //crci.pwszUser = NULL;
  2141. //crci.pwszProcess = NULL;
  2142. hr = myGetMachineDnsName(&crci.pwszMachine);
  2143. _PrintIfError(hr, "myGetMachineDnsName");
  2144. hr = myGetUserNameEx(NameSamCompatible, &crci.pwszUser);
  2145. _PrintIfError(hr, "myGetUserNameEx");
  2146. hr = myGetProcessName(&crci.pwszProcess);
  2147. _PrintIfError(hr, "myGetProcessName");
  2148. hr = myEncodeRequestClientAttribute(&crci, ppbOut, pcbOut);
  2149. _JumpIfError(hr, error, "myEncodeRequestClientAttribute");
  2150. error:
  2151. if (NULL != crci.pwszProcess)
  2152. {
  2153. LocalFree(crci.pwszProcess);
  2154. }
  2155. if (NULL != crci.pwszUser)
  2156. {
  2157. LocalFree(crci.pwszUser);
  2158. }
  2159. if (NULL != crci.pwszMachine)
  2160. {
  2161. LocalFree(crci.pwszMachine);
  2162. }
  2163. return(hr);
  2164. }
  2165. #ifdef _XENROLL_SRC_
  2166. typedef BOOL
  2167. (WINAPI * PFNGetComputerNameExW) (
  2168. COMPUTER_NAME_FORMAT NameType, // name type
  2169. WCHAR *lpBuffer, // name buffer
  2170. LPDWORD lpnSize // size of name buffer
  2171. );
  2172. typedef BOOL
  2173. (WINAPI * PFNGetUserNameExW)(
  2174. EXTENDED_NAME_FORMAT NameFormat, // name format
  2175. WCHAR *lpNameBuffer, // name buffer
  2176. PULONG nSize // size of name buffer
  2177. );
  2178. typedef WCHAR*
  2179. (WINAPI * PFNGetCommandLineW)(
  2180. VOID
  2181. );
  2182. #endif //_XENROLL_SRC_
  2183. BOOL
  2184. xeGetUserNameExW(
  2185. IN EXTENDED_NAME_FORMAT NameFormat,
  2186. IN WCHAR *pwszUserName,
  2187. IN PULONG pcwc)
  2188. {
  2189. #ifdef _XENROLL_SRC_
  2190. BOOL b = FALSE;
  2191. PFNGetUserNameExW pfnGetUserNameExW = NULL;
  2192. HMODULE hModule = GetModuleHandle("secur32.dll");
  2193. if (NULL != hModule)
  2194. {
  2195. pfnGetUserNameExW = (PFNGetUserNameExW)
  2196. GetProcAddress(hModule, "GetUserNameExW");
  2197. if (NULL != pfnGetUserNameExW)
  2198. {
  2199. return pfnGetUserNameExW(NameFormat, pwszUserName, pcwc);
  2200. }
  2201. //downlevel clients, do the hard work
  2202. if (NULL == pwszUserName)
  2203. {
  2204. //just get size
  2205. return GetUserName(NULL, pcwc);
  2206. }
  2207. CHAR *pszUserName = (CHAR*)LocalAlloc(LMEM_FIXED, *pcwc * sizeof(CHAR));
  2208. if (NULL == pszUserName)
  2209. {
  2210. return FALSE;
  2211. }
  2212. if (GetUserName(pszUserName, pcwc))
  2213. {
  2214. //convert to wide string
  2215. if (0 != MultiByteToWideChar(
  2216. CP_ACP,
  2217. 0,
  2218. pszUserName,
  2219. -1,
  2220. pwszUserName,
  2221. *pcwc))
  2222. {
  2223. b = TRUE;
  2224. }
  2225. }
  2226. LocalFree(pszUserName);
  2227. }
  2228. return b;
  2229. #else
  2230. return GetUserNameExW(NameFormat, pwszUserName, pcwc);
  2231. #endif //_XENROLL_SRC_
  2232. }
  2233. BOOL
  2234. xeGetComputerNameExW(
  2235. IN COMPUTER_NAME_FORMAT NameFormat, // name format
  2236. IN WCHAR *pwszComputerName, // name buffer
  2237. IN OUT DWORD *pcwc) // size of name buffer
  2238. {
  2239. #ifdef _XENROLL_SRC_
  2240. BOOL b = FALSE;
  2241. PFNGetComputerNameExW pfnGetComputerNameExW = NULL;
  2242. HMODULE hModule = GetModuleHandle("kernel32.dll");
  2243. if (NULL != hModule)
  2244. {
  2245. pfnGetComputerNameExW = (PFNGetComputerNameExW)
  2246. GetProcAddress(hModule, "GetComputerNameExW");
  2247. if (NULL != pfnGetComputerNameExW)
  2248. {
  2249. return pfnGetComputerNameExW(NameFormat, pwszComputerName, pcwc);
  2250. }
  2251. //downlevel clients, do the hard work
  2252. if (NULL == pwszComputerName)
  2253. {
  2254. //just get size, donwlevel machine has max size
  2255. *pcwc = MAX_COMPUTERNAME_LENGTH + 1;
  2256. SetLastError(ERROR_MORE_DATA); // caller check on
  2257. return FALSE;
  2258. }
  2259. CHAR *pszComputerName = (CHAR*)
  2260. LocalAlloc(LMEM_FIXED, *pcwc * sizeof(CHAR));
  2261. if (NULL == pszComputerName)
  2262. {
  2263. return FALSE;
  2264. }
  2265. if (GetComputerName(pszComputerName, pcwc))
  2266. {
  2267. //convert to wide string
  2268. if (0 != MultiByteToWideChar(
  2269. CP_ACP,
  2270. 0,
  2271. pszComputerName,
  2272. -1,
  2273. pwszComputerName,
  2274. *pcwc + 1))
  2275. {
  2276. b = TRUE;
  2277. }
  2278. }
  2279. LocalFree(pszComputerName);
  2280. }
  2281. return b;
  2282. #else
  2283. return GetComputerNameExW(NameFormat, pwszComputerName, pcwc);
  2284. #endif // _XENROLL_SRC_
  2285. }
  2286. WCHAR*
  2287. xeGetCommandLineW(
  2288. OUT BOOL *pfNeedFree)
  2289. {
  2290. //init
  2291. *pfNeedFree = FALSE;
  2292. #ifdef _XENROLL_SRC_
  2293. WCHAR *pwszCommandLine = NULL;
  2294. PFNGetCommandLineW pfnGetCommandLineW = NULL;
  2295. HMODULE hModule = GetModuleHandle("kernel32.dll");
  2296. CHAR *pszCommandLine;
  2297. int cch;
  2298. if (NULL != hModule)
  2299. {
  2300. pfnGetCommandLineW = (PFNGetCommandLineW)
  2301. GetProcAddress(hModule, "GetCommandLineW");
  2302. if (NULL != pfnGetCommandLineW)
  2303. {
  2304. return pfnGetCommandLineW();
  2305. }
  2306. //downlevel clients, do the hard work
  2307. pszCommandLine = GetCommandLine();
  2308. if (NULL == pszCommandLine)
  2309. {
  2310. //error
  2311. return NULL;
  2312. }
  2313. cch = strlen(pszCommandLine) + 1;
  2314. pwszCommandLine = (WCHAR*)LocalAlloc(LMEM_FIXED, cch * sizeof(WCHAR));
  2315. if (NULL != pwszCommandLine)
  2316. {
  2317. //convert to wide string
  2318. if (0 == MultiByteToWideChar(
  2319. CP_ACP,
  2320. 0,
  2321. pszCommandLine,
  2322. -1,
  2323. pwszCommandLine,
  2324. cch))
  2325. {
  2326. LocalFree(pwszCommandLine);
  2327. pwszCommandLine = NULL;
  2328. }
  2329. else
  2330. {
  2331. //caller to free
  2332. *pfNeedFree = TRUE;
  2333. }
  2334. }
  2335. }
  2336. return pwszCommandLine;
  2337. #else
  2338. return GetCommandLineW();
  2339. #endif // _XENROLL_SRC_
  2340. }
  2341. HRESULT
  2342. myGetUserNameEx(
  2343. IN EXTENDED_NAME_FORMAT NameFormat,
  2344. OUT WCHAR **ppwszUserName)
  2345. {
  2346. HRESULT hr;
  2347. DWORD cwc = 0;
  2348. WCHAR *pwszUserName = NULL;
  2349. for (;;)
  2350. {
  2351. if (!xeGetUserNameExW(NameFormat, pwszUserName, &cwc))
  2352. {
  2353. hr = myHLastError();
  2354. if (NULL != pwszUserName ||
  2355. HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr)
  2356. {
  2357. _JumpError(hr, error, "GetUserNameEx");
  2358. }
  2359. }
  2360. if (NULL != pwszUserName)
  2361. {
  2362. break;
  2363. }
  2364. pwszUserName = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  2365. if (NULL == pwszUserName)
  2366. {
  2367. hr = E_OUTOFMEMORY;
  2368. _JumpError(hr, error, "LocalAlloc");
  2369. }
  2370. }
  2371. *ppwszUserName = pwszUserName;
  2372. pwszUserName = NULL;
  2373. hr = S_OK;
  2374. error:
  2375. if (NULL != pwszUserName)
  2376. {
  2377. LocalFree(pwszUserName);
  2378. }
  2379. return(hr);
  2380. }
  2381. HRESULT
  2382. myGetMachineDnsName(
  2383. OUT WCHAR **ppwszDnsName)
  2384. {
  2385. HRESULT hr;
  2386. WCHAR *pwszDnsName = NULL;
  2387. DWORD cwc;
  2388. COMPUTER_NAME_FORMAT NameType = ComputerNameDnsFullyQualified;
  2389. *ppwszDnsName = NULL;
  2390. for (;;)
  2391. {
  2392. cwc = 0;
  2393. if (!xeGetComputerNameExW(NameType, NULL, &cwc))
  2394. {
  2395. hr = myHLastError();
  2396. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr &&
  2397. ComputerNameDnsFullyQualified == NameType)
  2398. {
  2399. _PrintError(hr, "GetComputerNameExW(DnsFullyQualified) -- switching to NetBIOS");
  2400. NameType = ComputerNameNetBIOS;
  2401. continue;
  2402. }
  2403. if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr)
  2404. {
  2405. _JumpError(hr, error, "GetComputerNameEx");
  2406. }
  2407. }
  2408. else
  2409. {
  2410. cwc++;
  2411. }
  2412. break;
  2413. }
  2414. pwszDnsName = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  2415. if (NULL == pwszDnsName)
  2416. {
  2417. hr = E_OUTOFMEMORY;
  2418. _JumpError(hr, error, "LocalAlloc");
  2419. }
  2420. if (!xeGetComputerNameExW(NameType, pwszDnsName, &cwc))
  2421. {
  2422. hr = myHLastError();
  2423. _JumpError(hr, error, "GetComputerNameEx");
  2424. }
  2425. *ppwszDnsName = pwszDnsName;
  2426. pwszDnsName = NULL;
  2427. hr = S_OK;
  2428. error:
  2429. if (NULL != pwszDnsName)
  2430. {
  2431. LocalFree(pwszDnsName);
  2432. }
  2433. return(hr);
  2434. }
  2435. HRESULT
  2436. myGetProcessName(
  2437. OUT WCHAR **ppwszProcessName)
  2438. {
  2439. HRESULT hr;
  2440. WCHAR *pwszCommandLine;
  2441. WCHAR const *pwsz;
  2442. WCHAR const *pwszStart;
  2443. WCHAR *pwszAlloc;
  2444. DWORD cwc;
  2445. WCHAR wc;
  2446. BOOL fNeedFree;
  2447. *ppwszProcessName = NULL;
  2448. pwszCommandLine = xeGetCommandLineW(&fNeedFree);
  2449. if (NULL == pwszCommandLine)
  2450. {
  2451. pwszCommandLine = L"";
  2452. }
  2453. wc = L' ';
  2454. pwsz = pwszCommandLine;
  2455. if ('"' == *pwsz)
  2456. {
  2457. wc = '"';
  2458. pwsz++;
  2459. }
  2460. pwszStart = pwsz;
  2461. while (L'\0' != *pwsz && wc != *pwsz)
  2462. {
  2463. if (L'\\' == *pwsz++)
  2464. {
  2465. pwszStart = pwsz;
  2466. }
  2467. }
  2468. cwc = SAFE_SUBTRACT_POINTERS(pwsz, pwszStart);
  2469. pwszAlloc = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR));
  2470. if (NULL == pwszAlloc)
  2471. {
  2472. hr = E_OUTOFMEMORY;
  2473. _JumpError(hr, error, "LocalAlloc");
  2474. }
  2475. CopyMemory(pwszAlloc, pwszStart, cwc * sizeof(WCHAR));
  2476. pwszAlloc[cwc] = L'\0';
  2477. *ppwszProcessName = pwszAlloc;
  2478. hr = S_OK;
  2479. error:
  2480. if (fNeedFree && NULL != pwszCommandLine)
  2481. {
  2482. LocalFree(pwszCommandLine);
  2483. }
  2484. return(hr);
  2485. }